dbus: Verify dbus_message_new_method_return() return value before use
[hostap-gosc2009.git] / wpa_supplicant / dbus / dbus_new_handlers.c
blobfe763add90d804f7f36e73511b5a2a22d2b6621a
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, Witold Sowa <witold.sowa@gmail.com>
5 * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
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.
11 * Alternatively, this software may be distributed under the terms of BSD
12 * license.
14 * See README and COPYING for more details.
17 #include "includes.h"
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 "../config.h"
24 #include "../wpa_supplicant_i.h"
25 #include "../driver_i.h"
26 #include "../notify.h"
27 #include "../wpas_glue.h"
28 #include "../bss.h"
29 #include "dbus_new_helpers.h"
30 #include "dbus_new.h"
31 #include "dbus_new_handlers.h"
32 #include "dbus_dict_helpers.h"
34 extern int wpa_debug_level;
35 extern int wpa_debug_show_keys;
36 extern int wpa_debug_timestamp;
39 /**
40 * wpas_dbus_new_decompose_object_path - Decompose an interface object path into parts
41 * @path: The dbus object path
42 * @network: (out) the configured network this object path refers to, if any
43 * @bssid: (out) the scanned bssid this object path refers to, if any
44 * Returns: The object path of the network interface this path refers to
46 * For a given object path, decomposes the object path into object id, network,
47 * and BSSID parts, if those parts exist.
49 static char * wpas_dbus_new_decompose_object_path(const char *path,
50 char **network,
51 char **bssid)
53 const unsigned int dev_path_prefix_len =
54 strlen(WPAS_DBUS_NEW_PATH_INTERFACES "/");
55 char *obj_path_only;
56 char *next_sep;
58 /* Be a bit paranoid about path */
59 if (!path || os_strncmp(path, WPAS_DBUS_NEW_PATH_INTERFACES "/",
60 dev_path_prefix_len))
61 return NULL;
63 /* Ensure there's something at the end of the path */
64 if ((path + dev_path_prefix_len)[0] == '\0')
65 return NULL;
67 obj_path_only = os_strdup(path);
68 if (obj_path_only == NULL)
69 return NULL;
71 next_sep = os_strchr(obj_path_only + dev_path_prefix_len, '/');
72 if (next_sep != NULL) {
73 const char *net_part = os_strstr(
74 next_sep, WPAS_DBUS_NEW_NETWORKS_PART "/");
75 const char *bssid_part = os_strstr(
76 next_sep, WPAS_DBUS_NEW_BSSIDS_PART "/");
78 if (network && net_part) {
79 /* Deal with a request for a configured network */
80 const char *net_name = net_part +
81 os_strlen(WPAS_DBUS_NEW_NETWORKS_PART "/");
82 *network = NULL;
83 if (os_strlen(net_name))
84 *network = os_strdup(net_name);
85 } else if (bssid && bssid_part) {
86 /* Deal with a request for a scanned BSSID */
87 const char *bssid_name = bssid_part +
88 os_strlen(WPAS_DBUS_NEW_BSSIDS_PART "/");
89 if (strlen(bssid_name))
90 *bssid = os_strdup(bssid_name);
91 else
92 *bssid = NULL;
95 /* Cut off interface object path before "/" */
96 *next_sep = '\0';
99 return obj_path_only;
104 * wpas_dbus_error_unknown_error - Return a new InvalidArgs error message
105 * @message: Pointer to incoming dbus message this error refers to
106 * @arg: Optional string appended to error message
107 * Returns: a dbus error message
109 * Convenience function to create and return an UnknownError
111 DBusMessage * wpas_dbus_error_unknown_error(DBusMessage *message,
112 const char *arg)
114 return dbus_message_new_error(message, WPAS_DBUS_ERROR_UNKNOWN_ERROR,
115 arg);
120 * wpas_dbus_error_iface_unknown - Return a new invalid interface error message
121 * @message: Pointer to incoming dbus message this error refers to
122 * Returns: A dbus error message
124 * Convenience function to create and return an invalid interface error
126 static DBusMessage * wpas_dbus_error_iface_unknown(DBusMessage *message)
128 return dbus_message_new_error(message, WPAS_DBUS_ERROR_IFACE_UNKNOWN,
129 "wpa_supplicant knows nothing about "
130 "this interface.");
135 * wpas_dbus_error_network_unknown - Return a new NetworkUnknown error message
136 * @message: Pointer to incoming dbus message this error refers to
137 * Returns: a dbus error message
139 * Convenience function to create and return an invalid network error
141 static DBusMessage * wpas_dbus_error_network_unknown(DBusMessage *message)
143 return dbus_message_new_error(message, WPAS_DBUS_ERROR_NETWORK_UNKNOWN,
144 "There is no such a network in this "
145 "interface.");
150 * wpas_dbus_error_invald_args - Return a new InvalidArgs error message
151 * @message: Pointer to incoming dbus message this error refers to
152 * Returns: a dbus error message
154 * Convenience function to create and return an invalid options error
156 DBusMessage * wpas_dbus_error_invald_args(DBusMessage *message,
157 const char *arg)
159 DBusMessage *reply;
161 reply = dbus_message_new_error(message, WPAS_DBUS_ERROR_INVALID_ARGS,
162 "Did not receive correct message "
163 "arguments.");
164 if (arg != NULL)
165 dbus_message_append_args(reply, DBUS_TYPE_STRING, &arg,
166 DBUS_TYPE_INVALID);
168 return reply;
172 static const char *dont_quote[] = {
173 "key_mgmt", "proto", "pairwise", "auth_alg", "group", "eap",
174 "opensc_engine_path", "pkcs11_engine_path", "pkcs11_module_path",
175 "bssid", NULL
178 static dbus_bool_t should_quote_opt(const char *key)
180 int i = 0;
181 while (dont_quote[i] != NULL) {
182 if (os_strcmp(key, dont_quote[i]) == 0)
183 return FALSE;
184 i++;
186 return TRUE;
190 * get_iface_by_dbus_path - Get a new network interface
191 * @global: Pointer to global data from wpa_supplicant_init()
192 * @path: Pointer to a dbus object path representing an interface
193 * Returns: Pointer to the interface or %NULL if not found
195 static struct wpa_supplicant * get_iface_by_dbus_path(
196 struct wpa_global *global, const char *path)
198 struct wpa_supplicant *wpa_s;
200 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
201 if (os_strcmp(wpa_s->dbus_new_path, path) == 0)
202 return wpa_s;
204 return NULL;
209 * set_network_properties - Set properties of a configured network
210 * @message: Pointer to incoming dbus message
211 * @ssid: wpa_ssid structure for a configured network
212 * @iter: DBus message iterator containing dictionary of network
213 * properties to set.
214 * Returns: NULL when succeed or DBus error on failure
216 * Sets network configuration with parameters given id DBus dictionary
218 static DBusMessage * set_network_properties(DBusMessage *message,
219 struct wpa_ssid *ssid,
220 DBusMessageIter *iter)
223 struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
224 DBusMessage *reply = NULL;
225 DBusMessageIter iter_dict;
227 if (!wpa_dbus_dict_open_read(iter, &iter_dict))
228 return wpas_dbus_error_invald_args(message, NULL);
230 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
231 char *value = NULL;
232 size_t size = 50;
233 int ret;
234 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) {
235 reply = wpas_dbus_error_invald_args(message, NULL);
236 break;
238 if (entry.type == DBUS_TYPE_ARRAY &&
239 entry.array_type == DBUS_TYPE_BYTE) {
240 if (entry.array_len <= 0)
241 goto error;
243 size = entry.array_len * 2 + 1;
244 value = os_zalloc(size);
245 if (value == NULL)
246 goto error;
248 ret = wpa_snprintf_hex(value, size,
249 (u8 *) entry.bytearray_value,
250 entry.array_len);
251 if (ret <= 0)
252 goto error;
253 } else if (entry.type == DBUS_TYPE_STRING) {
254 if (should_quote_opt(entry.key)) {
255 size = os_strlen(entry.str_value);
256 if (size <= 0)
257 goto error;
259 size += 3;
260 value = os_zalloc(size);
261 if (value == NULL)
262 goto error;
264 ret = os_snprintf(value, size, "\"%s\"",
265 entry.str_value);
266 if (ret < 0 || (size_t) ret != (size - 1))
267 goto error;
268 } else {
269 value = os_strdup(entry.str_value);
270 if (value == NULL)
271 goto error;
273 } else if (entry.type == DBUS_TYPE_UINT32) {
274 value = os_zalloc(size);
275 if (value == NULL)
276 goto error;
278 ret = os_snprintf(value, size, "%u",
279 entry.uint32_value);
280 if (ret <= 0)
281 goto error;
282 } else if (entry.type == DBUS_TYPE_INT32) {
283 value = os_zalloc(size);
284 if (value == NULL)
285 goto error;
287 ret = os_snprintf(value, size, "%d",
288 entry.int32_value);
289 if (ret <= 0)
290 goto error;
291 } else
292 goto error;
294 if (wpa_config_set(ssid, entry.key, value, 0) < 0)
295 goto error;
297 if ((os_strcmp(entry.key, "psk") == 0 &&
298 value[0] == '"' && ssid->ssid_len) ||
299 (strcmp(entry.key, "ssid") == 0 && ssid->passphrase))
300 wpa_config_update_psk(ssid);
302 os_free(value);
303 wpa_dbus_dict_entry_clear(&entry);
304 continue;
306 error:
307 os_free(value);
308 reply = wpas_dbus_error_invald_args(message, entry.key);
309 wpa_dbus_dict_entry_clear(&entry);
310 break;
313 return reply;
318 * wpas_dbus_handler_create_interface - Request registration of a network iface
319 * @message: Pointer to incoming dbus message
320 * @global: %wpa_supplicant global data structure
321 * Returns: The object path of the new interface object,
322 * or a dbus error message with more information
324 * Handler function for "CreateInterface" method call. Handles requests
325 * by dbus clients to register a network interface that wpa_supplicant
326 * will manage.
328 DBusMessage * wpas_dbus_handler_create_interface(DBusMessage *message,
329 struct wpa_global *global)
331 DBusMessageIter iter_dict;
332 DBusMessage *reply = NULL;
333 DBusMessageIter iter;
334 struct wpa_dbus_dict_entry entry;
335 char *driver = NULL;
336 char *ifname = NULL;
337 char *bridge_ifname = NULL;
339 dbus_message_iter_init(message, &iter);
341 if (!wpa_dbus_dict_open_read(&iter, &iter_dict))
342 goto error;
343 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
344 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
345 goto error;
346 if (!strcmp(entry.key, "Driver") &&
347 (entry.type == DBUS_TYPE_STRING)) {
348 driver = os_strdup(entry.str_value);
349 wpa_dbus_dict_entry_clear(&entry);
350 if (driver == NULL)
351 goto error;
352 } else if (!strcmp(entry.key, "Ifname") &&
353 (entry.type == DBUS_TYPE_STRING)) {
354 ifname = os_strdup(entry.str_value);
355 wpa_dbus_dict_entry_clear(&entry);
356 if (ifname == NULL)
357 goto error;
358 } else if (!strcmp(entry.key, "BridgeIfname") &&
359 (entry.type == DBUS_TYPE_STRING)) {
360 bridge_ifname = os_strdup(entry.str_value);
361 wpa_dbus_dict_entry_clear(&entry);
362 if (bridge_ifname == NULL)
363 goto error;
364 } else {
365 wpa_dbus_dict_entry_clear(&entry);
366 goto error;
370 if (ifname == NULL)
371 goto error; /* Required Ifname argument missing */
374 * Try to get the wpa_supplicant record for this iface, return
375 * an error if we already control it.
377 if (wpa_supplicant_get_iface(global, ifname) != NULL) {
378 reply = dbus_message_new_error(message,
379 WPAS_DBUS_ERROR_IFACE_EXISTS,
380 "wpa_supplicant already "
381 "controls this interface.");
382 } else {
383 struct wpa_supplicant *wpa_s;
384 struct wpa_interface iface;
385 os_memset(&iface, 0, sizeof(iface));
386 iface.driver = driver;
387 iface.ifname = ifname;
388 iface.bridge_ifname = bridge_ifname;
389 /* Otherwise, have wpa_supplicant attach to it. */
390 if ((wpa_s = wpa_supplicant_add_iface(global, &iface))) {
391 const char *path = wpas_dbus_get_path(wpa_s);
392 reply = dbus_message_new_method_return(message);
393 dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH,
394 &path, DBUS_TYPE_INVALID);
395 } else {
396 reply = wpas_dbus_error_unknown_error(
397 message, "wpa_supplicant couldn't grab this "
398 "interface.");
402 out:
403 os_free(driver);
404 os_free(ifname);
405 os_free(bridge_ifname);
406 return reply;
408 error:
409 reply = wpas_dbus_error_invald_args(message, NULL);
410 goto out;
415 * wpas_dbus_handler_remove_interface - Request deregistration of an interface
416 * @message: Pointer to incoming dbus message
417 * @global: wpa_supplicant global data structure
418 * Returns: a dbus message containing a UINT32 indicating success (1) or
419 * failure (0), or returns a dbus error message with more information
421 * Handler function for "removeInterface" method call. Handles requests
422 * by dbus clients to deregister a network interface that wpa_supplicant
423 * currently manages.
425 DBusMessage * wpas_dbus_handler_remove_interface(DBusMessage *message,
426 struct wpa_global *global)
428 struct wpa_supplicant *wpa_s;
429 char *path;
430 DBusMessage *reply = NULL;
432 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path,
433 DBUS_TYPE_INVALID);
435 wpa_s = get_iface_by_dbus_path(global, path);
436 if (wpa_s == NULL)
437 reply = wpas_dbus_error_iface_unknown(message);
438 else if (wpa_supplicant_remove_iface(global, wpa_s)) {
439 reply = wpas_dbus_error_unknown_error(
440 message, "wpa_supplicant couldn't remove this "
441 "interface.");
444 return reply;
449 * wpas_dbus_handler_get_interface - Get the object path for an interface name
450 * @message: Pointer to incoming dbus message
451 * @global: %wpa_supplicant global data structure
452 * Returns: The object path of the interface object,
453 * or a dbus error message with more information
455 * Handler function for "getInterface" method call.
457 DBusMessage * wpas_dbus_handler_get_interface(DBusMessage *message,
458 struct wpa_global *global)
460 DBusMessage *reply = NULL;
461 const char *ifname;
462 const char *path;
463 struct wpa_supplicant *wpa_s;
465 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &ifname,
466 DBUS_TYPE_INVALID);
468 wpa_s = wpa_supplicant_get_iface(global, ifname);
469 if (wpa_s == NULL)
470 return wpas_dbus_error_iface_unknown(message);
472 path = wpas_dbus_get_path(wpa_s);
473 if (path == NULL) {
474 wpa_printf(MSG_ERROR, "wpas_dbus_handler_get_interface[dbus]: "
475 "interface has no dbus object path set");
476 return wpas_dbus_error_unknown_error(message, "path not set");
479 reply = dbus_message_new_method_return(message);
480 if (reply == NULL) {
481 perror("wpas_dbus_handler_get_interface[dbus]: out of memory "
482 "when creating reply");
483 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
484 NULL);
486 if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
487 DBUS_TYPE_INVALID)) {
488 perror("wpas_dbus_handler_get_interface[dbus]: out of memory "
489 "when appending argument to reply");
490 dbus_message_unref(reply);
491 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
492 NULL);
495 return reply;
500 * wpas_dbus_getter_debug_params - Get the debug params
501 * @message: Pointer to incoming dbus message
502 * @global: %wpa_supplicant global data structure
503 * Returns: DBus message with struct containing debug params.
505 * Getter for "DebugParams" property.
507 DBusMessage * wpas_dbus_getter_debug_params(DBusMessage *message,
508 struct wpa_global *global)
510 DBusMessage *reply = NULL;
511 DBusMessageIter iter, variant_iter, struct_iter;
513 if (message == NULL)
514 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
515 else
516 reply = dbus_message_new_method_return(message);
517 if (!reply) {
518 perror("wpas_dbus_getter_network_properties[dbus] out of "
519 "memory when trying to initialize return message");
520 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
521 NULL);
522 goto out;
525 dbus_message_iter_init_append(reply, &iter);
527 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
528 "(ibb)", &variant_iter)) {
529 perror("wpas_dbus_getter_debug_params[dbus] out of memory "
530 "when trying to open variant");
531 dbus_message_unref(reply);
532 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
533 NULL);
534 goto out;
537 if (!dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_STRUCT,
538 NULL, &struct_iter)) {
539 perror("wpas_dbus_getter_debug_params[dbus] out of memory "
540 "when trying to open struct");
541 dbus_message_unref(reply);
542 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
543 NULL);
544 goto out;
547 if (!dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_INT32,
548 &wpa_debug_level)) {
549 perror("wpas_dbus_getter_debug_params[dbus] out of memory "
550 "when trying to append value to struct");
551 dbus_message_unref(reply);
552 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
553 NULL);
554 goto out;
557 if (!dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_BOOLEAN,
558 &wpa_debug_timestamp)) {
559 perror("wpas_dbus_getter_debug_params[dbus] out of memory "
560 "when trying to append value to struct");
561 dbus_message_unref(reply);
562 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
563 NULL);
564 goto out;
567 if (!dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_BOOLEAN,
568 &wpa_debug_show_keys)) {
569 perror("wpas_dbus_getter_debug_params[dbus] out of memory "
570 "when trying to append value to struct");
571 dbus_message_unref(reply);
572 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
573 NULL);
574 goto out;
577 if (!dbus_message_iter_close_container(&variant_iter, &struct_iter)) {
578 perror("wpas_dbus_getter_debug_params[dbus] out of memory "
579 "when trying to close struct");
580 dbus_message_unref(reply);
581 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
582 NULL);
583 goto out;
586 if (!dbus_message_iter_close_container(&iter, &variant_iter)) {
587 perror("wpas_dbus_getter_debug_params[dbus] out of memory "
588 "when trying to close variant");
589 dbus_message_unref(reply);
590 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
591 NULL);
592 goto out;
595 out:
596 return reply;
601 * wpas_dbus_setter_debugparams - Set the debug params
602 * @message: Pointer to incoming dbus message
603 * @global: %wpa_supplicant global data structure
604 * Returns: NULL indicating success or a dbus error message with more
605 * information
607 * Setter for "DebugParams" property.
609 DBusMessage * wpas_dbus_setter_debug_params(DBusMessage *message,
610 struct wpa_global *global)
612 DBusMessage *reply = NULL;
613 DBusMessageIter iter, variant_iter, struct_iter;
614 int debug_level;
615 dbus_bool_t debug_timestamp;
616 dbus_bool_t debug_show_keys;
618 if (!dbus_message_iter_init(message, &iter)) {
619 perror("wpas_dbus_handler_add_blob[dbus] out of memory when "
620 "trying to initialize message iterator");
621 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
622 NULL);
623 goto out;
625 dbus_message_iter_next(&iter);
626 dbus_message_iter_next(&iter);
628 dbus_message_iter_recurse(&iter, &variant_iter);
630 if (dbus_message_iter_get_arg_type(&variant_iter) != DBUS_TYPE_STRUCT)
632 reply = wpas_dbus_error_invald_args(
633 message, "Argument must by a structure");
634 goto out;
637 dbus_message_iter_recurse(&variant_iter, &struct_iter);
640 if (dbus_message_iter_get_arg_type(&struct_iter) != DBUS_TYPE_INT32) {
641 reply = wpas_dbus_error_invald_args(
642 message, "First struct argument must by an INT32");
643 goto out;
646 dbus_message_iter_get_basic(&struct_iter, &debug_level);
647 if (!dbus_message_iter_next(&struct_iter)) {
648 reply = wpas_dbus_error_invald_args(
649 message, "Not enough elements in struct");
650 goto out;
653 if (dbus_message_iter_get_arg_type(&struct_iter) != DBUS_TYPE_BOOLEAN)
655 reply = wpas_dbus_error_invald_args(
656 message, "Second struct argument must by a boolean");
657 goto out;
659 dbus_message_iter_get_basic(&struct_iter, &debug_timestamp);
660 if (!dbus_message_iter_next(&struct_iter)) {
661 reply = wpas_dbus_error_invald_args(
662 message, "Not enough elements in struct");
663 goto out;
666 if (dbus_message_iter_get_arg_type(&struct_iter) != DBUS_TYPE_BOOLEAN)
668 reply = wpas_dbus_error_invald_args(
669 message, "Third struct argument must by an boolean");
670 goto out;
672 dbus_message_iter_get_basic(&struct_iter, &debug_show_keys);
674 if (wpa_supplicant_set_debug_params(global, debug_level,
675 debug_timestamp ? 1 : 0,
676 debug_show_keys ? 1 : 0)) {
677 reply = wpas_dbus_error_invald_args(
678 message, "Wrong debug level value");
679 goto out;
682 out:
683 return reply;
688 * wpas_dbus_getter_interfaces - Request registered interfaces list
689 * @message: Pointer to incoming dbus message
690 * @global: %wpa_supplicant global data structure
691 * Returns: The object paths array containing registered interfaces
692 * objects paths or DBus error on failure
694 * Getter for "Interfaces" property. Handles requests
695 * by dbus clients to return list of registered interfaces objects
696 * paths
698 DBusMessage * wpas_dbus_getter_interfaces(DBusMessage *message,
699 struct wpa_global *global)
701 DBusMessage *reply = NULL;
702 DBusMessageIter iter, variant_iter, array_iter;
703 const char *path;
704 struct wpa_supplicant *wpa_s;
706 if (message == NULL)
707 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
708 else
709 reply = dbus_message_new_method_return(message);
710 if (!reply) {
711 perror("wpas_dbus_getter_interfaces[dbus] out of memory "
712 "when trying to initialize return message");
713 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
714 NULL);
715 goto out;
718 dbus_message_iter_init_append(reply, &iter);
719 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
720 "ao", &variant_iter)) {
721 perror("wpas_dbus_getter_interfaces[dbus] out of memory "
722 "when trying to open variant");
723 dbus_message_unref(reply);
724 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
725 NULL);
726 goto out;
728 if (!dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
729 "o", &array_iter)) {
730 perror("wpas_dbus_getter_interfaces[dbus] out of memory "
731 "when trying to open array");
732 dbus_message_unref(reply);
733 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
734 NULL);
735 goto out;
738 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
739 path = wpas_dbus_get_path(wpa_s);
740 if (!dbus_message_iter_append_basic(&array_iter,
741 DBUS_TYPE_OBJECT_PATH,
742 &path)) {
743 perror("wpas_dbus_getter_interfaces[dbus] out of "
744 "memory when trying to append interface path");
745 dbus_message_unref(reply);
746 reply = dbus_message_new_error(message,
747 DBUS_ERROR_NO_MEMORY,
748 NULL);
749 goto out;
753 if (!dbus_message_iter_close_container(&variant_iter, &array_iter)) {
754 perror("wpas_dbus_getter_interfaces[dbus] out of memory "
755 "when trying to close array");
756 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
757 NULL);
758 goto out;
760 if (!dbus_message_iter_close_container(&iter, &variant_iter)) {
761 perror("wpas_dbus_getter_interfaces[dbus] out of memory "
762 "when trying to close variant");
763 dbus_message_unref(reply);
764 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
765 NULL);
766 goto out;
769 out:
770 return reply;
775 * wpas_dbus_getter_eap_methods - Request supported EAP methods list
776 * @message: Pointer to incoming dbus message
777 * @nothing: not used argument. may be NULL or anything else
778 * Returns: The object paths array containing supported EAP methods
779 * represented by strings or DBus error on failure
781 * Getter for "EapMethods" property. Handles requests
782 * by dbus clients to return list of strings with supported EAP methods
784 DBusMessage * wpas_dbus_getter_eap_methods(DBusMessage *message, void *nothing)
786 DBusMessage *reply = NULL;
787 DBusMessageIter iter, variant_iter, array_iter;
788 char **eap_methods;
789 size_t num_items;
791 if (message == NULL)
792 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
793 else
794 reply = dbus_message_new_method_return(message);
795 if (!reply) {
796 perror("wpas_dbus_getter_eap_methods[dbus] out of memory "
797 "when trying to initialize return message");
798 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
799 NULL);
800 goto out;
803 dbus_message_iter_init_append(reply, &iter);
804 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
805 "as", &variant_iter)) {
806 perror("wpas_dbus_getter_eap_methods[dbus] out of memory "
807 "when trying to open variant");
808 dbus_message_unref(reply);
809 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
810 NULL);
811 goto out;
814 if (!dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
815 "s", &array_iter)) {
816 perror("wpas_dbus_getter_eap_methods[dbus] out of memory "
817 "when trying to open variant");
818 dbus_message_unref(reply);
819 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
820 NULL);
821 goto out;
824 eap_methods = eap_get_names_as_string_array(&num_items);
825 if (eap_methods) {
826 size_t i;
827 int err = 0;
828 for (i = 0; i < num_items; i++) {
829 if (!dbus_message_iter_append_basic(&array_iter,
830 DBUS_TYPE_STRING,
831 &(eap_methods[i])))
832 err = 1;
833 os_free(eap_methods[i]);
835 os_free(eap_methods);
837 if (err) {
838 wpa_printf(MSG_ERROR, "wpas_dbus_getter_eap_methods"
839 "[dbus] out of memory when adding to "
840 "array");
841 dbus_message_unref(reply);
842 reply = dbus_message_new_error(message,
843 DBUS_ERROR_NO_MEMORY,
844 NULL);
845 goto out;
849 if (!dbus_message_iter_close_container(&variant_iter, &array_iter)) {
850 perror("wpas_dbus_getter_eap_methods[dbus] "
851 "out of memory when trying to close array");
852 dbus_message_unref(reply);
853 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
854 NULL);
855 goto out;
857 if (!dbus_message_iter_close_container(&iter, &variant_iter)) {
858 perror("wpas_dbus_getter_eap_methods[dbus] "
859 "out of memory when trying to close variant");
860 dbus_message_unref(reply);
861 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
862 NULL);
863 goto out;
866 out:
867 return reply;
871 static int wpas_dbus_get_scan_type(DBusMessage *message, DBusMessageIter *var,
872 char **type, DBusMessage **reply)
874 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_STRING) {
875 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
876 "Type must be a string");
877 *reply = wpas_dbus_error_invald_args(
878 message, "Wrong Type value type. String required");
879 return -1;
881 dbus_message_iter_get_basic(var, type);
882 return 0;
886 static int wpas_dbus_get_scan_ssids(DBusMessage *message, DBusMessageIter *var,
887 struct wpa_driver_scan_params *params,
888 DBusMessage **reply)
890 struct wpa_driver_scan_ssid *ssids = params->ssids;
891 size_t ssids_num = 0;
892 u8 *ssid;
893 DBusMessageIter array_iter, sub_array_iter;
894 char *val;
895 int len;
897 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
898 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: ssids "
899 "must be an array of arrays of bytes");
900 *reply = wpas_dbus_error_invald_args(
901 message, "Wrong SSIDs value type. Array of arrays of "
902 "bytes required");
903 return -1;
906 dbus_message_iter_recurse(var, &array_iter);
908 if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY ||
909 dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_BYTE)
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_invald_args(
914 message, "Wrong SSIDs value type. Array of arrays of "
915 "bytes required");
916 return -1;
919 while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_ARRAY)
921 if (ssids_num >= WPAS_MAX_SCAN_SSIDS) {
922 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
923 "Too many ssids specified on scan dbus "
924 "call");
925 *reply = wpas_dbus_error_invald_args(
926 message, "Too many ssids specified. Specify "
927 "at most four");
928 return -1;
931 dbus_message_iter_recurse(&array_iter, &sub_array_iter);
933 dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len);
934 if (len == 0) {
935 dbus_message_iter_next(&array_iter);
936 continue;
939 ssid = os_malloc(len);
940 if (ssid == NULL) {
941 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
942 "out of memory. Cannot allocate memory for "
943 "SSID");
944 *reply = dbus_message_new_error(
945 message, DBUS_ERROR_NO_MEMORY, NULL);
946 return -1;
948 os_memcpy(ssid, val, len);
949 ssids[ssids_num].ssid = ssid;
950 ssids[ssids_num].ssid_len = len;
952 dbus_message_iter_next(&array_iter);
953 ssids_num++;
956 params->num_ssids = ssids_num;
957 return 0;
961 static int wpas_dbus_get_scan_ies(DBusMessage *message, DBusMessageIter *var,
962 struct wpa_driver_scan_params *params,
963 DBusMessage **reply)
965 u8 *ies = NULL, *nies;
966 int ies_len = 0;
967 DBusMessageIter array_iter, sub_array_iter;
968 char *val;
969 int len;
971 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
972 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: ies must "
973 "be an array of arrays of bytes");
974 *reply = wpas_dbus_error_invald_args(
975 message, "Wrong IEs value type. Array of arrays of "
976 "bytes required");
977 return -1;
980 dbus_message_iter_recurse(var, &array_iter);
982 if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY ||
983 dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_BYTE)
985 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: ies must "
986 "be an array of arrays of bytes");
987 *reply = wpas_dbus_error_invald_args(
988 message, "Wrong IEs value type. Array required");
989 return -1;
992 while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_ARRAY)
994 dbus_message_iter_recurse(&array_iter, &sub_array_iter);
996 dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len);
997 if (len == 0) {
998 dbus_message_iter_next(&array_iter);
999 continue;
1002 nies = os_realloc(ies, ies_len + len);
1003 if (nies == NULL) {
1004 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1005 "out of memory. Cannot allocate memory for "
1006 "IE");
1007 os_free(ies);
1008 *reply = dbus_message_new_error(
1009 message, DBUS_ERROR_NO_MEMORY, NULL);
1010 return -1;
1012 ies = nies;
1013 os_memcpy(ies + ies_len, val, len);
1014 ies_len += len;
1016 dbus_message_iter_next(&array_iter);
1019 params->extra_ies = ies;
1020 params->extra_ies_len = ies_len;
1021 return 0;
1025 static int wpas_dbus_get_scan_channels(DBusMessage *message,
1026 DBusMessageIter *var,
1027 struct wpa_driver_scan_params *params,
1028 DBusMessage **reply)
1030 DBusMessageIter array_iter, sub_array_iter;
1031 int *freqs = NULL, *nfreqs;
1032 int freqs_num = 0;
1034 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
1035 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1036 "Channels must be an array of structs");
1037 *reply = wpas_dbus_error_invald_args(
1038 message, "Wrong Channels value type. Array of structs "
1039 "required");
1040 return -1;
1043 dbus_message_iter_recurse(var, &array_iter);
1045 if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_STRUCT) {
1046 wpa_printf(MSG_DEBUG,
1047 "wpas_dbus_handler_scan[dbus]: Channels must be an "
1048 "array of structs");
1049 *reply = wpas_dbus_error_invald_args(
1050 message, "Wrong Channels value type. Array of structs "
1051 "required");
1052 return -1;
1055 while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_STRUCT)
1057 int freq, width;
1059 dbus_message_iter_recurse(&array_iter, &sub_array_iter);
1061 if (dbus_message_iter_get_arg_type(&sub_array_iter) !=
1062 DBUS_TYPE_UINT32) {
1063 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1064 "Channel must by specified by struct of "
1065 "two UINT32s %c",
1066 dbus_message_iter_get_arg_type(
1067 &sub_array_iter));
1068 *reply = wpas_dbus_error_invald_args(
1069 message, "Wrong Channel struct. Two UINT32s "
1070 "required");
1071 os_free(freqs);
1072 return -1;
1074 dbus_message_iter_get_basic(&sub_array_iter, &freq);
1076 if (!dbus_message_iter_next(&sub_array_iter) ||
1077 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");
1082 *reply = wpas_dbus_error_invald_args(
1083 message,
1084 "Wrong Channel struct. Two UINT32s required");
1085 os_free(freqs);
1086 return -1;
1089 dbus_message_iter_get_basic(&sub_array_iter, &width);
1091 #define FREQS_ALLOC_CHUNK 32
1092 if (freqs_num % FREQS_ALLOC_CHUNK == 0) {
1093 nfreqs = os_realloc(freqs, sizeof(int) *
1094 (freqs_num + FREQS_ALLOC_CHUNK));
1095 if (nfreqs == NULL)
1096 os_free(freqs);
1097 freqs = nfreqs;
1099 if (freqs == NULL) {
1100 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1101 "out of memory. can't allocate memory for "
1102 "freqs");
1103 *reply = dbus_message_new_error(
1104 message, DBUS_ERROR_NO_MEMORY, NULL);
1105 return -1;
1108 freqs[freqs_num] = freq;
1110 freqs_num++;
1111 dbus_message_iter_next(&array_iter);
1114 nfreqs = os_realloc(freqs,
1115 sizeof(int) * (freqs_num + 1));
1116 if (nfreqs == NULL)
1117 os_free(freqs);
1118 freqs = nfreqs;
1119 if (freqs == NULL) {
1120 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1121 "out of memory. Can't allocate memory for freqs");
1122 *reply = dbus_message_new_error(
1123 message, DBUS_ERROR_NO_MEMORY, NULL);
1124 return -1;
1126 freqs[freqs_num] = 0;
1128 params->freqs = freqs;
1129 return 0;
1134 * wpas_dbus_handler_scan - Request a wireless scan on an interface
1135 * @message: Pointer to incoming dbus message
1136 * @wpa_s: wpa_supplicant structure for a network interface
1137 * Returns: NULL indicating success or DBus error message on failure
1139 * Handler function for "Scan" method call of a network device. Requests
1140 * that wpa_supplicant perform a wireless scan as soon as possible
1141 * on a particular wireless interface.
1143 DBusMessage * wpas_dbus_handler_scan(DBusMessage *message,
1144 struct wpa_supplicant *wpa_s)
1146 DBusMessage *reply = NULL;
1147 DBusMessageIter iter, dict_iter, entry_iter, variant_iter;
1148 char *key = NULL, *type = NULL;
1149 struct wpa_driver_scan_params params;
1150 size_t i;
1152 os_memset(&params, 0, sizeof(params));
1154 dbus_message_iter_init(message, &iter);
1156 dbus_message_iter_recurse(&iter, &dict_iter);
1158 while (dbus_message_iter_get_arg_type(&dict_iter) ==
1159 DBUS_TYPE_DICT_ENTRY) {
1160 dbus_message_iter_recurse(&dict_iter, &entry_iter);
1161 dbus_message_iter_get_basic(&entry_iter, &key);
1162 dbus_message_iter_next(&entry_iter);
1163 dbus_message_iter_recurse(&entry_iter, &variant_iter);
1165 if (os_strcmp(key, "Type") == 0) {
1166 if (wpas_dbus_get_scan_type(message, &variant_iter,
1167 &type, &reply) < 0)
1168 goto out;
1169 } else if (os_strcmp(key, "SSIDs") == 0) {
1170 if (wpas_dbus_get_scan_ssids(message, &variant_iter,
1171 &params, &reply) < 0)
1172 goto out;
1173 } else if (os_strcmp(key, "IEs") == 0) {
1174 if (wpas_dbus_get_scan_ies(message, &variant_iter,
1175 &params, &reply) < 0)
1176 goto out;
1177 } else if (os_strcmp(key, "Channels") == 0) {
1178 if (wpas_dbus_get_scan_channels(message, &variant_iter,
1179 &params, &reply) < 0)
1180 goto out;
1181 } else {
1182 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1183 "Unknown argument %s", key);
1184 reply = wpas_dbus_error_invald_args(message, key);
1185 goto out;
1188 dbus_message_iter_next(&dict_iter);
1191 if (!type) {
1192 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1193 "Scan type not specified");
1194 reply = wpas_dbus_error_invald_args(message, key);
1195 goto out;
1198 if (!os_strcmp(type, "passive")) {
1199 if (params.num_ssids || params.extra_ies_len) {
1200 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1201 "SSIDs or IEs specified for passive scan.");
1202 reply = wpas_dbus_error_invald_args(
1203 message, "You can specify only Channels in "
1204 "passive scan");
1205 goto out;
1206 } else if (params.freqs && params.freqs[0]) {
1207 /* wildcard ssid */
1208 params.num_ssids++;
1209 wpa_supplicant_trigger_scan(wpa_s, &params);
1210 } else {
1211 wpa_s->scan_req = 2;
1212 wpa_supplicant_req_scan(wpa_s, 0, 0);
1214 } else if (!os_strcmp(type, "active")) {
1215 wpa_supplicant_trigger_scan(wpa_s, &params);
1216 } else {
1217 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1218 "Unknown scan type: %s", type);
1219 reply = wpas_dbus_error_invald_args(message,
1220 "Wrong scan type");
1221 goto out;
1224 out:
1225 for (i = 0; i < WPAS_MAX_SCAN_SSIDS; i++)
1226 os_free((u8 *) params.ssids[i].ssid);
1227 os_free((u8 *) params.extra_ies);
1228 os_free(params.freqs);
1229 return reply;
1234 * wpas_dbus_handler_disconnect - Terminate the current connection
1235 * @message: Pointer to incoming dbus message
1236 * @wpa_s: wpa_supplicant structure for a network interface
1237 * Returns: NotConnected DBus error message if already not connected
1238 * or NULL otherwise.
1240 * Handler function for "Disconnect" method call of network interface.
1242 DBusMessage * wpas_dbus_handler_disconnect(DBusMessage *message,
1243 struct wpa_supplicant *wpa_s)
1245 if (wpa_s->current_ssid != NULL) {
1246 wpa_s->disconnected = 1;
1247 wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1249 return NULL;
1252 return dbus_message_new_error(message, WPAS_DBUS_ERROR_NOT_CONNECTED,
1253 "This interface is not connected");
1258 * wpas_dbus_new_iface_add_network - Add a new configured network
1259 * @message: Pointer to incoming dbus message
1260 * @wpa_s: wpa_supplicant structure for a network interface
1261 * Returns: A dbus message containing the object path of the new network
1263 * Handler function for "AddNetwork" method call of a network interface.
1265 DBusMessage * wpas_dbus_handler_add_network(DBusMessage *message,
1266 struct wpa_supplicant *wpa_s)
1268 DBusMessage *reply = NULL;
1269 DBusMessageIter iter;
1270 struct wpa_ssid *ssid = NULL;
1271 char *path = NULL;
1273 path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1274 if (path == NULL) {
1275 perror("wpas_dbus_handler_add_network[dbus]: out of "
1276 "memory.");
1277 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1278 NULL);
1279 goto err;
1282 dbus_message_iter_init(message, &iter);
1284 ssid = wpa_config_add_network(wpa_s->conf);
1285 if (ssid == NULL) {
1286 wpa_printf(MSG_ERROR, "wpas_dbus_handler_add_network[dbus]: "
1287 "can't add new interface.");
1288 reply = wpas_dbus_error_unknown_error(
1289 message,
1290 "wpa_supplicant could not add "
1291 "a network on this interface.");
1292 goto err;
1294 wpas_notify_network_added(wpa_s, ssid);
1295 ssid->disabled = 1;
1296 wpa_config_set_network_defaults(ssid);
1298 reply = set_network_properties(message, ssid, &iter);
1299 if (reply) {
1300 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_add_network[dbus]:"
1301 "control interface couldn't set network "
1302 "properties");
1303 goto err;
1306 /* Construct the object path for this network. */
1307 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
1308 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
1309 wpas_dbus_get_path(wpa_s),
1310 ssid->id);
1312 reply = dbus_message_new_method_return(message);
1313 if (reply == NULL) {
1314 perror("wpas_dbus_handler_add_network[dbus]: out of memory "
1315 "when creating reply");
1316 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1317 NULL);
1318 goto err;
1320 if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
1321 DBUS_TYPE_INVALID)) {
1322 perror("wpas_dbus_handler_add_network[dbus]: out of memory "
1323 "when appending argument to reply");
1324 dbus_message_unref(reply);
1325 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1326 NULL);
1327 goto err;
1330 os_free(path);
1331 return reply;
1333 err:
1334 if (ssid) {
1335 wpas_notify_network_removed(wpa_s, ssid);
1336 wpa_config_remove_network(wpa_s->conf, ssid->id);
1338 os_free(path);
1339 return reply;
1344 * wpas_dbus_handler_remove_network - Remove a configured network
1345 * @message: Pointer to incoming dbus message
1346 * @wpa_s: wpa_supplicant structure for a network interface
1347 * Returns: NULL on success or dbus error on failure
1349 * Handler function for "RemoveNetwork" method call of a network interface.
1351 DBusMessage * wpas_dbus_handler_remove_network(DBusMessage *message,
1352 struct wpa_supplicant *wpa_s)
1354 DBusMessage *reply = NULL;
1355 const char *op;
1356 char *iface = NULL, *net_id = NULL;
1357 int id;
1358 struct wpa_ssid *ssid;
1360 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
1361 DBUS_TYPE_INVALID);
1363 /* Extract the network ID and ensure the network */
1364 /* is actually a child of this interface */
1365 iface = wpas_dbus_new_decompose_object_path(op, &net_id, NULL);
1366 if (iface == NULL || strcmp(iface, wpas_dbus_get_path(wpa_s)) != 0) {
1367 reply = wpas_dbus_error_invald_args(message, op);
1368 goto out;
1371 id = strtoul(net_id, NULL, 10);
1372 if (errno == EINVAL) {
1373 reply = wpas_dbus_error_invald_args(message, op);
1374 goto out;
1377 ssid = wpa_config_get_network(wpa_s->conf, id);
1378 if (ssid == NULL) {
1379 reply = wpas_dbus_error_network_unknown(message);
1380 goto out;
1383 wpas_notify_network_removed(wpa_s, ssid);
1385 if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
1386 wpa_printf(MSG_ERROR,
1387 "wpas_dbus_handler_remove_network[dbus]: "
1388 "error occurred when removing network %d", id);
1389 reply = wpas_dbus_error_unknown_error(
1390 message, "error removing the specified network on "
1391 "this interface.");
1392 goto out;
1395 if (ssid == wpa_s->current_ssid)
1396 wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1398 out:
1399 os_free(iface);
1400 os_free(net_id);
1401 return reply;
1406 * wpas_dbus_handler_select_network - Attempt association with a network
1407 * @message: Pointer to incoming dbus message
1408 * @wpa_s: wpa_supplicant structure for a network interface
1409 * Returns: NULL on success or dbus error on failure
1411 * Handler function for "SelectNetwork" method call of network interface.
1413 DBusMessage * wpas_dbus_handler_select_network(DBusMessage *message,
1414 struct wpa_supplicant *wpa_s)
1416 DBusMessage *reply = NULL;
1417 const char *op;
1418 char *iface = NULL, *net_id = NULL;
1419 int id;
1420 struct wpa_ssid *ssid;
1422 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
1423 DBUS_TYPE_INVALID);
1425 /* Extract the network ID and ensure the network */
1426 /* is actually a child of this interface */
1427 iface = wpas_dbus_new_decompose_object_path(op, &net_id, NULL);
1428 if (iface == NULL || strcmp(iface, wpas_dbus_get_path(wpa_s)) != 0) {
1429 reply = wpas_dbus_error_invald_args(message, op);
1430 goto out;
1433 id = strtoul(net_id, NULL, 10);
1434 if (errno == EINVAL) {
1435 reply = wpas_dbus_error_invald_args(message, op);
1436 goto out;
1439 ssid = wpa_config_get_network(wpa_s->conf, id);
1440 if (ssid == NULL) {
1441 reply = wpas_dbus_error_network_unknown(message);
1442 goto out;
1445 /* Finally, associate with the network */
1446 wpa_supplicant_select_network(wpa_s, ssid);
1448 out:
1449 os_free(iface);
1450 os_free(net_id);
1451 return reply;
1456 * wpas_dbus_handler_add_blob - Store named binary blob (ie, for certificates)
1457 * @message: Pointer to incoming dbus message
1458 * @wpa_s: %wpa_supplicant data structure
1459 * Returns: A dbus message containing an error on failure or NULL on success
1461 * Asks wpa_supplicant to internally store a binary blobs.
1463 DBusMessage * wpas_dbus_handler_add_blob(DBusMessage *message,
1464 struct wpa_supplicant *wpa_s)
1466 DBusMessage *reply = NULL;
1467 DBusMessageIter iter, array_iter;
1469 char *blob_name;
1470 u8 *blob_data;
1471 int blob_len;
1472 struct wpa_config_blob *blob = NULL;
1474 dbus_message_iter_init(message, &iter);
1475 dbus_message_iter_get_basic(&iter, &blob_name);
1477 if (wpa_config_get_blob(wpa_s->conf, blob_name)) {
1478 return dbus_message_new_error(message,
1479 WPAS_DBUS_ERROR_BLOB_EXISTS,
1480 NULL);
1483 dbus_message_iter_next(&iter);
1484 dbus_message_iter_recurse(&iter, &array_iter);
1486 dbus_message_iter_get_fixed_array(&array_iter, &blob_data, &blob_len);
1488 blob = os_zalloc(sizeof(*blob));
1489 if (!blob) {
1490 perror("wpas_dbus_handler_add_blob[dbus] out of memory when "
1491 "trying to allocate blob struct");
1492 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1493 NULL);
1494 goto err;
1497 blob->data = os_malloc(blob_len);
1498 if (!blob->data) {
1499 perror("wpas_dbus_handler_add_blob[dbus] out of memory when "
1500 "trying to allocate blob data");
1501 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1502 NULL);
1503 goto err;
1505 os_memcpy(blob->data, blob_data, blob_len);
1507 blob->len = blob_len;
1508 blob->name = os_strdup(blob_name);
1509 if (!blob->name) {
1510 perror("wpas_dbus_handler_add_blob[dbus] out of memory when "
1511 "trying to copy blob name");
1512 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1513 NULL);
1514 goto err;
1517 wpa_config_set_blob(wpa_s->conf, blob);
1518 wpas_notify_blob_added(wpa_s, blob->name);
1520 return reply;
1522 err:
1523 if (blob) {
1524 os_free(blob->name);
1525 os_free(blob->data);
1526 os_free(blob);
1528 return reply;
1533 * wpas_dbus_handler_get_blob - Get named binary blob (ie, for certificates)
1534 * @message: Pointer to incoming dbus message
1535 * @wpa_s: %wpa_supplicant data structure
1536 * Returns: A dbus message containing array of bytes (blob)
1538 * Gets one wpa_supplicant's binary blobs.
1540 DBusMessage * wpas_dbus_handler_get_blob(DBusMessage *message,
1541 struct wpa_supplicant *wpa_s)
1543 DBusMessage *reply = NULL;
1544 DBusMessageIter iter, array_iter;
1546 char *blob_name;
1547 const struct wpa_config_blob *blob;
1549 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &blob_name,
1550 DBUS_TYPE_INVALID);
1552 blob = wpa_config_get_blob(wpa_s->conf, blob_name);
1553 if (!blob) {
1554 return dbus_message_new_error(message,
1555 WPAS_DBUS_ERROR_BLOB_UNKNOWN,
1556 "Blob id not set");
1559 reply = dbus_message_new_method_return(message);
1560 if (!reply) {
1561 perror("wpas_dbus_handler_get_blob[dbus] out of memory when "
1562 "trying to allocate return message");
1563 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1564 NULL);
1565 goto out;
1568 dbus_message_iter_init_append(reply, &iter);
1570 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
1571 DBUS_TYPE_BYTE_AS_STRING,
1572 &array_iter)) {
1573 dbus_message_unref(reply);
1574 perror("wpas_dbus_handler_get_blob[dbus] out of memory when "
1575 "trying to open array");
1576 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1577 NULL);
1578 goto out;
1581 if (!dbus_message_iter_append_fixed_array(&array_iter, DBUS_TYPE_BYTE,
1582 &(blob->data), blob->len)) {
1583 dbus_message_unref(reply);
1584 perror("wpas_dbus_handler_get_blob[dbus] out of memory when "
1585 "trying to append data to array");
1586 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1587 NULL);
1588 goto out;
1591 if (!dbus_message_iter_close_container(&iter, &array_iter)) {
1592 dbus_message_unref(reply);
1593 perror("wpas_dbus_handler_get_blob[dbus] out of memory when "
1594 "trying to close array");
1595 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1596 NULL);
1597 goto out;
1600 out:
1601 return reply;
1606 * wpas_remove_handler_remove_blob - Remove named binary blob
1607 * @message: Pointer to incoming dbus message
1608 * @wpa_s: %wpa_supplicant data structure
1609 * Returns: NULL on success or dbus error
1611 * Asks wpa_supplicant to internally remove a binary blobs.
1613 DBusMessage * wpas_dbus_handler_remove_blob(DBusMessage *message,
1614 struct wpa_supplicant *wpa_s)
1616 DBusMessage *reply = NULL;
1617 char *blob_name;
1619 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &blob_name,
1620 DBUS_TYPE_INVALID);
1622 if (wpa_config_remove_blob(wpa_s->conf, blob_name)) {
1623 return dbus_message_new_error(message,
1624 WPAS_DBUS_ERROR_BLOB_UNKNOWN,
1625 "Blob id not set");
1627 wpas_notify_blob_removed(wpa_s, blob_name);
1629 return reply;
1635 * wpas_dbus_getter_capabilities - Return interface capabilities
1636 * @message: Pointer to incoming dbus message
1637 * @wpa_s: wpa_supplicant structure for a network interface
1638 * Returns: A dbus message containing a dict of strings
1640 * Getter for "Capabilities" property of an interface.
1642 DBusMessage * wpas_dbus_getter_capabilities(DBusMessage *message,
1643 struct wpa_supplicant *wpa_s)
1645 DBusMessage *reply = NULL;
1646 struct wpa_driver_capa capa;
1647 int res;
1648 DBusMessageIter iter, iter_dict;
1649 DBusMessageIter iter_dict_entry, iter_dict_val, iter_array,
1650 variant_iter;
1651 const char *scans[] = { "active", "passive", "ssid" };
1652 const char *modes[] = { "infrastructure", "ad-hoc", "ap" };
1653 int n = sizeof(modes) / sizeof(char *);
1655 if (message == NULL)
1656 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
1657 else
1658 reply = dbus_message_new_method_return(message);
1659 if (!reply)
1660 goto nomem;
1662 dbus_message_iter_init_append(reply, &iter);
1663 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
1664 "a{sv}", &variant_iter))
1665 goto nomem;
1667 if (!wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
1668 goto nomem;
1670 res = wpa_drv_get_capa(wpa_s, &capa);
1672 /***** pairwise cipher */
1673 if (res < 0) {
1674 const char *args[] = {"ccmp", "tkip", "none"};
1675 if (!wpa_dbus_dict_append_string_array(
1676 &iter_dict, "Pairwise", args,
1677 sizeof(args) / sizeof(char*)))
1678 goto nomem;
1679 } else {
1680 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Pairwise",
1681 &iter_dict_entry,
1682 &iter_dict_val,
1683 &iter_array))
1684 goto nomem;
1686 if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
1687 if (!wpa_dbus_dict_string_array_add_element(
1688 &iter_array, "ccmp"))
1689 goto nomem;
1692 if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
1693 if (!wpa_dbus_dict_string_array_add_element(
1694 &iter_array, "tkip"))
1695 goto nomem;
1698 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
1699 if (!wpa_dbus_dict_string_array_add_element(
1700 &iter_array, "none"))
1701 goto nomem;
1704 if (!wpa_dbus_dict_end_string_array(&iter_dict,
1705 &iter_dict_entry,
1706 &iter_dict_val,
1707 &iter_array))
1708 goto nomem;
1711 /***** group cipher */
1712 if (res < 0) {
1713 const char *args[] = {
1714 "ccmp", "tkip", "wep104", "wep40"
1716 if (!wpa_dbus_dict_append_string_array(
1717 &iter_dict, "Group", args,
1718 sizeof(args) / sizeof(char*)))
1719 goto nomem;
1720 } else {
1721 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Group",
1722 &iter_dict_entry,
1723 &iter_dict_val,
1724 &iter_array))
1725 goto nomem;
1727 if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
1728 if (!wpa_dbus_dict_string_array_add_element(
1729 &iter_array, "ccmp"))
1730 goto nomem;
1733 if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
1734 if (!wpa_dbus_dict_string_array_add_element(
1735 &iter_array, "tkip"))
1736 goto nomem;
1739 if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) {
1740 if (!wpa_dbus_dict_string_array_add_element(
1741 &iter_array, "wep104"))
1742 goto nomem;
1745 if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) {
1746 if (!wpa_dbus_dict_string_array_add_element(
1747 &iter_array, "wep40"))
1748 goto nomem;
1751 if (!wpa_dbus_dict_end_string_array(&iter_dict,
1752 &iter_dict_entry,
1753 &iter_dict_val,
1754 &iter_array))
1755 goto nomem;
1758 /***** key management */
1759 if (res < 0) {
1760 const char *args[] = {
1761 "wpa-psk", "wpa-eap", "ieee8021x", "wpa-none",
1762 #ifdef CONFIG_WPS
1763 "wps",
1764 #endif /* CONFIG_WPS */
1765 "none"
1767 if (!wpa_dbus_dict_append_string_array(
1768 &iter_dict, "KeyMgmt", args,
1769 sizeof(args) / sizeof(char*)))
1770 goto nomem;
1771 } else {
1772 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "KeyMgmt",
1773 &iter_dict_entry,
1774 &iter_dict_val,
1775 &iter_array))
1776 goto nomem;
1778 if (!wpa_dbus_dict_string_array_add_element(&iter_array,
1779 "none"))
1780 goto nomem;
1782 if (!wpa_dbus_dict_string_array_add_element(&iter_array,
1783 "ieee8021x"))
1784 goto nomem;
1786 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
1787 WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
1788 if (!wpa_dbus_dict_string_array_add_element(
1789 &iter_array, "wpa-eap"))
1790 goto nomem;
1793 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
1794 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
1795 if (!wpa_dbus_dict_string_array_add_element(
1796 &iter_array, "wpa-psk"))
1797 goto nomem;
1800 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
1801 if (!wpa_dbus_dict_string_array_add_element(
1802 &iter_array, "wpa-none"))
1803 goto nomem;
1807 #ifdef CONFIG_WPS
1808 if (!wpa_dbus_dict_string_array_add_element(&iter_array,
1809 "wps"))
1810 goto nomem;
1811 #endif /* CONFIG_WPS */
1813 if (!wpa_dbus_dict_end_string_array(&iter_dict,
1814 &iter_dict_entry,
1815 &iter_dict_val,
1816 &iter_array))
1817 goto nomem;
1820 /***** WPA protocol */
1821 if (res < 0) {
1822 const char *args[] = { "rsn", "wpa" };
1823 if (!wpa_dbus_dict_append_string_array(
1824 &iter_dict, "Protocol", args,
1825 sizeof(args) / sizeof(char*)))
1826 goto nomem;
1827 } else {
1828 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Protocol",
1829 &iter_dict_entry,
1830 &iter_dict_val,
1831 &iter_array))
1832 goto nomem;
1834 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
1835 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
1836 if (!wpa_dbus_dict_string_array_add_element(
1837 &iter_array, "rsn"))
1838 goto nomem;
1841 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
1842 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
1843 if (!wpa_dbus_dict_string_array_add_element(
1844 &iter_array, "wpa"))
1845 goto nomem;
1848 if (!wpa_dbus_dict_end_string_array(&iter_dict,
1849 &iter_dict_entry,
1850 &iter_dict_val,
1851 &iter_array))
1852 goto nomem;
1855 /***** auth alg */
1856 if (res < 0) {
1857 const char *args[] = { "open", "shared", "leap" };
1858 if (!wpa_dbus_dict_append_string_array(
1859 &iter_dict, "AuthAlg", args,
1860 sizeof(args) / sizeof(char*)))
1861 goto nomem;
1862 } else {
1863 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "AuthAlg",
1864 &iter_dict_entry,
1865 &iter_dict_val,
1866 &iter_array))
1867 goto nomem;
1869 if (capa.auth & (WPA_DRIVER_AUTH_OPEN)) {
1870 if (!wpa_dbus_dict_string_array_add_element(
1871 &iter_array, "open"))
1872 goto nomem;
1875 if (capa.auth & (WPA_DRIVER_AUTH_SHARED)) {
1876 if (!wpa_dbus_dict_string_array_add_element(
1877 &iter_array, "shared"))
1878 goto nomem;
1881 if (capa.auth & (WPA_DRIVER_AUTH_LEAP)) {
1882 if (!wpa_dbus_dict_string_array_add_element(
1883 &iter_array, "leap"))
1884 goto nomem;
1887 if (!wpa_dbus_dict_end_string_array(&iter_dict,
1888 &iter_dict_entry,
1889 &iter_dict_val,
1890 &iter_array))
1891 goto nomem;
1894 /***** Scan */
1895 if (!wpa_dbus_dict_append_string_array(&iter_dict, "Scan", scans,
1896 sizeof(scans) / sizeof(char *)))
1897 goto nomem;
1899 /***** Modes */
1900 if (res < 0 || !(capa.flags & WPA_DRIVER_FLAGS_AP))
1901 n--; /* exclude ap mode if it is not supported by the driver */
1902 if (!wpa_dbus_dict_append_string_array(&iter_dict, "Modes", modes, n))
1903 goto nomem;
1905 if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict))
1906 goto nomem;
1907 if (!dbus_message_iter_close_container(&iter, &variant_iter))
1908 goto nomem;
1910 return reply;
1912 nomem:
1913 if (reply)
1914 dbus_message_unref(reply);
1916 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, NULL);
1921 * wpas_dbus_getter_state - Get interface state
1922 * @message: Pointer to incoming dbus message
1923 * @wpa_s: wpa_supplicant structure for a network interface
1924 * Returns: A dbus message containing a STRING representing the current
1925 * interface state
1927 * Getter for "State" property.
1929 DBusMessage * wpas_dbus_getter_state(DBusMessage *message,
1930 struct wpa_supplicant *wpa_s)
1932 DBusMessage *reply = NULL;
1933 DBusMessageIter iter, variant_iter;
1934 const char *str_state;
1935 char *state_ls, *tmp;
1937 if (message == NULL)
1938 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
1939 else
1940 reply = dbus_message_new_method_return(message);
1941 if (reply != NULL) {
1942 dbus_message_iter_init_append(reply, &iter);
1943 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
1944 "s", &variant_iter)) {
1945 perror("wpas_dbus_getter_state[dbus] out of memory "
1946 "when trying to open variant");
1947 dbus_message_unref(reply);
1948 reply = dbus_message_new_error(message,
1949 DBUS_ERROR_NO_MEMORY,
1950 NULL);
1951 goto out;
1954 str_state = wpa_supplicant_state_txt(wpa_s->wpa_state);
1956 /* make state string lowercase to fit new DBus API convention
1958 state_ls = tmp = os_strdup(str_state);
1959 if (!tmp) {
1960 perror("wpas_dbus_getter_state[dbus] out of memory "
1961 "when trying read state");
1962 dbus_message_unref(reply);
1963 reply = dbus_message_new_error(message,
1964 DBUS_ERROR_NO_MEMORY,
1965 NULL);
1966 goto out;
1968 while (*tmp) {
1969 *tmp = tolower(*tmp);
1970 tmp++;
1973 if (!dbus_message_iter_append_basic(&variant_iter,
1974 DBUS_TYPE_STRING,
1975 &state_ls)) {
1976 perror("wpas_dbus_getter_state[dbus] out of memory "
1977 "when trying append state");
1978 dbus_message_unref(reply);
1979 reply = dbus_message_new_error(message,
1980 DBUS_ERROR_NO_MEMORY,
1981 NULL);
1982 goto err;
1984 if (!dbus_message_iter_close_container(&iter, &variant_iter)) {
1985 perror("wpas_dbus_getter_state[dbus] out of memory "
1986 "when trying close variant");
1987 dbus_message_unref(reply);
1988 reply = dbus_message_new_error(message,
1989 DBUS_ERROR_NO_MEMORY,
1990 NULL);
1991 goto err;
1993 err:
1994 os_free(state_ls);
1997 out:
1998 return reply;
2002 * wpas_dbus_new_iface_get_scanning - Get interface scanning state
2003 * @message: Pointer to incoming dbus message
2004 * @wpa_s: wpa_supplicant structure for a network interface
2005 * Returns: A dbus message containing whether the interface is scanning
2007 * Getter for "scanning" property.
2009 DBusMessage * wpas_dbus_getter_scanning(DBusMessage *message,
2010 struct wpa_supplicant *wpa_s)
2012 DBusMessage *reply = NULL;
2013 DBusMessageIter iter, variant_iter;
2014 dbus_bool_t scanning = wpa_s->scanning ? TRUE : FALSE;
2016 if (message == NULL)
2017 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
2018 else
2019 reply = dbus_message_new_method_return(message);
2021 if (reply != NULL) {
2022 dbus_message_iter_init_append(reply, &iter);
2023 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
2024 "b", &variant_iter) ||
2025 !dbus_message_iter_append_basic(&variant_iter,
2026 DBUS_TYPE_BOOLEAN,
2027 &scanning) ||
2028 !dbus_message_iter_close_container(&iter, &variant_iter)) {
2029 perror("wpas_dbus_getter_scanning[dbus]: out of "
2030 "memory to put scanning state into message.");
2031 dbus_message_unref(reply);
2032 reply = dbus_message_new_error(message,
2033 DBUS_ERROR_NO_MEMORY,
2034 NULL);
2036 } else {
2037 perror("wpas_dbus_getter_scanning[dbus]: out of "
2038 "memory to return scanning state.");
2039 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2040 NULL);
2043 return reply;
2048 * wpas_dbus_getter_ap_scan - Control roaming mode
2049 * @message: Pointer to incoming dbus message
2050 * @wpa_s: wpa_supplicant structure for a network interface
2051 * Returns: A message containong value of ap_scan variable
2053 * Getter function for "ApScan" property.
2055 DBusMessage * wpas_dbus_getter_ap_scan(DBusMessage *message,
2056 struct wpa_supplicant *wpa_s)
2058 DBusMessage *reply = NULL;
2059 DBusMessageIter iter, variant_iter;
2060 dbus_uint32_t ap_scan = wpa_s->conf->ap_scan;
2062 if (message == NULL)
2063 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
2064 else
2065 reply = dbus_message_new_method_return(message);
2067 if (reply != NULL) {
2068 dbus_message_iter_init_append(reply, &iter);
2069 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
2070 "u", &variant_iter) ||
2071 !dbus_message_iter_append_basic(&variant_iter,
2072 DBUS_TYPE_UINT32,
2073 &ap_scan) ||
2074 !dbus_message_iter_close_container(&iter, &variant_iter)) {
2075 perror("wpas_dbus_getter_ap_scan[dbus]: out of "
2076 "memory to put scanning state into message.");
2077 dbus_message_unref(reply);
2078 reply = dbus_message_new_error(message,
2079 DBUS_ERROR_NO_MEMORY,
2080 NULL);
2082 } else {
2083 perror("wpas_dbus_getter_ap_scan[dbus]: out of "
2084 "memory to return scanning state.");
2085 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2086 NULL);
2089 return reply;
2094 * wpas_dbus_setter_ap_scan - Control roaming mode
2095 * @message: Pointer to incoming dbus message
2096 * @wpa_s: wpa_supplicant structure for a network interface
2097 * Returns: NULL
2099 * Setter function for "ApScan" property.
2101 DBusMessage * wpas_dbus_setter_ap_scan(DBusMessage *message,
2102 struct wpa_supplicant *wpa_s)
2104 DBusMessage *reply = NULL;
2105 DBusMessageIter iter, variant_iter;
2106 dbus_uint32_t ap_scan;
2108 if (!dbus_message_iter_init(message, &iter)) {
2109 perror("wpas_dbus_getter_ap_scan[dbus]: out of "
2110 "memory to return scanning state.");
2111 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2112 NULL);
2113 goto out;
2116 /* omit first and second argument and get value from third*/
2117 dbus_message_iter_next(&iter);
2118 dbus_message_iter_next(&iter);
2119 dbus_message_iter_recurse(&iter, &variant_iter);
2121 if (dbus_message_iter_get_arg_type(&variant_iter) != DBUS_TYPE_UINT32)
2123 reply = wpas_dbus_error_invald_args(message,
2124 "UINT32 required");
2125 goto out;
2127 dbus_message_iter_get_basic(&variant_iter, &ap_scan);
2129 if (wpa_supplicant_set_ap_scan(wpa_s, ap_scan)) {
2130 reply = wpas_dbus_error_invald_args(
2131 message,
2132 "ap_scan must equal 0, 1 or 2");
2133 goto out;
2136 out:
2137 return reply;
2142 * wpas_dbus_getter_ifname - Get interface name
2143 * @message: Pointer to incoming dbus message
2144 * @wpa_s: wpa_supplicant structure for a network interface
2145 * Returns: A dbus message containing a name of network interface
2146 * associated with with wpa_s
2148 * Getter for "Ifname" property.
2150 DBusMessage * wpas_dbus_getter_ifname(DBusMessage *message,
2151 struct wpa_supplicant *wpa_s)
2153 DBusMessage *reply = NULL;
2154 DBusMessageIter iter, variant_iter;
2155 const char *ifname = NULL;
2157 ifname = wpa_s->ifname;
2158 if (ifname == NULL) {
2159 wpa_printf(MSG_DEBUG, "wpas_dbus_getter_ifname[dbus]: "
2160 "wpa_s has no interface name set"");");
2161 return wpas_dbus_error_unknown_error(message,
2162 "ifname not set");
2165 if (message == NULL)
2166 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
2167 else
2168 reply = dbus_message_new_method_return(message);
2170 if (reply != NULL) {
2171 dbus_message_iter_init_append(reply, &iter);
2172 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
2173 "s", &variant_iter) ||
2174 !dbus_message_iter_append_basic(&variant_iter,
2175 DBUS_TYPE_STRING,
2176 &ifname) ||
2177 !dbus_message_iter_close_container(&iter, &variant_iter)) {
2178 perror("wpas_dbus_getter_ifname[dbus]: out of "
2179 "memory to put ifname into message.");
2180 dbus_message_unref(reply);
2181 reply = dbus_message_new_error(message,
2182 DBUS_ERROR_NO_MEMORY,
2183 NULL);
2185 } else {
2186 perror("wpas_dbus_getter_ifname[dbus]: out of "
2187 "memory to return ifname state.");
2188 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2189 NULL);
2192 return reply;
2197 * wpas_dbus_getter_driver - Get interface name
2198 * @message: Pointer to incoming dbus message
2199 * @wpa_s: wpa_supplicant structure for a network interface
2200 * Returns: A dbus message containing a name of network interface
2201 * driver associated with with wpa_s
2203 * Getter for "Driver" property.
2205 DBusMessage * wpas_dbus_getter_driver(DBusMessage *message,
2206 struct wpa_supplicant *wpa_s)
2208 DBusMessage *reply = NULL;
2209 DBusMessageIter iter, variant_iter;
2210 const char *driver = NULL;
2212 if (wpa_s->driver == NULL || wpa_s->driver->name == NULL) {
2213 wpa_printf(MSG_DEBUG, "wpas_dbus_getter_driver[dbus]: "
2214 "wpa_s has no driver set"");");
2215 return wpas_dbus_error_unknown_error(message, NULL);
2218 driver = wpa_s->driver->name;
2220 if (message == NULL)
2221 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
2222 else
2223 reply = dbus_message_new_method_return(message);
2225 if (reply != NULL) {
2226 dbus_message_iter_init_append(reply, &iter);
2227 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
2228 "s", &variant_iter) ||
2229 !dbus_message_iter_append_basic(&variant_iter,
2230 DBUS_TYPE_STRING,
2231 &driver) ||
2232 !dbus_message_iter_close_container(&iter, &variant_iter)) {
2233 perror("wpas_dbus_getter_driver[dbus]: out of "
2234 "memory to put driver into message.");
2235 dbus_message_unref(reply);
2236 reply = dbus_message_new_error(message,
2237 DBUS_ERROR_NO_MEMORY,
2238 NULL);
2240 } else {
2241 perror("wpas_dbus_getter_driver[dbus]: out of "
2242 "memory to return driver.");
2243 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2244 NULL);
2247 return reply;
2252 * wpas_dbus_getter_current_bss - Get current bss object path
2253 * @message: Pointer to incoming dbus message
2254 * @wpa_s: wpa_supplicant structure for a network interface
2255 * Returns: A dbus message containing a DBus object path to
2256 * current BSS
2258 * Getter for "CurrentBSS" property.
2260 DBusMessage * wpas_dbus_getter_current_bss(DBusMessage *message,
2261 struct wpa_supplicant *wpa_s)
2263 DBusMessage *reply = NULL;
2264 DBusMessageIter iter, variant_iter;
2265 const char *path = wpas_dbus_get_path(wpa_s);
2266 char *bss_obj_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
2267 struct wpa_bss *bss = NULL;
2269 if (bss_obj_path == NULL) {
2270 perror("wpas_dbus_getter_current_bss[dbus]: out of "
2271 "memory to allocate result argument.");
2272 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2273 NULL);
2276 /* TODO: store current BSS or BSS id in wpa_s */
2277 if (!is_zero_ether_addr(wpa_s->bssid))
2278 bss = wpa_bss_get_bssid(wpa_s, wpa_s->bssid);
2280 if (bss)
2281 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2282 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
2283 path, bss->id);
2284 else
2285 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
2287 if (message == NULL)
2288 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
2289 else
2290 reply = dbus_message_new_method_return(message);
2292 if (reply != NULL) {
2293 dbus_message_iter_init_append(reply, &iter);
2294 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
2295 "o", &variant_iter) ||
2296 !dbus_message_iter_append_basic(&variant_iter,
2297 DBUS_TYPE_OBJECT_PATH,
2298 &bss_obj_path) ||
2299 !dbus_message_iter_close_container(&iter, &variant_iter)) {
2300 perror("wpas_dbus_getter_current_bss[dbus]: out of "
2301 "memory to put path into message.");
2302 dbus_message_unref(reply);
2303 reply = dbus_message_new_error(message,
2304 DBUS_ERROR_NO_MEMORY,
2305 NULL);
2307 } else {
2308 perror("wpas_dbus_getter_current_bss[dbus]: out of "
2309 "memory when creating reply.");
2310 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2311 NULL);
2314 os_free(bss_obj_path);
2315 return reply;
2320 * wpas_dbus_getter_current_network - Get current network object path
2321 * @message: Pointer to incoming dbus message
2322 * @wpa_s: wpa_supplicant structure for a network interface
2323 * Returns: A dbus message containing a DBus object path to
2324 * current network
2326 * Getter for "CurrentNetwork" property.
2328 DBusMessage * wpas_dbus_getter_current_network(DBusMessage *message,
2329 struct wpa_supplicant *wpa_s)
2331 DBusMessage *reply = NULL;
2332 DBusMessageIter iter, variant_iter;
2333 const char *path = wpas_dbus_get_path(wpa_s);
2334 char *net_obj_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
2336 if (net_obj_path == NULL) {
2337 perror("wpas_dbus_getter_current_network[dbus]: out of "
2338 "memory to allocate result argument.");
2339 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2340 NULL);
2343 if (wpa_s->current_ssid)
2344 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2345 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u", path,
2346 wpa_s->current_ssid->id);
2347 else
2348 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
2350 if (message == NULL)
2351 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
2352 else
2353 reply = dbus_message_new_method_return(message);
2355 if (reply != NULL) {
2356 dbus_message_iter_init_append(reply, &iter);
2357 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
2358 "o", &variant_iter) ||
2359 !dbus_message_iter_append_basic(&variant_iter,
2360 DBUS_TYPE_OBJECT_PATH,
2361 &net_obj_path) ||
2362 !dbus_message_iter_close_container(&iter, &variant_iter)) {
2363 perror("wpas_dbus_getter_current_network[dbus]: out "
2364 "of memory to put path into message.");
2365 dbus_message_unref(reply);
2366 reply = dbus_message_new_error(message,
2367 DBUS_ERROR_NO_MEMORY,
2368 NULL);
2370 } else {
2371 perror("wpas_dbus_getter_current_network[dbus]: out of "
2372 "memory when creating reply.");
2373 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2374 NULL);
2377 os_free(net_obj_path);
2378 return reply;
2383 * wpas_dbus_getter_bridge_ifname - Get interface name
2384 * @message: Pointer to incoming dbus message
2385 * @wpa_s: wpa_supplicant structure for a network interface
2386 * Returns: A dbus message containing a name of bridge network
2387 * interface associated with with wpa_s
2389 * Getter for "BridgeIfname" property.
2391 DBusMessage * wpas_dbus_getter_bridge_ifname(DBusMessage *message,
2392 struct wpa_supplicant *wpa_s)
2394 DBusMessage *reply = NULL;
2395 DBusMessageIter iter, variant_iter;
2396 const char *bridge_ifname = NULL;
2398 bridge_ifname = wpa_s->bridge_ifname;
2399 if (bridge_ifname == NULL) {
2400 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bridge_ifname[dbus]: "
2401 "wpa_s has no bridge interface name set"");");
2402 return wpas_dbus_error_unknown_error(message, NULL);
2405 if (message == NULL)
2406 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
2407 else
2408 reply = dbus_message_new_method_return(message);
2410 if (reply != NULL) {
2411 dbus_message_iter_init_append(reply, &iter);
2412 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
2413 "s", &variant_iter) ||
2414 !dbus_message_iter_append_basic(&variant_iter,
2415 DBUS_TYPE_STRING,
2416 &bridge_ifname) ||
2417 !dbus_message_iter_close_container(&iter, &variant_iter)) {
2418 perror("wpas_dbus_getter_bridge_ifname[dbus]: out of "
2419 "memory to put bridge ifname into message.");
2420 dbus_message_unref(reply);
2421 reply = dbus_message_new_error(message,
2422 DBUS_ERROR_NO_MEMORY,
2423 NULL);
2425 } else {
2426 perror("wpas_dbus_getter_bridge_ifname[dbus]: out of "
2427 "memory to return bridge ifname.");
2428 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2429 NULL);
2432 return reply;
2437 * wpas_dbus_getter_bsss - Get array of BSSs objects
2438 * @message: Pointer to incoming dbus message
2439 * @wpa_s: wpa_supplicant structure for a network interface
2440 * Returns: a dbus message containing an array of all known BSS objects
2441 * dbus paths
2443 * Getter for "BSSs" property.
2445 DBusMessage * wpas_dbus_getter_bsss(DBusMessage *message,
2446 struct wpa_supplicant *wpa_s)
2448 DBusMessage *reply = NULL;
2449 DBusMessageIter iter, variant_iter, array_iter;
2450 struct wpa_bss *bss;
2452 /* Create and initialize the return message */
2453 if (message == NULL)
2454 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
2455 else
2456 reply = dbus_message_new_method_return(message);
2457 if (reply == NULL) {
2458 perror("wpas_dbus_getter_bsss[dbus]: out of "
2459 "memory to create return message.");
2460 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2461 NULL);
2462 goto out;
2465 dbus_message_iter_init_append(reply, &iter);
2467 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
2468 "ao", &variant_iter) ||
2469 !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
2470 DBUS_TYPE_OBJECT_PATH_AS_STRING,
2471 &array_iter)) {
2472 perror("wpas_dbus_getter_bsss[dbus]: out of "
2473 "memory to open container.");
2474 dbus_message_unref(reply);
2475 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2476 NULL);
2477 goto out;
2480 /* Loop through scan results and append each result's object path */
2481 dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
2482 char *path;
2484 path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
2485 if (path == NULL) {
2486 perror("wpas_dbus_getter_bsss[dbus]: out of "
2487 "memory.");
2488 dbus_message_unref(reply);
2489 reply = dbus_message_new_error(message,
2490 DBUS_ERROR_NO_MEMORY,
2491 NULL);
2492 goto out;
2494 /* Construct the object path for this BSS. */
2495 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
2496 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
2497 wpas_dbus_get_path(wpa_s), bss->id);
2498 dbus_message_iter_append_basic(&array_iter,
2499 DBUS_TYPE_OBJECT_PATH, &path);
2500 os_free(path);
2503 if (!dbus_message_iter_close_container(&variant_iter, &array_iter) ||
2504 !dbus_message_iter_close_container(&iter, &variant_iter)) {
2505 perror("wpas_dbus_getter_bsss[dbus]: out of "
2506 "memory to close container.");
2507 dbus_message_unref(reply);
2508 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2509 NULL);
2510 goto out;
2513 out:
2514 return reply;
2519 * wpas_dbus_getter_networks - Get array of networks objects
2520 * @message: Pointer to incoming dbus message
2521 * @wpa_s: wpa_supplicant structure for a network interface
2522 * Returns: a dbus message containing an array of all configured
2523 * networks dbus object paths.
2525 * Getter for "Networks" property.
2527 DBusMessage * wpas_dbus_getter_networks(DBusMessage *message,
2528 struct wpa_supplicant *wpa_s)
2530 DBusMessage *reply = NULL;
2531 DBusMessageIter iter, variant_iter, array_iter;
2532 struct wpa_ssid *ssid;
2534 if (wpa_s->conf == NULL) {
2535 wpa_printf(MSG_ERROR, "wpas_dbus_getter_networks[dbus]: "
2536 "An error occurred getting networks list.");
2537 return wpas_dbus_error_unknown_error(message, NULL);
2540 /* Create and initialize the return message */
2541 if (message == NULL)
2542 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
2543 else
2544 reply = dbus_message_new_method_return(message);
2545 if (reply == NULL) {
2546 perror("wpas_dbus_getter_networks[dbus]: out of "
2547 "memory to create return message.");
2548 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2549 NULL);
2550 goto out;
2553 dbus_message_iter_init_append(reply, &iter);
2555 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
2556 "ao", &variant_iter) ||
2557 !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
2558 DBUS_TYPE_OBJECT_PATH_AS_STRING,
2559 &array_iter)) {
2560 perror("wpas_dbus_getter_networks[dbus]: out of "
2561 "memory to open container.");
2562 dbus_message_unref(reply);
2563 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2564 NULL);
2565 goto out;
2568 /* Loop through configured networks and append object path if each */
2569 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2570 char *path;
2572 path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
2573 if (path == NULL) {
2574 perror("wpas_dbus_getter_networks[dbus]: out of "
2575 "memory.");
2576 dbus_message_unref(reply);
2577 reply = dbus_message_new_error(message,
2578 DBUS_ERROR_NO_MEMORY,
2579 NULL);
2580 goto out;
2583 /* Construct the object path for this network. */
2584 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
2585 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
2586 wpas_dbus_get_path(wpa_s), ssid->id);
2587 dbus_message_iter_append_basic(&array_iter,
2588 DBUS_TYPE_OBJECT_PATH, &path);
2589 os_free(path);
2592 if (!dbus_message_iter_close_container(&variant_iter, &array_iter) ||
2593 !dbus_message_iter_close_container(&iter, &variant_iter)) {
2594 perror("wpas_dbus_getter_networks[dbus]: out of "
2595 "memory to close container.");
2596 dbus_message_unref(reply);
2597 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2598 NULL);
2599 goto out;
2602 out:
2603 return reply;
2608 * wpas_dbus_getter_blobs - Get all blobs defined for this interface
2609 * @message: Pointer to incoming dbus message
2610 * @wpa_s: wpa_supplicant structure for a network interface
2611 * Returns: a dbus message containing a dictionary of pairs (blob_name, blob)
2613 * Getter for "Blobs" property.
2615 DBusMessage * wpas_dbus_getter_blobs(DBusMessage *message,
2616 struct wpa_supplicant *wpa_s)
2618 DBusMessage *reply = NULL;
2619 DBusMessageIter iter, variant_iter, dict_iter, entry_iter, array_iter;
2620 struct wpa_config_blob *blob;
2622 if (message == NULL)
2623 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
2624 else
2625 reply = dbus_message_new_method_return(message);
2626 if (!reply) {
2627 perror("wpas_dbus_getter_blobs[dbus] out of memory when "
2628 "trying to initialize return message");
2629 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2630 NULL);
2631 goto out;
2634 dbus_message_iter_init_append(reply, &iter);
2636 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
2637 "a{say}", &variant_iter)) {
2638 dbus_message_unref(reply);
2639 perror("wpas_dbus_getter_blobs[dbus] out of memory when "
2640 "trying to open variant");
2641 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2642 NULL);
2643 goto out;
2646 if (!dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
2647 "{say}", &dict_iter)) {
2648 dbus_message_unref(reply);
2649 perror("wpas_dbus_getter_blobs[dbus] out of memory when "
2650 "trying to open dictionary");
2651 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2652 NULL);
2653 goto out;
2656 blob = wpa_s->conf->blobs;
2657 while (blob) {
2658 if (!dbus_message_iter_open_container(&dict_iter,
2659 DBUS_TYPE_DICT_ENTRY,
2660 NULL, &entry_iter)) {
2661 dbus_message_unref(reply);
2662 perror("wpas_dbus_getter_blobs[dbus] out of memory "
2663 "when trying to open entry");
2664 reply = dbus_message_new_error(message,
2665 DBUS_ERROR_NO_MEMORY,
2666 NULL);
2667 goto out;
2670 if (!dbus_message_iter_append_basic(&entry_iter,
2671 DBUS_TYPE_STRING,
2672 &(blob->name))) {
2673 dbus_message_unref(reply);
2674 perror("wpas_dbus_getter_blobs[dbus] out of memory "
2675 "when trying to append blob name");
2676 reply = dbus_message_new_error(message,
2677 DBUS_ERROR_NO_MEMORY,
2678 NULL);
2679 goto out;
2682 if (!dbus_message_iter_open_container(&entry_iter,
2683 DBUS_TYPE_ARRAY,
2684 DBUS_TYPE_BYTE_AS_STRING,
2685 &array_iter)) {
2686 dbus_message_unref(reply);
2687 perror("wpas_dbus_getter_blobs[dbus] out of memory "
2688 "when trying to open array");
2689 reply = dbus_message_new_error(message,
2690 DBUS_ERROR_NO_MEMORY,
2691 NULL);
2692 goto out;
2695 if (!dbus_message_iter_append_fixed_array(&array_iter,
2696 DBUS_TYPE_BYTE,
2697 &(blob->data),
2698 blob->len)) {
2699 dbus_message_unref(reply);
2700 perror("wpas_dbus_getter_blobs[dbus] out of memory "
2701 "when trying to append blob data");
2702 reply = dbus_message_new_error(message,
2703 DBUS_ERROR_NO_MEMORY,
2704 NULL);
2705 goto out;
2708 if (!dbus_message_iter_close_container(&entry_iter,
2709 &array_iter)) {
2710 dbus_message_unref(reply);
2711 perror("wpas_dbus_getter_blobs[dbus] out of memory "
2712 "when trying to close array");
2713 reply = dbus_message_new_error(message,
2714 DBUS_ERROR_NO_MEMORY,
2715 NULL);
2716 goto out;
2719 if (!dbus_message_iter_close_container(&dict_iter,
2720 &entry_iter)) {
2721 dbus_message_unref(reply);
2722 perror("wpas_dbus_getter_blobs[dbus] out of memory "
2723 "when trying to close entry");
2724 reply = dbus_message_new_error(message,
2725 DBUS_ERROR_NO_MEMORY,
2726 NULL);
2727 goto out;
2730 blob = blob->next;
2733 if (!dbus_message_iter_close_container(&variant_iter, &dict_iter)) {
2734 dbus_message_unref(reply);
2735 perror("wpas_dbus_getter_blobs[dbus] out of memory when "
2736 "trying to close dictionary");
2737 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2738 NULL);
2739 goto out;
2742 if (!dbus_message_iter_close_container(&iter, &variant_iter)) {
2743 dbus_message_unref(reply);
2744 perror("wpas_dbus_getter_blobs[dbus] out of memory when "
2745 "trying to close variant");
2746 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2747 NULL);
2748 goto out;
2751 out:
2752 return reply;
2757 * wpas_dbus_getter_bss_properties - Return the properties of a scanned bss
2758 * @message: Pointer to incoming dbus message
2759 * @bss: a pair of interface describing structure and bss' bssid
2760 * Returns: a dbus message containing the properties for the requested bss
2762 * Getter for "Properties" property.
2764 DBusMessage * wpas_dbus_getter_bss_properties(DBusMessage *message,
2765 struct bss_handler_args *bss)
2767 DBusMessage *reply = NULL;
2768 DBusMessageIter iter, iter_dict, variant_iter;
2769 const u8 *ie;
2770 struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id);
2772 if (res == NULL)
2773 return NULL;
2775 /* Dump the properties into a dbus message */
2776 if (message == NULL)
2777 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
2778 else
2779 reply = dbus_message_new_method_return(message);
2781 if (!reply)
2782 goto error;
2784 dbus_message_iter_init_append(reply, &iter);
2786 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
2787 "a{sv}", &variant_iter))
2788 goto error;
2790 if (!wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
2791 goto error;
2793 if (!wpa_dbus_dict_append_byte_array(&iter_dict, "BSSID",
2794 (const char *) res->bssid,
2795 ETH_ALEN))
2796 goto error;
2798 ie = wpa_bss_get_ie(res, WLAN_EID_SSID);
2799 if (ie) {
2800 if (!wpa_dbus_dict_append_byte_array(&iter_dict, "SSID",
2801 (const char *) (ie + 2),
2802 ie[1]))
2803 goto error;
2806 ie = wpa_bss_get_vendor_ie(res, WPA_IE_VENDOR_TYPE);
2807 if (ie) {
2808 if (!wpa_dbus_dict_append_byte_array(&iter_dict, "WPAIE",
2809 (const char *) ie,
2810 ie[1] + 2))
2811 goto error;
2814 ie = wpa_bss_get_ie(res, WLAN_EID_RSN);
2815 if (ie) {
2816 if (!wpa_dbus_dict_append_byte_array(&iter_dict, "RSNIE",
2817 (const char *) ie,
2818 ie[1] + 2))
2819 goto error;
2822 ie = wpa_bss_get_vendor_ie(res, WPS_IE_VENDOR_TYPE);
2823 if (ie) {
2824 if (!wpa_dbus_dict_append_byte_array(&iter_dict, "WPSIE",
2825 (const char *) ie,
2826 ie[1] + 2))
2827 goto error;
2830 if (res->freq) {
2831 if (!wpa_dbus_dict_append_int32(&iter_dict, "Frequency",
2832 res->freq))
2833 goto error;
2835 if (!wpa_dbus_dict_append_uint16(&iter_dict, "Capabilities",
2836 res->caps))
2837 goto error;
2838 if (!(res->flags & WPA_SCAN_QUAL_INVALID) &&
2839 !wpa_dbus_dict_append_int32(&iter_dict, "Quality", res->qual))
2840 goto error;
2841 if (!(res->flags & WPA_SCAN_NOISE_INVALID) &&
2842 !wpa_dbus_dict_append_int32(&iter_dict, "Noise", res->noise))
2843 goto error;
2844 if (!(res->flags & WPA_SCAN_LEVEL_INVALID) &&
2845 !wpa_dbus_dict_append_int32(&iter_dict, "Level", res->level))
2846 goto error;
2847 if (!wpa_dbus_dict_append_int32(&iter_dict, "MaxRate",
2848 wpa_bss_get_max_rate(res) * 500000))
2849 goto error;
2851 if (!wpa_dbus_dict_close_write(&iter, &iter_dict))
2852 goto error;
2854 return reply;
2856 error:
2857 if (reply)
2858 dbus_message_unref(reply);
2859 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, NULL);
2864 * wpas_dbus_getter_enabled - Check whether network is enabled or disabled
2865 * @message: Pointer to incoming dbus message
2866 * @wpas_dbus_setter_enabled: wpa_supplicant structure for a network interface
2867 * and wpa_ssid structure for a configured network
2868 * Returns: DBus message with boolean indicating state of configured network
2869 * or DBus error on failure
2871 * Getter for "enabled" property of a configured network.
2873 DBusMessage * wpas_dbus_getter_enabled(DBusMessage *message,
2874 struct network_handler_args *net)
2876 DBusMessage *reply = NULL;
2877 DBusMessageIter iter, variant_iter;
2879 dbus_bool_t enabled = net->ssid->disabled ? FALSE : TRUE;
2881 if (message == NULL)
2882 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
2883 else
2884 reply = dbus_message_new_method_return(message);
2885 if (!reply) {
2886 perror("wpas_dbus_getter_enabled[dbus] out of memory when "
2887 "trying to initialize return message");
2888 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2889 NULL);
2890 goto out;
2893 dbus_message_iter_init_append(reply, &iter);
2895 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
2896 "b", &variant_iter)) {
2897 dbus_message_unref(reply);
2898 perror("wpas_dbus_getter_enabled[dbus] out of memory when "
2899 "trying to open variant");
2900 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2901 NULL);
2902 goto out;
2905 if (!dbus_message_iter_append_basic(&variant_iter,
2906 DBUS_TYPE_BOOLEAN, &enabled)) {
2907 dbus_message_unref(reply);
2908 perror("wpas_dbus_getter_enabled[dbus] out of memory when "
2909 "trying to append value");
2910 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2911 NULL);
2912 goto out;
2915 if (!dbus_message_iter_close_container(&iter, &variant_iter)) {
2916 dbus_message_unref(reply);
2917 perror("wpas_dbus_getter_blobs[dbus] out of memory when "
2918 "trying to close variant");
2919 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2920 NULL);
2921 goto out;
2924 out:
2925 return reply;
2930 * wpas_dbus_setter_enabled - Mark a configured network as enabled or disabled
2931 * @message: Pointer to incoming dbus message
2932 * @wpas_dbus_setter_enabled: wpa_supplicant structure for a network interface
2933 * and wpa_ssid structure for a configured network
2934 * Returns: NULL indicating success or DBus error on failure
2936 * Setter for "Enabled" property of a configured network.
2938 DBusMessage * wpas_dbus_setter_enabled(DBusMessage *message,
2939 struct network_handler_args *net)
2941 DBusMessage *reply = NULL;
2942 DBusMessageIter iter, variant_iter;
2944 struct wpa_supplicant *wpa_s;
2945 struct wpa_ssid *ssid;
2947 dbus_bool_t enable;
2949 if (!dbus_message_iter_init(message, &iter)) {
2950 perror("wpas_dbus_setter_enabled[dbus] out of memory when "
2951 "trying to init iterator");
2952 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2953 NULL);
2954 goto out;
2957 dbus_message_iter_next(&iter);
2958 dbus_message_iter_next(&iter);
2960 dbus_message_iter_recurse(&iter, &variant_iter);
2961 if (dbus_message_iter_get_arg_type(&variant_iter) !=
2962 DBUS_TYPE_BOOLEAN) {
2963 perror("wpas_dbus_setter_enabled[dbus] "
2964 "variant content should be boolean");
2965 reply = dbus_message_new_error(message,
2966 DBUS_ERROR_INVALID_ARGS,
2967 "value should be a boolean");
2968 goto out;
2970 dbus_message_iter_get_basic(&variant_iter, &enable);
2972 wpa_s = net->wpa_s;
2973 ssid = net->ssid;
2975 if (enable)
2976 wpa_supplicant_enable_network(wpa_s, ssid);
2977 else
2978 wpa_supplicant_disable_network(wpa_s, ssid);
2980 out:
2981 return reply;
2986 * wpas_dbus_getter_network_properties - Get options for a configured network
2987 * @message: Pointer to incoming dbus message
2988 * @net: wpa_supplicant structure for a network interface and
2989 * wpa_ssid structure for a configured network
2990 * Returns: DBus message with network properties or DBus error on failure
2992 * Getter for "Properties" property of a configured network.
2994 DBusMessage * wpas_dbus_getter_network_properties(
2995 DBusMessage *message, struct network_handler_args *net)
2997 DBusMessage *reply = NULL;
2998 DBusMessageIter iter, variant_iter, dict_iter;
2999 char **iterator;
3000 char **props = wpa_config_get_all(net->ssid, 0);
3001 if (!props) {
3002 perror("wpas_dbus_getter_network_properties[dbus] couldn't "
3003 "read network properties. out of memory.");
3004 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
3005 NULL);
3008 if (message == NULL)
3009 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
3010 else
3011 reply = dbus_message_new_method_return(message);
3012 if (!reply) {
3013 perror("wpas_dbus_getter_network_properties[dbus] out of "
3014 "memory when trying to initialize return message");
3015 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
3016 NULL);
3017 goto out;
3020 dbus_message_iter_init_append(reply, &iter);
3022 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
3023 "a{sv}", &variant_iter)) {
3024 perror("wpas_dbus_getter_network_properties[dbus] out of "
3025 "memory when trying to open variant container");
3026 dbus_message_unref(reply);
3027 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
3028 NULL);
3029 goto out;
3032 if (!wpa_dbus_dict_open_write(&variant_iter, &dict_iter)) {
3033 perror("wpas_dbus_getter_network_properties[dbus] out of "
3034 "memory when trying to open dict");
3035 dbus_message_unref(reply);
3036 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
3037 NULL);
3038 goto out;
3041 iterator = props;
3042 while (*iterator) {
3043 if (!wpa_dbus_dict_append_string(&dict_iter, *iterator,
3044 *(iterator + 1))) {
3045 perror("wpas_dbus_getter_network_properties[dbus] out "
3046 "of memory when trying to add entry");
3047 dbus_message_unref(reply);
3048 reply = dbus_message_new_error(message,
3049 DBUS_ERROR_NO_MEMORY,
3050 NULL);
3051 goto out;
3053 iterator += 2;
3057 if (!wpa_dbus_dict_close_write(&variant_iter, &dict_iter)) {
3058 perror("wpas_dbus_getter_network_properties[dbus] out of "
3059 "memory when trying to close dictionary");
3060 dbus_message_unref(reply);
3061 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
3062 NULL);
3063 goto out;
3066 if (!dbus_message_iter_close_container(&iter, &variant_iter)) {
3067 perror("wpas_dbus_getter_network_properties[dbus] out of "
3068 "memory when trying to close variant container");
3069 dbus_message_unref(reply);
3070 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
3071 NULL);
3072 goto out;
3075 out:
3076 iterator = props;
3077 while (*iterator) {
3078 os_free(*iterator);
3079 iterator++;
3081 os_free(props);
3082 return reply;
3087 * wpas_dbus_setter_network_properties - Set options for a configured network
3088 * @message: Pointer to incoming dbus message
3089 * @net: wpa_supplicant structure for a network interface and
3090 * wpa_ssid structure for a configured network
3091 * Returns: NULL indicating success or DBus error on failure
3093 * Setter for "Properties" property of a configured network.
3095 DBusMessage * wpas_dbus_setter_network_properties(
3096 DBusMessage *message, struct network_handler_args *net)
3098 struct wpa_ssid *ssid = net->ssid;
3100 DBusMessage *reply = NULL;
3101 DBusMessageIter iter, variant_iter;
3103 dbus_message_iter_init(message, &iter);
3105 dbus_message_iter_next(&iter);
3106 dbus_message_iter_next(&iter);
3108 dbus_message_iter_recurse(&iter, &variant_iter);
3110 reply = set_network_properties(message, ssid, &variant_iter);
3111 if (reply)
3112 wpa_printf(MSG_DEBUG, "dbus control interface couldn't set "
3113 "network properties");
3115 return reply;