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>
7 * This software may be distributed under the terms of the BSD license.
8 * See README for more details.
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"
27 #include "../autoscan.h"
29 #include "dbus_new_helpers.h"
31 #include "dbus_new_handlers.h"
32 #include "dbus_dict_helpers.h"
33 #include "dbus_common_i.h"
34 #include "drivers/driver.h"
36 #include "ap/hostapd.h"
37 #include "ap/sta_info.h"
38 #endif /* CONFIG_MESH */
40 static const char * const debug_strings[] = {
41 "excessive", "msgdump", "debug", "info", "warning", "error", NULL
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
51 * Convenience function to create and return an UnknownError
53 DBusMessage * wpas_dbus_error_unknown_error(DBusMessage *message,
56 return dbus_message_new_error(message, WPAS_DBUS_ERROR_UNKNOWN_ERROR,
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
66 * Convenience function to create and return an invalid interface error
68 static DBusMessage * wpas_dbus_error_iface_unknown(DBusMessage *message)
70 return dbus_message_new_error(
71 message, WPAS_DBUS_ERROR_IFACE_UNKNOWN,
72 "wpa_supplicant knows nothing about this interface.");
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
81 * Convenience function to create and return an invalid network error
83 static DBusMessage * wpas_dbus_error_network_unknown(DBusMessage *message)
85 return dbus_message_new_error(
86 message, WPAS_DBUS_ERROR_NETWORK_UNKNOWN,
87 "There is no such a network in this interface.");
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
96 * Convenience function to create and return an invalid options error
98 DBusMessage * wpas_dbus_error_invalid_args(DBusMessage *message,
103 reply = dbus_message_new_error(
104 message, WPAS_DBUS_ERROR_INVALID_ARGS,
105 "Did not receive correct message arguments.");
107 dbus_message_append_args(reply, DBUS_TYPE_STRING, &arg,
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
120 * Convenience function to create and return a scan error
122 static DBusMessage * wpas_dbus_error_scan_error(DBusMessage *message,
125 return dbus_message_new_error(message,
126 WPAS_DBUS_ERROR_IFACE_SCAN_ERROR,
131 DBusMessage * wpas_dbus_error_no_memory(DBusMessage *message)
133 wpa_printf(MSG_DEBUG, "dbus: Failed to allocate memory");
134 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, NULL);
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
144 static dbus_bool_t should_quote_opt(const char *key)
148 while (dont_quote[i] != NULL) {
149 if (os_strcmp(key, dont_quote[i]) == 0)
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
162 static struct wpa_supplicant * get_iface_by_dbus_path(
163 struct wpa_global *global, const char *path)
165 struct wpa_supplicant *wpa_s;
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)
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
182 * @error: On failure, an error describing the failure
183 * Returns: TRUE if the request succeeds, FALSE if it failed
185 * Sets network configuration with parameters given id DBus dictionary
187 dbus_bool_t set_network_properties(struct wpa_supplicant *wpa_s,
188 struct wpa_ssid *ssid,
189 DBusMessageIter *iter,
192 struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
193 DBusMessageIter iter_dict;
196 if (!wpa_dbus_dict_open_read(iter, &iter_dict, error))
199 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
203 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
207 if (entry.type == DBUS_TYPE_ARRAY &&
208 entry.array_type == DBUS_TYPE_BYTE) {
209 if (entry.array_len <= 0)
212 size = entry.array_len * 2 + 1;
213 value = os_zalloc(size);
217 ret = wpa_snprintf_hex(value, size,
218 (u8 *) entry.bytearray_value,
222 } else if (entry.type == DBUS_TYPE_STRING) {
223 if (should_quote_opt(entry.key)) {
224 size = os_strlen(entry.str_value);
229 value = os_zalloc(size);
233 ret = os_snprintf(value, size, "\"%s\"",
235 if (os_snprintf_error(size, ret))
238 value = os_strdup(entry.str_value);
242 } else if (entry.type == DBUS_TYPE_UINT32) {
243 value = os_zalloc(size);
247 ret = os_snprintf(value, size, "%u",
249 if (os_snprintf_error(size, ret))
251 } else if (entry.type == DBUS_TYPE_INT32) {
252 value = os_zalloc(size);
256 ret = os_snprintf(value, size, "%d",
258 if (os_snprintf_error(size, ret))
263 if (wpa_config_set(ssid, entry.key, value, 0) < 0)
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);
270 if (wpa_s->current_ssid == ssid ||
271 wpa_s->current_ssid == NULL) {
273 * Invalidate the EAP session cache if anything in the
274 * current or previously used configuration changes.
276 eapol_sm_invalidate_cached_session(wpa_s->eapol);
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);
288 wpa_dbus_dict_entry_clear(&entry);
295 wpa_dbus_dict_entry_clear(&entry);
296 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
297 "invalid message format");
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
310 * Generic getter for basic type properties. Type is required to be basic.
312 dbus_bool_t wpas_dbus_simple_property_getter(DBusMessageIter *iter,
317 DBusMessageIter variant_iter;
319 if (!dbus_type_is_basic(type)) {
320 dbus_set_error(error, DBUS_ERROR_FAILED,
321 "%s: given type is not basic", __func__);
325 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
326 wpa_dbus_type_as_string(type),
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__);
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
346 * Generic setter for basic type properties. Type is required to be basic.
348 dbus_bool_t wpas_dbus_simple_property_setter(DBusMessageIter *iter,
350 const int type, void *val)
352 DBusMessageIter variant_iter;
354 if (!dbus_type_is_basic(type)) {
355 dbus_set_error(error, DBUS_ERROR_FAILED,
356 "%s: given type is not basic", __func__);
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");
367 dbus_message_iter_get_basic(&variant_iter, val);
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
382 * Generic getter for array type properties. Array elements type is
383 * required to be basic.
385 dbus_bool_t wpas_dbus_simple_array_property_getter(DBusMessageIter *iter,
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;
396 if (!dbus_type_is_basic(type)) {
397 dbus_set_error(error, DBUS_ERROR_FAILED,
398 "%s: given type is not basic", __func__);
402 sub_type_str = wpa_dbus_type_as_string(type);
403 type_str[1] = sub_type_str[0];
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__);
416 case DBUS_TYPE_BOOLEAN:
419 case DBUS_TYPE_INT16:
420 case DBUS_TYPE_UINT16:
421 element_size = sizeof(uint16_t);
423 case DBUS_TYPE_INT32:
424 case DBUS_TYPE_UINT32:
425 element_size = sizeof(uint32_t);
427 case DBUS_TYPE_INT64:
428 case DBUS_TYPE_UINT64:
429 element_size = sizeof(uint64_t);
431 case DBUS_TYPE_DOUBLE:
432 element_size = sizeof(double);
434 case DBUS_TYPE_STRING:
435 case DBUS_TYPE_OBJECT_PATH:
436 element_size = sizeof(char *);
439 dbus_set_error(error, DBUS_ERROR_FAILED,
440 "%s: unknown element type %d", __func__, type);
444 for (i = 0; i < array_len; i++) {
445 if (!dbus_message_iter_append_basic(&array_iter, type,
446 (const char *) array +
448 dbus_set_error(error, DBUS_ERROR_FAILED,
449 "%s: failed to construct message 2.5",
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__);
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
475 * Generic getter for array type properties. Array elements type is
476 * required to be basic.
478 dbus_bool_t wpas_dbus_simple_array_array_property_getter(DBusMessageIter *iter,
480 struct wpabuf **array,
484 DBusMessageIter variant_iter, array_iter;
485 char type_str[] = "aa?";
486 char inner_type_str[] = "a?";
487 const char *sub_type_str;
490 if (!dbus_type_is_basic(type)) {
491 dbus_set_error(error, DBUS_ERROR_FAILED,
492 "%s: given type is not basic", __func__);
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];
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__);
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]));
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__);
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
534 * Generic getter for string type properties. %NULL is converted to an empty
537 dbus_bool_t wpas_dbus_string_property_getter(DBusMessageIter *iter,
543 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
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
555 * Handler function for "CreateInterface" method call. Handles requests
556 * by dbus clients to register a network interface that wpa_supplicant
559 DBusMessage * wpas_dbus_handler_create_interface(DBusMessage *message,
560 struct wpa_global *global)
562 DBusMessageIter iter_dict;
563 DBusMessage *reply = NULL;
564 DBusMessageIter iter;
565 struct wpa_dbus_dict_entry entry;
568 char *confname = NULL;
569 char *bridge_ifname = NULL;
571 dbus_message_iter_init(message, &iter);
573 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
575 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
576 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
578 if (os_strcmp(entry.key, "Driver") == 0 &&
579 entry.type == DBUS_TYPE_STRING) {
581 driver = os_strdup(entry.str_value);
582 wpa_dbus_dict_entry_clear(&entry);
585 } else if (os_strcmp(entry.key, "Ifname") == 0 &&
586 entry.type == DBUS_TYPE_STRING) {
588 ifname = os_strdup(entry.str_value);
589 wpa_dbus_dict_entry_clear(&entry);
592 } else if (os_strcmp(entry.key, "ConfigFile") == 0 &&
593 entry.type == DBUS_TYPE_STRING) {
595 confname = os_strdup(entry.str_value);
596 wpa_dbus_dict_entry_clear(&entry);
597 if (confname == NULL)
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)
607 wpa_dbus_dict_entry_clear(&entry);
613 goto error; /* Required Ifname argument missing */
616 * Try to get the wpa_supplicant record for this iface, return
617 * an error if we already control it.
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.");
624 struct wpa_supplicant *wpa_s;
625 struct wpa_interface iface;
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;
637 reply = dbus_message_new_method_return(message);
638 dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH,
639 &path, DBUS_TYPE_INVALID);
641 reply = wpas_dbus_error_unknown_error(
643 "wpa_supplicant couldn't grab this interface.");
651 os_free(bridge_ifname);
655 reply = wpas_dbus_error_invalid_args(message, NULL);
658 reply = wpas_dbus_error_no_memory(message);
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
670 * Handler function for "removeInterface" method call. Handles requests
671 * by dbus clients to deregister a network interface that wpa_supplicant
674 DBusMessage * wpas_dbus_handler_remove_interface(DBusMessage *message,
675 struct wpa_global *global)
677 struct wpa_supplicant *wpa_s;
679 DBusMessage *reply = NULL;
681 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path,
684 wpa_s = get_iface_by_dbus_path(global, path);
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(
690 "wpa_supplicant couldn't remove this interface.");
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
704 * Handler function for "getInterface" method call.
706 DBusMessage * wpas_dbus_handler_get_interface(DBusMessage *message,
707 struct wpa_global *global)
709 DBusMessage *reply = NULL;
712 struct wpa_supplicant *wpa_s;
714 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &ifname,
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);
721 path = wpa_s->dbus_new_path;
722 reply = dbus_message_new_method_return(message);
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);
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
742 * Getter for "DebugLevel" property.
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)
749 int idx = wpa_debug_level;
755 str = debug_strings[idx];
756 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
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
768 * Getter for "DebugTimestamp" property.
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)
774 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
775 &wpa_debug_timestamp, error);
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
787 * Getter for "DebugShowKeys" property.
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)
793 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
794 &wpa_debug_show_keys, error);
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
805 * Setter for "DebugLevel" property.
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)
811 struct wpa_global *global = user_data;
812 const char *str = NULL;
815 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
819 for (i = 0; debug_strings[i]; i++)
820 if (os_strcmp(debug_strings[i], str) == 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");
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
844 * Setter for "DebugTimestamp" property.
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)
850 struct wpa_global *global = user_data;
853 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
857 wpa_supplicant_set_debug_params(global, wpa_debug_level, val ? 1 : 0,
858 wpa_debug_show_keys);
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
870 * Setter for "DebugShowKeys" property.
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)
876 struct wpa_global *global = user_data;
879 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
883 wpa_supplicant_set_debug_params(global, wpa_debug_level,
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
897 * Getter for "Interfaces" property. Handles requests
898 * by dbus clients to return list of registered interfaces objects
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)
905 struct wpa_global *global = user_data;
906 struct wpa_supplicant *wpa_s;
908 unsigned int i = 0, num = 0;
911 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
912 if (wpa_s->dbus_new_path)
916 paths = os_calloc(num, sizeof(char *));
918 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
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;
927 success = wpas_dbus_simple_array_property_getter(iter,
928 DBUS_TYPE_OBJECT_PATH,
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
943 * Getter for "EapMethods" property. Handles requests
944 * by dbus clients to return list of strings with supported EAP methods
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)
951 size_t num_items = 0;
954 eap_methods = eap_get_names_as_string_array(&num_items);
956 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
960 success = wpas_dbus_simple_array_property_getter(iter,
966 os_free(eap_methods[--num_items]);
967 os_free(eap_methods);
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
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.
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)
987 const char *capabilities[10] = { NULL, NULL, NULL, NULL, NULL, NULL,
988 NULL, NULL, NULL, NULL };
989 size_t num_items = 0;
991 struct wpa_global *global = user_data;
992 struct wpa_supplicant *wpa_s;
993 int fils_supported = 0, fils_sk_pfs_supported = 0;
995 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
996 if (wpa_is_fils_supported(wpa_s))
998 if (wpa_is_fils_sk_pfs_supported(wpa_s))
999 fils_sk_pfs_supported = 1;
1001 #endif /* CONFIG_FILS */
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 */
1010 capabilities[num_items++] = "p2p";
1011 #endif /* CONFIG_P2P */
1012 #ifdef CONFIG_INTERWORKING
1013 capabilities[num_items++] = "interworking";
1014 #endif /* CONFIG_INTERWORKING */
1015 #ifdef CONFIG_IEEE80211W
1016 capabilities[num_items++] = "pmf";
1017 #endif /* CONFIG_IEEE80211W */
1019 capabilities[num_items++] = "mesh";
1020 #endif /* CONFIG_MESH */
1023 capabilities[num_items++] = "fils";
1024 if (fils_sk_pfs_supported)
1025 capabilities[num_items++] = "fils_sk_pfs";
1026 #endif /* CONFIG_FILS */
1027 #ifdef CONFIG_IEEE80211R
1028 capabilities[num_items++] = "ft";
1029 #endif /* CONFIG_IEEE80211R */
1030 #ifdef CONFIG_SHA384
1031 capabilities[num_items++] = "sha384";
1032 #endif /* CONFIG_SHA384 */
1034 return wpas_dbus_simple_array_property_getter(iter,
1041 static int wpas_dbus_get_scan_type(DBusMessage *message, DBusMessageIter *var,
1042 char **type, DBusMessage **reply)
1044 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_STRING) {
1045 wpa_printf(MSG_DEBUG, "%s[dbus]: Type must be a string",
1047 *reply = wpas_dbus_error_invalid_args(
1048 message, "Wrong Type value type. String required");
1051 dbus_message_iter_get_basic(var, type);
1056 static int wpas_dbus_get_scan_ssids(DBusMessage *message, DBusMessageIter *var,
1057 struct wpa_driver_scan_params *params,
1058 DBusMessage **reply)
1060 struct wpa_driver_scan_ssid *ssids = params->ssids;
1061 size_t ssids_num = 0;
1063 DBusMessageIter array_iter, sub_array_iter;
1067 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
1068 wpa_printf(MSG_DEBUG,
1069 "%s[dbus]: ssids must be an array of arrays of bytes",
1071 *reply = wpas_dbus_error_invalid_args(
1073 "Wrong SSIDs value type. Array of arrays of bytes required");
1077 dbus_message_iter_recurse(var, &array_iter);
1079 if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY ||
1080 dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_BYTE) {
1081 wpa_printf(MSG_DEBUG,
1082 "%s[dbus]: ssids must be an array of arrays of bytes",
1084 *reply = wpas_dbus_error_invalid_args(
1086 "Wrong SSIDs value type. Array of arrays of bytes required");
1090 while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_ARRAY) {
1091 if (ssids_num >= WPAS_MAX_SCAN_SSIDS) {
1092 wpa_printf(MSG_DEBUG,
1093 "%s[dbus]: Too many ssids specified on scan dbus call",
1095 *reply = wpas_dbus_error_invalid_args(
1097 "Too many ssids specified. Specify at most four");
1101 dbus_message_iter_recurse(&array_iter, &sub_array_iter);
1103 dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len);
1105 if (len > SSID_MAX_LEN) {
1106 wpa_printf(MSG_DEBUG,
1107 "%s[dbus]: SSID too long (len=%d max_len=%d)",
1108 __func__, len, SSID_MAX_LEN);
1109 *reply = wpas_dbus_error_invalid_args(
1110 message, "Invalid SSID: too long");
1115 ssid = os_memdup(val, len);
1117 *reply = wpas_dbus_error_no_memory(message);
1121 /* Allow zero-length SSIDs */
1125 ssids[ssids_num].ssid = ssid;
1126 ssids[ssids_num].ssid_len = len;
1128 dbus_message_iter_next(&array_iter);
1132 params->num_ssids = ssids_num;
1137 static int wpas_dbus_get_scan_ies(DBusMessage *message, DBusMessageIter *var,
1138 struct wpa_driver_scan_params *params,
1139 DBusMessage **reply)
1141 u8 *ies = NULL, *nies;
1143 DBusMessageIter array_iter, sub_array_iter;
1147 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
1148 wpa_printf(MSG_DEBUG,
1149 "%s[dbus]: ies must be an array of arrays of bytes",
1151 *reply = wpas_dbus_error_invalid_args(
1153 "Wrong IEs value type. Array of arrays of bytes required");
1157 dbus_message_iter_recurse(var, &array_iter);
1159 if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY ||
1160 dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_BYTE) {
1161 wpa_printf(MSG_DEBUG,
1162 "%s[dbus]: ies must be an array of arrays of bytes",
1164 *reply = wpas_dbus_error_invalid_args(
1165 message, "Wrong IEs value type. Array required");
1169 while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_ARRAY) {
1170 dbus_message_iter_recurse(&array_iter, &sub_array_iter);
1172 dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len);
1174 dbus_message_iter_next(&array_iter);
1178 nies = os_realloc(ies, ies_len + len);
1181 *reply = wpas_dbus_error_no_memory(message);
1185 os_memcpy(ies + ies_len, val, len);
1188 dbus_message_iter_next(&array_iter);
1191 params->extra_ies = ies;
1192 params->extra_ies_len = ies_len;
1197 static int wpas_dbus_get_scan_channels(DBusMessage *message,
1198 DBusMessageIter *var,
1199 struct wpa_driver_scan_params *params,
1200 DBusMessage **reply)
1202 DBusMessageIter array_iter, sub_array_iter;
1203 int *freqs = NULL, *nfreqs;
1206 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
1207 wpa_printf(MSG_DEBUG,
1208 "%s[dbus]: Channels must be an array of structs",
1210 *reply = wpas_dbus_error_invalid_args(
1212 "Wrong Channels value type. Array of structs required");
1216 dbus_message_iter_recurse(var, &array_iter);
1218 if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_STRUCT) {
1219 wpa_printf(MSG_DEBUG,
1220 "%s[dbus]: Channels must be an array of structs",
1222 *reply = wpas_dbus_error_invalid_args(
1224 "Wrong Channels value type. Array of structs required");
1228 while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_STRUCT)
1232 dbus_message_iter_recurse(&array_iter, &sub_array_iter);
1234 if (dbus_message_iter_get_arg_type(&sub_array_iter) !=
1236 wpa_printf(MSG_DEBUG,
1237 "%s[dbus]: Channel must by specified by struct of two UINT32s %c",
1239 dbus_message_iter_get_arg_type(
1241 *reply = wpas_dbus_error_invalid_args(
1243 "Wrong Channel struct. Two UINT32s required");
1247 dbus_message_iter_get_basic(&sub_array_iter, &freq);
1249 if (!dbus_message_iter_next(&sub_array_iter) ||
1250 dbus_message_iter_get_arg_type(&sub_array_iter) !=
1252 wpa_printf(MSG_DEBUG,
1253 "%s[dbus]: Channel must by specified by struct of two UINT32s",
1255 *reply = wpas_dbus_error_invalid_args(
1257 "Wrong Channel struct. Two UINT32s required");
1262 dbus_message_iter_get_basic(&sub_array_iter, &width);
1264 #define FREQS_ALLOC_CHUNK 32
1265 if (freqs_num % FREQS_ALLOC_CHUNK == 0) {
1266 nfreqs = os_realloc_array(
1267 freqs, freqs_num + FREQS_ALLOC_CHUNK,
1273 if (freqs == NULL) {
1274 *reply = wpas_dbus_error_no_memory(message);
1278 freqs[freqs_num] = freq;
1281 dbus_message_iter_next(&array_iter);
1284 nfreqs = os_realloc_array(freqs, freqs_num + 1, sizeof(int));
1288 if (freqs == NULL) {
1289 *reply = wpas_dbus_error_no_memory(message);
1292 freqs[freqs_num] = 0;
1294 params->freqs = freqs;
1299 static int wpas_dbus_get_scan_allow_roam(DBusMessage *message,
1300 DBusMessageIter *var,
1302 DBusMessage **reply)
1304 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_BOOLEAN) {
1305 wpa_printf(MSG_DEBUG, "%s[dbus]: Type must be a boolean",
1307 *reply = wpas_dbus_error_invalid_args(
1308 message, "Wrong Type value type. Boolean required");
1311 dbus_message_iter_get_basic(var, allow);
1317 * wpas_dbus_handler_scan - Request a wireless scan on an interface
1318 * @message: Pointer to incoming dbus message
1319 * @wpa_s: wpa_supplicant structure for a network interface
1320 * Returns: NULL indicating success or DBus error message on failure
1322 * Handler function for "Scan" method call of a network device. Requests
1323 * that wpa_supplicant perform a wireless scan as soon as possible
1324 * on a particular wireless interface.
1326 DBusMessage * wpas_dbus_handler_scan(DBusMessage *message,
1327 struct wpa_supplicant *wpa_s)
1329 DBusMessage *reply = NULL;
1330 DBusMessageIter iter, dict_iter, entry_iter, variant_iter;
1331 char *key = NULL, *type = NULL;
1332 struct wpa_driver_scan_params params;
1334 dbus_bool_t allow_roam = 1;
1336 os_memset(¶ms, 0, sizeof(params));
1338 dbus_message_iter_init(message, &iter);
1340 dbus_message_iter_recurse(&iter, &dict_iter);
1342 while (dbus_message_iter_get_arg_type(&dict_iter) ==
1343 DBUS_TYPE_DICT_ENTRY) {
1344 dbus_message_iter_recurse(&dict_iter, &entry_iter);
1345 dbus_message_iter_get_basic(&entry_iter, &key);
1346 dbus_message_iter_next(&entry_iter);
1347 dbus_message_iter_recurse(&entry_iter, &variant_iter);
1349 if (os_strcmp(key, "Type") == 0) {
1350 if (wpas_dbus_get_scan_type(message, &variant_iter,
1353 } else if (os_strcmp(key, "SSIDs") == 0) {
1354 if (wpas_dbus_get_scan_ssids(message, &variant_iter,
1355 ¶ms, &reply) < 0)
1357 } else if (os_strcmp(key, "IEs") == 0) {
1358 if (wpas_dbus_get_scan_ies(message, &variant_iter,
1359 ¶ms, &reply) < 0)
1361 } else if (os_strcmp(key, "Channels") == 0) {
1362 if (wpas_dbus_get_scan_channels(message, &variant_iter,
1363 ¶ms, &reply) < 0)
1365 } else if (os_strcmp(key, "AllowRoam") == 0) {
1366 if (wpas_dbus_get_scan_allow_roam(message,
1372 wpa_printf(MSG_DEBUG, "%s[dbus]: Unknown argument %s",
1374 reply = wpas_dbus_error_invalid_args(message, key);
1378 dbus_message_iter_next(&dict_iter);
1382 wpa_printf(MSG_DEBUG, "%s[dbus]: Scan type not specified",
1384 reply = wpas_dbus_error_invalid_args(message, key);
1388 if (os_strcmp(type, "passive") == 0) {
1389 if (params.num_ssids || params.extra_ies_len) {
1390 wpa_printf(MSG_DEBUG,
1391 "%s[dbus]: SSIDs or IEs specified for passive scan.",
1393 reply = wpas_dbus_error_invalid_args(
1395 "You can specify only Channels in passive scan");
1398 if (wpa_s->sched_scanning) {
1399 wpa_printf(MSG_DEBUG,
1400 "%s[dbus]: Stop ongoing sched_scan to allow requested scan to proceed",
1402 wpa_supplicant_cancel_sched_scan(wpa_s);
1405 if (params.freqs && params.freqs[0]) {
1406 wpa_s->last_scan_req = MANUAL_SCAN_REQ;
1407 if (wpa_supplicant_trigger_scan(wpa_s,
1409 reply = wpas_dbus_error_scan_error(
1411 "Scan request rejected");
1414 wpa_s->scan_req = MANUAL_SCAN_REQ;
1415 wpa_supplicant_req_scan(wpa_s, 0, 0);
1418 } else if (os_strcmp(type, "active") == 0) {
1419 if (!params.num_ssids) {
1420 /* Add wildcard ssid */
1423 #ifdef CONFIG_AUTOSCAN
1424 autoscan_deinit(wpa_s);
1425 #endif /* CONFIG_AUTOSCAN */
1426 if (wpa_s->sched_scanning) {
1427 wpa_printf(MSG_DEBUG,
1428 "%s[dbus]: Stop ongoing sched_scan to allow requested scan to proceed",
1430 wpa_supplicant_cancel_sched_scan(wpa_s);
1433 wpa_s->last_scan_req = MANUAL_SCAN_REQ;
1434 if (wpa_supplicant_trigger_scan(wpa_s, ¶ms)) {
1435 reply = wpas_dbus_error_scan_error(
1436 message, "Scan request rejected");
1439 wpa_printf(MSG_DEBUG, "%s[dbus]: Unknown scan type: %s",
1441 reply = wpas_dbus_error_invalid_args(message,
1447 wpa_s->scan_res_handler = scan_only_handler;
1450 for (i = 0; i < WPAS_MAX_SCAN_SSIDS; i++)
1451 os_free((u8 *) params.ssids[i].ssid);
1452 os_free((u8 *) params.extra_ies);
1453 os_free(params.freqs);
1459 * wpas_dbus_handler_abort_scan - Request an ongoing scan to be aborted
1460 * @message: Pointer to incoming dbus message
1461 * @wpa_s: wpa_supplicant structure for a network interface
1462 * Returns: Abort failed or no scan in progress DBus error message on failure
1463 * or NULL otherwise.
1465 * Handler function for "AbortScan" method call of network interface.
1467 DBusMessage * wpas_dbus_handler_abort_scan(DBusMessage *message,
1468 struct wpa_supplicant *wpa_s)
1470 if (wpas_abort_ongoing_scan(wpa_s) < 0)
1471 return dbus_message_new_error(
1472 message, WPAS_DBUS_ERROR_IFACE_SCAN_ERROR,
1473 "Abort failed or no scan in progress");
1480 * wpas_dbus_handler_signal_poll - Request immediate signal properties
1481 * @message: Pointer to incoming dbus message
1482 * @wpa_s: wpa_supplicant structure for a network interface
1483 * Returns: NULL indicating success or DBus error message on failure
1485 * Handler function for "SignalPoll" method call of a network device. Requests
1486 * that wpa_supplicant read signal properties like RSSI, noise, and link
1487 * speed and return them.
1489 DBusMessage * wpas_dbus_handler_signal_poll(DBusMessage *message,
1490 struct wpa_supplicant *wpa_s)
1492 struct wpa_signal_info si;
1493 DBusMessage *reply = NULL;
1494 DBusMessageIter iter, iter_dict, variant_iter;
1497 ret = wpa_drv_signal_poll(wpa_s, &si);
1499 return dbus_message_new_error(message, DBUS_ERROR_FAILED,
1500 "Failed to read signal");
1503 reply = dbus_message_new_method_return(message);
1507 dbus_message_iter_init_append(reply, &iter);
1509 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
1510 "a{sv}", &variant_iter) ||
1511 !wpa_dbus_dict_open_write(&variant_iter, &iter_dict) ||
1512 !wpa_dbus_dict_append_int32(&iter_dict, "rssi",
1513 si.current_signal) ||
1514 !wpa_dbus_dict_append_int32(&iter_dict, "linkspeed",
1515 si.current_txrate / 1000) ||
1516 !wpa_dbus_dict_append_int32(&iter_dict, "noise",
1517 si.current_noise) ||
1518 !wpa_dbus_dict_append_uint32(&iter_dict, "frequency",
1520 (si.chanwidth != CHAN_WIDTH_UNKNOWN &&
1521 !wpa_dbus_dict_append_string(
1522 &iter_dict, "width",
1523 channel_width_to_string(si.chanwidth))) ||
1524 (si.center_frq1 > 0 && si.center_frq2 > 0 &&
1525 (!wpa_dbus_dict_append_int32(&iter_dict, "center-frq1",
1527 !wpa_dbus_dict_append_int32(&iter_dict, "center-frq2",
1528 si.center_frq2))) ||
1530 !wpa_dbus_dict_append_int32(&iter_dict, "avg-rssi",
1532 !wpa_dbus_dict_close_write(&variant_iter, &iter_dict) ||
1533 !dbus_message_iter_close_container(&iter, &variant_iter))
1540 dbus_message_unref(reply);
1541 return wpas_dbus_error_no_memory(message);
1546 * wpas_dbus_handler_disconnect - Terminate the current connection
1547 * @message: Pointer to incoming dbus message
1548 * @wpa_s: wpa_supplicant structure for a network interface
1549 * Returns: NotConnected DBus error message if already not connected
1550 * or NULL otherwise.
1552 * Handler function for "Disconnect" method call of network interface.
1554 DBusMessage * wpas_dbus_handler_disconnect(DBusMessage *message,
1555 struct wpa_supplicant *wpa_s)
1557 if (wpa_s->current_ssid != NULL) {
1558 wpas_request_disconnection(wpa_s);
1562 return dbus_message_new_error(message, WPAS_DBUS_ERROR_NOT_CONNECTED,
1563 "This interface is not connected");
1568 * wpas_dbus_new_iface_add_network - Add a new configured network
1569 * @message: Pointer to incoming dbus message
1570 * @wpa_s: wpa_supplicant structure for a network interface
1571 * Returns: A dbus message containing the object path of the new network
1573 * Handler function for "AddNetwork" method call of a network interface.
1575 DBusMessage * wpas_dbus_handler_add_network(DBusMessage *message,
1576 struct wpa_supplicant *wpa_s)
1578 DBusMessage *reply = NULL;
1579 DBusMessageIter iter;
1580 struct wpa_ssid *ssid = NULL;
1581 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf;
1584 dbus_message_iter_init(message, &iter);
1586 if (wpa_s->dbus_new_path)
1587 ssid = wpa_supplicant_add_network(wpa_s);
1589 wpa_printf(MSG_ERROR, "%s[dbus]: can't add new interface.",
1591 reply = wpas_dbus_error_unknown_error(
1593 "wpa_supplicant could not add a network on this interface.");
1597 dbus_error_init(&error);
1598 if (!set_network_properties(wpa_s, ssid, &iter, &error)) {
1599 wpa_printf(MSG_DEBUG,
1600 "%s[dbus]: control interface couldn't set network properties",
1602 reply = wpas_dbus_reply_new_from_error(message, &error,
1603 DBUS_ERROR_INVALID_ARGS,
1604 "Failed to add network");
1605 dbus_error_free(&error);
1609 /* Construct the object path for this network. */
1610 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
1611 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
1612 wpa_s->dbus_new_path, ssid->id);
1614 reply = dbus_message_new_method_return(message);
1615 if (reply == NULL) {
1616 reply = wpas_dbus_error_no_memory(message);
1619 if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
1620 DBUS_TYPE_INVALID)) {
1621 dbus_message_unref(reply);
1622 reply = wpas_dbus_error_no_memory(message);
1630 wpas_notify_network_removed(wpa_s, ssid);
1631 wpa_config_remove_network(wpa_s->conf, ssid->id);
1638 * wpas_dbus_handler_reassociate - Reassociate
1639 * @message: Pointer to incoming dbus message
1640 * @wpa_s: wpa_supplicant structure for a network interface
1641 * Returns: InterfaceDisabled DBus error message if disabled
1642 * or NULL otherwise.
1644 * Handler function for "Reassociate" method call of network interface.
1646 DBusMessage * wpas_dbus_handler_reassociate(DBusMessage *message,
1647 struct wpa_supplicant *wpa_s)
1649 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED) {
1650 wpas_request_connection(wpa_s);
1654 return dbus_message_new_error(message, WPAS_DBUS_ERROR_IFACE_DISABLED,
1655 "This interface is disabled");
1660 * wpas_dbus_handler_expect_disconnect - ExpectDisconnect
1661 * @message: Pointer to incoming dbus message
1662 * @global: %wpa_supplicant global data structure
1665 * Handler function for notifying system there will be a expected disconnect.
1666 * This will prevent wpa_supplicant from adding blacklists upon next disconnect..
1668 DBusMessage * wpas_dbus_handler_expect_disconnect(DBusMessage *message,
1669 struct wpa_global *global)
1671 struct wpa_supplicant *wpa_s = global->ifaces;
1673 for (; wpa_s; wpa_s = wpa_s->next)
1674 if (wpa_s->wpa_state >= WPA_ASSOCIATED)
1675 wpa_s->own_disconnect_req = 1;
1681 * wpas_dbus_handler_reattach - Reattach to current AP
1682 * @message: Pointer to incoming dbus message
1683 * @wpa_s: wpa_supplicant structure for a network interface
1684 * Returns: NotConnected DBus error message if not connected
1685 * or NULL otherwise.
1687 * Handler function for "Reattach" method call of network interface.
1689 DBusMessage * wpas_dbus_handler_reattach(DBusMessage *message,
1690 struct wpa_supplicant *wpa_s)
1692 if (wpa_s->current_ssid != NULL) {
1693 wpa_s->reattach = 1;
1694 wpas_request_connection(wpa_s);
1698 return dbus_message_new_error(message, WPAS_DBUS_ERROR_NOT_CONNECTED,
1699 "This interface is not connected");
1704 * wpas_dbus_handler_reconnect - Reconnect if disconnected
1705 * @message: Pointer to incoming dbus message
1706 * @wpa_s: wpa_supplicant structure for a network interface
1707 * Returns: InterfaceDisabled DBus error message if disabled
1708 * or NULL otherwise.
1710 * Handler function for "Reconnect" method call of network interface.
1712 DBusMessage * wpas_dbus_handler_reconnect(DBusMessage *message,
1713 struct wpa_supplicant *wpa_s)
1715 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
1716 return dbus_message_new_error(message,
1717 WPAS_DBUS_ERROR_IFACE_DISABLED,
1718 "This interface is disabled");
1721 if (wpa_s->disconnected)
1722 wpas_request_connection(wpa_s);
1728 * wpas_dbus_handler_remove_network - Remove a configured network
1729 * @message: Pointer to incoming dbus message
1730 * @wpa_s: wpa_supplicant structure for a network interface
1731 * Returns: NULL on success or dbus error on failure
1733 * Handler function for "RemoveNetwork" method call of a network interface.
1735 DBusMessage * wpas_dbus_handler_remove_network(DBusMessage *message,
1736 struct wpa_supplicant *wpa_s)
1738 DBusMessage *reply = NULL;
1740 char *iface, *net_id;
1744 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
1747 /* Extract the network ID and ensure the network */
1748 /* is actually a child of this interface */
1749 iface = wpas_dbus_new_decompose_object_path(op,
1750 WPAS_DBUS_NEW_NETWORKS_PART,
1752 if (iface == NULL || net_id == NULL || !wpa_s->dbus_new_path ||
1753 os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
1754 reply = wpas_dbus_error_invalid_args(message, op);
1759 id = strtoul(net_id, NULL, 10);
1761 reply = wpas_dbus_error_invalid_args(message, op);
1765 result = wpa_supplicant_remove_network(wpa_s, id);
1767 reply = wpas_dbus_error_network_unknown(message);
1771 wpa_printf(MSG_ERROR,
1772 "%s[dbus]: error occurred when removing network %d",
1774 reply = wpas_dbus_error_unknown_error(
1776 "error removing the specified network on is interface.");
1786 static void remove_network(void *arg, struct wpa_ssid *ssid)
1788 struct wpa_supplicant *wpa_s = arg;
1790 wpas_notify_network_removed(wpa_s, ssid);
1792 if (wpa_config_remove_network(wpa_s->conf, ssid->id) < 0) {
1793 wpa_printf(MSG_ERROR,
1794 "%s[dbus]: error occurred when removing network %d",
1795 __func__, ssid->id);
1799 if (ssid == wpa_s->current_ssid)
1800 wpa_supplicant_deauthenticate(wpa_s,
1801 WLAN_REASON_DEAUTH_LEAVING);
1806 * wpas_dbus_handler_remove_all_networks - Remove all configured networks
1807 * @message: Pointer to incoming dbus message
1808 * @wpa_s: wpa_supplicant structure for a network interface
1809 * Returns: NULL on success or dbus error on failure
1811 * Handler function for "RemoveAllNetworks" method call of a network interface.
1813 DBusMessage * wpas_dbus_handler_remove_all_networks(
1814 DBusMessage *message, struct wpa_supplicant *wpa_s)
1816 if (wpa_s->sched_scanning)
1817 wpa_supplicant_cancel_sched_scan(wpa_s);
1819 /* NB: could check for failure and return an error */
1820 wpa_config_foreach_network(wpa_s->conf, remove_network, wpa_s);
1826 * wpas_dbus_handler_select_network - Attempt association with a network
1827 * @message: Pointer to incoming dbus message
1828 * @wpa_s: wpa_supplicant structure for a network interface
1829 * Returns: NULL on success or dbus error on failure
1831 * Handler function for "SelectNetwork" method call of network interface.
1833 DBusMessage * wpas_dbus_handler_select_network(DBusMessage *message,
1834 struct wpa_supplicant *wpa_s)
1836 DBusMessage *reply = NULL;
1838 char *iface, *net_id;
1840 struct wpa_ssid *ssid;
1842 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
1845 /* Extract the network ID and ensure the network */
1846 /* is actually a child of this interface */
1847 iface = wpas_dbus_new_decompose_object_path(op,
1848 WPAS_DBUS_NEW_NETWORKS_PART,
1850 if (iface == NULL || net_id == NULL || !wpa_s->dbus_new_path ||
1851 os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
1852 reply = wpas_dbus_error_invalid_args(message, op);
1857 id = strtoul(net_id, NULL, 10);
1859 reply = wpas_dbus_error_invalid_args(message, op);
1863 ssid = wpa_config_get_network(wpa_s->conf, id);
1865 reply = wpas_dbus_error_network_unknown(message);
1869 /* Finally, associate with the network */
1870 wpa_supplicant_select_network(wpa_s, ssid);
1879 * wpas_dbus_handler_network_reply - Reply to a NetworkRequest signal
1880 * @message: Pointer to incoming dbus message
1881 * @wpa_s: wpa_supplicant structure for a network interface
1882 * Returns: NULL on success or dbus error on failure
1884 * Handler function for "NetworkReply" method call of network interface.
1886 DBusMessage * wpas_dbus_handler_network_reply(DBusMessage *message,
1887 struct wpa_supplicant *wpa_s)
1889 #ifdef IEEE8021X_EAPOL
1890 DBusMessage *reply = NULL;
1891 const char *op, *field, *value;
1892 char *iface, *net_id;
1894 struct wpa_ssid *ssid;
1896 if (!dbus_message_get_args(message, NULL,
1897 DBUS_TYPE_OBJECT_PATH, &op,
1898 DBUS_TYPE_STRING, &field,
1899 DBUS_TYPE_STRING, &value,
1901 return wpas_dbus_error_invalid_args(message, NULL);
1903 /* Extract the network ID and ensure the network */
1904 /* is actually a child of this interface */
1905 iface = wpas_dbus_new_decompose_object_path(op,
1906 WPAS_DBUS_NEW_NETWORKS_PART,
1908 if (iface == NULL || net_id == NULL || !wpa_s->dbus_new_path ||
1909 os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
1910 reply = wpas_dbus_error_invalid_args(message, op);
1915 id = strtoul(net_id, NULL, 10);
1917 reply = wpas_dbus_error_invalid_args(message, net_id);
1921 ssid = wpa_config_get_network(wpa_s->conf, id);
1923 reply = wpas_dbus_error_network_unknown(message);
1927 if (wpa_supplicant_ctrl_iface_ctrl_rsp_handle(wpa_s, ssid,
1929 reply = wpas_dbus_error_invalid_args(message, field);
1931 /* Tell EAP to retry immediately */
1932 eapol_sm_notify_ctrl_response(wpa_s->eapol);
1938 #else /* IEEE8021X_EAPOL */
1939 wpa_printf(MSG_DEBUG, "dbus: 802.1X not included");
1940 return wpas_dbus_error_unknown_error(message, "802.1X not included");
1941 #endif /* IEEE8021X_EAPOL */
1945 #ifndef CONFIG_NO_CONFIG_BLOBS
1948 * wpas_dbus_handler_add_blob - Store named binary blob (ie, for certificates)
1949 * @message: Pointer to incoming dbus message
1950 * @wpa_s: %wpa_supplicant data structure
1951 * Returns: A dbus message containing an error on failure or NULL on success
1953 * Asks wpa_supplicant to internally store a binary blobs.
1955 DBusMessage * wpas_dbus_handler_add_blob(DBusMessage *message,
1956 struct wpa_supplicant *wpa_s)
1958 DBusMessage *reply = NULL;
1959 DBusMessageIter iter, array_iter;
1964 struct wpa_config_blob *blob = NULL;
1966 dbus_message_iter_init(message, &iter);
1967 dbus_message_iter_get_basic(&iter, &blob_name);
1969 if (wpa_config_get_blob(wpa_s->conf, blob_name)) {
1970 return dbus_message_new_error(message,
1971 WPAS_DBUS_ERROR_BLOB_EXISTS,
1975 dbus_message_iter_next(&iter);
1976 dbus_message_iter_recurse(&iter, &array_iter);
1978 dbus_message_iter_get_fixed_array(&array_iter, &blob_data, &blob_len);
1980 blob = os_zalloc(sizeof(*blob));
1982 reply = wpas_dbus_error_no_memory(message);
1986 blob->data = os_memdup(blob_data, blob_len);
1987 blob->name = os_strdup(blob_name);
1988 if (!blob->data || !blob->name) {
1989 reply = wpas_dbus_error_no_memory(message);
1992 blob->len = blob_len;
1994 wpa_config_set_blob(wpa_s->conf, blob);
1995 wpas_notify_blob_added(wpa_s, blob->name);
2001 os_free(blob->name);
2002 os_free(blob->data);
2010 * wpas_dbus_handler_get_blob - Get named binary blob (ie, for certificates)
2011 * @message: Pointer to incoming dbus message
2012 * @wpa_s: %wpa_supplicant data structure
2013 * Returns: A dbus message containing array of bytes (blob)
2015 * Gets one wpa_supplicant's binary blobs.
2017 DBusMessage * wpas_dbus_handler_get_blob(DBusMessage *message,
2018 struct wpa_supplicant *wpa_s)
2020 DBusMessage *reply = NULL;
2021 DBusMessageIter iter, array_iter;
2024 const struct wpa_config_blob *blob;
2026 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &blob_name,
2029 blob = wpa_config_get_blob(wpa_s->conf, blob_name);
2031 return dbus_message_new_error(message,
2032 WPAS_DBUS_ERROR_BLOB_UNKNOWN,
2036 reply = dbus_message_new_method_return(message);
2038 return wpas_dbus_error_no_memory(message);
2040 dbus_message_iter_init_append(reply, &iter);
2042 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
2043 DBUS_TYPE_BYTE_AS_STRING,
2045 !dbus_message_iter_append_fixed_array(&array_iter, DBUS_TYPE_BYTE,
2046 &(blob->data), blob->len) ||
2047 !dbus_message_iter_close_container(&iter, &array_iter)) {
2048 dbus_message_unref(reply);
2049 reply = wpas_dbus_error_no_memory(message);
2057 * wpas_remove_handler_remove_blob - Remove named binary blob
2058 * @message: Pointer to incoming dbus message
2059 * @wpa_s: %wpa_supplicant data structure
2060 * Returns: NULL on success or dbus error
2062 * Asks wpa_supplicant to internally remove a binary blobs.
2064 DBusMessage * wpas_dbus_handler_remove_blob(DBusMessage *message,
2065 struct wpa_supplicant *wpa_s)
2067 DBusMessage *reply = NULL;
2070 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &blob_name,
2073 if (wpa_config_remove_blob(wpa_s->conf, blob_name)) {
2074 return dbus_message_new_error(message,
2075 WPAS_DBUS_ERROR_BLOB_UNKNOWN,
2078 wpas_notify_blob_removed(wpa_s, blob_name);
2084 #endif /* CONFIG_NO_CONFIG_BLOBS */
2088 * wpas_dbus_handler_flush_bss - Flush the BSS cache
2089 * @message: Pointer to incoming dbus message
2090 * @wpa_s: wpa_supplicant structure for a network interface
2093 * Handler function for "FlushBSS" method call of network interface.
2095 DBusMessage * wpas_dbus_handler_flush_bss(DBusMessage *message,
2096 struct wpa_supplicant *wpa_s)
2100 dbus_message_get_args(message, NULL, DBUS_TYPE_UINT32, &age,
2104 wpa_bss_flush(wpa_s);
2106 wpa_bss_flush_by_age(wpa_s, age);
2112 #ifdef CONFIG_AUTOSCAN
2114 * wpas_dbus_handler_autoscan - Set autoscan parameters for the interface
2115 * @message: Pointer to incoming dbus message
2116 * @wpa_s: wpa_supplicant structure for a network interface
2119 * Handler function for "AutoScan" method call of network interface.
2121 DBusMessage * wpas_dbus_handler_autoscan(DBusMessage *message,
2122 struct wpa_supplicant *wpa_s)
2124 DBusMessage *reply = NULL;
2125 enum wpa_states state = wpa_s->wpa_state;
2128 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &arg,
2131 if (arg != NULL && os_strlen(arg) > 0) {
2134 tmp = os_strdup(arg);
2136 reply = wpas_dbus_error_no_memory(message);
2138 os_free(wpa_s->conf->autoscan);
2139 wpa_s->conf->autoscan = tmp;
2140 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
2141 autoscan_init(wpa_s, 1);
2142 else if (state == WPA_SCANNING)
2143 wpa_supplicant_reinit_autoscan(wpa_s);
2145 } else if (arg != NULL && os_strlen(arg) == 0) {
2146 os_free(wpa_s->conf->autoscan);
2147 wpa_s->conf->autoscan = NULL;
2148 autoscan_deinit(wpa_s);
2150 reply = dbus_message_new_error(message,
2151 DBUS_ERROR_INVALID_ARGS,
2156 #endif /* CONFIG_AUTOSCAN */
2160 * wpas_dbus_handler_eap_logoff - IEEE 802.1X EAPOL state machine logoff
2161 * @message: Pointer to incoming dbus message
2162 * @wpa_s: wpa_supplicant structure for a network interface
2165 * Handler function for "EAPLogoff" method call of network interface.
2167 DBusMessage * wpas_dbus_handler_eap_logoff(DBusMessage *message,
2168 struct wpa_supplicant *wpa_s)
2170 eapol_sm_notify_logoff(wpa_s->eapol, TRUE);
2176 * wpas_dbus_handler_eap_logon - IEEE 802.1X EAPOL state machine logon
2177 * @message: Pointer to incoming dbus message
2178 * @wpa_s: wpa_supplicant structure for a network interface
2181 * Handler function for "EAPLogin" method call of network interface.
2183 DBusMessage * wpas_dbus_handler_eap_logon(DBusMessage *message,
2184 struct wpa_supplicant *wpa_s)
2186 eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
2193 static int get_peer_hwaddr_helper(DBusMessage *message, const char *func_name,
2194 u8 *peer_address, DBusMessage **error)
2196 const char *peer_string;
2200 if (!dbus_message_get_args(message, NULL,
2201 DBUS_TYPE_STRING, &peer_string,
2202 DBUS_TYPE_INVALID)) {
2203 *error = wpas_dbus_error_invalid_args(message, NULL);
2207 if (hwaddr_aton(peer_string, peer_address)) {
2208 wpa_printf(MSG_DEBUG, "%s: invalid address '%s'",
2209 func_name, peer_string);
2210 *error = wpas_dbus_error_invalid_args(
2211 message, "Invalid hardware address format");
2220 * wpas_dbus_handler_tdls_discover - Discover TDLS peer
2221 * @message: Pointer to incoming dbus message
2222 * @wpa_s: wpa_supplicant structure for a network interface
2223 * Returns: NULL indicating success or DBus error message on failure
2225 * Handler function for "TDLSDiscover" method call of network interface.
2227 DBusMessage * wpas_dbus_handler_tdls_discover(DBusMessage *message,
2228 struct wpa_supplicant *wpa_s)
2231 DBusMessage *error_reply;
2234 if (get_peer_hwaddr_helper(message, __func__, peer, &error_reply) < 0)
2237 wpa_printf(MSG_DEBUG, "DBUS TDLS_DISCOVER " MACSTR, MAC2STR(peer));
2239 if (wpa_tdls_is_external_setup(wpa_s->wpa))
2240 ret = wpa_tdls_send_discovery_request(wpa_s->wpa, peer);
2242 ret = wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer);
2245 return wpas_dbus_error_unknown_error(
2246 message, "error performing TDLS discovery");
2254 * wpas_dbus_handler_tdls_setup - Setup TDLS session
2255 * @message: Pointer to incoming dbus message
2256 * @wpa_s: wpa_supplicant structure for a network interface
2257 * Returns: NULL indicating success or DBus error message on failure
2259 * Handler function for "TDLSSetup" method call of network interface.
2261 DBusMessage * wpas_dbus_handler_tdls_setup(DBusMessage *message,
2262 struct wpa_supplicant *wpa_s)
2265 DBusMessage *error_reply;
2268 if (get_peer_hwaddr_helper(message, __func__, peer, &error_reply) < 0)
2271 wpa_printf(MSG_DEBUG, "DBUS TDLS_SETUP " MACSTR, MAC2STR(peer));
2273 wpa_tdls_remove(wpa_s->wpa, peer);
2274 if (wpa_tdls_is_external_setup(wpa_s->wpa))
2275 ret = wpa_tdls_start(wpa_s->wpa, peer);
2277 ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
2280 return wpas_dbus_error_unknown_error(
2281 message, "error performing TDLS setup");
2289 * wpas_dbus_handler_tdls_status - Return TDLS session status
2290 * @message: Pointer to incoming dbus message
2291 * @wpa_s: wpa_supplicant structure for a network interface
2292 * Returns: A string representing the state of the link to this TDLS peer
2294 * Handler function for "TDLSStatus" method call of network interface.
2296 DBusMessage * wpas_dbus_handler_tdls_status(DBusMessage *message,
2297 struct wpa_supplicant *wpa_s)
2301 const char *tdls_status;
2303 if (get_peer_hwaddr_helper(message, __func__, peer, &reply) < 0)
2306 wpa_printf(MSG_DEBUG, "DBUS TDLS_STATUS " MACSTR, MAC2STR(peer));
2308 tdls_status = wpa_tdls_get_link_status(wpa_s->wpa, peer);
2310 reply = dbus_message_new_method_return(message);
2311 dbus_message_append_args(reply, DBUS_TYPE_STRING,
2312 &tdls_status, DBUS_TYPE_INVALID);
2318 * wpas_dbus_handler_tdls_teardown - Teardown TDLS session
2319 * @message: Pointer to incoming dbus message
2320 * @wpa_s: wpa_supplicant structure for a network interface
2321 * Returns: NULL indicating success or DBus error message on failure
2323 * Handler function for "TDLSTeardown" method call of network interface.
2325 DBusMessage * wpas_dbus_handler_tdls_teardown(DBusMessage *message,
2326 struct wpa_supplicant *wpa_s)
2329 DBusMessage *error_reply;
2332 if (get_peer_hwaddr_helper(message, __func__, peer, &error_reply) < 0)
2335 wpa_printf(MSG_DEBUG, "DBUS TDLS_TEARDOWN " MACSTR, MAC2STR(peer));
2337 if (wpa_tdls_is_external_setup(wpa_s->wpa))
2338 ret = wpa_tdls_teardown_link(
2340 WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
2342 ret = wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
2345 return wpas_dbus_error_unknown_error(
2346 message, "error performing TDLS teardown");
2353 * wpas_dbus_handler_tdls_channel_switch - Enable channel switching with TDLS peer
2354 * @message: Pointer to incoming dbus message
2355 * @wpa_s: wpa_supplicant structure for a network interface
2356 * Returns: NULL indicating success or DBus error message on failure
2358 * Handler function for "TDLSChannelSwitch" method call of network interface.
2361 wpas_dbus_handler_tdls_channel_switch(DBusMessage *message,
2362 struct wpa_supplicant *wpa_s)
2364 DBusMessageIter iter, iter_dict;
2365 struct wpa_dbus_dict_entry entry;
2367 struct hostapd_freq_params freq_params;
2370 int is_peer_present = 0;
2372 if (!wpa_tdls_is_external_setup(wpa_s->wpa)) {
2373 wpa_printf(MSG_INFO,
2374 "tdls_chanswitch: Only supported with external setup");
2375 return wpas_dbus_error_unknown_error(message, "TDLS is not using external setup");
2378 os_memset(&freq_params, 0, sizeof(freq_params));
2380 dbus_message_iter_init(message, &iter);
2382 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
2383 return wpas_dbus_error_invalid_args(message, NULL);
2385 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2386 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2387 return wpas_dbus_error_invalid_args(message, NULL);
2389 if (os_strcmp(entry.key, "PeerAddress") == 0 &&
2390 entry.type == DBUS_TYPE_STRING) {
2391 if (hwaddr_aton(entry.str_value, peer)) {
2392 wpa_printf(MSG_DEBUG,
2393 "tdls_chanswitch: Invalid address '%s'",
2395 wpa_dbus_dict_entry_clear(&entry);
2396 return wpas_dbus_error_invalid_args(message,
2400 is_peer_present = 1;
2401 } else if (os_strcmp(entry.key, "OperClass") == 0 &&
2402 entry.type == DBUS_TYPE_BYTE) {
2403 oper_class = entry.byte_value;
2404 } else if (os_strcmp(entry.key, "Frequency") == 0 &&
2405 entry.type == DBUS_TYPE_UINT32) {
2406 freq_params.freq = entry.uint32_value;
2407 } else if (os_strcmp(entry.key, "SecChannelOffset") == 0 &&
2408 entry.type == DBUS_TYPE_UINT32) {
2409 freq_params.sec_channel_offset = entry.uint32_value;
2410 } else if (os_strcmp(entry.key, "CenterFrequency1") == 0 &&
2411 entry.type == DBUS_TYPE_UINT32) {
2412 freq_params.center_freq1 = entry.uint32_value;
2413 } else if (os_strcmp(entry.key, "CenterFrequency2") == 0 &&
2414 entry.type == DBUS_TYPE_UINT32) {
2415 freq_params.center_freq2 = entry.uint32_value;
2416 } else if (os_strcmp(entry.key, "Bandwidth") == 0 &&
2417 entry.type == DBUS_TYPE_UINT32) {
2418 freq_params.bandwidth = entry.uint32_value;
2419 } else if (os_strcmp(entry.key, "HT") == 0 &&
2420 entry.type == DBUS_TYPE_BOOLEAN) {
2421 freq_params.ht_enabled = entry.bool_value;
2422 } else if (os_strcmp(entry.key, "VHT") == 0 &&
2423 entry.type == DBUS_TYPE_BOOLEAN) {
2424 freq_params.vht_enabled = entry.bool_value;
2426 wpa_dbus_dict_entry_clear(&entry);
2427 return wpas_dbus_error_invalid_args(message, NULL);
2430 wpa_dbus_dict_entry_clear(&entry);
2433 if (oper_class == 0) {
2434 wpa_printf(MSG_INFO,
2435 "tdls_chanswitch: Invalid op class provided");
2436 return wpas_dbus_error_invalid_args(
2437 message, "Invalid op class provided");
2440 if (freq_params.freq == 0) {
2441 wpa_printf(MSG_INFO,
2442 "tdls_chanswitch: Invalid freq provided");
2443 return wpas_dbus_error_invalid_args(message,
2444 "Invalid freq provided");
2447 if (is_peer_present == 0) {
2448 wpa_printf(MSG_DEBUG,
2449 "tdls_chanswitch: peer address not provided");
2450 return wpas_dbus_error_invalid_args(
2451 message, "peer address not provided");
2454 wpa_printf(MSG_DEBUG, "dbus: TDLS_CHAN_SWITCH " MACSTR
2455 " OP CLASS %d FREQ %d CENTER1 %d CENTER2 %d BW %d SEC_OFFSET %d%s%s",
2456 MAC2STR(peer), oper_class, freq_params.freq,
2457 freq_params.center_freq1, freq_params.center_freq2,
2458 freq_params.bandwidth, freq_params.sec_channel_offset,
2459 freq_params.ht_enabled ? " HT" : "",
2460 freq_params.vht_enabled ? " VHT" : "");
2462 ret = wpa_tdls_enable_chan_switch(wpa_s->wpa, peer, oper_class,
2465 return wpas_dbus_error_unknown_error(
2466 message, "error processing TDLS channel switch");
2472 * wpas_dbus_handler_tdls_cancel_channel_switch - Disable channel switching with TDLS peer
2473 * @message: Pointer to incoming dbus message
2474 * @wpa_s: wpa_supplicant structure for a network interface
2475 * Returns: NULL indicating success or DBus error message on failure
2477 * Handler function for "TDLSCancelChannelSwitch" method call of network
2481 wpas_dbus_handler_tdls_cancel_channel_switch(DBusMessage *message,
2482 struct wpa_supplicant *wpa_s)
2485 DBusMessage *error_reply;
2488 if (get_peer_hwaddr_helper(message, __func__, peer, &error_reply) < 0)
2491 wpa_printf(MSG_DEBUG, "dbus: TDLS_CANCEL_CHAN_SWITCH " MACSTR,
2494 ret = wpa_tdls_disable_chan_switch(wpa_s->wpa, peer);
2496 return wpas_dbus_error_unknown_error(
2497 message, "error canceling TDLS channel switch");
2502 #endif /* CONFIG_TDLS */
2505 #ifndef CONFIG_NO_CONFIG_WRITE
2507 * wpas_dbus_handler_save_config - Save configuration to configuration file
2508 * @message: Pointer to incoming dbus message
2509 * @wpa_s: wpa_supplicant structure for a network interface
2510 * Returns: NULL on Success, Otherwise errror message
2512 * Handler function for "SaveConfig" method call of network interface.
2514 DBusMessage * wpas_dbus_handler_save_config(DBusMessage *message,
2515 struct wpa_supplicant *wpa_s)
2519 if (!wpa_s->conf->update_config) {
2520 return wpas_dbus_error_unknown_error(
2522 "Not allowed to update configuration (update_config=0)");
2525 ret = wpa_config_write(wpa_s->confname, wpa_s->conf);
2527 return wpas_dbus_error_unknown_error(
2528 message, "Failed to update configuration");
2531 #endif /* CONFIG_NO_CONFIG_WRITE */
2535 * wpas_dbus_handler_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
2536 * @message: Pointer to incoming dbus message
2537 * @wpa_s: %wpa_supplicant data structure
2538 * Returns: A dbus message containing an error on failure or NULL on success
2540 * Sets the PKCS #11 engine and module path.
2542 DBusMessage * wpas_dbus_handler_set_pkcs11_engine_and_module_path(
2543 DBusMessage *message, struct wpa_supplicant *wpa_s)
2545 DBusMessageIter iter;
2547 char *pkcs11_engine_path = NULL;
2548 char *pkcs11_module_path = NULL;
2550 dbus_message_iter_init(message, &iter);
2551 dbus_message_iter_get_basic(&iter, &value);
2552 if (value == NULL) {
2553 return dbus_message_new_error(
2554 message, DBUS_ERROR_INVALID_ARGS,
2555 "Invalid pkcs11_engine_path argument");
2557 /* Empty path defaults to NULL */
2558 if (os_strlen(value))
2559 pkcs11_engine_path = value;
2561 dbus_message_iter_next(&iter);
2562 dbus_message_iter_get_basic(&iter, &value);
2563 if (value == NULL) {
2564 os_free(pkcs11_engine_path);
2565 return dbus_message_new_error(
2566 message, DBUS_ERROR_INVALID_ARGS,
2567 "Invalid pkcs11_module_path argument");
2569 /* Empty path defaults to NULL */
2570 if (os_strlen(value))
2571 pkcs11_module_path = value;
2573 if (wpas_set_pkcs11_engine_and_module_path(wpa_s, pkcs11_engine_path,
2574 pkcs11_module_path))
2575 return dbus_message_new_error(
2576 message, DBUS_ERROR_FAILED,
2577 "Reinit of the EAPOL state machine with the new PKCS #11 engine and module path failed.");
2579 if (wpa_s->dbus_new_path) {
2580 wpa_dbus_mark_property_changed(
2581 wpa_s->global->dbus, wpa_s->dbus_new_path,
2582 WPAS_DBUS_NEW_IFACE_INTERFACE, "PKCS11EnginePath");
2583 wpa_dbus_mark_property_changed(
2584 wpa_s->global->dbus, wpa_s->dbus_new_path,
2585 WPAS_DBUS_NEW_IFACE_INTERFACE, "PKCS11ModulePath");
2593 * wpas_dbus_getter_capabilities - Return interface capabilities
2594 * @iter: Pointer to incoming dbus message iter
2595 * @error: Location to store error on failure
2596 * @user_data: Function specific data
2597 * Returns: TRUE on success, FALSE on failure
2599 * Getter for "Capabilities" property of an interface.
2601 dbus_bool_t wpas_dbus_getter_capabilities(
2602 const struct wpa_dbus_property_desc *property_desc,
2603 DBusMessageIter *iter, DBusError *error, void *user_data)
2605 struct wpa_supplicant *wpa_s = user_data;
2606 struct wpa_driver_capa capa;
2608 DBusMessageIter iter_dict, iter_dict_entry, iter_dict_val, iter_array,
2610 const char *scans[] = { "active", "passive", "ssid" };
2612 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
2613 "a{sv}", &variant_iter) ||
2614 !wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
2617 res = wpa_drv_get_capa(wpa_s, &capa);
2619 /***** pairwise cipher */
2621 const char *args[] = {"ccmp", "tkip", "none"};
2623 if (!wpa_dbus_dict_append_string_array(
2624 &iter_dict, "Pairwise", args,
2628 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Pairwise",
2632 ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP_256) &&
2633 !wpa_dbus_dict_string_array_add_element(
2634 &iter_array, "ccmp-256")) ||
2635 ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP_256) &&
2636 !wpa_dbus_dict_string_array_add_element(
2637 &iter_array, "gcmp-256")) ||
2638 ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) &&
2639 !wpa_dbus_dict_string_array_add_element(
2640 &iter_array, "ccmp")) ||
2641 ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP) &&
2642 !wpa_dbus_dict_string_array_add_element(
2643 &iter_array, "gcmp")) ||
2644 ((capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) &&
2645 !wpa_dbus_dict_string_array_add_element(
2646 &iter_array, "tkip")) ||
2647 ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) &&
2648 !wpa_dbus_dict_string_array_add_element(
2649 &iter_array, "none")) ||
2650 !wpa_dbus_dict_end_string_array(&iter_dict,
2657 /***** group cipher */
2659 const char *args[] = {
2660 "ccmp", "tkip", "wep104", "wep40"
2663 if (!wpa_dbus_dict_append_string_array(
2664 &iter_dict, "Group", args,
2668 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Group",
2672 ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP_256) &&
2673 !wpa_dbus_dict_string_array_add_element(
2674 &iter_array, "ccmp-256")) ||
2675 ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP_256) &&
2676 !wpa_dbus_dict_string_array_add_element(
2677 &iter_array, "gcmp-256")) ||
2678 ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) &&
2679 !wpa_dbus_dict_string_array_add_element(
2680 &iter_array, "ccmp")) ||
2681 ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP) &&
2682 !wpa_dbus_dict_string_array_add_element(
2683 &iter_array, "gcmp")) ||
2684 ((capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) &&
2685 !wpa_dbus_dict_string_array_add_element(
2686 &iter_array, "tkip")) ||
2687 ((capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) &&
2688 !wpa_dbus_dict_string_array_add_element(
2689 &iter_array, "wep104")) ||
2690 ((capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) &&
2691 !wpa_dbus_dict_string_array_add_element(
2692 &iter_array, "wep40")) ||
2693 !wpa_dbus_dict_end_string_array(&iter_dict,
2700 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "GroupMgmt",
2704 (res == 0 && (capa.enc & WPA_DRIVER_CAPA_ENC_BIP) &&
2705 !wpa_dbus_dict_string_array_add_element(
2706 &iter_array, "aes-128-cmac")) ||
2707 (res == 0 && (capa.enc & WPA_DRIVER_CAPA_ENC_BIP_GMAC_128) &&
2708 !wpa_dbus_dict_string_array_add_element(
2709 &iter_array, "bip-gmac-128")) ||
2710 (res == 0 && (capa.enc & WPA_DRIVER_CAPA_ENC_BIP_GMAC_256) &&
2711 !wpa_dbus_dict_string_array_add_element(
2712 &iter_array, "bip-gmac-256")) ||
2713 (res == 0 && (capa.enc & WPA_DRIVER_CAPA_ENC_BIP_CMAC_256) &&
2714 !wpa_dbus_dict_string_array_add_element(
2715 &iter_array, "bip-cmac-256")) ||
2716 !wpa_dbus_dict_end_string_array(&iter_dict,
2722 /***** key management */
2724 const char *args[] = {
2725 "wpa-psk", "wpa-eap", "ieee8021x", "wpa-none",
2728 #endif /* CONFIG_WPS */
2731 if (!wpa_dbus_dict_append_string_array(
2732 &iter_dict, "KeyMgmt", args,
2736 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "KeyMgmt",
2740 !wpa_dbus_dict_string_array_add_element(&iter_array,
2742 !wpa_dbus_dict_string_array_add_element(&iter_array,
2746 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
2747 WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
2748 if (!wpa_dbus_dict_string_array_add_element(
2749 &iter_array, "wpa-eap") ||
2750 ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT) &&
2751 !wpa_dbus_dict_string_array_add_element(
2752 &iter_array, "wpa-ft-eap")))
2755 /* TODO: Ensure that driver actually supports sha256 encryption. */
2756 #ifdef CONFIG_IEEE80211W
2757 if (!wpa_dbus_dict_string_array_add_element(
2758 &iter_array, "wpa-eap-sha256"))
2760 #endif /* CONFIG_IEEE80211W */
2763 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
2764 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
2765 if (!wpa_dbus_dict_string_array_add_element(
2766 &iter_array, "wpa-psk") ||
2768 WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK) &&
2769 !wpa_dbus_dict_string_array_add_element(
2770 &iter_array, "wpa-ft-psk")))
2773 /* TODO: Ensure that driver actually supports sha256 encryption. */
2774 #ifdef CONFIG_IEEE80211W
2775 if (!wpa_dbus_dict_string_array_add_element(
2776 &iter_array, "wpa-psk-sha256"))
2778 #endif /* CONFIG_IEEE80211W */
2781 if ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) &&
2782 !wpa_dbus_dict_string_array_add_element(&iter_array,
2788 if (!wpa_dbus_dict_string_array_add_element(&iter_array,
2791 #endif /* CONFIG_WPS */
2793 if (!wpa_dbus_dict_end_string_array(&iter_dict,
2800 /***** WPA protocol */
2802 const char *args[] = { "rsn", "wpa" };
2804 if (!wpa_dbus_dict_append_string_array(
2805 &iter_dict, "Protocol", args,
2809 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Protocol",
2813 ((capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
2814 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) &&
2815 !wpa_dbus_dict_string_array_add_element(
2816 &iter_array, "rsn")) ||
2817 ((capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
2818 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) &&
2819 !wpa_dbus_dict_string_array_add_element(
2820 &iter_array, "wpa")) ||
2821 !wpa_dbus_dict_end_string_array(&iter_dict,
2830 const char *args[] = { "open", "shared", "leap" };
2832 if (!wpa_dbus_dict_append_string_array(
2833 &iter_dict, "AuthAlg", args,
2837 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "AuthAlg",
2843 if (((capa.auth & WPA_DRIVER_AUTH_OPEN) &&
2844 !wpa_dbus_dict_string_array_add_element(
2845 &iter_array, "open")) ||
2846 ((capa.auth & WPA_DRIVER_AUTH_SHARED) &&
2847 !wpa_dbus_dict_string_array_add_element(
2848 &iter_array, "shared")) ||
2849 ((capa.auth & WPA_DRIVER_AUTH_LEAP) &&
2850 !wpa_dbus_dict_string_array_add_element(
2851 &iter_array, "leap")) ||
2852 !wpa_dbus_dict_end_string_array(&iter_dict,
2860 if (!wpa_dbus_dict_append_string_array(&iter_dict, "Scan", scans,
2865 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Modes",
2869 !wpa_dbus_dict_string_array_add_element(
2870 &iter_array, "infrastructure") ||
2871 (res >= 0 && (capa.flags & WPA_DRIVER_FLAGS_IBSS) &&
2872 !wpa_dbus_dict_string_array_add_element(
2873 &iter_array, "ad-hoc")) ||
2874 (res >= 0 && (capa.flags & WPA_DRIVER_FLAGS_AP) &&
2875 !wpa_dbus_dict_string_array_add_element(
2876 &iter_array, "ap")) ||
2877 (res >= 0 && (capa.flags & WPA_DRIVER_FLAGS_P2P_CAPABLE) &&
2878 !wpa_s->conf->p2p_disabled &&
2879 !wpa_dbus_dict_string_array_add_element(
2880 &iter_array, "p2p")) ||
2882 (res >= 0 && (capa.flags & WPA_DRIVER_FLAGS_MESH) &&
2883 !wpa_dbus_dict_string_array_add_element(
2884 &iter_array, "mesh")) ||
2885 #endif /* CONFIG_MESH */
2886 !wpa_dbus_dict_end_string_array(&iter_dict,
2894 dbus_int32_t max_scan_ssid = capa.max_scan_ssids;
2896 if (!wpa_dbus_dict_append_int32(&iter_dict, "MaxScanSSID",
2901 if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict) ||
2902 !dbus_message_iter_close_container(iter, &variant_iter))
2908 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
2914 * wpas_dbus_getter_state - Get interface state
2915 * @iter: Pointer to incoming dbus message iter
2916 * @error: Location to store error on failure
2917 * @user_data: Function specific data
2918 * Returns: TRUE on success, FALSE on failure
2920 * Getter for "State" property.
2922 dbus_bool_t wpas_dbus_getter_state(
2923 const struct wpa_dbus_property_desc *property_desc,
2924 DBusMessageIter *iter, DBusError *error, void *user_data)
2926 struct wpa_supplicant *wpa_s = user_data;
2927 const char *str_state;
2928 char *state_ls, *tmp;
2929 dbus_bool_t success = FALSE;
2931 str_state = wpa_supplicant_state_txt(wpa_s->wpa_state);
2933 /* make state string lowercase to fit new DBus API convention
2935 state_ls = tmp = os_strdup(str_state);
2937 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
2941 *tmp = tolower(*tmp);
2945 success = wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
2955 * wpas_dbus_new_iface_get_scanning - Get interface scanning state
2956 * @iter: Pointer to incoming dbus message iter
2957 * @error: Location to store error on failure
2958 * @user_data: Function specific data
2959 * Returns: TRUE on success, FALSE on failure
2961 * Getter for "scanning" property.
2963 dbus_bool_t wpas_dbus_getter_scanning(
2964 const struct wpa_dbus_property_desc *property_desc,
2965 DBusMessageIter *iter, DBusError *error, void *user_data)
2967 struct wpa_supplicant *wpa_s = user_data;
2968 dbus_bool_t scanning = wpa_s->scanning ? TRUE : FALSE;
2970 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
2976 * wpas_dbus_getter_ap_scan - Control roaming mode
2977 * @iter: Pointer to incoming dbus message iter
2978 * @error: Location to store error on failure
2979 * @user_data: Function specific data
2980 * Returns: TRUE on success, FALSE on failure
2982 * Getter function for "ApScan" property.
2984 dbus_bool_t wpas_dbus_getter_ap_scan(
2985 const struct wpa_dbus_property_desc *property_desc,
2986 DBusMessageIter *iter, DBusError *error, void *user_data)
2988 struct wpa_supplicant *wpa_s = user_data;
2989 dbus_uint32_t ap_scan = wpa_s->conf->ap_scan;
2991 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
2997 * wpas_dbus_setter_ap_scan - Control roaming mode
2998 * @iter: Pointer to incoming dbus message iter
2999 * @error: Location to store error on failure
3000 * @user_data: Function specific data
3001 * Returns: TRUE on success, FALSE on failure
3003 * Setter function for "ApScan" property.
3005 dbus_bool_t wpas_dbus_setter_ap_scan(
3006 const struct wpa_dbus_property_desc *property_desc,
3007 DBusMessageIter *iter, DBusError *error, void *user_data)
3009 struct wpa_supplicant *wpa_s = user_data;
3010 dbus_uint32_t ap_scan;
3012 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
3016 if (wpa_supplicant_set_ap_scan(wpa_s, ap_scan)) {
3017 dbus_set_error_const(error, DBUS_ERROR_FAILED,
3018 "ap_scan must be 0, 1, or 2");
3026 * wpas_dbus_getter_fast_reauth - Control fast
3027 * reauthentication (TLS session resumption)
3028 * @iter: Pointer to incoming dbus message iter
3029 * @error: Location to store error on failure
3030 * @user_data: Function specific data
3031 * Returns: TRUE on success, FALSE on failure
3033 * Getter function for "FastReauth" property.
3035 dbus_bool_t wpas_dbus_getter_fast_reauth(
3036 const struct wpa_dbus_property_desc *property_desc,
3037 DBusMessageIter *iter, DBusError *error, void *user_data)
3039 struct wpa_supplicant *wpa_s = user_data;
3040 dbus_bool_t fast_reauth = wpa_s->conf->fast_reauth ? TRUE : FALSE;
3042 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
3043 &fast_reauth, error);
3048 * wpas_dbus_setter_fast_reauth - Control fast
3049 * reauthentication (TLS session resumption)
3050 * @iter: Pointer to incoming dbus message iter
3051 * @error: Location to store error on failure
3052 * @user_data: Function specific data
3053 * Returns: TRUE on success, FALSE on failure
3055 * Setter function for "FastReauth" property.
3057 dbus_bool_t wpas_dbus_setter_fast_reauth(
3058 const struct wpa_dbus_property_desc *property_desc,
3059 DBusMessageIter *iter, DBusError *error, void *user_data)
3061 struct wpa_supplicant *wpa_s = user_data;
3062 dbus_bool_t fast_reauth;
3064 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
3068 wpa_s->conf->fast_reauth = fast_reauth;
3074 * wpas_dbus_getter_disconnect_reason - Get most recent reason for disconnect
3075 * @iter: Pointer to incoming dbus message iter
3076 * @error: Location to store error on failure
3077 * @user_data: Function specific data
3078 * Returns: TRUE on success, FALSE on failure
3080 * Getter for "DisconnectReason" property. The reason is negative if it is
3081 * locally generated.
3083 dbus_bool_t wpas_dbus_getter_disconnect_reason(
3084 const struct wpa_dbus_property_desc *property_desc,
3085 DBusMessageIter *iter, DBusError *error, void *user_data)
3087 struct wpa_supplicant *wpa_s = user_data;
3088 dbus_int32_t reason = wpa_s->disconnect_reason;
3090 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
3096 * wpas_dbus_getter_auth_status_code - Get most recent auth status code
3097 * @iter: Pointer to incoming dbus message iter
3098 * @error: Location to store error on failure
3099 * @user_data: Function specific data
3100 * Returns: TRUE on success, FALSE on failure
3102 * Getter for "AuthStatusCode" property.
3104 dbus_bool_t wpas_dbus_getter_auth_status_code(
3105 const struct wpa_dbus_property_desc *property_desc,
3106 DBusMessageIter *iter, DBusError *error, void *user_data)
3108 struct wpa_supplicant *wpa_s = user_data;
3109 dbus_int32_t reason = wpa_s->auth_status_code;
3111 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
3117 * wpas_dbus_getter_assoc_status_code - Get most recent failed assoc status code
3118 * @iter: Pointer to incoming dbus message iter
3119 * @error: Location to store error on failure
3120 * @user_data: Function specific data
3121 * Returns: TRUE on success, FALSE on failure
3123 * Getter for "AssocStatusCode" property.
3125 dbus_bool_t wpas_dbus_getter_assoc_status_code(
3126 const struct wpa_dbus_property_desc *property_desc,
3127 DBusMessageIter *iter, DBusError *error, void *user_data)
3129 struct wpa_supplicant *wpa_s = user_data;
3130 dbus_int32_t status_code = wpa_s->assoc_status_code;
3132 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
3133 &status_code, error);
3138 * wpas_dbus_getter_roam_time - Get most recent roam time
3139 * @iter: Pointer to incoming dbus message iter
3140 * @error: Location to store error on failure
3141 * @user_data: Function specific data
3142 * Returns: TRUE on success, FALSE on failure
3144 * Getter for "RoamTime" property.
3146 dbus_bool_t wpas_dbus_getter_roam_time(
3147 const struct wpa_dbus_property_desc *property_desc,
3148 DBusMessageIter *iter, DBusError *error, void *user_data)
3150 struct wpa_supplicant *wpa_s = user_data;
3151 dbus_uint32_t roam_time = wpa_s->roam_time.sec * 1000 +
3152 wpa_s->roam_time.usec / 1000;
3154 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
3160 * wpas_dbus_getter_roam_complete - Get most recent roam success or failure
3161 * @iter: Pointer to incoming dbus message iter
3162 * @error: Location to store error on failure
3163 * @user_data: Function specific data
3164 * Returns: TRUE on success, FALSE on failure
3166 * Getter for "RoamComplete" property.
3168 dbus_bool_t wpas_dbus_getter_roam_complete(
3169 const struct wpa_dbus_property_desc *property_desc,
3170 DBusMessageIter *iter, DBusError *error, void *user_data)
3172 struct wpa_supplicant *wpa_s = user_data;
3173 dbus_bool_t roam_complete = os_reltime_initialized(&wpa_s->roam_time);
3175 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
3176 &roam_complete, error);
3181 * wpas_dbus_getter_session_length - Get most recent BSS session length
3182 * @iter: Pointer to incoming dbus message iter
3183 * @error: Location to store error on failure
3184 * @user_data: Function specific data
3185 * Returns: TRUE on success, FALSE on failure
3187 * Getter for "SessionLength" property.
3189 dbus_bool_t wpas_dbus_getter_session_length(
3190 const struct wpa_dbus_property_desc *property_desc,
3191 DBusMessageIter *iter, DBusError *error, void *user_data)
3193 struct wpa_supplicant *wpa_s = user_data;
3194 dbus_uint32_t session_length = wpa_s->session_length.sec * 1000 +
3195 wpa_s->session_length.usec / 1000;
3197 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
3198 &session_length, error);
3203 * wpas_dbus_getter_bss_tm_status - Get most BSS Transition Management request
3205 * @iter: Pointer to incoming dbus message iter
3206 * @error: Location to store error on failure
3207 * @user_data: Function specific data
3208 * Returns: TRUE on success, FALSE on failure
3210 * Getter for "BSSTMStatus" property.
3212 dbus_bool_t wpas_dbus_getter_bss_tm_status(
3213 const struct wpa_dbus_property_desc *property_desc,
3214 DBusMessageIter *iter, DBusError *error, void *user_data)
3217 struct wpa_supplicant *wpa_s = user_data;
3218 dbus_uint32_t bss_tm_status = wpa_s->bss_tm_status;
3219 #else /* CONFIG_WNM */
3220 dbus_uint32_t bss_tm_status = 0;
3221 #endif /* CONFIG_WNM */
3223 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
3224 &bss_tm_status, error);
3229 * wpas_dbus_getter_bss_expire_age - Get BSS entry expiration age
3230 * @iter: Pointer to incoming dbus message iter
3231 * @error: Location to store error on failure
3232 * @user_data: Function specific data
3233 * Returns: TRUE on success, FALSE on failure
3235 * Getter function for "BSSExpireAge" property.
3237 dbus_bool_t wpas_dbus_getter_bss_expire_age(
3238 const struct wpa_dbus_property_desc *property_desc,
3239 DBusMessageIter *iter, DBusError *error, void *user_data)
3241 struct wpa_supplicant *wpa_s = user_data;
3242 dbus_uint32_t expire_age = wpa_s->conf->bss_expiration_age;
3244 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
3245 &expire_age, error);
3250 * wpas_dbus_setter_bss_expire_age - Control BSS entry expiration age
3251 * @iter: Pointer to incoming dbus message iter
3252 * @error: Location to store error on failure
3253 * @user_data: Function specific data
3254 * Returns: TRUE on success, FALSE on failure
3256 * Setter function for "BSSExpireAge" property.
3258 dbus_bool_t wpas_dbus_setter_bss_expire_age(
3259 const struct wpa_dbus_property_desc *property_desc,
3260 DBusMessageIter *iter, DBusError *error, void *user_data)
3262 struct wpa_supplicant *wpa_s = user_data;
3263 dbus_uint32_t expire_age;
3265 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
3269 if (wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age)) {
3270 dbus_set_error_const(error, DBUS_ERROR_FAILED,
3271 "BSSExpireAge must be >= 10");
3279 * wpas_dbus_getter_bss_expire_count - Get BSS entry expiration scan count
3280 * @iter: Pointer to incoming dbus message iter
3281 * @error: Location to store error on failure
3282 * @user_data: Function specific data
3283 * Returns: TRUE on success, FALSE on failure
3285 * Getter function for "BSSExpireCount" property.
3287 dbus_bool_t wpas_dbus_getter_bss_expire_count(
3288 const struct wpa_dbus_property_desc *property_desc,
3289 DBusMessageIter *iter, DBusError *error, void *user_data)
3291 struct wpa_supplicant *wpa_s = user_data;
3292 dbus_uint32_t expire_count = wpa_s->conf->bss_expiration_scan_count;
3294 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
3295 &expire_count, error);
3300 * wpas_dbus_setter_bss_expire_count - Control BSS entry expiration scan count
3301 * @iter: Pointer to incoming dbus message iter
3302 * @error: Location to store error on failure
3303 * @user_data: Function specific data
3304 * Returns: TRUE on success, FALSE on failure
3306 * Setter function for "BSSExpireCount" property.
3308 dbus_bool_t wpas_dbus_setter_bss_expire_count(
3309 const struct wpa_dbus_property_desc *property_desc,
3310 DBusMessageIter *iter, DBusError *error, void *user_data)
3312 struct wpa_supplicant *wpa_s = user_data;
3313 dbus_uint32_t expire_count;
3315 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
3319 if (wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count)) {
3320 dbus_set_error_const(error, DBUS_ERROR_FAILED,
3321 "BSSExpireCount must be > 0");
3329 * wpas_dbus_getter_country - Control country code
3330 * @iter: Pointer to incoming dbus message iter
3331 * @error: Location to store error on failure
3332 * @user_data: Function specific data
3333 * Returns: TRUE on success, FALSE on failure
3335 * Getter function for "Country" property.
3337 dbus_bool_t wpas_dbus_getter_country(
3338 const struct wpa_dbus_property_desc *property_desc,
3339 DBusMessageIter *iter, DBusError *error, void *user_data)
3341 struct wpa_supplicant *wpa_s = user_data;
3343 char *str = country;
3345 country[0] = wpa_s->conf->country[0];
3346 country[1] = wpa_s->conf->country[1];
3349 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3355 * wpas_dbus_setter_country - Control country code
3356 * @iter: Pointer to incoming dbus message iter
3357 * @error: Location to store error on failure
3358 * @user_data: Function specific data
3359 * Returns: TRUE on success, FALSE on failure
3361 * Setter function for "Country" property.
3363 dbus_bool_t wpas_dbus_setter_country(
3364 const struct wpa_dbus_property_desc *property_desc,
3365 DBusMessageIter *iter, DBusError *error, void *user_data)
3367 struct wpa_supplicant *wpa_s = user_data;
3368 const char *country;
3370 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
3374 if (!country[0] || !country[1]) {
3375 dbus_set_error_const(error, DBUS_ERROR_FAILED,
3376 "invalid country code");
3380 if (wpa_s->drv_priv != NULL && wpa_drv_set_country(wpa_s, country)) {
3381 wpa_printf(MSG_DEBUG, "Failed to set country");
3382 dbus_set_error_const(error, DBUS_ERROR_FAILED,
3383 "failed to set country code");
3387 wpa_s->conf->country[0] = country[0];
3388 wpa_s->conf->country[1] = country[1];
3394 * wpas_dbus_getter_scan_interval - Get scan interval
3395 * @iter: Pointer to incoming dbus message iter
3396 * @error: Location to store error on failure
3397 * @user_data: Function specific data
3398 * Returns: TRUE on success, FALSE on failure
3400 * Getter function for "ScanInterval" property.
3402 dbus_bool_t wpas_dbus_getter_scan_interval(
3403 const struct wpa_dbus_property_desc *property_desc,
3404 DBusMessageIter *iter, DBusError *error, void *user_data)
3406 struct wpa_supplicant *wpa_s = user_data;
3407 dbus_int32_t scan_interval = wpa_s->scan_interval;
3409 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
3410 &scan_interval, error);
3415 * wpas_dbus_setter_scan_interval - Control scan interval
3416 * @iter: Pointer to incoming dbus message iter
3417 * @error: Location to store error on failure
3418 * @user_data: Function specific data
3419 * Returns: TRUE on success, FALSE on failure
3421 * Setter function for "ScanInterval" property.
3423 dbus_bool_t wpas_dbus_setter_scan_interval(
3424 const struct wpa_dbus_property_desc *property_desc,
3425 DBusMessageIter *iter, DBusError *error, void *user_data)
3427 struct wpa_supplicant *wpa_s = user_data;
3428 dbus_int32_t scan_interval;
3430 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_INT32,
3434 if (wpa_supplicant_set_scan_interval(wpa_s, scan_interval)) {
3435 dbus_set_error_const(error, DBUS_ERROR_FAILED,
3436 "scan_interval must be >= 0");
3444 * wpas_dbus_getter_ifname - Get interface name
3445 * @iter: Pointer to incoming dbus message iter
3446 * @error: Location to store error on failure
3447 * @user_data: Function specific data
3448 * Returns: TRUE on success, FALSE on failure
3450 * Getter for "Ifname" property.
3452 dbus_bool_t wpas_dbus_getter_ifname(
3453 const struct wpa_dbus_property_desc *property_desc,
3454 DBusMessageIter *iter, DBusError *error, void *user_data)
3456 struct wpa_supplicant *wpa_s = user_data;
3458 return wpas_dbus_string_property_getter(iter, wpa_s->ifname, error);
3463 * wpas_dbus_getter_driver - Get interface name
3464 * @iter: Pointer to incoming dbus message iter
3465 * @error: Location to store error on failure
3466 * @user_data: Function specific data
3467 * Returns: TRUE on success, FALSE on failure
3469 * Getter for "Driver" property.
3471 dbus_bool_t wpas_dbus_getter_driver(
3472 const struct wpa_dbus_property_desc *property_desc,
3473 DBusMessageIter *iter, DBusError *error, void *user_data)
3475 struct wpa_supplicant *wpa_s = user_data;
3477 if (wpa_s->driver == NULL || wpa_s->driver->name == NULL) {
3478 wpa_printf(MSG_DEBUG, "%s[dbus]: wpa_s has no driver set",
3480 dbus_set_error(error, DBUS_ERROR_FAILED, "%s: no driver set",
3485 return wpas_dbus_string_property_getter(iter, wpa_s->driver->name,
3491 * wpas_dbus_getter_current_bss - Get current bss object path
3492 * @iter: Pointer to incoming dbus message iter
3493 * @error: Location to store error on failure
3494 * @user_data: Function specific data
3495 * Returns: TRUE on success, FALSE on failure
3497 * Getter for "CurrentBSS" property.
3499 dbus_bool_t wpas_dbus_getter_current_bss(
3500 const struct wpa_dbus_property_desc *property_desc,
3501 DBusMessageIter *iter, DBusError *error, void *user_data)
3503 struct wpa_supplicant *wpa_s = user_data;
3504 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *bss_obj_path = path_buf;
3506 if (wpa_s->current_bss && wpa_s->dbus_new_path)
3507 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3508 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
3509 wpa_s->dbus_new_path, wpa_s->current_bss->id);
3511 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
3513 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
3514 &bss_obj_path, error);
3519 * wpas_dbus_getter_current_network - Get current network object path
3520 * @iter: Pointer to incoming dbus message iter
3521 * @error: Location to store error on failure
3522 * @user_data: Function specific data
3523 * Returns: TRUE on success, FALSE on failure
3525 * Getter for "CurrentNetwork" property.
3527 dbus_bool_t wpas_dbus_getter_current_network(
3528 const struct wpa_dbus_property_desc *property_desc,
3529 DBusMessageIter *iter, DBusError *error, void *user_data)
3531 struct wpa_supplicant *wpa_s = user_data;
3532 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *net_obj_path = path_buf;
3534 if (wpa_s->current_ssid && wpa_s->dbus_new_path)
3535 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3536 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
3537 wpa_s->dbus_new_path, wpa_s->current_ssid->id);
3539 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
3541 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
3542 &net_obj_path, error);
3547 * wpas_dbus_getter_current_auth_mode - Get current authentication type
3548 * @iter: Pointer to incoming dbus message iter
3549 * @error: Location to store error on failure
3550 * @user_data: Function specific data
3551 * Returns: TRUE on success, FALSE on failure
3553 * Getter for "CurrentAuthMode" property.
3555 dbus_bool_t wpas_dbus_getter_current_auth_mode(
3556 const struct wpa_dbus_property_desc *property_desc,
3557 DBusMessageIter *iter, DBusError *error, void *user_data)
3559 struct wpa_supplicant *wpa_s = user_data;
3560 const char *eap_mode;
3561 const char *auth_mode;
3562 char eap_mode_buf[WPAS_DBUS_AUTH_MODE_MAX];
3564 if (wpa_s->wpa_state != WPA_COMPLETED) {
3565 auth_mode = "INACTIVE";
3566 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X ||
3567 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3568 eap_mode = wpa_supplicant_get_eap_mode(wpa_s);
3569 os_snprintf(eap_mode_buf, WPAS_DBUS_AUTH_MODE_MAX,
3570 "EAP-%s", eap_mode);
3571 auth_mode = eap_mode_buf;
3573 } else if (wpa_s->current_ssid) {
3574 auth_mode = wpa_key_mgmt_txt(wpa_s->key_mgmt,
3575 wpa_s->current_ssid->proto);
3577 auth_mode = "UNKNOWN";
3580 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3586 * wpas_dbus_getter_bridge_ifname - Get interface name
3587 * @iter: Pointer to incoming dbus message iter
3588 * @error: Location to store error on failure
3589 * @user_data: Function specific data
3590 * Returns: TRUE on success, FALSE on failure
3592 * Getter for "BridgeIfname" property.
3594 dbus_bool_t wpas_dbus_getter_bridge_ifname(
3595 const struct wpa_dbus_property_desc *property_desc,
3596 DBusMessageIter *iter, DBusError *error, void *user_data)
3598 struct wpa_supplicant *wpa_s = user_data;
3600 return wpas_dbus_string_property_getter(iter, wpa_s->bridge_ifname,
3606 * wpas_dbus_getter_config_file - Get interface configuration file path
3607 * @iter: Pointer to incoming dbus message iter
3608 * @error: Location to store error on failure
3609 * @user_data: Function specific data
3610 * Returns: TRUE on success, FALSE on failure
3612 * Getter for "ConfigFile" property.
3614 dbus_bool_t wpas_dbus_getter_config_file(
3615 const struct wpa_dbus_property_desc *property_desc,
3616 DBusMessageIter *iter, DBusError *error, void *user_data)
3618 struct wpa_supplicant *wpa_s = user_data;
3620 return wpas_dbus_string_property_getter(iter, wpa_s->confname, error);
3625 * wpas_dbus_getter_bsss - Get array of BSSs objects
3626 * @iter: Pointer to incoming dbus message iter
3627 * @error: Location to store error on failure
3628 * @user_data: Function specific data
3629 * Returns: TRUE on success, FALSE on failure
3631 * Getter for "BSSs" property.
3633 dbus_bool_t wpas_dbus_getter_bsss(
3634 const struct wpa_dbus_property_desc *property_desc,
3635 DBusMessageIter *iter, DBusError *error, void *user_data)
3637 struct wpa_supplicant *wpa_s = user_data;
3638 struct wpa_bss *bss;
3641 dbus_bool_t success = FALSE;
3643 if (!wpa_s->dbus_new_path) {
3644 dbus_set_error(error, DBUS_ERROR_FAILED,
3645 "%s: no D-Bus interface", __func__);
3649 paths = os_calloc(wpa_s->num_bss, sizeof(char *));
3651 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3655 /* Loop through scan results and append each result's object path */
3656 dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
3657 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
3658 if (paths[i] == NULL) {
3659 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
3663 /* Construct the object path for this BSS. */
3664 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
3665 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
3666 wpa_s->dbus_new_path, bss->id);
3669 success = wpas_dbus_simple_array_property_getter(iter,
3670 DBUS_TYPE_OBJECT_PATH,
3671 paths, wpa_s->num_bss,
3676 os_free(paths[--i]);
3683 * wpas_dbus_getter_networks - Get array of networks objects
3684 * @iter: Pointer to incoming dbus message iter
3685 * @error: Location to store error on failure
3686 * @user_data: Function specific data
3687 * Returns: TRUE on success, FALSE on failure
3689 * Getter for "Networks" property.
3691 dbus_bool_t wpas_dbus_getter_networks(
3692 const struct wpa_dbus_property_desc *property_desc,
3693 DBusMessageIter *iter, DBusError *error, void *user_data)
3695 struct wpa_supplicant *wpa_s = user_data;
3696 struct wpa_ssid *ssid;
3698 unsigned int i = 0, num = 0;
3699 dbus_bool_t success = FALSE;
3701 if (!wpa_s->dbus_new_path) {
3702 dbus_set_error(error, DBUS_ERROR_FAILED,
3703 "%s: no D-Bus interface", __func__);
3707 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
3708 if (!network_is_persistent_group(ssid))
3711 paths = os_calloc(num, sizeof(char *));
3713 dbus_set_error(error, DBUS_ERROR_NO_MEMORY, "no memory");
3717 /* Loop through configured networks and append object path of each */
3718 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
3719 if (network_is_persistent_group(ssid))
3721 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
3722 if (paths[i] == NULL) {
3723 dbus_set_error(error, DBUS_ERROR_NO_MEMORY,
3728 /* Construct the object path for this network. */
3729 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
3730 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
3731 wpa_s->dbus_new_path, ssid->id);
3734 success = wpas_dbus_simple_array_property_getter(iter,
3735 DBUS_TYPE_OBJECT_PATH,
3740 os_free(paths[--i]);
3747 * wpas_dbus_getter_pkcs11_engine_path - Get PKCS #11 engine path
3748 * @iter: Pointer to incoming dbus message iter
3749 * @error: Location to store error on failure
3750 * @user_data: Function specific data
3751 * Returns: A dbus message containing the PKCS #11 engine path
3753 * Getter for "PKCS11EnginePath" property.
3755 dbus_bool_t wpas_dbus_getter_pkcs11_engine_path(
3756 const struct wpa_dbus_property_desc *property_desc,
3757 DBusMessageIter *iter, DBusError *error, void *user_data)
3759 struct wpa_supplicant *wpa_s = user_data;
3761 return wpas_dbus_string_property_getter(iter,
3762 wpa_s->conf->pkcs11_engine_path,
3768 * wpas_dbus_getter_pkcs11_module_path - Get PKCS #11 module path
3769 * @iter: Pointer to incoming dbus message iter
3770 * @error: Location to store error on failure
3771 * @user_data: Function specific data
3772 * Returns: A dbus message containing the PKCS #11 module path
3774 * Getter for "PKCS11ModulePath" property.
3776 dbus_bool_t wpas_dbus_getter_pkcs11_module_path(
3777 const struct wpa_dbus_property_desc *property_desc,
3778 DBusMessageIter *iter, DBusError *error, void *user_data)
3780 struct wpa_supplicant *wpa_s = user_data;
3782 return wpas_dbus_string_property_getter(iter,
3783 wpa_s->conf->pkcs11_module_path,
3789 * wpas_dbus_getter_blobs - Get all blobs defined for this interface
3790 * @iter: Pointer to incoming dbus message iter
3791 * @error: Location to store error on failure
3792 * @user_data: Function specific data
3793 * Returns: TRUE on success, FALSE on failure
3795 * Getter for "Blobs" property.
3797 dbus_bool_t wpas_dbus_getter_blobs(
3798 const struct wpa_dbus_property_desc *property_desc,
3799 DBusMessageIter *iter, DBusError *error, void *user_data)
3801 struct wpa_supplicant *wpa_s = user_data;
3802 DBusMessageIter variant_iter, dict_iter, entry_iter, array_iter;
3803 struct wpa_config_blob *blob;
3805 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
3806 "a{say}", &variant_iter) ||
3807 !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
3808 "{say}", &dict_iter)) {
3809 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3813 blob = wpa_s->conf->blobs;
3815 if (!dbus_message_iter_open_container(&dict_iter,
3816 DBUS_TYPE_DICT_ENTRY,
3817 NULL, &entry_iter) ||
3818 !dbus_message_iter_append_basic(&entry_iter,
3821 !dbus_message_iter_open_container(&entry_iter,
3823 DBUS_TYPE_BYTE_AS_STRING,
3825 !dbus_message_iter_append_fixed_array(&array_iter,
3829 !dbus_message_iter_close_container(&entry_iter,
3831 !dbus_message_iter_close_container(&dict_iter,
3833 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
3841 if (!dbus_message_iter_close_container(&variant_iter, &dict_iter) ||
3842 !dbus_message_iter_close_container(iter, &variant_iter)) {
3843 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3851 dbus_bool_t wpas_dbus_getter_iface_global(
3852 const struct wpa_dbus_property_desc *property_desc,
3853 DBusMessageIter *iter, DBusError *error, void *user_data)
3855 struct wpa_supplicant *wpa_s = user_data;
3860 if (!property_desc->data) {
3861 dbus_set_error(error, DBUS_ERROR_INVALID_ARGS,
3862 "Unhandled interface property %s",
3863 property_desc->dbus_property);
3867 ret = wpa_config_get_value(property_desc->data, wpa_s->conf, buf,
3872 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &p,
3877 dbus_bool_t wpas_dbus_setter_iface_global(
3878 const struct wpa_dbus_property_desc *property_desc,
3879 DBusMessageIter *iter, DBusError *error, void *user_data)
3881 struct wpa_supplicant *wpa_s = user_data;
3882 const char *new_value = NULL;
3884 size_t combined_len;
3887 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
3891 combined_len = os_strlen(property_desc->data) + os_strlen(new_value) +
3893 if (combined_len >= sizeof(buf)) {
3894 dbus_set_error(error, DBUS_ERROR_INVALID_ARGS,
3895 "Interface property %s value too large",
3896 property_desc->dbus_property);
3903 ret = os_snprintf(buf, combined_len, "%s=%s", property_desc->data,
3905 if (os_snprintf_error(combined_len, ret)) {
3906 dbus_set_error(error, WPAS_DBUS_ERROR_UNKNOWN_ERROR,
3907 "Failed to construct new interface property %s",
3908 property_desc->dbus_property);
3912 if (wpa_config_process_global(wpa_s->conf, buf, -1)) {
3913 dbus_set_error(error, DBUS_ERROR_INVALID_ARGS,
3914 "Failed to set interface property %s",
3915 property_desc->dbus_property);
3919 wpa_supplicant_update_config(wpa_s);
3925 * wpas_dbus_getter_stas - Get connected stations for an interface
3926 * @iter: Pointer to incoming dbus message iter
3927 * @error: Location to store error on failure
3928 * @user_data: Function specific data
3929 * Returns: a list of stations
3931 * Getter for "Stations" property.
3933 dbus_bool_t wpas_dbus_getter_stas(
3934 const struct wpa_dbus_property_desc *property_desc,
3935 DBusMessageIter *iter, DBusError *error, void *user_data)
3937 struct wpa_supplicant *wpa_s = user_data;
3938 struct sta_info *sta = NULL;
3939 char **paths = NULL;
3940 unsigned int i = 0, num = 0;
3941 dbus_bool_t success = FALSE;
3943 if (!wpa_s->dbus_new_path) {
3944 dbus_set_error(error, DBUS_ERROR_FAILED,
3945 "%s: no D-Bus interface", __func__);
3950 if (wpa_s->ap_iface) {
3951 struct hostapd_data *hapd;
3953 hapd = wpa_s->ap_iface->bss[0];
3954 sta = hapd->sta_list;
3955 num = hapd->num_sta;
3957 #endif /* CONFIG_AP */
3959 paths = os_calloc(num, sizeof(char *));
3961 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3965 /* Loop through scan results and append each result's object path */
3966 for (; sta; sta = sta->next) {
3967 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
3969 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
3973 /* Construct the object path for this BSS. */
3974 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
3975 "%s/" WPAS_DBUS_NEW_STAS_PART "/" COMPACT_MACSTR,
3976 wpa_s->dbus_new_path, MAC2STR(sta->addr));
3979 success = wpas_dbus_simple_array_property_getter(iter,
3980 DBUS_TYPE_OBJECT_PATH,
3986 os_free(paths[--i]);
3993 * wpas_dbus_getter_sta_address - Return the address of a connected station
3994 * @iter: Pointer to incoming dbus message iter
3995 * @error: Location to store error on failure
3996 * @user_data: Function specific data
3997 * Returns: TRUE on success, FALSE on failure
3999 * Getter for "Address" property.
4001 dbus_bool_t wpas_dbus_getter_sta_address(
4002 const struct wpa_dbus_property_desc *property_desc,
4003 DBusMessageIter *iter, DBusError *error, void *user_data)
4006 struct sta_handler_args *args = user_data;
4007 struct sta_info *sta;
4009 sta = ap_get_sta(args->wpa_s->ap_iface->bss[0], args->sta);
4013 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
4014 sta->addr, ETH_ALEN,
4016 #else /* CONFIG_AP */
4018 #endif /* CONFIG_AP */
4023 * wpas_dbus_getter_sta_aid - Return the AID of a connected station
4024 * @iter: Pointer to incoming dbus message iter
4025 * @error: Location to store error on failure
4026 * @user_data: Function specific data
4027 * Returns: TRUE on success, FALSE on failure
4029 * Getter for "AID" property.
4031 dbus_bool_t wpas_dbus_getter_sta_aid(
4032 const struct wpa_dbus_property_desc *property_desc,
4033 DBusMessageIter *iter, DBusError *error, void *user_data)
4036 struct sta_handler_args *args = user_data;
4037 struct sta_info *sta;
4039 sta = ap_get_sta(args->wpa_s->ap_iface->bss[0], args->sta);
4043 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
4046 #else /* CONFIG_AP */
4048 #endif /* CONFIG_AP */
4053 * wpas_dbus_getter_sta_caps - Return the capabilities of a station
4054 * @iter: Pointer to incoming dbus message iter
4055 * @error: Location to store error on failure
4056 * @user_data: Function specific data
4057 * Returns: TRUE on success, FALSE on failure
4059 * Getter for "Capabilities" property.
4061 dbus_bool_t wpas_dbus_getter_sta_caps(
4062 const struct wpa_dbus_property_desc *property_desc,
4063 DBusMessageIter *iter, DBusError *error, void *user_data)
4066 struct sta_handler_args *args = user_data;
4067 struct sta_info *sta;
4069 sta = ap_get_sta(args->wpa_s->ap_iface->bss[0], args->sta);
4073 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
4076 #else /* CONFIG_AP */
4078 #endif /* CONFIG_AP */
4083 * wpas_dbus_getter_rx_packets - Return the received packets for a station
4084 * @iter: Pointer to incoming dbus message iter
4085 * @error: Location to store error on failure
4086 * @user_data: Function specific data
4087 * Returns: TRUE on success, FALSE on failure
4089 * Getter for "RxPackets" property.
4091 dbus_bool_t wpas_dbus_getter_sta_rx_packets(
4092 const struct wpa_dbus_property_desc *property_desc,
4093 DBusMessageIter *iter, DBusError *error, void *user_data)
4096 struct sta_handler_args *args = user_data;
4097 struct sta_info *sta;
4098 struct hostap_sta_driver_data data;
4099 struct hostapd_data *hapd;
4101 if (!args->wpa_s->ap_iface)
4104 hapd = args->wpa_s->ap_iface->bss[0];
4105 sta = ap_get_sta(hapd, args->sta);
4109 if (hostapd_drv_read_sta_data(hapd, &data, sta->addr) < 0)
4112 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT64,
4115 #else /* CONFIG_AP */
4117 #endif /* CONFIG_AP */
4122 * wpas_dbus_getter_tx_packets - Return the transmitted packets for a station
4123 * @iter: Pointer to incoming dbus message iter
4124 * @error: Location to store error on failure
4125 * @user_data: Function specific data
4126 * Returns: TRUE on success, FALSE on failure
4128 * Getter for "TxPackets" property.
4130 dbus_bool_t wpas_dbus_getter_sta_tx_packets(
4131 const struct wpa_dbus_property_desc *property_desc,
4132 DBusMessageIter *iter, DBusError *error, void *user_data)
4135 struct sta_handler_args *args = user_data;
4136 struct sta_info *sta;
4137 struct hostap_sta_driver_data data;
4138 struct hostapd_data *hapd;
4140 if (!args->wpa_s->ap_iface)
4143 hapd = args->wpa_s->ap_iface->bss[0];
4144 sta = ap_get_sta(hapd, args->sta);
4148 if (hostapd_drv_read_sta_data(hapd, &data, sta->addr) < 0)
4151 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT64,
4154 #else /* CONFIG_AP */
4156 #endif /* CONFIG_AP */
4161 * wpas_dbus_getter_tx_bytes - Return the transmitted bytes for a station
4162 * @iter: Pointer to incoming dbus message iter
4163 * @error: Location to store error on failure
4164 * @user_data: Function specific data
4165 * Returns: TRUE on success, FALSE on failure
4167 * Getter for "TxBytes" property.
4169 dbus_bool_t wpas_dbus_getter_sta_tx_bytes(
4170 const struct wpa_dbus_property_desc *property_desc,
4171 DBusMessageIter *iter, DBusError *error, void *user_data)
4174 struct sta_handler_args *args = user_data;
4175 struct sta_info *sta;
4176 struct hostap_sta_driver_data data;
4177 struct hostapd_data *hapd;
4179 if (!args->wpa_s->ap_iface)
4182 hapd = args->wpa_s->ap_iface->bss[0];
4183 sta = ap_get_sta(hapd, args->sta);
4187 if (hostapd_drv_read_sta_data(hapd, &data, sta->addr) < 0)
4190 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT64,
4193 #else /* CONFIG_AP */
4195 #endif /* CONFIG_AP */
4200 * wpas_dbus_getter_rx_bytes - Return the received bytes for a station
4201 * @iter: Pointer to incoming dbus message iter
4202 * @error: Location to store error on failure
4203 * @user_data: Function specific data
4204 * Returns: TRUE on success, FALSE on failure
4206 * Getter for "RxBytes" property.
4208 dbus_bool_t wpas_dbus_getter_sta_rx_bytes(
4209 const struct wpa_dbus_property_desc *property_desc,
4210 DBusMessageIter *iter, DBusError *error, void *user_data)
4213 struct sta_handler_args *args = user_data;
4214 struct sta_info *sta;
4215 struct hostap_sta_driver_data data;
4216 struct hostapd_data *hapd;
4218 if (!args->wpa_s->ap_iface)
4221 hapd = args->wpa_s->ap_iface->bss[0];
4222 sta = ap_get_sta(hapd, args->sta);
4226 if (hostapd_drv_read_sta_data(hapd, &data, sta->addr) < 0)
4229 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT64,
4232 #else /* CONFIG_AP */
4234 #endif /* CONFIG_AP */
4238 static struct wpa_bss * get_bss_helper(struct bss_handler_args *args,
4239 DBusError *error, const char *func_name)
4241 struct wpa_bss *res = wpa_bss_get_id(args->wpa_s, args->id);
4244 wpa_printf(MSG_ERROR, "%s[dbus]: no bss with id %d found",
4245 func_name, args->id);
4246 dbus_set_error(error, DBUS_ERROR_FAILED,
4247 "%s: BSS %d not found",
4248 func_name, args->id);
4256 * wpas_dbus_getter_bss_bssid - Return the BSSID of a BSS
4257 * @iter: Pointer to incoming dbus message iter
4258 * @error: Location to store error on failure
4259 * @user_data: Function specific data
4260 * Returns: TRUE on success, FALSE on failure
4262 * Getter for "BSSID" property.
4264 dbus_bool_t wpas_dbus_getter_bss_bssid(
4265 const struct wpa_dbus_property_desc *property_desc,
4266 DBusMessageIter *iter, DBusError *error, void *user_data)
4268 struct bss_handler_args *args = user_data;
4269 struct wpa_bss *res;
4271 res = get_bss_helper(args, error, __func__);
4275 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
4276 res->bssid, ETH_ALEN,
4282 * wpas_dbus_getter_bss_ssid - Return the SSID of a BSS
4283 * @iter: Pointer to incoming dbus message iter
4284 * @error: Location to store error on failure
4285 * @user_data: Function specific data
4286 * Returns: TRUE on success, FALSE on failure
4288 * Getter for "SSID" property.
4290 dbus_bool_t wpas_dbus_getter_bss_ssid(
4291 const struct wpa_dbus_property_desc *property_desc,
4292 DBusMessageIter *iter, DBusError *error, void *user_data)
4294 struct bss_handler_args *args = user_data;
4295 struct wpa_bss *res;
4297 res = get_bss_helper(args, error, __func__);
4301 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
4302 res->ssid, res->ssid_len,
4308 * wpas_dbus_getter_bss_privacy - Return the privacy flag of a BSS
4309 * @iter: Pointer to incoming dbus message iter
4310 * @error: Location to store error on failure
4311 * @user_data: Function specific data
4312 * Returns: TRUE on success, FALSE on failure
4314 * Getter for "Privacy" property.
4316 dbus_bool_t wpas_dbus_getter_bss_privacy(
4317 const struct wpa_dbus_property_desc *property_desc,
4318 DBusMessageIter *iter, DBusError *error, void *user_data)
4320 struct bss_handler_args *args = user_data;
4321 struct wpa_bss *res;
4322 dbus_bool_t privacy;
4324 res = get_bss_helper(args, error, __func__);
4328 privacy = (res->caps & IEEE80211_CAP_PRIVACY) ? TRUE : FALSE;
4329 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
4335 * wpas_dbus_getter_bss_mode - Return the mode of a BSS
4336 * @iter: Pointer to incoming dbus message iter
4337 * @error: Location to store error on failure
4338 * @user_data: Function specific data
4339 * Returns: TRUE on success, FALSE on failure
4341 * Getter for "Mode" property.
4343 dbus_bool_t wpas_dbus_getter_bss_mode(
4344 const struct wpa_dbus_property_desc *property_desc,
4345 DBusMessageIter *iter, DBusError *error, void *user_data)
4347 struct bss_handler_args *args = user_data;
4348 struct wpa_bss *res;
4352 res = get_bss_helper(args, error, __func__);
4355 if (bss_is_dmg(res)) {
4356 switch (res->caps & IEEE80211_CAP_DMG_MASK) {
4357 case IEEE80211_CAP_DMG_PBSS:
4358 case IEEE80211_CAP_DMG_IBSS:
4361 case IEEE80211_CAP_DMG_AP:
4362 mode = "infrastructure";
4369 mesh = wpa_bss_get_ie(res, WLAN_EID_MESH_ID);
4372 else if (res->caps & IEEE80211_CAP_IBSS)
4375 mode = "infrastructure";
4378 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
4384 * wpas_dbus_getter_bss_level - Return the signal strength of a BSS
4385 * @iter: Pointer to incoming dbus message iter
4386 * @error: Location to store error on failure
4387 * @user_data: Function specific data
4388 * Returns: TRUE on success, FALSE on failure
4390 * Getter for "Level" property.
4392 dbus_bool_t wpas_dbus_getter_bss_signal(
4393 const struct wpa_dbus_property_desc *property_desc,
4394 DBusMessageIter *iter, DBusError *error, void *user_data)
4396 struct bss_handler_args *args = user_data;
4397 struct wpa_bss *res;
4400 res = get_bss_helper(args, error, __func__);
4404 level = (s16) res->level;
4405 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT16,
4411 * wpas_dbus_getter_bss_frequency - Return the frequency of a BSS
4412 * @iter: Pointer to incoming dbus message iter
4413 * @error: Location to store error on failure
4414 * @user_data: Function specific data
4415 * Returns: TRUE on success, FALSE on failure
4417 * Getter for "Frequency" property.
4419 dbus_bool_t wpas_dbus_getter_bss_frequency(
4420 const struct wpa_dbus_property_desc *property_desc,
4421 DBusMessageIter *iter, DBusError *error, void *user_data)
4423 struct bss_handler_args *args = user_data;
4424 struct wpa_bss *res;
4427 res = get_bss_helper(args, error, __func__);
4431 freq = (u16) res->freq;
4432 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
4437 static int cmp_u8s_desc(const void *a, const void *b)
4439 return (*(u8 *) b - *(u8 *) a);
4444 * wpas_dbus_getter_bss_rates - Return available bit rates of a BSS
4445 * @iter: Pointer to incoming dbus message iter
4446 * @error: Location to store error on failure
4447 * @user_data: Function specific data
4448 * Returns: TRUE on success, FALSE on failure
4450 * Getter for "Rates" property.
4452 dbus_bool_t wpas_dbus_getter_bss_rates(
4453 const struct wpa_dbus_property_desc *property_desc,
4454 DBusMessageIter *iter, DBusError *error, void *user_data)
4456 struct bss_handler_args *args = user_data;
4457 struct wpa_bss *res;
4458 u8 *ie_rates = NULL;
4461 dbus_bool_t success = FALSE;
4463 res = get_bss_helper(args, error, __func__);
4467 rates_num = wpa_bss_get_bit_rates(res, &ie_rates);
4471 qsort(ie_rates, rates_num, 1, cmp_u8s_desc);
4473 real_rates = os_malloc(sizeof(u32) * rates_num);
4476 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
4480 for (i = 0; i < rates_num; i++)
4481 real_rates[i] = ie_rates[i] * 500000;
4483 success = wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_UINT32,
4484 real_rates, rates_num,
4488 os_free(real_rates);
4493 static dbus_bool_t wpas_dbus_get_bss_security_prop(
4494 const struct wpa_dbus_property_desc *property_desc,
4495 DBusMessageIter *iter, struct wpa_ie_data *ie_data, DBusError *error)
4497 DBusMessageIter iter_dict, variant_iter;
4499 const char *pairwise[5]; /* max 5 pairwise ciphers is supported */
4500 const char *key_mgmt[15]; /* max 15 key managements may be supported */
4503 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
4504 "a{sv}", &variant_iter))
4507 if (!wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
4513 * When adding a new entry here, please take care to extend key_mgmt[]
4514 * and keep documentation in doc/dbus.doxygen up to date.
4517 if (ie_data->key_mgmt & WPA_KEY_MGMT_PSK)
4518 key_mgmt[n++] = "wpa-psk";
4519 if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_PSK)
4520 key_mgmt[n++] = "wpa-ft-psk";
4521 if (ie_data->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
4522 key_mgmt[n++] = "wpa-psk-sha256";
4523 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X)
4524 key_mgmt[n++] = "wpa-eap";
4525 if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X)
4526 key_mgmt[n++] = "wpa-ft-eap";
4527 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256)
4528 key_mgmt[n++] = "wpa-eap-sha256";
4529 #ifdef CONFIG_SUITEB
4530 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B)
4531 key_mgmt[n++] = "wpa-eap-suite-b";
4532 #endif /* CONFIG_SUITEB */
4533 #ifdef CONFIG_SUITEB192
4534 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
4535 key_mgmt[n++] = "wpa-eap-suite-b-192";
4536 #endif /* CONFIG_SUITEB192 */
4538 if (ie_data->key_mgmt & WPA_KEY_MGMT_FILS_SHA256)
4539 key_mgmt[n++] = "wpa-fils-sha256";
4540 if (ie_data->key_mgmt & WPA_KEY_MGMT_FILS_SHA384)
4541 key_mgmt[n++] = "wpa-fils-sha384";
4542 if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA256)
4543 key_mgmt[n++] = "wpa-ft-fils-sha256";
4544 if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA384)
4545 key_mgmt[n++] = "wpa-ft-fils-sha384";
4546 #endif /* CONFIG_FILS */
4548 if (ie_data->key_mgmt & WPA_KEY_MGMT_SAE)
4549 key_mgmt[n++] = "sae";
4550 if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_SAE)
4551 key_mgmt[n++] = "ft-sae";
4552 #endif /* CONFIG_SAE */
4553 if (ie_data->key_mgmt & WPA_KEY_MGMT_NONE)
4554 key_mgmt[n++] = "wpa-none";
4556 if (!wpa_dbus_dict_append_string_array(&iter_dict, "KeyMgmt",
4561 switch (ie_data->group_cipher) {
4562 case WPA_CIPHER_WEP40:
4565 case WPA_CIPHER_TKIP:
4568 case WPA_CIPHER_CCMP:
4571 case WPA_CIPHER_GCMP:
4574 case WPA_CIPHER_WEP104:
4577 case WPA_CIPHER_CCMP_256:
4580 case WPA_CIPHER_GCMP_256:
4588 if (!wpa_dbus_dict_append_string(&iter_dict, "Group", group))
4593 if (ie_data->pairwise_cipher & WPA_CIPHER_TKIP)
4594 pairwise[n++] = "tkip";
4595 if (ie_data->pairwise_cipher & WPA_CIPHER_CCMP)
4596 pairwise[n++] = "ccmp";
4597 if (ie_data->pairwise_cipher & WPA_CIPHER_GCMP)
4598 pairwise[n++] = "gcmp";
4599 if (ie_data->pairwise_cipher & WPA_CIPHER_CCMP_256)
4600 pairwise[n++] = "ccmp-256";
4601 if (ie_data->pairwise_cipher & WPA_CIPHER_GCMP_256)
4602 pairwise[n++] = "gcmp-256";
4604 if (!wpa_dbus_dict_append_string_array(&iter_dict, "Pairwise",
4608 /* Management group (RSN only) */
4609 if (ie_data->proto == WPA_PROTO_RSN) {
4610 switch (ie_data->mgmt_group_cipher) {
4611 #ifdef CONFIG_IEEE80211W
4612 case WPA_CIPHER_AES_128_CMAC:
4613 group = "aes128cmac";
4615 #endif /* CONFIG_IEEE80211W */
4621 if (!wpa_dbus_dict_append_string(&iter_dict, "MgmtGroup",
4626 if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict) ||
4627 !dbus_message_iter_close_container(iter, &variant_iter))
4633 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
4639 * wpas_dbus_getter_bss_wpa - Return the WPA options of a BSS
4640 * @iter: Pointer to incoming dbus message iter
4641 * @error: Location to store error on failure
4642 * @user_data: Function specific data
4643 * Returns: TRUE on success, FALSE on failure
4645 * Getter for "WPA" property.
4647 dbus_bool_t wpas_dbus_getter_bss_wpa(
4648 const struct wpa_dbus_property_desc *property_desc,
4649 DBusMessageIter *iter, DBusError *error, void *user_data)
4651 struct bss_handler_args *args = user_data;
4652 struct wpa_bss *res;
4653 struct wpa_ie_data wpa_data;
4656 res = get_bss_helper(args, error, __func__);
4660 os_memset(&wpa_data, 0, sizeof(wpa_data));
4661 ie = wpa_bss_get_vendor_ie(res, WPA_IE_VENDOR_TYPE);
4662 if (ie && wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0) {
4663 dbus_set_error_const(error, DBUS_ERROR_FAILED,
4664 "failed to parse WPA IE");
4668 return wpas_dbus_get_bss_security_prop(property_desc, iter, &wpa_data, error);
4673 * wpas_dbus_getter_bss_rsn - Return the RSN options of a BSS
4674 * @iter: Pointer to incoming dbus message iter
4675 * @error: Location to store error on failure
4676 * @user_data: Function specific data
4677 * Returns: TRUE on success, FALSE on failure
4679 * Getter for "RSN" property.
4681 dbus_bool_t wpas_dbus_getter_bss_rsn(
4682 const struct wpa_dbus_property_desc *property_desc,
4683 DBusMessageIter *iter, DBusError *error, void *user_data)
4685 struct bss_handler_args *args = user_data;
4686 struct wpa_bss *res;
4687 struct wpa_ie_data wpa_data;
4690 res = get_bss_helper(args, error, __func__);
4694 os_memset(&wpa_data, 0, sizeof(wpa_data));
4695 ie = wpa_bss_get_ie(res, WLAN_EID_RSN);
4696 if (ie && wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0) {
4697 dbus_set_error_const(error, DBUS_ERROR_FAILED,
4698 "failed to parse RSN IE");
4702 return wpas_dbus_get_bss_security_prop(property_desc, iter, &wpa_data, error);
4707 * wpas_dbus_getter_bss_wps - Return the WPS options of a BSS
4708 * @iter: Pointer to incoming dbus message iter
4709 * @error: Location to store error on failure
4710 * @user_data: Function specific data
4711 * Returns: TRUE on success, FALSE on failure
4713 * Getter for "WPS" property.
4715 dbus_bool_t wpas_dbus_getter_bss_wps(
4716 const struct wpa_dbus_property_desc *property_desc,
4717 DBusMessageIter *iter, DBusError *error, void *user_data)
4719 struct bss_handler_args *args = user_data;
4720 struct wpa_bss *res;
4722 struct wpabuf *wps_ie;
4723 #endif /* CONFIG_WPS */
4724 DBusMessageIter iter_dict, variant_iter;
4725 int wps_support = 0;
4726 const char *type = "";
4728 res = get_bss_helper(args, error, __func__);
4732 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
4733 "a{sv}", &variant_iter) ||
4734 !wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
4738 wps_ie = wpa_bss_get_vendor_ie_multi(res, WPS_IE_VENDOR_TYPE);
4741 if (wps_is_selected_pbc_registrar(wps_ie))
4743 else if (wps_is_selected_pin_registrar(wps_ie))
4746 wpabuf_free(wps_ie);
4748 #endif /* CONFIG_WPS */
4750 if ((wps_support && !wpa_dbus_dict_append_string(&iter_dict, "Type", type)) ||
4751 !wpa_dbus_dict_close_write(&variant_iter, &iter_dict) ||
4752 !dbus_message_iter_close_container(iter, &variant_iter))
4758 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
4764 * wpas_dbus_getter_bss_ies - Return all IEs of a BSS
4765 * @iter: Pointer to incoming dbus message iter
4766 * @error: Location to store error on failure
4767 * @user_data: Function specific data
4768 * Returns: TRUE on success, FALSE on failure
4770 * Getter for "IEs" property.
4772 dbus_bool_t wpas_dbus_getter_bss_ies(
4773 const struct wpa_dbus_property_desc *property_desc,
4774 DBusMessageIter *iter, DBusError *error, void *user_data)
4776 struct bss_handler_args *args = user_data;
4777 struct wpa_bss *res;
4779 res = get_bss_helper(args, error, __func__);
4783 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
4784 res + 1, res->ie_len,
4790 * wpas_dbus_getter_bss_age - Return time in seconds since BSS was last seen
4791 * @iter: Pointer to incoming dbus message iter
4792 * @error: Location to store error on failure
4793 * @user_data: Function specific data
4794 * Returns: TRUE on success, FALSE on failure
4796 * Getter for BSS age
4798 dbus_bool_t wpas_dbus_getter_bss_age(
4799 const struct wpa_dbus_property_desc *property_desc,
4800 DBusMessageIter *iter, DBusError *error, void *user_data)
4802 struct bss_handler_args *args = user_data;
4803 struct wpa_bss *res;
4804 struct os_reltime now, diff = { 0, 0 };
4807 res = get_bss_helper(args, error, __func__);
4811 os_get_reltime(&now);
4812 os_reltime_sub(&now, &res->last_update, &diff);
4813 age = diff.sec > 0 ? diff.sec : 0;
4814 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32, &age,
4820 * wpas_dbus_getter_enabled - Check whether network is enabled or disabled
4821 * @iter: Pointer to incoming dbus message iter
4822 * @error: Location to store error on failure
4823 * @user_data: Function specific data
4824 * Returns: TRUE on success, FALSE on failure
4826 * Getter for "enabled" property of a configured network.
4828 dbus_bool_t wpas_dbus_getter_enabled(
4829 const struct wpa_dbus_property_desc *property_desc,
4830 DBusMessageIter *iter, DBusError *error, void *user_data)
4832 struct network_handler_args *net = user_data;
4833 dbus_bool_t enabled = net->ssid->disabled ? FALSE : TRUE;
4835 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
4841 * wpas_dbus_setter_enabled - Mark a configured network as enabled or disabled
4842 * @iter: Pointer to incoming dbus message iter
4843 * @error: Location to store error on failure
4844 * @user_data: Function specific data
4845 * Returns: TRUE on success, FALSE on failure
4847 * Setter for "Enabled" property of a configured network.
4849 dbus_bool_t wpas_dbus_setter_enabled(
4850 const struct wpa_dbus_property_desc *property_desc,
4851 DBusMessageIter *iter, DBusError *error, void *user_data)
4853 struct network_handler_args *net = user_data;
4854 struct wpa_supplicant *wpa_s;
4855 struct wpa_ssid *ssid;
4858 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
4866 wpa_supplicant_enable_network(wpa_s, ssid);
4868 wpa_supplicant_disable_network(wpa_s, ssid);
4875 * wpas_dbus_getter_network_properties - Get options for a configured network
4876 * @iter: Pointer to incoming dbus message iter
4877 * @error: Location to store error on failure
4878 * @user_data: Function specific data
4879 * Returns: TRUE on success, FALSE on failure
4881 * Getter for "Properties" property of a configured network.
4883 dbus_bool_t wpas_dbus_getter_network_properties(
4884 const struct wpa_dbus_property_desc *property_desc,
4885 DBusMessageIter *iter, DBusError *error, void *user_data)
4887 struct network_handler_args *net = user_data;
4888 DBusMessageIter variant_iter, dict_iter;
4890 char **props = wpa_config_get_all(net->ssid, 1);
4891 dbus_bool_t success = FALSE;
4894 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
4898 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a{sv}",
4900 !wpa_dbus_dict_open_write(&variant_iter, &dict_iter)) {
4901 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
4907 if (!wpa_dbus_dict_append_string(&dict_iter, *iterator,
4909 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
4917 if (!wpa_dbus_dict_close_write(&variant_iter, &dict_iter) ||
4918 !dbus_message_iter_close_container(iter, &variant_iter)) {
4919 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
4937 * wpas_dbus_setter_network_properties - Set options for a configured network
4938 * @iter: Pointer to incoming dbus message iter
4939 * @error: Location to store error on failure
4940 * @user_data: Function specific data
4941 * Returns: TRUE on success, FALSE on failure
4943 * Setter for "Properties" property of a configured network.
4945 dbus_bool_t wpas_dbus_setter_network_properties(
4946 const struct wpa_dbus_property_desc *property_desc,
4947 DBusMessageIter *iter, DBusError *error, void *user_data)
4949 struct network_handler_args *net = user_data;
4950 struct wpa_ssid *ssid = net->ssid;
4951 DBusMessageIter variant_iter;
4953 dbus_message_iter_recurse(iter, &variant_iter);
4954 return set_network_properties(net->wpa_s, ssid, &variant_iter, error);
4960 DBusMessage * wpas_dbus_handler_subscribe_preq(
4961 DBusMessage *message, struct wpa_supplicant *wpa_s)
4963 struct wpas_dbus_priv *priv = wpa_s->global->dbus;
4966 if (wpa_s->preq_notify_peer != NULL) {
4967 if (os_strcmp(dbus_message_get_sender(message),
4968 wpa_s->preq_notify_peer) == 0)
4971 return dbus_message_new_error(message,
4972 WPAS_DBUS_ERROR_SUBSCRIPTION_IN_USE,
4973 "Another application is already subscribed");
4976 name = os_strdup(dbus_message_get_sender(message));
4978 return wpas_dbus_error_no_memory(message);
4980 wpa_s->preq_notify_peer = name;
4982 /* Subscribe to clean up if application closes socket */
4983 wpas_dbus_subscribe_noc(priv);
4986 * Double-check it's still alive to make sure that we didn't
4987 * miss the NameOwnerChanged signal, e.g. while strdup'ing.
4989 if (!dbus_bus_name_has_owner(priv->con, name, NULL)) {
4991 * Application no longer exists, clean up.
4992 * The return value is irrelevant now.
4994 * Need to check if the NameOwnerChanged handling
4995 * already cleaned up because we have processed
4996 * DBus messages while checking if the name still
4999 if (!wpa_s->preq_notify_peer)
5001 os_free(wpa_s->preq_notify_peer);
5002 wpa_s->preq_notify_peer = NULL;
5003 wpas_dbus_unsubscribe_noc(priv);
5010 DBusMessage * wpas_dbus_handler_unsubscribe_preq(
5011 DBusMessage *message, struct wpa_supplicant *wpa_s)
5013 struct wpas_dbus_priv *priv = wpa_s->global->dbus;
5015 if (!wpa_s->preq_notify_peer)
5016 return dbus_message_new_error(message,
5017 WPAS_DBUS_ERROR_NO_SUBSCRIPTION,
5020 if (os_strcmp(wpa_s->preq_notify_peer,
5021 dbus_message_get_sender(message)))
5022 return dbus_message_new_error(message,
5023 WPAS_DBUS_ERROR_SUBSCRIPTION_EPERM,
5024 "Can't unsubscribe others");
5026 os_free(wpa_s->preq_notify_peer);
5027 wpa_s->preq_notify_peer = NULL;
5028 wpas_dbus_unsubscribe_noc(priv);
5033 void wpas_dbus_signal_preq(struct wpa_supplicant *wpa_s,
5034 const u8 *addr, const u8 *dst, const u8 *bssid,
5035 const u8 *ie, size_t ie_len, u32 ssi_signal)
5038 DBusMessageIter iter, dict_iter;
5039 struct wpas_dbus_priv *priv = wpa_s->global->dbus;
5041 /* Do nothing if the control interface is not turned on */
5042 if (priv == NULL || !wpa_s->dbus_new_path)
5045 if (wpa_s->preq_notify_peer == NULL)
5048 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
5049 WPAS_DBUS_NEW_IFACE_INTERFACE,
5054 dbus_message_set_destination(msg, wpa_s->preq_notify_peer);
5056 dbus_message_iter_init_append(msg, &iter);
5058 if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
5059 (addr && !wpa_dbus_dict_append_byte_array(&dict_iter, "addr",
5060 (const char *) addr,
5062 (dst && !wpa_dbus_dict_append_byte_array(&dict_iter, "dst",
5065 (bssid && !wpa_dbus_dict_append_byte_array(&dict_iter, "bssid",
5066 (const char *) bssid,
5068 (ie && ie_len && !wpa_dbus_dict_append_byte_array(&dict_iter, "ies",
5071 (ssi_signal && !wpa_dbus_dict_append_int32(&dict_iter, "signal",
5073 !wpa_dbus_dict_close_write(&iter, &dict_iter))
5076 dbus_connection_send(priv->con, msg, NULL);
5079 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
5081 dbus_message_unref(msg);
5084 #endif /* CONFIG_AP */
5087 DBusMessage * wpas_dbus_handler_vendor_elem_add(DBusMessage *message,
5088 struct wpa_supplicant *wpa_s)
5092 struct ieee802_11_elems elems;
5093 dbus_int32_t frame_id;
5094 DBusMessageIter iter, array;
5096 dbus_message_iter_init(message, &iter);
5097 dbus_message_iter_get_basic(&iter, &frame_id);
5098 if (frame_id < 0 || frame_id >= NUM_VENDOR_ELEM_FRAMES) {
5099 return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
5103 dbus_message_iter_next(&iter);
5104 dbus_message_iter_recurse(&iter, &array);
5105 dbus_message_iter_get_fixed_array(&array, &ielems, &len);
5106 if (!ielems || len == 0) {
5107 return dbus_message_new_error(
5108 message, DBUS_ERROR_INVALID_ARGS, "Invalid value");
5111 if (ieee802_11_parse_elems(ielems, len, &elems, 0) == ParseFailed) {
5112 return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
5116 wpa_s = wpas_vendor_elem(wpa_s, frame_id);
5117 if (!wpa_s->vendor_elem[frame_id]) {
5118 wpa_s->vendor_elem[frame_id] = wpabuf_alloc_copy(ielems, len);
5119 wpas_vendor_elem_update(wpa_s);
5123 if (wpabuf_resize(&wpa_s->vendor_elem[frame_id], len) < 0) {
5124 return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
5128 wpabuf_put_data(wpa_s->vendor_elem[frame_id], ielems, len);
5129 wpas_vendor_elem_update(wpa_s);
5134 DBusMessage * wpas_dbus_handler_vendor_elem_get(DBusMessage *message,
5135 struct wpa_supplicant *wpa_s)
5138 DBusMessageIter iter, array_iter;
5139 dbus_int32_t frame_id;
5143 dbus_message_iter_init(message, &iter);
5144 dbus_message_iter_get_basic(&iter, &frame_id);
5146 if (frame_id < 0 || frame_id >= NUM_VENDOR_ELEM_FRAMES) {
5147 return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
5151 wpa_s = wpas_vendor_elem(wpa_s, frame_id);
5152 if (!wpa_s->vendor_elem[frame_id]) {
5153 return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
5154 "ID value does not exist");
5157 reply = dbus_message_new_method_return(message);
5159 return wpas_dbus_error_no_memory(message);
5161 dbus_message_iter_init_append(reply, &iter);
5163 elem = wpabuf_head_u8(wpa_s->vendor_elem[frame_id]);
5164 elem_len = wpabuf_len(wpa_s->vendor_elem[frame_id]);
5166 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
5167 DBUS_TYPE_BYTE_AS_STRING,
5169 !dbus_message_iter_append_fixed_array(&array_iter, DBUS_TYPE_BYTE,
5171 !dbus_message_iter_close_container(&iter, &array_iter)) {
5172 dbus_message_unref(reply);
5173 reply = wpas_dbus_error_no_memory(message);
5180 DBusMessage * wpas_dbus_handler_vendor_elem_remove(DBusMessage *message,
5181 struct wpa_supplicant *wpa_s)
5185 struct ieee802_11_elems elems;
5186 DBusMessageIter iter, array;
5187 dbus_int32_t frame_id;
5189 dbus_message_iter_init(message, &iter);
5190 dbus_message_iter_get_basic(&iter, &frame_id);
5191 if (frame_id < 0 || frame_id >= NUM_VENDOR_ELEM_FRAMES) {
5192 return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
5196 dbus_message_iter_next(&iter);
5197 dbus_message_iter_recurse(&iter, &array);
5198 dbus_message_iter_get_fixed_array(&array, &ielems, &len);
5199 if (!ielems || len == 0) {
5200 return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
5204 wpa_s = wpas_vendor_elem(wpa_s, frame_id);
5206 if (len == 1 && *ielems == '*') {
5207 wpabuf_free(wpa_s->vendor_elem[frame_id]);
5208 wpa_s->vendor_elem[frame_id] = NULL;
5209 wpas_vendor_elem_update(wpa_s);
5213 if (!wpa_s->vendor_elem[frame_id]) {
5214 return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
5215 "ID value does not exist");
5218 if (ieee802_11_parse_elems(ielems, len, &elems, 0) == ParseFailed) {
5219 return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
5223 if (wpas_vendor_elem_remove(wpa_s, frame_id, ielems, len) == 0)
5226 return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
5234 * wpas_dbus_getter_mesh_peers - Get connected mesh peers
5235 * @iter: Pointer to incoming dbus message iter
5236 * @error: Location to store error on failure
5237 * @user_data: Function specific data
5238 * Returns: TRUE on success, FALSE on failure
5240 * Getter for "MeshPeers" property.
5242 dbus_bool_t wpas_dbus_getter_mesh_peers(
5243 const struct wpa_dbus_property_desc *property_desc,
5244 DBusMessageIter *iter, DBusError *error, void *user_data)
5246 struct wpa_supplicant *wpa_s = user_data;
5247 struct hostapd_data *hapd;
5248 struct sta_info *sta;
5249 DBusMessageIter variant_iter, array_iter;
5251 DBusMessageIter inner_array_iter;
5255 hapd = wpa_s->ifmsh->bss[0];
5257 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
5258 DBUS_TYPE_ARRAY_AS_STRING
5259 DBUS_TYPE_ARRAY_AS_STRING
5260 DBUS_TYPE_BYTE_AS_STRING,
5262 !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
5263 DBUS_TYPE_ARRAY_AS_STRING
5264 DBUS_TYPE_BYTE_AS_STRING,
5268 for (sta = hapd->sta_list; sta; sta = sta->next) {
5269 if (!dbus_message_iter_open_container(
5270 &array_iter, DBUS_TYPE_ARRAY,
5271 DBUS_TYPE_BYTE_AS_STRING,
5275 for (i = 0; i < ETH_ALEN; i++) {
5276 if (!dbus_message_iter_append_basic(&inner_array_iter,
5282 if (!dbus_message_iter_close_container(
5283 &array_iter, &inner_array_iter))
5287 if (!dbus_message_iter_close_container(&variant_iter, &array_iter) ||
5288 !dbus_message_iter_close_container(iter, &variant_iter))
5296 * wpas_dbus_getter_mesh_group - Get mesh group
5297 * @iter: Pointer to incoming dbus message iter
5298 * @error: Location to store error on failure
5299 * @user_data: Function specific data
5300 * Returns: TRUE on success, FALSE on failure
5302 * Getter for "MeshGroup" property.
5304 dbus_bool_t wpas_dbus_getter_mesh_group(
5305 const struct wpa_dbus_property_desc *property_desc,
5306 DBusMessageIter *iter, DBusError *error, void *user_data)
5308 struct wpa_supplicant *wpa_s = user_data;
5309 struct wpa_ssid *ssid = wpa_s->current_ssid;
5311 if (!wpa_s->ifmsh || !ssid)
5314 if (!wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
5315 (char *) ssid->ssid,
5316 ssid->ssid_len, error)) {
5317 dbus_set_error(error, DBUS_ERROR_FAILED,
5318 "%s: error constructing reply", __func__);
5325 #endif /* CONFIG_MESH */