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