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.
17
#include <dbus/dbus.h>
21
#include "wpa_supplicant_i.h"
22
#include "ctrl_iface_dbus.h"
23
#include "ctrl_iface_dbus_handlers.h"
24
#include "l2_packet.h"
25
#include "eap_methods.h"
26
#include "dbus_dict_helpers.h"
31
* wpas_dbus_new_invalid_opts_error - Return a new invalid options error message
32
* @message: Pointer to incoming dbus message this error refers to
33
* Returns: a dbus error message
35
* Convenience function to create and return an invalid options error
37
static DBusMessage * wpas_dbus_new_invalid_opts_error(DBusMessage *message,
42
reply = dbus_message_new_error(message, WPAS_ERROR_INVALID_OPTS,
43
"Did not receive correct message "
46
dbus_message_append_args(reply, DBUS_TYPE_STRING, &arg,
54
* wpas_dbus_new_success_reply - Return a new success reply message
55
* @message: Pointer to incoming dbus message this reply refers to
56
* Returns: a dbus message containing a single UINT32 that indicates
57
* success (ie, a value of 1)
59
* Convenience function to create and return a success reply message
61
static DBusMessage * wpas_dbus_new_success_reply(DBusMessage *message)
64
unsigned int success = 1;
66
reply = dbus_message_new_method_return(message);
67
dbus_message_append_args(message, DBUS_TYPE_UINT32, &success,
73
static void wpas_dbus_free_wpa_interface(struct wpa_interface *iface)
75
free((char *) iface->driver);
76
free((char *) iface->driver_param);
77
free((char *) iface->confname);
78
free((char *) iface->bridge_ifname);
83
* wpas_dbus_global_add_interface - Request registration of a network interface
84
* @message: Pointer to incoming dbus message
85
* @global: %wpa_supplicant global data structure
86
* Returns: The object path of the new interface object,
87
* or a dbus error message with more information
89
* Handler function for "addInterface" method call. Handles requests
90
* by dbus clients to register a network interface that wpa_supplicant
93
DBusMessage * wpas_dbus_global_add_interface(DBusMessage *message,
94
struct wpa_global *global)
96
struct wpa_interface iface;
98
DBusMessage *reply = NULL;
101
memset(&iface, 0, sizeof(iface));
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);
113
iface.ifname = ifname;
115
/* Second argument: dict of options */
116
if (dbus_message_iter_next(&iter)) {
117
DBusMessageIter iter_dict;
118
struct wpa_dbus_dict_entry entry;
120
if (!wpa_dbus_dict_open_read(&iter, &iter_dict))
122
while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
123
if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
125
if (!strcmp(entry.key, "driver") &&
126
(entry.type == DBUS_TYPE_STRING)) {
127
iface.driver = strdup(entry.str_value);
128
if (iface.driver == NULL)
130
} else if (!strcmp(entry.key, "driver-params") &&
131
(entry.type == DBUS_TYPE_STRING)) {
132
iface.driver_param = strdup(entry.str_value);
133
if (iface.driver_param == NULL)
135
} else if (!strcmp(entry.key, "config-file") &&
136
(entry.type == DBUS_TYPE_STRING)) {
137
iface.confname = strdup(entry.str_value);
138
if (iface.confname == NULL)
140
} else if (!strcmp(entry.key, "bridge-ifname") &&
141
(entry.type == DBUS_TYPE_STRING)) {
142
iface.bridge_ifname = strdup(entry.str_value);
143
if (iface.bridge_ifname == NULL)
146
wpa_dbus_dict_entry_clear(&entry);
149
wpa_dbus_dict_entry_clear(&entry);
154
* Try to get the wpa_supplicant record for this iface, return
155
* an error if we already control it.
157
if (wpa_supplicant_get_iface(global, iface.ifname) != 0) {
158
reply = dbus_message_new_error(message,
159
WPAS_ERROR_EXISTS_ERROR,
160
"wpa_supplicant already "
161
"controls this interface.");
163
struct wpa_supplicant *wpa_s;
164
/* Otherwise, have wpa_supplicant attach to it. */
165
if ((wpa_s = wpa_supplicant_add_iface(global, &iface))) {
166
const char *path = wpa_supplicant_get_dbus_path(wpa_s);
167
reply = dbus_message_new_method_return(message);
168
dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH,
169
&path, DBUS_TYPE_INVALID);
171
reply = dbus_message_new_error(message,
172
WPAS_ERROR_ADD_ERROR,
174
"couldn't grab this "
178
wpas_dbus_free_wpa_interface(&iface);
182
wpas_dbus_free_wpa_interface(&iface);
183
return wpas_dbus_new_invalid_opts_error(message, NULL);
188
* wpas_dbus_global_remove_interface - Request deregistration of an interface
189
* @message: Pointer to incoming dbus message
190
* @global: wpa_supplicant global data structure
191
* Returns: a dbus message containing a UINT32 indicating success (1) or
192
* failure (0), or returns a dbus error message with more information
194
* Handler function for "removeInterface" method call. Handles requests
195
* by dbus clients to deregister a network interface that wpa_supplicant
198
DBusMessage * wpas_dbus_global_remove_interface(DBusMessage *message,
199
struct wpa_global *global)
201
struct wpa_supplicant *wpa_s;
203
DBusMessage *reply = NULL;
205
if (!dbus_message_get_args(message, NULL,
206
DBUS_TYPE_OBJECT_PATH, &path,
207
DBUS_TYPE_INVALID)) {
208
reply = wpas_dbus_new_invalid_opts_error(message, NULL);
212
wpa_s = wpa_supplicant_get_iface_by_dbus_path(global, path);
214
reply = wpas_dbus_new_invalid_iface_error(message);
218
if (!wpa_supplicant_remove_iface(global, wpa_s)) {
219
reply = wpas_dbus_new_success_reply(message);
221
reply = dbus_message_new_error(message,
222
WPAS_ERROR_REMOVE_ERROR,
223
"wpa_supplicant couldn't "
224
"remove this interface.");
233
* wpas_dbus_global_get_interface - Get the object path for an interface name
234
* @message: Pointer to incoming dbus message
235
* @global: %wpa_supplicant global data structure
236
* Returns: The object path of the interface object,
237
* or a dbus error message with more information
239
* Handler function for "getInterface" method call. Handles requests
240
* by dbus clients for the object path of an specific network interface.
242
DBusMessage * wpas_dbus_global_get_interface(DBusMessage *message,
243
struct wpa_global *global)
245
DBusMessage *reply = NULL;
248
struct wpa_supplicant *wpa_s;
250
if (!dbus_message_get_args(message, NULL,
251
DBUS_TYPE_STRING, &ifname,
252
DBUS_TYPE_INVALID)) {
253
reply = wpas_dbus_new_invalid_opts_error(message, NULL);
257
wpa_s = wpa_supplicant_get_iface(global, ifname);
259
reply = wpas_dbus_new_invalid_iface_error(message);
263
path = wpa_supplicant_get_dbus_path(wpa_s);
265
reply = dbus_message_new_error(message,
266
WPAS_ERROR_INTERNAL_ERROR,
267
"an internal error occurred "
268
"getting the interface.");
272
reply = dbus_message_new_method_return(message);
273
dbus_message_append_args(reply,
274
DBUS_TYPE_OBJECT_PATH, &path,
283
* wpas_dbus_iface_scan - Request a wireless scan on an interface
284
* @message: Pointer to incoming dbus message
285
* @wpa_s: wpa_supplicant structure for a network interface
286
* Returns: a dbus message containing a UINT32 indicating success (1) or
289
* Handler function for "scan" method call of a network device. Requests
290
* that wpa_supplicant perform a wireless scan as soon as possible
291
* on a particular wireless interface.
293
DBusMessage * wpas_dbus_iface_scan(DBusMessage *message,
294
struct wpa_supplicant *wpa_s)
297
wpa_supplicant_req_scan(wpa_s, 0, 0);
298
return wpas_dbus_new_success_reply(message);
303
* wpas_dbus_iface_scan_results - Get the results of a recent scan request
304
* @message: Pointer to incoming dbus message
305
* @wpa_s: wpa_supplicant structure for a network interface
306
* Returns: a dbus message containing a dbus array of objects paths, or returns
307
* a dbus error message if not scan results could be found
309
* Handler function for "scanResults" method call of a network device. Returns
310
* a dbus message containing the object paths of wireless networks found.
312
DBusMessage * wpas_dbus_iface_scan_results(DBusMessage *message,
313
struct wpa_supplicant *wpa_s)
315
DBusMessage *reply = NULL;
316
DBusMessageIter iter;
317
DBusMessageIter sub_iter;
320
/* Ensure we've actually got scan results to return */
321
if (wpa_s->scan_results == NULL &&
322
wpa_supplicant_get_scan_results(wpa_s) < 0) {
323
reply = dbus_message_new_error(message, WPAS_ERROR_SCAN_ERROR,
324
"An error ocurred getting scan "
329
/* Create and initialize the return message */
330
reply = dbus_message_new_method_return(message);
331
dbus_message_iter_init_append(reply, &iter);
332
dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
333
DBUS_TYPE_OBJECT_PATH_AS_STRING,
336
/* Loop through scan results and append each result's object path */
337
for (i = 0; i < wpa_s->num_scan_results; i++) {
338
struct wpa_scan_result *res = &wpa_s->scan_results[i];
341
path = wpa_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
343
perror("wpas_dbus_iface_scan_results[dbus]: out of "
345
wpa_printf(MSG_ERROR, "dbus control interface: not "
346
"enough memory to send scan results "
350
/* Construct the object path for this network. Note that ':'
351
* is not a valid character in dbus object paths.
353
snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
354
"%s/" WPAS_DBUS_BSSIDS_PART "/"
355
WPAS_DBUS_BSSID_FORMAT,
356
wpa_supplicant_get_dbus_path(wpa_s),
357
MAC2STR(res->bssid));
358
dbus_message_iter_append_basic(&sub_iter,
359
DBUS_TYPE_OBJECT_PATH, &path);
363
dbus_message_iter_close_container(&iter, &sub_iter);
371
* wpas_dbus_bssid_properties - Return the properties of a scanned network
372
* @message: Pointer to incoming dbus message
373
* @wpa_s: wpa_supplicant structure for a network interface
374
* @res: wpa_supplicant scan result for which to get properties
375
* Returns: a dbus message containing the properties for the requested network
377
* Handler function for "properties" method call of a scanned network.
378
* Returns a dbus message containing the the properties.
380
DBusMessage * wpas_dbus_bssid_properties(DBusMessage *message,
381
struct wpa_supplicant *wpa_s,
382
struct wpa_scan_result *res)
384
DBusMessage *reply = NULL;
385
char *bssid_data, *ssid_data, *wpa_ie_data, *rsn_ie_data;
386
DBusMessageIter iter, iter_dict;
388
/* dbus needs the address of a pointer to the actual value
389
* for array types, not the address of the value itself.
391
bssid_data = (char *) &res->bssid;
392
ssid_data = (char *) &res->ssid;
393
wpa_ie_data = (char *) &res->wpa_ie;
394
rsn_ie_data = (char *) &res->rsn_ie;
396
/* Dump the properties into a dbus message */
397
reply = dbus_message_new_method_return(message);
399
dbus_message_iter_init_append(reply, &iter);
400
if (!wpa_dbus_dict_open_write(&iter, &iter_dict))
403
if (!wpa_dbus_dict_append_byte_array(&iter_dict, "bssid",
404
bssid_data, ETH_ALEN))
406
if (!wpa_dbus_dict_append_byte_array(&iter_dict, "ssid",
407
ssid_data, res->ssid_len))
409
if (res->wpa_ie_len) {
410
if (!wpa_dbus_dict_append_byte_array(&iter_dict, "wpaie",
416
if (res->rsn_ie_len) {
417
if (!wpa_dbus_dict_append_byte_array(&iter_dict, "rsnie",
424
if (!wpa_dbus_dict_append_int32(&iter_dict, "frequency",
428
if (!wpa_dbus_dict_append_uint16(&iter_dict, "capabilities",
431
if (!wpa_dbus_dict_append_int32(&iter_dict, "quality", res->qual))
433
if (!wpa_dbus_dict_append_int32(&iter_dict, "noise", res->noise))
435
if (!wpa_dbus_dict_append_int32(&iter_dict, "level", res->level))
437
if (!wpa_dbus_dict_append_int32(&iter_dict, "maxrate", res->maxrate))
440
if (!wpa_dbus_dict_close_write(&iter, &iter_dict))
447
dbus_message_unref(reply);
448
return dbus_message_new_error(message, WPAS_ERROR_INTERNAL_ERROR,
449
"an internal error occurred returning "
450
"BSSID properties.");
455
* wpas_dbus_iface_capabilities - Return interface capabilities
456
* @message: Pointer to incoming dbus message
457
* @wpa_s: wpa_supplicant structure for a network interface
458
* Returns: A dbus message containing a dict of strings
460
* Handler function for "capabilities" method call of an interface.
462
DBusMessage * wpas_dbus_iface_capabilities(DBusMessage *message,
463
struct wpa_supplicant *wpa_s)
465
DBusMessage *reply = NULL;
466
struct wpa_driver_capa capa;
468
DBusMessageIter iter, iter_dict;
471
dbus_bool_t strict = FALSE;
472
DBusMessageIter iter_dict_entry, iter_dict_val, iter_array;
474
if (!dbus_message_get_args(message, NULL,
475
DBUS_TYPE_BOOLEAN, &strict,
479
reply = dbus_message_new_method_return(message);
481
dbus_message_iter_init_append(reply, &iter);
482
if (!wpa_dbus_dict_open_write(&iter, &iter_dict))
486
eap_methods = eap_get_names_as_string_array(&num_items);
488
dbus_bool_t success = FALSE;
491
success = wpa_dbus_dict_append_string_array(
492
&iter_dict, "eap", (const char **) eap_methods,
495
/* free returned method array */
496
while (eap_methods[i])
497
free(eap_methods[i++]);
504
res = wpa_drv_get_capa(wpa_s, &capa);
506
/***** pairwise cipher */
509
const char *args[] = {"CCMP", "TKIP", "NONE"};
510
if (!wpa_dbus_dict_append_string_array(
511
&iter_dict, "pairwise", args,
512
sizeof(args) / sizeof(char*)))
516
if (!wpa_dbus_dict_begin_string_array(&iter_dict, "pairwise",
522
if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
523
if (!wpa_dbus_dict_string_array_add_element(
524
&iter_array, "CCMP"))
528
if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
529
if (!wpa_dbus_dict_string_array_add_element(
530
&iter_array, "TKIP"))
534
if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
535
if (!wpa_dbus_dict_string_array_add_element(
536
&iter_array, "NONE"))
540
if (!wpa_dbus_dict_end_string_array(&iter_dict,
547
/***** group cipher */
550
const char *args[] = {
551
"CCMP", "TKIP", "WEP104", "WEP40"
553
if (!wpa_dbus_dict_append_string_array(
554
&iter_dict, "group", args,
555
sizeof(args) / sizeof(char*)))
559
if (!wpa_dbus_dict_begin_string_array(&iter_dict, "group",
565
if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
566
if (!wpa_dbus_dict_string_array_add_element(
567
&iter_array, "CCMP"))
571
if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
572
if (!wpa_dbus_dict_string_array_add_element(
573
&iter_array, "TKIP"))
577
if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) {
578
if (!wpa_dbus_dict_string_array_add_element(
579
&iter_array, "WEP104"))
583
if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) {
584
if (!wpa_dbus_dict_string_array_add_element(
585
&iter_array, "WEP40"))
589
if (!wpa_dbus_dict_end_string_array(&iter_dict,
596
/***** key management */
599
const char *args[] = {
600
"WPA-PSK", "WPA-EAP", "IEEE8021X", "WPA-NONE",
603
if (!wpa_dbus_dict_append_string_array(
604
&iter_dict, "key_mgmt", args,
605
sizeof(args) / sizeof(char*)))
609
if (!wpa_dbus_dict_begin_string_array(&iter_dict, "key_mgmt",
615
if (!wpa_dbus_dict_string_array_add_element(&iter_array,
619
if (!wpa_dbus_dict_string_array_add_element(&iter_array,
623
if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
624
WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
625
if (!wpa_dbus_dict_string_array_add_element(
626
&iter_array, "WPA-EAP"))
630
if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
631
WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
632
if (!wpa_dbus_dict_string_array_add_element(
633
&iter_array, "WPA-PSK"))
637
if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
638
if (!wpa_dbus_dict_string_array_add_element(
639
&iter_array, "WPA-NONE"))
643
if (!wpa_dbus_dict_end_string_array(&iter_dict,
650
/***** WPA protocol */
653
const char *args[] = { "RSN", "WPA" };
654
if (!wpa_dbus_dict_append_string_array(
655
&iter_dict, "proto", args,
656
sizeof(args) / sizeof(char*)))
660
if (!wpa_dbus_dict_begin_string_array(&iter_dict, "proto",
666
if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
667
WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
668
if (!wpa_dbus_dict_string_array_add_element(
673
if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
674
WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
675
if (!wpa_dbus_dict_string_array_add_element(
680
if (!wpa_dbus_dict_end_string_array(&iter_dict,
690
const char *args[] = { "OPEN", "SHARED", "LEAP" };
691
if (!wpa_dbus_dict_append_string_array(
692
&iter_dict, "auth_alg", args,
693
sizeof(args) / sizeof(char*)))
697
if (!wpa_dbus_dict_begin_string_array(&iter_dict, "auth_alg",
703
if (capa.auth & (WPA_DRIVER_AUTH_OPEN)) {
704
if (!wpa_dbus_dict_string_array_add_element(
705
&iter_array, "OPEN"))
709
if (capa.auth & (WPA_DRIVER_AUTH_SHARED)) {
710
if (!wpa_dbus_dict_string_array_add_element(
711
&iter_array, "SHARED"))
715
if (capa.auth & (WPA_DRIVER_AUTH_LEAP)) {
716
if (!wpa_dbus_dict_string_array_add_element(
717
&iter_array, "LEAP"))
721
if (!wpa_dbus_dict_end_string_array(&iter_dict,
728
if (!wpa_dbus_dict_close_write(&iter, &iter_dict))
735
dbus_message_unref(reply);
736
return dbus_message_new_error(message, WPAS_ERROR_INTERNAL_ERROR,
737
"an internal error occurred returning "
738
"interface capabilities.");
743
* wpas_dbus_iface_add_network - Add a new configured network
744
* @message: Pointer to incoming dbus message
745
* @wpa_s: wpa_supplicant structure for a network interface
746
* Returns: A dbus message containing the object path of the new network
748
* Handler function for "addNetwork" method call of a network interface.
750
DBusMessage * wpas_dbus_iface_add_network(DBusMessage *message,
751
struct wpa_supplicant *wpa_s)
753
DBusMessage *reply = NULL;
754
struct wpa_ssid *ssid;
757
path = wpa_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
759
perror("wpas_dbus_iface_scan_results[dbus]: out of "
761
wpa_printf(MSG_ERROR, "dbus control interface: not "
762
"enough memory to send scan results "
767
ssid = wpa_config_add_network(wpa_s->conf);
769
reply = dbus_message_new_error(message,
770
WPAS_ERROR_ADD_NETWORK_ERROR,
771
"wpa_supplicant could not add "
772
"a network on this interface.");
776
wpa_config_set_network_defaults(ssid);
778
/* Construct the object path for this network. */
779
snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
780
"%s/" WPAS_DBUS_NETWORKS_PART "/%d",
781
wpa_supplicant_get_dbus_path(wpa_s),
784
reply = dbus_message_new_method_return(message);
785
dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH,
786
&path, DBUS_TYPE_INVALID);
795
* wpas_dbus_iface_remove_network - Remove a configured network
796
* @message: Pointer to incoming dbus message
797
* @wpa_s: wpa_supplicant structure for a network interface
798
* Returns: A dbus message containing a UINT32 indicating success (1) or
801
* Handler function for "removeNetwork" method call of a network interface.
803
DBusMessage * wpas_dbus_iface_remove_network(DBusMessage *message,
804
struct wpa_supplicant *wpa_s)
806
DBusMessage *reply = NULL;
808
char *iface = NULL, *net_id = NULL;
810
struct wpa_ssid *ssid;
812
if (!dbus_message_get_args(message, NULL,
813
DBUS_TYPE_OBJECT_PATH, &op,
814
DBUS_TYPE_INVALID)) {
815
reply = wpas_dbus_new_invalid_opts_error(message, NULL);
819
/* Extract the network ID */
820
iface = wpas_dbus_decompose_object_path(op, &net_id, NULL);
822
reply = wpas_dbus_new_invalid_network_error(message);
825
/* Ensure the network is actually a child of this interface */
826
if (strcmp(iface, wpa_supplicant_get_dbus_path(wpa_s)) != 0) {
827
reply = wpas_dbus_new_invalid_network_error(message);
831
id = strtoul(net_id, NULL, 10);
832
ssid = wpa_config_get_network(wpa_s->conf, id);
834
reply = wpas_dbus_new_invalid_network_error(message);
838
if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
839
reply = dbus_message_new_error(message,
840
WPAS_ERROR_REMOVE_NETWORK_ERROR,
841
"error removing the specified "
842
"on this interface.");
846
if (ssid == wpa_s->current_ssid)
847
wpa_supplicant_disassociate(wpa_s, REASON_DEAUTH_LEAVING);
848
reply = wpas_dbus_new_success_reply(message);
857
static const char *dont_quote[] = {
858
"key_mgmt", "proto", "pairwise", "auth_alg", "group", "eap",
859
"opensc_engine_path", "pkcs11_engine_path", "pkcs11_module_path",
863
static dbus_bool_t should_quote_opt(const char *key)
866
while (dont_quote[i] != NULL) {
867
if (strcmp(key, dont_quote[i]) == 0)
875
* wpas_dbus_iface_set_network - Set options for a configured network
876
* @message: Pointer to incoming dbus message
877
* @wpa_s: wpa_supplicant structure for a network interface
878
* @ssid: wpa_ssid structure for a configured network
879
* Returns: a dbus message containing a UINT32 indicating success (1) or
882
* Handler function for "set" method call of a configured network.
884
DBusMessage * wpas_dbus_iface_set_network(DBusMessage *message,
885
struct wpa_supplicant *wpa_s,
886
struct wpa_ssid *ssid)
888
DBusMessage *reply = NULL;
889
struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
890
DBusMessageIter iter, iter_dict;
892
dbus_message_iter_init(message, &iter);
894
if (!wpa_dbus_dict_open_read(&iter, &iter_dict)) {
895
reply = wpas_dbus_new_invalid_opts_error(message, NULL);
899
while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
904
if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) {
905
reply = wpas_dbus_new_invalid_opts_error(message,
910
/* Type conversions, since wpa_supplicant wants strings */
911
if (entry.type == DBUS_TYPE_ARRAY &&
912
entry.array_type == DBUS_TYPE_BYTE) {
913
if (entry.array_len <= 0)
916
size = entry.array_len * 2 + 1;
917
value = wpa_zalloc(size);
920
ret = wpa_snprintf_hex(value, size,
921
(u8 *) entry.bytearray_value,
925
} else if (entry.type == DBUS_TYPE_STRING) {
926
if (should_quote_opt(entry.key)) {
927
size = strlen(entry.str_value);
928
/* Zero-length option check */
931
size += 3; /* For quotes and terminator */
932
value = wpa_zalloc(size);
935
ret = snprintf(value, size, "\"%s\"",
937
if (ret < 0 || (size_t) ret != (size - 1))
940
value = strdup(entry.str_value);
942
} else if (entry.type == DBUS_TYPE_UINT32) {
943
value = wpa_zalloc(size);
946
ret = snprintf(value, size, "%u", entry.uint32_value);
949
} else if (entry.type == DBUS_TYPE_INT32) {
950
value = wpa_zalloc(size);
953
ret = snprintf(value, size, "%d", entry.int32_value);
959
if (wpa_config_set(ssid, entry.key, value, 0) < 0)
962
if ((strcmp(entry.key, "psk") == 0 &&
963
value[0] == '"' && ssid->ssid_len) ||
964
(strcmp(entry.key, "ssid") == 0 && ssid->passphrase))
965
wpa_config_update_psk(ssid);
968
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, 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(wpa_s,
1104
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->reassociate = 1;
1114
wpa_supplicant_req_scan(wpa_s, 0, 0);
1117
reply = wpas_dbus_new_success_reply(message);
1120
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_disassociate(wpa_s, 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);
1167
reply = wpas_dbus_new_invalid_opts_error(message, NULL);
1170
wpa_s->conf->ap_scan = ap_scan;
1171
reply = wpas_dbus_new_success_reply(message);