Line data Source code
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 "../config.h"
19 : #include "../wpa_supplicant_i.h"
20 : #include "../driver_i.h"
21 : #include "../notify.h"
22 : #include "../bss.h"
23 : #include "../scan.h"
24 : #include "../autoscan.h"
25 : #include "dbus_new_helpers.h"
26 : #include "dbus_new.h"
27 : #include "dbus_new_handlers.h"
28 : #include "dbus_dict_helpers.h"
29 : #include "dbus_common_i.h"
30 : #include "drivers/driver.h"
31 :
32 : static const char * const debug_strings[] = {
33 : "excessive", "msgdump", "debug", "info", "warning", "error", NULL
34 : };
35 :
36 :
37 : /**
38 : * wpas_dbus_error_unknown_error - Return a new UnknownError error message
39 : * @message: Pointer to incoming dbus message this error refers to
40 : * @arg: Optional string appended to error message
41 : * Returns: a dbus error message
42 : *
43 : * Convenience function to create and return an UnknownError
44 : */
45 35 : DBusMessage * wpas_dbus_error_unknown_error(DBusMessage *message,
46 : const char *arg)
47 : {
48 35 : return dbus_message_new_error(message, WPAS_DBUS_ERROR_UNKNOWN_ERROR,
49 : arg);
50 : }
51 :
52 :
53 : /**
54 : * wpas_dbus_error_iface_unknown - Return a new invalid interface error message
55 : * @message: Pointer to incoming dbus message this error refers to
56 : * Returns: A dbus error message
57 : *
58 : * Convenience function to create and return an invalid interface error
59 : */
60 2 : static DBusMessage * wpas_dbus_error_iface_unknown(DBusMessage *message)
61 : {
62 2 : return dbus_message_new_error(
63 : message, WPAS_DBUS_ERROR_IFACE_UNKNOWN,
64 : "wpa_supplicant knows nothing about this interface.");
65 : }
66 :
67 :
68 : /**
69 : * wpas_dbus_error_network_unknown - Return a new NetworkUnknown error message
70 : * @message: Pointer to incoming dbus message this error refers to
71 : * Returns: a dbus error message
72 : *
73 : * Convenience function to create and return an invalid network error
74 : */
75 2 : static DBusMessage * wpas_dbus_error_network_unknown(DBusMessage *message)
76 : {
77 2 : return dbus_message_new_error(
78 : message, WPAS_DBUS_ERROR_NETWORK_UNKNOWN,
79 : "There is no such a network in this interface.");
80 : }
81 :
82 :
83 : /**
84 : * wpas_dbus_error_invalid_args - Return a new InvalidArgs error message
85 : * @message: Pointer to incoming dbus message this error refers to
86 : * Returns: a dbus error message
87 : *
88 : * Convenience function to create and return an invalid options error
89 : */
90 123 : DBusMessage * wpas_dbus_error_invalid_args(DBusMessage *message,
91 : const char *arg)
92 : {
93 : DBusMessage *reply;
94 :
95 123 : reply = dbus_message_new_error(
96 : message, WPAS_DBUS_ERROR_INVALID_ARGS,
97 : "Did not receive correct message arguments.");
98 123 : if (arg != NULL)
99 45 : dbus_message_append_args(reply, DBUS_TYPE_STRING, &arg,
100 : DBUS_TYPE_INVALID);
101 :
102 123 : return reply;
103 : }
104 :
105 :
106 : /**
107 : * wpas_dbus_error_scan_error - Return a new ScanError error message
108 : * @message: Pointer to incoming dbus message this error refers to
109 : * @error: Optional string to be used as the error message
110 : * Returns: a dbus error message
111 : *
112 : * Convenience function to create and return a scan error
113 : */
114 2 : static DBusMessage * wpas_dbus_error_scan_error(DBusMessage *message,
115 : const char *error)
116 : {
117 2 : return dbus_message_new_error(message,
118 : WPAS_DBUS_ERROR_IFACE_SCAN_ERROR,
119 : error);
120 : }
121 :
122 :
123 12 : DBusMessage * wpas_dbus_error_no_memory(DBusMessage *message)
124 : {
125 12 : wpa_printf(MSG_DEBUG, "dbus: Failed to allocate memory");
126 12 : return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, NULL);
127 : }
128 :
129 :
130 : static const char * const dont_quote[] = {
131 : "key_mgmt", "proto", "pairwise", "auth_alg", "group", "eap",
132 : "opensc_engine_path", "pkcs11_engine_path", "pkcs11_module_path",
133 : "bssid", "scan_freq", "freq_list", NULL
134 : };
135 :
136 184 : static dbus_bool_t should_quote_opt(const char *key)
137 : {
138 184 : int i = 0;
139 :
140 1876 : while (dont_quote[i] != NULL) {
141 1571 : if (os_strcmp(key, dont_quote[i]) == 0)
142 63 : return FALSE;
143 1508 : i++;
144 : }
145 121 : return TRUE;
146 : }
147 :
148 : /**
149 : * get_iface_by_dbus_path - Get a new network interface
150 : * @global: Pointer to global data from wpa_supplicant_init()
151 : * @path: Pointer to a dbus object path representing an interface
152 : * Returns: Pointer to the interface or %NULL if not found
153 : */
154 32 : static struct wpa_supplicant * get_iface_by_dbus_path(
155 : struct wpa_global *global, const char *path)
156 : {
157 : struct wpa_supplicant *wpa_s;
158 :
159 33 : for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
160 64 : if (wpa_s->dbus_new_path &&
161 32 : os_strcmp(wpa_s->dbus_new_path, path) == 0)
162 31 : return wpa_s;
163 : }
164 1 : return NULL;
165 : }
166 :
167 :
168 : /**
169 : * set_network_properties - Set properties of a configured network
170 : * @wpa_s: wpa_supplicant structure for a network interface
171 : * @ssid: wpa_ssid structure for a configured network
172 : * @iter: DBus message iterator containing dictionary of network
173 : * properties to set.
174 : * @error: On failure, an error describing the failure
175 : * Returns: TRUE if the request succeeds, FALSE if it failed
176 : *
177 : * Sets network configuration with parameters given id DBus dictionary
178 : */
179 71 : dbus_bool_t set_network_properties(struct wpa_supplicant *wpa_s,
180 : struct wpa_ssid *ssid,
181 : DBusMessageIter *iter,
182 : DBusError *error)
183 : {
184 71 : struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
185 : DBusMessageIter iter_dict;
186 71 : char *value = NULL;
187 :
188 71 : if (!wpa_dbus_dict_open_read(iter, &iter_dict, error))
189 0 : return FALSE;
190 :
191 376 : while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
192 244 : size_t size = 50;
193 : int ret;
194 :
195 244 : if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
196 1 : goto error;
197 :
198 243 : value = NULL;
199 246 : if (entry.type == DBUS_TYPE_ARRAY &&
200 3 : entry.array_type == DBUS_TYPE_BYTE) {
201 3 : if (entry.array_len <= 0)
202 1 : goto error;
203 :
204 2 : size = entry.array_len * 2 + 1;
205 2 : value = os_zalloc(size);
206 2 : if (value == NULL)
207 1 : goto error;
208 :
209 2 : ret = wpa_snprintf_hex(value, size,
210 1 : (u8 *) entry.bytearray_value,
211 1 : entry.array_len);
212 2 : if (ret <= 0)
213 0 : goto error;
214 240 : } else if (entry.type == DBUS_TYPE_STRING) {
215 184 : if (should_quote_opt(entry.key)) {
216 121 : size = os_strlen(entry.str_value);
217 121 : if (size == 0)
218 1 : goto error;
219 :
220 120 : size += 3;
221 120 : value = os_zalloc(size);
222 120 : if (value == NULL)
223 1 : goto error;
224 :
225 119 : ret = os_snprintf(value, size, "\"%s\"",
226 : entry.str_value);
227 119 : if (os_snprintf_error(size, ret))
228 0 : goto error;
229 : } else {
230 63 : value = os_strdup(entry.str_value);
231 63 : if (value == NULL)
232 1 : goto error;
233 : }
234 56 : } else if (entry.type == DBUS_TYPE_UINT32) {
235 2 : value = os_zalloc(size);
236 2 : if (value == NULL)
237 1 : goto error;
238 :
239 1 : ret = os_snprintf(value, size, "%u",
240 : entry.uint32_value);
241 1 : if (os_snprintf_error(size, ret))
242 0 : goto error;
243 54 : } else if (entry.type == DBUS_TYPE_INT32) {
244 53 : value = os_zalloc(size);
245 53 : if (value == NULL)
246 1 : goto error;
247 :
248 52 : ret = os_snprintf(value, size, "%d",
249 : entry.int32_value);
250 52 : if (os_snprintf_error(size, ret))
251 0 : goto error;
252 : } else
253 1 : goto error;
254 :
255 235 : if (wpa_config_set(ssid, entry.key, value, 0) < 0)
256 1 : goto error;
257 :
258 468 : if (os_strcmp(entry.key, "bssid") != 0 &&
259 234 : os_strcmp(entry.key, "priority") != 0)
260 233 : wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
261 :
262 467 : if (wpa_s->current_ssid == ssid ||
263 233 : wpa_s->current_ssid == NULL) {
264 : /*
265 : * Invalidate the EAP session cache if anything in the
266 : * current or previously used configuration changes.
267 : */
268 226 : eapol_sm_invalidate_cached_session(wpa_s->eapol);
269 : }
270 :
271 281 : if ((os_strcmp(entry.key, "psk") == 0 &&
272 328 : value[0] == '"' && ssid->ssid_len) ||
273 293 : (os_strcmp(entry.key, "ssid") == 0 && ssid->passphrase))
274 48 : wpa_config_update_psk(ssid);
275 186 : else if (os_strcmp(entry.key, "priority") == 0)
276 1 : wpa_config_update_prio_list(wpa_s->conf);
277 :
278 234 : os_free(value);
279 234 : value = NULL;
280 234 : wpa_dbus_dict_entry_clear(&entry);
281 : }
282 :
283 61 : return TRUE;
284 :
285 : error:
286 10 : os_free(value);
287 10 : wpa_dbus_dict_entry_clear(&entry);
288 10 : dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
289 : "invalid message format");
290 10 : return FALSE;
291 : }
292 :
293 :
294 : /**
295 : * wpas_dbus_simple_property_getter - Get basic type property
296 : * @iter: Message iter to use when appending arguments
297 : * @type: DBus type of property (must be basic type)
298 : * @val: pointer to place holding property value
299 : * @error: On failure an error describing the failure
300 : * Returns: TRUE if the request was successful, FALSE if it failed
301 : *
302 : * Generic getter for basic type properties. Type is required to be basic.
303 : */
304 76673 : dbus_bool_t wpas_dbus_simple_property_getter(DBusMessageIter *iter,
305 : const int type,
306 : const void *val,
307 : DBusError *error)
308 : {
309 : DBusMessageIter variant_iter;
310 :
311 76673 : if (!dbus_type_is_basic(type)) {
312 0 : dbus_set_error(error, DBUS_ERROR_FAILED,
313 : "%s: given type is not basic", __func__);
314 0 : return FALSE;
315 : }
316 :
317 76673 : if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
318 : wpa_dbus_type_as_string(type),
319 76673 : &variant_iter) ||
320 153346 : !dbus_message_iter_append_basic(&variant_iter, type, val) ||
321 76673 : !dbus_message_iter_close_container(iter, &variant_iter)) {
322 0 : dbus_set_error(error, DBUS_ERROR_FAILED,
323 : "%s: error constructing reply", __func__);
324 0 : return FALSE;
325 : }
326 :
327 76673 : return TRUE;
328 : }
329 :
330 :
331 : /**
332 : * wpas_dbus_simple_property_setter - Set basic type property
333 : * @message: Pointer to incoming dbus message
334 : * @type: DBus type of property (must be basic type)
335 : * @val: pointer to place where value being set will be stored
336 : * Returns: TRUE if the request was successful, FALSE if it failed
337 : *
338 : * Generic setter for basic type properties. Type is required to be basic.
339 : */
340 43 : dbus_bool_t wpas_dbus_simple_property_setter(DBusMessageIter *iter,
341 : DBusError *error,
342 : const int type, void *val)
343 : {
344 : DBusMessageIter variant_iter;
345 :
346 43 : if (!dbus_type_is_basic(type)) {
347 0 : dbus_set_error(error, DBUS_ERROR_FAILED,
348 : "%s: given type is not basic", __func__);
349 0 : return FALSE;
350 : }
351 :
352 : /* Look at the new value */
353 43 : dbus_message_iter_recurse(iter, &variant_iter);
354 43 : if (dbus_message_iter_get_arg_type(&variant_iter) != type) {
355 10 : dbus_set_error_const(error, DBUS_ERROR_FAILED,
356 : "wrong property type");
357 10 : return FALSE;
358 : }
359 33 : dbus_message_iter_get_basic(&variant_iter, val);
360 :
361 33 : return TRUE;
362 : }
363 :
364 :
365 : /**
366 : * wpas_dbus_simple_array_property_getter - Get array type property
367 : * @iter: Pointer to incoming dbus message iterator
368 : * @type: DBus type of property array elements (must be basic type)
369 : * @array: pointer to array of elements to put into response message
370 : * @array_len: length of above array
371 : * @error: a pointer to an error to fill on failure
372 : * Returns: TRUE if the request succeeded, FALSE if it failed
373 : *
374 : * Generic getter for array type properties. Array elements type is
375 : * required to be basic.
376 : */
377 11558 : dbus_bool_t wpas_dbus_simple_array_property_getter(DBusMessageIter *iter,
378 : const int type,
379 : const void *array,
380 : size_t array_len,
381 : DBusError *error)
382 : {
383 : DBusMessageIter variant_iter, array_iter;
384 11558 : char type_str[] = "a?"; /* ? will be replaced with subtype letter; */
385 : const char *sub_type_str;
386 : size_t element_size, i;
387 :
388 11558 : if (!dbus_type_is_basic(type)) {
389 0 : dbus_set_error(error, DBUS_ERROR_FAILED,
390 : "%s: given type is not basic", __func__);
391 0 : return FALSE;
392 : }
393 :
394 11558 : sub_type_str = wpa_dbus_type_as_string(type);
395 11558 : type_str[1] = sub_type_str[0];
396 :
397 11558 : if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
398 11558 : type_str, &variant_iter) ||
399 11558 : !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
400 : sub_type_str, &array_iter)) {
401 0 : dbus_set_error(error, DBUS_ERROR_FAILED,
402 : "%s: failed to construct message", __func__);
403 0 : return FALSE;
404 : }
405 :
406 11558 : switch (type) {
407 : case DBUS_TYPE_BYTE:
408 : case DBUS_TYPE_BOOLEAN:
409 4313 : element_size = 1;
410 4313 : break;
411 : case DBUS_TYPE_INT16:
412 : case DBUS_TYPE_UINT16:
413 0 : element_size = sizeof(uint16_t);
414 0 : break;
415 : case DBUS_TYPE_INT32:
416 : case DBUS_TYPE_UINT32:
417 1391 : element_size = sizeof(uint32_t);
418 1391 : break;
419 : case DBUS_TYPE_INT64:
420 : case DBUS_TYPE_UINT64:
421 0 : element_size = sizeof(uint64_t);
422 0 : break;
423 : case DBUS_TYPE_DOUBLE:
424 0 : element_size = sizeof(double);
425 0 : break;
426 : case DBUS_TYPE_STRING:
427 : case DBUS_TYPE_OBJECT_PATH:
428 5854 : element_size = sizeof(char *);
429 5854 : break;
430 : default:
431 0 : dbus_set_error(error, DBUS_ERROR_FAILED,
432 : "%s: unknown element type %d", __func__, type);
433 0 : return FALSE;
434 : }
435 :
436 313153 : for (i = 0; i < array_len; i++) {
437 301595 : if (!dbus_message_iter_append_basic(&array_iter, type,
438 301595 : array + i * element_size)) {
439 0 : dbus_set_error(error, DBUS_ERROR_FAILED,
440 : "%s: failed to construct message 2.5",
441 : __func__);
442 0 : return FALSE;
443 : }
444 : }
445 :
446 23116 : if (!dbus_message_iter_close_container(&variant_iter, &array_iter) ||
447 11558 : !dbus_message_iter_close_container(iter, &variant_iter)) {
448 0 : dbus_set_error(error, DBUS_ERROR_FAILED,
449 : "%s: failed to construct message 3", __func__);
450 0 : return FALSE;
451 : }
452 :
453 11558 : return TRUE;
454 : }
455 :
456 :
457 : /**
458 : * wpas_dbus_simple_array_array_property_getter - Get array array type property
459 : * @iter: Pointer to incoming dbus message iterator
460 : * @type: DBus type of property array elements (must be basic type)
461 : * @array: pointer to array of elements to put into response message
462 : * @array_len: length of above array
463 : * @error: a pointer to an error to fill on failure
464 : * Returns: TRUE if the request succeeded, FALSE if it failed
465 : *
466 : * Generic getter for array type properties. Array elements type is
467 : * required to be basic.
468 : */
469 18 : dbus_bool_t wpas_dbus_simple_array_array_property_getter(DBusMessageIter *iter,
470 : const int type,
471 : struct wpabuf **array,
472 : size_t array_len,
473 : DBusError *error)
474 : {
475 : DBusMessageIter variant_iter, array_iter;
476 18 : char type_str[] = "aa?";
477 18 : char inner_type_str[] = "a?";
478 : const char *sub_type_str;
479 : size_t i;
480 :
481 18 : if (!dbus_type_is_basic(type)) {
482 0 : dbus_set_error(error, DBUS_ERROR_FAILED,
483 : "%s: given type is not basic", __func__);
484 0 : return FALSE;
485 : }
486 :
487 18 : sub_type_str = wpa_dbus_type_as_string(type);
488 18 : type_str[2] = sub_type_str[0];
489 18 : inner_type_str[1] = sub_type_str[0];
490 :
491 18 : if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
492 18 : type_str, &variant_iter) ||
493 18 : !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
494 : inner_type_str, &array_iter)) {
495 0 : dbus_set_error(error, DBUS_ERROR_FAILED,
496 : "%s: failed to construct message", __func__);
497 0 : return FALSE;
498 : }
499 :
500 22 : for (i = 0; i < array_len && array[i]; i++) {
501 8 : wpa_dbus_dict_bin_array_add_element(&array_iter,
502 4 : wpabuf_head(array[i]),
503 4 : wpabuf_len(array[i]));
504 :
505 : }
506 :
507 36 : if (!dbus_message_iter_close_container(&variant_iter, &array_iter) ||
508 18 : !dbus_message_iter_close_container(iter, &variant_iter)) {
509 0 : dbus_set_error(error, DBUS_ERROR_FAILED,
510 : "%s: failed to close message", __func__);
511 0 : return FALSE;
512 : }
513 :
514 18 : return TRUE;
515 : }
516 :
517 :
518 : /**
519 : * wpas_dbus_handler_create_interface - Request registration of a network iface
520 : * @message: Pointer to incoming dbus message
521 : * @global: %wpa_supplicant global data structure
522 : * Returns: The object path of the new interface object,
523 : * or a dbus error message with more information
524 : *
525 : * Handler function for "CreateInterface" method call. Handles requests
526 : * by dbus clients to register a network interface that wpa_supplicant
527 : * will manage.
528 : */
529 60 : DBusMessage * wpas_dbus_handler_create_interface(DBusMessage *message,
530 : struct wpa_global *global)
531 : {
532 : DBusMessageIter iter_dict;
533 60 : DBusMessage *reply = NULL;
534 : DBusMessageIter iter;
535 : struct wpa_dbus_dict_entry entry;
536 60 : char *driver = NULL;
537 60 : char *ifname = NULL;
538 60 : char *confname = NULL;
539 60 : char *bridge_ifname = NULL;
540 :
541 60 : dbus_message_iter_init(message, &iter);
542 :
543 60 : if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
544 0 : goto error;
545 230 : while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
546 116 : if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
547 1 : goto error;
548 170 : if (os_strcmp(entry.key, "Driver") == 0 &&
549 55 : entry.type == DBUS_TYPE_STRING) {
550 55 : os_free(driver);
551 55 : driver = os_strdup(entry.str_value);
552 55 : wpa_dbus_dict_entry_clear(&entry);
553 109 : if (driver == NULL)
554 1 : goto oom;
555 115 : } else if (os_strcmp(entry.key, "Ifname") == 0 &&
556 55 : entry.type == DBUS_TYPE_STRING) {
557 55 : os_free(ifname);
558 55 : ifname = os_strdup(entry.str_value);
559 55 : wpa_dbus_dict_entry_clear(&entry);
560 109 : if (ifname == NULL)
561 1 : goto oom;
562 7 : } else if (os_strcmp(entry.key, "ConfigFile") == 0 &&
563 2 : entry.type == DBUS_TYPE_STRING) {
564 2 : os_free(confname);
565 2 : confname = os_strdup(entry.str_value);
566 2 : wpa_dbus_dict_entry_clear(&entry);
567 3 : if (confname == NULL)
568 1 : goto oom;
569 5 : } else if (os_strcmp(entry.key, "BridgeIfname") == 0 &&
570 2 : entry.type == DBUS_TYPE_STRING) {
571 2 : os_free(bridge_ifname);
572 2 : bridge_ifname = os_strdup(entry.str_value);
573 2 : wpa_dbus_dict_entry_clear(&entry);
574 3 : if (bridge_ifname == NULL)
575 1 : goto oom;
576 : } else {
577 1 : wpa_dbus_dict_entry_clear(&entry);
578 1 : goto error;
579 : }
580 : }
581 :
582 54 : if (ifname == NULL)
583 1 : goto error; /* Required Ifname argument missing */
584 :
585 : /*
586 : * Try to get the wpa_supplicant record for this iface, return
587 : * an error if we already control it.
588 : */
589 53 : if (wpa_supplicant_get_iface(global, ifname) != NULL) {
590 1 : reply = dbus_message_new_error(
591 : message, WPAS_DBUS_ERROR_IFACE_EXISTS,
592 : "wpa_supplicant already controls this interface.");
593 : } else {
594 : struct wpa_supplicant *wpa_s;
595 : struct wpa_interface iface;
596 :
597 52 : os_memset(&iface, 0, sizeof(iface));
598 52 : iface.driver = driver;
599 52 : iface.ifname = ifname;
600 52 : iface.confname = confname;
601 52 : iface.bridge_ifname = bridge_ifname;
602 : /* Otherwise, have wpa_supplicant attach to it. */
603 52 : wpa_s = wpa_supplicant_add_iface(global, &iface, NULL);
604 83 : if (wpa_s && wpa_s->dbus_new_path) {
605 31 : const char *path = wpa_s->dbus_new_path;
606 :
607 31 : reply = dbus_message_new_method_return(message);
608 31 : dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH,
609 : &path, DBUS_TYPE_INVALID);
610 : } else {
611 21 : reply = wpas_dbus_error_unknown_error(
612 : message,
613 : "wpa_supplicant couldn't grab this interface.");
614 : }
615 : }
616 :
617 : out:
618 60 : os_free(driver);
619 60 : os_free(ifname);
620 60 : os_free(confname);
621 60 : os_free(bridge_ifname);
622 120 : return reply;
623 :
624 : error:
625 3 : reply = wpas_dbus_error_invalid_args(message, NULL);
626 3 : goto out;
627 : oom:
628 4 : reply = wpas_dbus_error_no_memory(message);
629 4 : goto out;
630 : }
631 :
632 :
633 : /**
634 : * wpas_dbus_handler_remove_interface - Request deregistration of an interface
635 : * @message: Pointer to incoming dbus message
636 : * @global: wpa_supplicant global data structure
637 : * Returns: a dbus message containing a UINT32 indicating success (1) or
638 : * failure (0), or returns a dbus error message with more information
639 : *
640 : * Handler function for "removeInterface" method call. Handles requests
641 : * by dbus clients to deregister a network interface that wpa_supplicant
642 : * currently manages.
643 : */
644 32 : DBusMessage * wpas_dbus_handler_remove_interface(DBusMessage *message,
645 : struct wpa_global *global)
646 : {
647 : struct wpa_supplicant *wpa_s;
648 : char *path;
649 32 : DBusMessage *reply = NULL;
650 :
651 32 : dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path,
652 : DBUS_TYPE_INVALID);
653 :
654 32 : wpa_s = get_iface_by_dbus_path(global, path);
655 32 : if (wpa_s == NULL)
656 1 : reply = wpas_dbus_error_iface_unknown(message);
657 31 : else if (wpa_supplicant_remove_iface(global, wpa_s, 0)) {
658 0 : reply = wpas_dbus_error_unknown_error(
659 : message,
660 : "wpa_supplicant couldn't remove this interface.");
661 : }
662 :
663 32 : return reply;
664 : }
665 :
666 :
667 : /**
668 : * wpas_dbus_handler_get_interface - Get the object path for an interface name
669 : * @message: Pointer to incoming dbus message
670 : * @global: %wpa_supplicant global data structure
671 : * Returns: The object path of the interface object,
672 : * or a dbus error message with more information
673 : *
674 : * Handler function for "getInterface" method call.
675 : */
676 68 : DBusMessage * wpas_dbus_handler_get_interface(DBusMessage *message,
677 : struct wpa_global *global)
678 : {
679 68 : DBusMessage *reply = NULL;
680 : const char *ifname;
681 : const char *path;
682 : struct wpa_supplicant *wpa_s;
683 :
684 68 : dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &ifname,
685 : DBUS_TYPE_INVALID);
686 :
687 68 : wpa_s = wpa_supplicant_get_iface(global, ifname);
688 68 : if (wpa_s == NULL || wpa_s->dbus_new_path == NULL)
689 1 : return wpas_dbus_error_iface_unknown(message);
690 :
691 67 : path = wpa_s->dbus_new_path;
692 67 : reply = dbus_message_new_method_return(message);
693 67 : if (reply == NULL)
694 0 : return wpas_dbus_error_no_memory(message);
695 67 : if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
696 : DBUS_TYPE_INVALID)) {
697 0 : dbus_message_unref(reply);
698 0 : return wpas_dbus_error_no_memory(message);
699 : }
700 :
701 67 : return reply;
702 : }
703 :
704 :
705 : /**
706 : * wpas_dbus_getter_debug_level - Get debug level
707 : * @iter: Pointer to incoming dbus message iter
708 : * @error: Location to store error on failure
709 : * @user_data: Function specific data
710 : * Returns: TRUE on success, FALSE on failure
711 : *
712 : * Getter for "DebugLevel" property.
713 : */
714 8 : dbus_bool_t wpas_dbus_getter_debug_level(DBusMessageIter *iter,
715 : DBusError *error,
716 : void *user_data)
717 : {
718 : const char *str;
719 8 : int idx = wpa_debug_level;
720 :
721 8 : if (idx < 0)
722 0 : idx = 0;
723 8 : if (idx > 5)
724 0 : idx = 5;
725 8 : str = debug_strings[idx];
726 8 : return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
727 : &str, error);
728 : }
729 :
730 :
731 : /**
732 : * wpas_dbus_getter_debug_timestamp - Get debug timestamp
733 : * @iter: Pointer to incoming dbus message iter
734 : * @error: Location to store error on failure
735 : * @user_data: Function specific data
736 : * Returns: TRUE on success, FALSE on failure
737 : *
738 : * Getter for "DebugTimestamp" property.
739 : */
740 8 : dbus_bool_t wpas_dbus_getter_debug_timestamp(DBusMessageIter *iter,
741 : DBusError *error,
742 : void *user_data)
743 : {
744 8 : return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
745 : &wpa_debug_timestamp, error);
746 :
747 : }
748 :
749 :
750 : /**
751 : * wpas_dbus_getter_debug_show_keys - Get debug show keys
752 : * @iter: Pointer to incoming dbus message iter
753 : * @error: Location to store error on failure
754 : * @user_data: Function specific data
755 : * Returns: TRUE on success, FALSE on failure
756 : *
757 : * Getter for "DebugShowKeys" property.
758 : */
759 8 : dbus_bool_t wpas_dbus_getter_debug_show_keys(DBusMessageIter *iter,
760 : DBusError *error,
761 : void *user_data)
762 : {
763 8 : return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
764 : &wpa_debug_show_keys, error);
765 :
766 : }
767 :
768 : /**
769 : * wpas_dbus_setter_debug_level - Set debug level
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 : * Setter for "DebugLevel" property.
776 : */
777 4 : dbus_bool_t wpas_dbus_setter_debug_level(DBusMessageIter *iter,
778 : DBusError *error, void *user_data)
779 : {
780 4 : struct wpa_global *global = user_data;
781 4 : const char *str = NULL;
782 4 : int i, val = -1;
783 :
784 4 : if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
785 : &str))
786 1 : return FALSE;
787 :
788 12 : for (i = 0; debug_strings[i]; i++)
789 11 : if (os_strcmp(debug_strings[i], str) == 0) {
790 2 : val = i;
791 2 : break;
792 : }
793 :
794 5 : if (val < 0 ||
795 2 : wpa_supplicant_set_debug_params(global, val, wpa_debug_timestamp,
796 : wpa_debug_show_keys)) {
797 1 : dbus_set_error_const(error, DBUS_ERROR_FAILED,
798 : "wrong debug level value");
799 1 : return FALSE;
800 : }
801 :
802 2 : return TRUE;
803 : }
804 :
805 :
806 : /**
807 : * wpas_dbus_setter_debug_timestamp - Set debug timestamp
808 : * @iter: Pointer to incoming dbus message iter
809 : * @error: Location to store error on failure
810 : * @user_data: Function specific data
811 : * Returns: TRUE on success, FALSE on failure
812 : *
813 : * Setter for "DebugTimestamp" property.
814 : */
815 3 : dbus_bool_t wpas_dbus_setter_debug_timestamp(DBusMessageIter *iter,
816 : DBusError *error,
817 : void *user_data)
818 : {
819 3 : struct wpa_global *global = user_data;
820 : dbus_bool_t val;
821 :
822 3 : if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
823 : &val))
824 1 : return FALSE;
825 :
826 2 : wpa_supplicant_set_debug_params(global, wpa_debug_level, val ? 1 : 0,
827 : wpa_debug_show_keys);
828 2 : return TRUE;
829 : }
830 :
831 :
832 : /**
833 : * wpas_dbus_setter_debug_show_keys - Set debug show keys
834 : * @iter: Pointer to incoming dbus message iter
835 : * @error: Location to store error on failure
836 : * @user_data: Function specific data
837 : * Returns: TRUE on success, FALSE on failure
838 : *
839 : * Setter for "DebugShowKeys" property.
840 : */
841 3 : dbus_bool_t wpas_dbus_setter_debug_show_keys(DBusMessageIter *iter,
842 : DBusError *error,
843 : void *user_data)
844 : {
845 3 : struct wpa_global *global = user_data;
846 : dbus_bool_t val;
847 :
848 3 : if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
849 : &val))
850 1 : return FALSE;
851 :
852 2 : wpa_supplicant_set_debug_params(global, wpa_debug_level,
853 : wpa_debug_timestamp,
854 : val ? 1 : 0);
855 2 : return TRUE;
856 : }
857 :
858 :
859 : /**
860 : * wpas_dbus_getter_interfaces - Request registered interfaces list
861 : * @iter: Pointer to incoming dbus message iter
862 : * @error: Location to store error on failure
863 : * @user_data: Function specific data
864 : * Returns: TRUE on success, FALSE on failure
865 : *
866 : * Getter for "Interfaces" property. Handles requests
867 : * by dbus clients to return list of registered interfaces objects
868 : * paths
869 : */
870 3 : dbus_bool_t wpas_dbus_getter_interfaces(DBusMessageIter *iter,
871 : DBusError *error,
872 : void *user_data)
873 : {
874 3 : struct wpa_global *global = user_data;
875 : struct wpa_supplicant *wpa_s;
876 : const char **paths;
877 3 : unsigned int i = 0, num = 0;
878 : dbus_bool_t success;
879 :
880 6 : for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
881 3 : if (wpa_s->dbus_new_path)
882 3 : num++;
883 : }
884 :
885 3 : paths = os_calloc(num, sizeof(char *));
886 3 : if (!paths) {
887 1 : dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
888 1 : return FALSE;
889 : }
890 :
891 4 : for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
892 2 : if (wpa_s->dbus_new_path)
893 2 : paths[i++] = wpa_s->dbus_new_path;
894 : }
895 :
896 2 : success = wpas_dbus_simple_array_property_getter(iter,
897 : DBUS_TYPE_OBJECT_PATH,
898 : paths, num, error);
899 :
900 2 : os_free(paths);
901 2 : return success;
902 : }
903 :
904 :
905 : /**
906 : * wpas_dbus_getter_eap_methods - Request supported EAP methods list
907 : * @iter: Pointer to incoming dbus message iter
908 : * @error: Location to store error on failure
909 : * @user_data: Function specific data
910 : * Returns: TRUE on success, FALSE on failure
911 : *
912 : * Getter for "EapMethods" property. Handles requests
913 : * by dbus clients to return list of strings with supported EAP methods
914 : */
915 8 : dbus_bool_t wpas_dbus_getter_eap_methods(DBusMessageIter *iter,
916 : DBusError *error, void *user_data)
917 : {
918 : char **eap_methods;
919 8 : size_t num_items = 0;
920 : dbus_bool_t success;
921 :
922 8 : eap_methods = eap_get_names_as_string_array(&num_items);
923 8 : if (!eap_methods) {
924 5 : dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
925 5 : return FALSE;
926 : }
927 :
928 3 : success = wpas_dbus_simple_array_property_getter(iter,
929 : DBUS_TYPE_STRING,
930 : eap_methods,
931 : num_items, error);
932 :
933 78 : while (num_items)
934 72 : os_free(eap_methods[--num_items]);
935 3 : os_free(eap_methods);
936 3 : return success;
937 : }
938 :
939 :
940 : /**
941 : * wpas_dbus_getter_global_capabilities - Request supported global capabilities
942 : * @iter: Pointer to incoming dbus message iter
943 : * @error: Location to store error on failure
944 : * @user_data: Function specific data
945 : * Returns: TRUE on success, FALSE on failure
946 : *
947 : * Getter for "Capabilities" property. Handles requests by dbus clients to
948 : * return a list of strings with supported capabilities like AP, RSN IBSS,
949 : * and P2P that are determined at compile time.
950 : */
951 2 : dbus_bool_t wpas_dbus_getter_global_capabilities(DBusMessageIter *iter,
952 : DBusError *error,
953 : void *user_data)
954 : {
955 2 : const char *capabilities[5] = { NULL, NULL, NULL, NULL, NULL };
956 2 : size_t num_items = 0;
957 :
958 : #ifdef CONFIG_AP
959 2 : capabilities[num_items++] = "ap";
960 : #endif /* CONFIG_AP */
961 : #ifdef CONFIG_IBSS_RSN
962 2 : capabilities[num_items++] = "ibss-rsn";
963 : #endif /* CONFIG_IBSS_RSN */
964 : #ifdef CONFIG_P2P
965 2 : capabilities[num_items++] = "p2p";
966 : #endif /* CONFIG_P2P */
967 : #ifdef CONFIG_INTERWORKING
968 2 : capabilities[num_items++] = "interworking";
969 : #endif /* CONFIG_INTERWORKING */
970 :
971 2 : return wpas_dbus_simple_array_property_getter(iter,
972 : DBUS_TYPE_STRING,
973 : capabilities,
974 : num_items, error);
975 : }
976 :
977 :
978 16 : static int wpas_dbus_get_scan_type(DBusMessage *message, DBusMessageIter *var,
979 : char **type, DBusMessage **reply)
980 : {
981 16 : if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_STRING) {
982 1 : wpa_printf(MSG_DEBUG, "%s[dbus]: Type must be a string",
983 : __func__);
984 1 : *reply = wpas_dbus_error_invalid_args(
985 : message, "Wrong Type value type. String required");
986 1 : return -1;
987 : }
988 15 : dbus_message_iter_get_basic(var, type);
989 15 : return 0;
990 : }
991 :
992 :
993 7 : static int wpas_dbus_get_scan_ssids(DBusMessage *message, DBusMessageIter *var,
994 : struct wpa_driver_scan_params *params,
995 : DBusMessage **reply)
996 : {
997 7 : struct wpa_driver_scan_ssid *ssids = params->ssids;
998 7 : size_t ssids_num = 0;
999 : u8 *ssid;
1000 : DBusMessageIter array_iter, sub_array_iter;
1001 : char *val;
1002 : int len;
1003 :
1004 7 : if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
1005 1 : wpa_printf(MSG_DEBUG,
1006 : "%s[dbus]: ssids must be an array of arrays of bytes",
1007 : __func__);
1008 1 : *reply = wpas_dbus_error_invalid_args(
1009 : message,
1010 : "Wrong SSIDs value type. Array of arrays of bytes required");
1011 1 : return -1;
1012 : }
1013 :
1014 6 : dbus_message_iter_recurse(var, &array_iter);
1015 :
1016 11 : if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY ||
1017 5 : dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_BYTE) {
1018 1 : wpa_printf(MSG_DEBUG,
1019 : "%s[dbus]: ssids must be an array of arrays of bytes",
1020 : __func__);
1021 1 : *reply = wpas_dbus_error_invalid_args(
1022 : message,
1023 : "Wrong SSIDs value type. Array of arrays of bytes required");
1024 1 : return -1;
1025 : }
1026 :
1027 29 : while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_ARRAY) {
1028 22 : if (ssids_num >= WPAS_MAX_SCAN_SSIDS) {
1029 1 : wpa_printf(MSG_DEBUG,
1030 : "%s[dbus]: Too many ssids specified on scan dbus call",
1031 : __func__);
1032 1 : *reply = wpas_dbus_error_invalid_args(
1033 : message,
1034 : "Too many ssids specified. Specify at most four");
1035 1 : return -1;
1036 : }
1037 :
1038 21 : dbus_message_iter_recurse(&array_iter, &sub_array_iter);
1039 :
1040 21 : dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len);
1041 :
1042 21 : if (len > SSID_MAX_LEN) {
1043 1 : wpa_printf(MSG_DEBUG,
1044 : "%s[dbus]: SSID too long (len=%d max_len=%d)",
1045 : __func__, len, SSID_MAX_LEN);
1046 1 : *reply = wpas_dbus_error_invalid_args(
1047 : message, "Invalid SSID: too long");
1048 1 : return -1;
1049 : }
1050 :
1051 20 : if (len != 0) {
1052 19 : ssid = os_malloc(len);
1053 19 : if (ssid == NULL) {
1054 1 : *reply = wpas_dbus_error_no_memory(message);
1055 1 : return -1;
1056 : }
1057 18 : os_memcpy(ssid, val, len);
1058 : } else {
1059 : /* Allow zero-length SSIDs */
1060 1 : ssid = NULL;
1061 : }
1062 :
1063 19 : ssids[ssids_num].ssid = ssid;
1064 19 : ssids[ssids_num].ssid_len = len;
1065 :
1066 19 : dbus_message_iter_next(&array_iter);
1067 19 : ssids_num++;
1068 : }
1069 :
1070 2 : params->num_ssids = ssids_num;
1071 2 : return 0;
1072 : }
1073 :
1074 :
1075 5 : static int wpas_dbus_get_scan_ies(DBusMessage *message, DBusMessageIter *var,
1076 : struct wpa_driver_scan_params *params,
1077 : DBusMessage **reply)
1078 : {
1079 5 : u8 *ies = NULL, *nies;
1080 5 : int ies_len = 0;
1081 : DBusMessageIter array_iter, sub_array_iter;
1082 : char *val;
1083 : int len;
1084 :
1085 5 : if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
1086 1 : wpa_printf(MSG_DEBUG,
1087 : "%s[dbus]: ies must be an array of arrays of bytes",
1088 : __func__);
1089 1 : *reply = wpas_dbus_error_invalid_args(
1090 : message,
1091 : "Wrong IEs value type. Array of arrays of bytes required");
1092 1 : return -1;
1093 : }
1094 :
1095 4 : dbus_message_iter_recurse(var, &array_iter);
1096 :
1097 7 : if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY ||
1098 3 : dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_BYTE) {
1099 1 : wpa_printf(MSG_DEBUG,
1100 : "%s[dbus]: ies must be an array of arrays of bytes",
1101 : __func__);
1102 1 : *reply = wpas_dbus_error_invalid_args(
1103 : message, "Wrong IEs value type. Array required");
1104 1 : return -1;
1105 : }
1106 :
1107 9 : while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_ARRAY) {
1108 4 : dbus_message_iter_recurse(&array_iter, &sub_array_iter);
1109 :
1110 4 : dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len);
1111 4 : if (len == 0) {
1112 1 : dbus_message_iter_next(&array_iter);
1113 1 : continue;
1114 : }
1115 :
1116 3 : nies = os_realloc(ies, ies_len + len);
1117 3 : if (nies == NULL) {
1118 1 : os_free(ies);
1119 1 : *reply = wpas_dbus_error_no_memory(message);
1120 1 : return -1;
1121 : }
1122 2 : ies = nies;
1123 2 : os_memcpy(ies + ies_len, val, len);
1124 2 : ies_len += len;
1125 :
1126 2 : dbus_message_iter_next(&array_iter);
1127 : }
1128 :
1129 2 : params->extra_ies = ies;
1130 2 : params->extra_ies_len = ies_len;
1131 2 : return 0;
1132 : }
1133 :
1134 :
1135 11 : static int wpas_dbus_get_scan_channels(DBusMessage *message,
1136 : DBusMessageIter *var,
1137 : struct wpa_driver_scan_params *params,
1138 : DBusMessage **reply)
1139 : {
1140 : DBusMessageIter array_iter, sub_array_iter;
1141 11 : int *freqs = NULL, *nfreqs;
1142 11 : int freqs_num = 0;
1143 :
1144 11 : if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
1145 1 : wpa_printf(MSG_DEBUG,
1146 : "%s[dbus]: Channels must be an array of structs",
1147 : __func__);
1148 1 : *reply = wpas_dbus_error_invalid_args(
1149 : message,
1150 : "Wrong Channels value type. Array of structs required");
1151 1 : return -1;
1152 : }
1153 :
1154 10 : dbus_message_iter_recurse(var, &array_iter);
1155 :
1156 10 : if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_STRUCT) {
1157 1 : wpa_printf(MSG_DEBUG,
1158 : "%s[dbus]: Channels must be an array of structs",
1159 : __func__);
1160 1 : *reply = wpas_dbus_error_invalid_args(
1161 : message,
1162 : "Wrong Channels value type. Array of structs required");
1163 1 : return -1;
1164 : }
1165 :
1166 24 : while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_STRUCT)
1167 : {
1168 : int freq, width;
1169 :
1170 9 : dbus_message_iter_recurse(&array_iter, &sub_array_iter);
1171 :
1172 9 : if (dbus_message_iter_get_arg_type(&sub_array_iter) !=
1173 : DBUS_TYPE_UINT32) {
1174 1 : wpa_printf(MSG_DEBUG,
1175 : "%s[dbus]: Channel must by specified by struct of two UINT32s %c",
1176 : __func__,
1177 : dbus_message_iter_get_arg_type(
1178 : &sub_array_iter));
1179 1 : *reply = wpas_dbus_error_invalid_args(
1180 : message,
1181 : "Wrong Channel struct. Two UINT32s required");
1182 1 : os_free(freqs);
1183 4 : return -1;
1184 : }
1185 8 : dbus_message_iter_get_basic(&sub_array_iter, &freq);
1186 :
1187 16 : if (!dbus_message_iter_next(&sub_array_iter) ||
1188 8 : dbus_message_iter_get_arg_type(&sub_array_iter) !=
1189 : DBUS_TYPE_UINT32) {
1190 1 : wpa_printf(MSG_DEBUG,
1191 : "%s[dbus]: Channel must by specified by struct of two UINT32s",
1192 : __func__);
1193 1 : *reply = wpas_dbus_error_invalid_args(
1194 : message,
1195 : "Wrong Channel struct. Two UINT32s required");
1196 1 : os_free(freqs);
1197 1 : return -1;
1198 : }
1199 :
1200 7 : dbus_message_iter_get_basic(&sub_array_iter, &width);
1201 :
1202 : #define FREQS_ALLOC_CHUNK 32
1203 7 : if (freqs_num % FREQS_ALLOC_CHUNK == 0) {
1204 7 : nfreqs = os_realloc_array(
1205 7 : freqs, freqs_num + FREQS_ALLOC_CHUNK,
1206 : sizeof(int));
1207 7 : if (nfreqs == NULL)
1208 1 : os_free(freqs);
1209 7 : freqs = nfreqs;
1210 : }
1211 7 : if (freqs == NULL) {
1212 1 : *reply = wpas_dbus_error_no_memory(message);
1213 1 : return -1;
1214 : }
1215 :
1216 6 : freqs[freqs_num] = freq;
1217 :
1218 6 : freqs_num++;
1219 6 : dbus_message_iter_next(&array_iter);
1220 : }
1221 :
1222 6 : nfreqs = os_realloc_array(freqs, freqs_num + 1, sizeof(int));
1223 6 : if (nfreqs == NULL)
1224 0 : os_free(freqs);
1225 6 : freqs = nfreqs;
1226 6 : if (freqs == NULL) {
1227 0 : *reply = wpas_dbus_error_no_memory(message);
1228 0 : return -1;
1229 : }
1230 6 : freqs[freqs_num] = 0;
1231 :
1232 6 : params->freqs = freqs;
1233 6 : return 0;
1234 : }
1235 :
1236 :
1237 6 : static int wpas_dbus_get_scan_allow_roam(DBusMessage *message,
1238 : DBusMessageIter *var,
1239 : dbus_bool_t *allow,
1240 : DBusMessage **reply)
1241 : {
1242 6 : if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_BOOLEAN) {
1243 1 : wpa_printf(MSG_DEBUG, "%s[dbus]: Type must be a boolean",
1244 : __func__);
1245 1 : *reply = wpas_dbus_error_invalid_args(
1246 : message, "Wrong Type value type. Boolean required");
1247 1 : return -1;
1248 : }
1249 5 : dbus_message_iter_get_basic(var, allow);
1250 5 : return 0;
1251 : }
1252 :
1253 :
1254 : /**
1255 : * wpas_dbus_handler_scan - Request a wireless scan on an interface
1256 : * @message: Pointer to incoming dbus message
1257 : * @wpa_s: wpa_supplicant structure for a network interface
1258 : * Returns: NULL indicating success or DBus error message on failure
1259 : *
1260 : * Handler function for "Scan" method call of a network device. Requests
1261 : * that wpa_supplicant perform a wireless scan as soon as possible
1262 : * on a particular wireless interface.
1263 : */
1264 26 : DBusMessage * wpas_dbus_handler_scan(DBusMessage *message,
1265 : struct wpa_supplicant *wpa_s)
1266 : {
1267 26 : DBusMessage *reply = NULL;
1268 : DBusMessageIter iter, dict_iter, entry_iter, variant_iter;
1269 26 : char *key = NULL, *type = NULL;
1270 : struct wpa_driver_scan_params params;
1271 : size_t i;
1272 26 : dbus_bool_t allow_roam = 1;
1273 :
1274 26 : os_memset(¶ms, 0, sizeof(params));
1275 :
1276 26 : dbus_message_iter_init(message, &iter);
1277 :
1278 26 : dbus_message_iter_recurse(&iter, &dict_iter);
1279 :
1280 82 : while (dbus_message_iter_get_arg_type(&dict_iter) ==
1281 : DBUS_TYPE_DICT_ENTRY) {
1282 46 : dbus_message_iter_recurse(&dict_iter, &entry_iter);
1283 46 : dbus_message_iter_get_basic(&entry_iter, &key);
1284 46 : dbus_message_iter_next(&entry_iter);
1285 46 : dbus_message_iter_recurse(&entry_iter, &variant_iter);
1286 :
1287 46 : if (os_strcmp(key, "Type") == 0) {
1288 16 : if (wpas_dbus_get_scan_type(message, &variant_iter,
1289 : &type, &reply) < 0)
1290 1 : goto out;
1291 30 : } else if (os_strcmp(key, "SSIDs") == 0) {
1292 7 : if (wpas_dbus_get_scan_ssids(message, &variant_iter,
1293 : ¶ms, &reply) < 0)
1294 5 : goto out;
1295 23 : } else if (os_strcmp(key, "IEs") == 0) {
1296 5 : if (wpas_dbus_get_scan_ies(message, &variant_iter,
1297 : ¶ms, &reply) < 0)
1298 3 : goto out;
1299 18 : } else if (os_strcmp(key, "Channels") == 0) {
1300 11 : if (wpas_dbus_get_scan_channels(message, &variant_iter,
1301 : ¶ms, &reply) < 0)
1302 5 : goto out;
1303 7 : } else if (os_strcmp(key, "AllowRoam") == 0) {
1304 6 : if (wpas_dbus_get_scan_allow_roam(message,
1305 : &variant_iter,
1306 : &allow_roam,
1307 : &reply) < 0)
1308 1 : goto out;
1309 : } else {
1310 1 : wpa_printf(MSG_DEBUG, "%s[dbus]: Unknown argument %s",
1311 : __func__, key);
1312 1 : reply = wpas_dbus_error_invalid_args(message, key);
1313 1 : goto out;
1314 : }
1315 :
1316 30 : dbus_message_iter_next(&dict_iter);
1317 : }
1318 :
1319 10 : if (!type) {
1320 1 : wpa_printf(MSG_DEBUG, "%s[dbus]: Scan type not specified",
1321 : __func__);
1322 1 : reply = wpas_dbus_error_invalid_args(message, key);
1323 1 : goto out;
1324 : }
1325 :
1326 9 : if (os_strcmp(type, "passive") == 0) {
1327 5 : if (params.num_ssids || params.extra_ies_len) {
1328 2 : wpa_printf(MSG_DEBUG,
1329 : "%s[dbus]: SSIDs or IEs specified for passive scan.",
1330 : __func__);
1331 2 : reply = wpas_dbus_error_invalid_args(
1332 : message,
1333 : "You can specify only Channels in passive scan");
1334 2 : goto out;
1335 : } else {
1336 3 : if (wpa_s->sched_scanning) {
1337 0 : wpa_printf(MSG_DEBUG,
1338 : "%s[dbus]: Stop ongoing sched_scan to allow requested scan to proceed",
1339 : __func__);
1340 0 : wpa_supplicant_cancel_sched_scan(wpa_s);
1341 : }
1342 :
1343 3 : if (params.freqs && params.freqs[0]) {
1344 2 : wpa_s->last_scan_req = MANUAL_SCAN_REQ;
1345 4 : if (wpa_supplicant_trigger_scan(wpa_s,
1346 : ¶ms)) {
1347 1 : reply = wpas_dbus_error_scan_error(
1348 : message,
1349 : "Scan request rejected");
1350 : }
1351 : } else {
1352 1 : wpa_s->scan_req = MANUAL_SCAN_REQ;
1353 1 : wpa_supplicant_req_scan(wpa_s, 0, 0);
1354 : }
1355 : }
1356 4 : } else if (os_strcmp(type, "active") == 0) {
1357 3 : if (!params.num_ssids) {
1358 : /* Add wildcard ssid */
1359 2 : params.num_ssids++;
1360 : }
1361 : #ifdef CONFIG_AUTOSCAN
1362 3 : autoscan_deinit(wpa_s);
1363 : #endif /* CONFIG_AUTOSCAN */
1364 3 : if (wpa_s->sched_scanning) {
1365 0 : wpa_printf(MSG_DEBUG,
1366 : "%s[dbus]: Stop ongoing sched_scan to allow requested scan to proceed",
1367 : __func__);
1368 0 : wpa_supplicant_cancel_sched_scan(wpa_s);
1369 : }
1370 :
1371 3 : wpa_s->last_scan_req = MANUAL_SCAN_REQ;
1372 3 : if (wpa_supplicant_trigger_scan(wpa_s, ¶ms)) {
1373 1 : reply = wpas_dbus_error_scan_error(
1374 : message, "Scan request rejected");
1375 : }
1376 : } else {
1377 1 : wpa_printf(MSG_DEBUG, "%s[dbus]: Unknown scan type: %s",
1378 : __func__, type);
1379 1 : reply = wpas_dbus_error_invalid_args(message,
1380 : "Wrong scan type");
1381 1 : goto out;
1382 : }
1383 :
1384 6 : if (!allow_roam)
1385 3 : wpa_s->scan_res_handler = scan_only_handler;
1386 :
1387 : out:
1388 442 : for (i = 0; i < WPAS_MAX_SCAN_SSIDS; i++)
1389 416 : os_free((u8 *) params.ssids[i].ssid);
1390 26 : os_free((u8 *) params.extra_ies);
1391 26 : os_free(params.freqs);
1392 26 : return reply;
1393 : }
1394 :
1395 :
1396 : /**
1397 : * wpas_dbus_handler_signal_poll - Request immediate signal properties
1398 : * @message: Pointer to incoming dbus message
1399 : * @wpa_s: wpa_supplicant structure for a network interface
1400 : * Returns: NULL indicating success or DBus error message on failure
1401 : *
1402 : * Handler function for "SignalPoll" method call of a network device. Requests
1403 : * that wpa_supplicant read signal properties like RSSI, noise, and link
1404 : * speed and return them.
1405 : */
1406 36 : DBusMessage * wpas_dbus_handler_signal_poll(DBusMessage *message,
1407 : struct wpa_supplicant *wpa_s)
1408 : {
1409 : struct wpa_signal_info si;
1410 36 : DBusMessage *reply = NULL;
1411 : DBusMessageIter iter, iter_dict, variant_iter;
1412 : int ret;
1413 :
1414 36 : ret = wpa_drv_signal_poll(wpa_s, &si);
1415 36 : if (ret) {
1416 0 : return dbus_message_new_error(message, DBUS_ERROR_FAILED,
1417 : "Failed to read signal");
1418 : }
1419 :
1420 36 : reply = dbus_message_new_method_return(message);
1421 36 : if (reply == NULL)
1422 0 : goto nomem;
1423 :
1424 36 : dbus_message_iter_init_append(reply, &iter);
1425 :
1426 36 : if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
1427 36 : "a{sv}", &variant_iter) ||
1428 72 : !wpa_dbus_dict_open_write(&variant_iter, &iter_dict) ||
1429 36 : !wpa_dbus_dict_append_int32(&iter_dict, "rssi",
1430 36 : si.current_signal) ||
1431 36 : !wpa_dbus_dict_append_int32(&iter_dict, "linkspeed",
1432 72 : si.current_txrate / 1000) ||
1433 36 : !wpa_dbus_dict_append_int32(&iter_dict, "noise",
1434 36 : si.current_noise) ||
1435 36 : !wpa_dbus_dict_append_uint32(&iter_dict, "frequency",
1436 36 : si.frequency) ||
1437 72 : (si.chanwidth != CHAN_WIDTH_UNKNOWN &&
1438 36 : !wpa_dbus_dict_append_string(
1439 : &iter_dict, "width",
1440 36 : channel_width_to_string(si.chanwidth))) ||
1441 72 : (si.center_frq1 > 0 && si.center_frq2 > 0 &&
1442 0 : (!wpa_dbus_dict_append_int32(&iter_dict, "center-frq1",
1443 0 : si.center_frq1) ||
1444 0 : !wpa_dbus_dict_append_int32(&iter_dict, "center-frq2",
1445 36 : si.center_frq2))) ||
1446 72 : (si.avg_signal &&
1447 36 : !wpa_dbus_dict_append_int32(&iter_dict, "avg-rssi",
1448 36 : si.avg_signal)) ||
1449 72 : !wpa_dbus_dict_close_write(&variant_iter, &iter_dict) ||
1450 36 : !dbus_message_iter_close_container(&iter, &variant_iter))
1451 : goto nomem;
1452 :
1453 36 : return reply;
1454 :
1455 : nomem:
1456 0 : if (reply)
1457 0 : dbus_message_unref(reply);
1458 0 : return wpas_dbus_error_no_memory(message);
1459 : }
1460 :
1461 :
1462 : /*
1463 : * wpas_dbus_handler_disconnect - Terminate the current connection
1464 : * @message: Pointer to incoming dbus message
1465 : * @wpa_s: wpa_supplicant structure for a network interface
1466 : * Returns: NotConnected DBus error message if already not connected
1467 : * or NULL otherwise.
1468 : *
1469 : * Handler function for "Disconnect" method call of network interface.
1470 : */
1471 75 : DBusMessage * wpas_dbus_handler_disconnect(DBusMessage *message,
1472 : struct wpa_supplicant *wpa_s)
1473 : {
1474 75 : if (wpa_s->current_ssid != NULL) {
1475 74 : wpa_s->disconnected = 1;
1476 74 : wpa_supplicant_deauthenticate(wpa_s,
1477 : WLAN_REASON_DEAUTH_LEAVING);
1478 :
1479 74 : return NULL;
1480 : }
1481 :
1482 1 : return dbus_message_new_error(message, WPAS_DBUS_ERROR_NOT_CONNECTED,
1483 : "This interface is not connected");
1484 : }
1485 :
1486 :
1487 : /**
1488 : * wpas_dbus_new_iface_add_network - Add a new configured network
1489 : * @message: Pointer to incoming dbus message
1490 : * @wpa_s: wpa_supplicant structure for a network interface
1491 : * Returns: A dbus message containing the object path of the new network
1492 : *
1493 : * Handler function for "AddNetwork" method call of a network interface.
1494 : */
1495 67 : DBusMessage * wpas_dbus_handler_add_network(DBusMessage *message,
1496 : struct wpa_supplicant *wpa_s)
1497 : {
1498 67 : DBusMessage *reply = NULL;
1499 : DBusMessageIter iter;
1500 67 : struct wpa_ssid *ssid = NULL;
1501 67 : char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf;
1502 : DBusError error;
1503 :
1504 67 : dbus_message_iter_init(message, &iter);
1505 :
1506 67 : if (wpa_s->dbus_new_path)
1507 67 : ssid = wpa_config_add_network(wpa_s->conf);
1508 67 : if (ssid == NULL) {
1509 1 : wpa_printf(MSG_ERROR, "%s[dbus]: can't add new interface.",
1510 : __func__);
1511 1 : reply = wpas_dbus_error_unknown_error(
1512 : message,
1513 : "wpa_supplicant could not add a network on this interface.");
1514 1 : goto err;
1515 : }
1516 66 : wpas_notify_network_added(wpa_s, ssid);
1517 66 : ssid->disabled = 1;
1518 66 : wpa_config_set_network_defaults(ssid);
1519 :
1520 66 : dbus_error_init(&error);
1521 66 : if (!set_network_properties(wpa_s, ssid, &iter, &error)) {
1522 10 : wpa_printf(MSG_DEBUG,
1523 : "%s[dbus]: control interface couldn't set network properties",
1524 : __func__);
1525 10 : reply = wpas_dbus_reply_new_from_error(message, &error,
1526 : DBUS_ERROR_INVALID_ARGS,
1527 : "Failed to add network");
1528 10 : dbus_error_free(&error);
1529 10 : goto err;
1530 : }
1531 :
1532 : /* Construct the object path for this network. */
1533 56 : os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
1534 : "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
1535 : wpa_s->dbus_new_path, ssid->id);
1536 :
1537 56 : reply = dbus_message_new_method_return(message);
1538 56 : if (reply == NULL) {
1539 0 : reply = wpas_dbus_error_no_memory(message);
1540 0 : goto err;
1541 : }
1542 56 : if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
1543 : DBUS_TYPE_INVALID)) {
1544 0 : dbus_message_unref(reply);
1545 0 : reply = wpas_dbus_error_no_memory(message);
1546 0 : goto err;
1547 : }
1548 :
1549 56 : return reply;
1550 :
1551 : err:
1552 11 : if (ssid) {
1553 10 : wpas_notify_network_removed(wpa_s, ssid);
1554 10 : wpa_config_remove_network(wpa_s->conf, ssid->id);
1555 : }
1556 11 : return reply;
1557 : }
1558 :
1559 :
1560 : /**
1561 : * wpas_dbus_handler_reassociate - Reassociate
1562 : * @message: Pointer to incoming dbus message
1563 : * @wpa_s: wpa_supplicant structure for a network interface
1564 : * Returns: InterfaceDisabled DBus error message if disabled
1565 : * or NULL otherwise.
1566 : *
1567 : * Handler function for "Reassociate" method call of network interface.
1568 : */
1569 36 : DBusMessage * wpas_dbus_handler_reassociate(DBusMessage *message,
1570 : struct wpa_supplicant *wpa_s)
1571 : {
1572 36 : if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED) {
1573 36 : wpas_request_connection(wpa_s);
1574 36 : return NULL;
1575 : }
1576 :
1577 0 : return dbus_message_new_error(message, WPAS_DBUS_ERROR_IFACE_DISABLED,
1578 : "This interface is disabled");
1579 : }
1580 :
1581 :
1582 : /**
1583 : * wpas_dbus_handler_reattach - Reattach to current AP
1584 : * @message: Pointer to incoming dbus message
1585 : * @wpa_s: wpa_supplicant structure for a network interface
1586 : * Returns: NotConnected DBus error message if not connected
1587 : * or NULL otherwise.
1588 : *
1589 : * Handler function for "Reattach" method call of network interface.
1590 : */
1591 37 : DBusMessage * wpas_dbus_handler_reattach(DBusMessage *message,
1592 : struct wpa_supplicant *wpa_s)
1593 : {
1594 37 : if (wpa_s->current_ssid != NULL) {
1595 36 : wpa_s->reattach = 1;
1596 36 : wpas_request_connection(wpa_s);
1597 36 : return NULL;
1598 : }
1599 :
1600 1 : return dbus_message_new_error(message, WPAS_DBUS_ERROR_NOT_CONNECTED,
1601 : "This interface is not connected");
1602 : }
1603 :
1604 :
1605 : /**
1606 : * wpas_dbus_handler_reconnect - Reconnect if disconnected
1607 : * @message: Pointer to incoming dbus message
1608 : * @wpa_s: wpa_supplicant structure for a network interface
1609 : * Returns: InterfaceDisabled DBus error message if disabled
1610 : * or NULL otherwise.
1611 : *
1612 : * Handler function for "Reconnect" method call of network interface.
1613 : */
1614 1 : DBusMessage * wpas_dbus_handler_reconnect(DBusMessage *message,
1615 : struct wpa_supplicant *wpa_s)
1616 : {
1617 1 : if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
1618 0 : return dbus_message_new_error(message,
1619 : WPAS_DBUS_ERROR_IFACE_DISABLED,
1620 : "This interface is disabled");
1621 : }
1622 :
1623 1 : if (wpa_s->disconnected)
1624 1 : wpas_request_connection(wpa_s);
1625 1 : return NULL;
1626 : }
1627 :
1628 :
1629 : /**
1630 : * wpas_dbus_handler_remove_network - Remove a configured network
1631 : * @message: Pointer to incoming dbus message
1632 : * @wpa_s: wpa_supplicant structure for a network interface
1633 : * Returns: NULL on success or dbus error on failure
1634 : *
1635 : * Handler function for "RemoveNetwork" method call of a network interface.
1636 : */
1637 43 : DBusMessage * wpas_dbus_handler_remove_network(DBusMessage *message,
1638 : struct wpa_supplicant *wpa_s)
1639 : {
1640 43 : DBusMessage *reply = NULL;
1641 : const char *op;
1642 : char *iface, *net_id;
1643 : int id;
1644 : struct wpa_ssid *ssid;
1645 : int was_disabled;
1646 :
1647 43 : dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
1648 : DBUS_TYPE_INVALID);
1649 :
1650 : /* Extract the network ID and ensure the network */
1651 : /* is actually a child of this interface */
1652 43 : iface = wpas_dbus_new_decompose_object_path(op,
1653 : WPAS_DBUS_NEW_NETWORKS_PART,
1654 : &net_id);
1655 85 : if (iface == NULL || net_id == NULL || !wpa_s->dbus_new_path ||
1656 42 : os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
1657 1 : reply = wpas_dbus_error_invalid_args(message, op);
1658 1 : goto out;
1659 : }
1660 :
1661 42 : errno = 0;
1662 42 : id = strtoul(net_id, NULL, 10);
1663 42 : if (errno != 0) {
1664 0 : reply = wpas_dbus_error_invalid_args(message, op);
1665 0 : goto out;
1666 : }
1667 :
1668 42 : ssid = wpa_config_get_network(wpa_s->conf, id);
1669 42 : if (ssid == NULL) {
1670 1 : reply = wpas_dbus_error_network_unknown(message);
1671 1 : goto out;
1672 : }
1673 :
1674 41 : was_disabled = ssid->disabled;
1675 :
1676 41 : wpas_notify_network_removed(wpa_s, ssid);
1677 :
1678 41 : if (ssid == wpa_s->current_ssid)
1679 36 : wpa_supplicant_deauthenticate(wpa_s,
1680 : WLAN_REASON_DEAUTH_LEAVING);
1681 5 : else if (!was_disabled && wpa_s->sched_scanning) {
1682 0 : wpa_printf(MSG_DEBUG,
1683 : "Stop ongoing sched_scan to remove network from filters");
1684 0 : wpa_supplicant_cancel_sched_scan(wpa_s);
1685 0 : wpa_supplicant_req_scan(wpa_s, 0, 0);
1686 : }
1687 :
1688 41 : if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
1689 0 : wpa_printf(MSG_ERROR,
1690 : "%s[dbus]: error occurred when removing network %d",
1691 : __func__, id);
1692 0 : reply = wpas_dbus_error_unknown_error(
1693 : message,
1694 : "error removing the specified network on is interface.");
1695 0 : goto out;
1696 : }
1697 :
1698 : out:
1699 43 : os_free(iface);
1700 43 : return reply;
1701 : }
1702 :
1703 :
1704 3 : static void remove_network(void *arg, struct wpa_ssid *ssid)
1705 : {
1706 3 : struct wpa_supplicant *wpa_s = arg;
1707 :
1708 3 : wpas_notify_network_removed(wpa_s, ssid);
1709 :
1710 3 : if (wpa_config_remove_network(wpa_s->conf, ssid->id) < 0) {
1711 0 : wpa_printf(MSG_ERROR,
1712 : "%s[dbus]: error occurred when removing network %d",
1713 : __func__, ssid->id);
1714 3 : return;
1715 : }
1716 :
1717 3 : if (ssid == wpa_s->current_ssid)
1718 0 : wpa_supplicant_deauthenticate(wpa_s,
1719 : WLAN_REASON_DEAUTH_LEAVING);
1720 : }
1721 :
1722 :
1723 : /**
1724 : * wpas_dbus_handler_remove_all_networks - Remove all configured networks
1725 : * @message: Pointer to incoming dbus message
1726 : * @wpa_s: wpa_supplicant structure for a network interface
1727 : * Returns: NULL on success or dbus error on failure
1728 : *
1729 : * Handler function for "RemoveAllNetworks" method call of a network interface.
1730 : */
1731 3 : DBusMessage * wpas_dbus_handler_remove_all_networks(
1732 : DBusMessage *message, struct wpa_supplicant *wpa_s)
1733 : {
1734 3 : if (wpa_s->sched_scanning)
1735 0 : wpa_supplicant_cancel_sched_scan(wpa_s);
1736 :
1737 : /* NB: could check for failure and return an error */
1738 3 : wpa_config_foreach_network(wpa_s->conf, remove_network, wpa_s);
1739 3 : return NULL;
1740 : }
1741 :
1742 :
1743 : /**
1744 : * wpas_dbus_handler_select_network - Attempt association with a network
1745 : * @message: Pointer to incoming dbus message
1746 : * @wpa_s: wpa_supplicant structure for a network interface
1747 : * Returns: NULL on success or dbus error on failure
1748 : *
1749 : * Handler function for "SelectNetwork" method call of network interface.
1750 : */
1751 87 : DBusMessage * wpas_dbus_handler_select_network(DBusMessage *message,
1752 : struct wpa_supplicant *wpa_s)
1753 : {
1754 87 : DBusMessage *reply = NULL;
1755 : const char *op;
1756 : char *iface, *net_id;
1757 : int id;
1758 : struct wpa_ssid *ssid;
1759 :
1760 87 : dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
1761 : DBUS_TYPE_INVALID);
1762 :
1763 : /* Extract the network ID and ensure the network */
1764 : /* is actually a child of this interface */
1765 87 : iface = wpas_dbus_new_decompose_object_path(op,
1766 : WPAS_DBUS_NEW_NETWORKS_PART,
1767 : &net_id);
1768 174 : if (iface == NULL || net_id == NULL || !wpa_s->dbus_new_path ||
1769 87 : os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
1770 0 : reply = wpas_dbus_error_invalid_args(message, op);
1771 0 : goto out;
1772 : }
1773 :
1774 87 : errno = 0;
1775 87 : id = strtoul(net_id, NULL, 10);
1776 87 : if (errno != 0) {
1777 0 : reply = wpas_dbus_error_invalid_args(message, op);
1778 0 : goto out;
1779 : }
1780 :
1781 87 : ssid = wpa_config_get_network(wpa_s->conf, id);
1782 87 : if (ssid == NULL) {
1783 1 : reply = wpas_dbus_error_network_unknown(message);
1784 1 : goto out;
1785 : }
1786 :
1787 : /* Finally, associate with the network */
1788 86 : wpa_supplicant_select_network(wpa_s, ssid);
1789 :
1790 : out:
1791 87 : os_free(iface);
1792 87 : return reply;
1793 : }
1794 :
1795 :
1796 : /**
1797 : * wpas_dbus_handler_network_reply - Reply to a NetworkRequest signal
1798 : * @message: Pointer to incoming dbus message
1799 : * @wpa_s: wpa_supplicant structure for a network interface
1800 : * Returns: NULL on success or dbus error on failure
1801 : *
1802 : * Handler function for "NetworkReply" method call of network interface.
1803 : */
1804 2 : DBusMessage * wpas_dbus_handler_network_reply(DBusMessage *message,
1805 : struct wpa_supplicant *wpa_s)
1806 : {
1807 : #ifdef IEEE8021X_EAPOL
1808 2 : DBusMessage *reply = NULL;
1809 : const char *op, *field, *value;
1810 : char *iface, *net_id;
1811 : int id;
1812 : struct wpa_ssid *ssid;
1813 :
1814 2 : if (!dbus_message_get_args(message, NULL,
1815 : DBUS_TYPE_OBJECT_PATH, &op,
1816 : DBUS_TYPE_STRING, &field,
1817 : DBUS_TYPE_STRING, &value,
1818 : DBUS_TYPE_INVALID))
1819 0 : return wpas_dbus_error_invalid_args(message, NULL);
1820 :
1821 : /* Extract the network ID and ensure the network */
1822 : /* is actually a child of this interface */
1823 2 : iface = wpas_dbus_new_decompose_object_path(op,
1824 : WPAS_DBUS_NEW_NETWORKS_PART,
1825 : &net_id);
1826 4 : if (iface == NULL || net_id == NULL || !wpa_s->dbus_new_path ||
1827 2 : os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
1828 0 : reply = wpas_dbus_error_invalid_args(message, op);
1829 0 : goto out;
1830 : }
1831 :
1832 2 : errno = 0;
1833 2 : id = strtoul(net_id, NULL, 10);
1834 2 : if (errno != 0) {
1835 0 : reply = wpas_dbus_error_invalid_args(message, net_id);
1836 0 : goto out;
1837 : }
1838 :
1839 2 : ssid = wpa_config_get_network(wpa_s->conf, id);
1840 2 : if (ssid == NULL) {
1841 0 : reply = wpas_dbus_error_network_unknown(message);
1842 0 : goto out;
1843 : }
1844 :
1845 2 : if (wpa_supplicant_ctrl_iface_ctrl_rsp_handle(wpa_s, ssid,
1846 : field, value) < 0)
1847 0 : reply = wpas_dbus_error_invalid_args(message, field);
1848 : else {
1849 : /* Tell EAP to retry immediately */
1850 2 : eapol_sm_notify_ctrl_response(wpa_s->eapol);
1851 : }
1852 :
1853 : out:
1854 2 : os_free(iface);
1855 2 : return reply;
1856 : #else /* IEEE8021X_EAPOL */
1857 : wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included");
1858 : return wpas_dbus_error_unknown_error(message, "802.1X not included");
1859 : #endif /* IEEE8021X_EAPOL */
1860 : }
1861 :
1862 :
1863 : #ifndef CONFIG_NO_CONFIG_BLOBS
1864 :
1865 : /**
1866 : * wpas_dbus_handler_add_blob - Store named binary blob (ie, for certificates)
1867 : * @message: Pointer to incoming dbus message
1868 : * @wpa_s: %wpa_supplicant data structure
1869 : * Returns: A dbus message containing an error on failure or NULL on success
1870 : *
1871 : * Asks wpa_supplicant to internally store a binary blobs.
1872 : */
1873 6 : DBusMessage * wpas_dbus_handler_add_blob(DBusMessage *message,
1874 : struct wpa_supplicant *wpa_s)
1875 : {
1876 6 : DBusMessage *reply = NULL;
1877 : DBusMessageIter iter, array_iter;
1878 :
1879 : char *blob_name;
1880 : u8 *blob_data;
1881 : int blob_len;
1882 6 : struct wpa_config_blob *blob = NULL;
1883 :
1884 6 : dbus_message_iter_init(message, &iter);
1885 6 : dbus_message_iter_get_basic(&iter, &blob_name);
1886 :
1887 6 : if (wpa_config_get_blob(wpa_s->conf, blob_name)) {
1888 1 : return dbus_message_new_error(message,
1889 : WPAS_DBUS_ERROR_BLOB_EXISTS,
1890 : NULL);
1891 : }
1892 :
1893 5 : dbus_message_iter_next(&iter);
1894 5 : dbus_message_iter_recurse(&iter, &array_iter);
1895 :
1896 5 : dbus_message_iter_get_fixed_array(&array_iter, &blob_data, &blob_len);
1897 :
1898 5 : blob = os_zalloc(sizeof(*blob));
1899 5 : if (!blob) {
1900 1 : reply = wpas_dbus_error_no_memory(message);
1901 1 : goto err;
1902 : }
1903 :
1904 4 : blob->data = os_malloc(blob_len);
1905 4 : blob->name = os_strdup(blob_name);
1906 4 : if (!blob->data || !blob->name) {
1907 2 : reply = wpas_dbus_error_no_memory(message);
1908 2 : goto err;
1909 : }
1910 2 : os_memcpy(blob->data, blob_data, blob_len);
1911 2 : blob->len = blob_len;
1912 :
1913 2 : wpa_config_set_blob(wpa_s->conf, blob);
1914 2 : wpas_notify_blob_added(wpa_s, blob->name);
1915 :
1916 2 : return reply;
1917 :
1918 : err:
1919 3 : if (blob) {
1920 2 : os_free(blob->name);
1921 2 : os_free(blob->data);
1922 2 : os_free(blob);
1923 : }
1924 3 : return reply;
1925 : }
1926 :
1927 :
1928 : /**
1929 : * wpas_dbus_handler_get_blob - Get named binary blob (ie, for certificates)
1930 : * @message: Pointer to incoming dbus message
1931 : * @wpa_s: %wpa_supplicant data structure
1932 : * Returns: A dbus message containing array of bytes (blob)
1933 : *
1934 : * Gets one wpa_supplicant's binary blobs.
1935 : */
1936 2 : DBusMessage * wpas_dbus_handler_get_blob(DBusMessage *message,
1937 : struct wpa_supplicant *wpa_s)
1938 : {
1939 2 : DBusMessage *reply = NULL;
1940 : DBusMessageIter iter, array_iter;
1941 :
1942 : char *blob_name;
1943 : const struct wpa_config_blob *blob;
1944 :
1945 2 : dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &blob_name,
1946 : DBUS_TYPE_INVALID);
1947 :
1948 2 : blob = wpa_config_get_blob(wpa_s->conf, blob_name);
1949 2 : if (!blob) {
1950 1 : return dbus_message_new_error(message,
1951 : WPAS_DBUS_ERROR_BLOB_UNKNOWN,
1952 : "Blob id not set");
1953 : }
1954 :
1955 1 : reply = dbus_message_new_method_return(message);
1956 1 : if (!reply)
1957 0 : return wpas_dbus_error_no_memory(message);
1958 :
1959 1 : dbus_message_iter_init_append(reply, &iter);
1960 :
1961 1 : if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
1962 : DBUS_TYPE_BYTE_AS_STRING,
1963 1 : &array_iter) ||
1964 2 : !dbus_message_iter_append_fixed_array(&array_iter, DBUS_TYPE_BYTE,
1965 3 : &(blob->data), blob->len) ||
1966 1 : !dbus_message_iter_close_container(&iter, &array_iter)) {
1967 0 : dbus_message_unref(reply);
1968 0 : reply = wpas_dbus_error_no_memory(message);
1969 : }
1970 :
1971 1 : return reply;
1972 : }
1973 :
1974 :
1975 : /**
1976 : * wpas_remove_handler_remove_blob - Remove named binary blob
1977 : * @message: Pointer to incoming dbus message
1978 : * @wpa_s: %wpa_supplicant data structure
1979 : * Returns: NULL on success or dbus error
1980 : *
1981 : * Asks wpa_supplicant to internally remove a binary blobs.
1982 : */
1983 3 : DBusMessage * wpas_dbus_handler_remove_blob(DBusMessage *message,
1984 : struct wpa_supplicant *wpa_s)
1985 : {
1986 3 : DBusMessage *reply = NULL;
1987 : char *blob_name;
1988 :
1989 3 : dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &blob_name,
1990 : DBUS_TYPE_INVALID);
1991 :
1992 3 : if (wpa_config_remove_blob(wpa_s->conf, blob_name)) {
1993 1 : return dbus_message_new_error(message,
1994 : WPAS_DBUS_ERROR_BLOB_UNKNOWN,
1995 : "Blob id not set");
1996 : }
1997 2 : wpas_notify_blob_removed(wpa_s, blob_name);
1998 :
1999 2 : return reply;
2000 :
2001 : }
2002 :
2003 : #endif /* CONFIG_NO_CONFIG_BLOBS */
2004 :
2005 :
2006 : /*
2007 : * wpas_dbus_handler_flush_bss - Flush the BSS cache
2008 : * @message: Pointer to incoming dbus message
2009 : * @wpa_s: wpa_supplicant structure for a network interface
2010 : * Returns: NULL
2011 : *
2012 : * Handler function for "FlushBSS" method call of network interface.
2013 : */
2014 2 : DBusMessage * wpas_dbus_handler_flush_bss(DBusMessage *message,
2015 : struct wpa_supplicant *wpa_s)
2016 : {
2017 : dbus_uint32_t age;
2018 :
2019 2 : dbus_message_get_args(message, NULL, DBUS_TYPE_UINT32, &age,
2020 : DBUS_TYPE_INVALID);
2021 :
2022 2 : if (age == 0)
2023 1 : wpa_bss_flush(wpa_s);
2024 : else
2025 1 : wpa_bss_flush_by_age(wpa_s, age);
2026 :
2027 2 : return NULL;
2028 : }
2029 :
2030 :
2031 : #ifdef CONFIG_AUTOSCAN
2032 : /**
2033 : * wpas_dbus_handler_autoscan - Set autoscan parameters for the interface
2034 : * @message: Pointer to incoming dbus message
2035 : * @wpa_s: wpa_supplicant structure for a network interface
2036 : * Returns: NULL
2037 : *
2038 : * Handler function for "AutoScan" method call of network interface.
2039 : */
2040 4 : DBusMessage * wpas_dbus_handler_autoscan(DBusMessage *message,
2041 : struct wpa_supplicant *wpa_s)
2042 : {
2043 4 : DBusMessage *reply = NULL;
2044 4 : enum wpa_states state = wpa_s->wpa_state;
2045 : char *arg;
2046 :
2047 4 : dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &arg,
2048 : DBUS_TYPE_INVALID);
2049 :
2050 7 : if (arg != NULL && os_strlen(arg) > 0) {
2051 : char *tmp;
2052 :
2053 3 : tmp = os_strdup(arg);
2054 3 : if (tmp == NULL) {
2055 1 : reply = wpas_dbus_error_no_memory(message);
2056 : } else {
2057 2 : os_free(wpa_s->conf->autoscan);
2058 2 : wpa_s->conf->autoscan = tmp;
2059 2 : if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
2060 2 : autoscan_init(wpa_s, 1);
2061 0 : else if (state == WPA_SCANNING)
2062 0 : wpa_supplicant_reinit_autoscan(wpa_s);
2063 : }
2064 1 : } else if (arg != NULL && os_strlen(arg) == 0) {
2065 1 : os_free(wpa_s->conf->autoscan);
2066 1 : wpa_s->conf->autoscan = NULL;
2067 1 : autoscan_deinit(wpa_s);
2068 : } else
2069 0 : reply = dbus_message_new_error(message,
2070 : DBUS_ERROR_INVALID_ARGS,
2071 : NULL);
2072 :
2073 4 : return reply;
2074 : }
2075 : #endif /* CONFIG_AUTOSCAN */
2076 :
2077 :
2078 : /*
2079 : * wpas_dbus_handler_eap_logoff - IEEE 802.1X EAPOL state machine logoff
2080 : * @message: Pointer to incoming dbus message
2081 : * @wpa_s: wpa_supplicant structure for a network interface
2082 : * Returns: NULL
2083 : *
2084 : * Handler function for "EAPLogoff" method call of network interface.
2085 : */
2086 1 : DBusMessage * wpas_dbus_handler_eap_logoff(DBusMessage *message,
2087 : struct wpa_supplicant *wpa_s)
2088 : {
2089 1 : eapol_sm_notify_logoff(wpa_s->eapol, TRUE);
2090 1 : return NULL;
2091 : }
2092 :
2093 :
2094 : /*
2095 : * wpas_dbus_handler_eap_logon - IEEE 802.1X EAPOL state machine logon
2096 : * @message: Pointer to incoming dbus message
2097 : * @wpa_s: wpa_supplicant structure for a network interface
2098 : * Returns: NULL
2099 : *
2100 : * Handler function for "EAPLogin" method call of network interface.
2101 : */
2102 1 : DBusMessage * wpas_dbus_handler_eap_logon(DBusMessage *message,
2103 : struct wpa_supplicant *wpa_s)
2104 : {
2105 1 : eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
2106 1 : return NULL;
2107 : }
2108 :
2109 :
2110 : #ifdef CONFIG_TDLS
2111 :
2112 12 : static int get_peer_hwaddr_helper(DBusMessage *message, const char *func_name,
2113 : u8 *peer_address, DBusMessage **error)
2114 : {
2115 : const char *peer_string;
2116 :
2117 12 : *error = NULL;
2118 :
2119 12 : if (!dbus_message_get_args(message, NULL,
2120 : DBUS_TYPE_STRING, &peer_string,
2121 : DBUS_TYPE_INVALID)) {
2122 0 : *error = wpas_dbus_error_invalid_args(message, NULL);
2123 0 : return -1;
2124 : }
2125 :
2126 12 : if (hwaddr_aton(peer_string, peer_address)) {
2127 4 : wpa_printf(MSG_DEBUG, "%s: invalid address '%s'",
2128 : func_name, peer_string);
2129 4 : *error = wpas_dbus_error_invalid_args(
2130 : message, "Invalid hardware address format");
2131 4 : return -1;
2132 : }
2133 :
2134 8 : return 0;
2135 : }
2136 :
2137 :
2138 : /*
2139 : * wpas_dbus_handler_tdls_discover - Discover TDLS peer
2140 : * @message: Pointer to incoming dbus message
2141 : * @wpa_s: wpa_supplicant structure for a network interface
2142 : * Returns: NULL indicating success or DBus error message on failure
2143 : *
2144 : * Handler function for "TDLSDiscover" method call of network interface.
2145 : */
2146 2 : DBusMessage * wpas_dbus_handler_tdls_discover(DBusMessage *message,
2147 : struct wpa_supplicant *wpa_s)
2148 : {
2149 : u8 peer[ETH_ALEN];
2150 : DBusMessage *error_reply;
2151 : int ret;
2152 :
2153 2 : if (get_peer_hwaddr_helper(message, __func__, peer, &error_reply) < 0)
2154 1 : return error_reply;
2155 :
2156 1 : wpa_printf(MSG_DEBUG, "DBUS TDLS_DISCOVER " MACSTR, MAC2STR(peer));
2157 :
2158 1 : if (wpa_tdls_is_external_setup(wpa_s->wpa))
2159 1 : ret = wpa_tdls_send_discovery_request(wpa_s->wpa, peer);
2160 : else
2161 0 : ret = wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer);
2162 :
2163 1 : if (ret) {
2164 0 : return wpas_dbus_error_unknown_error(
2165 : message, "error performing TDLS discovery");
2166 : }
2167 :
2168 1 : return NULL;
2169 : }
2170 :
2171 :
2172 : /*
2173 : * wpas_dbus_handler_tdls_setup - Setup TDLS session
2174 : * @message: Pointer to incoming dbus message
2175 : * @wpa_s: wpa_supplicant structure for a network interface
2176 : * Returns: NULL indicating success or DBus error message on failure
2177 : *
2178 : * Handler function for "TDLSSetup" method call of network interface.
2179 : */
2180 3 : DBusMessage * wpas_dbus_handler_tdls_setup(DBusMessage *message,
2181 : struct wpa_supplicant *wpa_s)
2182 : {
2183 : u8 peer[ETH_ALEN];
2184 : DBusMessage *error_reply;
2185 : int ret;
2186 :
2187 3 : if (get_peer_hwaddr_helper(message, __func__, peer, &error_reply) < 0)
2188 1 : return error_reply;
2189 :
2190 2 : wpa_printf(MSG_DEBUG, "DBUS TDLS_SETUP " MACSTR, MAC2STR(peer));
2191 :
2192 2 : wpa_tdls_remove(wpa_s->wpa, peer);
2193 2 : if (wpa_tdls_is_external_setup(wpa_s->wpa))
2194 2 : ret = wpa_tdls_start(wpa_s->wpa, peer);
2195 : else
2196 0 : ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
2197 :
2198 2 : if (ret) {
2199 1 : return wpas_dbus_error_unknown_error(
2200 : message, "error performing TDLS setup");
2201 : }
2202 :
2203 1 : return NULL;
2204 : }
2205 :
2206 :
2207 : /*
2208 : * wpas_dbus_handler_tdls_status - Return TDLS session status
2209 : * @message: Pointer to incoming dbus message
2210 : * @wpa_s: wpa_supplicant structure for a network interface
2211 : * Returns: A string representing the state of the link to this TDLS peer
2212 : *
2213 : * Handler function for "TDLSStatus" method call of network interface.
2214 : */
2215 4 : DBusMessage * wpas_dbus_handler_tdls_status(DBusMessage *message,
2216 : struct wpa_supplicant *wpa_s)
2217 : {
2218 : u8 peer[ETH_ALEN];
2219 : DBusMessage *reply;
2220 : const char *tdls_status;
2221 :
2222 4 : if (get_peer_hwaddr_helper(message, __func__, peer, &reply) < 0)
2223 1 : return reply;
2224 :
2225 3 : wpa_printf(MSG_DEBUG, "DBUS TDLS_STATUS " MACSTR, MAC2STR(peer));
2226 :
2227 3 : tdls_status = wpa_tdls_get_link_status(wpa_s->wpa, peer);
2228 :
2229 3 : reply = dbus_message_new_method_return(message);
2230 3 : dbus_message_append_args(reply, DBUS_TYPE_STRING,
2231 : &tdls_status, DBUS_TYPE_INVALID);
2232 3 : return reply;
2233 : }
2234 :
2235 :
2236 : /*
2237 : * wpas_dbus_handler_tdls_teardown - Teardown TDLS session
2238 : * @message: Pointer to incoming dbus message
2239 : * @wpa_s: wpa_supplicant structure for a network interface
2240 : * Returns: NULL indicating success or DBus error message on failure
2241 : *
2242 : * Handler function for "TDLSTeardown" method call of network interface.
2243 : */
2244 3 : DBusMessage * wpas_dbus_handler_tdls_teardown(DBusMessage *message,
2245 : struct wpa_supplicant *wpa_s)
2246 : {
2247 : u8 peer[ETH_ALEN];
2248 : DBusMessage *error_reply;
2249 : int ret;
2250 :
2251 3 : if (get_peer_hwaddr_helper(message, __func__, peer, &error_reply) < 0)
2252 1 : return error_reply;
2253 :
2254 2 : wpa_printf(MSG_DEBUG, "DBUS TDLS_TEARDOWN " MACSTR, MAC2STR(peer));
2255 :
2256 2 : if (wpa_tdls_is_external_setup(wpa_s->wpa))
2257 2 : ret = wpa_tdls_teardown_link(
2258 : wpa_s->wpa, peer,
2259 : WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
2260 : else
2261 0 : ret = wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
2262 :
2263 2 : if (ret) {
2264 1 : return wpas_dbus_error_unknown_error(
2265 : message, "error performing TDLS teardown");
2266 : }
2267 :
2268 1 : return NULL;
2269 : }
2270 :
2271 : #endif /* CONFIG_TDLS */
2272 :
2273 :
2274 : /**
2275 : * wpas_dbus_handler_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
2276 : * @message: Pointer to incoming dbus message
2277 : * @wpa_s: %wpa_supplicant data structure
2278 : * Returns: A dbus message containing an error on failure or NULL on success
2279 : *
2280 : * Sets the PKCS #11 engine and module path.
2281 : */
2282 4 : DBusMessage * wpas_dbus_handler_set_pkcs11_engine_and_module_path(
2283 : DBusMessage *message, struct wpa_supplicant *wpa_s)
2284 : {
2285 : DBusMessageIter iter;
2286 4 : char *value = NULL;
2287 4 : char *pkcs11_engine_path = NULL;
2288 4 : char *pkcs11_module_path = NULL;
2289 :
2290 4 : dbus_message_iter_init(message, &iter);
2291 4 : dbus_message_iter_get_basic(&iter, &value);
2292 4 : if (value == NULL) {
2293 0 : return dbus_message_new_error(
2294 : message, DBUS_ERROR_INVALID_ARGS,
2295 : "Invalid pkcs11_engine_path argument");
2296 : }
2297 : /* Empty path defaults to NULL */
2298 4 : if (os_strlen(value))
2299 2 : pkcs11_engine_path = value;
2300 :
2301 4 : dbus_message_iter_next(&iter);
2302 4 : dbus_message_iter_get_basic(&iter, &value);
2303 4 : if (value == NULL) {
2304 0 : os_free(pkcs11_engine_path);
2305 0 : return dbus_message_new_error(
2306 : message, DBUS_ERROR_INVALID_ARGS,
2307 : "Invalid pkcs11_module_path argument");
2308 : }
2309 : /* Empty path defaults to NULL */
2310 4 : if (os_strlen(value))
2311 2 : pkcs11_module_path = value;
2312 :
2313 4 : if (wpas_set_pkcs11_engine_and_module_path(wpa_s, pkcs11_engine_path,
2314 : pkcs11_module_path))
2315 0 : return dbus_message_new_error(
2316 : message, DBUS_ERROR_FAILED,
2317 : "Reinit of the EAPOL state machine with the new PKCS #11 engine and module path failed.");
2318 :
2319 4 : if (wpa_s->dbus_new_path) {
2320 4 : wpa_dbus_mark_property_changed(
2321 4 : wpa_s->global->dbus, wpa_s->dbus_new_path,
2322 : WPAS_DBUS_NEW_IFACE_INTERFACE, "PKCS11EnginePath");
2323 4 : wpa_dbus_mark_property_changed(
2324 4 : wpa_s->global->dbus, wpa_s->dbus_new_path,
2325 : WPAS_DBUS_NEW_IFACE_INTERFACE, "PKCS11ModulePath");
2326 : }
2327 :
2328 4 : return NULL;
2329 : }
2330 :
2331 :
2332 : /**
2333 : * wpas_dbus_getter_capabilities - Return interface capabilities
2334 : * @iter: Pointer to incoming dbus message iter
2335 : * @error: Location to store error on failure
2336 : * @user_data: Function specific data
2337 : * Returns: TRUE on success, FALSE on failure
2338 : *
2339 : * Getter for "Capabilities" property of an interface.
2340 : */
2341 148 : dbus_bool_t wpas_dbus_getter_capabilities(DBusMessageIter *iter,
2342 : DBusError *error, void *user_data)
2343 : {
2344 148 : struct wpa_supplicant *wpa_s = user_data;
2345 : struct wpa_driver_capa capa;
2346 : int res;
2347 : DBusMessageIter iter_dict, iter_dict_entry, iter_dict_val, iter_array,
2348 : variant_iter;
2349 148 : const char *scans[] = { "active", "passive", "ssid" };
2350 :
2351 148 : if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
2352 148 : "a{sv}", &variant_iter) ||
2353 148 : !wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
2354 : goto nomem;
2355 :
2356 148 : res = wpa_drv_get_capa(wpa_s, &capa);
2357 :
2358 : /***** pairwise cipher */
2359 148 : if (res < 0) {
2360 32 : const char *args[] = {"ccmp", "tkip", "none"};
2361 :
2362 32 : if (!wpa_dbus_dict_append_string_array(
2363 : &iter_dict, "Pairwise", args,
2364 : ARRAY_SIZE(args)))
2365 0 : goto nomem;
2366 : } else {
2367 116 : if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Pairwise",
2368 : &iter_dict_entry,
2369 : &iter_dict_val,
2370 116 : &iter_array) ||
2371 232 : ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP_256) &&
2372 116 : !wpa_dbus_dict_string_array_add_element(
2373 116 : &iter_array, "ccmp-256")) ||
2374 232 : ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP_256) &&
2375 116 : !wpa_dbus_dict_string_array_add_element(
2376 116 : &iter_array, "gcmp-256")) ||
2377 232 : ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) &&
2378 116 : !wpa_dbus_dict_string_array_add_element(
2379 116 : &iter_array, "ccmp")) ||
2380 232 : ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP) &&
2381 116 : !wpa_dbus_dict_string_array_add_element(
2382 116 : &iter_array, "gcmp")) ||
2383 232 : ((capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) &&
2384 116 : !wpa_dbus_dict_string_array_add_element(
2385 116 : &iter_array, "tkip")) ||
2386 116 : ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) &&
2387 0 : !wpa_dbus_dict_string_array_add_element(
2388 116 : &iter_array, "none")) ||
2389 116 : !wpa_dbus_dict_end_string_array(&iter_dict,
2390 : &iter_dict_entry,
2391 : &iter_dict_val,
2392 : &iter_array))
2393 : goto nomem;
2394 : }
2395 :
2396 : /***** group cipher */
2397 148 : if (res < 0) {
2398 32 : const char *args[] = {
2399 : "ccmp", "tkip", "wep104", "wep40"
2400 : };
2401 :
2402 32 : if (!wpa_dbus_dict_append_string_array(
2403 : &iter_dict, "Group", args,
2404 : ARRAY_SIZE(args)))
2405 0 : goto nomem;
2406 : } else {
2407 116 : if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Group",
2408 : &iter_dict_entry,
2409 : &iter_dict_val,
2410 116 : &iter_array) ||
2411 232 : ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP_256) &&
2412 116 : !wpa_dbus_dict_string_array_add_element(
2413 116 : &iter_array, "ccmp-256")) ||
2414 232 : ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP_256) &&
2415 116 : !wpa_dbus_dict_string_array_add_element(
2416 116 : &iter_array, "gcmp-256")) ||
2417 232 : ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) &&
2418 116 : !wpa_dbus_dict_string_array_add_element(
2419 116 : &iter_array, "ccmp")) ||
2420 232 : ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP) &&
2421 116 : !wpa_dbus_dict_string_array_add_element(
2422 116 : &iter_array, "gcmp")) ||
2423 232 : ((capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) &&
2424 116 : !wpa_dbus_dict_string_array_add_element(
2425 116 : &iter_array, "tkip")) ||
2426 232 : ((capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) &&
2427 116 : !wpa_dbus_dict_string_array_add_element(
2428 116 : &iter_array, "wep104")) ||
2429 232 : ((capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) &&
2430 116 : !wpa_dbus_dict_string_array_add_element(
2431 116 : &iter_array, "wep40")) ||
2432 116 : !wpa_dbus_dict_end_string_array(&iter_dict,
2433 : &iter_dict_entry,
2434 : &iter_dict_val,
2435 : &iter_array))
2436 : goto nomem;
2437 : }
2438 :
2439 : /***** key management */
2440 148 : if (res < 0) {
2441 32 : const char *args[] = {
2442 : "wpa-psk", "wpa-eap", "ieee8021x", "wpa-none",
2443 : #ifdef CONFIG_WPS
2444 : "wps",
2445 : #endif /* CONFIG_WPS */
2446 : "none"
2447 : };
2448 32 : if (!wpa_dbus_dict_append_string_array(
2449 : &iter_dict, "KeyMgmt", args,
2450 : ARRAY_SIZE(args)))
2451 0 : goto nomem;
2452 : } else {
2453 116 : if (!wpa_dbus_dict_begin_string_array(&iter_dict, "KeyMgmt",
2454 : &iter_dict_entry,
2455 : &iter_dict_val,
2456 116 : &iter_array) ||
2457 116 : !wpa_dbus_dict_string_array_add_element(&iter_array,
2458 116 : "none") ||
2459 116 : !wpa_dbus_dict_string_array_add_element(&iter_array,
2460 : "ieee8021x"))
2461 : goto nomem;
2462 :
2463 116 : if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
2464 : WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
2465 116 : if (!wpa_dbus_dict_string_array_add_element(
2466 116 : &iter_array, "wpa-eap") ||
2467 147 : ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT) &&
2468 31 : !wpa_dbus_dict_string_array_add_element(
2469 : &iter_array, "wpa-ft-eap")))
2470 : goto nomem;
2471 :
2472 : /* TODO: Ensure that driver actually supports sha256 encryption. */
2473 : #ifdef CONFIG_IEEE80211W
2474 116 : if (!wpa_dbus_dict_string_array_add_element(
2475 : &iter_array, "wpa-eap-sha256"))
2476 0 : goto nomem;
2477 : #endif /* CONFIG_IEEE80211W */
2478 : }
2479 :
2480 116 : if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
2481 : WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
2482 116 : if (!wpa_dbus_dict_string_array_add_element(
2483 116 : &iter_array, "wpa-psk") ||
2484 116 : ((capa.key_mgmt &
2485 31 : WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK) &&
2486 31 : !wpa_dbus_dict_string_array_add_element(
2487 : &iter_array, "wpa-ft-psk")))
2488 : goto nomem;
2489 :
2490 : /* TODO: Ensure that driver actually supports sha256 encryption. */
2491 : #ifdef CONFIG_IEEE80211W
2492 116 : if (!wpa_dbus_dict_string_array_add_element(
2493 : &iter_array, "wpa-psk-sha256"))
2494 0 : goto nomem;
2495 : #endif /* CONFIG_IEEE80211W */
2496 : }
2497 :
2498 116 : if ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) &&
2499 0 : !wpa_dbus_dict_string_array_add_element(&iter_array,
2500 : "wpa-none"))
2501 0 : goto nomem;
2502 :
2503 :
2504 : #ifdef CONFIG_WPS
2505 116 : if (!wpa_dbus_dict_string_array_add_element(&iter_array,
2506 : "wps"))
2507 0 : goto nomem;
2508 : #endif /* CONFIG_WPS */
2509 :
2510 116 : if (!wpa_dbus_dict_end_string_array(&iter_dict,
2511 : &iter_dict_entry,
2512 : &iter_dict_val,
2513 : &iter_array))
2514 0 : goto nomem;
2515 : }
2516 :
2517 : /***** WPA protocol */
2518 148 : if (res < 0) {
2519 32 : const char *args[] = { "rsn", "wpa" };
2520 :
2521 32 : if (!wpa_dbus_dict_append_string_array(
2522 : &iter_dict, "Protocol", args,
2523 : ARRAY_SIZE(args)))
2524 0 : goto nomem;
2525 : } else {
2526 116 : if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Protocol",
2527 : &iter_dict_entry,
2528 : &iter_dict_val,
2529 116 : &iter_array) ||
2530 116 : ((capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
2531 116 : WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) &&
2532 116 : !wpa_dbus_dict_string_array_add_element(
2533 116 : &iter_array, "rsn")) ||
2534 116 : ((capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
2535 116 : WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) &&
2536 116 : !wpa_dbus_dict_string_array_add_element(
2537 116 : &iter_array, "wpa")) ||
2538 116 : !wpa_dbus_dict_end_string_array(&iter_dict,
2539 : &iter_dict_entry,
2540 : &iter_dict_val,
2541 : &iter_array))
2542 : goto nomem;
2543 : }
2544 :
2545 : /***** auth alg */
2546 148 : if (res < 0) {
2547 32 : const char *args[] = { "open", "shared", "leap" };
2548 :
2549 32 : if (!wpa_dbus_dict_append_string_array(
2550 : &iter_dict, "AuthAlg", args,
2551 : ARRAY_SIZE(args)))
2552 0 : goto nomem;
2553 : } else {
2554 116 : if (!wpa_dbus_dict_begin_string_array(&iter_dict, "AuthAlg",
2555 : &iter_dict_entry,
2556 : &iter_dict_val,
2557 : &iter_array))
2558 0 : goto nomem;
2559 :
2560 232 : if (((capa.auth & WPA_DRIVER_AUTH_OPEN) &&
2561 116 : !wpa_dbus_dict_string_array_add_element(
2562 116 : &iter_array, "open")) ||
2563 232 : ((capa.auth & WPA_DRIVER_AUTH_SHARED) &&
2564 116 : !wpa_dbus_dict_string_array_add_element(
2565 116 : &iter_array, "shared")) ||
2566 232 : ((capa.auth & WPA_DRIVER_AUTH_LEAP) &&
2567 116 : !wpa_dbus_dict_string_array_add_element(
2568 116 : &iter_array, "leap")) ||
2569 116 : !wpa_dbus_dict_end_string_array(&iter_dict,
2570 : &iter_dict_entry,
2571 : &iter_dict_val,
2572 : &iter_array))
2573 : goto nomem;
2574 : }
2575 :
2576 : /***** Scan */
2577 148 : if (!wpa_dbus_dict_append_string_array(&iter_dict, "Scan", scans,
2578 : ARRAY_SIZE(scans)))
2579 0 : goto nomem;
2580 :
2581 : /***** Modes */
2582 148 : if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Modes",
2583 : &iter_dict_entry,
2584 : &iter_dict_val,
2585 148 : &iter_array) ||
2586 148 : !wpa_dbus_dict_string_array_add_element(
2587 148 : &iter_array, "infrastructure") ||
2588 148 : !wpa_dbus_dict_string_array_add_element(
2589 148 : &iter_array, "ad-hoc") ||
2590 232 : (res >= 0 && (capa.flags & WPA_DRIVER_FLAGS_AP) &&
2591 116 : !wpa_dbus_dict_string_array_add_element(
2592 148 : &iter_array, "ap")) ||
2593 232 : (res >= 0 && (capa.flags & WPA_DRIVER_FLAGS_P2P_CAPABLE) &&
2594 116 : !wpa_dbus_dict_string_array_add_element(
2595 148 : &iter_array, "p2p")) ||
2596 148 : !wpa_dbus_dict_end_string_array(&iter_dict,
2597 : &iter_dict_entry,
2598 : &iter_dict_val,
2599 : &iter_array))
2600 : goto nomem;
2601 : /***** Modes end */
2602 :
2603 148 : if (res >= 0) {
2604 116 : dbus_int32_t max_scan_ssid = capa.max_scan_ssids;
2605 :
2606 116 : if (!wpa_dbus_dict_append_int32(&iter_dict, "MaxScanSSID",
2607 : max_scan_ssid))
2608 0 : goto nomem;
2609 : }
2610 :
2611 296 : if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict) ||
2612 148 : !dbus_message_iter_close_container(iter, &variant_iter))
2613 : goto nomem;
2614 :
2615 148 : return TRUE;
2616 :
2617 : nomem:
2618 0 : dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
2619 0 : return FALSE;
2620 : }
2621 :
2622 :
2623 : /**
2624 : * wpas_dbus_getter_state - Get interface state
2625 : * @iter: Pointer to incoming dbus message iter
2626 : * @error: Location to store error on failure
2627 : * @user_data: Function specific data
2628 : * Returns: TRUE on success, FALSE on failure
2629 : *
2630 : * Getter for "State" property.
2631 : */
2632 28745 : dbus_bool_t wpas_dbus_getter_state(DBusMessageIter *iter, DBusError *error,
2633 : void *user_data)
2634 : {
2635 28745 : struct wpa_supplicant *wpa_s = user_data;
2636 : const char *str_state;
2637 : char *state_ls, *tmp;
2638 28745 : dbus_bool_t success = FALSE;
2639 :
2640 28745 : str_state = wpa_supplicant_state_txt(wpa_s->wpa_state);
2641 :
2642 : /* make state string lowercase to fit new DBus API convention
2643 : */
2644 28745 : state_ls = tmp = os_strdup(str_state);
2645 28745 : if (!tmp) {
2646 7 : dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
2647 7 : return FALSE;
2648 : }
2649 374550 : while (*tmp) {
2650 317074 : *tmp = tolower(*tmp);
2651 317074 : tmp++;
2652 : }
2653 :
2654 28738 : success = wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
2655 : &state_ls, error);
2656 :
2657 28738 : os_free(state_ls);
2658 :
2659 28738 : return success;
2660 : }
2661 :
2662 :
2663 : /**
2664 : * wpas_dbus_new_iface_get_scanning - Get interface scanning state
2665 : * @iter: Pointer to incoming dbus message iter
2666 : * @error: Location to store error on failure
2667 : * @user_data: Function specific data
2668 : * Returns: TRUE on success, FALSE on failure
2669 : *
2670 : * Getter for "scanning" property.
2671 : */
2672 8111 : dbus_bool_t wpas_dbus_getter_scanning(DBusMessageIter *iter, DBusError *error,
2673 : void *user_data)
2674 : {
2675 8111 : struct wpa_supplicant *wpa_s = user_data;
2676 8111 : dbus_bool_t scanning = wpa_s->scanning ? TRUE : FALSE;
2677 :
2678 8111 : return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
2679 : &scanning, error);
2680 : }
2681 :
2682 :
2683 : /**
2684 : * wpas_dbus_getter_ap_scan - Control roaming mode
2685 : * @iter: Pointer to incoming dbus message iter
2686 : * @error: Location to store error on failure
2687 : * @user_data: Function specific data
2688 : * Returns: TRUE on success, FALSE on failure
2689 : *
2690 : * Getter function for "ApScan" property.
2691 : */
2692 175 : dbus_bool_t wpas_dbus_getter_ap_scan(DBusMessageIter *iter, DBusError *error,
2693 : void *user_data)
2694 : {
2695 175 : struct wpa_supplicant *wpa_s = user_data;
2696 175 : dbus_uint32_t ap_scan = wpa_s->conf->ap_scan;
2697 :
2698 175 : return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
2699 : &ap_scan, error);
2700 : }
2701 :
2702 :
2703 : /**
2704 : * wpas_dbus_setter_ap_scan - Control roaming mode
2705 : * @iter: Pointer to incoming dbus message iter
2706 : * @error: Location to store error on failure
2707 : * @user_data: Function specific data
2708 : * Returns: TRUE on success, FALSE on failure
2709 : *
2710 : * Setter function for "ApScan" property.
2711 : */
2712 6 : dbus_bool_t wpas_dbus_setter_ap_scan(DBusMessageIter *iter, DBusError *error,
2713 : void *user_data)
2714 : {
2715 6 : struct wpa_supplicant *wpa_s = user_data;
2716 : dbus_uint32_t ap_scan;
2717 :
2718 6 : if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
2719 : &ap_scan))
2720 1 : return FALSE;
2721 :
2722 5 : if (wpa_supplicant_set_ap_scan(wpa_s, ap_scan)) {
2723 1 : dbus_set_error_const(error, DBUS_ERROR_FAILED,
2724 : "ap_scan must be 0, 1, or 2");
2725 1 : return FALSE;
2726 : }
2727 4 : return TRUE;
2728 : }
2729 :
2730 :
2731 : /**
2732 : * wpas_dbus_getter_fast_reauth - Control fast
2733 : * reauthentication (TLS session resumption)
2734 : * @iter: Pointer to incoming dbus message iter
2735 : * @error: Location to store error on failure
2736 : * @user_data: Function specific data
2737 : * Returns: TRUE on success, FALSE on failure
2738 : *
2739 : * Getter function for "FastReauth" property.
2740 : */
2741 148 : dbus_bool_t wpas_dbus_getter_fast_reauth(DBusMessageIter *iter,
2742 : DBusError *error,
2743 : void *user_data)
2744 : {
2745 148 : struct wpa_supplicant *wpa_s = user_data;
2746 148 : dbus_bool_t fast_reauth = wpa_s->conf->fast_reauth ? TRUE : FALSE;
2747 :
2748 148 : return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
2749 : &fast_reauth, error);
2750 : }
2751 :
2752 :
2753 : /**
2754 : * wpas_dbus_setter_fast_reauth - Control fast
2755 : * reauthentication (TLS session resumption)
2756 : * @iter: Pointer to incoming dbus message iter
2757 : * @error: Location to store error on failure
2758 : * @user_data: Function specific data
2759 : * Returns: TRUE on success, FALSE on failure
2760 : *
2761 : * Setter function for "FastReauth" property.
2762 : */
2763 4 : dbus_bool_t wpas_dbus_setter_fast_reauth(DBusMessageIter *iter,
2764 : DBusError *error,
2765 : void *user_data)
2766 : {
2767 4 : struct wpa_supplicant *wpa_s = user_data;
2768 : dbus_bool_t fast_reauth;
2769 :
2770 4 : if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
2771 : &fast_reauth))
2772 1 : return FALSE;
2773 :
2774 3 : wpa_s->conf->fast_reauth = fast_reauth;
2775 3 : return TRUE;
2776 : }
2777 :
2778 :
2779 : /**
2780 : * wpas_dbus_getter_disconnect_reason - Get most recent reason for disconnect
2781 : * @iter: Pointer to incoming dbus message iter
2782 : * @error: Location to store error on failure
2783 : * @user_data: Function specific data
2784 : * Returns: TRUE on success, FALSE on failure
2785 : *
2786 : * Getter for "DisconnectReason" property. The reason is negative if it is
2787 : * locally generated.
2788 : */
2789 4413 : dbus_bool_t wpas_dbus_getter_disconnect_reason(DBusMessageIter *iter,
2790 : DBusError *error,
2791 : void *user_data)
2792 : {
2793 4413 : struct wpa_supplicant *wpa_s = user_data;
2794 4413 : dbus_int32_t reason = wpa_s->disconnect_reason;
2795 :
2796 4413 : return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
2797 : &reason, error);
2798 : }
2799 :
2800 :
2801 : /**
2802 : * wpas_dbus_getter_bss_expire_age - Get BSS entry expiration age
2803 : * @iter: Pointer to incoming dbus message iter
2804 : * @error: Location to store error on failure
2805 : * @user_data: Function specific data
2806 : * Returns: TRUE on success, FALSE on failure
2807 : *
2808 : * Getter function for "BSSExpireAge" property.
2809 : */
2810 148 : dbus_bool_t wpas_dbus_getter_bss_expire_age(DBusMessageIter *iter,
2811 : DBusError *error,
2812 : void *user_data)
2813 : {
2814 148 : struct wpa_supplicant *wpa_s = user_data;
2815 148 : dbus_uint32_t expire_age = wpa_s->conf->bss_expiration_age;
2816 :
2817 148 : return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
2818 : &expire_age, error);
2819 : }
2820 :
2821 :
2822 : /**
2823 : * wpas_dbus_setter_bss_expire_age - Control BSS entry expiration age
2824 : * @iter: Pointer to incoming dbus message iter
2825 : * @error: Location to store error on failure
2826 : * @user_data: Function specific data
2827 : * Returns: TRUE on success, FALSE on failure
2828 : *
2829 : * Setter function for "BSSExpireAge" property.
2830 : */
2831 4 : dbus_bool_t wpas_dbus_setter_bss_expire_age(DBusMessageIter *iter,
2832 : DBusError *error,
2833 : void *user_data)
2834 : {
2835 4 : struct wpa_supplicant *wpa_s = user_data;
2836 : dbus_uint32_t expire_age;
2837 :
2838 4 : if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
2839 : &expire_age))
2840 1 : return FALSE;
2841 :
2842 3 : if (wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age)) {
2843 1 : dbus_set_error_const(error, DBUS_ERROR_FAILED,
2844 : "BSSExpireAge must be >= 10");
2845 1 : return FALSE;
2846 : }
2847 2 : return TRUE;
2848 : }
2849 :
2850 :
2851 : /**
2852 : * wpas_dbus_getter_bss_expire_count - Get BSS entry expiration scan count
2853 : * @iter: Pointer to incoming dbus message iter
2854 : * @error: Location to store error on failure
2855 : * @user_data: Function specific data
2856 : * Returns: TRUE on success, FALSE on failure
2857 : *
2858 : * Getter function for "BSSExpireCount" property.
2859 : */
2860 148 : dbus_bool_t wpas_dbus_getter_bss_expire_count(DBusMessageIter *iter,
2861 : DBusError *error,
2862 : void *user_data)
2863 : {
2864 148 : struct wpa_supplicant *wpa_s = user_data;
2865 148 : dbus_uint32_t expire_count = wpa_s->conf->bss_expiration_scan_count;
2866 :
2867 148 : return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
2868 : &expire_count, error);
2869 : }
2870 :
2871 :
2872 : /**
2873 : * wpas_dbus_setter_bss_expire_count - Control BSS entry expiration scan count
2874 : * @iter: Pointer to incoming dbus message iter
2875 : * @error: Location to store error on failure
2876 : * @user_data: Function specific data
2877 : * Returns: TRUE on success, FALSE on failure
2878 : *
2879 : * Setter function for "BSSExpireCount" property.
2880 : */
2881 4 : dbus_bool_t wpas_dbus_setter_bss_expire_count(DBusMessageIter *iter,
2882 : DBusError *error,
2883 : void *user_data)
2884 : {
2885 4 : struct wpa_supplicant *wpa_s = user_data;
2886 : dbus_uint32_t expire_count;
2887 :
2888 4 : if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
2889 : &expire_count))
2890 1 : return FALSE;
2891 :
2892 3 : if (wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count)) {
2893 1 : dbus_set_error_const(error, DBUS_ERROR_FAILED,
2894 : "BSSExpireCount must be > 0");
2895 1 : return FALSE;
2896 : }
2897 2 : return TRUE;
2898 : }
2899 :
2900 :
2901 : /**
2902 : * wpas_dbus_getter_country - Control country code
2903 : * @iter: Pointer to incoming dbus message iter
2904 : * @error: Location to store error on failure
2905 : * @user_data: Function specific data
2906 : * Returns: TRUE on success, FALSE on failure
2907 : *
2908 : * Getter function for "Country" property.
2909 : */
2910 148 : dbus_bool_t wpas_dbus_getter_country(DBusMessageIter *iter, DBusError *error,
2911 : void *user_data)
2912 : {
2913 148 : struct wpa_supplicant *wpa_s = user_data;
2914 : char country[3];
2915 148 : char *str = country;
2916 :
2917 148 : country[0] = wpa_s->conf->country[0];
2918 148 : country[1] = wpa_s->conf->country[1];
2919 148 : country[2] = '\0';
2920 :
2921 148 : return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
2922 : &str, error);
2923 : }
2924 :
2925 :
2926 : /**
2927 : * wpas_dbus_setter_country - Control country code
2928 : * @iter: Pointer to incoming dbus message iter
2929 : * @error: Location to store error on failure
2930 : * @user_data: Function specific data
2931 : * Returns: TRUE on success, FALSE on failure
2932 : *
2933 : * Setter function for "Country" property.
2934 : */
2935 4 : dbus_bool_t wpas_dbus_setter_country(DBusMessageIter *iter, DBusError *error,
2936 : void *user_data)
2937 : {
2938 4 : struct wpa_supplicant *wpa_s = user_data;
2939 : const char *country;
2940 :
2941 4 : if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
2942 : &country))
2943 1 : return FALSE;
2944 :
2945 3 : if (!country[0] || !country[1]) {
2946 1 : dbus_set_error_const(error, DBUS_ERROR_FAILED,
2947 : "invalid country code");
2948 1 : return FALSE;
2949 : }
2950 :
2951 2 : if (wpa_s->drv_priv != NULL && wpa_drv_set_country(wpa_s, country)) {
2952 0 : wpa_printf(MSG_DEBUG, "Failed to set country");
2953 0 : dbus_set_error_const(error, DBUS_ERROR_FAILED,
2954 : "failed to set country code");
2955 0 : return FALSE;
2956 : }
2957 :
2958 2 : wpa_s->conf->country[0] = country[0];
2959 2 : wpa_s->conf->country[1] = country[1];
2960 2 : return TRUE;
2961 : }
2962 :
2963 :
2964 : /**
2965 : * wpas_dbus_getter_scan_interval - Get scan interval
2966 : * @iter: Pointer to incoming dbus message iter
2967 : * @error: Location to store error on failure
2968 : * @user_data: Function specific data
2969 : * Returns: TRUE on success, FALSE on failure
2970 : *
2971 : * Getter function for "ScanInterval" property.
2972 : */
2973 146 : dbus_bool_t wpas_dbus_getter_scan_interval(DBusMessageIter *iter,
2974 : DBusError *error,
2975 : void *user_data)
2976 : {
2977 146 : struct wpa_supplicant *wpa_s = user_data;
2978 146 : dbus_int32_t scan_interval = wpa_s->scan_interval;
2979 :
2980 146 : return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
2981 : &scan_interval, error);
2982 : }
2983 :
2984 :
2985 : /**
2986 : * wpas_dbus_setter_scan_interval - Control scan interval
2987 : * @iter: Pointer to incoming dbus message iter
2988 : * @error: Location to store error on failure
2989 : * @user_data: Function specific data
2990 : * Returns: TRUE on success, FALSE on failure
2991 : *
2992 : * Setter function for "ScanInterval" property.
2993 : */
2994 4 : dbus_bool_t wpas_dbus_setter_scan_interval(DBusMessageIter *iter,
2995 : DBusError *error,
2996 : void *user_data)
2997 : {
2998 4 : struct wpa_supplicant *wpa_s = user_data;
2999 : dbus_int32_t scan_interval;
3000 :
3001 4 : if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_INT32,
3002 : &scan_interval))
3003 1 : return FALSE;
3004 :
3005 3 : if (wpa_supplicant_set_scan_interval(wpa_s, scan_interval)) {
3006 1 : dbus_set_error_const(error, DBUS_ERROR_FAILED,
3007 : "scan_interval must be >= 0");
3008 1 : return FALSE;
3009 : }
3010 2 : return TRUE;
3011 : }
3012 :
3013 :
3014 : /**
3015 : * wpas_dbus_getter_ifname - Get interface name
3016 : * @iter: Pointer to incoming dbus message iter
3017 : * @error: Location to store error on failure
3018 : * @user_data: Function specific data
3019 : * Returns: TRUE on success, FALSE on failure
3020 : *
3021 : * Getter for "Ifname" property.
3022 : */
3023 147 : dbus_bool_t wpas_dbus_getter_ifname(DBusMessageIter *iter, DBusError *error,
3024 : void *user_data)
3025 : {
3026 147 : struct wpa_supplicant *wpa_s = user_data;
3027 147 : const char *ifname = wpa_s->ifname;
3028 :
3029 147 : return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3030 : &ifname, error);
3031 : }
3032 :
3033 :
3034 : /**
3035 : * wpas_dbus_getter_driver - Get interface name
3036 : * @iter: Pointer to incoming dbus message iter
3037 : * @error: Location to store error on failure
3038 : * @user_data: Function specific data
3039 : * Returns: TRUE on success, FALSE on failure
3040 : *
3041 : * Getter for "Driver" property.
3042 : */
3043 147 : dbus_bool_t wpas_dbus_getter_driver(DBusMessageIter *iter, DBusError *error,
3044 : void *user_data)
3045 : {
3046 147 : struct wpa_supplicant *wpa_s = user_data;
3047 : const char *driver;
3048 :
3049 147 : if (wpa_s->driver == NULL || wpa_s->driver->name == NULL) {
3050 0 : wpa_printf(MSG_DEBUG, "%s[dbus]: wpa_s has no driver set",
3051 : __func__);
3052 0 : dbus_set_error(error, DBUS_ERROR_FAILED, "%s: no driver set",
3053 : __func__);
3054 0 : return FALSE;
3055 : }
3056 :
3057 147 : driver = wpa_s->driver->name;
3058 147 : return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3059 : &driver, error);
3060 : }
3061 :
3062 :
3063 : /**
3064 : * wpas_dbus_getter_current_bss - Get current bss object path
3065 : * @iter: Pointer to incoming dbus message iter
3066 : * @error: Location to store error on failure
3067 : * @user_data: Function specific data
3068 : * Returns: TRUE on success, FALSE on failure
3069 : *
3070 : * Getter for "CurrentBSS" property.
3071 : */
3072 9578 : dbus_bool_t wpas_dbus_getter_current_bss(DBusMessageIter *iter,
3073 : DBusError *error,
3074 : void *user_data)
3075 : {
3076 9578 : struct wpa_supplicant *wpa_s = user_data;
3077 9578 : char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *bss_obj_path = path_buf;
3078 :
3079 9578 : if (wpa_s->current_bss && wpa_s->dbus_new_path)
3080 5269 : os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3081 : "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
3082 5269 : wpa_s->dbus_new_path, wpa_s->current_bss->id);
3083 : else
3084 4309 : os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
3085 :
3086 9578 : return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
3087 : &bss_obj_path, error);
3088 : }
3089 :
3090 :
3091 : /**
3092 : * wpas_dbus_getter_current_network - Get current network object path
3093 : * @iter: Pointer to incoming dbus message iter
3094 : * @error: Location to store error on failure
3095 : * @user_data: Function specific data
3096 : * Returns: TRUE on success, FALSE on failure
3097 : *
3098 : * Getter for "CurrentNetwork" property.
3099 : */
3100 1603 : dbus_bool_t wpas_dbus_getter_current_network(DBusMessageIter *iter,
3101 : DBusError *error,
3102 : void *user_data)
3103 : {
3104 1603 : struct wpa_supplicant *wpa_s = user_data;
3105 1603 : char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *net_obj_path = path_buf;
3106 :
3107 1603 : if (wpa_s->current_ssid && wpa_s->dbus_new_path)
3108 1332 : os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3109 : "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
3110 1332 : wpa_s->dbus_new_path, wpa_s->current_ssid->id);
3111 : else
3112 271 : os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
3113 :
3114 1603 : return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
3115 : &net_obj_path, error);
3116 : }
3117 :
3118 :
3119 : /**
3120 : * wpas_dbus_getter_current_auth_mode - Get current authentication type
3121 : * @iter: Pointer to incoming dbus message iter
3122 : * @error: Location to store error on failure
3123 : * @user_data: Function specific data
3124 : * Returns: TRUE on success, FALSE on failure
3125 : *
3126 : * Getter for "CurrentAuthMode" property.
3127 : */
3128 7795 : dbus_bool_t wpas_dbus_getter_current_auth_mode(DBusMessageIter *iter,
3129 : DBusError *error,
3130 : void *user_data)
3131 : {
3132 7795 : struct wpa_supplicant *wpa_s = user_data;
3133 : const char *eap_mode;
3134 : const char *auth_mode;
3135 : char eap_mode_buf[WPAS_DBUS_AUTH_MODE_MAX];
3136 :
3137 7795 : if (wpa_s->wpa_state != WPA_COMPLETED) {
3138 3861 : auth_mode = "INACTIVE";
3139 6562 : } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X ||
3140 2628 : wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3141 1332 : eap_mode = wpa_supplicant_get_eap_mode(wpa_s);
3142 1332 : os_snprintf(eap_mode_buf, WPAS_DBUS_AUTH_MODE_MAX,
3143 : "EAP-%s", eap_mode);
3144 1332 : auth_mode = eap_mode_buf;
3145 :
3146 : } else {
3147 2602 : auth_mode = wpa_key_mgmt_txt(wpa_s->key_mgmt,
3148 2602 : wpa_s->current_ssid->proto);
3149 : }
3150 :
3151 7795 : return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3152 : &auth_mode, error);
3153 : }
3154 :
3155 :
3156 : /**
3157 : * wpas_dbus_getter_bridge_ifname - Get interface name
3158 : * @iter: Pointer to incoming dbus message iter
3159 : * @error: Location to store error on failure
3160 : * @user_data: Function specific data
3161 : * Returns: TRUE on success, FALSE on failure
3162 : *
3163 : * Getter for "BridgeIfname" property.
3164 : */
3165 147 : dbus_bool_t wpas_dbus_getter_bridge_ifname(DBusMessageIter *iter,
3166 : DBusError *error,
3167 : void *user_data)
3168 : {
3169 147 : struct wpa_supplicant *wpa_s = user_data;
3170 147 : const char *bridge_ifname = wpa_s->bridge_ifname;
3171 :
3172 147 : return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3173 : &bridge_ifname, error);
3174 : }
3175 :
3176 :
3177 : /**
3178 : * wpas_dbus_getter_bsss - Get array of BSSs objects
3179 : * @iter: Pointer to incoming dbus message iter
3180 : * @error: Location to store error on failure
3181 : * @user_data: Function specific data
3182 : * Returns: TRUE on success, FALSE on failure
3183 : *
3184 : * Getter for "BSSs" property.
3185 : */
3186 4939 : dbus_bool_t wpas_dbus_getter_bsss(DBusMessageIter *iter, DBusError *error,
3187 : void *user_data)
3188 : {
3189 4939 : struct wpa_supplicant *wpa_s = user_data;
3190 : struct wpa_bss *bss;
3191 : char **paths;
3192 4939 : unsigned int i = 0;
3193 4939 : dbus_bool_t success = FALSE;
3194 :
3195 4939 : if (!wpa_s->dbus_new_path) {
3196 0 : dbus_set_error(error, DBUS_ERROR_FAILED,
3197 : "%s: no D-Bus interface", __func__);
3198 0 : return FALSE;
3199 : }
3200 :
3201 4939 : paths = os_calloc(wpa_s->num_bss, sizeof(char *));
3202 4939 : if (!paths) {
3203 3 : dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3204 3 : return FALSE;
3205 : }
3206 :
3207 : /* Loop through scan results and append each result's object path */
3208 7863 : dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
3209 2928 : paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
3210 2928 : if (paths[i] == NULL) {
3211 1 : dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
3212 : "no memory");
3213 1 : goto out;
3214 : }
3215 : /* Construct the object path for this BSS. */
3216 2927 : os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
3217 : "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
3218 : wpa_s->dbus_new_path, bss->id);
3219 : }
3220 :
3221 4935 : success = wpas_dbus_simple_array_property_getter(iter,
3222 : DBUS_TYPE_OBJECT_PATH,
3223 : paths, wpa_s->num_bss,
3224 : error);
3225 :
3226 : out:
3227 12799 : while (i)
3228 2927 : os_free(paths[--i]);
3229 4936 : os_free(paths);
3230 4936 : return success;
3231 : }
3232 :
3233 :
3234 : /**
3235 : * wpas_dbus_getter_networks - Get array of networks objects
3236 : * @iter: Pointer to incoming dbus message iter
3237 : * @error: Location to store error on failure
3238 : * @user_data: Function specific data
3239 : * Returns: TRUE on success, FALSE on failure
3240 : *
3241 : * Getter for "Networks" property.
3242 : */
3243 153 : dbus_bool_t wpas_dbus_getter_networks(DBusMessageIter *iter, DBusError *error,
3244 : void *user_data)
3245 : {
3246 153 : struct wpa_supplicant *wpa_s = user_data;
3247 : struct wpa_ssid *ssid;
3248 : char **paths;
3249 153 : unsigned int i = 0, num = 0;
3250 153 : dbus_bool_t success = FALSE;
3251 :
3252 153 : if (!wpa_s->dbus_new_path) {
3253 0 : dbus_set_error(error, DBUS_ERROR_FAILED,
3254 : "%s: no D-Bus interface", __func__);
3255 0 : return FALSE;
3256 : }
3257 :
3258 158 : for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
3259 5 : if (!network_is_persistent_group(ssid))
3260 5 : num++;
3261 :
3262 153 : paths = os_calloc(num, sizeof(char *));
3263 153 : if (!paths) {
3264 2 : dbus_set_error(error, DBUS_ERROR_NO_MEMORY, "no memory");
3265 2 : return FALSE;
3266 : }
3267 :
3268 : /* Loop through configured networks and append object path of each */
3269 154 : for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
3270 4 : if (network_is_persistent_group(ssid))
3271 0 : continue;
3272 4 : paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
3273 4 : if (paths[i] == NULL) {
3274 1 : dbus_set_error(error, DBUS_ERROR_NO_MEMORY,
3275 : "no memory");
3276 1 : goto out;
3277 : }
3278 :
3279 : /* Construct the object path for this network. */
3280 3 : os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
3281 : "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
3282 : wpa_s->dbus_new_path, ssid->id);
3283 : }
3284 :
3285 150 : success = wpas_dbus_simple_array_property_getter(iter,
3286 : DBUS_TYPE_OBJECT_PATH,
3287 : paths, num, error);
3288 :
3289 : out:
3290 305 : while (i)
3291 3 : os_free(paths[--i]);
3292 151 : os_free(paths);
3293 151 : return success;
3294 : }
3295 :
3296 :
3297 : /**
3298 : * wpas_dbus_getter_pkcs11_engine_path - Get PKCS #11 engine path
3299 : * @iter: Pointer to incoming dbus message iter
3300 : * @error: Location to store error on failure
3301 : * @user_data: Function specific data
3302 : * Returns: A dbus message containing the PKCS #11 engine path
3303 : *
3304 : * Getter for "PKCS11EnginePath" property.
3305 : */
3306 155 : dbus_bool_t wpas_dbus_getter_pkcs11_engine_path(DBusMessageIter *iter,
3307 : DBusError *error,
3308 : void *user_data)
3309 : {
3310 155 : struct wpa_supplicant *wpa_s = user_data;
3311 : const char *pkcs11_engine_path;
3312 :
3313 155 : if (wpa_s->conf->pkcs11_engine_path == NULL)
3314 151 : pkcs11_engine_path = "";
3315 : else
3316 4 : pkcs11_engine_path = wpa_s->conf->pkcs11_engine_path;
3317 155 : return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3318 : &pkcs11_engine_path, error);
3319 : }
3320 :
3321 :
3322 : /**
3323 : * wpas_dbus_getter_pkcs11_module_path - Get PKCS #11 module path
3324 : * @iter: Pointer to incoming dbus message iter
3325 : * @error: Location to store error on failure
3326 : * @user_data: Function specific data
3327 : * Returns: A dbus message containing the PKCS #11 module path
3328 : *
3329 : * Getter for "PKCS11ModulePath" property.
3330 : */
3331 155 : dbus_bool_t wpas_dbus_getter_pkcs11_module_path(DBusMessageIter *iter,
3332 : DBusError *error,
3333 : void *user_data)
3334 : {
3335 155 : struct wpa_supplicant *wpa_s = user_data;
3336 : const char *pkcs11_module_path;
3337 :
3338 155 : if (wpa_s->conf->pkcs11_module_path == NULL)
3339 150 : pkcs11_module_path = "";
3340 : else
3341 5 : pkcs11_module_path = wpa_s->conf->pkcs11_module_path;
3342 155 : return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3343 : &pkcs11_module_path, error);
3344 : }
3345 :
3346 :
3347 : /**
3348 : * wpas_dbus_getter_blobs - Get all blobs defined for this interface
3349 : * @iter: Pointer to incoming dbus message iter
3350 : * @error: Location to store error on failure
3351 : * @user_data: Function specific data
3352 : * Returns: TRUE on success, FALSE on failure
3353 : *
3354 : * Getter for "Blobs" property.
3355 : */
3356 148 : dbus_bool_t wpas_dbus_getter_blobs(DBusMessageIter *iter, DBusError *error,
3357 : void *user_data)
3358 : {
3359 148 : struct wpa_supplicant *wpa_s = user_data;
3360 : DBusMessageIter variant_iter, dict_iter, entry_iter, array_iter;
3361 : struct wpa_config_blob *blob;
3362 :
3363 148 : if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
3364 148 : "a{say}", &variant_iter) ||
3365 148 : !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
3366 : "{say}", &dict_iter)) {
3367 0 : dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3368 0 : return FALSE;
3369 : }
3370 :
3371 148 : blob = wpa_s->conf->blobs;
3372 297 : while (blob) {
3373 1 : if (!dbus_message_iter_open_container(&dict_iter,
3374 : DBUS_TYPE_DICT_ENTRY,
3375 1 : NULL, &entry_iter) ||
3376 1 : !dbus_message_iter_append_basic(&entry_iter,
3377 : DBUS_TYPE_STRING,
3378 2 : &(blob->name)) ||
3379 1 : !dbus_message_iter_open_container(&entry_iter,
3380 : DBUS_TYPE_ARRAY,
3381 : DBUS_TYPE_BYTE_AS_STRING,
3382 1 : &array_iter) ||
3383 2 : !dbus_message_iter_append_fixed_array(&array_iter,
3384 : DBUS_TYPE_BYTE,
3385 1 : &(blob->data),
3386 2 : blob->len) ||
3387 1 : !dbus_message_iter_close_container(&entry_iter,
3388 1 : &array_iter) ||
3389 1 : !dbus_message_iter_close_container(&dict_iter,
3390 : &entry_iter)) {
3391 0 : dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
3392 : "no memory");
3393 0 : return FALSE;
3394 : }
3395 :
3396 1 : blob = blob->next;
3397 : }
3398 :
3399 296 : if (!dbus_message_iter_close_container(&variant_iter, &dict_iter) ||
3400 148 : !dbus_message_iter_close_container(iter, &variant_iter)) {
3401 0 : dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3402 0 : return FALSE;
3403 : }
3404 :
3405 148 : return TRUE;
3406 : }
3407 :
3408 :
3409 18739 : static struct wpa_bss * get_bss_helper(struct bss_handler_args *args,
3410 : DBusError *error, const char *func_name)
3411 : {
3412 18739 : struct wpa_bss *res = wpa_bss_get_id(args->wpa_s, args->id);
3413 :
3414 18739 : if (!res) {
3415 0 : wpa_printf(MSG_ERROR, "%s[dbus]: no bss with id %d found",
3416 : func_name, args->id);
3417 0 : dbus_set_error(error, DBUS_ERROR_FAILED,
3418 : "%s: BSS %d not found",
3419 : func_name, args->id);
3420 : }
3421 :
3422 18739 : return res;
3423 : }
3424 :
3425 :
3426 : /**
3427 : * wpas_dbus_getter_bss_bssid - Return the BSSID of a BSS
3428 : * @iter: Pointer to incoming dbus message iter
3429 : * @error: Location to store error on failure
3430 : * @user_data: Function specific data
3431 : * Returns: TRUE on success, FALSE on failure
3432 : *
3433 : * Getter for "BSSID" property.
3434 : */
3435 1391 : dbus_bool_t wpas_dbus_getter_bss_bssid(DBusMessageIter *iter, DBusError *error,
3436 : void *user_data)
3437 : {
3438 1391 : struct bss_handler_args *args = user_data;
3439 : struct wpa_bss *res;
3440 :
3441 1391 : res = get_bss_helper(args, error, __func__);
3442 1391 : if (!res)
3443 0 : return FALSE;
3444 :
3445 1391 : return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
3446 1391 : res->bssid, ETH_ALEN,
3447 : error);
3448 : }
3449 :
3450 :
3451 : /**
3452 : * wpas_dbus_getter_bss_ssid - Return the SSID of a BSS
3453 : * @iter: Pointer to incoming dbus message iter
3454 : * @error: Location to store error on failure
3455 : * @user_data: Function specific data
3456 : * Returns: TRUE on success, FALSE on failure
3457 : *
3458 : * Getter for "SSID" property.
3459 : */
3460 1391 : dbus_bool_t wpas_dbus_getter_bss_ssid(DBusMessageIter *iter, DBusError *error,
3461 : void *user_data)
3462 : {
3463 1391 : struct bss_handler_args *args = user_data;
3464 : struct wpa_bss *res;
3465 :
3466 1391 : res = get_bss_helper(args, error, __func__);
3467 1391 : if (!res)
3468 0 : return FALSE;
3469 :
3470 2782 : return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
3471 1391 : res->ssid, res->ssid_len,
3472 : error);
3473 : }
3474 :
3475 :
3476 : /**
3477 : * wpas_dbus_getter_bss_privacy - Return the privacy flag of a BSS
3478 : * @iter: Pointer to incoming dbus message iter
3479 : * @error: Location to store error on failure
3480 : * @user_data: Function specific data
3481 : * Returns: TRUE on success, FALSE on failure
3482 : *
3483 : * Getter for "Privacy" property.
3484 : */
3485 1409 : dbus_bool_t wpas_dbus_getter_bss_privacy(DBusMessageIter *iter,
3486 : DBusError *error, void *user_data)
3487 : {
3488 1409 : struct bss_handler_args *args = user_data;
3489 : struct wpa_bss *res;
3490 : dbus_bool_t privacy;
3491 :
3492 1409 : res = get_bss_helper(args, error, __func__);
3493 1409 : if (!res)
3494 0 : return FALSE;
3495 :
3496 1409 : privacy = (res->caps & IEEE80211_CAP_PRIVACY) ? TRUE : FALSE;
3497 1409 : return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
3498 : &privacy, error);
3499 : }
3500 :
3501 :
3502 : /**
3503 : * wpas_dbus_getter_bss_mode - Return the mode of a BSS
3504 : * @iter: Pointer to incoming dbus message iter
3505 : * @error: Location to store error on failure
3506 : * @user_data: Function specific data
3507 : * Returns: TRUE on success, FALSE on failure
3508 : *
3509 : * Getter for "Mode" property.
3510 : */
3511 1391 : dbus_bool_t wpas_dbus_getter_bss_mode(DBusMessageIter *iter, DBusError *error,
3512 : void *user_data)
3513 : {
3514 1391 : struct bss_handler_args *args = user_data;
3515 : struct wpa_bss *res;
3516 : const char *mode;
3517 :
3518 1391 : res = get_bss_helper(args, error, __func__);
3519 1391 : if (!res)
3520 0 : return FALSE;
3521 1391 : if (bss_is_dmg(res)) {
3522 0 : switch (res->caps & IEEE80211_CAP_DMG_MASK) {
3523 : case IEEE80211_CAP_DMG_PBSS:
3524 : case IEEE80211_CAP_DMG_IBSS:
3525 0 : mode = "ad-hoc";
3526 0 : break;
3527 : case IEEE80211_CAP_DMG_AP:
3528 0 : mode = "infrastructure";
3529 0 : break;
3530 : }
3531 : } else {
3532 1391 : if (res->caps & IEEE80211_CAP_IBSS)
3533 10 : mode = "ad-hoc";
3534 : else
3535 1381 : mode = "infrastructure";
3536 : }
3537 :
3538 1391 : return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3539 : &mode, error);
3540 : }
3541 :
3542 :
3543 : /**
3544 : * wpas_dbus_getter_bss_level - Return the signal strength of a BSS
3545 : * @iter: Pointer to incoming dbus message iter
3546 : * @error: Location to store error on failure
3547 : * @user_data: Function specific data
3548 : * Returns: TRUE on success, FALSE on failure
3549 : *
3550 : * Getter for "Level" property.
3551 : */
3552 1391 : dbus_bool_t wpas_dbus_getter_bss_signal(DBusMessageIter *iter,
3553 : DBusError *error, void *user_data)
3554 : {
3555 1391 : struct bss_handler_args *args = user_data;
3556 : struct wpa_bss *res;
3557 : s16 level;
3558 :
3559 1391 : res = get_bss_helper(args, error, __func__);
3560 1391 : if (!res)
3561 0 : return FALSE;
3562 :
3563 1391 : level = (s16) res->level;
3564 1391 : return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT16,
3565 : &level, error);
3566 : }
3567 :
3568 :
3569 : /**
3570 : * wpas_dbus_getter_bss_frequency - Return the frequency of a BSS
3571 : * @iter: Pointer to incoming dbus message iter
3572 : * @error: Location to store error on failure
3573 : * @user_data: Function specific data
3574 : * Returns: TRUE on success, FALSE on failure
3575 : *
3576 : * Getter for "Frequency" property.
3577 : */
3578 1395 : dbus_bool_t wpas_dbus_getter_bss_frequency(DBusMessageIter *iter,
3579 : DBusError *error, void *user_data)
3580 : {
3581 1395 : struct bss_handler_args *args = user_data;
3582 : struct wpa_bss *res;
3583 : u16 freq;
3584 :
3585 1395 : res = get_bss_helper(args, error, __func__);
3586 1395 : if (!res)
3587 0 : return FALSE;
3588 :
3589 1395 : freq = (u16) res->freq;
3590 1395 : return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
3591 : &freq, error);
3592 : }
3593 :
3594 :
3595 30421 : static int cmp_u8s_desc(const void *a, const void *b)
3596 : {
3597 30421 : return (*(u8 *) b - *(u8 *) a);
3598 : }
3599 :
3600 :
3601 : /**
3602 : * wpas_dbus_getter_bss_rates - Return available bit rates of a BSS
3603 : * @iter: Pointer to incoming dbus message iter
3604 : * @error: Location to store error on failure
3605 : * @user_data: Function specific data
3606 : * Returns: TRUE on success, FALSE on failure
3607 : *
3608 : * Getter for "Rates" property.
3609 : */
3610 1392 : dbus_bool_t wpas_dbus_getter_bss_rates(DBusMessageIter *iter,
3611 : DBusError *error, void *user_data)
3612 : {
3613 1392 : struct bss_handler_args *args = user_data;
3614 : struct wpa_bss *res;
3615 1392 : u8 *ie_rates = NULL;
3616 : u32 *real_rates;
3617 : int rates_num, i;
3618 1392 : dbus_bool_t success = FALSE;
3619 :
3620 1392 : res = get_bss_helper(args, error, __func__);
3621 1392 : if (!res)
3622 0 : return FALSE;
3623 :
3624 1392 : rates_num = wpa_bss_get_bit_rates(res, &ie_rates);
3625 1392 : if (rates_num < 0)
3626 0 : return FALSE;
3627 :
3628 1392 : qsort(ie_rates, rates_num, 1, cmp_u8s_desc);
3629 :
3630 1392 : real_rates = os_malloc(sizeof(u32) * rates_num);
3631 1392 : if (!real_rates) {
3632 1 : os_free(ie_rates);
3633 1 : dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3634 1 : return FALSE;
3635 : }
3636 :
3637 17499 : for (i = 0; i < rates_num; i++)
3638 16108 : real_rates[i] = ie_rates[i] * 500000;
3639 :
3640 1391 : success = wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_UINT32,
3641 : real_rates, rates_num,
3642 : error);
3643 :
3644 1391 : os_free(ie_rates);
3645 1391 : os_free(real_rates);
3646 1391 : return success;
3647 : }
3648 :
3649 :
3650 2812 : static dbus_bool_t wpas_dbus_get_bss_security_prop(DBusMessageIter *iter,
3651 : struct wpa_ie_data *ie_data,
3652 : DBusError *error)
3653 : {
3654 : DBusMessageIter iter_dict, variant_iter;
3655 : const char *group;
3656 : const char *pairwise[5]; /* max 5 pairwise ciphers is supported */
3657 : const char *key_mgmt[9]; /* max 9 key managements may be supported */
3658 : int n;
3659 :
3660 2812 : if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
3661 : "a{sv}", &variant_iter))
3662 0 : goto nomem;
3663 :
3664 2812 : if (!wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
3665 0 : goto nomem;
3666 :
3667 : /* KeyMgmt */
3668 2812 : n = 0;
3669 2812 : if (ie_data->key_mgmt & WPA_KEY_MGMT_PSK)
3670 511 : key_mgmt[n++] = "wpa-psk";
3671 2812 : if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_PSK)
3672 52 : key_mgmt[n++] = "wpa-ft-psk";
3673 2812 : if (ie_data->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
3674 17 : key_mgmt[n++] = "wpa-psk-sha256";
3675 2812 : if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X)
3676 399 : key_mgmt[n++] = "wpa-eap";
3677 2812 : if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X)
3678 7 : key_mgmt[n++] = "wpa-ft-eap";
3679 2812 : if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256)
3680 4 : key_mgmt[n++] = "wpa-eap-sha256";
3681 : #ifdef CONFIG_SUITEB
3682 2812 : if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B)
3683 2 : key_mgmt[n++] = "wpa-eap-suite-b";
3684 : #endif /* CONFIG_SUITEB */
3685 : #ifdef CONFIG_SUITEB192
3686 2812 : if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
3687 2 : key_mgmt[n++] = "wpa-eap-suite-b-192";
3688 : #endif /* CONFIG_SUITEB192 */
3689 2812 : if (ie_data->key_mgmt & WPA_KEY_MGMT_NONE)
3690 0 : key_mgmt[n++] = "wpa-none";
3691 :
3692 2812 : if (!wpa_dbus_dict_append_string_array(&iter_dict, "KeyMgmt",
3693 : key_mgmt, n))
3694 0 : goto nomem;
3695 :
3696 : /* Group */
3697 2812 : switch (ie_data->group_cipher) {
3698 : case WPA_CIPHER_WEP40:
3699 0 : group = "wep40";
3700 0 : break;
3701 : case WPA_CIPHER_TKIP:
3702 78 : group = "tkip";
3703 78 : break;
3704 : case WPA_CIPHER_CCMP:
3705 916 : group = "ccmp";
3706 916 : break;
3707 : case WPA_CIPHER_GCMP:
3708 3 : group = "gcmp";
3709 3 : break;
3710 : case WPA_CIPHER_WEP104:
3711 0 : group = "wep104";
3712 0 : break;
3713 : case WPA_CIPHER_CCMP_256:
3714 1 : group = "ccmp-256";
3715 1 : break;
3716 : case WPA_CIPHER_GCMP_256:
3717 5 : group = "gcmp-256";
3718 5 : break;
3719 : default:
3720 1809 : group = "";
3721 1809 : break;
3722 : }
3723 :
3724 2812 : if (!wpa_dbus_dict_append_string(&iter_dict, "Group", group))
3725 0 : goto nomem;
3726 :
3727 : /* Pairwise */
3728 2812 : n = 0;
3729 2812 : if (ie_data->pairwise_cipher & WPA_CIPHER_TKIP)
3730 65 : pairwise[n++] = "tkip";
3731 2812 : if (ie_data->pairwise_cipher & WPA_CIPHER_CCMP)
3732 962 : pairwise[n++] = "ccmp";
3733 2812 : if (ie_data->pairwise_cipher & WPA_CIPHER_GCMP)
3734 3 : pairwise[n++] = "gcmp";
3735 2812 : if (ie_data->pairwise_cipher & WPA_CIPHER_CCMP_256)
3736 1 : pairwise[n++] = "ccmp-256";
3737 2812 : if (ie_data->pairwise_cipher & WPA_CIPHER_GCMP_256)
3738 5 : pairwise[n++] = "gcmp-256";
3739 :
3740 2812 : if (!wpa_dbus_dict_append_string_array(&iter_dict, "Pairwise",
3741 : pairwise, n))
3742 0 : goto nomem;
3743 :
3744 : /* Management group (RSN only) */
3745 2812 : if (ie_data->proto == WPA_PROTO_RSN) {
3746 956 : switch (ie_data->mgmt_group_cipher) {
3747 : #ifdef CONFIG_IEEE80211W
3748 : case WPA_CIPHER_AES_128_CMAC:
3749 949 : group = "aes128cmac";
3750 949 : break;
3751 : #endif /* CONFIG_IEEE80211W */
3752 : default:
3753 7 : group = "";
3754 7 : break;
3755 : }
3756 :
3757 956 : if (!wpa_dbus_dict_append_string(&iter_dict, "MgmtGroup",
3758 : group))
3759 0 : goto nomem;
3760 : }
3761 :
3762 5624 : if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict) ||
3763 2812 : !dbus_message_iter_close_container(iter, &variant_iter))
3764 : goto nomem;
3765 :
3766 2812 : return TRUE;
3767 :
3768 : nomem:
3769 0 : dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3770 0 : return FALSE;
3771 : }
3772 :
3773 :
3774 : /**
3775 : * wpas_dbus_getter_bss_wpa - Return the WPA options of a BSS
3776 : * @iter: Pointer to incoming dbus message iter
3777 : * @error: Location to store error on failure
3778 : * @user_data: Function specific data
3779 : * Returns: TRUE on success, FALSE on failure
3780 : *
3781 : * Getter for "WPA" property.
3782 : */
3783 1405 : dbus_bool_t wpas_dbus_getter_bss_wpa(DBusMessageIter *iter, DBusError *error,
3784 : void *user_data)
3785 : {
3786 1405 : struct bss_handler_args *args = user_data;
3787 : struct wpa_bss *res;
3788 : struct wpa_ie_data wpa_data;
3789 : const u8 *ie;
3790 :
3791 1405 : res = get_bss_helper(args, error, __func__);
3792 1405 : if (!res)
3793 0 : return FALSE;
3794 :
3795 1405 : os_memset(&wpa_data, 0, sizeof(wpa_data));
3796 1405 : ie = wpa_bss_get_vendor_ie(res, WPA_IE_VENDOR_TYPE);
3797 1405 : if (ie && wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0) {
3798 0 : dbus_set_error_const(error, DBUS_ERROR_FAILED,
3799 : "failed to parse WPA IE");
3800 0 : return FALSE;
3801 : }
3802 :
3803 1405 : return wpas_dbus_get_bss_security_prop(iter, &wpa_data, error);
3804 : }
3805 :
3806 :
3807 : /**
3808 : * wpas_dbus_getter_bss_rsn - Return the RSN options of a BSS
3809 : * @iter: Pointer to incoming dbus message iter
3810 : * @error: Location to store error on failure
3811 : * @user_data: Function specific data
3812 : * Returns: TRUE on success, FALSE on failure
3813 : *
3814 : * Getter for "RSN" property.
3815 : */
3816 1407 : dbus_bool_t wpas_dbus_getter_bss_rsn(DBusMessageIter *iter, DBusError *error,
3817 : void *user_data)
3818 : {
3819 1407 : struct bss_handler_args *args = user_data;
3820 : struct wpa_bss *res;
3821 : struct wpa_ie_data wpa_data;
3822 : const u8 *ie;
3823 :
3824 1407 : res = get_bss_helper(args, error, __func__);
3825 1407 : if (!res)
3826 0 : return FALSE;
3827 :
3828 1407 : os_memset(&wpa_data, 0, sizeof(wpa_data));
3829 1407 : ie = wpa_bss_get_ie(res, WLAN_EID_RSN);
3830 1407 : if (ie && wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0) {
3831 0 : dbus_set_error_const(error, DBUS_ERROR_FAILED,
3832 : "failed to parse RSN IE");
3833 0 : return FALSE;
3834 : }
3835 :
3836 1407 : return wpas_dbus_get_bss_security_prop(iter, &wpa_data, error);
3837 : }
3838 :
3839 :
3840 : /**
3841 : * wpas_dbus_getter_bss_wps - Return the WPS options of a BSS
3842 : * @iter: Pointer to incoming dbus message iter
3843 : * @error: Location to store error on failure
3844 : * @user_data: Function specific data
3845 : * Returns: TRUE on success, FALSE on failure
3846 : *
3847 : * Getter for "WPS" property.
3848 : */
3849 1457 : dbus_bool_t wpas_dbus_getter_bss_wps(DBusMessageIter *iter, DBusError *error,
3850 : void *user_data)
3851 : {
3852 1457 : struct bss_handler_args *args = user_data;
3853 : struct wpa_bss *res;
3854 : #ifdef CONFIG_WPS
3855 : struct wpabuf *wps_ie;
3856 : #endif /* CONFIG_WPS */
3857 : DBusMessageIter iter_dict, variant_iter;
3858 1457 : int wps_support = 0;
3859 1457 : const char *type = "";
3860 :
3861 1457 : res = get_bss_helper(args, error, __func__);
3862 1457 : if (!res)
3863 0 : return FALSE;
3864 :
3865 1457 : if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
3866 1457 : "a{sv}", &variant_iter) ||
3867 1457 : !wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
3868 : goto nomem;
3869 :
3870 : #ifdef CONFIG_WPS
3871 1457 : wps_ie = wpa_bss_get_vendor_ie_multi(res, WPS_IE_VENDOR_TYPE);
3872 1457 : if (wps_ie) {
3873 413 : wps_support = 1;
3874 413 : if (wps_is_selected_pbc_registrar(wps_ie))
3875 100 : type = "pbc";
3876 313 : else if (wps_is_selected_pin_registrar(wps_ie))
3877 199 : type = "pin";
3878 :
3879 413 : wpabuf_free(wps_ie);
3880 : }
3881 : #endif /* CONFIG_WPS */
3882 :
3883 2914 : if ((wps_support && !wpa_dbus_dict_append_string(&iter_dict, "Type", type)) ||
3884 2914 : !wpa_dbus_dict_close_write(&variant_iter, &iter_dict) ||
3885 1457 : !dbus_message_iter_close_container(iter, &variant_iter))
3886 : goto nomem;
3887 :
3888 1457 : return TRUE;
3889 :
3890 : nomem:
3891 0 : dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3892 0 : return FALSE;
3893 : }
3894 :
3895 :
3896 : /**
3897 : * wpas_dbus_getter_bss_ies - Return all IEs of a BSS
3898 : * @iter: Pointer to incoming dbus message iter
3899 : * @error: Location to store error on failure
3900 : * @user_data: Function specific data
3901 : * Returns: TRUE on success, FALSE on failure
3902 : *
3903 : * Getter for "IEs" property.
3904 : */
3905 1479 : dbus_bool_t wpas_dbus_getter_bss_ies(DBusMessageIter *iter, DBusError *error,
3906 : void *user_data)
3907 : {
3908 1479 : struct bss_handler_args *args = user_data;
3909 : struct wpa_bss *res;
3910 :
3911 1479 : res = get_bss_helper(args, error, __func__);
3912 1479 : if (!res)
3913 0 : return FALSE;
3914 :
3915 1479 : return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
3916 : res + 1, res->ie_len,
3917 : error);
3918 : }
3919 :
3920 :
3921 : /**
3922 : * wpas_dbus_getter_bss_age - Return time in seconds since BSS was last seen
3923 : * @iter: Pointer to incoming dbus message iter
3924 : * @error: Location to store error on failure
3925 : * @user_data: Function specific data
3926 : * Returns: TRUE on success, FALSE on failure
3927 : *
3928 : * Getter for BSS age
3929 : */
3930 3231 : dbus_bool_t wpas_dbus_getter_bss_age(DBusMessageIter *iter, DBusError *error,
3931 : void *user_data)
3932 : {
3933 3231 : struct bss_handler_args *args = user_data;
3934 : struct wpa_bss *res;
3935 3231 : struct os_reltime now, diff = { 0, 0 };
3936 : u32 age;
3937 :
3938 3231 : res = get_bss_helper(args, error, __func__);
3939 3231 : if (!res)
3940 0 : return FALSE;
3941 :
3942 3231 : os_get_reltime(&now);
3943 3231 : os_reltime_sub(&now, &res->last_update, &diff);
3944 3231 : age = diff.sec > 0 ? diff.sec : 0;
3945 3231 : return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32, &age,
3946 : error);
3947 : }
3948 :
3949 :
3950 : /**
3951 : * wpas_dbus_getter_enabled - Check whether network is enabled or disabled
3952 : * @iter: Pointer to incoming dbus message iter
3953 : * @error: Location to store error on failure
3954 : * @user_data: Function specific data
3955 : * Returns: TRUE on success, FALSE on failure
3956 : *
3957 : * Getter for "enabled" property of a configured network.
3958 : */
3959 5793 : dbus_bool_t wpas_dbus_getter_enabled(DBusMessageIter *iter, DBusError *error,
3960 : void *user_data)
3961 : {
3962 5793 : struct network_handler_args *net = user_data;
3963 5793 : dbus_bool_t enabled = net->ssid->disabled ? FALSE : TRUE;
3964 :
3965 5793 : return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
3966 : &enabled, error);
3967 : }
3968 :
3969 :
3970 : /**
3971 : * wpas_dbus_setter_enabled - Mark a configured network as enabled or disabled
3972 : * @iter: Pointer to incoming dbus message iter
3973 : * @error: Location to store error on failure
3974 : * @user_data: Function specific data
3975 : * Returns: TRUE on success, FALSE on failure
3976 : *
3977 : * Setter for "Enabled" property of a configured network.
3978 : */
3979 3 : dbus_bool_t wpas_dbus_setter_enabled(DBusMessageIter *iter, DBusError *error,
3980 : void *user_data)
3981 : {
3982 3 : struct network_handler_args *net = user_data;
3983 : struct wpa_supplicant *wpa_s;
3984 : struct wpa_ssid *ssid;
3985 : dbus_bool_t enable;
3986 :
3987 3 : if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
3988 : &enable))
3989 1 : return FALSE;
3990 :
3991 2 : wpa_s = net->wpa_s;
3992 2 : ssid = net->ssid;
3993 :
3994 2 : if (enable)
3995 1 : wpa_supplicant_enable_network(wpa_s, ssid);
3996 : else
3997 1 : wpa_supplicant_disable_network(wpa_s, ssid);
3998 :
3999 2 : return TRUE;
4000 : }
4001 :
4002 :
4003 : /**
4004 : * wpas_dbus_getter_network_properties - Get options for a configured network
4005 : * @iter: Pointer to incoming dbus message iter
4006 : * @error: Location to store error on failure
4007 : * @user_data: Function specific data
4008 : * Returns: TRUE on success, FALSE on failure
4009 : *
4010 : * Getter for "Properties" property of a configured network.
4011 : */
4012 2877 : dbus_bool_t wpas_dbus_getter_network_properties(DBusMessageIter *iter,
4013 : DBusError *error,
4014 : void *user_data)
4015 : {
4016 2877 : struct network_handler_args *net = user_data;
4017 : DBusMessageIter variant_iter, dict_iter;
4018 : char **iterator;
4019 2877 : char **props = wpa_config_get_all(net->ssid, 1);
4020 2877 : dbus_bool_t success = FALSE;
4021 :
4022 2877 : if (!props) {
4023 1 : dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
4024 1 : return FALSE;
4025 : }
4026 :
4027 2876 : if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a{sv}",
4028 2876 : &variant_iter) ||
4029 2876 : !wpa_dbus_dict_open_write(&variant_iter, &dict_iter)) {
4030 0 : dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
4031 0 : goto out;
4032 : }
4033 :
4034 2876 : iterator = props;
4035 178350 : while (*iterator) {
4036 172598 : if (!wpa_dbus_dict_append_string(&dict_iter, *iterator,
4037 172598 : *(iterator + 1))) {
4038 0 : dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
4039 : "no memory");
4040 0 : goto out;
4041 : }
4042 172598 : iterator += 2;
4043 : }
4044 :
4045 :
4046 5752 : if (!wpa_dbus_dict_close_write(&variant_iter, &dict_iter) ||
4047 2876 : !dbus_message_iter_close_container(iter, &variant_iter)) {
4048 0 : dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
4049 0 : goto out;
4050 : }
4051 :
4052 2876 : success = TRUE;
4053 :
4054 : out:
4055 2876 : iterator = props;
4056 350948 : while (*iterator) {
4057 345196 : os_free(*iterator);
4058 345196 : iterator++;
4059 : }
4060 2876 : os_free(props);
4061 2876 : return success;
4062 : }
4063 :
4064 :
4065 : /**
4066 : * wpas_dbus_setter_network_properties - Set options for a configured network
4067 : * @iter: Pointer to incoming dbus message iter
4068 : * @error: Location to store error on failure
4069 : * @user_data: Function specific data
4070 : * Returns: TRUE on success, FALSE on failure
4071 : *
4072 : * Setter for "Properties" property of a configured network.
4073 : */
4074 3 : dbus_bool_t wpas_dbus_setter_network_properties(DBusMessageIter *iter,
4075 : DBusError *error,
4076 : void *user_data)
4077 : {
4078 3 : struct network_handler_args *net = user_data;
4079 3 : struct wpa_ssid *ssid = net->ssid;
4080 : DBusMessageIter variant_iter;
4081 :
4082 3 : dbus_message_iter_recurse(iter, &variant_iter);
4083 3 : return set_network_properties(net->wpa_s, ssid, &variant_iter, error);
4084 : }
4085 :
4086 :
4087 : #ifdef CONFIG_AP
4088 :
4089 4 : DBusMessage * wpas_dbus_handler_subscribe_preq(
4090 : DBusMessage *message, struct wpa_supplicant *wpa_s)
4091 : {
4092 4 : struct wpas_dbus_priv *priv = wpa_s->global->dbus;
4093 : char *name;
4094 :
4095 4 : if (wpa_s->preq_notify_peer != NULL) {
4096 0 : if (os_strcmp(dbus_message_get_sender(message),
4097 : wpa_s->preq_notify_peer) == 0)
4098 0 : return NULL;
4099 :
4100 0 : return dbus_message_new_error(message,
4101 : WPAS_DBUS_ERROR_SUBSCRIPTION_IN_USE,
4102 : "Another application is already subscribed");
4103 : }
4104 :
4105 4 : name = os_strdup(dbus_message_get_sender(message));
4106 4 : if (!name)
4107 1 : return wpas_dbus_error_no_memory(message);
4108 :
4109 3 : wpa_s->preq_notify_peer = name;
4110 :
4111 : /* Subscribe to clean up if application closes socket */
4112 3 : wpas_dbus_subscribe_noc(priv);
4113 :
4114 : /*
4115 : * Double-check it's still alive to make sure that we didn't
4116 : * miss the NameOwnerChanged signal, e.g. while strdup'ing.
4117 : */
4118 3 : if (!dbus_bus_name_has_owner(priv->con, name, NULL)) {
4119 : /*
4120 : * Application no longer exists, clean up.
4121 : * The return value is irrelevant now.
4122 : *
4123 : * Need to check if the NameOwnerChanged handling
4124 : * already cleaned up because we have processed
4125 : * DBus messages while checking if the name still
4126 : * has an owner.
4127 : */
4128 0 : if (!wpa_s->preq_notify_peer)
4129 0 : return NULL;
4130 0 : os_free(wpa_s->preq_notify_peer);
4131 0 : wpa_s->preq_notify_peer = NULL;
4132 0 : wpas_dbus_unsubscribe_noc(priv);
4133 : }
4134 :
4135 3 : return NULL;
4136 : }
4137 :
4138 :
4139 3 : DBusMessage * wpas_dbus_handler_unsubscribe_preq(
4140 : DBusMessage *message, struct wpa_supplicant *wpa_s)
4141 : {
4142 3 : struct wpas_dbus_priv *priv = wpa_s->global->dbus;
4143 :
4144 3 : if (!wpa_s->preq_notify_peer)
4145 1 : return dbus_message_new_error(message,
4146 : WPAS_DBUS_ERROR_NO_SUBSCRIPTION,
4147 : "Not subscribed");
4148 :
4149 2 : if (os_strcmp(wpa_s->preq_notify_peer,
4150 : dbus_message_get_sender(message)))
4151 0 : return dbus_message_new_error(message,
4152 : WPAS_DBUS_ERROR_SUBSCRIPTION_EPERM,
4153 : "Can't unsubscribe others");
4154 :
4155 2 : os_free(wpa_s->preq_notify_peer);
4156 2 : wpa_s->preq_notify_peer = NULL;
4157 2 : wpas_dbus_unsubscribe_noc(priv);
4158 2 : return NULL;
4159 : }
4160 :
4161 :
4162 469 : void wpas_dbus_signal_preq(struct wpa_supplicant *wpa_s,
4163 : const u8 *addr, const u8 *dst, const u8 *bssid,
4164 : const u8 *ie, size_t ie_len, u32 ssi_signal)
4165 : {
4166 : DBusMessage *msg;
4167 : DBusMessageIter iter, dict_iter;
4168 469 : struct wpas_dbus_priv *priv = wpa_s->global->dbus;
4169 :
4170 : /* Do nothing if the control interface is not turned on */
4171 469 : if (priv == NULL || !wpa_s->dbus_new_path)
4172 546 : return;
4173 :
4174 375 : if (wpa_s->preq_notify_peer == NULL)
4175 358 : return;
4176 :
4177 17 : msg = dbus_message_new_signal(wpa_s->dbus_new_path,
4178 : WPAS_DBUS_NEW_IFACE_INTERFACE,
4179 : "ProbeRequest");
4180 17 : if (msg == NULL)
4181 0 : return;
4182 :
4183 17 : dbus_message_set_destination(msg, wpa_s->preq_notify_peer);
4184 :
4185 17 : dbus_message_iter_init_append(msg, &iter);
4186 :
4187 17 : if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
4188 17 : (addr && !wpa_dbus_dict_append_byte_array(&dict_iter, "addr",
4189 : (const char *) addr,
4190 17 : ETH_ALEN)) ||
4191 17 : (dst && !wpa_dbus_dict_append_byte_array(&dict_iter, "dst",
4192 : (const char *) dst,
4193 17 : ETH_ALEN)) ||
4194 17 : (bssid && !wpa_dbus_dict_append_byte_array(&dict_iter, "bssid",
4195 : (const char *) bssid,
4196 17 : ETH_ALEN)) ||
4197 17 : (ie && ie_len && !wpa_dbus_dict_append_byte_array(&dict_iter, "ies",
4198 : (const char *) ie,
4199 17 : ie_len)) ||
4200 17 : (ssi_signal && !wpa_dbus_dict_append_int32(&dict_iter, "signal",
4201 17 : ssi_signal)) ||
4202 17 : !wpa_dbus_dict_close_write(&iter, &dict_iter))
4203 : goto fail;
4204 :
4205 17 : dbus_connection_send(priv->con, msg, NULL);
4206 17 : goto out;
4207 : fail:
4208 0 : wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
4209 : out:
4210 17 : dbus_message_unref(msg);
4211 : }
4212 :
4213 : #endif /* CONFIG_AP */
|