]> git.ipfire.org Git - thirdparty/hostap.git/blob - wpa_supplicant/dbus/dbus_new_handlers.c
67562a547172ff614893e68cc75dd075614b954d
[thirdparty/hostap.git] / wpa_supplicant / dbus / dbus_new_handlers.c
1 /*
2 * WPA Supplicant / dbus-based control interface
3 * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
4 * Copyright (c) 2009-2010, Witold Sowa <witold.sowa@gmail.com>
5 * Copyright (c) 2009-2015, Jouni Malinen <j@w1.fi>
6 *
7 * This software may be distributed under the terms of the BSD license.
8 * See README for more details.
9 */
10
11 #include "includes.h"
12
13 #include "common.h"
14 #include "common/ieee802_11_defs.h"
15 #include "eap_peer/eap_methods.h"
16 #include "eapol_supp/eapol_supp_sm.h"
17 #include "rsn_supp/wpa.h"
18 #include "../config.h"
19 #include "../wpa_supplicant_i.h"
20 #include "../driver_i.h"
21 #include "../notify.h"
22 #include "../bss.h"
23 #include "../scan.h"
24 #include "../autoscan.h"
25 #include "dbus_new_helpers.h"
26 #include "dbus_new.h"
27 #include "dbus_new_handlers.h"
28 #include "dbus_dict_helpers.h"
29 #include "dbus_common_i.h"
30 #include "drivers/driver.h"
31
32 static const char * const debug_strings[] = {
33 "excessive", "msgdump", "debug", "info", "warning", "error", NULL
34 };
35
36
37 /**
38 * wpas_dbus_error_unknown_error - Return a new UnknownError error message
39 * @message: Pointer to incoming dbus message this error refers to
40 * @arg: Optional string appended to error message
41 * Returns: a dbus error message
42 *
43 * Convenience function to create and return an UnknownError
44 */
45 DBusMessage * wpas_dbus_error_unknown_error(DBusMessage *message,
46 const char *arg)
47 {
48 return dbus_message_new_error(message, WPAS_DBUS_ERROR_UNKNOWN_ERROR,
49 arg);
50 }
51
52
53 /**
54 * wpas_dbus_error_iface_unknown - Return a new invalid interface error message
55 * @message: Pointer to incoming dbus message this error refers to
56 * Returns: A dbus error message
57 *
58 * Convenience function to create and return an invalid interface error
59 */
60 static DBusMessage * wpas_dbus_error_iface_unknown(DBusMessage *message)
61 {
62 return dbus_message_new_error(
63 message, WPAS_DBUS_ERROR_IFACE_UNKNOWN,
64 "wpa_supplicant knows nothing about this interface.");
65 }
66
67
68 /**
69 * wpas_dbus_error_network_unknown - Return a new NetworkUnknown error message
70 * @message: Pointer to incoming dbus message this error refers to
71 * Returns: a dbus error message
72 *
73 * Convenience function to create and return an invalid network error
74 */
75 static DBusMessage * wpas_dbus_error_network_unknown(DBusMessage *message)
76 {
77 return dbus_message_new_error(
78 message, WPAS_DBUS_ERROR_NETWORK_UNKNOWN,
79 "There is no such a network in this interface.");
80 }
81
82
83 /**
84 * wpas_dbus_error_invalid_args - Return a new InvalidArgs error message
85 * @message: Pointer to incoming dbus message this error refers to
86 * Returns: a dbus error message
87 *
88 * Convenience function to create and return an invalid options error
89 */
90 DBusMessage * wpas_dbus_error_invalid_args(DBusMessage *message,
91 const char *arg)
92 {
93 DBusMessage *reply;
94
95 reply = dbus_message_new_error(
96 message, WPAS_DBUS_ERROR_INVALID_ARGS,
97 "Did not receive correct message arguments.");
98 if (arg != NULL)
99 dbus_message_append_args(reply, DBUS_TYPE_STRING, &arg,
100 DBUS_TYPE_INVALID);
101
102 return reply;
103 }
104
105
106 /**
107 * wpas_dbus_error_scan_error - Return a new ScanError error message
108 * @message: Pointer to incoming dbus message this error refers to
109 * @error: Optional string to be used as the error message
110 * Returns: a dbus error message
111 *
112 * Convenience function to create and return a scan error
113 */
114 static DBusMessage * wpas_dbus_error_scan_error(DBusMessage *message,
115 const char *error)
116 {
117 return dbus_message_new_error(message,
118 WPAS_DBUS_ERROR_IFACE_SCAN_ERROR,
119 error);
120 }
121
122
123 DBusMessage * wpas_dbus_error_no_memory(DBusMessage *message)
124 {
125 wpa_printf(MSG_DEBUG, "dbus: Failed to allocate memory");
126 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, NULL);
127 }
128
129
130 static const char * const dont_quote[] = {
131 "key_mgmt", "proto", "pairwise", "auth_alg", "group", "eap",
132 "opensc_engine_path", "pkcs11_engine_path", "pkcs11_module_path",
133 "bssid", "scan_freq", "freq_list", NULL
134 };
135
136 static dbus_bool_t should_quote_opt(const char *key)
137 {
138 int i = 0;
139
140 while (dont_quote[i] != NULL) {
141 if (os_strcmp(key, dont_quote[i]) == 0)
142 return FALSE;
143 i++;
144 }
145 return TRUE;
146 }
147
148 /**
149 * get_iface_by_dbus_path - Get a new network interface
150 * @global: Pointer to global data from wpa_supplicant_init()
151 * @path: Pointer to a dbus object path representing an interface
152 * Returns: Pointer to the interface or %NULL if not found
153 */
154 static struct wpa_supplicant * get_iface_by_dbus_path(
155 struct wpa_global *global, const char *path)
156 {
157 struct wpa_supplicant *wpa_s;
158
159 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
160 if (wpa_s->dbus_new_path &&
161 os_strcmp(wpa_s->dbus_new_path, path) == 0)
162 return wpa_s;
163 }
164 return NULL;
165 }
166
167
168 /**
169 * set_network_properties - Set properties of a configured network
170 * @wpa_s: wpa_supplicant structure for a network interface
171 * @ssid: wpa_ssid structure for a configured network
172 * @iter: DBus message iterator containing dictionary of network
173 * properties to set.
174 * @error: On failure, an error describing the failure
175 * Returns: TRUE if the request succeeds, FALSE if it failed
176 *
177 * Sets network configuration with parameters given id DBus dictionary
178 */
179 dbus_bool_t set_network_properties(struct wpa_supplicant *wpa_s,
180 struct wpa_ssid *ssid,
181 DBusMessageIter *iter,
182 DBusError *error)
183 {
184 struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
185 DBusMessageIter iter_dict;
186 char *value = NULL;
187
188 if (!wpa_dbus_dict_open_read(iter, &iter_dict, error))
189 return FALSE;
190
191 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
192 size_t size = 50;
193 int ret;
194
195 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
196 goto error;
197
198 value = NULL;
199 if (entry.type == DBUS_TYPE_ARRAY &&
200 entry.array_type == DBUS_TYPE_BYTE) {
201 if (entry.array_len <= 0)
202 goto error;
203
204 size = entry.array_len * 2 + 1;
205 value = os_zalloc(size);
206 if (value == NULL)
207 goto error;
208
209 ret = wpa_snprintf_hex(value, size,
210 (u8 *) entry.bytearray_value,
211 entry.array_len);
212 if (ret <= 0)
213 goto error;
214 } else if (entry.type == DBUS_TYPE_STRING) {
215 if (should_quote_opt(entry.key)) {
216 size = os_strlen(entry.str_value);
217 if (size == 0)
218 goto error;
219
220 size += 3;
221 value = os_zalloc(size);
222 if (value == NULL)
223 goto error;
224
225 ret = os_snprintf(value, size, "\"%s\"",
226 entry.str_value);
227 if (os_snprintf_error(size, ret))
228 goto error;
229 } else {
230 value = os_strdup(entry.str_value);
231 if (value == NULL)
232 goto error;
233 }
234 } else if (entry.type == DBUS_TYPE_UINT32) {
235 value = os_zalloc(size);
236 if (value == NULL)
237 goto error;
238
239 ret = os_snprintf(value, size, "%u",
240 entry.uint32_value);
241 if (os_snprintf_error(size, ret))
242 goto error;
243 } else if (entry.type == DBUS_TYPE_INT32) {
244 value = os_zalloc(size);
245 if (value == NULL)
246 goto error;
247
248 ret = os_snprintf(value, size, "%d",
249 entry.int32_value);
250 if (os_snprintf_error(size, ret))
251 goto error;
252 } else
253 goto error;
254
255 if (wpa_config_set(ssid, entry.key, value, 0) < 0)
256 goto error;
257
258 if (os_strcmp(entry.key, "bssid") != 0 &&
259 os_strcmp(entry.key, "priority") != 0)
260 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
261
262 if (wpa_s->current_ssid == ssid ||
263 wpa_s->current_ssid == NULL) {
264 /*
265 * Invalidate the EAP session cache if anything in the
266 * current or previously used configuration changes.
267 */
268 eapol_sm_invalidate_cached_session(wpa_s->eapol);
269 }
270
271 if ((os_strcmp(entry.key, "psk") == 0 &&
272 value[0] == '"' && ssid->ssid_len) ||
273 (os_strcmp(entry.key, "ssid") == 0 && ssid->passphrase))
274 wpa_config_update_psk(ssid);
275 else if (os_strcmp(entry.key, "priority") == 0)
276 wpa_config_update_prio_list(wpa_s->conf);
277
278 os_free(value);
279 value = NULL;
280 wpa_dbus_dict_entry_clear(&entry);
281 }
282
283 return TRUE;
284
285 error:
286 os_free(value);
287 wpa_dbus_dict_entry_clear(&entry);
288 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
289 "invalid message format");
290 return FALSE;
291 }
292
293
294 /**
295 * wpas_dbus_simple_property_getter - Get basic type property
296 * @iter: Message iter to use when appending arguments
297 * @type: DBus type of property (must be basic type)
298 * @val: pointer to place holding property value
299 * @error: On failure an error describing the failure
300 * Returns: TRUE if the request was successful, FALSE if it failed
301 *
302 * Generic getter for basic type properties. Type is required to be basic.
303 */
304 dbus_bool_t wpas_dbus_simple_property_getter(DBusMessageIter *iter,
305 const int type,
306 const void *val,
307 DBusError *error)
308 {
309 DBusMessageIter variant_iter;
310
311 if (!dbus_type_is_basic(type)) {
312 dbus_set_error(error, DBUS_ERROR_FAILED,
313 "%s: given type is not basic", __func__);
314 return FALSE;
315 }
316
317 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
318 wpa_dbus_type_as_string(type),
319 &variant_iter) ||
320 !dbus_message_iter_append_basic(&variant_iter, type, val) ||
321 !dbus_message_iter_close_container(iter, &variant_iter)) {
322 dbus_set_error(error, DBUS_ERROR_FAILED,
323 "%s: error constructing reply", __func__);
324 return FALSE;
325 }
326
327 return TRUE;
328 }
329
330
331 /**
332 * wpas_dbus_simple_property_setter - Set basic type property
333 * @message: Pointer to incoming dbus message
334 * @type: DBus type of property (must be basic type)
335 * @val: pointer to place where value being set will be stored
336 * Returns: TRUE if the request was successful, FALSE if it failed
337 *
338 * Generic setter for basic type properties. Type is required to be basic.
339 */
340 dbus_bool_t wpas_dbus_simple_property_setter(DBusMessageIter *iter,
341 DBusError *error,
342 const int type, void *val)
343 {
344 DBusMessageIter variant_iter;
345
346 if (!dbus_type_is_basic(type)) {
347 dbus_set_error(error, DBUS_ERROR_FAILED,
348 "%s: given type is not basic", __func__);
349 return FALSE;
350 }
351
352 /* Look at the new value */
353 dbus_message_iter_recurse(iter, &variant_iter);
354 if (dbus_message_iter_get_arg_type(&variant_iter) != type) {
355 dbus_set_error_const(error, DBUS_ERROR_FAILED,
356 "wrong property type");
357 return FALSE;
358 }
359 dbus_message_iter_get_basic(&variant_iter, val);
360
361 return TRUE;
362 }
363
364
365 /**
366 * wpas_dbus_simple_array_property_getter - Get array type property
367 * @iter: Pointer to incoming dbus message iterator
368 * @type: DBus type of property array elements (must be basic type)
369 * @array: pointer to array of elements to put into response message
370 * @array_len: length of above array
371 * @error: a pointer to an error to fill on failure
372 * Returns: TRUE if the request succeeded, FALSE if it failed
373 *
374 * Generic getter for array type properties. Array elements type is
375 * required to be basic.
376 */
377 dbus_bool_t wpas_dbus_simple_array_property_getter(DBusMessageIter *iter,
378 const int type,
379 const void *array,
380 size_t array_len,
381 DBusError *error)
382 {
383 DBusMessageIter variant_iter, array_iter;
384 char type_str[] = "a?"; /* ? will be replaced with subtype letter; */
385 const char *sub_type_str;
386 size_t element_size, i;
387
388 if (!dbus_type_is_basic(type)) {
389 dbus_set_error(error, DBUS_ERROR_FAILED,
390 "%s: given type is not basic", __func__);
391 return FALSE;
392 }
393
394 sub_type_str = wpa_dbus_type_as_string(type);
395 type_str[1] = sub_type_str[0];
396
397 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
398 type_str, &variant_iter) ||
399 !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
400 sub_type_str, &array_iter)) {
401 dbus_set_error(error, DBUS_ERROR_FAILED,
402 "%s: failed to construct message", __func__);
403 return FALSE;
404 }
405
406 switch (type) {
407 case DBUS_TYPE_BYTE:
408 case DBUS_TYPE_BOOLEAN:
409 element_size = 1;
410 break;
411 case DBUS_TYPE_INT16:
412 case DBUS_TYPE_UINT16:
413 element_size = sizeof(uint16_t);
414 break;
415 case DBUS_TYPE_INT32:
416 case DBUS_TYPE_UINT32:
417 element_size = sizeof(uint32_t);
418 break;
419 case DBUS_TYPE_INT64:
420 case DBUS_TYPE_UINT64:
421 element_size = sizeof(uint64_t);
422 break;
423 case DBUS_TYPE_DOUBLE:
424 element_size = sizeof(double);
425 break;
426 case DBUS_TYPE_STRING:
427 case DBUS_TYPE_OBJECT_PATH:
428 element_size = sizeof(char *);
429 break;
430 default:
431 dbus_set_error(error, DBUS_ERROR_FAILED,
432 "%s: unknown element type %d", __func__, type);
433 return FALSE;
434 }
435
436 for (i = 0; i < array_len; i++) {
437 if (!dbus_message_iter_append_basic(&array_iter, type,
438 array + i * element_size)) {
439 dbus_set_error(error, DBUS_ERROR_FAILED,
440 "%s: failed to construct message 2.5",
441 __func__);
442 return FALSE;
443 }
444 }
445
446 if (!dbus_message_iter_close_container(&variant_iter, &array_iter) ||
447 !dbus_message_iter_close_container(iter, &variant_iter)) {
448 dbus_set_error(error, DBUS_ERROR_FAILED,
449 "%s: failed to construct message 3", __func__);
450 return FALSE;
451 }
452
453 return TRUE;
454 }
455
456
457 /**
458 * wpas_dbus_simple_array_array_property_getter - Get array array type property
459 * @iter: Pointer to incoming dbus message iterator
460 * @type: DBus type of property array elements (must be basic type)
461 * @array: pointer to array of elements to put into response message
462 * @array_len: length of above array
463 * @error: a pointer to an error to fill on failure
464 * Returns: TRUE if the request succeeded, FALSE if it failed
465 *
466 * Generic getter for array type properties. Array elements type is
467 * required to be basic.
468 */
469 dbus_bool_t wpas_dbus_simple_array_array_property_getter(DBusMessageIter *iter,
470 const int type,
471 struct wpabuf **array,
472 size_t array_len,
473 DBusError *error)
474 {
475 DBusMessageIter variant_iter, array_iter;
476 char type_str[] = "aa?";
477 char inner_type_str[] = "a?";
478 const char *sub_type_str;
479 size_t i;
480
481 if (!dbus_type_is_basic(type)) {
482 dbus_set_error(error, DBUS_ERROR_FAILED,
483 "%s: given type is not basic", __func__);
484 return FALSE;
485 }
486
487 sub_type_str = wpa_dbus_type_as_string(type);
488 type_str[2] = sub_type_str[0];
489 inner_type_str[1] = sub_type_str[0];
490
491 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
492 type_str, &variant_iter) ||
493 !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
494 inner_type_str, &array_iter)) {
495 dbus_set_error(error, DBUS_ERROR_FAILED,
496 "%s: failed to construct message", __func__);
497 return FALSE;
498 }
499
500 for (i = 0; i < array_len && array[i]; i++) {
501 wpa_dbus_dict_bin_array_add_element(&array_iter,
502 wpabuf_head(array[i]),
503 wpabuf_len(array[i]));
504
505 }
506
507 if (!dbus_message_iter_close_container(&variant_iter, &array_iter) ||
508 !dbus_message_iter_close_container(iter, &variant_iter)) {
509 dbus_set_error(error, DBUS_ERROR_FAILED,
510 "%s: failed to close message", __func__);
511 return FALSE;
512 }
513
514 return TRUE;
515 }
516
517
518 /**
519 * wpas_dbus_handler_create_interface - Request registration of a network iface
520 * @message: Pointer to incoming dbus message
521 * @global: %wpa_supplicant global data structure
522 * Returns: The object path of the new interface object,
523 * or a dbus error message with more information
524 *
525 * Handler function for "CreateInterface" method call. Handles requests
526 * by dbus clients to register a network interface that wpa_supplicant
527 * will manage.
528 */
529 DBusMessage * wpas_dbus_handler_create_interface(DBusMessage *message,
530 struct wpa_global *global)
531 {
532 DBusMessageIter iter_dict;
533 DBusMessage *reply = NULL;
534 DBusMessageIter iter;
535 struct wpa_dbus_dict_entry entry;
536 char *driver = NULL;
537 char *ifname = NULL;
538 char *confname = NULL;
539 char *bridge_ifname = NULL;
540
541 dbus_message_iter_init(message, &iter);
542
543 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
544 goto error;
545 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
546 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
547 goto error;
548 if (os_strcmp(entry.key, "Driver") == 0 &&
549 entry.type == DBUS_TYPE_STRING) {
550 os_free(driver);
551 driver = os_strdup(entry.str_value);
552 wpa_dbus_dict_entry_clear(&entry);
553 if (driver == NULL)
554 goto oom;
555 } else if (os_strcmp(entry.key, "Ifname") == 0 &&
556 entry.type == DBUS_TYPE_STRING) {
557 os_free(ifname);
558 ifname = os_strdup(entry.str_value);
559 wpa_dbus_dict_entry_clear(&entry);
560 if (ifname == NULL)
561 goto oom;
562 } else if (os_strcmp(entry.key, "ConfigFile") == 0 &&
563 entry.type == DBUS_TYPE_STRING) {
564 os_free(confname);
565 confname = os_strdup(entry.str_value);
566 wpa_dbus_dict_entry_clear(&entry);
567 if (confname == NULL)
568 goto oom;
569 } else if (os_strcmp(entry.key, "BridgeIfname") == 0 &&
570 entry.type == DBUS_TYPE_STRING) {
571 os_free(bridge_ifname);
572 bridge_ifname = os_strdup(entry.str_value);
573 wpa_dbus_dict_entry_clear(&entry);
574 if (bridge_ifname == NULL)
575 goto oom;
576 } else {
577 wpa_dbus_dict_entry_clear(&entry);
578 goto error;
579 }
580 }
581
582 if (ifname == NULL)
583 goto error; /* Required Ifname argument missing */
584
585 /*
586 * Try to get the wpa_supplicant record for this iface, return
587 * an error if we already control it.
588 */
589 if (wpa_supplicant_get_iface(global, ifname) != NULL) {
590 reply = dbus_message_new_error(
591 message, WPAS_DBUS_ERROR_IFACE_EXISTS,
592 "wpa_supplicant already controls this interface.");
593 } else {
594 struct wpa_supplicant *wpa_s;
595 struct wpa_interface iface;
596
597 os_memset(&iface, 0, sizeof(iface));
598 iface.driver = driver;
599 iface.ifname = ifname;
600 iface.confname = confname;
601 iface.bridge_ifname = bridge_ifname;
602 /* Otherwise, have wpa_supplicant attach to it. */
603 wpa_s = wpa_supplicant_add_iface(global, &iface, NULL);
604 if (wpa_s && wpa_s->dbus_new_path) {
605 const char *path = wpa_s->dbus_new_path;
606
607 reply = dbus_message_new_method_return(message);
608 dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH,
609 &path, DBUS_TYPE_INVALID);
610 } else {
611 reply = wpas_dbus_error_unknown_error(
612 message,
613 "wpa_supplicant couldn't grab this interface.");
614 }
615 }
616
617 out:
618 os_free(driver);
619 os_free(ifname);
620 os_free(confname);
621 os_free(bridge_ifname);
622 return reply;
623
624 error:
625 reply = wpas_dbus_error_invalid_args(message, NULL);
626 goto out;
627 oom:
628 reply = wpas_dbus_error_no_memory(message);
629 goto out;
630 }
631
632
633 /**
634 * wpas_dbus_handler_remove_interface - Request deregistration of an interface
635 * @message: Pointer to incoming dbus message
636 * @global: wpa_supplicant global data structure
637 * Returns: a dbus message containing a UINT32 indicating success (1) or
638 * failure (0), or returns a dbus error message with more information
639 *
640 * Handler function for "removeInterface" method call. Handles requests
641 * by dbus clients to deregister a network interface that wpa_supplicant
642 * currently manages.
643 */
644 DBusMessage * wpas_dbus_handler_remove_interface(DBusMessage *message,
645 struct wpa_global *global)
646 {
647 struct wpa_supplicant *wpa_s;
648 char *path;
649 DBusMessage *reply = NULL;
650
651 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path,
652 DBUS_TYPE_INVALID);
653
654 wpa_s = get_iface_by_dbus_path(global, path);
655 if (wpa_s == NULL)
656 reply = wpas_dbus_error_iface_unknown(message);
657 else if (wpa_supplicant_remove_iface(global, wpa_s, 0)) {
658 reply = wpas_dbus_error_unknown_error(
659 message,
660 "wpa_supplicant couldn't remove this interface.");
661 }
662
663 return reply;
664 }
665
666
667 /**
668 * wpas_dbus_handler_get_interface - Get the object path for an interface name
669 * @message: Pointer to incoming dbus message
670 * @global: %wpa_supplicant global data structure
671 * Returns: The object path of the interface object,
672 * or a dbus error message with more information
673 *
674 * Handler function for "getInterface" method call.
675 */
676 DBusMessage * wpas_dbus_handler_get_interface(DBusMessage *message,
677 struct wpa_global *global)
678 {
679 DBusMessage *reply = NULL;
680 const char *ifname;
681 const char *path;
682 struct wpa_supplicant *wpa_s;
683
684 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &ifname,
685 DBUS_TYPE_INVALID);
686
687 wpa_s = wpa_supplicant_get_iface(global, ifname);
688 if (wpa_s == NULL || wpa_s->dbus_new_path == NULL)
689 return wpas_dbus_error_iface_unknown(message);
690
691 path = wpa_s->dbus_new_path;
692 reply = dbus_message_new_method_return(message);
693 if (reply == NULL)
694 return wpas_dbus_error_no_memory(message);
695 if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
696 DBUS_TYPE_INVALID)) {
697 dbus_message_unref(reply);
698 return wpas_dbus_error_no_memory(message);
699 }
700
701 return reply;
702 }
703
704
705 /**
706 * wpas_dbus_getter_debug_level - Get debug level
707 * @iter: Pointer to incoming dbus message iter
708 * @error: Location to store error on failure
709 * @user_data: Function specific data
710 * Returns: TRUE on success, FALSE on failure
711 *
712 * Getter for "DebugLevel" property.
713 */
714 dbus_bool_t wpas_dbus_getter_debug_level(DBusMessageIter *iter,
715 DBusError *error,
716 void *user_data)
717 {
718 const char *str;
719 int idx = wpa_debug_level;
720
721 if (idx < 0)
722 idx = 0;
723 if (idx > 5)
724 idx = 5;
725 str = debug_strings[idx];
726 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
727 &str, error);
728 }
729
730
731 /**
732 * wpas_dbus_getter_debug_timestamp - Get debug timestamp
733 * @iter: Pointer to incoming dbus message iter
734 * @error: Location to store error on failure
735 * @user_data: Function specific data
736 * Returns: TRUE on success, FALSE on failure
737 *
738 * Getter for "DebugTimestamp" property.
739 */
740 dbus_bool_t wpas_dbus_getter_debug_timestamp(DBusMessageIter *iter,
741 DBusError *error,
742 void *user_data)
743 {
744 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
745 &wpa_debug_timestamp, error);
746
747 }
748
749
750 /**
751 * wpas_dbus_getter_debug_show_keys - Get debug show keys
752 * @iter: Pointer to incoming dbus message iter
753 * @error: Location to store error on failure
754 * @user_data: Function specific data
755 * Returns: TRUE on success, FALSE on failure
756 *
757 * Getter for "DebugShowKeys" property.
758 */
759 dbus_bool_t wpas_dbus_getter_debug_show_keys(DBusMessageIter *iter,
760 DBusError *error,
761 void *user_data)
762 {
763 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
764 &wpa_debug_show_keys, error);
765
766 }
767
768 /**
769 * wpas_dbus_setter_debug_level - Set debug level
770 * @iter: Pointer to incoming dbus message iter
771 * @error: Location to store error on failure
772 * @user_data: Function specific data
773 * Returns: TRUE on success, FALSE on failure
774 *
775 * Setter for "DebugLevel" property.
776 */
777 dbus_bool_t wpas_dbus_setter_debug_level(DBusMessageIter *iter,
778 DBusError *error, void *user_data)
779 {
780 struct wpa_global *global = user_data;
781 const char *str = NULL;
782 int i, val = -1;
783
784 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
785 &str))
786 return FALSE;
787
788 for (i = 0; debug_strings[i]; i++)
789 if (os_strcmp(debug_strings[i], str) == 0) {
790 val = i;
791 break;
792 }
793
794 if (val < 0 ||
795 wpa_supplicant_set_debug_params(global, val, wpa_debug_timestamp,
796 wpa_debug_show_keys)) {
797 dbus_set_error_const(error, DBUS_ERROR_FAILED,
798 "wrong debug level value");
799 return FALSE;
800 }
801
802 return TRUE;
803 }
804
805
806 /**
807 * wpas_dbus_setter_debug_timestamp - Set debug timestamp
808 * @iter: Pointer to incoming dbus message iter
809 * @error: Location to store error on failure
810 * @user_data: Function specific data
811 * Returns: TRUE on success, FALSE on failure
812 *
813 * Setter for "DebugTimestamp" property.
814 */
815 dbus_bool_t wpas_dbus_setter_debug_timestamp(DBusMessageIter *iter,
816 DBusError *error,
817 void *user_data)
818 {
819 struct wpa_global *global = user_data;
820 dbus_bool_t val;
821
822 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
823 &val))
824 return FALSE;
825
826 wpa_supplicant_set_debug_params(global, wpa_debug_level, val ? 1 : 0,
827 wpa_debug_show_keys);
828 return TRUE;
829 }
830
831
832 /**
833 * wpas_dbus_setter_debug_show_keys - Set debug show keys
834 * @iter: Pointer to incoming dbus message iter
835 * @error: Location to store error on failure
836 * @user_data: Function specific data
837 * Returns: TRUE on success, FALSE on failure
838 *
839 * Setter for "DebugShowKeys" property.
840 */
841 dbus_bool_t wpas_dbus_setter_debug_show_keys(DBusMessageIter *iter,
842 DBusError *error,
843 void *user_data)
844 {
845 struct wpa_global *global = user_data;
846 dbus_bool_t val;
847
848 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
849 &val))
850 return FALSE;
851
852 wpa_supplicant_set_debug_params(global, wpa_debug_level,
853 wpa_debug_timestamp,
854 val ? 1 : 0);
855 return TRUE;
856 }
857
858
859 /**
860 * wpas_dbus_getter_interfaces - Request registered interfaces list
861 * @iter: Pointer to incoming dbus message iter
862 * @error: Location to store error on failure
863 * @user_data: Function specific data
864 * Returns: TRUE on success, FALSE on failure
865 *
866 * Getter for "Interfaces" property. Handles requests
867 * by dbus clients to return list of registered interfaces objects
868 * paths
869 */
870 dbus_bool_t wpas_dbus_getter_interfaces(DBusMessageIter *iter,
871 DBusError *error,
872 void *user_data)
873 {
874 struct wpa_global *global = user_data;
875 struct wpa_supplicant *wpa_s;
876 const char **paths;
877 unsigned int i = 0, num = 0;
878 dbus_bool_t success;
879
880 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
881 if (wpa_s->dbus_new_path)
882 num++;
883 }
884
885 paths = os_calloc(num, sizeof(char *));
886 if (!paths) {
887 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
888 return FALSE;
889 }
890
891 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
892 if (wpa_s->dbus_new_path)
893 paths[i++] = wpa_s->dbus_new_path;
894 }
895
896 success = wpas_dbus_simple_array_property_getter(iter,
897 DBUS_TYPE_OBJECT_PATH,
898 paths, num, error);
899
900 os_free(paths);
901 return success;
902 }
903
904
905 /**
906 * wpas_dbus_getter_eap_methods - Request supported EAP methods list
907 * @iter: Pointer to incoming dbus message iter
908 * @error: Location to store error on failure
909 * @user_data: Function specific data
910 * Returns: TRUE on success, FALSE on failure
911 *
912 * Getter for "EapMethods" property. Handles requests
913 * by dbus clients to return list of strings with supported EAP methods
914 */
915 dbus_bool_t wpas_dbus_getter_eap_methods(DBusMessageIter *iter,
916 DBusError *error, void *user_data)
917 {
918 char **eap_methods;
919 size_t num_items = 0;
920 dbus_bool_t success;
921
922 eap_methods = eap_get_names_as_string_array(&num_items);
923 if (!eap_methods) {
924 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
925 return FALSE;
926 }
927
928 success = wpas_dbus_simple_array_property_getter(iter,
929 DBUS_TYPE_STRING,
930 eap_methods,
931 num_items, error);
932
933 while (num_items)
934 os_free(eap_methods[--num_items]);
935 os_free(eap_methods);
936 return success;
937 }
938
939
940 /**
941 * wpas_dbus_getter_global_capabilities - Request supported global capabilities
942 * @iter: Pointer to incoming dbus message iter
943 * @error: Location to store error on failure
944 * @user_data: Function specific data
945 * Returns: TRUE on success, FALSE on failure
946 *
947 * Getter for "Capabilities" property. Handles requests by dbus clients to
948 * return a list of strings with supported capabilities like AP, RSN IBSS,
949 * and P2P that are determined at compile time.
950 */
951 dbus_bool_t wpas_dbus_getter_global_capabilities(DBusMessageIter *iter,
952 DBusError *error,
953 void *user_data)
954 {
955 const char *capabilities[5] = { NULL, NULL, NULL, NULL, NULL };
956 size_t num_items = 0;
957
958 #ifdef CONFIG_AP
959 capabilities[num_items++] = "ap";
960 #endif /* CONFIG_AP */
961 #ifdef CONFIG_IBSS_RSN
962 capabilities[num_items++] = "ibss-rsn";
963 #endif /* CONFIG_IBSS_RSN */
964 #ifdef CONFIG_P2P
965 capabilities[num_items++] = "p2p";
966 #endif /* CONFIG_P2P */
967 #ifdef CONFIG_INTERWORKING
968 capabilities[num_items++] = "interworking";
969 #endif /* CONFIG_INTERWORKING */
970
971 return wpas_dbus_simple_array_property_getter(iter,
972 DBUS_TYPE_STRING,
973 capabilities,
974 num_items, error);
975 }
976
977
978 static int wpas_dbus_get_scan_type(DBusMessage *message, DBusMessageIter *var,
979 char **type, DBusMessage **reply)
980 {
981 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_STRING) {
982 wpa_printf(MSG_DEBUG, "%s[dbus]: Type must be a string",
983 __func__);
984 *reply = wpas_dbus_error_invalid_args(
985 message, "Wrong Type value type. String required");
986 return -1;
987 }
988 dbus_message_iter_get_basic(var, type);
989 return 0;
990 }
991
992
993 static int wpas_dbus_get_scan_ssids(DBusMessage *message, DBusMessageIter *var,
994 struct wpa_driver_scan_params *params,
995 DBusMessage **reply)
996 {
997 struct wpa_driver_scan_ssid *ssids = params->ssids;
998 size_t ssids_num = 0;
999 u8 *ssid;
1000 DBusMessageIter array_iter, sub_array_iter;
1001 char *val;
1002 int len;
1003
1004 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
1005 wpa_printf(MSG_DEBUG,
1006 "%s[dbus]: ssids must be an array of arrays of bytes",
1007 __func__);
1008 *reply = wpas_dbus_error_invalid_args(
1009 message,
1010 "Wrong SSIDs value type. Array of arrays of bytes required");
1011 return -1;
1012 }
1013
1014 dbus_message_iter_recurse(var, &array_iter);
1015
1016 if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY ||
1017 dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_BYTE) {
1018 wpa_printf(MSG_DEBUG,
1019 "%s[dbus]: ssids must be an array of arrays of bytes",
1020 __func__);
1021 *reply = wpas_dbus_error_invalid_args(
1022 message,
1023 "Wrong SSIDs value type. Array of arrays of bytes required");
1024 return -1;
1025 }
1026
1027 while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_ARRAY) {
1028 if (ssids_num >= WPAS_MAX_SCAN_SSIDS) {
1029 wpa_printf(MSG_DEBUG,
1030 "%s[dbus]: Too many ssids specified on scan dbus call",
1031 __func__);
1032 *reply = wpas_dbus_error_invalid_args(
1033 message,
1034 "Too many ssids specified. Specify at most four");
1035 return -1;
1036 }
1037
1038 dbus_message_iter_recurse(&array_iter, &sub_array_iter);
1039
1040 dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len);
1041
1042 if (len > SSID_MAX_LEN) {
1043 wpa_printf(MSG_DEBUG,
1044 "%s[dbus]: SSID too long (len=%d max_len=%d)",
1045 __func__, len, SSID_MAX_LEN);
1046 *reply = wpas_dbus_error_invalid_args(
1047 message, "Invalid SSID: too long");
1048 return -1;
1049 }
1050
1051 if (len != 0) {
1052 ssid = os_malloc(len);
1053 if (ssid == NULL) {
1054 *reply = wpas_dbus_error_no_memory(message);
1055 return -1;
1056 }
1057 os_memcpy(ssid, val, len);
1058 } else {
1059 /* Allow zero-length SSIDs */
1060 ssid = NULL;
1061 }
1062
1063 ssids[ssids_num].ssid = ssid;
1064 ssids[ssids_num].ssid_len = len;
1065
1066 dbus_message_iter_next(&array_iter);
1067 ssids_num++;
1068 }
1069
1070 params->num_ssids = ssids_num;
1071 return 0;
1072 }
1073
1074
1075 static int wpas_dbus_get_scan_ies(DBusMessage *message, DBusMessageIter *var,
1076 struct wpa_driver_scan_params *params,
1077 DBusMessage **reply)
1078 {
1079 u8 *ies = NULL, *nies;
1080 int ies_len = 0;
1081 DBusMessageIter array_iter, sub_array_iter;
1082 char *val;
1083 int len;
1084
1085 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
1086 wpa_printf(MSG_DEBUG,
1087 "%s[dbus]: ies must be an array of arrays of bytes",
1088 __func__);
1089 *reply = wpas_dbus_error_invalid_args(
1090 message,
1091 "Wrong IEs value type. Array of arrays of bytes required");
1092 return -1;
1093 }
1094
1095 dbus_message_iter_recurse(var, &array_iter);
1096
1097 if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY ||
1098 dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_BYTE) {
1099 wpa_printf(MSG_DEBUG,
1100 "%s[dbus]: ies must be an array of arrays of bytes",
1101 __func__);
1102 *reply = wpas_dbus_error_invalid_args(
1103 message, "Wrong IEs value type. Array required");
1104 return -1;
1105 }
1106
1107 while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_ARRAY) {
1108 dbus_message_iter_recurse(&array_iter, &sub_array_iter);
1109
1110 dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len);
1111 if (len == 0) {
1112 dbus_message_iter_next(&array_iter);
1113 continue;
1114 }
1115
1116 nies = os_realloc(ies, ies_len + len);
1117 if (nies == NULL) {
1118 os_free(ies);
1119 *reply = wpas_dbus_error_no_memory(message);
1120 return -1;
1121 }
1122 ies = nies;
1123 os_memcpy(ies + ies_len, val, len);
1124 ies_len += len;
1125
1126 dbus_message_iter_next(&array_iter);
1127 }
1128
1129 params->extra_ies = ies;
1130 params->extra_ies_len = ies_len;
1131 return 0;
1132 }
1133
1134
1135 static int wpas_dbus_get_scan_channels(DBusMessage *message,
1136 DBusMessageIter *var,
1137 struct wpa_driver_scan_params *params,
1138 DBusMessage **reply)
1139 {
1140 DBusMessageIter array_iter, sub_array_iter;
1141 int *freqs = NULL, *nfreqs;
1142 int freqs_num = 0;
1143
1144 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
1145 wpa_printf(MSG_DEBUG,
1146 "%s[dbus]: Channels must be an array of structs",
1147 __func__);
1148 *reply = wpas_dbus_error_invalid_args(
1149 message,
1150 "Wrong Channels value type. Array of structs required");
1151 return -1;
1152 }
1153
1154 dbus_message_iter_recurse(var, &array_iter);
1155
1156 if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_STRUCT) {
1157 wpa_printf(MSG_DEBUG,
1158 "%s[dbus]: Channels must be an array of structs",
1159 __func__);
1160 *reply = wpas_dbus_error_invalid_args(
1161 message,
1162 "Wrong Channels value type. Array of structs required");
1163 return -1;
1164 }
1165
1166 while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_STRUCT)
1167 {
1168 int freq, width;
1169
1170 dbus_message_iter_recurse(&array_iter, &sub_array_iter);
1171
1172 if (dbus_message_iter_get_arg_type(&sub_array_iter) !=
1173 DBUS_TYPE_UINT32) {
1174 wpa_printf(MSG_DEBUG,
1175 "%s[dbus]: Channel must by specified by struct of two UINT32s %c",
1176 __func__,
1177 dbus_message_iter_get_arg_type(
1178 &sub_array_iter));
1179 *reply = wpas_dbus_error_invalid_args(
1180 message,
1181 "Wrong Channel struct. Two UINT32s required");
1182 os_free(freqs);
1183 return -1;
1184 }
1185 dbus_message_iter_get_basic(&sub_array_iter, &freq);
1186
1187 if (!dbus_message_iter_next(&sub_array_iter) ||
1188 dbus_message_iter_get_arg_type(&sub_array_iter) !=
1189 DBUS_TYPE_UINT32) {
1190 wpa_printf(MSG_DEBUG,
1191 "%s[dbus]: Channel must by specified by struct of two UINT32s",
1192 __func__);
1193 *reply = wpas_dbus_error_invalid_args(
1194 message,
1195 "Wrong Channel struct. Two UINT32s required");
1196 os_free(freqs);
1197 return -1;
1198 }
1199
1200 dbus_message_iter_get_basic(&sub_array_iter, &width);
1201
1202 #define FREQS_ALLOC_CHUNK 32
1203 if (freqs_num % FREQS_ALLOC_CHUNK == 0) {
1204 nfreqs = os_realloc_array(
1205 freqs, freqs_num + FREQS_ALLOC_CHUNK,
1206 sizeof(int));
1207 if (nfreqs == NULL)
1208 os_free(freqs);
1209 freqs = nfreqs;
1210 }
1211 if (freqs == NULL) {
1212 *reply = wpas_dbus_error_no_memory(message);
1213 return -1;
1214 }
1215
1216 freqs[freqs_num] = freq;
1217
1218 freqs_num++;
1219 dbus_message_iter_next(&array_iter);
1220 }
1221
1222 nfreqs = os_realloc_array(freqs, freqs_num + 1, sizeof(int));
1223 if (nfreqs == NULL)
1224 os_free(freqs);
1225 freqs = nfreqs;
1226 if (freqs == NULL) {
1227 *reply = wpas_dbus_error_no_memory(message);
1228 return -1;
1229 }
1230 freqs[freqs_num] = 0;
1231
1232 params->freqs = freqs;
1233 return 0;
1234 }
1235
1236
1237 static int wpas_dbus_get_scan_allow_roam(DBusMessage *message,
1238 DBusMessageIter *var,
1239 dbus_bool_t *allow,
1240 DBusMessage **reply)
1241 {
1242 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_BOOLEAN) {
1243 wpa_printf(MSG_DEBUG, "%s[dbus]: Type must be a boolean",
1244 __func__);
1245 *reply = wpas_dbus_error_invalid_args(
1246 message, "Wrong Type value type. Boolean required");
1247 return -1;
1248 }
1249 dbus_message_iter_get_basic(var, allow);
1250 return 0;
1251 }
1252
1253
1254 /**
1255 * wpas_dbus_handler_scan - Request a wireless scan on an interface
1256 * @message: Pointer to incoming dbus message
1257 * @wpa_s: wpa_supplicant structure for a network interface
1258 * Returns: NULL indicating success or DBus error message on failure
1259 *
1260 * Handler function for "Scan" method call of a network device. Requests
1261 * that wpa_supplicant perform a wireless scan as soon as possible
1262 * on a particular wireless interface.
1263 */
1264 DBusMessage * wpas_dbus_handler_scan(DBusMessage *message,
1265 struct wpa_supplicant *wpa_s)
1266 {
1267 DBusMessage *reply = NULL;
1268 DBusMessageIter iter, dict_iter, entry_iter, variant_iter;
1269 char *key = NULL, *type = NULL;
1270 struct wpa_driver_scan_params params;
1271 size_t i;
1272 dbus_bool_t allow_roam = 1;
1273
1274 os_memset(&params, 0, sizeof(params));
1275
1276 dbus_message_iter_init(message, &iter);
1277
1278 dbus_message_iter_recurse(&iter, &dict_iter);
1279
1280 while (dbus_message_iter_get_arg_type(&dict_iter) ==
1281 DBUS_TYPE_DICT_ENTRY) {
1282 dbus_message_iter_recurse(&dict_iter, &entry_iter);
1283 dbus_message_iter_get_basic(&entry_iter, &key);
1284 dbus_message_iter_next(&entry_iter);
1285 dbus_message_iter_recurse(&entry_iter, &variant_iter);
1286
1287 if (os_strcmp(key, "Type") == 0) {
1288 if (wpas_dbus_get_scan_type(message, &variant_iter,
1289 &type, &reply) < 0)
1290 goto out;
1291 } else if (os_strcmp(key, "SSIDs") == 0) {
1292 if (wpas_dbus_get_scan_ssids(message, &variant_iter,
1293 &params, &reply) < 0)
1294 goto out;
1295 } else if (os_strcmp(key, "IEs") == 0) {
1296 if (wpas_dbus_get_scan_ies(message, &variant_iter,
1297 &params, &reply) < 0)
1298 goto out;
1299 } else if (os_strcmp(key, "Channels") == 0) {
1300 if (wpas_dbus_get_scan_channels(message, &variant_iter,
1301 &params, &reply) < 0)
1302 goto out;
1303 } else if (os_strcmp(key, "AllowRoam") == 0) {
1304 if (wpas_dbus_get_scan_allow_roam(message,
1305 &variant_iter,
1306 &allow_roam,
1307 &reply) < 0)
1308 goto out;
1309 } else {
1310 wpa_printf(MSG_DEBUG, "%s[dbus]: Unknown argument %s",
1311 __func__, key);
1312 reply = wpas_dbus_error_invalid_args(message, key);
1313 goto out;
1314 }
1315
1316 dbus_message_iter_next(&dict_iter);
1317 }
1318
1319 if (!type) {
1320 wpa_printf(MSG_DEBUG, "%s[dbus]: Scan type not specified",
1321 __func__);
1322 reply = wpas_dbus_error_invalid_args(message, key);
1323 goto out;
1324 }
1325
1326 if (os_strcmp(type, "passive") == 0) {
1327 if (params.num_ssids || params.extra_ies_len) {
1328 wpa_printf(MSG_DEBUG,
1329 "%s[dbus]: SSIDs or IEs specified for passive scan.",
1330 __func__);
1331 reply = wpas_dbus_error_invalid_args(
1332 message,
1333 "You can specify only Channels in passive scan");
1334 goto out;
1335 } else {
1336 if (wpa_s->sched_scanning) {
1337 wpa_printf(MSG_DEBUG,
1338 "%s[dbus]: Stop ongoing sched_scan to allow requested scan to proceed",
1339 __func__);
1340 wpa_supplicant_cancel_sched_scan(wpa_s);
1341 }
1342
1343 if (params.freqs && params.freqs[0]) {
1344 wpa_s->last_scan_req = MANUAL_SCAN_REQ;
1345 if (wpa_supplicant_trigger_scan(wpa_s,
1346 &params)) {
1347 reply = wpas_dbus_error_scan_error(
1348 message,
1349 "Scan request rejected");
1350 }
1351 } else {
1352 wpa_s->scan_req = MANUAL_SCAN_REQ;
1353 wpa_supplicant_req_scan(wpa_s, 0, 0);
1354 }
1355 }
1356 } else if (os_strcmp(type, "active") == 0) {
1357 if (!params.num_ssids) {
1358 /* Add wildcard ssid */
1359 params.num_ssids++;
1360 }
1361 #ifdef CONFIG_AUTOSCAN
1362 autoscan_deinit(wpa_s);
1363 #endif /* CONFIG_AUTOSCAN */
1364 if (wpa_s->sched_scanning) {
1365 wpa_printf(MSG_DEBUG,
1366 "%s[dbus]: Stop ongoing sched_scan to allow requested scan to proceed",
1367 __func__);
1368 wpa_supplicant_cancel_sched_scan(wpa_s);
1369 }
1370
1371 wpa_s->last_scan_req = MANUAL_SCAN_REQ;
1372 if (wpa_supplicant_trigger_scan(wpa_s, &params)) {
1373 reply = wpas_dbus_error_scan_error(
1374 message, "Scan request rejected");
1375 }
1376 } else {
1377 wpa_printf(MSG_DEBUG, "%s[dbus]: Unknown scan type: %s",
1378 __func__, type);
1379 reply = wpas_dbus_error_invalid_args(message,
1380 "Wrong scan type");
1381 goto out;
1382 }
1383
1384 if (!allow_roam)
1385 wpa_s->scan_res_handler = scan_only_handler;
1386
1387 out:
1388 for (i = 0; i < WPAS_MAX_SCAN_SSIDS; i++)
1389 os_free((u8 *) params.ssids[i].ssid);
1390 os_free((u8 *) params.extra_ies);
1391 os_free(params.freqs);
1392 return reply;
1393 }
1394
1395
1396 /**
1397 * wpas_dbus_handler_signal_poll - Request immediate signal properties
1398 * @message: Pointer to incoming dbus message
1399 * @wpa_s: wpa_supplicant structure for a network interface
1400 * Returns: NULL indicating success or DBus error message on failure
1401 *
1402 * Handler function for "SignalPoll" method call of a network device. Requests
1403 * that wpa_supplicant read signal properties like RSSI, noise, and link
1404 * speed and return them.
1405 */
1406 DBusMessage * wpas_dbus_handler_signal_poll(DBusMessage *message,
1407 struct wpa_supplicant *wpa_s)
1408 {
1409 struct wpa_signal_info si;
1410 DBusMessage *reply = NULL;
1411 DBusMessageIter iter, iter_dict, variant_iter;
1412 int ret;
1413
1414 ret = wpa_drv_signal_poll(wpa_s, &si);
1415 if (ret) {
1416 return dbus_message_new_error(message, DBUS_ERROR_FAILED,
1417 "Failed to read signal");
1418 }
1419
1420 reply = dbus_message_new_method_return(message);
1421 if (reply == NULL)
1422 goto nomem;
1423
1424 dbus_message_iter_init_append(reply, &iter);
1425
1426 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
1427 "a{sv}", &variant_iter) ||
1428 !wpa_dbus_dict_open_write(&variant_iter, &iter_dict) ||
1429 !wpa_dbus_dict_append_int32(&iter_dict, "rssi",
1430 si.current_signal) ||
1431 !wpa_dbus_dict_append_int32(&iter_dict, "linkspeed",
1432 si.current_txrate / 1000) ||
1433 !wpa_dbus_dict_append_int32(&iter_dict, "noise",
1434 si.current_noise) ||
1435 !wpa_dbus_dict_append_uint32(&iter_dict, "frequency",
1436 si.frequency) ||
1437 (si.chanwidth != CHAN_WIDTH_UNKNOWN &&
1438 !wpa_dbus_dict_append_string(
1439 &iter_dict, "width",
1440 channel_width_to_string(si.chanwidth))) ||
1441 (si.center_frq1 > 0 && si.center_frq2 > 0 &&
1442 (!wpa_dbus_dict_append_int32(&iter_dict, "center-frq1",
1443 si.center_frq1) ||
1444 !wpa_dbus_dict_append_int32(&iter_dict, "center-frq2",
1445 si.center_frq2))) ||
1446 (si.avg_signal &&
1447 !wpa_dbus_dict_append_int32(&iter_dict, "avg-rssi",
1448 si.avg_signal)) ||
1449 !wpa_dbus_dict_close_write(&variant_iter, &iter_dict) ||
1450 !dbus_message_iter_close_container(&iter, &variant_iter))
1451 goto nomem;
1452
1453 return reply;
1454
1455 nomem:
1456 if (reply)
1457 dbus_message_unref(reply);
1458 return wpas_dbus_error_no_memory(message);
1459 }
1460
1461
1462 /*
1463 * wpas_dbus_handler_disconnect - Terminate the current connection
1464 * @message: Pointer to incoming dbus message
1465 * @wpa_s: wpa_supplicant structure for a network interface
1466 * Returns: NotConnected DBus error message if already not connected
1467 * or NULL otherwise.
1468 *
1469 * Handler function for "Disconnect" method call of network interface.
1470 */
1471 DBusMessage * wpas_dbus_handler_disconnect(DBusMessage *message,
1472 struct wpa_supplicant *wpa_s)
1473 {
1474 if (wpa_s->current_ssid != NULL) {
1475 wpa_s->disconnected = 1;
1476 wpa_supplicant_deauthenticate(wpa_s,
1477 WLAN_REASON_DEAUTH_LEAVING);
1478
1479 return NULL;
1480 }
1481
1482 return dbus_message_new_error(message, WPAS_DBUS_ERROR_NOT_CONNECTED,
1483 "This interface is not connected");
1484 }
1485
1486
1487 /**
1488 * wpas_dbus_new_iface_add_network - Add a new configured network
1489 * @message: Pointer to incoming dbus message
1490 * @wpa_s: wpa_supplicant structure for a network interface
1491 * Returns: A dbus message containing the object path of the new network
1492 *
1493 * Handler function for "AddNetwork" method call of a network interface.
1494 */
1495 DBusMessage * wpas_dbus_handler_add_network(DBusMessage *message,
1496 struct wpa_supplicant *wpa_s)
1497 {
1498 DBusMessage *reply = NULL;
1499 DBusMessageIter iter;
1500 struct wpa_ssid *ssid = NULL;
1501 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf;
1502 DBusError error;
1503
1504 dbus_message_iter_init(message, &iter);
1505
1506 if (wpa_s->dbus_new_path)
1507 ssid = wpa_config_add_network(wpa_s->conf);
1508 if (ssid == NULL) {
1509 wpa_printf(MSG_ERROR, "%s[dbus]: can't add new interface.",
1510 __func__);
1511 reply = wpas_dbus_error_unknown_error(
1512 message,
1513 "wpa_supplicant could not add a network on this interface.");
1514 goto err;
1515 }
1516 wpas_notify_network_added(wpa_s, ssid);
1517 ssid->disabled = 1;
1518 wpa_config_set_network_defaults(ssid);
1519
1520 dbus_error_init(&error);
1521 if (!set_network_properties(wpa_s, ssid, &iter, &error)) {
1522 wpa_printf(MSG_DEBUG,
1523 "%s[dbus]: control interface couldn't set network properties",
1524 __func__);
1525 reply = wpas_dbus_reply_new_from_error(message, &error,
1526 DBUS_ERROR_INVALID_ARGS,
1527 "Failed to add network");
1528 dbus_error_free(&error);
1529 goto err;
1530 }
1531
1532 /* Construct the object path for this network. */
1533 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
1534 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
1535 wpa_s->dbus_new_path, ssid->id);
1536
1537 reply = dbus_message_new_method_return(message);
1538 if (reply == NULL) {
1539 reply = wpas_dbus_error_no_memory(message);
1540 goto err;
1541 }
1542 if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
1543 DBUS_TYPE_INVALID)) {
1544 dbus_message_unref(reply);
1545 reply = wpas_dbus_error_no_memory(message);
1546 goto err;
1547 }
1548
1549 return reply;
1550
1551 err:
1552 if (ssid) {
1553 wpas_notify_network_removed(wpa_s, ssid);
1554 wpa_config_remove_network(wpa_s->conf, ssid->id);
1555 }
1556 return reply;
1557 }
1558
1559
1560 /**
1561 * wpas_dbus_handler_reassociate - Reassociate
1562 * @message: Pointer to incoming dbus message
1563 * @wpa_s: wpa_supplicant structure for a network interface
1564 * Returns: InterfaceDisabled DBus error message if disabled
1565 * or NULL otherwise.
1566 *
1567 * Handler function for "Reassociate" method call of network interface.
1568 */
1569 DBusMessage * wpas_dbus_handler_reassociate(DBusMessage *message,
1570 struct wpa_supplicant *wpa_s)
1571 {
1572 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED) {
1573 wpas_request_connection(wpa_s);
1574 return NULL;
1575 }
1576
1577 return dbus_message_new_error(message, WPAS_DBUS_ERROR_IFACE_DISABLED,
1578 "This interface is disabled");
1579 }
1580
1581
1582 /**
1583 * wpas_dbus_handler_reattach - Reattach to current AP
1584 * @message: Pointer to incoming dbus message
1585 * @wpa_s: wpa_supplicant structure for a network interface
1586 * Returns: NotConnected DBus error message if not connected
1587 * or NULL otherwise.
1588 *
1589 * Handler function for "Reattach" method call of network interface.
1590 */
1591 DBusMessage * wpas_dbus_handler_reattach(DBusMessage *message,
1592 struct wpa_supplicant *wpa_s)
1593 {
1594 if (wpa_s->current_ssid != NULL) {
1595 wpa_s->reattach = 1;
1596 wpas_request_connection(wpa_s);
1597 return NULL;
1598 }
1599
1600 return dbus_message_new_error(message, WPAS_DBUS_ERROR_NOT_CONNECTED,
1601 "This interface is not connected");
1602 }
1603
1604
1605 /**
1606 * wpas_dbus_handler_reconnect - Reconnect if disconnected
1607 * @message: Pointer to incoming dbus message
1608 * @wpa_s: wpa_supplicant structure for a network interface
1609 * Returns: InterfaceDisabled DBus error message if disabled
1610 * or NULL otherwise.
1611 *
1612 * Handler function for "Reconnect" method call of network interface.
1613 */
1614 DBusMessage * wpas_dbus_handler_reconnect(DBusMessage *message,
1615 struct wpa_supplicant *wpa_s)
1616 {
1617 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
1618 return dbus_message_new_error(message,
1619 WPAS_DBUS_ERROR_IFACE_DISABLED,
1620 "This interface is disabled");
1621 }
1622
1623 if (wpa_s->disconnected)
1624 wpas_request_connection(wpa_s);
1625 return NULL;
1626 }
1627
1628
1629 /**
1630 * wpas_dbus_handler_remove_network - Remove a configured network
1631 * @message: Pointer to incoming dbus message
1632 * @wpa_s: wpa_supplicant structure for a network interface
1633 * Returns: NULL on success or dbus error on failure
1634 *
1635 * Handler function for "RemoveNetwork" method call of a network interface.
1636 */
1637 DBusMessage * wpas_dbus_handler_remove_network(DBusMessage *message,
1638 struct wpa_supplicant *wpa_s)
1639 {
1640 DBusMessage *reply = NULL;
1641 const char *op;
1642 char *iface, *net_id;
1643 int id;
1644 struct wpa_ssid *ssid;
1645 int was_disabled;
1646
1647 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
1648 DBUS_TYPE_INVALID);
1649
1650 /* Extract the network ID and ensure the network */
1651 /* is actually a child of this interface */
1652 iface = wpas_dbus_new_decompose_object_path(op,
1653 WPAS_DBUS_NEW_NETWORKS_PART,
1654 &net_id);
1655 if (iface == NULL || net_id == NULL || !wpa_s->dbus_new_path ||
1656 os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
1657 reply = wpas_dbus_error_invalid_args(message, op);
1658 goto out;
1659 }
1660
1661 errno = 0;
1662 id = strtoul(net_id, NULL, 10);
1663 if (errno != 0) {
1664 reply = wpas_dbus_error_invalid_args(message, op);
1665 goto out;
1666 }
1667
1668 ssid = wpa_config_get_network(wpa_s->conf, id);
1669 if (ssid == NULL) {
1670 reply = wpas_dbus_error_network_unknown(message);
1671 goto out;
1672 }
1673
1674 was_disabled = ssid->disabled;
1675
1676 wpas_notify_network_removed(wpa_s, ssid);
1677
1678 if (ssid == wpa_s->current_ssid)
1679 wpa_supplicant_deauthenticate(wpa_s,
1680 WLAN_REASON_DEAUTH_LEAVING);
1681 else if (!was_disabled && wpa_s->sched_scanning) {
1682 wpa_printf(MSG_DEBUG,
1683 "Stop ongoing sched_scan to remove network from filters");
1684 wpa_supplicant_cancel_sched_scan(wpa_s);
1685 wpa_supplicant_req_scan(wpa_s, 0, 0);
1686 }
1687
1688 if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
1689 wpa_printf(MSG_ERROR,
1690 "%s[dbus]: error occurred when removing network %d",
1691 __func__, id);
1692 reply = wpas_dbus_error_unknown_error(
1693 message,
1694 "error removing the specified network on is interface.");
1695 goto out;
1696 }
1697
1698 out:
1699 os_free(iface);
1700 return reply;
1701 }
1702
1703
1704 static void remove_network(void *arg, struct wpa_ssid *ssid)
1705 {
1706 struct wpa_supplicant *wpa_s = arg;
1707
1708 wpas_notify_network_removed(wpa_s, ssid);
1709
1710 if (wpa_config_remove_network(wpa_s->conf, ssid->id) < 0) {
1711 wpa_printf(MSG_ERROR,
1712 "%s[dbus]: error occurred when removing network %d",
1713 __func__, ssid->id);
1714 return;
1715 }
1716
1717 if (ssid == wpa_s->current_ssid)
1718 wpa_supplicant_deauthenticate(wpa_s,
1719 WLAN_REASON_DEAUTH_LEAVING);
1720 }
1721
1722
1723 /**
1724 * wpas_dbus_handler_remove_all_networks - Remove all configured networks
1725 * @message: Pointer to incoming dbus message
1726 * @wpa_s: wpa_supplicant structure for a network interface
1727 * Returns: NULL on success or dbus error on failure
1728 *
1729 * Handler function for "RemoveAllNetworks" method call of a network interface.
1730 */
1731 DBusMessage * wpas_dbus_handler_remove_all_networks(
1732 DBusMessage *message, struct wpa_supplicant *wpa_s)
1733 {
1734 if (wpa_s->sched_scanning)
1735 wpa_supplicant_cancel_sched_scan(wpa_s);
1736
1737 /* NB: could check for failure and return an error */
1738 wpa_config_foreach_network(wpa_s->conf, remove_network, wpa_s);
1739 return NULL;
1740 }
1741
1742
1743 /**
1744 * wpas_dbus_handler_select_network - Attempt association with a network
1745 * @message: Pointer to incoming dbus message
1746 * @wpa_s: wpa_supplicant structure for a network interface
1747 * Returns: NULL on success or dbus error on failure
1748 *
1749 * Handler function for "SelectNetwork" method call of network interface.
1750 */
1751 DBusMessage * wpas_dbus_handler_select_network(DBusMessage *message,
1752 struct wpa_supplicant *wpa_s)
1753 {
1754 DBusMessage *reply = NULL;
1755 const char *op;
1756 char *iface, *net_id;
1757 int id;
1758 struct wpa_ssid *ssid;
1759
1760 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
1761 DBUS_TYPE_INVALID);
1762
1763 /* Extract the network ID and ensure the network */
1764 /* is actually a child of this interface */
1765 iface = wpas_dbus_new_decompose_object_path(op,
1766 WPAS_DBUS_NEW_NETWORKS_PART,
1767 &net_id);
1768 if (iface == NULL || net_id == NULL || !wpa_s->dbus_new_path ||
1769 os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
1770 reply = wpas_dbus_error_invalid_args(message, op);
1771 goto out;
1772 }
1773
1774 errno = 0;
1775 id = strtoul(net_id, NULL, 10);
1776 if (errno != 0) {
1777 reply = wpas_dbus_error_invalid_args(message, op);
1778 goto out;
1779 }
1780
1781 ssid = wpa_config_get_network(wpa_s->conf, id);
1782 if (ssid == NULL) {
1783 reply = wpas_dbus_error_network_unknown(message);
1784 goto out;
1785 }
1786
1787 /* Finally, associate with the network */
1788 wpa_supplicant_select_network(wpa_s, ssid);
1789
1790 out:
1791 os_free(iface);
1792 return reply;
1793 }
1794
1795
1796 /**
1797 * wpas_dbus_handler_network_reply - Reply to a NetworkRequest signal
1798 * @message: Pointer to incoming dbus message
1799 * @wpa_s: wpa_supplicant structure for a network interface
1800 * Returns: NULL on success or dbus error on failure
1801 *
1802 * Handler function for "NetworkReply" method call of network interface.
1803 */
1804 DBusMessage * wpas_dbus_handler_network_reply(DBusMessage *message,
1805 struct wpa_supplicant *wpa_s)
1806 {
1807 #ifdef IEEE8021X_EAPOL
1808 DBusMessage *reply = NULL;
1809 const char *op, *field, *value;
1810 char *iface, *net_id;
1811 int id;
1812 struct wpa_ssid *ssid;
1813
1814 if (!dbus_message_get_args(message, NULL,
1815 DBUS_TYPE_OBJECT_PATH, &op,
1816 DBUS_TYPE_STRING, &field,
1817 DBUS_TYPE_STRING, &value,
1818 DBUS_TYPE_INVALID))
1819 return wpas_dbus_error_invalid_args(message, NULL);
1820
1821 /* Extract the network ID and ensure the network */
1822 /* is actually a child of this interface */
1823 iface = wpas_dbus_new_decompose_object_path(op,
1824 WPAS_DBUS_NEW_NETWORKS_PART,
1825 &net_id);
1826 if (iface == NULL || net_id == NULL || !wpa_s->dbus_new_path ||
1827 os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
1828 reply = wpas_dbus_error_invalid_args(message, op);
1829 goto out;
1830 }
1831
1832 errno = 0;
1833 id = strtoul(net_id, NULL, 10);
1834 if (errno != 0) {
1835 reply = wpas_dbus_error_invalid_args(message, net_id);
1836 goto out;
1837 }
1838
1839 ssid = wpa_config_get_network(wpa_s->conf, id);
1840 if (ssid == NULL) {
1841 reply = wpas_dbus_error_network_unknown(message);
1842 goto out;
1843 }
1844
1845 if (wpa_supplicant_ctrl_iface_ctrl_rsp_handle(wpa_s, ssid,
1846 field, value) < 0)
1847 reply = wpas_dbus_error_invalid_args(message, field);
1848 else {
1849 /* Tell EAP to retry immediately */
1850 eapol_sm_notify_ctrl_response(wpa_s->eapol);
1851 }
1852
1853 out:
1854 os_free(iface);
1855 return reply;
1856 #else /* IEEE8021X_EAPOL */
1857 wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included");
1858 return wpas_dbus_error_unknown_error(message, "802.1X not included");
1859 #endif /* IEEE8021X_EAPOL */
1860 }
1861
1862
1863 #ifndef CONFIG_NO_CONFIG_BLOBS
1864
1865 /**
1866 * wpas_dbus_handler_add_blob - Store named binary blob (ie, for certificates)
1867 * @message: Pointer to incoming dbus message
1868 * @wpa_s: %wpa_supplicant data structure
1869 * Returns: A dbus message containing an error on failure or NULL on success
1870 *
1871 * Asks wpa_supplicant to internally store a binary blobs.
1872 */
1873 DBusMessage * wpas_dbus_handler_add_blob(DBusMessage *message,
1874 struct wpa_supplicant *wpa_s)
1875 {
1876 DBusMessage *reply = NULL;
1877 DBusMessageIter iter, array_iter;
1878
1879 char *blob_name;
1880 u8 *blob_data;
1881 int blob_len;
1882 struct wpa_config_blob *blob = NULL;
1883
1884 dbus_message_iter_init(message, &iter);
1885 dbus_message_iter_get_basic(&iter, &blob_name);
1886
1887 if (wpa_config_get_blob(wpa_s->conf, blob_name)) {
1888 return dbus_message_new_error(message,
1889 WPAS_DBUS_ERROR_BLOB_EXISTS,
1890 NULL);
1891 }
1892
1893 dbus_message_iter_next(&iter);
1894 dbus_message_iter_recurse(&iter, &array_iter);
1895
1896 dbus_message_iter_get_fixed_array(&array_iter, &blob_data, &blob_len);
1897
1898 blob = os_zalloc(sizeof(*blob));
1899 if (!blob) {
1900 reply = wpas_dbus_error_no_memory(message);
1901 goto err;
1902 }
1903
1904 blob->data = os_malloc(blob_len);
1905 blob->name = os_strdup(blob_name);
1906 if (!blob->data || !blob->name) {
1907 reply = wpas_dbus_error_no_memory(message);
1908 goto err;
1909 }
1910 os_memcpy(blob->data, blob_data, blob_len);
1911 blob->len = blob_len;
1912
1913 wpa_config_set_blob(wpa_s->conf, blob);
1914 wpas_notify_blob_added(wpa_s, blob->name);
1915
1916 return reply;
1917
1918 err:
1919 if (blob) {
1920 os_free(blob->name);
1921 os_free(blob->data);
1922 os_free(blob);
1923 }
1924 return reply;
1925 }
1926
1927
1928 /**
1929 * wpas_dbus_handler_get_blob - Get named binary blob (ie, for certificates)
1930 * @message: Pointer to incoming dbus message
1931 * @wpa_s: %wpa_supplicant data structure
1932 * Returns: A dbus message containing array of bytes (blob)
1933 *
1934 * Gets one wpa_supplicant's binary blobs.
1935 */
1936 DBusMessage * wpas_dbus_handler_get_blob(DBusMessage *message,
1937 struct wpa_supplicant *wpa_s)
1938 {
1939 DBusMessage *reply = NULL;
1940 DBusMessageIter iter, array_iter;
1941
1942 char *blob_name;
1943 const struct wpa_config_blob *blob;
1944
1945 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &blob_name,
1946 DBUS_TYPE_INVALID);
1947
1948 blob = wpa_config_get_blob(wpa_s->conf, blob_name);
1949 if (!blob) {
1950 return dbus_message_new_error(message,
1951 WPAS_DBUS_ERROR_BLOB_UNKNOWN,
1952 "Blob id not set");
1953 }
1954
1955 reply = dbus_message_new_method_return(message);
1956 if (!reply)
1957 return wpas_dbus_error_no_memory(message);
1958
1959 dbus_message_iter_init_append(reply, &iter);
1960
1961 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
1962 DBUS_TYPE_BYTE_AS_STRING,
1963 &array_iter) ||
1964 !dbus_message_iter_append_fixed_array(&array_iter, DBUS_TYPE_BYTE,
1965 &(blob->data), blob->len) ||
1966 !dbus_message_iter_close_container(&iter, &array_iter)) {
1967 dbus_message_unref(reply);
1968 reply = wpas_dbus_error_no_memory(message);
1969 }
1970
1971 return reply;
1972 }
1973
1974
1975 /**
1976 * wpas_remove_handler_remove_blob - Remove named binary blob
1977 * @message: Pointer to incoming dbus message
1978 * @wpa_s: %wpa_supplicant data structure
1979 * Returns: NULL on success or dbus error
1980 *
1981 * Asks wpa_supplicant to internally remove a binary blobs.
1982 */
1983 DBusMessage * wpas_dbus_handler_remove_blob(DBusMessage *message,
1984 struct wpa_supplicant *wpa_s)
1985 {
1986 DBusMessage *reply = NULL;
1987 char *blob_name;
1988
1989 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &blob_name,
1990 DBUS_TYPE_INVALID);
1991
1992 if (wpa_config_remove_blob(wpa_s->conf, blob_name)) {
1993 return dbus_message_new_error(message,
1994 WPAS_DBUS_ERROR_BLOB_UNKNOWN,
1995 "Blob id not set");
1996 }
1997 wpas_notify_blob_removed(wpa_s, blob_name);
1998
1999 return reply;
2000
2001 }
2002
2003 #endif /* CONFIG_NO_CONFIG_BLOBS */
2004
2005
2006 /*
2007 * wpas_dbus_handler_flush_bss - Flush the BSS cache
2008 * @message: Pointer to incoming dbus message
2009 * @wpa_s: wpa_supplicant structure for a network interface
2010 * Returns: NULL
2011 *
2012 * Handler function for "FlushBSS" method call of network interface.
2013 */
2014 DBusMessage * wpas_dbus_handler_flush_bss(DBusMessage *message,
2015 struct wpa_supplicant *wpa_s)
2016 {
2017 dbus_uint32_t age;
2018
2019 dbus_message_get_args(message, NULL, DBUS_TYPE_UINT32, &age,
2020 DBUS_TYPE_INVALID);
2021
2022 if (age == 0)
2023 wpa_bss_flush(wpa_s);
2024 else
2025 wpa_bss_flush_by_age(wpa_s, age);
2026
2027 return NULL;
2028 }
2029
2030
2031 #ifdef CONFIG_AUTOSCAN
2032 /**
2033 * wpas_dbus_handler_autoscan - Set autoscan parameters for the interface
2034 * @message: Pointer to incoming dbus message
2035 * @wpa_s: wpa_supplicant structure for a network interface
2036 * Returns: NULL
2037 *
2038 * Handler function for "AutoScan" method call of network interface.
2039 */
2040 DBusMessage * wpas_dbus_handler_autoscan(DBusMessage *message,
2041 struct wpa_supplicant *wpa_s)
2042 {
2043 DBusMessage *reply = NULL;
2044 enum wpa_states state = wpa_s->wpa_state;
2045 char *arg;
2046
2047 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &arg,
2048 DBUS_TYPE_INVALID);
2049
2050 if (arg != NULL && os_strlen(arg) > 0) {
2051 char *tmp;
2052
2053 tmp = os_strdup(arg);
2054 if (tmp == NULL) {
2055 reply = wpas_dbus_error_no_memory(message);
2056 } else {
2057 os_free(wpa_s->conf->autoscan);
2058 wpa_s->conf->autoscan = tmp;
2059 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
2060 autoscan_init(wpa_s, 1);
2061 else if (state == WPA_SCANNING)
2062 wpa_supplicant_reinit_autoscan(wpa_s);
2063 }
2064 } else if (arg != NULL && os_strlen(arg) == 0) {
2065 os_free(wpa_s->conf->autoscan);
2066 wpa_s->conf->autoscan = NULL;
2067 autoscan_deinit(wpa_s);
2068 } else
2069 reply = dbus_message_new_error(message,
2070 DBUS_ERROR_INVALID_ARGS,
2071 NULL);
2072
2073 return reply;
2074 }
2075 #endif /* CONFIG_AUTOSCAN */
2076
2077
2078 /*
2079 * wpas_dbus_handler_eap_logoff - IEEE 802.1X EAPOL state machine logoff
2080 * @message: Pointer to incoming dbus message
2081 * @wpa_s: wpa_supplicant structure for a network interface
2082 * Returns: NULL
2083 *
2084 * Handler function for "EAPLogoff" method call of network interface.
2085 */
2086 DBusMessage * wpas_dbus_handler_eap_logoff(DBusMessage *message,
2087 struct wpa_supplicant *wpa_s)
2088 {
2089 eapol_sm_notify_logoff(wpa_s->eapol, TRUE);
2090 return NULL;
2091 }
2092
2093
2094 /*
2095 * wpas_dbus_handler_eap_logon - IEEE 802.1X EAPOL state machine logon
2096 * @message: Pointer to incoming dbus message
2097 * @wpa_s: wpa_supplicant structure for a network interface
2098 * Returns: NULL
2099 *
2100 * Handler function for "EAPLogin" method call of network interface.
2101 */
2102 DBusMessage * wpas_dbus_handler_eap_logon(DBusMessage *message,
2103 struct wpa_supplicant *wpa_s)
2104 {
2105 eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
2106 return NULL;
2107 }
2108
2109
2110 #ifdef CONFIG_TDLS
2111
2112 static int get_peer_hwaddr_helper(DBusMessage *message, const char *func_name,
2113 u8 *peer_address, DBusMessage **error)
2114 {
2115 const char *peer_string;
2116
2117 *error = NULL;
2118
2119 if (!dbus_message_get_args(message, NULL,
2120 DBUS_TYPE_STRING, &peer_string,
2121 DBUS_TYPE_INVALID)) {
2122 *error = wpas_dbus_error_invalid_args(message, NULL);
2123 return -1;
2124 }
2125
2126 if (hwaddr_aton(peer_string, peer_address)) {
2127 wpa_printf(MSG_DEBUG, "%s: invalid address '%s'",
2128 func_name, peer_string);
2129 *error = wpas_dbus_error_invalid_args(
2130 message, "Invalid hardware address format");
2131 return -1;
2132 }
2133
2134 return 0;
2135 }
2136
2137
2138 /*
2139 * wpas_dbus_handler_tdls_discover - Discover TDLS peer
2140 * @message: Pointer to incoming dbus message
2141 * @wpa_s: wpa_supplicant structure for a network interface
2142 * Returns: NULL indicating success or DBus error message on failure
2143 *
2144 * Handler function for "TDLSDiscover" method call of network interface.
2145 */
2146 DBusMessage * wpas_dbus_handler_tdls_discover(DBusMessage *message,
2147 struct wpa_supplicant *wpa_s)
2148 {
2149 u8 peer[ETH_ALEN];
2150 DBusMessage *error_reply;
2151 int ret;
2152
2153 if (get_peer_hwaddr_helper(message, __func__, peer, &error_reply) < 0)
2154 return error_reply;
2155
2156 wpa_printf(MSG_DEBUG, "DBUS TDLS_DISCOVER " MACSTR, MAC2STR(peer));
2157
2158 if (wpa_tdls_is_external_setup(wpa_s->wpa))
2159 ret = wpa_tdls_send_discovery_request(wpa_s->wpa, peer);
2160 else
2161 ret = wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer);
2162
2163 if (ret) {
2164 return wpas_dbus_error_unknown_error(
2165 message, "error performing TDLS discovery");
2166 }
2167
2168 return NULL;
2169 }
2170
2171
2172 /*
2173 * wpas_dbus_handler_tdls_setup - Setup TDLS session
2174 * @message: Pointer to incoming dbus message
2175 * @wpa_s: wpa_supplicant structure for a network interface
2176 * Returns: NULL indicating success or DBus error message on failure
2177 *
2178 * Handler function for "TDLSSetup" method call of network interface.
2179 */
2180 DBusMessage * wpas_dbus_handler_tdls_setup(DBusMessage *message,
2181 struct wpa_supplicant *wpa_s)
2182 {
2183 u8 peer[ETH_ALEN];
2184 DBusMessage *error_reply;
2185 int ret;
2186
2187 if (get_peer_hwaddr_helper(message, __func__, peer, &error_reply) < 0)
2188 return error_reply;
2189
2190 wpa_printf(MSG_DEBUG, "DBUS TDLS_SETUP " MACSTR, MAC2STR(peer));
2191
2192 wpa_tdls_remove(wpa_s->wpa, peer);
2193 if (wpa_tdls_is_external_setup(wpa_s->wpa))
2194 ret = wpa_tdls_start(wpa_s->wpa, peer);
2195 else
2196 ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
2197
2198 if (ret) {
2199 return wpas_dbus_error_unknown_error(
2200 message, "error performing TDLS setup");
2201 }
2202
2203 return NULL;
2204 }
2205
2206
2207 /*
2208 * wpas_dbus_handler_tdls_status - Return TDLS session status
2209 * @message: Pointer to incoming dbus message
2210 * @wpa_s: wpa_supplicant structure for a network interface
2211 * Returns: A string representing the state of the link to this TDLS peer
2212 *
2213 * Handler function for "TDLSStatus" method call of network interface.
2214 */
2215 DBusMessage * wpas_dbus_handler_tdls_status(DBusMessage *message,
2216 struct wpa_supplicant *wpa_s)
2217 {
2218 u8 peer[ETH_ALEN];
2219 DBusMessage *reply;
2220 const char *tdls_status;
2221
2222 if (get_peer_hwaddr_helper(message, __func__, peer, &reply) < 0)
2223 return reply;
2224
2225 wpa_printf(MSG_DEBUG, "DBUS TDLS_STATUS " MACSTR, MAC2STR(peer));
2226
2227 tdls_status = wpa_tdls_get_link_status(wpa_s->wpa, peer);
2228
2229 reply = dbus_message_new_method_return(message);
2230 dbus_message_append_args(reply, DBUS_TYPE_STRING,
2231 &tdls_status, DBUS_TYPE_INVALID);
2232 return reply;
2233 }
2234
2235
2236 /*
2237 * wpas_dbus_handler_tdls_teardown - Teardown TDLS session
2238 * @message: Pointer to incoming dbus message
2239 * @wpa_s: wpa_supplicant structure for a network interface
2240 * Returns: NULL indicating success or DBus error message on failure
2241 *
2242 * Handler function for "TDLSTeardown" method call of network interface.
2243 */
2244 DBusMessage * wpas_dbus_handler_tdls_teardown(DBusMessage *message,
2245 struct wpa_supplicant *wpa_s)
2246 {
2247 u8 peer[ETH_ALEN];
2248 DBusMessage *error_reply;
2249 int ret;
2250
2251 if (get_peer_hwaddr_helper(message, __func__, peer, &error_reply) < 0)
2252 return error_reply;
2253
2254 wpa_printf(MSG_DEBUG, "DBUS TDLS_TEARDOWN " MACSTR, MAC2STR(peer));
2255
2256 if (wpa_tdls_is_external_setup(wpa_s->wpa))
2257 ret = wpa_tdls_teardown_link(
2258 wpa_s->wpa, peer,
2259 WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
2260 else
2261 ret = wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
2262
2263 if (ret) {
2264 return wpas_dbus_error_unknown_error(
2265 message, "error performing TDLS teardown");
2266 }
2267
2268 return NULL;
2269 }
2270
2271 #endif /* CONFIG_TDLS */
2272
2273
2274 /**
2275 * wpas_dbus_handler_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
2276 * @message: Pointer to incoming dbus message
2277 * @wpa_s: %wpa_supplicant data structure
2278 * Returns: A dbus message containing an error on failure or NULL on success
2279 *
2280 * Sets the PKCS #11 engine and module path.
2281 */
2282 DBusMessage * wpas_dbus_handler_set_pkcs11_engine_and_module_path(
2283 DBusMessage *message, struct wpa_supplicant *wpa_s)
2284 {
2285 DBusMessageIter iter;
2286 char *value = NULL;
2287 char *pkcs11_engine_path = NULL;
2288 char *pkcs11_module_path = NULL;
2289
2290 dbus_message_iter_init(message, &iter);
2291 dbus_message_iter_get_basic(&iter, &value);
2292 if (value == NULL) {
2293 return dbus_message_new_error(
2294 message, DBUS_ERROR_INVALID_ARGS,
2295 "Invalid pkcs11_engine_path argument");
2296 }
2297 /* Empty path defaults to NULL */
2298 if (os_strlen(value))
2299 pkcs11_engine_path = value;
2300
2301 dbus_message_iter_next(&iter);
2302 dbus_message_iter_get_basic(&iter, &value);
2303 if (value == NULL) {
2304 os_free(pkcs11_engine_path);
2305 return dbus_message_new_error(
2306 message, DBUS_ERROR_INVALID_ARGS,
2307 "Invalid pkcs11_module_path argument");
2308 }
2309 /* Empty path defaults to NULL */
2310 if (os_strlen(value))
2311 pkcs11_module_path = value;
2312
2313 if (wpas_set_pkcs11_engine_and_module_path(wpa_s, pkcs11_engine_path,
2314 pkcs11_module_path))
2315 return dbus_message_new_error(
2316 message, DBUS_ERROR_FAILED,
2317 "Reinit of the EAPOL state machine with the new PKCS #11 engine and module path failed.");
2318
2319 if (wpa_s->dbus_new_path) {
2320 wpa_dbus_mark_property_changed(
2321 wpa_s->global->dbus, wpa_s->dbus_new_path,
2322 WPAS_DBUS_NEW_IFACE_INTERFACE, "PKCS11EnginePath");
2323 wpa_dbus_mark_property_changed(
2324 wpa_s->global->dbus, wpa_s->dbus_new_path,
2325 WPAS_DBUS_NEW_IFACE_INTERFACE, "PKCS11ModulePath");
2326 }
2327
2328 return NULL;
2329 }
2330
2331
2332 /**
2333 * wpas_dbus_getter_capabilities - Return interface capabilities
2334 * @iter: Pointer to incoming dbus message iter
2335 * @error: Location to store error on failure
2336 * @user_data: Function specific data
2337 * Returns: TRUE on success, FALSE on failure
2338 *
2339 * Getter for "Capabilities" property of an interface.
2340 */
2341 dbus_bool_t wpas_dbus_getter_capabilities(DBusMessageIter *iter,
2342 DBusError *error, void *user_data)
2343 {
2344 struct wpa_supplicant *wpa_s = user_data;
2345 struct wpa_driver_capa capa;
2346 int res;
2347 DBusMessageIter iter_dict, iter_dict_entry, iter_dict_val, iter_array,
2348 variant_iter;
2349 const char *scans[] = { "active", "passive", "ssid" };
2350
2351 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
2352 "a{sv}", &variant_iter) ||
2353 !wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
2354 goto nomem;
2355
2356 res = wpa_drv_get_capa(wpa_s, &capa);
2357
2358 /***** pairwise cipher */
2359 if (res < 0) {
2360 const char *args[] = {"ccmp", "tkip", "none"};
2361
2362 if (!wpa_dbus_dict_append_string_array(
2363 &iter_dict, "Pairwise", args,
2364 ARRAY_SIZE(args)))
2365 goto nomem;
2366 } else {
2367 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Pairwise",
2368 &iter_dict_entry,
2369 &iter_dict_val,
2370 &iter_array) ||
2371 ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP_256) &&
2372 !wpa_dbus_dict_string_array_add_element(
2373 &iter_array, "ccmp-256")) ||
2374 ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP_256) &&
2375 !wpa_dbus_dict_string_array_add_element(
2376 &iter_array, "gcmp-256")) ||
2377 ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) &&
2378 !wpa_dbus_dict_string_array_add_element(
2379 &iter_array, "ccmp")) ||
2380 ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP) &&
2381 !wpa_dbus_dict_string_array_add_element(
2382 &iter_array, "gcmp")) ||
2383 ((capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) &&
2384 !wpa_dbus_dict_string_array_add_element(
2385 &iter_array, "tkip")) ||
2386 ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) &&
2387 !wpa_dbus_dict_string_array_add_element(
2388 &iter_array, "none")) ||
2389 !wpa_dbus_dict_end_string_array(&iter_dict,
2390 &iter_dict_entry,
2391 &iter_dict_val,
2392 &iter_array))
2393 goto nomem;
2394 }
2395
2396 /***** group cipher */
2397 if (res < 0) {
2398 const char *args[] = {
2399 "ccmp", "tkip", "wep104", "wep40"
2400 };
2401
2402 if (!wpa_dbus_dict_append_string_array(
2403 &iter_dict, "Group", args,
2404 ARRAY_SIZE(args)))
2405 goto nomem;
2406 } else {
2407 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Group",
2408 &iter_dict_entry,
2409 &iter_dict_val,
2410 &iter_array) ||
2411 ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP_256) &&
2412 !wpa_dbus_dict_string_array_add_element(
2413 &iter_array, "ccmp-256")) ||
2414 ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP_256) &&
2415 !wpa_dbus_dict_string_array_add_element(
2416 &iter_array, "gcmp-256")) ||
2417 ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) &&
2418 !wpa_dbus_dict_string_array_add_element(
2419 &iter_array, "ccmp")) ||
2420 ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP) &&
2421 !wpa_dbus_dict_string_array_add_element(
2422 &iter_array, "gcmp")) ||
2423 ((capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) &&
2424 !wpa_dbus_dict_string_array_add_element(
2425 &iter_array, "tkip")) ||
2426 ((capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) &&
2427 !wpa_dbus_dict_string_array_add_element(
2428 &iter_array, "wep104")) ||
2429 ((capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) &&
2430 !wpa_dbus_dict_string_array_add_element(
2431 &iter_array, "wep40")) ||
2432 !wpa_dbus_dict_end_string_array(&iter_dict,
2433 &iter_dict_entry,
2434 &iter_dict_val,
2435 &iter_array))
2436 goto nomem;
2437 }
2438
2439 /***** key management */
2440 if (res < 0) {
2441 const char *args[] = {
2442 "wpa-psk", "wpa-eap", "ieee8021x", "wpa-none",
2443 #ifdef CONFIG_WPS
2444 "wps",
2445 #endif /* CONFIG_WPS */
2446 "none"
2447 };
2448 if (!wpa_dbus_dict_append_string_array(
2449 &iter_dict, "KeyMgmt", args,
2450 ARRAY_SIZE(args)))
2451 goto nomem;
2452 } else {
2453 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "KeyMgmt",
2454 &iter_dict_entry,
2455 &iter_dict_val,
2456 &iter_array) ||
2457 !wpa_dbus_dict_string_array_add_element(&iter_array,
2458 "none") ||
2459 !wpa_dbus_dict_string_array_add_element(&iter_array,
2460 "ieee8021x"))
2461 goto nomem;
2462
2463 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
2464 WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
2465 if (!wpa_dbus_dict_string_array_add_element(
2466 &iter_array, "wpa-eap") ||
2467 ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT) &&
2468 !wpa_dbus_dict_string_array_add_element(
2469 &iter_array, "wpa-ft-eap")))
2470 goto nomem;
2471
2472 /* TODO: Ensure that driver actually supports sha256 encryption. */
2473 #ifdef CONFIG_IEEE80211W
2474 if (!wpa_dbus_dict_string_array_add_element(
2475 &iter_array, "wpa-eap-sha256"))
2476 goto nomem;
2477 #endif /* CONFIG_IEEE80211W */
2478 }
2479
2480 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
2481 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
2482 if (!wpa_dbus_dict_string_array_add_element(
2483 &iter_array, "wpa-psk") ||
2484 ((capa.key_mgmt &
2485 WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK) &&
2486 !wpa_dbus_dict_string_array_add_element(
2487 &iter_array, "wpa-ft-psk")))
2488 goto nomem;
2489
2490 /* TODO: Ensure that driver actually supports sha256 encryption. */
2491 #ifdef CONFIG_IEEE80211W
2492 if (!wpa_dbus_dict_string_array_add_element(
2493 &iter_array, "wpa-psk-sha256"))
2494 goto nomem;
2495 #endif /* CONFIG_IEEE80211W */
2496 }
2497
2498 if ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) &&
2499 !wpa_dbus_dict_string_array_add_element(&iter_array,
2500 "wpa-none"))
2501 goto nomem;
2502
2503
2504 #ifdef CONFIG_WPS
2505 if (!wpa_dbus_dict_string_array_add_element(&iter_array,
2506 "wps"))
2507 goto nomem;
2508 #endif /* CONFIG_WPS */
2509
2510 if (!wpa_dbus_dict_end_string_array(&iter_dict,
2511 &iter_dict_entry,
2512 &iter_dict_val,
2513 &iter_array))
2514 goto nomem;
2515 }
2516
2517 /***** WPA protocol */
2518 if (res < 0) {
2519 const char *args[] = { "rsn", "wpa" };
2520
2521 if (!wpa_dbus_dict_append_string_array(
2522 &iter_dict, "Protocol", args,
2523 ARRAY_SIZE(args)))
2524 goto nomem;
2525 } else {
2526 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Protocol",
2527 &iter_dict_entry,
2528 &iter_dict_val,
2529 &iter_array) ||
2530 ((capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
2531 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) &&
2532 !wpa_dbus_dict_string_array_add_element(
2533 &iter_array, "rsn")) ||
2534 ((capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
2535 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) &&
2536 !wpa_dbus_dict_string_array_add_element(
2537 &iter_array, "wpa")) ||
2538 !wpa_dbus_dict_end_string_array(&iter_dict,
2539 &iter_dict_entry,
2540 &iter_dict_val,
2541 &iter_array))
2542 goto nomem;
2543 }
2544
2545 /***** auth alg */
2546 if (res < 0) {
2547 const char *args[] = { "open", "shared", "leap" };
2548
2549 if (!wpa_dbus_dict_append_string_array(
2550 &iter_dict, "AuthAlg", args,
2551 ARRAY_SIZE(args)))
2552 goto nomem;
2553 } else {
2554 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "AuthAlg",
2555 &iter_dict_entry,
2556 &iter_dict_val,
2557 &iter_array))
2558 goto nomem;
2559
2560 if (((capa.auth & WPA_DRIVER_AUTH_OPEN) &&
2561 !wpa_dbus_dict_string_array_add_element(
2562 &iter_array, "open")) ||
2563 ((capa.auth & WPA_DRIVER_AUTH_SHARED) &&
2564 !wpa_dbus_dict_string_array_add_element(
2565 &iter_array, "shared")) ||
2566 ((capa.auth & WPA_DRIVER_AUTH_LEAP) &&
2567 !wpa_dbus_dict_string_array_add_element(
2568 &iter_array, "leap")) ||
2569 !wpa_dbus_dict_end_string_array(&iter_dict,
2570 &iter_dict_entry,
2571 &iter_dict_val,
2572 &iter_array))
2573 goto nomem;
2574 }
2575
2576 /***** Scan */
2577 if (!wpa_dbus_dict_append_string_array(&iter_dict, "Scan", scans,
2578 ARRAY_SIZE(scans)))
2579 goto nomem;
2580
2581 /***** Modes */
2582 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Modes",
2583 &iter_dict_entry,
2584 &iter_dict_val,
2585 &iter_array) ||
2586 !wpa_dbus_dict_string_array_add_element(
2587 &iter_array, "infrastructure") ||
2588 !wpa_dbus_dict_string_array_add_element(
2589 &iter_array, "ad-hoc") ||
2590 (res >= 0 && (capa.flags & WPA_DRIVER_FLAGS_AP) &&
2591 !wpa_dbus_dict_string_array_add_element(
2592 &iter_array, "ap")) ||
2593 (res >= 0 && (capa.flags & WPA_DRIVER_FLAGS_P2P_CAPABLE) &&
2594 !wpa_dbus_dict_string_array_add_element(
2595 &iter_array, "p2p")) ||
2596 !wpa_dbus_dict_end_string_array(&iter_dict,
2597 &iter_dict_entry,
2598 &iter_dict_val,
2599 &iter_array))
2600 goto nomem;
2601 /***** Modes end */
2602
2603 if (res >= 0) {
2604 dbus_int32_t max_scan_ssid = capa.max_scan_ssids;
2605
2606 if (!wpa_dbus_dict_append_int32(&iter_dict, "MaxScanSSID",
2607 max_scan_ssid))
2608 goto nomem;
2609 }
2610
2611 if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict) ||
2612 !dbus_message_iter_close_container(iter, &variant_iter))
2613 goto nomem;
2614
2615 return TRUE;
2616
2617 nomem:
2618 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
2619 return FALSE;
2620 }
2621
2622
2623 /**
2624 * wpas_dbus_getter_state - Get interface state
2625 * @iter: Pointer to incoming dbus message iter
2626 * @error: Location to store error on failure
2627 * @user_data: Function specific data
2628 * Returns: TRUE on success, FALSE on failure
2629 *
2630 * Getter for "State" property.
2631 */
2632 dbus_bool_t wpas_dbus_getter_state(DBusMessageIter *iter, DBusError *error,
2633 void *user_data)
2634 {
2635 struct wpa_supplicant *wpa_s = user_data;
2636 const char *str_state;
2637 char *state_ls, *tmp;
2638 dbus_bool_t success = FALSE;
2639
2640 str_state = wpa_supplicant_state_txt(wpa_s->wpa_state);
2641
2642 /* make state string lowercase to fit new DBus API convention
2643 */
2644 state_ls = tmp = os_strdup(str_state);
2645 if (!tmp) {
2646 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
2647 return FALSE;
2648 }
2649 while (*tmp) {
2650 *tmp = tolower(*tmp);
2651 tmp++;
2652 }
2653
2654 success = wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
2655 &state_ls, error);
2656
2657 os_free(state_ls);
2658
2659 return success;
2660 }
2661
2662
2663 /**
2664 * wpas_dbus_new_iface_get_scanning - Get interface scanning state
2665 * @iter: Pointer to incoming dbus message iter
2666 * @error: Location to store error on failure
2667 * @user_data: Function specific data
2668 * Returns: TRUE on success, FALSE on failure
2669 *
2670 * Getter for "scanning" property.
2671 */
2672 dbus_bool_t wpas_dbus_getter_scanning(DBusMessageIter *iter, DBusError *error,
2673 void *user_data)
2674 {
2675 struct wpa_supplicant *wpa_s = user_data;
2676 dbus_bool_t scanning = wpa_s->scanning ? TRUE : FALSE;
2677
2678 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
2679 &scanning, error);
2680 }
2681
2682
2683 /**
2684 * wpas_dbus_getter_ap_scan - Control roaming mode
2685 * @iter: Pointer to incoming dbus message iter
2686 * @error: Location to store error on failure
2687 * @user_data: Function specific data
2688 * Returns: TRUE on success, FALSE on failure
2689 *
2690 * Getter function for "ApScan" property.
2691 */
2692 dbus_bool_t wpas_dbus_getter_ap_scan(DBusMessageIter *iter, DBusError *error,
2693 void *user_data)
2694 {
2695 struct wpa_supplicant *wpa_s = user_data;
2696 dbus_uint32_t ap_scan = wpa_s->conf->ap_scan;
2697
2698 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
2699 &ap_scan, error);
2700 }
2701
2702
2703 /**
2704 * wpas_dbus_setter_ap_scan - Control roaming mode
2705 * @iter: Pointer to incoming dbus message iter
2706 * @error: Location to store error on failure
2707 * @user_data: Function specific data
2708 * Returns: TRUE on success, FALSE on failure
2709 *
2710 * Setter function for "ApScan" property.
2711 */
2712 dbus_bool_t wpas_dbus_setter_ap_scan(DBusMessageIter *iter, DBusError *error,
2713 void *user_data)
2714 {
2715 struct wpa_supplicant *wpa_s = user_data;
2716 dbus_uint32_t ap_scan;
2717
2718 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
2719 &ap_scan))
2720 return FALSE;
2721
2722 if (wpa_supplicant_set_ap_scan(wpa_s, ap_scan)) {
2723 dbus_set_error_const(error, DBUS_ERROR_FAILED,
2724 "ap_scan must be 0, 1, or 2");
2725 return FALSE;
2726 }
2727 return TRUE;
2728 }
2729
2730
2731 /**
2732 * wpas_dbus_getter_fast_reauth - Control fast
2733 * reauthentication (TLS session resumption)
2734 * @iter: Pointer to incoming dbus message iter
2735 * @error: Location to store error on failure
2736 * @user_data: Function specific data
2737 * Returns: TRUE on success, FALSE on failure
2738 *
2739 * Getter function for "FastReauth" property.
2740 */
2741 dbus_bool_t wpas_dbus_getter_fast_reauth(DBusMessageIter *iter,
2742 DBusError *error,
2743 void *user_data)
2744 {
2745 struct wpa_supplicant *wpa_s = user_data;
2746 dbus_bool_t fast_reauth = wpa_s->conf->fast_reauth ? TRUE : FALSE;
2747
2748 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
2749 &fast_reauth, error);
2750 }
2751
2752
2753 /**
2754 * wpas_dbus_setter_fast_reauth - Control fast
2755 * reauthentication (TLS session resumption)
2756 * @iter: Pointer to incoming dbus message iter
2757 * @error: Location to store error on failure
2758 * @user_data: Function specific data
2759 * Returns: TRUE on success, FALSE on failure
2760 *
2761 * Setter function for "FastReauth" property.
2762 */
2763 dbus_bool_t wpas_dbus_setter_fast_reauth(DBusMessageIter *iter,
2764 DBusError *error,
2765 void *user_data)
2766 {
2767 struct wpa_supplicant *wpa_s = user_data;
2768 dbus_bool_t fast_reauth;
2769
2770 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
2771 &fast_reauth))
2772 return FALSE;
2773
2774 wpa_s->conf->fast_reauth = fast_reauth;
2775 return TRUE;
2776 }
2777
2778
2779 /**
2780 * wpas_dbus_getter_disconnect_reason - Get most recent reason for disconnect
2781 * @iter: Pointer to incoming dbus message iter
2782 * @error: Location to store error on failure
2783 * @user_data: Function specific data
2784 * Returns: TRUE on success, FALSE on failure
2785 *
2786 * Getter for "DisconnectReason" property. The reason is negative if it is
2787 * locally generated.
2788 */
2789 dbus_bool_t wpas_dbus_getter_disconnect_reason(DBusMessageIter *iter,
2790 DBusError *error,
2791 void *user_data)
2792 {
2793 struct wpa_supplicant *wpa_s = user_data;
2794 dbus_int32_t reason = wpa_s->disconnect_reason;
2795
2796 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
2797 &reason, error);
2798 }
2799
2800
2801 /**
2802 * wpas_dbus_getter_bss_expire_age - Get BSS entry expiration age
2803 * @iter: Pointer to incoming dbus message iter
2804 * @error: Location to store error on failure
2805 * @user_data: Function specific data
2806 * Returns: TRUE on success, FALSE on failure
2807 *
2808 * Getter function for "BSSExpireAge" property.
2809 */
2810 dbus_bool_t wpas_dbus_getter_bss_expire_age(DBusMessageIter *iter,
2811 DBusError *error,
2812 void *user_data)
2813 {
2814 struct wpa_supplicant *wpa_s = user_data;
2815 dbus_uint32_t expire_age = wpa_s->conf->bss_expiration_age;
2816
2817 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
2818 &expire_age, error);
2819 }
2820
2821
2822 /**
2823 * wpas_dbus_setter_bss_expire_age - Control BSS entry expiration age
2824 * @iter: Pointer to incoming dbus message iter
2825 * @error: Location to store error on failure
2826 * @user_data: Function specific data
2827 * Returns: TRUE on success, FALSE on failure
2828 *
2829 * Setter function for "BSSExpireAge" property.
2830 */
2831 dbus_bool_t wpas_dbus_setter_bss_expire_age(DBusMessageIter *iter,
2832 DBusError *error,
2833 void *user_data)
2834 {
2835 struct wpa_supplicant *wpa_s = user_data;
2836 dbus_uint32_t expire_age;
2837
2838 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
2839 &expire_age))
2840 return FALSE;
2841
2842 if (wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age)) {
2843 dbus_set_error_const(error, DBUS_ERROR_FAILED,
2844 "BSSExpireAge must be >= 10");
2845 return FALSE;
2846 }
2847 return TRUE;
2848 }
2849
2850
2851 /**
2852 * wpas_dbus_getter_bss_expire_count - Get BSS entry expiration scan count
2853 * @iter: Pointer to incoming dbus message iter
2854 * @error: Location to store error on failure
2855 * @user_data: Function specific data
2856 * Returns: TRUE on success, FALSE on failure
2857 *
2858 * Getter function for "BSSExpireCount" property.
2859 */
2860 dbus_bool_t wpas_dbus_getter_bss_expire_count(DBusMessageIter *iter,
2861 DBusError *error,
2862 void *user_data)
2863 {
2864 struct wpa_supplicant *wpa_s = user_data;
2865 dbus_uint32_t expire_count = wpa_s->conf->bss_expiration_scan_count;
2866
2867 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
2868 &expire_count, error);
2869 }
2870
2871
2872 /**
2873 * wpas_dbus_setter_bss_expire_count - Control BSS entry expiration scan count
2874 * @iter: Pointer to incoming dbus message iter
2875 * @error: Location to store error on failure
2876 * @user_data: Function specific data
2877 * Returns: TRUE on success, FALSE on failure
2878 *
2879 * Setter function for "BSSExpireCount" property.
2880 */
2881 dbus_bool_t wpas_dbus_setter_bss_expire_count(DBusMessageIter *iter,
2882 DBusError *error,
2883 void *user_data)
2884 {
2885 struct wpa_supplicant *wpa_s = user_data;
2886 dbus_uint32_t expire_count;
2887
2888 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
2889 &expire_count))
2890 return FALSE;
2891
2892 if (wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count)) {
2893 dbus_set_error_const(error, DBUS_ERROR_FAILED,
2894 "BSSExpireCount must be > 0");
2895 return FALSE;
2896 }
2897 return TRUE;
2898 }
2899
2900
2901 /**
2902 * wpas_dbus_getter_country - Control country code
2903 * @iter: Pointer to incoming dbus message iter
2904 * @error: Location to store error on failure
2905 * @user_data: Function specific data
2906 * Returns: TRUE on success, FALSE on failure
2907 *
2908 * Getter function for "Country" property.
2909 */
2910 dbus_bool_t wpas_dbus_getter_country(DBusMessageIter *iter, DBusError *error,
2911 void *user_data)
2912 {
2913 struct wpa_supplicant *wpa_s = user_data;
2914 char country[3];
2915 char *str = country;
2916
2917 country[0] = wpa_s->conf->country[0];
2918 country[1] = wpa_s->conf->country[1];
2919 country[2] = '\0';
2920
2921 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
2922 &str, error);
2923 }
2924
2925
2926 /**
2927 * wpas_dbus_setter_country - Control country code
2928 * @iter: Pointer to incoming dbus message iter
2929 * @error: Location to store error on failure
2930 * @user_data: Function specific data
2931 * Returns: TRUE on success, FALSE on failure
2932 *
2933 * Setter function for "Country" property.
2934 */
2935 dbus_bool_t wpas_dbus_setter_country(DBusMessageIter *iter, DBusError *error,
2936 void *user_data)
2937 {
2938 struct wpa_supplicant *wpa_s = user_data;
2939 const char *country;
2940
2941 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
2942 &country))
2943 return FALSE;
2944
2945 if (!country[0] || !country[1]) {
2946 dbus_set_error_const(error, DBUS_ERROR_FAILED,
2947 "invalid country code");
2948 return FALSE;
2949 }
2950
2951 if (wpa_s->drv_priv != NULL && wpa_drv_set_country(wpa_s, country)) {
2952 wpa_printf(MSG_DEBUG, "Failed to set country");
2953 dbus_set_error_const(error, DBUS_ERROR_FAILED,
2954 "failed to set country code");
2955 return FALSE;
2956 }
2957
2958 wpa_s->conf->country[0] = country[0];
2959 wpa_s->conf->country[1] = country[1];
2960 return TRUE;
2961 }
2962
2963
2964 /**
2965 * wpas_dbus_getter_scan_interval - Get scan interval
2966 * @iter: Pointer to incoming dbus message iter
2967 * @error: Location to store error on failure
2968 * @user_data: Function specific data
2969 * Returns: TRUE on success, FALSE on failure
2970 *
2971 * Getter function for "ScanInterval" property.
2972 */
2973 dbus_bool_t wpas_dbus_getter_scan_interval(DBusMessageIter *iter,
2974 DBusError *error,
2975 void *user_data)
2976 {
2977 struct wpa_supplicant *wpa_s = user_data;
2978 dbus_int32_t scan_interval = wpa_s->scan_interval;
2979
2980 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
2981 &scan_interval, error);
2982 }
2983
2984
2985 /**
2986 * wpas_dbus_setter_scan_interval - Control scan interval
2987 * @iter: Pointer to incoming dbus message iter
2988 * @error: Location to store error on failure
2989 * @user_data: Function specific data
2990 * Returns: TRUE on success, FALSE on failure
2991 *
2992 * Setter function for "ScanInterval" property.
2993 */
2994 dbus_bool_t wpas_dbus_setter_scan_interval(DBusMessageIter *iter,
2995 DBusError *error,
2996 void *user_data)
2997 {
2998 struct wpa_supplicant *wpa_s = user_data;
2999 dbus_int32_t scan_interval;
3000
3001 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_INT32,
3002 &scan_interval))
3003 return FALSE;
3004
3005 if (wpa_supplicant_set_scan_interval(wpa_s, scan_interval)) {
3006 dbus_set_error_const(error, DBUS_ERROR_FAILED,
3007 "scan_interval must be >= 0");
3008 return FALSE;
3009 }
3010 return TRUE;
3011 }
3012
3013
3014 /**
3015 * wpas_dbus_getter_ifname - Get interface name
3016 * @iter: Pointer to incoming dbus message iter
3017 * @error: Location to store error on failure
3018 * @user_data: Function specific data
3019 * Returns: TRUE on success, FALSE on failure
3020 *
3021 * Getter for "Ifname" property.
3022 */
3023 dbus_bool_t wpas_dbus_getter_ifname(DBusMessageIter *iter, DBusError *error,
3024 void *user_data)
3025 {
3026 struct wpa_supplicant *wpa_s = user_data;
3027 const char *ifname = wpa_s->ifname;
3028
3029 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3030 &ifname, error);
3031 }
3032
3033
3034 /**
3035 * wpas_dbus_getter_driver - Get interface name
3036 * @iter: Pointer to incoming dbus message iter
3037 * @error: Location to store error on failure
3038 * @user_data: Function specific data
3039 * Returns: TRUE on success, FALSE on failure
3040 *
3041 * Getter for "Driver" property.
3042 */
3043 dbus_bool_t wpas_dbus_getter_driver(DBusMessageIter *iter, DBusError *error,
3044 void *user_data)
3045 {
3046 struct wpa_supplicant *wpa_s = user_data;
3047 const char *driver;
3048
3049 if (wpa_s->driver == NULL || wpa_s->driver->name == NULL) {
3050 wpa_printf(MSG_DEBUG, "%s[dbus]: wpa_s has no driver set",
3051 __func__);
3052 dbus_set_error(error, DBUS_ERROR_FAILED, "%s: no driver set",
3053 __func__);
3054 return FALSE;
3055 }
3056
3057 driver = wpa_s->driver->name;
3058 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3059 &driver, error);
3060 }
3061
3062
3063 /**
3064 * wpas_dbus_getter_current_bss - Get current bss object path
3065 * @iter: Pointer to incoming dbus message iter
3066 * @error: Location to store error on failure
3067 * @user_data: Function specific data
3068 * Returns: TRUE on success, FALSE on failure
3069 *
3070 * Getter for "CurrentBSS" property.
3071 */
3072 dbus_bool_t wpas_dbus_getter_current_bss(DBusMessageIter *iter,
3073 DBusError *error,
3074 void *user_data)
3075 {
3076 struct wpa_supplicant *wpa_s = user_data;
3077 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *bss_obj_path = path_buf;
3078
3079 if (wpa_s->current_bss && wpa_s->dbus_new_path)
3080 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3081 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
3082 wpa_s->dbus_new_path, wpa_s->current_bss->id);
3083 else
3084 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
3085
3086 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
3087 &bss_obj_path, error);
3088 }
3089
3090
3091 /**
3092 * wpas_dbus_getter_current_network - Get current network object path
3093 * @iter: Pointer to incoming dbus message iter
3094 * @error: Location to store error on failure
3095 * @user_data: Function specific data
3096 * Returns: TRUE on success, FALSE on failure
3097 *
3098 * Getter for "CurrentNetwork" property.
3099 */
3100 dbus_bool_t wpas_dbus_getter_current_network(DBusMessageIter *iter,
3101 DBusError *error,
3102 void *user_data)
3103 {
3104 struct wpa_supplicant *wpa_s = user_data;
3105 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *net_obj_path = path_buf;
3106
3107 if (wpa_s->current_ssid && wpa_s->dbus_new_path)
3108 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3109 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
3110 wpa_s->dbus_new_path, wpa_s->current_ssid->id);
3111 else
3112 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
3113
3114 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
3115 &net_obj_path, error);
3116 }
3117
3118
3119 /**
3120 * wpas_dbus_getter_current_auth_mode - Get current authentication type
3121 * @iter: Pointer to incoming dbus message iter
3122 * @error: Location to store error on failure
3123 * @user_data: Function specific data
3124 * Returns: TRUE on success, FALSE on failure
3125 *
3126 * Getter for "CurrentAuthMode" property.
3127 */
3128 dbus_bool_t wpas_dbus_getter_current_auth_mode(DBusMessageIter *iter,
3129 DBusError *error,
3130 void *user_data)
3131 {
3132 struct wpa_supplicant *wpa_s = user_data;
3133 const char *eap_mode;
3134 const char *auth_mode;
3135 char eap_mode_buf[WPAS_DBUS_AUTH_MODE_MAX];
3136
3137 if (wpa_s->wpa_state != WPA_COMPLETED) {
3138 auth_mode = "INACTIVE";
3139 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X ||
3140 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3141 eap_mode = wpa_supplicant_get_eap_mode(wpa_s);
3142 os_snprintf(eap_mode_buf, WPAS_DBUS_AUTH_MODE_MAX,
3143 "EAP-%s", eap_mode);
3144 auth_mode = eap_mode_buf;
3145
3146 } else {
3147 auth_mode = wpa_key_mgmt_txt(wpa_s->key_mgmt,
3148 wpa_s->current_ssid->proto);
3149 }
3150
3151 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3152 &auth_mode, error);
3153 }
3154
3155
3156 /**
3157 * wpas_dbus_getter_bridge_ifname - Get interface name
3158 * @iter: Pointer to incoming dbus message iter
3159 * @error: Location to store error on failure
3160 * @user_data: Function specific data
3161 * Returns: TRUE on success, FALSE on failure
3162 *
3163 * Getter for "BridgeIfname" property.
3164 */
3165 dbus_bool_t wpas_dbus_getter_bridge_ifname(DBusMessageIter *iter,
3166 DBusError *error,
3167 void *user_data)
3168 {
3169 struct wpa_supplicant *wpa_s = user_data;
3170 const char *bridge_ifname = wpa_s->bridge_ifname;
3171
3172 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3173 &bridge_ifname, error);
3174 }
3175
3176
3177 /**
3178 * wpas_dbus_getter_bsss - Get array of BSSs objects
3179 * @iter: Pointer to incoming dbus message iter
3180 * @error: Location to store error on failure
3181 * @user_data: Function specific data
3182 * Returns: TRUE on success, FALSE on failure
3183 *
3184 * Getter for "BSSs" property.
3185 */
3186 dbus_bool_t wpas_dbus_getter_bsss(DBusMessageIter *iter, DBusError *error,
3187 void *user_data)
3188 {
3189 struct wpa_supplicant *wpa_s = user_data;
3190 struct wpa_bss *bss;
3191 char **paths;
3192 unsigned int i = 0;
3193 dbus_bool_t success = FALSE;
3194
3195 if (!wpa_s->dbus_new_path) {
3196 dbus_set_error(error, DBUS_ERROR_FAILED,
3197 "%s: no D-Bus interface", __func__);
3198 return FALSE;
3199 }
3200
3201 paths = os_calloc(wpa_s->num_bss, sizeof(char *));
3202 if (!paths) {
3203 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3204 return FALSE;
3205 }
3206
3207 /* Loop through scan results and append each result's object path */
3208 dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
3209 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
3210 if (paths[i] == NULL) {
3211 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
3212 "no memory");
3213 goto out;
3214 }
3215 /* Construct the object path for this BSS. */
3216 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
3217 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
3218 wpa_s->dbus_new_path, bss->id);
3219 }
3220
3221 success = wpas_dbus_simple_array_property_getter(iter,
3222 DBUS_TYPE_OBJECT_PATH,
3223 paths, wpa_s->num_bss,
3224 error);
3225
3226 out:
3227 while (i)
3228 os_free(paths[--i]);
3229 os_free(paths);
3230 return success;
3231 }
3232
3233
3234 /**
3235 * wpas_dbus_getter_networks - Get array of networks objects
3236 * @iter: Pointer to incoming dbus message iter
3237 * @error: Location to store error on failure
3238 * @user_data: Function specific data
3239 * Returns: TRUE on success, FALSE on failure
3240 *
3241 * Getter for "Networks" property.
3242 */
3243 dbus_bool_t wpas_dbus_getter_networks(DBusMessageIter *iter, DBusError *error,
3244 void *user_data)
3245 {
3246 struct wpa_supplicant *wpa_s = user_data;
3247 struct wpa_ssid *ssid;
3248 char **paths;
3249 unsigned int i = 0, num = 0;
3250 dbus_bool_t success = FALSE;
3251
3252 if (!wpa_s->dbus_new_path) {
3253 dbus_set_error(error, DBUS_ERROR_FAILED,
3254 "%s: no D-Bus interface", __func__);
3255 return FALSE;
3256 }
3257
3258 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
3259 if (!network_is_persistent_group(ssid))
3260 num++;
3261
3262 paths = os_calloc(num, sizeof(char *));
3263 if (!paths) {
3264 dbus_set_error(error, DBUS_ERROR_NO_MEMORY, "no memory");
3265 return FALSE;
3266 }
3267
3268 /* Loop through configured networks and append object path of each */
3269 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
3270 if (network_is_persistent_group(ssid))
3271 continue;
3272 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
3273 if (paths[i] == NULL) {
3274 dbus_set_error(error, DBUS_ERROR_NO_MEMORY,
3275 "no memory");
3276 goto out;
3277 }
3278
3279 /* Construct the object path for this network. */
3280 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
3281 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
3282 wpa_s->dbus_new_path, ssid->id);
3283 }
3284
3285 success = wpas_dbus_simple_array_property_getter(iter,
3286 DBUS_TYPE_OBJECT_PATH,
3287 paths, num, error);
3288
3289 out:
3290 while (i)
3291 os_free(paths[--i]);
3292 os_free(paths);
3293 return success;
3294 }
3295
3296
3297 /**
3298 * wpas_dbus_getter_pkcs11_engine_path - Get PKCS #11 engine path
3299 * @iter: Pointer to incoming dbus message iter
3300 * @error: Location to store error on failure
3301 * @user_data: Function specific data
3302 * Returns: A dbus message containing the PKCS #11 engine path
3303 *
3304 * Getter for "PKCS11EnginePath" property.
3305 */
3306 dbus_bool_t wpas_dbus_getter_pkcs11_engine_path(DBusMessageIter *iter,
3307 DBusError *error,
3308 void *user_data)
3309 {
3310 struct wpa_supplicant *wpa_s = user_data;
3311 const char *pkcs11_engine_path;
3312
3313 if (wpa_s->conf->pkcs11_engine_path == NULL)
3314 pkcs11_engine_path = "";
3315 else
3316 pkcs11_engine_path = wpa_s->conf->pkcs11_engine_path;
3317 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3318 &pkcs11_engine_path, error);
3319 }
3320
3321
3322 /**
3323 * wpas_dbus_getter_pkcs11_module_path - Get PKCS #11 module path
3324 * @iter: Pointer to incoming dbus message iter
3325 * @error: Location to store error on failure
3326 * @user_data: Function specific data
3327 * Returns: A dbus message containing the PKCS #11 module path
3328 *
3329 * Getter for "PKCS11ModulePath" property.
3330 */
3331 dbus_bool_t wpas_dbus_getter_pkcs11_module_path(DBusMessageIter *iter,
3332 DBusError *error,
3333 void *user_data)
3334 {
3335 struct wpa_supplicant *wpa_s = user_data;
3336 const char *pkcs11_module_path;
3337
3338 if (wpa_s->conf->pkcs11_module_path == NULL)
3339 pkcs11_module_path = "";
3340 else
3341 pkcs11_module_path = wpa_s->conf->pkcs11_module_path;
3342 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3343 &pkcs11_module_path, error);
3344 }
3345
3346
3347 /**
3348 * wpas_dbus_getter_blobs - Get all blobs defined for this interface
3349 * @iter: Pointer to incoming dbus message iter
3350 * @error: Location to store error on failure
3351 * @user_data: Function specific data
3352 * Returns: TRUE on success, FALSE on failure
3353 *
3354 * Getter for "Blobs" property.
3355 */
3356 dbus_bool_t wpas_dbus_getter_blobs(DBusMessageIter *iter, DBusError *error,
3357 void *user_data)
3358 {
3359 struct wpa_supplicant *wpa_s = user_data;
3360 DBusMessageIter variant_iter, dict_iter, entry_iter, array_iter;
3361 struct wpa_config_blob *blob;
3362
3363 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
3364 "a{say}", &variant_iter) ||
3365 !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
3366 "{say}", &dict_iter)) {
3367 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3368 return FALSE;
3369 }
3370
3371 blob = wpa_s->conf->blobs;
3372 while (blob) {
3373 if (!dbus_message_iter_open_container(&dict_iter,
3374 DBUS_TYPE_DICT_ENTRY,
3375 NULL, &entry_iter) ||
3376 !dbus_message_iter_append_basic(&entry_iter,
3377 DBUS_TYPE_STRING,
3378 &(blob->name)) ||
3379 !dbus_message_iter_open_container(&entry_iter,
3380 DBUS_TYPE_ARRAY,
3381 DBUS_TYPE_BYTE_AS_STRING,
3382 &array_iter) ||
3383 !dbus_message_iter_append_fixed_array(&array_iter,
3384 DBUS_TYPE_BYTE,
3385 &(blob->data),
3386 blob->len) ||
3387 !dbus_message_iter_close_container(&entry_iter,
3388 &array_iter) ||
3389 !dbus_message_iter_close_container(&dict_iter,
3390 &entry_iter)) {
3391 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
3392 "no memory");
3393 return FALSE;
3394 }
3395
3396 blob = blob->next;
3397 }
3398
3399 if (!dbus_message_iter_close_container(&variant_iter, &dict_iter) ||
3400 !dbus_message_iter_close_container(iter, &variant_iter)) {
3401 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3402 return FALSE;
3403 }
3404
3405 return TRUE;
3406 }
3407
3408
3409 static struct wpa_bss * get_bss_helper(struct bss_handler_args *args,
3410 DBusError *error, const char *func_name)
3411 {
3412 struct wpa_bss *res = wpa_bss_get_id(args->wpa_s, args->id);
3413
3414 if (!res) {
3415 wpa_printf(MSG_ERROR, "%s[dbus]: no bss with id %d found",
3416 func_name, args->id);
3417 dbus_set_error(error, DBUS_ERROR_FAILED,
3418 "%s: BSS %d not found",
3419 func_name, args->id);
3420 }
3421
3422 return res;
3423 }
3424
3425
3426 /**
3427 * wpas_dbus_getter_bss_bssid - Return the BSSID of a BSS
3428 * @iter: Pointer to incoming dbus message iter
3429 * @error: Location to store error on failure
3430 * @user_data: Function specific data
3431 * Returns: TRUE on success, FALSE on failure
3432 *
3433 * Getter for "BSSID" property.
3434 */
3435 dbus_bool_t wpas_dbus_getter_bss_bssid(DBusMessageIter *iter, DBusError *error,
3436 void *user_data)
3437 {
3438 struct bss_handler_args *args = user_data;
3439 struct wpa_bss *res;
3440
3441 res = get_bss_helper(args, error, __func__);
3442 if (!res)
3443 return FALSE;
3444
3445 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
3446 res->bssid, ETH_ALEN,
3447 error);
3448 }
3449
3450
3451 /**
3452 * wpas_dbus_getter_bss_ssid - Return the SSID of a BSS
3453 * @iter: Pointer to incoming dbus message iter
3454 * @error: Location to store error on failure
3455 * @user_data: Function specific data
3456 * Returns: TRUE on success, FALSE on failure
3457 *
3458 * Getter for "SSID" property.
3459 */
3460 dbus_bool_t wpas_dbus_getter_bss_ssid(DBusMessageIter *iter, DBusError *error,
3461 void *user_data)
3462 {
3463 struct bss_handler_args *args = user_data;
3464 struct wpa_bss *res;
3465
3466 res = get_bss_helper(args, error, __func__);
3467 if (!res)
3468 return FALSE;
3469
3470 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
3471 res->ssid, res->ssid_len,
3472 error);
3473 }
3474
3475
3476 /**
3477 * wpas_dbus_getter_bss_privacy - Return the privacy flag of a BSS
3478 * @iter: Pointer to incoming dbus message iter
3479 * @error: Location to store error on failure
3480 * @user_data: Function specific data
3481 * Returns: TRUE on success, FALSE on failure
3482 *
3483 * Getter for "Privacy" property.
3484 */
3485 dbus_bool_t wpas_dbus_getter_bss_privacy(DBusMessageIter *iter,
3486 DBusError *error, void *user_data)
3487 {
3488 struct bss_handler_args *args = user_data;
3489 struct wpa_bss *res;
3490 dbus_bool_t privacy;
3491
3492 res = get_bss_helper(args, error, __func__);
3493 if (!res)
3494 return FALSE;
3495
3496 privacy = (res->caps & IEEE80211_CAP_PRIVACY) ? TRUE : FALSE;
3497 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
3498 &privacy, error);
3499 }
3500
3501
3502 /**
3503 * wpas_dbus_getter_bss_mode - Return the mode of a BSS
3504 * @iter: Pointer to incoming dbus message iter
3505 * @error: Location to store error on failure
3506 * @user_data: Function specific data
3507 * Returns: TRUE on success, FALSE on failure
3508 *
3509 * Getter for "Mode" property.
3510 */
3511 dbus_bool_t wpas_dbus_getter_bss_mode(DBusMessageIter *iter, DBusError *error,
3512 void *user_data)
3513 {
3514 struct bss_handler_args *args = user_data;
3515 struct wpa_bss *res;
3516 const char *mode;
3517
3518 res = get_bss_helper(args, error, __func__);
3519 if (!res)
3520 return FALSE;
3521 if (bss_is_dmg(res)) {
3522 switch (res->caps & IEEE80211_CAP_DMG_MASK) {
3523 case IEEE80211_CAP_DMG_PBSS:
3524 case IEEE80211_CAP_DMG_IBSS:
3525 mode = "ad-hoc";
3526 break;
3527 case IEEE80211_CAP_DMG_AP:
3528 mode = "infrastructure";
3529 break;
3530 }
3531 } else {
3532 if (res->caps & IEEE80211_CAP_IBSS)
3533 mode = "ad-hoc";
3534 else
3535 mode = "infrastructure";
3536 }
3537
3538 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3539 &mode, error);
3540 }
3541
3542
3543 /**
3544 * wpas_dbus_getter_bss_level - Return the signal strength of a BSS
3545 * @iter: Pointer to incoming dbus message iter
3546 * @error: Location to store error on failure
3547 * @user_data: Function specific data
3548 * Returns: TRUE on success, FALSE on failure
3549 *
3550 * Getter for "Level" property.
3551 */
3552 dbus_bool_t wpas_dbus_getter_bss_signal(DBusMessageIter *iter,
3553 DBusError *error, void *user_data)
3554 {
3555 struct bss_handler_args *args = user_data;
3556 struct wpa_bss *res;
3557 s16 level;
3558
3559 res = get_bss_helper(args, error, __func__);
3560 if (!res)
3561 return FALSE;
3562
3563 level = (s16) res->level;
3564 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT16,
3565 &level, error);
3566 }
3567
3568
3569 /**
3570 * wpas_dbus_getter_bss_frequency - Return the frequency of a BSS
3571 * @iter: Pointer to incoming dbus message iter
3572 * @error: Location to store error on failure
3573 * @user_data: Function specific data
3574 * Returns: TRUE on success, FALSE on failure
3575 *
3576 * Getter for "Frequency" property.
3577 */
3578 dbus_bool_t wpas_dbus_getter_bss_frequency(DBusMessageIter *iter,
3579 DBusError *error, void *user_data)
3580 {
3581 struct bss_handler_args *args = user_data;
3582 struct wpa_bss *res;
3583 u16 freq;
3584
3585 res = get_bss_helper(args, error, __func__);
3586 if (!res)
3587 return FALSE;
3588
3589 freq = (u16) res->freq;
3590 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
3591 &freq, error);
3592 }
3593
3594
3595 static int cmp_u8s_desc(const void *a, const void *b)
3596 {
3597 return (*(u8 *) b - *(u8 *) a);
3598 }
3599
3600
3601 /**
3602 * wpas_dbus_getter_bss_rates - Return available bit rates of a BSS
3603 * @iter: Pointer to incoming dbus message iter
3604 * @error: Location to store error on failure
3605 * @user_data: Function specific data
3606 * Returns: TRUE on success, FALSE on failure
3607 *
3608 * Getter for "Rates" property.
3609 */
3610 dbus_bool_t wpas_dbus_getter_bss_rates(DBusMessageIter *iter,
3611 DBusError *error, void *user_data)
3612 {
3613 struct bss_handler_args *args = user_data;
3614 struct wpa_bss *res;
3615 u8 *ie_rates = NULL;
3616 u32 *real_rates;
3617 int rates_num, i;
3618 dbus_bool_t success = FALSE;
3619
3620 res = get_bss_helper(args, error, __func__);
3621 if (!res)
3622 return FALSE;
3623
3624 rates_num = wpa_bss_get_bit_rates(res, &ie_rates);
3625 if (rates_num < 0)
3626 return FALSE;
3627
3628 qsort(ie_rates, rates_num, 1, cmp_u8s_desc);
3629
3630 real_rates = os_malloc(sizeof(u32) * rates_num);
3631 if (!real_rates) {
3632 os_free(ie_rates);
3633 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3634 return FALSE;
3635 }
3636
3637 for (i = 0; i < rates_num; i++)
3638 real_rates[i] = ie_rates[i] * 500000;
3639
3640 success = wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_UINT32,
3641 real_rates, rates_num,
3642 error);
3643
3644 os_free(ie_rates);
3645 os_free(real_rates);
3646 return success;
3647 }
3648
3649
3650 static dbus_bool_t wpas_dbus_get_bss_security_prop(DBusMessageIter *iter,
3651 struct wpa_ie_data *ie_data,
3652 DBusError *error)
3653 {
3654 DBusMessageIter iter_dict, variant_iter;
3655 const char *group;
3656 const char *pairwise[5]; /* max 5 pairwise ciphers is supported */
3657 const char *key_mgmt[9]; /* max 9 key managements may be supported */
3658 int n;
3659
3660 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
3661 "a{sv}", &variant_iter))
3662 goto nomem;
3663
3664 if (!wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
3665 goto nomem;
3666
3667 /* KeyMgmt */
3668 n = 0;
3669 if (ie_data->key_mgmt & WPA_KEY_MGMT_PSK)
3670 key_mgmt[n++] = "wpa-psk";
3671 if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_PSK)
3672 key_mgmt[n++] = "wpa-ft-psk";
3673 if (ie_data->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
3674 key_mgmt[n++] = "wpa-psk-sha256";
3675 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X)
3676 key_mgmt[n++] = "wpa-eap";
3677 if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X)
3678 key_mgmt[n++] = "wpa-ft-eap";
3679 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256)
3680 key_mgmt[n++] = "wpa-eap-sha256";
3681 #ifdef CONFIG_SUITEB
3682 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B)
3683 key_mgmt[n++] = "wpa-eap-suite-b";
3684 #endif /* CONFIG_SUITEB */
3685 #ifdef CONFIG_SUITEB192
3686 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
3687 key_mgmt[n++] = "wpa-eap-suite-b-192";
3688 #endif /* CONFIG_SUITEB192 */
3689 if (ie_data->key_mgmt & WPA_KEY_MGMT_NONE)
3690 key_mgmt[n++] = "wpa-none";
3691
3692 if (!wpa_dbus_dict_append_string_array(&iter_dict, "KeyMgmt",
3693 key_mgmt, n))
3694 goto nomem;
3695
3696 /* Group */
3697 switch (ie_data->group_cipher) {
3698 case WPA_CIPHER_WEP40:
3699 group = "wep40";
3700 break;
3701 case WPA_CIPHER_TKIP:
3702 group = "tkip";
3703 break;
3704 case WPA_CIPHER_CCMP:
3705 group = "ccmp";
3706 break;
3707 case WPA_CIPHER_GCMP:
3708 group = "gcmp";
3709 break;
3710 case WPA_CIPHER_WEP104:
3711 group = "wep104";
3712 break;
3713 case WPA_CIPHER_CCMP_256:
3714 group = "ccmp-256";
3715 break;
3716 case WPA_CIPHER_GCMP_256:
3717 group = "gcmp-256";
3718 break;
3719 default:
3720 group = "";
3721 break;
3722 }
3723
3724 if (!wpa_dbus_dict_append_string(&iter_dict, "Group", group))
3725 goto nomem;
3726
3727 /* Pairwise */
3728 n = 0;
3729 if (ie_data->pairwise_cipher & WPA_CIPHER_TKIP)
3730 pairwise[n++] = "tkip";
3731 if (ie_data->pairwise_cipher & WPA_CIPHER_CCMP)
3732 pairwise[n++] = "ccmp";
3733 if (ie_data->pairwise_cipher & WPA_CIPHER_GCMP)
3734 pairwise[n++] = "gcmp";
3735 if (ie_data->pairwise_cipher & WPA_CIPHER_CCMP_256)
3736 pairwise[n++] = "ccmp-256";
3737 if (ie_data->pairwise_cipher & WPA_CIPHER_GCMP_256)
3738 pairwise[n++] = "gcmp-256";
3739
3740 if (!wpa_dbus_dict_append_string_array(&iter_dict, "Pairwise",
3741 pairwise, n))
3742 goto nomem;
3743
3744 /* Management group (RSN only) */
3745 if (ie_data->proto == WPA_PROTO_RSN) {
3746 switch (ie_data->mgmt_group_cipher) {
3747 #ifdef CONFIG_IEEE80211W
3748 case WPA_CIPHER_AES_128_CMAC:
3749 group = "aes128cmac";
3750 break;
3751 #endif /* CONFIG_IEEE80211W */
3752 default:
3753 group = "";
3754 break;
3755 }
3756
3757 if (!wpa_dbus_dict_append_string(&iter_dict, "MgmtGroup",
3758 group))
3759 goto nomem;
3760 }
3761
3762 if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict) ||
3763 !dbus_message_iter_close_container(iter, &variant_iter))
3764 goto nomem;
3765
3766 return TRUE;
3767
3768 nomem:
3769 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3770 return FALSE;
3771 }
3772
3773
3774 /**
3775 * wpas_dbus_getter_bss_wpa - Return the WPA options of a BSS
3776 * @iter: Pointer to incoming dbus message iter
3777 * @error: Location to store error on failure
3778 * @user_data: Function specific data
3779 * Returns: TRUE on success, FALSE on failure
3780 *
3781 * Getter for "WPA" property.
3782 */
3783 dbus_bool_t wpas_dbus_getter_bss_wpa(DBusMessageIter *iter, DBusError *error,
3784 void *user_data)
3785 {
3786 struct bss_handler_args *args = user_data;
3787 struct wpa_bss *res;
3788 struct wpa_ie_data wpa_data;
3789 const u8 *ie;
3790
3791 res = get_bss_helper(args, error, __func__);
3792 if (!res)
3793 return FALSE;
3794
3795 os_memset(&wpa_data, 0, sizeof(wpa_data));
3796 ie = wpa_bss_get_vendor_ie(res, WPA_IE_VENDOR_TYPE);
3797 if (ie && wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0) {
3798 dbus_set_error_const(error, DBUS_ERROR_FAILED,
3799 "failed to parse WPA IE");
3800 return FALSE;
3801 }
3802
3803 return wpas_dbus_get_bss_security_prop(iter, &wpa_data, error);
3804 }
3805
3806
3807 /**
3808 * wpas_dbus_getter_bss_rsn - Return the RSN options of a BSS
3809 * @iter: Pointer to incoming dbus message iter
3810 * @error: Location to store error on failure
3811 * @user_data: Function specific data
3812 * Returns: TRUE on success, FALSE on failure
3813 *
3814 * Getter for "RSN" property.
3815 */
3816 dbus_bool_t wpas_dbus_getter_bss_rsn(DBusMessageIter *iter, DBusError *error,
3817 void *user_data)
3818 {
3819 struct bss_handler_args *args = user_data;
3820 struct wpa_bss *res;
3821 struct wpa_ie_data wpa_data;
3822 const u8 *ie;
3823
3824 res = get_bss_helper(args, error, __func__);
3825 if (!res)
3826 return FALSE;
3827
3828 os_memset(&wpa_data, 0, sizeof(wpa_data));
3829 ie = wpa_bss_get_ie(res, WLAN_EID_RSN);
3830 if (ie && wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0) {
3831 dbus_set_error_const(error, DBUS_ERROR_FAILED,
3832 "failed to parse RSN IE");
3833 return FALSE;
3834 }
3835
3836 return wpas_dbus_get_bss_security_prop(iter, &wpa_data, error);
3837 }
3838
3839
3840 /**
3841 * wpas_dbus_getter_bss_wps - Return the WPS options of a BSS
3842 * @iter: Pointer to incoming dbus message iter
3843 * @error: Location to store error on failure
3844 * @user_data: Function specific data
3845 * Returns: TRUE on success, FALSE on failure
3846 *
3847 * Getter for "WPS" property.
3848 */
3849 dbus_bool_t wpas_dbus_getter_bss_wps(DBusMessageIter *iter, DBusError *error,
3850 void *user_data)
3851 {
3852 struct bss_handler_args *args = user_data;
3853 struct wpa_bss *res;
3854 #ifdef CONFIG_WPS
3855 struct wpabuf *wps_ie;
3856 #endif /* CONFIG_WPS */
3857 DBusMessageIter iter_dict, variant_iter;
3858 int wps_support = 0;
3859 const char *type = "";
3860
3861 res = get_bss_helper(args, error, __func__);
3862 if (!res)
3863 return FALSE;
3864
3865 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
3866 "a{sv}", &variant_iter) ||
3867 !wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
3868 goto nomem;
3869
3870 #ifdef CONFIG_WPS
3871 wps_ie = wpa_bss_get_vendor_ie_multi(res, WPS_IE_VENDOR_TYPE);
3872 if (wps_ie) {
3873 wps_support = 1;
3874 if (wps_is_selected_pbc_registrar(wps_ie))
3875 type = "pbc";
3876 else if (wps_is_selected_pin_registrar(wps_ie))
3877 type = "pin";
3878
3879 wpabuf_free(wps_ie);
3880 }
3881 #endif /* CONFIG_WPS */
3882
3883 if ((wps_support && !wpa_dbus_dict_append_string(&iter_dict, "Type", type)) ||
3884 !wpa_dbus_dict_close_write(&variant_iter, &iter_dict) ||
3885 !dbus_message_iter_close_container(iter, &variant_iter))
3886 goto nomem;
3887
3888 return TRUE;
3889
3890 nomem:
3891 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3892 return FALSE;
3893 }
3894
3895
3896 /**
3897 * wpas_dbus_getter_bss_ies - Return all IEs of a BSS
3898 * @iter: Pointer to incoming dbus message iter
3899 * @error: Location to store error on failure
3900 * @user_data: Function specific data
3901 * Returns: TRUE on success, FALSE on failure
3902 *
3903 * Getter for "IEs" property.
3904 */
3905 dbus_bool_t wpas_dbus_getter_bss_ies(DBusMessageIter *iter, DBusError *error,
3906 void *user_data)
3907 {
3908 struct bss_handler_args *args = user_data;
3909 struct wpa_bss *res;
3910
3911 res = get_bss_helper(args, error, __func__);
3912 if (!res)
3913 return FALSE;
3914
3915 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
3916 res + 1, res->ie_len,
3917 error);
3918 }
3919
3920
3921 /**
3922 * wpas_dbus_getter_bss_age - Return time in seconds since BSS was last seen
3923 * @iter: Pointer to incoming dbus message iter
3924 * @error: Location to store error on failure
3925 * @user_data: Function specific data
3926 * Returns: TRUE on success, FALSE on failure
3927 *
3928 * Getter for BSS age
3929 */
3930 dbus_bool_t wpas_dbus_getter_bss_age(DBusMessageIter *iter, DBusError *error,
3931 void *user_data)
3932 {
3933 struct bss_handler_args *args = user_data;
3934 struct wpa_bss *res;
3935 struct os_reltime now, diff = { 0, 0 };
3936 u32 age;
3937
3938 res = get_bss_helper(args, error, __func__);
3939 if (!res)
3940 return FALSE;
3941
3942 os_get_reltime(&now);
3943 os_reltime_sub(&now, &res->last_update, &diff);
3944 age = diff.sec > 0 ? diff.sec : 0;
3945 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32, &age,
3946 error);
3947 }
3948
3949
3950 /**
3951 * wpas_dbus_getter_enabled - Check whether network is enabled or disabled
3952 * @iter: Pointer to incoming dbus message iter
3953 * @error: Location to store error on failure
3954 * @user_data: Function specific data
3955 * Returns: TRUE on success, FALSE on failure
3956 *
3957 * Getter for "enabled" property of a configured network.
3958 */
3959 dbus_bool_t wpas_dbus_getter_enabled(DBusMessageIter *iter, DBusError *error,
3960 void *user_data)
3961 {
3962 struct network_handler_args *net = user_data;
3963 dbus_bool_t enabled = net->ssid->disabled ? FALSE : TRUE;
3964
3965 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
3966 &enabled, error);
3967 }
3968
3969
3970 /**
3971 * wpas_dbus_setter_enabled - Mark a configured network as enabled or disabled
3972 * @iter: Pointer to incoming dbus message iter
3973 * @error: Location to store error on failure
3974 * @user_data: Function specific data
3975 * Returns: TRUE on success, FALSE on failure
3976 *
3977 * Setter for "Enabled" property of a configured network.
3978 */
3979 dbus_bool_t wpas_dbus_setter_enabled(DBusMessageIter *iter, DBusError *error,
3980 void *user_data)
3981 {
3982 struct network_handler_args *net = user_data;
3983 struct wpa_supplicant *wpa_s;
3984 struct wpa_ssid *ssid;
3985 dbus_bool_t enable;
3986
3987 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
3988 &enable))
3989 return FALSE;
3990
3991 wpa_s = net->wpa_s;
3992 ssid = net->ssid;
3993
3994 if (enable)
3995 wpa_supplicant_enable_network(wpa_s, ssid);
3996 else
3997 wpa_supplicant_disable_network(wpa_s, ssid);
3998
3999 return TRUE;
4000 }
4001
4002
4003 /**
4004 * wpas_dbus_getter_network_properties - Get options for a configured network
4005 * @iter: Pointer to incoming dbus message iter
4006 * @error: Location to store error on failure
4007 * @user_data: Function specific data
4008 * Returns: TRUE on success, FALSE on failure
4009 *
4010 * Getter for "Properties" property of a configured network.
4011 */
4012 dbus_bool_t wpas_dbus_getter_network_properties(DBusMessageIter *iter,
4013 DBusError *error,
4014 void *user_data)
4015 {
4016 struct network_handler_args *net = user_data;
4017 DBusMessageIter variant_iter, dict_iter;
4018 char **iterator;
4019 char **props = wpa_config_get_all(net->ssid, 1);
4020 dbus_bool_t success = FALSE;
4021
4022 if (!props) {
4023 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
4024 return FALSE;
4025 }
4026
4027 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a{sv}",
4028 &variant_iter) ||
4029 !wpa_dbus_dict_open_write(&variant_iter, &dict_iter)) {
4030 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
4031 goto out;
4032 }
4033
4034 iterator = props;
4035 while (*iterator) {
4036 if (!wpa_dbus_dict_append_string(&dict_iter, *iterator,
4037 *(iterator + 1))) {
4038 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
4039 "no memory");
4040 goto out;
4041 }
4042 iterator += 2;
4043 }
4044
4045
4046 if (!wpa_dbus_dict_close_write(&variant_iter, &dict_iter) ||
4047 !dbus_message_iter_close_container(iter, &variant_iter)) {
4048 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
4049 goto out;
4050 }
4051
4052 success = TRUE;
4053
4054 out:
4055 iterator = props;
4056 while (*iterator) {
4057 os_free(*iterator);
4058 iterator++;
4059 }
4060 os_free(props);
4061 return success;
4062 }
4063
4064
4065 /**
4066 * wpas_dbus_setter_network_properties - Set options for a configured network
4067 * @iter: Pointer to incoming dbus message iter
4068 * @error: Location to store error on failure
4069 * @user_data: Function specific data
4070 * Returns: TRUE on success, FALSE on failure
4071 *
4072 * Setter for "Properties" property of a configured network.
4073 */
4074 dbus_bool_t wpas_dbus_setter_network_properties(DBusMessageIter *iter,
4075 DBusError *error,
4076 void *user_data)
4077 {
4078 struct network_handler_args *net = user_data;
4079 struct wpa_ssid *ssid = net->ssid;
4080 DBusMessageIter variant_iter;
4081
4082 dbus_message_iter_recurse(iter, &variant_iter);
4083 return set_network_properties(net->wpa_s, ssid, &variant_iter, error);
4084 }
4085
4086
4087 #ifdef CONFIG_AP
4088
4089 DBusMessage * wpas_dbus_handler_subscribe_preq(
4090 DBusMessage *message, struct wpa_supplicant *wpa_s)
4091 {
4092 struct wpas_dbus_priv *priv = wpa_s->global->dbus;
4093 char *name;
4094
4095 if (wpa_s->preq_notify_peer != NULL) {
4096 if (os_strcmp(dbus_message_get_sender(message),
4097 wpa_s->preq_notify_peer) == 0)
4098 return NULL;
4099
4100 return dbus_message_new_error(message,
4101 WPAS_DBUS_ERROR_SUBSCRIPTION_IN_USE,
4102 "Another application is already subscribed");
4103 }
4104
4105 name = os_strdup(dbus_message_get_sender(message));
4106 if (!name)
4107 return wpas_dbus_error_no_memory(message);
4108
4109 wpa_s->preq_notify_peer = name;
4110
4111 /* Subscribe to clean up if application closes socket */
4112 wpas_dbus_subscribe_noc(priv);
4113
4114 /*
4115 * Double-check it's still alive to make sure that we didn't
4116 * miss the NameOwnerChanged signal, e.g. while strdup'ing.
4117 */
4118 if (!dbus_bus_name_has_owner(priv->con, name, NULL)) {
4119 /*
4120 * Application no longer exists, clean up.
4121 * The return value is irrelevant now.
4122 *
4123 * Need to check if the NameOwnerChanged handling
4124 * already cleaned up because we have processed
4125 * DBus messages while checking if the name still
4126 * has an owner.
4127 */
4128 if (!wpa_s->preq_notify_peer)
4129 return NULL;
4130 os_free(wpa_s->preq_notify_peer);
4131 wpa_s->preq_notify_peer = NULL;
4132 wpas_dbus_unsubscribe_noc(priv);
4133 }
4134
4135 return NULL;
4136 }
4137
4138
4139 DBusMessage * wpas_dbus_handler_unsubscribe_preq(
4140 DBusMessage *message, struct wpa_supplicant *wpa_s)
4141 {
4142 struct wpas_dbus_priv *priv = wpa_s->global->dbus;
4143
4144 if (!wpa_s->preq_notify_peer)
4145 return dbus_message_new_error(message,
4146 WPAS_DBUS_ERROR_NO_SUBSCRIPTION,
4147 "Not subscribed");
4148
4149 if (os_strcmp(wpa_s->preq_notify_peer,
4150 dbus_message_get_sender(message)))
4151 return dbus_message_new_error(message,
4152 WPAS_DBUS_ERROR_SUBSCRIPTION_EPERM,
4153 "Can't unsubscribe others");
4154
4155 os_free(wpa_s->preq_notify_peer);
4156 wpa_s->preq_notify_peer = NULL;
4157 wpas_dbus_unsubscribe_noc(priv);
4158 return NULL;
4159 }
4160
4161
4162 void wpas_dbus_signal_preq(struct wpa_supplicant *wpa_s,
4163 const u8 *addr, const u8 *dst, const u8 *bssid,
4164 const u8 *ie, size_t ie_len, u32 ssi_signal)
4165 {
4166 DBusMessage *msg;
4167 DBusMessageIter iter, dict_iter;
4168 struct wpas_dbus_priv *priv = wpa_s->global->dbus;
4169
4170 /* Do nothing if the control interface is not turned on */
4171 if (priv == NULL || !wpa_s->dbus_new_path)
4172 return;
4173
4174 if (wpa_s->preq_notify_peer == NULL)
4175 return;
4176
4177 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
4178 WPAS_DBUS_NEW_IFACE_INTERFACE,
4179 "ProbeRequest");
4180 if (msg == NULL)
4181 return;
4182
4183 dbus_message_set_destination(msg, wpa_s->preq_notify_peer);
4184
4185 dbus_message_iter_init_append(msg, &iter);
4186
4187 if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
4188 (addr && !wpa_dbus_dict_append_byte_array(&dict_iter, "addr",
4189 (const char *) addr,
4190 ETH_ALEN)) ||
4191 (dst && !wpa_dbus_dict_append_byte_array(&dict_iter, "dst",
4192 (const char *) dst,
4193 ETH_ALEN)) ||
4194 (bssid && !wpa_dbus_dict_append_byte_array(&dict_iter, "bssid",
4195 (const char *) bssid,
4196 ETH_ALEN)) ||
4197 (ie && ie_len && !wpa_dbus_dict_append_byte_array(&dict_iter, "ies",
4198 (const char *) ie,
4199 ie_len)) ||
4200 (ssi_signal && !wpa_dbus_dict_append_int32(&dict_iter, "signal",
4201 ssi_signal)) ||
4202 !wpa_dbus_dict_close_write(&iter, &dict_iter))
4203 goto fail;
4204
4205 dbus_connection_send(priv->con, msg, NULL);
4206 goto out;
4207 fail:
4208 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
4209 out:
4210 dbus_message_unref(msg);
4211 }
4212
4213 #endif /* CONFIG_AP */