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 dbus_int32_t debug_level = 0;
52 static dbus_bool_t debug_show_timestamps = FALSE;
53 static dbus_bool_t debug_show_keys = FALSE;
55 static unsigned int eap_methods;
62 static struct strvalmap eap_method_map[] = {
63 { "MD5", SUPPLICANT_EAP_METHOD_MD5 },
64 { "TLS", SUPPLICANT_EAP_METHOD_TLS },
65 { "MSCHAPV2", SUPPLICANT_EAP_METHOD_MSCHAPV2 },
66 { "PEAP", SUPPLICANT_EAP_METHOD_PEAP },
67 { "TTLS", SUPPLICANT_EAP_METHOD_TTLS },
68 { "GTC", SUPPLICANT_EAP_METHOD_GTC },
69 { "OTP", SUPPLICANT_EAP_METHOD_OTP },
70 { "LEAP", SUPPLICANT_EAP_METHOD_LEAP },
74 static struct strvalmap auth_capa_map[] = {
75 { "open", SUPPLICANT_CAPABILITY_AUTH_OPEN },
76 { "shared", SUPPLICANT_CAPABILITY_AUTH_SHARED },
77 { "leap", SUPPLICANT_CAPABILITY_AUTH_LEAP },
81 static struct strvalmap scan_capa_map[] = {
82 { "active", SUPPLICANT_CAPABILITY_SCAN_ACTIVE },
83 { "passive", SUPPLICANT_CAPABILITY_SCAN_PASSIVE },
84 { "ssid", SUPPLICANT_CAPABILITY_SCAN_SSID },
88 static struct strvalmap mode_capa_map[] = {
89 { "infrastructure", SUPPLICANT_CAPABILITY_MODE_INFRA },
90 { "ad-hoc", SUPPLICANT_CAPABILITY_MODE_IBSS },
91 { "ap", SUPPLICANT_CAPABILITY_MODE_AP },
95 static GHashTable *interface_table;
97 struct supplicant_interface {
99 unsigned int auth_capa;
100 unsigned int scan_capa;
101 unsigned int mode_capa;
102 enum supplicant_state state;
103 dbus_bool_t scanning;
108 GHashTable *network_table;
109 GHashTable *bss_mapping;
112 struct supplicant_network {
113 struct supplicant_interface *interface;
116 enum supplicant_mode mode;
117 GHashTable *bss_table;
120 struct supplicant_bss {
121 struct supplicant_interface *interface;
123 unsigned char bssid[6];
124 unsigned char ssid[32];
125 unsigned int ssid_len;
126 unsigned int frequency;
127 enum supplicant_mode mode;
128 enum supplicant_security security;
131 dbus_bool_t ieee8021x;
134 static const char *mode2string(enum supplicant_mode mode)
137 case SUPPLICANT_MODE_UNKNOWN:
139 case SUPPLICANT_MODE_INFRA:
141 case SUPPLICANT_MODE_IBSS:
148 static const char *security2string(enum supplicant_security security)
151 case SUPPLICANT_SECURITY_UNKNOWN:
153 case SUPPLICANT_SECURITY_NONE:
155 case SUPPLICANT_SECURITY_WEP:
157 case SUPPLICANT_SECURITY_PSK:
159 case SUPPLICANT_SECURITY_IEEE8021X:
166 static enum supplicant_state string2state(const char *state)
169 return SUPPLICANT_STATE_UNKNOWN;
171 if (g_str_equal(state, "unknown") == TRUE)
172 return SUPPLICANT_STATE_UNKNOWN;
173 else if (g_str_equal(state, "disconnected") == TRUE)
174 return SUPPLICANT_STATE_DISCONNECTED;
175 else if (g_str_equal(state, "inactive") == TRUE)
176 return SUPPLICANT_STATE_INACTIVE;
177 else if (g_str_equal(state, "scanning") == TRUE)
178 return SUPPLICANT_STATE_SCANNING;
179 else if (g_str_equal(state, "authenticating") == TRUE)
180 return SUPPLICANT_STATE_AUTHENTICATING;
181 else if (g_str_equal(state, "associating") == TRUE)
182 return SUPPLICANT_STATE_ASSOCIATING;
183 else if (g_str_equal(state, "associated") == TRUE)
184 return SUPPLICANT_STATE_ASSOCIATED;
185 else if (g_str_equal(state, "group_handshake") == TRUE)
186 return SUPPLICANT_STATE_GROUP_HANDSHAKE;
187 else if (g_str_equal(state, "4way_handshake") == TRUE)
188 return SUPPLICANT_STATE_4WAY_HANDSHAKE;
189 else if (g_str_equal(state, "completed") == TRUE)
190 return SUPPLICANT_STATE_COMPLETED;
192 return SUPPLICANT_STATE_UNKNOWN;
195 static void callback_interface_added(struct supplicant_interface *interface)
197 if (callbacks_pointer == NULL)
200 if (callbacks_pointer->interface_added == NULL)
203 callbacks_pointer->interface_added(interface);
206 static void callback_interface_removed(struct supplicant_interface *interface)
208 if (callbacks_pointer == NULL)
211 if (callbacks_pointer->interface_removed == NULL)
214 callbacks_pointer->interface_removed(interface);
217 static void callback_network_added(struct supplicant_network *network)
219 if (callbacks_pointer == NULL)
222 if (callbacks_pointer->network_added == NULL)
225 callbacks_pointer->network_added(network);
228 static void callback_network_removed(struct supplicant_network *network)
230 if (callbacks_pointer == NULL)
233 if (callbacks_pointer->network_removed == NULL)
236 callbacks_pointer->network_removed(network);
239 static void remove_interface(gpointer data)
241 struct supplicant_interface *interface = data;
243 callback_interface_removed(interface);
245 g_hash_table_destroy(interface->bss_mapping);
246 g_hash_table_destroy(interface->network_table);
248 g_free(interface->path);
249 g_free(interface->ifname);
250 g_free(interface->driver);
251 g_free(interface->bridge);
255 static void remove_network(gpointer data)
257 struct supplicant_network *network = data;
259 callback_network_removed(network);
261 g_free(network->group);
262 g_free(network->name);
266 static void remove_bss(gpointer data)
268 struct supplicant_bss *bss = data;
274 static void debug_strvalmap(const char *label, struct strvalmap *map,
279 for (i = 0; map[i].str != NULL; i++) {
280 if (val & map[i].val)
281 DBG("%s: %s", label, map[i].str);
285 static void interface_capability_auth(DBusMessageIter *iter, void *user_data)
287 struct supplicant_interface *interface = user_data;
288 const char *str = NULL;
291 dbus_message_iter_get_basic(iter, &str);
295 for (i = 0; auth_capa_map[i].str != NULL; i++)
296 if (strcmp(str, auth_capa_map[i].str) == 0) {
297 interface->auth_capa |= auth_capa_map[i].val;
302 static void interface_capability_scan(DBusMessageIter *iter, void *user_data)
304 struct supplicant_interface *interface = user_data;
305 const char *str = NULL;
308 dbus_message_iter_get_basic(iter, &str);
312 for (i = 0; scan_capa_map[i].str != NULL; i++)
313 if (strcmp(str, scan_capa_map[i].str) == 0) {
314 interface->scan_capa |= scan_capa_map[i].val;
319 static void interface_capability_mode(DBusMessageIter *iter, void *user_data)
321 struct supplicant_interface *interface = user_data;
322 const char *str = NULL;
325 dbus_message_iter_get_basic(iter, &str);
329 for (i = 0; mode_capa_map[i].str != NULL; i++)
330 if (strcmp(str, mode_capa_map[i].str) == 0) {
331 interface->mode_capa |= mode_capa_map[i].val;
336 static void interface_capability(const char *key, DBusMessageIter *iter,
339 struct supplicant_interface *interface = user_data;
344 if (g_strcmp0(key, "AuthAlg") == 0)
345 supplicant_dbus_array_foreach(iter, interface_capability_auth,
347 else if (g_strcmp0(key, "Scan") == 0)
348 supplicant_dbus_array_foreach(iter, interface_capability_scan,
350 else if (g_strcmp0(key, "Modes") == 0)
351 supplicant_dbus_array_foreach(iter, interface_capability_mode,
354 DBG("key %s type %c",
355 key, dbus_message_iter_get_arg_type(iter));
358 const char *supplicant_interface_get_ifname(struct supplicant_interface *interface)
360 if (interface == NULL)
363 return interface->ifname;
366 struct supplicant_interface *supplicant_network_get_interface(struct supplicant_network *network)
371 return network->interface;
374 const char *supplicant_network_get_name(struct supplicant_network *network)
376 if (network == NULL || network->name == NULL)
379 return network->name;
382 const char *supplicant_network_get_identifier(struct supplicant_network *network)
384 if (network == NULL || network->group == NULL)
387 return network->group;
390 enum supplicant_mode supplicant_network_get_mode(struct supplicant_network *network)
393 return SUPPLICANT_MODE_UNKNOWN;
395 return network->mode;
398 static void network_property(const char *key, DBusMessageIter *iter,
404 DBG("key %s type %c", key, dbus_message_iter_get_arg_type(iter));
407 static void interface_network_added(DBusMessageIter *iter, void *user_data)
409 const char *path = NULL;
411 dbus_message_iter_get_basic(iter, &path);
415 DBG("path %s", path);
417 supplicant_dbus_property_get_all(path,
418 SUPPLICANT_INTERFACE ".Interface.Network",
419 network_property, NULL);
422 static void interface_network_removed(DBusMessageIter *iter, void *user_data)
424 const char *path = NULL;
426 dbus_message_iter_get_basic(iter, &path);
430 DBG("path %s", path);
433 static char *create_name(unsigned char *ssid, int ssid_len)
438 if (ssid_len < 1 || ssid[0] == '\0')
441 name = g_try_malloc0(ssid_len + 1);
446 for (i = 0; i < ssid_len; i++) {
447 if (g_ascii_isprint(ssid[i]))
456 static char *create_group(struct supplicant_bss *bss)
460 const char *mode, *security;
462 str = g_string_sized_new((bss->ssid_len * 2) + 24);
466 if (bss->ssid_len > 0 && bss->ssid[0] != '\0') {
467 for (i = 0; i < bss->ssid_len; i++)
468 g_string_append_printf(str, "%02x", bss->ssid[i]);
470 g_string_append_printf(str, "hidden");
472 mode = mode2string(bss->mode);
474 g_string_append_printf(str, "_%s", mode);
476 security = security2string(bss->security);
477 if (security != NULL)
478 g_string_append_printf(str, "_%s", security);
480 return g_string_free(str, FALSE);
483 static void add_bss_to_network(struct supplicant_bss *bss)
485 struct supplicant_interface *interface = bss->interface;
486 struct supplicant_network *network;
489 group = create_group(bss);
493 network = g_hash_table_lookup(interface->network_table, group);
494 if (network != NULL) {
499 network = g_try_new0(struct supplicant_network, 1);
500 if (network == NULL) {
505 network->group = group;
506 network->name = create_name(bss->ssid, bss->ssid_len);
507 network->mode = bss->mode;
509 network->bss_table = g_hash_table_new_full(g_str_hash, g_str_equal,
512 g_hash_table_replace(interface->network_table,
513 network->group, network);
515 callback_network_added(network);
518 g_hash_table_replace(interface->bss_mapping, bss->path, network);
519 g_hash_table_replace(network->bss_table, bss->path, bss);
522 static unsigned char wifi_oui[3] = { 0x00, 0x50, 0xf2 };
523 static unsigned char ieee80211_oui[3] = { 0x00, 0x0f, 0xac };
525 static void extract_rsn(struct supplicant_bss *bss,
526 const unsigned char *buf, int len)
545 /* Pairwise cipher */
549 count = buf[0] | (buf[1] << 8);
550 if (2 + (count * 4) > len)
553 buf += 2 + (count * 4);
554 len -= 2 + (count * 4);
560 count = buf[0] | (buf[1] << 8);
561 if (2 + (count * 4) > len)
564 for (i = 0; i < count; i++) {
565 const unsigned char *ptr = buf + 2 + (i * 4);
567 if (memcmp(ptr, wifi_oui, 3) == 0) {
570 bss->ieee8021x = TRUE;
576 } else if (memcmp(ptr, ieee80211_oui, 3) == 0) {
579 bss->ieee8021x = TRUE;
588 buf += 2 + (count * 4);
589 len -= 2 + (count * 4);
592 static void bss_property(const char *key, DBusMessageIter *iter,
595 struct supplicant_bss *bss = user_data;
597 if (bss->interface == NULL)
601 if (bss->ieee8021x == TRUE)
602 bss->security = SUPPLICANT_SECURITY_IEEE8021X;
603 else if (bss->psk == TRUE)
604 bss->security = SUPPLICANT_SECURITY_PSK;
605 else if (bss->privacy == TRUE)
606 bss->security = SUPPLICANT_SECURITY_WEP;
608 bss->security = SUPPLICANT_SECURITY_NONE;
610 add_bss_to_network(bss);
614 if (g_strcmp0(key, "BSSID") == 0) {
615 DBusMessageIter array;
619 dbus_message_iter_recurse(iter, &array);
620 dbus_message_iter_get_fixed_array(&array, &addr, &addr_len);
623 memcpy(bss->bssid, addr, addr_len);
624 } else if (g_strcmp0(key, "SSID") == 0) {
625 DBusMessageIter array;
629 dbus_message_iter_recurse(iter, &array);
630 dbus_message_iter_get_fixed_array(&array, &ssid, &ssid_len);
632 if (ssid_len > 0 && ssid_len < 33) {
633 memcpy(bss->ssid, ssid, ssid_len);
634 bss->ssid_len = ssid_len;
636 memset(bss->ssid, 0, sizeof(bss->ssid));
639 } else if (g_strcmp0(key, "Capabilities") == 0) {
640 dbus_uint16_t capabilities = 0x0000;
642 dbus_message_iter_get_basic(iter, &capabilities);
644 if (capabilities & IEEE80211_CAP_ESS)
645 bss->mode = SUPPLICANT_MODE_INFRA;
646 else if (capabilities & IEEE80211_CAP_IBSS)
647 bss->mode = SUPPLICANT_MODE_IBSS;
649 if (capabilities & IEEE80211_CAP_PRIVACY)
651 } else if (g_strcmp0(key, "Frequency") == 0) {
652 dbus_int32_t frequency = 0;
654 dbus_message_iter_get_basic(iter, &frequency);
655 bss->frequency = frequency;
656 } else if (g_strcmp0(key, "Level") == 0) {
657 dbus_int32_t level = 0;
659 dbus_message_iter_get_basic(iter, &level);
660 } else if (g_strcmp0(key, "MaxRate") == 0) {
661 dbus_int32_t maxrate = 0;
663 dbus_message_iter_get_basic(iter, &maxrate);
664 } else if (g_strcmp0(key, "RSNIE") == 0) {
665 DBusMessageIter array;
669 dbus_message_iter_recurse(iter, &array);
670 dbus_message_iter_get_fixed_array(&array, &ie, &ie_len);
673 extract_rsn(bss, ie + 2, ie_len - 2);
674 } else if (g_strcmp0(key, "WPAIE") == 0) {
675 DBusMessageIter array;
679 dbus_message_iter_recurse(iter, &array);
680 dbus_message_iter_get_fixed_array(&array, &ie, &ie_len);
683 extract_rsn(bss, ie + 6, ie_len - 6);
684 } else if (g_strcmp0(key, "WPSIE") == 0) {
685 DBusMessageIter array;
689 dbus_message_iter_recurse(iter, &array);
690 dbus_message_iter_get_fixed_array(&array, &ie, &ie_len);
692 DBG("key %s type %c",
693 key, dbus_message_iter_get_arg_type(iter));
696 static void interface_bss_added(DBusMessageIter *iter, void *user_data)
698 struct supplicant_interface *interface = user_data;
699 struct supplicant_network *network;
700 struct supplicant_bss *bss;
701 const char *path = NULL;
703 dbus_message_iter_get_basic(iter, &path);
707 network = g_hash_table_lookup(interface->bss_mapping, path);
708 if (network != NULL) {
709 bss = g_hash_table_lookup(network->bss_table, path);
714 bss = g_try_new0(struct supplicant_bss, 1);
718 bss->interface = interface;
719 bss->path = g_strdup(path);
721 supplicant_dbus_property_get_all(path,
722 SUPPLICANT_INTERFACE ".Interface.BSS",
726 static void interface_bss_removed(DBusMessageIter *iter, void *user_data)
728 struct supplicant_interface *interface = user_data;
729 struct supplicant_network *network;
730 const char *path = NULL;
732 dbus_message_iter_get_basic(iter, &path);
736 network = g_hash_table_lookup(interface->bss_mapping, path);
740 g_hash_table_remove(interface->bss_mapping, path);
741 g_hash_table_remove(network->bss_table, path);
743 if (g_hash_table_size(network->bss_table) == 0)
744 g_hash_table_remove(interface->network_table, network->group);
747 static void interface_property(const char *key, DBusMessageIter *iter,
750 struct supplicant_interface *interface = user_data;
752 if (interface == NULL)
756 debug_strvalmap("Auth capability", auth_capa_map,
757 interface->auth_capa);
758 debug_strvalmap("Scan capability", scan_capa_map,
759 interface->scan_capa);
760 debug_strvalmap("Mode capability", mode_capa_map,
761 interface->mode_capa);
763 g_hash_table_replace(interface_table,
764 interface->path, interface);
766 callback_interface_added(interface);
770 if (g_strcmp0(key, "Capabilities") == 0) {
771 supplicant_dbus_property_foreach(iter, interface_capability,
773 } else if (g_strcmp0(key, "State") == 0) {
774 const char *str = NULL;
776 dbus_message_iter_get_basic(iter, &str);
778 interface->state = string2state(str);
779 } else if (g_strcmp0(key, "Scanning") == 0) {
780 dbus_bool_t scanning = FALSE;
782 dbus_message_iter_get_basic(iter, &scanning);
783 interface->scanning = scanning;
784 } else if (g_strcmp0(key, "ApScan") == 0) {
787 dbus_message_iter_get_basic(iter, &apscan);
788 interface->apscan = apscan;
789 } else if (g_strcmp0(key, "Ifname") == 0) {
790 const char *str = NULL;
792 dbus_message_iter_get_basic(iter, &str);
794 interface->ifname = g_strdup(str);
795 } else if (g_strcmp0(key, "Driver") == 0) {
796 const char *str = NULL;
798 dbus_message_iter_get_basic(iter, &str);
800 interface->driver = g_strdup(str);
801 } else if (g_strcmp0(key, "BridgeIfname") == 0) {
802 const char *str = NULL;
804 dbus_message_iter_get_basic(iter, &str);
806 interface->bridge = g_strdup(str);
807 } else if (g_strcmp0(key, "CurrentBSS") == 0) {
808 interface_bss_added(iter, interface);
809 } else if (g_strcmp0(key, "CurrentNetwork") == 0) {
810 interface_network_added(iter, interface);
811 } else if (g_strcmp0(key, "BSSs") == 0) {
812 supplicant_dbus_array_foreach(iter, interface_bss_added,
814 } else if (g_strcmp0(key, "Blobs") == 0) {
815 } else if (g_strcmp0(key, "Networks") == 0) {
816 supplicant_dbus_array_foreach(iter, interface_network_added,
819 DBG("key %s type %c",
820 key, dbus_message_iter_get_arg_type(iter));
823 static void interface_added(DBusMessageIter *iter, void *user_data)
825 struct supplicant_interface *interface;
826 const char *path = NULL;
828 dbus_message_iter_get_basic(iter, &path);
832 interface = g_hash_table_lookup(interface_table, path);
833 if (interface != NULL)
836 interface = g_try_new0(struct supplicant_interface, 1);
837 if (interface == NULL)
840 interface->path = g_strdup(path);
842 interface->network_table = g_hash_table_new_full(g_str_hash, g_str_equal,
843 NULL, remove_network);
845 interface->bss_mapping = g_hash_table_new_full(g_str_hash, g_str_equal,
848 supplicant_dbus_property_get_all(path,
849 SUPPLICANT_INTERFACE ".Interface",
850 interface_property, interface);
853 static void interface_removed(DBusMessageIter *iter, void *user_data)
855 const char *path = NULL;
857 dbus_message_iter_get_basic(iter, &path);
861 g_hash_table_remove(interface_table, path);
864 static void eap_method(DBusMessageIter *iter, void *user_data)
866 const char *str = NULL;
869 dbus_message_iter_get_basic(iter, &str);
873 for (i = 0; eap_method_map[i].str != NULL; i++)
874 if (strcmp(str, eap_method_map[i].str) == 0) {
875 eap_methods |= eap_method_map[i].val;
880 static void service_property(const char *key, DBusMessageIter *iter,
886 if (g_strcmp0(key, "DebugParams") == 0) {
887 DBusMessageIter list;
889 dbus_message_iter_recurse(iter, &list);
890 dbus_message_iter_get_basic(&list, &debug_level);
892 dbus_message_iter_next(&list);
893 dbus_message_iter_get_basic(&list, &debug_show_timestamps);
895 dbus_message_iter_next(&list);
896 dbus_message_iter_get_basic(&list, &debug_show_keys);
898 DBG("Debug level %d (timestamps %u keys %u)", debug_level,
899 debug_show_timestamps, debug_show_keys);
900 } else if (g_strcmp0(key, "Interfaces") == 0) {
901 supplicant_dbus_array_foreach(iter, interface_added, user_data);
902 } else if (g_strcmp0(key, "EapMethods") == 0) {
903 supplicant_dbus_array_foreach(iter, eap_method, user_data);
904 debug_strvalmap("EAP method", eap_method_map, eap_methods);
908 static void supplicant_bootstrap(void)
910 supplicant_dbus_property_get_all(SUPPLICANT_PATH,
911 SUPPLICANT_INTERFACE,
912 service_property, NULL);
915 static void signal_name_owner_changed(const char *path, DBusMessageIter *iter)
917 const char *name = NULL, *old = NULL, *new = NULL;
919 if (g_strcmp0(path, DBUS_PATH_DBUS) != 0)
922 dbus_message_iter_get_basic(iter, &name);
926 if (g_strcmp0(name, SUPPLICANT_SERVICE) != 0)
929 dbus_message_iter_next(iter);
930 dbus_message_iter_get_basic(iter, &old);
931 dbus_message_iter_next(iter);
932 dbus_message_iter_get_basic(iter, &new);
934 if (old == NULL || new == NULL)
937 if (strlen(old) > 0 && strlen(new) == 0)
938 g_hash_table_remove_all(interface_table);
940 if (strlen(new) > 0 && strlen(old) == 0)
941 supplicant_bootstrap();
944 static void signal_properties_changed(const char *path, DBusMessageIter *iter)
946 if (g_strcmp0(path, SUPPLICANT_PATH) != 0)
949 supplicant_dbus_property_foreach(iter, service_property, NULL);
952 static void signal_interface_added(const char *path, DBusMessageIter *iter)
954 if (g_strcmp0(path, SUPPLICANT_PATH) == 0)
955 interface_added(iter, NULL);
958 static void signal_interface_removed(const char *path, DBusMessageIter *iter)
960 if (g_strcmp0(path, SUPPLICANT_PATH) == 0)
961 interface_removed(iter, NULL);
964 static void signal_bss_added(const char *path, DBusMessageIter *iter)
966 struct supplicant_interface *interface;
968 interface = g_hash_table_lookup(interface_table, path);
969 if (interface == NULL)
972 interface_bss_added(iter, interface);
975 static void signal_bss_removed(const char *path, DBusMessageIter *iter)
977 struct supplicant_interface *interface;
979 interface = g_hash_table_lookup(interface_table, path);
980 if (interface == NULL)
983 interface_bss_removed(iter, interface);
986 static void signal_network_added(const char *path, DBusMessageIter *iter)
988 struct supplicant_interface *interface;
990 interface = g_hash_table_lookup(interface_table, path);
991 if (interface == NULL)
994 interface_network_added(iter, interface);
997 static void signal_network_removed(const char *path, DBusMessageIter *iter)
999 struct supplicant_interface *interface;
1001 interface = g_hash_table_lookup(interface_table, path);
1002 if (interface == NULL)
1005 interface_network_removed(iter, interface);
1009 const char *interface;
1011 void (*function) (const char *path, DBusMessageIter *iter);
1013 { DBUS_INTERFACE_DBUS, "NameOwnerChanged", signal_name_owner_changed },
1015 { SUPPLICANT_INTERFACE, "PropertiesChanged", signal_properties_changed },
1016 { SUPPLICANT_INTERFACE, "InterfaceAdded", signal_interface_added },
1017 { SUPPLICANT_INTERFACE, "InterfaceCreated", signal_interface_added },
1018 { SUPPLICANT_INTERFACE, "InterfaceRemoved", signal_interface_removed },
1020 { SUPPLICANT_INTERFACE ".Interface", "BSSAdded", signal_bss_added },
1021 { SUPPLICANT_INTERFACE ".Interface", "BSSRemoved", signal_bss_removed },
1022 { SUPPLICANT_INTERFACE ".Interface", "NetworkAdded", signal_network_added },
1023 { SUPPLICANT_INTERFACE ".Interface", "NetworkRemoved", signal_network_removed },
1028 static DBusHandlerResult supplicant_filter(DBusConnection *conn,
1029 DBusMessage *message, void *data)
1031 DBusMessageIter iter;
1035 path = dbus_message_get_path(message);
1037 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1039 if (dbus_message_iter_init(message, &iter) == FALSE)
1040 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1042 for (i = 0; signal_map[i].interface != NULL; i++) {
1043 if (dbus_message_has_interface(message,
1044 signal_map[i].interface) == FALSE)
1047 if (dbus_message_has_member(message,
1048 signal_map[i].member) == FALSE)
1051 signal_map[i].function(path, &iter);
1055 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1058 static const char *supplicant_rule0 = "type=signal,"
1059 "path=" DBUS_PATH_DBUS ","
1060 "sender=" DBUS_SERVICE_DBUS ","
1061 "interface=" DBUS_INTERFACE_DBUS ","
1062 "member=NameOwnerChanged,"
1063 "arg0=" SUPPLICANT_SERVICE;
1064 static const char *supplicant_rule1 = "type=signal,"
1065 "interface=" SUPPLICANT_INTERFACE;
1066 static const char *supplicant_rule2 = "type=signal,"
1067 "interface=" SUPPLICANT_INTERFACE ".Interface";
1068 static const char *supplicant_rule3 = "type=signal,"
1069 "interface=" SUPPLICANT_INTERFACE ".Interface.WPS";
1070 static const char *supplicant_rule4 = "type=signal,"
1071 "interface=" SUPPLICANT_INTERFACE ".Interface.BSS";
1072 static const char *supplicant_rule5 = "type=signal,"
1073 "interface=" SUPPLICANT_INTERFACE ".Interface.Network";
1074 static const char *supplicant_rule6 = "type=signal,"
1075 "interface=" SUPPLICANT_INTERFACE ".Interface.Blob";
1077 int supplicant_register(const struct supplicant_callbacks *callbacks)
1079 connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
1080 if (connection == NULL)
1083 if (dbus_connection_add_filter(connection,
1084 supplicant_filter, NULL, NULL) == FALSE) {
1085 dbus_connection_unref(connection);
1090 callbacks_pointer = callbacks;
1093 interface_table = g_hash_table_new_full(g_str_hash, g_str_equal,
1094 NULL, remove_interface);
1096 supplicant_dbus_setup(connection);
1098 dbus_bus_add_match(connection, supplicant_rule0, NULL);
1099 dbus_bus_add_match(connection, supplicant_rule1, NULL);
1100 dbus_bus_add_match(connection, supplicant_rule2, NULL);
1101 dbus_bus_add_match(connection, supplicant_rule3, NULL);
1102 dbus_bus_add_match(connection, supplicant_rule4, NULL);
1103 dbus_bus_add_match(connection, supplicant_rule5, NULL);
1104 dbus_bus_add_match(connection, supplicant_rule6, NULL);
1105 dbus_connection_flush(connection);
1107 if (dbus_bus_name_has_owner(connection,
1108 SUPPLICANT_SERVICE, NULL) == TRUE)
1109 supplicant_bootstrap();
1114 void supplicant_unregister(const struct supplicant_callbacks *callbacks)
1116 if (connection != NULL) {
1117 dbus_bus_remove_match(connection, supplicant_rule6, NULL);
1118 dbus_bus_remove_match(connection, supplicant_rule5, NULL);
1119 dbus_bus_remove_match(connection, supplicant_rule4, NULL);
1120 dbus_bus_remove_match(connection, supplicant_rule3, NULL);
1121 dbus_bus_remove_match(connection, supplicant_rule2, NULL);
1122 dbus_bus_remove_match(connection, supplicant_rule1, NULL);
1123 dbus_bus_remove_match(connection, supplicant_rule0, NULL);
1124 dbus_connection_flush(connection);
1126 dbus_connection_remove_filter(connection,
1127 supplicant_filter, NULL);
1130 if (interface_table != NULL) {
1131 g_hash_table_destroy(interface_table);
1132 interface_table = NULL;
1135 if (connection != NULL) {
1136 dbus_connection_unref(connection);
1140 callbacks_pointer = NULL;
1144 static void add_debug_level(DBusMessageIter *iter, void *user_data)
1146 dbus_int32_t level = GPOINTER_TO_UINT(user_data);
1147 DBusMessageIter entry;
1149 dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT,
1152 dbus_message_iter_append_basic(&entry, DBUS_TYPE_INT32, &level);
1153 dbus_message_iter_append_basic(&entry, DBUS_TYPE_BOOLEAN,
1154 &debug_show_timestamps);
1155 dbus_message_iter_append_basic(&entry, DBUS_TYPE_BOOLEAN,
1158 dbus_message_iter_close_container(iter, &entry);
1161 void supplicant_set_debug_level(unsigned int level)
1163 supplicant_dbus_property_set(SUPPLICANT_PATH, SUPPLICANT_INTERFACE,
1164 "DebugParams", "(ibb)",
1165 add_debug_level, GUINT_TO_POINTER(level));
1168 static void add_show_timestamps(DBusMessageIter *iter, void *user_data)
1170 dbus_bool_t show_timestamps = GPOINTER_TO_UINT(user_data);
1171 DBusMessageIter entry;
1173 dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT,
1176 dbus_message_iter_append_basic(&entry, DBUS_TYPE_INT32, &debug_level);
1177 dbus_message_iter_append_basic(&entry, DBUS_TYPE_BOOLEAN,
1179 dbus_message_iter_append_basic(&entry, DBUS_TYPE_BOOLEAN,
1182 dbus_message_iter_close_container(iter, &entry);
1185 void supplicant_set_debug_show_timestamps(dbus_bool_t enabled)
1187 supplicant_dbus_property_set(SUPPLICANT_PATH, SUPPLICANT_INTERFACE,
1188 "DebugParams", "(ibb)",
1189 add_show_timestamps, GUINT_TO_POINTER(enabled));