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