]> git.ipfire.org Git - thirdparty/hostap.git/blame - wpa_supplicant/dbus/dbus_new_handlers.c
P2P: Fix a typo in debug message
[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
JM
437 if (!dbus_message_iter_append_basic(&array_iter, type,
438 array + i * element_size)) {
439 dbus_set_error(error, DBUS_ERROR_FAILED,
440 "%s: failed to construct message 2.5",
441 __func__);
442 return FALSE;
443 }
fcea0b7d
WS
444 }
445
e3c4f0b5
JM
446 if (!dbus_message_iter_close_container(&variant_iter, &array_iter) ||
447 !dbus_message_iter_close_container(iter, &variant_iter)) {
6aeeb6fa 448 dbus_set_error(error, DBUS_ERROR_FAILED,
38279bdb 449 "%s: failed to construct message 3", __func__);
6aeeb6fa 450 return FALSE;
fcea0b7d
WS
451 }
452
96c4f3a7
JS
453 return TRUE;
454}
455
456
457/**
458 * wpas_dbus_simple_array_array_property_getter - Get array array type property
459 * @iter: Pointer to incoming dbus message iterator
460 * @type: DBus type of property array elements (must be basic type)
461 * @array: pointer to array of elements to put into response message
462 * @array_len: length of above array
463 * @error: a pointer to an error to fill on failure
464 * Returns: TRUE if the request succeeded, FALSE if it failed
465 *
466 * Generic getter for array type properties. Array elements type is
467 * required to be basic.
468 */
469dbus_bool_t wpas_dbus_simple_array_array_property_getter(DBusMessageIter *iter,
470 const int type,
471 struct wpabuf **array,
472 size_t array_len,
473 DBusError *error)
474{
475 DBusMessageIter variant_iter, array_iter;
476 char type_str[] = "aa?";
477 char inner_type_str[] = "a?";
478 const char *sub_type_str;
479 size_t i;
480
481 if (!dbus_type_is_basic(type)) {
482 dbus_set_error(error, DBUS_ERROR_FAILED,
483 "%s: given type is not basic", __func__);
484 return FALSE;
485 }
486
487 sub_type_str = wpa_dbus_type_as_string(type);
488 type_str[2] = sub_type_str[0];
489 inner_type_str[1] = sub_type_str[0];
490
491 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
e3c4f0b5
JM
492 type_str, &variant_iter) ||
493 !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
96c4f3a7
JS
494 inner_type_str, &array_iter)) {
495 dbus_set_error(error, DBUS_ERROR_FAILED,
e3c4f0b5 496 "%s: failed to construct message", __func__);
96c4f3a7
JS
497 return FALSE;
498 }
499
010fc5f5 500 for (i = 0; i < array_len && array[i]; i++) {
96c4f3a7
JS
501 wpa_dbus_dict_bin_array_add_element(&array_iter,
502 wpabuf_head(array[i]),
503 wpabuf_len(array[i]));
504
505 }
506
e3c4f0b5
JM
507 if (!dbus_message_iter_close_container(&variant_iter, &array_iter) ||
508 !dbus_message_iter_close_container(iter, &variant_iter)) {
96c4f3a7 509 dbus_set_error(error, DBUS_ERROR_FAILED,
e3c4f0b5 510 "%s: failed to close message", __func__);
6aeeb6fa
DW
511 return FALSE;
512 }
513
514 return TRUE;
fcea0b7d
WS
515}
516
517
8fc2fb56
WS
518/**
519 * wpas_dbus_handler_create_interface - Request registration of a network iface
520 * @message: Pointer to incoming dbus message
521 * @global: %wpa_supplicant global data structure
522 * Returns: The object path of the new interface object,
523 * or a dbus error message with more information
524 *
2f00ad44 525 * Handler function for "CreateInterface" method call. Handles requests
8fc2fb56
WS
526 * by dbus clients to register a network interface that wpa_supplicant
527 * will manage.
528 */
529DBusMessage * wpas_dbus_handler_create_interface(DBusMessage *message,
5228401c 530 struct wpa_global *global)
8fc2fb56 531{
8fc2fb56
WS
532 DBusMessageIter iter_dict;
533 DBusMessage *reply = NULL;
534 DBusMessageIter iter;
535 struct wpa_dbus_dict_entry entry;
2f00ad44
JM
536 char *driver = NULL;
537 char *ifname = NULL;
d4c1ec56 538 char *confname = NULL;
2f00ad44 539 char *bridge_ifname = NULL;
8fc2fb56
WS
540
541 dbus_message_iter_init(message, &iter);
542
6aeeb6fa 543 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
8fc2fb56
WS
544 goto error;
545 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
546 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
547 goto error;
38279bdb
JM
548 if (os_strcmp(entry.key, "Driver") == 0 &&
549 entry.type == DBUS_TYPE_STRING) {
beb9e117 550 os_free(driver);
2f00ad44
JM
551 driver = os_strdup(entry.str_value);
552 wpa_dbus_dict_entry_clear(&entry);
553 if (driver == NULL)
a354bcc8 554 goto oom;
38279bdb
JM
555 } else if (os_strcmp(entry.key, "Ifname") == 0 &&
556 entry.type == DBUS_TYPE_STRING) {
beb9e117 557 os_free(ifname);
2f00ad44
JM
558 ifname = os_strdup(entry.str_value);
559 wpa_dbus_dict_entry_clear(&entry);
560 if (ifname == NULL)
a354bcc8 561 goto oom;
38279bdb
JM
562 } else if (os_strcmp(entry.key, "ConfigFile") == 0 &&
563 entry.type == DBUS_TYPE_STRING) {
beb9e117 564 os_free(confname);
d4c1ec56
SL
565 confname = os_strdup(entry.str_value);
566 wpa_dbus_dict_entry_clear(&entry);
567 if (confname == NULL)
a354bcc8 568 goto oom;
38279bdb
JM
569 } else if (os_strcmp(entry.key, "BridgeIfname") == 0 &&
570 entry.type == DBUS_TYPE_STRING) {
beb9e117 571 os_free(bridge_ifname);
2f00ad44
JM
572 bridge_ifname = os_strdup(entry.str_value);
573 wpa_dbus_dict_entry_clear(&entry);
574 if (bridge_ifname == NULL)
a354bcc8 575 goto oom;
5228401c 576 } else {
8fc2fb56
WS
577 wpa_dbus_dict_entry_clear(&entry);
578 goto error;
579 }
8fc2fb56
WS
580 }
581
2f00ad44
JM
582 if (ifname == NULL)
583 goto error; /* Required Ifname argument missing */
584
8fc2fb56
WS
585 /*
586 * Try to get the wpa_supplicant record for this iface, return
587 * an error if we already control it.
588 */
2f00ad44 589 if (wpa_supplicant_get_iface(global, ifname) != NULL) {
38279bdb
JM
590 reply = dbus_message_new_error(
591 message, WPAS_DBUS_ERROR_IFACE_EXISTS,
592 "wpa_supplicant already controls this interface.");
8fc2fb56
WS
593 } else {
594 struct wpa_supplicant *wpa_s;
2f00ad44 595 struct wpa_interface iface;
38279bdb 596
2f00ad44
JM
597 os_memset(&iface, 0, sizeof(iface));
598 iface.driver = driver;
599 iface.ifname = ifname;
d4c1ec56 600 iface.confname = confname;
2f00ad44 601 iface.bridge_ifname = bridge_ifname;
8fc2fb56 602 /* Otherwise, have wpa_supplicant attach to it. */
1772d348 603 wpa_s = wpa_supplicant_add_iface(global, &iface, NULL);
8a78e227 604 if (wpa_s && wpa_s->dbus_new_path) {
c49cf2d6 605 const char *path = wpa_s->dbus_new_path;
38279bdb 606
8fc2fb56
WS
607 reply = dbus_message_new_method_return(message);
608 dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH,
38279bdb 609 &path, DBUS_TYPE_INVALID);
8fc2fb56 610 } else {
5228401c 611 reply = wpas_dbus_error_unknown_error(
38279bdb
JM
612 message,
613 "wpa_supplicant couldn't grab this interface.");
8fc2fb56
WS
614 }
615 }
2f00ad44
JM
616
617out:
618 os_free(driver);
619 os_free(ifname);
21270bb4 620 os_free(confname);
2f00ad44 621 os_free(bridge_ifname);
8fc2fb56
WS
622 return reply;
623
624error:
db9a76c0 625 reply = wpas_dbus_error_invalid_args(message, NULL);
2f00ad44 626 goto out;
a354bcc8
JM
627oom:
628 reply = wpas_dbus_error_no_memory(message);
629 goto out;
8fc2fb56
WS
630}
631
632
633/**
634 * wpas_dbus_handler_remove_interface - Request deregistration of an interface
635 * @message: Pointer to incoming dbus message
636 * @global: wpa_supplicant global data structure
637 * Returns: a dbus message containing a UINT32 indicating success (1) or
638 * failure (0), or returns a dbus error message with more information
639 *
640 * Handler function for "removeInterface" method call. Handles requests
641 * by dbus clients to deregister a network interface that wpa_supplicant
642 * currently manages.
643 */
644DBusMessage * wpas_dbus_handler_remove_interface(DBusMessage *message,
5228401c 645 struct wpa_global *global)
8fc2fb56
WS
646{
647 struct wpa_supplicant *wpa_s;
648 char *path;
649 DBusMessage *reply = NULL;
650
651 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path,
5228401c 652 DBUS_TYPE_INVALID);
8fc2fb56
WS
653
654 wpa_s = get_iface_by_dbus_path(global, path);
5228401c 655 if (wpa_s == NULL)
8fc2fb56 656 reply = wpas_dbus_error_iface_unknown(message);
df509539 657 else if (wpa_supplicant_remove_iface(global, wpa_s, 0)) {
5228401c 658 reply = wpas_dbus_error_unknown_error(
38279bdb
JM
659 message,
660 "wpa_supplicant couldn't remove this interface.");
8fc2fb56
WS
661 }
662
663 return reply;
664}
665
666
667/**
668 * wpas_dbus_handler_get_interface - Get the object path for an interface name
669 * @message: Pointer to incoming dbus message
670 * @global: %wpa_supplicant global data structure
671 * Returns: The object path of the interface object,
672 * or a dbus error message with more information
673 *
674 * Handler function for "getInterface" method call.
675 */
676DBusMessage * wpas_dbus_handler_get_interface(DBusMessage *message,
5228401c 677 struct wpa_global *global)
8fc2fb56
WS
678{
679 DBusMessage *reply = NULL;
680 const char *ifname;
681 const char *path;
682 struct wpa_supplicant *wpa_s;
683
684 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &ifname,
5228401c 685 DBUS_TYPE_INVALID);
8fc2fb56
WS
686
687 wpa_s = wpa_supplicant_get_iface(global, ifname);
8a78e227 688 if (wpa_s == NULL || wpa_s->dbus_new_path == NULL)
5228401c 689 return wpas_dbus_error_iface_unknown(message);
8fc2fb56 690
c49cf2d6 691 path = wpa_s->dbus_new_path;
8fc2fb56 692 reply = dbus_message_new_method_return(message);
c2b8c674 693 if (reply == NULL)
a0caebf3 694 return wpas_dbus_error_no_memory(message);
8fc2fb56 695 if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
5228401c 696 DBUS_TYPE_INVALID)) {
8fc2fb56 697 dbus_message_unref(reply);
a0caebf3 698 return wpas_dbus_error_no_memory(message);
8fc2fb56
WS
699 }
700
8fc2fb56
WS
701 return reply;
702}
703
704
705/**
db9133ac 706 * wpas_dbus_getter_debug_level - Get debug level
6aeeb6fa
DW
707 * @iter: Pointer to incoming dbus message iter
708 * @error: Location to store error on failure
709 * @user_data: Function specific data
710 * Returns: TRUE on success, FALSE on failure
8fc2fb56 711 *
db9133ac 712 * Getter for "DebugLevel" property.
8fc2fb56 713 */
1aa0fb77
DW
714dbus_bool_t wpas_dbus_getter_debug_level(
715 const struct wpa_dbus_property_desc *property_desc,
716 DBusMessageIter *iter, DBusError *error, void *user_data)
8fc2fb56 717{
a2753c28
MH
718 const char *str;
719 int idx = wpa_debug_level;
6aeeb6fa 720
a2753c28
MH
721 if (idx < 0)
722 idx = 0;
14dc0011
PS
723 if (idx > 5)
724 idx = 5;
a2753c28 725 str = debug_strings[idx];
6aeeb6fa
DW
726 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
727 &str, error);
db9133ac 728}
8fc2fb56 729
8fc2fb56 730
db9133ac
WS
731/**
732 * wpas_dbus_getter_debug_timestamp - Get debug timestamp
6aeeb6fa
DW
733 * @iter: Pointer to incoming dbus message iter
734 * @error: Location to store error on failure
735 * @user_data: Function specific data
736 * Returns: TRUE on success, FALSE on failure
db9133ac
WS
737 *
738 * Getter for "DebugTimestamp" property.
739 */
1aa0fb77
DW
740dbus_bool_t wpas_dbus_getter_debug_timestamp(
741 const struct wpa_dbus_property_desc *property_desc,
742 DBusMessageIter *iter, DBusError *error, void *user_data)
db9133ac 743{
6aeeb6fa
DW
744 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
745 &wpa_debug_timestamp, error);
8fc2fb56 746
db9133ac 747}
8fc2fb56 748
8fc2fb56 749
db9133ac
WS
750/**
751 * wpas_dbus_getter_debug_show_keys - Get debug show keys
6aeeb6fa
DW
752 * @iter: Pointer to incoming dbus message iter
753 * @error: Location to store error on failure
754 * @user_data: Function specific data
755 * Returns: TRUE on success, FALSE on failure
db9133ac
WS
756 *
757 * Getter for "DebugShowKeys" property.
758 */
1aa0fb77
DW
759dbus_bool_t wpas_dbus_getter_debug_show_keys(
760 const struct wpa_dbus_property_desc *property_desc,
761 DBusMessageIter *iter, DBusError *error, void *user_data)
db9133ac 762{
6aeeb6fa
DW
763 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
764 &wpa_debug_show_keys, error);
8fc2fb56 765
db9133ac 766}
8fc2fb56 767
db9133ac
WS
768/**
769 * wpas_dbus_setter_debug_level - Set debug level
6aeeb6fa
DW
770 * @iter: Pointer to incoming dbus message iter
771 * @error: Location to store error on failure
772 * @user_data: Function specific data
773 * Returns: TRUE on success, FALSE on failure
db9133ac
WS
774 *
775 * Setter for "DebugLevel" property.
776 */
1aa0fb77
DW
777dbus_bool_t wpas_dbus_setter_debug_level(
778 const struct wpa_dbus_property_desc *property_desc,
779 DBusMessageIter *iter, DBusError *error, void *user_data)
db9133ac 780{
6aeeb6fa 781 struct wpa_global *global = user_data;
a2753c28
MH
782 const char *str = NULL;
783 int i, val = -1;
8fc2fb56 784
6aeeb6fa
DW
785 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
786 &str))
787 return FALSE;
db9133ac 788
a2753c28
MH
789 for (i = 0; debug_strings[i]; i++)
790 if (os_strcmp(debug_strings[i], str) == 0) {
791 val = i;
792 break;
793 }
794
795 if (val < 0 ||
796 wpa_supplicant_set_debug_params(global, val, wpa_debug_timestamp,
db9133ac 797 wpa_debug_show_keys)) {
38279bdb
JM
798 dbus_set_error_const(error, DBUS_ERROR_FAILED,
799 "wrong debug level value");
6aeeb6fa 800 return FALSE;
8fc2fb56
WS
801 }
802
6aeeb6fa 803 return TRUE;
8fc2fb56
WS
804}
805
806
807/**
db9133ac 808 * wpas_dbus_setter_debug_timestamp - Set debug timestamp
6aeeb6fa
DW
809 * @iter: Pointer to incoming dbus message iter
810 * @error: Location to store error on failure
811 * @user_data: Function specific data
812 * Returns: TRUE on success, FALSE on failure
8fc2fb56 813 *
db9133ac 814 * Setter for "DebugTimestamp" property.
8fc2fb56 815 */
1aa0fb77
DW
816dbus_bool_t wpas_dbus_setter_debug_timestamp(
817 const struct wpa_dbus_property_desc *property_desc,
818 DBusMessageIter *iter, DBusError *error, void *user_data)
8fc2fb56 819{
6aeeb6fa 820 struct wpa_global *global = user_data;
db9133ac 821 dbus_bool_t val;
8fc2fb56 822
6aeeb6fa
DW
823 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
824 &val))
825 return FALSE;
8fc2fb56 826
db9133ac
WS
827 wpa_supplicant_set_debug_params(global, wpa_debug_level, val ? 1 : 0,
828 wpa_debug_show_keys);
6aeeb6fa 829 return TRUE;
db9133ac 830}
8fc2fb56 831
8fc2fb56 832
db9133ac
WS
833/**
834 * wpas_dbus_setter_debug_show_keys - Set debug show keys
6aeeb6fa
DW
835 * @iter: Pointer to incoming dbus message iter
836 * @error: Location to store error on failure
837 * @user_data: Function specific data
838 * Returns: TRUE on success, FALSE on failure
db9133ac
WS
839 *
840 * Setter for "DebugShowKeys" property.
841 */
1aa0fb77
DW
842dbus_bool_t wpas_dbus_setter_debug_show_keys(
843 const struct wpa_dbus_property_desc *property_desc,
844 DBusMessageIter *iter, DBusError *error, void *user_data)
db9133ac 845{
6aeeb6fa 846 struct wpa_global *global = user_data;
db9133ac 847 dbus_bool_t val;
8fc2fb56 848
6aeeb6fa
DW
849 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
850 &val))
851 return FALSE;
8fc2fb56 852
db9133ac
WS
853 wpa_supplicant_set_debug_params(global, wpa_debug_level,
854 wpa_debug_timestamp,
855 val ? 1 : 0);
6aeeb6fa 856 return TRUE;
8fc2fb56
WS
857}
858
859
860/**
861 * wpas_dbus_getter_interfaces - Request registered interfaces list
6aeeb6fa
DW
862 * @iter: Pointer to incoming dbus message iter
863 * @error: Location to store error on failure
864 * @user_data: Function specific data
865 * Returns: TRUE on success, FALSE on failure
8fc2fb56
WS
866 *
867 * Getter for "Interfaces" property. Handles requests
868 * by dbus clients to return list of registered interfaces objects
869 * paths
870 */
1aa0fb77
DW
871dbus_bool_t wpas_dbus_getter_interfaces(
872 const struct wpa_dbus_property_desc *property_desc,
873 DBusMessageIter *iter, DBusError *error, void *user_data)
8fc2fb56 874{
6aeeb6fa 875 struct wpa_global *global = user_data;
8fc2fb56 876 struct wpa_supplicant *wpa_s;
fcea0b7d
WS
877 const char **paths;
878 unsigned int i = 0, num = 0;
6aeeb6fa 879 dbus_bool_t success;
8fc2fb56 880
8a78e227
JM
881 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
882 if (wpa_s->dbus_new_path)
883 num++;
884 }
8fc2fb56 885
f9884c09 886 paths = os_calloc(num, sizeof(char *));
fcea0b7d 887 if (!paths) {
6aeeb6fa
DW
888 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
889 return FALSE;
8fc2fb56
WS
890 }
891
8a78e227
JM
892 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
893 if (wpa_s->dbus_new_path)
894 paths[i++] = wpa_s->dbus_new_path;
895 }
8fc2fb56 896
6aeeb6fa
DW
897 success = wpas_dbus_simple_array_property_getter(iter,
898 DBUS_TYPE_OBJECT_PATH,
899 paths, num, error);
8fc2fb56 900
fcea0b7d 901 os_free(paths);
6aeeb6fa 902 return success;
8fc2fb56
WS
903}
904
905
906/**
907 * wpas_dbus_getter_eap_methods - Request supported EAP methods list
6aeeb6fa
DW
908 * @iter: Pointer to incoming dbus message iter
909 * @error: Location to store error on failure
910 * @user_data: Function specific data
911 * Returns: TRUE on success, FALSE on failure
8fc2fb56
WS
912 *
913 * Getter for "EapMethods" property. Handles requests
914 * by dbus clients to return list of strings with supported EAP methods
915 */
1aa0fb77
DW
916dbus_bool_t wpas_dbus_getter_eap_methods(
917 const struct wpa_dbus_property_desc *property_desc,
918 DBusMessageIter *iter, DBusError *error, void *user_data)
8fc2fb56 919{
8fc2fb56 920 char **eap_methods;
fcea0b7d 921 size_t num_items = 0;
6aeeb6fa 922 dbus_bool_t success;
8fc2fb56
WS
923
924 eap_methods = eap_get_names_as_string_array(&num_items);
fcea0b7d 925 if (!eap_methods) {
6aeeb6fa
DW
926 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
927 return FALSE;
8fc2fb56
WS
928 }
929
6aeeb6fa
DW
930 success = wpas_dbus_simple_array_property_getter(iter,
931 DBUS_TYPE_STRING,
932 eap_methods,
933 num_items, error);
8fc2fb56 934
fcea0b7d
WS
935 while (num_items)
936 os_free(eap_methods[--num_items]);
937 os_free(eap_methods);
6aeeb6fa 938 return success;
8fc2fb56
WS
939}
940
941
1634ac06
DW
942/**
943 * wpas_dbus_getter_global_capabilities - Request supported global capabilities
944 * @iter: Pointer to incoming dbus message iter
945 * @error: Location to store error on failure
946 * @user_data: Function specific data
947 * Returns: TRUE on success, FALSE on failure
948 *
949 * Getter for "Capabilities" property. Handles requests by dbus clients to
950 * return a list of strings with supported capabilities like AP, RSN IBSS,
951 * and P2P that are determined at compile time.
952 */
1aa0fb77
DW
953dbus_bool_t wpas_dbus_getter_global_capabilities(
954 const struct wpa_dbus_property_desc *property_desc,
955 DBusMessageIter *iter, DBusError *error, void *user_data)
1634ac06
DW
956{
957 const char *capabilities[5] = { NULL, NULL, NULL, NULL, NULL };
958 size_t num_items = 0;
959
960#ifdef CONFIG_AP
961 capabilities[num_items++] = "ap";
962#endif /* CONFIG_AP */
963#ifdef CONFIG_IBSS_RSN
964 capabilities[num_items++] = "ibss-rsn";
965#endif /* CONFIG_IBSS_RSN */
966#ifdef CONFIG_P2P
967 capabilities[num_items++] = "p2p";
968#endif /* CONFIG_P2P */
969#ifdef CONFIG_INTERWORKING
970 capabilities[num_items++] = "interworking";
971#endif /* CONFIG_INTERWORKING */
972
973 return wpas_dbus_simple_array_property_getter(iter,
974 DBUS_TYPE_STRING,
975 capabilities,
976 num_items, error);
977}
978
979
d401b48f
JM
980static int wpas_dbus_get_scan_type(DBusMessage *message, DBusMessageIter *var,
981 char **type, DBusMessage **reply)
8fc2fb56 982{
d401b48f 983 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_STRING) {
38279bdb
JM
984 wpa_printf(MSG_DEBUG, "%s[dbus]: Type must be a string",
985 __func__);
db9a76c0 986 *reply = wpas_dbus_error_invalid_args(
d401b48f
JM
987 message, "Wrong Type value type. String required");
988 return -1;
989 }
990 dbus_message_iter_get_basic(var, type);
991 return 0;
992}
8fc2fb56 993
8fc2fb56 994
d401b48f
JM
995static int wpas_dbus_get_scan_ssids(DBusMessage *message, DBusMessageIter *var,
996 struct wpa_driver_scan_params *params,
997 DBusMessage **reply)
998{
999 struct wpa_driver_scan_ssid *ssids = params->ssids;
1000 size_t ssids_num = 0;
1001 u8 *ssid;
1002 DBusMessageIter array_iter, sub_array_iter;
1003 char *val;
1004 int len;
8fc2fb56 1005
d401b48f 1006 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
38279bdb
JM
1007 wpa_printf(MSG_DEBUG,
1008 "%s[dbus]: ssids must be an array of arrays of bytes",
1009 __func__);
db9a76c0 1010 *reply = wpas_dbus_error_invalid_args(
38279bdb
JM
1011 message,
1012 "Wrong SSIDs value type. Array of arrays of bytes required");
d401b48f
JM
1013 return -1;
1014 }
8fc2fb56 1015
d401b48f 1016 dbus_message_iter_recurse(var, &array_iter);
8fc2fb56 1017
d401b48f 1018 if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY ||
38279bdb
JM
1019 dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_BYTE) {
1020 wpa_printf(MSG_DEBUG,
1021 "%s[dbus]: ssids must be an array of arrays of bytes",
1022 __func__);
db9a76c0 1023 *reply = wpas_dbus_error_invalid_args(
38279bdb
JM
1024 message,
1025 "Wrong SSIDs value type. Array of arrays of bytes required");
d401b48f
JM
1026 return -1;
1027 }
8fc2fb56 1028
38279bdb 1029 while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_ARRAY) {
d401b48f 1030 if (ssids_num >= WPAS_MAX_SCAN_SSIDS) {
38279bdb
JM
1031 wpa_printf(MSG_DEBUG,
1032 "%s[dbus]: Too many ssids specified on scan dbus call",
1033 __func__);
db9a76c0 1034 *reply = wpas_dbus_error_invalid_args(
38279bdb
JM
1035 message,
1036 "Too many ssids specified. Specify at most four");
d401b48f
JM
1037 return -1;
1038 }
8fc2fb56 1039
d401b48f 1040 dbus_message_iter_recurse(&array_iter, &sub_array_iter);
8fc2fb56 1041
d401b48f 1042 dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len);
8fc2fb56 1043
eaa8eefe 1044 if (len > SSID_MAX_LEN) {
f9121813 1045 wpa_printf(MSG_DEBUG,
38279bdb 1046 "%s[dbus]: SSID too long (len=%d max_len=%d)",
eaa8eefe 1047 __func__, len, SSID_MAX_LEN);
f9121813
SL
1048 *reply = wpas_dbus_error_invalid_args(
1049 message, "Invalid SSID: too long");
1050 return -1;
1051 }
1052
556522ee
DK
1053 if (len != 0) {
1054 ssid = os_malloc(len);
1055 if (ssid == NULL) {
a0caebf3 1056 *reply = wpas_dbus_error_no_memory(message);
556522ee
DK
1057 return -1;
1058 }
1059 os_memcpy(ssid, val, len);
1060 } else {
1061 /* Allow zero-length SSIDs */
1062 ssid = NULL;
d401b48f 1063 }
556522ee 1064
d401b48f
JM
1065 ssids[ssids_num].ssid = ssid;
1066 ssids[ssids_num].ssid_len = len;
5228401c 1067
d401b48f
JM
1068 dbus_message_iter_next(&array_iter);
1069 ssids_num++;
1070 }
8fc2fb56 1071
d401b48f
JM
1072 params->num_ssids = ssids_num;
1073 return 0;
1074}
8fc2fb56 1075
8fc2fb56 1076
d401b48f
JM
1077static int wpas_dbus_get_scan_ies(DBusMessage *message, DBusMessageIter *var,
1078 struct wpa_driver_scan_params *params,
1079 DBusMessage **reply)
1080{
1081 u8 *ies = NULL, *nies;
1082 int ies_len = 0;
1083 DBusMessageIter array_iter, sub_array_iter;
1084 char *val;
1085 int len;
8fc2fb56 1086
d401b48f 1087 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
38279bdb
JM
1088 wpa_printf(MSG_DEBUG,
1089 "%s[dbus]: ies must be an array of arrays of bytes",
1090 __func__);
db9a76c0 1091 *reply = wpas_dbus_error_invalid_args(
38279bdb
JM
1092 message,
1093 "Wrong IEs value type. Array of arrays of bytes required");
d401b48f
JM
1094 return -1;
1095 }
8fc2fb56 1096
d401b48f 1097 dbus_message_iter_recurse(var, &array_iter);
8fc2fb56 1098
d401b48f 1099 if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY ||
38279bdb
JM
1100 dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_BYTE) {
1101 wpa_printf(MSG_DEBUG,
1102 "%s[dbus]: ies must be an array of arrays of bytes",
1103 __func__);
db9a76c0 1104 *reply = wpas_dbus_error_invalid_args(
d401b48f
JM
1105 message, "Wrong IEs value type. Array required");
1106 return -1;
1107 }
8fc2fb56 1108
38279bdb 1109 while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_ARRAY) {
d401b48f 1110 dbus_message_iter_recurse(&array_iter, &sub_array_iter);
8fc2fb56 1111
d401b48f
JM
1112 dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len);
1113 if (len == 0) {
1114 dbus_message_iter_next(&array_iter);
1115 continue;
1116 }
8fc2fb56 1117
d401b48f
JM
1118 nies = os_realloc(ies, ies_len + len);
1119 if (nies == NULL) {
d401b48f 1120 os_free(ies);
a0caebf3 1121 *reply = wpas_dbus_error_no_memory(message);
d401b48f
JM
1122 return -1;
1123 }
1124 ies = nies;
1125 os_memcpy(ies + ies_len, val, len);
1126 ies_len += len;
8fc2fb56 1127
d401b48f
JM
1128 dbus_message_iter_next(&array_iter);
1129 }
5228401c 1130
d401b48f
JM
1131 params->extra_ies = ies;
1132 params->extra_ies_len = ies_len;
1133 return 0;
1134}
8fc2fb56 1135
8fc2fb56 1136
d401b48f
JM
1137static int wpas_dbus_get_scan_channels(DBusMessage *message,
1138 DBusMessageIter *var,
1139 struct wpa_driver_scan_params *params,
1140 DBusMessage **reply)
1141{
1142 DBusMessageIter array_iter, sub_array_iter;
1143 int *freqs = NULL, *nfreqs;
1144 int freqs_num = 0;
8fc2fb56 1145
d401b48f 1146 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
38279bdb
JM
1147 wpa_printf(MSG_DEBUG,
1148 "%s[dbus]: Channels must be an array of structs",
1149 __func__);
db9a76c0 1150 *reply = wpas_dbus_error_invalid_args(
38279bdb
JM
1151 message,
1152 "Wrong Channels value type. Array of structs required");
d401b48f
JM
1153 return -1;
1154 }
8fc2fb56 1155
d401b48f 1156 dbus_message_iter_recurse(var, &array_iter);
8fc2fb56 1157
d401b48f
JM
1158 if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_STRUCT) {
1159 wpa_printf(MSG_DEBUG,
38279bdb
JM
1160 "%s[dbus]: Channels must be an array of structs",
1161 __func__);
db9a76c0 1162 *reply = wpas_dbus_error_invalid_args(
38279bdb
JM
1163 message,
1164 "Wrong Channels value type. Array of structs required");
d401b48f
JM
1165 return -1;
1166 }
8fc2fb56 1167
d401b48f
JM
1168 while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_STRUCT)
1169 {
1170 int freq, width;
8fc2fb56 1171
d401b48f 1172 dbus_message_iter_recurse(&array_iter, &sub_array_iter);
8fc2fb56 1173
d401b48f
JM
1174 if (dbus_message_iter_get_arg_type(&sub_array_iter) !=
1175 DBUS_TYPE_UINT32) {
38279bdb
JM
1176 wpa_printf(MSG_DEBUG,
1177 "%s[dbus]: Channel must by specified by struct of two UINT32s %c",
1178 __func__,
d401b48f
JM
1179 dbus_message_iter_get_arg_type(
1180 &sub_array_iter));
db9a76c0 1181 *reply = wpas_dbus_error_invalid_args(
38279bdb
JM
1182 message,
1183 "Wrong Channel struct. Two UINT32s required");
d401b48f
JM
1184 os_free(freqs);
1185 return -1;
1186 }
1187 dbus_message_iter_get_basic(&sub_array_iter, &freq);
8fc2fb56 1188
d401b48f
JM
1189 if (!dbus_message_iter_next(&sub_array_iter) ||
1190 dbus_message_iter_get_arg_type(&sub_array_iter) !=
1191 DBUS_TYPE_UINT32) {
38279bdb
JM
1192 wpa_printf(MSG_DEBUG,
1193 "%s[dbus]: Channel must by specified by struct of two UINT32s",
1194 __func__);
db9a76c0 1195 *reply = wpas_dbus_error_invalid_args(
d401b48f
JM
1196 message,
1197 "Wrong Channel struct. Two UINT32s required");
1198 os_free(freqs);
1199 return -1;
1200 }
8fc2fb56 1201
d401b48f 1202 dbus_message_iter_get_basic(&sub_array_iter, &width);
8fc2fb56 1203
5228401c 1204#define FREQS_ALLOC_CHUNK 32
d401b48f 1205 if (freqs_num % FREQS_ALLOC_CHUNK == 0) {
067ffa26
JM
1206 nfreqs = os_realloc_array(
1207 freqs, freqs_num + FREQS_ALLOC_CHUNK,
1208 sizeof(int));
d401b48f
JM
1209 if (nfreqs == NULL)
1210 os_free(freqs);
1211 freqs = nfreqs;
1212 }
1213 if (freqs == NULL) {
a0caebf3 1214 *reply = wpas_dbus_error_no_memory(message);
d401b48f
JM
1215 return -1;
1216 }
8fc2fb56 1217
d401b48f 1218 freqs[freqs_num] = freq;
8fc2fb56 1219
d401b48f
JM
1220 freqs_num++;
1221 dbus_message_iter_next(&array_iter);
1222 }
8fc2fb56 1223
067ffa26 1224 nfreqs = os_realloc_array(freqs, freqs_num + 1, sizeof(int));
d401b48f
JM
1225 if (nfreqs == NULL)
1226 os_free(freqs);
1227 freqs = nfreqs;
1228 if (freqs == NULL) {
a0caebf3 1229 *reply = wpas_dbus_error_no_memory(message);
d401b48f
JM
1230 return -1;
1231 }
1232 freqs[freqs_num] = 0;
1233
1234 params->freqs = freqs;
1235 return 0;
1236}
8fc2fb56 1237
d401b48f 1238
538922a6
DW
1239static int wpas_dbus_get_scan_allow_roam(DBusMessage *message,
1240 DBusMessageIter *var,
1241 dbus_bool_t *allow,
1242 DBusMessage **reply)
1243{
1244 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_BOOLEAN) {
38279bdb
JM
1245 wpa_printf(MSG_DEBUG, "%s[dbus]: Type must be a boolean",
1246 __func__);
538922a6
DW
1247 *reply = wpas_dbus_error_invalid_args(
1248 message, "Wrong Type value type. Boolean required");
1249 return -1;
1250 }
1251 dbus_message_iter_get_basic(var, allow);
1252 return 0;
1253}
1254
1255
d401b48f
JM
1256/**
1257 * wpas_dbus_handler_scan - Request a wireless scan on an interface
1258 * @message: Pointer to incoming dbus message
1259 * @wpa_s: wpa_supplicant structure for a network interface
1260 * Returns: NULL indicating success or DBus error message on failure
1261 *
1262 * Handler function for "Scan" method call of a network device. Requests
1263 * that wpa_supplicant perform a wireless scan as soon as possible
1264 * on a particular wireless interface.
1265 */
1266DBusMessage * wpas_dbus_handler_scan(DBusMessage *message,
1267 struct wpa_supplicant *wpa_s)
1268{
1269 DBusMessage *reply = NULL;
1270 DBusMessageIter iter, dict_iter, entry_iter, variant_iter;
1271 char *key = NULL, *type = NULL;
1272 struct wpa_driver_scan_params params;
1273 size_t i;
538922a6 1274 dbus_bool_t allow_roam = 1;
d401b48f
JM
1275
1276 os_memset(&params, 0, sizeof(params));
1277
1278 dbus_message_iter_init(message, &iter);
1279
1280 dbus_message_iter_recurse(&iter, &dict_iter);
1281
1282 while (dbus_message_iter_get_arg_type(&dict_iter) ==
38279bdb 1283 DBUS_TYPE_DICT_ENTRY) {
d401b48f
JM
1284 dbus_message_iter_recurse(&dict_iter, &entry_iter);
1285 dbus_message_iter_get_basic(&entry_iter, &key);
1286 dbus_message_iter_next(&entry_iter);
1287 dbus_message_iter_recurse(&entry_iter, &variant_iter);
1288
1289 if (os_strcmp(key, "Type") == 0) {
1290 if (wpas_dbus_get_scan_type(message, &variant_iter,
1291 &type, &reply) < 0)
1292 goto out;
1293 } else if (os_strcmp(key, "SSIDs") == 0) {
1294 if (wpas_dbus_get_scan_ssids(message, &variant_iter,
1295 &params, &reply) < 0)
1296 goto out;
1297 } else if (os_strcmp(key, "IEs") == 0) {
1298 if (wpas_dbus_get_scan_ies(message, &variant_iter,
1299 &params, &reply) < 0)
1300 goto out;
1301 } else if (os_strcmp(key, "Channels") == 0) {
1302 if (wpas_dbus_get_scan_channels(message, &variant_iter,
1303 &params, &reply) < 0)
1304 goto out;
538922a6
DW
1305 } else if (os_strcmp(key, "AllowRoam") == 0) {
1306 if (wpas_dbus_get_scan_allow_roam(message,
1307 &variant_iter,
1308 &allow_roam,
1309 &reply) < 0)
1310 goto out;
5228401c 1311 } else {
38279bdb
JM
1312 wpa_printf(MSG_DEBUG, "%s[dbus]: Unknown argument %s",
1313 __func__, key);
db9a76c0 1314 reply = wpas_dbus_error_invalid_args(message, key);
8fc2fb56
WS
1315 goto out;
1316 }
1317
1318 dbus_message_iter_next(&dict_iter);
1319 }
1320
1321 if (!type) {
38279bdb
JM
1322 wpa_printf(MSG_DEBUG, "%s[dbus]: Scan type not specified",
1323 __func__);
db9a76c0 1324 reply = wpas_dbus_error_invalid_args(message, key);
8fc2fb56
WS
1325 goto out;
1326 }
1327
38279bdb 1328 if (os_strcmp(type, "passive") == 0) {
d401b48f 1329 if (params.num_ssids || params.extra_ies_len) {
38279bdb
JM
1330 wpa_printf(MSG_DEBUG,
1331 "%s[dbus]: SSIDs or IEs specified for passive scan.",
1332 __func__);
db9a76c0 1333 reply = wpas_dbus_error_invalid_args(
38279bdb
JM
1334 message,
1335 "You can specify only Channels in passive scan");
8fc2fb56 1336 goto out;
5228401c 1337 } else {
a5da6574
AS
1338 if (wpa_s->sched_scanning) {
1339 wpa_printf(MSG_DEBUG,
1340 "%s[dbus]: Stop ongoing sched_scan to allow requested scan to proceed",
1341 __func__);
1342 wpa_supplicant_cancel_sched_scan(wpa_s);
1343 }
1344
1345 if (params.freqs && params.freqs[0]) {
1fbff0b5 1346 wpa_s->last_scan_req = MANUAL_SCAN_REQ;
a5da6574
AS
1347 if (wpa_supplicant_trigger_scan(wpa_s,
1348 &params)) {
1349 reply = wpas_dbus_error_scan_error(
1350 message,
1351 "Scan request rejected");
1352 }
1353 } else {
1354 wpa_s->scan_req = MANUAL_SCAN_REQ;
1355 wpa_supplicant_req_scan(wpa_s, 0, 0);
1356 }
8fc2fb56 1357 }
38279bdb 1358 } else if (os_strcmp(type, "active") == 0) {
a7af023b
DK
1359 if (!params.num_ssids) {
1360 /* Add wildcard ssid */
1361 params.num_ssids++;
1362 }
7c865c68
TB
1363#ifdef CONFIG_AUTOSCAN
1364 autoscan_deinit(wpa_s);
1365#endif /* CONFIG_AUTOSCAN */
a5da6574
AS
1366 if (wpa_s->sched_scanning) {
1367 wpa_printf(MSG_DEBUG,
1368 "%s[dbus]: Stop ongoing sched_scan to allow requested scan to proceed",
1369 __func__);
1370 wpa_supplicant_cancel_sched_scan(wpa_s);
1371 }
1372
1fbff0b5 1373 wpa_s->last_scan_req = MANUAL_SCAN_REQ;
e9b32dae 1374 if (wpa_supplicant_trigger_scan(wpa_s, &params)) {
1375 reply = wpas_dbus_error_scan_error(
1376 message, "Scan request rejected");
1377 }
5228401c 1378 } else {
38279bdb
JM
1379 wpa_printf(MSG_DEBUG, "%s[dbus]: Unknown scan type: %s",
1380 __func__, type);
db9a76c0
JM
1381 reply = wpas_dbus_error_invalid_args(message,
1382 "Wrong scan type");
8fc2fb56
WS
1383 goto out;
1384 }
1385
538922a6
DW
1386 if (!allow_roam)
1387 wpa_s->scan_res_handler = scan_only_handler;
1388
8fc2fb56 1389out:
d401b48f
JM
1390 for (i = 0; i < WPAS_MAX_SCAN_SSIDS; i++)
1391 os_free((u8 *) params.ssids[i].ssid);
5228401c 1392 os_free((u8 *) params.extra_ies);
8fc2fb56
WS
1393 os_free(params.freqs);
1394 return reply;
1395}
1396
1397
7a4a93b9
DW
1398/**
1399 * wpas_dbus_handler_signal_poll - Request immediate signal properties
1400 * @message: Pointer to incoming dbus message
1401 * @wpa_s: wpa_supplicant structure for a network interface
1402 * Returns: NULL indicating success or DBus error message on failure
1403 *
1404 * Handler function for "SignalPoll" method call of a network device. Requests
1405 * that wpa_supplicant read signal properties like RSSI, noise, and link
1406 * speed and return them.
1407 */
1408DBusMessage * wpas_dbus_handler_signal_poll(DBusMessage *message,
1409 struct wpa_supplicant *wpa_s)
1410{
1411 struct wpa_signal_info si;
1412 DBusMessage *reply = NULL;
1413 DBusMessageIter iter, iter_dict, variant_iter;
1414 int ret;
1415
1416 ret = wpa_drv_signal_poll(wpa_s, &si);
1417 if (ret) {
1418 return dbus_message_new_error(message, DBUS_ERROR_FAILED,
1419 "Failed to read signal");
1420 }
1421
1422 reply = dbus_message_new_method_return(message);
1423 if (reply == NULL)
1424 goto nomem;
1425
1426 dbus_message_iter_init_append(reply, &iter);
1427
1428 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
e3c4f0b5
JM
1429 "a{sv}", &variant_iter) ||
1430 !wpa_dbus_dict_open_write(&variant_iter, &iter_dict) ||
1431 !wpa_dbus_dict_append_int32(&iter_dict, "rssi",
1432 si.current_signal) ||
1433 !wpa_dbus_dict_append_int32(&iter_dict, "linkspeed",
1434 si.current_txrate / 1000) ||
1435 !wpa_dbus_dict_append_int32(&iter_dict, "noise",
1436 si.current_noise) ||
1437 !wpa_dbus_dict_append_uint32(&iter_dict, "frequency",
1438 si.frequency) ||
1439 (si.chanwidth != CHAN_WIDTH_UNKNOWN &&
1440 !wpa_dbus_dict_append_string(
1441 &iter_dict, "width",
1442 channel_width_to_string(si.chanwidth))) ||
1443 (si.center_frq1 > 0 && si.center_frq2 > 0 &&
1444 (!wpa_dbus_dict_append_int32(&iter_dict, "center-frq1",
1445 si.center_frq1) ||
1446 !wpa_dbus_dict_append_int32(&iter_dict, "center-frq2",
1447 si.center_frq2))) ||
1448 (si.avg_signal &&
1449 !wpa_dbus_dict_append_int32(&iter_dict, "avg-rssi",
1450 si.avg_signal)) ||
1451 !wpa_dbus_dict_close_write(&variant_iter, &iter_dict) ||
1452 !dbus_message_iter_close_container(&iter, &variant_iter))
7a4a93b9
DW
1453 goto nomem;
1454
1455 return reply;
1456
1457nomem:
1458 if (reply)
1459 dbus_message_unref(reply);
a0caebf3 1460 return wpas_dbus_error_no_memory(message);
7a4a93b9
DW
1461}
1462
1463
8fc2fb56
WS
1464/*
1465 * wpas_dbus_handler_disconnect - Terminate the current connection
1466 * @message: Pointer to incoming dbus message
1467 * @wpa_s: wpa_supplicant structure for a network interface
1468 * Returns: NotConnected DBus error message if already not connected
1469 * or NULL otherwise.
1470 *
1471 * Handler function for "Disconnect" method call of network interface.
1472 */
1473DBusMessage * wpas_dbus_handler_disconnect(DBusMessage *message,
5228401c 1474 struct wpa_supplicant *wpa_s)
8fc2fb56
WS
1475{
1476 if (wpa_s->current_ssid != NULL) {
1477 wpa_s->disconnected = 1;
f9cd8587
JM
1478 wpa_supplicant_deauthenticate(wpa_s,
1479 WLAN_REASON_DEAUTH_LEAVING);
8fc2fb56
WS
1480
1481 return NULL;
1482 }
5228401c
JM
1483
1484 return dbus_message_new_error(message, WPAS_DBUS_ERROR_NOT_CONNECTED,
1485 "This interface is not connected");
8fc2fb56
WS
1486}
1487
1488
1489/**
1490 * wpas_dbus_new_iface_add_network - Add a new configured network
1491 * @message: Pointer to incoming dbus message
1492 * @wpa_s: wpa_supplicant structure for a network interface
1493 * Returns: A dbus message containing the object path of the new network
1494 *
1495 * Handler function for "AddNetwork" method call of a network interface.
1496 */
1497DBusMessage * wpas_dbus_handler_add_network(DBusMessage *message,
5228401c 1498 struct wpa_supplicant *wpa_s)
8fc2fb56
WS
1499{
1500 DBusMessage *reply = NULL;
1501 DBusMessageIter iter;
1502 struct wpa_ssid *ssid = NULL;
3e87bd54 1503 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf;
6aeeb6fa 1504 DBusError error;
8fc2fb56
WS
1505
1506 dbus_message_iter_init(message, &iter);
1507
8a78e227
JM
1508 if (wpa_s->dbus_new_path)
1509 ssid = wpa_config_add_network(wpa_s->conf);
8fc2fb56 1510 if (ssid == NULL) {
38279bdb
JM
1511 wpa_printf(MSG_ERROR, "%s[dbus]: can't add new interface.",
1512 __func__);
5228401c
JM
1513 reply = wpas_dbus_error_unknown_error(
1514 message,
38279bdb 1515 "wpa_supplicant could not add a network on this interface.");
8fc2fb56
WS
1516 goto err;
1517 }
1518 wpas_notify_network_added(wpa_s, ssid);
1519 ssid->disabled = 1;
1520 wpa_config_set_network_defaults(ssid);
1521
6aeeb6fa
DW
1522 dbus_error_init(&error);
1523 if (!set_network_properties(wpa_s, ssid, &iter, &error)) {
38279bdb
JM
1524 wpa_printf(MSG_DEBUG,
1525 "%s[dbus]: control interface couldn't set network properties",
1526 __func__);
6aeeb6fa
DW
1527 reply = wpas_dbus_reply_new_from_error(message, &error,
1528 DBUS_ERROR_INVALID_ARGS,
1529 "Failed to add network");
1530 dbus_error_free(&error);
8fc2fb56
WS
1531 goto err;
1532 }
1533
1534 /* Construct the object path for this network. */
5228401c
JM
1535 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
1536 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
c49cf2d6 1537 wpa_s->dbus_new_path, ssid->id);
8fc2fb56
WS
1538
1539 reply = dbus_message_new_method_return(message);
1540 if (reply == NULL) {
a0caebf3 1541 reply = wpas_dbus_error_no_memory(message);
8fc2fb56
WS
1542 goto err;
1543 }
1544 if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
5228401c 1545 DBUS_TYPE_INVALID)) {
8fc2fb56 1546 dbus_message_unref(reply);
a0caebf3 1547 reply = wpas_dbus_error_no_memory(message);
8fc2fb56
WS
1548 goto err;
1549 }
1550
8fc2fb56
WS
1551 return reply;
1552
1553err:
1554 if (ssid) {
1555 wpas_notify_network_removed(wpa_s, ssid);
1556 wpa_config_remove_network(wpa_s->conf, ssid->id);
1557 }
8fc2fb56
WS
1558 return reply;
1559}
1560
1561
6ed31175 1562/**
481e66b1 1563 * wpas_dbus_handler_reassociate - Reassociate
6ed31175
PS
1564 * @message: Pointer to incoming dbus message
1565 * @wpa_s: wpa_supplicant structure for a network interface
481e66b1 1566 * Returns: InterfaceDisabled DBus error message if disabled
6ed31175
PS
1567 * or NULL otherwise.
1568 *
1569 * Handler function for "Reassociate" method call of network interface.
1570 */
1571DBusMessage * wpas_dbus_handler_reassociate(DBusMessage *message,
1572 struct wpa_supplicant *wpa_s)
1573{
481e66b1 1574 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED) {
9796a86c 1575 wpas_request_connection(wpa_s);
6ed31175
PS
1576 return NULL;
1577 }
1578
481e66b1
FC
1579 return dbus_message_new_error(message, WPAS_DBUS_ERROR_IFACE_DISABLED,
1580 "This interface is disabled");
6ed31175
PS
1581}
1582
1583
c143c3b7
NW
1584/**
1585 * wpas_dbus_handler_expect_disconnect - ExpectDisconnect
1586 * @message: Pointer to incoming dbus message
1587 * @global: %wpa_supplicant global data structure
1588 * Returns: NULL
1589 *
1590 * Handler function for notifying system there will be a expected disconnect.
1591 * This will prevent wpa_supplicant from adding blacklists upon next disconnect..
1592 */
1593DBusMessage * wpas_dbus_handler_expect_disconnect(DBusMessage *message,
1594 struct wpa_global *global)
1595{
1596 struct wpa_supplicant *wpa_s = global->ifaces;
1597
1598 for (; wpa_s; wpa_s = wpa_s->next)
1599 if (wpa_s->wpa_state >= WPA_ASSOCIATED)
1600 wpa_s->own_disconnect_req = 1;
1601 return NULL;
1602}
1603
1604
0f44ec8e
PQ
1605/**
1606 * wpas_dbus_handler_reattach - Reattach to current AP
1607 * @message: Pointer to incoming dbus message
1608 * @wpa_s: wpa_supplicant structure for a network interface
1609 * Returns: NotConnected DBus error message if not connected
1610 * or NULL otherwise.
1611 *
1612 * Handler function for "Reattach" method call of network interface.
1613 */
1614DBusMessage * wpas_dbus_handler_reattach(DBusMessage *message,
1615 struct wpa_supplicant *wpa_s)
1616{
1617 if (wpa_s->current_ssid != NULL) {
1618 wpa_s->reattach = 1;
1619 wpas_request_connection(wpa_s);
1620 return NULL;
1621 }
1622
1623 return dbus_message_new_error(message, WPAS_DBUS_ERROR_NOT_CONNECTED,
1624 "This interface is not connected");
1625}
1626
1627
b649c0af
MH
1628/**
1629 * wpas_dbus_handler_reconnect - Reconnect if disconnected
1630 * @message: Pointer to incoming dbus message
1631 * @wpa_s: wpa_supplicant structure for a network interface
1632 * Returns: InterfaceDisabled DBus error message if disabled
1633 * or NULL otherwise.
1634 *
1635 * Handler function for "Reconnect" method call of network interface.
1636 */
1637DBusMessage * wpas_dbus_handler_reconnect(DBusMessage *message,
1638 struct wpa_supplicant *wpa_s)
1639{
1640 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
1641 return dbus_message_new_error(message,
1642 WPAS_DBUS_ERROR_IFACE_DISABLED,
1643 "This interface is disabled");
1644 }
1645
1646 if (wpa_s->disconnected)
1647 wpas_request_connection(wpa_s);
1648 return NULL;
1649}
1650
1651
8fc2fb56
WS
1652/**
1653 * wpas_dbus_handler_remove_network - Remove a configured network
1654 * @message: Pointer to incoming dbus message
1655 * @wpa_s: wpa_supplicant structure for a network interface
1656 * Returns: NULL on success or dbus error on failure
1657 *
1658 * Handler function for "RemoveNetwork" method call of a network interface.
1659 */
1660DBusMessage * wpas_dbus_handler_remove_network(DBusMessage *message,
5228401c 1661 struct wpa_supplicant *wpa_s)
8fc2fb56
WS
1662{
1663 DBusMessage *reply = NULL;
1664 const char *op;
054dc313 1665 char *iface, *net_id;
8fc2fb56
WS
1666 int id;
1667 struct wpa_ssid *ssid;
725fc39e 1668 int was_disabled;
8fc2fb56
WS
1669
1670 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
5228401c 1671 DBUS_TYPE_INVALID);
8fc2fb56
WS
1672
1673 /* Extract the network ID and ensure the network */
1674 /* is actually a child of this interface */
054dc313
JM
1675 iface = wpas_dbus_new_decompose_object_path(op,
1676 WPAS_DBUS_NEW_NETWORKS_PART,
1677 &net_id);
8a78e227 1678 if (iface == NULL || net_id == NULL || !wpa_s->dbus_new_path ||
45ac5793 1679 os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
db9a76c0 1680 reply = wpas_dbus_error_invalid_args(message, op);
8fc2fb56
WS
1681 goto out;
1682 }
1683
45ac5793 1684 errno = 0;
8fc2fb56 1685 id = strtoul(net_id, NULL, 10);
45ac5793 1686 if (errno != 0) {
db9a76c0 1687 reply = wpas_dbus_error_invalid_args(message, op);
8fc2fb56
WS
1688 goto out;
1689 }
1690
1691 ssid = wpa_config_get_network(wpa_s->conf, id);
1692 if (ssid == NULL) {
1693 reply = wpas_dbus_error_network_unknown(message);
1694 goto out;
1695 }
1696
725fc39e
DS
1697 was_disabled = ssid->disabled;
1698
8fc2fb56
WS
1699 wpas_notify_network_removed(wpa_s, ssid);
1700
8fc2fb56 1701 if (ssid == wpa_s->current_ssid)
f9cd8587
JM
1702 wpa_supplicant_deauthenticate(wpa_s,
1703 WLAN_REASON_DEAUTH_LEAVING);
725fc39e 1704 else if (!was_disabled && wpa_s->sched_scanning) {
38279bdb
JM
1705 wpa_printf(MSG_DEBUG,
1706 "Stop ongoing sched_scan to remove network from filters");
725fc39e
DS
1707 wpa_supplicant_cancel_sched_scan(wpa_s);
1708 wpa_supplicant_req_scan(wpa_s, 0, 0);
1709 }
1710
316f92cd
HM
1711 if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
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
bdec7ee5
MS
2297/**
2298 * wpas_dbus_handler_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
2299 * @message: Pointer to incoming dbus message
2300 * @wpa_s: %wpa_supplicant data structure
2301 * Returns: A dbus message containing an error on failure or NULL on success
2302 *
2303 * Sets the PKCS #11 engine and module path.
2304 */
2305DBusMessage * wpas_dbus_handler_set_pkcs11_engine_and_module_path(
2306 DBusMessage *message, struct wpa_supplicant *wpa_s)
2307{
2308 DBusMessageIter iter;
2309 char *value = NULL;
2310 char *pkcs11_engine_path = NULL;
2311 char *pkcs11_module_path = NULL;
2312
2313 dbus_message_iter_init(message, &iter);
2314 dbus_message_iter_get_basic(&iter, &value);
2315 if (value == NULL) {
2316 return dbus_message_new_error(
2317 message, DBUS_ERROR_INVALID_ARGS,
2318 "Invalid pkcs11_engine_path argument");
2319 }
2320 /* Empty path defaults to NULL */
2321 if (os_strlen(value))
2322 pkcs11_engine_path = value;
2323
2324 dbus_message_iter_next(&iter);
2325 dbus_message_iter_get_basic(&iter, &value);
2326 if (value == NULL) {
2327 os_free(pkcs11_engine_path);
2328 return dbus_message_new_error(
2329 message, DBUS_ERROR_INVALID_ARGS,
2330 "Invalid pkcs11_module_path argument");
2331 }
2332 /* Empty path defaults to NULL */
2333 if (os_strlen(value))
2334 pkcs11_module_path = value;
2335
2336 if (wpas_set_pkcs11_engine_and_module_path(wpa_s, pkcs11_engine_path,
2337 pkcs11_module_path))
2338 return dbus_message_new_error(
2339 message, DBUS_ERROR_FAILED,
38279bdb 2340 "Reinit of the EAPOL state machine with the new PKCS #11 engine and module path failed.");
bdec7ee5 2341
8a78e227
JM
2342 if (wpa_s->dbus_new_path) {
2343 wpa_dbus_mark_property_changed(
2344 wpa_s->global->dbus, wpa_s->dbus_new_path,
2345 WPAS_DBUS_NEW_IFACE_INTERFACE, "PKCS11EnginePath");
2346 wpa_dbus_mark_property_changed(
2347 wpa_s->global->dbus, wpa_s->dbus_new_path,
2348 WPAS_DBUS_NEW_IFACE_INTERFACE, "PKCS11ModulePath");
2349 }
bdec7ee5
MS
2350
2351 return NULL;
2352}
2353
2354
8fc2fb56
WS
2355/**
2356 * wpas_dbus_getter_capabilities - Return interface capabilities
6aeeb6fa
DW
2357 * @iter: Pointer to incoming dbus message iter
2358 * @error: Location to store error on failure
2359 * @user_data: Function specific data
2360 * Returns: TRUE on success, FALSE on failure
8fc2fb56
WS
2361 *
2362 * Getter for "Capabilities" property of an interface.
2363 */
1aa0fb77
DW
2364dbus_bool_t wpas_dbus_getter_capabilities(
2365 const struct wpa_dbus_property_desc *property_desc,
2366 DBusMessageIter *iter, DBusError *error, void *user_data)
8fc2fb56 2367{
6aeeb6fa 2368 struct wpa_supplicant *wpa_s = user_data;
8fc2fb56
WS
2369 struct wpa_driver_capa capa;
2370 int res;
6aeeb6fa 2371 DBusMessageIter iter_dict, iter_dict_entry, iter_dict_val, iter_array,
5228401c
JM
2372 variant_iter;
2373 const char *scans[] = { "active", "passive", "ssid" };
8fc2fb56 2374
6aeeb6fa 2375 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
e3c4f0b5
JM
2376 "a{sv}", &variant_iter) ||
2377 !wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
8fc2fb56
WS
2378 goto nomem;
2379
2380 res = wpa_drv_get_capa(wpa_s, &capa);
2381
2382 /***** pairwise cipher */
2383 if (res < 0) {
2384 const char *args[] = {"ccmp", "tkip", "none"};
38279bdb 2385
8fc2fb56 2386 if (!wpa_dbus_dict_append_string_array(
5228401c 2387 &iter_dict, "Pairwise", args,
e7ecab4a 2388 ARRAY_SIZE(args)))
8fc2fb56
WS
2389 goto nomem;
2390 } else {
2391 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Pairwise",
2392 &iter_dict_entry,
2393 &iter_dict_val,
e3c4f0b5
JM
2394 &iter_array) ||
2395 ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP_256) &&
2396 !wpa_dbus_dict_string_array_add_element(
2397 &iter_array, "ccmp-256")) ||
2398 ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP_256) &&
2399 !wpa_dbus_dict_string_array_add_element(
2400 &iter_array, "gcmp-256")) ||
2401 ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) &&
2402 !wpa_dbus_dict_string_array_add_element(
2403 &iter_array, "ccmp")) ||
2404 ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP) &&
2405 !wpa_dbus_dict_string_array_add_element(
2406 &iter_array, "gcmp")) ||
2407 ((capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) &&
2408 !wpa_dbus_dict_string_array_add_element(
2409 &iter_array, "tkip")) ||
2410 ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) &&
2411 !wpa_dbus_dict_string_array_add_element(
2412 &iter_array, "none")) ||
2413 !wpa_dbus_dict_end_string_array(&iter_dict,
8fc2fb56
WS
2414 &iter_dict_entry,
2415 &iter_dict_val,
2416 &iter_array))
2417 goto nomem;
2418 }
2419
2420 /***** group cipher */
2421 if (res < 0) {
2422 const char *args[] = {
2423 "ccmp", "tkip", "wep104", "wep40"
2424 };
38279bdb 2425
8fc2fb56 2426 if (!wpa_dbus_dict_append_string_array(
5228401c 2427 &iter_dict, "Group", args,
e7ecab4a 2428 ARRAY_SIZE(args)))
8fc2fb56
WS
2429 goto nomem;
2430 } else {
2431 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Group",
2432 &iter_dict_entry,
2433 &iter_dict_val,
e3c4f0b5
JM
2434 &iter_array) ||
2435 ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP_256) &&
2436 !wpa_dbus_dict_string_array_add_element(
2437 &iter_array, "ccmp-256")) ||
2438 ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP_256) &&
2439 !wpa_dbus_dict_string_array_add_element(
2440 &iter_array, "gcmp-256")) ||
2441 ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) &&
2442 !wpa_dbus_dict_string_array_add_element(
2443 &iter_array, "ccmp")) ||
2444 ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP) &&
2445 !wpa_dbus_dict_string_array_add_element(
2446 &iter_array, "gcmp")) ||
2447 ((capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) &&
2448 !wpa_dbus_dict_string_array_add_element(
2449 &iter_array, "tkip")) ||
2450 ((capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) &&
2451 !wpa_dbus_dict_string_array_add_element(
2452 &iter_array, "wep104")) ||
2453 ((capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) &&
2454 !wpa_dbus_dict_string_array_add_element(
2455 &iter_array, "wep40")) ||
2456 !wpa_dbus_dict_end_string_array(&iter_dict,
8fc2fb56
WS
2457 &iter_dict_entry,
2458 &iter_dict_val,
2459 &iter_array))
2460 goto nomem;
2461 }
2462
2463 /***** key management */
2464 if (res < 0) {
2465 const char *args[] = {
2466 "wpa-psk", "wpa-eap", "ieee8021x", "wpa-none",
2467#ifdef CONFIG_WPS
2468 "wps",
2469#endif /* CONFIG_WPS */
2470 "none"
2471 };
2472 if (!wpa_dbus_dict_append_string_array(
5228401c 2473 &iter_dict, "KeyMgmt", args,
e7ecab4a 2474 ARRAY_SIZE(args)))
8fc2fb56
WS
2475 goto nomem;
2476 } else {
2477 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "KeyMgmt",
2478 &iter_dict_entry,
2479 &iter_dict_val,
e3c4f0b5
JM
2480 &iter_array) ||
2481 !wpa_dbus_dict_string_array_add_element(&iter_array,
2482 "none") ||
2483 !wpa_dbus_dict_string_array_add_element(&iter_array,
8fc2fb56
WS
2484 "ieee8021x"))
2485 goto nomem;
2486
2487 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
2488 WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
2489 if (!wpa_dbus_dict_string_array_add_element(
e3c4f0b5
JM
2490 &iter_array, "wpa-eap") ||
2491 ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT) &&
2492 !wpa_dbus_dict_string_array_add_element(
2493 &iter_array, "wpa-ft-eap")))
8fc2fb56 2494 goto nomem;
c56ce48a 2495
c56ce48a
WS
2496/* TODO: Ensure that driver actually supports sha256 encryption. */
2497#ifdef CONFIG_IEEE80211W
2498 if (!wpa_dbus_dict_string_array_add_element(
2499 &iter_array, "wpa-eap-sha256"))
2500 goto nomem;
2501#endif /* CONFIG_IEEE80211W */
8fc2fb56
WS
2502 }
2503
2504 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
2505 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
2506 if (!wpa_dbus_dict_string_array_add_element(
e3c4f0b5
JM
2507 &iter_array, "wpa-psk") ||
2508 ((capa.key_mgmt &
2509 WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK) &&
2510 !wpa_dbus_dict_string_array_add_element(
2511 &iter_array, "wpa-ft-psk")))
8fc2fb56 2512 goto nomem;
c56ce48a 2513
c56ce48a
WS
2514/* TODO: Ensure that driver actually supports sha256 encryption. */
2515#ifdef CONFIG_IEEE80211W
2516 if (!wpa_dbus_dict_string_array_add_element(
2517 &iter_array, "wpa-psk-sha256"))
2518 goto nomem;
2519#endif /* CONFIG_IEEE80211W */
8fc2fb56
WS
2520 }
2521
e3c4f0b5
JM
2522 if ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) &&
2523 !wpa_dbus_dict_string_array_add_element(&iter_array,
2524 "wpa-none"))
2525 goto nomem;
8fc2fb56
WS
2526
2527
2528#ifdef CONFIG_WPS
5228401c
JM
2529 if (!wpa_dbus_dict_string_array_add_element(&iter_array,
2530 "wps"))
8fc2fb56
WS
2531 goto nomem;
2532#endif /* CONFIG_WPS */
2533
2534 if (!wpa_dbus_dict_end_string_array(&iter_dict,
2535 &iter_dict_entry,
2536 &iter_dict_val,
2537 &iter_array))
2538 goto nomem;
8fc2fb56
WS
2539 }
2540
2541 /***** WPA protocol */
2542 if (res < 0) {
2543 const char *args[] = { "rsn", "wpa" };
38279bdb 2544
8fc2fb56 2545 if (!wpa_dbus_dict_append_string_array(
5228401c 2546 &iter_dict, "Protocol", args,
e7ecab4a 2547 ARRAY_SIZE(args)))
8fc2fb56
WS
2548 goto nomem;
2549 } else {
2550 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Protocol",
2551 &iter_dict_entry,
2552 &iter_dict_val,
e3c4f0b5
JM
2553 &iter_array) ||
2554 ((capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
2555 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) &&
2556 !wpa_dbus_dict_string_array_add_element(
2557 &iter_array, "rsn")) ||
2558 ((capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
2559 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) &&
2560 !wpa_dbus_dict_string_array_add_element(
2561 &iter_array, "wpa")) ||
2562 !wpa_dbus_dict_end_string_array(&iter_dict,
8fc2fb56
WS
2563 &iter_dict_entry,
2564 &iter_dict_val,
2565 &iter_array))
2566 goto nomem;
2567 }
2568
2569 /***** auth alg */
2570 if (res < 0) {
2571 const char *args[] = { "open", "shared", "leap" };
38279bdb 2572
8fc2fb56 2573 if (!wpa_dbus_dict_append_string_array(
5228401c 2574 &iter_dict, "AuthAlg", args,
e7ecab4a 2575 ARRAY_SIZE(args)))
8fc2fb56
WS
2576 goto nomem;
2577 } else {
2578 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "AuthAlg",
2579 &iter_dict_entry,
2580 &iter_dict_val,
2581 &iter_array))
2582 goto nomem;
2583
e3c4f0b5
JM
2584 if (((capa.auth & WPA_DRIVER_AUTH_OPEN) &&
2585 !wpa_dbus_dict_string_array_add_element(
2586 &iter_array, "open")) ||
2587 ((capa.auth & WPA_DRIVER_AUTH_SHARED) &&
2588 !wpa_dbus_dict_string_array_add_element(
2589 &iter_array, "shared")) ||
2590 ((capa.auth & WPA_DRIVER_AUTH_LEAP) &&
2591 !wpa_dbus_dict_string_array_add_element(
2592 &iter_array, "leap")) ||
2593 !wpa_dbus_dict_end_string_array(&iter_dict,
8fc2fb56
WS
2594 &iter_dict_entry,
2595 &iter_dict_val,
2596 &iter_array))
2597 goto nomem;
2598 }
2599
2600 /***** Scan */
5228401c 2601 if (!wpa_dbus_dict_append_string_array(&iter_dict, "Scan", scans,
e7ecab4a 2602 ARRAY_SIZE(scans)))
8fc2fb56
WS
2603 goto nomem;
2604
2605 /***** Modes */
c988980d
JS
2606 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Modes",
2607 &iter_dict_entry,
2608 &iter_dict_val,
e3c4f0b5
JM
2609 &iter_array) ||
2610 !wpa_dbus_dict_string_array_add_element(
2611 &iter_array, "infrastructure") ||
2612 !wpa_dbus_dict_string_array_add_element(
2613 &iter_array, "ad-hoc") ||
2614 (res >= 0 && (capa.flags & WPA_DRIVER_FLAGS_AP) &&
2615 !wpa_dbus_dict_string_array_add_element(
2616 &iter_array, "ap")) ||
2617 (res >= 0 && (capa.flags & WPA_DRIVER_FLAGS_P2P_CAPABLE) &&
2618 !wpa_dbus_dict_string_array_add_element(
2619 &iter_array, "p2p")) ||
2620 !wpa_dbus_dict_end_string_array(&iter_dict,
c988980d
JS
2621 &iter_dict_entry,
2622 &iter_dict_val,
2623 &iter_array))
2624 goto nomem;
2625 /***** Modes end */
2626
0098ce6d
MA
2627 if (res >= 0) {
2628 dbus_int32_t max_scan_ssid = capa.max_scan_ssids;
2629
2630 if (!wpa_dbus_dict_append_int32(&iter_dict, "MaxScanSSID",
2631 max_scan_ssid))
2632 goto nomem;
2633 }
2634
e3c4f0b5
JM
2635 if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict) ||
2636 !dbus_message_iter_close_container(iter, &variant_iter))
8fc2fb56
WS
2637 goto nomem;
2638
6aeeb6fa 2639 return TRUE;
8fc2fb56
WS
2640
2641nomem:
6aeeb6fa
DW
2642 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
2643 return FALSE;
8fc2fb56
WS
2644}
2645
2646
2647/**
2648 * wpas_dbus_getter_state - Get interface state
6aeeb6fa
DW
2649 * @iter: Pointer to incoming dbus message iter
2650 * @error: Location to store error on failure
2651 * @user_data: Function specific data
2652 * Returns: TRUE on success, FALSE on failure
8fc2fb56
WS
2653 *
2654 * Getter for "State" property.
2655 */
1aa0fb77
DW
2656dbus_bool_t wpas_dbus_getter_state(
2657 const struct wpa_dbus_property_desc *property_desc,
2658 DBusMessageIter *iter, DBusError *error, void *user_data)
8fc2fb56 2659{
6aeeb6fa 2660 struct wpa_supplicant *wpa_s = user_data;
8fc2fb56
WS
2661 const char *str_state;
2662 char *state_ls, *tmp;
6aeeb6fa 2663 dbus_bool_t success = FALSE;
8fc2fb56 2664
fcea0b7d 2665 str_state = wpa_supplicant_state_txt(wpa_s->wpa_state);
8fc2fb56 2666
fcea0b7d
WS
2667 /* make state string lowercase to fit new DBus API convention
2668 */
2669 state_ls = tmp = os_strdup(str_state);
2670 if (!tmp) {
6aeeb6fa
DW
2671 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
2672 return FALSE;
fcea0b7d
WS
2673 }
2674 while (*tmp) {
2675 *tmp = tolower(*tmp);
2676 tmp++;
2677 }
8fc2fb56 2678
6aeeb6fa
DW
2679 success = wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
2680 &state_ls, error);
8fc2fb56 2681
fcea0b7d 2682 os_free(state_ls);
5228401c 2683
6aeeb6fa 2684 return success;
8fc2fb56
WS
2685}
2686
fcea0b7d 2687
8fc2fb56
WS
2688/**
2689 * wpas_dbus_new_iface_get_scanning - Get interface scanning state
6aeeb6fa
DW
2690 * @iter: Pointer to incoming dbus message iter
2691 * @error: Location to store error on failure
2692 * @user_data: Function specific data
2693 * Returns: TRUE on success, FALSE on failure
8fc2fb56
WS
2694 *
2695 * Getter for "scanning" property.
2696 */
1aa0fb77
DW
2697dbus_bool_t wpas_dbus_getter_scanning(
2698 const struct wpa_dbus_property_desc *property_desc,
2699 DBusMessageIter *iter, DBusError *error, void *user_data)
8fc2fb56 2700{
6aeeb6fa 2701 struct wpa_supplicant *wpa_s = user_data;
8fc2fb56 2702 dbus_bool_t scanning = wpa_s->scanning ? TRUE : FALSE;
6aeeb6fa
DW
2703
2704 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
2705 &scanning, error);
fcea0b7d 2706}
8fc2fb56
WS
2707
2708
2709/**
2710 * wpas_dbus_getter_ap_scan - Control roaming mode
6aeeb6fa
DW
2711 * @iter: Pointer to incoming dbus message iter
2712 * @error: Location to store error on failure
2713 * @user_data: Function specific data
2714 * Returns: TRUE on success, FALSE on failure
8fc2fb56
WS
2715 *
2716 * Getter function for "ApScan" property.
2717 */
1aa0fb77
DW
2718dbus_bool_t wpas_dbus_getter_ap_scan(
2719 const struct wpa_dbus_property_desc *property_desc,
2720 DBusMessageIter *iter, DBusError *error, void *user_data)
8fc2fb56 2721{
6aeeb6fa 2722 struct wpa_supplicant *wpa_s = user_data;
8fc2fb56 2723 dbus_uint32_t ap_scan = wpa_s->conf->ap_scan;
6aeeb6fa
DW
2724
2725 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
2726 &ap_scan, error);
8fc2fb56
WS
2727}
2728
2729
2730/**
2731 * wpas_dbus_setter_ap_scan - Control roaming mode
6aeeb6fa
DW
2732 * @iter: Pointer to incoming dbus message iter
2733 * @error: Location to store error on failure
2734 * @user_data: Function specific data
2735 * Returns: TRUE on success, FALSE on failure
8fc2fb56
WS
2736 *
2737 * Setter function for "ApScan" property.
2738 */
1aa0fb77
DW
2739dbus_bool_t wpas_dbus_setter_ap_scan(
2740 const struct wpa_dbus_property_desc *property_desc,
2741 DBusMessageIter *iter, DBusError *error, void *user_data)
8fc2fb56 2742{
6aeeb6fa 2743 struct wpa_supplicant *wpa_s = user_data;
8fc2fb56
WS
2744 dbus_uint32_t ap_scan;
2745
6aeeb6fa
DW
2746 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
2747 &ap_scan))
2748 return FALSE;
8fc2fb56
WS
2749
2750 if (wpa_supplicant_set_ap_scan(wpa_s, ap_scan)) {
6aeeb6fa
DW
2751 dbus_set_error_const(error, DBUS_ERROR_FAILED,
2752 "ap_scan must be 0, 1, or 2");
2753 return FALSE;
8fc2fb56 2754 }
6aeeb6fa 2755 return TRUE;
8fc2fb56
WS
2756}
2757
2758
a4bbb606
PS
2759/**
2760 * wpas_dbus_getter_fast_reauth - Control fast
2761 * reauthentication (TLS session resumption)
2762 * @iter: Pointer to incoming dbus message iter
2763 * @error: Location to store error on failure
2764 * @user_data: Function specific data
2765 * Returns: TRUE on success, FALSE on failure
2766 *
2767 * Getter function for "FastReauth" property.
2768 */
1aa0fb77
DW
2769dbus_bool_t wpas_dbus_getter_fast_reauth(
2770 const struct wpa_dbus_property_desc *property_desc,
2771 DBusMessageIter *iter, DBusError *error, void *user_data)
a4bbb606
PS
2772{
2773 struct wpa_supplicant *wpa_s = user_data;
2774 dbus_bool_t fast_reauth = wpa_s->conf->fast_reauth ? TRUE : FALSE;
2775
2776 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
2777 &fast_reauth, error);
2778}
2779
2780
2781/**
2782 * wpas_dbus_setter_fast_reauth - Control fast
2783 * reauthentication (TLS session resumption)
2784 * @iter: Pointer to incoming dbus message iter
2785 * @error: Location to store error on failure
2786 * @user_data: Function specific data
2787 * Returns: TRUE on success, FALSE on failure
2788 *
2789 * Setter function for "FastReauth" property.
2790 */
1aa0fb77
DW
2791dbus_bool_t wpas_dbus_setter_fast_reauth(
2792 const struct wpa_dbus_property_desc *property_desc,
2793 DBusMessageIter *iter, DBusError *error, void *user_data)
a4bbb606
PS
2794{
2795 struct wpa_supplicant *wpa_s = user_data;
2796 dbus_bool_t fast_reauth;
2797
2798 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
2799 &fast_reauth))
2800 return FALSE;
2801
2802 wpa_s->conf->fast_reauth = fast_reauth;
2803 return TRUE;
2804}
2805
2806
0bb1e425
GM
2807/**
2808 * wpas_dbus_getter_disconnect_reason - Get most recent reason for disconnect
2809 * @iter: Pointer to incoming dbus message iter
2810 * @error: Location to store error on failure
2811 * @user_data: Function specific data
2812 * Returns: TRUE on success, FALSE on failure
2813 *
2814 * Getter for "DisconnectReason" property. The reason is negative if it is
2815 * locally generated.
2816 */
1aa0fb77
DW
2817dbus_bool_t wpas_dbus_getter_disconnect_reason(
2818 const struct wpa_dbus_property_desc *property_desc,
2819 DBusMessageIter *iter, DBusError *error, void *user_data)
0bb1e425
GM
2820{
2821 struct wpa_supplicant *wpa_s = user_data;
2822 dbus_int32_t reason = wpa_s->disconnect_reason;
38279bdb 2823
0bb1e425
GM
2824 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
2825 &reason, error);
2826}
2827
2828
78633c37
SL
2829/**
2830 * wpas_dbus_getter_bss_expire_age - Get BSS entry expiration age
6aeeb6fa
DW
2831 * @iter: Pointer to incoming dbus message iter
2832 * @error: Location to store error on failure
2833 * @user_data: Function specific data
2834 * Returns: TRUE on success, FALSE on failure
78633c37
SL
2835 *
2836 * Getter function for "BSSExpireAge" property.
2837 */
1aa0fb77
DW
2838dbus_bool_t wpas_dbus_getter_bss_expire_age(
2839 const struct wpa_dbus_property_desc *property_desc,
2840 DBusMessageIter *iter, DBusError *error, void *user_data)
78633c37 2841{
6aeeb6fa 2842 struct wpa_supplicant *wpa_s = user_data;
78633c37 2843 dbus_uint32_t expire_age = wpa_s->conf->bss_expiration_age;
6aeeb6fa
DW
2844
2845 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
2846 &expire_age, error);
78633c37
SL
2847}
2848
2849
2850/**
2851 * wpas_dbus_setter_bss_expire_age - Control BSS entry expiration age
6aeeb6fa
DW
2852 * @iter: Pointer to incoming dbus message iter
2853 * @error: Location to store error on failure
2854 * @user_data: Function specific data
2855 * Returns: TRUE on success, FALSE on failure
78633c37
SL
2856 *
2857 * Setter function for "BSSExpireAge" property.
2858 */
1aa0fb77
DW
2859dbus_bool_t wpas_dbus_setter_bss_expire_age(
2860 const struct wpa_dbus_property_desc *property_desc,
2861 DBusMessageIter *iter, DBusError *error, void *user_data)
78633c37 2862{
6aeeb6fa 2863 struct wpa_supplicant *wpa_s = user_data;
78633c37
SL
2864 dbus_uint32_t expire_age;
2865
6aeeb6fa
DW
2866 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
2867 &expire_age))
2868 return FALSE;
78633c37
SL
2869
2870 if (wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age)) {
6aeeb6fa
DW
2871 dbus_set_error_const(error, DBUS_ERROR_FAILED,
2872 "BSSExpireAge must be >= 10");
2873 return FALSE;
78633c37 2874 }
6aeeb6fa 2875 return TRUE;
78633c37
SL
2876}
2877
2878
2879/**
2880 * wpas_dbus_getter_bss_expire_count - Get BSS entry expiration scan count
6aeeb6fa
DW
2881 * @iter: Pointer to incoming dbus message iter
2882 * @error: Location to store error on failure
2883 * @user_data: Function specific data
2884 * Returns: TRUE on success, FALSE on failure
78633c37
SL
2885 *
2886 * Getter function for "BSSExpireCount" property.
2887 */
1aa0fb77
DW
2888dbus_bool_t wpas_dbus_getter_bss_expire_count(
2889 const struct wpa_dbus_property_desc *property_desc,
2890 DBusMessageIter *iter, DBusError *error, void *user_data)
78633c37 2891{
6aeeb6fa 2892 struct wpa_supplicant *wpa_s = user_data;
c10fe8c1 2893 dbus_uint32_t expire_count = wpa_s->conf->bss_expiration_scan_count;
6aeeb6fa
DW
2894
2895 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
2896 &expire_count, error);
78633c37
SL
2897}
2898
2899
2900/**
2901 * wpas_dbus_setter_bss_expire_count - Control BSS entry expiration scan count
6aeeb6fa
DW
2902 * @iter: Pointer to incoming dbus message iter
2903 * @error: Location to store error on failure
2904 * @user_data: Function specific data
2905 * Returns: TRUE on success, FALSE on failure
78633c37
SL
2906 *
2907 * Setter function for "BSSExpireCount" property.
2908 */
1aa0fb77
DW
2909dbus_bool_t wpas_dbus_setter_bss_expire_count(
2910 const struct wpa_dbus_property_desc *property_desc,
2911 DBusMessageIter *iter, DBusError *error, void *user_data)
78633c37 2912{
6aeeb6fa 2913 struct wpa_supplicant *wpa_s = user_data;
78633c37
SL
2914 dbus_uint32_t expire_count;
2915
6aeeb6fa
DW
2916 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
2917 &expire_count))
2918 return FALSE;
78633c37
SL
2919
2920 if (wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count)) {
6aeeb6fa
DW
2921 dbus_set_error_const(error, DBUS_ERROR_FAILED,
2922 "BSSExpireCount must be > 0");
2923 return FALSE;
78633c37 2924 }
6aeeb6fa 2925 return TRUE;
78633c37
SL
2926}
2927
2928
9768da20
SL
2929/**
2930 * wpas_dbus_getter_country - Control country code
6aeeb6fa
DW
2931 * @iter: Pointer to incoming dbus message iter
2932 * @error: Location to store error on failure
2933 * @user_data: Function specific data
2934 * Returns: TRUE on success, FALSE on failure
9768da20
SL
2935 *
2936 * Getter function for "Country" property.
2937 */
1aa0fb77
DW
2938dbus_bool_t wpas_dbus_getter_country(
2939 const struct wpa_dbus_property_desc *property_desc,
2940 DBusMessageIter *iter, DBusError *error, void *user_data)
9768da20 2941{
6aeeb6fa 2942 struct wpa_supplicant *wpa_s = user_data;
9768da20
SL
2943 char country[3];
2944 char *str = country;
2945
2946 country[0] = wpa_s->conf->country[0];
2947 country[1] = wpa_s->conf->country[1];
2948 country[2] = '\0';
2949
6aeeb6fa
DW
2950 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
2951 &str, error);
9768da20
SL
2952}
2953
2954
2955/**
2956 * wpas_dbus_setter_country - Control country code
6aeeb6fa
DW
2957 * @iter: Pointer to incoming dbus message iter
2958 * @error: Location to store error on failure
2959 * @user_data: Function specific data
2960 * Returns: TRUE on success, FALSE on failure
9768da20
SL
2961 *
2962 * Setter function for "Country" property.
2963 */
1aa0fb77
DW
2964dbus_bool_t wpas_dbus_setter_country(
2965 const struct wpa_dbus_property_desc *property_desc,
2966 DBusMessageIter *iter, DBusError *error, void *user_data)
9768da20 2967{
6aeeb6fa 2968 struct wpa_supplicant *wpa_s = user_data;
9768da20
SL
2969 const char *country;
2970
6aeeb6fa
DW
2971 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
2972 &country))
2973 return FALSE;
9768da20 2974
6aeeb6fa
DW
2975 if (!country[0] || !country[1]) {
2976 dbus_set_error_const(error, DBUS_ERROR_FAILED,
2977 "invalid country code");
2978 return FALSE;
2979 }
9768da20
SL
2980
2981 if (wpa_s->drv_priv != NULL && wpa_drv_set_country(wpa_s, country)) {
2982 wpa_printf(MSG_DEBUG, "Failed to set country");
6aeeb6fa
DW
2983 dbus_set_error_const(error, DBUS_ERROR_FAILED,
2984 "failed to set country code");
2985 return FALSE;
9768da20
SL
2986 }
2987
2988 wpa_s->conf->country[0] = country[0];
2989 wpa_s->conf->country[1] = country[1];
6aeeb6fa 2990 return TRUE;
9768da20
SL
2991}
2992
2993
c6e86b63
MA
2994/**
2995 * wpas_dbus_getter_scan_interval - Get scan interval
2996 * @iter: Pointer to incoming dbus message iter
2997 * @error: Location to store error on failure
2998 * @user_data: Function specific data
2999 * Returns: TRUE on success, FALSE on failure
3000 *
3001 * Getter function for "ScanInterval" property.
3002 */
1aa0fb77
DW
3003dbus_bool_t wpas_dbus_getter_scan_interval(
3004 const struct wpa_dbus_property_desc *property_desc,
3005 DBusMessageIter *iter, DBusError *error, void *user_data)
c6e86b63
MA
3006{
3007 struct wpa_supplicant *wpa_s = user_data;
3008 dbus_int32_t scan_interval = wpa_s->scan_interval;
3009
3010 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
3011 &scan_interval, error);
3012}
3013
3014
3015/**
3016 * wpas_dbus_setter_scan_interval - Control scan interval
3017 * @iter: Pointer to incoming dbus message iter
3018 * @error: Location to store error on failure
3019 * @user_data: Function specific data
3020 * Returns: TRUE on success, FALSE on failure
3021 *
3022 * Setter function for "ScanInterval" property.
3023 */
1aa0fb77
DW
3024dbus_bool_t wpas_dbus_setter_scan_interval(
3025 const struct wpa_dbus_property_desc *property_desc,
3026 DBusMessageIter *iter, DBusError *error, void *user_data)
c6e86b63
MA
3027{
3028 struct wpa_supplicant *wpa_s = user_data;
3029 dbus_int32_t scan_interval;
3030
3031 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_INT32,
3032 &scan_interval))
3033 return FALSE;
3034
3035 if (wpa_supplicant_set_scan_interval(wpa_s, scan_interval)) {
3036 dbus_set_error_const(error, DBUS_ERROR_FAILED,
3037 "scan_interval must be >= 0");
3038 return FALSE;
3039 }
3040 return TRUE;
3041}
3042
3043
8fc2fb56
WS
3044/**
3045 * wpas_dbus_getter_ifname - Get interface name
6aeeb6fa
DW
3046 * @iter: Pointer to incoming dbus message iter
3047 * @error: Location to store error on failure
3048 * @user_data: Function specific data
3049 * Returns: TRUE on success, FALSE on failure
8fc2fb56
WS
3050 *
3051 * Getter for "Ifname" property.
3052 */
1aa0fb77
DW
3053dbus_bool_t wpas_dbus_getter_ifname(
3054 const struct wpa_dbus_property_desc *property_desc,
3055 DBusMessageIter *iter, DBusError *error, void *user_data)
8fc2fb56 3056{
6aeeb6fa 3057 struct wpa_supplicant *wpa_s = user_data;
fcea0b7d 3058 const char *ifname = wpa_s->ifname;
6aeeb6fa
DW
3059
3060 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3061 &ifname, error);
8fc2fb56
WS
3062}
3063
3064
3065/**
3066 * wpas_dbus_getter_driver - Get interface name
6aeeb6fa
DW
3067 * @iter: Pointer to incoming dbus message iter
3068 * @error: Location to store error on failure
3069 * @user_data: Function specific data
3070 * Returns: TRUE on success, FALSE on failure
8fc2fb56
WS
3071 *
3072 * Getter for "Driver" property.
3073 */
1aa0fb77
DW
3074dbus_bool_t wpas_dbus_getter_driver(
3075 const struct wpa_dbus_property_desc *property_desc,
3076 DBusMessageIter *iter, DBusError *error, void *user_data)
8fc2fb56 3077{
6aeeb6fa 3078 struct wpa_supplicant *wpa_s = user_data;
fcea0b7d 3079 const char *driver;
8fc2fb56
WS
3080
3081 if (wpa_s->driver == NULL || wpa_s->driver->name == NULL) {
38279bdb
JM
3082 wpa_printf(MSG_DEBUG, "%s[dbus]: wpa_s has no driver set",
3083 __func__);
6aeeb6fa
DW
3084 dbus_set_error(error, DBUS_ERROR_FAILED, "%s: no driver set",
3085 __func__);
3086 return FALSE;
8fc2fb56
WS
3087 }
3088
3089 driver = wpa_s->driver->name;
6aeeb6fa
DW
3090 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3091 &driver, error);
8fc2fb56
WS
3092}
3093
3094
3095/**
3096 * wpas_dbus_getter_current_bss - Get current bss object path
6aeeb6fa
DW
3097 * @iter: Pointer to incoming dbus message iter
3098 * @error: Location to store error on failure
3099 * @user_data: Function specific data
3100 * Returns: TRUE on success, FALSE on failure
8fc2fb56
WS
3101 *
3102 * Getter for "CurrentBSS" property.
3103 */
1aa0fb77
DW
3104dbus_bool_t wpas_dbus_getter_current_bss(
3105 const struct wpa_dbus_property_desc *property_desc,
3106 DBusMessageIter *iter, DBusError *error, void *user_data)
8fc2fb56 3107{
6aeeb6fa 3108 struct wpa_supplicant *wpa_s = user_data;
3e87bd54 3109 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *bss_obj_path = path_buf;
8fc2fb56 3110
8a78e227 3111 if (wpa_s->current_bss && wpa_s->dbus_new_path)
5228401c 3112 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
ccd286d0 3113 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
8f770587 3114 wpa_s->dbus_new_path, wpa_s->current_bss->id);
8fc2fb56 3115 else
5228401c 3116 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
8fc2fb56 3117
6aeeb6fa
DW
3118 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
3119 &bss_obj_path, error);
8fc2fb56
WS
3120}
3121
3122
3123/**
3124 * wpas_dbus_getter_current_network - Get current network object path
6aeeb6fa
DW
3125 * @iter: Pointer to incoming dbus message iter
3126 * @error: Location to store error on failure
3127 * @user_data: Function specific data
3128 * Returns: TRUE on success, FALSE on failure
8fc2fb56
WS
3129 *
3130 * Getter for "CurrentNetwork" property.
3131 */
1aa0fb77
DW
3132dbus_bool_t wpas_dbus_getter_current_network(
3133 const struct wpa_dbus_property_desc *property_desc,
3134 DBusMessageIter *iter, DBusError *error, void *user_data)
8fc2fb56 3135{
6aeeb6fa 3136 struct wpa_supplicant *wpa_s = user_data;
3e87bd54 3137 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *net_obj_path = path_buf;
8fc2fb56 3138
8a78e227 3139 if (wpa_s->current_ssid && wpa_s->dbus_new_path)
5228401c 3140 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
c49cf2d6
JM
3141 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
3142 wpa_s->dbus_new_path, wpa_s->current_ssid->id);
8fc2fb56 3143 else
5228401c 3144 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
8fc2fb56 3145
6aeeb6fa
DW
3146 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
3147 &net_obj_path, error);
8fc2fb56
WS
3148}
3149
3150
ba6f267f
PS
3151/**
3152 * wpas_dbus_getter_current_auth_mode - Get current authentication type
6aeeb6fa
DW
3153 * @iter: Pointer to incoming dbus message iter
3154 * @error: Location to store error on failure
3155 * @user_data: Function specific data
3156 * Returns: TRUE on success, FALSE on failure
ba6f267f
PS
3157 *
3158 * Getter for "CurrentAuthMode" property.
3159 */
1aa0fb77
DW
3160dbus_bool_t wpas_dbus_getter_current_auth_mode(
3161 const struct wpa_dbus_property_desc *property_desc,
3162 DBusMessageIter *iter, DBusError *error, void *user_data)
ba6f267f 3163{
6aeeb6fa 3164 struct wpa_supplicant *wpa_s = user_data;
ba6f267f
PS
3165 const char *eap_mode;
3166 const char *auth_mode;
3167 char eap_mode_buf[WPAS_DBUS_AUTH_MODE_MAX];
3168
3169 if (wpa_s->wpa_state != WPA_COMPLETED) {
3170 auth_mode = "INACTIVE";
3171 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X ||
3172 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3173 eap_mode = wpa_supplicant_get_eap_mode(wpa_s);
3174 os_snprintf(eap_mode_buf, WPAS_DBUS_AUTH_MODE_MAX,
3175 "EAP-%s", eap_mode);
3176 auth_mode = eap_mode_buf;
3177
3178 } else {
3179 auth_mode = wpa_key_mgmt_txt(wpa_s->key_mgmt,
3180 wpa_s->current_ssid->proto);
3181 }
3182
6aeeb6fa
DW
3183 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3184 &auth_mode, error);
ba6f267f
PS
3185}
3186
3187
8fc2fb56
WS
3188/**
3189 * wpas_dbus_getter_bridge_ifname - Get interface name
6aeeb6fa
DW
3190 * @iter: Pointer to incoming dbus message iter
3191 * @error: Location to store error on failure
3192 * @user_data: Function specific data
3193 * Returns: TRUE on success, FALSE on failure
8fc2fb56
WS
3194 *
3195 * Getter for "BridgeIfname" property.
3196 */
1aa0fb77
DW
3197dbus_bool_t wpas_dbus_getter_bridge_ifname(
3198 const struct wpa_dbus_property_desc *property_desc,
3199 DBusMessageIter *iter, DBusError *error, void *user_data)
8fc2fb56 3200{
6aeeb6fa 3201 struct wpa_supplicant *wpa_s = user_data;
c660b0c2 3202 const char *bridge_ifname = wpa_s->bridge_ifname;
38279bdb 3203
6aeeb6fa
DW
3204 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3205 &bridge_ifname, error);
8fc2fb56
WS
3206}
3207
3208
3209/**
3210 * wpas_dbus_getter_bsss - Get array of BSSs objects
6aeeb6fa
DW
3211 * @iter: Pointer to incoming dbus message iter
3212 * @error: Location to store error on failure
3213 * @user_data: Function specific data
3214 * Returns: TRUE on success, FALSE on failure
8fc2fb56
WS
3215 *
3216 * Getter for "BSSs" property.
3217 */
1aa0fb77
DW
3218dbus_bool_t wpas_dbus_getter_bsss(
3219 const struct wpa_dbus_property_desc *property_desc,
3220 DBusMessageIter *iter, DBusError *error, void *user_data)
8fc2fb56 3221{
6aeeb6fa 3222 struct wpa_supplicant *wpa_s = user_data;
ccd286d0 3223 struct wpa_bss *bss;
fcea0b7d
WS
3224 char **paths;
3225 unsigned int i = 0;
6aeeb6fa 3226 dbus_bool_t success = FALSE;
8fc2fb56 3227
8a78e227
JM
3228 if (!wpa_s->dbus_new_path) {
3229 dbus_set_error(error, DBUS_ERROR_FAILED,
3230 "%s: no D-Bus interface", __func__);
3231 return FALSE;
3232 }
3233
f9884c09 3234 paths = os_calloc(wpa_s->num_bss, sizeof(char *));
fcea0b7d 3235 if (!paths) {
6aeeb6fa
DW
3236 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3237 return FALSE;
8fc2fb56
WS
3238 }
3239
3240 /* Loop through scan results and append each result's object path */
ccd286d0 3241 dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
fcea0b7d
WS
3242 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
3243 if (paths[i] == NULL) {
6aeeb6fa
DW
3244 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
3245 "no memory");
8fc2fb56
WS
3246 goto out;
3247 }
ccd286d0 3248 /* Construct the object path for this BSS. */
fcea0b7d 3249 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
ccd286d0 3250 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
c49cf2d6 3251 wpa_s->dbus_new_path, bss->id);
8fc2fb56
WS
3252 }
3253
6aeeb6fa
DW
3254 success = wpas_dbus_simple_array_property_getter(iter,
3255 DBUS_TYPE_OBJECT_PATH,
3256 paths, wpa_s->num_bss,
3257 error);
8fc2fb56
WS
3258
3259out:
3e87bd54 3260 while (i)
fcea0b7d
WS
3261 os_free(paths[--i]);
3262 os_free(paths);
6aeeb6fa 3263 return success;
8fc2fb56
WS
3264}
3265
3266
3267/**
3268 * wpas_dbus_getter_networks - Get array of networks objects
6aeeb6fa
DW
3269 * @iter: Pointer to incoming dbus message iter
3270 * @error: Location to store error on failure
3271 * @user_data: Function specific data
3272 * Returns: TRUE on success, FALSE on failure
8fc2fb56
WS
3273 *
3274 * Getter for "Networks" property.
3275 */
1aa0fb77
DW
3276dbus_bool_t wpas_dbus_getter_networks(
3277 const struct wpa_dbus_property_desc *property_desc,
3278 DBusMessageIter *iter, DBusError *error, void *user_data)
8fc2fb56 3279{
6aeeb6fa 3280 struct wpa_supplicant *wpa_s = user_data;
8fc2fb56 3281 struct wpa_ssid *ssid;
fcea0b7d
WS
3282 char **paths;
3283 unsigned int i = 0, num = 0;
6aeeb6fa 3284 dbus_bool_t success = FALSE;
8fc2fb56 3285
8a78e227
JM
3286 if (!wpa_s->dbus_new_path) {
3287 dbus_set_error(error, DBUS_ERROR_FAILED,
3288 "%s: no D-Bus interface", __func__);
3289 return FALSE;
3290 }
3291
fcea0b7d 3292 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
c2762e41
JS
3293 if (!network_is_persistent_group(ssid))
3294 num++;
8fc2fb56 3295
f9884c09 3296 paths = os_calloc(num, sizeof(char *));
fcea0b7d 3297 if (!paths) {
6aeeb6fa
DW
3298 dbus_set_error(error, DBUS_ERROR_NO_MEMORY, "no memory");
3299 return FALSE;
8fc2fb56
WS
3300 }
3301
fcea0b7d 3302 /* Loop through configured networks and append object path of each */
8fc2fb56 3303 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
c2762e41
JS
3304 if (network_is_persistent_group(ssid))
3305 continue;
fcea0b7d
WS
3306 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
3307 if (paths[i] == NULL) {
38279bdb
JM
3308 dbus_set_error(error, DBUS_ERROR_NO_MEMORY,
3309 "no memory");
8fc2fb56
WS
3310 goto out;
3311 }
3312
3313 /* Construct the object path for this network. */
fcea0b7d 3314 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
5228401c 3315 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
c49cf2d6 3316 wpa_s->dbus_new_path, ssid->id);
8fc2fb56
WS
3317 }
3318
6aeeb6fa
DW
3319 success = wpas_dbus_simple_array_property_getter(iter,
3320 DBUS_TYPE_OBJECT_PATH,
3321 paths, num, error);
8fc2fb56
WS
3322
3323out:
fcea0b7d
WS
3324 while (i)
3325 os_free(paths[--i]);
3326 os_free(paths);
6aeeb6fa 3327 return success;
8fc2fb56
WS
3328}
3329
3330
bdec7ee5
MS
3331/**
3332 * wpas_dbus_getter_pkcs11_engine_path - Get PKCS #11 engine path
3333 * @iter: Pointer to incoming dbus message iter
3334 * @error: Location to store error on failure
3335 * @user_data: Function specific data
3336 * Returns: A dbus message containing the PKCS #11 engine path
3337 *
3338 * Getter for "PKCS11EnginePath" property.
3339 */
1aa0fb77
DW
3340dbus_bool_t wpas_dbus_getter_pkcs11_engine_path(
3341 const struct wpa_dbus_property_desc *property_desc,
3342 DBusMessageIter *iter, DBusError *error, void *user_data)
bdec7ee5
MS
3343{
3344 struct wpa_supplicant *wpa_s = user_data;
3345 const char *pkcs11_engine_path;
3346
bdec7ee5
MS
3347 if (wpa_s->conf->pkcs11_engine_path == NULL)
3348 pkcs11_engine_path = "";
3349 else
3350 pkcs11_engine_path = wpa_s->conf->pkcs11_engine_path;
3351 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3352 &pkcs11_engine_path, error);
3353}
3354
3355
3356/**
3357 * wpas_dbus_getter_pkcs11_module_path - Get PKCS #11 module path
3358 * @iter: Pointer to incoming dbus message iter
3359 * @error: Location to store error on failure
3360 * @user_data: Function specific data
3361 * Returns: A dbus message containing the PKCS #11 module path
3362 *
3363 * Getter for "PKCS11ModulePath" property.
3364 */
1aa0fb77
DW
3365dbus_bool_t wpas_dbus_getter_pkcs11_module_path(
3366 const struct wpa_dbus_property_desc *property_desc,
3367 DBusMessageIter *iter, DBusError *error, void *user_data)
bdec7ee5
MS
3368{
3369 struct wpa_supplicant *wpa_s = user_data;
3370 const char *pkcs11_module_path;
3371
bdec7ee5
MS
3372 if (wpa_s->conf->pkcs11_module_path == NULL)
3373 pkcs11_module_path = "";
3374 else
3375 pkcs11_module_path = wpa_s->conf->pkcs11_module_path;
3376 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3377 &pkcs11_module_path, error);
3378}
3379
3380
8fc2fb56
WS
3381/**
3382 * wpas_dbus_getter_blobs - Get all blobs defined for this interface
6aeeb6fa
DW
3383 * @iter: Pointer to incoming dbus message iter
3384 * @error: Location to store error on failure
3385 * @user_data: Function specific data
3386 * Returns: TRUE on success, FALSE on failure
8fc2fb56
WS
3387 *
3388 * Getter for "Blobs" property.
3389 */
1aa0fb77
DW
3390dbus_bool_t wpas_dbus_getter_blobs(
3391 const struct wpa_dbus_property_desc *property_desc,
3392 DBusMessageIter *iter, DBusError *error, void *user_data)
8fc2fb56 3393{
6aeeb6fa
DW
3394 struct wpa_supplicant *wpa_s = user_data;
3395 DBusMessageIter variant_iter, dict_iter, entry_iter, array_iter;
8fc2fb56
WS
3396 struct wpa_config_blob *blob;
3397
6aeeb6fa 3398 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
c2b8c674
JM
3399 "a{say}", &variant_iter) ||
3400 !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
5228401c 3401 "{say}", &dict_iter)) {
6aeeb6fa
DW
3402 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3403 return FALSE;
8fc2fb56
WS
3404 }
3405
3406 blob = wpa_s->conf->blobs;
3407 while (blob) {
5228401c
JM
3408 if (!dbus_message_iter_open_container(&dict_iter,
3409 DBUS_TYPE_DICT_ENTRY,
c2b8c674
JM
3410 NULL, &entry_iter) ||
3411 !dbus_message_iter_append_basic(&entry_iter,
5228401c 3412 DBUS_TYPE_STRING,
c2b8c674
JM
3413 &(blob->name)) ||
3414 !dbus_message_iter_open_container(&entry_iter,
5228401c
JM
3415 DBUS_TYPE_ARRAY,
3416 DBUS_TYPE_BYTE_AS_STRING,
c2b8c674
JM
3417 &array_iter) ||
3418 !dbus_message_iter_append_fixed_array(&array_iter,
5228401c
JM
3419 DBUS_TYPE_BYTE,
3420 &(blob->data),
c2b8c674
JM
3421 blob->len) ||
3422 !dbus_message_iter_close_container(&entry_iter,
3423 &array_iter) ||
3424 !dbus_message_iter_close_container(&dict_iter,
5228401c 3425 &entry_iter)) {
6aeeb6fa
DW
3426 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
3427 "no memory");
3428 return FALSE;
8fc2fb56
WS
3429 }
3430
3431 blob = blob->next;
3432 }
3433
c2b8c674 3434 if (!dbus_message_iter_close_container(&variant_iter, &dict_iter) ||
6aeeb6fa
DW
3435 !dbus_message_iter_close_container(iter, &variant_iter)) {
3436 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3437 return FALSE;
8fc2fb56
WS
3438 }
3439
6aeeb6fa
DW
3440 return TRUE;
3441}
3442
3443
e50c50d5
DW
3444dbus_bool_t wpas_dbus_getter_iface_global(
3445 const struct wpa_dbus_property_desc *property_desc,
3446 DBusMessageIter *iter, DBusError *error, void *user_data)
3447{
3448 struct wpa_supplicant *wpa_s = user_data;
3449 int ret;
3450 char buf[250];
3451 char *p = buf;
3452
3453 if (!property_desc->data) {
3454 dbus_set_error(error, DBUS_ERROR_INVALID_ARGS,
3455 "Unhandled interface property %s",
3456 property_desc->dbus_property);
3457 return FALSE;
3458 }
3459
3460 ret = wpa_config_get_value(property_desc->data, wpa_s->conf, buf,
3461 sizeof(buf));
3462 if (ret < 0)
3463 *p = '\0';
3464
3465 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &p,
3466 error);
3467}
3468
3469
3470dbus_bool_t wpas_dbus_setter_iface_global(
3471 const struct wpa_dbus_property_desc *property_desc,
3472 DBusMessageIter *iter, DBusError *error, void *user_data)
3473{
3474 struct wpa_supplicant *wpa_s = user_data;
3475 const char *new_value = NULL;
3476 char buf[250];
3477 size_t combined_len;
3478 int ret;
3479
3480 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
3481 &new_value))
3482 return FALSE;
3483
3484 combined_len = os_strlen(property_desc->data) + os_strlen(new_value) +
3485 3;
3486 if (combined_len >= sizeof(buf)) {
3487 dbus_set_error(error, DBUS_ERROR_INVALID_ARGS,
3488 "Interface property %s value too large",
3489 property_desc->dbus_property);
3490 return FALSE;
3491 }
3492
3493 if (!new_value[0])
3494 new_value = "NULL";
3495
3496 ret = os_snprintf(buf, combined_len, "%s=%s", property_desc->data,
3497 new_value);
3498 if (os_snprintf_error(combined_len, ret)) {
3499 dbus_set_error(error, WPAS_DBUS_ERROR_UNKNOWN_ERROR,
3500 "Failed to construct new interface property %s",
3501 property_desc->dbus_property);
3502 return FALSE;
3503 }
3504
3505 if (wpa_config_process_global(wpa_s->conf, buf, -1)) {
3506 dbus_set_error(error, DBUS_ERROR_INVALID_ARGS,
3507 "Failed to set interface property %s",
3508 property_desc->dbus_property);
3509 return FALSE;
3510 }
3511
3512 wpa_supplicant_update_config(wpa_s);
3513 return TRUE;
3514}
3515
3516
6aeeb6fa
DW
3517static struct wpa_bss * get_bss_helper(struct bss_handler_args *args,
3518 DBusError *error, const char *func_name)
3519{
3520 struct wpa_bss *res = wpa_bss_get_id(args->wpa_s, args->id);
3521
3522 if (!res) {
3523 wpa_printf(MSG_ERROR, "%s[dbus]: no bss with id %d found",
38279bdb 3524 func_name, args->id);
6aeeb6fa
DW
3525 dbus_set_error(error, DBUS_ERROR_FAILED,
3526 "%s: BSS %d not found",
3527 func_name, args->id);
3528 }
3529
3530 return res;
8fc2fb56
WS
3531}
3532
3533
3534/**
58605c6e 3535 * wpas_dbus_getter_bss_bssid - Return the BSSID of a BSS
6aeeb6fa
DW
3536 * @iter: Pointer to incoming dbus message iter
3537 * @error: Location to store error on failure
3538 * @user_data: Function specific data
3539 * Returns: TRUE on success, FALSE on failure
8fc2fb56 3540 *
58605c6e 3541 * Getter for "BSSID" property.
8fc2fb56 3542 */
1aa0fb77
DW
3543dbus_bool_t wpas_dbus_getter_bss_bssid(
3544 const struct wpa_dbus_property_desc *property_desc,
3545 DBusMessageIter *iter, DBusError *error, void *user_data)
58605c6e 3546{
6aeeb6fa
DW
3547 struct bss_handler_args *args = user_data;
3548 struct wpa_bss *res;
58605c6e 3549
6aeeb6fa
DW
3550 res = get_bss_helper(args, error, __func__);
3551 if (!res)
3552 return FALSE;
58605c6e 3553
6aeeb6fa
DW
3554 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
3555 res->bssid, ETH_ALEN,
3556 error);
58605c6e
WS
3557}
3558
3559
3560/**
3561 * wpas_dbus_getter_bss_ssid - Return the SSID of a BSS
6aeeb6fa
DW
3562 * @iter: Pointer to incoming dbus message iter
3563 * @error: Location to store error on failure
3564 * @user_data: Function specific data
3565 * Returns: TRUE on success, FALSE on failure
58605c6e
WS
3566 *
3567 * Getter for "SSID" property.
3568 */
1aa0fb77
DW
3569dbus_bool_t wpas_dbus_getter_bss_ssid(
3570 const struct wpa_dbus_property_desc *property_desc,
3571 DBusMessageIter *iter, DBusError *error, void *user_data)
8fc2fb56 3572{
6aeeb6fa
DW
3573 struct bss_handler_args *args = user_data;
3574 struct wpa_bss *res;
8fc2fb56 3575
6aeeb6fa
DW
3576 res = get_bss_helper(args, error, __func__);
3577 if (!res)
3578 return FALSE;
8fc2fb56 3579
6aeeb6fa
DW
3580 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
3581 res->ssid, res->ssid_len,
3582 error);
58605c6e 3583}
8fc2fb56 3584
8fc2fb56 3585
58605c6e
WS
3586/**
3587 * wpas_dbus_getter_bss_privacy - Return the privacy flag of a BSS
6aeeb6fa
DW
3588 * @iter: Pointer to incoming dbus message iter
3589 * @error: Location to store error on failure
3590 * @user_data: Function specific data
3591 * Returns: TRUE on success, FALSE on failure
58605c6e
WS
3592 *
3593 * Getter for "Privacy" property.
3594 */
1aa0fb77
DW
3595dbus_bool_t wpas_dbus_getter_bss_privacy(
3596 const struct wpa_dbus_property_desc *property_desc,
3597 DBusMessageIter *iter, DBusError *error, void *user_data)
58605c6e 3598{
6aeeb6fa
DW
3599 struct bss_handler_args *args = user_data;
3600 struct wpa_bss *res;
58605c6e 3601 dbus_bool_t privacy;
8fc2fb56 3602
6aeeb6fa
DW
3603 res = get_bss_helper(args, error, __func__);
3604 if (!res)
3605 return FALSE;
8fc2fb56 3606
097c5802 3607 privacy = (res->caps & IEEE80211_CAP_PRIVACY) ? TRUE : FALSE;
6aeeb6fa
DW
3608 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
3609 &privacy, error);
58605c6e 3610}
8fc2fb56 3611
8fc2fb56 3612
58605c6e
WS
3613/**
3614 * wpas_dbus_getter_bss_mode - Return the mode of a BSS
6aeeb6fa
DW
3615 * @iter: Pointer to incoming dbus message iter
3616 * @error: Location to store error on failure
3617 * @user_data: Function specific data
3618 * Returns: TRUE on success, FALSE on failure
58605c6e
WS
3619 *
3620 * Getter for "Mode" property.
3621 */
1aa0fb77
DW
3622dbus_bool_t wpas_dbus_getter_bss_mode(
3623 const struct wpa_dbus_property_desc *property_desc,
3624 DBusMessageIter *iter, DBusError *error, void *user_data)
58605c6e 3625{
6aeeb6fa
DW
3626 struct bss_handler_args *args = user_data;
3627 struct wpa_bss *res;
58605c6e
WS
3628 const char *mode;
3629
6aeeb6fa
DW
3630 res = get_bss_helper(args, error, __func__);
3631 if (!res)
3632 return FALSE;
e403ba85
BS
3633 if (bss_is_dmg(res)) {
3634 switch (res->caps & IEEE80211_CAP_DMG_MASK) {
3635 case IEEE80211_CAP_DMG_PBSS:
3636 case IEEE80211_CAP_DMG_IBSS:
3637 mode = "ad-hoc";
3638 break;
3639 case IEEE80211_CAP_DMG_AP:
3640 mode = "infrastructure";
3641 break;
3642 }
3643 } else {
3644 if (res->caps & IEEE80211_CAP_IBSS)
3645 mode = "ad-hoc";
3646 else
3647 mode = "infrastructure";
3648 }
58605c6e 3649
6aeeb6fa
DW
3650 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3651 &mode, error);
58605c6e
WS
3652}
3653
3654
3655/**
3656 * wpas_dbus_getter_bss_level - Return the signal strength of a BSS
6aeeb6fa
DW
3657 * @iter: Pointer to incoming dbus message iter
3658 * @error: Location to store error on failure
3659 * @user_data: Function specific data
3660 * Returns: TRUE on success, FALSE on failure
58605c6e
WS
3661 *
3662 * Getter for "Level" property.
3663 */
1aa0fb77
DW
3664dbus_bool_t wpas_dbus_getter_bss_signal(
3665 const struct wpa_dbus_property_desc *property_desc,
3666 DBusMessageIter *iter, DBusError *error, void *user_data)
58605c6e 3667{
6aeeb6fa
DW
3668 struct bss_handler_args *args = user_data;
3669 struct wpa_bss *res;
3d0a8438 3670 s16 level;
58605c6e 3671
6aeeb6fa
DW
3672 res = get_bss_helper(args, error, __func__);
3673 if (!res)
3674 return FALSE;
8fc2fb56 3675
3d0a8438 3676 level = (s16) res->level;
6aeeb6fa 3677 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT16,
3d0a8438 3678 &level, error);
58605c6e
WS
3679}
3680
3681
3682/**
3683 * wpas_dbus_getter_bss_frequency - Return the frequency of a BSS
6aeeb6fa
DW
3684 * @iter: Pointer to incoming dbus message iter
3685 * @error: Location to store error on failure
3686 * @user_data: Function specific data
3687 * Returns: TRUE on success, FALSE on failure
58605c6e
WS
3688 *
3689 * Getter for "Frequency" property.
3690 */
1aa0fb77
DW
3691dbus_bool_t wpas_dbus_getter_bss_frequency(
3692 const struct wpa_dbus_property_desc *property_desc,
3693 DBusMessageIter *iter, DBusError *error, void *user_data)
58605c6e 3694{
6aeeb6fa
DW
3695 struct bss_handler_args *args = user_data;
3696 struct wpa_bss *res;
3d0a8438 3697 u16 freq;
58605c6e 3698
6aeeb6fa
DW
3699 res = get_bss_helper(args, error, __func__);
3700 if (!res)
3701 return FALSE;
8fc2fb56 3702
3d0a8438 3703 freq = (u16) res->freq;
6aeeb6fa 3704 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
3d0a8438 3705 &freq, error);
58605c6e
WS
3706}
3707
3708
75d328af
WS
3709static int cmp_u8s_desc(const void *a, const void *b)
3710{
3711 return (*(u8 *) b - *(u8 *) a);
3712}
3713
3714
58605c6e 3715/**
75d328af 3716 * wpas_dbus_getter_bss_rates - Return available bit rates 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 3721 *
75d328af 3722 * Getter for "Rates" property.
58605c6e 3723 */
1aa0fb77
DW
3724dbus_bool_t wpas_dbus_getter_bss_rates(
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;
75d328af
WS
3730 u8 *ie_rates = NULL;
3731 u32 *real_rates;
3732 int rates_num, i;
6aeeb6fa 3733 dbus_bool_t success = FALSE;
58605c6e 3734
6aeeb6fa
DW
3735 res = get_bss_helper(args, error, __func__);
3736 if (!res)
3737 return FALSE;
8fc2fb56 3738
75d328af
WS
3739 rates_num = wpa_bss_get_bit_rates(res, &ie_rates);
3740 if (rates_num < 0)
6aeeb6fa 3741 return FALSE;
75d328af
WS
3742
3743 qsort(ie_rates, rates_num, 1, cmp_u8s_desc);
3744
3745 real_rates = os_malloc(sizeof(u32) * rates_num);
3746 if (!real_rates) {
3747 os_free(ie_rates);
6aeeb6fa
DW
3748 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3749 return FALSE;
75d328af
WS
3750 }
3751
3752 for (i = 0; i < rates_num; i++)
3753 real_rates[i] = ie_rates[i] * 500000;
3754
6aeeb6fa
DW
3755 success = wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_UINT32,
3756 real_rates, rates_num,
3757 error);
75d328af
WS
3758
3759 os_free(ie_rates);
3760 os_free(real_rates);
6aeeb6fa 3761 return success;
58605c6e
WS
3762}
3763
3764
1aa0fb77
DW
3765static dbus_bool_t wpas_dbus_get_bss_security_prop(
3766 const struct wpa_dbus_property_desc *property_desc,
3767 DBusMessageIter *iter, struct wpa_ie_data *ie_data, DBusError *error)
7899e2f4 3768{
6aeeb6fa 3769 DBusMessageIter iter_dict, variant_iter;
7899e2f4 3770 const char *group;
30675c34 3771 const char *pairwise[5]; /* max 5 pairwise ciphers is supported */
5e3b5197 3772 const char *key_mgmt[9]; /* max 9 key managements may be supported */
7899e2f4
WS
3773 int n;
3774
6aeeb6fa 3775 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
7899e2f4
WS
3776 "a{sv}", &variant_iter))
3777 goto nomem;
3778
3779 if (!wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
3780 goto nomem;
3781
3782 /* KeyMgmt */
3783 n = 0;
3784 if (ie_data->key_mgmt & WPA_KEY_MGMT_PSK)
3785 key_mgmt[n++] = "wpa-psk";
3786 if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_PSK)
3787 key_mgmt[n++] = "wpa-ft-psk";
3788 if (ie_data->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
3789 key_mgmt[n++] = "wpa-psk-sha256";
3790 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X)
3791 key_mgmt[n++] = "wpa-eap";
3792 if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X)
3793 key_mgmt[n++] = "wpa-ft-eap";
3794 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256)
3795 key_mgmt[n++] = "wpa-eap-sha256";
5e3b5197 3796#ifdef CONFIG_SUITEB
666497c8
JM
3797 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B)
3798 key_mgmt[n++] = "wpa-eap-suite-b";
5e3b5197
JM
3799#endif /* CONFIG_SUITEB */
3800#ifdef CONFIG_SUITEB192
3801 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
3802 key_mgmt[n++] = "wpa-eap-suite-b-192";
3803#endif /* CONFIG_SUITEB192 */
7899e2f4
WS
3804 if (ie_data->key_mgmt & WPA_KEY_MGMT_NONE)
3805 key_mgmt[n++] = "wpa-none";
3806
3807 if (!wpa_dbus_dict_append_string_array(&iter_dict, "KeyMgmt",
3808 key_mgmt, n))
3809 goto nomem;
3810
3811 /* Group */
3812 switch (ie_data->group_cipher) {
3813 case WPA_CIPHER_WEP40:
3814 group = "wep40";
3815 break;
3816 case WPA_CIPHER_TKIP:
3817 group = "tkip";
3818 break;
3819 case WPA_CIPHER_CCMP:
3820 group = "ccmp";
3821 break;
eb7719ff
JM
3822 case WPA_CIPHER_GCMP:
3823 group = "gcmp";
3824 break;
7899e2f4
WS
3825 case WPA_CIPHER_WEP104:
3826 group = "wep104";
3827 break;
30675c34
JM
3828 case WPA_CIPHER_CCMP_256:
3829 group = "ccmp-256";
3830 break;
3831 case WPA_CIPHER_GCMP_256:
3832 group = "gcmp-256";
3833 break;
7899e2f4
WS
3834 default:
3835 group = "";
3836 break;
3837 }
3838
3839 if (!wpa_dbus_dict_append_string(&iter_dict, "Group", group))
3840 goto nomem;
3841
3842 /* Pairwise */
3843 n = 0;
3844 if (ie_data->pairwise_cipher & WPA_CIPHER_TKIP)
3845 pairwise[n++] = "tkip";
3846 if (ie_data->pairwise_cipher & WPA_CIPHER_CCMP)
3847 pairwise[n++] = "ccmp";
eb7719ff
JM
3848 if (ie_data->pairwise_cipher & WPA_CIPHER_GCMP)
3849 pairwise[n++] = "gcmp";
30675c34
JM
3850 if (ie_data->pairwise_cipher & WPA_CIPHER_CCMP_256)
3851 pairwise[n++] = "ccmp-256";
3852 if (ie_data->pairwise_cipher & WPA_CIPHER_GCMP_256)
3853 pairwise[n++] = "gcmp-256";
7899e2f4
WS
3854
3855 if (!wpa_dbus_dict_append_string_array(&iter_dict, "Pairwise",
3856 pairwise, n))
3857 goto nomem;
3858
3859 /* Management group (RSN only) */
3860 if (ie_data->proto == WPA_PROTO_RSN) {
3861 switch (ie_data->mgmt_group_cipher) {
3862#ifdef CONFIG_IEEE80211W
3863 case WPA_CIPHER_AES_128_CMAC:
3864 group = "aes128cmac";
3865 break;
3866#endif /* CONFIG_IEEE80211W */
3867 default:
3868 group = "";
3869 break;
3870 }
3871
3872 if (!wpa_dbus_dict_append_string(&iter_dict, "MgmtGroup",
3873 group))
3874 goto nomem;
3875 }
3876
e3c4f0b5
JM
3877 if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict) ||
3878 !dbus_message_iter_close_container(iter, &variant_iter))
7899e2f4
WS
3879 goto nomem;
3880
6aeeb6fa 3881 return TRUE;
7899e2f4
WS
3882
3883nomem:
6aeeb6fa
DW
3884 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3885 return FALSE;
7899e2f4
WS
3886}
3887
3888
58605c6e 3889/**
7899e2f4 3890 * wpas_dbus_getter_bss_wpa - Return the WPA options of a BSS
6aeeb6fa
DW
3891 * @iter: Pointer to incoming dbus message iter
3892 * @error: Location to store error on failure
3893 * @user_data: Function specific data
3894 * Returns: TRUE on success, FALSE on failure
58605c6e 3895 *
7899e2f4 3896 * Getter for "WPA" property.
58605c6e 3897 */
1aa0fb77
DW
3898dbus_bool_t wpas_dbus_getter_bss_wpa(
3899 const struct wpa_dbus_property_desc *property_desc,
3900 DBusMessageIter *iter, DBusError *error, void *user_data)
58605c6e 3901{
6aeeb6fa
DW
3902 struct bss_handler_args *args = user_data;
3903 struct wpa_bss *res;
7899e2f4 3904 struct wpa_ie_data wpa_data;
58605c6e
WS
3905 const u8 *ie;
3906
6aeeb6fa
DW
3907 res = get_bss_helper(args, error, __func__);
3908 if (!res)
3909 return FALSE;
8fc2fb56 3910
7899e2f4 3911 os_memset(&wpa_data, 0, sizeof(wpa_data));
58605c6e 3912 ie = wpa_bss_get_vendor_ie(res, WPA_IE_VENDOR_TYPE);
e3c4f0b5
JM
3913 if (ie && wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0) {
3914 dbus_set_error_const(error, DBUS_ERROR_FAILED,
3915 "failed to parse WPA IE");
3916 return FALSE;
af3e1b0e 3917 }
7899e2f4 3918
1aa0fb77 3919 return wpas_dbus_get_bss_security_prop(property_desc, iter, &wpa_data, error);
58605c6e 3920}
8fc2fb56 3921
8fc2fb56 3922
58605c6e 3923/**
7899e2f4 3924 * wpas_dbus_getter_bss_rsn - Return the RSN options of a BSS
6aeeb6fa
DW
3925 * @iter: Pointer to incoming dbus message iter
3926 * @error: Location to store error on failure
3927 * @user_data: Function specific data
3928 * Returns: TRUE on success, FALSE on failure
58605c6e 3929 *
7899e2f4 3930 * Getter for "RSN" property.
58605c6e 3931 */
1aa0fb77
DW
3932dbus_bool_t wpas_dbus_getter_bss_rsn(
3933 const struct wpa_dbus_property_desc *property_desc,
3934 DBusMessageIter *iter, DBusError *error, void *user_data)
58605c6e 3935{
6aeeb6fa
DW
3936 struct bss_handler_args *args = user_data;
3937 struct wpa_bss *res;
7899e2f4 3938 struct wpa_ie_data wpa_data;
58605c6e
WS
3939 const u8 *ie;
3940
6aeeb6fa
DW
3941 res = get_bss_helper(args, error, __func__);
3942 if (!res)
3943 return FALSE;
58605c6e 3944
7899e2f4 3945 os_memset(&wpa_data, 0, sizeof(wpa_data));
58605c6e 3946 ie = wpa_bss_get_ie(res, WLAN_EID_RSN);
e3c4f0b5
JM
3947 if (ie && wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0) {
3948 dbus_set_error_const(error, DBUS_ERROR_FAILED,
3949 "failed to parse RSN IE");
3950 return FALSE;
af3e1b0e 3951 }
7899e2f4 3952
1aa0fb77 3953 return wpas_dbus_get_bss_security_prop(property_desc, iter, &wpa_data, error);
58605c6e
WS
3954}
3955
3956
caff3992
SN
3957/**
3958 * wpas_dbus_getter_bss_wps - Return the WPS options of a BSS
3959 * @iter: Pointer to incoming dbus message iter
3960 * @error: Location to store error on failure
3961 * @user_data: Function specific data
3962 * Returns: TRUE on success, FALSE on failure
3963 *
3964 * Getter for "WPS" property.
3965 */
1aa0fb77
DW
3966dbus_bool_t wpas_dbus_getter_bss_wps(
3967 const struct wpa_dbus_property_desc *property_desc,
3968 DBusMessageIter *iter, DBusError *error, void *user_data)
caff3992
SN
3969{
3970 struct bss_handler_args *args = user_data;
3971 struct wpa_bss *res;
3972#ifdef CONFIG_WPS
3973 struct wpabuf *wps_ie;
3974#endif /* CONFIG_WPS */
3975 DBusMessageIter iter_dict, variant_iter;
8e2c5f1a 3976 int wps_support = 0;
caff3992
SN
3977 const char *type = "";
3978
3979 res = get_bss_helper(args, error, __func__);
3980 if (!res)
3981 return FALSE;
3982
3983 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
e3c4f0b5
JM
3984 "a{sv}", &variant_iter) ||
3985 !wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
caff3992
SN
3986 goto nomem;
3987
3988#ifdef CONFIG_WPS
3989 wps_ie = wpa_bss_get_vendor_ie_multi(res, WPS_IE_VENDOR_TYPE);
3990 if (wps_ie) {
8e2c5f1a 3991 wps_support = 1;
caff3992
SN
3992 if (wps_is_selected_pbc_registrar(wps_ie))
3993 type = "pbc";
3994 else if (wps_is_selected_pin_registrar(wps_ie))
3995 type = "pin";
c66f2349
SM
3996
3997 wpabuf_free(wps_ie);
caff3992
SN
3998 }
3999#endif /* CONFIG_WPS */
4000
8e2c5f1a 4001 if ((wps_support && !wpa_dbus_dict_append_string(&iter_dict, "Type", type)) ||
e3c4f0b5
JM
4002 !wpa_dbus_dict_close_write(&variant_iter, &iter_dict) ||
4003 !dbus_message_iter_close_container(iter, &variant_iter))
caff3992
SN
4004 goto nomem;
4005
4006 return TRUE;
4007
4008nomem:
4009 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
4010 return FALSE;
4011}
4012
4013
58605c6e 4014/**
7899e2f4 4015 * wpas_dbus_getter_bss_ies - Return all IEs of a BSS
6aeeb6fa
DW
4016 * @iter: Pointer to incoming dbus message iter
4017 * @error: Location to store error on failure
4018 * @user_data: Function specific data
4019 * Returns: TRUE on success, FALSE on failure
58605c6e 4020 *
7899e2f4 4021 * Getter for "IEs" property.
58605c6e 4022 */
1aa0fb77
DW
4023dbus_bool_t wpas_dbus_getter_bss_ies(
4024 const struct wpa_dbus_property_desc *property_desc,
4025 DBusMessageIter *iter, DBusError *error, void *user_data)
58605c6e 4026{
6aeeb6fa
DW
4027 struct bss_handler_args *args = user_data;
4028 struct wpa_bss *res;
58605c6e 4029
6aeeb6fa
DW
4030 res = get_bss_helper(args, error, __func__);
4031 if (!res)
4032 return FALSE;
58605c6e 4033
6aeeb6fa
DW
4034 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
4035 res + 1, res->ie_len,
4036 error);
8fc2fb56
WS
4037}
4038
4039
3bd3257a
DW
4040/**
4041 * wpas_dbus_getter_bss_age - Return time in seconds since BSS was last seen
4042 * @iter: Pointer to incoming dbus message iter
4043 * @error: Location to store error on failure
4044 * @user_data: Function specific data
4045 * Returns: TRUE on success, FALSE on failure
4046 *
4047 * Getter for BSS age
4048 */
1aa0fb77
DW
4049dbus_bool_t wpas_dbus_getter_bss_age(
4050 const struct wpa_dbus_property_desc *property_desc,
4051 DBusMessageIter *iter, DBusError *error, void *user_data)
3bd3257a
DW
4052{
4053 struct bss_handler_args *args = user_data;
4054 struct wpa_bss *res;
4055 struct os_reltime now, diff = { 0, 0 };
4056 u32 age;
4057
4058 res = get_bss_helper(args, error, __func__);
4059 if (!res)
4060 return FALSE;
4061
4062 os_get_reltime(&now);
4063 os_reltime_sub(&now, &res->last_update, &diff);
4064 age = diff.sec > 0 ? diff.sec : 0;
4065 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32, &age,
4066 error);
4067}
4068
4069
8fc2fb56
WS
4070/**
4071 * wpas_dbus_getter_enabled - Check whether network is enabled or disabled
6aeeb6fa
DW
4072 * @iter: Pointer to incoming dbus message iter
4073 * @error: Location to store error on failure
4074 * @user_data: Function specific data
4075 * Returns: TRUE on success, FALSE on failure
8fc2fb56
WS
4076 *
4077 * Getter for "enabled" property of a configured network.
4078 */
1aa0fb77
DW
4079dbus_bool_t wpas_dbus_getter_enabled(
4080 const struct wpa_dbus_property_desc *property_desc,
4081 DBusMessageIter *iter, DBusError *error, void *user_data)
8fc2fb56 4082{
6aeeb6fa 4083 struct network_handler_args *net = user_data;
8fc2fb56 4084 dbus_bool_t enabled = net->ssid->disabled ? FALSE : TRUE;
6aeeb6fa
DW
4085
4086 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
4087 &enabled, error);
8fc2fb56
WS
4088}
4089
4090
4091/**
4092 * wpas_dbus_setter_enabled - Mark a configured network as enabled or disabled
6aeeb6fa
DW
4093 * @iter: Pointer to incoming dbus message iter
4094 * @error: Location to store error on failure
4095 * @user_data: Function specific data
4096 * Returns: TRUE on success, FALSE on failure
8fc2fb56
WS
4097 *
4098 * Setter for "Enabled" property of a configured network.
4099 */
1aa0fb77
DW
4100dbus_bool_t wpas_dbus_setter_enabled(
4101 const struct wpa_dbus_property_desc *property_desc,
4102 DBusMessageIter *iter, DBusError *error, void *user_data)
8fc2fb56 4103{
6aeeb6fa 4104 struct network_handler_args *net = user_data;
8fc2fb56
WS
4105 struct wpa_supplicant *wpa_s;
4106 struct wpa_ssid *ssid;
8fc2fb56
WS
4107 dbus_bool_t enable;
4108
6aeeb6fa
DW
4109 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
4110 &enable))
4111 return FALSE;
8fc2fb56
WS
4112
4113 wpa_s = net->wpa_s;
4114 ssid = net->ssid;
4115
5228401c 4116 if (enable)
8fc2fb56 4117 wpa_supplicant_enable_network(wpa_s, ssid);
5228401c 4118 else
8fc2fb56 4119 wpa_supplicant_disable_network(wpa_s, ssid);
8fc2fb56 4120
6aeeb6fa 4121 return TRUE;
8fc2fb56
WS
4122}
4123
4124
4125/**
4126 * wpas_dbus_getter_network_properties - Get options for a configured network
6aeeb6fa
DW
4127 * @iter: Pointer to incoming dbus message iter
4128 * @error: Location to store error on failure
4129 * @user_data: Function specific data
4130 * Returns: TRUE on success, FALSE on failure
8fc2fb56
WS
4131 *
4132 * Getter for "Properties" property of a configured network.
4133 */
1aa0fb77
DW
4134dbus_bool_t wpas_dbus_getter_network_properties(
4135 const struct wpa_dbus_property_desc *property_desc,
4136 DBusMessageIter *iter, DBusError *error, void *user_data)
8fc2fb56 4137{
6aeeb6fa
DW
4138 struct network_handler_args *net = user_data;
4139 DBusMessageIter variant_iter, dict_iter;
8fc2fb56 4140 char **iterator;
d1c8ac88 4141 char **props = wpa_config_get_all(net->ssid, 1);
6aeeb6fa 4142 dbus_bool_t success = FALSE;
8fc2fb56 4143
6aeeb6fa
DW
4144 if (!props) {
4145 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
4146 return FALSE;
8fc2fb56
WS
4147 }
4148
6aeeb6fa
DW
4149 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a{sv}",
4150 &variant_iter) ||
c2b8c674 4151 !wpa_dbus_dict_open_write(&variant_iter, &dict_iter)) {
6aeeb6fa 4152 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
8fc2fb56
WS
4153 goto out;
4154 }
4155
4156 iterator = props;
4157 while (*iterator) {
4158 if (!wpa_dbus_dict_append_string(&dict_iter, *iterator,
5228401c 4159 *(iterator + 1))) {
6aeeb6fa
DW
4160 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
4161 "no memory");
8fc2fb56
WS
4162 goto out;
4163 }
4164 iterator += 2;
4165 }
4166
4167
c2b8c674 4168 if (!wpa_dbus_dict_close_write(&variant_iter, &dict_iter) ||
6aeeb6fa
DW
4169 !dbus_message_iter_close_container(iter, &variant_iter)) {
4170 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
8fc2fb56
WS
4171 goto out;
4172 }
4173
6aeeb6fa
DW
4174 success = TRUE;
4175
8fc2fb56
WS
4176out:
4177 iterator = props;
4178 while (*iterator) {
4179 os_free(*iterator);
4180 iterator++;
4181 }
4182 os_free(props);
6aeeb6fa 4183 return success;
8fc2fb56
WS
4184}
4185
4186
4187/**
4188 * wpas_dbus_setter_network_properties - Set options for a configured network
6aeeb6fa
DW
4189 * @iter: Pointer to incoming dbus message iter
4190 * @error: Location to store error on failure
4191 * @user_data: Function specific data
4192 * Returns: TRUE on success, FALSE on failure
8fc2fb56
WS
4193 *
4194 * Setter for "Properties" property of a configured network.
4195 */
1aa0fb77
DW
4196dbus_bool_t wpas_dbus_setter_network_properties(
4197 const struct wpa_dbus_property_desc *property_desc,
4198 DBusMessageIter *iter, DBusError *error, void *user_data)
8fc2fb56 4199{
6aeeb6fa 4200 struct network_handler_args *net = user_data;
8fc2fb56 4201 struct wpa_ssid *ssid = net->ssid;
6aeeb6fa 4202 DBusMessageIter variant_iter;
8fc2fb56 4203
6aeeb6fa
DW
4204 dbus_message_iter_recurse(iter, &variant_iter);
4205 return set_network_properties(net->wpa_s, ssid, &variant_iter, error);
8fc2fb56 4206}
2d43d37f
JB
4207
4208
4209#ifdef CONFIG_AP
4210
4211DBusMessage * wpas_dbus_handler_subscribe_preq(
4212 DBusMessage *message, struct wpa_supplicant *wpa_s)
4213{
4214 struct wpas_dbus_priv *priv = wpa_s->global->dbus;
4215 char *name;
4216
4217 if (wpa_s->preq_notify_peer != NULL) {
4218 if (os_strcmp(dbus_message_get_sender(message),
4219 wpa_s->preq_notify_peer) == 0)
4220 return NULL;
4221
4222 return dbus_message_new_error(message,
4223 WPAS_DBUS_ERROR_SUBSCRIPTION_IN_USE,
4224 "Another application is already subscribed");
4225 }
4226
4227 name = os_strdup(dbus_message_get_sender(message));
4228 if (!name)
a0caebf3 4229 return wpas_dbus_error_no_memory(message);
2d43d37f
JB
4230
4231 wpa_s->preq_notify_peer = name;
4232
4233 /* Subscribe to clean up if application closes socket */
4234 wpas_dbus_subscribe_noc(priv);
4235
4236 /*
4237 * Double-check it's still alive to make sure that we didn't
4238 * miss the NameOwnerChanged signal, e.g. while strdup'ing.
4239 */
4240 if (!dbus_bus_name_has_owner(priv->con, name, NULL)) {
4241 /*
4242 * Application no longer exists, clean up.
4243 * The return value is irrelevant now.
4244 *
4245 * Need to check if the NameOwnerChanged handling
4246 * already cleaned up because we have processed
4247 * DBus messages while checking if the name still
4248 * has an owner.
4249 */
4250 if (!wpa_s->preq_notify_peer)
4251 return NULL;
4252 os_free(wpa_s->preq_notify_peer);
4253 wpa_s->preq_notify_peer = NULL;
4254 wpas_dbus_unsubscribe_noc(priv);
4255 }
4256
4257 return NULL;
4258}
4259
4260
4261DBusMessage * wpas_dbus_handler_unsubscribe_preq(
4262 DBusMessage *message, struct wpa_supplicant *wpa_s)
4263{
4264 struct wpas_dbus_priv *priv = wpa_s->global->dbus;
4265
4266 if (!wpa_s->preq_notify_peer)
4267 return dbus_message_new_error(message,
4268 WPAS_DBUS_ERROR_NO_SUBSCRIPTION,
4269 "Not subscribed");
4270
4271 if (os_strcmp(wpa_s->preq_notify_peer,
4272 dbus_message_get_sender(message)))
4273 return dbus_message_new_error(message,
4274 WPAS_DBUS_ERROR_SUBSCRIPTION_EPERM,
4275 "Can't unsubscribe others");
4276
4277 os_free(wpa_s->preq_notify_peer);
4278 wpa_s->preq_notify_peer = NULL;
4279 wpas_dbus_unsubscribe_noc(priv);
4280 return NULL;
4281}
4282
4283
4284void wpas_dbus_signal_preq(struct wpa_supplicant *wpa_s,
4285 const u8 *addr, const u8 *dst, const u8 *bssid,
4286 const u8 *ie, size_t ie_len, u32 ssi_signal)
4287{
4288 DBusMessage *msg;
4289 DBusMessageIter iter, dict_iter;
4290 struct wpas_dbus_priv *priv = wpa_s->global->dbus;
4291
4292 /* Do nothing if the control interface is not turned on */
8a78e227 4293 if (priv == NULL || !wpa_s->dbus_new_path)
2d43d37f
JB
4294 return;
4295
4296 if (wpa_s->preq_notify_peer == NULL)
4297 return;
4298
4299 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
4300 WPAS_DBUS_NEW_IFACE_INTERFACE,
4301 "ProbeRequest");
4302 if (msg == NULL)
4303 return;
4304
4305 dbus_message_set_destination(msg, wpa_s->preq_notify_peer);
4306
4307 dbus_message_iter_init_append(msg, &iter);
4308
e3c4f0b5
JM
4309 if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
4310 (addr && !wpa_dbus_dict_append_byte_array(&dict_iter, "addr",
4311 (const char *) addr,
4312 ETH_ALEN)) ||
4313 (dst && !wpa_dbus_dict_append_byte_array(&dict_iter, "dst",
4314 (const char *) dst,
4315 ETH_ALEN)) ||
4316 (bssid && !wpa_dbus_dict_append_byte_array(&dict_iter, "bssid",
4317 (const char *) bssid,
4318 ETH_ALEN)) ||
4319 (ie && ie_len && !wpa_dbus_dict_append_byte_array(&dict_iter, "ies",
4320 (const char *) ie,
4321 ie_len)) ||
4322 (ssi_signal && !wpa_dbus_dict_append_int32(&dict_iter, "signal",
4323 ssi_signal)) ||
4324 !wpa_dbus_dict_close_write(&iter, &dict_iter))
2d43d37f
JB
4325 goto fail;
4326
4327 dbus_connection_send(priv->con, msg, NULL);
4328 goto out;
4329fail:
4330 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
4331out:
4332 dbus_message_unref(msg);
4333}
4334
4335#endif /* CONFIG_AP */