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, 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 static const char *debug_strings[] = {
33 "excessive", "msgdump", "debug", "info", "warning", "error", NULL
38 * wpas_dbus_error_unknown_error - Return a new InvalidArgs error message
39 * @message: Pointer to incoming dbus message this error refers to
40 * @arg: Optional string appended to error message
41 * Returns: a dbus error message
43 * Convenience function to create and return an UnknownError
45 DBusMessage * wpas_dbus_error_unknown_error(DBusMessage *message,
49 * This function can be called as a result of a failure
50 * within internal getter calls, which will call this function
51 * with a NULL message parameter. However, dbus_message_new_error
52 * looks very unkindly (i.e, abort()) on a NULL message, so
53 * in this case, we should not call it.
55 if (message == NULL) {
56 wpa_printf(MSG_INFO, "dbus: wpas_dbus_error_unknown_error "
57 "called with NULL message (arg=%s)",
62 return dbus_message_new_error(message, WPAS_DBUS_ERROR_UNKNOWN_ERROR,
68 * wpas_dbus_error_iface_unknown - Return a new invalid interface error message
69 * @message: Pointer to incoming dbus message this error refers to
70 * Returns: A dbus error message
72 * Convenience function to create and return an invalid interface error
74 static DBusMessage * wpas_dbus_error_iface_unknown(DBusMessage *message)
76 return dbus_message_new_error(message, WPAS_DBUS_ERROR_IFACE_UNKNOWN,
77 "wpa_supplicant knows nothing about "
83 * wpas_dbus_error_network_unknown - Return a new NetworkUnknown error message
84 * @message: Pointer to incoming dbus message this error refers to
85 * Returns: a dbus error message
87 * Convenience function to create and return an invalid network error
89 static DBusMessage * wpas_dbus_error_network_unknown(DBusMessage *message)
91 return dbus_message_new_error(message, WPAS_DBUS_ERROR_NETWORK_UNKNOWN,
92 "There is no such a network in this "
98 * wpas_dbus_error_invalid_args - Return a new InvalidArgs error message
99 * @message: Pointer to incoming dbus message this error refers to
100 * Returns: a dbus error message
102 * Convenience function to create and return an invalid options error
104 DBusMessage * wpas_dbus_error_invalid_args(DBusMessage *message,
109 reply = dbus_message_new_error(message, WPAS_DBUS_ERROR_INVALID_ARGS,
110 "Did not receive correct message "
113 dbus_message_append_args(reply, DBUS_TYPE_STRING, &arg,
121 * wpas_dbus_error_scan_error - Return a new ScanError error message
122 * @message: Pointer to incoming dbus message this error refers to
123 * @error: Optional string to be used as the error message
124 * Returns: a dbus error message
126 * Convenience function to create and return a scan error
128 static DBusMessage * wpas_dbus_error_scan_error(DBusMessage *message,
131 return dbus_message_new_error(message,
132 WPAS_DBUS_ERROR_IFACE_SCAN_ERROR,
137 static const char *dont_quote[] = {
138 "key_mgmt", "proto", "pairwise", "auth_alg", "group", "eap",
139 "opensc_engine_path", "pkcs11_engine_path", "pkcs11_module_path",
140 "bssid", "scan_freq", "freq_list", NULL
143 static dbus_bool_t should_quote_opt(const char *key)
146 while (dont_quote[i] != NULL) {
147 if (os_strcmp(key, dont_quote[i]) == 0)
155 * get_iface_by_dbus_path - Get a new network interface
156 * @global: Pointer to global data from wpa_supplicant_init()
157 * @path: Pointer to a dbus object path representing an interface
158 * Returns: Pointer to the interface or %NULL if not found
160 static struct wpa_supplicant * get_iface_by_dbus_path(
161 struct wpa_global *global, const char *path)
163 struct wpa_supplicant *wpa_s;
165 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
166 if (os_strcmp(wpa_s->dbus_new_path, path) == 0)
174 * set_network_properties - Set properties of a configured network
175 * @wpa_s: wpa_supplicant structure for a network interface
176 * @ssid: wpa_ssid structure for a configured network
177 * @iter: DBus message iterator containing dictionary of network
179 * @error: On failure, an error describing the failure
180 * Returns: TRUE if the request succeeds, FALSE if it failed
182 * Sets network configuration with parameters given id DBus dictionary
184 dbus_bool_t set_network_properties(struct wpa_supplicant *wpa_s,
185 struct wpa_ssid *ssid,
186 DBusMessageIter *iter,
189 struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
190 DBusMessageIter iter_dict;
193 if (!wpa_dbus_dict_open_read(iter, &iter_dict, error))
196 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
200 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
204 if (entry.type == DBUS_TYPE_ARRAY &&
205 entry.array_type == DBUS_TYPE_BYTE) {
206 if (entry.array_len <= 0)
209 size = entry.array_len * 2 + 1;
210 value = os_zalloc(size);
214 ret = wpa_snprintf_hex(value, size,
215 (u8 *) entry.bytearray_value,
219 } else if (entry.type == DBUS_TYPE_STRING) {
220 if (should_quote_opt(entry.key)) {
221 size = os_strlen(entry.str_value);
226 value = os_zalloc(size);
230 ret = os_snprintf(value, size, "\"%s\"",
232 if (os_snprintf_error(size, ret))
235 value = os_strdup(entry.str_value);
239 } else if (entry.type == DBUS_TYPE_UINT32) {
240 value = os_zalloc(size);
244 ret = os_snprintf(value, size, "%u",
246 if (os_snprintf_error(size, ret))
248 } else if (entry.type == DBUS_TYPE_INT32) {
249 value = os_zalloc(size);
253 ret = os_snprintf(value, size, "%d",
255 if (os_snprintf_error(size, ret))
260 if (wpa_config_set(ssid, entry.key, value, 0) < 0)
263 if ((os_strcmp(entry.key, "psk") == 0 &&
264 value[0] == '"' && ssid->ssid_len) ||
265 (os_strcmp(entry.key, "ssid") == 0 && ssid->passphrase))
266 wpa_config_update_psk(ssid);
267 else if (os_strcmp(entry.key, "priority") == 0)
268 wpa_config_update_prio_list(wpa_s->conf);
272 wpa_dbus_dict_entry_clear(&entry);
279 wpa_dbus_dict_entry_clear(&entry);
280 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
281 "invalid message format");
287 * wpas_dbus_simple_property_getter - Get basic type property
288 * @iter: Message iter to use when appending arguments
289 * @type: DBus type of property (must be basic type)
290 * @val: pointer to place holding property value
291 * @error: On failure an error describing the failure
292 * Returns: TRUE if the request was successful, FALSE if it failed
294 * Generic getter for basic type properties. Type is required to be basic.
296 dbus_bool_t wpas_dbus_simple_property_getter(DBusMessageIter *iter,
301 DBusMessageIter variant_iter;
303 if (!dbus_type_is_basic(type)) {
304 dbus_set_error(error, DBUS_ERROR_FAILED,
305 "%s: given type is not basic", __func__);
309 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
310 wpa_dbus_type_as_string(type),
314 if (!dbus_message_iter_append_basic(&variant_iter, type, val))
317 if (!dbus_message_iter_close_container(iter, &variant_iter))
323 dbus_set_error(error, DBUS_ERROR_FAILED,
324 "%s: error constructing reply", __func__);
330 * wpas_dbus_simple_property_setter - Set basic type property
331 * @message: Pointer to incoming dbus message
332 * @type: DBus type of property (must be basic type)
333 * @val: pointer to place where value being set will be stored
334 * Returns: TRUE if the request was successful, FALSE if it failed
336 * Generic setter for basic type properties. Type is required to be basic.
338 dbus_bool_t wpas_dbus_simple_property_setter(DBusMessageIter *iter,
340 const int type, void *val)
342 DBusMessageIter variant_iter;
344 if (!dbus_type_is_basic(type)) {
345 dbus_set_error(error, DBUS_ERROR_FAILED,
346 "%s: given type is not basic", __func__);
350 /* Look at the new value */
351 dbus_message_iter_recurse(iter, &variant_iter);
352 if (dbus_message_iter_get_arg_type(&variant_iter) != type) {
353 dbus_set_error_const(error, DBUS_ERROR_FAILED,
354 "wrong property type");
357 dbus_message_iter_get_basic(&variant_iter, val);
364 * wpas_dbus_simple_array_property_getter - Get array type property
365 * @iter: Pointer to incoming dbus message iterator
366 * @type: DBus type of property array elements (must be basic type)
367 * @array: pointer to array of elements to put into response message
368 * @array_len: length of above array
369 * @error: a pointer to an error to fill on failure
370 * Returns: TRUE if the request succeeded, FALSE if it failed
372 * Generic getter for array type properties. Array elements type is
373 * required to be basic.
375 dbus_bool_t wpas_dbus_simple_array_property_getter(DBusMessageIter *iter,
381 DBusMessageIter variant_iter, array_iter;
382 char type_str[] = "a?"; /* ? will be replaced with subtype letter; */
383 const char *sub_type_str;
384 size_t element_size, i;
386 if (!dbus_type_is_basic(type)) {
387 dbus_set_error(error, DBUS_ERROR_FAILED,
388 "%s: given type is not basic", __func__);
392 sub_type_str = wpa_dbus_type_as_string(type);
393 type_str[1] = sub_type_str[0];
395 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
396 type_str, &variant_iter)) {
397 dbus_set_error(error, DBUS_ERROR_FAILED,
398 "%s: failed to construct message 1", __func__);
402 if (!dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
403 sub_type_str, &array_iter)) {
404 dbus_set_error(error, DBUS_ERROR_FAILED,
405 "%s: failed to construct message 2", __func__);
411 case DBUS_TYPE_BOOLEAN:
414 case DBUS_TYPE_INT16:
415 case DBUS_TYPE_UINT16:
416 element_size = sizeof(uint16_t);
418 case DBUS_TYPE_INT32:
419 case DBUS_TYPE_UINT32:
420 element_size = sizeof(uint32_t);
422 case DBUS_TYPE_INT64:
423 case DBUS_TYPE_UINT64:
424 element_size = sizeof(uint64_t);
426 case DBUS_TYPE_DOUBLE:
427 element_size = sizeof(double);
429 case DBUS_TYPE_STRING:
430 case DBUS_TYPE_OBJECT_PATH:
431 element_size = sizeof(char *);
434 dbus_set_error(error, DBUS_ERROR_FAILED,
435 "%s: unknown element type %d", __func__, type);
439 for (i = 0; i < array_len; i++) {
440 if (!dbus_message_iter_append_basic(&array_iter, type,
441 array + i * element_size)) {
442 dbus_set_error(error, DBUS_ERROR_FAILED,
443 "%s: failed to construct message 2.5",
449 if (!dbus_message_iter_close_container(&variant_iter, &array_iter)) {
450 dbus_set_error(error, DBUS_ERROR_FAILED,
451 "%s: failed to construct message 3", __func__);
455 if (!dbus_message_iter_close_container(iter, &variant_iter)) {
456 dbus_set_error(error, DBUS_ERROR_FAILED,
457 "%s: failed to construct message 4", __func__);
466 * wpas_dbus_simple_array_array_property_getter - Get array array type property
467 * @iter: Pointer to incoming dbus message iterator
468 * @type: DBus type of property array elements (must be basic type)
469 * @array: pointer to array of elements to put into response message
470 * @array_len: length of above array
471 * @error: a pointer to an error to fill on failure
472 * Returns: TRUE if the request succeeded, FALSE if it failed
474 * Generic getter for array type properties. Array elements type is
475 * required to be basic.
477 dbus_bool_t wpas_dbus_simple_array_array_property_getter(DBusMessageIter *iter,
479 struct wpabuf **array,
483 DBusMessageIter variant_iter, array_iter;
484 char type_str[] = "aa?";
485 char inner_type_str[] = "a?";
486 const char *sub_type_str;
489 if (!dbus_type_is_basic(type)) {
490 dbus_set_error(error, DBUS_ERROR_FAILED,
491 "%s: given type is not basic", __func__);
495 sub_type_str = wpa_dbus_type_as_string(type);
496 type_str[2] = sub_type_str[0];
497 inner_type_str[1] = sub_type_str[0];
499 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
500 type_str, &variant_iter)) {
501 dbus_set_error(error, DBUS_ERROR_FAILED,
502 "%s: failed to construct message 1", __func__);
505 if (!dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
506 inner_type_str, &array_iter)) {
507 dbus_set_error(error, DBUS_ERROR_FAILED,
508 "%s: failed to construct message 2", __func__);
512 for (i = 0; i < array_len && array[i]; i++) {
513 wpa_dbus_dict_bin_array_add_element(&array_iter,
514 wpabuf_head(array[i]),
515 wpabuf_len(array[i]));
519 if (!dbus_message_iter_close_container(&variant_iter, &array_iter)) {
520 dbus_set_error(error, DBUS_ERROR_FAILED,
521 "%s: failed to close message 2", __func__);
525 if (!dbus_message_iter_close_container(iter, &variant_iter)) {
526 dbus_set_error(error, DBUS_ERROR_FAILED,
527 "%s: failed to close message 1", __func__);
536 * wpas_dbus_handler_create_interface - Request registration of a network iface
537 * @message: Pointer to incoming dbus message
538 * @global: %wpa_supplicant global data structure
539 * Returns: The object path of the new interface object,
540 * or a dbus error message with more information
542 * Handler function for "CreateInterface" method call. Handles requests
543 * by dbus clients to register a network interface that wpa_supplicant
546 DBusMessage * wpas_dbus_handler_create_interface(DBusMessage *message,
547 struct wpa_global *global)
549 DBusMessageIter iter_dict;
550 DBusMessage *reply = NULL;
551 DBusMessageIter iter;
552 struct wpa_dbus_dict_entry entry;
555 char *confname = NULL;
556 char *bridge_ifname = NULL;
558 dbus_message_iter_init(message, &iter);
560 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
562 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
563 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
565 if (!os_strcmp(entry.key, "Driver") &&
566 (entry.type == DBUS_TYPE_STRING)) {
568 driver = os_strdup(entry.str_value);
569 wpa_dbus_dict_entry_clear(&entry);
572 } else if (!os_strcmp(entry.key, "Ifname") &&
573 (entry.type == DBUS_TYPE_STRING)) {
575 ifname = os_strdup(entry.str_value);
576 wpa_dbus_dict_entry_clear(&entry);
579 } else if (!os_strcmp(entry.key, "ConfigFile") &&
580 (entry.type == DBUS_TYPE_STRING)) {
582 confname = os_strdup(entry.str_value);
583 wpa_dbus_dict_entry_clear(&entry);
584 if (confname == NULL)
586 } else if (!os_strcmp(entry.key, "BridgeIfname") &&
587 (entry.type == DBUS_TYPE_STRING)) {
588 os_free(bridge_ifname);
589 bridge_ifname = os_strdup(entry.str_value);
590 wpa_dbus_dict_entry_clear(&entry);
591 if (bridge_ifname == NULL)
594 wpa_dbus_dict_entry_clear(&entry);
600 goto error; /* Required Ifname argument missing */
603 * Try to get the wpa_supplicant record for this iface, return
604 * an error if we already control it.
606 if (wpa_supplicant_get_iface(global, ifname) != NULL) {
607 reply = dbus_message_new_error(message,
608 WPAS_DBUS_ERROR_IFACE_EXISTS,
609 "wpa_supplicant already "
610 "controls this interface.");
612 struct wpa_supplicant *wpa_s;
613 struct wpa_interface iface;
614 os_memset(&iface, 0, sizeof(iface));
615 iface.driver = driver;
616 iface.ifname = ifname;
617 iface.confname = confname;
618 iface.bridge_ifname = bridge_ifname;
619 /* Otherwise, have wpa_supplicant attach to it. */
620 if ((wpa_s = wpa_supplicant_add_iface(global, &iface))) {
621 const char *path = wpa_s->dbus_new_path;
622 reply = dbus_message_new_method_return(message);
623 dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH,
624 &path, DBUS_TYPE_INVALID);
626 reply = wpas_dbus_error_unknown_error(
627 message, "wpa_supplicant couldn't grab this "
636 os_free(bridge_ifname);
640 reply = wpas_dbus_error_invalid_args(message, NULL);
646 * wpas_dbus_handler_remove_interface - Request deregistration of an interface
647 * @message: Pointer to incoming dbus message
648 * @global: wpa_supplicant global data structure
649 * Returns: a dbus message containing a UINT32 indicating success (1) or
650 * failure (0), or returns a dbus error message with more information
652 * Handler function for "removeInterface" method call. Handles requests
653 * by dbus clients to deregister a network interface that wpa_supplicant
656 DBusMessage * wpas_dbus_handler_remove_interface(DBusMessage *message,
657 struct wpa_global *global)
659 struct wpa_supplicant *wpa_s;
661 DBusMessage *reply = NULL;
663 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path,
666 wpa_s = get_iface_by_dbus_path(global, path);
668 reply = wpas_dbus_error_iface_unknown(message);
669 else if (wpa_supplicant_remove_iface(global, wpa_s, 0)) {
670 reply = wpas_dbus_error_unknown_error(
671 message, "wpa_supplicant couldn't remove this "
680 * wpas_dbus_handler_get_interface - Get the object path for an interface name
681 * @message: Pointer to incoming dbus message
682 * @global: %wpa_supplicant global data structure
683 * Returns: The object path of the interface object,
684 * or a dbus error message with more information
686 * Handler function for "getInterface" method call.
688 DBusMessage * wpas_dbus_handler_get_interface(DBusMessage *message,
689 struct wpa_global *global)
691 DBusMessage *reply = NULL;
694 struct wpa_supplicant *wpa_s;
696 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &ifname,
699 wpa_s = wpa_supplicant_get_iface(global, ifname);
701 return wpas_dbus_error_iface_unknown(message);
703 path = wpa_s->dbus_new_path;
704 reply = dbus_message_new_method_return(message);
706 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
708 if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
709 DBUS_TYPE_INVALID)) {
710 dbus_message_unref(reply);
711 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
720 * wpas_dbus_getter_debug_level - Get debug level
721 * @iter: Pointer to incoming dbus message iter
722 * @error: Location to store error on failure
723 * @user_data: Function specific data
724 * Returns: TRUE on success, FALSE on failure
726 * Getter for "DebugLevel" property.
728 dbus_bool_t wpas_dbus_getter_debug_level(DBusMessageIter *iter,
733 int idx = wpa_debug_level;
739 str = debug_strings[idx];
740 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
746 * wpas_dbus_getter_debug_timestamp - Get debug timestamp
747 * @iter: Pointer to incoming dbus message iter
748 * @error: Location to store error on failure
749 * @user_data: Function specific data
750 * Returns: TRUE on success, FALSE on failure
752 * Getter for "DebugTimestamp" property.
754 dbus_bool_t wpas_dbus_getter_debug_timestamp(DBusMessageIter *iter,
758 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
759 &wpa_debug_timestamp, error);
765 * wpas_dbus_getter_debug_show_keys - Get debug show keys
766 * @iter: Pointer to incoming dbus message iter
767 * @error: Location to store error on failure
768 * @user_data: Function specific data
769 * Returns: TRUE on success, FALSE on failure
771 * Getter for "DebugShowKeys" property.
773 dbus_bool_t wpas_dbus_getter_debug_show_keys(DBusMessageIter *iter,
777 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
778 &wpa_debug_show_keys, error);
783 * wpas_dbus_setter_debug_level - Set debug level
784 * @iter: Pointer to incoming dbus message iter
785 * @error: Location to store error on failure
786 * @user_data: Function specific data
787 * Returns: TRUE on success, FALSE on failure
789 * Setter for "DebugLevel" property.
791 dbus_bool_t wpas_dbus_setter_debug_level(DBusMessageIter *iter,
792 DBusError *error, void *user_data)
794 struct wpa_global *global = user_data;
795 const char *str = NULL;
798 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
802 for (i = 0; debug_strings[i]; i++)
803 if (os_strcmp(debug_strings[i], str) == 0) {
809 wpa_supplicant_set_debug_params(global, val, wpa_debug_timestamp,
810 wpa_debug_show_keys)) {
811 dbus_set_error_const(error, DBUS_ERROR_FAILED, "wrong debug "
821 * wpas_dbus_setter_debug_timestamp - Set debug timestamp
822 * @iter: Pointer to incoming dbus message iter
823 * @error: Location to store error on failure
824 * @user_data: Function specific data
825 * Returns: TRUE on success, FALSE on failure
827 * Setter for "DebugTimestamp" property.
829 dbus_bool_t wpas_dbus_setter_debug_timestamp(DBusMessageIter *iter,
833 struct wpa_global *global = user_data;
836 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
840 wpa_supplicant_set_debug_params(global, wpa_debug_level, val ? 1 : 0,
841 wpa_debug_show_keys);
847 * wpas_dbus_setter_debug_show_keys - Set debug show keys
848 * @iter: Pointer to incoming dbus message iter
849 * @error: Location to store error on failure
850 * @user_data: Function specific data
851 * Returns: TRUE on success, FALSE on failure
853 * Setter for "DebugShowKeys" property.
855 dbus_bool_t wpas_dbus_setter_debug_show_keys(DBusMessageIter *iter,
859 struct wpa_global *global = user_data;
862 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
866 wpa_supplicant_set_debug_params(global, wpa_debug_level,
874 * wpas_dbus_getter_interfaces - Request registered interfaces list
875 * @iter: Pointer to incoming dbus message iter
876 * @error: Location to store error on failure
877 * @user_data: Function specific data
878 * Returns: TRUE on success, FALSE on failure
880 * Getter for "Interfaces" property. Handles requests
881 * by dbus clients to return list of registered interfaces objects
884 dbus_bool_t wpas_dbus_getter_interfaces(DBusMessageIter *iter,
888 struct wpa_global *global = user_data;
889 struct wpa_supplicant *wpa_s;
891 unsigned int i = 0, num = 0;
894 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
897 paths = os_calloc(num, sizeof(char *));
899 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
903 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
904 paths[i++] = wpa_s->dbus_new_path;
906 success = wpas_dbus_simple_array_property_getter(iter,
907 DBUS_TYPE_OBJECT_PATH,
916 * wpas_dbus_getter_eap_methods - Request supported EAP methods list
917 * @iter: Pointer to incoming dbus message iter
918 * @error: Location to store error on failure
919 * @user_data: Function specific data
920 * Returns: TRUE on success, FALSE on failure
922 * Getter for "EapMethods" property. Handles requests
923 * by dbus clients to return list of strings with supported EAP methods
925 dbus_bool_t wpas_dbus_getter_eap_methods(DBusMessageIter *iter,
926 DBusError *error, void *user_data)
929 size_t num_items = 0;
932 eap_methods = eap_get_names_as_string_array(&num_items);
934 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
938 success = wpas_dbus_simple_array_property_getter(iter,
944 os_free(eap_methods[--num_items]);
945 os_free(eap_methods);
951 * wpas_dbus_getter_global_capabilities - Request supported global capabilities
952 * @iter: Pointer to incoming dbus message iter
953 * @error: Location to store error on failure
954 * @user_data: Function specific data
955 * Returns: TRUE on success, FALSE on failure
957 * Getter for "Capabilities" property. Handles requests by dbus clients to
958 * return a list of strings with supported capabilities like AP, RSN IBSS,
959 * and P2P that are determined at compile time.
961 dbus_bool_t wpas_dbus_getter_global_capabilities(DBusMessageIter *iter,
965 const char *capabilities[5] = { NULL, NULL, NULL, NULL, NULL };
966 size_t num_items = 0;
969 capabilities[num_items++] = "ap";
970 #endif /* CONFIG_AP */
971 #ifdef CONFIG_IBSS_RSN
972 capabilities[num_items++] = "ibss-rsn";
973 #endif /* CONFIG_IBSS_RSN */
975 capabilities[num_items++] = "p2p";
976 #endif /* CONFIG_P2P */
977 #ifdef CONFIG_INTERWORKING
978 capabilities[num_items++] = "interworking";
979 #endif /* CONFIG_INTERWORKING */
981 return wpas_dbus_simple_array_property_getter(iter,
988 static int wpas_dbus_get_scan_type(DBusMessage *message, DBusMessageIter *var,
989 char **type, DBusMessage **reply)
991 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_STRING) {
992 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
993 "Type must be a string");
994 *reply = wpas_dbus_error_invalid_args(
995 message, "Wrong Type value type. String required");
998 dbus_message_iter_get_basic(var, type);
1003 static int wpas_dbus_get_scan_ssids(DBusMessage *message, DBusMessageIter *var,
1004 struct wpa_driver_scan_params *params,
1005 DBusMessage **reply)
1007 struct wpa_driver_scan_ssid *ssids = params->ssids;
1008 size_t ssids_num = 0;
1010 DBusMessageIter array_iter, sub_array_iter;
1014 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
1015 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: ssids "
1016 "must be an array of arrays of bytes");
1017 *reply = wpas_dbus_error_invalid_args(
1018 message, "Wrong SSIDs value type. Array of arrays of "
1023 dbus_message_iter_recurse(var, &array_iter);
1025 if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY ||
1026 dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_BYTE)
1028 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: ssids "
1029 "must be an array of arrays of bytes");
1030 *reply = wpas_dbus_error_invalid_args(
1031 message, "Wrong SSIDs value type. Array of arrays of "
1036 while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_ARRAY)
1038 if (ssids_num >= WPAS_MAX_SCAN_SSIDS) {
1039 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1040 "Too many ssids specified on scan dbus "
1042 *reply = wpas_dbus_error_invalid_args(
1043 message, "Too many ssids specified. Specify "
1048 dbus_message_iter_recurse(&array_iter, &sub_array_iter);
1050 dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len);
1052 if (len > MAX_SSID_LEN) {
1053 wpa_printf(MSG_DEBUG,
1054 "wpas_dbus_handler_scan[dbus]: "
1055 "SSID too long (len=%d max_len=%d)",
1057 *reply = wpas_dbus_error_invalid_args(
1058 message, "Invalid SSID: too long");
1063 ssid = os_malloc(len);
1065 wpa_printf(MSG_DEBUG,
1066 "wpas_dbus_handler_scan[dbus]: "
1067 "out of memory. Cannot allocate "
1069 *reply = dbus_message_new_error(
1070 message, DBUS_ERROR_NO_MEMORY, NULL);
1073 os_memcpy(ssid, val, len);
1075 /* Allow zero-length SSIDs */
1079 ssids[ssids_num].ssid = ssid;
1080 ssids[ssids_num].ssid_len = len;
1082 dbus_message_iter_next(&array_iter);
1086 params->num_ssids = ssids_num;
1091 static int wpas_dbus_get_scan_ies(DBusMessage *message, DBusMessageIter *var,
1092 struct wpa_driver_scan_params *params,
1093 DBusMessage **reply)
1095 u8 *ies = NULL, *nies;
1097 DBusMessageIter array_iter, sub_array_iter;
1101 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
1102 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: ies must "
1103 "be an array of arrays of bytes");
1104 *reply = wpas_dbus_error_invalid_args(
1105 message, "Wrong IEs value type. Array of arrays of "
1110 dbus_message_iter_recurse(var, &array_iter);
1112 if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY ||
1113 dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_BYTE)
1115 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: ies must "
1116 "be an array of arrays of bytes");
1117 *reply = wpas_dbus_error_invalid_args(
1118 message, "Wrong IEs value type. Array required");
1122 while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_ARRAY)
1124 dbus_message_iter_recurse(&array_iter, &sub_array_iter);
1126 dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len);
1128 dbus_message_iter_next(&array_iter);
1132 nies = os_realloc(ies, ies_len + len);
1134 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1135 "out of memory. Cannot allocate memory for "
1138 *reply = dbus_message_new_error(
1139 message, DBUS_ERROR_NO_MEMORY, NULL);
1143 os_memcpy(ies + ies_len, val, len);
1146 dbus_message_iter_next(&array_iter);
1149 params->extra_ies = ies;
1150 params->extra_ies_len = ies_len;
1155 static int wpas_dbus_get_scan_channels(DBusMessage *message,
1156 DBusMessageIter *var,
1157 struct wpa_driver_scan_params *params,
1158 DBusMessage **reply)
1160 DBusMessageIter array_iter, sub_array_iter;
1161 int *freqs = NULL, *nfreqs;
1164 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
1165 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1166 "Channels must be an array of structs");
1167 *reply = wpas_dbus_error_invalid_args(
1168 message, "Wrong Channels value type. Array of structs "
1173 dbus_message_iter_recurse(var, &array_iter);
1175 if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_STRUCT) {
1176 wpa_printf(MSG_DEBUG,
1177 "wpas_dbus_handler_scan[dbus]: Channels must be an "
1178 "array of structs");
1179 *reply = wpas_dbus_error_invalid_args(
1180 message, "Wrong Channels value type. Array of structs "
1185 while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_STRUCT)
1189 dbus_message_iter_recurse(&array_iter, &sub_array_iter);
1191 if (dbus_message_iter_get_arg_type(&sub_array_iter) !=
1193 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1194 "Channel must by specified by struct of "
1196 dbus_message_iter_get_arg_type(
1198 *reply = wpas_dbus_error_invalid_args(
1199 message, "Wrong Channel struct. Two UINT32s "
1204 dbus_message_iter_get_basic(&sub_array_iter, &freq);
1206 if (!dbus_message_iter_next(&sub_array_iter) ||
1207 dbus_message_iter_get_arg_type(&sub_array_iter) !=
1209 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1210 "Channel must by specified by struct of "
1212 *reply = wpas_dbus_error_invalid_args(
1214 "Wrong Channel struct. Two UINT32s required");
1219 dbus_message_iter_get_basic(&sub_array_iter, &width);
1221 #define FREQS_ALLOC_CHUNK 32
1222 if (freqs_num % FREQS_ALLOC_CHUNK == 0) {
1223 nfreqs = os_realloc_array(
1224 freqs, freqs_num + FREQS_ALLOC_CHUNK,
1230 if (freqs == NULL) {
1231 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1232 "out of memory. can't allocate memory for "
1234 *reply = dbus_message_new_error(
1235 message, DBUS_ERROR_NO_MEMORY, NULL);
1239 freqs[freqs_num] = freq;
1242 dbus_message_iter_next(&array_iter);
1245 nfreqs = os_realloc_array(freqs, freqs_num + 1, sizeof(int));
1249 if (freqs == NULL) {
1250 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1251 "out of memory. Can't allocate memory for freqs");
1252 *reply = dbus_message_new_error(
1253 message, DBUS_ERROR_NO_MEMORY, NULL);
1256 freqs[freqs_num] = 0;
1258 params->freqs = freqs;
1263 static int wpas_dbus_get_scan_allow_roam(DBusMessage *message,
1264 DBusMessageIter *var,
1266 DBusMessage **reply)
1268 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_BOOLEAN) {
1269 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1270 "Type must be a boolean");
1271 *reply = wpas_dbus_error_invalid_args(
1272 message, "Wrong Type value type. Boolean required");
1275 dbus_message_iter_get_basic(var, allow);
1281 * wpas_dbus_handler_scan - Request a wireless scan on an interface
1282 * @message: Pointer to incoming dbus message
1283 * @wpa_s: wpa_supplicant structure for a network interface
1284 * Returns: NULL indicating success or DBus error message on failure
1286 * Handler function for "Scan" method call of a network device. Requests
1287 * that wpa_supplicant perform a wireless scan as soon as possible
1288 * on a particular wireless interface.
1290 DBusMessage * wpas_dbus_handler_scan(DBusMessage *message,
1291 struct wpa_supplicant *wpa_s)
1293 DBusMessage *reply = NULL;
1294 DBusMessageIter iter, dict_iter, entry_iter, variant_iter;
1295 char *key = NULL, *type = NULL;
1296 struct wpa_driver_scan_params params;
1298 dbus_bool_t allow_roam = 1;
1300 os_memset(¶ms, 0, sizeof(params));
1302 dbus_message_iter_init(message, &iter);
1304 dbus_message_iter_recurse(&iter, &dict_iter);
1306 while (dbus_message_iter_get_arg_type(&dict_iter) ==
1307 DBUS_TYPE_DICT_ENTRY) {
1308 dbus_message_iter_recurse(&dict_iter, &entry_iter);
1309 dbus_message_iter_get_basic(&entry_iter, &key);
1310 dbus_message_iter_next(&entry_iter);
1311 dbus_message_iter_recurse(&entry_iter, &variant_iter);
1313 if (os_strcmp(key, "Type") == 0) {
1314 if (wpas_dbus_get_scan_type(message, &variant_iter,
1317 } else if (os_strcmp(key, "SSIDs") == 0) {
1318 if (wpas_dbus_get_scan_ssids(message, &variant_iter,
1319 ¶ms, &reply) < 0)
1321 } else if (os_strcmp(key, "IEs") == 0) {
1322 if (wpas_dbus_get_scan_ies(message, &variant_iter,
1323 ¶ms, &reply) < 0)
1325 } else if (os_strcmp(key, "Channels") == 0) {
1326 if (wpas_dbus_get_scan_channels(message, &variant_iter,
1327 ¶ms, &reply) < 0)
1329 } else if (os_strcmp(key, "AllowRoam") == 0) {
1330 if (wpas_dbus_get_scan_allow_roam(message,
1336 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1337 "Unknown argument %s", key);
1338 reply = wpas_dbus_error_invalid_args(message, key);
1342 dbus_message_iter_next(&dict_iter);
1346 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1347 "Scan type not specified");
1348 reply = wpas_dbus_error_invalid_args(message, key);
1352 if (!os_strcmp(type, "passive")) {
1353 if (params.num_ssids || params.extra_ies_len) {
1354 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1355 "SSIDs or IEs specified for passive scan.");
1356 reply = wpas_dbus_error_invalid_args(
1357 message, "You can specify only Channels in "
1360 } else if (params.freqs && params.freqs[0]) {
1361 if (wpa_supplicant_trigger_scan(wpa_s, ¶ms)) {
1362 reply = wpas_dbus_error_scan_error(
1363 message, "Scan request rejected");
1366 wpa_s->scan_req = MANUAL_SCAN_REQ;
1367 wpa_supplicant_req_scan(wpa_s, 0, 0);
1369 } else if (!os_strcmp(type, "active")) {
1370 if (!params.num_ssids) {
1371 /* Add wildcard ssid */
1374 #ifdef CONFIG_AUTOSCAN
1375 autoscan_deinit(wpa_s);
1376 #endif /* CONFIG_AUTOSCAN */
1377 if (wpa_supplicant_trigger_scan(wpa_s, ¶ms)) {
1378 reply = wpas_dbus_error_scan_error(
1379 message, "Scan request rejected");
1382 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1383 "Unknown scan type: %s", type);
1384 reply = wpas_dbus_error_invalid_args(message,
1390 wpa_s->scan_res_handler = scan_only_handler;
1393 for (i = 0; i < WPAS_MAX_SCAN_SSIDS; i++)
1394 os_free((u8 *) params.ssids[i].ssid);
1395 os_free((u8 *) params.extra_ies);
1396 os_free(params.freqs);
1402 * wpas_dbus_handler_signal_poll - Request immediate signal properties
1403 * @message: Pointer to incoming dbus message
1404 * @wpa_s: wpa_supplicant structure for a network interface
1405 * Returns: NULL indicating success or DBus error message on failure
1407 * Handler function for "SignalPoll" method call of a network device. Requests
1408 * that wpa_supplicant read signal properties like RSSI, noise, and link
1409 * speed and return them.
1411 DBusMessage * wpas_dbus_handler_signal_poll(DBusMessage *message,
1412 struct wpa_supplicant *wpa_s)
1414 struct wpa_signal_info si;
1415 DBusMessage *reply = NULL;
1416 DBusMessageIter iter, iter_dict, variant_iter;
1419 ret = wpa_drv_signal_poll(wpa_s, &si);
1421 return dbus_message_new_error(message, DBUS_ERROR_FAILED,
1422 "Failed to read signal");
1425 reply = dbus_message_new_method_return(message);
1429 dbus_message_iter_init_append(reply, &iter);
1431 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
1432 "a{sv}", &variant_iter))
1434 if (!wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
1437 if (!wpa_dbus_dict_append_int32(&iter_dict, "rssi", si.current_signal))
1439 if (!wpa_dbus_dict_append_int32(&iter_dict, "linkspeed",
1440 si.current_txrate / 1000))
1442 if (!wpa_dbus_dict_append_int32(&iter_dict, "noise", si.current_noise))
1444 if (!wpa_dbus_dict_append_uint32(&iter_dict, "frequency", si.frequency))
1447 if (si.chanwidth != CHAN_WIDTH_UNKNOWN) {
1448 if (!wpa_dbus_dict_append_string(&iter_dict, "width",
1449 channel_width_to_string(si.chanwidth)))
1453 if (si.center_frq1 > 0 && si.center_frq2 > 0) {
1454 if (!wpa_dbus_dict_append_int32(&iter_dict, "center-frq1",
1457 if (!wpa_dbus_dict_append_int32(&iter_dict, "center-frq2",
1462 if (si.avg_signal) {
1463 if (!wpa_dbus_dict_append_int32(&iter_dict, "avg-rssi",
1468 if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict))
1470 if (!dbus_message_iter_close_container(&iter, &variant_iter))
1477 dbus_message_unref(reply);
1478 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, NULL);
1484 * wpas_dbus_handler_disconnect - Terminate the current connection
1485 * @message: Pointer to incoming dbus message
1486 * @wpa_s: wpa_supplicant structure for a network interface
1487 * Returns: NotConnected DBus error message if already not connected
1488 * or NULL otherwise.
1490 * Handler function for "Disconnect" method call of network interface.
1492 DBusMessage * wpas_dbus_handler_disconnect(DBusMessage *message,
1493 struct wpa_supplicant *wpa_s)
1495 if (wpa_s->current_ssid != NULL) {
1496 wpa_s->disconnected = 1;
1497 wpa_supplicant_deauthenticate(wpa_s,
1498 WLAN_REASON_DEAUTH_LEAVING);
1503 return dbus_message_new_error(message, WPAS_DBUS_ERROR_NOT_CONNECTED,
1504 "This interface is not connected");
1509 * wpas_dbus_new_iface_add_network - Add a new configured network
1510 * @message: Pointer to incoming dbus message
1511 * @wpa_s: wpa_supplicant structure for a network interface
1512 * Returns: A dbus message containing the object path of the new network
1514 * Handler function for "AddNetwork" method call of a network interface.
1516 DBusMessage * wpas_dbus_handler_add_network(DBusMessage *message,
1517 struct wpa_supplicant *wpa_s)
1519 DBusMessage *reply = NULL;
1520 DBusMessageIter iter;
1521 struct wpa_ssid *ssid = NULL;
1522 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf;
1525 dbus_message_iter_init(message, &iter);
1527 ssid = wpa_config_add_network(wpa_s->conf);
1529 wpa_printf(MSG_ERROR, "wpas_dbus_handler_add_network[dbus]: "
1530 "can't add new interface.");
1531 reply = wpas_dbus_error_unknown_error(
1533 "wpa_supplicant could not add "
1534 "a network on this interface.");
1537 wpas_notify_network_added(wpa_s, ssid);
1539 wpa_config_set_network_defaults(ssid);
1541 dbus_error_init(&error);
1542 if (!set_network_properties(wpa_s, ssid, &iter, &error)) {
1543 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_add_network[dbus]:"
1544 "control interface couldn't set network "
1546 reply = wpas_dbus_reply_new_from_error(message, &error,
1547 DBUS_ERROR_INVALID_ARGS,
1548 "Failed to add network");
1549 dbus_error_free(&error);
1553 /* Construct the object path for this network. */
1554 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
1555 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
1556 wpa_s->dbus_new_path, ssid->id);
1558 reply = dbus_message_new_method_return(message);
1559 if (reply == NULL) {
1560 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1564 if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
1565 DBUS_TYPE_INVALID)) {
1566 dbus_message_unref(reply);
1567 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1576 wpas_notify_network_removed(wpa_s, ssid);
1577 wpa_config_remove_network(wpa_s->conf, ssid->id);
1584 * wpas_dbus_handler_reassociate - Reassociate
1585 * @message: Pointer to incoming dbus message
1586 * @wpa_s: wpa_supplicant structure for a network interface
1587 * Returns: InterfaceDisabled DBus error message if disabled
1588 * or NULL otherwise.
1590 * Handler function for "Reassociate" method call of network interface.
1592 DBusMessage * wpas_dbus_handler_reassociate(DBusMessage *message,
1593 struct wpa_supplicant *wpa_s)
1595 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED) {
1596 wpas_request_connection(wpa_s);
1600 return dbus_message_new_error(message, WPAS_DBUS_ERROR_IFACE_DISABLED,
1601 "This interface is disabled");
1606 * wpas_dbus_handler_reattach - Reattach to current AP
1607 * @message: Pointer to incoming dbus message
1608 * @wpa_s: wpa_supplicant structure for a network interface
1609 * Returns: NotConnected DBus error message if not connected
1610 * or NULL otherwise.
1612 * Handler function for "Reattach" method call of network interface.
1614 DBusMessage * wpas_dbus_handler_reattach(DBusMessage *message,
1615 struct wpa_supplicant *wpa_s)
1617 if (wpa_s->current_ssid != NULL) {
1618 wpa_s->reattach = 1;
1619 wpas_request_connection(wpa_s);
1623 return dbus_message_new_error(message, WPAS_DBUS_ERROR_NOT_CONNECTED,
1624 "This interface is not connected");
1629 * wpas_dbus_handler_remove_network - Remove a configured network
1630 * @message: Pointer to incoming dbus message
1631 * @wpa_s: wpa_supplicant structure for a network interface
1632 * Returns: NULL on success or dbus error on failure
1634 * Handler function for "RemoveNetwork" method call of a network interface.
1636 DBusMessage * wpas_dbus_handler_remove_network(DBusMessage *message,
1637 struct wpa_supplicant *wpa_s)
1639 DBusMessage *reply = NULL;
1641 char *iface = NULL, *net_id = NULL;
1643 struct wpa_ssid *ssid;
1646 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
1649 /* Extract the network ID and ensure the network */
1650 /* is actually a child of this interface */
1651 iface = wpas_dbus_new_decompose_object_path(op, 0, &net_id, NULL);
1652 if (iface == NULL || net_id == NULL ||
1653 os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
1654 reply = wpas_dbus_error_invalid_args(message, op);
1659 id = strtoul(net_id, NULL, 10);
1661 reply = wpas_dbus_error_invalid_args(message, op);
1665 ssid = wpa_config_get_network(wpa_s->conf, id);
1667 reply = wpas_dbus_error_network_unknown(message);
1671 was_disabled = ssid->disabled;
1673 wpas_notify_network_removed(wpa_s, ssid);
1675 if (ssid == wpa_s->current_ssid)
1676 wpa_supplicant_deauthenticate(wpa_s,
1677 WLAN_REASON_DEAUTH_LEAVING);
1678 else if (!was_disabled && wpa_s->sched_scanning) {
1679 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to remove "
1680 "network from filters");
1681 wpa_supplicant_cancel_sched_scan(wpa_s);
1682 wpa_supplicant_req_scan(wpa_s, 0, 0);
1685 if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
1686 wpa_printf(MSG_ERROR,
1687 "wpas_dbus_handler_remove_network[dbus]: "
1688 "error occurred when removing network %d", id);
1689 reply = wpas_dbus_error_unknown_error(
1690 message, "error removing the specified network on "
1702 static void remove_network(void *arg, struct wpa_ssid *ssid)
1704 struct wpa_supplicant *wpa_s = arg;
1706 wpas_notify_network_removed(wpa_s, ssid);
1708 if (wpa_config_remove_network(wpa_s->conf, ssid->id) < 0) {
1709 wpa_printf(MSG_ERROR,
1710 "wpas_dbus_handler_remove_all_networks[dbus]: "
1711 "error occurred when removing network %d",
1716 if (ssid == wpa_s->current_ssid)
1717 wpa_supplicant_deauthenticate(wpa_s,
1718 WLAN_REASON_DEAUTH_LEAVING);
1723 * wpas_dbus_handler_remove_all_networks - Remove all configured networks
1724 * @message: Pointer to incoming dbus message
1725 * @wpa_s: wpa_supplicant structure for a network interface
1726 * Returns: NULL on success or dbus error on failure
1728 * Handler function for "RemoveAllNetworks" method call of a network interface.
1730 DBusMessage * wpas_dbus_handler_remove_all_networks(
1731 DBusMessage *message, struct wpa_supplicant *wpa_s)
1733 if (wpa_s->sched_scanning)
1734 wpa_supplicant_cancel_sched_scan(wpa_s);
1736 /* NB: could check for failure and return an error */
1737 wpa_config_foreach_network(wpa_s->conf, remove_network, wpa_s);
1743 * wpas_dbus_handler_select_network - Attempt association with a network
1744 * @message: Pointer to incoming dbus message
1745 * @wpa_s: wpa_supplicant structure for a network interface
1746 * Returns: NULL on success or dbus error on failure
1748 * Handler function for "SelectNetwork" method call of network interface.
1750 DBusMessage * wpas_dbus_handler_select_network(DBusMessage *message,
1751 struct wpa_supplicant *wpa_s)
1753 DBusMessage *reply = NULL;
1755 char *iface = NULL, *net_id = NULL;
1757 struct wpa_ssid *ssid;
1759 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
1762 /* Extract the network ID and ensure the network */
1763 /* is actually a child of this interface */
1764 iface = wpas_dbus_new_decompose_object_path(op, 0, &net_id, NULL);
1765 if (iface == NULL || net_id == NULL ||
1766 os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
1767 reply = wpas_dbus_error_invalid_args(message, op);
1772 id = strtoul(net_id, NULL, 10);
1774 reply = wpas_dbus_error_invalid_args(message, op);
1778 ssid = wpa_config_get_network(wpa_s->conf, id);
1780 reply = wpas_dbus_error_network_unknown(message);
1784 /* Finally, associate with the network */
1785 wpa_supplicant_select_network(wpa_s, ssid);
1795 * wpas_dbus_handler_network_reply - Reply to a NetworkRequest signal
1796 * @message: Pointer to incoming dbus message
1797 * @wpa_s: wpa_supplicant structure for a network interface
1798 * Returns: NULL on success or dbus error on failure
1800 * Handler function for "NetworkReply" method call of network interface.
1802 DBusMessage * wpas_dbus_handler_network_reply(DBusMessage *message,
1803 struct wpa_supplicant *wpa_s)
1805 #ifdef IEEE8021X_EAPOL
1806 DBusMessage *reply = NULL;
1807 const char *op, *field, *value;
1808 char *iface = NULL, *net_id = NULL;
1810 struct wpa_ssid *ssid;
1812 if (!dbus_message_get_args(message, NULL,
1813 DBUS_TYPE_OBJECT_PATH, &op,
1814 DBUS_TYPE_STRING, &field,
1815 DBUS_TYPE_STRING, &value,
1817 return wpas_dbus_error_invalid_args(message, NULL);
1819 /* Extract the network ID and ensure the network */
1820 /* is actually a child of this interface */
1821 iface = wpas_dbus_new_decompose_object_path(op, 0, &net_id, NULL);
1822 if (iface == NULL || net_id == NULL ||
1823 os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
1824 reply = wpas_dbus_error_invalid_args(message, op);
1829 id = strtoul(net_id, NULL, 10);
1831 reply = wpas_dbus_error_invalid_args(message, net_id);
1835 ssid = wpa_config_get_network(wpa_s->conf, id);
1837 reply = wpas_dbus_error_network_unknown(message);
1841 if (wpa_supplicant_ctrl_iface_ctrl_rsp_handle(wpa_s, ssid,
1843 reply = wpas_dbus_error_invalid_args(message, field);
1845 /* Tell EAP to retry immediately */
1846 eapol_sm_notify_ctrl_response(wpa_s->eapol);
1853 #else /* IEEE8021X_EAPOL */
1854 wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included");
1855 return wpas_dbus_error_unknown_error(message, "802.1X not included");
1856 #endif /* IEEE8021X_EAPOL */
1860 #ifndef CONFIG_NO_CONFIG_BLOBS
1863 * wpas_dbus_handler_add_blob - Store named binary blob (ie, for certificates)
1864 * @message: Pointer to incoming dbus message
1865 * @wpa_s: %wpa_supplicant data structure
1866 * Returns: A dbus message containing an error on failure or NULL on success
1868 * Asks wpa_supplicant to internally store a binary blobs.
1870 DBusMessage * wpas_dbus_handler_add_blob(DBusMessage *message,
1871 struct wpa_supplicant *wpa_s)
1873 DBusMessage *reply = NULL;
1874 DBusMessageIter iter, array_iter;
1879 struct wpa_config_blob *blob = NULL;
1881 dbus_message_iter_init(message, &iter);
1882 dbus_message_iter_get_basic(&iter, &blob_name);
1884 if (wpa_config_get_blob(wpa_s->conf, blob_name)) {
1885 return dbus_message_new_error(message,
1886 WPAS_DBUS_ERROR_BLOB_EXISTS,
1890 dbus_message_iter_next(&iter);
1891 dbus_message_iter_recurse(&iter, &array_iter);
1893 dbus_message_iter_get_fixed_array(&array_iter, &blob_data, &blob_len);
1895 blob = os_zalloc(sizeof(*blob));
1897 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1902 blob->data = os_malloc(blob_len);
1904 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1908 os_memcpy(blob->data, blob_data, blob_len);
1910 blob->len = blob_len;
1911 blob->name = os_strdup(blob_name);
1913 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1918 wpa_config_set_blob(wpa_s->conf, blob);
1919 wpas_notify_blob_added(wpa_s, blob->name);
1925 os_free(blob->name);
1926 os_free(blob->data);
1934 * wpas_dbus_handler_get_blob - Get named binary blob (ie, for certificates)
1935 * @message: Pointer to incoming dbus message
1936 * @wpa_s: %wpa_supplicant data structure
1937 * Returns: A dbus message containing array of bytes (blob)
1939 * Gets one wpa_supplicant's binary blobs.
1941 DBusMessage * wpas_dbus_handler_get_blob(DBusMessage *message,
1942 struct wpa_supplicant *wpa_s)
1944 DBusMessage *reply = NULL;
1945 DBusMessageIter iter, array_iter;
1948 const struct wpa_config_blob *blob;
1950 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &blob_name,
1953 blob = wpa_config_get_blob(wpa_s->conf, blob_name);
1955 return dbus_message_new_error(message,
1956 WPAS_DBUS_ERROR_BLOB_UNKNOWN,
1960 reply = dbus_message_new_method_return(message);
1962 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1967 dbus_message_iter_init_append(reply, &iter);
1969 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
1970 DBUS_TYPE_BYTE_AS_STRING,
1972 dbus_message_unref(reply);
1973 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1978 if (!dbus_message_iter_append_fixed_array(&array_iter, DBUS_TYPE_BYTE,
1979 &(blob->data), blob->len)) {
1980 dbus_message_unref(reply);
1981 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1986 if (!dbus_message_iter_close_container(&iter, &array_iter)) {
1987 dbus_message_unref(reply);
1988 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1999 * wpas_remove_handler_remove_blob - Remove named binary blob
2000 * @message: Pointer to incoming dbus message
2001 * @wpa_s: %wpa_supplicant data structure
2002 * Returns: NULL on success or dbus error
2004 * Asks wpa_supplicant to internally remove a binary blobs.
2006 DBusMessage * wpas_dbus_handler_remove_blob(DBusMessage *message,
2007 struct wpa_supplicant *wpa_s)
2009 DBusMessage *reply = NULL;
2012 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &blob_name,
2015 if (wpa_config_remove_blob(wpa_s->conf, blob_name)) {
2016 return dbus_message_new_error(message,
2017 WPAS_DBUS_ERROR_BLOB_UNKNOWN,
2020 wpas_notify_blob_removed(wpa_s, blob_name);
2026 #endif /* CONFIG_NO_CONFIG_BLOBS */
2030 * wpas_dbus_handler_flush_bss - Flush the BSS cache
2031 * @message: Pointer to incoming dbus message
2032 * @wpa_s: wpa_supplicant structure for a network interface
2035 * Handler function for "FlushBSS" method call of network interface.
2037 DBusMessage * wpas_dbus_handler_flush_bss(DBusMessage *message,
2038 struct wpa_supplicant *wpa_s)
2042 dbus_message_get_args(message, NULL, DBUS_TYPE_UINT32, &age,
2046 wpa_bss_flush(wpa_s);
2048 wpa_bss_flush_by_age(wpa_s, age);
2054 #ifdef CONFIG_AUTOSCAN
2056 * wpas_dbus_handler_autoscan - Set autoscan parameters for the interface
2057 * @message: Pointer to incoming dbus message
2058 * @wpa_s: wpa_supplicant structure for a network interface
2061 * Handler function for "AutoScan" method call of network interface.
2063 DBusMessage * wpas_dbus_handler_autoscan(DBusMessage *message,
2064 struct wpa_supplicant *wpa_s)
2066 DBusMessage *reply = NULL;
2067 enum wpa_states state = wpa_s->wpa_state;
2070 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &arg,
2073 if (arg != NULL && os_strlen(arg) > 0) {
2075 tmp = os_strdup(arg);
2077 reply = dbus_message_new_error(message,
2078 DBUS_ERROR_NO_MEMORY,
2081 os_free(wpa_s->conf->autoscan);
2082 wpa_s->conf->autoscan = tmp;
2083 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
2084 autoscan_init(wpa_s, 1);
2085 else if (state == WPA_SCANNING)
2086 wpa_supplicant_reinit_autoscan(wpa_s);
2088 } else if (arg != NULL && os_strlen(arg) == 0) {
2089 os_free(wpa_s->conf->autoscan);
2090 wpa_s->conf->autoscan = NULL;
2091 autoscan_deinit(wpa_s);
2093 reply = dbus_message_new_error(message,
2094 DBUS_ERROR_INVALID_ARGS,
2099 #endif /* CONFIG_AUTOSCAN */
2103 * wpas_dbus_handler_eap_logoff - IEEE 802.1X EAPOL state machine logoff
2104 * @message: Pointer to incoming dbus message
2105 * @wpa_s: wpa_supplicant structure for a network interface
2108 * Handler function for "EAPLogoff" method call of network interface.
2110 DBusMessage * wpas_dbus_handler_eap_logoff(DBusMessage *message,
2111 struct wpa_supplicant *wpa_s)
2113 eapol_sm_notify_logoff(wpa_s->eapol, TRUE);
2119 * wpas_dbus_handler_eap_logon - IEEE 802.1X EAPOL state machine logon
2120 * @message: Pointer to incoming dbus message
2121 * @wpa_s: wpa_supplicant structure for a network interface
2124 * Handler function for "EAPLogin" method call of network interface.
2126 DBusMessage * wpas_dbus_handler_eap_logon(DBusMessage *message,
2127 struct wpa_supplicant *wpa_s)
2129 eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
2136 static int get_peer_hwaddr_helper(DBusMessage *message, const char *func_name,
2137 u8 *peer_address, DBusMessage **error)
2139 const char *peer_string;
2143 if (!dbus_message_get_args(message, NULL,
2144 DBUS_TYPE_STRING, &peer_string,
2145 DBUS_TYPE_INVALID)) {
2146 *error = wpas_dbus_error_invalid_args(message, NULL);
2150 if (hwaddr_aton(peer_string, peer_address)) {
2151 wpa_printf(MSG_DEBUG, "%s: invalid address '%s'",
2152 func_name, peer_string);
2153 *error = wpas_dbus_error_invalid_args(
2154 message, "Invalid hardware address format");
2163 * wpas_dbus_handler_tdls_discover - Discover TDLS peer
2164 * @message: Pointer to incoming dbus message
2165 * @wpa_s: wpa_supplicant structure for a network interface
2166 * Returns: NULL indicating success or DBus error message on failure
2168 * Handler function for "TDLSDiscover" method call of network interface.
2170 DBusMessage * wpas_dbus_handler_tdls_discover(DBusMessage *message,
2171 struct wpa_supplicant *wpa_s)
2174 DBusMessage *error_reply;
2177 if (get_peer_hwaddr_helper(message, __func__, peer, &error_reply) < 0)
2180 wpa_printf(MSG_DEBUG, "DBUS TDLS_DISCOVER " MACSTR, MAC2STR(peer));
2182 if (wpa_tdls_is_external_setup(wpa_s->wpa))
2183 ret = wpa_tdls_send_discovery_request(wpa_s->wpa, peer);
2185 ret = wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer);
2188 return wpas_dbus_error_unknown_error(
2189 message, "error performing TDLS discovery");
2197 * wpas_dbus_handler_tdls_setup - Setup TDLS session
2198 * @message: Pointer to incoming dbus message
2199 * @wpa_s: wpa_supplicant structure for a network interface
2200 * Returns: NULL indicating success or DBus error message on failure
2202 * Handler function for "TDLSSetup" method call of network interface.
2204 DBusMessage * wpas_dbus_handler_tdls_setup(DBusMessage *message,
2205 struct wpa_supplicant *wpa_s)
2208 DBusMessage *error_reply;
2211 if (get_peer_hwaddr_helper(message, __func__, peer, &error_reply) < 0)
2214 wpa_printf(MSG_DEBUG, "DBUS TDLS_SETUP " MACSTR, MAC2STR(peer));
2216 wpa_tdls_remove(wpa_s->wpa, peer);
2217 if (wpa_tdls_is_external_setup(wpa_s->wpa))
2218 ret = wpa_tdls_start(wpa_s->wpa, peer);
2220 ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
2223 return wpas_dbus_error_unknown_error(
2224 message, "error performing TDLS setup");
2232 * wpas_dbus_handler_tdls_status - Return TDLS session status
2233 * @message: Pointer to incoming dbus message
2234 * @wpa_s: wpa_supplicant structure for a network interface
2235 * Returns: A string representing the state of the link to this TDLS peer
2237 * Handler function for "TDLSStatus" method call of network interface.
2239 DBusMessage * wpas_dbus_handler_tdls_status(DBusMessage *message,
2240 struct wpa_supplicant *wpa_s)
2244 const char *tdls_status;
2246 if (get_peer_hwaddr_helper(message, __func__, peer, &reply) < 0)
2249 wpa_printf(MSG_DEBUG, "DBUS TDLS_STATUS " MACSTR, MAC2STR(peer));
2251 tdls_status = wpa_tdls_get_link_status(wpa_s->wpa, peer);
2253 reply = dbus_message_new_method_return(message);
2254 dbus_message_append_args(reply, DBUS_TYPE_STRING,
2255 &tdls_status, DBUS_TYPE_INVALID);
2261 * wpas_dbus_handler_tdls_teardown - Teardown TDLS session
2262 * @message: Pointer to incoming dbus message
2263 * @wpa_s: wpa_supplicant structure for a network interface
2264 * Returns: NULL indicating success or DBus error message on failure
2266 * Handler function for "TDLSTeardown" method call of network interface.
2268 DBusMessage * wpas_dbus_handler_tdls_teardown(DBusMessage *message,
2269 struct wpa_supplicant *wpa_s)
2272 DBusMessage *error_reply;
2275 if (get_peer_hwaddr_helper(message, __func__, peer, &error_reply) < 0)
2278 wpa_printf(MSG_DEBUG, "DBUS TDLS_TEARDOWN " MACSTR, MAC2STR(peer));
2280 if (wpa_tdls_is_external_setup(wpa_s->wpa))
2281 ret = wpa_tdls_teardown_link(
2283 WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
2285 ret = wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
2288 return wpas_dbus_error_unknown_error(
2289 message, "error performing TDLS teardown");
2295 #endif /* CONFIG_TDLS */
2299 * wpas_dbus_handler_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
2300 * @message: Pointer to incoming dbus message
2301 * @wpa_s: %wpa_supplicant data structure
2302 * Returns: A dbus message containing an error on failure or NULL on success
2304 * Sets the PKCS #11 engine and module path.
2306 DBusMessage * wpas_dbus_handler_set_pkcs11_engine_and_module_path(
2307 DBusMessage *message, struct wpa_supplicant *wpa_s)
2309 DBusMessageIter iter;
2311 char *pkcs11_engine_path = NULL;
2312 char *pkcs11_module_path = NULL;
2314 dbus_message_iter_init(message, &iter);
2315 dbus_message_iter_get_basic(&iter, &value);
2316 if (value == NULL) {
2317 return dbus_message_new_error(
2318 message, DBUS_ERROR_INVALID_ARGS,
2319 "Invalid pkcs11_engine_path argument");
2321 /* Empty path defaults to NULL */
2322 if (os_strlen(value))
2323 pkcs11_engine_path = value;
2325 dbus_message_iter_next(&iter);
2326 dbus_message_iter_get_basic(&iter, &value);
2327 if (value == NULL) {
2328 os_free(pkcs11_engine_path);
2329 return dbus_message_new_error(
2330 message, DBUS_ERROR_INVALID_ARGS,
2331 "Invalid pkcs11_module_path argument");
2333 /* Empty path defaults to NULL */
2334 if (os_strlen(value))
2335 pkcs11_module_path = value;
2337 if (wpas_set_pkcs11_engine_and_module_path(wpa_s, pkcs11_engine_path,
2338 pkcs11_module_path))
2339 return dbus_message_new_error(
2340 message, DBUS_ERROR_FAILED,
2341 "Reinit of the EAPOL state machine with the new PKCS "
2342 "#11 engine and module path failed.");
2344 wpa_dbus_mark_property_changed(
2345 wpa_s->global->dbus, wpa_s->dbus_new_path,
2346 WPAS_DBUS_NEW_IFACE_INTERFACE, "PKCS11EnginePath");
2347 wpa_dbus_mark_property_changed(
2348 wpa_s->global->dbus, wpa_s->dbus_new_path,
2349 WPAS_DBUS_NEW_IFACE_INTERFACE, "PKCS11ModulePath");
2356 * wpas_dbus_getter_capabilities - Return interface capabilities
2357 * @iter: Pointer to incoming dbus message iter
2358 * @error: Location to store error on failure
2359 * @user_data: Function specific data
2360 * Returns: TRUE on success, FALSE on failure
2362 * Getter for "Capabilities" property of an interface.
2364 dbus_bool_t wpas_dbus_getter_capabilities(DBusMessageIter *iter,
2365 DBusError *error, void *user_data)
2367 struct wpa_supplicant *wpa_s = user_data;
2368 struct wpa_driver_capa capa;
2370 DBusMessageIter iter_dict, iter_dict_entry, iter_dict_val, iter_array,
2372 const char *scans[] = { "active", "passive", "ssid" };
2374 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
2375 "a{sv}", &variant_iter))
2378 if (!wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
2381 res = wpa_drv_get_capa(wpa_s, &capa);
2383 /***** pairwise cipher */
2385 const char *args[] = {"ccmp", "tkip", "none"};
2386 if (!wpa_dbus_dict_append_string_array(
2387 &iter_dict, "Pairwise", args,
2391 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Pairwise",
2397 if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP_256) {
2398 if (!wpa_dbus_dict_string_array_add_element(
2399 &iter_array, "ccmp-256"))
2403 if (capa.enc & WPA_DRIVER_CAPA_ENC_GCMP_256) {
2404 if (!wpa_dbus_dict_string_array_add_element(
2405 &iter_array, "gcmp-256"))
2409 if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
2410 if (!wpa_dbus_dict_string_array_add_element(
2411 &iter_array, "ccmp"))
2415 if (capa.enc & WPA_DRIVER_CAPA_ENC_GCMP) {
2416 if (!wpa_dbus_dict_string_array_add_element(
2417 &iter_array, "gcmp"))
2421 if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
2422 if (!wpa_dbus_dict_string_array_add_element(
2423 &iter_array, "tkip"))
2427 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
2428 if (!wpa_dbus_dict_string_array_add_element(
2429 &iter_array, "none"))
2433 if (!wpa_dbus_dict_end_string_array(&iter_dict,
2440 /***** group cipher */
2442 const char *args[] = {
2443 "ccmp", "tkip", "wep104", "wep40"
2445 if (!wpa_dbus_dict_append_string_array(
2446 &iter_dict, "Group", args,
2450 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Group",
2456 if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP_256) {
2457 if (!wpa_dbus_dict_string_array_add_element(
2458 &iter_array, "ccmp-256"))
2462 if (capa.enc & WPA_DRIVER_CAPA_ENC_GCMP_256) {
2463 if (!wpa_dbus_dict_string_array_add_element(
2464 &iter_array, "gcmp-256"))
2468 if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
2469 if (!wpa_dbus_dict_string_array_add_element(
2470 &iter_array, "ccmp"))
2474 if (capa.enc & WPA_DRIVER_CAPA_ENC_GCMP) {
2475 if (!wpa_dbus_dict_string_array_add_element(
2476 &iter_array, "gcmp"))
2480 if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
2481 if (!wpa_dbus_dict_string_array_add_element(
2482 &iter_array, "tkip"))
2486 if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) {
2487 if (!wpa_dbus_dict_string_array_add_element(
2488 &iter_array, "wep104"))
2492 if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) {
2493 if (!wpa_dbus_dict_string_array_add_element(
2494 &iter_array, "wep40"))
2498 if (!wpa_dbus_dict_end_string_array(&iter_dict,
2505 /***** key management */
2507 const char *args[] = {
2508 "wpa-psk", "wpa-eap", "ieee8021x", "wpa-none",
2511 #endif /* CONFIG_WPS */
2514 if (!wpa_dbus_dict_append_string_array(
2515 &iter_dict, "KeyMgmt", args,
2519 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "KeyMgmt",
2525 if (!wpa_dbus_dict_string_array_add_element(&iter_array,
2529 if (!wpa_dbus_dict_string_array_add_element(&iter_array,
2533 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
2534 WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
2535 if (!wpa_dbus_dict_string_array_add_element(
2536 &iter_array, "wpa-eap"))
2539 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT)
2540 if (!wpa_dbus_dict_string_array_add_element(
2541 &iter_array, "wpa-ft-eap"))
2544 /* TODO: Ensure that driver actually supports sha256 encryption. */
2545 #ifdef CONFIG_IEEE80211W
2546 if (!wpa_dbus_dict_string_array_add_element(
2547 &iter_array, "wpa-eap-sha256"))
2549 #endif /* CONFIG_IEEE80211W */
2552 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
2553 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
2554 if (!wpa_dbus_dict_string_array_add_element(
2555 &iter_array, "wpa-psk"))
2558 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK)
2559 if (!wpa_dbus_dict_string_array_add_element(
2560 &iter_array, "wpa-ft-psk"))
2563 /* TODO: Ensure that driver actually supports sha256 encryption. */
2564 #ifdef CONFIG_IEEE80211W
2565 if (!wpa_dbus_dict_string_array_add_element(
2566 &iter_array, "wpa-psk-sha256"))
2568 #endif /* CONFIG_IEEE80211W */
2571 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
2572 if (!wpa_dbus_dict_string_array_add_element(
2573 &iter_array, "wpa-none"))
2579 if (!wpa_dbus_dict_string_array_add_element(&iter_array,
2582 #endif /* CONFIG_WPS */
2584 if (!wpa_dbus_dict_end_string_array(&iter_dict,
2591 /***** WPA protocol */
2593 const char *args[] = { "rsn", "wpa" };
2594 if (!wpa_dbus_dict_append_string_array(
2595 &iter_dict, "Protocol", args,
2599 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Protocol",
2605 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
2606 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
2607 if (!wpa_dbus_dict_string_array_add_element(
2608 &iter_array, "rsn"))
2612 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
2613 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
2614 if (!wpa_dbus_dict_string_array_add_element(
2615 &iter_array, "wpa"))
2619 if (!wpa_dbus_dict_end_string_array(&iter_dict,
2628 const char *args[] = { "open", "shared", "leap" };
2629 if (!wpa_dbus_dict_append_string_array(
2630 &iter_dict, "AuthAlg", args,
2634 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "AuthAlg",
2640 if (capa.auth & (WPA_DRIVER_AUTH_OPEN)) {
2641 if (!wpa_dbus_dict_string_array_add_element(
2642 &iter_array, "open"))
2646 if (capa.auth & (WPA_DRIVER_AUTH_SHARED)) {
2647 if (!wpa_dbus_dict_string_array_add_element(
2648 &iter_array, "shared"))
2652 if (capa.auth & (WPA_DRIVER_AUTH_LEAP)) {
2653 if (!wpa_dbus_dict_string_array_add_element(
2654 &iter_array, "leap"))
2658 if (!wpa_dbus_dict_end_string_array(&iter_dict,
2666 if (!wpa_dbus_dict_append_string_array(&iter_dict, "Scan", scans,
2671 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Modes",
2677 if (!wpa_dbus_dict_string_array_add_element(
2678 &iter_array, "infrastructure"))
2681 if (!wpa_dbus_dict_string_array_add_element(
2682 &iter_array, "ad-hoc"))
2686 if (capa.flags & (WPA_DRIVER_FLAGS_AP)) {
2687 if (!wpa_dbus_dict_string_array_add_element(
2692 if (capa.flags & (WPA_DRIVER_FLAGS_P2P_CAPABLE)) {
2693 if (!wpa_dbus_dict_string_array_add_element(
2694 &iter_array, "p2p"))
2699 if (!wpa_dbus_dict_end_string_array(&iter_dict,
2707 dbus_int32_t max_scan_ssid = capa.max_scan_ssids;
2709 if (!wpa_dbus_dict_append_int32(&iter_dict, "MaxScanSSID",
2714 if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict))
2716 if (!dbus_message_iter_close_container(iter, &variant_iter))
2722 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
2728 * wpas_dbus_getter_state - Get interface state
2729 * @iter: Pointer to incoming dbus message iter
2730 * @error: Location to store error on failure
2731 * @user_data: Function specific data
2732 * Returns: TRUE on success, FALSE on failure
2734 * Getter for "State" property.
2736 dbus_bool_t wpas_dbus_getter_state(DBusMessageIter *iter, DBusError *error,
2739 struct wpa_supplicant *wpa_s = user_data;
2740 const char *str_state;
2741 char *state_ls, *tmp;
2742 dbus_bool_t success = FALSE;
2744 str_state = wpa_supplicant_state_txt(wpa_s->wpa_state);
2746 /* make state string lowercase to fit new DBus API convention
2748 state_ls = tmp = os_strdup(str_state);
2750 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
2754 *tmp = tolower(*tmp);
2758 success = wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
2768 * wpas_dbus_new_iface_get_scanning - Get interface scanning state
2769 * @iter: Pointer to incoming dbus message iter
2770 * @error: Location to store error on failure
2771 * @user_data: Function specific data
2772 * Returns: TRUE on success, FALSE on failure
2774 * Getter for "scanning" property.
2776 dbus_bool_t wpas_dbus_getter_scanning(DBusMessageIter *iter, DBusError *error,
2779 struct wpa_supplicant *wpa_s = user_data;
2780 dbus_bool_t scanning = wpa_s->scanning ? TRUE : FALSE;
2782 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
2788 * wpas_dbus_getter_ap_scan - Control roaming mode
2789 * @iter: Pointer to incoming dbus message iter
2790 * @error: Location to store error on failure
2791 * @user_data: Function specific data
2792 * Returns: TRUE on success, FALSE on failure
2794 * Getter function for "ApScan" property.
2796 dbus_bool_t wpas_dbus_getter_ap_scan(DBusMessageIter *iter, DBusError *error,
2799 struct wpa_supplicant *wpa_s = user_data;
2800 dbus_uint32_t ap_scan = wpa_s->conf->ap_scan;
2802 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
2808 * wpas_dbus_setter_ap_scan - Control roaming mode
2809 * @iter: Pointer to incoming dbus message iter
2810 * @error: Location to store error on failure
2811 * @user_data: Function specific data
2812 * Returns: TRUE on success, FALSE on failure
2814 * Setter function for "ApScan" property.
2816 dbus_bool_t wpas_dbus_setter_ap_scan(DBusMessageIter *iter, DBusError *error,
2819 struct wpa_supplicant *wpa_s = user_data;
2820 dbus_uint32_t ap_scan;
2822 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
2826 if (wpa_supplicant_set_ap_scan(wpa_s, ap_scan)) {
2827 dbus_set_error_const(error, DBUS_ERROR_FAILED,
2828 "ap_scan must be 0, 1, or 2");
2836 * wpas_dbus_getter_fast_reauth - Control fast
2837 * reauthentication (TLS session resumption)
2838 * @iter: Pointer to incoming dbus message iter
2839 * @error: Location to store error on failure
2840 * @user_data: Function specific data
2841 * Returns: TRUE on success, FALSE on failure
2843 * Getter function for "FastReauth" property.
2845 dbus_bool_t wpas_dbus_getter_fast_reauth(DBusMessageIter *iter,
2849 struct wpa_supplicant *wpa_s = user_data;
2850 dbus_bool_t fast_reauth = wpa_s->conf->fast_reauth ? TRUE : FALSE;
2852 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
2853 &fast_reauth, error);
2858 * wpas_dbus_setter_fast_reauth - Control fast
2859 * reauthentication (TLS session resumption)
2860 * @iter: Pointer to incoming dbus message iter
2861 * @error: Location to store error on failure
2862 * @user_data: Function specific data
2863 * Returns: TRUE on success, FALSE on failure
2865 * Setter function for "FastReauth" property.
2867 dbus_bool_t wpas_dbus_setter_fast_reauth(DBusMessageIter *iter,
2871 struct wpa_supplicant *wpa_s = user_data;
2872 dbus_bool_t fast_reauth;
2874 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
2878 wpa_s->conf->fast_reauth = fast_reauth;
2884 * wpas_dbus_getter_disconnect_reason - Get most recent reason for disconnect
2885 * @iter: Pointer to incoming dbus message iter
2886 * @error: Location to store error on failure
2887 * @user_data: Function specific data
2888 * Returns: TRUE on success, FALSE on failure
2890 * Getter for "DisconnectReason" property. The reason is negative if it is
2891 * locally generated.
2893 dbus_bool_t wpas_dbus_getter_disconnect_reason(DBusMessageIter *iter,
2897 struct wpa_supplicant *wpa_s = user_data;
2898 dbus_int32_t reason = wpa_s->disconnect_reason;
2899 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
2905 * wpas_dbus_getter_bss_expire_age - Get BSS entry expiration age
2906 * @iter: Pointer to incoming dbus message iter
2907 * @error: Location to store error on failure
2908 * @user_data: Function specific data
2909 * Returns: TRUE on success, FALSE on failure
2911 * Getter function for "BSSExpireAge" property.
2913 dbus_bool_t wpas_dbus_getter_bss_expire_age(DBusMessageIter *iter,
2917 struct wpa_supplicant *wpa_s = user_data;
2918 dbus_uint32_t expire_age = wpa_s->conf->bss_expiration_age;
2920 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
2921 &expire_age, error);
2926 * wpas_dbus_setter_bss_expire_age - Control BSS entry expiration age
2927 * @iter: Pointer to incoming dbus message iter
2928 * @error: Location to store error on failure
2929 * @user_data: Function specific data
2930 * Returns: TRUE on success, FALSE on failure
2932 * Setter function for "BSSExpireAge" property.
2934 dbus_bool_t wpas_dbus_setter_bss_expire_age(DBusMessageIter *iter,
2938 struct wpa_supplicant *wpa_s = user_data;
2939 dbus_uint32_t expire_age;
2941 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
2945 if (wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age)) {
2946 dbus_set_error_const(error, DBUS_ERROR_FAILED,
2947 "BSSExpireAge must be >= 10");
2955 * wpas_dbus_getter_bss_expire_count - Get BSS entry expiration scan count
2956 * @iter: Pointer to incoming dbus message iter
2957 * @error: Location to store error on failure
2958 * @user_data: Function specific data
2959 * Returns: TRUE on success, FALSE on failure
2961 * Getter function for "BSSExpireCount" property.
2963 dbus_bool_t wpas_dbus_getter_bss_expire_count(DBusMessageIter *iter,
2967 struct wpa_supplicant *wpa_s = user_data;
2968 dbus_uint32_t expire_count = wpa_s->conf->bss_expiration_scan_count;
2970 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
2971 &expire_count, error);
2976 * wpas_dbus_setter_bss_expire_count - Control BSS entry expiration scan count
2977 * @iter: Pointer to incoming dbus message iter
2978 * @error: Location to store error on failure
2979 * @user_data: Function specific data
2980 * Returns: TRUE on success, FALSE on failure
2982 * Setter function for "BSSExpireCount" property.
2984 dbus_bool_t wpas_dbus_setter_bss_expire_count(DBusMessageIter *iter,
2988 struct wpa_supplicant *wpa_s = user_data;
2989 dbus_uint32_t expire_count;
2991 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
2995 if (wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count)) {
2996 dbus_set_error_const(error, DBUS_ERROR_FAILED,
2997 "BSSExpireCount must be > 0");
3005 * wpas_dbus_getter_country - Control country code
3006 * @iter: Pointer to incoming dbus message iter
3007 * @error: Location to store error on failure
3008 * @user_data: Function specific data
3009 * Returns: TRUE on success, FALSE on failure
3011 * Getter function for "Country" property.
3013 dbus_bool_t wpas_dbus_getter_country(DBusMessageIter *iter, DBusError *error,
3016 struct wpa_supplicant *wpa_s = user_data;
3018 char *str = country;
3020 country[0] = wpa_s->conf->country[0];
3021 country[1] = wpa_s->conf->country[1];
3024 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3030 * wpas_dbus_setter_country - Control country code
3031 * @iter: Pointer to incoming dbus message iter
3032 * @error: Location to store error on failure
3033 * @user_data: Function specific data
3034 * Returns: TRUE on success, FALSE on failure
3036 * Setter function for "Country" property.
3038 dbus_bool_t wpas_dbus_setter_country(DBusMessageIter *iter, DBusError *error,
3041 struct wpa_supplicant *wpa_s = user_data;
3042 const char *country;
3044 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
3048 if (!country[0] || !country[1]) {
3049 dbus_set_error_const(error, DBUS_ERROR_FAILED,
3050 "invalid country code");
3054 if (wpa_s->drv_priv != NULL && wpa_drv_set_country(wpa_s, country)) {
3055 wpa_printf(MSG_DEBUG, "Failed to set country");
3056 dbus_set_error_const(error, DBUS_ERROR_FAILED,
3057 "failed to set country code");
3061 wpa_s->conf->country[0] = country[0];
3062 wpa_s->conf->country[1] = country[1];
3068 * wpas_dbus_getter_scan_interval - Get scan interval
3069 * @iter: Pointer to incoming dbus message iter
3070 * @error: Location to store error on failure
3071 * @user_data: Function specific data
3072 * Returns: TRUE on success, FALSE on failure
3074 * Getter function for "ScanInterval" property.
3076 dbus_bool_t wpas_dbus_getter_scan_interval(DBusMessageIter *iter,
3080 struct wpa_supplicant *wpa_s = user_data;
3081 dbus_int32_t scan_interval = wpa_s->scan_interval;
3083 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
3084 &scan_interval, error);
3089 * wpas_dbus_setter_scan_interval - Control scan interval
3090 * @iter: Pointer to incoming dbus message iter
3091 * @error: Location to store error on failure
3092 * @user_data: Function specific data
3093 * Returns: TRUE on success, FALSE on failure
3095 * Setter function for "ScanInterval" property.
3097 dbus_bool_t wpas_dbus_setter_scan_interval(DBusMessageIter *iter,
3101 struct wpa_supplicant *wpa_s = user_data;
3102 dbus_int32_t scan_interval;
3104 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_INT32,
3108 if (wpa_supplicant_set_scan_interval(wpa_s, scan_interval)) {
3109 dbus_set_error_const(error, DBUS_ERROR_FAILED,
3110 "scan_interval must be >= 0");
3118 * wpas_dbus_getter_ifname - Get interface name
3119 * @iter: Pointer to incoming dbus message iter
3120 * @error: Location to store error on failure
3121 * @user_data: Function specific data
3122 * Returns: TRUE on success, FALSE on failure
3124 * Getter for "Ifname" property.
3126 dbus_bool_t wpas_dbus_getter_ifname(DBusMessageIter *iter, DBusError *error,
3129 struct wpa_supplicant *wpa_s = user_data;
3130 const char *ifname = wpa_s->ifname;
3132 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3138 * wpas_dbus_getter_driver - Get interface name
3139 * @iter: Pointer to incoming dbus message iter
3140 * @error: Location to store error on failure
3141 * @user_data: Function specific data
3142 * Returns: TRUE on success, FALSE on failure
3144 * Getter for "Driver" property.
3146 dbus_bool_t wpas_dbus_getter_driver(DBusMessageIter *iter, DBusError *error,
3149 struct wpa_supplicant *wpa_s = user_data;
3152 if (wpa_s->driver == NULL || wpa_s->driver->name == NULL) {
3153 wpa_printf(MSG_DEBUG, "wpas_dbus_getter_driver[dbus]: "
3154 "wpa_s has no driver set");
3155 dbus_set_error(error, DBUS_ERROR_FAILED, "%s: no driver set",
3160 driver = wpa_s->driver->name;
3161 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3167 * wpas_dbus_getter_current_bss - Get current bss object path
3168 * @iter: Pointer to incoming dbus message iter
3169 * @error: Location to store error on failure
3170 * @user_data: Function specific data
3171 * Returns: TRUE on success, FALSE on failure
3173 * Getter for "CurrentBSS" property.
3175 dbus_bool_t wpas_dbus_getter_current_bss(DBusMessageIter *iter,
3179 struct wpa_supplicant *wpa_s = user_data;
3180 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *bss_obj_path = path_buf;
3182 if (wpa_s->current_bss)
3183 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3184 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
3185 wpa_s->dbus_new_path, wpa_s->current_bss->id);
3187 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
3189 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
3190 &bss_obj_path, error);
3195 * wpas_dbus_getter_current_network - Get current network object path
3196 * @iter: Pointer to incoming dbus message iter
3197 * @error: Location to store error on failure
3198 * @user_data: Function specific data
3199 * Returns: TRUE on success, FALSE on failure
3201 * Getter for "CurrentNetwork" property.
3203 dbus_bool_t wpas_dbus_getter_current_network(DBusMessageIter *iter,
3207 struct wpa_supplicant *wpa_s = user_data;
3208 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *net_obj_path = path_buf;
3210 if (wpa_s->current_ssid)
3211 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3212 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
3213 wpa_s->dbus_new_path, wpa_s->current_ssid->id);
3215 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
3217 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
3218 &net_obj_path, error);
3223 * wpas_dbus_getter_current_auth_mode - Get current authentication type
3224 * @iter: Pointer to incoming dbus message iter
3225 * @error: Location to store error on failure
3226 * @user_data: Function specific data
3227 * Returns: TRUE on success, FALSE on failure
3229 * Getter for "CurrentAuthMode" property.
3231 dbus_bool_t wpas_dbus_getter_current_auth_mode(DBusMessageIter *iter,
3235 struct wpa_supplicant *wpa_s = user_data;
3236 const char *eap_mode;
3237 const char *auth_mode;
3238 char eap_mode_buf[WPAS_DBUS_AUTH_MODE_MAX];
3240 if (wpa_s->wpa_state != WPA_COMPLETED) {
3241 auth_mode = "INACTIVE";
3242 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X ||
3243 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3244 eap_mode = wpa_supplicant_get_eap_mode(wpa_s);
3245 os_snprintf(eap_mode_buf, WPAS_DBUS_AUTH_MODE_MAX,
3246 "EAP-%s", eap_mode);
3247 auth_mode = eap_mode_buf;
3250 auth_mode = wpa_key_mgmt_txt(wpa_s->key_mgmt,
3251 wpa_s->current_ssid->proto);
3254 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3260 * wpas_dbus_getter_bridge_ifname - Get interface name
3261 * @iter: Pointer to incoming dbus message iter
3262 * @error: Location to store error on failure
3263 * @user_data: Function specific data
3264 * Returns: TRUE on success, FALSE on failure
3266 * Getter for "BridgeIfname" property.
3268 dbus_bool_t wpas_dbus_getter_bridge_ifname(DBusMessageIter *iter,
3272 struct wpa_supplicant *wpa_s = user_data;
3273 const char *bridge_ifname = wpa_s->bridge_ifname;
3274 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3275 &bridge_ifname, error);
3280 * wpas_dbus_getter_bsss - Get array of BSSs objects
3281 * @iter: Pointer to incoming dbus message iter
3282 * @error: Location to store error on failure
3283 * @user_data: Function specific data
3284 * Returns: TRUE on success, FALSE on failure
3286 * Getter for "BSSs" property.
3288 dbus_bool_t wpas_dbus_getter_bsss(DBusMessageIter *iter, DBusError *error,
3291 struct wpa_supplicant *wpa_s = user_data;
3292 struct wpa_bss *bss;
3295 dbus_bool_t success = FALSE;
3297 paths = os_calloc(wpa_s->num_bss, sizeof(char *));
3299 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3303 /* Loop through scan results and append each result's object path */
3304 dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
3305 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
3306 if (paths[i] == NULL) {
3307 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
3311 /* Construct the object path for this BSS. */
3312 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
3313 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
3314 wpa_s->dbus_new_path, bss->id);
3317 success = wpas_dbus_simple_array_property_getter(iter,
3318 DBUS_TYPE_OBJECT_PATH,
3319 paths, wpa_s->num_bss,
3324 os_free(paths[--i]);
3331 * wpas_dbus_getter_networks - Get array of networks objects
3332 * @iter: Pointer to incoming dbus message iter
3333 * @error: Location to store error on failure
3334 * @user_data: Function specific data
3335 * Returns: TRUE on success, FALSE on failure
3337 * Getter for "Networks" property.
3339 dbus_bool_t wpas_dbus_getter_networks(DBusMessageIter *iter, DBusError *error,
3342 struct wpa_supplicant *wpa_s = user_data;
3343 struct wpa_ssid *ssid;
3345 unsigned int i = 0, num = 0;
3346 dbus_bool_t success = FALSE;
3348 if (wpa_s->conf == NULL) {
3349 wpa_printf(MSG_ERROR, "%s[dbus]: An error occurred getting "
3350 "networks list.", __func__);
3351 dbus_set_error(error, DBUS_ERROR_FAILED, "%s: an error "
3352 "occurred getting the networks list", __func__);
3356 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
3357 if (!network_is_persistent_group(ssid))
3360 paths = os_calloc(num, sizeof(char *));
3362 dbus_set_error(error, DBUS_ERROR_NO_MEMORY, "no memory");
3366 /* Loop through configured networks and append object path of each */
3367 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
3368 if (network_is_persistent_group(ssid))
3370 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
3371 if (paths[i] == NULL) {
3372 dbus_set_error(error, DBUS_ERROR_NO_MEMORY, "no memory");
3376 /* Construct the object path for this network. */
3377 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
3378 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
3379 wpa_s->dbus_new_path, ssid->id);
3382 success = wpas_dbus_simple_array_property_getter(iter,
3383 DBUS_TYPE_OBJECT_PATH,
3388 os_free(paths[--i]);
3395 * wpas_dbus_getter_pkcs11_engine_path - Get PKCS #11 engine path
3396 * @iter: Pointer to incoming dbus message iter
3397 * @error: Location to store error on failure
3398 * @user_data: Function specific data
3399 * Returns: A dbus message containing the PKCS #11 engine path
3401 * Getter for "PKCS11EnginePath" property.
3403 dbus_bool_t wpas_dbus_getter_pkcs11_engine_path(DBusMessageIter *iter,
3407 struct wpa_supplicant *wpa_s = user_data;
3408 const char *pkcs11_engine_path;
3410 if (wpa_s->conf == NULL) {
3411 wpa_printf(MSG_ERROR,
3412 "wpas_dbus_getter_pkcs11_engine_path[dbus]: An "
3413 "error occurred getting the PKCS #11 engine path.");
3414 dbus_set_error_const(
3415 error, DBUS_ERROR_FAILED,
3416 "An error occured getting the PKCS #11 engine path.");
3420 if (wpa_s->conf->pkcs11_engine_path == NULL)
3421 pkcs11_engine_path = "";
3423 pkcs11_engine_path = wpa_s->conf->pkcs11_engine_path;
3424 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3425 &pkcs11_engine_path, error);
3430 * wpas_dbus_getter_pkcs11_module_path - Get PKCS #11 module path
3431 * @iter: Pointer to incoming dbus message iter
3432 * @error: Location to store error on failure
3433 * @user_data: Function specific data
3434 * Returns: A dbus message containing the PKCS #11 module path
3436 * Getter for "PKCS11ModulePath" property.
3438 dbus_bool_t wpas_dbus_getter_pkcs11_module_path(DBusMessageIter *iter,
3442 struct wpa_supplicant *wpa_s = user_data;
3443 const char *pkcs11_module_path;
3445 if (wpa_s->conf == NULL) {
3446 wpa_printf(MSG_ERROR,
3447 "wpas_dbus_getter_pkcs11_module_path[dbus]: An "
3448 "error occurred getting the PKCS #11 module path.");
3449 dbus_set_error_const(
3450 error, DBUS_ERROR_FAILED,
3451 "An error occured getting the PKCS #11 module path.");
3455 if (wpa_s->conf->pkcs11_module_path == NULL)
3456 pkcs11_module_path = "";
3458 pkcs11_module_path = wpa_s->conf->pkcs11_module_path;
3459 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3460 &pkcs11_module_path, error);
3465 * wpas_dbus_getter_blobs - Get all blobs defined for this interface
3466 * @iter: Pointer to incoming dbus message iter
3467 * @error: Location to store error on failure
3468 * @user_data: Function specific data
3469 * Returns: TRUE on success, FALSE on failure
3471 * Getter for "Blobs" property.
3473 dbus_bool_t wpas_dbus_getter_blobs(DBusMessageIter *iter, DBusError *error,
3476 struct wpa_supplicant *wpa_s = user_data;
3477 DBusMessageIter variant_iter, dict_iter, entry_iter, array_iter;
3478 struct wpa_config_blob *blob;
3480 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
3481 "a{say}", &variant_iter) ||
3482 !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
3483 "{say}", &dict_iter)) {
3484 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3488 blob = wpa_s->conf->blobs;
3490 if (!dbus_message_iter_open_container(&dict_iter,
3491 DBUS_TYPE_DICT_ENTRY,
3492 NULL, &entry_iter) ||
3493 !dbus_message_iter_append_basic(&entry_iter,
3496 !dbus_message_iter_open_container(&entry_iter,
3498 DBUS_TYPE_BYTE_AS_STRING,
3500 !dbus_message_iter_append_fixed_array(&array_iter,
3504 !dbus_message_iter_close_container(&entry_iter,
3506 !dbus_message_iter_close_container(&dict_iter,
3508 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
3516 if (!dbus_message_iter_close_container(&variant_iter, &dict_iter) ||
3517 !dbus_message_iter_close_container(iter, &variant_iter)) {
3518 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3526 static struct wpa_bss * get_bss_helper(struct bss_handler_args *args,
3527 DBusError *error, const char *func_name)
3529 struct wpa_bss *res = wpa_bss_get_id(args->wpa_s, args->id);
3532 wpa_printf(MSG_ERROR, "%s[dbus]: no bss with id %d found",
3533 func_name, args->id);
3534 dbus_set_error(error, DBUS_ERROR_FAILED,
3535 "%s: BSS %d not found",
3536 func_name, args->id);
3544 * wpas_dbus_getter_bss_bssid - Return the BSSID of a BSS
3545 * @iter: Pointer to incoming dbus message iter
3546 * @error: Location to store error on failure
3547 * @user_data: Function specific data
3548 * Returns: TRUE on success, FALSE on failure
3550 * Getter for "BSSID" property.
3552 dbus_bool_t wpas_dbus_getter_bss_bssid(DBusMessageIter *iter, DBusError *error,
3555 struct bss_handler_args *args = user_data;
3556 struct wpa_bss *res;
3558 res = get_bss_helper(args, error, __func__);
3562 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
3563 res->bssid, ETH_ALEN,
3569 * wpas_dbus_getter_bss_ssid - Return the SSID of a BSS
3570 * @iter: Pointer to incoming dbus message iter
3571 * @error: Location to store error on failure
3572 * @user_data: Function specific data
3573 * Returns: TRUE on success, FALSE on failure
3575 * Getter for "SSID" property.
3577 dbus_bool_t wpas_dbus_getter_bss_ssid(DBusMessageIter *iter, DBusError *error,
3580 struct bss_handler_args *args = user_data;
3581 struct wpa_bss *res;
3583 res = get_bss_helper(args, error, __func__);
3587 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
3588 res->ssid, res->ssid_len,
3594 * wpas_dbus_getter_bss_privacy - Return the privacy flag of a BSS
3595 * @iter: Pointer to incoming dbus message iter
3596 * @error: Location to store error on failure
3597 * @user_data: Function specific data
3598 * Returns: TRUE on success, FALSE on failure
3600 * Getter for "Privacy" property.
3602 dbus_bool_t wpas_dbus_getter_bss_privacy(DBusMessageIter *iter,
3603 DBusError *error, void *user_data)
3605 struct bss_handler_args *args = user_data;
3606 struct wpa_bss *res;
3607 dbus_bool_t privacy;
3609 res = get_bss_helper(args, error, __func__);
3613 privacy = (res->caps & IEEE80211_CAP_PRIVACY) ? TRUE : FALSE;
3614 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
3620 * wpas_dbus_getter_bss_mode - Return the mode of a BSS
3621 * @iter: Pointer to incoming dbus message iter
3622 * @error: Location to store error on failure
3623 * @user_data: Function specific data
3624 * Returns: TRUE on success, FALSE on failure
3626 * Getter for "Mode" property.
3628 dbus_bool_t wpas_dbus_getter_bss_mode(DBusMessageIter *iter, DBusError *error,
3631 struct bss_handler_args *args = user_data;
3632 struct wpa_bss *res;
3635 res = get_bss_helper(args, error, __func__);
3638 if (bss_is_dmg(res)) {
3639 switch (res->caps & IEEE80211_CAP_DMG_MASK) {
3640 case IEEE80211_CAP_DMG_PBSS:
3641 case IEEE80211_CAP_DMG_IBSS:
3644 case IEEE80211_CAP_DMG_AP:
3645 mode = "infrastructure";
3649 if (res->caps & IEEE80211_CAP_IBSS)
3652 mode = "infrastructure";
3655 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3661 * wpas_dbus_getter_bss_level - Return the signal strength of a BSS
3662 * @iter: Pointer to incoming dbus message iter
3663 * @error: Location to store error on failure
3664 * @user_data: Function specific data
3665 * Returns: TRUE on success, FALSE on failure
3667 * Getter for "Level" property.
3669 dbus_bool_t wpas_dbus_getter_bss_signal(DBusMessageIter *iter,
3670 DBusError *error, void *user_data)
3672 struct bss_handler_args *args = user_data;
3673 struct wpa_bss *res;
3676 res = get_bss_helper(args, error, __func__);
3680 level = (s16) res->level;
3681 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT16,
3687 * wpas_dbus_getter_bss_frequency - Return the frequency of a BSS
3688 * @iter: Pointer to incoming dbus message iter
3689 * @error: Location to store error on failure
3690 * @user_data: Function specific data
3691 * Returns: TRUE on success, FALSE on failure
3693 * Getter for "Frequency" property.
3695 dbus_bool_t wpas_dbus_getter_bss_frequency(DBusMessageIter *iter,
3696 DBusError *error, void *user_data)
3698 struct bss_handler_args *args = user_data;
3699 struct wpa_bss *res;
3702 res = get_bss_helper(args, error, __func__);
3706 freq = (u16) res->freq;
3707 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
3712 static int cmp_u8s_desc(const void *a, const void *b)
3714 return (*(u8 *) b - *(u8 *) a);
3719 * wpas_dbus_getter_bss_rates - Return available bit rates of a BSS
3720 * @iter: Pointer to incoming dbus message iter
3721 * @error: Location to store error on failure
3722 * @user_data: Function specific data
3723 * Returns: TRUE on success, FALSE on failure
3725 * Getter for "Rates" property.
3727 dbus_bool_t wpas_dbus_getter_bss_rates(DBusMessageIter *iter,
3728 DBusError *error, void *user_data)
3730 struct bss_handler_args *args = user_data;
3731 struct wpa_bss *res;
3732 u8 *ie_rates = NULL;
3735 dbus_bool_t success = FALSE;
3737 res = get_bss_helper(args, error, __func__);
3741 rates_num = wpa_bss_get_bit_rates(res, &ie_rates);
3745 qsort(ie_rates, rates_num, 1, cmp_u8s_desc);
3747 real_rates = os_malloc(sizeof(u32) * rates_num);
3750 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3754 for (i = 0; i < rates_num; i++)
3755 real_rates[i] = ie_rates[i] * 500000;
3757 success = wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_UINT32,
3758 real_rates, rates_num,
3762 os_free(real_rates);
3767 static dbus_bool_t wpas_dbus_get_bss_security_prop(DBusMessageIter *iter,
3768 struct wpa_ie_data *ie_data,
3771 DBusMessageIter iter_dict, variant_iter;
3773 const char *pairwise[5]; /* max 5 pairwise ciphers is supported */
3774 const char *key_mgmt[8]; /* max 8 key managements may be supported */
3777 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
3778 "a{sv}", &variant_iter))
3781 if (!wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
3786 if (ie_data->key_mgmt & WPA_KEY_MGMT_PSK)
3787 key_mgmt[n++] = "wpa-psk";
3788 if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_PSK)
3789 key_mgmt[n++] = "wpa-ft-psk";
3790 if (ie_data->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
3791 key_mgmt[n++] = "wpa-psk-sha256";
3792 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X)
3793 key_mgmt[n++] = "wpa-eap";
3794 if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X)
3795 key_mgmt[n++] = "wpa-ft-eap";
3796 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256)
3797 key_mgmt[n++] = "wpa-eap-sha256";
3798 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B)
3799 key_mgmt[n++] = "wpa-eap-suite-b";
3800 if (ie_data->key_mgmt & WPA_KEY_MGMT_NONE)
3801 key_mgmt[n++] = "wpa-none";
3803 if (!wpa_dbus_dict_append_string_array(&iter_dict, "KeyMgmt",
3808 switch (ie_data->group_cipher) {
3809 case WPA_CIPHER_WEP40:
3812 case WPA_CIPHER_TKIP:
3815 case WPA_CIPHER_CCMP:
3818 case WPA_CIPHER_GCMP:
3821 case WPA_CIPHER_WEP104:
3824 case WPA_CIPHER_CCMP_256:
3827 case WPA_CIPHER_GCMP_256:
3835 if (!wpa_dbus_dict_append_string(&iter_dict, "Group", group))
3840 if (ie_data->pairwise_cipher & WPA_CIPHER_TKIP)
3841 pairwise[n++] = "tkip";
3842 if (ie_data->pairwise_cipher & WPA_CIPHER_CCMP)
3843 pairwise[n++] = "ccmp";
3844 if (ie_data->pairwise_cipher & WPA_CIPHER_GCMP)
3845 pairwise[n++] = "gcmp";
3846 if (ie_data->pairwise_cipher & WPA_CIPHER_CCMP_256)
3847 pairwise[n++] = "ccmp-256";
3848 if (ie_data->pairwise_cipher & WPA_CIPHER_GCMP_256)
3849 pairwise[n++] = "gcmp-256";
3851 if (!wpa_dbus_dict_append_string_array(&iter_dict, "Pairwise",
3855 /* Management group (RSN only) */
3856 if (ie_data->proto == WPA_PROTO_RSN) {
3857 switch (ie_data->mgmt_group_cipher) {
3858 #ifdef CONFIG_IEEE80211W
3859 case WPA_CIPHER_AES_128_CMAC:
3860 group = "aes128cmac";
3862 #endif /* CONFIG_IEEE80211W */
3868 if (!wpa_dbus_dict_append_string(&iter_dict, "MgmtGroup",
3873 if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict))
3875 if (!dbus_message_iter_close_container(iter, &variant_iter))
3881 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3887 * wpas_dbus_getter_bss_wpa - Return the WPA options of a BSS
3888 * @iter: Pointer to incoming dbus message iter
3889 * @error: Location to store error on failure
3890 * @user_data: Function specific data
3891 * Returns: TRUE on success, FALSE on failure
3893 * Getter for "WPA" property.
3895 dbus_bool_t wpas_dbus_getter_bss_wpa(DBusMessageIter *iter, DBusError *error,
3898 struct bss_handler_args *args = user_data;
3899 struct wpa_bss *res;
3900 struct wpa_ie_data wpa_data;
3903 res = get_bss_helper(args, error, __func__);
3907 os_memset(&wpa_data, 0, sizeof(wpa_data));
3908 ie = wpa_bss_get_vendor_ie(res, WPA_IE_VENDOR_TYPE);
3910 if (wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0) {
3911 dbus_set_error_const(error, DBUS_ERROR_FAILED,
3912 "failed to parse WPA IE");
3917 return wpas_dbus_get_bss_security_prop(iter, &wpa_data, error);
3922 * wpas_dbus_getter_bss_rsn - Return the RSN options of a BSS
3923 * @iter: Pointer to incoming dbus message iter
3924 * @error: Location to store error on failure
3925 * @user_data: Function specific data
3926 * Returns: TRUE on success, FALSE on failure
3928 * Getter for "RSN" property.
3930 dbus_bool_t wpas_dbus_getter_bss_rsn(DBusMessageIter *iter, DBusError *error,
3933 struct bss_handler_args *args = user_data;
3934 struct wpa_bss *res;
3935 struct wpa_ie_data wpa_data;
3938 res = get_bss_helper(args, error, __func__);
3942 os_memset(&wpa_data, 0, sizeof(wpa_data));
3943 ie = wpa_bss_get_ie(res, WLAN_EID_RSN);
3945 if (wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0) {
3946 dbus_set_error_const(error, DBUS_ERROR_FAILED,
3947 "failed to parse RSN IE");
3952 return wpas_dbus_get_bss_security_prop(iter, &wpa_data, error);
3957 * wpas_dbus_getter_bss_wps - Return the WPS options of a BSS
3958 * @iter: Pointer to incoming dbus message iter
3959 * @error: Location to store error on failure
3960 * @user_data: Function specific data
3961 * Returns: TRUE on success, FALSE on failure
3963 * Getter for "WPS" property.
3965 dbus_bool_t wpas_dbus_getter_bss_wps(DBusMessageIter *iter, DBusError *error,
3968 struct bss_handler_args *args = user_data;
3969 struct wpa_bss *res;
3971 struct wpabuf *wps_ie;
3972 #endif /* CONFIG_WPS */
3973 DBusMessageIter iter_dict, variant_iter;
3974 const char *type = "";
3976 res = get_bss_helper(args, error, __func__);
3980 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
3981 "a{sv}", &variant_iter))
3984 if (!wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
3988 wps_ie = wpa_bss_get_vendor_ie_multi(res, WPS_IE_VENDOR_TYPE);
3990 if (wps_is_selected_pbc_registrar(wps_ie))
3992 else if (wps_is_selected_pin_registrar(wps_ie))
3995 wpabuf_free(wps_ie);
3997 #endif /* CONFIG_WPS */
3999 if (!wpa_dbus_dict_append_string(&iter_dict, "Type", type))
4002 if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict))
4004 if (!dbus_message_iter_close_container(iter, &variant_iter))
4010 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
4016 * wpas_dbus_getter_bss_ies - Return all IEs of a BSS
4017 * @iter: Pointer to incoming dbus message iter
4018 * @error: Location to store error on failure
4019 * @user_data: Function specific data
4020 * Returns: TRUE on success, FALSE on failure
4022 * Getter for "IEs" property.
4024 dbus_bool_t wpas_dbus_getter_bss_ies(DBusMessageIter *iter, DBusError *error,
4027 struct bss_handler_args *args = user_data;
4028 struct wpa_bss *res;
4030 res = get_bss_helper(args, error, __func__);
4034 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
4035 res + 1, res->ie_len,
4041 * wpas_dbus_getter_bss_age - Return time in seconds since BSS was last seen
4042 * @iter: Pointer to incoming dbus message iter
4043 * @error: Location to store error on failure
4044 * @user_data: Function specific data
4045 * Returns: TRUE on success, FALSE on failure
4047 * Getter for BSS age
4049 dbus_bool_t wpas_dbus_getter_bss_age(DBusMessageIter *iter, DBusError *error,
4052 struct bss_handler_args *args = user_data;
4053 struct wpa_bss *res;
4054 struct os_reltime now, diff = { 0, 0 };
4057 res = get_bss_helper(args, error, __func__);
4061 os_get_reltime(&now);
4062 os_reltime_sub(&now, &res->last_update, &diff);
4063 age = diff.sec > 0 ? diff.sec : 0;
4064 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32, &age,
4070 * wpas_dbus_getter_enabled - Check whether network is enabled or disabled
4071 * @iter: Pointer to incoming dbus message iter
4072 * @error: Location to store error on failure
4073 * @user_data: Function specific data
4074 * Returns: TRUE on success, FALSE on failure
4076 * Getter for "enabled" property of a configured network.
4078 dbus_bool_t wpas_dbus_getter_enabled(DBusMessageIter *iter, DBusError *error,
4081 struct network_handler_args *net = user_data;
4082 dbus_bool_t enabled = net->ssid->disabled ? FALSE : TRUE;
4084 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
4090 * wpas_dbus_setter_enabled - Mark a configured network as enabled or disabled
4091 * @iter: Pointer to incoming dbus message iter
4092 * @error: Location to store error on failure
4093 * @user_data: Function specific data
4094 * Returns: TRUE on success, FALSE on failure
4096 * Setter for "Enabled" property of a configured network.
4098 dbus_bool_t wpas_dbus_setter_enabled(DBusMessageIter *iter, DBusError *error,
4101 struct network_handler_args *net = user_data;
4102 struct wpa_supplicant *wpa_s;
4103 struct wpa_ssid *ssid;
4106 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
4114 wpa_supplicant_enable_network(wpa_s, ssid);
4116 wpa_supplicant_disable_network(wpa_s, ssid);
4123 * wpas_dbus_getter_network_properties - Get options for a configured network
4124 * @iter: Pointer to incoming dbus message iter
4125 * @error: Location to store error on failure
4126 * @user_data: Function specific data
4127 * Returns: TRUE on success, FALSE on failure
4129 * Getter for "Properties" property of a configured network.
4131 dbus_bool_t wpas_dbus_getter_network_properties(DBusMessageIter *iter,
4135 struct network_handler_args *net = user_data;
4136 DBusMessageIter variant_iter, dict_iter;
4138 char **props = wpa_config_get_all(net->ssid, 1);
4139 dbus_bool_t success = FALSE;
4142 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
4146 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a{sv}",
4148 !wpa_dbus_dict_open_write(&variant_iter, &dict_iter)) {
4149 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
4155 if (!wpa_dbus_dict_append_string(&dict_iter, *iterator,
4157 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
4165 if (!wpa_dbus_dict_close_write(&variant_iter, &dict_iter) ||
4166 !dbus_message_iter_close_container(iter, &variant_iter)) {
4167 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
4185 * wpas_dbus_setter_network_properties - Set options for a configured network
4186 * @iter: Pointer to incoming dbus message iter
4187 * @error: Location to store error on failure
4188 * @user_data: Function specific data
4189 * Returns: TRUE on success, FALSE on failure
4191 * Setter for "Properties" property of a configured network.
4193 dbus_bool_t wpas_dbus_setter_network_properties(DBusMessageIter *iter,
4197 struct network_handler_args *net = user_data;
4198 struct wpa_ssid *ssid = net->ssid;
4199 DBusMessageIter variant_iter;
4201 dbus_message_iter_recurse(iter, &variant_iter);
4202 return set_network_properties(net->wpa_s, ssid, &variant_iter, error);
4208 DBusMessage * wpas_dbus_handler_subscribe_preq(
4209 DBusMessage *message, struct wpa_supplicant *wpa_s)
4211 struct wpas_dbus_priv *priv = wpa_s->global->dbus;
4214 if (wpa_s->preq_notify_peer != NULL) {
4215 if (os_strcmp(dbus_message_get_sender(message),
4216 wpa_s->preq_notify_peer) == 0)
4219 return dbus_message_new_error(message,
4220 WPAS_DBUS_ERROR_SUBSCRIPTION_IN_USE,
4221 "Another application is already subscribed");
4224 name = os_strdup(dbus_message_get_sender(message));
4226 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
4229 wpa_s->preq_notify_peer = name;
4231 /* Subscribe to clean up if application closes socket */
4232 wpas_dbus_subscribe_noc(priv);
4235 * Double-check it's still alive to make sure that we didn't
4236 * miss the NameOwnerChanged signal, e.g. while strdup'ing.
4238 if (!dbus_bus_name_has_owner(priv->con, name, NULL)) {
4240 * Application no longer exists, clean up.
4241 * The return value is irrelevant now.
4243 * Need to check if the NameOwnerChanged handling
4244 * already cleaned up because we have processed
4245 * DBus messages while checking if the name still
4248 if (!wpa_s->preq_notify_peer)
4250 os_free(wpa_s->preq_notify_peer);
4251 wpa_s->preq_notify_peer = NULL;
4252 wpas_dbus_unsubscribe_noc(priv);
4259 DBusMessage * wpas_dbus_handler_unsubscribe_preq(
4260 DBusMessage *message, struct wpa_supplicant *wpa_s)
4262 struct wpas_dbus_priv *priv = wpa_s->global->dbus;
4264 if (!wpa_s->preq_notify_peer)
4265 return dbus_message_new_error(message,
4266 WPAS_DBUS_ERROR_NO_SUBSCRIPTION,
4269 if (os_strcmp(wpa_s->preq_notify_peer,
4270 dbus_message_get_sender(message)))
4271 return dbus_message_new_error(message,
4272 WPAS_DBUS_ERROR_SUBSCRIPTION_EPERM,
4273 "Can't unsubscribe others");
4275 os_free(wpa_s->preq_notify_peer);
4276 wpa_s->preq_notify_peer = NULL;
4277 wpas_dbus_unsubscribe_noc(priv);
4282 void wpas_dbus_signal_preq(struct wpa_supplicant *wpa_s,
4283 const u8 *addr, const u8 *dst, const u8 *bssid,
4284 const u8 *ie, size_t ie_len, u32 ssi_signal)
4287 DBusMessageIter iter, dict_iter;
4288 struct wpas_dbus_priv *priv = wpa_s->global->dbus;
4290 /* Do nothing if the control interface is not turned on */
4294 if (wpa_s->preq_notify_peer == NULL)
4297 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
4298 WPAS_DBUS_NEW_IFACE_INTERFACE,
4303 dbus_message_set_destination(msg, wpa_s->preq_notify_peer);
4305 dbus_message_iter_init_append(msg, &iter);
4307 if (!wpa_dbus_dict_open_write(&iter, &dict_iter))
4309 if (addr && !wpa_dbus_dict_append_byte_array(&dict_iter, "addr",
4310 (const char *) addr,
4313 if (dst && !wpa_dbus_dict_append_byte_array(&dict_iter, "dst",
4317 if (bssid && !wpa_dbus_dict_append_byte_array(&dict_iter, "bssid",
4318 (const char *) bssid,
4321 if (ie && ie_len && !wpa_dbus_dict_append_byte_array(&dict_iter, "ies",
4325 if (ssi_signal && !wpa_dbus_dict_append_int32(&dict_iter, "signal",
4328 if (!wpa_dbus_dict_close_write(&iter, &dict_iter))
4331 dbus_connection_send(priv->con, msg, NULL);
4334 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
4336 dbus_message_unref(msg);
4339 #endif /* CONFIG_AP */