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