1 /*
2 * WPA Supplicant / dbus-based control interface
3 * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
4 * Copyright (c) 2009-2010, Witold Sowa <witold.sowa@gmail.com>
5 * Copyright (c) 2009-2015, Jouni Malinen <j@w1.fi>
6 *
7 * This software may be distributed under the terms of the BSD license.
8 * See README for more details.
9 */
10
11 #include "includes.h"
12
13 #include "common.h"
14 #include "common/ieee802_11_defs.h"
15 #include "eap_peer/eap_methods.h"
16 #include "eapol_supp/eapol_supp_sm.h"
17 #include "rsn_supp/wpa.h"
18 #include "ap/hostapd.h"
19 #include "ap/sta_info.h"
20 #include "ap/ap_drv_ops.h"
21 #include "../config.h"
22 #include "../wpa_supplicant_i.h"
23 #include "../driver_i.h"
24 #include "../notify.h"
25 #include "../bss.h"
26 #include "../scan.h"
27 #include "../autoscan.h"
28 #include "../ap.h"
29 #include "dbus_new_helpers.h"
30 #include "dbus_new.h"
31 #include "dbus_new_handlers.h"
32 #include "dbus_dict_helpers.h"
33 #include "dbus_common_i.h"
34 #include "drivers/driver.h"
35 #ifdef CONFIG_MESH
36 #include "ap/hostapd.h"
37 #include "ap/sta_info.h"
38 #endif /* CONFIG_MESH */
39
40 static const char * const debug_strings[] = {
41 "excessive", "msgdump", "debug", "info", "warning", "error", NULL
42 };
43
44
45 /**
46 * wpas_dbus_error_unknown_error - Return a new UnknownError error message
47 * @message: Pointer to incoming dbus message this error refers to
48 * @arg: Optional string appended to error message
49 * Returns: a dbus error message
50 *
51 * Convenience function to create and return an UnknownError
52 */
wpas_dbus_error_unknown_error(DBusMessage * message,const char * arg)53 DBusMessage * wpas_dbus_error_unknown_error(DBusMessage *message,
54 const char *arg)
55 {
56 return dbus_message_new_error(message, WPAS_DBUS_ERROR_UNKNOWN_ERROR,
57 arg);
58 }
59
60
61 /**
62 * wpas_dbus_error_iface_unknown - Return a new invalid interface error message
63 * @message: Pointer to incoming dbus message this error refers to
64 * Returns: A dbus error message
65 *
66 * Convenience function to create and return an invalid interface error
67 */
wpas_dbus_error_iface_unknown(DBusMessage * message)68 static DBusMessage * wpas_dbus_error_iface_unknown(DBusMessage *message)
69 {
70 return dbus_message_new_error(
71 message, WPAS_DBUS_ERROR_IFACE_UNKNOWN,
72 "wpa_supplicant knows nothing about this interface.");
73 }
74
75
76 /**
77 * wpas_dbus_error_network_unknown - Return a new NetworkUnknown error message
78 * @message: Pointer to incoming dbus message this error refers to
79 * Returns: a dbus error message
80 *
81 * Convenience function to create and return an invalid network error
82 */
wpas_dbus_error_network_unknown(DBusMessage * message)83 static DBusMessage * wpas_dbus_error_network_unknown(DBusMessage *message)
84 {
85 return dbus_message_new_error(
86 message, WPAS_DBUS_ERROR_NETWORK_UNKNOWN,
87 "There is no such a network in this interface.");
88 }
89
90
91 /**
92 * wpas_dbus_error_invalid_args - Return a new InvalidArgs error message
93 * @message: Pointer to incoming dbus message this error refers to
94 * Returns: a dbus error message
95 *
96 * Convenience function to create and return an invalid options error
97 */
wpas_dbus_error_invalid_args(DBusMessage * message,const char * arg)98 DBusMessage * wpas_dbus_error_invalid_args(DBusMessage *message,
99 const char *arg)
100 {
101 DBusMessage *reply;
102
103 reply = dbus_message_new_error(
104 message, WPAS_DBUS_ERROR_INVALID_ARGS,
105 "Did not receive correct message arguments.");
106 if (arg != NULL)
107 dbus_message_append_args(reply, DBUS_TYPE_STRING, &arg,
108 DBUS_TYPE_INVALID);
109
110 return reply;
111 }
112
113
114 /**
115 * wpas_dbus_error_scan_error - Return a new ScanError error message
116 * @message: Pointer to incoming dbus message this error refers to
117 * @error: Optional string to be used as the error message
118 * Returns: a dbus error message
119 *
120 * Convenience function to create and return a scan error
121 */
wpas_dbus_error_scan_error(DBusMessage * message,const char * error)122 static DBusMessage * wpas_dbus_error_scan_error(DBusMessage *message,
123 const char *error)
124 {
125 return dbus_message_new_error(message,
126 WPAS_DBUS_ERROR_IFACE_SCAN_ERROR,
127 error);
128 }
129
130
wpas_dbus_error_no_memory(DBusMessage * message)131 DBusMessage * wpas_dbus_error_no_memory(DBusMessage *message)
132 {
133 wpa_printf(MSG_DEBUG, "dbus: Failed to allocate memory");
134 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, NULL);
135 }
136
137
138 static const char * const dont_quote[] = {
139 "key_mgmt", "proto", "pairwise", "auth_alg", "group", "eap",
140 "bssid", "scan_freq", "freq_list", "scan_ssid", "bssid_hint",
141 "bssid_ignore", "bssid_accept", /* deprecated aliases */
142 "bssid_blacklist", "bssid_whitelist",
143 "group_mgmt",
144 "ignore_broadcast_ssid",
145 #ifdef CONFIG_MESH
146 "mesh_basic_rates",
147 #endif /* CONFIG_MESH */
148 #ifdef CONFIG_P2P
149 "go_p2p_dev_addr", "p2p_client_list", "psk_list",
150 #endif /* CONFIG_P2P */
151 NULL
152 };
153
should_quote_opt(const char * key)154 static dbus_bool_t should_quote_opt(const char *key)
155 {
156 int i = 0;
157
158 while (dont_quote[i] != NULL) {
159 if (os_strcmp(key, dont_quote[i]) == 0)
160 return FALSE;
161 i++;
162 }
163 return TRUE;
164 }
165
166 /**
167 * get_iface_by_dbus_path - Get a new network interface
168 * @global: Pointer to global data from wpa_supplicant_init()
169 * @path: Pointer to a dbus object path representing an interface
170 * Returns: Pointer to the interface or %NULL if not found
171 */
get_iface_by_dbus_path(struct wpa_global * global,const char * path)172 static struct wpa_supplicant * get_iface_by_dbus_path(
173 struct wpa_global *global, const char *path)
174 {
175 struct wpa_supplicant *wpa_s;
176
177 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
178 if (wpa_s->dbus_new_path &&
179 os_strcmp(wpa_s->dbus_new_path, path) == 0)
180 return wpa_s;
181 }
182 return NULL;
183 }
184
185
186 /**
187 * set_network_properties - Set properties of a configured network
188 * @wpa_s: wpa_supplicant structure for a network interface
189 * @ssid: wpa_ssid structure for a configured network
190 * @iter: DBus message iterator containing dictionary of network
191 * properties to set.
192 * @error: On failure, an error describing the failure
193 * Returns: TRUE if the request succeeds, FALSE if it failed
194 *
195 * Sets network configuration with parameters given id DBus dictionary
196 */
set_network_properties(struct wpa_supplicant * wpa_s,struct wpa_ssid * ssid,DBusMessageIter * iter,DBusError * error)197 dbus_bool_t set_network_properties(struct wpa_supplicant *wpa_s,
198 struct wpa_ssid *ssid,
199 DBusMessageIter *iter,
200 DBusError *error)
201 {
202 struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
203 DBusMessageIter iter_dict;
204 char *value = NULL;
205
206 if (!wpa_dbus_dict_open_read(iter, &iter_dict, error))
207 return FALSE;
208
209 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
210 size_t size = 50;
211 int ret;
212
213 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
214 goto error;
215
216 value = NULL;
217 if (entry.type == DBUS_TYPE_ARRAY &&
218 entry.array_type == DBUS_TYPE_BYTE) {
219 if (entry.array_len <= 0)
220 goto error;
221
222 size = entry.array_len * 2 + 1;
223 value = os_zalloc(size);
224 if (value == NULL)
225 goto error;
226
227 ret = wpa_snprintf_hex(value, size,
228 (u8 *) entry.bytearray_value,
229 entry.array_len);
230 if (ret <= 0)
231 goto error;
232 } else if (entry.type == DBUS_TYPE_STRING) {
233 if (should_quote_opt(entry.key)) {
234 size = os_strlen(entry.str_value);
235
236 size += 3;
237 value = os_zalloc(size);
238 if (value == NULL)
239 goto error;
240
241 ret = os_snprintf(value, size, "\"%s\"",
242 entry.str_value);
243 if (os_snprintf_error(size, ret))
244 goto error;
245 } else {
246 value = os_strdup(entry.str_value);
247 if (value == NULL)
248 goto error;
249 }
250 } else if (entry.type == DBUS_TYPE_UINT32) {
251 value = os_zalloc(size);
252 if (value == NULL)
253 goto error;
254
255 ret = os_snprintf(value, size, "%u",
256 entry.uint32_value);
257 if (os_snprintf_error(size, ret))
258 goto error;
259 } else if (entry.type == DBUS_TYPE_INT32) {
260 value = os_zalloc(size);
261 if (value == NULL)
262 goto error;
263
264 ret = os_snprintf(value, size, "%d",
265 entry.int32_value);
266 if (os_snprintf_error(size, ret))
267 goto error;
268 } else
269 goto error;
270
271 ret = wpa_config_set(ssid, entry.key, value, 0);
272 if (ret < 0)
273 goto error;
274 if (ret == 1)
275 goto skip_update;
276
277 #ifdef CONFIG_BGSCAN
278 if (os_strcmp(entry.key, "bgscan") == 0) {
279 /*
280 * Reset the bgscan parameters for the current network
281 * and continue. There's no need to flush caches for
282 * bgscan parameter changes.
283 */
284 if (wpa_s->current_ssid == ssid &&
285 wpa_s->wpa_state == WPA_COMPLETED)
286 wpa_supplicant_reset_bgscan(wpa_s);
287 os_free(value);
288 value = NULL;
289 wpa_dbus_dict_entry_clear(&entry);
290 continue;
291 }
292 #endif /* CONFIG_BGSCAN */
293
294 if (os_strcmp(entry.key, "bssid") != 0 &&
295 os_strcmp(entry.key, "priority") != 0)
296 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
297
298 if (wpa_s->current_ssid == ssid ||
299 wpa_s->current_ssid == NULL) {
300 /*
301 * Invalidate the EAP session cache if anything in the
302 * current or previously used configuration changes.
303 */
304 eapol_sm_invalidate_cached_session(wpa_s->eapol);
305 }
306
307 if ((os_strcmp(entry.key, "psk") == 0 &&
308 value[0] == '"' && ssid->ssid_len) ||
309 (os_strcmp(entry.key, "ssid") == 0 && ssid->passphrase))
310 wpa_config_update_psk(ssid);
311 else if (os_strcmp(entry.key, "priority") == 0)
312 wpa_config_update_prio_list(wpa_s->conf);
313
314 skip_update:
315 os_free(value);
316 value = NULL;
317 wpa_dbus_dict_entry_clear(&entry);
318 }
319
320 return TRUE;
321
322 error:
323 os_free(value);
324 wpa_dbus_dict_entry_clear(&entry);
325 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
326 "invalid message format");
327 return FALSE;
328 }
329
330
331 /**
332 * wpas_dbus_simple_property_getter - Get basic type property
333 * @iter: Message iter to use when appending arguments
334 * @type: DBus type of property (must be basic type)
335 * @val: pointer to place holding property value
336 * @error: On failure an error describing the failure
337 * Returns: TRUE if the request was successful, FALSE if it failed
338 *
339 * Generic getter for basic type properties. Type is required to be basic.
340 */
wpas_dbus_simple_property_getter(DBusMessageIter * iter,const int type,const void * val,DBusError * error)341 dbus_bool_t wpas_dbus_simple_property_getter(DBusMessageIter *iter,
342 const int type,
343 const void *val,
344 DBusError *error)
345 {
346 DBusMessageIter variant_iter;
347
348 if (!dbus_type_is_basic(type)) {
349 dbus_set_error(error, DBUS_ERROR_FAILED,
350 "%s: given type is not basic", __func__);
351 return FALSE;
352 }
353
354 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
355 wpa_dbus_type_as_string(type),
356 &variant_iter) ||
357 !dbus_message_iter_append_basic(&variant_iter, type, val) ||
358 !dbus_message_iter_close_container(iter, &variant_iter)) {
359 dbus_set_error(error, DBUS_ERROR_FAILED,
360 "%s: error constructing reply", __func__);
361 return FALSE;
362 }
363
364 return TRUE;
365 }
366
367
368 /**
369 * wpas_dbus_simple_property_setter - Set basic type property
370 * @message: Pointer to incoming dbus message
371 * @type: DBus type of property (must be basic type)
372 * @val: pointer to place where value being set will be stored
373 * Returns: TRUE if the request was successful, FALSE if it failed
374 *
375 * Generic setter for basic type properties. Type is required to be basic.
376 */
wpas_dbus_simple_property_setter(DBusMessageIter * iter,DBusError * error,const int type,void * val)377 dbus_bool_t wpas_dbus_simple_property_setter(DBusMessageIter *iter,
378 DBusError *error,
379 const int type, void *val)
380 {
381 DBusMessageIter variant_iter;
382
383 if (!dbus_type_is_basic(type)) {
384 dbus_set_error(error, DBUS_ERROR_FAILED,
385 "%s: given type is not basic", __func__);
386 return FALSE;
387 }
388
389 /* Look at the new value */
390 dbus_message_iter_recurse(iter, &variant_iter);
391 if (dbus_message_iter_get_arg_type(&variant_iter) != type) {
392 dbus_set_error_const(error, DBUS_ERROR_FAILED,
393 "wrong property type");
394 return FALSE;
395 }
396 dbus_message_iter_get_basic(&variant_iter, val);
397
398 return TRUE;
399 }
400
401
402 /**
403 * wpas_dbus_simple_array_property_getter - Get array type property
404 * @iter: Pointer to incoming dbus message iterator
405 * @type: DBus type of property array elements (must be basic type)
406 * @array: pointer to array of elements to put into response message
407 * @array_len: length of above array
408 * @error: a pointer to an error to fill on failure
409 * Returns: TRUE if the request succeeded, FALSE if it failed
410 *
411 * Generic getter for array type properties. Array elements type is
412 * required to be basic.
413 */
wpas_dbus_simple_array_property_getter(DBusMessageIter * iter,const int type,const void * array,size_t array_len,DBusError * error)414 dbus_bool_t wpas_dbus_simple_array_property_getter(DBusMessageIter *iter,
415 const int type,
416 const void *array,
417 size_t array_len,
418 DBusError *error)
419 {
420 DBusMessageIter variant_iter, array_iter;
421 char type_str[] = "a?"; /* ? will be replaced with subtype letter; */
422 const char *sub_type_str;
423 size_t element_size, i;
424
425 if (!dbus_type_is_basic(type)) {
426 dbus_set_error(error, DBUS_ERROR_FAILED,
427 "%s: given type is not basic", __func__);
428 return FALSE;
429 }
430
431 sub_type_str = wpa_dbus_type_as_string(type);
432 type_str[1] = sub_type_str[0];
433
434 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
435 type_str, &variant_iter) ||
436 !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
437 sub_type_str, &array_iter)) {
438 dbus_set_error(error, DBUS_ERROR_FAILED,
439 "%s: failed to construct message", __func__);
440 return FALSE;
441 }
442
443 switch (type) {
444 case DBUS_TYPE_BYTE:
445 case DBUS_TYPE_BOOLEAN:
446 element_size = 1;
447 break;
448 case DBUS_TYPE_INT16:
449 case DBUS_TYPE_UINT16:
450 element_size = sizeof(uint16_t);
451 break;
452 case DBUS_TYPE_INT32:
453 case DBUS_TYPE_UINT32:
454 element_size = sizeof(uint32_t);
455 break;
456 case DBUS_TYPE_INT64:
457 case DBUS_TYPE_UINT64:
458 element_size = sizeof(uint64_t);
459 break;
460 case DBUS_TYPE_DOUBLE:
461 element_size = sizeof(double);
462 break;
463 case DBUS_TYPE_STRING:
464 case DBUS_TYPE_OBJECT_PATH:
465 element_size = sizeof(char *);
466 break;
467 default:
468 dbus_set_error(error, DBUS_ERROR_FAILED,
469 "%s: unknown element type %d", __func__, type);
470 return FALSE;
471 }
472
473 for (i = 0; i < array_len; i++) {
474 if (!dbus_message_iter_append_basic(&array_iter, type,
475 (const char *) array +
476 i * element_size)) {
477 dbus_set_error(error, DBUS_ERROR_FAILED,
478 "%s: failed to construct message 2.5",
479 __func__);
480 return FALSE;
481 }
482 }
483
484 if (!dbus_message_iter_close_container(&variant_iter, &array_iter) ||
485 !dbus_message_iter_close_container(iter, &variant_iter)) {
486 dbus_set_error(error, DBUS_ERROR_FAILED,
487 "%s: failed to construct message 3", __func__);
488 return FALSE;
489 }
490
491 return TRUE;
492 }
493
494
495 /**
496 * wpas_dbus_simple_array_array_property_getter - Get array array type property
497 * @iter: Pointer to incoming dbus message iterator
498 * @type: DBus type of property array elements (must be basic type)
499 * @array: pointer to array of elements to put into response message
500 * @array_len: length of above array
501 * @error: a pointer to an error to fill on failure
502 * Returns: TRUE if the request succeeded, FALSE if it failed
503 *
504 * Generic getter for array type properties. Array elements type is
505 * required to be basic.
506 */
wpas_dbus_simple_array_array_property_getter(DBusMessageIter * iter,const int type,struct wpabuf ** array,size_t array_len,DBusError * error)507 dbus_bool_t wpas_dbus_simple_array_array_property_getter(DBusMessageIter *iter,
508 const int type,
509 struct wpabuf **array,
510 size_t array_len,
511 DBusError *error)
512 {
513 DBusMessageIter variant_iter, array_iter;
514 char type_str[] = "aa?";
515 char inner_type_str[] = "a?";
516 const char *sub_type_str;
517 size_t i;
518
519 if (!dbus_type_is_basic(type)) {
520 dbus_set_error(error, DBUS_ERROR_FAILED,
521 "%s: given type is not basic", __func__);
522 return FALSE;
523 }
524
525 sub_type_str = wpa_dbus_type_as_string(type);
526 type_str[2] = sub_type_str[0];
527 inner_type_str[1] = sub_type_str[0];
528
529 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
530 type_str, &variant_iter) ||
531 !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
532 inner_type_str, &array_iter)) {
533 dbus_set_error(error, DBUS_ERROR_FAILED,
534 "%s: failed to construct message", __func__);
535 return FALSE;
536 }
537
538 for (i = 0; i < array_len && array[i]; i++) {
539 wpa_dbus_dict_bin_array_add_element(&array_iter,
540 wpabuf_head(array[i]),
541 wpabuf_len(array[i]));
542
543 }
544
545 if (!dbus_message_iter_close_container(&variant_iter, &array_iter) ||
546 !dbus_message_iter_close_container(iter, &variant_iter)) {
547 dbus_set_error(error, DBUS_ERROR_FAILED,
548 "%s: failed to close message", __func__);
549 return FALSE;
550 }
551
552 return TRUE;
553 }
554
555
556 /**
557 * wpas_dbus_string_property_getter - Get string type property
558 * @iter: Message iter to use when appending arguments
559 * @val: Pointer to place holding property value, can be %NULL
560 * @error: On failure an error describing the failure
561 * Returns: TRUE if the request was successful, FALSE if it failed
562 *
563 * Generic getter for string type properties. %NULL is converted to an empty
564 * string.
565 */
wpas_dbus_string_property_getter(DBusMessageIter * iter,const void * val,DBusError * error)566 dbus_bool_t wpas_dbus_string_property_getter(DBusMessageIter *iter,
567 const void *val,
568 DBusError *error)
569 {
570 if (!val)
571 val = "";
572 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
573 &val, error);
574 }
575
576
577 /**
578 * wpas_dbus_handler_create_interface - Request registration of a network iface
579 * @message: Pointer to incoming dbus message
580 * @global: %wpa_supplicant global data structure
581 * Returns: The object path of the new interface object,
582 * or a dbus error message with more information
583 *
584 * Handler function for "CreateInterface" method call. Handles requests
585 * by dbus clients to register a network interface that wpa_supplicant
586 * will manage.
587 */
wpas_dbus_handler_create_interface(DBusMessage * message,struct wpa_global * global)588 DBusMessage * wpas_dbus_handler_create_interface(DBusMessage *message,
589 struct wpa_global *global)
590 {
591 DBusMessageIter iter_dict;
592 DBusMessage *reply = NULL;
593 DBusMessageIter iter;
594 struct wpa_dbus_dict_entry entry;
595 char *driver = NULL;
596 char *ifname = NULL;
597 char *confname = NULL;
598 char *bridge_ifname = NULL;
599
600 dbus_message_iter_init(message, &iter);
601
602 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
603 goto error;
604 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
605 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
606 goto error;
607 if (os_strcmp(entry.key, "Driver") == 0 &&
608 entry.type == DBUS_TYPE_STRING) {
609 os_free(driver);
610 driver = os_strdup(entry.str_value);
611 wpa_dbus_dict_entry_clear(&entry);
612 if (driver == NULL)
613 goto oom;
614 } else if (os_strcmp(entry.key, "Ifname") == 0 &&
615 entry.type == DBUS_TYPE_STRING) {
616 os_free(ifname);
617 ifname = os_strdup(entry.str_value);
618 wpa_dbus_dict_entry_clear(&entry);
619 if (ifname == NULL)
620 goto oom;
621 } else if (os_strcmp(entry.key, "ConfigFile") == 0 &&
622 entry.type == DBUS_TYPE_STRING) {
623 os_free(confname);
624 confname = os_strdup(entry.str_value);
625 wpa_dbus_dict_entry_clear(&entry);
626 if (confname == NULL)
627 goto oom;
628 } else if (os_strcmp(entry.key, "BridgeIfname") == 0 &&
629 entry.type == DBUS_TYPE_STRING) {
630 os_free(bridge_ifname);
631 bridge_ifname = os_strdup(entry.str_value);
632 wpa_dbus_dict_entry_clear(&entry);
633 if (bridge_ifname == NULL)
634 goto oom;
635 } else {
636 wpa_dbus_dict_entry_clear(&entry);
637 goto error;
638 }
639 }
640
641 if (ifname == NULL)
642 goto error; /* Required Ifname argument missing */
643
644 /*
645 * Try to get the wpa_supplicant record for this iface, return
646 * an error if we already control it.
647 */
648 if (wpa_supplicant_get_iface(global, ifname) != NULL) {
649 reply = dbus_message_new_error(
650 message, WPAS_DBUS_ERROR_IFACE_EXISTS,
651 "wpa_supplicant already controls this interface.");
652 } else {
653 struct wpa_supplicant *wpa_s;
654 struct wpa_interface iface;
655
656 os_memset(&iface, 0, sizeof(iface));
657 iface.driver = driver;
658 iface.ifname = ifname;
659 iface.confname = confname;
660 iface.bridge_ifname = bridge_ifname;
661 /* Otherwise, have wpa_supplicant attach to it. */
662 wpa_s = wpa_supplicant_add_iface(global, &iface, NULL);
663 if (wpa_s && wpa_s->dbus_new_path) {
664 const char *path = wpa_s->dbus_new_path;
665
666 reply = dbus_message_new_method_return(message);
667 dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH,
668 &path, DBUS_TYPE_INVALID);
669 } else {
670 reply = wpas_dbus_error_unknown_error(
671 message,
672 "wpa_supplicant couldn't grab this interface.");
673 }
674 }
675
676 out:
677 os_free(driver);
678 os_free(ifname);
679 os_free(confname);
680 os_free(bridge_ifname);
681 return reply;
682
683 error:
684 reply = wpas_dbus_error_invalid_args(message, NULL);
685 goto out;
686 oom:
687 reply = wpas_dbus_error_no_memory(message);
688 goto out;
689 }
690
691
692 /**
693 * wpas_dbus_handler_remove_interface - Request deregistration of an interface
694 * @message: Pointer to incoming dbus message
695 * @global: wpa_supplicant global data structure
696 * Returns: a dbus message containing a UINT32 indicating success (1) or
697 * failure (0), or returns a dbus error message with more information
698 *
699 * Handler function for "removeInterface" method call. Handles requests
700 * by dbus clients to deregister a network interface that wpa_supplicant
701 * currently manages.
702 */
wpas_dbus_handler_remove_interface(DBusMessage * message,struct wpa_global * global)703 DBusMessage * wpas_dbus_handler_remove_interface(DBusMessage *message,
704 struct wpa_global *global)
705 {
706 struct wpa_supplicant *wpa_s;
707 char *path;
708 DBusMessage *reply = NULL;
709
710 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path,
711 DBUS_TYPE_INVALID);
712
713 wpa_s = get_iface_by_dbus_path(global, path);
714 if (wpa_s == NULL)
715 reply = wpas_dbus_error_iface_unknown(message);
716 else if (wpa_supplicant_remove_iface(global, wpa_s, 0)) {
717 reply = wpas_dbus_error_unknown_error(
718 message,
719 "wpa_supplicant couldn't remove this interface.");
720 }
721
722 return reply;
723 }
724
725
726 /**
727 * wpas_dbus_handler_get_interface - Get the object path for an interface name
728 * @message: Pointer to incoming dbus message
729 * @global: %wpa_supplicant global data structure
730 * Returns: The object path of the interface object,
731 * or a dbus error message with more information
732 *
733 * Handler function for "getInterface" method call.
734 */
wpas_dbus_handler_get_interface(DBusMessage * message,struct wpa_global * global)735 DBusMessage * wpas_dbus_handler_get_interface(DBusMessage *message,
736 struct wpa_global *global)
737 {
738 DBusMessage *reply = NULL;
739 const char *ifname;
740 const char *path;
741 struct wpa_supplicant *wpa_s;
742
743 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &ifname,
744 DBUS_TYPE_INVALID);
745
746 wpa_s = wpa_supplicant_get_iface(global, ifname);
747 if (wpa_s == NULL || wpa_s->dbus_new_path == NULL)
748 return wpas_dbus_error_iface_unknown(message);
749
750 path = wpa_s->dbus_new_path;
751 reply = dbus_message_new_method_return(message);
752 if (reply == NULL)
753 return wpas_dbus_error_no_memory(message);
754 if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
755 DBUS_TYPE_INVALID)) {
756 dbus_message_unref(reply);
757 return wpas_dbus_error_no_memory(message);
758 }
759
760 return reply;
761 }
762
763
764 /**
765 * wpas_dbus_getter_debug_level - Get debug level
766 * @iter: Pointer to incoming dbus message iter
767 * @error: Location to store error on failure
768 * @user_data: Function specific data
769 * Returns: TRUE on success, FALSE on failure
770 *
771 * Getter for "DebugLevel" property.
772 */
wpas_dbus_getter_debug_level(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)773 dbus_bool_t wpas_dbus_getter_debug_level(
774 const struct wpa_dbus_property_desc *property_desc,
775 DBusMessageIter *iter, DBusError *error, void *user_data)
776 {
777 const char *str;
778 int idx = wpa_debug_level;
779
780 if (idx < 0)
781 idx = 0;
782 if (idx > 5)
783 idx = 5;
784 str = debug_strings[idx];
785 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
786 &str, error);
787 }
788
789
790 /**
791 * wpas_dbus_getter_debug_timestamp - Get debug timestamp
792 * @iter: Pointer to incoming dbus message iter
793 * @error: Location to store error on failure
794 * @user_data: Function specific data
795 * Returns: TRUE on success, FALSE on failure
796 *
797 * Getter for "DebugTimestamp" property.
798 */
wpas_dbus_getter_debug_timestamp(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)799 dbus_bool_t wpas_dbus_getter_debug_timestamp(
800 const struct wpa_dbus_property_desc *property_desc,
801 DBusMessageIter *iter, DBusError *error, void *user_data)
802 {
803 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
804 &wpa_debug_timestamp, error);
805
806 }
807
808
809 /**
810 * wpas_dbus_getter_debug_show_keys - Get debug show keys
811 * @iter: Pointer to incoming dbus message iter
812 * @error: Location to store error on failure
813 * @user_data: Function specific data
814 * Returns: TRUE on success, FALSE on failure
815 *
816 * Getter for "DebugShowKeys" property.
817 */
wpas_dbus_getter_debug_show_keys(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)818 dbus_bool_t wpas_dbus_getter_debug_show_keys(
819 const struct wpa_dbus_property_desc *property_desc,
820 DBusMessageIter *iter, DBusError *error, void *user_data)
821 {
822 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
823 &wpa_debug_show_keys, error);
824
825 }
826
827 /**
828 * wpas_dbus_setter_debug_level - Set debug level
829 * @iter: Pointer to incoming dbus message iter
830 * @error: Location to store error on failure
831 * @user_data: Function specific data
832 * Returns: TRUE on success, FALSE on failure
833 *
834 * Setter for "DebugLevel" property.
835 */
wpas_dbus_setter_debug_level(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)836 dbus_bool_t wpas_dbus_setter_debug_level(
837 const struct wpa_dbus_property_desc *property_desc,
838 DBusMessageIter *iter, DBusError *error, void *user_data)
839 {
840 struct wpa_global *global = user_data;
841 const char *str = NULL;
842 int i, val = -1;
843
844 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
845 &str))
846 return FALSE;
847
848 for (i = 0; debug_strings[i]; i++)
849 if (os_strcmp(debug_strings[i], str) == 0) {
850 val = i;
851 break;
852 }
853
854 if (val < 0 ||
855 wpa_supplicant_set_debug_params(global, val, wpa_debug_timestamp,
856 wpa_debug_show_keys)) {
857 dbus_set_error_const(error, DBUS_ERROR_FAILED,
858 "wrong debug level value");
859 return FALSE;
860 }
861
862 return TRUE;
863 }
864
865
866 /**
867 * wpas_dbus_setter_debug_timestamp - Set debug timestamp
868 * @iter: Pointer to incoming dbus message iter
869 * @error: Location to store error on failure
870 * @user_data: Function specific data
871 * Returns: TRUE on success, FALSE on failure
872 *
873 * Setter for "DebugTimestamp" property.
874 */
wpas_dbus_setter_debug_timestamp(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)875 dbus_bool_t wpas_dbus_setter_debug_timestamp(
876 const struct wpa_dbus_property_desc *property_desc,
877 DBusMessageIter *iter, DBusError *error, void *user_data)
878 {
879 struct wpa_global *global = user_data;
880 dbus_bool_t val;
881
882 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
883 &val))
884 return FALSE;
885
886 wpa_supplicant_set_debug_params(global, wpa_debug_level, val ? 1 : 0,
887 wpa_debug_show_keys);
888 return TRUE;
889 }
890
891
892 /**
893 * wpas_dbus_setter_debug_show_keys - Set debug show keys
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 * Setter for "DebugShowKeys" property.
900 */
wpas_dbus_setter_debug_show_keys(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)901 dbus_bool_t wpas_dbus_setter_debug_show_keys(
902 const struct wpa_dbus_property_desc *property_desc,
903 DBusMessageIter *iter, DBusError *error, void *user_data)
904 {
905 struct wpa_global *global = user_data;
906 dbus_bool_t val;
907
908 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
909 &val))
910 return FALSE;
911
912 wpa_supplicant_set_debug_params(global, wpa_debug_level,
913 wpa_debug_timestamp,
914 val ? 1 : 0);
915 return TRUE;
916 }
917
918
919 /**
920 * wpas_dbus_getter_interfaces - Request registered interfaces list
921 * @iter: Pointer to incoming dbus message iter
922 * @error: Location to store error on failure
923 * @user_data: Function specific data
924 * Returns: TRUE on success, FALSE on failure
925 *
926 * Getter for "Interfaces" property. Handles requests
927 * by dbus clients to return list of registered interfaces objects
928 * paths
929 */
wpas_dbus_getter_interfaces(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)930 dbus_bool_t wpas_dbus_getter_interfaces(
931 const struct wpa_dbus_property_desc *property_desc,
932 DBusMessageIter *iter, DBusError *error, void *user_data)
933 {
934 struct wpa_global *global = user_data;
935 struct wpa_supplicant *wpa_s;
936 const char **paths;
937 unsigned int i = 0, num = 0;
938 dbus_bool_t success;
939
940 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
941 if (wpa_s->dbus_new_path)
942 num++;
943 }
944
945 paths = os_calloc(num, sizeof(char *));
946 if (!paths) {
947 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
948 return FALSE;
949 }
950
951 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
952 if (wpa_s->dbus_new_path)
953 paths[i++] = wpa_s->dbus_new_path;
954 }
955
956 success = wpas_dbus_simple_array_property_getter(iter,
957 DBUS_TYPE_OBJECT_PATH,
958 paths, num, error);
959
960 os_free(paths);
961 return success;
962 }
963
964
965 /**
966 * wpas_dbus_getter_eap_methods - Request supported EAP methods list
967 * @iter: Pointer to incoming dbus message iter
968 * @error: Location to store error on failure
969 * @user_data: Function specific data
970 * Returns: TRUE on success, FALSE on failure
971 *
972 * Getter for "EapMethods" property. Handles requests
973 * by dbus clients to return list of strings with supported EAP methods
974 */
wpas_dbus_getter_eap_methods(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)975 dbus_bool_t wpas_dbus_getter_eap_methods(
976 const struct wpa_dbus_property_desc *property_desc,
977 DBusMessageIter *iter, DBusError *error, void *user_data)
978 {
979 char **eap_methods;
980 size_t num_items = 0;
981 dbus_bool_t success;
982
983 eap_methods = eap_get_names_as_string_array(&num_items);
984 if (!eap_methods) {
985 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
986 return FALSE;
987 }
988
989 success = wpas_dbus_simple_array_property_getter(iter,
990 DBUS_TYPE_STRING,
991 eap_methods,
992 num_items, error);
993
994 while (num_items)
995 os_free(eap_methods[--num_items]);
996 os_free(eap_methods);
997 return success;
998 }
999
1000
1001 /**
1002 * wpas_dbus_getter_global_capabilities - Request supported global capabilities
1003 * @iter: Pointer to incoming dbus message iter
1004 * @error: Location to store error on failure
1005 * @user_data: Function specific data
1006 * Returns: TRUE on success, FALSE on failure
1007 *
1008 * Getter for "Capabilities" property. Handles requests by dbus clients to
1009 * return a list of strings with supported capabilities like AP, RSN IBSS,
1010 * and P2P that are determined at compile time.
1011 */
wpas_dbus_getter_global_capabilities(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)1012 dbus_bool_t wpas_dbus_getter_global_capabilities(
1013 const struct wpa_dbus_property_desc *property_desc,
1014 DBusMessageIter *iter, DBusError *error, void *user_data)
1015 {
1016 const char *capabilities[13];
1017 size_t num_items = 0;
1018 struct wpa_global *global = user_data;
1019 struct wpa_supplicant *wpa_s;
1020 #ifdef CONFIG_FILS
1021 int fils_supported = 0, fils_sk_pfs_supported = 0;
1022 #endif /* CONFIG_FILS */
1023 int ext_key_id_supported = 0;
1024
1025 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
1026 #ifdef CONFIG_FILS
1027 if (wpa_is_fils_supported(wpa_s))
1028 fils_supported = 1;
1029 if (wpa_is_fils_sk_pfs_supported(wpa_s))
1030 fils_sk_pfs_supported = 1;
1031 #endif /* CONFIG_FILS */
1032 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_EXTENDED_KEY_ID)
1033 ext_key_id_supported = 1;
1034 }
1035
1036 #ifdef CONFIG_AP
1037 capabilities[num_items++] = "ap";
1038 #endif /* CONFIG_AP */
1039 #ifdef CONFIG_IBSS_RSN
1040 capabilities[num_items++] = "ibss-rsn";
1041 #endif /* CONFIG_IBSS_RSN */
1042 #ifdef CONFIG_P2P
1043 capabilities[num_items++] = "p2p";
1044 #endif /* CONFIG_P2P */
1045 #ifdef CONFIG_INTERWORKING
1046 capabilities[num_items++] = "interworking";
1047 #endif /* CONFIG_INTERWORKING */
1048 capabilities[num_items++] = "pmf";
1049 #ifdef CONFIG_MESH
1050 capabilities[num_items++] = "mesh";
1051 #endif /* CONFIG_MESH */
1052 #ifdef CONFIG_FILS
1053 if (fils_supported)
1054 capabilities[num_items++] = "fils";
1055 if (fils_sk_pfs_supported)
1056 capabilities[num_items++] = "fils_sk_pfs";
1057 #endif /* CONFIG_FILS */
1058 #ifdef CONFIG_IEEE80211R
1059 capabilities[num_items++] = "ft";
1060 #endif /* CONFIG_IEEE80211R */
1061 #ifdef CONFIG_SHA384
1062 capabilities[num_items++] = "sha384";
1063 #endif /* CONFIG_SHA384 */
1064 #ifdef CONFIG_OWE
1065 capabilities[num_items++] = "owe";
1066 #endif /* CONFIG_OWE */
1067 #ifdef CONFIG_SUITEB192
1068 capabilities[num_items++] = "suiteb192";
1069 #endif /* CONFIG_SUITEB192 */
1070 if (ext_key_id_supported)
1071 capabilities[num_items++] = "extended_key_id";
1072
1073 return wpas_dbus_simple_array_property_getter(iter,
1074 DBUS_TYPE_STRING,
1075 capabilities,
1076 num_items, error);
1077 }
1078
1079
wpas_dbus_get_scan_type(DBusMessage * message,DBusMessageIter * var,char ** type,DBusMessage ** reply)1080 static int wpas_dbus_get_scan_type(DBusMessage *message, DBusMessageIter *var,
1081 char **type, DBusMessage **reply)
1082 {
1083 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_STRING) {
1084 wpa_printf(MSG_DEBUG, "%s[dbus]: Type must be a string",
1085 __func__);
1086 *reply = wpas_dbus_error_invalid_args(
1087 message, "Wrong Type value type. String required");
1088 return -1;
1089 }
1090 dbus_message_iter_get_basic(var, type);
1091 return 0;
1092 }
1093
1094
wpas_dbus_get_scan_ssids(DBusMessage * message,DBusMessageIter * var,struct wpa_driver_scan_params * params,DBusMessage ** reply)1095 static int wpas_dbus_get_scan_ssids(DBusMessage *message, DBusMessageIter *var,
1096 struct wpa_driver_scan_params *params,
1097 DBusMessage **reply)
1098 {
1099 struct wpa_driver_scan_ssid *ssids = params->ssids;
1100 size_t ssids_num = 0;
1101 u8 *ssid;
1102 DBusMessageIter array_iter, sub_array_iter;
1103 char *val;
1104 int len;
1105
1106 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
1107 wpa_printf(MSG_DEBUG,
1108 "%s[dbus]: ssids must be an array of arrays of bytes",
1109 __func__);
1110 *reply = wpas_dbus_error_invalid_args(
1111 message,
1112 "Wrong SSIDs value type. Array of arrays of bytes required");
1113 return -1;
1114 }
1115
1116 dbus_message_iter_recurse(var, &array_iter);
1117
1118 if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY ||
1119 dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_BYTE) {
1120 wpa_printf(MSG_DEBUG,
1121 "%s[dbus]: ssids must be an array of arrays of bytes",
1122 __func__);
1123 *reply = wpas_dbus_error_invalid_args(
1124 message,
1125 "Wrong SSIDs value type. Array of arrays of bytes required");
1126 return -1;
1127 }
1128
1129 while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_ARRAY) {
1130 if (ssids_num >= WPAS_MAX_SCAN_SSIDS) {
1131 wpa_printf(MSG_DEBUG,
1132 "%s[dbus]: Too many ssids specified on scan dbus call",
1133 __func__);
1134 *reply = wpas_dbus_error_invalid_args(
1135 message,
1136 "Too many ssids specified. Specify at most four");
1137 return -1;
1138 }
1139
1140 dbus_message_iter_recurse(&array_iter, &sub_array_iter);
1141
1142 dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len);
1143
1144 if (len > SSID_MAX_LEN) {
1145 wpa_printf(MSG_DEBUG,
1146 "%s[dbus]: SSID too long (len=%d max_len=%d)",
1147 __func__, len, SSID_MAX_LEN);
1148 *reply = wpas_dbus_error_invalid_args(
1149 message, "Invalid SSID: too long");
1150 return -1;
1151 }
1152
1153 if (len != 0) {
1154 ssid = os_memdup(val, len);
1155 if (ssid == NULL) {
1156 *reply = wpas_dbus_error_no_memory(message);
1157 return -1;
1158 }
1159 } else {
1160 /* Allow zero-length SSIDs */
1161 ssid = NULL;
1162 }
1163
1164 ssids[ssids_num].ssid = ssid;
1165 ssids[ssids_num].ssid_len = len;
1166
1167 dbus_message_iter_next(&array_iter);
1168 ssids_num++;
1169 }
1170
1171 params->num_ssids = ssids_num;
1172 return 0;
1173 }
1174
1175
wpas_dbus_get_scan_ies(DBusMessage * message,DBusMessageIter * var,struct wpa_driver_scan_params * params,DBusMessage ** reply)1176 static int wpas_dbus_get_scan_ies(DBusMessage *message, DBusMessageIter *var,
1177 struct wpa_driver_scan_params *params,
1178 DBusMessage **reply)
1179 {
1180 u8 *ies = NULL, *nies;
1181 size_t ies_len = 0;
1182 DBusMessageIter array_iter, sub_array_iter;
1183 char *val;
1184 int len;
1185
1186 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
1187 wpa_printf(MSG_DEBUG,
1188 "%s[dbus]: ies must be an array of arrays of bytes",
1189 __func__);
1190 *reply = wpas_dbus_error_invalid_args(
1191 message,
1192 "Wrong IEs value type. Array of arrays of bytes required");
1193 return -1;
1194 }
1195
1196 dbus_message_iter_recurse(var, &array_iter);
1197
1198 if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY ||
1199 dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_BYTE) {
1200 wpa_printf(MSG_DEBUG,
1201 "%s[dbus]: ies must be an array of arrays of bytes",
1202 __func__);
1203 *reply = wpas_dbus_error_invalid_args(
1204 message, "Wrong IEs value type. Array required");
1205 return -1;
1206 }
1207
1208 while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_ARRAY) {
1209 dbus_message_iter_recurse(&array_iter, &sub_array_iter);
1210
1211 dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len);
1212 if (len <= 0) {
1213 dbus_message_iter_next(&array_iter);
1214 continue;
1215 }
1216
1217 nies = os_realloc(ies, ies_len + len);
1218 if (nies == NULL) {
1219 os_free(ies);
1220 *reply = wpas_dbus_error_no_memory(message);
1221 return -1;
1222 }
1223 ies = nies;
1224 os_memcpy(ies + ies_len, val, len);
1225 ies_len += len;
1226
1227 dbus_message_iter_next(&array_iter);
1228 }
1229
1230 params->extra_ies = ies;
1231 params->extra_ies_len = ies_len;
1232 return 0;
1233 }
1234
1235
wpas_dbus_get_scan_channels(DBusMessage * message,DBusMessageIter * var,struct wpa_driver_scan_params * params,DBusMessage ** reply)1236 static int wpas_dbus_get_scan_channels(DBusMessage *message,
1237 DBusMessageIter *var,
1238 struct wpa_driver_scan_params *params,
1239 DBusMessage **reply)
1240 {
1241 DBusMessageIter array_iter, sub_array_iter;
1242 int *freqs = NULL, *nfreqs;
1243 size_t freqs_num = 0;
1244
1245 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
1246 wpa_printf(MSG_DEBUG,
1247 "%s[dbus]: Channels must be an array of structs",
1248 __func__);
1249 *reply = wpas_dbus_error_invalid_args(
1250 message,
1251 "Wrong Channels value type. Array of structs required");
1252 return -1;
1253 }
1254
1255 dbus_message_iter_recurse(var, &array_iter);
1256
1257 if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_STRUCT) {
1258 wpa_printf(MSG_DEBUG,
1259 "%s[dbus]: Channels must be an array of structs",
1260 __func__);
1261 *reply = wpas_dbus_error_invalid_args(
1262 message,
1263 "Wrong Channels value type. Array of structs required");
1264 return -1;
1265 }
1266
1267 while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_STRUCT)
1268 {
1269 int freq, width;
1270
1271 dbus_message_iter_recurse(&array_iter, &sub_array_iter);
1272
1273 if (dbus_message_iter_get_arg_type(&sub_array_iter) !=
1274 DBUS_TYPE_UINT32) {
1275 wpa_printf(MSG_DEBUG,
1276 "%s[dbus]: Channel must by specified by struct of two UINT32s %c",
1277 __func__,
1278 dbus_message_iter_get_arg_type(
1279 &sub_array_iter));
1280 *reply = wpas_dbus_error_invalid_args(
1281 message,
1282 "Wrong Channel struct. Two UINT32s required");
1283 os_free(freqs);
1284 return -1;
1285 }
1286 dbus_message_iter_get_basic(&sub_array_iter, &freq);
1287
1288 if (!dbus_message_iter_next(&sub_array_iter) ||
1289 dbus_message_iter_get_arg_type(&sub_array_iter) !=
1290 DBUS_TYPE_UINT32) {
1291 wpa_printf(MSG_DEBUG,
1292 "%s[dbus]: Channel must by specified by struct of two UINT32s",
1293 __func__);
1294 *reply = wpas_dbus_error_invalid_args(
1295 message,
1296 "Wrong Channel struct. Two UINT32s required");
1297 os_free(freqs);
1298 return -1;
1299 }
1300
1301 dbus_message_iter_get_basic(&sub_array_iter, &width);
1302
1303 #define FREQS_ALLOC_CHUNK 32
1304 if (freqs_num % FREQS_ALLOC_CHUNK == 0) {
1305 nfreqs = os_realloc_array(
1306 freqs, freqs_num + FREQS_ALLOC_CHUNK,
1307 sizeof(int));
1308 if (nfreqs == NULL)
1309 os_free(freqs);
1310 freqs = nfreqs;
1311 }
1312 if (freqs == NULL) {
1313 *reply = wpas_dbus_error_no_memory(message);
1314 return -1;
1315 }
1316
1317 freqs[freqs_num] = freq;
1318
1319 freqs_num++;
1320 dbus_message_iter_next(&array_iter);
1321 }
1322
1323 nfreqs = os_realloc_array(freqs, freqs_num + 1, sizeof(int));
1324 if (nfreqs == NULL)
1325 os_free(freqs);
1326 freqs = nfreqs;
1327 if (freqs == NULL) {
1328 *reply = wpas_dbus_error_no_memory(message);
1329 return -1;
1330 }
1331 freqs[freqs_num] = 0;
1332
1333 params->freqs = freqs;
1334 return 0;
1335 }
1336
1337
wpas_dbus_get_scan_allow_roam(DBusMessage * message,DBusMessageIter * var,dbus_bool_t * allow,DBusMessage ** reply)1338 static int wpas_dbus_get_scan_allow_roam(DBusMessage *message,
1339 DBusMessageIter *var,
1340 dbus_bool_t *allow,
1341 DBusMessage **reply)
1342 {
1343 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_BOOLEAN) {
1344 wpa_printf(MSG_DEBUG, "%s[dbus]: Type must be a boolean",
1345 __func__);
1346 *reply = wpas_dbus_error_invalid_args(
1347 message, "Wrong Type value type. Boolean required");
1348 return -1;
1349 }
1350 dbus_message_iter_get_basic(var, allow);
1351 return 0;
1352 }
1353
1354
1355 /**
1356 * wpas_dbus_handler_scan - Request a wireless scan on an interface
1357 * @message: Pointer to incoming dbus message
1358 * @wpa_s: wpa_supplicant structure for a network interface
1359 * Returns: NULL indicating success or DBus error message on failure
1360 *
1361 * Handler function for "Scan" method call of a network device. Requests
1362 * that wpa_supplicant perform a wireless scan as soon as possible
1363 * on a particular wireless interface.
1364 */
wpas_dbus_handler_scan(DBusMessage * message,struct wpa_supplicant * wpa_s)1365 DBusMessage * wpas_dbus_handler_scan(DBusMessage *message,
1366 struct wpa_supplicant *wpa_s)
1367 {
1368 DBusMessage *reply = NULL;
1369 DBusMessageIter iter, dict_iter, entry_iter, variant_iter;
1370 char *key = NULL, *type = NULL;
1371 struct wpa_driver_scan_params params;
1372 size_t i;
1373 dbus_bool_t allow_roam = 1;
1374
1375 os_memset(¶ms, 0, sizeof(params));
1376
1377 dbus_message_iter_init(message, &iter);
1378
1379 dbus_message_iter_recurse(&iter, &dict_iter);
1380
1381 while (dbus_message_iter_get_arg_type(&dict_iter) ==
1382 DBUS_TYPE_DICT_ENTRY) {
1383 dbus_message_iter_recurse(&dict_iter, &entry_iter);
1384 dbus_message_iter_get_basic(&entry_iter, &key);
1385 dbus_message_iter_next(&entry_iter);
1386 dbus_message_iter_recurse(&entry_iter, &variant_iter);
1387
1388 if (os_strcmp(key, "Type") == 0) {
1389 if (wpas_dbus_get_scan_type(message, &variant_iter,
1390 &type, &reply) < 0)
1391 goto out;
1392 } else if (os_strcmp(key, "SSIDs") == 0) {
1393 if (wpas_dbus_get_scan_ssids(message, &variant_iter,
1394 ¶ms, &reply) < 0)
1395 goto out;
1396 } else if (os_strcmp(key, "IEs") == 0) {
1397 if (wpas_dbus_get_scan_ies(message, &variant_iter,
1398 ¶ms, &reply) < 0)
1399 goto out;
1400 } else if (os_strcmp(key, "Channels") == 0) {
1401 if (wpas_dbus_get_scan_channels(message, &variant_iter,
1402 ¶ms, &reply) < 0)
1403 goto out;
1404 } else if (os_strcmp(key, "AllowRoam") == 0) {
1405 if (wpas_dbus_get_scan_allow_roam(message,
1406 &variant_iter,
1407 &allow_roam,
1408 &reply) < 0)
1409 goto out;
1410 } else {
1411 wpa_printf(MSG_DEBUG, "%s[dbus]: Unknown argument %s",
1412 __func__, key);
1413 reply = wpas_dbus_error_invalid_args(message, key);
1414 goto out;
1415 }
1416
1417 dbus_message_iter_next(&dict_iter);
1418 }
1419
1420 if (!type) {
1421 wpa_printf(MSG_DEBUG, "%s[dbus]: Scan type not specified",
1422 __func__);
1423 reply = wpas_dbus_error_invalid_args(message, key);
1424 goto out;
1425 }
1426
1427 if (os_strcmp(type, "passive") == 0) {
1428 if (params.num_ssids || params.extra_ies_len) {
1429 wpa_printf(MSG_DEBUG,
1430 "%s[dbus]: SSIDs or IEs specified for passive scan.",
1431 __func__);
1432 reply = wpas_dbus_error_invalid_args(
1433 message,
1434 "You can specify only Channels in passive scan");
1435 goto out;
1436 } else {
1437 if (wpa_s->sched_scanning) {
1438 wpa_printf(MSG_DEBUG,
1439 "%s[dbus]: Stop ongoing sched_scan to allow requested scan to proceed",
1440 __func__);
1441 wpa_supplicant_cancel_sched_scan(wpa_s);
1442 }
1443
1444 if (params.freqs && params.freqs[0]) {
1445 wpa_s->last_scan_req = MANUAL_SCAN_REQ;
1446 if (wpa_supplicant_trigger_scan(wpa_s,
1447 ¶ms)) {
1448 reply = wpas_dbus_error_scan_error(
1449 message,
1450 "Scan request rejected");
1451 }
1452 } else {
1453 wpa_s->scan_req = MANUAL_SCAN_REQ;
1454 wpa_supplicant_req_scan(wpa_s, 0, 0);
1455 }
1456 }
1457 } else if (os_strcmp(type, "active") == 0) {
1458 if (!params.num_ssids) {
1459 /* Add wildcard ssid */
1460 params.num_ssids++;
1461 }
1462 #ifdef CONFIG_AUTOSCAN
1463 autoscan_deinit(wpa_s);
1464 #endif /* CONFIG_AUTOSCAN */
1465 if (wpa_s->sched_scanning) {
1466 wpa_printf(MSG_DEBUG,
1467 "%s[dbus]: Stop ongoing sched_scan to allow requested scan to proceed",
1468 __func__);
1469 wpa_supplicant_cancel_sched_scan(wpa_s);
1470 }
1471
1472 wpa_s->last_scan_req = MANUAL_SCAN_REQ;
1473 if (wpa_supplicant_trigger_scan(wpa_s, ¶ms)) {
1474 reply = wpas_dbus_error_scan_error(
1475 message, "Scan request rejected");
1476 }
1477 } else {
1478 wpa_printf(MSG_DEBUG, "%s[dbus]: Unknown scan type: %s",
1479 __func__, type);
1480 reply = wpas_dbus_error_invalid_args(message,
1481 "Wrong scan type");
1482 goto out;
1483 }
1484
1485 if (!allow_roam)
1486 wpa_s->scan_res_handler = scan_only_handler;
1487
1488 out:
1489 for (i = 0; i < WPAS_MAX_SCAN_SSIDS; i++)
1490 os_free((u8 *) params.ssids[i].ssid);
1491 os_free((u8 *) params.extra_ies);
1492 os_free(params.freqs);
1493 return reply;
1494 }
1495
1496
1497 /*
1498 * wpas_dbus_handler_abort_scan - Request an ongoing scan to be aborted
1499 * @message: Pointer to incoming dbus message
1500 * @wpa_s: wpa_supplicant structure for a network interface
1501 * Returns: Abort failed or no scan in progress DBus error message on failure
1502 * or NULL otherwise.
1503 *
1504 * Handler function for "AbortScan" method call of network interface.
1505 */
wpas_dbus_handler_abort_scan(DBusMessage * message,struct wpa_supplicant * wpa_s)1506 DBusMessage * wpas_dbus_handler_abort_scan(DBusMessage *message,
1507 struct wpa_supplicant *wpa_s)
1508 {
1509 if (wpas_abort_ongoing_scan(wpa_s) < 0)
1510 return dbus_message_new_error(
1511 message, WPAS_DBUS_ERROR_IFACE_SCAN_ERROR,
1512 "Abort failed or no scan in progress");
1513
1514 return NULL;
1515 }
1516
1517
1518 /**
1519 * wpas_dbus_handler_signal_poll - Request immediate signal properties
1520 * @message: Pointer to incoming dbus message
1521 * @wpa_s: wpa_supplicant structure for a network interface
1522 * Returns: NULL indicating success or DBus error message on failure
1523 *
1524 * Handler function for "SignalPoll" method call of a network device. Requests
1525 * that wpa_supplicant read signal properties like RSSI, noise, and link
1526 * speed and return them.
1527 */
wpas_dbus_handler_signal_poll(DBusMessage * message,struct wpa_supplicant * wpa_s)1528 DBusMessage * wpas_dbus_handler_signal_poll(DBusMessage *message,
1529 struct wpa_supplicant *wpa_s)
1530 {
1531 struct wpa_signal_info si;
1532 DBusMessage *reply = NULL;
1533 DBusMessageIter iter, iter_dict, variant_iter;
1534 int ret;
1535
1536 ret = wpa_drv_signal_poll(wpa_s, &si);
1537 if (ret) {
1538 return dbus_message_new_error(message, DBUS_ERROR_FAILED,
1539 "Failed to read signal");
1540 }
1541
1542 reply = dbus_message_new_method_return(message);
1543 if (reply == NULL)
1544 goto nomem;
1545
1546 dbus_message_iter_init_append(reply, &iter);
1547
1548 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
1549 "a{sv}", &variant_iter) ||
1550 !wpa_dbus_dict_open_write(&variant_iter, &iter_dict) ||
1551 !wpa_dbus_dict_append_int32(&iter_dict, "rssi",
1552 si.current_signal) ||
1553 !wpa_dbus_dict_append_int32(&iter_dict, "linkspeed",
1554 si.current_txrate / 1000) ||
1555 !wpa_dbus_dict_append_int32(&iter_dict, "noise",
1556 si.current_noise) ||
1557 !wpa_dbus_dict_append_uint32(&iter_dict, "frequency",
1558 si.frequency) ||
1559 (si.chanwidth != CHAN_WIDTH_UNKNOWN &&
1560 !wpa_dbus_dict_append_string(
1561 &iter_dict, "width",
1562 channel_width_to_string(si.chanwidth))) ||
1563 (si.center_frq1 > 0 && si.center_frq2 > 0 &&
1564 (!wpa_dbus_dict_append_int32(&iter_dict, "center-frq1",
1565 si.center_frq1) ||
1566 !wpa_dbus_dict_append_int32(&iter_dict, "center-frq2",
1567 si.center_frq2))) ||
1568 (si.avg_signal &&
1569 !wpa_dbus_dict_append_int32(&iter_dict, "avg-rssi",
1570 si.avg_signal)) ||
1571 !wpa_dbus_dict_close_write(&variant_iter, &iter_dict) ||
1572 !dbus_message_iter_close_container(&iter, &variant_iter))
1573 goto nomem;
1574
1575 return reply;
1576
1577 nomem:
1578 if (reply)
1579 dbus_message_unref(reply);
1580 return wpas_dbus_error_no_memory(message);
1581 }
1582
1583
1584 /*
1585 * wpas_dbus_handler_disconnect - Terminate the current connection
1586 * @message: Pointer to incoming dbus message
1587 * @wpa_s: wpa_supplicant structure for a network interface
1588 * Returns: NotConnected DBus error message if already not connected
1589 * or NULL otherwise.
1590 *
1591 * Handler function for "Disconnect" method call of network interface.
1592 */
wpas_dbus_handler_disconnect(DBusMessage * message,struct wpa_supplicant * wpa_s)1593 DBusMessage * wpas_dbus_handler_disconnect(DBusMessage *message,
1594 struct wpa_supplicant *wpa_s)
1595 {
1596 if (wpa_s->current_ssid != NULL) {
1597 wpas_request_disconnection(wpa_s);
1598 return NULL;
1599 }
1600
1601 return dbus_message_new_error(message, WPAS_DBUS_ERROR_NOT_CONNECTED,
1602 "This interface is not connected");
1603 }
1604
1605
1606 /**
1607 * wpas_dbus_new_iface_add_network - Add a new configured network
1608 * @message: Pointer to incoming dbus message
1609 * @wpa_s: wpa_supplicant structure for a network interface
1610 * Returns: A dbus message containing the object path of the new network
1611 *
1612 * Handler function for "AddNetwork" method call of a network interface.
1613 */
wpas_dbus_handler_add_network(DBusMessage * message,struct wpa_supplicant * wpa_s)1614 DBusMessage * wpas_dbus_handler_add_network(DBusMessage *message,
1615 struct wpa_supplicant *wpa_s)
1616 {
1617 DBusMessage *reply = NULL;
1618 DBusMessageIter iter;
1619 struct wpa_ssid *ssid = NULL;
1620 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf;
1621 DBusError error;
1622
1623 dbus_message_iter_init(message, &iter);
1624
1625 if (wpa_s->dbus_new_path)
1626 ssid = wpa_supplicant_add_network(wpa_s);
1627 if (ssid == NULL) {
1628 wpa_printf(MSG_ERROR, "%s[dbus]: can't add new interface.",
1629 __func__);
1630 reply = wpas_dbus_error_unknown_error(
1631 message,
1632 "wpa_supplicant could not add a network on this interface.");
1633 goto err;
1634 }
1635
1636 dbus_error_init(&error);
1637 if (!set_network_properties(wpa_s, ssid, &iter, &error)) {
1638 wpa_printf(MSG_DEBUG,
1639 "%s[dbus]: control interface couldn't set network properties",
1640 __func__);
1641 reply = wpas_dbus_reply_new_from_error(message, &error,
1642 DBUS_ERROR_INVALID_ARGS,
1643 "Failed to add network");
1644 dbus_error_free(&error);
1645 goto err;
1646 }
1647
1648 /* Construct the object path for this network. */
1649 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
1650 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
1651 wpa_s->dbus_new_path, ssid->id);
1652
1653 reply = dbus_message_new_method_return(message);
1654 if (reply == NULL) {
1655 reply = wpas_dbus_error_no_memory(message);
1656 goto err;
1657 }
1658 if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
1659 DBUS_TYPE_INVALID)) {
1660 dbus_message_unref(reply);
1661 reply = wpas_dbus_error_no_memory(message);
1662 goto err;
1663 }
1664
1665 return reply;
1666
1667 err:
1668 if (ssid) {
1669 wpas_notify_network_removed(wpa_s, ssid);
1670 wpa_config_remove_network(wpa_s->conf, ssid->id);
1671 }
1672 return reply;
1673 }
1674
1675
1676 /**
1677 * wpas_dbus_handler_reassociate - Reassociate
1678 * @message: Pointer to incoming dbus message
1679 * @wpa_s: wpa_supplicant structure for a network interface
1680 * Returns: InterfaceDisabled DBus error message if disabled
1681 * or NULL otherwise.
1682 *
1683 * Handler function for "Reassociate" method call of network interface.
1684 */
wpas_dbus_handler_reassociate(DBusMessage * message,struct wpa_supplicant * wpa_s)1685 DBusMessage * wpas_dbus_handler_reassociate(DBusMessage *message,
1686 struct wpa_supplicant *wpa_s)
1687 {
1688 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED) {
1689 wpas_request_connection(wpa_s);
1690 return NULL;
1691 }
1692
1693 return dbus_message_new_error(message, WPAS_DBUS_ERROR_IFACE_DISABLED,
1694 "This interface is disabled");
1695 }
1696
1697
1698 /**
1699 * wpas_dbus_handler_expect_disconnect - ExpectDisconnect
1700 * @message: Pointer to incoming dbus message
1701 * @global: %wpa_supplicant global data structure
1702 * Returns: NULL
1703 *
1704 * Handler function for notifying system there will be a expected disconnect.
1705 * This will prevent wpa_supplicant from adding the BSSID to the ignore list
1706 * upon next disconnect.
1707 */
wpas_dbus_handler_expect_disconnect(DBusMessage * message,struct wpa_global * global)1708 DBusMessage * wpas_dbus_handler_expect_disconnect(DBusMessage *message,
1709 struct wpa_global *global)
1710 {
1711 struct wpa_supplicant *wpa_s = global->ifaces;
1712
1713 for (; wpa_s; wpa_s = wpa_s->next)
1714 if (wpa_s->wpa_state >= WPA_ASSOCIATED)
1715 wpa_s->own_disconnect_req = 1;
1716 return NULL;
1717 }
1718
1719
1720 /**
1721 * wpas_dbus_handler_reattach - Reattach to current AP
1722 * @message: Pointer to incoming dbus message
1723 * @wpa_s: wpa_supplicant structure for a network interface
1724 * Returns: NotConnected DBus error message if not connected
1725 * or NULL otherwise.
1726 *
1727 * Handler function for "Reattach" method call of network interface.
1728 */
wpas_dbus_handler_reattach(DBusMessage * message,struct wpa_supplicant * wpa_s)1729 DBusMessage * wpas_dbus_handler_reattach(DBusMessage *message,
1730 struct wpa_supplicant *wpa_s)
1731 {
1732 if (wpa_s->current_ssid != NULL) {
1733 wpa_s->reattach = 1;
1734 wpas_request_connection(wpa_s);
1735 return NULL;
1736 }
1737
1738 return dbus_message_new_error(message, WPAS_DBUS_ERROR_NOT_CONNECTED,
1739 "This interface is not connected");
1740 }
1741
1742
1743 /**
1744 * wpas_dbus_handler_reconnect - Reconnect if disconnected
1745 * @message: Pointer to incoming dbus message
1746 * @wpa_s: wpa_supplicant structure for a network interface
1747 * Returns: InterfaceDisabled DBus error message if disabled
1748 * or NULL otherwise.
1749 *
1750 * Handler function for "Reconnect" method call of network interface.
1751 */
wpas_dbus_handler_reconnect(DBusMessage * message,struct wpa_supplicant * wpa_s)1752 DBusMessage * wpas_dbus_handler_reconnect(DBusMessage *message,
1753 struct wpa_supplicant *wpa_s)
1754 {
1755 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
1756 return dbus_message_new_error(message,
1757 WPAS_DBUS_ERROR_IFACE_DISABLED,
1758 "This interface is disabled");
1759 }
1760
1761 if (wpa_s->disconnected)
1762 wpas_request_connection(wpa_s);
1763 return NULL;
1764 }
1765
1766
1767 /**
1768 * wpas_dbus_handler_remove_network - Remove a configured network
1769 * @message: Pointer to incoming dbus message
1770 * @wpa_s: wpa_supplicant structure for a network interface
1771 * Returns: NULL on success or dbus error on failure
1772 *
1773 * Handler function for "RemoveNetwork" method call of a network interface.
1774 */
wpas_dbus_handler_remove_network(DBusMessage * message,struct wpa_supplicant * wpa_s)1775 DBusMessage * wpas_dbus_handler_remove_network(DBusMessage *message,
1776 struct wpa_supplicant *wpa_s)
1777 {
1778 DBusMessage *reply = NULL;
1779 const char *op;
1780 char *iface, *net_id;
1781 int id;
1782 int result;
1783
1784 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
1785 DBUS_TYPE_INVALID);
1786
1787 /* Extract the network ID and ensure the network */
1788 /* is actually a child of this interface */
1789 iface = wpas_dbus_new_decompose_object_path(op,
1790 WPAS_DBUS_NEW_NETWORKS_PART,
1791 &net_id);
1792 if (iface == NULL || net_id == NULL || !wpa_s->dbus_new_path ||
1793 os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
1794 reply = wpas_dbus_error_invalid_args(message, op);
1795 goto out;
1796 }
1797
1798 errno = 0;
1799 id = strtoul(net_id, NULL, 10);
1800 if (errno != 0) {
1801 reply = wpas_dbus_error_invalid_args(message, op);
1802 goto out;
1803 }
1804
1805 result = wpa_supplicant_remove_network(wpa_s, id);
1806 if (result == -1) {
1807 reply = wpas_dbus_error_network_unknown(message);
1808 goto out;
1809 }
1810 if (result == -2) {
1811 wpa_printf(MSG_ERROR,
1812 "%s[dbus]: error occurred when removing network %d",
1813 __func__, id);
1814 reply = wpas_dbus_error_unknown_error(
1815 message,
1816 "error removing the specified network on is interface.");
1817 goto out;
1818 }
1819
1820 out:
1821 os_free(iface);
1822 return reply;
1823 }
1824
1825
1826 /**
1827 * wpas_dbus_handler_remove_all_networks - Remove all configured networks
1828 * @message: Pointer to incoming dbus message
1829 * @wpa_s: wpa_supplicant structure for a network interface
1830 * Returns: NULL on success or dbus error on failure
1831 *
1832 * Handler function for "RemoveAllNetworks" method call of a network interface.
1833 */
wpas_dbus_handler_remove_all_networks(DBusMessage * message,struct wpa_supplicant * wpa_s)1834 DBusMessage * wpas_dbus_handler_remove_all_networks(
1835 DBusMessage *message, struct wpa_supplicant *wpa_s)
1836 {
1837 /* NB: could check for failure and return an error */
1838 wpa_supplicant_remove_all_networks(wpa_s);
1839 return NULL;
1840 }
1841
1842
1843 /**
1844 * wpas_dbus_handler_select_network - Attempt association with a network
1845 * @message: Pointer to incoming dbus message
1846 * @wpa_s: wpa_supplicant structure for a network interface
1847 * Returns: NULL on success or dbus error on failure
1848 *
1849 * Handler function for "SelectNetwork" method call of network interface.
1850 */
wpas_dbus_handler_select_network(DBusMessage * message,struct wpa_supplicant * wpa_s)1851 DBusMessage * wpas_dbus_handler_select_network(DBusMessage *message,
1852 struct wpa_supplicant *wpa_s)
1853 {
1854 DBusMessage *reply = NULL;
1855 const char *op;
1856 char *iface, *net_id;
1857 int id;
1858 struct wpa_ssid *ssid;
1859
1860 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
1861 DBUS_TYPE_INVALID);
1862
1863 /* Extract the network ID and ensure the network */
1864 /* is actually a child of this interface */
1865 iface = wpas_dbus_new_decompose_object_path(op,
1866 WPAS_DBUS_NEW_NETWORKS_PART,
1867 &net_id);
1868 if (iface == NULL || net_id == NULL || !wpa_s->dbus_new_path ||
1869 os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
1870 reply = wpas_dbus_error_invalid_args(message, op);
1871 goto out;
1872 }
1873
1874 errno = 0;
1875 id = strtoul(net_id, NULL, 10);
1876 if (errno != 0) {
1877 reply = wpas_dbus_error_invalid_args(message, op);
1878 goto out;
1879 }
1880
1881 ssid = wpa_config_get_network(wpa_s->conf, id);
1882 if (ssid == NULL) {
1883 reply = wpas_dbus_error_network_unknown(message);
1884 goto out;
1885 }
1886
1887 /* Finally, associate with the network */
1888 wpa_supplicant_select_network(wpa_s, ssid);
1889
1890 out:
1891 os_free(iface);
1892 return reply;
1893 }
1894
1895
1896 /**
1897 * wpas_dbus_handler_network_reply - Reply to a NetworkRequest signal
1898 * @message: Pointer to incoming dbus message
1899 * @wpa_s: wpa_supplicant structure for a network interface
1900 * Returns: NULL on success or dbus error on failure
1901 *
1902 * Handler function for "NetworkReply" method call of network interface.
1903 */
wpas_dbus_handler_network_reply(DBusMessage * message,struct wpa_supplicant * wpa_s)1904 DBusMessage * wpas_dbus_handler_network_reply(DBusMessage *message,
1905 struct wpa_supplicant *wpa_s)
1906 {
1907 #ifdef IEEE8021X_EAPOL
1908 DBusMessage *reply = NULL;
1909 const char *op, *field, *value;
1910 char *iface, *net_id;
1911 int id;
1912 struct wpa_ssid *ssid;
1913
1914 if (!dbus_message_get_args(message, NULL,
1915 DBUS_TYPE_OBJECT_PATH, &op,
1916 DBUS_TYPE_STRING, &field,
1917 DBUS_TYPE_STRING, &value,
1918 DBUS_TYPE_INVALID))
1919 return wpas_dbus_error_invalid_args(message, NULL);
1920
1921 /* Extract the network ID and ensure the network */
1922 /* is actually a child of this interface */
1923 iface = wpas_dbus_new_decompose_object_path(op,
1924 WPAS_DBUS_NEW_NETWORKS_PART,
1925 &net_id);
1926 if (iface == NULL || net_id == NULL || !wpa_s->dbus_new_path ||
1927 os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
1928 reply = wpas_dbus_error_invalid_args(message, op);
1929 goto out;
1930 }
1931
1932 errno = 0;
1933 id = strtoul(net_id, NULL, 10);
1934 if (errno != 0) {
1935 reply = wpas_dbus_error_invalid_args(message, net_id);
1936 goto out;
1937 }
1938
1939 ssid = wpa_config_get_network(wpa_s->conf, id);
1940 if (ssid == NULL) {
1941 reply = wpas_dbus_error_network_unknown(message);
1942 goto out;
1943 }
1944
1945 if (wpa_supplicant_ctrl_iface_ctrl_rsp_handle(wpa_s, ssid,
1946 field, value) < 0)
1947 reply = wpas_dbus_error_invalid_args(message, field);
1948 else {
1949 /* Tell EAP to retry immediately */
1950 eapol_sm_notify_ctrl_response(wpa_s->eapol);
1951 }
1952
1953 out:
1954 os_free(iface);
1955 return reply;
1956 #else /* IEEE8021X_EAPOL */
1957 wpa_printf(MSG_DEBUG, "dbus: 802.1X not included");
1958 return wpas_dbus_error_unknown_error(message, "802.1X not included");
1959 #endif /* IEEE8021X_EAPOL */
1960 }
1961
1962
1963 /**
1964 * wpas_dbus_handler_roam - Initiate a roam to another BSS within the ESS
1965 * @message: Pointer to incoming dbus message
1966 * @wpa_s: wpa_supplicant structure for a network interface
1967 * Returns: NULL on success or dbus error on failure
1968 *
1969 * Handler function for "Roam" method call of network interface.
1970 */
wpas_dbus_handler_roam(DBusMessage * message,struct wpa_supplicant * wpa_s)1971 DBusMessage * wpas_dbus_handler_roam(DBusMessage *message,
1972 struct wpa_supplicant *wpa_s)
1973 {
1974 #ifdef CONFIG_NO_SCAN_PROCESSING
1975 return wpas_dbus_error_unknown_error(message,
1976 "scan processing not included");
1977 #else /* CONFIG_NO_SCAN_PROCESSING */
1978 u8 bssid[ETH_ALEN];
1979 struct wpa_bss *bss;
1980 struct wpa_ssid *ssid = wpa_s->current_ssid;
1981 char *addr;
1982
1983 if (!dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &addr,
1984 DBUS_TYPE_INVALID))
1985 return wpas_dbus_error_invalid_args(message, NULL);
1986
1987 if (hwaddr_aton(addr, bssid))
1988 return wpas_dbus_error_invalid_args(
1989 message, "Invalid hardware address format");
1990
1991 wpa_printf(MSG_DEBUG, "dbus: Roam " MACSTR, MAC2STR(bssid));
1992
1993 if (!ssid)
1994 return dbus_message_new_error(
1995 message, WPAS_DBUS_ERROR_NOT_CONNECTED,
1996 "This interface is not connected");
1997
1998 bss = wpa_bss_get(wpa_s, bssid, ssid->ssid, ssid->ssid_len);
1999 if (!bss) {
2000 wpa_printf(MSG_DEBUG, "dbus: Roam: Target BSS not found");
2001 return wpas_dbus_error_invalid_args(
2002 message, "Target BSS not found");
2003 }
2004
2005 wpa_s->reassociate = 1;
2006 wpa_supplicant_connect(wpa_s, bss, ssid);
2007
2008 return NULL;
2009 #endif /* CONFIG_NO_SCAN_PROCESSING */
2010 }
2011
2012 #ifndef CONFIG_NO_CONFIG_BLOBS
2013
2014 /**
2015 * wpas_dbus_handler_add_blob - Store named binary blob (ie, for certificates)
2016 * @message: Pointer to incoming dbus message
2017 * @wpa_s: %wpa_supplicant data structure
2018 * Returns: A dbus message containing an error on failure or NULL on success
2019 *
2020 * Asks wpa_supplicant to internally store a binary blobs.
2021 */
wpas_dbus_handler_add_blob(DBusMessage * message,struct wpa_supplicant * wpa_s)2022 DBusMessage * wpas_dbus_handler_add_blob(DBusMessage *message,
2023 struct wpa_supplicant *wpa_s)
2024 {
2025 DBusMessage *reply = NULL;
2026 DBusMessageIter iter, array_iter;
2027
2028 char *blob_name;
2029 u8 *blob_data;
2030 int blob_len;
2031 struct wpa_config_blob *blob = NULL;
2032
2033 dbus_message_iter_init(message, &iter);
2034 dbus_message_iter_get_basic(&iter, &blob_name);
2035
2036 if (wpa_config_get_blob(wpa_s->conf, blob_name)) {
2037 return dbus_message_new_error(message,
2038 WPAS_DBUS_ERROR_BLOB_EXISTS,
2039 NULL);
2040 }
2041
2042 dbus_message_iter_next(&iter);
2043 dbus_message_iter_recurse(&iter, &array_iter);
2044
2045 dbus_message_iter_get_fixed_array(&array_iter, &blob_data, &blob_len);
2046
2047 blob = os_zalloc(sizeof(*blob));
2048 if (!blob) {
2049 reply = wpas_dbus_error_no_memory(message);
2050 goto err;
2051 }
2052
2053 blob->data = os_memdup(blob_data, blob_len);
2054 blob->name = os_strdup(blob_name);
2055 if (!blob->data || !blob->name) {
2056 reply = wpas_dbus_error_no_memory(message);
2057 goto err;
2058 }
2059 blob->len = blob_len;
2060
2061 wpa_config_set_blob(wpa_s->conf, blob);
2062 wpas_notify_blob_added(wpa_s, blob->name);
2063
2064 return reply;
2065
2066 err:
2067 if (blob) {
2068 os_free(blob->name);
2069 os_free(blob->data);
2070 os_free(blob);
2071 }
2072 return reply;
2073 }
2074
2075
2076 /**
2077 * wpas_dbus_handler_get_blob - Get named binary blob (ie, for certificates)
2078 * @message: Pointer to incoming dbus message
2079 * @wpa_s: %wpa_supplicant data structure
2080 * Returns: A dbus message containing array of bytes (blob)
2081 *
2082 * Gets one wpa_supplicant's binary blobs.
2083 */
wpas_dbus_handler_get_blob(DBusMessage * message,struct wpa_supplicant * wpa_s)2084 DBusMessage * wpas_dbus_handler_get_blob(DBusMessage *message,
2085 struct wpa_supplicant *wpa_s)
2086 {
2087 DBusMessage *reply = NULL;
2088 DBusMessageIter iter, array_iter;
2089
2090 char *blob_name;
2091 const struct wpa_config_blob *blob;
2092
2093 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &blob_name,
2094 DBUS_TYPE_INVALID);
2095
2096 blob = wpa_config_get_blob(wpa_s->conf, blob_name);
2097 if (!blob) {
2098 return dbus_message_new_error(message,
2099 WPAS_DBUS_ERROR_BLOB_UNKNOWN,
2100 "Blob id not set");
2101 }
2102
2103 reply = dbus_message_new_method_return(message);
2104 if (!reply)
2105 return wpas_dbus_error_no_memory(message);
2106
2107 dbus_message_iter_init_append(reply, &iter);
2108
2109 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
2110 DBUS_TYPE_BYTE_AS_STRING,
2111 &array_iter) ||
2112 !dbus_message_iter_append_fixed_array(&array_iter, DBUS_TYPE_BYTE,
2113 &(blob->data), blob->len) ||
2114 !dbus_message_iter_close_container(&iter, &array_iter)) {
2115 dbus_message_unref(reply);
2116 reply = wpas_dbus_error_no_memory(message);
2117 }
2118
2119 return reply;
2120 }
2121
2122
2123 /**
2124 * wpas_remove_handler_remove_blob - Remove named binary blob
2125 * @message: Pointer to incoming dbus message
2126 * @wpa_s: %wpa_supplicant data structure
2127 * Returns: NULL on success or dbus error
2128 *
2129 * Asks wpa_supplicant to internally remove a binary blobs.
2130 */
wpas_dbus_handler_remove_blob(DBusMessage * message,struct wpa_supplicant * wpa_s)2131 DBusMessage * wpas_dbus_handler_remove_blob(DBusMessage *message,
2132 struct wpa_supplicant *wpa_s)
2133 {
2134 DBusMessage *reply = NULL;
2135 char *blob_name;
2136
2137 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &blob_name,
2138 DBUS_TYPE_INVALID);
2139
2140 if (wpa_config_remove_blob(wpa_s->conf, blob_name)) {
2141 return dbus_message_new_error(message,
2142 WPAS_DBUS_ERROR_BLOB_UNKNOWN,
2143 "Blob id not set");
2144 }
2145 wpas_notify_blob_removed(wpa_s, blob_name);
2146
2147 return reply;
2148
2149 }
2150
2151 #endif /* CONFIG_NO_CONFIG_BLOBS */
2152
2153
2154 /*
2155 * wpas_dbus_handler_flush_bss - Flush the BSS cache
2156 * @message: Pointer to incoming dbus message
2157 * @wpa_s: wpa_supplicant structure for a network interface
2158 * Returns: NULL
2159 *
2160 * Handler function for "FlushBSS" method call of network interface.
2161 */
wpas_dbus_handler_flush_bss(DBusMessage * message,struct wpa_supplicant * wpa_s)2162 DBusMessage * wpas_dbus_handler_flush_bss(DBusMessage *message,
2163 struct wpa_supplicant *wpa_s)
2164 {
2165 dbus_uint32_t age;
2166
2167 dbus_message_get_args(message, NULL, DBUS_TYPE_UINT32, &age,
2168 DBUS_TYPE_INVALID);
2169
2170 if (age == 0)
2171 wpa_bss_flush(wpa_s);
2172 else
2173 wpa_bss_flush_by_age(wpa_s, age);
2174
2175 return NULL;
2176 }
2177
2178
2179 #ifdef CONFIG_AUTOSCAN
2180 /**
2181 * wpas_dbus_handler_autoscan - Set autoscan parameters for the interface
2182 * @message: Pointer to incoming dbus message
2183 * @wpa_s: wpa_supplicant structure for a network interface
2184 * Returns: NULL
2185 *
2186 * Handler function for "AutoScan" method call of network interface.
2187 */
wpas_dbus_handler_autoscan(DBusMessage * message,struct wpa_supplicant * wpa_s)2188 DBusMessage * wpas_dbus_handler_autoscan(DBusMessage *message,
2189 struct wpa_supplicant *wpa_s)
2190 {
2191 DBusMessage *reply = NULL;
2192 enum wpa_states state = wpa_s->wpa_state;
2193 char *arg;
2194
2195 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &arg,
2196 DBUS_TYPE_INVALID);
2197
2198 if (arg != NULL && os_strlen(arg) > 0) {
2199 char *tmp;
2200
2201 tmp = os_strdup(arg);
2202 if (tmp == NULL) {
2203 reply = wpas_dbus_error_no_memory(message);
2204 } else {
2205 os_free(wpa_s->conf->autoscan);
2206 wpa_s->conf->autoscan = tmp;
2207 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
2208 autoscan_init(wpa_s, 1);
2209 else if (state == WPA_SCANNING)
2210 wpa_supplicant_reinit_autoscan(wpa_s);
2211 }
2212 } else if (arg != NULL && os_strlen(arg) == 0) {
2213 os_free(wpa_s->conf->autoscan);
2214 wpa_s->conf->autoscan = NULL;
2215 autoscan_deinit(wpa_s);
2216 } else
2217 reply = dbus_message_new_error(message,
2218 DBUS_ERROR_INVALID_ARGS,
2219 NULL);
2220
2221 return reply;
2222 }
2223 #endif /* CONFIG_AUTOSCAN */
2224
2225
2226 /*
2227 * wpas_dbus_handler_eap_logoff - IEEE 802.1X EAPOL state machine logoff
2228 * @message: Pointer to incoming dbus message
2229 * @wpa_s: wpa_supplicant structure for a network interface
2230 * Returns: NULL
2231 *
2232 * Handler function for "EAPLogoff" method call of network interface.
2233 */
wpas_dbus_handler_eap_logoff(DBusMessage * message,struct wpa_supplicant * wpa_s)2234 DBusMessage * wpas_dbus_handler_eap_logoff(DBusMessage *message,
2235 struct wpa_supplicant *wpa_s)
2236 {
2237 eapol_sm_notify_logoff(wpa_s->eapol, TRUE);
2238 return NULL;
2239 }
2240
2241
2242 /*
2243 * wpas_dbus_handler_eap_logon - IEEE 802.1X EAPOL state machine logon
2244 * @message: Pointer to incoming dbus message
2245 * @wpa_s: wpa_supplicant structure for a network interface
2246 * Returns: NULL
2247 *
2248 * Handler function for "EAPLogin" method call of network interface.
2249 */
wpas_dbus_handler_eap_logon(DBusMessage * message,struct wpa_supplicant * wpa_s)2250 DBusMessage * wpas_dbus_handler_eap_logon(DBusMessage *message,
2251 struct wpa_supplicant *wpa_s)
2252 {
2253 eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
2254 return NULL;
2255 }
2256
2257
2258 #ifdef CONFIG_TDLS
2259
get_peer_hwaddr_helper(DBusMessage * message,const char * func_name,u8 * peer_address,DBusMessage ** error)2260 static int get_peer_hwaddr_helper(DBusMessage *message, const char *func_name,
2261 u8 *peer_address, DBusMessage **error)
2262 {
2263 const char *peer_string;
2264
2265 *error = NULL;
2266
2267 if (!dbus_message_get_args(message, NULL,
2268 DBUS_TYPE_STRING, &peer_string,
2269 DBUS_TYPE_INVALID)) {
2270 *error = wpas_dbus_error_invalid_args(message, NULL);
2271 return -1;
2272 }
2273
2274 if (hwaddr_aton(peer_string, peer_address)) {
2275 wpa_printf(MSG_DEBUG, "%s: invalid address '%s'",
2276 func_name, peer_string);
2277 *error = wpas_dbus_error_invalid_args(
2278 message, "Invalid hardware address format");
2279 return -1;
2280 }
2281
2282 return 0;
2283 }
2284
2285
2286 /*
2287 * wpas_dbus_handler_tdls_discover - Discover TDLS peer
2288 * @message: Pointer to incoming dbus message
2289 * @wpa_s: wpa_supplicant structure for a network interface
2290 * Returns: NULL indicating success or DBus error message on failure
2291 *
2292 * Handler function for "TDLSDiscover" method call of network interface.
2293 */
wpas_dbus_handler_tdls_discover(DBusMessage * message,struct wpa_supplicant * wpa_s)2294 DBusMessage * wpas_dbus_handler_tdls_discover(DBusMessage *message,
2295 struct wpa_supplicant *wpa_s)
2296 {
2297 u8 peer[ETH_ALEN];
2298 DBusMessage *error_reply;
2299 int ret;
2300
2301 if (get_peer_hwaddr_helper(message, __func__, peer, &error_reply) < 0)
2302 return error_reply;
2303
2304 wpa_printf(MSG_DEBUG, "DBUS TDLS_DISCOVER " MACSTR, MAC2STR(peer));
2305
2306 if (wpa_tdls_is_external_setup(wpa_s->wpa))
2307 ret = wpa_tdls_send_discovery_request(wpa_s->wpa, peer);
2308 else
2309 ret = wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer);
2310
2311 if (ret) {
2312 return wpas_dbus_error_unknown_error(
2313 message, "error performing TDLS discovery");
2314 }
2315
2316 return NULL;
2317 }
2318
2319
2320 /*
2321 * wpas_dbus_handler_tdls_setup - Setup TDLS session
2322 * @message: Pointer to incoming dbus message
2323 * @wpa_s: wpa_supplicant structure for a network interface
2324 * Returns: NULL indicating success or DBus error message on failure
2325 *
2326 * Handler function for "TDLSSetup" method call of network interface.
2327 */
wpas_dbus_handler_tdls_setup(DBusMessage * message,struct wpa_supplicant * wpa_s)2328 DBusMessage * wpas_dbus_handler_tdls_setup(DBusMessage *message,
2329 struct wpa_supplicant *wpa_s)
2330 {
2331 u8 peer[ETH_ALEN];
2332 DBusMessage *error_reply;
2333 int ret;
2334
2335 if (get_peer_hwaddr_helper(message, __func__, peer, &error_reply) < 0)
2336 return error_reply;
2337
2338 wpa_printf(MSG_DEBUG, "DBUS TDLS_SETUP " MACSTR, MAC2STR(peer));
2339
2340 wpa_tdls_remove(wpa_s->wpa, peer);
2341 if (wpa_tdls_is_external_setup(wpa_s->wpa))
2342 ret = wpa_tdls_start(wpa_s->wpa, peer);
2343 else
2344 ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
2345
2346 if (ret) {
2347 return wpas_dbus_error_unknown_error(
2348 message, "error performing TDLS setup");
2349 }
2350
2351 return NULL;
2352 }
2353
2354
2355 /*
2356 * wpas_dbus_handler_tdls_status - Return TDLS session status
2357 * @message: Pointer to incoming dbus message
2358 * @wpa_s: wpa_supplicant structure for a network interface
2359 * Returns: A string representing the state of the link to this TDLS peer
2360 *
2361 * Handler function for "TDLSStatus" method call of network interface.
2362 */
wpas_dbus_handler_tdls_status(DBusMessage * message,struct wpa_supplicant * wpa_s)2363 DBusMessage * wpas_dbus_handler_tdls_status(DBusMessage *message,
2364 struct wpa_supplicant *wpa_s)
2365 {
2366 u8 peer[ETH_ALEN];
2367 DBusMessage *reply;
2368 const char *tdls_status;
2369
2370 if (get_peer_hwaddr_helper(message, __func__, peer, &reply) < 0)
2371 return reply;
2372
2373 wpa_printf(MSG_DEBUG, "DBUS TDLS_STATUS " MACSTR, MAC2STR(peer));
2374
2375 tdls_status = wpa_tdls_get_link_status(wpa_s->wpa, peer);
2376
2377 reply = dbus_message_new_method_return(message);
2378 dbus_message_append_args(reply, DBUS_TYPE_STRING,
2379 &tdls_status, DBUS_TYPE_INVALID);
2380 return reply;
2381 }
2382
2383
2384 /*
2385 * wpas_dbus_handler_tdls_teardown - Teardown TDLS session
2386 * @message: Pointer to incoming dbus message
2387 * @wpa_s: wpa_supplicant structure for a network interface
2388 * Returns: NULL indicating success or DBus error message on failure
2389 *
2390 * Handler function for "TDLSTeardown" method call of network interface.
2391 */
wpas_dbus_handler_tdls_teardown(DBusMessage * message,struct wpa_supplicant * wpa_s)2392 DBusMessage * wpas_dbus_handler_tdls_teardown(DBusMessage *message,
2393 struct wpa_supplicant *wpa_s)
2394 {
2395 u8 peer[ETH_ALEN];
2396 DBusMessage *error_reply;
2397 int ret;
2398
2399 if (get_peer_hwaddr_helper(message, __func__, peer, &error_reply) < 0)
2400 return error_reply;
2401
2402 wpa_printf(MSG_DEBUG, "DBUS TDLS_TEARDOWN " MACSTR, MAC2STR(peer));
2403
2404 if (wpa_tdls_is_external_setup(wpa_s->wpa))
2405 ret = wpa_tdls_teardown_link(
2406 wpa_s->wpa, peer,
2407 WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
2408 else
2409 ret = wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
2410
2411 if (ret) {
2412 return wpas_dbus_error_unknown_error(
2413 message, "error performing TDLS teardown");
2414 }
2415
2416 return NULL;
2417 }
2418
2419 /*
2420 * wpas_dbus_handler_tdls_channel_switch - Enable channel switching with TDLS peer
2421 * @message: Pointer to incoming dbus message
2422 * @wpa_s: wpa_supplicant structure for a network interface
2423 * Returns: NULL indicating success or DBus error message on failure
2424 *
2425 * Handler function for "TDLSChannelSwitch" method call of network interface.
2426 */
2427 DBusMessage *
wpas_dbus_handler_tdls_channel_switch(DBusMessage * message,struct wpa_supplicant * wpa_s)2428 wpas_dbus_handler_tdls_channel_switch(DBusMessage *message,
2429 struct wpa_supplicant *wpa_s)
2430 {
2431 DBusMessageIter iter, iter_dict;
2432 struct wpa_dbus_dict_entry entry;
2433 u8 peer[ETH_ALEN];
2434 struct hostapd_freq_params freq_params;
2435 u8 oper_class = 0;
2436 int ret;
2437 int is_peer_present = 0;
2438
2439 if (!wpa_tdls_is_external_setup(wpa_s->wpa)) {
2440 wpa_printf(MSG_INFO,
2441 "tdls_chanswitch: Only supported with external setup");
2442 return wpas_dbus_error_unknown_error(message, "TDLS is not using external setup");
2443 }
2444
2445 os_memset(&freq_params, 0, sizeof(freq_params));
2446
2447 dbus_message_iter_init(message, &iter);
2448
2449 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
2450 return wpas_dbus_error_invalid_args(message, NULL);
2451
2452 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2453 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2454 return wpas_dbus_error_invalid_args(message, NULL);
2455
2456 if (os_strcmp(entry.key, "PeerAddress") == 0 &&
2457 entry.type == DBUS_TYPE_STRING) {
2458 if (hwaddr_aton(entry.str_value, peer)) {
2459 wpa_printf(MSG_DEBUG,
2460 "tdls_chanswitch: Invalid address '%s'",
2461 entry.str_value);
2462 wpa_dbus_dict_entry_clear(&entry);
2463 return wpas_dbus_error_invalid_args(message,
2464 NULL);
2465 }
2466
2467 is_peer_present = 1;
2468 } else if (os_strcmp(entry.key, "OperClass") == 0 &&
2469 entry.type == DBUS_TYPE_BYTE) {
2470 oper_class = entry.byte_value;
2471 } else if (os_strcmp(entry.key, "Frequency") == 0 &&
2472 entry.type == DBUS_TYPE_UINT32) {
2473 freq_params.freq = entry.uint32_value;
2474 } else if (os_strcmp(entry.key, "SecChannelOffset") == 0 &&
2475 entry.type == DBUS_TYPE_UINT32) {
2476 freq_params.sec_channel_offset = entry.uint32_value;
2477 } else if (os_strcmp(entry.key, "CenterFrequency1") == 0 &&
2478 entry.type == DBUS_TYPE_UINT32) {
2479 freq_params.center_freq1 = entry.uint32_value;
2480 } else if (os_strcmp(entry.key, "CenterFrequency2") == 0 &&
2481 entry.type == DBUS_TYPE_UINT32) {
2482 freq_params.center_freq2 = entry.uint32_value;
2483 } else if (os_strcmp(entry.key, "Bandwidth") == 0 &&
2484 entry.type == DBUS_TYPE_UINT32) {
2485 freq_params.bandwidth = entry.uint32_value;
2486 } else if (os_strcmp(entry.key, "HT") == 0 &&
2487 entry.type == DBUS_TYPE_BOOLEAN) {
2488 freq_params.ht_enabled = entry.bool_value;
2489 } else if (os_strcmp(entry.key, "VHT") == 0 &&
2490 entry.type == DBUS_TYPE_BOOLEAN) {
2491 freq_params.vht_enabled = entry.bool_value;
2492 } else {
2493 wpa_dbus_dict_entry_clear(&entry);
2494 return wpas_dbus_error_invalid_args(message, NULL);
2495 }
2496
2497 wpa_dbus_dict_entry_clear(&entry);
2498 }
2499
2500 if (oper_class == 0) {
2501 wpa_printf(MSG_INFO,
2502 "tdls_chanswitch: Invalid op class provided");
2503 return wpas_dbus_error_invalid_args(
2504 message, "Invalid op class provided");
2505 }
2506
2507 if (freq_params.freq == 0) {
2508 wpa_printf(MSG_INFO,
2509 "tdls_chanswitch: Invalid freq provided");
2510 return wpas_dbus_error_invalid_args(message,
2511 "Invalid freq provided");
2512 }
2513
2514 if (is_peer_present == 0) {
2515 wpa_printf(MSG_DEBUG,
2516 "tdls_chanswitch: peer address not provided");
2517 return wpas_dbus_error_invalid_args(
2518 message, "peer address not provided");
2519 }
2520
2521 wpa_printf(MSG_DEBUG, "dbus: TDLS_CHAN_SWITCH " MACSTR
2522 " OP CLASS %d FREQ %d CENTER1 %d CENTER2 %d BW %d SEC_OFFSET %d%s%s",
2523 MAC2STR(peer), oper_class, freq_params.freq,
2524 freq_params.center_freq1, freq_params.center_freq2,
2525 freq_params.bandwidth, freq_params.sec_channel_offset,
2526 freq_params.ht_enabled ? " HT" : "",
2527 freq_params.vht_enabled ? " VHT" : "");
2528
2529 ret = wpa_tdls_enable_chan_switch(wpa_s->wpa, peer, oper_class,
2530 &freq_params);
2531 if (ret)
2532 return wpas_dbus_error_unknown_error(
2533 message, "error processing TDLS channel switch");
2534
2535 return NULL;
2536 }
2537
2538 /*
2539 * wpas_dbus_handler_tdls_cancel_channel_switch - Disable channel switching with TDLS peer
2540 * @message: Pointer to incoming dbus message
2541 * @wpa_s: wpa_supplicant structure for a network interface
2542 * Returns: NULL indicating success or DBus error message on failure
2543 *
2544 * Handler function for "TDLSCancelChannelSwitch" method call of network
2545 * interface.
2546 */
2547 DBusMessage *
wpas_dbus_handler_tdls_cancel_channel_switch(DBusMessage * message,struct wpa_supplicant * wpa_s)2548 wpas_dbus_handler_tdls_cancel_channel_switch(DBusMessage *message,
2549 struct wpa_supplicant *wpa_s)
2550 {
2551 u8 peer[ETH_ALEN];
2552 DBusMessage *error_reply;
2553 int ret;
2554
2555 if (get_peer_hwaddr_helper(message, __func__, peer, &error_reply) < 0)
2556 return error_reply;
2557
2558 wpa_printf(MSG_DEBUG, "dbus: TDLS_CANCEL_CHAN_SWITCH " MACSTR,
2559 MAC2STR(peer));
2560
2561 ret = wpa_tdls_disable_chan_switch(wpa_s->wpa, peer);
2562 if (ret)
2563 return wpas_dbus_error_unknown_error(
2564 message, "error canceling TDLS channel switch");
2565
2566 return NULL;
2567 }
2568
2569 #endif /* CONFIG_TDLS */
2570
2571
2572 #ifndef CONFIG_NO_CONFIG_WRITE
2573 /**
2574 * wpas_dbus_handler_save_config - Save configuration to configuration file
2575 * @message: Pointer to incoming dbus message
2576 * @wpa_s: wpa_supplicant structure for a network interface
2577 * Returns: NULL on Success, Otherwise error message
2578 *
2579 * Handler function for "SaveConfig" method call of network interface.
2580 */
wpas_dbus_handler_save_config(DBusMessage * message,struct wpa_supplicant * wpa_s)2581 DBusMessage * wpas_dbus_handler_save_config(DBusMessage *message,
2582 struct wpa_supplicant *wpa_s)
2583 {
2584 int ret;
2585
2586 if (!wpa_s->conf->update_config) {
2587 return wpas_dbus_error_unknown_error(
2588 message,
2589 "Not allowed to update configuration (update_config=0)");
2590 }
2591
2592 ret = wpa_config_write(wpa_s->confname, wpa_s->conf);
2593 if (ret)
2594 return wpas_dbus_error_unknown_error(
2595 message, "Failed to update configuration");
2596 return NULL;
2597 }
2598 #endif /* CONFIG_NO_CONFIG_WRITE */
2599
2600
2601 /**
2602 * wpas_dbus_handler_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
2603 * @message: Pointer to incoming dbus message
2604 * @wpa_s: %wpa_supplicant data structure
2605 * Returns: A dbus message containing an error on failure or NULL on success
2606 *
2607 * Sets the PKCS #11 engine and module path.
2608 */
wpas_dbus_handler_set_pkcs11_engine_and_module_path(DBusMessage * message,struct wpa_supplicant * wpa_s)2609 DBusMessage * wpas_dbus_handler_set_pkcs11_engine_and_module_path(
2610 DBusMessage *message, struct wpa_supplicant *wpa_s)
2611 {
2612 DBusMessageIter iter;
2613 char *value = NULL;
2614 char *pkcs11_engine_path = NULL;
2615 char *pkcs11_module_path = NULL;
2616
2617 dbus_message_iter_init(message, &iter);
2618 dbus_message_iter_get_basic(&iter, &value);
2619 if (value == NULL) {
2620 return dbus_message_new_error(
2621 message, DBUS_ERROR_INVALID_ARGS,
2622 "Invalid pkcs11_engine_path argument");
2623 }
2624 /* Empty path defaults to NULL */
2625 if (os_strlen(value))
2626 pkcs11_engine_path = value;
2627
2628 dbus_message_iter_next(&iter);
2629 dbus_message_iter_get_basic(&iter, &value);
2630 if (value == NULL) {
2631 os_free(pkcs11_engine_path);
2632 return dbus_message_new_error(
2633 message, DBUS_ERROR_INVALID_ARGS,
2634 "Invalid pkcs11_module_path argument");
2635 }
2636 /* Empty path defaults to NULL */
2637 if (os_strlen(value))
2638 pkcs11_module_path = value;
2639
2640 if (wpas_set_pkcs11_engine_and_module_path(wpa_s, pkcs11_engine_path,
2641 pkcs11_module_path))
2642 return dbus_message_new_error(
2643 message, DBUS_ERROR_FAILED,
2644 "Reinit of the EAPOL state machine with the new PKCS #11 engine and module path failed.");
2645
2646 if (wpa_s->dbus_new_path) {
2647 wpa_dbus_mark_property_changed(
2648 wpa_s->global->dbus, wpa_s->dbus_new_path,
2649 WPAS_DBUS_NEW_IFACE_INTERFACE, "PKCS11EnginePath");
2650 wpa_dbus_mark_property_changed(
2651 wpa_s->global->dbus, wpa_s->dbus_new_path,
2652 WPAS_DBUS_NEW_IFACE_INTERFACE, "PKCS11ModulePath");
2653 }
2654
2655 return NULL;
2656 }
2657
2658
2659 /**
2660 * wpas_dbus_getter_capabilities - Return interface capabilities
2661 * @iter: Pointer to incoming dbus message iter
2662 * @error: Location to store error on failure
2663 * @user_data: Function specific data
2664 * Returns: TRUE on success, FALSE on failure
2665 *
2666 * Getter for "Capabilities" property of an interface.
2667 */
wpas_dbus_getter_capabilities(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)2668 dbus_bool_t wpas_dbus_getter_capabilities(
2669 const struct wpa_dbus_property_desc *property_desc,
2670 DBusMessageIter *iter, DBusError *error, void *user_data)
2671 {
2672 struct wpa_supplicant *wpa_s = user_data;
2673 struct wpa_driver_capa capa;
2674 int res;
2675 DBusMessageIter iter_dict, iter_dict_entry, iter_dict_val, iter_array,
2676 variant_iter;
2677 const char *scans[] = { "active", "passive", "ssid" };
2678
2679 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
2680 "a{sv}", &variant_iter) ||
2681 !wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
2682 goto nomem;
2683
2684 res = wpa_drv_get_capa(wpa_s, &capa);
2685
2686 /***** pairwise cipher */
2687 if (res < 0) {
2688 #ifdef CONFIG_NO_TKIP
2689 const char *args[] = {"ccmp", "none"};
2690 #else /* CONFIG_NO_TKIP */
2691 const char *args[] = {"ccmp", "tkip", "none"};
2692 #endif /* CONFIG_NO_TKIP */
2693
2694 if (!wpa_dbus_dict_append_string_array(
2695 &iter_dict, "Pairwise", args,
2696 ARRAY_SIZE(args)))
2697 goto nomem;
2698 } else {
2699 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Pairwise",
2700 &iter_dict_entry,
2701 &iter_dict_val,
2702 &iter_array) ||
2703 ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP_256) &&
2704 !wpa_dbus_dict_string_array_add_element(
2705 &iter_array, "ccmp-256")) ||
2706 ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP_256) &&
2707 !wpa_dbus_dict_string_array_add_element(
2708 &iter_array, "gcmp-256")) ||
2709 ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) &&
2710 !wpa_dbus_dict_string_array_add_element(
2711 &iter_array, "ccmp")) ||
2712 ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP) &&
2713 !wpa_dbus_dict_string_array_add_element(
2714 &iter_array, "gcmp")) ||
2715 #ifndef CONFIG_NO_TKIP
2716 ((capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) &&
2717 !wpa_dbus_dict_string_array_add_element(
2718 &iter_array, "tkip")) ||
2719 #endif /* CONFIG_NO_TKIP */
2720 ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) &&
2721 !wpa_dbus_dict_string_array_add_element(
2722 &iter_array, "none")) ||
2723 !wpa_dbus_dict_end_string_array(&iter_dict,
2724 &iter_dict_entry,
2725 &iter_dict_val,
2726 &iter_array))
2727 goto nomem;
2728 }
2729
2730 /***** group cipher */
2731 if (res < 0) {
2732 const char *args[] = {
2733 "ccmp",
2734 #ifndef CONFIG_NO_TKIP
2735 "tkip",
2736 #endif /* CONFIG_NO_TKIP */
2737 #ifdef CONFIG_WEP
2738 "wep104", "wep40"
2739 #endif /* CONFIG_WEP */
2740 };
2741
2742 if (!wpa_dbus_dict_append_string_array(
2743 &iter_dict, "Group", args,
2744 ARRAY_SIZE(args)))
2745 goto nomem;
2746 } else {
2747 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Group",
2748 &iter_dict_entry,
2749 &iter_dict_val,
2750 &iter_array) ||
2751 ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP_256) &&
2752 !wpa_dbus_dict_string_array_add_element(
2753 &iter_array, "ccmp-256")) ||
2754 ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP_256) &&
2755 !wpa_dbus_dict_string_array_add_element(
2756 &iter_array, "gcmp-256")) ||
2757 ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) &&
2758 !wpa_dbus_dict_string_array_add_element(
2759 &iter_array, "ccmp")) ||
2760 ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP) &&
2761 !wpa_dbus_dict_string_array_add_element(
2762 &iter_array, "gcmp")) ||
2763 #ifndef CONFIG_NO_TKIP
2764 ((capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) &&
2765 !wpa_dbus_dict_string_array_add_element(
2766 &iter_array, "tkip")) ||
2767 #endif /* CONFIG_NO_TKIP */
2768 #ifdef CONFIG_WEP
2769 ((capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) &&
2770 !wpa_dbus_dict_string_array_add_element(
2771 &iter_array, "wep104")) ||
2772 ((capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) &&
2773 !wpa_dbus_dict_string_array_add_element(
2774 &iter_array, "wep40")) ||
2775 #endif /* CONFIG_WEP */
2776 !wpa_dbus_dict_end_string_array(&iter_dict,
2777 &iter_dict_entry,
2778 &iter_dict_val,
2779 &iter_array))
2780 goto nomem;
2781 }
2782
2783 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "GroupMgmt",
2784 &iter_dict_entry,
2785 &iter_dict_val,
2786 &iter_array) ||
2787 (res == 0 && (capa.enc & WPA_DRIVER_CAPA_ENC_BIP) &&
2788 !wpa_dbus_dict_string_array_add_element(
2789 &iter_array, "aes-128-cmac")) ||
2790 (res == 0 && (capa.enc & WPA_DRIVER_CAPA_ENC_BIP_GMAC_128) &&
2791 !wpa_dbus_dict_string_array_add_element(
2792 &iter_array, "bip-gmac-128")) ||
2793 (res == 0 && (capa.enc & WPA_DRIVER_CAPA_ENC_BIP_GMAC_256) &&
2794 !wpa_dbus_dict_string_array_add_element(
2795 &iter_array, "bip-gmac-256")) ||
2796 (res == 0 && (capa.enc & WPA_DRIVER_CAPA_ENC_BIP_CMAC_256) &&
2797 !wpa_dbus_dict_string_array_add_element(
2798 &iter_array, "bip-cmac-256")) ||
2799 !wpa_dbus_dict_end_string_array(&iter_dict,
2800 &iter_dict_entry,
2801 &iter_dict_val,
2802 &iter_array))
2803 goto nomem;
2804
2805 /***** key management */
2806 if (res < 0) {
2807 const char *args[] = {
2808 "wpa-psk", "wpa-eap", "ieee8021x", "wpa-none",
2809 #ifdef CONFIG_WPS
2810 "wps",
2811 #endif /* CONFIG_WPS */
2812 "none"
2813 };
2814 if (!wpa_dbus_dict_append_string_array(
2815 &iter_dict, "KeyMgmt", args,
2816 ARRAY_SIZE(args)))
2817 goto nomem;
2818 } else {
2819 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "KeyMgmt",
2820 &iter_dict_entry,
2821 &iter_dict_val,
2822 &iter_array) ||
2823 !wpa_dbus_dict_string_array_add_element(&iter_array,
2824 "none") ||
2825 !wpa_dbus_dict_string_array_add_element(&iter_array,
2826 "ieee8021x"))
2827 goto nomem;
2828
2829 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
2830 WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
2831 if (!wpa_dbus_dict_string_array_add_element(
2832 &iter_array, "wpa-eap") ||
2833 ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT) &&
2834 !wpa_dbus_dict_string_array_add_element(
2835 &iter_array, "wpa-ft-eap")))
2836 goto nomem;
2837
2838 /* TODO: Ensure that driver actually supports sha256 encryption. */
2839 if (!wpa_dbus_dict_string_array_add_element(
2840 &iter_array, "wpa-eap-sha256"))
2841 goto nomem;
2842 }
2843
2844 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
2845 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
2846 if (!wpa_dbus_dict_string_array_add_element(
2847 &iter_array, "wpa-psk") ||
2848 ((capa.key_mgmt &
2849 WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK) &&
2850 !wpa_dbus_dict_string_array_add_element(
2851 &iter_array, "wpa-ft-psk")))
2852 goto nomem;
2853
2854 /* TODO: Ensure that driver actually supports sha256 encryption. */
2855 if (!wpa_dbus_dict_string_array_add_element(
2856 &iter_array, "wpa-psk-sha256"))
2857 goto nomem;
2858 }
2859
2860 if ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) &&
2861 !wpa_dbus_dict_string_array_add_element(&iter_array,
2862 "wpa-none"))
2863 goto nomem;
2864
2865
2866 #ifdef CONFIG_WPS
2867 if (!wpa_dbus_dict_string_array_add_element(&iter_array,
2868 "wps"))
2869 goto nomem;
2870 #endif /* CONFIG_WPS */
2871
2872 #ifdef CONFIG_SAE
2873 if ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SAE) &&
2874 !wpa_dbus_dict_string_array_add_element(&iter_array, "sae"))
2875 goto nomem;
2876 #endif /* CONFIG_SAE */
2877
2878 #ifdef CONFIG_OWE
2879 if ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_OWE) &&
2880 !wpa_dbus_dict_string_array_add_element(&iter_array, "owe"))
2881 goto nomem;
2882 #endif /* CONFIG_OWE */
2883
2884 if (!wpa_dbus_dict_end_string_array(&iter_dict,
2885 &iter_dict_entry,
2886 &iter_dict_val,
2887 &iter_array))
2888 goto nomem;
2889 }
2890
2891 /***** WPA protocol */
2892 if (res < 0) {
2893 const char *args[] = { "rsn", "wpa" };
2894
2895 if (!wpa_dbus_dict_append_string_array(
2896 &iter_dict, "Protocol", args,
2897 ARRAY_SIZE(args)))
2898 goto nomem;
2899 } else {
2900 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Protocol",
2901 &iter_dict_entry,
2902 &iter_dict_val,
2903 &iter_array) ||
2904 ((capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
2905 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) &&
2906 !wpa_dbus_dict_string_array_add_element(
2907 &iter_array, "rsn")) ||
2908 ((capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
2909 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) &&
2910 !wpa_dbus_dict_string_array_add_element(
2911 &iter_array, "wpa")) ||
2912 !wpa_dbus_dict_end_string_array(&iter_dict,
2913 &iter_dict_entry,
2914 &iter_dict_val,
2915 &iter_array))
2916 goto nomem;
2917 }
2918
2919 /***** auth alg */
2920 if (res < 0) {
2921 const char *args[] = { "open", "shared", "leap" };
2922
2923 if (!wpa_dbus_dict_append_string_array(
2924 &iter_dict, "AuthAlg", args,
2925 ARRAY_SIZE(args)))
2926 goto nomem;
2927 } else {
2928 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "AuthAlg",
2929 &iter_dict_entry,
2930 &iter_dict_val,
2931 &iter_array))
2932 goto nomem;
2933
2934 if (((capa.auth & WPA_DRIVER_AUTH_OPEN) &&
2935 !wpa_dbus_dict_string_array_add_element(
2936 &iter_array, "open")) ||
2937 ((capa.auth & WPA_DRIVER_AUTH_SHARED) &&
2938 !wpa_dbus_dict_string_array_add_element(
2939 &iter_array, "shared")) ||
2940 ((capa.auth & WPA_DRIVER_AUTH_LEAP) &&
2941 !wpa_dbus_dict_string_array_add_element(
2942 &iter_array, "leap")) ||
2943 !wpa_dbus_dict_end_string_array(&iter_dict,
2944 &iter_dict_entry,
2945 &iter_dict_val,
2946 &iter_array))
2947 goto nomem;
2948 }
2949
2950 /***** Scan */
2951 if (!wpa_dbus_dict_append_string_array(&iter_dict, "Scan", scans,
2952 ARRAY_SIZE(scans)))
2953 goto nomem;
2954
2955 /***** Modes */
2956 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Modes",
2957 &iter_dict_entry,
2958 &iter_dict_val,
2959 &iter_array) ||
2960 !wpa_dbus_dict_string_array_add_element(
2961 &iter_array, "infrastructure") ||
2962 (res >= 0 && (capa.flags & WPA_DRIVER_FLAGS_IBSS) &&
2963 !wpa_dbus_dict_string_array_add_element(
2964 &iter_array, "ad-hoc")) ||
2965 (res >= 0 && (capa.flags & WPA_DRIVER_FLAGS_AP) &&
2966 !wpa_dbus_dict_string_array_add_element(
2967 &iter_array, "ap")) ||
2968 (res >= 0 && (capa.flags & WPA_DRIVER_FLAGS_P2P_CAPABLE) &&
2969 !wpa_s->conf->p2p_disabled &&
2970 !wpa_dbus_dict_string_array_add_element(
2971 &iter_array, "p2p")) ||
2972 #ifdef CONFIG_MESH
2973 (res >= 0 && (capa.flags & WPA_DRIVER_FLAGS_MESH) &&
2974 !wpa_dbus_dict_string_array_add_element(
2975 &iter_array, "mesh")) ||
2976 #endif /* CONFIG_MESH */
2977 !wpa_dbus_dict_end_string_array(&iter_dict,
2978 &iter_dict_entry,
2979 &iter_dict_val,
2980 &iter_array))
2981 goto nomem;
2982 /***** Modes end */
2983
2984 if (res >= 0) {
2985 dbus_int32_t max_scan_ssid = capa.max_scan_ssids;
2986
2987 if (!wpa_dbus_dict_append_int32(&iter_dict, "MaxScanSSID",
2988 max_scan_ssid))
2989 goto nomem;
2990 }
2991
2992 if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict) ||
2993 !dbus_message_iter_close_container(iter, &variant_iter))
2994 goto nomem;
2995
2996 return TRUE;
2997
2998 nomem:
2999 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3000 return FALSE;
3001 }
3002
3003
3004 /**
3005 * wpas_dbus_getter_state - Get interface state
3006 * @iter: Pointer to incoming dbus message iter
3007 * @error: Location to store error on failure
3008 * @user_data: Function specific data
3009 * Returns: TRUE on success, FALSE on failure
3010 *
3011 * Getter for "State" property.
3012 */
wpas_dbus_getter_state(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3013 dbus_bool_t wpas_dbus_getter_state(
3014 const struct wpa_dbus_property_desc *property_desc,
3015 DBusMessageIter *iter, DBusError *error, void *user_data)
3016 {
3017 struct wpa_supplicant *wpa_s = user_data;
3018 const char *str_state;
3019 char *state_ls, *tmp;
3020 dbus_bool_t success = FALSE;
3021
3022 str_state = wpa_supplicant_state_txt(wpa_s->wpa_state);
3023
3024 /* make state string lowercase to fit new DBus API convention
3025 */
3026 state_ls = tmp = os_strdup(str_state);
3027 if (!tmp) {
3028 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3029 return FALSE;
3030 }
3031 while (*tmp) {
3032 *tmp = tolower(*tmp);
3033 tmp++;
3034 }
3035
3036 success = wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3037 &state_ls, error);
3038
3039 os_free(state_ls);
3040
3041 return success;
3042 }
3043
3044
3045 /**
3046 * wpas_dbus_new_iface_get_scanning - Get interface scanning state
3047 * @iter: Pointer to incoming dbus message iter
3048 * @error: Location to store error on failure
3049 * @user_data: Function specific data
3050 * Returns: TRUE on success, FALSE on failure
3051 *
3052 * Getter for "scanning" property.
3053 */
wpas_dbus_getter_scanning(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3054 dbus_bool_t wpas_dbus_getter_scanning(
3055 const struct wpa_dbus_property_desc *property_desc,
3056 DBusMessageIter *iter, DBusError *error, void *user_data)
3057 {
3058 struct wpa_supplicant *wpa_s = user_data;
3059 dbus_bool_t scanning = wpa_s->scanning ? TRUE : FALSE;
3060
3061 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
3062 &scanning, error);
3063 }
3064
3065
3066 /**
3067 * wpas_dbus_getter_ap_scan - Control roaming mode
3068 * @iter: Pointer to incoming dbus message iter
3069 * @error: Location to store error on failure
3070 * @user_data: Function specific data
3071 * Returns: TRUE on success, FALSE on failure
3072 *
3073 * Getter function for "ApScan" property.
3074 */
wpas_dbus_getter_ap_scan(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3075 dbus_bool_t wpas_dbus_getter_ap_scan(
3076 const struct wpa_dbus_property_desc *property_desc,
3077 DBusMessageIter *iter, DBusError *error, void *user_data)
3078 {
3079 struct wpa_supplicant *wpa_s = user_data;
3080 dbus_uint32_t ap_scan = wpa_s->conf->ap_scan;
3081
3082 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
3083 &ap_scan, error);
3084 }
3085
3086
3087 /**
3088 * wpas_dbus_setter_ap_scan - Control roaming mode
3089 * @iter: Pointer to incoming dbus message iter
3090 * @error: Location to store error on failure
3091 * @user_data: Function specific data
3092 * Returns: TRUE on success, FALSE on failure
3093 *
3094 * Setter function for "ApScan" property.
3095 */
wpas_dbus_setter_ap_scan(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3096 dbus_bool_t wpas_dbus_setter_ap_scan(
3097 const struct wpa_dbus_property_desc *property_desc,
3098 DBusMessageIter *iter, DBusError *error, void *user_data)
3099 {
3100 struct wpa_supplicant *wpa_s = user_data;
3101 dbus_uint32_t ap_scan;
3102
3103 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
3104 &ap_scan))
3105 return FALSE;
3106
3107 if (wpa_supplicant_set_ap_scan(wpa_s, ap_scan)) {
3108 dbus_set_error_const(error, DBUS_ERROR_FAILED,
3109 "ap_scan must be 0, 1, or 2");
3110 return FALSE;
3111 }
3112 return TRUE;
3113 }
3114
3115
3116 /**
3117 * wpas_dbus_getter_fast_reauth - Control fast
3118 * reauthentication (TLS session resumption)
3119 * @iter: Pointer to incoming dbus message iter
3120 * @error: Location to store error on failure
3121 * @user_data: Function specific data
3122 * Returns: TRUE on success, FALSE on failure
3123 *
3124 * Getter function for "FastReauth" property.
3125 */
wpas_dbus_getter_fast_reauth(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3126 dbus_bool_t wpas_dbus_getter_fast_reauth(
3127 const struct wpa_dbus_property_desc *property_desc,
3128 DBusMessageIter *iter, DBusError *error, void *user_data)
3129 {
3130 struct wpa_supplicant *wpa_s = user_data;
3131 dbus_bool_t fast_reauth = wpa_s->conf->fast_reauth ? TRUE : FALSE;
3132
3133 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
3134 &fast_reauth, error);
3135 }
3136
3137
3138 /**
3139 * wpas_dbus_setter_fast_reauth - Control fast
3140 * reauthentication (TLS session resumption)
3141 * @iter: Pointer to incoming dbus message iter
3142 * @error: Location to store error on failure
3143 * @user_data: Function specific data
3144 * Returns: TRUE on success, FALSE on failure
3145 *
3146 * Setter function for "FastReauth" property.
3147 */
wpas_dbus_setter_fast_reauth(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3148 dbus_bool_t wpas_dbus_setter_fast_reauth(
3149 const struct wpa_dbus_property_desc *property_desc,
3150 DBusMessageIter *iter, DBusError *error, void *user_data)
3151 {
3152 struct wpa_supplicant *wpa_s = user_data;
3153 dbus_bool_t fast_reauth;
3154
3155 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
3156 &fast_reauth))
3157 return FALSE;
3158
3159 wpa_s->conf->fast_reauth = fast_reauth;
3160 return TRUE;
3161 }
3162
3163
3164 /**
3165 * wpas_dbus_getter_disconnect_reason - Get most recent reason for disconnect
3166 * @iter: Pointer to incoming dbus message iter
3167 * @error: Location to store error on failure
3168 * @user_data: Function specific data
3169 * Returns: TRUE on success, FALSE on failure
3170 *
3171 * Getter for "DisconnectReason" property. The reason is negative if it is
3172 * locally generated.
3173 */
wpas_dbus_getter_disconnect_reason(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3174 dbus_bool_t wpas_dbus_getter_disconnect_reason(
3175 const struct wpa_dbus_property_desc *property_desc,
3176 DBusMessageIter *iter, DBusError *error, void *user_data)
3177 {
3178 struct wpa_supplicant *wpa_s = user_data;
3179 dbus_int32_t reason = wpa_s->disconnect_reason;
3180
3181 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
3182 &reason, error);
3183 }
3184
3185
3186 /**
3187 * wpas_dbus_getter_auth_status_code - Get most recent auth status code
3188 * @iter: Pointer to incoming dbus message iter
3189 * @error: Location to store error on failure
3190 * @user_data: Function specific data
3191 * Returns: TRUE on success, FALSE on failure
3192 *
3193 * Getter for "AuthStatusCode" property.
3194 */
wpas_dbus_getter_auth_status_code(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3195 dbus_bool_t wpas_dbus_getter_auth_status_code(
3196 const struct wpa_dbus_property_desc *property_desc,
3197 DBusMessageIter *iter, DBusError *error, void *user_data)
3198 {
3199 struct wpa_supplicant *wpa_s = user_data;
3200 dbus_int32_t reason = wpa_s->auth_status_code;
3201
3202 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
3203 &reason, error);
3204 }
3205
3206
3207 /**
3208 * wpas_dbus_getter_assoc_status_code - Get most recent failed assoc status code
3209 * @iter: Pointer to incoming dbus message iter
3210 * @error: Location to store error on failure
3211 * @user_data: Function specific data
3212 * Returns: TRUE on success, FALSE on failure
3213 *
3214 * Getter for "AssocStatusCode" property.
3215 */
wpas_dbus_getter_assoc_status_code(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3216 dbus_bool_t wpas_dbus_getter_assoc_status_code(
3217 const struct wpa_dbus_property_desc *property_desc,
3218 DBusMessageIter *iter, DBusError *error, void *user_data)
3219 {
3220 struct wpa_supplicant *wpa_s = user_data;
3221 dbus_int32_t status_code = wpa_s->assoc_status_code;
3222
3223 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
3224 &status_code, error);
3225 }
3226
3227
3228 /**
3229 * wpas_dbus_getter_roam_time - Get most recent roam time
3230 * @iter: Pointer to incoming dbus message iter
3231 * @error: Location to store error on failure
3232 * @user_data: Function specific data
3233 * Returns: TRUE on success, FALSE on failure
3234 *
3235 * Getter for "RoamTime" property.
3236 */
wpas_dbus_getter_roam_time(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3237 dbus_bool_t wpas_dbus_getter_roam_time(
3238 const struct wpa_dbus_property_desc *property_desc,
3239 DBusMessageIter *iter, DBusError *error, void *user_data)
3240 {
3241 struct wpa_supplicant *wpa_s = user_data;
3242 dbus_uint32_t roam_time = wpa_s->roam_time.sec * 1000 +
3243 wpa_s->roam_time.usec / 1000;
3244
3245 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
3246 &roam_time, error);
3247 }
3248
3249
3250 /**
3251 * wpas_dbus_getter_roam_complete - Get most recent roam success or failure
3252 * @iter: Pointer to incoming dbus message iter
3253 * @error: Location to store error on failure
3254 * @user_data: Function specific data
3255 * Returns: TRUE on success, FALSE on failure
3256 *
3257 * Getter for "RoamComplete" property.
3258 */
wpas_dbus_getter_roam_complete(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3259 dbus_bool_t wpas_dbus_getter_roam_complete(
3260 const struct wpa_dbus_property_desc *property_desc,
3261 DBusMessageIter *iter, DBusError *error, void *user_data)
3262 {
3263 struct wpa_supplicant *wpa_s = user_data;
3264 dbus_bool_t roam_complete = os_reltime_initialized(&wpa_s->roam_time);
3265
3266 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
3267 &roam_complete, error);
3268 }
3269
3270
3271 /**
3272 * wpas_dbus_getter_session_length - Get most recent BSS session length
3273 * @iter: Pointer to incoming dbus message iter
3274 * @error: Location to store error on failure
3275 * @user_data: Function specific data
3276 * Returns: TRUE on success, FALSE on failure
3277 *
3278 * Getter for "SessionLength" property.
3279 */
wpas_dbus_getter_session_length(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3280 dbus_bool_t wpas_dbus_getter_session_length(
3281 const struct wpa_dbus_property_desc *property_desc,
3282 DBusMessageIter *iter, DBusError *error, void *user_data)
3283 {
3284 struct wpa_supplicant *wpa_s = user_data;
3285 dbus_uint32_t session_length = wpa_s->session_length.sec * 1000 +
3286 wpa_s->session_length.usec / 1000;
3287
3288 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
3289 &session_length, error);
3290 }
3291
3292
3293 /**
3294 * wpas_dbus_getter_bss_tm_status - Get most BSS Transition Management request
3295 * status code
3296 * @iter: Pointer to incoming dbus message iter
3297 * @error: Location to store error on failure
3298 * @user_data: Function specific data
3299 * Returns: TRUE on success, FALSE on failure
3300 *
3301 * Getter for "BSSTMStatus" property.
3302 */
wpas_dbus_getter_bss_tm_status(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3303 dbus_bool_t wpas_dbus_getter_bss_tm_status(
3304 const struct wpa_dbus_property_desc *property_desc,
3305 DBusMessageIter *iter, DBusError *error, void *user_data)
3306 {
3307 #ifdef CONFIG_WNM
3308 struct wpa_supplicant *wpa_s = user_data;
3309 dbus_uint32_t bss_tm_status = wpa_s->bss_tm_status;
3310 #else /* CONFIG_WNM */
3311 dbus_uint32_t bss_tm_status = 0;
3312 #endif /* CONFIG_WNM */
3313
3314 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
3315 &bss_tm_status, error);
3316 }
3317
3318
3319 /**
3320 * wpas_dbus_getter_bss_expire_age - Get BSS entry expiration age
3321 * @iter: Pointer to incoming dbus message iter
3322 * @error: Location to store error on failure
3323 * @user_data: Function specific data
3324 * Returns: TRUE on success, FALSE on failure
3325 *
3326 * Getter function for "BSSExpireAge" property.
3327 */
wpas_dbus_getter_bss_expire_age(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3328 dbus_bool_t wpas_dbus_getter_bss_expire_age(
3329 const struct wpa_dbus_property_desc *property_desc,
3330 DBusMessageIter *iter, DBusError *error, void *user_data)
3331 {
3332 struct wpa_supplicant *wpa_s = user_data;
3333 dbus_uint32_t expire_age = wpa_s->conf->bss_expiration_age;
3334
3335 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
3336 &expire_age, error);
3337 }
3338
3339
3340 /**
3341 * wpas_dbus_setter_bss_expire_age - Control BSS entry expiration age
3342 * @iter: Pointer to incoming dbus message iter
3343 * @error: Location to store error on failure
3344 * @user_data: Function specific data
3345 * Returns: TRUE on success, FALSE on failure
3346 *
3347 * Setter function for "BSSExpireAge" property.
3348 */
wpas_dbus_setter_bss_expire_age(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3349 dbus_bool_t wpas_dbus_setter_bss_expire_age(
3350 const struct wpa_dbus_property_desc *property_desc,
3351 DBusMessageIter *iter, DBusError *error, void *user_data)
3352 {
3353 struct wpa_supplicant *wpa_s = user_data;
3354 dbus_uint32_t expire_age;
3355
3356 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
3357 &expire_age))
3358 return FALSE;
3359
3360 if (wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age)) {
3361 dbus_set_error_const(error, DBUS_ERROR_FAILED,
3362 "BSSExpireAge must be >= 10");
3363 return FALSE;
3364 }
3365 return TRUE;
3366 }
3367
3368
3369 /**
3370 * wpas_dbus_getter_bss_expire_count - Get BSS entry expiration scan count
3371 * @iter: Pointer to incoming dbus message iter
3372 * @error: Location to store error on failure
3373 * @user_data: Function specific data
3374 * Returns: TRUE on success, FALSE on failure
3375 *
3376 * Getter function for "BSSExpireCount" property.
3377 */
wpas_dbus_getter_bss_expire_count(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3378 dbus_bool_t wpas_dbus_getter_bss_expire_count(
3379 const struct wpa_dbus_property_desc *property_desc,
3380 DBusMessageIter *iter, DBusError *error, void *user_data)
3381 {
3382 struct wpa_supplicant *wpa_s = user_data;
3383 dbus_uint32_t expire_count = wpa_s->conf->bss_expiration_scan_count;
3384
3385 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
3386 &expire_count, error);
3387 }
3388
3389
3390 /**
3391 * wpas_dbus_setter_bss_expire_count - Control BSS entry expiration scan count
3392 * @iter: Pointer to incoming dbus message iter
3393 * @error: Location to store error on failure
3394 * @user_data: Function specific data
3395 * Returns: TRUE on success, FALSE on failure
3396 *
3397 * Setter function for "BSSExpireCount" property.
3398 */
wpas_dbus_setter_bss_expire_count(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3399 dbus_bool_t wpas_dbus_setter_bss_expire_count(
3400 const struct wpa_dbus_property_desc *property_desc,
3401 DBusMessageIter *iter, DBusError *error, void *user_data)
3402 {
3403 struct wpa_supplicant *wpa_s = user_data;
3404 dbus_uint32_t expire_count;
3405
3406 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
3407 &expire_count))
3408 return FALSE;
3409
3410 if (wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count)) {
3411 dbus_set_error_const(error, DBUS_ERROR_FAILED,
3412 "BSSExpireCount must be > 0");
3413 return FALSE;
3414 }
3415 return TRUE;
3416 }
3417
3418
3419 /**
3420 * wpas_dbus_getter_country - Control country code
3421 * @iter: Pointer to incoming dbus message iter
3422 * @error: Location to store error on failure
3423 * @user_data: Function specific data
3424 * Returns: TRUE on success, FALSE on failure
3425 *
3426 * Getter function for "Country" property.
3427 */
wpas_dbus_getter_country(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3428 dbus_bool_t wpas_dbus_getter_country(
3429 const struct wpa_dbus_property_desc *property_desc,
3430 DBusMessageIter *iter, DBusError *error, void *user_data)
3431 {
3432 struct wpa_supplicant *wpa_s = user_data;
3433 char country[3];
3434 char *str = country;
3435
3436 country[0] = wpa_s->conf->country[0];
3437 country[1] = wpa_s->conf->country[1];
3438 country[2] = '\0';
3439
3440 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3441 &str, error);
3442 }
3443
3444
3445 /**
3446 * wpas_dbus_setter_country - Control country code
3447 * @iter: Pointer to incoming dbus message iter
3448 * @error: Location to store error on failure
3449 * @user_data: Function specific data
3450 * Returns: TRUE on success, FALSE on failure
3451 *
3452 * Setter function for "Country" property.
3453 */
wpas_dbus_setter_country(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3454 dbus_bool_t wpas_dbus_setter_country(
3455 const struct wpa_dbus_property_desc *property_desc,
3456 DBusMessageIter *iter, DBusError *error, void *user_data)
3457 {
3458 struct wpa_supplicant *wpa_s = user_data;
3459 const char *country;
3460
3461 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
3462 &country))
3463 return FALSE;
3464
3465 if (!country[0] || !country[1]) {
3466 dbus_set_error_const(error, DBUS_ERROR_FAILED,
3467 "invalid country code");
3468 return FALSE;
3469 }
3470
3471 if (wpa_s->drv_priv != NULL && wpa_drv_set_country(wpa_s, country)) {
3472 wpa_printf(MSG_DEBUG, "Failed to set country");
3473 dbus_set_error_const(error, DBUS_ERROR_FAILED,
3474 "failed to set country code");
3475 return FALSE;
3476 }
3477
3478 wpa_s->conf->country[0] = country[0];
3479 wpa_s->conf->country[1] = country[1];
3480 return TRUE;
3481 }
3482
3483
3484 /**
3485 * wpas_dbus_getter_scan_interval - Get scan interval
3486 * @iter: Pointer to incoming dbus message iter
3487 * @error: Location to store error on failure
3488 * @user_data: Function specific data
3489 * Returns: TRUE on success, FALSE on failure
3490 *
3491 * Getter function for "ScanInterval" property.
3492 */
wpas_dbus_getter_scan_interval(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3493 dbus_bool_t wpas_dbus_getter_scan_interval(
3494 const struct wpa_dbus_property_desc *property_desc,
3495 DBusMessageIter *iter, DBusError *error, void *user_data)
3496 {
3497 struct wpa_supplicant *wpa_s = user_data;
3498 dbus_int32_t scan_interval = wpa_s->scan_interval;
3499
3500 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
3501 &scan_interval, error);
3502 }
3503
3504
3505 /**
3506 * wpas_dbus_setter_scan_interval - Control scan interval
3507 * @iter: Pointer to incoming dbus message iter
3508 * @error: Location to store error on failure
3509 * @user_data: Function specific data
3510 * Returns: TRUE on success, FALSE on failure
3511 *
3512 * Setter function for "ScanInterval" property.
3513 */
wpas_dbus_setter_scan_interval(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3514 dbus_bool_t wpas_dbus_setter_scan_interval(
3515 const struct wpa_dbus_property_desc *property_desc,
3516 DBusMessageIter *iter, DBusError *error, void *user_data)
3517 {
3518 struct wpa_supplicant *wpa_s = user_data;
3519 dbus_int32_t scan_interval;
3520
3521 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_INT32,
3522 &scan_interval))
3523 return FALSE;
3524
3525 if (wpa_supplicant_set_scan_interval(wpa_s, scan_interval)) {
3526 dbus_set_error_const(error, DBUS_ERROR_FAILED,
3527 "scan_interval must be >= 0");
3528 return FALSE;
3529 }
3530 return TRUE;
3531 }
3532
3533
3534 /**
3535 * wpas_dbus_getter_ifname - Get interface name
3536 * @iter: Pointer to incoming dbus message iter
3537 * @error: Location to store error on failure
3538 * @user_data: Function specific data
3539 * Returns: TRUE on success, FALSE on failure
3540 *
3541 * Getter for "Ifname" property.
3542 */
wpas_dbus_getter_ifname(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3543 dbus_bool_t wpas_dbus_getter_ifname(
3544 const struct wpa_dbus_property_desc *property_desc,
3545 DBusMessageIter *iter, DBusError *error, void *user_data)
3546 {
3547 struct wpa_supplicant *wpa_s = user_data;
3548
3549 return wpas_dbus_string_property_getter(iter, wpa_s->ifname, error);
3550 }
3551
3552
3553 /**
3554 * wpas_dbus_getter_driver - Get interface name
3555 * @iter: Pointer to incoming dbus message iter
3556 * @error: Location to store error on failure
3557 * @user_data: Function specific data
3558 * Returns: TRUE on success, FALSE on failure
3559 *
3560 * Getter for "Driver" property.
3561 */
wpas_dbus_getter_driver(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3562 dbus_bool_t wpas_dbus_getter_driver(
3563 const struct wpa_dbus_property_desc *property_desc,
3564 DBusMessageIter *iter, DBusError *error, void *user_data)
3565 {
3566 struct wpa_supplicant *wpa_s = user_data;
3567
3568 if (wpa_s->driver == NULL || wpa_s->driver->name == NULL) {
3569 wpa_printf(MSG_DEBUG, "%s[dbus]: wpa_s has no driver set",
3570 __func__);
3571 dbus_set_error(error, DBUS_ERROR_FAILED, "%s: no driver set",
3572 __func__);
3573 return FALSE;
3574 }
3575
3576 return wpas_dbus_string_property_getter(iter, wpa_s->driver->name,
3577 error);
3578 }
3579
3580
3581 /**
3582 * wpas_dbus_getter_current_bss - Get current bss object path
3583 * @iter: Pointer to incoming dbus message iter
3584 * @error: Location to store error on failure
3585 * @user_data: Function specific data
3586 * Returns: TRUE on success, FALSE on failure
3587 *
3588 * Getter for "CurrentBSS" property.
3589 */
wpas_dbus_getter_current_bss(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3590 dbus_bool_t wpas_dbus_getter_current_bss(
3591 const struct wpa_dbus_property_desc *property_desc,
3592 DBusMessageIter *iter, DBusError *error, void *user_data)
3593 {
3594 struct wpa_supplicant *wpa_s = user_data;
3595 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *bss_obj_path = path_buf;
3596
3597 if (wpa_s->current_bss && wpa_s->dbus_new_path)
3598 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3599 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
3600 wpa_s->dbus_new_path, wpa_s->current_bss->id);
3601 else
3602 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
3603
3604 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
3605 &bss_obj_path, error);
3606 }
3607
3608
3609 /**
3610 * wpas_dbus_getter_current_network - Get current network object path
3611 * @iter: Pointer to incoming dbus message iter
3612 * @error: Location to store error on failure
3613 * @user_data: Function specific data
3614 * Returns: TRUE on success, FALSE on failure
3615 *
3616 * Getter for "CurrentNetwork" property.
3617 */
wpas_dbus_getter_current_network(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3618 dbus_bool_t wpas_dbus_getter_current_network(
3619 const struct wpa_dbus_property_desc *property_desc,
3620 DBusMessageIter *iter, DBusError *error, void *user_data)
3621 {
3622 struct wpa_supplicant *wpa_s = user_data;
3623 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *net_obj_path = path_buf;
3624
3625 if (wpa_s->current_ssid && wpa_s->dbus_new_path)
3626 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3627 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
3628 wpa_s->dbus_new_path, wpa_s->current_ssid->id);
3629 else
3630 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
3631
3632 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
3633 &net_obj_path, error);
3634 }
3635
3636
3637 /**
3638 * wpas_dbus_getter_current_auth_mode - Get current authentication type
3639 * @iter: Pointer to incoming dbus message iter
3640 * @error: Location to store error on failure
3641 * @user_data: Function specific data
3642 * Returns: TRUE on success, FALSE on failure
3643 *
3644 * Getter for "CurrentAuthMode" property.
3645 */
wpas_dbus_getter_current_auth_mode(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3646 dbus_bool_t wpas_dbus_getter_current_auth_mode(
3647 const struct wpa_dbus_property_desc *property_desc,
3648 DBusMessageIter *iter, DBusError *error, void *user_data)
3649 {
3650 struct wpa_supplicant *wpa_s = user_data;
3651 const char *eap_mode;
3652 const char *auth_mode;
3653 char eap_mode_buf[WPAS_DBUS_AUTH_MODE_MAX];
3654
3655 if (wpa_s->wpa_state != WPA_COMPLETED) {
3656 auth_mode = "INACTIVE";
3657 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X ||
3658 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3659 eap_mode = wpa_supplicant_get_eap_mode(wpa_s);
3660 os_snprintf(eap_mode_buf, WPAS_DBUS_AUTH_MODE_MAX,
3661 "EAP-%s", eap_mode);
3662 auth_mode = eap_mode_buf;
3663
3664 } else if (wpa_s->current_ssid) {
3665 auth_mode = wpa_key_mgmt_txt(wpa_s->key_mgmt,
3666 wpa_s->current_ssid->proto);
3667 } else {
3668 auth_mode = "UNKNOWN";
3669 }
3670
3671 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3672 &auth_mode, error);
3673 }
3674
3675
3676 /**
3677 * wpas_dbus_getter_bridge_ifname - Get interface name
3678 * @iter: Pointer to incoming dbus message iter
3679 * @error: Location to store error on failure
3680 * @user_data: Function specific data
3681 * Returns: TRUE on success, FALSE on failure
3682 *
3683 * Getter for "BridgeIfname" property.
3684 */
wpas_dbus_getter_bridge_ifname(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3685 dbus_bool_t wpas_dbus_getter_bridge_ifname(
3686 const struct wpa_dbus_property_desc *property_desc,
3687 DBusMessageIter *iter, DBusError *error, void *user_data)
3688 {
3689 struct wpa_supplicant *wpa_s = user_data;
3690
3691 return wpas_dbus_string_property_getter(iter, wpa_s->bridge_ifname,
3692 error);
3693 }
3694
3695
wpas_dbus_setter_bridge_ifname(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3696 dbus_bool_t wpas_dbus_setter_bridge_ifname(
3697 const struct wpa_dbus_property_desc *property_desc,
3698 DBusMessageIter *iter, DBusError *error, void *user_data)
3699 {
3700 struct wpa_supplicant *wpa_s = user_data;
3701 const char *bridge_ifname = NULL;
3702 const char *msg;
3703 int r;
3704
3705 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
3706 &bridge_ifname))
3707 return FALSE;
3708
3709 r = wpa_supplicant_update_bridge_ifname(wpa_s, bridge_ifname);
3710 if (r != 0) {
3711 switch (r) {
3712 case -EINVAL:
3713 msg = "invalid interface name";
3714 break;
3715 case -EBUSY:
3716 msg = "interface is busy";
3717 break;
3718 case -EIO:
3719 msg = "socket error";
3720 break;
3721 default:
3722 msg = "unknown error";
3723 break;
3724 }
3725 dbus_set_error_const(error, DBUS_ERROR_FAILED, msg);
3726 return FALSE;
3727 }
3728
3729 return TRUE;
3730 }
3731
3732
3733 /**
3734 * wpas_dbus_getter_config_file - Get interface configuration file path
3735 * @iter: Pointer to incoming dbus message iter
3736 * @error: Location to store error on failure
3737 * @user_data: Function specific data
3738 * Returns: TRUE on success, FALSE on failure
3739 *
3740 * Getter for "ConfigFile" property.
3741 */
wpas_dbus_getter_config_file(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3742 dbus_bool_t wpas_dbus_getter_config_file(
3743 const struct wpa_dbus_property_desc *property_desc,
3744 DBusMessageIter *iter, DBusError *error, void *user_data)
3745 {
3746 struct wpa_supplicant *wpa_s = user_data;
3747
3748 return wpas_dbus_string_property_getter(iter, wpa_s->confname, error);
3749 }
3750
3751
3752 /**
3753 * wpas_dbus_getter_bsss - Get array of BSSs objects
3754 * @iter: Pointer to incoming dbus message iter
3755 * @error: Location to store error on failure
3756 * @user_data: Function specific data
3757 * Returns: TRUE on success, FALSE on failure
3758 *
3759 * Getter for "BSSs" property.
3760 */
wpas_dbus_getter_bsss(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3761 dbus_bool_t wpas_dbus_getter_bsss(
3762 const struct wpa_dbus_property_desc *property_desc,
3763 DBusMessageIter *iter, DBusError *error, void *user_data)
3764 {
3765 struct wpa_supplicant *wpa_s = user_data;
3766 struct wpa_bss *bss;
3767 char **paths;
3768 unsigned int i = 0;
3769 dbus_bool_t success = FALSE;
3770
3771 if (!wpa_s->dbus_new_path) {
3772 dbus_set_error(error, DBUS_ERROR_FAILED,
3773 "%s: no D-Bus interface", __func__);
3774 return FALSE;
3775 }
3776
3777 paths = os_calloc(wpa_s->num_bss, sizeof(char *));
3778 if (!paths) {
3779 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3780 return FALSE;
3781 }
3782
3783 /* Loop through scan results and append each result's object path */
3784 dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
3785 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
3786 if (paths[i] == NULL) {
3787 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
3788 "no memory");
3789 goto out;
3790 }
3791 /* Construct the object path for this BSS. */
3792 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
3793 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
3794 wpa_s->dbus_new_path, bss->id);
3795 }
3796
3797 success = wpas_dbus_simple_array_property_getter(iter,
3798 DBUS_TYPE_OBJECT_PATH,
3799 paths, wpa_s->num_bss,
3800 error);
3801
3802 out:
3803 while (i)
3804 os_free(paths[--i]);
3805 os_free(paths);
3806 return success;
3807 }
3808
3809
3810 /**
3811 * wpas_dbus_getter_networks - Get array of networks objects
3812 * @iter: Pointer to incoming dbus message iter
3813 * @error: Location to store error on failure
3814 * @user_data: Function specific data
3815 * Returns: TRUE on success, FALSE on failure
3816 *
3817 * Getter for "Networks" property.
3818 */
wpas_dbus_getter_networks(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3819 dbus_bool_t wpas_dbus_getter_networks(
3820 const struct wpa_dbus_property_desc *property_desc,
3821 DBusMessageIter *iter, DBusError *error, void *user_data)
3822 {
3823 struct wpa_supplicant *wpa_s = user_data;
3824 struct wpa_ssid *ssid;
3825 char **paths;
3826 unsigned int i = 0, num = 0;
3827 dbus_bool_t success = FALSE;
3828
3829 if (!wpa_s->dbus_new_path) {
3830 dbus_set_error(error, DBUS_ERROR_FAILED,
3831 "%s: no D-Bus interface", __func__);
3832 return FALSE;
3833 }
3834
3835 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
3836 if (!network_is_persistent_group(ssid))
3837 num++;
3838
3839 paths = os_calloc(num, sizeof(char *));
3840 if (!paths) {
3841 dbus_set_error(error, DBUS_ERROR_NO_MEMORY, "no memory");
3842 return FALSE;
3843 }
3844
3845 /* Loop through configured networks and append object path of each */
3846 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
3847 if (network_is_persistent_group(ssid))
3848 continue;
3849 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
3850 if (paths[i] == NULL) {
3851 dbus_set_error(error, DBUS_ERROR_NO_MEMORY,
3852 "no memory");
3853 goto out;
3854 }
3855
3856 /* Construct the object path for this network. */
3857 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
3858 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
3859 wpa_s->dbus_new_path, ssid->id);
3860 }
3861
3862 success = wpas_dbus_simple_array_property_getter(iter,
3863 DBUS_TYPE_OBJECT_PATH,
3864 paths, num, error);
3865
3866 out:
3867 while (i)
3868 os_free(paths[--i]);
3869 os_free(paths);
3870 return success;
3871 }
3872
3873
3874 /**
3875 * wpas_dbus_getter_pkcs11_engine_path - Get PKCS #11 engine path
3876 * @iter: Pointer to incoming dbus message iter
3877 * @error: Location to store error on failure
3878 * @user_data: Function specific data
3879 * Returns: A dbus message containing the PKCS #11 engine path
3880 *
3881 * Getter for "PKCS11EnginePath" property.
3882 */
wpas_dbus_getter_pkcs11_engine_path(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3883 dbus_bool_t wpas_dbus_getter_pkcs11_engine_path(
3884 const struct wpa_dbus_property_desc *property_desc,
3885 DBusMessageIter *iter, DBusError *error, void *user_data)
3886 {
3887 struct wpa_supplicant *wpa_s = user_data;
3888
3889 return wpas_dbus_string_property_getter(iter,
3890 wpa_s->conf->pkcs11_engine_path,
3891 error);
3892 }
3893
3894
3895 /**
3896 * wpas_dbus_getter_pkcs11_module_path - Get PKCS #11 module path
3897 * @iter: Pointer to incoming dbus message iter
3898 * @error: Location to store error on failure
3899 * @user_data: Function specific data
3900 * Returns: A dbus message containing the PKCS #11 module path
3901 *
3902 * Getter for "PKCS11ModulePath" property.
3903 */
wpas_dbus_getter_pkcs11_module_path(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3904 dbus_bool_t wpas_dbus_getter_pkcs11_module_path(
3905 const struct wpa_dbus_property_desc *property_desc,
3906 DBusMessageIter *iter, DBusError *error, void *user_data)
3907 {
3908 struct wpa_supplicant *wpa_s = user_data;
3909
3910 return wpas_dbus_string_property_getter(iter,
3911 wpa_s->conf->pkcs11_module_path,
3912 error);
3913 }
3914
3915
3916 /**
3917 * wpas_dbus_getter_blobs - Get all blobs defined for this interface
3918 * @iter: Pointer to incoming dbus message iter
3919 * @error: Location to store error on failure
3920 * @user_data: Function specific data
3921 * Returns: TRUE on success, FALSE on failure
3922 *
3923 * Getter for "Blobs" property.
3924 */
wpas_dbus_getter_blobs(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3925 dbus_bool_t wpas_dbus_getter_blobs(
3926 const struct wpa_dbus_property_desc *property_desc,
3927 DBusMessageIter *iter, DBusError *error, void *user_data)
3928 {
3929 struct wpa_supplicant *wpa_s = user_data;
3930 DBusMessageIter variant_iter, dict_iter, entry_iter, array_iter;
3931 struct wpa_config_blob *blob;
3932
3933 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
3934 "a{say}", &variant_iter) ||
3935 !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
3936 "{say}", &dict_iter)) {
3937 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3938 return FALSE;
3939 }
3940
3941 blob = wpa_s->conf->blobs;
3942 while (blob) {
3943 if (!dbus_message_iter_open_container(&dict_iter,
3944 DBUS_TYPE_DICT_ENTRY,
3945 NULL, &entry_iter) ||
3946 !dbus_message_iter_append_basic(&entry_iter,
3947 DBUS_TYPE_STRING,
3948 &(blob->name)) ||
3949 !dbus_message_iter_open_container(&entry_iter,
3950 DBUS_TYPE_ARRAY,
3951 DBUS_TYPE_BYTE_AS_STRING,
3952 &array_iter) ||
3953 !dbus_message_iter_append_fixed_array(&array_iter,
3954 DBUS_TYPE_BYTE,
3955 &(blob->data),
3956 blob->len) ||
3957 !dbus_message_iter_close_container(&entry_iter,
3958 &array_iter) ||
3959 !dbus_message_iter_close_container(&dict_iter,
3960 &entry_iter)) {
3961 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
3962 "no memory");
3963 return FALSE;
3964 }
3965
3966 blob = blob->next;
3967 }
3968
3969 if (!dbus_message_iter_close_container(&variant_iter, &dict_iter) ||
3970 !dbus_message_iter_close_container(iter, &variant_iter)) {
3971 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3972 return FALSE;
3973 }
3974
3975 return TRUE;
3976 }
3977
3978
wpas_dbus_getter_iface_global(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3979 dbus_bool_t wpas_dbus_getter_iface_global(
3980 const struct wpa_dbus_property_desc *property_desc,
3981 DBusMessageIter *iter, DBusError *error, void *user_data)
3982 {
3983 struct wpa_supplicant *wpa_s = user_data;
3984 int ret;
3985 char buf[250];
3986 char *p = buf;
3987
3988 if (!property_desc->data) {
3989 dbus_set_error(error, DBUS_ERROR_INVALID_ARGS,
3990 "Unhandled interface property %s",
3991 property_desc->dbus_property);
3992 return FALSE;
3993 }
3994
3995 ret = wpa_config_get_value(property_desc->data, wpa_s->conf, buf,
3996 sizeof(buf));
3997 if (ret < 0)
3998 *p = '\0';
3999
4000 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &p,
4001 error);
4002 }
4003
4004
wpas_dbus_setter_iface_global(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)4005 dbus_bool_t wpas_dbus_setter_iface_global(
4006 const struct wpa_dbus_property_desc *property_desc,
4007 DBusMessageIter *iter, DBusError *error, void *user_data)
4008 {
4009 struct wpa_supplicant *wpa_s = user_data;
4010 const char *new_value = NULL;
4011 char buf[250];
4012 size_t combined_len;
4013 int ret;
4014
4015 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
4016 &new_value))
4017 return FALSE;
4018
4019 combined_len = os_strlen(property_desc->data) + os_strlen(new_value) +
4020 3;
4021 if (combined_len >= sizeof(buf)) {
4022 dbus_set_error(error, DBUS_ERROR_INVALID_ARGS,
4023 "Interface property %s value too large",
4024 property_desc->dbus_property);
4025 return FALSE;
4026 }
4027
4028 if (!new_value[0])
4029 new_value = "NULL";
4030
4031 ret = os_snprintf(buf, combined_len, "%s=%s", property_desc->data,
4032 new_value);
4033 if (os_snprintf_error(combined_len, ret)) {
4034 dbus_set_error(error, WPAS_DBUS_ERROR_UNKNOWN_ERROR,
4035 "Failed to construct new interface property %s",
4036 property_desc->dbus_property);
4037 return FALSE;
4038 }
4039
4040 ret = wpa_config_process_global(wpa_s->conf, buf, -1);
4041 if (ret < 0) {
4042 dbus_set_error(error, DBUS_ERROR_INVALID_ARGS,
4043 "Failed to set interface property %s",
4044 property_desc->dbus_property);
4045 return FALSE;
4046 } else if (ret == 0) {
4047 wpa_supplicant_update_config(wpa_s);
4048 }
4049 return TRUE;
4050 }
4051
4052
4053 /**
4054 * wpas_dbus_getter_stas - Get connected stations for an interface
4055 * @iter: Pointer to incoming dbus message iter
4056 * @error: Location to store error on failure
4057 * @user_data: Function specific data
4058 * Returns: a list of stations
4059 *
4060 * Getter for "Stations" property.
4061 */
wpas_dbus_getter_stas(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)4062 dbus_bool_t wpas_dbus_getter_stas(
4063 const struct wpa_dbus_property_desc *property_desc,
4064 DBusMessageIter *iter, DBusError *error, void *user_data)
4065 {
4066 struct wpa_supplicant *wpa_s = user_data;
4067 struct sta_info *sta = NULL;
4068 char **paths = NULL;
4069 unsigned int i = 0, num = 0;
4070 dbus_bool_t success = FALSE;
4071
4072 if (!wpa_s->dbus_new_path) {
4073 dbus_set_error(error, DBUS_ERROR_FAILED,
4074 "%s: no D-Bus interface", __func__);
4075 return FALSE;
4076 }
4077
4078 #ifdef CONFIG_AP
4079 if (wpa_s->ap_iface) {
4080 struct hostapd_data *hapd;
4081
4082 hapd = wpa_s->ap_iface->bss[0];
4083 sta = hapd->sta_list;
4084 num = hapd->num_sta;
4085 }
4086 #endif /* CONFIG_AP */
4087
4088 paths = os_calloc(num, sizeof(char *));
4089 if (!paths) {
4090 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
4091 return FALSE;
4092 }
4093
4094 /* Loop through scan results and append each result's object path */
4095 for (; sta; sta = sta->next) {
4096 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
4097 if (!paths[i]) {
4098 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
4099 "no memory");
4100 goto out;
4101 }
4102 /* Construct the object path for this BSS. */
4103 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
4104 "%s/" WPAS_DBUS_NEW_STAS_PART "/" COMPACT_MACSTR,
4105 wpa_s->dbus_new_path, MAC2STR(sta->addr));
4106 }
4107
4108 success = wpas_dbus_simple_array_property_getter(iter,
4109 DBUS_TYPE_OBJECT_PATH,
4110 paths, num,
4111 error);
4112
4113 out:
4114 while (i)
4115 os_free(paths[--i]);
4116 os_free(paths);
4117 return success;
4118 }
4119
4120
4121 /**
4122 * wpas_dbus_setter_mac_address_randomization_mask - Set masks used for
4123 * MAC address randomization
4124 * @iter: Pointer to incoming dbus message iter
4125 * @error: Location to store error on failure
4126 * @user_data: Function specific data
4127 * Returns: TRUE on success, FALSE on failure
4128 *
4129 * Setter for "MACAddressRandomizationMask" property.
4130 */
wpas_dbus_setter_mac_address_randomization_mask(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)4131 dbus_bool_t wpas_dbus_setter_mac_address_randomization_mask(
4132 const struct wpa_dbus_property_desc *property_desc,
4133 DBusMessageIter *iter, DBusError *error, void *user_data)
4134 {
4135 struct wpa_supplicant *wpa_s = user_data;
4136 DBusMessageIter variant_iter, dict_iter, entry_iter, array_iter;
4137 const char *key;
4138 unsigned int rand_type = 0;
4139 const u8 *mask;
4140 int mask_len;
4141 unsigned int rand_types_to_disable = MAC_ADDR_RAND_ALL;
4142
4143 dbus_message_iter_recurse(iter, &variant_iter);
4144 if (dbus_message_iter_get_arg_type(&variant_iter) != DBUS_TYPE_ARRAY) {
4145 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
4146 "invalid message format");
4147 return FALSE;
4148 }
4149 dbus_message_iter_recurse(&variant_iter, &dict_iter);
4150 while (dbus_message_iter_get_arg_type(&dict_iter) ==
4151 DBUS_TYPE_DICT_ENTRY) {
4152 dbus_message_iter_recurse(&dict_iter, &entry_iter);
4153 if (dbus_message_iter_get_arg_type(&entry_iter) !=
4154 DBUS_TYPE_STRING) {
4155 dbus_set_error(error, DBUS_ERROR_FAILED,
4156 "%s: key not a string", __func__);
4157 return FALSE;
4158 }
4159 dbus_message_iter_get_basic(&entry_iter, &key);
4160 dbus_message_iter_next(&entry_iter);
4161 if (dbus_message_iter_get_arg_type(&entry_iter) !=
4162 DBUS_TYPE_ARRAY ||
4163 dbus_message_iter_get_element_type(&entry_iter) !=
4164 DBUS_TYPE_BYTE) {
4165 dbus_set_error(error, DBUS_ERROR_FAILED,
4166 "%s: mask was not a byte array",
4167 __func__);
4168 return FALSE;
4169 }
4170 dbus_message_iter_recurse(&entry_iter, &array_iter);
4171 dbus_message_iter_get_fixed_array(&array_iter, &mask,
4172 &mask_len);
4173
4174 if (os_strcmp(key, "scan") == 0) {
4175 rand_type = MAC_ADDR_RAND_SCAN;
4176 } else if (os_strcmp(key, "sched_scan") == 0) {
4177 rand_type = MAC_ADDR_RAND_SCHED_SCAN;
4178 } else if (os_strcmp(key, "pno") == 0) {
4179 rand_type = MAC_ADDR_RAND_PNO;
4180 } else {
4181 dbus_set_error(error, DBUS_ERROR_FAILED,
4182 "%s: bad scan type \"%s\"",
4183 __func__, key);
4184 return FALSE;
4185 }
4186
4187 if (mask_len != ETH_ALEN) {
4188 dbus_set_error(error, DBUS_ERROR_FAILED,
4189 "%s: malformed MAC mask given",
4190 __func__);
4191 return FALSE;
4192 }
4193
4194 if (wpas_enable_mac_addr_randomization(
4195 wpa_s, rand_type, wpa_s->perm_addr, mask)) {
4196 dbus_set_error(error, DBUS_ERROR_FAILED,
4197 "%s: failed to set up MAC address randomization for %s",
4198 __func__, key);
4199 return FALSE;
4200 }
4201
4202 wpa_printf(MSG_DEBUG,
4203 "%s: Enabled MAC address randomization for %s with mask: "
4204 MACSTR, wpa_s->ifname, key, MAC2STR(mask));
4205 rand_types_to_disable &= ~rand_type;
4206 dbus_message_iter_next(&dict_iter);
4207 }
4208
4209 if (rand_types_to_disable &&
4210 wpas_disable_mac_addr_randomization(wpa_s, rand_types_to_disable)) {
4211 dbus_set_error(error, DBUS_ERROR_FAILED,
4212 "%s: failed to disable MAC address randomization",
4213 __func__);
4214 return FALSE;
4215 }
4216
4217 return TRUE;
4218 }
4219
4220
wpas_dbus_getter_mac_address_randomization_mask(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)4221 dbus_bool_t wpas_dbus_getter_mac_address_randomization_mask(
4222 const struct wpa_dbus_property_desc *property_desc,
4223 DBusMessageIter *iter, DBusError *error, void *user_data)
4224 {
4225 struct wpa_supplicant *wpa_s = user_data;
4226 DBusMessageIter variant_iter, dict_iter, entry_iter, array_iter;
4227 unsigned int i;
4228 u8 mask_buf[ETH_ALEN];
4229 /* Read docs on dbus_message_iter_append_fixed_array() for why this
4230 * is necessary... */
4231 u8 *mask = mask_buf;
4232 static const struct {
4233 const char *key;
4234 unsigned int type;
4235 } types[] = {
4236 { "scan", MAC_ADDR_RAND_SCAN },
4237 { "sched_scan", MAC_ADDR_RAND_SCHED_SCAN },
4238 { "pno", MAC_ADDR_RAND_PNO }
4239 };
4240
4241 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
4242 "a{say}", &variant_iter) ||
4243 !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
4244 "{say}", &dict_iter)) {
4245 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
4246 return FALSE;
4247 }
4248
4249 for (i = 0; i < ARRAY_SIZE(types); i++) {
4250 if (wpas_mac_addr_rand_scan_get_mask(wpa_s, types[i].type,
4251 mask))
4252 continue;
4253
4254 if (!dbus_message_iter_open_container(&dict_iter,
4255 DBUS_TYPE_DICT_ENTRY,
4256 NULL, &entry_iter) ||
4257 !dbus_message_iter_append_basic(&entry_iter,
4258 DBUS_TYPE_STRING,
4259 &types[i].key) ||
4260 !dbus_message_iter_open_container(&entry_iter,
4261 DBUS_TYPE_ARRAY,
4262 DBUS_TYPE_BYTE_AS_STRING,
4263 &array_iter) ||
4264 !dbus_message_iter_append_fixed_array(&array_iter,
4265 DBUS_TYPE_BYTE,
4266 &mask,
4267 ETH_ALEN) ||
4268 !dbus_message_iter_close_container(&entry_iter,
4269 &array_iter) ||
4270 !dbus_message_iter_close_container(&dict_iter,
4271 &entry_iter)) {
4272 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
4273 "no memory");
4274 return FALSE;
4275 }
4276 }
4277
4278 if (!dbus_message_iter_close_container(&variant_iter, &dict_iter) ||
4279 !dbus_message_iter_close_container(iter, &variant_iter)) {
4280 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
4281 return FALSE;
4282 }
4283
4284 return TRUE;
4285 }
4286
4287
4288 /**
4289 * wpas_dbus_getter_sta_address - Return the address of a connected station
4290 * @iter: Pointer to incoming dbus message iter
4291 * @error: Location to store error on failure
4292 * @user_data: Function specific data
4293 * Returns: TRUE on success, FALSE on failure
4294 *
4295 * Getter for "Address" property.
4296 */
wpas_dbus_getter_sta_address(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)4297 dbus_bool_t wpas_dbus_getter_sta_address(
4298 const struct wpa_dbus_property_desc *property_desc,
4299 DBusMessageIter *iter, DBusError *error, void *user_data)
4300 {
4301 #ifdef CONFIG_AP
4302 struct sta_handler_args *args = user_data;
4303 struct sta_info *sta;
4304
4305 sta = ap_get_sta(args->wpa_s->ap_iface->bss[0], args->sta);
4306 if (!sta)
4307 return FALSE;
4308
4309 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
4310 sta->addr, ETH_ALEN,
4311 error);
4312 #else /* CONFIG_AP */
4313 return FALSE;
4314 #endif /* CONFIG_AP */
4315 }
4316
4317
4318 /**
4319 * wpas_dbus_getter_sta_aid - Return the AID of a connected station
4320 * @iter: Pointer to incoming dbus message iter
4321 * @error: Location to store error on failure
4322 * @user_data: Function specific data
4323 * Returns: TRUE on success, FALSE on failure
4324 *
4325 * Getter for "AID" property.
4326 */
wpas_dbus_getter_sta_aid(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)4327 dbus_bool_t wpas_dbus_getter_sta_aid(
4328 const struct wpa_dbus_property_desc *property_desc,
4329 DBusMessageIter *iter, DBusError *error, void *user_data)
4330 {
4331 #ifdef CONFIG_AP
4332 struct sta_handler_args *args = user_data;
4333 struct sta_info *sta;
4334
4335 sta = ap_get_sta(args->wpa_s->ap_iface->bss[0], args->sta);
4336 if (!sta)
4337 return FALSE;
4338
4339 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
4340 &sta->aid,
4341 error);
4342 #else /* CONFIG_AP */
4343 return FALSE;
4344 #endif /* CONFIG_AP */
4345 }
4346
4347
4348 /**
4349 * wpas_dbus_getter_sta_caps - Return the capabilities of a station
4350 * @iter: Pointer to incoming dbus message iter
4351 * @error: Location to store error on failure
4352 * @user_data: Function specific data
4353 * Returns: TRUE on success, FALSE on failure
4354 *
4355 * Getter for "Capabilities" property.
4356 */
wpas_dbus_getter_sta_caps(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)4357 dbus_bool_t wpas_dbus_getter_sta_caps(
4358 const struct wpa_dbus_property_desc *property_desc,
4359 DBusMessageIter *iter, DBusError *error, void *user_data)
4360 {
4361 #ifdef CONFIG_AP
4362 struct sta_handler_args *args = user_data;
4363 struct sta_info *sta;
4364
4365 sta = ap_get_sta(args->wpa_s->ap_iface->bss[0], args->sta);
4366 if (!sta)
4367 return FALSE;
4368
4369 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
4370 &sta->capability,
4371 error);
4372 #else /* CONFIG_AP */
4373 return FALSE;
4374 #endif /* CONFIG_AP */
4375 }
4376
4377
4378 /**
4379 * wpas_dbus_getter_rx_packets - Return the received packets for a station
4380 * @iter: Pointer to incoming dbus message iter
4381 * @error: Location to store error on failure
4382 * @user_data: Function specific data
4383 * Returns: TRUE on success, FALSE on failure
4384 *
4385 * Getter for "RxPackets" property.
4386 */
wpas_dbus_getter_sta_rx_packets(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)4387 dbus_bool_t wpas_dbus_getter_sta_rx_packets(
4388 const struct wpa_dbus_property_desc *property_desc,
4389 DBusMessageIter *iter, DBusError *error, void *user_data)
4390 {
4391 #ifdef CONFIG_AP
4392 struct sta_handler_args *args = user_data;
4393 struct sta_info *sta;
4394 struct hostap_sta_driver_data data;
4395 struct hostapd_data *hapd;
4396
4397 if (!args->wpa_s->ap_iface)
4398 return FALSE;
4399
4400 hapd = args->wpa_s->ap_iface->bss[0];
4401 sta = ap_get_sta(hapd, args->sta);
4402 if (!sta)
4403 return FALSE;
4404
4405 if (hostapd_drv_read_sta_data(hapd, &data, sta->addr) < 0)
4406 return FALSE;
4407
4408 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT64,
4409 &data.rx_packets,
4410 error);
4411 #else /* CONFIG_AP */
4412 return FALSE;
4413 #endif /* CONFIG_AP */
4414 }
4415
4416
4417 /**
4418 * wpas_dbus_getter_tx_packets - Return the transmitted packets for a station
4419 * @iter: Pointer to incoming dbus message iter
4420 * @error: Location to store error on failure
4421 * @user_data: Function specific data
4422 * Returns: TRUE on success, FALSE on failure
4423 *
4424 * Getter for "TxPackets" property.
4425 */
wpas_dbus_getter_sta_tx_packets(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)4426 dbus_bool_t wpas_dbus_getter_sta_tx_packets(
4427 const struct wpa_dbus_property_desc *property_desc,
4428 DBusMessageIter *iter, DBusError *error, void *user_data)
4429 {
4430 #ifdef CONFIG_AP
4431 struct sta_handler_args *args = user_data;
4432 struct sta_info *sta;
4433 struct hostap_sta_driver_data data;
4434 struct hostapd_data *hapd;
4435
4436 if (!args->wpa_s->ap_iface)
4437 return FALSE;
4438
4439 hapd = args->wpa_s->ap_iface->bss[0];
4440 sta = ap_get_sta(hapd, args->sta);
4441 if (!sta)
4442 return FALSE;
4443
4444 if (hostapd_drv_read_sta_data(hapd, &data, sta->addr) < 0)
4445 return FALSE;
4446
4447 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT64,
4448 &data.tx_packets,
4449 error);
4450 #else /* CONFIG_AP */
4451 return FALSE;
4452 #endif /* CONFIG_AP */
4453 }
4454
4455
4456 /**
4457 * wpas_dbus_getter_tx_bytes - Return the transmitted bytes for a station
4458 * @iter: Pointer to incoming dbus message iter
4459 * @error: Location to store error on failure
4460 * @user_data: Function specific data
4461 * Returns: TRUE on success, FALSE on failure
4462 *
4463 * Getter for "TxBytes" property.
4464 */
wpas_dbus_getter_sta_tx_bytes(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)4465 dbus_bool_t wpas_dbus_getter_sta_tx_bytes(
4466 const struct wpa_dbus_property_desc *property_desc,
4467 DBusMessageIter *iter, DBusError *error, void *user_data)
4468 {
4469 #ifdef CONFIG_AP
4470 struct sta_handler_args *args = user_data;
4471 struct sta_info *sta;
4472 struct hostap_sta_driver_data data;
4473 struct hostapd_data *hapd;
4474
4475 if (!args->wpa_s->ap_iface)
4476 return FALSE;
4477
4478 hapd = args->wpa_s->ap_iface->bss[0];
4479 sta = ap_get_sta(hapd, args->sta);
4480 if (!sta)
4481 return FALSE;
4482
4483 if (hostapd_drv_read_sta_data(hapd, &data, sta->addr) < 0)
4484 return FALSE;
4485
4486 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT64,
4487 &data.tx_bytes,
4488 error);
4489 #else /* CONFIG_AP */
4490 return FALSE;
4491 #endif /* CONFIG_AP */
4492 }
4493
4494
4495 /**
4496 * wpas_dbus_getter_rx_bytes - Return the received bytes for a station
4497 * @iter: Pointer to incoming dbus message iter
4498 * @error: Location to store error on failure
4499 * @user_data: Function specific data
4500 * Returns: TRUE on success, FALSE on failure
4501 *
4502 * Getter for "RxBytes" property.
4503 */
wpas_dbus_getter_sta_rx_bytes(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)4504 dbus_bool_t wpas_dbus_getter_sta_rx_bytes(
4505 const struct wpa_dbus_property_desc *property_desc,
4506 DBusMessageIter *iter, DBusError *error, void *user_data)
4507 {
4508 #ifdef CONFIG_AP
4509 struct sta_handler_args *args = user_data;
4510 struct sta_info *sta;
4511 struct hostap_sta_driver_data data;
4512 struct hostapd_data *hapd;
4513
4514 if (!args->wpa_s->ap_iface)
4515 return FALSE;
4516
4517 hapd = args->wpa_s->ap_iface->bss[0];
4518 sta = ap_get_sta(hapd, args->sta);
4519 if (!sta)
4520 return FALSE;
4521
4522 if (hostapd_drv_read_sta_data(hapd, &data, sta->addr) < 0)
4523 return FALSE;
4524
4525 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT64,
4526 &data.rx_bytes,
4527 error);
4528 #else /* CONFIG_AP */
4529 return FALSE;
4530 #endif /* CONFIG_AP */
4531 }
4532
4533
get_bss_helper(struct bss_handler_args * args,DBusError * error,const char * func_name)4534 static struct wpa_bss * get_bss_helper(struct bss_handler_args *args,
4535 DBusError *error, const char *func_name)
4536 {
4537 struct wpa_bss *res = wpa_bss_get_id(args->wpa_s, args->id);
4538
4539 if (!res) {
4540 wpa_printf(MSG_ERROR, "%s[dbus]: no bss with id %d found",
4541 func_name, args->id);
4542 dbus_set_error(error, DBUS_ERROR_FAILED,
4543 "%s: BSS %d not found",
4544 func_name, args->id);
4545 }
4546
4547 return res;
4548 }
4549
4550
4551 /**
4552 * wpas_dbus_getter_bss_bssid - Return the BSSID of a BSS
4553 * @iter: Pointer to incoming dbus message iter
4554 * @error: Location to store error on failure
4555 * @user_data: Function specific data
4556 * Returns: TRUE on success, FALSE on failure
4557 *
4558 * Getter for "BSSID" property.
4559 */
wpas_dbus_getter_bss_bssid(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)4560 dbus_bool_t wpas_dbus_getter_bss_bssid(
4561 const struct wpa_dbus_property_desc *property_desc,
4562 DBusMessageIter *iter, DBusError *error, void *user_data)
4563 {
4564 struct bss_handler_args *args = user_data;
4565 struct wpa_bss *res;
4566
4567 res = get_bss_helper(args, error, __func__);
4568 if (!res)
4569 return FALSE;
4570
4571 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
4572 res->bssid, ETH_ALEN,
4573 error);
4574 }
4575
4576
4577 /**
4578 * wpas_dbus_getter_bss_ssid - Return the SSID of a BSS
4579 * @iter: Pointer to incoming dbus message iter
4580 * @error: Location to store error on failure
4581 * @user_data: Function specific data
4582 * Returns: TRUE on success, FALSE on failure
4583 *
4584 * Getter for "SSID" property.
4585 */
wpas_dbus_getter_bss_ssid(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)4586 dbus_bool_t wpas_dbus_getter_bss_ssid(
4587 const struct wpa_dbus_property_desc *property_desc,
4588 DBusMessageIter *iter, DBusError *error, void *user_data)
4589 {
4590 struct bss_handler_args *args = user_data;
4591 struct wpa_bss *res;
4592
4593 res = get_bss_helper(args, error, __func__);
4594 if (!res)
4595 return FALSE;
4596
4597 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
4598 res->ssid, res->ssid_len,
4599 error);
4600 }
4601
4602
4603 /**
4604 * wpas_dbus_getter_bss_privacy - Return the privacy flag of a BSS
4605 * @iter: Pointer to incoming dbus message iter
4606 * @error: Location to store error on failure
4607 * @user_data: Function specific data
4608 * Returns: TRUE on success, FALSE on failure
4609 *
4610 * Getter for "Privacy" property.
4611 */
wpas_dbus_getter_bss_privacy(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)4612 dbus_bool_t wpas_dbus_getter_bss_privacy(
4613 const struct wpa_dbus_property_desc *property_desc,
4614 DBusMessageIter *iter, DBusError *error, void *user_data)
4615 {
4616 struct bss_handler_args *args = user_data;
4617 struct wpa_bss *res;
4618 dbus_bool_t privacy;
4619
4620 res = get_bss_helper(args, error, __func__);
4621 if (!res)
4622 return FALSE;
4623
4624 privacy = (res->caps & IEEE80211_CAP_PRIVACY) ? TRUE : FALSE;
4625 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
4626 &privacy, error);
4627 }
4628
4629
4630 /**
4631 * wpas_dbus_getter_bss_mode - Return the mode of a BSS
4632 * @iter: Pointer to incoming dbus message iter
4633 * @error: Location to store error on failure
4634 * @user_data: Function specific data
4635 * Returns: TRUE on success, FALSE on failure
4636 *
4637 * Getter for "Mode" property.
4638 */
wpas_dbus_getter_bss_mode(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)4639 dbus_bool_t wpas_dbus_getter_bss_mode(
4640 const struct wpa_dbus_property_desc *property_desc,
4641 DBusMessageIter *iter, DBusError *error, void *user_data)
4642 {
4643 struct bss_handler_args *args = user_data;
4644 struct wpa_bss *res;
4645 const char *mode;
4646 const u8 *mesh;
4647
4648 res = get_bss_helper(args, error, __func__);
4649 if (!res)
4650 return FALSE;
4651 if (bss_is_dmg(res)) {
4652 switch (res->caps & IEEE80211_CAP_DMG_MASK) {
4653 case IEEE80211_CAP_DMG_PBSS:
4654 case IEEE80211_CAP_DMG_IBSS:
4655 mode = "ad-hoc";
4656 break;
4657 case IEEE80211_CAP_DMG_AP:
4658 mode = "infrastructure";
4659 break;
4660 default:
4661 mode = "";
4662 break;
4663 }
4664 } else {
4665 mesh = wpa_bss_get_ie(res, WLAN_EID_MESH_ID);
4666 if (mesh)
4667 mode = "mesh";
4668 else if (res->caps & IEEE80211_CAP_IBSS)
4669 mode = "ad-hoc";
4670 else
4671 mode = "infrastructure";
4672 }
4673
4674 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
4675 &mode, error);
4676 }
4677
4678
4679 /**
4680 * wpas_dbus_getter_bss_level - Return the signal strength of a BSS
4681 * @iter: Pointer to incoming dbus message iter
4682 * @error: Location to store error on failure
4683 * @user_data: Function specific data
4684 * Returns: TRUE on success, FALSE on failure
4685 *
4686 * Getter for "Level" property.
4687 */
wpas_dbus_getter_bss_signal(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)4688 dbus_bool_t wpas_dbus_getter_bss_signal(
4689 const struct wpa_dbus_property_desc *property_desc,
4690 DBusMessageIter *iter, DBusError *error, void *user_data)
4691 {
4692 struct bss_handler_args *args = user_data;
4693 struct wpa_bss *res;
4694 s16 level;
4695
4696 res = get_bss_helper(args, error, __func__);
4697 if (!res)
4698 return FALSE;
4699
4700 level = (s16) res->level;
4701 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT16,
4702 &level, error);
4703 }
4704
4705
4706 /**
4707 * wpas_dbus_getter_bss_frequency - Return the frequency of a BSS
4708 * @iter: Pointer to incoming dbus message iter
4709 * @error: Location to store error on failure
4710 * @user_data: Function specific data
4711 * Returns: TRUE on success, FALSE on failure
4712 *
4713 * Getter for "Frequency" property.
4714 */
wpas_dbus_getter_bss_frequency(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)4715 dbus_bool_t wpas_dbus_getter_bss_frequency(
4716 const struct wpa_dbus_property_desc *property_desc,
4717 DBusMessageIter *iter, DBusError *error, void *user_data)
4718 {
4719 struct bss_handler_args *args = user_data;
4720 struct wpa_bss *res;
4721 u16 freq;
4722
4723 res = get_bss_helper(args, error, __func__);
4724 if (!res)
4725 return FALSE;
4726
4727 freq = (u16) res->freq;
4728 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
4729 &freq, error);
4730 }
4731
4732
cmp_u8s_desc(const void * a,const void * b)4733 static int cmp_u8s_desc(const void *a, const void *b)
4734 {
4735 return (*(u8 *) b - *(u8 *) a);
4736 }
4737
4738
4739 /**
4740 * wpas_dbus_getter_bss_rates - Return available bit rates of a BSS
4741 * @iter: Pointer to incoming dbus message iter
4742 * @error: Location to store error on failure
4743 * @user_data: Function specific data
4744 * Returns: TRUE on success, FALSE on failure
4745 *
4746 * Getter for "Rates" property.
4747 */
wpas_dbus_getter_bss_rates(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)4748 dbus_bool_t wpas_dbus_getter_bss_rates(
4749 const struct wpa_dbus_property_desc *property_desc,
4750 DBusMessageIter *iter, DBusError *error, void *user_data)
4751 {
4752 struct bss_handler_args *args = user_data;
4753 struct wpa_bss *res;
4754 u8 *ie_rates = NULL;
4755 u32 *real_rates;
4756 int rates_num, i;
4757 dbus_bool_t success = FALSE;
4758
4759 res = get_bss_helper(args, error, __func__);
4760 if (!res)
4761 return FALSE;
4762
4763 rates_num = wpa_bss_get_bit_rates(res, &ie_rates);
4764 if (rates_num < 0)
4765 return FALSE;
4766
4767 qsort(ie_rates, rates_num, 1, cmp_u8s_desc);
4768
4769 real_rates = os_malloc(sizeof(u32) * rates_num);
4770 if (!real_rates) {
4771 os_free(ie_rates);
4772 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
4773 return FALSE;
4774 }
4775
4776 for (i = 0; i < rates_num; i++)
4777 real_rates[i] = ie_rates[i] * 500000;
4778
4779 success = wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_UINT32,
4780 real_rates, rates_num,
4781 error);
4782
4783 os_free(ie_rates);
4784 os_free(real_rates);
4785 return success;
4786 }
4787
4788
wpas_dbus_get_bss_security_prop(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,struct wpa_ie_data * ie_data,DBusError * error)4789 static dbus_bool_t wpas_dbus_get_bss_security_prop(
4790 const struct wpa_dbus_property_desc *property_desc,
4791 DBusMessageIter *iter, struct wpa_ie_data *ie_data, DBusError *error)
4792 {
4793 DBusMessageIter iter_dict, variant_iter;
4794 const char *group;
4795 const char *pairwise[5]; /* max 5 pairwise ciphers is supported */
4796 const char *key_mgmt[16]; /* max 16 key managements may be supported */
4797 int n;
4798
4799 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
4800 "a{sv}", &variant_iter))
4801 goto nomem;
4802
4803 if (!wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
4804 goto nomem;
4805
4806 /*
4807 * KeyMgmt
4808 *
4809 * When adding a new entry here, please take care to extend key_mgmt[]
4810 * and keep documentation in doc/dbus.doxygen up to date.
4811 */
4812 n = 0;
4813 if (ie_data->key_mgmt & WPA_KEY_MGMT_PSK)
4814 key_mgmt[n++] = "wpa-psk";
4815 if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_PSK)
4816 key_mgmt[n++] = "wpa-ft-psk";
4817 if (ie_data->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
4818 key_mgmt[n++] = "wpa-psk-sha256";
4819 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X)
4820 key_mgmt[n++] = "wpa-eap";
4821 if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X)
4822 key_mgmt[n++] = "wpa-ft-eap";
4823 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256)
4824 key_mgmt[n++] = "wpa-eap-sha256";
4825 #ifdef CONFIG_SUITEB
4826 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B)
4827 key_mgmt[n++] = "wpa-eap-suite-b";
4828 #endif /* CONFIG_SUITEB */
4829 #ifdef CONFIG_SUITEB192
4830 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
4831 key_mgmt[n++] = "wpa-eap-suite-b-192";
4832 #endif /* CONFIG_SUITEB192 */
4833 #ifdef CONFIG_FILS
4834 if (ie_data->key_mgmt & WPA_KEY_MGMT_FILS_SHA256)
4835 key_mgmt[n++] = "wpa-fils-sha256";
4836 if (ie_data->key_mgmt & WPA_KEY_MGMT_FILS_SHA384)
4837 key_mgmt[n++] = "wpa-fils-sha384";
4838 if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA256)
4839 key_mgmt[n++] = "wpa-ft-fils-sha256";
4840 if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA384)
4841 key_mgmt[n++] = "wpa-ft-fils-sha384";
4842 #endif /* CONFIG_FILS */
4843 #ifdef CONFIG_SAE
4844 if (ie_data->key_mgmt & WPA_KEY_MGMT_SAE)
4845 key_mgmt[n++] = "sae";
4846 if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_SAE)
4847 key_mgmt[n++] = "ft-sae";
4848 #endif /* CONFIG_SAE */
4849 #ifdef CONFIG_OWE
4850 if (ie_data->key_mgmt & WPA_KEY_MGMT_OWE)
4851 key_mgmt[n++] = "owe";
4852 #endif /* CONFIG_OWE */
4853 if (ie_data->key_mgmt & WPA_KEY_MGMT_NONE)
4854 key_mgmt[n++] = "wpa-none";
4855
4856 if (!wpa_dbus_dict_append_string_array(&iter_dict, "KeyMgmt",
4857 key_mgmt, n))
4858 goto nomem;
4859
4860 /* Group */
4861 switch (ie_data->group_cipher) {
4862 #ifdef CONFIG_WEP
4863 case WPA_CIPHER_WEP40:
4864 group = "wep40";
4865 break;
4866 case WPA_CIPHER_WEP104:
4867 group = "wep104";
4868 break;
4869 #endif /* CONFIG_WEP */
4870 #ifndef CONFIG_NO_TKIP
4871 case WPA_CIPHER_TKIP:
4872 group = "tkip";
4873 break;
4874 #endif /* CONFIG_NO_TKIP */
4875 case WPA_CIPHER_CCMP:
4876 group = "ccmp";
4877 break;
4878 case WPA_CIPHER_GCMP:
4879 group = "gcmp";
4880 break;
4881 case WPA_CIPHER_CCMP_256:
4882 group = "ccmp-256";
4883 break;
4884 case WPA_CIPHER_GCMP_256:
4885 group = "gcmp-256";
4886 break;
4887 default:
4888 group = "";
4889 break;
4890 }
4891
4892 if (!wpa_dbus_dict_append_string(&iter_dict, "Group", group))
4893 goto nomem;
4894
4895 /* Pairwise */
4896 n = 0;
4897 #ifndef CONFIG_NO_TKIP
4898 if (ie_data->pairwise_cipher & WPA_CIPHER_TKIP)
4899 pairwise[n++] = "tkip";
4900 #endif /* CONFIG_NO_TKIP */
4901 if (ie_data->pairwise_cipher & WPA_CIPHER_CCMP)
4902 pairwise[n++] = "ccmp";
4903 if (ie_data->pairwise_cipher & WPA_CIPHER_GCMP)
4904 pairwise[n++] = "gcmp";
4905 if (ie_data->pairwise_cipher & WPA_CIPHER_CCMP_256)
4906 pairwise[n++] = "ccmp-256";
4907 if (ie_data->pairwise_cipher & WPA_CIPHER_GCMP_256)
4908 pairwise[n++] = "gcmp-256";
4909
4910 if (!wpa_dbus_dict_append_string_array(&iter_dict, "Pairwise",
4911 pairwise, n))
4912 goto nomem;
4913
4914 /* Management group (RSN only) */
4915 if (ie_data->proto == WPA_PROTO_RSN) {
4916 switch (ie_data->mgmt_group_cipher) {
4917 case WPA_CIPHER_AES_128_CMAC:
4918 group = "aes128cmac";
4919 break;
4920 default:
4921 group = "";
4922 break;
4923 }
4924
4925 if (!wpa_dbus_dict_append_string(&iter_dict, "MgmtGroup",
4926 group))
4927 goto nomem;
4928 }
4929
4930 if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict) ||
4931 !dbus_message_iter_close_container(iter, &variant_iter))
4932 goto nomem;
4933
4934 return TRUE;
4935
4936 nomem:
4937 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
4938 return FALSE;
4939 }
4940
4941
4942 /**
4943 * wpas_dbus_getter_bss_wpa - Return the WPA options of a BSS
4944 * @iter: Pointer to incoming dbus message iter
4945 * @error: Location to store error on failure
4946 * @user_data: Function specific data
4947 * Returns: TRUE on success, FALSE on failure
4948 *
4949 * Getter for "WPA" property.
4950 */
wpas_dbus_getter_bss_wpa(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)4951 dbus_bool_t wpas_dbus_getter_bss_wpa(
4952 const struct wpa_dbus_property_desc *property_desc,
4953 DBusMessageIter *iter, DBusError *error, void *user_data)
4954 {
4955 struct bss_handler_args *args = user_data;
4956 struct wpa_bss *res;
4957 struct wpa_ie_data wpa_data;
4958 const u8 *ie;
4959
4960 res = get_bss_helper(args, error, __func__);
4961 if (!res)
4962 return FALSE;
4963
4964 os_memset(&wpa_data, 0, sizeof(wpa_data));
4965 ie = wpa_bss_get_vendor_ie(res, WPA_IE_VENDOR_TYPE);
4966 if (ie && wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0) {
4967 dbus_set_error_const(error, DBUS_ERROR_FAILED,
4968 "failed to parse WPA IE");
4969 return FALSE;
4970 }
4971
4972 return wpas_dbus_get_bss_security_prop(property_desc, iter, &wpa_data, error);
4973 }
4974
4975
4976 /**
4977 * wpas_dbus_getter_bss_rsn - Return the RSN options of a BSS
4978 * @iter: Pointer to incoming dbus message iter
4979 * @error: Location to store error on failure
4980 * @user_data: Function specific data
4981 * Returns: TRUE on success, FALSE on failure
4982 *
4983 * Getter for "RSN" property.
4984 */
wpas_dbus_getter_bss_rsn(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)4985 dbus_bool_t wpas_dbus_getter_bss_rsn(
4986 const struct wpa_dbus_property_desc *property_desc,
4987 DBusMessageIter *iter, DBusError *error, void *user_data)
4988 {
4989 struct bss_handler_args *args = user_data;
4990 struct wpa_bss *res;
4991 struct wpa_ie_data wpa_data;
4992 const u8 *ie;
4993
4994 res = get_bss_helper(args, error, __func__);
4995 if (!res)
4996 return FALSE;
4997
4998 os_memset(&wpa_data, 0, sizeof(wpa_data));
4999 ie = wpa_bss_get_ie(res, WLAN_EID_RSN);
5000 if (ie && wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0) {
5001 dbus_set_error_const(error, DBUS_ERROR_FAILED,
5002 "failed to parse RSN IE");
5003 return FALSE;
5004 }
5005
5006 return wpas_dbus_get_bss_security_prop(property_desc, iter, &wpa_data, error);
5007 }
5008
5009
5010 /**
5011 * wpas_dbus_getter_bss_wps - Return the WPS options of a BSS
5012 * @iter: Pointer to incoming dbus message iter
5013 * @error: Location to store error on failure
5014 * @user_data: Function specific data
5015 * Returns: TRUE on success, FALSE on failure
5016 *
5017 * Getter for "WPS" property.
5018 */
wpas_dbus_getter_bss_wps(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)5019 dbus_bool_t wpas_dbus_getter_bss_wps(
5020 const struct wpa_dbus_property_desc *property_desc,
5021 DBusMessageIter *iter, DBusError *error, void *user_data)
5022 {
5023 struct bss_handler_args *args = user_data;
5024 struct wpa_bss *res;
5025 #ifdef CONFIG_WPS
5026 struct wpabuf *wps_ie;
5027 #endif /* CONFIG_WPS */
5028 DBusMessageIter iter_dict, variant_iter;
5029 int wps_support = 0;
5030 const char *type = "";
5031
5032 res = get_bss_helper(args, error, __func__);
5033 if (!res)
5034 return FALSE;
5035
5036 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
5037 "a{sv}", &variant_iter) ||
5038 !wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
5039 goto nomem;
5040
5041 #ifdef CONFIG_WPS
5042 wps_ie = wpa_bss_get_vendor_ie_multi(res, WPS_IE_VENDOR_TYPE);
5043 if (wps_ie) {
5044 wps_support = 1;
5045 if (wps_is_selected_pbc_registrar(wps_ie))
5046 type = "pbc";
5047 else if (wps_is_selected_pin_registrar(wps_ie))
5048 type = "pin";
5049
5050 wpabuf_free(wps_ie);
5051 }
5052 #endif /* CONFIG_WPS */
5053
5054 if ((wps_support && !wpa_dbus_dict_append_string(&iter_dict, "Type", type)) ||
5055 !wpa_dbus_dict_close_write(&variant_iter, &iter_dict) ||
5056 !dbus_message_iter_close_container(iter, &variant_iter))
5057 goto nomem;
5058
5059 return TRUE;
5060
5061 nomem:
5062 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
5063 return FALSE;
5064 }
5065
5066
5067 /**
5068 * wpas_dbus_getter_bss_ies - Return all IEs of a BSS
5069 * @iter: Pointer to incoming dbus message iter
5070 * @error: Location to store error on failure
5071 * @user_data: Function specific data
5072 * Returns: TRUE on success, FALSE on failure
5073 *
5074 * Getter for "IEs" property.
5075 */
wpas_dbus_getter_bss_ies(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)5076 dbus_bool_t wpas_dbus_getter_bss_ies(
5077 const struct wpa_dbus_property_desc *property_desc,
5078 DBusMessageIter *iter, DBusError *error, void *user_data)
5079 {
5080 struct bss_handler_args *args = user_data;
5081 struct wpa_bss *res;
5082
5083 res = get_bss_helper(args, error, __func__);
5084 if (!res)
5085 return FALSE;
5086
5087 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
5088 wpa_bss_ie_ptr(res),
5089 res->ie_len, error);
5090 }
5091
5092
5093 /**
5094 * wpas_dbus_getter_bss_age - Return time in seconds since BSS was last seen
5095 * @iter: Pointer to incoming dbus message iter
5096 * @error: Location to store error on failure
5097 * @user_data: Function specific data
5098 * Returns: TRUE on success, FALSE on failure
5099 *
5100 * Getter for BSS age
5101 */
wpas_dbus_getter_bss_age(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)5102 dbus_bool_t wpas_dbus_getter_bss_age(
5103 const struct wpa_dbus_property_desc *property_desc,
5104 DBusMessageIter *iter, DBusError *error, void *user_data)
5105 {
5106 struct bss_handler_args *args = user_data;
5107 struct wpa_bss *res;
5108 struct os_reltime now, diff = { 0, 0 };
5109 u32 age;
5110
5111 res = get_bss_helper(args, error, __func__);
5112 if (!res)
5113 return FALSE;
5114
5115 os_get_reltime(&now);
5116 os_reltime_sub(&now, &res->last_update, &diff);
5117 age = diff.sec > 0 ? diff.sec : 0;
5118 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32, &age,
5119 error);
5120 }
5121
5122
5123 /**
5124 * wpas_dbus_getter_enabled - Check whether network is enabled or disabled
5125 * @iter: Pointer to incoming dbus message iter
5126 * @error: Location to store error on failure
5127 * @user_data: Function specific data
5128 * Returns: TRUE on success, FALSE on failure
5129 *
5130 * Getter for "enabled" property of a configured network.
5131 */
wpas_dbus_getter_enabled(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)5132 dbus_bool_t wpas_dbus_getter_enabled(
5133 const struct wpa_dbus_property_desc *property_desc,
5134 DBusMessageIter *iter, DBusError *error, void *user_data)
5135 {
5136 struct network_handler_args *net = user_data;
5137 dbus_bool_t enabled = net->ssid->disabled ? FALSE : TRUE;
5138
5139 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
5140 &enabled, error);
5141 }
5142
5143
5144 /**
5145 * wpas_dbus_setter_enabled - Mark a configured network as enabled or disabled
5146 * @iter: Pointer to incoming dbus message iter
5147 * @error: Location to store error on failure
5148 * @user_data: Function specific data
5149 * Returns: TRUE on success, FALSE on failure
5150 *
5151 * Setter for "Enabled" property of a configured network.
5152 */
wpas_dbus_setter_enabled(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)5153 dbus_bool_t wpas_dbus_setter_enabled(
5154 const struct wpa_dbus_property_desc *property_desc,
5155 DBusMessageIter *iter, DBusError *error, void *user_data)
5156 {
5157 struct network_handler_args *net = user_data;
5158 struct wpa_supplicant *wpa_s;
5159 struct wpa_ssid *ssid;
5160 dbus_bool_t enable;
5161
5162 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
5163 &enable))
5164 return FALSE;
5165
5166 wpa_s = net->wpa_s;
5167 ssid = net->ssid;
5168
5169 if (enable)
5170 wpa_supplicant_enable_network(wpa_s, ssid);
5171 else
5172 wpa_supplicant_disable_network(wpa_s, ssid);
5173
5174 return TRUE;
5175 }
5176
5177
5178 /**
5179 * wpas_dbus_getter_network_properties - Get options for a configured network
5180 * @iter: Pointer to incoming dbus message iter
5181 * @error: Location to store error on failure
5182 * @user_data: Function specific data
5183 * Returns: TRUE on success, FALSE on failure
5184 *
5185 * Getter for "Properties" property of a configured network.
5186 */
wpas_dbus_getter_network_properties(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)5187 dbus_bool_t wpas_dbus_getter_network_properties(
5188 const struct wpa_dbus_property_desc *property_desc,
5189 DBusMessageIter *iter, DBusError *error, void *user_data)
5190 {
5191 struct network_handler_args *net = user_data;
5192 DBusMessageIter variant_iter, dict_iter;
5193 char **iterator;
5194 char **props = wpa_config_get_all(net->ssid, 1);
5195 dbus_bool_t success = FALSE;
5196
5197 if (!props) {
5198 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
5199 return FALSE;
5200 }
5201
5202 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a{sv}",
5203 &variant_iter) ||
5204 !wpa_dbus_dict_open_write(&variant_iter, &dict_iter)) {
5205 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
5206 goto out;
5207 }
5208
5209 iterator = props;
5210 while (*iterator) {
5211 if (!wpa_dbus_dict_append_string(&dict_iter, *iterator,
5212 *(iterator + 1))) {
5213 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
5214 "no memory");
5215 goto out;
5216 }
5217 iterator += 2;
5218 }
5219
5220
5221 if (!wpa_dbus_dict_close_write(&variant_iter, &dict_iter) ||
5222 !dbus_message_iter_close_container(iter, &variant_iter)) {
5223 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
5224 goto out;
5225 }
5226
5227 success = TRUE;
5228
5229 out:
5230 iterator = props;
5231 while (*iterator) {
5232 os_free(*iterator);
5233 iterator++;
5234 }
5235 os_free(props);
5236 return success;
5237 }
5238
5239
5240 /**
5241 * wpas_dbus_setter_network_properties - Set options for a configured network
5242 * @iter: Pointer to incoming dbus message iter
5243 * @error: Location to store error on failure
5244 * @user_data: Function specific data
5245 * Returns: TRUE on success, FALSE on failure
5246 *
5247 * Setter for "Properties" property of a configured network.
5248 */
wpas_dbus_setter_network_properties(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)5249 dbus_bool_t wpas_dbus_setter_network_properties(
5250 const struct wpa_dbus_property_desc *property_desc,
5251 DBusMessageIter *iter, DBusError *error, void *user_data)
5252 {
5253 struct network_handler_args *net = user_data;
5254 struct wpa_ssid *ssid = net->ssid;
5255 DBusMessageIter variant_iter;
5256
5257 dbus_message_iter_recurse(iter, &variant_iter);
5258 return set_network_properties(net->wpa_s, ssid, &variant_iter, error);
5259 }
5260
5261
5262 #ifdef CONFIG_AP
5263
wpas_dbus_handler_subscribe_preq(DBusMessage * message,struct wpa_supplicant * wpa_s)5264 DBusMessage * wpas_dbus_handler_subscribe_preq(
5265 DBusMessage *message, struct wpa_supplicant *wpa_s)
5266 {
5267 struct wpas_dbus_priv *priv = wpa_s->global->dbus;
5268 char *name;
5269
5270 if (wpa_s->preq_notify_peer != NULL) {
5271 if (os_strcmp(dbus_message_get_sender(message),
5272 wpa_s->preq_notify_peer) == 0)
5273 return NULL;
5274
5275 return dbus_message_new_error(message,
5276 WPAS_DBUS_ERROR_SUBSCRIPTION_IN_USE,
5277 "Another application is already subscribed");
5278 }
5279
5280 name = os_strdup(dbus_message_get_sender(message));
5281 if (!name)
5282 return wpas_dbus_error_no_memory(message);
5283
5284 wpa_s->preq_notify_peer = name;
5285
5286 /* Subscribe to clean up if application closes socket */
5287 wpas_dbus_subscribe_noc(priv);
5288
5289 /*
5290 * Double-check it's still alive to make sure that we didn't
5291 * miss the NameOwnerChanged signal, e.g. while strdup'ing.
5292 */
5293 if (!dbus_bus_name_has_owner(priv->con, name, NULL)) {
5294 /*
5295 * Application no longer exists, clean up.
5296 * The return value is irrelevant now.
5297 *
5298 * Need to check if the NameOwnerChanged handling
5299 * already cleaned up because we have processed
5300 * DBus messages while checking if the name still
5301 * has an owner.
5302 */
5303 if (!wpa_s->preq_notify_peer)
5304 return NULL;
5305 os_free(wpa_s->preq_notify_peer);
5306 wpa_s->preq_notify_peer = NULL;
5307 wpas_dbus_unsubscribe_noc(priv);
5308 }
5309
5310 return NULL;
5311 }
5312
5313
wpas_dbus_handler_unsubscribe_preq(DBusMessage * message,struct wpa_supplicant * wpa_s)5314 DBusMessage * wpas_dbus_handler_unsubscribe_preq(
5315 DBusMessage *message, struct wpa_supplicant *wpa_s)
5316 {
5317 struct wpas_dbus_priv *priv = wpa_s->global->dbus;
5318
5319 if (!wpa_s->preq_notify_peer)
5320 return dbus_message_new_error(message,
5321 WPAS_DBUS_ERROR_NO_SUBSCRIPTION,
5322 "Not subscribed");
5323
5324 if (os_strcmp(wpa_s->preq_notify_peer,
5325 dbus_message_get_sender(message)))
5326 return dbus_message_new_error(message,
5327 WPAS_DBUS_ERROR_SUBSCRIPTION_EPERM,
5328 "Can't unsubscribe others");
5329
5330 os_free(wpa_s->preq_notify_peer);
5331 wpa_s->preq_notify_peer = NULL;
5332 wpas_dbus_unsubscribe_noc(priv);
5333 return NULL;
5334 }
5335
5336
wpas_dbus_signal_preq(struct wpa_supplicant * wpa_s,const u8 * addr,const u8 * dst,const u8 * bssid,const u8 * ie,size_t ie_len,u32 ssi_signal)5337 void wpas_dbus_signal_preq(struct wpa_supplicant *wpa_s,
5338 const u8 *addr, const u8 *dst, const u8 *bssid,
5339 const u8 *ie, size_t ie_len, u32 ssi_signal)
5340 {
5341 DBusMessage *msg;
5342 DBusMessageIter iter, dict_iter;
5343 struct wpas_dbus_priv *priv = wpa_s->global->dbus;
5344
5345 /* Do nothing if the control interface is not turned on */
5346 if (priv == NULL || !wpa_s->dbus_new_path)
5347 return;
5348
5349 if (wpa_s->preq_notify_peer == NULL)
5350 return;
5351
5352 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
5353 WPAS_DBUS_NEW_IFACE_INTERFACE,
5354 "ProbeRequest");
5355 if (msg == NULL)
5356 return;
5357
5358 dbus_message_set_destination(msg, wpa_s->preq_notify_peer);
5359
5360 dbus_message_iter_init_append(msg, &iter);
5361
5362 if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
5363 (addr && !wpa_dbus_dict_append_byte_array(&dict_iter, "addr",
5364 (const char *) addr,
5365 ETH_ALEN)) ||
5366 (dst && !wpa_dbus_dict_append_byte_array(&dict_iter, "dst",
5367 (const char *) dst,
5368 ETH_ALEN)) ||
5369 (bssid && !wpa_dbus_dict_append_byte_array(&dict_iter, "bssid",
5370 (const char *) bssid,
5371 ETH_ALEN)) ||
5372 (ie && ie_len && !wpa_dbus_dict_append_byte_array(&dict_iter, "ies",
5373 (const char *) ie,
5374 ie_len)) ||
5375 (ssi_signal && !wpa_dbus_dict_append_int32(&dict_iter, "signal",
5376 ssi_signal)) ||
5377 !wpa_dbus_dict_close_write(&iter, &dict_iter))
5378 goto fail;
5379
5380 dbus_connection_send(priv->con, msg, NULL);
5381 goto out;
5382 fail:
5383 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
5384 out:
5385 dbus_message_unref(msg);
5386 }
5387
5388 #endif /* CONFIG_AP */
5389
5390
wpas_dbus_handler_vendor_elem_add(DBusMessage * message,struct wpa_supplicant * wpa_s)5391 DBusMessage * wpas_dbus_handler_vendor_elem_add(DBusMessage *message,
5392 struct wpa_supplicant *wpa_s)
5393 {
5394 u8 *ielems;
5395 int len;
5396 struct ieee802_11_elems elems;
5397 dbus_int32_t frame_id;
5398 DBusMessageIter iter, array;
5399
5400 dbus_message_iter_init(message, &iter);
5401 dbus_message_iter_get_basic(&iter, &frame_id);
5402 if (frame_id < 0 || frame_id >= NUM_VENDOR_ELEM_FRAMES) {
5403 return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
5404 "Invalid ID");
5405 }
5406
5407 dbus_message_iter_next(&iter);
5408 dbus_message_iter_recurse(&iter, &array);
5409 dbus_message_iter_get_fixed_array(&array, &ielems, &len);
5410 if (!ielems || len == 0) {
5411 return dbus_message_new_error(
5412 message, DBUS_ERROR_INVALID_ARGS, "Invalid value");
5413 }
5414
5415 if (ieee802_11_parse_elems(ielems, len, &elems, 0) == ParseFailed) {
5416 return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
5417 "Parse error");
5418 }
5419
5420 wpa_s = wpas_vendor_elem(wpa_s, frame_id);
5421 if (!wpa_s->vendor_elem[frame_id]) {
5422 wpa_s->vendor_elem[frame_id] = wpabuf_alloc_copy(ielems, len);
5423 wpas_vendor_elem_update(wpa_s);
5424 return NULL;
5425 }
5426
5427 if (wpabuf_resize(&wpa_s->vendor_elem[frame_id], len) < 0) {
5428 return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
5429 "Resize error");
5430 }
5431
5432 wpabuf_put_data(wpa_s->vendor_elem[frame_id], ielems, len);
5433 wpas_vendor_elem_update(wpa_s);
5434 return NULL;
5435 }
5436
5437
wpas_dbus_handler_vendor_elem_get(DBusMessage * message,struct wpa_supplicant * wpa_s)5438 DBusMessage * wpas_dbus_handler_vendor_elem_get(DBusMessage *message,
5439 struct wpa_supplicant *wpa_s)
5440 {
5441 DBusMessage *reply;
5442 DBusMessageIter iter, array_iter;
5443 dbus_int32_t frame_id;
5444 const u8 *elem;
5445 size_t elem_len;
5446
5447 dbus_message_iter_init(message, &iter);
5448 dbus_message_iter_get_basic(&iter, &frame_id);
5449
5450 if (frame_id < 0 || frame_id >= NUM_VENDOR_ELEM_FRAMES) {
5451 return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
5452 "Invalid ID");
5453 }
5454
5455 wpa_s = wpas_vendor_elem(wpa_s, frame_id);
5456 if (!wpa_s->vendor_elem[frame_id]) {
5457 return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
5458 "ID value does not exist");
5459 }
5460
5461 reply = dbus_message_new_method_return(message);
5462 if (!reply)
5463 return wpas_dbus_error_no_memory(message);
5464
5465 dbus_message_iter_init_append(reply, &iter);
5466
5467 elem = wpabuf_head_u8(wpa_s->vendor_elem[frame_id]);
5468 elem_len = wpabuf_len(wpa_s->vendor_elem[frame_id]);
5469
5470 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
5471 DBUS_TYPE_BYTE_AS_STRING,
5472 &array_iter) ||
5473 !dbus_message_iter_append_fixed_array(&array_iter, DBUS_TYPE_BYTE,
5474 &elem, elem_len) ||
5475 !dbus_message_iter_close_container(&iter, &array_iter)) {
5476 dbus_message_unref(reply);
5477 reply = wpas_dbus_error_no_memory(message);
5478 }
5479
5480 return reply;
5481 }
5482
5483
wpas_dbus_handler_vendor_elem_remove(DBusMessage * message,struct wpa_supplicant * wpa_s)5484 DBusMessage * wpas_dbus_handler_vendor_elem_remove(DBusMessage *message,
5485 struct wpa_supplicant *wpa_s)
5486 {
5487 u8 *ielems;
5488 int len;
5489 struct ieee802_11_elems elems;
5490 DBusMessageIter iter, array;
5491 dbus_int32_t frame_id;
5492
5493 dbus_message_iter_init(message, &iter);
5494 dbus_message_iter_get_basic(&iter, &frame_id);
5495 if (frame_id < 0 || frame_id >= NUM_VENDOR_ELEM_FRAMES) {
5496 return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
5497 "Invalid ID");
5498 }
5499
5500 dbus_message_iter_next(&iter);
5501 dbus_message_iter_recurse(&iter, &array);
5502 dbus_message_iter_get_fixed_array(&array, &ielems, &len);
5503 if (!ielems || len == 0) {
5504 return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
5505 "Invalid value");
5506 }
5507
5508 wpa_s = wpas_vendor_elem(wpa_s, frame_id);
5509
5510 if (len == 1 && *ielems == '*') {
5511 wpabuf_free(wpa_s->vendor_elem[frame_id]);
5512 wpa_s->vendor_elem[frame_id] = NULL;
5513 wpas_vendor_elem_update(wpa_s);
5514 return NULL;
5515 }
5516
5517 if (!wpa_s->vendor_elem[frame_id]) {
5518 return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
5519 "ID value does not exist");
5520 }
5521
5522 if (ieee802_11_parse_elems(ielems, len, &elems, 0) == ParseFailed) {
5523 return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
5524 "Parse error");
5525 }
5526
5527 if (wpas_vendor_elem_remove(wpa_s, frame_id, ielems, len) == 0)
5528 return NULL;
5529
5530 return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
5531 "Not found");
5532 }
5533
5534
5535 #ifdef CONFIG_MESH
5536
5537 /**
5538 * wpas_dbus_getter_mesh_peers - Get connected mesh peers
5539 * @iter: Pointer to incoming dbus message iter
5540 * @error: Location to store error on failure
5541 * @user_data: Function specific data
5542 * Returns: TRUE on success, FALSE on failure
5543 *
5544 * Getter for "MeshPeers" property.
5545 */
wpas_dbus_getter_mesh_peers(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)5546 dbus_bool_t wpas_dbus_getter_mesh_peers(
5547 const struct wpa_dbus_property_desc *property_desc,
5548 DBusMessageIter *iter, DBusError *error, void *user_data)
5549 {
5550 struct wpa_supplicant *wpa_s = user_data;
5551 struct hostapd_data *hapd;
5552 struct sta_info *sta;
5553 DBusMessageIter variant_iter, array_iter;
5554 int i;
5555 DBusMessageIter inner_array_iter;
5556
5557 if (!wpa_s->ifmsh)
5558 return FALSE;
5559 hapd = wpa_s->ifmsh->bss[0];
5560
5561 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
5562 DBUS_TYPE_ARRAY_AS_STRING
5563 DBUS_TYPE_ARRAY_AS_STRING
5564 DBUS_TYPE_BYTE_AS_STRING,
5565 &variant_iter) ||
5566 !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
5567 DBUS_TYPE_ARRAY_AS_STRING
5568 DBUS_TYPE_BYTE_AS_STRING,
5569 &array_iter))
5570 return FALSE;
5571
5572 for (sta = hapd->sta_list; sta; sta = sta->next) {
5573 if (!dbus_message_iter_open_container(
5574 &array_iter, DBUS_TYPE_ARRAY,
5575 DBUS_TYPE_BYTE_AS_STRING,
5576 &inner_array_iter))
5577 return FALSE;
5578
5579 for (i = 0; i < ETH_ALEN; i++) {
5580 if (!dbus_message_iter_append_basic(&inner_array_iter,
5581 DBUS_TYPE_BYTE,
5582 &(sta->addr[i])))
5583 return FALSE;
5584 }
5585
5586 if (!dbus_message_iter_close_container(
5587 &array_iter, &inner_array_iter))
5588 return FALSE;
5589 }
5590
5591 if (!dbus_message_iter_close_container(&variant_iter, &array_iter) ||
5592 !dbus_message_iter_close_container(iter, &variant_iter))
5593 return FALSE;
5594
5595 return TRUE;
5596 }
5597
5598
5599 /**
5600 * wpas_dbus_getter_mesh_group - Get mesh group
5601 * @iter: Pointer to incoming dbus message iter
5602 * @error: Location to store error on failure
5603 * @user_data: Function specific data
5604 * Returns: TRUE on success, FALSE on failure
5605 *
5606 * Getter for "MeshGroup" property.
5607 */
wpas_dbus_getter_mesh_group(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)5608 dbus_bool_t wpas_dbus_getter_mesh_group(
5609 const struct wpa_dbus_property_desc *property_desc,
5610 DBusMessageIter *iter, DBusError *error, void *user_data)
5611 {
5612 struct wpa_supplicant *wpa_s = user_data;
5613 struct wpa_ssid *ssid = wpa_s->current_ssid;
5614
5615 if (!wpa_s->ifmsh || !ssid)
5616 return FALSE;
5617
5618 if (!wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
5619 (char *) ssid->ssid,
5620 ssid->ssid_len, error)) {
5621 dbus_set_error(error, DBUS_ERROR_FAILED,
5622 "%s: error constructing reply", __func__);
5623 return FALSE;
5624 }
5625
5626 return TRUE;
5627 }
5628
5629 #endif /* CONFIG_MESH */
5630