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