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 debug_level_result(const char *error,
1145
DBusMessageIter *iter, void *user_data)
1148
DBG("debug level failure: %s", error);
1151
static void add_debug_level(DBusMessageIter *iter, void *user_data)
1153
dbus_int32_t level = GPOINTER_TO_UINT(user_data);
1154
DBusMessageIter entry;
1156
dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT,
1159
dbus_message_iter_append_basic(&entry, DBUS_TYPE_INT32, &level);
1160
dbus_message_iter_append_basic(&entry, DBUS_TYPE_BOOLEAN,
1161
&debug_show_timestamps);
1162
dbus_message_iter_append_basic(&entry, DBUS_TYPE_BOOLEAN,
1165
dbus_message_iter_close_container(iter, &entry);
1168
void supplicant_set_debug_level(unsigned int level)
1170
supplicant_dbus_property_set(SUPPLICANT_PATH, SUPPLICANT_INTERFACE,
1171
"DebugParams", "(ibb)", add_debug_level,
1172
debug_level_result, GUINT_TO_POINTER(level));
1175
static void add_show_timestamps(DBusMessageIter *iter, void *user_data)
1177
dbus_bool_t show_timestamps = GPOINTER_TO_UINT(user_data);
1178
DBusMessageIter entry;
1180
dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT,
1183
dbus_message_iter_append_basic(&entry, DBUS_TYPE_INT32, &debug_level);
1184
dbus_message_iter_append_basic(&entry, DBUS_TYPE_BOOLEAN,
1186
dbus_message_iter_append_basic(&entry, DBUS_TYPE_BOOLEAN,
1189
dbus_message_iter_close_container(iter, &entry);
1192
void supplicant_set_debug_show_timestamps(dbus_bool_t enabled)
1194
supplicant_dbus_property_set(SUPPLICANT_PATH, SUPPLICANT_INTERFACE,
1195
"DebugParams", "(ibb)", add_show_timestamps,
1196
NULL, GUINT_TO_POINTER(enabled));