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