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