~shakaran/ubuntu/quantal/connman/bug-pattern-update

« back to all changes in this revision

Viewing changes to tools/supplicant.c

  • Committer: Bazaar Package Importer
  • Author(s): Mathieu Trudel
  • Date: 2010-02-12 10:08:03 UTC
  • mfrom: (1.1.8 upstream) (0.1.5 sid)
  • Revision ID: james.westby@ubuntu.com-20100212100803-s8iaj8g1dmgwm2uz
Tags: 0.48+dfsg-2
* Ubuntu/Debian sync upload
* Re-add missing changes from 0.45+dfsg that made it only in Ubuntu:
  - ship development parts in a connman-dev package (Closes: 546616)
    - add debian/connman-dev.install
    - update debian/control
* Update long descriptions for connman and connman-dev
  - update debian/control
* Add missing Depends on libglib2.0-dev, libdbus-1-dev for connman-dev
  - update debian/control
* Don't run bootstrap twice during build.
  - update debian/rules
* Remove old configure option: enable-ppp, with-pppd, enable-novatel,
  enable-huawei and enable-modemmgr are no longer recognized.
  - update debian/rules

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *
 
3
 *  Connection Manager
 
4
 *
 
5
 *  Copyright (C) 2007-2009  Intel Corporation. All rights reserved.
 
6
 *
 
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.
 
10
 *
 
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.
 
15
 *
 
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
 
19
 *
 
20
 */
 
21
 
 
22
#ifdef HAVE_CONFIG_H
 
23
#include <config.h>
 
24
#endif
 
25
 
 
26
#include <errno.h>
 
27
#include <string.h>
 
28
#include <stdint.h>
 
29
#include <syslog.h>
 
30
 
 
31
#include <glib.h>
 
32
#include <gdbus.h>
 
33
 
 
34
#include "supplicant-dbus.h"
 
35
#include "supplicant.h"
 
36
 
 
37
#define DBG(fmt, arg...) do { \
 
38
        syslog(LOG_DEBUG, "%s() " fmt, __FUNCTION__ , ## arg); \
 
39
} while (0)
 
40
 
 
41
#define TIMEOUT 5000
 
42
 
 
43
#define IEEE80211_CAP_ESS       0x0001
 
44
#define IEEE80211_CAP_IBSS      0x0002
 
45
#define IEEE80211_CAP_PRIVACY   0x0010
 
46
 
 
47
static DBusConnection *connection;
 
48
 
 
49
static const struct supplicant_callbacks *callbacks_pointer;
 
50
 
 
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;
 
54
 
 
55
static unsigned int eap_methods;
 
56
 
 
57
struct strvalmap {
 
58
        const char *str;
 
59
        unsigned int val;
 
60
};
 
61
 
 
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      },
 
71
        { }
 
72
};
 
73
 
 
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         },
 
78
        { }
 
79
};
 
80
 
 
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         },
 
85
        { }
 
86
};
 
87
 
 
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           },
 
92
        { }
 
93
};
 
94
 
 
95
static GHashTable *interface_table;
 
96
 
 
97
struct supplicant_interface {
 
98
        char *path;
 
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;
 
104
        int apscan;
 
105
        char *ifname;
 
106
        char *driver;
 
107
        char *bridge;
 
108
        GHashTable *network_table;
 
109
        GHashTable *bss_mapping;
 
110
};
 
111
 
 
112
struct supplicant_network {
 
113
        struct supplicant_interface *interface;
 
114
        char *group;
 
115
        char *name;
 
116
        enum supplicant_mode mode;
 
117
        GHashTable *bss_table;
 
118
};
 
119
 
 
120
struct supplicant_bss {
 
121
        struct supplicant_interface *interface;
 
122
        char *path;
 
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;
 
129
        dbus_bool_t privacy;
 
130
        dbus_bool_t psk;
 
131
        dbus_bool_t ieee8021x;
 
132
};
 
133
 
 
134
static const char *mode2string(enum supplicant_mode mode)
 
135
{
 
136
        switch (mode) {
 
137
        case SUPPLICANT_MODE_UNKNOWN:
 
138
                break;
 
139
        case SUPPLICANT_MODE_INFRA:
 
140
                return "managed";
 
141
        case SUPPLICANT_MODE_IBSS:
 
142
                return "adhoc";
 
143
        }
 
144
 
 
145
        return NULL;
 
146
}
 
147
 
 
148
static const char *security2string(enum supplicant_security security)
 
149
{
 
150
        switch (security) {
 
151
        case SUPPLICANT_SECURITY_UNKNOWN:
 
152
                break;
 
153
        case SUPPLICANT_SECURITY_NONE:
 
154
                return "none";
 
155
        case SUPPLICANT_SECURITY_WEP:
 
156
                return "wep";
 
157
        case SUPPLICANT_SECURITY_PSK:
 
158
                return "psk";
 
159
        case SUPPLICANT_SECURITY_IEEE8021X:
 
160
                return "ieee8021x";
 
161
        }
 
162
 
 
163
        return NULL;
 
164
}
 
165
 
 
166
static enum supplicant_state string2state(const char *state)
 
167
{
 
168
        if (state == NULL)
 
169
                return SUPPLICANT_STATE_UNKNOWN;
 
170
 
 
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;
 
191
 
 
192
        return SUPPLICANT_STATE_UNKNOWN;
 
193
}
 
194
 
 
195
static void callback_interface_added(struct supplicant_interface *interface)
 
196
{
 
197
        if (callbacks_pointer == NULL)
 
198
                return;
 
199
 
 
200
        if (callbacks_pointer->interface_added == NULL)
 
201
                return;
 
202
 
 
203
        callbacks_pointer->interface_added(interface);
 
204
}
 
205
 
 
206
static void callback_interface_removed(struct supplicant_interface *interface)
 
207
{
 
208
        if (callbacks_pointer == NULL)
 
209
                return;
 
210
 
 
211
        if (callbacks_pointer->interface_removed == NULL)
 
212
                return;
 
213
 
 
214
        callbacks_pointer->interface_removed(interface);
 
215
}
 
216
 
 
217
static void callback_network_added(struct supplicant_network *network)
 
218
{
 
219
        if (callbacks_pointer == NULL)
 
220
                return;
 
221
 
 
222
        if (callbacks_pointer->network_added == NULL)
 
223
                return;
 
224
 
 
225
        callbacks_pointer->network_added(network);
 
226
}
 
227
 
 
228
static void callback_network_removed(struct supplicant_network *network)
 
229
{
 
230
        if (callbacks_pointer == NULL)
 
231
                return;
 
232
 
 
233
        if (callbacks_pointer->network_removed == NULL)
 
234
                return;
 
235
 
 
236
        callbacks_pointer->network_removed(network);
 
237
}
 
238
 
 
239
static void remove_interface(gpointer data)
 
240
{
 
241
        struct supplicant_interface *interface = data;
 
242
 
 
243
        callback_interface_removed(interface);
 
244
 
 
245
        g_hash_table_destroy(interface->bss_mapping);
 
246
        g_hash_table_destroy(interface->network_table);
 
247
 
 
248
        g_free(interface->path);
 
249
        g_free(interface->ifname);
 
250
        g_free(interface->driver);
 
251
        g_free(interface->bridge);
 
252
        g_free(interface);
 
253
}
 
254
 
 
255
static void remove_network(gpointer data)
 
256
{
 
257
        struct supplicant_network *network = data;
 
258
 
 
259
        callback_network_removed(network);
 
260
 
 
261
        g_free(network->group);
 
262
        g_free(network->name);
 
263
        g_free(network);
 
264
}
 
265
 
 
266
static void remove_bss(gpointer data)
 
267
{
 
268
        struct supplicant_bss *bss = data;
 
269
 
 
270
        g_free(bss->path);
 
271
        g_free(bss);
 
272
}
 
273
 
 
274
static void debug_strvalmap(const char *label, struct strvalmap *map,
 
275
                                                        unsigned int val)
 
276
{
 
277
        int i;
 
278
 
 
279
        for (i = 0; map[i].str != NULL; i++) {
 
280
                if (val & map[i].val)
 
281
                        DBG("%s: %s", label, map[i].str);
 
282
        }
 
283
}
 
284
 
 
285
static void interface_capability_auth(DBusMessageIter *iter, void *user_data)
 
286
{
 
287
        struct supplicant_interface *interface = user_data;
 
288
        const char *str = NULL;
 
289
        int i;
 
290
 
 
291
        dbus_message_iter_get_basic(iter, &str);
 
292
        if (str == NULL)
 
293
                return;
 
294
 
 
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;
 
298
                        break;
 
299
                }
 
300
}
 
301
 
 
302
static void interface_capability_scan(DBusMessageIter *iter, void *user_data)
 
303
{
 
304
        struct supplicant_interface *interface = user_data;
 
305
        const char *str = NULL;
 
306
        int i;
 
307
 
 
308
        dbus_message_iter_get_basic(iter, &str);
 
309
        if (str == NULL)
 
310
                return;
 
311
 
 
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;
 
315
                        break;
 
316
                }
 
317
}
 
318
 
 
319
static void interface_capability_mode(DBusMessageIter *iter, void *user_data)
 
320
{
 
321
        struct supplicant_interface *interface = user_data;
 
322
        const char *str = NULL;
 
323
        int i;
 
324
 
 
325
        dbus_message_iter_get_basic(iter, &str);
 
326
        if (str == NULL)
 
327
                return;
 
328
 
 
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;
 
332
                        break;
 
333
                }
 
334
}
 
335
 
 
336
static void interface_capability(const char *key, DBusMessageIter *iter,
 
337
                                                        void *user_data)
 
338
{
 
339
        struct supplicant_interface *interface = user_data;
 
340
 
 
341
        if (key == NULL)
 
342
                return;
 
343
 
 
344
        if (g_strcmp0(key, "AuthAlg") == 0)
 
345
                supplicant_dbus_array_foreach(iter, interface_capability_auth,
 
346
                                                                interface);
 
347
        else if (g_strcmp0(key, "Scan") == 0)
 
348
                supplicant_dbus_array_foreach(iter, interface_capability_scan,
 
349
                                                                interface);
 
350
        else if (g_strcmp0(key, "Modes") == 0)
 
351
                supplicant_dbus_array_foreach(iter, interface_capability_mode,
 
352
                                                                interface);
 
353
        else
 
354
                DBG("key %s type %c",
 
355
                                key, dbus_message_iter_get_arg_type(iter));
 
356
}
 
357
 
 
358
const char *supplicant_interface_get_ifname(struct supplicant_interface *interface)
 
359
{
 
360
        if (interface == NULL)
 
361
                return NULL;
 
362
 
 
363
        return interface->ifname;
 
364
}
 
365
 
 
366
struct supplicant_interface *supplicant_network_get_interface(struct supplicant_network *network)
 
367
{
 
368
        if (network == NULL)
 
369
                return NULL;
 
370
 
 
371
        return network->interface;
 
372
}
 
373
 
 
374
const char *supplicant_network_get_name(struct supplicant_network *network)
 
375
{
 
376
        if (network == NULL || network->name == NULL)
 
377
                return "";
 
378
 
 
379
        return network->name;
 
380
}
 
381
 
 
382
const char *supplicant_network_get_identifier(struct supplicant_network *network)
 
383
{
 
384
        if (network == NULL || network->group == NULL)
 
385
                return "";
 
386
 
 
387
        return network->group;
 
388
}
 
389
 
 
390
enum supplicant_mode supplicant_network_get_mode(struct supplicant_network *network)
 
391
{
 
392
        if (network == NULL)
 
393
                return SUPPLICANT_MODE_UNKNOWN;
 
394
 
 
395
        return network->mode;
 
396
}
 
397
 
 
398
static void network_property(const char *key, DBusMessageIter *iter,
 
399
                                                        void *user_data)
 
400
{
 
401
        if (key == NULL)
 
402
                return;
 
403
 
 
404
        DBG("key %s type %c", key, dbus_message_iter_get_arg_type(iter));
 
405
}
 
406
 
 
407
static void interface_network_added(DBusMessageIter *iter, void *user_data)
 
408
{
 
409
        const char *path = NULL;
 
410
 
 
411
        dbus_message_iter_get_basic(iter, &path);
 
412
        if (path == NULL)
 
413
                return;
 
414
 
 
415
        DBG("path %s", path);
 
416
 
 
417
        supplicant_dbus_property_get_all(path,
 
418
                                SUPPLICANT_INTERFACE ".Interface.Network",
 
419
                                                network_property, NULL);
 
420
}
 
421
 
 
422
static void interface_network_removed(DBusMessageIter *iter, void *user_data)
 
423
{
 
424
        const char *path = NULL;
 
425
 
 
426
        dbus_message_iter_get_basic(iter, &path);
 
427
        if (path == NULL)
 
428
                return;
 
429
 
 
430
        DBG("path %s", path);
 
431
}
 
432
 
 
433
static char *create_name(unsigned char *ssid, int ssid_len)
 
434
{
 
435
        char *name;
 
436
        int i;
 
437
 
 
438
        if (ssid_len < 1 || ssid[0] == '\0')
 
439
                name = NULL;
 
440
        else
 
441
                name = g_try_malloc0(ssid_len + 1);
 
442
 
 
443
        if (name == NULL)
 
444
                return g_strdup("");
 
445
 
 
446
        for (i = 0; i < ssid_len; i++) {
 
447
                if (g_ascii_isprint(ssid[i]))
 
448
                        name[i] = ssid[i];
 
449
                else
 
450
                        name[i] = ' ';
 
451
        }
 
452
 
 
453
        return name;
 
454
}
 
455
 
 
456
static char *create_group(struct supplicant_bss *bss)
 
457
{
 
458
        GString *str;
 
459
        unsigned int i;
 
460
        const char *mode, *security;
 
461
 
 
462
        str = g_string_sized_new((bss->ssid_len * 2) + 24);
 
463
        if (str == NULL)
 
464
                return NULL;
 
465
 
 
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]);
 
469
        } else
 
470
                g_string_append_printf(str, "hidden");
 
471
 
 
472
        mode = mode2string(bss->mode);
 
473
        if (mode != NULL)
 
474
                g_string_append_printf(str, "_%s", mode);
 
475
 
 
476
        security = security2string(bss->security);
 
477
        if (security != NULL)
 
478
                g_string_append_printf(str, "_%s", security);
 
479
 
 
480
        return g_string_free(str, FALSE);
 
481
}
 
482
 
 
483
static void add_bss_to_network(struct supplicant_bss *bss)
 
484
{
 
485
        struct supplicant_interface *interface = bss->interface;
 
486
        struct supplicant_network *network;
 
487
        char *group;
 
488
 
 
489
        group = create_group(bss);
 
490
        if (group == NULL)
 
491
                return;
 
492
 
 
493
        network = g_hash_table_lookup(interface->network_table, group);
 
494
        if (network != NULL) {
 
495
                g_free(group);
 
496
                goto done;
 
497
        }
 
498
 
 
499
        network = g_try_new0(struct supplicant_network, 1);
 
500
        if (network == NULL) {
 
501
                g_free(group);
 
502
                return;
 
503
        }
 
504
 
 
505
        network->group = group;
 
506
        network->name = create_name(bss->ssid, bss->ssid_len);
 
507
        network->mode = bss->mode;
 
508
 
 
509
        network->bss_table = g_hash_table_new_full(g_str_hash, g_str_equal,
 
510
                                                        NULL, remove_bss);
 
511
 
 
512
        g_hash_table_replace(interface->network_table,
 
513
                                                network->group, network);
 
514
 
 
515
        callback_network_added(network);
 
516
 
 
517
done:
 
518
        g_hash_table_replace(interface->bss_mapping, bss->path, network);
 
519
        g_hash_table_replace(network->bss_table, bss->path, bss);
 
520
}
 
521
 
 
522
static unsigned char wifi_oui[3]      = { 0x00, 0x50, 0xf2 };
 
523
static unsigned char ieee80211_oui[3] = { 0x00, 0x0f, 0xac };
 
524
 
 
525
static void extract_rsn(struct supplicant_bss *bss,
 
526
                                        const unsigned char *buf, int len)
 
527
{
 
528
        uint16_t count;
 
529
        int i;
 
530
 
 
531
        /* Version */
 
532
        if (len < 2)
 
533
                return;
 
534
 
 
535
        buf += 2;
 
536
        len -= 2;
 
537
 
 
538
        /* Group cipher */
 
539
        if (len < 4)
 
540
                return;
 
541
 
 
542
        buf += 4;
 
543
        len -= 4;
 
544
 
 
545
        /* Pairwise cipher */
 
546
        if (len < 2)
 
547
                return;
 
548
 
 
549
        count = buf[0] | (buf[1] << 8);
 
550
        if (2 + (count * 4) > len)
 
551
                return;
 
552
 
 
553
        buf += 2 + (count * 4);
 
554
        len -= 2 + (count * 4);
 
555
 
 
556
        /* Authentication */
 
557
        if (len < 2)
 
558
                return;
 
559
 
 
560
        count = buf[0] | (buf[1] << 8);
 
561
        if (2 + (count * 4) > len)
 
562
                return;
 
563
 
 
564
        for (i = 0; i < count; i++) {
 
565
                const unsigned char *ptr = buf + 2 + (i * 4);
 
566
 
 
567
                if (memcmp(ptr, wifi_oui, 3) == 0) {
 
568
                        switch (ptr[3]) {
 
569
                        case 1:
 
570
                                bss->ieee8021x = TRUE;
 
571
                                break;
 
572
                        case 2:
 
573
                                bss->psk = TRUE;
 
574
                                break;
 
575
                        }
 
576
                } else if (memcmp(ptr, ieee80211_oui, 3) == 0) {
 
577
                        switch (ptr[3]) {
 
578
                        case 1:
 
579
                                bss->ieee8021x = TRUE;
 
580
                                break;
 
581
                        case 2:
 
582
                                bss->psk = TRUE;
 
583
                                break;
 
584
                        }
 
585
                }
 
586
        }
 
587
 
 
588
        buf += 2 + (count * 4);
 
589
        len -= 2 + (count * 4);
 
590
}
 
591
 
 
592
static void bss_property(const char *key, DBusMessageIter *iter,
 
593
                                                        void *user_data)
 
594
{
 
595
        struct supplicant_bss *bss = user_data;
 
596
 
 
597
        if (bss->interface == NULL)
 
598
                return;
 
599
 
 
600
        if (key == 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;
 
607
                else
 
608
                        bss->security = SUPPLICANT_SECURITY_NONE;
 
609
 
 
610
                add_bss_to_network(bss);
 
611
                return;
 
612
        }
 
613
 
 
614
        if (g_strcmp0(key, "BSSID") == 0) {
 
615
                DBusMessageIter array;
 
616
                unsigned char *addr;
 
617
                int addr_len;
 
618
 
 
619
                dbus_message_iter_recurse(iter, &array);
 
620
                dbus_message_iter_get_fixed_array(&array, &addr, &addr_len);
 
621
 
 
622
                if (addr_len == 6)
 
623
                        memcpy(bss->bssid, addr, addr_len);
 
624
        } else if (g_strcmp0(key, "SSID") == 0) {
 
625
                DBusMessageIter array;
 
626
                unsigned char *ssid;
 
627
                int ssid_len;
 
628
 
 
629
                dbus_message_iter_recurse(iter, &array);
 
630
                dbus_message_iter_get_fixed_array(&array, &ssid, &ssid_len);
 
631
 
 
632
                if (ssid_len > 0 && ssid_len < 33) {
 
633
                        memcpy(bss->ssid, ssid, ssid_len);
 
634
                        bss->ssid_len = ssid_len;
 
635
                } else {
 
636
                        memset(bss->ssid, 0, sizeof(bss->ssid));
 
637
                        bss->ssid_len = 0;
 
638
                }
 
639
        } else if (g_strcmp0(key, "Capabilities") == 0) {
 
640
                dbus_uint16_t capabilities = 0x0000;
 
641
 
 
642
                dbus_message_iter_get_basic(iter, &capabilities);
 
643
 
 
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;
 
648
 
 
649
                if (capabilities & IEEE80211_CAP_PRIVACY)
 
650
                        bss->privacy = TRUE;
 
651
        } else if (g_strcmp0(key, "Frequency") == 0) {
 
652
                dbus_int32_t frequency = 0;
 
653
 
 
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;
 
658
 
 
659
                dbus_message_iter_get_basic(iter, &level);
 
660
        } else if (g_strcmp0(key, "MaxRate") == 0) {
 
661
                dbus_int32_t maxrate = 0;
 
662
 
 
663
                dbus_message_iter_get_basic(iter, &maxrate);
 
664
        } else if (g_strcmp0(key, "RSNIE") == 0) {
 
665
                DBusMessageIter array;
 
666
                unsigned char *ie;
 
667
                int ie_len;
 
668
 
 
669
                dbus_message_iter_recurse(iter, &array);
 
670
                dbus_message_iter_get_fixed_array(&array, &ie, &ie_len);
 
671
 
 
672
                if (ie_len > 2)
 
673
                        extract_rsn(bss, ie + 2, ie_len - 2);
 
674
        } else if (g_strcmp0(key, "WPAIE") == 0) {
 
675
                DBusMessageIter array;
 
676
                unsigned char *ie;
 
677
                int ie_len;
 
678
 
 
679
                dbus_message_iter_recurse(iter, &array);
 
680
                dbus_message_iter_get_fixed_array(&array, &ie, &ie_len);
 
681
 
 
682
                if (ie_len > 6)
 
683
                        extract_rsn(bss, ie + 6, ie_len - 6);
 
684
        } else if (g_strcmp0(key, "WPSIE") == 0) {
 
685
                DBusMessageIter array;
 
686
                unsigned char *ie;
 
687
                int ie_len;
 
688
 
 
689
                dbus_message_iter_recurse(iter, &array);
 
690
                dbus_message_iter_get_fixed_array(&array, &ie, &ie_len);
 
691
        } else
 
692
                DBG("key %s type %c",
 
693
                                key, dbus_message_iter_get_arg_type(iter));
 
694
}
 
695
 
 
696
static void interface_bss_added(DBusMessageIter *iter, void *user_data)
 
697
{
 
698
        struct supplicant_interface *interface = user_data;
 
699
        struct supplicant_network *network;
 
700
        struct supplicant_bss *bss;
 
701
        const char *path = NULL;
 
702
 
 
703
        dbus_message_iter_get_basic(iter, &path);
 
704
        if (path == NULL)
 
705
                return;
 
706
 
 
707
        network = g_hash_table_lookup(interface->bss_mapping, path);
 
708
        if (network != NULL) {
 
709
                bss = g_hash_table_lookup(network->bss_table, path);
 
710
                if (bss != NULL)
 
711
                        return;
 
712
        }
 
713
 
 
714
        bss = g_try_new0(struct supplicant_bss, 1);
 
715
        if (bss == NULL)
 
716
                return;
 
717
 
 
718
        bss->interface = interface;
 
719
        bss->path = g_strdup(path);
 
720
 
 
721
        supplicant_dbus_property_get_all(path,
 
722
                                        SUPPLICANT_INTERFACE ".Interface.BSS",
 
723
                                                        bss_property, bss);
 
724
}
 
725
 
 
726
static void interface_bss_removed(DBusMessageIter *iter, void *user_data)
 
727
{
 
728
        struct supplicant_interface *interface = user_data;
 
729
        struct supplicant_network *network;
 
730
        const char *path = NULL;
 
731
 
 
732
        dbus_message_iter_get_basic(iter, &path);
 
733
        if (path == NULL)
 
734
                return;
 
735
 
 
736
        network = g_hash_table_lookup(interface->bss_mapping, path);
 
737
        if (network == NULL)
 
738
                return;
 
739
 
 
740
        g_hash_table_remove(interface->bss_mapping, path);
 
741
        g_hash_table_remove(network->bss_table, path);
 
742
 
 
743
        if (g_hash_table_size(network->bss_table) == 0)
 
744
                g_hash_table_remove(interface->network_table, network->group);
 
745
}
 
746
 
 
747
static void interface_property(const char *key, DBusMessageIter *iter,
 
748
                                                        void *user_data)
 
749
{
 
750
        struct supplicant_interface *interface = user_data;
 
751
 
 
752
        if (interface == NULL)
 
753
                return;
 
754
 
 
755
        if (key == 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);
 
762
 
 
763
                g_hash_table_replace(interface_table,
 
764
                                        interface->path, interface);
 
765
 
 
766
                callback_interface_added(interface);
 
767
                return;
 
768
        }
 
769
 
 
770
        if (g_strcmp0(key, "Capabilities") == 0) {
 
771
                supplicant_dbus_property_foreach(iter, interface_capability,
 
772
                                                                interface);
 
773
        } else if (g_strcmp0(key, "State") == 0) {
 
774
                const char *str = NULL;
 
775
 
 
776
                dbus_message_iter_get_basic(iter, &str);
 
777
                if (str != NULL)
 
778
                        interface->state = string2state(str);
 
779
        } else if (g_strcmp0(key, "Scanning") == 0) {
 
780
                dbus_bool_t scanning = FALSE;
 
781
 
 
782
                dbus_message_iter_get_basic(iter, &scanning);
 
783
                interface->scanning = scanning;
 
784
        } else if (g_strcmp0(key, "ApScan") == 0) {
 
785
                int apscan;
 
786
 
 
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;
 
791
 
 
792
                dbus_message_iter_get_basic(iter, &str);
 
793
                if (str != NULL)
 
794
                        interface->ifname = g_strdup(str);
 
795
        } else if (g_strcmp0(key, "Driver") == 0) {
 
796
                const char *str = NULL;
 
797
 
 
798
                dbus_message_iter_get_basic(iter, &str);
 
799
                if (str != NULL)
 
800
                        interface->driver = g_strdup(str);
 
801
        } else if (g_strcmp0(key, "BridgeIfname") == 0) {
 
802
                const char *str = NULL;
 
803
 
 
804
                dbus_message_iter_get_basic(iter, &str);
 
805
                if (str != NULL)
 
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,
 
813
                                                                interface);
 
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,
 
817
                                                                interface);
 
818
        } else
 
819
                DBG("key %s type %c",
 
820
                                key, dbus_message_iter_get_arg_type(iter));
 
821
}
 
822
 
 
823
static void interface_added(DBusMessageIter *iter, void *user_data)
 
824
{
 
825
        struct supplicant_interface *interface;
 
826
        const char *path = NULL;
 
827
 
 
828
        dbus_message_iter_get_basic(iter, &path);
 
829
        if (path == NULL)
 
830
                return;
 
831
 
 
832
        interface = g_hash_table_lookup(interface_table, path);
 
833
        if (interface != NULL)
 
834
                return;
 
835
 
 
836
        interface = g_try_new0(struct supplicant_interface, 1);
 
837
        if (interface == NULL)
 
838
                return;
 
839
 
 
840
        interface->path = g_strdup(path);
 
841
 
 
842
        interface->network_table = g_hash_table_new_full(g_str_hash, g_str_equal,
 
843
                                                        NULL, remove_network);
 
844
 
 
845
        interface->bss_mapping = g_hash_table_new_full(g_str_hash, g_str_equal,
 
846
                                                                NULL, NULL);
 
847
 
 
848
        supplicant_dbus_property_get_all(path,
 
849
                                        SUPPLICANT_INTERFACE ".Interface",
 
850
                                                interface_property, interface);
 
851
}
 
852
 
 
853
static void interface_removed(DBusMessageIter *iter, void *user_data)
 
854
{
 
855
        const char *path = NULL;
 
856
 
 
857
        dbus_message_iter_get_basic(iter, &path);
 
858
        if (path == NULL)
 
859
                return;
 
860
 
 
861
        g_hash_table_remove(interface_table, path);
 
862
}
 
863
 
 
864
static void eap_method(DBusMessageIter *iter, void *user_data)
 
865
{
 
866
        const char *str = NULL;
 
867
        int i;
 
868
 
 
869
        dbus_message_iter_get_basic(iter, &str);
 
870
        if (str == NULL)
 
871
                return;
 
872
 
 
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;
 
876
                        break;
 
877
                }
 
878
}
 
879
 
 
880
static void service_property(const char *key, DBusMessageIter *iter,
 
881
                                                        void *user_data)
 
882
{
 
883
        if (key == NULL)
 
884
                return;
 
885
 
 
886
        if (g_strcmp0(key, "DebugParams") == 0) {
 
887
                DBusMessageIter list;
 
888
 
 
889
                dbus_message_iter_recurse(iter, &list);
 
890
                dbus_message_iter_get_basic(&list, &debug_level);
 
891
 
 
892
                dbus_message_iter_next(&list);
 
893
                dbus_message_iter_get_basic(&list, &debug_show_timestamps);
 
894
 
 
895
                dbus_message_iter_next(&list);
 
896
                dbus_message_iter_get_basic(&list, &debug_show_keys);
 
897
 
 
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);
 
905
        }
 
906
}
 
907
 
 
908
static void supplicant_bootstrap(void)
 
909
{
 
910
        supplicant_dbus_property_get_all(SUPPLICANT_PATH,
 
911
                                                SUPPLICANT_INTERFACE,
 
912
                                                service_property, NULL);
 
913
}
 
914
 
 
915
static void signal_name_owner_changed(const char *path, DBusMessageIter *iter)
 
916
{
 
917
        const char *name = NULL, *old = NULL, *new = NULL;
 
918
 
 
919
        if (g_strcmp0(path, DBUS_PATH_DBUS) != 0)
 
920
                return;
 
921
 
 
922
        dbus_message_iter_get_basic(iter, &name);
 
923
        if (name == NULL)
 
924
                return;
 
925
 
 
926
        if (g_strcmp0(name, SUPPLICANT_SERVICE) != 0)
 
927
                return;
 
928
 
 
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);
 
933
 
 
934
        if (old == NULL || new == NULL)
 
935
                return;
 
936
 
 
937
        if (strlen(old) > 0 && strlen(new) == 0)
 
938
                g_hash_table_remove_all(interface_table);
 
939
 
 
940
        if (strlen(new) > 0 && strlen(old) == 0)
 
941
                supplicant_bootstrap();
 
942
}
 
943
 
 
944
static void signal_properties_changed(const char *path, DBusMessageIter *iter)
 
945
{
 
946
        if (g_strcmp0(path, SUPPLICANT_PATH) != 0)
 
947
                return;
 
948
 
 
949
        supplicant_dbus_property_foreach(iter, service_property, NULL);
 
950
}
 
951
 
 
952
static void signal_interface_added(const char *path, DBusMessageIter *iter)
 
953
{
 
954
        if (g_strcmp0(path, SUPPLICANT_PATH) == 0)
 
955
                interface_added(iter, NULL);
 
956
}
 
957
 
 
958
static void signal_interface_removed(const char *path, DBusMessageIter *iter)
 
959
{
 
960
        if (g_strcmp0(path, SUPPLICANT_PATH) == 0)
 
961
                interface_removed(iter, NULL);
 
962
}
 
963
 
 
964
static void signal_bss_added(const char *path, DBusMessageIter *iter)
 
965
{
 
966
        struct supplicant_interface *interface;
 
967
 
 
968
        interface = g_hash_table_lookup(interface_table, path);
 
969
        if (interface == NULL)
 
970
                return;
 
971
 
 
972
        interface_bss_added(iter, interface);
 
973
}
 
974
 
 
975
static void signal_bss_removed(const char *path, DBusMessageIter *iter)
 
976
{
 
977
        struct supplicant_interface *interface;
 
978
 
 
979
        interface = g_hash_table_lookup(interface_table, path);
 
980
        if (interface == NULL)
 
981
                return;
 
982
 
 
983
        interface_bss_removed(iter, interface);
 
984
}
 
985
 
 
986
static void signal_network_added(const char *path, DBusMessageIter *iter)
 
987
{
 
988
        struct supplicant_interface *interface;
 
989
 
 
990
        interface = g_hash_table_lookup(interface_table, path);
 
991
        if (interface == NULL)
 
992
                return;
 
993
 
 
994
        interface_network_added(iter, interface);
 
995
}
 
996
 
 
997
static void signal_network_removed(const char *path, DBusMessageIter *iter)
 
998
{
 
999
        struct supplicant_interface *interface;
 
1000
 
 
1001
        interface = g_hash_table_lookup(interface_table, path);
 
1002
        if (interface == NULL)
 
1003
                return;
 
1004
 
 
1005
        interface_network_removed(iter, interface);
 
1006
}
 
1007
 
 
1008
static struct {
 
1009
        const char *interface;
 
1010
        const char *member;
 
1011
        void (*function) (const char *path, DBusMessageIter *iter);
 
1012
} signal_map[] = {
 
1013
        { DBUS_INTERFACE_DBUS,  "NameOwnerChanged",  signal_name_owner_changed },
 
1014
 
 
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  },
 
1019
 
 
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 },
 
1024
 
 
1025
        { }
 
1026
};
 
1027
 
 
1028
static DBusHandlerResult supplicant_filter(DBusConnection *conn,
 
1029
                                        DBusMessage *message, void *data)
 
1030
{
 
1031
        DBusMessageIter iter;
 
1032
        const char *path;
 
1033
        int i;
 
1034
 
 
1035
        path = dbus_message_get_path(message);
 
1036
        if (path == NULL)
 
1037
                return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
 
1038
 
 
1039
        if (dbus_message_iter_init(message, &iter) == FALSE)
 
1040
                return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
 
1041
 
 
1042
        for (i = 0; signal_map[i].interface != NULL; i++) {
 
1043
                if (dbus_message_has_interface(message,
 
1044
                                        signal_map[i].interface) == FALSE)
 
1045
                        continue;
 
1046
 
 
1047
                if (dbus_message_has_member(message,
 
1048
                                        signal_map[i].member) == FALSE)
 
1049
                        continue;
 
1050
 
 
1051
                signal_map[i].function(path, &iter);
 
1052
                break;
 
1053
        }
 
1054
 
 
1055
        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
 
1056
}
 
1057
 
 
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";
 
1076
 
 
1077
int supplicant_register(const struct supplicant_callbacks *callbacks)
 
1078
{
 
1079
        connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
 
1080
        if (connection == NULL)
 
1081
                return -EIO;
 
1082
 
 
1083
        if (dbus_connection_add_filter(connection,
 
1084
                                supplicant_filter, NULL, NULL) == FALSE) {
 
1085
                dbus_connection_unref(connection);
 
1086
                connection = NULL;
 
1087
                return -EIO;
 
1088
        }
 
1089
 
 
1090
        callbacks_pointer = callbacks;
 
1091
        eap_methods = 0;
 
1092
 
 
1093
        interface_table = g_hash_table_new_full(g_str_hash, g_str_equal,
 
1094
                                                NULL, remove_interface);
 
1095
 
 
1096
        supplicant_dbus_setup(connection);
 
1097
 
 
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);
 
1106
 
 
1107
        if (dbus_bus_name_has_owner(connection,
 
1108
                                        SUPPLICANT_SERVICE, NULL) == TRUE)
 
1109
                supplicant_bootstrap();
 
1110
 
 
1111
        return 0;
 
1112
}
 
1113
 
 
1114
void supplicant_unregister(const struct supplicant_callbacks *callbacks)
 
1115
{
 
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);
 
1125
 
 
1126
                dbus_connection_remove_filter(connection,
 
1127
                                                supplicant_filter, NULL);
 
1128
        }
 
1129
 
 
1130
        if (interface_table != NULL) {
 
1131
                g_hash_table_destroy(interface_table);
 
1132
                interface_table = NULL;
 
1133
        }
 
1134
 
 
1135
        if (connection != NULL) {
 
1136
                dbus_connection_unref(connection);
 
1137
                connection = NULL;
 
1138
        }
 
1139
 
 
1140
        callbacks_pointer = NULL;
 
1141
        eap_methods = 0;
 
1142
}
 
1143
 
 
1144
static void debug_level_result(const char *error,
 
1145
                                DBusMessageIter *iter, void *user_data)
 
1146
{
 
1147
        if (error != NULL)
 
1148
                DBG("debug level failure: %s", error);
 
1149
}
 
1150
 
 
1151
static void add_debug_level(DBusMessageIter *iter, void *user_data)
 
1152
{
 
1153
        dbus_int32_t level = GPOINTER_TO_UINT(user_data);
 
1154
        DBusMessageIter entry;
 
1155
 
 
1156
        dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT,
 
1157
                                                        NULL, &entry);
 
1158
 
 
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,
 
1163
                                                &debug_show_keys);
 
1164
 
 
1165
        dbus_message_iter_close_container(iter, &entry);
 
1166
}
 
1167
 
 
1168
void supplicant_set_debug_level(unsigned int level)
 
1169
{
 
1170
        supplicant_dbus_property_set(SUPPLICANT_PATH, SUPPLICANT_INTERFACE,
 
1171
                                "DebugParams", "(ibb)", add_debug_level,
 
1172
                                debug_level_result, GUINT_TO_POINTER(level));
 
1173
}
 
1174
 
 
1175
static void add_show_timestamps(DBusMessageIter *iter, void *user_data)
 
1176
{
 
1177
        dbus_bool_t show_timestamps = GPOINTER_TO_UINT(user_data);
 
1178
        DBusMessageIter entry;
 
1179
 
 
1180
        dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT,
 
1181
                                                        NULL, &entry);
 
1182
 
 
1183
        dbus_message_iter_append_basic(&entry, DBUS_TYPE_INT32, &debug_level);
 
1184
        dbus_message_iter_append_basic(&entry, DBUS_TYPE_BOOLEAN,
 
1185
                                                        &show_timestamps);
 
1186
        dbus_message_iter_append_basic(&entry, DBUS_TYPE_BOOLEAN,
 
1187
                                                        &debug_show_keys);
 
1188
 
 
1189
        dbus_message_iter_close_container(iter, &entry);
 
1190
}
 
1191
 
 
1192
void supplicant_set_debug_show_timestamps(dbus_bool_t enabled)
 
1193
{
 
1194
        supplicant_dbus_property_set(SUPPLICANT_PATH, SUPPLICANT_INTERFACE,
 
1195
                                "DebugParams", "(ibb)", add_show_timestamps,
 
1196
                                        NULL, GUINT_TO_POINTER(enabled));
 
1197
}