xref: /freebsd/contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers_p2p.c (revision a90b9d0159070121c221b966469c3e36d912bf82)
1d4f2939cSRui Paulo /*
2d4f2939cSRui Paulo  * WPA Supplicant / dbus-based control interface (P2P)
3d4f2939cSRui Paulo  * Copyright (c) 2011-2012, Intel Corporation
4d4f2939cSRui Paulo  *
5d4f2939cSRui Paulo  * This software may be distributed under the terms of the BSD license.
6d4f2939cSRui Paulo  * See README for more details.
7d4f2939cSRui Paulo  */
8d4f2939cSRui Paulo 
9d4f2939cSRui Paulo #include "includes.h"
10d4f2939cSRui Paulo 
11d4f2939cSRui Paulo #include "utils/includes.h"
12d4f2939cSRui Paulo #include "common.h"
13d4f2939cSRui Paulo #include "../config.h"
14d4f2939cSRui Paulo #include "../wpa_supplicant_i.h"
15d4f2939cSRui Paulo #include "../wps_supplicant.h"
16d4f2939cSRui Paulo #include "../notify.h"
17*a90b9d01SCy Schubert #include "../bss.h"
18d4f2939cSRui Paulo #include "dbus_new_helpers.h"
19d4f2939cSRui Paulo #include "dbus_new.h"
20d4f2939cSRui Paulo #include "dbus_new_handlers.h"
21d4f2939cSRui Paulo #include "dbus_new_handlers_p2p.h"
22d4f2939cSRui Paulo #include "dbus_dict_helpers.h"
23d4f2939cSRui Paulo #include "p2p/p2p.h"
24d4f2939cSRui Paulo #include "common/ieee802_11_defs.h"
25d4f2939cSRui Paulo #include "ap/hostapd.h"
26d4f2939cSRui Paulo #include "ap/ap_config.h"
27d4f2939cSRui Paulo #include "ap/wps_hostapd.h"
28d4f2939cSRui Paulo 
29d4f2939cSRui Paulo #include "../p2p_supplicant.h"
305b9c547cSRui Paulo #include "../wifi_display.h"
31d4f2939cSRui Paulo 
3285732ac8SCy Schubert 
wpas_dbus_validate_dbus_ipaddr(struct wpa_dbus_dict_entry entry)3385732ac8SCy Schubert static int wpas_dbus_validate_dbus_ipaddr(struct wpa_dbus_dict_entry entry)
3485732ac8SCy Schubert {
3585732ac8SCy Schubert 	if (entry.type != DBUS_TYPE_ARRAY ||
3685732ac8SCy Schubert 	    entry.array_type != DBUS_TYPE_BYTE ||
3785732ac8SCy Schubert 	    entry.array_len != 4)
3885732ac8SCy Schubert 		return 0;
3985732ac8SCy Schubert 
4085732ac8SCy Schubert 	return 1;
4185732ac8SCy Schubert }
4285732ac8SCy Schubert 
4385732ac8SCy Schubert 
no_p2p_mgmt_interface(DBusError * error)44c1d255d3SCy Schubert static dbus_bool_t no_p2p_mgmt_interface(DBusError *error)
45c1d255d3SCy Schubert {
46c1d255d3SCy Schubert 	dbus_set_error_const(error, WPAS_DBUS_ERROR_IFACE_UNKNOWN,
47c1d255d3SCy Schubert 			     "Could not find P2P mgmt interface");
48c1d255d3SCy Schubert 	return FALSE;
49c1d255d3SCy Schubert }
50c1d255d3SCy Schubert 
51c1d255d3SCy Schubert 
52d4f2939cSRui Paulo /**
53d4f2939cSRui Paulo  * Parses out the mac address from the peer object path.
54d4f2939cSRui Paulo  * @peer_path - object path of the form
55d4f2939cSRui Paulo  *	/fi/w1/wpa_supplicant1/Interfaces/n/Peers/00112233445566 (no colons)
56d4f2939cSRui Paulo  * @addr - out param must be of ETH_ALEN size
57d4f2939cSRui Paulo  * Returns 0 if valid (including MAC), -1 otherwise
58d4f2939cSRui Paulo  */
parse_peer_object_path(const char * peer_path,u8 addr[ETH_ALEN])595b9c547cSRui Paulo static int parse_peer_object_path(const char *peer_path, u8 addr[ETH_ALEN])
60d4f2939cSRui Paulo {
615b9c547cSRui Paulo 	const char *p;
62d4f2939cSRui Paulo 
63d4f2939cSRui Paulo 	if (!peer_path)
64d4f2939cSRui Paulo 		return -1;
65d4f2939cSRui Paulo 	p = os_strrchr(peer_path, '/');
66d4f2939cSRui Paulo 	if (!p)
67d4f2939cSRui Paulo 		return -1;
68d4f2939cSRui Paulo 	p++;
69d4f2939cSRui Paulo 	return hwaddr_compact_aton(p, addr);
70d4f2939cSRui Paulo }
71d4f2939cSRui Paulo 
72d4f2939cSRui Paulo 
73d4f2939cSRui Paulo /**
74d4f2939cSRui Paulo  * wpas_dbus_error_persistent_group_unknown - Return a new PersistentGroupUnknown
75d4f2939cSRui Paulo  * error message
76d4f2939cSRui Paulo  * @message: Pointer to incoming dbus message this error refers to
77d4f2939cSRui Paulo  * Returns: a dbus error message
78d4f2939cSRui Paulo  *
79d4f2939cSRui Paulo  * Convenience function to create and return an invalid persistent group error.
80d4f2939cSRui Paulo  */
815b9c547cSRui Paulo static DBusMessage *
wpas_dbus_error_persistent_group_unknown(DBusMessage * message)825b9c547cSRui Paulo wpas_dbus_error_persistent_group_unknown(DBusMessage *message)
83d4f2939cSRui Paulo {
845b9c547cSRui Paulo 	return dbus_message_new_error(
855b9c547cSRui Paulo 		message, WPAS_DBUS_ERROR_NETWORK_UNKNOWN,
865b9c547cSRui Paulo 		"There is no such persistent group in this P2P device.");
87d4f2939cSRui Paulo }
88d4f2939cSRui Paulo 
89d4f2939cSRui Paulo 
90c1d255d3SCy Schubert /**
91c1d255d3SCy Schubert  * wpas_dbus_error_no_p2p_mgmt_iface - Return a new InterfaceUnknown error
92c1d255d3SCy Schubert  * message
93c1d255d3SCy Schubert  * @message: Pointer to incoming dbus message this error refers to
94c1d255d3SCy Schubert  * Returns: a dbus error message
95c1d255d3SCy Schubert  *
96c1d255d3SCy Schubert  * Convenience function to create and return an unknown interface error.
97c1d255d3SCy Schubert  */
wpas_dbus_error_no_p2p_mgmt_iface(DBusMessage * message)98c1d255d3SCy Schubert static DBusMessage * wpas_dbus_error_no_p2p_mgmt_iface(DBusMessage *message)
99c1d255d3SCy Schubert {
100c1d255d3SCy Schubert 	wpa_printf(MSG_DEBUG, "dbus: Could not find P2P mgmt interface");
101c1d255d3SCy Schubert 	return dbus_message_new_error(message, WPAS_DBUS_ERROR_IFACE_UNKNOWN,
102c1d255d3SCy Schubert 				      "Could not find P2P mgmt interface");
103c1d255d3SCy Schubert }
104c1d255d3SCy Schubert 
105c1d255d3SCy Schubert 
wpas_dbus_handler_p2p_find(DBusMessage * message,struct wpa_supplicant * wpa_s)106d4f2939cSRui Paulo DBusMessage * wpas_dbus_handler_p2p_find(DBusMessage *message,
107d4f2939cSRui Paulo 					 struct wpa_supplicant *wpa_s)
108d4f2939cSRui Paulo {
109d4f2939cSRui Paulo 	struct wpa_dbus_dict_entry entry;
110d4f2939cSRui Paulo 	DBusMessage *reply = NULL;
111d4f2939cSRui Paulo 	DBusMessageIter iter;
112d4f2939cSRui Paulo 	DBusMessageIter iter_dict;
113d4f2939cSRui Paulo 	unsigned int timeout = 0;
1145b9c547cSRui Paulo 	enum p2p_discovery_type type = P2P_FIND_START_WITH_FULL;
115d4f2939cSRui Paulo 	int num_req_dev_types = 0;
116d4f2939cSRui Paulo 	unsigned int i;
117d4f2939cSRui Paulo 	u8 *req_dev_types = NULL;
11885732ac8SCy Schubert 	unsigned int freq = 0;
119d4f2939cSRui Paulo 
120d4f2939cSRui Paulo 	dbus_message_iter_init(message, &iter);
121d4f2939cSRui Paulo 	entry.key = NULL;
122d4f2939cSRui Paulo 
123d4f2939cSRui Paulo 	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
124d4f2939cSRui Paulo 		goto error;
125d4f2939cSRui Paulo 
126d4f2939cSRui Paulo 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
127d4f2939cSRui Paulo 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
128d4f2939cSRui Paulo 			goto error;
129d4f2939cSRui Paulo 
1305b9c547cSRui Paulo 		if (os_strcmp(entry.key, "Timeout") == 0 &&
1315b9c547cSRui Paulo 		    entry.type == DBUS_TYPE_INT32) {
132d4f2939cSRui Paulo 			timeout = entry.uint32_value;
133d4f2939cSRui Paulo 		} else if (os_strcmp(entry.key, "RequestedDeviceTypes") == 0) {
1345b9c547cSRui Paulo 			if (entry.type != DBUS_TYPE_ARRAY ||
1355b9c547cSRui Paulo 			    entry.array_type != WPAS_DBUS_TYPE_BINARRAY)
136d4f2939cSRui Paulo 				goto error_clear;
137d4f2939cSRui Paulo 
138d4f2939cSRui Paulo 			os_free(req_dev_types);
139d4f2939cSRui Paulo 			req_dev_types =
140d4f2939cSRui Paulo 				os_malloc(WPS_DEV_TYPE_LEN * entry.array_len);
141d4f2939cSRui Paulo 			if (!req_dev_types)
142d4f2939cSRui Paulo 				goto error_clear;
143d4f2939cSRui Paulo 
144d4f2939cSRui Paulo 			for (i = 0; i < entry.array_len; i++) {
145d4f2939cSRui Paulo 				if (wpabuf_len(entry.binarray_value[i]) !=
146d4f2939cSRui Paulo 				    WPS_DEV_TYPE_LEN)
147d4f2939cSRui Paulo 					goto error_clear;
148d4f2939cSRui Paulo 				os_memcpy(req_dev_types + i * WPS_DEV_TYPE_LEN,
149d4f2939cSRui Paulo 					  wpabuf_head(entry.binarray_value[i]),
150d4f2939cSRui Paulo 					  WPS_DEV_TYPE_LEN);
151d4f2939cSRui Paulo 			}
152d4f2939cSRui Paulo 			num_req_dev_types = entry.array_len;
1535b9c547cSRui Paulo 		} else if (os_strcmp(entry.key, "DiscoveryType") == 0 &&
1545b9c547cSRui Paulo 			   entry.type == DBUS_TYPE_STRING) {
1555b9c547cSRui Paulo 			if (os_strcmp(entry.str_value, "start_with_full") == 0)
156d4f2939cSRui Paulo 				type = P2P_FIND_START_WITH_FULL;
1575b9c547cSRui Paulo 			else if (os_strcmp(entry.str_value, "social") == 0)
158d4f2939cSRui Paulo 				type = P2P_FIND_ONLY_SOCIAL;
1595b9c547cSRui Paulo 			else if (os_strcmp(entry.str_value, "progressive") == 0)
160d4f2939cSRui Paulo 				type = P2P_FIND_PROGRESSIVE;
161d4f2939cSRui Paulo 			else
162d4f2939cSRui Paulo 				goto error_clear;
16385732ac8SCy Schubert 		} else if (os_strcmp(entry.key, "freq") == 0 &&
16485732ac8SCy Schubert 			   (entry.type == DBUS_TYPE_INT32 ||
16585732ac8SCy Schubert 			    entry.type == DBUS_TYPE_UINT32)) {
16685732ac8SCy Schubert 			freq = entry.uint32_value;
167d4f2939cSRui Paulo 		} else
168d4f2939cSRui Paulo 			goto error_clear;
169d4f2939cSRui Paulo 		wpa_dbus_dict_entry_clear(&entry);
170d4f2939cSRui Paulo 	}
171d4f2939cSRui Paulo 
172325151a3SRui Paulo 	wpa_s = wpa_s->global->p2p_init_wpa_s;
173c1d255d3SCy Schubert 	if (!wpa_s) {
174c1d255d3SCy Schubert 		reply = wpas_dbus_error_no_p2p_mgmt_iface(message);
175c1d255d3SCy Schubert 		goto error_nop2p;
176c1d255d3SCy Schubert 	}
1775b9c547cSRui Paulo 
17885732ac8SCy Schubert 	if (wpas_p2p_find(wpa_s, timeout, type, num_req_dev_types,
179c1d255d3SCy Schubert 			  req_dev_types, NULL, 0, 0, NULL, freq, false))
18085732ac8SCy Schubert 		reply = wpas_dbus_error_unknown_error(
18185732ac8SCy Schubert 			message, "Could not start P2P find");
18285732ac8SCy Schubert 
183d4f2939cSRui Paulo 	os_free(req_dev_types);
184d4f2939cSRui Paulo 	return reply;
185d4f2939cSRui Paulo 
186d4f2939cSRui Paulo error_clear:
187d4f2939cSRui Paulo 	wpa_dbus_dict_entry_clear(&entry);
188d4f2939cSRui Paulo error:
189d4f2939cSRui Paulo 	reply = wpas_dbus_error_invalid_args(message, entry.key);
190c1d255d3SCy Schubert error_nop2p:
191c1d255d3SCy Schubert 	os_free(req_dev_types);
192d4f2939cSRui Paulo 	return reply;
193d4f2939cSRui Paulo }
194d4f2939cSRui Paulo 
195d4f2939cSRui Paulo 
wpas_dbus_handler_p2p_stop_find(DBusMessage * message,struct wpa_supplicant * wpa_s)196d4f2939cSRui Paulo DBusMessage * wpas_dbus_handler_p2p_stop_find(DBusMessage *message,
197d4f2939cSRui Paulo 					      struct wpa_supplicant *wpa_s)
198d4f2939cSRui Paulo {
199c1d255d3SCy Schubert 	wpa_s = wpa_s->global->p2p_init_wpa_s;
200c1d255d3SCy Schubert 	if (wpa_s)
201c1d255d3SCy Schubert 		wpas_p2p_stop_find(wpa_s);
202d4f2939cSRui Paulo 	return NULL;
203d4f2939cSRui Paulo }
204d4f2939cSRui Paulo 
205d4f2939cSRui Paulo 
wpas_dbus_handler_p2p_rejectpeer(DBusMessage * message,struct wpa_supplicant * wpa_s)206d4f2939cSRui Paulo DBusMessage * wpas_dbus_handler_p2p_rejectpeer(DBusMessage *message,
207d4f2939cSRui Paulo 					       struct wpa_supplicant *wpa_s)
208d4f2939cSRui Paulo {
209d4f2939cSRui Paulo 	DBusMessageIter iter;
210d4f2939cSRui Paulo 	char *peer_object_path = NULL;
211d4f2939cSRui Paulo 	u8 peer_addr[ETH_ALEN];
212d4f2939cSRui Paulo 
213d4f2939cSRui Paulo 	dbus_message_iter_init(message, &iter);
214d4f2939cSRui Paulo 	dbus_message_iter_get_basic(&iter, &peer_object_path);
215d4f2939cSRui Paulo 
216d4f2939cSRui Paulo 	if (parse_peer_object_path(peer_object_path, peer_addr) < 0)
217d4f2939cSRui Paulo 		return wpas_dbus_error_invalid_args(message, NULL);
218d4f2939cSRui Paulo 
219325151a3SRui Paulo 	wpa_s = wpa_s->global->p2p_init_wpa_s;
220c1d255d3SCy Schubert 	if (!wpa_s)
221c1d255d3SCy Schubert 		return wpas_dbus_error_no_p2p_mgmt_iface(message);
2225b9c547cSRui Paulo 
223d4f2939cSRui Paulo 	if (wpas_p2p_reject(wpa_s, peer_addr) < 0)
224d4f2939cSRui Paulo 		return wpas_dbus_error_unknown_error(message,
225d4f2939cSRui Paulo 				"Failed to call wpas_p2p_reject method.");
226d4f2939cSRui Paulo 
227d4f2939cSRui Paulo 	return NULL;
228d4f2939cSRui Paulo }
229d4f2939cSRui Paulo 
230d4f2939cSRui Paulo 
wpas_dbus_handler_p2p_listen(DBusMessage * message,struct wpa_supplicant * wpa_s)231d4f2939cSRui Paulo DBusMessage * wpas_dbus_handler_p2p_listen(DBusMessage *message,
232d4f2939cSRui Paulo 					   struct wpa_supplicant *wpa_s)
233d4f2939cSRui Paulo {
234d4f2939cSRui Paulo 	dbus_int32_t timeout = 0;
235d4f2939cSRui Paulo 
236d4f2939cSRui Paulo 	if (!dbus_message_get_args(message, NULL, DBUS_TYPE_INT32, &timeout,
237d4f2939cSRui Paulo 				   DBUS_TYPE_INVALID))
2385b9c547cSRui Paulo 		return wpas_dbus_error_no_memory(message);
239d4f2939cSRui Paulo 
240325151a3SRui Paulo 	wpa_s = wpa_s->global->p2p_init_wpa_s;
241c1d255d3SCy Schubert 	if (!wpa_s)
242c1d255d3SCy Schubert 		return wpas_dbus_error_no_p2p_mgmt_iface(message);
2435b9c547cSRui Paulo 
2445b9c547cSRui Paulo 	if (wpas_p2p_listen(wpa_s, (unsigned int) timeout)) {
2455b9c547cSRui Paulo 		return dbus_message_new_error(message,
2465b9c547cSRui Paulo 					      WPAS_DBUS_ERROR_UNKNOWN_ERROR,
2475b9c547cSRui Paulo 					      "Could not start P2P listen");
2485b9c547cSRui Paulo 	}
249d4f2939cSRui Paulo 
250d4f2939cSRui Paulo 	return NULL;
251d4f2939cSRui Paulo }
252d4f2939cSRui Paulo 
253d4f2939cSRui Paulo 
wpas_dbus_handler_p2p_extendedlisten(DBusMessage * message,struct wpa_supplicant * wpa_s)254d4f2939cSRui Paulo DBusMessage * wpas_dbus_handler_p2p_extendedlisten(
255d4f2939cSRui Paulo 	DBusMessage *message, struct wpa_supplicant *wpa_s)
256d4f2939cSRui Paulo {
257d4f2939cSRui Paulo 	unsigned int period = 0, interval = 0;
258d4f2939cSRui Paulo 	struct wpa_dbus_dict_entry entry;
259d4f2939cSRui Paulo 	DBusMessageIter iter;
260d4f2939cSRui Paulo 	DBusMessageIter iter_dict;
261d4f2939cSRui Paulo 
262d4f2939cSRui Paulo 	dbus_message_iter_init(message, &iter);
263d4f2939cSRui Paulo 	entry.key = NULL;
264d4f2939cSRui Paulo 
265d4f2939cSRui Paulo 	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
266d4f2939cSRui Paulo 		goto error;
267d4f2939cSRui Paulo 
268d4f2939cSRui Paulo 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
269d4f2939cSRui Paulo 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
270d4f2939cSRui Paulo 			goto error;
271d4f2939cSRui Paulo 
2725b9c547cSRui Paulo 		if (os_strcmp(entry.key, "period") == 0 &&
2735b9c547cSRui Paulo 		    entry.type == DBUS_TYPE_INT32)
274d4f2939cSRui Paulo 			period = entry.uint32_value;
2755b9c547cSRui Paulo 		else if (os_strcmp(entry.key, "interval") == 0 &&
2765b9c547cSRui Paulo 			 entry.type == DBUS_TYPE_INT32)
277d4f2939cSRui Paulo 			interval = entry.uint32_value;
278d4f2939cSRui Paulo 		else
279d4f2939cSRui Paulo 			goto error_clear;
280d4f2939cSRui Paulo 		wpa_dbus_dict_entry_clear(&entry);
281d4f2939cSRui Paulo 	}
282d4f2939cSRui Paulo 
283325151a3SRui Paulo 	wpa_s = wpa_s->global->p2p_init_wpa_s;
284c1d255d3SCy Schubert 	if (!wpa_s)
285c1d255d3SCy Schubert 		return wpas_dbus_error_no_p2p_mgmt_iface(message);
2865b9c547cSRui Paulo 
287d4f2939cSRui Paulo 	if (wpas_p2p_ext_listen(wpa_s, period, interval))
288d4f2939cSRui Paulo 		return wpas_dbus_error_unknown_error(
289d4f2939cSRui Paulo 			message, "failed to initiate a p2p_ext_listen.");
290d4f2939cSRui Paulo 
291d4f2939cSRui Paulo 	return NULL;
292d4f2939cSRui Paulo 
293d4f2939cSRui Paulo error_clear:
294d4f2939cSRui Paulo 	wpa_dbus_dict_entry_clear(&entry);
295d4f2939cSRui Paulo error:
296d4f2939cSRui Paulo 	return wpas_dbus_error_invalid_args(message, entry.key);
297d4f2939cSRui Paulo }
298d4f2939cSRui Paulo 
299d4f2939cSRui Paulo 
wpas_dbus_handler_p2p_presence_request(DBusMessage * message,struct wpa_supplicant * wpa_s)300d4f2939cSRui Paulo DBusMessage * wpas_dbus_handler_p2p_presence_request(
301d4f2939cSRui Paulo 	DBusMessage *message, struct wpa_supplicant *wpa_s)
302d4f2939cSRui Paulo {
303d4f2939cSRui Paulo 	unsigned int dur1 = 0, int1 = 0, dur2 = 0, int2 = 0;
304d4f2939cSRui Paulo 	struct wpa_dbus_dict_entry entry;
305d4f2939cSRui Paulo 	DBusMessageIter iter;
306d4f2939cSRui Paulo 	DBusMessageIter iter_dict;
307d4f2939cSRui Paulo 
308d4f2939cSRui Paulo 	dbus_message_iter_init(message, &iter);
309d4f2939cSRui Paulo 	entry.key = NULL;
310d4f2939cSRui Paulo 
311d4f2939cSRui Paulo 	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
312d4f2939cSRui Paulo 		goto error;
313d4f2939cSRui Paulo 
314d4f2939cSRui Paulo 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
315d4f2939cSRui Paulo 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
316d4f2939cSRui Paulo 			goto error;
317d4f2939cSRui Paulo 
3185b9c547cSRui Paulo 		if (os_strcmp(entry.key, "duration1") == 0 &&
3195b9c547cSRui Paulo 		    entry.type == DBUS_TYPE_INT32)
320d4f2939cSRui Paulo 			dur1 = entry.uint32_value;
3215b9c547cSRui Paulo 		else if (os_strcmp(entry.key, "interval1") == 0 &&
322d4f2939cSRui Paulo 			 entry.type == DBUS_TYPE_INT32)
323d4f2939cSRui Paulo 			int1 = entry.uint32_value;
3245b9c547cSRui Paulo 		else if (os_strcmp(entry.key, "duration2") == 0 &&
325d4f2939cSRui Paulo 			 entry.type == DBUS_TYPE_INT32)
326d4f2939cSRui Paulo 			dur2 = entry.uint32_value;
3275b9c547cSRui Paulo 		else if (os_strcmp(entry.key, "interval2") == 0 &&
328d4f2939cSRui Paulo 			 entry.type == DBUS_TYPE_INT32)
329d4f2939cSRui Paulo 			int2 = entry.uint32_value;
330d4f2939cSRui Paulo 		else
331d4f2939cSRui Paulo 			goto error_clear;
332d4f2939cSRui Paulo 
333d4f2939cSRui Paulo 		wpa_dbus_dict_entry_clear(&entry);
334d4f2939cSRui Paulo 	}
3355b9c547cSRui Paulo 
336d4f2939cSRui Paulo 	if (wpas_p2p_presence_req(wpa_s, dur1, int1, dur2, int2) < 0)
337d4f2939cSRui Paulo 		return wpas_dbus_error_unknown_error(message,
338d4f2939cSRui Paulo 				"Failed to invoke presence request.");
339d4f2939cSRui Paulo 
340d4f2939cSRui Paulo 	return NULL;
341d4f2939cSRui Paulo 
342d4f2939cSRui Paulo error_clear:
343d4f2939cSRui Paulo 	wpa_dbus_dict_entry_clear(&entry);
344d4f2939cSRui Paulo error:
345d4f2939cSRui Paulo 	return wpas_dbus_error_invalid_args(message, entry.key);
346d4f2939cSRui Paulo }
347d4f2939cSRui Paulo 
348d4f2939cSRui Paulo 
wpas_dbus_handler_p2p_group_add(DBusMessage * message,struct wpa_supplicant * wpa_s)349d4f2939cSRui Paulo DBusMessage * wpas_dbus_handler_p2p_group_add(DBusMessage *message,
350d4f2939cSRui Paulo 					      struct wpa_supplicant *wpa_s)
351d4f2939cSRui Paulo {
352d4f2939cSRui Paulo 	DBusMessageIter iter_dict;
353d4f2939cSRui Paulo 	DBusMessage *reply = NULL;
354d4f2939cSRui Paulo 	DBusMessageIter iter;
355d4f2939cSRui Paulo 	struct wpa_dbus_dict_entry entry;
356d4f2939cSRui Paulo 	char *pg_object_path = NULL;
357d4f2939cSRui Paulo 	int persistent_group = 0;
358d4f2939cSRui Paulo 	int freq = 0;
359*a90b9d01SCy Schubert 	int retry_limit = 0;
360d4f2939cSRui Paulo 	char *iface = NULL;
361d4f2939cSRui Paulo 	unsigned int group_id = 0;
362d4f2939cSRui Paulo 	struct wpa_ssid *ssid;
363*a90b9d01SCy Schubert 	u8 go_bssid_buf[ETH_ALEN], *go_bssid = NULL;
364*a90b9d01SCy Schubert 	bool allow_6ghz = false;
365*a90b9d01SCy Schubert 	int vht = wpa_s->conf->p2p_go_vht;
366*a90b9d01SCy Schubert 	int ht40 = wpa_s->conf->p2p_go_ht40 || vht;
367*a90b9d01SCy Schubert 	int he = wpa_s->conf->p2p_go_he;
368*a90b9d01SCy Schubert 	int edmg = wpa_s->conf->p2p_go_edmg;
369*a90b9d01SCy Schubert 	int max_oper_chwidth, chwidth = 0, freq2 = 0;
370d4f2939cSRui Paulo 
371d4f2939cSRui Paulo 	dbus_message_iter_init(message, &iter);
372d4f2939cSRui Paulo 
373d4f2939cSRui Paulo 	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
374d4f2939cSRui Paulo 		goto inv_args;
375d4f2939cSRui Paulo 
376d4f2939cSRui Paulo 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
377d4f2939cSRui Paulo 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
378d4f2939cSRui Paulo 			goto inv_args;
379d4f2939cSRui Paulo 
3805b9c547cSRui Paulo 		if (os_strcmp(entry.key, "persistent") == 0 &&
3815b9c547cSRui Paulo 		    entry.type == DBUS_TYPE_BOOLEAN) {
3825b9c547cSRui Paulo 			persistent_group = entry.bool_value;
3835b9c547cSRui Paulo 		} else if (os_strcmp(entry.key, "frequency") == 0 &&
3845b9c547cSRui Paulo 			   entry.type == DBUS_TYPE_INT32) {
385d4f2939cSRui Paulo 			freq = entry.int32_value;
386d4f2939cSRui Paulo 			if (freq <= 0)
387d4f2939cSRui Paulo 				goto inv_args_clear;
388*a90b9d01SCy Schubert 		} else if (os_strcmp(entry.key, "retry_limit") == 0 &&
389*a90b9d01SCy Schubert 			   entry.type == DBUS_TYPE_INT32) {
390*a90b9d01SCy Schubert 			retry_limit = entry.int32_value;
391*a90b9d01SCy Schubert 			if (retry_limit <= 0)
392*a90b9d01SCy Schubert 				goto inv_args_clear;
3935b9c547cSRui Paulo 		} else if (os_strcmp(entry.key, "persistent_group_object") ==
3945b9c547cSRui Paulo 			   0 &&
395*a90b9d01SCy Schubert 			   entry.type == DBUS_TYPE_OBJECT_PATH) {
396d4f2939cSRui Paulo 			pg_object_path = os_strdup(entry.str_value);
397*a90b9d01SCy Schubert 		} else if (os_strcmp(entry.key, "go_bssid") == 0 &&
398*a90b9d01SCy Schubert 			   entry.type == DBUS_TYPE_STRING) {
399*a90b9d01SCy Schubert 			if (hwaddr_aton(entry.str_value, go_bssid_buf))
400d4f2939cSRui Paulo 				goto inv_args_clear;
401*a90b9d01SCy Schubert 			go_bssid = go_bssid_buf;
402*a90b9d01SCy Schubert 		} else if (os_strcmp(entry.key, "ht40") == 0 &&
403*a90b9d01SCy Schubert 			   entry.type == DBUS_TYPE_BOOLEAN) {
404*a90b9d01SCy Schubert 			ht40 = entry.bool_value;
405*a90b9d01SCy Schubert 		} else if (os_strcmp(entry.key, "vht") == 0 &&
406*a90b9d01SCy Schubert 			   entry.type == DBUS_TYPE_BOOLEAN) {
407*a90b9d01SCy Schubert 			vht = entry.bool_value;
408*a90b9d01SCy Schubert 			ht40 |= vht;
409*a90b9d01SCy Schubert 		} else if (os_strcmp(entry.key, "he") == 0 &&
410*a90b9d01SCy Schubert 			   entry.type == DBUS_TYPE_BOOLEAN) {
411*a90b9d01SCy Schubert 			he = entry.bool_value;
412*a90b9d01SCy Schubert 		} else if (os_strcmp(entry.key, "edmg") == 0 &&
413*a90b9d01SCy Schubert 			   entry.type == DBUS_TYPE_BOOLEAN) {
414*a90b9d01SCy Schubert 			edmg = entry.bool_value;
415*a90b9d01SCy Schubert 		} else if (os_strcmp(entry.key, "allow_6ghz") == 0 &&
416*a90b9d01SCy Schubert 			   entry.type == DBUS_TYPE_BOOLEAN) {
417*a90b9d01SCy Schubert 			allow_6ghz = entry.bool_value;
418*a90b9d01SCy Schubert 		} else if (os_strcmp(entry.key, "freq2") == 0 &&
419*a90b9d01SCy Schubert 			   entry.type == DBUS_TYPE_INT32) {
420*a90b9d01SCy Schubert 			freq2 = entry.int32_value;
421*a90b9d01SCy Schubert 		} else if (os_strcmp(entry.key, "max_oper_chwidth") == 0 &&
422*a90b9d01SCy Schubert 			   entry.type == DBUS_TYPE_INT32) {
423*a90b9d01SCy Schubert 			chwidth = entry.int32_value;
424*a90b9d01SCy Schubert 		} else {
425*a90b9d01SCy Schubert 			goto inv_args_clear;
426*a90b9d01SCy Schubert 		}
427d4f2939cSRui Paulo 
428d4f2939cSRui Paulo 		wpa_dbus_dict_entry_clear(&entry);
429d4f2939cSRui Paulo 	}
430d4f2939cSRui Paulo 
431*a90b9d01SCy Schubert 	max_oper_chwidth = chwidth_freq2_to_ch_width(chwidth, freq2);
432*a90b9d01SCy Schubert 	if (max_oper_chwidth < 0)
433*a90b9d01SCy Schubert 		goto inv_args;
434*a90b9d01SCy Schubert 
435*a90b9d01SCy Schubert 	if (allow_6ghz && chwidth == 40)
436*a90b9d01SCy Schubert 		max_oper_chwidth = CONF_OPER_CHWIDTH_40MHZ_6GHZ;
437*a90b9d01SCy Schubert 
438325151a3SRui Paulo 	wpa_s = wpa_s->global->p2p_init_wpa_s;
439c1d255d3SCy Schubert 	if (!wpa_s) {
440c1d255d3SCy Schubert 		reply = wpas_dbus_error_no_p2p_mgmt_iface(message);
441c1d255d3SCy Schubert 		goto out;
442c1d255d3SCy Schubert 	}
4435b9c547cSRui Paulo 
444d4f2939cSRui Paulo 	if (pg_object_path != NULL) {
4455b9c547cSRui Paulo 		char *net_id_str;
4465b9c547cSRui Paulo 
447d4f2939cSRui Paulo 		/*
448d4f2939cSRui Paulo 		 * A persistent group Object Path is defined meaning we want
449d4f2939cSRui Paulo 		 * to re-invoke a persistent group.
450d4f2939cSRui Paulo 		 */
451d4f2939cSRui Paulo 
4525b9c547cSRui Paulo 		iface = wpas_dbus_new_decompose_object_path(
4535b9c547cSRui Paulo 			pg_object_path, WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART,
4545b9c547cSRui Paulo 			&net_id_str);
4555b9c547cSRui Paulo 		if (iface == NULL || net_id_str == NULL ||
456325151a3SRui Paulo 		    !wpa_s->parent->dbus_new_path ||
457325151a3SRui Paulo 		    os_strcmp(iface, wpa_s->parent->dbus_new_path) != 0) {
458d4f2939cSRui Paulo 			reply =
459d4f2939cSRui Paulo 			    wpas_dbus_error_invalid_args(message,
460d4f2939cSRui Paulo 							 pg_object_path);
461d4f2939cSRui Paulo 			goto out;
462d4f2939cSRui Paulo 		}
463d4f2939cSRui Paulo 
464d4f2939cSRui Paulo 		group_id = strtoul(net_id_str, NULL, 10);
465d4f2939cSRui Paulo 		if (errno == EINVAL) {
466d4f2939cSRui Paulo 			reply = wpas_dbus_error_invalid_args(
467d4f2939cSRui Paulo 						message, pg_object_path);
468d4f2939cSRui Paulo 			goto out;
469d4f2939cSRui Paulo 		}
470d4f2939cSRui Paulo 
471d4f2939cSRui Paulo 		/* Get the SSID structure from the persistent group id */
472d4f2939cSRui Paulo 		ssid = wpa_config_get_network(wpa_s->conf, group_id);
473d4f2939cSRui Paulo 		if (ssid == NULL || ssid->disabled != 2)
474d4f2939cSRui Paulo 			goto inv_args;
475d4f2939cSRui Paulo 
476*a90b9d01SCy Schubert 		if (wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 0,
477*a90b9d01SCy Schubert 						  freq2, ht40, vht,
478*a90b9d01SCy Schubert 						  max_oper_chwidth, he, edmg,
479*a90b9d01SCy Schubert 						  NULL, 0, 0, allow_6ghz,
480*a90b9d01SCy Schubert 						  retry_limit, go_bssid)) {
481d4f2939cSRui Paulo 			reply = wpas_dbus_error_unknown_error(
482d4f2939cSRui Paulo 				message,
483d4f2939cSRui Paulo 				"Failed to reinvoke a persistent group");
484d4f2939cSRui Paulo 			goto out;
485d4f2939cSRui Paulo 		}
486*a90b9d01SCy Schubert 	} else if (wpas_p2p_group_add(wpa_s, persistent_group, freq, freq2,
487*a90b9d01SCy Schubert 				      ht40, vht, max_oper_chwidth, he, edmg,
488*a90b9d01SCy Schubert 				      allow_6ghz))
489d4f2939cSRui Paulo 		goto inv_args;
490d4f2939cSRui Paulo 
491d4f2939cSRui Paulo out:
492d4f2939cSRui Paulo 	os_free(pg_object_path);
493d4f2939cSRui Paulo 	os_free(iface);
494d4f2939cSRui Paulo 	return reply;
495d4f2939cSRui Paulo inv_args_clear:
496d4f2939cSRui Paulo 	wpa_dbus_dict_entry_clear(&entry);
497d4f2939cSRui Paulo inv_args:
498d4f2939cSRui Paulo 	reply = wpas_dbus_error_invalid_args(message, NULL);
499d4f2939cSRui Paulo 	goto out;
500d4f2939cSRui Paulo }
501d4f2939cSRui Paulo 
502d4f2939cSRui Paulo 
wpas_dbus_handler_p2p_disconnect(DBusMessage * message,struct wpa_supplicant * wpa_s)503d4f2939cSRui Paulo DBusMessage * wpas_dbus_handler_p2p_disconnect(DBusMessage *message,
504d4f2939cSRui Paulo 					       struct wpa_supplicant *wpa_s)
505d4f2939cSRui Paulo {
506d4f2939cSRui Paulo 	if (wpas_p2p_disconnect(wpa_s))
507d4f2939cSRui Paulo 		return wpas_dbus_error_unknown_error(message,
508d4f2939cSRui Paulo 						"failed to disconnect");
509d4f2939cSRui Paulo 
510d4f2939cSRui Paulo 	return NULL;
511d4f2939cSRui Paulo }
512d4f2939cSRui Paulo 
513d4f2939cSRui Paulo 
wpa_dbus_p2p_check_enabled(struct wpa_supplicant * wpa_s,DBusMessage * message,DBusMessage ** out_reply,DBusError * error)514d4f2939cSRui Paulo static dbus_bool_t wpa_dbus_p2p_check_enabled(struct wpa_supplicant *wpa_s,
515d4f2939cSRui Paulo 					      DBusMessage *message,
516d4f2939cSRui Paulo 					      DBusMessage **out_reply,
517d4f2939cSRui Paulo 					      DBusError *error)
518d4f2939cSRui Paulo {
519d4f2939cSRui Paulo 	/* Return an error message or an error if P2P isn't available */
520d4f2939cSRui Paulo 	if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL) {
521d4f2939cSRui Paulo 		if (out_reply) {
522d4f2939cSRui Paulo 			*out_reply = dbus_message_new_error(
523d4f2939cSRui Paulo 				message, DBUS_ERROR_FAILED,
524d4f2939cSRui Paulo 				"P2P is not available for this interface");
525d4f2939cSRui Paulo 		}
526d4f2939cSRui Paulo 		dbus_set_error_const(error, DBUS_ERROR_FAILED,
5275b9c547cSRui Paulo 				     "P2P is not available for this interface");
528d4f2939cSRui Paulo 		return FALSE;
529d4f2939cSRui Paulo 	}
530c1d255d3SCy Schubert 	if (!wpa_s->global->p2p_init_wpa_s) {
531c1d255d3SCy Schubert 		if (out_reply)
532c1d255d3SCy Schubert 			*out_reply = wpas_dbus_error_no_p2p_mgmt_iface(
533c1d255d3SCy Schubert 				message);
534c1d255d3SCy Schubert 		return no_p2p_mgmt_interface(error);
535c1d255d3SCy Schubert 	}
536d4f2939cSRui Paulo 	return TRUE;
537d4f2939cSRui Paulo }
538d4f2939cSRui Paulo 
539d4f2939cSRui Paulo 
wpas_dbus_handler_p2p_remove_client(DBusMessage * message,struct wpa_supplicant * wpa_s)540325151a3SRui Paulo DBusMessage * wpas_dbus_handler_p2p_remove_client(DBusMessage *message,
541325151a3SRui Paulo 						  struct wpa_supplicant *wpa_s)
542325151a3SRui Paulo {
543325151a3SRui Paulo 	DBusMessageIter iter_dict;
544325151a3SRui Paulo 	DBusMessage *reply = NULL;
545325151a3SRui Paulo 	DBusMessageIter iter;
546325151a3SRui Paulo 	struct wpa_dbus_dict_entry entry;
547325151a3SRui Paulo 	char *peer_object_path = NULL;
548325151a3SRui Paulo 	char *interface_addr = NULL;
549325151a3SRui Paulo 	u8 peer_addr[ETH_ALEN];
550325151a3SRui Paulo 
551325151a3SRui Paulo 	if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL))
552325151a3SRui Paulo 		return reply;
553325151a3SRui Paulo 
554325151a3SRui Paulo 	dbus_message_iter_init(message, &iter);
555325151a3SRui Paulo 
556325151a3SRui Paulo 	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
557325151a3SRui Paulo 		goto err;
558325151a3SRui Paulo 
559325151a3SRui Paulo 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
560325151a3SRui Paulo 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
561325151a3SRui Paulo 			goto err;
562325151a3SRui Paulo 
563325151a3SRui Paulo 		if (os_strcmp(entry.key, "peer") == 0 &&
564325151a3SRui Paulo 		    entry.type == DBUS_TYPE_OBJECT_PATH) {
565325151a3SRui Paulo 			os_free(peer_object_path);
566325151a3SRui Paulo 			peer_object_path = os_strdup(entry.str_value);
567325151a3SRui Paulo 			wpa_dbus_dict_entry_clear(&entry);
568325151a3SRui Paulo 		} else if (os_strcmp(entry.key, "iface") == 0 &&
569325151a3SRui Paulo 			   entry.type == DBUS_TYPE_STRING) {
570325151a3SRui Paulo 			os_free(interface_addr);
571325151a3SRui Paulo 			interface_addr = os_strdup(entry.str_value);
572325151a3SRui Paulo 			wpa_dbus_dict_entry_clear(&entry);
573325151a3SRui Paulo 		} else {
574325151a3SRui Paulo 			wpa_dbus_dict_entry_clear(&entry);
575325151a3SRui Paulo 			goto err;
576325151a3SRui Paulo 		}
577325151a3SRui Paulo 	}
578325151a3SRui Paulo 
579325151a3SRui Paulo 	if ((!peer_object_path && !interface_addr) ||
580325151a3SRui Paulo 	    (peer_object_path &&
581325151a3SRui Paulo 	     (parse_peer_object_path(peer_object_path, peer_addr) < 0 ||
582325151a3SRui Paulo 	      !p2p_peer_known(wpa_s->global->p2p, peer_addr))) ||
583325151a3SRui Paulo 	    (interface_addr && hwaddr_aton(interface_addr, peer_addr) < 0))
584325151a3SRui Paulo 		goto err;
585325151a3SRui Paulo 
586325151a3SRui Paulo 	wpas_p2p_remove_client(wpa_s, peer_addr, interface_addr != NULL);
587325151a3SRui Paulo 	reply = NULL;
588325151a3SRui Paulo out:
589325151a3SRui Paulo 	os_free(peer_object_path);
590325151a3SRui Paulo 	os_free(interface_addr);
591325151a3SRui Paulo 	return reply;
592325151a3SRui Paulo err:
593325151a3SRui Paulo 	reply = wpas_dbus_error_invalid_args(message, "Invalid address format");
594325151a3SRui Paulo 	goto out;
595325151a3SRui Paulo }
596325151a3SRui Paulo 
597325151a3SRui Paulo 
wpas_dbus_handler_p2p_flush(DBusMessage * message,struct wpa_supplicant * wpa_s)598d4f2939cSRui Paulo DBusMessage * wpas_dbus_handler_p2p_flush(DBusMessage *message,
599d4f2939cSRui Paulo 					  struct wpa_supplicant *wpa_s)
600d4f2939cSRui Paulo {
601d4f2939cSRui Paulo 	DBusMessage *reply = NULL;
602d4f2939cSRui Paulo 
603d4f2939cSRui Paulo 	if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL))
604d4f2939cSRui Paulo 		return reply;
605d4f2939cSRui Paulo 
606325151a3SRui Paulo 	wpa_s = wpa_s->global->p2p_init_wpa_s;
6075b9c547cSRui Paulo 
6084bc52338SCy Schubert 	wpas_p2p_stop_find(wpa_s);
609d4f2939cSRui Paulo 	os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
610d4f2939cSRui Paulo 	wpa_s->force_long_sd = 0;
611d4f2939cSRui Paulo 	p2p_flush(wpa_s->global->p2p);
612d4f2939cSRui Paulo 
613d4f2939cSRui Paulo 	return NULL;
614d4f2939cSRui Paulo }
615d4f2939cSRui Paulo 
616d4f2939cSRui Paulo 
wpas_dbus_handler_p2p_connect(DBusMessage * message,struct wpa_supplicant * wpa_s)617d4f2939cSRui Paulo DBusMessage * wpas_dbus_handler_p2p_connect(DBusMessage *message,
618d4f2939cSRui Paulo 					    struct wpa_supplicant *wpa_s)
619d4f2939cSRui Paulo {
620d4f2939cSRui Paulo 	DBusMessageIter iter_dict;
621d4f2939cSRui Paulo 	DBusMessage *reply = NULL;
622d4f2939cSRui Paulo 	DBusMessageIter iter;
623d4f2939cSRui Paulo 	struct wpa_dbus_dict_entry entry;
624d4f2939cSRui Paulo 	char *peer_object_path = NULL;
625d4f2939cSRui Paulo 	int persistent_group = 0;
626d4f2939cSRui Paulo 	int join = 0;
627d4f2939cSRui Paulo 	int authorize_only = 0;
628d4f2939cSRui Paulo 	int go_intent = -1;
629d4f2939cSRui Paulo 	int freq = 0;
630d4f2939cSRui Paulo 	u8 addr[ETH_ALEN];
631d4f2939cSRui Paulo 	char *pin = NULL;
632d4f2939cSRui Paulo 	enum p2p_wps_method wps_method = WPS_NOT_READY;
633d4f2939cSRui Paulo 	int new_pin;
634d4f2939cSRui Paulo 	char *err_msg = NULL;
635d4f2939cSRui Paulo 	char *iface = NULL;
6364bc52338SCy Schubert 	int ret;
637d4f2939cSRui Paulo 
638d4f2939cSRui Paulo 	if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL))
639d4f2939cSRui Paulo 		return reply;
640d4f2939cSRui Paulo 
641d4f2939cSRui Paulo 	dbus_message_iter_init(message, &iter);
642d4f2939cSRui Paulo 
643d4f2939cSRui Paulo 	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
644d4f2939cSRui Paulo 		goto inv_args;
645d4f2939cSRui Paulo 
646d4f2939cSRui Paulo 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
647d4f2939cSRui Paulo 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
648d4f2939cSRui Paulo 			goto inv_args;
649d4f2939cSRui Paulo 
6505b9c547cSRui Paulo 		if (os_strcmp(entry.key, "peer") == 0 &&
6515b9c547cSRui Paulo 		    entry.type == DBUS_TYPE_OBJECT_PATH) {
652d4f2939cSRui Paulo 			peer_object_path = os_strdup(entry.str_value);
6535b9c547cSRui Paulo 		} else if (os_strcmp(entry.key, "persistent") == 0 &&
6545b9c547cSRui Paulo 			   entry.type == DBUS_TYPE_BOOLEAN) {
6555b9c547cSRui Paulo 			persistent_group = entry.bool_value;
6565b9c547cSRui Paulo 		} else if (os_strcmp(entry.key, "join") == 0 &&
6575b9c547cSRui Paulo 			   entry.type == DBUS_TYPE_BOOLEAN) {
6585b9c547cSRui Paulo 			join = entry.bool_value;
6595b9c547cSRui Paulo 		} else if (os_strcmp(entry.key, "authorize_only") == 0 &&
6605b9c547cSRui Paulo 			   entry.type == DBUS_TYPE_BOOLEAN) {
6615b9c547cSRui Paulo 			authorize_only = entry.bool_value;
6625b9c547cSRui Paulo 		} else if (os_strcmp(entry.key, "frequency") == 0 &&
6635b9c547cSRui Paulo 			   entry.type == DBUS_TYPE_INT32) {
664d4f2939cSRui Paulo 			freq = entry.int32_value;
665d4f2939cSRui Paulo 			if (freq <= 0)
666d4f2939cSRui Paulo 				goto inv_args_clear;
6675b9c547cSRui Paulo 		} else if (os_strcmp(entry.key, "go_intent") == 0 &&
6685b9c547cSRui Paulo 			   entry.type == DBUS_TYPE_INT32) {
669d4f2939cSRui Paulo 			go_intent = entry.int32_value;
670d4f2939cSRui Paulo 			if ((go_intent < 0) || (go_intent > 15))
671d4f2939cSRui Paulo 				goto inv_args_clear;
6725b9c547cSRui Paulo 		} else if (os_strcmp(entry.key, "wps_method") == 0 &&
6735b9c547cSRui Paulo 			   entry.type == DBUS_TYPE_STRING) {
6745b9c547cSRui Paulo 			if (os_strcmp(entry.str_value, "pbc") == 0)
675d4f2939cSRui Paulo 				wps_method = WPS_PBC;
6765b9c547cSRui Paulo 			else if (os_strcmp(entry.str_value, "pin") == 0)
677d4f2939cSRui Paulo 				wps_method = WPS_PIN_DISPLAY;
6785b9c547cSRui Paulo 			else if (os_strcmp(entry.str_value, "display") == 0)
679d4f2939cSRui Paulo 				wps_method = WPS_PIN_DISPLAY;
6805b9c547cSRui Paulo 			else if (os_strcmp(entry.str_value, "keypad") == 0)
681d4f2939cSRui Paulo 				wps_method = WPS_PIN_KEYPAD;
682d4f2939cSRui Paulo 			else
683d4f2939cSRui Paulo 				goto inv_args_clear;
6845b9c547cSRui Paulo 		} else if (os_strcmp(entry.key, "pin") == 0 &&
6855b9c547cSRui Paulo 			   entry.type == DBUS_TYPE_STRING) {
686d4f2939cSRui Paulo 			pin = os_strdup(entry.str_value);
687d4f2939cSRui Paulo 		} else
688d4f2939cSRui Paulo 			goto inv_args_clear;
689d4f2939cSRui Paulo 
690d4f2939cSRui Paulo 		wpa_dbus_dict_entry_clear(&entry);
691d4f2939cSRui Paulo 	}
692d4f2939cSRui Paulo 
6935b9c547cSRui Paulo 	if (wps_method == WPS_NOT_READY ||
6945b9c547cSRui Paulo 	    parse_peer_object_path(peer_object_path, addr) < 0 ||
695d4f2939cSRui Paulo 	    !p2p_peer_known(wpa_s->global->p2p, addr))
696d4f2939cSRui Paulo 		goto inv_args;
697d4f2939cSRui Paulo 
698d4f2939cSRui Paulo 	/*
699d4f2939cSRui Paulo 	 * Validate the wps_method specified and the pin value.
700d4f2939cSRui Paulo 	 */
7015b9c547cSRui Paulo 	if ((!pin || !pin[0]) && wps_method == WPS_PIN_KEYPAD)
702d4f2939cSRui Paulo 		goto inv_args;
703d4f2939cSRui Paulo 
704325151a3SRui Paulo 	wpa_s = wpa_s->global->p2p_init_wpa_s;
7055b9c547cSRui Paulo 
706d4f2939cSRui Paulo 	new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
707d4f2939cSRui Paulo 				   persistent_group, 0, join, authorize_only,
708c1d255d3SCy Schubert 				   go_intent, freq, 0, -1, 0, 0, 0, 0, 0, 0,
709c1d255d3SCy Schubert 				   NULL, 0, false);
710d4f2939cSRui Paulo 
711d4f2939cSRui Paulo 	if (new_pin >= 0) {
712d4f2939cSRui Paulo 		char npin[9];
713d4f2939cSRui Paulo 		char *generated_pin;
7145b9c547cSRui Paulo 
7154bc52338SCy Schubert 		ret = os_snprintf(npin, sizeof(npin), "%08d", new_pin);
7164bc52338SCy Schubert 		if (os_snprintf_error(sizeof(npin), ret)) {
7174bc52338SCy Schubert 			reply = wpas_dbus_error_unknown_error(message,
7184bc52338SCy Schubert 							      "invalid PIN");
7194bc52338SCy Schubert 			goto out;
7204bc52338SCy Schubert 		}
721d4f2939cSRui Paulo 		generated_pin = npin;
722d4f2939cSRui Paulo 		reply = dbus_message_new_method_return(message);
723d4f2939cSRui Paulo 		dbus_message_append_args(reply, DBUS_TYPE_STRING,
724d4f2939cSRui Paulo 					 &generated_pin, DBUS_TYPE_INVALID);
725d4f2939cSRui Paulo 	} else {
726d4f2939cSRui Paulo 		switch (new_pin) {
727d4f2939cSRui Paulo 		case -2:
7285b9c547cSRui Paulo 			err_msg =
7295b9c547cSRui Paulo 				"connect failed due to channel unavailability.";
730d4f2939cSRui Paulo 			iface = WPAS_DBUS_ERROR_CONNECT_CHANNEL_UNAVAILABLE;
731d4f2939cSRui Paulo 			break;
732d4f2939cSRui Paulo 
733d4f2939cSRui Paulo 		case -3:
734d4f2939cSRui Paulo 			err_msg = "connect failed due to unsupported channel.";
735d4f2939cSRui Paulo 			iface = WPAS_DBUS_ERROR_CONNECT_CHANNEL_UNSUPPORTED;
736d4f2939cSRui Paulo 			break;
737d4f2939cSRui Paulo 
738d4f2939cSRui Paulo 		default:
739d4f2939cSRui Paulo 			err_msg = "connect failed due to unspecified error.";
740d4f2939cSRui Paulo 			iface = WPAS_DBUS_ERROR_CONNECT_UNSPECIFIED_ERROR;
741d4f2939cSRui Paulo 			break;
742d4f2939cSRui Paulo 		}
743d4f2939cSRui Paulo 
744d4f2939cSRui Paulo 		/*
745d4f2939cSRui Paulo 		 * TODO:
746d4f2939cSRui Paulo 		 * Do we need specialized errors corresponding to above
747d4f2939cSRui Paulo 		 * error conditions as against just returning a different
748d4f2939cSRui Paulo 		 * error message?
749d4f2939cSRui Paulo 		 */
750d4f2939cSRui Paulo 		reply = dbus_message_new_error(message, iface, err_msg);
751d4f2939cSRui Paulo 	}
752d4f2939cSRui Paulo 
753d4f2939cSRui Paulo out:
754d4f2939cSRui Paulo 	os_free(peer_object_path);
755d4f2939cSRui Paulo 	os_free(pin);
756d4f2939cSRui Paulo 	return reply;
757d4f2939cSRui Paulo inv_args_clear:
758d4f2939cSRui Paulo 	wpa_dbus_dict_entry_clear(&entry);
759d4f2939cSRui Paulo inv_args:
760d4f2939cSRui Paulo 	reply = wpas_dbus_error_invalid_args(message, NULL);
761d4f2939cSRui Paulo 	goto out;
762d4f2939cSRui Paulo }
763d4f2939cSRui Paulo 
764d4f2939cSRui Paulo 
765325151a3SRui Paulo /**
766325151a3SRui Paulo  * wpas_dbus_handler_p2p_cancel - Cancel P2P group formation
767325151a3SRui Paulo  * @message: Pointer to incoming dbus message
768325151a3SRui Paulo  * @wpa_s: %wpa_supplicant data structure
769325151a3SRui Paulo  * Returns: NULL on success or DBus error on failure
770325151a3SRui Paulo  *
771325151a3SRui Paulo  * Handler for "Cancel" method call. Returns NULL if P2P cancel succeeds or DBus
772325151a3SRui Paulo  * error on P2P cancel failure
773325151a3SRui Paulo  */
wpas_dbus_handler_p2p_cancel(DBusMessage * message,struct wpa_supplicant * wpa_s)774325151a3SRui Paulo DBusMessage * wpas_dbus_handler_p2p_cancel(DBusMessage *message,
775325151a3SRui Paulo 					   struct wpa_supplicant *wpa_s)
776325151a3SRui Paulo {
777325151a3SRui Paulo 	if (wpas_p2p_cancel(wpa_s))
778325151a3SRui Paulo 		return wpas_dbus_error_unknown_error(message,
779325151a3SRui Paulo 						     "P2P cancel failed");
780325151a3SRui Paulo 
781325151a3SRui Paulo 	return NULL;
782325151a3SRui Paulo }
783325151a3SRui Paulo 
784325151a3SRui Paulo 
wpas_dbus_handler_p2p_invite(DBusMessage * message,struct wpa_supplicant * wpa_s)785d4f2939cSRui Paulo DBusMessage * wpas_dbus_handler_p2p_invite(DBusMessage *message,
786d4f2939cSRui Paulo 					   struct wpa_supplicant *wpa_s)
787d4f2939cSRui Paulo {
788d4f2939cSRui Paulo 	DBusMessageIter iter_dict;
789d4f2939cSRui Paulo 	DBusMessage *reply = NULL;
790d4f2939cSRui Paulo 	DBusMessageIter iter;
791d4f2939cSRui Paulo 	struct wpa_dbus_dict_entry entry;
792d4f2939cSRui Paulo 	char *peer_object_path = NULL;
793d4f2939cSRui Paulo 	char *pg_object_path = NULL;
794d4f2939cSRui Paulo 	char *iface = NULL;
795d4f2939cSRui Paulo 	u8 peer_addr[ETH_ALEN];
796d4f2939cSRui Paulo 	unsigned int group_id = 0;
797d4f2939cSRui Paulo 	int persistent = 0;
798d4f2939cSRui Paulo 	struct wpa_ssid *ssid;
79932a95656SCy Schubert 	const char *group_ifname;
800d4f2939cSRui Paulo 
801d4f2939cSRui Paulo 	if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL))
802d4f2939cSRui Paulo 		return reply;
803d4f2939cSRui Paulo 
804d4f2939cSRui Paulo 	dbus_message_iter_init(message, &iter);
805d4f2939cSRui Paulo 
806d4f2939cSRui Paulo 	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
807d4f2939cSRui Paulo 		goto err;
808d4f2939cSRui Paulo 
809d4f2939cSRui Paulo 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
810d4f2939cSRui Paulo 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
811d4f2939cSRui Paulo 			goto err;
812d4f2939cSRui Paulo 
8135b9c547cSRui Paulo 		if (os_strcmp(entry.key, "peer") == 0 &&
8145b9c547cSRui Paulo 		    entry.type == DBUS_TYPE_OBJECT_PATH) {
815d4f2939cSRui Paulo 			peer_object_path = os_strdup(entry.str_value);
816d4f2939cSRui Paulo 			wpa_dbus_dict_entry_clear(&entry);
8175b9c547cSRui Paulo 		} else if (os_strcmp(entry.key, "persistent_group_object") ==
8185b9c547cSRui Paulo 			   0 &&
8195b9c547cSRui Paulo 			   entry.type == DBUS_TYPE_OBJECT_PATH) {
820d4f2939cSRui Paulo 			pg_object_path = os_strdup(entry.str_value);
821d4f2939cSRui Paulo 			persistent = 1;
822d4f2939cSRui Paulo 			wpa_dbus_dict_entry_clear(&entry);
823d4f2939cSRui Paulo 		} else {
824d4f2939cSRui Paulo 			wpa_dbus_dict_entry_clear(&entry);
825d4f2939cSRui Paulo 			goto err;
826d4f2939cSRui Paulo 		}
827d4f2939cSRui Paulo 	}
828d4f2939cSRui Paulo 
8295b9c547cSRui Paulo 	if (parse_peer_object_path(peer_object_path, peer_addr) < 0 ||
8305b9c547cSRui Paulo 	    !p2p_peer_known(wpa_s->global->p2p, peer_addr))
831d4f2939cSRui Paulo 		goto err;
8325b9c547cSRui Paulo 
83332a95656SCy Schubert 	/* Capture the interface name for the group first */
83432a95656SCy Schubert 	group_ifname = wpa_s->ifname;
835325151a3SRui Paulo 	wpa_s = wpa_s->global->p2p_init_wpa_s;
836d4f2939cSRui Paulo 
837d4f2939cSRui Paulo 	if (persistent) {
8385b9c547cSRui Paulo 		char *net_id_str;
839d4f2939cSRui Paulo 		/*
840d4f2939cSRui Paulo 		 * A group ID is defined meaning we want to re-invoke a
841d4f2939cSRui Paulo 		 * persistent group
842d4f2939cSRui Paulo 		 */
843d4f2939cSRui Paulo 
8445b9c547cSRui Paulo 		iface = wpas_dbus_new_decompose_object_path(
8455b9c547cSRui Paulo 			pg_object_path,
8465b9c547cSRui Paulo 			WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART,
8475b9c547cSRui Paulo 			&net_id_str);
8485b9c547cSRui Paulo 		if (iface == NULL || net_id_str == NULL ||
849325151a3SRui Paulo 		    !wpa_s->parent->dbus_new_path ||
850325151a3SRui Paulo 		    os_strcmp(iface, wpa_s->parent->dbus_new_path) != 0) {
851d4f2939cSRui Paulo 			reply = wpas_dbus_error_invalid_args(message,
852d4f2939cSRui Paulo 							     pg_object_path);
853d4f2939cSRui Paulo 			goto out;
854d4f2939cSRui Paulo 		}
855d4f2939cSRui Paulo 
856d4f2939cSRui Paulo 		group_id = strtoul(net_id_str, NULL, 10);
857d4f2939cSRui Paulo 		if (errno == EINVAL) {
858d4f2939cSRui Paulo 			reply = wpas_dbus_error_invalid_args(
859d4f2939cSRui Paulo 				message, pg_object_path);
860d4f2939cSRui Paulo 			goto out;
861d4f2939cSRui Paulo 		}
862d4f2939cSRui Paulo 
863d4f2939cSRui Paulo 		/* Get the SSID structure from the persistent group id */
864d4f2939cSRui Paulo 		ssid = wpa_config_get_network(wpa_s->conf, group_id);
865d4f2939cSRui Paulo 		if (ssid == NULL || ssid->disabled != 2)
866d4f2939cSRui Paulo 			goto err;
867d4f2939cSRui Paulo 
868780fb4a2SCy Schubert 		if (wpas_p2p_invite(wpa_s, peer_addr, ssid, NULL, 0, 0, 0, 0, 0,
869c1d255d3SCy Schubert 				    0, 0, 0, false) < 0) {
870d4f2939cSRui Paulo 			reply = wpas_dbus_error_unknown_error(
871d4f2939cSRui Paulo 				message,
872d4f2939cSRui Paulo 				"Failed to reinvoke a persistent group");
873d4f2939cSRui Paulo 			goto out;
874d4f2939cSRui Paulo 		}
875d4f2939cSRui Paulo 	} else {
876d4f2939cSRui Paulo 		/*
877d4f2939cSRui Paulo 		 * No group ID means propose to a peer to join my active group
878d4f2939cSRui Paulo 		 */
87932a95656SCy Schubert 		if (wpas_p2p_invite_group(wpa_s, group_ifname,
880c1d255d3SCy Schubert 					  peer_addr, NULL, false)) {
881d4f2939cSRui Paulo 			reply = wpas_dbus_error_unknown_error(
882d4f2939cSRui Paulo 				message, "Failed to join to an active group");
883d4f2939cSRui Paulo 			goto out;
884d4f2939cSRui Paulo 		}
885d4f2939cSRui Paulo 	}
886d4f2939cSRui Paulo 
887d4f2939cSRui Paulo out:
8885b9c547cSRui Paulo 	os_free(iface);
889d4f2939cSRui Paulo 	os_free(pg_object_path);
890d4f2939cSRui Paulo 	os_free(peer_object_path);
891d4f2939cSRui Paulo 	return reply;
892d4f2939cSRui Paulo 
893d4f2939cSRui Paulo err:
894d4f2939cSRui Paulo 	reply = wpas_dbus_error_invalid_args(message, NULL);
895d4f2939cSRui Paulo 	goto out;
896d4f2939cSRui Paulo }
897d4f2939cSRui Paulo 
898d4f2939cSRui Paulo 
wpas_dbus_handler_p2p_prov_disc_req(DBusMessage * message,struct wpa_supplicant * wpa_s)899d4f2939cSRui Paulo DBusMessage * wpas_dbus_handler_p2p_prov_disc_req(DBusMessage *message,
900d4f2939cSRui Paulo 						  struct wpa_supplicant *wpa_s)
901d4f2939cSRui Paulo {
902d4f2939cSRui Paulo 	DBusMessageIter iter;
903d4f2939cSRui Paulo 	char *peer_object_path = NULL;
904d4f2939cSRui Paulo 	char *config_method = NULL;
905d4f2939cSRui Paulo 	u8 peer_addr[ETH_ALEN];
906d4f2939cSRui Paulo 
907d4f2939cSRui Paulo 	dbus_message_iter_init(message, &iter);
908d4f2939cSRui Paulo 	dbus_message_iter_get_basic(&iter, &peer_object_path);
909d4f2939cSRui Paulo 
910d4f2939cSRui Paulo 	if (parse_peer_object_path(peer_object_path, peer_addr) < 0)
911d4f2939cSRui Paulo 		return wpas_dbus_error_invalid_args(message, NULL);
912d4f2939cSRui Paulo 
913d4f2939cSRui Paulo 	dbus_message_iter_next(&iter);
914d4f2939cSRui Paulo 	dbus_message_iter_get_basic(&iter, &config_method);
915d4f2939cSRui Paulo 
916d4f2939cSRui Paulo 	/*
917d4f2939cSRui Paulo 	 * Validation checks on config_method are being duplicated here
918d4f2939cSRui Paulo 	 * to be able to return invalid args reply since the error code
919d4f2939cSRui Paulo 	 * from p2p module are not granular enough (yet).
920d4f2939cSRui Paulo 	 */
921d4f2939cSRui Paulo 	if (os_strcmp(config_method, "display") &&
922d4f2939cSRui Paulo 	    os_strcmp(config_method, "keypad") &&
923d4f2939cSRui Paulo 	    os_strcmp(config_method, "pbc") &&
924d4f2939cSRui Paulo 	    os_strcmp(config_method, "pushbutton"))
925d4f2939cSRui Paulo 		return wpas_dbus_error_invalid_args(message, NULL);
926d4f2939cSRui Paulo 
927325151a3SRui Paulo 	wpa_s = wpa_s->global->p2p_init_wpa_s;
928c1d255d3SCy Schubert 	if (!wpa_s)
929c1d255d3SCy Schubert 		return wpas_dbus_error_no_p2p_mgmt_iface(message);
9305b9c547cSRui Paulo 
931d4f2939cSRui Paulo 	if (wpas_p2p_prov_disc(wpa_s, peer_addr, config_method,
9325b9c547cSRui Paulo 			       WPAS_P2P_PD_FOR_GO_NEG, NULL) < 0)
933d4f2939cSRui Paulo 		return wpas_dbus_error_unknown_error(message,
934d4f2939cSRui Paulo 				"Failed to send provision discovery request");
935d4f2939cSRui Paulo 
936d4f2939cSRui Paulo 	return NULL;
937d4f2939cSRui Paulo }
938d4f2939cSRui Paulo 
939d4f2939cSRui Paulo 
940d4f2939cSRui Paulo /*
941d4f2939cSRui Paulo  * P2P Device property accessor methods.
942d4f2939cSRui Paulo  */
943d4f2939cSRui Paulo 
wpas_dbus_getter_p2p_device_config(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)944780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_p2p_device_config(
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_supplicant *wpa_s = user_data;
949d4f2939cSRui Paulo 	DBusMessageIter variant_iter, dict_iter;
950d4f2939cSRui Paulo 	DBusMessageIter iter_secdev_dict_entry, iter_secdev_dict_val,
951d4f2939cSRui Paulo 		iter_secdev_dict_array;
952d4f2939cSRui Paulo 	const char *dev_name;
953d4f2939cSRui Paulo 	int num_vendor_extensions = 0;
954d4f2939cSRui Paulo 	int i;
955d4f2939cSRui Paulo 	const struct wpabuf *vendor_ext[P2P_MAX_WPS_VENDOR_EXT];
956d4f2939cSRui Paulo 
957d4f2939cSRui Paulo 	if (!wpa_dbus_p2p_check_enabled(wpa_s, NULL, NULL, error))
958d4f2939cSRui Paulo 		return FALSE;
959d4f2939cSRui Paulo 
960325151a3SRui Paulo 	wpa_s = wpa_s->global->p2p_init_wpa_s;
9615b9c547cSRui Paulo 
962d4f2939cSRui Paulo 	if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
963d4f2939cSRui Paulo 					      "a{sv}", &variant_iter) ||
964d4f2939cSRui Paulo 	    !wpa_dbus_dict_open_write(&variant_iter, &dict_iter))
965d4f2939cSRui Paulo 		goto err_no_mem;
966d4f2939cSRui Paulo 
967d4f2939cSRui Paulo 	/* DeviceName */
968d4f2939cSRui Paulo 	dev_name = wpa_s->conf->device_name;
969d4f2939cSRui Paulo 	if (dev_name &&
970d4f2939cSRui Paulo 	    !wpa_dbus_dict_append_string(&dict_iter, "DeviceName", dev_name))
971d4f2939cSRui Paulo 		goto err_no_mem;
972d4f2939cSRui Paulo 
973d4f2939cSRui Paulo 	/* Primary device type */
974d4f2939cSRui Paulo 	if (!wpa_dbus_dict_append_byte_array(&dict_iter, "PrimaryDeviceType",
975d4f2939cSRui Paulo 					     (char *) wpa_s->conf->device_type,
976d4f2939cSRui Paulo 					     WPS_DEV_TYPE_LEN))
977d4f2939cSRui Paulo 		goto err_no_mem;
978d4f2939cSRui Paulo 
979d4f2939cSRui Paulo 	/* Secondary device types */
980d4f2939cSRui Paulo 	if (wpa_s->conf->num_sec_device_types) {
981d4f2939cSRui Paulo 		if (!wpa_dbus_dict_begin_array(&dict_iter,
982d4f2939cSRui Paulo 					       "SecondaryDeviceTypes",
983d4f2939cSRui Paulo 					       DBUS_TYPE_ARRAY_AS_STRING
984d4f2939cSRui Paulo 					       DBUS_TYPE_BYTE_AS_STRING,
985d4f2939cSRui Paulo 					       &iter_secdev_dict_entry,
986d4f2939cSRui Paulo 					       &iter_secdev_dict_val,
987d4f2939cSRui Paulo 					       &iter_secdev_dict_array))
988d4f2939cSRui Paulo 			goto err_no_mem;
989d4f2939cSRui Paulo 
990d4f2939cSRui Paulo 		for (i = 0; i < wpa_s->conf->num_sec_device_types; i++)
991d4f2939cSRui Paulo 			wpa_dbus_dict_bin_array_add_element(
992d4f2939cSRui Paulo 				&iter_secdev_dict_array,
993d4f2939cSRui Paulo 				wpa_s->conf->sec_device_type[i],
994d4f2939cSRui Paulo 				WPS_DEV_TYPE_LEN);
995d4f2939cSRui Paulo 
996d4f2939cSRui Paulo 		if (!wpa_dbus_dict_end_array(&dict_iter,
997d4f2939cSRui Paulo 					     &iter_secdev_dict_entry,
998d4f2939cSRui Paulo 					     &iter_secdev_dict_val,
999d4f2939cSRui Paulo 					     &iter_secdev_dict_array))
1000d4f2939cSRui Paulo 			goto err_no_mem;
1001d4f2939cSRui Paulo 	}
1002d4f2939cSRui Paulo 
100385732ac8SCy Schubert 	/* GO IP address */
100485732ac8SCy Schubert 	if (WPA_GET_BE32(wpa_s->conf->ip_addr_go) &&
100585732ac8SCy Schubert 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddrGo",
100685732ac8SCy Schubert 					     (char *) wpa_s->conf->ip_addr_go,
100785732ac8SCy Schubert 					     4))
100885732ac8SCy Schubert 		goto err_no_mem;
100985732ac8SCy Schubert 
101085732ac8SCy Schubert 	/* IP address mask */
101185732ac8SCy Schubert 	if (WPA_GET_BE32(wpa_s->conf->ip_addr_mask) &&
101285732ac8SCy Schubert 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddrMask",
101385732ac8SCy Schubert 					     (char *) wpa_s->conf->ip_addr_mask,
101485732ac8SCy Schubert 					     4))
101585732ac8SCy Schubert 		goto err_no_mem;
101685732ac8SCy Schubert 
101785732ac8SCy Schubert 	/* IP address start */
101885732ac8SCy Schubert 	if (WPA_GET_BE32(wpa_s->conf->ip_addr_start) &&
101985732ac8SCy Schubert 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddrStart",
102085732ac8SCy Schubert 					     (char *)
102185732ac8SCy Schubert 					     wpa_s->conf->ip_addr_start,
102285732ac8SCy Schubert 					     4))
102385732ac8SCy Schubert 		goto err_no_mem;
102485732ac8SCy Schubert 
102585732ac8SCy Schubert 	/* IP address end */
102685732ac8SCy Schubert 	if (WPA_GET_BE32(wpa_s->conf->ip_addr_end) &&
102785732ac8SCy Schubert 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddrEnd",
102885732ac8SCy Schubert 					     (char *) wpa_s->conf->ip_addr_end,
102985732ac8SCy Schubert 					     4))
103085732ac8SCy Schubert 		goto err_no_mem;
103185732ac8SCy Schubert 
1032d4f2939cSRui Paulo 	/* Vendor Extensions */
1033d4f2939cSRui Paulo 	for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
1034d4f2939cSRui Paulo 		if (wpa_s->conf->wps_vendor_ext[i] == NULL)
1035d4f2939cSRui Paulo 			continue;
1036d4f2939cSRui Paulo 		vendor_ext[num_vendor_extensions++] =
1037d4f2939cSRui Paulo 			wpa_s->conf->wps_vendor_ext[i];
1038d4f2939cSRui Paulo 	}
1039d4f2939cSRui Paulo 
10405b9c547cSRui Paulo 	if ((num_vendor_extensions &&
1041d4f2939cSRui Paulo 	     !wpa_dbus_dict_append_wpabuf_array(&dict_iter,
1042d4f2939cSRui Paulo 						"VendorExtension",
1043d4f2939cSRui Paulo 						vendor_ext,
10445b9c547cSRui Paulo 						num_vendor_extensions)) ||
10455b9c547cSRui Paulo 	    !wpa_dbus_dict_append_uint32(&dict_iter, "GOIntent",
10465b9c547cSRui Paulo 					 wpa_s->conf->p2p_go_intent) ||
10475b9c547cSRui Paulo 	    !wpa_dbus_dict_append_bool(&dict_iter, "PersistentReconnect",
10485b9c547cSRui Paulo 				       wpa_s->conf->persistent_reconnect) ||
10495b9c547cSRui Paulo 	    !wpa_dbus_dict_append_uint32(&dict_iter, "ListenRegClass",
10505b9c547cSRui Paulo 					 wpa_s->conf->p2p_listen_reg_class) ||
10515b9c547cSRui Paulo 	    !wpa_dbus_dict_append_uint32(&dict_iter, "ListenChannel",
10525b9c547cSRui Paulo 					 wpa_s->conf->p2p_listen_channel) ||
10535b9c547cSRui Paulo 	    !wpa_dbus_dict_append_uint32(&dict_iter, "OperRegClass",
10545b9c547cSRui Paulo 					 wpa_s->conf->p2p_oper_reg_class) ||
10555b9c547cSRui Paulo 	    !wpa_dbus_dict_append_uint32(&dict_iter, "OperChannel",
10565b9c547cSRui Paulo 					 wpa_s->conf->p2p_oper_channel) ||
10575b9c547cSRui Paulo 	    (wpa_s->conf->p2p_ssid_postfix &&
1058d4f2939cSRui Paulo 	     !wpa_dbus_dict_append_string(&dict_iter, "SsidPostfix",
10595b9c547cSRui Paulo 					  wpa_s->conf->p2p_ssid_postfix)) ||
10605b9c547cSRui Paulo 	    !wpa_dbus_dict_append_bool(&dict_iter, "IntraBss",
10615b9c547cSRui Paulo 				       wpa_s->conf->p2p_intra_bss) ||
10625b9c547cSRui Paulo 	    !wpa_dbus_dict_append_uint32(&dict_iter, "GroupIdle",
10635b9c547cSRui Paulo 					 wpa_s->conf->p2p_group_idle) ||
10645b9c547cSRui Paulo 	    !wpa_dbus_dict_append_uint32(&dict_iter, "disassoc_low_ack",
10655b9c547cSRui Paulo 					 wpa_s->conf->disassoc_low_ack) ||
10665b9c547cSRui Paulo 	    !wpa_dbus_dict_append_bool(&dict_iter, "NoGroupIface",
10675b9c547cSRui Paulo 				       wpa_s->conf->p2p_no_group_iface) ||
10685b9c547cSRui Paulo 	    !wpa_dbus_dict_append_uint32(&dict_iter, "p2p_search_delay",
10695b9c547cSRui Paulo 					 wpa_s->conf->p2p_search_delay) ||
10705b9c547cSRui Paulo 	    !wpa_dbus_dict_close_write(&variant_iter, &dict_iter) ||
1071d4f2939cSRui Paulo 	    !dbus_message_iter_close_container(iter, &variant_iter))
1072d4f2939cSRui Paulo 		goto err_no_mem;
1073d4f2939cSRui Paulo 
1074d4f2939cSRui Paulo 	return TRUE;
1075d4f2939cSRui Paulo 
1076d4f2939cSRui Paulo err_no_mem:
1077d4f2939cSRui Paulo 	dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1078d4f2939cSRui Paulo 	return FALSE;
1079d4f2939cSRui Paulo }
1080d4f2939cSRui Paulo 
1081d4f2939cSRui Paulo 
wpas_dbus_setter_p2p_device_config(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)1082780fb4a2SCy Schubert dbus_bool_t wpas_dbus_setter_p2p_device_config(
1083780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
1084780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
1085d4f2939cSRui Paulo {
1086d4f2939cSRui Paulo 	struct wpa_supplicant *wpa_s = user_data;
1087d4f2939cSRui Paulo 	DBusMessageIter variant_iter, iter_dict;
1088d4f2939cSRui Paulo 	struct wpa_dbus_dict_entry entry = {.type = DBUS_TYPE_STRING };
1089d4f2939cSRui Paulo 	unsigned int i;
1090d4f2939cSRui Paulo 
1091d4f2939cSRui Paulo 	if (!wpa_dbus_p2p_check_enabled(wpa_s, NULL, NULL, error))
1092d4f2939cSRui Paulo 		return FALSE;
1093d4f2939cSRui Paulo 
1094325151a3SRui Paulo 	wpa_s = wpa_s->global->p2p_init_wpa_s;
10955b9c547cSRui Paulo 
1096d4f2939cSRui Paulo 	dbus_message_iter_recurse(iter, &variant_iter);
1097d4f2939cSRui Paulo 	if (!wpa_dbus_dict_open_read(&variant_iter, &iter_dict, error))
1098d4f2939cSRui Paulo 		return FALSE;
1099d4f2939cSRui Paulo 
1100d4f2939cSRui Paulo 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
1101d4f2939cSRui Paulo 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) {
1102d4f2939cSRui Paulo 			dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
1103d4f2939cSRui Paulo 					     "invalid message format");
1104d4f2939cSRui Paulo 			return FALSE;
1105d4f2939cSRui Paulo 		}
1106d4f2939cSRui Paulo 
1107d4f2939cSRui Paulo 		if (os_strcmp(entry.key, "DeviceName") == 0) {
1108d4f2939cSRui Paulo 			char *devname;
1109d4f2939cSRui Paulo 
1110780fb4a2SCy Schubert 			if (entry.type != DBUS_TYPE_STRING ||
1111780fb4a2SCy Schubert 			    os_strlen(entry.str_value) > WPS_DEV_NAME_MAX_LEN)
1112d4f2939cSRui Paulo 				goto error;
1113d4f2939cSRui Paulo 
1114d4f2939cSRui Paulo 			devname = os_strdup(entry.str_value);
1115d4f2939cSRui Paulo 			if (devname == NULL)
1116d4f2939cSRui Paulo 				goto err_no_mem_clear;
1117d4f2939cSRui Paulo 
1118d4f2939cSRui Paulo 			os_free(wpa_s->conf->device_name);
1119d4f2939cSRui Paulo 			wpa_s->conf->device_name = devname;
1120d4f2939cSRui Paulo 
1121d4f2939cSRui Paulo 			wpa_s->conf->changed_parameters |=
1122d4f2939cSRui Paulo 				CFG_CHANGED_DEVICE_NAME;
1123d4f2939cSRui Paulo 		} else if (os_strcmp(entry.key, "PrimaryDeviceType") == 0) {
1124d4f2939cSRui Paulo 			if (entry.type != DBUS_TYPE_ARRAY ||
1125d4f2939cSRui Paulo 			    entry.array_type != DBUS_TYPE_BYTE ||
1126d4f2939cSRui Paulo 			    entry.array_len != WPS_DEV_TYPE_LEN)
1127d4f2939cSRui Paulo 				goto error;
1128d4f2939cSRui Paulo 
1129d4f2939cSRui Paulo 			os_memcpy(wpa_s->conf->device_type,
1130d4f2939cSRui Paulo 				  entry.bytearray_value,
1131d4f2939cSRui Paulo 				  WPS_DEV_TYPE_LEN);
1132d4f2939cSRui Paulo 			wpa_s->conf->changed_parameters |=
1133d4f2939cSRui Paulo 				CFG_CHANGED_DEVICE_TYPE;
1134d4f2939cSRui Paulo 		} else if (os_strcmp(entry.key, "SecondaryDeviceTypes") == 0) {
1135d4f2939cSRui Paulo 			if (entry.type != DBUS_TYPE_ARRAY ||
1136d4f2939cSRui Paulo 			    entry.array_type != WPAS_DBUS_TYPE_BINARRAY ||
1137d4f2939cSRui Paulo 			    entry.array_len > MAX_SEC_DEVICE_TYPES)
1138d4f2939cSRui Paulo 				goto error;
1139d4f2939cSRui Paulo 
1140d4f2939cSRui Paulo 			for (i = 0; i < entry.array_len; i++)
1141d4f2939cSRui Paulo 				if (wpabuf_len(entry.binarray_value[i]) !=
1142d4f2939cSRui Paulo 				    WPS_DEV_TYPE_LEN)
1143d4f2939cSRui Paulo 					goto err_no_mem_clear;
1144d4f2939cSRui Paulo 			for (i = 0; i < entry.array_len; i++)
1145d4f2939cSRui Paulo 				os_memcpy(wpa_s->conf->sec_device_type[i],
1146d4f2939cSRui Paulo 					  wpabuf_head(entry.binarray_value[i]),
1147d4f2939cSRui Paulo 					  WPS_DEV_TYPE_LEN);
1148d4f2939cSRui Paulo 			wpa_s->conf->num_sec_device_types = entry.array_len;
1149d4f2939cSRui Paulo 			wpa_s->conf->changed_parameters |=
1150d4f2939cSRui Paulo 					CFG_CHANGED_SEC_DEVICE_TYPE;
1151d4f2939cSRui Paulo 		} else if (os_strcmp(entry.key, "VendorExtension") == 0) {
11525b9c547cSRui Paulo 			if (entry.type != DBUS_TYPE_ARRAY ||
11535b9c547cSRui Paulo 			    entry.array_type != WPAS_DBUS_TYPE_BINARRAY ||
1154d4f2939cSRui Paulo 			    (entry.array_len > P2P_MAX_WPS_VENDOR_EXT))
1155d4f2939cSRui Paulo 				goto error;
1156d4f2939cSRui Paulo 
1157d4f2939cSRui Paulo 			wpa_s->conf->changed_parameters |=
1158d4f2939cSRui Paulo 				CFG_CHANGED_VENDOR_EXTENSION;
1159d4f2939cSRui Paulo 
1160d4f2939cSRui Paulo 			for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
1161d4f2939cSRui Paulo 				wpabuf_free(wpa_s->conf->wps_vendor_ext[i]);
1162d4f2939cSRui Paulo 				if (i < entry.array_len) {
1163d4f2939cSRui Paulo 					wpa_s->conf->wps_vendor_ext[i] =
1164d4f2939cSRui Paulo 						entry.binarray_value[i];
1165d4f2939cSRui Paulo 					entry.binarray_value[i] = NULL;
1166d4f2939cSRui Paulo 				} else
1167d4f2939cSRui Paulo 					wpa_s->conf->wps_vendor_ext[i] = NULL;
1168d4f2939cSRui Paulo 			}
11695b9c547cSRui Paulo 		} else if (os_strcmp(entry.key, "GOIntent") == 0 &&
11705b9c547cSRui Paulo 			   entry.type == DBUS_TYPE_UINT32 &&
1171d4f2939cSRui Paulo 			   (entry.uint32_value <= 15))
1172d4f2939cSRui Paulo 			wpa_s->conf->p2p_go_intent = entry.uint32_value;
11735b9c547cSRui Paulo 		else if (os_strcmp(entry.key, "PersistentReconnect") == 0 &&
11745b9c547cSRui Paulo 			 entry.type == DBUS_TYPE_BOOLEAN)
1175d4f2939cSRui Paulo 			wpa_s->conf->persistent_reconnect = entry.bool_value;
11765b9c547cSRui Paulo 		else if (os_strcmp(entry.key, "ListenRegClass") == 0 &&
11775b9c547cSRui Paulo 			 entry.type == DBUS_TYPE_UINT32) {
1178d4f2939cSRui Paulo 			wpa_s->conf->p2p_listen_reg_class = entry.uint32_value;
1179d4f2939cSRui Paulo 			wpa_s->conf->changed_parameters |=
1180d4f2939cSRui Paulo 				CFG_CHANGED_P2P_LISTEN_CHANNEL;
11815b9c547cSRui Paulo 		} else if (os_strcmp(entry.key, "ListenChannel") == 0 &&
11825b9c547cSRui Paulo 			   entry.type == DBUS_TYPE_UINT32) {
1183d4f2939cSRui Paulo 			wpa_s->conf->p2p_listen_channel = entry.uint32_value;
1184d4f2939cSRui Paulo 			wpa_s->conf->changed_parameters |=
1185d4f2939cSRui Paulo 				CFG_CHANGED_P2P_LISTEN_CHANNEL;
11865b9c547cSRui Paulo 		} else if (os_strcmp(entry.key, "OperRegClass") == 0 &&
11875b9c547cSRui Paulo 			   entry.type == DBUS_TYPE_UINT32) {
1188d4f2939cSRui Paulo 			wpa_s->conf->p2p_oper_reg_class = entry.uint32_value;
1189d4f2939cSRui Paulo 			wpa_s->conf->changed_parameters |=
1190d4f2939cSRui Paulo 				CFG_CHANGED_P2P_OPER_CHANNEL;
11915b9c547cSRui Paulo 		} else if (os_strcmp(entry.key, "OperChannel") == 0 &&
11925b9c547cSRui Paulo 			   entry.type == DBUS_TYPE_UINT32) {
1193d4f2939cSRui Paulo 			wpa_s->conf->p2p_oper_channel = entry.uint32_value;
1194d4f2939cSRui Paulo 			wpa_s->conf->changed_parameters |=
1195d4f2939cSRui Paulo 				CFG_CHANGED_P2P_OPER_CHANNEL;
1196d4f2939cSRui Paulo 		} else if (os_strcmp(entry.key, "SsidPostfix") == 0) {
1197d4f2939cSRui Paulo 			char *postfix;
1198d4f2939cSRui Paulo 
1199d4f2939cSRui Paulo 			if (entry.type != DBUS_TYPE_STRING)
1200d4f2939cSRui Paulo 				goto error;
1201d4f2939cSRui Paulo 
1202d4f2939cSRui Paulo 			postfix = os_strdup(entry.str_value);
1203d4f2939cSRui Paulo 			if (!postfix)
1204d4f2939cSRui Paulo 				goto err_no_mem_clear;
1205d4f2939cSRui Paulo 
1206d4f2939cSRui Paulo 			os_free(wpa_s->conf->p2p_ssid_postfix);
1207d4f2939cSRui Paulo 			wpa_s->conf->p2p_ssid_postfix = postfix;
1208d4f2939cSRui Paulo 
1209d4f2939cSRui Paulo 			wpa_s->conf->changed_parameters |=
1210d4f2939cSRui Paulo 					CFG_CHANGED_P2P_SSID_POSTFIX;
12115b9c547cSRui Paulo 		} else if (os_strcmp(entry.key, "IntraBss") == 0 &&
12125b9c547cSRui Paulo 			   entry.type == DBUS_TYPE_BOOLEAN) {
1213d4f2939cSRui Paulo 			wpa_s->conf->p2p_intra_bss = entry.bool_value;
1214d4f2939cSRui Paulo 			wpa_s->conf->changed_parameters |=
1215d4f2939cSRui Paulo 				CFG_CHANGED_P2P_INTRA_BSS;
121685732ac8SCy Schubert 		} else if (os_strcmp(entry.key, "IpAddrGo") == 0) {
121785732ac8SCy Schubert 			if (!wpas_dbus_validate_dbus_ipaddr(entry))
121885732ac8SCy Schubert 				goto error;
121985732ac8SCy Schubert 			os_memcpy(wpa_s->conf->ip_addr_go,
122085732ac8SCy Schubert 				  entry.bytearray_value, 4);
122185732ac8SCy Schubert 		} else if (os_strcmp(entry.key, "IpAddrMask") == 0) {
122285732ac8SCy Schubert 			if (!wpas_dbus_validate_dbus_ipaddr(entry))
122385732ac8SCy Schubert 				goto error;
122485732ac8SCy Schubert 			os_memcpy(wpa_s->conf->ip_addr_mask,
122585732ac8SCy Schubert 				  entry.bytearray_value, 4);
122685732ac8SCy Schubert 		} else if (os_strcmp(entry.key, "IpAddrStart") == 0) {
122785732ac8SCy Schubert 			if (!wpas_dbus_validate_dbus_ipaddr(entry))
122885732ac8SCy Schubert 				goto error;
122985732ac8SCy Schubert 			os_memcpy(wpa_s->conf->ip_addr_start,
123085732ac8SCy Schubert 				  entry.bytearray_value, 4);
123185732ac8SCy Schubert 		} else if (os_strcmp(entry.key, "IpAddrEnd") == 0) {
123285732ac8SCy Schubert 			if (!wpas_dbus_validate_dbus_ipaddr(entry))
123385732ac8SCy Schubert 				goto error;
123485732ac8SCy Schubert 			os_memcpy(wpa_s->conf->ip_addr_end,
123585732ac8SCy Schubert 				  entry.bytearray_value, 4);
12365b9c547cSRui Paulo 		} else if (os_strcmp(entry.key, "GroupIdle") == 0 &&
12375b9c547cSRui Paulo 			   entry.type == DBUS_TYPE_UINT32)
1238d4f2939cSRui Paulo 			wpa_s->conf->p2p_group_idle = entry.uint32_value;
1239d4f2939cSRui Paulo 		else if (os_strcmp(entry.key, "disassoc_low_ack") == 0 &&
1240d4f2939cSRui Paulo 			 entry.type == DBUS_TYPE_UINT32)
1241d4f2939cSRui Paulo 			wpa_s->conf->disassoc_low_ack = entry.uint32_value;
12425b9c547cSRui Paulo 		else if (os_strcmp(entry.key, "NoGroupIface") == 0 &&
12435b9c547cSRui Paulo 			 entry.type == DBUS_TYPE_BOOLEAN)
12445b9c547cSRui Paulo 			wpa_s->conf->p2p_no_group_iface = entry.bool_value;
12455b9c547cSRui Paulo 		else if (os_strcmp(entry.key, "p2p_search_delay") == 0 &&
12465b9c547cSRui Paulo 			 entry.type == DBUS_TYPE_UINT32)
12475b9c547cSRui Paulo 			wpa_s->conf->p2p_search_delay = entry.uint32_value;
1248d4f2939cSRui Paulo 		else
1249d4f2939cSRui Paulo 			goto error;
1250d4f2939cSRui Paulo 
1251d4f2939cSRui Paulo 		wpa_dbus_dict_entry_clear(&entry);
1252d4f2939cSRui Paulo 	}
1253d4f2939cSRui Paulo 
1254d4f2939cSRui Paulo 	if (wpa_s->conf->changed_parameters) {
1255d4f2939cSRui Paulo 		/* Some changed parameters requires to update config*/
1256d4f2939cSRui Paulo 		wpa_supplicant_update_config(wpa_s);
1257d4f2939cSRui Paulo 	}
1258d4f2939cSRui Paulo 
1259d4f2939cSRui Paulo 	return TRUE;
1260d4f2939cSRui Paulo 
1261d4f2939cSRui Paulo  error:
1262d4f2939cSRui Paulo 	dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
1263d4f2939cSRui Paulo 			     "invalid message format");
1264d4f2939cSRui Paulo 	wpa_dbus_dict_entry_clear(&entry);
1265d4f2939cSRui Paulo 	return FALSE;
1266d4f2939cSRui Paulo 
1267d4f2939cSRui Paulo  err_no_mem_clear:
1268d4f2939cSRui Paulo 	dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1269d4f2939cSRui Paulo 	wpa_dbus_dict_entry_clear(&entry);
1270d4f2939cSRui Paulo 	return FALSE;
1271d4f2939cSRui Paulo }
1272d4f2939cSRui Paulo 
1273d4f2939cSRui Paulo 
wpas_dbus_getter_p2p_peers(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)1274780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_p2p_peers(
1275780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
1276780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
1277d4f2939cSRui Paulo {
1278d4f2939cSRui Paulo 	struct wpa_supplicant *wpa_s = user_data;
1279d4f2939cSRui Paulo 	struct p2p_data *p2p = wpa_s->global->p2p;
1280d4f2939cSRui Paulo 	int next = 0, i = 0;
1281d4f2939cSRui Paulo 	int num = 0, out_of_mem = 0;
1282d4f2939cSRui Paulo 	const u8 *addr;
1283d4f2939cSRui Paulo 	const struct p2p_peer_info *peer_info = NULL;
1284d4f2939cSRui Paulo 	dbus_bool_t success = FALSE;
1285d4f2939cSRui Paulo 
1286d4f2939cSRui Paulo 	struct dl_list peer_objpath_list;
1287d4f2939cSRui Paulo 	struct peer_objpath_node {
1288d4f2939cSRui Paulo 		struct dl_list list;
1289d4f2939cSRui Paulo 		char path[WPAS_DBUS_OBJECT_PATH_MAX];
1290d4f2939cSRui Paulo 	} *node, *tmp;
1291d4f2939cSRui Paulo 
1292d4f2939cSRui Paulo 	char **peer_obj_paths = NULL;
1293d4f2939cSRui Paulo 
1294325151a3SRui Paulo 	if (!wpa_dbus_p2p_check_enabled(wpa_s, NULL, NULL, error) ||
1295325151a3SRui Paulo 	    !wpa_s->parent->parent->dbus_new_path)
1296d4f2939cSRui Paulo 		return FALSE;
1297d4f2939cSRui Paulo 
1298d4f2939cSRui Paulo 	dl_list_init(&peer_objpath_list);
1299d4f2939cSRui Paulo 
1300d4f2939cSRui Paulo 	/* Get the first peer info */
1301d4f2939cSRui Paulo 	peer_info = p2p_get_peer_found(p2p, NULL, next);
1302d4f2939cSRui Paulo 
1303d4f2939cSRui Paulo 	/* Get next and accumulate them */
1304d4f2939cSRui Paulo 	next = 1;
1305d4f2939cSRui Paulo 	while (peer_info != NULL) {
1306d4f2939cSRui Paulo 		node = os_zalloc(sizeof(struct peer_objpath_node));
1307d4f2939cSRui Paulo 		if (!node) {
1308d4f2939cSRui Paulo 			out_of_mem = 1;
1309d4f2939cSRui Paulo 			goto error;
1310d4f2939cSRui Paulo 		}
1311d4f2939cSRui Paulo 
1312d4f2939cSRui Paulo 		addr = peer_info->p2p_device_addr;
1313d4f2939cSRui Paulo 		os_snprintf(node->path, WPAS_DBUS_OBJECT_PATH_MAX,
1314d4f2939cSRui Paulo 			    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART
1315d4f2939cSRui Paulo 			    "/" COMPACT_MACSTR,
1316325151a3SRui Paulo 			    wpa_s->parent->parent->dbus_new_path,
1317325151a3SRui Paulo 			    MAC2STR(addr));
1318d4f2939cSRui Paulo 		dl_list_add_tail(&peer_objpath_list, &node->list);
1319d4f2939cSRui Paulo 		num++;
1320d4f2939cSRui Paulo 
1321d4f2939cSRui Paulo 		peer_info = p2p_get_peer_found(p2p, addr, next);
1322d4f2939cSRui Paulo 	}
1323d4f2939cSRui Paulo 
1324d4f2939cSRui Paulo 	/*
1325d4f2939cSRui Paulo 	 * Now construct the peer object paths in a form suitable for
1326d4f2939cSRui Paulo 	 * array_property_getter helper below.
1327d4f2939cSRui Paulo 	 */
1328d4f2939cSRui Paulo 	peer_obj_paths = os_calloc(num, sizeof(char *));
1329d4f2939cSRui Paulo 
1330d4f2939cSRui Paulo 	if (!peer_obj_paths) {
1331d4f2939cSRui Paulo 		out_of_mem = 1;
1332d4f2939cSRui Paulo 		goto error;
1333d4f2939cSRui Paulo 	}
1334d4f2939cSRui Paulo 
1335d4f2939cSRui Paulo 	dl_list_for_each_safe(node, tmp, &peer_objpath_list,
1336d4f2939cSRui Paulo 			      struct peer_objpath_node, list)
1337d4f2939cSRui Paulo 		peer_obj_paths[i++] = node->path;
1338d4f2939cSRui Paulo 
1339d4f2939cSRui Paulo 	success = wpas_dbus_simple_array_property_getter(iter,
1340d4f2939cSRui Paulo 							 DBUS_TYPE_OBJECT_PATH,
1341d4f2939cSRui Paulo 							 peer_obj_paths, num,
1342d4f2939cSRui Paulo 							 error);
1343d4f2939cSRui Paulo 
1344d4f2939cSRui Paulo error:
1345d4f2939cSRui Paulo 	if (peer_obj_paths)
1346d4f2939cSRui Paulo 		os_free(peer_obj_paths);
1347d4f2939cSRui Paulo 
1348d4f2939cSRui Paulo 	dl_list_for_each_safe(node, tmp, &peer_objpath_list,
1349d4f2939cSRui Paulo 			      struct peer_objpath_node, list) {
1350d4f2939cSRui Paulo 		dl_list_del(&node->list);
1351d4f2939cSRui Paulo 		os_free(node);
1352d4f2939cSRui Paulo 	}
1353d4f2939cSRui Paulo 	if (out_of_mem)
1354d4f2939cSRui Paulo 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1355d4f2939cSRui Paulo 
1356d4f2939cSRui Paulo 	return success;
1357d4f2939cSRui Paulo }
1358d4f2939cSRui Paulo 
1359d4f2939cSRui Paulo 
1360d4f2939cSRui Paulo enum wpas_p2p_role {
1361d4f2939cSRui Paulo 	WPAS_P2P_ROLE_DEVICE,
1362d4f2939cSRui Paulo 	WPAS_P2P_ROLE_GO,
1363d4f2939cSRui Paulo 	WPAS_P2P_ROLE_CLIENT,
1364d4f2939cSRui Paulo };
1365d4f2939cSRui Paulo 
wpas_get_p2p_role(struct wpa_supplicant * wpa_s)1366d4f2939cSRui Paulo static enum wpas_p2p_role wpas_get_p2p_role(struct wpa_supplicant *wpa_s)
1367d4f2939cSRui Paulo {
1368d4f2939cSRui Paulo 	struct wpa_ssid *ssid = wpa_s->current_ssid;
1369d4f2939cSRui Paulo 
1370d4f2939cSRui Paulo 	if (!ssid)
1371d4f2939cSRui Paulo 		return WPAS_P2P_ROLE_DEVICE;
1372d4f2939cSRui Paulo 	if (wpa_s->wpa_state != WPA_COMPLETED)
1373d4f2939cSRui Paulo 		return WPAS_P2P_ROLE_DEVICE;
1374d4f2939cSRui Paulo 
1375d4f2939cSRui Paulo 	switch (ssid->mode) {
1376d4f2939cSRui Paulo 	case WPAS_MODE_P2P_GO:
1377d4f2939cSRui Paulo 	case WPAS_MODE_P2P_GROUP_FORMATION:
1378d4f2939cSRui Paulo 		return WPAS_P2P_ROLE_GO;
1379d4f2939cSRui Paulo 	case WPAS_MODE_INFRA:
1380d4f2939cSRui Paulo 		if (ssid->p2p_group)
1381d4f2939cSRui Paulo 			return WPAS_P2P_ROLE_CLIENT;
1382d4f2939cSRui Paulo 		return WPAS_P2P_ROLE_DEVICE;
1383d4f2939cSRui Paulo 	default:
1384d4f2939cSRui Paulo 		return WPAS_P2P_ROLE_DEVICE;
1385d4f2939cSRui Paulo 	}
1386d4f2939cSRui Paulo }
1387d4f2939cSRui Paulo 
1388d4f2939cSRui Paulo 
wpas_dbus_getter_p2p_role(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)1389780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_p2p_role(
1390780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
1391780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
1392d4f2939cSRui Paulo {
1393d4f2939cSRui Paulo 	struct wpa_supplicant *wpa_s = user_data;
1394d4f2939cSRui Paulo 	char *str;
1395d4f2939cSRui Paulo 
1396d4f2939cSRui Paulo 	switch (wpas_get_p2p_role(wpa_s)) {
1397d4f2939cSRui Paulo 	case WPAS_P2P_ROLE_GO:
1398d4f2939cSRui Paulo 		str = "GO";
1399d4f2939cSRui Paulo 		break;
1400d4f2939cSRui Paulo 	case WPAS_P2P_ROLE_CLIENT:
1401d4f2939cSRui Paulo 		str = "client";
1402d4f2939cSRui Paulo 		break;
1403d4f2939cSRui Paulo 	default:
1404d4f2939cSRui Paulo 		str = "device";
14055b9c547cSRui Paulo 		break;
1406d4f2939cSRui Paulo 	}
1407d4f2939cSRui Paulo 
1408d4f2939cSRui Paulo 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &str,
1409d4f2939cSRui Paulo 						error);
1410d4f2939cSRui Paulo }
1411d4f2939cSRui Paulo 
1412d4f2939cSRui Paulo 
wpas_dbus_getter_p2p_group(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)1413780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_p2p_group(
1414780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
1415780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
1416d4f2939cSRui Paulo {
1417d4f2939cSRui Paulo 	struct wpa_supplicant *wpa_s = user_data;
1418d4f2939cSRui Paulo 	char path_buf[WPAS_DBUS_OBJECT_PATH_MAX];
1419d4f2939cSRui Paulo 	char *dbus_groupobj_path = path_buf;
1420d4f2939cSRui Paulo 
1421d4f2939cSRui Paulo 	if (wpa_s->dbus_groupobj_path == NULL)
1422d4f2939cSRui Paulo 		os_snprintf(dbus_groupobj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1423d4f2939cSRui Paulo 			    "/");
1424d4f2939cSRui Paulo 	else
1425d4f2939cSRui Paulo 		os_snprintf(dbus_groupobj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1426d4f2939cSRui Paulo 			    "%s", wpa_s->dbus_groupobj_path);
1427d4f2939cSRui Paulo 
1428d4f2939cSRui Paulo 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
1429d4f2939cSRui Paulo 						&dbus_groupobj_path, error);
1430d4f2939cSRui Paulo }
1431d4f2939cSRui Paulo 
1432d4f2939cSRui Paulo 
wpas_dbus_getter_p2p_peergo(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)1433780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_p2p_peergo(
1434780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
1435780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
1436d4f2939cSRui Paulo {
1437d4f2939cSRui Paulo 	struct wpa_supplicant *wpa_s = user_data;
1438d4f2939cSRui Paulo 	char go_peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1439d4f2939cSRui Paulo 
1440325151a3SRui Paulo 	if (!wpa_s->parent->parent->dbus_new_path)
1441325151a3SRui Paulo 		return FALSE;
1442325151a3SRui Paulo 
1443d4f2939cSRui Paulo 	if (wpas_get_p2p_role(wpa_s) != WPAS_P2P_ROLE_CLIENT)
1444d4f2939cSRui Paulo 		os_snprintf(go_peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
1445d4f2939cSRui Paulo 	else
1446d4f2939cSRui Paulo 		os_snprintf(go_peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1447d4f2939cSRui Paulo 			    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
1448d4f2939cSRui Paulo 			    COMPACT_MACSTR,
1449325151a3SRui Paulo 			    wpa_s->parent->parent->dbus_new_path,
1450325151a3SRui Paulo 			    MAC2STR(wpa_s->go_dev_addr));
1451d4f2939cSRui Paulo 
1452d4f2939cSRui Paulo 	path = go_peer_obj_path;
1453d4f2939cSRui Paulo 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
1454d4f2939cSRui Paulo 						&path, error);
1455d4f2939cSRui Paulo }
1456d4f2939cSRui Paulo 
1457d4f2939cSRui Paulo 
1458d4f2939cSRui Paulo /*
1459d4f2939cSRui Paulo  * Peer object properties accessor methods
1460d4f2939cSRui Paulo  */
1461d4f2939cSRui Paulo 
wpas_dbus_getter_p2p_peer_device_name(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)1462780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_p2p_peer_device_name(
1463780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
1464780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
1465d4f2939cSRui Paulo {
1466d4f2939cSRui Paulo 	struct peer_handler_args *peer_args = user_data;
1467d4f2939cSRui Paulo 	const struct p2p_peer_info *info;
1468d4f2939cSRui Paulo 	char *tmp;
1469d4f2939cSRui Paulo 
1470d4f2939cSRui Paulo 	if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error))
1471d4f2939cSRui Paulo 		return FALSE;
1472d4f2939cSRui Paulo 
1473d4f2939cSRui Paulo 	/* get the peer info */
1474d4f2939cSRui Paulo 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1475d4f2939cSRui Paulo 				  peer_args->p2p_device_addr, 0);
1476d4f2939cSRui Paulo 	if (info == NULL) {
1477d4f2939cSRui Paulo 		dbus_set_error(error, DBUS_ERROR_FAILED,
1478d4f2939cSRui Paulo 			       "failed to find peer");
1479d4f2939cSRui Paulo 		return FALSE;
1480d4f2939cSRui Paulo 	}
1481d4f2939cSRui Paulo 
1482d4f2939cSRui Paulo 	tmp = os_strdup(info->device_name);
1483d4f2939cSRui Paulo 	if (!tmp) {
1484d4f2939cSRui Paulo 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1485d4f2939cSRui Paulo 		return FALSE;
1486d4f2939cSRui Paulo 	}
1487d4f2939cSRui Paulo 
1488d4f2939cSRui Paulo 	if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp,
1489d4f2939cSRui Paulo 					      error)) {
1490d4f2939cSRui Paulo 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1491d4f2939cSRui Paulo 		os_free(tmp);
1492d4f2939cSRui Paulo 		return FALSE;
1493d4f2939cSRui Paulo 	}
1494d4f2939cSRui Paulo 
1495d4f2939cSRui Paulo 	os_free(tmp);
1496d4f2939cSRui Paulo 	return TRUE;
1497d4f2939cSRui Paulo }
1498d4f2939cSRui Paulo 
1499d4f2939cSRui Paulo 
wpas_dbus_getter_p2p_peer_manufacturer(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)1500780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_p2p_peer_manufacturer(
1501780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
1502780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
1503325151a3SRui Paulo {
1504325151a3SRui Paulo 	struct peer_handler_args *peer_args = user_data;
1505325151a3SRui Paulo 	const struct p2p_peer_info *info;
1506325151a3SRui Paulo 	char *tmp;
1507325151a3SRui Paulo 
1508325151a3SRui Paulo 	if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error))
1509325151a3SRui Paulo 		return FALSE;
1510325151a3SRui Paulo 
1511325151a3SRui Paulo 	/* get the peer info */
1512325151a3SRui Paulo 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1513325151a3SRui Paulo 				  peer_args->p2p_device_addr, 0);
1514325151a3SRui Paulo 	if (info == NULL) {
1515325151a3SRui Paulo 		dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer");
1516325151a3SRui Paulo 		return FALSE;
1517325151a3SRui Paulo 	}
1518325151a3SRui Paulo 
1519325151a3SRui Paulo 	tmp = os_strdup(info->manufacturer);
1520325151a3SRui Paulo 	if (!tmp) {
1521325151a3SRui Paulo 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1522325151a3SRui Paulo 		return FALSE;
1523325151a3SRui Paulo 	}
1524325151a3SRui Paulo 
1525325151a3SRui Paulo 	if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp,
1526325151a3SRui Paulo 					      error)) {
1527325151a3SRui Paulo 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1528325151a3SRui Paulo 		os_free(tmp);
1529325151a3SRui Paulo 		return FALSE;
1530325151a3SRui Paulo 	}
1531325151a3SRui Paulo 
1532325151a3SRui Paulo 	os_free(tmp);
1533325151a3SRui Paulo 	return TRUE;
1534325151a3SRui Paulo }
1535325151a3SRui Paulo 
1536325151a3SRui Paulo 
wpas_dbus_getter_p2p_peer_modelname(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)1537780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_p2p_peer_modelname(
1538780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
1539780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
1540325151a3SRui Paulo {
1541325151a3SRui Paulo 	struct peer_handler_args *peer_args = user_data;
1542325151a3SRui Paulo 	const struct p2p_peer_info *info;
1543325151a3SRui Paulo 	char *tmp;
1544325151a3SRui Paulo 
1545325151a3SRui Paulo 	if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error))
1546325151a3SRui Paulo 		return FALSE;
1547325151a3SRui Paulo 
1548325151a3SRui Paulo 	/* get the peer info */
1549325151a3SRui Paulo 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1550325151a3SRui Paulo 				  peer_args->p2p_device_addr, 0);
1551325151a3SRui Paulo 	if (info == NULL) {
1552325151a3SRui Paulo 		dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer");
1553325151a3SRui Paulo 		return FALSE;
1554325151a3SRui Paulo 	}
1555325151a3SRui Paulo 
1556325151a3SRui Paulo 	tmp = os_strdup(info->model_name);
1557325151a3SRui Paulo 	if (!tmp) {
1558325151a3SRui Paulo 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1559325151a3SRui Paulo 		return FALSE;
1560325151a3SRui Paulo 	}
1561325151a3SRui Paulo 
1562325151a3SRui Paulo 	if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp,
1563325151a3SRui Paulo 					      error)) {
1564325151a3SRui Paulo 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1565325151a3SRui Paulo 		os_free(tmp);
1566325151a3SRui Paulo 		return FALSE;
1567325151a3SRui Paulo 	}
1568325151a3SRui Paulo 
1569325151a3SRui Paulo 	os_free(tmp);
1570325151a3SRui Paulo 	return TRUE;
1571325151a3SRui Paulo }
1572325151a3SRui Paulo 
1573325151a3SRui Paulo 
wpas_dbus_getter_p2p_peer_modelnumber(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)1574780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_p2p_peer_modelnumber(
1575780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
1576780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
1577325151a3SRui Paulo {
1578325151a3SRui Paulo 	struct peer_handler_args *peer_args = user_data;
1579325151a3SRui Paulo 	const struct p2p_peer_info *info;
1580325151a3SRui Paulo 	char *tmp;
1581325151a3SRui Paulo 
1582325151a3SRui Paulo 	if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error))
1583325151a3SRui Paulo 		return FALSE;
1584325151a3SRui Paulo 
1585325151a3SRui Paulo 	/* get the peer info */
1586325151a3SRui Paulo 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1587325151a3SRui Paulo 				  peer_args->p2p_device_addr, 0);
1588325151a3SRui Paulo 	if (info == NULL) {
1589325151a3SRui Paulo 		dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer");
1590325151a3SRui Paulo 		return FALSE;
1591325151a3SRui Paulo 	}
1592325151a3SRui Paulo 
1593325151a3SRui Paulo 	tmp = os_strdup(info->model_number);
1594325151a3SRui Paulo 	if (!tmp) {
1595325151a3SRui Paulo 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1596325151a3SRui Paulo 		return FALSE;
1597325151a3SRui Paulo 	}
1598325151a3SRui Paulo 
1599325151a3SRui Paulo 	if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp,
1600325151a3SRui Paulo 					      error)) {
1601325151a3SRui Paulo 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1602325151a3SRui Paulo 		os_free(tmp);
1603325151a3SRui Paulo 		return FALSE;
1604325151a3SRui Paulo 	}
1605325151a3SRui Paulo 
1606325151a3SRui Paulo 	os_free(tmp);
1607325151a3SRui Paulo 	return TRUE;
1608325151a3SRui Paulo }
1609325151a3SRui Paulo 
1610325151a3SRui Paulo 
wpas_dbus_getter_p2p_peer_serialnumber(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)1611780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_p2p_peer_serialnumber(
1612780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
1613780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
1614325151a3SRui Paulo {
1615325151a3SRui Paulo 	struct peer_handler_args *peer_args = user_data;
1616325151a3SRui Paulo 	const struct p2p_peer_info *info;
1617325151a3SRui Paulo 	char *tmp;
1618325151a3SRui Paulo 
1619325151a3SRui Paulo 	if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error))
1620325151a3SRui Paulo 		return FALSE;
1621325151a3SRui Paulo 
1622325151a3SRui Paulo 	/* get the peer info */
1623325151a3SRui Paulo 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1624325151a3SRui Paulo 				  peer_args->p2p_device_addr, 0);
1625325151a3SRui Paulo 	if (info == NULL) {
1626325151a3SRui Paulo 		dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer");
1627325151a3SRui Paulo 		return FALSE;
1628325151a3SRui Paulo 	}
1629325151a3SRui Paulo 
1630325151a3SRui Paulo 	tmp = os_strdup(info->serial_number);
1631325151a3SRui Paulo 	if (!tmp) {
1632325151a3SRui Paulo 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1633325151a3SRui Paulo 		return FALSE;
1634325151a3SRui Paulo 	}
1635325151a3SRui Paulo 
1636325151a3SRui Paulo 	if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp,
1637325151a3SRui Paulo 					      error)) {
1638325151a3SRui Paulo 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1639325151a3SRui Paulo 		os_free(tmp);
1640325151a3SRui Paulo 		return FALSE;
1641325151a3SRui Paulo 	}
1642325151a3SRui Paulo 
1643325151a3SRui Paulo 	os_free(tmp);
1644325151a3SRui Paulo 	return TRUE;
1645325151a3SRui Paulo }
1646325151a3SRui Paulo 
1647325151a3SRui Paulo 
wpas_dbus_getter_p2p_peer_primary_device_type(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)1648d4f2939cSRui Paulo dbus_bool_t wpas_dbus_getter_p2p_peer_primary_device_type(
1649780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
1650d4f2939cSRui Paulo 	DBusMessageIter *iter, DBusError *error, void *user_data)
1651d4f2939cSRui Paulo {
1652d4f2939cSRui Paulo 	struct peer_handler_args *peer_args = user_data;
1653d4f2939cSRui Paulo 	const struct p2p_peer_info *info;
1654d4f2939cSRui Paulo 
1655d4f2939cSRui Paulo 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1656d4f2939cSRui Paulo 				  peer_args->p2p_device_addr, 0);
1657d4f2939cSRui Paulo 	if (info == NULL) {
1658d4f2939cSRui Paulo 		dbus_set_error(error, DBUS_ERROR_FAILED,
1659d4f2939cSRui Paulo 			       "failed to find peer");
1660d4f2939cSRui Paulo 		return FALSE;
1661d4f2939cSRui Paulo 	}
1662d4f2939cSRui Paulo 
1663d4f2939cSRui Paulo 	if (!wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
1664d4f2939cSRui Paulo 						    (char *)
1665d4f2939cSRui Paulo 						    info->pri_dev_type,
1666d4f2939cSRui Paulo 						    WPS_DEV_TYPE_LEN, error)) {
1667d4f2939cSRui Paulo 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1668d4f2939cSRui Paulo 		return FALSE;
1669d4f2939cSRui Paulo 	}
1670d4f2939cSRui Paulo 
1671d4f2939cSRui Paulo 	return TRUE;
1672d4f2939cSRui Paulo }
1673d4f2939cSRui Paulo 
1674d4f2939cSRui Paulo 
wpas_dbus_getter_p2p_peer_config_method(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)1675780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_p2p_peer_config_method(
1676780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
1677780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
1678d4f2939cSRui Paulo {
1679d4f2939cSRui Paulo 	struct peer_handler_args *peer_args = user_data;
1680d4f2939cSRui Paulo 	const struct p2p_peer_info *info;
1681d4f2939cSRui Paulo 
1682d4f2939cSRui Paulo 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1683d4f2939cSRui Paulo 				  peer_args->p2p_device_addr, 0);
1684d4f2939cSRui Paulo 	if (info == NULL) {
1685d4f2939cSRui Paulo 		dbus_set_error(error, DBUS_ERROR_FAILED,
1686d4f2939cSRui Paulo 			       "failed to find peer");
1687d4f2939cSRui Paulo 		return FALSE;
1688d4f2939cSRui Paulo 	}
1689d4f2939cSRui Paulo 
1690d4f2939cSRui Paulo 	if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
1691d4f2939cSRui Paulo 					      &info->config_methods, error)) {
1692d4f2939cSRui Paulo 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1693d4f2939cSRui Paulo 		return FALSE;
1694d4f2939cSRui Paulo 	}
1695d4f2939cSRui Paulo 
1696d4f2939cSRui Paulo 	return TRUE;
1697d4f2939cSRui Paulo }
1698d4f2939cSRui Paulo 
1699d4f2939cSRui Paulo 
wpas_dbus_getter_p2p_peer_level(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)1700780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_p2p_peer_level(
1701780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
1702780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
1703d4f2939cSRui Paulo {
1704d4f2939cSRui Paulo 	struct peer_handler_args *peer_args = user_data;
1705d4f2939cSRui Paulo 	const struct p2p_peer_info *info;
1706d4f2939cSRui Paulo 
1707d4f2939cSRui Paulo 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1708d4f2939cSRui Paulo 				  peer_args->p2p_device_addr, 0);
1709d4f2939cSRui Paulo 	if (info == NULL) {
1710d4f2939cSRui Paulo 		dbus_set_error(error, DBUS_ERROR_FAILED,
1711d4f2939cSRui Paulo 			       "failed to find peer");
1712d4f2939cSRui Paulo 		return FALSE;
1713d4f2939cSRui Paulo 	}
1714d4f2939cSRui Paulo 
1715d4f2939cSRui Paulo 	if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
1716d4f2939cSRui Paulo 					      &info->level, error)) {
1717d4f2939cSRui Paulo 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1718d4f2939cSRui Paulo 		return FALSE;
1719d4f2939cSRui Paulo 	}
1720d4f2939cSRui Paulo 
1721d4f2939cSRui Paulo 	return TRUE;
1722d4f2939cSRui Paulo }
1723d4f2939cSRui Paulo 
1724d4f2939cSRui Paulo 
wpas_dbus_getter_p2p_peer_device_capability(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)1725780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_p2p_peer_device_capability(
1726780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
1727780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
1728d4f2939cSRui Paulo {
1729d4f2939cSRui Paulo 	struct peer_handler_args *peer_args = user_data;
1730d4f2939cSRui Paulo 	const struct p2p_peer_info *info;
1731d4f2939cSRui Paulo 
1732d4f2939cSRui Paulo 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1733d4f2939cSRui Paulo 				  peer_args->p2p_device_addr, 0);
1734d4f2939cSRui Paulo 	if (info == NULL) {
1735d4f2939cSRui Paulo 		dbus_set_error(error, DBUS_ERROR_FAILED,
1736d4f2939cSRui Paulo 			       "failed to find peer");
1737d4f2939cSRui Paulo 		return FALSE;
1738d4f2939cSRui Paulo 	}
1739d4f2939cSRui Paulo 
1740d4f2939cSRui Paulo 	if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BYTE,
1741d4f2939cSRui Paulo 					      &info->dev_capab, error)) {
1742d4f2939cSRui Paulo 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1743d4f2939cSRui Paulo 		return FALSE;
1744d4f2939cSRui Paulo 	}
1745d4f2939cSRui Paulo 
1746d4f2939cSRui Paulo 	return TRUE;
1747d4f2939cSRui Paulo }
1748d4f2939cSRui Paulo 
1749d4f2939cSRui Paulo 
wpas_dbus_getter_p2p_peer_group_capability(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)1750780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_p2p_peer_group_capability(
1751780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
1752780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
1753d4f2939cSRui Paulo {
1754d4f2939cSRui Paulo 	struct peer_handler_args *peer_args = user_data;
1755d4f2939cSRui Paulo 	const struct p2p_peer_info *info;
1756d4f2939cSRui Paulo 
1757d4f2939cSRui Paulo 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1758d4f2939cSRui Paulo 				  peer_args->p2p_device_addr, 0);
1759d4f2939cSRui Paulo 	if (info == NULL) {
1760d4f2939cSRui Paulo 		dbus_set_error(error, DBUS_ERROR_FAILED,
1761d4f2939cSRui Paulo 			       "failed to find peer");
1762d4f2939cSRui Paulo 		return FALSE;
1763d4f2939cSRui Paulo 	}
1764d4f2939cSRui Paulo 
1765d4f2939cSRui Paulo 	if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BYTE,
1766d4f2939cSRui Paulo 					      &info->group_capab, error)) {
1767d4f2939cSRui Paulo 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1768d4f2939cSRui Paulo 		return FALSE;
1769d4f2939cSRui Paulo 	}
1770d4f2939cSRui Paulo 
1771d4f2939cSRui Paulo 	return TRUE;
1772d4f2939cSRui Paulo }
1773d4f2939cSRui Paulo 
1774d4f2939cSRui Paulo 
wpas_dbus_getter_p2p_peer_secondary_device_types(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)1775d4f2939cSRui Paulo dbus_bool_t wpas_dbus_getter_p2p_peer_secondary_device_types(
1776780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
1777d4f2939cSRui Paulo 	DBusMessageIter *iter, DBusError *error, void *user_data)
1778d4f2939cSRui Paulo {
1779d4f2939cSRui Paulo 	struct peer_handler_args *peer_args = user_data;
1780d4f2939cSRui Paulo 	const struct p2p_peer_info *info;
1781d4f2939cSRui Paulo 	DBusMessageIter variant_iter, array_iter;
1782d4f2939cSRui Paulo 
1783d4f2939cSRui Paulo 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1784d4f2939cSRui Paulo 				  peer_args->p2p_device_addr, 0);
1785d4f2939cSRui Paulo 	if (info == NULL) {
17865b9c547cSRui Paulo 		dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer");
1787d4f2939cSRui Paulo 		return FALSE;
1788d4f2939cSRui Paulo 	}
1789d4f2939cSRui Paulo 
1790d4f2939cSRui Paulo 	if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
1791d4f2939cSRui Paulo 					      DBUS_TYPE_ARRAY_AS_STRING
1792d4f2939cSRui Paulo 					      DBUS_TYPE_ARRAY_AS_STRING
1793d4f2939cSRui Paulo 					      DBUS_TYPE_BYTE_AS_STRING,
17945b9c547cSRui Paulo 					      &variant_iter) ||
17955b9c547cSRui Paulo 	    !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
1796d4f2939cSRui Paulo 					      DBUS_TYPE_ARRAY_AS_STRING
1797d4f2939cSRui Paulo 					      DBUS_TYPE_BYTE_AS_STRING,
1798d4f2939cSRui Paulo 					      &array_iter)) {
1799d4f2939cSRui Paulo 		dbus_set_error(error, DBUS_ERROR_FAILED,
18005b9c547cSRui Paulo 			       "%s: failed to construct message 1", __func__);
1801d4f2939cSRui Paulo 		return FALSE;
1802d4f2939cSRui Paulo 	}
1803d4f2939cSRui Paulo 
1804d4f2939cSRui Paulo 	if (info->wps_sec_dev_type_list_len) {
1805d4f2939cSRui Paulo 		const u8 *sec_dev_type_list = info->wps_sec_dev_type_list;
1806d4f2939cSRui Paulo 		int num_sec_device_types =
1807d4f2939cSRui Paulo 			info->wps_sec_dev_type_list_len / WPS_DEV_TYPE_LEN;
1808d4f2939cSRui Paulo 		int i;
1809d4f2939cSRui Paulo 		DBusMessageIter inner_array_iter;
1810d4f2939cSRui Paulo 
1811d4f2939cSRui Paulo 		for (i = 0; i < num_sec_device_types; i++) {
1812d4f2939cSRui Paulo 			if (!dbus_message_iter_open_container(
1813d4f2939cSRui Paulo 				    &array_iter, DBUS_TYPE_ARRAY,
1814d4f2939cSRui Paulo 				    DBUS_TYPE_BYTE_AS_STRING,
18155b9c547cSRui Paulo 				    &inner_array_iter) ||
18165b9c547cSRui Paulo 			    !dbus_message_iter_append_fixed_array(
1817d4f2939cSRui Paulo 				    &inner_array_iter, DBUS_TYPE_BYTE,
18185b9c547cSRui Paulo 				    &sec_dev_type_list, WPS_DEV_TYPE_LEN) ||
18195b9c547cSRui Paulo 			    !dbus_message_iter_close_container(
1820d4f2939cSRui Paulo 				    &array_iter, &inner_array_iter)) {
1821d4f2939cSRui Paulo 				dbus_set_error(error, DBUS_ERROR_FAILED,
18225b9c547cSRui Paulo 					       "%s: failed to construct message 2 (%d)",
1823d4f2939cSRui Paulo 					       __func__, i);
1824d4f2939cSRui Paulo 				return FALSE;
1825d4f2939cSRui Paulo 			}
1826d4f2939cSRui Paulo 
1827d4f2939cSRui Paulo 			sec_dev_type_list += WPS_DEV_TYPE_LEN;
1828d4f2939cSRui Paulo 		}
1829d4f2939cSRui Paulo 	}
1830d4f2939cSRui Paulo 
18315b9c547cSRui Paulo 	if (!dbus_message_iter_close_container(&variant_iter, &array_iter) ||
18325b9c547cSRui Paulo 	    !dbus_message_iter_close_container(iter, &variant_iter)) {
1833d4f2939cSRui Paulo 		dbus_set_error(error, DBUS_ERROR_FAILED,
18345b9c547cSRui Paulo 			       "%s: failed to construct message 3", __func__);
1835d4f2939cSRui Paulo 		return FALSE;
1836d4f2939cSRui Paulo 	}
1837d4f2939cSRui Paulo 
1838d4f2939cSRui Paulo 	return TRUE;
1839d4f2939cSRui Paulo }
1840d4f2939cSRui Paulo 
1841d4f2939cSRui Paulo 
wpas_dbus_getter_p2p_peer_vendor_extension(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)1842780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_p2p_peer_vendor_extension(
1843780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
1844780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
1845d4f2939cSRui Paulo {
1846d4f2939cSRui Paulo 	struct wpabuf *vendor_extension[P2P_MAX_WPS_VENDOR_EXT];
18475b9c547cSRui Paulo 	unsigned int i, num = 0;
1848d4f2939cSRui Paulo 	struct peer_handler_args *peer_args = user_data;
1849d4f2939cSRui Paulo 	const struct p2p_peer_info *info;
1850d4f2939cSRui Paulo 
1851d4f2939cSRui Paulo 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1852d4f2939cSRui Paulo 				  peer_args->p2p_device_addr, 0);
1853d4f2939cSRui Paulo 	if (info == NULL) {
1854d4f2939cSRui Paulo 		dbus_set_error(error, DBUS_ERROR_FAILED,
1855d4f2939cSRui Paulo 			       "failed to find peer");
1856d4f2939cSRui Paulo 		return FALSE;
1857d4f2939cSRui Paulo 	}
1858d4f2939cSRui Paulo 
1859d4f2939cSRui Paulo 	/* Add WPS vendor extensions attribute */
18605b9c547cSRui Paulo 	os_memset(vendor_extension, 0, sizeof(vendor_extension));
18615b9c547cSRui Paulo 	for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
1862d4f2939cSRui Paulo 		if (info->wps_vendor_ext[i] == NULL)
1863d4f2939cSRui Paulo 			continue;
1864d4f2939cSRui Paulo 		vendor_extension[num] = info->wps_vendor_ext[i];
1865d4f2939cSRui Paulo 		num++;
1866d4f2939cSRui Paulo 	}
1867d4f2939cSRui Paulo 
1868d4f2939cSRui Paulo 	if (!wpas_dbus_simple_array_array_property_getter(iter, DBUS_TYPE_BYTE,
1869d4f2939cSRui Paulo 							  vendor_extension,
1870d4f2939cSRui Paulo 							  num, error))
1871d4f2939cSRui Paulo 		return FALSE;
1872d4f2939cSRui Paulo 
1873d4f2939cSRui Paulo 	return TRUE;
1874d4f2939cSRui Paulo }
1875d4f2939cSRui Paulo 
1876d4f2939cSRui Paulo 
wpas_dbus_getter_p2p_peer_ies(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)1877780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_p2p_peer_ies(
1878780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
1879780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
1880d4f2939cSRui Paulo {
18815b9c547cSRui Paulo 	struct peer_handler_args *peer_args = user_data;
18825b9c547cSRui Paulo 	const struct p2p_peer_info *info;
1883d4f2939cSRui Paulo 
18845b9c547cSRui Paulo 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
18855b9c547cSRui Paulo 				  peer_args->p2p_device_addr, 0);
18865b9c547cSRui Paulo 	if (info == NULL) {
18875b9c547cSRui Paulo 		dbus_set_error(error, DBUS_ERROR_FAILED,
18885b9c547cSRui Paulo 			       "failed to find peer");
18895b9c547cSRui Paulo 		return FALSE;
18905b9c547cSRui Paulo 	}
18915b9c547cSRui Paulo 
18925b9c547cSRui Paulo 	if (info->wfd_subelems == NULL)
18935b9c547cSRui Paulo 		return wpas_dbus_simple_array_property_getter(iter,
18945b9c547cSRui Paulo 							      DBUS_TYPE_BYTE,
1895d4f2939cSRui Paulo 							      NULL, 0, error);
18965b9c547cSRui Paulo 
18975b9c547cSRui Paulo 	return wpas_dbus_simple_array_property_getter(
18985b9c547cSRui Paulo 		iter, DBUS_TYPE_BYTE, (char *) info->wfd_subelems->buf,
18995b9c547cSRui Paulo 		info->wfd_subelems->used, error);
19005b9c547cSRui Paulo }
19015b9c547cSRui Paulo 
19025b9c547cSRui Paulo 
wpas_dbus_getter_p2p_peer_device_address(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)1903780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_p2p_peer_device_address(
1904780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
1905780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
19065b9c547cSRui Paulo {
19075b9c547cSRui Paulo 	struct peer_handler_args *peer_args = user_data;
19085b9c547cSRui Paulo 	const struct p2p_peer_info *info;
19095b9c547cSRui Paulo 
19105b9c547cSRui Paulo 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
19115b9c547cSRui Paulo 				  peer_args->p2p_device_addr, 0);
19125b9c547cSRui Paulo 	if (info == NULL) {
19135b9c547cSRui Paulo 		dbus_set_error(error, DBUS_ERROR_FAILED,
19145b9c547cSRui Paulo 			       "failed to find peer");
19155b9c547cSRui Paulo 		return FALSE;
19165b9c547cSRui Paulo 	}
19175b9c547cSRui Paulo 
19185b9c547cSRui Paulo 	return wpas_dbus_simple_array_property_getter(
19195b9c547cSRui Paulo 		iter, DBUS_TYPE_BYTE, (char *) info->p2p_device_addr,
19205b9c547cSRui Paulo 		ETH_ALEN, error);
19215b9c547cSRui Paulo }
19225b9c547cSRui Paulo 
19235b9c547cSRui Paulo 
19245b9c547cSRui Paulo struct peer_group_data {
19255b9c547cSRui Paulo 	struct wpa_supplicant *wpa_s;
19265b9c547cSRui Paulo 	const struct p2p_peer_info *info;
19275b9c547cSRui Paulo 	char **paths;
19285b9c547cSRui Paulo 	unsigned int nb_paths;
19295b9c547cSRui Paulo 	int error;
19305b9c547cSRui Paulo };
19315b9c547cSRui Paulo 
19325b9c547cSRui Paulo 
match_group_where_peer_is_client(struct p2p_group * group,void * user_data)19335b9c547cSRui Paulo static int match_group_where_peer_is_client(struct p2p_group *group,
19345b9c547cSRui Paulo 					    void *user_data)
19355b9c547cSRui Paulo {
19365b9c547cSRui Paulo 	struct peer_group_data *data = user_data;
19375b9c547cSRui Paulo 	const struct p2p_group_config *cfg;
19385b9c547cSRui Paulo 	struct wpa_supplicant *wpa_s_go;
19395b9c547cSRui Paulo 	char **paths;
19405b9c547cSRui Paulo 
19415b9c547cSRui Paulo 	if (!p2p_group_is_client_connected(group, data->info->p2p_device_addr))
19425b9c547cSRui Paulo 		return 1;
19435b9c547cSRui Paulo 
19445b9c547cSRui Paulo 	cfg = p2p_group_get_config(group);
19455b9c547cSRui Paulo 
19465b9c547cSRui Paulo 	wpa_s_go = wpas_get_p2p_go_iface(data->wpa_s, cfg->ssid,
19475b9c547cSRui Paulo 					 cfg->ssid_len);
19485b9c547cSRui Paulo 	if (wpa_s_go == NULL)
19495b9c547cSRui Paulo 		return 1;
19505b9c547cSRui Paulo 
19515b9c547cSRui Paulo 	paths = os_realloc_array(data->paths, data->nb_paths + 1,
19525b9c547cSRui Paulo 				 sizeof(char *));
19535b9c547cSRui Paulo 	if (paths == NULL)
19545b9c547cSRui Paulo 		goto out_of_memory;
19555b9c547cSRui Paulo 
19565b9c547cSRui Paulo 	data->paths = paths;
19575b9c547cSRui Paulo 	data->paths[data->nb_paths] = wpa_s_go->dbus_groupobj_path;
19585b9c547cSRui Paulo 	data->nb_paths++;
19595b9c547cSRui Paulo 
19605b9c547cSRui Paulo 	return 1;
19615b9c547cSRui Paulo 
19625b9c547cSRui Paulo out_of_memory:
19635b9c547cSRui Paulo 	data->error = ENOMEM;
19645b9c547cSRui Paulo 	return 0;
19655b9c547cSRui Paulo }
19665b9c547cSRui Paulo 
19675b9c547cSRui Paulo 
wpas_dbus_getter_p2p_peer_groups(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)1968780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_p2p_peer_groups(
1969780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
1970780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
19715b9c547cSRui Paulo {
19725b9c547cSRui Paulo 	struct peer_handler_args *peer_args = user_data;
19735b9c547cSRui Paulo 	const struct p2p_peer_info *info;
19745b9c547cSRui Paulo 	struct peer_group_data data;
19755b9c547cSRui Paulo 	struct wpa_supplicant *wpa_s, *wpa_s_go;
19765b9c547cSRui Paulo 	dbus_bool_t success = FALSE;
19775b9c547cSRui Paulo 
19785b9c547cSRui Paulo 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
19795b9c547cSRui Paulo 				  peer_args->p2p_device_addr, 0);
19805b9c547cSRui Paulo 	if (info == NULL) {
19815b9c547cSRui Paulo 		dbus_set_error(error, DBUS_ERROR_FAILED,
19825b9c547cSRui Paulo 			       "failed to find peer");
19835b9c547cSRui Paulo 		return FALSE;
19845b9c547cSRui Paulo 	}
19855b9c547cSRui Paulo 
19865b9c547cSRui Paulo 	os_memset(&data, 0, sizeof(data));
19875b9c547cSRui Paulo 
19885b9c547cSRui Paulo 	wpa_s = peer_args->wpa_s;
1989325151a3SRui Paulo 	wpa_s = wpa_s->global->p2p_init_wpa_s;
1990c1d255d3SCy Schubert 	if (!wpa_s)
1991c1d255d3SCy Schubert 		return no_p2p_mgmt_interface(error);
19925b9c547cSRui Paulo 
19935b9c547cSRui Paulo 	wpa_s_go = wpas_get_p2p_client_iface(wpa_s, info->p2p_device_addr);
19945b9c547cSRui Paulo 	if (wpa_s_go) {
19955b9c547cSRui Paulo 		data.paths = os_calloc(1, sizeof(char *));
19965b9c547cSRui Paulo 		if (data.paths == NULL)
19975b9c547cSRui Paulo 			goto out_of_memory;
19985b9c547cSRui Paulo 		data.paths[0] = wpa_s_go->dbus_groupobj_path;
19995b9c547cSRui Paulo 		data.nb_paths = 1;
20005b9c547cSRui Paulo 	}
20015b9c547cSRui Paulo 
20025b9c547cSRui Paulo 	data.wpa_s = peer_args->wpa_s;
20035b9c547cSRui Paulo 	data.info = info;
20045b9c547cSRui Paulo 
20055b9c547cSRui Paulo 	p2p_loop_on_all_groups(peer_args->wpa_s->global->p2p,
20065b9c547cSRui Paulo 			       match_group_where_peer_is_client, &data);
20075b9c547cSRui Paulo 	if (data.error)
20085b9c547cSRui Paulo 		goto out_of_memory;
20095b9c547cSRui Paulo 
20105b9c547cSRui Paulo 	if (data.paths == NULL) {
20115b9c547cSRui Paulo 		return wpas_dbus_simple_array_property_getter(
20125b9c547cSRui Paulo 			iter, DBUS_TYPE_OBJECT_PATH, NULL, 0, error);
20135b9c547cSRui Paulo 	}
20145b9c547cSRui Paulo 
20155b9c547cSRui Paulo 	success = wpas_dbus_simple_array_property_getter(iter,
20165b9c547cSRui Paulo 							 DBUS_TYPE_OBJECT_PATH,
20175b9c547cSRui Paulo 							 data.paths,
20185b9c547cSRui Paulo 							 data.nb_paths, error);
20195b9c547cSRui Paulo 	goto out;
20205b9c547cSRui Paulo 
20215b9c547cSRui Paulo out_of_memory:
20225b9c547cSRui Paulo 	dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
20235b9c547cSRui Paulo out:
20245b9c547cSRui Paulo 	os_free(data.paths);
2025d4f2939cSRui Paulo 	return success;
2026d4f2939cSRui Paulo }
2027d4f2939cSRui Paulo 
wpas_dbus_getter_p2p_peer_vsie(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)20284bc52338SCy Schubert dbus_bool_t wpas_dbus_getter_p2p_peer_vsie(
20294bc52338SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
20304bc52338SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
20314bc52338SCy Schubert {
20324bc52338SCy Schubert 	struct peer_handler_args *peer_args = user_data;
20334bc52338SCy Schubert 	const struct p2p_peer_info *info;
20344bc52338SCy Schubert 
20354bc52338SCy Schubert 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
20364bc52338SCy Schubert 				  peer_args->p2p_device_addr, 0);
20374bc52338SCy Schubert 	if (!info) {
20384bc52338SCy Schubert 		dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer");
20394bc52338SCy Schubert 		return FALSE;
20404bc52338SCy Schubert 	}
20414bc52338SCy Schubert 
20424bc52338SCy Schubert 	if (!info->vendor_elems)
20434bc52338SCy Schubert 		return wpas_dbus_simple_array_property_getter(iter,
20444bc52338SCy Schubert 							      DBUS_TYPE_BYTE,
20454bc52338SCy Schubert 							      NULL, 0, error);
20464bc52338SCy Schubert 
20474bc52338SCy Schubert 	return wpas_dbus_simple_array_property_getter(
20484bc52338SCy Schubert 		iter, DBUS_TYPE_BYTE, (char *) info->vendor_elems->buf,
20494bc52338SCy Schubert 		info->vendor_elems->used, error);
20504bc52338SCy Schubert }
20514bc52338SCy Schubert 
2052d4f2939cSRui Paulo 
2053d4f2939cSRui Paulo /**
2054d4f2939cSRui Paulo  * wpas_dbus_getter_persistent_groups - Get array of persistent group objects
2055d4f2939cSRui Paulo  * @iter: Pointer to incoming dbus message iter
2056d4f2939cSRui Paulo  * @error: Location to store error on failure
2057d4f2939cSRui Paulo  * @user_data: Function specific data
2058d4f2939cSRui Paulo  * Returns: TRUE on success, FALSE on failure
2059d4f2939cSRui Paulo  *
2060d4f2939cSRui Paulo  * Getter for "PersistentGroups" property.
2061d4f2939cSRui Paulo  */
wpas_dbus_getter_persistent_groups(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)2062780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_persistent_groups(
2063780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
2064780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
2065d4f2939cSRui Paulo {
2066d4f2939cSRui Paulo 	struct wpa_supplicant *wpa_s = user_data;
2067d4f2939cSRui Paulo 	struct wpa_ssid *ssid;
2068d4f2939cSRui Paulo 	char **paths;
2069d4f2939cSRui Paulo 	unsigned int i = 0, num = 0;
2070d4f2939cSRui Paulo 	dbus_bool_t success = FALSE;
2071d4f2939cSRui Paulo 
2072325151a3SRui Paulo 	wpa_s = wpa_s->global->p2p_init_wpa_s;
2073c1d255d3SCy Schubert 	if (!wpa_s)
2074c1d255d3SCy Schubert 		return no_p2p_mgmt_interface(error);
2075c1d255d3SCy Schubert 
2076325151a3SRui Paulo 	if (!wpa_s->parent->dbus_new_path)
2077325151a3SRui Paulo 		return FALSE;
2078325151a3SRui Paulo 
2079d4f2939cSRui Paulo 	for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
2080d4f2939cSRui Paulo 		if (network_is_persistent_group(ssid))
2081d4f2939cSRui Paulo 			num++;
2082d4f2939cSRui Paulo 
2083d4f2939cSRui Paulo 	paths = os_calloc(num, sizeof(char *));
2084d4f2939cSRui Paulo 	if (!paths) {
2085d4f2939cSRui Paulo 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
2086d4f2939cSRui Paulo 		return FALSE;
2087d4f2939cSRui Paulo 	}
2088d4f2939cSRui Paulo 
2089d4f2939cSRui Paulo 	/* Loop through configured networks and append object path of each */
2090d4f2939cSRui Paulo 	for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2091d4f2939cSRui Paulo 		if (!network_is_persistent_group(ssid))
2092d4f2939cSRui Paulo 			continue;
2093d4f2939cSRui Paulo 		paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
2094d4f2939cSRui Paulo 		if (paths[i] == NULL) {
2095d4f2939cSRui Paulo 			dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
2096d4f2939cSRui Paulo 					     "no memory");
2097d4f2939cSRui Paulo 			goto out;
2098d4f2939cSRui Paulo 		}
2099d4f2939cSRui Paulo 		/* Construct the object path for this network. */
2100d4f2939cSRui Paulo 		os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
2101d4f2939cSRui Paulo 			    "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%d",
2102325151a3SRui Paulo 			    wpa_s->parent->dbus_new_path, ssid->id);
2103d4f2939cSRui Paulo 	}
2104d4f2939cSRui Paulo 
2105d4f2939cSRui Paulo 	success = wpas_dbus_simple_array_property_getter(iter,
2106d4f2939cSRui Paulo 							 DBUS_TYPE_OBJECT_PATH,
2107d4f2939cSRui Paulo 							 paths, num, error);
2108d4f2939cSRui Paulo 
2109d4f2939cSRui Paulo out:
2110d4f2939cSRui Paulo 	while (i)
2111d4f2939cSRui Paulo 		os_free(paths[--i]);
2112d4f2939cSRui Paulo 	os_free(paths);
2113d4f2939cSRui Paulo 	return success;
2114d4f2939cSRui Paulo }
2115d4f2939cSRui Paulo 
2116d4f2939cSRui Paulo 
2117d4f2939cSRui Paulo /**
2118d4f2939cSRui Paulo  * wpas_dbus_getter_persistent_group_properties - Get options for a persistent
2119d4f2939cSRui Paulo  *	group
2120d4f2939cSRui Paulo  * @iter: Pointer to incoming dbus message iter
2121d4f2939cSRui Paulo  * @error: Location to store error on failure
2122d4f2939cSRui Paulo  * @user_data: Function specific data
2123d4f2939cSRui Paulo  * Returns: TRUE on success, FALSE on failure
2124d4f2939cSRui Paulo  *
2125d4f2939cSRui Paulo  * Getter for "Properties" property of a persistent group.
2126d4f2939cSRui Paulo  */
wpas_dbus_getter_persistent_group_properties(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)2127780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_persistent_group_properties(
2128780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
2129780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
2130d4f2939cSRui Paulo {
2131d4f2939cSRui Paulo 	struct network_handler_args *net = user_data;
2132d4f2939cSRui Paulo 
2133d4f2939cSRui Paulo 	/* Leveraging the fact that persistent group object is still
2134d4f2939cSRui Paulo 	 * represented in same manner as network within.
2135d4f2939cSRui Paulo 	 */
2136780fb4a2SCy Schubert 	return wpas_dbus_getter_network_properties(property_desc, iter, error, net);
2137d4f2939cSRui Paulo }
2138d4f2939cSRui Paulo 
2139d4f2939cSRui Paulo 
2140d4f2939cSRui Paulo /**
2141325151a3SRui Paulo  * wpas_dbus_setter_persistent_group_properties - Set options for a persistent
2142d4f2939cSRui Paulo  *	group
2143d4f2939cSRui Paulo  * @iter: Pointer to incoming dbus message iter
2144d4f2939cSRui Paulo  * @error: Location to store error on failure
2145d4f2939cSRui Paulo  * @user_data: Function specific data
2146d4f2939cSRui Paulo  * Returns: TRUE on success, FALSE on failure
2147d4f2939cSRui Paulo  *
2148d4f2939cSRui Paulo  * Setter for "Properties" property of a persistent group.
2149d4f2939cSRui Paulo  */
wpas_dbus_setter_persistent_group_properties(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)2150780fb4a2SCy Schubert dbus_bool_t wpas_dbus_setter_persistent_group_properties(
2151780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
2152780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
2153d4f2939cSRui Paulo {
2154d4f2939cSRui Paulo 	struct network_handler_args *net = user_data;
2155d4f2939cSRui Paulo 	struct wpa_ssid *ssid = net->ssid;
2156d4f2939cSRui Paulo 	DBusMessageIter	variant_iter;
2157d4f2939cSRui Paulo 
2158d4f2939cSRui Paulo 	/*
2159d4f2939cSRui Paulo 	 * Leveraging the fact that persistent group object is still
2160d4f2939cSRui Paulo 	 * represented in same manner as network within.
2161d4f2939cSRui Paulo 	 */
2162d4f2939cSRui Paulo 	dbus_message_iter_recurse(iter, &variant_iter);
2163d4f2939cSRui Paulo 	return set_network_properties(net->wpa_s, ssid, &variant_iter, error);
2164d4f2939cSRui Paulo }
2165d4f2939cSRui Paulo 
2166d4f2939cSRui Paulo 
2167d4f2939cSRui Paulo /**
2168d4f2939cSRui Paulo  * wpas_dbus_new_iface_add_persistent_group - Add a new configured
2169d4f2939cSRui Paulo  *	persistent_group
2170d4f2939cSRui Paulo  * @message: Pointer to incoming dbus message
2171d4f2939cSRui Paulo  * @wpa_s: wpa_supplicant structure for a network interface
2172d4f2939cSRui Paulo  * Returns: A dbus message containing the object path of the new
2173d4f2939cSRui Paulo  * persistent group
2174d4f2939cSRui Paulo  *
2175d4f2939cSRui Paulo  * Handler function for "AddPersistentGroup" method call of a P2P Device
2176d4f2939cSRui Paulo  * interface.
2177d4f2939cSRui Paulo  */
wpas_dbus_handler_add_persistent_group(DBusMessage * message,struct wpa_supplicant * wpa_s)2178d4f2939cSRui Paulo DBusMessage * wpas_dbus_handler_add_persistent_group(
2179d4f2939cSRui Paulo 	DBusMessage *message, struct wpa_supplicant *wpa_s)
2180d4f2939cSRui Paulo {
2181d4f2939cSRui Paulo 	DBusMessage *reply = NULL;
2182d4f2939cSRui Paulo 	DBusMessageIter	iter;
2183d4f2939cSRui Paulo 	struct wpa_ssid *ssid = NULL;
2184d4f2939cSRui Paulo 	char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf;
2185d4f2939cSRui Paulo 	DBusError error;
2186d4f2939cSRui Paulo 
2187d4f2939cSRui Paulo 	dbus_message_iter_init(message, &iter);
2188d4f2939cSRui Paulo 
2189325151a3SRui Paulo 	wpa_s = wpa_s->global->p2p_init_wpa_s;
2190c1d255d3SCy Schubert 	if (!wpa_s) {
2191c1d255d3SCy Schubert 		reply = wpas_dbus_error_no_p2p_mgmt_iface(message);
2192c1d255d3SCy Schubert 		goto err;
2193c1d255d3SCy Schubert 	}
2194c1d255d3SCy Schubert 
2195325151a3SRui Paulo 	if (wpa_s->parent->dbus_new_path)
2196d4f2939cSRui Paulo 		ssid = wpa_config_add_network(wpa_s->conf);
2197d4f2939cSRui Paulo 	if (ssid == NULL) {
21985b9c547cSRui Paulo 		wpa_printf(MSG_ERROR,
21995b9c547cSRui Paulo 			   "dbus: %s: Cannot add new persistent group",
22005b9c547cSRui Paulo 			   __func__);
2201d4f2939cSRui Paulo 		reply = wpas_dbus_error_unknown_error(
2202d4f2939cSRui Paulo 			message,
22035b9c547cSRui Paulo 			"wpa_supplicant could not add a persistent group on this interface.");
2204d4f2939cSRui Paulo 		goto err;
2205d4f2939cSRui Paulo 	}
2206d4f2939cSRui Paulo 
2207d4f2939cSRui Paulo 	/* Mark the ssid as being a persistent group before the notification */
2208d4f2939cSRui Paulo 	ssid->disabled = 2;
2209d4f2939cSRui Paulo 	ssid->p2p_persistent_group = 1;
2210d4f2939cSRui Paulo 	wpas_notify_persistent_group_added(wpa_s, ssid);
2211d4f2939cSRui Paulo 
2212d4f2939cSRui Paulo 	wpa_config_set_network_defaults(ssid);
2213d4f2939cSRui Paulo 
2214d4f2939cSRui Paulo 	dbus_error_init(&error);
2215d4f2939cSRui Paulo 	if (!set_network_properties(wpa_s, ssid, &iter, &error)) {
22165b9c547cSRui Paulo 		wpa_printf(MSG_DEBUG,
22175b9c547cSRui Paulo 			   "dbus: %s: Control interface could not set persistent group properties",
22185b9c547cSRui Paulo 			   __func__);
22195b9c547cSRui Paulo 		reply = wpas_dbus_reply_new_from_error(
22205b9c547cSRui Paulo 			message, &error, DBUS_ERROR_INVALID_ARGS,
22215b9c547cSRui Paulo 			"Failed to set network properties");
2222d4f2939cSRui Paulo 		dbus_error_free(&error);
2223d4f2939cSRui Paulo 		goto err;
2224d4f2939cSRui Paulo 	}
2225d4f2939cSRui Paulo 
2226d4f2939cSRui Paulo 	/* Construct the object path for this network. */
2227d4f2939cSRui Paulo 	os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
2228d4f2939cSRui Paulo 		    "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%d",
2229325151a3SRui Paulo 		    wpa_s->parent->dbus_new_path, ssid->id);
2230d4f2939cSRui Paulo 
2231d4f2939cSRui Paulo 	reply = dbus_message_new_method_return(message);
2232d4f2939cSRui Paulo 	if (reply == NULL) {
22335b9c547cSRui Paulo 		reply = wpas_dbus_error_no_memory(message);
2234d4f2939cSRui Paulo 		goto err;
2235d4f2939cSRui Paulo 	}
2236d4f2939cSRui Paulo 	if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
2237d4f2939cSRui Paulo 				      DBUS_TYPE_INVALID)) {
2238d4f2939cSRui Paulo 		dbus_message_unref(reply);
22395b9c547cSRui Paulo 		reply = wpas_dbus_error_no_memory(message);
2240d4f2939cSRui Paulo 		goto err;
2241d4f2939cSRui Paulo 	}
2242d4f2939cSRui Paulo 
2243d4f2939cSRui Paulo 	return reply;
2244d4f2939cSRui Paulo 
2245d4f2939cSRui Paulo err:
2246d4f2939cSRui Paulo 	if (ssid) {
2247d4f2939cSRui Paulo 		wpas_notify_persistent_group_removed(wpa_s, ssid);
2248d4f2939cSRui Paulo 		wpa_config_remove_network(wpa_s->conf, ssid->id);
2249d4f2939cSRui Paulo 	}
2250d4f2939cSRui Paulo 	return reply;
2251d4f2939cSRui Paulo }
2252d4f2939cSRui Paulo 
2253d4f2939cSRui Paulo 
2254d4f2939cSRui Paulo /**
2255d4f2939cSRui Paulo  * wpas_dbus_handler_remove_persistent_group - Remove a configured persistent
2256d4f2939cSRui Paulo  *	group
2257d4f2939cSRui Paulo  * @message: Pointer to incoming dbus message
2258d4f2939cSRui Paulo  * @wpa_s: wpa_supplicant structure for a network interface
2259d4f2939cSRui Paulo  * Returns: NULL on success or dbus error on failure
2260d4f2939cSRui Paulo  *
2261d4f2939cSRui Paulo  * Handler function for "RemovePersistentGroup" method call of a P2P Device
2262d4f2939cSRui Paulo  * interface.
2263d4f2939cSRui Paulo  */
wpas_dbus_handler_remove_persistent_group(DBusMessage * message,struct wpa_supplicant * wpa_s)2264d4f2939cSRui Paulo DBusMessage * wpas_dbus_handler_remove_persistent_group(
2265d4f2939cSRui Paulo 	DBusMessage *message, struct wpa_supplicant *wpa_s)
2266d4f2939cSRui Paulo {
2267d4f2939cSRui Paulo 	DBusMessage *reply = NULL;
2268d4f2939cSRui Paulo 	const char *op;
22695b9c547cSRui Paulo 	char *iface = NULL, *persistent_group_id;
2270d4f2939cSRui Paulo 	int id;
2271d4f2939cSRui Paulo 	struct wpa_ssid *ssid;
2272d4f2939cSRui Paulo 
2273d4f2939cSRui Paulo 	dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
2274d4f2939cSRui Paulo 			      DBUS_TYPE_INVALID);
2275d4f2939cSRui Paulo 
2276325151a3SRui Paulo 	wpa_s = wpa_s->global->p2p_init_wpa_s;
2277c1d255d3SCy Schubert 	if (!wpa_s) {
2278c1d255d3SCy Schubert 		reply = wpas_dbus_error_no_p2p_mgmt_iface(message);
2279c1d255d3SCy Schubert 		goto out;
2280c1d255d3SCy Schubert 	}
2281325151a3SRui Paulo 
2282d4f2939cSRui Paulo 	/*
2283d4f2939cSRui Paulo 	 * Extract the network ID and ensure the network is actually a child of
2284d4f2939cSRui Paulo 	 * this interface.
2285d4f2939cSRui Paulo 	 */
22865b9c547cSRui Paulo 	iface = wpas_dbus_new_decompose_object_path(
22875b9c547cSRui Paulo 		op, WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART,
22885b9c547cSRui Paulo 		&persistent_group_id);
22895b9c547cSRui Paulo 	if (iface == NULL || persistent_group_id == NULL ||
2290325151a3SRui Paulo 	    !wpa_s->parent->dbus_new_path ||
2291325151a3SRui Paulo 	    os_strcmp(iface, wpa_s->parent->dbus_new_path) != 0) {
2292d4f2939cSRui Paulo 		reply = wpas_dbus_error_invalid_args(message, op);
2293d4f2939cSRui Paulo 		goto out;
2294d4f2939cSRui Paulo 	}
2295d4f2939cSRui Paulo 
2296d4f2939cSRui Paulo 	id = strtoul(persistent_group_id, NULL, 10);
2297d4f2939cSRui Paulo 	if (errno == EINVAL) {
2298d4f2939cSRui Paulo 		reply = wpas_dbus_error_invalid_args(message, op);
2299d4f2939cSRui Paulo 		goto out;
2300d4f2939cSRui Paulo 	}
2301d4f2939cSRui Paulo 
2302d4f2939cSRui Paulo 	ssid = wpa_config_get_network(wpa_s->conf, id);
2303d4f2939cSRui Paulo 	if (ssid == NULL) {
2304d4f2939cSRui Paulo 		reply = wpas_dbus_error_persistent_group_unknown(message);
2305d4f2939cSRui Paulo 		goto out;
2306d4f2939cSRui Paulo 	}
2307d4f2939cSRui Paulo 
2308d4f2939cSRui Paulo 	wpas_notify_persistent_group_removed(wpa_s, ssid);
2309d4f2939cSRui Paulo 
2310d4f2939cSRui Paulo 	if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
23115b9c547cSRui Paulo 		wpa_printf(MSG_ERROR,
23125b9c547cSRui Paulo 			   "dbus: %s: error occurred when removing persistent group %d",
2313d4f2939cSRui Paulo 			   __func__, id);
2314d4f2939cSRui Paulo 		reply = wpas_dbus_error_unknown_error(
2315d4f2939cSRui Paulo 			message,
23165b9c547cSRui Paulo 			"error removing the specified persistent group on this interface.");
2317d4f2939cSRui Paulo 		goto out;
2318d4f2939cSRui Paulo 	}
2319d4f2939cSRui Paulo 
2320d4f2939cSRui Paulo out:
2321d4f2939cSRui Paulo 	os_free(iface);
2322d4f2939cSRui Paulo 	return reply;
2323d4f2939cSRui Paulo }
2324d4f2939cSRui Paulo 
2325d4f2939cSRui Paulo 
remove_persistent_group(struct wpa_supplicant * wpa_s,struct wpa_ssid * ssid)2326d4f2939cSRui Paulo static void remove_persistent_group(struct wpa_supplicant *wpa_s,
2327d4f2939cSRui Paulo 				    struct wpa_ssid *ssid)
2328d4f2939cSRui Paulo {
2329d4f2939cSRui Paulo 	wpas_notify_persistent_group_removed(wpa_s, ssid);
2330d4f2939cSRui Paulo 
2331d4f2939cSRui Paulo 	if (wpa_config_remove_network(wpa_s->conf, ssid->id) < 0) {
23325b9c547cSRui Paulo 		wpa_printf(MSG_ERROR,
23335b9c547cSRui Paulo 			   "dbus: %s: error occurred when removing persistent group %d",
2334d4f2939cSRui Paulo 			   __func__, ssid->id);
2335d4f2939cSRui Paulo 		return;
2336d4f2939cSRui Paulo 	}
2337d4f2939cSRui Paulo }
2338d4f2939cSRui Paulo 
2339d4f2939cSRui Paulo 
2340d4f2939cSRui Paulo /**
2341d4f2939cSRui Paulo  * wpas_dbus_handler_remove_all_persistent_groups - Remove all configured
2342d4f2939cSRui Paulo  * persistent groups
2343d4f2939cSRui Paulo  * @message: Pointer to incoming dbus message
2344d4f2939cSRui Paulo  * @wpa_s: wpa_supplicant structure for a network interface
2345d4f2939cSRui Paulo  * Returns: NULL on success or dbus error on failure
2346d4f2939cSRui Paulo  *
2347d4f2939cSRui Paulo  * Handler function for "RemoveAllPersistentGroups" method call of a
2348d4f2939cSRui Paulo  * P2P Device interface.
2349d4f2939cSRui Paulo  */
wpas_dbus_handler_remove_all_persistent_groups(DBusMessage * message,struct wpa_supplicant * wpa_s)2350d4f2939cSRui Paulo DBusMessage * wpas_dbus_handler_remove_all_persistent_groups(
2351d4f2939cSRui Paulo 	DBusMessage *message, struct wpa_supplicant *wpa_s)
2352d4f2939cSRui Paulo {
2353d4f2939cSRui Paulo 	struct wpa_ssid *ssid, *next;
2354d4f2939cSRui Paulo 	struct wpa_config *config;
2355d4f2939cSRui Paulo 
2356325151a3SRui Paulo 	wpa_s = wpa_s->global->p2p_init_wpa_s;
2357c1d255d3SCy Schubert 	if (!wpa_s)
2358c1d255d3SCy Schubert 		return wpas_dbus_error_no_p2p_mgmt_iface(message);
2359325151a3SRui Paulo 
2360d4f2939cSRui Paulo 	config = wpa_s->conf;
2361d4f2939cSRui Paulo 	ssid = config->ssid;
2362d4f2939cSRui Paulo 	while (ssid) {
2363d4f2939cSRui Paulo 		next = ssid->next;
2364d4f2939cSRui Paulo 		if (network_is_persistent_group(ssid))
2365d4f2939cSRui Paulo 			remove_persistent_group(wpa_s, ssid);
2366d4f2939cSRui Paulo 		ssid = next;
2367d4f2939cSRui Paulo 	}
2368d4f2939cSRui Paulo 	return NULL;
2369d4f2939cSRui Paulo }
2370d4f2939cSRui Paulo 
2371d4f2939cSRui Paulo 
2372d4f2939cSRui Paulo /*
2373d4f2939cSRui Paulo  * Group object properties accessor methods
2374d4f2939cSRui Paulo  */
2375d4f2939cSRui Paulo 
wpas_dbus_getter_p2p_group_members(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)2376780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_p2p_group_members(
2377780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
2378780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
2379d4f2939cSRui Paulo {
2380d4f2939cSRui Paulo 	struct wpa_supplicant *wpa_s = user_data;
2381d4f2939cSRui Paulo 	struct wpa_ssid *ssid;
2382d4f2939cSRui Paulo 	unsigned int num_members;
2383d4f2939cSRui Paulo 	char **paths;
2384d4f2939cSRui Paulo 	unsigned int i;
2385d4f2939cSRui Paulo 	void *next = NULL;
2386d4f2939cSRui Paulo 	const u8 *addr;
2387d4f2939cSRui Paulo 	dbus_bool_t success = FALSE;
2388d4f2939cSRui Paulo 
2389325151a3SRui Paulo 	if (!wpa_s->parent->parent->dbus_new_path)
2390325151a3SRui Paulo 		return FALSE;
2391325151a3SRui Paulo 
2392d4f2939cSRui Paulo 	/* Verify correct role for this property */
2393d4f2939cSRui Paulo 	if (wpas_get_p2p_role(wpa_s) != WPAS_P2P_ROLE_GO) {
2394d4f2939cSRui Paulo 		return wpas_dbus_simple_array_property_getter(
2395d4f2939cSRui Paulo 			iter, DBUS_TYPE_OBJECT_PATH, NULL, 0, error);
2396d4f2939cSRui Paulo 	}
2397d4f2939cSRui Paulo 
2398d4f2939cSRui Paulo 	ssid = wpa_s->conf->ssid;
2399d4f2939cSRui Paulo 	/* At present WPAS P2P_GO mode only applicable for p2p_go */
2400d4f2939cSRui Paulo 	if (ssid->mode != WPAS_MODE_P2P_GO &&
2401d4f2939cSRui Paulo 	    ssid->mode != WPAS_MODE_AP &&
2402d4f2939cSRui Paulo 	    ssid->mode != WPAS_MODE_P2P_GROUP_FORMATION)
2403d4f2939cSRui Paulo 		return FALSE;
2404d4f2939cSRui Paulo 
2405d4f2939cSRui Paulo 	num_members = p2p_get_group_num_members(wpa_s->p2p_group);
2406d4f2939cSRui Paulo 
2407d4f2939cSRui Paulo 	paths = os_calloc(num_members, sizeof(char *));
2408d4f2939cSRui Paulo 	if (!paths)
2409d4f2939cSRui Paulo 		goto out_of_memory;
2410d4f2939cSRui Paulo 
2411d4f2939cSRui Paulo 	i = 0;
2412d4f2939cSRui Paulo 	while ((addr = p2p_iterate_group_members(wpa_s->p2p_group, &next))) {
2413d4f2939cSRui Paulo 		paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
2414d4f2939cSRui Paulo 		if (!paths[i])
2415d4f2939cSRui Paulo 			goto out_of_memory;
2416d4f2939cSRui Paulo 		os_snprintf(paths[i], WPAS_DBUS_OBJECT_PATH_MAX,
24175b9c547cSRui Paulo 			    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART
2418d4f2939cSRui Paulo 			    "/" COMPACT_MACSTR,
2419325151a3SRui Paulo 			    wpa_s->parent->parent->dbus_new_path,
2420325151a3SRui Paulo 			    MAC2STR(addr));
2421d4f2939cSRui Paulo 		i++;
2422d4f2939cSRui Paulo 	}
2423d4f2939cSRui Paulo 
2424d4f2939cSRui Paulo 	success = wpas_dbus_simple_array_property_getter(iter,
2425d4f2939cSRui Paulo 							 DBUS_TYPE_OBJECT_PATH,
2426d4f2939cSRui Paulo 							 paths, num_members,
2427d4f2939cSRui Paulo 							 error);
2428d4f2939cSRui Paulo 
2429d4f2939cSRui Paulo 	for (i = 0; i < num_members; i++)
2430d4f2939cSRui Paulo 		os_free(paths[i]);
2431d4f2939cSRui Paulo 	os_free(paths);
2432d4f2939cSRui Paulo 	return success;
2433d4f2939cSRui Paulo 
2434d4f2939cSRui Paulo out_of_memory:
2435d4f2939cSRui Paulo 	dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
2436d4f2939cSRui Paulo 	if (paths) {
2437d4f2939cSRui Paulo 		for (i = 0; i < num_members; i++)
2438d4f2939cSRui Paulo 			os_free(paths[i]);
2439d4f2939cSRui Paulo 		os_free(paths);
2440d4f2939cSRui Paulo 	}
2441d4f2939cSRui Paulo 	return FALSE;
2442d4f2939cSRui Paulo }
2443d4f2939cSRui Paulo 
2444d4f2939cSRui Paulo 
wpas_dbus_getter_p2p_group_ssid(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)2445780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_p2p_group_ssid(
2446780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
2447780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
2448d4f2939cSRui Paulo {
2449d4f2939cSRui Paulo 	struct wpa_supplicant *wpa_s = user_data;
24505b9c547cSRui Paulo 
2451d4f2939cSRui Paulo 	if (wpa_s->current_ssid == NULL)
2452d4f2939cSRui Paulo 		return FALSE;
2453d4f2939cSRui Paulo 	return wpas_dbus_simple_array_property_getter(
2454d4f2939cSRui Paulo 		iter, DBUS_TYPE_BYTE, wpa_s->current_ssid->ssid,
2455d4f2939cSRui Paulo 		wpa_s->current_ssid->ssid_len, error);
2456d4f2939cSRui Paulo }
2457d4f2939cSRui Paulo 
2458d4f2939cSRui Paulo 
wpas_dbus_getter_p2p_group_bssid(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)2459780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_p2p_group_bssid(
2460780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
2461780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
2462d4f2939cSRui Paulo {
2463d4f2939cSRui Paulo 	struct wpa_supplicant *wpa_s = user_data;
2464d4f2939cSRui Paulo 	u8 role = wpas_get_p2p_role(wpa_s);
2465d4f2939cSRui Paulo 	u8 *p_bssid;
2466d4f2939cSRui Paulo 
2467d4f2939cSRui Paulo 	if (role == WPAS_P2P_ROLE_CLIENT) {
2468*a90b9d01SCy Schubert 		if (!wpa_s->current_bss)
2469d4f2939cSRui Paulo 			return FALSE;
2470*a90b9d01SCy Schubert 		p_bssid = wpa_s->current_bss->bssid;
2471d4f2939cSRui Paulo 	} else {
2472d4f2939cSRui Paulo 		if (wpa_s->ap_iface == NULL)
2473d4f2939cSRui Paulo 			return FALSE;
2474d4f2939cSRui Paulo 		p_bssid = wpa_s->ap_iface->bss[0]->own_addr;
2475d4f2939cSRui Paulo 	}
2476d4f2939cSRui Paulo 
2477d4f2939cSRui Paulo 	return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
2478d4f2939cSRui Paulo 						      p_bssid, ETH_ALEN,
2479d4f2939cSRui Paulo 						      error);
2480d4f2939cSRui Paulo }
2481d4f2939cSRui Paulo 
2482d4f2939cSRui Paulo 
wpas_dbus_getter_p2p_group_frequency(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)2483780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_p2p_group_frequency(
2484780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
2485780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
2486d4f2939cSRui Paulo {
2487d4f2939cSRui Paulo 	struct wpa_supplicant *wpa_s = user_data;
2488d4f2939cSRui Paulo 	u16 op_freq;
2489d4f2939cSRui Paulo 	u8 role = wpas_get_p2p_role(wpa_s);
2490d4f2939cSRui Paulo 
2491d4f2939cSRui Paulo 	if (role == WPAS_P2P_ROLE_CLIENT) {
2492*a90b9d01SCy Schubert 		if (!wpa_s->current_bss)
2493d4f2939cSRui Paulo 			return FALSE;
2494*a90b9d01SCy Schubert 		op_freq = wpa_s->current_bss->freq;
2495d4f2939cSRui Paulo 	} else {
2496d4f2939cSRui Paulo 		if (wpa_s->ap_iface == NULL)
2497d4f2939cSRui Paulo 			return FALSE;
2498d4f2939cSRui Paulo 		op_freq = wpa_s->ap_iface->freq;
2499d4f2939cSRui Paulo 	}
2500d4f2939cSRui Paulo 
2501d4f2939cSRui Paulo 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
2502d4f2939cSRui Paulo 						&op_freq, error);
2503d4f2939cSRui Paulo }
2504d4f2939cSRui Paulo 
2505d4f2939cSRui Paulo 
wpas_dbus_getter_p2p_group_passphrase(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)2506780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_p2p_group_passphrase(
2507780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
2508780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
2509d4f2939cSRui Paulo {
2510d4f2939cSRui Paulo 	struct wpa_supplicant *wpa_s = user_data;
25115b9c547cSRui Paulo 	struct wpa_ssid *ssid = wpa_s->current_ssid;
2512d4f2939cSRui Paulo 
25135b9c547cSRui Paulo 	if (ssid == NULL)
2514d4f2939cSRui Paulo 		return FALSE;
25155b9c547cSRui Paulo 
251685732ac8SCy Schubert 	return wpas_dbus_string_property_getter(iter, ssid->passphrase, error);
2517d4f2939cSRui Paulo }
2518d4f2939cSRui Paulo 
2519d4f2939cSRui Paulo 
wpas_dbus_getter_p2p_group_psk(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)2520780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_p2p_group_psk(
2521780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
2522780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
2523d4f2939cSRui Paulo {
2524d4f2939cSRui Paulo 	struct wpa_supplicant *wpa_s = user_data;
2525d4f2939cSRui Paulo 	u8 *p_psk = NULL;
2526d4f2939cSRui Paulo 	u8 psk_len = 0;
25275b9c547cSRui Paulo 	struct wpa_ssid *ssid = wpa_s->current_ssid;
2528d4f2939cSRui Paulo 
25295b9c547cSRui Paulo 	if (ssid == NULL)
2530d4f2939cSRui Paulo 		return FALSE;
25315b9c547cSRui Paulo 
25325b9c547cSRui Paulo 	if (ssid->psk_set) {
25335b9c547cSRui Paulo 		p_psk = ssid->psk;
25345b9c547cSRui Paulo 		psk_len = sizeof(ssid->psk);
2535d4f2939cSRui Paulo 	}
2536d4f2939cSRui Paulo 
2537d4f2939cSRui Paulo 	return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
25385b9c547cSRui Paulo 						      p_psk, psk_len, error);
2539d4f2939cSRui Paulo }
2540d4f2939cSRui Paulo 
2541d4f2939cSRui Paulo 
wpas_dbus_getter_p2p_group_vendor_ext(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)2542780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_p2p_group_vendor_ext(
2543780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
2544780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
2545d4f2939cSRui Paulo {
2546d4f2939cSRui Paulo 	struct wpa_supplicant *wpa_s = user_data;
2547d4f2939cSRui Paulo 	struct hostapd_data *hapd;
2548d4f2939cSRui Paulo 	struct wpabuf *vendor_ext[MAX_WPS_VENDOR_EXTENSIONS];
25495b9c547cSRui Paulo 	unsigned int i, num_vendor_ext = 0;
25505b9c547cSRui Paulo 
25515b9c547cSRui Paulo 	os_memset(vendor_ext, 0, sizeof(vendor_ext));
2552d4f2939cSRui Paulo 
2553d4f2939cSRui Paulo 	/* Verify correct role for this property */
2554d4f2939cSRui Paulo 	if (wpas_get_p2p_role(wpa_s) == WPAS_P2P_ROLE_GO) {
2555d4f2939cSRui Paulo 		if (wpa_s->ap_iface == NULL)
2556d4f2939cSRui Paulo 			return FALSE;
2557d4f2939cSRui Paulo 		hapd = wpa_s->ap_iface->bss[0];
2558d4f2939cSRui Paulo 
2559d4f2939cSRui Paulo 		/* Parse WPS Vendor Extensions sent in Beacon/Probe Response */
2560d4f2939cSRui Paulo 		for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
2561d4f2939cSRui Paulo 			if (hapd->conf->wps_vendor_ext[i] == NULL)
25625b9c547cSRui Paulo 				continue;
2563d4f2939cSRui Paulo 			vendor_ext[num_vendor_ext++] =
2564d4f2939cSRui Paulo 				hapd->conf->wps_vendor_ext[i];
2565d4f2939cSRui Paulo 		}
2566d4f2939cSRui Paulo 	}
2567d4f2939cSRui Paulo 
2568d4f2939cSRui Paulo 	/* Return vendor extensions or no data */
2569d4f2939cSRui Paulo 	return wpas_dbus_simple_array_array_property_getter(iter,
2570d4f2939cSRui Paulo 							    DBUS_TYPE_BYTE,
2571d4f2939cSRui Paulo 							    vendor_ext,
2572d4f2939cSRui Paulo 							    num_vendor_ext,
2573d4f2939cSRui Paulo 							    error);
2574d4f2939cSRui Paulo }
2575d4f2939cSRui Paulo 
2576d4f2939cSRui Paulo 
wpas_dbus_setter_p2p_group_vendor_ext(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)2577780fb4a2SCy Schubert dbus_bool_t wpas_dbus_setter_p2p_group_vendor_ext(
2578780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
2579780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
2580d4f2939cSRui Paulo {
2581d4f2939cSRui Paulo 	struct wpa_supplicant *wpa_s = user_data;
25825b9c547cSRui Paulo 	DBusMessageIter variant_iter, iter_dict, array_iter, sub;
2583d4f2939cSRui Paulo 	struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
2584d4f2939cSRui Paulo 	unsigned int i;
2585d4f2939cSRui Paulo 	struct hostapd_data *hapd = NULL;
2586d4f2939cSRui Paulo 
2587d4f2939cSRui Paulo 	if (wpas_get_p2p_role(wpa_s) == WPAS_P2P_ROLE_GO &&
2588d4f2939cSRui Paulo 	    wpa_s->ap_iface != NULL)
2589d4f2939cSRui Paulo 		hapd = wpa_s->ap_iface->bss[0];
2590d4f2939cSRui Paulo 	else
2591d4f2939cSRui Paulo 		return FALSE;
2592d4f2939cSRui Paulo 
2593d4f2939cSRui Paulo 	dbus_message_iter_recurse(iter, &variant_iter);
25945b9c547cSRui Paulo 	if (dbus_message_iter_get_arg_type(&variant_iter) != DBUS_TYPE_ARRAY)
25955b9c547cSRui Paulo 		return FALSE;
25965b9c547cSRui Paulo 
25975b9c547cSRui Paulo 	/*
25985b9c547cSRui Paulo 	 * This is supposed to be array of bytearrays (aay), but the earlier
25995b9c547cSRui Paulo 	 * implementation used a dict with "WPSVendorExtensions" as the key in
26005b9c547cSRui Paulo 	 * this setter function which does not match the format used by the
26015b9c547cSRui Paulo 	 * getter function. For backwards compatibility, allow both formats to
26025b9c547cSRui Paulo 	 * be used in the setter.
26035b9c547cSRui Paulo 	 */
26045b9c547cSRui Paulo 	if (dbus_message_iter_get_element_type(&variant_iter) ==
26055b9c547cSRui Paulo 	    DBUS_TYPE_ARRAY) {
26065b9c547cSRui Paulo 		/* This is the proper format matching the getter */
26075b9c547cSRui Paulo 		struct wpabuf *vals[MAX_WPS_VENDOR_EXTENSIONS];
26085b9c547cSRui Paulo 
26095b9c547cSRui Paulo 		dbus_message_iter_recurse(&variant_iter, &array_iter);
26105b9c547cSRui Paulo 
26115b9c547cSRui Paulo 		if (dbus_message_iter_get_arg_type(&array_iter) !=
26125b9c547cSRui Paulo 		    DBUS_TYPE_ARRAY ||
26135b9c547cSRui Paulo 		    dbus_message_iter_get_element_type(&array_iter) !=
26145b9c547cSRui Paulo 		    DBUS_TYPE_BYTE) {
26155b9c547cSRui Paulo 			wpa_printf(MSG_DEBUG,
26165b9c547cSRui Paulo 				   "dbus: Not an array of array of bytes");
26175b9c547cSRui Paulo 			return FALSE;
26185b9c547cSRui Paulo 		}
26195b9c547cSRui Paulo 
26205b9c547cSRui Paulo 		i = 0;
26215b9c547cSRui Paulo 		os_memset(vals, 0, sizeof(vals));
26225b9c547cSRui Paulo 
26235b9c547cSRui Paulo 		while (dbus_message_iter_get_arg_type(&array_iter) ==
26245b9c547cSRui Paulo 		       DBUS_TYPE_ARRAY) {
26255b9c547cSRui Paulo 			char *val;
26265b9c547cSRui Paulo 			int len;
26275b9c547cSRui Paulo 
26285b9c547cSRui Paulo 			if (i == MAX_WPS_VENDOR_EXTENSIONS) {
26295b9c547cSRui Paulo 				wpa_printf(MSG_DEBUG,
26305b9c547cSRui Paulo 					   "dbus: Too many WPSVendorExtensions values");
26315b9c547cSRui Paulo 				i = MAX_WPS_VENDOR_EXTENSIONS + 1;
26325b9c547cSRui Paulo 				break;
26335b9c547cSRui Paulo 			}
26345b9c547cSRui Paulo 
26355b9c547cSRui Paulo 			dbus_message_iter_recurse(&array_iter, &sub);
26365b9c547cSRui Paulo 			dbus_message_iter_get_fixed_array(&sub, &val, &len);
26375b9c547cSRui Paulo 			wpa_hexdump(MSG_DEBUG, "dbus: WPSVendorExtentions[]",
26385b9c547cSRui Paulo 				    val, len);
26395b9c547cSRui Paulo 			vals[i] = wpabuf_alloc_copy(val, len);
26405b9c547cSRui Paulo 			if (vals[i] == NULL) {
26415b9c547cSRui Paulo 				i = MAX_WPS_VENDOR_EXTENSIONS + 1;
26425b9c547cSRui Paulo 				break;
26435b9c547cSRui Paulo 			}
26445b9c547cSRui Paulo 			i++;
26455b9c547cSRui Paulo 			dbus_message_iter_next(&array_iter);
26465b9c547cSRui Paulo 		}
26475b9c547cSRui Paulo 
26485b9c547cSRui Paulo 		if (i > MAX_WPS_VENDOR_EXTENSIONS) {
26495b9c547cSRui Paulo 			for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++)
26505b9c547cSRui Paulo 				wpabuf_free(vals[i]);
26515b9c547cSRui Paulo 			return FALSE;
26525b9c547cSRui Paulo 		}
26535b9c547cSRui Paulo 
26545b9c547cSRui Paulo 		for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
26555b9c547cSRui Paulo 			wpabuf_free(hapd->conf->wps_vendor_ext[i]);
26565b9c547cSRui Paulo 			hapd->conf->wps_vendor_ext[i] = vals[i];
26575b9c547cSRui Paulo 		}
26585b9c547cSRui Paulo 
26595b9c547cSRui Paulo 		hostapd_update_wps(hapd);
26605b9c547cSRui Paulo 
26615b9c547cSRui Paulo 		return TRUE;
26625b9c547cSRui Paulo 	}
26635b9c547cSRui Paulo 
26645b9c547cSRui Paulo 	if (dbus_message_iter_get_element_type(&variant_iter) !=
26655b9c547cSRui Paulo 	    DBUS_TYPE_DICT_ENTRY)
26665b9c547cSRui Paulo 		return FALSE;
26675b9c547cSRui Paulo 
26685b9c547cSRui Paulo 	wpa_printf(MSG_DEBUG,
26695b9c547cSRui Paulo 		   "dbus: Try to use backwards compatibility version of WPSVendorExtensions setter");
2670d4f2939cSRui Paulo 	if (!wpa_dbus_dict_open_read(&variant_iter, &iter_dict, error))
2671d4f2939cSRui Paulo 		return FALSE;
2672d4f2939cSRui Paulo 
2673d4f2939cSRui Paulo 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2674d4f2939cSRui Paulo 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) {
2675d4f2939cSRui Paulo 			dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
2676d4f2939cSRui Paulo 					     "invalid message format");
2677d4f2939cSRui Paulo 			return FALSE;
2678d4f2939cSRui Paulo 		}
2679d4f2939cSRui Paulo 
2680d4f2939cSRui Paulo 		if (os_strcmp(entry.key, "WPSVendorExtensions") == 0) {
2681d4f2939cSRui Paulo 			if (entry.type != DBUS_TYPE_ARRAY ||
2682d4f2939cSRui Paulo 			    entry.array_type != WPAS_DBUS_TYPE_BINARRAY ||
2683d4f2939cSRui Paulo 			    entry.array_len > MAX_WPS_VENDOR_EXTENSIONS)
2684d4f2939cSRui Paulo 				goto error;
2685d4f2939cSRui Paulo 
2686d4f2939cSRui Paulo 			for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
26875b9c547cSRui Paulo 				wpabuf_free(hapd->conf->wps_vendor_ext[i]);
2688d4f2939cSRui Paulo 				if (i < entry.array_len) {
2689d4f2939cSRui Paulo 					hapd->conf->wps_vendor_ext[i] =
2690d4f2939cSRui Paulo 						entry.binarray_value[i];
2691d4f2939cSRui Paulo 					entry.binarray_value[i] = NULL;
2692d4f2939cSRui Paulo 				} else
2693d4f2939cSRui Paulo 					hapd->conf->wps_vendor_ext[i] = NULL;
2694d4f2939cSRui Paulo 			}
2695d4f2939cSRui Paulo 
2696d4f2939cSRui Paulo 			hostapd_update_wps(hapd);
2697d4f2939cSRui Paulo 		} else
2698d4f2939cSRui Paulo 			goto error;
2699d4f2939cSRui Paulo 
2700d4f2939cSRui Paulo 		wpa_dbus_dict_entry_clear(&entry);
2701d4f2939cSRui Paulo 	}
2702d4f2939cSRui Paulo 
2703d4f2939cSRui Paulo 	return TRUE;
2704d4f2939cSRui Paulo 
2705d4f2939cSRui Paulo error:
2706d4f2939cSRui Paulo 	wpa_dbus_dict_entry_clear(&entry);
2707d4f2939cSRui Paulo 	dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
2708d4f2939cSRui Paulo 			     "invalid message format");
2709d4f2939cSRui Paulo 	return FALSE;
2710d4f2939cSRui Paulo }
2711d4f2939cSRui Paulo 
2712d4f2939cSRui Paulo 
wpas_dbus_handler_p2p_add_service(DBusMessage * message,struct wpa_supplicant * wpa_s)2713d4f2939cSRui Paulo DBusMessage * wpas_dbus_handler_p2p_add_service(DBusMessage *message,
2714d4f2939cSRui Paulo 						struct wpa_supplicant *wpa_s)
2715d4f2939cSRui Paulo {
2716d4f2939cSRui Paulo 	DBusMessageIter iter_dict;
2717d4f2939cSRui Paulo 	DBusMessage *reply = NULL;
2718d4f2939cSRui Paulo 	DBusMessageIter iter;
2719d4f2939cSRui Paulo 	struct wpa_dbus_dict_entry entry;
2720d4f2939cSRui Paulo 	int upnp = 0;
2721d4f2939cSRui Paulo 	int bonjour = 0;
2722d4f2939cSRui Paulo 	char *service = NULL;
2723d4f2939cSRui Paulo 	struct wpabuf *query = NULL;
2724d4f2939cSRui Paulo 	struct wpabuf *resp = NULL;
2725d4f2939cSRui Paulo 	u8 version = 0;
2726d4f2939cSRui Paulo 
2727d4f2939cSRui Paulo 	dbus_message_iter_init(message, &iter);
2728d4f2939cSRui Paulo 
2729d4f2939cSRui Paulo 	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
2730d4f2939cSRui Paulo 		goto error;
2731d4f2939cSRui Paulo 
2732d4f2939cSRui Paulo 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2733d4f2939cSRui Paulo 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2734d4f2939cSRui Paulo 			goto error;
2735d4f2939cSRui Paulo 
27365b9c547cSRui Paulo 		if (os_strcmp(entry.key, "service_type") == 0 &&
27375b9c547cSRui Paulo 		    entry.type == DBUS_TYPE_STRING) {
27385b9c547cSRui Paulo 			if (os_strcmp(entry.str_value, "upnp") == 0)
2739d4f2939cSRui Paulo 				upnp = 1;
27405b9c547cSRui Paulo 			else if (os_strcmp(entry.str_value, "bonjour") == 0)
2741d4f2939cSRui Paulo 				bonjour = 1;
2742d4f2939cSRui Paulo 			else
2743d4f2939cSRui Paulo 				goto error_clear;
27445b9c547cSRui Paulo 		} else if (os_strcmp(entry.key, "version") == 0 &&
2745d4f2939cSRui Paulo 			   entry.type == DBUS_TYPE_INT32) {
2746d4f2939cSRui Paulo 			version = entry.uint32_value;
27475b9c547cSRui Paulo 		} else if (os_strcmp(entry.key, "service") == 0 &&
27485b9c547cSRui Paulo 			   entry.type == DBUS_TYPE_STRING) {
27495b9c547cSRui Paulo 			os_free(service);
2750d4f2939cSRui Paulo 			service = os_strdup(entry.str_value);
27515b9c547cSRui Paulo 		} else if (os_strcmp(entry.key, "query") == 0) {
27525b9c547cSRui Paulo 			if (entry.type != DBUS_TYPE_ARRAY ||
27535b9c547cSRui Paulo 			    entry.array_type != DBUS_TYPE_BYTE)
2754d4f2939cSRui Paulo 				goto error_clear;
2755d4f2939cSRui Paulo 			query = wpabuf_alloc_copy(
2756d4f2939cSRui Paulo 				entry.bytearray_value,
2757d4f2939cSRui Paulo 				entry.array_len);
27585b9c547cSRui Paulo 		} else if (os_strcmp(entry.key, "response") == 0) {
27595b9c547cSRui Paulo 			if (entry.type != DBUS_TYPE_ARRAY ||
27605b9c547cSRui Paulo 			    entry.array_type != DBUS_TYPE_BYTE)
2761d4f2939cSRui Paulo 				goto error_clear;
2762d4f2939cSRui Paulo 			resp = wpabuf_alloc_copy(entry.bytearray_value,
2763d4f2939cSRui Paulo 						 entry.array_len);
2764d4f2939cSRui Paulo 		}
2765d4f2939cSRui Paulo 		wpa_dbus_dict_entry_clear(&entry);
2766d4f2939cSRui Paulo 	}
2767d4f2939cSRui Paulo 
2768d4f2939cSRui Paulo 	if (upnp == 1) {
2769d4f2939cSRui Paulo 		if (version <= 0 || service == NULL)
2770d4f2939cSRui Paulo 			goto error;
2771d4f2939cSRui Paulo 
2772d4f2939cSRui Paulo 		if (wpas_p2p_service_add_upnp(wpa_s, version, service) != 0)
2773d4f2939cSRui Paulo 			goto error;
2774d4f2939cSRui Paulo 
2775d4f2939cSRui Paulo 	} else if (bonjour == 1) {
2776d4f2939cSRui Paulo 		if (query == NULL || resp == NULL)
2777d4f2939cSRui Paulo 			goto error;
2778d4f2939cSRui Paulo 
2779d4f2939cSRui Paulo 		if (wpas_p2p_service_add_bonjour(wpa_s, query, resp) < 0)
2780d4f2939cSRui Paulo 			goto error;
2781d4f2939cSRui Paulo 	} else
2782d4f2939cSRui Paulo 		goto error;
2783d4f2939cSRui Paulo 
2784*a90b9d01SCy Schubert out:
27855b9c547cSRui Paulo 	os_free(service);
2786*a90b9d01SCy Schubert 	wpabuf_free(query);
2787*a90b9d01SCy Schubert 	wpabuf_free(resp);
2788*a90b9d01SCy Schubert 
2789d4f2939cSRui Paulo 	return reply;
2790d4f2939cSRui Paulo error_clear:
2791d4f2939cSRui Paulo 	wpa_dbus_dict_entry_clear(&entry);
2792d4f2939cSRui Paulo error:
2793*a90b9d01SCy Schubert 	reply = wpas_dbus_error_invalid_args(message, NULL);
2794*a90b9d01SCy Schubert 	goto out;
2795d4f2939cSRui Paulo }
2796d4f2939cSRui Paulo 
2797d4f2939cSRui Paulo 
wpas_dbus_handler_p2p_delete_service(DBusMessage * message,struct wpa_supplicant * wpa_s)2798d4f2939cSRui Paulo DBusMessage * wpas_dbus_handler_p2p_delete_service(
2799d4f2939cSRui Paulo 	DBusMessage *message, struct wpa_supplicant *wpa_s)
2800d4f2939cSRui Paulo {
2801d4f2939cSRui Paulo 	DBusMessageIter iter_dict;
2802d4f2939cSRui Paulo 	DBusMessage *reply = NULL;
2803d4f2939cSRui Paulo 	DBusMessageIter iter;
2804d4f2939cSRui Paulo 	struct wpa_dbus_dict_entry entry;
2805d4f2939cSRui Paulo 	int upnp = 0;
2806d4f2939cSRui Paulo 	int bonjour = 0;
2807d4f2939cSRui Paulo 	int ret = 0;
2808d4f2939cSRui Paulo 	char *service = NULL;
2809d4f2939cSRui Paulo 	struct wpabuf *query = NULL;
2810d4f2939cSRui Paulo 	u8 version = 0;
2811d4f2939cSRui Paulo 
2812d4f2939cSRui Paulo 	dbus_message_iter_init(message, &iter);
2813d4f2939cSRui Paulo 
2814d4f2939cSRui Paulo 	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
2815d4f2939cSRui Paulo 		goto error;
2816d4f2939cSRui Paulo 
28174bc52338SCy Schubert 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2818d4f2939cSRui Paulo 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2819d4f2939cSRui Paulo 			goto error;
2820d4f2939cSRui Paulo 
28215b9c547cSRui Paulo 		if (os_strcmp(entry.key, "service_type") == 0 &&
28225b9c547cSRui Paulo 		    entry.type == DBUS_TYPE_STRING) {
28235b9c547cSRui Paulo 			if (os_strcmp(entry.str_value, "upnp") == 0)
2824d4f2939cSRui Paulo 				upnp = 1;
28255b9c547cSRui Paulo 			else if (os_strcmp(entry.str_value, "bonjour") == 0)
2826d4f2939cSRui Paulo 				bonjour = 1;
2827d4f2939cSRui Paulo 			else
2828d4f2939cSRui Paulo 				goto error_clear;
28294bc52338SCy Schubert 		} else if (os_strcmp(entry.key, "version") == 0 &&
28304bc52338SCy Schubert 			   entry.type == DBUS_TYPE_INT32) {
2831d4f2939cSRui Paulo 			version = entry.uint32_value;
28324bc52338SCy Schubert 		} else if (os_strcmp(entry.key, "service") == 0 &&
28335b9c547cSRui Paulo 			   entry.type == DBUS_TYPE_STRING) {
28345b9c547cSRui Paulo 			os_free(service);
2835d4f2939cSRui Paulo 			service = os_strdup(entry.str_value);
28364bc52338SCy Schubert 		} else if (os_strcmp(entry.key, "query") == 0) {
28374bc52338SCy Schubert 			if (entry.type != DBUS_TYPE_ARRAY ||
28384bc52338SCy Schubert 			    entry.array_type != DBUS_TYPE_BYTE)
2839d4f2939cSRui Paulo 				goto error_clear;
28404bc52338SCy Schubert 			wpabuf_free(query);
28414bc52338SCy Schubert 			query = wpabuf_alloc_copy(entry.bytearray_value,
28424bc52338SCy Schubert 						  entry.array_len);
28434bc52338SCy Schubert 		} else {
28444bc52338SCy Schubert 			goto error_clear;
28454bc52338SCy Schubert 		}
2846d4f2939cSRui Paulo 
2847d4f2939cSRui Paulo 		wpa_dbus_dict_entry_clear(&entry);
2848d4f2939cSRui Paulo 	}
28494bc52338SCy Schubert 	if (upnp == 1) {
2850d4f2939cSRui Paulo 		if (version <= 0 || service == NULL)
2851d4f2939cSRui Paulo 			goto error;
2852d4f2939cSRui Paulo 
2853d4f2939cSRui Paulo 		ret = wpas_p2p_service_del_upnp(wpa_s, version, service);
2854d4f2939cSRui Paulo 		if (ret != 0)
2855d4f2939cSRui Paulo 			goto error;
2856d4f2939cSRui Paulo 	} else if (bonjour == 1) {
2857d4f2939cSRui Paulo 		if (query == NULL)
2858d4f2939cSRui Paulo 			goto error;
2859d4f2939cSRui Paulo 
2860d4f2939cSRui Paulo 		ret = wpas_p2p_service_del_bonjour(wpa_s, query);
2861d4f2939cSRui Paulo 		if (ret != 0)
2862d4f2939cSRui Paulo 			goto error;
2863d4f2939cSRui Paulo 	} else
2864d4f2939cSRui Paulo 		goto error;
2865d4f2939cSRui Paulo 
28665b9c547cSRui Paulo 	wpabuf_free(query);
28675b9c547cSRui Paulo 	os_free(service);
2868d4f2939cSRui Paulo 	return reply;
2869d4f2939cSRui Paulo error_clear:
2870d4f2939cSRui Paulo 	wpa_dbus_dict_entry_clear(&entry);
2871d4f2939cSRui Paulo error:
28725b9c547cSRui Paulo 	wpabuf_free(query);
28735b9c547cSRui Paulo 	os_free(service);
2874d4f2939cSRui Paulo 	return wpas_dbus_error_invalid_args(message, NULL);
2875d4f2939cSRui Paulo }
2876d4f2939cSRui Paulo 
2877d4f2939cSRui Paulo 
wpas_dbus_handler_p2p_flush_service(DBusMessage * message,struct wpa_supplicant * wpa_s)2878d4f2939cSRui Paulo DBusMessage * wpas_dbus_handler_p2p_flush_service(DBusMessage *message,
2879d4f2939cSRui Paulo 						  struct wpa_supplicant *wpa_s)
2880d4f2939cSRui Paulo {
2881d4f2939cSRui Paulo 	wpas_p2p_service_flush(wpa_s);
2882d4f2939cSRui Paulo 	return NULL;
2883d4f2939cSRui Paulo }
2884d4f2939cSRui Paulo 
2885d4f2939cSRui Paulo 
wpas_dbus_handler_p2p_service_sd_req(DBusMessage * message,struct wpa_supplicant * wpa_s)2886d4f2939cSRui Paulo DBusMessage * wpas_dbus_handler_p2p_service_sd_req(
2887d4f2939cSRui Paulo 	DBusMessage *message, struct wpa_supplicant *wpa_s)
2888d4f2939cSRui Paulo {
2889d4f2939cSRui Paulo 	DBusMessageIter iter_dict;
2890d4f2939cSRui Paulo 	DBusMessage *reply = NULL;
2891d4f2939cSRui Paulo 	DBusMessageIter iter;
2892d4f2939cSRui Paulo 	struct wpa_dbus_dict_entry entry;
2893d4f2939cSRui Paulo 	int upnp = 0;
2894d4f2939cSRui Paulo 	char *service = NULL;
2895d4f2939cSRui Paulo 	char *peer_object_path = NULL;
2896d4f2939cSRui Paulo 	struct wpabuf *tlv = NULL;
2897d4f2939cSRui Paulo 	u8 version = 0;
2898d4f2939cSRui Paulo 	u64 ref = 0;
2899d4f2939cSRui Paulo 	u8 addr_buf[ETH_ALEN], *addr;
2900d4f2939cSRui Paulo 
2901d4f2939cSRui Paulo 	dbus_message_iter_init(message, &iter);
2902d4f2939cSRui Paulo 
2903d4f2939cSRui Paulo 	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
2904d4f2939cSRui Paulo 		goto error;
2905d4f2939cSRui Paulo 
2906d4f2939cSRui Paulo 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2907d4f2939cSRui Paulo 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2908d4f2939cSRui Paulo 			goto error;
29095b9c547cSRui Paulo 		if (os_strcmp(entry.key, "peer_object") == 0 &&
2910d4f2939cSRui Paulo 		    entry.type == DBUS_TYPE_OBJECT_PATH) {
2911d4f2939cSRui Paulo 			peer_object_path = os_strdup(entry.str_value);
29125b9c547cSRui Paulo 		} else if (os_strcmp(entry.key, "service_type") == 0 &&
2913d4f2939cSRui Paulo 			   entry.type == DBUS_TYPE_STRING) {
29145b9c547cSRui Paulo 			if (os_strcmp(entry.str_value, "upnp") == 0)
2915d4f2939cSRui Paulo 				upnp = 1;
2916d4f2939cSRui Paulo 			else
2917d4f2939cSRui Paulo 				goto error_clear;
29185b9c547cSRui Paulo 		} else if (os_strcmp(entry.key, "version") == 0 &&
2919d4f2939cSRui Paulo 			   entry.type == DBUS_TYPE_INT32) {
2920d4f2939cSRui Paulo 			version = entry.uint32_value;
29215b9c547cSRui Paulo 		} else if (os_strcmp(entry.key, "service") == 0 &&
2922d4f2939cSRui Paulo 			   entry.type == DBUS_TYPE_STRING) {
2923d4f2939cSRui Paulo 			service = os_strdup(entry.str_value);
29245b9c547cSRui Paulo 		} else if (os_strcmp(entry.key, "tlv") == 0) {
2925d4f2939cSRui Paulo 			if (entry.type != DBUS_TYPE_ARRAY ||
2926d4f2939cSRui Paulo 			    entry.array_type != DBUS_TYPE_BYTE)
2927d4f2939cSRui Paulo 				goto error_clear;
2928*a90b9d01SCy Schubert 			wpabuf_free(tlv);
2929d4f2939cSRui Paulo 			tlv = wpabuf_alloc_copy(entry.bytearray_value,
2930d4f2939cSRui Paulo 						entry.array_len);
2931d4f2939cSRui Paulo 		} else
2932d4f2939cSRui Paulo 			goto error_clear;
2933d4f2939cSRui Paulo 
2934d4f2939cSRui Paulo 		wpa_dbus_dict_entry_clear(&entry);
2935d4f2939cSRui Paulo 	}
2936d4f2939cSRui Paulo 
2937d4f2939cSRui Paulo 	if (!peer_object_path) {
2938d4f2939cSRui Paulo 		addr = NULL;
2939d4f2939cSRui Paulo 	} else {
2940d4f2939cSRui Paulo 		if (parse_peer_object_path(peer_object_path, addr_buf) < 0 ||
2941d4f2939cSRui Paulo 		    !p2p_peer_known(wpa_s->global->p2p, addr_buf))
2942d4f2939cSRui Paulo 			goto error;
2943d4f2939cSRui Paulo 
2944d4f2939cSRui Paulo 		addr = addr_buf;
2945d4f2939cSRui Paulo 	}
2946d4f2939cSRui Paulo 
2947d4f2939cSRui Paulo 	if (upnp == 1) {
2948d4f2939cSRui Paulo 		if (version <= 0 || service == NULL)
2949d4f2939cSRui Paulo 			goto error;
2950d4f2939cSRui Paulo 
2951d4f2939cSRui Paulo 		ref = wpas_p2p_sd_request_upnp(wpa_s, addr, version, service);
2952d4f2939cSRui Paulo 	} else {
2953d4f2939cSRui Paulo 		if (tlv == NULL)
2954d4f2939cSRui Paulo 			goto error;
2955d4f2939cSRui Paulo 		ref = wpas_p2p_sd_request(wpa_s, addr, tlv);
2956d4f2939cSRui Paulo 	}
2957d4f2939cSRui Paulo 
2958d4f2939cSRui Paulo 	if (ref != 0) {
2959d4f2939cSRui Paulo 		reply = dbus_message_new_method_return(message);
2960d4f2939cSRui Paulo 		dbus_message_append_args(reply, DBUS_TYPE_UINT64,
2961d4f2939cSRui Paulo 					 &ref, DBUS_TYPE_INVALID);
2962d4f2939cSRui Paulo 	} else {
2963d4f2939cSRui Paulo 		reply = wpas_dbus_error_unknown_error(
2964d4f2939cSRui Paulo 			message, "Unable to send SD request");
2965d4f2939cSRui Paulo 	}
2966d4f2939cSRui Paulo out:
2967*a90b9d01SCy Schubert 	wpabuf_free(tlv);
2968d4f2939cSRui Paulo 	os_free(service);
2969d4f2939cSRui Paulo 	os_free(peer_object_path);
2970d4f2939cSRui Paulo 	return reply;
2971d4f2939cSRui Paulo error_clear:
2972d4f2939cSRui Paulo 	wpa_dbus_dict_entry_clear(&entry);
2973d4f2939cSRui Paulo error:
2974d4f2939cSRui Paulo 	reply = wpas_dbus_error_invalid_args(message, NULL);
2975d4f2939cSRui Paulo 	goto out;
2976d4f2939cSRui Paulo }
2977d4f2939cSRui Paulo 
2978d4f2939cSRui Paulo 
wpas_dbus_handler_p2p_service_sd_res(DBusMessage * message,struct wpa_supplicant * wpa_s)2979d4f2939cSRui Paulo DBusMessage * wpas_dbus_handler_p2p_service_sd_res(
2980d4f2939cSRui Paulo 	DBusMessage *message, struct wpa_supplicant *wpa_s)
2981d4f2939cSRui Paulo {
2982d4f2939cSRui Paulo 	DBusMessageIter iter_dict;
2983d4f2939cSRui Paulo 	DBusMessage *reply = NULL;
2984d4f2939cSRui Paulo 	DBusMessageIter iter;
2985d4f2939cSRui Paulo 	struct wpa_dbus_dict_entry entry;
2986d4f2939cSRui Paulo 	char *peer_object_path = NULL;
2987d4f2939cSRui Paulo 	struct wpabuf *tlv = NULL;
2988d4f2939cSRui Paulo 	int freq = 0;
2989d4f2939cSRui Paulo 	int dlg_tok = 0;
2990d4f2939cSRui Paulo 	u8 addr[ETH_ALEN];
2991d4f2939cSRui Paulo 
2992d4f2939cSRui Paulo 	dbus_message_iter_init(message, &iter);
2993d4f2939cSRui Paulo 
2994d4f2939cSRui Paulo 	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
2995d4f2939cSRui Paulo 		goto error;
2996d4f2939cSRui Paulo 
2997d4f2939cSRui Paulo 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2998d4f2939cSRui Paulo 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2999d4f2939cSRui Paulo 			goto error;
3000d4f2939cSRui Paulo 
30015b9c547cSRui Paulo 		if (os_strcmp(entry.key, "peer_object") == 0 &&
3002d4f2939cSRui Paulo 		    entry.type == DBUS_TYPE_OBJECT_PATH) {
3003d4f2939cSRui Paulo 			peer_object_path = os_strdup(entry.str_value);
30045b9c547cSRui Paulo 		} else if (os_strcmp(entry.key, "frequency") == 0 &&
3005d4f2939cSRui Paulo 			   entry.type == DBUS_TYPE_INT32) {
3006d4f2939cSRui Paulo 			freq = entry.uint32_value;
30075b9c547cSRui Paulo 		} else if (os_strcmp(entry.key, "dialog_token") == 0 &&
30085b9c547cSRui Paulo 			   (entry.type == DBUS_TYPE_UINT32 ||
30095b9c547cSRui Paulo 			    entry.type == DBUS_TYPE_INT32)) {
3010d4f2939cSRui Paulo 			dlg_tok = entry.uint32_value;
30115b9c547cSRui Paulo 		} else if (os_strcmp(entry.key, "tlvs") == 0) {
3012d4f2939cSRui Paulo 			if (entry.type != DBUS_TYPE_ARRAY ||
3013d4f2939cSRui Paulo 			    entry.array_type != DBUS_TYPE_BYTE)
3014d4f2939cSRui Paulo 				goto error_clear;
3015*a90b9d01SCy Schubert 			wpabuf_free(tlv);
3016d4f2939cSRui Paulo 			tlv = wpabuf_alloc_copy(entry.bytearray_value,
3017d4f2939cSRui Paulo 						entry.array_len);
3018d4f2939cSRui Paulo 		} else
3019d4f2939cSRui Paulo 			goto error_clear;
3020d4f2939cSRui Paulo 
3021d4f2939cSRui Paulo 		wpa_dbus_dict_entry_clear(&entry);
3022d4f2939cSRui Paulo 	}
30235b9c547cSRui Paulo 	if (parse_peer_object_path(peer_object_path, addr) < 0 ||
30245b9c547cSRui Paulo 	    !p2p_peer_known(wpa_s->global->p2p, addr) ||
30255b9c547cSRui Paulo 	    tlv == NULL)
3026d4f2939cSRui Paulo 		goto error;
3027d4f2939cSRui Paulo 
3028d4f2939cSRui Paulo 	wpas_p2p_sd_response(wpa_s, freq, addr, (u8) dlg_tok, tlv);
3029d4f2939cSRui Paulo out:
3030*a90b9d01SCy Schubert 	wpabuf_free(tlv);
3031d4f2939cSRui Paulo 	os_free(peer_object_path);
3032d4f2939cSRui Paulo 	return reply;
3033d4f2939cSRui Paulo error_clear:
3034d4f2939cSRui Paulo 	wpa_dbus_dict_entry_clear(&entry);
3035d4f2939cSRui Paulo error:
3036d4f2939cSRui Paulo 	reply = wpas_dbus_error_invalid_args(message, NULL);
3037d4f2939cSRui Paulo 	goto out;
3038d4f2939cSRui Paulo }
3039d4f2939cSRui Paulo 
3040d4f2939cSRui Paulo 
wpas_dbus_handler_p2p_service_sd_cancel_req(DBusMessage * message,struct wpa_supplicant * wpa_s)3041d4f2939cSRui Paulo DBusMessage * wpas_dbus_handler_p2p_service_sd_cancel_req(
3042d4f2939cSRui Paulo 	DBusMessage *message, struct wpa_supplicant *wpa_s)
3043d4f2939cSRui Paulo {
3044d4f2939cSRui Paulo 	DBusMessageIter iter;
3045d4f2939cSRui Paulo 	u64 req = 0;
3046d4f2939cSRui Paulo 
3047d4f2939cSRui Paulo 	dbus_message_iter_init(message, &iter);
3048d4f2939cSRui Paulo 	dbus_message_iter_get_basic(&iter, &req);
3049d4f2939cSRui Paulo 
3050d4f2939cSRui Paulo 	if (req == 0)
3051d4f2939cSRui Paulo 		goto error;
3052d4f2939cSRui Paulo 
30535b9c547cSRui Paulo 	if (wpas_p2p_sd_cancel_request(wpa_s, req) < 0)
3054d4f2939cSRui Paulo 		goto error;
3055d4f2939cSRui Paulo 
3056d4f2939cSRui Paulo 	return NULL;
3057d4f2939cSRui Paulo error:
3058d4f2939cSRui Paulo 	return wpas_dbus_error_invalid_args(message, NULL);
3059d4f2939cSRui Paulo }
3060d4f2939cSRui Paulo 
3061d4f2939cSRui Paulo 
wpas_dbus_handler_p2p_service_update(DBusMessage * message,struct wpa_supplicant * wpa_s)3062d4f2939cSRui Paulo DBusMessage * wpas_dbus_handler_p2p_service_update(
3063d4f2939cSRui Paulo 	DBusMessage *message, struct wpa_supplicant *wpa_s)
3064d4f2939cSRui Paulo {
3065d4f2939cSRui Paulo 	wpas_p2p_sd_service_update(wpa_s);
3066d4f2939cSRui Paulo 	return NULL;
3067d4f2939cSRui Paulo }
3068d4f2939cSRui Paulo 
3069d4f2939cSRui Paulo 
wpas_dbus_handler_p2p_serv_disc_external(DBusMessage * message,struct wpa_supplicant * wpa_s)3070d4f2939cSRui Paulo DBusMessage * wpas_dbus_handler_p2p_serv_disc_external(
3071d4f2939cSRui Paulo 	DBusMessage *message, struct wpa_supplicant *wpa_s)
3072d4f2939cSRui Paulo {
3073d4f2939cSRui Paulo 	DBusMessageIter iter;
3074d4f2939cSRui Paulo 	int ext = 0;
3075d4f2939cSRui Paulo 
3076d4f2939cSRui Paulo 	dbus_message_iter_init(message, &iter);
3077d4f2939cSRui Paulo 	dbus_message_iter_get_basic(&iter, &ext);
3078d4f2939cSRui Paulo 
3079d4f2939cSRui Paulo 	wpa_s->p2p_sd_over_ctrl_iface = ext;
3080d4f2939cSRui Paulo 
3081d4f2939cSRui Paulo 	return NULL;
3082d4f2939cSRui Paulo 
3083d4f2939cSRui Paulo }
30845b9c547cSRui Paulo 
30855b9c547cSRui Paulo 
30865b9c547cSRui Paulo #ifdef CONFIG_WIFI_DISPLAY
30875b9c547cSRui Paulo 
wpas_dbus_getter_global_wfd_ies(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3088780fb4a2SCy Schubert dbus_bool_t wpas_dbus_getter_global_wfd_ies(
3089780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
3090780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
30915b9c547cSRui Paulo {
30925b9c547cSRui Paulo 	struct wpa_global *global = user_data;
30935b9c547cSRui Paulo 	struct wpabuf *ie;
30945b9c547cSRui Paulo 	dbus_bool_t ret;
30955b9c547cSRui Paulo 
30965b9c547cSRui Paulo 	ie = wifi_display_get_wfd_ie(global);
30975b9c547cSRui Paulo 	if (ie == NULL)
30985b9c547cSRui Paulo 		return wpas_dbus_simple_array_property_getter(iter,
30995b9c547cSRui Paulo 							      DBUS_TYPE_BYTE,
31005b9c547cSRui Paulo 							      NULL, 0, error);
31015b9c547cSRui Paulo 
31025b9c547cSRui Paulo 	ret = wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
31035b9c547cSRui Paulo 						     wpabuf_head(ie),
31045b9c547cSRui Paulo 						     wpabuf_len(ie), error);
31055b9c547cSRui Paulo 	wpabuf_free(ie);
31065b9c547cSRui Paulo 
31075b9c547cSRui Paulo 	return ret;
31085b9c547cSRui Paulo }
31095b9c547cSRui Paulo 
31105b9c547cSRui Paulo 
wpas_dbus_setter_global_wfd_ies(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3111780fb4a2SCy Schubert dbus_bool_t wpas_dbus_setter_global_wfd_ies(
3112780fb4a2SCy Schubert 	const struct wpa_dbus_property_desc *property_desc,
3113780fb4a2SCy Schubert 	DBusMessageIter *iter, DBusError *error, void *user_data)
31145b9c547cSRui Paulo {
31155b9c547cSRui Paulo 	struct wpa_global *global = user_data;
31165b9c547cSRui Paulo 	DBusMessageIter variant, array;
31175b9c547cSRui Paulo 	struct wpabuf *ie = NULL;
31185b9c547cSRui Paulo 	const u8 *data;
31195b9c547cSRui Paulo 	int len;
31205b9c547cSRui Paulo 
31215b9c547cSRui Paulo 	if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_VARIANT)
31225b9c547cSRui Paulo 		goto err;
31235b9c547cSRui Paulo 
31245b9c547cSRui Paulo 	dbus_message_iter_recurse(iter, &variant);
31255b9c547cSRui Paulo 	if (dbus_message_iter_get_arg_type(&variant) != DBUS_TYPE_ARRAY)
31265b9c547cSRui Paulo 		goto err;
31275b9c547cSRui Paulo 
31285b9c547cSRui Paulo 	dbus_message_iter_recurse(&variant, &array);
31295b9c547cSRui Paulo 	dbus_message_iter_get_fixed_array(&array, &data, &len);
31305b9c547cSRui Paulo 	if (len == 0) {
31315b9c547cSRui Paulo 		wifi_display_enable(global, 0);
31325b9c547cSRui Paulo 		wifi_display_deinit(global);
31335b9c547cSRui Paulo 
31345b9c547cSRui Paulo 		return TRUE;
31355b9c547cSRui Paulo 	}
31365b9c547cSRui Paulo 
31375b9c547cSRui Paulo 	ie = wpabuf_alloc(len);
31385b9c547cSRui Paulo 	if (ie == NULL)
31395b9c547cSRui Paulo 		goto err;
31405b9c547cSRui Paulo 
31415b9c547cSRui Paulo 	wpabuf_put_data(ie, data, len);
31425b9c547cSRui Paulo 	if (wifi_display_subelem_set_from_ies(global, ie) != 0)
31435b9c547cSRui Paulo 		goto err;
31445b9c547cSRui Paulo 
31455b9c547cSRui Paulo 	if (global->wifi_display == 0)
31465b9c547cSRui Paulo 		wifi_display_enable(global, 1);
31475b9c547cSRui Paulo 
31485b9c547cSRui Paulo 	wpabuf_free(ie);
31495b9c547cSRui Paulo 
31505b9c547cSRui Paulo 	return TRUE;
31515b9c547cSRui Paulo err:
31525b9c547cSRui Paulo 	wpabuf_free(ie);
31535b9c547cSRui Paulo 
31545b9c547cSRui Paulo 	dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
31555b9c547cSRui Paulo 			     "invalid message format");
31565b9c547cSRui Paulo 	return FALSE;
31575b9c547cSRui Paulo }
31585b9c547cSRui Paulo 
31595b9c547cSRui Paulo #endif /* CONFIG_WIFI_DISPLAY */
3160