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 (os_strcmp(wpa_s->dbus_new_path, path) == 0)
168 * set_network_properties - Set properties of a configured network
169 * @wpa_s: wpa_supplicant structure for a network interface
170 * @ssid: wpa_ssid structure for a configured network
171 * @iter: DBus message iterator containing dictionary of network
173 * @error: On failure, an error describing the failure
174 * Returns: TRUE if the request succeeds, FALSE if it failed
176 * Sets network configuration with parameters given id DBus dictionary
178 dbus_bool_t set_network_properties(struct wpa_supplicant *wpa_s,
179 struct wpa_ssid *ssid,
180 DBusMessageIter *iter,
183 struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
184 DBusMessageIter iter_dict;
187 if (!wpa_dbus_dict_open_read(iter, &iter_dict, error))
190 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
194 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
198 if (entry.type == DBUS_TYPE_ARRAY &&
199 entry.array_type == DBUS_TYPE_BYTE) {
200 if (entry.array_len <= 0)
203 size = entry.array_len * 2 + 1;
204 value = os_zalloc(size);
208 ret = wpa_snprintf_hex(value, size,
209 (u8 *) entry.bytearray_value,
213 } else if (entry.type == DBUS_TYPE_STRING) {
214 if (should_quote_opt(entry.key)) {
215 size = os_strlen(entry.str_value);
220 value = os_zalloc(size);
224 ret = os_snprintf(value, size, "\"%s\"",
226 if (os_snprintf_error(size, ret))
229 value = os_strdup(entry.str_value);
233 } else if (entry.type == DBUS_TYPE_UINT32) {
234 value = os_zalloc(size);
238 ret = os_snprintf(value, size, "%u",
240 if (os_snprintf_error(size, ret))
242 } else if (entry.type == DBUS_TYPE_INT32) {
243 value = os_zalloc(size);
247 ret = os_snprintf(value, size, "%d",
249 if (os_snprintf_error(size, ret))
254 if (wpa_config_set(ssid, entry.key, value, 0) < 0)
257 if (os_strcmp(entry.key, "bssid") != 0 &&
258 os_strcmp(entry.key, "priority") != 0)
259 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
261 if (wpa_s->current_ssid == ssid ||
262 wpa_s->current_ssid == NULL) {
264 * Invalidate the EAP session cache if anything in the
265 * current or previously used configuration changes.
267 eapol_sm_invalidate_cached_session(wpa_s->eapol);
270 if ((os_strcmp(entry.key, "psk") == 0 &&
271 value[0] == '"' && ssid->ssid_len) ||
272 (os_strcmp(entry.key, "ssid") == 0 && ssid->passphrase))
273 wpa_config_update_psk(ssid);
274 else if (os_strcmp(entry.key, "priority") == 0)
275 wpa_config_update_prio_list(wpa_s->conf);
279 wpa_dbus_dict_entry_clear(&entry);
286 wpa_dbus_dict_entry_clear(&entry);
287 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
288 "invalid message format");
294 * wpas_dbus_simple_property_getter - Get basic type property
295 * @iter: Message iter to use when appending arguments
296 * @type: DBus type of property (must be basic type)
297 * @val: pointer to place holding property value
298 * @error: On failure an error describing the failure
299 * Returns: TRUE if the request was successful, FALSE if it failed
301 * Generic getter for basic type properties. Type is required to be basic.
303 dbus_bool_t wpas_dbus_simple_property_getter(DBusMessageIter *iter,
308 DBusMessageIter variant_iter;
310 if (!dbus_type_is_basic(type)) {
311 dbus_set_error(error, DBUS_ERROR_FAILED,
312 "%s: given type is not basic", __func__);
316 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
317 wpa_dbus_type_as_string(type),
319 !dbus_message_iter_append_basic(&variant_iter, type, val) ||
320 !dbus_message_iter_close_container(iter, &variant_iter)) {
321 dbus_set_error(error, DBUS_ERROR_FAILED,
322 "%s: error constructing reply", __func__);
331 * wpas_dbus_simple_property_setter - Set basic type property
332 * @message: Pointer to incoming dbus message
333 * @type: DBus type of property (must be basic type)
334 * @val: pointer to place where value being set will be stored
335 * Returns: TRUE if the request was successful, FALSE if it failed
337 * Generic setter for basic type properties. Type is required to be basic.
339 dbus_bool_t wpas_dbus_simple_property_setter(DBusMessageIter *iter,
341 const int type, void *val)
343 DBusMessageIter variant_iter;
345 if (!dbus_type_is_basic(type)) {
346 dbus_set_error(error, DBUS_ERROR_FAILED,
347 "%s: given type is not basic", __func__);
351 /* Look at the new value */
352 dbus_message_iter_recurse(iter, &variant_iter);
353 if (dbus_message_iter_get_arg_type(&variant_iter) != type) {
354 dbus_set_error_const(error, DBUS_ERROR_FAILED,
355 "wrong property type");
358 dbus_message_iter_get_basic(&variant_iter, val);
365 * wpas_dbus_simple_array_property_getter - Get array type property
366 * @iter: Pointer to incoming dbus message iterator
367 * @type: DBus type of property array elements (must be basic type)
368 * @array: pointer to array of elements to put into response message
369 * @array_len: length of above array
370 * @error: a pointer to an error to fill on failure
371 * Returns: TRUE if the request succeeded, FALSE if it failed
373 * Generic getter for array type properties. Array elements type is
374 * required to be basic.
376 dbus_bool_t wpas_dbus_simple_array_property_getter(DBusMessageIter *iter,
382 DBusMessageIter variant_iter, array_iter;
383 char type_str[] = "a?"; /* ? will be replaced with subtype letter; */
384 const char *sub_type_str;
385 size_t element_size, i;
387 if (!dbus_type_is_basic(type)) {
388 dbus_set_error(error, DBUS_ERROR_FAILED,
389 "%s: given type is not basic", __func__);
393 sub_type_str = wpa_dbus_type_as_string(type);
394 type_str[1] = sub_type_str[0];
396 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
397 type_str, &variant_iter) ||
398 !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
399 sub_type_str, &array_iter)) {
400 dbus_set_error(error, DBUS_ERROR_FAILED,
401 "%s: failed to construct message", __func__);
407 case DBUS_TYPE_BOOLEAN:
410 case DBUS_TYPE_INT16:
411 case DBUS_TYPE_UINT16:
412 element_size = sizeof(uint16_t);
414 case DBUS_TYPE_INT32:
415 case DBUS_TYPE_UINT32:
416 element_size = sizeof(uint32_t);
418 case DBUS_TYPE_INT64:
419 case DBUS_TYPE_UINT64:
420 element_size = sizeof(uint64_t);
422 case DBUS_TYPE_DOUBLE:
423 element_size = sizeof(double);
425 case DBUS_TYPE_STRING:
426 case DBUS_TYPE_OBJECT_PATH:
427 element_size = sizeof(char *);
430 dbus_set_error(error, DBUS_ERROR_FAILED,
431 "%s: unknown element type %d", __func__, type);
435 for (i = 0; i < array_len; i++) {
436 if (!dbus_message_iter_append_basic(&array_iter, type,
437 array + i * element_size)) {
438 dbus_set_error(error, DBUS_ERROR_FAILED,
439 "%s: failed to construct message 2.5",
445 if (!dbus_message_iter_close_container(&variant_iter, &array_iter) ||
446 !dbus_message_iter_close_container(iter, &variant_iter)) {
447 dbus_set_error(error, DBUS_ERROR_FAILED,
448 "%s: failed to construct message 3", __func__);
457 * wpas_dbus_simple_array_array_property_getter - Get array array type property
458 * @iter: Pointer to incoming dbus message iterator
459 * @type: DBus type of property array elements (must be basic type)
460 * @array: pointer to array of elements to put into response message
461 * @array_len: length of above array
462 * @error: a pointer to an error to fill on failure
463 * Returns: TRUE if the request succeeded, FALSE if it failed
465 * Generic getter for array type properties. Array elements type is
466 * required to be basic.
468 dbus_bool_t wpas_dbus_simple_array_array_property_getter(DBusMessageIter *iter,
470 struct wpabuf **array,
474 DBusMessageIter variant_iter, array_iter;
475 char type_str[] = "aa?";
476 char inner_type_str[] = "a?";
477 const char *sub_type_str;
480 if (!dbus_type_is_basic(type)) {
481 dbus_set_error(error, DBUS_ERROR_FAILED,
482 "%s: given type is not basic", __func__);
486 sub_type_str = wpa_dbus_type_as_string(type);
487 type_str[2] = sub_type_str[0];
488 inner_type_str[1] = sub_type_str[0];
490 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
491 type_str, &variant_iter) ||
492 !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
493 inner_type_str, &array_iter)) {
494 dbus_set_error(error, DBUS_ERROR_FAILED,
495 "%s: failed to construct message", __func__);
499 for (i = 0; i < array_len && array[i]; i++) {
500 wpa_dbus_dict_bin_array_add_element(&array_iter,
501 wpabuf_head(array[i]),
502 wpabuf_len(array[i]));
506 if (!dbus_message_iter_close_container(&variant_iter, &array_iter) ||
507 !dbus_message_iter_close_container(iter, &variant_iter)) {
508 dbus_set_error(error, DBUS_ERROR_FAILED,
509 "%s: failed to close message", __func__);
518 * wpas_dbus_handler_create_interface - Request registration of a network iface
519 * @message: Pointer to incoming dbus message
520 * @global: %wpa_supplicant global data structure
521 * Returns: The object path of the new interface object,
522 * or a dbus error message with more information
524 * Handler function for "CreateInterface" method call. Handles requests
525 * by dbus clients to register a network interface that wpa_supplicant
528 DBusMessage * wpas_dbus_handler_create_interface(DBusMessage *message,
529 struct wpa_global *global)
531 DBusMessageIter iter_dict;
532 DBusMessage *reply = NULL;
533 DBusMessageIter iter;
534 struct wpa_dbus_dict_entry entry;
537 char *confname = NULL;
538 char *bridge_ifname = NULL;
540 dbus_message_iter_init(message, &iter);
542 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
544 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
545 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
547 if (os_strcmp(entry.key, "Driver") == 0 &&
548 entry.type == DBUS_TYPE_STRING) {
550 driver = os_strdup(entry.str_value);
551 wpa_dbus_dict_entry_clear(&entry);
554 } else if (os_strcmp(entry.key, "Ifname") == 0 &&
555 entry.type == DBUS_TYPE_STRING) {
557 ifname = os_strdup(entry.str_value);
558 wpa_dbus_dict_entry_clear(&entry);
561 } else if (os_strcmp(entry.key, "ConfigFile") == 0 &&
562 entry.type == DBUS_TYPE_STRING) {
564 confname = os_strdup(entry.str_value);
565 wpa_dbus_dict_entry_clear(&entry);
566 if (confname == NULL)
568 } else if (os_strcmp(entry.key, "BridgeIfname") == 0 &&
569 entry.type == DBUS_TYPE_STRING) {
570 os_free(bridge_ifname);
571 bridge_ifname = os_strdup(entry.str_value);
572 wpa_dbus_dict_entry_clear(&entry);
573 if (bridge_ifname == NULL)
576 wpa_dbus_dict_entry_clear(&entry);
582 goto error; /* Required Ifname argument missing */
585 * Try to get the wpa_supplicant record for this iface, return
586 * an error if we already control it.
588 if (wpa_supplicant_get_iface(global, ifname) != NULL) {
589 reply = dbus_message_new_error(
590 message, WPAS_DBUS_ERROR_IFACE_EXISTS,
591 "wpa_supplicant already controls this interface.");
593 struct wpa_supplicant *wpa_s;
594 struct wpa_interface iface;
596 os_memset(&iface, 0, sizeof(iface));
597 iface.driver = driver;
598 iface.ifname = ifname;
599 iface.confname = confname;
600 iface.bridge_ifname = bridge_ifname;
601 /* Otherwise, have wpa_supplicant attach to it. */
602 wpa_s = wpa_supplicant_add_iface(global, &iface, NULL);
604 const char *path = wpa_s->dbus_new_path;
606 reply = dbus_message_new_method_return(message);
607 dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH,
608 &path, DBUS_TYPE_INVALID);
610 reply = wpas_dbus_error_unknown_error(
612 "wpa_supplicant couldn't grab this interface.");
620 os_free(bridge_ifname);
624 reply = wpas_dbus_error_invalid_args(message, NULL);
627 reply = wpas_dbus_error_no_memory(message);
633 * wpas_dbus_handler_remove_interface - Request deregistration of an interface
634 * @message: Pointer to incoming dbus message
635 * @global: wpa_supplicant global data structure
636 * Returns: a dbus message containing a UINT32 indicating success (1) or
637 * failure (0), or returns a dbus error message with more information
639 * Handler function for "removeInterface" method call. Handles requests
640 * by dbus clients to deregister a network interface that wpa_supplicant
643 DBusMessage * wpas_dbus_handler_remove_interface(DBusMessage *message,
644 struct wpa_global *global)
646 struct wpa_supplicant *wpa_s;
648 DBusMessage *reply = NULL;
650 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path,
653 wpa_s = get_iface_by_dbus_path(global, path);
655 reply = wpas_dbus_error_iface_unknown(message);
656 else if (wpa_supplicant_remove_iface(global, wpa_s, 0)) {
657 reply = wpas_dbus_error_unknown_error(
659 "wpa_supplicant couldn't remove this interface.");
667 * wpas_dbus_handler_get_interface - Get the object path for an interface name
668 * @message: Pointer to incoming dbus message
669 * @global: %wpa_supplicant global data structure
670 * Returns: The object path of the interface object,
671 * or a dbus error message with more information
673 * Handler function for "getInterface" method call.
675 DBusMessage * wpas_dbus_handler_get_interface(DBusMessage *message,
676 struct wpa_global *global)
678 DBusMessage *reply = NULL;
681 struct wpa_supplicant *wpa_s;
683 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &ifname,
686 wpa_s = wpa_supplicant_get_iface(global, ifname);
688 return wpas_dbus_error_iface_unknown(message);
690 path = wpa_s->dbus_new_path;
691 reply = dbus_message_new_method_return(message);
693 return wpas_dbus_error_no_memory(message);
694 if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
695 DBUS_TYPE_INVALID)) {
696 dbus_message_unref(reply);
697 return wpas_dbus_error_no_memory(message);
705 * wpas_dbus_getter_debug_level - Get debug level
706 * @iter: Pointer to incoming dbus message iter
707 * @error: Location to store error on failure
708 * @user_data: Function specific data
709 * Returns: TRUE on success, FALSE on failure
711 * Getter for "DebugLevel" property.
713 dbus_bool_t wpas_dbus_getter_debug_level(DBusMessageIter *iter,
718 int idx = wpa_debug_level;
724 str = debug_strings[idx];
725 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
731 * wpas_dbus_getter_debug_timestamp - Get debug timestamp
732 * @iter: Pointer to incoming dbus message iter
733 * @error: Location to store error on failure
734 * @user_data: Function specific data
735 * Returns: TRUE on success, FALSE on failure
737 * Getter for "DebugTimestamp" property.
739 dbus_bool_t wpas_dbus_getter_debug_timestamp(DBusMessageIter *iter,
743 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
744 &wpa_debug_timestamp, error);
750 * wpas_dbus_getter_debug_show_keys - Get debug show keys
751 * @iter: Pointer to incoming dbus message iter
752 * @error: Location to store error on failure
753 * @user_data: Function specific data
754 * Returns: TRUE on success, FALSE on failure
756 * Getter for "DebugShowKeys" property.
758 dbus_bool_t wpas_dbus_getter_debug_show_keys(DBusMessageIter *iter,
762 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
763 &wpa_debug_show_keys, error);
768 * wpas_dbus_setter_debug_level - Set debug level
769 * @iter: Pointer to incoming dbus message iter
770 * @error: Location to store error on failure
771 * @user_data: Function specific data
772 * Returns: TRUE on success, FALSE on failure
774 * Setter for "DebugLevel" property.
776 dbus_bool_t wpas_dbus_setter_debug_level(DBusMessageIter *iter,
777 DBusError *error, void *user_data)
779 struct wpa_global *global = user_data;
780 const char *str = NULL;
783 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
787 for (i = 0; debug_strings[i]; i++)
788 if (os_strcmp(debug_strings[i], str) == 0) {
794 wpa_supplicant_set_debug_params(global, val, wpa_debug_timestamp,
795 wpa_debug_show_keys)) {
796 dbus_set_error_const(error, DBUS_ERROR_FAILED,
797 "wrong debug level value");
806 * wpas_dbus_setter_debug_timestamp - Set debug timestamp
807 * @iter: Pointer to incoming dbus message iter
808 * @error: Location to store error on failure
809 * @user_data: Function specific data
810 * Returns: TRUE on success, FALSE on failure
812 * Setter for "DebugTimestamp" property.
814 dbus_bool_t wpas_dbus_setter_debug_timestamp(DBusMessageIter *iter,
818 struct wpa_global *global = user_data;
821 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
825 wpa_supplicant_set_debug_params(global, wpa_debug_level, val ? 1 : 0,
826 wpa_debug_show_keys);
832 * wpas_dbus_setter_debug_show_keys - Set debug show keys
833 * @iter: Pointer to incoming dbus message iter
834 * @error: Location to store error on failure
835 * @user_data: Function specific data
836 * Returns: TRUE on success, FALSE on failure
838 * Setter for "DebugShowKeys" property.
840 dbus_bool_t wpas_dbus_setter_debug_show_keys(DBusMessageIter *iter,
844 struct wpa_global *global = user_data;
847 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
851 wpa_supplicant_set_debug_params(global, wpa_debug_level,
859 * wpas_dbus_getter_interfaces - Request registered interfaces list
860 * @iter: Pointer to incoming dbus message iter
861 * @error: Location to store error on failure
862 * @user_data: Function specific data
863 * Returns: TRUE on success, FALSE on failure
865 * Getter for "Interfaces" property. Handles requests
866 * by dbus clients to return list of registered interfaces objects
869 dbus_bool_t wpas_dbus_getter_interfaces(DBusMessageIter *iter,
873 struct wpa_global *global = user_data;
874 struct wpa_supplicant *wpa_s;
876 unsigned int i = 0, num = 0;
879 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
882 paths = os_calloc(num, sizeof(char *));
884 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
888 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
889 paths[i++] = wpa_s->dbus_new_path;
891 success = wpas_dbus_simple_array_property_getter(iter,
892 DBUS_TYPE_OBJECT_PATH,
901 * wpas_dbus_getter_eap_methods - Request supported EAP methods list
902 * @iter: Pointer to incoming dbus message iter
903 * @error: Location to store error on failure
904 * @user_data: Function specific data
905 * Returns: TRUE on success, FALSE on failure
907 * Getter for "EapMethods" property. Handles requests
908 * by dbus clients to return list of strings with supported EAP methods
910 dbus_bool_t wpas_dbus_getter_eap_methods(DBusMessageIter *iter,
911 DBusError *error, void *user_data)
914 size_t num_items = 0;
917 eap_methods = eap_get_names_as_string_array(&num_items);
919 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
923 success = wpas_dbus_simple_array_property_getter(iter,
929 os_free(eap_methods[--num_items]);
930 os_free(eap_methods);
936 * wpas_dbus_getter_global_capabilities - Request supported global capabilities
937 * @iter: Pointer to incoming dbus message iter
938 * @error: Location to store error on failure
939 * @user_data: Function specific data
940 * Returns: TRUE on success, FALSE on failure
942 * Getter for "Capabilities" property. Handles requests by dbus clients to
943 * return a list of strings with supported capabilities like AP, RSN IBSS,
944 * and P2P that are determined at compile time.
946 dbus_bool_t wpas_dbus_getter_global_capabilities(DBusMessageIter *iter,
950 const char *capabilities[5] = { NULL, NULL, NULL, NULL, NULL };
951 size_t num_items = 0;
954 capabilities[num_items++] = "ap";
955 #endif /* CONFIG_AP */
956 #ifdef CONFIG_IBSS_RSN
957 capabilities[num_items++] = "ibss-rsn";
958 #endif /* CONFIG_IBSS_RSN */
960 capabilities[num_items++] = "p2p";
961 #endif /* CONFIG_P2P */
962 #ifdef CONFIG_INTERWORKING
963 capabilities[num_items++] = "interworking";
964 #endif /* CONFIG_INTERWORKING */
966 return wpas_dbus_simple_array_property_getter(iter,
973 static int wpas_dbus_get_scan_type(DBusMessage *message, DBusMessageIter *var,
974 char **type, DBusMessage **reply)
976 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_STRING) {
977 wpa_printf(MSG_DEBUG, "%s[dbus]: Type must be a string",
979 *reply = wpas_dbus_error_invalid_args(
980 message, "Wrong Type value type. String required");
983 dbus_message_iter_get_basic(var, type);
988 static int wpas_dbus_get_scan_ssids(DBusMessage *message, DBusMessageIter *var,
989 struct wpa_driver_scan_params *params,
992 struct wpa_driver_scan_ssid *ssids = params->ssids;
993 size_t ssids_num = 0;
995 DBusMessageIter array_iter, sub_array_iter;
999 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
1000 wpa_printf(MSG_DEBUG,
1001 "%s[dbus]: ssids must be an array of arrays of bytes",
1003 *reply = wpas_dbus_error_invalid_args(
1005 "Wrong SSIDs value type. Array of arrays of bytes required");
1009 dbus_message_iter_recurse(var, &array_iter);
1011 if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY ||
1012 dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_BYTE) {
1013 wpa_printf(MSG_DEBUG,
1014 "%s[dbus]: ssids must be an array of arrays of bytes",
1016 *reply = wpas_dbus_error_invalid_args(
1018 "Wrong SSIDs value type. Array of arrays of bytes required");
1022 while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_ARRAY) {
1023 if (ssids_num >= WPAS_MAX_SCAN_SSIDS) {
1024 wpa_printf(MSG_DEBUG,
1025 "%s[dbus]: Too many ssids specified on scan dbus call",
1027 *reply = wpas_dbus_error_invalid_args(
1029 "Too many ssids specified. Specify at most four");
1033 dbus_message_iter_recurse(&array_iter, &sub_array_iter);
1035 dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len);
1037 if (len > MAX_SSID_LEN) {
1038 wpa_printf(MSG_DEBUG,
1039 "%s[dbus]: SSID too long (len=%d max_len=%d)",
1040 __func__, len, MAX_SSID_LEN);
1041 *reply = wpas_dbus_error_invalid_args(
1042 message, "Invalid SSID: too long");
1047 ssid = os_malloc(len);
1049 *reply = wpas_dbus_error_no_memory(message);
1052 os_memcpy(ssid, val, len);
1054 /* Allow zero-length SSIDs */
1058 ssids[ssids_num].ssid = ssid;
1059 ssids[ssids_num].ssid_len = len;
1061 dbus_message_iter_next(&array_iter);
1065 params->num_ssids = ssids_num;
1070 static int wpas_dbus_get_scan_ies(DBusMessage *message, DBusMessageIter *var,
1071 struct wpa_driver_scan_params *params,
1072 DBusMessage **reply)
1074 u8 *ies = NULL, *nies;
1076 DBusMessageIter array_iter, sub_array_iter;
1080 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
1081 wpa_printf(MSG_DEBUG,
1082 "%s[dbus]: ies must be an array of arrays of bytes",
1084 *reply = wpas_dbus_error_invalid_args(
1086 "Wrong IEs value type. Array of arrays of bytes required");
1090 dbus_message_iter_recurse(var, &array_iter);
1092 if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY ||
1093 dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_BYTE) {
1094 wpa_printf(MSG_DEBUG,
1095 "%s[dbus]: ies must be an array of arrays of bytes",
1097 *reply = wpas_dbus_error_invalid_args(
1098 message, "Wrong IEs value type. Array required");
1102 while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_ARRAY) {
1103 dbus_message_iter_recurse(&array_iter, &sub_array_iter);
1105 dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len);
1107 dbus_message_iter_next(&array_iter);
1111 nies = os_realloc(ies, ies_len + len);
1114 *reply = wpas_dbus_error_no_memory(message);
1118 os_memcpy(ies + ies_len, val, len);
1121 dbus_message_iter_next(&array_iter);
1124 params->extra_ies = ies;
1125 params->extra_ies_len = ies_len;
1130 static int wpas_dbus_get_scan_channels(DBusMessage *message,
1131 DBusMessageIter *var,
1132 struct wpa_driver_scan_params *params,
1133 DBusMessage **reply)
1135 DBusMessageIter array_iter, sub_array_iter;
1136 int *freqs = NULL, *nfreqs;
1139 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
1140 wpa_printf(MSG_DEBUG,
1141 "%s[dbus]: Channels must be an array of structs",
1143 *reply = wpas_dbus_error_invalid_args(
1145 "Wrong Channels value type. Array of structs required");
1149 dbus_message_iter_recurse(var, &array_iter);
1151 if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_STRUCT) {
1152 wpa_printf(MSG_DEBUG,
1153 "%s[dbus]: Channels must be an array of structs",
1155 *reply = wpas_dbus_error_invalid_args(
1157 "Wrong Channels value type. Array of structs required");
1161 while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_STRUCT)
1165 dbus_message_iter_recurse(&array_iter, &sub_array_iter);
1167 if (dbus_message_iter_get_arg_type(&sub_array_iter) !=
1169 wpa_printf(MSG_DEBUG,
1170 "%s[dbus]: Channel must by specified by struct of two UINT32s %c",
1172 dbus_message_iter_get_arg_type(
1174 *reply = wpas_dbus_error_invalid_args(
1176 "Wrong Channel struct. Two UINT32s required");
1180 dbus_message_iter_get_basic(&sub_array_iter, &freq);
1182 if (!dbus_message_iter_next(&sub_array_iter) ||
1183 dbus_message_iter_get_arg_type(&sub_array_iter) !=
1185 wpa_printf(MSG_DEBUG,
1186 "%s[dbus]: Channel must by specified by struct of two UINT32s",
1188 *reply = wpas_dbus_error_invalid_args(
1190 "Wrong Channel struct. Two UINT32s required");
1195 dbus_message_iter_get_basic(&sub_array_iter, &width);
1197 #define FREQS_ALLOC_CHUNK 32
1198 if (freqs_num % FREQS_ALLOC_CHUNK == 0) {
1199 nfreqs = os_realloc_array(
1200 freqs, freqs_num + FREQS_ALLOC_CHUNK,
1206 if (freqs == NULL) {
1207 *reply = wpas_dbus_error_no_memory(message);
1211 freqs[freqs_num] = freq;
1214 dbus_message_iter_next(&array_iter);
1217 nfreqs = os_realloc_array(freqs, freqs_num + 1, sizeof(int));
1221 if (freqs == NULL) {
1222 *reply = wpas_dbus_error_no_memory(message);
1225 freqs[freqs_num] = 0;
1227 params->freqs = freqs;
1232 static int wpas_dbus_get_scan_allow_roam(DBusMessage *message,
1233 DBusMessageIter *var,
1235 DBusMessage **reply)
1237 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_BOOLEAN) {
1238 wpa_printf(MSG_DEBUG, "%s[dbus]: Type must be a boolean",
1240 *reply = wpas_dbus_error_invalid_args(
1241 message, "Wrong Type value type. Boolean required");
1244 dbus_message_iter_get_basic(var, allow);
1250 * wpas_dbus_handler_scan - Request a wireless scan on an interface
1251 * @message: Pointer to incoming dbus message
1252 * @wpa_s: wpa_supplicant structure for a network interface
1253 * Returns: NULL indicating success or DBus error message on failure
1255 * Handler function for "Scan" method call of a network device. Requests
1256 * that wpa_supplicant perform a wireless scan as soon as possible
1257 * on a particular wireless interface.
1259 DBusMessage * wpas_dbus_handler_scan(DBusMessage *message,
1260 struct wpa_supplicant *wpa_s)
1262 DBusMessage *reply = NULL;
1263 DBusMessageIter iter, dict_iter, entry_iter, variant_iter;
1264 char *key = NULL, *type = NULL;
1265 struct wpa_driver_scan_params params;
1267 dbus_bool_t allow_roam = 1;
1269 os_memset(¶ms, 0, sizeof(params));
1271 dbus_message_iter_init(message, &iter);
1273 dbus_message_iter_recurse(&iter, &dict_iter);
1275 while (dbus_message_iter_get_arg_type(&dict_iter) ==
1276 DBUS_TYPE_DICT_ENTRY) {
1277 dbus_message_iter_recurse(&dict_iter, &entry_iter);
1278 dbus_message_iter_get_basic(&entry_iter, &key);
1279 dbus_message_iter_next(&entry_iter);
1280 dbus_message_iter_recurse(&entry_iter, &variant_iter);
1282 if (os_strcmp(key, "Type") == 0) {
1283 if (wpas_dbus_get_scan_type(message, &variant_iter,
1286 } else if (os_strcmp(key, "SSIDs") == 0) {
1287 if (wpas_dbus_get_scan_ssids(message, &variant_iter,
1288 ¶ms, &reply) < 0)
1290 } else if (os_strcmp(key, "IEs") == 0) {
1291 if (wpas_dbus_get_scan_ies(message, &variant_iter,
1292 ¶ms, &reply) < 0)
1294 } else if (os_strcmp(key, "Channels") == 0) {
1295 if (wpas_dbus_get_scan_channels(message, &variant_iter,
1296 ¶ms, &reply) < 0)
1298 } else if (os_strcmp(key, "AllowRoam") == 0) {
1299 if (wpas_dbus_get_scan_allow_roam(message,
1305 wpa_printf(MSG_DEBUG, "%s[dbus]: Unknown argument %s",
1307 reply = wpas_dbus_error_invalid_args(message, key);
1311 dbus_message_iter_next(&dict_iter);
1315 wpa_printf(MSG_DEBUG, "%s[dbus]: Scan type not specified",
1317 reply = wpas_dbus_error_invalid_args(message, key);
1321 if (os_strcmp(type, "passive") == 0) {
1322 if (params.num_ssids || params.extra_ies_len) {
1323 wpa_printf(MSG_DEBUG,
1324 "%s[dbus]: SSIDs or IEs specified for passive scan.",
1326 reply = wpas_dbus_error_invalid_args(
1328 "You can specify only Channels in passive scan");
1330 } else if (params.freqs && params.freqs[0]) {
1331 if (wpa_supplicant_trigger_scan(wpa_s, ¶ms)) {
1332 reply = wpas_dbus_error_scan_error(
1333 message, "Scan request rejected");
1336 wpa_s->scan_req = MANUAL_SCAN_REQ;
1337 wpa_supplicant_req_scan(wpa_s, 0, 0);
1339 } else if (os_strcmp(type, "active") == 0) {
1340 if (!params.num_ssids) {
1341 /* Add wildcard ssid */
1344 #ifdef CONFIG_AUTOSCAN
1345 autoscan_deinit(wpa_s);
1346 #endif /* CONFIG_AUTOSCAN */
1347 if (wpa_supplicant_trigger_scan(wpa_s, ¶ms)) {
1348 reply = wpas_dbus_error_scan_error(
1349 message, "Scan request rejected");
1352 wpa_printf(MSG_DEBUG, "%s[dbus]: Unknown scan type: %s",
1354 reply = wpas_dbus_error_invalid_args(message,
1360 wpa_s->scan_res_handler = scan_only_handler;
1363 for (i = 0; i < WPAS_MAX_SCAN_SSIDS; i++)
1364 os_free((u8 *) params.ssids[i].ssid);
1365 os_free((u8 *) params.extra_ies);
1366 os_free(params.freqs);
1372 * wpas_dbus_handler_signal_poll - Request immediate signal properties
1373 * @message: Pointer to incoming dbus message
1374 * @wpa_s: wpa_supplicant structure for a network interface
1375 * Returns: NULL indicating success or DBus error message on failure
1377 * Handler function for "SignalPoll" method call of a network device. Requests
1378 * that wpa_supplicant read signal properties like RSSI, noise, and link
1379 * speed and return them.
1381 DBusMessage * wpas_dbus_handler_signal_poll(DBusMessage *message,
1382 struct wpa_supplicant *wpa_s)
1384 struct wpa_signal_info si;
1385 DBusMessage *reply = NULL;
1386 DBusMessageIter iter, iter_dict, variant_iter;
1389 ret = wpa_drv_signal_poll(wpa_s, &si);
1391 return dbus_message_new_error(message, DBUS_ERROR_FAILED,
1392 "Failed to read signal");
1395 reply = dbus_message_new_method_return(message);
1399 dbus_message_iter_init_append(reply, &iter);
1401 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
1402 "a{sv}", &variant_iter) ||
1403 !wpa_dbus_dict_open_write(&variant_iter, &iter_dict) ||
1404 !wpa_dbus_dict_append_int32(&iter_dict, "rssi",
1405 si.current_signal) ||
1406 !wpa_dbus_dict_append_int32(&iter_dict, "linkspeed",
1407 si.current_txrate / 1000) ||
1408 !wpa_dbus_dict_append_int32(&iter_dict, "noise",
1409 si.current_noise) ||
1410 !wpa_dbus_dict_append_uint32(&iter_dict, "frequency",
1412 (si.chanwidth != CHAN_WIDTH_UNKNOWN &&
1413 !wpa_dbus_dict_append_string(
1414 &iter_dict, "width",
1415 channel_width_to_string(si.chanwidth))) ||
1416 (si.center_frq1 > 0 && si.center_frq2 > 0 &&
1417 (!wpa_dbus_dict_append_int32(&iter_dict, "center-frq1",
1419 !wpa_dbus_dict_append_int32(&iter_dict, "center-frq2",
1420 si.center_frq2))) ||
1422 !wpa_dbus_dict_append_int32(&iter_dict, "avg-rssi",
1424 !wpa_dbus_dict_close_write(&variant_iter, &iter_dict) ||
1425 !dbus_message_iter_close_container(&iter, &variant_iter))
1432 dbus_message_unref(reply);
1433 return wpas_dbus_error_no_memory(message);
1438 * wpas_dbus_handler_disconnect - Terminate the current connection
1439 * @message: Pointer to incoming dbus message
1440 * @wpa_s: wpa_supplicant structure for a network interface
1441 * Returns: NotConnected DBus error message if already not connected
1442 * or NULL otherwise.
1444 * Handler function for "Disconnect" method call of network interface.
1446 DBusMessage * wpas_dbus_handler_disconnect(DBusMessage *message,
1447 struct wpa_supplicant *wpa_s)
1449 if (wpa_s->current_ssid != NULL) {
1450 wpa_s->disconnected = 1;
1451 wpa_supplicant_deauthenticate(wpa_s,
1452 WLAN_REASON_DEAUTH_LEAVING);
1457 return dbus_message_new_error(message, WPAS_DBUS_ERROR_NOT_CONNECTED,
1458 "This interface is not connected");
1463 * wpas_dbus_new_iface_add_network - Add a new configured network
1464 * @message: Pointer to incoming dbus message
1465 * @wpa_s: wpa_supplicant structure for a network interface
1466 * Returns: A dbus message containing the object path of the new network
1468 * Handler function for "AddNetwork" method call of a network interface.
1470 DBusMessage * wpas_dbus_handler_add_network(DBusMessage *message,
1471 struct wpa_supplicant *wpa_s)
1473 DBusMessage *reply = NULL;
1474 DBusMessageIter iter;
1475 struct wpa_ssid *ssid = NULL;
1476 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf;
1479 dbus_message_iter_init(message, &iter);
1481 ssid = wpa_config_add_network(wpa_s->conf);
1483 wpa_printf(MSG_ERROR, "%s[dbus]: can't add new interface.",
1485 reply = wpas_dbus_error_unknown_error(
1487 "wpa_supplicant could not add a network on this interface.");
1490 wpas_notify_network_added(wpa_s, ssid);
1492 wpa_config_set_network_defaults(ssid);
1494 dbus_error_init(&error);
1495 if (!set_network_properties(wpa_s, ssid, &iter, &error)) {
1496 wpa_printf(MSG_DEBUG,
1497 "%s[dbus]: control interface couldn't set network properties",
1499 reply = wpas_dbus_reply_new_from_error(message, &error,
1500 DBUS_ERROR_INVALID_ARGS,
1501 "Failed to add network");
1502 dbus_error_free(&error);
1506 /* Construct the object path for this network. */
1507 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
1508 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
1509 wpa_s->dbus_new_path, ssid->id);
1511 reply = dbus_message_new_method_return(message);
1512 if (reply == NULL) {
1513 reply = wpas_dbus_error_no_memory(message);
1516 if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
1517 DBUS_TYPE_INVALID)) {
1518 dbus_message_unref(reply);
1519 reply = wpas_dbus_error_no_memory(message);
1527 wpas_notify_network_removed(wpa_s, ssid);
1528 wpa_config_remove_network(wpa_s->conf, ssid->id);
1535 * wpas_dbus_handler_reassociate - Reassociate
1536 * @message: Pointer to incoming dbus message
1537 * @wpa_s: wpa_supplicant structure for a network interface
1538 * Returns: InterfaceDisabled DBus error message if disabled
1539 * or NULL otherwise.
1541 * Handler function for "Reassociate" method call of network interface.
1543 DBusMessage * wpas_dbus_handler_reassociate(DBusMessage *message,
1544 struct wpa_supplicant *wpa_s)
1546 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED) {
1547 wpas_request_connection(wpa_s);
1551 return dbus_message_new_error(message, WPAS_DBUS_ERROR_IFACE_DISABLED,
1552 "This interface is disabled");
1557 * wpas_dbus_handler_reattach - Reattach to current AP
1558 * @message: Pointer to incoming dbus message
1559 * @wpa_s: wpa_supplicant structure for a network interface
1560 * Returns: NotConnected DBus error message if not connected
1561 * or NULL otherwise.
1563 * Handler function for "Reattach" method call of network interface.
1565 DBusMessage * wpas_dbus_handler_reattach(DBusMessage *message,
1566 struct wpa_supplicant *wpa_s)
1568 if (wpa_s->current_ssid != NULL) {
1569 wpa_s->reattach = 1;
1570 wpas_request_connection(wpa_s);
1574 return dbus_message_new_error(message, WPAS_DBUS_ERROR_NOT_CONNECTED,
1575 "This interface is not connected");
1580 * wpas_dbus_handler_remove_network - Remove a configured network
1581 * @message: Pointer to incoming dbus message
1582 * @wpa_s: wpa_supplicant structure for a network interface
1583 * Returns: NULL on success or dbus error on failure
1585 * Handler function for "RemoveNetwork" method call of a network interface.
1587 DBusMessage * wpas_dbus_handler_remove_network(DBusMessage *message,
1588 struct wpa_supplicant *wpa_s)
1590 DBusMessage *reply = NULL;
1592 char *iface, *net_id;
1594 struct wpa_ssid *ssid;
1597 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
1600 /* Extract the network ID and ensure the network */
1601 /* is actually a child of this interface */
1602 iface = wpas_dbus_new_decompose_object_path(op,
1603 WPAS_DBUS_NEW_NETWORKS_PART,
1605 if (iface == NULL || net_id == NULL ||
1606 os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
1607 reply = wpas_dbus_error_invalid_args(message, op);
1612 id = strtoul(net_id, NULL, 10);
1614 reply = wpas_dbus_error_invalid_args(message, op);
1618 ssid = wpa_config_get_network(wpa_s->conf, id);
1620 reply = wpas_dbus_error_network_unknown(message);
1624 was_disabled = ssid->disabled;
1626 wpas_notify_network_removed(wpa_s, ssid);
1628 if (ssid == wpa_s->current_ssid)
1629 wpa_supplicant_deauthenticate(wpa_s,
1630 WLAN_REASON_DEAUTH_LEAVING);
1631 else if (!was_disabled && wpa_s->sched_scanning) {
1632 wpa_printf(MSG_DEBUG,
1633 "Stop ongoing sched_scan to remove network from filters");
1634 wpa_supplicant_cancel_sched_scan(wpa_s);
1635 wpa_supplicant_req_scan(wpa_s, 0, 0);
1638 if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
1639 wpa_printf(MSG_ERROR,
1640 "%s[dbus]: error occurred when removing network %d",
1642 reply = wpas_dbus_error_unknown_error(
1644 "error removing the specified network on is interface.");
1654 static void remove_network(void *arg, struct wpa_ssid *ssid)
1656 struct wpa_supplicant *wpa_s = arg;
1658 wpas_notify_network_removed(wpa_s, ssid);
1660 if (wpa_config_remove_network(wpa_s->conf, ssid->id) < 0) {
1661 wpa_printf(MSG_ERROR,
1662 "%s[dbus]: error occurred when removing network %d",
1663 __func__, ssid->id);
1667 if (ssid == wpa_s->current_ssid)
1668 wpa_supplicant_deauthenticate(wpa_s,
1669 WLAN_REASON_DEAUTH_LEAVING);
1674 * wpas_dbus_handler_remove_all_networks - Remove all configured networks
1675 * @message: Pointer to incoming dbus message
1676 * @wpa_s: wpa_supplicant structure for a network interface
1677 * Returns: NULL on success or dbus error on failure
1679 * Handler function for "RemoveAllNetworks" method call of a network interface.
1681 DBusMessage * wpas_dbus_handler_remove_all_networks(
1682 DBusMessage *message, struct wpa_supplicant *wpa_s)
1684 if (wpa_s->sched_scanning)
1685 wpa_supplicant_cancel_sched_scan(wpa_s);
1687 /* NB: could check for failure and return an error */
1688 wpa_config_foreach_network(wpa_s->conf, remove_network, wpa_s);
1694 * wpas_dbus_handler_select_network - Attempt association with a network
1695 * @message: Pointer to incoming dbus message
1696 * @wpa_s: wpa_supplicant structure for a network interface
1697 * Returns: NULL on success or dbus error on failure
1699 * Handler function for "SelectNetwork" method call of network interface.
1701 DBusMessage * wpas_dbus_handler_select_network(DBusMessage *message,
1702 struct wpa_supplicant *wpa_s)
1704 DBusMessage *reply = NULL;
1706 char *iface, *net_id;
1708 struct wpa_ssid *ssid;
1710 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
1713 /* Extract the network ID and ensure the network */
1714 /* is actually a child of this interface */
1715 iface = wpas_dbus_new_decompose_object_path(op,
1716 WPAS_DBUS_NEW_NETWORKS_PART,
1718 if (iface == NULL || net_id == NULL ||
1719 os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
1720 reply = wpas_dbus_error_invalid_args(message, op);
1725 id = strtoul(net_id, NULL, 10);
1727 reply = wpas_dbus_error_invalid_args(message, op);
1731 ssid = wpa_config_get_network(wpa_s->conf, id);
1733 reply = wpas_dbus_error_network_unknown(message);
1737 /* Finally, associate with the network */
1738 wpa_supplicant_select_network(wpa_s, ssid);
1747 * wpas_dbus_handler_network_reply - Reply to a NetworkRequest signal
1748 * @message: Pointer to incoming dbus message
1749 * @wpa_s: wpa_supplicant structure for a network interface
1750 * Returns: NULL on success or dbus error on failure
1752 * Handler function for "NetworkReply" method call of network interface.
1754 DBusMessage * wpas_dbus_handler_network_reply(DBusMessage *message,
1755 struct wpa_supplicant *wpa_s)
1757 #ifdef IEEE8021X_EAPOL
1758 DBusMessage *reply = NULL;
1759 const char *op, *field, *value;
1760 char *iface, *net_id;
1762 struct wpa_ssid *ssid;
1764 if (!dbus_message_get_args(message, NULL,
1765 DBUS_TYPE_OBJECT_PATH, &op,
1766 DBUS_TYPE_STRING, &field,
1767 DBUS_TYPE_STRING, &value,
1769 return wpas_dbus_error_invalid_args(message, NULL);
1771 /* Extract the network ID and ensure the network */
1772 /* is actually a child of this interface */
1773 iface = wpas_dbus_new_decompose_object_path(op,
1774 WPAS_DBUS_NEW_NETWORKS_PART,
1776 if (iface == NULL || net_id == NULL ||
1777 os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
1778 reply = wpas_dbus_error_invalid_args(message, op);
1783 id = strtoul(net_id, NULL, 10);
1785 reply = wpas_dbus_error_invalid_args(message, net_id);
1789 ssid = wpa_config_get_network(wpa_s->conf, id);
1791 reply = wpas_dbus_error_network_unknown(message);
1795 if (wpa_supplicant_ctrl_iface_ctrl_rsp_handle(wpa_s, ssid,
1797 reply = wpas_dbus_error_invalid_args(message, field);
1799 /* Tell EAP to retry immediately */
1800 eapol_sm_notify_ctrl_response(wpa_s->eapol);
1806 #else /* IEEE8021X_EAPOL */
1807 wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included");
1808 return wpas_dbus_error_unknown_error(message, "802.1X not included");
1809 #endif /* IEEE8021X_EAPOL */
1813 #ifndef CONFIG_NO_CONFIG_BLOBS
1816 * wpas_dbus_handler_add_blob - Store named binary blob (ie, for certificates)
1817 * @message: Pointer to incoming dbus message
1818 * @wpa_s: %wpa_supplicant data structure
1819 * Returns: A dbus message containing an error on failure or NULL on success
1821 * Asks wpa_supplicant to internally store a binary blobs.
1823 DBusMessage * wpas_dbus_handler_add_blob(DBusMessage *message,
1824 struct wpa_supplicant *wpa_s)
1826 DBusMessage *reply = NULL;
1827 DBusMessageIter iter, array_iter;
1832 struct wpa_config_blob *blob = NULL;
1834 dbus_message_iter_init(message, &iter);
1835 dbus_message_iter_get_basic(&iter, &blob_name);
1837 if (wpa_config_get_blob(wpa_s->conf, blob_name)) {
1838 return dbus_message_new_error(message,
1839 WPAS_DBUS_ERROR_BLOB_EXISTS,
1843 dbus_message_iter_next(&iter);
1844 dbus_message_iter_recurse(&iter, &array_iter);
1846 dbus_message_iter_get_fixed_array(&array_iter, &blob_data, &blob_len);
1848 blob = os_zalloc(sizeof(*blob));
1850 reply = wpas_dbus_error_no_memory(message);
1854 blob->data = os_malloc(blob_len);
1855 blob->name = os_strdup(blob_name);
1856 if (!blob->data || !blob->name) {
1857 reply = wpas_dbus_error_no_memory(message);
1860 os_memcpy(blob->data, blob_data, blob_len);
1861 blob->len = blob_len;
1863 wpa_config_set_blob(wpa_s->conf, blob);
1864 wpas_notify_blob_added(wpa_s, blob->name);
1870 os_free(blob->name);
1871 os_free(blob->data);
1879 * wpas_dbus_handler_get_blob - Get named binary blob (ie, for certificates)
1880 * @message: Pointer to incoming dbus message
1881 * @wpa_s: %wpa_supplicant data structure
1882 * Returns: A dbus message containing array of bytes (blob)
1884 * Gets one wpa_supplicant's binary blobs.
1886 DBusMessage * wpas_dbus_handler_get_blob(DBusMessage *message,
1887 struct wpa_supplicant *wpa_s)
1889 DBusMessage *reply = NULL;
1890 DBusMessageIter iter, array_iter;
1893 const struct wpa_config_blob *blob;
1895 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &blob_name,
1898 blob = wpa_config_get_blob(wpa_s->conf, blob_name);
1900 return dbus_message_new_error(message,
1901 WPAS_DBUS_ERROR_BLOB_UNKNOWN,
1905 reply = dbus_message_new_method_return(message);
1907 return wpas_dbus_error_no_memory(message);
1909 dbus_message_iter_init_append(reply, &iter);
1911 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
1912 DBUS_TYPE_BYTE_AS_STRING,
1914 !dbus_message_iter_append_fixed_array(&array_iter, DBUS_TYPE_BYTE,
1915 &(blob->data), blob->len) ||
1916 !dbus_message_iter_close_container(&iter, &array_iter)) {
1917 dbus_message_unref(reply);
1918 reply = wpas_dbus_error_no_memory(message);
1926 * wpas_remove_handler_remove_blob - Remove named binary blob
1927 * @message: Pointer to incoming dbus message
1928 * @wpa_s: %wpa_supplicant data structure
1929 * Returns: NULL on success or dbus error
1931 * Asks wpa_supplicant to internally remove a binary blobs.
1933 DBusMessage * wpas_dbus_handler_remove_blob(DBusMessage *message,
1934 struct wpa_supplicant *wpa_s)
1936 DBusMessage *reply = NULL;
1939 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &blob_name,
1942 if (wpa_config_remove_blob(wpa_s->conf, blob_name)) {
1943 return dbus_message_new_error(message,
1944 WPAS_DBUS_ERROR_BLOB_UNKNOWN,
1947 wpas_notify_blob_removed(wpa_s, blob_name);
1953 #endif /* CONFIG_NO_CONFIG_BLOBS */
1957 * wpas_dbus_handler_flush_bss - Flush the BSS cache
1958 * @message: Pointer to incoming dbus message
1959 * @wpa_s: wpa_supplicant structure for a network interface
1962 * Handler function for "FlushBSS" method call of network interface.
1964 DBusMessage * wpas_dbus_handler_flush_bss(DBusMessage *message,
1965 struct wpa_supplicant *wpa_s)
1969 dbus_message_get_args(message, NULL, DBUS_TYPE_UINT32, &age,
1973 wpa_bss_flush(wpa_s);
1975 wpa_bss_flush_by_age(wpa_s, age);
1981 #ifdef CONFIG_AUTOSCAN
1983 * wpas_dbus_handler_autoscan - Set autoscan parameters for the interface
1984 * @message: Pointer to incoming dbus message
1985 * @wpa_s: wpa_supplicant structure for a network interface
1988 * Handler function for "AutoScan" method call of network interface.
1990 DBusMessage * wpas_dbus_handler_autoscan(DBusMessage *message,
1991 struct wpa_supplicant *wpa_s)
1993 DBusMessage *reply = NULL;
1994 enum wpa_states state = wpa_s->wpa_state;
1997 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &arg,
2000 if (arg != NULL && os_strlen(arg) > 0) {
2003 tmp = os_strdup(arg);
2005 reply = wpas_dbus_error_no_memory(message);
2007 os_free(wpa_s->conf->autoscan);
2008 wpa_s->conf->autoscan = tmp;
2009 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
2010 autoscan_init(wpa_s, 1);
2011 else if (state == WPA_SCANNING)
2012 wpa_supplicant_reinit_autoscan(wpa_s);
2014 } else if (arg != NULL && os_strlen(arg) == 0) {
2015 os_free(wpa_s->conf->autoscan);
2016 wpa_s->conf->autoscan = NULL;
2017 autoscan_deinit(wpa_s);
2019 reply = dbus_message_new_error(message,
2020 DBUS_ERROR_INVALID_ARGS,
2025 #endif /* CONFIG_AUTOSCAN */
2029 * wpas_dbus_handler_eap_logoff - IEEE 802.1X EAPOL state machine logoff
2030 * @message: Pointer to incoming dbus message
2031 * @wpa_s: wpa_supplicant structure for a network interface
2034 * Handler function for "EAPLogoff" method call of network interface.
2036 DBusMessage * wpas_dbus_handler_eap_logoff(DBusMessage *message,
2037 struct wpa_supplicant *wpa_s)
2039 eapol_sm_notify_logoff(wpa_s->eapol, TRUE);
2045 * wpas_dbus_handler_eap_logon - IEEE 802.1X EAPOL state machine logon
2046 * @message: Pointer to incoming dbus message
2047 * @wpa_s: wpa_supplicant structure for a network interface
2050 * Handler function for "EAPLogin" method call of network interface.
2052 DBusMessage * wpas_dbus_handler_eap_logon(DBusMessage *message,
2053 struct wpa_supplicant *wpa_s)
2055 eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
2062 static int get_peer_hwaddr_helper(DBusMessage *message, const char *func_name,
2063 u8 *peer_address, DBusMessage **error)
2065 const char *peer_string;
2069 if (!dbus_message_get_args(message, NULL,
2070 DBUS_TYPE_STRING, &peer_string,
2071 DBUS_TYPE_INVALID)) {
2072 *error = wpas_dbus_error_invalid_args(message, NULL);
2076 if (hwaddr_aton(peer_string, peer_address)) {
2077 wpa_printf(MSG_DEBUG, "%s: invalid address '%s'",
2078 func_name, peer_string);
2079 *error = wpas_dbus_error_invalid_args(
2080 message, "Invalid hardware address format");
2089 * wpas_dbus_handler_tdls_discover - Discover TDLS peer
2090 * @message: Pointer to incoming dbus message
2091 * @wpa_s: wpa_supplicant structure for a network interface
2092 * Returns: NULL indicating success or DBus error message on failure
2094 * Handler function for "TDLSDiscover" method call of network interface.
2096 DBusMessage * wpas_dbus_handler_tdls_discover(DBusMessage *message,
2097 struct wpa_supplicant *wpa_s)
2100 DBusMessage *error_reply;
2103 if (get_peer_hwaddr_helper(message, __func__, peer, &error_reply) < 0)
2106 wpa_printf(MSG_DEBUG, "DBUS TDLS_DISCOVER " MACSTR, MAC2STR(peer));
2108 if (wpa_tdls_is_external_setup(wpa_s->wpa))
2109 ret = wpa_tdls_send_discovery_request(wpa_s->wpa, peer);
2111 ret = wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer);
2114 return wpas_dbus_error_unknown_error(
2115 message, "error performing TDLS discovery");
2123 * wpas_dbus_handler_tdls_setup - Setup TDLS session
2124 * @message: Pointer to incoming dbus message
2125 * @wpa_s: wpa_supplicant structure for a network interface
2126 * Returns: NULL indicating success or DBus error message on failure
2128 * Handler function for "TDLSSetup" method call of network interface.
2130 DBusMessage * wpas_dbus_handler_tdls_setup(DBusMessage *message,
2131 struct wpa_supplicant *wpa_s)
2134 DBusMessage *error_reply;
2137 if (get_peer_hwaddr_helper(message, __func__, peer, &error_reply) < 0)
2140 wpa_printf(MSG_DEBUG, "DBUS TDLS_SETUP " MACSTR, MAC2STR(peer));
2142 wpa_tdls_remove(wpa_s->wpa, peer);
2143 if (wpa_tdls_is_external_setup(wpa_s->wpa))
2144 ret = wpa_tdls_start(wpa_s->wpa, peer);
2146 ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
2149 return wpas_dbus_error_unknown_error(
2150 message, "error performing TDLS setup");
2158 * wpas_dbus_handler_tdls_status - Return TDLS session status
2159 * @message: Pointer to incoming dbus message
2160 * @wpa_s: wpa_supplicant structure for a network interface
2161 * Returns: A string representing the state of the link to this TDLS peer
2163 * Handler function for "TDLSStatus" method call of network interface.
2165 DBusMessage * wpas_dbus_handler_tdls_status(DBusMessage *message,
2166 struct wpa_supplicant *wpa_s)
2170 const char *tdls_status;
2172 if (get_peer_hwaddr_helper(message, __func__, peer, &reply) < 0)
2175 wpa_printf(MSG_DEBUG, "DBUS TDLS_STATUS " MACSTR, MAC2STR(peer));
2177 tdls_status = wpa_tdls_get_link_status(wpa_s->wpa, peer);
2179 reply = dbus_message_new_method_return(message);
2180 dbus_message_append_args(reply, DBUS_TYPE_STRING,
2181 &tdls_status, DBUS_TYPE_INVALID);
2187 * wpas_dbus_handler_tdls_teardown - Teardown TDLS session
2188 * @message: Pointer to incoming dbus message
2189 * @wpa_s: wpa_supplicant structure for a network interface
2190 * Returns: NULL indicating success or DBus error message on failure
2192 * Handler function for "TDLSTeardown" method call of network interface.
2194 DBusMessage * wpas_dbus_handler_tdls_teardown(DBusMessage *message,
2195 struct wpa_supplicant *wpa_s)
2198 DBusMessage *error_reply;
2201 if (get_peer_hwaddr_helper(message, __func__, peer, &error_reply) < 0)
2204 wpa_printf(MSG_DEBUG, "DBUS TDLS_TEARDOWN " MACSTR, MAC2STR(peer));
2206 if (wpa_tdls_is_external_setup(wpa_s->wpa))
2207 ret = wpa_tdls_teardown_link(
2209 WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
2211 ret = wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
2214 return wpas_dbus_error_unknown_error(
2215 message, "error performing TDLS teardown");
2221 #endif /* CONFIG_TDLS */
2225 * wpas_dbus_handler_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
2226 * @message: Pointer to incoming dbus message
2227 * @wpa_s: %wpa_supplicant data structure
2228 * Returns: A dbus message containing an error on failure or NULL on success
2230 * Sets the PKCS #11 engine and module path.
2232 DBusMessage * wpas_dbus_handler_set_pkcs11_engine_and_module_path(
2233 DBusMessage *message, struct wpa_supplicant *wpa_s)
2235 DBusMessageIter iter;
2237 char *pkcs11_engine_path = NULL;
2238 char *pkcs11_module_path = NULL;
2240 dbus_message_iter_init(message, &iter);
2241 dbus_message_iter_get_basic(&iter, &value);
2242 if (value == NULL) {
2243 return dbus_message_new_error(
2244 message, DBUS_ERROR_INVALID_ARGS,
2245 "Invalid pkcs11_engine_path argument");
2247 /* Empty path defaults to NULL */
2248 if (os_strlen(value))
2249 pkcs11_engine_path = value;
2251 dbus_message_iter_next(&iter);
2252 dbus_message_iter_get_basic(&iter, &value);
2253 if (value == NULL) {
2254 os_free(pkcs11_engine_path);
2255 return dbus_message_new_error(
2256 message, DBUS_ERROR_INVALID_ARGS,
2257 "Invalid pkcs11_module_path argument");
2259 /* Empty path defaults to NULL */
2260 if (os_strlen(value))
2261 pkcs11_module_path = value;
2263 if (wpas_set_pkcs11_engine_and_module_path(wpa_s, pkcs11_engine_path,
2264 pkcs11_module_path))
2265 return dbus_message_new_error(
2266 message, DBUS_ERROR_FAILED,
2267 "Reinit of the EAPOL state machine with the new PKCS #11 engine and module path failed.");
2269 wpa_dbus_mark_property_changed(
2270 wpa_s->global->dbus, wpa_s->dbus_new_path,
2271 WPAS_DBUS_NEW_IFACE_INTERFACE, "PKCS11EnginePath");
2272 wpa_dbus_mark_property_changed(
2273 wpa_s->global->dbus, wpa_s->dbus_new_path,
2274 WPAS_DBUS_NEW_IFACE_INTERFACE, "PKCS11ModulePath");
2281 * wpas_dbus_getter_capabilities - Return interface capabilities
2282 * @iter: Pointer to incoming dbus message iter
2283 * @error: Location to store error on failure
2284 * @user_data: Function specific data
2285 * Returns: TRUE on success, FALSE on failure
2287 * Getter for "Capabilities" property of an interface.
2289 dbus_bool_t wpas_dbus_getter_capabilities(DBusMessageIter *iter,
2290 DBusError *error, void *user_data)
2292 struct wpa_supplicant *wpa_s = user_data;
2293 struct wpa_driver_capa capa;
2295 DBusMessageIter iter_dict, iter_dict_entry, iter_dict_val, iter_array,
2297 const char *scans[] = { "active", "passive", "ssid" };
2299 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
2300 "a{sv}", &variant_iter) ||
2301 !wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
2304 res = wpa_drv_get_capa(wpa_s, &capa);
2306 /***** pairwise cipher */
2308 const char *args[] = {"ccmp", "tkip", "none"};
2310 if (!wpa_dbus_dict_append_string_array(
2311 &iter_dict, "Pairwise", args,
2315 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Pairwise",
2319 ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP_256) &&
2320 !wpa_dbus_dict_string_array_add_element(
2321 &iter_array, "ccmp-256")) ||
2322 ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP_256) &&
2323 !wpa_dbus_dict_string_array_add_element(
2324 &iter_array, "gcmp-256")) ||
2325 ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) &&
2326 !wpa_dbus_dict_string_array_add_element(
2327 &iter_array, "ccmp")) ||
2328 ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP) &&
2329 !wpa_dbus_dict_string_array_add_element(
2330 &iter_array, "gcmp")) ||
2331 ((capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) &&
2332 !wpa_dbus_dict_string_array_add_element(
2333 &iter_array, "tkip")) ||
2334 ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) &&
2335 !wpa_dbus_dict_string_array_add_element(
2336 &iter_array, "none")) ||
2337 !wpa_dbus_dict_end_string_array(&iter_dict,
2344 /***** group cipher */
2346 const char *args[] = {
2347 "ccmp", "tkip", "wep104", "wep40"
2350 if (!wpa_dbus_dict_append_string_array(
2351 &iter_dict, "Group", args,
2355 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Group",
2359 ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP_256) &&
2360 !wpa_dbus_dict_string_array_add_element(
2361 &iter_array, "ccmp-256")) ||
2362 ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP_256) &&
2363 !wpa_dbus_dict_string_array_add_element(
2364 &iter_array, "gcmp-256")) ||
2365 ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) &&
2366 !wpa_dbus_dict_string_array_add_element(
2367 &iter_array, "ccmp")) ||
2368 ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP) &&
2369 !wpa_dbus_dict_string_array_add_element(
2370 &iter_array, "gcmp")) ||
2371 ((capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) &&
2372 !wpa_dbus_dict_string_array_add_element(
2373 &iter_array, "tkip")) ||
2374 ((capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) &&
2375 !wpa_dbus_dict_string_array_add_element(
2376 &iter_array, "wep104")) ||
2377 ((capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) &&
2378 !wpa_dbus_dict_string_array_add_element(
2379 &iter_array, "wep40")) ||
2380 !wpa_dbus_dict_end_string_array(&iter_dict,
2387 /***** key management */
2389 const char *args[] = {
2390 "wpa-psk", "wpa-eap", "ieee8021x", "wpa-none",
2393 #endif /* CONFIG_WPS */
2396 if (!wpa_dbus_dict_append_string_array(
2397 &iter_dict, "KeyMgmt", args,
2401 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "KeyMgmt",
2405 !wpa_dbus_dict_string_array_add_element(&iter_array,
2407 !wpa_dbus_dict_string_array_add_element(&iter_array,
2411 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
2412 WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
2413 if (!wpa_dbus_dict_string_array_add_element(
2414 &iter_array, "wpa-eap") ||
2415 ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT) &&
2416 !wpa_dbus_dict_string_array_add_element(
2417 &iter_array, "wpa-ft-eap")))
2420 /* TODO: Ensure that driver actually supports sha256 encryption. */
2421 #ifdef CONFIG_IEEE80211W
2422 if (!wpa_dbus_dict_string_array_add_element(
2423 &iter_array, "wpa-eap-sha256"))
2425 #endif /* CONFIG_IEEE80211W */
2428 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
2429 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
2430 if (!wpa_dbus_dict_string_array_add_element(
2431 &iter_array, "wpa-psk") ||
2433 WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK) &&
2434 !wpa_dbus_dict_string_array_add_element(
2435 &iter_array, "wpa-ft-psk")))
2438 /* TODO: Ensure that driver actually supports sha256 encryption. */
2439 #ifdef CONFIG_IEEE80211W
2440 if (!wpa_dbus_dict_string_array_add_element(
2441 &iter_array, "wpa-psk-sha256"))
2443 #endif /* CONFIG_IEEE80211W */
2446 if ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) &&
2447 !wpa_dbus_dict_string_array_add_element(&iter_array,
2453 if (!wpa_dbus_dict_string_array_add_element(&iter_array,
2456 #endif /* CONFIG_WPS */
2458 if (!wpa_dbus_dict_end_string_array(&iter_dict,
2465 /***** WPA protocol */
2467 const char *args[] = { "rsn", "wpa" };
2469 if (!wpa_dbus_dict_append_string_array(
2470 &iter_dict, "Protocol", args,
2474 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Protocol",
2478 ((capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
2479 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) &&
2480 !wpa_dbus_dict_string_array_add_element(
2481 &iter_array, "rsn")) ||
2482 ((capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
2483 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) &&
2484 !wpa_dbus_dict_string_array_add_element(
2485 &iter_array, "wpa")) ||
2486 !wpa_dbus_dict_end_string_array(&iter_dict,
2495 const char *args[] = { "open", "shared", "leap" };
2497 if (!wpa_dbus_dict_append_string_array(
2498 &iter_dict, "AuthAlg", args,
2502 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "AuthAlg",
2508 if (((capa.auth & WPA_DRIVER_AUTH_OPEN) &&
2509 !wpa_dbus_dict_string_array_add_element(
2510 &iter_array, "open")) ||
2511 ((capa.auth & WPA_DRIVER_AUTH_SHARED) &&
2512 !wpa_dbus_dict_string_array_add_element(
2513 &iter_array, "shared")) ||
2514 ((capa.auth & WPA_DRIVER_AUTH_LEAP) &&
2515 !wpa_dbus_dict_string_array_add_element(
2516 &iter_array, "leap")) ||
2517 !wpa_dbus_dict_end_string_array(&iter_dict,
2525 if (!wpa_dbus_dict_append_string_array(&iter_dict, "Scan", scans,
2530 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Modes",
2534 !wpa_dbus_dict_string_array_add_element(
2535 &iter_array, "infrastructure") ||
2536 !wpa_dbus_dict_string_array_add_element(
2537 &iter_array, "ad-hoc") ||
2538 (res >= 0 && (capa.flags & WPA_DRIVER_FLAGS_AP) &&
2539 !wpa_dbus_dict_string_array_add_element(
2540 &iter_array, "ap")) ||
2541 (res >= 0 && (capa.flags & WPA_DRIVER_FLAGS_P2P_CAPABLE) &&
2542 !wpa_dbus_dict_string_array_add_element(
2543 &iter_array, "p2p")) ||
2544 !wpa_dbus_dict_end_string_array(&iter_dict,
2552 dbus_int32_t max_scan_ssid = capa.max_scan_ssids;
2554 if (!wpa_dbus_dict_append_int32(&iter_dict, "MaxScanSSID",
2559 if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict) ||
2560 !dbus_message_iter_close_container(iter, &variant_iter))
2566 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
2572 * wpas_dbus_getter_state - Get interface state
2573 * @iter: Pointer to incoming dbus message iter
2574 * @error: Location to store error on failure
2575 * @user_data: Function specific data
2576 * Returns: TRUE on success, FALSE on failure
2578 * Getter for "State" property.
2580 dbus_bool_t wpas_dbus_getter_state(DBusMessageIter *iter, DBusError *error,
2583 struct wpa_supplicant *wpa_s = user_data;
2584 const char *str_state;
2585 char *state_ls, *tmp;
2586 dbus_bool_t success = FALSE;
2588 str_state = wpa_supplicant_state_txt(wpa_s->wpa_state);
2590 /* make state string lowercase to fit new DBus API convention
2592 state_ls = tmp = os_strdup(str_state);
2594 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
2598 *tmp = tolower(*tmp);
2602 success = wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
2612 * wpas_dbus_new_iface_get_scanning - Get interface scanning state
2613 * @iter: Pointer to incoming dbus message iter
2614 * @error: Location to store error on failure
2615 * @user_data: Function specific data
2616 * Returns: TRUE on success, FALSE on failure
2618 * Getter for "scanning" property.
2620 dbus_bool_t wpas_dbus_getter_scanning(DBusMessageIter *iter, DBusError *error,
2623 struct wpa_supplicant *wpa_s = user_data;
2624 dbus_bool_t scanning = wpa_s->scanning ? TRUE : FALSE;
2626 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
2632 * wpas_dbus_getter_ap_scan - Control roaming mode
2633 * @iter: Pointer to incoming dbus message iter
2634 * @error: Location to store error on failure
2635 * @user_data: Function specific data
2636 * Returns: TRUE on success, FALSE on failure
2638 * Getter function for "ApScan" property.
2640 dbus_bool_t wpas_dbus_getter_ap_scan(DBusMessageIter *iter, DBusError *error,
2643 struct wpa_supplicant *wpa_s = user_data;
2644 dbus_uint32_t ap_scan = wpa_s->conf->ap_scan;
2646 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
2652 * wpas_dbus_setter_ap_scan - Control roaming mode
2653 * @iter: Pointer to incoming dbus message iter
2654 * @error: Location to store error on failure
2655 * @user_data: Function specific data
2656 * Returns: TRUE on success, FALSE on failure
2658 * Setter function for "ApScan" property.
2660 dbus_bool_t wpas_dbus_setter_ap_scan(DBusMessageIter *iter, DBusError *error,
2663 struct wpa_supplicant *wpa_s = user_data;
2664 dbus_uint32_t ap_scan;
2666 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
2670 if (wpa_supplicant_set_ap_scan(wpa_s, ap_scan)) {
2671 dbus_set_error_const(error, DBUS_ERROR_FAILED,
2672 "ap_scan must be 0, 1, or 2");
2680 * wpas_dbus_getter_fast_reauth - Control fast
2681 * reauthentication (TLS session resumption)
2682 * @iter: Pointer to incoming dbus message iter
2683 * @error: Location to store error on failure
2684 * @user_data: Function specific data
2685 * Returns: TRUE on success, FALSE on failure
2687 * Getter function for "FastReauth" property.
2689 dbus_bool_t wpas_dbus_getter_fast_reauth(DBusMessageIter *iter,
2693 struct wpa_supplicant *wpa_s = user_data;
2694 dbus_bool_t fast_reauth = wpa_s->conf->fast_reauth ? TRUE : FALSE;
2696 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
2697 &fast_reauth, error);
2702 * wpas_dbus_setter_fast_reauth - Control fast
2703 * reauthentication (TLS session resumption)
2704 * @iter: Pointer to incoming dbus message iter
2705 * @error: Location to store error on failure
2706 * @user_data: Function specific data
2707 * Returns: TRUE on success, FALSE on failure
2709 * Setter function for "FastReauth" property.
2711 dbus_bool_t wpas_dbus_setter_fast_reauth(DBusMessageIter *iter,
2715 struct wpa_supplicant *wpa_s = user_data;
2716 dbus_bool_t fast_reauth;
2718 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
2722 wpa_s->conf->fast_reauth = fast_reauth;
2728 * wpas_dbus_getter_disconnect_reason - Get most recent reason for disconnect
2729 * @iter: Pointer to incoming dbus message iter
2730 * @error: Location to store error on failure
2731 * @user_data: Function specific data
2732 * Returns: TRUE on success, FALSE on failure
2734 * Getter for "DisconnectReason" property. The reason is negative if it is
2735 * locally generated.
2737 dbus_bool_t wpas_dbus_getter_disconnect_reason(DBusMessageIter *iter,
2741 struct wpa_supplicant *wpa_s = user_data;
2742 dbus_int32_t reason = wpa_s->disconnect_reason;
2744 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
2750 * wpas_dbus_getter_bss_expire_age - Get BSS entry expiration age
2751 * @iter: Pointer to incoming dbus message iter
2752 * @error: Location to store error on failure
2753 * @user_data: Function specific data
2754 * Returns: TRUE on success, FALSE on failure
2756 * Getter function for "BSSExpireAge" property.
2758 dbus_bool_t wpas_dbus_getter_bss_expire_age(DBusMessageIter *iter,
2762 struct wpa_supplicant *wpa_s = user_data;
2763 dbus_uint32_t expire_age = wpa_s->conf->bss_expiration_age;
2765 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
2766 &expire_age, error);
2771 * wpas_dbus_setter_bss_expire_age - Control BSS entry expiration age
2772 * @iter: Pointer to incoming dbus message iter
2773 * @error: Location to store error on failure
2774 * @user_data: Function specific data
2775 * Returns: TRUE on success, FALSE on failure
2777 * Setter function for "BSSExpireAge" property.
2779 dbus_bool_t wpas_dbus_setter_bss_expire_age(DBusMessageIter *iter,
2783 struct wpa_supplicant *wpa_s = user_data;
2784 dbus_uint32_t expire_age;
2786 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
2790 if (wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age)) {
2791 dbus_set_error_const(error, DBUS_ERROR_FAILED,
2792 "BSSExpireAge must be >= 10");
2800 * wpas_dbus_getter_bss_expire_count - Get BSS entry expiration scan count
2801 * @iter: Pointer to incoming dbus message iter
2802 * @error: Location to store error on failure
2803 * @user_data: Function specific data
2804 * Returns: TRUE on success, FALSE on failure
2806 * Getter function for "BSSExpireCount" property.
2808 dbus_bool_t wpas_dbus_getter_bss_expire_count(DBusMessageIter *iter,
2812 struct wpa_supplicant *wpa_s = user_data;
2813 dbus_uint32_t expire_count = wpa_s->conf->bss_expiration_scan_count;
2815 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
2816 &expire_count, error);
2821 * wpas_dbus_setter_bss_expire_count - Control BSS entry expiration scan count
2822 * @iter: Pointer to incoming dbus message iter
2823 * @error: Location to store error on failure
2824 * @user_data: Function specific data
2825 * Returns: TRUE on success, FALSE on failure
2827 * Setter function for "BSSExpireCount" property.
2829 dbus_bool_t wpas_dbus_setter_bss_expire_count(DBusMessageIter *iter,
2833 struct wpa_supplicant *wpa_s = user_data;
2834 dbus_uint32_t expire_count;
2836 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
2840 if (wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count)) {
2841 dbus_set_error_const(error, DBUS_ERROR_FAILED,
2842 "BSSExpireCount must be > 0");
2850 * wpas_dbus_getter_country - Control country code
2851 * @iter: Pointer to incoming dbus message iter
2852 * @error: Location to store error on failure
2853 * @user_data: Function specific data
2854 * Returns: TRUE on success, FALSE on failure
2856 * Getter function for "Country" property.
2858 dbus_bool_t wpas_dbus_getter_country(DBusMessageIter *iter, DBusError *error,
2861 struct wpa_supplicant *wpa_s = user_data;
2863 char *str = country;
2865 country[0] = wpa_s->conf->country[0];
2866 country[1] = wpa_s->conf->country[1];
2869 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
2875 * wpas_dbus_setter_country - Control country code
2876 * @iter: Pointer to incoming dbus message iter
2877 * @error: Location to store error on failure
2878 * @user_data: Function specific data
2879 * Returns: TRUE on success, FALSE on failure
2881 * Setter function for "Country" property.
2883 dbus_bool_t wpas_dbus_setter_country(DBusMessageIter *iter, DBusError *error,
2886 struct wpa_supplicant *wpa_s = user_data;
2887 const char *country;
2889 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
2893 if (!country[0] || !country[1]) {
2894 dbus_set_error_const(error, DBUS_ERROR_FAILED,
2895 "invalid country code");
2899 if (wpa_s->drv_priv != NULL && wpa_drv_set_country(wpa_s, country)) {
2900 wpa_printf(MSG_DEBUG, "Failed to set country");
2901 dbus_set_error_const(error, DBUS_ERROR_FAILED,
2902 "failed to set country code");
2906 wpa_s->conf->country[0] = country[0];
2907 wpa_s->conf->country[1] = country[1];
2913 * wpas_dbus_getter_scan_interval - Get scan interval
2914 * @iter: Pointer to incoming dbus message iter
2915 * @error: Location to store error on failure
2916 * @user_data: Function specific data
2917 * Returns: TRUE on success, FALSE on failure
2919 * Getter function for "ScanInterval" property.
2921 dbus_bool_t wpas_dbus_getter_scan_interval(DBusMessageIter *iter,
2925 struct wpa_supplicant *wpa_s = user_data;
2926 dbus_int32_t scan_interval = wpa_s->scan_interval;
2928 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
2929 &scan_interval, error);
2934 * wpas_dbus_setter_scan_interval - Control scan interval
2935 * @iter: Pointer to incoming dbus message iter
2936 * @error: Location to store error on failure
2937 * @user_data: Function specific data
2938 * Returns: TRUE on success, FALSE on failure
2940 * Setter function for "ScanInterval" property.
2942 dbus_bool_t wpas_dbus_setter_scan_interval(DBusMessageIter *iter,
2946 struct wpa_supplicant *wpa_s = user_data;
2947 dbus_int32_t scan_interval;
2949 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_INT32,
2953 if (wpa_supplicant_set_scan_interval(wpa_s, scan_interval)) {
2954 dbus_set_error_const(error, DBUS_ERROR_FAILED,
2955 "scan_interval must be >= 0");
2963 * wpas_dbus_getter_ifname - Get interface name
2964 * @iter: Pointer to incoming dbus message iter
2965 * @error: Location to store error on failure
2966 * @user_data: Function specific data
2967 * Returns: TRUE on success, FALSE on failure
2969 * Getter for "Ifname" property.
2971 dbus_bool_t wpas_dbus_getter_ifname(DBusMessageIter *iter, DBusError *error,
2974 struct wpa_supplicant *wpa_s = user_data;
2975 const char *ifname = wpa_s->ifname;
2977 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
2983 * wpas_dbus_getter_driver - Get interface name
2984 * @iter: Pointer to incoming dbus message iter
2985 * @error: Location to store error on failure
2986 * @user_data: Function specific data
2987 * Returns: TRUE on success, FALSE on failure
2989 * Getter for "Driver" property.
2991 dbus_bool_t wpas_dbus_getter_driver(DBusMessageIter *iter, DBusError *error,
2994 struct wpa_supplicant *wpa_s = user_data;
2997 if (wpa_s->driver == NULL || wpa_s->driver->name == NULL) {
2998 wpa_printf(MSG_DEBUG, "%s[dbus]: wpa_s has no driver set",
3000 dbus_set_error(error, DBUS_ERROR_FAILED, "%s: no driver set",
3005 driver = wpa_s->driver->name;
3006 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3012 * wpas_dbus_getter_current_bss - Get current bss object path
3013 * @iter: Pointer to incoming dbus message iter
3014 * @error: Location to store error on failure
3015 * @user_data: Function specific data
3016 * Returns: TRUE on success, FALSE on failure
3018 * Getter for "CurrentBSS" property.
3020 dbus_bool_t wpas_dbus_getter_current_bss(DBusMessageIter *iter,
3024 struct wpa_supplicant *wpa_s = user_data;
3025 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *bss_obj_path = path_buf;
3027 if (wpa_s->current_bss)
3028 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3029 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
3030 wpa_s->dbus_new_path, wpa_s->current_bss->id);
3032 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
3034 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
3035 &bss_obj_path, error);
3040 * wpas_dbus_getter_current_network - Get current network object path
3041 * @iter: Pointer to incoming dbus message iter
3042 * @error: Location to store error on failure
3043 * @user_data: Function specific data
3044 * Returns: TRUE on success, FALSE on failure
3046 * Getter for "CurrentNetwork" property.
3048 dbus_bool_t wpas_dbus_getter_current_network(DBusMessageIter *iter,
3052 struct wpa_supplicant *wpa_s = user_data;
3053 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *net_obj_path = path_buf;
3055 if (wpa_s->current_ssid)
3056 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3057 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
3058 wpa_s->dbus_new_path, wpa_s->current_ssid->id);
3060 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
3062 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
3063 &net_obj_path, error);
3068 * wpas_dbus_getter_current_auth_mode - Get current authentication type
3069 * @iter: Pointer to incoming dbus message iter
3070 * @error: Location to store error on failure
3071 * @user_data: Function specific data
3072 * Returns: TRUE on success, FALSE on failure
3074 * Getter for "CurrentAuthMode" property.
3076 dbus_bool_t wpas_dbus_getter_current_auth_mode(DBusMessageIter *iter,
3080 struct wpa_supplicant *wpa_s = user_data;
3081 const char *eap_mode;
3082 const char *auth_mode;
3083 char eap_mode_buf[WPAS_DBUS_AUTH_MODE_MAX];
3085 if (wpa_s->wpa_state != WPA_COMPLETED) {
3086 auth_mode = "INACTIVE";
3087 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X ||
3088 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3089 eap_mode = wpa_supplicant_get_eap_mode(wpa_s);
3090 os_snprintf(eap_mode_buf, WPAS_DBUS_AUTH_MODE_MAX,
3091 "EAP-%s", eap_mode);
3092 auth_mode = eap_mode_buf;
3095 auth_mode = wpa_key_mgmt_txt(wpa_s->key_mgmt,
3096 wpa_s->current_ssid->proto);
3099 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3105 * wpas_dbus_getter_bridge_ifname - Get interface name
3106 * @iter: Pointer to incoming dbus message iter
3107 * @error: Location to store error on failure
3108 * @user_data: Function specific data
3109 * Returns: TRUE on success, FALSE on failure
3111 * Getter for "BridgeIfname" property.
3113 dbus_bool_t wpas_dbus_getter_bridge_ifname(DBusMessageIter *iter,
3117 struct wpa_supplicant *wpa_s = user_data;
3118 const char *bridge_ifname = wpa_s->bridge_ifname;
3120 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3121 &bridge_ifname, error);
3126 * wpas_dbus_getter_bsss - Get array of BSSs objects
3127 * @iter: Pointer to incoming dbus message iter
3128 * @error: Location to store error on failure
3129 * @user_data: Function specific data
3130 * Returns: TRUE on success, FALSE on failure
3132 * Getter for "BSSs" property.
3134 dbus_bool_t wpas_dbus_getter_bsss(DBusMessageIter *iter, DBusError *error,
3137 struct wpa_supplicant *wpa_s = user_data;
3138 struct wpa_bss *bss;
3141 dbus_bool_t success = FALSE;
3143 paths = os_calloc(wpa_s->num_bss, sizeof(char *));
3145 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3149 /* Loop through scan results and append each result's object path */
3150 dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
3151 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
3152 if (paths[i] == NULL) {
3153 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
3157 /* Construct the object path for this BSS. */
3158 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
3159 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
3160 wpa_s->dbus_new_path, bss->id);
3163 success = wpas_dbus_simple_array_property_getter(iter,
3164 DBUS_TYPE_OBJECT_PATH,
3165 paths, wpa_s->num_bss,
3170 os_free(paths[--i]);
3177 * wpas_dbus_getter_networks - Get array of networks objects
3178 * @iter: Pointer to incoming dbus message iter
3179 * @error: Location to store error on failure
3180 * @user_data: Function specific data
3181 * Returns: TRUE on success, FALSE on failure
3183 * Getter for "Networks" property.
3185 dbus_bool_t wpas_dbus_getter_networks(DBusMessageIter *iter, DBusError *error,
3188 struct wpa_supplicant *wpa_s = user_data;
3189 struct wpa_ssid *ssid;
3191 unsigned int i = 0, num = 0;
3192 dbus_bool_t success = FALSE;
3194 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
3195 if (!network_is_persistent_group(ssid))
3198 paths = os_calloc(num, sizeof(char *));
3200 dbus_set_error(error, DBUS_ERROR_NO_MEMORY, "no memory");
3204 /* Loop through configured networks and append object path of each */
3205 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
3206 if (network_is_persistent_group(ssid))
3208 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
3209 if (paths[i] == NULL) {
3210 dbus_set_error(error, DBUS_ERROR_NO_MEMORY,
3215 /* Construct the object path for this network. */
3216 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
3217 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
3218 wpa_s->dbus_new_path, ssid->id);
3221 success = wpas_dbus_simple_array_property_getter(iter,
3222 DBUS_TYPE_OBJECT_PATH,
3227 os_free(paths[--i]);
3234 * wpas_dbus_getter_pkcs11_engine_path - Get PKCS #11 engine path
3235 * @iter: Pointer to incoming dbus message iter
3236 * @error: Location to store error on failure
3237 * @user_data: Function specific data
3238 * Returns: A dbus message containing the PKCS #11 engine path
3240 * Getter for "PKCS11EnginePath" property.
3242 dbus_bool_t wpas_dbus_getter_pkcs11_engine_path(DBusMessageIter *iter,
3246 struct wpa_supplicant *wpa_s = user_data;
3247 const char *pkcs11_engine_path;
3249 if (wpa_s->conf->pkcs11_engine_path == NULL)
3250 pkcs11_engine_path = "";
3252 pkcs11_engine_path = wpa_s->conf->pkcs11_engine_path;
3253 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3254 &pkcs11_engine_path, error);
3259 * wpas_dbus_getter_pkcs11_module_path - Get PKCS #11 module path
3260 * @iter: Pointer to incoming dbus message iter
3261 * @error: Location to store error on failure
3262 * @user_data: Function specific data
3263 * Returns: A dbus message containing the PKCS #11 module path
3265 * Getter for "PKCS11ModulePath" property.
3267 dbus_bool_t wpas_dbus_getter_pkcs11_module_path(DBusMessageIter *iter,
3271 struct wpa_supplicant *wpa_s = user_data;
3272 const char *pkcs11_module_path;
3274 if (wpa_s->conf->pkcs11_module_path == NULL)
3275 pkcs11_module_path = "";
3277 pkcs11_module_path = wpa_s->conf->pkcs11_module_path;
3278 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3279 &pkcs11_module_path, error);
3284 * wpas_dbus_getter_blobs - Get all blobs defined for this interface
3285 * @iter: Pointer to incoming dbus message iter
3286 * @error: Location to store error on failure
3287 * @user_data: Function specific data
3288 * Returns: TRUE on success, FALSE on failure
3290 * Getter for "Blobs" property.
3292 dbus_bool_t wpas_dbus_getter_blobs(DBusMessageIter *iter, DBusError *error,
3295 struct wpa_supplicant *wpa_s = user_data;
3296 DBusMessageIter variant_iter, dict_iter, entry_iter, array_iter;
3297 struct wpa_config_blob *blob;
3299 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
3300 "a{say}", &variant_iter) ||
3301 !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
3302 "{say}", &dict_iter)) {
3303 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3307 blob = wpa_s->conf->blobs;
3309 if (!dbus_message_iter_open_container(&dict_iter,
3310 DBUS_TYPE_DICT_ENTRY,
3311 NULL, &entry_iter) ||
3312 !dbus_message_iter_append_basic(&entry_iter,
3315 !dbus_message_iter_open_container(&entry_iter,
3317 DBUS_TYPE_BYTE_AS_STRING,
3319 !dbus_message_iter_append_fixed_array(&array_iter,
3323 !dbus_message_iter_close_container(&entry_iter,
3325 !dbus_message_iter_close_container(&dict_iter,
3327 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
3335 if (!dbus_message_iter_close_container(&variant_iter, &dict_iter) ||
3336 !dbus_message_iter_close_container(iter, &variant_iter)) {
3337 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3345 static struct wpa_bss * get_bss_helper(struct bss_handler_args *args,
3346 DBusError *error, const char *func_name)
3348 struct wpa_bss *res = wpa_bss_get_id(args->wpa_s, args->id);
3351 wpa_printf(MSG_ERROR, "%s[dbus]: no bss with id %d found",
3352 func_name, args->id);
3353 dbus_set_error(error, DBUS_ERROR_FAILED,
3354 "%s: BSS %d not found",
3355 func_name, args->id);
3363 * wpas_dbus_getter_bss_bssid - Return the BSSID of a BSS
3364 * @iter: Pointer to incoming dbus message iter
3365 * @error: Location to store error on failure
3366 * @user_data: Function specific data
3367 * Returns: TRUE on success, FALSE on failure
3369 * Getter for "BSSID" property.
3371 dbus_bool_t wpas_dbus_getter_bss_bssid(DBusMessageIter *iter, DBusError *error,
3374 struct bss_handler_args *args = user_data;
3375 struct wpa_bss *res;
3377 res = get_bss_helper(args, error, __func__);
3381 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
3382 res->bssid, ETH_ALEN,
3388 * wpas_dbus_getter_bss_ssid - Return the SSID of a BSS
3389 * @iter: Pointer to incoming dbus message iter
3390 * @error: Location to store error on failure
3391 * @user_data: Function specific data
3392 * Returns: TRUE on success, FALSE on failure
3394 * Getter for "SSID" property.
3396 dbus_bool_t wpas_dbus_getter_bss_ssid(DBusMessageIter *iter, DBusError *error,
3399 struct bss_handler_args *args = user_data;
3400 struct wpa_bss *res;
3402 res = get_bss_helper(args, error, __func__);
3406 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
3407 res->ssid, res->ssid_len,
3413 * wpas_dbus_getter_bss_privacy - Return the privacy flag of a BSS
3414 * @iter: Pointer to incoming dbus message iter
3415 * @error: Location to store error on failure
3416 * @user_data: Function specific data
3417 * Returns: TRUE on success, FALSE on failure
3419 * Getter for "Privacy" property.
3421 dbus_bool_t wpas_dbus_getter_bss_privacy(DBusMessageIter *iter,
3422 DBusError *error, void *user_data)
3424 struct bss_handler_args *args = user_data;
3425 struct wpa_bss *res;
3426 dbus_bool_t privacy;
3428 res = get_bss_helper(args, error, __func__);
3432 privacy = (res->caps & IEEE80211_CAP_PRIVACY) ? TRUE : FALSE;
3433 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
3439 * wpas_dbus_getter_bss_mode - Return the mode of a BSS
3440 * @iter: Pointer to incoming dbus message iter
3441 * @error: Location to store error on failure
3442 * @user_data: Function specific data
3443 * Returns: TRUE on success, FALSE on failure
3445 * Getter for "Mode" property.
3447 dbus_bool_t wpas_dbus_getter_bss_mode(DBusMessageIter *iter, DBusError *error,
3450 struct bss_handler_args *args = user_data;
3451 struct wpa_bss *res;
3454 res = get_bss_helper(args, error, __func__);
3457 if (bss_is_dmg(res)) {
3458 switch (res->caps & IEEE80211_CAP_DMG_MASK) {
3459 case IEEE80211_CAP_DMG_PBSS:
3460 case IEEE80211_CAP_DMG_IBSS:
3463 case IEEE80211_CAP_DMG_AP:
3464 mode = "infrastructure";
3468 if (res->caps & IEEE80211_CAP_IBSS)
3471 mode = "infrastructure";
3474 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3480 * wpas_dbus_getter_bss_level - Return the signal strength of a BSS
3481 * @iter: Pointer to incoming dbus message iter
3482 * @error: Location to store error on failure
3483 * @user_data: Function specific data
3484 * Returns: TRUE on success, FALSE on failure
3486 * Getter for "Level" property.
3488 dbus_bool_t wpas_dbus_getter_bss_signal(DBusMessageIter *iter,
3489 DBusError *error, void *user_data)
3491 struct bss_handler_args *args = user_data;
3492 struct wpa_bss *res;
3495 res = get_bss_helper(args, error, __func__);
3499 level = (s16) res->level;
3500 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT16,
3506 * wpas_dbus_getter_bss_frequency - Return the frequency of a BSS
3507 * @iter: Pointer to incoming dbus message iter
3508 * @error: Location to store error on failure
3509 * @user_data: Function specific data
3510 * Returns: TRUE on success, FALSE on failure
3512 * Getter for "Frequency" property.
3514 dbus_bool_t wpas_dbus_getter_bss_frequency(DBusMessageIter *iter,
3515 DBusError *error, void *user_data)
3517 struct bss_handler_args *args = user_data;
3518 struct wpa_bss *res;
3521 res = get_bss_helper(args, error, __func__);
3525 freq = (u16) res->freq;
3526 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
3531 static int cmp_u8s_desc(const void *a, const void *b)
3533 return (*(u8 *) b - *(u8 *) a);
3538 * wpas_dbus_getter_bss_rates - Return available bit rates of a BSS
3539 * @iter: Pointer to incoming dbus message iter
3540 * @error: Location to store error on failure
3541 * @user_data: Function specific data
3542 * Returns: TRUE on success, FALSE on failure
3544 * Getter for "Rates" property.
3546 dbus_bool_t wpas_dbus_getter_bss_rates(DBusMessageIter *iter,
3547 DBusError *error, void *user_data)
3549 struct bss_handler_args *args = user_data;
3550 struct wpa_bss *res;
3551 u8 *ie_rates = NULL;
3554 dbus_bool_t success = FALSE;
3556 res = get_bss_helper(args, error, __func__);
3560 rates_num = wpa_bss_get_bit_rates(res, &ie_rates);
3564 qsort(ie_rates, rates_num, 1, cmp_u8s_desc);
3566 real_rates = os_malloc(sizeof(u32) * rates_num);
3569 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3573 for (i = 0; i < rates_num; i++)
3574 real_rates[i] = ie_rates[i] * 500000;
3576 success = wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_UINT32,
3577 real_rates, rates_num,
3581 os_free(real_rates);
3586 static dbus_bool_t wpas_dbus_get_bss_security_prop(DBusMessageIter *iter,
3587 struct wpa_ie_data *ie_data,
3590 DBusMessageIter iter_dict, variant_iter;
3592 const char *pairwise[5]; /* max 5 pairwise ciphers is supported */
3593 const char *key_mgmt[9]; /* max 9 key managements may be supported */
3596 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
3597 "a{sv}", &variant_iter))
3600 if (!wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
3605 if (ie_data->key_mgmt & WPA_KEY_MGMT_PSK)
3606 key_mgmt[n++] = "wpa-psk";
3607 if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_PSK)
3608 key_mgmt[n++] = "wpa-ft-psk";
3609 if (ie_data->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
3610 key_mgmt[n++] = "wpa-psk-sha256";
3611 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X)
3612 key_mgmt[n++] = "wpa-eap";
3613 if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X)
3614 key_mgmt[n++] = "wpa-ft-eap";
3615 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256)
3616 key_mgmt[n++] = "wpa-eap-sha256";
3617 #ifdef CONFIG_SUITEB
3618 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B)
3619 key_mgmt[n++] = "wpa-eap-suite-b";
3620 #endif /* CONFIG_SUITEB */
3621 #ifdef CONFIG_SUITEB192
3622 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
3623 key_mgmt[n++] = "wpa-eap-suite-b-192";
3624 #endif /* CONFIG_SUITEB192 */
3625 if (ie_data->key_mgmt & WPA_KEY_MGMT_NONE)
3626 key_mgmt[n++] = "wpa-none";
3628 if (!wpa_dbus_dict_append_string_array(&iter_dict, "KeyMgmt",
3633 switch (ie_data->group_cipher) {
3634 case WPA_CIPHER_WEP40:
3637 case WPA_CIPHER_TKIP:
3640 case WPA_CIPHER_CCMP:
3643 case WPA_CIPHER_GCMP:
3646 case WPA_CIPHER_WEP104:
3649 case WPA_CIPHER_CCMP_256:
3652 case WPA_CIPHER_GCMP_256:
3660 if (!wpa_dbus_dict_append_string(&iter_dict, "Group", group))
3665 if (ie_data->pairwise_cipher & WPA_CIPHER_TKIP)
3666 pairwise[n++] = "tkip";
3667 if (ie_data->pairwise_cipher & WPA_CIPHER_CCMP)
3668 pairwise[n++] = "ccmp";
3669 if (ie_data->pairwise_cipher & WPA_CIPHER_GCMP)
3670 pairwise[n++] = "gcmp";
3671 if (ie_data->pairwise_cipher & WPA_CIPHER_CCMP_256)
3672 pairwise[n++] = "ccmp-256";
3673 if (ie_data->pairwise_cipher & WPA_CIPHER_GCMP_256)
3674 pairwise[n++] = "gcmp-256";
3676 if (!wpa_dbus_dict_append_string_array(&iter_dict, "Pairwise",
3680 /* Management group (RSN only) */
3681 if (ie_data->proto == WPA_PROTO_RSN) {
3682 switch (ie_data->mgmt_group_cipher) {
3683 #ifdef CONFIG_IEEE80211W
3684 case WPA_CIPHER_AES_128_CMAC:
3685 group = "aes128cmac";
3687 #endif /* CONFIG_IEEE80211W */
3693 if (!wpa_dbus_dict_append_string(&iter_dict, "MgmtGroup",
3698 if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict) ||
3699 !dbus_message_iter_close_container(iter, &variant_iter))
3705 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3711 * wpas_dbus_getter_bss_wpa - Return the WPA options of a BSS
3712 * @iter: Pointer to incoming dbus message iter
3713 * @error: Location to store error on failure
3714 * @user_data: Function specific data
3715 * Returns: TRUE on success, FALSE on failure
3717 * Getter for "WPA" property.
3719 dbus_bool_t wpas_dbus_getter_bss_wpa(DBusMessageIter *iter, DBusError *error,
3722 struct bss_handler_args *args = user_data;
3723 struct wpa_bss *res;
3724 struct wpa_ie_data wpa_data;
3727 res = get_bss_helper(args, error, __func__);
3731 os_memset(&wpa_data, 0, sizeof(wpa_data));
3732 ie = wpa_bss_get_vendor_ie(res, WPA_IE_VENDOR_TYPE);
3733 if (ie && wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0) {
3734 dbus_set_error_const(error, DBUS_ERROR_FAILED,
3735 "failed to parse WPA IE");
3739 return wpas_dbus_get_bss_security_prop(iter, &wpa_data, error);
3744 * wpas_dbus_getter_bss_rsn - Return the RSN options of a BSS
3745 * @iter: Pointer to incoming dbus message iter
3746 * @error: Location to store error on failure
3747 * @user_data: Function specific data
3748 * Returns: TRUE on success, FALSE on failure
3750 * Getter for "RSN" property.
3752 dbus_bool_t wpas_dbus_getter_bss_rsn(DBusMessageIter *iter, DBusError *error,
3755 struct bss_handler_args *args = user_data;
3756 struct wpa_bss *res;
3757 struct wpa_ie_data wpa_data;
3760 res = get_bss_helper(args, error, __func__);
3764 os_memset(&wpa_data, 0, sizeof(wpa_data));
3765 ie = wpa_bss_get_ie(res, WLAN_EID_RSN);
3766 if (ie && wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0) {
3767 dbus_set_error_const(error, DBUS_ERROR_FAILED,
3768 "failed to parse RSN IE");
3772 return wpas_dbus_get_bss_security_prop(iter, &wpa_data, error);
3777 * wpas_dbus_getter_bss_wps - Return the WPS options of a BSS
3778 * @iter: Pointer to incoming dbus message iter
3779 * @error: Location to store error on failure
3780 * @user_data: Function specific data
3781 * Returns: TRUE on success, FALSE on failure
3783 * Getter for "WPS" property.
3785 dbus_bool_t wpas_dbus_getter_bss_wps(DBusMessageIter *iter, DBusError *error,
3788 struct bss_handler_args *args = user_data;
3789 struct wpa_bss *res;
3791 struct wpabuf *wps_ie;
3792 #endif /* CONFIG_WPS */
3793 DBusMessageIter iter_dict, variant_iter;
3794 const char *type = "";
3796 res = get_bss_helper(args, error, __func__);
3800 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
3801 "a{sv}", &variant_iter) ||
3802 !wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
3806 wps_ie = wpa_bss_get_vendor_ie_multi(res, WPS_IE_VENDOR_TYPE);
3808 if (wps_is_selected_pbc_registrar(wps_ie))
3810 else if (wps_is_selected_pin_registrar(wps_ie))
3813 wpabuf_free(wps_ie);
3815 #endif /* CONFIG_WPS */
3817 if (!wpa_dbus_dict_append_string(&iter_dict, "Type", type) ||
3818 !wpa_dbus_dict_close_write(&variant_iter, &iter_dict) ||
3819 !dbus_message_iter_close_container(iter, &variant_iter))
3825 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3831 * wpas_dbus_getter_bss_ies - Return all IEs of a BSS
3832 * @iter: Pointer to incoming dbus message iter
3833 * @error: Location to store error on failure
3834 * @user_data: Function specific data
3835 * Returns: TRUE on success, FALSE on failure
3837 * Getter for "IEs" property.
3839 dbus_bool_t wpas_dbus_getter_bss_ies(DBusMessageIter *iter, DBusError *error,
3842 struct bss_handler_args *args = user_data;
3843 struct wpa_bss *res;
3845 res = get_bss_helper(args, error, __func__);
3849 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
3850 res + 1, res->ie_len,
3856 * wpas_dbus_getter_bss_age - Return time in seconds since BSS was last seen
3857 * @iter: Pointer to incoming dbus message iter
3858 * @error: Location to store error on failure
3859 * @user_data: Function specific data
3860 * Returns: TRUE on success, FALSE on failure
3862 * Getter for BSS age
3864 dbus_bool_t wpas_dbus_getter_bss_age(DBusMessageIter *iter, DBusError *error,
3867 struct bss_handler_args *args = user_data;
3868 struct wpa_bss *res;
3869 struct os_reltime now, diff = { 0, 0 };
3872 res = get_bss_helper(args, error, __func__);
3876 os_get_reltime(&now);
3877 os_reltime_sub(&now, &res->last_update, &diff);
3878 age = diff.sec > 0 ? diff.sec : 0;
3879 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32, &age,
3885 * wpas_dbus_getter_enabled - Check whether network is enabled or disabled
3886 * @iter: Pointer to incoming dbus message iter
3887 * @error: Location to store error on failure
3888 * @user_data: Function specific data
3889 * Returns: TRUE on success, FALSE on failure
3891 * Getter for "enabled" property of a configured network.
3893 dbus_bool_t wpas_dbus_getter_enabled(DBusMessageIter *iter, DBusError *error,
3896 struct network_handler_args *net = user_data;
3897 dbus_bool_t enabled = net->ssid->disabled ? FALSE : TRUE;
3899 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
3905 * wpas_dbus_setter_enabled - Mark a configured network as enabled or disabled
3906 * @iter: Pointer to incoming dbus message iter
3907 * @error: Location to store error on failure
3908 * @user_data: Function specific data
3909 * Returns: TRUE on success, FALSE on failure
3911 * Setter for "Enabled" property of a configured network.
3913 dbus_bool_t wpas_dbus_setter_enabled(DBusMessageIter *iter, DBusError *error,
3916 struct network_handler_args *net = user_data;
3917 struct wpa_supplicant *wpa_s;
3918 struct wpa_ssid *ssid;
3921 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
3929 wpa_supplicant_enable_network(wpa_s, ssid);
3931 wpa_supplicant_disable_network(wpa_s, ssid);
3938 * wpas_dbus_getter_network_properties - Get options for a configured network
3939 * @iter: Pointer to incoming dbus message iter
3940 * @error: Location to store error on failure
3941 * @user_data: Function specific data
3942 * Returns: TRUE on success, FALSE on failure
3944 * Getter for "Properties" property of a configured network.
3946 dbus_bool_t wpas_dbus_getter_network_properties(DBusMessageIter *iter,
3950 struct network_handler_args *net = user_data;
3951 DBusMessageIter variant_iter, dict_iter;
3953 char **props = wpa_config_get_all(net->ssid, 1);
3954 dbus_bool_t success = FALSE;
3957 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3961 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a{sv}",
3963 !wpa_dbus_dict_open_write(&variant_iter, &dict_iter)) {
3964 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3970 if (!wpa_dbus_dict_append_string(&dict_iter, *iterator,
3972 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
3980 if (!wpa_dbus_dict_close_write(&variant_iter, &dict_iter) ||
3981 !dbus_message_iter_close_container(iter, &variant_iter)) {
3982 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
4000 * wpas_dbus_setter_network_properties - Set options for a configured network
4001 * @iter: Pointer to incoming dbus message iter
4002 * @error: Location to store error on failure
4003 * @user_data: Function specific data
4004 * Returns: TRUE on success, FALSE on failure
4006 * Setter for "Properties" property of a configured network.
4008 dbus_bool_t wpas_dbus_setter_network_properties(DBusMessageIter *iter,
4012 struct network_handler_args *net = user_data;
4013 struct wpa_ssid *ssid = net->ssid;
4014 DBusMessageIter variant_iter;
4016 dbus_message_iter_recurse(iter, &variant_iter);
4017 return set_network_properties(net->wpa_s, ssid, &variant_iter, error);
4023 DBusMessage * wpas_dbus_handler_subscribe_preq(
4024 DBusMessage *message, struct wpa_supplicant *wpa_s)
4026 struct wpas_dbus_priv *priv = wpa_s->global->dbus;
4029 if (wpa_s->preq_notify_peer != NULL) {
4030 if (os_strcmp(dbus_message_get_sender(message),
4031 wpa_s->preq_notify_peer) == 0)
4034 return dbus_message_new_error(message,
4035 WPAS_DBUS_ERROR_SUBSCRIPTION_IN_USE,
4036 "Another application is already subscribed");
4039 name = os_strdup(dbus_message_get_sender(message));
4041 return wpas_dbus_error_no_memory(message);
4043 wpa_s->preq_notify_peer = name;
4045 /* Subscribe to clean up if application closes socket */
4046 wpas_dbus_subscribe_noc(priv);
4049 * Double-check it's still alive to make sure that we didn't
4050 * miss the NameOwnerChanged signal, e.g. while strdup'ing.
4052 if (!dbus_bus_name_has_owner(priv->con, name, NULL)) {
4054 * Application no longer exists, clean up.
4055 * The return value is irrelevant now.
4057 * Need to check if the NameOwnerChanged handling
4058 * already cleaned up because we have processed
4059 * DBus messages while checking if the name still
4062 if (!wpa_s->preq_notify_peer)
4064 os_free(wpa_s->preq_notify_peer);
4065 wpa_s->preq_notify_peer = NULL;
4066 wpas_dbus_unsubscribe_noc(priv);
4073 DBusMessage * wpas_dbus_handler_unsubscribe_preq(
4074 DBusMessage *message, struct wpa_supplicant *wpa_s)
4076 struct wpas_dbus_priv *priv = wpa_s->global->dbus;
4078 if (!wpa_s->preq_notify_peer)
4079 return dbus_message_new_error(message,
4080 WPAS_DBUS_ERROR_NO_SUBSCRIPTION,
4083 if (os_strcmp(wpa_s->preq_notify_peer,
4084 dbus_message_get_sender(message)))
4085 return dbus_message_new_error(message,
4086 WPAS_DBUS_ERROR_SUBSCRIPTION_EPERM,
4087 "Can't unsubscribe others");
4089 os_free(wpa_s->preq_notify_peer);
4090 wpa_s->preq_notify_peer = NULL;
4091 wpas_dbus_unsubscribe_noc(priv);
4096 void wpas_dbus_signal_preq(struct wpa_supplicant *wpa_s,
4097 const u8 *addr, const u8 *dst, const u8 *bssid,
4098 const u8 *ie, size_t ie_len, u32 ssi_signal)
4101 DBusMessageIter iter, dict_iter;
4102 struct wpas_dbus_priv *priv = wpa_s->global->dbus;
4104 /* Do nothing if the control interface is not turned on */
4108 if (wpa_s->preq_notify_peer == NULL)
4111 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
4112 WPAS_DBUS_NEW_IFACE_INTERFACE,
4117 dbus_message_set_destination(msg, wpa_s->preq_notify_peer);
4119 dbus_message_iter_init_append(msg, &iter);
4121 if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
4122 (addr && !wpa_dbus_dict_append_byte_array(&dict_iter, "addr",
4123 (const char *) addr,
4125 (dst && !wpa_dbus_dict_append_byte_array(&dict_iter, "dst",
4128 (bssid && !wpa_dbus_dict_append_byte_array(&dict_iter, "bssid",
4129 (const char *) bssid,
4131 (ie && ie_len && !wpa_dbus_dict_append_byte_array(&dict_iter, "ies",
4134 (ssi_signal && !wpa_dbus_dict_append_int32(&dict_iter, "signal",
4136 !wpa_dbus_dict_close_write(&iter, &dict_iter))
4139 dbus_connection_send(priv->con, msg, NULL);
4142 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
4144 dbus_message_unref(msg);
4147 #endif /* CONFIG_AP */