Add code for retrieving supplicant global properties
[framework/connectivity/connman.git] / tools / supplicant.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2009  Intel Corporation. All rights reserved.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <errno.h>
27 #include <syslog.h>
28
29 #include <gdbus.h>
30
31 #include "supplicant.h"
32
33 #define DBG(fmt, arg...) do { \
34         syslog(LOG_DEBUG, "%s() " fmt, __FUNCTION__ , ## arg); \
35 } while (0)
36
37 #define SUPPLICANT_SERVICE      "fi.w1.wpa_supplicant1"
38 #define SUPPLICANT_INTERFACE    "fi.w1.wpa_supplicant1"
39 #define SUPPLICANT_PATH         "/fi/w1/wpa_supplicant1"
40
41 #define TIMEOUT 5000
42
43 static DBusConnection *connection;
44
45 static void show_property(const char *key, DBusMessageIter *iter)
46 {
47         DBusMessageIter array;
48         const char *str;
49         unsigned char byte;
50
51         switch (dbus_message_iter_get_arg_type(iter)) {
52         case DBUS_TYPE_STRING:
53                 dbus_message_iter_get_basic(iter, &str);
54                 DBG("%s = %s", key, str);
55                 break;
56         case DBUS_TYPE_BYTE:
57                 dbus_message_iter_get_basic(iter, &byte);
58                 DBG("%s = %u", key, byte);
59                 break;
60         case DBUS_TYPE_ARRAY:
61                 DBG("%s = {array}", key);
62                 dbus_message_iter_recurse(iter, &array);
63                 while (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_INVALID) {
64                         dbus_message_iter_get_basic(&array, &str);
65                         DBG("  %s", str);
66                         dbus_message_iter_next(&array);
67                 }
68                 break;
69         default:
70                 DBG("%s = ...", key);
71                 break;
72         }
73 }
74
75 static void properties_decode(DBusMessageIter *iter)
76 {
77         DBusMessageIter dict;
78
79         if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY) {
80                 syslog(LOG_ERR, "Invalid message type");
81                 return;
82         }
83
84         dbus_message_iter_recurse(iter, &dict);
85
86         while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
87                 DBusMessageIter entry, value;
88                 const char *key;
89
90                 dbus_message_iter_recurse(&dict, &entry);
91
92                 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
93                         return;
94
95                 dbus_message_iter_get_basic(&entry, &key);
96                 dbus_message_iter_next(&entry);
97
98                 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
99                         return;
100
101                 dbus_message_iter_recurse(&entry, &value);
102
103                 show_property(key, &value);
104
105                 dbus_message_iter_next(&dict);
106         }
107 }
108
109 static void properties_get_all_reply(DBusPendingCall *call, void *user_data)
110 {
111         DBusMessage *reply;
112         DBusMessageIter iter;
113
114         DBG("call %p", call);
115
116         reply = dbus_pending_call_steal_reply(call);
117         if (reply == NULL)
118                 return;
119
120         if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR)
121                 goto failed;
122
123         if (dbus_message_iter_init(reply, &iter) == FALSE)
124                 goto failed;
125
126         DBG("success");
127
128         properties_decode(&iter);
129
130         dbus_message_unref(reply);
131
132         return;
133
134 failed:
135         dbus_message_unref(reply);
136 }
137
138 static int properties_get_all(const char *path, const char *interface)
139 {
140         DBusMessage *message;
141         DBusPendingCall *call;
142
143         DBG("");
144
145         message = dbus_message_new_method_call(SUPPLICANT_SERVICE, path,
146                                         DBUS_INTERFACE_PROPERTIES, "GetAll");
147         if (message == NULL)
148                 return -ENOMEM;
149
150         dbus_message_set_auto_start(message, FALSE);
151
152         dbus_message_append_args(message, DBUS_TYPE_STRING, &interface, NULL);
153
154         if (dbus_connection_send_with_reply(connection, message,
155                                                 &call, TIMEOUT) == FALSE) {
156                 syslog(LOG_ERR, "Failed to add interface");
157                 dbus_message_unref(message);
158                 return -EIO;
159         }
160
161         if (call == NULL) {
162                 syslog(LOG_ERR, "D-Bus connection not available");
163                 dbus_message_unref(message);
164                 return -EIO;
165         }
166
167         DBG("call %p", call);
168
169         dbus_pending_call_set_notify(call, properties_get_all_reply,
170                                                                 NULL, NULL);
171
172         dbus_message_unref(message);
173
174         return 0;
175 }
176
177 int supplicant_init(void)
178 {
179         DBG("");
180
181         connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
182         if (connection == NULL)
183                 return -EIO;
184
185         properties_get_all(SUPPLICANT_PATH, SUPPLICANT_INTERFACE);
186
187         return 0;
188 }
189
190 void supplicant_exit(void)
191 {
192         DBG("");
193
194         if (connection != NULL)
195                 dbus_connection_unref(connection);
196 }