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, Jouni Malinen <j@w1.fi>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 * Alternatively, this software may be distributed under the terms of BSD
12 * license.
13 *
14 * See README and COPYING for more details.
15 */
16
17 #include "includes.h"
18
19 #include "common.h"
20 #include "common/ieee802_11_defs.h"
21 #include "eap_peer/eap_methods.h"
22 #include "eapol_supp/eapol_supp_sm.h"
23 #include "rsn_supp/wpa.h"
24 #include "../config.h"
25 #include "../wpa_supplicant_i.h"
26 #include "../driver_i.h"
27 #include "../notify.h"
28 #include "../wpas_glue.h"
29 #include "../bss.h"
30 #include "../scan.h"
31 #include "dbus_new_helpers.h"
32 #include "dbus_new.h"
33 #include "dbus_new_handlers.h"
34 #include "dbus_dict_helpers.h"
35
36 extern int wpa_debug_level;
37 extern int wpa_debug_show_keys;
38 extern int wpa_debug_timestamp;
39
40 static const char *debug_strings[] = {
41 "excessive", "msgdump", "debug", "info", "warning", "error", NULL
42 };
43
44
45 /**
46 * wpas_dbus_error_unknown_error - Return a new InvalidArgs error message
47 * @message: Pointer to incoming dbus message this error refers to
48 * @arg: Optional string appended to error message
49 * Returns: a dbus error message
50 *
51 * Convenience function to create and return an UnknownError
52 */
wpas_dbus_error_unknown_error(DBusMessage * message,const char * arg)53 DBusMessage * wpas_dbus_error_unknown_error(DBusMessage *message,
54 const char *arg)
55 {
56 /*
57 * This function can be called as a result of a failure
58 * within internal getter calls, which will call this function
59 * with a NULL message parameter. However, dbus_message_new_error
60 * looks very unkindly (i.e, abort()) on a NULL message, so
61 * in this case, we should not call it.
62 */
63 if (message == NULL) {
64 wpa_printf(MSG_INFO, "dbus: wpas_dbus_error_unknown_error "
65 "called with NULL message (arg=%s)",
66 arg ? arg : "N/A");
67 return NULL;
68 }
69
70 return dbus_message_new_error(message, WPAS_DBUS_ERROR_UNKNOWN_ERROR,
71 arg);
72 }
73
74
75 /**
76 * wpas_dbus_error_iface_unknown - Return a new invalid interface error message
77 * @message: Pointer to incoming dbus message this error refers to
78 * Returns: A dbus error message
79 *
80 * Convenience function to create and return an invalid interface error
81 */
wpas_dbus_error_iface_unknown(DBusMessage * message)82 static DBusMessage * wpas_dbus_error_iface_unknown(DBusMessage *message)
83 {
84 return dbus_message_new_error(message, WPAS_DBUS_ERROR_IFACE_UNKNOWN,
85 "wpa_supplicant knows nothing about "
86 "this interface.");
87 }
88
89
90 /**
91 * wpas_dbus_error_network_unknown - Return a new NetworkUnknown error message
92 * @message: Pointer to incoming dbus message this error refers to
93 * Returns: a dbus error message
94 *
95 * Convenience function to create and return an invalid network error
96 */
wpas_dbus_error_network_unknown(DBusMessage * message)97 static DBusMessage * wpas_dbus_error_network_unknown(DBusMessage *message)
98 {
99 return dbus_message_new_error(message, WPAS_DBUS_ERROR_NETWORK_UNKNOWN,
100 "There is no such a network in this "
101 "interface.");
102 }
103
104
105 /**
106 * wpas_dbus_error_invalid_args - Return a new InvalidArgs error message
107 * @message: Pointer to incoming dbus message this error refers to
108 * Returns: a dbus error message
109 *
110 * Convenience function to create and return an invalid options error
111 */
wpas_dbus_error_invalid_args(DBusMessage * message,const char * arg)112 DBusMessage * wpas_dbus_error_invalid_args(DBusMessage *message,
113 const char *arg)
114 {
115 DBusMessage *reply;
116
117 reply = dbus_message_new_error(message, WPAS_DBUS_ERROR_INVALID_ARGS,
118 "Did not receive correct message "
119 "arguments.");
120 if (arg != NULL)
121 dbus_message_append_args(reply, DBUS_TYPE_STRING, &arg,
122 DBUS_TYPE_INVALID);
123
124 return reply;
125 }
126
127
128 static const char *dont_quote[] = {
129 "key_mgmt", "proto", "pairwise", "auth_alg", "group", "eap",
130 "opensc_engine_path", "pkcs11_engine_path", "pkcs11_module_path",
131 "bssid", NULL
132 };
133
should_quote_opt(const char * key)134 static dbus_bool_t should_quote_opt(const char *key)
135 {
136 int i = 0;
137 while (dont_quote[i] != NULL) {
138 if (os_strcmp(key, dont_quote[i]) == 0)
139 return FALSE;
140 i++;
141 }
142 return TRUE;
143 }
144
145 /**
146 * get_iface_by_dbus_path - Get a new network interface
147 * @global: Pointer to global data from wpa_supplicant_init()
148 * @path: Pointer to a dbus object path representing an interface
149 * Returns: Pointer to the interface or %NULL if not found
150 */
get_iface_by_dbus_path(struct wpa_global * global,const char * path)151 static struct wpa_supplicant * get_iface_by_dbus_path(
152 struct wpa_global *global, const char *path)
153 {
154 struct wpa_supplicant *wpa_s;
155
156 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
157 if (os_strcmp(wpa_s->dbus_new_path, path) == 0)
158 return wpa_s;
159 }
160 return NULL;
161 }
162
163
164 /**
165 * set_network_properties - Set properties of a configured network
166 * @message: Pointer to incoming dbus message
167 * @wpa_s: wpa_supplicant structure for a network interface
168 * @ssid: wpa_ssid structure for a configured network
169 * @iter: DBus message iterator containing dictionary of network
170 * properties to set.
171 * Returns: NULL when succeed or DBus error on failure
172 *
173 * Sets network configuration with parameters given id DBus dictionary
174 */
set_network_properties(DBusMessage * message,struct wpa_supplicant * wpa_s,struct wpa_ssid * ssid,DBusMessageIter * iter)175 DBusMessage * set_network_properties(DBusMessage *message,
176 struct wpa_supplicant *wpa_s,
177 struct wpa_ssid *ssid,
178 DBusMessageIter *iter)
179 {
180
181 struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
182 DBusMessage *reply = NULL;
183 DBusMessageIter iter_dict;
184
185 if (!wpa_dbus_dict_open_read(iter, &iter_dict))
186 return wpas_dbus_error_invalid_args(message, NULL);
187
188 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
189 char *value = NULL;
190 size_t size = 50;
191 int ret;
192 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) {
193 reply = wpas_dbus_error_invalid_args(message, NULL);
194 break;
195 }
196 if (entry.type == DBUS_TYPE_ARRAY &&
197 entry.array_type == DBUS_TYPE_BYTE) {
198 if (entry.array_len <= 0)
199 goto error;
200
201 size = entry.array_len * 2 + 1;
202 value = os_zalloc(size);
203 if (value == NULL)
204 goto error;
205
206 ret = wpa_snprintf_hex(value, size,
207 (u8 *) entry.bytearray_value,
208 entry.array_len);
209 if (ret <= 0)
210 goto error;
211 } else if (entry.type == DBUS_TYPE_STRING) {
212 if (should_quote_opt(entry.key)) {
213 size = os_strlen(entry.str_value);
214 if (size <= 0)
215 goto error;
216
217 size += 3;
218 value = os_zalloc(size);
219 if (value == NULL)
220 goto error;
221
222 ret = os_snprintf(value, size, "\"%s\"",
223 entry.str_value);
224 if (ret < 0 || (size_t) ret != (size - 1))
225 goto error;
226 } else {
227 value = os_strdup(entry.str_value);
228 if (value == NULL)
229 goto error;
230 }
231 } else if (entry.type == DBUS_TYPE_UINT32) {
232 value = os_zalloc(size);
233 if (value == NULL)
234 goto error;
235
236 ret = os_snprintf(value, size, "%u",
237 entry.uint32_value);
238 if (ret <= 0)
239 goto error;
240 } else if (entry.type == DBUS_TYPE_INT32) {
241 value = os_zalloc(size);
242 if (value == NULL)
243 goto error;
244
245 ret = os_snprintf(value, size, "%d",
246 entry.int32_value);
247 if (ret <= 0)
248 goto error;
249 } else
250 goto error;
251
252 if (wpa_config_set(ssid, entry.key, value, 0) < 0)
253 goto error;
254
255 if ((os_strcmp(entry.key, "psk") == 0 &&
256 value[0] == '"' && ssid->ssid_len) ||
257 (strcmp(entry.key, "ssid") == 0 && ssid->passphrase))
258 wpa_config_update_psk(ssid);
259 else if (os_strcmp(entry.key, "priority") == 0)
260 wpa_config_update_prio_list(wpa_s->conf);
261
262 os_free(value);
263 wpa_dbus_dict_entry_clear(&entry);
264 continue;
265
266 error:
267 os_free(value);
268 reply = wpas_dbus_error_invalid_args(message, entry.key);
269 wpa_dbus_dict_entry_clear(&entry);
270 break;
271 }
272
273 return reply;
274 }
275
276
277 /**
278 * wpas_dbus_simple_property_getter - Get basic type property
279 * @message: Pointer to incoming dbus message
280 * @type: DBus type of property (must be basic type)
281 * @val: pointer to place holding property value
282 * Returns: The DBus message containing response for Properties.Get call
283 * or DBus error message if error occurred.
284 *
285 * Generic getter for basic type properties. Type is required to be basic.
286 */
wpas_dbus_simple_property_getter(DBusMessage * message,const int type,const void * val)287 DBusMessage * wpas_dbus_simple_property_getter(DBusMessage *message,
288 const int type, const void *val)
289 {
290 DBusMessage *reply = NULL;
291 DBusMessageIter iter, variant_iter;
292
293 if (!dbus_type_is_basic(type)) {
294 wpa_printf(MSG_ERROR, "dbus: wpas_dbus_simple_property_getter:"
295 " given type is not basic");
296 return wpas_dbus_error_unknown_error(message, NULL);
297 }
298
299 if (message == NULL)
300 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
301 else
302 reply = dbus_message_new_method_return(message);
303
304 if (reply != NULL) {
305 dbus_message_iter_init_append(reply, &iter);
306 if (!dbus_message_iter_open_container(
307 &iter, DBUS_TYPE_VARIANT,
308 wpa_dbus_type_as_string(type), &variant_iter) ||
309 !dbus_message_iter_append_basic(&variant_iter, type,
310 val) ||
311 !dbus_message_iter_close_container(&iter, &variant_iter)) {
312 wpa_printf(MSG_ERROR, "dbus: "
313 "wpas_dbus_simple_property_getter: out of "
314 "memory to put property value into "
315 "message");
316 dbus_message_unref(reply);
317 reply = dbus_message_new_error(message,
318 DBUS_ERROR_NO_MEMORY,
319 NULL);
320 }
321 } else {
322 wpa_printf(MSG_ERROR, "dbus: wpas_dbus_simple_property_getter:"
323 " out of memory to return property value");
324 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
325 NULL);
326 }
327
328 return reply;
329 }
330
331
332 /**
333 * wpas_dbus_simple_property_setter - Set basic type property
334 * @message: Pointer to incoming dbus message
335 * @type: DBus type of property (must be basic type)
336 * @val: pointer to place where value being set will be stored
337 * Returns: NULL or DBus error message if error occurred.
338 *
339 * Generic setter for basic type properties. Type is required to be basic.
340 */
wpas_dbus_simple_property_setter(DBusMessage * message,const int type,void * val)341 DBusMessage * wpas_dbus_simple_property_setter(DBusMessage *message,
342 const int type, void *val)
343 {
344 DBusMessageIter iter, variant_iter;
345
346 if (!dbus_type_is_basic(type)) {
347 wpa_printf(MSG_ERROR, "dbus: wpas_dbus_simple_property_setter:"
348 " given type is not basic");
349 return wpas_dbus_error_unknown_error(message, NULL);
350 }
351
352 if (!dbus_message_iter_init(message, &iter)) {
353 wpa_printf(MSG_ERROR, "dbus: wpas_dbus_simple_property_setter:"
354 " out of memory to return scanning state");
355 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
356 NULL);
357 }
358
359 /* omit first and second argument and get value from third */
360 dbus_message_iter_next(&iter);
361 dbus_message_iter_next(&iter);
362 dbus_message_iter_recurse(&iter, &variant_iter);
363
364 if (dbus_message_iter_get_arg_type(&variant_iter) != type) {
365 wpa_printf(MSG_DEBUG, "dbus: wpas_dbus_simple_property_setter:"
366 " wrong property type");
367 return wpas_dbus_error_invalid_args(message,
368 "wrong property type");
369 }
370 dbus_message_iter_get_basic(&variant_iter, val);
371
372 return NULL;
373 }
374
375
376 /**
377 * wpas_dbus_simple_array_property_getter - Get array type property
378 * @message: Pointer to incoming dbus message
379 * @type: DBus type of property array elements (must be basic type)
380 * @array: pointer to array of elements to put into response message
381 * @array_len: length of above array
382 * Returns: The DBus message containing response for Properties.Get call
383 * or DBus error message if error occurred.
384 *
385 * Generic getter for array type properties. Array elements type is
386 * required to be basic.
387 */
wpas_dbus_simple_array_property_getter(DBusMessage * message,const int type,const void * array,size_t array_len)388 DBusMessage * wpas_dbus_simple_array_property_getter(DBusMessage *message,
389 const int type,
390 const void *array,
391 size_t array_len)
392 {
393 DBusMessage *reply = NULL;
394 DBusMessageIter iter, variant_iter, array_iter;
395 char type_str[] = "a?"; /* ? will be replaced with subtype letter; */
396 const char *sub_type_str;
397 size_t element_size, i;
398
399 if (!dbus_type_is_basic(type)) {
400 wpa_printf(MSG_ERROR, "dbus: "
401 "wpas_dbus_simple_array_property_getter: given "
402 "type is not basic");
403 return wpas_dbus_error_unknown_error(message, NULL);
404 }
405
406 sub_type_str = wpa_dbus_type_as_string(type);
407 type_str[1] = sub_type_str[0];
408
409 if (message == NULL)
410 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
411 else
412 reply = dbus_message_new_method_return(message);
413 if (reply == NULL) {
414 wpa_printf(MSG_ERROR, "dbus: "
415 "wpas_dbus_simple_array_property_getter: out of "
416 "memory to create return message");
417 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
418 NULL);
419 }
420
421 dbus_message_iter_init_append(reply, &iter);
422
423 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
424 type_str, &variant_iter) ||
425 !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
426 sub_type_str, &array_iter)) {
427 wpa_printf(MSG_ERROR, "dbus: "
428 "wpas_dbus_simple_array_property_getter: out of "
429 "memory to open container");
430 dbus_message_unref(reply);
431 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
432 NULL);
433 }
434
435 switch(type) {
436 case DBUS_TYPE_BYTE:
437 case DBUS_TYPE_BOOLEAN:
438 element_size = 1;
439 break;
440 case DBUS_TYPE_INT16:
441 case DBUS_TYPE_UINT16:
442 element_size = sizeof(uint16_t);
443 break;
444 case DBUS_TYPE_INT32:
445 case DBUS_TYPE_UINT32:
446 element_size = sizeof(uint32_t);
447 break;
448 case DBUS_TYPE_INT64:
449 case DBUS_TYPE_UINT64:
450 element_size = sizeof(uint64_t);
451 break;
452 case DBUS_TYPE_DOUBLE:
453 element_size = sizeof(double);
454 break;
455 case DBUS_TYPE_STRING:
456 case DBUS_TYPE_OBJECT_PATH:
457 element_size = sizeof(char *);
458 break;
459 default:
460 wpa_printf(MSG_ERROR, "dbus: "
461 "wpas_dbus_simple_array_property_getter: "
462 "fatal: unknown element type");
463 element_size = 1;
464 break;
465 }
466
467 for (i = 0; i < array_len; i++) {
468 dbus_message_iter_append_basic(&array_iter, type,
469 array + i * element_size);
470 }
471
472 if (!dbus_message_iter_close_container(&variant_iter, &array_iter) ||
473 !dbus_message_iter_close_container(&iter, &variant_iter)) {
474 wpa_printf(MSG_ERROR, "dbus: "
475 "wpas_dbus_simple_array_property_getter: out of "
476 "memory to close container");
477 dbus_message_unref(reply);
478 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
479 NULL);
480 }
481
482 return reply;
483 }
484
485
486 /**
487 * wpas_dbus_handler_create_interface - Request registration of a network iface
488 * @message: Pointer to incoming dbus message
489 * @global: %wpa_supplicant global data structure
490 * Returns: The object path of the new interface object,
491 * or a dbus error message with more information
492 *
493 * Handler function for "CreateInterface" method call. Handles requests
494 * by dbus clients to register a network interface that wpa_supplicant
495 * will manage.
496 */
wpas_dbus_handler_create_interface(DBusMessage * message,struct wpa_global * global)497 DBusMessage * wpas_dbus_handler_create_interface(DBusMessage *message,
498 struct wpa_global *global)
499 {
500 DBusMessageIter iter_dict;
501 DBusMessage *reply = NULL;
502 DBusMessageIter iter;
503 struct wpa_dbus_dict_entry entry;
504 char *driver = NULL;
505 char *ifname = NULL;
506 char *confname = NULL;
507 char *bridge_ifname = NULL;
508
509 dbus_message_iter_init(message, &iter);
510
511 if (!wpa_dbus_dict_open_read(&iter, &iter_dict))
512 goto error;
513 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
514 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
515 goto error;
516 if (!strcmp(entry.key, "Driver") &&
517 (entry.type == DBUS_TYPE_STRING)) {
518 driver = os_strdup(entry.str_value);
519 wpa_dbus_dict_entry_clear(&entry);
520 if (driver == NULL)
521 goto error;
522 } else if (!strcmp(entry.key, "Ifname") &&
523 (entry.type == DBUS_TYPE_STRING)) {
524 ifname = os_strdup(entry.str_value);
525 wpa_dbus_dict_entry_clear(&entry);
526 if (ifname == NULL)
527 goto error;
528 } else if (!strcmp(entry.key, "ConfigFile") &&
529 (entry.type == DBUS_TYPE_STRING)) {
530 confname = os_strdup(entry.str_value);
531 wpa_dbus_dict_entry_clear(&entry);
532 if (confname == NULL)
533 goto error;
534 } else if (!strcmp(entry.key, "BridgeIfname") &&
535 (entry.type == DBUS_TYPE_STRING)) {
536 bridge_ifname = os_strdup(entry.str_value);
537 wpa_dbus_dict_entry_clear(&entry);
538 if (bridge_ifname == NULL)
539 goto error;
540 } else {
541 wpa_dbus_dict_entry_clear(&entry);
542 goto error;
543 }
544 }
545
546 if (ifname == NULL)
547 goto error; /* Required Ifname argument missing */
548
549 /*
550 * Try to get the wpa_supplicant record for this iface, return
551 * an error if we already control it.
552 */
553 if (wpa_supplicant_get_iface(global, ifname) != NULL) {
554 reply = dbus_message_new_error(message,
555 WPAS_DBUS_ERROR_IFACE_EXISTS,
556 "wpa_supplicant already "
557 "controls this interface.");
558 } else {
559 struct wpa_supplicant *wpa_s;
560 struct wpa_interface iface;
561 os_memset(&iface, 0, sizeof(iface));
562 iface.driver = driver;
563 iface.ifname = ifname;
564 iface.confname = confname;
565 iface.bridge_ifname = bridge_ifname;
566 /* Otherwise, have wpa_supplicant attach to it. */
567 if ((wpa_s = wpa_supplicant_add_iface(global, &iface))) {
568 const char *path = wpa_s->dbus_new_path;
569 reply = dbus_message_new_method_return(message);
570 dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH,
571 &path, DBUS_TYPE_INVALID);
572 } else {
573 reply = wpas_dbus_error_unknown_error(
574 message, "wpa_supplicant couldn't grab this "
575 "interface.");
576 }
577 }
578
579 out:
580 os_free(driver);
581 os_free(ifname);
582 os_free(bridge_ifname);
583 return reply;
584
585 error:
586 reply = wpas_dbus_error_invalid_args(message, NULL);
587 goto out;
588 }
589
590
591 /**
592 * wpas_dbus_handler_remove_interface - Request deregistration of an interface
593 * @message: Pointer to incoming dbus message
594 * @global: wpa_supplicant global data structure
595 * Returns: a dbus message containing a UINT32 indicating success (1) or
596 * failure (0), or returns a dbus error message with more information
597 *
598 * Handler function for "removeInterface" method call. Handles requests
599 * by dbus clients to deregister a network interface that wpa_supplicant
600 * currently manages.
601 */
wpas_dbus_handler_remove_interface(DBusMessage * message,struct wpa_global * global)602 DBusMessage * wpas_dbus_handler_remove_interface(DBusMessage *message,
603 struct wpa_global *global)
604 {
605 struct wpa_supplicant *wpa_s;
606 char *path;
607 DBusMessage *reply = NULL;
608
609 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path,
610 DBUS_TYPE_INVALID);
611
612 wpa_s = get_iface_by_dbus_path(global, path);
613 if (wpa_s == NULL)
614 reply = wpas_dbus_error_iface_unknown(message);
615 else if (wpa_supplicant_remove_iface(global, wpa_s, 0)) {
616 reply = wpas_dbus_error_unknown_error(
617 message, "wpa_supplicant couldn't remove this "
618 "interface.");
619 }
620
621 return reply;
622 }
623
624
625 /**
626 * wpas_dbus_handler_get_interface - Get the object path for an interface name
627 * @message: Pointer to incoming dbus message
628 * @global: %wpa_supplicant global data structure
629 * Returns: The object path of the interface object,
630 * or a dbus error message with more information
631 *
632 * Handler function for "getInterface" method call.
633 */
wpas_dbus_handler_get_interface(DBusMessage * message,struct wpa_global * global)634 DBusMessage * wpas_dbus_handler_get_interface(DBusMessage *message,
635 struct wpa_global *global)
636 {
637 DBusMessage *reply = NULL;
638 const char *ifname;
639 const char *path;
640 struct wpa_supplicant *wpa_s;
641
642 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &ifname,
643 DBUS_TYPE_INVALID);
644
645 wpa_s = wpa_supplicant_get_iface(global, ifname);
646 if (wpa_s == NULL)
647 return wpas_dbus_error_iface_unknown(message);
648
649 path = wpa_s->dbus_new_path;
650 reply = dbus_message_new_method_return(message);
651 if (reply == NULL)
652 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
653 NULL);
654 if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
655 DBUS_TYPE_INVALID)) {
656 dbus_message_unref(reply);
657 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
658 NULL);
659 }
660
661 return reply;
662 }
663
664
665 /**
666 * wpas_dbus_getter_debug_level - Get debug level
667 * @message: Pointer to incoming dbus message
668 * @global: %wpa_supplicant global data structure
669 * Returns: DBus message with value of debug level
670 *
671 * Getter for "DebugLevel" property.
672 */
wpas_dbus_getter_debug_level(DBusMessage * message,struct wpa_global * global)673 DBusMessage * wpas_dbus_getter_debug_level(DBusMessage *message,
674 struct wpa_global *global)
675 {
676 const char *str;
677 int idx = wpa_debug_level;
678 if (idx < 0)
679 idx = 0;
680 if (idx > 5)
681 idx = 5;
682 str = debug_strings[idx];
683 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_STRING,
684 &str);
685 }
686
687
688 /**
689 * wpas_dbus_getter_debug_timestamp - Get debug timestamp
690 * @message: Pointer to incoming dbus message
691 * @global: %wpa_supplicant global data structure
692 * Returns: DBus message with value of debug timestamp
693 *
694 * Getter for "DebugTimestamp" property.
695 */
wpas_dbus_getter_debug_timestamp(DBusMessage * message,struct wpa_global * global)696 DBusMessage * wpas_dbus_getter_debug_timestamp(DBusMessage *message,
697 struct wpa_global *global)
698 {
699 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_BOOLEAN,
700 &wpa_debug_timestamp);
701
702 }
703
704
705 /**
706 * wpas_dbus_getter_debug_show_keys - Get debug show keys
707 * @message: Pointer to incoming dbus message
708 * @global: %wpa_supplicant global data structure
709 * Returns: DBus message with value of debug show_keys
710 *
711 * Getter for "DebugShowKeys" property.
712 */
wpas_dbus_getter_debug_show_keys(DBusMessage * message,struct wpa_global * global)713 DBusMessage * wpas_dbus_getter_debug_show_keys(DBusMessage *message,
714 struct wpa_global *global)
715 {
716 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_BOOLEAN,
717 &wpa_debug_show_keys);
718
719 }
720
721 /**
722 * wpas_dbus_setter_debug_level - Set debug level
723 * @message: Pointer to incoming dbus message
724 * @global: %wpa_supplicant global data structure
725 * Returns: %NULL or DBus error message
726 *
727 * Setter for "DebugLevel" property.
728 */
wpas_dbus_setter_debug_level(DBusMessage * message,struct wpa_global * global)729 DBusMessage * wpas_dbus_setter_debug_level(DBusMessage *message,
730 struct wpa_global *global)
731 {
732 DBusMessage *reply;
733 const char *str = NULL;
734 int i, val = -1;
735
736 reply = wpas_dbus_simple_property_setter(message, DBUS_TYPE_STRING,
737 &str);
738 if (reply)
739 return reply;
740
741 for (i = 0; debug_strings[i]; i++)
742 if (os_strcmp(debug_strings[i], str) == 0) {
743 val = i;
744 break;
745 }
746
747 if (val < 0 ||
748 wpa_supplicant_set_debug_params(global, val, wpa_debug_timestamp,
749 wpa_debug_show_keys)) {
750 return wpas_dbus_error_invalid_args(
751 message, "Wrong debug level value");
752 }
753
754 return NULL;
755 }
756
757
758 /**
759 * wpas_dbus_setter_debug_timestamp - Set debug timestamp
760 * @message: Pointer to incoming dbus message
761 * @global: %wpa_supplicant global data structure
762 * Returns: %NULL or DBus error message
763 *
764 * Setter for "DebugTimestamp" property.
765 */
wpas_dbus_setter_debug_timestamp(DBusMessage * message,struct wpa_global * global)766 DBusMessage * wpas_dbus_setter_debug_timestamp(DBusMessage *message,
767 struct wpa_global *global)
768 {
769 DBusMessage *reply;
770 dbus_bool_t val;
771
772 reply = wpas_dbus_simple_property_setter(message, DBUS_TYPE_BOOLEAN,
773 &val);
774 if (reply)
775 return reply;
776
777 wpa_supplicant_set_debug_params(global, wpa_debug_level, val ? 1 : 0,
778 wpa_debug_show_keys);
779
780 return NULL;
781 }
782
783
784 /**
785 * wpas_dbus_setter_debug_show_keys - Set debug show keys
786 * @message: Pointer to incoming dbus message
787 * @global: %wpa_supplicant global data structure
788 * Returns: %NULL or DBus error message
789 *
790 * Setter for "DebugShowKeys" property.
791 */
wpas_dbus_setter_debug_show_keys(DBusMessage * message,struct wpa_global * global)792 DBusMessage * wpas_dbus_setter_debug_show_keys(DBusMessage *message,
793 struct wpa_global *global)
794 {
795 DBusMessage *reply;
796 dbus_bool_t val;
797
798 reply = wpas_dbus_simple_property_setter(message, DBUS_TYPE_BOOLEAN,
799 &val);
800 if (reply)
801 return reply;
802
803 wpa_supplicant_set_debug_params(global, wpa_debug_level,
804 wpa_debug_timestamp,
805 val ? 1 : 0);
806
807 return NULL;
808 }
809
810
811 /**
812 * wpas_dbus_getter_interfaces - Request registered interfaces list
813 * @message: Pointer to incoming dbus message
814 * @global: %wpa_supplicant global data structure
815 * Returns: The object paths array containing registered interfaces
816 * objects paths or DBus error on failure
817 *
818 * Getter for "Interfaces" property. Handles requests
819 * by dbus clients to return list of registered interfaces objects
820 * paths
821 */
wpas_dbus_getter_interfaces(DBusMessage * message,struct wpa_global * global)822 DBusMessage * wpas_dbus_getter_interfaces(DBusMessage *message,
823 struct wpa_global *global)
824 {
825 DBusMessage *reply = NULL;
826 struct wpa_supplicant *wpa_s;
827 const char **paths;
828 unsigned int i = 0, num = 0;
829
830 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
831 num++;
832
833 paths = os_zalloc(num * sizeof(char*));
834 if (!paths) {
835 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
836 NULL);
837 }
838
839 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
840 paths[i++] = wpa_s->dbus_new_path;
841
842 reply = wpas_dbus_simple_array_property_getter(message,
843 DBUS_TYPE_OBJECT_PATH,
844 paths, num);
845
846 os_free(paths);
847 return reply;
848 }
849
850
851 /**
852 * wpas_dbus_getter_eap_methods - Request supported EAP methods list
853 * @message: Pointer to incoming dbus message
854 * @nothing: not used argument. may be NULL or anything else
855 * Returns: The object paths array containing supported EAP methods
856 * represented by strings or DBus error on failure
857 *
858 * Getter for "EapMethods" property. Handles requests
859 * by dbus clients to return list of strings with supported EAP methods
860 */
wpas_dbus_getter_eap_methods(DBusMessage * message,void * nothing)861 DBusMessage * wpas_dbus_getter_eap_methods(DBusMessage *message, void *nothing)
862 {
863 DBusMessage *reply = NULL;
864 char **eap_methods;
865 size_t num_items = 0;
866
867 eap_methods = eap_get_names_as_string_array(&num_items);
868 if (!eap_methods) {
869 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
870 NULL);
871 }
872
873 reply = wpas_dbus_simple_array_property_getter(message,
874 DBUS_TYPE_STRING,
875 eap_methods, num_items);
876
877 while (num_items)
878 os_free(eap_methods[--num_items]);
879 os_free(eap_methods);
880 return reply;
881 }
882
883
wpas_dbus_get_scan_type(DBusMessage * message,DBusMessageIter * var,char ** type,DBusMessage ** reply)884 static int wpas_dbus_get_scan_type(DBusMessage *message, DBusMessageIter *var,
885 char **type, DBusMessage **reply)
886 {
887 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_STRING) {
888 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
889 "Type must be a string");
890 *reply = wpas_dbus_error_invalid_args(
891 message, "Wrong Type value type. String required");
892 return -1;
893 }
894 dbus_message_iter_get_basic(var, type);
895 return 0;
896 }
897
898
wpas_dbus_get_scan_ssids(DBusMessage * message,DBusMessageIter * var,struct wpa_driver_scan_params * params,DBusMessage ** reply)899 static int wpas_dbus_get_scan_ssids(DBusMessage *message, DBusMessageIter *var,
900 struct wpa_driver_scan_params *params,
901 DBusMessage **reply)
902 {
903 struct wpa_driver_scan_ssid *ssids = params->ssids;
904 size_t ssids_num = 0;
905 u8 *ssid;
906 DBusMessageIter array_iter, sub_array_iter;
907 char *val;
908 int len;
909
910 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
911 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: ssids "
912 "must be an array of arrays of bytes");
913 *reply = wpas_dbus_error_invalid_args(
914 message, "Wrong SSIDs value type. Array of arrays of "
915 "bytes required");
916 return -1;
917 }
918
919 dbus_message_iter_recurse(var, &array_iter);
920
921 if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY ||
922 dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_BYTE)
923 {
924 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: ssids "
925 "must be an array of arrays of bytes");
926 *reply = wpas_dbus_error_invalid_args(
927 message, "Wrong SSIDs value type. Array of arrays of "
928 "bytes required");
929 return -1;
930 }
931
932 while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_ARRAY)
933 {
934 if (ssids_num >= WPAS_MAX_SCAN_SSIDS) {
935 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
936 "Too many ssids specified on scan dbus "
937 "call");
938 *reply = wpas_dbus_error_invalid_args(
939 message, "Too many ssids specified. Specify "
940 "at most four");
941 return -1;
942 }
943
944 dbus_message_iter_recurse(&array_iter, &sub_array_iter);
945
946 dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len);
947
948 if (len != 0) {
949 ssid = os_malloc(len);
950 if (ssid == NULL) {
951 wpa_printf(MSG_DEBUG,
952 "wpas_dbus_handler_scan[dbus]: "
953 "out of memory. Cannot allocate "
954 "memory for SSID");
955 *reply = dbus_message_new_error(
956 message, DBUS_ERROR_NO_MEMORY, NULL);
957 return -1;
958 }
959 os_memcpy(ssid, val, len);
960 } else {
961 /* Allow zero-length SSIDs */
962 ssid = NULL;
963 }
964
965 ssids[ssids_num].ssid = ssid;
966 ssids[ssids_num].ssid_len = len;
967
968 dbus_message_iter_next(&array_iter);
969 ssids_num++;
970 }
971
972 params->num_ssids = ssids_num;
973 return 0;
974 }
975
976
wpas_dbus_get_scan_ies(DBusMessage * message,DBusMessageIter * var,struct wpa_driver_scan_params * params,DBusMessage ** reply)977 static int wpas_dbus_get_scan_ies(DBusMessage *message, DBusMessageIter *var,
978 struct wpa_driver_scan_params *params,
979 DBusMessage **reply)
980 {
981 u8 *ies = NULL, *nies;
982 int ies_len = 0;
983 DBusMessageIter array_iter, sub_array_iter;
984 char *val;
985 int len;
986
987 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
988 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: ies must "
989 "be an array of arrays of bytes");
990 *reply = wpas_dbus_error_invalid_args(
991 message, "Wrong IEs value type. Array of arrays of "
992 "bytes required");
993 return -1;
994 }
995
996 dbus_message_iter_recurse(var, &array_iter);
997
998 if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY ||
999 dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_BYTE)
1000 {
1001 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: ies must "
1002 "be an array of arrays of bytes");
1003 *reply = wpas_dbus_error_invalid_args(
1004 message, "Wrong IEs value type. Array required");
1005 return -1;
1006 }
1007
1008 while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_ARRAY)
1009 {
1010 dbus_message_iter_recurse(&array_iter, &sub_array_iter);
1011
1012 dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len);
1013 if (len == 0) {
1014 dbus_message_iter_next(&array_iter);
1015 continue;
1016 }
1017
1018 nies = os_realloc(ies, ies_len + len);
1019 if (nies == NULL) {
1020 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1021 "out of memory. Cannot allocate memory for "
1022 "IE");
1023 os_free(ies);
1024 *reply = dbus_message_new_error(
1025 message, DBUS_ERROR_NO_MEMORY, NULL);
1026 return -1;
1027 }
1028 ies = nies;
1029 os_memcpy(ies + ies_len, val, len);
1030 ies_len += len;
1031
1032 dbus_message_iter_next(&array_iter);
1033 }
1034
1035 params->extra_ies = ies;
1036 params->extra_ies_len = ies_len;
1037 return 0;
1038 }
1039
1040
wpas_dbus_get_scan_channels(DBusMessage * message,DBusMessageIter * var,struct wpa_driver_scan_params * params,DBusMessage ** reply)1041 static int wpas_dbus_get_scan_channels(DBusMessage *message,
1042 DBusMessageIter *var,
1043 struct wpa_driver_scan_params *params,
1044 DBusMessage **reply)
1045 {
1046 DBusMessageIter array_iter, sub_array_iter;
1047 int *freqs = NULL, *nfreqs;
1048 int freqs_num = 0;
1049
1050 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
1051 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1052 "Channels must be an array of structs");
1053 *reply = wpas_dbus_error_invalid_args(
1054 message, "Wrong Channels value type. Array of structs "
1055 "required");
1056 return -1;
1057 }
1058
1059 dbus_message_iter_recurse(var, &array_iter);
1060
1061 if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_STRUCT) {
1062 wpa_printf(MSG_DEBUG,
1063 "wpas_dbus_handler_scan[dbus]: Channels must be an "
1064 "array of structs");
1065 *reply = wpas_dbus_error_invalid_args(
1066 message, "Wrong Channels value type. Array of structs "
1067 "required");
1068 return -1;
1069 }
1070
1071 while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_STRUCT)
1072 {
1073 int freq, width;
1074
1075 dbus_message_iter_recurse(&array_iter, &sub_array_iter);
1076
1077 if (dbus_message_iter_get_arg_type(&sub_array_iter) !=
1078 DBUS_TYPE_UINT32) {
1079 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1080 "Channel must by specified by struct of "
1081 "two UINT32s %c",
1082 dbus_message_iter_get_arg_type(
1083 &sub_array_iter));
1084 *reply = wpas_dbus_error_invalid_args(
1085 message, "Wrong Channel struct. Two UINT32s "
1086 "required");
1087 os_free(freqs);
1088 return -1;
1089 }
1090 dbus_message_iter_get_basic(&sub_array_iter, &freq);
1091
1092 if (!dbus_message_iter_next(&sub_array_iter) ||
1093 dbus_message_iter_get_arg_type(&sub_array_iter) !=
1094 DBUS_TYPE_UINT32) {
1095 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1096 "Channel must by specified by struct of "
1097 "two UINT32s");
1098 *reply = wpas_dbus_error_invalid_args(
1099 message,
1100 "Wrong Channel struct. Two UINT32s required");
1101 os_free(freqs);
1102 return -1;
1103 }
1104
1105 dbus_message_iter_get_basic(&sub_array_iter, &width);
1106
1107 #define FREQS_ALLOC_CHUNK 32
1108 if (freqs_num % FREQS_ALLOC_CHUNK == 0) {
1109 nfreqs = os_realloc(freqs, sizeof(int) *
1110 (freqs_num + FREQS_ALLOC_CHUNK));
1111 if (nfreqs == NULL)
1112 os_free(freqs);
1113 freqs = nfreqs;
1114 }
1115 if (freqs == NULL) {
1116 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1117 "out of memory. can't allocate memory for "
1118 "freqs");
1119 *reply = dbus_message_new_error(
1120 message, DBUS_ERROR_NO_MEMORY, NULL);
1121 return -1;
1122 }
1123
1124 freqs[freqs_num] = freq;
1125
1126 freqs_num++;
1127 dbus_message_iter_next(&array_iter);
1128 }
1129
1130 nfreqs = os_realloc(freqs,
1131 sizeof(int) * (freqs_num + 1));
1132 if (nfreqs == NULL)
1133 os_free(freqs);
1134 freqs = nfreqs;
1135 if (freqs == NULL) {
1136 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1137 "out of memory. Can't allocate memory for freqs");
1138 *reply = dbus_message_new_error(
1139 message, DBUS_ERROR_NO_MEMORY, NULL);
1140 return -1;
1141 }
1142 freqs[freqs_num] = 0;
1143
1144 params->freqs = freqs;
1145 return 0;
1146 }
1147
1148
1149 /**
1150 * wpas_dbus_handler_scan - Request a wireless scan on an interface
1151 * @message: Pointer to incoming dbus message
1152 * @wpa_s: wpa_supplicant structure for a network interface
1153 * Returns: NULL indicating success or DBus error message on failure
1154 *
1155 * Handler function for "Scan" method call of a network device. Requests
1156 * that wpa_supplicant perform a wireless scan as soon as possible
1157 * on a particular wireless interface.
1158 */
wpas_dbus_handler_scan(DBusMessage * message,struct wpa_supplicant * wpa_s)1159 DBusMessage * wpas_dbus_handler_scan(DBusMessage *message,
1160 struct wpa_supplicant *wpa_s)
1161 {
1162 DBusMessage *reply = NULL;
1163 DBusMessageIter iter, dict_iter, entry_iter, variant_iter;
1164 char *key = NULL, *type = NULL;
1165 struct wpa_driver_scan_params params;
1166 size_t i;
1167
1168 os_memset(¶ms, 0, sizeof(params));
1169
1170 dbus_message_iter_init(message, &iter);
1171
1172 dbus_message_iter_recurse(&iter, &dict_iter);
1173
1174 while (dbus_message_iter_get_arg_type(&dict_iter) ==
1175 DBUS_TYPE_DICT_ENTRY) {
1176 dbus_message_iter_recurse(&dict_iter, &entry_iter);
1177 dbus_message_iter_get_basic(&entry_iter, &key);
1178 dbus_message_iter_next(&entry_iter);
1179 dbus_message_iter_recurse(&entry_iter, &variant_iter);
1180
1181 if (os_strcmp(key, "Type") == 0) {
1182 if (wpas_dbus_get_scan_type(message, &variant_iter,
1183 &type, &reply) < 0)
1184 goto out;
1185 } else if (os_strcmp(key, "SSIDs") == 0) {
1186 if (wpas_dbus_get_scan_ssids(message, &variant_iter,
1187 ¶ms, &reply) < 0)
1188 goto out;
1189 } else if (os_strcmp(key, "IEs") == 0) {
1190 if (wpas_dbus_get_scan_ies(message, &variant_iter,
1191 ¶ms, &reply) < 0)
1192 goto out;
1193 } else if (os_strcmp(key, "Channels") == 0) {
1194 if (wpas_dbus_get_scan_channels(message, &variant_iter,
1195 ¶ms, &reply) < 0)
1196 goto out;
1197 } else {
1198 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1199 "Unknown argument %s", key);
1200 reply = wpas_dbus_error_invalid_args(message, key);
1201 goto out;
1202 }
1203
1204 dbus_message_iter_next(&dict_iter);
1205 }
1206
1207 if (!type) {
1208 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1209 "Scan type not specified");
1210 reply = wpas_dbus_error_invalid_args(message, key);
1211 goto out;
1212 }
1213
1214 if (!os_strcmp(type, "passive")) {
1215 if (params.num_ssids || params.extra_ies_len) {
1216 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1217 "SSIDs or IEs specified for passive scan.");
1218 reply = wpas_dbus_error_invalid_args(
1219 message, "You can specify only Channels in "
1220 "passive scan");
1221 goto out;
1222 } else if (params.freqs && params.freqs[0]) {
1223 wpa_supplicant_trigger_scan(wpa_s, ¶ms);
1224 } else {
1225 wpa_s->scan_req = 2;
1226 wpa_supplicant_req_scan(wpa_s, 0, 0);
1227 }
1228 } else if (!os_strcmp(type, "active")) {
1229 if (!params.num_ssids) {
1230 /* Add wildcard ssid */
1231 params.num_ssids++;
1232 }
1233 wpa_supplicant_trigger_scan(wpa_s, ¶ms);
1234 } else {
1235 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1236 "Unknown scan type: %s", type);
1237 reply = wpas_dbus_error_invalid_args(message,
1238 "Wrong scan type");
1239 goto out;
1240 }
1241
1242 out:
1243 for (i = 0; i < WPAS_MAX_SCAN_SSIDS; i++)
1244 os_free((u8 *) params.ssids[i].ssid);
1245 os_free((u8 *) params.extra_ies);
1246 os_free(params.freqs);
1247 return reply;
1248 }
1249
1250
1251 /*
1252 * wpas_dbus_handler_disconnect - Terminate the current connection
1253 * @message: Pointer to incoming dbus message
1254 * @wpa_s: wpa_supplicant structure for a network interface
1255 * Returns: NotConnected DBus error message if already not connected
1256 * or NULL otherwise.
1257 *
1258 * Handler function for "Disconnect" method call of network interface.
1259 */
wpas_dbus_handler_disconnect(DBusMessage * message,struct wpa_supplicant * wpa_s)1260 DBusMessage * wpas_dbus_handler_disconnect(DBusMessage *message,
1261 struct wpa_supplicant *wpa_s)
1262 {
1263 if (wpa_s->current_ssid != NULL) {
1264 wpa_s->disconnected = 1;
1265 wpa_supplicant_deauthenticate(wpa_s,
1266 WLAN_REASON_DEAUTH_LEAVING);
1267
1268 return NULL;
1269 }
1270
1271 return dbus_message_new_error(message, WPAS_DBUS_ERROR_NOT_CONNECTED,
1272 "This interface is not connected");
1273 }
1274
1275
1276 /**
1277 * wpas_dbus_new_iface_add_network - Add a new configured network
1278 * @message: Pointer to incoming dbus message
1279 * @wpa_s: wpa_supplicant structure for a network interface
1280 * Returns: A dbus message containing the object path of the new network
1281 *
1282 * Handler function for "AddNetwork" method call of a network interface.
1283 */
wpas_dbus_handler_add_network(DBusMessage * message,struct wpa_supplicant * wpa_s)1284 DBusMessage * wpas_dbus_handler_add_network(DBusMessage *message,
1285 struct wpa_supplicant *wpa_s)
1286 {
1287 DBusMessage *reply = NULL;
1288 DBusMessageIter iter;
1289 struct wpa_ssid *ssid = NULL;
1290 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf;
1291
1292 dbus_message_iter_init(message, &iter);
1293
1294 ssid = wpa_config_add_network(wpa_s->conf);
1295 if (ssid == NULL) {
1296 wpa_printf(MSG_ERROR, "wpas_dbus_handler_add_network[dbus]: "
1297 "can't add new interface.");
1298 reply = wpas_dbus_error_unknown_error(
1299 message,
1300 "wpa_supplicant could not add "
1301 "a network on this interface.");
1302 goto err;
1303 }
1304 wpas_notify_network_added(wpa_s, ssid);
1305 ssid->disabled = 1;
1306 wpa_config_set_network_defaults(ssid);
1307
1308 reply = set_network_properties(message, wpa_s, ssid, &iter);
1309 if (reply) {
1310 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_add_network[dbus]:"
1311 "control interface couldn't set network "
1312 "properties");
1313 goto err;
1314 }
1315
1316 /* Construct the object path for this network. */
1317 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
1318 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
1319 wpa_s->dbus_new_path, ssid->id);
1320
1321 reply = dbus_message_new_method_return(message);
1322 if (reply == NULL) {
1323 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1324 NULL);
1325 goto err;
1326 }
1327 if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
1328 DBUS_TYPE_INVALID)) {
1329 dbus_message_unref(reply);
1330 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1331 NULL);
1332 goto err;
1333 }
1334
1335 return reply;
1336
1337 err:
1338 if (ssid) {
1339 wpas_notify_network_removed(wpa_s, ssid);
1340 wpa_config_remove_network(wpa_s->conf, ssid->id);
1341 }
1342 return reply;
1343 }
1344
1345
1346 /**
1347 * wpas_dbus_handler_remove_network - Remove a configured network
1348 * @message: Pointer to incoming dbus message
1349 * @wpa_s: wpa_supplicant structure for a network interface
1350 * Returns: NULL on success or dbus error on failure
1351 *
1352 * Handler function for "RemoveNetwork" method call of a network interface.
1353 */
wpas_dbus_handler_remove_network(DBusMessage * message,struct wpa_supplicant * wpa_s)1354 DBusMessage * wpas_dbus_handler_remove_network(DBusMessage *message,
1355 struct wpa_supplicant *wpa_s)
1356 {
1357 DBusMessage *reply = NULL;
1358 const char *op;
1359 char *iface = NULL, *net_id = NULL;
1360 int id;
1361 struct wpa_ssid *ssid;
1362
1363 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
1364 DBUS_TYPE_INVALID);
1365
1366 /* Extract the network ID and ensure the network */
1367 /* is actually a child of this interface */
1368 iface = wpas_dbus_new_decompose_object_path(op, 0, &net_id, NULL);
1369 if (iface == NULL || os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
1370 reply = wpas_dbus_error_invalid_args(message, op);
1371 goto out;
1372 }
1373
1374 id = strtoul(net_id, NULL, 10);
1375 if (errno == EINVAL) {
1376 reply = wpas_dbus_error_invalid_args(message, op);
1377 goto out;
1378 }
1379
1380 ssid = wpa_config_get_network(wpa_s->conf, id);
1381 if (ssid == NULL) {
1382 reply = wpas_dbus_error_network_unknown(message);
1383 goto out;
1384 }
1385
1386 wpas_notify_network_removed(wpa_s, ssid);
1387
1388 if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
1389 wpa_printf(MSG_ERROR,
1390 "wpas_dbus_handler_remove_network[dbus]: "
1391 "error occurred when removing network %d", id);
1392 reply = wpas_dbus_error_unknown_error(
1393 message, "error removing the specified network on "
1394 "this interface.");
1395 goto out;
1396 }
1397
1398 if (ssid == wpa_s->current_ssid)
1399 wpa_supplicant_deauthenticate(wpa_s,
1400 WLAN_REASON_DEAUTH_LEAVING);
1401
1402 out:
1403 os_free(iface);
1404 os_free(net_id);
1405 return reply;
1406 }
1407
1408
remove_network(void * arg,struct wpa_ssid * ssid)1409 static void remove_network(void *arg, struct wpa_ssid *ssid)
1410 {
1411 struct wpa_supplicant *wpa_s = arg;
1412
1413 wpas_notify_network_removed(wpa_s, ssid);
1414
1415 if (wpa_config_remove_network(wpa_s->conf, ssid->id) < 0) {
1416 wpa_printf(MSG_ERROR,
1417 "wpas_dbus_handler_remove_all_networks[dbus]: "
1418 "error occurred when removing network %d",
1419 ssid->id);
1420 return;
1421 }
1422
1423 if (ssid == wpa_s->current_ssid)
1424 wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1425 }
1426
1427
1428 /**
1429 * wpas_dbus_handler_remove_all_networks - Remove all configured networks
1430 * @message: Pointer to incoming dbus message
1431 * @wpa_s: wpa_supplicant structure for a network interface
1432 * Returns: NULL on success or dbus error on failure
1433 *
1434 * Handler function for "RemoveAllNetworks" method call of a network interface.
1435 */
wpas_dbus_handler_remove_all_networks(DBusMessage * message,struct wpa_supplicant * wpa_s)1436 DBusMessage * wpas_dbus_handler_remove_all_networks(
1437 DBusMessage *message, struct wpa_supplicant *wpa_s)
1438 {
1439 /* NB: could check for failure and return an error */
1440 wpa_config_foreach_network(wpa_s->conf, remove_network, wpa_s);
1441 return NULL;
1442 }
1443
1444
1445 /**
1446 * wpas_dbus_handler_select_network - Attempt association with a network
1447 * @message: Pointer to incoming dbus message
1448 * @wpa_s: wpa_supplicant structure for a network interface
1449 * Returns: NULL on success or dbus error on failure
1450 *
1451 * Handler function for "SelectNetwork" method call of network interface.
1452 */
wpas_dbus_handler_select_network(DBusMessage * message,struct wpa_supplicant * wpa_s)1453 DBusMessage * wpas_dbus_handler_select_network(DBusMessage *message,
1454 struct wpa_supplicant *wpa_s)
1455 {
1456 DBusMessage *reply = NULL;
1457 const char *op;
1458 char *iface = NULL, *net_id = NULL;
1459 int id;
1460 struct wpa_ssid *ssid;
1461
1462 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
1463 DBUS_TYPE_INVALID);
1464
1465 /* Extract the network ID and ensure the network */
1466 /* is actually a child of this interface */
1467 iface = wpas_dbus_new_decompose_object_path(op, 0, &net_id, NULL);
1468 if (iface == NULL || os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
1469 reply = wpas_dbus_error_invalid_args(message, op);
1470 goto out;
1471 }
1472
1473 id = strtoul(net_id, NULL, 10);
1474 if (errno == EINVAL) {
1475 reply = wpas_dbus_error_invalid_args(message, op);
1476 goto out;
1477 }
1478
1479 ssid = wpa_config_get_network(wpa_s->conf, id);
1480 if (ssid == NULL) {
1481 reply = wpas_dbus_error_network_unknown(message);
1482 goto out;
1483 }
1484
1485 /* Finally, associate with the network */
1486 wpa_supplicant_select_network(wpa_s, ssid);
1487
1488 out:
1489 os_free(iface);
1490 os_free(net_id);
1491 return reply;
1492 }
1493
1494
1495 /**
1496 * wpas_dbus_handler_add_blob - Store named binary blob (ie, for certificates)
1497 * @message: Pointer to incoming dbus message
1498 * @wpa_s: %wpa_supplicant data structure
1499 * Returns: A dbus message containing an error on failure or NULL on success
1500 *
1501 * Asks wpa_supplicant to internally store a binary blobs.
1502 */
wpas_dbus_handler_add_blob(DBusMessage * message,struct wpa_supplicant * wpa_s)1503 DBusMessage * wpas_dbus_handler_add_blob(DBusMessage *message,
1504 struct wpa_supplicant *wpa_s)
1505 {
1506 DBusMessage *reply = NULL;
1507 DBusMessageIter iter, array_iter;
1508
1509 char *blob_name;
1510 u8 *blob_data;
1511 int blob_len;
1512 struct wpa_config_blob *blob = NULL;
1513
1514 dbus_message_iter_init(message, &iter);
1515 dbus_message_iter_get_basic(&iter, &blob_name);
1516
1517 if (wpa_config_get_blob(wpa_s->conf, blob_name)) {
1518 return dbus_message_new_error(message,
1519 WPAS_DBUS_ERROR_BLOB_EXISTS,
1520 NULL);
1521 }
1522
1523 dbus_message_iter_next(&iter);
1524 dbus_message_iter_recurse(&iter, &array_iter);
1525
1526 dbus_message_iter_get_fixed_array(&array_iter, &blob_data, &blob_len);
1527
1528 blob = os_zalloc(sizeof(*blob));
1529 if (!blob) {
1530 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1531 NULL);
1532 goto err;
1533 }
1534
1535 blob->data = os_malloc(blob_len);
1536 if (!blob->data) {
1537 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1538 NULL);
1539 goto err;
1540 }
1541 os_memcpy(blob->data, blob_data, blob_len);
1542
1543 blob->len = blob_len;
1544 blob->name = os_strdup(blob_name);
1545 if (!blob->name) {
1546 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1547 NULL);
1548 goto err;
1549 }
1550
1551 wpa_config_set_blob(wpa_s->conf, blob);
1552 wpas_notify_blob_added(wpa_s, blob->name);
1553
1554 return reply;
1555
1556 err:
1557 if (blob) {
1558 os_free(blob->name);
1559 os_free(blob->data);
1560 os_free(blob);
1561 }
1562 return reply;
1563 }
1564
1565
1566 /**
1567 * wpas_dbus_handler_get_blob - Get named binary blob (ie, for certificates)
1568 * @message: Pointer to incoming dbus message
1569 * @wpa_s: %wpa_supplicant data structure
1570 * Returns: A dbus message containing array of bytes (blob)
1571 *
1572 * Gets one wpa_supplicant's binary blobs.
1573 */
wpas_dbus_handler_get_blob(DBusMessage * message,struct wpa_supplicant * wpa_s)1574 DBusMessage * wpas_dbus_handler_get_blob(DBusMessage *message,
1575 struct wpa_supplicant *wpa_s)
1576 {
1577 DBusMessage *reply = NULL;
1578 DBusMessageIter iter, array_iter;
1579
1580 char *blob_name;
1581 const struct wpa_config_blob *blob;
1582
1583 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &blob_name,
1584 DBUS_TYPE_INVALID);
1585
1586 blob = wpa_config_get_blob(wpa_s->conf, blob_name);
1587 if (!blob) {
1588 return dbus_message_new_error(message,
1589 WPAS_DBUS_ERROR_BLOB_UNKNOWN,
1590 "Blob id not set");
1591 }
1592
1593 reply = dbus_message_new_method_return(message);
1594 if (!reply) {
1595 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1596 NULL);
1597 goto out;
1598 }
1599
1600 dbus_message_iter_init_append(reply, &iter);
1601
1602 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
1603 DBUS_TYPE_BYTE_AS_STRING,
1604 &array_iter)) {
1605 dbus_message_unref(reply);
1606 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1607 NULL);
1608 goto out;
1609 }
1610
1611 if (!dbus_message_iter_append_fixed_array(&array_iter, DBUS_TYPE_BYTE,
1612 &(blob->data), blob->len)) {
1613 dbus_message_unref(reply);
1614 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1615 NULL);
1616 goto out;
1617 }
1618
1619 if (!dbus_message_iter_close_container(&iter, &array_iter)) {
1620 dbus_message_unref(reply);
1621 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1622 NULL);
1623 goto out;
1624 }
1625
1626 out:
1627 return reply;
1628 }
1629
1630
1631 /**
1632 * wpas_remove_handler_remove_blob - Remove named binary blob
1633 * @message: Pointer to incoming dbus message
1634 * @wpa_s: %wpa_supplicant data structure
1635 * Returns: NULL on success or dbus error
1636 *
1637 * Asks wpa_supplicant to internally remove a binary blobs.
1638 */
wpas_dbus_handler_remove_blob(DBusMessage * message,struct wpa_supplicant * wpa_s)1639 DBusMessage * wpas_dbus_handler_remove_blob(DBusMessage *message,
1640 struct wpa_supplicant *wpa_s)
1641 {
1642 DBusMessage *reply = NULL;
1643 char *blob_name;
1644
1645 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &blob_name,
1646 DBUS_TYPE_INVALID);
1647
1648 if (wpa_config_remove_blob(wpa_s->conf, blob_name)) {
1649 return dbus_message_new_error(message,
1650 WPAS_DBUS_ERROR_BLOB_UNKNOWN,
1651 "Blob id not set");
1652 }
1653 wpas_notify_blob_removed(wpa_s, blob_name);
1654
1655 return reply;
1656
1657 }
1658
1659 /*
1660 * wpas_dbus_handler_flush_bss - Flush the BSS cache
1661 * @message: Pointer to incoming dbus message
1662 * @wpa_s: wpa_supplicant structure for a network interface
1663 * Returns: NULL
1664 *
1665 * Handler function for "FlushBSS" method call of network interface.
1666 */
wpas_dbus_handler_flush_bss(DBusMessage * message,struct wpa_supplicant * wpa_s)1667 DBusMessage * wpas_dbus_handler_flush_bss(DBusMessage *message,
1668 struct wpa_supplicant *wpa_s)
1669 {
1670 dbus_uint32_t age;
1671
1672 dbus_message_get_args(message, NULL, DBUS_TYPE_UINT32, &age,
1673 DBUS_TYPE_INVALID);
1674
1675 if (age == 0)
1676 wpa_bss_flush(wpa_s);
1677 else
1678 wpa_bss_flush_by_age(wpa_s, age);
1679
1680 return NULL;
1681 }
1682
1683
1684 /**
1685 * wpas_dbus_getter_capabilities - Return interface capabilities
1686 * @message: Pointer to incoming dbus message
1687 * @wpa_s: wpa_supplicant structure for a network interface
1688 * Returns: A dbus message containing a dict of strings
1689 *
1690 * Getter for "Capabilities" property of an interface.
1691 */
wpas_dbus_getter_capabilities(DBusMessage * message,struct wpa_supplicant * wpa_s)1692 DBusMessage * wpas_dbus_getter_capabilities(DBusMessage *message,
1693 struct wpa_supplicant *wpa_s)
1694 {
1695 DBusMessage *reply = NULL;
1696 struct wpa_driver_capa capa;
1697 int res;
1698 DBusMessageIter iter, iter_dict;
1699 DBusMessageIter iter_dict_entry, iter_dict_val, iter_array,
1700 variant_iter;
1701 const char *scans[] = { "active", "passive", "ssid" };
1702
1703 if (message == NULL)
1704 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
1705 else
1706 reply = dbus_message_new_method_return(message);
1707 if (!reply)
1708 goto nomem;
1709
1710 dbus_message_iter_init_append(reply, &iter);
1711 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
1712 "a{sv}", &variant_iter))
1713 goto nomem;
1714
1715 if (!wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
1716 goto nomem;
1717
1718 res = wpa_drv_get_capa(wpa_s, &capa);
1719
1720 /***** pairwise cipher */
1721 if (res < 0) {
1722 const char *args[] = {"ccmp", "tkip", "none"};
1723 if (!wpa_dbus_dict_append_string_array(
1724 &iter_dict, "Pairwise", args,
1725 sizeof(args) / sizeof(char*)))
1726 goto nomem;
1727 } else {
1728 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Pairwise",
1729 &iter_dict_entry,
1730 &iter_dict_val,
1731 &iter_array))
1732 goto nomem;
1733
1734 if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
1735 if (!wpa_dbus_dict_string_array_add_element(
1736 &iter_array, "ccmp"))
1737 goto nomem;
1738 }
1739
1740 if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
1741 if (!wpa_dbus_dict_string_array_add_element(
1742 &iter_array, "tkip"))
1743 goto nomem;
1744 }
1745
1746 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
1747 if (!wpa_dbus_dict_string_array_add_element(
1748 &iter_array, "none"))
1749 goto nomem;
1750 }
1751
1752 if (!wpa_dbus_dict_end_string_array(&iter_dict,
1753 &iter_dict_entry,
1754 &iter_dict_val,
1755 &iter_array))
1756 goto nomem;
1757 }
1758
1759 /***** group cipher */
1760 if (res < 0) {
1761 const char *args[] = {
1762 "ccmp", "tkip", "wep104", "wep40"
1763 };
1764 if (!wpa_dbus_dict_append_string_array(
1765 &iter_dict, "Group", args,
1766 sizeof(args) / sizeof(char*)))
1767 goto nomem;
1768 } else {
1769 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Group",
1770 &iter_dict_entry,
1771 &iter_dict_val,
1772 &iter_array))
1773 goto nomem;
1774
1775 if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
1776 if (!wpa_dbus_dict_string_array_add_element(
1777 &iter_array, "ccmp"))
1778 goto nomem;
1779 }
1780
1781 if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
1782 if (!wpa_dbus_dict_string_array_add_element(
1783 &iter_array, "tkip"))
1784 goto nomem;
1785 }
1786
1787 if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) {
1788 if (!wpa_dbus_dict_string_array_add_element(
1789 &iter_array, "wep104"))
1790 goto nomem;
1791 }
1792
1793 if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) {
1794 if (!wpa_dbus_dict_string_array_add_element(
1795 &iter_array, "wep40"))
1796 goto nomem;
1797 }
1798
1799 if (!wpa_dbus_dict_end_string_array(&iter_dict,
1800 &iter_dict_entry,
1801 &iter_dict_val,
1802 &iter_array))
1803 goto nomem;
1804 }
1805
1806 /***** key management */
1807 if (res < 0) {
1808 const char *args[] = {
1809 "wpa-psk", "wpa-eap", "ieee8021x", "wpa-none",
1810 #ifdef CONFIG_WPS
1811 "wps",
1812 #endif /* CONFIG_WPS */
1813 "none"
1814 };
1815 if (!wpa_dbus_dict_append_string_array(
1816 &iter_dict, "KeyMgmt", args,
1817 sizeof(args) / sizeof(char*)))
1818 goto nomem;
1819 } else {
1820 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "KeyMgmt",
1821 &iter_dict_entry,
1822 &iter_dict_val,
1823 &iter_array))
1824 goto nomem;
1825
1826 if (!wpa_dbus_dict_string_array_add_element(&iter_array,
1827 "none"))
1828 goto nomem;
1829
1830 if (!wpa_dbus_dict_string_array_add_element(&iter_array,
1831 "ieee8021x"))
1832 goto nomem;
1833
1834 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
1835 WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
1836 if (!wpa_dbus_dict_string_array_add_element(
1837 &iter_array, "wpa-eap"))
1838 goto nomem;
1839
1840 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT)
1841 if (!wpa_dbus_dict_string_array_add_element(
1842 &iter_array, "wpa-ft-eap"))
1843 goto nomem;
1844
1845 /* TODO: Ensure that driver actually supports sha256 encryption. */
1846 #ifdef CONFIG_IEEE80211W
1847 if (!wpa_dbus_dict_string_array_add_element(
1848 &iter_array, "wpa-eap-sha256"))
1849 goto nomem;
1850 #endif /* CONFIG_IEEE80211W */
1851 }
1852
1853 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
1854 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
1855 if (!wpa_dbus_dict_string_array_add_element(
1856 &iter_array, "wpa-psk"))
1857 goto nomem;
1858
1859 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK)
1860 if (!wpa_dbus_dict_string_array_add_element(
1861 &iter_array, "wpa-ft-psk"))
1862 goto nomem;
1863
1864 /* TODO: Ensure that driver actually supports sha256 encryption. */
1865 #ifdef CONFIG_IEEE80211W
1866 if (!wpa_dbus_dict_string_array_add_element(
1867 &iter_array, "wpa-psk-sha256"))
1868 goto nomem;
1869 #endif /* CONFIG_IEEE80211W */
1870 }
1871
1872 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
1873 if (!wpa_dbus_dict_string_array_add_element(
1874 &iter_array, "wpa-none"))
1875 goto nomem;
1876 }
1877
1878
1879 #ifdef CONFIG_WPS
1880 if (!wpa_dbus_dict_string_array_add_element(&iter_array,
1881 "wps"))
1882 goto nomem;
1883 #endif /* CONFIG_WPS */
1884
1885 if (!wpa_dbus_dict_end_string_array(&iter_dict,
1886 &iter_dict_entry,
1887 &iter_dict_val,
1888 &iter_array))
1889 goto nomem;
1890 }
1891
1892 /***** WPA protocol */
1893 if (res < 0) {
1894 const char *args[] = { "rsn", "wpa" };
1895 if (!wpa_dbus_dict_append_string_array(
1896 &iter_dict, "Protocol", args,
1897 sizeof(args) / sizeof(char*)))
1898 goto nomem;
1899 } else {
1900 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Protocol",
1901 &iter_dict_entry,
1902 &iter_dict_val,
1903 &iter_array))
1904 goto nomem;
1905
1906 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
1907 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
1908 if (!wpa_dbus_dict_string_array_add_element(
1909 &iter_array, "rsn"))
1910 goto nomem;
1911 }
1912
1913 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
1914 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
1915 if (!wpa_dbus_dict_string_array_add_element(
1916 &iter_array, "wpa"))
1917 goto nomem;
1918 }
1919
1920 if (!wpa_dbus_dict_end_string_array(&iter_dict,
1921 &iter_dict_entry,
1922 &iter_dict_val,
1923 &iter_array))
1924 goto nomem;
1925 }
1926
1927 /***** auth alg */
1928 if (res < 0) {
1929 const char *args[] = { "open", "shared", "leap" };
1930 if (!wpa_dbus_dict_append_string_array(
1931 &iter_dict, "AuthAlg", args,
1932 sizeof(args) / sizeof(char*)))
1933 goto nomem;
1934 } else {
1935 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "AuthAlg",
1936 &iter_dict_entry,
1937 &iter_dict_val,
1938 &iter_array))
1939 goto nomem;
1940
1941 if (capa.auth & (WPA_DRIVER_AUTH_OPEN)) {
1942 if (!wpa_dbus_dict_string_array_add_element(
1943 &iter_array, "open"))
1944 goto nomem;
1945 }
1946
1947 if (capa.auth & (WPA_DRIVER_AUTH_SHARED)) {
1948 if (!wpa_dbus_dict_string_array_add_element(
1949 &iter_array, "shared"))
1950 goto nomem;
1951 }
1952
1953 if (capa.auth & (WPA_DRIVER_AUTH_LEAP)) {
1954 if (!wpa_dbus_dict_string_array_add_element(
1955 &iter_array, "leap"))
1956 goto nomem;
1957 }
1958
1959 if (!wpa_dbus_dict_end_string_array(&iter_dict,
1960 &iter_dict_entry,
1961 &iter_dict_val,
1962 &iter_array))
1963 goto nomem;
1964 }
1965
1966 /***** Scan */
1967 if (!wpa_dbus_dict_append_string_array(&iter_dict, "Scan", scans,
1968 sizeof(scans) / sizeof(char *)))
1969 goto nomem;
1970
1971 /***** Modes */
1972 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Modes",
1973 &iter_dict_entry,
1974 &iter_dict_val,
1975 &iter_array))
1976 goto nomem;
1977
1978 if (!wpa_dbus_dict_string_array_add_element(
1979 &iter_array, "infrastructure"))
1980 goto nomem;
1981
1982 if (!wpa_dbus_dict_string_array_add_element(
1983 &iter_array, "ad-hoc"))
1984 goto nomem;
1985
1986 if (res >= 0) {
1987 if (capa.flags & (WPA_DRIVER_FLAGS_AP)) {
1988 if (!wpa_dbus_dict_string_array_add_element(
1989 &iter_array, "ap"))
1990 goto nomem;
1991 }
1992
1993 if (capa.flags & (WPA_DRIVER_FLAGS_P2P_CAPABLE)) {
1994 if (!wpa_dbus_dict_string_array_add_element(
1995 &iter_array, "p2p"))
1996 goto nomem;
1997 }
1998 }
1999
2000 if (!wpa_dbus_dict_end_string_array(&iter_dict,
2001 &iter_dict_entry,
2002 &iter_dict_val,
2003 &iter_array))
2004 goto nomem;
2005 /***** Modes end */
2006
2007 if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict))
2008 goto nomem;
2009 if (!dbus_message_iter_close_container(&iter, &variant_iter))
2010 goto nomem;
2011
2012 return reply;
2013
2014 nomem:
2015 if (reply)
2016 dbus_message_unref(reply);
2017
2018 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, NULL);
2019 }
2020
2021
2022 /**
2023 * wpas_dbus_getter_state - Get interface state
2024 * @message: Pointer to incoming dbus message
2025 * @wpa_s: wpa_supplicant structure for a network interface
2026 * Returns: A dbus message containing a STRING representing the current
2027 * interface state
2028 *
2029 * Getter for "State" property.
2030 */
wpas_dbus_getter_state(DBusMessage * message,struct wpa_supplicant * wpa_s)2031 DBusMessage * wpas_dbus_getter_state(DBusMessage *message,
2032 struct wpa_supplicant *wpa_s)
2033 {
2034 DBusMessage *reply = NULL;
2035 const char *str_state;
2036 char *state_ls, *tmp;
2037
2038 str_state = wpa_supplicant_state_txt(wpa_s->wpa_state);
2039
2040 /* make state string lowercase to fit new DBus API convention
2041 */
2042 state_ls = tmp = os_strdup(str_state);
2043 if (!tmp) {
2044 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2045 NULL);
2046 }
2047 while (*tmp) {
2048 *tmp = tolower(*tmp);
2049 tmp++;
2050 }
2051
2052 reply = wpas_dbus_simple_property_getter(message, DBUS_TYPE_STRING,
2053 &state_ls);
2054
2055 os_free(state_ls);
2056
2057 return reply;
2058 }
2059
2060
2061 /**
2062 * wpas_dbus_new_iface_get_scanning - Get interface scanning state
2063 * @message: Pointer to incoming dbus message
2064 * @wpa_s: wpa_supplicant structure for a network interface
2065 * Returns: A dbus message containing whether the interface is scanning
2066 *
2067 * Getter for "scanning" property.
2068 */
wpas_dbus_getter_scanning(DBusMessage * message,struct wpa_supplicant * wpa_s)2069 DBusMessage * wpas_dbus_getter_scanning(DBusMessage *message,
2070 struct wpa_supplicant *wpa_s)
2071 {
2072 dbus_bool_t scanning = wpa_s->scanning ? TRUE : FALSE;
2073 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_BOOLEAN,
2074 &scanning);
2075 }
2076
2077
2078 /**
2079 * wpas_dbus_getter_ap_scan - Control roaming mode
2080 * @message: Pointer to incoming dbus message
2081 * @wpa_s: wpa_supplicant structure for a network interface
2082 * Returns: A message containong value of ap_scan variable
2083 *
2084 * Getter function for "ApScan" property.
2085 */
wpas_dbus_getter_ap_scan(DBusMessage * message,struct wpa_supplicant * wpa_s)2086 DBusMessage * wpas_dbus_getter_ap_scan(DBusMessage *message,
2087 struct wpa_supplicant *wpa_s)
2088 {
2089 dbus_uint32_t ap_scan = wpa_s->conf->ap_scan;
2090 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_UINT32,
2091 &ap_scan);
2092 }
2093
2094
2095 /**
2096 * wpas_dbus_setter_ap_scan - Control roaming mode
2097 * @message: Pointer to incoming dbus message
2098 * @wpa_s: wpa_supplicant structure for a network interface
2099 * Returns: NULL
2100 *
2101 * Setter function for "ApScan" property.
2102 */
wpas_dbus_setter_ap_scan(DBusMessage * message,struct wpa_supplicant * wpa_s)2103 DBusMessage * wpas_dbus_setter_ap_scan(DBusMessage *message,
2104 struct wpa_supplicant *wpa_s)
2105 {
2106 DBusMessage *reply = NULL;
2107 dbus_uint32_t ap_scan;
2108
2109 reply = wpas_dbus_simple_property_setter(message, DBUS_TYPE_UINT32,
2110 &ap_scan);
2111 if (reply)
2112 return reply;
2113
2114 if (wpa_supplicant_set_ap_scan(wpa_s, ap_scan)) {
2115 return wpas_dbus_error_invalid_args(
2116 message, "ap_scan must equal 0, 1 or 2");
2117 }
2118 return NULL;
2119 }
2120
2121
2122 /**
2123 * wpas_dbus_getter_bss_expire_age - Get BSS entry expiration age
2124 * @message: Pointer to incoming dbus message
2125 * @wpa_s: wpa_supplicant structure for a network interface
2126 * Returns: A message containing value of bss_expiration_age variable
2127 *
2128 * Getter function for "BSSExpireAge" property.
2129 */
wpas_dbus_getter_bss_expire_age(DBusMessage * message,struct wpa_supplicant * wpa_s)2130 DBusMessage * wpas_dbus_getter_bss_expire_age(DBusMessage *message,
2131 struct wpa_supplicant *wpa_s)
2132 {
2133 dbus_uint32_t expire_age = wpa_s->conf->bss_expiration_age;
2134 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_UINT32,
2135 &expire_age);
2136 }
2137
2138
2139 /**
2140 * wpas_dbus_setter_bss_expire_age - Control BSS entry expiration age
2141 * @message: Pointer to incoming dbus message
2142 * @wpa_s: wpa_supplicant structure for a network interface
2143 * Returns: NULL
2144 *
2145 * Setter function for "BSSExpireAge" property.
2146 */
wpas_dbus_setter_bss_expire_age(DBusMessage * message,struct wpa_supplicant * wpa_s)2147 DBusMessage * wpas_dbus_setter_bss_expire_age(DBusMessage *message,
2148 struct wpa_supplicant *wpa_s)
2149 {
2150 DBusMessage *reply = NULL;
2151 dbus_uint32_t expire_age;
2152
2153 reply = wpas_dbus_simple_property_setter(message, DBUS_TYPE_UINT32,
2154 &expire_age);
2155 if (reply)
2156 return reply;
2157
2158 if (wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age)) {
2159 return wpas_dbus_error_invalid_args(
2160 message, "BSSExpireAge must be >=10");
2161 }
2162 return NULL;
2163 }
2164
2165
2166 /**
2167 * wpas_dbus_getter_bss_expire_count - Get BSS entry expiration scan count
2168 * @message: Pointer to incoming dbus message
2169 * @wpa_s: wpa_supplicant structure for a network interface
2170 * Returns: A message containing value of bss_expire_count variable
2171 *
2172 * Getter function for "BSSExpireCount" property.
2173 */
wpas_dbus_getter_bss_expire_count(DBusMessage * message,struct wpa_supplicant * wpa_s)2174 DBusMessage * wpas_dbus_getter_bss_expire_count(DBusMessage *message,
2175 struct wpa_supplicant *wpa_s)
2176 {
2177 dbus_uint32_t expire_count = wpa_s->conf->bss_expiration_age;
2178 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_UINT32,
2179 &expire_count);
2180 }
2181
2182
2183 /**
2184 * wpas_dbus_setter_bss_expire_count - Control BSS entry expiration scan count
2185 * @message: Pointer to incoming dbus message
2186 * @wpa_s: wpa_supplicant structure for a network interface
2187 * Returns: NULL
2188 *
2189 * Setter function for "BSSExpireCount" property.
2190 */
wpas_dbus_setter_bss_expire_count(DBusMessage * message,struct wpa_supplicant * wpa_s)2191 DBusMessage * wpas_dbus_setter_bss_expire_count(DBusMessage *message,
2192 struct wpa_supplicant *wpa_s)
2193 {
2194 DBusMessage *reply = NULL;
2195 dbus_uint32_t expire_count;
2196
2197 reply = wpas_dbus_simple_property_setter(message, DBUS_TYPE_UINT32,
2198 &expire_count);
2199 if (reply)
2200 return reply;
2201
2202 if (wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count)) {
2203 return wpas_dbus_error_invalid_args(
2204 message, "BSSExpireCount must be >0");
2205 }
2206 return NULL;
2207 }
2208
2209
2210 /**
2211 * wpas_dbus_getter_country - Control country code
2212 * @message: Pointer to incoming dbus message
2213 * @wpa_s: wpa_supplicant structure for a network interface
2214 * Returns: A message containong value of country variable
2215 *
2216 * Getter function for "Country" property.
2217 */
wpas_dbus_getter_country(DBusMessage * message,struct wpa_supplicant * wpa_s)2218 DBusMessage * wpas_dbus_getter_country(DBusMessage *message,
2219 struct wpa_supplicant *wpa_s)
2220 {
2221 char country[3];
2222 char *str = country;
2223
2224 country[0] = wpa_s->conf->country[0];
2225 country[1] = wpa_s->conf->country[1];
2226 country[2] = '\0';
2227
2228 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_STRING,
2229 &str);
2230 }
2231
2232
2233 /**
2234 * wpas_dbus_setter_country - Control country code
2235 * @message: Pointer to incoming dbus message
2236 * @wpa_s: wpa_supplicant structure for a network interface
2237 * Returns: NULL
2238 *
2239 * Setter function for "Country" property.
2240 */
wpas_dbus_setter_country(DBusMessage * message,struct wpa_supplicant * wpa_s)2241 DBusMessage * wpas_dbus_setter_country(DBusMessage *message,
2242 struct wpa_supplicant *wpa_s)
2243 {
2244 DBusMessage *reply = NULL;
2245 const char *country;
2246
2247 reply = wpas_dbus_simple_property_setter(message, DBUS_TYPE_STRING,
2248 &country);
2249 if (reply)
2250 return reply;
2251
2252 if (!country[0] || !country[1])
2253 return wpas_dbus_error_invalid_args(message,
2254 "invalid country code");
2255
2256 if (wpa_s->drv_priv != NULL && wpa_drv_set_country(wpa_s, country)) {
2257 wpa_printf(MSG_DEBUG, "Failed to set country");
2258 return wpas_dbus_error_invalid_args(
2259 message, "failed to set country code");
2260 }
2261
2262 wpa_s->conf->country[0] = country[0];
2263 wpa_s->conf->country[1] = country[1];
2264 return NULL;
2265 }
2266
2267
2268 /**
2269 * wpas_dbus_getter_ifname - Get interface name
2270 * @message: Pointer to incoming dbus message
2271 * @wpa_s: wpa_supplicant structure for a network interface
2272 * Returns: A dbus message containing a name of network interface
2273 * associated with with wpa_s
2274 *
2275 * Getter for "Ifname" property.
2276 */
wpas_dbus_getter_ifname(DBusMessage * message,struct wpa_supplicant * wpa_s)2277 DBusMessage * wpas_dbus_getter_ifname(DBusMessage *message,
2278 struct wpa_supplicant *wpa_s)
2279 {
2280 const char *ifname = wpa_s->ifname;
2281 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_STRING,
2282 &ifname);
2283 }
2284
2285
2286 /**
2287 * wpas_dbus_getter_driver - Get interface name
2288 * @message: Pointer to incoming dbus message
2289 * @wpa_s: wpa_supplicant structure for a network interface
2290 * Returns: A dbus message containing a name of network interface
2291 * driver associated with with wpa_s
2292 *
2293 * Getter for "Driver" property.
2294 */
wpas_dbus_getter_driver(DBusMessage * message,struct wpa_supplicant * wpa_s)2295 DBusMessage * wpas_dbus_getter_driver(DBusMessage *message,
2296 struct wpa_supplicant *wpa_s)
2297 {
2298 const char *driver;
2299
2300 if (wpa_s->driver == NULL || wpa_s->driver->name == NULL) {
2301 wpa_printf(MSG_DEBUG, "wpas_dbus_getter_driver[dbus]: "
2302 "wpa_s has no driver set");
2303 return wpas_dbus_error_unknown_error(message, NULL);
2304 }
2305
2306 driver = wpa_s->driver->name;
2307 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_STRING,
2308 &driver);
2309 }
2310
2311
2312 /**
2313 * wpas_dbus_getter_current_bss - Get current bss object path
2314 * @message: Pointer to incoming dbus message
2315 * @wpa_s: wpa_supplicant structure for a network interface
2316 * Returns: A dbus message containing a DBus object path to
2317 * current BSS
2318 *
2319 * Getter for "CurrentBSS" property.
2320 */
wpas_dbus_getter_current_bss(DBusMessage * message,struct wpa_supplicant * wpa_s)2321 DBusMessage * wpas_dbus_getter_current_bss(DBusMessage *message,
2322 struct wpa_supplicant *wpa_s)
2323 {
2324 DBusMessage *reply;
2325 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *bss_obj_path = path_buf;
2326
2327 if (wpa_s->current_bss)
2328 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2329 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
2330 wpa_s->dbus_new_path, wpa_s->current_bss->id);
2331 else
2332 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
2333
2334 reply = wpas_dbus_simple_property_getter(message,
2335 DBUS_TYPE_OBJECT_PATH,
2336 &bss_obj_path);
2337
2338 return reply;
2339 }
2340
2341
2342 /**
2343 * wpas_dbus_getter_current_network - Get current network object path
2344 * @message: Pointer to incoming dbus message
2345 * @wpa_s: wpa_supplicant structure for a network interface
2346 * Returns: A dbus message containing a DBus object path to
2347 * current network
2348 *
2349 * Getter for "CurrentNetwork" property.
2350 */
wpas_dbus_getter_current_network(DBusMessage * message,struct wpa_supplicant * wpa_s)2351 DBusMessage * wpas_dbus_getter_current_network(DBusMessage *message,
2352 struct wpa_supplicant *wpa_s)
2353 {
2354 DBusMessage *reply;
2355 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *net_obj_path = path_buf;
2356
2357 if (wpa_s->current_ssid)
2358 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2359 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
2360 wpa_s->dbus_new_path, wpa_s->current_ssid->id);
2361 else
2362 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
2363
2364 reply = wpas_dbus_simple_property_getter(message,
2365 DBUS_TYPE_OBJECT_PATH,
2366 &net_obj_path);
2367
2368 return reply;
2369 }
2370
2371
2372 /**
2373 * wpas_dbus_getter_current_auth_mode - Get current authentication type
2374 * @message: Pointer to incoming dbus message
2375 * @wpa_s: wpa_supplicant structure for a network interface
2376 * Returns: A dbus message containing a string indicating the current
2377 * authentication type.
2378 *
2379 * Getter for "CurrentAuthMode" property.
2380 */
wpas_dbus_getter_current_auth_mode(DBusMessage * message,struct wpa_supplicant * wpa_s)2381 DBusMessage * wpas_dbus_getter_current_auth_mode(DBusMessage *message,
2382 struct wpa_supplicant *wpa_s)
2383 {
2384 DBusMessage *reply;
2385 const char *eap_mode;
2386 const char *auth_mode;
2387 char eap_mode_buf[WPAS_DBUS_AUTH_MODE_MAX];
2388
2389 if (wpa_s->wpa_state != WPA_COMPLETED) {
2390 auth_mode = "INACTIVE";
2391 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X ||
2392 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2393 eap_mode = wpa_supplicant_get_eap_mode(wpa_s);
2394 os_snprintf(eap_mode_buf, WPAS_DBUS_AUTH_MODE_MAX,
2395 "EAP-%s", eap_mode);
2396 auth_mode = eap_mode_buf;
2397
2398 } else {
2399 auth_mode = wpa_key_mgmt_txt(wpa_s->key_mgmt,
2400 wpa_s->current_ssid->proto);
2401 }
2402
2403 reply = wpas_dbus_simple_property_getter(message,
2404 DBUS_TYPE_STRING,
2405 &auth_mode);
2406
2407 return reply;
2408 }
2409
2410
2411 /**
2412 * wpas_dbus_getter_bridge_ifname - Get interface name
2413 * @message: Pointer to incoming dbus message
2414 * @wpa_s: wpa_supplicant structure for a network interface
2415 * Returns: A dbus message containing a name of bridge network
2416 * interface associated with with wpa_s
2417 *
2418 * Getter for "BridgeIfname" property.
2419 */
wpas_dbus_getter_bridge_ifname(DBusMessage * message,struct wpa_supplicant * wpa_s)2420 DBusMessage * wpas_dbus_getter_bridge_ifname(DBusMessage *message,
2421 struct wpa_supplicant *wpa_s)
2422 {
2423 const char *bridge_ifname = NULL;
2424
2425 bridge_ifname = wpa_s->bridge_ifname;
2426 if (bridge_ifname == NULL) {
2427 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bridge_ifname[dbus]: "
2428 "wpa_s has no bridge interface name set");
2429 return wpas_dbus_error_unknown_error(message, NULL);
2430 }
2431
2432 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_STRING,
2433 &bridge_ifname);
2434 }
2435
2436
2437 /**
2438 * wpas_dbus_getter_bsss - Get array of BSSs objects
2439 * @message: Pointer to incoming dbus message
2440 * @wpa_s: wpa_supplicant structure for a network interface
2441 * Returns: a dbus message containing an array of all known BSS objects
2442 * dbus paths
2443 *
2444 * Getter for "BSSs" property.
2445 */
wpas_dbus_getter_bsss(DBusMessage * message,struct wpa_supplicant * wpa_s)2446 DBusMessage * wpas_dbus_getter_bsss(DBusMessage *message,
2447 struct wpa_supplicant *wpa_s)
2448 {
2449 DBusMessage *reply = NULL;
2450 struct wpa_bss *bss;
2451 char **paths;
2452 unsigned int i = 0;
2453
2454 paths = os_zalloc(wpa_s->num_bss * sizeof(char *));
2455 if (!paths) {
2456 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2457 NULL);
2458 }
2459
2460 /* Loop through scan results and append each result's object path */
2461 dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
2462 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
2463 if (paths[i] == NULL) {
2464 reply = dbus_message_new_error(message,
2465 DBUS_ERROR_NO_MEMORY,
2466 NULL);
2467 goto out;
2468 }
2469 /* Construct the object path for this BSS. */
2470 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
2471 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
2472 wpa_s->dbus_new_path, bss->id);
2473 }
2474
2475 reply = wpas_dbus_simple_array_property_getter(message,
2476 DBUS_TYPE_OBJECT_PATH,
2477 paths, wpa_s->num_bss);
2478
2479 out:
2480 while (i)
2481 os_free(paths[--i]);
2482 os_free(paths);
2483 return reply;
2484 }
2485
2486
2487 /**
2488 * wpas_dbus_getter_networks - Get array of networks objects
2489 * @message: Pointer to incoming dbus message
2490 * @wpa_s: wpa_supplicant structure for a network interface
2491 * Returns: a dbus message containing an array of all configured
2492 * networks dbus object paths.
2493 *
2494 * Getter for "Networks" property.
2495 */
wpas_dbus_getter_networks(DBusMessage * message,struct wpa_supplicant * wpa_s)2496 DBusMessage * wpas_dbus_getter_networks(DBusMessage *message,
2497 struct wpa_supplicant *wpa_s)
2498 {
2499 DBusMessage *reply = NULL;
2500 struct wpa_ssid *ssid;
2501 char **paths;
2502 unsigned int i = 0, num = 0;
2503
2504 if (wpa_s->conf == NULL) {
2505 wpa_printf(MSG_ERROR, "wpas_dbus_getter_networks[dbus]: "
2506 "An error occurred getting networks list.");
2507 return wpas_dbus_error_unknown_error(message, NULL);
2508 }
2509
2510 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
2511 if (!network_is_persistent_group(ssid))
2512 num++;
2513
2514 paths = os_zalloc(num * sizeof(char *));
2515 if (!paths) {
2516 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2517 NULL);
2518 }
2519
2520 /* Loop through configured networks and append object path of each */
2521 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2522 if (network_is_persistent_group(ssid))
2523 continue;
2524 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
2525 if (paths[i] == NULL) {
2526 reply = dbus_message_new_error(message,
2527 DBUS_ERROR_NO_MEMORY,
2528 NULL);
2529 goto out;
2530 }
2531
2532 /* Construct the object path for this network. */
2533 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
2534 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
2535 wpa_s->dbus_new_path, ssid->id);
2536 }
2537
2538 reply = wpas_dbus_simple_array_property_getter(message,
2539 DBUS_TYPE_OBJECT_PATH,
2540 paths, num);
2541
2542 out:
2543 while (i)
2544 os_free(paths[--i]);
2545 os_free(paths);
2546 return reply;
2547 }
2548
2549
2550 /**
2551 * wpas_dbus_getter_blobs - Get all blobs defined for this interface
2552 * @message: Pointer to incoming dbus message
2553 * @wpa_s: wpa_supplicant structure for a network interface
2554 * Returns: a dbus message containing a dictionary of pairs (blob_name, blob)
2555 *
2556 * Getter for "Blobs" property.
2557 */
wpas_dbus_getter_blobs(DBusMessage * message,struct wpa_supplicant * wpa_s)2558 DBusMessage * wpas_dbus_getter_blobs(DBusMessage *message,
2559 struct wpa_supplicant *wpa_s)
2560 {
2561 DBusMessage *reply = NULL;
2562 DBusMessageIter iter, variant_iter, dict_iter, entry_iter, array_iter;
2563 struct wpa_config_blob *blob;
2564
2565 if (message == NULL)
2566 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
2567 else
2568 reply = dbus_message_new_method_return(message);
2569 if (!reply)
2570 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2571 NULL);
2572
2573 dbus_message_iter_init_append(reply, &iter);
2574
2575 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
2576 "a{say}", &variant_iter) ||
2577 !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
2578 "{say}", &dict_iter)) {
2579 dbus_message_unref(reply);
2580 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2581 NULL);
2582 }
2583
2584 blob = wpa_s->conf->blobs;
2585 while (blob) {
2586 if (!dbus_message_iter_open_container(&dict_iter,
2587 DBUS_TYPE_DICT_ENTRY,
2588 NULL, &entry_iter) ||
2589 !dbus_message_iter_append_basic(&entry_iter,
2590 DBUS_TYPE_STRING,
2591 &(blob->name)) ||
2592 !dbus_message_iter_open_container(&entry_iter,
2593 DBUS_TYPE_ARRAY,
2594 DBUS_TYPE_BYTE_AS_STRING,
2595 &array_iter) ||
2596 !dbus_message_iter_append_fixed_array(&array_iter,
2597 DBUS_TYPE_BYTE,
2598 &(blob->data),
2599 blob->len) ||
2600 !dbus_message_iter_close_container(&entry_iter,
2601 &array_iter) ||
2602 !dbus_message_iter_close_container(&dict_iter,
2603 &entry_iter)) {
2604 dbus_message_unref(reply);
2605 return dbus_message_new_error(message,
2606 DBUS_ERROR_NO_MEMORY,
2607 NULL);
2608 }
2609
2610 blob = blob->next;
2611 }
2612
2613 if (!dbus_message_iter_close_container(&variant_iter, &dict_iter) ||
2614 !dbus_message_iter_close_container(&iter, &variant_iter)) {
2615 dbus_message_unref(reply);
2616 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2617 NULL);
2618 }
2619
2620 return reply;
2621 }
2622
2623
2624 /**
2625 * wpas_dbus_getter_bss_bssid - Return the BSSID of a BSS
2626 * @message: Pointer to incoming dbus message
2627 * @bss: a pair of interface describing structure and bss's id
2628 * Returns: a dbus message containing the bssid for the requested bss
2629 *
2630 * Getter for "BSSID" property.
2631 */
wpas_dbus_getter_bss_bssid(DBusMessage * message,struct bss_handler_args * bss)2632 DBusMessage * wpas_dbus_getter_bss_bssid(DBusMessage *message,
2633 struct bss_handler_args *bss)
2634 {
2635 struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id);
2636
2637 if (!res) {
2638 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_bssid[dbus]: no "
2639 "bss with id %d found", bss->id);
2640 return NULL;
2641 }
2642
2643 return wpas_dbus_simple_array_property_getter(message, DBUS_TYPE_BYTE,
2644 res->bssid, ETH_ALEN);
2645 }
2646
2647
2648 /**
2649 * wpas_dbus_getter_bss_ssid - Return the SSID of a BSS
2650 * @message: Pointer to incoming dbus message
2651 * @bss: a pair of interface describing structure and bss's id
2652 * Returns: a dbus message containing the ssid for the requested bss
2653 *
2654 * Getter for "SSID" property.
2655 */
wpas_dbus_getter_bss_ssid(DBusMessage * message,struct bss_handler_args * bss)2656 DBusMessage * wpas_dbus_getter_bss_ssid(DBusMessage *message,
2657 struct bss_handler_args *bss)
2658 {
2659 struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id);
2660
2661 if (!res) {
2662 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_ssid[dbus]: no "
2663 "bss with id %d found", bss->id);
2664 return NULL;
2665 }
2666
2667 return wpas_dbus_simple_array_property_getter(message, DBUS_TYPE_BYTE,
2668 res->ssid,
2669 res->ssid_len);
2670 }
2671
2672
2673 /**
2674 * wpas_dbus_getter_bss_privacy - Return the privacy flag of a BSS
2675 * @message: Pointer to incoming dbus message
2676 * @bss: a pair of interface describing structure and bss's id
2677 * Returns: a dbus message containing the privacy flag value of requested bss
2678 *
2679 * Getter for "Privacy" property.
2680 */
wpas_dbus_getter_bss_privacy(DBusMessage * message,struct bss_handler_args * bss)2681 DBusMessage * wpas_dbus_getter_bss_privacy(DBusMessage *message,
2682 struct bss_handler_args *bss)
2683 {
2684 struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id);
2685 dbus_bool_t privacy;
2686
2687 if (!res) {
2688 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_privacy[dbus]: no "
2689 "bss with id %d found", bss->id);
2690 return NULL;
2691 }
2692
2693 privacy = (res->caps & IEEE80211_CAP_PRIVACY) ? TRUE : FALSE;
2694 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_BOOLEAN,
2695 &privacy);
2696 }
2697
2698
2699 /**
2700 * wpas_dbus_getter_bss_mode - Return the mode of a BSS
2701 * @message: Pointer to incoming dbus message
2702 * @bss: a pair of interface describing structure and bss's id
2703 * Returns: a dbus message containing the mode of requested bss
2704 *
2705 * Getter for "Mode" property.
2706 */
wpas_dbus_getter_bss_mode(DBusMessage * message,struct bss_handler_args * bss)2707 DBusMessage * wpas_dbus_getter_bss_mode(DBusMessage *message,
2708 struct bss_handler_args *bss)
2709 {
2710 struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id);
2711 const char *mode;
2712
2713 if (!res) {
2714 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_mode[dbus]: no "
2715 "bss with id %d found", bss->id);
2716 return NULL;
2717 }
2718
2719 if (res->caps & IEEE80211_CAP_IBSS)
2720 mode = "ad-hoc";
2721 else
2722 mode = "infrastructure";
2723
2724 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_STRING,
2725 &mode);
2726 }
2727
2728
2729 /**
2730 * wpas_dbus_getter_bss_level - Return the signal strength of a BSS
2731 * @message: Pointer to incoming dbus message
2732 * @bss: a pair of interface describing structure and bss's id
2733 * Returns: a dbus message containing the signal strength of requested bss
2734 *
2735 * Getter for "Level" property.
2736 */
wpas_dbus_getter_bss_signal(DBusMessage * message,struct bss_handler_args * bss)2737 DBusMessage * wpas_dbus_getter_bss_signal(DBusMessage *message,
2738 struct bss_handler_args *bss)
2739 {
2740 struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id);
2741
2742 if (!res) {
2743 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_signal[dbus]: no "
2744 "bss with id %d found", bss->id);
2745 return NULL;
2746 }
2747
2748 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_INT16,
2749 &res->level);
2750 }
2751
2752
2753 /**
2754 * wpas_dbus_getter_bss_frequency - Return the frequency of a BSS
2755 * @message: Pointer to incoming dbus message
2756 * @bss: a pair of interface describing structure and bss's id
2757 * Returns: a dbus message containing the frequency of requested bss
2758 *
2759 * Getter for "Frequency" property.
2760 */
wpas_dbus_getter_bss_frequency(DBusMessage * message,struct bss_handler_args * bss)2761 DBusMessage * wpas_dbus_getter_bss_frequency(DBusMessage *message,
2762 struct bss_handler_args *bss)
2763 {
2764 struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id);
2765
2766 if (!res) {
2767 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_frequency[dbus]: "
2768 "no bss with id %d found", bss->id);
2769 return NULL;
2770 }
2771
2772 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_UINT16,
2773 &res->freq);
2774 }
2775
2776
cmp_u8s_desc(const void * a,const void * b)2777 static int cmp_u8s_desc(const void *a, const void *b)
2778 {
2779 return (*(u8 *) b - *(u8 *) a);
2780 }
2781
2782
2783 /**
2784 * wpas_dbus_getter_bss_rates - Return available bit rates of a BSS
2785 * @message: Pointer to incoming dbus message
2786 * @bss: a pair of interface describing structure and bss's id
2787 * Returns: a dbus message containing sorted array of bit rates
2788 *
2789 * Getter for "Rates" property.
2790 */
wpas_dbus_getter_bss_rates(DBusMessage * message,struct bss_handler_args * bss)2791 DBusMessage * wpas_dbus_getter_bss_rates(DBusMessage *message,
2792 struct bss_handler_args *bss)
2793 {
2794 DBusMessage *reply;
2795 struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id);
2796 u8 *ie_rates = NULL;
2797 u32 *real_rates;
2798 int rates_num, i;
2799
2800 if (!res) {
2801 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_rates[dbus]: "
2802 "no bss with id %d found", bss->id);
2803 return NULL;
2804 }
2805
2806 rates_num = wpa_bss_get_bit_rates(res, &ie_rates);
2807 if (rates_num < 0)
2808 return NULL;
2809
2810 qsort(ie_rates, rates_num, 1, cmp_u8s_desc);
2811
2812 real_rates = os_malloc(sizeof(u32) * rates_num);
2813 if (!real_rates) {
2814 os_free(ie_rates);
2815 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2816 NULL);
2817 }
2818
2819 for (i = 0; i < rates_num; i++)
2820 real_rates[i] = ie_rates[i] * 500000;
2821
2822 reply = wpas_dbus_simple_array_property_getter(message,
2823 DBUS_TYPE_UINT32,
2824 real_rates, rates_num);
2825
2826 os_free(ie_rates);
2827 os_free(real_rates);
2828 return reply;
2829 }
2830
2831
wpas_dbus_get_bss_security_prop(DBusMessage * message,struct wpa_ie_data * ie_data)2832 static DBusMessage * wpas_dbus_get_bss_security_prop(
2833 DBusMessage *message, struct wpa_ie_data *ie_data)
2834 {
2835 DBusMessage *reply;
2836 DBusMessageIter iter, iter_dict, variant_iter;
2837 const char *group;
2838 const char *pairwise[2]; /* max 2 pairwise ciphers is supported */
2839 const char *key_mgmt[7]; /* max 7 key managements may be supported */
2840 int n;
2841
2842 if (message == NULL)
2843 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
2844 else
2845 reply = dbus_message_new_method_return(message);
2846 if (!reply)
2847 goto nomem;
2848
2849 dbus_message_iter_init_append(reply, &iter);
2850 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
2851 "a{sv}", &variant_iter))
2852 goto nomem;
2853
2854 if (!wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
2855 goto nomem;
2856
2857 /* KeyMgmt */
2858 n = 0;
2859 if (ie_data->key_mgmt & WPA_KEY_MGMT_PSK)
2860 key_mgmt[n++] = "wpa-psk";
2861 if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_PSK)
2862 key_mgmt[n++] = "wpa-ft-psk";
2863 if (ie_data->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
2864 key_mgmt[n++] = "wpa-psk-sha256";
2865 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X)
2866 key_mgmt[n++] = "wpa-eap";
2867 if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X)
2868 key_mgmt[n++] = "wpa-ft-eap";
2869 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256)
2870 key_mgmt[n++] = "wpa-eap-sha256";
2871 if (ie_data->key_mgmt & WPA_KEY_MGMT_NONE)
2872 key_mgmt[n++] = "wpa-none";
2873
2874 if (!wpa_dbus_dict_append_string_array(&iter_dict, "KeyMgmt",
2875 key_mgmt, n))
2876 goto nomem;
2877
2878 /* Group */
2879 switch (ie_data->group_cipher) {
2880 case WPA_CIPHER_WEP40:
2881 group = "wep40";
2882 break;
2883 case WPA_CIPHER_TKIP:
2884 group = "tkip";
2885 break;
2886 case WPA_CIPHER_CCMP:
2887 group = "ccmp";
2888 break;
2889 case WPA_CIPHER_WEP104:
2890 group = "wep104";
2891 break;
2892 default:
2893 group = "";
2894 break;
2895 }
2896
2897 if (!wpa_dbus_dict_append_string(&iter_dict, "Group", group))
2898 goto nomem;
2899
2900 /* Pairwise */
2901 n = 0;
2902 if (ie_data->pairwise_cipher & WPA_CIPHER_TKIP)
2903 pairwise[n++] = "tkip";
2904 if (ie_data->pairwise_cipher & WPA_CIPHER_CCMP)
2905 pairwise[n++] = "ccmp";
2906
2907 if (!wpa_dbus_dict_append_string_array(&iter_dict, "Pairwise",
2908 pairwise, n))
2909 goto nomem;
2910
2911 /* Management group (RSN only) */
2912 if (ie_data->proto == WPA_PROTO_RSN) {
2913 switch (ie_data->mgmt_group_cipher) {
2914 #ifdef CONFIG_IEEE80211W
2915 case WPA_CIPHER_AES_128_CMAC:
2916 group = "aes128cmac";
2917 break;
2918 #endif /* CONFIG_IEEE80211W */
2919 default:
2920 group = "";
2921 break;
2922 }
2923
2924 if (!wpa_dbus_dict_append_string(&iter_dict, "MgmtGroup",
2925 group))
2926 goto nomem;
2927 }
2928
2929 if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict))
2930 goto nomem;
2931 if (!dbus_message_iter_close_container(&iter, &variant_iter))
2932 goto nomem;
2933
2934 return reply;
2935
2936 nomem:
2937 if (reply)
2938 dbus_message_unref(reply);
2939
2940 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, NULL);
2941 }
2942
2943
2944 /**
2945 * wpas_dbus_getter_bss_wpa - Return the WPA options of a BSS
2946 * @message: Pointer to incoming dbus message
2947 * @bss: a pair of interface describing structure and bss's id
2948 * Returns: a dbus message containing the WPA options of requested bss
2949 *
2950 * Getter for "WPA" property.
2951 */
wpas_dbus_getter_bss_wpa(DBusMessage * message,struct bss_handler_args * bss)2952 DBusMessage * wpas_dbus_getter_bss_wpa(DBusMessage *message,
2953 struct bss_handler_args *bss)
2954 {
2955 struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id);
2956 struct wpa_ie_data wpa_data;
2957 const u8 *ie;
2958
2959 if (!res) {
2960 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_wpa[dbus]: no "
2961 "bss with id %d found", bss->id);
2962 return NULL;
2963 }
2964
2965 os_memset(&wpa_data, 0, sizeof(wpa_data));
2966 ie = wpa_bss_get_vendor_ie(res, WPA_IE_VENDOR_TYPE);
2967 if (ie) {
2968 if (wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0)
2969 return wpas_dbus_error_unknown_error(message,
2970 "invalid WPA IE");
2971 }
2972
2973 return wpas_dbus_get_bss_security_prop(message, &wpa_data);
2974 }
2975
2976
2977 /**
2978 * wpas_dbus_getter_bss_rsn - Return the RSN options of a BSS
2979 * @message: Pointer to incoming dbus message
2980 * @bss: a pair of interface describing structure and bss's id
2981 * Returns: a dbus message containing the RSN options of requested bss
2982 *
2983 * Getter for "RSN" property.
2984 */
wpas_dbus_getter_bss_rsn(DBusMessage * message,struct bss_handler_args * bss)2985 DBusMessage * wpas_dbus_getter_bss_rsn(DBusMessage *message,
2986 struct bss_handler_args *bss)
2987 {
2988 struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id);
2989 struct wpa_ie_data wpa_data;
2990 const u8 *ie;
2991
2992 if (!res) {
2993 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_rsn[dbus]: no "
2994 "bss with id %d found", bss->id);
2995 return NULL;
2996 }
2997
2998 os_memset(&wpa_data, 0, sizeof(wpa_data));
2999 ie = wpa_bss_get_ie(res, WLAN_EID_RSN);
3000 if (ie) {
3001 if (wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0)
3002 return wpas_dbus_error_unknown_error(message,
3003 "invalid RSN IE");
3004 }
3005
3006 return wpas_dbus_get_bss_security_prop(message, &wpa_data);
3007 }
3008
3009
3010 /**
3011 * wpas_dbus_getter_bss_ies - Return all IEs of a BSS
3012 * @message: Pointer to incoming dbus message
3013 * @bss: a pair of interface describing structure and bss's id
3014 * Returns: a dbus message containing IEs byte array
3015 *
3016 * Getter for "IEs" property.
3017 */
wpas_dbus_getter_bss_ies(DBusMessage * message,struct bss_handler_args * bss)3018 DBusMessage * wpas_dbus_getter_bss_ies(DBusMessage *message,
3019 struct bss_handler_args *bss)
3020 {
3021 struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id);
3022
3023 if (!res) {
3024 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_ies[dbus]: no "
3025 "bss with id %d found", bss->id);
3026 return NULL;
3027 }
3028
3029 return wpas_dbus_simple_array_property_getter(message, DBUS_TYPE_BYTE,
3030 res + 1, res->ie_len);
3031 }
3032
3033
3034 /**
3035 * wpas_dbus_getter_enabled - Check whether network is enabled or disabled
3036 * @message: Pointer to incoming dbus message
3037 * @wpas_dbus_setter_enabled: wpa_supplicant structure for a network interface
3038 * and wpa_ssid structure for a configured network
3039 * Returns: DBus message with boolean indicating state of configured network
3040 * or DBus error on failure
3041 *
3042 * Getter for "enabled" property of a configured network.
3043 */
wpas_dbus_getter_enabled(DBusMessage * message,struct network_handler_args * net)3044 DBusMessage * wpas_dbus_getter_enabled(DBusMessage *message,
3045 struct network_handler_args *net)
3046 {
3047 dbus_bool_t enabled = net->ssid->disabled ? FALSE : TRUE;
3048 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_BOOLEAN,
3049 &enabled);
3050 }
3051
3052
3053 /**
3054 * wpas_dbus_setter_enabled - Mark a configured network as enabled or disabled
3055 * @message: Pointer to incoming dbus message
3056 * @wpas_dbus_setter_enabled: wpa_supplicant structure for a network interface
3057 * and wpa_ssid structure for a configured network
3058 * Returns: NULL indicating success or DBus error on failure
3059 *
3060 * Setter for "Enabled" property of a configured network.
3061 */
wpas_dbus_setter_enabled(DBusMessage * message,struct network_handler_args * net)3062 DBusMessage * wpas_dbus_setter_enabled(DBusMessage *message,
3063 struct network_handler_args *net)
3064 {
3065 DBusMessage *reply = NULL;
3066
3067 struct wpa_supplicant *wpa_s;
3068 struct wpa_ssid *ssid;
3069
3070 dbus_bool_t enable;
3071
3072 reply = wpas_dbus_simple_property_setter(message, DBUS_TYPE_BOOLEAN,
3073 &enable);
3074
3075 if (reply)
3076 return reply;
3077
3078 wpa_s = net->wpa_s;
3079 ssid = net->ssid;
3080
3081 if (enable)
3082 wpa_supplicant_enable_network(wpa_s, ssid);
3083 else
3084 wpa_supplicant_disable_network(wpa_s, ssid);
3085
3086 return NULL;
3087 }
3088
3089
3090 /**
3091 * wpas_dbus_getter_network_properties - Get options for a configured network
3092 * @message: Pointer to incoming dbus message
3093 * @net: wpa_supplicant structure for a network interface and
3094 * wpa_ssid structure for a configured network
3095 * Returns: DBus message with network properties or DBus error on failure
3096 *
3097 * Getter for "Properties" property of a configured network.
3098 */
wpas_dbus_getter_network_properties(DBusMessage * message,struct network_handler_args * net)3099 DBusMessage * wpas_dbus_getter_network_properties(
3100 DBusMessage *message, struct network_handler_args *net)
3101 {
3102 DBusMessage *reply = NULL;
3103 DBusMessageIter iter, variant_iter, dict_iter;
3104 char **iterator;
3105 char **props = wpa_config_get_all(net->ssid, 1);
3106 if (!props)
3107 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
3108 NULL);
3109
3110 if (message == NULL)
3111 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
3112 else
3113 reply = dbus_message_new_method_return(message);
3114 if (!reply) {
3115 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
3116 NULL);
3117 goto out;
3118 }
3119
3120 dbus_message_iter_init_append(reply, &iter);
3121
3122 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
3123 "a{sv}", &variant_iter) ||
3124 !wpa_dbus_dict_open_write(&variant_iter, &dict_iter)) {
3125 dbus_message_unref(reply);
3126 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
3127 NULL);
3128 goto out;
3129 }
3130
3131 iterator = props;
3132 while (*iterator) {
3133 if (!wpa_dbus_dict_append_string(&dict_iter, *iterator,
3134 *(iterator + 1))) {
3135 dbus_message_unref(reply);
3136 reply = dbus_message_new_error(message,
3137 DBUS_ERROR_NO_MEMORY,
3138 NULL);
3139 goto out;
3140 }
3141 iterator += 2;
3142 }
3143
3144
3145 if (!wpa_dbus_dict_close_write(&variant_iter, &dict_iter) ||
3146 !dbus_message_iter_close_container(&iter, &variant_iter)) {
3147 dbus_message_unref(reply);
3148 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
3149 NULL);
3150 goto out;
3151 }
3152
3153 out:
3154 iterator = props;
3155 while (*iterator) {
3156 os_free(*iterator);
3157 iterator++;
3158 }
3159 os_free(props);
3160 return reply;
3161 }
3162
3163
3164 /**
3165 * wpas_dbus_setter_network_properties - Set options for a configured network
3166 * @message: Pointer to incoming dbus message
3167 * @net: wpa_supplicant structure for a network interface and
3168 * wpa_ssid structure for a configured network
3169 * Returns: NULL indicating success or DBus error on failure
3170 *
3171 * Setter for "Properties" property of a configured network.
3172 */
wpas_dbus_setter_network_properties(DBusMessage * message,struct network_handler_args * net)3173 DBusMessage * wpas_dbus_setter_network_properties(
3174 DBusMessage *message, struct network_handler_args *net)
3175 {
3176 struct wpa_ssid *ssid = net->ssid;
3177
3178 DBusMessage *reply = NULL;
3179 DBusMessageIter iter, variant_iter;
3180
3181 dbus_message_iter_init(message, &iter);
3182
3183 dbus_message_iter_next(&iter);
3184 dbus_message_iter_next(&iter);
3185
3186 dbus_message_iter_recurse(&iter, &variant_iter);
3187
3188 reply = set_network_properties(message, net->wpa_s, ssid,
3189 &variant_iter);
3190 if (reply)
3191 wpa_printf(MSG_DEBUG, "dbus control interface couldn't set "
3192 "network properties");
3193
3194 return reply;
3195 }
3196