2 * WPA Supplicant / dbus-based control interface
3 * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
4 * Copyright (c) 2009-2010, Witold Sowa <witold.sowa@gmail.com>
5 * Copyright (c) 2009-2015, Jouni Malinen <j@w1.fi>
7 * This software may be distributed under the terms of the BSD license.
8 * See README for more details.
14 #include "common/ieee802_11_defs.h"
15 #include "eap_peer/eap_methods.h"
16 #include "eapol_supp/eapol_supp_sm.h"
17 #include "rsn_supp/wpa.h"
18 #include "../config.h"
19 #include "../wpa_supplicant_i.h"
20 #include "../driver_i.h"
21 #include "../notify.h"
24 #include "../autoscan.h"
25 #include "dbus_new_helpers.h"
27 #include "dbus_new_handlers.h"
28 #include "dbus_dict_helpers.h"
29 #include "dbus_common_i.h"
30 #include "drivers/driver.h"
32 static const char * const debug_strings[] = {
33 "excessive", "msgdump", "debug", "info", "warning", "error", NULL
38 * wpas_dbus_error_unknown_error - Return a new UnknownError 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,
48 return dbus_message_new_error(message, WPAS_DBUS_ERROR_UNKNOWN_ERROR,
54 * wpas_dbus_error_iface_unknown - Return a new invalid interface error message
55 * @message: Pointer to incoming dbus message this error refers to
56 * Returns: A dbus error message
58 * Convenience function to create and return an invalid interface error
60 static DBusMessage * wpas_dbus_error_iface_unknown(DBusMessage *message)
62 return dbus_message_new_error(
63 message, WPAS_DBUS_ERROR_IFACE_UNKNOWN,
64 "wpa_supplicant knows nothing about this interface.");
69 * wpas_dbus_error_network_unknown - Return a new NetworkUnknown error message
70 * @message: Pointer to incoming dbus message this error refers to
71 * Returns: a dbus error message
73 * Convenience function to create and return an invalid network error
75 static DBusMessage * wpas_dbus_error_network_unknown(DBusMessage *message)
77 return dbus_message_new_error(
78 message, WPAS_DBUS_ERROR_NETWORK_UNKNOWN,
79 "There is no such a network in this interface.");
84 * wpas_dbus_error_invalid_args - Return a new InvalidArgs error message
85 * @message: Pointer to incoming dbus message this error refers to
86 * Returns: a dbus error message
88 * Convenience function to create and return an invalid options error
90 DBusMessage * wpas_dbus_error_invalid_args(DBusMessage *message,
95 reply = dbus_message_new_error(
96 message, WPAS_DBUS_ERROR_INVALID_ARGS,
97 "Did not receive correct message arguments.");
99 dbus_message_append_args(reply, DBUS_TYPE_STRING, &arg,
107 * wpas_dbus_error_scan_error - Return a new ScanError error message
108 * @message: Pointer to incoming dbus message this error refers to
109 * @error: Optional string to be used as the error message
110 * Returns: a dbus error message
112 * Convenience function to create and return a scan error
114 static DBusMessage * wpas_dbus_error_scan_error(DBusMessage *message,
117 return dbus_message_new_error(message,
118 WPAS_DBUS_ERROR_IFACE_SCAN_ERROR,
123 DBusMessage * wpas_dbus_error_no_memory(DBusMessage *message)
125 wpa_printf(MSG_DEBUG, "dbus: Failed to allocate memory");
126 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, NULL);
130 static const char * const dont_quote[] = {
131 "key_mgmt", "proto", "pairwise", "auth_alg", "group", "eap",
132 "opensc_engine_path", "pkcs11_engine_path", "pkcs11_module_path",
133 "bssid", "scan_freq", "freq_list", NULL
136 static dbus_bool_t should_quote_opt(const char *key)
140 while (dont_quote[i] != NULL) {
141 if (os_strcmp(key, dont_quote[i]) == 0)
149 * get_iface_by_dbus_path - Get a new network interface
150 * @global: Pointer to global data from wpa_supplicant_init()
151 * @path: Pointer to a dbus object path representing an interface
152 * Returns: Pointer to the interface or %NULL if not found
154 static struct wpa_supplicant * get_iface_by_dbus_path(
155 struct wpa_global *global, const char *path)
157 struct wpa_supplicant *wpa_s;
159 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
160 if (wpa_s->dbus_new_path &&
161 os_strcmp(wpa_s->dbus_new_path, path) == 0)
169 * set_network_properties - Set properties of a configured network
170 * @wpa_s: wpa_supplicant structure for a network interface
171 * @ssid: wpa_ssid structure for a configured network
172 * @iter: DBus message iterator containing dictionary of network
174 * @error: On failure, an error describing the failure
175 * Returns: TRUE if the request succeeds, FALSE if it failed
177 * Sets network configuration with parameters given id DBus dictionary
179 dbus_bool_t set_network_properties(struct wpa_supplicant *wpa_s,
180 struct wpa_ssid *ssid,
181 DBusMessageIter *iter,
184 struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
185 DBusMessageIter iter_dict;
188 if (!wpa_dbus_dict_open_read(iter, &iter_dict, error))
191 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
195 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
199 if (entry.type == DBUS_TYPE_ARRAY &&
200 entry.array_type == DBUS_TYPE_BYTE) {
201 if (entry.array_len <= 0)
204 size = entry.array_len * 2 + 1;
205 value = os_zalloc(size);
209 ret = wpa_snprintf_hex(value, size,
210 (u8 *) entry.bytearray_value,
214 } else if (entry.type == DBUS_TYPE_STRING) {
215 if (should_quote_opt(entry.key)) {
216 size = os_strlen(entry.str_value);
221 value = os_zalloc(size);
225 ret = os_snprintf(value, size, "\"%s\"",
227 if (os_snprintf_error(size, ret))
230 value = os_strdup(entry.str_value);
234 } else if (entry.type == DBUS_TYPE_UINT32) {
235 value = os_zalloc(size);
239 ret = os_snprintf(value, size, "%u",
241 if (os_snprintf_error(size, ret))
243 } else if (entry.type == DBUS_TYPE_INT32) {
244 value = os_zalloc(size);
248 ret = os_snprintf(value, size, "%d",
250 if (os_snprintf_error(size, ret))
255 if (wpa_config_set(ssid, entry.key, value, 0) < 0)
258 if (os_strcmp(entry.key, "bssid") != 0 &&
259 os_strcmp(entry.key, "priority") != 0)
260 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
262 if (wpa_s->current_ssid == ssid ||
263 wpa_s->current_ssid == NULL) {
265 * Invalidate the EAP session cache if anything in the
266 * current or previously used configuration changes.
268 eapol_sm_invalidate_cached_session(wpa_s->eapol);
271 if ((os_strcmp(entry.key, "psk") == 0 &&
272 value[0] == '"' && ssid->ssid_len) ||
273 (os_strcmp(entry.key, "ssid") == 0 && ssid->passphrase))
274 wpa_config_update_psk(ssid);
275 else if (os_strcmp(entry.key, "priority") == 0)
276 wpa_config_update_prio_list(wpa_s->conf);
280 wpa_dbus_dict_entry_clear(&entry);
287 wpa_dbus_dict_entry_clear(&entry);
288 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
289 "invalid message format");
295 * wpas_dbus_simple_property_getter - Get basic type property
296 * @iter: Message iter to use when appending arguments
297 * @type: DBus type of property (must be basic type)
298 * @val: pointer to place holding property value
299 * @error: On failure an error describing the failure
300 * Returns: TRUE if the request was successful, FALSE if it failed
302 * Generic getter for basic type properties. Type is required to be basic.
304 dbus_bool_t wpas_dbus_simple_property_getter(DBusMessageIter *iter,
309 DBusMessageIter variant_iter;
311 if (!dbus_type_is_basic(type)) {
312 dbus_set_error(error, DBUS_ERROR_FAILED,
313 "%s: given type is not basic", __func__);
317 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
318 wpa_dbus_type_as_string(type),
320 !dbus_message_iter_append_basic(&variant_iter, type, val) ||
321 !dbus_message_iter_close_container(iter, &variant_iter)) {
322 dbus_set_error(error, DBUS_ERROR_FAILED,
323 "%s: error constructing reply", __func__);
332 * wpas_dbus_simple_property_setter - Set basic type property
333 * @message: Pointer to incoming dbus message
334 * @type: DBus type of property (must be basic type)
335 * @val: pointer to place where value being set will be stored
336 * Returns: TRUE if the request was successful, FALSE if it failed
338 * Generic setter for basic type properties. Type is required to be basic.
340 dbus_bool_t wpas_dbus_simple_property_setter(DBusMessageIter *iter,
342 const int type, void *val)
344 DBusMessageIter variant_iter;
346 if (!dbus_type_is_basic(type)) {
347 dbus_set_error(error, DBUS_ERROR_FAILED,
348 "%s: given type is not basic", __func__);
352 /* Look at the new value */
353 dbus_message_iter_recurse(iter, &variant_iter);
354 if (dbus_message_iter_get_arg_type(&variant_iter) != type) {
355 dbus_set_error_const(error, DBUS_ERROR_FAILED,
356 "wrong property type");
359 dbus_message_iter_get_basic(&variant_iter, val);
366 * wpas_dbus_simple_array_property_getter - Get array type property
367 * @iter: Pointer to incoming dbus message iterator
368 * @type: DBus type of property array elements (must be basic type)
369 * @array: pointer to array of elements to put into response message
370 * @array_len: length of above array
371 * @error: a pointer to an error to fill on failure
372 * Returns: TRUE if the request succeeded, FALSE if it failed
374 * Generic getter for array type properties. Array elements type is
375 * required to be basic.
377 dbus_bool_t wpas_dbus_simple_array_property_getter(DBusMessageIter *iter,
383 DBusMessageIter variant_iter, array_iter;
384 char type_str[] = "a?"; /* ? will be replaced with subtype letter; */
385 const char *sub_type_str;
386 size_t element_size, i;
388 if (!dbus_type_is_basic(type)) {
389 dbus_set_error(error, DBUS_ERROR_FAILED,
390 "%s: given type is not basic", __func__);
394 sub_type_str = wpa_dbus_type_as_string(type);
395 type_str[1] = sub_type_str[0];
397 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
398 type_str, &variant_iter) ||
399 !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
400 sub_type_str, &array_iter)) {
401 dbus_set_error(error, DBUS_ERROR_FAILED,
402 "%s: failed to construct message", __func__);
408 case DBUS_TYPE_BOOLEAN:
411 case DBUS_TYPE_INT16:
412 case DBUS_TYPE_UINT16:
413 element_size = sizeof(uint16_t);
415 case DBUS_TYPE_INT32:
416 case DBUS_TYPE_UINT32:
417 element_size = sizeof(uint32_t);
419 case DBUS_TYPE_INT64:
420 case DBUS_TYPE_UINT64:
421 element_size = sizeof(uint64_t);
423 case DBUS_TYPE_DOUBLE:
424 element_size = sizeof(double);
426 case DBUS_TYPE_STRING:
427 case DBUS_TYPE_OBJECT_PATH:
428 element_size = sizeof(char *);
431 dbus_set_error(error, DBUS_ERROR_FAILED,
432 "%s: unknown element type %d", __func__, type);
436 for (i = 0; i < array_len; i++) {
437 if (!dbus_message_iter_append_basic(&array_iter, type,
438 array + i * element_size)) {
439 dbus_set_error(error, DBUS_ERROR_FAILED,
440 "%s: failed to construct message 2.5",
446 if (!dbus_message_iter_close_container(&variant_iter, &array_iter) ||
447 !dbus_message_iter_close_container(iter, &variant_iter)) {
448 dbus_set_error(error, DBUS_ERROR_FAILED,
449 "%s: failed to construct message 3", __func__);
458 * wpas_dbus_simple_array_array_property_getter - Get array array type property
459 * @iter: Pointer to incoming dbus message iterator
460 * @type: DBus type of property array elements (must be basic type)
461 * @array: pointer to array of elements to put into response message
462 * @array_len: length of above array
463 * @error: a pointer to an error to fill on failure
464 * Returns: TRUE if the request succeeded, FALSE if it failed
466 * Generic getter for array type properties. Array elements type is
467 * required to be basic.
469 dbus_bool_t wpas_dbus_simple_array_array_property_getter(DBusMessageIter *iter,
471 struct wpabuf **array,
475 DBusMessageIter variant_iter, array_iter;
476 char type_str[] = "aa?";
477 char inner_type_str[] = "a?";
478 const char *sub_type_str;
481 if (!dbus_type_is_basic(type)) {
482 dbus_set_error(error, DBUS_ERROR_FAILED,
483 "%s: given type is not basic", __func__);
487 sub_type_str = wpa_dbus_type_as_string(type);
488 type_str[2] = sub_type_str[0];
489 inner_type_str[1] = sub_type_str[0];
491 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
492 type_str, &variant_iter) ||
493 !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
494 inner_type_str, &array_iter)) {
495 dbus_set_error(error, DBUS_ERROR_FAILED,
496 "%s: failed to construct message", __func__);
500 for (i = 0; i < array_len && array[i]; i++) {
501 wpa_dbus_dict_bin_array_add_element(&array_iter,
502 wpabuf_head(array[i]),
503 wpabuf_len(array[i]));
507 if (!dbus_message_iter_close_container(&variant_iter, &array_iter) ||
508 !dbus_message_iter_close_container(iter, &variant_iter)) {
509 dbus_set_error(error, DBUS_ERROR_FAILED,
510 "%s: failed to close message", __func__);
519 * wpas_dbus_handler_create_interface - Request registration of a network iface
520 * @message: Pointer to incoming dbus message
521 * @global: %wpa_supplicant global data structure
522 * Returns: The object path of the new interface object,
523 * or a dbus error message with more information
525 * Handler function for "CreateInterface" method call. Handles requests
526 * by dbus clients to register a network interface that wpa_supplicant
529 DBusMessage * wpas_dbus_handler_create_interface(DBusMessage *message,
530 struct wpa_global *global)
532 DBusMessageIter iter_dict;
533 DBusMessage *reply = NULL;
534 DBusMessageIter iter;
535 struct wpa_dbus_dict_entry entry;
538 char *confname = NULL;
539 char *bridge_ifname = NULL;
541 dbus_message_iter_init(message, &iter);
543 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
545 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
546 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
548 if (os_strcmp(entry.key, "Driver") == 0 &&
549 entry.type == DBUS_TYPE_STRING) {
551 driver = os_strdup(entry.str_value);
552 wpa_dbus_dict_entry_clear(&entry);
555 } else if (os_strcmp(entry.key, "Ifname") == 0 &&
556 entry.type == DBUS_TYPE_STRING) {
558 ifname = os_strdup(entry.str_value);
559 wpa_dbus_dict_entry_clear(&entry);
562 } else if (os_strcmp(entry.key, "ConfigFile") == 0 &&
563 entry.type == DBUS_TYPE_STRING) {
565 confname = os_strdup(entry.str_value);
566 wpa_dbus_dict_entry_clear(&entry);
567 if (confname == NULL)
569 } else if (os_strcmp(entry.key, "BridgeIfname") == 0 &&
570 entry.type == DBUS_TYPE_STRING) {
571 os_free(bridge_ifname);
572 bridge_ifname = os_strdup(entry.str_value);
573 wpa_dbus_dict_entry_clear(&entry);
574 if (bridge_ifname == NULL)
577 wpa_dbus_dict_entry_clear(&entry);
583 goto error; /* Required Ifname argument missing */
586 * Try to get the wpa_supplicant record for this iface, return
587 * an error if we already control it.
589 if (wpa_supplicant_get_iface(global, ifname) != NULL) {
590 reply = dbus_message_new_error(
591 message, WPAS_DBUS_ERROR_IFACE_EXISTS,
592 "wpa_supplicant already controls this interface.");
594 struct wpa_supplicant *wpa_s;
595 struct wpa_interface iface;
597 os_memset(&iface, 0, sizeof(iface));
598 iface.driver = driver;
599 iface.ifname = ifname;
600 iface.confname = confname;
601 iface.bridge_ifname = bridge_ifname;
602 /* Otherwise, have wpa_supplicant attach to it. */
603 wpa_s = wpa_supplicant_add_iface(global, &iface, NULL);
604 if (wpa_s && wpa_s->dbus_new_path) {
605 const char *path = wpa_s->dbus_new_path;
607 reply = dbus_message_new_method_return(message);
608 dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH,
609 &path, DBUS_TYPE_INVALID);
611 reply = wpas_dbus_error_unknown_error(
613 "wpa_supplicant couldn't grab this interface.");
621 os_free(bridge_ifname);
625 reply = wpas_dbus_error_invalid_args(message, NULL);
628 reply = wpas_dbus_error_no_memory(message);
634 * wpas_dbus_handler_remove_interface - Request deregistration of an interface
635 * @message: Pointer to incoming dbus message
636 * @global: wpa_supplicant global data structure
637 * Returns: a dbus message containing a UINT32 indicating success (1) or
638 * failure (0), or returns a dbus error message with more information
640 * Handler function for "removeInterface" method call. Handles requests
641 * by dbus clients to deregister a network interface that wpa_supplicant
644 DBusMessage * wpas_dbus_handler_remove_interface(DBusMessage *message,
645 struct wpa_global *global)
647 struct wpa_supplicant *wpa_s;
649 DBusMessage *reply = NULL;
651 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path,
654 wpa_s = get_iface_by_dbus_path(global, path);
656 reply = wpas_dbus_error_iface_unknown(message);
657 else if (wpa_supplicant_remove_iface(global, wpa_s, 0)) {
658 reply = wpas_dbus_error_unknown_error(
660 "wpa_supplicant couldn't remove this interface.");
668 * wpas_dbus_handler_get_interface - Get the object path for an interface name
669 * @message: Pointer to incoming dbus message
670 * @global: %wpa_supplicant global data structure
671 * Returns: The object path of the interface object,
672 * or a dbus error message with more information
674 * Handler function for "getInterface" method call.
676 DBusMessage * wpas_dbus_handler_get_interface(DBusMessage *message,
677 struct wpa_global *global)
679 DBusMessage *reply = NULL;
682 struct wpa_supplicant *wpa_s;
684 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &ifname,
687 wpa_s = wpa_supplicant_get_iface(global, ifname);
688 if (wpa_s == NULL || wpa_s->dbus_new_path == NULL)
689 return wpas_dbus_error_iface_unknown(message);
691 path = wpa_s->dbus_new_path;
692 reply = dbus_message_new_method_return(message);
694 return wpas_dbus_error_no_memory(message);
695 if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
696 DBUS_TYPE_INVALID)) {
697 dbus_message_unref(reply);
698 return wpas_dbus_error_no_memory(message);
706 * wpas_dbus_getter_debug_level - Get debug level
707 * @iter: Pointer to incoming dbus message iter
708 * @error: Location to store error on failure
709 * @user_data: Function specific data
710 * Returns: TRUE on success, FALSE on failure
712 * Getter for "DebugLevel" property.
714 dbus_bool_t wpas_dbus_getter_debug_level(DBusMessageIter *iter,
719 int idx = wpa_debug_level;
725 str = debug_strings[idx];
726 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
732 * wpas_dbus_getter_debug_timestamp - Get debug timestamp
733 * @iter: Pointer to incoming dbus message iter
734 * @error: Location to store error on failure
735 * @user_data: Function specific data
736 * Returns: TRUE on success, FALSE on failure
738 * Getter for "DebugTimestamp" property.
740 dbus_bool_t wpas_dbus_getter_debug_timestamp(DBusMessageIter *iter,
744 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
745 &wpa_debug_timestamp, error);
751 * wpas_dbus_getter_debug_show_keys - Get debug show keys
752 * @iter: Pointer to incoming dbus message iter
753 * @error: Location to store error on failure
754 * @user_data: Function specific data
755 * Returns: TRUE on success, FALSE on failure
757 * Getter for "DebugShowKeys" property.
759 dbus_bool_t wpas_dbus_getter_debug_show_keys(DBusMessageIter *iter,
763 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
764 &wpa_debug_show_keys, error);
769 * wpas_dbus_setter_debug_level - Set debug level
770 * @iter: Pointer to incoming dbus message iter
771 * @error: Location to store error on failure
772 * @user_data: Function specific data
773 * Returns: TRUE on success, FALSE on failure
775 * Setter for "DebugLevel" property.
777 dbus_bool_t wpas_dbus_setter_debug_level(DBusMessageIter *iter,
778 DBusError *error, void *user_data)
780 struct wpa_global *global = user_data;
781 const char *str = NULL;
784 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
788 for (i = 0; debug_strings[i]; i++)
789 if (os_strcmp(debug_strings[i], str) == 0) {
795 wpa_supplicant_set_debug_params(global, val, wpa_debug_timestamp,
796 wpa_debug_show_keys)) {
797 dbus_set_error_const(error, DBUS_ERROR_FAILED,
798 "wrong debug level value");
807 * wpas_dbus_setter_debug_timestamp - Set debug timestamp
808 * @iter: Pointer to incoming dbus message iter
809 * @error: Location to store error on failure
810 * @user_data: Function specific data
811 * Returns: TRUE on success, FALSE on failure
813 * Setter for "DebugTimestamp" property.
815 dbus_bool_t wpas_dbus_setter_debug_timestamp(DBusMessageIter *iter,
819 struct wpa_global *global = user_data;
822 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
826 wpa_supplicant_set_debug_params(global, wpa_debug_level, val ? 1 : 0,
827 wpa_debug_show_keys);
833 * wpas_dbus_setter_debug_show_keys - Set debug show keys
834 * @iter: Pointer to incoming dbus message iter
835 * @error: Location to store error on failure
836 * @user_data: Function specific data
837 * Returns: TRUE on success, FALSE on failure
839 * Setter for "DebugShowKeys" property.
841 dbus_bool_t wpas_dbus_setter_debug_show_keys(DBusMessageIter *iter,
845 struct wpa_global *global = user_data;
848 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
852 wpa_supplicant_set_debug_params(global, wpa_debug_level,
860 * wpas_dbus_getter_interfaces - Request registered interfaces list
861 * @iter: Pointer to incoming dbus message iter
862 * @error: Location to store error on failure
863 * @user_data: Function specific data
864 * Returns: TRUE on success, FALSE on failure
866 * Getter for "Interfaces" property. Handles requests
867 * by dbus clients to return list of registered interfaces objects
870 dbus_bool_t wpas_dbus_getter_interfaces(DBusMessageIter *iter,
874 struct wpa_global *global = user_data;
875 struct wpa_supplicant *wpa_s;
877 unsigned int i = 0, num = 0;
880 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
881 if (wpa_s->dbus_new_path)
885 paths = os_calloc(num, sizeof(char *));
887 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
891 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
892 if (wpa_s->dbus_new_path)
893 paths[i++] = wpa_s->dbus_new_path;
896 success = wpas_dbus_simple_array_property_getter(iter,
897 DBUS_TYPE_OBJECT_PATH,
906 * wpas_dbus_getter_eap_methods - Request supported EAP methods list
907 * @iter: Pointer to incoming dbus message iter
908 * @error: Location to store error on failure
909 * @user_data: Function specific data
910 * Returns: TRUE on success, FALSE on failure
912 * Getter for "EapMethods" property. Handles requests
913 * by dbus clients to return list of strings with supported EAP methods
915 dbus_bool_t wpas_dbus_getter_eap_methods(DBusMessageIter *iter,
916 DBusError *error, void *user_data)
919 size_t num_items = 0;
922 eap_methods = eap_get_names_as_string_array(&num_items);
924 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
928 success = wpas_dbus_simple_array_property_getter(iter,
934 os_free(eap_methods[--num_items]);
935 os_free(eap_methods);
941 * wpas_dbus_getter_global_capabilities - Request supported global capabilities
942 * @iter: Pointer to incoming dbus message iter
943 * @error: Location to store error on failure
944 * @user_data: Function specific data
945 * Returns: TRUE on success, FALSE on failure
947 * Getter for "Capabilities" property. Handles requests by dbus clients to
948 * return a list of strings with supported capabilities like AP, RSN IBSS,
949 * and P2P that are determined at compile time.
951 dbus_bool_t wpas_dbus_getter_global_capabilities(DBusMessageIter *iter,
955 const char *capabilities[5] = { NULL, NULL, NULL, NULL, NULL };
956 size_t num_items = 0;
959 capabilities[num_items++] = "ap";
960 #endif /* CONFIG_AP */
961 #ifdef CONFIG_IBSS_RSN
962 capabilities[num_items++] = "ibss-rsn";
963 #endif /* CONFIG_IBSS_RSN */
965 capabilities[num_items++] = "p2p";
966 #endif /* CONFIG_P2P */
967 #ifdef CONFIG_INTERWORKING
968 capabilities[num_items++] = "interworking";
969 #endif /* CONFIG_INTERWORKING */
971 return wpas_dbus_simple_array_property_getter(iter,
978 static int wpas_dbus_get_scan_type(DBusMessage *message, DBusMessageIter *var,
979 char **type, DBusMessage **reply)
981 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_STRING) {
982 wpa_printf(MSG_DEBUG, "%s[dbus]: Type must be a string",
984 *reply = wpas_dbus_error_invalid_args(
985 message, "Wrong Type value type. String required");
988 dbus_message_iter_get_basic(var, type);
993 static int wpas_dbus_get_scan_ssids(DBusMessage *message, DBusMessageIter *var,
994 struct wpa_driver_scan_params *params,
997 struct wpa_driver_scan_ssid *ssids = params->ssids;
998 size_t ssids_num = 0;
1000 DBusMessageIter array_iter, sub_array_iter;
1004 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
1005 wpa_printf(MSG_DEBUG,
1006 "%s[dbus]: ssids must be an array of arrays of bytes",
1008 *reply = wpas_dbus_error_invalid_args(
1010 "Wrong SSIDs value type. Array of arrays of bytes required");
1014 dbus_message_iter_recurse(var, &array_iter);
1016 if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY ||
1017 dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_BYTE) {
1018 wpa_printf(MSG_DEBUG,
1019 "%s[dbus]: ssids must be an array of arrays of bytes",
1021 *reply = wpas_dbus_error_invalid_args(
1023 "Wrong SSIDs value type. Array of arrays of bytes required");
1027 while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_ARRAY) {
1028 if (ssids_num >= WPAS_MAX_SCAN_SSIDS) {
1029 wpa_printf(MSG_DEBUG,
1030 "%s[dbus]: Too many ssids specified on scan dbus call",
1032 *reply = wpas_dbus_error_invalid_args(
1034 "Too many ssids specified. Specify at most four");
1038 dbus_message_iter_recurse(&array_iter, &sub_array_iter);
1040 dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len);
1042 if (len > SSID_MAX_LEN) {
1043 wpa_printf(MSG_DEBUG,
1044 "%s[dbus]: SSID too long (len=%d max_len=%d)",
1045 __func__, len, SSID_MAX_LEN);
1046 *reply = wpas_dbus_error_invalid_args(
1047 message, "Invalid SSID: too long");
1052 ssid = os_malloc(len);
1054 *reply = wpas_dbus_error_no_memory(message);
1057 os_memcpy(ssid, val, len);
1059 /* Allow zero-length SSIDs */
1063 ssids[ssids_num].ssid = ssid;
1064 ssids[ssids_num].ssid_len = len;
1066 dbus_message_iter_next(&array_iter);
1070 params->num_ssids = ssids_num;
1075 static int wpas_dbus_get_scan_ies(DBusMessage *message, DBusMessageIter *var,
1076 struct wpa_driver_scan_params *params,
1077 DBusMessage **reply)
1079 u8 *ies = NULL, *nies;
1081 DBusMessageIter array_iter, sub_array_iter;
1085 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
1086 wpa_printf(MSG_DEBUG,
1087 "%s[dbus]: ies must be an array of arrays of bytes",
1089 *reply = wpas_dbus_error_invalid_args(
1091 "Wrong IEs value type. Array of arrays of bytes required");
1095 dbus_message_iter_recurse(var, &array_iter);
1097 if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY ||
1098 dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_BYTE) {
1099 wpa_printf(MSG_DEBUG,
1100 "%s[dbus]: ies must be an array of arrays of bytes",
1102 *reply = wpas_dbus_error_invalid_args(
1103 message, "Wrong IEs value type. Array required");
1107 while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_ARRAY) {
1108 dbus_message_iter_recurse(&array_iter, &sub_array_iter);
1110 dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len);
1112 dbus_message_iter_next(&array_iter);
1116 nies = os_realloc(ies, ies_len + len);
1119 *reply = wpas_dbus_error_no_memory(message);
1123 os_memcpy(ies + ies_len, val, len);
1126 dbus_message_iter_next(&array_iter);
1129 params->extra_ies = ies;
1130 params->extra_ies_len = ies_len;
1135 static int wpas_dbus_get_scan_channels(DBusMessage *message,
1136 DBusMessageIter *var,
1137 struct wpa_driver_scan_params *params,
1138 DBusMessage **reply)
1140 DBusMessageIter array_iter, sub_array_iter;
1141 int *freqs = NULL, *nfreqs;
1144 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
1145 wpa_printf(MSG_DEBUG,
1146 "%s[dbus]: Channels must be an array of structs",
1148 *reply = wpas_dbus_error_invalid_args(
1150 "Wrong Channels value type. Array of structs required");
1154 dbus_message_iter_recurse(var, &array_iter);
1156 if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_STRUCT) {
1157 wpa_printf(MSG_DEBUG,
1158 "%s[dbus]: Channels must be an array of structs",
1160 *reply = wpas_dbus_error_invalid_args(
1162 "Wrong Channels value type. Array of structs required");
1166 while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_STRUCT)
1170 dbus_message_iter_recurse(&array_iter, &sub_array_iter);
1172 if (dbus_message_iter_get_arg_type(&sub_array_iter) !=
1174 wpa_printf(MSG_DEBUG,
1175 "%s[dbus]: Channel must by specified by struct of two UINT32s %c",
1177 dbus_message_iter_get_arg_type(
1179 *reply = wpas_dbus_error_invalid_args(
1181 "Wrong Channel struct. Two UINT32s required");
1185 dbus_message_iter_get_basic(&sub_array_iter, &freq);
1187 if (!dbus_message_iter_next(&sub_array_iter) ||
1188 dbus_message_iter_get_arg_type(&sub_array_iter) !=
1190 wpa_printf(MSG_DEBUG,
1191 "%s[dbus]: Channel must by specified by struct of two UINT32s",
1193 *reply = wpas_dbus_error_invalid_args(
1195 "Wrong Channel struct. Two UINT32s required");
1200 dbus_message_iter_get_basic(&sub_array_iter, &width);
1202 #define FREQS_ALLOC_CHUNK 32
1203 if (freqs_num % FREQS_ALLOC_CHUNK == 0) {
1204 nfreqs = os_realloc_array(
1205 freqs, freqs_num + FREQS_ALLOC_CHUNK,
1211 if (freqs == NULL) {
1212 *reply = wpas_dbus_error_no_memory(message);
1216 freqs[freqs_num] = freq;
1219 dbus_message_iter_next(&array_iter);
1222 nfreqs = os_realloc_array(freqs, freqs_num + 1, sizeof(int));
1226 if (freqs == NULL) {
1227 *reply = wpas_dbus_error_no_memory(message);
1230 freqs[freqs_num] = 0;
1232 params->freqs = freqs;
1237 static int wpas_dbus_get_scan_allow_roam(DBusMessage *message,
1238 DBusMessageIter *var,
1240 DBusMessage **reply)
1242 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_BOOLEAN) {
1243 wpa_printf(MSG_DEBUG, "%s[dbus]: Type must be a boolean",
1245 *reply = wpas_dbus_error_invalid_args(
1246 message, "Wrong Type value type. Boolean required");
1249 dbus_message_iter_get_basic(var, allow);
1255 * wpas_dbus_handler_scan - Request a wireless scan on an interface
1256 * @message: Pointer to incoming dbus message
1257 * @wpa_s: wpa_supplicant structure for a network interface
1258 * Returns: NULL indicating success or DBus error message on failure
1260 * Handler function for "Scan" method call of a network device. Requests
1261 * that wpa_supplicant perform a wireless scan as soon as possible
1262 * on a particular wireless interface.
1264 DBusMessage * wpas_dbus_handler_scan(DBusMessage *message,
1265 struct wpa_supplicant *wpa_s)
1267 DBusMessage *reply = NULL;
1268 DBusMessageIter iter, dict_iter, entry_iter, variant_iter;
1269 char *key = NULL, *type = NULL;
1270 struct wpa_driver_scan_params params;
1272 dbus_bool_t allow_roam = 1;
1274 os_memset(¶ms, 0, sizeof(params));
1276 dbus_message_iter_init(message, &iter);
1278 dbus_message_iter_recurse(&iter, &dict_iter);
1280 while (dbus_message_iter_get_arg_type(&dict_iter) ==
1281 DBUS_TYPE_DICT_ENTRY) {
1282 dbus_message_iter_recurse(&dict_iter, &entry_iter);
1283 dbus_message_iter_get_basic(&entry_iter, &key);
1284 dbus_message_iter_next(&entry_iter);
1285 dbus_message_iter_recurse(&entry_iter, &variant_iter);
1287 if (os_strcmp(key, "Type") == 0) {
1288 if (wpas_dbus_get_scan_type(message, &variant_iter,
1291 } else if (os_strcmp(key, "SSIDs") == 0) {
1292 if (wpas_dbus_get_scan_ssids(message, &variant_iter,
1293 ¶ms, &reply) < 0)
1295 } else if (os_strcmp(key, "IEs") == 0) {
1296 if (wpas_dbus_get_scan_ies(message, &variant_iter,
1297 ¶ms, &reply) < 0)
1299 } else if (os_strcmp(key, "Channels") == 0) {
1300 if (wpas_dbus_get_scan_channels(message, &variant_iter,
1301 ¶ms, &reply) < 0)
1303 } else if (os_strcmp(key, "AllowRoam") == 0) {
1304 if (wpas_dbus_get_scan_allow_roam(message,
1310 wpa_printf(MSG_DEBUG, "%s[dbus]: Unknown argument %s",
1312 reply = wpas_dbus_error_invalid_args(message, key);
1316 dbus_message_iter_next(&dict_iter);
1320 wpa_printf(MSG_DEBUG, "%s[dbus]: Scan type not specified",
1322 reply = wpas_dbus_error_invalid_args(message, key);
1326 if (os_strcmp(type, "passive") == 0) {
1327 if (params.num_ssids || params.extra_ies_len) {
1328 wpa_printf(MSG_DEBUG,
1329 "%s[dbus]: SSIDs or IEs specified for passive scan.",
1331 reply = wpas_dbus_error_invalid_args(
1333 "You can specify only Channels in passive scan");
1336 if (wpa_s->sched_scanning) {
1337 wpa_printf(MSG_DEBUG,
1338 "%s[dbus]: Stop ongoing sched_scan to allow requested scan to proceed",
1340 wpa_supplicant_cancel_sched_scan(wpa_s);
1343 if (params.freqs && params.freqs[0]) {
1344 wpa_s->last_scan_req = MANUAL_SCAN_REQ;
1345 if (wpa_supplicant_trigger_scan(wpa_s,
1347 reply = wpas_dbus_error_scan_error(
1349 "Scan request rejected");
1352 wpa_s->scan_req = MANUAL_SCAN_REQ;
1353 wpa_supplicant_req_scan(wpa_s, 0, 0);
1356 } else if (os_strcmp(type, "active") == 0) {
1357 if (!params.num_ssids) {
1358 /* Add wildcard ssid */
1361 #ifdef CONFIG_AUTOSCAN
1362 autoscan_deinit(wpa_s);
1363 #endif /* CONFIG_AUTOSCAN */
1364 if (wpa_s->sched_scanning) {
1365 wpa_printf(MSG_DEBUG,
1366 "%s[dbus]: Stop ongoing sched_scan to allow requested scan to proceed",
1368 wpa_supplicant_cancel_sched_scan(wpa_s);
1371 wpa_s->last_scan_req = MANUAL_SCAN_REQ;
1372 if (wpa_supplicant_trigger_scan(wpa_s, ¶ms)) {
1373 reply = wpas_dbus_error_scan_error(
1374 message, "Scan request rejected");
1377 wpa_printf(MSG_DEBUG, "%s[dbus]: Unknown scan type: %s",
1379 reply = wpas_dbus_error_invalid_args(message,
1385 wpa_s->scan_res_handler = scan_only_handler;
1388 for (i = 0; i < WPAS_MAX_SCAN_SSIDS; i++)
1389 os_free((u8 *) params.ssids[i].ssid);
1390 os_free((u8 *) params.extra_ies);
1391 os_free(params.freqs);
1397 * wpas_dbus_handler_signal_poll - Request immediate signal properties
1398 * @message: Pointer to incoming dbus message
1399 * @wpa_s: wpa_supplicant structure for a network interface
1400 * Returns: NULL indicating success or DBus error message on failure
1402 * Handler function for "SignalPoll" method call of a network device. Requests
1403 * that wpa_supplicant read signal properties like RSSI, noise, and link
1404 * speed and return them.
1406 DBusMessage * wpas_dbus_handler_signal_poll(DBusMessage *message,
1407 struct wpa_supplicant *wpa_s)
1409 struct wpa_signal_info si;
1410 DBusMessage *reply = NULL;
1411 DBusMessageIter iter, iter_dict, variant_iter;
1414 ret = wpa_drv_signal_poll(wpa_s, &si);
1416 return dbus_message_new_error(message, DBUS_ERROR_FAILED,
1417 "Failed to read signal");
1420 reply = dbus_message_new_method_return(message);
1424 dbus_message_iter_init_append(reply, &iter);
1426 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
1427 "a{sv}", &variant_iter) ||
1428 !wpa_dbus_dict_open_write(&variant_iter, &iter_dict) ||
1429 !wpa_dbus_dict_append_int32(&iter_dict, "rssi",
1430 si.current_signal) ||
1431 !wpa_dbus_dict_append_int32(&iter_dict, "linkspeed",
1432 si.current_txrate / 1000) ||
1433 !wpa_dbus_dict_append_int32(&iter_dict, "noise",
1434 si.current_noise) ||
1435 !wpa_dbus_dict_append_uint32(&iter_dict, "frequency",
1437 (si.chanwidth != CHAN_WIDTH_UNKNOWN &&
1438 !wpa_dbus_dict_append_string(
1439 &iter_dict, "width",
1440 channel_width_to_string(si.chanwidth))) ||
1441 (si.center_frq1 > 0 && si.center_frq2 > 0 &&
1442 (!wpa_dbus_dict_append_int32(&iter_dict, "center-frq1",
1444 !wpa_dbus_dict_append_int32(&iter_dict, "center-frq2",
1445 si.center_frq2))) ||
1447 !wpa_dbus_dict_append_int32(&iter_dict, "avg-rssi",
1449 !wpa_dbus_dict_close_write(&variant_iter, &iter_dict) ||
1450 !dbus_message_iter_close_container(&iter, &variant_iter))
1457 dbus_message_unref(reply);
1458 return wpas_dbus_error_no_memory(message);
1463 * wpas_dbus_handler_disconnect - Terminate the current connection
1464 * @message: Pointer to incoming dbus message
1465 * @wpa_s: wpa_supplicant structure for a network interface
1466 * Returns: NotConnected DBus error message if already not connected
1467 * or NULL otherwise.
1469 * Handler function for "Disconnect" method call of network interface.
1471 DBusMessage * wpas_dbus_handler_disconnect(DBusMessage *message,
1472 struct wpa_supplicant *wpa_s)
1474 if (wpa_s->current_ssid != NULL) {
1475 wpa_s->disconnected = 1;
1476 wpa_supplicant_deauthenticate(wpa_s,
1477 WLAN_REASON_DEAUTH_LEAVING);
1482 return dbus_message_new_error(message, WPAS_DBUS_ERROR_NOT_CONNECTED,
1483 "This interface is not connected");
1488 * wpas_dbus_new_iface_add_network - Add a new configured network
1489 * @message: Pointer to incoming dbus message
1490 * @wpa_s: wpa_supplicant structure for a network interface
1491 * Returns: A dbus message containing the object path of the new network
1493 * Handler function for "AddNetwork" method call of a network interface.
1495 DBusMessage * wpas_dbus_handler_add_network(DBusMessage *message,
1496 struct wpa_supplicant *wpa_s)
1498 DBusMessage *reply = NULL;
1499 DBusMessageIter iter;
1500 struct wpa_ssid *ssid = NULL;
1501 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf;
1504 dbus_message_iter_init(message, &iter);
1506 if (wpa_s->dbus_new_path)
1507 ssid = wpa_config_add_network(wpa_s->conf);
1509 wpa_printf(MSG_ERROR, "%s[dbus]: can't add new interface.",
1511 reply = wpas_dbus_error_unknown_error(
1513 "wpa_supplicant could not add a network on this interface.");
1516 wpas_notify_network_added(wpa_s, ssid);
1518 wpa_config_set_network_defaults(ssid);
1520 dbus_error_init(&error);
1521 if (!set_network_properties(wpa_s, ssid, &iter, &error)) {
1522 wpa_printf(MSG_DEBUG,
1523 "%s[dbus]: control interface couldn't set network properties",
1525 reply = wpas_dbus_reply_new_from_error(message, &error,
1526 DBUS_ERROR_INVALID_ARGS,
1527 "Failed to add network");
1528 dbus_error_free(&error);
1532 /* Construct the object path for this network. */
1533 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
1534 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
1535 wpa_s->dbus_new_path, ssid->id);
1537 reply = dbus_message_new_method_return(message);
1538 if (reply == NULL) {
1539 reply = wpas_dbus_error_no_memory(message);
1542 if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
1543 DBUS_TYPE_INVALID)) {
1544 dbus_message_unref(reply);
1545 reply = wpas_dbus_error_no_memory(message);
1553 wpas_notify_network_removed(wpa_s, ssid);
1554 wpa_config_remove_network(wpa_s->conf, ssid->id);
1561 * wpas_dbus_handler_reassociate - Reassociate
1562 * @message: Pointer to incoming dbus message
1563 * @wpa_s: wpa_supplicant structure for a network interface
1564 * Returns: InterfaceDisabled DBus error message if disabled
1565 * or NULL otherwise.
1567 * Handler function for "Reassociate" method call of network interface.
1569 DBusMessage * wpas_dbus_handler_reassociate(DBusMessage *message,
1570 struct wpa_supplicant *wpa_s)
1572 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED) {
1573 wpas_request_connection(wpa_s);
1577 return dbus_message_new_error(message, WPAS_DBUS_ERROR_IFACE_DISABLED,
1578 "This interface is disabled");
1583 * wpas_dbus_handler_expect_disconnect - ExpectDisconnect
1584 * @message: Pointer to incoming dbus message
1585 * @global: %wpa_supplicant global data structure
1588 * Handler function for notifying system there will be a expected disconnect.
1589 * This will prevent wpa_supplicant from adding blacklists upon next disconnect..
1591 DBusMessage * wpas_dbus_handler_expect_disconnect(DBusMessage *message,
1592 struct wpa_global *global)
1594 struct wpa_supplicant *wpa_s = global->ifaces;
1596 for (; wpa_s; wpa_s = wpa_s->next)
1597 if (wpa_s->wpa_state >= WPA_ASSOCIATED)
1598 wpa_s->own_disconnect_req = 1;
1604 * wpas_dbus_handler_reattach - Reattach to current AP
1605 * @message: Pointer to incoming dbus message
1606 * @wpa_s: wpa_supplicant structure for a network interface
1607 * Returns: NotConnected DBus error message if not connected
1608 * or NULL otherwise.
1610 * Handler function for "Reattach" method call of network interface.
1612 DBusMessage * wpas_dbus_handler_reattach(DBusMessage *message,
1613 struct wpa_supplicant *wpa_s)
1615 if (wpa_s->current_ssid != NULL) {
1616 wpa_s->reattach = 1;
1617 wpas_request_connection(wpa_s);
1621 return dbus_message_new_error(message, WPAS_DBUS_ERROR_NOT_CONNECTED,
1622 "This interface is not connected");
1627 * wpas_dbus_handler_reconnect - Reconnect if disconnected
1628 * @message: Pointer to incoming dbus message
1629 * @wpa_s: wpa_supplicant structure for a network interface
1630 * Returns: InterfaceDisabled DBus error message if disabled
1631 * or NULL otherwise.
1633 * Handler function for "Reconnect" method call of network interface.
1635 DBusMessage * wpas_dbus_handler_reconnect(DBusMessage *message,
1636 struct wpa_supplicant *wpa_s)
1638 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
1639 return dbus_message_new_error(message,
1640 WPAS_DBUS_ERROR_IFACE_DISABLED,
1641 "This interface is disabled");
1644 if (wpa_s->disconnected)
1645 wpas_request_connection(wpa_s);
1651 * wpas_dbus_handler_remove_network - Remove a configured network
1652 * @message: Pointer to incoming dbus message
1653 * @wpa_s: wpa_supplicant structure for a network interface
1654 * Returns: NULL on success or dbus error on failure
1656 * Handler function for "RemoveNetwork" method call of a network interface.
1658 DBusMessage * wpas_dbus_handler_remove_network(DBusMessage *message,
1659 struct wpa_supplicant *wpa_s)
1661 DBusMessage *reply = NULL;
1663 char *iface, *net_id;
1665 struct wpa_ssid *ssid;
1668 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
1671 /* Extract the network ID and ensure the network */
1672 /* is actually a child of this interface */
1673 iface = wpas_dbus_new_decompose_object_path(op,
1674 WPAS_DBUS_NEW_NETWORKS_PART,
1676 if (iface == NULL || net_id == NULL || !wpa_s->dbus_new_path ||
1677 os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
1678 reply = wpas_dbus_error_invalid_args(message, op);
1683 id = strtoul(net_id, NULL, 10);
1685 reply = wpas_dbus_error_invalid_args(message, op);
1689 ssid = wpa_config_get_network(wpa_s->conf, id);
1691 reply = wpas_dbus_error_network_unknown(message);
1695 was_disabled = ssid->disabled;
1697 wpas_notify_network_removed(wpa_s, ssid);
1699 if (ssid == wpa_s->current_ssid)
1700 wpa_supplicant_deauthenticate(wpa_s,
1701 WLAN_REASON_DEAUTH_LEAVING);
1702 else if (!was_disabled && wpa_s->sched_scanning) {
1703 wpa_printf(MSG_DEBUG,
1704 "Stop ongoing sched_scan to remove network from filters");
1705 wpa_supplicant_cancel_sched_scan(wpa_s);
1706 wpa_supplicant_req_scan(wpa_s, 0, 0);
1709 if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
1710 wpa_printf(MSG_ERROR,
1711 "%s[dbus]: error occurred when removing network %d",
1713 reply = wpas_dbus_error_unknown_error(
1715 "error removing the specified network on is interface.");
1725 static void remove_network(void *arg, struct wpa_ssid *ssid)
1727 struct wpa_supplicant *wpa_s = arg;
1729 wpas_notify_network_removed(wpa_s, ssid);
1731 if (wpa_config_remove_network(wpa_s->conf, ssid->id) < 0) {
1732 wpa_printf(MSG_ERROR,
1733 "%s[dbus]: error occurred when removing network %d",
1734 __func__, ssid->id);
1738 if (ssid == wpa_s->current_ssid)
1739 wpa_supplicant_deauthenticate(wpa_s,
1740 WLAN_REASON_DEAUTH_LEAVING);
1745 * wpas_dbus_handler_remove_all_networks - Remove all configured networks
1746 * @message: Pointer to incoming dbus message
1747 * @wpa_s: wpa_supplicant structure for a network interface
1748 * Returns: NULL on success or dbus error on failure
1750 * Handler function for "RemoveAllNetworks" method call of a network interface.
1752 DBusMessage * wpas_dbus_handler_remove_all_networks(
1753 DBusMessage *message, struct wpa_supplicant *wpa_s)
1755 if (wpa_s->sched_scanning)
1756 wpa_supplicant_cancel_sched_scan(wpa_s);
1758 /* NB: could check for failure and return an error */
1759 wpa_config_foreach_network(wpa_s->conf, remove_network, wpa_s);
1765 * wpas_dbus_handler_select_network - Attempt association with a network
1766 * @message: Pointer to incoming dbus message
1767 * @wpa_s: wpa_supplicant structure for a network interface
1768 * Returns: NULL on success or dbus error on failure
1770 * Handler function for "SelectNetwork" method call of network interface.
1772 DBusMessage * wpas_dbus_handler_select_network(DBusMessage *message,
1773 struct wpa_supplicant *wpa_s)
1775 DBusMessage *reply = NULL;
1777 char *iface, *net_id;
1779 struct wpa_ssid *ssid;
1781 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
1784 /* Extract the network ID and ensure the network */
1785 /* is actually a child of this interface */
1786 iface = wpas_dbus_new_decompose_object_path(op,
1787 WPAS_DBUS_NEW_NETWORKS_PART,
1789 if (iface == NULL || net_id == NULL || !wpa_s->dbus_new_path ||
1790 os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
1791 reply = wpas_dbus_error_invalid_args(message, op);
1796 id = strtoul(net_id, NULL, 10);
1798 reply = wpas_dbus_error_invalid_args(message, op);
1802 ssid = wpa_config_get_network(wpa_s->conf, id);
1804 reply = wpas_dbus_error_network_unknown(message);
1808 /* Finally, associate with the network */
1809 wpa_supplicant_select_network(wpa_s, ssid);
1818 * wpas_dbus_handler_network_reply - Reply to a NetworkRequest signal
1819 * @message: Pointer to incoming dbus message
1820 * @wpa_s: wpa_supplicant structure for a network interface
1821 * Returns: NULL on success or dbus error on failure
1823 * Handler function for "NetworkReply" method call of network interface.
1825 DBusMessage * wpas_dbus_handler_network_reply(DBusMessage *message,
1826 struct wpa_supplicant *wpa_s)
1828 #ifdef IEEE8021X_EAPOL
1829 DBusMessage *reply = NULL;
1830 const char *op, *field, *value;
1831 char *iface, *net_id;
1833 struct wpa_ssid *ssid;
1835 if (!dbus_message_get_args(message, NULL,
1836 DBUS_TYPE_OBJECT_PATH, &op,
1837 DBUS_TYPE_STRING, &field,
1838 DBUS_TYPE_STRING, &value,
1840 return wpas_dbus_error_invalid_args(message, NULL);
1842 /* Extract the network ID and ensure the network */
1843 /* is actually a child of this interface */
1844 iface = wpas_dbus_new_decompose_object_path(op,
1845 WPAS_DBUS_NEW_NETWORKS_PART,
1847 if (iface == NULL || net_id == NULL || !wpa_s->dbus_new_path ||
1848 os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
1849 reply = wpas_dbus_error_invalid_args(message, op);
1854 id = strtoul(net_id, NULL, 10);
1856 reply = wpas_dbus_error_invalid_args(message, net_id);
1860 ssid = wpa_config_get_network(wpa_s->conf, id);
1862 reply = wpas_dbus_error_network_unknown(message);
1866 if (wpa_supplicant_ctrl_iface_ctrl_rsp_handle(wpa_s, ssid,
1868 reply = wpas_dbus_error_invalid_args(message, field);
1870 /* Tell EAP to retry immediately */
1871 eapol_sm_notify_ctrl_response(wpa_s->eapol);
1877 #else /* IEEE8021X_EAPOL */
1878 wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included");
1879 return wpas_dbus_error_unknown_error(message, "802.1X not included");
1880 #endif /* IEEE8021X_EAPOL */
1884 #ifndef CONFIG_NO_CONFIG_BLOBS
1887 * wpas_dbus_handler_add_blob - Store named binary blob (ie, for certificates)
1888 * @message: Pointer to incoming dbus message
1889 * @wpa_s: %wpa_supplicant data structure
1890 * Returns: A dbus message containing an error on failure or NULL on success
1892 * Asks wpa_supplicant to internally store a binary blobs.
1894 DBusMessage * wpas_dbus_handler_add_blob(DBusMessage *message,
1895 struct wpa_supplicant *wpa_s)
1897 DBusMessage *reply = NULL;
1898 DBusMessageIter iter, array_iter;
1903 struct wpa_config_blob *blob = NULL;
1905 dbus_message_iter_init(message, &iter);
1906 dbus_message_iter_get_basic(&iter, &blob_name);
1908 if (wpa_config_get_blob(wpa_s->conf, blob_name)) {
1909 return dbus_message_new_error(message,
1910 WPAS_DBUS_ERROR_BLOB_EXISTS,
1914 dbus_message_iter_next(&iter);
1915 dbus_message_iter_recurse(&iter, &array_iter);
1917 dbus_message_iter_get_fixed_array(&array_iter, &blob_data, &blob_len);
1919 blob = os_zalloc(sizeof(*blob));
1921 reply = wpas_dbus_error_no_memory(message);
1925 blob->data = os_malloc(blob_len);
1926 blob->name = os_strdup(blob_name);
1927 if (!blob->data || !blob->name) {
1928 reply = wpas_dbus_error_no_memory(message);
1931 os_memcpy(blob->data, blob_data, blob_len);
1932 blob->len = blob_len;
1934 wpa_config_set_blob(wpa_s->conf, blob);
1935 wpas_notify_blob_added(wpa_s, blob->name);
1941 os_free(blob->name);
1942 os_free(blob->data);
1950 * wpas_dbus_handler_get_blob - Get named binary blob (ie, for certificates)
1951 * @message: Pointer to incoming dbus message
1952 * @wpa_s: %wpa_supplicant data structure
1953 * Returns: A dbus message containing array of bytes (blob)
1955 * Gets one wpa_supplicant's binary blobs.
1957 DBusMessage * wpas_dbus_handler_get_blob(DBusMessage *message,
1958 struct wpa_supplicant *wpa_s)
1960 DBusMessage *reply = NULL;
1961 DBusMessageIter iter, array_iter;
1964 const struct wpa_config_blob *blob;
1966 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &blob_name,
1969 blob = wpa_config_get_blob(wpa_s->conf, blob_name);
1971 return dbus_message_new_error(message,
1972 WPAS_DBUS_ERROR_BLOB_UNKNOWN,
1976 reply = dbus_message_new_method_return(message);
1978 return wpas_dbus_error_no_memory(message);
1980 dbus_message_iter_init_append(reply, &iter);
1982 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
1983 DBUS_TYPE_BYTE_AS_STRING,
1985 !dbus_message_iter_append_fixed_array(&array_iter, DBUS_TYPE_BYTE,
1986 &(blob->data), blob->len) ||
1987 !dbus_message_iter_close_container(&iter, &array_iter)) {
1988 dbus_message_unref(reply);
1989 reply = wpas_dbus_error_no_memory(message);
1997 * wpas_remove_handler_remove_blob - Remove named binary blob
1998 * @message: Pointer to incoming dbus message
1999 * @wpa_s: %wpa_supplicant data structure
2000 * Returns: NULL on success or dbus error
2002 * Asks wpa_supplicant to internally remove a binary blobs.
2004 DBusMessage * wpas_dbus_handler_remove_blob(DBusMessage *message,
2005 struct wpa_supplicant *wpa_s)
2007 DBusMessage *reply = NULL;
2010 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &blob_name,
2013 if (wpa_config_remove_blob(wpa_s->conf, blob_name)) {
2014 return dbus_message_new_error(message,
2015 WPAS_DBUS_ERROR_BLOB_UNKNOWN,
2018 wpas_notify_blob_removed(wpa_s, blob_name);
2024 #endif /* CONFIG_NO_CONFIG_BLOBS */
2028 * wpas_dbus_handler_flush_bss - Flush the BSS cache
2029 * @message: Pointer to incoming dbus message
2030 * @wpa_s: wpa_supplicant structure for a network interface
2033 * Handler function for "FlushBSS" method call of network interface.
2035 DBusMessage * wpas_dbus_handler_flush_bss(DBusMessage *message,
2036 struct wpa_supplicant *wpa_s)
2040 dbus_message_get_args(message, NULL, DBUS_TYPE_UINT32, &age,
2044 wpa_bss_flush(wpa_s);
2046 wpa_bss_flush_by_age(wpa_s, age);
2052 #ifdef CONFIG_AUTOSCAN
2054 * wpas_dbus_handler_autoscan - Set autoscan parameters for the interface
2055 * @message: Pointer to incoming dbus message
2056 * @wpa_s: wpa_supplicant structure for a network interface
2059 * Handler function for "AutoScan" method call of network interface.
2061 DBusMessage * wpas_dbus_handler_autoscan(DBusMessage *message,
2062 struct wpa_supplicant *wpa_s)
2064 DBusMessage *reply = NULL;
2065 enum wpa_states state = wpa_s->wpa_state;
2068 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &arg,
2071 if (arg != NULL && os_strlen(arg) > 0) {
2074 tmp = os_strdup(arg);
2076 reply = wpas_dbus_error_no_memory(message);
2078 os_free(wpa_s->conf->autoscan);
2079 wpa_s->conf->autoscan = tmp;
2080 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
2081 autoscan_init(wpa_s, 1);
2082 else if (state == WPA_SCANNING)
2083 wpa_supplicant_reinit_autoscan(wpa_s);
2085 } else if (arg != NULL && os_strlen(arg) == 0) {
2086 os_free(wpa_s->conf->autoscan);
2087 wpa_s->conf->autoscan = NULL;
2088 autoscan_deinit(wpa_s);
2090 reply = dbus_message_new_error(message,
2091 DBUS_ERROR_INVALID_ARGS,
2096 #endif /* CONFIG_AUTOSCAN */
2100 * wpas_dbus_handler_eap_logoff - IEEE 802.1X EAPOL state machine logoff
2101 * @message: Pointer to incoming dbus message
2102 * @wpa_s: wpa_supplicant structure for a network interface
2105 * Handler function for "EAPLogoff" method call of network interface.
2107 DBusMessage * wpas_dbus_handler_eap_logoff(DBusMessage *message,
2108 struct wpa_supplicant *wpa_s)
2110 eapol_sm_notify_logoff(wpa_s->eapol, TRUE);
2116 * wpas_dbus_handler_eap_logon - IEEE 802.1X EAPOL state machine logon
2117 * @message: Pointer to incoming dbus message
2118 * @wpa_s: wpa_supplicant structure for a network interface
2121 * Handler function for "EAPLogin" method call of network interface.
2123 DBusMessage * wpas_dbus_handler_eap_logon(DBusMessage *message,
2124 struct wpa_supplicant *wpa_s)
2126 eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
2133 static int get_peer_hwaddr_helper(DBusMessage *message, const char *func_name,
2134 u8 *peer_address, DBusMessage **error)
2136 const char *peer_string;
2140 if (!dbus_message_get_args(message, NULL,
2141 DBUS_TYPE_STRING, &peer_string,
2142 DBUS_TYPE_INVALID)) {
2143 *error = wpas_dbus_error_invalid_args(message, NULL);
2147 if (hwaddr_aton(peer_string, peer_address)) {
2148 wpa_printf(MSG_DEBUG, "%s: invalid address '%s'",
2149 func_name, peer_string);
2150 *error = wpas_dbus_error_invalid_args(
2151 message, "Invalid hardware address format");
2160 * wpas_dbus_handler_tdls_discover - Discover TDLS peer
2161 * @message: Pointer to incoming dbus message
2162 * @wpa_s: wpa_supplicant structure for a network interface
2163 * Returns: NULL indicating success or DBus error message on failure
2165 * Handler function for "TDLSDiscover" method call of network interface.
2167 DBusMessage * wpas_dbus_handler_tdls_discover(DBusMessage *message,
2168 struct wpa_supplicant *wpa_s)
2171 DBusMessage *error_reply;
2174 if (get_peer_hwaddr_helper(message, __func__, peer, &error_reply) < 0)
2177 wpa_printf(MSG_DEBUG, "DBUS TDLS_DISCOVER " MACSTR, MAC2STR(peer));
2179 if (wpa_tdls_is_external_setup(wpa_s->wpa))
2180 ret = wpa_tdls_send_discovery_request(wpa_s->wpa, peer);
2182 ret = wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer);
2185 return wpas_dbus_error_unknown_error(
2186 message, "error performing TDLS discovery");
2194 * wpas_dbus_handler_tdls_setup - Setup TDLS session
2195 * @message: Pointer to incoming dbus message
2196 * @wpa_s: wpa_supplicant structure for a network interface
2197 * Returns: NULL indicating success or DBus error message on failure
2199 * Handler function for "TDLSSetup" method call of network interface.
2201 DBusMessage * wpas_dbus_handler_tdls_setup(DBusMessage *message,
2202 struct wpa_supplicant *wpa_s)
2205 DBusMessage *error_reply;
2208 if (get_peer_hwaddr_helper(message, __func__, peer, &error_reply) < 0)
2211 wpa_printf(MSG_DEBUG, "DBUS TDLS_SETUP " MACSTR, MAC2STR(peer));
2213 wpa_tdls_remove(wpa_s->wpa, peer);
2214 if (wpa_tdls_is_external_setup(wpa_s->wpa))
2215 ret = wpa_tdls_start(wpa_s->wpa, peer);
2217 ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
2220 return wpas_dbus_error_unknown_error(
2221 message, "error performing TDLS setup");
2229 * wpas_dbus_handler_tdls_status - Return TDLS session status
2230 * @message: Pointer to incoming dbus message
2231 * @wpa_s: wpa_supplicant structure for a network interface
2232 * Returns: A string representing the state of the link to this TDLS peer
2234 * Handler function for "TDLSStatus" method call of network interface.
2236 DBusMessage * wpas_dbus_handler_tdls_status(DBusMessage *message,
2237 struct wpa_supplicant *wpa_s)
2241 const char *tdls_status;
2243 if (get_peer_hwaddr_helper(message, __func__, peer, &reply) < 0)
2246 wpa_printf(MSG_DEBUG, "DBUS TDLS_STATUS " MACSTR, MAC2STR(peer));
2248 tdls_status = wpa_tdls_get_link_status(wpa_s->wpa, peer);
2250 reply = dbus_message_new_method_return(message);
2251 dbus_message_append_args(reply, DBUS_TYPE_STRING,
2252 &tdls_status, DBUS_TYPE_INVALID);
2258 * wpas_dbus_handler_tdls_teardown - Teardown TDLS session
2259 * @message: Pointer to incoming dbus message
2260 * @wpa_s: wpa_supplicant structure for a network interface
2261 * Returns: NULL indicating success or DBus error message on failure
2263 * Handler function for "TDLSTeardown" method call of network interface.
2265 DBusMessage * wpas_dbus_handler_tdls_teardown(DBusMessage *message,
2266 struct wpa_supplicant *wpa_s)
2269 DBusMessage *error_reply;
2272 if (get_peer_hwaddr_helper(message, __func__, peer, &error_reply) < 0)
2275 wpa_printf(MSG_DEBUG, "DBUS TDLS_TEARDOWN " MACSTR, MAC2STR(peer));
2277 if (wpa_tdls_is_external_setup(wpa_s->wpa))
2278 ret = wpa_tdls_teardown_link(
2280 WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
2282 ret = wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
2285 return wpas_dbus_error_unknown_error(
2286 message, "error performing TDLS teardown");
2292 #endif /* CONFIG_TDLS */
2296 * wpas_dbus_handler_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
2297 * @message: Pointer to incoming dbus message
2298 * @wpa_s: %wpa_supplicant data structure
2299 * Returns: A dbus message containing an error on failure or NULL on success
2301 * Sets the PKCS #11 engine and module path.
2303 DBusMessage * wpas_dbus_handler_set_pkcs11_engine_and_module_path(
2304 DBusMessage *message, struct wpa_supplicant *wpa_s)
2306 DBusMessageIter iter;
2308 char *pkcs11_engine_path = NULL;
2309 char *pkcs11_module_path = NULL;
2311 dbus_message_iter_init(message, &iter);
2312 dbus_message_iter_get_basic(&iter, &value);
2313 if (value == NULL) {
2314 return dbus_message_new_error(
2315 message, DBUS_ERROR_INVALID_ARGS,
2316 "Invalid pkcs11_engine_path argument");
2318 /* Empty path defaults to NULL */
2319 if (os_strlen(value))
2320 pkcs11_engine_path = value;
2322 dbus_message_iter_next(&iter);
2323 dbus_message_iter_get_basic(&iter, &value);
2324 if (value == NULL) {
2325 os_free(pkcs11_engine_path);
2326 return dbus_message_new_error(
2327 message, DBUS_ERROR_INVALID_ARGS,
2328 "Invalid pkcs11_module_path argument");
2330 /* Empty path defaults to NULL */
2331 if (os_strlen(value))
2332 pkcs11_module_path = value;
2334 if (wpas_set_pkcs11_engine_and_module_path(wpa_s, pkcs11_engine_path,
2335 pkcs11_module_path))
2336 return dbus_message_new_error(
2337 message, DBUS_ERROR_FAILED,
2338 "Reinit of the EAPOL state machine with the new PKCS #11 engine and module path failed.");
2340 if (wpa_s->dbus_new_path) {
2341 wpa_dbus_mark_property_changed(
2342 wpa_s->global->dbus, wpa_s->dbus_new_path,
2343 WPAS_DBUS_NEW_IFACE_INTERFACE, "PKCS11EnginePath");
2344 wpa_dbus_mark_property_changed(
2345 wpa_s->global->dbus, wpa_s->dbus_new_path,
2346 WPAS_DBUS_NEW_IFACE_INTERFACE, "PKCS11ModulePath");
2354 * wpas_dbus_getter_capabilities - Return interface capabilities
2355 * @iter: Pointer to incoming dbus message iter
2356 * @error: Location to store error on failure
2357 * @user_data: Function specific data
2358 * Returns: TRUE on success, FALSE on failure
2360 * Getter for "Capabilities" property of an interface.
2362 dbus_bool_t wpas_dbus_getter_capabilities(DBusMessageIter *iter,
2363 DBusError *error, void *user_data)
2365 struct wpa_supplicant *wpa_s = user_data;
2366 struct wpa_driver_capa capa;
2368 DBusMessageIter iter_dict, iter_dict_entry, iter_dict_val, iter_array,
2370 const char *scans[] = { "active", "passive", "ssid" };
2372 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
2373 "a{sv}", &variant_iter) ||
2374 !wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
2377 res = wpa_drv_get_capa(wpa_s, &capa);
2379 /***** pairwise cipher */
2381 const char *args[] = {"ccmp", "tkip", "none"};
2383 if (!wpa_dbus_dict_append_string_array(
2384 &iter_dict, "Pairwise", args,
2388 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Pairwise",
2392 ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP_256) &&
2393 !wpa_dbus_dict_string_array_add_element(
2394 &iter_array, "ccmp-256")) ||
2395 ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP_256) &&
2396 !wpa_dbus_dict_string_array_add_element(
2397 &iter_array, "gcmp-256")) ||
2398 ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) &&
2399 !wpa_dbus_dict_string_array_add_element(
2400 &iter_array, "ccmp")) ||
2401 ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP) &&
2402 !wpa_dbus_dict_string_array_add_element(
2403 &iter_array, "gcmp")) ||
2404 ((capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) &&
2405 !wpa_dbus_dict_string_array_add_element(
2406 &iter_array, "tkip")) ||
2407 ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) &&
2408 !wpa_dbus_dict_string_array_add_element(
2409 &iter_array, "none")) ||
2410 !wpa_dbus_dict_end_string_array(&iter_dict,
2417 /***** group cipher */
2419 const char *args[] = {
2420 "ccmp", "tkip", "wep104", "wep40"
2423 if (!wpa_dbus_dict_append_string_array(
2424 &iter_dict, "Group", args,
2428 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Group",
2432 ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP_256) &&
2433 !wpa_dbus_dict_string_array_add_element(
2434 &iter_array, "ccmp-256")) ||
2435 ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP_256) &&
2436 !wpa_dbus_dict_string_array_add_element(
2437 &iter_array, "gcmp-256")) ||
2438 ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) &&
2439 !wpa_dbus_dict_string_array_add_element(
2440 &iter_array, "ccmp")) ||
2441 ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP) &&
2442 !wpa_dbus_dict_string_array_add_element(
2443 &iter_array, "gcmp")) ||
2444 ((capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) &&
2445 !wpa_dbus_dict_string_array_add_element(
2446 &iter_array, "tkip")) ||
2447 ((capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) &&
2448 !wpa_dbus_dict_string_array_add_element(
2449 &iter_array, "wep104")) ||
2450 ((capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) &&
2451 !wpa_dbus_dict_string_array_add_element(
2452 &iter_array, "wep40")) ||
2453 !wpa_dbus_dict_end_string_array(&iter_dict,
2460 /***** key management */
2462 const char *args[] = {
2463 "wpa-psk", "wpa-eap", "ieee8021x", "wpa-none",
2466 #endif /* CONFIG_WPS */
2469 if (!wpa_dbus_dict_append_string_array(
2470 &iter_dict, "KeyMgmt", args,
2474 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "KeyMgmt",
2478 !wpa_dbus_dict_string_array_add_element(&iter_array,
2480 !wpa_dbus_dict_string_array_add_element(&iter_array,
2484 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
2485 WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
2486 if (!wpa_dbus_dict_string_array_add_element(
2487 &iter_array, "wpa-eap") ||
2488 ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT) &&
2489 !wpa_dbus_dict_string_array_add_element(
2490 &iter_array, "wpa-ft-eap")))
2493 /* TODO: Ensure that driver actually supports sha256 encryption. */
2494 #ifdef CONFIG_IEEE80211W
2495 if (!wpa_dbus_dict_string_array_add_element(
2496 &iter_array, "wpa-eap-sha256"))
2498 #endif /* CONFIG_IEEE80211W */
2501 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
2502 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
2503 if (!wpa_dbus_dict_string_array_add_element(
2504 &iter_array, "wpa-psk") ||
2506 WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK) &&
2507 !wpa_dbus_dict_string_array_add_element(
2508 &iter_array, "wpa-ft-psk")))
2511 /* TODO: Ensure that driver actually supports sha256 encryption. */
2512 #ifdef CONFIG_IEEE80211W
2513 if (!wpa_dbus_dict_string_array_add_element(
2514 &iter_array, "wpa-psk-sha256"))
2516 #endif /* CONFIG_IEEE80211W */
2519 if ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) &&
2520 !wpa_dbus_dict_string_array_add_element(&iter_array,
2526 if (!wpa_dbus_dict_string_array_add_element(&iter_array,
2529 #endif /* CONFIG_WPS */
2531 if (!wpa_dbus_dict_end_string_array(&iter_dict,
2538 /***** WPA protocol */
2540 const char *args[] = { "rsn", "wpa" };
2542 if (!wpa_dbus_dict_append_string_array(
2543 &iter_dict, "Protocol", args,
2547 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Protocol",
2551 ((capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
2552 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) &&
2553 !wpa_dbus_dict_string_array_add_element(
2554 &iter_array, "rsn")) ||
2555 ((capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
2556 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) &&
2557 !wpa_dbus_dict_string_array_add_element(
2558 &iter_array, "wpa")) ||
2559 !wpa_dbus_dict_end_string_array(&iter_dict,
2568 const char *args[] = { "open", "shared", "leap" };
2570 if (!wpa_dbus_dict_append_string_array(
2571 &iter_dict, "AuthAlg", args,
2575 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "AuthAlg",
2581 if (((capa.auth & WPA_DRIVER_AUTH_OPEN) &&
2582 !wpa_dbus_dict_string_array_add_element(
2583 &iter_array, "open")) ||
2584 ((capa.auth & WPA_DRIVER_AUTH_SHARED) &&
2585 !wpa_dbus_dict_string_array_add_element(
2586 &iter_array, "shared")) ||
2587 ((capa.auth & WPA_DRIVER_AUTH_LEAP) &&
2588 !wpa_dbus_dict_string_array_add_element(
2589 &iter_array, "leap")) ||
2590 !wpa_dbus_dict_end_string_array(&iter_dict,
2598 if (!wpa_dbus_dict_append_string_array(&iter_dict, "Scan", scans,
2603 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Modes",
2607 !wpa_dbus_dict_string_array_add_element(
2608 &iter_array, "infrastructure") ||
2609 !wpa_dbus_dict_string_array_add_element(
2610 &iter_array, "ad-hoc") ||
2611 (res >= 0 && (capa.flags & WPA_DRIVER_FLAGS_AP) &&
2612 !wpa_dbus_dict_string_array_add_element(
2613 &iter_array, "ap")) ||
2614 (res >= 0 && (capa.flags & WPA_DRIVER_FLAGS_P2P_CAPABLE) &&
2615 !wpa_dbus_dict_string_array_add_element(
2616 &iter_array, "p2p")) ||
2617 !wpa_dbus_dict_end_string_array(&iter_dict,
2625 dbus_int32_t max_scan_ssid = capa.max_scan_ssids;
2627 if (!wpa_dbus_dict_append_int32(&iter_dict, "MaxScanSSID",
2632 if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict) ||
2633 !dbus_message_iter_close_container(iter, &variant_iter))
2639 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
2645 * wpas_dbus_getter_state - Get interface state
2646 * @iter: Pointer to incoming dbus message iter
2647 * @error: Location to store error on failure
2648 * @user_data: Function specific data
2649 * Returns: TRUE on success, FALSE on failure
2651 * Getter for "State" property.
2653 dbus_bool_t wpas_dbus_getter_state(DBusMessageIter *iter, DBusError *error,
2656 struct wpa_supplicant *wpa_s = user_data;
2657 const char *str_state;
2658 char *state_ls, *tmp;
2659 dbus_bool_t success = FALSE;
2661 str_state = wpa_supplicant_state_txt(wpa_s->wpa_state);
2663 /* make state string lowercase to fit new DBus API convention
2665 state_ls = tmp = os_strdup(str_state);
2667 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
2671 *tmp = tolower(*tmp);
2675 success = wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
2685 * wpas_dbus_new_iface_get_scanning - Get interface scanning state
2686 * @iter: Pointer to incoming dbus message iter
2687 * @error: Location to store error on failure
2688 * @user_data: Function specific data
2689 * Returns: TRUE on success, FALSE on failure
2691 * Getter for "scanning" property.
2693 dbus_bool_t wpas_dbus_getter_scanning(DBusMessageIter *iter, DBusError *error,
2696 struct wpa_supplicant *wpa_s = user_data;
2697 dbus_bool_t scanning = wpa_s->scanning ? TRUE : FALSE;
2699 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
2705 * wpas_dbus_getter_ap_scan - Control roaming mode
2706 * @iter: Pointer to incoming dbus message iter
2707 * @error: Location to store error on failure
2708 * @user_data: Function specific data
2709 * Returns: TRUE on success, FALSE on failure
2711 * Getter function for "ApScan" property.
2713 dbus_bool_t wpas_dbus_getter_ap_scan(DBusMessageIter *iter, DBusError *error,
2716 struct wpa_supplicant *wpa_s = user_data;
2717 dbus_uint32_t ap_scan = wpa_s->conf->ap_scan;
2719 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
2725 * wpas_dbus_setter_ap_scan - Control roaming mode
2726 * @iter: Pointer to incoming dbus message iter
2727 * @error: Location to store error on failure
2728 * @user_data: Function specific data
2729 * Returns: TRUE on success, FALSE on failure
2731 * Setter function for "ApScan" property.
2733 dbus_bool_t wpas_dbus_setter_ap_scan(DBusMessageIter *iter, DBusError *error,
2736 struct wpa_supplicant *wpa_s = user_data;
2737 dbus_uint32_t ap_scan;
2739 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
2743 if (wpa_supplicant_set_ap_scan(wpa_s, ap_scan)) {
2744 dbus_set_error_const(error, DBUS_ERROR_FAILED,
2745 "ap_scan must be 0, 1, or 2");
2753 * wpas_dbus_getter_fast_reauth - Control fast
2754 * reauthentication (TLS session resumption)
2755 * @iter: Pointer to incoming dbus message iter
2756 * @error: Location to store error on failure
2757 * @user_data: Function specific data
2758 * Returns: TRUE on success, FALSE on failure
2760 * Getter function for "FastReauth" property.
2762 dbus_bool_t wpas_dbus_getter_fast_reauth(DBusMessageIter *iter,
2766 struct wpa_supplicant *wpa_s = user_data;
2767 dbus_bool_t fast_reauth = wpa_s->conf->fast_reauth ? TRUE : FALSE;
2769 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
2770 &fast_reauth, error);
2775 * wpas_dbus_setter_fast_reauth - Control fast
2776 * reauthentication (TLS session resumption)
2777 * @iter: Pointer to incoming dbus message iter
2778 * @error: Location to store error on failure
2779 * @user_data: Function specific data
2780 * Returns: TRUE on success, FALSE on failure
2782 * Setter function for "FastReauth" property.
2784 dbus_bool_t wpas_dbus_setter_fast_reauth(DBusMessageIter *iter,
2788 struct wpa_supplicant *wpa_s = user_data;
2789 dbus_bool_t fast_reauth;
2791 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
2795 wpa_s->conf->fast_reauth = fast_reauth;
2801 * wpas_dbus_getter_disconnect_reason - Get most recent reason for disconnect
2802 * @iter: Pointer to incoming dbus message iter
2803 * @error: Location to store error on failure
2804 * @user_data: Function specific data
2805 * Returns: TRUE on success, FALSE on failure
2807 * Getter for "DisconnectReason" property. The reason is negative if it is
2808 * locally generated.
2810 dbus_bool_t wpas_dbus_getter_disconnect_reason(DBusMessageIter *iter,
2814 struct wpa_supplicant *wpa_s = user_data;
2815 dbus_int32_t reason = wpa_s->disconnect_reason;
2817 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
2823 * wpas_dbus_getter_bss_expire_age - Get BSS entry expiration age
2824 * @iter: Pointer to incoming dbus message iter
2825 * @error: Location to store error on failure
2826 * @user_data: Function specific data
2827 * Returns: TRUE on success, FALSE on failure
2829 * Getter function for "BSSExpireAge" property.
2831 dbus_bool_t wpas_dbus_getter_bss_expire_age(DBusMessageIter *iter,
2835 struct wpa_supplicant *wpa_s = user_data;
2836 dbus_uint32_t expire_age = wpa_s->conf->bss_expiration_age;
2838 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
2839 &expire_age, error);
2844 * wpas_dbus_setter_bss_expire_age - Control BSS entry expiration age
2845 * @iter: Pointer to incoming dbus message iter
2846 * @error: Location to store error on failure
2847 * @user_data: Function specific data
2848 * Returns: TRUE on success, FALSE on failure
2850 * Setter function for "BSSExpireAge" property.
2852 dbus_bool_t wpas_dbus_setter_bss_expire_age(DBusMessageIter *iter,
2856 struct wpa_supplicant *wpa_s = user_data;
2857 dbus_uint32_t expire_age;
2859 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
2863 if (wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age)) {
2864 dbus_set_error_const(error, DBUS_ERROR_FAILED,
2865 "BSSExpireAge must be >= 10");
2873 * wpas_dbus_getter_bss_expire_count - Get BSS entry expiration scan count
2874 * @iter: Pointer to incoming dbus message iter
2875 * @error: Location to store error on failure
2876 * @user_data: Function specific data
2877 * Returns: TRUE on success, FALSE on failure
2879 * Getter function for "BSSExpireCount" property.
2881 dbus_bool_t wpas_dbus_getter_bss_expire_count(DBusMessageIter *iter,
2885 struct wpa_supplicant *wpa_s = user_data;
2886 dbus_uint32_t expire_count = wpa_s->conf->bss_expiration_scan_count;
2888 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
2889 &expire_count, error);
2894 * wpas_dbus_setter_bss_expire_count - Control BSS entry expiration scan count
2895 * @iter: Pointer to incoming dbus message iter
2896 * @error: Location to store error on failure
2897 * @user_data: Function specific data
2898 * Returns: TRUE on success, FALSE on failure
2900 * Setter function for "BSSExpireCount" property.
2902 dbus_bool_t wpas_dbus_setter_bss_expire_count(DBusMessageIter *iter,
2906 struct wpa_supplicant *wpa_s = user_data;
2907 dbus_uint32_t expire_count;
2909 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
2913 if (wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count)) {
2914 dbus_set_error_const(error, DBUS_ERROR_FAILED,
2915 "BSSExpireCount must be > 0");
2923 * wpas_dbus_getter_country - Control country code
2924 * @iter: Pointer to incoming dbus message iter
2925 * @error: Location to store error on failure
2926 * @user_data: Function specific data
2927 * Returns: TRUE on success, FALSE on failure
2929 * Getter function for "Country" property.
2931 dbus_bool_t wpas_dbus_getter_country(DBusMessageIter *iter, DBusError *error,
2934 struct wpa_supplicant *wpa_s = user_data;
2936 char *str = country;
2938 country[0] = wpa_s->conf->country[0];
2939 country[1] = wpa_s->conf->country[1];
2942 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
2948 * wpas_dbus_setter_country - Control country code
2949 * @iter: Pointer to incoming dbus message iter
2950 * @error: Location to store error on failure
2951 * @user_data: Function specific data
2952 * Returns: TRUE on success, FALSE on failure
2954 * Setter function for "Country" property.
2956 dbus_bool_t wpas_dbus_setter_country(DBusMessageIter *iter, DBusError *error,
2959 struct wpa_supplicant *wpa_s = user_data;
2960 const char *country;
2962 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
2966 if (!country[0] || !country[1]) {
2967 dbus_set_error_const(error, DBUS_ERROR_FAILED,
2968 "invalid country code");
2972 if (wpa_s->drv_priv != NULL && wpa_drv_set_country(wpa_s, country)) {
2973 wpa_printf(MSG_DEBUG, "Failed to set country");
2974 dbus_set_error_const(error, DBUS_ERROR_FAILED,
2975 "failed to set country code");
2979 wpa_s->conf->country[0] = country[0];
2980 wpa_s->conf->country[1] = country[1];
2986 * wpas_dbus_getter_scan_interval - Get scan interval
2987 * @iter: Pointer to incoming dbus message iter
2988 * @error: Location to store error on failure
2989 * @user_data: Function specific data
2990 * Returns: TRUE on success, FALSE on failure
2992 * Getter function for "ScanInterval" property.
2994 dbus_bool_t wpas_dbus_getter_scan_interval(DBusMessageIter *iter,
2998 struct wpa_supplicant *wpa_s = user_data;
2999 dbus_int32_t scan_interval = wpa_s->scan_interval;
3001 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
3002 &scan_interval, error);
3007 * wpas_dbus_setter_scan_interval - Control scan interval
3008 * @iter: Pointer to incoming dbus message iter
3009 * @error: Location to store error on failure
3010 * @user_data: Function specific data
3011 * Returns: TRUE on success, FALSE on failure
3013 * Setter function for "ScanInterval" property.
3015 dbus_bool_t wpas_dbus_setter_scan_interval(DBusMessageIter *iter,
3019 struct wpa_supplicant *wpa_s = user_data;
3020 dbus_int32_t scan_interval;
3022 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_INT32,
3026 if (wpa_supplicant_set_scan_interval(wpa_s, scan_interval)) {
3027 dbus_set_error_const(error, DBUS_ERROR_FAILED,
3028 "scan_interval must be >= 0");
3036 * wpas_dbus_getter_ifname - Get interface name
3037 * @iter: Pointer to incoming dbus message iter
3038 * @error: Location to store error on failure
3039 * @user_data: Function specific data
3040 * Returns: TRUE on success, FALSE on failure
3042 * Getter for "Ifname" property.
3044 dbus_bool_t wpas_dbus_getter_ifname(DBusMessageIter *iter, DBusError *error,
3047 struct wpa_supplicant *wpa_s = user_data;
3048 const char *ifname = wpa_s->ifname;
3050 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3056 * wpas_dbus_getter_driver - Get interface name
3057 * @iter: Pointer to incoming dbus message iter
3058 * @error: Location to store error on failure
3059 * @user_data: Function specific data
3060 * Returns: TRUE on success, FALSE on failure
3062 * Getter for "Driver" property.
3064 dbus_bool_t wpas_dbus_getter_driver(DBusMessageIter *iter, DBusError *error,
3067 struct wpa_supplicant *wpa_s = user_data;
3070 if (wpa_s->driver == NULL || wpa_s->driver->name == NULL) {
3071 wpa_printf(MSG_DEBUG, "%s[dbus]: wpa_s has no driver set",
3073 dbus_set_error(error, DBUS_ERROR_FAILED, "%s: no driver set",
3078 driver = wpa_s->driver->name;
3079 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3085 * wpas_dbus_getter_current_bss - Get current bss object path
3086 * @iter: Pointer to incoming dbus message iter
3087 * @error: Location to store error on failure
3088 * @user_data: Function specific data
3089 * Returns: TRUE on success, FALSE on failure
3091 * Getter for "CurrentBSS" property.
3093 dbus_bool_t wpas_dbus_getter_current_bss(DBusMessageIter *iter,
3097 struct wpa_supplicant *wpa_s = user_data;
3098 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *bss_obj_path = path_buf;
3100 if (wpa_s->current_bss && wpa_s->dbus_new_path)
3101 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3102 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
3103 wpa_s->dbus_new_path, wpa_s->current_bss->id);
3105 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
3107 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
3108 &bss_obj_path, error);
3113 * wpas_dbus_getter_current_network - Get current network object path
3114 * @iter: Pointer to incoming dbus message iter
3115 * @error: Location to store error on failure
3116 * @user_data: Function specific data
3117 * Returns: TRUE on success, FALSE on failure
3119 * Getter for "CurrentNetwork" property.
3121 dbus_bool_t wpas_dbus_getter_current_network(DBusMessageIter *iter,
3125 struct wpa_supplicant *wpa_s = user_data;
3126 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *net_obj_path = path_buf;
3128 if (wpa_s->current_ssid && wpa_s->dbus_new_path)
3129 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3130 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
3131 wpa_s->dbus_new_path, wpa_s->current_ssid->id);
3133 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
3135 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
3136 &net_obj_path, error);
3141 * wpas_dbus_getter_current_auth_mode - Get current authentication type
3142 * @iter: Pointer to incoming dbus message iter
3143 * @error: Location to store error on failure
3144 * @user_data: Function specific data
3145 * Returns: TRUE on success, FALSE on failure
3147 * Getter for "CurrentAuthMode" property.
3149 dbus_bool_t wpas_dbus_getter_current_auth_mode(DBusMessageIter *iter,
3153 struct wpa_supplicant *wpa_s = user_data;
3154 const char *eap_mode;
3155 const char *auth_mode;
3156 char eap_mode_buf[WPAS_DBUS_AUTH_MODE_MAX];
3158 if (wpa_s->wpa_state != WPA_COMPLETED) {
3159 auth_mode = "INACTIVE";
3160 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X ||
3161 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3162 eap_mode = wpa_supplicant_get_eap_mode(wpa_s);
3163 os_snprintf(eap_mode_buf, WPAS_DBUS_AUTH_MODE_MAX,
3164 "EAP-%s", eap_mode);
3165 auth_mode = eap_mode_buf;
3168 auth_mode = wpa_key_mgmt_txt(wpa_s->key_mgmt,
3169 wpa_s->current_ssid->proto);
3172 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3178 * wpas_dbus_getter_bridge_ifname - Get interface name
3179 * @iter: Pointer to incoming dbus message iter
3180 * @error: Location to store error on failure
3181 * @user_data: Function specific data
3182 * Returns: TRUE on success, FALSE on failure
3184 * Getter for "BridgeIfname" property.
3186 dbus_bool_t wpas_dbus_getter_bridge_ifname(DBusMessageIter *iter,
3190 struct wpa_supplicant *wpa_s = user_data;
3191 const char *bridge_ifname = wpa_s->bridge_ifname;
3193 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3194 &bridge_ifname, error);
3199 * wpas_dbus_getter_bsss - Get array of BSSs objects
3200 * @iter: Pointer to incoming dbus message iter
3201 * @error: Location to store error on failure
3202 * @user_data: Function specific data
3203 * Returns: TRUE on success, FALSE on failure
3205 * Getter for "BSSs" property.
3207 dbus_bool_t wpas_dbus_getter_bsss(DBusMessageIter *iter, DBusError *error,
3210 struct wpa_supplicant *wpa_s = user_data;
3211 struct wpa_bss *bss;
3214 dbus_bool_t success = FALSE;
3216 if (!wpa_s->dbus_new_path) {
3217 dbus_set_error(error, DBUS_ERROR_FAILED,
3218 "%s: no D-Bus interface", __func__);
3222 paths = os_calloc(wpa_s->num_bss, sizeof(char *));
3224 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3228 /* Loop through scan results and append each result's object path */
3229 dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
3230 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
3231 if (paths[i] == NULL) {
3232 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
3236 /* Construct the object path for this BSS. */
3237 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
3238 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
3239 wpa_s->dbus_new_path, bss->id);
3242 success = wpas_dbus_simple_array_property_getter(iter,
3243 DBUS_TYPE_OBJECT_PATH,
3244 paths, wpa_s->num_bss,
3249 os_free(paths[--i]);
3256 * wpas_dbus_getter_networks - Get array of networks objects
3257 * @iter: Pointer to incoming dbus message iter
3258 * @error: Location to store error on failure
3259 * @user_data: Function specific data
3260 * Returns: TRUE on success, FALSE on failure
3262 * Getter for "Networks" property.
3264 dbus_bool_t wpas_dbus_getter_networks(DBusMessageIter *iter, DBusError *error,
3267 struct wpa_supplicant *wpa_s = user_data;
3268 struct wpa_ssid *ssid;
3270 unsigned int i = 0, num = 0;
3271 dbus_bool_t success = FALSE;
3273 if (!wpa_s->dbus_new_path) {
3274 dbus_set_error(error, DBUS_ERROR_FAILED,
3275 "%s: no D-Bus interface", __func__);
3279 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
3280 if (!network_is_persistent_group(ssid))
3283 paths = os_calloc(num, sizeof(char *));
3285 dbus_set_error(error, DBUS_ERROR_NO_MEMORY, "no memory");
3289 /* Loop through configured networks and append object path of each */
3290 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
3291 if (network_is_persistent_group(ssid))
3293 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
3294 if (paths[i] == NULL) {
3295 dbus_set_error(error, DBUS_ERROR_NO_MEMORY,
3300 /* Construct the object path for this network. */
3301 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
3302 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
3303 wpa_s->dbus_new_path, ssid->id);
3306 success = wpas_dbus_simple_array_property_getter(iter,
3307 DBUS_TYPE_OBJECT_PATH,
3312 os_free(paths[--i]);
3319 * wpas_dbus_getter_pkcs11_engine_path - Get PKCS #11 engine path
3320 * @iter: Pointer to incoming dbus message iter
3321 * @error: Location to store error on failure
3322 * @user_data: Function specific data
3323 * Returns: A dbus message containing the PKCS #11 engine path
3325 * Getter for "PKCS11EnginePath" property.
3327 dbus_bool_t wpas_dbus_getter_pkcs11_engine_path(DBusMessageIter *iter,
3331 struct wpa_supplicant *wpa_s = user_data;
3332 const char *pkcs11_engine_path;
3334 if (wpa_s->conf->pkcs11_engine_path == NULL)
3335 pkcs11_engine_path = "";
3337 pkcs11_engine_path = wpa_s->conf->pkcs11_engine_path;
3338 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3339 &pkcs11_engine_path, error);
3344 * wpas_dbus_getter_pkcs11_module_path - Get PKCS #11 module path
3345 * @iter: Pointer to incoming dbus message iter
3346 * @error: Location to store error on failure
3347 * @user_data: Function specific data
3348 * Returns: A dbus message containing the PKCS #11 module path
3350 * Getter for "PKCS11ModulePath" property.
3352 dbus_bool_t wpas_dbus_getter_pkcs11_module_path(DBusMessageIter *iter,
3356 struct wpa_supplicant *wpa_s = user_data;
3357 const char *pkcs11_module_path;
3359 if (wpa_s->conf->pkcs11_module_path == NULL)
3360 pkcs11_module_path = "";
3362 pkcs11_module_path = wpa_s->conf->pkcs11_module_path;
3363 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3364 &pkcs11_module_path, error);
3369 * wpas_dbus_getter_blobs - Get all blobs defined for this interface
3370 * @iter: Pointer to incoming dbus message iter
3371 * @error: Location to store error on failure
3372 * @user_data: Function specific data
3373 * Returns: TRUE on success, FALSE on failure
3375 * Getter for "Blobs" property.
3377 dbus_bool_t wpas_dbus_getter_blobs(DBusMessageIter *iter, DBusError *error,
3380 struct wpa_supplicant *wpa_s = user_data;
3381 DBusMessageIter variant_iter, dict_iter, entry_iter, array_iter;
3382 struct wpa_config_blob *blob;
3384 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
3385 "a{say}", &variant_iter) ||
3386 !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
3387 "{say}", &dict_iter)) {
3388 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3392 blob = wpa_s->conf->blobs;
3394 if (!dbus_message_iter_open_container(&dict_iter,
3395 DBUS_TYPE_DICT_ENTRY,
3396 NULL, &entry_iter) ||
3397 !dbus_message_iter_append_basic(&entry_iter,
3400 !dbus_message_iter_open_container(&entry_iter,
3402 DBUS_TYPE_BYTE_AS_STRING,
3404 !dbus_message_iter_append_fixed_array(&array_iter,
3408 !dbus_message_iter_close_container(&entry_iter,
3410 !dbus_message_iter_close_container(&dict_iter,
3412 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
3420 if (!dbus_message_iter_close_container(&variant_iter, &dict_iter) ||
3421 !dbus_message_iter_close_container(iter, &variant_iter)) {
3422 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3430 static struct wpa_bss * get_bss_helper(struct bss_handler_args *args,
3431 DBusError *error, const char *func_name)
3433 struct wpa_bss *res = wpa_bss_get_id(args->wpa_s, args->id);
3436 wpa_printf(MSG_ERROR, "%s[dbus]: no bss with id %d found",
3437 func_name, args->id);
3438 dbus_set_error(error, DBUS_ERROR_FAILED,
3439 "%s: BSS %d not found",
3440 func_name, args->id);
3448 * wpas_dbus_getter_bss_bssid - Return the BSSID of a BSS
3449 * @iter: Pointer to incoming dbus message iter
3450 * @error: Location to store error on failure
3451 * @user_data: Function specific data
3452 * Returns: TRUE on success, FALSE on failure
3454 * Getter for "BSSID" property.
3456 dbus_bool_t wpas_dbus_getter_bss_bssid(DBusMessageIter *iter, DBusError *error,
3459 struct bss_handler_args *args = user_data;
3460 struct wpa_bss *res;
3462 res = get_bss_helper(args, error, __func__);
3466 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
3467 res->bssid, ETH_ALEN,
3473 * wpas_dbus_getter_bss_ssid - Return the SSID of a BSS
3474 * @iter: Pointer to incoming dbus message iter
3475 * @error: Location to store error on failure
3476 * @user_data: Function specific data
3477 * Returns: TRUE on success, FALSE on failure
3479 * Getter for "SSID" property.
3481 dbus_bool_t wpas_dbus_getter_bss_ssid(DBusMessageIter *iter, DBusError *error,
3484 struct bss_handler_args *args = user_data;
3485 struct wpa_bss *res;
3487 res = get_bss_helper(args, error, __func__);
3491 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
3492 res->ssid, res->ssid_len,
3498 * wpas_dbus_getter_bss_privacy - Return the privacy flag of a BSS
3499 * @iter: Pointer to incoming dbus message iter
3500 * @error: Location to store error on failure
3501 * @user_data: Function specific data
3502 * Returns: TRUE on success, FALSE on failure
3504 * Getter for "Privacy" property.
3506 dbus_bool_t wpas_dbus_getter_bss_privacy(DBusMessageIter *iter,
3507 DBusError *error, void *user_data)
3509 struct bss_handler_args *args = user_data;
3510 struct wpa_bss *res;
3511 dbus_bool_t privacy;
3513 res = get_bss_helper(args, error, __func__);
3517 privacy = (res->caps & IEEE80211_CAP_PRIVACY) ? TRUE : FALSE;
3518 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
3524 * wpas_dbus_getter_bss_mode - Return the mode of a BSS
3525 * @iter: Pointer to incoming dbus message iter
3526 * @error: Location to store error on failure
3527 * @user_data: Function specific data
3528 * Returns: TRUE on success, FALSE on failure
3530 * Getter for "Mode" property.
3532 dbus_bool_t wpas_dbus_getter_bss_mode(DBusMessageIter *iter, DBusError *error,
3535 struct bss_handler_args *args = user_data;
3536 struct wpa_bss *res;
3539 res = get_bss_helper(args, error, __func__);
3542 if (bss_is_dmg(res)) {
3543 switch (res->caps & IEEE80211_CAP_DMG_MASK) {
3544 case IEEE80211_CAP_DMG_PBSS:
3545 case IEEE80211_CAP_DMG_IBSS:
3548 case IEEE80211_CAP_DMG_AP:
3549 mode = "infrastructure";
3553 if (res->caps & IEEE80211_CAP_IBSS)
3556 mode = "infrastructure";
3559 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3565 * wpas_dbus_getter_bss_level - Return the signal strength of a BSS
3566 * @iter: Pointer to incoming dbus message iter
3567 * @error: Location to store error on failure
3568 * @user_data: Function specific data
3569 * Returns: TRUE on success, FALSE on failure
3571 * Getter for "Level" property.
3573 dbus_bool_t wpas_dbus_getter_bss_signal(DBusMessageIter *iter,
3574 DBusError *error, void *user_data)
3576 struct bss_handler_args *args = user_data;
3577 struct wpa_bss *res;
3580 res = get_bss_helper(args, error, __func__);
3584 level = (s16) res->level;
3585 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT16,
3591 * wpas_dbus_getter_bss_frequency - Return the frequency of a BSS
3592 * @iter: Pointer to incoming dbus message iter
3593 * @error: Location to store error on failure
3594 * @user_data: Function specific data
3595 * Returns: TRUE on success, FALSE on failure
3597 * Getter for "Frequency" property.
3599 dbus_bool_t wpas_dbus_getter_bss_frequency(DBusMessageIter *iter,
3600 DBusError *error, void *user_data)
3602 struct bss_handler_args *args = user_data;
3603 struct wpa_bss *res;
3606 res = get_bss_helper(args, error, __func__);
3610 freq = (u16) res->freq;
3611 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
3616 static int cmp_u8s_desc(const void *a, const void *b)
3618 return (*(u8 *) b - *(u8 *) a);
3623 * wpas_dbus_getter_bss_rates - Return available bit rates of a BSS
3624 * @iter: Pointer to incoming dbus message iter
3625 * @error: Location to store error on failure
3626 * @user_data: Function specific data
3627 * Returns: TRUE on success, FALSE on failure
3629 * Getter for "Rates" property.
3631 dbus_bool_t wpas_dbus_getter_bss_rates(DBusMessageIter *iter,
3632 DBusError *error, void *user_data)
3634 struct bss_handler_args *args = user_data;
3635 struct wpa_bss *res;
3636 u8 *ie_rates = NULL;
3639 dbus_bool_t success = FALSE;
3641 res = get_bss_helper(args, error, __func__);
3645 rates_num = wpa_bss_get_bit_rates(res, &ie_rates);
3649 qsort(ie_rates, rates_num, 1, cmp_u8s_desc);
3651 real_rates = os_malloc(sizeof(u32) * rates_num);
3654 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3658 for (i = 0; i < rates_num; i++)
3659 real_rates[i] = ie_rates[i] * 500000;
3661 success = wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_UINT32,
3662 real_rates, rates_num,
3666 os_free(real_rates);
3671 static dbus_bool_t wpas_dbus_get_bss_security_prop(DBusMessageIter *iter,
3672 struct wpa_ie_data *ie_data,
3675 DBusMessageIter iter_dict, variant_iter;
3677 const char *pairwise[5]; /* max 5 pairwise ciphers is supported */
3678 const char *key_mgmt[9]; /* max 9 key managements may be supported */
3681 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
3682 "a{sv}", &variant_iter))
3685 if (!wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
3690 if (ie_data->key_mgmt & WPA_KEY_MGMT_PSK)
3691 key_mgmt[n++] = "wpa-psk";
3692 if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_PSK)
3693 key_mgmt[n++] = "wpa-ft-psk";
3694 if (ie_data->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
3695 key_mgmt[n++] = "wpa-psk-sha256";
3696 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X)
3697 key_mgmt[n++] = "wpa-eap";
3698 if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X)
3699 key_mgmt[n++] = "wpa-ft-eap";
3700 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256)
3701 key_mgmt[n++] = "wpa-eap-sha256";
3702 #ifdef CONFIG_SUITEB
3703 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B)
3704 key_mgmt[n++] = "wpa-eap-suite-b";
3705 #endif /* CONFIG_SUITEB */
3706 #ifdef CONFIG_SUITEB192
3707 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
3708 key_mgmt[n++] = "wpa-eap-suite-b-192";
3709 #endif /* CONFIG_SUITEB192 */
3710 if (ie_data->key_mgmt & WPA_KEY_MGMT_NONE)
3711 key_mgmt[n++] = "wpa-none";
3713 if (!wpa_dbus_dict_append_string_array(&iter_dict, "KeyMgmt",
3718 switch (ie_data->group_cipher) {
3719 case WPA_CIPHER_WEP40:
3722 case WPA_CIPHER_TKIP:
3725 case WPA_CIPHER_CCMP:
3728 case WPA_CIPHER_GCMP:
3731 case WPA_CIPHER_WEP104:
3734 case WPA_CIPHER_CCMP_256:
3737 case WPA_CIPHER_GCMP_256:
3745 if (!wpa_dbus_dict_append_string(&iter_dict, "Group", group))
3750 if (ie_data->pairwise_cipher & WPA_CIPHER_TKIP)
3751 pairwise[n++] = "tkip";
3752 if (ie_data->pairwise_cipher & WPA_CIPHER_CCMP)
3753 pairwise[n++] = "ccmp";
3754 if (ie_data->pairwise_cipher & WPA_CIPHER_GCMP)
3755 pairwise[n++] = "gcmp";
3756 if (ie_data->pairwise_cipher & WPA_CIPHER_CCMP_256)
3757 pairwise[n++] = "ccmp-256";
3758 if (ie_data->pairwise_cipher & WPA_CIPHER_GCMP_256)
3759 pairwise[n++] = "gcmp-256";
3761 if (!wpa_dbus_dict_append_string_array(&iter_dict, "Pairwise",
3765 /* Management group (RSN only) */
3766 if (ie_data->proto == WPA_PROTO_RSN) {
3767 switch (ie_data->mgmt_group_cipher) {
3768 #ifdef CONFIG_IEEE80211W
3769 case WPA_CIPHER_AES_128_CMAC:
3770 group = "aes128cmac";
3772 #endif /* CONFIG_IEEE80211W */
3778 if (!wpa_dbus_dict_append_string(&iter_dict, "MgmtGroup",
3783 if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict) ||
3784 !dbus_message_iter_close_container(iter, &variant_iter))
3790 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3796 * wpas_dbus_getter_bss_wpa - Return the WPA options of a BSS
3797 * @iter: Pointer to incoming dbus message iter
3798 * @error: Location to store error on failure
3799 * @user_data: Function specific data
3800 * Returns: TRUE on success, FALSE on failure
3802 * Getter for "WPA" property.
3804 dbus_bool_t wpas_dbus_getter_bss_wpa(DBusMessageIter *iter, DBusError *error,
3807 struct bss_handler_args *args = user_data;
3808 struct wpa_bss *res;
3809 struct wpa_ie_data wpa_data;
3812 res = get_bss_helper(args, error, __func__);
3816 os_memset(&wpa_data, 0, sizeof(wpa_data));
3817 ie = wpa_bss_get_vendor_ie(res, WPA_IE_VENDOR_TYPE);
3818 if (ie && wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0) {
3819 dbus_set_error_const(error, DBUS_ERROR_FAILED,
3820 "failed to parse WPA IE");
3824 return wpas_dbus_get_bss_security_prop(iter, &wpa_data, error);
3829 * wpas_dbus_getter_bss_rsn - Return the RSN options of a BSS
3830 * @iter: Pointer to incoming dbus message iter
3831 * @error: Location to store error on failure
3832 * @user_data: Function specific data
3833 * Returns: TRUE on success, FALSE on failure
3835 * Getter for "RSN" property.
3837 dbus_bool_t wpas_dbus_getter_bss_rsn(DBusMessageIter *iter, DBusError *error,
3840 struct bss_handler_args *args = user_data;
3841 struct wpa_bss *res;
3842 struct wpa_ie_data wpa_data;
3845 res = get_bss_helper(args, error, __func__);
3849 os_memset(&wpa_data, 0, sizeof(wpa_data));
3850 ie = wpa_bss_get_ie(res, WLAN_EID_RSN);
3851 if (ie && wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0) {
3852 dbus_set_error_const(error, DBUS_ERROR_FAILED,
3853 "failed to parse RSN IE");
3857 return wpas_dbus_get_bss_security_prop(iter, &wpa_data, error);
3862 * wpas_dbus_getter_bss_wps - Return the WPS options of a BSS
3863 * @iter: Pointer to incoming dbus message iter
3864 * @error: Location to store error on failure
3865 * @user_data: Function specific data
3866 * Returns: TRUE on success, FALSE on failure
3868 * Getter for "WPS" property.
3870 dbus_bool_t wpas_dbus_getter_bss_wps(DBusMessageIter *iter, DBusError *error,
3873 struct bss_handler_args *args = user_data;
3874 struct wpa_bss *res;
3876 struct wpabuf *wps_ie;
3877 #endif /* CONFIG_WPS */
3878 DBusMessageIter iter_dict, variant_iter;
3879 int wps_support = 0;
3880 const char *type = "";
3882 res = get_bss_helper(args, error, __func__);
3886 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
3887 "a{sv}", &variant_iter) ||
3888 !wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
3892 wps_ie = wpa_bss_get_vendor_ie_multi(res, WPS_IE_VENDOR_TYPE);
3895 if (wps_is_selected_pbc_registrar(wps_ie))
3897 else if (wps_is_selected_pin_registrar(wps_ie))
3900 wpabuf_free(wps_ie);
3902 #endif /* CONFIG_WPS */
3904 if ((wps_support && !wpa_dbus_dict_append_string(&iter_dict, "Type", type)) ||
3905 !wpa_dbus_dict_close_write(&variant_iter, &iter_dict) ||
3906 !dbus_message_iter_close_container(iter, &variant_iter))
3912 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3918 * wpas_dbus_getter_bss_ies - Return all IEs of a BSS
3919 * @iter: Pointer to incoming dbus message iter
3920 * @error: Location to store error on failure
3921 * @user_data: Function specific data
3922 * Returns: TRUE on success, FALSE on failure
3924 * Getter for "IEs" property.
3926 dbus_bool_t wpas_dbus_getter_bss_ies(DBusMessageIter *iter, DBusError *error,
3929 struct bss_handler_args *args = user_data;
3930 struct wpa_bss *res;
3932 res = get_bss_helper(args, error, __func__);
3936 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
3937 res + 1, res->ie_len,
3943 * wpas_dbus_getter_bss_age - Return time in seconds since BSS was last seen
3944 * @iter: Pointer to incoming dbus message iter
3945 * @error: Location to store error on failure
3946 * @user_data: Function specific data
3947 * Returns: TRUE on success, FALSE on failure
3949 * Getter for BSS age
3951 dbus_bool_t wpas_dbus_getter_bss_age(DBusMessageIter *iter, DBusError *error,
3954 struct bss_handler_args *args = user_data;
3955 struct wpa_bss *res;
3956 struct os_reltime now, diff = { 0, 0 };
3959 res = get_bss_helper(args, error, __func__);
3963 os_get_reltime(&now);
3964 os_reltime_sub(&now, &res->last_update, &diff);
3965 age = diff.sec > 0 ? diff.sec : 0;
3966 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32, &age,
3972 * wpas_dbus_getter_enabled - Check whether network is enabled or disabled
3973 * @iter: Pointer to incoming dbus message iter
3974 * @error: Location to store error on failure
3975 * @user_data: Function specific data
3976 * Returns: TRUE on success, FALSE on failure
3978 * Getter for "enabled" property of a configured network.
3980 dbus_bool_t wpas_dbus_getter_enabled(DBusMessageIter *iter, DBusError *error,
3983 struct network_handler_args *net = user_data;
3984 dbus_bool_t enabled = net->ssid->disabled ? FALSE : TRUE;
3986 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
3992 * wpas_dbus_setter_enabled - Mark a configured network as enabled or disabled
3993 * @iter: Pointer to incoming dbus message iter
3994 * @error: Location to store error on failure
3995 * @user_data: Function specific data
3996 * Returns: TRUE on success, FALSE on failure
3998 * Setter for "Enabled" property of a configured network.
4000 dbus_bool_t wpas_dbus_setter_enabled(DBusMessageIter *iter, DBusError *error,
4003 struct network_handler_args *net = user_data;
4004 struct wpa_supplicant *wpa_s;
4005 struct wpa_ssid *ssid;
4008 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
4016 wpa_supplicant_enable_network(wpa_s, ssid);
4018 wpa_supplicant_disable_network(wpa_s, ssid);
4025 * wpas_dbus_getter_network_properties - Get options for a configured network
4026 * @iter: Pointer to incoming dbus message iter
4027 * @error: Location to store error on failure
4028 * @user_data: Function specific data
4029 * Returns: TRUE on success, FALSE on failure
4031 * Getter for "Properties" property of a configured network.
4033 dbus_bool_t wpas_dbus_getter_network_properties(DBusMessageIter *iter,
4037 struct network_handler_args *net = user_data;
4038 DBusMessageIter variant_iter, dict_iter;
4040 char **props = wpa_config_get_all(net->ssid, 1);
4041 dbus_bool_t success = FALSE;
4044 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
4048 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a{sv}",
4050 !wpa_dbus_dict_open_write(&variant_iter, &dict_iter)) {
4051 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
4057 if (!wpa_dbus_dict_append_string(&dict_iter, *iterator,
4059 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
4067 if (!wpa_dbus_dict_close_write(&variant_iter, &dict_iter) ||
4068 !dbus_message_iter_close_container(iter, &variant_iter)) {
4069 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
4087 * wpas_dbus_setter_network_properties - Set options for a configured network
4088 * @iter: Pointer to incoming dbus message iter
4089 * @error: Location to store error on failure
4090 * @user_data: Function specific data
4091 * Returns: TRUE on success, FALSE on failure
4093 * Setter for "Properties" property of a configured network.
4095 dbus_bool_t wpas_dbus_setter_network_properties(DBusMessageIter *iter,
4099 struct network_handler_args *net = user_data;
4100 struct wpa_ssid *ssid = net->ssid;
4101 DBusMessageIter variant_iter;
4103 dbus_message_iter_recurse(iter, &variant_iter);
4104 return set_network_properties(net->wpa_s, ssid, &variant_iter, error);
4110 DBusMessage * wpas_dbus_handler_subscribe_preq(
4111 DBusMessage *message, struct wpa_supplicant *wpa_s)
4113 struct wpas_dbus_priv *priv = wpa_s->global->dbus;
4116 if (wpa_s->preq_notify_peer != NULL) {
4117 if (os_strcmp(dbus_message_get_sender(message),
4118 wpa_s->preq_notify_peer) == 0)
4121 return dbus_message_new_error(message,
4122 WPAS_DBUS_ERROR_SUBSCRIPTION_IN_USE,
4123 "Another application is already subscribed");
4126 name = os_strdup(dbus_message_get_sender(message));
4128 return wpas_dbus_error_no_memory(message);
4130 wpa_s->preq_notify_peer = name;
4132 /* Subscribe to clean up if application closes socket */
4133 wpas_dbus_subscribe_noc(priv);
4136 * Double-check it's still alive to make sure that we didn't
4137 * miss the NameOwnerChanged signal, e.g. while strdup'ing.
4139 if (!dbus_bus_name_has_owner(priv->con, name, NULL)) {
4141 * Application no longer exists, clean up.
4142 * The return value is irrelevant now.
4144 * Need to check if the NameOwnerChanged handling
4145 * already cleaned up because we have processed
4146 * DBus messages while checking if the name still
4149 if (!wpa_s->preq_notify_peer)
4151 os_free(wpa_s->preq_notify_peer);
4152 wpa_s->preq_notify_peer = NULL;
4153 wpas_dbus_unsubscribe_noc(priv);
4160 DBusMessage * wpas_dbus_handler_unsubscribe_preq(
4161 DBusMessage *message, struct wpa_supplicant *wpa_s)
4163 struct wpas_dbus_priv *priv = wpa_s->global->dbus;
4165 if (!wpa_s->preq_notify_peer)
4166 return dbus_message_new_error(message,
4167 WPAS_DBUS_ERROR_NO_SUBSCRIPTION,
4170 if (os_strcmp(wpa_s->preq_notify_peer,
4171 dbus_message_get_sender(message)))
4172 return dbus_message_new_error(message,
4173 WPAS_DBUS_ERROR_SUBSCRIPTION_EPERM,
4174 "Can't unsubscribe others");
4176 os_free(wpa_s->preq_notify_peer);
4177 wpa_s->preq_notify_peer = NULL;
4178 wpas_dbus_unsubscribe_noc(priv);
4183 void wpas_dbus_signal_preq(struct wpa_supplicant *wpa_s,
4184 const u8 *addr, const u8 *dst, const u8 *bssid,
4185 const u8 *ie, size_t ie_len, u32 ssi_signal)
4188 DBusMessageIter iter, dict_iter;
4189 struct wpas_dbus_priv *priv = wpa_s->global->dbus;
4191 /* Do nothing if the control interface is not turned on */
4192 if (priv == NULL || !wpa_s->dbus_new_path)
4195 if (wpa_s->preq_notify_peer == NULL)
4198 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
4199 WPAS_DBUS_NEW_IFACE_INTERFACE,
4204 dbus_message_set_destination(msg, wpa_s->preq_notify_peer);
4206 dbus_message_iter_init_append(msg, &iter);
4208 if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
4209 (addr && !wpa_dbus_dict_append_byte_array(&dict_iter, "addr",
4210 (const char *) addr,
4212 (dst && !wpa_dbus_dict_append_byte_array(&dict_iter, "dst",
4215 (bssid && !wpa_dbus_dict_append_byte_array(&dict_iter, "bssid",
4216 (const char *) bssid,
4218 (ie && ie_len && !wpa_dbus_dict_append_byte_array(&dict_iter, "ies",
4221 (ssi_signal && !wpa_dbus_dict_append_int32(&dict_iter, "signal",
4223 !wpa_dbus_dict_close_write(&iter, &dict_iter))
4226 dbus_connection_send(priv->con, msg, NULL);
4229 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
4231 dbus_message_unref(msg);
4234 #endif /* CONFIG_AP */