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