2
* WPA Supplicant / dbus-based control interface
3
* Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License version 2 as
7
* published by the Free Software Foundation.
9
* Alternatively, this software may be distributed under the terms of BSD
12
* See README and COPYING for more details.
16
#include <dbus/dbus.h>
19
#include "eap_peer/eap_methods.h"
20
#include "common/ieee802_11_defs.h"
21
#include "eapol_supp/eapol_supp_sm.h"
22
#include "rsn_supp/wpa.h"
23
#include "../config.h"
24
#include "../wpa_supplicant_i.h"
25
#include "../driver_i.h"
26
#include "../notify.h"
27
#include "../wpas_glue.h"
31
#include "dbus_old_handlers.h"
32
#include "dbus_dict_helpers.h"
34
extern int wpa_debug_level;
35
extern int wpa_debug_show_keys;
36
extern int wpa_debug_timestamp;
39
* wpas_dbus_new_invalid_opts_error - Return a new invalid options error message
40
* @message: Pointer to incoming dbus message this error refers to
41
* Returns: a dbus error message
43
* Convenience function to create and return an invalid options error
45
DBusMessage * wpas_dbus_new_invalid_opts_error(DBusMessage *message,
50
reply = dbus_message_new_error(message, WPAS_ERROR_INVALID_OPTS,
51
"Did not receive correct message "
54
dbus_message_append_args(reply, DBUS_TYPE_STRING, &arg,
62
* wpas_dbus_new_success_reply - Return a new success reply message
63
* @message: Pointer to incoming dbus message this reply refers to
64
* Returns: a dbus message containing a single UINT32 that indicates
65
* success (ie, a value of 1)
67
* Convenience function to create and return a success reply message
69
DBusMessage * wpas_dbus_new_success_reply(DBusMessage *message)
72
unsigned int success = 1;
74
reply = dbus_message_new_method_return(message);
75
dbus_message_append_args(reply, DBUS_TYPE_UINT32, &success,
82
* wpas_dbus_global_add_interface - Request registration of a network interface
83
* @message: Pointer to incoming dbus message
84
* @global: %wpa_supplicant global data structure
85
* Returns: The object path of the new interface object,
86
* or a dbus error message with more information
88
* Handler function for "addInterface" method call. Handles requests
89
* by dbus clients to register a network interface that wpa_supplicant
92
DBusMessage * wpas_dbus_global_add_interface(DBusMessage *message,
93
struct wpa_global *global)
97
char *driver_param = NULL;
98
char *confname = NULL;
99
char *bridge_ifname = NULL;
100
DBusMessage *reply = NULL;
101
DBusMessageIter iter;
103
dbus_message_iter_init(message, &iter);
105
/* First argument: interface name (DBUS_TYPE_STRING)
106
* Required; must be non-zero length
108
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
110
dbus_message_iter_get_basic(&iter, &ifname);
111
if (!os_strlen(ifname))
114
/* Second argument: dict of options */
115
if (dbus_message_iter_next(&iter)) {
116
DBusMessageIter iter_dict;
117
struct wpa_dbus_dict_entry entry;
119
if (!wpa_dbus_dict_open_read(&iter, &iter_dict))
121
while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
122
if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
124
if (!strcmp(entry.key, "driver") &&
125
(entry.type == DBUS_TYPE_STRING)) {
126
driver = os_strdup(entry.str_value);
127
wpa_dbus_dict_entry_clear(&entry);
130
} else if (!strcmp(entry.key, "driver-params") &&
131
(entry.type == DBUS_TYPE_STRING)) {
132
driver_param = os_strdup(entry.str_value);
133
wpa_dbus_dict_entry_clear(&entry);
134
if (driver_param == NULL)
136
} else if (!strcmp(entry.key, "config-file") &&
137
(entry.type == DBUS_TYPE_STRING)) {
138
confname = os_strdup(entry.str_value);
139
wpa_dbus_dict_entry_clear(&entry);
140
if (confname == NULL)
142
} else if (!strcmp(entry.key, "bridge-ifname") &&
143
(entry.type == DBUS_TYPE_STRING)) {
144
bridge_ifname = os_strdup(entry.str_value);
145
wpa_dbus_dict_entry_clear(&entry);
146
if (bridge_ifname == NULL)
149
wpa_dbus_dict_entry_clear(&entry);
156
* Try to get the wpa_supplicant record for this iface, return
157
* an error if we already control it.
159
if (wpa_supplicant_get_iface(global, ifname) != NULL) {
160
reply = dbus_message_new_error(message,
161
WPAS_ERROR_EXISTS_ERROR,
162
"wpa_supplicant already "
163
"controls this interface.");
165
struct wpa_supplicant *wpa_s;
166
struct wpa_interface iface;
167
os_memset(&iface, 0, sizeof(iface));
168
iface.ifname = ifname;
169
iface.driver = driver;
170
iface.driver_param = driver_param;
171
iface.confname = confname;
172
iface.bridge_ifname = bridge_ifname;
173
/* Otherwise, have wpa_supplicant attach to it. */
174
if ((wpa_s = wpa_supplicant_add_iface(global, &iface))) {
175
const char *path = wpa_s->dbus_path;
176
reply = dbus_message_new_method_return(message);
177
dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH,
178
&path, DBUS_TYPE_INVALID);
180
reply = dbus_message_new_error(message,
181
WPAS_ERROR_ADD_ERROR,
183
"couldn't grab this "
190
os_free(driver_param);
192
os_free(bridge_ifname);
196
reply = wpas_dbus_new_invalid_opts_error(message, NULL);
202
* wpas_dbus_global_remove_interface - Request deregistration of an interface
203
* @message: Pointer to incoming dbus message
204
* @global: wpa_supplicant global data structure
205
* Returns: a dbus message containing a UINT32 indicating success (1) or
206
* failure (0), or returns a dbus error message with more information
208
* Handler function for "removeInterface" method call. Handles requests
209
* by dbus clients to deregister a network interface that wpa_supplicant
212
DBusMessage * wpas_dbus_global_remove_interface(DBusMessage *message,
213
struct wpa_global *global)
215
struct wpa_supplicant *wpa_s;
217
DBusMessage *reply = NULL;
219
if (!dbus_message_get_args(message, NULL,
220
DBUS_TYPE_OBJECT_PATH, &path,
221
DBUS_TYPE_INVALID)) {
222
reply = wpas_dbus_new_invalid_opts_error(message, NULL);
226
wpa_s = wpa_supplicant_get_iface_by_dbus_path(global, path);
228
reply = wpas_dbus_new_invalid_iface_error(message);
232
if (!wpa_supplicant_remove_iface(global, wpa_s)) {
233
reply = wpas_dbus_new_success_reply(message);
235
reply = dbus_message_new_error(message,
236
WPAS_ERROR_REMOVE_ERROR,
237
"wpa_supplicant couldn't "
238
"remove this interface.");
247
* wpas_dbus_global_get_interface - Get the object path for an interface name
248
* @message: Pointer to incoming dbus message
249
* @global: %wpa_supplicant global data structure
250
* Returns: The object path of the interface object,
251
* or a dbus error message with more information
253
* Handler function for "getInterface" method call. Handles requests
254
* by dbus clients for the object path of an specific network interface.
256
DBusMessage * wpas_dbus_global_get_interface(DBusMessage *message,
257
struct wpa_global *global)
259
DBusMessage *reply = NULL;
262
struct wpa_supplicant *wpa_s;
264
if (!dbus_message_get_args(message, NULL,
265
DBUS_TYPE_STRING, &ifname,
266
DBUS_TYPE_INVALID)) {
267
reply = wpas_dbus_new_invalid_opts_error(message, NULL);
271
wpa_s = wpa_supplicant_get_iface(global, ifname);
273
reply = wpas_dbus_new_invalid_iface_error(message);
277
path = wpa_s->dbus_path;
278
reply = dbus_message_new_method_return(message);
279
dbus_message_append_args(reply,
280
DBUS_TYPE_OBJECT_PATH, &path,
289
* wpas_dbus_global_set_debugparams- Set the debug params
290
* @message: Pointer to incoming dbus message
291
* @global: %wpa_supplicant global data structure
292
* Returns: a dbus message containing a UINT32 indicating success (1) or
293
* failure (0), or returns a dbus error message with more information
295
* Handler function for "setDebugParams" method call. Handles requests
296
* by dbus clients for the object path of an specific network interface.
298
DBusMessage * wpas_dbus_global_set_debugparams(DBusMessage *message,
299
struct wpa_global *global)
301
DBusMessage *reply = NULL;
303
dbus_bool_t debug_timestamp;
304
dbus_bool_t debug_show_keys;
306
if (!dbus_message_get_args(message, NULL,
307
DBUS_TYPE_INT32, &debug_level,
308
DBUS_TYPE_BOOLEAN, &debug_timestamp,
309
DBUS_TYPE_BOOLEAN, &debug_show_keys,
310
DBUS_TYPE_INVALID)) {
311
return wpas_dbus_new_invalid_opts_error(message, NULL);
314
if (wpa_supplicant_set_debug_params(global, debug_level,
315
debug_timestamp ? 1 : 0,
316
debug_show_keys ? 1 : 0)) {
317
return wpas_dbus_new_invalid_opts_error(message, NULL);
320
reply = wpas_dbus_new_success_reply(message);
327
* wpas_dbus_iface_scan - Request a wireless scan on an interface
328
* @message: Pointer to incoming dbus message
329
* @wpa_s: wpa_supplicant structure for a network interface
330
* Returns: a dbus message containing a UINT32 indicating success (1) or
333
* Handler function for "scan" method call of a network device. Requests
334
* that wpa_supplicant perform a wireless scan as soon as possible
335
* on a particular wireless interface.
337
DBusMessage * wpas_dbus_iface_scan(DBusMessage *message,
338
struct wpa_supplicant *wpa_s)
341
wpa_supplicant_req_scan(wpa_s, 0, 0);
342
return wpas_dbus_new_success_reply(message);
347
* wpas_dbus_iface_scan_results - Get the results of a recent scan request
348
* @message: Pointer to incoming dbus message
349
* @wpa_s: wpa_supplicant structure for a network interface
350
* Returns: a dbus message containing a dbus array of objects paths, or returns
351
* a dbus error message if not scan results could be found
353
* Handler function for "scanResults" method call of a network device. Returns
354
* a dbus message containing the object paths of wireless networks found.
356
DBusMessage * wpas_dbus_iface_scan_results(DBusMessage *message,
357
struct wpa_supplicant *wpa_s)
359
DBusMessage *reply = NULL;
360
DBusMessageIter iter;
361
DBusMessageIter sub_iter;
364
/* Create and initialize the return message */
365
reply = dbus_message_new_method_return(message);
366
dbus_message_iter_init_append(reply, &iter);
367
dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
368
DBUS_TYPE_OBJECT_PATH_AS_STRING,
371
/* Loop through scan results and append each result's object path */
372
dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
373
char path_buf[WPAS_DBUS_OBJECT_PATH_MAX];
374
char *path = path_buf;
376
/* Construct the object path for this network. Note that ':'
377
* is not a valid character in dbus object paths.
379
os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
380
"%s/" WPAS_DBUS_BSSIDS_PART "/"
381
WPAS_DBUS_BSSID_FORMAT,
382
wpa_s->dbus_path, MAC2STR(bss->bssid));
383
dbus_message_iter_append_basic(&sub_iter,
384
DBUS_TYPE_OBJECT_PATH, &path);
387
dbus_message_iter_close_container(&iter, &sub_iter);
394
* wpas_dbus_bssid_properties - Return the properties of a scanned network
395
* @message: Pointer to incoming dbus message
396
* @wpa_s: wpa_supplicant structure for a network interface
397
* @res: wpa_supplicant scan result for which to get properties
398
* Returns: a dbus message containing the properties for the requested network
400
* Handler function for "properties" method call of a scanned network.
401
* Returns a dbus message containing the the properties.
403
DBusMessage * wpas_dbus_bssid_properties(DBusMessage *message,
404
struct wpa_supplicant *wpa_s,
408
DBusMessageIter iter, iter_dict;
411
/* Dump the properties into a dbus message */
412
reply = dbus_message_new_method_return(message);
414
dbus_message_iter_init_append(reply, &iter);
415
if (!wpa_dbus_dict_open_write(&iter, &iter_dict))
418
if (!wpa_dbus_dict_append_byte_array(&iter_dict, "bssid",
419
(const char *) bss->bssid,
423
ie = wpa_bss_get_ie(bss, WLAN_EID_SSID);
425
if (!wpa_dbus_dict_append_byte_array(&iter_dict, "ssid",
426
(const char *) (ie + 2),
431
ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
433
if (!wpa_dbus_dict_append_byte_array(&iter_dict, "wpaie",
439
ie = wpa_bss_get_ie(bss, WLAN_EID_RSN);
441
if (!wpa_dbus_dict_append_byte_array(&iter_dict, "rsnie",
447
ie = wpa_bss_get_vendor_ie(bss, WPS_IE_VENDOR_TYPE);
449
if (!wpa_dbus_dict_append_byte_array(&iter_dict, "wpsie",
456
if (!wpa_dbus_dict_append_int32(&iter_dict, "frequency",
460
if (!wpa_dbus_dict_append_uint16(&iter_dict, "capabilities",
463
if (!(bss->flags & WPA_BSS_QUAL_INVALID) &&
464
!wpa_dbus_dict_append_int32(&iter_dict, "quality", bss->qual))
466
if (!(bss->flags & WPA_BSS_NOISE_INVALID) &&
467
!wpa_dbus_dict_append_int32(&iter_dict, "noise", bss->noise))
469
if (!(bss->flags & WPA_BSS_LEVEL_INVALID) &&
470
!wpa_dbus_dict_append_int32(&iter_dict, "level", bss->level))
472
if (!wpa_dbus_dict_append_int32(&iter_dict, "maxrate",
473
wpa_bss_get_max_rate(bss) * 500000))
476
if (!wpa_dbus_dict_close_write(&iter, &iter_dict))
483
dbus_message_unref(reply);
484
return dbus_message_new_error(message, WPAS_ERROR_INTERNAL_ERROR,
485
"an internal error occurred returning "
486
"BSSID properties.");
491
* wpas_dbus_iface_capabilities - Return interface capabilities
492
* @message: Pointer to incoming dbus message
493
* @wpa_s: wpa_supplicant structure for a network interface
494
* Returns: A dbus message containing a dict of strings
496
* Handler function for "capabilities" method call of an interface.
498
DBusMessage * wpas_dbus_iface_capabilities(DBusMessage *message,
499
struct wpa_supplicant *wpa_s)
501
DBusMessage *reply = NULL;
502
struct wpa_driver_capa capa;
504
DBusMessageIter iter, iter_dict;
507
dbus_bool_t strict = FALSE;
508
DBusMessageIter iter_dict_entry, iter_dict_val, iter_array;
510
if (!dbus_message_get_args(message, NULL,
511
DBUS_TYPE_BOOLEAN, &strict,
515
reply = dbus_message_new_method_return(message);
517
dbus_message_iter_init_append(reply, &iter);
518
if (!wpa_dbus_dict_open_write(&iter, &iter_dict))
522
eap_methods = eap_get_names_as_string_array(&num_items);
524
dbus_bool_t success = FALSE;
527
success = wpa_dbus_dict_append_string_array(
528
&iter_dict, "eap", (const char **) eap_methods,
531
/* free returned method array */
532
while (eap_methods[i])
533
os_free(eap_methods[i++]);
534
os_free(eap_methods);
540
res = wpa_drv_get_capa(wpa_s, &capa);
542
/***** pairwise cipher */
545
const char *args[] = {"CCMP", "TKIP", "NONE"};
546
if (!wpa_dbus_dict_append_string_array(
547
&iter_dict, "pairwise", args,
548
sizeof(args) / sizeof(char*)))
552
if (!wpa_dbus_dict_begin_string_array(&iter_dict, "pairwise",
558
if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
559
if (!wpa_dbus_dict_string_array_add_element(
560
&iter_array, "CCMP"))
564
if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
565
if (!wpa_dbus_dict_string_array_add_element(
566
&iter_array, "TKIP"))
570
if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
571
if (!wpa_dbus_dict_string_array_add_element(
572
&iter_array, "NONE"))
576
if (!wpa_dbus_dict_end_string_array(&iter_dict,
583
/***** group cipher */
586
const char *args[] = {
587
"CCMP", "TKIP", "WEP104", "WEP40"
589
if (!wpa_dbus_dict_append_string_array(
590
&iter_dict, "group", args,
591
sizeof(args) / sizeof(char*)))
595
if (!wpa_dbus_dict_begin_string_array(&iter_dict, "group",
601
if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
602
if (!wpa_dbus_dict_string_array_add_element(
603
&iter_array, "CCMP"))
607
if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
608
if (!wpa_dbus_dict_string_array_add_element(
609
&iter_array, "TKIP"))
613
if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) {
614
if (!wpa_dbus_dict_string_array_add_element(
615
&iter_array, "WEP104"))
619
if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) {
620
if (!wpa_dbus_dict_string_array_add_element(
621
&iter_array, "WEP40"))
625
if (!wpa_dbus_dict_end_string_array(&iter_dict,
632
/***** key management */
635
const char *args[] = {
636
"WPA-PSK", "WPA-EAP", "IEEE8021X", "WPA-NONE",
639
if (!wpa_dbus_dict_append_string_array(
640
&iter_dict, "key_mgmt", args,
641
sizeof(args) / sizeof(char*)))
645
if (!wpa_dbus_dict_begin_string_array(&iter_dict, "key_mgmt",
651
if (!wpa_dbus_dict_string_array_add_element(&iter_array,
655
if (!wpa_dbus_dict_string_array_add_element(&iter_array,
659
if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
660
WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
661
if (!wpa_dbus_dict_string_array_add_element(
662
&iter_array, "WPA-EAP"))
666
if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
667
WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
668
if (!wpa_dbus_dict_string_array_add_element(
669
&iter_array, "WPA-PSK"))
673
if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
674
if (!wpa_dbus_dict_string_array_add_element(
675
&iter_array, "WPA-NONE"))
679
if (!wpa_dbus_dict_end_string_array(&iter_dict,
686
/***** WPA protocol */
689
const char *args[] = { "RSN", "WPA" };
690
if (!wpa_dbus_dict_append_string_array(
691
&iter_dict, "proto", args,
692
sizeof(args) / sizeof(char*)))
696
if (!wpa_dbus_dict_begin_string_array(&iter_dict, "proto",
702
if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
703
WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
704
if (!wpa_dbus_dict_string_array_add_element(
709
if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
710
WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
711
if (!wpa_dbus_dict_string_array_add_element(
716
if (!wpa_dbus_dict_end_string_array(&iter_dict,
726
const char *args[] = { "OPEN", "SHARED", "LEAP" };
727
if (!wpa_dbus_dict_append_string_array(
728
&iter_dict, "auth_alg", args,
729
sizeof(args) / sizeof(char*)))
733
if (!wpa_dbus_dict_begin_string_array(&iter_dict, "auth_alg",
739
if (capa.auth & (WPA_DRIVER_AUTH_OPEN)) {
740
if (!wpa_dbus_dict_string_array_add_element(
741
&iter_array, "OPEN"))
745
if (capa.auth & (WPA_DRIVER_AUTH_SHARED)) {
746
if (!wpa_dbus_dict_string_array_add_element(
747
&iter_array, "SHARED"))
751
if (capa.auth & (WPA_DRIVER_AUTH_LEAP)) {
752
if (!wpa_dbus_dict_string_array_add_element(
753
&iter_array, "LEAP"))
757
if (!wpa_dbus_dict_end_string_array(&iter_dict,
764
if (!wpa_dbus_dict_close_write(&iter, &iter_dict))
771
dbus_message_unref(reply);
772
return dbus_message_new_error(message, WPAS_ERROR_INTERNAL_ERROR,
773
"an internal error occurred returning "
774
"interface capabilities.");
779
* wpas_dbus_iface_add_network - Add a new configured network
780
* @message: Pointer to incoming dbus message
781
* @wpa_s: wpa_supplicant structure for a network interface
782
* Returns: A dbus message containing the object path of the new network
784
* Handler function for "addNetwork" method call of a network interface.
786
DBusMessage * wpas_dbus_iface_add_network(DBusMessage *message,
787
struct wpa_supplicant *wpa_s)
789
DBusMessage *reply = NULL;
790
struct wpa_ssid *ssid;
791
char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf;
793
ssid = wpa_config_add_network(wpa_s->conf);
795
reply = dbus_message_new_error(message,
796
WPAS_ERROR_ADD_NETWORK_ERROR,
797
"wpa_supplicant could not add "
798
"a network on this interface.");
801
wpas_notify_network_added(wpa_s, ssid);
803
wpa_config_set_network_defaults(ssid);
805
/* Construct the object path for this network. */
806
os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
807
"%s/" WPAS_DBUS_NETWORKS_PART "/%d",
808
wpa_s->dbus_path, ssid->id);
810
reply = dbus_message_new_method_return(message);
811
dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH,
812
&path, DBUS_TYPE_INVALID);
820
* wpas_dbus_iface_remove_network - Remove a configured network
821
* @message: Pointer to incoming dbus message
822
* @wpa_s: wpa_supplicant structure for a network interface
823
* Returns: A dbus message containing a UINT32 indicating success (1) or
826
* Handler function for "removeNetwork" method call of a network interface.
828
DBusMessage * wpas_dbus_iface_remove_network(DBusMessage *message,
829
struct wpa_supplicant *wpa_s)
831
DBusMessage *reply = NULL;
833
char *iface = NULL, *net_id = NULL;
835
struct wpa_ssid *ssid;
837
if (!dbus_message_get_args(message, NULL,
838
DBUS_TYPE_OBJECT_PATH, &op,
839
DBUS_TYPE_INVALID)) {
840
reply = wpas_dbus_new_invalid_opts_error(message, NULL);
844
/* Extract the network ID */
845
iface = wpas_dbus_decompose_object_path(op, &net_id, NULL);
847
reply = wpas_dbus_new_invalid_network_error(message);
851
/* Ensure the network is actually a child of this interface */
852
if (os_strcmp(iface, wpa_s->dbus_path) != 0) {
853
reply = wpas_dbus_new_invalid_network_error(message);
857
id = strtoul(net_id, NULL, 10);
858
ssid = wpa_config_get_network(wpa_s->conf, id);
860
reply = wpas_dbus_new_invalid_network_error(message);
864
wpas_notify_network_removed(wpa_s, ssid);
866
if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
867
reply = dbus_message_new_error(message,
868
WPAS_ERROR_REMOVE_NETWORK_ERROR,
869
"error removing the specified "
870
"on this interface.");
874
if (ssid == wpa_s->current_ssid)
875
wpa_supplicant_deauthenticate(wpa_s,
876
WLAN_REASON_DEAUTH_LEAVING);
877
reply = wpas_dbus_new_success_reply(message);
886
static const char *dont_quote[] = {
887
"key_mgmt", "proto", "pairwise", "auth_alg", "group", "eap",
888
"opensc_engine_path", "pkcs11_engine_path", "pkcs11_module_path",
893
static dbus_bool_t should_quote_opt(const char *key)
896
while (dont_quote[i] != NULL) {
897
if (strcmp(key, dont_quote[i]) == 0)
906
* wpas_dbus_iface_set_network - Set options for a configured network
907
* @message: Pointer to incoming dbus message
908
* @wpa_s: wpa_supplicant structure for a network interface
909
* @ssid: wpa_ssid structure for a configured network
910
* Returns: a dbus message containing a UINT32 indicating success (1) or
913
* Handler function for "set" method call of a configured network.
915
DBusMessage * wpas_dbus_iface_set_network(DBusMessage *message,
916
struct wpa_supplicant *wpa_s,
917
struct wpa_ssid *ssid)
919
DBusMessage *reply = NULL;
920
struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
921
DBusMessageIter iter, iter_dict;
923
dbus_message_iter_init(message, &iter);
925
if (!wpa_dbus_dict_open_read(&iter, &iter_dict)) {
926
reply = wpas_dbus_new_invalid_opts_error(message, NULL);
930
while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
935
if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) {
936
reply = wpas_dbus_new_invalid_opts_error(message,
941
/* Type conversions, since wpa_supplicant wants strings */
942
if (entry.type == DBUS_TYPE_ARRAY &&
943
entry.array_type == DBUS_TYPE_BYTE) {
944
if (entry.array_len <= 0)
947
size = entry.array_len * 2 + 1;
948
value = os_zalloc(size);
951
ret = wpa_snprintf_hex(value, size,
952
(u8 *) entry.bytearray_value,
956
} else if (entry.type == DBUS_TYPE_STRING) {
957
if (should_quote_opt(entry.key)) {
958
size = os_strlen(entry.str_value);
959
/* Zero-length option check */
962
size += 3; /* For quotes and terminator */
963
value = os_zalloc(size);
966
ret = os_snprintf(value, size, "\"%s\"",
968
if (ret < 0 || (size_t) ret != (size - 1))
971
value = os_strdup(entry.str_value);
975
} else if (entry.type == DBUS_TYPE_UINT32) {
976
value = os_zalloc(size);
979
ret = os_snprintf(value, size, "%u",
983
} else if (entry.type == DBUS_TYPE_INT32) {
984
value = os_zalloc(size);
987
ret = os_snprintf(value, size, "%d",
994
if (wpa_config_set(ssid, entry.key, value, 0) < 0)
997
if ((os_strcmp(entry.key, "psk") == 0 &&
998
value[0] == '"' && ssid->ssid_len) ||
999
(os_strcmp(entry.key, "ssid") == 0 && ssid->passphrase))
1000
wpa_config_update_psk(ssid);
1001
else if (os_strcmp(entry.key, "priority") == 0)
1002
wpa_config_update_prio_list(wpa_s->conf);
1005
wpa_dbus_dict_entry_clear(&entry);
1010
reply = wpas_dbus_new_invalid_opts_error(message, entry.key);
1011
wpa_dbus_dict_entry_clear(&entry);
1016
reply = wpas_dbus_new_success_reply(message);
1024
* wpas_dbus_iface_enable_network - Mark a configured network as enabled
1025
* @message: Pointer to incoming dbus message
1026
* @wpa_s: wpa_supplicant structure for a network interface
1027
* @ssid: wpa_ssid structure for a configured network
1028
* Returns: A dbus message containing a UINT32 indicating success (1) or
1031
* Handler function for "enable" method call of a configured network.
1033
DBusMessage * wpas_dbus_iface_enable_network(DBusMessage *message,
1034
struct wpa_supplicant *wpa_s,
1035
struct wpa_ssid *ssid)
1037
wpa_supplicant_enable_network(wpa_s, ssid);
1038
return wpas_dbus_new_success_reply(message);
1043
* wpas_dbus_iface_disable_network - Mark a configured network as disabled
1044
* @message: Pointer to incoming dbus message
1045
* @wpa_s: wpa_supplicant structure for a network interface
1046
* @ssid: wpa_ssid structure for a configured network
1047
* Returns: A dbus message containing a UINT32 indicating success (1) or
1050
* Handler function for "disable" method call of a configured network.
1052
DBusMessage * wpas_dbus_iface_disable_network(DBusMessage *message,
1053
struct wpa_supplicant *wpa_s,
1054
struct wpa_ssid *ssid)
1056
wpa_supplicant_disable_network(wpa_s, ssid);
1057
return wpas_dbus_new_success_reply(message);
1062
* wpas_dbus_iface_select_network - Attempt association with a configured network
1063
* @message: Pointer to incoming dbus message
1064
* @wpa_s: wpa_supplicant structure for a network interface
1065
* Returns: A dbus message containing a UINT32 indicating success (1) or
1068
* Handler function for "selectNetwork" method call of network interface.
1070
DBusMessage * wpas_dbus_iface_select_network(DBusMessage *message,
1071
struct wpa_supplicant *wpa_s)
1073
DBusMessage *reply = NULL;
1075
struct wpa_ssid *ssid;
1076
char *iface_obj_path = NULL;
1077
char *network = NULL;
1079
if (os_strlen(dbus_message_get_signature(message)) == 0) {
1085
if (!dbus_message_get_args(message, NULL,
1086
DBUS_TYPE_OBJECT_PATH, &op,
1087
DBUS_TYPE_INVALID)) {
1088
reply = wpas_dbus_new_invalid_opts_error(message,
1093
/* Extract the network number */
1094
iface_obj_path = wpas_dbus_decompose_object_path(op,
1097
if (iface_obj_path == NULL) {
1098
reply = wpas_dbus_new_invalid_iface_error(message);
1101
/* Ensure the object path really points to this interface */
1102
if (os_strcmp(iface_obj_path, wpa_s->dbus_path) != 0) {
1103
reply = wpas_dbus_new_invalid_network_error(message);
1107
nid = strtoul(network, NULL, 10);
1108
if (errno == EINVAL) {
1109
reply = wpas_dbus_new_invalid_network_error(message);
1113
ssid = wpa_config_get_network(wpa_s->conf, nid);
1115
reply = wpas_dbus_new_invalid_network_error(message);
1120
/* Finally, associate with the network */
1121
wpa_supplicant_select_network(wpa_s, ssid);
1123
reply = wpas_dbus_new_success_reply(message);
1126
os_free(iface_obj_path);
1133
* wpas_dbus_iface_disconnect - Terminate the current connection
1134
* @message: Pointer to incoming dbus message
1135
* @wpa_s: wpa_supplicant structure for a network interface
1136
* Returns: A dbus message containing a UINT32 indicating success (1) or
1139
* Handler function for "disconnect" method call of network interface.
1141
DBusMessage * wpas_dbus_iface_disconnect(DBusMessage *message,
1142
struct wpa_supplicant *wpa_s)
1144
wpa_s->disconnected = 1;
1145
wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1147
return wpas_dbus_new_success_reply(message);
1152
* wpas_dbus_iface_set_ap_scan - Control roaming mode
1153
* @message: Pointer to incoming dbus message
1154
* @wpa_s: wpa_supplicant structure for a network interface
1155
* Returns: A dbus message containing a UINT32 indicating success (1) or
1158
* Handler function for "setAPScan" method call.
1160
DBusMessage * wpas_dbus_iface_set_ap_scan(DBusMessage *message,
1161
struct wpa_supplicant *wpa_s)
1163
DBusMessage *reply = NULL;
1164
dbus_uint32_t ap_scan = 1;
1166
if (!dbus_message_get_args(message, NULL, DBUS_TYPE_UINT32, &ap_scan,
1167
DBUS_TYPE_INVALID)) {
1168
reply = wpas_dbus_new_invalid_opts_error(message, NULL);
1172
if (wpa_supplicant_set_ap_scan(wpa_s, ap_scan)) {
1173
reply = wpas_dbus_new_invalid_opts_error(message, NULL);
1177
reply = wpas_dbus_new_success_reply(message);
1185
* wpas_dbus_iface_set_smartcard_modules - Set smartcard related module paths
1186
* @message: Pointer to incoming dbus message
1187
* @wpa_s: wpa_supplicant structure for a network interface
1188
* Returns: A dbus message containing a UINT32 indicating success (1) or
1191
* Handler function for "setSmartcardModules" method call.
1193
DBusMessage * wpas_dbus_iface_set_smartcard_modules(
1194
DBusMessage *message, struct wpa_supplicant *wpa_s)
1196
DBusMessageIter iter, iter_dict;
1197
char *opensc_engine_path = NULL;
1198
char *pkcs11_engine_path = NULL;
1199
char *pkcs11_module_path = NULL;
1200
struct wpa_dbus_dict_entry entry;
1202
if (!dbus_message_iter_init(message, &iter))
1205
if (!wpa_dbus_dict_open_read(&iter, &iter_dict))
1208
while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
1209
if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
1211
if (!strcmp(entry.key, "opensc_engine_path") &&
1212
(entry.type == DBUS_TYPE_STRING)) {
1213
opensc_engine_path = os_strdup(entry.str_value);
1214
if (opensc_engine_path == NULL)
1216
} else if (!strcmp(entry.key, "pkcs11_engine_path") &&
1217
(entry.type == DBUS_TYPE_STRING)) {
1218
pkcs11_engine_path = os_strdup(entry.str_value);
1219
if (pkcs11_engine_path == NULL)
1221
} else if (!strcmp(entry.key, "pkcs11_module_path") &&
1222
(entry.type == DBUS_TYPE_STRING)) {
1223
pkcs11_module_path = os_strdup(entry.str_value);
1224
if (pkcs11_module_path == NULL)
1227
wpa_dbus_dict_entry_clear(&entry);
1230
wpa_dbus_dict_entry_clear(&entry);
1233
os_free(wpa_s->conf->opensc_engine_path);
1234
wpa_s->conf->opensc_engine_path = opensc_engine_path;
1235
os_free(wpa_s->conf->pkcs11_engine_path);
1236
wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path;
1237
os_free(wpa_s->conf->pkcs11_module_path);
1238
wpa_s->conf->pkcs11_module_path = pkcs11_module_path;
1240
wpa_sm_set_eapol(wpa_s->wpa, NULL);
1241
eapol_sm_deinit(wpa_s->eapol);
1242
wpa_s->eapol = NULL;
1243
wpa_supplicant_init_eapol(wpa_s);
1244
wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
1246
return wpas_dbus_new_success_reply(message);
1249
os_free(opensc_engine_path);
1250
os_free(pkcs11_engine_path);
1251
os_free(pkcs11_module_path);
1252
return wpas_dbus_new_invalid_opts_error(message, NULL);
1257
* wpas_dbus_iface_get_state - Get interface state
1258
* @message: Pointer to incoming dbus message
1259
* @wpa_s: wpa_supplicant structure for a network interface
1260
* Returns: A dbus message containing a STRING representing the current
1263
* Handler function for "state" method call.
1265
DBusMessage * wpas_dbus_iface_get_state(DBusMessage *message,
1266
struct wpa_supplicant *wpa_s)
1268
DBusMessage *reply = NULL;
1269
const char *str_state;
1271
reply = dbus_message_new_method_return(message);
1272
if (reply != NULL) {
1273
str_state = wpa_supplicant_state_txt(wpa_s->wpa_state);
1274
dbus_message_append_args(reply, DBUS_TYPE_STRING, &str_state,
1283
* wpas_dbus_iface_get_scanning - Get interface scanning state
1284
* @message: Pointer to incoming dbus message
1285
* @wpa_s: wpa_supplicant structure for a network interface
1286
* Returns: A dbus message containing whether the interface is scanning
1288
* Handler function for "scanning" method call.
1290
DBusMessage * wpas_dbus_iface_get_scanning(DBusMessage *message,
1291
struct wpa_supplicant *wpa_s)
1293
DBusMessage *reply = NULL;
1294
dbus_bool_t scanning = wpa_s->scanning ? TRUE : FALSE;
1296
reply = dbus_message_new_method_return(message);
1297
if (reply != NULL) {
1298
dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &scanning,
1301
wpa_printf(MSG_ERROR, "dbus: Not enough memory to return "
1310
* wpas_dbus_iface_set_blobs - Store named binary blobs (ie, for certificates)
1311
* @message: Pointer to incoming dbus message
1312
* @wpa_s: %wpa_supplicant data structure
1313
* Returns: A dbus message containing a UINT32 indicating success (1) or
1316
* Asks wpa_supplicant to internally store a one or more binary blobs.
1318
DBusMessage * wpas_dbus_iface_set_blobs(DBusMessage *message,
1319
struct wpa_supplicant *wpa_s)
1321
DBusMessage *reply = NULL;
1322
struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
1323
DBusMessageIter iter, iter_dict;
1325
dbus_message_iter_init(message, &iter);
1327
if (!wpa_dbus_dict_open_read(&iter, &iter_dict))
1328
return wpas_dbus_new_invalid_opts_error(message, NULL);
1330
while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
1331
struct wpa_config_blob *blob;
1333
if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) {
1334
reply = wpas_dbus_new_invalid_opts_error(message,
1339
if (entry.type != DBUS_TYPE_ARRAY ||
1340
entry.array_type != DBUS_TYPE_BYTE) {
1341
reply = wpas_dbus_new_invalid_opts_error(
1342
message, "Byte array expected.");
1346
if ((entry.array_len <= 0) || (entry.array_len > 65536) ||
1347
!strlen(entry.key)) {
1348
reply = wpas_dbus_new_invalid_opts_error(
1349
message, "Invalid array size.");
1353
blob = os_zalloc(sizeof(*blob));
1355
reply = dbus_message_new_error(
1356
message, WPAS_ERROR_ADD_ERROR,
1357
"Not enough memory to add blob.");
1360
blob->data = os_zalloc(entry.array_len);
1361
if (blob->data == NULL) {
1362
reply = dbus_message_new_error(
1363
message, WPAS_ERROR_ADD_ERROR,
1364
"Not enough memory to add blob data.");
1369
blob->name = os_strdup(entry.key);
1370
blob->len = entry.array_len;
1371
os_memcpy(blob->data, (u8 *) entry.bytearray_value,
1373
if (blob->name == NULL || blob->data == NULL) {
1374
wpa_config_free_blob(blob);
1375
reply = dbus_message_new_error(
1376
message, WPAS_ERROR_ADD_ERROR,
1377
"Error adding blob.");
1382
if (!wpa_config_remove_blob(wpa_s->conf, blob->name))
1383
wpas_notify_blob_removed(wpa_s, blob->name);
1384
wpa_config_set_blob(wpa_s->conf, blob);
1385
wpas_notify_blob_added(wpa_s, blob->name);
1387
wpa_dbus_dict_entry_clear(&entry);
1389
wpa_dbus_dict_entry_clear(&entry);
1391
return reply ? reply : wpas_dbus_new_success_reply(message);
1396
* wpas_dbus_iface_remove_blob - Remove named binary blobs
1397
* @message: Pointer to incoming dbus message
1398
* @wpa_s: %wpa_supplicant data structure
1399
* Returns: A dbus message containing a UINT32 indicating success (1) or
1402
* Asks wpa_supplicant to remove one or more previously stored binary blobs.
1404
DBusMessage * wpas_dbus_iface_remove_blobs(DBusMessage *message,
1405
struct wpa_supplicant *wpa_s)
1407
DBusMessageIter iter, array;
1408
char *err_msg = NULL;
1410
dbus_message_iter_init(message, &iter);
1412
if ((dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY) ||
1413
(dbus_message_iter_get_element_type (&iter) != DBUS_TYPE_STRING))
1414
return wpas_dbus_new_invalid_opts_error(message, NULL);
1416
dbus_message_iter_recurse(&iter, &array);
1417
while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRING) {
1420
dbus_message_iter_get_basic(&array, &name);
1421
if (!os_strlen(name))
1422
err_msg = "Invalid blob name.";
1424
if (wpa_config_remove_blob(wpa_s->conf, name) != 0)
1425
err_msg = "Error removing blob.";
1427
wpas_notify_blob_removed(wpa_s, name);
1428
dbus_message_iter_next(&array);
1432
return dbus_message_new_error(message, WPAS_ERROR_REMOVE_ERROR,
1435
return wpas_dbus_new_success_reply(message);