2 * WPA Supplicant / dbus-based control interface
3 * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
4 * Copyright (c) 2009-2010, Witold Sowa <witold.sowa@gmail.com>
5 * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * Alternatively, this software may be distributed under the terms of BSD
14 * See README and COPYING for more details.
20 #include "common/ieee802_11_defs.h"
21 #include "eap_peer/eap_methods.h"
22 #include "eapol_supp/eapol_supp_sm.h"
23 #include "rsn_supp/wpa.h"
24 #include "../config.h"
25 #include "../wpa_supplicant_i.h"
26 #include "../driver_i.h"
27 #include "../notify.h"
28 #include "../wpas_glue.h"
31 #include "dbus_new_helpers.h"
33 #include "dbus_new_handlers.h"
34 #include "dbus_dict_helpers.h"
36 extern int wpa_debug_level;
37 extern int wpa_debug_show_keys;
38 extern int wpa_debug_timestamp;
40 static const char *debug_strings[] = {
41 "excessive", "msgdump", "debug", "info", "warning", "error", NULL
46 * wpas_dbus_error_unknown_error - Return a new InvalidArgs error message
47 * @message: Pointer to incoming dbus message this error refers to
48 * @arg: Optional string appended to error message
49 * Returns: a dbus error message
51 * Convenience function to create and return an UnknownError
53 DBusMessage * wpas_dbus_error_unknown_error(DBusMessage *message,
57 * This function can be called as a result of a failure
58 * within internal getter calls, which will call this function
59 * with a NULL message parameter. However, dbus_message_new_error
60 * looks very unkindly (i.e, abort()) on a NULL message, so
61 * in this case, we should not call it.
63 if (message == NULL) {
64 wpa_printf(MSG_INFO, "dbus: wpas_dbus_error_unknown_error "
65 "called with NULL message (arg=%s)",
70 return dbus_message_new_error(message, WPAS_DBUS_ERROR_UNKNOWN_ERROR,
76 * wpas_dbus_error_iface_unknown - Return a new invalid interface error message
77 * @message: Pointer to incoming dbus message this error refers to
78 * Returns: A dbus error message
80 * Convenience function to create and return an invalid interface error
82 static DBusMessage * wpas_dbus_error_iface_unknown(DBusMessage *message)
84 return dbus_message_new_error(message, WPAS_DBUS_ERROR_IFACE_UNKNOWN,
85 "wpa_supplicant knows nothing about "
91 * wpas_dbus_error_network_unknown - Return a new NetworkUnknown error message
92 * @message: Pointer to incoming dbus message this error refers to
93 * Returns: a dbus error message
95 * Convenience function to create and return an invalid network error
97 static DBusMessage * wpas_dbus_error_network_unknown(DBusMessage *message)
99 return dbus_message_new_error(message, WPAS_DBUS_ERROR_NETWORK_UNKNOWN,
100 "There is no such a network in this "
106 * wpas_dbus_error_invalid_args - Return a new InvalidArgs error message
107 * @message: Pointer to incoming dbus message this error refers to
108 * Returns: a dbus error message
110 * Convenience function to create and return an invalid options error
112 DBusMessage * wpas_dbus_error_invalid_args(DBusMessage *message,
117 reply = dbus_message_new_error(message, WPAS_DBUS_ERROR_INVALID_ARGS,
118 "Did not receive correct message "
121 dbus_message_append_args(reply, DBUS_TYPE_STRING, &arg,
128 static const char *dont_quote[] = {
129 "key_mgmt", "proto", "pairwise", "auth_alg", "group", "eap",
130 "opensc_engine_path", "pkcs11_engine_path", "pkcs11_module_path",
134 static dbus_bool_t should_quote_opt(const char *key)
137 while (dont_quote[i] != NULL) {
138 if (os_strcmp(key, dont_quote[i]) == 0)
146 * get_iface_by_dbus_path - Get a new network interface
147 * @global: Pointer to global data from wpa_supplicant_init()
148 * @path: Pointer to a dbus object path representing an interface
149 * Returns: Pointer to the interface or %NULL if not found
151 static struct wpa_supplicant * get_iface_by_dbus_path(
152 struct wpa_global *global, const char *path)
154 struct wpa_supplicant *wpa_s;
156 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
157 if (os_strcmp(wpa_s->dbus_new_path, path) == 0)
165 * set_network_properties - Set properties of a configured network
166 * @message: Pointer to incoming dbus message
167 * @wpa_s: wpa_supplicant structure for a network interface
168 * @ssid: wpa_ssid structure for a configured network
169 * @iter: DBus message iterator containing dictionary of network
171 * Returns: NULL when succeed or DBus error on failure
173 * Sets network configuration with parameters given id DBus dictionary
175 DBusMessage * set_network_properties(DBusMessage *message,
176 struct wpa_supplicant *wpa_s,
177 struct wpa_ssid *ssid,
178 DBusMessageIter *iter)
181 struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
182 DBusMessage *reply = NULL;
183 DBusMessageIter iter_dict;
185 if (!wpa_dbus_dict_open_read(iter, &iter_dict))
186 return wpas_dbus_error_invalid_args(message, NULL);
188 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
192 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) {
193 reply = wpas_dbus_error_invalid_args(message, NULL);
196 if (entry.type == DBUS_TYPE_ARRAY &&
197 entry.array_type == DBUS_TYPE_BYTE) {
198 if (entry.array_len <= 0)
201 size = entry.array_len * 2 + 1;
202 value = os_zalloc(size);
206 ret = wpa_snprintf_hex(value, size,
207 (u8 *) entry.bytearray_value,
211 } else if (entry.type == DBUS_TYPE_STRING) {
212 if (should_quote_opt(entry.key)) {
213 size = os_strlen(entry.str_value);
218 value = os_zalloc(size);
222 ret = os_snprintf(value, size, "\"%s\"",
224 if (ret < 0 || (size_t) ret != (size - 1))
227 value = os_strdup(entry.str_value);
231 } else if (entry.type == DBUS_TYPE_UINT32) {
232 value = os_zalloc(size);
236 ret = os_snprintf(value, size, "%u",
240 } else if (entry.type == DBUS_TYPE_INT32) {
241 value = os_zalloc(size);
245 ret = os_snprintf(value, size, "%d",
252 if (wpa_config_set(ssid, entry.key, value, 0) < 0)
255 if ((os_strcmp(entry.key, "psk") == 0 &&
256 value[0] == '"' && ssid->ssid_len) ||
257 (strcmp(entry.key, "ssid") == 0 && ssid->passphrase))
258 wpa_config_update_psk(ssid);
259 else if (os_strcmp(entry.key, "priority") == 0)
260 wpa_config_update_prio_list(wpa_s->conf);
263 wpa_dbus_dict_entry_clear(&entry);
268 reply = wpas_dbus_error_invalid_args(message, entry.key);
269 wpa_dbus_dict_entry_clear(&entry);
278 * wpas_dbus_simple_property_getter - Get basic type property
279 * @message: Pointer to incoming dbus message
280 * @type: DBus type of property (must be basic type)
281 * @val: pointer to place holding property value
282 * Returns: The DBus message containing response for Properties.Get call
283 * or DBus error message if error occurred.
285 * Generic getter for basic type properties. Type is required to be basic.
287 DBusMessage * wpas_dbus_simple_property_getter(DBusMessage *message,
288 const int type, const void *val)
290 DBusMessage *reply = NULL;
291 DBusMessageIter iter, variant_iter;
293 if (!dbus_type_is_basic(type)) {
294 wpa_printf(MSG_ERROR, "dbus: wpas_dbus_simple_property_getter:"
295 " given type is not basic");
296 return wpas_dbus_error_unknown_error(message, NULL);
300 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
302 reply = dbus_message_new_method_return(message);
305 dbus_message_iter_init_append(reply, &iter);
306 if (!dbus_message_iter_open_container(
307 &iter, DBUS_TYPE_VARIANT,
308 wpa_dbus_type_as_string(type), &variant_iter) ||
309 !dbus_message_iter_append_basic(&variant_iter, type,
311 !dbus_message_iter_close_container(&iter, &variant_iter)) {
312 wpa_printf(MSG_ERROR, "dbus: "
313 "wpas_dbus_simple_property_getter: out of "
314 "memory to put property value into "
316 dbus_message_unref(reply);
317 reply = dbus_message_new_error(message,
318 DBUS_ERROR_NO_MEMORY,
322 wpa_printf(MSG_ERROR, "dbus: wpas_dbus_simple_property_getter:"
323 " out of memory to return property value");
324 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
333 * wpas_dbus_simple_property_setter - Set basic type property
334 * @message: Pointer to incoming dbus message
335 * @type: DBus type of property (must be basic type)
336 * @val: pointer to place where value being set will be stored
337 * Returns: NULL or DBus error message if error occurred.
339 * Generic setter for basic type properties. Type is required to be basic.
341 DBusMessage * wpas_dbus_simple_property_setter(DBusMessage *message,
342 const int type, void *val)
344 DBusMessageIter iter, variant_iter;
346 if (!dbus_type_is_basic(type)) {
347 wpa_printf(MSG_ERROR, "dbus: wpas_dbus_simple_property_setter:"
348 " given type is not basic");
349 return wpas_dbus_error_unknown_error(message, NULL);
352 if (!dbus_message_iter_init(message, &iter)) {
353 wpa_printf(MSG_ERROR, "dbus: wpas_dbus_simple_property_setter:"
354 " out of memory to return scanning state");
355 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
359 /* omit first and second argument and get value from third */
360 dbus_message_iter_next(&iter);
361 dbus_message_iter_next(&iter);
362 dbus_message_iter_recurse(&iter, &variant_iter);
364 if (dbus_message_iter_get_arg_type(&variant_iter) != type) {
365 wpa_printf(MSG_DEBUG, "dbus: wpas_dbus_simple_property_setter:"
366 " wrong property type");
367 return wpas_dbus_error_invalid_args(message,
368 "wrong property type");
370 dbus_message_iter_get_basic(&variant_iter, val);
377 * wpas_dbus_simple_array_property_getter - Get array type property
378 * @message: Pointer to incoming dbus message
379 * @type: DBus type of property array elements (must be basic type)
380 * @array: pointer to array of elements to put into response message
381 * @array_len: length of above array
382 * Returns: The DBus message containing response for Properties.Get call
383 * or DBus error message if error occurred.
385 * Generic getter for array type properties. Array elements type is
386 * required to be basic.
388 DBusMessage * wpas_dbus_simple_array_property_getter(DBusMessage *message,
393 DBusMessage *reply = NULL;
394 DBusMessageIter iter, variant_iter, array_iter;
395 char type_str[] = "a?"; /* ? will be replaced with subtype letter; */
396 const char *sub_type_str;
397 size_t element_size, i;
399 if (!dbus_type_is_basic(type)) {
400 wpa_printf(MSG_ERROR, "dbus: "
401 "wpas_dbus_simple_array_property_getter: given "
402 "type is not basic");
403 return wpas_dbus_error_unknown_error(message, NULL);
406 sub_type_str = wpa_dbus_type_as_string(type);
407 type_str[1] = sub_type_str[0];
410 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
412 reply = dbus_message_new_method_return(message);
414 wpa_printf(MSG_ERROR, "dbus: "
415 "wpas_dbus_simple_array_property_getter: out of "
416 "memory to create return message");
417 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
421 dbus_message_iter_init_append(reply, &iter);
423 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
424 type_str, &variant_iter) ||
425 !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
426 sub_type_str, &array_iter)) {
427 wpa_printf(MSG_ERROR, "dbus: "
428 "wpas_dbus_simple_array_property_getter: out of "
429 "memory to open container");
430 dbus_message_unref(reply);
431 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
437 case DBUS_TYPE_BOOLEAN:
440 case DBUS_TYPE_INT16:
441 case DBUS_TYPE_UINT16:
442 element_size = sizeof(uint16_t);
444 case DBUS_TYPE_INT32:
445 case DBUS_TYPE_UINT32:
446 element_size = sizeof(uint32_t);
448 case DBUS_TYPE_INT64:
449 case DBUS_TYPE_UINT64:
450 element_size = sizeof(uint64_t);
452 case DBUS_TYPE_DOUBLE:
453 element_size = sizeof(double);
455 case DBUS_TYPE_STRING:
456 case DBUS_TYPE_OBJECT_PATH:
457 element_size = sizeof(char *);
460 wpa_printf(MSG_ERROR, "dbus: "
461 "wpas_dbus_simple_array_property_getter: "
462 "fatal: unknown element type");
467 for (i = 0; i < array_len; i++) {
468 dbus_message_iter_append_basic(&array_iter, type,
469 array + i * element_size);
472 if (!dbus_message_iter_close_container(&variant_iter, &array_iter) ||
473 !dbus_message_iter_close_container(&iter, &variant_iter)) {
474 wpa_printf(MSG_ERROR, "dbus: "
475 "wpas_dbus_simple_array_property_getter: out of "
476 "memory to close container");
477 dbus_message_unref(reply);
478 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
487 * wpas_dbus_handler_create_interface - Request registration of a network iface
488 * @message: Pointer to incoming dbus message
489 * @global: %wpa_supplicant global data structure
490 * Returns: The object path of the new interface object,
491 * or a dbus error message with more information
493 * Handler function for "CreateInterface" method call. Handles requests
494 * by dbus clients to register a network interface that wpa_supplicant
497 DBusMessage * wpas_dbus_handler_create_interface(DBusMessage *message,
498 struct wpa_global *global)
500 DBusMessageIter iter_dict;
501 DBusMessage *reply = NULL;
502 DBusMessageIter iter;
503 struct wpa_dbus_dict_entry entry;
506 char *confname = NULL;
507 char *bridge_ifname = NULL;
509 dbus_message_iter_init(message, &iter);
511 if (!wpa_dbus_dict_open_read(&iter, &iter_dict))
513 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
514 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
516 if (!strcmp(entry.key, "Driver") &&
517 (entry.type == DBUS_TYPE_STRING)) {
518 driver = os_strdup(entry.str_value);
519 wpa_dbus_dict_entry_clear(&entry);
522 } else if (!strcmp(entry.key, "Ifname") &&
523 (entry.type == DBUS_TYPE_STRING)) {
524 ifname = os_strdup(entry.str_value);
525 wpa_dbus_dict_entry_clear(&entry);
528 } else if (!strcmp(entry.key, "ConfigFile") &&
529 (entry.type == DBUS_TYPE_STRING)) {
530 confname = os_strdup(entry.str_value);
531 wpa_dbus_dict_entry_clear(&entry);
532 if (confname == NULL)
534 } else if (!strcmp(entry.key, "BridgeIfname") &&
535 (entry.type == DBUS_TYPE_STRING)) {
536 bridge_ifname = os_strdup(entry.str_value);
537 wpa_dbus_dict_entry_clear(&entry);
538 if (bridge_ifname == NULL)
541 wpa_dbus_dict_entry_clear(&entry);
547 goto error; /* Required Ifname argument missing */
550 * Try to get the wpa_supplicant record for this iface, return
551 * an error if we already control it.
553 if (wpa_supplicant_get_iface(global, ifname) != NULL) {
554 reply = dbus_message_new_error(message,
555 WPAS_DBUS_ERROR_IFACE_EXISTS,
556 "wpa_supplicant already "
557 "controls this interface.");
559 struct wpa_supplicant *wpa_s;
560 struct wpa_interface iface;
561 os_memset(&iface, 0, sizeof(iface));
562 iface.driver = driver;
563 iface.ifname = ifname;
564 iface.confname = confname;
565 iface.bridge_ifname = bridge_ifname;
566 /* Otherwise, have wpa_supplicant attach to it. */
567 if ((wpa_s = wpa_supplicant_add_iface(global, &iface))) {
568 const char *path = wpa_s->dbus_new_path;
569 reply = dbus_message_new_method_return(message);
570 dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH,
571 &path, DBUS_TYPE_INVALID);
573 reply = wpas_dbus_error_unknown_error(
574 message, "wpa_supplicant couldn't grab this "
582 os_free(bridge_ifname);
586 reply = wpas_dbus_error_invalid_args(message, NULL);
592 * wpas_dbus_handler_remove_interface - Request deregistration of an interface
593 * @message: Pointer to incoming dbus message
594 * @global: wpa_supplicant global data structure
595 * Returns: a dbus message containing a UINT32 indicating success (1) or
596 * failure (0), or returns a dbus error message with more information
598 * Handler function for "removeInterface" method call. Handles requests
599 * by dbus clients to deregister a network interface that wpa_supplicant
602 DBusMessage * wpas_dbus_handler_remove_interface(DBusMessage *message,
603 struct wpa_global *global)
605 struct wpa_supplicant *wpa_s;
607 DBusMessage *reply = NULL;
609 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path,
612 wpa_s = get_iface_by_dbus_path(global, path);
614 reply = wpas_dbus_error_iface_unknown(message);
615 else if (wpa_supplicant_remove_iface(global, wpa_s, 0)) {
616 reply = wpas_dbus_error_unknown_error(
617 message, "wpa_supplicant couldn't remove this "
626 * wpas_dbus_handler_get_interface - Get the object path for an interface name
627 * @message: Pointer to incoming dbus message
628 * @global: %wpa_supplicant global data structure
629 * Returns: The object path of the interface object,
630 * or a dbus error message with more information
632 * Handler function for "getInterface" method call.
634 DBusMessage * wpas_dbus_handler_get_interface(DBusMessage *message,
635 struct wpa_global *global)
637 DBusMessage *reply = NULL;
640 struct wpa_supplicant *wpa_s;
642 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &ifname,
645 wpa_s = wpa_supplicant_get_iface(global, ifname);
647 return wpas_dbus_error_iface_unknown(message);
649 path = wpa_s->dbus_new_path;
650 reply = dbus_message_new_method_return(message);
652 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
654 if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
655 DBUS_TYPE_INVALID)) {
656 dbus_message_unref(reply);
657 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
666 * wpas_dbus_getter_debug_level - Get debug level
667 * @message: Pointer to incoming dbus message
668 * @global: %wpa_supplicant global data structure
669 * Returns: DBus message with value of debug level
671 * Getter for "DebugLevel" property.
673 DBusMessage * wpas_dbus_getter_debug_level(DBusMessage *message,
674 struct wpa_global *global)
677 int idx = wpa_debug_level;
682 str = debug_strings[idx];
683 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_STRING,
689 * wpas_dbus_getter_debug_timestamp - Get debug timestamp
690 * @message: Pointer to incoming dbus message
691 * @global: %wpa_supplicant global data structure
692 * Returns: DBus message with value of debug timestamp
694 * Getter for "DebugTimestamp" property.
696 DBusMessage * wpas_dbus_getter_debug_timestamp(DBusMessage *message,
697 struct wpa_global *global)
699 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_BOOLEAN,
700 &wpa_debug_timestamp);
706 * wpas_dbus_getter_debug_show_keys - Get debug show keys
707 * @message: Pointer to incoming dbus message
708 * @global: %wpa_supplicant global data structure
709 * Returns: DBus message with value of debug show_keys
711 * Getter for "DebugShowKeys" property.
713 DBusMessage * wpas_dbus_getter_debug_show_keys(DBusMessage *message,
714 struct wpa_global *global)
716 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_BOOLEAN,
717 &wpa_debug_show_keys);
722 * wpas_dbus_setter_debug_level - Set debug level
723 * @message: Pointer to incoming dbus message
724 * @global: %wpa_supplicant global data structure
725 * Returns: %NULL or DBus error message
727 * Setter for "DebugLevel" property.
729 DBusMessage * wpas_dbus_setter_debug_level(DBusMessage *message,
730 struct wpa_global *global)
733 const char *str = NULL;
736 reply = wpas_dbus_simple_property_setter(message, DBUS_TYPE_STRING,
741 for (i = 0; debug_strings[i]; i++)
742 if (os_strcmp(debug_strings[i], str) == 0) {
748 wpa_supplicant_set_debug_params(global, val, wpa_debug_timestamp,
749 wpa_debug_show_keys)) {
750 return wpas_dbus_error_invalid_args(
751 message, "Wrong debug level value");
759 * wpas_dbus_setter_debug_timestamp - Set debug timestamp
760 * @message: Pointer to incoming dbus message
761 * @global: %wpa_supplicant global data structure
762 * Returns: %NULL or DBus error message
764 * Setter for "DebugTimestamp" property.
766 DBusMessage * wpas_dbus_setter_debug_timestamp(DBusMessage *message,
767 struct wpa_global *global)
772 reply = wpas_dbus_simple_property_setter(message, DBUS_TYPE_BOOLEAN,
777 wpa_supplicant_set_debug_params(global, wpa_debug_level, val ? 1 : 0,
778 wpa_debug_show_keys);
785 * wpas_dbus_setter_debug_show_keys - Set debug show keys
786 * @message: Pointer to incoming dbus message
787 * @global: %wpa_supplicant global data structure
788 * Returns: %NULL or DBus error message
790 * Setter for "DebugShowKeys" property.
792 DBusMessage * wpas_dbus_setter_debug_show_keys(DBusMessage *message,
793 struct wpa_global *global)
798 reply = wpas_dbus_simple_property_setter(message, DBUS_TYPE_BOOLEAN,
803 wpa_supplicant_set_debug_params(global, wpa_debug_level,
812 * wpas_dbus_getter_interfaces - Request registered interfaces list
813 * @message: Pointer to incoming dbus message
814 * @global: %wpa_supplicant global data structure
815 * Returns: The object paths array containing registered interfaces
816 * objects paths or DBus error on failure
818 * Getter for "Interfaces" property. Handles requests
819 * by dbus clients to return list of registered interfaces objects
822 DBusMessage * wpas_dbus_getter_interfaces(DBusMessage *message,
823 struct wpa_global *global)
825 DBusMessage *reply = NULL;
826 struct wpa_supplicant *wpa_s;
828 unsigned int i = 0, num = 0;
830 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
833 paths = os_zalloc(num * sizeof(char*));
835 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
839 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
840 paths[i++] = wpa_s->dbus_new_path;
842 reply = wpas_dbus_simple_array_property_getter(message,
843 DBUS_TYPE_OBJECT_PATH,
852 * wpas_dbus_getter_eap_methods - Request supported EAP methods list
853 * @message: Pointer to incoming dbus message
854 * @nothing: not used argument. may be NULL or anything else
855 * Returns: The object paths array containing supported EAP methods
856 * represented by strings or DBus error on failure
858 * Getter for "EapMethods" property. Handles requests
859 * by dbus clients to return list of strings with supported EAP methods
861 DBusMessage * wpas_dbus_getter_eap_methods(DBusMessage *message, void *nothing)
863 DBusMessage *reply = NULL;
865 size_t num_items = 0;
867 eap_methods = eap_get_names_as_string_array(&num_items);
869 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
873 reply = wpas_dbus_simple_array_property_getter(message,
875 eap_methods, num_items);
878 os_free(eap_methods[--num_items]);
879 os_free(eap_methods);
884 static int wpas_dbus_get_scan_type(DBusMessage *message, DBusMessageIter *var,
885 char **type, DBusMessage **reply)
887 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_STRING) {
888 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
889 "Type must be a string");
890 *reply = wpas_dbus_error_invalid_args(
891 message, "Wrong Type value type. String required");
894 dbus_message_iter_get_basic(var, type);
899 static int wpas_dbus_get_scan_ssids(DBusMessage *message, DBusMessageIter *var,
900 struct wpa_driver_scan_params *params,
903 struct wpa_driver_scan_ssid *ssids = params->ssids;
904 size_t ssids_num = 0;
906 DBusMessageIter array_iter, sub_array_iter;
910 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
911 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: ssids "
912 "must be an array of arrays of bytes");
913 *reply = wpas_dbus_error_invalid_args(
914 message, "Wrong SSIDs value type. Array of arrays of "
919 dbus_message_iter_recurse(var, &array_iter);
921 if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY ||
922 dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_BYTE)
924 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: ssids "
925 "must be an array of arrays of bytes");
926 *reply = wpas_dbus_error_invalid_args(
927 message, "Wrong SSIDs value type. Array of arrays of "
932 while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_ARRAY)
934 if (ssids_num >= WPAS_MAX_SCAN_SSIDS) {
935 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
936 "Too many ssids specified on scan dbus "
938 *reply = wpas_dbus_error_invalid_args(
939 message, "Too many ssids specified. Specify "
944 dbus_message_iter_recurse(&array_iter, &sub_array_iter);
946 dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len);
949 ssid = os_malloc(len);
951 wpa_printf(MSG_DEBUG,
952 "wpas_dbus_handler_scan[dbus]: "
953 "out of memory. Cannot allocate "
955 *reply = dbus_message_new_error(
956 message, DBUS_ERROR_NO_MEMORY, NULL);
959 os_memcpy(ssid, val, len);
961 /* Allow zero-length SSIDs */
965 ssids[ssids_num].ssid = ssid;
966 ssids[ssids_num].ssid_len = len;
968 dbus_message_iter_next(&array_iter);
972 params->num_ssids = ssids_num;
977 static int wpas_dbus_get_scan_ies(DBusMessage *message, DBusMessageIter *var,
978 struct wpa_driver_scan_params *params,
981 u8 *ies = NULL, *nies;
983 DBusMessageIter array_iter, sub_array_iter;
987 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
988 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: ies must "
989 "be an array of arrays of bytes");
990 *reply = wpas_dbus_error_invalid_args(
991 message, "Wrong IEs value type. Array of arrays of "
996 dbus_message_iter_recurse(var, &array_iter);
998 if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY ||
999 dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_BYTE)
1001 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: ies must "
1002 "be an array of arrays of bytes");
1003 *reply = wpas_dbus_error_invalid_args(
1004 message, "Wrong IEs value type. Array required");
1008 while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_ARRAY)
1010 dbus_message_iter_recurse(&array_iter, &sub_array_iter);
1012 dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len);
1014 dbus_message_iter_next(&array_iter);
1018 nies = os_realloc(ies, ies_len + len);
1020 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1021 "out of memory. Cannot allocate memory for "
1024 *reply = dbus_message_new_error(
1025 message, DBUS_ERROR_NO_MEMORY, NULL);
1029 os_memcpy(ies + ies_len, val, len);
1032 dbus_message_iter_next(&array_iter);
1035 params->extra_ies = ies;
1036 params->extra_ies_len = ies_len;
1041 static int wpas_dbus_get_scan_channels(DBusMessage *message,
1042 DBusMessageIter *var,
1043 struct wpa_driver_scan_params *params,
1044 DBusMessage **reply)
1046 DBusMessageIter array_iter, sub_array_iter;
1047 int *freqs = NULL, *nfreqs;
1050 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
1051 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1052 "Channels must be an array of structs");
1053 *reply = wpas_dbus_error_invalid_args(
1054 message, "Wrong Channels value type. Array of structs "
1059 dbus_message_iter_recurse(var, &array_iter);
1061 if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_STRUCT) {
1062 wpa_printf(MSG_DEBUG,
1063 "wpas_dbus_handler_scan[dbus]: Channels must be an "
1064 "array of structs");
1065 *reply = wpas_dbus_error_invalid_args(
1066 message, "Wrong Channels value type. Array of structs "
1071 while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_STRUCT)
1075 dbus_message_iter_recurse(&array_iter, &sub_array_iter);
1077 if (dbus_message_iter_get_arg_type(&sub_array_iter) !=
1079 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1080 "Channel must by specified by struct of "
1082 dbus_message_iter_get_arg_type(
1084 *reply = wpas_dbus_error_invalid_args(
1085 message, "Wrong Channel struct. Two UINT32s "
1090 dbus_message_iter_get_basic(&sub_array_iter, &freq);
1092 if (!dbus_message_iter_next(&sub_array_iter) ||
1093 dbus_message_iter_get_arg_type(&sub_array_iter) !=
1095 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1096 "Channel must by specified by struct of "
1098 *reply = wpas_dbus_error_invalid_args(
1100 "Wrong Channel struct. Two UINT32s required");
1105 dbus_message_iter_get_basic(&sub_array_iter, &width);
1107 #define FREQS_ALLOC_CHUNK 32
1108 if (freqs_num % FREQS_ALLOC_CHUNK == 0) {
1109 nfreqs = os_realloc(freqs, sizeof(int) *
1110 (freqs_num + FREQS_ALLOC_CHUNK));
1115 if (freqs == NULL) {
1116 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1117 "out of memory. can't allocate memory for "
1119 *reply = dbus_message_new_error(
1120 message, DBUS_ERROR_NO_MEMORY, NULL);
1124 freqs[freqs_num] = freq;
1127 dbus_message_iter_next(&array_iter);
1130 nfreqs = os_realloc(freqs,
1131 sizeof(int) * (freqs_num + 1));
1135 if (freqs == NULL) {
1136 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1137 "out of memory. Can't allocate memory for freqs");
1138 *reply = dbus_message_new_error(
1139 message, DBUS_ERROR_NO_MEMORY, NULL);
1142 freqs[freqs_num] = 0;
1144 params->freqs = freqs;
1150 * wpas_dbus_handler_scan - Request a wireless scan on an interface
1151 * @message: Pointer to incoming dbus message
1152 * @wpa_s: wpa_supplicant structure for a network interface
1153 * Returns: NULL indicating success or DBus error message on failure
1155 * Handler function for "Scan" method call of a network device. Requests
1156 * that wpa_supplicant perform a wireless scan as soon as possible
1157 * on a particular wireless interface.
1159 DBusMessage * wpas_dbus_handler_scan(DBusMessage *message,
1160 struct wpa_supplicant *wpa_s)
1162 DBusMessage *reply = NULL;
1163 DBusMessageIter iter, dict_iter, entry_iter, variant_iter;
1164 char *key = NULL, *type = NULL;
1165 struct wpa_driver_scan_params params;
1168 os_memset(¶ms, 0, sizeof(params));
1170 dbus_message_iter_init(message, &iter);
1172 dbus_message_iter_recurse(&iter, &dict_iter);
1174 while (dbus_message_iter_get_arg_type(&dict_iter) ==
1175 DBUS_TYPE_DICT_ENTRY) {
1176 dbus_message_iter_recurse(&dict_iter, &entry_iter);
1177 dbus_message_iter_get_basic(&entry_iter, &key);
1178 dbus_message_iter_next(&entry_iter);
1179 dbus_message_iter_recurse(&entry_iter, &variant_iter);
1181 if (os_strcmp(key, "Type") == 0) {
1182 if (wpas_dbus_get_scan_type(message, &variant_iter,
1185 } else if (os_strcmp(key, "SSIDs") == 0) {
1186 if (wpas_dbus_get_scan_ssids(message, &variant_iter,
1187 ¶ms, &reply) < 0)
1189 } else if (os_strcmp(key, "IEs") == 0) {
1190 if (wpas_dbus_get_scan_ies(message, &variant_iter,
1191 ¶ms, &reply) < 0)
1193 } else if (os_strcmp(key, "Channels") == 0) {
1194 if (wpas_dbus_get_scan_channels(message, &variant_iter,
1195 ¶ms, &reply) < 0)
1198 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1199 "Unknown argument %s", key);
1200 reply = wpas_dbus_error_invalid_args(message, key);
1204 dbus_message_iter_next(&dict_iter);
1208 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1209 "Scan type not specified");
1210 reply = wpas_dbus_error_invalid_args(message, key);
1214 if (!os_strcmp(type, "passive")) {
1215 if (params.num_ssids || params.extra_ies_len) {
1216 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1217 "SSIDs or IEs specified for passive scan.");
1218 reply = wpas_dbus_error_invalid_args(
1219 message, "You can specify only Channels in "
1222 } else if (params.freqs && params.freqs[0]) {
1223 wpa_supplicant_trigger_scan(wpa_s, ¶ms);
1225 wpa_s->scan_req = 2;
1226 wpa_supplicant_req_scan(wpa_s, 0, 0);
1228 } else if (!os_strcmp(type, "active")) {
1229 if (!params.num_ssids) {
1230 /* Add wildcard ssid */
1233 wpa_supplicant_trigger_scan(wpa_s, ¶ms);
1235 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1236 "Unknown scan type: %s", type);
1237 reply = wpas_dbus_error_invalid_args(message,
1243 for (i = 0; i < WPAS_MAX_SCAN_SSIDS; i++)
1244 os_free((u8 *) params.ssids[i].ssid);
1245 os_free((u8 *) params.extra_ies);
1246 os_free(params.freqs);
1252 * wpas_dbus_handler_disconnect - Terminate the current connection
1253 * @message: Pointer to incoming dbus message
1254 * @wpa_s: wpa_supplicant structure for a network interface
1255 * Returns: NotConnected DBus error message if already not connected
1256 * or NULL otherwise.
1258 * Handler function for "Disconnect" method call of network interface.
1260 DBusMessage * wpas_dbus_handler_disconnect(DBusMessage *message,
1261 struct wpa_supplicant *wpa_s)
1263 if (wpa_s->current_ssid != NULL) {
1264 wpa_s->disconnected = 1;
1265 wpa_supplicant_deauthenticate(wpa_s,
1266 WLAN_REASON_DEAUTH_LEAVING);
1271 return dbus_message_new_error(message, WPAS_DBUS_ERROR_NOT_CONNECTED,
1272 "This interface is not connected");
1277 * wpas_dbus_new_iface_add_network - Add a new configured network
1278 * @message: Pointer to incoming dbus message
1279 * @wpa_s: wpa_supplicant structure for a network interface
1280 * Returns: A dbus message containing the object path of the new network
1282 * Handler function for "AddNetwork" method call of a network interface.
1284 DBusMessage * wpas_dbus_handler_add_network(DBusMessage *message,
1285 struct wpa_supplicant *wpa_s)
1287 DBusMessage *reply = NULL;
1288 DBusMessageIter iter;
1289 struct wpa_ssid *ssid = NULL;
1290 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf;
1292 dbus_message_iter_init(message, &iter);
1294 ssid = wpa_config_add_network(wpa_s->conf);
1296 wpa_printf(MSG_ERROR, "wpas_dbus_handler_add_network[dbus]: "
1297 "can't add new interface.");
1298 reply = wpas_dbus_error_unknown_error(
1300 "wpa_supplicant could not add "
1301 "a network on this interface.");
1304 wpas_notify_network_added(wpa_s, ssid);
1306 wpa_config_set_network_defaults(ssid);
1308 reply = set_network_properties(message, wpa_s, ssid, &iter);
1310 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_add_network[dbus]:"
1311 "control interface couldn't set network "
1316 /* Construct the object path for this network. */
1317 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
1318 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
1319 wpa_s->dbus_new_path, ssid->id);
1321 reply = dbus_message_new_method_return(message);
1322 if (reply == NULL) {
1323 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1327 if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
1328 DBUS_TYPE_INVALID)) {
1329 dbus_message_unref(reply);
1330 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1339 wpas_notify_network_removed(wpa_s, ssid);
1340 wpa_config_remove_network(wpa_s->conf, ssid->id);
1347 * wpas_dbus_handler_remove_network - Remove a configured network
1348 * @message: Pointer to incoming dbus message
1349 * @wpa_s: wpa_supplicant structure for a network interface
1350 * Returns: NULL on success or dbus error on failure
1352 * Handler function for "RemoveNetwork" method call of a network interface.
1354 DBusMessage * wpas_dbus_handler_remove_network(DBusMessage *message,
1355 struct wpa_supplicant *wpa_s)
1357 DBusMessage *reply = NULL;
1359 char *iface = NULL, *net_id = NULL;
1361 struct wpa_ssid *ssid;
1363 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
1366 /* Extract the network ID and ensure the network */
1367 /* is actually a child of this interface */
1368 iface = wpas_dbus_new_decompose_object_path(op, 0, &net_id, NULL);
1369 if (iface == NULL || os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
1370 reply = wpas_dbus_error_invalid_args(message, op);
1374 id = strtoul(net_id, NULL, 10);
1375 if (errno == EINVAL) {
1376 reply = wpas_dbus_error_invalid_args(message, op);
1380 ssid = wpa_config_get_network(wpa_s->conf, id);
1382 reply = wpas_dbus_error_network_unknown(message);
1386 wpas_notify_network_removed(wpa_s, ssid);
1388 if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
1389 wpa_printf(MSG_ERROR,
1390 "wpas_dbus_handler_remove_network[dbus]: "
1391 "error occurred when removing network %d", id);
1392 reply = wpas_dbus_error_unknown_error(
1393 message, "error removing the specified network on "
1398 if (ssid == wpa_s->current_ssid)
1399 wpa_supplicant_deauthenticate(wpa_s,
1400 WLAN_REASON_DEAUTH_LEAVING);
1409 static void remove_network(void *arg, struct wpa_ssid *ssid)
1411 struct wpa_supplicant *wpa_s = arg;
1413 wpas_notify_network_removed(wpa_s, ssid);
1415 if (wpa_config_remove_network(wpa_s->conf, ssid->id) < 0) {
1416 wpa_printf(MSG_ERROR,
1417 "wpas_dbus_handler_remove_all_networks[dbus]: "
1418 "error occurred when removing network %d",
1423 if (ssid == wpa_s->current_ssid)
1424 wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1429 * wpas_dbus_handler_remove_all_networks - Remove all configured networks
1430 * @message: Pointer to incoming dbus message
1431 * @wpa_s: wpa_supplicant structure for a network interface
1432 * Returns: NULL on success or dbus error on failure
1434 * Handler function for "RemoveAllNetworks" method call of a network interface.
1436 DBusMessage * wpas_dbus_handler_remove_all_networks(
1437 DBusMessage *message, struct wpa_supplicant *wpa_s)
1439 /* NB: could check for failure and return an error */
1440 wpa_config_foreach_network(wpa_s->conf, remove_network, wpa_s);
1446 * wpas_dbus_handler_select_network - Attempt association with a network
1447 * @message: Pointer to incoming dbus message
1448 * @wpa_s: wpa_supplicant structure for a network interface
1449 * Returns: NULL on success or dbus error on failure
1451 * Handler function for "SelectNetwork" method call of network interface.
1453 DBusMessage * wpas_dbus_handler_select_network(DBusMessage *message,
1454 struct wpa_supplicant *wpa_s)
1456 DBusMessage *reply = NULL;
1458 char *iface = NULL, *net_id = NULL;
1460 struct wpa_ssid *ssid;
1462 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
1465 /* Extract the network ID and ensure the network */
1466 /* is actually a child of this interface */
1467 iface = wpas_dbus_new_decompose_object_path(op, 0, &net_id, NULL);
1468 if (iface == NULL || os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
1469 reply = wpas_dbus_error_invalid_args(message, op);
1473 id = strtoul(net_id, NULL, 10);
1474 if (errno == EINVAL) {
1475 reply = wpas_dbus_error_invalid_args(message, op);
1479 ssid = wpa_config_get_network(wpa_s->conf, id);
1481 reply = wpas_dbus_error_network_unknown(message);
1485 /* Finally, associate with the network */
1486 wpa_supplicant_select_network(wpa_s, ssid);
1496 * wpas_dbus_handler_add_blob - Store named binary blob (ie, for certificates)
1497 * @message: Pointer to incoming dbus message
1498 * @wpa_s: %wpa_supplicant data structure
1499 * Returns: A dbus message containing an error on failure or NULL on success
1501 * Asks wpa_supplicant to internally store a binary blobs.
1503 DBusMessage * wpas_dbus_handler_add_blob(DBusMessage *message,
1504 struct wpa_supplicant *wpa_s)
1506 DBusMessage *reply = NULL;
1507 DBusMessageIter iter, array_iter;
1512 struct wpa_config_blob *blob = NULL;
1514 dbus_message_iter_init(message, &iter);
1515 dbus_message_iter_get_basic(&iter, &blob_name);
1517 if (wpa_config_get_blob(wpa_s->conf, blob_name)) {
1518 return dbus_message_new_error(message,
1519 WPAS_DBUS_ERROR_BLOB_EXISTS,
1523 dbus_message_iter_next(&iter);
1524 dbus_message_iter_recurse(&iter, &array_iter);
1526 dbus_message_iter_get_fixed_array(&array_iter, &blob_data, &blob_len);
1528 blob = os_zalloc(sizeof(*blob));
1530 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1535 blob->data = os_malloc(blob_len);
1537 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1541 os_memcpy(blob->data, blob_data, blob_len);
1543 blob->len = blob_len;
1544 blob->name = os_strdup(blob_name);
1546 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1551 wpa_config_set_blob(wpa_s->conf, blob);
1552 wpas_notify_blob_added(wpa_s, blob->name);
1558 os_free(blob->name);
1559 os_free(blob->data);
1567 * wpas_dbus_handler_get_blob - Get named binary blob (ie, for certificates)
1568 * @message: Pointer to incoming dbus message
1569 * @wpa_s: %wpa_supplicant data structure
1570 * Returns: A dbus message containing array of bytes (blob)
1572 * Gets one wpa_supplicant's binary blobs.
1574 DBusMessage * wpas_dbus_handler_get_blob(DBusMessage *message,
1575 struct wpa_supplicant *wpa_s)
1577 DBusMessage *reply = NULL;
1578 DBusMessageIter iter, array_iter;
1581 const struct wpa_config_blob *blob;
1583 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &blob_name,
1586 blob = wpa_config_get_blob(wpa_s->conf, blob_name);
1588 return dbus_message_new_error(message,
1589 WPAS_DBUS_ERROR_BLOB_UNKNOWN,
1593 reply = dbus_message_new_method_return(message);
1595 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1600 dbus_message_iter_init_append(reply, &iter);
1602 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
1603 DBUS_TYPE_BYTE_AS_STRING,
1605 dbus_message_unref(reply);
1606 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1611 if (!dbus_message_iter_append_fixed_array(&array_iter, DBUS_TYPE_BYTE,
1612 &(blob->data), blob->len)) {
1613 dbus_message_unref(reply);
1614 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1619 if (!dbus_message_iter_close_container(&iter, &array_iter)) {
1620 dbus_message_unref(reply);
1621 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1632 * wpas_remove_handler_remove_blob - Remove named binary blob
1633 * @message: Pointer to incoming dbus message
1634 * @wpa_s: %wpa_supplicant data structure
1635 * Returns: NULL on success or dbus error
1637 * Asks wpa_supplicant to internally remove a binary blobs.
1639 DBusMessage * wpas_dbus_handler_remove_blob(DBusMessage *message,
1640 struct wpa_supplicant *wpa_s)
1642 DBusMessage *reply = NULL;
1645 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &blob_name,
1648 if (wpa_config_remove_blob(wpa_s->conf, blob_name)) {
1649 return dbus_message_new_error(message,
1650 WPAS_DBUS_ERROR_BLOB_UNKNOWN,
1653 wpas_notify_blob_removed(wpa_s, blob_name);
1660 * wpas_dbus_handler_flush_bss - Flush the BSS cache
1661 * @message: Pointer to incoming dbus message
1662 * @wpa_s: wpa_supplicant structure for a network interface
1665 * Handler function for "FlushBSS" method call of network interface.
1667 DBusMessage * wpas_dbus_handler_flush_bss(DBusMessage *message,
1668 struct wpa_supplicant *wpa_s)
1672 dbus_message_get_args(message, NULL, DBUS_TYPE_UINT32, &age,
1676 wpa_bss_flush(wpa_s);
1678 wpa_bss_flush_by_age(wpa_s, age);
1685 * wpas_dbus_getter_capabilities - Return interface capabilities
1686 * @message: Pointer to incoming dbus message
1687 * @wpa_s: wpa_supplicant structure for a network interface
1688 * Returns: A dbus message containing a dict of strings
1690 * Getter for "Capabilities" property of an interface.
1692 DBusMessage * wpas_dbus_getter_capabilities(DBusMessage *message,
1693 struct wpa_supplicant *wpa_s)
1695 DBusMessage *reply = NULL;
1696 struct wpa_driver_capa capa;
1698 DBusMessageIter iter, iter_dict;
1699 DBusMessageIter iter_dict_entry, iter_dict_val, iter_array,
1701 const char *scans[] = { "active", "passive", "ssid" };
1703 if (message == NULL)
1704 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
1706 reply = dbus_message_new_method_return(message);
1710 dbus_message_iter_init_append(reply, &iter);
1711 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
1712 "a{sv}", &variant_iter))
1715 if (!wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
1718 res = wpa_drv_get_capa(wpa_s, &capa);
1720 /***** pairwise cipher */
1722 const char *args[] = {"ccmp", "tkip", "none"};
1723 if (!wpa_dbus_dict_append_string_array(
1724 &iter_dict, "Pairwise", args,
1725 sizeof(args) / sizeof(char*)))
1728 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Pairwise",
1734 if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
1735 if (!wpa_dbus_dict_string_array_add_element(
1736 &iter_array, "ccmp"))
1740 if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
1741 if (!wpa_dbus_dict_string_array_add_element(
1742 &iter_array, "tkip"))
1746 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
1747 if (!wpa_dbus_dict_string_array_add_element(
1748 &iter_array, "none"))
1752 if (!wpa_dbus_dict_end_string_array(&iter_dict,
1759 /***** group cipher */
1761 const char *args[] = {
1762 "ccmp", "tkip", "wep104", "wep40"
1764 if (!wpa_dbus_dict_append_string_array(
1765 &iter_dict, "Group", args,
1766 sizeof(args) / sizeof(char*)))
1769 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Group",
1775 if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
1776 if (!wpa_dbus_dict_string_array_add_element(
1777 &iter_array, "ccmp"))
1781 if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
1782 if (!wpa_dbus_dict_string_array_add_element(
1783 &iter_array, "tkip"))
1787 if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) {
1788 if (!wpa_dbus_dict_string_array_add_element(
1789 &iter_array, "wep104"))
1793 if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) {
1794 if (!wpa_dbus_dict_string_array_add_element(
1795 &iter_array, "wep40"))
1799 if (!wpa_dbus_dict_end_string_array(&iter_dict,
1806 /***** key management */
1808 const char *args[] = {
1809 "wpa-psk", "wpa-eap", "ieee8021x", "wpa-none",
1812 #endif /* CONFIG_WPS */
1815 if (!wpa_dbus_dict_append_string_array(
1816 &iter_dict, "KeyMgmt", args,
1817 sizeof(args) / sizeof(char*)))
1820 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "KeyMgmt",
1826 if (!wpa_dbus_dict_string_array_add_element(&iter_array,
1830 if (!wpa_dbus_dict_string_array_add_element(&iter_array,
1834 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
1835 WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
1836 if (!wpa_dbus_dict_string_array_add_element(
1837 &iter_array, "wpa-eap"))
1840 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT)
1841 if (!wpa_dbus_dict_string_array_add_element(
1842 &iter_array, "wpa-ft-eap"))
1845 /* TODO: Ensure that driver actually supports sha256 encryption. */
1846 #ifdef CONFIG_IEEE80211W
1847 if (!wpa_dbus_dict_string_array_add_element(
1848 &iter_array, "wpa-eap-sha256"))
1850 #endif /* CONFIG_IEEE80211W */
1853 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
1854 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
1855 if (!wpa_dbus_dict_string_array_add_element(
1856 &iter_array, "wpa-psk"))
1859 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK)
1860 if (!wpa_dbus_dict_string_array_add_element(
1861 &iter_array, "wpa-ft-psk"))
1864 /* TODO: Ensure that driver actually supports sha256 encryption. */
1865 #ifdef CONFIG_IEEE80211W
1866 if (!wpa_dbus_dict_string_array_add_element(
1867 &iter_array, "wpa-psk-sha256"))
1869 #endif /* CONFIG_IEEE80211W */
1872 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
1873 if (!wpa_dbus_dict_string_array_add_element(
1874 &iter_array, "wpa-none"))
1880 if (!wpa_dbus_dict_string_array_add_element(&iter_array,
1883 #endif /* CONFIG_WPS */
1885 if (!wpa_dbus_dict_end_string_array(&iter_dict,
1892 /***** WPA protocol */
1894 const char *args[] = { "rsn", "wpa" };
1895 if (!wpa_dbus_dict_append_string_array(
1896 &iter_dict, "Protocol", args,
1897 sizeof(args) / sizeof(char*)))
1900 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Protocol",
1906 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
1907 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
1908 if (!wpa_dbus_dict_string_array_add_element(
1909 &iter_array, "rsn"))
1913 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
1914 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
1915 if (!wpa_dbus_dict_string_array_add_element(
1916 &iter_array, "wpa"))
1920 if (!wpa_dbus_dict_end_string_array(&iter_dict,
1929 const char *args[] = { "open", "shared", "leap" };
1930 if (!wpa_dbus_dict_append_string_array(
1931 &iter_dict, "AuthAlg", args,
1932 sizeof(args) / sizeof(char*)))
1935 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "AuthAlg",
1941 if (capa.auth & (WPA_DRIVER_AUTH_OPEN)) {
1942 if (!wpa_dbus_dict_string_array_add_element(
1943 &iter_array, "open"))
1947 if (capa.auth & (WPA_DRIVER_AUTH_SHARED)) {
1948 if (!wpa_dbus_dict_string_array_add_element(
1949 &iter_array, "shared"))
1953 if (capa.auth & (WPA_DRIVER_AUTH_LEAP)) {
1954 if (!wpa_dbus_dict_string_array_add_element(
1955 &iter_array, "leap"))
1959 if (!wpa_dbus_dict_end_string_array(&iter_dict,
1967 if (!wpa_dbus_dict_append_string_array(&iter_dict, "Scan", scans,
1968 sizeof(scans) / sizeof(char *)))
1972 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Modes",
1978 if (!wpa_dbus_dict_string_array_add_element(
1979 &iter_array, "infrastructure"))
1982 if (!wpa_dbus_dict_string_array_add_element(
1983 &iter_array, "ad-hoc"))
1987 if (capa.flags & (WPA_DRIVER_FLAGS_AP)) {
1988 if (!wpa_dbus_dict_string_array_add_element(
1993 if (capa.flags & (WPA_DRIVER_FLAGS_P2P_CAPABLE)) {
1994 if (!wpa_dbus_dict_string_array_add_element(
1995 &iter_array, "p2p"))
2000 if (!wpa_dbus_dict_end_string_array(&iter_dict,
2007 if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict))
2009 if (!dbus_message_iter_close_container(&iter, &variant_iter))
2016 dbus_message_unref(reply);
2018 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, NULL);
2023 * wpas_dbus_getter_state - Get interface state
2024 * @message: Pointer to incoming dbus message
2025 * @wpa_s: wpa_supplicant structure for a network interface
2026 * Returns: A dbus message containing a STRING representing the current
2029 * Getter for "State" property.
2031 DBusMessage * wpas_dbus_getter_state(DBusMessage *message,
2032 struct wpa_supplicant *wpa_s)
2034 DBusMessage *reply = NULL;
2035 const char *str_state;
2036 char *state_ls, *tmp;
2038 str_state = wpa_supplicant_state_txt(wpa_s->wpa_state);
2040 /* make state string lowercase to fit new DBus API convention
2042 state_ls = tmp = os_strdup(str_state);
2044 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2048 *tmp = tolower(*tmp);
2052 reply = wpas_dbus_simple_property_getter(message, DBUS_TYPE_STRING,
2062 * wpas_dbus_new_iface_get_scanning - Get interface scanning state
2063 * @message: Pointer to incoming dbus message
2064 * @wpa_s: wpa_supplicant structure for a network interface
2065 * Returns: A dbus message containing whether the interface is scanning
2067 * Getter for "scanning" property.
2069 DBusMessage * wpas_dbus_getter_scanning(DBusMessage *message,
2070 struct wpa_supplicant *wpa_s)
2072 dbus_bool_t scanning = wpa_s->scanning ? TRUE : FALSE;
2073 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_BOOLEAN,
2079 * wpas_dbus_getter_ap_scan - Control roaming mode
2080 * @message: Pointer to incoming dbus message
2081 * @wpa_s: wpa_supplicant structure for a network interface
2082 * Returns: A message containong value of ap_scan variable
2084 * Getter function for "ApScan" property.
2086 DBusMessage * wpas_dbus_getter_ap_scan(DBusMessage *message,
2087 struct wpa_supplicant *wpa_s)
2089 dbus_uint32_t ap_scan = wpa_s->conf->ap_scan;
2090 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_UINT32,
2096 * wpas_dbus_setter_ap_scan - Control roaming mode
2097 * @message: Pointer to incoming dbus message
2098 * @wpa_s: wpa_supplicant structure for a network interface
2101 * Setter function for "ApScan" property.
2103 DBusMessage * wpas_dbus_setter_ap_scan(DBusMessage *message,
2104 struct wpa_supplicant *wpa_s)
2106 DBusMessage *reply = NULL;
2107 dbus_uint32_t ap_scan;
2109 reply = wpas_dbus_simple_property_setter(message, DBUS_TYPE_UINT32,
2114 if (wpa_supplicant_set_ap_scan(wpa_s, ap_scan)) {
2115 return wpas_dbus_error_invalid_args(
2116 message, "ap_scan must equal 0, 1 or 2");
2123 * wpas_dbus_getter_bss_expire_age - Get BSS entry expiration age
2124 * @message: Pointer to incoming dbus message
2125 * @wpa_s: wpa_supplicant structure for a network interface
2126 * Returns: A message containing value of bss_expiration_age variable
2128 * Getter function for "BSSExpireAge" property.
2130 DBusMessage * wpas_dbus_getter_bss_expire_age(DBusMessage *message,
2131 struct wpa_supplicant *wpa_s)
2133 dbus_uint32_t expire_age = wpa_s->conf->bss_expiration_age;
2134 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_UINT32,
2140 * wpas_dbus_setter_bss_expire_age - Control BSS entry expiration age
2141 * @message: Pointer to incoming dbus message
2142 * @wpa_s: wpa_supplicant structure for a network interface
2145 * Setter function for "BSSExpireAge" property.
2147 DBusMessage * wpas_dbus_setter_bss_expire_age(DBusMessage *message,
2148 struct wpa_supplicant *wpa_s)
2150 DBusMessage *reply = NULL;
2151 dbus_uint32_t expire_age;
2153 reply = wpas_dbus_simple_property_setter(message, DBUS_TYPE_UINT32,
2158 if (wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age)) {
2159 return wpas_dbus_error_invalid_args(
2160 message, "BSSExpireAge must be >=10");
2167 * wpas_dbus_getter_bss_expire_count - Get BSS entry expiration scan count
2168 * @message: Pointer to incoming dbus message
2169 * @wpa_s: wpa_supplicant structure for a network interface
2170 * Returns: A message containing value of bss_expire_count variable
2172 * Getter function for "BSSExpireCount" property.
2174 DBusMessage * wpas_dbus_getter_bss_expire_count(DBusMessage *message,
2175 struct wpa_supplicant *wpa_s)
2177 dbus_uint32_t expire_count = wpa_s->conf->bss_expiration_age;
2178 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_UINT32,
2184 * wpas_dbus_setter_bss_expire_count - Control BSS entry expiration scan count
2185 * @message: Pointer to incoming dbus message
2186 * @wpa_s: wpa_supplicant structure for a network interface
2189 * Setter function for "BSSExpireCount" property.
2191 DBusMessage * wpas_dbus_setter_bss_expire_count(DBusMessage *message,
2192 struct wpa_supplicant *wpa_s)
2194 DBusMessage *reply = NULL;
2195 dbus_uint32_t expire_count;
2197 reply = wpas_dbus_simple_property_setter(message, DBUS_TYPE_UINT32,
2202 if (wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count)) {
2203 return wpas_dbus_error_invalid_args(
2204 message, "BSSExpireCount must be >0");
2211 * wpas_dbus_getter_country - Control country code
2212 * @message: Pointer to incoming dbus message
2213 * @wpa_s: wpa_supplicant structure for a network interface
2214 * Returns: A message containong value of country variable
2216 * Getter function for "Country" property.
2218 DBusMessage * wpas_dbus_getter_country(DBusMessage *message,
2219 struct wpa_supplicant *wpa_s)
2222 char *str = country;
2224 country[0] = wpa_s->conf->country[0];
2225 country[1] = wpa_s->conf->country[1];
2228 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_STRING,
2234 * wpas_dbus_setter_country - Control country code
2235 * @message: Pointer to incoming dbus message
2236 * @wpa_s: wpa_supplicant structure for a network interface
2239 * Setter function for "Country" property.
2241 DBusMessage * wpas_dbus_setter_country(DBusMessage *message,
2242 struct wpa_supplicant *wpa_s)
2244 DBusMessage *reply = NULL;
2245 const char *country;
2247 reply = wpas_dbus_simple_property_setter(message, DBUS_TYPE_STRING,
2252 if (!country[0] || !country[1])
2253 return wpas_dbus_error_invalid_args(message,
2254 "invalid country code");
2256 if (wpa_s->drv_priv != NULL && wpa_drv_set_country(wpa_s, country)) {
2257 wpa_printf(MSG_DEBUG, "Failed to set country");
2258 return wpas_dbus_error_invalid_args(
2259 message, "failed to set country code");
2262 wpa_s->conf->country[0] = country[0];
2263 wpa_s->conf->country[1] = country[1];
2269 * wpas_dbus_getter_ifname - Get interface name
2270 * @message: Pointer to incoming dbus message
2271 * @wpa_s: wpa_supplicant structure for a network interface
2272 * Returns: A dbus message containing a name of network interface
2273 * associated with with wpa_s
2275 * Getter for "Ifname" property.
2277 DBusMessage * wpas_dbus_getter_ifname(DBusMessage *message,
2278 struct wpa_supplicant *wpa_s)
2280 const char *ifname = wpa_s->ifname;
2281 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_STRING,
2287 * wpas_dbus_getter_driver - Get interface name
2288 * @message: Pointer to incoming dbus message
2289 * @wpa_s: wpa_supplicant structure for a network interface
2290 * Returns: A dbus message containing a name of network interface
2291 * driver associated with with wpa_s
2293 * Getter for "Driver" property.
2295 DBusMessage * wpas_dbus_getter_driver(DBusMessage *message,
2296 struct wpa_supplicant *wpa_s)
2300 if (wpa_s->driver == NULL || wpa_s->driver->name == NULL) {
2301 wpa_printf(MSG_DEBUG, "wpas_dbus_getter_driver[dbus]: "
2302 "wpa_s has no driver set");
2303 return wpas_dbus_error_unknown_error(message, NULL);
2306 driver = wpa_s->driver->name;
2307 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_STRING,
2313 * wpas_dbus_getter_current_bss - Get current bss object path
2314 * @message: Pointer to incoming dbus message
2315 * @wpa_s: wpa_supplicant structure for a network interface
2316 * Returns: A dbus message containing a DBus object path to
2319 * Getter for "CurrentBSS" property.
2321 DBusMessage * wpas_dbus_getter_current_bss(DBusMessage *message,
2322 struct wpa_supplicant *wpa_s)
2325 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *bss_obj_path = path_buf;
2327 if (wpa_s->current_bss)
2328 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2329 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
2330 wpa_s->dbus_new_path, wpa_s->current_bss->id);
2332 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
2334 reply = wpas_dbus_simple_property_getter(message,
2335 DBUS_TYPE_OBJECT_PATH,
2343 * wpas_dbus_getter_current_network - Get current network object path
2344 * @message: Pointer to incoming dbus message
2345 * @wpa_s: wpa_supplicant structure for a network interface
2346 * Returns: A dbus message containing a DBus object path to
2349 * Getter for "CurrentNetwork" property.
2351 DBusMessage * wpas_dbus_getter_current_network(DBusMessage *message,
2352 struct wpa_supplicant *wpa_s)
2355 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *net_obj_path = path_buf;
2357 if (wpa_s->current_ssid)
2358 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2359 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
2360 wpa_s->dbus_new_path, wpa_s->current_ssid->id);
2362 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
2364 reply = wpas_dbus_simple_property_getter(message,
2365 DBUS_TYPE_OBJECT_PATH,
2373 * wpas_dbus_getter_current_auth_mode - Get current authentication type
2374 * @message: Pointer to incoming dbus message
2375 * @wpa_s: wpa_supplicant structure for a network interface
2376 * Returns: A dbus message containing a string indicating the current
2377 * authentication type.
2379 * Getter for "CurrentAuthMode" property.
2381 DBusMessage * wpas_dbus_getter_current_auth_mode(DBusMessage *message,
2382 struct wpa_supplicant *wpa_s)
2385 const char *eap_mode;
2386 const char *auth_mode;
2387 char eap_mode_buf[WPAS_DBUS_AUTH_MODE_MAX];
2389 if (wpa_s->wpa_state != WPA_COMPLETED) {
2390 auth_mode = "INACTIVE";
2391 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X ||
2392 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2393 eap_mode = wpa_supplicant_get_eap_mode(wpa_s);
2394 os_snprintf(eap_mode_buf, WPAS_DBUS_AUTH_MODE_MAX,
2395 "EAP-%s", eap_mode);
2396 auth_mode = eap_mode_buf;
2399 auth_mode = wpa_key_mgmt_txt(wpa_s->key_mgmt,
2400 wpa_s->current_ssid->proto);
2403 reply = wpas_dbus_simple_property_getter(message,
2412 * wpas_dbus_getter_bridge_ifname - Get interface name
2413 * @message: Pointer to incoming dbus message
2414 * @wpa_s: wpa_supplicant structure for a network interface
2415 * Returns: A dbus message containing a name of bridge network
2416 * interface associated with with wpa_s
2418 * Getter for "BridgeIfname" property.
2420 DBusMessage * wpas_dbus_getter_bridge_ifname(DBusMessage *message,
2421 struct wpa_supplicant *wpa_s)
2423 const char *bridge_ifname = NULL;
2425 bridge_ifname = wpa_s->bridge_ifname;
2426 if (bridge_ifname == NULL) {
2427 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bridge_ifname[dbus]: "
2428 "wpa_s has no bridge interface name set");
2429 return wpas_dbus_error_unknown_error(message, NULL);
2432 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_STRING,
2438 * wpas_dbus_getter_bsss - Get array of BSSs objects
2439 * @message: Pointer to incoming dbus message
2440 * @wpa_s: wpa_supplicant structure for a network interface
2441 * Returns: a dbus message containing an array of all known BSS objects
2444 * Getter for "BSSs" property.
2446 DBusMessage * wpas_dbus_getter_bsss(DBusMessage *message,
2447 struct wpa_supplicant *wpa_s)
2449 DBusMessage *reply = NULL;
2450 struct wpa_bss *bss;
2454 paths = os_zalloc(wpa_s->num_bss * sizeof(char *));
2456 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2460 /* Loop through scan results and append each result's object path */
2461 dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
2462 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
2463 if (paths[i] == NULL) {
2464 reply = dbus_message_new_error(message,
2465 DBUS_ERROR_NO_MEMORY,
2469 /* Construct the object path for this BSS. */
2470 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
2471 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
2472 wpa_s->dbus_new_path, bss->id);
2475 reply = wpas_dbus_simple_array_property_getter(message,
2476 DBUS_TYPE_OBJECT_PATH,
2477 paths, wpa_s->num_bss);
2481 os_free(paths[--i]);
2488 * wpas_dbus_getter_networks - Get array of networks objects
2489 * @message: Pointer to incoming dbus message
2490 * @wpa_s: wpa_supplicant structure for a network interface
2491 * Returns: a dbus message containing an array of all configured
2492 * networks dbus object paths.
2494 * Getter for "Networks" property.
2496 DBusMessage * wpas_dbus_getter_networks(DBusMessage *message,
2497 struct wpa_supplicant *wpa_s)
2499 DBusMessage *reply = NULL;
2500 struct wpa_ssid *ssid;
2502 unsigned int i = 0, num = 0;
2504 if (wpa_s->conf == NULL) {
2505 wpa_printf(MSG_ERROR, "wpas_dbus_getter_networks[dbus]: "
2506 "An error occurred getting networks list.");
2507 return wpas_dbus_error_unknown_error(message, NULL);
2510 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
2511 if (!network_is_persistent_group(ssid))
2514 paths = os_zalloc(num * sizeof(char *));
2516 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2520 /* Loop through configured networks and append object path of each */
2521 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2522 if (network_is_persistent_group(ssid))
2524 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
2525 if (paths[i] == NULL) {
2526 reply = dbus_message_new_error(message,
2527 DBUS_ERROR_NO_MEMORY,
2532 /* Construct the object path for this network. */
2533 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
2534 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
2535 wpa_s->dbus_new_path, ssid->id);
2538 reply = wpas_dbus_simple_array_property_getter(message,
2539 DBUS_TYPE_OBJECT_PATH,
2544 os_free(paths[--i]);
2551 * wpas_dbus_getter_blobs - Get all blobs defined for this interface
2552 * @message: Pointer to incoming dbus message
2553 * @wpa_s: wpa_supplicant structure for a network interface
2554 * Returns: a dbus message containing a dictionary of pairs (blob_name, blob)
2556 * Getter for "Blobs" property.
2558 DBusMessage * wpas_dbus_getter_blobs(DBusMessage *message,
2559 struct wpa_supplicant *wpa_s)
2561 DBusMessage *reply = NULL;
2562 DBusMessageIter iter, variant_iter, dict_iter, entry_iter, array_iter;
2563 struct wpa_config_blob *blob;
2565 if (message == NULL)
2566 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
2568 reply = dbus_message_new_method_return(message);
2570 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2573 dbus_message_iter_init_append(reply, &iter);
2575 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
2576 "a{say}", &variant_iter) ||
2577 !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
2578 "{say}", &dict_iter)) {
2579 dbus_message_unref(reply);
2580 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2584 blob = wpa_s->conf->blobs;
2586 if (!dbus_message_iter_open_container(&dict_iter,
2587 DBUS_TYPE_DICT_ENTRY,
2588 NULL, &entry_iter) ||
2589 !dbus_message_iter_append_basic(&entry_iter,
2592 !dbus_message_iter_open_container(&entry_iter,
2594 DBUS_TYPE_BYTE_AS_STRING,
2596 !dbus_message_iter_append_fixed_array(&array_iter,
2600 !dbus_message_iter_close_container(&entry_iter,
2602 !dbus_message_iter_close_container(&dict_iter,
2604 dbus_message_unref(reply);
2605 return dbus_message_new_error(message,
2606 DBUS_ERROR_NO_MEMORY,
2613 if (!dbus_message_iter_close_container(&variant_iter, &dict_iter) ||
2614 !dbus_message_iter_close_container(&iter, &variant_iter)) {
2615 dbus_message_unref(reply);
2616 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2625 * wpas_dbus_getter_bss_bssid - Return the BSSID of a BSS
2626 * @message: Pointer to incoming dbus message
2627 * @bss: a pair of interface describing structure and bss's id
2628 * Returns: a dbus message containing the bssid for the requested bss
2630 * Getter for "BSSID" property.
2632 DBusMessage * wpas_dbus_getter_bss_bssid(DBusMessage *message,
2633 struct bss_handler_args *bss)
2635 struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id);
2638 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_bssid[dbus]: no "
2639 "bss with id %d found", bss->id);
2643 return wpas_dbus_simple_array_property_getter(message, DBUS_TYPE_BYTE,
2644 res->bssid, ETH_ALEN);
2649 * wpas_dbus_getter_bss_ssid - Return the SSID of a BSS
2650 * @message: Pointer to incoming dbus message
2651 * @bss: a pair of interface describing structure and bss's id
2652 * Returns: a dbus message containing the ssid for the requested bss
2654 * Getter for "SSID" property.
2656 DBusMessage * wpas_dbus_getter_bss_ssid(DBusMessage *message,
2657 struct bss_handler_args *bss)
2659 struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id);
2662 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_ssid[dbus]: no "
2663 "bss with id %d found", bss->id);
2667 return wpas_dbus_simple_array_property_getter(message, DBUS_TYPE_BYTE,
2674 * wpas_dbus_getter_bss_privacy - Return the privacy flag of a BSS
2675 * @message: Pointer to incoming dbus message
2676 * @bss: a pair of interface describing structure and bss's id
2677 * Returns: a dbus message containing the privacy flag value of requested bss
2679 * Getter for "Privacy" property.
2681 DBusMessage * wpas_dbus_getter_bss_privacy(DBusMessage *message,
2682 struct bss_handler_args *bss)
2684 struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id);
2685 dbus_bool_t privacy;
2688 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_privacy[dbus]: no "
2689 "bss with id %d found", bss->id);
2693 privacy = (res->caps & IEEE80211_CAP_PRIVACY) ? TRUE : FALSE;
2694 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_BOOLEAN,
2700 * wpas_dbus_getter_bss_mode - Return the mode of a BSS
2701 * @message: Pointer to incoming dbus message
2702 * @bss: a pair of interface describing structure and bss's id
2703 * Returns: a dbus message containing the mode of requested bss
2705 * Getter for "Mode" property.
2707 DBusMessage * wpas_dbus_getter_bss_mode(DBusMessage *message,
2708 struct bss_handler_args *bss)
2710 struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id);
2714 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_mode[dbus]: no "
2715 "bss with id %d found", bss->id);
2719 if (res->caps & IEEE80211_CAP_IBSS)
2722 mode = "infrastructure";
2724 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_STRING,
2730 * wpas_dbus_getter_bss_level - Return the signal strength of a BSS
2731 * @message: Pointer to incoming dbus message
2732 * @bss: a pair of interface describing structure and bss's id
2733 * Returns: a dbus message containing the signal strength of requested bss
2735 * Getter for "Level" property.
2737 DBusMessage * wpas_dbus_getter_bss_signal(DBusMessage *message,
2738 struct bss_handler_args *bss)
2740 struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id);
2743 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_signal[dbus]: no "
2744 "bss with id %d found", bss->id);
2748 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_INT16,
2754 * wpas_dbus_getter_bss_frequency - Return the frequency of a BSS
2755 * @message: Pointer to incoming dbus message
2756 * @bss: a pair of interface describing structure and bss's id
2757 * Returns: a dbus message containing the frequency of requested bss
2759 * Getter for "Frequency" property.
2761 DBusMessage * wpas_dbus_getter_bss_frequency(DBusMessage *message,
2762 struct bss_handler_args *bss)
2764 struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id);
2767 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_frequency[dbus]: "
2768 "no bss with id %d found", bss->id);
2772 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_UINT16,
2777 static int cmp_u8s_desc(const void *a, const void *b)
2779 return (*(u8 *) b - *(u8 *) a);
2784 * wpas_dbus_getter_bss_rates - Return available bit rates of a BSS
2785 * @message: Pointer to incoming dbus message
2786 * @bss: a pair of interface describing structure and bss's id
2787 * Returns: a dbus message containing sorted array of bit rates
2789 * Getter for "Rates" property.
2791 DBusMessage * wpas_dbus_getter_bss_rates(DBusMessage *message,
2792 struct bss_handler_args *bss)
2795 struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id);
2796 u8 *ie_rates = NULL;
2801 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_rates[dbus]: "
2802 "no bss with id %d found", bss->id);
2806 rates_num = wpa_bss_get_bit_rates(res, &ie_rates);
2810 qsort(ie_rates, rates_num, 1, cmp_u8s_desc);
2812 real_rates = os_malloc(sizeof(u32) * rates_num);
2815 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2819 for (i = 0; i < rates_num; i++)
2820 real_rates[i] = ie_rates[i] * 500000;
2822 reply = wpas_dbus_simple_array_property_getter(message,
2824 real_rates, rates_num);
2827 os_free(real_rates);
2832 static DBusMessage * wpas_dbus_get_bss_security_prop(
2833 DBusMessage *message, struct wpa_ie_data *ie_data)
2836 DBusMessageIter iter, iter_dict, variant_iter;
2838 const char *pairwise[2]; /* max 2 pairwise ciphers is supported */
2839 const char *key_mgmt[7]; /* max 7 key managements may be supported */
2842 if (message == NULL)
2843 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
2845 reply = dbus_message_new_method_return(message);
2849 dbus_message_iter_init_append(reply, &iter);
2850 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
2851 "a{sv}", &variant_iter))
2854 if (!wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
2859 if (ie_data->key_mgmt & WPA_KEY_MGMT_PSK)
2860 key_mgmt[n++] = "wpa-psk";
2861 if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_PSK)
2862 key_mgmt[n++] = "wpa-ft-psk";
2863 if (ie_data->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
2864 key_mgmt[n++] = "wpa-psk-sha256";
2865 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X)
2866 key_mgmt[n++] = "wpa-eap";
2867 if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X)
2868 key_mgmt[n++] = "wpa-ft-eap";
2869 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256)
2870 key_mgmt[n++] = "wpa-eap-sha256";
2871 if (ie_data->key_mgmt & WPA_KEY_MGMT_NONE)
2872 key_mgmt[n++] = "wpa-none";
2874 if (!wpa_dbus_dict_append_string_array(&iter_dict, "KeyMgmt",
2879 switch (ie_data->group_cipher) {
2880 case WPA_CIPHER_WEP40:
2883 case WPA_CIPHER_TKIP:
2886 case WPA_CIPHER_CCMP:
2889 case WPA_CIPHER_WEP104:
2897 if (!wpa_dbus_dict_append_string(&iter_dict, "Group", group))
2902 if (ie_data->pairwise_cipher & WPA_CIPHER_TKIP)
2903 pairwise[n++] = "tkip";
2904 if (ie_data->pairwise_cipher & WPA_CIPHER_CCMP)
2905 pairwise[n++] = "ccmp";
2907 if (!wpa_dbus_dict_append_string_array(&iter_dict, "Pairwise",
2911 /* Management group (RSN only) */
2912 if (ie_data->proto == WPA_PROTO_RSN) {
2913 switch (ie_data->mgmt_group_cipher) {
2914 #ifdef CONFIG_IEEE80211W
2915 case WPA_CIPHER_AES_128_CMAC:
2916 group = "aes128cmac";
2918 #endif /* CONFIG_IEEE80211W */
2924 if (!wpa_dbus_dict_append_string(&iter_dict, "MgmtGroup",
2929 if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict))
2931 if (!dbus_message_iter_close_container(&iter, &variant_iter))
2938 dbus_message_unref(reply);
2940 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, NULL);
2945 * wpas_dbus_getter_bss_wpa - Return the WPA options of a BSS
2946 * @message: Pointer to incoming dbus message
2947 * @bss: a pair of interface describing structure and bss's id
2948 * Returns: a dbus message containing the WPA options of requested bss
2950 * Getter for "WPA" property.
2952 DBusMessage * wpas_dbus_getter_bss_wpa(DBusMessage *message,
2953 struct bss_handler_args *bss)
2955 struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id);
2956 struct wpa_ie_data wpa_data;
2960 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_wpa[dbus]: no "
2961 "bss with id %d found", bss->id);
2965 os_memset(&wpa_data, 0, sizeof(wpa_data));
2966 ie = wpa_bss_get_vendor_ie(res, WPA_IE_VENDOR_TYPE);
2968 if (wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0)
2969 return wpas_dbus_error_unknown_error(message,
2973 return wpas_dbus_get_bss_security_prop(message, &wpa_data);
2978 * wpas_dbus_getter_bss_rsn - Return the RSN options of a BSS
2979 * @message: Pointer to incoming dbus message
2980 * @bss: a pair of interface describing structure and bss's id
2981 * Returns: a dbus message containing the RSN options of requested bss
2983 * Getter for "RSN" property.
2985 DBusMessage * wpas_dbus_getter_bss_rsn(DBusMessage *message,
2986 struct bss_handler_args *bss)
2988 struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id);
2989 struct wpa_ie_data wpa_data;
2993 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_rsn[dbus]: no "
2994 "bss with id %d found", bss->id);
2998 os_memset(&wpa_data, 0, sizeof(wpa_data));
2999 ie = wpa_bss_get_ie(res, WLAN_EID_RSN);
3001 if (wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0)
3002 return wpas_dbus_error_unknown_error(message,
3006 return wpas_dbus_get_bss_security_prop(message, &wpa_data);
3011 * wpas_dbus_getter_bss_ies - Return all IEs of a BSS
3012 * @message: Pointer to incoming dbus message
3013 * @bss: a pair of interface describing structure and bss's id
3014 * Returns: a dbus message containing IEs byte array
3016 * Getter for "IEs" property.
3018 DBusMessage * wpas_dbus_getter_bss_ies(DBusMessage *message,
3019 struct bss_handler_args *bss)
3021 struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id);
3024 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_ies[dbus]: no "
3025 "bss with id %d found", bss->id);
3029 return wpas_dbus_simple_array_property_getter(message, DBUS_TYPE_BYTE,
3030 res + 1, res->ie_len);
3035 * wpas_dbus_getter_enabled - Check whether network is enabled or disabled
3036 * @message: Pointer to incoming dbus message
3037 * @wpas_dbus_setter_enabled: wpa_supplicant structure for a network interface
3038 * and wpa_ssid structure for a configured network
3039 * Returns: DBus message with boolean indicating state of configured network
3040 * or DBus error on failure
3042 * Getter for "enabled" property of a configured network.
3044 DBusMessage * wpas_dbus_getter_enabled(DBusMessage *message,
3045 struct network_handler_args *net)
3047 dbus_bool_t enabled = net->ssid->disabled ? FALSE : TRUE;
3048 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_BOOLEAN,
3054 * wpas_dbus_setter_enabled - Mark a configured network as enabled or disabled
3055 * @message: Pointer to incoming dbus message
3056 * @wpas_dbus_setter_enabled: wpa_supplicant structure for a network interface
3057 * and wpa_ssid structure for a configured network
3058 * Returns: NULL indicating success or DBus error on failure
3060 * Setter for "Enabled" property of a configured network.
3062 DBusMessage * wpas_dbus_setter_enabled(DBusMessage *message,
3063 struct network_handler_args *net)
3065 DBusMessage *reply = NULL;
3067 struct wpa_supplicant *wpa_s;
3068 struct wpa_ssid *ssid;
3072 reply = wpas_dbus_simple_property_setter(message, DBUS_TYPE_BOOLEAN,
3082 wpa_supplicant_enable_network(wpa_s, ssid);
3084 wpa_supplicant_disable_network(wpa_s, ssid);
3091 * wpas_dbus_getter_network_properties - Get options for a configured network
3092 * @message: Pointer to incoming dbus message
3093 * @net: wpa_supplicant structure for a network interface and
3094 * wpa_ssid structure for a configured network
3095 * Returns: DBus message with network properties or DBus error on failure
3097 * Getter for "Properties" property of a configured network.
3099 DBusMessage * wpas_dbus_getter_network_properties(
3100 DBusMessage *message, struct network_handler_args *net)
3102 DBusMessage *reply = NULL;
3103 DBusMessageIter iter, variant_iter, dict_iter;
3105 char **props = wpa_config_get_all(net->ssid, 1);
3107 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
3110 if (message == NULL)
3111 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
3113 reply = dbus_message_new_method_return(message);
3115 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
3120 dbus_message_iter_init_append(reply, &iter);
3122 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
3123 "a{sv}", &variant_iter) ||
3124 !wpa_dbus_dict_open_write(&variant_iter, &dict_iter)) {
3125 dbus_message_unref(reply);
3126 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
3133 if (!wpa_dbus_dict_append_string(&dict_iter, *iterator,
3135 dbus_message_unref(reply);
3136 reply = dbus_message_new_error(message,
3137 DBUS_ERROR_NO_MEMORY,
3145 if (!wpa_dbus_dict_close_write(&variant_iter, &dict_iter) ||
3146 !dbus_message_iter_close_container(&iter, &variant_iter)) {
3147 dbus_message_unref(reply);
3148 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
3165 * wpas_dbus_setter_network_properties - Set options for a configured network
3166 * @message: Pointer to incoming dbus message
3167 * @net: wpa_supplicant structure for a network interface and
3168 * wpa_ssid structure for a configured network
3169 * Returns: NULL indicating success or DBus error on failure
3171 * Setter for "Properties" property of a configured network.
3173 DBusMessage * wpas_dbus_setter_network_properties(
3174 DBusMessage *message, struct network_handler_args *net)
3176 struct wpa_ssid *ssid = net->ssid;
3178 DBusMessage *reply = NULL;
3179 DBusMessageIter iter, variant_iter;
3181 dbus_message_iter_init(message, &iter);
3183 dbus_message_iter_next(&iter);
3184 dbus_message_iter_next(&iter);
3186 dbus_message_iter_recurse(&iter, &variant_iter);
3188 reply = set_network_properties(message, net->wpa_s, ssid,
3191 wpa_printf(MSG_DEBUG, "dbus control interface couldn't set "
3192 "network properties");