]> git.ipfire.org Git - thirdparty/hostap.git/blame - wpa_supplicant/dbus/dbus_new_handlers.c
Use a shared function for requesting a new connection
[thirdparty/hostap.git] / wpa_supplicant / dbus / dbus_new_handlers.c
CommitLineData
8fc2fb56
WS
1/*
2 * WPA Supplicant / dbus-based control interface
3 * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
7899e2f4 4 * Copyright (c) 2009-2010, Witold Sowa <witold.sowa@gmail.com>
ccd286d0 5 * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
8fc2fb56 6 *
c5a3cebf
JM
7 * This software may be distributed under the terms of the BSD license.
8 * See README for more details.
8fc2fb56
WS
9 */
10
11#include "includes.h"
12
13#include "common.h"
a206a29a
JM
14#include "common/ieee802_11_defs.h"
15#include "eap_peer/eap_methods.h"
16#include "eapol_supp/eapol_supp_sm.h"
7899e2f4 17#include "rsn_supp/wpa.h"
19b3211d
JM
18#include "../config.h"
19#include "../wpa_supplicant_i.h"
20#include "../driver_i.h"
19b3211d 21#include "../notify.h"
ccd286d0 22#include "../bss.h"
9ba9fa07 23#include "../scan.h"
e9c3c1af 24#include "../ctrl_iface.h"
7c865c68 25#include "../autoscan.h"
a206a29a
JM
26#include "dbus_new_helpers.h"
27#include "dbus_new.h"
28#include "dbus_new_handlers.h"
29#include "dbus_dict_helpers.h"
2d43d37f 30#include "dbus_common_i.h"
8fc2fb56
WS
31
32extern int wpa_debug_level;
33extern int wpa_debug_show_keys;
34extern int wpa_debug_timestamp;
35
a2753c28 36static const char *debug_strings[] = {
14dc0011 37 "excessive", "msgdump", "debug", "info", "warning", "error", NULL
a2753c28
MH
38};
39
8fc2fb56 40
8fc2fb56
WS
41/**
42 * wpas_dbus_error_unknown_error - Return a new InvalidArgs error message
43 * @message: Pointer to incoming dbus message this error refers to
44 * @arg: Optional string appended to error message
45 * Returns: a dbus error message
46 *
47 * Convenience function to create and return an UnknownError
48 */
36da1358
JM
49DBusMessage * wpas_dbus_error_unknown_error(DBusMessage *message,
50 const char *arg)
8fc2fb56 51{
8ee69e06
PS
52 /*
53 * This function can be called as a result of a failure
54 * within internal getter calls, which will call this function
55 * with a NULL message parameter. However, dbus_message_new_error
56 * looks very unkindly (i.e, abort()) on a NULL message, so
57 * in this case, we should not call it.
58 */
59 if (message == NULL) {
60 wpa_printf(MSG_INFO, "dbus: wpas_dbus_error_unknown_error "
61 "called with NULL message (arg=%s)",
62 arg ? arg : "N/A");
63 return NULL;
64 }
65
5228401c
JM
66 return dbus_message_new_error(message, WPAS_DBUS_ERROR_UNKNOWN_ERROR,
67 arg);
8fc2fb56
WS
68}
69
70
71/**
72 * wpas_dbus_error_iface_unknown - Return a new invalid interface error message
73 * @message: Pointer to incoming dbus message this error refers to
74 * Returns: A dbus error message
75 *
76 * Convenience function to create and return an invalid interface error
77 */
78static DBusMessage * wpas_dbus_error_iface_unknown(DBusMessage *message)
79{
80 return dbus_message_new_error(message, WPAS_DBUS_ERROR_IFACE_UNKNOWN,
5228401c
JM
81 "wpa_supplicant knows nothing about "
82 "this interface.");
8fc2fb56
WS
83}
84
85
86/**
87 * wpas_dbus_error_network_unknown - Return a new NetworkUnknown error message
88 * @message: Pointer to incoming dbus message this error refers to
89 * Returns: a dbus error message
90 *
91 * Convenience function to create and return an invalid network error
92 */
93static DBusMessage * wpas_dbus_error_network_unknown(DBusMessage *message)
94{
95 return dbus_message_new_error(message, WPAS_DBUS_ERROR_NETWORK_UNKNOWN,
5228401c
JM
96 "There is no such a network in this "
97 "interface.");
8fc2fb56
WS
98}
99
100
101/**
db9a76c0 102 * wpas_dbus_error_invalid_args - Return a new InvalidArgs error message
8fc2fb56
WS
103 * @message: Pointer to incoming dbus message this error refers to
104 * Returns: a dbus error message
105 *
106 * Convenience function to create and return an invalid options error
107 */
db9a76c0 108DBusMessage * wpas_dbus_error_invalid_args(DBusMessage *message,
36da1358 109 const char *arg)
8fc2fb56
WS
110{
111 DBusMessage *reply;
112
113 reply = dbus_message_new_error(message, WPAS_DBUS_ERROR_INVALID_ARGS,
5228401c
JM
114 "Did not receive correct message "
115 "arguments.");
8fc2fb56
WS
116 if (arg != NULL)
117 dbus_message_append_args(reply, DBUS_TYPE_STRING, &arg,
118 DBUS_TYPE_INVALID);
119
120 return reply;
121}
122
123
8fc2fb56
WS
124static const char *dont_quote[] = {
125 "key_mgmt", "proto", "pairwise", "auth_alg", "group", "eap",
126 "opensc_engine_path", "pkcs11_engine_path", "pkcs11_module_path",
99276998 127 "bssid", "scan_freq", "freq_list", NULL
8fc2fb56
WS
128};
129
130static dbus_bool_t should_quote_opt(const char *key)
131{
132 int i = 0;
133 while (dont_quote[i] != NULL) {
5228401c 134 if (os_strcmp(key, dont_quote[i]) == 0)
8fc2fb56
WS
135 return FALSE;
136 i++;
137 }
138 return TRUE;
139}
140
8fc2fb56
WS
141/**
142 * get_iface_by_dbus_path - Get a new network interface
143 * @global: Pointer to global data from wpa_supplicant_init()
144 * @path: Pointer to a dbus object path representing an interface
145 * Returns: Pointer to the interface or %NULL if not found
146 */
147static struct wpa_supplicant * get_iface_by_dbus_path(
148 struct wpa_global *global, const char *path)
149{
150 struct wpa_supplicant *wpa_s;
151
152 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
5228401c 153 if (os_strcmp(wpa_s->dbus_new_path, path) == 0)
8fc2fb56
WS
154 return wpa_s;
155 }
156 return NULL;
157}
158
159
160/**
161 * set_network_properties - Set properties of a configured network
aa53509f 162 * @wpa_s: wpa_supplicant structure for a network interface
8fc2fb56
WS
163 * @ssid: wpa_ssid structure for a configured network
164 * @iter: DBus message iterator containing dictionary of network
165 * properties to set.
6aeeb6fa
DW
166 * @error: On failure, an error describing the failure
167 * Returns: TRUE if the request succeeds, FALSE if it failed
8fc2fb56
WS
168 *
169 * Sets network configuration with parameters given id DBus dictionary
170 */
6aeeb6fa
DW
171dbus_bool_t set_network_properties(struct wpa_supplicant *wpa_s,
172 struct wpa_ssid *ssid,
173 DBusMessageIter *iter,
174 DBusError *error)
8fc2fb56 175{
8fc2fb56 176 struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
8fc2fb56 177 DBusMessageIter iter_dict;
6aeeb6fa 178 char *value = NULL;
8fc2fb56 179
6aeeb6fa
DW
180 if (!wpa_dbus_dict_open_read(iter, &iter_dict, error))
181 return FALSE;
8fc2fb56
WS
182
183 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
8fc2fb56
WS
184 size_t size = 50;
185 int ret;
6aeeb6fa
DW
186
187 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
188 goto error;
189
190 value = NULL;
8fc2fb56 191 if (entry.type == DBUS_TYPE_ARRAY &&
5228401c 192 entry.array_type == DBUS_TYPE_BYTE) {
8fc2fb56
WS
193 if (entry.array_len <= 0)
194 goto error;
195
196 size = entry.array_len * 2 + 1;
197 value = os_zalloc(size);
198 if (value == NULL)
199 goto error;
200
5228401c
JM
201 ret = wpa_snprintf_hex(value, size,
202 (u8 *) entry.bytearray_value,
203 entry.array_len);
8fc2fb56
WS
204 if (ret <= 0)
205 goto error;
fae3a72f
JM
206 } else if (entry.type == DBUS_TYPE_STRING) {
207 if (should_quote_opt(entry.key)) {
208 size = os_strlen(entry.str_value);
209 if (size <= 0)
210 goto error;
211
212 size += 3;
213 value = os_zalloc(size);
214 if (value == NULL)
215 goto error;
216
217 ret = os_snprintf(value, size, "\"%s\"",
218 entry.str_value);
219 if (ret < 0 || (size_t) ret != (size - 1))
220 goto error;
5228401c 221 } else {
fae3a72f
JM
222 value = os_strdup(entry.str_value);
223 if (value == NULL)
224 goto error;
8fc2fb56 225 }
fae3a72f
JM
226 } else if (entry.type == DBUS_TYPE_UINT32) {
227 value = os_zalloc(size);
228 if (value == NULL)
229 goto error;
230
231 ret = os_snprintf(value, size, "%u",
232 entry.uint32_value);
233 if (ret <= 0)
234 goto error;
235 } else if (entry.type == DBUS_TYPE_INT32) {
236 value = os_zalloc(size);
237 if (value == NULL)
238 goto error;
239
240 ret = os_snprintf(value, size, "%d",
241 entry.int32_value);
242 if (ret <= 0)
243 goto error;
244 } else
245 goto error;
8fc2fb56
WS
246
247 if (wpa_config_set(ssid, entry.key, value, 0) < 0)
248 goto error;
249
5228401c
JM
250 if ((os_strcmp(entry.key, "psk") == 0 &&
251 value[0] == '"' && ssid->ssid_len) ||
024d018b 252 (os_strcmp(entry.key, "ssid") == 0 && ssid->passphrase))
8fc2fb56 253 wpa_config_update_psk(ssid);
aa53509f
DS
254 else if (os_strcmp(entry.key, "priority") == 0)
255 wpa_config_update_prio_list(wpa_s->conf);
8fc2fb56
WS
256
257 os_free(value);
258 wpa_dbus_dict_entry_clear(&entry);
8fc2fb56 259 }
fae3a72f 260
6aeeb6fa
DW
261 return TRUE;
262
263error:
264 os_free(value);
265 wpa_dbus_dict_entry_clear(&entry);
266 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
267 "invalid message format");
268 return FALSE;
8fc2fb56
WS
269}
270
271
fcea0b7d
WS
272/**
273 * wpas_dbus_simple_property_getter - Get basic type property
6aeeb6fa 274 * @iter: Message iter to use when appending arguments
fcea0b7d
WS
275 * @type: DBus type of property (must be basic type)
276 * @val: pointer to place holding property value
6aeeb6fa
DW
277 * @error: On failure an error describing the failure
278 * Returns: TRUE if the request was successful, FALSE if it failed
fcea0b7d
WS
279 *
280 * Generic getter for basic type properties. Type is required to be basic.
281 */
6aeeb6fa
DW
282dbus_bool_t wpas_dbus_simple_property_getter(DBusMessageIter *iter,
283 const int type,
284 const void *val,
285 DBusError *error)
fcea0b7d 286{
6aeeb6fa 287 DBusMessageIter variant_iter;
fcea0b7d
WS
288
289 if (!dbus_type_is_basic(type)) {
6aeeb6fa
DW
290 dbus_set_error(error, DBUS_ERROR_FAILED,
291 "%s: given type is not basic", __func__);
292 return FALSE;
fcea0b7d
WS
293 }
294
6aeeb6fa
DW
295 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
296 wpa_dbus_type_as_string(type),
297 &variant_iter))
298 goto error;
fcea0b7d 299
6aeeb6fa
DW
300 if (!dbus_message_iter_append_basic(&variant_iter, type, val))
301 goto error;
302
303 if (!dbus_message_iter_close_container(iter, &variant_iter))
304 goto error;
305
306 return TRUE;
307
308error:
309 dbus_set_error(error, DBUS_ERROR_FAILED,
310 "%s: error constructing reply", __func__);
311 return FALSE;
fcea0b7d
WS
312}
313
314
315/**
316 * wpas_dbus_simple_property_setter - Set basic type property
317 * @message: Pointer to incoming dbus message
318 * @type: DBus type of property (must be basic type)
319 * @val: pointer to place where value being set will be stored
6aeeb6fa 320 * Returns: TRUE if the request was successful, FALSE if it failed
fcea0b7d
WS
321 *
322 * Generic setter for basic type properties. Type is required to be basic.
323 */
6aeeb6fa
DW
324dbus_bool_t wpas_dbus_simple_property_setter(DBusMessageIter *iter,
325 DBusError *error,
326 const int type, void *val)
fcea0b7d 327{
6aeeb6fa 328 DBusMessageIter variant_iter;
fcea0b7d
WS
329
330 if (!dbus_type_is_basic(type)) {
6aeeb6fa
DW
331 dbus_set_error(error, DBUS_ERROR_FAILED,
332 "%s: given type is not basic", __func__);
333 return FALSE;
fcea0b7d
WS
334 }
335
6aeeb6fa
DW
336 /* Look at the new value */
337 dbus_message_iter_recurse(iter, &variant_iter);
fcea0b7d 338 if (dbus_message_iter_get_arg_type(&variant_iter) != type) {
6aeeb6fa
DW
339 dbus_set_error_const(error, DBUS_ERROR_FAILED,
340 "wrong property type");
341 return FALSE;
fcea0b7d
WS
342 }
343 dbus_message_iter_get_basic(&variant_iter, val);
344
6aeeb6fa 345 return TRUE;
fcea0b7d
WS
346}
347
348
349/**
350 * wpas_dbus_simple_array_property_getter - Get array type property
6aeeb6fa 351 * @iter: Pointer to incoming dbus message iterator
fcea0b7d
WS
352 * @type: DBus type of property array elements (must be basic type)
353 * @array: pointer to array of elements to put into response message
354 * @array_len: length of above array
6aeeb6fa
DW
355 * @error: a pointer to an error to fill on failure
356 * Returns: TRUE if the request succeeded, FALSE if it failed
fcea0b7d
WS
357 *
358 * Generic getter for array type properties. Array elements type is
359 * required to be basic.
360 */
6aeeb6fa
DW
361dbus_bool_t wpas_dbus_simple_array_property_getter(DBusMessageIter *iter,
362 const int type,
363 const void *array,
364 size_t array_len,
365 DBusError *error)
fcea0b7d 366{
6aeeb6fa 367 DBusMessageIter variant_iter, array_iter;
fcea0b7d
WS
368 char type_str[] = "a?"; /* ? will be replaced with subtype letter; */
369 const char *sub_type_str;
370 size_t element_size, i;
371
372 if (!dbus_type_is_basic(type)) {
6aeeb6fa
DW
373 dbus_set_error(error, DBUS_ERROR_FAILED,
374 "%s: given type is not basic", __func__);
375 return FALSE;
fcea0b7d
WS
376 }
377
97d3f8c3 378 sub_type_str = wpa_dbus_type_as_string(type);
fcea0b7d
WS
379 type_str[1] = sub_type_str[0];
380
6aeeb6fa
DW
381 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
382 type_str, &variant_iter)) {
383 dbus_set_error(error, DBUS_ERROR_FAILED,
384 "%s: failed to construct message 1", __func__);
385 return FALSE;
fcea0b7d
WS
386 }
387
6aeeb6fa 388 if (!dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
fcea0b7d 389 sub_type_str, &array_iter)) {
6aeeb6fa
DW
390 dbus_set_error(error, DBUS_ERROR_FAILED,
391 "%s: failed to construct message 2", __func__);
392 return FALSE;
fcea0b7d
WS
393 }
394
395 switch(type) {
396 case DBUS_TYPE_BYTE:
397 case DBUS_TYPE_BOOLEAN:
398 element_size = 1;
399 break;
400 case DBUS_TYPE_INT16:
401 case DBUS_TYPE_UINT16:
402 element_size = sizeof(uint16_t);
403 break;
404 case DBUS_TYPE_INT32:
405 case DBUS_TYPE_UINT32:
406 element_size = sizeof(uint32_t);
407 break;
408 case DBUS_TYPE_INT64:
409 case DBUS_TYPE_UINT64:
410 element_size = sizeof(uint64_t);
411 break;
412 case DBUS_TYPE_DOUBLE:
413 element_size = sizeof(double);
414 break;
415 case DBUS_TYPE_STRING:
416 case DBUS_TYPE_OBJECT_PATH:
417 element_size = sizeof(char *);
418 break;
419 default:
6aeeb6fa
DW
420 dbus_set_error(error, DBUS_ERROR_FAILED,
421 "%s: unknown element type %d", __func__, type);
422 return FALSE;
fcea0b7d
WS
423 }
424
425 for (i = 0; i < array_len; i++) {
426 dbus_message_iter_append_basic(&array_iter, type,
427 array + i * element_size);
428 }
429
6aeeb6fa
DW
430 if (!dbus_message_iter_close_container(&variant_iter, &array_iter)) {
431 dbus_set_error(error, DBUS_ERROR_FAILED,
432 "%s: failed to construct message 3", __func__);
433 return FALSE;
fcea0b7d
WS
434 }
435
6aeeb6fa
DW
436 if (!dbus_message_iter_close_container(iter, &variant_iter)) {
437 dbus_set_error(error, DBUS_ERROR_FAILED,
438 "%s: failed to construct message 4", __func__);
96c4f3a7
JS
439 return FALSE;
440 }
441
442 return TRUE;
443}
444
445
446/**
447 * wpas_dbus_simple_array_array_property_getter - Get array array type property
448 * @iter: Pointer to incoming dbus message iterator
449 * @type: DBus type of property array elements (must be basic type)
450 * @array: pointer to array of elements to put into response message
451 * @array_len: length of above array
452 * @error: a pointer to an error to fill on failure
453 * Returns: TRUE if the request succeeded, FALSE if it failed
454 *
455 * Generic getter for array type properties. Array elements type is
456 * required to be basic.
457 */
458dbus_bool_t wpas_dbus_simple_array_array_property_getter(DBusMessageIter *iter,
459 const int type,
460 struct wpabuf **array,
461 size_t array_len,
462 DBusError *error)
463{
464 DBusMessageIter variant_iter, array_iter;
465 char type_str[] = "aa?";
466 char inner_type_str[] = "a?";
467 const char *sub_type_str;
468 size_t i;
469
470 if (!dbus_type_is_basic(type)) {
471 dbus_set_error(error, DBUS_ERROR_FAILED,
472 "%s: given type is not basic", __func__);
473 return FALSE;
474 }
475
476 sub_type_str = wpa_dbus_type_as_string(type);
477 type_str[2] = sub_type_str[0];
478 inner_type_str[1] = sub_type_str[0];
479
480 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
481 type_str, &variant_iter)) {
482 dbus_set_error(error, DBUS_ERROR_FAILED,
483 "%s: failed to construct message 1", __func__);
484 return FALSE;
485 }
486 if (!dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
487 inner_type_str, &array_iter)) {
488 dbus_set_error(error, DBUS_ERROR_FAILED,
489 "%s: failed to construct message 2", __func__);
490 return FALSE;
491 }
492
493 for (i = 0; i < array_len; i++) {
494 wpa_dbus_dict_bin_array_add_element(&array_iter,
495 wpabuf_head(array[i]),
496 wpabuf_len(array[i]));
497
498 }
499
500 if (!dbus_message_iter_close_container(&variant_iter, &array_iter)) {
501 dbus_set_error(error, DBUS_ERROR_FAILED,
502 "%s: failed to close message 2", __func__);
503 return FALSE;
504 }
505
506 if (!dbus_message_iter_close_container(iter, &variant_iter)) {
507 dbus_set_error(error, DBUS_ERROR_FAILED,
508 "%s: failed to close message 1", __func__);
6aeeb6fa
DW
509 return FALSE;
510 }
511
512 return TRUE;
fcea0b7d
WS
513}
514
515
8fc2fb56
WS
516/**
517 * wpas_dbus_handler_create_interface - Request registration of a network iface
518 * @message: Pointer to incoming dbus message
519 * @global: %wpa_supplicant global data structure
520 * Returns: The object path of the new interface object,
521 * or a dbus error message with more information
522 *
2f00ad44 523 * Handler function for "CreateInterface" method call. Handles requests
8fc2fb56
WS
524 * by dbus clients to register a network interface that wpa_supplicant
525 * will manage.
526 */
527DBusMessage * wpas_dbus_handler_create_interface(DBusMessage *message,
5228401c 528 struct wpa_global *global)
8fc2fb56 529{
8fc2fb56
WS
530 DBusMessageIter iter_dict;
531 DBusMessage *reply = NULL;
532 DBusMessageIter iter;
533 struct wpa_dbus_dict_entry entry;
2f00ad44
JM
534 char *driver = NULL;
535 char *ifname = NULL;
d4c1ec56 536 char *confname = NULL;
2f00ad44 537 char *bridge_ifname = NULL;
8fc2fb56
WS
538
539 dbus_message_iter_init(message, &iter);
540
6aeeb6fa 541 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
8fc2fb56
WS
542 goto error;
543 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
544 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
545 goto error;
024d018b 546 if (!os_strcmp(entry.key, "Driver") &&
5228401c 547 (entry.type == DBUS_TYPE_STRING)) {
2f00ad44
JM
548 driver = os_strdup(entry.str_value);
549 wpa_dbus_dict_entry_clear(&entry);
550 if (driver == NULL)
8fc2fb56 551 goto error;
024d018b 552 } else if (!os_strcmp(entry.key, "Ifname") &&
8fc2fb56 553 (entry.type == DBUS_TYPE_STRING)) {
2f00ad44
JM
554 ifname = os_strdup(entry.str_value);
555 wpa_dbus_dict_entry_clear(&entry);
556 if (ifname == NULL)
8fc2fb56 557 goto error;
024d018b 558 } else if (!os_strcmp(entry.key, "ConfigFile") &&
d4c1ec56
SL
559 (entry.type == DBUS_TYPE_STRING)) {
560 confname = os_strdup(entry.str_value);
561 wpa_dbus_dict_entry_clear(&entry);
562 if (confname == NULL)
563 goto error;
024d018b 564 } else if (!os_strcmp(entry.key, "BridgeIfname") &&
8fc2fb56 565 (entry.type == DBUS_TYPE_STRING)) {
2f00ad44
JM
566 bridge_ifname = os_strdup(entry.str_value);
567 wpa_dbus_dict_entry_clear(&entry);
568 if (bridge_ifname == NULL)
8fc2fb56 569 goto error;
5228401c 570 } else {
8fc2fb56
WS
571 wpa_dbus_dict_entry_clear(&entry);
572 goto error;
573 }
8fc2fb56
WS
574 }
575
2f00ad44
JM
576 if (ifname == NULL)
577 goto error; /* Required Ifname argument missing */
578
8fc2fb56
WS
579 /*
580 * Try to get the wpa_supplicant record for this iface, return
581 * an error if we already control it.
582 */
2f00ad44 583 if (wpa_supplicant_get_iface(global, ifname) != NULL) {
8fc2fb56
WS
584 reply = dbus_message_new_error(message,
585 WPAS_DBUS_ERROR_IFACE_EXISTS,
586 "wpa_supplicant already "
587 "controls this interface.");
588 } else {
589 struct wpa_supplicant *wpa_s;
2f00ad44
JM
590 struct wpa_interface iface;
591 os_memset(&iface, 0, sizeof(iface));
592 iface.driver = driver;
593 iface.ifname = ifname;
d4c1ec56 594 iface.confname = confname;
2f00ad44 595 iface.bridge_ifname = bridge_ifname;
8fc2fb56
WS
596 /* Otherwise, have wpa_supplicant attach to it. */
597 if ((wpa_s = wpa_supplicant_add_iface(global, &iface))) {
c49cf2d6 598 const char *path = wpa_s->dbus_new_path;
8fc2fb56
WS
599 reply = dbus_message_new_method_return(message);
600 dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH,
601 &path, DBUS_TYPE_INVALID);
602 } else {
5228401c
JM
603 reply = wpas_dbus_error_unknown_error(
604 message, "wpa_supplicant couldn't grab this "
605 "interface.");
8fc2fb56
WS
606 }
607 }
2f00ad44
JM
608
609out:
610 os_free(driver);
611 os_free(ifname);
21270bb4 612 os_free(confname);
2f00ad44 613 os_free(bridge_ifname);
8fc2fb56
WS
614 return reply;
615
616error:
db9a76c0 617 reply = wpas_dbus_error_invalid_args(message, NULL);
2f00ad44 618 goto out;
8fc2fb56
WS
619}
620
621
622/**
623 * wpas_dbus_handler_remove_interface - Request deregistration of an interface
624 * @message: Pointer to incoming dbus message
625 * @global: wpa_supplicant global data structure
626 * Returns: a dbus message containing a UINT32 indicating success (1) or
627 * failure (0), or returns a dbus error message with more information
628 *
629 * Handler function for "removeInterface" method call. Handles requests
630 * by dbus clients to deregister a network interface that wpa_supplicant
631 * currently manages.
632 */
633DBusMessage * wpas_dbus_handler_remove_interface(DBusMessage *message,
5228401c 634 struct wpa_global *global)
8fc2fb56
WS
635{
636 struct wpa_supplicant *wpa_s;
637 char *path;
638 DBusMessage *reply = NULL;
639
640 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path,
5228401c 641 DBUS_TYPE_INVALID);
8fc2fb56
WS
642
643 wpa_s = get_iface_by_dbus_path(global, path);
5228401c 644 if (wpa_s == NULL)
8fc2fb56 645 reply = wpas_dbus_error_iface_unknown(message);
df509539 646 else if (wpa_supplicant_remove_iface(global, wpa_s, 0)) {
5228401c
JM
647 reply = wpas_dbus_error_unknown_error(
648 message, "wpa_supplicant couldn't remove this "
649 "interface.");
8fc2fb56
WS
650 }
651
652 return reply;
653}
654
655
656/**
657 * wpas_dbus_handler_get_interface - Get the object path for an interface name
658 * @message: Pointer to incoming dbus message
659 * @global: %wpa_supplicant global data structure
660 * Returns: The object path of the interface object,
661 * or a dbus error message with more information
662 *
663 * Handler function for "getInterface" method call.
664 */
665DBusMessage * wpas_dbus_handler_get_interface(DBusMessage *message,
5228401c 666 struct wpa_global *global)
8fc2fb56
WS
667{
668 DBusMessage *reply = NULL;
669 const char *ifname;
670 const char *path;
671 struct wpa_supplicant *wpa_s;
672
673 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &ifname,
5228401c 674 DBUS_TYPE_INVALID);
8fc2fb56
WS
675
676 wpa_s = wpa_supplicant_get_iface(global, ifname);
5228401c
JM
677 if (wpa_s == NULL)
678 return wpas_dbus_error_iface_unknown(message);
8fc2fb56 679
c49cf2d6 680 path = wpa_s->dbus_new_path;
8fc2fb56 681 reply = dbus_message_new_method_return(message);
c2b8c674 682 if (reply == NULL)
5228401c
JM
683 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
684 NULL);
8fc2fb56 685 if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
5228401c 686 DBUS_TYPE_INVALID)) {
8fc2fb56 687 dbus_message_unref(reply);
5228401c
JM
688 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
689 NULL);
8fc2fb56
WS
690 }
691
8fc2fb56
WS
692 return reply;
693}
694
695
696/**
db9133ac 697 * wpas_dbus_getter_debug_level - Get debug level
6aeeb6fa
DW
698 * @iter: Pointer to incoming dbus message iter
699 * @error: Location to store error on failure
700 * @user_data: Function specific data
701 * Returns: TRUE on success, FALSE on failure
8fc2fb56 702 *
db9133ac 703 * Getter for "DebugLevel" property.
8fc2fb56 704 */
6aeeb6fa
DW
705dbus_bool_t wpas_dbus_getter_debug_level(DBusMessageIter *iter,
706 DBusError *error,
707 void *user_data)
8fc2fb56 708{
a2753c28
MH
709 const char *str;
710 int idx = wpa_debug_level;
6aeeb6fa 711
a2753c28
MH
712 if (idx < 0)
713 idx = 0;
14dc0011
PS
714 if (idx > 5)
715 idx = 5;
a2753c28 716 str = debug_strings[idx];
6aeeb6fa
DW
717 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
718 &str, error);
db9133ac 719}
8fc2fb56 720
8fc2fb56 721
db9133ac
WS
722/**
723 * wpas_dbus_getter_debug_timestamp - Get debug timestamp
6aeeb6fa
DW
724 * @iter: Pointer to incoming dbus message iter
725 * @error: Location to store error on failure
726 * @user_data: Function specific data
727 * Returns: TRUE on success, FALSE on failure
db9133ac
WS
728 *
729 * Getter for "DebugTimestamp" property.
730 */
6aeeb6fa
DW
731dbus_bool_t wpas_dbus_getter_debug_timestamp(DBusMessageIter *iter,
732 DBusError *error,
733 void *user_data)
db9133ac 734{
6aeeb6fa
DW
735 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
736 &wpa_debug_timestamp, error);
8fc2fb56 737
db9133ac 738}
8fc2fb56 739
8fc2fb56 740
db9133ac
WS
741/**
742 * wpas_dbus_getter_debug_show_keys - Get debug show keys
6aeeb6fa
DW
743 * @iter: Pointer to incoming dbus message iter
744 * @error: Location to store error on failure
745 * @user_data: Function specific data
746 * Returns: TRUE on success, FALSE on failure
db9133ac
WS
747 *
748 * Getter for "DebugShowKeys" property.
749 */
6aeeb6fa
DW
750dbus_bool_t wpas_dbus_getter_debug_show_keys(DBusMessageIter *iter,
751 DBusError *error,
752 void *user_data)
db9133ac 753{
6aeeb6fa
DW
754 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
755 &wpa_debug_show_keys, error);
8fc2fb56 756
db9133ac 757}
8fc2fb56 758
db9133ac
WS
759/**
760 * wpas_dbus_setter_debug_level - Set debug level
6aeeb6fa
DW
761 * @iter: Pointer to incoming dbus message iter
762 * @error: Location to store error on failure
763 * @user_data: Function specific data
764 * Returns: TRUE on success, FALSE on failure
db9133ac
WS
765 *
766 * Setter for "DebugLevel" property.
767 */
6aeeb6fa
DW
768dbus_bool_t wpas_dbus_setter_debug_level(DBusMessageIter *iter,
769 DBusError *error, void *user_data)
db9133ac 770{
6aeeb6fa 771 struct wpa_global *global = user_data;
a2753c28
MH
772 const char *str = NULL;
773 int i, val = -1;
8fc2fb56 774
6aeeb6fa
DW
775 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
776 &str))
777 return FALSE;
db9133ac 778
a2753c28
MH
779 for (i = 0; debug_strings[i]; i++)
780 if (os_strcmp(debug_strings[i], str) == 0) {
781 val = i;
782 break;
783 }
784
785 if (val < 0 ||
786 wpa_supplicant_set_debug_params(global, val, wpa_debug_timestamp,
db9133ac 787 wpa_debug_show_keys)) {
6aeeb6fa
DW
788 dbus_set_error_const(error, DBUS_ERROR_FAILED, "wrong debug "
789 "level value");
790 return FALSE;
8fc2fb56
WS
791 }
792
6aeeb6fa 793 return TRUE;
8fc2fb56
WS
794}
795
796
797/**
db9133ac 798 * wpas_dbus_setter_debug_timestamp - Set debug timestamp
6aeeb6fa
DW
799 * @iter: Pointer to incoming dbus message iter
800 * @error: Location to store error on failure
801 * @user_data: Function specific data
802 * Returns: TRUE on success, FALSE on failure
8fc2fb56 803 *
db9133ac 804 * Setter for "DebugTimestamp" property.
8fc2fb56 805 */
6aeeb6fa
DW
806dbus_bool_t wpas_dbus_setter_debug_timestamp(DBusMessageIter *iter,
807 DBusError *error,
808 void *user_data)
8fc2fb56 809{
6aeeb6fa 810 struct wpa_global *global = user_data;
db9133ac 811 dbus_bool_t val;
8fc2fb56 812
6aeeb6fa
DW
813 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
814 &val))
815 return FALSE;
8fc2fb56 816
db9133ac
WS
817 wpa_supplicant_set_debug_params(global, wpa_debug_level, val ? 1 : 0,
818 wpa_debug_show_keys);
6aeeb6fa 819 return TRUE;
db9133ac 820}
8fc2fb56 821
8fc2fb56 822
db9133ac
WS
823/**
824 * wpas_dbus_setter_debug_show_keys - Set debug show keys
6aeeb6fa
DW
825 * @iter: Pointer to incoming dbus message iter
826 * @error: Location to store error on failure
827 * @user_data: Function specific data
828 * Returns: TRUE on success, FALSE on failure
db9133ac
WS
829 *
830 * Setter for "DebugShowKeys" property.
831 */
6aeeb6fa
DW
832dbus_bool_t wpas_dbus_setter_debug_show_keys(DBusMessageIter *iter,
833 DBusError *error,
834 void *user_data)
db9133ac 835{
6aeeb6fa 836 struct wpa_global *global = user_data;
db9133ac 837 dbus_bool_t val;
8fc2fb56 838
6aeeb6fa
DW
839 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
840 &val))
841 return FALSE;
8fc2fb56 842
db9133ac
WS
843 wpa_supplicant_set_debug_params(global, wpa_debug_level,
844 wpa_debug_timestamp,
845 val ? 1 : 0);
6aeeb6fa 846 return TRUE;
8fc2fb56
WS
847}
848
849
850/**
851 * wpas_dbus_getter_interfaces - Request registered interfaces list
6aeeb6fa
DW
852 * @iter: Pointer to incoming dbus message iter
853 * @error: Location to store error on failure
854 * @user_data: Function specific data
855 * Returns: TRUE on success, FALSE on failure
8fc2fb56
WS
856 *
857 * Getter for "Interfaces" property. Handles requests
858 * by dbus clients to return list of registered interfaces objects
859 * paths
860 */
6aeeb6fa
DW
861dbus_bool_t wpas_dbus_getter_interfaces(DBusMessageIter *iter,
862 DBusError *error,
863 void *user_data)
8fc2fb56 864{
6aeeb6fa 865 struct wpa_global *global = user_data;
8fc2fb56 866 struct wpa_supplicant *wpa_s;
fcea0b7d
WS
867 const char **paths;
868 unsigned int i = 0, num = 0;
6aeeb6fa 869 dbus_bool_t success;
8fc2fb56 870
fcea0b7d
WS
871 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
872 num++;
8fc2fb56 873
f9884c09 874 paths = os_calloc(num, sizeof(char *));
fcea0b7d 875 if (!paths) {
6aeeb6fa
DW
876 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
877 return FALSE;
8fc2fb56
WS
878 }
879
fcea0b7d 880 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
5b49c9d5 881 paths[i++] = wpa_s->dbus_new_path;
8fc2fb56 882
6aeeb6fa
DW
883 success = wpas_dbus_simple_array_property_getter(iter,
884 DBUS_TYPE_OBJECT_PATH,
885 paths, num, error);
8fc2fb56 886
fcea0b7d 887 os_free(paths);
6aeeb6fa 888 return success;
8fc2fb56
WS
889}
890
891
892/**
893 * wpas_dbus_getter_eap_methods - Request supported EAP methods list
6aeeb6fa
DW
894 * @iter: Pointer to incoming dbus message iter
895 * @error: Location to store error on failure
896 * @user_data: Function specific data
897 * Returns: TRUE on success, FALSE on failure
8fc2fb56
WS
898 *
899 * Getter for "EapMethods" property. Handles requests
900 * by dbus clients to return list of strings with supported EAP methods
901 */
6aeeb6fa
DW
902dbus_bool_t wpas_dbus_getter_eap_methods(DBusMessageIter *iter,
903 DBusError *error, void *user_data)
8fc2fb56 904{
8fc2fb56 905 char **eap_methods;
fcea0b7d 906 size_t num_items = 0;
6aeeb6fa 907 dbus_bool_t success;
8fc2fb56
WS
908
909 eap_methods = eap_get_names_as_string_array(&num_items);
fcea0b7d 910 if (!eap_methods) {
6aeeb6fa
DW
911 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
912 return FALSE;
8fc2fb56
WS
913 }
914
6aeeb6fa
DW
915 success = wpas_dbus_simple_array_property_getter(iter,
916 DBUS_TYPE_STRING,
917 eap_methods,
918 num_items, error);
8fc2fb56 919
fcea0b7d
WS
920 while (num_items)
921 os_free(eap_methods[--num_items]);
922 os_free(eap_methods);
6aeeb6fa 923 return success;
8fc2fb56
WS
924}
925
926
1634ac06
DW
927/**
928 * wpas_dbus_getter_global_capabilities - Request supported global capabilities
929 * @iter: Pointer to incoming dbus message iter
930 * @error: Location to store error on failure
931 * @user_data: Function specific data
932 * Returns: TRUE on success, FALSE on failure
933 *
934 * Getter for "Capabilities" property. Handles requests by dbus clients to
935 * return a list of strings with supported capabilities like AP, RSN IBSS,
936 * and P2P that are determined at compile time.
937 */
938dbus_bool_t wpas_dbus_getter_global_capabilities(DBusMessageIter *iter,
939 DBusError *error,
940 void *user_data)
941{
942 const char *capabilities[5] = { NULL, NULL, NULL, NULL, NULL };
943 size_t num_items = 0;
944
945#ifdef CONFIG_AP
946 capabilities[num_items++] = "ap";
947#endif /* CONFIG_AP */
948#ifdef CONFIG_IBSS_RSN
949 capabilities[num_items++] = "ibss-rsn";
950#endif /* CONFIG_IBSS_RSN */
951#ifdef CONFIG_P2P
952 capabilities[num_items++] = "p2p";
953#endif /* CONFIG_P2P */
954#ifdef CONFIG_INTERWORKING
955 capabilities[num_items++] = "interworking";
956#endif /* CONFIG_INTERWORKING */
957
958 return wpas_dbus_simple_array_property_getter(iter,
959 DBUS_TYPE_STRING,
960 capabilities,
961 num_items, error);
962}
963
964
d401b48f
JM
965static int wpas_dbus_get_scan_type(DBusMessage *message, DBusMessageIter *var,
966 char **type, DBusMessage **reply)
8fc2fb56 967{
d401b48f
JM
968 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_STRING) {
969 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
970 "Type must be a string");
db9a76c0 971 *reply = wpas_dbus_error_invalid_args(
d401b48f
JM
972 message, "Wrong Type value type. String required");
973 return -1;
974 }
975 dbus_message_iter_get_basic(var, type);
976 return 0;
977}
8fc2fb56 978
8fc2fb56 979
d401b48f
JM
980static int wpas_dbus_get_scan_ssids(DBusMessage *message, DBusMessageIter *var,
981 struct wpa_driver_scan_params *params,
982 DBusMessage **reply)
983{
984 struct wpa_driver_scan_ssid *ssids = params->ssids;
985 size_t ssids_num = 0;
986 u8 *ssid;
987 DBusMessageIter array_iter, sub_array_iter;
988 char *val;
989 int len;
8fc2fb56 990
d401b48f
JM
991 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
992 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: ssids "
993 "must be an array of arrays of bytes");
db9a76c0 994 *reply = wpas_dbus_error_invalid_args(
d401b48f
JM
995 message, "Wrong SSIDs value type. Array of arrays of "
996 "bytes required");
997 return -1;
998 }
8fc2fb56 999
d401b48f 1000 dbus_message_iter_recurse(var, &array_iter);
8fc2fb56 1001
d401b48f
JM
1002 if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY ||
1003 dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_BYTE)
1004 {
1005 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: ssids "
1006 "must be an array of arrays of bytes");
db9a76c0 1007 *reply = wpas_dbus_error_invalid_args(
d401b48f
JM
1008 message, "Wrong SSIDs value type. Array of arrays of "
1009 "bytes required");
1010 return -1;
1011 }
8fc2fb56 1012
d401b48f
JM
1013 while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_ARRAY)
1014 {
1015 if (ssids_num >= WPAS_MAX_SCAN_SSIDS) {
1016 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1017 "Too many ssids specified on scan dbus "
1018 "call");
db9a76c0 1019 *reply = wpas_dbus_error_invalid_args(
d401b48f
JM
1020 message, "Too many ssids specified. Specify "
1021 "at most four");
1022 return -1;
1023 }
8fc2fb56 1024
d401b48f 1025 dbus_message_iter_recurse(&array_iter, &sub_array_iter);
8fc2fb56 1026
d401b48f 1027 dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len);
8fc2fb56 1028
f9121813
SL
1029 if (len > MAX_SSID_LEN) {
1030 wpa_printf(MSG_DEBUG,
1031 "wpas_dbus_handler_scan[dbus]: "
1032 "SSID too long (len=%d max_len=%d)",
1033 len, MAX_SSID_LEN);
1034 *reply = wpas_dbus_error_invalid_args(
1035 message, "Invalid SSID: too long");
1036 return -1;
1037 }
1038
556522ee
DK
1039 if (len != 0) {
1040 ssid = os_malloc(len);
1041 if (ssid == NULL) {
1042 wpa_printf(MSG_DEBUG,
1043 "wpas_dbus_handler_scan[dbus]: "
1044 "out of memory. Cannot allocate "
1045 "memory for SSID");
1046 *reply = dbus_message_new_error(
1047 message, DBUS_ERROR_NO_MEMORY, NULL);
1048 return -1;
1049 }
1050 os_memcpy(ssid, val, len);
1051 } else {
1052 /* Allow zero-length SSIDs */
1053 ssid = NULL;
d401b48f 1054 }
556522ee 1055
d401b48f
JM
1056 ssids[ssids_num].ssid = ssid;
1057 ssids[ssids_num].ssid_len = len;
5228401c 1058
d401b48f
JM
1059 dbus_message_iter_next(&array_iter);
1060 ssids_num++;
1061 }
8fc2fb56 1062
d401b48f
JM
1063 params->num_ssids = ssids_num;
1064 return 0;
1065}
8fc2fb56 1066
8fc2fb56 1067
d401b48f
JM
1068static int wpas_dbus_get_scan_ies(DBusMessage *message, DBusMessageIter *var,
1069 struct wpa_driver_scan_params *params,
1070 DBusMessage **reply)
1071{
1072 u8 *ies = NULL, *nies;
1073 int ies_len = 0;
1074 DBusMessageIter array_iter, sub_array_iter;
1075 char *val;
1076 int len;
8fc2fb56 1077
d401b48f
JM
1078 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
1079 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: ies must "
1080 "be an array of arrays of bytes");
db9a76c0 1081 *reply = wpas_dbus_error_invalid_args(
d401b48f
JM
1082 message, "Wrong IEs value type. Array of arrays of "
1083 "bytes required");
1084 return -1;
1085 }
8fc2fb56 1086
d401b48f 1087 dbus_message_iter_recurse(var, &array_iter);
8fc2fb56 1088
d401b48f
JM
1089 if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY ||
1090 dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_BYTE)
1091 {
1092 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: ies must "
1093 "be an array of arrays of bytes");
db9a76c0 1094 *reply = wpas_dbus_error_invalid_args(
d401b48f
JM
1095 message, "Wrong IEs value type. Array required");
1096 return -1;
1097 }
8fc2fb56 1098
d401b48f
JM
1099 while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_ARRAY)
1100 {
1101 dbus_message_iter_recurse(&array_iter, &sub_array_iter);
8fc2fb56 1102
d401b48f
JM
1103 dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len);
1104 if (len == 0) {
1105 dbus_message_iter_next(&array_iter);
1106 continue;
1107 }
8fc2fb56 1108
d401b48f
JM
1109 nies = os_realloc(ies, ies_len + len);
1110 if (nies == NULL) {
1111 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1112 "out of memory. Cannot allocate memory for "
1113 "IE");
1114 os_free(ies);
1115 *reply = dbus_message_new_error(
1116 message, DBUS_ERROR_NO_MEMORY, NULL);
1117 return -1;
1118 }
1119 ies = nies;
1120 os_memcpy(ies + ies_len, val, len);
1121 ies_len += len;
8fc2fb56 1122
d401b48f
JM
1123 dbus_message_iter_next(&array_iter);
1124 }
5228401c 1125
d401b48f
JM
1126 params->extra_ies = ies;
1127 params->extra_ies_len = ies_len;
1128 return 0;
1129}
8fc2fb56 1130
8fc2fb56 1131
d401b48f
JM
1132static int wpas_dbus_get_scan_channels(DBusMessage *message,
1133 DBusMessageIter *var,
1134 struct wpa_driver_scan_params *params,
1135 DBusMessage **reply)
1136{
1137 DBusMessageIter array_iter, sub_array_iter;
1138 int *freqs = NULL, *nfreqs;
1139 int freqs_num = 0;
8fc2fb56 1140
d401b48f
JM
1141 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
1142 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1143 "Channels must be an array of structs");
db9a76c0 1144 *reply = wpas_dbus_error_invalid_args(
d401b48f
JM
1145 message, "Wrong Channels value type. Array of structs "
1146 "required");
1147 return -1;
1148 }
8fc2fb56 1149
d401b48f 1150 dbus_message_iter_recurse(var, &array_iter);
8fc2fb56 1151
d401b48f
JM
1152 if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_STRUCT) {
1153 wpa_printf(MSG_DEBUG,
1154 "wpas_dbus_handler_scan[dbus]: Channels must be an "
1155 "array of structs");
db9a76c0 1156 *reply = wpas_dbus_error_invalid_args(
d401b48f
JM
1157 message, "Wrong Channels value type. Array of structs "
1158 "required");
1159 return -1;
1160 }
8fc2fb56 1161
d401b48f
JM
1162 while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_STRUCT)
1163 {
1164 int freq, width;
8fc2fb56 1165
d401b48f 1166 dbus_message_iter_recurse(&array_iter, &sub_array_iter);
8fc2fb56 1167
d401b48f
JM
1168 if (dbus_message_iter_get_arg_type(&sub_array_iter) !=
1169 DBUS_TYPE_UINT32) {
1170 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1171 "Channel must by specified by struct of "
1172 "two UINT32s %c",
1173 dbus_message_iter_get_arg_type(
1174 &sub_array_iter));
db9a76c0 1175 *reply = wpas_dbus_error_invalid_args(
d401b48f
JM
1176 message, "Wrong Channel struct. Two UINT32s "
1177 "required");
1178 os_free(freqs);
1179 return -1;
1180 }
1181 dbus_message_iter_get_basic(&sub_array_iter, &freq);
8fc2fb56 1182
d401b48f
JM
1183 if (!dbus_message_iter_next(&sub_array_iter) ||
1184 dbus_message_iter_get_arg_type(&sub_array_iter) !=
1185 DBUS_TYPE_UINT32) {
1186 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1187 "Channel must by specified by struct of "
1188 "two UINT32s");
db9a76c0 1189 *reply = wpas_dbus_error_invalid_args(
d401b48f
JM
1190 message,
1191 "Wrong Channel struct. Two UINT32s required");
1192 os_free(freqs);
1193 return -1;
1194 }
8fc2fb56 1195
d401b48f 1196 dbus_message_iter_get_basic(&sub_array_iter, &width);
8fc2fb56 1197
5228401c 1198#define FREQS_ALLOC_CHUNK 32
d401b48f 1199 if (freqs_num % FREQS_ALLOC_CHUNK == 0) {
067ffa26
JM
1200 nfreqs = os_realloc_array(
1201 freqs, freqs_num + FREQS_ALLOC_CHUNK,
1202 sizeof(int));
d401b48f
JM
1203 if (nfreqs == NULL)
1204 os_free(freqs);
1205 freqs = nfreqs;
1206 }
1207 if (freqs == NULL) {
1208 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1209 "out of memory. can't allocate memory for "
1210 "freqs");
1211 *reply = dbus_message_new_error(
1212 message, DBUS_ERROR_NO_MEMORY, NULL);
1213 return -1;
1214 }
8fc2fb56 1215
d401b48f 1216 freqs[freqs_num] = freq;
8fc2fb56 1217
d401b48f
JM
1218 freqs_num++;
1219 dbus_message_iter_next(&array_iter);
1220 }
8fc2fb56 1221
067ffa26 1222 nfreqs = os_realloc_array(freqs, freqs_num + 1, sizeof(int));
d401b48f
JM
1223 if (nfreqs == NULL)
1224 os_free(freqs);
1225 freqs = nfreqs;
1226 if (freqs == NULL) {
1227 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1228 "out of memory. Can't allocate memory for freqs");
1229 *reply = dbus_message_new_error(
1230 message, DBUS_ERROR_NO_MEMORY, NULL);
1231 return -1;
1232 }
1233 freqs[freqs_num] = 0;
1234
1235 params->freqs = freqs;
1236 return 0;
1237}
8fc2fb56 1238
d401b48f
JM
1239
1240/**
1241 * wpas_dbus_handler_scan - Request a wireless scan on an interface
1242 * @message: Pointer to incoming dbus message
1243 * @wpa_s: wpa_supplicant structure for a network interface
1244 * Returns: NULL indicating success or DBus error message on failure
1245 *
1246 * Handler function for "Scan" method call of a network device. Requests
1247 * that wpa_supplicant perform a wireless scan as soon as possible
1248 * on a particular wireless interface.
1249 */
1250DBusMessage * wpas_dbus_handler_scan(DBusMessage *message,
1251 struct wpa_supplicant *wpa_s)
1252{
1253 DBusMessage *reply = NULL;
1254 DBusMessageIter iter, dict_iter, entry_iter, variant_iter;
1255 char *key = NULL, *type = NULL;
1256 struct wpa_driver_scan_params params;
1257 size_t i;
1258
1259 os_memset(&params, 0, sizeof(params));
1260
1261 dbus_message_iter_init(message, &iter);
1262
1263 dbus_message_iter_recurse(&iter, &dict_iter);
1264
1265 while (dbus_message_iter_get_arg_type(&dict_iter) ==
1266 DBUS_TYPE_DICT_ENTRY) {
1267 dbus_message_iter_recurse(&dict_iter, &entry_iter);
1268 dbus_message_iter_get_basic(&entry_iter, &key);
1269 dbus_message_iter_next(&entry_iter);
1270 dbus_message_iter_recurse(&entry_iter, &variant_iter);
1271
1272 if (os_strcmp(key, "Type") == 0) {
1273 if (wpas_dbus_get_scan_type(message, &variant_iter,
1274 &type, &reply) < 0)
1275 goto out;
1276 } else if (os_strcmp(key, "SSIDs") == 0) {
1277 if (wpas_dbus_get_scan_ssids(message, &variant_iter,
1278 &params, &reply) < 0)
1279 goto out;
1280 } else if (os_strcmp(key, "IEs") == 0) {
1281 if (wpas_dbus_get_scan_ies(message, &variant_iter,
1282 &params, &reply) < 0)
1283 goto out;
1284 } else if (os_strcmp(key, "Channels") == 0) {
1285 if (wpas_dbus_get_scan_channels(message, &variant_iter,
1286 &params, &reply) < 0)
1287 goto out;
5228401c 1288 } else {
8fc2fb56 1289 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
5228401c 1290 "Unknown argument %s", key);
db9a76c0 1291 reply = wpas_dbus_error_invalid_args(message, key);
8fc2fb56
WS
1292 goto out;
1293 }
1294
1295 dbus_message_iter_next(&dict_iter);
1296 }
1297
1298 if (!type) {
1299 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
5228401c 1300 "Scan type not specified");
db9a76c0 1301 reply = wpas_dbus_error_invalid_args(message, key);
8fc2fb56
WS
1302 goto out;
1303 }
1304
d401b48f
JM
1305 if (!os_strcmp(type, "passive")) {
1306 if (params.num_ssids || params.extra_ies_len) {
8fc2fb56 1307 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
5228401c 1308 "SSIDs or IEs specified for passive scan.");
db9a76c0 1309 reply = wpas_dbus_error_invalid_args(
5228401c
JM
1310 message, "You can specify only Channels in "
1311 "passive scan");
8fc2fb56 1312 goto out;
d401b48f 1313 } else if (params.freqs && params.freqs[0]) {
8fc2fb56 1314 wpa_supplicant_trigger_scan(wpa_s, &params);
5228401c 1315 } else {
4115303b 1316 wpa_s->scan_req = MANUAL_SCAN_REQ;
8fc2fb56
WS
1317 wpa_supplicant_req_scan(wpa_s, 0, 0);
1318 }
d401b48f 1319 } else if (!os_strcmp(type, "active")) {
a7af023b
DK
1320 if (!params.num_ssids) {
1321 /* Add wildcard ssid */
1322 params.num_ssids++;
1323 }
7c865c68
TB
1324#ifdef CONFIG_AUTOSCAN
1325 autoscan_deinit(wpa_s);
1326#endif /* CONFIG_AUTOSCAN */
8fc2fb56 1327 wpa_supplicant_trigger_scan(wpa_s, &params);
5228401c 1328 } else {
8fc2fb56 1329 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
5228401c 1330 "Unknown scan type: %s", type);
db9a76c0
JM
1331 reply = wpas_dbus_error_invalid_args(message,
1332 "Wrong scan type");
8fc2fb56
WS
1333 goto out;
1334 }
1335
1336out:
d401b48f
JM
1337 for (i = 0; i < WPAS_MAX_SCAN_SSIDS; i++)
1338 os_free((u8 *) params.ssids[i].ssid);
5228401c 1339 os_free((u8 *) params.extra_ies);
8fc2fb56
WS
1340 os_free(params.freqs);
1341 return reply;
1342}
1343
1344
1345/*
1346 * wpas_dbus_handler_disconnect - Terminate the current connection
1347 * @message: Pointer to incoming dbus message
1348 * @wpa_s: wpa_supplicant structure for a network interface
1349 * Returns: NotConnected DBus error message if already not connected
1350 * or NULL otherwise.
1351 *
1352 * Handler function for "Disconnect" method call of network interface.
1353 */
1354DBusMessage * wpas_dbus_handler_disconnect(DBusMessage *message,
5228401c 1355 struct wpa_supplicant *wpa_s)
8fc2fb56
WS
1356{
1357 if (wpa_s->current_ssid != NULL) {
1358 wpa_s->disconnected = 1;
f9cd8587
JM
1359 wpa_supplicant_deauthenticate(wpa_s,
1360 WLAN_REASON_DEAUTH_LEAVING);
8fc2fb56
WS
1361
1362 return NULL;
1363 }
5228401c
JM
1364
1365 return dbus_message_new_error(message, WPAS_DBUS_ERROR_NOT_CONNECTED,
1366 "This interface is not connected");
8fc2fb56
WS
1367}
1368
1369
1370/**
1371 * wpas_dbus_new_iface_add_network - Add a new configured network
1372 * @message: Pointer to incoming dbus message
1373 * @wpa_s: wpa_supplicant structure for a network interface
1374 * Returns: A dbus message containing the object path of the new network
1375 *
1376 * Handler function for "AddNetwork" method call of a network interface.
1377 */
1378DBusMessage * wpas_dbus_handler_add_network(DBusMessage *message,
5228401c 1379 struct wpa_supplicant *wpa_s)
8fc2fb56
WS
1380{
1381 DBusMessage *reply = NULL;
1382 DBusMessageIter iter;
1383 struct wpa_ssid *ssid = NULL;
3e87bd54 1384 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf;
6aeeb6fa 1385 DBusError error;
8fc2fb56
WS
1386
1387 dbus_message_iter_init(message, &iter);
1388
1389 ssid = wpa_config_add_network(wpa_s->conf);
1390 if (ssid == NULL) {
1391 wpa_printf(MSG_ERROR, "wpas_dbus_handler_add_network[dbus]: "
5228401c
JM
1392 "can't add new interface.");
1393 reply = wpas_dbus_error_unknown_error(
1394 message,
1395 "wpa_supplicant could not add "
1396 "a network on this interface.");
8fc2fb56
WS
1397 goto err;
1398 }
1399 wpas_notify_network_added(wpa_s, ssid);
1400 ssid->disabled = 1;
1401 wpa_config_set_network_defaults(ssid);
1402
6aeeb6fa
DW
1403 dbus_error_init(&error);
1404 if (!set_network_properties(wpa_s, ssid, &iter, &error)) {
8fc2fb56 1405 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_add_network[dbus]:"
5228401c
JM
1406 "control interface couldn't set network "
1407 "properties");
6aeeb6fa
DW
1408 reply = wpas_dbus_reply_new_from_error(message, &error,
1409 DBUS_ERROR_INVALID_ARGS,
1410 "Failed to add network");
1411 dbus_error_free(&error);
8fc2fb56
WS
1412 goto err;
1413 }
1414
1415 /* Construct the object path for this network. */
5228401c
JM
1416 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
1417 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
c49cf2d6 1418 wpa_s->dbus_new_path, ssid->id);
8fc2fb56
WS
1419
1420 reply = dbus_message_new_method_return(message);
1421 if (reply == NULL) {
5228401c
JM
1422 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1423 NULL);
8fc2fb56
WS
1424 goto err;
1425 }
1426 if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
5228401c 1427 DBUS_TYPE_INVALID)) {
8fc2fb56 1428 dbus_message_unref(reply);
5228401c
JM
1429 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1430 NULL);
8fc2fb56
WS
1431 goto err;
1432 }
1433
8fc2fb56
WS
1434 return reply;
1435
1436err:
1437 if (ssid) {
1438 wpas_notify_network_removed(wpa_s, ssid);
1439 wpa_config_remove_network(wpa_s->conf, ssid->id);
1440 }
8fc2fb56
WS
1441 return reply;
1442}
1443
1444
6ed31175
PS
1445/**
1446 * wpas_dbus_handler_reassociate - Reassociate to current AP
1447 * @message: Pointer to incoming dbus message
1448 * @wpa_s: wpa_supplicant structure for a network interface
1449 * Returns: NotConnected DBus error message if not connected
1450 * or NULL otherwise.
1451 *
1452 * Handler function for "Reassociate" method call of network interface.
1453 */
1454DBusMessage * wpas_dbus_handler_reassociate(DBusMessage *message,
1455 struct wpa_supplicant *wpa_s)
1456{
1457 if (wpa_s->current_ssid != NULL) {
9796a86c 1458 wpas_request_connection(wpa_s);
6ed31175
PS
1459 return NULL;
1460 }
1461
1462 return dbus_message_new_error(message, WPAS_DBUS_ERROR_NOT_CONNECTED,
1463 "This interface is not connected");
1464}
1465
1466
8fc2fb56
WS
1467/**
1468 * wpas_dbus_handler_remove_network - Remove a configured network
1469 * @message: Pointer to incoming dbus message
1470 * @wpa_s: wpa_supplicant structure for a network interface
1471 * Returns: NULL on success or dbus error on failure
1472 *
1473 * Handler function for "RemoveNetwork" method call of a network interface.
1474 */
1475DBusMessage * wpas_dbus_handler_remove_network(DBusMessage *message,
5228401c 1476 struct wpa_supplicant *wpa_s)
8fc2fb56
WS
1477{
1478 DBusMessage *reply = NULL;
1479 const char *op;
1480 char *iface = NULL, *net_id = NULL;
1481 int id;
1482 struct wpa_ssid *ssid;
1483
1484 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
5228401c 1485 DBUS_TYPE_INVALID);
8fc2fb56
WS
1486
1487 /* Extract the network ID and ensure the network */
1488 /* is actually a child of this interface */
28550706 1489 iface = wpas_dbus_new_decompose_object_path(op, 0, &net_id, NULL);
45ac5793
PS
1490 if (iface == NULL || net_id == NULL ||
1491 os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
db9a76c0 1492 reply = wpas_dbus_error_invalid_args(message, op);
8fc2fb56
WS
1493 goto out;
1494 }
1495
45ac5793 1496 errno = 0;
8fc2fb56 1497 id = strtoul(net_id, NULL, 10);
45ac5793 1498 if (errno != 0) {
db9a76c0 1499 reply = wpas_dbus_error_invalid_args(message, op);
8fc2fb56
WS
1500 goto out;
1501 }
1502
1503 ssid = wpa_config_get_network(wpa_s->conf, id);
1504 if (ssid == NULL) {
1505 reply = wpas_dbus_error_network_unknown(message);
1506 goto out;
1507 }
1508
1509 wpas_notify_network_removed(wpa_s, ssid);
1510
1511 if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
5228401c
JM
1512 wpa_printf(MSG_ERROR,
1513 "wpas_dbus_handler_remove_network[dbus]: "
1514 "error occurred when removing network %d", id);
1515 reply = wpas_dbus_error_unknown_error(
1516 message, "error removing the specified network on "
1517 "this interface.");
8fc2fb56
WS
1518 goto out;
1519 }
1520
1521 if (ssid == wpa_s->current_ssid)
f9cd8587
JM
1522 wpa_supplicant_deauthenticate(wpa_s,
1523 WLAN_REASON_DEAUTH_LEAVING);
8fc2fb56
WS
1524
1525out:
1526 os_free(iface);
1527 os_free(net_id);
1528 return reply;
1529}
1530
1531
7c49fdd0
SL
1532static void remove_network(void *arg, struct wpa_ssid *ssid)
1533{
1534 struct wpa_supplicant *wpa_s = arg;
1535
1536 wpas_notify_network_removed(wpa_s, ssid);
1537
1538 if (wpa_config_remove_network(wpa_s->conf, ssid->id) < 0) {
1539 wpa_printf(MSG_ERROR,
1540 "wpas_dbus_handler_remove_all_networks[dbus]: "
1541 "error occurred when removing network %d",
1542 ssid->id);
1543 return;
1544 }
1545
1546 if (ssid == wpa_s->current_ssid)
07783eaa
JM
1547 wpa_supplicant_deauthenticate(wpa_s,
1548 WLAN_REASON_DEAUTH_LEAVING);
7c49fdd0
SL
1549}
1550
1551
1552/**
1553 * wpas_dbus_handler_remove_all_networks - Remove all configured networks
1554 * @message: Pointer to incoming dbus message
1555 * @wpa_s: wpa_supplicant structure for a network interface
1556 * Returns: NULL on success or dbus error on failure
1557 *
1558 * Handler function for "RemoveAllNetworks" method call of a network interface.
1559 */
1560DBusMessage * wpas_dbus_handler_remove_all_networks(
1561 DBusMessage *message, struct wpa_supplicant *wpa_s)
1562{
1563 /* NB: could check for failure and return an error */
1564 wpa_config_foreach_network(wpa_s->conf, remove_network, wpa_s);
1565 return NULL;
1566}
1567
1568
8fc2fb56
WS
1569/**
1570 * wpas_dbus_handler_select_network - Attempt association with a network
1571 * @message: Pointer to incoming dbus message
1572 * @wpa_s: wpa_supplicant structure for a network interface
1573 * Returns: NULL on success or dbus error on failure
1574 *
1575 * Handler function for "SelectNetwork" method call of network interface.
1576 */
1577DBusMessage * wpas_dbus_handler_select_network(DBusMessage *message,
5228401c 1578 struct wpa_supplicant *wpa_s)
8fc2fb56
WS
1579{
1580 DBusMessage *reply = NULL;
1581 const char *op;
1582 char *iface = NULL, *net_id = NULL;
1583 int id;
1584 struct wpa_ssid *ssid;
1585
1586 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
5228401c 1587 DBUS_TYPE_INVALID);
8fc2fb56
WS
1588
1589 /* Extract the network ID and ensure the network */
1590 /* is actually a child of this interface */
28550706 1591 iface = wpas_dbus_new_decompose_object_path(op, 0, &net_id, NULL);
45ac5793
PS
1592 if (iface == NULL || net_id == NULL ||
1593 os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
db9a76c0 1594 reply = wpas_dbus_error_invalid_args(message, op);
8fc2fb56
WS
1595 goto out;
1596 }
1597
45ac5793 1598 errno = 0;
8fc2fb56 1599 id = strtoul(net_id, NULL, 10);
45ac5793 1600 if (errno != 0) {
db9a76c0 1601 reply = wpas_dbus_error_invalid_args(message, op);
8fc2fb56
WS
1602 goto out;
1603 }
1604
1605 ssid = wpa_config_get_network(wpa_s->conf, id);
1606 if (ssid == NULL) {
1607 reply = wpas_dbus_error_network_unknown(message);
1608 goto out;
1609 }
5228401c 1610
8fc2fb56
WS
1611 /* Finally, associate with the network */
1612 wpa_supplicant_select_network(wpa_s, ssid);
1613
1614out:
1615 os_free(iface);
1616 os_free(net_id);
1617 return reply;
1618}
1619
1620
e9c3c1af
DW
1621/**
1622 * wpas_dbus_handler_network_reply - Reply to a NetworkRequest signal
1623 * @message: Pointer to incoming dbus message
1624 * @wpa_s: wpa_supplicant structure for a network interface
1625 * Returns: NULL on success or dbus error on failure
1626 *
1627 * Handler function for "NetworkReply" method call of network interface.
1628 */
1629DBusMessage * wpas_dbus_handler_network_reply(DBusMessage *message,
1630 struct wpa_supplicant *wpa_s)
1631{
1632#ifdef IEEE8021X_EAPOL
1633 DBusMessage *reply = NULL;
1634 const char *op, *field, *value;
1635 char *iface = NULL, *net_id = NULL;
1636 int id;
1637 struct wpa_ssid *ssid;
1638
1639 if (!dbus_message_get_args(message, NULL,
1640 DBUS_TYPE_OBJECT_PATH, &op,
1641 DBUS_TYPE_STRING, &field,
1642 DBUS_TYPE_STRING, &value,
1643 DBUS_TYPE_INVALID))
1644 return wpas_dbus_error_invalid_args(message, NULL);
1645
1646 /* Extract the network ID and ensure the network */
1647 /* is actually a child of this interface */
1648 iface = wpas_dbus_new_decompose_object_path(op, 0, &net_id, NULL);
45ac5793
PS
1649 if (iface == NULL || net_id == NULL ||
1650 os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
e9c3c1af
DW
1651 reply = wpas_dbus_error_invalid_args(message, op);
1652 goto out;
1653 }
1654
45ac5793 1655 errno = 0;
e9c3c1af 1656 id = strtoul(net_id, NULL, 10);
45ac5793 1657 if (errno != 0) {
e9c3c1af
DW
1658 reply = wpas_dbus_error_invalid_args(message, net_id);
1659 goto out;
1660 }
1661
1662 ssid = wpa_config_get_network(wpa_s->conf, id);
1663 if (ssid == NULL) {
1664 reply = wpas_dbus_error_network_unknown(message);
1665 goto out;
1666 }
1667
1668 if (wpa_supplicant_ctrl_iface_ctrl_rsp_handle(wpa_s, ssid,
1669 field, value) < 0)
1670 reply = wpas_dbus_error_invalid_args(message, field);
1671 else {
1672 /* Tell EAP to retry immediately */
1673 eapol_sm_notify_ctrl_response(wpa_s->eapol);
1674 }
1675
1676out:
1677 os_free(iface);
1678 os_free(net_id);
1679 return reply;
1680#else /* IEEE8021X_EAPOL */
1681 wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included");
1682 return wpas_dbus_error_unknown_error(message, "802.1X not included");
1683#endif /* IEEE8021X_EAPOL */
1684}
1685
1686
8fc2fb56
WS
1687/**
1688 * wpas_dbus_handler_add_blob - Store named binary blob (ie, for certificates)
1689 * @message: Pointer to incoming dbus message
1690 * @wpa_s: %wpa_supplicant data structure
1691 * Returns: A dbus message containing an error on failure or NULL on success
1692 *
1693 * Asks wpa_supplicant to internally store a binary blobs.
1694 */
1695DBusMessage * wpas_dbus_handler_add_blob(DBusMessage *message,
5228401c 1696 struct wpa_supplicant *wpa_s)
8fc2fb56
WS
1697{
1698 DBusMessage *reply = NULL;
1699 DBusMessageIter iter, array_iter;
1700
1701 char *blob_name;
1702 u8 *blob_data;
1703 int blob_len;
1704 struct wpa_config_blob *blob = NULL;
1705
1706 dbus_message_iter_init(message, &iter);
1707 dbus_message_iter_get_basic(&iter, &blob_name);
1708
1709 if (wpa_config_get_blob(wpa_s->conf, blob_name)) {
5228401c
JM
1710 return dbus_message_new_error(message,
1711 WPAS_DBUS_ERROR_BLOB_EXISTS,
1712 NULL);
8fc2fb56
WS
1713 }
1714
1715 dbus_message_iter_next(&iter);
1716 dbus_message_iter_recurse(&iter, &array_iter);
1717
1718 dbus_message_iter_get_fixed_array(&array_iter, &blob_data, &blob_len);
1719
1720 blob = os_zalloc(sizeof(*blob));
1721 if (!blob) {
5228401c
JM
1722 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1723 NULL);
8fc2fb56
WS
1724 goto err;
1725 }
1726
1727 blob->data = os_malloc(blob_len);
1728 if (!blob->data) {
5228401c
JM
1729 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1730 NULL);
8fc2fb56
WS
1731 goto err;
1732 }
1733 os_memcpy(blob->data, blob_data, blob_len);
1734
1735 blob->len = blob_len;
a646086d 1736 blob->name = os_strdup(blob_name);
8fc2fb56 1737 if (!blob->name) {
5228401c
JM
1738 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1739 NULL);
8fc2fb56
WS
1740 goto err;
1741 }
1742
1743 wpa_config_set_blob(wpa_s->conf, blob);
1744 wpas_notify_blob_added(wpa_s, blob->name);
1745
1746 return reply;
1747
1748err:
1749 if (blob) {
1750 os_free(blob->name);
1751 os_free(blob->data);
1752 os_free(blob);
1753 }
1754 return reply;
1755}
1756
1757
1758/**
1759 * wpas_dbus_handler_get_blob - Get named binary blob (ie, for certificates)
1760 * @message: Pointer to incoming dbus message
1761 * @wpa_s: %wpa_supplicant data structure
1762 * Returns: A dbus message containing array of bytes (blob)
1763 *
1764 * Gets one wpa_supplicant's binary blobs.
1765 */
1766DBusMessage * wpas_dbus_handler_get_blob(DBusMessage *message,
5228401c 1767 struct wpa_supplicant *wpa_s)
8fc2fb56
WS
1768{
1769 DBusMessage *reply = NULL;
1770 DBusMessageIter iter, array_iter;
1771
1772 char *blob_name;
1773 const struct wpa_config_blob *blob;
1774
1775 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &blob_name,
5228401c 1776 DBUS_TYPE_INVALID);
8fc2fb56
WS
1777
1778 blob = wpa_config_get_blob(wpa_s->conf, blob_name);
1779 if (!blob) {
5228401c
JM
1780 return dbus_message_new_error(message,
1781 WPAS_DBUS_ERROR_BLOB_UNKNOWN,
1782 "Blob id not set");
8fc2fb56
WS
1783 }
1784
1785 reply = dbus_message_new_method_return(message);
1786 if (!reply) {
5228401c
JM
1787 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1788 NULL);
8fc2fb56
WS
1789 goto out;
1790 }
1791
1792 dbus_message_iter_init_append(reply, &iter);
1793
1794 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
5228401c
JM
1795 DBUS_TYPE_BYTE_AS_STRING,
1796 &array_iter)) {
8fc2fb56 1797 dbus_message_unref(reply);
5228401c
JM
1798 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1799 NULL);
8fc2fb56
WS
1800 goto out;
1801 }
1802
1803 if (!dbus_message_iter_append_fixed_array(&array_iter, DBUS_TYPE_BYTE,
5228401c 1804 &(blob->data), blob->len)) {
8fc2fb56 1805 dbus_message_unref(reply);
5228401c
JM
1806 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1807 NULL);
8fc2fb56
WS
1808 goto out;
1809 }
1810
1811 if (!dbus_message_iter_close_container(&iter, &array_iter)) {
1812 dbus_message_unref(reply);
5228401c
JM
1813 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1814 NULL);
8fc2fb56
WS
1815 goto out;
1816 }
1817
1818out:
1819 return reply;
8fc2fb56
WS
1820}
1821
1822
1823/**
1824 * wpas_remove_handler_remove_blob - Remove named binary blob
1825 * @message: Pointer to incoming dbus message
1826 * @wpa_s: %wpa_supplicant data structure
1827 * Returns: NULL on success or dbus error
1828 *
1829 * Asks wpa_supplicant to internally remove a binary blobs.
1830 */
1831DBusMessage * wpas_dbus_handler_remove_blob(DBusMessage *message,
5228401c 1832 struct wpa_supplicant *wpa_s)
8fc2fb56
WS
1833{
1834 DBusMessage *reply = NULL;
8fc2fb56
WS
1835 char *blob_name;
1836
1837 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &blob_name,
5228401c 1838 DBUS_TYPE_INVALID);
8fc2fb56
WS
1839
1840 if (wpa_config_remove_blob(wpa_s->conf, blob_name)) {
5228401c
JM
1841 return dbus_message_new_error(message,
1842 WPAS_DBUS_ERROR_BLOB_UNKNOWN,
1843 "Blob id not set");
8fc2fb56
WS
1844 }
1845 wpas_notify_blob_removed(wpa_s, blob_name);
1846
1847 return reply;
1848
1849}
1850
2b65b30d
SL
1851/*
1852 * wpas_dbus_handler_flush_bss - Flush the BSS cache
1853 * @message: Pointer to incoming dbus message
1854 * @wpa_s: wpa_supplicant structure for a network interface
1855 * Returns: NULL
1856 *
1857 * Handler function for "FlushBSS" method call of network interface.
1858 */
1859DBusMessage * wpas_dbus_handler_flush_bss(DBusMessage *message,
1860 struct wpa_supplicant *wpa_s)
1861{
1862 dbus_uint32_t age;
1863
1864 dbus_message_get_args(message, NULL, DBUS_TYPE_UINT32, &age,
1865 DBUS_TYPE_INVALID);
1866
1867 if (age == 0)
1868 wpa_bss_flush(wpa_s);
1869 else
1870 wpa_bss_flush_by_age(wpa_s, age);
1871
1872 return NULL;
1873}
1874
8fc2fb56 1875
67892d5c
TB
1876#ifdef CONFIG_AUTOSCAN
1877/**
1878 * wpas_dbus_handler_autoscan - Set autoscan parameters for the interface
1879 * @message: Pointer to incoming dbus message
1880 * @wpa_s: wpa_supplicant structure for a network interface
1881 * Returns: NULL
1882 *
1883 * Handler function for "AutoScan" method call of network interface.
1884 */
1885DBusMessage * wpas_dbus_handler_autoscan(DBusMessage *message,
1886 struct wpa_supplicant *wpa_s)
1887{
1888 DBusMessage *reply = NULL;
1889 enum wpa_states state = wpa_s->wpa_state;
1890 char *arg;
1891
1892 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &arg,
1893 DBUS_TYPE_INVALID);
1894
1895 if (arg != NULL && os_strlen(arg) > 0) {
1896 char *tmp;
1897 tmp = os_strdup(arg);
1898 if (tmp == NULL) {
1899 reply = dbus_message_new_error(message,
1900 DBUS_ERROR_NO_MEMORY,
1901 NULL);
1902 } else {
1903 os_free(wpa_s->conf->autoscan);
1904 wpa_s->conf->autoscan = tmp;
1905 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
99218999 1906 autoscan_init(wpa_s, 1);
99f00324
JM
1907 else if (state == WPA_SCANNING)
1908 wpa_supplicant_reinit_autoscan(wpa_s);
67892d5c
TB
1909 }
1910 } else if (arg != NULL && os_strlen(arg) == 0) {
1911 os_free(wpa_s->conf->autoscan);
1912 wpa_s->conf->autoscan = NULL;
1913 autoscan_deinit(wpa_s);
1914 } else
1915 reply = dbus_message_new_error(message,
1916 DBUS_ERROR_INVALID_ARGS,
1917 NULL);
1918
1919 return reply;
1920}
1921#endif /* CONFIG_AUTOSCAN */
1922
1923
8fc2fb56
WS
1924/**
1925 * wpas_dbus_getter_capabilities - Return interface capabilities
6aeeb6fa
DW
1926 * @iter: Pointer to incoming dbus message iter
1927 * @error: Location to store error on failure
1928 * @user_data: Function specific data
1929 * Returns: TRUE on success, FALSE on failure
8fc2fb56
WS
1930 *
1931 * Getter for "Capabilities" property of an interface.
1932 */
6aeeb6fa
DW
1933dbus_bool_t wpas_dbus_getter_capabilities(DBusMessageIter *iter,
1934 DBusError *error, void *user_data)
8fc2fb56 1935{
6aeeb6fa 1936 struct wpa_supplicant *wpa_s = user_data;
8fc2fb56
WS
1937 struct wpa_driver_capa capa;
1938 int res;
6aeeb6fa 1939 DBusMessageIter iter_dict, iter_dict_entry, iter_dict_val, iter_array,
5228401c
JM
1940 variant_iter;
1941 const char *scans[] = { "active", "passive", "ssid" };
8fc2fb56 1942
6aeeb6fa 1943 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
5228401c 1944 "a{sv}", &variant_iter))
8fc2fb56
WS
1945 goto nomem;
1946
1947 if (!wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
1948 goto nomem;
1949
1950 res = wpa_drv_get_capa(wpa_s, &capa);
1951
1952 /***** pairwise cipher */
1953 if (res < 0) {
1954 const char *args[] = {"ccmp", "tkip", "none"};
1955 if (!wpa_dbus_dict_append_string_array(
5228401c
JM
1956 &iter_dict, "Pairwise", args,
1957 sizeof(args) / sizeof(char*)))
8fc2fb56
WS
1958 goto nomem;
1959 } else {
1960 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Pairwise",
1961 &iter_dict_entry,
1962 &iter_dict_val,
1963 &iter_array))
1964 goto nomem;
1965
1966 if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
1967 if (!wpa_dbus_dict_string_array_add_element(
1968 &iter_array, "ccmp"))
1969 goto nomem;
1970 }
1971
eb7719ff
JM
1972 if (capa.enc & WPA_DRIVER_CAPA_ENC_GCMP) {
1973 if (!wpa_dbus_dict_string_array_add_element(
1974 &iter_array, "gcmp"))
1975 goto nomem;
1976 }
1977
8fc2fb56
WS
1978 if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
1979 if (!wpa_dbus_dict_string_array_add_element(
1980 &iter_array, "tkip"))
1981 goto nomem;
1982 }
1983
1984 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
1985 if (!wpa_dbus_dict_string_array_add_element(
1986 &iter_array, "none"))
1987 goto nomem;
1988 }
1989
1990 if (!wpa_dbus_dict_end_string_array(&iter_dict,
1991 &iter_dict_entry,
1992 &iter_dict_val,
1993 &iter_array))
1994 goto nomem;
1995 }
1996
1997 /***** group cipher */
1998 if (res < 0) {
1999 const char *args[] = {
2000 "ccmp", "tkip", "wep104", "wep40"
2001 };
2002 if (!wpa_dbus_dict_append_string_array(
5228401c
JM
2003 &iter_dict, "Group", args,
2004 sizeof(args) / sizeof(char*)))
8fc2fb56
WS
2005 goto nomem;
2006 } else {
2007 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Group",
2008 &iter_dict_entry,
2009 &iter_dict_val,
2010 &iter_array))
2011 goto nomem;
2012
2013 if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
2014 if (!wpa_dbus_dict_string_array_add_element(
2015 &iter_array, "ccmp"))
2016 goto nomem;
2017 }
2018
eb7719ff
JM
2019 if (capa.enc & WPA_DRIVER_CAPA_ENC_GCMP) {
2020 if (!wpa_dbus_dict_string_array_add_element(
2021 &iter_array, "gcmp"))
2022 goto nomem;
2023 }
2024
8fc2fb56
WS
2025 if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
2026 if (!wpa_dbus_dict_string_array_add_element(
2027 &iter_array, "tkip"))
2028 goto nomem;
2029 }
2030
2031 if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) {
2032 if (!wpa_dbus_dict_string_array_add_element(
2033 &iter_array, "wep104"))
2034 goto nomem;
2035 }
2036
2037 if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) {
2038 if (!wpa_dbus_dict_string_array_add_element(
2039 &iter_array, "wep40"))
2040 goto nomem;
2041 }
2042
2043 if (!wpa_dbus_dict_end_string_array(&iter_dict,
2044 &iter_dict_entry,
2045 &iter_dict_val,
2046 &iter_array))
2047 goto nomem;
2048 }
2049
2050 /***** key management */
2051 if (res < 0) {
2052 const char *args[] = {
2053 "wpa-psk", "wpa-eap", "ieee8021x", "wpa-none",
2054#ifdef CONFIG_WPS
2055 "wps",
2056#endif /* CONFIG_WPS */
2057 "none"
2058 };
2059 if (!wpa_dbus_dict_append_string_array(
5228401c
JM
2060 &iter_dict, "KeyMgmt", args,
2061 sizeof(args) / sizeof(char*)))
8fc2fb56
WS
2062 goto nomem;
2063 } else {
2064 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "KeyMgmt",
2065 &iter_dict_entry,
2066 &iter_dict_val,
2067 &iter_array))
2068 goto nomem;
2069
2070 if (!wpa_dbus_dict_string_array_add_element(&iter_array,
2071 "none"))
2072 goto nomem;
2073
2074 if (!wpa_dbus_dict_string_array_add_element(&iter_array,
2075 "ieee8021x"))
2076 goto nomem;
2077
2078 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
2079 WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
2080 if (!wpa_dbus_dict_string_array_add_element(
2081 &iter_array, "wpa-eap"))
2082 goto nomem;
c56ce48a
WS
2083
2084 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT)
2085 if (!wpa_dbus_dict_string_array_add_element(
2086 &iter_array, "wpa-ft-eap"))
2087 goto nomem;
2088
2089/* TODO: Ensure that driver actually supports sha256 encryption. */
2090#ifdef CONFIG_IEEE80211W
2091 if (!wpa_dbus_dict_string_array_add_element(
2092 &iter_array, "wpa-eap-sha256"))
2093 goto nomem;
2094#endif /* CONFIG_IEEE80211W */
8fc2fb56
WS
2095 }
2096
2097 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
2098 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
2099 if (!wpa_dbus_dict_string_array_add_element(
2100 &iter_array, "wpa-psk"))
2101 goto nomem;
c56ce48a
WS
2102
2103 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK)
2104 if (!wpa_dbus_dict_string_array_add_element(
2105 &iter_array, "wpa-ft-psk"))
2106 goto nomem;
2107
2108/* TODO: Ensure that driver actually supports sha256 encryption. */
2109#ifdef CONFIG_IEEE80211W
2110 if (!wpa_dbus_dict_string_array_add_element(
2111 &iter_array, "wpa-psk-sha256"))
2112 goto nomem;
2113#endif /* CONFIG_IEEE80211W */
8fc2fb56
WS
2114 }
2115
2116 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
2117 if (!wpa_dbus_dict_string_array_add_element(
2118 &iter_array, "wpa-none"))
2119 goto nomem;
2120 }
2121
2122
2123#ifdef CONFIG_WPS
5228401c
JM
2124 if (!wpa_dbus_dict_string_array_add_element(&iter_array,
2125 "wps"))
8fc2fb56
WS
2126 goto nomem;
2127#endif /* CONFIG_WPS */
2128
2129 if (!wpa_dbus_dict_end_string_array(&iter_dict,
2130 &iter_dict_entry,
2131 &iter_dict_val,
2132 &iter_array))
2133 goto nomem;
8fc2fb56
WS
2134 }
2135
2136 /***** WPA protocol */
2137 if (res < 0) {
2138 const char *args[] = { "rsn", "wpa" };
2139 if (!wpa_dbus_dict_append_string_array(
5228401c
JM
2140 &iter_dict, "Protocol", args,
2141 sizeof(args) / sizeof(char*)))
8fc2fb56
WS
2142 goto nomem;
2143 } else {
2144 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Protocol",
2145 &iter_dict_entry,
2146 &iter_dict_val,
2147 &iter_array))
2148 goto nomem;
2149
2150 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
2151 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
2152 if (!wpa_dbus_dict_string_array_add_element(
2153 &iter_array, "rsn"))
2154 goto nomem;
2155 }
2156
2157 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
2158 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
2159 if (!wpa_dbus_dict_string_array_add_element(
2160 &iter_array, "wpa"))
2161 goto nomem;
2162 }
2163
2164 if (!wpa_dbus_dict_end_string_array(&iter_dict,
2165 &iter_dict_entry,
2166 &iter_dict_val,
2167 &iter_array))
2168 goto nomem;
2169 }
2170
2171 /***** auth alg */
2172 if (res < 0) {
2173 const char *args[] = { "open", "shared", "leap" };
2174 if (!wpa_dbus_dict_append_string_array(
5228401c
JM
2175 &iter_dict, "AuthAlg", args,
2176 sizeof(args) / sizeof(char*)))
8fc2fb56
WS
2177 goto nomem;
2178 } else {
2179 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "AuthAlg",
2180 &iter_dict_entry,
2181 &iter_dict_val,
2182 &iter_array))
2183 goto nomem;
2184
2185 if (capa.auth & (WPA_DRIVER_AUTH_OPEN)) {
2186 if (!wpa_dbus_dict_string_array_add_element(
2187 &iter_array, "open"))
2188 goto nomem;
2189 }
2190
2191 if (capa.auth & (WPA_DRIVER_AUTH_SHARED)) {
2192 if (!wpa_dbus_dict_string_array_add_element(
2193 &iter_array, "shared"))
2194 goto nomem;
2195 }
2196
2197 if (capa.auth & (WPA_DRIVER_AUTH_LEAP)) {
2198 if (!wpa_dbus_dict_string_array_add_element(
2199 &iter_array, "leap"))
2200 goto nomem;
2201 }
2202
2203 if (!wpa_dbus_dict_end_string_array(&iter_dict,
2204 &iter_dict_entry,
2205 &iter_dict_val,
2206 &iter_array))
2207 goto nomem;
2208 }
2209
2210 /***** Scan */
5228401c
JM
2211 if (!wpa_dbus_dict_append_string_array(&iter_dict, "Scan", scans,
2212 sizeof(scans) / sizeof(char *)))
8fc2fb56
WS
2213 goto nomem;
2214
2215 /***** Modes */
c988980d
JS
2216 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Modes",
2217 &iter_dict_entry,
2218 &iter_dict_val,
2219 &iter_array))
8fc2fb56
WS
2220 goto nomem;
2221
c988980d
JS
2222 if (!wpa_dbus_dict_string_array_add_element(
2223 &iter_array, "infrastructure"))
2224 goto nomem;
2225
2226 if (!wpa_dbus_dict_string_array_add_element(
2227 &iter_array, "ad-hoc"))
2228 goto nomem;
2229
2230 if (res >= 0) {
2231 if (capa.flags & (WPA_DRIVER_FLAGS_AP)) {
2232 if (!wpa_dbus_dict_string_array_add_element(
2233 &iter_array, "ap"))
2234 goto nomem;
2235 }
2236
2237 if (capa.flags & (WPA_DRIVER_FLAGS_P2P_CAPABLE)) {
2238 if (!wpa_dbus_dict_string_array_add_element(
2239 &iter_array, "p2p"))
2240 goto nomem;
2241 }
2242 }
2243
2244 if (!wpa_dbus_dict_end_string_array(&iter_dict,
2245 &iter_dict_entry,
2246 &iter_dict_val,
2247 &iter_array))
2248 goto nomem;
2249 /***** Modes end */
2250
0098ce6d
MA
2251 if (res >= 0) {
2252 dbus_int32_t max_scan_ssid = capa.max_scan_ssids;
2253
2254 if (!wpa_dbus_dict_append_int32(&iter_dict, "MaxScanSSID",
2255 max_scan_ssid))
2256 goto nomem;
2257 }
2258
8fc2fb56
WS
2259 if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict))
2260 goto nomem;
6aeeb6fa 2261 if (!dbus_message_iter_close_container(iter, &variant_iter))
8fc2fb56
WS
2262 goto nomem;
2263
6aeeb6fa 2264 return TRUE;
8fc2fb56
WS
2265
2266nomem:
6aeeb6fa
DW
2267 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
2268 return FALSE;
8fc2fb56
WS
2269}
2270
2271
2272/**
2273 * wpas_dbus_getter_state - Get interface state
6aeeb6fa
DW
2274 * @iter: Pointer to incoming dbus message iter
2275 * @error: Location to store error on failure
2276 * @user_data: Function specific data
2277 * Returns: TRUE on success, FALSE on failure
8fc2fb56
WS
2278 *
2279 * Getter for "State" property.
2280 */
6aeeb6fa
DW
2281dbus_bool_t wpas_dbus_getter_state(DBusMessageIter *iter, DBusError *error,
2282 void *user_data)
8fc2fb56 2283{
6aeeb6fa 2284 struct wpa_supplicant *wpa_s = user_data;
8fc2fb56
WS
2285 const char *str_state;
2286 char *state_ls, *tmp;
6aeeb6fa 2287 dbus_bool_t success = FALSE;
8fc2fb56 2288
fcea0b7d 2289 str_state = wpa_supplicant_state_txt(wpa_s->wpa_state);
8fc2fb56 2290
fcea0b7d
WS
2291 /* make state string lowercase to fit new DBus API convention
2292 */
2293 state_ls = tmp = os_strdup(str_state);
2294 if (!tmp) {
6aeeb6fa
DW
2295 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
2296 return FALSE;
fcea0b7d
WS
2297 }
2298 while (*tmp) {
2299 *tmp = tolower(*tmp);
2300 tmp++;
2301 }
8fc2fb56 2302
6aeeb6fa
DW
2303 success = wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
2304 &state_ls, error);
8fc2fb56 2305
fcea0b7d 2306 os_free(state_ls);
5228401c 2307
6aeeb6fa 2308 return success;
8fc2fb56
WS
2309}
2310
fcea0b7d 2311
8fc2fb56
WS
2312/**
2313 * wpas_dbus_new_iface_get_scanning - Get interface scanning state
6aeeb6fa
DW
2314 * @iter: Pointer to incoming dbus message iter
2315 * @error: Location to store error on failure
2316 * @user_data: Function specific data
2317 * Returns: TRUE on success, FALSE on failure
8fc2fb56
WS
2318 *
2319 * Getter for "scanning" property.
2320 */
6aeeb6fa
DW
2321dbus_bool_t wpas_dbus_getter_scanning(DBusMessageIter *iter, DBusError *error,
2322 void *user_data)
8fc2fb56 2323{
6aeeb6fa 2324 struct wpa_supplicant *wpa_s = user_data;
8fc2fb56 2325 dbus_bool_t scanning = wpa_s->scanning ? TRUE : FALSE;
6aeeb6fa
DW
2326
2327 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
2328 &scanning, error);
fcea0b7d 2329}
8fc2fb56
WS
2330
2331
2332/**
2333 * wpas_dbus_getter_ap_scan - Control roaming mode
6aeeb6fa
DW
2334 * @iter: Pointer to incoming dbus message iter
2335 * @error: Location to store error on failure
2336 * @user_data: Function specific data
2337 * Returns: TRUE on success, FALSE on failure
8fc2fb56
WS
2338 *
2339 * Getter function for "ApScan" property.
2340 */
6aeeb6fa
DW
2341dbus_bool_t wpas_dbus_getter_ap_scan(DBusMessageIter *iter, DBusError *error,
2342 void *user_data)
8fc2fb56 2343{
6aeeb6fa 2344 struct wpa_supplicant *wpa_s = user_data;
8fc2fb56 2345 dbus_uint32_t ap_scan = wpa_s->conf->ap_scan;
6aeeb6fa
DW
2346
2347 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
2348 &ap_scan, error);
8fc2fb56
WS
2349}
2350
2351
2352/**
2353 * wpas_dbus_setter_ap_scan - Control roaming mode
6aeeb6fa
DW
2354 * @iter: Pointer to incoming dbus message iter
2355 * @error: Location to store error on failure
2356 * @user_data: Function specific data
2357 * Returns: TRUE on success, FALSE on failure
8fc2fb56
WS
2358 *
2359 * Setter function for "ApScan" property.
2360 */
6aeeb6fa
DW
2361dbus_bool_t wpas_dbus_setter_ap_scan(DBusMessageIter *iter, DBusError *error,
2362 void *user_data)
8fc2fb56 2363{
6aeeb6fa 2364 struct wpa_supplicant *wpa_s = user_data;
8fc2fb56
WS
2365 dbus_uint32_t ap_scan;
2366
6aeeb6fa
DW
2367 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
2368 &ap_scan))
2369 return FALSE;
8fc2fb56
WS
2370
2371 if (wpa_supplicant_set_ap_scan(wpa_s, ap_scan)) {
6aeeb6fa
DW
2372 dbus_set_error_const(error, DBUS_ERROR_FAILED,
2373 "ap_scan must be 0, 1, or 2");
2374 return FALSE;
8fc2fb56 2375 }
6aeeb6fa 2376 return TRUE;
8fc2fb56
WS
2377}
2378
2379
a4bbb606
PS
2380/**
2381 * wpas_dbus_getter_fast_reauth - Control fast
2382 * reauthentication (TLS session resumption)
2383 * @iter: Pointer to incoming dbus message iter
2384 * @error: Location to store error on failure
2385 * @user_data: Function specific data
2386 * Returns: TRUE on success, FALSE on failure
2387 *
2388 * Getter function for "FastReauth" property.
2389 */
2390dbus_bool_t wpas_dbus_getter_fast_reauth(DBusMessageIter *iter,
2391 DBusError *error,
2392 void *user_data)
2393{
2394 struct wpa_supplicant *wpa_s = user_data;
2395 dbus_bool_t fast_reauth = wpa_s->conf->fast_reauth ? TRUE : FALSE;
2396
2397 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
2398 &fast_reauth, error);
2399}
2400
2401
2402/**
2403 * wpas_dbus_setter_fast_reauth - Control fast
2404 * reauthentication (TLS session resumption)
2405 * @iter: Pointer to incoming dbus message iter
2406 * @error: Location to store error on failure
2407 * @user_data: Function specific data
2408 * Returns: TRUE on success, FALSE on failure
2409 *
2410 * Setter function for "FastReauth" property.
2411 */
2412dbus_bool_t wpas_dbus_setter_fast_reauth(DBusMessageIter *iter,
2413 DBusError *error,
2414 void *user_data)
2415{
2416 struct wpa_supplicant *wpa_s = user_data;
2417 dbus_bool_t fast_reauth;
2418
2419 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
2420 &fast_reauth))
2421 return FALSE;
2422
2423 wpa_s->conf->fast_reauth = fast_reauth;
2424 return TRUE;
2425}
2426
2427
0bb1e425
GM
2428/**
2429 * wpas_dbus_getter_disconnect_reason - Get most recent reason for disconnect
2430 * @iter: Pointer to incoming dbus message iter
2431 * @error: Location to store error on failure
2432 * @user_data: Function specific data
2433 * Returns: TRUE on success, FALSE on failure
2434 *
2435 * Getter for "DisconnectReason" property. The reason is negative if it is
2436 * locally generated.
2437 */
2438dbus_bool_t wpas_dbus_getter_disconnect_reason(DBusMessageIter *iter,
2439 DBusError *error,
2440 void *user_data)
2441{
2442 struct wpa_supplicant *wpa_s = user_data;
2443 dbus_int32_t reason = wpa_s->disconnect_reason;
2444 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
2445 &reason, error);
2446}
2447
2448
78633c37
SL
2449/**
2450 * wpas_dbus_getter_bss_expire_age - Get BSS entry expiration age
6aeeb6fa
DW
2451 * @iter: Pointer to incoming dbus message iter
2452 * @error: Location to store error on failure
2453 * @user_data: Function specific data
2454 * Returns: TRUE on success, FALSE on failure
78633c37
SL
2455 *
2456 * Getter function for "BSSExpireAge" property.
2457 */
6aeeb6fa
DW
2458dbus_bool_t wpas_dbus_getter_bss_expire_age(DBusMessageIter *iter,
2459 DBusError *error,
2460 void *user_data)
78633c37 2461{
6aeeb6fa 2462 struct wpa_supplicant *wpa_s = user_data;
78633c37 2463 dbus_uint32_t expire_age = wpa_s->conf->bss_expiration_age;
6aeeb6fa
DW
2464
2465 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
2466 &expire_age, error);
78633c37
SL
2467}
2468
2469
2470/**
2471 * wpas_dbus_setter_bss_expire_age - Control BSS entry expiration age
6aeeb6fa
DW
2472 * @iter: Pointer to incoming dbus message iter
2473 * @error: Location to store error on failure
2474 * @user_data: Function specific data
2475 * Returns: TRUE on success, FALSE on failure
78633c37
SL
2476 *
2477 * Setter function for "BSSExpireAge" property.
2478 */
6aeeb6fa
DW
2479dbus_bool_t wpas_dbus_setter_bss_expire_age(DBusMessageIter *iter,
2480 DBusError *error,
2481 void *user_data)
78633c37 2482{
6aeeb6fa 2483 struct wpa_supplicant *wpa_s = user_data;
78633c37
SL
2484 dbus_uint32_t expire_age;
2485
6aeeb6fa
DW
2486 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
2487 &expire_age))
2488 return FALSE;
78633c37
SL
2489
2490 if (wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age)) {
6aeeb6fa
DW
2491 dbus_set_error_const(error, DBUS_ERROR_FAILED,
2492 "BSSExpireAge must be >= 10");
2493 return FALSE;
78633c37 2494 }
6aeeb6fa 2495 return TRUE;
78633c37
SL
2496}
2497
2498
2499/**
2500 * wpas_dbus_getter_bss_expire_count - Get BSS entry expiration scan count
6aeeb6fa
DW
2501 * @iter: Pointer to incoming dbus message iter
2502 * @error: Location to store error on failure
2503 * @user_data: Function specific data
2504 * Returns: TRUE on success, FALSE on failure
78633c37
SL
2505 *
2506 * Getter function for "BSSExpireCount" property.
2507 */
6aeeb6fa
DW
2508dbus_bool_t wpas_dbus_getter_bss_expire_count(DBusMessageIter *iter,
2509 DBusError *error,
2510 void *user_data)
78633c37 2511{
6aeeb6fa 2512 struct wpa_supplicant *wpa_s = user_data;
c10fe8c1 2513 dbus_uint32_t expire_count = wpa_s->conf->bss_expiration_scan_count;
6aeeb6fa
DW
2514
2515 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
2516 &expire_count, error);
78633c37
SL
2517}
2518
2519
2520/**
2521 * wpas_dbus_setter_bss_expire_count - Control BSS entry expiration scan count
6aeeb6fa
DW
2522 * @iter: Pointer to incoming dbus message iter
2523 * @error: Location to store error on failure
2524 * @user_data: Function specific data
2525 * Returns: TRUE on success, FALSE on failure
78633c37
SL
2526 *
2527 * Setter function for "BSSExpireCount" property.
2528 */
6aeeb6fa
DW
2529dbus_bool_t wpas_dbus_setter_bss_expire_count(DBusMessageIter *iter,
2530 DBusError *error,
2531 void *user_data)
78633c37 2532{
6aeeb6fa 2533 struct wpa_supplicant *wpa_s = user_data;
78633c37
SL
2534 dbus_uint32_t expire_count;
2535
6aeeb6fa
DW
2536 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
2537 &expire_count))
2538 return FALSE;
78633c37
SL
2539
2540 if (wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count)) {
6aeeb6fa
DW
2541 dbus_set_error_const(error, DBUS_ERROR_FAILED,
2542 "BSSExpireCount must be > 0");
2543 return FALSE;
78633c37 2544 }
6aeeb6fa 2545 return TRUE;
78633c37
SL
2546}
2547
2548
9768da20
SL
2549/**
2550 * wpas_dbus_getter_country - Control country code
6aeeb6fa
DW
2551 * @iter: Pointer to incoming dbus message iter
2552 * @error: Location to store error on failure
2553 * @user_data: Function specific data
2554 * Returns: TRUE on success, FALSE on failure
9768da20
SL
2555 *
2556 * Getter function for "Country" property.
2557 */
6aeeb6fa
DW
2558dbus_bool_t wpas_dbus_getter_country(DBusMessageIter *iter, DBusError *error,
2559 void *user_data)
9768da20 2560{
6aeeb6fa 2561 struct wpa_supplicant *wpa_s = user_data;
9768da20
SL
2562 char country[3];
2563 char *str = country;
2564
2565 country[0] = wpa_s->conf->country[0];
2566 country[1] = wpa_s->conf->country[1];
2567 country[2] = '\0';
2568
6aeeb6fa
DW
2569 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
2570 &str, error);
9768da20
SL
2571}
2572
2573
2574/**
2575 * wpas_dbus_setter_country - Control country code
6aeeb6fa
DW
2576 * @iter: Pointer to incoming dbus message iter
2577 * @error: Location to store error on failure
2578 * @user_data: Function specific data
2579 * Returns: TRUE on success, FALSE on failure
9768da20
SL
2580 *
2581 * Setter function for "Country" property.
2582 */
6aeeb6fa
DW
2583dbus_bool_t wpas_dbus_setter_country(DBusMessageIter *iter, DBusError *error,
2584 void *user_data)
9768da20 2585{
6aeeb6fa 2586 struct wpa_supplicant *wpa_s = user_data;
9768da20
SL
2587 const char *country;
2588
6aeeb6fa
DW
2589 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
2590 &country))
2591 return FALSE;
9768da20 2592
6aeeb6fa
DW
2593 if (!country[0] || !country[1]) {
2594 dbus_set_error_const(error, DBUS_ERROR_FAILED,
2595 "invalid country code");
2596 return FALSE;
2597 }
9768da20
SL
2598
2599 if (wpa_s->drv_priv != NULL && wpa_drv_set_country(wpa_s, country)) {
2600 wpa_printf(MSG_DEBUG, "Failed to set country");
6aeeb6fa
DW
2601 dbus_set_error_const(error, DBUS_ERROR_FAILED,
2602 "failed to set country code");
2603 return FALSE;
9768da20
SL
2604 }
2605
2606 wpa_s->conf->country[0] = country[0];
2607 wpa_s->conf->country[1] = country[1];
6aeeb6fa 2608 return TRUE;
9768da20
SL
2609}
2610
2611
c6e86b63
MA
2612/**
2613 * wpas_dbus_getter_scan_interval - Get scan interval
2614 * @iter: Pointer to incoming dbus message iter
2615 * @error: Location to store error on failure
2616 * @user_data: Function specific data
2617 * Returns: TRUE on success, FALSE on failure
2618 *
2619 * Getter function for "ScanInterval" property.
2620 */
2621dbus_bool_t wpas_dbus_getter_scan_interval(DBusMessageIter *iter,
2622 DBusError *error,
2623 void *user_data)
2624{
2625 struct wpa_supplicant *wpa_s = user_data;
2626 dbus_int32_t scan_interval = wpa_s->scan_interval;
2627
2628 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
2629 &scan_interval, error);
2630}
2631
2632
2633/**
2634 * wpas_dbus_setter_scan_interval - Control scan interval
2635 * @iter: Pointer to incoming dbus message iter
2636 * @error: Location to store error on failure
2637 * @user_data: Function specific data
2638 * Returns: TRUE on success, FALSE on failure
2639 *
2640 * Setter function for "ScanInterval" property.
2641 */
2642dbus_bool_t wpas_dbus_setter_scan_interval(DBusMessageIter *iter,
2643 DBusError *error,
2644 void *user_data)
2645{
2646 struct wpa_supplicant *wpa_s = user_data;
2647 dbus_int32_t scan_interval;
2648
2649 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_INT32,
2650 &scan_interval))
2651 return FALSE;
2652
2653 if (wpa_supplicant_set_scan_interval(wpa_s, scan_interval)) {
2654 dbus_set_error_const(error, DBUS_ERROR_FAILED,
2655 "scan_interval must be >= 0");
2656 return FALSE;
2657 }
2658 return TRUE;
2659}
2660
2661
8fc2fb56
WS
2662/**
2663 * wpas_dbus_getter_ifname - Get interface name
6aeeb6fa
DW
2664 * @iter: Pointer to incoming dbus message iter
2665 * @error: Location to store error on failure
2666 * @user_data: Function specific data
2667 * Returns: TRUE on success, FALSE on failure
8fc2fb56
WS
2668 *
2669 * Getter for "Ifname" property.
2670 */
6aeeb6fa
DW
2671dbus_bool_t wpas_dbus_getter_ifname(DBusMessageIter *iter, DBusError *error,
2672 void *user_data)
8fc2fb56 2673{
6aeeb6fa 2674 struct wpa_supplicant *wpa_s = user_data;
fcea0b7d 2675 const char *ifname = wpa_s->ifname;
6aeeb6fa
DW
2676
2677 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
2678 &ifname, error);
8fc2fb56
WS
2679}
2680
2681
2682/**
2683 * wpas_dbus_getter_driver - Get interface name
6aeeb6fa
DW
2684 * @iter: Pointer to incoming dbus message iter
2685 * @error: Location to store error on failure
2686 * @user_data: Function specific data
2687 * Returns: TRUE on success, FALSE on failure
8fc2fb56
WS
2688 *
2689 * Getter for "Driver" property.
2690 */
6aeeb6fa
DW
2691dbus_bool_t wpas_dbus_getter_driver(DBusMessageIter *iter, DBusError *error,
2692 void *user_data)
8fc2fb56 2693{
6aeeb6fa 2694 struct wpa_supplicant *wpa_s = user_data;
fcea0b7d 2695 const char *driver;
8fc2fb56
WS
2696
2697 if (wpa_s->driver == NULL || wpa_s->driver->name == NULL) {
2698 wpa_printf(MSG_DEBUG, "wpas_dbus_getter_driver[dbus]: "
fcea0b7d 2699 "wpa_s has no driver set");
6aeeb6fa
DW
2700 dbus_set_error(error, DBUS_ERROR_FAILED, "%s: no driver set",
2701 __func__);
2702 return FALSE;
8fc2fb56
WS
2703 }
2704
2705 driver = wpa_s->driver->name;
6aeeb6fa
DW
2706 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
2707 &driver, error);
8fc2fb56
WS
2708}
2709
2710
2711/**
2712 * wpas_dbus_getter_current_bss - Get current bss object path
6aeeb6fa
DW
2713 * @iter: Pointer to incoming dbus message iter
2714 * @error: Location to store error on failure
2715 * @user_data: Function specific data
2716 * Returns: TRUE on success, FALSE on failure
8fc2fb56
WS
2717 *
2718 * Getter for "CurrentBSS" property.
2719 */
6aeeb6fa
DW
2720dbus_bool_t wpas_dbus_getter_current_bss(DBusMessageIter *iter,
2721 DBusError *error,
2722 void *user_data)
8fc2fb56 2723{
6aeeb6fa 2724 struct wpa_supplicant *wpa_s = user_data;
3e87bd54 2725 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *bss_obj_path = path_buf;
8fc2fb56 2726
8f770587 2727 if (wpa_s->current_bss)
5228401c 2728 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
ccd286d0 2729 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
8f770587 2730 wpa_s->dbus_new_path, wpa_s->current_bss->id);
8fc2fb56 2731 else
5228401c 2732 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
8fc2fb56 2733
6aeeb6fa
DW
2734 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
2735 &bss_obj_path, error);
8fc2fb56
WS
2736}
2737
2738
2739/**
2740 * wpas_dbus_getter_current_network - Get current network object path
6aeeb6fa
DW
2741 * @iter: Pointer to incoming dbus message iter
2742 * @error: Location to store error on failure
2743 * @user_data: Function specific data
2744 * Returns: TRUE on success, FALSE on failure
8fc2fb56
WS
2745 *
2746 * Getter for "CurrentNetwork" property.
2747 */
6aeeb6fa
DW
2748dbus_bool_t wpas_dbus_getter_current_network(DBusMessageIter *iter,
2749 DBusError *error,
2750 void *user_data)
8fc2fb56 2751{
6aeeb6fa 2752 struct wpa_supplicant *wpa_s = user_data;
3e87bd54 2753 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *net_obj_path = path_buf;
8fc2fb56
WS
2754
2755 if (wpa_s->current_ssid)
5228401c 2756 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
c49cf2d6
JM
2757 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
2758 wpa_s->dbus_new_path, wpa_s->current_ssid->id);
8fc2fb56 2759 else
5228401c 2760 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
8fc2fb56 2761
6aeeb6fa
DW
2762 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
2763 &net_obj_path, error);
8fc2fb56
WS
2764}
2765
2766
ba6f267f
PS
2767/**
2768 * wpas_dbus_getter_current_auth_mode - Get current authentication type
6aeeb6fa
DW
2769 * @iter: Pointer to incoming dbus message iter
2770 * @error: Location to store error on failure
2771 * @user_data: Function specific data
2772 * Returns: TRUE on success, FALSE on failure
ba6f267f
PS
2773 *
2774 * Getter for "CurrentAuthMode" property.
2775 */
6aeeb6fa
DW
2776dbus_bool_t wpas_dbus_getter_current_auth_mode(DBusMessageIter *iter,
2777 DBusError *error,
2778 void *user_data)
ba6f267f 2779{
6aeeb6fa 2780 struct wpa_supplicant *wpa_s = user_data;
ba6f267f
PS
2781 const char *eap_mode;
2782 const char *auth_mode;
2783 char eap_mode_buf[WPAS_DBUS_AUTH_MODE_MAX];
2784
2785 if (wpa_s->wpa_state != WPA_COMPLETED) {
2786 auth_mode = "INACTIVE";
2787 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X ||
2788 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2789 eap_mode = wpa_supplicant_get_eap_mode(wpa_s);
2790 os_snprintf(eap_mode_buf, WPAS_DBUS_AUTH_MODE_MAX,
2791 "EAP-%s", eap_mode);
2792 auth_mode = eap_mode_buf;
2793
2794 } else {
2795 auth_mode = wpa_key_mgmt_txt(wpa_s->key_mgmt,
2796 wpa_s->current_ssid->proto);
2797 }
2798
6aeeb6fa
DW
2799 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
2800 &auth_mode, error);
ba6f267f
PS
2801}
2802
2803
8fc2fb56
WS
2804/**
2805 * wpas_dbus_getter_bridge_ifname - Get interface name
6aeeb6fa
DW
2806 * @iter: Pointer to incoming dbus message iter
2807 * @error: Location to store error on failure
2808 * @user_data: Function specific data
2809 * Returns: TRUE on success, FALSE on failure
8fc2fb56
WS
2810 *
2811 * Getter for "BridgeIfname" property.
2812 */
6aeeb6fa
DW
2813dbus_bool_t wpas_dbus_getter_bridge_ifname(DBusMessageIter *iter,
2814 DBusError *error,
2815 void *user_data)
8fc2fb56 2816{
6aeeb6fa 2817 struct wpa_supplicant *wpa_s = user_data;
c660b0c2 2818 const char *bridge_ifname = wpa_s->bridge_ifname;
6aeeb6fa
DW
2819 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
2820 &bridge_ifname, error);
8fc2fb56
WS
2821}
2822
2823
2824/**
2825 * wpas_dbus_getter_bsss - Get array of BSSs objects
6aeeb6fa
DW
2826 * @iter: Pointer to incoming dbus message iter
2827 * @error: Location to store error on failure
2828 * @user_data: Function specific data
2829 * Returns: TRUE on success, FALSE on failure
8fc2fb56
WS
2830 *
2831 * Getter for "BSSs" property.
2832 */
6aeeb6fa
DW
2833dbus_bool_t wpas_dbus_getter_bsss(DBusMessageIter *iter, DBusError *error,
2834 void *user_data)
8fc2fb56 2835{
6aeeb6fa 2836 struct wpa_supplicant *wpa_s = user_data;
ccd286d0 2837 struct wpa_bss *bss;
fcea0b7d
WS
2838 char **paths;
2839 unsigned int i = 0;
6aeeb6fa 2840 dbus_bool_t success = FALSE;
8fc2fb56 2841
f9884c09 2842 paths = os_calloc(wpa_s->num_bss, sizeof(char *));
fcea0b7d 2843 if (!paths) {
6aeeb6fa
DW
2844 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
2845 return FALSE;
8fc2fb56
WS
2846 }
2847
2848 /* Loop through scan results and append each result's object path */
ccd286d0 2849 dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
fcea0b7d
WS
2850 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
2851 if (paths[i] == NULL) {
6aeeb6fa
DW
2852 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
2853 "no memory");
8fc2fb56
WS
2854 goto out;
2855 }
ccd286d0 2856 /* Construct the object path for this BSS. */
fcea0b7d 2857 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
ccd286d0 2858 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
c49cf2d6 2859 wpa_s->dbus_new_path, bss->id);
8fc2fb56
WS
2860 }
2861
6aeeb6fa
DW
2862 success = wpas_dbus_simple_array_property_getter(iter,
2863 DBUS_TYPE_OBJECT_PATH,
2864 paths, wpa_s->num_bss,
2865 error);
8fc2fb56
WS
2866
2867out:
3e87bd54 2868 while (i)
fcea0b7d
WS
2869 os_free(paths[--i]);
2870 os_free(paths);
6aeeb6fa 2871 return success;
8fc2fb56
WS
2872}
2873
2874
2875/**
2876 * wpas_dbus_getter_networks - Get array of networks objects
6aeeb6fa
DW
2877 * @iter: Pointer to incoming dbus message iter
2878 * @error: Location to store error on failure
2879 * @user_data: Function specific data
2880 * Returns: TRUE on success, FALSE on failure
8fc2fb56
WS
2881 *
2882 * Getter for "Networks" property.
2883 */
6aeeb6fa
DW
2884dbus_bool_t wpas_dbus_getter_networks(DBusMessageIter *iter, DBusError *error,
2885 void *user_data)
8fc2fb56 2886{
6aeeb6fa 2887 struct wpa_supplicant *wpa_s = user_data;
8fc2fb56 2888 struct wpa_ssid *ssid;
fcea0b7d
WS
2889 char **paths;
2890 unsigned int i = 0, num = 0;
6aeeb6fa 2891 dbus_bool_t success = FALSE;
8fc2fb56
WS
2892
2893 if (wpa_s->conf == NULL) {
6aeeb6fa
DW
2894 wpa_printf(MSG_ERROR, "%s[dbus]: An error occurred getting "
2895 "networks list.", __func__);
2896 dbus_set_error(error, DBUS_ERROR_FAILED, "%s: an error "
2897 "occurred getting the networks list", __func__);
2898 return FALSE;
8fc2fb56
WS
2899 }
2900
fcea0b7d 2901 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
c2762e41
JS
2902 if (!network_is_persistent_group(ssid))
2903 num++;
8fc2fb56 2904
f9884c09 2905 paths = os_calloc(num, sizeof(char *));
fcea0b7d 2906 if (!paths) {
6aeeb6fa
DW
2907 dbus_set_error(error, DBUS_ERROR_NO_MEMORY, "no memory");
2908 return FALSE;
8fc2fb56
WS
2909 }
2910
fcea0b7d 2911 /* Loop through configured networks and append object path of each */
8fc2fb56 2912 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
c2762e41
JS
2913 if (network_is_persistent_group(ssid))
2914 continue;
fcea0b7d
WS
2915 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
2916 if (paths[i] == NULL) {
6aeeb6fa 2917 dbus_set_error(error, DBUS_ERROR_NO_MEMORY, "no memory");
8fc2fb56
WS
2918 goto out;
2919 }
2920
2921 /* Construct the object path for this network. */
fcea0b7d 2922 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
5228401c 2923 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
c49cf2d6 2924 wpa_s->dbus_new_path, ssid->id);
8fc2fb56
WS
2925 }
2926
6aeeb6fa
DW
2927 success = wpas_dbus_simple_array_property_getter(iter,
2928 DBUS_TYPE_OBJECT_PATH,
2929 paths, num, error);
8fc2fb56
WS
2930
2931out:
fcea0b7d
WS
2932 while (i)
2933 os_free(paths[--i]);
2934 os_free(paths);
6aeeb6fa 2935 return success;
8fc2fb56
WS
2936}
2937
2938
2939/**
2940 * wpas_dbus_getter_blobs - Get all blobs defined for this interface
6aeeb6fa
DW
2941 * @iter: Pointer to incoming dbus message iter
2942 * @error: Location to store error on failure
2943 * @user_data: Function specific data
2944 * Returns: TRUE on success, FALSE on failure
8fc2fb56
WS
2945 *
2946 * Getter for "Blobs" property.
2947 */
6aeeb6fa
DW
2948dbus_bool_t wpas_dbus_getter_blobs(DBusMessageIter *iter, DBusError *error,
2949 void *user_data)
8fc2fb56 2950{
6aeeb6fa
DW
2951 struct wpa_supplicant *wpa_s = user_data;
2952 DBusMessageIter variant_iter, dict_iter, entry_iter, array_iter;
8fc2fb56
WS
2953 struct wpa_config_blob *blob;
2954
6aeeb6fa 2955 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
c2b8c674
JM
2956 "a{say}", &variant_iter) ||
2957 !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
5228401c 2958 "{say}", &dict_iter)) {
6aeeb6fa
DW
2959 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
2960 return FALSE;
8fc2fb56
WS
2961 }
2962
2963 blob = wpa_s->conf->blobs;
2964 while (blob) {
5228401c
JM
2965 if (!dbus_message_iter_open_container(&dict_iter,
2966 DBUS_TYPE_DICT_ENTRY,
c2b8c674
JM
2967 NULL, &entry_iter) ||
2968 !dbus_message_iter_append_basic(&entry_iter,
5228401c 2969 DBUS_TYPE_STRING,
c2b8c674
JM
2970 &(blob->name)) ||
2971 !dbus_message_iter_open_container(&entry_iter,
5228401c
JM
2972 DBUS_TYPE_ARRAY,
2973 DBUS_TYPE_BYTE_AS_STRING,
c2b8c674
JM
2974 &array_iter) ||
2975 !dbus_message_iter_append_fixed_array(&array_iter,
5228401c
JM
2976 DBUS_TYPE_BYTE,
2977 &(blob->data),
c2b8c674
JM
2978 blob->len) ||
2979 !dbus_message_iter_close_container(&entry_iter,
2980 &array_iter) ||
2981 !dbus_message_iter_close_container(&dict_iter,
5228401c 2982 &entry_iter)) {
6aeeb6fa
DW
2983 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
2984 "no memory");
2985 return FALSE;
8fc2fb56
WS
2986 }
2987
2988 blob = blob->next;
2989 }
2990
c2b8c674 2991 if (!dbus_message_iter_close_container(&variant_iter, &dict_iter) ||
6aeeb6fa
DW
2992 !dbus_message_iter_close_container(iter, &variant_iter)) {
2993 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
2994 return FALSE;
8fc2fb56
WS
2995 }
2996
6aeeb6fa
DW
2997 return TRUE;
2998}
2999
3000
3001static struct wpa_bss * get_bss_helper(struct bss_handler_args *args,
3002 DBusError *error, const char *func_name)
3003{
3004 struct wpa_bss *res = wpa_bss_get_id(args->wpa_s, args->id);
3005
3006 if (!res) {
3007 wpa_printf(MSG_ERROR, "%s[dbus]: no bss with id %d found",
3008 func_name, args->id);
3009 dbus_set_error(error, DBUS_ERROR_FAILED,
3010 "%s: BSS %d not found",
3011 func_name, args->id);
3012 }
3013
3014 return res;
8fc2fb56
WS
3015}
3016
3017
3018/**
58605c6e 3019 * wpas_dbus_getter_bss_bssid - Return the BSSID of a BSS
6aeeb6fa
DW
3020 * @iter: Pointer to incoming dbus message iter
3021 * @error: Location to store error on failure
3022 * @user_data: Function specific data
3023 * Returns: TRUE on success, FALSE on failure
8fc2fb56 3024 *
58605c6e 3025 * Getter for "BSSID" property.
8fc2fb56 3026 */
6aeeb6fa
DW
3027dbus_bool_t wpas_dbus_getter_bss_bssid(DBusMessageIter *iter, DBusError *error,
3028 void *user_data)
58605c6e 3029{
6aeeb6fa
DW
3030 struct bss_handler_args *args = user_data;
3031 struct wpa_bss *res;
58605c6e 3032
6aeeb6fa
DW
3033 res = get_bss_helper(args, error, __func__);
3034 if (!res)
3035 return FALSE;
58605c6e 3036
6aeeb6fa
DW
3037 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
3038 res->bssid, ETH_ALEN,
3039 error);
58605c6e
WS
3040}
3041
3042
3043/**
3044 * wpas_dbus_getter_bss_ssid - Return the SSID of a BSS
6aeeb6fa
DW
3045 * @iter: Pointer to incoming dbus message iter
3046 * @error: Location to store error on failure
3047 * @user_data: Function specific data
3048 * Returns: TRUE on success, FALSE on failure
58605c6e
WS
3049 *
3050 * Getter for "SSID" property.
3051 */
6aeeb6fa
DW
3052dbus_bool_t wpas_dbus_getter_bss_ssid(DBusMessageIter *iter, DBusError *error,
3053 void *user_data)
8fc2fb56 3054{
6aeeb6fa
DW
3055 struct bss_handler_args *args = user_data;
3056 struct wpa_bss *res;
8fc2fb56 3057
6aeeb6fa
DW
3058 res = get_bss_helper(args, error, __func__);
3059 if (!res)
3060 return FALSE;
8fc2fb56 3061
6aeeb6fa
DW
3062 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
3063 res->ssid, res->ssid_len,
3064 error);
58605c6e 3065}
8fc2fb56 3066
8fc2fb56 3067
58605c6e
WS
3068/**
3069 * wpas_dbus_getter_bss_privacy - Return the privacy flag of a BSS
6aeeb6fa
DW
3070 * @iter: Pointer to incoming dbus message iter
3071 * @error: Location to store error on failure
3072 * @user_data: Function specific data
3073 * Returns: TRUE on success, FALSE on failure
58605c6e
WS
3074 *
3075 * Getter for "Privacy" property.
3076 */
6aeeb6fa
DW
3077dbus_bool_t wpas_dbus_getter_bss_privacy(DBusMessageIter *iter,
3078 DBusError *error, void *user_data)
58605c6e 3079{
6aeeb6fa
DW
3080 struct bss_handler_args *args = user_data;
3081 struct wpa_bss *res;
58605c6e 3082 dbus_bool_t privacy;
8fc2fb56 3083
6aeeb6fa
DW
3084 res = get_bss_helper(args, error, __func__);
3085 if (!res)
3086 return FALSE;
8fc2fb56 3087
097c5802 3088 privacy = (res->caps & IEEE80211_CAP_PRIVACY) ? TRUE : FALSE;
6aeeb6fa
DW
3089 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
3090 &privacy, error);
58605c6e 3091}
8fc2fb56 3092
8fc2fb56 3093
58605c6e
WS
3094/**
3095 * wpas_dbus_getter_bss_mode - Return the mode of a BSS
6aeeb6fa
DW
3096 * @iter: Pointer to incoming dbus message iter
3097 * @error: Location to store error on failure
3098 * @user_data: Function specific data
3099 * Returns: TRUE on success, FALSE on failure
58605c6e
WS
3100 *
3101 * Getter for "Mode" property.
3102 */
6aeeb6fa
DW
3103dbus_bool_t wpas_dbus_getter_bss_mode(DBusMessageIter *iter, DBusError *error,
3104 void *user_data)
58605c6e 3105{
6aeeb6fa
DW
3106 struct bss_handler_args *args = user_data;
3107 struct wpa_bss *res;
58605c6e
WS
3108 const char *mode;
3109
6aeeb6fa
DW
3110 res = get_bss_helper(args, error, __func__);
3111 if (!res)
3112 return FALSE;
8fc2fb56 3113
58605c6e
WS
3114 if (res->caps & IEEE80211_CAP_IBSS)
3115 mode = "ad-hoc";
3116 else
3117 mode = "infrastructure";
3118
6aeeb6fa
DW
3119 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3120 &mode, error);
58605c6e
WS
3121}
3122
3123
3124/**
3125 * wpas_dbus_getter_bss_level - Return the signal strength of a BSS
6aeeb6fa
DW
3126 * @iter: Pointer to incoming dbus message iter
3127 * @error: Location to store error on failure
3128 * @user_data: Function specific data
3129 * Returns: TRUE on success, FALSE on failure
58605c6e
WS
3130 *
3131 * Getter for "Level" property.
3132 */
6aeeb6fa
DW
3133dbus_bool_t wpas_dbus_getter_bss_signal(DBusMessageIter *iter,
3134 DBusError *error, void *user_data)
58605c6e 3135{
6aeeb6fa
DW
3136 struct bss_handler_args *args = user_data;
3137 struct wpa_bss *res;
3d0a8438 3138 s16 level;
58605c6e 3139
6aeeb6fa
DW
3140 res = get_bss_helper(args, error, __func__);
3141 if (!res)
3142 return FALSE;
8fc2fb56 3143
3d0a8438 3144 level = (s16) res->level;
6aeeb6fa 3145 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT16,
3d0a8438 3146 &level, error);
58605c6e
WS
3147}
3148
3149
3150/**
3151 * wpas_dbus_getter_bss_frequency - Return the frequency of a BSS
6aeeb6fa
DW
3152 * @iter: Pointer to incoming dbus message iter
3153 * @error: Location to store error on failure
3154 * @user_data: Function specific data
3155 * Returns: TRUE on success, FALSE on failure
58605c6e
WS
3156 *
3157 * Getter for "Frequency" property.
3158 */
6aeeb6fa
DW
3159dbus_bool_t wpas_dbus_getter_bss_frequency(DBusMessageIter *iter,
3160 DBusError *error, void *user_data)
58605c6e 3161{
6aeeb6fa
DW
3162 struct bss_handler_args *args = user_data;
3163 struct wpa_bss *res;
3d0a8438 3164 u16 freq;
58605c6e 3165
6aeeb6fa
DW
3166 res = get_bss_helper(args, error, __func__);
3167 if (!res)
3168 return FALSE;
8fc2fb56 3169
3d0a8438 3170 freq = (u16) res->freq;
6aeeb6fa 3171 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
3d0a8438 3172 &freq, error);
58605c6e
WS
3173}
3174
3175
75d328af
WS
3176static int cmp_u8s_desc(const void *a, const void *b)
3177{
3178 return (*(u8 *) b - *(u8 *) a);
3179}
3180
3181
58605c6e 3182/**
75d328af 3183 * wpas_dbus_getter_bss_rates - Return available bit rates of a BSS
6aeeb6fa
DW
3184 * @iter: Pointer to incoming dbus message iter
3185 * @error: Location to store error on failure
3186 * @user_data: Function specific data
3187 * Returns: TRUE on success, FALSE on failure
58605c6e 3188 *
75d328af 3189 * Getter for "Rates" property.
58605c6e 3190 */
6aeeb6fa
DW
3191dbus_bool_t wpas_dbus_getter_bss_rates(DBusMessageIter *iter,
3192 DBusError *error, void *user_data)
58605c6e 3193{
6aeeb6fa
DW
3194 struct bss_handler_args *args = user_data;
3195 struct wpa_bss *res;
75d328af
WS
3196 u8 *ie_rates = NULL;
3197 u32 *real_rates;
3198 int rates_num, i;
6aeeb6fa 3199 dbus_bool_t success = FALSE;
58605c6e 3200
6aeeb6fa
DW
3201 res = get_bss_helper(args, error, __func__);
3202 if (!res)
3203 return FALSE;
8fc2fb56 3204
75d328af
WS
3205 rates_num = wpa_bss_get_bit_rates(res, &ie_rates);
3206 if (rates_num < 0)
6aeeb6fa 3207 return FALSE;
75d328af
WS
3208
3209 qsort(ie_rates, rates_num, 1, cmp_u8s_desc);
3210
3211 real_rates = os_malloc(sizeof(u32) * rates_num);
3212 if (!real_rates) {
3213 os_free(ie_rates);
6aeeb6fa
DW
3214 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3215 return FALSE;
75d328af
WS
3216 }
3217
3218 for (i = 0; i < rates_num; i++)
3219 real_rates[i] = ie_rates[i] * 500000;
3220
6aeeb6fa
DW
3221 success = wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_UINT32,
3222 real_rates, rates_num,
3223 error);
75d328af
WS
3224
3225 os_free(ie_rates);
3226 os_free(real_rates);
6aeeb6fa 3227 return success;
58605c6e
WS
3228}
3229
3230
6aeeb6fa
DW
3231static dbus_bool_t wpas_dbus_get_bss_security_prop(DBusMessageIter *iter,
3232 struct wpa_ie_data *ie_data,
3233 DBusError *error)
7899e2f4 3234{
6aeeb6fa 3235 DBusMessageIter iter_dict, variant_iter;
7899e2f4 3236 const char *group;
eb7719ff 3237 const char *pairwise[3]; /* max 3 pairwise ciphers is supported */
7899e2f4
WS
3238 const char *key_mgmt[7]; /* max 7 key managements may be supported */
3239 int n;
3240
6aeeb6fa 3241 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
7899e2f4
WS
3242 "a{sv}", &variant_iter))
3243 goto nomem;
3244
3245 if (!wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
3246 goto nomem;
3247
3248 /* KeyMgmt */
3249 n = 0;
3250 if (ie_data->key_mgmt & WPA_KEY_MGMT_PSK)
3251 key_mgmt[n++] = "wpa-psk";
3252 if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_PSK)
3253 key_mgmt[n++] = "wpa-ft-psk";
3254 if (ie_data->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
3255 key_mgmt[n++] = "wpa-psk-sha256";
3256 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X)
3257 key_mgmt[n++] = "wpa-eap";
3258 if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X)
3259 key_mgmt[n++] = "wpa-ft-eap";
3260 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256)
3261 key_mgmt[n++] = "wpa-eap-sha256";
3262 if (ie_data->key_mgmt & WPA_KEY_MGMT_NONE)
3263 key_mgmt[n++] = "wpa-none";
3264
3265 if (!wpa_dbus_dict_append_string_array(&iter_dict, "KeyMgmt",
3266 key_mgmt, n))
3267 goto nomem;
3268
3269 /* Group */
3270 switch (ie_data->group_cipher) {
3271 case WPA_CIPHER_WEP40:
3272 group = "wep40";
3273 break;
3274 case WPA_CIPHER_TKIP:
3275 group = "tkip";
3276 break;
3277 case WPA_CIPHER_CCMP:
3278 group = "ccmp";
3279 break;
eb7719ff
JM
3280 case WPA_CIPHER_GCMP:
3281 group = "gcmp";
3282 break;
7899e2f4
WS
3283 case WPA_CIPHER_WEP104:
3284 group = "wep104";
3285 break;
3286 default:
3287 group = "";
3288 break;
3289 }
3290
3291 if (!wpa_dbus_dict_append_string(&iter_dict, "Group", group))
3292 goto nomem;
3293
3294 /* Pairwise */
3295 n = 0;
3296 if (ie_data->pairwise_cipher & WPA_CIPHER_TKIP)
3297 pairwise[n++] = "tkip";
3298 if (ie_data->pairwise_cipher & WPA_CIPHER_CCMP)
3299 pairwise[n++] = "ccmp";
eb7719ff
JM
3300 if (ie_data->pairwise_cipher & WPA_CIPHER_GCMP)
3301 pairwise[n++] = "gcmp";
7899e2f4
WS
3302
3303 if (!wpa_dbus_dict_append_string_array(&iter_dict, "Pairwise",
3304 pairwise, n))
3305 goto nomem;
3306
3307 /* Management group (RSN only) */
3308 if (ie_data->proto == WPA_PROTO_RSN) {
3309 switch (ie_data->mgmt_group_cipher) {
3310#ifdef CONFIG_IEEE80211W
3311 case WPA_CIPHER_AES_128_CMAC:
3312 group = "aes128cmac";
3313 break;
3314#endif /* CONFIG_IEEE80211W */
3315 default:
3316 group = "";
3317 break;
3318 }
3319
3320 if (!wpa_dbus_dict_append_string(&iter_dict, "MgmtGroup",
3321 group))
3322 goto nomem;
3323 }
3324
3325 if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict))
3326 goto nomem;
6aeeb6fa 3327 if (!dbus_message_iter_close_container(iter, &variant_iter))
7899e2f4
WS
3328 goto nomem;
3329
6aeeb6fa 3330 return TRUE;
7899e2f4
WS
3331
3332nomem:
6aeeb6fa
DW
3333 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3334 return FALSE;
7899e2f4
WS
3335}
3336
3337
58605c6e 3338/**
7899e2f4 3339 * wpas_dbus_getter_bss_wpa - Return the WPA options of a BSS
6aeeb6fa
DW
3340 * @iter: Pointer to incoming dbus message iter
3341 * @error: Location to store error on failure
3342 * @user_data: Function specific data
3343 * Returns: TRUE on success, FALSE on failure
58605c6e 3344 *
7899e2f4 3345 * Getter for "WPA" property.
58605c6e 3346 */
6aeeb6fa
DW
3347dbus_bool_t wpas_dbus_getter_bss_wpa(DBusMessageIter *iter, DBusError *error,
3348 void *user_data)
58605c6e 3349{
6aeeb6fa
DW
3350 struct bss_handler_args *args = user_data;
3351 struct wpa_bss *res;
7899e2f4 3352 struct wpa_ie_data wpa_data;
58605c6e
WS
3353 const u8 *ie;
3354
6aeeb6fa
DW
3355 res = get_bss_helper(args, error, __func__);
3356 if (!res)
3357 return FALSE;
8fc2fb56 3358
7899e2f4 3359 os_memset(&wpa_data, 0, sizeof(wpa_data));
58605c6e 3360 ie = wpa_bss_get_vendor_ie(res, WPA_IE_VENDOR_TYPE);
af3e1b0e 3361 if (ie) {
6aeeb6fa
DW
3362 if (wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0) {
3363 dbus_set_error_const(error, DBUS_ERROR_FAILED,
3364 "failed to parse WPA IE");
3365 return FALSE;
3366 }
af3e1b0e 3367 }
7899e2f4 3368
6aeeb6fa 3369 return wpas_dbus_get_bss_security_prop(iter, &wpa_data, error);
58605c6e 3370}
8fc2fb56 3371
8fc2fb56 3372
58605c6e 3373/**
7899e2f4 3374 * wpas_dbus_getter_bss_rsn - Return the RSN options of a BSS
6aeeb6fa
DW
3375 * @iter: Pointer to incoming dbus message iter
3376 * @error: Location to store error on failure
3377 * @user_data: Function specific data
3378 * Returns: TRUE on success, FALSE on failure
58605c6e 3379 *
7899e2f4 3380 * Getter for "RSN" property.
58605c6e 3381 */
6aeeb6fa
DW
3382dbus_bool_t wpas_dbus_getter_bss_rsn(DBusMessageIter *iter, DBusError *error,
3383 void *user_data)
58605c6e 3384{
6aeeb6fa
DW
3385 struct bss_handler_args *args = user_data;
3386 struct wpa_bss *res;
7899e2f4 3387 struct wpa_ie_data wpa_data;
58605c6e
WS
3388 const u8 *ie;
3389
6aeeb6fa
DW
3390 res = get_bss_helper(args, error, __func__);
3391 if (!res)
3392 return FALSE;
58605c6e 3393
7899e2f4 3394 os_memset(&wpa_data, 0, sizeof(wpa_data));
58605c6e 3395 ie = wpa_bss_get_ie(res, WLAN_EID_RSN);
af3e1b0e 3396 if (ie) {
6aeeb6fa
DW
3397 if (wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0) {
3398 dbus_set_error_const(error, DBUS_ERROR_FAILED,
3399 "failed to parse RSN IE");
3400 return FALSE;
3401 }
af3e1b0e 3402 }
7899e2f4 3403
6aeeb6fa 3404 return wpas_dbus_get_bss_security_prop(iter, &wpa_data, error);
58605c6e
WS
3405}
3406
3407
caff3992
SN
3408/**
3409 * wpas_dbus_getter_bss_wps - Return the WPS options of a BSS
3410 * @iter: Pointer to incoming dbus message iter
3411 * @error: Location to store error on failure
3412 * @user_data: Function specific data
3413 * Returns: TRUE on success, FALSE on failure
3414 *
3415 * Getter for "WPS" property.
3416 */
3417dbus_bool_t wpas_dbus_getter_bss_wps(DBusMessageIter *iter, DBusError *error,
3418 void *user_data)
3419{
3420 struct bss_handler_args *args = user_data;
3421 struct wpa_bss *res;
3422#ifdef CONFIG_WPS
3423 struct wpabuf *wps_ie;
3424#endif /* CONFIG_WPS */
3425 DBusMessageIter iter_dict, variant_iter;
3426 const char *type = "";
3427
3428 res = get_bss_helper(args, error, __func__);
3429 if (!res)
3430 return FALSE;
3431
3432 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
3433 "a{sv}", &variant_iter))
3434 goto nomem;
3435
3436 if (!wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
3437 goto nomem;
3438
3439#ifdef CONFIG_WPS
3440 wps_ie = wpa_bss_get_vendor_ie_multi(res, WPS_IE_VENDOR_TYPE);
3441 if (wps_ie) {
3442 if (wps_is_selected_pbc_registrar(wps_ie))
3443 type = "pbc";
3444 else if (wps_is_selected_pin_registrar(wps_ie))
3445 type = "pin";
3446 }
3447#endif /* CONFIG_WPS */
3448
3449 if (!wpa_dbus_dict_append_string(&iter_dict, "Type", type))
3450 goto nomem;
3451
3452 if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict))
3453 goto nomem;
3454 if (!dbus_message_iter_close_container(iter, &variant_iter))
3455 goto nomem;
3456
3457 return TRUE;
3458
3459nomem:
3460 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3461 return FALSE;
3462}
3463
3464
58605c6e 3465/**
7899e2f4 3466 * wpas_dbus_getter_bss_ies - Return all IEs of a BSS
6aeeb6fa
DW
3467 * @iter: Pointer to incoming dbus message iter
3468 * @error: Location to store error on failure
3469 * @user_data: Function specific data
3470 * Returns: TRUE on success, FALSE on failure
58605c6e 3471 *
7899e2f4 3472 * Getter for "IEs" property.
58605c6e 3473 */
6aeeb6fa
DW
3474dbus_bool_t wpas_dbus_getter_bss_ies(DBusMessageIter *iter, DBusError *error,
3475 void *user_data)
58605c6e 3476{
6aeeb6fa
DW
3477 struct bss_handler_args *args = user_data;
3478 struct wpa_bss *res;
58605c6e 3479
6aeeb6fa
DW
3480 res = get_bss_helper(args, error, __func__);
3481 if (!res)
3482 return FALSE;
58605c6e 3483
6aeeb6fa
DW
3484 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
3485 res + 1, res->ie_len,
3486 error);
8fc2fb56
WS
3487}
3488
3489
3490/**
3491 * wpas_dbus_getter_enabled - Check whether network is enabled or disabled
6aeeb6fa
DW
3492 * @iter: Pointer to incoming dbus message iter
3493 * @error: Location to store error on failure
3494 * @user_data: Function specific data
3495 * Returns: TRUE on success, FALSE on failure
8fc2fb56
WS
3496 *
3497 * Getter for "enabled" property of a configured network.
3498 */
6aeeb6fa
DW
3499dbus_bool_t wpas_dbus_getter_enabled(DBusMessageIter *iter, DBusError *error,
3500 void *user_data)
8fc2fb56 3501{
6aeeb6fa 3502 struct network_handler_args *net = user_data;
8fc2fb56 3503 dbus_bool_t enabled = net->ssid->disabled ? FALSE : TRUE;
6aeeb6fa
DW
3504
3505 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
3506 &enabled, error);
8fc2fb56
WS
3507}
3508
3509
3510/**
3511 * wpas_dbus_setter_enabled - Mark a configured network as enabled or disabled
6aeeb6fa
DW
3512 * @iter: Pointer to incoming dbus message iter
3513 * @error: Location to store error on failure
3514 * @user_data: Function specific data
3515 * Returns: TRUE on success, FALSE on failure
8fc2fb56
WS
3516 *
3517 * Setter for "Enabled" property of a configured network.
3518 */
6aeeb6fa
DW
3519dbus_bool_t wpas_dbus_setter_enabled(DBusMessageIter *iter, DBusError *error,
3520 void *user_data)
8fc2fb56 3521{
6aeeb6fa 3522 struct network_handler_args *net = user_data;
8fc2fb56
WS
3523 struct wpa_supplicant *wpa_s;
3524 struct wpa_ssid *ssid;
8fc2fb56
WS
3525 dbus_bool_t enable;
3526
6aeeb6fa
DW
3527 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
3528 &enable))
3529 return FALSE;
8fc2fb56
WS
3530
3531 wpa_s = net->wpa_s;
3532 ssid = net->ssid;
3533
5228401c 3534 if (enable)
8fc2fb56 3535 wpa_supplicant_enable_network(wpa_s, ssid);
5228401c 3536 else
8fc2fb56 3537 wpa_supplicant_disable_network(wpa_s, ssid);
8fc2fb56 3538
6aeeb6fa 3539 return TRUE;
8fc2fb56
WS
3540}
3541
3542
3543/**
3544 * wpas_dbus_getter_network_properties - Get options for a configured network
6aeeb6fa
DW
3545 * @iter: Pointer to incoming dbus message iter
3546 * @error: Location to store error on failure
3547 * @user_data: Function specific data
3548 * Returns: TRUE on success, FALSE on failure
8fc2fb56
WS
3549 *
3550 * Getter for "Properties" property of a configured network.
3551 */
6aeeb6fa
DW
3552dbus_bool_t wpas_dbus_getter_network_properties(DBusMessageIter *iter,
3553 DBusError *error,
3554 void *user_data)
8fc2fb56 3555{
6aeeb6fa
DW
3556 struct network_handler_args *net = user_data;
3557 DBusMessageIter variant_iter, dict_iter;
8fc2fb56 3558 char **iterator;
d1c8ac88 3559 char **props = wpa_config_get_all(net->ssid, 1);
6aeeb6fa 3560 dbus_bool_t success = FALSE;
8fc2fb56 3561
6aeeb6fa
DW
3562 if (!props) {
3563 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3564 return FALSE;
8fc2fb56
WS
3565 }
3566
6aeeb6fa
DW
3567 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a{sv}",
3568 &variant_iter) ||
c2b8c674 3569 !wpa_dbus_dict_open_write(&variant_iter, &dict_iter)) {
6aeeb6fa 3570 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
8fc2fb56
WS
3571 goto out;
3572 }
3573
3574 iterator = props;
3575 while (*iterator) {
3576 if (!wpa_dbus_dict_append_string(&dict_iter, *iterator,
5228401c 3577 *(iterator + 1))) {
6aeeb6fa
DW
3578 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
3579 "no memory");
8fc2fb56
WS
3580 goto out;
3581 }
3582 iterator += 2;
3583 }
3584
3585
c2b8c674 3586 if (!wpa_dbus_dict_close_write(&variant_iter, &dict_iter) ||
6aeeb6fa
DW
3587 !dbus_message_iter_close_container(iter, &variant_iter)) {
3588 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
8fc2fb56
WS
3589 goto out;
3590 }
3591
6aeeb6fa
DW
3592 success = TRUE;
3593
8fc2fb56
WS
3594out:
3595 iterator = props;
3596 while (*iterator) {
3597 os_free(*iterator);
3598 iterator++;
3599 }
3600 os_free(props);
6aeeb6fa 3601 return success;
8fc2fb56
WS
3602}
3603
3604
3605/**
3606 * wpas_dbus_setter_network_properties - Set options for a configured network
6aeeb6fa
DW
3607 * @iter: Pointer to incoming dbus message iter
3608 * @error: Location to store error on failure
3609 * @user_data: Function specific data
3610 * Returns: TRUE on success, FALSE on failure
8fc2fb56
WS
3611 *
3612 * Setter for "Properties" property of a configured network.
3613 */
6aeeb6fa
DW
3614dbus_bool_t wpas_dbus_setter_network_properties(DBusMessageIter *iter,
3615 DBusError *error,
3616 void *user_data)
8fc2fb56 3617{
6aeeb6fa 3618 struct network_handler_args *net = user_data;
8fc2fb56 3619 struct wpa_ssid *ssid = net->ssid;
6aeeb6fa 3620 DBusMessageIter variant_iter;
8fc2fb56 3621
6aeeb6fa
DW
3622 dbus_message_iter_recurse(iter, &variant_iter);
3623 return set_network_properties(net->wpa_s, ssid, &variant_iter, error);
8fc2fb56 3624}
2d43d37f
JB
3625
3626
3627#ifdef CONFIG_AP
3628
3629DBusMessage * wpas_dbus_handler_subscribe_preq(
3630 DBusMessage *message, struct wpa_supplicant *wpa_s)
3631{
3632 struct wpas_dbus_priv *priv = wpa_s->global->dbus;
3633 char *name;
3634
3635 if (wpa_s->preq_notify_peer != NULL) {
3636 if (os_strcmp(dbus_message_get_sender(message),
3637 wpa_s->preq_notify_peer) == 0)
3638 return NULL;
3639
3640 return dbus_message_new_error(message,
3641 WPAS_DBUS_ERROR_SUBSCRIPTION_IN_USE,
3642 "Another application is already subscribed");
3643 }
3644
3645 name = os_strdup(dbus_message_get_sender(message));
3646 if (!name)
3647 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
3648 "out of memory");
3649
3650 wpa_s->preq_notify_peer = name;
3651
3652 /* Subscribe to clean up if application closes socket */
3653 wpas_dbus_subscribe_noc(priv);
3654
3655 /*
3656 * Double-check it's still alive to make sure that we didn't
3657 * miss the NameOwnerChanged signal, e.g. while strdup'ing.
3658 */
3659 if (!dbus_bus_name_has_owner(priv->con, name, NULL)) {
3660 /*
3661 * Application no longer exists, clean up.
3662 * The return value is irrelevant now.
3663 *
3664 * Need to check if the NameOwnerChanged handling
3665 * already cleaned up because we have processed
3666 * DBus messages while checking if the name still
3667 * has an owner.
3668 */
3669 if (!wpa_s->preq_notify_peer)
3670 return NULL;
3671 os_free(wpa_s->preq_notify_peer);
3672 wpa_s->preq_notify_peer = NULL;
3673 wpas_dbus_unsubscribe_noc(priv);
3674 }
3675
3676 return NULL;
3677}
3678
3679
3680DBusMessage * wpas_dbus_handler_unsubscribe_preq(
3681 DBusMessage *message, struct wpa_supplicant *wpa_s)
3682{
3683 struct wpas_dbus_priv *priv = wpa_s->global->dbus;
3684
3685 if (!wpa_s->preq_notify_peer)
3686 return dbus_message_new_error(message,
3687 WPAS_DBUS_ERROR_NO_SUBSCRIPTION,
3688 "Not subscribed");
3689
3690 if (os_strcmp(wpa_s->preq_notify_peer,
3691 dbus_message_get_sender(message)))
3692 return dbus_message_new_error(message,
3693 WPAS_DBUS_ERROR_SUBSCRIPTION_EPERM,
3694 "Can't unsubscribe others");
3695
3696 os_free(wpa_s->preq_notify_peer);
3697 wpa_s->preq_notify_peer = NULL;
3698 wpas_dbus_unsubscribe_noc(priv);
3699 return NULL;
3700}
3701
3702
3703void wpas_dbus_signal_preq(struct wpa_supplicant *wpa_s,
3704 const u8 *addr, const u8 *dst, const u8 *bssid,
3705 const u8 *ie, size_t ie_len, u32 ssi_signal)
3706{
3707 DBusMessage *msg;
3708 DBusMessageIter iter, dict_iter;
3709 struct wpas_dbus_priv *priv = wpa_s->global->dbus;
3710
3711 /* Do nothing if the control interface is not turned on */
3712 if (priv == NULL)
3713 return;
3714
3715 if (wpa_s->preq_notify_peer == NULL)
3716 return;
3717
3718 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
3719 WPAS_DBUS_NEW_IFACE_INTERFACE,
3720 "ProbeRequest");
3721 if (msg == NULL)
3722 return;
3723
3724 dbus_message_set_destination(msg, wpa_s->preq_notify_peer);
3725
3726 dbus_message_iter_init_append(msg, &iter);
3727
3728 if (!wpa_dbus_dict_open_write(&iter, &dict_iter))
3729 goto fail;
3730 if (addr && !wpa_dbus_dict_append_byte_array(&dict_iter, "addr",
3731 (const char *) addr,
3732 ETH_ALEN))
3733 goto fail;
3734 if (dst && !wpa_dbus_dict_append_byte_array(&dict_iter, "dst",
3735 (const char *) dst,
3736 ETH_ALEN))
3737 goto fail;
3738 if (bssid && !wpa_dbus_dict_append_byte_array(&dict_iter, "bssid",
3739 (const char *) bssid,
3740 ETH_ALEN))
3741 goto fail;
3742 if (ie && ie_len && !wpa_dbus_dict_append_byte_array(&dict_iter, "ies",
3743 (const char *) ie,
3744 ie_len))
3745 goto fail;
3746 if (ssi_signal && !wpa_dbus_dict_append_int32(&dict_iter, "signal",
3747 ssi_signal))
3748 goto fail;
3749 if (!wpa_dbus_dict_close_write(&iter, &dict_iter))
3750 goto fail;
3751
3752 dbus_connection_send(priv->con, msg, NULL);
3753 goto out;
3754fail:
3755 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
3756out:
3757 dbus_message_unref(msg);
3758}
3759
3760#endif /* CONFIG_AP */