~ubuntu-branches/ubuntu/gutsy/wpasupplicant/gutsy

« back to all changes in this revision

Viewing changes to ctrl_iface_dbus_handlers.c

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler, Alexander Sack
  • Date: 2007-08-26 16:06:57 UTC
  • mfrom: (1.1.9 upstream)
  • Revision ID: james.westby@ubuntu.com-20070826160657-2m8pxoweuxe8f93t
Tags: 0.6.0+0.5.8-0ubuntu1
* New upstream release
* remove patch 11_erroneous_manpage_ref, applied upstream
* remove patch 25_wpas_dbus_unregister_iface_fix, applied upstream

[ Alexander Sack ]
* bumping upstream version to replace development version 0.6.0 with
  this package from stable release branch.
* attempt to fix wierd timeout and high latency issues by going
  back to stable upstream version (0.5.9) (LP: #140763,
  LP: #141233).

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 <dbus/dbus.h>
 
18
 
 
19
#include "common.h"
 
20
#include "config.h"
 
21
#include "wpa_supplicant_i.h"
 
22
#include "ctrl_iface_dbus.h"
 
23
#include "ctrl_iface_dbus_handlers.h"
 
24
#include "l2_packet.h"
 
25
#include "eap_methods.h"
 
26
#include "dbus_dict_helpers.h"
 
27
#include "wpa.h"
 
28
 
 
29
 
 
30
/**
 
31
 * wpas_dbus_new_invalid_opts_error - Return a new invalid options error message
 
32
 * @message: Pointer to incoming dbus message this error refers to
 
33
 * Returns: a dbus error message
 
34
 *
 
35
 * Convenience function to create and return an invalid options error
 
36
 */
 
37
static DBusMessage * wpas_dbus_new_invalid_opts_error(DBusMessage *message,
 
38
                                                      const char *arg)
 
39
{
 
40
        DBusMessage *reply;
 
41
 
 
42
        reply = dbus_message_new_error(message, WPAS_ERROR_INVALID_OPTS,
 
43
                                      "Did not receive correct message "
 
44
                                      "arguments.");
 
45
        if (arg != NULL)
 
46
                dbus_message_append_args(reply, DBUS_TYPE_STRING, &arg,
 
47
                                         DBUS_TYPE_INVALID);
 
48
 
 
49
        return reply;
 
50
}
 
51
 
 
52
 
 
53
/**
 
54
 * wpas_dbus_new_success_reply - Return a new success reply message
 
55
 * @message: Pointer to incoming dbus message this reply refers to
 
56
 * Returns: a dbus message containing a single UINT32 that indicates
 
57
 *          success (ie, a value of 1)
 
58
 *
 
59
 * Convenience function to create and return a success reply message
 
60
 */
 
61
static DBusMessage * wpas_dbus_new_success_reply(DBusMessage *message)
 
62
{
 
63
        DBusMessage *reply;
 
64
        unsigned int success = 1;
 
65
 
 
66
        reply = dbus_message_new_method_return(message);
 
67
        dbus_message_append_args(reply, DBUS_TYPE_UINT32, &success,
 
68
                                 DBUS_TYPE_INVALID);
 
69
        return reply;
 
70
}
 
71
 
 
72
 
 
73
static void wpas_dbus_free_wpa_interface(struct wpa_interface *iface)
 
74
{
 
75
        free((char *) iface->driver);
 
76
        free((char *) iface->driver_param);
 
77
        free((char *) iface->confname);
 
78
        free((char *) iface->bridge_ifname);
 
79
}
 
80
 
 
81
 
 
82
/**
 
83
 * wpas_dbus_global_add_interface - Request registration of a network interface
 
84
 * @message: Pointer to incoming dbus message
 
85
 * @global: %wpa_supplicant global data structure
 
86
 * Returns: The object path of the new interface object,
 
87
 *          or a dbus error message with more information
 
88
 *
 
89
 * Handler function for "addInterface" method call. Handles requests
 
90
 * by dbus clients to register a network interface that wpa_supplicant
 
91
 * will manage.
 
92
 */
 
93
DBusMessage * wpas_dbus_global_add_interface(DBusMessage *message,
 
94
                                             struct wpa_global *global)
 
95
{
 
96
        struct wpa_interface iface;
 
97
        char *ifname = NULL;
 
98
        DBusMessage *reply = NULL;
 
99
        DBusMessageIter iter;
 
100
 
 
101
        memset(&iface, 0, sizeof(iface));
 
102
 
 
103
        dbus_message_iter_init(message, &iter);
 
104
 
 
105
        /* First argument: interface name (DBUS_TYPE_STRING)
 
106
         *    Required; must be non-zero length
 
107
         */
 
108
        if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
 
109
                goto error;
 
110
        dbus_message_iter_get_basic(&iter, &ifname);
 
111
        if (!strlen(ifname))
 
112
                goto error;
 
113
        iface.ifname = ifname;
 
114
 
 
115
        /* Second argument: dict of options */
 
116
        if (dbus_message_iter_next(&iter)) {
 
117
                DBusMessageIter iter_dict;
 
118
                struct wpa_dbus_dict_entry entry;
 
119
 
 
120
                if (!wpa_dbus_dict_open_read(&iter, &iter_dict))
 
121
                        goto error;
 
122
                while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
 
123
                        if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
 
124
                                goto error;
 
125
                        if (!strcmp(entry.key, "driver") &&
 
126
                            (entry.type == DBUS_TYPE_STRING)) {
 
127
                                iface.driver = strdup(entry.str_value);
 
128
                                if (iface.driver == NULL)
 
129
                                        goto error;
 
130
                        } else if (!strcmp(entry.key, "driver-params") &&
 
131
                                   (entry.type == DBUS_TYPE_STRING)) {
 
132
                                iface.driver_param = strdup(entry.str_value);
 
133
                                if (iface.driver_param == NULL)
 
134
                                        goto error;
 
135
                        } else if (!strcmp(entry.key, "config-file") &&
 
136
                                   (entry.type == DBUS_TYPE_STRING)) {
 
137
                                iface.confname = strdup(entry.str_value);
 
138
                                if (iface.confname == NULL)
 
139
                                        goto error;
 
140
                        } else if (!strcmp(entry.key, "bridge-ifname") &&
 
141
                                   (entry.type == DBUS_TYPE_STRING)) {
 
142
                                iface.bridge_ifname = strdup(entry.str_value);
 
143
                                if (iface.bridge_ifname == NULL)
 
144
                                        goto error;
 
145
                        } else {
 
146
                                wpa_dbus_dict_entry_clear(&entry);
 
147
                                goto error;
 
148
                        }
 
149
                        wpa_dbus_dict_entry_clear(&entry);
 
150
                }
 
151
        }
 
152
 
 
153
        /*
 
154
         * Try to get the wpa_supplicant record for this iface, return
 
155
         * an error if we already control it.
 
156
         */
 
157
        if (wpa_supplicant_get_iface(global, iface.ifname) != 0) {
 
158
                reply = dbus_message_new_error(message,
 
159
                                               WPAS_ERROR_EXISTS_ERROR,
 
160
                                               "wpa_supplicant already "
 
161
                                               "controls this interface.");
 
162
        } else {
 
163
                struct wpa_supplicant *wpa_s;
 
164
                /* Otherwise, have wpa_supplicant attach to it. */
 
165
                if ((wpa_s = wpa_supplicant_add_iface(global, &iface))) {
 
166
                        const char *path = wpa_supplicant_get_dbus_path(wpa_s);
 
167
                        reply = dbus_message_new_method_return(message);
 
168
                        dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH,
 
169
                                                 &path, DBUS_TYPE_INVALID);
 
170
                } else {
 
171
                        reply = dbus_message_new_error(message,
 
172
                                                       WPAS_ERROR_ADD_ERROR,
 
173
                                                       "wpa_supplicant "
 
174
                                                       "couldn't grab this "
 
175
                                                       "interface.");
 
176
                }
 
177
        }
 
178
        wpas_dbus_free_wpa_interface(&iface);
 
179
        return reply;
 
180
 
 
181
error:
 
182
        wpas_dbus_free_wpa_interface(&iface);
 
183
        return wpas_dbus_new_invalid_opts_error(message, NULL);
 
184
}
 
185
 
 
186
 
 
187
/**
 
188
 * wpas_dbus_global_remove_interface - Request deregistration of an interface
 
189
 * @message: Pointer to incoming dbus message
 
190
 * @global: wpa_supplicant global data structure
 
191
 * Returns: a dbus message containing a UINT32 indicating success (1) or
 
192
 *          failure (0), or returns a dbus error message with more information
 
193
 *
 
194
 * Handler function for "removeInterface" method call.  Handles requests
 
195
 * by dbus clients to deregister a network interface that wpa_supplicant
 
196
 * currently manages.
 
197
 */
 
198
DBusMessage * wpas_dbus_global_remove_interface(DBusMessage *message,
 
199
                                                struct wpa_global *global)
 
200
{
 
201
        struct wpa_supplicant *wpa_s;
 
202
        char *path;
 
203
        DBusMessage *reply = NULL;
 
204
 
 
205
        if (!dbus_message_get_args(message, NULL,
 
206
                                   DBUS_TYPE_OBJECT_PATH, &path,
 
207
                                   DBUS_TYPE_INVALID)) {
 
208
                reply = wpas_dbus_new_invalid_opts_error(message, NULL);
 
209
                goto out;
 
210
        }
 
211
 
 
212
        wpa_s = wpa_supplicant_get_iface_by_dbus_path(global, path);
 
213
        if (wpa_s == NULL) {
 
214
                reply = wpas_dbus_new_invalid_iface_error(message);
 
215
                goto out;
 
216
        }
 
217
 
 
218
        if (!wpa_supplicant_remove_iface(global, wpa_s)) {
 
219
                reply = wpas_dbus_new_success_reply(message);
 
220
        } else {
 
221
                reply = dbus_message_new_error(message,
 
222
                                               WPAS_ERROR_REMOVE_ERROR,
 
223
                                               "wpa_supplicant couldn't "
 
224
                                               "remove this interface.");
 
225
        }
 
226
 
 
227
out:
 
228
        return reply;
 
229
}
 
230
 
 
231
 
 
232
/**
 
233
 * wpas_dbus_global_get_interface - Get the object path for an interface name
 
234
 * @message: Pointer to incoming dbus message
 
235
 * @global: %wpa_supplicant global data structure
 
236
 * Returns: The object path of the interface object,
 
237
 *          or a dbus error message with more information
 
238
 *
 
239
 * Handler function for "getInterface" method call. Handles requests
 
240
 * by dbus clients for the object path of an specific network interface.
 
241
 */
 
242
DBusMessage * wpas_dbus_global_get_interface(DBusMessage *message,
 
243
                                             struct wpa_global *global)
 
244
{
 
245
        DBusMessage *reply = NULL;
 
246
        const char *ifname;
 
247
        const char *path;
 
248
        struct wpa_supplicant *wpa_s;
 
249
 
 
250
        if (!dbus_message_get_args(message, NULL,
 
251
                                   DBUS_TYPE_STRING, &ifname,
 
252
                                   DBUS_TYPE_INVALID)) {
 
253
                reply = wpas_dbus_new_invalid_opts_error(message, NULL);
 
254
                goto out;
 
255
        }
 
256
 
 
257
        wpa_s = wpa_supplicant_get_iface(global, ifname);
 
258
        if (wpa_s == NULL) {
 
259
                reply = wpas_dbus_new_invalid_iface_error(message);
 
260
                goto out;
 
261
        }
 
262
 
 
263
        path = wpa_supplicant_get_dbus_path(wpa_s);
 
264
        if (path == NULL) {
 
265
                reply = dbus_message_new_error(message,
 
266
                                               WPAS_ERROR_INTERNAL_ERROR,
 
267
                                               "an internal error occurred "
 
268
                                               "getting the interface.");
 
269
                goto out;
 
270
        }
 
271
 
 
272
        reply = dbus_message_new_method_return(message);
 
273
        dbus_message_append_args(reply,
 
274
                                 DBUS_TYPE_OBJECT_PATH, &path,
 
275
                                 DBUS_TYPE_INVALID);
 
276
 
 
277
out:
 
278
        return reply;
 
279
}
 
280
 
 
281
 
 
282
/**
 
283
 * wpas_dbus_iface_scan - Request a wireless scan on an interface
 
284
 * @message: Pointer to incoming dbus message
 
285
 * @wpa_s: wpa_supplicant structure for a network interface
 
286
 * Returns: a dbus message containing a UINT32 indicating success (1) or
 
287
 *          failure (0)
 
288
 *
 
289
 * Handler function for "scan" method call of a network device. Requests
 
290
 * that wpa_supplicant perform a wireless scan as soon as possible
 
291
 * on a particular wireless interface.
 
292
 */
 
293
DBusMessage * wpas_dbus_iface_scan(DBusMessage *message,
 
294
                                   struct wpa_supplicant *wpa_s)
 
295
{
 
296
        wpa_s->scan_req = 2;
 
297
        wpa_supplicant_req_scan(wpa_s, 0, 0);
 
298
        return wpas_dbus_new_success_reply(message);
 
299
}
 
300
 
 
301
 
 
302
/**
 
303
 * wpas_dbus_iface_scan_results - Get the results of a recent scan request
 
304
 * @message: Pointer to incoming dbus message
 
305
 * @wpa_s: wpa_supplicant structure for a network interface
 
306
 * Returns: a dbus message containing a dbus array of objects paths, or returns
 
307
 *          a dbus error message if not scan results could be found
 
308
 *
 
309
 * Handler function for "scanResults" method call of a network device. Returns
 
310
 * a dbus message containing the object paths of wireless networks found.
 
311
 */
 
312
DBusMessage * wpas_dbus_iface_scan_results(DBusMessage *message,
 
313
                                           struct wpa_supplicant *wpa_s)
 
314
{
 
315
        DBusMessage *reply = NULL;
 
316
        DBusMessageIter iter;
 
317
        DBusMessageIter sub_iter;
 
318
        int i;
 
319
 
 
320
        /* Ensure we've actually got scan results to return */
 
321
        if (wpa_s->scan_results == NULL &&
 
322
            wpa_supplicant_get_scan_results(wpa_s) < 0) {
 
323
                reply = dbus_message_new_error(message, WPAS_ERROR_SCAN_ERROR,
 
324
                                               "An error ocurred getting scan "
 
325
                                               "results.");
 
326
                goto out;
 
327
        }
 
328
 
 
329
        /* Create and initialize the return message */
 
330
        reply = dbus_message_new_method_return(message);
 
331
        dbus_message_iter_init_append(reply, &iter);
 
332
        dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
 
333
                                         DBUS_TYPE_OBJECT_PATH_AS_STRING,
 
334
                                         &sub_iter);
 
335
 
 
336
        /* Loop through scan results and append each result's object path */
 
337
        for (i = 0; i < wpa_s->num_scan_results; i++) {
 
338
                struct wpa_scan_result *res = &wpa_s->scan_results[i];
 
339
                char *path;
 
340
 
 
341
                path = wpa_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
 
342
                if (path == NULL) {
 
343
                        perror("wpas_dbus_iface_scan_results[dbus]: out of "
 
344
                               "memory.");
 
345
                        wpa_printf(MSG_ERROR, "dbus control interface: not "
 
346
                                   "enough memory to send scan results "
 
347
                                   "signal.");
 
348
                        break;
 
349
                }
 
350
                /* Construct the object path for this network.  Note that ':'
 
351
                 * is not a valid character in dbus object paths.
 
352
                 */
 
353
                snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
 
354
                         "%s/" WPAS_DBUS_BSSIDS_PART "/"
 
355
                         WPAS_DBUS_BSSID_FORMAT,
 
356
                         wpa_supplicant_get_dbus_path(wpa_s),
 
357
                         MAC2STR(res->bssid));
 
358
                dbus_message_iter_append_basic(&sub_iter,
 
359
                                               DBUS_TYPE_OBJECT_PATH, &path);
 
360
                free(path);
 
361
        }
 
362
 
 
363
        dbus_message_iter_close_container(&iter, &sub_iter);
 
364
 
 
365
out:
 
366
        return reply;
 
367
}
 
368
 
 
369
 
 
370
/**
 
371
 * wpas_dbus_bssid_properties - Return the properties of a scanned network
 
372
 * @message: Pointer to incoming dbus message
 
373
 * @wpa_s: wpa_supplicant structure for a network interface
 
374
 * @res: wpa_supplicant scan result for which to get properties
 
375
 * Returns: a dbus message containing the properties for the requested network
 
376
 *
 
377
 * Handler function for "properties" method call of a scanned network.
 
378
 * Returns a dbus message containing the the properties.
 
379
 */
 
380
DBusMessage * wpas_dbus_bssid_properties(DBusMessage *message,
 
381
                                         struct wpa_supplicant *wpa_s,
 
382
                                         struct wpa_scan_result *res)
 
383
{
 
384
        DBusMessage *reply = NULL;
 
385
        char *bssid_data, *ssid_data, *wpa_ie_data, *rsn_ie_data;
 
386
        DBusMessageIter iter, iter_dict;
 
387
 
 
388
        /* dbus needs the address of a pointer to the actual value
 
389
         * for array types, not the address of the value itself.
 
390
         */
 
391
        bssid_data = (char *) &res->bssid;
 
392
        ssid_data = (char *) &res->ssid;
 
393
        wpa_ie_data = (char *) &res->wpa_ie;
 
394
        rsn_ie_data = (char *) &res->rsn_ie;
 
395
 
 
396
        /* Dump the properties into a dbus message */
 
397
        reply = dbus_message_new_method_return(message);
 
398
 
 
399
        dbus_message_iter_init_append(reply, &iter);
 
400
        if (!wpa_dbus_dict_open_write(&iter, &iter_dict))
 
401
                goto error;
 
402
 
 
403
        if (!wpa_dbus_dict_append_byte_array(&iter_dict, "bssid",
 
404
                                             bssid_data, ETH_ALEN))
 
405
                goto error;
 
406
        if (!wpa_dbus_dict_append_byte_array(&iter_dict, "ssid",
 
407
                                             ssid_data, res->ssid_len))
 
408
                goto error;
 
409
        if (res->wpa_ie_len) {
 
410
                if (!wpa_dbus_dict_append_byte_array(&iter_dict, "wpaie",
 
411
                                                     wpa_ie_data,
 
412
                                                     res->wpa_ie_len)) {
 
413
                        goto error;
 
414
                }
 
415
        }
 
416
        if (res->rsn_ie_len) {
 
417
                if (!wpa_dbus_dict_append_byte_array(&iter_dict, "rsnie",
 
418
                                                     rsn_ie_data,
 
419
                                                     res->rsn_ie_len)) {
 
420
                        goto error;
 
421
                }
 
422
        }
 
423
        if (res->freq) {
 
424
                if (!wpa_dbus_dict_append_int32(&iter_dict, "frequency",
 
425
                                                res->freq))
 
426
                        goto error;
 
427
        }
 
428
        if (!wpa_dbus_dict_append_uint16(&iter_dict, "capabilities",
 
429
                                         res->caps))
 
430
                goto error;
 
431
        if (!wpa_dbus_dict_append_int32(&iter_dict, "quality", res->qual))
 
432
                goto error;
 
433
        if (!wpa_dbus_dict_append_int32(&iter_dict, "noise", res->noise))
 
434
                goto error;
 
435
        if (!wpa_dbus_dict_append_int32(&iter_dict, "level", res->level))
 
436
                goto error;
 
437
        if (!wpa_dbus_dict_append_int32(&iter_dict, "maxrate", res->maxrate))
 
438
                goto error;
 
439
 
 
440
        if (!wpa_dbus_dict_close_write(&iter, &iter_dict))
 
441
                goto error;
 
442
 
 
443
        return reply;
 
444
 
 
445
error:
 
446
        if (reply)
 
447
                dbus_message_unref(reply);
 
448
        return dbus_message_new_error(message, WPAS_ERROR_INTERNAL_ERROR,
 
449
                                      "an internal error occurred returning "
 
450
                                      "BSSID properties.");
 
451
}
 
452
 
 
453
 
 
454
/**
 
455
 * wpas_dbus_iface_capabilities - Return interface capabilities
 
456
 * @message: Pointer to incoming dbus message
 
457
 * @wpa_s: wpa_supplicant structure for a network interface
 
458
 * Returns: A dbus message containing a dict of strings
 
459
 *
 
460
 * Handler function for "capabilities" method call of an interface.
 
461
 */
 
462
DBusMessage * wpas_dbus_iface_capabilities(DBusMessage *message,
 
463
                                           struct wpa_supplicant *wpa_s)
 
464
{
 
465
        DBusMessage *reply = NULL;
 
466
        struct wpa_driver_capa capa;
 
467
        int res;
 
468
        DBusMessageIter iter, iter_dict;
 
469
        char **eap_methods;
 
470
        size_t num_items;
 
471
        dbus_bool_t strict = FALSE;
 
472
        DBusMessageIter iter_dict_entry, iter_dict_val, iter_array;
 
473
 
 
474
        if (!dbus_message_get_args(message, NULL,
 
475
                                   DBUS_TYPE_BOOLEAN, &strict,
 
476
                                   DBUS_TYPE_INVALID))
 
477
                strict = FALSE;
 
478
 
 
479
        reply = dbus_message_new_method_return(message);
 
480
 
 
481
        dbus_message_iter_init_append(reply, &iter);
 
482
        if (!wpa_dbus_dict_open_write(&iter, &iter_dict))
 
483
                goto error;
 
484
 
 
485
        /* EAP methods */
 
486
        eap_methods = eap_get_names_as_string_array(&num_items);
 
487
        if (eap_methods) {
 
488
                dbus_bool_t success = FALSE;
 
489
                size_t i = 0;
 
490
 
 
491
                success = wpa_dbus_dict_append_string_array(
 
492
                        &iter_dict, "eap", (const char **) eap_methods,
 
493
                        num_items);
 
494
 
 
495
                /* free returned method array */
 
496
                while (eap_methods[i])
 
497
                        free(eap_methods[i++]);
 
498
                free(eap_methods);
 
499
 
 
500
                if (!success)
 
501
                        goto error;
 
502
        }
 
503
 
 
504
        res = wpa_drv_get_capa(wpa_s, &capa);
 
505
 
 
506
        /***** pairwise cipher */
 
507
        if (res < 0) {
 
508
                if (!strict) {
 
509
                        const char *args[] = {"CCMP", "TKIP", "NONE"};
 
510
                        if (!wpa_dbus_dict_append_string_array(
 
511
                                    &iter_dict, "pairwise", args,
 
512
                                    sizeof(args) / sizeof(char*)))
 
513
                                goto error;
 
514
                }
 
515
        } else {
 
516
                if (!wpa_dbus_dict_begin_string_array(&iter_dict, "pairwise",
 
517
                                                      &iter_dict_entry,
 
518
                                                      &iter_dict_val,
 
519
                                                      &iter_array))
 
520
                        goto error;
 
521
 
 
522
                if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
 
523
                        if (!wpa_dbus_dict_string_array_add_element(
 
524
                                    &iter_array, "CCMP"))
 
525
                                goto error;
 
526
                }
 
527
 
 
528
                if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
 
529
                        if (!wpa_dbus_dict_string_array_add_element(
 
530
                                    &iter_array, "TKIP"))
 
531
                                goto error;
 
532
                }
 
533
 
 
534
                if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
 
535
                        if (!wpa_dbus_dict_string_array_add_element(
 
536
                                    &iter_array, "NONE"))
 
537
                                goto error;
 
538
                }
 
539
 
 
540
                if (!wpa_dbus_dict_end_string_array(&iter_dict,
 
541
                                                    &iter_dict_entry,
 
542
                                                    &iter_dict_val,
 
543
                                                    &iter_array))
 
544
                        goto error;
 
545
        }
 
546
 
 
547
        /***** group cipher */
 
548
        if (res < 0) {
 
549
                if (!strict) {
 
550
                        const char *args[] = {
 
551
                                "CCMP", "TKIP", "WEP104", "WEP40"
 
552
                        };
 
553
                        if (!wpa_dbus_dict_append_string_array(
 
554
                                    &iter_dict, "group", args,
 
555
                                    sizeof(args) / sizeof(char*)))
 
556
                                goto error;
 
557
                }
 
558
        } else {
 
559
                if (!wpa_dbus_dict_begin_string_array(&iter_dict, "group",
 
560
                                                      &iter_dict_entry,
 
561
                                                      &iter_dict_val,
 
562
                                                      &iter_array))
 
563
                        goto error;
 
564
 
 
565
                if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
 
566
                        if (!wpa_dbus_dict_string_array_add_element(
 
567
                                    &iter_array, "CCMP"))
 
568
                                goto error;
 
569
                }
 
570
 
 
571
                if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
 
572
                        if (!wpa_dbus_dict_string_array_add_element(
 
573
                                    &iter_array, "TKIP"))
 
574
                                goto error;
 
575
                }
 
576
 
 
577
                if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) {
 
578
                        if (!wpa_dbus_dict_string_array_add_element(
 
579
                                    &iter_array, "WEP104"))
 
580
                                goto error;
 
581
                }
 
582
 
 
583
                if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) {
 
584
                        if (!wpa_dbus_dict_string_array_add_element(
 
585
                                    &iter_array, "WEP40"))
 
586
                                goto error;
 
587
                }
 
588
 
 
589
                if (!wpa_dbus_dict_end_string_array(&iter_dict,
 
590
                                                    &iter_dict_entry,
 
591
                                                    &iter_dict_val,
 
592
                                                    &iter_array))
 
593
                        goto error;
 
594
        }
 
595
 
 
596
        /***** key management */
 
597
        if (res < 0) {
 
598
                if (!strict) {
 
599
                        const char *args[] = {
 
600
                                "WPA-PSK", "WPA-EAP", "IEEE8021X", "WPA-NONE",
 
601
                                "NONE"
 
602
                        };
 
603
                        if (!wpa_dbus_dict_append_string_array(
 
604
                                    &iter_dict, "key_mgmt", args,
 
605
                                    sizeof(args) / sizeof(char*)))
 
606
                                goto error;
 
607
                }
 
608
        } else {
 
609
                if (!wpa_dbus_dict_begin_string_array(&iter_dict, "key_mgmt",
 
610
                                                      &iter_dict_entry,
 
611
                                                      &iter_dict_val,
 
612
                                                      &iter_array))
 
613
                        goto error;
 
614
 
 
615
                if (!wpa_dbus_dict_string_array_add_element(&iter_array,
 
616
                                                            "NONE"))
 
617
                        goto error;
 
618
 
 
619
                if (!wpa_dbus_dict_string_array_add_element(&iter_array,
 
620
                                                            "IEEE8021X"))
 
621
                        goto error;
 
622
 
 
623
                if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
 
624
                                     WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
 
625
                        if (!wpa_dbus_dict_string_array_add_element(
 
626
                                    &iter_array, "WPA-EAP"))
 
627
                                goto error;
 
628
                }
 
629
 
 
630
                if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
 
631
                                     WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
 
632
                        if (!wpa_dbus_dict_string_array_add_element(
 
633
                                    &iter_array, "WPA-PSK"))
 
634
                                goto error;
 
635
                }
 
636
 
 
637
                if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
 
638
                        if (!wpa_dbus_dict_string_array_add_element(
 
639
                                    &iter_array, "WPA-NONE"))
 
640
                                goto error;
 
641
                }
 
642
 
 
643
                if (!wpa_dbus_dict_end_string_array(&iter_dict,
 
644
                                                    &iter_dict_entry,
 
645
                                                    &iter_dict_val,
 
646
                                                    &iter_array))
 
647
                        goto error;
 
648
        }
 
649
 
 
650
        /***** WPA protocol */
 
651
        if (res < 0) {
 
652
                if (!strict) {
 
653
                        const char *args[] = { "RSN", "WPA" };
 
654
                        if (!wpa_dbus_dict_append_string_array(
 
655
                                    &iter_dict, "proto", args,
 
656
                                    sizeof(args) / sizeof(char*)))
 
657
                                goto error;
 
658
                }
 
659
        } else {
 
660
                if (!wpa_dbus_dict_begin_string_array(&iter_dict, "proto",
 
661
                                                      &iter_dict_entry,
 
662
                                                      &iter_dict_val,
 
663
                                                      &iter_array))
 
664
                        goto error;
 
665
 
 
666
                if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
 
667
                                     WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
 
668
                        if (!wpa_dbus_dict_string_array_add_element(
 
669
                                    &iter_array, "RSN"))
 
670
                                goto error;
 
671
                }
 
672
 
 
673
                if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
 
674
                                     WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
 
675
                        if (!wpa_dbus_dict_string_array_add_element(
 
676
                                    &iter_array, "WPA"))
 
677
                                goto error;
 
678
                }
 
679
 
 
680
                if (!wpa_dbus_dict_end_string_array(&iter_dict,
 
681
                                                    &iter_dict_entry,
 
682
                                                    &iter_dict_val,
 
683
                                                    &iter_array))
 
684
                        goto error;
 
685
        }
 
686
 
 
687
        /***** auth alg */
 
688
        if (res < 0) {
 
689
                if (!strict) {
 
690
                        const char *args[] = { "OPEN", "SHARED", "LEAP" };
 
691
                        if (!wpa_dbus_dict_append_string_array(
 
692
                                    &iter_dict, "auth_alg", args,
 
693
                                    sizeof(args) / sizeof(char*)))
 
694
                                goto error;
 
695
                }
 
696
        } else {
 
697
                if (!wpa_dbus_dict_begin_string_array(&iter_dict, "auth_alg",
 
698
                                                      &iter_dict_entry,
 
699
                                                      &iter_dict_val,
 
700
                                                      &iter_array))
 
701
                        goto error;
 
702
 
 
703
                if (capa.auth & (WPA_DRIVER_AUTH_OPEN)) {
 
704
                        if (!wpa_dbus_dict_string_array_add_element(
 
705
                                    &iter_array, "OPEN"))
 
706
                                goto error;
 
707
                }
 
708
 
 
709
                if (capa.auth & (WPA_DRIVER_AUTH_SHARED)) {
 
710
                        if (!wpa_dbus_dict_string_array_add_element(
 
711
                                    &iter_array, "SHARED"))
 
712
                                goto error;
 
713
                }
 
714
 
 
715
                if (capa.auth & (WPA_DRIVER_AUTH_LEAP)) {
 
716
                        if (!wpa_dbus_dict_string_array_add_element(
 
717
                                    &iter_array, "LEAP"))
 
718
                                goto error;
 
719
                }
 
720
 
 
721
                if (!wpa_dbus_dict_end_string_array(&iter_dict,
 
722
                                                    &iter_dict_entry,
 
723
                                                    &iter_dict_val,
 
724
                                                    &iter_array))
 
725
                        goto error;
 
726
        }
 
727
 
 
728
        if (!wpa_dbus_dict_close_write(&iter, &iter_dict))
 
729
                goto error;
 
730
 
 
731
        return reply;
 
732
 
 
733
error:
 
734
        if (reply)
 
735
                dbus_message_unref(reply);
 
736
        return dbus_message_new_error(message, WPAS_ERROR_INTERNAL_ERROR,
 
737
                                      "an internal error occurred returning "
 
738
                                      "interface capabilities.");
 
739
}
 
740
 
 
741
 
 
742
/**
 
743
 * wpas_dbus_iface_add_network - Add a new configured network
 
744
 * @message: Pointer to incoming dbus message
 
745
 * @wpa_s: wpa_supplicant structure for a network interface
 
746
 * Returns: A dbus message containing the object path of the new network
 
747
 *
 
748
 * Handler function for "addNetwork" method call of a network interface.
 
749
 */
 
750
DBusMessage * wpas_dbus_iface_add_network(DBusMessage *message,
 
751
                                          struct wpa_supplicant *wpa_s)
 
752
{
 
753
        DBusMessage *reply = NULL;
 
754
        struct wpa_ssid *ssid;
 
755
        char *path = NULL;
 
756
 
 
757
        path = wpa_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
 
758
        if (path == NULL) {
 
759
                perror("wpas_dbus_iface_scan_results[dbus]: out of "
 
760
                       "memory.");
 
761
                wpa_printf(MSG_ERROR, "dbus control interface: not "
 
762
                           "enough memory to send scan results "
 
763
                           "signal.");
 
764
                goto out;
 
765
        }
 
766
 
 
767
        ssid = wpa_config_add_network(wpa_s->conf);
 
768
        if (ssid == NULL) {
 
769
                reply = dbus_message_new_error(message,
 
770
                                               WPAS_ERROR_ADD_NETWORK_ERROR,
 
771
                                               "wpa_supplicant could not add "
 
772
                                               "a network on this interface.");
 
773
                goto out;
 
774
        }
 
775
        ssid->disabled = 1;
 
776
        wpa_config_set_network_defaults(ssid);
 
777
 
 
778
        /* Construct the object path for this network. */
 
779
        snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
 
780
                 "%s/" WPAS_DBUS_NETWORKS_PART "/%d",
 
781
                 wpa_supplicant_get_dbus_path(wpa_s),
 
782
                 ssid->id);
 
783
 
 
784
        reply = dbus_message_new_method_return(message);
 
785
        dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH,
 
786
                                 &path, DBUS_TYPE_INVALID);
 
787
 
 
788
out:
 
789
        free(path);
 
790
        return reply;
 
791
}
 
792
 
 
793
 
 
794
/**
 
795
 * wpas_dbus_iface_remove_network - Remove a configured network
 
796
 * @message: Pointer to incoming dbus message
 
797
 * @wpa_s: wpa_supplicant structure for a network interface
 
798
 * Returns: A dbus message containing a UINT32 indicating success (1) or
 
799
 *          failure (0)
 
800
 *
 
801
 * Handler function for "removeNetwork" method call of a network interface.
 
802
 */
 
803
DBusMessage * wpas_dbus_iface_remove_network(DBusMessage *message,
 
804
                                             struct wpa_supplicant *wpa_s)
 
805
{
 
806
        DBusMessage *reply = NULL;
 
807
        const char *op;
 
808
        char *iface = NULL, *net_id = NULL;
 
809
        int id;
 
810
        struct wpa_ssid *ssid;
 
811
 
 
812
        if (!dbus_message_get_args(message, NULL,
 
813
                                   DBUS_TYPE_OBJECT_PATH, &op,
 
814
                                   DBUS_TYPE_INVALID)) {
 
815
                reply = wpas_dbus_new_invalid_opts_error(message, NULL);
 
816
                goto out;
 
817
        }
 
818
 
 
819
        /* Extract the network ID */
 
820
        iface = wpas_dbus_decompose_object_path(op, &net_id, NULL);
 
821
        if (iface == NULL) {
 
822
                reply = wpas_dbus_new_invalid_network_error(message);
 
823
                goto out;
 
824
        }
 
825
        /* Ensure the network is actually a child of this interface */
 
826
        if (strcmp(iface, wpa_supplicant_get_dbus_path(wpa_s)) != 0) {
 
827
                reply = wpas_dbus_new_invalid_network_error(message);
 
828
                goto out;
 
829
        }
 
830
 
 
831
        id = strtoul(net_id, NULL, 10);
 
832
        ssid = wpa_config_get_network(wpa_s->conf, id);
 
833
        if (ssid == NULL) {
 
834
                reply = wpas_dbus_new_invalid_network_error(message);
 
835
                goto out;
 
836
        }
 
837
 
 
838
        if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
 
839
                reply = dbus_message_new_error(message,
 
840
                                               WPAS_ERROR_REMOVE_NETWORK_ERROR,
 
841
                                               "error removing the specified "
 
842
                                               "on this interface.");
 
843
                goto out;
 
844
        }
 
845
 
 
846
        if (ssid == wpa_s->current_ssid)
 
847
                wpa_supplicant_disassociate(wpa_s, REASON_DEAUTH_LEAVING);
 
848
        reply = wpas_dbus_new_success_reply(message);
 
849
 
 
850
out:
 
851
        free(iface);
 
852
        free(net_id);
 
853
        return reply;
 
854
}
 
855
 
 
856
 
 
857
static const char *dont_quote[] = {
 
858
        "key_mgmt", "proto", "pairwise", "auth_alg", "group", "eap",
 
859
        "opensc_engine_path", "pkcs11_engine_path", "pkcs11_module_path",
 
860
        "bssid", NULL
 
861
};
 
862
 
 
863
static dbus_bool_t should_quote_opt(const char *key)
 
864
{
 
865
        int i = 0;
 
866
        while (dont_quote[i] != NULL) {
 
867
                if (strcmp(key, dont_quote[i]) == 0)
 
868
                        return FALSE;
 
869
                i++;
 
870
        }
 
871
        return TRUE;
 
872
}
 
873
 
 
874
/**
 
875
 * wpas_dbus_iface_set_network - Set options for a configured network
 
876
 * @message: Pointer to incoming dbus message
 
877
 * @wpa_s: wpa_supplicant structure for a network interface
 
878
 * @ssid: wpa_ssid structure for a configured network
 
879
 * Returns: a dbus message containing a UINT32 indicating success (1) or
 
880
 *          failure (0)
 
881
 *
 
882
 * Handler function for "set" method call of a configured network.
 
883
 */
 
884
DBusMessage * wpas_dbus_iface_set_network(DBusMessage *message,
 
885
                                          struct wpa_supplicant *wpa_s,
 
886
                                          struct wpa_ssid *ssid)
 
887
{
 
888
        DBusMessage *reply = NULL;
 
889
        struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
 
890
        DBusMessageIter iter, iter_dict;
 
891
 
 
892
        dbus_message_iter_init(message, &iter);
 
893
 
 
894
        if (!wpa_dbus_dict_open_read(&iter, &iter_dict)) {
 
895
                reply = wpas_dbus_new_invalid_opts_error(message, NULL);
 
896
                goto out;
 
897
        }
 
898
 
 
899
        while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
 
900
                char *value = NULL;
 
901
                size_t size = 50;
 
902
                int ret;
 
903
 
 
904
                if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) {
 
905
                        reply = wpas_dbus_new_invalid_opts_error(message,
 
906
                                                                 NULL);
 
907
                        goto out;
 
908
                }
 
909
 
 
910
                /* Type conversions, since wpa_supplicant wants strings */
 
911
                if (entry.type == DBUS_TYPE_ARRAY &&
 
912
                    entry.array_type == DBUS_TYPE_BYTE) {
 
913
                        if (entry.array_len <= 0)
 
914
                                goto error;
 
915
 
 
916
                        size = entry.array_len * 2 + 1;
 
917
                        value = wpa_zalloc(size);
 
918
                        if (value == NULL)
 
919
                                goto error;
 
920
                        ret = wpa_snprintf_hex(value, size,
 
921
                                        (u8 *) entry.bytearray_value,
 
922
                                        entry.array_len);
 
923
                        if (ret <= 0)
 
924
                                goto error;
 
925
                } else if (entry.type == DBUS_TYPE_STRING) {
 
926
                        if (should_quote_opt(entry.key)) {
 
927
                                size = strlen(entry.str_value);
 
928
                                /* Zero-length option check */
 
929
                                if (size <= 0)
 
930
                                        goto error;
 
931
                                size += 3;  /* For quotes and terminator */
 
932
                                value = wpa_zalloc(size);
 
933
                                if (value == NULL)
 
934
                                        goto error;
 
935
                                ret = snprintf(value, size, "\"%s\"",
 
936
                                                entry.str_value);
 
937
                                if (ret < 0 || (size_t) ret != (size - 1))
 
938
                                        goto error;
 
939
                        } else {
 
940
                                value = strdup(entry.str_value);
 
941
                                if (value == NULL)
 
942
                                        goto error;
 
943
                        }
 
944
                } else if (entry.type == DBUS_TYPE_UINT32) {
 
945
                        value = wpa_zalloc(size);
 
946
                        if (value == NULL)
 
947
                                goto error;
 
948
                        ret = snprintf(value, size, "%u", entry.uint32_value);
 
949
                        if (ret <= 0)
 
950
                                goto error;
 
951
                } else if (entry.type == DBUS_TYPE_INT32) {
 
952
                        value = wpa_zalloc(size);
 
953
                        if (value == NULL)
 
954
                                goto error;
 
955
                        ret = snprintf(value, size, "%d", entry.int32_value);
 
956
                        if (ret <= 0)
 
957
                                goto error;
 
958
                } else
 
959
                        goto error;
 
960
 
 
961
                if (wpa_config_set(ssid, entry.key, value, 0) < 0)
 
962
                        goto error;
 
963
 
 
964
                if ((strcmp(entry.key, "psk") == 0 &&
 
965
                     value[0] == '"' && ssid->ssid_len) ||
 
966
                    (strcmp(entry.key, "ssid") == 0 && ssid->passphrase))
 
967
                        wpa_config_update_psk(ssid);
 
968
 
 
969
                free(value);
 
970
                wpa_dbus_dict_entry_clear(&entry);
 
971
                continue;
 
972
 
 
973
        error:
 
974
                free(value);
 
975
                reply = wpas_dbus_new_invalid_opts_error(message, entry.key);
 
976
                wpa_dbus_dict_entry_clear(&entry);
 
977
                break;
 
978
        }
 
979
 
 
980
        if (!reply)
 
981
                reply = wpas_dbus_new_success_reply(message);
 
982
 
 
983
out:
 
984
        return reply;
 
985
}
 
986
 
 
987
 
 
988
/**
 
989
 * wpas_dbus_iface_enable_network - Mark a configured network as enabled
 
990
 * @message: Pointer to incoming dbus message
 
991
 * @wpa_s: wpa_supplicant structure for a network interface
 
992
 * @ssid: wpa_ssid structure for a configured network
 
993
 * Returns: A dbus message containing a UINT32 indicating success (1) or
 
994
 *          failure (0)
 
995
 *
 
996
 * Handler function for "enable" method call of a configured network.
 
997
 */
 
998
DBusMessage * wpas_dbus_iface_enable_network(DBusMessage *message,
 
999
                                             struct wpa_supplicant *wpa_s,
 
1000
                                             struct wpa_ssid *ssid)
 
1001
{
 
1002
        if (wpa_s->current_ssid == NULL && ssid->disabled) {
 
1003
                /*
 
1004
                 * Try to reassociate since there is no current configuration
 
1005
                 * and a new network was made available.
 
1006
                 */
 
1007
                wpa_s->reassociate = 1;
 
1008
                wpa_supplicant_req_scan(wpa_s, 0, 0);
 
1009
        }
 
1010
        ssid->disabled = 0;
 
1011
 
 
1012
        return wpas_dbus_new_success_reply(message);
 
1013
}
 
1014
 
 
1015
 
 
1016
/**
 
1017
 * wpas_dbus_iface_disable_network - Mark a configured network as disabled
 
1018
 * @message: Pointer to incoming dbus message
 
1019
 * @wpa_s: wpa_supplicant structure for a network interface
 
1020
 * @ssid: wpa_ssid structure for a configured network
 
1021
 * Returns: A dbus message containing a UINT32 indicating success (1) or
 
1022
 *          failure (0)
 
1023
 *
 
1024
 * Handler function for "disable" method call of a configured network.
 
1025
 */
 
1026
DBusMessage * wpas_dbus_iface_disable_network(DBusMessage *message,
 
1027
                                              struct wpa_supplicant *wpa_s,
 
1028
                                              struct wpa_ssid *ssid)
 
1029
{
 
1030
        if (ssid == wpa_s->current_ssid)
 
1031
                wpa_supplicant_disassociate(wpa_s, REASON_DEAUTH_LEAVING);
 
1032
        ssid->disabled = 1;
 
1033
 
 
1034
        return wpas_dbus_new_success_reply(message);
 
1035
}
 
1036
 
 
1037
 
 
1038
/**
 
1039
 * wpas_dbus_iface_select_network - Attempt association with a configured network
 
1040
 * @message: Pointer to incoming dbus message
 
1041
 * @wpa_s: wpa_supplicant structure for a network interface
 
1042
 * Returns: A dbus message containing a UINT32 indicating success (1) or
 
1043
 *          failure (0)
 
1044
 *
 
1045
 * Handler function for "selectNetwork" method call of network interface.
 
1046
 */
 
1047
DBusMessage * wpas_dbus_iface_select_network(DBusMessage *message,
 
1048
                                             struct wpa_supplicant *wpa_s)
 
1049
{
 
1050
        DBusMessage *reply = NULL;
 
1051
        const char *op;
 
1052
        struct wpa_ssid *ssid;
 
1053
        char *iface_obj_path = NULL;
 
1054
        char *network = NULL;
 
1055
 
 
1056
        if (strlen(dbus_message_get_signature(message)) == 0) {
 
1057
                /* Any network */
 
1058
                ssid = wpa_s->conf->ssid;
 
1059
                while (ssid) {
 
1060
                        ssid->disabled = 0;
 
1061
                        ssid = ssid->next;
 
1062
                }
 
1063
                wpa_s->reassociate = 1;
 
1064
                wpa_supplicant_req_scan(wpa_s, 0, 0);
 
1065
        } else {
 
1066
                const char *obj_path;
 
1067
                int nid;
 
1068
 
 
1069
                if (!dbus_message_get_args(message, NULL,
 
1070
                                           DBUS_TYPE_OBJECT_PATH, &op,
 
1071
                                           DBUS_TYPE_INVALID)) {
 
1072
                        reply = wpas_dbus_new_invalid_opts_error(message,
 
1073
                                                                 NULL);
 
1074
                        goto out;
 
1075
                }
 
1076
 
 
1077
                /* Extract the network number */
 
1078
                iface_obj_path = wpas_dbus_decompose_object_path(op,
 
1079
                                                                 &network,
 
1080
                                                                 NULL);
 
1081
                if (iface_obj_path == NULL) {
 
1082
                        reply = wpas_dbus_new_invalid_iface_error(message);
 
1083
                        goto out;
 
1084
                }
 
1085
                /* Ensure the object path really points to this interface */
 
1086
                obj_path = wpa_supplicant_get_dbus_path(wpa_s);
 
1087
                if (strcmp(iface_obj_path, obj_path) != 0) {
 
1088
                        reply = wpas_dbus_new_invalid_network_error(message);
 
1089
                        goto out;
 
1090
                }
 
1091
 
 
1092
                nid = strtoul(network, NULL, 10);
 
1093
                if (errno == EINVAL) {
 
1094
                        reply = wpas_dbus_new_invalid_network_error(message);
 
1095
                        goto out;
 
1096
                }
 
1097
 
 
1098
                ssid = wpa_config_get_network(wpa_s->conf, nid);
 
1099
                if (ssid == NULL) {
 
1100
                        reply = wpas_dbus_new_invalid_network_error(message);
 
1101
                        goto out;
 
1102
                }
 
1103
 
 
1104
                /* Finally, associate with the network */
 
1105
                if (ssid != wpa_s->current_ssid && wpa_s->current_ssid)
 
1106
                        wpa_supplicant_disassociate(wpa_s,
 
1107
                                                    REASON_DEAUTH_LEAVING);
 
1108
 
 
1109
                /* Mark all other networks disabled and trigger reassociation
 
1110
                 */
 
1111
                ssid = wpa_s->conf->ssid;
 
1112
                while (ssid) {
 
1113
                        ssid->disabled = (nid != ssid->id);
 
1114
                        ssid = ssid->next;
 
1115
                }
 
1116
                wpa_s->disconnected = 0;
 
1117
                wpa_s->reassociate = 1;
 
1118
                wpa_supplicant_req_scan(wpa_s, 0, 0);
 
1119
        }
 
1120
 
 
1121
        reply = wpas_dbus_new_success_reply(message);
 
1122
 
 
1123
out:
 
1124
        free(iface_obj_path);
 
1125
        free(network);
 
1126
        return reply;
 
1127
}
 
1128
 
 
1129
 
 
1130
/**
 
1131
 * wpas_dbus_iface_disconnect - Terminate the current connection
 
1132
 * @message: Pointer to incoming dbus message
 
1133
 * @wpa_s: wpa_supplicant structure for a network interface
 
1134
 * Returns: A dbus message containing a UINT32 indicating success (1) or
 
1135
 *          failure (0)
 
1136
 *
 
1137
 * Handler function for "disconnect" method call of network interface.
 
1138
 */
 
1139
DBusMessage * wpas_dbus_iface_disconnect(DBusMessage *message,
 
1140
                                         struct wpa_supplicant *wpa_s)
 
1141
{
 
1142
        wpa_s->disconnected = 1;
 
1143
        wpa_supplicant_disassociate(wpa_s, REASON_DEAUTH_LEAVING);
 
1144
 
 
1145
        return wpas_dbus_new_success_reply(message);
 
1146
}
 
1147
 
 
1148
 
 
1149
/**
 
1150
 * wpas_dbus_iface_set_ap_scan - Control roaming mode
 
1151
 * @message: Pointer to incoming dbus message
 
1152
 * @wpa_s: wpa_supplicant structure for a network interface
 
1153
 * Returns: A dbus message containing a UINT32 indicating success (1) or
 
1154
 *          failure (0)
 
1155
 *
 
1156
 * Handler function for "setAPScan" method call.
 
1157
 */
 
1158
DBusMessage * wpas_dbus_iface_set_ap_scan(DBusMessage *message,
 
1159
                                          struct wpa_supplicant *wpa_s)
 
1160
{
 
1161
        DBusMessage *reply = NULL;
 
1162
        dbus_uint32_t ap_scan = 1;
 
1163
 
 
1164
        if (!dbus_message_get_args(message, NULL, DBUS_TYPE_UINT32, &ap_scan,
 
1165
                                   DBUS_TYPE_INVALID)) {
 
1166
                reply = wpas_dbus_new_invalid_opts_error(message, NULL);
 
1167
                goto out;
 
1168
        }
 
1169
 
 
1170
        if (ap_scan > 2) {
 
1171
                reply = wpas_dbus_new_invalid_opts_error(message, NULL);
 
1172
                goto out;
 
1173
        }
 
1174
        wpa_s->conf->ap_scan = ap_scan;
 
1175
        reply = wpas_dbus_new_success_reply(message);
 
1176
 
 
1177
out:
 
1178
        return reply;
 
1179
}
 
1180
 
 
1181
 
 
1182
/**
 
1183
 * wpas_dbus_iface_get_state - Get interface state
 
1184
 * @message: Pointer to incoming dbus message
 
1185
 * @wpa_s: wpa_supplicant structure for a network interface
 
1186
 * Returns: A dbus message containing a STRING representing the current
 
1187
 *          interface state
 
1188
 *
 
1189
 * Handler function for "state" method call.
 
1190
 */
 
1191
DBusMessage * wpas_dbus_iface_get_state(DBusMessage *message,
 
1192
                                        struct wpa_supplicant *wpa_s)
 
1193
{
 
1194
        DBusMessage *reply = NULL;
 
1195
        const char *str_state;
 
1196
 
 
1197
        reply = dbus_message_new_method_return(message);
 
1198
        if (reply != NULL) {
 
1199
                str_state = wpa_supplicant_state_txt(wpa_s->wpa_state);
 
1200
                dbus_message_append_args(reply, DBUS_TYPE_STRING, &str_state,
 
1201
                                         DBUS_TYPE_INVALID);
 
1202
        }
 
1203
 
 
1204
        return reply;
 
1205
}