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