2 * WPA Supplicant / dbus-based control interface
3 * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
10 #include <dbus/dbus.h>
13 #include "eap_peer/eap_methods.h"
14 #include "common/ieee802_11_defs.h"
15 #include "eapol_supp/eapol_supp_sm.h"
16 #include "rsn_supp/wpa.h"
17 #include "../config.h"
18 #include "../wpa_supplicant_i.h"
19 #include "../driver_i.h"
20 #include "../notify.h"
21 #include "../wpas_glue.h"
25 #include "dbus_old_handlers.h"
26 #include "dbus_dict_helpers.h"
28 extern int wpa_debug_level
;
29 extern int wpa_debug_show_keys
;
30 extern int wpa_debug_timestamp
;
33 * wpas_dbus_new_invalid_opts_error - Return a new invalid options error message
34 * @message: Pointer to incoming dbus message this error refers to
35 * Returns: a dbus error message
37 * Convenience function to create and return an invalid options error
39 DBusMessage
* wpas_dbus_new_invalid_opts_error(DBusMessage
*message
,
44 reply
= dbus_message_new_error(message
, WPAS_ERROR_INVALID_OPTS
,
45 "Did not receive correct message "
48 dbus_message_append_args(reply
, DBUS_TYPE_STRING
, &arg
,
56 * wpas_dbus_new_success_reply - Return a new success reply message
57 * @message: Pointer to incoming dbus message this reply refers to
58 * Returns: a dbus message containing a single UINT32 that indicates
59 * success (ie, a value of 1)
61 * Convenience function to create and return a success reply message
63 DBusMessage
* wpas_dbus_new_success_reply(DBusMessage
*message
)
66 unsigned int success
= 1;
68 reply
= dbus_message_new_method_return(message
);
69 dbus_message_append_args(reply
, DBUS_TYPE_UINT32
, &success
,
76 * wpas_dbus_global_add_interface - Request registration of a network interface
77 * @message: Pointer to incoming dbus message
78 * @global: %wpa_supplicant global data structure
79 * Returns: The object path of the new interface object,
80 * or a dbus error message with more information
82 * Handler function for "addInterface" method call. Handles requests
83 * by dbus clients to register a network interface that wpa_supplicant
86 DBusMessage
* wpas_dbus_global_add_interface(DBusMessage
*message
,
87 struct wpa_global
*global
)
91 char *driver_param
= NULL
;
92 char *confname
= NULL
;
93 char *bridge_ifname
= NULL
;
94 DBusMessage
*reply
= NULL
;
97 dbus_message_iter_init(message
, &iter
);
99 /* First argument: interface name (DBUS_TYPE_STRING)
100 * Required; must be non-zero length
102 if (dbus_message_iter_get_arg_type(&iter
) != DBUS_TYPE_STRING
)
104 dbus_message_iter_get_basic(&iter
, &ifname
);
105 if (!os_strlen(ifname
))
108 /* Second argument: dict of options */
109 if (dbus_message_iter_next(&iter
)) {
110 DBusMessageIter iter_dict
;
111 struct wpa_dbus_dict_entry entry
;
113 if (!wpa_dbus_dict_open_read(&iter
, &iter_dict
, NULL
))
115 while (wpa_dbus_dict_has_dict_entry(&iter_dict
)) {
116 if (!wpa_dbus_dict_get_entry(&iter_dict
, &entry
))
118 if (!strcmp(entry
.key
, "driver") &&
119 (entry
.type
== DBUS_TYPE_STRING
)) {
120 driver
= os_strdup(entry
.str_value
);
121 wpa_dbus_dict_entry_clear(&entry
);
124 } else if (!strcmp(entry
.key
, "driver-params") &&
125 (entry
.type
== DBUS_TYPE_STRING
)) {
126 driver_param
= os_strdup(entry
.str_value
);
127 wpa_dbus_dict_entry_clear(&entry
);
128 if (driver_param
== NULL
)
130 } else if (!strcmp(entry
.key
, "config-file") &&
131 (entry
.type
== DBUS_TYPE_STRING
)) {
132 confname
= os_strdup(entry
.str_value
);
133 wpa_dbus_dict_entry_clear(&entry
);
134 if (confname
== NULL
)
136 } else if (!strcmp(entry
.key
, "bridge-ifname") &&
137 (entry
.type
== DBUS_TYPE_STRING
)) {
138 bridge_ifname
= os_strdup(entry
.str_value
);
139 wpa_dbus_dict_entry_clear(&entry
);
140 if (bridge_ifname
== NULL
)
143 wpa_dbus_dict_entry_clear(&entry
);
150 * Try to get the wpa_supplicant record for this iface, return
151 * an error if we already control it.
153 if (wpa_supplicant_get_iface(global
, ifname
) != NULL
) {
154 reply
= dbus_message_new_error(message
,
155 WPAS_ERROR_EXISTS_ERROR
,
156 "wpa_supplicant already "
157 "controls this interface.");
159 struct wpa_supplicant
*wpa_s
;
160 struct wpa_interface iface
;
161 os_memset(&iface
, 0, sizeof(iface
));
162 iface
.ifname
= ifname
;
163 iface
.driver
= driver
;
164 iface
.driver_param
= driver_param
;
165 iface
.confname
= confname
;
166 iface
.bridge_ifname
= bridge_ifname
;
167 /* Otherwise, have wpa_supplicant attach to it. */
168 if ((wpa_s
= wpa_supplicant_add_iface(global
, &iface
))) {
169 const char *path
= wpa_s
->dbus_path
;
170 reply
= dbus_message_new_method_return(message
);
171 dbus_message_append_args(reply
, DBUS_TYPE_OBJECT_PATH
,
172 &path
, DBUS_TYPE_INVALID
);
174 reply
= dbus_message_new_error(message
,
175 WPAS_ERROR_ADD_ERROR
,
177 "couldn't grab this "
184 os_free(driver_param
);
186 os_free(bridge_ifname
);
190 reply
= wpas_dbus_new_invalid_opts_error(message
, NULL
);
196 * wpas_dbus_global_remove_interface - Request deregistration of an interface
197 * @message: Pointer to incoming dbus message
198 * @global: wpa_supplicant global data structure
199 * Returns: a dbus message containing a UINT32 indicating success (1) or
200 * failure (0), or returns a dbus error message with more information
202 * Handler function for "removeInterface" method call. Handles requests
203 * by dbus clients to deregister a network interface that wpa_supplicant
206 DBusMessage
* wpas_dbus_global_remove_interface(DBusMessage
*message
,
207 struct wpa_global
*global
)
209 struct wpa_supplicant
*wpa_s
;
211 DBusMessage
*reply
= NULL
;
213 if (!dbus_message_get_args(message
, NULL
,
214 DBUS_TYPE_OBJECT_PATH
, &path
,
215 DBUS_TYPE_INVALID
)) {
216 reply
= wpas_dbus_new_invalid_opts_error(message
, NULL
);
220 wpa_s
= wpa_supplicant_get_iface_by_dbus_path(global
, path
);
222 reply
= wpas_dbus_new_invalid_iface_error(message
);
226 if (!wpa_supplicant_remove_iface(global
, wpa_s
, 0)) {
227 reply
= wpas_dbus_new_success_reply(message
);
229 reply
= dbus_message_new_error(message
,
230 WPAS_ERROR_REMOVE_ERROR
,
231 "wpa_supplicant couldn't "
232 "remove this interface.");
241 * wpas_dbus_global_get_interface - Get the object path for an interface name
242 * @message: Pointer to incoming dbus message
243 * @global: %wpa_supplicant global data structure
244 * Returns: The object path of the interface object,
245 * or a dbus error message with more information
247 * Handler function for "getInterface" method call. Handles requests
248 * by dbus clients for the object path of an specific network interface.
250 DBusMessage
* wpas_dbus_global_get_interface(DBusMessage
*message
,
251 struct wpa_global
*global
)
253 DBusMessage
*reply
= NULL
;
256 struct wpa_supplicant
*wpa_s
;
258 if (!dbus_message_get_args(message
, NULL
,
259 DBUS_TYPE_STRING
, &ifname
,
260 DBUS_TYPE_INVALID
)) {
261 reply
= wpas_dbus_new_invalid_opts_error(message
, NULL
);
265 wpa_s
= wpa_supplicant_get_iface(global
, ifname
);
267 reply
= wpas_dbus_new_invalid_iface_error(message
);
271 path
= wpa_s
->dbus_path
;
272 reply
= dbus_message_new_method_return(message
);
273 dbus_message_append_args(reply
,
274 DBUS_TYPE_OBJECT_PATH
, &path
,
283 * wpas_dbus_global_set_debugparams- Set the debug params
284 * @message: Pointer to incoming dbus message
285 * @global: %wpa_supplicant global data structure
286 * Returns: a dbus message containing a UINT32 indicating success (1) or
287 * failure (0), or returns a dbus error message with more information
289 * Handler function for "setDebugParams" method call. Handles requests
290 * by dbus clients for the object path of an specific network interface.
292 DBusMessage
* wpas_dbus_global_set_debugparams(DBusMessage
*message
,
293 struct wpa_global
*global
)
295 DBusMessage
*reply
= NULL
;
297 dbus_bool_t debug_timestamp
;
298 dbus_bool_t debug_show_keys
;
300 if (!dbus_message_get_args(message
, NULL
,
301 DBUS_TYPE_INT32
, &debug_level
,
302 DBUS_TYPE_BOOLEAN
, &debug_timestamp
,
303 DBUS_TYPE_BOOLEAN
, &debug_show_keys
,
304 DBUS_TYPE_INVALID
)) {
305 return wpas_dbus_new_invalid_opts_error(message
, NULL
);
308 if (wpa_supplicant_set_debug_params(global
, debug_level
,
309 debug_timestamp
? 1 : 0,
310 debug_show_keys
? 1 : 0)) {
311 return wpas_dbus_new_invalid_opts_error(message
, NULL
);
314 reply
= wpas_dbus_new_success_reply(message
);
321 * wpas_dbus_iface_scan - Request a wireless scan on an interface
322 * @message: Pointer to incoming dbus message
323 * @wpa_s: wpa_supplicant structure for a network interface
324 * Returns: a dbus message containing a UINT32 indicating success (1) or
327 * Handler function for "scan" method call of a network device. Requests
328 * that wpa_supplicant perform a wireless scan as soon as possible
329 * on a particular wireless interface.
331 DBusMessage
* wpas_dbus_iface_scan(DBusMessage
*message
,
332 struct wpa_supplicant
*wpa_s
)
334 wpa_s
->scan_req
= MANUAL_SCAN_REQ
;
335 wpa_supplicant_req_scan(wpa_s
, 0, 0);
336 return wpas_dbus_new_success_reply(message
);
341 * wpas_dbus_iface_scan_results - Get the results of a recent scan request
342 * @message: Pointer to incoming dbus message
343 * @wpa_s: wpa_supplicant structure for a network interface
344 * Returns: a dbus message containing a dbus array of objects paths, or returns
345 * a dbus error message if not scan results could be found
347 * Handler function for "scanResults" method call of a network device. Returns
348 * a dbus message containing the object paths of wireless networks found.
350 DBusMessage
* wpas_dbus_iface_scan_results(DBusMessage
*message
,
351 struct wpa_supplicant
*wpa_s
)
353 DBusMessage
*reply
= NULL
;
354 DBusMessageIter iter
;
355 DBusMessageIter sub_iter
;
358 /* Create and initialize the return message */
359 reply
= dbus_message_new_method_return(message
);
360 dbus_message_iter_init_append(reply
, &iter
);
361 dbus_message_iter_open_container(&iter
, DBUS_TYPE_ARRAY
,
362 DBUS_TYPE_OBJECT_PATH_AS_STRING
,
365 /* Loop through scan results and append each result's object path */
366 dl_list_for_each(bss
, &wpa_s
->bss_id
, struct wpa_bss
, list_id
) {
367 char path_buf
[WPAS_DBUS_OBJECT_PATH_MAX
];
368 char *path
= path_buf
;
370 /* Construct the object path for this network. Note that ':'
371 * is not a valid character in dbus object paths.
373 os_snprintf(path
, WPAS_DBUS_OBJECT_PATH_MAX
,
374 "%s/" WPAS_DBUS_BSSIDS_PART
"/"
375 WPAS_DBUS_BSSID_FORMAT
,
376 wpa_s
->dbus_path
, MAC2STR(bss
->bssid
));
377 dbus_message_iter_append_basic(&sub_iter
,
378 DBUS_TYPE_OBJECT_PATH
, &path
);
381 dbus_message_iter_close_container(&iter
, &sub_iter
);
388 * wpas_dbus_bssid_properties - Return the properties of a scanned network
389 * @message: Pointer to incoming dbus message
390 * @wpa_s: wpa_supplicant structure for a network interface
391 * @res: wpa_supplicant scan result for which to get properties
392 * Returns: a dbus message containing the properties for the requested network
394 * Handler function for "properties" method call of a scanned network.
395 * Returns a dbus message containing the the properties.
397 DBusMessage
* wpas_dbus_bssid_properties(DBusMessage
*message
,
398 struct wpa_supplicant
*wpa_s
,
402 DBusMessageIter iter
, iter_dict
;
405 /* Dump the properties into a dbus message */
406 reply
= dbus_message_new_method_return(message
);
408 dbus_message_iter_init_append(reply
, &iter
);
409 if (!wpa_dbus_dict_open_write(&iter
, &iter_dict
))
412 if (!wpa_dbus_dict_append_byte_array(&iter_dict
, "bssid",
413 (const char *) bss
->bssid
,
417 ie
= wpa_bss_get_ie(bss
, WLAN_EID_SSID
);
419 if (!wpa_dbus_dict_append_byte_array(&iter_dict
, "ssid",
420 (const char *) (ie
+ 2),
425 ie
= wpa_bss_get_vendor_ie(bss
, WPA_IE_VENDOR_TYPE
);
427 if (!wpa_dbus_dict_append_byte_array(&iter_dict
, "wpaie",
433 ie
= wpa_bss_get_ie(bss
, WLAN_EID_RSN
);
435 if (!wpa_dbus_dict_append_byte_array(&iter_dict
, "rsnie",
441 ie
= wpa_bss_get_vendor_ie(bss
, WPS_IE_VENDOR_TYPE
);
443 if (!wpa_dbus_dict_append_byte_array(&iter_dict
, "wpsie",
450 if (!wpa_dbus_dict_append_int32(&iter_dict
, "frequency",
454 if (!wpa_dbus_dict_append_uint16(&iter_dict
, "capabilities",
457 if (!(bss
->flags
& WPA_BSS_QUAL_INVALID
) &&
458 !wpa_dbus_dict_append_int32(&iter_dict
, "quality", bss
->qual
))
460 if (!(bss
->flags
& WPA_BSS_NOISE_INVALID
) &&
461 !wpa_dbus_dict_append_int32(&iter_dict
, "noise", bss
->noise
))
463 if (!(bss
->flags
& WPA_BSS_LEVEL_INVALID
) &&
464 !wpa_dbus_dict_append_int32(&iter_dict
, "level", bss
->level
))
466 if (!wpa_dbus_dict_append_int32(&iter_dict
, "maxrate",
467 wpa_bss_get_max_rate(bss
) * 500000))
470 if (!wpa_dbus_dict_close_write(&iter
, &iter_dict
))
477 dbus_message_unref(reply
);
478 return dbus_message_new_error(message
, WPAS_ERROR_INTERNAL_ERROR
,
479 "an internal error occurred returning "
480 "BSSID properties.");
485 * wpas_dbus_iface_capabilities - Return interface capabilities
486 * @message: Pointer to incoming dbus message
487 * @wpa_s: wpa_supplicant structure for a network interface
488 * Returns: A dbus message containing a dict of strings
490 * Handler function for "capabilities" method call of an interface.
492 DBusMessage
* wpas_dbus_iface_capabilities(DBusMessage
*message
,
493 struct wpa_supplicant
*wpa_s
)
495 DBusMessage
*reply
= NULL
;
496 struct wpa_driver_capa capa
;
498 DBusMessageIter iter
, iter_dict
;
501 dbus_bool_t strict
= FALSE
;
502 DBusMessageIter iter_dict_entry
, iter_dict_val
, iter_array
;
504 if (!dbus_message_get_args(message
, NULL
,
505 DBUS_TYPE_BOOLEAN
, &strict
,
509 reply
= dbus_message_new_method_return(message
);
511 dbus_message_iter_init_append(reply
, &iter
);
512 if (!wpa_dbus_dict_open_write(&iter
, &iter_dict
))
516 eap_methods
= eap_get_names_as_string_array(&num_items
);
518 dbus_bool_t success
= FALSE
;
521 success
= wpa_dbus_dict_append_string_array(
522 &iter_dict
, "eap", (const char **) eap_methods
,
525 /* free returned method array */
526 while (eap_methods
[i
])
527 os_free(eap_methods
[i
++]);
528 os_free(eap_methods
);
534 res
= wpa_drv_get_capa(wpa_s
, &capa
);
536 /***** pairwise cipher */
539 const char *args
[] = {"CCMP", "TKIP", "NONE"};
540 if (!wpa_dbus_dict_append_string_array(
541 &iter_dict
, "pairwise", args
,
542 sizeof(args
) / sizeof(char*)))
546 if (!wpa_dbus_dict_begin_string_array(&iter_dict
, "pairwise",
552 if (capa
.enc
& WPA_DRIVER_CAPA_ENC_CCMP
) {
553 if (!wpa_dbus_dict_string_array_add_element(
554 &iter_array
, "CCMP"))
558 if (capa
.enc
& WPA_DRIVER_CAPA_ENC_TKIP
) {
559 if (!wpa_dbus_dict_string_array_add_element(
560 &iter_array
, "TKIP"))
564 if (capa
.key_mgmt
& WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE
) {
565 if (!wpa_dbus_dict_string_array_add_element(
566 &iter_array
, "NONE"))
570 if (!wpa_dbus_dict_end_string_array(&iter_dict
,
577 /***** group cipher */
580 const char *args
[] = {
581 "CCMP", "TKIP", "WEP104", "WEP40"
583 if (!wpa_dbus_dict_append_string_array(
584 &iter_dict
, "group", args
,
585 sizeof(args
) / sizeof(char*)))
589 if (!wpa_dbus_dict_begin_string_array(&iter_dict
, "group",
595 if (capa
.enc
& WPA_DRIVER_CAPA_ENC_CCMP
) {
596 if (!wpa_dbus_dict_string_array_add_element(
597 &iter_array
, "CCMP"))
601 if (capa
.enc
& WPA_DRIVER_CAPA_ENC_TKIP
) {
602 if (!wpa_dbus_dict_string_array_add_element(
603 &iter_array
, "TKIP"))
607 if (capa
.enc
& WPA_DRIVER_CAPA_ENC_WEP104
) {
608 if (!wpa_dbus_dict_string_array_add_element(
609 &iter_array
, "WEP104"))
613 if (capa
.enc
& WPA_DRIVER_CAPA_ENC_WEP40
) {
614 if (!wpa_dbus_dict_string_array_add_element(
615 &iter_array
, "WEP40"))
619 if (!wpa_dbus_dict_end_string_array(&iter_dict
,
626 /***** key management */
629 const char *args
[] = {
630 "WPA-PSK", "WPA-EAP", "IEEE8021X", "WPA-NONE",
633 if (!wpa_dbus_dict_append_string_array(
634 &iter_dict
, "key_mgmt", args
,
635 sizeof(args
) / sizeof(char*)))
639 if (!wpa_dbus_dict_begin_string_array(&iter_dict
, "key_mgmt",
645 if (!wpa_dbus_dict_string_array_add_element(&iter_array
,
649 if (!wpa_dbus_dict_string_array_add_element(&iter_array
,
653 if (capa
.key_mgmt
& (WPA_DRIVER_CAPA_KEY_MGMT_WPA
|
654 WPA_DRIVER_CAPA_KEY_MGMT_WPA2
)) {
655 if (!wpa_dbus_dict_string_array_add_element(
656 &iter_array
, "WPA-EAP"))
660 if (capa
.key_mgmt
& (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK
|
661 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK
)) {
662 if (!wpa_dbus_dict_string_array_add_element(
663 &iter_array
, "WPA-PSK"))
667 if (capa
.key_mgmt
& WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE
) {
668 if (!wpa_dbus_dict_string_array_add_element(
669 &iter_array
, "WPA-NONE"))
673 if (!wpa_dbus_dict_end_string_array(&iter_dict
,
680 /***** WPA protocol */
683 const char *args
[] = { "RSN", "WPA" };
684 if (!wpa_dbus_dict_append_string_array(
685 &iter_dict
, "proto", args
,
686 sizeof(args
) / sizeof(char*)))
690 if (!wpa_dbus_dict_begin_string_array(&iter_dict
, "proto",
696 if (capa
.key_mgmt
& (WPA_DRIVER_CAPA_KEY_MGMT_WPA2
|
697 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK
)) {
698 if (!wpa_dbus_dict_string_array_add_element(
703 if (capa
.key_mgmt
& (WPA_DRIVER_CAPA_KEY_MGMT_WPA
|
704 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK
)) {
705 if (!wpa_dbus_dict_string_array_add_element(
710 if (!wpa_dbus_dict_end_string_array(&iter_dict
,
720 const char *args
[] = { "OPEN", "SHARED", "LEAP" };
721 if (!wpa_dbus_dict_append_string_array(
722 &iter_dict
, "auth_alg", args
,
723 sizeof(args
) / sizeof(char*)))
727 if (!wpa_dbus_dict_begin_string_array(&iter_dict
, "auth_alg",
733 if (capa
.auth
& (WPA_DRIVER_AUTH_OPEN
)) {
734 if (!wpa_dbus_dict_string_array_add_element(
735 &iter_array
, "OPEN"))
739 if (capa
.auth
& (WPA_DRIVER_AUTH_SHARED
)) {
740 if (!wpa_dbus_dict_string_array_add_element(
741 &iter_array
, "SHARED"))
745 if (capa
.auth
& (WPA_DRIVER_AUTH_LEAP
)) {
746 if (!wpa_dbus_dict_string_array_add_element(
747 &iter_array
, "LEAP"))
751 if (!wpa_dbus_dict_end_string_array(&iter_dict
,
758 if (!wpa_dbus_dict_close_write(&iter
, &iter_dict
))
765 dbus_message_unref(reply
);
766 return dbus_message_new_error(message
, WPAS_ERROR_INTERNAL_ERROR
,
767 "an internal error occurred returning "
768 "interface capabilities.");
773 * wpas_dbus_iface_add_network - Add a new configured network
774 * @message: Pointer to incoming dbus message
775 * @wpa_s: wpa_supplicant structure for a network interface
776 * Returns: A dbus message containing the object path of the new network
778 * Handler function for "addNetwork" method call of a network interface.
780 DBusMessage
* wpas_dbus_iface_add_network(DBusMessage
*message
,
781 struct wpa_supplicant
*wpa_s
)
783 DBusMessage
*reply
= NULL
;
784 struct wpa_ssid
*ssid
;
785 char path_buf
[WPAS_DBUS_OBJECT_PATH_MAX
], *path
= path_buf
;
787 ssid
= wpa_config_add_network(wpa_s
->conf
);
789 reply
= dbus_message_new_error(message
,
790 WPAS_ERROR_ADD_NETWORK_ERROR
,
791 "wpa_supplicant could not add "
792 "a network on this interface.");
795 wpas_notify_network_added(wpa_s
, ssid
);
797 wpa_config_set_network_defaults(ssid
);
799 /* Construct the object path for this network. */
800 os_snprintf(path
, WPAS_DBUS_OBJECT_PATH_MAX
,
801 "%s/" WPAS_DBUS_NETWORKS_PART
"/%d",
802 wpa_s
->dbus_path
, ssid
->id
);
804 reply
= dbus_message_new_method_return(message
);
805 dbus_message_append_args(reply
, DBUS_TYPE_OBJECT_PATH
,
806 &path
, DBUS_TYPE_INVALID
);
814 * wpas_dbus_iface_remove_network - Remove a configured network
815 * @message: Pointer to incoming dbus message
816 * @wpa_s: wpa_supplicant structure for a network interface
817 * Returns: A dbus message containing a UINT32 indicating success (1) or
820 * Handler function for "removeNetwork" method call of a network interface.
822 DBusMessage
* wpas_dbus_iface_remove_network(DBusMessage
*message
,
823 struct wpa_supplicant
*wpa_s
)
825 DBusMessage
*reply
= NULL
;
827 char *iface
= NULL
, *net_id
= NULL
;
829 struct wpa_ssid
*ssid
;
831 if (!dbus_message_get_args(message
, NULL
,
832 DBUS_TYPE_OBJECT_PATH
, &op
,
833 DBUS_TYPE_INVALID
)) {
834 reply
= wpas_dbus_new_invalid_opts_error(message
, NULL
);
838 /* Extract the network ID */
839 iface
= wpas_dbus_decompose_object_path(op
, &net_id
, NULL
);
841 reply
= wpas_dbus_new_invalid_network_error(message
);
845 /* Ensure the network is actually a child of this interface */
846 if (os_strcmp(iface
, wpa_s
->dbus_path
) != 0) {
847 reply
= wpas_dbus_new_invalid_network_error(message
);
851 id
= strtoul(net_id
, NULL
, 10);
852 ssid
= wpa_config_get_network(wpa_s
->conf
, id
);
854 reply
= wpas_dbus_new_invalid_network_error(message
);
858 wpas_notify_network_removed(wpa_s
, ssid
);
860 if (wpa_config_remove_network(wpa_s
->conf
, id
) < 0) {
861 reply
= dbus_message_new_error(message
,
862 WPAS_ERROR_REMOVE_NETWORK_ERROR
,
863 "error removing the specified "
864 "on this interface.");
868 if (ssid
== wpa_s
->current_ssid
)
869 wpa_supplicant_deauthenticate(wpa_s
,
870 WLAN_REASON_DEAUTH_LEAVING
);
871 reply
= wpas_dbus_new_success_reply(message
);
880 static const char *dont_quote
[] = {
881 "key_mgmt", "proto", "pairwise", "auth_alg", "group", "eap",
882 "opensc_engine_path", "pkcs11_engine_path", "pkcs11_module_path",
887 static dbus_bool_t
should_quote_opt(const char *key
)
890 while (dont_quote
[i
] != NULL
) {
891 if (strcmp(key
, dont_quote
[i
]) == 0)
900 * wpas_dbus_iface_set_network - Set options for a configured network
901 * @message: Pointer to incoming dbus message
902 * @wpa_s: wpa_supplicant structure for a network interface
903 * @ssid: wpa_ssid structure for a configured network
904 * Returns: a dbus message containing a UINT32 indicating success (1) or
907 * Handler function for "set" method call of a configured network.
909 DBusMessage
* wpas_dbus_iface_set_network(DBusMessage
*message
,
910 struct wpa_supplicant
*wpa_s
,
911 struct wpa_ssid
*ssid
)
913 DBusMessage
*reply
= NULL
;
914 struct wpa_dbus_dict_entry entry
= { .type
= DBUS_TYPE_STRING
};
915 DBusMessageIter iter
, iter_dict
;
917 dbus_message_iter_init(message
, &iter
);
919 if (!wpa_dbus_dict_open_read(&iter
, &iter_dict
, NULL
)) {
920 reply
= wpas_dbus_new_invalid_opts_error(message
, NULL
);
924 while (wpa_dbus_dict_has_dict_entry(&iter_dict
)) {
929 if (!wpa_dbus_dict_get_entry(&iter_dict
, &entry
)) {
930 reply
= wpas_dbus_new_invalid_opts_error(message
,
935 /* Type conversions, since wpa_supplicant wants strings */
936 if (entry
.type
== DBUS_TYPE_ARRAY
&&
937 entry
.array_type
== DBUS_TYPE_BYTE
) {
938 if (entry
.array_len
<= 0)
941 size
= entry
.array_len
* 2 + 1;
942 value
= os_zalloc(size
);
945 ret
= wpa_snprintf_hex(value
, size
,
946 (u8
*) entry
.bytearray_value
,
950 } else if (entry
.type
== DBUS_TYPE_STRING
) {
951 if (should_quote_opt(entry
.key
)) {
952 size
= os_strlen(entry
.str_value
);
953 /* Zero-length option check */
956 size
+= 3; /* For quotes and terminator */
957 value
= os_zalloc(size
);
960 ret
= os_snprintf(value
, size
, "\"%s\"",
962 if (ret
< 0 || (size_t) ret
!= (size
- 1))
965 value
= os_strdup(entry
.str_value
);
969 } else if (entry
.type
== DBUS_TYPE_UINT32
) {
970 value
= os_zalloc(size
);
973 ret
= os_snprintf(value
, size
, "%u",
977 } else if (entry
.type
== DBUS_TYPE_INT32
) {
978 value
= os_zalloc(size
);
981 ret
= os_snprintf(value
, size
, "%d",
988 if (wpa_config_set(ssid
, entry
.key
, value
, 0) < 0)
991 if ((os_strcmp(entry
.key
, "psk") == 0 &&
992 value
[0] == '"' && ssid
->ssid_len
) ||
993 (os_strcmp(entry
.key
, "ssid") == 0 && ssid
->passphrase
))
994 wpa_config_update_psk(ssid
);
995 else if (os_strcmp(entry
.key
, "priority") == 0)
996 wpa_config_update_prio_list(wpa_s
->conf
);
999 wpa_dbus_dict_entry_clear(&entry
);
1004 reply
= wpas_dbus_new_invalid_opts_error(message
, entry
.key
);
1005 wpa_dbus_dict_entry_clear(&entry
);
1010 reply
= wpas_dbus_new_success_reply(message
);
1018 * wpas_dbus_iface_enable_network - Mark a configured network as enabled
1019 * @message: Pointer to incoming dbus message
1020 * @wpa_s: wpa_supplicant structure for a network interface
1021 * @ssid: wpa_ssid structure for a configured network
1022 * Returns: A dbus message containing a UINT32 indicating success (1) or
1025 * Handler function for "enable" method call of a configured network.
1027 DBusMessage
* wpas_dbus_iface_enable_network(DBusMessage
*message
,
1028 struct wpa_supplicant
*wpa_s
,
1029 struct wpa_ssid
*ssid
)
1031 wpa_supplicant_enable_network(wpa_s
, ssid
);
1032 return wpas_dbus_new_success_reply(message
);
1037 * wpas_dbus_iface_disable_network - Mark a configured network as disabled
1038 * @message: Pointer to incoming dbus message
1039 * @wpa_s: wpa_supplicant structure for a network interface
1040 * @ssid: wpa_ssid structure for a configured network
1041 * Returns: A dbus message containing a UINT32 indicating success (1) or
1044 * Handler function for "disable" method call of a configured network.
1046 DBusMessage
* wpas_dbus_iface_disable_network(DBusMessage
*message
,
1047 struct wpa_supplicant
*wpa_s
,
1048 struct wpa_ssid
*ssid
)
1050 wpa_supplicant_disable_network(wpa_s
, ssid
);
1051 return wpas_dbus_new_success_reply(message
);
1056 * wpas_dbus_iface_select_network - Attempt association with a configured network
1057 * @message: Pointer to incoming dbus message
1058 * @wpa_s: wpa_supplicant structure for a network interface
1059 * Returns: A dbus message containing a UINT32 indicating success (1) or
1062 * Handler function for "selectNetwork" method call of network interface.
1064 DBusMessage
* wpas_dbus_iface_select_network(DBusMessage
*message
,
1065 struct wpa_supplicant
*wpa_s
)
1067 DBusMessage
*reply
= NULL
;
1069 struct wpa_ssid
*ssid
;
1070 char *iface_obj_path
= NULL
;
1071 char *network
= NULL
;
1073 if (os_strlen(dbus_message_get_signature(message
)) == 0) {
1079 if (!dbus_message_get_args(message
, NULL
,
1080 DBUS_TYPE_OBJECT_PATH
, &op
,
1081 DBUS_TYPE_INVALID
)) {
1082 reply
= wpas_dbus_new_invalid_opts_error(message
,
1087 /* Extract the network number */
1088 iface_obj_path
= wpas_dbus_decompose_object_path(op
,
1091 if (iface_obj_path
== NULL
) {
1092 reply
= wpas_dbus_new_invalid_iface_error(message
);
1095 /* Ensure the object path really points to this interface */
1096 if (os_strcmp(iface_obj_path
, wpa_s
->dbus_path
) != 0) {
1097 reply
= wpas_dbus_new_invalid_network_error(message
);
1101 nid
= strtoul(network
, NULL
, 10);
1102 if (errno
== EINVAL
) {
1103 reply
= wpas_dbus_new_invalid_network_error(message
);
1107 ssid
= wpa_config_get_network(wpa_s
->conf
, nid
);
1109 reply
= wpas_dbus_new_invalid_network_error(message
);
1114 /* Finally, associate with the network */
1115 wpa_supplicant_select_network(wpa_s
, ssid
);
1117 reply
= wpas_dbus_new_success_reply(message
);
1120 os_free(iface_obj_path
);
1127 * wpas_dbus_iface_disconnect - Terminate the current connection
1128 * @message: Pointer to incoming dbus message
1129 * @wpa_s: wpa_supplicant structure for a network interface
1130 * Returns: A dbus message containing a UINT32 indicating success (1) or
1133 * Handler function for "disconnect" method call of network interface.
1135 DBusMessage
* wpas_dbus_iface_disconnect(DBusMessage
*message
,
1136 struct wpa_supplicant
*wpa_s
)
1138 wpa_s
->disconnected
= 1;
1139 wpa_supplicant_deauthenticate(wpa_s
, WLAN_REASON_DEAUTH_LEAVING
);
1141 return wpas_dbus_new_success_reply(message
);
1146 * wpas_dbus_iface_set_ap_scan - Control roaming mode
1147 * @message: Pointer to incoming dbus message
1148 * @wpa_s: wpa_supplicant structure for a network interface
1149 * Returns: A dbus message containing a UINT32 indicating success (1) or
1152 * Handler function for "setAPScan" method call.
1154 DBusMessage
* wpas_dbus_iface_set_ap_scan(DBusMessage
*message
,
1155 struct wpa_supplicant
*wpa_s
)
1157 DBusMessage
*reply
= NULL
;
1158 dbus_uint32_t ap_scan
= 1;
1160 if (!dbus_message_get_args(message
, NULL
, DBUS_TYPE_UINT32
, &ap_scan
,
1161 DBUS_TYPE_INVALID
)) {
1162 reply
= wpas_dbus_new_invalid_opts_error(message
, NULL
);
1166 if (wpa_supplicant_set_ap_scan(wpa_s
, ap_scan
)) {
1167 reply
= wpas_dbus_new_invalid_opts_error(message
, NULL
);
1171 reply
= wpas_dbus_new_success_reply(message
);
1179 * wpas_dbus_iface_set_smartcard_modules - Set smartcard related module paths
1180 * @message: Pointer to incoming dbus message
1181 * @wpa_s: wpa_supplicant structure for a network interface
1182 * Returns: A dbus message containing a UINT32 indicating success (1) or
1185 * Handler function for "setSmartcardModules" method call.
1187 DBusMessage
* wpas_dbus_iface_set_smartcard_modules(
1188 DBusMessage
*message
, struct wpa_supplicant
*wpa_s
)
1190 DBusMessageIter iter
, iter_dict
;
1191 char *opensc_engine_path
= NULL
;
1192 char *pkcs11_engine_path
= NULL
;
1193 char *pkcs11_module_path
= NULL
;
1194 struct wpa_dbus_dict_entry entry
;
1196 if (!dbus_message_iter_init(message
, &iter
))
1199 if (!wpa_dbus_dict_open_read(&iter
, &iter_dict
, NULL
))
1202 while (wpa_dbus_dict_has_dict_entry(&iter_dict
)) {
1203 if (!wpa_dbus_dict_get_entry(&iter_dict
, &entry
))
1205 if (!strcmp(entry
.key
, "opensc_engine_path") &&
1206 (entry
.type
== DBUS_TYPE_STRING
)) {
1207 opensc_engine_path
= os_strdup(entry
.str_value
);
1208 if (opensc_engine_path
== NULL
)
1210 } else if (!strcmp(entry
.key
, "pkcs11_engine_path") &&
1211 (entry
.type
== DBUS_TYPE_STRING
)) {
1212 pkcs11_engine_path
= os_strdup(entry
.str_value
);
1213 if (pkcs11_engine_path
== NULL
)
1215 } else if (!strcmp(entry
.key
, "pkcs11_module_path") &&
1216 (entry
.type
== DBUS_TYPE_STRING
)) {
1217 pkcs11_module_path
= os_strdup(entry
.str_value
);
1218 if (pkcs11_module_path
== NULL
)
1221 wpa_dbus_dict_entry_clear(&entry
);
1224 wpa_dbus_dict_entry_clear(&entry
);
1227 os_free(wpa_s
->conf
->opensc_engine_path
);
1228 wpa_s
->conf
->opensc_engine_path
= opensc_engine_path
;
1229 os_free(wpa_s
->conf
->pkcs11_engine_path
);
1230 wpa_s
->conf
->pkcs11_engine_path
= pkcs11_engine_path
;
1231 os_free(wpa_s
->conf
->pkcs11_module_path
);
1232 wpa_s
->conf
->pkcs11_module_path
= pkcs11_module_path
;
1234 wpa_sm_set_eapol(wpa_s
->wpa
, NULL
);
1235 eapol_sm_deinit(wpa_s
->eapol
);
1236 wpa_s
->eapol
= NULL
;
1237 wpa_supplicant_init_eapol(wpa_s
);
1238 wpa_sm_set_eapol(wpa_s
->wpa
, wpa_s
->eapol
);
1240 return wpas_dbus_new_success_reply(message
);
1243 os_free(opensc_engine_path
);
1244 os_free(pkcs11_engine_path
);
1245 os_free(pkcs11_module_path
);
1246 return wpas_dbus_new_invalid_opts_error(message
, NULL
);
1251 * wpas_dbus_iface_get_state - Get interface state
1252 * @message: Pointer to incoming dbus message
1253 * @wpa_s: wpa_supplicant structure for a network interface
1254 * Returns: A dbus message containing a STRING representing the current
1257 * Handler function for "state" method call.
1259 DBusMessage
* wpas_dbus_iface_get_state(DBusMessage
*message
,
1260 struct wpa_supplicant
*wpa_s
)
1262 DBusMessage
*reply
= NULL
;
1263 const char *str_state
;
1265 reply
= dbus_message_new_method_return(message
);
1266 if (reply
!= NULL
) {
1267 str_state
= wpa_supplicant_state_txt(wpa_s
->wpa_state
);
1268 dbus_message_append_args(reply
, DBUS_TYPE_STRING
, &str_state
,
1277 * wpas_dbus_iface_get_scanning - Get interface scanning state
1278 * @message: Pointer to incoming dbus message
1279 * @wpa_s: wpa_supplicant structure for a network interface
1280 * Returns: A dbus message containing whether the interface is scanning
1282 * Handler function for "scanning" method call.
1284 DBusMessage
* wpas_dbus_iface_get_scanning(DBusMessage
*message
,
1285 struct wpa_supplicant
*wpa_s
)
1287 DBusMessage
*reply
= NULL
;
1288 dbus_bool_t scanning
= wpa_s
->scanning
? TRUE
: FALSE
;
1290 reply
= dbus_message_new_method_return(message
);
1291 if (reply
!= NULL
) {
1292 dbus_message_append_args(reply
, DBUS_TYPE_BOOLEAN
, &scanning
,
1295 wpa_printf(MSG_ERROR
, "dbus: Not enough memory to return "
1304 * wpas_dbus_iface_set_blobs - Store named binary blobs (ie, for certificates)
1305 * @message: Pointer to incoming dbus message
1306 * @wpa_s: %wpa_supplicant data structure
1307 * Returns: A dbus message containing a UINT32 indicating success (1) or
1310 * Asks wpa_supplicant to internally store a one or more binary blobs.
1312 DBusMessage
* wpas_dbus_iface_set_blobs(DBusMessage
*message
,
1313 struct wpa_supplicant
*wpa_s
)
1315 DBusMessage
*reply
= NULL
;
1316 struct wpa_dbus_dict_entry entry
= { .type
= DBUS_TYPE_STRING
};
1317 DBusMessageIter iter
, iter_dict
;
1319 dbus_message_iter_init(message
, &iter
);
1321 if (!wpa_dbus_dict_open_read(&iter
, &iter_dict
, NULL
))
1322 return wpas_dbus_new_invalid_opts_error(message
, NULL
);
1324 while (wpa_dbus_dict_has_dict_entry(&iter_dict
)) {
1325 struct wpa_config_blob
*blob
;
1327 if (!wpa_dbus_dict_get_entry(&iter_dict
, &entry
)) {
1328 reply
= wpas_dbus_new_invalid_opts_error(message
,
1333 if (entry
.type
!= DBUS_TYPE_ARRAY
||
1334 entry
.array_type
!= DBUS_TYPE_BYTE
) {
1335 reply
= wpas_dbus_new_invalid_opts_error(
1336 message
, "Byte array expected.");
1340 if ((entry
.array_len
<= 0) || (entry
.array_len
> 65536) ||
1341 !strlen(entry
.key
)) {
1342 reply
= wpas_dbus_new_invalid_opts_error(
1343 message
, "Invalid array size.");
1347 blob
= os_zalloc(sizeof(*blob
));
1349 reply
= dbus_message_new_error(
1350 message
, WPAS_ERROR_ADD_ERROR
,
1351 "Not enough memory to add blob.");
1354 blob
->data
= os_zalloc(entry
.array_len
);
1355 if (blob
->data
== NULL
) {
1356 reply
= dbus_message_new_error(
1357 message
, WPAS_ERROR_ADD_ERROR
,
1358 "Not enough memory to add blob data.");
1363 blob
->name
= os_strdup(entry
.key
);
1364 blob
->len
= entry
.array_len
;
1365 os_memcpy(blob
->data
, (u8
*) entry
.bytearray_value
,
1367 if (blob
->name
== NULL
|| blob
->data
== NULL
) {
1368 wpa_config_free_blob(blob
);
1369 reply
= dbus_message_new_error(
1370 message
, WPAS_ERROR_ADD_ERROR
,
1371 "Error adding blob.");
1376 if (!wpa_config_remove_blob(wpa_s
->conf
, blob
->name
))
1377 wpas_notify_blob_removed(wpa_s
, blob
->name
);
1378 wpa_config_set_blob(wpa_s
->conf
, blob
);
1379 wpas_notify_blob_added(wpa_s
, blob
->name
);
1381 wpa_dbus_dict_entry_clear(&entry
);
1383 wpa_dbus_dict_entry_clear(&entry
);
1385 return reply
? reply
: wpas_dbus_new_success_reply(message
);
1390 * wpas_dbus_iface_remove_blob - Remove named binary blobs
1391 * @message: Pointer to incoming dbus message
1392 * @wpa_s: %wpa_supplicant data structure
1393 * Returns: A dbus message containing a UINT32 indicating success (1) or
1396 * Asks wpa_supplicant to remove one or more previously stored binary blobs.
1398 DBusMessage
* wpas_dbus_iface_remove_blobs(DBusMessage
*message
,
1399 struct wpa_supplicant
*wpa_s
)
1401 DBusMessageIter iter
, array
;
1402 char *err_msg
= NULL
;
1404 dbus_message_iter_init(message
, &iter
);
1406 if ((dbus_message_iter_get_arg_type (&iter
) != DBUS_TYPE_ARRAY
) ||
1407 (dbus_message_iter_get_element_type (&iter
) != DBUS_TYPE_STRING
))
1408 return wpas_dbus_new_invalid_opts_error(message
, NULL
);
1410 dbus_message_iter_recurse(&iter
, &array
);
1411 while (dbus_message_iter_get_arg_type(&array
) == DBUS_TYPE_STRING
) {
1414 dbus_message_iter_get_basic(&array
, &name
);
1415 if (!os_strlen(name
))
1416 err_msg
= "Invalid blob name.";
1418 if (wpa_config_remove_blob(wpa_s
->conf
, name
) != 0)
1419 err_msg
= "Error removing blob.";
1421 wpas_notify_blob_removed(wpa_s
, name
);
1422 dbus_message_iter_next(&array
);
1426 return dbus_message_new_error(message
, WPAS_ERROR_REMOVE_ERROR
,
1429 return wpas_dbus_new_success_reply(message
);
1434 * wpas_dbus_iface_flush - Clear BSS of old or all inactive entries
1435 * @message: Pointer to incoming dbus message
1436 * @wpa_s: %wpa_supplicant data structure
1437 * Returns: a dbus message containing a UINT32 indicating success (1) or
1438 * failure (0), or returns a dbus error message with more information
1440 * Handler function for "flush" method call. Handles requests for an
1441 * interface with an optional "age" parameter that specifies the minimum
1442 * age of a BSS to be flushed.
1444 DBusMessage
* wpas_dbus_iface_flush(DBusMessage
*message
,
1445 struct wpa_supplicant
*wpa_s
)
1449 if (os_strlen(dbus_message_get_signature(message
)) != 0 &&
1450 !dbus_message_get_args(message
, NULL
,
1451 DBUS_TYPE_INT32
, &flush_age
,
1452 DBUS_TYPE_INVALID
)) {
1453 return wpas_dbus_new_invalid_opts_error(message
, NULL
);
1457 wpa_bss_flush(wpa_s
);
1459 wpa_bss_flush_by_age(wpa_s
, flush_age
);
1461 return wpas_dbus_new_success_reply(message
);