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