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