~ubuntu-branches/ubuntu/vivid/wpasupplicant/vivid

« back to all changes in this revision

Viewing changes to wpa_supplicant/ctrl_iface_dbus_handlers.c

  • Committer: Bazaar Package Importer
  • Author(s): Kel Modderman
  • Date: 2008-03-12 20:03:04 UTC
  • mfrom: (1.1.10 upstream)
  • mto: This revision was merged to the branch mainline in revision 4.
  • Revision ID: james.westby@ubuntu.com-20080312200304-4331y9wj46pdd34z
Tags: 0.6.3-1
* New upstream release.
* Drop patches applied upstream:
  - debian/patches/30_wpa_gui_qt4_eventhistoryui_rework.patch
  - debian/patches/31_wpa_gui_qt4_eventhistory_always_scrollbar.patch
  - debian/patches/32_wpa_gui_qt4_eventhistory_scroll_with_events.patch
  - debian/patches/40_dbus_ssid_data.patch
* Tidy up the clean target of debian/rules. Now that the madwifi headers are
  handled differently we no longer need to do any cleanup.
* Fix formatting error in debian/ifupdown/wpa_action.8 to make lintian
  quieter.
* Add patch to fix formatting errors in manpages build from sgml source. Use
  <emphasis> tags to hightlight keywords instead of surrounding them in
  strong quotes.
  - debian/patches/41_manpage_format_fixes.patch
* wpasupplicant binary package no longer suggests pcscd, guessnet, iproute
  or wireless-tools, nor does it recommend dhcp3-client. These are not
  needed.
* Add debian/patches/10_silence_siocsiwauth_icotl_failure.patch to disable
  ioctl failure messages that occur under normal conditions.
* Cherry pick two upstream git commits concerning the dbus interface:
  - debian/patches/11_avoid_dbus_version_namespace.patch
  - debian/patches/12_fix_potential_use_after_free.patch
* Add debian/patches/42_manpage_explain_available_drivers.patch to explain
  that not all of the driver backends are available in the provided
  wpa_supplicant binary, and that the canonical list of supported driver
  backends can be retrieved from the wpa_supplicant -h (help) output.
  (Closes: #466910)
* Add debian/patches/20_wpa_gui_qt4_disable_link_prl.patch to remove
  link_prl CONFIG compile flag added by qmake-qt4 >= 4.3.4-2 to avoid excess
  linking.

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