~ubuntu-branches/ubuntu/saucy/wpasupplicant/saucy

« back to all changes in this revision

Viewing changes to wpa_supplicant/ctrl_iface_dbus.c

  • Committer: Bazaar Package Importer
  • Author(s): Mathieu Trudel-Lapierre
  • Date: 2010-11-22 09:43:43 UTC
  • mfrom: (1.1.16 upstream)
  • Revision ID: james.westby@ubuntu.com-20101122094343-qgsxaojvmswfri77
Tags: 0.7.3-0ubuntu1
* Get wpasupplicant 0.7.3 from Debian's SVN. Leaving 0.7.3-1 as unreleased
  for now.
* Build-Depend on debhelper 8, since the packaging from Debian uses compat 8.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * WPA Supplicant / dbus-based control interface
3
 
 * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
4
 
 *
5
 
 * This program is free software; you can redistribute it and/or modify
6
 
 * it under the terms of the GNU General Public License version 2 as
7
 
 * published by the Free Software Foundation.
8
 
 *
9
 
 * Alternatively, this software may be distributed under the terms of BSD
10
 
 * license.
11
 
 *
12
 
 * See README and COPYING for more details.
13
 
 */
14
 
 
15
 
#include "includes.h"
16
 
 
17
 
#include "common.h"
18
 
#include "eloop.h"
19
 
#include "config.h"
20
 
#include "wpa_supplicant_i.h"
21
 
#include "wps/wps.h"
22
 
#include "ctrl_iface_dbus.h"
23
 
#include "ctrl_iface_dbus_handlers.h"
24
 
 
25
 
#define _DBUS_VERSION (DBUS_VERSION_MAJOR << 8 | DBUS_VERSION_MINOR)
26
 
#define DBUS_VER(major, minor) ((major) << 8 | (minor))
27
 
 
28
 
#if _DBUS_VERSION < DBUS_VER(1,1)
29
 
#define dbus_watch_get_unix_fd dbus_watch_get_fd
30
 
#endif
31
 
 
32
 
 
33
 
struct ctrl_iface_dbus_priv {
34
 
        DBusConnection *con;
35
 
        int should_dispatch;
36
 
        struct wpa_global *global;
37
 
 
38
 
        u32 next_objid;
39
 
};
40
 
 
41
 
 
42
 
static void process_watch(struct ctrl_iface_dbus_priv *iface,
43
 
                          DBusWatch *watch, eloop_event_type type)
44
 
{
45
 
        dbus_connection_ref(iface->con);
46
 
 
47
 
        iface->should_dispatch = 0;
48
 
 
49
 
        if (type == EVENT_TYPE_READ)
50
 
                dbus_watch_handle(watch, DBUS_WATCH_READABLE);
51
 
        else if (type == EVENT_TYPE_WRITE)
52
 
                dbus_watch_handle(watch, DBUS_WATCH_WRITABLE);
53
 
        else if (type == EVENT_TYPE_EXCEPTION)
54
 
                dbus_watch_handle(watch, DBUS_WATCH_ERROR);
55
 
 
56
 
        if (iface->should_dispatch) {
57
 
                while (dbus_connection_get_dispatch_status(iface->con) ==
58
 
                       DBUS_DISPATCH_DATA_REMAINS)
59
 
                        dbus_connection_dispatch(iface->con);
60
 
                iface->should_dispatch = 0;
61
 
        }
62
 
 
63
 
        dbus_connection_unref(iface->con);
64
 
}
65
 
 
66
 
 
67
 
static void process_watch_exception(int sock, void *eloop_ctx, void *sock_ctx)
68
 
{
69
 
        process_watch(eloop_ctx, sock_ctx, EVENT_TYPE_EXCEPTION);
70
 
}
71
 
 
72
 
 
73
 
static void process_watch_read(int sock, void *eloop_ctx, void *sock_ctx)
74
 
{
75
 
        process_watch(eloop_ctx, sock_ctx, EVENT_TYPE_READ);
76
 
}
77
 
 
78
 
 
79
 
static void process_watch_write(int sock, void *eloop_ctx, void *sock_ctx)
80
 
{
81
 
        process_watch(eloop_ctx, sock_ctx, EVENT_TYPE_WRITE);
82
 
}
83
 
 
84
 
 
85
 
static void connection_setup_add_watch(struct ctrl_iface_dbus_priv *iface,
86
 
                                       DBusWatch *watch)
87
 
{
88
 
        unsigned int flags;
89
 
        int fd;
90
 
 
91
 
        if (!dbus_watch_get_enabled(watch))
92
 
                return;
93
 
 
94
 
        flags = dbus_watch_get_flags(watch);
95
 
        fd = dbus_watch_get_unix_fd(watch);
96
 
 
97
 
        eloop_register_sock(fd, EVENT_TYPE_EXCEPTION, process_watch_exception,
98
 
                            iface, watch);
99
 
 
100
 
        if (flags & DBUS_WATCH_READABLE) {
101
 
                eloop_register_sock(fd, EVENT_TYPE_READ, process_watch_read,
102
 
                                    iface, watch);
103
 
        }
104
 
        if (flags & DBUS_WATCH_WRITABLE) {
105
 
                eloop_register_sock(fd, EVENT_TYPE_WRITE, process_watch_write,
106
 
                                    iface, watch);
107
 
        }
108
 
 
109
 
        dbus_watch_set_data(watch, iface, NULL);
110
 
}
111
 
 
112
 
 
113
 
static void connection_setup_remove_watch(struct ctrl_iface_dbus_priv *iface,
114
 
                                          DBusWatch *watch)
115
 
{
116
 
        unsigned int flags;
117
 
        int fd;
118
 
 
119
 
        flags = dbus_watch_get_flags(watch);
120
 
        fd = dbus_watch_get_unix_fd(watch);
121
 
 
122
 
        eloop_unregister_sock(fd, EVENT_TYPE_EXCEPTION);
123
 
 
124
 
        if (flags & DBUS_WATCH_READABLE)
125
 
                eloop_unregister_sock(fd, EVENT_TYPE_READ);
126
 
        if (flags & DBUS_WATCH_WRITABLE)
127
 
                eloop_unregister_sock(fd, EVENT_TYPE_WRITE);
128
 
 
129
 
        dbus_watch_set_data(watch, NULL, NULL);
130
 
}
131
 
 
132
 
 
133
 
static dbus_bool_t add_watch(DBusWatch *watch, void *data)
134
 
{
135
 
        connection_setup_add_watch(data, watch);
136
 
        return TRUE;
137
 
}
138
 
 
139
 
 
140
 
static void remove_watch(DBusWatch *watch, void *data)
141
 
{
142
 
        connection_setup_remove_watch(data, watch);
143
 
}
144
 
 
145
 
 
146
 
static void watch_toggled(DBusWatch *watch, void *data)
147
 
{
148
 
        if (dbus_watch_get_enabled(watch))
149
 
                add_watch(watch, data);
150
 
        else
151
 
                remove_watch(watch, data);
152
 
}
153
 
 
154
 
 
155
 
static void process_timeout(void *eloop_ctx, void *sock_ctx)
156
 
{
157
 
        DBusTimeout *timeout = sock_ctx;
158
 
 
159
 
        dbus_timeout_handle(timeout);
160
 
}
161
 
 
162
 
 
163
 
static void connection_setup_add_timeout(struct ctrl_iface_dbus_priv *iface,
164
 
                                         DBusTimeout *timeout)
165
 
{
166
 
        if (!dbus_timeout_get_enabled(timeout))
167
 
                return;
168
 
 
169
 
        eloop_register_timeout(0, dbus_timeout_get_interval(timeout) * 1000,
170
 
                               process_timeout, iface, timeout);
171
 
 
172
 
        dbus_timeout_set_data(timeout, iface, NULL);
173
 
}
174
 
 
175
 
 
176
 
static void connection_setup_remove_timeout(struct ctrl_iface_dbus_priv *iface,
177
 
                                            DBusTimeout *timeout)
178
 
{
179
 
        eloop_cancel_timeout(process_timeout, iface, timeout);
180
 
        dbus_timeout_set_data(timeout, NULL, NULL);
181
 
}
182
 
 
183
 
 
184
 
static dbus_bool_t add_timeout(DBusTimeout *timeout, void *data)
185
 
{
186
 
        if (!dbus_timeout_get_enabled(timeout))
187
 
                return TRUE;
188
 
 
189
 
        connection_setup_add_timeout(data, timeout);
190
 
 
191
 
        return TRUE;
192
 
}
193
 
 
194
 
 
195
 
static void remove_timeout(DBusTimeout *timeout, void *data)
196
 
{
197
 
        connection_setup_remove_timeout(data, timeout);
198
 
}
199
 
 
200
 
 
201
 
static void timeout_toggled(DBusTimeout *timeout, void *data)
202
 
{
203
 
        if (dbus_timeout_get_enabled(timeout))
204
 
                add_timeout(timeout, data);
205
 
        else
206
 
                remove_timeout(timeout, data);
207
 
}
208
 
 
209
 
 
210
 
static void process_wakeup_main(int sig, void *eloop_ctx, void *signal_ctx)
211
 
{
212
 
        struct ctrl_iface_dbus_priv *iface = signal_ctx;
213
 
 
214
 
        if (sig != SIGPOLL || !iface->con)
215
 
                return;
216
 
 
217
 
        if (dbus_connection_get_dispatch_status(iface->con) !=
218
 
            DBUS_DISPATCH_DATA_REMAINS)
219
 
                return;
220
 
 
221
 
        /* Only dispatch once - we do not want to starve other events */
222
 
        dbus_connection_ref(iface->con);
223
 
        dbus_connection_dispatch(iface->con);
224
 
        dbus_connection_unref(iface->con);
225
 
}
226
 
 
227
 
 
228
 
/**
229
 
 * wakeup_main - Attempt to wake our mainloop up
230
 
 * @data: dbus control interface private data
231
 
 *
232
 
 * Try to wake up the main eloop so it will process
233
 
 * dbus events that may have happened.
234
 
 */
235
 
static void wakeup_main(void *data)
236
 
{
237
 
        struct ctrl_iface_dbus_priv *iface = data;
238
 
 
239
 
        /* Use SIGPOLL to break out of the eloop select() */
240
 
        raise(SIGPOLL);
241
 
        iface->should_dispatch = 1;
242
 
}
243
 
 
244
 
 
245
 
/**
246
 
 * connection_setup_wakeup_main - Tell dbus about our wakeup_main function
247
 
 * @iface: dbus control interface private data
248
 
 * Returns: 0 on success, -1 on failure
249
 
 *
250
 
 * Register our wakeup_main handler with dbus
251
 
 */
252
 
static int connection_setup_wakeup_main(struct ctrl_iface_dbus_priv *iface)
253
 
{
254
 
        if (eloop_register_signal(SIGPOLL, process_wakeup_main, iface))
255
 
                return -1;
256
 
 
257
 
        dbus_connection_set_wakeup_main_function(iface->con, wakeup_main,
258
 
                                                 iface, NULL);
259
 
 
260
 
        return 0;
261
 
}
262
 
 
263
 
 
264
 
/**
265
 
 * wpa_supplicant_dbus_next_objid - Return next available object id
266
 
 * @iface: dbus control interface private data
267
 
 * Returns: Object id
268
 
 */
269
 
u32 wpa_supplicant_dbus_next_objid (struct ctrl_iface_dbus_priv *iface)
270
 
{
271
 
        return iface->next_objid++;
272
 
}
273
 
 
274
 
 
275
 
/**
276
 
 * wpas_dbus_decompose_object_path - Decompose an interface object path into parts
277
 
 * @path: The dbus object path
278
 
 * @network: (out) the configured network this object path refers to, if any
279
 
 * @bssid: (out) the scanned bssid this object path refers to, if any
280
 
 * Returns: The object path of the network interface this path refers to
281
 
 *
282
 
 * For a given object path, decomposes the object path into object id, network,
283
 
 * and BSSID parts, if those parts exist.
284
 
 */
285
 
char * wpas_dbus_decompose_object_path(const char *path, char **network,
286
 
                                       char **bssid)
287
 
{
288
 
        const unsigned int dev_path_prefix_len =
289
 
                strlen(WPAS_DBUS_PATH_INTERFACES "/");
290
 
        char *obj_path_only;
291
 
        char *next_sep;
292
 
 
293
 
        /* Be a bit paranoid about path */
294
 
        if (!path || strncmp(path, WPAS_DBUS_PATH_INTERFACES "/",
295
 
                             dev_path_prefix_len))
296
 
                return NULL;
297
 
 
298
 
        /* Ensure there's something at the end of the path */
299
 
        if ((path + dev_path_prefix_len)[0] == '\0')
300
 
                return NULL;
301
 
 
302
 
        obj_path_only = strdup(path);
303
 
        if (obj_path_only == NULL)
304
 
                return NULL;
305
 
 
306
 
        next_sep = strchr(obj_path_only + dev_path_prefix_len, '/');
307
 
        if (next_sep != NULL) {
308
 
                const char *net_part = strstr(next_sep,
309
 
                                              WPAS_DBUS_NETWORKS_PART "/");
310
 
                const char *bssid_part = strstr(next_sep,
311
 
                                                WPAS_DBUS_BSSIDS_PART "/");
312
 
 
313
 
                if (network && net_part) {
314
 
                        /* Deal with a request for a configured network */
315
 
                        const char *net_name = net_part +
316
 
                                strlen(WPAS_DBUS_NETWORKS_PART "/");
317
 
                        *network = NULL;
318
 
                        if (strlen(net_name))
319
 
                                *network = strdup(net_name);
320
 
                } else if (bssid && bssid_part) {
321
 
                        /* Deal with a request for a scanned BSSID */
322
 
                        const char *bssid_name = bssid_part +
323
 
                                strlen(WPAS_DBUS_BSSIDS_PART "/");
324
 
                        if (strlen(bssid_name))
325
 
                                *bssid = strdup(bssid_name);
326
 
                        else
327
 
                                *bssid = NULL;
328
 
                }
329
 
 
330
 
                /* Cut off interface object path before "/" */
331
 
                *next_sep = '\0';
332
 
        }
333
 
 
334
 
        return obj_path_only;
335
 
}
336
 
 
337
 
 
338
 
/**
339
 
 * wpas_dbus_new_invalid_iface_error - Return a new invalid interface error message
340
 
 * @message: Pointer to incoming dbus message this error refers to
341
 
 * Returns: A dbus error message
342
 
 *
343
 
 * Convenience function to create and return an invalid interface error
344
 
 */
345
 
DBusMessage * wpas_dbus_new_invalid_iface_error(DBusMessage *message)
346
 
{
347
 
        return dbus_message_new_error(message, WPAS_ERROR_INVALID_IFACE,
348
 
                                      "wpa_supplicant knows nothing about "
349
 
                                      "this interface.");
350
 
}
351
 
 
352
 
 
353
 
/**
354
 
 * wpas_dbus_new_invalid_network_error - Return a new invalid network error message
355
 
 * @message: Pointer to incoming dbus message this error refers to
356
 
 * Returns: a dbus error message
357
 
 *
358
 
 * Convenience function to create and return an invalid network error
359
 
 */
360
 
DBusMessage * wpas_dbus_new_invalid_network_error(DBusMessage *message)
361
 
{
362
 
        return dbus_message_new_error(message, WPAS_ERROR_INVALID_NETWORK,
363
 
                                      "The requested network does not exist.");
364
 
}
365
 
 
366
 
 
367
 
/**
368
 
 * wpas_dbus_new_invalid_bssid_error - Return a new invalid bssid error message
369
 
 * @message: Pointer to incoming dbus message this error refers to
370
 
 * Returns: a dbus error message
371
 
 *
372
 
 * Convenience function to create and return an invalid bssid error
373
 
 */
374
 
static DBusMessage * wpas_dbus_new_invalid_bssid_error(DBusMessage *message)
375
 
{
376
 
        return dbus_message_new_error(message, WPAS_ERROR_INVALID_BSSID,
377
 
                                      "The BSSID requested was invalid.");
378
 
}
379
 
 
380
 
 
381
 
/**
382
 
 * wpas_dispatch_network_method - dispatch messages for configured networks
383
 
 * @message: the incoming dbus message
384
 
 * @wpa_s: a network interface's data
385
 
 * @network_id: id of the configured network we're interested in
386
 
 * Returns: a reply dbus message, or a dbus error message
387
 
 *
388
 
 * This function dispatches all incoming dbus messages for configured networks.
389
 
 */
390
 
static DBusMessage * wpas_dispatch_network_method(DBusMessage *message,
391
 
                                                  struct wpa_supplicant *wpa_s,
392
 
                                                  int network_id)
393
 
{
394
 
        DBusMessage *reply = NULL;
395
 
        const char *method = dbus_message_get_member(message);
396
 
        struct wpa_ssid *ssid;
397
 
 
398
 
        ssid = wpa_config_get_network(wpa_s->conf, network_id);
399
 
        if (ssid == NULL)
400
 
                return wpas_dbus_new_invalid_network_error(message);
401
 
 
402
 
        if (!strcmp(method, "set"))
403
 
                reply = wpas_dbus_iface_set_network(message, wpa_s, ssid);
404
 
        else if (!strcmp(method, "enable"))
405
 
                reply = wpas_dbus_iface_enable_network(message, wpa_s, ssid);
406
 
        else if (!strcmp(method, "disable"))
407
 
                reply = wpas_dbus_iface_disable_network(message, wpa_s, ssid);
408
 
 
409
 
        return reply;
410
 
}
411
 
 
412
 
 
413
 
/**
414
 
 * wpas_dispatch_bssid_method - dispatch messages for scanned networks
415
 
 * @message: the incoming dbus message
416
 
 * @wpa_s: a network interface's data
417
 
 * @bssid: bssid of the scanned network we're interested in
418
 
 * Returns: a reply dbus message, or a dbus error message
419
 
 *
420
 
 * This function dispatches all incoming dbus messages for scanned networks.
421
 
 */
422
 
static DBusMessage * wpas_dispatch_bssid_method(DBusMessage *message,
423
 
                                                struct wpa_supplicant *wpa_s,
424
 
                                                const char *bssid)
425
 
{
426
 
        DBusMessage *reply = NULL;
427
 
        const char *method = dbus_message_get_member(message);
428
 
        struct wpa_scan_res *res = NULL;
429
 
        size_t i;
430
 
 
431
 
        /* Ensure we actually have scan data */
432
 
        if (wpa_s->scan_res == NULL &&
433
 
            wpa_supplicant_get_scan_results(wpa_s) < 0) {
434
 
                reply = wpas_dbus_new_invalid_bssid_error(message);
435
 
                goto out;
436
 
        }
437
 
 
438
 
        /* Find the bssid's scan data */
439
 
        for (i = 0; i < wpa_s->scan_res->num; i++) {
440
 
                struct wpa_scan_res *search_res = wpa_s->scan_res->res[i];
441
 
                char mac_str[18];
442
 
 
443
 
                memset(mac_str, 0, sizeof(mac_str));
444
 
                snprintf(mac_str, sizeof(mac_str) - 1, WPAS_DBUS_BSSID_FORMAT,
445
 
                         MAC2STR(search_res->bssid));
446
 
                if (!strcmp(bssid, mac_str)) {
447
 
                        res = search_res;
448
 
                        break;
449
 
                }
450
 
        }
451
 
 
452
 
        if (!res) {
453
 
                reply = wpas_dbus_new_invalid_bssid_error(message);
454
 
                goto out;
455
 
        }
456
 
 
457
 
        /* Dispatch the method call against the scanned bssid */
458
 
        if (!strcmp(method, "properties"))
459
 
                reply = wpas_dbus_bssid_properties(message, wpa_s, res);
460
 
 
461
 
out:
462
 
        return reply;
463
 
}
464
 
 
465
 
 
466
 
/**
467
 
 * wpas_iface_message_handler - Dispatch messages for interfaces or networks
468
 
 * @connection: Connection to the system message bus
469
 
 * @message: An incoming dbus message
470
 
 * @user_data: A pointer to a dbus control interface data structure
471
 
 * Returns: Whether or not the message was handled
472
 
 *
473
 
 * This function dispatches all incoming dbus messages for network interfaces,
474
 
 * or objects owned by them, such as scanned BSSIDs and configured networks.
475
 
 */
476
 
static DBusHandlerResult wpas_iface_message_handler(DBusConnection *connection,
477
 
                                                    DBusMessage *message,
478
 
                                                    void *user_data)
479
 
{
480
 
        struct wpa_supplicant *wpa_s = user_data;
481
 
        const char *method = dbus_message_get_member(message);
482
 
        const char *path = dbus_message_get_path(message);
483
 
        const char *msg_interface = dbus_message_get_interface(message);
484
 
        char *iface_obj_path = NULL;
485
 
        char *network = NULL;
486
 
        char *bssid = NULL;
487
 
        DBusMessage *reply = NULL;
488
 
 
489
 
        /* Caller must specify a message interface */
490
 
        if (!msg_interface)
491
 
                goto out;
492
 
 
493
 
        iface_obj_path = wpas_dbus_decompose_object_path(path, &network,
494
 
                                                         &bssid);
495
 
        if (iface_obj_path == NULL) {
496
 
                reply = wpas_dbus_new_invalid_iface_error(message);
497
 
                goto out;
498
 
        }
499
 
 
500
 
        /* Make sure the message's object path actually refers to the
501
 
         * wpa_supplicant structure it's supposed to (which is wpa_s)
502
 
         */
503
 
        if (wpa_supplicant_get_iface_by_dbus_path(wpa_s->global,
504
 
                                                  iface_obj_path) != wpa_s) {
505
 
                reply = wpas_dbus_new_invalid_iface_error(message);
506
 
                goto out;
507
 
        }
508
 
 
509
 
        if (network && !strcmp(msg_interface, WPAS_DBUS_IFACE_NETWORK)) {
510
 
                /* A method for one of this interface's configured networks */
511
 
                int nid = strtoul(network, NULL, 10);
512
 
                if (errno != EINVAL)
513
 
                        reply = wpas_dispatch_network_method(message, wpa_s,
514
 
                                                             nid);
515
 
                else
516
 
                        reply = wpas_dbus_new_invalid_network_error(message);
517
 
        } else if (bssid && !strcmp(msg_interface, WPAS_DBUS_IFACE_BSSID)) {
518
 
                /* A method for one of this interface's scanned BSSIDs */
519
 
                reply = wpas_dispatch_bssid_method(message, wpa_s, bssid);
520
 
        } else if (!strcmp(msg_interface, WPAS_DBUS_IFACE_INTERFACE)) {
521
 
                /* A method for an interface only. */
522
 
                if (!strcmp(method, "scan"))
523
 
                        reply = wpas_dbus_iface_scan(message, wpa_s);
524
 
                else if (!strcmp(method, "scanResults"))
525
 
                        reply = wpas_dbus_iface_scan_results(message, wpa_s);
526
 
                else if (!strcmp(method, "addNetwork"))
527
 
                        reply = wpas_dbus_iface_add_network(message, wpa_s);
528
 
                else if (!strcmp(method, "removeNetwork"))
529
 
                        reply = wpas_dbus_iface_remove_network(message, wpa_s);
530
 
                else if (!strcmp(method, "selectNetwork"))
531
 
                        reply = wpas_dbus_iface_select_network(message, wpa_s);
532
 
                else if (!strcmp(method, "capabilities"))
533
 
                        reply = wpas_dbus_iface_capabilities(message, wpa_s);
534
 
                else if (!strcmp(method, "disconnect"))
535
 
                        reply = wpas_dbus_iface_disconnect(message, wpa_s);
536
 
                else if (!strcmp(method, "setAPScan"))
537
 
                        reply = wpas_dbus_iface_set_ap_scan(message, wpa_s);
538
 
                else if (!strcmp(method, "setSmartcardModules"))
539
 
                        reply = wpas_dbus_iface_set_smartcard_modules(message,
540
 
                                                                      wpa_s);
541
 
                else if (!strcmp(method, "state"))
542
 
                        reply = wpas_dbus_iface_get_state(message, wpa_s);
543
 
                else if (!strcmp(method, "scanning"))
544
 
                        reply = wpas_dbus_iface_get_scanning(message, wpa_s);
545
 
                else if (!strcmp(method, "setBlobs"))
546
 
                        reply = wpas_dbus_iface_set_blobs(message, wpa_s);
547
 
                else if (!strcmp(method, "removeBlobs"))
548
 
                        reply = wpas_dbus_iface_remove_blobs(message, wpa_s);
549
 
        }
550
 
 
551
 
        /* If the message was handled, send back the reply */
552
 
        if (reply) {
553
 
                if (!dbus_message_get_no_reply(message))
554
 
                        dbus_connection_send(connection, reply, NULL);
555
 
                dbus_message_unref(reply);
556
 
        }
557
 
 
558
 
out:
559
 
        free(iface_obj_path);
560
 
        free(network);
561
 
        free(bssid);
562
 
        return reply ? DBUS_HANDLER_RESULT_HANDLED :
563
 
                DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
564
 
}
565
 
 
566
 
 
567
 
/**
568
 
 * wpas_message_handler - dispatch incoming dbus messages
569
 
 * @connection: connection to the system message bus
570
 
 * @message: an incoming dbus message
571
 
 * @user_data: a pointer to a dbus control interface data structure
572
 
 * Returns: whether or not the message was handled
573
 
 *
574
 
 * This function dispatches all incoming dbus messages to the correct
575
 
 * handlers, depending on what the message's target object path is,
576
 
 * and what the method call is.
577
 
 */
578
 
static DBusHandlerResult wpas_message_handler(DBusConnection *connection,
579
 
        DBusMessage *message, void *user_data)
580
 
{
581
 
        struct ctrl_iface_dbus_priv *ctrl_iface = user_data;
582
 
        const char *method;
583
 
        const char *path;
584
 
        const char *msg_interface;
585
 
        DBusMessage *reply = NULL;
586
 
 
587
 
        method = dbus_message_get_member(message);
588
 
        path = dbus_message_get_path(message);
589
 
        msg_interface = dbus_message_get_interface(message);
590
 
        if (!method || !path || !ctrl_iface || !msg_interface)
591
 
                return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
592
 
 
593
 
        /* Validate the method interface */
594
 
        if (strcmp(msg_interface, WPAS_DBUS_INTERFACE) != 0)
595
 
                return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
596
 
 
597
 
        if (!strcmp(path, WPAS_DBUS_PATH)) {
598
 
                /* dispatch methods against our global dbus interface here */
599
 
                if (!strcmp(method, "addInterface")) {
600
 
                        reply = wpas_dbus_global_add_interface(
601
 
                                message, ctrl_iface->global);
602
 
                } else if (!strcmp(method, "removeInterface")) {
603
 
                        reply = wpas_dbus_global_remove_interface(
604
 
                                message, ctrl_iface->global);
605
 
                } else if (!strcmp(method, "getInterface")) {
606
 
                        reply = wpas_dbus_global_get_interface(
607
 
                                message, ctrl_iface->global);
608
 
                } else if (!strcmp(method, "setDebugParams")) {
609
 
                        reply = wpas_dbus_global_set_debugparams(
610
 
                                message, ctrl_iface->global);
611
 
                }
612
 
        }
613
 
 
614
 
        /* If the message was handled, send back the reply */
615
 
        if (reply) {
616
 
                if (!dbus_message_get_no_reply(message))
617
 
                        dbus_connection_send(connection, reply, NULL);
618
 
                dbus_message_unref(reply);
619
 
        }
620
 
 
621
 
        return reply ? DBUS_HANDLER_RESULT_HANDLED :
622
 
                DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
623
 
}
624
 
 
625
 
 
626
 
/**
627
 
 * wpa_supplicant_dbus_notify_scan_results - Send a scan results signal
628
 
 * @wpa_s: %wpa_supplicant network interface data
629
 
 * Returns: 0 on success, -1 on failure
630
 
 *
631
 
 * Notify listeners that this interface has updated scan results.
632
 
 */
633
 
void wpa_supplicant_dbus_notify_scan_results(struct wpa_supplicant *wpa_s)
634
 
{
635
 
        struct ctrl_iface_dbus_priv *iface = wpa_s->global->dbus_ctrl_iface;
636
 
        DBusMessage *_signal;
637
 
        const char *path;
638
 
 
639
 
        /* Do nothing if the control interface is not turned on */
640
 
        if (iface == NULL)
641
 
                return;
642
 
 
643
 
        path = wpa_supplicant_get_dbus_path(wpa_s);
644
 
        if (path == NULL) {
645
 
                perror("wpa_supplicant_dbus_notify_scan_results[dbus]: "
646
 
                       "interface didn't have a dbus path");
647
 
                wpa_printf(MSG_ERROR,
648
 
                           "wpa_supplicant_dbus_notify_scan_results[dbus]: "
649
 
                           "interface didn't have a dbus path; can't send "
650
 
                           "scan result signal.");
651
 
                return;
652
 
        }
653
 
        _signal = dbus_message_new_signal(path, WPAS_DBUS_IFACE_INTERFACE,
654
 
                                          "ScanResultsAvailable");
655
 
        if (_signal == NULL) {
656
 
                perror("wpa_supplicant_dbus_notify_scan_results[dbus]: "
657
 
                       "couldn't create dbus signal; likely out of memory");
658
 
                wpa_printf(MSG_ERROR, "dbus control interface: not enough "
659
 
                           "memory to send scan results signal.");
660
 
                return;
661
 
        }
662
 
        dbus_connection_send(iface->con, _signal, NULL);
663
 
        dbus_message_unref(_signal);
664
 
}
665
 
 
666
 
 
667
 
/**
668
 
 * wpa_supplicant_dbus_notify_state_change - Send a state change signal
669
 
 * @wpa_s: %wpa_supplicant network interface data
670
 
 * @new_state: new state wpa_supplicant is entering
671
 
 * @old_state: old state wpa_supplicant is leaving
672
 
 * Returns: 0 on success, -1 on failure
673
 
 *
674
 
 * Notify listeners that wpa_supplicant has changed state
675
 
 */
676
 
void wpa_supplicant_dbus_notify_state_change(struct wpa_supplicant *wpa_s,
677
 
                                             wpa_states new_state,
678
 
                                             wpa_states old_state)
679
 
{
680
 
        struct ctrl_iface_dbus_priv *iface;
681
 
        DBusMessage *_signal = NULL;
682
 
        const char *path;
683
 
        const char *new_state_str, *old_state_str;
684
 
 
685
 
        /* Do nothing if the control interface is not turned on */
686
 
        if (wpa_s->global == NULL)
687
 
                return;
688
 
        iface = wpa_s->global->dbus_ctrl_iface;
689
 
        if (iface == NULL)
690
 
                return;
691
 
 
692
 
        /* Only send signal if state really changed */
693
 
        if (new_state == old_state)
694
 
                return;
695
 
 
696
 
        path = wpa_supplicant_get_dbus_path(wpa_s);
697
 
        if (path == NULL) {
698
 
                perror("wpa_supplicant_dbus_notify_state_change[dbus]: "
699
 
                       "interface didn't have a dbus path");
700
 
                wpa_printf(MSG_ERROR,
701
 
                           "wpa_supplicant_dbus_notify_state_change[dbus]: "
702
 
                           "interface didn't have a dbus path; can't send "
703
 
                           "signal.");
704
 
                return;
705
 
        }
706
 
        _signal = dbus_message_new_signal(path, WPAS_DBUS_IFACE_INTERFACE,
707
 
                                          "StateChange");
708
 
        if (_signal == NULL) {
709
 
                perror("wpa_supplicant_dbus_notify_state_change[dbus]: "
710
 
                       "couldn't create dbus signal; likely out of memory");
711
 
                wpa_printf(MSG_ERROR,
712
 
                           "wpa_supplicant_dbus_notify_state_change[dbus]: "
713
 
                           "couldn't create dbus signal; likely out of "
714
 
                           "memory.");
715
 
                return;
716
 
        }
717
 
 
718
 
        new_state_str = wpa_supplicant_state_txt(new_state);
719
 
        old_state_str = wpa_supplicant_state_txt(old_state);
720
 
        if (new_state_str == NULL || old_state_str == NULL) {
721
 
                perror("wpa_supplicant_dbus_notify_state_change[dbus]: "
722
 
                       "couldn't convert state strings");
723
 
                wpa_printf(MSG_ERROR,
724
 
                           "wpa_supplicant_dbus_notify_state_change[dbus]: "
725
 
                           "couldn't convert state strings.");
726
 
                goto out;
727
 
        }
728
 
 
729
 
        if (!dbus_message_append_args(_signal,
730
 
                                      DBUS_TYPE_STRING, &new_state_str,
731
 
                                      DBUS_TYPE_STRING, &old_state_str,
732
 
                                      DBUS_TYPE_INVALID)) {
733
 
                perror("wpa_supplicant_dbus_notify_state_change[dbus]: "
734
 
                       "not enough memory to construct state change signal.");
735
 
                wpa_printf(MSG_ERROR,
736
 
                           "wpa_supplicant_dbus_notify_state_change[dbus]: "
737
 
                           "not enough memory to construct state change "
738
 
                           "signal.");
739
 
                goto out;
740
 
        }
741
 
 
742
 
        dbus_connection_send(iface->con, _signal, NULL);
743
 
 
744
 
out:
745
 
        dbus_message_unref(_signal);
746
 
}
747
 
 
748
 
 
749
 
/**
750
 
 * wpa_supplicant_dbus_notify_scanning - send scanning status
751
 
 * @wpa_s: %wpa_supplicant network interface data
752
 
 * Returns: 0 on success, -1 on failure
753
 
 *
754
 
 * Notify listeners of interface scanning state changes
755
 
 */
756
 
void wpa_supplicant_dbus_notify_scanning(struct wpa_supplicant *wpa_s)
757
 
{
758
 
        struct ctrl_iface_dbus_priv *iface = wpa_s->global->dbus_ctrl_iface;
759
 
        DBusMessage *_signal;
760
 
        const char *path;
761
 
        dbus_bool_t scanning = wpa_s->scanning ? TRUE : FALSE;
762
 
 
763
 
        /* Do nothing if the control interface is not turned on */
764
 
        if (iface == NULL)
765
 
                return;
766
 
 
767
 
        path = wpa_supplicant_get_dbus_path(wpa_s);
768
 
        if (path == NULL) {
769
 
                perror("wpa_supplicant_dbus_notify_scanning[dbus]: interface "
770
 
                       "didn't have a dbus path");
771
 
                wpa_printf(MSG_ERROR,
772
 
                           "%s[dbus]: interface didn't have a dbus path; "
773
 
                           "can't send scanning signal.", __FUNCTION__);
774
 
                return;
775
 
        }
776
 
        _signal = dbus_message_new_signal(path, WPAS_DBUS_IFACE_INTERFACE,
777
 
                                          "Scanning");
778
 
        if (_signal == NULL) {
779
 
                perror("wpa_supplicant_dbus_notify_scanning[dbus]: couldn't "
780
 
                       "create dbus signal; likely out of memory");
781
 
                wpa_printf(MSG_ERROR, "%s[dbus]: dbus control interface: not "
782
 
                           "enough memory to send scan results signal.",
783
 
                           __FUNCTION__);
784
 
                return;
785
 
        }
786
 
 
787
 
        if (dbus_message_append_args(_signal,
788
 
                                     DBUS_TYPE_BOOLEAN, &scanning,
789
 
                                     DBUS_TYPE_INVALID)) {
790
 
                dbus_connection_send(iface->con, _signal, NULL);
791
 
        } else {
792
 
                perror("wpa_supplicant_dbus_notify_scanning[dbus]: not enough "
793
 
                       "memory to construct signal.");
794
 
                wpa_printf(MSG_ERROR, "%s[dbus]: not enough memory to "
795
 
                           "construct signal.", __FUNCTION__);
796
 
        }
797
 
        dbus_message_unref(_signal);
798
 
}
799
 
 
800
 
 
801
 
#ifdef CONFIG_WPS
802
 
void wpa_supplicant_dbus_notify_wps_cred(struct wpa_supplicant *wpa_s,
803
 
                                         const struct wps_credential *cred)
804
 
{
805
 
        struct ctrl_iface_dbus_priv *iface;
806
 
        DBusMessage *_signal = NULL;
807
 
        const char *path;
808
 
 
809
 
        /* Do nothing if the control interface is not turned on */
810
 
        if (wpa_s->global == NULL)
811
 
                return;
812
 
        iface = wpa_s->global->dbus_ctrl_iface;
813
 
        if (iface == NULL)
814
 
                return;
815
 
 
816
 
        path = wpa_supplicant_get_dbus_path(wpa_s);
817
 
        if (path == NULL) {
818
 
                perror("wpa_supplicant_dbus_notify_wps_cred[dbus]: "
819
 
                       "interface didn't have a dbus path");
820
 
                wpa_printf(MSG_ERROR,
821
 
                           "wpa_supplicant_dbus_notify_wps_cred[dbus]: "
822
 
                           "interface didn't have a dbus path; can't send "
823
 
                           "signal.");
824
 
                return;
825
 
        }
826
 
        _signal = dbus_message_new_signal(path, WPAS_DBUS_IFACE_INTERFACE,
827
 
                                          "WpsCred");
828
 
        if (_signal == NULL) {
829
 
                perror("wpa_supplicant_dbus_notify_wps_cred[dbus]: "
830
 
                       "couldn't create dbus signal; likely out of memory");
831
 
                wpa_printf(MSG_ERROR,
832
 
                           "wpa_supplicant_dbus_notify_wps_cred[dbus]: "
833
 
                           "couldn't create dbus signal; likely out of "
834
 
                           "memory.");
835
 
                return;
836
 
        }
837
 
 
838
 
        if (!dbus_message_append_args(_signal,
839
 
                                      DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
840
 
                                      &cred->cred_attr, cred->cred_attr_len,
841
 
                                      DBUS_TYPE_INVALID)) {
842
 
                perror("wpa_supplicant_dbus_notify_wps_cred[dbus]: "
843
 
                       "not enough memory to construct signal.");
844
 
                wpa_printf(MSG_ERROR,
845
 
                           "wpa_supplicant_dbus_notify_wps_cred[dbus]: "
846
 
                           "not enough memory to construct signal.");
847
 
                goto out;
848
 
        }
849
 
 
850
 
        dbus_connection_send(iface->con, _signal, NULL);
851
 
 
852
 
out:
853
 
        dbus_message_unref(_signal);
854
 
}
855
 
#else /* CONFIG_WPS */
856
 
void wpa_supplicant_dbus_notify_wps_cred(struct wpa_supplicant *wpa_s,
857
 
                                         const struct wps_credential *cred)
858
 
{
859
 
}
860
 
#endif /* CONFIG_WPS */
861
 
 
862
 
 
863
 
/**
864
 
 * integrate_with_eloop - Register our mainloop integration with dbus
865
 
 * @connection: connection to the system message bus
866
 
 * @iface: a dbus control interface data structure
867
 
 * Returns: 0 on success, -1 on failure
868
 
 *
869
 
 * We register our mainloop integration functions with dbus here.
870
 
 */
871
 
static int integrate_with_eloop(DBusConnection *connection,
872
 
        struct ctrl_iface_dbus_priv *iface)
873
 
{
874
 
        if (!dbus_connection_set_watch_functions(connection, add_watch,
875
 
                                                 remove_watch, watch_toggled,
876
 
                                                 iface, NULL)) {
877
 
                perror("dbus_connection_set_watch_functions[dbus]");
878
 
                wpa_printf(MSG_ERROR, "Not enough memory to set up dbus.");
879
 
                return -1;
880
 
        }
881
 
 
882
 
        if (!dbus_connection_set_timeout_functions(connection, add_timeout,
883
 
                                                   remove_timeout,
884
 
                                                   timeout_toggled, iface,
885
 
                                                   NULL)) {
886
 
                perror("dbus_connection_set_timeout_functions[dbus]");
887
 
                wpa_printf(MSG_ERROR, "Not enough memory to set up dbus.");
888
 
                return -1;
889
 
        }
890
 
 
891
 
        if (connection_setup_wakeup_main(iface) < 0) {
892
 
                perror("connection_setup_wakeup_main[dbus]");
893
 
                wpa_printf(MSG_ERROR, "Could not setup main wakeup function.");
894
 
                return -1;
895
 
        }
896
 
 
897
 
        return 0;
898
 
}
899
 
 
900
 
 
901
 
/**
902
 
 * dispatch_initial_dbus_messages - Dispatch initial dbus messages after
903
 
 *     claiming bus name
904
 
 * @eloop_ctx: the DBusConnection to dispatch on
905
 
 * @timeout_ctx: unused
906
 
 *
907
 
 * If clients are quick to notice that wpa_supplicant claimed its bus name,
908
 
 * there may have been messages that came in before initialization was
909
 
 * all finished.  Dispatch those here.
910
 
 */
911
 
static void dispatch_initial_dbus_messages(void *eloop_ctx, void *timeout_ctx)
912
 
{
913
 
        DBusConnection *con = eloop_ctx;
914
 
 
915
 
        while (dbus_connection_get_dispatch_status(con) ==
916
 
               DBUS_DISPATCH_DATA_REMAINS)
917
 
                dbus_connection_dispatch(con);
918
 
}
919
 
 
920
 
 
921
 
/**
922
 
 * wpa_supplicant_dbus_ctrl_iface_init - Initialize dbus control interface
923
 
 * @global: Pointer to global data from wpa_supplicant_init()
924
 
 * Returns: Pointer to dbus_ctrl_iface date or %NULL on failure
925
 
 *
926
 
 * Initialize the dbus control interface and start receiving commands from
927
 
 * external programs over the bus.
928
 
 */
929
 
struct ctrl_iface_dbus_priv *
930
 
wpa_supplicant_dbus_ctrl_iface_init(struct wpa_global *global)
931
 
{
932
 
        struct ctrl_iface_dbus_priv *iface;
933
 
        DBusError error;
934
 
        int ret = -1;
935
 
        DBusObjectPathVTable wpas_vtable = {
936
 
                NULL, &wpas_message_handler, NULL, NULL, NULL, NULL
937
 
        };
938
 
 
939
 
        iface = os_zalloc(sizeof(struct ctrl_iface_dbus_priv));
940
 
        if (iface == NULL)
941
 
                return NULL;
942
 
 
943
 
        iface->global = global;
944
 
 
945
 
        /* Get a reference to the system bus */
946
 
        dbus_error_init(&error);
947
 
        iface->con = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
948
 
        dbus_error_free(&error);
949
 
        if (!iface->con) {
950
 
                perror("dbus_bus_get[ctrl_iface_dbus]");
951
 
                wpa_printf(MSG_ERROR, "Could not acquire the system bus.");
952
 
                goto fail;
953
 
        }
954
 
 
955
 
        /* Tell dbus about our mainloop integration functions */
956
 
        if (integrate_with_eloop(iface->con, iface))
957
 
                goto fail;
958
 
 
959
 
        /* Register the message handler for the global dbus interface */
960
 
        if (!dbus_connection_register_object_path(iface->con,
961
 
                                                  WPAS_DBUS_PATH, &wpas_vtable,
962
 
                                                  iface)) {
963
 
                perror("dbus_connection_register_object_path[dbus]");
964
 
                wpa_printf(MSG_ERROR, "Could not set up DBus message "
965
 
                           "handler.");
966
 
                goto fail;
967
 
        }
968
 
 
969
 
        /* Register our service with the message bus */
970
 
        dbus_error_init(&error);
971
 
        switch (dbus_bus_request_name(iface->con, WPAS_DBUS_SERVICE,
972
 
                                      0, &error)) {
973
 
        case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER:
974
 
                ret = 0;
975
 
                break;
976
 
        case DBUS_REQUEST_NAME_REPLY_EXISTS:
977
 
        case DBUS_REQUEST_NAME_REPLY_IN_QUEUE:
978
 
        case DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER:
979
 
                perror("dbus_bus_request_name[dbus]");
980
 
                wpa_printf(MSG_ERROR, "Could not request DBus service name: "
981
 
                           "already registered.");
982
 
                break;
983
 
        default:
984
 
                perror("dbus_bus_request_name[dbus]");
985
 
                wpa_printf(MSG_ERROR, "Could not request DBus service name: "
986
 
                           "%s %s.", error.name, error.message);
987
 
                break;
988
 
        }
989
 
        dbus_error_free(&error);
990
 
 
991
 
        if (ret != 0)
992
 
                goto fail;
993
 
 
994
 
        wpa_printf(MSG_DEBUG, "Providing DBus service '" WPAS_DBUS_SERVICE
995
 
                   "'.");
996
 
 
997
 
        /*
998
 
         * Dispatch initial DBus messages that may have come in since the bus
999
 
         * name was claimed above. Happens when clients are quick to notice the
1000
 
         * wpa_supplicant service.
1001
 
         *
1002
 
         * FIXME: is there a better solution to this problem?
1003
 
         */
1004
 
        eloop_register_timeout(0, 50, dispatch_initial_dbus_messages,
1005
 
                               iface->con, NULL);
1006
 
 
1007
 
        return iface;
1008
 
 
1009
 
fail:
1010
 
        wpa_supplicant_dbus_ctrl_iface_deinit(iface);
1011
 
        return NULL;
1012
 
}
1013
 
 
1014
 
 
1015
 
/**
1016
 
 * wpa_supplicant_dbus_ctrl_iface_deinit - Deinitialize dbus ctrl interface
1017
 
 * @iface: Pointer to dbus private data from
1018
 
 * wpa_supplicant_dbus_ctrl_iface_init()
1019
 
 *
1020
 
 * Deinitialize the dbus control interface that was initialized with
1021
 
 * wpa_supplicant_dbus_ctrl_iface_init().
1022
 
 */
1023
 
void wpa_supplicant_dbus_ctrl_iface_deinit(struct ctrl_iface_dbus_priv *iface)
1024
 
{
1025
 
        if (iface == NULL)
1026
 
                return;
1027
 
 
1028
 
        if (iface->con) {
1029
 
                eloop_cancel_timeout(dispatch_initial_dbus_messages,
1030
 
                                     iface->con, NULL);
1031
 
                dbus_connection_set_watch_functions(iface->con, NULL, NULL,
1032
 
                                                    NULL, NULL, NULL);
1033
 
                dbus_connection_set_timeout_functions(iface->con, NULL, NULL,
1034
 
                                                      NULL, NULL, NULL);
1035
 
                dbus_connection_unref(iface->con);
1036
 
        }
1037
 
 
1038
 
        memset(iface, 0, sizeof(struct ctrl_iface_dbus_priv));
1039
 
        free(iface);
1040
 
}
1041
 
 
1042
 
 
1043
 
/**
1044
 
 * wpas_dbus_register_new_iface - Register a new interface with dbus
1045
 
 * @wpa_s: %wpa_supplicant interface description structure to register
1046
 
 * Returns: 0 on success, -1 on error
1047
 
 *
1048
 
 * Registers a new interface with dbus and assigns it a dbus object path.
1049
 
 */
1050
 
int wpas_dbus_register_iface(struct wpa_supplicant *wpa_s)
1051
 
{
1052
 
        struct ctrl_iface_dbus_priv *ctrl_iface =
1053
 
                wpa_s->global->dbus_ctrl_iface;
1054
 
        DBusConnection * con;
1055
 
        u32 next;
1056
 
        DBusObjectPathVTable vtable = {
1057
 
                NULL, &wpas_iface_message_handler, NULL, NULL, NULL, NULL
1058
 
        };
1059
 
        char *path;
1060
 
        int ret = -1;
1061
 
 
1062
 
        /* Do nothing if the control interface is not turned on */
1063
 
        if (ctrl_iface == NULL)
1064
 
                return 0;
1065
 
 
1066
 
        con = ctrl_iface->con;
1067
 
        next = wpa_supplicant_dbus_next_objid(ctrl_iface);
1068
 
 
1069
 
        /* Create and set the interface's object path */
1070
 
        path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1071
 
        if (path == NULL)
1072
 
                return -1;
1073
 
        snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
1074
 
                 WPAS_DBUS_PATH_INTERFACES "/%u",
1075
 
                 next);
1076
 
        if (wpa_supplicant_set_dbus_path(wpa_s, path)) {
1077
 
                wpa_printf(MSG_DEBUG,
1078
 
                           "Failed to set dbus path for interface %s",
1079
 
                           wpa_s->ifname);
1080
 
                goto out;
1081
 
        }
1082
 
 
1083
 
        /* Register the message handler for the interface functions */
1084
 
        if (!dbus_connection_register_fallback(con, path, &vtable, wpa_s)) {
1085
 
                perror("wpas_dbus_register_iface [dbus]");
1086
 
                wpa_printf(MSG_ERROR, "Could not set up DBus message "
1087
 
                           "handler for interface %s.", wpa_s->ifname);
1088
 
                goto out;
1089
 
        }
1090
 
        ret = 0;
1091
 
 
1092
 
out:
1093
 
        free(path);
1094
 
        return ret;
1095
 
}
1096
 
 
1097
 
 
1098
 
/**
1099
 
 * wpas_dbus_unregister_iface - Unregister an interface from dbus
1100
 
 * @wpa_s: wpa_supplicant interface structure
1101
 
 * Returns: 0 on success, -1 on failure
1102
 
 *
1103
 
 * Unregisters the interface with dbus
1104
 
 */
1105
 
int wpas_dbus_unregister_iface(struct wpa_supplicant *wpa_s)
1106
 
{
1107
 
        struct ctrl_iface_dbus_priv *ctrl_iface;
1108
 
        DBusConnection *con;
1109
 
        const char *path;
1110
 
 
1111
 
        /* Do nothing if the control interface is not turned on */
1112
 
        if (wpa_s == NULL || wpa_s->global == NULL)
1113
 
                return 0;
1114
 
        ctrl_iface = wpa_s->global->dbus_ctrl_iface;
1115
 
        if (ctrl_iface == NULL)
1116
 
                return 0;
1117
 
 
1118
 
        con = ctrl_iface->con;
1119
 
        path = wpa_supplicant_get_dbus_path(wpa_s);
1120
 
 
1121
 
        if (!dbus_connection_unregister_object_path(con, path))
1122
 
                return -1;
1123
 
 
1124
 
        free(wpa_s->dbus_path);
1125
 
        wpa_s->dbus_path = NULL;
1126
 
 
1127
 
        return 0;
1128
 
}
1129
 
 
1130
 
 
1131
 
/**
1132
 
 * wpa_supplicant_get_iface_by_dbus_path - Get a new network interface
1133
 
 * @global: Pointer to global data from wpa_supplicant_init()
1134
 
 * @path: Pointer to a dbus object path representing an interface
1135
 
 * Returns: Pointer to the interface or %NULL if not found
1136
 
 */
1137
 
struct wpa_supplicant * wpa_supplicant_get_iface_by_dbus_path(
1138
 
        struct wpa_global *global, const char *path)
1139
 
{
1140
 
        struct wpa_supplicant *wpa_s;
1141
 
 
1142
 
        for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
1143
 
                if (strcmp(wpa_s->dbus_path, path) == 0)
1144
 
                        return wpa_s;
1145
 
        }
1146
 
        return NULL;
1147
 
}
1148
 
 
1149
 
 
1150
 
/**
1151
 
 * wpa_supplicant_set_dbus_path - Assign a dbus path to an interface
1152
 
 * @wpa_s: wpa_supplicant interface structure
1153
 
 * @path: dbus path to set on the interface
1154
 
 * Returns: 0 on succes, -1 on error
1155
 
 */
1156
 
int wpa_supplicant_set_dbus_path(struct wpa_supplicant *wpa_s,
1157
 
                                  const char *path)
1158
 
{
1159
 
        u32 len = strlen (path);
1160
 
        if (len >= WPAS_DBUS_OBJECT_PATH_MAX)
1161
 
                return -1;
1162
 
        if (wpa_s->dbus_path)
1163
 
                return -1;
1164
 
        wpa_s->dbus_path = strdup(path);
1165
 
        return 0;
1166
 
}
1167
 
 
1168
 
 
1169
 
/**
1170
 
 * wpa_supplicant_get_dbus_path - Get an interface's dbus path
1171
 
 * @wpa_s: %wpa_supplicant interface structure
1172
 
 * Returns: Interface's dbus object path, or %NULL on error
1173
 
 */
1174
 
const char * wpa_supplicant_get_dbus_path(struct wpa_supplicant *wpa_s)
1175
 
{
1176
 
        return wpa_s->dbus_path;
1177
 
}