2 * WPA Supplicant / dbus-based control interface
3 * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
4 * Copyright (c) 2009, Witold Sowa <witold.sowa@gmail.com>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
10 * Alternatively, this software may be distributed under the terms of BSD
13 * See README and COPYING for more details.
19 #include "common/ieee802_11_defs.h"
20 #include "eap_peer/eap_methods.h"
21 #include "eapol_supp/eapol_supp_sm.h"
22 #include "../config.h"
23 #include "../wpa_supplicant_i.h"
24 #include "../driver_i.h"
25 #include "../notify.h"
26 #include "../wpas_glue.h"
27 #include "dbus_new_helpers.h"
29 #include "dbus_new_handlers.h"
30 #include "dbus_dict_helpers.h"
32 extern int wpa_debug_level;
33 extern int wpa_debug_show_keys;
34 extern int wpa_debug_timestamp;
38 * wpas_dbus_new_decompose_object_path - Decompose an interface object path into parts
39 * @path: The dbus object path
40 * @network: (out) the configured network this object path refers to, if any
41 * @bssid: (out) the scanned bssid this object path refers to, if any
42 * Returns: The object path of the network interface this path refers to
44 * For a given object path, decomposes the object path into object id, network,
45 * and BSSID parts, if those parts exist.
47 static char * wpas_dbus_new_decompose_object_path(const char *path,
51 const unsigned int dev_path_prefix_len =
52 strlen(WPAS_DBUS_NEW_PATH_INTERFACES "/");
56 /* Be a bit paranoid about path */
57 if (!path || os_strncmp(path, WPAS_DBUS_NEW_PATH_INTERFACES "/",
61 /* Ensure there's something at the end of the path */
62 if ((path + dev_path_prefix_len)[0] == '\0')
65 obj_path_only = os_strdup(path);
66 if (obj_path_only == NULL)
69 next_sep = os_strchr(obj_path_only + dev_path_prefix_len, '/');
70 if (next_sep != NULL) {
71 const char *net_part = os_strstr(
72 next_sep, WPAS_DBUS_NEW_NETWORKS_PART "/");
73 const char *bssid_part = os_strstr(
74 next_sep, WPAS_DBUS_NEW_BSSIDS_PART "/");
76 if (network && net_part) {
77 /* Deal with a request for a configured network */
78 const char *net_name = net_part +
79 os_strlen(WPAS_DBUS_NEW_NETWORKS_PART "/");
81 if (os_strlen(net_name))
82 *network = os_strdup(net_name);
83 } else if (bssid && bssid_part) {
84 /* Deal with a request for a scanned BSSID */
85 const char *bssid_name = bssid_part +
86 os_strlen(WPAS_DBUS_NEW_BSSIDS_PART "/");
87 if (strlen(bssid_name))
88 *bssid = os_strdup(bssid_name);
93 /* Cut off interface object path before "/" */
102 * wpas_dbus_error_unknown_error - Return a new InvalidArgs error message
103 * @message: Pointer to incoming dbus message this error refers to
104 * @arg: Optional string appended to error message
105 * Returns: a dbus error message
107 * Convenience function to create and return an UnknownError
109 DBusMessage * wpas_dbus_error_unknown_error(DBusMessage *message,
112 return dbus_message_new_error(message, WPAS_DBUS_ERROR_UNKNOWN_ERROR,
118 * wpas_dbus_error_iface_unknown - Return a new invalid interface error message
119 * @message: Pointer to incoming dbus message this error refers to
120 * Returns: A dbus error message
122 * Convenience function to create and return an invalid interface error
124 static DBusMessage * wpas_dbus_error_iface_unknown(DBusMessage *message)
126 return dbus_message_new_error(message, WPAS_DBUS_ERROR_IFACE_UNKNOWN,
127 "wpa_supplicant knows nothing about "
133 * wpas_dbus_error_network_unknown - Return a new NetworkUnknown error message
134 * @message: Pointer to incoming dbus message this error refers to
135 * Returns: a dbus error message
137 * Convenience function to create and return an invalid network error
139 static DBusMessage * wpas_dbus_error_network_unknown(DBusMessage *message)
141 return dbus_message_new_error(message, WPAS_DBUS_ERROR_NETWORK_UNKNOWN,
142 "There is no such a network in this "
148 * wpas_dbus_error_invald_args - Return a new InvalidArgs error message
149 * @message: Pointer to incoming dbus message this error refers to
150 * Returns: a dbus error message
152 * Convenience function to create and return an invalid options error
154 DBusMessage * wpas_dbus_error_invald_args(DBusMessage *message,
159 reply = dbus_message_new_error(message, WPAS_DBUS_ERROR_INVALID_ARGS,
160 "Did not receive correct message "
163 dbus_message_append_args(reply, DBUS_TYPE_STRING, &arg,
170 static const char *dont_quote[] = {
171 "key_mgmt", "proto", "pairwise", "auth_alg", "group", "eap",
172 "opensc_engine_path", "pkcs11_engine_path", "pkcs11_module_path",
176 static dbus_bool_t should_quote_opt(const char *key)
179 while (dont_quote[i] != NULL) {
180 if (os_strcmp(key, dont_quote[i]) == 0)
187 static struct wpa_scan_res * find_scan_result(struct bss_handler_args *bss)
189 struct wpa_scan_results *results = bss->wpa_s->scan_res;
191 for (i = 0; results && i < results->num; i++) {
192 if (!os_memcmp(results->res[i]->bssid, bss->bssid, ETH_ALEN))
193 return results->res[i];
200 * get_iface_by_dbus_path - Get a new network interface
201 * @global: Pointer to global data from wpa_supplicant_init()
202 * @path: Pointer to a dbus object path representing an interface
203 * Returns: Pointer to the interface or %NULL if not found
205 static struct wpa_supplicant * get_iface_by_dbus_path(
206 struct wpa_global *global, const char *path)
208 struct wpa_supplicant *wpa_s;
210 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
211 if (os_strcmp(wpa_s->dbus_new_path, path) == 0)
219 * set_network_properties - Set properties of a configured network
220 * @message: Pointer to incoming dbus message
221 * @ssid: wpa_ssid structure for a configured network
222 * @iter: DBus message iterator containing dictionary of network
224 * Returns: NULL when succeed or DBus error on failure
226 * Sets network configuration with parameters given id DBus dictionary
228 static DBusMessage * set_network_properties(DBusMessage *message,
229 struct wpa_ssid *ssid,
230 DBusMessageIter *iter)
233 struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
234 DBusMessage *reply = NULL;
235 DBusMessageIter iter_dict;
237 if (!wpa_dbus_dict_open_read(iter, &iter_dict)) {
238 reply = wpas_dbus_error_invald_args(message, NULL);
242 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
246 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) {
247 reply = wpas_dbus_error_invald_args(message, NULL);
250 if (entry.type == DBUS_TYPE_ARRAY &&
251 entry.array_type == DBUS_TYPE_BYTE) {
252 if (entry.array_len <= 0)
255 size = entry.array_len * 2 + 1;
256 value = os_zalloc(size);
260 ret = wpa_snprintf_hex(value, size,
261 (u8 *) entry.bytearray_value,
266 if (entry.type == DBUS_TYPE_STRING) {
267 if (should_quote_opt(entry.key)) {
268 size = os_strlen(entry.str_value);
273 value = os_zalloc(size);
277 ret = os_snprintf(value, size,
281 (size_t) ret != (size - 1))
284 value = os_strdup(entry.str_value);
289 if (entry.type == DBUS_TYPE_UINT32) {
290 value = os_zalloc(size);
294 ret = os_snprintf(value, size, "%u",
299 if (entry.type == DBUS_TYPE_INT32) {
300 value = os_zalloc(size);
315 if (wpa_config_set(ssid, entry.key, value, 0) < 0)
318 if ((os_strcmp(entry.key, "psk") == 0 &&
319 value[0] == '"' && ssid->ssid_len) ||
320 (strcmp(entry.key, "ssid") == 0 && ssid->passphrase))
321 wpa_config_update_psk(ssid);
324 wpa_dbus_dict_entry_clear(&entry);
329 reply = wpas_dbus_error_invald_args(message, entry.key);
330 wpa_dbus_dict_entry_clear(&entry);
339 * wpas_dbus_handler_create_interface - Request registration of a network iface
340 * @message: Pointer to incoming dbus message
341 * @global: %wpa_supplicant global data structure
342 * Returns: The object path of the new interface object,
343 * or a dbus error message with more information
345 * Handler function for "CreateInterface" method call. Handles requests
346 * by dbus clients to register a network interface that wpa_supplicant
349 DBusMessage * wpas_dbus_handler_create_interface(DBusMessage *message,
350 struct wpa_global *global)
352 DBusMessageIter iter_dict;
353 DBusMessage *reply = NULL;
354 DBusMessageIter iter;
355 struct wpa_dbus_dict_entry entry;
358 char *bridge_ifname = NULL;
360 dbus_message_iter_init(message, &iter);
362 if (!wpa_dbus_dict_open_read(&iter, &iter_dict))
364 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
365 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
367 if (!strcmp(entry.key, "Driver") &&
368 (entry.type == DBUS_TYPE_STRING)) {
369 driver = os_strdup(entry.str_value);
370 wpa_dbus_dict_entry_clear(&entry);
373 } else if (!strcmp(entry.key, "Ifname") &&
374 (entry.type == DBUS_TYPE_STRING)) {
375 ifname = os_strdup(entry.str_value);
376 wpa_dbus_dict_entry_clear(&entry);
379 } else if (!strcmp(entry.key, "BridgeIfname") &&
380 (entry.type == DBUS_TYPE_STRING)) {
381 bridge_ifname = os_strdup(entry.str_value);
382 wpa_dbus_dict_entry_clear(&entry);
383 if (bridge_ifname == NULL)
386 wpa_dbus_dict_entry_clear(&entry);
392 goto error; /* Required Ifname argument missing */
395 * Try to get the wpa_supplicant record for this iface, return
396 * an error if we already control it.
398 if (wpa_supplicant_get_iface(global, ifname) != NULL) {
399 reply = dbus_message_new_error(message,
400 WPAS_DBUS_ERROR_IFACE_EXISTS,
401 "wpa_supplicant already "
402 "controls this interface.");
404 struct wpa_supplicant *wpa_s;
405 struct wpa_interface iface;
406 os_memset(&iface, 0, sizeof(iface));
407 iface.driver = driver;
408 iface.ifname = ifname;
409 iface.bridge_ifname = bridge_ifname;
410 /* Otherwise, have wpa_supplicant attach to it. */
411 if ((wpa_s = wpa_supplicant_add_iface(global, &iface))) {
412 const char *path = wpas_dbus_get_path(wpa_s);
413 reply = dbus_message_new_method_return(message);
414 dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH,
415 &path, DBUS_TYPE_INVALID);
417 reply = wpas_dbus_error_unknown_error(
418 message, "wpa_supplicant couldn't grab this "
426 os_free(bridge_ifname);
430 reply = wpas_dbus_error_invald_args(message, NULL);
436 * wpas_dbus_handler_remove_interface - Request deregistration of an interface
437 * @message: Pointer to incoming dbus message
438 * @global: wpa_supplicant global data structure
439 * Returns: a dbus message containing a UINT32 indicating success (1) or
440 * failure (0), or returns a dbus error message with more information
442 * Handler function for "removeInterface" method call. Handles requests
443 * by dbus clients to deregister a network interface that wpa_supplicant
446 DBusMessage * wpas_dbus_handler_remove_interface(DBusMessage *message,
447 struct wpa_global *global)
449 struct wpa_supplicant *wpa_s;
451 DBusMessage *reply = NULL;
453 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path,
456 wpa_s = get_iface_by_dbus_path(global, path);
458 reply = wpas_dbus_error_iface_unknown(message);
459 else if (wpa_supplicant_remove_iface(global, wpa_s)) {
460 reply = wpas_dbus_error_unknown_error(
461 message, "wpa_supplicant couldn't remove this "
470 * wpas_dbus_handler_get_interface - Get the object path for an interface name
471 * @message: Pointer to incoming dbus message
472 * @global: %wpa_supplicant global data structure
473 * Returns: The object path of the interface object,
474 * or a dbus error message with more information
476 * Handler function for "getInterface" method call.
478 DBusMessage * wpas_dbus_handler_get_interface(DBusMessage *message,
479 struct wpa_global *global)
481 DBusMessage *reply = NULL;
484 struct wpa_supplicant *wpa_s;
486 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &ifname,
489 wpa_s = wpa_supplicant_get_iface(global, ifname);
491 return wpas_dbus_error_iface_unknown(message);
493 path = wpas_dbus_get_path(wpa_s);
495 wpa_printf(MSG_ERROR, "wpas_dbus_handler_get_interface[dbus]: "
496 "interface has no dbus object path set");
497 return wpas_dbus_error_unknown_error(message, "path not set");
500 reply = dbus_message_new_method_return(message);
502 perror("wpas_dbus_handler_get_interface[dbus]: out of memory "
503 "when creating reply");
504 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
507 if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
508 DBUS_TYPE_INVALID)) {
509 perror("wpas_dbus_handler_get_interface[dbus]: out of memory "
510 "when appending argument to reply");
511 dbus_message_unref(reply);
512 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
521 * wpas_dbus_getter_debug_params - Get the debug params
522 * @message: Pointer to incoming dbus message
523 * @global: %wpa_supplicant global data structure
524 * Returns: DBus message with struct containing debug params.
526 * Getter for "DebugParams" property.
528 DBusMessage * wpas_dbus_getter_debug_params(DBusMessage *message,
529 struct wpa_global *global)
531 DBusMessage *reply = NULL;
532 DBusMessageIter iter, variant_iter, struct_iter;
535 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
537 reply = dbus_message_new_method_return(message);
539 perror("wpas_dbus_getter_network_properties[dbus] out of "
540 "memory when trying to initialize return message");
541 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
546 dbus_message_iter_init_append(reply, &iter);
548 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
549 "(ibb)", &variant_iter)) {
550 perror("wpas_dbus_getter_debug_params[dbus] out of memory "
551 "when trying to open variant");
552 dbus_message_unref(reply);
553 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
558 if (!dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_STRUCT,
559 NULL, &struct_iter)) {
560 perror("wpas_dbus_getter_debug_params[dbus] out of memory "
561 "when trying to open struct");
562 dbus_message_unref(reply);
563 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
568 if (!dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_INT32,
570 perror("wpas_dbus_getter_debug_params[dbus] out of memory "
571 "when trying to append value to struct");
572 dbus_message_unref(reply);
573 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
578 if (!dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_BOOLEAN,
579 &wpa_debug_timestamp)) {
580 perror("wpas_dbus_getter_debug_params[dbus] out of memory "
581 "when trying to append value to struct");
582 dbus_message_unref(reply);
583 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
588 if (!dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_BOOLEAN,
589 &wpa_debug_show_keys)) {
590 perror("wpas_dbus_getter_debug_params[dbus] out of memory "
591 "when trying to append value to struct");
592 dbus_message_unref(reply);
593 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
598 if (!dbus_message_iter_close_container(&variant_iter, &struct_iter)) {
599 perror("wpas_dbus_getter_debug_params[dbus] out of memory "
600 "when trying to close struct");
601 dbus_message_unref(reply);
602 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
607 if (!dbus_message_iter_close_container(&iter, &variant_iter)) {
608 perror("wpas_dbus_getter_debug_params[dbus] out of memory "
609 "when trying to close variant");
610 dbus_message_unref(reply);
611 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
622 * wpas_dbus_setter_debugparams - Set the debug params
623 * @message: Pointer to incoming dbus message
624 * @global: %wpa_supplicant global data structure
625 * Returns: NULL indicating success or a dbus error message with more
628 * Setter for "DebugParams" property.
630 DBusMessage * wpas_dbus_setter_debug_params(DBusMessage *message,
631 struct wpa_global *global)
633 DBusMessage *reply = NULL;
634 DBusMessageIter iter, variant_iter, struct_iter;
636 dbus_bool_t debug_timestamp;
637 dbus_bool_t debug_show_keys;
639 if (!dbus_message_iter_init(message, &iter)) {
640 perror("wpas_dbus_handler_add_blob[dbus] out of memory when "
641 "trying to initialize message iterator");
642 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
646 dbus_message_iter_next(&iter);
647 dbus_message_iter_next(&iter);
649 dbus_message_iter_recurse(&iter, &variant_iter);
651 if (dbus_message_iter_get_arg_type(&variant_iter) != DBUS_TYPE_STRUCT)
653 reply = wpas_dbus_error_invald_args(
654 message, "Argument must by a structure");
658 dbus_message_iter_recurse(&variant_iter, &struct_iter);
661 if (dbus_message_iter_get_arg_type(&struct_iter) != DBUS_TYPE_INT32) {
662 reply = wpas_dbus_error_invald_args(
663 message, "First struct argument must by an INT32");
667 dbus_message_iter_get_basic(&struct_iter, &debug_level);
668 if (!dbus_message_iter_next(&struct_iter)) {
669 reply = wpas_dbus_error_invald_args(
670 message, "Not enough elements in struct");
674 if (dbus_message_iter_get_arg_type(&struct_iter) != DBUS_TYPE_BOOLEAN)
676 reply = wpas_dbus_error_invald_args(
677 message, "Second struct argument must by a boolean");
680 dbus_message_iter_get_basic(&struct_iter, &debug_timestamp);
681 if (!dbus_message_iter_next(&struct_iter)) {
682 reply = wpas_dbus_error_invald_args(
683 message, "Not enough elements in struct");
687 if (dbus_message_iter_get_arg_type(&struct_iter) != DBUS_TYPE_BOOLEAN)
689 reply = wpas_dbus_error_invald_args(
690 message, "Third struct argument must by an boolean");
693 dbus_message_iter_get_basic(&struct_iter, &debug_show_keys);
695 if (wpa_supplicant_set_debug_params(global, debug_level,
696 debug_timestamp ? 1 : 0,
697 debug_show_keys ? 1 : 0)) {
698 reply = wpas_dbus_error_invald_args(
699 message, "Wrong debug level value");
709 * wpas_dbus_getter_interfaces - Request registered interfaces list
710 * @message: Pointer to incoming dbus message
711 * @global: %wpa_supplicant global data structure
712 * Returns: The object paths array containing registered interfaces
713 * objects paths or DBus error on failure
715 * Getter for "Interfaces" property. Handles requests
716 * by dbus clients to return list of registered interfaces objects
719 DBusMessage * wpas_dbus_getter_interfaces(DBusMessage *message,
720 struct wpa_global *global)
722 DBusMessage *reply = NULL;
723 DBusMessageIter iter, variant_iter, array_iter;
725 struct wpa_supplicant *wpa_s;
728 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
730 reply = dbus_message_new_method_return(message);
732 perror("wpas_dbus_getter_interfaces[dbus] out of memory "
733 "when trying to initialize return message");
734 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
739 dbus_message_iter_init_append(reply, &iter);
740 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
741 "ao", &variant_iter)) {
742 perror("wpas_dbus_getter_interfaces[dbus] out of memory "
743 "when trying to open variant");
744 dbus_message_unref(reply);
745 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
749 if (!dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
751 perror("wpas_dbus_getter_interfaces[dbus] out of memory "
752 "when trying to open array");
753 dbus_message_unref(reply);
754 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
759 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
760 path = wpas_dbus_get_path(wpa_s);
761 if (!dbus_message_iter_append_basic(&array_iter,
762 DBUS_TYPE_OBJECT_PATH,
764 perror("wpas_dbus_getter_interfaces[dbus] out of "
765 "memory when trying to append interface path");
766 dbus_message_unref(reply);
767 reply = dbus_message_new_error(message,
768 DBUS_ERROR_NO_MEMORY,
774 if (!dbus_message_iter_close_container(&variant_iter, &array_iter)) {
775 perror("wpas_dbus_getter_interfaces[dbus] out of memory "
776 "when trying to close array");
777 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
781 if (!dbus_message_iter_close_container(&iter, &variant_iter)) {
782 perror("wpas_dbus_getter_interfaces[dbus] out of memory "
783 "when trying to close variant");
784 dbus_message_unref(reply);
785 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
796 * wpas_dbus_getter_eap_methods - Request supported EAP methods list
797 * @message: Pointer to incoming dbus message
798 * @nothing: not used argument. may be NULL or anything else
799 * Returns: The object paths array containing supported EAP methods
800 * represented by strings or DBus error on failure
802 * Getter for "EapMethods" property. Handles requests
803 * by dbus clients to return list of strings with supported EAP methods
805 DBusMessage * wpas_dbus_getter_eap_methods(DBusMessage *message, void *nothing)
807 DBusMessage *reply = NULL;
808 DBusMessageIter iter, variant_iter, array_iter;
813 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
815 reply = dbus_message_new_method_return(message);
817 perror("wpas_dbus_getter_eap_methods[dbus] out of memory "
818 "when trying to initialize return message");
819 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
824 dbus_message_iter_init_append(reply, &iter);
825 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
826 "as", &variant_iter)) {
827 perror("wpas_dbus_getter_eap_methods[dbus] out of memory "
828 "when trying to open variant");
829 dbus_message_unref(reply);
830 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
835 if (!dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
837 perror("wpas_dbus_getter_eap_methods[dbus] out of memory "
838 "when trying to open variant");
839 dbus_message_unref(reply);
840 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
845 eap_methods = eap_get_names_as_string_array(&num_items);
849 for (i = 0; i < num_items; i++) {
850 if (!dbus_message_iter_append_basic(&array_iter,
854 os_free(eap_methods[i]);
856 os_free(eap_methods);
859 wpa_printf(MSG_ERROR, "wpas_dbus_getter_eap_methods"
860 "[dbus] out of memory when adding to "
862 dbus_message_unref(reply);
863 reply = dbus_message_new_error(message,
864 DBUS_ERROR_NO_MEMORY,
870 if (!dbus_message_iter_close_container(&variant_iter, &array_iter)) {
871 perror("wpas_dbus_getter_eap_methods[dbus] "
872 "out of memory when trying to close array");
873 dbus_message_unref(reply);
874 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
878 if (!dbus_message_iter_close_container(&iter, &variant_iter)) {
879 perror("wpas_dbus_getter_eap_methods[dbus] "
880 "out of memory when trying to close variant");
881 dbus_message_unref(reply);
882 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
892 static int wpas_dbus_get_scan_type(DBusMessage *message, DBusMessageIter *var,
893 char **type, DBusMessage **reply)
895 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_STRING) {
896 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
897 "Type must be a string");
898 *reply = wpas_dbus_error_invald_args(
899 message, "Wrong Type value type. String required");
902 dbus_message_iter_get_basic(var, type);
907 static int wpas_dbus_get_scan_ssids(DBusMessage *message, DBusMessageIter *var,
908 struct wpa_driver_scan_params *params,
911 struct wpa_driver_scan_ssid *ssids = params->ssids;
912 size_t ssids_num = 0;
914 DBusMessageIter array_iter, sub_array_iter;
918 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
919 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: ssids "
920 "must be an array of arrays of bytes");
921 *reply = wpas_dbus_error_invald_args(
922 message, "Wrong SSIDs value type. Array of arrays of "
927 dbus_message_iter_recurse(var, &array_iter);
929 if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY ||
930 dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_BYTE)
932 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: ssids "
933 "must be an array of arrays of bytes");
934 *reply = wpas_dbus_error_invald_args(
935 message, "Wrong SSIDs value type. Array of arrays of "
940 while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_ARRAY)
942 if (ssids_num >= WPAS_MAX_SCAN_SSIDS) {
943 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
944 "Too many ssids specified on scan dbus "
946 *reply = wpas_dbus_error_invald_args(
947 message, "Too many ssids specified. Specify "
952 dbus_message_iter_recurse(&array_iter, &sub_array_iter);
954 dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len);
956 dbus_message_iter_next(&array_iter);
960 ssid = os_malloc(len);
962 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
963 "out of memory. Cannot allocate memory for "
965 *reply = dbus_message_new_error(
966 message, DBUS_ERROR_NO_MEMORY, NULL);
969 os_memcpy(ssid, val, len);
970 ssids[ssids_num].ssid = ssid;
971 ssids[ssids_num].ssid_len = len;
973 dbus_message_iter_next(&array_iter);
977 params->num_ssids = ssids_num;
982 static int wpas_dbus_get_scan_ies(DBusMessage *message, DBusMessageIter *var,
983 struct wpa_driver_scan_params *params,
986 u8 *ies = NULL, *nies;
988 DBusMessageIter array_iter, sub_array_iter;
992 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
993 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: ies must "
994 "be an array of arrays of bytes");
995 *reply = wpas_dbus_error_invald_args(
996 message, "Wrong IEs value type. Array of arrays of "
1001 dbus_message_iter_recurse(var, &array_iter);
1003 if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY ||
1004 dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_BYTE)
1006 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: ies must "
1007 "be an array of arrays of bytes");
1008 *reply = wpas_dbus_error_invald_args(
1009 message, "Wrong IEs value type. Array required");
1013 while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_ARRAY)
1015 dbus_message_iter_recurse(&array_iter, &sub_array_iter);
1017 dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len);
1019 dbus_message_iter_next(&array_iter);
1023 nies = os_realloc(ies, ies_len + len);
1025 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1026 "out of memory. Cannot allocate memory for "
1029 *reply = dbus_message_new_error(
1030 message, DBUS_ERROR_NO_MEMORY, NULL);
1034 os_memcpy(ies + ies_len, val, len);
1037 dbus_message_iter_next(&array_iter);
1040 params->extra_ies = ies;
1041 params->extra_ies_len = ies_len;
1046 static int wpas_dbus_get_scan_channels(DBusMessage *message,
1047 DBusMessageIter *var,
1048 struct wpa_driver_scan_params *params,
1049 DBusMessage **reply)
1051 DBusMessageIter array_iter, sub_array_iter;
1052 int *freqs = NULL, *nfreqs;
1055 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
1056 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1057 "Channels must be an array of structs");
1058 *reply = wpas_dbus_error_invald_args(
1059 message, "Wrong Channels value type. Array of structs "
1064 dbus_message_iter_recurse(var, &array_iter);
1066 if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_STRUCT) {
1067 wpa_printf(MSG_DEBUG,
1068 "wpas_dbus_handler_scan[dbus]: Channels must be an "
1069 "array of structs");
1070 *reply = wpas_dbus_error_invald_args(
1071 message, "Wrong Channels value type. Array of structs "
1076 while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_STRUCT)
1080 dbus_message_iter_recurse(&array_iter, &sub_array_iter);
1082 if (dbus_message_iter_get_arg_type(&sub_array_iter) !=
1084 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1085 "Channel must by specified by struct of "
1087 dbus_message_iter_get_arg_type(
1089 *reply = wpas_dbus_error_invald_args(
1090 message, "Wrong Channel struct. Two UINT32s "
1095 dbus_message_iter_get_basic(&sub_array_iter, &freq);
1097 if (!dbus_message_iter_next(&sub_array_iter) ||
1098 dbus_message_iter_get_arg_type(&sub_array_iter) !=
1100 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1101 "Channel must by specified by struct of "
1103 *reply = wpas_dbus_error_invald_args(
1105 "Wrong Channel struct. Two UINT32s required");
1110 dbus_message_iter_get_basic(&sub_array_iter, &width);
1112 #define FREQS_ALLOC_CHUNK 32
1113 if (freqs_num % FREQS_ALLOC_CHUNK == 0) {
1114 nfreqs = os_realloc(freqs, sizeof(int) *
1115 (freqs_num + FREQS_ALLOC_CHUNK));
1120 if (freqs == NULL) {
1121 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1122 "out of memory. can't allocate memory for "
1124 *reply = dbus_message_new_error(
1125 message, DBUS_ERROR_NO_MEMORY, NULL);
1129 freqs[freqs_num] = freq;
1132 dbus_message_iter_next(&array_iter);
1135 nfreqs = os_realloc(freqs,
1136 sizeof(int) * (freqs_num + 1));
1140 if (freqs == NULL) {
1141 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1142 "out of memory. Can't allocate memory for freqs");
1143 *reply = dbus_message_new_error(
1144 message, DBUS_ERROR_NO_MEMORY, NULL);
1147 freqs[freqs_num] = 0;
1149 params->freqs = freqs;
1155 * wpas_dbus_handler_scan - Request a wireless scan on an interface
1156 * @message: Pointer to incoming dbus message
1157 * @wpa_s: wpa_supplicant structure for a network interface
1158 * Returns: NULL indicating success or DBus error message on failure
1160 * Handler function for "Scan" method call of a network device. Requests
1161 * that wpa_supplicant perform a wireless scan as soon as possible
1162 * on a particular wireless interface.
1164 DBusMessage * wpas_dbus_handler_scan(DBusMessage *message,
1165 struct wpa_supplicant *wpa_s)
1167 DBusMessage *reply = NULL;
1168 DBusMessageIter iter, dict_iter, entry_iter, variant_iter;
1169 char *key = NULL, *type = NULL;
1170 struct wpa_driver_scan_params params;
1173 os_memset(¶ms, 0, sizeof(params));
1175 dbus_message_iter_init(message, &iter);
1177 dbus_message_iter_recurse(&iter, &dict_iter);
1179 while (dbus_message_iter_get_arg_type(&dict_iter) ==
1180 DBUS_TYPE_DICT_ENTRY) {
1181 dbus_message_iter_recurse(&dict_iter, &entry_iter);
1182 dbus_message_iter_get_basic(&entry_iter, &key);
1183 dbus_message_iter_next(&entry_iter);
1184 dbus_message_iter_recurse(&entry_iter, &variant_iter);
1186 if (os_strcmp(key, "Type") == 0) {
1187 if (wpas_dbus_get_scan_type(message, &variant_iter,
1190 } else if (os_strcmp(key, "SSIDs") == 0) {
1191 if (wpas_dbus_get_scan_ssids(message, &variant_iter,
1192 ¶ms, &reply) < 0)
1194 } else if (os_strcmp(key, "IEs") == 0) {
1195 if (wpas_dbus_get_scan_ies(message, &variant_iter,
1196 ¶ms, &reply) < 0)
1198 } else if (os_strcmp(key, "Channels") == 0) {
1199 if (wpas_dbus_get_scan_channels(message, &variant_iter,
1200 ¶ms, &reply) < 0)
1203 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1204 "Unknown argument %s", key);
1205 reply = wpas_dbus_error_invald_args(message, key);
1209 dbus_message_iter_next(&dict_iter);
1213 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1214 "Scan type not specified");
1215 reply = wpas_dbus_error_invald_args(message, key);
1219 if (!os_strcmp(type, "passive")) {
1220 if (params.num_ssids || params.extra_ies_len) {
1221 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1222 "SSIDs or IEs specified for passive scan.");
1223 reply = wpas_dbus_error_invald_args(
1224 message, "You can specify only Channels in "
1227 } else if (params.freqs && params.freqs[0]) {
1230 wpa_supplicant_trigger_scan(wpa_s, ¶ms);
1232 wpa_s->scan_req = 2;
1233 wpa_supplicant_req_scan(wpa_s, 0, 0);
1235 } else if (!os_strcmp(type, "active")) {
1236 wpa_supplicant_trigger_scan(wpa_s, ¶ms);
1238 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1239 "Unknown scan type: %s", type);
1240 reply = wpas_dbus_error_invald_args(message,
1246 for (i = 0; i < WPAS_MAX_SCAN_SSIDS; i++)
1247 os_free((u8 *) params.ssids[i].ssid);
1248 os_free((u8 *) params.extra_ies);
1249 os_free(params.freqs);
1255 * wpas_dbus_handler_disconnect - Terminate the current connection
1256 * @message: Pointer to incoming dbus message
1257 * @wpa_s: wpa_supplicant structure for a network interface
1258 * Returns: NotConnected DBus error message if already not connected
1259 * or NULL otherwise.
1261 * Handler function for "Disconnect" method call of network interface.
1263 DBusMessage * wpas_dbus_handler_disconnect(DBusMessage *message,
1264 struct wpa_supplicant *wpa_s)
1266 if (wpa_s->current_ssid != NULL) {
1267 wpa_s->disconnected = 1;
1268 wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1273 return dbus_message_new_error(message, WPAS_DBUS_ERROR_NOT_CONNECTED,
1274 "This interface is not connected");
1279 * wpas_dbus_new_iface_add_network - Add a new configured network
1280 * @message: Pointer to incoming dbus message
1281 * @wpa_s: wpa_supplicant structure for a network interface
1282 * Returns: A dbus message containing the object path of the new network
1284 * Handler function for "AddNetwork" method call of a network interface.
1286 DBusMessage * wpas_dbus_handler_add_network(DBusMessage *message,
1287 struct wpa_supplicant *wpa_s)
1289 DBusMessage *reply = NULL;
1290 DBusMessageIter iter;
1291 struct wpa_ssid *ssid = NULL;
1294 path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1296 perror("wpas_dbus_handler_add_network[dbus]: out of "
1298 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1303 dbus_message_iter_init(message, &iter);
1305 ssid = wpa_config_add_network(wpa_s->conf);
1307 wpa_printf(MSG_ERROR, "wpas_dbus_handler_add_network[dbus]: "
1308 "can't add new interface.");
1309 reply = wpas_dbus_error_unknown_error(
1311 "wpa_supplicant could not add "
1312 "a network on this interface.");
1315 wpas_notify_network_added(wpa_s, ssid);
1317 wpa_config_set_network_defaults(ssid);
1319 reply = set_network_properties(message, ssid, &iter);
1321 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_add_network[dbus]:"
1322 "control interface couldn't set network "
1327 /* Construct the object path for this network. */
1328 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
1329 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
1330 wpas_dbus_get_path(wpa_s),
1333 reply = dbus_message_new_method_return(message);
1334 if (reply == NULL) {
1335 perror("wpas_dbus_handler_add_network[dbus]: out of memory "
1336 "when creating reply");
1337 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1341 if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
1342 DBUS_TYPE_INVALID)) {
1343 perror("wpas_dbus_handler_add_network[dbus]: out of memory "
1344 "when appending argument to reply");
1345 dbus_message_unref(reply);
1346 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1356 wpas_notify_network_removed(wpa_s, ssid);
1357 wpa_config_remove_network(wpa_s->conf, ssid->id);
1365 * wpas_dbus_handler_remove_network - Remove a configured network
1366 * @message: Pointer to incoming dbus message
1367 * @wpa_s: wpa_supplicant structure for a network interface
1368 * Returns: NULL on success or dbus error on failure
1370 * Handler function for "RemoveNetwork" method call of a network interface.
1372 DBusMessage * wpas_dbus_handler_remove_network(DBusMessage *message,
1373 struct wpa_supplicant *wpa_s)
1375 DBusMessage *reply = NULL;
1377 char *iface = NULL, *net_id = NULL;
1379 struct wpa_ssid *ssid;
1381 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
1384 /* Extract the network ID and ensure the network */
1385 /* is actually a child of this interface */
1386 iface = wpas_dbus_new_decompose_object_path(op, &net_id, NULL);
1387 if (iface == NULL || strcmp(iface, wpas_dbus_get_path(wpa_s)) != 0) {
1388 reply = wpas_dbus_error_invald_args(message, op);
1392 id = strtoul(net_id, NULL, 10);
1393 if (errno == EINVAL) {
1394 reply = wpas_dbus_error_invald_args(message, op);
1398 ssid = wpa_config_get_network(wpa_s->conf, id);
1400 reply = wpas_dbus_error_network_unknown(message);
1404 wpas_notify_network_removed(wpa_s, ssid);
1406 if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
1407 wpa_printf(MSG_ERROR,
1408 "wpas_dbus_handler_remove_network[dbus]: "
1409 "error occurred when removing network %d", id);
1410 reply = wpas_dbus_error_unknown_error(
1411 message, "error removing the specified network on "
1416 if (ssid == wpa_s->current_ssid)
1417 wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1427 * wpas_dbus_handler_select_network - Attempt association with a network
1428 * @message: Pointer to incoming dbus message
1429 * @wpa_s: wpa_supplicant structure for a network interface
1430 * Returns: NULL on success or dbus error on failure
1432 * Handler function for "SelectNetwork" method call of network interface.
1434 DBusMessage * wpas_dbus_handler_select_network(DBusMessage *message,
1435 struct wpa_supplicant *wpa_s)
1437 DBusMessage *reply = NULL;
1439 char *iface = NULL, *net_id = NULL;
1441 struct wpa_ssid *ssid;
1443 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
1446 /* Extract the network ID and ensure the network */
1447 /* is actually a child of this interface */
1448 iface = wpas_dbus_new_decompose_object_path(op, &net_id, NULL);
1449 if (iface == NULL || strcmp(iface, wpas_dbus_get_path(wpa_s)) != 0) {
1450 reply = wpas_dbus_error_invald_args(message, op);
1454 id = strtoul(net_id, NULL, 10);
1455 if (errno == EINVAL) {
1456 reply = wpas_dbus_error_invald_args(message, op);
1460 ssid = wpa_config_get_network(wpa_s->conf, id);
1462 reply = wpas_dbus_error_network_unknown(message);
1466 /* Finally, associate with the network */
1467 wpa_supplicant_select_network(wpa_s, ssid);
1477 * wpas_dbus_handler_add_blob - Store named binary blob (ie, for certificates)
1478 * @message: Pointer to incoming dbus message
1479 * @wpa_s: %wpa_supplicant data structure
1480 * Returns: A dbus message containing an error on failure or NULL on success
1482 * Asks wpa_supplicant to internally store a binary blobs.
1484 DBusMessage * wpas_dbus_handler_add_blob(DBusMessage *message,
1485 struct wpa_supplicant *wpa_s)
1487 DBusMessage *reply = NULL;
1488 DBusMessageIter iter, array_iter;
1493 struct wpa_config_blob *blob = NULL;
1495 dbus_message_iter_init(message, &iter);
1496 dbus_message_iter_get_basic(&iter, &blob_name);
1498 if (wpa_config_get_blob(wpa_s->conf, blob_name)) {
1499 return dbus_message_new_error(message,
1500 WPAS_DBUS_ERROR_BLOB_EXISTS,
1504 dbus_message_iter_next(&iter);
1505 dbus_message_iter_recurse(&iter, &array_iter);
1507 dbus_message_iter_get_fixed_array(&array_iter, &blob_data, &blob_len);
1509 blob = os_zalloc(sizeof(*blob));
1511 perror("wpas_dbus_handler_add_blob[dbus] out of memory when "
1512 "trying to allocate blob struct");
1513 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1518 blob->data = os_malloc(blob_len);
1520 perror("wpas_dbus_handler_add_blob[dbus] out of memory when "
1521 "trying to allocate blob data");
1522 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1526 os_memcpy(blob->data, blob_data, blob_len);
1528 blob->len = blob_len;
1529 blob->name = os_strdup(blob_name);
1531 perror("wpas_dbus_handler_add_blob[dbus] out of memory when "
1532 "trying to copy blob name");
1533 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1538 wpa_config_set_blob(wpa_s->conf, blob);
1539 wpas_notify_blob_added(wpa_s, blob->name);
1545 os_free(blob->name);
1546 os_free(blob->data);
1554 * wpas_dbus_handler_get_blob - Get named binary blob (ie, for certificates)
1555 * @message: Pointer to incoming dbus message
1556 * @wpa_s: %wpa_supplicant data structure
1557 * Returns: A dbus message containing array of bytes (blob)
1559 * Gets one wpa_supplicant's binary blobs.
1561 DBusMessage * wpas_dbus_handler_get_blob(DBusMessage *message,
1562 struct wpa_supplicant *wpa_s)
1564 DBusMessage *reply = NULL;
1565 DBusMessageIter iter, array_iter;
1568 const struct wpa_config_blob *blob;
1570 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &blob_name,
1573 blob = wpa_config_get_blob(wpa_s->conf, blob_name);
1575 return dbus_message_new_error(message,
1576 WPAS_DBUS_ERROR_BLOB_UNKNOWN,
1580 reply = dbus_message_new_method_return(message);
1582 perror("wpas_dbus_handler_get_blob[dbus] out of memory when "
1583 "trying to allocate return message");
1584 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1589 dbus_message_iter_init_append(reply, &iter);
1591 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
1592 DBUS_TYPE_BYTE_AS_STRING,
1594 dbus_message_unref(reply);
1595 perror("wpas_dbus_handler_get_blob[dbus] out of memory when "
1596 "trying to open array");
1597 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1602 if (!dbus_message_iter_append_fixed_array(&array_iter, DBUS_TYPE_BYTE,
1603 &(blob->data), blob->len)) {
1604 dbus_message_unref(reply);
1605 perror("wpas_dbus_handler_get_blob[dbus] out of memory when "
1606 "trying to append data to array");
1607 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1612 if (!dbus_message_iter_close_container(&iter, &array_iter)) {
1613 dbus_message_unref(reply);
1614 perror("wpas_dbus_handler_get_blob[dbus] out of memory when "
1615 "trying to close array");
1616 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1627 * wpas_remove_handler_remove_blob - Remove named binary blob
1628 * @message: Pointer to incoming dbus message
1629 * @wpa_s: %wpa_supplicant data structure
1630 * Returns: NULL on success or dbus error
1632 * Asks wpa_supplicant to internally remove a binary blobs.
1634 DBusMessage * wpas_dbus_handler_remove_blob(DBusMessage *message,
1635 struct wpa_supplicant *wpa_s)
1637 DBusMessage *reply = NULL;
1640 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &blob_name,
1643 if (wpa_config_remove_blob(wpa_s->conf, blob_name)) {
1644 return dbus_message_new_error(message,
1645 WPAS_DBUS_ERROR_BLOB_UNKNOWN,
1648 wpas_notify_blob_removed(wpa_s, blob_name);
1656 * wpas_dbus_getter_capabilities - Return interface capabilities
1657 * @message: Pointer to incoming dbus message
1658 * @wpa_s: wpa_supplicant structure for a network interface
1659 * Returns: A dbus message containing a dict of strings
1661 * Getter for "Capabilities" property of an interface.
1663 DBusMessage * wpas_dbus_getter_capabilities(DBusMessage *message,
1664 struct wpa_supplicant *wpa_s)
1666 DBusMessage *reply = NULL;
1667 struct wpa_driver_capa capa;
1669 DBusMessageIter iter, iter_dict;
1670 DBusMessageIter iter_dict_entry, iter_dict_val, iter_array,
1672 const char *scans[] = { "active", "passive", "ssid" };
1673 const char *modes[] = { "infrastructure", "ad-hoc", "ap" };
1674 int n = sizeof(modes) / sizeof(char *);
1676 if (message == NULL)
1677 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
1679 reply = dbus_message_new_method_return(message);
1683 dbus_message_iter_init_append(reply, &iter);
1684 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
1685 "a{sv}", &variant_iter))
1688 if (!wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
1691 res = wpa_drv_get_capa(wpa_s, &capa);
1693 /***** pairwise cipher */
1695 const char *args[] = {"ccmp", "tkip", "none"};
1696 if (!wpa_dbus_dict_append_string_array(
1697 &iter_dict, "Pairwise", args,
1698 sizeof(args) / sizeof(char*)))
1701 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Pairwise",
1707 if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
1708 if (!wpa_dbus_dict_string_array_add_element(
1709 &iter_array, "ccmp"))
1713 if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
1714 if (!wpa_dbus_dict_string_array_add_element(
1715 &iter_array, "tkip"))
1719 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
1720 if (!wpa_dbus_dict_string_array_add_element(
1721 &iter_array, "none"))
1725 if (!wpa_dbus_dict_end_string_array(&iter_dict,
1732 /***** group cipher */
1734 const char *args[] = {
1735 "ccmp", "tkip", "wep104", "wep40"
1737 if (!wpa_dbus_dict_append_string_array(
1738 &iter_dict, "Group", args,
1739 sizeof(args) / sizeof(char*)))
1742 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Group",
1748 if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
1749 if (!wpa_dbus_dict_string_array_add_element(
1750 &iter_array, "ccmp"))
1754 if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
1755 if (!wpa_dbus_dict_string_array_add_element(
1756 &iter_array, "tkip"))
1760 if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) {
1761 if (!wpa_dbus_dict_string_array_add_element(
1762 &iter_array, "wep104"))
1766 if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) {
1767 if (!wpa_dbus_dict_string_array_add_element(
1768 &iter_array, "wep40"))
1772 if (!wpa_dbus_dict_end_string_array(&iter_dict,
1779 /***** key management */
1781 const char *args[] = {
1782 "wpa-psk", "wpa-eap", "ieee8021x", "wpa-none",
1785 #endif /* CONFIG_WPS */
1788 if (!wpa_dbus_dict_append_string_array(
1789 &iter_dict, "KeyMgmt", args,
1790 sizeof(args) / sizeof(char*)))
1793 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "KeyMgmt",
1799 if (!wpa_dbus_dict_string_array_add_element(&iter_array,
1803 if (!wpa_dbus_dict_string_array_add_element(&iter_array,
1807 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
1808 WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
1809 if (!wpa_dbus_dict_string_array_add_element(
1810 &iter_array, "wpa-eap"))
1814 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
1815 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
1816 if (!wpa_dbus_dict_string_array_add_element(
1817 &iter_array, "wpa-psk"))
1821 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
1822 if (!wpa_dbus_dict_string_array_add_element(
1823 &iter_array, "wpa-none"))
1829 if (!wpa_dbus_dict_string_array_add_element(&iter_array,
1832 #endif /* CONFIG_WPS */
1834 if (!wpa_dbus_dict_end_string_array(&iter_dict,
1841 /***** WPA protocol */
1843 const char *args[] = { "rsn", "wpa" };
1844 if (!wpa_dbus_dict_append_string_array(
1845 &iter_dict, "Protocol", args,
1846 sizeof(args) / sizeof(char*)))
1849 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Protocol",
1855 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
1856 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
1857 if (!wpa_dbus_dict_string_array_add_element(
1858 &iter_array, "rsn"))
1862 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
1863 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
1864 if (!wpa_dbus_dict_string_array_add_element(
1865 &iter_array, "wpa"))
1869 if (!wpa_dbus_dict_end_string_array(&iter_dict,
1878 const char *args[] = { "open", "shared", "leap" };
1879 if (!wpa_dbus_dict_append_string_array(
1880 &iter_dict, "AuthAlg", args,
1881 sizeof(args) / sizeof(char*)))
1884 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "AuthAlg",
1890 if (capa.auth & (WPA_DRIVER_AUTH_OPEN)) {
1891 if (!wpa_dbus_dict_string_array_add_element(
1892 &iter_array, "open"))
1896 if (capa.auth & (WPA_DRIVER_AUTH_SHARED)) {
1897 if (!wpa_dbus_dict_string_array_add_element(
1898 &iter_array, "shared"))
1902 if (capa.auth & (WPA_DRIVER_AUTH_LEAP)) {
1903 if (!wpa_dbus_dict_string_array_add_element(
1904 &iter_array, "leap"))
1908 if (!wpa_dbus_dict_end_string_array(&iter_dict,
1916 if (!wpa_dbus_dict_append_string_array(&iter_dict, "Scan", scans,
1917 sizeof(scans) / sizeof(char *)))
1921 if (res < 0 || !(capa.flags & WPA_DRIVER_FLAGS_AP))
1922 n--; /* exclude ap mode if it is not supported by the driver */
1923 if (!wpa_dbus_dict_append_string_array(&iter_dict, "Modes", modes, n))
1926 if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict))
1928 if (!dbus_message_iter_close_container(&iter, &variant_iter))
1935 dbus_message_unref(reply);
1937 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, NULL);
1942 * wpas_dbus_getter_state - Get interface state
1943 * @message: Pointer to incoming dbus message
1944 * @wpa_s: wpa_supplicant structure for a network interface
1945 * Returns: A dbus message containing a STRING representing the current
1948 * Getter for "State" property.
1950 DBusMessage * wpas_dbus_getter_state(DBusMessage *message,
1951 struct wpa_supplicant *wpa_s)
1953 DBusMessage *reply = NULL;
1954 DBusMessageIter iter, variant_iter;
1955 const char *str_state;
1956 char *state_ls, *tmp;
1958 if (message == NULL)
1959 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
1961 reply = dbus_message_new_method_return(message);
1962 if (reply != NULL) {
1963 dbus_message_iter_init_append(reply, &iter);
1964 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
1965 "s", &variant_iter)) {
1966 perror("wpas_dbus_getter_state[dbus] out of memory "
1967 "when trying to open variant");
1968 dbus_message_unref(reply);
1969 reply = dbus_message_new_error(message,
1970 DBUS_ERROR_NO_MEMORY,
1975 str_state = wpa_supplicant_state_txt(wpa_s->wpa_state);
1977 /* make state string lowercase to fit new DBus API convention
1979 state_ls = tmp = os_strdup(str_state);
1981 perror("wpas_dbus_getter_state[dbus] out of memory "
1982 "when trying read state");
1983 dbus_message_unref(reply);
1984 reply = dbus_message_new_error(message,
1985 DBUS_ERROR_NO_MEMORY,
1990 *tmp = tolower(*tmp);
1994 if (!dbus_message_iter_append_basic(&variant_iter,
1997 perror("wpas_dbus_getter_state[dbus] out of memory "
1998 "when trying append state");
1999 dbus_message_unref(reply);
2000 reply = dbus_message_new_error(message,
2001 DBUS_ERROR_NO_MEMORY,
2005 if (!dbus_message_iter_close_container(&iter, &variant_iter)) {
2006 perror("wpas_dbus_getter_state[dbus] out of memory "
2007 "when trying close variant");
2008 dbus_message_unref(reply);
2009 reply = dbus_message_new_error(message,
2010 DBUS_ERROR_NO_MEMORY,
2023 * wpas_dbus_new_iface_get_scanning - Get interface scanning state
2024 * @message: Pointer to incoming dbus message
2025 * @wpa_s: wpa_supplicant structure for a network interface
2026 * Returns: A dbus message containing whether the interface is scanning
2028 * Getter for "scanning" property.
2030 DBusMessage * wpas_dbus_getter_scanning(DBusMessage *message,
2031 struct wpa_supplicant *wpa_s)
2033 DBusMessage *reply = NULL;
2034 DBusMessageIter iter, variant_iter;
2035 dbus_bool_t scanning = wpa_s->scanning ? TRUE : FALSE;
2037 if (message == NULL)
2038 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
2040 reply = dbus_message_new_method_return(message);
2042 if (reply != NULL) {
2043 dbus_message_iter_init_append(reply, &iter);
2044 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
2045 "b", &variant_iter) ||
2046 !dbus_message_iter_append_basic(&variant_iter,
2049 !dbus_message_iter_close_container(&iter, &variant_iter)) {
2050 perror("wpas_dbus_getter_scanning[dbus]: out of "
2051 "memory to put scanning state into message.");
2052 dbus_message_unref(reply);
2053 reply = dbus_message_new_error(message,
2054 DBUS_ERROR_NO_MEMORY,
2058 perror("wpas_dbus_getter_scanning[dbus]: out of "
2059 "memory to return scanning state.");
2060 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2069 * wpas_dbus_getter_ap_scan - Control roaming mode
2070 * @message: Pointer to incoming dbus message
2071 * @wpa_s: wpa_supplicant structure for a network interface
2072 * Returns: A message containong value of ap_scan variable
2074 * Getter function for "ApScan" property.
2076 DBusMessage * wpas_dbus_getter_ap_scan(DBusMessage *message,
2077 struct wpa_supplicant *wpa_s)
2079 DBusMessage *reply = NULL;
2080 DBusMessageIter iter, variant_iter;
2081 dbus_uint32_t ap_scan = wpa_s->conf->ap_scan;
2083 if (message == NULL)
2084 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
2086 reply = dbus_message_new_method_return(message);
2088 if (reply != NULL) {
2089 dbus_message_iter_init_append(reply, &iter);
2090 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
2091 "u", &variant_iter) ||
2092 !dbus_message_iter_append_basic(&variant_iter,
2095 !dbus_message_iter_close_container(&iter, &variant_iter)) {
2096 perror("wpas_dbus_getter_ap_scan[dbus]: out of "
2097 "memory to put scanning state into message.");
2098 dbus_message_unref(reply);
2099 reply = dbus_message_new_error(message,
2100 DBUS_ERROR_NO_MEMORY,
2104 perror("wpas_dbus_getter_ap_scan[dbus]: out of "
2105 "memory to return scanning state.");
2106 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2115 * wpas_dbus_setter_ap_scan - Control roaming mode
2116 * @message: Pointer to incoming dbus message
2117 * @wpa_s: wpa_supplicant structure for a network interface
2120 * Setter function for "ApScan" property.
2122 DBusMessage * wpas_dbus_setter_ap_scan(DBusMessage *message,
2123 struct wpa_supplicant *wpa_s)
2125 DBusMessage *reply = NULL;
2126 DBusMessageIter iter, variant_iter;
2127 dbus_uint32_t ap_scan;
2129 if (!dbus_message_iter_init(message, &iter)) {
2130 perror("wpas_dbus_getter_ap_scan[dbus]: out of "
2131 "memory to return scanning state.");
2132 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2137 /* omit first and second argument and get value from third*/
2138 dbus_message_iter_next(&iter);
2139 dbus_message_iter_next(&iter);
2140 dbus_message_iter_recurse(&iter, &variant_iter);
2142 if (dbus_message_iter_get_arg_type(&variant_iter) != DBUS_TYPE_UINT32)
2144 reply = wpas_dbus_error_invald_args(message,
2148 dbus_message_iter_get_basic(&variant_iter, &ap_scan);
2150 if (wpa_supplicant_set_ap_scan(wpa_s, ap_scan)) {
2151 reply = wpas_dbus_error_invald_args(
2153 "ap_scan must equal 0, 1 or 2");
2163 * wpas_dbus_getter_ifname - Get interface name
2164 * @message: Pointer to incoming dbus message
2165 * @wpa_s: wpa_supplicant structure for a network interface
2166 * Returns: A dbus message containing a name of network interface
2167 * associated with with wpa_s
2169 * Getter for "Ifname" property.
2171 DBusMessage * wpas_dbus_getter_ifname(DBusMessage *message,
2172 struct wpa_supplicant *wpa_s)
2174 DBusMessage *reply = NULL;
2175 DBusMessageIter iter, variant_iter;
2176 const char *ifname = NULL;
2178 ifname = wpa_s->ifname;
2179 if (ifname == NULL) {
2180 wpa_printf(MSG_DEBUG, "wpas_dbus_getter_ifname[dbus]: "
2181 "wpa_s has no interface name set"");");
2182 return wpas_dbus_error_unknown_error(message,
2186 if (message == NULL)
2187 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
2189 reply = dbus_message_new_method_return(message);
2191 if (reply != NULL) {
2192 dbus_message_iter_init_append(reply, &iter);
2193 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
2194 "s", &variant_iter) ||
2195 !dbus_message_iter_append_basic(&variant_iter,
2198 !dbus_message_iter_close_container(&iter, &variant_iter)) {
2199 perror("wpas_dbus_getter_ifname[dbus]: out of "
2200 "memory to put ifname into message.");
2201 dbus_message_unref(reply);
2202 reply = dbus_message_new_error(message,
2203 DBUS_ERROR_NO_MEMORY,
2207 perror("wpas_dbus_getter_ifname[dbus]: out of "
2208 "memory to return ifname state.");
2209 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2218 * wpas_dbus_getter_driver - Get interface name
2219 * @message: Pointer to incoming dbus message
2220 * @wpa_s: wpa_supplicant structure for a network interface
2221 * Returns: A dbus message containing a name of network interface
2222 * driver associated with with wpa_s
2224 * Getter for "Driver" property.
2226 DBusMessage * wpas_dbus_getter_driver(DBusMessage *message,
2227 struct wpa_supplicant *wpa_s)
2229 DBusMessage *reply = NULL;
2230 DBusMessageIter iter, variant_iter;
2231 const char *driver = NULL;
2233 if (wpa_s->driver == NULL || wpa_s->driver->name == NULL) {
2234 wpa_printf(MSG_DEBUG, "wpas_dbus_getter_driver[dbus]: "
2235 "wpa_s has no driver set"");");
2236 return wpas_dbus_error_unknown_error(message, NULL);
2239 driver = wpa_s->driver->name;
2241 if (message == NULL)
2242 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
2244 reply = dbus_message_new_method_return(message);
2246 if (reply != NULL) {
2247 dbus_message_iter_init_append(reply, &iter);
2248 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
2249 "s", &variant_iter) ||
2250 !dbus_message_iter_append_basic(&variant_iter,
2253 !dbus_message_iter_close_container(&iter, &variant_iter)) {
2254 perror("wpas_dbus_getter_driver[dbus]: out of "
2255 "memory to put driver into message.");
2256 dbus_message_unref(reply);
2257 reply = dbus_message_new_error(message,
2258 DBUS_ERROR_NO_MEMORY,
2262 perror("wpas_dbus_getter_driver[dbus]: out of "
2263 "memory to return driver.");
2264 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2273 * wpas_dbus_getter_current_bss - Get current bss object path
2274 * @message: Pointer to incoming dbus message
2275 * @wpa_s: wpa_supplicant structure for a network interface
2276 * Returns: A dbus message containing a DBus object path to
2279 * Getter for "CurrentBSS" property.
2281 DBusMessage * wpas_dbus_getter_current_bss(DBusMessage *message,
2282 struct wpa_supplicant *wpa_s)
2284 DBusMessage *reply = NULL;
2285 DBusMessageIter iter, variant_iter;
2286 const char *path = wpas_dbus_get_path(wpa_s);
2287 char *bss_obj_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
2288 int is_bssid_known = 0;
2290 if (bss_obj_path == NULL) {
2291 perror("wpas_dbus_getter_current_bss[dbus]: out of "
2292 "memory to allocate result argument.");
2293 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2297 if (!is_zero_ether_addr(wpa_s->bssid)) {
2299 for (i = 0; wpa_s->scan_res && i < wpa_s->scan_res->num; i++) {
2300 struct wpa_scan_res *res = wpa_s->scan_res->res[i];
2301 if (!os_memcmp(wpa_s->bssid, res->bssid, ETH_ALEN)) {
2309 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2310 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/"
2311 WPAS_DBUS_BSSID_FORMAT,
2312 path, MAC2STR(wpa_s->bssid));
2314 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
2316 if (message == NULL)
2317 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
2319 reply = dbus_message_new_method_return(message);
2321 if (reply != NULL) {
2322 dbus_message_iter_init_append(reply, &iter);
2323 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
2324 "o", &variant_iter) ||
2325 !dbus_message_iter_append_basic(&variant_iter,
2326 DBUS_TYPE_OBJECT_PATH,
2328 !dbus_message_iter_close_container(&iter, &variant_iter)) {
2329 perror("wpas_dbus_getter_current_bss[dbus]: out of "
2330 "memory to put path into message.");
2331 dbus_message_unref(reply);
2332 reply = dbus_message_new_error(message,
2333 DBUS_ERROR_NO_MEMORY,
2337 perror("wpas_dbus_getter_current_bss[dbus]: out of "
2338 "memory when creating reply.");
2339 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2343 os_free(bss_obj_path);
2349 * wpas_dbus_getter_current_network - Get current network object path
2350 * @message: Pointer to incoming dbus message
2351 * @wpa_s: wpa_supplicant structure for a network interface
2352 * Returns: A dbus message containing a DBus object path to
2355 * Getter for "CurrentNetwork" property.
2357 DBusMessage * wpas_dbus_getter_current_network(DBusMessage *message,
2358 struct wpa_supplicant *wpa_s)
2360 DBusMessage *reply = NULL;
2361 DBusMessageIter iter, variant_iter;
2362 const char *path = wpas_dbus_get_path(wpa_s);
2363 char *net_obj_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
2365 if (net_obj_path == NULL) {
2366 perror("wpas_dbus_getter_current_network[dbus]: out of "
2367 "memory to allocate result argument.");
2368 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2372 if (wpa_s->current_ssid)
2373 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2374 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u", path,
2375 wpa_s->current_ssid->id);
2377 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
2379 if (message == NULL)
2380 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
2382 reply = dbus_message_new_method_return(message);
2384 if (reply != NULL) {
2385 dbus_message_iter_init_append(reply, &iter);
2386 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
2387 "o", &variant_iter) ||
2388 !dbus_message_iter_append_basic(&variant_iter,
2389 DBUS_TYPE_OBJECT_PATH,
2391 !dbus_message_iter_close_container(&iter, &variant_iter)) {
2392 perror("wpas_dbus_getter_current_network[dbus]: out "
2393 "of memory to put path into message.");
2394 dbus_message_unref(reply);
2395 reply = dbus_message_new_error(message,
2396 DBUS_ERROR_NO_MEMORY,
2400 perror("wpas_dbus_getter_current_network[dbus]: out of "
2401 "memory when creating reply.");
2402 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2406 os_free(net_obj_path);
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 DBusMessage *reply = NULL;
2424 DBusMessageIter iter, variant_iter;
2425 const char *bridge_ifname = NULL;
2427 bridge_ifname = wpa_s->bridge_ifname;
2428 if (bridge_ifname == NULL) {
2429 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bridge_ifname[dbus]: "
2430 "wpa_s has no bridge interface name set"");");
2431 return wpas_dbus_error_unknown_error(message, NULL);
2434 if (message == NULL)
2435 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
2437 reply = dbus_message_new_method_return(message);
2439 if (reply != NULL) {
2440 dbus_message_iter_init_append(reply, &iter);
2441 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
2442 "s", &variant_iter) ||
2443 !dbus_message_iter_append_basic(&variant_iter,
2446 !dbus_message_iter_close_container(&iter, &variant_iter)) {
2447 perror("wpas_dbus_getter_bridge_ifname[dbus]: out of "
2448 "memory to put bridge ifname into message.");
2449 dbus_message_unref(reply);
2450 reply = dbus_message_new_error(message,
2451 DBUS_ERROR_NO_MEMORY,
2455 perror("wpas_dbus_getter_bridge_ifname[dbus]: out of "
2456 "memory to return bridge ifname.");
2457 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2466 * wpas_dbus_getter_bsss - Get array of BSSs objects
2467 * @message: Pointer to incoming dbus message
2468 * @wpa_s: wpa_supplicant structure for a network interface
2469 * Returns: a dbus message containing an array of all known BSS objects
2472 * Getter for "BSSs" property.
2474 DBusMessage * wpas_dbus_getter_bsss(DBusMessage *message,
2475 struct wpa_supplicant *wpa_s)
2477 DBusMessage *reply = NULL;
2478 DBusMessageIter iter, variant_iter, array_iter;
2481 /* Ensure we've actually got scan results to return */
2482 if (wpa_s->scan_res == NULL &&
2483 wpa_supplicant_get_scan_results(wpa_s) < 0) {
2484 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bsss[dbus]: "
2485 "An error occurred getting scan results.");
2486 return wpas_dbus_error_unknown_error(message, NULL);
2489 /* Create and initialize the return message */
2490 if (message == NULL)
2491 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
2493 reply = dbus_message_new_method_return(message);
2494 if (reply == NULL) {
2495 perror("wpas_dbus_getter_bsss[dbus]: out of "
2496 "memory to create return message.");
2497 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2502 dbus_message_iter_init_append(reply, &iter);
2504 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
2505 "ao", &variant_iter) ||
2506 !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
2507 DBUS_TYPE_OBJECT_PATH_AS_STRING,
2509 perror("wpas_dbus_getter_bsss[dbus]: out of "
2510 "memory to open container.");
2511 dbus_message_unref(reply);
2512 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2517 /* Loop through scan results and append each result's object path */
2518 for (i = 0; i < wpa_s->scan_res->num; i++) {
2519 struct wpa_scan_res *res = wpa_s->scan_res->res[i];
2522 path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
2524 perror("wpas_dbus_getter_bsss[dbus]: out of "
2526 dbus_message_unref(reply);
2527 reply = dbus_message_new_error(message,
2528 DBUS_ERROR_NO_MEMORY,
2532 /* Construct the object path for this BSS. Note that ':'
2533 * is not a valid character in dbus object paths.
2535 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
2536 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/"
2537 WPAS_DBUS_BSSID_FORMAT,
2538 wpas_dbus_get_path(wpa_s),
2539 MAC2STR(res->bssid));
2540 dbus_message_iter_append_basic(&array_iter,
2541 DBUS_TYPE_OBJECT_PATH, &path);
2545 if (!dbus_message_iter_close_container(&variant_iter, &array_iter) ||
2546 !dbus_message_iter_close_container(&iter, &variant_iter)) {
2547 perror("wpas_dbus_getter_bsss[dbus]: out of "
2548 "memory to close container.");
2549 dbus_message_unref(reply);
2550 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2561 * wpas_dbus_getter_networks - Get array of networks objects
2562 * @message: Pointer to incoming dbus message
2563 * @wpa_s: wpa_supplicant structure for a network interface
2564 * Returns: a dbus message containing an array of all configured
2565 * networks dbus object paths.
2567 * Getter for "Networks" property.
2569 DBusMessage * wpas_dbus_getter_networks(DBusMessage *message,
2570 struct wpa_supplicant *wpa_s)
2572 DBusMessage *reply = NULL;
2573 DBusMessageIter iter, variant_iter, array_iter;
2574 struct wpa_ssid *ssid;
2576 if (wpa_s->conf == NULL) {
2577 wpa_printf(MSG_ERROR, "wpas_dbus_getter_networks[dbus]: "
2578 "An error occurred getting networks list.");
2579 return wpas_dbus_error_unknown_error(message, NULL);
2582 /* Create and initialize the return message */
2583 if (message == NULL)
2584 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
2586 reply = dbus_message_new_method_return(message);
2587 if (reply == NULL) {
2588 perror("wpas_dbus_getter_networks[dbus]: out of "
2589 "memory to create return message.");
2590 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2595 dbus_message_iter_init_append(reply, &iter);
2597 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
2598 "ao", &variant_iter) ||
2599 !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
2600 DBUS_TYPE_OBJECT_PATH_AS_STRING,
2602 perror("wpas_dbus_getter_networks[dbus]: out of "
2603 "memory to open container.");
2604 dbus_message_unref(reply);
2605 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2610 /* Loop through configured networks and append object path if each */
2611 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2614 path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
2616 perror("wpas_dbus_getter_networks[dbus]: out of "
2618 dbus_message_unref(reply);
2619 reply = dbus_message_new_error(message,
2620 DBUS_ERROR_NO_MEMORY,
2625 /* Construct the object path for this network. */
2626 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
2627 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
2628 wpas_dbus_get_path(wpa_s), ssid->id);
2629 dbus_message_iter_append_basic(&array_iter,
2630 DBUS_TYPE_OBJECT_PATH, &path);
2634 if (!dbus_message_iter_close_container(&variant_iter, &array_iter) ||
2635 !dbus_message_iter_close_container(&iter, &variant_iter)) {
2636 perror("wpas_dbus_getter_networks[dbus]: out of "
2637 "memory to close container.");
2638 dbus_message_unref(reply);
2639 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2650 * wpas_dbus_getter_blobs - Get all blobs defined for this interface
2651 * @message: Pointer to incoming dbus message
2652 * @wpa_s: wpa_supplicant structure for a network interface
2653 * Returns: a dbus message containing a dictionary of pairs (blob_name, blob)
2655 * Getter for "Blobs" property.
2657 DBusMessage * wpas_dbus_getter_blobs(DBusMessage *message,
2658 struct wpa_supplicant *wpa_s)
2660 DBusMessage *reply = NULL;
2661 DBusMessageIter iter, variant_iter, dict_iter, entry_iter, array_iter;
2662 struct wpa_config_blob *blob;
2664 if (message == NULL)
2665 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
2667 reply = dbus_message_new_method_return(message);
2669 perror("wpas_dbus_getter_blobs[dbus] out of memory when "
2670 "trying to initialize return message");
2671 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2676 dbus_message_iter_init_append(reply, &iter);
2678 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
2679 "a{say}", &variant_iter)) {
2680 dbus_message_unref(reply);
2681 perror("wpas_dbus_getter_blobs[dbus] out of memory when "
2682 "trying to open variant");
2683 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2688 if (!dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
2689 "{say}", &dict_iter)) {
2690 dbus_message_unref(reply);
2691 perror("wpas_dbus_getter_blobs[dbus] out of memory when "
2692 "trying to open dictionary");
2693 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2698 blob = wpa_s->conf->blobs;
2700 if (!dbus_message_iter_open_container(&dict_iter,
2701 DBUS_TYPE_DICT_ENTRY,
2702 NULL, &entry_iter)) {
2703 dbus_message_unref(reply);
2704 perror("wpas_dbus_getter_blobs[dbus] out of memory "
2705 "when trying to open entry");
2706 reply = dbus_message_new_error(message,
2707 DBUS_ERROR_NO_MEMORY,
2712 if (!dbus_message_iter_append_basic(&entry_iter,
2715 dbus_message_unref(reply);
2716 perror("wpas_dbus_getter_blobs[dbus] out of memory "
2717 "when trying to append blob name");
2718 reply = dbus_message_new_error(message,
2719 DBUS_ERROR_NO_MEMORY,
2724 if (!dbus_message_iter_open_container(&entry_iter,
2726 DBUS_TYPE_BYTE_AS_STRING,
2728 dbus_message_unref(reply);
2729 perror("wpas_dbus_getter_blobs[dbus] out of memory "
2730 "when trying to open array");
2731 reply = dbus_message_new_error(message,
2732 DBUS_ERROR_NO_MEMORY,
2737 if (!dbus_message_iter_append_fixed_array(&array_iter,
2741 dbus_message_unref(reply);
2742 perror("wpas_dbus_getter_blobs[dbus] out of memory "
2743 "when trying to append blob data");
2744 reply = dbus_message_new_error(message,
2745 DBUS_ERROR_NO_MEMORY,
2750 if (!dbus_message_iter_close_container(&entry_iter,
2752 dbus_message_unref(reply);
2753 perror("wpas_dbus_getter_blobs[dbus] out of memory "
2754 "when trying to close array");
2755 reply = dbus_message_new_error(message,
2756 DBUS_ERROR_NO_MEMORY,
2761 if (!dbus_message_iter_close_container(&dict_iter,
2763 dbus_message_unref(reply);
2764 perror("wpas_dbus_getter_blobs[dbus] out of memory "
2765 "when trying to close entry");
2766 reply = dbus_message_new_error(message,
2767 DBUS_ERROR_NO_MEMORY,
2775 if (!dbus_message_iter_close_container(&variant_iter, &dict_iter)) {
2776 dbus_message_unref(reply);
2777 perror("wpas_dbus_getter_blobs[dbus] out of memory when "
2778 "trying to close dictionary");
2779 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2784 if (!dbus_message_iter_close_container(&iter, &variant_iter)) {
2785 dbus_message_unref(reply);
2786 perror("wpas_dbus_getter_blobs[dbus] out of memory when "
2787 "trying to close variant");
2788 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2799 * wpas_dbus_getter_bss_properties - Return the properties of a scanned bss
2800 * @message: Pointer to incoming dbus message
2801 * @bss: a pair of interface describing structure and bss' bssid
2802 * Returns: a dbus message containing the properties for the requested bss
2804 * Getter for "Properties" property.
2806 DBusMessage * wpas_dbus_getter_bss_properties(DBusMessage *message,
2807 struct bss_handler_args *bss)
2809 DBusMessage *reply = NULL;
2810 DBusMessageIter iter, iter_dict, variant_iter;
2812 struct wpa_scan_res *res = find_scan_result(bss);
2817 /* Dump the properties into a dbus message */
2818 if (message == NULL)
2819 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
2821 reply = dbus_message_new_method_return(message);
2826 dbus_message_iter_init_append(reply, &iter);
2828 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
2829 "a{sv}", &variant_iter))
2832 if (!wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
2835 if (!wpa_dbus_dict_append_byte_array(&iter_dict, "BSSID",
2836 (const char *) res->bssid,
2840 ie = wpa_scan_get_ie(res, WLAN_EID_SSID);
2842 if (!wpa_dbus_dict_append_byte_array(&iter_dict, "SSID",
2843 (const char *) (ie + 2),
2848 ie = wpa_scan_get_vendor_ie(res, WPA_IE_VENDOR_TYPE);
2850 if (!wpa_dbus_dict_append_byte_array(&iter_dict, "WPAIE",
2856 ie = wpa_scan_get_ie(res, WLAN_EID_RSN);
2858 if (!wpa_dbus_dict_append_byte_array(&iter_dict, "RSNIE",
2864 ie = wpa_scan_get_vendor_ie(res, WPS_IE_VENDOR_TYPE);
2866 if (!wpa_dbus_dict_append_byte_array(&iter_dict, "WPSIE",
2873 if (!wpa_dbus_dict_append_int32(&iter_dict, "Frequency",
2877 if (!wpa_dbus_dict_append_uint16(&iter_dict, "Capabilities",
2880 if (!(res->flags & WPA_SCAN_QUAL_INVALID) &&
2881 !wpa_dbus_dict_append_int32(&iter_dict, "Quality", res->qual))
2883 if (!(res->flags & WPA_SCAN_NOISE_INVALID) &&
2884 !wpa_dbus_dict_append_int32(&iter_dict, "Noise", res->noise))
2886 if (!(res->flags & WPA_SCAN_LEVEL_INVALID) &&
2887 !wpa_dbus_dict_append_int32(&iter_dict, "Level", res->level))
2889 if (!wpa_dbus_dict_append_int32(&iter_dict, "MaxRate",
2890 wpa_scan_get_max_rate(res) * 500000))
2893 if (!wpa_dbus_dict_close_write(&iter, &iter_dict))
2900 dbus_message_unref(reply);
2901 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, NULL);
2906 * wpas_dbus_getter_enabled - Check whether network is enabled or disabled
2907 * @message: Pointer to incoming dbus message
2908 * @wpas_dbus_setter_enabled: wpa_supplicant structure for a network interface
2909 * and wpa_ssid structure for a configured network
2910 * Returns: DBus message with boolean indicating state of configured network
2911 * or DBus error on failure
2913 * Getter for "enabled" property of a configured network.
2915 DBusMessage * wpas_dbus_getter_enabled(DBusMessage *message,
2916 struct network_handler_args *net)
2918 DBusMessage *reply = NULL;
2919 DBusMessageIter iter, variant_iter;
2921 dbus_bool_t enabled = net->ssid->disabled ? FALSE : TRUE;
2923 if (message == NULL)
2924 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
2926 reply = dbus_message_new_method_return(message);
2928 perror("wpas_dbus_getter_enabled[dbus] out of memory when "
2929 "trying to initialize return message");
2930 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2935 dbus_message_iter_init_append(reply, &iter);
2937 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
2938 "b", &variant_iter)) {
2939 dbus_message_unref(reply);
2940 perror("wpas_dbus_getter_enabled[dbus] out of memory when "
2941 "trying to open variant");
2942 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2947 if (!dbus_message_iter_append_basic(&variant_iter,
2948 DBUS_TYPE_BOOLEAN, &enabled)) {
2949 dbus_message_unref(reply);
2950 perror("wpas_dbus_getter_enabled[dbus] out of memory when "
2951 "trying to append value");
2952 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2957 if (!dbus_message_iter_close_container(&iter, &variant_iter)) {
2958 dbus_message_unref(reply);
2959 perror("wpas_dbus_getter_blobs[dbus] out of memory when "
2960 "trying to close variant");
2961 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2972 * wpas_dbus_setter_enabled - Mark a configured network as enabled or disabled
2973 * @message: Pointer to incoming dbus message
2974 * @wpas_dbus_setter_enabled: wpa_supplicant structure for a network interface
2975 * and wpa_ssid structure for a configured network
2976 * Returns: NULL indicating success or DBus error on failure
2978 * Setter for "Enabled" property of a configured network.
2980 DBusMessage * wpas_dbus_setter_enabled(DBusMessage *message,
2981 struct network_handler_args *net)
2983 DBusMessage *reply = NULL;
2984 DBusMessageIter iter, variant_iter;
2986 struct wpa_supplicant *wpa_s;
2987 struct wpa_ssid *ssid;
2991 if (!dbus_message_iter_init(message, &iter)) {
2992 perror("wpas_dbus_setter_enabled[dbus] out of memory when "
2993 "trying to init iterator");
2994 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2999 dbus_message_iter_next(&iter);
3000 dbus_message_iter_next(&iter);
3002 dbus_message_iter_recurse(&iter, &variant_iter);
3003 if (dbus_message_iter_get_arg_type(&variant_iter) !=
3004 DBUS_TYPE_BOOLEAN) {
3005 perror("wpas_dbus_setter_enabled[dbus] "
3006 "variant content should be boolean");
3007 reply = dbus_message_new_error(message,
3008 DBUS_ERROR_INVALID_ARGS,
3009 "value should be a boolean");
3012 dbus_message_iter_get_basic(&variant_iter, &enable);
3018 wpa_supplicant_enable_network(wpa_s, ssid);
3020 wpa_supplicant_disable_network(wpa_s, ssid);
3028 * wpas_dbus_getter_network_properties - Get options for a configured network
3029 * @message: Pointer to incoming dbus message
3030 * @net: wpa_supplicant structure for a network interface and
3031 * wpa_ssid structure for a configured network
3032 * Returns: DBus message with network properties or DBus error on failure
3034 * Getter for "Properties" property of a configured network.
3036 DBusMessage * wpas_dbus_getter_network_properties(
3037 DBusMessage *message, struct network_handler_args *net)
3039 DBusMessage *reply = NULL;
3040 DBusMessageIter iter, variant_iter, dict_iter;
3042 char **props = wpa_config_get_all(net->ssid, 0);
3044 perror("wpas_dbus_getter_network_properties[dbus] couldn't "
3045 "read network properties. out of memory.");
3046 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
3050 if (message == NULL)
3051 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
3053 reply = dbus_message_new_method_return(message);
3055 perror("wpas_dbus_getter_network_properties[dbus] out of "
3056 "memory when trying to initialize return message");
3057 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
3062 dbus_message_iter_init_append(reply, &iter);
3064 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
3065 "a{sv}", &variant_iter)) {
3066 perror("wpas_dbus_getter_network_properties[dbus] out of "
3067 "memory when trying to open variant container");
3068 dbus_message_unref(reply);
3069 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
3074 if (!wpa_dbus_dict_open_write(&variant_iter, &dict_iter)) {
3075 perror("wpas_dbus_getter_network_properties[dbus] out of "
3076 "memory when trying to open dict");
3077 dbus_message_unref(reply);
3078 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
3085 if (!wpa_dbus_dict_append_string(&dict_iter, *iterator,
3087 perror("wpas_dbus_getter_network_properties[dbus] out "
3088 "of memory when trying to add entry");
3089 dbus_message_unref(reply);
3090 reply = dbus_message_new_error(message,
3091 DBUS_ERROR_NO_MEMORY,
3099 if (!wpa_dbus_dict_close_write(&variant_iter, &dict_iter)) {
3100 perror("wpas_dbus_getter_network_properties[dbus] out of "
3101 "memory when trying to close dictionary");
3102 dbus_message_unref(reply);
3103 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
3108 if (!dbus_message_iter_close_container(&iter, &variant_iter)) {
3109 perror("wpas_dbus_getter_network_properties[dbus] out of "
3110 "memory when trying to close variant container");
3111 dbus_message_unref(reply);
3112 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
3129 * wpas_dbus_setter_network_properties - Set options for a configured network
3130 * @message: Pointer to incoming dbus message
3131 * @net: wpa_supplicant structure for a network interface and
3132 * wpa_ssid structure for a configured network
3133 * Returns: NULL indicating success or DBus error on failure
3135 * Setter for "Properties" property of a configured network.
3137 DBusMessage * wpas_dbus_setter_network_properties(
3138 DBusMessage *message, struct network_handler_args *net)
3140 struct wpa_ssid *ssid = net->ssid;
3142 DBusMessage *reply = NULL;
3143 DBusMessageIter iter, variant_iter;
3145 dbus_message_iter_init(message, &iter);
3147 dbus_message_iter_next(&iter);
3148 dbus_message_iter_next(&iter);
3150 dbus_message_iter_recurse(&iter, &variant_iter);
3152 reply = set_network_properties(message, ssid, &variant_iter);
3154 wpa_printf(MSG_DEBUG, "dbus control interface couldn't set "
3155 "network properties");