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 "../config.h"
19 #include "../wpa_supplicant_i.h"
20 #include "../driver_i.h"
21 #include "../notify.h"
24 #include "../autoscan.h"
25 #include "dbus_new_helpers.h"
27 #include "dbus_new_handlers.h"
28 #include "dbus_dict_helpers.h"
29 #include "dbus_common_i.h"
30 #include "drivers/driver.h"
32 #include "ap/hostapd.h"
33 #include "ap/sta_info.h"
34 #endif /* CONFIG_MESH */
36 static const char * const debug_strings[] = {
37 "excessive", "msgdump", "debug", "info", "warning", "error", NULL
42 * wpas_dbus_error_unknown_error - Return a new UnknownError error message
43 * @message: Pointer to incoming dbus message this error refers to
44 * @arg: Optional string appended to error message
45 * Returns: a dbus error message
47 * Convenience function to create and return an UnknownError
49 DBusMessage * wpas_dbus_error_unknown_error(DBusMessage *message,
52 return dbus_message_new_error(message, WPAS_DBUS_ERROR_UNKNOWN_ERROR,
58 * wpas_dbus_error_iface_unknown - Return a new invalid interface error message
59 * @message: Pointer to incoming dbus message this error refers to
60 * Returns: A dbus error message
62 * Convenience function to create and return an invalid interface error
64 static DBusMessage * wpas_dbus_error_iface_unknown(DBusMessage *message)
66 return dbus_message_new_error(
67 message, WPAS_DBUS_ERROR_IFACE_UNKNOWN,
68 "wpa_supplicant knows nothing about this interface.");
73 * wpas_dbus_error_network_unknown - Return a new NetworkUnknown error message
74 * @message: Pointer to incoming dbus message this error refers to
75 * Returns: a dbus error message
77 * Convenience function to create and return an invalid network error
79 static DBusMessage * wpas_dbus_error_network_unknown(DBusMessage *message)
81 return dbus_message_new_error(
82 message, WPAS_DBUS_ERROR_NETWORK_UNKNOWN,
83 "There is no such a network in this interface.");
88 * wpas_dbus_error_invalid_args - Return a new InvalidArgs error message
89 * @message: Pointer to incoming dbus message this error refers to
90 * Returns: a dbus error message
92 * Convenience function to create and return an invalid options error
94 DBusMessage * wpas_dbus_error_invalid_args(DBusMessage *message,
99 reply = dbus_message_new_error(
100 message, WPAS_DBUS_ERROR_INVALID_ARGS,
101 "Did not receive correct message arguments.");
103 dbus_message_append_args(reply, DBUS_TYPE_STRING, &arg,
111 * wpas_dbus_error_scan_error - Return a new ScanError error message
112 * @message: Pointer to incoming dbus message this error refers to
113 * @error: Optional string to be used as the error message
114 * Returns: a dbus error message
116 * Convenience function to create and return a scan error
118 static DBusMessage * wpas_dbus_error_scan_error(DBusMessage *message,
121 return dbus_message_new_error(message,
122 WPAS_DBUS_ERROR_IFACE_SCAN_ERROR,
127 DBusMessage * wpas_dbus_error_no_memory(DBusMessage *message)
129 wpa_printf(MSG_DEBUG, "dbus: Failed to allocate memory");
130 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, NULL);
134 static const char * const dont_quote[] = {
135 "key_mgmt", "proto", "pairwise", "auth_alg", "group", "eap",
136 "opensc_engine_path", "pkcs11_engine_path", "pkcs11_module_path",
137 "bssid", "scan_freq", "freq_list", NULL
140 static dbus_bool_t should_quote_opt(const char *key)
144 while (dont_quote[i] != NULL) {
145 if (os_strcmp(key, dont_quote[i]) == 0)
153 * get_iface_by_dbus_path - Get a new network interface
154 * @global: Pointer to global data from wpa_supplicant_init()
155 * @path: Pointer to a dbus object path representing an interface
156 * Returns: Pointer to the interface or %NULL if not found
158 static struct wpa_supplicant * get_iface_by_dbus_path(
159 struct wpa_global *global, const char *path)
161 struct wpa_supplicant *wpa_s;
163 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
164 if (wpa_s->dbus_new_path &&
165 os_strcmp(wpa_s->dbus_new_path, path) == 0)
173 * set_network_properties - Set properties of a configured network
174 * @wpa_s: wpa_supplicant structure for a network interface
175 * @ssid: wpa_ssid structure for a configured network
176 * @iter: DBus message iterator containing dictionary of network
178 * @error: On failure, an error describing the failure
179 * Returns: TRUE if the request succeeds, FALSE if it failed
181 * Sets network configuration with parameters given id DBus dictionary
183 dbus_bool_t set_network_properties(struct wpa_supplicant *wpa_s,
184 struct wpa_ssid *ssid,
185 DBusMessageIter *iter,
188 struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
189 DBusMessageIter iter_dict;
192 if (!wpa_dbus_dict_open_read(iter, &iter_dict, error))
195 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
199 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
203 if (entry.type == DBUS_TYPE_ARRAY &&
204 entry.array_type == DBUS_TYPE_BYTE) {
205 if (entry.array_len <= 0)
208 size = entry.array_len * 2 + 1;
209 value = os_zalloc(size);
213 ret = wpa_snprintf_hex(value, size,
214 (u8 *) entry.bytearray_value,
218 } else if (entry.type == DBUS_TYPE_STRING) {
219 if (should_quote_opt(entry.key)) {
220 size = os_strlen(entry.str_value);
225 value = os_zalloc(size);
229 ret = os_snprintf(value, size, "\"%s\"",
231 if (os_snprintf_error(size, ret))
234 value = os_strdup(entry.str_value);
238 } else if (entry.type == DBUS_TYPE_UINT32) {
239 value = os_zalloc(size);
243 ret = os_snprintf(value, size, "%u",
245 if (os_snprintf_error(size, ret))
247 } else if (entry.type == DBUS_TYPE_INT32) {
248 value = os_zalloc(size);
252 ret = os_snprintf(value, size, "%d",
254 if (os_snprintf_error(size, ret))
259 if (wpa_config_set(ssid, entry.key, value, 0) < 0)
262 if (os_strcmp(entry.key, "bssid") != 0 &&
263 os_strcmp(entry.key, "priority") != 0)
264 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
266 if (wpa_s->current_ssid == ssid ||
267 wpa_s->current_ssid == NULL) {
269 * Invalidate the EAP session cache if anything in the
270 * current or previously used configuration changes.
272 eapol_sm_invalidate_cached_session(wpa_s->eapol);
275 if ((os_strcmp(entry.key, "psk") == 0 &&
276 value[0] == '"' && ssid->ssid_len) ||
277 (os_strcmp(entry.key, "ssid") == 0 && ssid->passphrase))
278 wpa_config_update_psk(ssid);
279 else if (os_strcmp(entry.key, "priority") == 0)
280 wpa_config_update_prio_list(wpa_s->conf);
284 wpa_dbus_dict_entry_clear(&entry);
291 wpa_dbus_dict_entry_clear(&entry);
292 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
293 "invalid message format");
299 * wpas_dbus_simple_property_getter - Get basic type property
300 * @iter: Message iter to use when appending arguments
301 * @type: DBus type of property (must be basic type)
302 * @val: pointer to place holding property value
303 * @error: On failure an error describing the failure
304 * Returns: TRUE if the request was successful, FALSE if it failed
306 * Generic getter for basic type properties. Type is required to be basic.
308 dbus_bool_t wpas_dbus_simple_property_getter(DBusMessageIter *iter,
313 DBusMessageIter variant_iter;
315 if (!dbus_type_is_basic(type)) {
316 dbus_set_error(error, DBUS_ERROR_FAILED,
317 "%s: given type is not basic", __func__);
321 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
322 wpa_dbus_type_as_string(type),
324 !dbus_message_iter_append_basic(&variant_iter, type, val) ||
325 !dbus_message_iter_close_container(iter, &variant_iter)) {
326 dbus_set_error(error, DBUS_ERROR_FAILED,
327 "%s: error constructing reply", __func__);
336 * wpas_dbus_simple_property_setter - Set basic type property
337 * @message: Pointer to incoming dbus message
338 * @type: DBus type of property (must be basic type)
339 * @val: pointer to place where value being set will be stored
340 * Returns: TRUE if the request was successful, FALSE if it failed
342 * Generic setter for basic type properties. Type is required to be basic.
344 dbus_bool_t wpas_dbus_simple_property_setter(DBusMessageIter *iter,
346 const int type, void *val)
348 DBusMessageIter variant_iter;
350 if (!dbus_type_is_basic(type)) {
351 dbus_set_error(error, DBUS_ERROR_FAILED,
352 "%s: given type is not basic", __func__);
356 /* Look at the new value */
357 dbus_message_iter_recurse(iter, &variant_iter);
358 if (dbus_message_iter_get_arg_type(&variant_iter) != type) {
359 dbus_set_error_const(error, DBUS_ERROR_FAILED,
360 "wrong property type");
363 dbus_message_iter_get_basic(&variant_iter, val);
370 * wpas_dbus_simple_array_property_getter - Get array type property
371 * @iter: Pointer to incoming dbus message iterator
372 * @type: DBus type of property array elements (must be basic type)
373 * @array: pointer to array of elements to put into response message
374 * @array_len: length of above array
375 * @error: a pointer to an error to fill on failure
376 * Returns: TRUE if the request succeeded, FALSE if it failed
378 * Generic getter for array type properties. Array elements type is
379 * required to be basic.
381 dbus_bool_t wpas_dbus_simple_array_property_getter(DBusMessageIter *iter,
387 DBusMessageIter variant_iter, array_iter;
388 char type_str[] = "a?"; /* ? will be replaced with subtype letter; */
389 const char *sub_type_str;
390 size_t element_size, i;
392 if (!dbus_type_is_basic(type)) {
393 dbus_set_error(error, DBUS_ERROR_FAILED,
394 "%s: given type is not basic", __func__);
398 sub_type_str = wpa_dbus_type_as_string(type);
399 type_str[1] = sub_type_str[0];
401 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
402 type_str, &variant_iter) ||
403 !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
404 sub_type_str, &array_iter)) {
405 dbus_set_error(error, DBUS_ERROR_FAILED,
406 "%s: failed to construct message", __func__);
412 case DBUS_TYPE_BOOLEAN:
415 case DBUS_TYPE_INT16:
416 case DBUS_TYPE_UINT16:
417 element_size = sizeof(uint16_t);
419 case DBUS_TYPE_INT32:
420 case DBUS_TYPE_UINT32:
421 element_size = sizeof(uint32_t);
423 case DBUS_TYPE_INT64:
424 case DBUS_TYPE_UINT64:
425 element_size = sizeof(uint64_t);
427 case DBUS_TYPE_DOUBLE:
428 element_size = sizeof(double);
430 case DBUS_TYPE_STRING:
431 case DBUS_TYPE_OBJECT_PATH:
432 element_size = sizeof(char *);
435 dbus_set_error(error, DBUS_ERROR_FAILED,
436 "%s: unknown element type %d", __func__, type);
440 for (i = 0; i < array_len; i++) {
441 if (!dbus_message_iter_append_basic(&array_iter, type,
442 (const char *) array +
444 dbus_set_error(error, DBUS_ERROR_FAILED,
445 "%s: failed to construct message 2.5",
451 if (!dbus_message_iter_close_container(&variant_iter, &array_iter) ||
452 !dbus_message_iter_close_container(iter, &variant_iter)) {
453 dbus_set_error(error, DBUS_ERROR_FAILED,
454 "%s: failed to construct message 3", __func__);
463 * wpas_dbus_simple_array_array_property_getter - Get array array type property
464 * @iter: Pointer to incoming dbus message iterator
465 * @type: DBus type of property array elements (must be basic type)
466 * @array: pointer to array of elements to put into response message
467 * @array_len: length of above array
468 * @error: a pointer to an error to fill on failure
469 * Returns: TRUE if the request succeeded, FALSE if it failed
471 * Generic getter for array type properties. Array elements type is
472 * required to be basic.
474 dbus_bool_t wpas_dbus_simple_array_array_property_getter(DBusMessageIter *iter,
476 struct wpabuf **array,
480 DBusMessageIter variant_iter, array_iter;
481 char type_str[] = "aa?";
482 char inner_type_str[] = "a?";
483 const char *sub_type_str;
486 if (!dbus_type_is_basic(type)) {
487 dbus_set_error(error, DBUS_ERROR_FAILED,
488 "%s: given type is not basic", __func__);
492 sub_type_str = wpa_dbus_type_as_string(type);
493 type_str[2] = sub_type_str[0];
494 inner_type_str[1] = sub_type_str[0];
496 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
497 type_str, &variant_iter) ||
498 !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
499 inner_type_str, &array_iter)) {
500 dbus_set_error(error, DBUS_ERROR_FAILED,
501 "%s: failed to construct message", __func__);
505 for (i = 0; i < array_len && array[i]; i++) {
506 wpa_dbus_dict_bin_array_add_element(&array_iter,
507 wpabuf_head(array[i]),
508 wpabuf_len(array[i]));
512 if (!dbus_message_iter_close_container(&variant_iter, &array_iter) ||
513 !dbus_message_iter_close_container(iter, &variant_iter)) {
514 dbus_set_error(error, DBUS_ERROR_FAILED,
515 "%s: failed to close message", __func__);
524 * wpas_dbus_string_property_getter - Get string type property
525 * @iter: Message iter to use when appending arguments
526 * @val: Pointer to place holding property value, can be %NULL
527 * @error: On failure an error describing the failure
528 * Returns: TRUE if the request was successful, FALSE if it failed
530 * Generic getter for string type properties. %NULL is converted to an empty
533 dbus_bool_t wpas_dbus_string_property_getter(DBusMessageIter *iter,
539 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
545 * wpas_dbus_handler_create_interface - Request registration of a network iface
546 * @message: Pointer to incoming dbus message
547 * @global: %wpa_supplicant global data structure
548 * Returns: The object path of the new interface object,
549 * or a dbus error message with more information
551 * Handler function for "CreateInterface" method call. Handles requests
552 * by dbus clients to register a network interface that wpa_supplicant
555 DBusMessage * wpas_dbus_handler_create_interface(DBusMessage *message,
556 struct wpa_global *global)
558 DBusMessageIter iter_dict;
559 DBusMessage *reply = NULL;
560 DBusMessageIter iter;
561 struct wpa_dbus_dict_entry entry;
564 char *confname = NULL;
565 char *bridge_ifname = NULL;
567 dbus_message_iter_init(message, &iter);
569 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
571 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
572 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
574 if (os_strcmp(entry.key, "Driver") == 0 &&
575 entry.type == DBUS_TYPE_STRING) {
577 driver = os_strdup(entry.str_value);
578 wpa_dbus_dict_entry_clear(&entry);
581 } else if (os_strcmp(entry.key, "Ifname") == 0 &&
582 entry.type == DBUS_TYPE_STRING) {
584 ifname = os_strdup(entry.str_value);
585 wpa_dbus_dict_entry_clear(&entry);
588 } else if (os_strcmp(entry.key, "ConfigFile") == 0 &&
589 entry.type == DBUS_TYPE_STRING) {
591 confname = os_strdup(entry.str_value);
592 wpa_dbus_dict_entry_clear(&entry);
593 if (confname == NULL)
595 } else if (os_strcmp(entry.key, "BridgeIfname") == 0 &&
596 entry.type == DBUS_TYPE_STRING) {
597 os_free(bridge_ifname);
598 bridge_ifname = os_strdup(entry.str_value);
599 wpa_dbus_dict_entry_clear(&entry);
600 if (bridge_ifname == NULL)
603 wpa_dbus_dict_entry_clear(&entry);
609 goto error; /* Required Ifname argument missing */
612 * Try to get the wpa_supplicant record for this iface, return
613 * an error if we already control it.
615 if (wpa_supplicant_get_iface(global, ifname) != NULL) {
616 reply = dbus_message_new_error(
617 message, WPAS_DBUS_ERROR_IFACE_EXISTS,
618 "wpa_supplicant already controls this interface.");
620 struct wpa_supplicant *wpa_s;
621 struct wpa_interface iface;
623 os_memset(&iface, 0, sizeof(iface));
624 iface.driver = driver;
625 iface.ifname = ifname;
626 iface.confname = confname;
627 iface.bridge_ifname = bridge_ifname;
628 /* Otherwise, have wpa_supplicant attach to it. */
629 wpa_s = wpa_supplicant_add_iface(global, &iface, NULL);
630 if (wpa_s && wpa_s->dbus_new_path) {
631 const char *path = wpa_s->dbus_new_path;
633 reply = dbus_message_new_method_return(message);
634 dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH,
635 &path, DBUS_TYPE_INVALID);
637 reply = wpas_dbus_error_unknown_error(
639 "wpa_supplicant couldn't grab this interface.");
647 os_free(bridge_ifname);
651 reply = wpas_dbus_error_invalid_args(message, NULL);
654 reply = wpas_dbus_error_no_memory(message);
660 * wpas_dbus_handler_remove_interface - Request deregistration of an interface
661 * @message: Pointer to incoming dbus message
662 * @global: wpa_supplicant global data structure
663 * Returns: a dbus message containing a UINT32 indicating success (1) or
664 * failure (0), or returns a dbus error message with more information
666 * Handler function for "removeInterface" method call. Handles requests
667 * by dbus clients to deregister a network interface that wpa_supplicant
670 DBusMessage * wpas_dbus_handler_remove_interface(DBusMessage *message,
671 struct wpa_global *global)
673 struct wpa_supplicant *wpa_s;
675 DBusMessage *reply = NULL;
677 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path,
680 wpa_s = get_iface_by_dbus_path(global, path);
682 reply = wpas_dbus_error_iface_unknown(message);
683 else if (wpa_supplicant_remove_iface(global, wpa_s, 0)) {
684 reply = wpas_dbus_error_unknown_error(
686 "wpa_supplicant couldn't remove this interface.");
694 * wpas_dbus_handler_get_interface - Get the object path for an interface name
695 * @message: Pointer to incoming dbus message
696 * @global: %wpa_supplicant global data structure
697 * Returns: The object path of the interface object,
698 * or a dbus error message with more information
700 * Handler function for "getInterface" method call.
702 DBusMessage * wpas_dbus_handler_get_interface(DBusMessage *message,
703 struct wpa_global *global)
705 DBusMessage *reply = NULL;
708 struct wpa_supplicant *wpa_s;
710 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &ifname,
713 wpa_s = wpa_supplicant_get_iface(global, ifname);
714 if (wpa_s == NULL || wpa_s->dbus_new_path == NULL)
715 return wpas_dbus_error_iface_unknown(message);
717 path = wpa_s->dbus_new_path;
718 reply = dbus_message_new_method_return(message);
720 return wpas_dbus_error_no_memory(message);
721 if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
722 DBUS_TYPE_INVALID)) {
723 dbus_message_unref(reply);
724 return wpas_dbus_error_no_memory(message);
732 * wpas_dbus_getter_debug_level - Get debug level
733 * @iter: Pointer to incoming dbus message iter
734 * @error: Location to store error on failure
735 * @user_data: Function specific data
736 * Returns: TRUE on success, FALSE on failure
738 * Getter for "DebugLevel" property.
740 dbus_bool_t wpas_dbus_getter_debug_level(
741 const struct wpa_dbus_property_desc *property_desc,
742 DBusMessageIter *iter, DBusError *error, void *user_data)
745 int idx = wpa_debug_level;
751 str = debug_strings[idx];
752 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
758 * wpas_dbus_getter_debug_timestamp - Get debug timestamp
759 * @iter: Pointer to incoming dbus message iter
760 * @error: Location to store error on failure
761 * @user_data: Function specific data
762 * Returns: TRUE on success, FALSE on failure
764 * Getter for "DebugTimestamp" property.
766 dbus_bool_t wpas_dbus_getter_debug_timestamp(
767 const struct wpa_dbus_property_desc *property_desc,
768 DBusMessageIter *iter, DBusError *error, void *user_data)
770 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
771 &wpa_debug_timestamp, error);
777 * wpas_dbus_getter_debug_show_keys - Get debug show keys
778 * @iter: Pointer to incoming dbus message iter
779 * @error: Location to store error on failure
780 * @user_data: Function specific data
781 * Returns: TRUE on success, FALSE on failure
783 * Getter for "DebugShowKeys" property.
785 dbus_bool_t wpas_dbus_getter_debug_show_keys(
786 const struct wpa_dbus_property_desc *property_desc,
787 DBusMessageIter *iter, DBusError *error, void *user_data)
789 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
790 &wpa_debug_show_keys, error);
795 * wpas_dbus_setter_debug_level - Set debug level
796 * @iter: Pointer to incoming dbus message iter
797 * @error: Location to store error on failure
798 * @user_data: Function specific data
799 * Returns: TRUE on success, FALSE on failure
801 * Setter for "DebugLevel" property.
803 dbus_bool_t wpas_dbus_setter_debug_level(
804 const struct wpa_dbus_property_desc *property_desc,
805 DBusMessageIter *iter, DBusError *error, void *user_data)
807 struct wpa_global *global = user_data;
808 const char *str = NULL;
811 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
815 for (i = 0; debug_strings[i]; i++)
816 if (os_strcmp(debug_strings[i], str) == 0) {
822 wpa_supplicant_set_debug_params(global, val, wpa_debug_timestamp,
823 wpa_debug_show_keys)) {
824 dbus_set_error_const(error, DBUS_ERROR_FAILED,
825 "wrong debug level value");
834 * wpas_dbus_setter_debug_timestamp - Set debug timestamp
835 * @iter: Pointer to incoming dbus message iter
836 * @error: Location to store error on failure
837 * @user_data: Function specific data
838 * Returns: TRUE on success, FALSE on failure
840 * Setter for "DebugTimestamp" property.
842 dbus_bool_t wpas_dbus_setter_debug_timestamp(
843 const struct wpa_dbus_property_desc *property_desc,
844 DBusMessageIter *iter, DBusError *error, void *user_data)
846 struct wpa_global *global = user_data;
849 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
853 wpa_supplicant_set_debug_params(global, wpa_debug_level, val ? 1 : 0,
854 wpa_debug_show_keys);
860 * wpas_dbus_setter_debug_show_keys - Set debug show keys
861 * @iter: Pointer to incoming dbus message iter
862 * @error: Location to store error on failure
863 * @user_data: Function specific data
864 * Returns: TRUE on success, FALSE on failure
866 * Setter for "DebugShowKeys" property.
868 dbus_bool_t wpas_dbus_setter_debug_show_keys(
869 const struct wpa_dbus_property_desc *property_desc,
870 DBusMessageIter *iter, DBusError *error, void *user_data)
872 struct wpa_global *global = user_data;
875 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
879 wpa_supplicant_set_debug_params(global, wpa_debug_level,
887 * wpas_dbus_getter_interfaces - Request registered interfaces list
888 * @iter: Pointer to incoming dbus message iter
889 * @error: Location to store error on failure
890 * @user_data: Function specific data
891 * Returns: TRUE on success, FALSE on failure
893 * Getter for "Interfaces" property. Handles requests
894 * by dbus clients to return list of registered interfaces objects
897 dbus_bool_t wpas_dbus_getter_interfaces(
898 const struct wpa_dbus_property_desc *property_desc,
899 DBusMessageIter *iter, DBusError *error, void *user_data)
901 struct wpa_global *global = user_data;
902 struct wpa_supplicant *wpa_s;
904 unsigned int i = 0, num = 0;
907 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
908 if (wpa_s->dbus_new_path)
912 paths = os_calloc(num, sizeof(char *));
914 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
918 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
919 if (wpa_s->dbus_new_path)
920 paths[i++] = wpa_s->dbus_new_path;
923 success = wpas_dbus_simple_array_property_getter(iter,
924 DBUS_TYPE_OBJECT_PATH,
933 * wpas_dbus_getter_eap_methods - Request supported EAP methods list
934 * @iter: Pointer to incoming dbus message iter
935 * @error: Location to store error on failure
936 * @user_data: Function specific data
937 * Returns: TRUE on success, FALSE on failure
939 * Getter for "EapMethods" property. Handles requests
940 * by dbus clients to return list of strings with supported EAP methods
942 dbus_bool_t wpas_dbus_getter_eap_methods(
943 const struct wpa_dbus_property_desc *property_desc,
944 DBusMessageIter *iter, DBusError *error, void *user_data)
947 size_t num_items = 0;
950 eap_methods = eap_get_names_as_string_array(&num_items);
952 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
956 success = wpas_dbus_simple_array_property_getter(iter,
962 os_free(eap_methods[--num_items]);
963 os_free(eap_methods);
969 * wpas_dbus_getter_global_capabilities - Request supported global capabilities
970 * @iter: Pointer to incoming dbus message iter
971 * @error: Location to store error on failure
972 * @user_data: Function specific data
973 * Returns: TRUE on success, FALSE on failure
975 * Getter for "Capabilities" property. Handles requests by dbus clients to
976 * return a list of strings with supported capabilities like AP, RSN IBSS,
977 * and P2P that are determined at compile time.
979 dbus_bool_t wpas_dbus_getter_global_capabilities(
980 const struct wpa_dbus_property_desc *property_desc,
981 DBusMessageIter *iter, DBusError *error, void *user_data)
983 const char *capabilities[10] = { NULL, NULL, NULL, NULL, NULL, NULL,
984 NULL, NULL, NULL, NULL };
985 size_t num_items = 0;
987 struct wpa_global *global = user_data;
988 struct wpa_supplicant *wpa_s;
989 int fils_supported = 0, fils_sk_pfs_supported = 0;
991 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
992 if (wpa_is_fils_supported(wpa_s))
994 if (wpa_is_fils_sk_pfs_supported(wpa_s))
995 fils_sk_pfs_supported = 1;
997 #endif /* CONFIG_FILS */
1000 capabilities[num_items++] = "ap";
1001 #endif /* CONFIG_AP */
1002 #ifdef CONFIG_IBSS_RSN
1003 capabilities[num_items++] = "ibss-rsn";
1004 #endif /* CONFIG_IBSS_RSN */
1006 capabilities[num_items++] = "p2p";
1007 #endif /* CONFIG_P2P */
1008 #ifdef CONFIG_INTERWORKING
1009 capabilities[num_items++] = "interworking";
1010 #endif /* CONFIG_INTERWORKING */
1011 #ifdef CONFIG_IEEE80211W
1012 capabilities[num_items++] = "pmf";
1013 #endif /* CONFIG_IEEE80211W */
1015 capabilities[num_items++] = "mesh";
1016 #endif /* CONFIG_MESH */
1019 capabilities[num_items++] = "fils";
1020 if (fils_sk_pfs_supported)
1021 capabilities[num_items++] = "fils_sk_pfs";
1022 #endif /* CONFIG_FILS */
1023 #ifdef CONFIG_IEEE80211R
1024 capabilities[num_items++] = "ft";
1025 #endif /* CONFIG_IEEE80211R */
1026 #ifdef CONFIG_SHA384
1027 capabilities[num_items++] = "sha384";
1028 #endif /* CONFIG_SHA384 */
1030 return wpas_dbus_simple_array_property_getter(iter,
1037 static int wpas_dbus_get_scan_type(DBusMessage *message, DBusMessageIter *var,
1038 char **type, DBusMessage **reply)
1040 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_STRING) {
1041 wpa_printf(MSG_DEBUG, "%s[dbus]: Type must be a string",
1043 *reply = wpas_dbus_error_invalid_args(
1044 message, "Wrong Type value type. String required");
1047 dbus_message_iter_get_basic(var, type);
1052 static int wpas_dbus_get_scan_ssids(DBusMessage *message, DBusMessageIter *var,
1053 struct wpa_driver_scan_params *params,
1054 DBusMessage **reply)
1056 struct wpa_driver_scan_ssid *ssids = params->ssids;
1057 size_t ssids_num = 0;
1059 DBusMessageIter array_iter, sub_array_iter;
1063 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
1064 wpa_printf(MSG_DEBUG,
1065 "%s[dbus]: ssids must be an array of arrays of bytes",
1067 *reply = wpas_dbus_error_invalid_args(
1069 "Wrong SSIDs value type. Array of arrays of bytes required");
1073 dbus_message_iter_recurse(var, &array_iter);
1075 if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY ||
1076 dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_BYTE) {
1077 wpa_printf(MSG_DEBUG,
1078 "%s[dbus]: ssids must be an array of arrays of bytes",
1080 *reply = wpas_dbus_error_invalid_args(
1082 "Wrong SSIDs value type. Array of arrays of bytes required");
1086 while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_ARRAY) {
1087 if (ssids_num >= WPAS_MAX_SCAN_SSIDS) {
1088 wpa_printf(MSG_DEBUG,
1089 "%s[dbus]: Too many ssids specified on scan dbus call",
1091 *reply = wpas_dbus_error_invalid_args(
1093 "Too many ssids specified. Specify at most four");
1097 dbus_message_iter_recurse(&array_iter, &sub_array_iter);
1099 dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len);
1101 if (len > SSID_MAX_LEN) {
1102 wpa_printf(MSG_DEBUG,
1103 "%s[dbus]: SSID too long (len=%d max_len=%d)",
1104 __func__, len, SSID_MAX_LEN);
1105 *reply = wpas_dbus_error_invalid_args(
1106 message, "Invalid SSID: too long");
1111 ssid = os_memdup(val, len);
1113 *reply = wpas_dbus_error_no_memory(message);
1117 /* Allow zero-length SSIDs */
1121 ssids[ssids_num].ssid = ssid;
1122 ssids[ssids_num].ssid_len = len;
1124 dbus_message_iter_next(&array_iter);
1128 params->num_ssids = ssids_num;
1133 static int wpas_dbus_get_scan_ies(DBusMessage *message, DBusMessageIter *var,
1134 struct wpa_driver_scan_params *params,
1135 DBusMessage **reply)
1137 u8 *ies = NULL, *nies;
1139 DBusMessageIter array_iter, sub_array_iter;
1143 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
1144 wpa_printf(MSG_DEBUG,
1145 "%s[dbus]: ies must be an array of arrays of bytes",
1147 *reply = wpas_dbus_error_invalid_args(
1149 "Wrong IEs value type. Array of arrays of bytes required");
1153 dbus_message_iter_recurse(var, &array_iter);
1155 if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY ||
1156 dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_BYTE) {
1157 wpa_printf(MSG_DEBUG,
1158 "%s[dbus]: ies must be an array of arrays of bytes",
1160 *reply = wpas_dbus_error_invalid_args(
1161 message, "Wrong IEs value type. Array required");
1165 while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_ARRAY) {
1166 dbus_message_iter_recurse(&array_iter, &sub_array_iter);
1168 dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len);
1170 dbus_message_iter_next(&array_iter);
1174 nies = os_realloc(ies, ies_len + len);
1177 *reply = wpas_dbus_error_no_memory(message);
1181 os_memcpy(ies + ies_len, val, len);
1184 dbus_message_iter_next(&array_iter);
1187 params->extra_ies = ies;
1188 params->extra_ies_len = ies_len;
1193 static int wpas_dbus_get_scan_channels(DBusMessage *message,
1194 DBusMessageIter *var,
1195 struct wpa_driver_scan_params *params,
1196 DBusMessage **reply)
1198 DBusMessageIter array_iter, sub_array_iter;
1199 int *freqs = NULL, *nfreqs;
1202 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
1203 wpa_printf(MSG_DEBUG,
1204 "%s[dbus]: Channels must be an array of structs",
1206 *reply = wpas_dbus_error_invalid_args(
1208 "Wrong Channels value type. Array of structs required");
1212 dbus_message_iter_recurse(var, &array_iter);
1214 if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_STRUCT) {
1215 wpa_printf(MSG_DEBUG,
1216 "%s[dbus]: Channels must be an array of structs",
1218 *reply = wpas_dbus_error_invalid_args(
1220 "Wrong Channels value type. Array of structs required");
1224 while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_STRUCT)
1228 dbus_message_iter_recurse(&array_iter, &sub_array_iter);
1230 if (dbus_message_iter_get_arg_type(&sub_array_iter) !=
1232 wpa_printf(MSG_DEBUG,
1233 "%s[dbus]: Channel must by specified by struct of two UINT32s %c",
1235 dbus_message_iter_get_arg_type(
1237 *reply = wpas_dbus_error_invalid_args(
1239 "Wrong Channel struct. Two UINT32s required");
1243 dbus_message_iter_get_basic(&sub_array_iter, &freq);
1245 if (!dbus_message_iter_next(&sub_array_iter) ||
1246 dbus_message_iter_get_arg_type(&sub_array_iter) !=
1248 wpa_printf(MSG_DEBUG,
1249 "%s[dbus]: Channel must by specified by struct of two UINT32s",
1251 *reply = wpas_dbus_error_invalid_args(
1253 "Wrong Channel struct. Two UINT32s required");
1258 dbus_message_iter_get_basic(&sub_array_iter, &width);
1260 #define FREQS_ALLOC_CHUNK 32
1261 if (freqs_num % FREQS_ALLOC_CHUNK == 0) {
1262 nfreqs = os_realloc_array(
1263 freqs, freqs_num + FREQS_ALLOC_CHUNK,
1269 if (freqs == NULL) {
1270 *reply = wpas_dbus_error_no_memory(message);
1274 freqs[freqs_num] = freq;
1277 dbus_message_iter_next(&array_iter);
1280 nfreqs = os_realloc_array(freqs, freqs_num + 1, sizeof(int));
1284 if (freqs == NULL) {
1285 *reply = wpas_dbus_error_no_memory(message);
1288 freqs[freqs_num] = 0;
1290 params->freqs = freqs;
1295 static int wpas_dbus_get_scan_allow_roam(DBusMessage *message,
1296 DBusMessageIter *var,
1298 DBusMessage **reply)
1300 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_BOOLEAN) {
1301 wpa_printf(MSG_DEBUG, "%s[dbus]: Type must be a boolean",
1303 *reply = wpas_dbus_error_invalid_args(
1304 message, "Wrong Type value type. Boolean required");
1307 dbus_message_iter_get_basic(var, allow);
1313 * wpas_dbus_handler_scan - Request a wireless scan on an interface
1314 * @message: Pointer to incoming dbus message
1315 * @wpa_s: wpa_supplicant structure for a network interface
1316 * Returns: NULL indicating success or DBus error message on failure
1318 * Handler function for "Scan" method call of a network device. Requests
1319 * that wpa_supplicant perform a wireless scan as soon as possible
1320 * on a particular wireless interface.
1322 DBusMessage * wpas_dbus_handler_scan(DBusMessage *message,
1323 struct wpa_supplicant *wpa_s)
1325 DBusMessage *reply = NULL;
1326 DBusMessageIter iter, dict_iter, entry_iter, variant_iter;
1327 char *key = NULL, *type = NULL;
1328 struct wpa_driver_scan_params params;
1330 dbus_bool_t allow_roam = 1;
1332 os_memset(¶ms, 0, sizeof(params));
1334 dbus_message_iter_init(message, &iter);
1336 dbus_message_iter_recurse(&iter, &dict_iter);
1338 while (dbus_message_iter_get_arg_type(&dict_iter) ==
1339 DBUS_TYPE_DICT_ENTRY) {
1340 dbus_message_iter_recurse(&dict_iter, &entry_iter);
1341 dbus_message_iter_get_basic(&entry_iter, &key);
1342 dbus_message_iter_next(&entry_iter);
1343 dbus_message_iter_recurse(&entry_iter, &variant_iter);
1345 if (os_strcmp(key, "Type") == 0) {
1346 if (wpas_dbus_get_scan_type(message, &variant_iter,
1349 } else if (os_strcmp(key, "SSIDs") == 0) {
1350 if (wpas_dbus_get_scan_ssids(message, &variant_iter,
1351 ¶ms, &reply) < 0)
1353 } else if (os_strcmp(key, "IEs") == 0) {
1354 if (wpas_dbus_get_scan_ies(message, &variant_iter,
1355 ¶ms, &reply) < 0)
1357 } else if (os_strcmp(key, "Channels") == 0) {
1358 if (wpas_dbus_get_scan_channels(message, &variant_iter,
1359 ¶ms, &reply) < 0)
1361 } else if (os_strcmp(key, "AllowRoam") == 0) {
1362 if (wpas_dbus_get_scan_allow_roam(message,
1368 wpa_printf(MSG_DEBUG, "%s[dbus]: Unknown argument %s",
1370 reply = wpas_dbus_error_invalid_args(message, key);
1374 dbus_message_iter_next(&dict_iter);
1378 wpa_printf(MSG_DEBUG, "%s[dbus]: Scan type not specified",
1380 reply = wpas_dbus_error_invalid_args(message, key);
1384 if (os_strcmp(type, "passive") == 0) {
1385 if (params.num_ssids || params.extra_ies_len) {
1386 wpa_printf(MSG_DEBUG,
1387 "%s[dbus]: SSIDs or IEs specified for passive scan.",
1389 reply = wpas_dbus_error_invalid_args(
1391 "You can specify only Channels in passive scan");
1394 if (wpa_s->sched_scanning) {
1395 wpa_printf(MSG_DEBUG,
1396 "%s[dbus]: Stop ongoing sched_scan to allow requested scan to proceed",
1398 wpa_supplicant_cancel_sched_scan(wpa_s);
1401 if (params.freqs && params.freqs[0]) {
1402 wpa_s->last_scan_req = MANUAL_SCAN_REQ;
1403 if (wpa_supplicant_trigger_scan(wpa_s,
1405 reply = wpas_dbus_error_scan_error(
1407 "Scan request rejected");
1410 wpa_s->scan_req = MANUAL_SCAN_REQ;
1411 wpa_supplicant_req_scan(wpa_s, 0, 0);
1414 } else if (os_strcmp(type, "active") == 0) {
1415 if (!params.num_ssids) {
1416 /* Add wildcard ssid */
1419 #ifdef CONFIG_AUTOSCAN
1420 autoscan_deinit(wpa_s);
1421 #endif /* CONFIG_AUTOSCAN */
1422 if (wpa_s->sched_scanning) {
1423 wpa_printf(MSG_DEBUG,
1424 "%s[dbus]: Stop ongoing sched_scan to allow requested scan to proceed",
1426 wpa_supplicant_cancel_sched_scan(wpa_s);
1429 wpa_s->last_scan_req = MANUAL_SCAN_REQ;
1430 if (wpa_supplicant_trigger_scan(wpa_s, ¶ms)) {
1431 reply = wpas_dbus_error_scan_error(
1432 message, "Scan request rejected");
1435 wpa_printf(MSG_DEBUG, "%s[dbus]: Unknown scan type: %s",
1437 reply = wpas_dbus_error_invalid_args(message,
1443 wpa_s->scan_res_handler = scan_only_handler;
1446 for (i = 0; i < WPAS_MAX_SCAN_SSIDS; i++)
1447 os_free((u8 *) params.ssids[i].ssid);
1448 os_free((u8 *) params.extra_ies);
1449 os_free(params.freqs);
1455 * wpas_dbus_handler_abort_scan - Request an ongoing scan to be aborted
1456 * @message: Pointer to incoming dbus message
1457 * @wpa_s: wpa_supplicant structure for a network interface
1458 * Returns: Abort failed or no scan in progress DBus error message on failure
1459 * or NULL otherwise.
1461 * Handler function for "AbortScan" method call of network interface.
1463 DBusMessage * wpas_dbus_handler_abort_scan(DBusMessage *message,
1464 struct wpa_supplicant *wpa_s)
1466 if (wpas_abort_ongoing_scan(wpa_s) < 0)
1467 return dbus_message_new_error(
1468 message, WPAS_DBUS_ERROR_IFACE_SCAN_ERROR,
1469 "Abort failed or no scan in progress");
1476 * wpas_dbus_handler_signal_poll - Request immediate signal properties
1477 * @message: Pointer to incoming dbus message
1478 * @wpa_s: wpa_supplicant structure for a network interface
1479 * Returns: NULL indicating success or DBus error message on failure
1481 * Handler function for "SignalPoll" method call of a network device. Requests
1482 * that wpa_supplicant read signal properties like RSSI, noise, and link
1483 * speed and return them.
1485 DBusMessage * wpas_dbus_handler_signal_poll(DBusMessage *message,
1486 struct wpa_supplicant *wpa_s)
1488 struct wpa_signal_info si;
1489 DBusMessage *reply = NULL;
1490 DBusMessageIter iter, iter_dict, variant_iter;
1493 ret = wpa_drv_signal_poll(wpa_s, &si);
1495 return dbus_message_new_error(message, DBUS_ERROR_FAILED,
1496 "Failed to read signal");
1499 reply = dbus_message_new_method_return(message);
1503 dbus_message_iter_init_append(reply, &iter);
1505 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
1506 "a{sv}", &variant_iter) ||
1507 !wpa_dbus_dict_open_write(&variant_iter, &iter_dict) ||
1508 !wpa_dbus_dict_append_int32(&iter_dict, "rssi",
1509 si.current_signal) ||
1510 !wpa_dbus_dict_append_int32(&iter_dict, "linkspeed",
1511 si.current_txrate / 1000) ||
1512 !wpa_dbus_dict_append_int32(&iter_dict, "noise",
1513 si.current_noise) ||
1514 !wpa_dbus_dict_append_uint32(&iter_dict, "frequency",
1516 (si.chanwidth != CHAN_WIDTH_UNKNOWN &&
1517 !wpa_dbus_dict_append_string(
1518 &iter_dict, "width",
1519 channel_width_to_string(si.chanwidth))) ||
1520 (si.center_frq1 > 0 && si.center_frq2 > 0 &&
1521 (!wpa_dbus_dict_append_int32(&iter_dict, "center-frq1",
1523 !wpa_dbus_dict_append_int32(&iter_dict, "center-frq2",
1524 si.center_frq2))) ||
1526 !wpa_dbus_dict_append_int32(&iter_dict, "avg-rssi",
1528 !wpa_dbus_dict_close_write(&variant_iter, &iter_dict) ||
1529 !dbus_message_iter_close_container(&iter, &variant_iter))
1536 dbus_message_unref(reply);
1537 return wpas_dbus_error_no_memory(message);
1542 * wpas_dbus_handler_disconnect - Terminate the current connection
1543 * @message: Pointer to incoming dbus message
1544 * @wpa_s: wpa_supplicant structure for a network interface
1545 * Returns: NotConnected DBus error message if already not connected
1546 * or NULL otherwise.
1548 * Handler function for "Disconnect" method call of network interface.
1550 DBusMessage * wpas_dbus_handler_disconnect(DBusMessage *message,
1551 struct wpa_supplicant *wpa_s)
1553 if (wpa_s->current_ssid != NULL) {
1554 wpas_request_disconnection(wpa_s);
1558 return dbus_message_new_error(message, WPAS_DBUS_ERROR_NOT_CONNECTED,
1559 "This interface is not connected");
1564 * wpas_dbus_new_iface_add_network - Add a new configured network
1565 * @message: Pointer to incoming dbus message
1566 * @wpa_s: wpa_supplicant structure for a network interface
1567 * Returns: A dbus message containing the object path of the new network
1569 * Handler function for "AddNetwork" method call of a network interface.
1571 DBusMessage * wpas_dbus_handler_add_network(DBusMessage *message,
1572 struct wpa_supplicant *wpa_s)
1574 DBusMessage *reply = NULL;
1575 DBusMessageIter iter;
1576 struct wpa_ssid *ssid = NULL;
1577 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf;
1580 dbus_message_iter_init(message, &iter);
1582 if (wpa_s->dbus_new_path)
1583 ssid = wpa_supplicant_add_network(wpa_s);
1585 wpa_printf(MSG_ERROR, "%s[dbus]: can't add new interface.",
1587 reply = wpas_dbus_error_unknown_error(
1589 "wpa_supplicant could not add a network on this interface.");
1593 dbus_error_init(&error);
1594 if (!set_network_properties(wpa_s, ssid, &iter, &error)) {
1595 wpa_printf(MSG_DEBUG,
1596 "%s[dbus]: control interface couldn't set network properties",
1598 reply = wpas_dbus_reply_new_from_error(message, &error,
1599 DBUS_ERROR_INVALID_ARGS,
1600 "Failed to add network");
1601 dbus_error_free(&error);
1605 /* Construct the object path for this network. */
1606 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
1607 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
1608 wpa_s->dbus_new_path, ssid->id);
1610 reply = dbus_message_new_method_return(message);
1611 if (reply == NULL) {
1612 reply = wpas_dbus_error_no_memory(message);
1615 if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
1616 DBUS_TYPE_INVALID)) {
1617 dbus_message_unref(reply);
1618 reply = wpas_dbus_error_no_memory(message);
1626 wpas_notify_network_removed(wpa_s, ssid);
1627 wpa_config_remove_network(wpa_s->conf, ssid->id);
1634 * wpas_dbus_handler_reassociate - Reassociate
1635 * @message: Pointer to incoming dbus message
1636 * @wpa_s: wpa_supplicant structure for a network interface
1637 * Returns: InterfaceDisabled DBus error message if disabled
1638 * or NULL otherwise.
1640 * Handler function for "Reassociate" method call of network interface.
1642 DBusMessage * wpas_dbus_handler_reassociate(DBusMessage *message,
1643 struct wpa_supplicant *wpa_s)
1645 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED) {
1646 wpas_request_connection(wpa_s);
1650 return dbus_message_new_error(message, WPAS_DBUS_ERROR_IFACE_DISABLED,
1651 "This interface is disabled");
1656 * wpas_dbus_handler_expect_disconnect - ExpectDisconnect
1657 * @message: Pointer to incoming dbus message
1658 * @global: %wpa_supplicant global data structure
1661 * Handler function for notifying system there will be a expected disconnect.
1662 * This will prevent wpa_supplicant from adding blacklists upon next disconnect..
1664 DBusMessage * wpas_dbus_handler_expect_disconnect(DBusMessage *message,
1665 struct wpa_global *global)
1667 struct wpa_supplicant *wpa_s = global->ifaces;
1669 for (; wpa_s; wpa_s = wpa_s->next)
1670 if (wpa_s->wpa_state >= WPA_ASSOCIATED)
1671 wpa_s->own_disconnect_req = 1;
1677 * wpas_dbus_handler_reattach - Reattach to current AP
1678 * @message: Pointer to incoming dbus message
1679 * @wpa_s: wpa_supplicant structure for a network interface
1680 * Returns: NotConnected DBus error message if not connected
1681 * or NULL otherwise.
1683 * Handler function for "Reattach" method call of network interface.
1685 DBusMessage * wpas_dbus_handler_reattach(DBusMessage *message,
1686 struct wpa_supplicant *wpa_s)
1688 if (wpa_s->current_ssid != NULL) {
1689 wpa_s->reattach = 1;
1690 wpas_request_connection(wpa_s);
1694 return dbus_message_new_error(message, WPAS_DBUS_ERROR_NOT_CONNECTED,
1695 "This interface is not connected");
1700 * wpas_dbus_handler_reconnect - Reconnect if disconnected
1701 * @message: Pointer to incoming dbus message
1702 * @wpa_s: wpa_supplicant structure for a network interface
1703 * Returns: InterfaceDisabled DBus error message if disabled
1704 * or NULL otherwise.
1706 * Handler function for "Reconnect" method call of network interface.
1708 DBusMessage * wpas_dbus_handler_reconnect(DBusMessage *message,
1709 struct wpa_supplicant *wpa_s)
1711 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
1712 return dbus_message_new_error(message,
1713 WPAS_DBUS_ERROR_IFACE_DISABLED,
1714 "This interface is disabled");
1717 if (wpa_s->disconnected)
1718 wpas_request_connection(wpa_s);
1724 * wpas_dbus_handler_remove_network - Remove a configured network
1725 * @message: Pointer to incoming dbus message
1726 * @wpa_s: wpa_supplicant structure for a network interface
1727 * Returns: NULL on success or dbus error on failure
1729 * Handler function for "RemoveNetwork" method call of a network interface.
1731 DBusMessage * wpas_dbus_handler_remove_network(DBusMessage *message,
1732 struct wpa_supplicant *wpa_s)
1734 DBusMessage *reply = NULL;
1736 char *iface, *net_id;
1740 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
1743 /* Extract the network ID and ensure the network */
1744 /* is actually a child of this interface */
1745 iface = wpas_dbus_new_decompose_object_path(op,
1746 WPAS_DBUS_NEW_NETWORKS_PART,
1748 if (iface == NULL || net_id == NULL || !wpa_s->dbus_new_path ||
1749 os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
1750 reply = wpas_dbus_error_invalid_args(message, op);
1755 id = strtoul(net_id, NULL, 10);
1757 reply = wpas_dbus_error_invalid_args(message, op);
1761 result = wpa_supplicant_remove_network(wpa_s, id);
1763 reply = wpas_dbus_error_network_unknown(message);
1767 wpa_printf(MSG_ERROR,
1768 "%s[dbus]: error occurred when removing network %d",
1770 reply = wpas_dbus_error_unknown_error(
1772 "error removing the specified network on is interface.");
1782 static void remove_network(void *arg, struct wpa_ssid *ssid)
1784 struct wpa_supplicant *wpa_s = arg;
1786 wpas_notify_network_removed(wpa_s, ssid);
1788 if (wpa_config_remove_network(wpa_s->conf, ssid->id) < 0) {
1789 wpa_printf(MSG_ERROR,
1790 "%s[dbus]: error occurred when removing network %d",
1791 __func__, ssid->id);
1795 if (ssid == wpa_s->current_ssid)
1796 wpa_supplicant_deauthenticate(wpa_s,
1797 WLAN_REASON_DEAUTH_LEAVING);
1802 * wpas_dbus_handler_remove_all_networks - Remove all configured networks
1803 * @message: Pointer to incoming dbus message
1804 * @wpa_s: wpa_supplicant structure for a network interface
1805 * Returns: NULL on success or dbus error on failure
1807 * Handler function for "RemoveAllNetworks" method call of a network interface.
1809 DBusMessage * wpas_dbus_handler_remove_all_networks(
1810 DBusMessage *message, struct wpa_supplicant *wpa_s)
1812 if (wpa_s->sched_scanning)
1813 wpa_supplicant_cancel_sched_scan(wpa_s);
1815 /* NB: could check for failure and return an error */
1816 wpa_config_foreach_network(wpa_s->conf, remove_network, wpa_s);
1822 * wpas_dbus_handler_select_network - Attempt association with a network
1823 * @message: Pointer to incoming dbus message
1824 * @wpa_s: wpa_supplicant structure for a network interface
1825 * Returns: NULL on success or dbus error on failure
1827 * Handler function for "SelectNetwork" method call of network interface.
1829 DBusMessage * wpas_dbus_handler_select_network(DBusMessage *message,
1830 struct wpa_supplicant *wpa_s)
1832 DBusMessage *reply = NULL;
1834 char *iface, *net_id;
1836 struct wpa_ssid *ssid;
1838 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
1841 /* Extract the network ID and ensure the network */
1842 /* is actually a child of this interface */
1843 iface = wpas_dbus_new_decompose_object_path(op,
1844 WPAS_DBUS_NEW_NETWORKS_PART,
1846 if (iface == NULL || net_id == NULL || !wpa_s->dbus_new_path ||
1847 os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
1848 reply = wpas_dbus_error_invalid_args(message, op);
1853 id = strtoul(net_id, NULL, 10);
1855 reply = wpas_dbus_error_invalid_args(message, op);
1859 ssid = wpa_config_get_network(wpa_s->conf, id);
1861 reply = wpas_dbus_error_network_unknown(message);
1865 /* Finally, associate with the network */
1866 wpa_supplicant_select_network(wpa_s, ssid);
1875 * wpas_dbus_handler_network_reply - Reply to a NetworkRequest signal
1876 * @message: Pointer to incoming dbus message
1877 * @wpa_s: wpa_supplicant structure for a network interface
1878 * Returns: NULL on success or dbus error on failure
1880 * Handler function for "NetworkReply" method call of network interface.
1882 DBusMessage * wpas_dbus_handler_network_reply(DBusMessage *message,
1883 struct wpa_supplicant *wpa_s)
1885 #ifdef IEEE8021X_EAPOL
1886 DBusMessage *reply = NULL;
1887 const char *op, *field, *value;
1888 char *iface, *net_id;
1890 struct wpa_ssid *ssid;
1892 if (!dbus_message_get_args(message, NULL,
1893 DBUS_TYPE_OBJECT_PATH, &op,
1894 DBUS_TYPE_STRING, &field,
1895 DBUS_TYPE_STRING, &value,
1897 return wpas_dbus_error_invalid_args(message, NULL);
1899 /* Extract the network ID and ensure the network */
1900 /* is actually a child of this interface */
1901 iface = wpas_dbus_new_decompose_object_path(op,
1902 WPAS_DBUS_NEW_NETWORKS_PART,
1904 if (iface == NULL || net_id == NULL || !wpa_s->dbus_new_path ||
1905 os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
1906 reply = wpas_dbus_error_invalid_args(message, op);
1911 id = strtoul(net_id, NULL, 10);
1913 reply = wpas_dbus_error_invalid_args(message, net_id);
1917 ssid = wpa_config_get_network(wpa_s->conf, id);
1919 reply = wpas_dbus_error_network_unknown(message);
1923 if (wpa_supplicant_ctrl_iface_ctrl_rsp_handle(wpa_s, ssid,
1925 reply = wpas_dbus_error_invalid_args(message, field);
1927 /* Tell EAP to retry immediately */
1928 eapol_sm_notify_ctrl_response(wpa_s->eapol);
1934 #else /* IEEE8021X_EAPOL */
1935 wpa_printf(MSG_DEBUG, "dbus: 802.1X not included");
1936 return wpas_dbus_error_unknown_error(message, "802.1X not included");
1937 #endif /* IEEE8021X_EAPOL */
1941 #ifndef CONFIG_NO_CONFIG_BLOBS
1944 * wpas_dbus_handler_add_blob - Store named binary blob (ie, for certificates)
1945 * @message: Pointer to incoming dbus message
1946 * @wpa_s: %wpa_supplicant data structure
1947 * Returns: A dbus message containing an error on failure or NULL on success
1949 * Asks wpa_supplicant to internally store a binary blobs.
1951 DBusMessage * wpas_dbus_handler_add_blob(DBusMessage *message,
1952 struct wpa_supplicant *wpa_s)
1954 DBusMessage *reply = NULL;
1955 DBusMessageIter iter, array_iter;
1960 struct wpa_config_blob *blob = NULL;
1962 dbus_message_iter_init(message, &iter);
1963 dbus_message_iter_get_basic(&iter, &blob_name);
1965 if (wpa_config_get_blob(wpa_s->conf, blob_name)) {
1966 return dbus_message_new_error(message,
1967 WPAS_DBUS_ERROR_BLOB_EXISTS,
1971 dbus_message_iter_next(&iter);
1972 dbus_message_iter_recurse(&iter, &array_iter);
1974 dbus_message_iter_get_fixed_array(&array_iter, &blob_data, &blob_len);
1976 blob = os_zalloc(sizeof(*blob));
1978 reply = wpas_dbus_error_no_memory(message);
1982 blob->data = os_memdup(blob_data, blob_len);
1983 blob->name = os_strdup(blob_name);
1984 if (!blob->data || !blob->name) {
1985 reply = wpas_dbus_error_no_memory(message);
1988 blob->len = blob_len;
1990 wpa_config_set_blob(wpa_s->conf, blob);
1991 wpas_notify_blob_added(wpa_s, blob->name);
1997 os_free(blob->name);
1998 os_free(blob->data);
2006 * wpas_dbus_handler_get_blob - Get named binary blob (ie, for certificates)
2007 * @message: Pointer to incoming dbus message
2008 * @wpa_s: %wpa_supplicant data structure
2009 * Returns: A dbus message containing array of bytes (blob)
2011 * Gets one wpa_supplicant's binary blobs.
2013 DBusMessage * wpas_dbus_handler_get_blob(DBusMessage *message,
2014 struct wpa_supplicant *wpa_s)
2016 DBusMessage *reply = NULL;
2017 DBusMessageIter iter, array_iter;
2020 const struct wpa_config_blob *blob;
2022 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &blob_name,
2025 blob = wpa_config_get_blob(wpa_s->conf, blob_name);
2027 return dbus_message_new_error(message,
2028 WPAS_DBUS_ERROR_BLOB_UNKNOWN,
2032 reply = dbus_message_new_method_return(message);
2034 return wpas_dbus_error_no_memory(message);
2036 dbus_message_iter_init_append(reply, &iter);
2038 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
2039 DBUS_TYPE_BYTE_AS_STRING,
2041 !dbus_message_iter_append_fixed_array(&array_iter, DBUS_TYPE_BYTE,
2042 &(blob->data), blob->len) ||
2043 !dbus_message_iter_close_container(&iter, &array_iter)) {
2044 dbus_message_unref(reply);
2045 reply = wpas_dbus_error_no_memory(message);
2053 * wpas_remove_handler_remove_blob - Remove named binary blob
2054 * @message: Pointer to incoming dbus message
2055 * @wpa_s: %wpa_supplicant data structure
2056 * Returns: NULL on success or dbus error
2058 * Asks wpa_supplicant to internally remove a binary blobs.
2060 DBusMessage * wpas_dbus_handler_remove_blob(DBusMessage *message,
2061 struct wpa_supplicant *wpa_s)
2063 DBusMessage *reply = NULL;
2066 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &blob_name,
2069 if (wpa_config_remove_blob(wpa_s->conf, blob_name)) {
2070 return dbus_message_new_error(message,
2071 WPAS_DBUS_ERROR_BLOB_UNKNOWN,
2074 wpas_notify_blob_removed(wpa_s, blob_name);
2080 #endif /* CONFIG_NO_CONFIG_BLOBS */
2084 * wpas_dbus_handler_flush_bss - Flush the BSS cache
2085 * @message: Pointer to incoming dbus message
2086 * @wpa_s: wpa_supplicant structure for a network interface
2089 * Handler function for "FlushBSS" method call of network interface.
2091 DBusMessage * wpas_dbus_handler_flush_bss(DBusMessage *message,
2092 struct wpa_supplicant *wpa_s)
2096 dbus_message_get_args(message, NULL, DBUS_TYPE_UINT32, &age,
2100 wpa_bss_flush(wpa_s);
2102 wpa_bss_flush_by_age(wpa_s, age);
2108 #ifdef CONFIG_AUTOSCAN
2110 * wpas_dbus_handler_autoscan - Set autoscan parameters for the interface
2111 * @message: Pointer to incoming dbus message
2112 * @wpa_s: wpa_supplicant structure for a network interface
2115 * Handler function for "AutoScan" method call of network interface.
2117 DBusMessage * wpas_dbus_handler_autoscan(DBusMessage *message,
2118 struct wpa_supplicant *wpa_s)
2120 DBusMessage *reply = NULL;
2121 enum wpa_states state = wpa_s->wpa_state;
2124 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &arg,
2127 if (arg != NULL && os_strlen(arg) > 0) {
2130 tmp = os_strdup(arg);
2132 reply = wpas_dbus_error_no_memory(message);
2134 os_free(wpa_s->conf->autoscan);
2135 wpa_s->conf->autoscan = tmp;
2136 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
2137 autoscan_init(wpa_s, 1);
2138 else if (state == WPA_SCANNING)
2139 wpa_supplicant_reinit_autoscan(wpa_s);
2141 } else if (arg != NULL && os_strlen(arg) == 0) {
2142 os_free(wpa_s->conf->autoscan);
2143 wpa_s->conf->autoscan = NULL;
2144 autoscan_deinit(wpa_s);
2146 reply = dbus_message_new_error(message,
2147 DBUS_ERROR_INVALID_ARGS,
2152 #endif /* CONFIG_AUTOSCAN */
2156 * wpas_dbus_handler_eap_logoff - IEEE 802.1X EAPOL state machine logoff
2157 * @message: Pointer to incoming dbus message
2158 * @wpa_s: wpa_supplicant structure for a network interface
2161 * Handler function for "EAPLogoff" method call of network interface.
2163 DBusMessage * wpas_dbus_handler_eap_logoff(DBusMessage *message,
2164 struct wpa_supplicant *wpa_s)
2166 eapol_sm_notify_logoff(wpa_s->eapol, TRUE);
2172 * wpas_dbus_handler_eap_logon - IEEE 802.1X EAPOL state machine logon
2173 * @message: Pointer to incoming dbus message
2174 * @wpa_s: wpa_supplicant structure for a network interface
2177 * Handler function for "EAPLogin" method call of network interface.
2179 DBusMessage * wpas_dbus_handler_eap_logon(DBusMessage *message,
2180 struct wpa_supplicant *wpa_s)
2182 eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
2189 static int get_peer_hwaddr_helper(DBusMessage *message, const char *func_name,
2190 u8 *peer_address, DBusMessage **error)
2192 const char *peer_string;
2196 if (!dbus_message_get_args(message, NULL,
2197 DBUS_TYPE_STRING, &peer_string,
2198 DBUS_TYPE_INVALID)) {
2199 *error = wpas_dbus_error_invalid_args(message, NULL);
2203 if (hwaddr_aton(peer_string, peer_address)) {
2204 wpa_printf(MSG_DEBUG, "%s: invalid address '%s'",
2205 func_name, peer_string);
2206 *error = wpas_dbus_error_invalid_args(
2207 message, "Invalid hardware address format");
2216 * wpas_dbus_handler_tdls_discover - Discover TDLS peer
2217 * @message: Pointer to incoming dbus message
2218 * @wpa_s: wpa_supplicant structure for a network interface
2219 * Returns: NULL indicating success or DBus error message on failure
2221 * Handler function for "TDLSDiscover" method call of network interface.
2223 DBusMessage * wpas_dbus_handler_tdls_discover(DBusMessage *message,
2224 struct wpa_supplicant *wpa_s)
2227 DBusMessage *error_reply;
2230 if (get_peer_hwaddr_helper(message, __func__, peer, &error_reply) < 0)
2233 wpa_printf(MSG_DEBUG, "DBUS TDLS_DISCOVER " MACSTR, MAC2STR(peer));
2235 if (wpa_tdls_is_external_setup(wpa_s->wpa))
2236 ret = wpa_tdls_send_discovery_request(wpa_s->wpa, peer);
2238 ret = wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer);
2241 return wpas_dbus_error_unknown_error(
2242 message, "error performing TDLS discovery");
2250 * wpas_dbus_handler_tdls_setup - Setup TDLS session
2251 * @message: Pointer to incoming dbus message
2252 * @wpa_s: wpa_supplicant structure for a network interface
2253 * Returns: NULL indicating success or DBus error message on failure
2255 * Handler function for "TDLSSetup" method call of network interface.
2257 DBusMessage * wpas_dbus_handler_tdls_setup(DBusMessage *message,
2258 struct wpa_supplicant *wpa_s)
2261 DBusMessage *error_reply;
2264 if (get_peer_hwaddr_helper(message, __func__, peer, &error_reply) < 0)
2267 wpa_printf(MSG_DEBUG, "DBUS TDLS_SETUP " MACSTR, MAC2STR(peer));
2269 wpa_tdls_remove(wpa_s->wpa, peer);
2270 if (wpa_tdls_is_external_setup(wpa_s->wpa))
2271 ret = wpa_tdls_start(wpa_s->wpa, peer);
2273 ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
2276 return wpas_dbus_error_unknown_error(
2277 message, "error performing TDLS setup");
2285 * wpas_dbus_handler_tdls_status - Return TDLS session status
2286 * @message: Pointer to incoming dbus message
2287 * @wpa_s: wpa_supplicant structure for a network interface
2288 * Returns: A string representing the state of the link to this TDLS peer
2290 * Handler function for "TDLSStatus" method call of network interface.
2292 DBusMessage * wpas_dbus_handler_tdls_status(DBusMessage *message,
2293 struct wpa_supplicant *wpa_s)
2297 const char *tdls_status;
2299 if (get_peer_hwaddr_helper(message, __func__, peer, &reply) < 0)
2302 wpa_printf(MSG_DEBUG, "DBUS TDLS_STATUS " MACSTR, MAC2STR(peer));
2304 tdls_status = wpa_tdls_get_link_status(wpa_s->wpa, peer);
2306 reply = dbus_message_new_method_return(message);
2307 dbus_message_append_args(reply, DBUS_TYPE_STRING,
2308 &tdls_status, DBUS_TYPE_INVALID);
2314 * wpas_dbus_handler_tdls_teardown - Teardown TDLS session
2315 * @message: Pointer to incoming dbus message
2316 * @wpa_s: wpa_supplicant structure for a network interface
2317 * Returns: NULL indicating success or DBus error message on failure
2319 * Handler function for "TDLSTeardown" method call of network interface.
2321 DBusMessage * wpas_dbus_handler_tdls_teardown(DBusMessage *message,
2322 struct wpa_supplicant *wpa_s)
2325 DBusMessage *error_reply;
2328 if (get_peer_hwaddr_helper(message, __func__, peer, &error_reply) < 0)
2331 wpa_printf(MSG_DEBUG, "DBUS TDLS_TEARDOWN " MACSTR, MAC2STR(peer));
2333 if (wpa_tdls_is_external_setup(wpa_s->wpa))
2334 ret = wpa_tdls_teardown_link(
2336 WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
2338 ret = wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
2341 return wpas_dbus_error_unknown_error(
2342 message, "error performing TDLS teardown");
2349 * wpas_dbus_handler_tdls_channel_switch - Enable channel switching with TDLS peer
2350 * @message: Pointer to incoming dbus message
2351 * @wpa_s: wpa_supplicant structure for a network interface
2352 * Returns: NULL indicating success or DBus error message on failure
2354 * Handler function for "TDLSChannelSwitch" method call of network interface.
2357 wpas_dbus_handler_tdls_channel_switch(DBusMessage *message,
2358 struct wpa_supplicant *wpa_s)
2360 DBusMessageIter iter, iter_dict;
2361 struct wpa_dbus_dict_entry entry;
2363 struct hostapd_freq_params freq_params;
2366 int is_peer_present = 0;
2368 if (!wpa_tdls_is_external_setup(wpa_s->wpa)) {
2369 wpa_printf(MSG_INFO,
2370 "tdls_chanswitch: Only supported with external setup");
2371 return wpas_dbus_error_unknown_error(message, "TDLS is not using external setup");
2374 os_memset(&freq_params, 0, sizeof(freq_params));
2376 dbus_message_iter_init(message, &iter);
2378 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
2379 return wpas_dbus_error_invalid_args(message, NULL);
2381 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2382 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2383 return wpas_dbus_error_invalid_args(message, NULL);
2385 if (os_strcmp(entry.key, "PeerAddress") == 0 &&
2386 entry.type == DBUS_TYPE_STRING) {
2387 if (hwaddr_aton(entry.str_value, peer)) {
2388 wpa_printf(MSG_DEBUG,
2389 "tdls_chanswitch: Invalid address '%s'",
2391 wpa_dbus_dict_entry_clear(&entry);
2392 return wpas_dbus_error_invalid_args(message,
2396 is_peer_present = 1;
2397 } else if (os_strcmp(entry.key, "OperClass") == 0 &&
2398 entry.type == DBUS_TYPE_BYTE) {
2399 oper_class = entry.byte_value;
2400 } else if (os_strcmp(entry.key, "Frequency") == 0 &&
2401 entry.type == DBUS_TYPE_UINT32) {
2402 freq_params.freq = entry.uint32_value;
2403 } else if (os_strcmp(entry.key, "SecChannelOffset") == 0 &&
2404 entry.type == DBUS_TYPE_UINT32) {
2405 freq_params.sec_channel_offset = entry.uint32_value;
2406 } else if (os_strcmp(entry.key, "CenterFrequency1") == 0 &&
2407 entry.type == DBUS_TYPE_UINT32) {
2408 freq_params.center_freq1 = entry.uint32_value;
2409 } else if (os_strcmp(entry.key, "CenterFrequency2") == 0 &&
2410 entry.type == DBUS_TYPE_UINT32) {
2411 freq_params.center_freq2 = entry.uint32_value;
2412 } else if (os_strcmp(entry.key, "Bandwidth") == 0 &&
2413 entry.type == DBUS_TYPE_UINT32) {
2414 freq_params.bandwidth = entry.uint32_value;
2415 } else if (os_strcmp(entry.key, "HT") == 0 &&
2416 entry.type == DBUS_TYPE_BOOLEAN) {
2417 freq_params.ht_enabled = entry.bool_value;
2418 } else if (os_strcmp(entry.key, "VHT") == 0 &&
2419 entry.type == DBUS_TYPE_BOOLEAN) {
2420 freq_params.vht_enabled = entry.bool_value;
2422 wpa_dbus_dict_entry_clear(&entry);
2423 return wpas_dbus_error_invalid_args(message, NULL);
2426 wpa_dbus_dict_entry_clear(&entry);
2429 if (oper_class == 0) {
2430 wpa_printf(MSG_INFO,
2431 "tdls_chanswitch: Invalid op class provided");
2432 return wpas_dbus_error_invalid_args(
2433 message, "Invalid op class provided");
2436 if (freq_params.freq == 0) {
2437 wpa_printf(MSG_INFO,
2438 "tdls_chanswitch: Invalid freq provided");
2439 return wpas_dbus_error_invalid_args(message,
2440 "Invalid freq provided");
2443 if (is_peer_present == 0) {
2444 wpa_printf(MSG_DEBUG,
2445 "tdls_chanswitch: peer address not provided");
2446 return wpas_dbus_error_invalid_args(
2447 message, "peer address not provided");
2450 wpa_printf(MSG_DEBUG, "dbus: TDLS_CHAN_SWITCH " MACSTR
2451 " OP CLASS %d FREQ %d CENTER1 %d CENTER2 %d BW %d SEC_OFFSET %d%s%s",
2452 MAC2STR(peer), oper_class, freq_params.freq,
2453 freq_params.center_freq1, freq_params.center_freq2,
2454 freq_params.bandwidth, freq_params.sec_channel_offset,
2455 freq_params.ht_enabled ? " HT" : "",
2456 freq_params.vht_enabled ? " VHT" : "");
2458 ret = wpa_tdls_enable_chan_switch(wpa_s->wpa, peer, oper_class,
2461 return wpas_dbus_error_unknown_error(
2462 message, "error processing TDLS channel switch");
2468 * wpas_dbus_handler_tdls_cancel_channel_switch - Disable channel switching with TDLS peer
2469 * @message: Pointer to incoming dbus message
2470 * @wpa_s: wpa_supplicant structure for a network interface
2471 * Returns: NULL indicating success or DBus error message on failure
2473 * Handler function for "TDLSCancelChannelSwitch" method call of network
2477 wpas_dbus_handler_tdls_cancel_channel_switch(DBusMessage *message,
2478 struct wpa_supplicant *wpa_s)
2481 DBusMessage *error_reply;
2484 if (get_peer_hwaddr_helper(message, __func__, peer, &error_reply) < 0)
2487 wpa_printf(MSG_DEBUG, "dbus: TDLS_CANCEL_CHAN_SWITCH " MACSTR,
2490 ret = wpa_tdls_disable_chan_switch(wpa_s->wpa, peer);
2492 return wpas_dbus_error_unknown_error(
2493 message, "error canceling TDLS channel switch");
2498 #endif /* CONFIG_TDLS */
2501 #ifndef CONFIG_NO_CONFIG_WRITE
2503 * wpas_dbus_handler_save_config - Save configuration to configuration file
2504 * @message: Pointer to incoming dbus message
2505 * @wpa_s: wpa_supplicant structure for a network interface
2506 * Returns: NULL on Success, Otherwise errror message
2508 * Handler function for "SaveConfig" method call of network interface.
2510 DBusMessage * wpas_dbus_handler_save_config(DBusMessage *message,
2511 struct wpa_supplicant *wpa_s)
2515 if (!wpa_s->conf->update_config) {
2516 return wpas_dbus_error_unknown_error(
2518 "Not allowed to update configuration (update_config=0)");
2521 ret = wpa_config_write(wpa_s->confname, wpa_s->conf);
2523 return wpas_dbus_error_unknown_error(
2524 message, "Failed to update configuration");
2527 #endif /* CONFIG_NO_CONFIG_WRITE */
2531 * wpas_dbus_handler_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
2532 * @message: Pointer to incoming dbus message
2533 * @wpa_s: %wpa_supplicant data structure
2534 * Returns: A dbus message containing an error on failure or NULL on success
2536 * Sets the PKCS #11 engine and module path.
2538 DBusMessage * wpas_dbus_handler_set_pkcs11_engine_and_module_path(
2539 DBusMessage *message, struct wpa_supplicant *wpa_s)
2541 DBusMessageIter iter;
2543 char *pkcs11_engine_path = NULL;
2544 char *pkcs11_module_path = NULL;
2546 dbus_message_iter_init(message, &iter);
2547 dbus_message_iter_get_basic(&iter, &value);
2548 if (value == NULL) {
2549 return dbus_message_new_error(
2550 message, DBUS_ERROR_INVALID_ARGS,
2551 "Invalid pkcs11_engine_path argument");
2553 /* Empty path defaults to NULL */
2554 if (os_strlen(value))
2555 pkcs11_engine_path = value;
2557 dbus_message_iter_next(&iter);
2558 dbus_message_iter_get_basic(&iter, &value);
2559 if (value == NULL) {
2560 os_free(pkcs11_engine_path);
2561 return dbus_message_new_error(
2562 message, DBUS_ERROR_INVALID_ARGS,
2563 "Invalid pkcs11_module_path argument");
2565 /* Empty path defaults to NULL */
2566 if (os_strlen(value))
2567 pkcs11_module_path = value;
2569 if (wpas_set_pkcs11_engine_and_module_path(wpa_s, pkcs11_engine_path,
2570 pkcs11_module_path))
2571 return dbus_message_new_error(
2572 message, DBUS_ERROR_FAILED,
2573 "Reinit of the EAPOL state machine with the new PKCS #11 engine and module path failed.");
2575 if (wpa_s->dbus_new_path) {
2576 wpa_dbus_mark_property_changed(
2577 wpa_s->global->dbus, wpa_s->dbus_new_path,
2578 WPAS_DBUS_NEW_IFACE_INTERFACE, "PKCS11EnginePath");
2579 wpa_dbus_mark_property_changed(
2580 wpa_s->global->dbus, wpa_s->dbus_new_path,
2581 WPAS_DBUS_NEW_IFACE_INTERFACE, "PKCS11ModulePath");
2589 * wpas_dbus_getter_capabilities - Return interface capabilities
2590 * @iter: Pointer to incoming dbus message iter
2591 * @error: Location to store error on failure
2592 * @user_data: Function specific data
2593 * Returns: TRUE on success, FALSE on failure
2595 * Getter for "Capabilities" property of an interface.
2597 dbus_bool_t wpas_dbus_getter_capabilities(
2598 const struct wpa_dbus_property_desc *property_desc,
2599 DBusMessageIter *iter, DBusError *error, void *user_data)
2601 struct wpa_supplicant *wpa_s = user_data;
2602 struct wpa_driver_capa capa;
2604 DBusMessageIter iter_dict, iter_dict_entry, iter_dict_val, iter_array,
2606 const char *scans[] = { "active", "passive", "ssid" };
2608 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
2609 "a{sv}", &variant_iter) ||
2610 !wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
2613 res = wpa_drv_get_capa(wpa_s, &capa);
2615 /***** pairwise cipher */
2617 const char *args[] = {"ccmp", "tkip", "none"};
2619 if (!wpa_dbus_dict_append_string_array(
2620 &iter_dict, "Pairwise", args,
2624 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Pairwise",
2628 ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP_256) &&
2629 !wpa_dbus_dict_string_array_add_element(
2630 &iter_array, "ccmp-256")) ||
2631 ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP_256) &&
2632 !wpa_dbus_dict_string_array_add_element(
2633 &iter_array, "gcmp-256")) ||
2634 ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) &&
2635 !wpa_dbus_dict_string_array_add_element(
2636 &iter_array, "ccmp")) ||
2637 ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP) &&
2638 !wpa_dbus_dict_string_array_add_element(
2639 &iter_array, "gcmp")) ||
2640 ((capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) &&
2641 !wpa_dbus_dict_string_array_add_element(
2642 &iter_array, "tkip")) ||
2643 ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) &&
2644 !wpa_dbus_dict_string_array_add_element(
2645 &iter_array, "none")) ||
2646 !wpa_dbus_dict_end_string_array(&iter_dict,
2653 /***** group cipher */
2655 const char *args[] = {
2656 "ccmp", "tkip", "wep104", "wep40"
2659 if (!wpa_dbus_dict_append_string_array(
2660 &iter_dict, "Group", args,
2664 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Group",
2668 ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP_256) &&
2669 !wpa_dbus_dict_string_array_add_element(
2670 &iter_array, "ccmp-256")) ||
2671 ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP_256) &&
2672 !wpa_dbus_dict_string_array_add_element(
2673 &iter_array, "gcmp-256")) ||
2674 ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) &&
2675 !wpa_dbus_dict_string_array_add_element(
2676 &iter_array, "ccmp")) ||
2677 ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP) &&
2678 !wpa_dbus_dict_string_array_add_element(
2679 &iter_array, "gcmp")) ||
2680 ((capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) &&
2681 !wpa_dbus_dict_string_array_add_element(
2682 &iter_array, "tkip")) ||
2683 ((capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) &&
2684 !wpa_dbus_dict_string_array_add_element(
2685 &iter_array, "wep104")) ||
2686 ((capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) &&
2687 !wpa_dbus_dict_string_array_add_element(
2688 &iter_array, "wep40")) ||
2689 !wpa_dbus_dict_end_string_array(&iter_dict,
2696 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "GroupMgmt",
2700 (res == 0 && (capa.enc & WPA_DRIVER_CAPA_ENC_BIP) &&
2701 !wpa_dbus_dict_string_array_add_element(
2702 &iter_array, "aes-128-cmac")) ||
2703 (res == 0 && (capa.enc & WPA_DRIVER_CAPA_ENC_BIP_GMAC_128) &&
2704 !wpa_dbus_dict_string_array_add_element(
2705 &iter_array, "bip-gmac-128")) ||
2706 (res == 0 && (capa.enc & WPA_DRIVER_CAPA_ENC_BIP_GMAC_256) &&
2707 !wpa_dbus_dict_string_array_add_element(
2708 &iter_array, "bip-gmac-256")) ||
2709 (res == 0 && (capa.enc & WPA_DRIVER_CAPA_ENC_BIP_CMAC_256) &&
2710 !wpa_dbus_dict_string_array_add_element(
2711 &iter_array, "bip-cmac-256")) ||
2712 !wpa_dbus_dict_end_string_array(&iter_dict,
2718 /***** key management */
2720 const char *args[] = {
2721 "wpa-psk", "wpa-eap", "ieee8021x", "wpa-none",
2724 #endif /* CONFIG_WPS */
2727 if (!wpa_dbus_dict_append_string_array(
2728 &iter_dict, "KeyMgmt", args,
2732 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "KeyMgmt",
2736 !wpa_dbus_dict_string_array_add_element(&iter_array,
2738 !wpa_dbus_dict_string_array_add_element(&iter_array,
2742 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
2743 WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
2744 if (!wpa_dbus_dict_string_array_add_element(
2745 &iter_array, "wpa-eap") ||
2746 ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT) &&
2747 !wpa_dbus_dict_string_array_add_element(
2748 &iter_array, "wpa-ft-eap")))
2751 /* TODO: Ensure that driver actually supports sha256 encryption. */
2752 #ifdef CONFIG_IEEE80211W
2753 if (!wpa_dbus_dict_string_array_add_element(
2754 &iter_array, "wpa-eap-sha256"))
2756 #endif /* CONFIG_IEEE80211W */
2759 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
2760 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
2761 if (!wpa_dbus_dict_string_array_add_element(
2762 &iter_array, "wpa-psk") ||
2764 WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK) &&
2765 !wpa_dbus_dict_string_array_add_element(
2766 &iter_array, "wpa-ft-psk")))
2769 /* TODO: Ensure that driver actually supports sha256 encryption. */
2770 #ifdef CONFIG_IEEE80211W
2771 if (!wpa_dbus_dict_string_array_add_element(
2772 &iter_array, "wpa-psk-sha256"))
2774 #endif /* CONFIG_IEEE80211W */
2777 if ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) &&
2778 !wpa_dbus_dict_string_array_add_element(&iter_array,
2784 if (!wpa_dbus_dict_string_array_add_element(&iter_array,
2787 #endif /* CONFIG_WPS */
2789 if (!wpa_dbus_dict_end_string_array(&iter_dict,
2796 /***** WPA protocol */
2798 const char *args[] = { "rsn", "wpa" };
2800 if (!wpa_dbus_dict_append_string_array(
2801 &iter_dict, "Protocol", args,
2805 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Protocol",
2809 ((capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
2810 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) &&
2811 !wpa_dbus_dict_string_array_add_element(
2812 &iter_array, "rsn")) ||
2813 ((capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
2814 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) &&
2815 !wpa_dbus_dict_string_array_add_element(
2816 &iter_array, "wpa")) ||
2817 !wpa_dbus_dict_end_string_array(&iter_dict,
2826 const char *args[] = { "open", "shared", "leap" };
2828 if (!wpa_dbus_dict_append_string_array(
2829 &iter_dict, "AuthAlg", args,
2833 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "AuthAlg",
2839 if (((capa.auth & WPA_DRIVER_AUTH_OPEN) &&
2840 !wpa_dbus_dict_string_array_add_element(
2841 &iter_array, "open")) ||
2842 ((capa.auth & WPA_DRIVER_AUTH_SHARED) &&
2843 !wpa_dbus_dict_string_array_add_element(
2844 &iter_array, "shared")) ||
2845 ((capa.auth & WPA_DRIVER_AUTH_LEAP) &&
2846 !wpa_dbus_dict_string_array_add_element(
2847 &iter_array, "leap")) ||
2848 !wpa_dbus_dict_end_string_array(&iter_dict,
2856 if (!wpa_dbus_dict_append_string_array(&iter_dict, "Scan", scans,
2861 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Modes",
2865 !wpa_dbus_dict_string_array_add_element(
2866 &iter_array, "infrastructure") ||
2867 (res >= 0 && (capa.flags & WPA_DRIVER_FLAGS_IBSS) &&
2868 !wpa_dbus_dict_string_array_add_element(
2869 &iter_array, "ad-hoc")) ||
2870 (res >= 0 && (capa.flags & WPA_DRIVER_FLAGS_AP) &&
2871 !wpa_dbus_dict_string_array_add_element(
2872 &iter_array, "ap")) ||
2873 (res >= 0 && (capa.flags & WPA_DRIVER_FLAGS_P2P_CAPABLE) &&
2874 !wpa_s->conf->p2p_disabled &&
2875 !wpa_dbus_dict_string_array_add_element(
2876 &iter_array, "p2p")) ||
2878 (res >= 0 && (capa.flags & WPA_DRIVER_FLAGS_MESH) &&
2879 !wpa_dbus_dict_string_array_add_element(
2880 &iter_array, "mesh")) ||
2881 #endif /* CONFIG_MESH */
2882 !wpa_dbus_dict_end_string_array(&iter_dict,
2890 dbus_int32_t max_scan_ssid = capa.max_scan_ssids;
2892 if (!wpa_dbus_dict_append_int32(&iter_dict, "MaxScanSSID",
2897 if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict) ||
2898 !dbus_message_iter_close_container(iter, &variant_iter))
2904 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
2910 * wpas_dbus_getter_state - Get interface state
2911 * @iter: Pointer to incoming dbus message iter
2912 * @error: Location to store error on failure
2913 * @user_data: Function specific data
2914 * Returns: TRUE on success, FALSE on failure
2916 * Getter for "State" property.
2918 dbus_bool_t wpas_dbus_getter_state(
2919 const struct wpa_dbus_property_desc *property_desc,
2920 DBusMessageIter *iter, DBusError *error, void *user_data)
2922 struct wpa_supplicant *wpa_s = user_data;
2923 const char *str_state;
2924 char *state_ls, *tmp;
2925 dbus_bool_t success = FALSE;
2927 str_state = wpa_supplicant_state_txt(wpa_s->wpa_state);
2929 /* make state string lowercase to fit new DBus API convention
2931 state_ls = tmp = os_strdup(str_state);
2933 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
2937 *tmp = tolower(*tmp);
2941 success = wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
2951 * wpas_dbus_new_iface_get_scanning - Get interface scanning state
2952 * @iter: Pointer to incoming dbus message iter
2953 * @error: Location to store error on failure
2954 * @user_data: Function specific data
2955 * Returns: TRUE on success, FALSE on failure
2957 * Getter for "scanning" property.
2959 dbus_bool_t wpas_dbus_getter_scanning(
2960 const struct wpa_dbus_property_desc *property_desc,
2961 DBusMessageIter *iter, DBusError *error, void *user_data)
2963 struct wpa_supplicant *wpa_s = user_data;
2964 dbus_bool_t scanning = wpa_s->scanning ? TRUE : FALSE;
2966 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
2972 * wpas_dbus_getter_ap_scan - Control roaming mode
2973 * @iter: Pointer to incoming dbus message iter
2974 * @error: Location to store error on failure
2975 * @user_data: Function specific data
2976 * Returns: TRUE on success, FALSE on failure
2978 * Getter function for "ApScan" property.
2980 dbus_bool_t wpas_dbus_getter_ap_scan(
2981 const struct wpa_dbus_property_desc *property_desc,
2982 DBusMessageIter *iter, DBusError *error, void *user_data)
2984 struct wpa_supplicant *wpa_s = user_data;
2985 dbus_uint32_t ap_scan = wpa_s->conf->ap_scan;
2987 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
2993 * wpas_dbus_setter_ap_scan - Control roaming mode
2994 * @iter: Pointer to incoming dbus message iter
2995 * @error: Location to store error on failure
2996 * @user_data: Function specific data
2997 * Returns: TRUE on success, FALSE on failure
2999 * Setter function for "ApScan" property.
3001 dbus_bool_t wpas_dbus_setter_ap_scan(
3002 const struct wpa_dbus_property_desc *property_desc,
3003 DBusMessageIter *iter, DBusError *error, void *user_data)
3005 struct wpa_supplicant *wpa_s = user_data;
3006 dbus_uint32_t ap_scan;
3008 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
3012 if (wpa_supplicant_set_ap_scan(wpa_s, ap_scan)) {
3013 dbus_set_error_const(error, DBUS_ERROR_FAILED,
3014 "ap_scan must be 0, 1, or 2");
3022 * wpas_dbus_getter_fast_reauth - Control fast
3023 * reauthentication (TLS session resumption)
3024 * @iter: Pointer to incoming dbus message iter
3025 * @error: Location to store error on failure
3026 * @user_data: Function specific data
3027 * Returns: TRUE on success, FALSE on failure
3029 * Getter function for "FastReauth" property.
3031 dbus_bool_t wpas_dbus_getter_fast_reauth(
3032 const struct wpa_dbus_property_desc *property_desc,
3033 DBusMessageIter *iter, DBusError *error, void *user_data)
3035 struct wpa_supplicant *wpa_s = user_data;
3036 dbus_bool_t fast_reauth = wpa_s->conf->fast_reauth ? TRUE : FALSE;
3038 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
3039 &fast_reauth, error);
3044 * wpas_dbus_setter_fast_reauth - Control fast
3045 * reauthentication (TLS session resumption)
3046 * @iter: Pointer to incoming dbus message iter
3047 * @error: Location to store error on failure
3048 * @user_data: Function specific data
3049 * Returns: TRUE on success, FALSE on failure
3051 * Setter function for "FastReauth" property.
3053 dbus_bool_t wpas_dbus_setter_fast_reauth(
3054 const struct wpa_dbus_property_desc *property_desc,
3055 DBusMessageIter *iter, DBusError *error, void *user_data)
3057 struct wpa_supplicant *wpa_s = user_data;
3058 dbus_bool_t fast_reauth;
3060 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
3064 wpa_s->conf->fast_reauth = fast_reauth;
3070 * wpas_dbus_getter_disconnect_reason - Get most recent reason for disconnect
3071 * @iter: Pointer to incoming dbus message iter
3072 * @error: Location to store error on failure
3073 * @user_data: Function specific data
3074 * Returns: TRUE on success, FALSE on failure
3076 * Getter for "DisconnectReason" property. The reason is negative if it is
3077 * locally generated.
3079 dbus_bool_t wpas_dbus_getter_disconnect_reason(
3080 const struct wpa_dbus_property_desc *property_desc,
3081 DBusMessageIter *iter, DBusError *error, void *user_data)
3083 struct wpa_supplicant *wpa_s = user_data;
3084 dbus_int32_t reason = wpa_s->disconnect_reason;
3086 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
3092 * wpas_dbus_getter_assoc_status_code - Get most recent failed assoc status code
3093 * @iter: Pointer to incoming dbus message iter
3094 * @error: Location to store error on failure
3095 * @user_data: Function specific data
3096 * Returns: TRUE on success, FALSE on failure
3098 * Getter for "AssocStatusCode" property.
3100 dbus_bool_t wpas_dbus_getter_assoc_status_code(
3101 const struct wpa_dbus_property_desc *property_desc,
3102 DBusMessageIter *iter, DBusError *error, void *user_data)
3104 struct wpa_supplicant *wpa_s = user_data;
3105 dbus_int32_t status_code = wpa_s->assoc_status_code;
3107 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
3108 &status_code, error);
3113 * wpas_dbus_getter_bss_expire_age - Get BSS entry expiration age
3114 * @iter: Pointer to incoming dbus message iter
3115 * @error: Location to store error on failure
3116 * @user_data: Function specific data
3117 * Returns: TRUE on success, FALSE on failure
3119 * Getter function for "BSSExpireAge" property.
3121 dbus_bool_t wpas_dbus_getter_bss_expire_age(
3122 const struct wpa_dbus_property_desc *property_desc,
3123 DBusMessageIter *iter, DBusError *error, void *user_data)
3125 struct wpa_supplicant *wpa_s = user_data;
3126 dbus_uint32_t expire_age = wpa_s->conf->bss_expiration_age;
3128 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
3129 &expire_age, error);
3134 * wpas_dbus_setter_bss_expire_age - Control BSS entry expiration age
3135 * @iter: Pointer to incoming dbus message iter
3136 * @error: Location to store error on failure
3137 * @user_data: Function specific data
3138 * Returns: TRUE on success, FALSE on failure
3140 * Setter function for "BSSExpireAge" property.
3142 dbus_bool_t wpas_dbus_setter_bss_expire_age(
3143 const struct wpa_dbus_property_desc *property_desc,
3144 DBusMessageIter *iter, DBusError *error, void *user_data)
3146 struct wpa_supplicant *wpa_s = user_data;
3147 dbus_uint32_t expire_age;
3149 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
3153 if (wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age)) {
3154 dbus_set_error_const(error, DBUS_ERROR_FAILED,
3155 "BSSExpireAge must be >= 10");
3163 * wpas_dbus_getter_bss_expire_count - Get BSS entry expiration scan count
3164 * @iter: Pointer to incoming dbus message iter
3165 * @error: Location to store error on failure
3166 * @user_data: Function specific data
3167 * Returns: TRUE on success, FALSE on failure
3169 * Getter function for "BSSExpireCount" property.
3171 dbus_bool_t wpas_dbus_getter_bss_expire_count(
3172 const struct wpa_dbus_property_desc *property_desc,
3173 DBusMessageIter *iter, DBusError *error, void *user_data)
3175 struct wpa_supplicant *wpa_s = user_data;
3176 dbus_uint32_t expire_count = wpa_s->conf->bss_expiration_scan_count;
3178 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
3179 &expire_count, error);
3184 * wpas_dbus_setter_bss_expire_count - Control BSS entry expiration scan count
3185 * @iter: Pointer to incoming dbus message iter
3186 * @error: Location to store error on failure
3187 * @user_data: Function specific data
3188 * Returns: TRUE on success, FALSE on failure
3190 * Setter function for "BSSExpireCount" property.
3192 dbus_bool_t wpas_dbus_setter_bss_expire_count(
3193 const struct wpa_dbus_property_desc *property_desc,
3194 DBusMessageIter *iter, DBusError *error, void *user_data)
3196 struct wpa_supplicant *wpa_s = user_data;
3197 dbus_uint32_t expire_count;
3199 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
3203 if (wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count)) {
3204 dbus_set_error_const(error, DBUS_ERROR_FAILED,
3205 "BSSExpireCount must be > 0");
3213 * wpas_dbus_getter_country - Control country code
3214 * @iter: Pointer to incoming dbus message iter
3215 * @error: Location to store error on failure
3216 * @user_data: Function specific data
3217 * Returns: TRUE on success, FALSE on failure
3219 * Getter function for "Country" property.
3221 dbus_bool_t wpas_dbus_getter_country(
3222 const struct wpa_dbus_property_desc *property_desc,
3223 DBusMessageIter *iter, DBusError *error, void *user_data)
3225 struct wpa_supplicant *wpa_s = user_data;
3227 char *str = country;
3229 country[0] = wpa_s->conf->country[0];
3230 country[1] = wpa_s->conf->country[1];
3233 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3239 * wpas_dbus_setter_country - Control country code
3240 * @iter: Pointer to incoming dbus message iter
3241 * @error: Location to store error on failure
3242 * @user_data: Function specific data
3243 * Returns: TRUE on success, FALSE on failure
3245 * Setter function for "Country" property.
3247 dbus_bool_t wpas_dbus_setter_country(
3248 const struct wpa_dbus_property_desc *property_desc,
3249 DBusMessageIter *iter, DBusError *error, void *user_data)
3251 struct wpa_supplicant *wpa_s = user_data;
3252 const char *country;
3254 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
3258 if (!country[0] || !country[1]) {
3259 dbus_set_error_const(error, DBUS_ERROR_FAILED,
3260 "invalid country code");
3264 if (wpa_s->drv_priv != NULL && wpa_drv_set_country(wpa_s, country)) {
3265 wpa_printf(MSG_DEBUG, "Failed to set country");
3266 dbus_set_error_const(error, DBUS_ERROR_FAILED,
3267 "failed to set country code");
3271 wpa_s->conf->country[0] = country[0];
3272 wpa_s->conf->country[1] = country[1];
3278 * wpas_dbus_getter_scan_interval - Get scan interval
3279 * @iter: Pointer to incoming dbus message iter
3280 * @error: Location to store error on failure
3281 * @user_data: Function specific data
3282 * Returns: TRUE on success, FALSE on failure
3284 * Getter function for "ScanInterval" property.
3286 dbus_bool_t wpas_dbus_getter_scan_interval(
3287 const struct wpa_dbus_property_desc *property_desc,
3288 DBusMessageIter *iter, DBusError *error, void *user_data)
3290 struct wpa_supplicant *wpa_s = user_data;
3291 dbus_int32_t scan_interval = wpa_s->scan_interval;
3293 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
3294 &scan_interval, error);
3299 * wpas_dbus_setter_scan_interval - Control scan interval
3300 * @iter: Pointer to incoming dbus message iter
3301 * @error: Location to store error on failure
3302 * @user_data: Function specific data
3303 * Returns: TRUE on success, FALSE on failure
3305 * Setter function for "ScanInterval" property.
3307 dbus_bool_t wpas_dbus_setter_scan_interval(
3308 const struct wpa_dbus_property_desc *property_desc,
3309 DBusMessageIter *iter, DBusError *error, void *user_data)
3311 struct wpa_supplicant *wpa_s = user_data;
3312 dbus_int32_t scan_interval;
3314 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_INT32,
3318 if (wpa_supplicant_set_scan_interval(wpa_s, scan_interval)) {
3319 dbus_set_error_const(error, DBUS_ERROR_FAILED,
3320 "scan_interval must be >= 0");
3328 * wpas_dbus_getter_ifname - Get interface name
3329 * @iter: Pointer to incoming dbus message iter
3330 * @error: Location to store error on failure
3331 * @user_data: Function specific data
3332 * Returns: TRUE on success, FALSE on failure
3334 * Getter for "Ifname" property.
3336 dbus_bool_t wpas_dbus_getter_ifname(
3337 const struct wpa_dbus_property_desc *property_desc,
3338 DBusMessageIter *iter, DBusError *error, void *user_data)
3340 struct wpa_supplicant *wpa_s = user_data;
3342 return wpas_dbus_string_property_getter(iter, wpa_s->ifname, error);
3347 * wpas_dbus_getter_driver - Get interface name
3348 * @iter: Pointer to incoming dbus message iter
3349 * @error: Location to store error on failure
3350 * @user_data: Function specific data
3351 * Returns: TRUE on success, FALSE on failure
3353 * Getter for "Driver" property.
3355 dbus_bool_t wpas_dbus_getter_driver(
3356 const struct wpa_dbus_property_desc *property_desc,
3357 DBusMessageIter *iter, DBusError *error, void *user_data)
3359 struct wpa_supplicant *wpa_s = user_data;
3361 if (wpa_s->driver == NULL || wpa_s->driver->name == NULL) {
3362 wpa_printf(MSG_DEBUG, "%s[dbus]: wpa_s has no driver set",
3364 dbus_set_error(error, DBUS_ERROR_FAILED, "%s: no driver set",
3369 return wpas_dbus_string_property_getter(iter, wpa_s->driver->name,
3375 * wpas_dbus_getter_current_bss - Get current bss object path
3376 * @iter: Pointer to incoming dbus message iter
3377 * @error: Location to store error on failure
3378 * @user_data: Function specific data
3379 * Returns: TRUE on success, FALSE on failure
3381 * Getter for "CurrentBSS" property.
3383 dbus_bool_t wpas_dbus_getter_current_bss(
3384 const struct wpa_dbus_property_desc *property_desc,
3385 DBusMessageIter *iter, DBusError *error, void *user_data)
3387 struct wpa_supplicant *wpa_s = user_data;
3388 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *bss_obj_path = path_buf;
3390 if (wpa_s->current_bss && wpa_s->dbus_new_path)
3391 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3392 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
3393 wpa_s->dbus_new_path, wpa_s->current_bss->id);
3395 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
3397 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
3398 &bss_obj_path, error);
3403 * wpas_dbus_getter_current_network - Get current network object path
3404 * @iter: Pointer to incoming dbus message iter
3405 * @error: Location to store error on failure
3406 * @user_data: Function specific data
3407 * Returns: TRUE on success, FALSE on failure
3409 * Getter for "CurrentNetwork" property.
3411 dbus_bool_t wpas_dbus_getter_current_network(
3412 const struct wpa_dbus_property_desc *property_desc,
3413 DBusMessageIter *iter, DBusError *error, void *user_data)
3415 struct wpa_supplicant *wpa_s = user_data;
3416 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *net_obj_path = path_buf;
3418 if (wpa_s->current_ssid && wpa_s->dbus_new_path)
3419 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3420 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
3421 wpa_s->dbus_new_path, wpa_s->current_ssid->id);
3423 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
3425 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
3426 &net_obj_path, error);
3431 * wpas_dbus_getter_current_auth_mode - Get current authentication type
3432 * @iter: Pointer to incoming dbus message iter
3433 * @error: Location to store error on failure
3434 * @user_data: Function specific data
3435 * Returns: TRUE on success, FALSE on failure
3437 * Getter for "CurrentAuthMode" property.
3439 dbus_bool_t wpas_dbus_getter_current_auth_mode(
3440 const struct wpa_dbus_property_desc *property_desc,
3441 DBusMessageIter *iter, DBusError *error, void *user_data)
3443 struct wpa_supplicant *wpa_s = user_data;
3444 const char *eap_mode;
3445 const char *auth_mode;
3446 char eap_mode_buf[WPAS_DBUS_AUTH_MODE_MAX];
3448 if (wpa_s->wpa_state != WPA_COMPLETED) {
3449 auth_mode = "INACTIVE";
3450 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X ||
3451 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3452 eap_mode = wpa_supplicant_get_eap_mode(wpa_s);
3453 os_snprintf(eap_mode_buf, WPAS_DBUS_AUTH_MODE_MAX,
3454 "EAP-%s", eap_mode);
3455 auth_mode = eap_mode_buf;
3457 } else if (wpa_s->current_ssid) {
3458 auth_mode = wpa_key_mgmt_txt(wpa_s->key_mgmt,
3459 wpa_s->current_ssid->proto);
3461 auth_mode = "UNKNOWN";
3464 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3470 * wpas_dbus_getter_bridge_ifname - Get interface name
3471 * @iter: Pointer to incoming dbus message iter
3472 * @error: Location to store error on failure
3473 * @user_data: Function specific data
3474 * Returns: TRUE on success, FALSE on failure
3476 * Getter for "BridgeIfname" property.
3478 dbus_bool_t wpas_dbus_getter_bridge_ifname(
3479 const struct wpa_dbus_property_desc *property_desc,
3480 DBusMessageIter *iter, DBusError *error, void *user_data)
3482 struct wpa_supplicant *wpa_s = user_data;
3484 return wpas_dbus_string_property_getter(iter, wpa_s->bridge_ifname,
3490 * wpas_dbus_getter_config_file - Get interface configuration file path
3491 * @iter: Pointer to incoming dbus message iter
3492 * @error: Location to store error on failure
3493 * @user_data: Function specific data
3494 * Returns: TRUE on success, FALSE on failure
3496 * Getter for "ConfigFile" property.
3498 dbus_bool_t wpas_dbus_getter_config_file(
3499 const struct wpa_dbus_property_desc *property_desc,
3500 DBusMessageIter *iter, DBusError *error, void *user_data)
3502 struct wpa_supplicant *wpa_s = user_data;
3504 return wpas_dbus_string_property_getter(iter, wpa_s->confname, error);
3509 * wpas_dbus_getter_bsss - Get array of BSSs objects
3510 * @iter: Pointer to incoming dbus message iter
3511 * @error: Location to store error on failure
3512 * @user_data: Function specific data
3513 * Returns: TRUE on success, FALSE on failure
3515 * Getter for "BSSs" property.
3517 dbus_bool_t wpas_dbus_getter_bsss(
3518 const struct wpa_dbus_property_desc *property_desc,
3519 DBusMessageIter *iter, DBusError *error, void *user_data)
3521 struct wpa_supplicant *wpa_s = user_data;
3522 struct wpa_bss *bss;
3525 dbus_bool_t success = FALSE;
3527 if (!wpa_s->dbus_new_path) {
3528 dbus_set_error(error, DBUS_ERROR_FAILED,
3529 "%s: no D-Bus interface", __func__);
3533 paths = os_calloc(wpa_s->num_bss, sizeof(char *));
3535 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3539 /* Loop through scan results and append each result's object path */
3540 dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
3541 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
3542 if (paths[i] == NULL) {
3543 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
3547 /* Construct the object path for this BSS. */
3548 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
3549 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
3550 wpa_s->dbus_new_path, bss->id);
3553 success = wpas_dbus_simple_array_property_getter(iter,
3554 DBUS_TYPE_OBJECT_PATH,
3555 paths, wpa_s->num_bss,
3560 os_free(paths[--i]);
3567 * wpas_dbus_getter_networks - Get array of networks objects
3568 * @iter: Pointer to incoming dbus message iter
3569 * @error: Location to store error on failure
3570 * @user_data: Function specific data
3571 * Returns: TRUE on success, FALSE on failure
3573 * Getter for "Networks" property.
3575 dbus_bool_t wpas_dbus_getter_networks(
3576 const struct wpa_dbus_property_desc *property_desc,
3577 DBusMessageIter *iter, DBusError *error, void *user_data)
3579 struct wpa_supplicant *wpa_s = user_data;
3580 struct wpa_ssid *ssid;
3582 unsigned int i = 0, num = 0;
3583 dbus_bool_t success = FALSE;
3585 if (!wpa_s->dbus_new_path) {
3586 dbus_set_error(error, DBUS_ERROR_FAILED,
3587 "%s: no D-Bus interface", __func__);
3591 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
3592 if (!network_is_persistent_group(ssid))
3595 paths = os_calloc(num, sizeof(char *));
3597 dbus_set_error(error, DBUS_ERROR_NO_MEMORY, "no memory");
3601 /* Loop through configured networks and append object path of each */
3602 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
3603 if (network_is_persistent_group(ssid))
3605 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
3606 if (paths[i] == NULL) {
3607 dbus_set_error(error, DBUS_ERROR_NO_MEMORY,
3612 /* Construct the object path for this network. */
3613 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
3614 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
3615 wpa_s->dbus_new_path, ssid->id);
3618 success = wpas_dbus_simple_array_property_getter(iter,
3619 DBUS_TYPE_OBJECT_PATH,
3624 os_free(paths[--i]);
3631 * wpas_dbus_getter_pkcs11_engine_path - Get PKCS #11 engine path
3632 * @iter: Pointer to incoming dbus message iter
3633 * @error: Location to store error on failure
3634 * @user_data: Function specific data
3635 * Returns: A dbus message containing the PKCS #11 engine path
3637 * Getter for "PKCS11EnginePath" property.
3639 dbus_bool_t wpas_dbus_getter_pkcs11_engine_path(
3640 const struct wpa_dbus_property_desc *property_desc,
3641 DBusMessageIter *iter, DBusError *error, void *user_data)
3643 struct wpa_supplicant *wpa_s = user_data;
3645 return wpas_dbus_string_property_getter(iter,
3646 wpa_s->conf->pkcs11_engine_path,
3652 * wpas_dbus_getter_pkcs11_module_path - Get PKCS #11 module path
3653 * @iter: Pointer to incoming dbus message iter
3654 * @error: Location to store error on failure
3655 * @user_data: Function specific data
3656 * Returns: A dbus message containing the PKCS #11 module path
3658 * Getter for "PKCS11ModulePath" property.
3660 dbus_bool_t wpas_dbus_getter_pkcs11_module_path(
3661 const struct wpa_dbus_property_desc *property_desc,
3662 DBusMessageIter *iter, DBusError *error, void *user_data)
3664 struct wpa_supplicant *wpa_s = user_data;
3666 return wpas_dbus_string_property_getter(iter,
3667 wpa_s->conf->pkcs11_module_path,
3673 * wpas_dbus_getter_blobs - Get all blobs defined for this interface
3674 * @iter: Pointer to incoming dbus message iter
3675 * @error: Location to store error on failure
3676 * @user_data: Function specific data
3677 * Returns: TRUE on success, FALSE on failure
3679 * Getter for "Blobs" property.
3681 dbus_bool_t wpas_dbus_getter_blobs(
3682 const struct wpa_dbus_property_desc *property_desc,
3683 DBusMessageIter *iter, DBusError *error, void *user_data)
3685 struct wpa_supplicant *wpa_s = user_data;
3686 DBusMessageIter variant_iter, dict_iter, entry_iter, array_iter;
3687 struct wpa_config_blob *blob;
3689 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
3690 "a{say}", &variant_iter) ||
3691 !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
3692 "{say}", &dict_iter)) {
3693 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3697 blob = wpa_s->conf->blobs;
3699 if (!dbus_message_iter_open_container(&dict_iter,
3700 DBUS_TYPE_DICT_ENTRY,
3701 NULL, &entry_iter) ||
3702 !dbus_message_iter_append_basic(&entry_iter,
3705 !dbus_message_iter_open_container(&entry_iter,
3707 DBUS_TYPE_BYTE_AS_STRING,
3709 !dbus_message_iter_append_fixed_array(&array_iter,
3713 !dbus_message_iter_close_container(&entry_iter,
3715 !dbus_message_iter_close_container(&dict_iter,
3717 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
3725 if (!dbus_message_iter_close_container(&variant_iter, &dict_iter) ||
3726 !dbus_message_iter_close_container(iter, &variant_iter)) {
3727 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3735 dbus_bool_t wpas_dbus_getter_iface_global(
3736 const struct wpa_dbus_property_desc *property_desc,
3737 DBusMessageIter *iter, DBusError *error, void *user_data)
3739 struct wpa_supplicant *wpa_s = user_data;
3744 if (!property_desc->data) {
3745 dbus_set_error(error, DBUS_ERROR_INVALID_ARGS,
3746 "Unhandled interface property %s",
3747 property_desc->dbus_property);
3751 ret = wpa_config_get_value(property_desc->data, wpa_s->conf, buf,
3756 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &p,
3761 dbus_bool_t wpas_dbus_setter_iface_global(
3762 const struct wpa_dbus_property_desc *property_desc,
3763 DBusMessageIter *iter, DBusError *error, void *user_data)
3765 struct wpa_supplicant *wpa_s = user_data;
3766 const char *new_value = NULL;
3768 size_t combined_len;
3771 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
3775 combined_len = os_strlen(property_desc->data) + os_strlen(new_value) +
3777 if (combined_len >= sizeof(buf)) {
3778 dbus_set_error(error, DBUS_ERROR_INVALID_ARGS,
3779 "Interface property %s value too large",
3780 property_desc->dbus_property);
3787 ret = os_snprintf(buf, combined_len, "%s=%s", property_desc->data,
3789 if (os_snprintf_error(combined_len, ret)) {
3790 dbus_set_error(error, WPAS_DBUS_ERROR_UNKNOWN_ERROR,
3791 "Failed to construct new interface property %s",
3792 property_desc->dbus_property);
3796 if (wpa_config_process_global(wpa_s->conf, buf, -1)) {
3797 dbus_set_error(error, DBUS_ERROR_INVALID_ARGS,
3798 "Failed to set interface property %s",
3799 property_desc->dbus_property);
3803 wpa_supplicant_update_config(wpa_s);
3808 static struct wpa_bss * get_bss_helper(struct bss_handler_args *args,
3809 DBusError *error, const char *func_name)
3811 struct wpa_bss *res = wpa_bss_get_id(args->wpa_s, args->id);
3814 wpa_printf(MSG_ERROR, "%s[dbus]: no bss with id %d found",
3815 func_name, args->id);
3816 dbus_set_error(error, DBUS_ERROR_FAILED,
3817 "%s: BSS %d not found",
3818 func_name, args->id);
3826 * wpas_dbus_getter_bss_bssid - Return the BSSID of a BSS
3827 * @iter: Pointer to incoming dbus message iter
3828 * @error: Location to store error on failure
3829 * @user_data: Function specific data
3830 * Returns: TRUE on success, FALSE on failure
3832 * Getter for "BSSID" property.
3834 dbus_bool_t wpas_dbus_getter_bss_bssid(
3835 const struct wpa_dbus_property_desc *property_desc,
3836 DBusMessageIter *iter, DBusError *error, void *user_data)
3838 struct bss_handler_args *args = user_data;
3839 struct wpa_bss *res;
3841 res = get_bss_helper(args, error, __func__);
3845 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
3846 res->bssid, ETH_ALEN,
3852 * wpas_dbus_getter_bss_ssid - Return the SSID of a BSS
3853 * @iter: Pointer to incoming dbus message iter
3854 * @error: Location to store error on failure
3855 * @user_data: Function specific data
3856 * Returns: TRUE on success, FALSE on failure
3858 * Getter for "SSID" property.
3860 dbus_bool_t wpas_dbus_getter_bss_ssid(
3861 const struct wpa_dbus_property_desc *property_desc,
3862 DBusMessageIter *iter, DBusError *error, void *user_data)
3864 struct bss_handler_args *args = user_data;
3865 struct wpa_bss *res;
3867 res = get_bss_helper(args, error, __func__);
3871 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
3872 res->ssid, res->ssid_len,
3878 * wpas_dbus_getter_bss_privacy - Return the privacy flag of a BSS
3879 * @iter: Pointer to incoming dbus message iter
3880 * @error: Location to store error on failure
3881 * @user_data: Function specific data
3882 * Returns: TRUE on success, FALSE on failure
3884 * Getter for "Privacy" property.
3886 dbus_bool_t wpas_dbus_getter_bss_privacy(
3887 const struct wpa_dbus_property_desc *property_desc,
3888 DBusMessageIter *iter, DBusError *error, void *user_data)
3890 struct bss_handler_args *args = user_data;
3891 struct wpa_bss *res;
3892 dbus_bool_t privacy;
3894 res = get_bss_helper(args, error, __func__);
3898 privacy = (res->caps & IEEE80211_CAP_PRIVACY) ? TRUE : FALSE;
3899 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
3905 * wpas_dbus_getter_bss_mode - Return the mode of a BSS
3906 * @iter: Pointer to incoming dbus message iter
3907 * @error: Location to store error on failure
3908 * @user_data: Function specific data
3909 * Returns: TRUE on success, FALSE on failure
3911 * Getter for "Mode" property.
3913 dbus_bool_t wpas_dbus_getter_bss_mode(
3914 const struct wpa_dbus_property_desc *property_desc,
3915 DBusMessageIter *iter, DBusError *error, void *user_data)
3917 struct bss_handler_args *args = user_data;
3918 struct wpa_bss *res;
3922 res = get_bss_helper(args, error, __func__);
3925 if (bss_is_dmg(res)) {
3926 switch (res->caps & IEEE80211_CAP_DMG_MASK) {
3927 case IEEE80211_CAP_DMG_PBSS:
3928 case IEEE80211_CAP_DMG_IBSS:
3931 case IEEE80211_CAP_DMG_AP:
3932 mode = "infrastructure";
3939 mesh = wpa_bss_get_ie(res, WLAN_EID_MESH_ID);
3942 else if (res->caps & IEEE80211_CAP_IBSS)
3945 mode = "infrastructure";
3948 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3954 * wpas_dbus_getter_bss_level - Return the signal strength of a BSS
3955 * @iter: Pointer to incoming dbus message iter
3956 * @error: Location to store error on failure
3957 * @user_data: Function specific data
3958 * Returns: TRUE on success, FALSE on failure
3960 * Getter for "Level" property.
3962 dbus_bool_t wpas_dbus_getter_bss_signal(
3963 const struct wpa_dbus_property_desc *property_desc,
3964 DBusMessageIter *iter, DBusError *error, void *user_data)
3966 struct bss_handler_args *args = user_data;
3967 struct wpa_bss *res;
3970 res = get_bss_helper(args, error, __func__);
3974 level = (s16) res->level;
3975 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT16,
3981 * wpas_dbus_getter_bss_frequency - Return the frequency of a BSS
3982 * @iter: Pointer to incoming dbus message iter
3983 * @error: Location to store error on failure
3984 * @user_data: Function specific data
3985 * Returns: TRUE on success, FALSE on failure
3987 * Getter for "Frequency" property.
3989 dbus_bool_t wpas_dbus_getter_bss_frequency(
3990 const struct wpa_dbus_property_desc *property_desc,
3991 DBusMessageIter *iter, DBusError *error, void *user_data)
3993 struct bss_handler_args *args = user_data;
3994 struct wpa_bss *res;
3997 res = get_bss_helper(args, error, __func__);
4001 freq = (u16) res->freq;
4002 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
4007 static int cmp_u8s_desc(const void *a, const void *b)
4009 return (*(u8 *) b - *(u8 *) a);
4014 * wpas_dbus_getter_bss_rates - Return available bit rates of a BSS
4015 * @iter: Pointer to incoming dbus message iter
4016 * @error: Location to store error on failure
4017 * @user_data: Function specific data
4018 * Returns: TRUE on success, FALSE on failure
4020 * Getter for "Rates" property.
4022 dbus_bool_t wpas_dbus_getter_bss_rates(
4023 const struct wpa_dbus_property_desc *property_desc,
4024 DBusMessageIter *iter, DBusError *error, void *user_data)
4026 struct bss_handler_args *args = user_data;
4027 struct wpa_bss *res;
4028 u8 *ie_rates = NULL;
4031 dbus_bool_t success = FALSE;
4033 res = get_bss_helper(args, error, __func__);
4037 rates_num = wpa_bss_get_bit_rates(res, &ie_rates);
4041 qsort(ie_rates, rates_num, 1, cmp_u8s_desc);
4043 real_rates = os_malloc(sizeof(u32) * rates_num);
4046 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
4050 for (i = 0; i < rates_num; i++)
4051 real_rates[i] = ie_rates[i] * 500000;
4053 success = wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_UINT32,
4054 real_rates, rates_num,
4058 os_free(real_rates);
4063 static dbus_bool_t wpas_dbus_get_bss_security_prop(
4064 const struct wpa_dbus_property_desc *property_desc,
4065 DBusMessageIter *iter, struct wpa_ie_data *ie_data, DBusError *error)
4067 DBusMessageIter iter_dict, variant_iter;
4069 const char *pairwise[5]; /* max 5 pairwise ciphers is supported */
4070 const char *key_mgmt[13]; /* max 13 key managements may be supported */
4073 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
4074 "a{sv}", &variant_iter))
4077 if (!wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
4082 if (ie_data->key_mgmt & WPA_KEY_MGMT_PSK)
4083 key_mgmt[n++] = "wpa-psk";
4084 if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_PSK)
4085 key_mgmt[n++] = "wpa-ft-psk";
4086 if (ie_data->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
4087 key_mgmt[n++] = "wpa-psk-sha256";
4088 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X)
4089 key_mgmt[n++] = "wpa-eap";
4090 if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X)
4091 key_mgmt[n++] = "wpa-ft-eap";
4092 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256)
4093 key_mgmt[n++] = "wpa-eap-sha256";
4094 #ifdef CONFIG_SUITEB
4095 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B)
4096 key_mgmt[n++] = "wpa-eap-suite-b";
4097 #endif /* CONFIG_SUITEB */
4098 #ifdef CONFIG_SUITEB192
4099 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
4100 key_mgmt[n++] = "wpa-eap-suite-b-192";
4101 #endif /* CONFIG_SUITEB192 */
4103 if (ie_data->key_mgmt & WPA_KEY_MGMT_FILS_SHA256)
4104 key_mgmt[n++] = "wpa-fils-sha256";
4105 if (ie_data->key_mgmt & WPA_KEY_MGMT_FILS_SHA384)
4106 key_mgmt[n++] = "wpa-fils-sha384";
4107 if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA256)
4108 key_mgmt[n++] = "wpa-ft-fils-sha256";
4109 if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA384)
4110 key_mgmt[n++] = "wpa-ft-fils-sha384";
4111 #endif /* CONFIG_FILS */
4112 if (ie_data->key_mgmt & WPA_KEY_MGMT_NONE)
4113 key_mgmt[n++] = "wpa-none";
4115 if (!wpa_dbus_dict_append_string_array(&iter_dict, "KeyMgmt",
4120 switch (ie_data->group_cipher) {
4121 case WPA_CIPHER_WEP40:
4124 case WPA_CIPHER_TKIP:
4127 case WPA_CIPHER_CCMP:
4130 case WPA_CIPHER_GCMP:
4133 case WPA_CIPHER_WEP104:
4136 case WPA_CIPHER_CCMP_256:
4139 case WPA_CIPHER_GCMP_256:
4147 if (!wpa_dbus_dict_append_string(&iter_dict, "Group", group))
4152 if (ie_data->pairwise_cipher & WPA_CIPHER_TKIP)
4153 pairwise[n++] = "tkip";
4154 if (ie_data->pairwise_cipher & WPA_CIPHER_CCMP)
4155 pairwise[n++] = "ccmp";
4156 if (ie_data->pairwise_cipher & WPA_CIPHER_GCMP)
4157 pairwise[n++] = "gcmp";
4158 if (ie_data->pairwise_cipher & WPA_CIPHER_CCMP_256)
4159 pairwise[n++] = "ccmp-256";
4160 if (ie_data->pairwise_cipher & WPA_CIPHER_GCMP_256)
4161 pairwise[n++] = "gcmp-256";
4163 if (!wpa_dbus_dict_append_string_array(&iter_dict, "Pairwise",
4167 /* Management group (RSN only) */
4168 if (ie_data->proto == WPA_PROTO_RSN) {
4169 switch (ie_data->mgmt_group_cipher) {
4170 #ifdef CONFIG_IEEE80211W
4171 case WPA_CIPHER_AES_128_CMAC:
4172 group = "aes128cmac";
4174 #endif /* CONFIG_IEEE80211W */
4180 if (!wpa_dbus_dict_append_string(&iter_dict, "MgmtGroup",
4185 if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict) ||
4186 !dbus_message_iter_close_container(iter, &variant_iter))
4192 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
4198 * wpas_dbus_getter_bss_wpa - Return the WPA options of a BSS
4199 * @iter: Pointer to incoming dbus message iter
4200 * @error: Location to store error on failure
4201 * @user_data: Function specific data
4202 * Returns: TRUE on success, FALSE on failure
4204 * Getter for "WPA" property.
4206 dbus_bool_t wpas_dbus_getter_bss_wpa(
4207 const struct wpa_dbus_property_desc *property_desc,
4208 DBusMessageIter *iter, DBusError *error, void *user_data)
4210 struct bss_handler_args *args = user_data;
4211 struct wpa_bss *res;
4212 struct wpa_ie_data wpa_data;
4215 res = get_bss_helper(args, error, __func__);
4219 os_memset(&wpa_data, 0, sizeof(wpa_data));
4220 ie = wpa_bss_get_vendor_ie(res, WPA_IE_VENDOR_TYPE);
4221 if (ie && wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0) {
4222 dbus_set_error_const(error, DBUS_ERROR_FAILED,
4223 "failed to parse WPA IE");
4227 return wpas_dbus_get_bss_security_prop(property_desc, iter, &wpa_data, error);
4232 * wpas_dbus_getter_bss_rsn - Return the RSN options of a BSS
4233 * @iter: Pointer to incoming dbus message iter
4234 * @error: Location to store error on failure
4235 * @user_data: Function specific data
4236 * Returns: TRUE on success, FALSE on failure
4238 * Getter for "RSN" property.
4240 dbus_bool_t wpas_dbus_getter_bss_rsn(
4241 const struct wpa_dbus_property_desc *property_desc,
4242 DBusMessageIter *iter, DBusError *error, void *user_data)
4244 struct bss_handler_args *args = user_data;
4245 struct wpa_bss *res;
4246 struct wpa_ie_data wpa_data;
4249 res = get_bss_helper(args, error, __func__);
4253 os_memset(&wpa_data, 0, sizeof(wpa_data));
4254 ie = wpa_bss_get_ie(res, WLAN_EID_RSN);
4255 if (ie && wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0) {
4256 dbus_set_error_const(error, DBUS_ERROR_FAILED,
4257 "failed to parse RSN IE");
4261 return wpas_dbus_get_bss_security_prop(property_desc, iter, &wpa_data, error);
4266 * wpas_dbus_getter_bss_wps - Return the WPS options of a BSS
4267 * @iter: Pointer to incoming dbus message iter
4268 * @error: Location to store error on failure
4269 * @user_data: Function specific data
4270 * Returns: TRUE on success, FALSE on failure
4272 * Getter for "WPS" property.
4274 dbus_bool_t wpas_dbus_getter_bss_wps(
4275 const struct wpa_dbus_property_desc *property_desc,
4276 DBusMessageIter *iter, DBusError *error, void *user_data)
4278 struct bss_handler_args *args = user_data;
4279 struct wpa_bss *res;
4281 struct wpabuf *wps_ie;
4282 #endif /* CONFIG_WPS */
4283 DBusMessageIter iter_dict, variant_iter;
4284 int wps_support = 0;
4285 const char *type = "";
4287 res = get_bss_helper(args, error, __func__);
4291 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
4292 "a{sv}", &variant_iter) ||
4293 !wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
4297 wps_ie = wpa_bss_get_vendor_ie_multi(res, WPS_IE_VENDOR_TYPE);
4300 if (wps_is_selected_pbc_registrar(wps_ie))
4302 else if (wps_is_selected_pin_registrar(wps_ie))
4305 wpabuf_free(wps_ie);
4307 #endif /* CONFIG_WPS */
4309 if ((wps_support && !wpa_dbus_dict_append_string(&iter_dict, "Type", type)) ||
4310 !wpa_dbus_dict_close_write(&variant_iter, &iter_dict) ||
4311 !dbus_message_iter_close_container(iter, &variant_iter))
4317 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
4323 * wpas_dbus_getter_bss_ies - Return all IEs of a BSS
4324 * @iter: Pointer to incoming dbus message iter
4325 * @error: Location to store error on failure
4326 * @user_data: Function specific data
4327 * Returns: TRUE on success, FALSE on failure
4329 * Getter for "IEs" property.
4331 dbus_bool_t wpas_dbus_getter_bss_ies(
4332 const struct wpa_dbus_property_desc *property_desc,
4333 DBusMessageIter *iter, DBusError *error, void *user_data)
4335 struct bss_handler_args *args = user_data;
4336 struct wpa_bss *res;
4338 res = get_bss_helper(args, error, __func__);
4342 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
4343 res + 1, res->ie_len,
4349 * wpas_dbus_getter_bss_age - Return time in seconds since BSS was last seen
4350 * @iter: Pointer to incoming dbus message iter
4351 * @error: Location to store error on failure
4352 * @user_data: Function specific data
4353 * Returns: TRUE on success, FALSE on failure
4355 * Getter for BSS age
4357 dbus_bool_t wpas_dbus_getter_bss_age(
4358 const struct wpa_dbus_property_desc *property_desc,
4359 DBusMessageIter *iter, DBusError *error, void *user_data)
4361 struct bss_handler_args *args = user_data;
4362 struct wpa_bss *res;
4363 struct os_reltime now, diff = { 0, 0 };
4366 res = get_bss_helper(args, error, __func__);
4370 os_get_reltime(&now);
4371 os_reltime_sub(&now, &res->last_update, &diff);
4372 age = diff.sec > 0 ? diff.sec : 0;
4373 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32, &age,
4379 * wpas_dbus_getter_enabled - Check whether network is enabled or disabled
4380 * @iter: Pointer to incoming dbus message iter
4381 * @error: Location to store error on failure
4382 * @user_data: Function specific data
4383 * Returns: TRUE on success, FALSE on failure
4385 * Getter for "enabled" property of a configured network.
4387 dbus_bool_t wpas_dbus_getter_enabled(
4388 const struct wpa_dbus_property_desc *property_desc,
4389 DBusMessageIter *iter, DBusError *error, void *user_data)
4391 struct network_handler_args *net = user_data;
4392 dbus_bool_t enabled = net->ssid->disabled ? FALSE : TRUE;
4394 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
4400 * wpas_dbus_setter_enabled - Mark a configured network as enabled or disabled
4401 * @iter: Pointer to incoming dbus message iter
4402 * @error: Location to store error on failure
4403 * @user_data: Function specific data
4404 * Returns: TRUE on success, FALSE on failure
4406 * Setter for "Enabled" property of a configured network.
4408 dbus_bool_t wpas_dbus_setter_enabled(
4409 const struct wpa_dbus_property_desc *property_desc,
4410 DBusMessageIter *iter, DBusError *error, void *user_data)
4412 struct network_handler_args *net = user_data;
4413 struct wpa_supplicant *wpa_s;
4414 struct wpa_ssid *ssid;
4417 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
4425 wpa_supplicant_enable_network(wpa_s, ssid);
4427 wpa_supplicant_disable_network(wpa_s, ssid);
4434 * wpas_dbus_getter_network_properties - Get options for a configured network
4435 * @iter: Pointer to incoming dbus message iter
4436 * @error: Location to store error on failure
4437 * @user_data: Function specific data
4438 * Returns: TRUE on success, FALSE on failure
4440 * Getter for "Properties" property of a configured network.
4442 dbus_bool_t wpas_dbus_getter_network_properties(
4443 const struct wpa_dbus_property_desc *property_desc,
4444 DBusMessageIter *iter, DBusError *error, void *user_data)
4446 struct network_handler_args *net = user_data;
4447 DBusMessageIter variant_iter, dict_iter;
4449 char **props = wpa_config_get_all(net->ssid, 1);
4450 dbus_bool_t success = FALSE;
4453 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
4457 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a{sv}",
4459 !wpa_dbus_dict_open_write(&variant_iter, &dict_iter)) {
4460 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
4466 if (!wpa_dbus_dict_append_string(&dict_iter, *iterator,
4468 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
4476 if (!wpa_dbus_dict_close_write(&variant_iter, &dict_iter) ||
4477 !dbus_message_iter_close_container(iter, &variant_iter)) {
4478 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
4496 * wpas_dbus_setter_network_properties - Set options for a configured network
4497 * @iter: Pointer to incoming dbus message iter
4498 * @error: Location to store error on failure
4499 * @user_data: Function specific data
4500 * Returns: TRUE on success, FALSE on failure
4502 * Setter for "Properties" property of a configured network.
4504 dbus_bool_t wpas_dbus_setter_network_properties(
4505 const struct wpa_dbus_property_desc *property_desc,
4506 DBusMessageIter *iter, DBusError *error, void *user_data)
4508 struct network_handler_args *net = user_data;
4509 struct wpa_ssid *ssid = net->ssid;
4510 DBusMessageIter variant_iter;
4512 dbus_message_iter_recurse(iter, &variant_iter);
4513 return set_network_properties(net->wpa_s, ssid, &variant_iter, error);
4519 DBusMessage * wpas_dbus_handler_subscribe_preq(
4520 DBusMessage *message, struct wpa_supplicant *wpa_s)
4522 struct wpas_dbus_priv *priv = wpa_s->global->dbus;
4525 if (wpa_s->preq_notify_peer != NULL) {
4526 if (os_strcmp(dbus_message_get_sender(message),
4527 wpa_s->preq_notify_peer) == 0)
4530 return dbus_message_new_error(message,
4531 WPAS_DBUS_ERROR_SUBSCRIPTION_IN_USE,
4532 "Another application is already subscribed");
4535 name = os_strdup(dbus_message_get_sender(message));
4537 return wpas_dbus_error_no_memory(message);
4539 wpa_s->preq_notify_peer = name;
4541 /* Subscribe to clean up if application closes socket */
4542 wpas_dbus_subscribe_noc(priv);
4545 * Double-check it's still alive to make sure that we didn't
4546 * miss the NameOwnerChanged signal, e.g. while strdup'ing.
4548 if (!dbus_bus_name_has_owner(priv->con, name, NULL)) {
4550 * Application no longer exists, clean up.
4551 * The return value is irrelevant now.
4553 * Need to check if the NameOwnerChanged handling
4554 * already cleaned up because we have processed
4555 * DBus messages while checking if the name still
4558 if (!wpa_s->preq_notify_peer)
4560 os_free(wpa_s->preq_notify_peer);
4561 wpa_s->preq_notify_peer = NULL;
4562 wpas_dbus_unsubscribe_noc(priv);
4569 DBusMessage * wpas_dbus_handler_unsubscribe_preq(
4570 DBusMessage *message, struct wpa_supplicant *wpa_s)
4572 struct wpas_dbus_priv *priv = wpa_s->global->dbus;
4574 if (!wpa_s->preq_notify_peer)
4575 return dbus_message_new_error(message,
4576 WPAS_DBUS_ERROR_NO_SUBSCRIPTION,
4579 if (os_strcmp(wpa_s->preq_notify_peer,
4580 dbus_message_get_sender(message)))
4581 return dbus_message_new_error(message,
4582 WPAS_DBUS_ERROR_SUBSCRIPTION_EPERM,
4583 "Can't unsubscribe others");
4585 os_free(wpa_s->preq_notify_peer);
4586 wpa_s->preq_notify_peer = NULL;
4587 wpas_dbus_unsubscribe_noc(priv);
4592 void wpas_dbus_signal_preq(struct wpa_supplicant *wpa_s,
4593 const u8 *addr, const u8 *dst, const u8 *bssid,
4594 const u8 *ie, size_t ie_len, u32 ssi_signal)
4597 DBusMessageIter iter, dict_iter;
4598 struct wpas_dbus_priv *priv = wpa_s->global->dbus;
4600 /* Do nothing if the control interface is not turned on */
4601 if (priv == NULL || !wpa_s->dbus_new_path)
4604 if (wpa_s->preq_notify_peer == NULL)
4607 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
4608 WPAS_DBUS_NEW_IFACE_INTERFACE,
4613 dbus_message_set_destination(msg, wpa_s->preq_notify_peer);
4615 dbus_message_iter_init_append(msg, &iter);
4617 if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
4618 (addr && !wpa_dbus_dict_append_byte_array(&dict_iter, "addr",
4619 (const char *) addr,
4621 (dst && !wpa_dbus_dict_append_byte_array(&dict_iter, "dst",
4624 (bssid && !wpa_dbus_dict_append_byte_array(&dict_iter, "bssid",
4625 (const char *) bssid,
4627 (ie && ie_len && !wpa_dbus_dict_append_byte_array(&dict_iter, "ies",
4630 (ssi_signal && !wpa_dbus_dict_append_int32(&dict_iter, "signal",
4632 !wpa_dbus_dict_close_write(&iter, &dict_iter))
4635 dbus_connection_send(priv->con, msg, NULL);
4638 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
4640 dbus_message_unref(msg);
4643 #endif /* CONFIG_AP */
4646 DBusMessage * wpas_dbus_handler_vendor_elem_add(DBusMessage *message,
4647 struct wpa_supplicant *wpa_s)
4651 struct ieee802_11_elems elems;
4652 dbus_int32_t frame_id;
4653 DBusMessageIter iter, array;
4655 dbus_message_iter_init(message, &iter);
4656 dbus_message_iter_get_basic(&iter, &frame_id);
4657 if (frame_id < 0 || frame_id >= NUM_VENDOR_ELEM_FRAMES) {
4658 return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
4662 dbus_message_iter_next(&iter);
4663 dbus_message_iter_recurse(&iter, &array);
4664 dbus_message_iter_get_fixed_array(&array, &ielems, &len);
4665 if (!ielems || len == 0) {
4666 return dbus_message_new_error(
4667 message, DBUS_ERROR_INVALID_ARGS, "Invalid value");
4670 if (ieee802_11_parse_elems(ielems, len, &elems, 0) == ParseFailed) {
4671 return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
4675 wpa_s = wpas_vendor_elem(wpa_s, frame_id);
4676 if (!wpa_s->vendor_elem[frame_id]) {
4677 wpa_s->vendor_elem[frame_id] = wpabuf_alloc_copy(ielems, len);
4678 wpas_vendor_elem_update(wpa_s);
4682 if (wpabuf_resize(&wpa_s->vendor_elem[frame_id], len) < 0) {
4683 return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
4687 wpabuf_put_data(wpa_s->vendor_elem[frame_id], ielems, len);
4688 wpas_vendor_elem_update(wpa_s);
4693 DBusMessage * wpas_dbus_handler_vendor_elem_get(DBusMessage *message,
4694 struct wpa_supplicant *wpa_s)
4697 DBusMessageIter iter, array_iter;
4698 dbus_int32_t frame_id;
4702 dbus_message_iter_init(message, &iter);
4703 dbus_message_iter_get_basic(&iter, &frame_id);
4705 if (frame_id < 0 || frame_id >= NUM_VENDOR_ELEM_FRAMES) {
4706 return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
4710 wpa_s = wpas_vendor_elem(wpa_s, frame_id);
4711 if (!wpa_s->vendor_elem[frame_id]) {
4712 return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
4713 "ID value does not exist");
4716 reply = dbus_message_new_method_return(message);
4718 return wpas_dbus_error_no_memory(message);
4720 dbus_message_iter_init_append(reply, &iter);
4722 elem = wpabuf_head_u8(wpa_s->vendor_elem[frame_id]);
4723 elem_len = wpabuf_len(wpa_s->vendor_elem[frame_id]);
4725 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
4726 DBUS_TYPE_BYTE_AS_STRING,
4728 !dbus_message_iter_append_fixed_array(&array_iter, DBUS_TYPE_BYTE,
4730 !dbus_message_iter_close_container(&iter, &array_iter)) {
4731 dbus_message_unref(reply);
4732 reply = wpas_dbus_error_no_memory(message);
4739 DBusMessage * wpas_dbus_handler_vendor_elem_remove(DBusMessage *message,
4740 struct wpa_supplicant *wpa_s)
4744 struct ieee802_11_elems elems;
4745 DBusMessageIter iter, array;
4746 dbus_int32_t frame_id;
4748 dbus_message_iter_init(message, &iter);
4749 dbus_message_iter_get_basic(&iter, &frame_id);
4750 if (frame_id < 0 || frame_id >= NUM_VENDOR_ELEM_FRAMES) {
4751 return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
4755 dbus_message_iter_next(&iter);
4756 dbus_message_iter_recurse(&iter, &array);
4757 dbus_message_iter_get_fixed_array(&array, &ielems, &len);
4758 if (!ielems || len == 0) {
4759 return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
4763 wpa_s = wpas_vendor_elem(wpa_s, frame_id);
4765 if (len == 1 && *ielems == '*') {
4766 wpabuf_free(wpa_s->vendor_elem[frame_id]);
4767 wpa_s->vendor_elem[frame_id] = NULL;
4768 wpas_vendor_elem_update(wpa_s);
4772 if (!wpa_s->vendor_elem[frame_id]) {
4773 return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
4774 "ID value does not exist");
4777 if (ieee802_11_parse_elems(ielems, len, &elems, 0) == ParseFailed) {
4778 return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
4782 if (wpas_vendor_elem_remove(wpa_s, frame_id, ielems, len) == 0)
4785 return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
4793 * wpas_dbus_getter_mesh_peers - Get connected mesh peers
4794 * @iter: Pointer to incoming dbus message iter
4795 * @error: Location to store error on failure
4796 * @user_data: Function specific data
4797 * Returns: TRUE on success, FALSE on failure
4799 * Getter for "MeshPeers" property.
4801 dbus_bool_t wpas_dbus_getter_mesh_peers(
4802 const struct wpa_dbus_property_desc *property_desc,
4803 DBusMessageIter *iter, DBusError *error, void *user_data)
4805 struct wpa_supplicant *wpa_s = user_data;
4806 struct hostapd_data *hapd;
4807 struct sta_info *sta;
4808 DBusMessageIter variant_iter, array_iter;
4810 DBusMessageIter inner_array_iter;
4814 hapd = wpa_s->ifmsh->bss[0];
4816 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
4817 DBUS_TYPE_ARRAY_AS_STRING
4818 DBUS_TYPE_ARRAY_AS_STRING
4819 DBUS_TYPE_BYTE_AS_STRING,
4821 !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
4822 DBUS_TYPE_ARRAY_AS_STRING
4823 DBUS_TYPE_BYTE_AS_STRING,
4827 for (sta = hapd->sta_list; sta; sta = sta->next) {
4828 if (!dbus_message_iter_open_container(
4829 &array_iter, DBUS_TYPE_ARRAY,
4830 DBUS_TYPE_BYTE_AS_STRING,
4834 for (i = 0; i < ETH_ALEN; i++) {
4835 if (!dbus_message_iter_append_basic(&inner_array_iter,
4841 if (!dbus_message_iter_close_container(
4842 &array_iter, &inner_array_iter))
4846 if (!dbus_message_iter_close_container(&variant_iter, &array_iter) ||
4847 !dbus_message_iter_close_container(iter, &variant_iter))
4855 * wpas_dbus_getter_mesh_group - Get mesh group
4856 * @iter: Pointer to incoming dbus message iter
4857 * @error: Location to store error on failure
4858 * @user_data: Function specific data
4859 * Returns: TRUE on success, FALSE on failure
4861 * Getter for "MeshGroup" property.
4863 dbus_bool_t wpas_dbus_getter_mesh_group(
4864 const struct wpa_dbus_property_desc *property_desc,
4865 DBusMessageIter *iter, DBusError *error, void *user_data)
4867 struct wpa_supplicant *wpa_s = user_data;
4868 struct wpa_ssid *ssid = wpa_s->current_ssid;
4870 if (!wpa_s->ifmsh || !ssid)
4873 if (!wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
4874 (char *) ssid->ssid,
4875 ssid->ssid_len, error)) {
4876 dbus_set_error(error, DBUS_ERROR_FAILED,
4877 "%s: error constructing reply", __func__);
4884 #endif /* CONFIG_MESH */