]> git.ipfire.org Git - thirdparty/hostap.git/blob - wpa_supplicant/dbus/dbus_new_handlers.c
Maintain maximum blacklist count over list clear operations
[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 wpa_s->extra_blacklist_count = 0;
1459 wpa_s->normal_scans = 0;
1460 wpa_supplicant_reinit_autoscan(wpa_s);
1461 wpa_s->disconnected = 0;
1462 wpa_s->reassociate = 1;
1463 wpa_supplicant_req_scan(wpa_s, 0, 0);
1464
1465 return NULL;
1466 }
1467
1468 return dbus_message_new_error(message, WPAS_DBUS_ERROR_NOT_CONNECTED,
1469 "This interface is not connected");
1470 }
1471
1472
1473 /**
1474 * wpas_dbus_handler_remove_network - Remove a configured network
1475 * @message: Pointer to incoming dbus message
1476 * @wpa_s: wpa_supplicant structure for a network interface
1477 * Returns: NULL on success or dbus error on failure
1478 *
1479 * Handler function for "RemoveNetwork" method call of a network interface.
1480 */
1481 DBusMessage * wpas_dbus_handler_remove_network(DBusMessage *message,
1482 struct wpa_supplicant *wpa_s)
1483 {
1484 DBusMessage *reply = NULL;
1485 const char *op;
1486 char *iface = NULL, *net_id = NULL;
1487 int id;
1488 struct wpa_ssid *ssid;
1489
1490 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
1491 DBUS_TYPE_INVALID);
1492
1493 /* Extract the network ID and ensure the network */
1494 /* is actually a child of this interface */
1495 iface = wpas_dbus_new_decompose_object_path(op, 0, &net_id, NULL);
1496 if (iface == NULL || net_id == NULL ||
1497 os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
1498 reply = wpas_dbus_error_invalid_args(message, op);
1499 goto out;
1500 }
1501
1502 errno = 0;
1503 id = strtoul(net_id, NULL, 10);
1504 if (errno != 0) {
1505 reply = wpas_dbus_error_invalid_args(message, op);
1506 goto out;
1507 }
1508
1509 ssid = wpa_config_get_network(wpa_s->conf, id);
1510 if (ssid == NULL) {
1511 reply = wpas_dbus_error_network_unknown(message);
1512 goto out;
1513 }
1514
1515 wpas_notify_network_removed(wpa_s, ssid);
1516
1517 if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
1518 wpa_printf(MSG_ERROR,
1519 "wpas_dbus_handler_remove_network[dbus]: "
1520 "error occurred when removing network %d", id);
1521 reply = wpas_dbus_error_unknown_error(
1522 message, "error removing the specified network on "
1523 "this interface.");
1524 goto out;
1525 }
1526
1527 if (ssid == wpa_s->current_ssid)
1528 wpa_supplicant_deauthenticate(wpa_s,
1529 WLAN_REASON_DEAUTH_LEAVING);
1530
1531 out:
1532 os_free(iface);
1533 os_free(net_id);
1534 return reply;
1535 }
1536
1537
1538 static void remove_network(void *arg, struct wpa_ssid *ssid)
1539 {
1540 struct wpa_supplicant *wpa_s = arg;
1541
1542 wpas_notify_network_removed(wpa_s, ssid);
1543
1544 if (wpa_config_remove_network(wpa_s->conf, ssid->id) < 0) {
1545 wpa_printf(MSG_ERROR,
1546 "wpas_dbus_handler_remove_all_networks[dbus]: "
1547 "error occurred when removing network %d",
1548 ssid->id);
1549 return;
1550 }
1551
1552 if (ssid == wpa_s->current_ssid)
1553 wpa_supplicant_deauthenticate(wpa_s,
1554 WLAN_REASON_DEAUTH_LEAVING);
1555 }
1556
1557
1558 /**
1559 * wpas_dbus_handler_remove_all_networks - Remove all configured networks
1560 * @message: Pointer to incoming dbus message
1561 * @wpa_s: wpa_supplicant structure for a network interface
1562 * Returns: NULL on success or dbus error on failure
1563 *
1564 * Handler function for "RemoveAllNetworks" method call of a network interface.
1565 */
1566 DBusMessage * wpas_dbus_handler_remove_all_networks(
1567 DBusMessage *message, struct wpa_supplicant *wpa_s)
1568 {
1569 /* NB: could check for failure and return an error */
1570 wpa_config_foreach_network(wpa_s->conf, remove_network, wpa_s);
1571 return NULL;
1572 }
1573
1574
1575 /**
1576 * wpas_dbus_handler_select_network - Attempt association with a network
1577 * @message: Pointer to incoming dbus message
1578 * @wpa_s: wpa_supplicant structure for a network interface
1579 * Returns: NULL on success or dbus error on failure
1580 *
1581 * Handler function for "SelectNetwork" method call of network interface.
1582 */
1583 DBusMessage * wpas_dbus_handler_select_network(DBusMessage *message,
1584 struct wpa_supplicant *wpa_s)
1585 {
1586 DBusMessage *reply = NULL;
1587 const char *op;
1588 char *iface = NULL, *net_id = NULL;
1589 int id;
1590 struct wpa_ssid *ssid;
1591
1592 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
1593 DBUS_TYPE_INVALID);
1594
1595 /* Extract the network ID and ensure the network */
1596 /* is actually a child of this interface */
1597 iface = wpas_dbus_new_decompose_object_path(op, 0, &net_id, NULL);
1598 if (iface == NULL || net_id == NULL ||
1599 os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
1600 reply = wpas_dbus_error_invalid_args(message, op);
1601 goto out;
1602 }
1603
1604 errno = 0;
1605 id = strtoul(net_id, NULL, 10);
1606 if (errno != 0) {
1607 reply = wpas_dbus_error_invalid_args(message, op);
1608 goto out;
1609 }
1610
1611 ssid = wpa_config_get_network(wpa_s->conf, id);
1612 if (ssid == NULL) {
1613 reply = wpas_dbus_error_network_unknown(message);
1614 goto out;
1615 }
1616
1617 /* Finally, associate with the network */
1618 wpa_supplicant_select_network(wpa_s, ssid);
1619
1620 out:
1621 os_free(iface);
1622 os_free(net_id);
1623 return reply;
1624 }
1625
1626
1627 /**
1628 * wpas_dbus_handler_network_reply - Reply to a NetworkRequest signal
1629 * @message: Pointer to incoming dbus message
1630 * @wpa_s: wpa_supplicant structure for a network interface
1631 * Returns: NULL on success or dbus error on failure
1632 *
1633 * Handler function for "NetworkReply" method call of network interface.
1634 */
1635 DBusMessage * wpas_dbus_handler_network_reply(DBusMessage *message,
1636 struct wpa_supplicant *wpa_s)
1637 {
1638 #ifdef IEEE8021X_EAPOL
1639 DBusMessage *reply = NULL;
1640 const char *op, *field, *value;
1641 char *iface = NULL, *net_id = NULL;
1642 int id;
1643 struct wpa_ssid *ssid;
1644
1645 if (!dbus_message_get_args(message, NULL,
1646 DBUS_TYPE_OBJECT_PATH, &op,
1647 DBUS_TYPE_STRING, &field,
1648 DBUS_TYPE_STRING, &value,
1649 DBUS_TYPE_INVALID))
1650 return wpas_dbus_error_invalid_args(message, NULL);
1651
1652 /* Extract the network ID and ensure the network */
1653 /* is actually a child of this interface */
1654 iface = wpas_dbus_new_decompose_object_path(op, 0, &net_id, NULL);
1655 if (iface == NULL || net_id == NULL ||
1656 os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
1657 reply = wpas_dbus_error_invalid_args(message, op);
1658 goto out;
1659 }
1660
1661 errno = 0;
1662 id = strtoul(net_id, NULL, 10);
1663 if (errno != 0) {
1664 reply = wpas_dbus_error_invalid_args(message, net_id);
1665 goto out;
1666 }
1667
1668 ssid = wpa_config_get_network(wpa_s->conf, id);
1669 if (ssid == NULL) {
1670 reply = wpas_dbus_error_network_unknown(message);
1671 goto out;
1672 }
1673
1674 if (wpa_supplicant_ctrl_iface_ctrl_rsp_handle(wpa_s, ssid,
1675 field, value) < 0)
1676 reply = wpas_dbus_error_invalid_args(message, field);
1677 else {
1678 /* Tell EAP to retry immediately */
1679 eapol_sm_notify_ctrl_response(wpa_s->eapol);
1680 }
1681
1682 out:
1683 os_free(iface);
1684 os_free(net_id);
1685 return reply;
1686 #else /* IEEE8021X_EAPOL */
1687 wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included");
1688 return wpas_dbus_error_unknown_error(message, "802.1X not included");
1689 #endif /* IEEE8021X_EAPOL */
1690 }
1691
1692
1693 /**
1694 * wpas_dbus_handler_add_blob - Store named binary blob (ie, for certificates)
1695 * @message: Pointer to incoming dbus message
1696 * @wpa_s: %wpa_supplicant data structure
1697 * Returns: A dbus message containing an error on failure or NULL on success
1698 *
1699 * Asks wpa_supplicant to internally store a binary blobs.
1700 */
1701 DBusMessage * wpas_dbus_handler_add_blob(DBusMessage *message,
1702 struct wpa_supplicant *wpa_s)
1703 {
1704 DBusMessage *reply = NULL;
1705 DBusMessageIter iter, array_iter;
1706
1707 char *blob_name;
1708 u8 *blob_data;
1709 int blob_len;
1710 struct wpa_config_blob *blob = NULL;
1711
1712 dbus_message_iter_init(message, &iter);
1713 dbus_message_iter_get_basic(&iter, &blob_name);
1714
1715 if (wpa_config_get_blob(wpa_s->conf, blob_name)) {
1716 return dbus_message_new_error(message,
1717 WPAS_DBUS_ERROR_BLOB_EXISTS,
1718 NULL);
1719 }
1720
1721 dbus_message_iter_next(&iter);
1722 dbus_message_iter_recurse(&iter, &array_iter);
1723
1724 dbus_message_iter_get_fixed_array(&array_iter, &blob_data, &blob_len);
1725
1726 blob = os_zalloc(sizeof(*blob));
1727 if (!blob) {
1728 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1729 NULL);
1730 goto err;
1731 }
1732
1733 blob->data = os_malloc(blob_len);
1734 if (!blob->data) {
1735 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1736 NULL);
1737 goto err;
1738 }
1739 os_memcpy(blob->data, blob_data, blob_len);
1740
1741 blob->len = blob_len;
1742 blob->name = os_strdup(blob_name);
1743 if (!blob->name) {
1744 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1745 NULL);
1746 goto err;
1747 }
1748
1749 wpa_config_set_blob(wpa_s->conf, blob);
1750 wpas_notify_blob_added(wpa_s, blob->name);
1751
1752 return reply;
1753
1754 err:
1755 if (blob) {
1756 os_free(blob->name);
1757 os_free(blob->data);
1758 os_free(blob);
1759 }
1760 return reply;
1761 }
1762
1763
1764 /**
1765 * wpas_dbus_handler_get_blob - Get named binary blob (ie, for certificates)
1766 * @message: Pointer to incoming dbus message
1767 * @wpa_s: %wpa_supplicant data structure
1768 * Returns: A dbus message containing array of bytes (blob)
1769 *
1770 * Gets one wpa_supplicant's binary blobs.
1771 */
1772 DBusMessage * wpas_dbus_handler_get_blob(DBusMessage *message,
1773 struct wpa_supplicant *wpa_s)
1774 {
1775 DBusMessage *reply = NULL;
1776 DBusMessageIter iter, array_iter;
1777
1778 char *blob_name;
1779 const struct wpa_config_blob *blob;
1780
1781 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &blob_name,
1782 DBUS_TYPE_INVALID);
1783
1784 blob = wpa_config_get_blob(wpa_s->conf, blob_name);
1785 if (!blob) {
1786 return dbus_message_new_error(message,
1787 WPAS_DBUS_ERROR_BLOB_UNKNOWN,
1788 "Blob id not set");
1789 }
1790
1791 reply = dbus_message_new_method_return(message);
1792 if (!reply) {
1793 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1794 NULL);
1795 goto out;
1796 }
1797
1798 dbus_message_iter_init_append(reply, &iter);
1799
1800 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
1801 DBUS_TYPE_BYTE_AS_STRING,
1802 &array_iter)) {
1803 dbus_message_unref(reply);
1804 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1805 NULL);
1806 goto out;
1807 }
1808
1809 if (!dbus_message_iter_append_fixed_array(&array_iter, DBUS_TYPE_BYTE,
1810 &(blob->data), blob->len)) {
1811 dbus_message_unref(reply);
1812 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1813 NULL);
1814 goto out;
1815 }
1816
1817 if (!dbus_message_iter_close_container(&iter, &array_iter)) {
1818 dbus_message_unref(reply);
1819 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1820 NULL);
1821 goto out;
1822 }
1823
1824 out:
1825 return reply;
1826 }
1827
1828
1829 /**
1830 * wpas_remove_handler_remove_blob - Remove named binary blob
1831 * @message: Pointer to incoming dbus message
1832 * @wpa_s: %wpa_supplicant data structure
1833 * Returns: NULL on success or dbus error
1834 *
1835 * Asks wpa_supplicant to internally remove a binary blobs.
1836 */
1837 DBusMessage * wpas_dbus_handler_remove_blob(DBusMessage *message,
1838 struct wpa_supplicant *wpa_s)
1839 {
1840 DBusMessage *reply = NULL;
1841 char *blob_name;
1842
1843 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &blob_name,
1844 DBUS_TYPE_INVALID);
1845
1846 if (wpa_config_remove_blob(wpa_s->conf, blob_name)) {
1847 return dbus_message_new_error(message,
1848 WPAS_DBUS_ERROR_BLOB_UNKNOWN,
1849 "Blob id not set");
1850 }
1851 wpas_notify_blob_removed(wpa_s, blob_name);
1852
1853 return reply;
1854
1855 }
1856
1857 /*
1858 * wpas_dbus_handler_flush_bss - Flush the BSS cache
1859 * @message: Pointer to incoming dbus message
1860 * @wpa_s: wpa_supplicant structure for a network interface
1861 * Returns: NULL
1862 *
1863 * Handler function for "FlushBSS" method call of network interface.
1864 */
1865 DBusMessage * wpas_dbus_handler_flush_bss(DBusMessage *message,
1866 struct wpa_supplicant *wpa_s)
1867 {
1868 dbus_uint32_t age;
1869
1870 dbus_message_get_args(message, NULL, DBUS_TYPE_UINT32, &age,
1871 DBUS_TYPE_INVALID);
1872
1873 if (age == 0)
1874 wpa_bss_flush(wpa_s);
1875 else
1876 wpa_bss_flush_by_age(wpa_s, age);
1877
1878 return NULL;
1879 }
1880
1881
1882 #ifdef CONFIG_AUTOSCAN
1883 /**
1884 * wpas_dbus_handler_autoscan - Set autoscan parameters for the interface
1885 * @message: Pointer to incoming dbus message
1886 * @wpa_s: wpa_supplicant structure for a network interface
1887 * Returns: NULL
1888 *
1889 * Handler function for "AutoScan" method call of network interface.
1890 */
1891 DBusMessage * wpas_dbus_handler_autoscan(DBusMessage *message,
1892 struct wpa_supplicant *wpa_s)
1893 {
1894 DBusMessage *reply = NULL;
1895 enum wpa_states state = wpa_s->wpa_state;
1896 char *arg;
1897
1898 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &arg,
1899 DBUS_TYPE_INVALID);
1900
1901 if (arg != NULL && os_strlen(arg) > 0) {
1902 char *tmp;
1903 tmp = os_strdup(arg);
1904 if (tmp == NULL) {
1905 reply = dbus_message_new_error(message,
1906 DBUS_ERROR_NO_MEMORY,
1907 NULL);
1908 } else {
1909 os_free(wpa_s->conf->autoscan);
1910 wpa_s->conf->autoscan = tmp;
1911 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
1912 autoscan_init(wpa_s, 1);
1913 else if (state == WPA_SCANNING)
1914 wpa_supplicant_reinit_autoscan(wpa_s);
1915 }
1916 } else if (arg != NULL && os_strlen(arg) == 0) {
1917 os_free(wpa_s->conf->autoscan);
1918 wpa_s->conf->autoscan = NULL;
1919 autoscan_deinit(wpa_s);
1920 } else
1921 reply = dbus_message_new_error(message,
1922 DBUS_ERROR_INVALID_ARGS,
1923 NULL);
1924
1925 return reply;
1926 }
1927 #endif /* CONFIG_AUTOSCAN */
1928
1929
1930 /**
1931 * wpas_dbus_getter_capabilities - Return interface capabilities
1932 * @iter: Pointer to incoming dbus message iter
1933 * @error: Location to store error on failure
1934 * @user_data: Function specific data
1935 * Returns: TRUE on success, FALSE on failure
1936 *
1937 * Getter for "Capabilities" property of an interface.
1938 */
1939 dbus_bool_t wpas_dbus_getter_capabilities(DBusMessageIter *iter,
1940 DBusError *error, void *user_data)
1941 {
1942 struct wpa_supplicant *wpa_s = user_data;
1943 struct wpa_driver_capa capa;
1944 int res;
1945 DBusMessageIter iter_dict, iter_dict_entry, iter_dict_val, iter_array,
1946 variant_iter;
1947 const char *scans[] = { "active", "passive", "ssid" };
1948
1949 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
1950 "a{sv}", &variant_iter))
1951 goto nomem;
1952
1953 if (!wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
1954 goto nomem;
1955
1956 res = wpa_drv_get_capa(wpa_s, &capa);
1957
1958 /***** pairwise cipher */
1959 if (res < 0) {
1960 const char *args[] = {"ccmp", "tkip", "none"};
1961 if (!wpa_dbus_dict_append_string_array(
1962 &iter_dict, "Pairwise", args,
1963 sizeof(args) / sizeof(char*)))
1964 goto nomem;
1965 } else {
1966 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Pairwise",
1967 &iter_dict_entry,
1968 &iter_dict_val,
1969 &iter_array))
1970 goto nomem;
1971
1972 if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
1973 if (!wpa_dbus_dict_string_array_add_element(
1974 &iter_array, "ccmp"))
1975 goto nomem;
1976 }
1977
1978 if (capa.enc & WPA_DRIVER_CAPA_ENC_GCMP) {
1979 if (!wpa_dbus_dict_string_array_add_element(
1980 &iter_array, "gcmp"))
1981 goto nomem;
1982 }
1983
1984 if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
1985 if (!wpa_dbus_dict_string_array_add_element(
1986 &iter_array, "tkip"))
1987 goto nomem;
1988 }
1989
1990 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
1991 if (!wpa_dbus_dict_string_array_add_element(
1992 &iter_array, "none"))
1993 goto nomem;
1994 }
1995
1996 if (!wpa_dbus_dict_end_string_array(&iter_dict,
1997 &iter_dict_entry,
1998 &iter_dict_val,
1999 &iter_array))
2000 goto nomem;
2001 }
2002
2003 /***** group cipher */
2004 if (res < 0) {
2005 const char *args[] = {
2006 "ccmp", "tkip", "wep104", "wep40"
2007 };
2008 if (!wpa_dbus_dict_append_string_array(
2009 &iter_dict, "Group", args,
2010 sizeof(args) / sizeof(char*)))
2011 goto nomem;
2012 } else {
2013 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Group",
2014 &iter_dict_entry,
2015 &iter_dict_val,
2016 &iter_array))
2017 goto nomem;
2018
2019 if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
2020 if (!wpa_dbus_dict_string_array_add_element(
2021 &iter_array, "ccmp"))
2022 goto nomem;
2023 }
2024
2025 if (capa.enc & WPA_DRIVER_CAPA_ENC_GCMP) {
2026 if (!wpa_dbus_dict_string_array_add_element(
2027 &iter_array, "gcmp"))
2028 goto nomem;
2029 }
2030
2031 if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
2032 if (!wpa_dbus_dict_string_array_add_element(
2033 &iter_array, "tkip"))
2034 goto nomem;
2035 }
2036
2037 if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) {
2038 if (!wpa_dbus_dict_string_array_add_element(
2039 &iter_array, "wep104"))
2040 goto nomem;
2041 }
2042
2043 if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) {
2044 if (!wpa_dbus_dict_string_array_add_element(
2045 &iter_array, "wep40"))
2046 goto nomem;
2047 }
2048
2049 if (!wpa_dbus_dict_end_string_array(&iter_dict,
2050 &iter_dict_entry,
2051 &iter_dict_val,
2052 &iter_array))
2053 goto nomem;
2054 }
2055
2056 /***** key management */
2057 if (res < 0) {
2058 const char *args[] = {
2059 "wpa-psk", "wpa-eap", "ieee8021x", "wpa-none",
2060 #ifdef CONFIG_WPS
2061 "wps",
2062 #endif /* CONFIG_WPS */
2063 "none"
2064 };
2065 if (!wpa_dbus_dict_append_string_array(
2066 &iter_dict, "KeyMgmt", args,
2067 sizeof(args) / sizeof(char*)))
2068 goto nomem;
2069 } else {
2070 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "KeyMgmt",
2071 &iter_dict_entry,
2072 &iter_dict_val,
2073 &iter_array))
2074 goto nomem;
2075
2076 if (!wpa_dbus_dict_string_array_add_element(&iter_array,
2077 "none"))
2078 goto nomem;
2079
2080 if (!wpa_dbus_dict_string_array_add_element(&iter_array,
2081 "ieee8021x"))
2082 goto nomem;
2083
2084 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
2085 WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
2086 if (!wpa_dbus_dict_string_array_add_element(
2087 &iter_array, "wpa-eap"))
2088 goto nomem;
2089
2090 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT)
2091 if (!wpa_dbus_dict_string_array_add_element(
2092 &iter_array, "wpa-ft-eap"))
2093 goto nomem;
2094
2095 /* TODO: Ensure that driver actually supports sha256 encryption. */
2096 #ifdef CONFIG_IEEE80211W
2097 if (!wpa_dbus_dict_string_array_add_element(
2098 &iter_array, "wpa-eap-sha256"))
2099 goto nomem;
2100 #endif /* CONFIG_IEEE80211W */
2101 }
2102
2103 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
2104 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
2105 if (!wpa_dbus_dict_string_array_add_element(
2106 &iter_array, "wpa-psk"))
2107 goto nomem;
2108
2109 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK)
2110 if (!wpa_dbus_dict_string_array_add_element(
2111 &iter_array, "wpa-ft-psk"))
2112 goto nomem;
2113
2114 /* TODO: Ensure that driver actually supports sha256 encryption. */
2115 #ifdef CONFIG_IEEE80211W
2116 if (!wpa_dbus_dict_string_array_add_element(
2117 &iter_array, "wpa-psk-sha256"))
2118 goto nomem;
2119 #endif /* CONFIG_IEEE80211W */
2120 }
2121
2122 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
2123 if (!wpa_dbus_dict_string_array_add_element(
2124 &iter_array, "wpa-none"))
2125 goto nomem;
2126 }
2127
2128
2129 #ifdef CONFIG_WPS
2130 if (!wpa_dbus_dict_string_array_add_element(&iter_array,
2131 "wps"))
2132 goto nomem;
2133 #endif /* CONFIG_WPS */
2134
2135 if (!wpa_dbus_dict_end_string_array(&iter_dict,
2136 &iter_dict_entry,
2137 &iter_dict_val,
2138 &iter_array))
2139 goto nomem;
2140 }
2141
2142 /***** WPA protocol */
2143 if (res < 0) {
2144 const char *args[] = { "rsn", "wpa" };
2145 if (!wpa_dbus_dict_append_string_array(
2146 &iter_dict, "Protocol", args,
2147 sizeof(args) / sizeof(char*)))
2148 goto nomem;
2149 } else {
2150 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Protocol",
2151 &iter_dict_entry,
2152 &iter_dict_val,
2153 &iter_array))
2154 goto nomem;
2155
2156 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
2157 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
2158 if (!wpa_dbus_dict_string_array_add_element(
2159 &iter_array, "rsn"))
2160 goto nomem;
2161 }
2162
2163 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
2164 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
2165 if (!wpa_dbus_dict_string_array_add_element(
2166 &iter_array, "wpa"))
2167 goto nomem;
2168 }
2169
2170 if (!wpa_dbus_dict_end_string_array(&iter_dict,
2171 &iter_dict_entry,
2172 &iter_dict_val,
2173 &iter_array))
2174 goto nomem;
2175 }
2176
2177 /***** auth alg */
2178 if (res < 0) {
2179 const char *args[] = { "open", "shared", "leap" };
2180 if (!wpa_dbus_dict_append_string_array(
2181 &iter_dict, "AuthAlg", args,
2182 sizeof(args) / sizeof(char*)))
2183 goto nomem;
2184 } else {
2185 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "AuthAlg",
2186 &iter_dict_entry,
2187 &iter_dict_val,
2188 &iter_array))
2189 goto nomem;
2190
2191 if (capa.auth & (WPA_DRIVER_AUTH_OPEN)) {
2192 if (!wpa_dbus_dict_string_array_add_element(
2193 &iter_array, "open"))
2194 goto nomem;
2195 }
2196
2197 if (capa.auth & (WPA_DRIVER_AUTH_SHARED)) {
2198 if (!wpa_dbus_dict_string_array_add_element(
2199 &iter_array, "shared"))
2200 goto nomem;
2201 }
2202
2203 if (capa.auth & (WPA_DRIVER_AUTH_LEAP)) {
2204 if (!wpa_dbus_dict_string_array_add_element(
2205 &iter_array, "leap"))
2206 goto nomem;
2207 }
2208
2209 if (!wpa_dbus_dict_end_string_array(&iter_dict,
2210 &iter_dict_entry,
2211 &iter_dict_val,
2212 &iter_array))
2213 goto nomem;
2214 }
2215
2216 /***** Scan */
2217 if (!wpa_dbus_dict_append_string_array(&iter_dict, "Scan", scans,
2218 sizeof(scans) / sizeof(char *)))
2219 goto nomem;
2220
2221 /***** Modes */
2222 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Modes",
2223 &iter_dict_entry,
2224 &iter_dict_val,
2225 &iter_array))
2226 goto nomem;
2227
2228 if (!wpa_dbus_dict_string_array_add_element(
2229 &iter_array, "infrastructure"))
2230 goto nomem;
2231
2232 if (!wpa_dbus_dict_string_array_add_element(
2233 &iter_array, "ad-hoc"))
2234 goto nomem;
2235
2236 if (res >= 0) {
2237 if (capa.flags & (WPA_DRIVER_FLAGS_AP)) {
2238 if (!wpa_dbus_dict_string_array_add_element(
2239 &iter_array, "ap"))
2240 goto nomem;
2241 }
2242
2243 if (capa.flags & (WPA_DRIVER_FLAGS_P2P_CAPABLE)) {
2244 if (!wpa_dbus_dict_string_array_add_element(
2245 &iter_array, "p2p"))
2246 goto nomem;
2247 }
2248 }
2249
2250 if (!wpa_dbus_dict_end_string_array(&iter_dict,
2251 &iter_dict_entry,
2252 &iter_dict_val,
2253 &iter_array))
2254 goto nomem;
2255 /***** Modes end */
2256
2257 if (res >= 0) {
2258 dbus_int32_t max_scan_ssid = capa.max_scan_ssids;
2259
2260 if (!wpa_dbus_dict_append_int32(&iter_dict, "MaxScanSSID",
2261 max_scan_ssid))
2262 goto nomem;
2263 }
2264
2265 if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict))
2266 goto nomem;
2267 if (!dbus_message_iter_close_container(iter, &variant_iter))
2268 goto nomem;
2269
2270 return TRUE;
2271
2272 nomem:
2273 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
2274 return FALSE;
2275 }
2276
2277
2278 /**
2279 * wpas_dbus_getter_state - Get interface state
2280 * @iter: Pointer to incoming dbus message iter
2281 * @error: Location to store error on failure
2282 * @user_data: Function specific data
2283 * Returns: TRUE on success, FALSE on failure
2284 *
2285 * Getter for "State" property.
2286 */
2287 dbus_bool_t wpas_dbus_getter_state(DBusMessageIter *iter, DBusError *error,
2288 void *user_data)
2289 {
2290 struct wpa_supplicant *wpa_s = user_data;
2291 const char *str_state;
2292 char *state_ls, *tmp;
2293 dbus_bool_t success = FALSE;
2294
2295 str_state = wpa_supplicant_state_txt(wpa_s->wpa_state);
2296
2297 /* make state string lowercase to fit new DBus API convention
2298 */
2299 state_ls = tmp = os_strdup(str_state);
2300 if (!tmp) {
2301 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
2302 return FALSE;
2303 }
2304 while (*tmp) {
2305 *tmp = tolower(*tmp);
2306 tmp++;
2307 }
2308
2309 success = wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
2310 &state_ls, error);
2311
2312 os_free(state_ls);
2313
2314 return success;
2315 }
2316
2317
2318 /**
2319 * wpas_dbus_new_iface_get_scanning - Get interface scanning state
2320 * @iter: Pointer to incoming dbus message iter
2321 * @error: Location to store error on failure
2322 * @user_data: Function specific data
2323 * Returns: TRUE on success, FALSE on failure
2324 *
2325 * Getter for "scanning" property.
2326 */
2327 dbus_bool_t wpas_dbus_getter_scanning(DBusMessageIter *iter, DBusError *error,
2328 void *user_data)
2329 {
2330 struct wpa_supplicant *wpa_s = user_data;
2331 dbus_bool_t scanning = wpa_s->scanning ? TRUE : FALSE;
2332
2333 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
2334 &scanning, error);
2335 }
2336
2337
2338 /**
2339 * wpas_dbus_getter_ap_scan - Control roaming mode
2340 * @iter: Pointer to incoming dbus message iter
2341 * @error: Location to store error on failure
2342 * @user_data: Function specific data
2343 * Returns: TRUE on success, FALSE on failure
2344 *
2345 * Getter function for "ApScan" property.
2346 */
2347 dbus_bool_t wpas_dbus_getter_ap_scan(DBusMessageIter *iter, DBusError *error,
2348 void *user_data)
2349 {
2350 struct wpa_supplicant *wpa_s = user_data;
2351 dbus_uint32_t ap_scan = wpa_s->conf->ap_scan;
2352
2353 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
2354 &ap_scan, error);
2355 }
2356
2357
2358 /**
2359 * wpas_dbus_setter_ap_scan - Control roaming mode
2360 * @iter: Pointer to incoming dbus message iter
2361 * @error: Location to store error on failure
2362 * @user_data: Function specific data
2363 * Returns: TRUE on success, FALSE on failure
2364 *
2365 * Setter function for "ApScan" property.
2366 */
2367 dbus_bool_t wpas_dbus_setter_ap_scan(DBusMessageIter *iter, DBusError *error,
2368 void *user_data)
2369 {
2370 struct wpa_supplicant *wpa_s = user_data;
2371 dbus_uint32_t ap_scan;
2372
2373 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
2374 &ap_scan))
2375 return FALSE;
2376
2377 if (wpa_supplicant_set_ap_scan(wpa_s, ap_scan)) {
2378 dbus_set_error_const(error, DBUS_ERROR_FAILED,
2379 "ap_scan must be 0, 1, or 2");
2380 return FALSE;
2381 }
2382 return TRUE;
2383 }
2384
2385
2386 /**
2387 * wpas_dbus_getter_fast_reauth - Control fast
2388 * reauthentication (TLS session resumption)
2389 * @iter: Pointer to incoming dbus message iter
2390 * @error: Location to store error on failure
2391 * @user_data: Function specific data
2392 * Returns: TRUE on success, FALSE on failure
2393 *
2394 * Getter function for "FastReauth" property.
2395 */
2396 dbus_bool_t wpas_dbus_getter_fast_reauth(DBusMessageIter *iter,
2397 DBusError *error,
2398 void *user_data)
2399 {
2400 struct wpa_supplicant *wpa_s = user_data;
2401 dbus_bool_t fast_reauth = wpa_s->conf->fast_reauth ? TRUE : FALSE;
2402
2403 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
2404 &fast_reauth, error);
2405 }
2406
2407
2408 /**
2409 * wpas_dbus_setter_fast_reauth - Control fast
2410 * reauthentication (TLS session resumption)
2411 * @iter: Pointer to incoming dbus message iter
2412 * @error: Location to store error on failure
2413 * @user_data: Function specific data
2414 * Returns: TRUE on success, FALSE on failure
2415 *
2416 * Setter function for "FastReauth" property.
2417 */
2418 dbus_bool_t wpas_dbus_setter_fast_reauth(DBusMessageIter *iter,
2419 DBusError *error,
2420 void *user_data)
2421 {
2422 struct wpa_supplicant *wpa_s = user_data;
2423 dbus_bool_t fast_reauth;
2424
2425 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
2426 &fast_reauth))
2427 return FALSE;
2428
2429 wpa_s->conf->fast_reauth = fast_reauth;
2430 return TRUE;
2431 }
2432
2433
2434 /**
2435 * wpas_dbus_getter_disconnect_reason - Get most recent reason for disconnect
2436 * @iter: Pointer to incoming dbus message iter
2437 * @error: Location to store error on failure
2438 * @user_data: Function specific data
2439 * Returns: TRUE on success, FALSE on failure
2440 *
2441 * Getter for "DisconnectReason" property. The reason is negative if it is
2442 * locally generated.
2443 */
2444 dbus_bool_t wpas_dbus_getter_disconnect_reason(DBusMessageIter *iter,
2445 DBusError *error,
2446 void *user_data)
2447 {
2448 struct wpa_supplicant *wpa_s = user_data;
2449 dbus_int32_t reason = wpa_s->disconnect_reason;
2450 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
2451 &reason, error);
2452 }
2453
2454
2455 /**
2456 * wpas_dbus_getter_bss_expire_age - Get BSS entry expiration age
2457 * @iter: Pointer to incoming dbus message iter
2458 * @error: Location to store error on failure
2459 * @user_data: Function specific data
2460 * Returns: TRUE on success, FALSE on failure
2461 *
2462 * Getter function for "BSSExpireAge" property.
2463 */
2464 dbus_bool_t wpas_dbus_getter_bss_expire_age(DBusMessageIter *iter,
2465 DBusError *error,
2466 void *user_data)
2467 {
2468 struct wpa_supplicant *wpa_s = user_data;
2469 dbus_uint32_t expire_age = wpa_s->conf->bss_expiration_age;
2470
2471 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
2472 &expire_age, error);
2473 }
2474
2475
2476 /**
2477 * wpas_dbus_setter_bss_expire_age - Control BSS entry expiration age
2478 * @iter: Pointer to incoming dbus message iter
2479 * @error: Location to store error on failure
2480 * @user_data: Function specific data
2481 * Returns: TRUE on success, FALSE on failure
2482 *
2483 * Setter function for "BSSExpireAge" property.
2484 */
2485 dbus_bool_t wpas_dbus_setter_bss_expire_age(DBusMessageIter *iter,
2486 DBusError *error,
2487 void *user_data)
2488 {
2489 struct wpa_supplicant *wpa_s = user_data;
2490 dbus_uint32_t expire_age;
2491
2492 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
2493 &expire_age))
2494 return FALSE;
2495
2496 if (wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age)) {
2497 dbus_set_error_const(error, DBUS_ERROR_FAILED,
2498 "BSSExpireAge must be >= 10");
2499 return FALSE;
2500 }
2501 return TRUE;
2502 }
2503
2504
2505 /**
2506 * wpas_dbus_getter_bss_expire_count - Get BSS entry expiration scan count
2507 * @iter: Pointer to incoming dbus message iter
2508 * @error: Location to store error on failure
2509 * @user_data: Function specific data
2510 * Returns: TRUE on success, FALSE on failure
2511 *
2512 * Getter function for "BSSExpireCount" property.
2513 */
2514 dbus_bool_t wpas_dbus_getter_bss_expire_count(DBusMessageIter *iter,
2515 DBusError *error,
2516 void *user_data)
2517 {
2518 struct wpa_supplicant *wpa_s = user_data;
2519 dbus_uint32_t expire_count = wpa_s->conf->bss_expiration_scan_count;
2520
2521 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
2522 &expire_count, error);
2523 }
2524
2525
2526 /**
2527 * wpas_dbus_setter_bss_expire_count - Control BSS entry expiration scan count
2528 * @iter: Pointer to incoming dbus message iter
2529 * @error: Location to store error on failure
2530 * @user_data: Function specific data
2531 * Returns: TRUE on success, FALSE on failure
2532 *
2533 * Setter function for "BSSExpireCount" property.
2534 */
2535 dbus_bool_t wpas_dbus_setter_bss_expire_count(DBusMessageIter *iter,
2536 DBusError *error,
2537 void *user_data)
2538 {
2539 struct wpa_supplicant *wpa_s = user_data;
2540 dbus_uint32_t expire_count;
2541
2542 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
2543 &expire_count))
2544 return FALSE;
2545
2546 if (wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count)) {
2547 dbus_set_error_const(error, DBUS_ERROR_FAILED,
2548 "BSSExpireCount must be > 0");
2549 return FALSE;
2550 }
2551 return TRUE;
2552 }
2553
2554
2555 /**
2556 * wpas_dbus_getter_country - Control country code
2557 * @iter: Pointer to incoming dbus message iter
2558 * @error: Location to store error on failure
2559 * @user_data: Function specific data
2560 * Returns: TRUE on success, FALSE on failure
2561 *
2562 * Getter function for "Country" property.
2563 */
2564 dbus_bool_t wpas_dbus_getter_country(DBusMessageIter *iter, DBusError *error,
2565 void *user_data)
2566 {
2567 struct wpa_supplicant *wpa_s = user_data;
2568 char country[3];
2569 char *str = country;
2570
2571 country[0] = wpa_s->conf->country[0];
2572 country[1] = wpa_s->conf->country[1];
2573 country[2] = '\0';
2574
2575 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
2576 &str, error);
2577 }
2578
2579
2580 /**
2581 * wpas_dbus_setter_country - Control country code
2582 * @iter: Pointer to incoming dbus message iter
2583 * @error: Location to store error on failure
2584 * @user_data: Function specific data
2585 * Returns: TRUE on success, FALSE on failure
2586 *
2587 * Setter function for "Country" property.
2588 */
2589 dbus_bool_t wpas_dbus_setter_country(DBusMessageIter *iter, DBusError *error,
2590 void *user_data)
2591 {
2592 struct wpa_supplicant *wpa_s = user_data;
2593 const char *country;
2594
2595 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
2596 &country))
2597 return FALSE;
2598
2599 if (!country[0] || !country[1]) {
2600 dbus_set_error_const(error, DBUS_ERROR_FAILED,
2601 "invalid country code");
2602 return FALSE;
2603 }
2604
2605 if (wpa_s->drv_priv != NULL && wpa_drv_set_country(wpa_s, country)) {
2606 wpa_printf(MSG_DEBUG, "Failed to set country");
2607 dbus_set_error_const(error, DBUS_ERROR_FAILED,
2608 "failed to set country code");
2609 return FALSE;
2610 }
2611
2612 wpa_s->conf->country[0] = country[0];
2613 wpa_s->conf->country[1] = country[1];
2614 return TRUE;
2615 }
2616
2617
2618 /**
2619 * wpas_dbus_getter_scan_interval - Get scan interval
2620 * @iter: Pointer to incoming dbus message iter
2621 * @error: Location to store error on failure
2622 * @user_data: Function specific data
2623 * Returns: TRUE on success, FALSE on failure
2624 *
2625 * Getter function for "ScanInterval" property.
2626 */
2627 dbus_bool_t wpas_dbus_getter_scan_interval(DBusMessageIter *iter,
2628 DBusError *error,
2629 void *user_data)
2630 {
2631 struct wpa_supplicant *wpa_s = user_data;
2632 dbus_int32_t scan_interval = wpa_s->scan_interval;
2633
2634 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
2635 &scan_interval, error);
2636 }
2637
2638
2639 /**
2640 * wpas_dbus_setter_scan_interval - Control scan interval
2641 * @iter: Pointer to incoming dbus message iter
2642 * @error: Location to store error on failure
2643 * @user_data: Function specific data
2644 * Returns: TRUE on success, FALSE on failure
2645 *
2646 * Setter function for "ScanInterval" property.
2647 */
2648 dbus_bool_t wpas_dbus_setter_scan_interval(DBusMessageIter *iter,
2649 DBusError *error,
2650 void *user_data)
2651 {
2652 struct wpa_supplicant *wpa_s = user_data;
2653 dbus_int32_t scan_interval;
2654
2655 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_INT32,
2656 &scan_interval))
2657 return FALSE;
2658
2659 if (wpa_supplicant_set_scan_interval(wpa_s, scan_interval)) {
2660 dbus_set_error_const(error, DBUS_ERROR_FAILED,
2661 "scan_interval must be >= 0");
2662 return FALSE;
2663 }
2664 return TRUE;
2665 }
2666
2667
2668 /**
2669 * wpas_dbus_getter_ifname - Get interface name
2670 * @iter: Pointer to incoming dbus message iter
2671 * @error: Location to store error on failure
2672 * @user_data: Function specific data
2673 * Returns: TRUE on success, FALSE on failure
2674 *
2675 * Getter for "Ifname" property.
2676 */
2677 dbus_bool_t wpas_dbus_getter_ifname(DBusMessageIter *iter, DBusError *error,
2678 void *user_data)
2679 {
2680 struct wpa_supplicant *wpa_s = user_data;
2681 const char *ifname = wpa_s->ifname;
2682
2683 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
2684 &ifname, error);
2685 }
2686
2687
2688 /**
2689 * wpas_dbus_getter_driver - Get interface name
2690 * @iter: Pointer to incoming dbus message iter
2691 * @error: Location to store error on failure
2692 * @user_data: Function specific data
2693 * Returns: TRUE on success, FALSE on failure
2694 *
2695 * Getter for "Driver" property.
2696 */
2697 dbus_bool_t wpas_dbus_getter_driver(DBusMessageIter *iter, DBusError *error,
2698 void *user_data)
2699 {
2700 struct wpa_supplicant *wpa_s = user_data;
2701 const char *driver;
2702
2703 if (wpa_s->driver == NULL || wpa_s->driver->name == NULL) {
2704 wpa_printf(MSG_DEBUG, "wpas_dbus_getter_driver[dbus]: "
2705 "wpa_s has no driver set");
2706 dbus_set_error(error, DBUS_ERROR_FAILED, "%s: no driver set",
2707 __func__);
2708 return FALSE;
2709 }
2710
2711 driver = wpa_s->driver->name;
2712 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
2713 &driver, error);
2714 }
2715
2716
2717 /**
2718 * wpas_dbus_getter_current_bss - Get current bss object path
2719 * @iter: Pointer to incoming dbus message iter
2720 * @error: Location to store error on failure
2721 * @user_data: Function specific data
2722 * Returns: TRUE on success, FALSE on failure
2723 *
2724 * Getter for "CurrentBSS" property.
2725 */
2726 dbus_bool_t wpas_dbus_getter_current_bss(DBusMessageIter *iter,
2727 DBusError *error,
2728 void *user_data)
2729 {
2730 struct wpa_supplicant *wpa_s = user_data;
2731 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *bss_obj_path = path_buf;
2732
2733 if (wpa_s->current_bss)
2734 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2735 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
2736 wpa_s->dbus_new_path, wpa_s->current_bss->id);
2737 else
2738 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
2739
2740 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
2741 &bss_obj_path, error);
2742 }
2743
2744
2745 /**
2746 * wpas_dbus_getter_current_network - Get current network object path
2747 * @iter: Pointer to incoming dbus message iter
2748 * @error: Location to store error on failure
2749 * @user_data: Function specific data
2750 * Returns: TRUE on success, FALSE on failure
2751 *
2752 * Getter for "CurrentNetwork" property.
2753 */
2754 dbus_bool_t wpas_dbus_getter_current_network(DBusMessageIter *iter,
2755 DBusError *error,
2756 void *user_data)
2757 {
2758 struct wpa_supplicant *wpa_s = user_data;
2759 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *net_obj_path = path_buf;
2760
2761 if (wpa_s->current_ssid)
2762 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2763 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
2764 wpa_s->dbus_new_path, wpa_s->current_ssid->id);
2765 else
2766 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
2767
2768 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
2769 &net_obj_path, error);
2770 }
2771
2772
2773 /**
2774 * wpas_dbus_getter_current_auth_mode - Get current authentication type
2775 * @iter: Pointer to incoming dbus message iter
2776 * @error: Location to store error on failure
2777 * @user_data: Function specific data
2778 * Returns: TRUE on success, FALSE on failure
2779 *
2780 * Getter for "CurrentAuthMode" property.
2781 */
2782 dbus_bool_t wpas_dbus_getter_current_auth_mode(DBusMessageIter *iter,
2783 DBusError *error,
2784 void *user_data)
2785 {
2786 struct wpa_supplicant *wpa_s = user_data;
2787 const char *eap_mode;
2788 const char *auth_mode;
2789 char eap_mode_buf[WPAS_DBUS_AUTH_MODE_MAX];
2790
2791 if (wpa_s->wpa_state != WPA_COMPLETED) {
2792 auth_mode = "INACTIVE";
2793 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X ||
2794 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2795 eap_mode = wpa_supplicant_get_eap_mode(wpa_s);
2796 os_snprintf(eap_mode_buf, WPAS_DBUS_AUTH_MODE_MAX,
2797 "EAP-%s", eap_mode);
2798 auth_mode = eap_mode_buf;
2799
2800 } else {
2801 auth_mode = wpa_key_mgmt_txt(wpa_s->key_mgmt,
2802 wpa_s->current_ssid->proto);
2803 }
2804
2805 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
2806 &auth_mode, error);
2807 }
2808
2809
2810 /**
2811 * wpas_dbus_getter_bridge_ifname - Get interface name
2812 * @iter: Pointer to incoming dbus message iter
2813 * @error: Location to store error on failure
2814 * @user_data: Function specific data
2815 * Returns: TRUE on success, FALSE on failure
2816 *
2817 * Getter for "BridgeIfname" property.
2818 */
2819 dbus_bool_t wpas_dbus_getter_bridge_ifname(DBusMessageIter *iter,
2820 DBusError *error,
2821 void *user_data)
2822 {
2823 struct wpa_supplicant *wpa_s = user_data;
2824 const char *bridge_ifname = wpa_s->bridge_ifname;
2825 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
2826 &bridge_ifname, error);
2827 }
2828
2829
2830 /**
2831 * wpas_dbus_getter_bsss - Get array of BSSs objects
2832 * @iter: Pointer to incoming dbus message iter
2833 * @error: Location to store error on failure
2834 * @user_data: Function specific data
2835 * Returns: TRUE on success, FALSE on failure
2836 *
2837 * Getter for "BSSs" property.
2838 */
2839 dbus_bool_t wpas_dbus_getter_bsss(DBusMessageIter *iter, DBusError *error,
2840 void *user_data)
2841 {
2842 struct wpa_supplicant *wpa_s = user_data;
2843 struct wpa_bss *bss;
2844 char **paths;
2845 unsigned int i = 0;
2846 dbus_bool_t success = FALSE;
2847
2848 paths = os_calloc(wpa_s->num_bss, sizeof(char *));
2849 if (!paths) {
2850 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
2851 return FALSE;
2852 }
2853
2854 /* Loop through scan results and append each result's object path */
2855 dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
2856 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
2857 if (paths[i] == NULL) {
2858 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
2859 "no memory");
2860 goto out;
2861 }
2862 /* Construct the object path for this BSS. */
2863 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
2864 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
2865 wpa_s->dbus_new_path, bss->id);
2866 }
2867
2868 success = wpas_dbus_simple_array_property_getter(iter,
2869 DBUS_TYPE_OBJECT_PATH,
2870 paths, wpa_s->num_bss,
2871 error);
2872
2873 out:
2874 while (i)
2875 os_free(paths[--i]);
2876 os_free(paths);
2877 return success;
2878 }
2879
2880
2881 /**
2882 * wpas_dbus_getter_networks - Get array of networks objects
2883 * @iter: Pointer to incoming dbus message iter
2884 * @error: Location to store error on failure
2885 * @user_data: Function specific data
2886 * Returns: TRUE on success, FALSE on failure
2887 *
2888 * Getter for "Networks" property.
2889 */
2890 dbus_bool_t wpas_dbus_getter_networks(DBusMessageIter *iter, DBusError *error,
2891 void *user_data)
2892 {
2893 struct wpa_supplicant *wpa_s = user_data;
2894 struct wpa_ssid *ssid;
2895 char **paths;
2896 unsigned int i = 0, num = 0;
2897 dbus_bool_t success = FALSE;
2898
2899 if (wpa_s->conf == NULL) {
2900 wpa_printf(MSG_ERROR, "%s[dbus]: An error occurred getting "
2901 "networks list.", __func__);
2902 dbus_set_error(error, DBUS_ERROR_FAILED, "%s: an error "
2903 "occurred getting the networks list", __func__);
2904 return FALSE;
2905 }
2906
2907 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
2908 if (!network_is_persistent_group(ssid))
2909 num++;
2910
2911 paths = os_calloc(num, sizeof(char *));
2912 if (!paths) {
2913 dbus_set_error(error, DBUS_ERROR_NO_MEMORY, "no memory");
2914 return FALSE;
2915 }
2916
2917 /* Loop through configured networks and append object path of each */
2918 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2919 if (network_is_persistent_group(ssid))
2920 continue;
2921 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
2922 if (paths[i] == NULL) {
2923 dbus_set_error(error, DBUS_ERROR_NO_MEMORY, "no memory");
2924 goto out;
2925 }
2926
2927 /* Construct the object path for this network. */
2928 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
2929 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
2930 wpa_s->dbus_new_path, ssid->id);
2931 }
2932
2933 success = wpas_dbus_simple_array_property_getter(iter,
2934 DBUS_TYPE_OBJECT_PATH,
2935 paths, num, error);
2936
2937 out:
2938 while (i)
2939 os_free(paths[--i]);
2940 os_free(paths);
2941 return success;
2942 }
2943
2944
2945 /**
2946 * wpas_dbus_getter_blobs - Get all blobs defined for this interface
2947 * @iter: Pointer to incoming dbus message iter
2948 * @error: Location to store error on failure
2949 * @user_data: Function specific data
2950 * Returns: TRUE on success, FALSE on failure
2951 *
2952 * Getter for "Blobs" property.
2953 */
2954 dbus_bool_t wpas_dbus_getter_blobs(DBusMessageIter *iter, DBusError *error,
2955 void *user_data)
2956 {
2957 struct wpa_supplicant *wpa_s = user_data;
2958 DBusMessageIter variant_iter, dict_iter, entry_iter, array_iter;
2959 struct wpa_config_blob *blob;
2960
2961 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
2962 "a{say}", &variant_iter) ||
2963 !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
2964 "{say}", &dict_iter)) {
2965 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
2966 return FALSE;
2967 }
2968
2969 blob = wpa_s->conf->blobs;
2970 while (blob) {
2971 if (!dbus_message_iter_open_container(&dict_iter,
2972 DBUS_TYPE_DICT_ENTRY,
2973 NULL, &entry_iter) ||
2974 !dbus_message_iter_append_basic(&entry_iter,
2975 DBUS_TYPE_STRING,
2976 &(blob->name)) ||
2977 !dbus_message_iter_open_container(&entry_iter,
2978 DBUS_TYPE_ARRAY,
2979 DBUS_TYPE_BYTE_AS_STRING,
2980 &array_iter) ||
2981 !dbus_message_iter_append_fixed_array(&array_iter,
2982 DBUS_TYPE_BYTE,
2983 &(blob->data),
2984 blob->len) ||
2985 !dbus_message_iter_close_container(&entry_iter,
2986 &array_iter) ||
2987 !dbus_message_iter_close_container(&dict_iter,
2988 &entry_iter)) {
2989 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
2990 "no memory");
2991 return FALSE;
2992 }
2993
2994 blob = blob->next;
2995 }
2996
2997 if (!dbus_message_iter_close_container(&variant_iter, &dict_iter) ||
2998 !dbus_message_iter_close_container(iter, &variant_iter)) {
2999 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3000 return FALSE;
3001 }
3002
3003 return TRUE;
3004 }
3005
3006
3007 static struct wpa_bss * get_bss_helper(struct bss_handler_args *args,
3008 DBusError *error, const char *func_name)
3009 {
3010 struct wpa_bss *res = wpa_bss_get_id(args->wpa_s, args->id);
3011
3012 if (!res) {
3013 wpa_printf(MSG_ERROR, "%s[dbus]: no bss with id %d found",
3014 func_name, args->id);
3015 dbus_set_error(error, DBUS_ERROR_FAILED,
3016 "%s: BSS %d not found",
3017 func_name, args->id);
3018 }
3019
3020 return res;
3021 }
3022
3023
3024 /**
3025 * wpas_dbus_getter_bss_bssid - Return the BSSID of a BSS
3026 * @iter: Pointer to incoming dbus message iter
3027 * @error: Location to store error on failure
3028 * @user_data: Function specific data
3029 * Returns: TRUE on success, FALSE on failure
3030 *
3031 * Getter for "BSSID" property.
3032 */
3033 dbus_bool_t wpas_dbus_getter_bss_bssid(DBusMessageIter *iter, DBusError *error,
3034 void *user_data)
3035 {
3036 struct bss_handler_args *args = user_data;
3037 struct wpa_bss *res;
3038
3039 res = get_bss_helper(args, error, __func__);
3040 if (!res)
3041 return FALSE;
3042
3043 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
3044 res->bssid, ETH_ALEN,
3045 error);
3046 }
3047
3048
3049 /**
3050 * wpas_dbus_getter_bss_ssid - Return the SSID of a BSS
3051 * @iter: Pointer to incoming dbus message iter
3052 * @error: Location to store error on failure
3053 * @user_data: Function specific data
3054 * Returns: TRUE on success, FALSE on failure
3055 *
3056 * Getter for "SSID" property.
3057 */
3058 dbus_bool_t wpas_dbus_getter_bss_ssid(DBusMessageIter *iter, DBusError *error,
3059 void *user_data)
3060 {
3061 struct bss_handler_args *args = user_data;
3062 struct wpa_bss *res;
3063
3064 res = get_bss_helper(args, error, __func__);
3065 if (!res)
3066 return FALSE;
3067
3068 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
3069 res->ssid, res->ssid_len,
3070 error);
3071 }
3072
3073
3074 /**
3075 * wpas_dbus_getter_bss_privacy - Return the privacy flag of a BSS
3076 * @iter: Pointer to incoming dbus message iter
3077 * @error: Location to store error on failure
3078 * @user_data: Function specific data
3079 * Returns: TRUE on success, FALSE on failure
3080 *
3081 * Getter for "Privacy" property.
3082 */
3083 dbus_bool_t wpas_dbus_getter_bss_privacy(DBusMessageIter *iter,
3084 DBusError *error, void *user_data)
3085 {
3086 struct bss_handler_args *args = user_data;
3087 struct wpa_bss *res;
3088 dbus_bool_t privacy;
3089
3090 res = get_bss_helper(args, error, __func__);
3091 if (!res)
3092 return FALSE;
3093
3094 privacy = (res->caps & IEEE80211_CAP_PRIVACY) ? TRUE : FALSE;
3095 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
3096 &privacy, error);
3097 }
3098
3099
3100 /**
3101 * wpas_dbus_getter_bss_mode - Return the mode of a BSS
3102 * @iter: Pointer to incoming dbus message iter
3103 * @error: Location to store error on failure
3104 * @user_data: Function specific data
3105 * Returns: TRUE on success, FALSE on failure
3106 *
3107 * Getter for "Mode" property.
3108 */
3109 dbus_bool_t wpas_dbus_getter_bss_mode(DBusMessageIter *iter, DBusError *error,
3110 void *user_data)
3111 {
3112 struct bss_handler_args *args = user_data;
3113 struct wpa_bss *res;
3114 const char *mode;
3115
3116 res = get_bss_helper(args, error, __func__);
3117 if (!res)
3118 return FALSE;
3119
3120 if (res->caps & IEEE80211_CAP_IBSS)
3121 mode = "ad-hoc";
3122 else
3123 mode = "infrastructure";
3124
3125 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3126 &mode, error);
3127 }
3128
3129
3130 /**
3131 * wpas_dbus_getter_bss_level - Return the signal strength of a BSS
3132 * @iter: Pointer to incoming dbus message iter
3133 * @error: Location to store error on failure
3134 * @user_data: Function specific data
3135 * Returns: TRUE on success, FALSE on failure
3136 *
3137 * Getter for "Level" property.
3138 */
3139 dbus_bool_t wpas_dbus_getter_bss_signal(DBusMessageIter *iter,
3140 DBusError *error, void *user_data)
3141 {
3142 struct bss_handler_args *args = user_data;
3143 struct wpa_bss *res;
3144 s16 level;
3145
3146 res = get_bss_helper(args, error, __func__);
3147 if (!res)
3148 return FALSE;
3149
3150 level = (s16) res->level;
3151 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT16,
3152 &level, error);
3153 }
3154
3155
3156 /**
3157 * wpas_dbus_getter_bss_frequency - Return the frequency of a BSS
3158 * @iter: Pointer to incoming dbus message iter
3159 * @error: Location to store error on failure
3160 * @user_data: Function specific data
3161 * Returns: TRUE on success, FALSE on failure
3162 *
3163 * Getter for "Frequency" property.
3164 */
3165 dbus_bool_t wpas_dbus_getter_bss_frequency(DBusMessageIter *iter,
3166 DBusError *error, void *user_data)
3167 {
3168 struct bss_handler_args *args = user_data;
3169 struct wpa_bss *res;
3170 u16 freq;
3171
3172 res = get_bss_helper(args, error, __func__);
3173 if (!res)
3174 return FALSE;
3175
3176 freq = (u16) res->freq;
3177 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
3178 &freq, error);
3179 }
3180
3181
3182 static int cmp_u8s_desc(const void *a, const void *b)
3183 {
3184 return (*(u8 *) b - *(u8 *) a);
3185 }
3186
3187
3188 /**
3189 * wpas_dbus_getter_bss_rates - Return available bit rates of a BSS
3190 * @iter: Pointer to incoming dbus message iter
3191 * @error: Location to store error on failure
3192 * @user_data: Function specific data
3193 * Returns: TRUE on success, FALSE on failure
3194 *
3195 * Getter for "Rates" property.
3196 */
3197 dbus_bool_t wpas_dbus_getter_bss_rates(DBusMessageIter *iter,
3198 DBusError *error, void *user_data)
3199 {
3200 struct bss_handler_args *args = user_data;
3201 struct wpa_bss *res;
3202 u8 *ie_rates = NULL;
3203 u32 *real_rates;
3204 int rates_num, i;
3205 dbus_bool_t success = FALSE;
3206
3207 res = get_bss_helper(args, error, __func__);
3208 if (!res)
3209 return FALSE;
3210
3211 rates_num = wpa_bss_get_bit_rates(res, &ie_rates);
3212 if (rates_num < 0)
3213 return FALSE;
3214
3215 qsort(ie_rates, rates_num, 1, cmp_u8s_desc);
3216
3217 real_rates = os_malloc(sizeof(u32) * rates_num);
3218 if (!real_rates) {
3219 os_free(ie_rates);
3220 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3221 return FALSE;
3222 }
3223
3224 for (i = 0; i < rates_num; i++)
3225 real_rates[i] = ie_rates[i] * 500000;
3226
3227 success = wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_UINT32,
3228 real_rates, rates_num,
3229 error);
3230
3231 os_free(ie_rates);
3232 os_free(real_rates);
3233 return success;
3234 }
3235
3236
3237 static dbus_bool_t wpas_dbus_get_bss_security_prop(DBusMessageIter *iter,
3238 struct wpa_ie_data *ie_data,
3239 DBusError *error)
3240 {
3241 DBusMessageIter iter_dict, variant_iter;
3242 const char *group;
3243 const char *pairwise[3]; /* max 3 pairwise ciphers is supported */
3244 const char *key_mgmt[7]; /* max 7 key managements may be supported */
3245 int n;
3246
3247 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
3248 "a{sv}", &variant_iter))
3249 goto nomem;
3250
3251 if (!wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
3252 goto nomem;
3253
3254 /* KeyMgmt */
3255 n = 0;
3256 if (ie_data->key_mgmt & WPA_KEY_MGMT_PSK)
3257 key_mgmt[n++] = "wpa-psk";
3258 if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_PSK)
3259 key_mgmt[n++] = "wpa-ft-psk";
3260 if (ie_data->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
3261 key_mgmt[n++] = "wpa-psk-sha256";
3262 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X)
3263 key_mgmt[n++] = "wpa-eap";
3264 if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X)
3265 key_mgmt[n++] = "wpa-ft-eap";
3266 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256)
3267 key_mgmt[n++] = "wpa-eap-sha256";
3268 if (ie_data->key_mgmt & WPA_KEY_MGMT_NONE)
3269 key_mgmt[n++] = "wpa-none";
3270
3271 if (!wpa_dbus_dict_append_string_array(&iter_dict, "KeyMgmt",
3272 key_mgmt, n))
3273 goto nomem;
3274
3275 /* Group */
3276 switch (ie_data->group_cipher) {
3277 case WPA_CIPHER_WEP40:
3278 group = "wep40";
3279 break;
3280 case WPA_CIPHER_TKIP:
3281 group = "tkip";
3282 break;
3283 case WPA_CIPHER_CCMP:
3284 group = "ccmp";
3285 break;
3286 case WPA_CIPHER_GCMP:
3287 group = "gcmp";
3288 break;
3289 case WPA_CIPHER_WEP104:
3290 group = "wep104";
3291 break;
3292 default:
3293 group = "";
3294 break;
3295 }
3296
3297 if (!wpa_dbus_dict_append_string(&iter_dict, "Group", group))
3298 goto nomem;
3299
3300 /* Pairwise */
3301 n = 0;
3302 if (ie_data->pairwise_cipher & WPA_CIPHER_TKIP)
3303 pairwise[n++] = "tkip";
3304 if (ie_data->pairwise_cipher & WPA_CIPHER_CCMP)
3305 pairwise[n++] = "ccmp";
3306 if (ie_data->pairwise_cipher & WPA_CIPHER_GCMP)
3307 pairwise[n++] = "gcmp";
3308
3309 if (!wpa_dbus_dict_append_string_array(&iter_dict, "Pairwise",
3310 pairwise, n))
3311 goto nomem;
3312
3313 /* Management group (RSN only) */
3314 if (ie_data->proto == WPA_PROTO_RSN) {
3315 switch (ie_data->mgmt_group_cipher) {
3316 #ifdef CONFIG_IEEE80211W
3317 case WPA_CIPHER_AES_128_CMAC:
3318 group = "aes128cmac";
3319 break;
3320 #endif /* CONFIG_IEEE80211W */
3321 default:
3322 group = "";
3323 break;
3324 }
3325
3326 if (!wpa_dbus_dict_append_string(&iter_dict, "MgmtGroup",
3327 group))
3328 goto nomem;
3329 }
3330
3331 if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict))
3332 goto nomem;
3333 if (!dbus_message_iter_close_container(iter, &variant_iter))
3334 goto nomem;
3335
3336 return TRUE;
3337
3338 nomem:
3339 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3340 return FALSE;
3341 }
3342
3343
3344 /**
3345 * wpas_dbus_getter_bss_wpa - Return the WPA options of a BSS
3346 * @iter: Pointer to incoming dbus message iter
3347 * @error: Location to store error on failure
3348 * @user_data: Function specific data
3349 * Returns: TRUE on success, FALSE on failure
3350 *
3351 * Getter for "WPA" property.
3352 */
3353 dbus_bool_t wpas_dbus_getter_bss_wpa(DBusMessageIter *iter, DBusError *error,
3354 void *user_data)
3355 {
3356 struct bss_handler_args *args = user_data;
3357 struct wpa_bss *res;
3358 struct wpa_ie_data wpa_data;
3359 const u8 *ie;
3360
3361 res = get_bss_helper(args, error, __func__);
3362 if (!res)
3363 return FALSE;
3364
3365 os_memset(&wpa_data, 0, sizeof(wpa_data));
3366 ie = wpa_bss_get_vendor_ie(res, WPA_IE_VENDOR_TYPE);
3367 if (ie) {
3368 if (wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0) {
3369 dbus_set_error_const(error, DBUS_ERROR_FAILED,
3370 "failed to parse WPA IE");
3371 return FALSE;
3372 }
3373 }
3374
3375 return wpas_dbus_get_bss_security_prop(iter, &wpa_data, error);
3376 }
3377
3378
3379 /**
3380 * wpas_dbus_getter_bss_rsn - Return the RSN options of a BSS
3381 * @iter: Pointer to incoming dbus message iter
3382 * @error: Location to store error on failure
3383 * @user_data: Function specific data
3384 * Returns: TRUE on success, FALSE on failure
3385 *
3386 * Getter for "RSN" property.
3387 */
3388 dbus_bool_t wpas_dbus_getter_bss_rsn(DBusMessageIter *iter, DBusError *error,
3389 void *user_data)
3390 {
3391 struct bss_handler_args *args = user_data;
3392 struct wpa_bss *res;
3393 struct wpa_ie_data wpa_data;
3394 const u8 *ie;
3395
3396 res = get_bss_helper(args, error, __func__);
3397 if (!res)
3398 return FALSE;
3399
3400 os_memset(&wpa_data, 0, sizeof(wpa_data));
3401 ie = wpa_bss_get_ie(res, WLAN_EID_RSN);
3402 if (ie) {
3403 if (wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0) {
3404 dbus_set_error_const(error, DBUS_ERROR_FAILED,
3405 "failed to parse RSN IE");
3406 return FALSE;
3407 }
3408 }
3409
3410 return wpas_dbus_get_bss_security_prop(iter, &wpa_data, error);
3411 }
3412
3413
3414 /**
3415 * wpas_dbus_getter_bss_wps - Return the WPS options of a BSS
3416 * @iter: Pointer to incoming dbus message iter
3417 * @error: Location to store error on failure
3418 * @user_data: Function specific data
3419 * Returns: TRUE on success, FALSE on failure
3420 *
3421 * Getter for "WPS" property.
3422 */
3423 dbus_bool_t wpas_dbus_getter_bss_wps(DBusMessageIter *iter, DBusError *error,
3424 void *user_data)
3425 {
3426 struct bss_handler_args *args = user_data;
3427 struct wpa_bss *res;
3428 #ifdef CONFIG_WPS
3429 struct wpabuf *wps_ie;
3430 #endif /* CONFIG_WPS */
3431 DBusMessageIter iter_dict, variant_iter;
3432 const char *type = "";
3433
3434 res = get_bss_helper(args, error, __func__);
3435 if (!res)
3436 return FALSE;
3437
3438 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
3439 "a{sv}", &variant_iter))
3440 goto nomem;
3441
3442 if (!wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
3443 goto nomem;
3444
3445 #ifdef CONFIG_WPS
3446 wps_ie = wpa_bss_get_vendor_ie_multi(res, WPS_IE_VENDOR_TYPE);
3447 if (wps_ie) {
3448 if (wps_is_selected_pbc_registrar(wps_ie))
3449 type = "pbc";
3450 else if (wps_is_selected_pin_registrar(wps_ie))
3451 type = "pin";
3452 }
3453 #endif /* CONFIG_WPS */
3454
3455 if (!wpa_dbus_dict_append_string(&iter_dict, "Type", type))
3456 goto nomem;
3457
3458 if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict))
3459 goto nomem;
3460 if (!dbus_message_iter_close_container(iter, &variant_iter))
3461 goto nomem;
3462
3463 return TRUE;
3464
3465 nomem:
3466 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3467 return FALSE;
3468 }
3469
3470
3471 /**
3472 * wpas_dbus_getter_bss_ies - Return all IEs of a BSS
3473 * @iter: Pointer to incoming dbus message iter
3474 * @error: Location to store error on failure
3475 * @user_data: Function specific data
3476 * Returns: TRUE on success, FALSE on failure
3477 *
3478 * Getter for "IEs" property.
3479 */
3480 dbus_bool_t wpas_dbus_getter_bss_ies(DBusMessageIter *iter, DBusError *error,
3481 void *user_data)
3482 {
3483 struct bss_handler_args *args = user_data;
3484 struct wpa_bss *res;
3485
3486 res = get_bss_helper(args, error, __func__);
3487 if (!res)
3488 return FALSE;
3489
3490 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
3491 res + 1, res->ie_len,
3492 error);
3493 }
3494
3495
3496 /**
3497 * wpas_dbus_getter_enabled - Check whether network is enabled or disabled
3498 * @iter: Pointer to incoming dbus message iter
3499 * @error: Location to store error on failure
3500 * @user_data: Function specific data
3501 * Returns: TRUE on success, FALSE on failure
3502 *
3503 * Getter for "enabled" property of a configured network.
3504 */
3505 dbus_bool_t wpas_dbus_getter_enabled(DBusMessageIter *iter, DBusError *error,
3506 void *user_data)
3507 {
3508 struct network_handler_args *net = user_data;
3509 dbus_bool_t enabled = net->ssid->disabled ? FALSE : TRUE;
3510
3511 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
3512 &enabled, error);
3513 }
3514
3515
3516 /**
3517 * wpas_dbus_setter_enabled - Mark a configured network as enabled or disabled
3518 * @iter: Pointer to incoming dbus message iter
3519 * @error: Location to store error on failure
3520 * @user_data: Function specific data
3521 * Returns: TRUE on success, FALSE on failure
3522 *
3523 * Setter for "Enabled" property of a configured network.
3524 */
3525 dbus_bool_t wpas_dbus_setter_enabled(DBusMessageIter *iter, DBusError *error,
3526 void *user_data)
3527 {
3528 struct network_handler_args *net = user_data;
3529 struct wpa_supplicant *wpa_s;
3530 struct wpa_ssid *ssid;
3531 dbus_bool_t enable;
3532
3533 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
3534 &enable))
3535 return FALSE;
3536
3537 wpa_s = net->wpa_s;
3538 ssid = net->ssid;
3539
3540 if (enable)
3541 wpa_supplicant_enable_network(wpa_s, ssid);
3542 else
3543 wpa_supplicant_disable_network(wpa_s, ssid);
3544
3545 return TRUE;
3546 }
3547
3548
3549 /**
3550 * wpas_dbus_getter_network_properties - Get options for a configured network
3551 * @iter: Pointer to incoming dbus message iter
3552 * @error: Location to store error on failure
3553 * @user_data: Function specific data
3554 * Returns: TRUE on success, FALSE on failure
3555 *
3556 * Getter for "Properties" property of a configured network.
3557 */
3558 dbus_bool_t wpas_dbus_getter_network_properties(DBusMessageIter *iter,
3559 DBusError *error,
3560 void *user_data)
3561 {
3562 struct network_handler_args *net = user_data;
3563 DBusMessageIter variant_iter, dict_iter;
3564 char **iterator;
3565 char **props = wpa_config_get_all(net->ssid, 1);
3566 dbus_bool_t success = FALSE;
3567
3568 if (!props) {
3569 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3570 return FALSE;
3571 }
3572
3573 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a{sv}",
3574 &variant_iter) ||
3575 !wpa_dbus_dict_open_write(&variant_iter, &dict_iter)) {
3576 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3577 goto out;
3578 }
3579
3580 iterator = props;
3581 while (*iterator) {
3582 if (!wpa_dbus_dict_append_string(&dict_iter, *iterator,
3583 *(iterator + 1))) {
3584 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
3585 "no memory");
3586 goto out;
3587 }
3588 iterator += 2;
3589 }
3590
3591
3592 if (!wpa_dbus_dict_close_write(&variant_iter, &dict_iter) ||
3593 !dbus_message_iter_close_container(iter, &variant_iter)) {
3594 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3595 goto out;
3596 }
3597
3598 success = TRUE;
3599
3600 out:
3601 iterator = props;
3602 while (*iterator) {
3603 os_free(*iterator);
3604 iterator++;
3605 }
3606 os_free(props);
3607 return success;
3608 }
3609
3610
3611 /**
3612 * wpas_dbus_setter_network_properties - Set options for a configured network
3613 * @iter: Pointer to incoming dbus message iter
3614 * @error: Location to store error on failure
3615 * @user_data: Function specific data
3616 * Returns: TRUE on success, FALSE on failure
3617 *
3618 * Setter for "Properties" property of a configured network.
3619 */
3620 dbus_bool_t wpas_dbus_setter_network_properties(DBusMessageIter *iter,
3621 DBusError *error,
3622 void *user_data)
3623 {
3624 struct network_handler_args *net = user_data;
3625 struct wpa_ssid *ssid = net->ssid;
3626 DBusMessageIter variant_iter;
3627
3628 dbus_message_iter_recurse(iter, &variant_iter);
3629 return set_network_properties(net->wpa_s, ssid, &variant_iter, error);
3630 }
3631
3632
3633 #ifdef CONFIG_AP
3634
3635 DBusMessage * wpas_dbus_handler_subscribe_preq(
3636 DBusMessage *message, struct wpa_supplicant *wpa_s)
3637 {
3638 struct wpas_dbus_priv *priv = wpa_s->global->dbus;
3639 char *name;
3640
3641 if (wpa_s->preq_notify_peer != NULL) {
3642 if (os_strcmp(dbus_message_get_sender(message),
3643 wpa_s->preq_notify_peer) == 0)
3644 return NULL;
3645
3646 return dbus_message_new_error(message,
3647 WPAS_DBUS_ERROR_SUBSCRIPTION_IN_USE,
3648 "Another application is already subscribed");
3649 }
3650
3651 name = os_strdup(dbus_message_get_sender(message));
3652 if (!name)
3653 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
3654 "out of memory");
3655
3656 wpa_s->preq_notify_peer = name;
3657
3658 /* Subscribe to clean up if application closes socket */
3659 wpas_dbus_subscribe_noc(priv);
3660
3661 /*
3662 * Double-check it's still alive to make sure that we didn't
3663 * miss the NameOwnerChanged signal, e.g. while strdup'ing.
3664 */
3665 if (!dbus_bus_name_has_owner(priv->con, name, NULL)) {
3666 /*
3667 * Application no longer exists, clean up.
3668 * The return value is irrelevant now.
3669 *
3670 * Need to check if the NameOwnerChanged handling
3671 * already cleaned up because we have processed
3672 * DBus messages while checking if the name still
3673 * has an owner.
3674 */
3675 if (!wpa_s->preq_notify_peer)
3676 return NULL;
3677 os_free(wpa_s->preq_notify_peer);
3678 wpa_s->preq_notify_peer = NULL;
3679 wpas_dbus_unsubscribe_noc(priv);
3680 }
3681
3682 return NULL;
3683 }
3684
3685
3686 DBusMessage * wpas_dbus_handler_unsubscribe_preq(
3687 DBusMessage *message, struct wpa_supplicant *wpa_s)
3688 {
3689 struct wpas_dbus_priv *priv = wpa_s->global->dbus;
3690
3691 if (!wpa_s->preq_notify_peer)
3692 return dbus_message_new_error(message,
3693 WPAS_DBUS_ERROR_NO_SUBSCRIPTION,
3694 "Not subscribed");
3695
3696 if (os_strcmp(wpa_s->preq_notify_peer,
3697 dbus_message_get_sender(message)))
3698 return dbus_message_new_error(message,
3699 WPAS_DBUS_ERROR_SUBSCRIPTION_EPERM,
3700 "Can't unsubscribe others");
3701
3702 os_free(wpa_s->preq_notify_peer);
3703 wpa_s->preq_notify_peer = NULL;
3704 wpas_dbus_unsubscribe_noc(priv);
3705 return NULL;
3706 }
3707
3708
3709 void wpas_dbus_signal_preq(struct wpa_supplicant *wpa_s,
3710 const u8 *addr, const u8 *dst, const u8 *bssid,
3711 const u8 *ie, size_t ie_len, u32 ssi_signal)
3712 {
3713 DBusMessage *msg;
3714 DBusMessageIter iter, dict_iter;
3715 struct wpas_dbus_priv *priv = wpa_s->global->dbus;
3716
3717 /* Do nothing if the control interface is not turned on */
3718 if (priv == NULL)
3719 return;
3720
3721 if (wpa_s->preq_notify_peer == NULL)
3722 return;
3723
3724 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
3725 WPAS_DBUS_NEW_IFACE_INTERFACE,
3726 "ProbeRequest");
3727 if (msg == NULL)
3728 return;
3729
3730 dbus_message_set_destination(msg, wpa_s->preq_notify_peer);
3731
3732 dbus_message_iter_init_append(msg, &iter);
3733
3734 if (!wpa_dbus_dict_open_write(&iter, &dict_iter))
3735 goto fail;
3736 if (addr && !wpa_dbus_dict_append_byte_array(&dict_iter, "addr",
3737 (const char *) addr,
3738 ETH_ALEN))
3739 goto fail;
3740 if (dst && !wpa_dbus_dict_append_byte_array(&dict_iter, "dst",
3741 (const char *) dst,
3742 ETH_ALEN))
3743 goto fail;
3744 if (bssid && !wpa_dbus_dict_append_byte_array(&dict_iter, "bssid",
3745 (const char *) bssid,
3746 ETH_ALEN))
3747 goto fail;
3748 if (ie && ie_len && !wpa_dbus_dict_append_byte_array(&dict_iter, "ies",
3749 (const char *) ie,
3750 ie_len))
3751 goto fail;
3752 if (ssi_signal && !wpa_dbus_dict_append_int32(&dict_iter, "signal",
3753 ssi_signal))
3754 goto fail;
3755 if (!wpa_dbus_dict_close_write(&iter, &dict_iter))
3756 goto fail;
3757
3758 dbus_connection_send(priv->con, msg, NULL);
3759 goto out;
3760 fail:
3761 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
3762 out:
3763 dbus_message_unref(msg);
3764 }
3765
3766 #endif /* CONFIG_AP */