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