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;
56 } eap_method_map[] = {
57 { "MD5", SUPPLICANT_EAP_METHOD_MD5 },
58 { "TLS", SUPPLICANT_EAP_METHOD_TLS },
59 { "MSCHAPV2", SUPPLICANT_EAP_METHOD_MSCHAPV2 },
60 { "PEAP", SUPPLICANT_EAP_METHOD_PEAP },
61 { "TTLS", SUPPLICANT_EAP_METHOD_TTLS },
62 { "GTC", SUPPLICANT_EAP_METHOD_GTC },
63 { "OTP", SUPPLICANT_EAP_METHOD_OTP },
64 { "LEAP", SUPPLICANT_EAP_METHOD_LEAP },
72 { "active", SUPPLICANT_CAPABILITY_SCAN_ACTIVE },
73 { "passive", SUPPLICANT_CAPABILITY_SCAN_PASSIVE },
74 { "ssid", SUPPLICANT_CAPABILITY_SCAN_SSID },
78 static GHashTable *interface_table;
80 struct supplicant_interface {
82 unsigned int scan_capa;
83 enum supplicant_state state;
89 GHashTable *network_table;
90 GHashTable *bss_mapping;
93 struct supplicant_network {
94 struct supplicant_interface *interface;
97 enum supplicant_mode mode;
98 GHashTable *bss_table;
101 struct supplicant_bss {
102 struct supplicant_interface *interface;
104 unsigned char bssid[6];
105 unsigned char ssid[32];
106 unsigned int ssid_len;
107 unsigned int frequency;
108 enum supplicant_mode mode;
109 enum supplicant_security security;
112 dbus_bool_t ieee8021x;
115 static const char *mode2string(enum supplicant_mode mode)
118 case SUPPLICANT_MODE_UNKNOWN:
120 case SUPPLICANT_MODE_INFRA:
122 case SUPPLICANT_MODE_IBSS:
129 static const char *security2string(enum supplicant_security security)
132 case SUPPLICANT_SECURITY_UNKNOWN:
134 case SUPPLICANT_SECURITY_NONE:
136 case SUPPLICANT_SECURITY_WEP:
138 case SUPPLICANT_SECURITY_PSK:
140 case SUPPLICANT_SECURITY_IEEE8021X:
147 static enum supplicant_state string2state(const char *state)
150 return SUPPLICANT_STATE_UNKNOWN;
152 if (g_str_equal(state, "unknown") == TRUE)
153 return SUPPLICANT_STATE_UNKNOWN;
154 else if (g_str_equal(state, "disconnected") == TRUE)
155 return SUPPLICANT_STATE_DISCONNECTED;
156 else if (g_str_equal(state, "inactive") == TRUE)
157 return SUPPLICANT_STATE_INACTIVE;
158 else if (g_str_equal(state, "scanning") == TRUE)
159 return SUPPLICANT_STATE_SCANNING;
160 else if (g_str_equal(state, "authenticating") == TRUE)
161 return SUPPLICANT_STATE_AUTHENTICATING;
162 else if (g_str_equal(state, "associating") == TRUE)
163 return SUPPLICANT_STATE_ASSOCIATING;
164 else if (g_str_equal(state, "associated") == TRUE)
165 return SUPPLICANT_STATE_ASSOCIATED;
166 else if (g_str_equal(state, "group_handshake") == TRUE)
167 return SUPPLICANT_STATE_GROUP_HANDSHAKE;
168 else if (g_str_equal(state, "4way_handshake") == TRUE)
169 return SUPPLICANT_STATE_4WAY_HANDSHAKE;
170 else if (g_str_equal(state, "completed") == TRUE)
171 return SUPPLICANT_STATE_COMPLETED;
173 return SUPPLICANT_STATE_UNKNOWN;
176 static void callback_interface_added(struct supplicant_interface *interface)
178 if (callbacks_pointer == NULL)
181 if (callbacks_pointer->interface_added == NULL)
184 callbacks_pointer->interface_added(interface);
187 static void callback_interface_removed(struct supplicant_interface *interface)
189 if (callbacks_pointer == NULL)
192 if (callbacks_pointer->interface_removed == NULL)
195 callbacks_pointer->interface_removed(interface);
198 static void callback_network_added(struct supplicant_network *network)
200 if (callbacks_pointer == NULL)
203 if (callbacks_pointer->network_added == NULL)
206 callbacks_pointer->network_added(network);
209 static void callback_network_removed(struct supplicant_network *network)
211 if (callbacks_pointer == NULL)
214 if (callbacks_pointer->network_removed == NULL)
217 callbacks_pointer->network_removed(network);
220 static void remove_interface(gpointer data)
222 struct supplicant_interface *interface = data;
224 callback_interface_removed(interface);
226 g_hash_table_destroy(interface->bss_mapping);
227 g_hash_table_destroy(interface->network_table);
229 g_free(interface->path);
230 g_free(interface->ifname);
231 g_free(interface->driver);
232 g_free(interface->bridge);
236 static void remove_network(gpointer data)
238 struct supplicant_network *network = data;
240 callback_network_removed(network);
242 g_free(network->group);
243 g_free(network->name);
247 static void remove_bss(gpointer data)
249 struct supplicant_bss *bss = data;
255 static void debug_eap_methods(void)
259 for (i = 0; eap_method_map[i].str != NULL; i++) {
260 if (eap_methods & eap_method_map[i].val)
261 DBG("EAP Method: %s", eap_method_map[i].str);
265 static void debug_scan_capabilities(struct supplicant_interface *interface)
269 for (i = 0; scan_capa_map[i].str != NULL; i++) {
270 if (interface->scan_capa & scan_capa_map[i].val)
271 DBG("Scan Capability: %s", scan_capa_map[i].str);
275 static void interface_capability_scan(DBusMessageIter *iter, void *user_data)
277 struct supplicant_interface *interface = user_data;
278 const char *str = NULL;
281 dbus_message_iter_get_basic(iter, &str);
285 for (i = 0; scan_capa_map[i].str != NULL; i++)
286 if (strcmp(str, scan_capa_map[i].str) == 0) {
287 interface->scan_capa |= scan_capa_map[i].val;
292 static void interface_capability(const char *key, DBusMessageIter *iter,
295 struct supplicant_interface *interface = user_data;
300 if (g_strcmp0(key, "Scan") == 0)
301 supplicant_dbus_array_foreach(iter, interface_capability_scan,
304 DBG("key %s type %c",
305 key, dbus_message_iter_get_arg_type(iter));
308 const char *supplicant_interface_get_ifname(struct supplicant_interface *interface)
310 if (interface == NULL)
313 return interface->ifname;
316 struct supplicant_interface *supplicant_network_get_interface(struct supplicant_network *network)
321 return network->interface;
324 const char *supplicant_network_get_name(struct supplicant_network *network)
326 if (network == NULL || network->name == NULL)
329 return network->name;
332 const char *supplicant_network_get_identifier(struct supplicant_network *network)
334 if (network == NULL || network->group == NULL)
337 return network->group;
340 enum supplicant_mode supplicant_network_get_mode(struct supplicant_network *network)
343 return SUPPLICANT_MODE_UNKNOWN;
345 return network->mode;
348 static void network_property(const char *key, DBusMessageIter *iter,
354 DBG("key %s type %c", key, dbus_message_iter_get_arg_type(iter));
357 static void interface_network_added(DBusMessageIter *iter, void *user_data)
359 const char *path = NULL;
361 dbus_message_iter_get_basic(iter, &path);
365 DBG("path %s", path);
367 supplicant_dbus_property_get_all(path,
368 SUPPLICANT_INTERFACE ".Interface.Network",
369 network_property, NULL);
372 static void interface_network_removed(DBusMessageIter *iter, void *user_data)
374 const char *path = NULL;
376 dbus_message_iter_get_basic(iter, &path);
380 DBG("path %s", path);
383 static char *create_name(unsigned char *ssid, int ssid_len)
388 if (ssid_len < 1 || ssid[0] == '\0')
391 name = g_try_malloc0(ssid_len + 1);
396 for (i = 0; i < ssid_len; i++) {
397 if (g_ascii_isprint(ssid[i]))
406 static char *create_group(struct supplicant_bss *bss)
410 const char *mode, *security;
412 str = g_string_sized_new((bss->ssid_len * 2) + 24);
416 if (bss->ssid_len > 0 && bss->ssid[0] != '\0') {
417 for (i = 0; i < bss->ssid_len; i++)
418 g_string_append_printf(str, "%02x", bss->ssid[i]);
420 g_string_append_printf(str, "hidden");
422 mode = mode2string(bss->mode);
424 g_string_append_printf(str, "_%s", mode);
426 security = security2string(bss->security);
427 if (security != NULL)
428 g_string_append_printf(str, "_%s", security);
430 return g_string_free(str, FALSE);
433 static void add_bss_to_network(struct supplicant_bss *bss)
435 struct supplicant_interface *interface = bss->interface;
436 struct supplicant_network *network;
439 group = create_group(bss);
443 network = g_hash_table_lookup(interface->network_table, group);
444 if (network != NULL) {
449 network = g_try_new0(struct supplicant_network, 1);
450 if (network == NULL) {
455 network->group = group;
456 network->name = create_name(bss->ssid, bss->ssid_len);
457 network->mode = bss->mode;
459 network->bss_table = g_hash_table_new_full(g_str_hash, g_str_equal,
462 g_hash_table_replace(interface->network_table,
463 network->group, network);
465 callback_network_added(network);
468 g_hash_table_replace(interface->bss_mapping, bss->path, network);
469 g_hash_table_replace(network->bss_table, bss->path, bss);
472 static unsigned char wifi_oui[3] = { 0x00, 0x50, 0xf2 };
473 static unsigned char ieee80211_oui[3] = { 0x00, 0x0f, 0xac };
475 static void extract_rsn(struct supplicant_bss *bss,
476 const unsigned char *buf, int len)
495 /* Pairwise cipher */
499 count = buf[0] | (buf[1] << 8);
500 if (2 + (count * 4) > len)
503 buf += 2 + (count * 4);
504 len -= 2 + (count * 4);
510 count = buf[0] | (buf[1] << 8);
511 if (2 + (count * 4) > len)
514 for (i = 0; i < count; i++) {
515 const unsigned char *ptr = buf + 2 + (i * 4);
517 if (memcmp(ptr, wifi_oui, 3) == 0) {
520 bss->ieee8021x = TRUE;
526 } else if (memcmp(ptr, ieee80211_oui, 3) == 0) {
529 bss->ieee8021x = TRUE;
538 buf += 2 + (count * 4);
539 len -= 2 + (count * 4);
542 static void bss_property(const char *key, DBusMessageIter *iter,
545 struct supplicant_bss *bss = user_data;
547 if (bss->interface == NULL)
551 if (bss->ieee8021x == TRUE)
552 bss->security = SUPPLICANT_SECURITY_IEEE8021X;
553 else if (bss->psk == TRUE)
554 bss->security = SUPPLICANT_SECURITY_PSK;
555 else if (bss->privacy == TRUE)
556 bss->security = SUPPLICANT_SECURITY_WEP;
558 bss->security = SUPPLICANT_SECURITY_NONE;
560 add_bss_to_network(bss);
564 if (g_strcmp0(key, "BSSID") == 0) {
565 DBusMessageIter array;
569 dbus_message_iter_recurse(iter, &array);
570 dbus_message_iter_get_fixed_array(&array, &addr, &addr_len);
573 memcpy(bss->bssid, addr, addr_len);
574 } else if (g_strcmp0(key, "SSID") == 0) {
575 DBusMessageIter array;
579 dbus_message_iter_recurse(iter, &array);
580 dbus_message_iter_get_fixed_array(&array, &ssid, &ssid_len);
582 if (ssid_len > 0 && ssid_len < 33) {
583 memcpy(bss->ssid, ssid, ssid_len);
584 bss->ssid_len = ssid_len;
586 memset(bss->ssid, 0, sizeof(bss->ssid));
589 } else if (g_strcmp0(key, "Capabilities") == 0) {
590 dbus_uint16_t capabilities = 0x0000;
592 dbus_message_iter_get_basic(iter, &capabilities);
594 if (capabilities & IEEE80211_CAP_ESS)
595 bss->mode = SUPPLICANT_MODE_INFRA;
596 else if (capabilities & IEEE80211_CAP_IBSS)
597 bss->mode = SUPPLICANT_MODE_IBSS;
599 if (capabilities & IEEE80211_CAP_PRIVACY)
601 } else if (g_strcmp0(key, "Frequency") == 0) {
602 dbus_int32_t frequency = 0;
604 dbus_message_iter_get_basic(iter, &frequency);
605 bss->frequency = frequency;
606 } else if (g_strcmp0(key, "Level") == 0) {
607 dbus_int32_t level = 0;
609 dbus_message_iter_get_basic(iter, &level);
610 } else if (g_strcmp0(key, "MaxRate") == 0) {
611 dbus_int32_t maxrate = 0;
613 dbus_message_iter_get_basic(iter, &maxrate);
614 } else if (g_strcmp0(key, "RSNIE") == 0) {
615 DBusMessageIter array;
619 dbus_message_iter_recurse(iter, &array);
620 dbus_message_iter_get_fixed_array(&array, &ie, &ie_len);
623 extract_rsn(bss, ie + 2, ie_len - 2);
624 } else if (g_strcmp0(key, "WPAIE") == 0) {
625 DBusMessageIter array;
629 dbus_message_iter_recurse(iter, &array);
630 dbus_message_iter_get_fixed_array(&array, &ie, &ie_len);
633 extract_rsn(bss, ie + 6, ie_len - 6);
634 } else if (g_strcmp0(key, "WPSIE") == 0) {
635 DBusMessageIter array;
639 dbus_message_iter_recurse(iter, &array);
640 dbus_message_iter_get_fixed_array(&array, &ie, &ie_len);
642 DBG("key %s type %c",
643 key, dbus_message_iter_get_arg_type(iter));
646 static void interface_bss_added(DBusMessageIter *iter, void *user_data)
648 struct supplicant_interface *interface = user_data;
649 struct supplicant_network *network;
650 struct supplicant_bss *bss;
651 const char *path = NULL;
653 dbus_message_iter_get_basic(iter, &path);
657 network = g_hash_table_lookup(interface->bss_mapping, path);
658 if (network != NULL) {
659 bss = g_hash_table_lookup(network->bss_table, path);
664 bss = g_try_new0(struct supplicant_bss, 1);
668 bss->interface = interface;
669 bss->path = g_strdup(path);
671 supplicant_dbus_property_get_all(path,
672 SUPPLICANT_INTERFACE ".Interface.BSS",
676 static void interface_bss_removed(DBusMessageIter *iter, void *user_data)
678 struct supplicant_interface *interface = user_data;
679 struct supplicant_network *network;
680 const char *path = NULL;
682 dbus_message_iter_get_basic(iter, &path);
686 network = g_hash_table_lookup(interface->bss_mapping, path);
690 g_hash_table_remove(interface->bss_mapping, path);
691 g_hash_table_remove(network->bss_table, path);
693 if (g_hash_table_size(network->bss_table) == 0)
694 g_hash_table_remove(interface->network_table, network->group);
697 static void interface_property(const char *key, DBusMessageIter *iter,
700 struct supplicant_interface *interface = user_data;
702 if (interface == NULL)
706 debug_scan_capabilities(interface);
708 g_hash_table_replace(interface_table,
709 interface->path, interface);
711 callback_interface_added(interface);
715 if (g_strcmp0(key, "Capabilities") == 0) {
716 supplicant_dbus_property_foreach(iter, interface_capability,
718 } else if (g_strcmp0(key, "State") == 0) {
719 const char *str = NULL;
721 dbus_message_iter_get_basic(iter, &str);
723 interface->state = string2state(str);
724 } else if (g_strcmp0(key, "Scanning") == 0) {
725 dbus_bool_t scanning = FALSE;
727 dbus_message_iter_get_basic(iter, &scanning);
728 interface->scanning = scanning;
729 } else if (g_strcmp0(key, "ApScan") == 0) {
732 dbus_message_iter_get_basic(iter, &apscan);
733 interface->apscan = apscan;
734 } else if (g_strcmp0(key, "Ifname") == 0) {
735 const char *str = NULL;
737 dbus_message_iter_get_basic(iter, &str);
739 interface->ifname = g_strdup(str);
740 } else if (g_strcmp0(key, "Driver") == 0) {
741 const char *str = NULL;
743 dbus_message_iter_get_basic(iter, &str);
745 interface->driver = g_strdup(str);
746 } else if (g_strcmp0(key, "BridgeIfname") == 0) {
747 const char *str = NULL;
749 dbus_message_iter_get_basic(iter, &str);
751 interface->bridge = g_strdup(str);
752 } else if (g_strcmp0(key, "CurrentBSS") == 0) {
753 interface_bss_added(iter, interface);
754 } else if (g_strcmp0(key, "CurrentNetwork") == 0) {
755 interface_network_added(iter, interface);
756 } else if (g_strcmp0(key, "BSSs") == 0) {
757 supplicant_dbus_array_foreach(iter, interface_bss_added,
759 } else if (g_strcmp0(key, "Blobs") == 0) {
760 } else if (g_strcmp0(key, "Networks") == 0) {
761 supplicant_dbus_array_foreach(iter, interface_network_added,
764 DBG("key %s type %c",
765 key, dbus_message_iter_get_arg_type(iter));
768 static void interface_added(DBusMessageIter *iter, void *user_data)
770 struct supplicant_interface *interface;
771 const char *path = NULL;
773 dbus_message_iter_get_basic(iter, &path);
777 interface = g_hash_table_lookup(interface_table, path);
778 if (interface != NULL)
781 interface = g_try_new0(struct supplicant_interface, 1);
782 if (interface == NULL)
785 interface->path = g_strdup(path);
787 interface->network_table = g_hash_table_new_full(g_str_hash, g_str_equal,
788 NULL, remove_network);
790 interface->bss_mapping = g_hash_table_new_full(g_str_hash, g_str_equal,
793 supplicant_dbus_property_get_all(path,
794 SUPPLICANT_INTERFACE ".Interface",
795 interface_property, interface);
798 static void interface_removed(DBusMessageIter *iter, void *user_data)
800 const char *path = NULL;
802 dbus_message_iter_get_basic(iter, &path);
806 g_hash_table_remove(interface_table, path);
809 static void eap_method(DBusMessageIter *iter, void *user_data)
811 const char *str = NULL;
814 dbus_message_iter_get_basic(iter, &str);
818 for (i = 0; eap_method_map[i].str != NULL; i++)
819 if (strcmp(str, eap_method_map[i].str) == 0) {
820 eap_methods |= eap_method_map[i].val;
825 static void service_property(const char *key, DBusMessageIter *iter,
831 if (g_strcmp0(key, "Interfaces") == 0)
832 supplicant_dbus_array_foreach(iter, interface_added, user_data);
833 else if (g_strcmp0(key, "EapMethods") == 0) {
834 supplicant_dbus_array_foreach(iter, eap_method, user_data);
836 } else if (g_strcmp0(key, "DebugParams") == 0) {
840 static void supplicant_bootstrap(void)
842 supplicant_dbus_property_get_all(SUPPLICANT_PATH,
843 SUPPLICANT_INTERFACE,
844 service_property, NULL);
847 static void signal_name_owner_changed(const char *path, DBusMessageIter *iter)
849 const char *name = NULL, *old = NULL, *new = NULL;
851 if (g_strcmp0(path, DBUS_PATH_DBUS) != 0)
854 dbus_message_iter_get_basic(iter, &name);
858 if (g_strcmp0(name, SUPPLICANT_SERVICE) != 0)
861 dbus_message_iter_next(iter);
862 dbus_message_iter_get_basic(iter, &old);
863 dbus_message_iter_next(iter);
864 dbus_message_iter_get_basic(iter, &new);
866 if (old == NULL || new == NULL)
869 if (strlen(old) > 0 && strlen(new) == 0)
870 g_hash_table_remove_all(interface_table);
872 if (strlen(new) > 0 && strlen(old) == 0)
873 supplicant_bootstrap();
876 static void signal_interface_added(const char *path, DBusMessageIter *iter)
878 if (g_strcmp0(path, SUPPLICANT_PATH) == 0)
879 interface_added(iter, NULL);
882 static void signal_interface_removed(const char *path, DBusMessageIter *iter)
884 if (g_strcmp0(path, SUPPLICANT_PATH) == 0)
885 interface_removed(iter, NULL);
888 static void signal_bss_added(const char *path, DBusMessageIter *iter)
890 struct supplicant_interface *interface;
892 interface = g_hash_table_lookup(interface_table, path);
893 if (interface == NULL)
896 interface_bss_added(iter, interface);
899 static void signal_bss_removed(const char *path, DBusMessageIter *iter)
901 struct supplicant_interface *interface;
903 interface = g_hash_table_lookup(interface_table, path);
904 if (interface == NULL)
907 interface_bss_removed(iter, interface);
910 static void signal_network_added(const char *path, DBusMessageIter *iter)
912 struct supplicant_interface *interface;
914 interface = g_hash_table_lookup(interface_table, path);
915 if (interface == NULL)
918 interface_network_added(iter, interface);
921 static void signal_network_removed(const char *path, DBusMessageIter *iter)
923 struct supplicant_interface *interface;
925 interface = g_hash_table_lookup(interface_table, path);
926 if (interface == NULL)
929 interface_network_removed(iter, interface);
933 const char *interface;
935 void (*function) (const char *path, DBusMessageIter *iter);
937 { DBUS_INTERFACE_DBUS, "NameOwnerChanged", signal_name_owner_changed },
939 { SUPPLICANT_INTERFACE, "InterfaceAdded", signal_interface_added },
940 { SUPPLICANT_INTERFACE, "InterfaceCreated", signal_interface_added },
941 { SUPPLICANT_INTERFACE, "InterfaceRemoved", signal_interface_removed },
943 { SUPPLICANT_INTERFACE ".Interface", "BSSAdded", signal_bss_added },
944 { SUPPLICANT_INTERFACE ".Interface", "BSSRemoved", signal_bss_removed },
945 { SUPPLICANT_INTERFACE ".Interface", "NetworkAdded", signal_network_added },
946 { SUPPLICANT_INTERFACE ".Interface", "NetworkRemoved", signal_network_removed },
951 static DBusHandlerResult supplicant_filter(DBusConnection *conn,
952 DBusMessage *message, void *data)
954 DBusMessageIter iter;
958 path = dbus_message_get_path(message);
960 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
962 if (dbus_message_iter_init(message, &iter) == FALSE)
963 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
965 for (i = 0; signal_map[i].interface != NULL; i++) {
966 if (dbus_message_has_interface(message,
967 signal_map[i].interface) == FALSE)
970 if (dbus_message_has_member(message,
971 signal_map[i].member) == FALSE)
974 signal_map[i].function(path, &iter);
978 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
981 static const char *supplicant_rule0 = "type=signal,"
982 "path=" DBUS_PATH_DBUS ","
983 "sender=" DBUS_SERVICE_DBUS ","
984 "interface=" DBUS_INTERFACE_DBUS ","
985 "member=NameOwnerChanged,"
986 "arg0=" SUPPLICANT_SERVICE;
987 static const char *supplicant_rule1 = "type=signal,"
988 "interface=" SUPPLICANT_INTERFACE;
989 static const char *supplicant_rule2 = "type=signal,"
990 "interface=" SUPPLICANT_INTERFACE ".Interface";
991 static const char *supplicant_rule3 = "type=signal,"
992 "interface=" SUPPLICANT_INTERFACE ".Interface.WPS";
993 static const char *supplicant_rule4 = "type=signal,"
994 "interface=" SUPPLICANT_INTERFACE ".Interface.BSS";
995 static const char *supplicant_rule5 = "type=signal,"
996 "interface=" SUPPLICANT_INTERFACE ".Interface.Network";
997 static const char *supplicant_rule6 = "type=signal,"
998 "interface=" SUPPLICANT_INTERFACE ".Interface.Blob";
1000 int supplicant_register(const struct supplicant_callbacks *callbacks)
1002 connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
1003 if (connection == NULL)
1006 if (dbus_connection_add_filter(connection,
1007 supplicant_filter, NULL, NULL) == FALSE) {
1008 dbus_connection_unref(connection);
1013 callbacks_pointer = callbacks;
1016 interface_table = g_hash_table_new_full(g_str_hash, g_str_equal,
1017 NULL, remove_interface);
1019 supplicant_dbus_setup(connection);
1021 dbus_bus_add_match(connection, supplicant_rule0, NULL);
1022 dbus_bus_add_match(connection, supplicant_rule1, NULL);
1023 dbus_bus_add_match(connection, supplicant_rule2, NULL);
1024 dbus_bus_add_match(connection, supplicant_rule3, NULL);
1025 dbus_bus_add_match(connection, supplicant_rule4, NULL);
1026 dbus_bus_add_match(connection, supplicant_rule5, NULL);
1027 dbus_bus_add_match(connection, supplicant_rule6, NULL);
1028 dbus_connection_flush(connection);
1030 if (dbus_bus_name_has_owner(connection,
1031 SUPPLICANT_SERVICE, NULL) == TRUE)
1032 supplicant_bootstrap();
1037 void supplicant_unregister(const struct supplicant_callbacks *callbacks)
1039 if (connection != NULL) {
1040 dbus_bus_remove_match(connection, supplicant_rule6, NULL);
1041 dbus_bus_remove_match(connection, supplicant_rule5, NULL);
1042 dbus_bus_remove_match(connection, supplicant_rule4, NULL);
1043 dbus_bus_remove_match(connection, supplicant_rule3, NULL);
1044 dbus_bus_remove_match(connection, supplicant_rule2, NULL);
1045 dbus_bus_remove_match(connection, supplicant_rule1, NULL);
1046 dbus_bus_remove_match(connection, supplicant_rule0, NULL);
1047 dbus_connection_flush(connection);
1049 dbus_connection_remove_filter(connection,
1050 supplicant_filter, NULL);
1053 if (interface_table != NULL) {
1054 g_hash_table_destroy(interface_table);
1055 interface_table = NULL;
1058 if (connection != NULL) {
1059 dbus_connection_unref(connection);
1063 callbacks_pointer = NULL;