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.
19
#include "wpa_supplicant_i.h"
20
#include "ctrl_iface_dbus.h"
21
#include "ctrl_iface_dbus_handlers.h"
22
#include "eap_peer/eap_methods.h"
23
#include "dbus_dict_helpers.h"
24
#include "ieee802_11_defs.h"
28
* wpas_dbus_new_invalid_opts_error - Return a new invalid options error message
29
* @message: Pointer to incoming dbus message this error refers to
30
* Returns: a dbus error message
32
* Convenience function to create and return an invalid options error
34
static DBusMessage * wpas_dbus_new_invalid_opts_error(DBusMessage *message,
39
reply = dbus_message_new_error(message, WPAS_ERROR_INVALID_OPTS,
40
"Did not receive correct message "
43
dbus_message_append_args(reply, DBUS_TYPE_STRING, &arg,
51
* wpas_dbus_new_success_reply - Return a new success reply message
52
* @message: Pointer to incoming dbus message this reply refers to
53
* Returns: a dbus message containing a single UINT32 that indicates
54
* success (ie, a value of 1)
56
* Convenience function to create and return a success reply message
58
static DBusMessage * wpas_dbus_new_success_reply(DBusMessage *message)
61
unsigned int success = 1;
63
reply = dbus_message_new_method_return(message);
64
dbus_message_append_args(reply, DBUS_TYPE_UINT32, &success,
70
static void wpas_dbus_free_wpa_interface(struct wpa_interface *iface)
72
free((char *) iface->driver);
73
free((char *) iface->driver_param);
74
free((char *) iface->confname);
75
free((char *) iface->bridge_ifname);
80
* wpas_dbus_global_add_interface - Request registration of a network interface
81
* @message: Pointer to incoming dbus message
82
* @global: %wpa_supplicant global data structure
83
* Returns: The object path of the new interface object,
84
* or a dbus error message with more information
86
* Handler function for "addInterface" method call. Handles requests
87
* by dbus clients to register a network interface that wpa_supplicant
90
DBusMessage * wpas_dbus_global_add_interface(DBusMessage *message,
91
struct wpa_global *global)
93
struct wpa_interface iface;
95
DBusMessage *reply = NULL;
98
memset(&iface, 0, sizeof(iface));
100
dbus_message_iter_init(message, &iter);
102
/* First argument: interface name (DBUS_TYPE_STRING)
103
* Required; must be non-zero length
105
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
107
dbus_message_iter_get_basic(&iter, &ifname);
110
iface.ifname = ifname;
112
/* Second argument: dict of options */
113
if (dbus_message_iter_next(&iter)) {
114
DBusMessageIter iter_dict;
115
struct wpa_dbus_dict_entry entry;
117
if (!wpa_dbus_dict_open_read(&iter, &iter_dict))
119
while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
120
if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
122
if (!strcmp(entry.key, "driver") &&
123
(entry.type == DBUS_TYPE_STRING)) {
124
iface.driver = strdup(entry.str_value);
125
if (iface.driver == NULL)
127
} else if (!strcmp(entry.key, "driver-params") &&
128
(entry.type == DBUS_TYPE_STRING)) {
129
iface.driver_param = strdup(entry.str_value);
130
if (iface.driver_param == NULL)
132
} else if (!strcmp(entry.key, "config-file") &&
133
(entry.type == DBUS_TYPE_STRING)) {
134
iface.confname = strdup(entry.str_value);
135
if (iface.confname == NULL)
137
} else if (!strcmp(entry.key, "bridge-ifname") &&
138
(entry.type == DBUS_TYPE_STRING)) {
139
iface.bridge_ifname = strdup(entry.str_value);
140
if (iface.bridge_ifname == NULL)
143
wpa_dbus_dict_entry_clear(&entry);
146
wpa_dbus_dict_entry_clear(&entry);
151
* Try to get the wpa_supplicant record for this iface, return
152
* an error if we already control it.
154
if (wpa_supplicant_get_iface(global, iface.ifname) != 0) {
155
reply = dbus_message_new_error(message,
156
WPAS_ERROR_EXISTS_ERROR,
157
"wpa_supplicant already "
158
"controls this interface.");
160
struct wpa_supplicant *wpa_s;
161
/* Otherwise, have wpa_supplicant attach to it. */
162
if ((wpa_s = wpa_supplicant_add_iface(global, &iface))) {
163
const char *path = wpa_supplicant_get_dbus_path(wpa_s);
164
reply = dbus_message_new_method_return(message);
165
dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH,
166
&path, DBUS_TYPE_INVALID);
168
reply = dbus_message_new_error(message,
169
WPAS_ERROR_ADD_ERROR,
171
"couldn't grab this "
175
wpas_dbus_free_wpa_interface(&iface);
179
wpas_dbus_free_wpa_interface(&iface);
180
return wpas_dbus_new_invalid_opts_error(message, NULL);
185
* wpas_dbus_global_remove_interface - Request deregistration of an interface
186
* @message: Pointer to incoming dbus message
187
* @global: wpa_supplicant global data structure
188
* Returns: a dbus message containing a UINT32 indicating success (1) or
189
* failure (0), or returns a dbus error message with more information
191
* Handler function for "removeInterface" method call. Handles requests
192
* by dbus clients to deregister a network interface that wpa_supplicant
195
DBusMessage * wpas_dbus_global_remove_interface(DBusMessage *message,
196
struct wpa_global *global)
198
struct wpa_supplicant *wpa_s;
200
DBusMessage *reply = NULL;
202
if (!dbus_message_get_args(message, NULL,
203
DBUS_TYPE_OBJECT_PATH, &path,
204
DBUS_TYPE_INVALID)) {
205
reply = wpas_dbus_new_invalid_opts_error(message, NULL);
209
wpa_s = wpa_supplicant_get_iface_by_dbus_path(global, path);
211
reply = wpas_dbus_new_invalid_iface_error(message);
215
if (!wpa_supplicant_remove_iface(global, wpa_s)) {
216
reply = wpas_dbus_new_success_reply(message);
218
reply = dbus_message_new_error(message,
219
WPAS_ERROR_REMOVE_ERROR,
220
"wpa_supplicant couldn't "
221
"remove this interface.");
230
* wpas_dbus_global_get_interface - Get the object path for an interface name
231
* @message: Pointer to incoming dbus message
232
* @global: %wpa_supplicant global data structure
233
* Returns: The object path of the interface object,
234
* or a dbus error message with more information
236
* Handler function for "getInterface" method call. Handles requests
237
* by dbus clients for the object path of an specific network interface.
239
DBusMessage * wpas_dbus_global_get_interface(DBusMessage *message,
240
struct wpa_global *global)
242
DBusMessage *reply = NULL;
245
struct wpa_supplicant *wpa_s;
247
if (!dbus_message_get_args(message, NULL,
248
DBUS_TYPE_STRING, &ifname,
249
DBUS_TYPE_INVALID)) {
250
reply = wpas_dbus_new_invalid_opts_error(message, NULL);
254
wpa_s = wpa_supplicant_get_iface(global, ifname);
256
reply = wpas_dbus_new_invalid_iface_error(message);
260
path = wpa_supplicant_get_dbus_path(wpa_s);
262
reply = dbus_message_new_error(message,
263
WPAS_ERROR_INTERNAL_ERROR,
264
"an internal error occurred "
265
"getting the interface.");
269
reply = dbus_message_new_method_return(message);
270
dbus_message_append_args(reply,
271
DBUS_TYPE_OBJECT_PATH, &path,
280
* wpas_dbus_iface_scan - Request a wireless scan on an interface
281
* @message: Pointer to incoming dbus message
282
* @wpa_s: wpa_supplicant structure for a network interface
283
* Returns: a dbus message containing a UINT32 indicating success (1) or
286
* Handler function for "scan" method call of a network device. Requests
287
* that wpa_supplicant perform a wireless scan as soon as possible
288
* on a particular wireless interface.
290
DBusMessage * wpas_dbus_iface_scan(DBusMessage *message,
291
struct wpa_supplicant *wpa_s)
294
wpa_supplicant_req_scan(wpa_s, 0, 0);
295
return wpas_dbus_new_success_reply(message);
300
* wpas_dbus_iface_scan_results - Get the results of a recent scan request
301
* @message: Pointer to incoming dbus message
302
* @wpa_s: wpa_supplicant structure for a network interface
303
* Returns: a dbus message containing a dbus array of objects paths, or returns
304
* a dbus error message if not scan results could be found
306
* Handler function for "scanResults" method call of a network device. Returns
307
* a dbus message containing the object paths of wireless networks found.
309
DBusMessage * wpas_dbus_iface_scan_results(DBusMessage *message,
310
struct wpa_supplicant *wpa_s)
312
DBusMessage *reply = NULL;
313
DBusMessageIter iter;
314
DBusMessageIter sub_iter;
317
/* Ensure we've actually got scan results to return */
318
if (wpa_s->scan_results == NULL &&
319
wpa_supplicant_get_scan_results(wpa_s) < 0) {
320
reply = dbus_message_new_error(message, WPAS_ERROR_SCAN_ERROR,
321
"An error ocurred getting scan "
326
/* Create and initialize the return message */
327
reply = dbus_message_new_method_return(message);
328
dbus_message_iter_init_append(reply, &iter);
329
dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
330
DBUS_TYPE_OBJECT_PATH_AS_STRING,
333
/* Loop through scan results and append each result's object path */
334
for (i = 0; i < wpa_s->num_scan_results; i++) {
335
struct wpa_scan_result *res = &wpa_s->scan_results[i];
338
path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
340
perror("wpas_dbus_iface_scan_results[dbus]: out of "
342
wpa_printf(MSG_ERROR, "dbus control interface: not "
343
"enough memory to send scan results "
347
/* Construct the object path for this network. Note that ':'
348
* is not a valid character in dbus object paths.
350
snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
351
"%s/" WPAS_DBUS_BSSIDS_PART "/"
352
WPAS_DBUS_BSSID_FORMAT,
353
wpa_supplicant_get_dbus_path(wpa_s),
354
MAC2STR(res->bssid));
355
dbus_message_iter_append_basic(&sub_iter,
356
DBUS_TYPE_OBJECT_PATH, &path);
360
dbus_message_iter_close_container(&iter, &sub_iter);
368
* wpas_dbus_bssid_properties - Return the properties of a scanned network
369
* @message: Pointer to incoming dbus message
370
* @wpa_s: wpa_supplicant structure for a network interface
371
* @res: wpa_supplicant scan result for which to get properties
372
* Returns: a dbus message containing the properties for the requested network
374
* Handler function for "properties" method call of a scanned network.
375
* Returns a dbus message containing the the properties.
377
DBusMessage * wpas_dbus_bssid_properties(DBusMessage *message,
378
struct wpa_supplicant *wpa_s,
379
struct wpa_scan_result *res)
381
DBusMessage *reply = NULL;
382
char *bssid_data, *ssid_data, *wpa_ie_data, *rsn_ie_data;
383
DBusMessageIter iter, iter_dict;
385
/* dbus needs the address of a pointer to the actual value
386
* for array types, not the address of the value itself.
388
bssid_data = (char *) &res->bssid;
389
ssid_data = (char *) &res->ssid;
390
wpa_ie_data = (char *) &res->wpa_ie;
391
rsn_ie_data = (char *) &res->rsn_ie;
393
/* Dump the properties into a dbus message */
394
reply = dbus_message_new_method_return(message);
396
dbus_message_iter_init_append(reply, &iter);
397
if (!wpa_dbus_dict_open_write(&iter, &iter_dict))
400
if (!wpa_dbus_dict_append_byte_array(&iter_dict, "bssid",
401
bssid_data, ETH_ALEN))
403
if (!wpa_dbus_dict_append_byte_array(&iter_dict, "ssid",
404
ssid_data, res->ssid_len))
406
if (res->wpa_ie_len) {
407
if (!wpa_dbus_dict_append_byte_array(&iter_dict, "wpaie",
413
if (res->rsn_ie_len) {
414
if (!wpa_dbus_dict_append_byte_array(&iter_dict, "rsnie",
421
if (!wpa_dbus_dict_append_int32(&iter_dict, "frequency",
425
if (!wpa_dbus_dict_append_uint16(&iter_dict, "capabilities",
428
if (!wpa_dbus_dict_append_int32(&iter_dict, "quality", res->qual))
430
if (!wpa_dbus_dict_append_int32(&iter_dict, "noise", res->noise))
432
if (!wpa_dbus_dict_append_int32(&iter_dict, "level", res->level))
434
if (!wpa_dbus_dict_append_int32(&iter_dict, "maxrate", res->maxrate))
437
if (!wpa_dbus_dict_close_write(&iter, &iter_dict))
444
dbus_message_unref(reply);
445
return dbus_message_new_error(message, WPAS_ERROR_INTERNAL_ERROR,
446
"an internal error occurred returning "
447
"BSSID properties.");
452
* wpas_dbus_iface_capabilities - Return interface capabilities
453
* @message: Pointer to incoming dbus message
454
* @wpa_s: wpa_supplicant structure for a network interface
455
* Returns: A dbus message containing a dict of strings
457
* Handler function for "capabilities" method call of an interface.
459
DBusMessage * wpas_dbus_iface_capabilities(DBusMessage *message,
460
struct wpa_supplicant *wpa_s)
462
DBusMessage *reply = NULL;
463
struct wpa_driver_capa capa;
465
DBusMessageIter iter, iter_dict;
468
dbus_bool_t strict = FALSE;
469
DBusMessageIter iter_dict_entry, iter_dict_val, iter_array;
471
if (!dbus_message_get_args(message, NULL,
472
DBUS_TYPE_BOOLEAN, &strict,
476
reply = dbus_message_new_method_return(message);
478
dbus_message_iter_init_append(reply, &iter);
479
if (!wpa_dbus_dict_open_write(&iter, &iter_dict))
483
eap_methods = eap_get_names_as_string_array(&num_items);
485
dbus_bool_t success = FALSE;
488
success = wpa_dbus_dict_append_string_array(
489
&iter_dict, "eap", (const char **) eap_methods,
492
/* free returned method array */
493
while (eap_methods[i])
494
free(eap_methods[i++]);
501
res = wpa_drv_get_capa(wpa_s, &capa);
503
/***** pairwise cipher */
506
const char *args[] = {"CCMP", "TKIP", "NONE"};
507
if (!wpa_dbus_dict_append_string_array(
508
&iter_dict, "pairwise", args,
509
sizeof(args) / sizeof(char*)))
513
if (!wpa_dbus_dict_begin_string_array(&iter_dict, "pairwise",
519
if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
520
if (!wpa_dbus_dict_string_array_add_element(
521
&iter_array, "CCMP"))
525
if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
526
if (!wpa_dbus_dict_string_array_add_element(
527
&iter_array, "TKIP"))
531
if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
532
if (!wpa_dbus_dict_string_array_add_element(
533
&iter_array, "NONE"))
537
if (!wpa_dbus_dict_end_string_array(&iter_dict,
544
/***** group cipher */
547
const char *args[] = {
548
"CCMP", "TKIP", "WEP104", "WEP40"
550
if (!wpa_dbus_dict_append_string_array(
551
&iter_dict, "group", args,
552
sizeof(args) / sizeof(char*)))
556
if (!wpa_dbus_dict_begin_string_array(&iter_dict, "group",
562
if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
563
if (!wpa_dbus_dict_string_array_add_element(
564
&iter_array, "CCMP"))
568
if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
569
if (!wpa_dbus_dict_string_array_add_element(
570
&iter_array, "TKIP"))
574
if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) {
575
if (!wpa_dbus_dict_string_array_add_element(
576
&iter_array, "WEP104"))
580
if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) {
581
if (!wpa_dbus_dict_string_array_add_element(
582
&iter_array, "WEP40"))
586
if (!wpa_dbus_dict_end_string_array(&iter_dict,
593
/***** key management */
596
const char *args[] = {
597
"WPA-PSK", "WPA-EAP", "IEEE8021X", "WPA-NONE",
600
if (!wpa_dbus_dict_append_string_array(
601
&iter_dict, "key_mgmt", args,
602
sizeof(args) / sizeof(char*)))
606
if (!wpa_dbus_dict_begin_string_array(&iter_dict, "key_mgmt",
612
if (!wpa_dbus_dict_string_array_add_element(&iter_array,
616
if (!wpa_dbus_dict_string_array_add_element(&iter_array,
620
if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
621
WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
622
if (!wpa_dbus_dict_string_array_add_element(
623
&iter_array, "WPA-EAP"))
627
if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
628
WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
629
if (!wpa_dbus_dict_string_array_add_element(
630
&iter_array, "WPA-PSK"))
634
if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
635
if (!wpa_dbus_dict_string_array_add_element(
636
&iter_array, "WPA-NONE"))
640
if (!wpa_dbus_dict_end_string_array(&iter_dict,
647
/***** WPA protocol */
650
const char *args[] = { "RSN", "WPA" };
651
if (!wpa_dbus_dict_append_string_array(
652
&iter_dict, "proto", args,
653
sizeof(args) / sizeof(char*)))
657
if (!wpa_dbus_dict_begin_string_array(&iter_dict, "proto",
663
if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
664
WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
665
if (!wpa_dbus_dict_string_array_add_element(
670
if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
671
WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
672
if (!wpa_dbus_dict_string_array_add_element(
677
if (!wpa_dbus_dict_end_string_array(&iter_dict,
687
const char *args[] = { "OPEN", "SHARED", "LEAP" };
688
if (!wpa_dbus_dict_append_string_array(
689
&iter_dict, "auth_alg", args,
690
sizeof(args) / sizeof(char*)))
694
if (!wpa_dbus_dict_begin_string_array(&iter_dict, "auth_alg",
700
if (capa.auth & (WPA_DRIVER_AUTH_OPEN)) {
701
if (!wpa_dbus_dict_string_array_add_element(
702
&iter_array, "OPEN"))
706
if (capa.auth & (WPA_DRIVER_AUTH_SHARED)) {
707
if (!wpa_dbus_dict_string_array_add_element(
708
&iter_array, "SHARED"))
712
if (capa.auth & (WPA_DRIVER_AUTH_LEAP)) {
713
if (!wpa_dbus_dict_string_array_add_element(
714
&iter_array, "LEAP"))
718
if (!wpa_dbus_dict_end_string_array(&iter_dict,
725
if (!wpa_dbus_dict_close_write(&iter, &iter_dict))
732
dbus_message_unref(reply);
733
return dbus_message_new_error(message, WPAS_ERROR_INTERNAL_ERROR,
734
"an internal error occurred returning "
735
"interface capabilities.");
740
* wpas_dbus_iface_add_network - Add a new configured network
741
* @message: Pointer to incoming dbus message
742
* @wpa_s: wpa_supplicant structure for a network interface
743
* Returns: A dbus message containing the object path of the new network
745
* Handler function for "addNetwork" method call of a network interface.
747
DBusMessage * wpas_dbus_iface_add_network(DBusMessage *message,
748
struct wpa_supplicant *wpa_s)
750
DBusMessage *reply = NULL;
751
struct wpa_ssid *ssid;
754
path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
756
perror("wpas_dbus_iface_scan_results[dbus]: out of "
758
wpa_printf(MSG_ERROR, "dbus control interface: not "
759
"enough memory to send scan results "
764
ssid = wpa_config_add_network(wpa_s->conf);
766
reply = dbus_message_new_error(message,
767
WPAS_ERROR_ADD_NETWORK_ERROR,
768
"wpa_supplicant could not add "
769
"a network on this interface.");
773
wpa_config_set_network_defaults(ssid);
775
/* Construct the object path for this network. */
776
snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
777
"%s/" WPAS_DBUS_NETWORKS_PART "/%d",
778
wpa_supplicant_get_dbus_path(wpa_s),
781
reply = dbus_message_new_method_return(message);
782
dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH,
783
&path, DBUS_TYPE_INVALID);
792
* wpas_dbus_iface_remove_network - Remove a configured network
793
* @message: Pointer to incoming dbus message
794
* @wpa_s: wpa_supplicant structure for a network interface
795
* Returns: A dbus message containing a UINT32 indicating success (1) or
798
* Handler function for "removeNetwork" method call of a network interface.
800
DBusMessage * wpas_dbus_iface_remove_network(DBusMessage *message,
801
struct wpa_supplicant *wpa_s)
803
DBusMessage *reply = NULL;
805
char *iface = NULL, *net_id = NULL;
807
struct wpa_ssid *ssid;
809
if (!dbus_message_get_args(message, NULL,
810
DBUS_TYPE_OBJECT_PATH, &op,
811
DBUS_TYPE_INVALID)) {
812
reply = wpas_dbus_new_invalid_opts_error(message, NULL);
816
/* Extract the network ID */
817
iface = wpas_dbus_decompose_object_path(op, &net_id, NULL);
819
reply = wpas_dbus_new_invalid_network_error(message);
822
/* Ensure the network is actually a child of this interface */
823
if (strcmp(iface, wpa_supplicant_get_dbus_path(wpa_s)) != 0) {
824
reply = wpas_dbus_new_invalid_network_error(message);
828
id = strtoul(net_id, NULL, 10);
829
ssid = wpa_config_get_network(wpa_s->conf, id);
831
reply = wpas_dbus_new_invalid_network_error(message);
835
if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
836
reply = dbus_message_new_error(message,
837
WPAS_ERROR_REMOVE_NETWORK_ERROR,
838
"error removing the specified "
839
"on this interface.");
843
if (ssid == wpa_s->current_ssid)
844
wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
845
reply = wpas_dbus_new_success_reply(message);
854
static const char *dont_quote[] = {
855
"key_mgmt", "proto", "pairwise", "auth_alg", "group", "eap",
856
"opensc_engine_path", "pkcs11_engine_path", "pkcs11_module_path",
860
static dbus_bool_t should_quote_opt(const char *key)
863
while (dont_quote[i] != NULL) {
864
if (strcmp(key, dont_quote[i]) == 0)
872
* wpas_dbus_iface_set_network - Set options for a configured network
873
* @message: Pointer to incoming dbus message
874
* @wpa_s: wpa_supplicant structure for a network interface
875
* @ssid: wpa_ssid structure for a configured network
876
* Returns: a dbus message containing a UINT32 indicating success (1) or
879
* Handler function for "set" method call of a configured network.
881
DBusMessage * wpas_dbus_iface_set_network(DBusMessage *message,
882
struct wpa_supplicant *wpa_s,
883
struct wpa_ssid *ssid)
885
DBusMessage *reply = NULL;
886
struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
887
DBusMessageIter iter, iter_dict;
889
dbus_message_iter_init(message, &iter);
891
if (!wpa_dbus_dict_open_read(&iter, &iter_dict)) {
892
reply = wpas_dbus_new_invalid_opts_error(message, NULL);
896
while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
901
if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) {
902
reply = wpas_dbus_new_invalid_opts_error(message,
907
/* Type conversions, since wpa_supplicant wants strings */
908
if (entry.type == DBUS_TYPE_ARRAY &&
909
entry.array_type == DBUS_TYPE_BYTE) {
910
if (entry.array_len <= 0)
913
size = entry.array_len * 2 + 1;
914
value = os_zalloc(size);
917
ret = wpa_snprintf_hex(value, size,
918
(u8 *) entry.bytearray_value,
922
} else if (entry.type == DBUS_TYPE_STRING) {
923
if (should_quote_opt(entry.key)) {
924
size = strlen(entry.str_value);
925
/* Zero-length option check */
928
size += 3; /* For quotes and terminator */
929
value = os_zalloc(size);
932
ret = snprintf(value, size, "\"%s\"",
934
if (ret < 0 || (size_t) ret != (size - 1))
937
value = strdup(entry.str_value);
941
} else if (entry.type == DBUS_TYPE_UINT32) {
942
value = os_zalloc(size);
945
ret = snprintf(value, size, "%u", entry.uint32_value);
948
} else if (entry.type == DBUS_TYPE_INT32) {
949
value = os_zalloc(size);
952
ret = snprintf(value, size, "%d", entry.int32_value);
958
if (wpa_config_set(ssid, entry.key, value, 0) < 0)
961
if ((strcmp(entry.key, "psk") == 0 &&
962
value[0] == '"' && ssid->ssid_len) ||
963
(strcmp(entry.key, "ssid") == 0 && ssid->passphrase))
964
wpa_config_update_psk(ssid);
967
wpa_dbus_dict_entry_clear(&entry);
972
reply = wpas_dbus_new_invalid_opts_error(message, entry.key);
973
wpa_dbus_dict_entry_clear(&entry);
978
reply = wpas_dbus_new_success_reply(message);
986
* wpas_dbus_iface_enable_network - Mark a configured network as enabled
987
* @message: Pointer to incoming dbus message
988
* @wpa_s: wpa_supplicant structure for a network interface
989
* @ssid: wpa_ssid structure for a configured network
990
* Returns: A dbus message containing a UINT32 indicating success (1) or
993
* Handler function for "enable" method call of a configured network.
995
DBusMessage * wpas_dbus_iface_enable_network(DBusMessage *message,
996
struct wpa_supplicant *wpa_s,
997
struct wpa_ssid *ssid)
999
if (wpa_s->current_ssid == NULL && ssid->disabled) {
1001
* Try to reassociate since there is no current configuration
1002
* and a new network was made available.
1004
wpa_s->reassociate = 1;
1005
wpa_supplicant_req_scan(wpa_s, 0, 0);
1009
return wpas_dbus_new_success_reply(message);
1014
* wpas_dbus_iface_disable_network - Mark a configured network as disabled
1015
* @message: Pointer to incoming dbus message
1016
* @wpa_s: wpa_supplicant structure for a network interface
1017
* @ssid: wpa_ssid structure for a configured network
1018
* Returns: A dbus message containing a UINT32 indicating success (1) or
1021
* Handler function for "disable" method call of a configured network.
1023
DBusMessage * wpas_dbus_iface_disable_network(DBusMessage *message,
1024
struct wpa_supplicant *wpa_s,
1025
struct wpa_ssid *ssid)
1027
if (ssid == wpa_s->current_ssid)
1028
wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1031
return wpas_dbus_new_success_reply(message);
1036
* wpas_dbus_iface_select_network - Attempt association with a configured network
1037
* @message: Pointer to incoming dbus message
1038
* @wpa_s: wpa_supplicant structure for a network interface
1039
* Returns: A dbus message containing a UINT32 indicating success (1) or
1042
* Handler function for "selectNetwork" method call of network interface.
1044
DBusMessage * wpas_dbus_iface_select_network(DBusMessage *message,
1045
struct wpa_supplicant *wpa_s)
1047
DBusMessage *reply = NULL;
1049
struct wpa_ssid *ssid;
1050
char *iface_obj_path = NULL;
1051
char *network = NULL;
1053
if (strlen(dbus_message_get_signature(message)) == 0) {
1055
ssid = wpa_s->conf->ssid;
1060
wpa_s->reassociate = 1;
1061
wpa_supplicant_req_scan(wpa_s, 0, 0);
1063
const char *obj_path;
1066
if (!dbus_message_get_args(message, NULL,
1067
DBUS_TYPE_OBJECT_PATH, &op,
1068
DBUS_TYPE_INVALID)) {
1069
reply = wpas_dbus_new_invalid_opts_error(message,
1074
/* Extract the network number */
1075
iface_obj_path = wpas_dbus_decompose_object_path(op,
1078
if (iface_obj_path == NULL) {
1079
reply = wpas_dbus_new_invalid_iface_error(message);
1082
/* Ensure the object path really points to this interface */
1083
obj_path = wpa_supplicant_get_dbus_path(wpa_s);
1084
if (strcmp(iface_obj_path, obj_path) != 0) {
1085
reply = wpas_dbus_new_invalid_network_error(message);
1089
nid = strtoul(network, NULL, 10);
1090
if (errno == EINVAL) {
1091
reply = wpas_dbus_new_invalid_network_error(message);
1095
ssid = wpa_config_get_network(wpa_s->conf, nid);
1097
reply = wpas_dbus_new_invalid_network_error(message);
1101
/* Finally, associate with the network */
1102
if (ssid != wpa_s->current_ssid && wpa_s->current_ssid)
1103
wpa_supplicant_disassociate(
1104
wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1106
/* Mark all other networks disabled and trigger reassociation
1108
ssid = wpa_s->conf->ssid;
1110
ssid->disabled = (nid != ssid->id);
1113
wpa_s->disconnected = 0;
1114
wpa_s->reassociate = 1;
1115
wpa_supplicant_req_scan(wpa_s, 0, 0);
1118
reply = wpas_dbus_new_success_reply(message);
1121
free(iface_obj_path);
1128
* wpas_dbus_iface_disconnect - Terminate the current connection
1129
* @message: Pointer to incoming dbus message
1130
* @wpa_s: wpa_supplicant structure for a network interface
1131
* Returns: A dbus message containing a UINT32 indicating success (1) or
1134
* Handler function for "disconnect" method call of network interface.
1136
DBusMessage * wpas_dbus_iface_disconnect(DBusMessage *message,
1137
struct wpa_supplicant *wpa_s)
1139
wpa_s->disconnected = 1;
1140
wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1142
return wpas_dbus_new_success_reply(message);
1147
* wpas_dbus_iface_set_ap_scan - Control roaming mode
1148
* @message: Pointer to incoming dbus message
1149
* @wpa_s: wpa_supplicant structure for a network interface
1150
* Returns: A dbus message containing a UINT32 indicating success (1) or
1153
* Handler function for "setAPScan" method call.
1155
DBusMessage * wpas_dbus_iface_set_ap_scan(DBusMessage *message,
1156
struct wpa_supplicant *wpa_s)
1158
DBusMessage *reply = NULL;
1159
dbus_uint32_t ap_scan = 1;
1161
if (!dbus_message_get_args(message, NULL, DBUS_TYPE_UINT32, &ap_scan,
1162
DBUS_TYPE_INVALID)) {
1163
reply = wpas_dbus_new_invalid_opts_error(message, NULL);
1168
reply = wpas_dbus_new_invalid_opts_error(message, NULL);
1171
wpa_s->conf->ap_scan = ap_scan;
1172
reply = wpas_dbus_new_success_reply(message);
1180
* wpas_dbus_iface_get_state - Get interface state
1181
* @message: Pointer to incoming dbus message
1182
* @wpa_s: wpa_supplicant structure for a network interface
1183
* Returns: A dbus message containing a STRING representing the current
1186
* Handler function for "state" method call.
1188
DBusMessage * wpas_dbus_iface_get_state(DBusMessage *message,
1189
struct wpa_supplicant *wpa_s)
1191
DBusMessage *reply = NULL;
1192
const char *str_state;
1194
reply = dbus_message_new_method_return(message);
1195
if (reply != NULL) {
1196
str_state = wpa_supplicant_state_txt(wpa_s->wpa_state);
1197
dbus_message_append_args(reply, DBUS_TYPE_STRING, &str_state,