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