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