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
34 #include "supplicant-dbus.h"
35 #include "supplicant.h"
37 #define DBG(fmt, arg...) do { \
38 syslog(LOG_DEBUG, "%s() " fmt, __FUNCTION__ , ## arg); \
43 #define IEEE80211_CAP_ESS 0x0001
44 #define IEEE80211_CAP_IBSS 0x0002
45 #define IEEE80211_CAP_PRIVACY 0x0010
47 static DBusConnection *connection;
49 static const struct supplicant_callbacks *callbacks_pointer;
51 static unsigned int eap_methods;
58 static struct strvalmap eap_method_map[] = {
59 { "MD5", SUPPLICANT_EAP_METHOD_MD5 },
60 { "TLS", SUPPLICANT_EAP_METHOD_TLS },
61 { "MSCHAPV2", SUPPLICANT_EAP_METHOD_MSCHAPV2 },
62 { "PEAP", SUPPLICANT_EAP_METHOD_PEAP },
63 { "TTLS", SUPPLICANT_EAP_METHOD_TTLS },
64 { "GTC", SUPPLICANT_EAP_METHOD_GTC },
65 { "OTP", SUPPLICANT_EAP_METHOD_OTP },
66 { "LEAP", SUPPLICANT_EAP_METHOD_LEAP },
70 static struct strvalmap auth_capa_map[] = {
71 { "open", SUPPLICANT_CAPABILITY_AUTH_OPEN },
72 { "shared", SUPPLICANT_CAPABILITY_AUTH_SHARED },
73 { "leap", SUPPLICANT_CAPABILITY_AUTH_LEAP },
77 static struct strvalmap scan_capa_map[] = {
78 { "active", SUPPLICANT_CAPABILITY_SCAN_ACTIVE },
79 { "passive", SUPPLICANT_CAPABILITY_SCAN_PASSIVE },
80 { "ssid", SUPPLICANT_CAPABILITY_SCAN_SSID },
84 static struct strvalmap mode_capa_map[] = {
85 { "infrastructure", SUPPLICANT_CAPABILITY_MODE_INFRA },
86 { "ad-hoc", SUPPLICANT_CAPABILITY_MODE_IBSS },
87 { "ap", SUPPLICANT_CAPABILITY_MODE_AP },
91 static GHashTable *interface_table;
93 struct supplicant_interface {
95 unsigned int auth_capa;
96 unsigned int scan_capa;
97 unsigned int mode_capa;
98 enum supplicant_state state;
104 GHashTable *network_table;
105 GHashTable *bss_mapping;
108 struct supplicant_network {
109 struct supplicant_interface *interface;
112 enum supplicant_mode mode;
113 GHashTable *bss_table;
116 struct supplicant_bss {
117 struct supplicant_interface *interface;
119 unsigned char bssid[6];
120 unsigned char ssid[32];
121 unsigned int ssid_len;
122 unsigned int frequency;
123 enum supplicant_mode mode;
124 enum supplicant_security security;
127 dbus_bool_t ieee8021x;
130 static const char *mode2string(enum supplicant_mode mode)
133 case SUPPLICANT_MODE_UNKNOWN:
135 case SUPPLICANT_MODE_INFRA:
137 case SUPPLICANT_MODE_IBSS:
144 static const char *security2string(enum supplicant_security security)
147 case SUPPLICANT_SECURITY_UNKNOWN:
149 case SUPPLICANT_SECURITY_NONE:
151 case SUPPLICANT_SECURITY_WEP:
153 case SUPPLICANT_SECURITY_PSK:
155 case SUPPLICANT_SECURITY_IEEE8021X:
162 static enum supplicant_state string2state(const char *state)
165 return SUPPLICANT_STATE_UNKNOWN;
167 if (g_str_equal(state, "unknown") == TRUE)
168 return SUPPLICANT_STATE_UNKNOWN;
169 else if (g_str_equal(state, "disconnected") == TRUE)
170 return SUPPLICANT_STATE_DISCONNECTED;
171 else if (g_str_equal(state, "inactive") == TRUE)
172 return SUPPLICANT_STATE_INACTIVE;
173 else if (g_str_equal(state, "scanning") == TRUE)
174 return SUPPLICANT_STATE_SCANNING;
175 else if (g_str_equal(state, "authenticating") == TRUE)
176 return SUPPLICANT_STATE_AUTHENTICATING;
177 else if (g_str_equal(state, "associating") == TRUE)
178 return SUPPLICANT_STATE_ASSOCIATING;
179 else if (g_str_equal(state, "associated") == TRUE)
180 return SUPPLICANT_STATE_ASSOCIATED;
181 else if (g_str_equal(state, "group_handshake") == TRUE)
182 return SUPPLICANT_STATE_GROUP_HANDSHAKE;
183 else if (g_str_equal(state, "4way_handshake") == TRUE)
184 return SUPPLICANT_STATE_4WAY_HANDSHAKE;
185 else if (g_str_equal(state, "completed") == TRUE)
186 return SUPPLICANT_STATE_COMPLETED;
188 return SUPPLICANT_STATE_UNKNOWN;
191 static void callback_interface_added(struct supplicant_interface *interface)
193 if (callbacks_pointer == NULL)
196 if (callbacks_pointer->interface_added == NULL)
199 callbacks_pointer->interface_added(interface);
202 static void callback_interface_removed(struct supplicant_interface *interface)
204 if (callbacks_pointer == NULL)
207 if (callbacks_pointer->interface_removed == NULL)
210 callbacks_pointer->interface_removed(interface);
213 static void callback_network_added(struct supplicant_network *network)
215 if (callbacks_pointer == NULL)
218 if (callbacks_pointer->network_added == NULL)
221 callbacks_pointer->network_added(network);
224 static void callback_network_removed(struct supplicant_network *network)
226 if (callbacks_pointer == NULL)
229 if (callbacks_pointer->network_removed == NULL)
232 callbacks_pointer->network_removed(network);
235 static void remove_interface(gpointer data)
237 struct supplicant_interface *interface = data;
239 callback_interface_removed(interface);
241 g_hash_table_destroy(interface->bss_mapping);
242 g_hash_table_destroy(interface->network_table);
244 g_free(interface->path);
245 g_free(interface->ifname);
246 g_free(interface->driver);
247 g_free(interface->bridge);
251 static void remove_network(gpointer data)
253 struct supplicant_network *network = data;
255 callback_network_removed(network);
257 g_free(network->group);
258 g_free(network->name);
262 static void remove_bss(gpointer data)
264 struct supplicant_bss *bss = data;
270 static void debug_strvalmap(const char *label, struct strvalmap *map,
275 for (i = 0; map[i].str != NULL; i++) {
276 if (val & map[i].val)
277 DBG("%s: %s", label, map[i].str);
281 static void interface_capability_auth(DBusMessageIter *iter, void *user_data)
283 struct supplicant_interface *interface = user_data;
284 const char *str = NULL;
287 dbus_message_iter_get_basic(iter, &str);
291 for (i = 0; auth_capa_map[i].str != NULL; i++)
292 if (strcmp(str, auth_capa_map[i].str) == 0) {
293 interface->auth_capa |= auth_capa_map[i].val;
298 static void interface_capability_scan(DBusMessageIter *iter, void *user_data)
300 struct supplicant_interface *interface = user_data;
301 const char *str = NULL;
304 dbus_message_iter_get_basic(iter, &str);
308 for (i = 0; scan_capa_map[i].str != NULL; i++)
309 if (strcmp(str, scan_capa_map[i].str) == 0) {
310 interface->scan_capa |= scan_capa_map[i].val;
315 static void interface_capability_mode(DBusMessageIter *iter, void *user_data)
317 struct supplicant_interface *interface = user_data;
318 const char *str = NULL;
321 dbus_message_iter_get_basic(iter, &str);
325 for (i = 0; mode_capa_map[i].str != NULL; i++)
326 if (strcmp(str, mode_capa_map[i].str) == 0) {
327 interface->mode_capa |= mode_capa_map[i].val;
332 static void interface_capability(const char *key, DBusMessageIter *iter,
335 struct supplicant_interface *interface = user_data;
340 if (g_strcmp0(key, "AuthAlg") == 0)
341 supplicant_dbus_array_foreach(iter, interface_capability_auth,
343 else if (g_strcmp0(key, "Scan") == 0)
344 supplicant_dbus_array_foreach(iter, interface_capability_scan,
346 else if (g_strcmp0(key, "Modes") == 0)
347 supplicant_dbus_array_foreach(iter, interface_capability_mode,
350 DBG("key %s type %c",
351 key, dbus_message_iter_get_arg_type(iter));
354 const char *supplicant_interface_get_ifname(struct supplicant_interface *interface)
356 if (interface == NULL)
359 return interface->ifname;
362 struct supplicant_interface *supplicant_network_get_interface(struct supplicant_network *network)
367 return network->interface;
370 const char *supplicant_network_get_name(struct supplicant_network *network)
372 if (network == NULL || network->name == NULL)
375 return network->name;
378 const char *supplicant_network_get_identifier(struct supplicant_network *network)
380 if (network == NULL || network->group == NULL)
383 return network->group;
386 enum supplicant_mode supplicant_network_get_mode(struct supplicant_network *network)
389 return SUPPLICANT_MODE_UNKNOWN;
391 return network->mode;
394 static void network_property(const char *key, DBusMessageIter *iter,
400 DBG("key %s type %c", key, dbus_message_iter_get_arg_type(iter));
403 static void interface_network_added(DBusMessageIter *iter, void *user_data)
405 const char *path = NULL;
407 dbus_message_iter_get_basic(iter, &path);
411 DBG("path %s", path);
413 supplicant_dbus_property_get_all(path,
414 SUPPLICANT_INTERFACE ".Interface.Network",
415 network_property, NULL);
418 static void interface_network_removed(DBusMessageIter *iter, void *user_data)
420 const char *path = NULL;
422 dbus_message_iter_get_basic(iter, &path);
426 DBG("path %s", path);
429 static char *create_name(unsigned char *ssid, int ssid_len)
434 if (ssid_len < 1 || ssid[0] == '\0')
437 name = g_try_malloc0(ssid_len + 1);
442 for (i = 0; i < ssid_len; i++) {
443 if (g_ascii_isprint(ssid[i]))
452 static char *create_group(struct supplicant_bss *bss)
456 const char *mode, *security;
458 str = g_string_sized_new((bss->ssid_len * 2) + 24);
462 if (bss->ssid_len > 0 && bss->ssid[0] != '\0') {
463 for (i = 0; i < bss->ssid_len; i++)
464 g_string_append_printf(str, "%02x", bss->ssid[i]);
466 g_string_append_printf(str, "hidden");
468 mode = mode2string(bss->mode);
470 g_string_append_printf(str, "_%s", mode);
472 security = security2string(bss->security);
473 if (security != NULL)
474 g_string_append_printf(str, "_%s", security);
476 return g_string_free(str, FALSE);
479 static void add_bss_to_network(struct supplicant_bss *bss)
481 struct supplicant_interface *interface = bss->interface;
482 struct supplicant_network *network;
485 group = create_group(bss);
489 network = g_hash_table_lookup(interface->network_table, group);
490 if (network != NULL) {
495 network = g_try_new0(struct supplicant_network, 1);
496 if (network == NULL) {
501 network->group = group;
502 network->name = create_name(bss->ssid, bss->ssid_len);
503 network->mode = bss->mode;
505 network->bss_table = g_hash_table_new_full(g_str_hash, g_str_equal,
508 g_hash_table_replace(interface->network_table,
509 network->group, network);
511 callback_network_added(network);
514 g_hash_table_replace(interface->bss_mapping, bss->path, network);
515 g_hash_table_replace(network->bss_table, bss->path, bss);
518 static unsigned char wifi_oui[3] = { 0x00, 0x50, 0xf2 };
519 static unsigned char ieee80211_oui[3] = { 0x00, 0x0f, 0xac };
521 static void extract_rsn(struct supplicant_bss *bss,
522 const unsigned char *buf, int len)
541 /* Pairwise cipher */
545 count = buf[0] | (buf[1] << 8);
546 if (2 + (count * 4) > len)
549 buf += 2 + (count * 4);
550 len -= 2 + (count * 4);
556 count = buf[0] | (buf[1] << 8);
557 if (2 + (count * 4) > len)
560 for (i = 0; i < count; i++) {
561 const unsigned char *ptr = buf + 2 + (i * 4);
563 if (memcmp(ptr, wifi_oui, 3) == 0) {
566 bss->ieee8021x = TRUE;
572 } else if (memcmp(ptr, ieee80211_oui, 3) == 0) {
575 bss->ieee8021x = TRUE;
584 buf += 2 + (count * 4);
585 len -= 2 + (count * 4);
588 static void bss_property(const char *key, DBusMessageIter *iter,
591 struct supplicant_bss *bss = user_data;
593 if (bss->interface == NULL)
597 if (bss->ieee8021x == TRUE)
598 bss->security = SUPPLICANT_SECURITY_IEEE8021X;
599 else if (bss->psk == TRUE)
600 bss->security = SUPPLICANT_SECURITY_PSK;
601 else if (bss->privacy == TRUE)
602 bss->security = SUPPLICANT_SECURITY_WEP;
604 bss->security = SUPPLICANT_SECURITY_NONE;
606 add_bss_to_network(bss);
610 if (g_strcmp0(key, "BSSID") == 0) {
611 DBusMessageIter array;
615 dbus_message_iter_recurse(iter, &array);
616 dbus_message_iter_get_fixed_array(&array, &addr, &addr_len);
619 memcpy(bss->bssid, addr, addr_len);
620 } else if (g_strcmp0(key, "SSID") == 0) {
621 DBusMessageIter array;
625 dbus_message_iter_recurse(iter, &array);
626 dbus_message_iter_get_fixed_array(&array, &ssid, &ssid_len);
628 if (ssid_len > 0 && ssid_len < 33) {
629 memcpy(bss->ssid, ssid, ssid_len);
630 bss->ssid_len = ssid_len;
632 memset(bss->ssid, 0, sizeof(bss->ssid));
635 } else if (g_strcmp0(key, "Capabilities") == 0) {
636 dbus_uint16_t capabilities = 0x0000;
638 dbus_message_iter_get_basic(iter, &capabilities);
640 if (capabilities & IEEE80211_CAP_ESS)
641 bss->mode = SUPPLICANT_MODE_INFRA;
642 else if (capabilities & IEEE80211_CAP_IBSS)
643 bss->mode = SUPPLICANT_MODE_IBSS;
645 if (capabilities & IEEE80211_CAP_PRIVACY)
647 } else if (g_strcmp0(key, "Frequency") == 0) {
648 dbus_int32_t frequency = 0;
650 dbus_message_iter_get_basic(iter, &frequency);
651 bss->frequency = frequency;
652 } else if (g_strcmp0(key, "Level") == 0) {
653 dbus_int32_t level = 0;
655 dbus_message_iter_get_basic(iter, &level);
656 } else if (g_strcmp0(key, "MaxRate") == 0) {
657 dbus_int32_t maxrate = 0;
659 dbus_message_iter_get_basic(iter, &maxrate);
660 } else if (g_strcmp0(key, "RSNIE") == 0) {
661 DBusMessageIter array;
665 dbus_message_iter_recurse(iter, &array);
666 dbus_message_iter_get_fixed_array(&array, &ie, &ie_len);
669 extract_rsn(bss, ie + 2, ie_len - 2);
670 } else if (g_strcmp0(key, "WPAIE") == 0) {
671 DBusMessageIter array;
675 dbus_message_iter_recurse(iter, &array);
676 dbus_message_iter_get_fixed_array(&array, &ie, &ie_len);
679 extract_rsn(bss, ie + 6, ie_len - 6);
680 } else if (g_strcmp0(key, "WPSIE") == 0) {
681 DBusMessageIter array;
685 dbus_message_iter_recurse(iter, &array);
686 dbus_message_iter_get_fixed_array(&array, &ie, &ie_len);
688 DBG("key %s type %c",
689 key, dbus_message_iter_get_arg_type(iter));
692 static void interface_bss_added(DBusMessageIter *iter, void *user_data)
694 struct supplicant_interface *interface = user_data;
695 struct supplicant_network *network;
696 struct supplicant_bss *bss;
697 const char *path = NULL;
699 dbus_message_iter_get_basic(iter, &path);
703 network = g_hash_table_lookup(interface->bss_mapping, path);
704 if (network != NULL) {
705 bss = g_hash_table_lookup(network->bss_table, path);
710 bss = g_try_new0(struct supplicant_bss, 1);
714 bss->interface = interface;
715 bss->path = g_strdup(path);
717 supplicant_dbus_property_get_all(path,
718 SUPPLICANT_INTERFACE ".Interface.BSS",
722 static void interface_bss_removed(DBusMessageIter *iter, void *user_data)
724 struct supplicant_interface *interface = user_data;
725 struct supplicant_network *network;
726 const char *path = NULL;
728 dbus_message_iter_get_basic(iter, &path);
732 network = g_hash_table_lookup(interface->bss_mapping, path);
736 g_hash_table_remove(interface->bss_mapping, path);
737 g_hash_table_remove(network->bss_table, path);
739 if (g_hash_table_size(network->bss_table) == 0)
740 g_hash_table_remove(interface->network_table, network->group);
743 static void interface_property(const char *key, DBusMessageIter *iter,
746 struct supplicant_interface *interface = user_data;
748 if (interface == NULL)
752 debug_strvalmap("Auth capability", auth_capa_map,
753 interface->auth_capa);
754 debug_strvalmap("Scan capability", scan_capa_map,
755 interface->scan_capa);
756 debug_strvalmap("Mode capability", mode_capa_map,
757 interface->mode_capa);
759 g_hash_table_replace(interface_table,
760 interface->path, interface);
762 callback_interface_added(interface);
766 if (g_strcmp0(key, "Capabilities") == 0) {
767 supplicant_dbus_property_foreach(iter, interface_capability,
769 } else if (g_strcmp0(key, "State") == 0) {
770 const char *str = NULL;
772 dbus_message_iter_get_basic(iter, &str);
774 interface->state = string2state(str);
775 } else if (g_strcmp0(key, "Scanning") == 0) {
776 dbus_bool_t scanning = FALSE;
778 dbus_message_iter_get_basic(iter, &scanning);
779 interface->scanning = scanning;
780 } else if (g_strcmp0(key, "ApScan") == 0) {
783 dbus_message_iter_get_basic(iter, &apscan);
784 interface->apscan = apscan;
785 } else if (g_strcmp0(key, "Ifname") == 0) {
786 const char *str = NULL;
788 dbus_message_iter_get_basic(iter, &str);
790 interface->ifname = g_strdup(str);
791 } else if (g_strcmp0(key, "Driver") == 0) {
792 const char *str = NULL;
794 dbus_message_iter_get_basic(iter, &str);
796 interface->driver = g_strdup(str);
797 } else if (g_strcmp0(key, "BridgeIfname") == 0) {
798 const char *str = NULL;
800 dbus_message_iter_get_basic(iter, &str);
802 interface->bridge = g_strdup(str);
803 } else if (g_strcmp0(key, "CurrentBSS") == 0) {
804 interface_bss_added(iter, interface);
805 } else if (g_strcmp0(key, "CurrentNetwork") == 0) {
806 interface_network_added(iter, interface);
807 } else if (g_strcmp0(key, "BSSs") == 0) {
808 supplicant_dbus_array_foreach(iter, interface_bss_added,
810 } else if (g_strcmp0(key, "Blobs") == 0) {
811 } else if (g_strcmp0(key, "Networks") == 0) {
812 supplicant_dbus_array_foreach(iter, interface_network_added,
815 DBG("key %s type %c",
816 key, dbus_message_iter_get_arg_type(iter));
819 static void interface_added(DBusMessageIter *iter, void *user_data)
821 struct supplicant_interface *interface;
822 const char *path = NULL;
824 dbus_message_iter_get_basic(iter, &path);
828 interface = g_hash_table_lookup(interface_table, path);
829 if (interface != NULL)
832 interface = g_try_new0(struct supplicant_interface, 1);
833 if (interface == NULL)
836 interface->path = g_strdup(path);
838 interface->network_table = g_hash_table_new_full(g_str_hash, g_str_equal,
839 NULL, remove_network);
841 interface->bss_mapping = g_hash_table_new_full(g_str_hash, g_str_equal,
844 supplicant_dbus_property_get_all(path,
845 SUPPLICANT_INTERFACE ".Interface",
846 interface_property, interface);
849 static void interface_removed(DBusMessageIter *iter, void *user_data)
851 const char *path = NULL;
853 dbus_message_iter_get_basic(iter, &path);
857 g_hash_table_remove(interface_table, path);
860 static void eap_method(DBusMessageIter *iter, void *user_data)
862 const char *str = NULL;
865 dbus_message_iter_get_basic(iter, &str);
869 for (i = 0; eap_method_map[i].str != NULL; i++)
870 if (strcmp(str, eap_method_map[i].str) == 0) {
871 eap_methods |= eap_method_map[i].val;
876 static void service_property(const char *key, DBusMessageIter *iter,
882 if (g_strcmp0(key, "Interfaces") == 0)
883 supplicant_dbus_array_foreach(iter, interface_added, user_data);
884 else if (g_strcmp0(key, "EapMethods") == 0) {
885 supplicant_dbus_array_foreach(iter, eap_method, user_data);
886 debug_strvalmap("EAP method", eap_method_map, eap_methods);
887 } else if (g_strcmp0(key, "DebugParams") == 0) {
891 static void supplicant_bootstrap(void)
893 supplicant_dbus_property_get_all(SUPPLICANT_PATH,
894 SUPPLICANT_INTERFACE,
895 service_property, NULL);
898 static void signal_name_owner_changed(const char *path, DBusMessageIter *iter)
900 const char *name = NULL, *old = NULL, *new = NULL;
902 if (g_strcmp0(path, DBUS_PATH_DBUS) != 0)
905 dbus_message_iter_get_basic(iter, &name);
909 if (g_strcmp0(name, SUPPLICANT_SERVICE) != 0)
912 dbus_message_iter_next(iter);
913 dbus_message_iter_get_basic(iter, &old);
914 dbus_message_iter_next(iter);
915 dbus_message_iter_get_basic(iter, &new);
917 if (old == NULL || new == NULL)
920 if (strlen(old) > 0 && strlen(new) == 0)
921 g_hash_table_remove_all(interface_table);
923 if (strlen(new) > 0 && strlen(old) == 0)
924 supplicant_bootstrap();
927 static void signal_interface_added(const char *path, DBusMessageIter *iter)
929 if (g_strcmp0(path, SUPPLICANT_PATH) == 0)
930 interface_added(iter, NULL);
933 static void signal_interface_removed(const char *path, DBusMessageIter *iter)
935 if (g_strcmp0(path, SUPPLICANT_PATH) == 0)
936 interface_removed(iter, NULL);
939 static void signal_bss_added(const char *path, DBusMessageIter *iter)
941 struct supplicant_interface *interface;
943 interface = g_hash_table_lookup(interface_table, path);
944 if (interface == NULL)
947 interface_bss_added(iter, interface);
950 static void signal_bss_removed(const char *path, DBusMessageIter *iter)
952 struct supplicant_interface *interface;
954 interface = g_hash_table_lookup(interface_table, path);
955 if (interface == NULL)
958 interface_bss_removed(iter, interface);
961 static void signal_network_added(const char *path, DBusMessageIter *iter)
963 struct supplicant_interface *interface;
965 interface = g_hash_table_lookup(interface_table, path);
966 if (interface == NULL)
969 interface_network_added(iter, interface);
972 static void signal_network_removed(const char *path, DBusMessageIter *iter)
974 struct supplicant_interface *interface;
976 interface = g_hash_table_lookup(interface_table, path);
977 if (interface == NULL)
980 interface_network_removed(iter, interface);
984 const char *interface;
986 void (*function) (const char *path, DBusMessageIter *iter);
988 { DBUS_INTERFACE_DBUS, "NameOwnerChanged", signal_name_owner_changed },
990 { SUPPLICANT_INTERFACE, "InterfaceAdded", signal_interface_added },
991 { SUPPLICANT_INTERFACE, "InterfaceCreated", signal_interface_added },
992 { SUPPLICANT_INTERFACE, "InterfaceRemoved", signal_interface_removed },
994 { SUPPLICANT_INTERFACE ".Interface", "BSSAdded", signal_bss_added },
995 { SUPPLICANT_INTERFACE ".Interface", "BSSRemoved", signal_bss_removed },
996 { SUPPLICANT_INTERFACE ".Interface", "NetworkAdded", signal_network_added },
997 { SUPPLICANT_INTERFACE ".Interface", "NetworkRemoved", signal_network_removed },
1002 static DBusHandlerResult supplicant_filter(DBusConnection *conn,
1003 DBusMessage *message, void *data)
1005 DBusMessageIter iter;
1009 path = dbus_message_get_path(message);
1011 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1013 if (dbus_message_iter_init(message, &iter) == FALSE)
1014 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1016 for (i = 0; signal_map[i].interface != NULL; i++) {
1017 if (dbus_message_has_interface(message,
1018 signal_map[i].interface) == FALSE)
1021 if (dbus_message_has_member(message,
1022 signal_map[i].member) == FALSE)
1025 signal_map[i].function(path, &iter);
1029 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1032 static const char *supplicant_rule0 = "type=signal,"
1033 "path=" DBUS_PATH_DBUS ","
1034 "sender=" DBUS_SERVICE_DBUS ","
1035 "interface=" DBUS_INTERFACE_DBUS ","
1036 "member=NameOwnerChanged,"
1037 "arg0=" SUPPLICANT_SERVICE;
1038 static const char *supplicant_rule1 = "type=signal,"
1039 "interface=" SUPPLICANT_INTERFACE;
1040 static const char *supplicant_rule2 = "type=signal,"
1041 "interface=" SUPPLICANT_INTERFACE ".Interface";
1042 static const char *supplicant_rule3 = "type=signal,"
1043 "interface=" SUPPLICANT_INTERFACE ".Interface.WPS";
1044 static const char *supplicant_rule4 = "type=signal,"
1045 "interface=" SUPPLICANT_INTERFACE ".Interface.BSS";
1046 static const char *supplicant_rule5 = "type=signal,"
1047 "interface=" SUPPLICANT_INTERFACE ".Interface.Network";
1048 static const char *supplicant_rule6 = "type=signal,"
1049 "interface=" SUPPLICANT_INTERFACE ".Interface.Blob";
1051 int supplicant_register(const struct supplicant_callbacks *callbacks)
1053 connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
1054 if (connection == NULL)
1057 if (dbus_connection_add_filter(connection,
1058 supplicant_filter, NULL, NULL) == FALSE) {
1059 dbus_connection_unref(connection);
1064 callbacks_pointer = callbacks;
1067 interface_table = g_hash_table_new_full(g_str_hash, g_str_equal,
1068 NULL, remove_interface);
1070 supplicant_dbus_setup(connection);
1072 dbus_bus_add_match(connection, supplicant_rule0, NULL);
1073 dbus_bus_add_match(connection, supplicant_rule1, NULL);
1074 dbus_bus_add_match(connection, supplicant_rule2, NULL);
1075 dbus_bus_add_match(connection, supplicant_rule3, NULL);
1076 dbus_bus_add_match(connection, supplicant_rule4, NULL);
1077 dbus_bus_add_match(connection, supplicant_rule5, NULL);
1078 dbus_bus_add_match(connection, supplicant_rule6, NULL);
1079 dbus_connection_flush(connection);
1081 if (dbus_bus_name_has_owner(connection,
1082 SUPPLICANT_SERVICE, NULL) == TRUE)
1083 supplicant_bootstrap();
1088 void supplicant_unregister(const struct supplicant_callbacks *callbacks)
1090 if (connection != NULL) {
1091 dbus_bus_remove_match(connection, supplicant_rule6, NULL);
1092 dbus_bus_remove_match(connection, supplicant_rule5, NULL);
1093 dbus_bus_remove_match(connection, supplicant_rule4, NULL);
1094 dbus_bus_remove_match(connection, supplicant_rule3, NULL);
1095 dbus_bus_remove_match(connection, supplicant_rule2, NULL);
1096 dbus_bus_remove_match(connection, supplicant_rule1, NULL);
1097 dbus_bus_remove_match(connection, supplicant_rule0, NULL);
1098 dbus_connection_flush(connection);
1100 dbus_connection_remove_filter(connection,
1101 supplicant_filter, NULL);
1104 if (interface_table != NULL) {
1105 g_hash_table_destroy(interface_table);
1106 interface_table = NULL;
1109 if (connection != NULL) {
1110 dbus_connection_unref(connection);
1114 callbacks_pointer = NULL;