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