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