5 * Copyright (C) 2007-2009 Intel Corporation. All rights reserved.
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.
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.
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
33 #include "supplicant.h"
35 #define DBG(fmt, arg...) do { \
36 syslog(LOG_DEBUG, "%s() " fmt, __FUNCTION__ , ## arg); \
39 #define SUPPLICANT_SERVICE "fi.w1.wpa_supplicant1"
40 #define SUPPLICANT_INTERFACE "fi.w1.wpa_supplicant1"
41 #define SUPPLICANT_PATH "/fi/w1/wpa_supplicant1"
45 static DBusConnection *connection;
47 static const struct supplicant_callbacks *callbacks_pointer;
49 static void show_property(const char *key, DBusMessageIter *iter)
51 DBusMessageIter array;
55 switch (dbus_message_iter_get_arg_type(iter)) {
56 case DBUS_TYPE_STRING:
57 case DBUS_TYPE_OBJECT_PATH:
58 dbus_message_iter_get_basic(iter, &str);
59 DBG("%s = %s", key, str);
62 case DBUS_TYPE_BOOLEAN:
63 dbus_message_iter_get_basic(iter, &byte);
64 DBG("%s = %u", key, byte);
67 DBG("%s = {array}", key);
68 dbus_message_iter_recurse(iter, &array);
69 while (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_INVALID) {
70 dbus_message_iter_get_basic(&array, &str);
72 dbus_message_iter_next(&array);
81 static void properties_decode(DBusMessageIter *iter)
85 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY) {
86 syslog(LOG_ERR, "Invalid message type");
90 dbus_message_iter_recurse(iter, &dict);
92 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
93 DBusMessageIter entry, value;
96 dbus_message_iter_recurse(&dict, &entry);
98 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
101 dbus_message_iter_get_basic(&entry, &key);
102 dbus_message_iter_next(&entry);
104 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
107 dbus_message_iter_recurse(&entry, &value);
109 show_property(key, &value);
111 dbus_message_iter_next(&dict);
115 static void properties_get_all_reply(DBusPendingCall *call, void *user_data)
118 DBusMessageIter iter;
120 DBG("call %p", call);
122 reply = dbus_pending_call_steal_reply(call);
126 if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR)
129 if (dbus_message_iter_init(reply, &iter) == FALSE)
134 properties_decode(&iter);
136 dbus_message_unref(reply);
141 dbus_message_unref(reply);
144 static int properties_get_all(const char *path, const char *interface)
146 DBusMessage *message;
147 DBusPendingCall *call;
151 message = dbus_message_new_method_call(SUPPLICANT_SERVICE, path,
152 DBUS_INTERFACE_PROPERTIES, "GetAll");
156 dbus_message_set_auto_start(message, FALSE);
158 dbus_message_append_args(message, DBUS_TYPE_STRING, &interface, NULL);
160 if (dbus_connection_send_with_reply(connection, message,
161 &call, TIMEOUT) == FALSE) {
162 syslog(LOG_ERR, "Failed to add interface");
163 dbus_message_unref(message);
168 syslog(LOG_ERR, "D-Bus connection not available");
169 dbus_message_unref(message);
173 DBG("call %p", call);
175 dbus_pending_call_set_notify(call, properties_get_all_reply,
178 dbus_message_unref(message);
183 static DBusHandlerResult supplicant_filter(DBusConnection *conn,
184 DBusMessage *msg, void *data)
186 int prefixlen = strlen(SUPPLICANT_INTERFACE);
187 const char *interface, *member, *path;
189 interface = dbus_message_get_interface(msg);
190 if (interface == NULL)
191 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
193 if (g_str_has_prefix(interface, SUPPLICANT_INTERFACE) == FALSE)
194 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
196 member = dbus_message_get_member(msg);
198 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
200 path = dbus_message_get_path(msg);
202 syslog(LOG_DEBUG, "[ %s ]%s.%s", path, interface + prefixlen, member);
204 if (g_str_equal(member, "PropertiesChanged") == TRUE) {
205 DBusMessageIter iter;
207 if (dbus_message_iter_init(msg, &iter) == TRUE)
208 properties_decode(&iter);
211 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
214 static const char *supplicant_rule1 = "type=signal,"
215 "interface=" SUPPLICANT_INTERFACE;
216 static const char *supplicant_rule2 = "type=signal,"
217 "interface=" SUPPLICANT_INTERFACE ".Interface";
218 static const char *supplicant_rule3 = "type=signal,"
219 "interface=" SUPPLICANT_INTERFACE ".Interface.WPS";
220 static const char *supplicant_rule4 = "type=signal,"
221 "interface=" SUPPLICANT_INTERFACE ".Interface.BSS";
222 static const char *supplicant_rule5 = "type=signal,"
223 "interface=" SUPPLICANT_INTERFACE ".Interface.Network";
224 static const char *supplicant_rule6 = "type=signal,"
225 "interface=" SUPPLICANT_INTERFACE ".Interface.Blob";
227 int supplicant_register(const struct supplicant_callbacks *callbacks)
231 connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
232 if (connection == NULL)
235 if (dbus_connection_add_filter(connection,
236 supplicant_filter, NULL, NULL) == FALSE) {
237 dbus_connection_unref(connection);
242 callbacks_pointer = callbacks;
244 dbus_bus_add_match(connection, supplicant_rule1, NULL);
245 dbus_bus_add_match(connection, supplicant_rule2, NULL);
246 dbus_bus_add_match(connection, supplicant_rule3, NULL);
247 dbus_bus_add_match(connection, supplicant_rule4, NULL);
248 dbus_bus_add_match(connection, supplicant_rule5, NULL);
249 dbus_bus_add_match(connection, supplicant_rule6, NULL);
250 dbus_connection_flush(connection);
252 properties_get_all(SUPPLICANT_PATH, SUPPLICANT_INTERFACE);
257 void supplicant_unregister(const struct supplicant_callbacks *callbacks)
261 if (connection != NULL) {
262 dbus_bus_remove_match(connection, supplicant_rule6, NULL);
263 dbus_bus_remove_match(connection, supplicant_rule5, NULL);
264 dbus_bus_remove_match(connection, supplicant_rule4, NULL);
265 dbus_bus_remove_match(connection, supplicant_rule3, NULL);
266 dbus_bus_remove_match(connection, supplicant_rule2, NULL);
267 dbus_bus_remove_match(connection, supplicant_rule1, NULL);
268 dbus_connection_flush(connection);
270 dbus_connection_remove_filter(connection,
271 supplicant_filter, NULL);
273 dbus_connection_unref(connection);
277 callbacks_pointer = NULL;