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