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