1d4f2939cSRui Paulo /*
2d4f2939cSRui Paulo  * WPA Supplicant / dbus-based control interface
3d4f2939cSRui Paulo  * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
4d4f2939cSRui Paulo  * Copyright (c) 2009-2010, Witold Sowa <witold.sowa@gmail.com>
55b9c547cSRui Paulo  * Copyright (c) 2009-2015, Jouni Malinen <j@w1.fi>
6d4f2939cSRui Paulo  *
7d4f2939cSRui Paulo  * This software may be distributed under the terms of the BSD license.
8d4f2939cSRui Paulo  * See README for more details.
9d4f2939cSRui Paulo  */
10d4f2939cSRui Paulo 
11d4f2939cSRui Paulo #include "includes.h"
12d4f2939cSRui Paulo 
13d4f2939cSRui Paulo #include "common.h"
14d4f2939cSRui Paulo #include "common/ieee802_11_defs.h"
15d4f2939cSRui Paulo #include "eap_peer/eap_methods.h"
16d4f2939cSRui Paulo #include "eapol_supp/eapol_supp_sm.h"
17d4f2939cSRui Paulo #include "rsn_supp/wpa.h"
184bc52338SCy Schubert #include "ap/hostapd.h"
194bc52338SCy Schubert #include "ap/sta_info.h"
204bc52338SCy Schubert #include "ap/ap_drv_ops.h"
21d4f2939cSRui Paulo #include "../config.h"
22d4f2939cSRui Paulo #include "../wpa_supplicant_i.h"
23d4f2939cSRui Paulo #include "../driver_i.h"
24d4f2939cSRui Paulo #include "../notify.h"
25d4f2939cSRui Paulo #include "../bss.h"
26d4f2939cSRui Paulo #include "../scan.h"
27d4f2939cSRui Paulo #include "../autoscan.h"
284bc52338SCy Schubert #include "../ap.h"
2932a95656SCy Schubert #include "../interworking.h"
30d4f2939cSRui Paulo #include "dbus_new_helpers.h"
31d4f2939cSRui Paulo #include "dbus_new.h"
32d4f2939cSRui Paulo #include "dbus_new_handlers.h"
33d4f2939cSRui Paulo #include "dbus_dict_helpers.h"
34d4f2939cSRui Paulo #include "dbus_common_i.h"
355b9c547cSRui Paulo #include "drivers/driver.h"
3685732ac8SCy Schubert #ifdef CONFIG_MESH
3785732ac8SCy Schubert #include "ap/hostapd.h"
3885732ac8SCy Schubert #include "ap/sta_info.h"
3985732ac8SCy Schubert #endif /* CONFIG_MESH */
40d4f2939cSRui Paulo 
415b9c547cSRui Paulo static const char * const debug_strings[] = {
42d4f2939cSRui Paulo 	"excessive", "msgdump", "debug", "info", "warning", "error", NULL
43d4f2939cSRui Paulo };
44d4f2939cSRui Paulo 
45d4f2939cSRui Paulo 
46d4f2939cSRui Paulo /**
475b9c547cSRui Paulo  * wpas_dbus_error_unknown_error - Return a new UnknownError error message
48d4f2939cSRui Paulo  * @message: Pointer to incoming dbus message this error refers to
49d4f2939cSRui Paulo  * @arg: Optional string appended to error message
50d4f2939cSRui Paulo  * Returns: a dbus error message
51d4f2939cSRui Paulo  *
52d4f2939cSRui Paulo  * Convenience function to create and return an UnknownError
53d4f2939cSRui Paulo  */
wpas_dbus_error_unknown_error(DBusMessage * message,const char * arg)54d4f2939cSRui Paulo DBusMessage * wpas_dbus_error_unknown_error(DBusMessage *message,
55d4f2939cSRui Paulo 					    const char *arg)
56d4f2939cSRui Paulo {
57d4f2939cSRui Paulo 	return dbus_message_new_error(message, WPAS_DBUS_ERROR_UNKNOWN_ERROR,
58d4f2939cSRui Paulo 				      arg);
59d4f2939cSRui Paulo }
60d4f2939cSRui Paulo 
61d4f2939cSRui Paulo 
62d4f2939cSRui Paulo /**
63d4f2939cSRui Paulo  * wpas_dbus_error_iface_unknown - Return a new invalid interface error message
64d4f2939cSRui Paulo  * @message: Pointer to incoming dbus message this error refers to
65d4f2939cSRui Paulo  * Returns: A dbus error message
66d4f2939cSRui Paulo  *
67d4f2939cSRui Paulo  * Convenience function to create and return an invalid interface error
68d4f2939cSRui Paulo  */
wpas_dbus_error_iface_unknown(DBusMessage * message)69d4f2939cSRui Paulo static DBusMessage * wpas_dbus_error_iface_unknown(DBusMessage *message)
70d4f2939cSRui Paulo {
715b9c547cSRui Paulo 	return dbus_message_new_error(
725b9c547cSRui Paulo 		message, WPAS_DBUS_ERROR_IFACE_UNKNOWN,
735b9c547cSRui Paulo 		"wpa_supplicant knows nothing about this interface.");
74d4f2939cSRui Paulo }
75d4f2939cSRui Paulo 
76d4f2939cSRui Paulo 
77d4f2939cSRui Paulo /**
78d4f2939cSRui Paulo  * wpas_dbus_error_network_unknown - Return a new NetworkUnknown error message
79d4f2939cSRui Paulo  * @message: Pointer to incoming dbus message this error refers to
80d4f2939cSRui Paulo  * Returns: a dbus error message
81d4f2939cSRui Paulo  *
82d4f2939cSRui Paulo  * Convenience function to create and return an invalid network error
83d4f2939cSRui Paulo  */
wpas_dbus_error_network_unknown(DBusMessage * message)84d4f2939cSRui Paulo static DBusMessage * wpas_dbus_error_network_unknown(DBusMessage *message)
85d4f2939cSRui Paulo {
865b9c547cSRui Paulo 	return dbus_message_new_error(
875b9c547cSRui Paulo 		message, WPAS_DBUS_ERROR_NETWORK_UNKNOWN,
885b9c547cSRui Paulo 		"There is no such a network in this interface.");
89d4f2939cSRui Paulo }
90d4f2939cSRui Paulo 
91d4f2939cSRui Paulo 
92d4f2939cSRui Paulo /**
93d4f2939cSRui Paulo  * wpas_dbus_error_invalid_args - Return a new InvalidArgs error message
94d4f2939cSRui Paulo  * @message: Pointer to incoming dbus message this error refers to
95d4f2939cSRui Paulo  * Returns: a dbus error message
96d4f2939cSRui Paulo  *
97d4f2939cSRui Paulo  * Convenience function to create and return an invalid options error
98d4f2939cSRui Paulo  */
wpas_dbus_error_invalid_args(DBusMessage * message,const char * arg)99d4f2939cSRui Paulo DBusMessage * wpas_dbus_error_invalid_args(DBusMessage *message,
100d4f2939cSRui Paulo 					  const char *arg)
101d4f2939cSRui Paulo {
102d4f2939cSRui Paulo 	DBusMessage *reply;
103d4f2939cSRui Paulo 
1045b9c547cSRui Paulo 	reply = dbus_message_new_error(
1055b9c547cSRui Paulo 		message, WPAS_DBUS_ERROR_INVALID_ARGS,
1065b9c547cSRui Paulo 		"Did not receive correct message arguments.");
107d4f2939cSRui Paulo 	if (arg != NULL)
108d4f2939cSRui Paulo 		dbus_message_append_args(reply, DBUS_TYPE_STRING, &arg,
109d4f2939cSRui Paulo 					 DBUS_TYPE_INVALID);
110d4f2939cSRui Paulo 
111d4f2939cSRui Paulo 	return reply;
112d4f2939cSRui Paulo }
113d4f2939cSRui Paulo 
114d4f2939cSRui Paulo 
1155b9c547cSRui Paulo /**
1165b9c547cSRui Paulo  * wpas_dbus_error_scan_error - Return a new ScanError error message
1175b9c547cSRui Paulo  * @message: Pointer to incoming dbus message this error refers to
1185b9c547cSRui Paulo  * @error: Optional string to be used as the error message
1195b9c547cSRui Paulo  * Returns: a dbus error message
1205b9c547cSRui Paulo  *
1215b9c547cSRui Paulo  * Convenience function to create and return a scan error
1225b9c547cSRui Paulo  */
wpas_dbus_error_scan_error(DBusMessage * message,const char * error)1235b9c547cSRui Paulo static DBusMessage * wpas_dbus_error_scan_error(DBusMessage *message,
1245b9c547cSRui Paulo 						const char *error)
1255b9c547cSRui Paulo {
1265b9c547cSRui Paulo 	return dbus_message_new_error(message,
1275b9c547cSRui Paulo 				      WPAS_DBUS_ERROR_IFACE_SCAN_ERROR,
1285b9c547cSRui Paulo 				      error);
1295b9c547cSRui Paulo }
1305b9c547cSRui Paulo 
1315b9c547cSRui Paulo 
wpas_dbus_error_no_memory(DBusMessage * message)1325b9c547cSRui Paulo DBusMessage * wpas_dbus_error_no_memory(DBusMessage *message)
1335b9c547cSRui Paulo {
1345b9c547cSRui Paulo 	wpa_printf(MSG_DEBUG, "dbus: Failed to allocate memory");
1355b9c547cSRui Paulo 	return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, NULL);
1365b9c547cSRui Paulo }
1375b9c547cSRui Paulo 
1385b9c547cSRui Paulo 
1395b9c547cSRui Paulo static const char * const dont_quote[] = {
140d4f2939cSRui Paulo 	"key_mgmt", "proto", "pairwise", "auth_alg", "group", "eap",
141c1d255d3SCy Schubert 	"bssid", "scan_freq", "freq_list", "scan_ssid", "bssid_hint",
142c1d255d3SCy Schubert 	"bssid_ignore", "bssid_accept", /* deprecated aliases */
143c1d255d3SCy Schubert 	"bssid_blacklist", "bssid_whitelist",
144c1d255d3SCy Schubert 	"group_mgmt",
145c1d255d3SCy Schubert 	"ignore_broadcast_ssid",
146c1d255d3SCy Schubert #ifdef CONFIG_MESH
147c1d255d3SCy Schubert 	"mesh_basic_rates",
148c1d255d3SCy Schubert #endif /* CONFIG_MESH */
149c1d255d3SCy Schubert #ifdef CONFIG_P2P
150c1d255d3SCy Schubert 	"go_p2p_dev_addr", "p2p_client_list", "psk_list",
151c1d255d3SCy Schubert #endif /* CONFIG_P2P */
15232a95656SCy Schubert #ifdef CONFIG_INTERWORKING
15332a95656SCy Schubert 	"roaming_consortium", "required_roaming_consortium",
15432a95656SCy Schubert #endif /* CONFIG_INTERWORKING */
155c1d255d3SCy Schubert 	NULL
156d4f2939cSRui Paulo };
157d4f2939cSRui Paulo 
should_quote_opt(const char * key)158d4f2939cSRui Paulo static dbus_bool_t should_quote_opt(const char *key)
159d4f2939cSRui Paulo {
160d4f2939cSRui Paulo 	int i = 0;
1615b9c547cSRui Paulo 
162d4f2939cSRui Paulo 	while (dont_quote[i] != NULL) {
163d4f2939cSRui Paulo 		if (os_strcmp(key, dont_quote[i]) == 0)
164d4f2939cSRui Paulo 			return FALSE;
165d4f2939cSRui Paulo 		i++;
166d4f2939cSRui Paulo 	}
167d4f2939cSRui Paulo 	return TRUE;
168d4f2939cSRui Paulo }
169d4f2939cSRui Paulo 
170d4f2939cSRui Paulo /**
171d4f2939cSRui Paulo  * get_iface_by_dbus_path - Get a new network interface
172d4f2939cSRui Paulo  * @global: Pointer to global data from wpa_supplicant_init()
173d4f2939cSRui Paulo  * @path: Pointer to a dbus object path representing an interface
174d4f2939cSRui Paulo  * Returns: Pointer to the interface or %NULL if not found
175d4f2939cSRui Paulo  */
get_iface_by_dbus_path(struct wpa_global * global,const char * path)176d4f2939cSRui Paulo static struct wpa_supplicant * get_iface_by_dbus_path(
177d4f2939cSRui Paulo 	struct wpa_global *global, const char *path)
178d4f2939cSRui Paulo {
179d4f2939cSRui Paulo 	struct wpa_supplicant *wpa_s;
180d4f2939cSRui Paulo 
181d4f2939cSRui Paulo 	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
182325151a3SRui Paulo 		if (wpa_s->dbus_new_path &&
183325151a3SRui Paulo 		    os_strcmp(wpa_s->dbus_new_path, path) == 0)
184d4f2939cSRui Paulo 			return wpa_s;
185d4f2939cSRui Paulo 	}
186d4f2939cSRui Paulo 	return NULL;
187d4f2939cSRui Paulo }
188d4f2939cSRui Paulo 
189d4f2939cSRui Paulo 
190d4f2939cSRui Paulo /**
191d4f2939cSRui Paulo  * set_network_properties - Set properties of a configured network
192d4f2939cSRui Paulo  * @wpa_s: wpa_supplicant structure for a network interface
193d4f2939cSRui Paulo  * @ssid: wpa_ssid structure for a configured network
194d4f2939cSRui Paulo  * @iter: DBus message iterator containing dictionary of network
195d4f2939cSRui Paulo  * properties to set.
196d4f2939cSRui Paulo  * @error: On failure, an error describing the failure
197d4f2939cSRui Paulo  * Returns: TRUE if the request succeeds, FALSE if it failed
198d4f2939cSRui Paulo  *
199d4f2939cSRui Paulo  * Sets network configuration with parameters given id DBus dictionary
200d4f2939cSRui Paulo  */
set_network_properties(struct wpa_supplicant * wpa_s,struct wpa_ssid * ssid,DBusMessageIter * iter,DBusError * error)201d4f2939cSRui Paulo dbus_bool_t set_network_properties(struct wpa_supplicant *wpa_s,
202d4f2939cSRui Paulo 				   struct wpa_ssid *ssid,
203d4f2939cSRui Paulo 				   DBusMessageIter *iter,
204d4f2939cSRui Paulo 				   DBusError *error)
205d4f2939cSRui Paulo {
206d4f2939cSRui Paulo 	struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
207d4f2939cSRui Paulo 	DBusMessageIter	iter_dict;
208d4f2939cSRui Paulo 	char *value = NULL;
209d4f2939cSRui Paulo 
210d4f2939cSRui Paulo 	if (!wpa_dbus_dict_open_read(iter, &iter_dict, error))
211d4f2939cSRui Paulo 		return FALSE;
212d4f2939cSRui Paulo 
213d4f2939cSRui Paulo 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
214d4f2939cSRui Paulo 		size_t size = 50;
215d4f2939cSRui Paulo 		int ret;
216d4f2939cSRui Paulo 
217d4f2939cSRui Paulo 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
218d4f2939cSRui Paulo 			goto error;
219d4f2939cSRui Paulo 
220d4f2939cSRui Paulo 		value = NULL;
221d4f2939cSRui Paulo 		if (entry.type == DBUS_TYPE_ARRAY &&
222d4f2939cSRui Paulo 		    entry.array_type == DBUS_TYPE_BYTE) {
223d4f2939cSRui Paulo 			if (entry.array_len <= 0)
224d4f2939cSRui Paulo 				goto error;
225d4f2939cSRui Paulo 
226d4f2939cSRui Paulo 			size = entry.array_len * 2 + 1;
227d4f2939cSRui Paulo 			value = os_zalloc(size);
228d4f2939cSRui Paulo 			if (value == NULL)
229d4f2939cSRui Paulo 				goto error;
230d4f2939cSRui Paulo 
231d4f2939cSRui Paulo 			ret = wpa_snprintf_hex(value, size,
232d4f2939cSRui Paulo 					       (u8 *) entry.bytearray_value,
233d4f2939cSRui Paulo 					       entry.array_len);
234d4f2939cSRui Paulo 			if (ret <= 0)
235d4f2939cSRui Paulo 				goto error;
236d4f2939cSRui Paulo 		} else if (entry.type == DBUS_TYPE_STRING) {
237d4f2939cSRui Paulo 			if (should_quote_opt(entry.key)) {
238d4f2939cSRui Paulo 				size = os_strlen(entry.str_value);
239d4f2939cSRui Paulo 
240d4f2939cSRui Paulo 				size += 3;
241d4f2939cSRui Paulo 				value = os_zalloc(size);
242d4f2939cSRui Paulo 				if (value == NULL)
243d4f2939cSRui Paulo 					goto error;
244d4f2939cSRui Paulo 
245d4f2939cSRui Paulo 				ret = os_snprintf(value, size, "\"%s\"",
246d4f2939cSRui Paulo 						  entry.str_value);
2475b9c547cSRui Paulo 				if (os_snprintf_error(size, ret))
248d4f2939cSRui Paulo 					goto error;
249d4f2939cSRui Paulo 			} else {
250d4f2939cSRui Paulo 				value = os_strdup(entry.str_value);
251d4f2939cSRui Paulo 				if (value == NULL)
252d4f2939cSRui Paulo 					goto error;
253d4f2939cSRui Paulo 			}
254d4f2939cSRui Paulo 		} else if (entry.type == DBUS_TYPE_UINT32) {
255d4f2939cSRui Paulo 			value = os_zalloc(size);
256d4f2939cSRui Paulo 			if (value == NULL)
257d4f2939cSRui Paulo 				goto error;
258d4f2939cSRui Paulo 
259d4f2939cSRui Paulo 			ret = os_snprintf(value, size, "%u",
260d4f2939cSRui Paulo 					  entry.uint32_value);
2615b9c547cSRui Paulo 			if (os_snprintf_error(size, ret))
262d4f2939cSRui Paulo 				goto error;
263d4f2939cSRui Paulo 		} else if (entry.type == DBUS_TYPE_INT32) {
264d4f2939cSRui Paulo 			value = os_zalloc(size);
265d4f2939cSRui Paulo 			if (value == NULL)
266d4f2939cSRui Paulo 				goto error;
267d4f2939cSRui Paulo 
268d4f2939cSRui Paulo 			ret = os_snprintf(value, size, "%d",
269d4f2939cSRui Paulo 					  entry.int32_value);
2705b9c547cSRui Paulo 			if (os_snprintf_error(size, ret))
271d4f2939cSRui Paulo 				goto error;
272d4f2939cSRui Paulo 		} else
273d4f2939cSRui Paulo 			goto error;
274d4f2939cSRui Paulo 
275c1d255d3SCy Schubert 		ret = wpa_config_set(ssid, entry.key, value, 0);
276c1d255d3SCy Schubert 		if (ret < 0)
277d4f2939cSRui Paulo 			goto error;
278c1d255d3SCy Schubert 		if (ret == 1)
279c1d255d3SCy Schubert 			goto skip_update;
280c1d255d3SCy Schubert 
281c1d255d3SCy Schubert #ifdef CONFIG_BGSCAN
282c1d255d3SCy Schubert 		if (os_strcmp(entry.key, "bgscan") == 0) {
283c1d255d3SCy Schubert 			/*
284c1d255d3SCy Schubert 			 * Reset the bgscan parameters for the current network
285c1d255d3SCy Schubert 			 * and continue. There's no need to flush caches for
286c1d255d3SCy Schubert 			 * bgscan parameter changes.
287c1d255d3SCy Schubert 			 */
288c1d255d3SCy Schubert 			if (wpa_s->current_ssid == ssid &&
289c1d255d3SCy Schubert 			    wpa_s->wpa_state == WPA_COMPLETED)
290c1d255d3SCy Schubert 				wpa_supplicant_reset_bgscan(wpa_s);
291c1d255d3SCy Schubert 			os_free(value);
292c1d255d3SCy Schubert 			value = NULL;
293c1d255d3SCy Schubert 			wpa_dbus_dict_entry_clear(&entry);
294c1d255d3SCy Schubert 			continue;
295c1d255d3SCy Schubert 		}
296c1d255d3SCy Schubert #endif /* CONFIG_BGSCAN */
297d4f2939cSRui Paulo 
2985b9c547cSRui Paulo 		if (os_strcmp(entry.key, "bssid") != 0 &&
2995b9c547cSRui Paulo 		    os_strcmp(entry.key, "priority") != 0)
3005b9c547cSRui Paulo 			wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
3015b9c547cSRui Paulo 
3025b9c547cSRui Paulo 		if (wpa_s->current_ssid == ssid ||
3035b9c547cSRui Paulo 		    wpa_s->current_ssid == NULL) {
3045b9c547cSRui Paulo 			/*
3055b9c547cSRui Paulo 			 * Invalidate the EAP session cache if anything in the
3065b9c547cSRui Paulo 			 * current or previously used configuration changes.
3075b9c547cSRui Paulo 			 */
3085b9c547cSRui Paulo 			eapol_sm_invalidate_cached_session(wpa_s->eapol);
3095b9c547cSRui Paulo 		}
3105b9c547cSRui Paulo 
311d4f2939cSRui Paulo 		if ((os_strcmp(entry.key, "psk") == 0 &&
312d4f2939cSRui Paulo 		     value[0] == '"' && ssid->ssid_len) ||
313d4f2939cSRui Paulo 		    (os_strcmp(entry.key, "ssid") == 0 && ssid->passphrase))
314d4f2939cSRui Paulo 			wpa_config_update_psk(ssid);
315d4f2939cSRui Paulo 		else if (os_strcmp(entry.key, "priority") == 0)
316d4f2939cSRui Paulo 			wpa_config_update_prio_list(wpa_s->conf);
317d4f2939cSRui Paulo 
318c1d255d3SCy Schubert 	skip_update:
319d4f2939cSRui Paulo 		os_free(value);
3205b9c547cSRui Paulo 		value = NULL;
321d4f2939cSRui Paulo 		wpa_dbus_dict_entry_clear(&entry);
322d4f2939cSRui Paulo 	}
323d4f2939cSRui Paulo 
324d4f2939cSRui Paulo 	return TRUE;
325d4f2939cSRui Paulo 
326d4f2939cSRui Paulo error:
327d4f2939cSRui Paulo 	os_free(value);
328d4f2939cSRui Paulo 	wpa_dbus_dict_entry_clear(&entry);
329d4f2939cSRui Paulo 	dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
330d4f2939cSRui Paulo 			     "invalid message format");
331d4f2939cSRui Paulo 	return FALSE;
332d4f2939cSRui Paulo }
333d4f2939cSRui Paulo 
334d4f2939cSRui Paulo 
335d4f2939cSRui Paulo /**
33632a95656SCy Schubert  * set_cred_properties - Set the properties of a configured credential
33732a95656SCy Schubert  * @wpa_s: wpa_supplicant structure for a network interface
33832a95656SCy Schubert  * @cred: wpa_cred structure for a configured credential
33932a95656SCy Schubert  * @iter: DBus message iterator containing dictionary of network
34032a95656SCy Schubert  * properties to set.
34132a95656SCy Schubert  * @error: On failure, an error describing the failure
34232a95656SCy Schubert  * Returns: TRUE if the request succeeds, FALSE if it failed
34332a95656SCy Schubert  */
set_cred_properties(struct wpa_supplicant * wpa_s,struct wpa_cred * cred,DBusMessageIter * iter,DBusError * error)34432a95656SCy Schubert static dbus_bool_t set_cred_properties(struct wpa_supplicant *wpa_s,
34532a95656SCy Schubert 				       struct wpa_cred *cred,
34632a95656SCy Schubert 				       DBusMessageIter *iter,
34732a95656SCy Schubert 				       DBusError *error)
34832a95656SCy Schubert {
34932a95656SCy Schubert 	struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
35032a95656SCy Schubert 	DBusMessageIter	iter_dict;
35132a95656SCy Schubert 	char *value = NULL;
35232a95656SCy Schubert 
35332a95656SCy Schubert 	if (!wpa_dbus_dict_open_read(iter, &iter_dict, error))
35432a95656SCy Schubert 		return FALSE;
35532a95656SCy Schubert 
35632a95656SCy Schubert 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
35732a95656SCy Schubert 		size_t size = 50;
35832a95656SCy Schubert 		int ret;
35932a95656SCy Schubert 
36032a95656SCy Schubert 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
36132a95656SCy Schubert 			goto error;
36232a95656SCy Schubert 
36332a95656SCy Schubert 		value = NULL;
36432a95656SCy Schubert 		if (entry.type == DBUS_TYPE_ARRAY &&
36532a95656SCy Schubert 		    entry.array_type == DBUS_TYPE_BYTE) {
36632a95656SCy Schubert 			if (entry.array_len <= 0)
36732a95656SCy Schubert 				goto error;
36832a95656SCy Schubert 
36932a95656SCy Schubert 			size = entry.array_len * 2 + 1;
37032a95656SCy Schubert 			value = os_zalloc(size);
37132a95656SCy Schubert 			if (!value)
37232a95656SCy Schubert 				goto error;
37332a95656SCy Schubert 
37432a95656SCy Schubert 			ret = wpa_snprintf_hex(value, size,
37532a95656SCy Schubert 					       (u8 *) entry.bytearray_value,
37632a95656SCy Schubert 					       entry.array_len);
37732a95656SCy Schubert 			if (ret <= 0)
37832a95656SCy Schubert 				goto error;
37932a95656SCy Schubert 		} else if (entry.type == DBUS_TYPE_STRING) {
38032a95656SCy Schubert 			if (should_quote_opt(entry.key)) {
38132a95656SCy Schubert 				size = os_strlen(entry.str_value);
38232a95656SCy Schubert 
38332a95656SCy Schubert 				size += 3;
38432a95656SCy Schubert 				value = os_zalloc(size);
38532a95656SCy Schubert 				if (!value)
38632a95656SCy Schubert 					goto error;
38732a95656SCy Schubert 
38832a95656SCy Schubert 				ret = os_snprintf(value, size, "\"%s\"",
38932a95656SCy Schubert 						  entry.str_value);
39032a95656SCy Schubert 				if (os_snprintf_error(size, ret))
39132a95656SCy Schubert 					goto error;
39232a95656SCy Schubert 			} else {
39332a95656SCy Schubert 				value = os_strdup(entry.str_value);
39432a95656SCy Schubert 				if (!value)
39532a95656SCy Schubert 					goto error;
39632a95656SCy Schubert 			}
39732a95656SCy Schubert 		} else if (entry.type == DBUS_TYPE_UINT32) {
39832a95656SCy Schubert 			value = os_zalloc(size);
39932a95656SCy Schubert 			if (!value)
40032a95656SCy Schubert 				goto error;
40132a95656SCy Schubert 
40232a95656SCy Schubert 			ret = os_snprintf(value, size, "%u",
40332a95656SCy Schubert 					  entry.uint32_value);
40432a95656SCy Schubert 			if (os_snprintf_error(size, ret))
40532a95656SCy Schubert 				goto error;
40632a95656SCy Schubert 		} else if (entry.type == DBUS_TYPE_INT32) {
40732a95656SCy Schubert 			value = os_zalloc(size);
40832a95656SCy Schubert 			if (!value)
40932a95656SCy Schubert 				goto error;
41032a95656SCy Schubert 
41132a95656SCy Schubert 			ret = os_snprintf(value, size, "%d",
41232a95656SCy Schubert 					  entry.int32_value);
41332a95656SCy Schubert 			if (os_snprintf_error(size, ret))
41432a95656SCy Schubert 				goto error;
41532a95656SCy Schubert 		} else {
41632a95656SCy Schubert 			goto error;
41732a95656SCy Schubert 		}
41832a95656SCy Schubert 
41932a95656SCy Schubert 		ret = wpa_config_set_cred(cred, entry.key, value, 0);
42032a95656SCy Schubert 		if (ret < 0)
42132a95656SCy Schubert 			goto error;
42232a95656SCy Schubert 
42332a95656SCy Schubert 		os_free(value);
42432a95656SCy Schubert 		value = NULL;
42532a95656SCy Schubert 		wpa_dbus_dict_entry_clear(&entry);
42632a95656SCy Schubert 	}
42732a95656SCy Schubert 
42832a95656SCy Schubert 	return TRUE;
42932a95656SCy Schubert 
43032a95656SCy Schubert error:
43132a95656SCy Schubert 	os_free(value);
43232a95656SCy Schubert 	wpa_dbus_dict_entry_clear(&entry);
43332a95656SCy Schubert 	dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
43432a95656SCy Schubert 			     "invalid message format");
43532a95656SCy Schubert 	return FALSE;
43632a95656SCy Schubert }
43732a95656SCy Schubert 
43832a95656SCy Schubert 
43932a95656SCy Schubert /**
440d4f2939cSRui Paulo  * wpas_dbus_simple_property_getter - Get basic type property
441d4f2939cSRui Paulo  * @iter: Message iter to use when appending arguments
442d4f2939cSRui Paulo  * @type: DBus type of property (must be basic type)
443d4f2939cSRui Paulo  * @val: pointer to place holding property value
444d4f2939cSRui Paulo  * @error: On failure an error describing the failure
445d4f2939cSRui Paulo  * Returns: TRUE if the request was successful, FALSE if it failed
446d4f2939cSRui Paulo  *
447d4f2939cSRui Paulo  * Generic getter for basic type properties. Type is required to be basic.
448d4f2939cSRui Paulo  */
wpas_dbus_simple_property_getter(DBusMessageIter * iter,const int type,const void * val,DBusError * error)449d4f2939cSRui Paulo dbus_bool_t wpas_dbus_simple_property_getter(DBusMessageIter *iter,
450d4f2939cSRui Paulo 					     const int type,
451d4f2939cSRui Paulo 					     const void *val,
452d4f2939cSRui Paulo 					     DBusError *error)
453d4f2939cSRui Paulo {
454d4f2939cSRui Paulo 	DBusMessageIter variant_iter;
455d4f2939cSRui Paulo 
456d4f2939cSRui Paulo 	if (!dbus_type_is_basic(type)) {
457d4f2939cSRui Paulo 		dbus_set_error(error, DBUS_ERROR_FAILED,
458d4f2939cSRui Paulo 			       "%s: given type is not basic", __func__);
459d4f2939cSRui Paulo 		return FALSE;
460d4f2939cSRui Paulo 	}
461d4f2939cSRui Paulo 
462d4f2939cSRui Paulo 	if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
463d4f2939cSRui Paulo 					      wpa_dbus_type_as_string(type),
4645b9c547cSRui Paulo 					      &variant_iter) ||
4655b9c547cSRui Paulo 	    !dbus_message_iter_append_basic(&variant_iter, type, val) ||
4665b9c547cSRui Paulo 	    !dbus_message_iter_close_container(iter, &variant_iter)) {
467d4f2939cSRui Paulo 		dbus_set_error(error, DBUS_ERROR_FAILED,
468d4f2939cSRui Paulo 			       "%s: error constructing reply", __func__);
469d4f2939cSRui Paulo 		return FALSE;
470d4f2939cSRui Paulo 	}
471d4f2939cSRui Paulo 
4725b9c547cSRui Paulo 	return TRUE;
4735b9c547cSRui Paulo }
4745b9c547cSRui Paulo 
475d4f2939cSRui Paulo 
476d4f2939cSRui Paulo /**
477d4f2939cSRui Paulo  * wpas_dbus_simple_property_setter - Set basic type property
478d4f2939cSRui Paulo  * @message: Pointer to incoming dbus message
479d4f2939cSRui Paulo  * @type: DBus type of property (must be basic type)
480d4f2939cSRui Paulo  * @val: pointer to place where value being set will be stored
481d4f2939cSRui Paulo  * Returns: TRUE if the request was successful, FALSE if it failed
482d4f2939cSRui Paulo  *
483d4f2939cSRui Paulo  * Generic setter for basic type properties. Type is required to be basic.
484d4f2939cSRui Paulo  */
wpas_dbus_simple_property_setter(DBusMessageIter * iter,DBusError * error,const int type,void * val)485d4f2939cSRui Paulo dbus_bool_t wpas_dbus_simple_property_setter(DBusMessageIter *iter,
486d4f2939cSRui Paulo 					     DBusError *error,
487d4f2939cSRui Paulo 					     const int type, void *val)
488d4f2939cSRui Paulo {
489d4f2939cSRui Paulo 	DBusMessageIter variant_iter;
490d4f2939cSRui Paulo 
491d4f2939cSRui Paulo 	if (!dbus_type_is_basic(type)) {
492d4f2939cSRui Paulo 		dbus_set_error(error, DBUS_ERROR_FAILED,
493d4f2939cSRui Paulo 			       "%s: given type is not basic", __func__);
494d4f2939cSRui Paulo 		return FALSE;
495d4f2939cSRui Paulo 	}
496d4f2939cSRui Paulo 
497d4f2939cSRui Paulo 	/* Look at the new value */
498d4f2939cSRui Paulo 	dbus_message_iter_recurse(iter, &variant_iter);
499d4f2939cSRui Paulo 	if (dbus_message_iter_get_arg_type(&variant_iter) != type) {
500d4f2939cSRui Paulo 		dbus_set_error_const(error, DBUS_ERROR_FAILED,
501d4f2939cSRui Paulo 				     "wrong property type");
502d4f2939cSRui Paulo 		return FALSE;
503d4f2939cSRui Paulo 	}
504d4f2939cSRui Paulo 	dbus_message_iter_get_basic(&variant_iter, val);
505d4f2939cSRui Paulo 
506d4f2939cSRui Paulo 	return TRUE;
507d4f2939cSRui Paulo }
508d4f2939cSRui Paulo 
509d4f2939cSRui Paulo 
510d4f2939cSRui Paulo /**
511d4f2939cSRui Paulo  * wpas_dbus_simple_array_property_getter - Get array type property
512d4f2939cSRui Paulo  * @iter: Pointer to incoming dbus message iterator
513d4f2939cSRui Paulo  * @type: DBus type of property array elements (must be basic type)
514d4f2939cSRui Paulo  * @array: pointer to array of elements to put into response message
515d4f2939cSRui Paulo  * @array_len: length of above array
516d4f2939cSRui Paulo  * @error: a pointer to an error to fill on failure
517d4f2939cSRui Paulo  * Returns: TRUE if the request succeeded, FALSE if it failed
518d4f2939cSRui Paulo  *
519d4f2939cSRui Paulo  * Generic getter for array type properties. Array elements type is
520d4f2939cSRui Paulo  * required to be basic.
521d4f2939cSRui Paulo  */
wpas_dbus_simple_array_property_getter(DBusMessageIter * iter,const int type,const void * array,size_t array_len,DBusError * error)522d4f2939cSRui Paulo dbus_bool_t wpas_dbus_simple_array_property_getter(DBusMessageIter *iter,
523d4f2939cSRui Paulo 						   const int type,
524d4f2939cSRui Paulo 						   const void *array,
525d4f2939cSRui Paulo 						   size_t array_len,
526d4f2939cSRui Paulo 						   DBusError *error)
527d4f2939cSRui Paulo {
528d4f2939cSRui Paulo 	DBusMessageIter variant_iter, array_iter;
529d4f2939cSRui Paulo 	char type_str[] = "a?"; /* ? will be replaced with subtype letter; */
530d4f2939cSRui Paulo 	const char *sub_type_str;
531d4f2939cSRui Paulo 	size_t element_size, i;
532d4f2939cSRui Paulo 
533d4f2939cSRui Paulo 	if (!dbus_type_is_basic(type)) {
534d4f2939cSRui Paulo 		dbus_set_error(error, DBUS_ERROR_FAILED,
535d4f2939cSRui Paulo 			       "%s: given type is not basic", __func__);
536d4f2939cSRui Paulo 		return FALSE;
537d4f2939cSRui Paulo 	}
538d4f2939cSRui Paulo 
539d4f2939cSRui Paulo 	sub_type_str = wpa_dbus_type_as_string(type);
540d4f2939cSRui Paulo 	type_str[1] = sub_type_str[0];
541d4f2939cSRui Paulo 
542d4f2939cSRui Paulo 	if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
5435b9c547cSRui Paulo 					      type_str, &variant_iter) ||
5445b9c547cSRui Paulo 	    !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
545d4f2939cSRui Paulo 					      sub_type_str, &array_iter)) {
546d4f2939cSRui Paulo 		dbus_set_error(error, DBUS_ERROR_FAILED,
5475b9c547cSRui Paulo 			       "%s: failed to construct message", __func__);
548d4f2939cSRui Paulo 		return FALSE;
549d4f2939cSRui Paulo 	}
550d4f2939cSRui Paulo 
551d4f2939cSRui Paulo 	switch (type) {
552d4f2939cSRui Paulo 	case DBUS_TYPE_BYTE:
553d4f2939cSRui Paulo 	case DBUS_TYPE_BOOLEAN:
554d4f2939cSRui Paulo 		element_size = 1;
555d4f2939cSRui Paulo 		break;
556d4f2939cSRui Paulo 	case DBUS_TYPE_INT16:
557d4f2939cSRui Paulo 	case DBUS_TYPE_UINT16:
558d4f2939cSRui Paulo 		element_size = sizeof(uint16_t);
559d4f2939cSRui Paulo 		break;
560d4f2939cSRui Paulo 	case DBUS_TYPE_INT32:
561d4f2939cSRui Paulo 	case DBUS_TYPE_UINT32:
562d4f2939cSRui Paulo 		element_size = sizeof(uint32_t);
563d4f2939cSRui Paulo 		break;
564d4f2939cSRui Paulo 	case DBUS_TYPE_INT64:
565d4f2939cSRui Paulo 	case DBUS_TYPE_UINT64:
566d4f2939cSRui Paulo 		element_size = sizeof(uint64_t);
567d4f2939cSRui Paulo 		break;
568d4f2939cSRui Paulo 	case DBUS_TYPE_DOUBLE:
569d4f2939cSRui Paulo 		element_size = sizeof(double);
570d4f2939cSRui Paulo 		break;
571d4f2939cSRui Paulo 	case DBUS_TYPE_STRING:
572d4f2939cSRui Paulo 	case DBUS_TYPE_OBJECT_PATH:
573d4f2939cSRui Paulo 		element_size = sizeof(char *);
574d4f2939cSRui Paulo 		break;
575d4f2939cSRui Paulo 	default:
576d4f2939cSRui Paulo 		dbus_set_error(error, DBUS_ERROR_FAILED,
577d4f2939cSRui Paulo 			       "%s: unknown element type %d", __func__, type);
578d4f2939cSRui Paulo 		return FALSE;
579d4f2939cSRui Paulo 	}
580d4f2939cSRui Paulo 
581d4f2939cSRui Paulo 	for (i = 0; i < array_len; i++) {
5825b9c547cSRui Paulo 		if (!dbus_message_iter_append_basic(&array_iter, type,
583780fb4a2SCy Schubert 						    (const char *) array +
584780fb4a2SCy Schubert 						    i * element_size)) {
585d4f2939cSRui Paulo 			dbus_set_error(error, DBUS_ERROR_FAILED,
5865b9c547cSRui Paulo 				       "%s: failed to construct message 2.5",
5875b9c547cSRui Paulo 				       __func__);
588d4f2939cSRui Paulo 			return FALSE;
589d4f2939cSRui Paulo 		}
5905b9c547cSRui Paulo 	}
591d4f2939cSRui Paulo 
5925b9c547cSRui Paulo 	if (!dbus_message_iter_close_container(&variant_iter, &array_iter) ||
5935b9c547cSRui Paulo 	    !dbus_message_iter_close_container(iter, &variant_iter)) {
594d4f2939cSRui Paulo 		dbus_set_error(error, DBUS_ERROR_FAILED,
5955b9c547cSRui Paulo 			       "%s: failed to construct message 3", __func__);
596d4f2939cSRui Paulo 		return FALSE;
597d4f2939cSRui Paulo 	}
598d4f2939cSRui Paulo 
599d4f2939cSRui Paulo 	return TRUE;
600d4f2939cSRui Paulo }
601d4f2939cSRui Paulo 
602d4f2939cSRui Paulo 
603d4f2939cSRui Paulo /**
604d4f2939cSRui Paulo  * wpas_dbus_simple_array_array_property_getter - Get array array type property
605d4f2939cSRui Paulo  * @iter: Pointer to incoming dbus message iterator
606d4f2939cSRui Paulo  * @type: DBus type of property array elements (must be basic type)
607d4f2939cSRui Paulo  * @array: pointer to array of elements to put into response message
608d4f2939cSRui Paulo  * @array_len: length of above array
609d4f2939cSRui Paulo  * @error: a pointer to an error to fill on failure
610d4f2939cSRui Paulo  * Returns: TRUE if the request succeeded, FALSE if it failed
611d4f2939cSRui Paulo  *
612d4f2939cSRui Paulo  * Generic getter for array type properties. Array elements type is
613d4f2939cSRui Paulo  * required to be basic.
614d4f2939cSRui Paulo  */
wpas_dbus_simple_array_array_property_getter(DBusMessageIter * iter,const int type,struct wpabuf ** array,size_t array_len,DBusError * error)615d4f2939cSRui Paulo dbus_bool_t wpas_dbus_simple_array_array_property_getter(DBusMessageIter *iter,
616d4f2939cSRui Paulo 							 const int type,
617d4f2939cSRui Paulo 							 struct wpabuf **array,
618d4f2939cSRui Paulo 							 size_t array_len,
619d4f2939cSRui Paulo 							 DBusError *error)
620d4f2939cSRui Paulo {
621d4f2939cSRui Paulo 	DBusMessageIter variant_iter, array_iter;
622d4f2939cSRui Paulo 	char type_str[] = "aa?";
623d4f2939cSRui Paulo 	char inner_type_str[] = "a?";
624d4f2939cSRui Paulo 	const char *sub_type_str;
625d4f2939cSRui Paulo 	size_t i;
626d4f2939cSRui Paulo 
627d4f2939cSRui Paulo 	if (!dbus_type_is_basic(type)) {
628d4f2939cSRui Paulo 		dbus_set_error(error, DBUS_ERROR_FAILED,
629d4f2939cSRui Paulo 			       "%s: given type is not basic", __func__);
630d4f2939cSRui Paulo 		return FALSE;
631d4f2939cSRui Paulo 	}
632d4f2939cSRui Paulo 
633d4f2939cSRui Paulo 	sub_type_str = wpa_dbus_type_as_string(type);
634d4f2939cSRui Paulo 	type_str[2] = sub_type_str[0];
635d4f2939cSRui Paulo 	inner_type_str[1] = sub_type_str[0];
636d4f2939cSRui Paulo 
637d4f2939cSRui Paulo 	if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
6385b9c547cSRui Paulo 					      type_str, &variant_iter) ||
6395b9c547cSRui Paulo 	    !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
640d4f2939cSRui Paulo 					      inner_type_str, &array_iter)) {
641d4f2939cSRui Paulo 		dbus_set_error(error, DBUS_ERROR_FAILED,
6425b9c547cSRui Paulo 			       "%s: failed to construct message", __func__);
643d4f2939cSRui Paulo 		return FALSE;
644d4f2939cSRui Paulo 	}
645d4f2939cSRui Paulo 
6465b9c547cSRui Paulo 	for (i = 0; i < array_len && array[i]; i++) {
647d4f2939cSRui Paulo 		wpa_dbus_dict_bin_array_add_element(&array_iter,
648d4f2939cSRui Paulo 						    wpabuf_head(array[i]),
649d4f2939cSRui Paulo 						    wpabuf_len(array[i]));
650d4f2939cSRui Paulo 
651d4f2939cSRui Paulo 	}
652d4f2939cSRui Paulo 
6535b9c547cSRui Paulo 	if (!dbus_message_iter_close_container(&variant_iter, &array_iter) ||
6545b9c547cSRui Paulo 	    !dbus_message_iter_close_container(iter, &variant_iter)) {
655d4f2939cSRui Paulo 		dbus_set_error(error, DBUS_ERROR_FAILED,
6565b9c547cSRui Paulo 			       "%s: failed to close message", __func__);
657d4f2939cSRui Paulo 		return FALSE;
658d4f2939cSRui Paulo 	}
659d4f2939cSRui Paulo 
660d4f2939cSRui Paulo 	return TRUE;
661d4f2939cSRui Paulo }
662d4f2939cSRui Paulo 
663d4f2939cSRui Paulo 
664d4f2939cSRui Paulo /**
66585732ac8SCy Schubert  * wpas_dbus_string_property_getter - Get string type property
66685732ac8SCy Schubert  * @iter: Message iter to use when appending arguments
66785732ac8SCy Schubert  * @val: Pointer to place holding property value, can be %NULL
66885732ac8SCy Schubert  * @error: On failure an error describing the failure
66985732ac8SCy Schubert  * Returns: TRUE if the request was successful, FALSE if it failed
67085732ac8SCy Schubert  *
67185732ac8SCy Schubert  * Generic getter for string type properties. %NULL is converted to an empty
67285732ac8SCy Schubert  * string.
67385732ac8SCy Schubert  */
wpas_dbus_string_property_getter(DBusMessageIter * iter,const void * val,DBusError * error)67485732ac8SCy Schubert dbus_bool_t wpas_dbus_string_property_getter(DBusMessageIter *iter,
67585732ac8SCy Schubert 					     const void *val,
67685732ac8SCy Schubert 					     DBusError *error)
67785732ac8SCy Schubert {
67885732ac8SCy Schubert 	if (!val)
67985732ac8SCy Schubert 		val = "";
68085732ac8SCy Schubert 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
68185732ac8SCy Schubert 						&val, error);
68285732ac8SCy Schubert }
68385732ac8SCy Schubert 
68485732ac8SCy Schubert 
68585732ac8SCy Schubert /**
686d4f2939cSRui Paulo  * wpas_dbus_handler_create_interface - Request registration of a network iface
687d4f2939cSRui Paulo  * @message: Pointer to incoming dbus message
688d4f2939cSRui Paulo  * @global: %wpa_supplicant global data structure
689d4f2939cSRui Paulo  * Returns: The object path of the new interface object,
690d4f2939cSRui Paulo  *          or a dbus error message with more information
691d4f2939cSRui Paulo  *
692d4f2939cSRui Paulo  * Handler function for "CreateInterface" method call. Handles requests
693d4f2939cSRui Paulo  * by dbus clients to register a network interface that wpa_supplicant
694d4f2939cSRui Paulo  * will manage.
695d4f2939cSRui Paulo  */
wpas_dbus_handler_create_interface(DBusMessage * message,struct wpa_global * global)696d4f2939cSRui Paulo DBusMessage * wpas_dbus_handler_create_interface(DBusMessage *message,
697d4f2939cSRui Paulo 						 struct wpa_global *global)
698d4f2939cSRui Paulo {
699d4f2939cSRui Paulo 	DBusMessageIter iter_dict;
700d4f2939cSRui Paulo 	DBusMessage *reply = NULL;
701d4f2939cSRui Paulo 	DBusMessageIter iter;
702d4f2939cSRui Paulo 	struct wpa_dbus_dict_entry entry;
703d4f2939cSRui Paulo 	char *driver = NULL;
704d4f2939cSRui Paulo 	char *ifname = NULL;
705d4f2939cSRui Paulo 	char *confname = NULL;
706d4f2939cSRui Paulo 	char *bridge_ifname = NULL;
707d4f2939cSRui Paulo 
708d4f2939cSRui Paulo 	dbus_message_iter_init(message, &iter);
709d4f2939cSRui Paulo 
710d4f2939cSRui Paulo 	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
711d4f2939cSRui Paulo 		goto error;
712d4f2939cSRui Paulo 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
713d4f2939cSRui Paulo 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
714d4f2939cSRui Paulo 			goto error;
7155b9c547cSRui Paulo 		if (os_strcmp(entry.key, "Driver") == 0 &&
7165b9c547cSRui Paulo 		    entry.type == DBUS_TYPE_STRING) {
7175b9c547cSRui Paulo 			os_free(driver);
718d4f2939cSRui Paulo 			driver = os_strdup(entry.str_value);
719d4f2939cSRui Paulo 			wpa_dbus_dict_entry_clear(&entry);
720d4f2939cSRui Paulo 			if (driver == NULL)
7215b9c547cSRui Paulo 				goto oom;
7225b9c547cSRui Paulo 		} else if (os_strcmp(entry.key, "Ifname") == 0 &&
7235b9c547cSRui Paulo 			   entry.type == DBUS_TYPE_STRING) {
7245b9c547cSRui Paulo 			os_free(ifname);
725d4f2939cSRui Paulo 			ifname = os_strdup(entry.str_value);
726d4f2939cSRui Paulo 			wpa_dbus_dict_entry_clear(&entry);
727d4f2939cSRui Paulo 			if (ifname == NULL)
7285b9c547cSRui Paulo 				goto oom;
7295b9c547cSRui Paulo 		} else if (os_strcmp(entry.key, "ConfigFile") == 0 &&
7305b9c547cSRui Paulo 			   entry.type == DBUS_TYPE_STRING) {
7315b9c547cSRui Paulo 			os_free(confname);
732d4f2939cSRui Paulo 			confname = os_strdup(entry.str_value);
733d4f2939cSRui Paulo 			wpa_dbus_dict_entry_clear(&entry);
734d4f2939cSRui Paulo 			if (confname == NULL)
7355b9c547cSRui Paulo 				goto oom;
7365b9c547cSRui Paulo 		} else if (os_strcmp(entry.key, "BridgeIfname") == 0 &&
7375b9c547cSRui Paulo 			   entry.type == DBUS_TYPE_STRING) {
7385b9c547cSRui Paulo 			os_free(bridge_ifname);
739d4f2939cSRui Paulo 			bridge_ifname = os_strdup(entry.str_value);
740d4f2939cSRui Paulo 			wpa_dbus_dict_entry_clear(&entry);
741d4f2939cSRui Paulo 			if (bridge_ifname == NULL)
7425b9c547cSRui Paulo 				goto oom;
743d4f2939cSRui Paulo 		} else {
744d4f2939cSRui Paulo 			wpa_dbus_dict_entry_clear(&entry);
745d4f2939cSRui Paulo 			goto error;
746d4f2939cSRui Paulo 		}
747d4f2939cSRui Paulo 	}
748d4f2939cSRui Paulo 
749d4f2939cSRui Paulo 	if (ifname == NULL)
750d4f2939cSRui Paulo 		goto error; /* Required Ifname argument missing */
751d4f2939cSRui Paulo 
752d4f2939cSRui Paulo 	/*
753d4f2939cSRui Paulo 	 * Try to get the wpa_supplicant record for this iface, return
754d4f2939cSRui Paulo 	 * an error if we already control it.
755d4f2939cSRui Paulo 	 */
756d4f2939cSRui Paulo 	if (wpa_supplicant_get_iface(global, ifname) != NULL) {
7575b9c547cSRui Paulo 		reply = dbus_message_new_error(
7585b9c547cSRui Paulo 			message, WPAS_DBUS_ERROR_IFACE_EXISTS,
7595b9c547cSRui Paulo 			"wpa_supplicant already controls this interface.");
760d4f2939cSRui Paulo 	} else {
761d4f2939cSRui Paulo 		struct wpa_supplicant *wpa_s;
762d4f2939cSRui Paulo 		struct wpa_interface iface;
7635b9c547cSRui Paulo 
764d4f2939cSRui Paulo 		os_memset(&iface, 0, sizeof(iface));
765d4f2939cSRui Paulo 		iface.driver = driver;
766d4f2939cSRui Paulo 		iface.ifname = ifname;
767d4f2939cSRui Paulo 		iface.confname = confname;
768d4f2939cSRui Paulo 		iface.bridge_ifname = bridge_ifname;
769d4f2939cSRui Paulo 		/* Otherwise, have wpa_supplicant attach to it. */
7705b9c547cSRui Paulo 		wpa_s = wpa_supplicant_add_iface(global, &iface, NULL);
771325151a3SRui Paulo 		if (wpa_s && wpa_s->dbus_new_path) {
772d4f2939cSRui Paulo 			const char *path = wpa_s->dbus_new_path;
7735b9c547cSRui Paulo 
774d4f2939cSRui Paulo 			reply = dbus_message_new_method_return(message);
775d4f2939cSRui Paulo 			dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH,
776d4f2939cSRui Paulo 						 &path, DBUS_TYPE_INVALID);
777d4f2939cSRui Paulo 		} else {
778d4f2939cSRui Paulo 			reply = wpas_dbus_error_unknown_error(
7795b9c547cSRui Paulo 				message,
7805b9c547cSRui Paulo 				"wpa_supplicant couldn't grab this interface.");
781d4f2939cSRui Paulo 		}
782d4f2939cSRui Paulo 	}
783d4f2939cSRui Paulo 
784d4f2939cSRui Paulo out:
785d4f2939cSRui Paulo 	os_free(driver);
786d4f2939cSRui Paulo 	os_free(ifname);
787d4f2939cSRui Paulo 	os_free(confname);
788d4f2939cSRui Paulo 	os_free(bridge_ifname);
789d4f2939cSRui Paulo 	return reply;
790d4f2939cSRui Paulo 
791d4f2939cSRui Paulo error:
792d4f2939cSRui Paulo 	reply = wpas_dbus_error_invalid_args(message, NULL);
793d4f2939cSRui Paulo 	goto out;
7945b9c547cSRui Paulo oom:
7955b9c547cSRui Paulo 	reply = wpas_dbus_error_no_memory(message);
7965b9c547cSRui Paulo 	goto out;
797d4f2939cSRui Paulo }
798d4f2939cSRui Paulo 
799d4f2939cSRui Paulo 
800d4f2939cSRui Paulo /**
801d4f2939cSRui Paulo  * wpas_dbus_handler_remove_interface - Request deregistration of an interface
802d4f2939cSRui Paulo  * @message: Pointer to incoming dbus message
803d4f2939cSRui Paulo  * @global: wpa_supplicant global data structure
804d4f2939cSRui Paulo  * Returns: a dbus message containing a UINT32 indicating success (1) or
805d4f2939cSRui Paulo  *          failure (0), or returns a dbus error message with more information
806d4f2939cSRui Paulo  *
807d4f2939cSRui Paulo  * Handler function for "removeInterface" method call.  Handles requests
808d4f2939cSRui Paulo  * by dbus clients to deregister a network interface that wpa_supplicant
809d4f2939cSRui Paulo  * currently manages.
810d4f2939cSRui Paulo  */
wpas_dbus_handler_remove_interface(DBusMessage * message,struct wpa_global * global)811d4f2939cSRui Paulo DBusMessage * wpas_dbus_handler_remove_interface(DBusMessage *message,
812d4f2939cSRui Paulo 						 struct wpa_global *global)
813d4f2939cSRui Paulo {
814d4f2939cSRui Paulo 	struct wpa_supplicant *wpa_s;
815d4f2939cSRui Paulo 	char *path;
816d4f2939cSRui Paulo 	DBusMessage *reply = NULL;
817d4f2939cSRui Paulo 
818d4f2939cSRui Paulo 	dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path,
819d4f2939cSRui Paulo 			      DBUS_TYPE_INVALID);
820d4f2939cSRui Paulo 
821d4f2939cSRui Paulo 	wpa_s = get_iface_by_dbus_path(global, path);
822d4f2939cSRui Paulo 	if (wpa_s == NULL)
823d4f2939cSRui Paulo 		reply = wpas_dbus_error_iface_unknown(message);
824d4f2939cSRui Paulo 	else if (wpa_supplicant_remove_iface(global, wpa_s, 0)) {
825d4f2939cSRui Paulo 		reply = wpas_dbus_error_unknown_error(
8265b9c547cSRui Paulo 			message,
8275b9c547cSRui Paulo 			"wpa_supplicant couldn't remove this interface.");
828d4f2939cSRui Paulo 	}
829d4f2939cSRui Paulo 
830d4f2939cSRui Paulo 	return reply;
831d4f2939cSRui Paulo }
832d4f2939cSRui Paulo 
833d4f2939cSRui Paulo 
834d4f2939cSRui Paulo /**
835d4f2939cSRui Paulo  * wpas_dbus_handler_get_interface - Get the object path for an interface name
836d4f2939cSRui Paulo  * @message: Pointer to incoming dbus message
837d4f2939cSRui Paulo  * @global: %wpa_supplicant global data structure
838d4f2939cSRui Paulo  * Returns: The object path of the interface object,
839d4f2939cSRui Paulo  *          or a dbus error message with more information
840d4f2939cSRui Paulo  *
841d4f2939cSRui Paulo  * Handler function for "getInterface" method call.
842d4f2939cSRui Paulo  */
wpas_dbus_handler_get_interface(DBusMessage * message,struct wpa_global * global)843d4f2939cSRui Paulo DBusMessage * wpas_dbus_handler_get_interface(DBusMessage *message,
844d4f2939cSRui Paulo 					      struct wpa_global *global)
845d4f2939cSRui Paulo {
846d4f2939cSRui Paulo 	DBusMessage *reply = NULL;
847d4f2939cSRui Paulo 	const char *ifname;
848d4f2939cSRui Paulo 	const char *path;
849d4f2939cSRui Paulo 	struct wpa_supplicant *wpa_s;
850d4f2939cSRui Paulo 
851d4f2939cSRui Paulo 	dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &ifname,
852d4f2939cSRui Paulo 			      DBUS_TYPE_INVALID);
853d4f2939cSRui Paulo 
854d4f2939cSRui Paulo 	wpa_s = wpa_supplicant_get_iface(global, ifname);
855325151a3SRui Paulo 	if (wpa_s == NULL || wpa_s->dbus_new_path == NULL)
856d4f2939cSRui Paulo 		return wpas_dbus_error_iface_unknown(message);
857d4f2939cSRui Paulo 
858d4f2939cSRui Paulo 	path = wpa_s->dbus_new_path;
859d4f2939cSRui Paulo 	reply = dbus_message_new_method_return(message);
860d4f2939cSRui Paulo 	if (reply == NULL)
8615b9c547cSRui Paulo 		return wpas_dbus_error_no_memory(message);
862d4f2939cSRui Paulo 	if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
863d4f2939cSRui Paulo 				      DBUS_TYPE_INVALID)) {
864d4f2939cSRui Paulo 		dbus_message_unref(reply);
8655b9c547cSRui Paulo 		return wpas_dbus_error_no_memory(message);
866d4f2939cSRui Paulo 	}
867d4f2939cSRui Paulo 
868d4f2939cSRui Paulo 	return reply;
869d4f2939cSRui Paulo }
870d4f2939cSRui Paulo 
871d4f2939cSRui Paulo 
872d4f2939cSRui Paulo /**
873d4f2939cSRui Paulo  * wpas_dbus_getter_debug_level - Get debug level
874d4f2939cSRui Paulo  * @iter: Pointer to incoming dbus message iter
875d4f2939cSRui Paulo  * @error: Location to store error on failure
876d4f2939cSRui Paulo  * @user_data: Function specific data
877d4f2939cSRui Paulo  * Returns: TRUE on success, FALSE on failure
878d4f2939cSRui Paulo  *
879d4f2939cSRui Paulo  * Getter for "DebugLevel" property.
880d4f2939cSRui Paulo  */
wpas_dbus_getter_debug_level(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)881780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_debug_level(
882780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
883780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
884d4f2939cSRui Paulo {
885d4f2939cSRui Paulo 	const char *str;
886d4f2939cSRui Paulo 	int idx = wpa_debug_level;
887d4f2939cSRui Paulo 
888d4f2939cSRui Paulo 	if (idx < 0)
889d4f2939cSRui Paulo 		idx = 0;
890d4f2939cSRui Paulo 	if (idx > 5)
891d4f2939cSRui Paulo 		idx = 5;
892d4f2939cSRui Paulo 	str = debug_strings[idx];
893d4f2939cSRui Paulo 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
894d4f2939cSRui Paulo 						&str, error);
895d4f2939cSRui Paulo }
896d4f2939cSRui Paulo 
897d4f2939cSRui Paulo 
898d4f2939cSRui Paulo /**
899d4f2939cSRui Paulo  * wpas_dbus_getter_debug_timestamp - Get debug timestamp
900d4f2939cSRui Paulo  * @iter: Pointer to incoming dbus message iter
901d4f2939cSRui Paulo  * @error: Location to store error on failure
902d4f2939cSRui Paulo  * @user_data: Function specific data
903d4f2939cSRui Paulo  * Returns: TRUE on success, FALSE on failure
904d4f2939cSRui Paulo  *
905d4f2939cSRui Paulo  * Getter for "DebugTimestamp" property.
906d4f2939cSRui Paulo  */
wpas_dbus_getter_debug_timestamp(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)907780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_debug_timestamp(
908780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
909780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
910d4f2939cSRui Paulo {
911d4f2939cSRui Paulo 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
912d4f2939cSRui Paulo 						&wpa_debug_timestamp, error);
913d4f2939cSRui Paulo 
914d4f2939cSRui Paulo }
915d4f2939cSRui Paulo 
916d4f2939cSRui Paulo 
917d4f2939cSRui Paulo /**
918d4f2939cSRui Paulo  * wpas_dbus_getter_debug_show_keys - Get debug show keys
919d4f2939cSRui Paulo  * @iter: Pointer to incoming dbus message iter
920d4f2939cSRui Paulo  * @error: Location to store error on failure
921d4f2939cSRui Paulo  * @user_data: Function specific data
922d4f2939cSRui Paulo  * Returns: TRUE on success, FALSE on failure
923d4f2939cSRui Paulo  *
924d4f2939cSRui Paulo  * Getter for "DebugShowKeys" property.
925d4f2939cSRui Paulo  */
wpas_dbus_getter_debug_show_keys(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)926780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_debug_show_keys(
927780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
928780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
929d4f2939cSRui Paulo {
930d4f2939cSRui Paulo 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
931d4f2939cSRui Paulo 						&wpa_debug_show_keys, error);
932d4f2939cSRui Paulo 
933d4f2939cSRui Paulo }
934d4f2939cSRui Paulo 
935d4f2939cSRui Paulo /**
936d4f2939cSRui Paulo  * wpas_dbus_setter_debug_level - Set debug level
937d4f2939cSRui Paulo  * @iter: Pointer to incoming dbus message iter
938d4f2939cSRui Paulo  * @error: Location to store error on failure
939d4f2939cSRui Paulo  * @user_data: Function specific data
940d4f2939cSRui Paulo  * Returns: TRUE on success, FALSE on failure
941d4f2939cSRui Paulo  *
942d4f2939cSRui Paulo  * Setter for "DebugLevel" property.
943d4f2939cSRui Paulo  */
wpas_dbus_setter_debug_level(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)944780fb4a2SCy Schubert dbus_bool_t wpas_dbus_setter_debug_level(
945780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
946780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
947d4f2939cSRui Paulo {
948d4f2939cSRui Paulo 	struct wpa_global *global = user_data;
949d4f2939cSRui Paulo 	const char *str = NULL;
950d4f2939cSRui Paulo 	int i, val = -1;
951d4f2939cSRui Paulo 
952d4f2939cSRui Paulo 	if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
953d4f2939cSRui Paulo 					      &str))
954d4f2939cSRui Paulo 		return FALSE;
955d4f2939cSRui Paulo 
956d4f2939cSRui Paulo 	for (i = 0; debug_strings[i]; i++)
957d4f2939cSRui Paulo 		if (os_strcmp(debug_strings[i], str) == 0) {
958d4f2939cSRui Paulo 			val = i;
959d4f2939cSRui Paulo 			break;
960d4f2939cSRui Paulo 		}
961d4f2939cSRui Paulo 
962d4f2939cSRui Paulo 	if (val < 0 ||
963d4f2939cSRui Paulo 	    wpa_supplicant_set_debug_params(global, val, wpa_debug_timestamp,
964d4f2939cSRui Paulo 					    wpa_debug_show_keys)) {
9655b9c547cSRui Paulo 		dbus_set_error_const(error, DBUS_ERROR_FAILED,
9665b9c547cSRui Paulo 				     "wrong debug level value");
967d4f2939cSRui Paulo 		return FALSE;
968d4f2939cSRui Paulo 	}
969d4f2939cSRui Paulo 
970d4f2939cSRui Paulo 	return TRUE;
971d4f2939cSRui Paulo }
972d4f2939cSRui Paulo 
973d4f2939cSRui Paulo 
974d4f2939cSRui Paulo /**
975d4f2939cSRui Paulo  * wpas_dbus_setter_debug_timestamp - Set debug timestamp
976d4f2939cSRui Paulo  * @iter: Pointer to incoming dbus message iter
977d4f2939cSRui Paulo  * @error: Location to store error on failure
978d4f2939cSRui Paulo  * @user_data: Function specific data
979d4f2939cSRui Paulo  * Returns: TRUE on success, FALSE on failure
980d4f2939cSRui Paulo  *
981d4f2939cSRui Paulo  * Setter for "DebugTimestamp" property.
982d4f2939cSRui Paulo  */
wpas_dbus_setter_debug_timestamp(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)983780fb4a2SCy Schubert dbus_bool_t wpas_dbus_setter_debug_timestamp(
984780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
985780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
986d4f2939cSRui Paulo {
987d4f2939cSRui Paulo 	struct wpa_global *global = user_data;
988d4f2939cSRui Paulo 	dbus_bool_t val;
989d4f2939cSRui Paulo 
990d4f2939cSRui Paulo 	if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
991d4f2939cSRui Paulo 					      &val))
992d4f2939cSRui Paulo 		return FALSE;
993d4f2939cSRui Paulo 
994d4f2939cSRui Paulo 	wpa_supplicant_set_debug_params(global, wpa_debug_level, val ? 1 : 0,
995d4f2939cSRui Paulo 					wpa_debug_show_keys);
996d4f2939cSRui Paulo 	return TRUE;
997d4f2939cSRui Paulo }
998d4f2939cSRui Paulo 
999d4f2939cSRui Paulo 
1000d4f2939cSRui Paulo /**
1001d4f2939cSRui Paulo  * wpas_dbus_setter_debug_show_keys - Set debug show keys
1002d4f2939cSRui Paulo  * @iter: Pointer to incoming dbus message iter
1003d4f2939cSRui Paulo  * @error: Location to store error on failure
1004d4f2939cSRui Paulo  * @user_data: Function specific data
1005d4f2939cSRui Paulo  * Returns: TRUE on success, FALSE on failure
1006d4f2939cSRui Paulo  *
1007d4f2939cSRui Paulo  * Setter for "DebugShowKeys" property.
1008d4f2939cSRui Paulo  */
wpas_dbus_setter_debug_show_keys(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)1009780fb4a2SCy Schubert dbus_bool_t wpas_dbus_setter_debug_show_keys(
1010780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
1011780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
1012d4f2939cSRui Paulo {
1013d4f2939cSRui Paulo 	struct wpa_global *global = user_data;
1014d4f2939cSRui Paulo 	dbus_bool_t val;
1015d4f2939cSRui Paulo 
1016d4f2939cSRui Paulo 	if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
1017d4f2939cSRui Paulo 					      &val))
1018d4f2939cSRui Paulo 		return FALSE;
1019d4f2939cSRui Paulo 
1020d4f2939cSRui Paulo 	wpa_supplicant_set_debug_params(global, wpa_debug_level,
1021d4f2939cSRui Paulo 					wpa_debug_timestamp,
1022d4f2939cSRui Paulo 					val ? 1 : 0);
1023d4f2939cSRui Paulo 	return TRUE;
1024d4f2939cSRui Paulo }
1025d4f2939cSRui Paulo 
1026d4f2939cSRui Paulo 
1027d4f2939cSRui Paulo /**
1028d4f2939cSRui Paulo  * wpas_dbus_getter_interfaces - Request registered interfaces list
1029d4f2939cSRui Paulo  * @iter: Pointer to incoming dbus message iter
1030d4f2939cSRui Paulo  * @error: Location to store error on failure
1031d4f2939cSRui Paulo  * @user_data: Function specific data
1032d4f2939cSRui Paulo  * Returns: TRUE on success, FALSE on failure
1033d4f2939cSRui Paulo  *
1034d4f2939cSRui Paulo  * Getter for "Interfaces" property. Handles requests
1035d4f2939cSRui Paulo  * by dbus clients to return list of registered interfaces objects
1036d4f2939cSRui Paulo  * paths
1037d4f2939cSRui Paulo  */
wpas_dbus_getter_interfaces(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)1038780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_interfaces(
1039780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
1040780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
1041d4f2939cSRui Paulo {
1042d4f2939cSRui Paulo 	struct wpa_global *global = user_data;
1043d4f2939cSRui Paulo 	struct wpa_supplicant *wpa_s;
1044d4f2939cSRui Paulo 	const char **paths;
1045d4f2939cSRui Paulo 	unsigned int i = 0, num = 0;
1046d4f2939cSRui Paulo 	dbus_bool_t success;
1047d4f2939cSRui Paulo 
1048325151a3SRui Paulo 	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
1049325151a3SRui Paulo 		if (wpa_s->dbus_new_path)
1050d4f2939cSRui Paulo 			num++;
1051325151a3SRui Paulo 	}
1052d4f2939cSRui Paulo 
1053d4f2939cSRui Paulo 	paths = os_calloc(num, sizeof(char *));
1054d4f2939cSRui Paulo 	if (!paths) {
1055d4f2939cSRui Paulo 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1056d4f2939cSRui Paulo 		return FALSE;
1057d4f2939cSRui Paulo 	}
1058d4f2939cSRui Paulo 
1059325151a3SRui Paulo 	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
1060325151a3SRui Paulo 		if (wpa_s->dbus_new_path)
1061d4f2939cSRui Paulo 			paths[i++] = wpa_s->dbus_new_path;
1062325151a3SRui Paulo 	}
1063d4f2939cSRui Paulo 
1064d4f2939cSRui Paulo 	success = wpas_dbus_simple_array_property_getter(iter,
1065d4f2939cSRui Paulo 							 DBUS_TYPE_OBJECT_PATH,
1066d4f2939cSRui Paulo 							 paths, num, error);
1067d4f2939cSRui Paulo 
1068d4f2939cSRui Paulo 	os_free(paths);
1069d4f2939cSRui Paulo 	return success;
1070d4f2939cSRui Paulo }
1071d4f2939cSRui Paulo 
1072d4f2939cSRui Paulo 
1073d4f2939cSRui Paulo /**
1074d4f2939cSRui Paulo  * wpas_dbus_getter_eap_methods - Request supported EAP methods list
1075d4f2939cSRui Paulo  * @iter: Pointer to incoming dbus message iter
1076d4f2939cSRui Paulo  * @error: Location to store error on failure
1077d4f2939cSRui Paulo  * @user_data: Function specific data
1078d4f2939cSRui Paulo  * Returns: TRUE on success, FALSE on failure
1079d4f2939cSRui Paulo  *
1080d4f2939cSRui Paulo  * Getter for "EapMethods" property. Handles requests
1081d4f2939cSRui Paulo  * by dbus clients to return list of strings with supported EAP methods
1082d4f2939cSRui Paulo  */
wpas_dbus_getter_eap_methods(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)1083780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_eap_methods(
1084780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
1085780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
1086d4f2939cSRui Paulo {
1087d4f2939cSRui Paulo 	char **eap_methods;
1088d4f2939cSRui Paulo 	size_t num_items = 0;
1089d4f2939cSRui Paulo 	dbus_bool_t success;
1090d4f2939cSRui Paulo 
1091d4f2939cSRui Paulo 	eap_methods = eap_get_names_as_string_array(&num_items);
1092d4f2939cSRui Paulo 	if (!eap_methods) {
1093d4f2939cSRui Paulo 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1094d4f2939cSRui Paulo 		return FALSE;
1095d4f2939cSRui Paulo 	}
1096d4f2939cSRui Paulo 
1097d4f2939cSRui Paulo 	success = wpas_dbus_simple_array_property_getter(iter,
1098d4f2939cSRui Paulo 							 DBUS_TYPE_STRING,
1099d4f2939cSRui Paulo 							 eap_methods,
1100d4f2939cSRui Paulo 							 num_items, error);
1101d4f2939cSRui Paulo 
1102d4f2939cSRui Paulo 	while (num_items)
1103d4f2939cSRui Paulo 		os_free(eap_methods[--num_items]);
1104d4f2939cSRui Paulo 	os_free(eap_methods);
1105d4f2939cSRui Paulo 	return success;
1106d4f2939cSRui Paulo }
1107d4f2939cSRui Paulo 
1108d4f2939cSRui Paulo 
1109d4f2939cSRui Paulo /**
1110d4f2939cSRui Paulo  * wpas_dbus_getter_global_capabilities - Request supported global capabilities
1111d4f2939cSRui Paulo  * @iter: Pointer to incoming dbus message iter
1112d4f2939cSRui Paulo  * @error: Location to store error on failure
1113d4f2939cSRui Paulo  * @user_data: Function specific data
1114d4f2939cSRui Paulo  * Returns: TRUE on success, FALSE on failure
1115d4f2939cSRui Paulo  *
1116d4f2939cSRui Paulo  * Getter for "Capabilities" property. Handles requests by dbus clients to
1117d4f2939cSRui Paulo  * return a list of strings with supported capabilities like AP, RSN IBSS,
1118d4f2939cSRui Paulo  * and P2P that are determined at compile time.
1119d4f2939cSRui Paulo  */
wpas_dbus_getter_global_capabilities(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)1120780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_global_capabilities(
1121780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
1122780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
1123d4f2939cSRui Paulo {
1124c1d255d3SCy Schubert 	const char *capabilities[13];
1125d4f2939cSRui Paulo 	size_t num_items = 0;
112685732ac8SCy Schubert 	struct wpa_global *global = user_data;
112785732ac8SCy Schubert 	struct wpa_supplicant *wpa_s;
1128c1d255d3SCy Schubert #ifdef CONFIG_FILS
112985732ac8SCy Schubert 	int fils_supported = 0, fils_sk_pfs_supported = 0;
1130c1d255d3SCy Schubert #endif /* CONFIG_FILS */
1131c1d255d3SCy Schubert 	int ext_key_id_supported = 0;
113285732ac8SCy Schubert 
113385732ac8SCy Schubert 	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
1134c1d255d3SCy Schubert #ifdef CONFIG_FILS
113585732ac8SCy Schubert 		if (wpa_is_fils_supported(wpa_s))
113685732ac8SCy Schubert 			fils_supported = 1;
113785732ac8SCy Schubert 		if (wpa_is_fils_sk_pfs_supported(wpa_s))
113885732ac8SCy Schubert 			fils_sk_pfs_supported = 1;
113985732ac8SCy Schubert #endif /* CONFIG_FILS */
1140c1d255d3SCy Schubert 		if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_EXTENDED_KEY_ID)
1141c1d255d3SCy Schubert 			ext_key_id_supported = 1;
1142c1d255d3SCy Schubert 	}
1143d4f2939cSRui Paulo 
1144d4f2939cSRui Paulo #ifdef CONFIG_AP
1145d4f2939cSRui Paulo 	capabilities[num_items++] = "ap";
1146d4f2939cSRui Paulo #endif /* CONFIG_AP */
1147d4f2939cSRui Paulo #ifdef CONFIG_IBSS_RSN
1148d4f2939cSRui Paulo 	capabilities[num_items++] = "ibss-rsn";
1149d4f2939cSRui Paulo #endif /* CONFIG_IBSS_RSN */
1150d4f2939cSRui Paulo #ifdef CONFIG_P2P
1151d4f2939cSRui Paulo 	capabilities[num_items++] = "p2p";
1152d4f2939cSRui Paulo #endif /* CONFIG_P2P */
1153d4f2939cSRui Paulo #ifdef CONFIG_INTERWORKING
1154d4f2939cSRui Paulo 	capabilities[num_items++] = "interworking";
1155d4f2939cSRui Paulo #endif /* CONFIG_INTERWORKING */
115685732ac8SCy Schubert 	capabilities[num_items++] = "pmf";
115785732ac8SCy Schubert #ifdef CONFIG_MESH
115885732ac8SCy Schubert 	capabilities[num_items++] = "mesh";
115985732ac8SCy Schubert #endif /* CONFIG_MESH */
116085732ac8SCy Schubert #ifdef CONFIG_FILS
116185732ac8SCy Schubert 	if (fils_supported)
116285732ac8SCy Schubert 		capabilities[num_items++] = "fils";
116385732ac8SCy Schubert 	if (fils_sk_pfs_supported)
116485732ac8SCy Schubert 		capabilities[num_items++] = "fils_sk_pfs";
116585732ac8SCy Schubert #endif /* CONFIG_FILS */
116685732ac8SCy Schubert #ifdef CONFIG_IEEE80211R
116785732ac8SCy Schubert 	capabilities[num_items++] = "ft";
116885732ac8SCy Schubert #endif /* CONFIG_IEEE80211R */
116985732ac8SCy Schubert #ifdef CONFIG_SHA384
117085732ac8SCy Schubert 	capabilities[num_items++] = "sha384";
117185732ac8SCy Schubert #endif /* CONFIG_SHA384 */
1172c1d255d3SCy Schubert #ifdef CONFIG_OWE
1173c1d255d3SCy Schubert 	capabilities[num_items++] = "owe";
1174c1d255d3SCy Schubert #endif /* CONFIG_OWE */
1175c1d255d3SCy Schubert #ifdef CONFIG_SUITEB192
1176c1d255d3SCy Schubert 	capabilities[num_items++] = "suiteb192";
1177c1d255d3SCy Schubert #endif /* CONFIG_SUITEB192 */
1178c1d255d3SCy Schubert 	if (ext_key_id_supported)
1179c1d255d3SCy Schubert 		capabilities[num_items++] = "extended_key_id";
1180d4f2939cSRui Paulo 
1181d4f2939cSRui Paulo 	return wpas_dbus_simple_array_property_getter(iter,
1182d4f2939cSRui Paulo 						      DBUS_TYPE_STRING,
1183d4f2939cSRui Paulo 						      capabilities,
1184d4f2939cSRui Paulo 						      num_items, error);
1185d4f2939cSRui Paulo }
1186d4f2939cSRui Paulo 
1187d4f2939cSRui Paulo 
wpas_dbus_get_scan_type(DBusMessage * message,DBusMessageIter * var,char ** type,DBusMessage ** reply)1188d4f2939cSRui Paulo static int wpas_dbus_get_scan_type(DBusMessage *message, DBusMessageIter *var,
1189d4f2939cSRui Paulo 				   char **type, DBusMessage **reply)
1190d4f2939cSRui Paulo {
1191d4f2939cSRui Paulo 	if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_STRING) {
11925b9c547cSRui Paulo 		wpa_printf(MSG_DEBUG, "%s[dbus]: Type must be a string",
11935b9c547cSRui Paulo 			   __func__);
1194d4f2939cSRui Paulo 		*reply = wpas_dbus_error_invalid_args(
1195d4f2939cSRui Paulo 			message, "Wrong Type value type. String required");
1196d4f2939cSRui Paulo 		return -1;
1197d4f2939cSRui Paulo 	}
1198d4f2939cSRui Paulo 	dbus_message_iter_get_basic(var, type);
1199d4f2939cSRui Paulo 	return 0;
1200d4f2939cSRui Paulo }
1201d4f2939cSRui Paulo 
1202d4f2939cSRui Paulo 
wpas_dbus_get_scan_ssids(DBusMessage * message,DBusMessageIter * var,struct wpa_driver_scan_params * params,DBusMessage ** reply)1203d4f2939cSRui Paulo static int wpas_dbus_get_scan_ssids(DBusMessage *message, DBusMessageIter *var,
1204d4f2939cSRui Paulo 				    struct wpa_driver_scan_params *params,
1205d4f2939cSRui Paulo 				    DBusMessage **reply)
1206d4f2939cSRui Paulo {
1207d4f2939cSRui Paulo 	struct wpa_driver_scan_ssid *ssids = params->ssids;
1208d4f2939cSRui Paulo 	size_t ssids_num = 0;
1209d4f2939cSRui Paulo 	u8 *ssid;
1210d4f2939cSRui Paulo 	DBusMessageIter array_iter, sub_array_iter;
1211d4f2939cSRui Paulo 	char *val;
1212d4f2939cSRui Paulo 	int len;
1213d4f2939cSRui Paulo 
1214d4f2939cSRui Paulo 	if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
12155b9c547cSRui Paulo 		wpa_printf(MSG_DEBUG,
12165b9c547cSRui Paulo 			   "%s[dbus]: ssids must be an array of arrays of bytes",
12175b9c547cSRui Paulo 			   __func__);
1218d4f2939cSRui Paulo 		*reply = wpas_dbus_error_invalid_args(
12195b9c547cSRui Paulo 			message,
12205b9c547cSRui Paulo 			"Wrong SSIDs value type. Array of arrays of bytes required");
1221d4f2939cSRui Paulo 		return -1;
1222d4f2939cSRui Paulo 	}
1223d4f2939cSRui Paulo 
1224d4f2939cSRui Paulo 	dbus_message_iter_recurse(var, &array_iter);
1225d4f2939cSRui Paulo 
1226d4f2939cSRui Paulo 	if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY ||
12275b9c547cSRui Paulo 	    dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_BYTE) {
12285b9c547cSRui Paulo 		wpa_printf(MSG_DEBUG,
12295b9c547cSRui Paulo 			   "%s[dbus]: ssids must be an array of arrays of bytes",
12305b9c547cSRui Paulo 			   __func__);
1231d4f2939cSRui Paulo 		*reply = wpas_dbus_error_invalid_args(
12325b9c547cSRui Paulo 			message,
12335b9c547cSRui Paulo 			"Wrong SSIDs value type. Array of arrays of bytes required");
1234d4f2939cSRui Paulo 		return -1;
1235d4f2939cSRui Paulo 	}
1236d4f2939cSRui Paulo 
12375b9c547cSRui Paulo 	while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_ARRAY) {
1238d4f2939cSRui Paulo 		if (ssids_num >= WPAS_MAX_SCAN_SSIDS) {
12395b9c547cSRui Paulo 			wpa_printf(MSG_DEBUG,
12405b9c547cSRui Paulo 				   "%s[dbus]: Too many ssids specified on scan dbus call",
12415b9c547cSRui Paulo 				   __func__);
1242d4f2939cSRui Paulo 			*reply = wpas_dbus_error_invalid_args(
12435b9c547cSRui Paulo 				message,
12445b9c547cSRui Paulo 				"Too many ssids specified. Specify at most four");
1245d4f2939cSRui Paulo 			return -1;
1246d4f2939cSRui Paulo 		}
1247d4f2939cSRui Paulo 
1248d4f2939cSRui Paulo 		dbus_message_iter_recurse(&array_iter, &sub_array_iter);
1249d4f2939cSRui Paulo 
1250d4f2939cSRui Paulo 		dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len);
1251d4f2939cSRui Paulo 
1252325151a3SRui Paulo 		if (len > SSID_MAX_LEN) {
1253d4f2939cSRui Paulo 			wpa_printf(MSG_DEBUG,
12545b9c547cSRui Paulo 				   "%s[dbus]: SSID too long (len=%d max_len=%d)",
1255325151a3SRui Paulo 				   __func__, len, SSID_MAX_LEN);
1256d4f2939cSRui Paulo 			*reply = wpas_dbus_error_invalid_args(
1257d4f2939cSRui Paulo 				message, "Invalid SSID: too long");
1258d4f2939cSRui Paulo 			return -1;
1259d4f2939cSRui Paulo 		}
1260d4f2939cSRui Paulo 
1261d4f2939cSRui Paulo 		if (len != 0) {
126285732ac8SCy Schubert 			ssid = os_memdup(val, len);
1263d4f2939cSRui Paulo 			if (ssid == NULL) {
12645b9c547cSRui Paulo 				*reply = wpas_dbus_error_no_memory(message);
1265d4f2939cSRui Paulo 				return -1;
1266d4f2939cSRui Paulo 			}
1267d4f2939cSRui Paulo 		} else {
1268d4f2939cSRui Paulo 			/* Allow zero-length SSIDs */
1269d4f2939cSRui Paulo 			ssid = NULL;
1270d4f2939cSRui Paulo 		}
1271d4f2939cSRui Paulo 
1272d4f2939cSRui Paulo 		ssids[ssids_num].ssid = ssid;
1273d4f2939cSRui Paulo 		ssids[ssids_num].ssid_len = len;
1274d4f2939cSRui Paulo 
1275d4f2939cSRui Paulo 		dbus_message_iter_next(&array_iter);
1276d4f2939cSRui Paulo 		ssids_num++;
1277d4f2939cSRui Paulo 	}
1278d4f2939cSRui Paulo 
1279d4f2939cSRui Paulo 	params->num_ssids = ssids_num;
1280d4f2939cSRui Paulo 	return 0;
1281d4f2939cSRui Paulo }
1282d4f2939cSRui Paulo 
1283d4f2939cSRui Paulo 
wpas_dbus_get_scan_ies(DBusMessage * message,DBusMessageIter * var,struct wpa_driver_scan_params * params,DBusMessage ** reply)1284d4f2939cSRui Paulo static int wpas_dbus_get_scan_ies(DBusMessage *message, DBusMessageIter *var,
1285d4f2939cSRui Paulo 				  struct wpa_driver_scan_params *params,
1286d4f2939cSRui Paulo 				  DBusMessage **reply)
1287d4f2939cSRui Paulo {
1288d4f2939cSRui Paulo 	u8 *ies = NULL, *nies;
1289c1d255d3SCy Schubert 	size_t ies_len = 0;
1290d4f2939cSRui Paulo 	DBusMessageIter array_iter, sub_array_iter;
1291d4f2939cSRui Paulo 	char *val;
1292d4f2939cSRui Paulo 	int len;
1293d4f2939cSRui Paulo 
1294d4f2939cSRui Paulo 	if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
12955b9c547cSRui Paulo 		wpa_printf(MSG_DEBUG,
12965b9c547cSRui Paulo 			   "%s[dbus]: ies must be an array of arrays of bytes",
12975b9c547cSRui Paulo 			   __func__);
1298d4f2939cSRui Paulo 		*reply = wpas_dbus_error_invalid_args(
12995b9c547cSRui Paulo 			message,
13005b9c547cSRui Paulo 			"Wrong IEs value type. Array of arrays of bytes required");
1301d4f2939cSRui Paulo 		return -1;
1302d4f2939cSRui Paulo 	}
1303d4f2939cSRui Paulo 
1304d4f2939cSRui Paulo 	dbus_message_iter_recurse(var, &array_iter);
1305d4f2939cSRui Paulo 
1306d4f2939cSRui Paulo 	if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY ||
13075b9c547cSRui Paulo 	    dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_BYTE) {
13085b9c547cSRui Paulo 		wpa_printf(MSG_DEBUG,
13095b9c547cSRui Paulo 			   "%s[dbus]: ies must be an array of arrays of bytes",
13105b9c547cSRui Paulo 			   __func__);
1311d4f2939cSRui Paulo 		*reply = wpas_dbus_error_invalid_args(
1312d4f2939cSRui Paulo 			message, "Wrong IEs value type. Array required");
1313d4f2939cSRui Paulo 		return -1;
1314d4f2939cSRui Paulo 	}
1315d4f2939cSRui Paulo 
13165b9c547cSRui Paulo 	while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_ARRAY) {
1317d4f2939cSRui Paulo 		dbus_message_iter_recurse(&array_iter, &sub_array_iter);
1318d4f2939cSRui Paulo 
1319d4f2939cSRui Paulo 		dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len);
1320c1d255d3SCy Schubert 		if (len <= 0) {
1321d4f2939cSRui Paulo 			dbus_message_iter_next(&array_iter);
1322d4f2939cSRui Paulo 			continue;
1323d4f2939cSRui Paulo 		}
1324d4f2939cSRui Paulo 
1325d4f2939cSRui Paulo 		nies = os_realloc(ies, ies_len + len);
1326d4f2939cSRui Paulo 		if (nies == NULL) {
1327d4f2939cSRui Paulo 			os_free(ies);
13285b9c547cSRui Paulo 			*reply = wpas_dbus_error_no_memory(message);
1329d4f2939cSRui Paulo 			return -1;
1330d4f2939cSRui Paulo 		}
1331d4f2939cSRui Paulo 		ies = nies;
1332d4f2939cSRui Paulo 		os_memcpy(ies + ies_len, val, len);
1333d4f2939cSRui Paulo 		ies_len += len;
1334d4f2939cSRui Paulo 
1335d4f2939cSRui Paulo 		dbus_message_iter_next(&array_iter);
1336d4f2939cSRui Paulo 	}
1337d4f2939cSRui Paulo 
1338d4f2939cSRui Paulo 	params->extra_ies = ies;
1339d4f2939cSRui Paulo 	params->extra_ies_len = ies_len;
1340d4f2939cSRui Paulo 	return 0;
1341d4f2939cSRui Paulo }
1342d4f2939cSRui Paulo 
1343d4f2939cSRui Paulo 
wpas_dbus_get_scan_channels(DBusMessage * message,DBusMessageIter * var,struct wpa_driver_scan_params * params,DBusMessage ** reply)1344d4f2939cSRui Paulo static int wpas_dbus_get_scan_channels(DBusMessage *message,
1345d4f2939cSRui Paulo 				       DBusMessageIter *var,
1346d4f2939cSRui Paulo 				       struct wpa_driver_scan_params *params,
1347d4f2939cSRui Paulo 				       DBusMessage **reply)
1348d4f2939cSRui Paulo {
1349d4f2939cSRui Paulo 	DBusMessageIter array_iter, sub_array_iter;
1350d4f2939cSRui Paulo 	int *freqs = NULL, *nfreqs;
1351c1d255d3SCy Schubert 	size_t freqs_num = 0;
1352d4f2939cSRui Paulo 
1353d4f2939cSRui Paulo 	if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
13545b9c547cSRui Paulo 		wpa_printf(MSG_DEBUG,
13555b9c547cSRui Paulo 			   "%s[dbus]: Channels must be an array of structs",
13565b9c547cSRui Paulo 			   __func__);
1357d4f2939cSRui Paulo 		*reply = wpas_dbus_error_invalid_args(
13585b9c547cSRui Paulo 			message,
13595b9c547cSRui Paulo 			"Wrong Channels value type. Array of structs required");
1360d4f2939cSRui Paulo 		return -1;
1361d4f2939cSRui Paulo 	}
1362d4f2939cSRui Paulo 
1363d4f2939cSRui Paulo 	dbus_message_iter_recurse(var, &array_iter);
1364d4f2939cSRui Paulo 
1365d4f2939cSRui Paulo 	if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_STRUCT) {
1366d4f2939cSRui Paulo 		wpa_printf(MSG_DEBUG,
13675b9c547cSRui Paulo 			   "%s[dbus]: Channels must be an array of structs",
13685b9c547cSRui Paulo 			   __func__);
1369d4f2939cSRui Paulo 		*reply = wpas_dbus_error_invalid_args(
13705b9c547cSRui Paulo 			message,
13715b9c547cSRui Paulo 			"Wrong Channels value type. Array of structs required");
1372d4f2939cSRui Paulo 		return -1;
1373d4f2939cSRui Paulo 	}
1374d4f2939cSRui Paulo 
1375d4f2939cSRui Paulo 	while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_STRUCT)
1376d4f2939cSRui Paulo 	{
1377d4f2939cSRui Paulo 		int freq, width;
1378d4f2939cSRui Paulo 
1379d4f2939cSRui Paulo 		dbus_message_iter_recurse(&array_iter, &sub_array_iter);
1380d4f2939cSRui Paulo 
1381d4f2939cSRui Paulo 		if (dbus_message_iter_get_arg_type(&sub_array_iter) !=
1382d4f2939cSRui Paulo 		    DBUS_TYPE_UINT32) {
13835b9c547cSRui Paulo 			wpa_printf(MSG_DEBUG,
13845b9c547cSRui Paulo 				   "%s[dbus]: Channel must by specified by struct of two UINT32s %c",
13855b9c547cSRui Paulo 				   __func__,
1386d4f2939cSRui Paulo 				   dbus_message_iter_get_arg_type(
1387d4f2939cSRui Paulo 					   &sub_array_iter));
1388d4f2939cSRui Paulo 			*reply = wpas_dbus_error_invalid_args(
13895b9c547cSRui Paulo 				message,
13905b9c547cSRui Paulo 				"Wrong Channel struct. Two UINT32s required");
1391d4f2939cSRui Paulo 			os_free(freqs);
1392d4f2939cSRui Paulo 			return -1;
1393d4f2939cSRui Paulo 		}
1394d4f2939cSRui Paulo 		dbus_message_iter_get_basic(&sub_array_iter, &freq);
1395d4f2939cSRui Paulo 
1396d4f2939cSRui Paulo 		if (!dbus_message_iter_next(&sub_array_iter) ||
1397d4f2939cSRui Paulo 		    dbus_message_iter_get_arg_type(&sub_array_iter) !=
1398d4f2939cSRui Paulo 		    DBUS_TYPE_UINT32) {
13995b9c547cSRui Paulo 			wpa_printf(MSG_DEBUG,
14005b9c547cSRui Paulo 				   "%s[dbus]: Channel must by specified by struct of two UINT32s",
14015b9c547cSRui Paulo 				   __func__);
1402d4f2939cSRui Paulo 			*reply = wpas_dbus_error_invalid_args(
1403d4f2939cSRui Paulo 				message,
1404d4f2939cSRui Paulo 				"Wrong Channel struct. Two UINT32s required");
1405d4f2939cSRui Paulo 			os_free(freqs);
1406d4f2939cSRui Paulo 			return -1;
1407d4f2939cSRui Paulo 		}
1408d4f2939cSRui Paulo 
1409d4f2939cSRui Paulo 		dbus_message_iter_get_basic(&sub_array_iter, &width);
1410d4f2939cSRui Paulo 
1411d4f2939cSRui Paulo #define FREQS_ALLOC_CHUNK 32
1412d4f2939cSRui Paulo 		if (freqs_num % FREQS_ALLOC_CHUNK == 0) {
1413d4f2939cSRui Paulo 			nfreqs = os_realloc_array(
1414d4f2939cSRui Paulo 				freqs, freqs_num + FREQS_ALLOC_CHUNK,
1415d4f2939cSRui Paulo 				sizeof(int));
1416d4f2939cSRui Paulo 			if (nfreqs == NULL)
1417d4f2939cSRui Paulo 				os_free(freqs);
1418d4f2939cSRui Paulo 			freqs = nfreqs;
1419d4f2939cSRui Paulo 		}
1420d4f2939cSRui Paulo 		if (freqs == NULL) {
14215b9c547cSRui Paulo 			*reply = wpas_dbus_error_no_memory(message);
1422d4f2939cSRui Paulo 			return -1;
1423d4f2939cSRui Paulo 		}
1424d4f2939cSRui Paulo 
1425d4f2939cSRui Paulo 		freqs[freqs_num] = freq;
1426d4f2939cSRui Paulo 
1427d4f2939cSRui Paulo 		freqs_num++;
1428d4f2939cSRui Paulo 		dbus_message_iter_next(&array_iter);
1429d4f2939cSRui Paulo 	}
1430d4f2939cSRui Paulo 
1431d4f2939cSRui Paulo 	nfreqs = os_realloc_array(freqs, freqs_num + 1, sizeof(int));
1432d4f2939cSRui Paulo 	if (nfreqs == NULL)
1433d4f2939cSRui Paulo 		os_free(freqs);
1434d4f2939cSRui Paulo 	freqs = nfreqs;
1435d4f2939cSRui Paulo 	if (freqs == NULL) {
14365b9c547cSRui Paulo 		*reply = wpas_dbus_error_no_memory(message);
1437d4f2939cSRui Paulo 		return -1;
1438d4f2939cSRui Paulo 	}
1439d4f2939cSRui Paulo 	freqs[freqs_num] = 0;
1440d4f2939cSRui Paulo 
1441d4f2939cSRui Paulo 	params->freqs = freqs;
1442d4f2939cSRui Paulo 	return 0;
1443d4f2939cSRui Paulo }
1444d4f2939cSRui Paulo 
1445d4f2939cSRui Paulo 
wpas_dbus_get_scan_allow_roam(DBusMessage * message,DBusMessageIter * var,dbus_bool_t * allow,DBusMessage ** reply)14465b9c547cSRui Paulo static int wpas_dbus_get_scan_allow_roam(DBusMessage *message,
14475b9c547cSRui Paulo 					 DBusMessageIter *var,
14485b9c547cSRui Paulo 					 dbus_bool_t *allow,
14495b9c547cSRui Paulo 					 DBusMessage **reply)
14505b9c547cSRui Paulo {
14515b9c547cSRui Paulo 	if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_BOOLEAN) {
14525b9c547cSRui Paulo 		wpa_printf(MSG_DEBUG, "%s[dbus]: Type must be a boolean",
14535b9c547cSRui Paulo 			   __func__);
14545b9c547cSRui Paulo 		*reply = wpas_dbus_error_invalid_args(
14555b9c547cSRui Paulo 			message, "Wrong Type value type. Boolean required");
14565b9c547cSRui Paulo 		return -1;
14575b9c547cSRui Paulo 	}
14585b9c547cSRui Paulo 	dbus_message_iter_get_basic(var, allow);
14595b9c547cSRui Paulo 	return 0;
14605b9c547cSRui Paulo }
14615b9c547cSRui Paulo 
14625b9c547cSRui Paulo 
1463d4f2939cSRui Paulo /**
1464d4f2939cSRui Paulo  * wpas_dbus_handler_scan - Request a wireless scan on an interface
1465d4f2939cSRui Paulo  * @message: Pointer to incoming dbus message
1466d4f2939cSRui Paulo  * @wpa_s: wpa_supplicant structure for a network interface
1467d4f2939cSRui Paulo  * Returns: NULL indicating success or DBus error message on failure
1468d4f2939cSRui Paulo  *
1469d4f2939cSRui Paulo  * Handler function for "Scan" method call of a network device. Requests
1470d4f2939cSRui Paulo  * that wpa_supplicant perform a wireless scan as soon as possible
1471d4f2939cSRui Paulo  * on a particular wireless interface.
1472d4f2939cSRui Paulo  */
wpas_dbus_handler_scan(DBusMessage * message,struct wpa_supplicant * wpa_s)1473d4f2939cSRui Paulo DBusMessage * wpas_dbus_handler_scan(DBusMessage *message,
1474d4f2939cSRui Paulo 				     struct wpa_supplicant *wpa_s)
1475d4f2939cSRui Paulo {
1476d4f2939cSRui Paulo 	DBusMessage *reply = NULL;
1477d4f2939cSRui Paulo 	DBusMessageIter iter, dict_iter, entry_iter, variant_iter;
1478d4f2939cSRui Paulo 	char *key = NULL, *type = NULL;
1479d4f2939cSRui Paulo 	struct wpa_driver_scan_params params;
1480d4f2939cSRui Paulo 	size_t i;
14815b9c547cSRui Paulo 	dbus_bool_t allow_roam = 1;
1482d4f2939cSRui Paulo 
1483d4f2939cSRui Paulo 	os_memset(&params, 0, sizeof(params));
1484d4f2939cSRui Paulo 
1485d4f2939cSRui Paulo 	dbus_message_iter_init(message, &iter);
1486d4f2939cSRui Paulo 
1487d4f2939cSRui Paulo 	dbus_message_iter_recurse(&iter, &dict_iter);
1488d4f2939cSRui Paulo 
1489d4f2939cSRui Paulo 	while (dbus_message_iter_get_arg_type(&dict_iter) ==
1490d4f2939cSRui Paulo 	       DBUS_TYPE_DICT_ENTRY) {
1491d4f2939cSRui Paulo 		dbus_message_iter_recurse(&dict_iter, &entry_iter);
1492d4f2939cSRui Paulo 		dbus_message_iter_get_basic(&entry_iter, &key);
1493d4f2939cSRui Paulo 		dbus_message_iter_next(&entry_iter);
1494d4f2939cSRui Paulo 		dbus_message_iter_recurse(&entry_iter, &variant_iter);
1495d4f2939cSRui Paulo 
1496d4f2939cSRui Paulo 		if (os_strcmp(key, "Type") == 0) {
1497d4f2939cSRui Paulo 			if (wpas_dbus_get_scan_type(message, &variant_iter,
1498d4f2939cSRui Paulo 						    &type, &reply) < 0)
1499d4f2939cSRui Paulo 				goto out;
1500d4f2939cSRui Paulo 		} else if (os_strcmp(key, "SSIDs") == 0) {
1501d4f2939cSRui Paulo 			if (wpas_dbus_get_scan_ssids(message, &variant_iter,
1502d4f2939cSRui Paulo 						     &params, &reply) < 0)
1503d4f2939cSRui Paulo 				goto out;
1504d4f2939cSRui Paulo 		} else if (os_strcmp(key, "IEs") == 0) {
1505d4f2939cSRui Paulo 			if (wpas_dbus_get_scan_ies(message, &variant_iter,
1506d4f2939cSRui Paulo 						   &params, &reply) < 0)
1507d4f2939cSRui Paulo 				goto out;
1508d4f2939cSRui Paulo 		} else if (os_strcmp(key, "Channels") == 0) {
1509d4f2939cSRui Paulo 			if (wpas_dbus_get_scan_channels(message, &variant_iter,
1510d4f2939cSRui Paulo 							&params, &reply) < 0)
1511d4f2939cSRui Paulo 				goto out;
15125b9c547cSRui Paulo 		} else if (os_strcmp(key, "AllowRoam") == 0) {
15135b9c547cSRui Paulo 			if (wpas_dbus_get_scan_allow_roam(message,
15145b9c547cSRui Paulo 							  &variant_iter,
15155b9c547cSRui Paulo 							  &allow_roam,
15165b9c547cSRui Paulo 							  &reply) < 0)
15175b9c547cSRui Paulo 				goto out;
1518d4f2939cSRui Paulo 		} else {
15195b9c547cSRui Paulo 			wpa_printf(MSG_DEBUG, "%s[dbus]: Unknown argument %s",
15205b9c547cSRui Paulo 				   __func__, key);
1521d4f2939cSRui Paulo 			reply = wpas_dbus_error_invalid_args(message, key);
1522d4f2939cSRui Paulo 			goto out;
1523d4f2939cSRui Paulo 		}
1524d4f2939cSRui Paulo 
1525d4f2939cSRui Paulo 		dbus_message_iter_next(&dict_iter);
1526d4f2939cSRui Paulo 	}
1527d4f2939cSRui Paulo 
1528d4f2939cSRui Paulo 	if (!type) {
15295b9c547cSRui Paulo 		wpa_printf(MSG_DEBUG, "%s[dbus]: Scan type not specified",
15305b9c547cSRui Paulo 			   __func__);
1531d4f2939cSRui Paulo 		reply = wpas_dbus_error_invalid_args(message, key);
1532d4f2939cSRui Paulo 		goto out;
1533d4f2939cSRui Paulo 	}
1534d4f2939cSRui Paulo 
15355b9c547cSRui Paulo 	if (os_strcmp(type, "passive") == 0) {
1536d4f2939cSRui Paulo 		if (params.num_ssids || params.extra_ies_len) {
15375b9c547cSRui Paulo 			wpa_printf(MSG_DEBUG,
15385b9c547cSRui Paulo 				   "%s[dbus]: SSIDs or IEs specified for passive scan.",
15395b9c547cSRui Paulo 				   __func__);
1540d4f2939cSRui Paulo 			reply = wpas_dbus_error_invalid_args(
15415b9c547cSRui Paulo 				message,
15425b9c547cSRui Paulo 				"You can specify only Channels in passive scan");
1543d4f2939cSRui Paulo 			goto out;
1544325151a3SRui Paulo 		} else {
1545325151a3SRui Paulo 			if (wpa_s->sched_scanning) {
1546325151a3SRui Paulo 				wpa_printf(MSG_DEBUG,
1547325151a3SRui Paulo 					   "%s[dbus]: Stop ongoing sched_scan to allow requested scan to proceed",
1548325151a3SRui Paulo 					   __func__);
1549325151a3SRui Paulo 				wpa_supplicant_cancel_sched_scan(wpa_s);
1550325151a3SRui Paulo 			}
1551325151a3SRui Paulo 
1552325151a3SRui Paulo 			if (params.freqs && params.freqs[0]) {
1553325151a3SRui Paulo 				wpa_s->last_scan_req = MANUAL_SCAN_REQ;
1554325151a3SRui Paulo 				if (wpa_supplicant_trigger_scan(wpa_s,
1555325151a3SRui Paulo 								&params)) {
15565b9c547cSRui Paulo 					reply = wpas_dbus_error_scan_error(
1557325151a3SRui Paulo 						message,
1558325151a3SRui Paulo 						"Scan request rejected");
15595b9c547cSRui Paulo 				}
1560d4f2939cSRui Paulo 			} else {
1561d4f2939cSRui Paulo 				wpa_s->scan_req = MANUAL_SCAN_REQ;
1562d4f2939cSRui Paulo 				wpa_supplicant_req_scan(wpa_s, 0, 0);
1563d4f2939cSRui Paulo 			}
1564325151a3SRui Paulo 		}
15655b9c547cSRui Paulo 	} else if (os_strcmp(type, "active") == 0) {
1566d4f2939cSRui Paulo 		if (!params.num_ssids) {
1567d4f2939cSRui Paulo 			/* Add wildcard ssid */
1568d4f2939cSRui Paulo 			params.num_ssids++;
1569d4f2939cSRui Paulo 		}
1570d4f2939cSRui Paulo #ifdef CONFIG_AUTOSCAN
1571d4f2939cSRui Paulo 		autoscan_deinit(wpa_s);
1572d4f2939cSRui Paulo #endif /* CONFIG_AUTOSCAN */
1573325151a3SRui Paulo 		if (wpa_s->sched_scanning) {
1574325151a3SRui Paulo 			wpa_printf(MSG_DEBUG,
1575325151a3SRui Paulo 				   "%s[dbus]: Stop ongoing sched_scan to allow requested scan to proceed",
1576325151a3SRui Paulo 				   __func__);
1577325151a3SRui Paulo 			wpa_supplicant_cancel_sched_scan(wpa_s);
1578325151a3SRui Paulo 		}
1579325151a3SRui Paulo 
1580325151a3SRui Paulo 		wpa_s->last_scan_req = MANUAL_SCAN_REQ;
15815b9c547cSRui Paulo 		if (wpa_supplicant_trigger_scan(wpa_s, &params)) {
15825b9c547cSRui Paulo 			reply = wpas_dbus_error_scan_error(
15835b9c547cSRui Paulo 				message, "Scan request rejected");
15845b9c547cSRui Paulo 		}
1585d4f2939cSRui Paulo 	} else {
15865b9c547cSRui Paulo 		wpa_printf(MSG_DEBUG, "%s[dbus]: Unknown scan type: %s",
15875b9c547cSRui Paulo 			   __func__, type);
1588d4f2939cSRui Paulo 		reply = wpas_dbus_error_invalid_args(message,
1589d4f2939cSRui Paulo 						     "Wrong scan type");
1590d4f2939cSRui Paulo 		goto out;
1591d4f2939cSRui Paulo 	}
1592d4f2939cSRui Paulo 
15935b9c547cSRui Paulo 	if (!allow_roam)
15945b9c547cSRui Paulo 		wpa_s->scan_res_handler = scan_only_handler;
15955b9c547cSRui Paulo 
1596d4f2939cSRui Paulo out:
1597d4f2939cSRui Paulo 	for (i = 0; i < WPAS_MAX_SCAN_SSIDS; i++)
1598d4f2939cSRui Paulo 		os_free((u8 *) params.ssids[i].ssid);
1599d4f2939cSRui Paulo 	os_free((u8 *) params.extra_ies);
1600d4f2939cSRui Paulo 	os_free(params.freqs);
1601d4f2939cSRui Paulo 	return reply;
1602d4f2939cSRui Paulo }
1603d4f2939cSRui Paulo 
1604d4f2939cSRui Paulo 
160585732ac8SCy Schubert /*
160685732ac8SCy Schubert  * wpas_dbus_handler_abort_scan - Request an ongoing scan to be aborted
160785732ac8SCy Schubert  * @message: Pointer to incoming dbus message
160885732ac8SCy Schubert  * @wpa_s: wpa_supplicant structure for a network interface
160985732ac8SCy Schubert  * Returns: Abort failed or no scan in progress DBus error message on failure
161085732ac8SCy Schubert  * or NULL otherwise.
161185732ac8SCy Schubert  *
161285732ac8SCy Schubert  * Handler function for "AbortScan" method call of network interface.
161385732ac8SCy Schubert  */
wpas_dbus_handler_abort_scan(DBusMessage * message,struct wpa_supplicant * wpa_s)161485732ac8SCy Schubert DBusMessage * wpas_dbus_handler_abort_scan(DBusMessage *message,
161585732ac8SCy Schubert 					   struct wpa_supplicant *wpa_s)
161685732ac8SCy Schubert {
161785732ac8SCy Schubert 	if (wpas_abort_ongoing_scan(wpa_s) < 0)
161885732ac8SCy Schubert 		return dbus_message_new_error(
161985732ac8SCy Schubert 			message, WPAS_DBUS_ERROR_IFACE_SCAN_ERROR,
162085732ac8SCy Schubert 			"Abort failed or no scan in progress");
162185732ac8SCy Schubert 
162285732ac8SCy Schubert 	return NULL;
162385732ac8SCy Schubert }
162485732ac8SCy Schubert 
162585732ac8SCy Schubert 
16265b9c547cSRui Paulo /**
162732a95656SCy Schubert  * wpas_dbus_new_iface_add_cred - Add a new credential
162832a95656SCy Schubert  * @message: Pointer to incoming dbus message
162932a95656SCy Schubert  * @wpa_s: wpa_supplicant structure for a network interface
163032a95656SCy Schubert  * Returns: A dbus message containing the object path of the new credential
163132a95656SCy Schubert  *
163232a95656SCy Schubert  * Handler function for "AddCred" method call of a network interface.
163332a95656SCy Schubert  */
wpas_dbus_handler_add_cred(DBusMessage * message,struct wpa_supplicant * wpa_s)163432a95656SCy Schubert DBusMessage * wpas_dbus_handler_add_cred(DBusMessage *message,
163532a95656SCy Schubert 					 struct wpa_supplicant *wpa_s)
163632a95656SCy Schubert {
163732a95656SCy Schubert 	DBusMessage *reply = NULL;
163832a95656SCy Schubert 	DBusMessageIter	iter;
163932a95656SCy Schubert 	struct wpa_cred *cred = NULL;
164032a95656SCy Schubert 	char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf;
164132a95656SCy Schubert 	DBusError error;
164232a95656SCy Schubert 
164332a95656SCy Schubert 	dbus_message_iter_init(message, &iter);
164432a95656SCy Schubert 
164532a95656SCy Schubert 	if (wpa_s->dbus_new_path)
164632a95656SCy Schubert 		cred = wpa_config_add_cred(wpa_s->conf);
164732a95656SCy Schubert 	if (!cred) {
164832a95656SCy Schubert 		wpa_printf(MSG_ERROR, "%s[dbus]: can't add new credential.",
164932a95656SCy Schubert 			   __func__);
165032a95656SCy Schubert 		reply = wpas_dbus_error_unknown_error(
165132a95656SCy Schubert 			message,
165232a95656SCy Schubert 			"wpa_supplicant could not add a credential on this interface.");
165332a95656SCy Schubert 		goto err;
165432a95656SCy Schubert 	}
165532a95656SCy Schubert 
165632a95656SCy Schubert 	dbus_error_init(&error);
165732a95656SCy Schubert 	if (!set_cred_properties(wpa_s, cred, &iter, &error)) {
165832a95656SCy Schubert 		wpa_printf(MSG_DEBUG,
165932a95656SCy Schubert 			   "%s[dbus]: control interface couldn't set credential properties",
166032a95656SCy Schubert 			   __func__);
166132a95656SCy Schubert 		reply = wpas_dbus_reply_new_from_error(message, &error,
166232a95656SCy Schubert 						       DBUS_ERROR_INVALID_ARGS,
166332a95656SCy Schubert 						       "Failed to add credential");
166432a95656SCy Schubert 		dbus_error_free(&error);
166532a95656SCy Schubert 		goto err;
166632a95656SCy Schubert 	}
166732a95656SCy Schubert 
166832a95656SCy Schubert 	/* Construct the object path for this network. */
166932a95656SCy Schubert 	os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
167032a95656SCy Schubert 		    "%s/" WPAS_DBUS_NEW_CREDENTIALS_PART "/%d",
167132a95656SCy Schubert 		    wpa_s->dbus_new_path, cred->id);
167232a95656SCy Schubert 
167332a95656SCy Schubert 	reply = dbus_message_new_method_return(message);
167432a95656SCy Schubert 	if (!reply) {
167532a95656SCy Schubert 		reply = wpas_dbus_error_no_memory(message);
167632a95656SCy Schubert 		goto err;
167732a95656SCy Schubert 	}
167832a95656SCy Schubert 	if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
167932a95656SCy Schubert 				      DBUS_TYPE_INVALID)) {
168032a95656SCy Schubert 		dbus_message_unref(reply);
168132a95656SCy Schubert 		reply = wpas_dbus_error_no_memory(message);
168232a95656SCy Schubert 		goto err;
168332a95656SCy Schubert 	}
168432a95656SCy Schubert 
168532a95656SCy Schubert 	return reply;
168632a95656SCy Schubert 
168732a95656SCy Schubert err:
168832a95656SCy Schubert 	if (cred)
168932a95656SCy Schubert 		wpa_config_remove_cred(wpa_s->conf, cred->id);
169032a95656SCy Schubert 	return reply;
169132a95656SCy Schubert }
169232a95656SCy Schubert 
169332a95656SCy Schubert 
169432a95656SCy Schubert /**
169532a95656SCy Schubert  * wpas_dbus_handler_remove_cred - Remove a configured credential
169632a95656SCy Schubert  * @message: Pointer to incoming dbus message
169732a95656SCy Schubert  * @wpa_s: wpa_supplicant structure for a network interface
169832a95656SCy Schubert  * Returns: NULL on success or dbus error on failure
169932a95656SCy Schubert  *
170032a95656SCy Schubert  * Handler function for "RemoveCred" method call of a network interface.
170132a95656SCy Schubert  */
wpas_dbus_handler_remove_cred(DBusMessage * message,struct wpa_supplicant * wpa_s)170232a95656SCy Schubert DBusMessage * wpas_dbus_handler_remove_cred(DBusMessage *message,
170332a95656SCy Schubert 					    struct wpa_supplicant *wpa_s)
170432a95656SCy Schubert {
170532a95656SCy Schubert 	DBusMessage *reply = NULL;
170632a95656SCy Schubert 	const char *op;
170732a95656SCy Schubert 	char *iface, *cred_id;
170832a95656SCy Schubert 	int id;
170932a95656SCy Schubert 	struct wpa_cred *cred;
171032a95656SCy Schubert 
171132a95656SCy Schubert 	dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
171232a95656SCy Schubert 			      DBUS_TYPE_INVALID);
171332a95656SCy Schubert 
171432a95656SCy Schubert 	/* Extract the network ID and ensure the network is actually a child of
171532a95656SCy Schubert 	 * this interface */
171632a95656SCy Schubert 	iface = wpas_dbus_new_decompose_object_path(
171732a95656SCy Schubert 		op, WPAS_DBUS_NEW_CREDENTIALS_PART, &cred_id);
171832a95656SCy Schubert 	if (!iface || !cred_id || !wpa_s->dbus_new_path ||
171932a95656SCy Schubert 	    os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
172032a95656SCy Schubert 		reply = wpas_dbus_error_invalid_args(message, op);
172132a95656SCy Schubert 		goto out;
172232a95656SCy Schubert 	}
172332a95656SCy Schubert 
172432a95656SCy Schubert 	errno = 0;
172532a95656SCy Schubert 	id = strtoul(cred_id, NULL, 10);
172632a95656SCy Schubert 	if (errno != 0) {
172732a95656SCy Schubert 		reply = wpas_dbus_error_invalid_args(message, op);
172832a95656SCy Schubert 		goto out;
172932a95656SCy Schubert 	}
173032a95656SCy Schubert 
173132a95656SCy Schubert 	cred = wpa_config_get_cred(wpa_s->conf, id);
173232a95656SCy Schubert 	if (!cred) {
173332a95656SCy Schubert 		wpa_printf(MSG_ERROR, "%s[dbus]: could not find credential %s",
173432a95656SCy Schubert 			   __func__, op);
173532a95656SCy Schubert 		reply = wpas_dbus_error_invalid_args(
173632a95656SCy Schubert 			message, "could not find credential");
173732a95656SCy Schubert 		goto out;
173832a95656SCy Schubert 	}
173932a95656SCy Schubert 
174032a95656SCy Schubert 	if (wpas_remove_cred(wpa_s, cred) < 0) {
174132a95656SCy Schubert 		wpa_printf(MSG_ERROR,
174232a95656SCy Schubert 			   "%s[dbus]: error occurred when removing cred %d",
174332a95656SCy Schubert 			   __func__, id);
174432a95656SCy Schubert 		reply = wpas_dbus_error_unknown_error(
174532a95656SCy Schubert 			message,
174632a95656SCy Schubert 			"error removing the specified credential on its interface.");
174732a95656SCy Schubert 		goto out;
174832a95656SCy Schubert 	}
174932a95656SCy Schubert 
175032a95656SCy Schubert out:
175132a95656SCy Schubert 	os_free(iface);
175232a95656SCy Schubert 	return reply;
175332a95656SCy Schubert }
175432a95656SCy Schubert 
175532a95656SCy Schubert 
175632a95656SCy Schubert /**
175732a95656SCy Schubert  * wpas_dbus_handler_remove_all_creds - Remove all the configured credentials
175832a95656SCy Schubert  * @message: Pointer to incoming dbus message
175932a95656SCy Schubert  * @wpa_s: wpa_supplicant structure for a network interface
176032a95656SCy Schubert  * Returns: NULL indicating success or DBus error message on failure
176132a95656SCy Schubert  *
176232a95656SCy Schubert  * Handler function for "RemoveAllCreds" method call of a network interface.
176332a95656SCy Schubert  */
wpas_dbus_handler_remove_all_creds(DBusMessage * message,struct wpa_supplicant * wpa_s)176432a95656SCy Schubert DBusMessage * wpas_dbus_handler_remove_all_creds(DBusMessage *message,
176532a95656SCy Schubert 						 struct wpa_supplicant *wpa_s)
176632a95656SCy Schubert {
176732a95656SCy Schubert 	int res;
176832a95656SCy Schubert 	DBusMessage *reply = NULL;
176932a95656SCy Schubert 
177032a95656SCy Schubert 	res = wpas_remove_all_creds(wpa_s);
177132a95656SCy Schubert 	if (res < 0) {
177232a95656SCy Schubert 		wpa_printf(MSG_ERROR,
177332a95656SCy Schubert 			   "%s[dbus]: failed to remove all credentials",
177432a95656SCy Schubert 			   __func__);
177532a95656SCy Schubert 		reply = wpas_dbus_error_unknown_error(
177632a95656SCy Schubert 			message, "failed to remove all credentials");
177732a95656SCy Schubert 	}
177832a95656SCy Schubert 
177932a95656SCy Schubert 	return reply;
178032a95656SCy Schubert }
178132a95656SCy Schubert 
178232a95656SCy Schubert 
1783ec080394SCy Schubert #ifdef CONFIG_INTERWORKING
178432a95656SCy Schubert DBusMessage *
wpas_dbus_handler_interworking_select(DBusMessage * message,struct wpa_supplicant * wpa_s)178532a95656SCy Schubert wpas_dbus_handler_interworking_select(DBusMessage *message,
178632a95656SCy Schubert 				      struct wpa_supplicant *wpa_s)
178732a95656SCy Schubert {
178832a95656SCy Schubert 	int result;
178932a95656SCy Schubert 	DBusMessage *reply = NULL;
179032a95656SCy Schubert 
179132a95656SCy Schubert 	/* Automatic selection is disabled and no constraint on channels */
179232a95656SCy Schubert 	result = interworking_select(wpa_s, 0, NULL);
179332a95656SCy Schubert 	if (result < 0) {
179432a95656SCy Schubert 		wpa_printf(MSG_ERROR,
179532a95656SCy Schubert 			   "%s[dbus]: failed to start Interworking selection",
179632a95656SCy Schubert 			   __func__);
179732a95656SCy Schubert 		reply = wpas_dbus_error_scan_error(
179832a95656SCy Schubert 			message,
179932a95656SCy Schubert 			"error starting Interworking selection.");
180032a95656SCy Schubert 	}
180132a95656SCy Schubert 
180232a95656SCy Schubert 	return reply;
180332a95656SCy Schubert }
1804ec080394SCy Schubert #endif /* CONFIG_INTERWORKING */
180532a95656SCy Schubert 
180632a95656SCy Schubert 
180732a95656SCy Schubert /**
18085b9c547cSRui Paulo  * wpas_dbus_handler_signal_poll - Request immediate signal properties
18095b9c547cSRui Paulo  * @message: Pointer to incoming dbus message
18105b9c547cSRui Paulo  * @wpa_s: wpa_supplicant structure for a network interface
18115b9c547cSRui Paulo  * Returns: NULL indicating success or DBus error message on failure
18125b9c547cSRui Paulo  *
18135b9c547cSRui Paulo  * Handler function for "SignalPoll" method call of a network device. Requests
18145b9c547cSRui Paulo  * that wpa_supplicant read signal properties like RSSI, noise, and link
18155b9c547cSRui Paulo  * speed and return them.
18165b9c547cSRui Paulo  */
wpas_dbus_handler_signal_poll(DBusMessage * message,struct wpa_supplicant * wpa_s)18175b9c547cSRui Paulo DBusMessage * wpas_dbus_handler_signal_poll(DBusMessage *message,
18185b9c547cSRui Paulo 					    struct wpa_supplicant *wpa_s)
18195b9c547cSRui Paulo {
18205b9c547cSRui Paulo 	struct wpa_signal_info si;
18215b9c547cSRui Paulo 	DBusMessage *reply = NULL;
18225b9c547cSRui Paulo 	DBusMessageIter iter, iter_dict, variant_iter;
18235b9c547cSRui Paulo 	int ret;
18245b9c547cSRui Paulo 
18255b9c547cSRui Paulo 	ret = wpa_drv_signal_poll(wpa_s, &si);
18265b9c547cSRui Paulo 	if (ret) {
18275b9c547cSRui Paulo 		return dbus_message_new_error(message, DBUS_ERROR_FAILED,
18285b9c547cSRui Paulo 					      "Failed to read signal");
18295b9c547cSRui Paulo 	}
18305b9c547cSRui Paulo 
18315b9c547cSRui Paulo 	reply = dbus_message_new_method_return(message);
18325b9c547cSRui Paulo 	if (reply == NULL)
18335b9c547cSRui Paulo 		goto nomem;
18345b9c547cSRui Paulo 
18355b9c547cSRui Paulo 	dbus_message_iter_init_append(reply, &iter);
18365b9c547cSRui Paulo 
18375b9c547cSRui Paulo 	if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
18385b9c547cSRui Paulo 					      "a{sv}", &variant_iter) ||
18395b9c547cSRui Paulo 	    !wpa_dbus_dict_open_write(&variant_iter, &iter_dict) ||
18405b9c547cSRui Paulo 	    !wpa_dbus_dict_append_int32(&iter_dict, "rssi",
18415b9c547cSRui Paulo 					si.current_signal) ||
18425b9c547cSRui Paulo 	    !wpa_dbus_dict_append_int32(&iter_dict, "linkspeed",
18435b9c547cSRui Paulo 					si.current_txrate / 1000) ||
18445b9c547cSRui Paulo 	    !wpa_dbus_dict_append_int32(&iter_dict, "noise",
18455b9c547cSRui Paulo 					si.current_noise) ||
18465b9c547cSRui Paulo 	    !wpa_dbus_dict_append_uint32(&iter_dict, "frequency",
18475b9c547cSRui Paulo 					 si.frequency) ||
18485b9c547cSRui Paulo 	    (si.chanwidth != CHAN_WIDTH_UNKNOWN &&
18495b9c547cSRui Paulo 	     !wpa_dbus_dict_append_string(
18505b9c547cSRui Paulo 		     &iter_dict, "width",
18515b9c547cSRui Paulo 		     channel_width_to_string(si.chanwidth))) ||
18525b9c547cSRui Paulo 	    (si.center_frq1 > 0 && si.center_frq2 > 0 &&
18535b9c547cSRui Paulo 	     (!wpa_dbus_dict_append_int32(&iter_dict, "center-frq1",
18545b9c547cSRui Paulo 					  si.center_frq1) ||
18555b9c547cSRui Paulo 	      !wpa_dbus_dict_append_int32(&iter_dict, "center-frq2",
18565b9c547cSRui Paulo 					  si.center_frq2))) ||
18575b9c547cSRui Paulo 	    (si.avg_signal &&
18585b9c547cSRui Paulo 	     !wpa_dbus_dict_append_int32(&iter_dict, "avg-rssi",
18595b9c547cSRui Paulo 					 si.avg_signal)) ||
18605b9c547cSRui Paulo 	    !wpa_dbus_dict_close_write(&variant_iter, &iter_dict) ||
18615b9c547cSRui Paulo 	    !dbus_message_iter_close_container(&iter, &variant_iter))
18625b9c547cSRui Paulo 		goto nomem;
18635b9c547cSRui Paulo 
18645b9c547cSRui Paulo 	return reply;
18655b9c547cSRui Paulo 
18665b9c547cSRui Paulo nomem:
18675b9c547cSRui Paulo 	if (reply)
18685b9c547cSRui Paulo 		dbus_message_unref(reply);
18695b9c547cSRui Paulo 	return wpas_dbus_error_no_memory(message);
18705b9c547cSRui Paulo }
18715b9c547cSRui Paulo 
18725b9c547cSRui Paulo 
1873d4f2939cSRui Paulo /*
1874d4f2939cSRui Paulo  * wpas_dbus_handler_disconnect - Terminate the current connection
1875d4f2939cSRui Paulo  * @message: Pointer to incoming dbus message
1876d4f2939cSRui Paulo  * @wpa_s: wpa_supplicant structure for a network interface
1877d4f2939cSRui Paulo  * Returns: NotConnected DBus error message if already not connected
1878d4f2939cSRui Paulo  * or NULL otherwise.
1879d4f2939cSRui Paulo  *
1880d4f2939cSRui Paulo  * Handler function for "Disconnect" method call of network interface.
1881d4f2939cSRui Paulo  */
wpas_dbus_handler_disconnect(DBusMessage * message,struct wpa_supplicant * wpa_s)1882d4f2939cSRui Paulo DBusMessage * wpas_dbus_handler_disconnect(DBusMessage *message,
1883d4f2939cSRui Paulo 					   struct wpa_supplicant *wpa_s)
1884d4f2939cSRui Paulo {
1885d4f2939cSRui Paulo 	if (wpa_s->current_ssid != NULL) {
1886780fb4a2SCy Schubert 		wpas_request_disconnection(wpa_s);
1887d4f2939cSRui Paulo 		return NULL;
1888d4f2939cSRui Paulo 	}
1889d4f2939cSRui Paulo 
1890d4f2939cSRui Paulo 	return dbus_message_new_error(message, WPAS_DBUS_ERROR_NOT_CONNECTED,
1891d4f2939cSRui Paulo 				      "This interface is not connected");
1892d4f2939cSRui Paulo }
1893d4f2939cSRui Paulo 
1894d4f2939cSRui Paulo 
1895d4f2939cSRui Paulo /**
1896d4f2939cSRui Paulo  * wpas_dbus_new_iface_add_network - Add a new configured network
1897d4f2939cSRui Paulo  * @message: Pointer to incoming dbus message
1898d4f2939cSRui Paulo  * @wpa_s: wpa_supplicant structure for a network interface
1899d4f2939cSRui Paulo  * Returns: A dbus message containing the object path of the new network
1900d4f2939cSRui Paulo  *
1901d4f2939cSRui Paulo  * Handler function for "AddNetwork" method call of a network interface.
1902d4f2939cSRui Paulo  */
wpas_dbus_handler_add_network(DBusMessage * message,struct wpa_supplicant * wpa_s)1903d4f2939cSRui Paulo DBusMessage * wpas_dbus_handler_add_network(DBusMessage *message,
1904d4f2939cSRui Paulo 					    struct wpa_supplicant *wpa_s)
1905d4f2939cSRui Paulo {
1906d4f2939cSRui Paulo 	DBusMessage *reply = NULL;
1907d4f2939cSRui Paulo 	DBusMessageIter	iter;
1908d4f2939cSRui Paulo 	struct wpa_ssid *ssid = NULL;
1909d4f2939cSRui Paulo 	char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf;
1910d4f2939cSRui Paulo 	DBusError error;
1911d4f2939cSRui Paulo 
1912d4f2939cSRui Paulo 	dbus_message_iter_init(message, &iter);
1913d4f2939cSRui Paulo 
1914325151a3SRui Paulo 	if (wpa_s->dbus_new_path)
1915780fb4a2SCy Schubert 		ssid = wpa_supplicant_add_network(wpa_s);
1916d4f2939cSRui Paulo 	if (ssid == NULL) {
19175b9c547cSRui Paulo 		wpa_printf(MSG_ERROR, "%s[dbus]: can't add new interface.",
19185b9c547cSRui Paulo 			   __func__);
1919d4f2939cSRui Paulo 		reply = wpas_dbus_error_unknown_error(
1920d4f2939cSRui Paulo 			message,
19215b9c547cSRui Paulo 			"wpa_supplicant could not add a network on this interface.");
1922d4f2939cSRui Paulo 		goto err;
1923d4f2939cSRui Paulo 	}
1924d4f2939cSRui Paulo 
1925d4f2939cSRui Paulo 	dbus_error_init(&error);
1926d4f2939cSRui Paulo 	if (!set_network_properties(wpa_s, ssid, &iter, &error)) {
19275b9c547cSRui Paulo 		wpa_printf(MSG_DEBUG,
19285b9c547cSRui Paulo 			   "%s[dbus]: control interface couldn't set network properties",
19295b9c547cSRui Paulo 			   __func__);
1930d4f2939cSRui Paulo 		reply = wpas_dbus_reply_new_from_error(message, &error,
1931d4f2939cSRui Paulo 						       DBUS_ERROR_INVALID_ARGS,
1932d4f2939cSRui Paulo 						       "Failed to add network");
1933d4f2939cSRui Paulo 		dbus_error_free(&error);
1934d4f2939cSRui Paulo 		goto err;
1935d4f2939cSRui Paulo 	}
1936d4f2939cSRui Paulo 
1937d4f2939cSRui Paulo 	/* Construct the object path for this network. */
1938d4f2939cSRui Paulo 	os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
1939d4f2939cSRui Paulo 		    "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
1940d4f2939cSRui Paulo 		    wpa_s->dbus_new_path, ssid->id);
1941d4f2939cSRui Paulo 
1942d4f2939cSRui Paulo 	reply = dbus_message_new_method_return(message);
1943d4f2939cSRui Paulo 	if (reply == NULL) {
19445b9c547cSRui Paulo 		reply = wpas_dbus_error_no_memory(message);
1945d4f2939cSRui Paulo 		goto err;
1946d4f2939cSRui Paulo 	}
1947d4f2939cSRui Paulo 	if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
1948d4f2939cSRui Paulo 				      DBUS_TYPE_INVALID)) {
1949d4f2939cSRui Paulo 		dbus_message_unref(reply);
19505b9c547cSRui Paulo 		reply = wpas_dbus_error_no_memory(message);
1951d4f2939cSRui Paulo 		goto err;
1952d4f2939cSRui Paulo 	}
1953d4f2939cSRui Paulo 
1954d4f2939cSRui Paulo 	return reply;
1955d4f2939cSRui Paulo 
1956d4f2939cSRui Paulo err:
1957d4f2939cSRui Paulo 	if (ssid) {
1958d4f2939cSRui Paulo 		wpas_notify_network_removed(wpa_s, ssid);
1959d4f2939cSRui Paulo 		wpa_config_remove_network(wpa_s->conf, ssid->id);
1960d4f2939cSRui Paulo 	}
1961d4f2939cSRui Paulo 	return reply;
1962d4f2939cSRui Paulo }
1963d4f2939cSRui Paulo 
1964d4f2939cSRui Paulo 
1965d4f2939cSRui Paulo /**
19665b9c547cSRui Paulo  * wpas_dbus_handler_reassociate - Reassociate
1967d4f2939cSRui Paulo  * @message: Pointer to incoming dbus message
1968d4f2939cSRui Paulo  * @wpa_s: wpa_supplicant structure for a network interface
19695b9c547cSRui Paulo  * Returns: InterfaceDisabled DBus error message if disabled
1970d4f2939cSRui Paulo  * or NULL otherwise.
1971d4f2939cSRui Paulo  *
1972d4f2939cSRui Paulo  * Handler function for "Reassociate" method call of network interface.
1973d4f2939cSRui Paulo  */
wpas_dbus_handler_reassociate(DBusMessage * message,struct wpa_supplicant * wpa_s)1974d4f2939cSRui Paulo DBusMessage * wpas_dbus_handler_reassociate(DBusMessage *message,
1975d4f2939cSRui Paulo 					    struct wpa_supplicant *wpa_s)
1976d4f2939cSRui Paulo {
19775b9c547cSRui Paulo 	if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED) {
19785b9c547cSRui Paulo 		wpas_request_connection(wpa_s);
19795b9c547cSRui Paulo 		return NULL;
19805b9c547cSRui Paulo 	}
19815b9c547cSRui Paulo 
19825b9c547cSRui Paulo 	return dbus_message_new_error(message, WPAS_DBUS_ERROR_IFACE_DISABLED,
19835b9c547cSRui Paulo 				      "This interface is disabled");
19845b9c547cSRui Paulo }
19855b9c547cSRui Paulo 
19865b9c547cSRui Paulo 
19875b9c547cSRui Paulo /**
1988780fb4a2SCy Schubert  * wpas_dbus_handler_expect_disconnect - ExpectDisconnect
1989780fb4a2SCy Schubert  * @message: Pointer to incoming dbus message
1990780fb4a2SCy Schubert  * @global: %wpa_supplicant global data structure
1991780fb4a2SCy Schubert  * Returns: NULL
1992780fb4a2SCy Schubert  *
1993780fb4a2SCy Schubert  * Handler function for notifying system there will be a expected disconnect.
1994c1d255d3SCy Schubert  * This will prevent wpa_supplicant from adding the BSSID to the ignore list
1995c1d255d3SCy Schubert  * upon next disconnect.
1996780fb4a2SCy Schubert  */
wpas_dbus_handler_expect_disconnect(DBusMessage * message,struct wpa_global * global)1997780fb4a2SCy Schubert DBusMessage * wpas_dbus_handler_expect_disconnect(DBusMessage *message,
1998780fb4a2SCy Schubert 						  struct wpa_global *global)
1999780fb4a2SCy Schubert {
2000780fb4a2SCy Schubert 	struct wpa_supplicant *wpa_s = global->ifaces;
2001780fb4a2SCy Schubert 
2002780fb4a2SCy Schubert 	for (; wpa_s; wpa_s = wpa_s->next)
2003780fb4a2SCy Schubert 		if (wpa_s->wpa_state >= WPA_ASSOCIATED)
2004780fb4a2SCy Schubert 			wpa_s->own_disconnect_req = 1;
2005780fb4a2SCy Schubert 	return NULL;
2006780fb4a2SCy Schubert }
2007780fb4a2SCy Schubert 
2008780fb4a2SCy Schubert 
2009780fb4a2SCy Schubert /**
20105b9c547cSRui Paulo  * wpas_dbus_handler_reattach - Reattach to current AP
20115b9c547cSRui Paulo  * @message: Pointer to incoming dbus message
20125b9c547cSRui Paulo  * @wpa_s: wpa_supplicant structure for a network interface
20135b9c547cSRui Paulo  * Returns: NotConnected DBus error message if not connected
20145b9c547cSRui Paulo  * or NULL otherwise.
20155b9c547cSRui Paulo  *
20165b9c547cSRui Paulo  * Handler function for "Reattach" method call of network interface.
20175b9c547cSRui Paulo  */
wpas_dbus_handler_reattach(DBusMessage * message,struct wpa_supplicant * wpa_s)20185b9c547cSRui Paulo DBusMessage * wpas_dbus_handler_reattach(DBusMessage *message,
20195b9c547cSRui Paulo 					 struct wpa_supplicant *wpa_s)
20205b9c547cSRui Paulo {
2021d4f2939cSRui Paulo 	if (wpa_s->current_ssid != NULL) {
20225b9c547cSRui Paulo 		wpa_s->reattach = 1;
2023d4f2939cSRui Paulo 		wpas_request_connection(wpa_s);
2024d4f2939cSRui Paulo 		return NULL;
2025d4f2939cSRui Paulo 	}
2026d4f2939cSRui Paulo 
2027d4f2939cSRui Paulo 	return dbus_message_new_error(message, WPAS_DBUS_ERROR_NOT_CONNECTED,
2028d4f2939cSRui Paulo 				      "This interface is not connected");
2029d4f2939cSRui Paulo }
2030d4f2939cSRui Paulo 
2031d4f2939cSRui Paulo 
2032d4f2939cSRui Paulo /**
2033325151a3SRui Paulo  * wpas_dbus_handler_reconnect - Reconnect if disconnected
2034325151a3SRui Paulo  * @message: Pointer to incoming dbus message
2035325151a3SRui Paulo  * @wpa_s: wpa_supplicant structure for a network interface
2036325151a3SRui Paulo  * Returns: InterfaceDisabled DBus error message if disabled
2037325151a3SRui Paulo  * or NULL otherwise.
2038325151a3SRui Paulo  *
2039325151a3SRui Paulo  * Handler function for "Reconnect" method call of network interface.
2040325151a3SRui Paulo  */
wpas_dbus_handler_reconnect(DBusMessage * message,struct wpa_supplicant * wpa_s)2041325151a3SRui Paulo DBusMessage * wpas_dbus_handler_reconnect(DBusMessage *message,
2042325151a3SRui Paulo 		struct wpa_supplicant *wpa_s)
2043325151a3SRui Paulo {
2044325151a3SRui Paulo 	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
2045325151a3SRui Paulo 		return dbus_message_new_error(message,
2046325151a3SRui Paulo 					      WPAS_DBUS_ERROR_IFACE_DISABLED,
2047325151a3SRui Paulo 					      "This interface is disabled");
2048325151a3SRui Paulo 	}
2049325151a3SRui Paulo 
2050325151a3SRui Paulo 	if (wpa_s->disconnected)
2051325151a3SRui Paulo 		wpas_request_connection(wpa_s);
2052325151a3SRui Paulo 	return NULL;
2053325151a3SRui Paulo }
2054325151a3SRui Paulo 
2055325151a3SRui Paulo 
2056325151a3SRui Paulo /**
2057d4f2939cSRui Paulo  * wpas_dbus_handler_remove_network - Remove a configured network
2058d4f2939cSRui Paulo  * @message: Pointer to incoming dbus message
2059d4f2939cSRui Paulo  * @wpa_s: wpa_supplicant structure for a network interface
2060d4f2939cSRui Paulo  * Returns: NULL on success or dbus error on failure
2061d4f2939cSRui Paulo  *
2062d4f2939cSRui Paulo  * Handler function for "RemoveNetwork" method call of a network interface.
2063d4f2939cSRui Paulo  */
wpas_dbus_handler_remove_network(DBusMessage * message,struct wpa_supplicant * wpa_s)2064d4f2939cSRui Paulo DBusMessage * wpas_dbus_handler_remove_network(DBusMessage *message,
2065d4f2939cSRui Paulo 					       struct wpa_supplicant *wpa_s)
2066d4f2939cSRui Paulo {
2067d4f2939cSRui Paulo 	DBusMessage *reply = NULL;
2068d4f2939cSRui Paulo 	const char *op;
20695b9c547cSRui Paulo 	char *iface, *net_id;
2070d4f2939cSRui Paulo 	int id;
2071780fb4a2SCy Schubert 	int result;
2072d4f2939cSRui Paulo 
2073d4f2939cSRui Paulo 	dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
2074d4f2939cSRui Paulo 			      DBUS_TYPE_INVALID);
2075d4f2939cSRui Paulo 
2076d4f2939cSRui Paulo 	/* Extract the network ID and ensure the network */
2077d4f2939cSRui Paulo 	/* is actually a child of this interface */
20785b9c547cSRui Paulo 	iface = wpas_dbus_new_decompose_object_path(op,
20795b9c547cSRui Paulo 						    WPAS_DBUS_NEW_NETWORKS_PART,
20805b9c547cSRui Paulo 						    &net_id);
2081325151a3SRui Paulo 	if (iface == NULL || net_id == NULL || !wpa_s->dbus_new_path ||
2082d4f2939cSRui Paulo 	    os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
2083d4f2939cSRui Paulo 		reply = wpas_dbus_error_invalid_args(message, op);
2084d4f2939cSRui Paulo 		goto out;
2085d4f2939cSRui Paulo 	}
2086d4f2939cSRui Paulo 
2087d4f2939cSRui Paulo 	errno = 0;
2088d4f2939cSRui Paulo 	id = strtoul(net_id, NULL, 10);
2089d4f2939cSRui Paulo 	if (errno != 0) {
2090d4f2939cSRui Paulo 		reply = wpas_dbus_error_invalid_args(message, op);
2091d4f2939cSRui Paulo 		goto out;
2092d4f2939cSRui Paulo 	}
2093d4f2939cSRui Paulo 
2094780fb4a2SCy Schubert 	result = wpa_supplicant_remove_network(wpa_s, id);
2095780fb4a2SCy Schubert 	if (result == -1) {
2096d4f2939cSRui Paulo 		reply = wpas_dbus_error_network_unknown(message);
2097d4f2939cSRui Paulo 		goto out;
2098d4f2939cSRui Paulo 	}
2099780fb4a2SCy Schubert 	if (result == -2) {
21005b9c547cSRui Paulo 		wpa_printf(MSG_ERROR,
21015b9c547cSRui Paulo 			   "%s[dbus]: error occurred when removing network %d",
21025b9c547cSRui Paulo 			   __func__, id);
21035b9c547cSRui Paulo 		reply = wpas_dbus_error_unknown_error(
21045b9c547cSRui Paulo 			message,
21055b9c547cSRui Paulo 			"error removing the specified network on is interface.");
21065b9c547cSRui Paulo 		goto out;
21075b9c547cSRui Paulo 	}
2108d4f2939cSRui Paulo 
2109d4f2939cSRui Paulo out:
2110d4f2939cSRui Paulo 	os_free(iface);
2111d4f2939cSRui Paulo 	return reply;
2112d4f2939cSRui Paulo }
2113d4f2939cSRui Paulo 
2114d4f2939cSRui Paulo 
2115d4f2939cSRui Paulo /**
2116d4f2939cSRui Paulo  * wpas_dbus_handler_remove_all_networks - Remove all configured networks
2117d4f2939cSRui Paulo  * @message: Pointer to incoming dbus message
2118d4f2939cSRui Paulo  * @wpa_s: wpa_supplicant structure for a network interface
2119d4f2939cSRui Paulo  * Returns: NULL on success or dbus error on failure
2120d4f2939cSRui Paulo  *
2121d4f2939cSRui Paulo  * Handler function for "RemoveAllNetworks" method call of a network interface.
2122d4f2939cSRui Paulo  */
wpas_dbus_handler_remove_all_networks(DBusMessage * message,struct wpa_supplicant * wpa_s)2123d4f2939cSRui Paulo DBusMessage * wpas_dbus_handler_remove_all_networks(
2124d4f2939cSRui Paulo 	DBusMessage *message, struct wpa_supplicant *wpa_s)
2125d4f2939cSRui Paulo {
2126d4f2939cSRui Paulo 	/* NB: could check for failure and return an error */
2127c1d255d3SCy Schubert 	wpa_supplicant_remove_all_networks(wpa_s);
2128d4f2939cSRui Paulo 	return NULL;
2129d4f2939cSRui Paulo }
2130d4f2939cSRui Paulo 
2131d4f2939cSRui Paulo 
2132d4f2939cSRui Paulo /**
2133d4f2939cSRui Paulo  * wpas_dbus_handler_select_network - Attempt association with a network
2134d4f2939cSRui Paulo  * @message: Pointer to incoming dbus message
2135d4f2939cSRui Paulo  * @wpa_s: wpa_supplicant structure for a network interface
2136d4f2939cSRui Paulo  * Returns: NULL on success or dbus error on failure
2137d4f2939cSRui Paulo  *
2138d4f2939cSRui Paulo  * Handler function for "SelectNetwork" method call of network interface.
2139d4f2939cSRui Paulo  */
wpas_dbus_handler_select_network(DBusMessage * message,struct wpa_supplicant * wpa_s)2140d4f2939cSRui Paulo DBusMessage * wpas_dbus_handler_select_network(DBusMessage *message,
2141d4f2939cSRui Paulo 					       struct wpa_supplicant *wpa_s)
2142d4f2939cSRui Paulo {
2143d4f2939cSRui Paulo 	DBusMessage *reply = NULL;
2144d4f2939cSRui Paulo 	const char *op;
21455b9c547cSRui Paulo 	char *iface, *net_id;
2146d4f2939cSRui Paulo 	int id;
2147d4f2939cSRui Paulo 	struct wpa_ssid *ssid;
2148d4f2939cSRui Paulo 
2149d4f2939cSRui Paulo 	dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
2150d4f2939cSRui Paulo 			      DBUS_TYPE_INVALID);
2151d4f2939cSRui Paulo 
2152d4f2939cSRui Paulo 	/* Extract the network ID and ensure the network */
2153d4f2939cSRui Paulo 	/* is actually a child of this interface */
21545b9c547cSRui Paulo 	iface = wpas_dbus_new_decompose_object_path(op,
21555b9c547cSRui Paulo 						    WPAS_DBUS_NEW_NETWORKS_PART,
21565b9c547cSRui Paulo 						    &net_id);
2157325151a3SRui Paulo 	if (iface == NULL || net_id == NULL || !wpa_s->dbus_new_path ||
2158d4f2939cSRui Paulo 	    os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
2159d4f2939cSRui Paulo 		reply = wpas_dbus_error_invalid_args(message, op);
2160d4f2939cSRui Paulo 		goto out;
2161d4f2939cSRui Paulo 	}
2162d4f2939cSRui Paulo 
2163d4f2939cSRui Paulo 	errno = 0;
2164d4f2939cSRui Paulo 	id = strtoul(net_id, NULL, 10);
2165d4f2939cSRui Paulo 	if (errno != 0) {
2166d4f2939cSRui Paulo 		reply = wpas_dbus_error_invalid_args(message, op);
2167d4f2939cSRui Paulo 		goto out;
2168d4f2939cSRui Paulo 	}
2169d4f2939cSRui Paulo 
2170d4f2939cSRui Paulo 	ssid = wpa_config_get_network(wpa_s->conf, id);
2171d4f2939cSRui Paulo 	if (ssid == NULL) {
2172d4f2939cSRui Paulo 		reply = wpas_dbus_error_network_unknown(message);
2173d4f2939cSRui Paulo 		goto out;
2174d4f2939cSRui Paulo 	}
2175d4f2939cSRui Paulo 
2176d4f2939cSRui Paulo 	/* Finally, associate with the network */
2177d4f2939cSRui Paulo 	wpa_supplicant_select_network(wpa_s, ssid);
2178d4f2939cSRui Paulo 
2179d4f2939cSRui Paulo out:
2180d4f2939cSRui Paulo 	os_free(iface);
2181d4f2939cSRui Paulo 	return reply;
2182d4f2939cSRui Paulo }
2183d4f2939cSRui Paulo 
2184d4f2939cSRui Paulo 
2185d4f2939cSRui Paulo /**
2186d4f2939cSRui Paulo  * wpas_dbus_handler_network_reply - Reply to a NetworkRequest signal
2187d4f2939cSRui Paulo  * @message: Pointer to incoming dbus message
2188d4f2939cSRui Paulo  * @wpa_s: wpa_supplicant structure for a network interface
2189d4f2939cSRui Paulo  * Returns: NULL on success or dbus error on failure
2190d4f2939cSRui Paulo  *
2191d4f2939cSRui Paulo  * Handler function for "NetworkReply" method call of network interface.
2192d4f2939cSRui Paulo  */
wpas_dbus_handler_network_reply(DBusMessage * message,struct wpa_supplicant * wpa_s)2193d4f2939cSRui Paulo DBusMessage * wpas_dbus_handler_network_reply(DBusMessage *message,
2194d4f2939cSRui Paulo 					      struct wpa_supplicant *wpa_s)
2195d4f2939cSRui Paulo {
2196d4f2939cSRui Paulo #ifdef IEEE8021X_EAPOL
2197d4f2939cSRui Paulo 	DBusMessage *reply = NULL;
2198d4f2939cSRui Paulo 	const char *op, *field, *value;
21995b9c547cSRui Paulo 	char *iface, *net_id;
2200d4f2939cSRui Paulo 	int id;
2201d4f2939cSRui Paulo 	struct wpa_ssid *ssid;
2202d4f2939cSRui Paulo 
2203d4f2939cSRui Paulo 	if (!dbus_message_get_args(message, NULL,
2204d4f2939cSRui Paulo 				   DBUS_TYPE_OBJECT_PATH, &op,
2205d4f2939cSRui Paulo 				   DBUS_TYPE_STRING, &field,
2206d4f2939cSRui Paulo 				   DBUS_TYPE_STRING, &value,
2207d4f2939cSRui Paulo 				   DBUS_TYPE_INVALID))
2208d4f2939cSRui Paulo 		return wpas_dbus_error_invalid_args(message, NULL);
2209d4f2939cSRui Paulo 
2210d4f2939cSRui Paulo 	/* Extract the network ID and ensure the network */
2211d4f2939cSRui Paulo 	/* is actually a child of this interface */
22125b9c547cSRui Paulo 	iface = wpas_dbus_new_decompose_object_path(op,
22135b9c547cSRui Paulo 						    WPAS_DBUS_NEW_NETWORKS_PART,
22145b9c547cSRui Paulo 						    &net_id);
2215325151a3SRui Paulo 	if (iface == NULL || net_id == NULL || !wpa_s->dbus_new_path ||
2216d4f2939cSRui Paulo 	    os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
2217d4f2939cSRui Paulo 		reply = wpas_dbus_error_invalid_args(message, op);
2218d4f2939cSRui Paulo 		goto out;
2219d4f2939cSRui Paulo 	}
2220d4f2939cSRui Paulo 
2221d4f2939cSRui Paulo 	errno = 0;
2222d4f2939cSRui Paulo 	id = strtoul(net_id, NULL, 10);
2223d4f2939cSRui Paulo 	if (errno != 0) {
2224d4f2939cSRui Paulo 		reply = wpas_dbus_error_invalid_args(message, net_id);
2225d4f2939cSRui Paulo 		goto out;
2226d4f2939cSRui Paulo 	}
2227d4f2939cSRui Paulo 
2228d4f2939cSRui Paulo 	ssid = wpa_config_get_network(wpa_s->conf, id);
2229d4f2939cSRui Paulo 	if (ssid == NULL) {
2230d4f2939cSRui Paulo 		reply = wpas_dbus_error_network_unknown(message);
2231d4f2939cSRui Paulo 		goto out;
2232d4f2939cSRui Paulo 	}
2233d4f2939cSRui Paulo 
2234d4f2939cSRui Paulo 	if (wpa_supplicant_ctrl_iface_ctrl_rsp_handle(wpa_s, ssid,
2235d4f2939cSRui Paulo 						      field, value) < 0)
2236d4f2939cSRui Paulo 		reply = wpas_dbus_error_invalid_args(message, field);
2237d4f2939cSRui Paulo 	else {
2238d4f2939cSRui Paulo 		/* Tell EAP to retry immediately */
2239d4f2939cSRui Paulo 		eapol_sm_notify_ctrl_response(wpa_s->eapol);
2240d4f2939cSRui Paulo 	}
2241d4f2939cSRui Paulo 
2242d4f2939cSRui Paulo out:
2243d4f2939cSRui Paulo 	os_free(iface);
2244d4f2939cSRui Paulo 	return reply;
2245d4f2939cSRui Paulo #else /* IEEE8021X_EAPOL */
2246780fb4a2SCy Schubert 	wpa_printf(MSG_DEBUG, "dbus: 802.1X not included");
2247d4f2939cSRui Paulo 	return wpas_dbus_error_unknown_error(message, "802.1X not included");
2248d4f2939cSRui Paulo #endif /* IEEE8021X_EAPOL */
2249d4f2939cSRui Paulo }
2250d4f2939cSRui Paulo 
2251d4f2939cSRui Paulo 
2252c1d255d3SCy Schubert /**
2253c1d255d3SCy Schubert  * wpas_dbus_handler_roam - Initiate a roam to another BSS within the ESS
2254c1d255d3SCy Schubert  * @message: Pointer to incoming dbus message
2255c1d255d3SCy Schubert  * @wpa_s: wpa_supplicant structure for a network interface
2256c1d255d3SCy Schubert  * Returns: NULL on success or dbus error on failure
2257c1d255d3SCy Schubert  *
2258c1d255d3SCy Schubert  * Handler function for "Roam" method call of network interface.
2259c1d255d3SCy Schubert  */
wpas_dbus_handler_roam(DBusMessage * message,struct wpa_supplicant * wpa_s)2260c1d255d3SCy Schubert DBusMessage * wpas_dbus_handler_roam(DBusMessage *message,
2261c1d255d3SCy Schubert 				     struct wpa_supplicant *wpa_s)
2262c1d255d3SCy Schubert {
2263c1d255d3SCy Schubert #ifdef CONFIG_NO_SCAN_PROCESSING
2264c1d255d3SCy Schubert 	return wpas_dbus_error_unknown_error(message,
2265c1d255d3SCy Schubert 					     "scan processing not included");
2266c1d255d3SCy Schubert #else /* CONFIG_NO_SCAN_PROCESSING */
2267c1d255d3SCy Schubert 	u8 bssid[ETH_ALEN];
2268c1d255d3SCy Schubert 	struct wpa_bss *bss;
2269c1d255d3SCy Schubert 	struct wpa_ssid *ssid = wpa_s->current_ssid;
2270c1d255d3SCy Schubert 	char *addr;
2271c1d255d3SCy Schubert 	struct wpa_radio_work *already_connecting;
2272c1d255d3SCy Schubert 
2273c1d255d3SCy Schubert 	if (!dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &addr,
2274c1d255d3SCy Schubert 				   DBUS_TYPE_INVALID))
2275c1d255d3SCy Schubert 		return wpas_dbus_error_invalid_args(message, NULL);
2276c1d255d3SCy Schubert 
2277c1d255d3SCy Schubert 	if (hwaddr_aton(addr, bssid))
2278c1d255d3SCy Schubert 		return wpas_dbus_error_invalid_args(
2279c1d255d3SCy Schubert 			message, "Invalid hardware address format");
2280c1d255d3SCy Schubert 
2281c1d255d3SCy Schubert 	wpa_printf(MSG_DEBUG, "dbus: Roam " MACSTR, MAC2STR(bssid));
2282c1d255d3SCy Schubert 
2283c1d255d3SCy Schubert 	if (!ssid)
2284c1d255d3SCy Schubert 		return dbus_message_new_error(
2285c1d255d3SCy Schubert 			message, WPAS_DBUS_ERROR_NOT_CONNECTED,
2286c1d255d3SCy Schubert 			"This interface is not connected");
2287c1d255d3SCy Schubert 
2288c1d255d3SCy Schubert 	bss = wpa_bss_get(wpa_s, bssid, ssid->ssid, ssid->ssid_len);
2289c1d255d3SCy Schubert 	if (!bss) {
2290c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG, "dbus: Roam: Target BSS not found");
2291c1d255d3SCy Schubert 		return wpas_dbus_error_invalid_args(
2292c1d255d3SCy Schubert 			message, "Target BSS not found");
2293c1d255d3SCy Schubert 	}
2294c1d255d3SCy Schubert 
2295c1d255d3SCy Schubert 	already_connecting = radio_work_pending(wpa_s, "sme-connect");
2296c1d255d3SCy Schubert 	wpa_s->reassociate = 1;
2297c1d255d3SCy Schubert 	wpa_supplicant_connect(wpa_s, bss, ssid);
2298c1d255d3SCy Schubert 
2299c1d255d3SCy Schubert 	/*
2300c1d255d3SCy Schubert 	 * Indicate that an explicitly requested roam is in progress so scan
2301c1d255d3SCy Schubert 	 * results that come in before the 'sme-connect' radio work gets
2302c1d255d3SCy Schubert 	 * executed do not override the original connection attempt.
2303c1d255d3SCy Schubert 	 */
2304c1d255d3SCy Schubert 	if (!already_connecting && radio_work_pending(wpa_s, "sme-connect"))
2305c1d255d3SCy Schubert 		wpa_s->roam_in_progress = true;
2306c1d255d3SCy Schubert 
2307c1d255d3SCy Schubert 	return NULL;
2308c1d255d3SCy Schubert #endif /* CONFIG_NO_SCAN_PROCESSING */
2309c1d255d3SCy Schubert }
2310c1d255d3SCy Schubert 
23115b9c547cSRui Paulo #ifndef CONFIG_NO_CONFIG_BLOBS
23125b9c547cSRui Paulo 
2313d4f2939cSRui Paulo /**
2314d4f2939cSRui Paulo  * wpas_dbus_handler_add_blob - Store named binary blob (ie, for certificates)
2315d4f2939cSRui Paulo  * @message: Pointer to incoming dbus message
2316d4f2939cSRui Paulo  * @wpa_s: %wpa_supplicant data structure
2317d4f2939cSRui Paulo  * Returns: A dbus message containing an error on failure or NULL on success
2318d4f2939cSRui Paulo  *
2319d4f2939cSRui Paulo  * Asks wpa_supplicant to internally store a binary blobs.
2320d4f2939cSRui Paulo  */
wpas_dbus_handler_add_blob(DBusMessage * message,struct wpa_supplicant * wpa_s)2321d4f2939cSRui Paulo DBusMessage * wpas_dbus_handler_add_blob(DBusMessage *message,
2322d4f2939cSRui Paulo 					 struct wpa_supplicant *wpa_s)
2323d4f2939cSRui Paulo {
2324d4f2939cSRui Paulo 	DBusMessage *reply = NULL;
2325d4f2939cSRui Paulo 	DBusMessageIter	iter, array_iter;
2326d4f2939cSRui Paulo 
2327d4f2939cSRui Paulo 	char *blob_name;
2328d4f2939cSRui Paulo 	u8 *blob_data;
2329d4f2939cSRui Paulo 	int blob_len;
2330d4f2939cSRui Paulo 	struct wpa_config_blob *blob = NULL;
2331d4f2939cSRui Paulo 
2332d4f2939cSRui Paulo 	dbus_message_iter_init(message, &iter);
2333d4f2939cSRui Paulo 	dbus_message_iter_get_basic(&iter, &blob_name);
2334d4f2939cSRui Paulo 
2335d4f2939cSRui Paulo 	if (wpa_config_get_blob(wpa_s->conf, blob_name)) {
2336d4f2939cSRui Paulo 		return dbus_message_new_error(message,
2337d4f2939cSRui Paulo 					      WPAS_DBUS_ERROR_BLOB_EXISTS,
2338d4f2939cSRui Paulo 					      NULL);
2339d4f2939cSRui Paulo 	}
2340d4f2939cSRui Paulo 
2341d4f2939cSRui Paulo 	dbus_message_iter_next(&iter);
2342d4f2939cSRui Paulo 	dbus_message_iter_recurse(&iter, &array_iter);
2343d4f2939cSRui Paulo 
2344d4f2939cSRui Paulo 	dbus_message_iter_get_fixed_array(&array_iter, &blob_data, &blob_len);
2345d4f2939cSRui Paulo 
2346d4f2939cSRui Paulo 	blob = os_zalloc(sizeof(*blob));
2347d4f2939cSRui Paulo 	if (!blob) {
23485b9c547cSRui Paulo 		reply = wpas_dbus_error_no_memory(message);
2349d4f2939cSRui Paulo 		goto err;
2350d4f2939cSRui Paulo 	}
2351d4f2939cSRui Paulo 
235285732ac8SCy Schubert 	blob->data = os_memdup(blob_data, blob_len);
23535b9c547cSRui Paulo 	blob->name = os_strdup(blob_name);
23545b9c547cSRui Paulo 	if (!blob->data || !blob->name) {
23555b9c547cSRui Paulo 		reply = wpas_dbus_error_no_memory(message);
2356d4f2939cSRui Paulo 		goto err;
2357d4f2939cSRui Paulo 	}
2358d4f2939cSRui Paulo 	blob->len = blob_len;
2359d4f2939cSRui Paulo 
2360d4f2939cSRui Paulo 	wpa_config_set_blob(wpa_s->conf, blob);
2361d4f2939cSRui Paulo 	wpas_notify_blob_added(wpa_s, blob->name);
2362d4f2939cSRui Paulo 
2363d4f2939cSRui Paulo 	return reply;
2364d4f2939cSRui Paulo 
2365d4f2939cSRui Paulo err:
2366d4f2939cSRui Paulo 	if (blob) {
2367d4f2939cSRui Paulo 		os_free(blob->name);
2368d4f2939cSRui Paulo 		os_free(blob->data);
2369d4f2939cSRui Paulo 		os_free(blob);
2370d4f2939cSRui Paulo 	}
2371d4f2939cSRui Paulo 	return reply;
2372d4f2939cSRui Paulo }
2373d4f2939cSRui Paulo 
2374d4f2939cSRui Paulo 
2375d4f2939cSRui Paulo /**
2376d4f2939cSRui Paulo  * wpas_dbus_handler_get_blob - Get named binary blob (ie, for certificates)
2377d4f2939cSRui Paulo  * @message: Pointer to incoming dbus message
2378d4f2939cSRui Paulo  * @wpa_s: %wpa_supplicant data structure
2379d4f2939cSRui Paulo  * Returns: A dbus message containing array of bytes (blob)
2380d4f2939cSRui Paulo  *
2381d4f2939cSRui Paulo  * Gets one wpa_supplicant's binary blobs.
2382d4f2939cSRui Paulo  */
wpas_dbus_handler_get_blob(DBusMessage * message,struct wpa_supplicant * wpa_s)2383d4f2939cSRui Paulo DBusMessage * wpas_dbus_handler_get_blob(DBusMessage *message,
2384d4f2939cSRui Paulo 					 struct wpa_supplicant *wpa_s)
2385d4f2939cSRui Paulo {
2386d4f2939cSRui Paulo 	DBusMessage *reply = NULL;
2387d4f2939cSRui Paulo 	DBusMessageIter	iter, array_iter;
2388d4f2939cSRui Paulo 
2389d4f2939cSRui Paulo 	char *blob_name;
2390d4f2939cSRui Paulo 	const struct wpa_config_blob *blob;
2391d4f2939cSRui Paulo 
2392d4f2939cSRui Paulo 	dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &blob_name,
2393d4f2939cSRui Paulo 			      DBUS_TYPE_INVALID);
2394d4f2939cSRui Paulo 
2395d4f2939cSRui Paulo 	blob = wpa_config_get_blob(wpa_s->conf, blob_name);
2396d4f2939cSRui Paulo 	if (!blob) {
2397d4f2939cSRui Paulo 		return dbus_message_new_error(message,
2398d4f2939cSRui Paulo 					      WPAS_DBUS_ERROR_BLOB_UNKNOWN,
2399d4f2939cSRui Paulo 					      "Blob id not set");
2400d4f2939cSRui Paulo 	}
2401d4f2939cSRui Paulo 
2402d4f2939cSRui Paulo 	reply = dbus_message_new_method_return(message);
24035b9c547cSRui Paulo 	if (!reply)
24045b9c547cSRui Paulo 		return wpas_dbus_error_no_memory(message);
2405d4f2939cSRui Paulo 
2406d4f2939cSRui Paulo 	dbus_message_iter_init_append(reply, &iter);
2407d4f2939cSRui Paulo 
2408d4f2939cSRui Paulo 	if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
2409d4f2939cSRui Paulo 					      DBUS_TYPE_BYTE_AS_STRING,
24105b9c547cSRui Paulo 					      &array_iter) ||
24115b9c547cSRui Paulo 	    !dbus_message_iter_append_fixed_array(&array_iter, DBUS_TYPE_BYTE,
24125b9c547cSRui Paulo 						  &(blob->data), blob->len) ||
24135b9c547cSRui Paulo 	    !dbus_message_iter_close_container(&iter, &array_iter)) {
2414d4f2939cSRui Paulo 		dbus_message_unref(reply);
24155b9c547cSRui Paulo 		reply = wpas_dbus_error_no_memory(message);
2416d4f2939cSRui Paulo 	}
2417d4f2939cSRui Paulo 
2418d4f2939cSRui Paulo 	return reply;
2419d4f2939cSRui Paulo }
2420d4f2939cSRui Paulo 
2421d4f2939cSRui Paulo 
2422d4f2939cSRui Paulo /**
2423d4f2939cSRui Paulo  * wpas_remove_handler_remove_blob - Remove named binary blob
2424d4f2939cSRui Paulo  * @message: Pointer to incoming dbus message
2425d4f2939cSRui Paulo  * @wpa_s: %wpa_supplicant data structure
2426d4f2939cSRui Paulo  * Returns: NULL on success or dbus error
2427d4f2939cSRui Paulo  *
2428d4f2939cSRui Paulo  * Asks wpa_supplicant to internally remove a binary blobs.
2429d4f2939cSRui Paulo  */
wpas_dbus_handler_remove_blob(DBusMessage * message,struct wpa_supplicant * wpa_s)2430d4f2939cSRui Paulo DBusMessage * wpas_dbus_handler_remove_blob(DBusMessage *message,
2431d4f2939cSRui Paulo 					    struct wpa_supplicant *wpa_s)
2432d4f2939cSRui Paulo {
2433d4f2939cSRui Paulo 	DBusMessage *reply = NULL;
2434d4f2939cSRui Paulo 	char *blob_name;
2435d4f2939cSRui Paulo 
2436d4f2939cSRui Paulo 	dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &blob_name,
2437d4f2939cSRui Paulo 			      DBUS_TYPE_INVALID);
2438d4f2939cSRui Paulo 
2439d4f2939cSRui Paulo 	if (wpa_config_remove_blob(wpa_s->conf, blob_name)) {
2440d4f2939cSRui Paulo 		return dbus_message_new_error(message,
2441d4f2939cSRui Paulo 					      WPAS_DBUS_ERROR_BLOB_UNKNOWN,
2442d4f2939cSRui Paulo 					      "Blob id not set");
2443d4f2939cSRui Paulo 	}
2444d4f2939cSRui Paulo 	wpas_notify_blob_removed(wpa_s, blob_name);
2445d4f2939cSRui Paulo 
2446d4f2939cSRui Paulo 	return reply;
2447d4f2939cSRui Paulo 
2448d4f2939cSRui Paulo }
2449d4f2939cSRui Paulo 
24505b9c547cSRui Paulo #endif /* CONFIG_NO_CONFIG_BLOBS */
24515b9c547cSRui Paulo 
24525b9c547cSRui Paulo 
2453d4f2939cSRui Paulo /*
2454d4f2939cSRui Paulo  * wpas_dbus_handler_flush_bss - Flush the BSS cache
2455d4f2939cSRui Paulo  * @message: Pointer to incoming dbus message
2456d4f2939cSRui Paulo  * @wpa_s: wpa_supplicant structure for a network interface
2457d4f2939cSRui Paulo  * Returns: NULL
2458d4f2939cSRui Paulo  *
2459d4f2939cSRui Paulo  * Handler function for "FlushBSS" method call of network interface.
2460d4f2939cSRui Paulo  */
wpas_dbus_handler_flush_bss(DBusMessage * message,struct wpa_supplicant * wpa_s)2461d4f2939cSRui Paulo DBusMessage * wpas_dbus_handler_flush_bss(DBusMessage *message,
2462d4f2939cSRui Paulo 					  struct wpa_supplicant *wpa_s)
2463d4f2939cSRui Paulo {
2464d4f2939cSRui Paulo 	dbus_uint32_t age;
2465d4f2939cSRui Paulo 
2466d4f2939cSRui Paulo 	dbus_message_get_args(message, NULL, DBUS_TYPE_UINT32, &age,
2467d4f2939cSRui Paulo 			      DBUS_TYPE_INVALID);
2468d4f2939cSRui Paulo 
2469d4f2939cSRui Paulo 	if (age == 0)
2470d4f2939cSRui Paulo 		wpa_bss_flush(wpa_s);
2471d4f2939cSRui Paulo 	else
2472d4f2939cSRui Paulo 		wpa_bss_flush_by_age(wpa_s, age);
2473d4f2939cSRui Paulo 
2474d4f2939cSRui Paulo 	return NULL;
2475d4f2939cSRui Paulo }
2476d4f2939cSRui Paulo 
2477d4f2939cSRui Paulo 
2478d4f2939cSRui Paulo #ifdef CONFIG_AUTOSCAN
2479d4f2939cSRui Paulo /**
2480d4f2939cSRui Paulo  * wpas_dbus_handler_autoscan - Set autoscan parameters for the interface
2481d4f2939cSRui Paulo  * @message: Pointer to incoming dbus message
2482d4f2939cSRui Paulo  * @wpa_s: wpa_supplicant structure for a network interface
2483d4f2939cSRui Paulo  * Returns: NULL
2484d4f2939cSRui Paulo  *
2485d4f2939cSRui Paulo  * Handler function for "AutoScan" method call of network interface.
2486d4f2939cSRui Paulo  */
wpas_dbus_handler_autoscan(DBusMessage * message,struct wpa_supplicant * wpa_s)2487d4f2939cSRui Paulo DBusMessage * wpas_dbus_handler_autoscan(DBusMessage *message,
2488d4f2939cSRui Paulo 					 struct wpa_supplicant *wpa_s)
2489d4f2939cSRui Paulo {
2490d4f2939cSRui Paulo 	DBusMessage *reply = NULL;
2491d4f2939cSRui Paulo 	enum wpa_states state = wpa_s->wpa_state;
2492d4f2939cSRui Paulo 	char *arg;
2493d4f2939cSRui Paulo 
2494d4f2939cSRui Paulo 	dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &arg,
2495d4f2939cSRui Paulo 			      DBUS_TYPE_INVALID);
2496d4f2939cSRui Paulo 
2497d4f2939cSRui Paulo 	if (arg != NULL && os_strlen(arg) > 0) {
2498d4f2939cSRui Paulo 		char *tmp;
24995b9c547cSRui Paulo 
2500d4f2939cSRui Paulo 		tmp = os_strdup(arg);
2501d4f2939cSRui Paulo 		if (tmp == NULL) {
25025b9c547cSRui Paulo 			reply = wpas_dbus_error_no_memory(message);
2503d4f2939cSRui Paulo 		} else {
2504d4f2939cSRui Paulo 			os_free(wpa_s->conf->autoscan);
2505d4f2939cSRui Paulo 			wpa_s->conf->autoscan = tmp;
2506d4f2939cSRui Paulo 			if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
2507d4f2939cSRui Paulo 				autoscan_init(wpa_s, 1);
2508d4f2939cSRui Paulo 			else if (state == WPA_SCANNING)
2509d4f2939cSRui Paulo 				wpa_supplicant_reinit_autoscan(wpa_s);
2510d4f2939cSRui Paulo 		}
2511d4f2939cSRui Paulo 	} else if (arg != NULL && os_strlen(arg) == 0) {
2512d4f2939cSRui Paulo 		os_free(wpa_s->conf->autoscan);
2513d4f2939cSRui Paulo 		wpa_s->conf->autoscan = NULL;
2514d4f2939cSRui Paulo 		autoscan_deinit(wpa_s);
2515d4f2939cSRui Paulo 	} else
2516d4f2939cSRui Paulo 		reply = dbus_message_new_error(message,
2517d4f2939cSRui Paulo 					       DBUS_ERROR_INVALID_ARGS,
2518d4f2939cSRui Paulo 					       NULL);
2519d4f2939cSRui Paulo 
2520d4f2939cSRui Paulo 	return reply;
2521d4f2939cSRui Paulo }
2522d4f2939cSRui Paulo #endif /* CONFIG_AUTOSCAN */
2523d4f2939cSRui Paulo 
2524d4f2939cSRui Paulo 
25255b9c547cSRui Paulo /*
25265b9c547cSRui Paulo  * wpas_dbus_handler_eap_logoff - IEEE 802.1X EAPOL state machine logoff
25275b9c547cSRui Paulo  * @message: Pointer to incoming dbus message
25285b9c547cSRui Paulo  * @wpa_s: wpa_supplicant structure for a network interface
25295b9c547cSRui Paulo  * Returns: NULL
25305b9c547cSRui Paulo  *
25315b9c547cSRui Paulo  * Handler function for "EAPLogoff" method call of network interface.
25325b9c547cSRui Paulo  */
wpas_dbus_handler_eap_logoff(DBusMessage * message,struct wpa_supplicant * wpa_s)25335b9c547cSRui Paulo DBusMessage * wpas_dbus_handler_eap_logoff(DBusMessage *message,
25345b9c547cSRui Paulo 					   struct wpa_supplicant *wpa_s)
25355b9c547cSRui Paulo {
25365b9c547cSRui Paulo 	eapol_sm_notify_logoff(wpa_s->eapol, TRUE);
25375b9c547cSRui Paulo 	return NULL;
25385b9c547cSRui Paulo }
25395b9c547cSRui Paulo 
25405b9c547cSRui Paulo 
25415b9c547cSRui Paulo /*
25425b9c547cSRui Paulo  * wpas_dbus_handler_eap_logon - IEEE 802.1X EAPOL state machine logon
25435b9c547cSRui Paulo  * @message: Pointer to incoming dbus message
25445b9c547cSRui Paulo  * @wpa_s: wpa_supplicant structure for a network interface
25455b9c547cSRui Paulo  * Returns: NULL
25465b9c547cSRui Paulo  *
25475b9c547cSRui Paulo  * Handler function for "EAPLogin" method call of network interface.
25485b9c547cSRui Paulo  */
wpas_dbus_handler_eap_logon(DBusMessage * message,struct wpa_supplicant * wpa_s)25495b9c547cSRui Paulo DBusMessage * wpas_dbus_handler_eap_logon(DBusMessage *message,
25505b9c547cSRui Paulo 					  struct wpa_supplicant *wpa_s)
25515b9c547cSRui Paulo {
25525b9c547cSRui Paulo 	eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
25535b9c547cSRui Paulo 	return NULL;
25545b9c547cSRui Paulo }
25555b9c547cSRui Paulo 
25565b9c547cSRui Paulo 
25575b9c547cSRui Paulo #ifdef CONFIG_TDLS
25585b9c547cSRui Paulo 
get_peer_hwaddr_helper(DBusMessage * message,const char * func_name,u8 * peer_address,DBusMessage ** error)25595b9c547cSRui Paulo static int get_peer_hwaddr_helper(DBusMessage *message, const char *func_name,
25605b9c547cSRui Paulo 				  u8 *peer_address, DBusMessage **error)
25615b9c547cSRui Paulo {
25625b9c547cSRui Paulo 	const char *peer_string;
25635b9c547cSRui Paulo 
25645b9c547cSRui Paulo 	*error = NULL;
25655b9c547cSRui Paulo 
25665b9c547cSRui Paulo 	if (!dbus_message_get_args(message, NULL,
25675b9c547cSRui Paulo 				   DBUS_TYPE_STRING, &peer_string,
25685b9c547cSRui Paulo 				   DBUS_TYPE_INVALID)) {
25695b9c547cSRui Paulo 		*error = wpas_dbus_error_invalid_args(message, NULL);
25705b9c547cSRui Paulo 		return -1;
25715b9c547cSRui Paulo 	}
25725b9c547cSRui Paulo 
25735b9c547cSRui Paulo 	if (hwaddr_aton(peer_string, peer_address)) {
25745b9c547cSRui Paulo 		wpa_printf(MSG_DEBUG, "%s: invalid address '%s'",
25755b9c547cSRui Paulo 			   func_name, peer_string);
25765b9c547cSRui Paulo 		*error = wpas_dbus_error_invalid_args(
25775b9c547cSRui Paulo 			message, "Invalid hardware address format");
25785b9c547cSRui Paulo 		return -1;
25795b9c547cSRui Paulo 	}
25805b9c547cSRui Paulo 
25815b9c547cSRui Paulo 	return 0;
25825b9c547cSRui Paulo }
25835b9c547cSRui Paulo 
25845b9c547cSRui Paulo 
25855b9c547cSRui Paulo /*
25865b9c547cSRui Paulo  * wpas_dbus_handler_tdls_discover - Discover TDLS peer
25875b9c547cSRui Paulo  * @message: Pointer to incoming dbus message
25885b9c547cSRui Paulo  * @wpa_s: wpa_supplicant structure for a network interface
25895b9c547cSRui Paulo  * Returns: NULL indicating success or DBus error message on failure
25905b9c547cSRui Paulo  *
25915b9c547cSRui Paulo  * Handler function for "TDLSDiscover" method call of network interface.
25925b9c547cSRui Paulo  */
wpas_dbus_handler_tdls_discover(DBusMessage * message,struct wpa_supplicant * wpa_s)25935b9c547cSRui Paulo DBusMessage * wpas_dbus_handler_tdls_discover(DBusMessage *message,
25945b9c547cSRui Paulo 					      struct wpa_supplicant *wpa_s)
25955b9c547cSRui Paulo {
25965b9c547cSRui Paulo 	u8 peer[ETH_ALEN];
25975b9c547cSRui Paulo 	DBusMessage *error_reply;
25985b9c547cSRui Paulo 	int ret;
25995b9c547cSRui Paulo 
26005b9c547cSRui Paulo 	if (get_peer_hwaddr_helper(message, __func__, peer, &error_reply) < 0)
26015b9c547cSRui Paulo 		return error_reply;
26025b9c547cSRui Paulo 
26035b9c547cSRui Paulo 	wpa_printf(MSG_DEBUG, "DBUS TDLS_DISCOVER " MACSTR, MAC2STR(peer));
26045b9c547cSRui Paulo 
26055b9c547cSRui Paulo 	if (wpa_tdls_is_external_setup(wpa_s->wpa))
26065b9c547cSRui Paulo 		ret = wpa_tdls_send_discovery_request(wpa_s->wpa, peer);
26075b9c547cSRui Paulo 	else
26085b9c547cSRui Paulo 		ret = wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer);
26095b9c547cSRui Paulo 
26105b9c547cSRui Paulo 	if (ret) {
26115b9c547cSRui Paulo 		return wpas_dbus_error_unknown_error(
26125b9c547cSRui Paulo 			message, "error performing TDLS discovery");
26135b9c547cSRui Paulo 	}
26145b9c547cSRui Paulo 
26155b9c547cSRui Paulo 	return NULL;
26165b9c547cSRui Paulo }
26175b9c547cSRui Paulo 
26185b9c547cSRui Paulo 
26195b9c547cSRui Paulo /*
26205b9c547cSRui Paulo  * wpas_dbus_handler_tdls_setup - Setup TDLS session
26215b9c547cSRui Paulo  * @message: Pointer to incoming dbus message
26225b9c547cSRui Paulo  * @wpa_s: wpa_supplicant structure for a network interface
26235b9c547cSRui Paulo  * Returns: NULL indicating success or DBus error message on failure
26245b9c547cSRui Paulo  *
26255b9c547cSRui Paulo  * Handler function for "TDLSSetup" method call of network interface.
26265b9c547cSRui Paulo  */
wpas_dbus_handler_tdls_setup(DBusMessage * message,struct wpa_supplicant * wpa_s)26275b9c547cSRui Paulo DBusMessage * wpas_dbus_handler_tdls_setup(DBusMessage *message,
26285b9c547cSRui Paulo 					   struct wpa_supplicant *wpa_s)
26295b9c547cSRui Paulo {
26305b9c547cSRui Paulo 	u8 peer[ETH_ALEN];
26315b9c547cSRui Paulo 	DBusMessage *error_reply;
26325b9c547cSRui Paulo 	int ret;
26335b9c547cSRui Paulo 
26345b9c547cSRui Paulo 	if (get_peer_hwaddr_helper(message, __func__, peer, &error_reply) < 0)
26355b9c547cSRui Paulo 		return error_reply;
26365b9c547cSRui Paulo 
26375b9c547cSRui Paulo 	wpa_printf(MSG_DEBUG, "DBUS TDLS_SETUP " MACSTR, MAC2STR(peer));
26385b9c547cSRui Paulo 
26395b9c547cSRui Paulo 	wpa_tdls_remove(wpa_s->wpa, peer);
26405b9c547cSRui Paulo 	if (wpa_tdls_is_external_setup(wpa_s->wpa))
26415b9c547cSRui Paulo 		ret = wpa_tdls_start(wpa_s->wpa, peer);
26425b9c547cSRui Paulo 	else
26435b9c547cSRui Paulo 		ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
26445b9c547cSRui Paulo 
26455b9c547cSRui Paulo 	if (ret) {
26465b9c547cSRui Paulo 		return wpas_dbus_error_unknown_error(
26475b9c547cSRui Paulo 			message, "error performing TDLS setup");
26485b9c547cSRui Paulo 	}
26495b9c547cSRui Paulo 
26505b9c547cSRui Paulo 	return NULL;
26515b9c547cSRui Paulo }
26525b9c547cSRui Paulo 
26535b9c547cSRui Paulo 
26545b9c547cSRui Paulo /*
26555b9c547cSRui Paulo  * wpas_dbus_handler_tdls_status - Return TDLS session status
26565b9c547cSRui Paulo  * @message: Pointer to incoming dbus message
26575b9c547cSRui Paulo  * @wpa_s: wpa_supplicant structure for a network interface
26585b9c547cSRui Paulo  * Returns: A string representing the state of the link to this TDLS peer
26595b9c547cSRui Paulo  *
26605b9c547cSRui Paulo  * Handler function for "TDLSStatus" method call of network interface.
26615b9c547cSRui Paulo  */
wpas_dbus_handler_tdls_status(DBusMessage * message,struct wpa_supplicant * wpa_s)26625b9c547cSRui Paulo DBusMessage * wpas_dbus_handler_tdls_status(DBusMessage *message,
26635b9c547cSRui Paulo 					    struct wpa_supplicant *wpa_s)
26645b9c547cSRui Paulo {
26655b9c547cSRui Paulo 	u8 peer[ETH_ALEN];
26665b9c547cSRui Paulo 	DBusMessage *reply;
26675b9c547cSRui Paulo 	const char *tdls_status;
26685b9c547cSRui Paulo 
26695b9c547cSRui Paulo 	if (get_peer_hwaddr_helper(message, __func__, peer, &reply) < 0)
26705b9c547cSRui Paulo 		return reply;
26715b9c547cSRui Paulo 
26725b9c547cSRui Paulo 	wpa_printf(MSG_DEBUG, "DBUS TDLS_STATUS " MACSTR, MAC2STR(peer));
26735b9c547cSRui Paulo 
26745b9c547cSRui Paulo 	tdls_status = wpa_tdls_get_link_status(wpa_s->wpa, peer);
26755b9c547cSRui Paulo 
26765b9c547cSRui Paulo 	reply = dbus_message_new_method_return(message);
26775b9c547cSRui Paulo 	dbus_message_append_args(reply, DBUS_TYPE_STRING,
26785b9c547cSRui Paulo 				 &tdls_status, DBUS_TYPE_INVALID);
26795b9c547cSRui Paulo 	return reply;
26805b9c547cSRui Paulo }
26815b9c547cSRui Paulo 
26825b9c547cSRui Paulo 
26835b9c547cSRui Paulo /*
26845b9c547cSRui Paulo  * wpas_dbus_handler_tdls_teardown - Teardown TDLS session
26855b9c547cSRui Paulo  * @message: Pointer to incoming dbus message
26865b9c547cSRui Paulo  * @wpa_s: wpa_supplicant structure for a network interface
26875b9c547cSRui Paulo  * Returns: NULL indicating success or DBus error message on failure
26885b9c547cSRui Paulo  *
26895b9c547cSRui Paulo  * Handler function for "TDLSTeardown" method call of network interface.
26905b9c547cSRui Paulo  */
wpas_dbus_handler_tdls_teardown(DBusMessage * message,struct wpa_supplicant * wpa_s)26915b9c547cSRui Paulo DBusMessage * wpas_dbus_handler_tdls_teardown(DBusMessage *message,
26925b9c547cSRui Paulo 					      struct wpa_supplicant *wpa_s)
26935b9c547cSRui Paulo {
26945b9c547cSRui Paulo 	u8 peer[ETH_ALEN];
26955b9c547cSRui Paulo 	DBusMessage *error_reply;
26965b9c547cSRui Paulo 	int ret;
26975b9c547cSRui Paulo 
26985b9c547cSRui Paulo 	if (get_peer_hwaddr_helper(message, __func__, peer, &error_reply) < 0)
26995b9c547cSRui Paulo 		return error_reply;
27005b9c547cSRui Paulo 
27015b9c547cSRui Paulo 	wpa_printf(MSG_DEBUG, "DBUS TDLS_TEARDOWN " MACSTR, MAC2STR(peer));
27025b9c547cSRui Paulo 
27035b9c547cSRui Paulo 	if (wpa_tdls_is_external_setup(wpa_s->wpa))
27045b9c547cSRui Paulo 		ret = wpa_tdls_teardown_link(
27055b9c547cSRui Paulo 			wpa_s->wpa, peer,
27065b9c547cSRui Paulo 			WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
27075b9c547cSRui Paulo 	else
27085b9c547cSRui Paulo 		ret = wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
27095b9c547cSRui Paulo 
27105b9c547cSRui Paulo 	if (ret) {
27115b9c547cSRui Paulo 		return wpas_dbus_error_unknown_error(
27125b9c547cSRui Paulo 			message, "error performing TDLS teardown");
27135b9c547cSRui Paulo 	}
27145b9c547cSRui Paulo 
27155b9c547cSRui Paulo 	return NULL;
27165b9c547cSRui Paulo }
27175b9c547cSRui Paulo 
271885732ac8SCy Schubert /*
271985732ac8SCy Schubert  * wpas_dbus_handler_tdls_channel_switch - Enable channel switching with TDLS peer
272085732ac8SCy Schubert  * @message: Pointer to incoming dbus message
272185732ac8SCy Schubert  * @wpa_s: wpa_supplicant structure for a network interface
272285732ac8SCy Schubert  * Returns: NULL indicating success or DBus error message on failure
272385732ac8SCy Schubert  *
272485732ac8SCy Schubert  * Handler function for "TDLSChannelSwitch" method call of network interface.
272585732ac8SCy Schubert  */
272685732ac8SCy Schubert DBusMessage *
wpas_dbus_handler_tdls_channel_switch(DBusMessage * message,struct wpa_supplicant * wpa_s)272785732ac8SCy Schubert wpas_dbus_handler_tdls_channel_switch(DBusMessage *message,
272885732ac8SCy Schubert 				      struct wpa_supplicant *wpa_s)
272985732ac8SCy Schubert {
273085732ac8SCy Schubert 	DBusMessageIter	iter, iter_dict;
273185732ac8SCy Schubert 	struct wpa_dbus_dict_entry entry;
273285732ac8SCy Schubert 	u8 peer[ETH_ALEN];
273385732ac8SCy Schubert 	struct hostapd_freq_params freq_params;
273485732ac8SCy Schubert 	u8 oper_class = 0;
273585732ac8SCy Schubert 	int ret;
273685732ac8SCy Schubert 	int is_peer_present = 0;
273785732ac8SCy Schubert 
273885732ac8SCy Schubert 	if (!wpa_tdls_is_external_setup(wpa_s->wpa)) {
273985732ac8SCy Schubert 		wpa_printf(MSG_INFO,
274085732ac8SCy Schubert 			   "tdls_chanswitch: Only supported with external setup");
274185732ac8SCy Schubert 		return wpas_dbus_error_unknown_error(message, "TDLS is not using external setup");
274285732ac8SCy Schubert 	}
274385732ac8SCy Schubert 
274485732ac8SCy Schubert 	os_memset(&freq_params, 0, sizeof(freq_params));
274585732ac8SCy Schubert 
274685732ac8SCy Schubert 	dbus_message_iter_init(message, &iter);
274785732ac8SCy Schubert 
274885732ac8SCy Schubert 	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
274985732ac8SCy Schubert 		return wpas_dbus_error_invalid_args(message, NULL);
275085732ac8SCy Schubert 
275185732ac8SCy Schubert 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
275285732ac8SCy Schubert 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
275385732ac8SCy Schubert 			return wpas_dbus_error_invalid_args(message, NULL);
275485732ac8SCy Schubert 
275585732ac8SCy Schubert 		if (os_strcmp(entry.key, "PeerAddress") == 0 &&
275685732ac8SCy Schubert 		    entry.type == DBUS_TYPE_STRING) {
275785732ac8SCy Schubert 			if (hwaddr_aton(entry.str_value, peer)) {
275885732ac8SCy Schubert 				wpa_printf(MSG_DEBUG,
275985732ac8SCy Schubert 					   "tdls_chanswitch: Invalid address '%s'",
276085732ac8SCy Schubert 					   entry.str_value);
276185732ac8SCy Schubert 				wpa_dbus_dict_entry_clear(&entry);
276285732ac8SCy Schubert 				return wpas_dbus_error_invalid_args(message,
276385732ac8SCy Schubert 								    NULL);
276485732ac8SCy Schubert 			}
276585732ac8SCy Schubert 
276685732ac8SCy Schubert 			is_peer_present = 1;
276785732ac8SCy Schubert 		} else if (os_strcmp(entry.key, "OperClass") == 0 &&
276885732ac8SCy Schubert 			   entry.type == DBUS_TYPE_BYTE) {
276985732ac8SCy Schubert 			oper_class = entry.byte_value;
277085732ac8SCy Schubert 		} else if (os_strcmp(entry.key, "Frequency") == 0 &&
277185732ac8SCy Schubert 			   entry.type == DBUS_TYPE_UINT32) {
277285732ac8SCy Schubert 			freq_params.freq = entry.uint32_value;
277385732ac8SCy Schubert 		} else if (os_strcmp(entry.key, "SecChannelOffset") == 0 &&
277485732ac8SCy Schubert 			   entry.type == DBUS_TYPE_UINT32) {
277585732ac8SCy Schubert 			freq_params.sec_channel_offset = entry.uint32_value;
277685732ac8SCy Schubert 		} else if (os_strcmp(entry.key, "CenterFrequency1") == 0 &&
277785732ac8SCy Schubert 			   entry.type == DBUS_TYPE_UINT32) {
277885732ac8SCy Schubert 			freq_params.center_freq1 = entry.uint32_value;
277985732ac8SCy Schubert 		} else if (os_strcmp(entry.key, "CenterFrequency2") == 0 &&
278085732ac8SCy Schubert 			   entry.type == DBUS_TYPE_UINT32) {
278185732ac8SCy Schubert 			freq_params.center_freq2 = entry.uint32_value;
278285732ac8SCy Schubert 		} else if (os_strcmp(entry.key, "Bandwidth") == 0 &&
278385732ac8SCy Schubert 			   entry.type == DBUS_TYPE_UINT32) {
278485732ac8SCy Schubert 			freq_params.bandwidth = entry.uint32_value;
278585732ac8SCy Schubert 		} else if (os_strcmp(entry.key, "HT") == 0 &&
278685732ac8SCy Schubert 			   entry.type == DBUS_TYPE_BOOLEAN) {
278785732ac8SCy Schubert 			freq_params.ht_enabled = entry.bool_value;
278885732ac8SCy Schubert 		} else if (os_strcmp(entry.key, "VHT") == 0 &&
278985732ac8SCy Schubert 			   entry.type == DBUS_TYPE_BOOLEAN) {
279085732ac8SCy Schubert 			freq_params.vht_enabled = entry.bool_value;
279185732ac8SCy Schubert 		} else {
279285732ac8SCy Schubert 			wpa_dbus_dict_entry_clear(&entry);
279385732ac8SCy Schubert 			return wpas_dbus_error_invalid_args(message, NULL);
279485732ac8SCy Schubert 		}
279585732ac8SCy Schubert 
279685732ac8SCy Schubert 		wpa_dbus_dict_entry_clear(&entry);
279785732ac8SCy Schubert 	}
279885732ac8SCy Schubert 
279985732ac8SCy Schubert 	if (oper_class == 0) {
280085732ac8SCy Schubert 		wpa_printf(MSG_INFO,
280185732ac8SCy Schubert 			   "tdls_chanswitch: Invalid op class provided");
280285732ac8SCy Schubert 		return wpas_dbus_error_invalid_args(
280385732ac8SCy Schubert 			message, "Invalid op class provided");
280485732ac8SCy Schubert 	}
280585732ac8SCy Schubert 
280685732ac8SCy Schubert 	if (freq_params.freq == 0) {
280785732ac8SCy Schubert 		wpa_printf(MSG_INFO,
280885732ac8SCy Schubert 			   "tdls_chanswitch: Invalid freq provided");
280985732ac8SCy Schubert 		return wpas_dbus_error_invalid_args(message,
281085732ac8SCy Schubert 						    "Invalid freq provided");
281185732ac8SCy Schubert 	}
281285732ac8SCy Schubert 
281385732ac8SCy Schubert 	if (is_peer_present == 0) {
281485732ac8SCy Schubert 		wpa_printf(MSG_DEBUG,
281585732ac8SCy Schubert 			   "tdls_chanswitch: peer address not provided");
281685732ac8SCy Schubert 		return wpas_dbus_error_invalid_args(
281785732ac8SCy Schubert 			message, "peer address not provided");
281885732ac8SCy Schubert 	}
281985732ac8SCy Schubert 
282085732ac8SCy Schubert 	wpa_printf(MSG_DEBUG, "dbus: TDLS_CHAN_SWITCH " MACSTR
282185732ac8SCy Schubert 		   " OP CLASS %d FREQ %d CENTER1 %d CENTER2 %d BW %d SEC_OFFSET %d%s%s",
282285732ac8SCy Schubert 		   MAC2STR(peer), oper_class, freq_params.freq,
282385732ac8SCy Schubert 		   freq_params.center_freq1, freq_params.center_freq2,
282485732ac8SCy Schubert 		   freq_params.bandwidth, freq_params.sec_channel_offset,
282585732ac8SCy Schubert 		   freq_params.ht_enabled ? " HT" : "",
282685732ac8SCy Schubert 		   freq_params.vht_enabled ? " VHT" : "");
282785732ac8SCy Schubert 
282885732ac8SCy Schubert 	ret = wpa_tdls_enable_chan_switch(wpa_s->wpa, peer, oper_class,
282985732ac8SCy Schubert 					  &freq_params);
283085732ac8SCy Schubert 	if (ret)
283185732ac8SCy Schubert 		return wpas_dbus_error_unknown_error(
283285732ac8SCy Schubert 			message, "error processing TDLS channel switch");
283385732ac8SCy Schubert 
283485732ac8SCy Schubert 	return NULL;
283585732ac8SCy Schubert }
283685732ac8SCy Schubert 
283785732ac8SCy Schubert /*
283885732ac8SCy Schubert  * wpas_dbus_handler_tdls_cancel_channel_switch - Disable channel switching with TDLS peer
283985732ac8SCy Schubert  * @message: Pointer to incoming dbus message
284085732ac8SCy Schubert  * @wpa_s: wpa_supplicant structure for a network interface
284185732ac8SCy Schubert  * Returns: NULL indicating success or DBus error message on failure
284285732ac8SCy Schubert  *
284385732ac8SCy Schubert  * Handler function for "TDLSCancelChannelSwitch" method call of network
284485732ac8SCy Schubert  * interface.
284585732ac8SCy Schubert  */
284685732ac8SCy Schubert DBusMessage *
wpas_dbus_handler_tdls_cancel_channel_switch(DBusMessage * message,struct wpa_supplicant * wpa_s)284785732ac8SCy Schubert wpas_dbus_handler_tdls_cancel_channel_switch(DBusMessage *message,
284885732ac8SCy Schubert 					     struct wpa_supplicant *wpa_s)
284985732ac8SCy Schubert {
285085732ac8SCy Schubert 	u8 peer[ETH_ALEN];
285185732ac8SCy Schubert 	DBusMessage *error_reply;
285285732ac8SCy Schubert 	int ret;
285385732ac8SCy Schubert 
285485732ac8SCy Schubert 	if (get_peer_hwaddr_helper(message, __func__, peer, &error_reply) < 0)
285585732ac8SCy Schubert 		return error_reply;
285685732ac8SCy Schubert 
285785732ac8SCy Schubert 	wpa_printf(MSG_DEBUG, "dbus: TDLS_CANCEL_CHAN_SWITCH " MACSTR,
285885732ac8SCy Schubert 		   MAC2STR(peer));
285985732ac8SCy Schubert 
286085732ac8SCy Schubert 	ret = wpa_tdls_disable_chan_switch(wpa_s->wpa, peer);
286185732ac8SCy Schubert 	if (ret)
286285732ac8SCy Schubert 		return wpas_dbus_error_unknown_error(
286385732ac8SCy Schubert 			message, "error canceling TDLS channel switch");
286485732ac8SCy Schubert 
286585732ac8SCy Schubert 	return NULL;
286685732ac8SCy Schubert }
286785732ac8SCy Schubert 
28685b9c547cSRui Paulo #endif /* CONFIG_TDLS */
28695b9c547cSRui Paulo 
28705b9c547cSRui Paulo 
2871780fb4a2SCy Schubert #ifndef CONFIG_NO_CONFIG_WRITE
2872780fb4a2SCy Schubert /**
2873780fb4a2SCy Schubert  * wpas_dbus_handler_save_config - Save configuration to configuration file
2874780fb4a2SCy Schubert  * @message: Pointer to incoming dbus message
2875780fb4a2SCy Schubert  * @wpa_s: wpa_supplicant structure for a network interface
2876c1d255d3SCy Schubert  * Returns: NULL on Success, Otherwise error message
2877780fb4a2SCy Schubert  *
2878780fb4a2SCy Schubert  * Handler function for "SaveConfig" method call of network interface.
2879780fb4a2SCy Schubert  */
wpas_dbus_handler_save_config(DBusMessage * message,struct wpa_supplicant * wpa_s)2880780fb4a2SCy Schubert DBusMessage * wpas_dbus_handler_save_config(DBusMessage *message,
2881780fb4a2SCy Schubert 					    struct wpa_supplicant *wpa_s)
2882780fb4a2SCy Schubert {
2883780fb4a2SCy Schubert 	int ret;
2884780fb4a2SCy Schubert 
2885780fb4a2SCy Schubert 	if (!wpa_s->conf->update_config) {
2886780fb4a2SCy Schubert 		return wpas_dbus_error_unknown_error(
2887780fb4a2SCy Schubert 			message,
2888780fb4a2SCy Schubert 			"Not allowed to update configuration (update_config=0)");
2889780fb4a2SCy Schubert 	}
2890780fb4a2SCy Schubert 
2891780fb4a2SCy Schubert 	ret = wpa_config_write(wpa_s->confname, wpa_s->conf);
2892780fb4a2SCy Schubert 	if (ret)
2893780fb4a2SCy Schubert 		return wpas_dbus_error_unknown_error(
2894780fb4a2SCy Schubert 			message, "Failed to update configuration");
2895780fb4a2SCy Schubert 	return NULL;
2896780fb4a2SCy Schubert }
2897780fb4a2SCy Schubert #endif /* CONFIG_NO_CONFIG_WRITE */
2898780fb4a2SCy Schubert 
2899780fb4a2SCy Schubert 
29005b9c547cSRui Paulo /**
29015b9c547cSRui Paulo  * wpas_dbus_handler_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
29025b9c547cSRui Paulo  * @message: Pointer to incoming dbus message
29035b9c547cSRui Paulo  * @wpa_s: %wpa_supplicant data structure
29045b9c547cSRui Paulo  * Returns: A dbus message containing an error on failure or NULL on success
29055b9c547cSRui Paulo  *
29065b9c547cSRui Paulo  * Sets the PKCS #11 engine and module path.
29075b9c547cSRui Paulo  */
wpas_dbus_handler_set_pkcs11_engine_and_module_path(DBusMessage * message,struct wpa_supplicant * wpa_s)29085b9c547cSRui Paulo DBusMessage * wpas_dbus_handler_set_pkcs11_engine_and_module_path(
29095b9c547cSRui Paulo 	DBusMessage *message, struct wpa_supplicant *wpa_s)
29105b9c547cSRui Paulo {
29115b9c547cSRui Paulo 	DBusMessageIter iter;
29125b9c547cSRui Paulo 	char *value = NULL;
29135b9c547cSRui Paulo 	char *pkcs11_engine_path = NULL;
29145b9c547cSRui Paulo 	char *pkcs11_module_path = NULL;
29155b9c547cSRui Paulo 
29165b9c547cSRui Paulo 	dbus_message_iter_init(message, &iter);
29175b9c547cSRui Paulo 	dbus_message_iter_get_basic(&iter, &value);
29185b9c547cSRui Paulo 	if (value == NULL) {
29195b9c547cSRui Paulo 		return dbus_message_new_error(
29205b9c547cSRui Paulo 			message, DBUS_ERROR_INVALID_ARGS,
29215b9c547cSRui Paulo 			"Invalid pkcs11_engine_path argument");
29225b9c547cSRui Paulo 	}
29235b9c547cSRui Paulo 	/* Empty path defaults to NULL */
29245b9c547cSRui Paulo 	if (os_strlen(value))
29255b9c547cSRui Paulo 		pkcs11_engine_path = value;
29265b9c547cSRui Paulo 
29275b9c547cSRui Paulo 	dbus_message_iter_next(&iter);
29285b9c547cSRui Paulo 	dbus_message_iter_get_basic(&iter, &value);
29295b9c547cSRui Paulo 	if (value == NULL) {
29305b9c547cSRui Paulo 		os_free(pkcs11_engine_path);
29315b9c547cSRui Paulo 		return dbus_message_new_error(
29325b9c547cSRui Paulo 			message, DBUS_ERROR_INVALID_ARGS,
29335b9c547cSRui Paulo 			"Invalid pkcs11_module_path argument");
29345b9c547cSRui Paulo 	}
29355b9c547cSRui Paulo 	/* Empty path defaults to NULL */
29365b9c547cSRui Paulo 	if (os_strlen(value))
29375b9c547cSRui Paulo 		pkcs11_module_path = value;
29385b9c547cSRui Paulo 
29395b9c547cSRui Paulo 	if (wpas_set_pkcs11_engine_and_module_path(wpa_s, pkcs11_engine_path,
29405b9c547cSRui Paulo 						   pkcs11_module_path))
29415b9c547cSRui Paulo 		return dbus_message_new_error(
29425b9c547cSRui Paulo 			message, DBUS_ERROR_FAILED,
29435b9c547cSRui Paulo 			"Reinit of the EAPOL state machine with the new PKCS #11 engine and module path failed.");
29445b9c547cSRui Paulo 
2945325151a3SRui Paulo 	if (wpa_s->dbus_new_path) {
29465b9c547cSRui Paulo 		wpa_dbus_mark_property_changed(
29475b9c547cSRui Paulo 			wpa_s->global->dbus, wpa_s->dbus_new_path,
29485b9c547cSRui Paulo 			WPAS_DBUS_NEW_IFACE_INTERFACE, "PKCS11EnginePath");
29495b9c547cSRui Paulo 		wpa_dbus_mark_property_changed(
29505b9c547cSRui Paulo 			wpa_s->global->dbus, wpa_s->dbus_new_path,
29515b9c547cSRui Paulo 			WPAS_DBUS_NEW_IFACE_INTERFACE, "PKCS11ModulePath");
2952325151a3SRui Paulo 	}
29535b9c547cSRui Paulo 
29545b9c547cSRui Paulo 	return NULL;
29555b9c547cSRui Paulo }
29565b9c547cSRui Paulo 
29575b9c547cSRui Paulo 
2958d4f2939cSRui Paulo /**
2959d4f2939cSRui Paulo  * wpas_dbus_getter_capabilities - Return interface capabilities
2960d4f2939cSRui Paulo  * @iter: Pointer to incoming dbus message iter
2961d4f2939cSRui Paulo  * @error: Location to store error on failure
2962d4f2939cSRui Paulo  * @user_data: Function specific data
2963d4f2939cSRui Paulo  * Returns: TRUE on success, FALSE on failure
2964d4f2939cSRui Paulo  *
2965d4f2939cSRui Paulo  * Getter for "Capabilities" property of an interface.
2966d4f2939cSRui Paulo  */
wpas_dbus_getter_capabilities(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)2967780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_capabilities(
2968780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
2969780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
2970d4f2939cSRui Paulo {
2971d4f2939cSRui Paulo 	struct wpa_supplicant *wpa_s = user_data;
2972d4f2939cSRui Paulo 	struct wpa_driver_capa capa;
2973d4f2939cSRui Paulo 	int res;
2974d4f2939cSRui Paulo 	DBusMessageIter iter_dict, iter_dict_entry, iter_dict_val, iter_array,
2975d4f2939cSRui Paulo 		variant_iter;
2976d4f2939cSRui Paulo 	const char *scans[] = { "active", "passive", "ssid" };
2977d4f2939cSRui Paulo 
2978d4f2939cSRui Paulo 	if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
29795b9c547cSRui Paulo 					      "a{sv}", &variant_iter) ||
29805b9c547cSRui Paulo 	    !wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
2981d4f2939cSRui Paulo 		goto nomem;
2982d4f2939cSRui Paulo 
2983d4f2939cSRui Paulo 	res = wpa_drv_get_capa(wpa_s, &capa);
2984d4f2939cSRui Paulo 
2985d4f2939cSRui Paulo 	/***** pairwise cipher */
2986d4f2939cSRui Paulo 	if (res < 0) {
2987c1d255d3SCy Schubert #ifdef CONFIG_NO_TKIP
2988c1d255d3SCy Schubert 		const char *args[] = {"ccmp", "none"};
2989c1d255d3SCy Schubert #else /* CONFIG_NO_TKIP */
2990d4f2939cSRui Paulo 		const char *args[] = {"ccmp", "tkip", "none"};
2991c1d255d3SCy Schubert #endif /* CONFIG_NO_TKIP */
29925b9c547cSRui Paulo 
2993d4f2939cSRui Paulo 		if (!wpa_dbus_dict_append_string_array(
2994d4f2939cSRui Paulo 			    &iter_dict, "Pairwise", args,
29955b9c547cSRui Paulo 			    ARRAY_SIZE(args)))
2996d4f2939cSRui Paulo 			goto nomem;
2997d4f2939cSRui Paulo 	} else {
2998d4f2939cSRui Paulo 		if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Pairwise",
2999d4f2939cSRui Paulo 						      &iter_dict_entry,
3000d4f2939cSRui Paulo 						      &iter_dict_val,
30015b9c547cSRui Paulo 						      &iter_array) ||
30025b9c547cSRui Paulo 		    ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP_256) &&
30035b9c547cSRui Paulo 		     !wpa_dbus_dict_string_array_add_element(
30045b9c547cSRui Paulo 			     &iter_array, "ccmp-256")) ||
30055b9c547cSRui Paulo 		    ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP_256) &&
30065b9c547cSRui Paulo 		     !wpa_dbus_dict_string_array_add_element(
30075b9c547cSRui Paulo 			     &iter_array, "gcmp-256")) ||
30085b9c547cSRui Paulo 		    ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) &&
30095b9c547cSRui Paulo 		     !wpa_dbus_dict_string_array_add_element(
30105b9c547cSRui Paulo 			     &iter_array, "ccmp")) ||
30115b9c547cSRui Paulo 		    ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP) &&
30125b9c547cSRui Paulo 		     !wpa_dbus_dict_string_array_add_element(
30135b9c547cSRui Paulo 			     &iter_array, "gcmp")) ||
3014c1d255d3SCy Schubert #ifndef CONFIG_NO_TKIP
30155b9c547cSRui Paulo 		    ((capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) &&
30165b9c547cSRui Paulo 		     !wpa_dbus_dict_string_array_add_element(
30175b9c547cSRui Paulo 			     &iter_array, "tkip")) ||
3018c1d255d3SCy Schubert #endif /* CONFIG_NO_TKIP */
30195b9c547cSRui Paulo 		    ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) &&
30205b9c547cSRui Paulo 		     !wpa_dbus_dict_string_array_add_element(
30215b9c547cSRui Paulo 			     &iter_array, "none")) ||
30225b9c547cSRui Paulo 		    !wpa_dbus_dict_end_string_array(&iter_dict,
3023d4f2939cSRui Paulo 						    &iter_dict_entry,
3024d4f2939cSRui Paulo 						    &iter_dict_val,
3025d4f2939cSRui Paulo 						    &iter_array))
3026d4f2939cSRui Paulo 			goto nomem;
3027d4f2939cSRui Paulo 	}
3028d4f2939cSRui Paulo 
3029d4f2939cSRui Paulo 	/***** group cipher */
3030d4f2939cSRui Paulo 	if (res < 0) {
3031d4f2939cSRui Paulo 		const char *args[] = {
3032c1d255d3SCy Schubert 			"ccmp",
3033c1d255d3SCy Schubert #ifndef CONFIG_NO_TKIP
3034c1d255d3SCy Schubert 			"tkip",
3035c1d255d3SCy Schubert #endif /* CONFIG_NO_TKIP */
3036c1d255d3SCy Schubert #ifdef CONFIG_WEP
3037c1d255d3SCy Schubert 			"wep104", "wep40"
3038c1d255d3SCy Schubert #endif /* CONFIG_WEP */
3039d4f2939cSRui Paulo 		};
30405b9c547cSRui Paulo 
3041d4f2939cSRui Paulo 		if (!wpa_dbus_dict_append_string_array(
3042d4f2939cSRui Paulo 			    &iter_dict, "Group", args,
30435b9c547cSRui Paulo 			    ARRAY_SIZE(args)))
3044d4f2939cSRui Paulo 			goto nomem;
3045d4f2939cSRui Paulo 	} else {
3046d4f2939cSRui Paulo 		if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Group",
3047d4f2939cSRui Paulo 						      &iter_dict_entry,
3048d4f2939cSRui Paulo 						      &iter_dict_val,
30495b9c547cSRui Paulo 						      &iter_array) ||
30505b9c547cSRui Paulo 		    ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP_256) &&
30515b9c547cSRui Paulo 		     !wpa_dbus_dict_string_array_add_element(
30525b9c547cSRui Paulo 			     &iter_array, "ccmp-256")) ||
30535b9c547cSRui Paulo 		    ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP_256) &&
30545b9c547cSRui Paulo 		     !wpa_dbus_dict_string_array_add_element(
30555b9c547cSRui Paulo 			     &iter_array, "gcmp-256")) ||
30565b9c547cSRui Paulo 		    ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) &&
30575b9c547cSRui Paulo 		     !wpa_dbus_dict_string_array_add_element(
30585b9c547cSRui Paulo 			     &iter_array, "ccmp")) ||
30595b9c547cSRui Paulo 		    ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP) &&
30605b9c547cSRui Paulo 		     !wpa_dbus_dict_string_array_add_element(
30615b9c547cSRui Paulo 			     &iter_array, "gcmp")) ||
3062c1d255d3SCy Schubert #ifndef CONFIG_NO_TKIP
30635b9c547cSRui Paulo 		    ((capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) &&
30645b9c547cSRui Paulo 		     !wpa_dbus_dict_string_array_add_element(
30655b9c547cSRui Paulo 			     &iter_array, "tkip")) ||
3066c1d255d3SCy Schubert #endif /* CONFIG_NO_TKIP */
3067c1d255d3SCy Schubert #ifdef CONFIG_WEP
30685b9c547cSRui Paulo 		    ((capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) &&
30695b9c547cSRui Paulo 		     !wpa_dbus_dict_string_array_add_element(
30705b9c547cSRui Paulo 			     &iter_array, "wep104")) ||
30715b9c547cSRui Paulo 		    ((capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) &&
30725b9c547cSRui Paulo 		     !wpa_dbus_dict_string_array_add_element(
30735b9c547cSRui Paulo 			     &iter_array, "wep40")) ||
3074c1d255d3SCy Schubert #endif /* CONFIG_WEP */
30755b9c547cSRui Paulo 		    !wpa_dbus_dict_end_string_array(&iter_dict,
3076d4f2939cSRui Paulo 						    &iter_dict_entry,
3077d4f2939cSRui Paulo 						    &iter_dict_val,
3078d4f2939cSRui Paulo 						    &iter_array))
3079d4f2939cSRui Paulo 			goto nomem;
3080d4f2939cSRui Paulo 	}
3081d4f2939cSRui Paulo 
308285732ac8SCy Schubert 	if (!wpa_dbus_dict_begin_string_array(&iter_dict, "GroupMgmt",
308385732ac8SCy Schubert 					      &iter_dict_entry,
308485732ac8SCy Schubert 					      &iter_dict_val,
308585732ac8SCy Schubert 					      &iter_array) ||
308685732ac8SCy Schubert 	    (res == 0 && (capa.enc & WPA_DRIVER_CAPA_ENC_BIP) &&
308785732ac8SCy Schubert 	     !wpa_dbus_dict_string_array_add_element(
308885732ac8SCy Schubert 		     &iter_array, "aes-128-cmac")) ||
308985732ac8SCy Schubert 	    (res == 0 && (capa.enc & WPA_DRIVER_CAPA_ENC_BIP_GMAC_128) &&
309085732ac8SCy Schubert 	     !wpa_dbus_dict_string_array_add_element(
309185732ac8SCy Schubert 		     &iter_array, "bip-gmac-128")) ||
309285732ac8SCy Schubert 	    (res == 0 && (capa.enc & WPA_DRIVER_CAPA_ENC_BIP_GMAC_256) &&
309385732ac8SCy Schubert 	     !wpa_dbus_dict_string_array_add_element(
309485732ac8SCy Schubert 		     &iter_array, "bip-gmac-256")) ||
309585732ac8SCy Schubert 	    (res == 0 && (capa.enc & WPA_DRIVER_CAPA_ENC_BIP_CMAC_256) &&
309685732ac8SCy Schubert 	     !wpa_dbus_dict_string_array_add_element(
309785732ac8SCy Schubert 		     &iter_array, "bip-cmac-256")) ||
309885732ac8SCy Schubert 	    !wpa_dbus_dict_end_string_array(&iter_dict,
309985732ac8SCy Schubert 					    &iter_dict_entry,
310085732ac8SCy Schubert 					    &iter_dict_val,
310185732ac8SCy Schubert 					    &iter_array))
310285732ac8SCy Schubert 		goto nomem;
310385732ac8SCy Schubert 
3104d4f2939cSRui Paulo 	/***** key management */
3105d4f2939cSRui Paulo 	if (res < 0) {
3106d4f2939cSRui Paulo 		const char *args[] = {
3107d4f2939cSRui Paulo 			"wpa-psk", "wpa-eap", "ieee8021x", "wpa-none",
3108d4f2939cSRui Paulo #ifdef CONFIG_WPS
3109d4f2939cSRui Paulo 			"wps",
3110d4f2939cSRui Paulo #endif /* CONFIG_WPS */
3111d4f2939cSRui Paulo 			"none"
3112d4f2939cSRui Paulo 		};
3113d4f2939cSRui Paulo 		if (!wpa_dbus_dict_append_string_array(
3114d4f2939cSRui Paulo 			    &iter_dict, "KeyMgmt", args,
31155b9c547cSRui Paulo 			    ARRAY_SIZE(args)))
3116d4f2939cSRui Paulo 			goto nomem;
3117d4f2939cSRui Paulo 	} else {
3118d4f2939cSRui Paulo 		if (!wpa_dbus_dict_begin_string_array(&iter_dict, "KeyMgmt",
3119d4f2939cSRui Paulo 						      &iter_dict_entry,
3120d4f2939cSRui Paulo 						      &iter_dict_val,
31215b9c547cSRui Paulo 						      &iter_array) ||
31225b9c547cSRui Paulo 		    !wpa_dbus_dict_string_array_add_element(&iter_array,
31235b9c547cSRui Paulo 							    "none") ||
31245b9c547cSRui Paulo 		    !wpa_dbus_dict_string_array_add_element(&iter_array,
3125d4f2939cSRui Paulo 							    "ieee8021x"))
3126d4f2939cSRui Paulo 			goto nomem;
3127d4f2939cSRui Paulo 
3128d4f2939cSRui Paulo 		if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
3129d4f2939cSRui Paulo 				     WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
3130d4f2939cSRui Paulo 			if (!wpa_dbus_dict_string_array_add_element(
31315b9c547cSRui Paulo 				    &iter_array, "wpa-eap") ||
31325b9c547cSRui Paulo 			    ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT) &&
31335b9c547cSRui Paulo 			     !wpa_dbus_dict_string_array_add_element(
31345b9c547cSRui Paulo 				     &iter_array, "wpa-ft-eap")))
3135d4f2939cSRui Paulo 				goto nomem;
3136d4f2939cSRui Paulo 
3137d4f2939cSRui Paulo /* TODO: Ensure that driver actually supports sha256 encryption. */
3138d4f2939cSRui Paulo 			if (!wpa_dbus_dict_string_array_add_element(
3139d4f2939cSRui Paulo 				    &iter_array, "wpa-eap-sha256"))
3140d4f2939cSRui Paulo 				goto nomem;
3141d4f2939cSRui Paulo 		}
3142d4f2939cSRui Paulo 
3143d4f2939cSRui Paulo 		if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
3144d4f2939cSRui Paulo 				     WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
3145d4f2939cSRui Paulo 			if (!wpa_dbus_dict_string_array_add_element(
31465b9c547cSRui Paulo 				    &iter_array, "wpa-psk") ||
31475b9c547cSRui Paulo 			    ((capa.key_mgmt &
31485b9c547cSRui Paulo 			      WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK) &&
31495b9c547cSRui Paulo 			     !wpa_dbus_dict_string_array_add_element(
31505b9c547cSRui Paulo 				     &iter_array, "wpa-ft-psk")))
3151d4f2939cSRui Paulo 				goto nomem;
3152d4f2939cSRui Paulo 
3153d4f2939cSRui Paulo /* TODO: Ensure that driver actually supports sha256 encryption. */
3154d4f2939cSRui Paulo 			if (!wpa_dbus_dict_string_array_add_element(
3155d4f2939cSRui Paulo 				    &iter_array, "wpa-psk-sha256"))
3156d4f2939cSRui Paulo 				goto nomem;
3157d4f2939cSRui Paulo 		}
3158d4f2939cSRui Paulo 
31595b9c547cSRui Paulo 		if ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) &&
31605b9c547cSRui Paulo 		    !wpa_dbus_dict_string_array_add_element(&iter_array,
31615b9c547cSRui Paulo 							    "wpa-none"))
3162d4f2939cSRui Paulo 			goto nomem;
3163d4f2939cSRui Paulo 
3164d4f2939cSRui Paulo 
3165d4f2939cSRui Paulo #ifdef CONFIG_WPS
3166d4f2939cSRui Paulo 		if (!wpa_dbus_dict_string_array_add_element(&iter_array,
3167d4f2939cSRui Paulo 							    "wps"))
3168d4f2939cSRui Paulo 			goto nomem;
3169d4f2939cSRui Paulo #endif /* CONFIG_WPS */
3170d4f2939cSRui Paulo 
3171c1d255d3SCy Schubert #ifdef CONFIG_SAE
3172c1d255d3SCy Schubert 		if ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SAE) &&
3173c1d255d3SCy Schubert 		    !wpa_dbus_dict_string_array_add_element(&iter_array, "sae"))
3174c1d255d3SCy Schubert 			goto nomem;
3175c1d255d3SCy Schubert #endif /* CONFIG_SAE */
3176c1d255d3SCy Schubert 
3177c1d255d3SCy Schubert #ifdef CONFIG_OWE
3178c1d255d3SCy Schubert 		if ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_OWE) &&
3179c1d255d3SCy Schubert 		    !wpa_dbus_dict_string_array_add_element(&iter_array, "owe"))
3180c1d255d3SCy Schubert 			goto nomem;
3181c1d255d3SCy Schubert #endif /* CONFIG_OWE */
3182c1d255d3SCy Schubert 
3183d4f2939cSRui Paulo 		if (!wpa_dbus_dict_end_string_array(&iter_dict,
3184d4f2939cSRui Paulo 						    &iter_dict_entry,
3185d4f2939cSRui Paulo 						    &iter_dict_val,
3186d4f2939cSRui Paulo 						    &iter_array))
3187d4f2939cSRui Paulo 			goto nomem;
3188d4f2939cSRui Paulo 	}
3189d4f2939cSRui Paulo 
3190d4f2939cSRui Paulo 	/***** WPA protocol */
3191d4f2939cSRui Paulo 	if (res < 0) {
3192d4f2939cSRui Paulo 		const char *args[] = { "rsn", "wpa" };
31935b9c547cSRui Paulo 
3194d4f2939cSRui Paulo 		if (!wpa_dbus_dict_append_string_array(
3195d4f2939cSRui Paulo 			    &iter_dict, "Protocol", args,
31965b9c547cSRui Paulo 			    ARRAY_SIZE(args)))
3197d4f2939cSRui Paulo 			goto nomem;
3198d4f2939cSRui Paulo 	} else {
3199d4f2939cSRui Paulo 		if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Protocol",
3200d4f2939cSRui Paulo 						      &iter_dict_entry,
3201d4f2939cSRui Paulo 						      &iter_dict_val,
32025b9c547cSRui Paulo 						      &iter_array) ||
32035b9c547cSRui Paulo 		    ((capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
32045b9c547cSRui Paulo 				       WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) &&
32055b9c547cSRui Paulo 		     !wpa_dbus_dict_string_array_add_element(
32065b9c547cSRui Paulo 			     &iter_array, "rsn")) ||
32075b9c547cSRui Paulo 		    ((capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
32085b9c547cSRui Paulo 				       WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) &&
32095b9c547cSRui Paulo 		     !wpa_dbus_dict_string_array_add_element(
32105b9c547cSRui Paulo 			     &iter_array, "wpa")) ||
32115b9c547cSRui Paulo 		    !wpa_dbus_dict_end_string_array(&iter_dict,
3212d4f2939cSRui Paulo 						    &iter_dict_entry,
3213d4f2939cSRui Paulo 						    &iter_dict_val,
3214d4f2939cSRui Paulo 						    &iter_array))
3215d4f2939cSRui Paulo 			goto nomem;
3216d4f2939cSRui Paulo 	}
3217d4f2939cSRui Paulo 
3218d4f2939cSRui Paulo 	/***** auth alg */
3219d4f2939cSRui Paulo 	if (res < 0) {
3220d4f2939cSRui Paulo 		const char *args[] = { "open", "shared", "leap" };
32215b9c547cSRui Paulo 
3222d4f2939cSRui Paulo 		if (!wpa_dbus_dict_append_string_array(
3223d4f2939cSRui Paulo 			    &iter_dict, "AuthAlg", args,
32245b9c547cSRui Paulo 			    ARRAY_SIZE(args)))
3225d4f2939cSRui Paulo 			goto nomem;
3226d4f2939cSRui Paulo 	} else {
3227d4f2939cSRui Paulo 		if (!wpa_dbus_dict_begin_string_array(&iter_dict, "AuthAlg",
3228d4f2939cSRui Paulo 						      &iter_dict_entry,
3229d4f2939cSRui Paulo 						      &iter_dict_val,
3230d4f2939cSRui Paulo 						      &iter_array))
3231d4f2939cSRui Paulo 			goto nomem;
3232d4f2939cSRui Paulo 
32335b9c547cSRui Paulo 		if (((capa.auth & WPA_DRIVER_AUTH_OPEN) &&
32345b9c547cSRui Paulo 		     !wpa_dbus_dict_string_array_add_element(
32355b9c547cSRui Paulo 			     &iter_array, "open")) ||
32365b9c547cSRui Paulo 		    ((capa.auth & WPA_DRIVER_AUTH_SHARED) &&
32375b9c547cSRui Paulo 		     !wpa_dbus_dict_string_array_add_element(
32385b9c547cSRui Paulo 			     &iter_array, "shared")) ||
32395b9c547cSRui Paulo 		    ((capa.auth & WPA_DRIVER_AUTH_LEAP) &&
32405b9c547cSRui Paulo 		     !wpa_dbus_dict_string_array_add_element(
32415b9c547cSRui Paulo 			     &iter_array, "leap")) ||
32425b9c547cSRui Paulo 		    !wpa_dbus_dict_end_string_array(&iter_dict,
3243d4f2939cSRui Paulo 						    &iter_dict_entry,
3244d4f2939cSRui Paulo 						    &iter_dict_val,
3245d4f2939cSRui Paulo 						    &iter_array))
3246d4f2939cSRui Paulo 			goto nomem;
3247d4f2939cSRui Paulo 	}
3248d4f2939cSRui Paulo 
3249d4f2939cSRui Paulo 	/***** Scan */
3250d4f2939cSRui Paulo 	if (!wpa_dbus_dict_append_string_array(&iter_dict, "Scan", scans,
32515b9c547cSRui Paulo 					       ARRAY_SIZE(scans)))
3252d4f2939cSRui Paulo 		goto nomem;
3253d4f2939cSRui Paulo 
3254d4f2939cSRui Paulo 	/***** Modes */
3255d4f2939cSRui Paulo 	if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Modes",
3256d4f2939cSRui Paulo 					      &iter_dict_entry,
3257d4f2939cSRui Paulo 					      &iter_dict_val,
32585b9c547cSRui Paulo 					      &iter_array) ||
32595b9c547cSRui Paulo 	    !wpa_dbus_dict_string_array_add_element(
32605b9c547cSRui Paulo 		    &iter_array, "infrastructure") ||
3261780fb4a2SCy Schubert 	    (res >= 0 && (capa.flags & WPA_DRIVER_FLAGS_IBSS) &&
32625b9c547cSRui Paulo 	     !wpa_dbus_dict_string_array_add_element(
3263780fb4a2SCy Schubert 		     &iter_array, "ad-hoc")) ||
32645b9c547cSRui Paulo 	    (res >= 0 && (capa.flags & WPA_DRIVER_FLAGS_AP) &&
32655b9c547cSRui Paulo 	     !wpa_dbus_dict_string_array_add_element(
32665b9c547cSRui Paulo 		     &iter_array, "ap")) ||
32675b9c547cSRui Paulo 	    (res >= 0 && (capa.flags & WPA_DRIVER_FLAGS_P2P_CAPABLE) &&
3268780fb4a2SCy Schubert 	     !wpa_s->conf->p2p_disabled &&
32695b9c547cSRui Paulo 	     !wpa_dbus_dict_string_array_add_element(
32705b9c547cSRui Paulo 		     &iter_array, "p2p")) ||
327185732ac8SCy Schubert #ifdef CONFIG_MESH
327285732ac8SCy Schubert 	    (res >= 0 && (capa.flags & WPA_DRIVER_FLAGS_MESH) &&
327385732ac8SCy Schubert 	     !wpa_dbus_dict_string_array_add_element(
327485732ac8SCy Schubert 		     &iter_array, "mesh")) ||
327585732ac8SCy Schubert #endif /* CONFIG_MESH */
32765b9c547cSRui Paulo 	    !wpa_dbus_dict_end_string_array(&iter_dict,
3277d4f2939cSRui Paulo 					    &iter_dict_entry,
3278d4f2939cSRui Paulo 					    &iter_dict_val,
3279d4f2939cSRui Paulo 					    &iter_array))
3280d4f2939cSRui Paulo 		goto nomem;
3281d4f2939cSRui Paulo 	/***** Modes end */
3282d4f2939cSRui Paulo 
3283d4f2939cSRui Paulo 	if (res >= 0) {
3284d4f2939cSRui Paulo 		dbus_int32_t max_scan_ssid = capa.max_scan_ssids;
3285d4f2939cSRui Paulo 
3286d4f2939cSRui Paulo 		if (!wpa_dbus_dict_append_int32(&iter_dict, "MaxScanSSID",
3287d4f2939cSRui Paulo 						max_scan_ssid))
3288d4f2939cSRui Paulo 			goto nomem;
3289d4f2939cSRui Paulo 	}
3290d4f2939cSRui Paulo 
32915b9c547cSRui Paulo 	if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict) ||
32925b9c547cSRui Paulo 	    !dbus_message_iter_close_container(iter, &variant_iter))
3293d4f2939cSRui Paulo 		goto nomem;
3294d4f2939cSRui Paulo 
3295d4f2939cSRui Paulo 	return TRUE;
3296d4f2939cSRui Paulo 
3297d4f2939cSRui Paulo nomem:
3298d4f2939cSRui Paulo 	dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3299d4f2939cSRui Paulo 	return FALSE;
3300d4f2939cSRui Paulo }
3301d4f2939cSRui Paulo 
3302d4f2939cSRui Paulo 
3303d4f2939cSRui Paulo /**
3304d4f2939cSRui Paulo  * wpas_dbus_getter_state - Get interface state
3305d4f2939cSRui Paulo  * @iter: Pointer to incoming dbus message iter
3306d4f2939cSRui Paulo  * @error: Location to store error on failure
3307d4f2939cSRui Paulo  * @user_data: Function specific data
3308d4f2939cSRui Paulo  * Returns: TRUE on success, FALSE on failure
3309d4f2939cSRui Paulo  *
3310d4f2939cSRui Paulo  * Getter for "State" property.
3311d4f2939cSRui Paulo  */
wpas_dbus_getter_state(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3312780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_state(
3313780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
3314780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
3315d4f2939cSRui Paulo {
3316d4f2939cSRui Paulo 	struct wpa_supplicant *wpa_s = user_data;
3317d4f2939cSRui Paulo 	const char *str_state;
3318d4f2939cSRui Paulo 	char *state_ls, *tmp;
3319d4f2939cSRui Paulo 	dbus_bool_t success = FALSE;
3320d4f2939cSRui Paulo 
3321d4f2939cSRui Paulo 	str_state = wpa_supplicant_state_txt(wpa_s->wpa_state);
3322d4f2939cSRui Paulo 
3323d4f2939cSRui Paulo 	/* make state string lowercase to fit new DBus API convention
3324d4f2939cSRui Paulo 	 */
3325d4f2939cSRui Paulo 	state_ls = tmp = os_strdup(str_state);
3326d4f2939cSRui Paulo 	if (!tmp) {
3327d4f2939cSRui Paulo 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3328d4f2939cSRui Paulo 		return FALSE;
3329d4f2939cSRui Paulo 	}
3330d4f2939cSRui Paulo 	while (*tmp) {
3331d4f2939cSRui Paulo 		*tmp = tolower(*tmp);
3332d4f2939cSRui Paulo 		tmp++;
3333d4f2939cSRui Paulo 	}
3334d4f2939cSRui Paulo 
3335d4f2939cSRui Paulo 	success = wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3336d4f2939cSRui Paulo 						   &state_ls, error);
3337d4f2939cSRui Paulo 
3338d4f2939cSRui Paulo 	os_free(state_ls);
3339d4f2939cSRui Paulo 
3340d4f2939cSRui Paulo 	return success;
3341d4f2939cSRui Paulo }
3342d4f2939cSRui Paulo 
3343d4f2939cSRui Paulo 
3344d4f2939cSRui Paulo /**
3345d4f2939cSRui Paulo  * wpas_dbus_new_iface_get_scanning - Get interface scanning state
3346d4f2939cSRui Paulo  * @iter: Pointer to incoming dbus message iter
3347d4f2939cSRui Paulo  * @error: Location to store error on failure
3348d4f2939cSRui Paulo  * @user_data: Function specific data
3349d4f2939cSRui Paulo  * Returns: TRUE on success, FALSE on failure
3350d4f2939cSRui Paulo  *
3351d4f2939cSRui Paulo  * Getter for "scanning" property.
3352d4f2939cSRui Paulo  */
wpas_dbus_getter_scanning(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3353780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_scanning(
3354780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
3355780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
3356d4f2939cSRui Paulo {
3357d4f2939cSRui Paulo 	struct wpa_supplicant *wpa_s = user_data;
3358d4f2939cSRui Paulo 	dbus_bool_t scanning = wpa_s->scanning ? TRUE : FALSE;
3359d4f2939cSRui Paulo 
3360d4f2939cSRui Paulo 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
3361d4f2939cSRui Paulo 						&scanning, error);
3362d4f2939cSRui Paulo }
3363d4f2939cSRui Paulo 
3364d4f2939cSRui Paulo 
3365d4f2939cSRui Paulo /**
3366d4f2939cSRui Paulo  * wpas_dbus_getter_ap_scan - Control roaming mode
3367d4f2939cSRui Paulo  * @iter: Pointer to incoming dbus message iter
3368d4f2939cSRui Paulo  * @error: Location to store error on failure
3369d4f2939cSRui Paulo  * @user_data: Function specific data
3370d4f2939cSRui Paulo  * Returns: TRUE on success, FALSE on failure
3371d4f2939cSRui Paulo  *
3372d4f2939cSRui Paulo  * Getter function for "ApScan" property.
3373d4f2939cSRui Paulo  */
wpas_dbus_getter_ap_scan(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3374780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_ap_scan(
3375780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
3376780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
3377d4f2939cSRui Paulo {
3378d4f2939cSRui Paulo 	struct wpa_supplicant *wpa_s = user_data;
3379d4f2939cSRui Paulo 	dbus_uint32_t ap_scan = wpa_s->conf->ap_scan;
3380d4f2939cSRui Paulo 
3381d4f2939cSRui Paulo 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
3382d4f2939cSRui Paulo 						&ap_scan, error);
3383d4f2939cSRui Paulo }
3384d4f2939cSRui Paulo 
3385d4f2939cSRui Paulo 
3386d4f2939cSRui Paulo /**
3387d4f2939cSRui Paulo  * wpas_dbus_setter_ap_scan - Control roaming mode
3388d4f2939cSRui Paulo  * @iter: Pointer to incoming dbus message iter
3389d4f2939cSRui Paulo  * @error: Location to store error on failure
3390d4f2939cSRui Paulo  * @user_data: Function specific data
3391d4f2939cSRui Paulo  * Returns: TRUE on success, FALSE on failure
3392d4f2939cSRui Paulo  *
3393d4f2939cSRui Paulo  * Setter function for "ApScan" property.
3394d4f2939cSRui Paulo  */
wpas_dbus_setter_ap_scan(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3395780fb4a2SCy Schubert dbus_bool_t wpas_dbus_setter_ap_scan(
3396780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
3397780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
3398d4f2939cSRui Paulo {
3399d4f2939cSRui Paulo 	struct wpa_supplicant *wpa_s = user_data;
3400d4f2939cSRui Paulo 	dbus_uint32_t ap_scan;
3401d4f2939cSRui Paulo 
3402d4f2939cSRui Paulo 	if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
3403d4f2939cSRui Paulo 					      &ap_scan))
3404d4f2939cSRui Paulo 		return FALSE;
3405d4f2939cSRui Paulo 
3406d4f2939cSRui Paulo 	if (wpa_supplicant_set_ap_scan(wpa_s, ap_scan)) {
3407d4f2939cSRui Paulo 		dbus_set_error_const(error, DBUS_ERROR_FAILED,
3408d4f2939cSRui Paulo 				     "ap_scan must be 0, 1, or 2");
3409d4f2939cSRui Paulo 		return FALSE;
3410d4f2939cSRui Paulo 	}
3411d4f2939cSRui Paulo 	return TRUE;
3412d4f2939cSRui Paulo }
3413d4f2939cSRui Paulo 
3414d4f2939cSRui Paulo 
3415d4f2939cSRui Paulo /**
3416d4f2939cSRui Paulo  * wpas_dbus_getter_fast_reauth - Control fast
3417d4f2939cSRui Paulo  * reauthentication (TLS session resumption)
3418d4f2939cSRui Paulo  * @iter: Pointer to incoming dbus message iter
3419d4f2939cSRui Paulo  * @error: Location to store error on failure
3420d4f2939cSRui Paulo  * @user_data: Function specific data
3421d4f2939cSRui Paulo  * Returns: TRUE on success, FALSE on failure
3422d4f2939cSRui Paulo  *
3423d4f2939cSRui Paulo  * Getter function for "FastReauth" property.
3424d4f2939cSRui Paulo  */
wpas_dbus_getter_fast_reauth(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3425780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_fast_reauth(
3426780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
3427780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
3428d4f2939cSRui Paulo {
3429d4f2939cSRui Paulo 	struct wpa_supplicant *wpa_s = user_data;
3430d4f2939cSRui Paulo 	dbus_bool_t fast_reauth = wpa_s->conf->fast_reauth ? TRUE : FALSE;
3431d4f2939cSRui Paulo 
3432d4f2939cSRui Paulo 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
3433d4f2939cSRui Paulo 						&fast_reauth, error);
3434d4f2939cSRui Paulo }
3435d4f2939cSRui Paulo 
3436d4f2939cSRui Paulo 
3437d4f2939cSRui Paulo /**
3438d4f2939cSRui Paulo  * wpas_dbus_setter_fast_reauth - Control fast
3439d4f2939cSRui Paulo  * reauthentication (TLS session resumption)
3440d4f2939cSRui Paulo  * @iter: Pointer to incoming dbus message iter
3441d4f2939cSRui Paulo  * @error: Location to store error on failure
3442d4f2939cSRui Paulo  * @user_data: Function specific data
3443d4f2939cSRui Paulo  * Returns: TRUE on success, FALSE on failure
3444d4f2939cSRui Paulo  *
3445d4f2939cSRui Paulo  * Setter function for "FastReauth" property.
3446d4f2939cSRui Paulo  */
wpas_dbus_setter_fast_reauth(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3447780fb4a2SCy Schubert dbus_bool_t wpas_dbus_setter_fast_reauth(
3448780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
3449780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
3450d4f2939cSRui Paulo {
3451d4f2939cSRui Paulo 	struct wpa_supplicant *wpa_s = user_data;
3452d4f2939cSRui Paulo 	dbus_bool_t fast_reauth;
3453d4f2939cSRui Paulo 
3454d4f2939cSRui Paulo 	if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
3455d4f2939cSRui Paulo 					      &fast_reauth))
3456d4f2939cSRui Paulo 		return FALSE;
3457d4f2939cSRui Paulo 
3458d4f2939cSRui Paulo 	wpa_s->conf->fast_reauth = fast_reauth;
3459d4f2939cSRui Paulo 	return TRUE;
3460d4f2939cSRui Paulo }
3461d4f2939cSRui Paulo 
3462d4f2939cSRui Paulo 
3463d4f2939cSRui Paulo /**
3464d4f2939cSRui Paulo  * wpas_dbus_getter_disconnect_reason - Get most recent reason for disconnect
3465d4f2939cSRui Paulo  * @iter: Pointer to incoming dbus message iter
3466d4f2939cSRui Paulo  * @error: Location to store error on failure
3467d4f2939cSRui Paulo  * @user_data: Function specific data
3468d4f2939cSRui Paulo  * Returns: TRUE on success, FALSE on failure
3469d4f2939cSRui Paulo  *
3470d4f2939cSRui Paulo  * Getter for "DisconnectReason" property.  The reason is negative if it is
3471d4f2939cSRui Paulo  * locally generated.
3472d4f2939cSRui Paulo  */
wpas_dbus_getter_disconnect_reason(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3473780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_disconnect_reason(
3474780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
3475780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
3476d4f2939cSRui Paulo {
3477d4f2939cSRui Paulo 	struct wpa_supplicant *wpa_s = user_data;
3478d4f2939cSRui Paulo 	dbus_int32_t reason = wpa_s->disconnect_reason;
34795b9c547cSRui Paulo 
3480d4f2939cSRui Paulo 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
3481d4f2939cSRui Paulo 						&reason, error);
3482d4f2939cSRui Paulo }
3483d4f2939cSRui Paulo 
3484d4f2939cSRui Paulo 
3485d4f2939cSRui Paulo /**
34864bc52338SCy Schubert  * wpas_dbus_getter_auth_status_code - Get most recent auth status code
34874bc52338SCy Schubert  * @iter: Pointer to incoming dbus message iter
34884bc52338SCy Schubert  * @error: Location to store error on failure
34894bc52338SCy Schubert  * @user_data: Function specific data
34904bc52338SCy Schubert  * Returns: TRUE on success, FALSE on failure
34914bc52338SCy Schubert  *
34924bc52338SCy Schubert  * Getter for "AuthStatusCode" property.
34934bc52338SCy Schubert  */
wpas_dbus_getter_auth_status_code(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)34944bc52338SCy Schubert dbus_bool_t wpas_dbus_getter_auth_status_code(
34954bc52338SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
34964bc52338SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
34974bc52338SCy Schubert {
34984bc52338SCy Schubert 	struct wpa_supplicant *wpa_s = user_data;
34994bc52338SCy Schubert 	dbus_int32_t reason = wpa_s->auth_status_code;
35004bc52338SCy Schubert 
35014bc52338SCy Schubert 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
35024bc52338SCy Schubert 						&reason, error);
35034bc52338SCy Schubert }
35044bc52338SCy Schubert 
35054bc52338SCy Schubert 
35064bc52338SCy Schubert /**
3507780fb4a2SCy Schubert  * wpas_dbus_getter_assoc_status_code - Get most recent failed assoc status code
3508780fb4a2SCy Schubert  * @iter: Pointer to incoming dbus message iter
3509780fb4a2SCy Schubert  * @error: Location to store error on failure
3510780fb4a2SCy Schubert  * @user_data: Function specific data
3511780fb4a2SCy Schubert  * Returns: TRUE on success, FALSE on failure
3512780fb4a2SCy Schubert  *
3513780fb4a2SCy Schubert  * Getter for "AssocStatusCode" property.
3514780fb4a2SCy Schubert  */
wpas_dbus_getter_assoc_status_code(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3515780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_assoc_status_code(
3516780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
3517780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
3518780fb4a2SCy Schubert {
3519780fb4a2SCy Schubert 	struct wpa_supplicant *wpa_s = user_data;
3520780fb4a2SCy Schubert 	dbus_int32_t status_code = wpa_s->assoc_status_code;
3521780fb4a2SCy Schubert 
3522780fb4a2SCy Schubert 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
3523780fb4a2SCy Schubert 						&status_code, error);
3524780fb4a2SCy Schubert }
3525780fb4a2SCy Schubert 
3526780fb4a2SCy Schubert 
3527780fb4a2SCy Schubert /**
35284bc52338SCy Schubert  * wpas_dbus_getter_roam_time - Get most recent roam time
35294bc52338SCy Schubert  * @iter: Pointer to incoming dbus message iter
35304bc52338SCy Schubert  * @error: Location to store error on failure
35314bc52338SCy Schubert  * @user_data: Function specific data
35324bc52338SCy Schubert  * Returns: TRUE on success, FALSE on failure
35334bc52338SCy Schubert  *
35344bc52338SCy Schubert  * Getter for "RoamTime" property.
35354bc52338SCy Schubert  */
wpas_dbus_getter_roam_time(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)35364bc52338SCy Schubert dbus_bool_t wpas_dbus_getter_roam_time(
35374bc52338SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
35384bc52338SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
35394bc52338SCy Schubert {
35404bc52338SCy Schubert 	struct wpa_supplicant *wpa_s = user_data;
35414bc52338SCy Schubert 	dbus_uint32_t roam_time = wpa_s->roam_time.sec * 1000 +
35424bc52338SCy Schubert 		wpa_s->roam_time.usec / 1000;
35434bc52338SCy Schubert 
35444bc52338SCy Schubert 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
35454bc52338SCy Schubert 						&roam_time, error);
35464bc52338SCy Schubert }
35474bc52338SCy Schubert 
35484bc52338SCy Schubert 
35494bc52338SCy Schubert /**
35504bc52338SCy Schubert  * wpas_dbus_getter_roam_complete - Get most recent roam success or failure
35514bc52338SCy Schubert  * @iter: Pointer to incoming dbus message iter
35524bc52338SCy Schubert  * @error: Location to store error on failure
35534bc52338SCy Schubert  * @user_data: Function specific data
35544bc52338SCy Schubert  * Returns: TRUE on success, FALSE on failure
35554bc52338SCy Schubert  *
35564bc52338SCy Schubert  * Getter for "RoamComplete" property.
35574bc52338SCy Schubert  */
wpas_dbus_getter_roam_complete(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)35584bc52338SCy Schubert dbus_bool_t wpas_dbus_getter_roam_complete(
35594bc52338SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
35604bc52338SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
35614bc52338SCy Schubert {
35624bc52338SCy Schubert 	struct wpa_supplicant *wpa_s = user_data;
35634bc52338SCy Schubert 	dbus_bool_t roam_complete = os_reltime_initialized(&wpa_s->roam_time);
35644bc52338SCy Schubert 
35654bc52338SCy Schubert 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
35664bc52338SCy Schubert 						&roam_complete, error);
35674bc52338SCy Schubert }
35684bc52338SCy Schubert 
35694bc52338SCy Schubert 
35704bc52338SCy Schubert /**
35714bc52338SCy Schubert  * wpas_dbus_getter_session_length - Get most recent BSS session length
35724bc52338SCy Schubert  * @iter: Pointer to incoming dbus message iter
35734bc52338SCy Schubert  * @error: Location to store error on failure
35744bc52338SCy Schubert  * @user_data: Function specific data
35754bc52338SCy Schubert  * Returns: TRUE on success, FALSE on failure
35764bc52338SCy Schubert  *
35774bc52338SCy Schubert  * Getter for "SessionLength" property.
35784bc52338SCy Schubert  */
wpas_dbus_getter_session_length(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)35794bc52338SCy Schubert dbus_bool_t wpas_dbus_getter_session_length(
35804bc52338SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
35814bc52338SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
35824bc52338SCy Schubert {
35834bc52338SCy Schubert 	struct wpa_supplicant *wpa_s = user_data;
35844bc52338SCy Schubert 	dbus_uint32_t session_length = wpa_s->session_length.sec * 1000 +
35854bc52338SCy Schubert 		wpa_s->session_length.usec / 1000;
35864bc52338SCy Schubert 
35874bc52338SCy Schubert 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
35884bc52338SCy Schubert 						&session_length, error);
35894bc52338SCy Schubert }
35904bc52338SCy Schubert 
35914bc52338SCy Schubert 
35924bc52338SCy Schubert /**
35934bc52338SCy Schubert  * wpas_dbus_getter_bss_tm_status - Get most BSS Transition Management request
35944bc52338SCy Schubert  * status code
35954bc52338SCy Schubert  * @iter: Pointer to incoming dbus message iter
35964bc52338SCy Schubert  * @error: Location to store error on failure
35974bc52338SCy Schubert  * @user_data: Function specific data
35984bc52338SCy Schubert  * Returns: TRUE on success, FALSE on failure
35994bc52338SCy Schubert  *
36004bc52338SCy Schubert  * Getter for "BSSTMStatus" property.
36014bc52338SCy Schubert  */
wpas_dbus_getter_bss_tm_status(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)36024bc52338SCy Schubert dbus_bool_t wpas_dbus_getter_bss_tm_status(
36034bc52338SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
36044bc52338SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
36054bc52338SCy Schubert {
36064bc52338SCy Schubert #ifdef CONFIG_WNM
36074bc52338SCy Schubert 	struct wpa_supplicant *wpa_s = user_data;
36084bc52338SCy Schubert 	dbus_uint32_t bss_tm_status = wpa_s->bss_tm_status;
36094bc52338SCy Schubert #else /* CONFIG_WNM */
36104bc52338SCy Schubert 	dbus_uint32_t bss_tm_status = 0;
36114bc52338SCy Schubert #endif /* CONFIG_WNM */
36124bc52338SCy Schubert 
36134bc52338SCy Schubert 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
36144bc52338SCy Schubert 						&bss_tm_status, error);
36154bc52338SCy Schubert }
36164bc52338SCy Schubert 
36174bc52338SCy Schubert 
36184bc52338SCy Schubert /**
3619d4f2939cSRui Paulo  * wpas_dbus_getter_bss_expire_age - Get BSS entry expiration age
3620d4f2939cSRui Paulo  * @iter: Pointer to incoming dbus message iter
3621d4f2939cSRui Paulo  * @error: Location to store error on failure
3622d4f2939cSRui Paulo  * @user_data: Function specific data
3623d4f2939cSRui Paulo  * Returns: TRUE on success, FALSE on failure
3624d4f2939cSRui Paulo  *
3625d4f2939cSRui Paulo  * Getter function for "BSSExpireAge" property.
3626d4f2939cSRui Paulo  */
wpas_dbus_getter_bss_expire_age(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3627780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_bss_expire_age(
3628780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
3629780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
3630d4f2939cSRui Paulo {
3631d4f2939cSRui Paulo 	struct wpa_supplicant *wpa_s = user_data;
3632d4f2939cSRui Paulo 	dbus_uint32_t expire_age = wpa_s->conf->bss_expiration_age;
3633d4f2939cSRui Paulo 
3634d4f2939cSRui Paulo 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
3635d4f2939cSRui Paulo 						&expire_age, error);
3636d4f2939cSRui Paulo }
3637d4f2939cSRui Paulo 
3638d4f2939cSRui Paulo 
3639d4f2939cSRui Paulo /**
3640d4f2939cSRui Paulo  * wpas_dbus_setter_bss_expire_age - Control BSS entry expiration age
3641d4f2939cSRui Paulo  * @iter: Pointer to incoming dbus message iter
3642d4f2939cSRui Paulo  * @error: Location to store error on failure
3643d4f2939cSRui Paulo  * @user_data: Function specific data
3644d4f2939cSRui Paulo  * Returns: TRUE on success, FALSE on failure
3645d4f2939cSRui Paulo  *
3646d4f2939cSRui Paulo  * Setter function for "BSSExpireAge" property.
3647d4f2939cSRui Paulo  */
wpas_dbus_setter_bss_expire_age(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3648780fb4a2SCy Schubert dbus_bool_t wpas_dbus_setter_bss_expire_age(
3649780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
3650780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
3651d4f2939cSRui Paulo {
3652d4f2939cSRui Paulo 	struct wpa_supplicant *wpa_s = user_data;
3653d4f2939cSRui Paulo 	dbus_uint32_t expire_age;
3654d4f2939cSRui Paulo 
3655d4f2939cSRui Paulo 	if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
3656d4f2939cSRui Paulo 					      &expire_age))
3657d4f2939cSRui Paulo 		return FALSE;
3658d4f2939cSRui Paulo 
3659d4f2939cSRui Paulo 	if (wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age)) {
3660d4f2939cSRui Paulo 		dbus_set_error_const(error, DBUS_ERROR_FAILED,
3661d4f2939cSRui Paulo 				     "BSSExpireAge must be >= 10");
3662d4f2939cSRui Paulo 		return FALSE;
3663d4f2939cSRui Paulo 	}
3664d4f2939cSRui Paulo 	return TRUE;
3665d4f2939cSRui Paulo }
3666d4f2939cSRui Paulo 
3667d4f2939cSRui Paulo 
3668d4f2939cSRui Paulo /**
3669d4f2939cSRui Paulo  * wpas_dbus_getter_bss_expire_count - Get BSS entry expiration scan count
3670d4f2939cSRui Paulo  * @iter: Pointer to incoming dbus message iter
3671d4f2939cSRui Paulo  * @error: Location to store error on failure
3672d4f2939cSRui Paulo  * @user_data: Function specific data
3673d4f2939cSRui Paulo  * Returns: TRUE on success, FALSE on failure
3674d4f2939cSRui Paulo  *
3675d4f2939cSRui Paulo  * Getter function for "BSSExpireCount" property.
3676d4f2939cSRui Paulo  */
wpas_dbus_getter_bss_expire_count(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3677780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_bss_expire_count(
3678780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
3679780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
3680d4f2939cSRui Paulo {
3681d4f2939cSRui Paulo 	struct wpa_supplicant *wpa_s = user_data;
3682d4f2939cSRui Paulo 	dbus_uint32_t expire_count = wpa_s->conf->bss_expiration_scan_count;
3683d4f2939cSRui Paulo 
3684d4f2939cSRui Paulo 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
3685d4f2939cSRui Paulo 						&expire_count, error);
3686d4f2939cSRui Paulo }
3687d4f2939cSRui Paulo 
3688d4f2939cSRui Paulo 
3689d4f2939cSRui Paulo /**
3690d4f2939cSRui Paulo  * wpas_dbus_setter_bss_expire_count - Control BSS entry expiration scan count
3691d4f2939cSRui Paulo  * @iter: Pointer to incoming dbus message iter
3692d4f2939cSRui Paulo  * @error: Location to store error on failure
3693d4f2939cSRui Paulo  * @user_data: Function specific data
3694d4f2939cSRui Paulo  * Returns: TRUE on success, FALSE on failure
3695d4f2939cSRui Paulo  *
3696d4f2939cSRui Paulo  * Setter function for "BSSExpireCount" property.
3697d4f2939cSRui Paulo  */
wpas_dbus_setter_bss_expire_count(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3698780fb4a2SCy Schubert dbus_bool_t wpas_dbus_setter_bss_expire_count(
3699780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
3700780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
3701d4f2939cSRui Paulo {
3702d4f2939cSRui Paulo 	struct wpa_supplicant *wpa_s = user_data;
3703d4f2939cSRui Paulo 	dbus_uint32_t expire_count;
3704d4f2939cSRui Paulo 
3705d4f2939cSRui Paulo 	if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
3706d4f2939cSRui Paulo 					      &expire_count))
3707d4f2939cSRui Paulo 		return FALSE;
3708d4f2939cSRui Paulo 
3709d4f2939cSRui Paulo 	if (wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count)) {
3710d4f2939cSRui Paulo 		dbus_set_error_const(error, DBUS_ERROR_FAILED,
3711d4f2939cSRui Paulo 				     "BSSExpireCount must be > 0");
3712d4f2939cSRui Paulo 		return FALSE;
3713d4f2939cSRui Paulo 	}
3714d4f2939cSRui Paulo 	return TRUE;
3715d4f2939cSRui Paulo }
3716d4f2939cSRui Paulo 
3717d4f2939cSRui Paulo 
3718d4f2939cSRui Paulo /**
3719d4f2939cSRui Paulo  * wpas_dbus_getter_country - Control country code
3720d4f2939cSRui Paulo  * @iter: Pointer to incoming dbus message iter
3721d4f2939cSRui Paulo  * @error: Location to store error on failure
3722d4f2939cSRui Paulo  * @user_data: Function specific data
3723d4f2939cSRui Paulo  * Returns: TRUE on success, FALSE on failure
3724d4f2939cSRui Paulo  *
3725d4f2939cSRui Paulo  * Getter function for "Country" property.
3726d4f2939cSRui Paulo  */
wpas_dbus_getter_country(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3727780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_country(
3728780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
3729780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
3730d4f2939cSRui Paulo {
3731d4f2939cSRui Paulo 	struct wpa_supplicant *wpa_s = user_data;
3732d4f2939cSRui Paulo 	char country[3];
3733d4f2939cSRui Paulo 	char *str = country;
3734d4f2939cSRui Paulo 
3735d4f2939cSRui Paulo 	country[0] = wpa_s->conf->country[0];
3736d4f2939cSRui Paulo 	country[1] = wpa_s->conf->country[1];
3737d4f2939cSRui Paulo 	country[2] = '\0';
3738d4f2939cSRui Paulo 
3739d4f2939cSRui Paulo 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3740d4f2939cSRui Paulo 						&str, error);
3741d4f2939cSRui Paulo }
3742d4f2939cSRui Paulo 
3743d4f2939cSRui Paulo 
3744d4f2939cSRui Paulo /**
3745d4f2939cSRui Paulo  * wpas_dbus_setter_country - Control country code
3746d4f2939cSRui Paulo  * @iter: Pointer to incoming dbus message iter
3747d4f2939cSRui Paulo  * @error: Location to store error on failure
3748d4f2939cSRui Paulo  * @user_data: Function specific data
3749d4f2939cSRui Paulo  * Returns: TRUE on success, FALSE on failure
3750d4f2939cSRui Paulo  *
3751d4f2939cSRui Paulo  * Setter function for "Country" property.
3752d4f2939cSRui Paulo  */
wpas_dbus_setter_country(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3753780fb4a2SCy Schubert dbus_bool_t wpas_dbus_setter_country(
3754780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
3755780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
3756d4f2939cSRui Paulo {
3757d4f2939cSRui Paulo 	struct wpa_supplicant *wpa_s = user_data;
3758d4f2939cSRui Paulo 	const char *country;
3759d4f2939cSRui Paulo 
3760d4f2939cSRui Paulo 	if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
3761d4f2939cSRui Paulo 					      &country))
3762d4f2939cSRui Paulo 		return FALSE;
3763d4f2939cSRui Paulo 
3764d4f2939cSRui Paulo 	if (!country[0] || !country[1]) {
3765d4f2939cSRui Paulo 		dbus_set_error_const(error, DBUS_ERROR_FAILED,
3766d4f2939cSRui Paulo 				     "invalid country code");
3767d4f2939cSRui Paulo 		return FALSE;
3768d4f2939cSRui Paulo 	}
3769d4f2939cSRui Paulo 
3770d4f2939cSRui Paulo 	if (wpa_s->drv_priv != NULL && wpa_drv_set_country(wpa_s, country)) {
3771d4f2939cSRui Paulo 		wpa_printf(MSG_DEBUG, "Failed to set country");
3772d4f2939cSRui Paulo 		dbus_set_error_const(error, DBUS_ERROR_FAILED,
3773d4f2939cSRui Paulo 				     "failed to set country code");
3774d4f2939cSRui Paulo 		return FALSE;
3775d4f2939cSRui Paulo 	}
3776d4f2939cSRui Paulo 
3777d4f2939cSRui Paulo 	wpa_s->conf->country[0] = country[0];
3778d4f2939cSRui Paulo 	wpa_s->conf->country[1] = country[1];
3779d4f2939cSRui Paulo 	return TRUE;
3780d4f2939cSRui Paulo }
3781d4f2939cSRui Paulo 
3782d4f2939cSRui Paulo 
3783d4f2939cSRui Paulo /**
3784d4f2939cSRui Paulo  * wpas_dbus_getter_scan_interval - Get scan interval
3785d4f2939cSRui Paulo  * @iter: Pointer to incoming dbus message iter
3786d4f2939cSRui Paulo  * @error: Location to store error on failure
3787d4f2939cSRui Paulo  * @user_data: Function specific data
3788d4f2939cSRui Paulo  * Returns: TRUE on success, FALSE on failure
3789d4f2939cSRui Paulo  *
3790d4f2939cSRui Paulo  * Getter function for "ScanInterval" property.
3791d4f2939cSRui Paulo  */
wpas_dbus_getter_scan_interval(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3792780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_scan_interval(
3793780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
3794780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
3795d4f2939cSRui Paulo {
3796d4f2939cSRui Paulo 	struct wpa_supplicant *wpa_s = user_data;
3797d4f2939cSRui Paulo 	dbus_int32_t scan_interval = wpa_s->scan_interval;
3798d4f2939cSRui Paulo 
3799d4f2939cSRui Paulo 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
3800d4f2939cSRui Paulo 						&scan_interval, error);
3801d4f2939cSRui Paulo }
3802d4f2939cSRui Paulo 
3803d4f2939cSRui Paulo 
3804d4f2939cSRui Paulo /**
3805d4f2939cSRui Paulo  * wpas_dbus_setter_scan_interval - Control scan interval
3806d4f2939cSRui Paulo  * @iter: Pointer to incoming dbus message iter
3807d4f2939cSRui Paulo  * @error: Location to store error on failure
3808d4f2939cSRui Paulo  * @user_data: Function specific data
3809d4f2939cSRui Paulo  * Returns: TRUE on success, FALSE on failure
3810d4f2939cSRui Paulo  *
3811d4f2939cSRui Paulo  * Setter function for "ScanInterval" property.
3812d4f2939cSRui Paulo  */
wpas_dbus_setter_scan_interval(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3813780fb4a2SCy Schubert dbus_bool_t wpas_dbus_setter_scan_interval(
3814780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
3815780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
3816d4f2939cSRui Paulo {
3817d4f2939cSRui Paulo 	struct wpa_supplicant *wpa_s = user_data;
3818d4f2939cSRui Paulo 	dbus_int32_t scan_interval;
3819d4f2939cSRui Paulo 
3820d4f2939cSRui Paulo 	if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_INT32,
3821d4f2939cSRui Paulo 					      &scan_interval))
3822d4f2939cSRui Paulo 		return FALSE;
3823d4f2939cSRui Paulo 
3824d4f2939cSRui Paulo 	if (wpa_supplicant_set_scan_interval(wpa_s, scan_interval)) {
3825d4f2939cSRui Paulo 		dbus_set_error_const(error, DBUS_ERROR_FAILED,
3826d4f2939cSRui Paulo 				     "scan_interval must be >= 0");
3827d4f2939cSRui Paulo 		return FALSE;
3828d4f2939cSRui Paulo 	}
3829d4f2939cSRui Paulo 	return TRUE;
3830d4f2939cSRui Paulo }
3831d4f2939cSRui Paulo 
3832d4f2939cSRui Paulo 
3833d4f2939cSRui Paulo /**
3834d4f2939cSRui Paulo  * wpas_dbus_getter_ifname - Get interface name
3835d4f2939cSRui Paulo  * @iter: Pointer to incoming dbus message iter
3836d4f2939cSRui Paulo  * @error: Location to store error on failure
3837d4f2939cSRui Paulo  * @user_data: Function specific data
3838d4f2939cSRui Paulo  * Returns: TRUE on success, FALSE on failure
3839d4f2939cSRui Paulo  *
3840d4f2939cSRui Paulo  * Getter for "Ifname" property.
3841d4f2939cSRui Paulo  */
wpas_dbus_getter_ifname(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3842780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_ifname(
3843780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
3844780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
3845d4f2939cSRui Paulo {
3846d4f2939cSRui Paulo 	struct wpa_supplicant *wpa_s = user_data;
3847d4f2939cSRui Paulo 
384885732ac8SCy Schubert 	return wpas_dbus_string_property_getter(iter, wpa_s->ifname, error);
3849d4f2939cSRui Paulo }
3850d4f2939cSRui Paulo 
3851d4f2939cSRui Paulo 
3852d4f2939cSRui Paulo /**
3853d4f2939cSRui Paulo  * wpas_dbus_getter_driver - Get interface name
3854d4f2939cSRui Paulo  * @iter: Pointer to incoming dbus message iter
3855d4f2939cSRui Paulo  * @error: Location to store error on failure
3856d4f2939cSRui Paulo  * @user_data: Function specific data
3857d4f2939cSRui Paulo  * Returns: TRUE on success, FALSE on failure
3858d4f2939cSRui Paulo  *
3859d4f2939cSRui Paulo  * Getter for "Driver" property.
3860d4f2939cSRui Paulo  */
wpas_dbus_getter_driver(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3861780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_driver(
3862780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
3863780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
3864d4f2939cSRui Paulo {
3865d4f2939cSRui Paulo 	struct wpa_supplicant *wpa_s = user_data;
3866d4f2939cSRui Paulo 
3867d4f2939cSRui Paulo 	if (wpa_s->driver == NULL || wpa_s->driver->name == NULL) {
38685b9c547cSRui Paulo 		wpa_printf(MSG_DEBUG, "%s[dbus]: wpa_s has no driver set",
38695b9c547cSRui Paulo 			   __func__);
3870d4f2939cSRui Paulo 		dbus_set_error(error, DBUS_ERROR_FAILED, "%s: no driver set",
3871d4f2939cSRui Paulo 			       __func__);
3872d4f2939cSRui Paulo 		return FALSE;
3873d4f2939cSRui Paulo 	}
3874d4f2939cSRui Paulo 
387585732ac8SCy Schubert 	return wpas_dbus_string_property_getter(iter, wpa_s->driver->name,
387685732ac8SCy Schubert 						error);
3877d4f2939cSRui Paulo }
3878d4f2939cSRui Paulo 
3879d4f2939cSRui Paulo 
3880d4f2939cSRui Paulo /**
3881d4f2939cSRui Paulo  * wpas_dbus_getter_current_bss - Get current bss object path
3882d4f2939cSRui Paulo  * @iter: Pointer to incoming dbus message iter
3883d4f2939cSRui Paulo  * @error: Location to store error on failure
3884d4f2939cSRui Paulo  * @user_data: Function specific data
3885d4f2939cSRui Paulo  * Returns: TRUE on success, FALSE on failure
3886d4f2939cSRui Paulo  *
3887d4f2939cSRui Paulo  * Getter for "CurrentBSS" property.
3888d4f2939cSRui Paulo  */
wpas_dbus_getter_current_bss(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3889780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_current_bss(
3890780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
3891780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
3892d4f2939cSRui Paulo {
3893d4f2939cSRui Paulo 	struct wpa_supplicant *wpa_s = user_data;
3894d4f2939cSRui Paulo 	char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *bss_obj_path = path_buf;
3895d4f2939cSRui Paulo 
3896325151a3SRui Paulo 	if (wpa_s->current_bss && wpa_s->dbus_new_path)
3897d4f2939cSRui Paulo 		os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3898d4f2939cSRui Paulo 			    "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
3899d4f2939cSRui Paulo 			    wpa_s->dbus_new_path, wpa_s->current_bss->id);
3900d4f2939cSRui Paulo 	else
3901d4f2939cSRui Paulo 		os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
3902d4f2939cSRui Paulo 
3903d4f2939cSRui Paulo 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
3904d4f2939cSRui Paulo 						&bss_obj_path, error);
3905d4f2939cSRui Paulo }
3906d4f2939cSRui Paulo 
3907d4f2939cSRui Paulo 
3908d4f2939cSRui Paulo /**
3909d4f2939cSRui Paulo  * wpas_dbus_getter_current_network - Get current network object path
3910d4f2939cSRui Paulo  * @iter: Pointer to incoming dbus message iter
3911d4f2939cSRui Paulo  * @error: Location to store error on failure
3912d4f2939cSRui Paulo  * @user_data: Function specific data
3913d4f2939cSRui Paulo  * Returns: TRUE on success, FALSE on failure
3914d4f2939cSRui Paulo  *
3915d4f2939cSRui Paulo  * Getter for "CurrentNetwork" property.
3916d4f2939cSRui Paulo  */
wpas_dbus_getter_current_network(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3917780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_current_network(
3918780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
3919780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
3920d4f2939cSRui Paulo {
3921d4f2939cSRui Paulo 	struct wpa_supplicant *wpa_s = user_data;
3922d4f2939cSRui Paulo 	char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *net_obj_path = path_buf;
3923d4f2939cSRui Paulo 
3924325151a3SRui Paulo 	if (wpa_s->current_ssid && wpa_s->dbus_new_path)
3925d4f2939cSRui Paulo 		os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3926d4f2939cSRui Paulo 			    "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
3927d4f2939cSRui Paulo 			    wpa_s->dbus_new_path, wpa_s->current_ssid->id);
3928d4f2939cSRui Paulo 	else
3929d4f2939cSRui Paulo 		os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
3930d4f2939cSRui Paulo 
3931d4f2939cSRui Paulo 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
3932d4f2939cSRui Paulo 						&net_obj_path, error);
3933d4f2939cSRui Paulo }
3934d4f2939cSRui Paulo 
3935d4f2939cSRui Paulo 
3936d4f2939cSRui Paulo /**
3937d4f2939cSRui Paulo  * wpas_dbus_getter_current_auth_mode - Get current authentication type
3938d4f2939cSRui Paulo  * @iter: Pointer to incoming dbus message iter
3939d4f2939cSRui Paulo  * @error: Location to store error on failure
3940d4f2939cSRui Paulo  * @user_data: Function specific data
3941d4f2939cSRui Paulo  * Returns: TRUE on success, FALSE on failure
3942d4f2939cSRui Paulo  *
3943d4f2939cSRui Paulo  * Getter for "CurrentAuthMode" property.
3944d4f2939cSRui Paulo  */
wpas_dbus_getter_current_auth_mode(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3945780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_current_auth_mode(
3946780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
3947780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
3948d4f2939cSRui Paulo {
3949d4f2939cSRui Paulo 	struct wpa_supplicant *wpa_s = user_data;
3950d4f2939cSRui Paulo 	const char *eap_mode;
3951d4f2939cSRui Paulo 	const char *auth_mode;
3952d4f2939cSRui Paulo 	char eap_mode_buf[WPAS_DBUS_AUTH_MODE_MAX];
3953d4f2939cSRui Paulo 
3954d4f2939cSRui Paulo 	if (wpa_s->wpa_state != WPA_COMPLETED) {
3955d4f2939cSRui Paulo 		auth_mode = "INACTIVE";
3956d4f2939cSRui Paulo 	} else if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X ||
3957d4f2939cSRui Paulo 	    wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3958d4f2939cSRui Paulo 		eap_mode = wpa_supplicant_get_eap_mode(wpa_s);
3959d4f2939cSRui Paulo 		os_snprintf(eap_mode_buf, WPAS_DBUS_AUTH_MODE_MAX,
3960d4f2939cSRui Paulo 			    "EAP-%s", eap_mode);
3961d4f2939cSRui Paulo 		auth_mode = eap_mode_buf;
3962d4f2939cSRui Paulo 
3963780fb4a2SCy Schubert 	} else if (wpa_s->current_ssid) {
3964d4f2939cSRui Paulo 		auth_mode = wpa_key_mgmt_txt(wpa_s->key_mgmt,
3965d4f2939cSRui Paulo 					     wpa_s->current_ssid->proto);
3966780fb4a2SCy Schubert 	} else {
3967780fb4a2SCy Schubert 		auth_mode = "UNKNOWN";
3968d4f2939cSRui Paulo 	}
3969d4f2939cSRui Paulo 
3970d4f2939cSRui Paulo 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3971d4f2939cSRui Paulo 						&auth_mode, error);
3972d4f2939cSRui Paulo }
3973d4f2939cSRui Paulo 
3974d4f2939cSRui Paulo 
3975d4f2939cSRui Paulo /**
3976d4f2939cSRui Paulo  * wpas_dbus_getter_bridge_ifname - Get interface name
3977d4f2939cSRui Paulo  * @iter: Pointer to incoming dbus message iter
3978d4f2939cSRui Paulo  * @error: Location to store error on failure
3979d4f2939cSRui Paulo  * @user_data: Function specific data
3980d4f2939cSRui Paulo  * Returns: TRUE on success, FALSE on failure
3981d4f2939cSRui Paulo  *
3982d4f2939cSRui Paulo  * Getter for "BridgeIfname" property.
3983d4f2939cSRui Paulo  */
wpas_dbus_getter_bridge_ifname(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3984780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_bridge_ifname(
3985780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
3986780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
3987d4f2939cSRui Paulo {
3988d4f2939cSRui Paulo 	struct wpa_supplicant *wpa_s = user_data;
39895b9c547cSRui Paulo 
399085732ac8SCy Schubert 	return wpas_dbus_string_property_getter(iter, wpa_s->bridge_ifname,
399185732ac8SCy Schubert 						error);
3992d4f2939cSRui Paulo }
3993d4f2939cSRui Paulo 
3994d4f2939cSRui Paulo 
wpas_dbus_setter_bridge_ifname(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3995c1d255d3SCy Schubert dbus_bool_t wpas_dbus_setter_bridge_ifname(
3996c1d255d3SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
3997c1d255d3SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
3998c1d255d3SCy Schubert {
3999c1d255d3SCy Schubert 	struct wpa_supplicant *wpa_s = user_data;
4000c1d255d3SCy Schubert 	const char *bridge_ifname = NULL;
4001c1d255d3SCy Schubert 	const char *msg;
4002c1d255d3SCy Schubert 	int r;
4003c1d255d3SCy Schubert 
4004c1d255d3SCy Schubert 	if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
4005c1d255d3SCy Schubert 					      &bridge_ifname))
4006c1d255d3SCy Schubert 		return FALSE;
4007c1d255d3SCy Schubert 
4008c1d255d3SCy Schubert 	r = wpa_supplicant_update_bridge_ifname(wpa_s, bridge_ifname);
4009c1d255d3SCy Schubert 	if (r != 0) {
4010c1d255d3SCy Schubert 		switch (r) {
4011c1d255d3SCy Schubert 		case -EINVAL:
4012c1d255d3SCy Schubert 			msg = "invalid interface name";
4013c1d255d3SCy Schubert 			break;
4014c1d255d3SCy Schubert 		case -EBUSY:
4015c1d255d3SCy Schubert 			msg = "interface is busy";
4016c1d255d3SCy Schubert 			break;
4017c1d255d3SCy Schubert 		case -EIO:
4018c1d255d3SCy Schubert 			msg = "socket error";
4019c1d255d3SCy Schubert 			break;
4020c1d255d3SCy Schubert 		default:
4021c1d255d3SCy Schubert 			msg = "unknown error";
4022c1d255d3SCy Schubert 			break;
4023c1d255d3SCy Schubert 		}
4024c1d255d3SCy Schubert 		dbus_set_error_const(error, DBUS_ERROR_FAILED, msg);
4025c1d255d3SCy Schubert 		return FALSE;
4026c1d255d3SCy Schubert 	}
4027c1d255d3SCy Schubert 
4028c1d255d3SCy Schubert 	return TRUE;
4029c1d255d3SCy Schubert }
4030c1d255d3SCy Schubert 
4031c1d255d3SCy Schubert 
4032d4f2939cSRui Paulo /**
4033780fb4a2SCy Schubert  * wpas_dbus_getter_config_file - Get interface configuration file path
4034780fb4a2SCy Schubert  * @iter: Pointer to incoming dbus message iter
4035780fb4a2SCy Schubert  * @error: Location to store error on failure
4036780fb4a2SCy Schubert  * @user_data: Function specific data
4037780fb4a2SCy Schubert  * Returns: TRUE on success, FALSE on failure
4038780fb4a2SCy Schubert  *
4039780fb4a2SCy Schubert  * Getter for "ConfigFile" property.
4040780fb4a2SCy Schubert  */
wpas_dbus_getter_config_file(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)4041780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_config_file(
4042780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
4043780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
4044780fb4a2SCy Schubert {
4045780fb4a2SCy Schubert 	struct wpa_supplicant *wpa_s = user_data;
4046780fb4a2SCy Schubert 
404785732ac8SCy Schubert 	return wpas_dbus_string_property_getter(iter, wpa_s->confname, error);
4048780fb4a2SCy Schubert }
4049780fb4a2SCy Schubert 
4050780fb4a2SCy Schubert 
4051780fb4a2SCy Schubert /**
4052d4f2939cSRui Paulo  * wpas_dbus_getter_bsss - Get array of BSSs objects
4053d4f2939cSRui Paulo  * @iter: Pointer to incoming dbus message iter
4054d4f2939cSRui Paulo  * @error: Location to store error on failure
4055d4f2939cSRui Paulo  * @user_data: Function specific data
4056d4f2939cSRui Paulo  * Returns: TRUE on success, FALSE on failure
4057d4f2939cSRui Paulo  *
4058d4f2939cSRui Paulo  * Getter for "BSSs" property.
4059d4f2939cSRui Paulo  */
wpas_dbus_getter_bsss(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)4060780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_bsss(
4061780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
4062780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
4063d4f2939cSRui Paulo {
4064d4f2939cSRui Paulo 	struct wpa_supplicant *wpa_s = user_data;
4065d4f2939cSRui Paulo 	struct wpa_bss *bss;
4066d4f2939cSRui Paulo 	char **paths;
4067d4f2939cSRui Paulo 	unsigned int i = 0;
4068d4f2939cSRui Paulo 	dbus_bool_t success = FALSE;
4069d4f2939cSRui Paulo 
4070325151a3SRui Paulo 	if (!wpa_s->dbus_new_path) {
4071325151a3SRui Paulo 		dbus_set_error(error, DBUS_ERROR_FAILED,
4072325151a3SRui Paulo 			       "%s: no D-Bus interface", __func__);
4073325151a3SRui Paulo 		return FALSE;
4074325151a3SRui Paulo 	}
4075325151a3SRui Paulo 
4076d4f2939cSRui Paulo 	paths = os_calloc(wpa_s->num_bss, sizeof(char *));
4077d4f2939cSRui Paulo 	if (!paths) {
4078d4f2939cSRui Paulo 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
4079d4f2939cSRui Paulo 		return FALSE;
4080d4f2939cSRui Paulo 	}
4081d4f2939cSRui Paulo 
4082d4f2939cSRui Paulo 	/* Loop through scan results and append each result's object path */
4083d4f2939cSRui Paulo 	dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
4084d4f2939cSRui Paulo 		paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
4085d4f2939cSRui Paulo 		if (paths[i] == NULL) {
4086d4f2939cSRui Paulo 			dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
4087d4f2939cSRui Paulo 					     "no memory");
4088d4f2939cSRui Paulo 			goto out;
4089d4f2939cSRui Paulo 		}
4090d4f2939cSRui Paulo 		/* Construct the object path for this BSS. */
4091d4f2939cSRui Paulo 		os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
4092d4f2939cSRui Paulo 			    "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
4093d4f2939cSRui Paulo 			    wpa_s->dbus_new_path, bss->id);
4094d4f2939cSRui Paulo 	}
4095d4f2939cSRui Paulo 
4096d4f2939cSRui Paulo 	success = wpas_dbus_simple_array_property_getter(iter,
4097d4f2939cSRui Paulo 							 DBUS_TYPE_OBJECT_PATH,
4098d4f2939cSRui Paulo 							 paths, wpa_s->num_bss,
4099d4f2939cSRui Paulo 							 error);
4100d4f2939cSRui Paulo 
4101d4f2939cSRui Paulo out:
4102d4f2939cSRui Paulo 	while (i)
4103d4f2939cSRui Paulo 		os_free(paths[--i]);
4104d4f2939cSRui Paulo 	os_free(paths);
4105d4f2939cSRui Paulo 	return success;
4106d4f2939cSRui Paulo }
4107d4f2939cSRui Paulo 
4108d4f2939cSRui Paulo 
4109d4f2939cSRui Paulo /**
4110d4f2939cSRui Paulo  * wpas_dbus_getter_networks - Get array of networks objects
4111d4f2939cSRui Paulo  * @iter: Pointer to incoming dbus message iter
4112d4f2939cSRui Paulo  * @error: Location to store error on failure
4113d4f2939cSRui Paulo  * @user_data: Function specific data
4114d4f2939cSRui Paulo  * Returns: TRUE on success, FALSE on failure
4115d4f2939cSRui Paulo  *
4116d4f2939cSRui Paulo  * Getter for "Networks" property.
4117d4f2939cSRui Paulo  */
wpas_dbus_getter_networks(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)4118780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_networks(
4119780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
4120780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
4121d4f2939cSRui Paulo {
4122d4f2939cSRui Paulo 	struct wpa_supplicant *wpa_s = user_data;
4123d4f2939cSRui Paulo 	struct wpa_ssid *ssid;
4124d4f2939cSRui Paulo 	char **paths;
4125d4f2939cSRui Paulo 	unsigned int i = 0, num = 0;
4126d4f2939cSRui Paulo 	dbus_bool_t success = FALSE;
4127d4f2939cSRui Paulo 
4128325151a3SRui Paulo 	if (!wpa_s->dbus_new_path) {
4129325151a3SRui Paulo 		dbus_set_error(error, DBUS_ERROR_FAILED,
4130325151a3SRui Paulo 			       "%s: no D-Bus interface", __func__);
4131325151a3SRui Paulo 		return FALSE;
4132325151a3SRui Paulo 	}
4133325151a3SRui Paulo 
4134d4f2939cSRui Paulo 	for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
4135d4f2939cSRui Paulo 		if (!network_is_persistent_group(ssid))
4136d4f2939cSRui Paulo 			num++;
4137d4f2939cSRui Paulo 
4138d4f2939cSRui Paulo 	paths = os_calloc(num, sizeof(char *));
4139d4f2939cSRui Paulo 	if (!paths) {
4140d4f2939cSRui Paulo 		dbus_set_error(error, DBUS_ERROR_NO_MEMORY, "no memory");
4141d4f2939cSRui Paulo 		return FALSE;
4142d4f2939cSRui Paulo 	}
4143d4f2939cSRui Paulo 
4144d4f2939cSRui Paulo 	/* Loop through configured networks and append object path of each */
4145d4f2939cSRui Paulo 	for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
4146d4f2939cSRui Paulo 		if (network_is_persistent_group(ssid))
4147d4f2939cSRui Paulo 			continue;
4148d4f2939cSRui Paulo 		paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
4149d4f2939cSRui Paulo 		if (paths[i] == NULL) {
41505b9c547cSRui Paulo 			dbus_set_error(error, DBUS_ERROR_NO_MEMORY,
41515b9c547cSRui Paulo 				       "no memory");
4152d4f2939cSRui Paulo 			goto out;
4153d4f2939cSRui Paulo 		}
4154d4f2939cSRui Paulo 
4155d4f2939cSRui Paulo 		/* Construct the object path for this network. */
4156d4f2939cSRui Paulo 		os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
4157d4f2939cSRui Paulo 			    "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
4158d4f2939cSRui Paulo 			    wpa_s->dbus_new_path, ssid->id);
4159d4f2939cSRui Paulo 	}
4160d4f2939cSRui Paulo 
4161d4f2939cSRui Paulo 	success = wpas_dbus_simple_array_property_getter(iter,
4162d4f2939cSRui Paulo 							 DBUS_TYPE_OBJECT_PATH,
4163d4f2939cSRui Paulo 							 paths, num, error);
4164d4f2939cSRui Paulo 
4165d4f2939cSRui Paulo out:
4166d4f2939cSRui Paulo 	while (i)
4167d4f2939cSRui Paulo 		os_free(paths[--i]);
4168d4f2939cSRui Paulo 	os_free(paths);
4169d4f2939cSRui Paulo 	return success;
4170d4f2939cSRui Paulo }
4171d4f2939cSRui Paulo 
4172d4f2939cSRui Paulo 
4173d4f2939cSRui Paulo /**
41745b9c547cSRui Paulo  * wpas_dbus_getter_pkcs11_engine_path - Get PKCS #11 engine path
41755b9c547cSRui Paulo  * @iter: Pointer to incoming dbus message iter
41765b9c547cSRui Paulo  * @error: Location to store error on failure
41775b9c547cSRui Paulo  * @user_data: Function specific data
41785b9c547cSRui Paulo  * Returns: A dbus message containing the PKCS #11 engine path
41795b9c547cSRui Paulo  *
41805b9c547cSRui Paulo  * Getter for "PKCS11EnginePath" property.
41815b9c547cSRui Paulo  */
wpas_dbus_getter_pkcs11_engine_path(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)4182780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_pkcs11_engine_path(
4183780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
4184780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
41855b9c547cSRui Paulo {
41865b9c547cSRui Paulo 	struct wpa_supplicant *wpa_s = user_data;
41875b9c547cSRui Paulo 
418885732ac8SCy Schubert 	return wpas_dbus_string_property_getter(iter,
418985732ac8SCy Schubert 						wpa_s->conf->pkcs11_engine_path,
419085732ac8SCy Schubert 						error);
41915b9c547cSRui Paulo }
41925b9c547cSRui Paulo 
41935b9c547cSRui Paulo 
41945b9c547cSRui Paulo /**
41955b9c547cSRui Paulo  * wpas_dbus_getter_pkcs11_module_path - Get PKCS #11 module path
41965b9c547cSRui Paulo  * @iter: Pointer to incoming dbus message iter
41975b9c547cSRui Paulo  * @error: Location to store error on failure
41985b9c547cSRui Paulo  * @user_data: Function specific data
41995b9c547cSRui Paulo  * Returns: A dbus message containing the PKCS #11 module path
42005b9c547cSRui Paulo  *
42015b9c547cSRui Paulo  * Getter for "PKCS11ModulePath" property.
42025b9c547cSRui Paulo  */
wpas_dbus_getter_pkcs11_module_path(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)4203780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_pkcs11_module_path(
4204780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
4205780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
42065b9c547cSRui Paulo {
42075b9c547cSRui Paulo 	struct wpa_supplicant *wpa_s = user_data;
42085b9c547cSRui Paulo 
420985732ac8SCy Schubert 	return wpas_dbus_string_property_getter(iter,
421085732ac8SCy Schubert 						wpa_s->conf->pkcs11_module_path,
421185732ac8SCy Schubert 						error);
42125b9c547cSRui Paulo }
42135b9c547cSRui Paulo 
42145b9c547cSRui Paulo 
42155b9c547cSRui Paulo /**
4216d4f2939cSRui Paulo  * wpas_dbus_getter_blobs - Get all blobs defined for this interface
4217d4f2939cSRui Paulo  * @iter: Pointer to incoming dbus message iter
4218d4f2939cSRui Paulo  * @error: Location to store error on failure
4219d4f2939cSRui Paulo  * @user_data: Function specific data
4220d4f2939cSRui Paulo  * Returns: TRUE on success, FALSE on failure
4221d4f2939cSRui Paulo  *
4222d4f2939cSRui Paulo  * Getter for "Blobs" property.
4223d4f2939cSRui Paulo  */
wpas_dbus_getter_blobs(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)4224780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_blobs(
4225780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
4226780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
4227d4f2939cSRui Paulo {
4228d4f2939cSRui Paulo 	struct wpa_supplicant *wpa_s = user_data;
4229d4f2939cSRui Paulo 	DBusMessageIter variant_iter, dict_iter, entry_iter, array_iter;
4230d4f2939cSRui Paulo 	struct wpa_config_blob *blob;
4231d4f2939cSRui Paulo 
4232d4f2939cSRui Paulo 	if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
4233d4f2939cSRui Paulo 					      "a{say}", &variant_iter) ||
4234d4f2939cSRui Paulo 	    !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
4235d4f2939cSRui Paulo 					      "{say}", &dict_iter)) {
4236d4f2939cSRui Paulo 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
4237d4f2939cSRui Paulo 		return FALSE;
4238d4f2939cSRui Paulo 	}
4239d4f2939cSRui Paulo 
4240d4f2939cSRui Paulo 	blob = wpa_s->conf->blobs;
4241d4f2939cSRui Paulo 	while (blob) {
4242d4f2939cSRui Paulo 		if (!dbus_message_iter_open_container(&dict_iter,
4243d4f2939cSRui Paulo 						      DBUS_TYPE_DICT_ENTRY,
4244d4f2939cSRui Paulo 						      NULL, &entry_iter) ||
4245d4f2939cSRui Paulo 		    !dbus_message_iter_append_basic(&entry_iter,
4246d4f2939cSRui Paulo 						    DBUS_TYPE_STRING,
4247d4f2939cSRui Paulo 						    &(blob->name)) ||
4248d4f2939cSRui Paulo 		    !dbus_message_iter_open_container(&entry_iter,
4249d4f2939cSRui Paulo 						      DBUS_TYPE_ARRAY,
4250d4f2939cSRui Paulo 						      DBUS_TYPE_BYTE_AS_STRING,
4251d4f2939cSRui Paulo 						      &array_iter) ||
4252d4f2939cSRui Paulo 		    !dbus_message_iter_append_fixed_array(&array_iter,
4253d4f2939cSRui Paulo 							  DBUS_TYPE_BYTE,
4254d4f2939cSRui Paulo 							  &(blob->data),
4255d4f2939cSRui Paulo 							  blob->len) ||
4256d4f2939cSRui Paulo 		    !dbus_message_iter_close_container(&entry_iter,
4257d4f2939cSRui Paulo 						       &array_iter) ||
4258d4f2939cSRui Paulo 		    !dbus_message_iter_close_container(&dict_iter,
4259d4f2939cSRui Paulo 						       &entry_iter)) {
4260d4f2939cSRui Paulo 			dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
4261d4f2939cSRui Paulo 					     "no memory");
4262d4f2939cSRui Paulo 			return FALSE;
4263d4f2939cSRui Paulo 		}
4264d4f2939cSRui Paulo 
4265d4f2939cSRui Paulo 		blob = blob->next;
4266d4f2939cSRui Paulo 	}
4267d4f2939cSRui Paulo 
4268d4f2939cSRui Paulo 	if (!dbus_message_iter_close_container(&variant_iter, &dict_iter) ||
4269d4f2939cSRui Paulo 	    !dbus_message_iter_close_container(iter, &variant_iter)) {
4270d4f2939cSRui Paulo 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
4271d4f2939cSRui Paulo 		return FALSE;
4272d4f2939cSRui Paulo 	}
4273d4f2939cSRui Paulo 
4274d4f2939cSRui Paulo 	return TRUE;
4275d4f2939cSRui Paulo }
4276d4f2939cSRui Paulo 
4277d4f2939cSRui Paulo 
wpas_dbus_getter_iface_global(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)4278780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_iface_global(
4279780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
4280780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
4281780fb4a2SCy Schubert {
4282780fb4a2SCy Schubert 	struct wpa_supplicant *wpa_s = user_data;
4283780fb4a2SCy Schubert 	int ret;
4284780fb4a2SCy Schubert 	char buf[250];
4285780fb4a2SCy Schubert 	char *p = buf;
4286780fb4a2SCy Schubert 
4287780fb4a2SCy Schubert 	if (!property_desc->data) {
4288780fb4a2SCy Schubert 		dbus_set_error(error, DBUS_ERROR_INVALID_ARGS,
4289780fb4a2SCy Schubert 			       "Unhandled interface property %s",
4290780fb4a2SCy Schubert 			       property_desc->dbus_property);
4291780fb4a2SCy Schubert 		return FALSE;
4292780fb4a2SCy Schubert 	}
4293780fb4a2SCy Schubert 
4294780fb4a2SCy Schubert 	ret = wpa_config_get_value(property_desc->data, wpa_s->conf, buf,
4295780fb4a2SCy Schubert 				   sizeof(buf));
4296780fb4a2SCy Schubert 	if (ret < 0)
4297780fb4a2SCy Schubert 		*p = '\0';
4298780fb4a2SCy Schubert 
4299780fb4a2SCy Schubert 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &p,
4300780fb4a2SCy Schubert 						error);
4301780fb4a2SCy Schubert }
4302780fb4a2SCy Schubert 
4303780fb4a2SCy Schubert 
wpas_dbus_setter_iface_global(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)4304780fb4a2SCy Schubert dbus_bool_t wpas_dbus_setter_iface_global(
4305780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
4306780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
4307780fb4a2SCy Schubert {
4308780fb4a2SCy Schubert 	struct wpa_supplicant *wpa_s = user_data;
4309780fb4a2SCy Schubert 	const char *new_value = NULL;
4310780fb4a2SCy Schubert 	char buf[250];
4311780fb4a2SCy Schubert 	size_t combined_len;
4312780fb4a2SCy Schubert 	int ret;
4313780fb4a2SCy Schubert 
4314780fb4a2SCy Schubert 	if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
4315780fb4a2SCy Schubert 					      &new_value))
4316780fb4a2SCy Schubert 		return FALSE;
4317780fb4a2SCy Schubert 
4318780fb4a2SCy Schubert 	combined_len = os_strlen(property_desc->data) + os_strlen(new_value) +
4319780fb4a2SCy Schubert 		3;
4320780fb4a2SCy Schubert 	if (combined_len >= sizeof(buf)) {
4321780fb4a2SCy Schubert 		dbus_set_error(error, DBUS_ERROR_INVALID_ARGS,
4322780fb4a2SCy Schubert 			       "Interface property %s value too large",
4323780fb4a2SCy Schubert 			       property_desc->dbus_property);
4324780fb4a2SCy Schubert 		return FALSE;
4325780fb4a2SCy Schubert 	}
4326780fb4a2SCy Schubert 
4327780fb4a2SCy Schubert 	if (!new_value[0])
4328780fb4a2SCy Schubert 		new_value = "NULL";
4329780fb4a2SCy Schubert 
4330780fb4a2SCy Schubert 	ret = os_snprintf(buf, combined_len, "%s=%s", property_desc->data,
4331780fb4a2SCy Schubert 			  new_value);
4332780fb4a2SCy Schubert 	if (os_snprintf_error(combined_len, ret)) {
4333780fb4a2SCy Schubert 		dbus_set_error(error,  WPAS_DBUS_ERROR_UNKNOWN_ERROR,
4334780fb4a2SCy Schubert 			       "Failed to construct new interface property %s",
4335780fb4a2SCy Schubert 			       property_desc->dbus_property);
4336780fb4a2SCy Schubert 		return FALSE;
4337780fb4a2SCy Schubert 	}
4338780fb4a2SCy Schubert 
4339c1d255d3SCy Schubert 	ret = wpa_config_process_global(wpa_s->conf, buf, -1);
4340c1d255d3SCy Schubert 	if (ret < 0) {
4341780fb4a2SCy Schubert 		dbus_set_error(error, DBUS_ERROR_INVALID_ARGS,
4342780fb4a2SCy Schubert 			       "Failed to set interface property %s",
4343780fb4a2SCy Schubert 			       property_desc->dbus_property);
4344780fb4a2SCy Schubert 		return FALSE;
4345c1d255d3SCy Schubert 	} else if (ret == 0) {
4346780fb4a2SCy Schubert 		wpa_supplicant_update_config(wpa_s);
4347c1d255d3SCy Schubert 	}
4348780fb4a2SCy Schubert 	return TRUE;
4349780fb4a2SCy Schubert }
4350780fb4a2SCy Schubert 
4351780fb4a2SCy Schubert 
43524bc52338SCy Schubert /**
43534bc52338SCy Schubert  * wpas_dbus_getter_stas - Get connected stations for an interface
43544bc52338SCy Schubert  * @iter: Pointer to incoming dbus message iter
43554bc52338SCy Schubert  * @error: Location to store error on failure
43564bc52338SCy Schubert  * @user_data: Function specific data
43574bc52338SCy Schubert  * Returns: a list of stations
43584bc52338SCy Schubert  *
43594bc52338SCy Schubert  * Getter for "Stations" property.
43604bc52338SCy Schubert  */
wpas_dbus_getter_stas(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)43614bc52338SCy Schubert dbus_bool_t wpas_dbus_getter_stas(
43624bc52338SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
43634bc52338SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
43644bc52338SCy Schubert {
43654bc52338SCy Schubert 	struct wpa_supplicant *wpa_s = user_data;
43664bc52338SCy Schubert 	struct sta_info *sta = NULL;
43674bc52338SCy Schubert 	char **paths = NULL;
43684bc52338SCy Schubert 	unsigned int i = 0, num = 0;
43694bc52338SCy Schubert 	dbus_bool_t success = FALSE;
43704bc52338SCy Schubert 
43714bc52338SCy Schubert 	if (!wpa_s->dbus_new_path) {
43724bc52338SCy Schubert 		dbus_set_error(error, DBUS_ERROR_FAILED,
43734bc52338SCy Schubert 			       "%s: no D-Bus interface", __func__);
43744bc52338SCy Schubert 		return FALSE;
43754bc52338SCy Schubert 	}
43764bc52338SCy Schubert 
43774bc52338SCy Schubert #ifdef CONFIG_AP
43784bc52338SCy Schubert 	if (wpa_s->ap_iface) {
43794bc52338SCy Schubert 		struct hostapd_data *hapd;
43804bc52338SCy Schubert 
43814bc52338SCy Schubert 		hapd = wpa_s->ap_iface->bss[0];
43824bc52338SCy Schubert 		sta = hapd->sta_list;
43834bc52338SCy Schubert 		num = hapd->num_sta;
43844bc52338SCy Schubert 	}
43854bc52338SCy Schubert #endif /* CONFIG_AP */
43864bc52338SCy Schubert 
43874bc52338SCy Schubert 	paths = os_calloc(num, sizeof(char *));
43884bc52338SCy Schubert 	if (!paths) {
43894bc52338SCy Schubert 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
43904bc52338SCy Schubert 		return FALSE;
43914bc52338SCy Schubert 	}
43924bc52338SCy Schubert 
43934bc52338SCy Schubert 	/* Loop through scan results and append each result's object path */
43944bc52338SCy Schubert 	for (; sta; sta = sta->next) {
43954bc52338SCy Schubert 		paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
43964bc52338SCy Schubert 		if (!paths[i]) {
43974bc52338SCy Schubert 			dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
43984bc52338SCy Schubert 					     "no memory");
43994bc52338SCy Schubert 			goto out;
44004bc52338SCy Schubert 		}
44014bc52338SCy Schubert 		/* Construct the object path for this BSS. */
44024bc52338SCy Schubert 		os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
44034bc52338SCy Schubert 			    "%s/" WPAS_DBUS_NEW_STAS_PART "/" COMPACT_MACSTR,
44044bc52338SCy Schubert 			    wpa_s->dbus_new_path, MAC2STR(sta->addr));
44054bc52338SCy Schubert 	}
44064bc52338SCy Schubert 
44074bc52338SCy Schubert 	success = wpas_dbus_simple_array_property_getter(iter,
44084bc52338SCy Schubert 							 DBUS_TYPE_OBJECT_PATH,
44094bc52338SCy Schubert 							 paths, num,
44104bc52338SCy Schubert 							 error);
44114bc52338SCy Schubert 
44124bc52338SCy Schubert out:
44134bc52338SCy Schubert 	while (i)
44144bc52338SCy Schubert 		os_free(paths[--i]);
44154bc52338SCy Schubert 	os_free(paths);
44164bc52338SCy Schubert 	return success;
44174bc52338SCy Schubert }
44184bc52338SCy Schubert 
44194bc52338SCy Schubert 
44204bc52338SCy Schubert /**
4421c1d255d3SCy Schubert  * wpas_dbus_setter_mac_address_randomization_mask - Set masks used for
4422c1d255d3SCy Schubert  * MAC address randomization
4423c1d255d3SCy Schubert  * @iter: Pointer to incoming dbus message iter
4424c1d255d3SCy Schubert  * @error: Location to store error on failure
4425c1d255d3SCy Schubert  * @user_data: Function specific data
4426c1d255d3SCy Schubert  * Returns: TRUE on success, FALSE on failure
4427c1d255d3SCy Schubert  *
4428c1d255d3SCy Schubert  * Setter for "MACAddressRandomizationMask" property.
4429c1d255d3SCy Schubert  */
wpas_dbus_setter_mac_address_randomization_mask(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)4430c1d255d3SCy Schubert dbus_bool_t wpas_dbus_setter_mac_address_randomization_mask(
4431c1d255d3SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
4432c1d255d3SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
4433c1d255d3SCy Schubert {
4434c1d255d3SCy Schubert 	struct wpa_supplicant *wpa_s = user_data;
4435c1d255d3SCy Schubert 	DBusMessageIter variant_iter, dict_iter, entry_iter, array_iter;
4436c1d255d3SCy Schubert 	const char *key;
4437c1d255d3SCy Schubert 	unsigned int rand_type = 0;
4438c1d255d3SCy Schubert 	const u8 *mask;
4439c1d255d3SCy Schubert 	int mask_len;
4440c1d255d3SCy Schubert 	unsigned int rand_types_to_disable = MAC_ADDR_RAND_ALL;
4441c1d255d3SCy Schubert 
4442c1d255d3SCy Schubert 	dbus_message_iter_recurse(iter, &variant_iter);
4443c1d255d3SCy Schubert 	if (dbus_message_iter_get_arg_type(&variant_iter) != DBUS_TYPE_ARRAY) {
4444c1d255d3SCy Schubert 		dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
4445c1d255d3SCy Schubert 				     "invalid message format");
4446c1d255d3SCy Schubert 		return FALSE;
4447c1d255d3SCy Schubert 	}
4448c1d255d3SCy Schubert 	dbus_message_iter_recurse(&variant_iter, &dict_iter);
4449c1d255d3SCy Schubert 	while (dbus_message_iter_get_arg_type(&dict_iter) ==
4450c1d255d3SCy Schubert 	       DBUS_TYPE_DICT_ENTRY) {
4451c1d255d3SCy Schubert 		dbus_message_iter_recurse(&dict_iter, &entry_iter);
4452c1d255d3SCy Schubert 		if (dbus_message_iter_get_arg_type(&entry_iter) !=
4453c1d255d3SCy Schubert 		    DBUS_TYPE_STRING) {
4454c1d255d3SCy Schubert 			dbus_set_error(error, DBUS_ERROR_FAILED,
4455c1d255d3SCy Schubert 				       "%s: key not a string", __func__);
4456c1d255d3SCy Schubert 			return FALSE;
4457c1d255d3SCy Schubert 		}
4458c1d255d3SCy Schubert 		dbus_message_iter_get_basic(&entry_iter, &key);
4459c1d255d3SCy Schubert 		dbus_message_iter_next(&entry_iter);
4460c1d255d3SCy Schubert 		if (dbus_message_iter_get_arg_type(&entry_iter) !=
4461c1d255d3SCy Schubert 		    DBUS_TYPE_ARRAY ||
4462c1d255d3SCy Schubert 		    dbus_message_iter_get_element_type(&entry_iter) !=
4463c1d255d3SCy Schubert 		    DBUS_TYPE_BYTE) {
4464c1d255d3SCy Schubert 			dbus_set_error(error, DBUS_ERROR_FAILED,
4465c1d255d3SCy Schubert 				       "%s: mask was not a byte array",
4466c1d255d3SCy Schubert 				       __func__);
4467c1d255d3SCy Schubert 			return FALSE;
4468c1d255d3SCy Schubert 		}
4469c1d255d3SCy Schubert 		dbus_message_iter_recurse(&entry_iter, &array_iter);
4470c1d255d3SCy Schubert 		dbus_message_iter_get_fixed_array(&array_iter, &mask,
4471c1d255d3SCy Schubert 						  &mask_len);
4472c1d255d3SCy Schubert 
4473c1d255d3SCy Schubert 		if (os_strcmp(key, "scan") == 0) {
4474c1d255d3SCy Schubert 			rand_type = MAC_ADDR_RAND_SCAN;
4475c1d255d3SCy Schubert 		} else if (os_strcmp(key, "sched_scan") == 0) {
4476c1d255d3SCy Schubert 			rand_type = MAC_ADDR_RAND_SCHED_SCAN;
4477c1d255d3SCy Schubert 		} else if (os_strcmp(key, "pno") == 0) {
4478c1d255d3SCy Schubert 			rand_type = MAC_ADDR_RAND_PNO;
4479c1d255d3SCy Schubert 		} else {
4480c1d255d3SCy Schubert 			dbus_set_error(error, DBUS_ERROR_FAILED,
4481c1d255d3SCy Schubert 				       "%s: bad scan type \"%s\"",
4482c1d255d3SCy Schubert 				       __func__, key);
4483c1d255d3SCy Schubert 			return FALSE;
4484c1d255d3SCy Schubert 		}
4485c1d255d3SCy Schubert 
4486c1d255d3SCy Schubert 		if (mask_len != ETH_ALEN) {
4487c1d255d3SCy Schubert 			dbus_set_error(error, DBUS_ERROR_FAILED,
4488c1d255d3SCy Schubert 				       "%s: malformed MAC mask given",
4489c1d255d3SCy Schubert 				       __func__);
4490c1d255d3SCy Schubert 			return FALSE;
4491c1d255d3SCy Schubert 		}
4492c1d255d3SCy Schubert 
4493c1d255d3SCy Schubert 		if (wpas_enable_mac_addr_randomization(
4494c1d255d3SCy Schubert 			    wpa_s, rand_type, wpa_s->perm_addr, mask)) {
4495c1d255d3SCy Schubert 			dbus_set_error(error, DBUS_ERROR_FAILED,
4496c1d255d3SCy Schubert 				       "%s: failed to set up MAC address randomization for %s",
4497c1d255d3SCy Schubert 				       __func__, key);
4498c1d255d3SCy Schubert 			return FALSE;
4499c1d255d3SCy Schubert 		}
4500c1d255d3SCy Schubert 
4501c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG,
4502c1d255d3SCy Schubert 			   "%s: Enabled MAC address randomization for %s with mask: "
4503c1d255d3SCy Schubert 			   MACSTR, wpa_s->ifname, key, MAC2STR(mask));
4504c1d255d3SCy Schubert 		rand_types_to_disable &= ~rand_type;
4505c1d255d3SCy Schubert 		dbus_message_iter_next(&dict_iter);
4506c1d255d3SCy Schubert 	}
4507c1d255d3SCy Schubert 
4508c1d255d3SCy Schubert 	if (rand_types_to_disable &&
4509c1d255d3SCy Schubert 	    wpas_disable_mac_addr_randomization(wpa_s, rand_types_to_disable)) {
4510c1d255d3SCy Schubert 		dbus_set_error(error, DBUS_ERROR_FAILED,
4511c1d255d3SCy Schubert 			       "%s: failed to disable MAC address randomization",
4512c1d255d3SCy Schubert 			       __func__);
4513c1d255d3SCy Schubert 		return FALSE;
4514c1d255d3SCy Schubert 	}
4515c1d255d3SCy Schubert 
4516c1d255d3SCy Schubert 	return TRUE;
4517c1d255d3SCy Schubert }
4518c1d255d3SCy Schubert 
4519c1d255d3SCy Schubert 
wpas_dbus_getter_mac_address_randomization_mask(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)4520c1d255d3SCy Schubert dbus_bool_t wpas_dbus_getter_mac_address_randomization_mask(
4521c1d255d3SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
4522c1d255d3SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
4523c1d255d3SCy Schubert {
4524c1d255d3SCy Schubert 	struct wpa_supplicant *wpa_s = user_data;
4525c1d255d3SCy Schubert 	DBusMessageIter variant_iter, dict_iter, entry_iter, array_iter;
4526c1d255d3SCy Schubert 	unsigned int i;
4527c1d255d3SCy Schubert 	u8 mask_buf[ETH_ALEN];
4528c1d255d3SCy Schubert 	/* Read docs on dbus_message_iter_append_fixed_array() for why this
4529c1d255d3SCy Schubert 	 * is necessary... */
4530c1d255d3SCy Schubert 	u8 *mask = mask_buf;
4531c1d255d3SCy Schubert 	static const struct {
4532c1d255d3SCy Schubert 		const char *key;
4533c1d255d3SCy Schubert 		unsigned int type;
4534c1d255d3SCy Schubert 	} types[] = {
4535c1d255d3SCy Schubert 		{ "scan", MAC_ADDR_RAND_SCAN },
4536c1d255d3SCy Schubert 		{ "sched_scan", MAC_ADDR_RAND_SCHED_SCAN },
4537c1d255d3SCy Schubert 		{ "pno", MAC_ADDR_RAND_PNO }
4538c1d255d3SCy Schubert 	};
4539c1d255d3SCy Schubert 
4540c1d255d3SCy Schubert 	if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
4541c1d255d3SCy Schubert 					      "a{say}", &variant_iter) ||
4542c1d255d3SCy Schubert 	    !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
4543c1d255d3SCy Schubert 					      "{say}", &dict_iter)) {
4544c1d255d3SCy Schubert 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
4545c1d255d3SCy Schubert 		return FALSE;
4546c1d255d3SCy Schubert 	}
4547c1d255d3SCy Schubert 
4548c1d255d3SCy Schubert 	for (i = 0; i < ARRAY_SIZE(types); i++) {
4549c1d255d3SCy Schubert 		if (wpas_mac_addr_rand_scan_get_mask(wpa_s, types[i].type,
4550c1d255d3SCy Schubert 						     mask))
4551c1d255d3SCy Schubert 			continue;
4552c1d255d3SCy Schubert 
4553c1d255d3SCy Schubert 		if (!dbus_message_iter_open_container(&dict_iter,
4554c1d255d3SCy Schubert 						      DBUS_TYPE_DICT_ENTRY,
4555c1d255d3SCy Schubert 						      NULL, &entry_iter) ||
4556c1d255d3SCy Schubert 		    !dbus_message_iter_append_basic(&entry_iter,
4557c1d255d3SCy Schubert 						    DBUS_TYPE_STRING,
4558c1d255d3SCy Schubert 						    &types[i].key) ||
4559c1d255d3SCy Schubert 		    !dbus_message_iter_open_container(&entry_iter,
4560c1d255d3SCy Schubert 						      DBUS_TYPE_ARRAY,
4561c1d255d3SCy Schubert 						      DBUS_TYPE_BYTE_AS_STRING,
4562c1d255d3SCy Schubert 						      &array_iter) ||
4563c1d255d3SCy Schubert 		    !dbus_message_iter_append_fixed_array(&array_iter,
4564c1d255d3SCy Schubert 							  DBUS_TYPE_BYTE,
4565c1d255d3SCy Schubert 							  &mask,
4566c1d255d3SCy Schubert 							  ETH_ALEN) ||
4567c1d255d3SCy Schubert 		    !dbus_message_iter_close_container(&entry_iter,
4568c1d255d3SCy Schubert 						       &array_iter) ||
4569c1d255d3SCy Schubert 		    !dbus_message_iter_close_container(&dict_iter,
4570c1d255d3SCy Schubert 						       &entry_iter)) {
4571c1d255d3SCy Schubert 			dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
4572c1d255d3SCy Schubert 					     "no memory");
4573c1d255d3SCy Schubert 			return FALSE;
4574c1d255d3SCy Schubert 		}
4575c1d255d3SCy Schubert 	}
4576c1d255d3SCy Schubert 
4577c1d255d3SCy Schubert 	if (!dbus_message_iter_close_container(&variant_iter, &dict_iter) ||
4578c1d255d3SCy Schubert 	    !dbus_message_iter_close_container(iter, &variant_iter)) {
4579c1d255d3SCy Schubert 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
4580c1d255d3SCy Schubert 		return FALSE;
4581c1d255d3SCy Schubert 	}
4582c1d255d3SCy Schubert 
4583c1d255d3SCy Schubert 	return TRUE;
4584c1d255d3SCy Schubert }
4585c1d255d3SCy Schubert 
4586c1d255d3SCy Schubert 
4587c1d255d3SCy Schubert /**
45884bc52338SCy Schubert  * wpas_dbus_getter_sta_address - Return the address of a connected station
45894bc52338SCy Schubert  * @iter: Pointer to incoming dbus message iter
45904bc52338SCy Schubert  * @error: Location to store error on failure
45914bc52338SCy Schubert  * @user_data: Function specific data
45924bc52338SCy Schubert  * Returns: TRUE on success, FALSE on failure
45934bc52338SCy Schubert  *
45944bc52338SCy Schubert  * Getter for "Address" property.
45954bc52338SCy Schubert  */
wpas_dbus_getter_sta_address(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)45964bc52338SCy Schubert dbus_bool_t wpas_dbus_getter_sta_address(
45974bc52338SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
45984bc52338SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
45994bc52338SCy Schubert {
46004bc52338SCy Schubert #ifdef CONFIG_AP
46014bc52338SCy Schubert 	struct sta_handler_args *args = user_data;
46024bc52338SCy Schubert 	struct sta_info *sta;
46034bc52338SCy Schubert 
46044bc52338SCy Schubert 	sta = ap_get_sta(args->wpa_s->ap_iface->bss[0], args->sta);
46054bc52338SCy Schubert 	if (!sta)
46064bc52338SCy Schubert 		return FALSE;
46074bc52338SCy Schubert 
46084bc52338SCy Schubert 	return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
46094bc52338SCy Schubert 						      sta->addr, ETH_ALEN,
46104bc52338SCy Schubert 						      error);
46114bc52338SCy Schubert #else /* CONFIG_AP */
46124bc52338SCy Schubert     return FALSE;
46134bc52338SCy Schubert #endif /* CONFIG_AP */
46144bc52338SCy Schubert }
46154bc52338SCy Schubert 
46164bc52338SCy Schubert 
46174bc52338SCy Schubert /**
46184bc52338SCy Schubert  * wpas_dbus_getter_sta_aid - Return the AID of a connected station
46194bc52338SCy Schubert  * @iter: Pointer to incoming dbus message iter
46204bc52338SCy Schubert  * @error: Location to store error on failure
46214bc52338SCy Schubert  * @user_data: Function specific data
46224bc52338SCy Schubert  * Returns: TRUE on success, FALSE on failure
46234bc52338SCy Schubert  *
46244bc52338SCy Schubert  * Getter for "AID" property.
46254bc52338SCy Schubert  */
wpas_dbus_getter_sta_aid(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)46264bc52338SCy Schubert dbus_bool_t wpas_dbus_getter_sta_aid(
46274bc52338SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
46284bc52338SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
46294bc52338SCy Schubert {
46304bc52338SCy Schubert #ifdef CONFIG_AP
46314bc52338SCy Schubert 	struct sta_handler_args *args = user_data;
46324bc52338SCy Schubert 	struct sta_info *sta;
46334bc52338SCy Schubert 
46344bc52338SCy Schubert 	sta = ap_get_sta(args->wpa_s->ap_iface->bss[0], args->sta);
46354bc52338SCy Schubert 	if (!sta)
46364bc52338SCy Schubert 		return FALSE;
46374bc52338SCy Schubert 
46384bc52338SCy Schubert 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
46394bc52338SCy Schubert 						&sta->aid,
46404bc52338SCy Schubert 						error);
46414bc52338SCy Schubert #else /* CONFIG_AP */
46424bc52338SCy Schubert     return FALSE;
46434bc52338SCy Schubert #endif /* CONFIG_AP */
46444bc52338SCy Schubert }
46454bc52338SCy Schubert 
46464bc52338SCy Schubert 
46474bc52338SCy Schubert /**
46484bc52338SCy Schubert  * wpas_dbus_getter_sta_caps - Return the capabilities of a station
46494bc52338SCy Schubert  * @iter: Pointer to incoming dbus message iter
46504bc52338SCy Schubert  * @error: Location to store error on failure
46514bc52338SCy Schubert  * @user_data: Function specific data
46524bc52338SCy Schubert  * Returns: TRUE on success, FALSE on failure
46534bc52338SCy Schubert  *
46544bc52338SCy Schubert  * Getter for "Capabilities" property.
46554bc52338SCy Schubert  */
wpas_dbus_getter_sta_caps(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)46564bc52338SCy Schubert dbus_bool_t wpas_dbus_getter_sta_caps(
46574bc52338SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
46584bc52338SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
46594bc52338SCy Schubert {
46604bc52338SCy Schubert #ifdef CONFIG_AP
46614bc52338SCy Schubert 	struct sta_handler_args *args = user_data;
46624bc52338SCy Schubert 	struct sta_info *sta;
46634bc52338SCy Schubert 
46644bc52338SCy Schubert 	sta = ap_get_sta(args->wpa_s->ap_iface->bss[0], args->sta);
46654bc52338SCy Schubert 	if (!sta)
46664bc52338SCy Schubert 		return FALSE;
46674bc52338SCy Schubert 
46684bc52338SCy Schubert 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
46694bc52338SCy Schubert 						&sta->capability,
46704bc52338SCy Schubert 						error);
46714bc52338SCy Schubert #else /* CONFIG_AP */
46724bc52338SCy Schubert     return FALSE;
46734bc52338SCy Schubert #endif /* CONFIG_AP */
46744bc52338SCy Schubert }
46754bc52338SCy Schubert 
46764bc52338SCy Schubert 
46774bc52338SCy Schubert /**
46784bc52338SCy Schubert  * wpas_dbus_getter_rx_packets - Return the received packets for a station
46794bc52338SCy Schubert  * @iter: Pointer to incoming dbus message iter
46804bc52338SCy Schubert  * @error: Location to store error on failure
46814bc52338SCy Schubert  * @user_data: Function specific data
46824bc52338SCy Schubert  * Returns: TRUE on success, FALSE on failure
46834bc52338SCy Schubert  *
46844bc52338SCy Schubert  * Getter for "RxPackets" property.
46854bc52338SCy Schubert  */
wpas_dbus_getter_sta_rx_packets(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)46864bc52338SCy Schubert dbus_bool_t wpas_dbus_getter_sta_rx_packets(
46874bc52338SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
46884bc52338SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
46894bc52338SCy Schubert {
46904bc52338SCy Schubert #ifdef CONFIG_AP
46914bc52338SCy Schubert 	struct sta_handler_args *args = user_data;
46924bc52338SCy Schubert 	struct sta_info *sta;
46934bc52338SCy Schubert 	struct hostap_sta_driver_data data;
46944bc52338SCy Schubert 	struct hostapd_data *hapd;
46954bc52338SCy Schubert 
46964bc52338SCy Schubert 	if (!args->wpa_s->ap_iface)
46974bc52338SCy Schubert 		return FALSE;
46984bc52338SCy Schubert 
46994bc52338SCy Schubert 	hapd = args->wpa_s->ap_iface->bss[0];
47004bc52338SCy Schubert 	sta = ap_get_sta(hapd, args->sta);
47014bc52338SCy Schubert 	if (!sta)
47024bc52338SCy Schubert 		return FALSE;
47034bc52338SCy Schubert 
47044bc52338SCy Schubert 	if (hostapd_drv_read_sta_data(hapd, &data, sta->addr) < 0)
47054bc52338SCy Schubert 		return FALSE;
47064bc52338SCy Schubert 
47074bc52338SCy Schubert 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT64,
47084bc52338SCy Schubert 						&data.rx_packets,
47094bc52338SCy Schubert 						error);
47104bc52338SCy Schubert #else /* CONFIG_AP */
47114bc52338SCy Schubert     return FALSE;
47124bc52338SCy Schubert #endif /* CONFIG_AP */
47134bc52338SCy Schubert }
47144bc52338SCy Schubert 
47154bc52338SCy Schubert 
47164bc52338SCy Schubert /**
47174bc52338SCy Schubert  * wpas_dbus_getter_tx_packets - Return the transmitted packets for a station
47184bc52338SCy Schubert  * @iter: Pointer to incoming dbus message iter
47194bc52338SCy Schubert  * @error: Location to store error on failure
47204bc52338SCy Schubert  * @user_data: Function specific data
47214bc52338SCy Schubert  * Returns: TRUE on success, FALSE on failure
47224bc52338SCy Schubert  *
47234bc52338SCy Schubert  * Getter for "TxPackets" property.
47244bc52338SCy Schubert  */
wpas_dbus_getter_sta_tx_packets(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)47254bc52338SCy Schubert dbus_bool_t wpas_dbus_getter_sta_tx_packets(
47264bc52338SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
47274bc52338SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
47284bc52338SCy Schubert {
47294bc52338SCy Schubert #ifdef CONFIG_AP
47304bc52338SCy Schubert 	struct sta_handler_args *args = user_data;
47314bc52338SCy Schubert 	struct sta_info *sta;
47324bc52338SCy Schubert 	struct hostap_sta_driver_data data;
47334bc52338SCy Schubert 	struct hostapd_data *hapd;
47344bc52338SCy Schubert 
47354bc52338SCy Schubert 	if (!args->wpa_s->ap_iface)
47364bc52338SCy Schubert 		return FALSE;
47374bc52338SCy Schubert 
47384bc52338SCy Schubert 	hapd = args->wpa_s->ap_iface->bss[0];
47394bc52338SCy Schubert 	sta = ap_get_sta(hapd, args->sta);
47404bc52338SCy Schubert 	if (!sta)
47414bc52338SCy Schubert 		return FALSE;
47424bc52338SCy Schubert 
47434bc52338SCy Schubert 	if (hostapd_drv_read_sta_data(hapd, &data, sta->addr) < 0)
47444bc52338SCy Schubert 		return FALSE;
47454bc52338SCy Schubert 
47464bc52338SCy Schubert 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT64,
47474bc52338SCy Schubert 						&data.tx_packets,
47484bc52338SCy Schubert 						error);
47494bc52338SCy Schubert #else /* CONFIG_AP */
47504bc52338SCy Schubert     return FALSE;
47514bc52338SCy Schubert #endif /* CONFIG_AP */
47524bc52338SCy Schubert }
47534bc52338SCy Schubert 
47544bc52338SCy Schubert 
47554bc52338SCy Schubert /**
47564bc52338SCy Schubert  * wpas_dbus_getter_tx_bytes - Return the transmitted bytes for a station
47574bc52338SCy Schubert  * @iter: Pointer to incoming dbus message iter
47584bc52338SCy Schubert  * @error: Location to store error on failure
47594bc52338SCy Schubert  * @user_data: Function specific data
47604bc52338SCy Schubert  * Returns: TRUE on success, FALSE on failure
47614bc52338SCy Schubert  *
47624bc52338SCy Schubert  * Getter for "TxBytes" property.
47634bc52338SCy Schubert  */
wpas_dbus_getter_sta_tx_bytes(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)47644bc52338SCy Schubert dbus_bool_t wpas_dbus_getter_sta_tx_bytes(
47654bc52338SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
47664bc52338SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
47674bc52338SCy Schubert {
47684bc52338SCy Schubert #ifdef CONFIG_AP
47694bc52338SCy Schubert 	struct sta_handler_args *args = user_data;
47704bc52338SCy Schubert 	struct sta_info *sta;
47714bc52338SCy Schubert 	struct hostap_sta_driver_data data;
47724bc52338SCy Schubert 	struct hostapd_data *hapd;
47734bc52338SCy Schubert 
47744bc52338SCy Schubert 	if (!args->wpa_s->ap_iface)
47754bc52338SCy Schubert 		return FALSE;
47764bc52338SCy Schubert 
47774bc52338SCy Schubert 	hapd = args->wpa_s->ap_iface->bss[0];
47784bc52338SCy Schubert 	sta = ap_get_sta(hapd, args->sta);
47794bc52338SCy Schubert 	if (!sta)
47804bc52338SCy Schubert 		return FALSE;
47814bc52338SCy Schubert 
47824bc52338SCy Schubert 	if (hostapd_drv_read_sta_data(hapd, &data, sta->addr) < 0)
47834bc52338SCy Schubert 		return FALSE;
47844bc52338SCy Schubert 
47854bc52338SCy Schubert 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT64,
47864bc52338SCy Schubert 						&data.tx_bytes,
47874bc52338SCy Schubert 						error);
47884bc52338SCy Schubert #else /* CONFIG_AP */
47894bc52338SCy Schubert     return FALSE;
47904bc52338SCy Schubert #endif /* CONFIG_AP */
47914bc52338SCy Schubert }
47924bc52338SCy Schubert 
47934bc52338SCy Schubert 
47944bc52338SCy Schubert /**
47954bc52338SCy Schubert  * wpas_dbus_getter_rx_bytes - Return the received bytes for a station
47964bc52338SCy Schubert  * @iter: Pointer to incoming dbus message iter
47974bc52338SCy Schubert  * @error: Location to store error on failure
47984bc52338SCy Schubert  * @user_data: Function specific data
47994bc52338SCy Schubert  * Returns: TRUE on success, FALSE on failure
48004bc52338SCy Schubert  *
48014bc52338SCy Schubert  * Getter for "RxBytes" property.
48024bc52338SCy Schubert  */
wpas_dbus_getter_sta_rx_bytes(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)48034bc52338SCy Schubert dbus_bool_t wpas_dbus_getter_sta_rx_bytes(
48044bc52338SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
48054bc52338SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
48064bc52338SCy Schubert {
48074bc52338SCy Schubert #ifdef CONFIG_AP
48084bc52338SCy Schubert 	struct sta_handler_args *args = user_data;
48094bc52338SCy Schubert 	struct sta_info *sta;
48104bc52338SCy Schubert 	struct hostap_sta_driver_data data;
48114bc52338SCy Schubert 	struct hostapd_data *hapd;
48124bc52338SCy Schubert 
48134bc52338SCy Schubert 	if (!args->wpa_s->ap_iface)
48144bc52338SCy Schubert 		return FALSE;
48154bc52338SCy Schubert 
48164bc52338SCy Schubert 	hapd = args->wpa_s->ap_iface->bss[0];
48174bc52338SCy Schubert 	sta = ap_get_sta(hapd, args->sta);
48184bc52338SCy Schubert 	if (!sta)
48194bc52338SCy Schubert 		return FALSE;
48204bc52338SCy Schubert 
48214bc52338SCy Schubert 	if (hostapd_drv_read_sta_data(hapd, &data, sta->addr) < 0)
48224bc52338SCy Schubert 		return FALSE;
48234bc52338SCy Schubert 
48244bc52338SCy Schubert 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT64,
48254bc52338SCy Schubert 						&data.rx_bytes,
48264bc52338SCy Schubert 						error);
48274bc52338SCy Schubert #else /* CONFIG_AP */
48284bc52338SCy Schubert     return FALSE;
48294bc52338SCy Schubert #endif /* CONFIG_AP */
48304bc52338SCy Schubert }
48314bc52338SCy Schubert 
48324bc52338SCy Schubert 
get_bss_helper(struct bss_handler_args * args,DBusError * error,const char * func_name)4833d4f2939cSRui Paulo static struct wpa_bss * get_bss_helper(struct bss_handler_args *args,
4834d4f2939cSRui Paulo 				       DBusError *error, const char *func_name)
4835d4f2939cSRui Paulo {
4836d4f2939cSRui Paulo 	struct wpa_bss *res = wpa_bss_get_id(args->wpa_s, args->id);
4837d4f2939cSRui Paulo 
4838d4f2939cSRui Paulo 	if (!res) {
4839d4f2939cSRui Paulo 		wpa_printf(MSG_ERROR, "%s[dbus]: no bss with id %d found",
4840d4f2939cSRui Paulo 			   func_name, args->id);
4841d4f2939cSRui Paulo 		dbus_set_error(error, DBUS_ERROR_FAILED,
4842d4f2939cSRui Paulo 			       "%s: BSS %d not found",
4843d4f2939cSRui Paulo 			       func_name, args->id);
4844d4f2939cSRui Paulo 	}
4845d4f2939cSRui Paulo 
4846d4f2939cSRui Paulo 	return res;
4847d4f2939cSRui Paulo }
4848d4f2939cSRui Paulo 
4849d4f2939cSRui Paulo 
4850d4f2939cSRui Paulo /**
4851d4f2939cSRui Paulo  * wpas_dbus_getter_bss_bssid - Return the BSSID of a BSS
4852d4f2939cSRui Paulo  * @iter: Pointer to incoming dbus message iter
4853d4f2939cSRui Paulo  * @error: Location to store error on failure
4854d4f2939cSRui Paulo  * @user_data: Function specific data
4855d4f2939cSRui Paulo  * Returns: TRUE on success, FALSE on failure
4856d4f2939cSRui Paulo  *
4857d4f2939cSRui Paulo  * Getter for "BSSID" property.
4858d4f2939cSRui Paulo  */
wpas_dbus_getter_bss_bssid(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)4859780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_bss_bssid(
4860780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
4861780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
4862d4f2939cSRui Paulo {
4863d4f2939cSRui Paulo 	struct bss_handler_args *args = user_data;
4864d4f2939cSRui Paulo 	struct wpa_bss *res;
4865d4f2939cSRui Paulo 
4866d4f2939cSRui Paulo 	res = get_bss_helper(args, error, __func__);
4867d4f2939cSRui Paulo 	if (!res)
4868d4f2939cSRui Paulo 		return FALSE;
4869d4f2939cSRui Paulo 
4870d4f2939cSRui Paulo 	return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
4871d4f2939cSRui Paulo 						      res->bssid, ETH_ALEN,
4872d4f2939cSRui Paulo 						      error);
4873d4f2939cSRui Paulo }
4874d4f2939cSRui Paulo 
4875d4f2939cSRui Paulo 
4876d4f2939cSRui Paulo /**
4877d4f2939cSRui Paulo  * wpas_dbus_getter_bss_ssid - Return the SSID of a BSS
4878d4f2939cSRui Paulo  * @iter: Pointer to incoming dbus message iter
4879d4f2939cSRui Paulo  * @error: Location to store error on failure
4880d4f2939cSRui Paulo  * @user_data: Function specific data
4881d4f2939cSRui Paulo  * Returns: TRUE on success, FALSE on failure
4882d4f2939cSRui Paulo  *
4883d4f2939cSRui Paulo  * Getter for "SSID" property.
4884d4f2939cSRui Paulo  */
wpas_dbus_getter_bss_ssid(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)4885780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_bss_ssid(
4886780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
4887780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
4888d4f2939cSRui Paulo {
4889d4f2939cSRui Paulo 	struct bss_handler_args *args = user_data;
4890d4f2939cSRui Paulo 	struct wpa_bss *res;
4891d4f2939cSRui Paulo 
4892d4f2939cSRui Paulo 	res = get_bss_helper(args, error, __func__);
4893d4f2939cSRui Paulo 	if (!res)
4894d4f2939cSRui Paulo 		return FALSE;
4895d4f2939cSRui Paulo 
4896d4f2939cSRui Paulo 	return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
4897d4f2939cSRui Paulo 						      res->ssid, res->ssid_len,
4898d4f2939cSRui Paulo 						      error);
4899d4f2939cSRui Paulo }
4900d4f2939cSRui Paulo 
4901d4f2939cSRui Paulo 
4902d4f2939cSRui Paulo /**
4903d4f2939cSRui Paulo  * wpas_dbus_getter_bss_privacy - Return the privacy flag of a BSS
4904d4f2939cSRui Paulo  * @iter: Pointer to incoming dbus message iter
4905d4f2939cSRui Paulo  * @error: Location to store error on failure
4906d4f2939cSRui Paulo  * @user_data: Function specific data
4907d4f2939cSRui Paulo  * Returns: TRUE on success, FALSE on failure
4908d4f2939cSRui Paulo  *
4909d4f2939cSRui Paulo  * Getter for "Privacy" property.
4910d4f2939cSRui Paulo  */
wpas_dbus_getter_bss_privacy(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)4911780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_bss_privacy(
4912780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
4913780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
4914d4f2939cSRui Paulo {
4915d4f2939cSRui Paulo 	struct bss_handler_args *args = user_data;
4916d4f2939cSRui Paulo 	struct wpa_bss *res;
4917d4f2939cSRui Paulo 	dbus_bool_t privacy;
4918d4f2939cSRui Paulo 
4919d4f2939cSRui Paulo 	res = get_bss_helper(args, error, __func__);
4920d4f2939cSRui Paulo 	if (!res)
4921d4f2939cSRui Paulo 		return FALSE;
4922d4f2939cSRui Paulo 
4923d4f2939cSRui Paulo 	privacy = (res->caps & IEEE80211_CAP_PRIVACY) ? TRUE : FALSE;
4924d4f2939cSRui Paulo 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
4925d4f2939cSRui Paulo 						&privacy, error);
4926d4f2939cSRui Paulo }
4927d4f2939cSRui Paulo 
4928d4f2939cSRui Paulo 
4929d4f2939cSRui Paulo /**
4930d4f2939cSRui Paulo  * wpas_dbus_getter_bss_mode - Return the mode of a BSS
4931d4f2939cSRui Paulo  * @iter: Pointer to incoming dbus message iter
4932d4f2939cSRui Paulo  * @error: Location to store error on failure
4933d4f2939cSRui Paulo  * @user_data: Function specific data
4934d4f2939cSRui Paulo  * Returns: TRUE on success, FALSE on failure
4935d4f2939cSRui Paulo  *
4936d4f2939cSRui Paulo  * Getter for "Mode" property.
4937d4f2939cSRui Paulo  */
wpas_dbus_getter_bss_mode(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)4938780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_bss_mode(
4939780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
4940780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
4941d4f2939cSRui Paulo {
4942d4f2939cSRui Paulo 	struct bss_handler_args *args = user_data;
4943d4f2939cSRui Paulo 	struct wpa_bss *res;
4944d4f2939cSRui Paulo 	const char *mode;
494585732ac8SCy Schubert 	const u8 *mesh;
4946d4f2939cSRui Paulo 
4947d4f2939cSRui Paulo 	res = get_bss_helper(args, error, __func__);
4948d4f2939cSRui Paulo 	if (!res)
4949d4f2939cSRui Paulo 		return FALSE;
49505b9c547cSRui Paulo 	if (bss_is_dmg(res)) {
49515b9c547cSRui Paulo 		switch (res->caps & IEEE80211_CAP_DMG_MASK) {
49525b9c547cSRui Paulo 		case IEEE80211_CAP_DMG_PBSS:
49535b9c547cSRui Paulo 		case IEEE80211_CAP_DMG_IBSS:
49545b9c547cSRui Paulo 			mode = "ad-hoc";
49555b9c547cSRui Paulo 			break;
49565b9c547cSRui Paulo 		case IEEE80211_CAP_DMG_AP:
49575b9c547cSRui Paulo 			mode = "infrastructure";
49585b9c547cSRui Paulo 			break;
495985732ac8SCy Schubert 		default:
496085732ac8SCy Schubert 			mode = "";
496185732ac8SCy Schubert 			break;
49625b9c547cSRui Paulo 		}
49635b9c547cSRui Paulo 	} else {
496485732ac8SCy Schubert 		mesh = wpa_bss_get_ie(res, WLAN_EID_MESH_ID);
496585732ac8SCy Schubert 		if (mesh)
496685732ac8SCy Schubert 			mode = "mesh";
496785732ac8SCy Schubert 		else if (res->caps & IEEE80211_CAP_IBSS)
4968d4f2939cSRui Paulo 			mode = "ad-hoc";
4969d4f2939cSRui Paulo 		else
4970d4f2939cSRui Paulo 			mode = "infrastructure";
49715b9c547cSRui Paulo 	}
4972d4f2939cSRui Paulo 
4973d4f2939cSRui Paulo 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
4974d4f2939cSRui Paulo 						&mode, error);
4975d4f2939cSRui Paulo }
4976d4f2939cSRui Paulo 
4977d4f2939cSRui Paulo 
4978d4f2939cSRui Paulo /**
4979d4f2939cSRui Paulo  * wpas_dbus_getter_bss_level - Return the signal strength of a BSS
4980d4f2939cSRui Paulo  * @iter: Pointer to incoming dbus message iter
4981d4f2939cSRui Paulo  * @error: Location to store error on failure
4982d4f2939cSRui Paulo  * @user_data: Function specific data
4983d4f2939cSRui Paulo  * Returns: TRUE on success, FALSE on failure
4984d4f2939cSRui Paulo  *
4985d4f2939cSRui Paulo  * Getter for "Level" property.
4986d4f2939cSRui Paulo  */
wpas_dbus_getter_bss_signal(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)4987780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_bss_signal(
4988780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
4989780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
4990d4f2939cSRui Paulo {
4991d4f2939cSRui Paulo 	struct bss_handler_args *args = user_data;
4992d4f2939cSRui Paulo 	struct wpa_bss *res;
4993d4f2939cSRui Paulo 	s16 level;
4994d4f2939cSRui Paulo 
4995d4f2939cSRui Paulo 	res = get_bss_helper(args, error, __func__);
4996d4f2939cSRui Paulo 	if (!res)
4997d4f2939cSRui Paulo 		return FALSE;
4998d4f2939cSRui Paulo 
4999d4f2939cSRui Paulo 	level = (s16) res->level;
5000d4f2939cSRui Paulo 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT16,
5001d4f2939cSRui Paulo 						&level, error);
5002d4f2939cSRui Paulo }
5003d4f2939cSRui Paulo 
5004d4f2939cSRui Paulo 
5005d4f2939cSRui Paulo /**
5006d4f2939cSRui Paulo  * wpas_dbus_getter_bss_frequency - Return the frequency of a BSS
5007d4f2939cSRui Paulo  * @iter: Pointer to incoming dbus message iter
5008d4f2939cSRui Paulo  * @error: Location to store error on failure
5009d4f2939cSRui Paulo  * @user_data: Function specific data
5010d4f2939cSRui Paulo  * Returns: TRUE on success, FALSE on failure
5011d4f2939cSRui Paulo  *
5012d4f2939cSRui Paulo  * Getter for "Frequency" property.
5013d4f2939cSRui Paulo  */
wpas_dbus_getter_bss_frequency(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)5014780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_bss_frequency(
5015780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
5016780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
5017d4f2939cSRui Paulo {
5018d4f2939cSRui Paulo 	struct bss_handler_args *args = user_data;
5019d4f2939cSRui Paulo 	struct wpa_bss *res;
5020d4f2939cSRui Paulo 	u16 freq;
5021d4f2939cSRui Paulo 
5022d4f2939cSRui Paulo 	res = get_bss_helper(args, error, __func__);
5023d4f2939cSRui Paulo 	if (!res)
5024d4f2939cSRui Paulo 		return FALSE;
5025d4f2939cSRui Paulo 
5026d4f2939cSRui Paulo 	freq = (u16) res->freq;
5027d4f2939cSRui Paulo 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
5028d4f2939cSRui Paulo 						&freq, error);
5029d4f2939cSRui Paulo }
5030d4f2939cSRui Paulo 
5031d4f2939cSRui Paulo 
cmp_u8s_desc(const void * a,const void * b)5032d4f2939cSRui Paulo static int cmp_u8s_desc(const void *a, const void *b)
5033d4f2939cSRui Paulo {
5034d4f2939cSRui Paulo 	return (*(u8 *) b - *(u8 *) a);
5035d4f2939cSRui Paulo }
5036d4f2939cSRui Paulo 
5037d4f2939cSRui Paulo 
5038d4f2939cSRui Paulo /**
5039d4f2939cSRui Paulo  * wpas_dbus_getter_bss_rates - Return available bit rates of a BSS
5040d4f2939cSRui Paulo  * @iter: Pointer to incoming dbus message iter
5041d4f2939cSRui Paulo  * @error: Location to store error on failure
5042d4f2939cSRui Paulo  * @user_data: Function specific data
5043d4f2939cSRui Paulo  * Returns: TRUE on success, FALSE on failure
5044d4f2939cSRui Paulo  *
5045d4f2939cSRui Paulo  * Getter for "Rates" property.
5046d4f2939cSRui Paulo  */
wpas_dbus_getter_bss_rates(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)5047780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_bss_rates(
5048780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
5049780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
5050d4f2939cSRui Paulo {
5051d4f2939cSRui Paulo 	struct bss_handler_args *args = user_data;
5052d4f2939cSRui Paulo 	struct wpa_bss *res;
5053d4f2939cSRui Paulo 	u8 *ie_rates = NULL;
5054d4f2939cSRui Paulo 	u32 *real_rates;
5055d4f2939cSRui Paulo 	int rates_num, i;
5056d4f2939cSRui Paulo 	dbus_bool_t success = FALSE;
5057d4f2939cSRui Paulo 
5058d4f2939cSRui Paulo 	res = get_bss_helper(args, error, __func__);
5059d4f2939cSRui Paulo 	if (!res)
5060d4f2939cSRui Paulo 		return FALSE;
5061d4f2939cSRui Paulo 
5062d4f2939cSRui Paulo 	rates_num = wpa_bss_get_bit_rates(res, &ie_rates);
5063d4f2939cSRui Paulo 	if (rates_num < 0)
5064d4f2939cSRui Paulo 		return FALSE;
5065d4f2939cSRui Paulo 
5066d4f2939cSRui Paulo 	qsort(ie_rates, rates_num, 1, cmp_u8s_desc);
5067d4f2939cSRui Paulo 
5068d4f2939cSRui Paulo 	real_rates = os_malloc(sizeof(u32) * rates_num);
5069d4f2939cSRui Paulo 	if (!real_rates) {
5070d4f2939cSRui Paulo 		os_free(ie_rates);
5071d4f2939cSRui Paulo 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
5072d4f2939cSRui Paulo 		return FALSE;
5073d4f2939cSRui Paulo 	}
5074d4f2939cSRui Paulo 
5075d4f2939cSRui Paulo 	for (i = 0; i < rates_num; i++)
5076d4f2939cSRui Paulo 		real_rates[i] = ie_rates[i] * 500000;
5077d4f2939cSRui Paulo 
5078d4f2939cSRui Paulo 	success = wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_UINT32,
5079d4f2939cSRui Paulo 							 real_rates, rates_num,
5080d4f2939cSRui Paulo 							 error);
5081d4f2939cSRui Paulo 
5082d4f2939cSRui Paulo 	os_free(ie_rates);
5083d4f2939cSRui Paulo 	os_free(real_rates);
5084d4f2939cSRui Paulo 	return success;
5085d4f2939cSRui Paulo }
5086d4f2939cSRui Paulo 
5087d4f2939cSRui Paulo 
wpas_dbus_get_bss_security_prop(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,struct wpa_ie_data * ie_data,DBusError * error)5088780fb4a2SCy Schubert static dbus_bool_t wpas_dbus_get_bss_security_prop(
5089780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
5090780fb4a2SCy Schubert 	DBusMessageIter *iter, struct wpa_ie_data *ie_data, DBusError *error)
5091d4f2939cSRui Paulo {
5092d4f2939cSRui Paulo 	DBusMessageIter iter_dict, variant_iter;
5093d4f2939cSRui Paulo 	const char *group;
50945b9c547cSRui Paulo 	const char *pairwise[5]; /* max 5 pairwise ciphers is supported */
5095c1d255d3SCy Schubert 	const char *key_mgmt[16]; /* max 16 key managements may be supported */
5096d4f2939cSRui Paulo 	int n;
5097d4f2939cSRui Paulo 
5098d4f2939cSRui Paulo 	if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
5099d4f2939cSRui Paulo 					      "a{sv}", &variant_iter))
5100d4f2939cSRui Paulo 		goto nomem;
5101d4f2939cSRui Paulo 
5102d4f2939cSRui Paulo 	if (!wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
5103d4f2939cSRui Paulo 		goto nomem;
5104d4f2939cSRui Paulo 
51054bc52338SCy Schubert 	/*
51064bc52338SCy Schubert 	 * KeyMgmt
51074bc52338SCy Schubert 	 *
51084bc52338SCy Schubert 	 * When adding a new entry here, please take care to extend key_mgmt[]
51094bc52338SCy Schubert 	 * and keep documentation in doc/dbus.doxygen up to date.
51104bc52338SCy Schubert 	 */
5111d4f2939cSRui Paulo 	n = 0;
5112d4f2939cSRui Paulo 	if (ie_data->key_mgmt & WPA_KEY_MGMT_PSK)
5113d4f2939cSRui Paulo 		key_mgmt[n++] = "wpa-psk";
5114d4f2939cSRui Paulo 	if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_PSK)
5115d4f2939cSRui Paulo 		key_mgmt[n++] = "wpa-ft-psk";
5116d4f2939cSRui Paulo 	if (ie_data->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
5117d4f2939cSRui Paulo 		key_mgmt[n++] = "wpa-psk-sha256";
5118d4f2939cSRui Paulo 	if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X)
5119d4f2939cSRui Paulo 		key_mgmt[n++] = "wpa-eap";
5120d4f2939cSRui Paulo 	if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X)
5121d4f2939cSRui Paulo 		key_mgmt[n++] = "wpa-ft-eap";
5122d4f2939cSRui Paulo 	if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256)
5123d4f2939cSRui Paulo 		key_mgmt[n++] = "wpa-eap-sha256";
51245b9c547cSRui Paulo #ifdef CONFIG_SUITEB
51255b9c547cSRui Paulo 	if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B)
51265b9c547cSRui Paulo 		key_mgmt[n++] = "wpa-eap-suite-b";
51275b9c547cSRui Paulo #endif /* CONFIG_SUITEB */
51285b9c547cSRui Paulo #ifdef CONFIG_SUITEB192
51295b9c547cSRui Paulo 	if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
51305b9c547cSRui Paulo 		key_mgmt[n++] = "wpa-eap-suite-b-192";
51315b9c547cSRui Paulo #endif /* CONFIG_SUITEB192 */
513285732ac8SCy Schubert #ifdef CONFIG_FILS
513385732ac8SCy Schubert 	if (ie_data->key_mgmt & WPA_KEY_MGMT_FILS_SHA256)
513485732ac8SCy Schubert 		key_mgmt[n++] = "wpa-fils-sha256";
513585732ac8SCy Schubert 	if (ie_data->key_mgmt & WPA_KEY_MGMT_FILS_SHA384)
513685732ac8SCy Schubert 		key_mgmt[n++] = "wpa-fils-sha384";
513785732ac8SCy Schubert 	if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA256)
513885732ac8SCy Schubert 		key_mgmt[n++] = "wpa-ft-fils-sha256";
513985732ac8SCy Schubert 	if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA384)
514085732ac8SCy Schubert 		key_mgmt[n++] = "wpa-ft-fils-sha384";
514185732ac8SCy Schubert #endif /* CONFIG_FILS */
51424bc52338SCy Schubert #ifdef CONFIG_SAE
51434bc52338SCy Schubert 	if (ie_data->key_mgmt & WPA_KEY_MGMT_SAE)
51444bc52338SCy Schubert 		key_mgmt[n++] = "sae";
51454bc52338SCy Schubert 	if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_SAE)
51464bc52338SCy Schubert 		key_mgmt[n++] = "ft-sae";
51474bc52338SCy Schubert #endif /* CONFIG_SAE */
5148c1d255d3SCy Schubert #ifdef CONFIG_OWE
5149c1d255d3SCy Schubert 	if (ie_data->key_mgmt & WPA_KEY_MGMT_OWE)
5150c1d255d3SCy Schubert 		key_mgmt[n++] = "owe";
5151c1d255d3SCy Schubert #endif /* CONFIG_OWE */
5152d4f2939cSRui Paulo 	if (ie_data->key_mgmt & WPA_KEY_MGMT_NONE)
5153d4f2939cSRui Paulo 		key_mgmt[n++] = "wpa-none";
5154d4f2939cSRui Paulo 
5155d4f2939cSRui Paulo 	if (!wpa_dbus_dict_append_string_array(&iter_dict, "KeyMgmt",
5156d4f2939cSRui Paulo 					       key_mgmt, n))
5157d4f2939cSRui Paulo 		goto nomem;
5158d4f2939cSRui Paulo 
5159d4f2939cSRui Paulo 	/* Group */
5160d4f2939cSRui Paulo 	switch (ie_data->group_cipher) {
5161c1d255d3SCy Schubert #ifdef CONFIG_WEP
5162d4f2939cSRui Paulo 	case WPA_CIPHER_WEP40:
5163d4f2939cSRui Paulo 		group = "wep40";
5164d4f2939cSRui Paulo 		break;
5165c1d255d3SCy Schubert 	case WPA_CIPHER_WEP104:
5166c1d255d3SCy Schubert 		group = "wep104";
5167c1d255d3SCy Schubert 		break;
5168c1d255d3SCy Schubert #endif /* CONFIG_WEP */
5169c1d255d3SCy Schubert #ifndef CONFIG_NO_TKIP
5170d4f2939cSRui Paulo 	case WPA_CIPHER_TKIP:
5171d4f2939cSRui Paulo 		group = "tkip";
5172d4f2939cSRui Paulo 		break;
5173c1d255d3SCy Schubert #endif /* CONFIG_NO_TKIP */
5174d4f2939cSRui Paulo 	case WPA_CIPHER_CCMP:
5175d4f2939cSRui Paulo 		group = "ccmp";
5176d4f2939cSRui Paulo 		break;
5177d4f2939cSRui Paulo 	case WPA_CIPHER_GCMP:
5178d4f2939cSRui Paulo 		group = "gcmp";
5179d4f2939cSRui Paulo 		break;
51805b9c547cSRui Paulo 	case WPA_CIPHER_CCMP_256:
51815b9c547cSRui Paulo 		group = "ccmp-256";
51825b9c547cSRui Paulo 		break;
51835b9c547cSRui Paulo 	case WPA_CIPHER_GCMP_256:
51845b9c547cSRui Paulo 		group = "gcmp-256";
51855b9c547cSRui Paulo 		break;
5186d4f2939cSRui Paulo 	default:
5187d4f2939cSRui Paulo 		group = "";
5188d4f2939cSRui Paulo 		break;
5189d4f2939cSRui Paulo 	}
5190d4f2939cSRui Paulo 
5191d4f2939cSRui Paulo 	if (!wpa_dbus_dict_append_string(&iter_dict, "Group", group))
5192d4f2939cSRui Paulo 		goto nomem;
5193d4f2939cSRui Paulo 
5194d4f2939cSRui Paulo 	/* Pairwise */
5195d4f2939cSRui Paulo 	n = 0;
5196c1d255d3SCy Schubert #ifndef CONFIG_NO_TKIP
5197d4f2939cSRui Paulo 	if (ie_data->pairwise_cipher & WPA_CIPHER_TKIP)
5198d4f2939cSRui Paulo 		pairwise[n++] = "tkip";
5199c1d255d3SCy Schubert #endif /* CONFIG_NO_TKIP */
5200d4f2939cSRui Paulo 	if (ie_data->pairwise_cipher & WPA_CIPHER_CCMP)
5201d4f2939cSRui Paulo 		pairwise[n++] = "ccmp";
5202d4f2939cSRui Paulo 	if (ie_data->pairwise_cipher & WPA_CIPHER_GCMP)
5203d4f2939cSRui Paulo 		pairwise[n++] = "gcmp";
52045b9c547cSRui Paulo 	if (ie_data->pairwise_cipher & WPA_CIPHER_CCMP_256)
52055b9c547cSRui Paulo 		pairwise[n++] = "ccmp-256";
52065b9c547cSRui Paulo 	if (ie_data->pairwise_cipher & WPA_CIPHER_GCMP_256)
52075b9c547cSRui Paulo 		pairwise[n++] = "gcmp-256";
5208d4f2939cSRui Paulo 
5209d4f2939cSRui Paulo 	if (!wpa_dbus_dict_append_string_array(&iter_dict, "Pairwise",
5210d4f2939cSRui Paulo 					       pairwise, n))
5211d4f2939cSRui Paulo 		goto nomem;
5212d4f2939cSRui Paulo 
5213d4f2939cSRui Paulo 	/* Management group (RSN only) */
5214d4f2939cSRui Paulo 	if (ie_data->proto == WPA_PROTO_RSN) {
5215d4f2939cSRui Paulo 		switch (ie_data->mgmt_group_cipher) {
5216d4f2939cSRui Paulo 		case WPA_CIPHER_AES_128_CMAC:
5217d4f2939cSRui Paulo 			group = "aes128cmac";
5218d4f2939cSRui Paulo 			break;
5219d4f2939cSRui Paulo 		default:
5220d4f2939cSRui Paulo 			group = "";
5221d4f2939cSRui Paulo 			break;
5222d4f2939cSRui Paulo 		}
5223d4f2939cSRui Paulo 
5224d4f2939cSRui Paulo 		if (!wpa_dbus_dict_append_string(&iter_dict, "MgmtGroup",
5225d4f2939cSRui Paulo 						 group))
5226d4f2939cSRui Paulo 			goto nomem;
5227d4f2939cSRui Paulo 	}
5228d4f2939cSRui Paulo 
52295b9c547cSRui Paulo 	if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict) ||
52305b9c547cSRui Paulo 	    !dbus_message_iter_close_container(iter, &variant_iter))
5231d4f2939cSRui Paulo 		goto nomem;
5232d4f2939cSRui Paulo 
5233d4f2939cSRui Paulo 	return TRUE;
5234d4f2939cSRui Paulo 
5235d4f2939cSRui Paulo nomem:
5236d4f2939cSRui Paulo 	dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
5237d4f2939cSRui Paulo 	return FALSE;
5238d4f2939cSRui Paulo }
5239d4f2939cSRui Paulo 
5240d4f2939cSRui Paulo 
5241d4f2939cSRui Paulo /**
5242d4f2939cSRui Paulo  * wpas_dbus_getter_bss_wpa - Return the WPA options of a BSS
5243d4f2939cSRui Paulo  * @iter: Pointer to incoming dbus message iter
5244d4f2939cSRui Paulo  * @error: Location to store error on failure
5245d4f2939cSRui Paulo  * @user_data: Function specific data
5246d4f2939cSRui Paulo  * Returns: TRUE on success, FALSE on failure
5247d4f2939cSRui Paulo  *
5248d4f2939cSRui Paulo  * Getter for "WPA" property.
5249d4f2939cSRui Paulo  */
wpas_dbus_getter_bss_wpa(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)5250780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_bss_wpa(
5251780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
5252780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
5253d4f2939cSRui Paulo {
5254d4f2939cSRui Paulo 	struct bss_handler_args *args = user_data;
5255d4f2939cSRui Paulo 	struct wpa_bss *res;
5256d4f2939cSRui Paulo 	struct wpa_ie_data wpa_data;
5257d4f2939cSRui Paulo 	const u8 *ie;
5258d4f2939cSRui Paulo 
5259d4f2939cSRui Paulo 	res = get_bss_helper(args, error, __func__);
5260d4f2939cSRui Paulo 	if (!res)
5261d4f2939cSRui Paulo 		return FALSE;
5262d4f2939cSRui Paulo 
5263d4f2939cSRui Paulo 	os_memset(&wpa_data, 0, sizeof(wpa_data));
5264d4f2939cSRui Paulo 	ie = wpa_bss_get_vendor_ie(res, WPA_IE_VENDOR_TYPE);
52655b9c547cSRui Paulo 	if (ie && wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0) {
5266d4f2939cSRui Paulo 		dbus_set_error_const(error, DBUS_ERROR_FAILED,
5267d4f2939cSRui Paulo 				     "failed to parse WPA IE");
5268d4f2939cSRui Paulo 		return FALSE;
5269d4f2939cSRui Paulo 	}
5270d4f2939cSRui Paulo 
5271780fb4a2SCy Schubert 	return wpas_dbus_get_bss_security_prop(property_desc, iter, &wpa_data, error);
5272d4f2939cSRui Paulo }
5273d4f2939cSRui Paulo 
5274d4f2939cSRui Paulo 
5275d4f2939cSRui Paulo /**
5276d4f2939cSRui Paulo  * wpas_dbus_getter_bss_rsn - Return the RSN options of a BSS
5277d4f2939cSRui Paulo  * @iter: Pointer to incoming dbus message iter
5278d4f2939cSRui Paulo  * @error: Location to store error on failure
5279d4f2939cSRui Paulo  * @user_data: Function specific data
5280d4f2939cSRui Paulo  * Returns: TRUE on success, FALSE on failure
5281d4f2939cSRui Paulo  *
5282d4f2939cSRui Paulo  * Getter for "RSN" property.
5283d4f2939cSRui Paulo  */
wpas_dbus_getter_bss_rsn(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)5284780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_bss_rsn(
5285780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
5286780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
5287d4f2939cSRui Paulo {
5288d4f2939cSRui Paulo 	struct bss_handler_args *args = user_data;
5289d4f2939cSRui Paulo 	struct wpa_bss *res;
5290d4f2939cSRui Paulo 	struct wpa_ie_data wpa_data;
5291d4f2939cSRui Paulo 	const u8 *ie;
5292d4f2939cSRui Paulo 
5293d4f2939cSRui Paulo 	res = get_bss_helper(args, error, __func__);
5294d4f2939cSRui Paulo 	if (!res)
5295d4f2939cSRui Paulo 		return FALSE;
5296d4f2939cSRui Paulo 
5297d4f2939cSRui Paulo 	os_memset(&wpa_data, 0, sizeof(wpa_data));
5298d4f2939cSRui Paulo 	ie = wpa_bss_get_ie(res, WLAN_EID_RSN);
52995b9c547cSRui Paulo 	if (ie && wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0) {
5300d4f2939cSRui Paulo 		dbus_set_error_const(error, DBUS_ERROR_FAILED,
5301d4f2939cSRui Paulo 				     "failed to parse RSN IE");
5302d4f2939cSRui Paulo 		return FALSE;
5303d4f2939cSRui Paulo 	}
5304d4f2939cSRui Paulo 
5305780fb4a2SCy Schubert 	return wpas_dbus_get_bss_security_prop(property_desc, iter, &wpa_data, error);
5306d4f2939cSRui Paulo }
5307d4f2939cSRui Paulo 
5308d4f2939cSRui Paulo 
5309d4f2939cSRui Paulo /**
5310d4f2939cSRui Paulo  * wpas_dbus_getter_bss_wps - Return the WPS options of a BSS
5311d4f2939cSRui Paulo  * @iter: Pointer to incoming dbus message iter
5312d4f2939cSRui Paulo  * @error: Location to store error on failure
5313d4f2939cSRui Paulo  * @user_data: Function specific data
5314d4f2939cSRui Paulo  * Returns: TRUE on success, FALSE on failure
5315d4f2939cSRui Paulo  *
5316d4f2939cSRui Paulo  * Getter for "WPS" property.
5317d4f2939cSRui Paulo  */
wpas_dbus_getter_bss_wps(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)5318780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_bss_wps(
5319780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
5320780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
5321d4f2939cSRui Paulo {
5322d4f2939cSRui Paulo 	struct bss_handler_args *args = user_data;
5323d4f2939cSRui Paulo 	struct wpa_bss *res;
5324d4f2939cSRui Paulo #ifdef CONFIG_WPS
5325d4f2939cSRui Paulo 	struct wpabuf *wps_ie;
5326d4f2939cSRui Paulo #endif /* CONFIG_WPS */
5327d4f2939cSRui Paulo 	DBusMessageIter iter_dict, variant_iter;
5328325151a3SRui Paulo 	int wps_support = 0;
5329d4f2939cSRui Paulo 	const char *type = "";
5330d4f2939cSRui Paulo 
5331d4f2939cSRui Paulo 	res = get_bss_helper(args, error, __func__);
5332d4f2939cSRui Paulo 	if (!res)
5333d4f2939cSRui Paulo 		return FALSE;
5334d4f2939cSRui Paulo 
5335d4f2939cSRui Paulo 	if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
53365b9c547cSRui Paulo 					      "a{sv}", &variant_iter) ||
53375b9c547cSRui Paulo 	    !wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
5338d4f2939cSRui Paulo 		goto nomem;
5339d4f2939cSRui Paulo 
5340d4f2939cSRui Paulo #ifdef CONFIG_WPS
5341d4f2939cSRui Paulo 	wps_ie = wpa_bss_get_vendor_ie_multi(res, WPS_IE_VENDOR_TYPE);
5342d4f2939cSRui Paulo 	if (wps_ie) {
5343325151a3SRui Paulo 		wps_support = 1;
5344d4f2939cSRui Paulo 		if (wps_is_selected_pbc_registrar(wps_ie))
5345d4f2939cSRui Paulo 			type = "pbc";
5346d4f2939cSRui Paulo 		else if (wps_is_selected_pin_registrar(wps_ie))
5347d4f2939cSRui Paulo 			type = "pin";
53485b9c547cSRui Paulo 
53495b9c547cSRui Paulo 		wpabuf_free(wps_ie);
5350d4f2939cSRui Paulo 	}
5351d4f2939cSRui Paulo #endif /* CONFIG_WPS */
5352d4f2939cSRui Paulo 
5353325151a3SRui Paulo 	if ((wps_support && !wpa_dbus_dict_append_string(&iter_dict, "Type", type)) ||
53545b9c547cSRui Paulo 	    !wpa_dbus_dict_close_write(&variant_iter, &iter_dict) ||
53555b9c547cSRui Paulo 	    !dbus_message_iter_close_container(iter, &variant_iter))
5356d4f2939cSRui Paulo 		goto nomem;
5357d4f2939cSRui Paulo 
5358d4f2939cSRui Paulo 	return TRUE;
5359d4f2939cSRui Paulo 
5360d4f2939cSRui Paulo nomem:
5361d4f2939cSRui Paulo 	dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
5362d4f2939cSRui Paulo 	return FALSE;
5363d4f2939cSRui Paulo }
5364d4f2939cSRui Paulo 
5365d4f2939cSRui Paulo 
5366d4f2939cSRui Paulo /**
5367d4f2939cSRui Paulo  * wpas_dbus_getter_bss_ies - Return all IEs of a BSS
5368d4f2939cSRui Paulo  * @iter: Pointer to incoming dbus message iter
5369d4f2939cSRui Paulo  * @error: Location to store error on failure
5370d4f2939cSRui Paulo  * @user_data: Function specific data
5371d4f2939cSRui Paulo  * Returns: TRUE on success, FALSE on failure
5372d4f2939cSRui Paulo  *
5373d4f2939cSRui Paulo  * Getter for "IEs" property.
5374d4f2939cSRui Paulo  */
wpas_dbus_getter_bss_ies(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)5375780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_bss_ies(
5376780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
5377780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
5378d4f2939cSRui Paulo {
5379d4f2939cSRui Paulo 	struct bss_handler_args *args = user_data;
5380d4f2939cSRui Paulo 	struct wpa_bss *res;
5381d4f2939cSRui Paulo 
5382d4f2939cSRui Paulo 	res = get_bss_helper(args, error, __func__);
5383d4f2939cSRui Paulo 	if (!res)
5384d4f2939cSRui Paulo 		return FALSE;
5385d4f2939cSRui Paulo 
5386d4f2939cSRui Paulo 	return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
5387c1d255d3SCy Schubert 						      wpa_bss_ie_ptr(res),
5388c1d255d3SCy Schubert 						      res->ie_len, error);
5389d4f2939cSRui Paulo }
5390d4f2939cSRui Paulo 
5391d4f2939cSRui Paulo 
5392d4f2939cSRui Paulo /**
53935b9c547cSRui Paulo  * wpas_dbus_getter_bss_age - Return time in seconds since BSS was last seen
53945b9c547cSRui Paulo  * @iter: Pointer to incoming dbus message iter
53955b9c547cSRui Paulo  * @error: Location to store error on failure
53965b9c547cSRui Paulo  * @user_data: Function specific data
53975b9c547cSRui Paulo  * Returns: TRUE on success, FALSE on failure
53985b9c547cSRui Paulo  *
53995b9c547cSRui Paulo  * Getter for BSS age
54005b9c547cSRui Paulo  */
wpas_dbus_getter_bss_age(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)5401780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_bss_age(
5402780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
5403780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
54045b9c547cSRui Paulo {
54055b9c547cSRui Paulo 	struct bss_handler_args *args = user_data;
54065b9c547cSRui Paulo 	struct wpa_bss *res;
54075b9c547cSRui Paulo 	struct os_reltime now, diff = { 0, 0 };
54085b9c547cSRui Paulo 	u32 age;
54095b9c547cSRui Paulo 
54105b9c547cSRui Paulo 	res = get_bss_helper(args, error, __func__);
54115b9c547cSRui Paulo 	if (!res)
54125b9c547cSRui Paulo 		return FALSE;
54135b9c547cSRui Paulo 
54145b9c547cSRui Paulo 	os_get_reltime(&now);
54155b9c547cSRui Paulo 	os_reltime_sub(&now, &res->last_update, &diff);
54165b9c547cSRui Paulo 	age = diff.sec > 0 ? diff.sec : 0;
54175b9c547cSRui Paulo 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32, &age,
54185b9c547cSRui Paulo 						error);
54195b9c547cSRui Paulo }
54205b9c547cSRui Paulo 
54215b9c547cSRui Paulo 
54225b9c547cSRui Paulo /**
5423d4f2939cSRui Paulo  * wpas_dbus_getter_enabled - Check whether network is enabled or disabled
5424d4f2939cSRui Paulo  * @iter: Pointer to incoming dbus message iter
5425d4f2939cSRui Paulo  * @error: Location to store error on failure
5426d4f2939cSRui Paulo  * @user_data: Function specific data
5427d4f2939cSRui Paulo  * Returns: TRUE on success, FALSE on failure
5428d4f2939cSRui Paulo  *
5429d4f2939cSRui Paulo  * Getter for "enabled" property of a configured network.
5430d4f2939cSRui Paulo  */
wpas_dbus_getter_enabled(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)5431780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_enabled(
5432780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
5433780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
5434d4f2939cSRui Paulo {
5435d4f2939cSRui Paulo 	struct network_handler_args *net = user_data;
5436d4f2939cSRui Paulo 	dbus_bool_t enabled = net->ssid->disabled ? FALSE : TRUE;
5437d4f2939cSRui Paulo 
5438d4f2939cSRui Paulo 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
5439d4f2939cSRui Paulo 						&enabled, error);
5440d4f2939cSRui Paulo }
5441d4f2939cSRui Paulo 
5442d4f2939cSRui Paulo 
5443d4f2939cSRui Paulo /**
5444d4f2939cSRui Paulo  * wpas_dbus_setter_enabled - Mark a configured network as enabled or disabled
5445d4f2939cSRui Paulo  * @iter: Pointer to incoming dbus message iter
5446d4f2939cSRui Paulo  * @error: Location to store error on failure
5447d4f2939cSRui Paulo  * @user_data: Function specific data
5448d4f2939cSRui Paulo  * Returns: TRUE on success, FALSE on failure
5449d4f2939cSRui Paulo  *
5450d4f2939cSRui Paulo  * Setter for "Enabled" property of a configured network.
5451d4f2939cSRui Paulo  */
wpas_dbus_setter_enabled(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)5452780fb4a2SCy Schubert dbus_bool_t wpas_dbus_setter_enabled(
5453780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
5454780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
5455d4f2939cSRui Paulo {
5456d4f2939cSRui Paulo 	struct network_handler_args *net = user_data;
5457d4f2939cSRui Paulo 	struct wpa_supplicant *wpa_s;
5458d4f2939cSRui Paulo 	struct wpa_ssid *ssid;
5459d4f2939cSRui Paulo 	dbus_bool_t enable;
5460d4f2939cSRui Paulo 
5461d4f2939cSRui Paulo 	if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
5462d4f2939cSRui Paulo 					      &enable))
5463d4f2939cSRui Paulo 		return FALSE;
5464d4f2939cSRui Paulo 
5465d4f2939cSRui Paulo 	wpa_s = net->wpa_s;
5466d4f2939cSRui Paulo 	ssid = net->ssid;
5467d4f2939cSRui Paulo 
5468d4f2939cSRui Paulo 	if (enable)
5469d4f2939cSRui Paulo 		wpa_supplicant_enable_network(wpa_s, ssid);
5470d4f2939cSRui Paulo 	else
5471d4f2939cSRui Paulo 		wpa_supplicant_disable_network(wpa_s, ssid);
5472d4f2939cSRui Paulo 
5473d4f2939cSRui Paulo 	return TRUE;
5474d4f2939cSRui Paulo }
5475d4f2939cSRui Paulo 
5476d4f2939cSRui Paulo 
5477d4f2939cSRui Paulo /**
5478d4f2939cSRui Paulo  * wpas_dbus_getter_network_properties - Get options for a configured network
5479d4f2939cSRui Paulo  * @iter: Pointer to incoming dbus message iter
5480d4f2939cSRui Paulo  * @error: Location to store error on failure
5481d4f2939cSRui Paulo  * @user_data: Function specific data
5482d4f2939cSRui Paulo  * Returns: TRUE on success, FALSE on failure
5483d4f2939cSRui Paulo  *
5484d4f2939cSRui Paulo  * Getter for "Properties" property of a configured network.
5485d4f2939cSRui Paulo  */
wpas_dbus_getter_network_properties(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)5486780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_network_properties(
5487780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
5488780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
5489d4f2939cSRui Paulo {
5490d4f2939cSRui Paulo 	struct network_handler_args *net = user_data;
5491d4f2939cSRui Paulo 	DBusMessageIter	variant_iter, dict_iter;
5492d4f2939cSRui Paulo 	char **iterator;
5493d4f2939cSRui Paulo 	char **props = wpa_config_get_all(net->ssid, 1);
5494d4f2939cSRui Paulo 	dbus_bool_t success = FALSE;
5495d4f2939cSRui Paulo 
5496d4f2939cSRui Paulo 	if (!props) {
5497d4f2939cSRui Paulo 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
5498d4f2939cSRui Paulo 		return FALSE;
5499d4f2939cSRui Paulo 	}
5500d4f2939cSRui Paulo 
5501d4f2939cSRui Paulo 	if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a{sv}",
5502d4f2939cSRui Paulo 					      &variant_iter) ||
5503d4f2939cSRui Paulo 	    !wpa_dbus_dict_open_write(&variant_iter, &dict_iter)) {
5504d4f2939cSRui Paulo 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
5505d4f2939cSRui Paulo 		goto out;
5506d4f2939cSRui Paulo 	}
5507d4f2939cSRui Paulo 
5508d4f2939cSRui Paulo 	iterator = props;
5509d4f2939cSRui Paulo 	while (*iterator) {
5510d4f2939cSRui Paulo 		if (!wpa_dbus_dict_append_string(&dict_iter, *iterator,
5511d4f2939cSRui Paulo 						 *(iterator + 1))) {
5512d4f2939cSRui Paulo 			dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
5513d4f2939cSRui Paulo 					     "no memory");
5514d4f2939cSRui Paulo 			goto out;
5515d4f2939cSRui Paulo 		}
5516d4f2939cSRui Paulo 		iterator += 2;
5517d4f2939cSRui Paulo 	}
5518d4f2939cSRui Paulo 
5519d4f2939cSRui Paulo 
5520d4f2939cSRui Paulo 	if (!wpa_dbus_dict_close_write(&variant_iter, &dict_iter) ||
5521d4f2939cSRui Paulo 	    !dbus_message_iter_close_container(iter, &variant_iter)) {
5522d4f2939cSRui Paulo 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
5523d4f2939cSRui Paulo 		goto out;
5524d4f2939cSRui Paulo 	}
5525d4f2939cSRui Paulo 
5526d4f2939cSRui Paulo 	success = TRUE;
5527d4f2939cSRui Paulo 
5528d4f2939cSRui Paulo out:
5529d4f2939cSRui Paulo 	iterator = props;
5530d4f2939cSRui Paulo 	while (*iterator) {
5531d4f2939cSRui Paulo 		os_free(*iterator);
5532d4f2939cSRui Paulo 		iterator++;
5533d4f2939cSRui Paulo 	}
5534d4f2939cSRui Paulo 	os_free(props);
5535d4f2939cSRui Paulo 	return success;
5536d4f2939cSRui Paulo }
5537d4f2939cSRui Paulo 
5538d4f2939cSRui Paulo 
5539d4f2939cSRui Paulo /**
5540d4f2939cSRui Paulo  * wpas_dbus_setter_network_properties - Set options for a configured network
5541d4f2939cSRui Paulo  * @iter: Pointer to incoming dbus message iter
5542d4f2939cSRui Paulo  * @error: Location to store error on failure
5543d4f2939cSRui Paulo  * @user_data: Function specific data
5544d4f2939cSRui Paulo  * Returns: TRUE on success, FALSE on failure
5545d4f2939cSRui Paulo  *
5546d4f2939cSRui Paulo  * Setter for "Properties" property of a configured network.
5547d4f2939cSRui Paulo  */
wpas_dbus_setter_network_properties(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)5548780fb4a2SCy Schubert dbus_bool_t wpas_dbus_setter_network_properties(
5549780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
5550780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
5551d4f2939cSRui Paulo {
5552d4f2939cSRui Paulo 	struct network_handler_args *net = user_data;
5553d4f2939cSRui Paulo 	struct wpa_ssid *ssid = net->ssid;
5554d4f2939cSRui Paulo 	DBusMessageIter	variant_iter;
5555d4f2939cSRui Paulo 
5556d4f2939cSRui Paulo 	dbus_message_iter_recurse(iter, &variant_iter);
5557d4f2939cSRui Paulo 	return set_network_properties(net->wpa_s, ssid, &variant_iter, error);
5558d4f2939cSRui Paulo }
5559d4f2939cSRui Paulo 
5560d4f2939cSRui Paulo 
5561d4f2939cSRui Paulo #ifdef CONFIG_AP
5562d4f2939cSRui Paulo 
wpas_dbus_handler_subscribe_preq(DBusMessage * message,struct wpa_supplicant * wpa_s)5563d4f2939cSRui Paulo DBusMessage * wpas_dbus_handler_subscribe_preq(
5564d4f2939cSRui Paulo 	DBusMessage *message, struct wpa_supplicant *wpa_s)
5565d4f2939cSRui Paulo {
5566d4f2939cSRui Paulo 	struct wpas_dbus_priv *priv = wpa_s->global->dbus;
5567d4f2939cSRui Paulo 	char *name;
5568d4f2939cSRui Paulo 
5569d4f2939cSRui Paulo 	if (wpa_s->preq_notify_peer != NULL) {
5570d4f2939cSRui Paulo 		if (os_strcmp(dbus_message_get_sender(message),
5571d4f2939cSRui Paulo 			      wpa_s->preq_notify_peer) == 0)
5572d4f2939cSRui Paulo 			return NULL;
5573d4f2939cSRui Paulo 
5574d4f2939cSRui Paulo 		return dbus_message_new_error(message,
5575d4f2939cSRui Paulo 			WPAS_DBUS_ERROR_SUBSCRIPTION_IN_USE,
5576d4f2939cSRui Paulo 			"Another application is already subscribed");
5577d4f2939cSRui Paulo 	}
5578d4f2939cSRui Paulo 
5579d4f2939cSRui Paulo 	name = os_strdup(dbus_message_get_sender(message));
5580d4f2939cSRui Paulo 	if (!name)
55815b9c547cSRui Paulo 		return wpas_dbus_error_no_memory(message);
5582d4f2939cSRui Paulo 
5583d4f2939cSRui Paulo 	wpa_s->preq_notify_peer = name;
5584d4f2939cSRui Paulo 
5585d4f2939cSRui Paulo 	/* Subscribe to clean up if application closes socket */
5586d4f2939cSRui Paulo 	wpas_dbus_subscribe_noc(priv);
5587d4f2939cSRui Paulo 
5588d4f2939cSRui Paulo 	/*
5589d4f2939cSRui Paulo 	 * Double-check it's still alive to make sure that we didn't
5590d4f2939cSRui Paulo 	 * miss the NameOwnerChanged signal, e.g. while strdup'ing.
5591d4f2939cSRui Paulo 	 */
5592d4f2939cSRui Paulo 	if (!dbus_bus_name_has_owner(priv->con, name, NULL)) {
5593d4f2939cSRui Paulo 		/*
5594d4f2939cSRui Paulo 		 * Application no longer exists, clean up.
5595d4f2939cSRui Paulo 		 * The return value is irrelevant now.
5596d4f2939cSRui Paulo 		 *
5597d4f2939cSRui Paulo 		 * Need to check if the NameOwnerChanged handling
5598d4f2939cSRui Paulo 		 * already cleaned up because we have processed
5599d4f2939cSRui Paulo 		 * DBus messages while checking if the name still
5600d4f2939cSRui Paulo 		 * has an owner.
5601d4f2939cSRui Paulo 		 */
5602d4f2939cSRui Paulo 		if (!wpa_s->preq_notify_peer)
5603d4f2939cSRui Paulo 			return NULL;
5604d4f2939cSRui Paulo 		os_free(wpa_s->preq_notify_peer);
5605d4f2939cSRui Paulo 		wpa_s->preq_notify_peer = NULL;
5606d4f2939cSRui Paulo 		wpas_dbus_unsubscribe_noc(priv);
5607d4f2939cSRui Paulo 	}
5608d4f2939cSRui Paulo 
5609d4f2939cSRui Paulo 	return NULL;
5610d4f2939cSRui Paulo }
5611d4f2939cSRui Paulo 
5612d4f2939cSRui Paulo 
wpas_dbus_handler_unsubscribe_preq(DBusMessage * message,struct wpa_supplicant * wpa_s)5613d4f2939cSRui Paulo DBusMessage * wpas_dbus_handler_unsubscribe_preq(
5614d4f2939cSRui Paulo 	DBusMessage *message, struct wpa_supplicant *wpa_s)
5615d4f2939cSRui Paulo {
5616d4f2939cSRui Paulo 	struct wpas_dbus_priv *priv = wpa_s->global->dbus;
5617d4f2939cSRui Paulo 
5618d4f2939cSRui Paulo 	if (!wpa_s->preq_notify_peer)
5619d4f2939cSRui Paulo 		return dbus_message_new_error(message,
5620d4f2939cSRui Paulo 			WPAS_DBUS_ERROR_NO_SUBSCRIPTION,
5621d4f2939cSRui Paulo 			"Not subscribed");
5622d4f2939cSRui Paulo 
5623d4f2939cSRui Paulo 	if (os_strcmp(wpa_s->preq_notify_peer,
5624d4f2939cSRui Paulo 		      dbus_message_get_sender(message)))
5625d4f2939cSRui Paulo 		return dbus_message_new_error(message,
5626d4f2939cSRui Paulo 			WPAS_DBUS_ERROR_SUBSCRIPTION_EPERM,
5627d4f2939cSRui Paulo 			"Can't unsubscribe others");
5628d4f2939cSRui Paulo 
5629d4f2939cSRui Paulo 	os_free(wpa_s->preq_notify_peer);
5630d4f2939cSRui Paulo 	wpa_s->preq_notify_peer = NULL;
5631d4f2939cSRui Paulo 	wpas_dbus_unsubscribe_noc(priv);
5632d4f2939cSRui Paulo 	return NULL;
5633d4f2939cSRui Paulo }
5634d4f2939cSRui Paulo 
5635d4f2939cSRui Paulo 
wpas_dbus_signal_preq(struct wpa_supplicant * wpa_s,const u8 * addr,const u8 * dst,const u8 * bssid,const u8 * ie,size_t ie_len,u32 ssi_signal)5636d4f2939cSRui Paulo void wpas_dbus_signal_preq(struct wpa_supplicant *wpa_s,
5637d4f2939cSRui Paulo 			   const u8 *addr, const u8 *dst, const u8 *bssid,
5638d4f2939cSRui Paulo 			   const u8 *ie, size_t ie_len, u32 ssi_signal)
5639d4f2939cSRui Paulo {
5640d4f2939cSRui Paulo 	DBusMessage *msg;
5641d4f2939cSRui Paulo 	DBusMessageIter iter, dict_iter;
5642d4f2939cSRui Paulo 	struct wpas_dbus_priv *priv = wpa_s->global->dbus;
5643d4f2939cSRui Paulo 
5644d4f2939cSRui Paulo 	/* Do nothing if the control interface is not turned on */
5645325151a3SRui Paulo 	if (priv == NULL || !wpa_s->dbus_new_path)
5646d4f2939cSRui Paulo 		return;
5647d4f2939cSRui Paulo 
5648d4f2939cSRui Paulo 	if (wpa_s->preq_notify_peer == NULL)
5649d4f2939cSRui Paulo 		return;
5650d4f2939cSRui Paulo 
5651d4f2939cSRui Paulo 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
5652d4f2939cSRui Paulo 				      WPAS_DBUS_NEW_IFACE_INTERFACE,
5653d4f2939cSRui Paulo 				      "ProbeRequest");
5654d4f2939cSRui Paulo 	if (msg == NULL)
5655d4f2939cSRui Paulo 		return;
5656d4f2939cSRui Paulo 
5657d4f2939cSRui Paulo 	dbus_message_set_destination(msg, wpa_s->preq_notify_peer);
5658d4f2939cSRui Paulo 
5659d4f2939cSRui Paulo 	dbus_message_iter_init_append(msg, &iter);
5660d4f2939cSRui Paulo 
56615b9c547cSRui Paulo 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
56625b9c547cSRui Paulo 	    (addr && !wpa_dbus_dict_append_byte_array(&dict_iter, "addr",
5663d4f2939cSRui Paulo 						      (const char *) addr,
56645b9c547cSRui Paulo 						      ETH_ALEN)) ||
56655b9c547cSRui Paulo 	    (dst && !wpa_dbus_dict_append_byte_array(&dict_iter, "dst",
5666d4f2939cSRui Paulo 						     (const char *) dst,
56675b9c547cSRui Paulo 						     ETH_ALEN)) ||
56685b9c547cSRui Paulo 	    (bssid && !wpa_dbus_dict_append_byte_array(&dict_iter, "bssid",
5669d4f2939cSRui Paulo 						       (const char *) bssid,
56705b9c547cSRui Paulo 						       ETH_ALEN)) ||
56715b9c547cSRui Paulo 	    (ie && ie_len && !wpa_dbus_dict_append_byte_array(&dict_iter, "ies",
5672d4f2939cSRui Paulo 							      (const char *) ie,
56735b9c547cSRui Paulo 							      ie_len)) ||
56745b9c547cSRui Paulo 	    (ssi_signal && !wpa_dbus_dict_append_int32(&dict_iter, "signal",
56755b9c547cSRui Paulo 						       ssi_signal)) ||
56765b9c547cSRui Paulo 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
5677d4f2939cSRui Paulo 		goto fail;
5678d4f2939cSRui Paulo 
5679d4f2939cSRui Paulo 	dbus_connection_send(priv->con, msg, NULL);
5680d4f2939cSRui Paulo 	goto out;
5681d4f2939cSRui Paulo fail:
5682d4f2939cSRui Paulo 	wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
5683d4f2939cSRui Paulo out:
5684d4f2939cSRui Paulo 	dbus_message_unref(msg);
5685d4f2939cSRui Paulo }
5686d4f2939cSRui Paulo 
5687d4f2939cSRui Paulo #endif /* CONFIG_AP */
5688780fb4a2SCy Schubert 
5689780fb4a2SCy Schubert 
wpas_dbus_handler_vendor_elem_add(DBusMessage * message,struct wpa_supplicant * wpa_s)5690780fb4a2SCy Schubert DBusMessage * wpas_dbus_handler_vendor_elem_add(DBusMessage *message,
5691780fb4a2SCy Schubert 						struct wpa_supplicant *wpa_s)
5692780fb4a2SCy Schubert {
5693780fb4a2SCy Schubert 	u8 *ielems;
5694780fb4a2SCy Schubert 	int len;
5695780fb4a2SCy Schubert 	struct ieee802_11_elems elems;
5696780fb4a2SCy Schubert 	dbus_int32_t frame_id;
5697780fb4a2SCy Schubert 	DBusMessageIter	iter, array;
5698780fb4a2SCy Schubert 
5699780fb4a2SCy Schubert 	dbus_message_iter_init(message, &iter);
5700780fb4a2SCy Schubert 	dbus_message_iter_get_basic(&iter, &frame_id);
5701780fb4a2SCy Schubert 	if (frame_id < 0 || frame_id >= NUM_VENDOR_ELEM_FRAMES) {
5702780fb4a2SCy Schubert 		return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
5703780fb4a2SCy Schubert 					      "Invalid ID");
5704780fb4a2SCy Schubert 	}
5705780fb4a2SCy Schubert 
5706780fb4a2SCy Schubert 	dbus_message_iter_next(&iter);
5707780fb4a2SCy Schubert 	dbus_message_iter_recurse(&iter, &array);
5708780fb4a2SCy Schubert 	dbus_message_iter_get_fixed_array(&array, &ielems, &len);
5709780fb4a2SCy Schubert 	if (!ielems || len == 0) {
5710780fb4a2SCy Schubert 		return dbus_message_new_error(
5711780fb4a2SCy Schubert 			message, DBUS_ERROR_INVALID_ARGS, "Invalid value");
5712780fb4a2SCy Schubert 	}
5713780fb4a2SCy Schubert 
5714780fb4a2SCy Schubert 	if (ieee802_11_parse_elems(ielems, len, &elems, 0) == ParseFailed) {
5715780fb4a2SCy Schubert 		return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
5716780fb4a2SCy Schubert 					      "Parse error");
5717780fb4a2SCy Schubert 	}
5718780fb4a2SCy Schubert 
5719780fb4a2SCy Schubert 	wpa_s = wpas_vendor_elem(wpa_s, frame_id);
5720780fb4a2SCy Schubert 	if (!wpa_s->vendor_elem[frame_id]) {
5721780fb4a2SCy Schubert 		wpa_s->vendor_elem[frame_id] = wpabuf_alloc_copy(ielems, len);
5722780fb4a2SCy Schubert 		wpas_vendor_elem_update(wpa_s);
5723780fb4a2SCy Schubert 		return NULL;
5724780fb4a2SCy Schubert 	}
5725780fb4a2SCy Schubert 
5726780fb4a2SCy Schubert 	if (wpabuf_resize(&wpa_s->vendor_elem[frame_id], len) < 0) {
5727780fb4a2SCy Schubert 		return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
5728780fb4a2SCy Schubert 					      "Resize error");
5729780fb4a2SCy Schubert 	}
5730780fb4a2SCy Schubert 
5731780fb4a2SCy Schubert 	wpabuf_put_data(wpa_s->vendor_elem[frame_id], ielems, len);
5732780fb4a2SCy Schubert 	wpas_vendor_elem_update(wpa_s);
5733780fb4a2SCy Schubert 	return NULL;
5734780fb4a2SCy Schubert }
5735780fb4a2SCy Schubert 
5736780fb4a2SCy Schubert 
wpas_dbus_handler_vendor_elem_get(DBusMessage * message,struct wpa_supplicant * wpa_s)5737780fb4a2SCy Schubert DBusMessage * wpas_dbus_handler_vendor_elem_get(DBusMessage *message,
5738780fb4a2SCy Schubert 						struct wpa_supplicant *wpa_s)
5739780fb4a2SCy Schubert {
5740780fb4a2SCy Schubert 	DBusMessage *reply;
5741780fb4a2SCy Schubert 	DBusMessageIter	iter, array_iter;
5742780fb4a2SCy Schubert 	dbus_int32_t frame_id;
5743780fb4a2SCy Schubert 	const u8 *elem;
5744780fb4a2SCy Schubert 	size_t elem_len;
5745780fb4a2SCy Schubert 
5746780fb4a2SCy Schubert 	dbus_message_iter_init(message, &iter);
5747780fb4a2SCy Schubert 	dbus_message_iter_get_basic(&iter, &frame_id);
5748780fb4a2SCy Schubert 
5749780fb4a2SCy Schubert 	if (frame_id < 0 || frame_id >= NUM_VENDOR_ELEM_FRAMES) {
5750780fb4a2SCy Schubert 		return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
5751780fb4a2SCy Schubert 					      "Invalid ID");
5752780fb4a2SCy Schubert 	}
5753780fb4a2SCy Schubert 
5754780fb4a2SCy Schubert 	wpa_s = wpas_vendor_elem(wpa_s, frame_id);
5755780fb4a2SCy Schubert 	if (!wpa_s->vendor_elem[frame_id]) {
5756780fb4a2SCy Schubert 		return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
5757780fb4a2SCy Schubert 					      "ID value does not exist");
5758780fb4a2SCy Schubert 	}
5759780fb4a2SCy Schubert 
5760780fb4a2SCy Schubert 	reply = dbus_message_new_method_return(message);
5761780fb4a2SCy Schubert 	if (!reply)
5762780fb4a2SCy Schubert 		return wpas_dbus_error_no_memory(message);
5763780fb4a2SCy Schubert 
5764780fb4a2SCy Schubert 	dbus_message_iter_init_append(reply, &iter);
5765780fb4a2SCy Schubert 
5766780fb4a2SCy Schubert 	elem = wpabuf_head_u8(wpa_s->vendor_elem[frame_id]);
5767780fb4a2SCy Schubert 	elem_len = wpabuf_len(wpa_s->vendor_elem[frame_id]);
5768780fb4a2SCy Schubert 
5769780fb4a2SCy Schubert 	if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
5770780fb4a2SCy Schubert 					      DBUS_TYPE_BYTE_AS_STRING,
5771780fb4a2SCy Schubert 					      &array_iter) ||
5772780fb4a2SCy Schubert 	    !dbus_message_iter_append_fixed_array(&array_iter, DBUS_TYPE_BYTE,
5773780fb4a2SCy Schubert 						  &elem, elem_len) ||
5774780fb4a2SCy Schubert 	    !dbus_message_iter_close_container(&iter, &array_iter)) {
5775780fb4a2SCy Schubert 		dbus_message_unref(reply);
5776780fb4a2SCy Schubert 		reply = wpas_dbus_error_no_memory(message);
5777780fb4a2SCy Schubert 	}
5778780fb4a2SCy Schubert 
5779780fb4a2SCy Schubert 	return reply;
5780780fb4a2SCy Schubert }
5781780fb4a2SCy Schubert 
5782780fb4a2SCy Schubert 
wpas_dbus_handler_vendor_elem_remove(DBusMessage * message,struct wpa_supplicant * wpa_s)5783780fb4a2SCy Schubert DBusMessage * wpas_dbus_handler_vendor_elem_remove(DBusMessage *message,
5784780fb4a2SCy Schubert 						   struct wpa_supplicant *wpa_s)
5785780fb4a2SCy Schubert {
5786780fb4a2SCy Schubert 	u8 *ielems;
5787780fb4a2SCy Schubert 	int len;
5788780fb4a2SCy Schubert 	struct ieee802_11_elems elems;
5789780fb4a2SCy Schubert 	DBusMessageIter	iter, array;
5790780fb4a2SCy Schubert 	dbus_int32_t frame_id;
5791780fb4a2SCy Schubert 
5792780fb4a2SCy Schubert 	dbus_message_iter_init(message, &iter);
5793780fb4a2SCy Schubert 	dbus_message_iter_get_basic(&iter, &frame_id);
5794780fb4a2SCy Schubert 	if (frame_id < 0 || frame_id >= NUM_VENDOR_ELEM_FRAMES) {
5795780fb4a2SCy Schubert 		return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
5796780fb4a2SCy Schubert 					      "Invalid ID");
5797780fb4a2SCy Schubert 	}
5798780fb4a2SCy Schubert 
5799780fb4a2SCy Schubert 	dbus_message_iter_next(&iter);
5800780fb4a2SCy Schubert 	dbus_message_iter_recurse(&iter, &array);
5801780fb4a2SCy Schubert 	dbus_message_iter_get_fixed_array(&array, &ielems, &len);
5802780fb4a2SCy Schubert 	if (!ielems || len == 0) {
5803780fb4a2SCy Schubert 		return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
5804780fb4a2SCy Schubert 					      "Invalid value");
5805780fb4a2SCy Schubert 	}
5806780fb4a2SCy Schubert 
5807780fb4a2SCy Schubert 	wpa_s = wpas_vendor_elem(wpa_s, frame_id);
5808780fb4a2SCy Schubert 
5809780fb4a2SCy Schubert 	if (len == 1 && *ielems == '*') {
5810780fb4a2SCy Schubert 		wpabuf_free(wpa_s->vendor_elem[frame_id]);
5811780fb4a2SCy Schubert 		wpa_s->vendor_elem[frame_id] = NULL;
5812780fb4a2SCy Schubert 		wpas_vendor_elem_update(wpa_s);
5813780fb4a2SCy Schubert 		return NULL;
5814780fb4a2SCy Schubert 	}
5815780fb4a2SCy Schubert 
5816780fb4a2SCy Schubert 	if (!wpa_s->vendor_elem[frame_id]) {
5817780fb4a2SCy Schubert 		return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
5818780fb4a2SCy Schubert 					      "ID value does not exist");
5819780fb4a2SCy Schubert 	}
5820780fb4a2SCy Schubert 
5821780fb4a2SCy Schubert 	if (ieee802_11_parse_elems(ielems, len, &elems, 0) == ParseFailed) {
5822780fb4a2SCy Schubert 		return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
5823780fb4a2SCy Schubert 					      "Parse error");
5824780fb4a2SCy Schubert 	}
5825780fb4a2SCy Schubert 
5826780fb4a2SCy Schubert 	if (wpas_vendor_elem_remove(wpa_s, frame_id, ielems, len) == 0)
5827780fb4a2SCy Schubert 		return NULL;
5828780fb4a2SCy Schubert 
5829780fb4a2SCy Schubert 	return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
5830780fb4a2SCy Schubert 				      "Not found");
5831780fb4a2SCy Schubert }
583285732ac8SCy Schubert 
583385732ac8SCy Schubert 
583485732ac8SCy Schubert #ifdef CONFIG_MESH
583585732ac8SCy Schubert 
583685732ac8SCy Schubert /**
583785732ac8SCy Schubert  * wpas_dbus_getter_mesh_peers - Get connected mesh peers
583885732ac8SCy Schubert  * @iter: Pointer to incoming dbus message iter
583985732ac8SCy Schubert  * @error: Location to store error on failure
584085732ac8SCy Schubert  * @user_data: Function specific data
584185732ac8SCy Schubert  * Returns: TRUE on success, FALSE on failure
584285732ac8SCy Schubert  *
584385732ac8SCy Schubert  * Getter for "MeshPeers" property.
584485732ac8SCy Schubert  */
wpas_dbus_getter_mesh_peers(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)584585732ac8SCy Schubert dbus_bool_t wpas_dbus_getter_mesh_peers(
584685732ac8SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
584785732ac8SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
584885732ac8SCy Schubert {
584985732ac8SCy Schubert 	struct wpa_supplicant *wpa_s = user_data;
585085732ac8SCy Schubert 	struct hostapd_data *hapd;
585185732ac8SCy Schubert 	struct sta_info *sta;
585285732ac8SCy Schubert 	DBusMessageIter variant_iter, array_iter;
585385732ac8SCy Schubert 	int i;
585485732ac8SCy Schubert 	DBusMessageIter inner_array_iter;
585585732ac8SCy Schubert 
585685732ac8SCy Schubert 	if (!wpa_s->ifmsh)
585785732ac8SCy Schubert 		return FALSE;
585885732ac8SCy Schubert 	hapd = wpa_s->ifmsh->bss[0];
585985732ac8SCy Schubert 
586085732ac8SCy Schubert 	if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
586185732ac8SCy Schubert 					      DBUS_TYPE_ARRAY_AS_STRING
586285732ac8SCy Schubert 					      DBUS_TYPE_ARRAY_AS_STRING
586385732ac8SCy Schubert 					      DBUS_TYPE_BYTE_AS_STRING,
586485732ac8SCy Schubert 					      &variant_iter) ||
586585732ac8SCy Schubert 	    !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
586685732ac8SCy Schubert 					      DBUS_TYPE_ARRAY_AS_STRING
586785732ac8SCy Schubert 					      DBUS_TYPE_BYTE_AS_STRING,
586885732ac8SCy Schubert 					      &array_iter))
586985732ac8SCy Schubert 		return FALSE;
587085732ac8SCy Schubert 
587185732ac8SCy Schubert 	for (sta = hapd->sta_list; sta; sta = sta->next) {
587285732ac8SCy Schubert 		if (!dbus_message_iter_open_container(
587385732ac8SCy Schubert 			    &array_iter, DBUS_TYPE_ARRAY,
587485732ac8SCy Schubert 			    DBUS_TYPE_BYTE_AS_STRING,
587585732ac8SCy Schubert 			    &inner_array_iter))
587685732ac8SCy Schubert 			return FALSE;
587785732ac8SCy Schubert 
587885732ac8SCy Schubert 		for (i = 0; i < ETH_ALEN; i++) {
587985732ac8SCy Schubert 			if (!dbus_message_iter_append_basic(&inner_array_iter,
588085732ac8SCy Schubert 							    DBUS_TYPE_BYTE,
588185732ac8SCy Schubert 							    &(sta->addr[i])))
588285732ac8SCy Schubert 				return FALSE;
588385732ac8SCy Schubert 		}
588485732ac8SCy Schubert 
588585732ac8SCy Schubert 		if (!dbus_message_iter_close_container(
588685732ac8SCy Schubert 			    &array_iter, &inner_array_iter))
588785732ac8SCy Schubert 			return FALSE;
588885732ac8SCy Schubert 	}
588985732ac8SCy Schubert 
589085732ac8SCy Schubert 	if (!dbus_message_iter_close_container(&variant_iter, &array_iter) ||
589185732ac8SCy Schubert 	    !dbus_message_iter_close_container(iter, &variant_iter))
589285732ac8SCy Schubert 		return FALSE;
589385732ac8SCy Schubert 
589485732ac8SCy Schubert 	return TRUE;
589585732ac8SCy Schubert }
589685732ac8SCy Schubert 
589785732ac8SCy Schubert 
589885732ac8SCy Schubert /**
589985732ac8SCy Schubert  * wpas_dbus_getter_mesh_group - Get mesh group
590085732ac8SCy Schubert  * @iter: Pointer to incoming dbus message iter
590185732ac8SCy Schubert  * @error: Location to store error on failure
590285732ac8SCy Schubert  * @user_data: Function specific data
590385732ac8SCy Schubert  * Returns: TRUE on success, FALSE on failure
590485732ac8SCy Schubert  *
590585732ac8SCy Schubert  * Getter for "MeshGroup" property.
590685732ac8SCy Schubert  */
wpas_dbus_getter_mesh_group(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)590785732ac8SCy Schubert dbus_bool_t wpas_dbus_getter_mesh_group(
590885732ac8SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
590985732ac8SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
591085732ac8SCy Schubert {
591185732ac8SCy Schubert 	struct wpa_supplicant *wpa_s = user_data;
591285732ac8SCy Schubert 	struct wpa_ssid *ssid = wpa_s->current_ssid;
591385732ac8SCy Schubert 
591485732ac8SCy Schubert 	if (!wpa_s->ifmsh || !ssid)
591585732ac8SCy Schubert 		return FALSE;
591685732ac8SCy Schubert 
591785732ac8SCy Schubert 	if (!wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
591885732ac8SCy Schubert 						    (char *) ssid->ssid,
591985732ac8SCy Schubert 						    ssid->ssid_len, error)) {
592085732ac8SCy Schubert 		dbus_set_error(error, DBUS_ERROR_FAILED,
592185732ac8SCy Schubert 			       "%s: error constructing reply", __func__);
592285732ac8SCy Schubert 		return FALSE;
592385732ac8SCy Schubert 	}
592485732ac8SCy Schubert 
592585732ac8SCy Schubert 	return TRUE;
592685732ac8SCy Schubert }
592785732ac8SCy Schubert 
592885732ac8SCy Schubert #endif /* CONFIG_MESH */
5929