1 /*
2  * WPA Supplicant / dbus-based control interface (P2P)
3  * Copyright (c) 2011-2012, Intel Corporation
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8 
9 #include "includes.h"
10 
11 #include "utils/includes.h"
12 #include "common.h"
13 #include "../config.h"
14 #include "../wpa_supplicant_i.h"
15 #include "../wps_supplicant.h"
16 #include "../notify.h"
17 #include "dbus_new_helpers.h"
18 #include "dbus_new.h"
19 #include "dbus_new_handlers.h"
20 #include "dbus_new_handlers_p2p.h"
21 #include "dbus_dict_helpers.h"
22 #include "p2p/p2p.h"
23 #include "common/ieee802_11_defs.h"
24 #include "ap/hostapd.h"
25 #include "ap/ap_config.h"
26 #include "ap/wps_hostapd.h"
27 
28 #include "../p2p_supplicant.h"
29 #include "../wifi_display.h"
30 
31 
32 static int wpas_dbus_validate_dbus_ipaddr(struct wpa_dbus_dict_entry entry)
33 {
34 	if (entry.type != DBUS_TYPE_ARRAY ||
35 	    entry.array_type != DBUS_TYPE_BYTE ||
36 	    entry.array_len != 4)
37 		return 0;
38 
39 	return 1;
40 }
41 
42 
43 /**
44  * Parses out the mac address from the peer object path.
45  * @peer_path - object path of the form
46  *	/fi/w1/wpa_supplicant1/Interfaces/n/Peers/00112233445566 (no colons)
47  * @addr - out param must be of ETH_ALEN size
48  * Returns 0 if valid (including MAC), -1 otherwise
49  */
50 static int parse_peer_object_path(const char *peer_path, u8 addr[ETH_ALEN])
51 {
52 	const char *p;
53 
54 	if (!peer_path)
55 		return -1;
56 	p = os_strrchr(peer_path, '/');
57 	if (!p)
58 		return -1;
59 	p++;
60 	return hwaddr_compact_aton(p, addr);
61 }
62 
63 
64 /**
65  * wpas_dbus_error_persistent_group_unknown - Return a new PersistentGroupUnknown
66  * error message
67  * @message: Pointer to incoming dbus message this error refers to
68  * Returns: a dbus error message
69  *
70  * Convenience function to create and return an invalid persistent group error.
71  */
72 static DBusMessage *
73 wpas_dbus_error_persistent_group_unknown(DBusMessage *message)
74 {
75 	return dbus_message_new_error(
76 		message, WPAS_DBUS_ERROR_NETWORK_UNKNOWN,
77 		"There is no such persistent group in this P2P device.");
78 }
79 
80 
81 DBusMessage * wpas_dbus_handler_p2p_find(DBusMessage *message,
82 					 struct wpa_supplicant *wpa_s)
83 {
84 	struct wpa_dbus_dict_entry entry;
85 	DBusMessage *reply = NULL;
86 	DBusMessageIter iter;
87 	DBusMessageIter iter_dict;
88 	unsigned int timeout = 0;
89 	enum p2p_discovery_type type = P2P_FIND_START_WITH_FULL;
90 	int num_req_dev_types = 0;
91 	unsigned int i;
92 	u8 *req_dev_types = NULL;
93 	unsigned int freq = 0;
94 
95 	dbus_message_iter_init(message, &iter);
96 	entry.key = NULL;
97 
98 	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
99 		goto error;
100 
101 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
102 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
103 			goto error;
104 
105 		if (os_strcmp(entry.key, "Timeout") == 0 &&
106 		    entry.type == DBUS_TYPE_INT32) {
107 			timeout = entry.uint32_value;
108 		} else if (os_strcmp(entry.key, "RequestedDeviceTypes") == 0) {
109 			if (entry.type != DBUS_TYPE_ARRAY ||
110 			    entry.array_type != WPAS_DBUS_TYPE_BINARRAY)
111 				goto error_clear;
112 
113 			os_free(req_dev_types);
114 			req_dev_types =
115 				os_malloc(WPS_DEV_TYPE_LEN * entry.array_len);
116 			if (!req_dev_types)
117 				goto error_clear;
118 
119 			for (i = 0; i < entry.array_len; i++) {
120 				if (wpabuf_len(entry.binarray_value[i]) !=
121 				    WPS_DEV_TYPE_LEN)
122 					goto error_clear;
123 				os_memcpy(req_dev_types + i * WPS_DEV_TYPE_LEN,
124 					  wpabuf_head(entry.binarray_value[i]),
125 					  WPS_DEV_TYPE_LEN);
126 			}
127 			num_req_dev_types = entry.array_len;
128 		} else if (os_strcmp(entry.key, "DiscoveryType") == 0 &&
129 			   entry.type == DBUS_TYPE_STRING) {
130 			if (os_strcmp(entry.str_value, "start_with_full") == 0)
131 				type = P2P_FIND_START_WITH_FULL;
132 			else if (os_strcmp(entry.str_value, "social") == 0)
133 				type = P2P_FIND_ONLY_SOCIAL;
134 			else if (os_strcmp(entry.str_value, "progressive") == 0)
135 				type = P2P_FIND_PROGRESSIVE;
136 			else
137 				goto error_clear;
138 		} else if (os_strcmp(entry.key, "freq") == 0 &&
139 			   (entry.type == DBUS_TYPE_INT32 ||
140 			    entry.type == DBUS_TYPE_UINT32)) {
141 			freq = entry.uint32_value;
142 		} else
143 			goto error_clear;
144 		wpa_dbus_dict_entry_clear(&entry);
145 	}
146 
147 	wpa_s = wpa_s->global->p2p_init_wpa_s;
148 
149 	if (wpas_p2p_find(wpa_s, timeout, type, num_req_dev_types,
150 			  req_dev_types, NULL, 0, 0, NULL, freq))
151 		reply = wpas_dbus_error_unknown_error(
152 			message, "Could not start P2P find");
153 
154 	os_free(req_dev_types);
155 	return reply;
156 
157 error_clear:
158 	wpa_dbus_dict_entry_clear(&entry);
159 error:
160 	os_free(req_dev_types);
161 	reply = wpas_dbus_error_invalid_args(message, entry.key);
162 	return reply;
163 }
164 
165 
166 DBusMessage * wpas_dbus_handler_p2p_stop_find(DBusMessage *message,
167 					      struct wpa_supplicant *wpa_s)
168 {
169 	wpas_p2p_stop_find(wpa_s->global->p2p_init_wpa_s);
170 	return NULL;
171 }
172 
173 
174 DBusMessage * wpas_dbus_handler_p2p_rejectpeer(DBusMessage *message,
175 					       struct wpa_supplicant *wpa_s)
176 {
177 	DBusMessageIter iter;
178 	char *peer_object_path = NULL;
179 	u8 peer_addr[ETH_ALEN];
180 
181 	dbus_message_iter_init(message, &iter);
182 	dbus_message_iter_get_basic(&iter, &peer_object_path);
183 
184 	if (parse_peer_object_path(peer_object_path, peer_addr) < 0)
185 		return wpas_dbus_error_invalid_args(message, NULL);
186 
187 	wpa_s = wpa_s->global->p2p_init_wpa_s;
188 
189 	if (wpas_p2p_reject(wpa_s, peer_addr) < 0)
190 		return wpas_dbus_error_unknown_error(message,
191 				"Failed to call wpas_p2p_reject method.");
192 
193 	return NULL;
194 }
195 
196 
197 DBusMessage * wpas_dbus_handler_p2p_listen(DBusMessage *message,
198 					   struct wpa_supplicant *wpa_s)
199 {
200 	dbus_int32_t timeout = 0;
201 
202 	if (!dbus_message_get_args(message, NULL, DBUS_TYPE_INT32, &timeout,
203 				   DBUS_TYPE_INVALID))
204 		return wpas_dbus_error_no_memory(message);
205 
206 	wpa_s = wpa_s->global->p2p_init_wpa_s;
207 
208 	if (wpas_p2p_listen(wpa_s, (unsigned int) timeout)) {
209 		return dbus_message_new_error(message,
210 					      WPAS_DBUS_ERROR_UNKNOWN_ERROR,
211 					      "Could not start P2P listen");
212 	}
213 
214 	return NULL;
215 }
216 
217 
218 DBusMessage * wpas_dbus_handler_p2p_extendedlisten(
219 	DBusMessage *message, struct wpa_supplicant *wpa_s)
220 {
221 	unsigned int period = 0, interval = 0;
222 	struct wpa_dbus_dict_entry entry;
223 	DBusMessageIter iter;
224 	DBusMessageIter iter_dict;
225 
226 	dbus_message_iter_init(message, &iter);
227 	entry.key = NULL;
228 
229 	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
230 		goto error;
231 
232 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
233 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
234 			goto error;
235 
236 		if (os_strcmp(entry.key, "period") == 0 &&
237 		    entry.type == DBUS_TYPE_INT32)
238 			period = entry.uint32_value;
239 		else if (os_strcmp(entry.key, "interval") == 0 &&
240 			 entry.type == DBUS_TYPE_INT32)
241 			interval = entry.uint32_value;
242 		else
243 			goto error_clear;
244 		wpa_dbus_dict_entry_clear(&entry);
245 	}
246 
247 	wpa_s = wpa_s->global->p2p_init_wpa_s;
248 
249 	if (wpas_p2p_ext_listen(wpa_s, period, interval))
250 		return wpas_dbus_error_unknown_error(
251 			message, "failed to initiate a p2p_ext_listen.");
252 
253 	return NULL;
254 
255 error_clear:
256 	wpa_dbus_dict_entry_clear(&entry);
257 error:
258 	return wpas_dbus_error_invalid_args(message, entry.key);
259 }
260 
261 
262 DBusMessage * wpas_dbus_handler_p2p_presence_request(
263 	DBusMessage *message, struct wpa_supplicant *wpa_s)
264 {
265 	unsigned int dur1 = 0, int1 = 0, dur2 = 0, int2 = 0;
266 	struct wpa_dbus_dict_entry entry;
267 	DBusMessageIter iter;
268 	DBusMessageIter iter_dict;
269 
270 	dbus_message_iter_init(message, &iter);
271 	entry.key = NULL;
272 
273 	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
274 		goto error;
275 
276 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
277 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
278 			goto error;
279 
280 		if (os_strcmp(entry.key, "duration1") == 0 &&
281 		    entry.type == DBUS_TYPE_INT32)
282 			dur1 = entry.uint32_value;
283 		else if (os_strcmp(entry.key, "interval1") == 0 &&
284 			 entry.type == DBUS_TYPE_INT32)
285 			int1 = entry.uint32_value;
286 		else if (os_strcmp(entry.key, "duration2") == 0 &&
287 			 entry.type == DBUS_TYPE_INT32)
288 			dur2 = entry.uint32_value;
289 		else if (os_strcmp(entry.key, "interval2") == 0 &&
290 			 entry.type == DBUS_TYPE_INT32)
291 			int2 = entry.uint32_value;
292 		else
293 			goto error_clear;
294 
295 		wpa_dbus_dict_entry_clear(&entry);
296 	}
297 
298 	if (wpas_p2p_presence_req(wpa_s, dur1, int1, dur2, int2) < 0)
299 		return wpas_dbus_error_unknown_error(message,
300 				"Failed to invoke presence request.");
301 
302 	return NULL;
303 
304 error_clear:
305 	wpa_dbus_dict_entry_clear(&entry);
306 error:
307 	return wpas_dbus_error_invalid_args(message, entry.key);
308 }
309 
310 
311 DBusMessage * wpas_dbus_handler_p2p_group_add(DBusMessage *message,
312 					      struct wpa_supplicant *wpa_s)
313 {
314 	DBusMessageIter iter_dict;
315 	DBusMessage *reply = NULL;
316 	DBusMessageIter iter;
317 	struct wpa_dbus_dict_entry entry;
318 	char *pg_object_path = NULL;
319 	int persistent_group = 0;
320 	int freq = 0;
321 	char *iface = NULL;
322 	unsigned int group_id = 0;
323 	struct wpa_ssid *ssid;
324 
325 	dbus_message_iter_init(message, &iter);
326 
327 	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
328 		goto inv_args;
329 
330 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
331 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
332 			goto inv_args;
333 
334 		if (os_strcmp(entry.key, "persistent") == 0 &&
335 		    entry.type == DBUS_TYPE_BOOLEAN) {
336 			persistent_group = entry.bool_value;
337 		} else if (os_strcmp(entry.key, "frequency") == 0 &&
338 			   entry.type == DBUS_TYPE_INT32) {
339 			freq = entry.int32_value;
340 			if (freq <= 0)
341 				goto inv_args_clear;
342 		} else if (os_strcmp(entry.key, "persistent_group_object") ==
343 			   0 &&
344 			   entry.type == DBUS_TYPE_OBJECT_PATH)
345 			pg_object_path = os_strdup(entry.str_value);
346 		else
347 			goto inv_args_clear;
348 
349 		wpa_dbus_dict_entry_clear(&entry);
350 	}
351 
352 	wpa_s = wpa_s->global->p2p_init_wpa_s;
353 
354 	if (pg_object_path != NULL) {
355 		char *net_id_str;
356 
357 		/*
358 		 * A persistent group Object Path is defined meaning we want
359 		 * to re-invoke a persistent group.
360 		 */
361 
362 		iface = wpas_dbus_new_decompose_object_path(
363 			pg_object_path, WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART,
364 			&net_id_str);
365 		if (iface == NULL || net_id_str == NULL ||
366 		    !wpa_s->parent->dbus_new_path ||
367 		    os_strcmp(iface, wpa_s->parent->dbus_new_path) != 0) {
368 			reply =
369 			    wpas_dbus_error_invalid_args(message,
370 							 pg_object_path);
371 			goto out;
372 		}
373 
374 		group_id = strtoul(net_id_str, NULL, 10);
375 		if (errno == EINVAL) {
376 			reply = wpas_dbus_error_invalid_args(
377 						message, pg_object_path);
378 			goto out;
379 		}
380 
381 		/* Get the SSID structure from the persistent group id */
382 		ssid = wpa_config_get_network(wpa_s->conf, group_id);
383 		if (ssid == NULL || ssid->disabled != 2)
384 			goto inv_args;
385 
386 		if (wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 0, 0, 0,
387 						  0, 0, 0, NULL, 0, 0)) {
388 			reply = wpas_dbus_error_unknown_error(
389 				message,
390 				"Failed to reinvoke a persistent group");
391 			goto out;
392 		}
393 	} else if (wpas_p2p_group_add(wpa_s, persistent_group, freq, 0, 0, 0,
394 				      0, 0))
395 		goto inv_args;
396 
397 out:
398 	os_free(pg_object_path);
399 	os_free(iface);
400 	return reply;
401 inv_args_clear:
402 	wpa_dbus_dict_entry_clear(&entry);
403 inv_args:
404 	reply = wpas_dbus_error_invalid_args(message, NULL);
405 	goto out;
406 }
407 
408 
409 DBusMessage * wpas_dbus_handler_p2p_disconnect(DBusMessage *message,
410 					       struct wpa_supplicant *wpa_s)
411 {
412 	if (wpas_p2p_disconnect(wpa_s))
413 		return wpas_dbus_error_unknown_error(message,
414 						"failed to disconnect");
415 
416 	return NULL;
417 }
418 
419 
420 static dbus_bool_t wpa_dbus_p2p_check_enabled(struct wpa_supplicant *wpa_s,
421 					      DBusMessage *message,
422 					      DBusMessage **out_reply,
423 					      DBusError *error)
424 {
425 	/* Return an error message or an error if P2P isn't available */
426 	if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL) {
427 		if (out_reply) {
428 			*out_reply = dbus_message_new_error(
429 				message, DBUS_ERROR_FAILED,
430 				"P2P is not available for this interface");
431 		}
432 		dbus_set_error_const(error, DBUS_ERROR_FAILED,
433 				     "P2P is not available for this interface");
434 		return FALSE;
435 	}
436 	return TRUE;
437 }
438 
439 
440 DBusMessage * wpas_dbus_handler_p2p_remove_client(DBusMessage *message,
441 						  struct wpa_supplicant *wpa_s)
442 {
443 	DBusMessageIter iter_dict;
444 	DBusMessage *reply = NULL;
445 	DBusMessageIter iter;
446 	struct wpa_dbus_dict_entry entry;
447 	char *peer_object_path = NULL;
448 	char *interface_addr = NULL;
449 	u8 peer_addr[ETH_ALEN];
450 
451 	if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL))
452 		return reply;
453 
454 	dbus_message_iter_init(message, &iter);
455 
456 	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
457 		goto err;
458 
459 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
460 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
461 			goto err;
462 
463 		if (os_strcmp(entry.key, "peer") == 0 &&
464 		    entry.type == DBUS_TYPE_OBJECT_PATH) {
465 			os_free(peer_object_path);
466 			peer_object_path = os_strdup(entry.str_value);
467 			wpa_dbus_dict_entry_clear(&entry);
468 		} else if (os_strcmp(entry.key, "iface") == 0 &&
469 			   entry.type == DBUS_TYPE_STRING) {
470 			os_free(interface_addr);
471 			interface_addr = os_strdup(entry.str_value);
472 			wpa_dbus_dict_entry_clear(&entry);
473 		} else {
474 			wpa_dbus_dict_entry_clear(&entry);
475 			goto err;
476 		}
477 	}
478 
479 	if ((!peer_object_path && !interface_addr) ||
480 	    (peer_object_path &&
481 	     (parse_peer_object_path(peer_object_path, peer_addr) < 0 ||
482 	      !p2p_peer_known(wpa_s->global->p2p, peer_addr))) ||
483 	    (interface_addr && hwaddr_aton(interface_addr, peer_addr) < 0))
484 		goto err;
485 
486 	wpas_p2p_remove_client(wpa_s, peer_addr, interface_addr != NULL);
487 	reply = NULL;
488 out:
489 	os_free(peer_object_path);
490 	os_free(interface_addr);
491 	return reply;
492 err:
493 	reply = wpas_dbus_error_invalid_args(message, "Invalid address format");
494 	goto out;
495 }
496 
497 
498 DBusMessage * wpas_dbus_handler_p2p_flush(DBusMessage *message,
499 					  struct wpa_supplicant *wpa_s)
500 {
501 	DBusMessage *reply = NULL;
502 
503 	if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL))
504 		return reply;
505 
506 	wpa_s = wpa_s->global->p2p_init_wpa_s;
507 
508 	wpas_p2p_stop_find(wpa_s);
509 	os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
510 	wpa_s->force_long_sd = 0;
511 	p2p_flush(wpa_s->global->p2p);
512 
513 	return NULL;
514 }
515 
516 
517 DBusMessage * wpas_dbus_handler_p2p_connect(DBusMessage *message,
518 					    struct wpa_supplicant *wpa_s)
519 {
520 	DBusMessageIter iter_dict;
521 	DBusMessage *reply = NULL;
522 	DBusMessageIter iter;
523 	struct wpa_dbus_dict_entry entry;
524 	char *peer_object_path = NULL;
525 	int persistent_group = 0;
526 	int join = 0;
527 	int authorize_only = 0;
528 	int go_intent = -1;
529 	int freq = 0;
530 	u8 addr[ETH_ALEN];
531 	char *pin = NULL;
532 	enum p2p_wps_method wps_method = WPS_NOT_READY;
533 	int new_pin;
534 	char *err_msg = NULL;
535 	char *iface = NULL;
536 	int ret;
537 
538 	if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL))
539 		return reply;
540 
541 	dbus_message_iter_init(message, &iter);
542 
543 	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
544 		goto inv_args;
545 
546 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
547 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
548 			goto inv_args;
549 
550 		if (os_strcmp(entry.key, "peer") == 0 &&
551 		    entry.type == DBUS_TYPE_OBJECT_PATH) {
552 			peer_object_path = os_strdup(entry.str_value);
553 		} else if (os_strcmp(entry.key, "persistent") == 0 &&
554 			   entry.type == DBUS_TYPE_BOOLEAN) {
555 			persistent_group = entry.bool_value;
556 		} else if (os_strcmp(entry.key, "join") == 0 &&
557 			   entry.type == DBUS_TYPE_BOOLEAN) {
558 			join = entry.bool_value;
559 		} else if (os_strcmp(entry.key, "authorize_only") == 0 &&
560 			   entry.type == DBUS_TYPE_BOOLEAN) {
561 			authorize_only = entry.bool_value;
562 		} else if (os_strcmp(entry.key, "frequency") == 0 &&
563 			   entry.type == DBUS_TYPE_INT32) {
564 			freq = entry.int32_value;
565 			if (freq <= 0)
566 				goto inv_args_clear;
567 		} else if (os_strcmp(entry.key, "go_intent") == 0 &&
568 			   entry.type == DBUS_TYPE_INT32) {
569 			go_intent = entry.int32_value;
570 			if ((go_intent < 0) || (go_intent > 15))
571 				goto inv_args_clear;
572 		} else if (os_strcmp(entry.key, "wps_method") == 0 &&
573 			   entry.type == DBUS_TYPE_STRING) {
574 			if (os_strcmp(entry.str_value, "pbc") == 0)
575 				wps_method = WPS_PBC;
576 			else if (os_strcmp(entry.str_value, "pin") == 0)
577 				wps_method = WPS_PIN_DISPLAY;
578 			else if (os_strcmp(entry.str_value, "display") == 0)
579 				wps_method = WPS_PIN_DISPLAY;
580 			else if (os_strcmp(entry.str_value, "keypad") == 0)
581 				wps_method = WPS_PIN_KEYPAD;
582 			else
583 				goto inv_args_clear;
584 		} else if (os_strcmp(entry.key, "pin") == 0 &&
585 			   entry.type == DBUS_TYPE_STRING) {
586 			pin = os_strdup(entry.str_value);
587 		} else
588 			goto inv_args_clear;
589 
590 		wpa_dbus_dict_entry_clear(&entry);
591 	}
592 
593 	if (wps_method == WPS_NOT_READY ||
594 	    parse_peer_object_path(peer_object_path, addr) < 0 ||
595 	    !p2p_peer_known(wpa_s->global->p2p, addr))
596 		goto inv_args;
597 
598 	/*
599 	 * Validate the wps_method specified and the pin value.
600 	 */
601 	if ((!pin || !pin[0]) && wps_method == WPS_PIN_KEYPAD)
602 		goto inv_args;
603 
604 	wpa_s = wpa_s->global->p2p_init_wpa_s;
605 
606 	new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
607 				   persistent_group, 0, join, authorize_only,
608 				   go_intent, freq, 0, -1, 0, 0, 0, 0, 0,
609 				   NULL, 0);
610 
611 	if (new_pin >= 0) {
612 		char npin[9];
613 		char *generated_pin;
614 
615 		ret = os_snprintf(npin, sizeof(npin), "%08d", new_pin);
616 		if (os_snprintf_error(sizeof(npin), ret)) {
617 			reply = wpas_dbus_error_unknown_error(message,
618 							      "invalid PIN");
619 			goto out;
620 		}
621 		generated_pin = npin;
622 		reply = dbus_message_new_method_return(message);
623 		dbus_message_append_args(reply, DBUS_TYPE_STRING,
624 					 &generated_pin, DBUS_TYPE_INVALID);
625 	} else {
626 		switch (new_pin) {
627 		case -2:
628 			err_msg =
629 				"connect failed due to channel unavailability.";
630 			iface = WPAS_DBUS_ERROR_CONNECT_CHANNEL_UNAVAILABLE;
631 			break;
632 
633 		case -3:
634 			err_msg = "connect failed due to unsupported channel.";
635 			iface = WPAS_DBUS_ERROR_CONNECT_CHANNEL_UNSUPPORTED;
636 			break;
637 
638 		default:
639 			err_msg = "connect failed due to unspecified error.";
640 			iface = WPAS_DBUS_ERROR_CONNECT_UNSPECIFIED_ERROR;
641 			break;
642 		}
643 
644 		/*
645 		 * TODO:
646 		 * Do we need specialized errors corresponding to above
647 		 * error conditions as against just returning a different
648 		 * error message?
649 		 */
650 		reply = dbus_message_new_error(message, iface, err_msg);
651 	}
652 
653 out:
654 	os_free(peer_object_path);
655 	os_free(pin);
656 	return reply;
657 inv_args_clear:
658 	wpa_dbus_dict_entry_clear(&entry);
659 inv_args:
660 	reply = wpas_dbus_error_invalid_args(message, NULL);
661 	goto out;
662 }
663 
664 
665 /**
666  * wpas_dbus_handler_p2p_cancel - Cancel P2P group formation
667  * @message: Pointer to incoming dbus message
668  * @wpa_s: %wpa_supplicant data structure
669  * Returns: NULL on success or DBus error on failure
670  *
671  * Handler for "Cancel" method call. Returns NULL if P2P cancel succeeds or DBus
672  * error on P2P cancel failure
673  */
674 DBusMessage * wpas_dbus_handler_p2p_cancel(DBusMessage *message,
675 					   struct wpa_supplicant *wpa_s)
676 {
677 	if (wpas_p2p_cancel(wpa_s))
678 		return wpas_dbus_error_unknown_error(message,
679 						     "P2P cancel failed");
680 
681 	return NULL;
682 }
683 
684 
685 DBusMessage * wpas_dbus_handler_p2p_invite(DBusMessage *message,
686 					   struct wpa_supplicant *wpa_s)
687 {
688 	DBusMessageIter iter_dict;
689 	DBusMessage *reply = NULL;
690 	DBusMessageIter iter;
691 	struct wpa_dbus_dict_entry entry;
692 	char *peer_object_path = NULL;
693 	char *pg_object_path = NULL;
694 	char *iface = NULL;
695 	u8 peer_addr[ETH_ALEN];
696 	unsigned int group_id = 0;
697 	int persistent = 0;
698 	struct wpa_ssid *ssid;
699 
700 	if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL))
701 		return reply;
702 
703 	dbus_message_iter_init(message, &iter);
704 
705 	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
706 		goto err;
707 
708 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
709 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
710 			goto err;
711 
712 		if (os_strcmp(entry.key, "peer") == 0 &&
713 		    entry.type == DBUS_TYPE_OBJECT_PATH) {
714 			peer_object_path = os_strdup(entry.str_value);
715 			wpa_dbus_dict_entry_clear(&entry);
716 		} else if (os_strcmp(entry.key, "persistent_group_object") ==
717 			   0 &&
718 			   entry.type == DBUS_TYPE_OBJECT_PATH) {
719 			pg_object_path = os_strdup(entry.str_value);
720 			persistent = 1;
721 			wpa_dbus_dict_entry_clear(&entry);
722 		} else {
723 			wpa_dbus_dict_entry_clear(&entry);
724 			goto err;
725 		}
726 	}
727 
728 	if (parse_peer_object_path(peer_object_path, peer_addr) < 0 ||
729 	    !p2p_peer_known(wpa_s->global->p2p, peer_addr))
730 		goto err;
731 
732 	wpa_s = wpa_s->global->p2p_init_wpa_s;
733 
734 	if (persistent) {
735 		char *net_id_str;
736 		/*
737 		 * A group ID is defined meaning we want to re-invoke a
738 		 * persistent group
739 		 */
740 
741 		iface = wpas_dbus_new_decompose_object_path(
742 			pg_object_path,
743 			WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART,
744 			&net_id_str);
745 		if (iface == NULL || net_id_str == NULL ||
746 		    !wpa_s->parent->dbus_new_path ||
747 		    os_strcmp(iface, wpa_s->parent->dbus_new_path) != 0) {
748 			reply = wpas_dbus_error_invalid_args(message,
749 							     pg_object_path);
750 			goto out;
751 		}
752 
753 		group_id = strtoul(net_id_str, NULL, 10);
754 		if (errno == EINVAL) {
755 			reply = wpas_dbus_error_invalid_args(
756 				message, pg_object_path);
757 			goto out;
758 		}
759 
760 		/* Get the SSID structure from the persistent group id */
761 		ssid = wpa_config_get_network(wpa_s->conf, group_id);
762 		if (ssid == NULL || ssid->disabled != 2)
763 			goto err;
764 
765 		if (wpas_p2p_invite(wpa_s, peer_addr, ssid, NULL, 0, 0, 0, 0, 0,
766 				    0, 0) < 0) {
767 			reply = wpas_dbus_error_unknown_error(
768 				message,
769 				"Failed to reinvoke a persistent group");
770 			goto out;
771 		}
772 	} else {
773 		/*
774 		 * No group ID means propose to a peer to join my active group
775 		 */
776 		if (wpas_p2p_invite_group(wpa_s, wpa_s->ifname,
777 					  peer_addr, NULL)) {
778 			reply = wpas_dbus_error_unknown_error(
779 				message, "Failed to join to an active group");
780 			goto out;
781 		}
782 	}
783 
784 out:
785 	os_free(iface);
786 	os_free(pg_object_path);
787 	os_free(peer_object_path);
788 	return reply;
789 
790 err:
791 	reply = wpas_dbus_error_invalid_args(message, NULL);
792 	goto out;
793 }
794 
795 
796 DBusMessage * wpas_dbus_handler_p2p_prov_disc_req(DBusMessage *message,
797 						  struct wpa_supplicant *wpa_s)
798 {
799 	DBusMessageIter iter;
800 	char *peer_object_path = NULL;
801 	char *config_method = NULL;
802 	u8 peer_addr[ETH_ALEN];
803 
804 	dbus_message_iter_init(message, &iter);
805 	dbus_message_iter_get_basic(&iter, &peer_object_path);
806 
807 	if (parse_peer_object_path(peer_object_path, peer_addr) < 0)
808 		return wpas_dbus_error_invalid_args(message, NULL);
809 
810 	dbus_message_iter_next(&iter);
811 	dbus_message_iter_get_basic(&iter, &config_method);
812 
813 	/*
814 	 * Validation checks on config_method are being duplicated here
815 	 * to be able to return invalid args reply since the error code
816 	 * from p2p module are not granular enough (yet).
817 	 */
818 	if (os_strcmp(config_method, "display") &&
819 	    os_strcmp(config_method, "keypad") &&
820 	    os_strcmp(config_method, "pbc") &&
821 	    os_strcmp(config_method, "pushbutton"))
822 		return wpas_dbus_error_invalid_args(message, NULL);
823 
824 	wpa_s = wpa_s->global->p2p_init_wpa_s;
825 
826 	if (wpas_p2p_prov_disc(wpa_s, peer_addr, config_method,
827 			       WPAS_P2P_PD_FOR_GO_NEG, NULL) < 0)
828 		return wpas_dbus_error_unknown_error(message,
829 				"Failed to send provision discovery request");
830 
831 	return NULL;
832 }
833 
834 
835 /*
836  * P2P Device property accessor methods.
837  */
838 
839 dbus_bool_t wpas_dbus_getter_p2p_device_config(
840 	const struct wpa_dbus_property_desc *property_desc,
841 	DBusMessageIter *iter, DBusError *error, void *user_data)
842 {
843 	struct wpa_supplicant *wpa_s = user_data;
844 	DBusMessageIter variant_iter, dict_iter;
845 	DBusMessageIter iter_secdev_dict_entry, iter_secdev_dict_val,
846 		iter_secdev_dict_array;
847 	const char *dev_name;
848 	int num_vendor_extensions = 0;
849 	int i;
850 	const struct wpabuf *vendor_ext[P2P_MAX_WPS_VENDOR_EXT];
851 
852 	if (!wpa_dbus_p2p_check_enabled(wpa_s, NULL, NULL, error))
853 		return FALSE;
854 
855 	wpa_s = wpa_s->global->p2p_init_wpa_s;
856 
857 	if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
858 					      "a{sv}", &variant_iter) ||
859 	    !wpa_dbus_dict_open_write(&variant_iter, &dict_iter))
860 		goto err_no_mem;
861 
862 	/* DeviceName */
863 	dev_name = wpa_s->conf->device_name;
864 	if (dev_name &&
865 	    !wpa_dbus_dict_append_string(&dict_iter, "DeviceName", dev_name))
866 		goto err_no_mem;
867 
868 	/* Primary device type */
869 	if (!wpa_dbus_dict_append_byte_array(&dict_iter, "PrimaryDeviceType",
870 					     (char *) wpa_s->conf->device_type,
871 					     WPS_DEV_TYPE_LEN))
872 		goto err_no_mem;
873 
874 	/* Secondary device types */
875 	if (wpa_s->conf->num_sec_device_types) {
876 		if (!wpa_dbus_dict_begin_array(&dict_iter,
877 					       "SecondaryDeviceTypes",
878 					       DBUS_TYPE_ARRAY_AS_STRING
879 					       DBUS_TYPE_BYTE_AS_STRING,
880 					       &iter_secdev_dict_entry,
881 					       &iter_secdev_dict_val,
882 					       &iter_secdev_dict_array))
883 			goto err_no_mem;
884 
885 		for (i = 0; i < wpa_s->conf->num_sec_device_types; i++)
886 			wpa_dbus_dict_bin_array_add_element(
887 				&iter_secdev_dict_array,
888 				wpa_s->conf->sec_device_type[i],
889 				WPS_DEV_TYPE_LEN);
890 
891 		if (!wpa_dbus_dict_end_array(&dict_iter,
892 					     &iter_secdev_dict_entry,
893 					     &iter_secdev_dict_val,
894 					     &iter_secdev_dict_array))
895 			goto err_no_mem;
896 	}
897 
898 	/* GO IP address */
899 	if (WPA_GET_BE32(wpa_s->conf->ip_addr_go) &&
900 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddrGo",
901 					     (char *) wpa_s->conf->ip_addr_go,
902 					     4))
903 		goto err_no_mem;
904 
905 	/* IP address mask */
906 	if (WPA_GET_BE32(wpa_s->conf->ip_addr_mask) &&
907 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddrMask",
908 					     (char *) wpa_s->conf->ip_addr_mask,
909 					     4))
910 		goto err_no_mem;
911 
912 	/* IP address start */
913 	if (WPA_GET_BE32(wpa_s->conf->ip_addr_start) &&
914 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddrStart",
915 					     (char *)
916 					     wpa_s->conf->ip_addr_start,
917 					     4))
918 		goto err_no_mem;
919 
920 	/* IP address end */
921 	if (WPA_GET_BE32(wpa_s->conf->ip_addr_end) &&
922 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddrEnd",
923 					     (char *) wpa_s->conf->ip_addr_end,
924 					     4))
925 		goto err_no_mem;
926 
927 	/* Vendor Extensions */
928 	for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
929 		if (wpa_s->conf->wps_vendor_ext[i] == NULL)
930 			continue;
931 		vendor_ext[num_vendor_extensions++] =
932 			wpa_s->conf->wps_vendor_ext[i];
933 	}
934 
935 	if ((num_vendor_extensions &&
936 	     !wpa_dbus_dict_append_wpabuf_array(&dict_iter,
937 						"VendorExtension",
938 						vendor_ext,
939 						num_vendor_extensions)) ||
940 	    !wpa_dbus_dict_append_uint32(&dict_iter, "GOIntent",
941 					 wpa_s->conf->p2p_go_intent) ||
942 	    !wpa_dbus_dict_append_bool(&dict_iter, "PersistentReconnect",
943 				       wpa_s->conf->persistent_reconnect) ||
944 	    !wpa_dbus_dict_append_uint32(&dict_iter, "ListenRegClass",
945 					 wpa_s->conf->p2p_listen_reg_class) ||
946 	    !wpa_dbus_dict_append_uint32(&dict_iter, "ListenChannel",
947 					 wpa_s->conf->p2p_listen_channel) ||
948 	    !wpa_dbus_dict_append_uint32(&dict_iter, "OperRegClass",
949 					 wpa_s->conf->p2p_oper_reg_class) ||
950 	    !wpa_dbus_dict_append_uint32(&dict_iter, "OperChannel",
951 					 wpa_s->conf->p2p_oper_channel) ||
952 	    (wpa_s->conf->p2p_ssid_postfix &&
953 	     !wpa_dbus_dict_append_string(&dict_iter, "SsidPostfix",
954 					  wpa_s->conf->p2p_ssid_postfix)) ||
955 	    !wpa_dbus_dict_append_bool(&dict_iter, "IntraBss",
956 				       wpa_s->conf->p2p_intra_bss) ||
957 	    !wpa_dbus_dict_append_uint32(&dict_iter, "GroupIdle",
958 					 wpa_s->conf->p2p_group_idle) ||
959 	    !wpa_dbus_dict_append_uint32(&dict_iter, "disassoc_low_ack",
960 					 wpa_s->conf->disassoc_low_ack) ||
961 	    !wpa_dbus_dict_append_bool(&dict_iter, "NoGroupIface",
962 				       wpa_s->conf->p2p_no_group_iface) ||
963 	    !wpa_dbus_dict_append_uint32(&dict_iter, "p2p_search_delay",
964 					 wpa_s->conf->p2p_search_delay) ||
965 	    !wpa_dbus_dict_close_write(&variant_iter, &dict_iter) ||
966 	    !dbus_message_iter_close_container(iter, &variant_iter))
967 		goto err_no_mem;
968 
969 	return TRUE;
970 
971 err_no_mem:
972 	dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
973 	return FALSE;
974 }
975 
976 
977 dbus_bool_t wpas_dbus_setter_p2p_device_config(
978 	const struct wpa_dbus_property_desc *property_desc,
979 	DBusMessageIter *iter, DBusError *error, void *user_data)
980 {
981 	struct wpa_supplicant *wpa_s = user_data;
982 	DBusMessageIter variant_iter, iter_dict;
983 	struct wpa_dbus_dict_entry entry = {.type = DBUS_TYPE_STRING };
984 	unsigned int i;
985 
986 	if (!wpa_dbus_p2p_check_enabled(wpa_s, NULL, NULL, error))
987 		return FALSE;
988 
989 	wpa_s = wpa_s->global->p2p_init_wpa_s;
990 
991 	dbus_message_iter_recurse(iter, &variant_iter);
992 	if (!wpa_dbus_dict_open_read(&variant_iter, &iter_dict, error))
993 		return FALSE;
994 
995 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
996 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) {
997 			dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
998 					     "invalid message format");
999 			return FALSE;
1000 		}
1001 
1002 		if (os_strcmp(entry.key, "DeviceName") == 0) {
1003 			char *devname;
1004 
1005 			if (entry.type != DBUS_TYPE_STRING ||
1006 			    os_strlen(entry.str_value) > WPS_DEV_NAME_MAX_LEN)
1007 				goto error;
1008 
1009 			devname = os_strdup(entry.str_value);
1010 			if (devname == NULL)
1011 				goto err_no_mem_clear;
1012 
1013 			os_free(wpa_s->conf->device_name);
1014 			wpa_s->conf->device_name = devname;
1015 
1016 			wpa_s->conf->changed_parameters |=
1017 				CFG_CHANGED_DEVICE_NAME;
1018 		} else if (os_strcmp(entry.key, "PrimaryDeviceType") == 0) {
1019 			if (entry.type != DBUS_TYPE_ARRAY ||
1020 			    entry.array_type != DBUS_TYPE_BYTE ||
1021 			    entry.array_len != WPS_DEV_TYPE_LEN)
1022 				goto error;
1023 
1024 			os_memcpy(wpa_s->conf->device_type,
1025 				  entry.bytearray_value,
1026 				  WPS_DEV_TYPE_LEN);
1027 			wpa_s->conf->changed_parameters |=
1028 				CFG_CHANGED_DEVICE_TYPE;
1029 		} else if (os_strcmp(entry.key, "SecondaryDeviceTypes") == 0) {
1030 			if (entry.type != DBUS_TYPE_ARRAY ||
1031 			    entry.array_type != WPAS_DBUS_TYPE_BINARRAY ||
1032 			    entry.array_len > MAX_SEC_DEVICE_TYPES)
1033 				goto error;
1034 
1035 			for (i = 0; i < entry.array_len; i++)
1036 				if (wpabuf_len(entry.binarray_value[i]) !=
1037 				    WPS_DEV_TYPE_LEN)
1038 					goto err_no_mem_clear;
1039 			for (i = 0; i < entry.array_len; i++)
1040 				os_memcpy(wpa_s->conf->sec_device_type[i],
1041 					  wpabuf_head(entry.binarray_value[i]),
1042 					  WPS_DEV_TYPE_LEN);
1043 			wpa_s->conf->num_sec_device_types = entry.array_len;
1044 			wpa_s->conf->changed_parameters |=
1045 					CFG_CHANGED_SEC_DEVICE_TYPE;
1046 		} else if (os_strcmp(entry.key, "VendorExtension") == 0) {
1047 			if (entry.type != DBUS_TYPE_ARRAY ||
1048 			    entry.array_type != WPAS_DBUS_TYPE_BINARRAY ||
1049 			    (entry.array_len > P2P_MAX_WPS_VENDOR_EXT))
1050 				goto error;
1051 
1052 			wpa_s->conf->changed_parameters |=
1053 				CFG_CHANGED_VENDOR_EXTENSION;
1054 
1055 			for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
1056 				wpabuf_free(wpa_s->conf->wps_vendor_ext[i]);
1057 				if (i < entry.array_len) {
1058 					wpa_s->conf->wps_vendor_ext[i] =
1059 						entry.binarray_value[i];
1060 					entry.binarray_value[i] = NULL;
1061 				} else
1062 					wpa_s->conf->wps_vendor_ext[i] = NULL;
1063 			}
1064 		} else if (os_strcmp(entry.key, "GOIntent") == 0 &&
1065 			   entry.type == DBUS_TYPE_UINT32 &&
1066 			   (entry.uint32_value <= 15))
1067 			wpa_s->conf->p2p_go_intent = entry.uint32_value;
1068 		else if (os_strcmp(entry.key, "PersistentReconnect") == 0 &&
1069 			 entry.type == DBUS_TYPE_BOOLEAN)
1070 			wpa_s->conf->persistent_reconnect = entry.bool_value;
1071 		else if (os_strcmp(entry.key, "ListenRegClass") == 0 &&
1072 			 entry.type == DBUS_TYPE_UINT32) {
1073 			wpa_s->conf->p2p_listen_reg_class = entry.uint32_value;
1074 			wpa_s->conf->changed_parameters |=
1075 				CFG_CHANGED_P2P_LISTEN_CHANNEL;
1076 		} else if (os_strcmp(entry.key, "ListenChannel") == 0 &&
1077 			   entry.type == DBUS_TYPE_UINT32) {
1078 			wpa_s->conf->p2p_listen_channel = entry.uint32_value;
1079 			wpa_s->conf->changed_parameters |=
1080 				CFG_CHANGED_P2P_LISTEN_CHANNEL;
1081 		} else if (os_strcmp(entry.key, "OperRegClass") == 0 &&
1082 			   entry.type == DBUS_TYPE_UINT32) {
1083 			wpa_s->conf->p2p_oper_reg_class = entry.uint32_value;
1084 			wpa_s->conf->changed_parameters |=
1085 				CFG_CHANGED_P2P_OPER_CHANNEL;
1086 		} else if (os_strcmp(entry.key, "OperChannel") == 0 &&
1087 			   entry.type == DBUS_TYPE_UINT32) {
1088 			wpa_s->conf->p2p_oper_channel = entry.uint32_value;
1089 			wpa_s->conf->changed_parameters |=
1090 				CFG_CHANGED_P2P_OPER_CHANNEL;
1091 		} else if (os_strcmp(entry.key, "SsidPostfix") == 0) {
1092 			char *postfix;
1093 
1094 			if (entry.type != DBUS_TYPE_STRING)
1095 				goto error;
1096 
1097 			postfix = os_strdup(entry.str_value);
1098 			if (!postfix)
1099 				goto err_no_mem_clear;
1100 
1101 			os_free(wpa_s->conf->p2p_ssid_postfix);
1102 			wpa_s->conf->p2p_ssid_postfix = postfix;
1103 
1104 			wpa_s->conf->changed_parameters |=
1105 					CFG_CHANGED_P2P_SSID_POSTFIX;
1106 		} else if (os_strcmp(entry.key, "IntraBss") == 0 &&
1107 			   entry.type == DBUS_TYPE_BOOLEAN) {
1108 			wpa_s->conf->p2p_intra_bss = entry.bool_value;
1109 			wpa_s->conf->changed_parameters |=
1110 				CFG_CHANGED_P2P_INTRA_BSS;
1111 		} else if (os_strcmp(entry.key, "IpAddrGo") == 0) {
1112 			if (!wpas_dbus_validate_dbus_ipaddr(entry))
1113 				goto error;
1114 			os_memcpy(wpa_s->conf->ip_addr_go,
1115 				  entry.bytearray_value, 4);
1116 		} else if (os_strcmp(entry.key, "IpAddrMask") == 0) {
1117 			if (!wpas_dbus_validate_dbus_ipaddr(entry))
1118 				goto error;
1119 			os_memcpy(wpa_s->conf->ip_addr_mask,
1120 				  entry.bytearray_value, 4);
1121 		} else if (os_strcmp(entry.key, "IpAddrStart") == 0) {
1122 			if (!wpas_dbus_validate_dbus_ipaddr(entry))
1123 				goto error;
1124 			os_memcpy(wpa_s->conf->ip_addr_start,
1125 				  entry.bytearray_value, 4);
1126 		} else if (os_strcmp(entry.key, "IpAddrEnd") == 0) {
1127 			if (!wpas_dbus_validate_dbus_ipaddr(entry))
1128 				goto error;
1129 			os_memcpy(wpa_s->conf->ip_addr_end,
1130 				  entry.bytearray_value, 4);
1131 		} else if (os_strcmp(entry.key, "GroupIdle") == 0 &&
1132 			   entry.type == DBUS_TYPE_UINT32)
1133 			wpa_s->conf->p2p_group_idle = entry.uint32_value;
1134 		else if (os_strcmp(entry.key, "disassoc_low_ack") == 0 &&
1135 			 entry.type == DBUS_TYPE_UINT32)
1136 			wpa_s->conf->disassoc_low_ack = entry.uint32_value;
1137 		else if (os_strcmp(entry.key, "NoGroupIface") == 0 &&
1138 			 entry.type == DBUS_TYPE_BOOLEAN)
1139 			wpa_s->conf->p2p_no_group_iface = entry.bool_value;
1140 		else if (os_strcmp(entry.key, "p2p_search_delay") == 0 &&
1141 			 entry.type == DBUS_TYPE_UINT32)
1142 			wpa_s->conf->p2p_search_delay = entry.uint32_value;
1143 		else
1144 			goto error;
1145 
1146 		wpa_dbus_dict_entry_clear(&entry);
1147 	}
1148 
1149 	if (wpa_s->conf->changed_parameters) {
1150 		/* Some changed parameters requires to update config*/
1151 		wpa_supplicant_update_config(wpa_s);
1152 	}
1153 
1154 	return TRUE;
1155 
1156  error:
1157 	dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
1158 			     "invalid message format");
1159 	wpa_dbus_dict_entry_clear(&entry);
1160 	return FALSE;
1161 
1162  err_no_mem_clear:
1163 	dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1164 	wpa_dbus_dict_entry_clear(&entry);
1165 	return FALSE;
1166 }
1167 
1168 
1169 dbus_bool_t wpas_dbus_getter_p2p_peers(
1170 	const struct wpa_dbus_property_desc *property_desc,
1171 	DBusMessageIter *iter, DBusError *error, void *user_data)
1172 {
1173 	struct wpa_supplicant *wpa_s = user_data;
1174 	struct p2p_data *p2p = wpa_s->global->p2p;
1175 	int next = 0, i = 0;
1176 	int num = 0, out_of_mem = 0;
1177 	const u8 *addr;
1178 	const struct p2p_peer_info *peer_info = NULL;
1179 	dbus_bool_t success = FALSE;
1180 
1181 	struct dl_list peer_objpath_list;
1182 	struct peer_objpath_node {
1183 		struct dl_list list;
1184 		char path[WPAS_DBUS_OBJECT_PATH_MAX];
1185 	} *node, *tmp;
1186 
1187 	char **peer_obj_paths = NULL;
1188 
1189 	if (!wpa_dbus_p2p_check_enabled(wpa_s, NULL, NULL, error) ||
1190 	    !wpa_s->parent->parent->dbus_new_path)
1191 		return FALSE;
1192 
1193 	dl_list_init(&peer_objpath_list);
1194 
1195 	/* Get the first peer info */
1196 	peer_info = p2p_get_peer_found(p2p, NULL, next);
1197 
1198 	/* Get next and accumulate them */
1199 	next = 1;
1200 	while (peer_info != NULL) {
1201 		node = os_zalloc(sizeof(struct peer_objpath_node));
1202 		if (!node) {
1203 			out_of_mem = 1;
1204 			goto error;
1205 		}
1206 
1207 		addr = peer_info->p2p_device_addr;
1208 		os_snprintf(node->path, WPAS_DBUS_OBJECT_PATH_MAX,
1209 			    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART
1210 			    "/" COMPACT_MACSTR,
1211 			    wpa_s->parent->parent->dbus_new_path,
1212 			    MAC2STR(addr));
1213 		dl_list_add_tail(&peer_objpath_list, &node->list);
1214 		num++;
1215 
1216 		peer_info = p2p_get_peer_found(p2p, addr, next);
1217 	}
1218 
1219 	/*
1220 	 * Now construct the peer object paths in a form suitable for
1221 	 * array_property_getter helper below.
1222 	 */
1223 	peer_obj_paths = os_calloc(num, sizeof(char *));
1224 
1225 	if (!peer_obj_paths) {
1226 		out_of_mem = 1;
1227 		goto error;
1228 	}
1229 
1230 	dl_list_for_each_safe(node, tmp, &peer_objpath_list,
1231 			      struct peer_objpath_node, list)
1232 		peer_obj_paths[i++] = node->path;
1233 
1234 	success = wpas_dbus_simple_array_property_getter(iter,
1235 							 DBUS_TYPE_OBJECT_PATH,
1236 							 peer_obj_paths, num,
1237 							 error);
1238 
1239 error:
1240 	if (peer_obj_paths)
1241 		os_free(peer_obj_paths);
1242 
1243 	dl_list_for_each_safe(node, tmp, &peer_objpath_list,
1244 			      struct peer_objpath_node, list) {
1245 		dl_list_del(&node->list);
1246 		os_free(node);
1247 	}
1248 	if (out_of_mem)
1249 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1250 
1251 	return success;
1252 }
1253 
1254 
1255 enum wpas_p2p_role {
1256 	WPAS_P2P_ROLE_DEVICE,
1257 	WPAS_P2P_ROLE_GO,
1258 	WPAS_P2P_ROLE_CLIENT,
1259 };
1260 
1261 static enum wpas_p2p_role wpas_get_p2p_role(struct wpa_supplicant *wpa_s)
1262 {
1263 	struct wpa_ssid *ssid = wpa_s->current_ssid;
1264 
1265 	if (!ssid)
1266 		return WPAS_P2P_ROLE_DEVICE;
1267 	if (wpa_s->wpa_state != WPA_COMPLETED)
1268 		return WPAS_P2P_ROLE_DEVICE;
1269 
1270 	switch (ssid->mode) {
1271 	case WPAS_MODE_P2P_GO:
1272 	case WPAS_MODE_P2P_GROUP_FORMATION:
1273 		return WPAS_P2P_ROLE_GO;
1274 	case WPAS_MODE_INFRA:
1275 		if (ssid->p2p_group)
1276 			return WPAS_P2P_ROLE_CLIENT;
1277 		return WPAS_P2P_ROLE_DEVICE;
1278 	default:
1279 		return WPAS_P2P_ROLE_DEVICE;
1280 	}
1281 }
1282 
1283 
1284 dbus_bool_t wpas_dbus_getter_p2p_role(
1285 	const struct wpa_dbus_property_desc *property_desc,
1286 	DBusMessageIter *iter, DBusError *error, void *user_data)
1287 {
1288 	struct wpa_supplicant *wpa_s = user_data;
1289 	char *str;
1290 
1291 	switch (wpas_get_p2p_role(wpa_s)) {
1292 	case WPAS_P2P_ROLE_GO:
1293 		str = "GO";
1294 		break;
1295 	case WPAS_P2P_ROLE_CLIENT:
1296 		str = "client";
1297 		break;
1298 	default:
1299 		str = "device";
1300 		break;
1301 	}
1302 
1303 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &str,
1304 						error);
1305 }
1306 
1307 
1308 dbus_bool_t wpas_dbus_getter_p2p_group(
1309 	const struct wpa_dbus_property_desc *property_desc,
1310 	DBusMessageIter *iter, DBusError *error, void *user_data)
1311 {
1312 	struct wpa_supplicant *wpa_s = user_data;
1313 	char path_buf[WPAS_DBUS_OBJECT_PATH_MAX];
1314 	char *dbus_groupobj_path = path_buf;
1315 
1316 	if (wpa_s->dbus_groupobj_path == NULL)
1317 		os_snprintf(dbus_groupobj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1318 			    "/");
1319 	else
1320 		os_snprintf(dbus_groupobj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1321 			    "%s", wpa_s->dbus_groupobj_path);
1322 
1323 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
1324 						&dbus_groupobj_path, error);
1325 }
1326 
1327 
1328 dbus_bool_t wpas_dbus_getter_p2p_peergo(
1329 	const struct wpa_dbus_property_desc *property_desc,
1330 	DBusMessageIter *iter, DBusError *error, void *user_data)
1331 {
1332 	struct wpa_supplicant *wpa_s = user_data;
1333 	char go_peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1334 
1335 	if (!wpa_s->parent->parent->dbus_new_path)
1336 		return FALSE;
1337 
1338 	if (wpas_get_p2p_role(wpa_s) != WPAS_P2P_ROLE_CLIENT)
1339 		os_snprintf(go_peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
1340 	else
1341 		os_snprintf(go_peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1342 			    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
1343 			    COMPACT_MACSTR,
1344 			    wpa_s->parent->parent->dbus_new_path,
1345 			    MAC2STR(wpa_s->go_dev_addr));
1346 
1347 	path = go_peer_obj_path;
1348 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
1349 						&path, error);
1350 }
1351 
1352 
1353 /*
1354  * Peer object properties accessor methods
1355  */
1356 
1357 dbus_bool_t wpas_dbus_getter_p2p_peer_device_name(
1358 	const struct wpa_dbus_property_desc *property_desc,
1359 	DBusMessageIter *iter, DBusError *error, void *user_data)
1360 {
1361 	struct peer_handler_args *peer_args = user_data;
1362 	const struct p2p_peer_info *info;
1363 	char *tmp;
1364 
1365 	if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error))
1366 		return FALSE;
1367 
1368 	/* get the peer info */
1369 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1370 				  peer_args->p2p_device_addr, 0);
1371 	if (info == NULL) {
1372 		dbus_set_error(error, DBUS_ERROR_FAILED,
1373 			       "failed to find peer");
1374 		return FALSE;
1375 	}
1376 
1377 	tmp = os_strdup(info->device_name);
1378 	if (!tmp) {
1379 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1380 		return FALSE;
1381 	}
1382 
1383 	if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp,
1384 					      error)) {
1385 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1386 		os_free(tmp);
1387 		return FALSE;
1388 	}
1389 
1390 	os_free(tmp);
1391 	return TRUE;
1392 }
1393 
1394 
1395 dbus_bool_t wpas_dbus_getter_p2p_peer_manufacturer(
1396 	const struct wpa_dbus_property_desc *property_desc,
1397 	DBusMessageIter *iter, DBusError *error, void *user_data)
1398 {
1399 	struct peer_handler_args *peer_args = user_data;
1400 	const struct p2p_peer_info *info;
1401 	char *tmp;
1402 
1403 	if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error))
1404 		return FALSE;
1405 
1406 	/* get the peer info */
1407 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1408 				  peer_args->p2p_device_addr, 0);
1409 	if (info == NULL) {
1410 		dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer");
1411 		return FALSE;
1412 	}
1413 
1414 	tmp = os_strdup(info->manufacturer);
1415 	if (!tmp) {
1416 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1417 		return FALSE;
1418 	}
1419 
1420 	if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp,
1421 					      error)) {
1422 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1423 		os_free(tmp);
1424 		return FALSE;
1425 	}
1426 
1427 	os_free(tmp);
1428 	return TRUE;
1429 }
1430 
1431 
1432 dbus_bool_t wpas_dbus_getter_p2p_peer_modelname(
1433 	const struct wpa_dbus_property_desc *property_desc,
1434 	DBusMessageIter *iter, DBusError *error, void *user_data)
1435 {
1436 	struct peer_handler_args *peer_args = user_data;
1437 	const struct p2p_peer_info *info;
1438 	char *tmp;
1439 
1440 	if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error))
1441 		return FALSE;
1442 
1443 	/* get the peer info */
1444 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1445 				  peer_args->p2p_device_addr, 0);
1446 	if (info == NULL) {
1447 		dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer");
1448 		return FALSE;
1449 	}
1450 
1451 	tmp = os_strdup(info->model_name);
1452 	if (!tmp) {
1453 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1454 		return FALSE;
1455 	}
1456 
1457 	if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp,
1458 					      error)) {
1459 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1460 		os_free(tmp);
1461 		return FALSE;
1462 	}
1463 
1464 	os_free(tmp);
1465 	return TRUE;
1466 }
1467 
1468 
1469 dbus_bool_t wpas_dbus_getter_p2p_peer_modelnumber(
1470 	const struct wpa_dbus_property_desc *property_desc,
1471 	DBusMessageIter *iter, DBusError *error, void *user_data)
1472 {
1473 	struct peer_handler_args *peer_args = user_data;
1474 	const struct p2p_peer_info *info;
1475 	char *tmp;
1476 
1477 	if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error))
1478 		return FALSE;
1479 
1480 	/* get the peer info */
1481 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1482 				  peer_args->p2p_device_addr, 0);
1483 	if (info == NULL) {
1484 		dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer");
1485 		return FALSE;
1486 	}
1487 
1488 	tmp = os_strdup(info->model_number);
1489 	if (!tmp) {
1490 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1491 		return FALSE;
1492 	}
1493 
1494 	if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp,
1495 					      error)) {
1496 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1497 		os_free(tmp);
1498 		return FALSE;
1499 	}
1500 
1501 	os_free(tmp);
1502 	return TRUE;
1503 }
1504 
1505 
1506 dbus_bool_t wpas_dbus_getter_p2p_peer_serialnumber(
1507 	const struct wpa_dbus_property_desc *property_desc,
1508 	DBusMessageIter *iter, DBusError *error, void *user_data)
1509 {
1510 	struct peer_handler_args *peer_args = user_data;
1511 	const struct p2p_peer_info *info;
1512 	char *tmp;
1513 
1514 	if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error))
1515 		return FALSE;
1516 
1517 	/* get the peer info */
1518 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1519 				  peer_args->p2p_device_addr, 0);
1520 	if (info == NULL) {
1521 		dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer");
1522 		return FALSE;
1523 	}
1524 
1525 	tmp = os_strdup(info->serial_number);
1526 	if (!tmp) {
1527 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1528 		return FALSE;
1529 	}
1530 
1531 	if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp,
1532 					      error)) {
1533 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1534 		os_free(tmp);
1535 		return FALSE;
1536 	}
1537 
1538 	os_free(tmp);
1539 	return TRUE;
1540 }
1541 
1542 
1543 dbus_bool_t wpas_dbus_getter_p2p_peer_primary_device_type(
1544 	const struct wpa_dbus_property_desc *property_desc,
1545 	DBusMessageIter *iter, DBusError *error, void *user_data)
1546 {
1547 	struct peer_handler_args *peer_args = user_data;
1548 	const struct p2p_peer_info *info;
1549 
1550 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1551 				  peer_args->p2p_device_addr, 0);
1552 	if (info == NULL) {
1553 		dbus_set_error(error, DBUS_ERROR_FAILED,
1554 			       "failed to find peer");
1555 		return FALSE;
1556 	}
1557 
1558 	if (!wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
1559 						    (char *)
1560 						    info->pri_dev_type,
1561 						    WPS_DEV_TYPE_LEN, error)) {
1562 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1563 		return FALSE;
1564 	}
1565 
1566 	return TRUE;
1567 }
1568 
1569 
1570 dbus_bool_t wpas_dbus_getter_p2p_peer_config_method(
1571 	const struct wpa_dbus_property_desc *property_desc,
1572 	DBusMessageIter *iter, DBusError *error, void *user_data)
1573 {
1574 	struct peer_handler_args *peer_args = user_data;
1575 	const struct p2p_peer_info *info;
1576 
1577 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1578 				  peer_args->p2p_device_addr, 0);
1579 	if (info == NULL) {
1580 		dbus_set_error(error, DBUS_ERROR_FAILED,
1581 			       "failed to find peer");
1582 		return FALSE;
1583 	}
1584 
1585 	if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
1586 					      &info->config_methods, error)) {
1587 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1588 		return FALSE;
1589 	}
1590 
1591 	return TRUE;
1592 }
1593 
1594 
1595 dbus_bool_t wpas_dbus_getter_p2p_peer_level(
1596 	const struct wpa_dbus_property_desc *property_desc,
1597 	DBusMessageIter *iter, DBusError *error, void *user_data)
1598 {
1599 	struct peer_handler_args *peer_args = user_data;
1600 	const struct p2p_peer_info *info;
1601 
1602 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1603 				  peer_args->p2p_device_addr, 0);
1604 	if (info == NULL) {
1605 		dbus_set_error(error, DBUS_ERROR_FAILED,
1606 			       "failed to find peer");
1607 		return FALSE;
1608 	}
1609 
1610 	if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
1611 					      &info->level, error)) {
1612 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1613 		return FALSE;
1614 	}
1615 
1616 	return TRUE;
1617 }
1618 
1619 
1620 dbus_bool_t wpas_dbus_getter_p2p_peer_device_capability(
1621 	const struct wpa_dbus_property_desc *property_desc,
1622 	DBusMessageIter *iter, DBusError *error, void *user_data)
1623 {
1624 	struct peer_handler_args *peer_args = user_data;
1625 	const struct p2p_peer_info *info;
1626 
1627 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1628 				  peer_args->p2p_device_addr, 0);
1629 	if (info == NULL) {
1630 		dbus_set_error(error, DBUS_ERROR_FAILED,
1631 			       "failed to find peer");
1632 		return FALSE;
1633 	}
1634 
1635 	if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BYTE,
1636 					      &info->dev_capab, error)) {
1637 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1638 		return FALSE;
1639 	}
1640 
1641 	return TRUE;
1642 }
1643 
1644 
1645 dbus_bool_t wpas_dbus_getter_p2p_peer_group_capability(
1646 	const struct wpa_dbus_property_desc *property_desc,
1647 	DBusMessageIter *iter, DBusError *error, void *user_data)
1648 {
1649 	struct peer_handler_args *peer_args = user_data;
1650 	const struct p2p_peer_info *info;
1651 
1652 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1653 				  peer_args->p2p_device_addr, 0);
1654 	if (info == NULL) {
1655 		dbus_set_error(error, DBUS_ERROR_FAILED,
1656 			       "failed to find peer");
1657 		return FALSE;
1658 	}
1659 
1660 	if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BYTE,
1661 					      &info->group_capab, error)) {
1662 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1663 		return FALSE;
1664 	}
1665 
1666 	return TRUE;
1667 }
1668 
1669 
1670 dbus_bool_t wpas_dbus_getter_p2p_peer_secondary_device_types(
1671 	const struct wpa_dbus_property_desc *property_desc,
1672 	DBusMessageIter *iter, DBusError *error, void *user_data)
1673 {
1674 	struct peer_handler_args *peer_args = user_data;
1675 	const struct p2p_peer_info *info;
1676 	DBusMessageIter variant_iter, array_iter;
1677 
1678 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1679 				  peer_args->p2p_device_addr, 0);
1680 	if (info == NULL) {
1681 		dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer");
1682 		return FALSE;
1683 	}
1684 
1685 	if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
1686 					      DBUS_TYPE_ARRAY_AS_STRING
1687 					      DBUS_TYPE_ARRAY_AS_STRING
1688 					      DBUS_TYPE_BYTE_AS_STRING,
1689 					      &variant_iter) ||
1690 	    !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
1691 					      DBUS_TYPE_ARRAY_AS_STRING
1692 					      DBUS_TYPE_BYTE_AS_STRING,
1693 					      &array_iter)) {
1694 		dbus_set_error(error, DBUS_ERROR_FAILED,
1695 			       "%s: failed to construct message 1", __func__);
1696 		return FALSE;
1697 	}
1698 
1699 	if (info->wps_sec_dev_type_list_len) {
1700 		const u8 *sec_dev_type_list = info->wps_sec_dev_type_list;
1701 		int num_sec_device_types =
1702 			info->wps_sec_dev_type_list_len / WPS_DEV_TYPE_LEN;
1703 		int i;
1704 		DBusMessageIter inner_array_iter;
1705 
1706 		for (i = 0; i < num_sec_device_types; i++) {
1707 			if (!dbus_message_iter_open_container(
1708 				    &array_iter, DBUS_TYPE_ARRAY,
1709 				    DBUS_TYPE_BYTE_AS_STRING,
1710 				    &inner_array_iter) ||
1711 			    !dbus_message_iter_append_fixed_array(
1712 				    &inner_array_iter, DBUS_TYPE_BYTE,
1713 				    &sec_dev_type_list, WPS_DEV_TYPE_LEN) ||
1714 			    !dbus_message_iter_close_container(
1715 				    &array_iter, &inner_array_iter)) {
1716 				dbus_set_error(error, DBUS_ERROR_FAILED,
1717 					       "%s: failed to construct message 2 (%d)",
1718 					       __func__, i);
1719 				return FALSE;
1720 			}
1721 
1722 			sec_dev_type_list += WPS_DEV_TYPE_LEN;
1723 		}
1724 	}
1725 
1726 	if (!dbus_message_iter_close_container(&variant_iter, &array_iter) ||
1727 	    !dbus_message_iter_close_container(iter, &variant_iter)) {
1728 		dbus_set_error(error, DBUS_ERROR_FAILED,
1729 			       "%s: failed to construct message 3", __func__);
1730 		return FALSE;
1731 	}
1732 
1733 	return TRUE;
1734 }
1735 
1736 
1737 dbus_bool_t wpas_dbus_getter_p2p_peer_vendor_extension(
1738 	const struct wpa_dbus_property_desc *property_desc,
1739 	DBusMessageIter *iter, DBusError *error, void *user_data)
1740 {
1741 	struct wpabuf *vendor_extension[P2P_MAX_WPS_VENDOR_EXT];
1742 	unsigned int i, num = 0;
1743 	struct peer_handler_args *peer_args = user_data;
1744 	const struct p2p_peer_info *info;
1745 
1746 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1747 				  peer_args->p2p_device_addr, 0);
1748 	if (info == NULL) {
1749 		dbus_set_error(error, DBUS_ERROR_FAILED,
1750 			       "failed to find peer");
1751 		return FALSE;
1752 	}
1753 
1754 	/* Add WPS vendor extensions attribute */
1755 	os_memset(vendor_extension, 0, sizeof(vendor_extension));
1756 	for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
1757 		if (info->wps_vendor_ext[i] == NULL)
1758 			continue;
1759 		vendor_extension[num] = info->wps_vendor_ext[i];
1760 		num++;
1761 	}
1762 
1763 	if (!wpas_dbus_simple_array_array_property_getter(iter, DBUS_TYPE_BYTE,
1764 							  vendor_extension,
1765 							  num, error))
1766 		return FALSE;
1767 
1768 	return TRUE;
1769 }
1770 
1771 
1772 dbus_bool_t wpas_dbus_getter_p2p_peer_ies(
1773 	const struct wpa_dbus_property_desc *property_desc,
1774 	DBusMessageIter *iter, DBusError *error, void *user_data)
1775 {
1776 	struct peer_handler_args *peer_args = user_data;
1777 	const struct p2p_peer_info *info;
1778 
1779 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1780 				  peer_args->p2p_device_addr, 0);
1781 	if (info == NULL) {
1782 		dbus_set_error(error, DBUS_ERROR_FAILED,
1783 			       "failed to find peer");
1784 		return FALSE;
1785 	}
1786 
1787 	if (info->wfd_subelems == NULL)
1788 		return wpas_dbus_simple_array_property_getter(iter,
1789 							      DBUS_TYPE_BYTE,
1790 							      NULL, 0, error);
1791 
1792 	return wpas_dbus_simple_array_property_getter(
1793 		iter, DBUS_TYPE_BYTE, (char *) info->wfd_subelems->buf,
1794 		info->wfd_subelems->used, error);
1795 }
1796 
1797 
1798 dbus_bool_t wpas_dbus_getter_p2p_peer_device_address(
1799 	const struct wpa_dbus_property_desc *property_desc,
1800 	DBusMessageIter *iter, DBusError *error, void *user_data)
1801 {
1802 	struct peer_handler_args *peer_args = user_data;
1803 	const struct p2p_peer_info *info;
1804 
1805 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1806 				  peer_args->p2p_device_addr, 0);
1807 	if (info == NULL) {
1808 		dbus_set_error(error, DBUS_ERROR_FAILED,
1809 			       "failed to find peer");
1810 		return FALSE;
1811 	}
1812 
1813 	return wpas_dbus_simple_array_property_getter(
1814 		iter, DBUS_TYPE_BYTE, (char *) info->p2p_device_addr,
1815 		ETH_ALEN, error);
1816 }
1817 
1818 
1819 struct peer_group_data {
1820 	struct wpa_supplicant *wpa_s;
1821 	const struct p2p_peer_info *info;
1822 	char **paths;
1823 	unsigned int nb_paths;
1824 	int error;
1825 };
1826 
1827 
1828 static int match_group_where_peer_is_client(struct p2p_group *group,
1829 					    void *user_data)
1830 {
1831 	struct peer_group_data *data = user_data;
1832 	const struct p2p_group_config *cfg;
1833 	struct wpa_supplicant *wpa_s_go;
1834 	char **paths;
1835 
1836 	if (!p2p_group_is_client_connected(group, data->info->p2p_device_addr))
1837 		return 1;
1838 
1839 	cfg = p2p_group_get_config(group);
1840 
1841 	wpa_s_go = wpas_get_p2p_go_iface(data->wpa_s, cfg->ssid,
1842 					 cfg->ssid_len);
1843 	if (wpa_s_go == NULL)
1844 		return 1;
1845 
1846 	paths = os_realloc_array(data->paths, data->nb_paths + 1,
1847 				 sizeof(char *));
1848 	if (paths == NULL)
1849 		goto out_of_memory;
1850 
1851 	data->paths = paths;
1852 	data->paths[data->nb_paths] = wpa_s_go->dbus_groupobj_path;
1853 	data->nb_paths++;
1854 
1855 	return 1;
1856 
1857 out_of_memory:
1858 	data->error = ENOMEM;
1859 	return 0;
1860 }
1861 
1862 
1863 dbus_bool_t wpas_dbus_getter_p2p_peer_groups(
1864 	const struct wpa_dbus_property_desc *property_desc,
1865 	DBusMessageIter *iter, DBusError *error, void *user_data)
1866 {
1867 	struct peer_handler_args *peer_args = user_data;
1868 	const struct p2p_peer_info *info;
1869 	struct peer_group_data data;
1870 	struct wpa_supplicant *wpa_s, *wpa_s_go;
1871 	dbus_bool_t success = FALSE;
1872 
1873 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1874 				  peer_args->p2p_device_addr, 0);
1875 	if (info == NULL) {
1876 		dbus_set_error(error, DBUS_ERROR_FAILED,
1877 			       "failed to find peer");
1878 		return FALSE;
1879 	}
1880 
1881 	os_memset(&data, 0, sizeof(data));
1882 
1883 	wpa_s = peer_args->wpa_s;
1884 	wpa_s = wpa_s->global->p2p_init_wpa_s;
1885 
1886 	wpa_s_go = wpas_get_p2p_client_iface(wpa_s, info->p2p_device_addr);
1887 	if (wpa_s_go) {
1888 		data.paths = os_calloc(1, sizeof(char *));
1889 		if (data.paths == NULL)
1890 			goto out_of_memory;
1891 		data.paths[0] = wpa_s_go->dbus_groupobj_path;
1892 		data.nb_paths = 1;
1893 	}
1894 
1895 	data.wpa_s = peer_args->wpa_s;
1896 	data.info = info;
1897 
1898 	p2p_loop_on_all_groups(peer_args->wpa_s->global->p2p,
1899 			       match_group_where_peer_is_client, &data);
1900 	if (data.error)
1901 		goto out_of_memory;
1902 
1903 	if (data.paths == NULL) {
1904 		return wpas_dbus_simple_array_property_getter(
1905 			iter, DBUS_TYPE_OBJECT_PATH, NULL, 0, error);
1906 	}
1907 
1908 	success = wpas_dbus_simple_array_property_getter(iter,
1909 							 DBUS_TYPE_OBJECT_PATH,
1910 							 data.paths,
1911 							 data.nb_paths, error);
1912 	goto out;
1913 
1914 out_of_memory:
1915 	dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1916 out:
1917 	os_free(data.paths);
1918 	return success;
1919 }
1920 
1921 dbus_bool_t wpas_dbus_getter_p2p_peer_vsie(
1922 	const struct wpa_dbus_property_desc *property_desc,
1923 	DBusMessageIter *iter, DBusError *error, void *user_data)
1924 {
1925 	struct peer_handler_args *peer_args = user_data;
1926 	const struct p2p_peer_info *info;
1927 
1928 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1929 				  peer_args->p2p_device_addr, 0);
1930 	if (!info) {
1931 		dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer");
1932 		return FALSE;
1933 	}
1934 
1935 	if (!info->vendor_elems)
1936 		return wpas_dbus_simple_array_property_getter(iter,
1937 							      DBUS_TYPE_BYTE,
1938 							      NULL, 0, error);
1939 
1940 	return wpas_dbus_simple_array_property_getter(
1941 		iter, DBUS_TYPE_BYTE, (char *) info->vendor_elems->buf,
1942 		info->vendor_elems->used, error);
1943 }
1944 
1945 
1946 /**
1947  * wpas_dbus_getter_persistent_groups - Get array of persistent group objects
1948  * @iter: Pointer to incoming dbus message iter
1949  * @error: Location to store error on failure
1950  * @user_data: Function specific data
1951  * Returns: TRUE on success, FALSE on failure
1952  *
1953  * Getter for "PersistentGroups" property.
1954  */
1955 dbus_bool_t wpas_dbus_getter_persistent_groups(
1956 	const struct wpa_dbus_property_desc *property_desc,
1957 	DBusMessageIter *iter, DBusError *error, void *user_data)
1958 {
1959 	struct wpa_supplicant *wpa_s = user_data;
1960 	struct wpa_ssid *ssid;
1961 	char **paths;
1962 	unsigned int i = 0, num = 0;
1963 	dbus_bool_t success = FALSE;
1964 
1965 	wpa_s = wpa_s->global->p2p_init_wpa_s;
1966 	if (!wpa_s->parent->dbus_new_path)
1967 		return FALSE;
1968 
1969 	for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
1970 		if (network_is_persistent_group(ssid))
1971 			num++;
1972 
1973 	paths = os_calloc(num, sizeof(char *));
1974 	if (!paths) {
1975 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1976 		return FALSE;
1977 	}
1978 
1979 	/* Loop through configured networks and append object path of each */
1980 	for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1981 		if (!network_is_persistent_group(ssid))
1982 			continue;
1983 		paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1984 		if (paths[i] == NULL) {
1985 			dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
1986 					     "no memory");
1987 			goto out;
1988 		}
1989 		/* Construct the object path for this network. */
1990 		os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
1991 			    "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%d",
1992 			    wpa_s->parent->dbus_new_path, ssid->id);
1993 	}
1994 
1995 	success = wpas_dbus_simple_array_property_getter(iter,
1996 							 DBUS_TYPE_OBJECT_PATH,
1997 							 paths, num, error);
1998 
1999 out:
2000 	while (i)
2001 		os_free(paths[--i]);
2002 	os_free(paths);
2003 	return success;
2004 }
2005 
2006 
2007 /**
2008  * wpas_dbus_getter_persistent_group_properties - Get options for a persistent
2009  *	group
2010  * @iter: Pointer to incoming dbus message iter
2011  * @error: Location to store error on failure
2012  * @user_data: Function specific data
2013  * Returns: TRUE on success, FALSE on failure
2014  *
2015  * Getter for "Properties" property of a persistent group.
2016  */
2017 dbus_bool_t wpas_dbus_getter_persistent_group_properties(
2018 	const struct wpa_dbus_property_desc *property_desc,
2019 	DBusMessageIter *iter, DBusError *error, void *user_data)
2020 {
2021 	struct network_handler_args *net = user_data;
2022 
2023 	/* Leveraging the fact that persistent group object is still
2024 	 * represented in same manner as network within.
2025 	 */
2026 	return wpas_dbus_getter_network_properties(property_desc, iter, error, net);
2027 }
2028 
2029 
2030 /**
2031  * wpas_dbus_setter_persistent_group_properties - Set options for a persistent
2032  *	group
2033  * @iter: Pointer to incoming dbus message iter
2034  * @error: Location to store error on failure
2035  * @user_data: Function specific data
2036  * Returns: TRUE on success, FALSE on failure
2037  *
2038  * Setter for "Properties" property of a persistent group.
2039  */
2040 dbus_bool_t wpas_dbus_setter_persistent_group_properties(
2041 	const struct wpa_dbus_property_desc *property_desc,
2042 	DBusMessageIter *iter, DBusError *error, void *user_data)
2043 {
2044 	struct network_handler_args *net = user_data;
2045 	struct wpa_ssid *ssid = net->ssid;
2046 	DBusMessageIter	variant_iter;
2047 
2048 	/*
2049 	 * Leveraging the fact that persistent group object is still
2050 	 * represented in same manner as network within.
2051 	 */
2052 	dbus_message_iter_recurse(iter, &variant_iter);
2053 	return set_network_properties(net->wpa_s, ssid, &variant_iter, error);
2054 }
2055 
2056 
2057 /**
2058  * wpas_dbus_new_iface_add_persistent_group - Add a new configured
2059  *	persistent_group
2060  * @message: Pointer to incoming dbus message
2061  * @wpa_s: wpa_supplicant structure for a network interface
2062  * Returns: A dbus message containing the object path of the new
2063  * persistent group
2064  *
2065  * Handler function for "AddPersistentGroup" method call of a P2P Device
2066  * interface.
2067  */
2068 DBusMessage * wpas_dbus_handler_add_persistent_group(
2069 	DBusMessage *message, struct wpa_supplicant *wpa_s)
2070 {
2071 	DBusMessage *reply = NULL;
2072 	DBusMessageIter	iter;
2073 	struct wpa_ssid *ssid = NULL;
2074 	char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf;
2075 	DBusError error;
2076 
2077 	dbus_message_iter_init(message, &iter);
2078 
2079 	wpa_s = wpa_s->global->p2p_init_wpa_s;
2080 	if (wpa_s->parent->dbus_new_path)
2081 		ssid = wpa_config_add_network(wpa_s->conf);
2082 	if (ssid == NULL) {
2083 		wpa_printf(MSG_ERROR,
2084 			   "dbus: %s: Cannot add new persistent group",
2085 			   __func__);
2086 		reply = wpas_dbus_error_unknown_error(
2087 			message,
2088 			"wpa_supplicant could not add a persistent group on this interface.");
2089 		goto err;
2090 	}
2091 
2092 	/* Mark the ssid as being a persistent group before the notification */
2093 	ssid->disabled = 2;
2094 	ssid->p2p_persistent_group = 1;
2095 	wpas_notify_persistent_group_added(wpa_s, ssid);
2096 
2097 	wpa_config_set_network_defaults(ssid);
2098 
2099 	dbus_error_init(&error);
2100 	if (!set_network_properties(wpa_s, ssid, &iter, &error)) {
2101 		wpa_printf(MSG_DEBUG,
2102 			   "dbus: %s: Control interface could not set persistent group properties",
2103 			   __func__);
2104 		reply = wpas_dbus_reply_new_from_error(
2105 			message, &error, DBUS_ERROR_INVALID_ARGS,
2106 			"Failed to set network properties");
2107 		dbus_error_free(&error);
2108 		goto err;
2109 	}
2110 
2111 	/* Construct the object path for this network. */
2112 	os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
2113 		    "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%d",
2114 		    wpa_s->parent->dbus_new_path, ssid->id);
2115 
2116 	reply = dbus_message_new_method_return(message);
2117 	if (reply == NULL) {
2118 		reply = wpas_dbus_error_no_memory(message);
2119 		goto err;
2120 	}
2121 	if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
2122 				      DBUS_TYPE_INVALID)) {
2123 		dbus_message_unref(reply);
2124 		reply = wpas_dbus_error_no_memory(message);
2125 		goto err;
2126 	}
2127 
2128 	return reply;
2129 
2130 err:
2131 	if (ssid) {
2132 		wpas_notify_persistent_group_removed(wpa_s, ssid);
2133 		wpa_config_remove_network(wpa_s->conf, ssid->id);
2134 	}
2135 	return reply;
2136 }
2137 
2138 
2139 /**
2140  * wpas_dbus_handler_remove_persistent_group - Remove a configured persistent
2141  *	group
2142  * @message: Pointer to incoming dbus message
2143  * @wpa_s: wpa_supplicant structure for a network interface
2144  * Returns: NULL on success or dbus error on failure
2145  *
2146  * Handler function for "RemovePersistentGroup" method call of a P2P Device
2147  * interface.
2148  */
2149 DBusMessage * wpas_dbus_handler_remove_persistent_group(
2150 	DBusMessage *message, struct wpa_supplicant *wpa_s)
2151 {
2152 	DBusMessage *reply = NULL;
2153 	const char *op;
2154 	char *iface = NULL, *persistent_group_id;
2155 	int id;
2156 	struct wpa_ssid *ssid;
2157 
2158 	dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
2159 			      DBUS_TYPE_INVALID);
2160 
2161 	wpa_s = wpa_s->global->p2p_init_wpa_s;
2162 
2163 	/*
2164 	 * Extract the network ID and ensure the network is actually a child of
2165 	 * this interface.
2166 	 */
2167 	iface = wpas_dbus_new_decompose_object_path(
2168 		op, WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART,
2169 		&persistent_group_id);
2170 	if (iface == NULL || persistent_group_id == NULL ||
2171 	    !wpa_s->parent->dbus_new_path ||
2172 	    os_strcmp(iface, wpa_s->parent->dbus_new_path) != 0) {
2173 		reply = wpas_dbus_error_invalid_args(message, op);
2174 		goto out;
2175 	}
2176 
2177 	id = strtoul(persistent_group_id, NULL, 10);
2178 	if (errno == EINVAL) {
2179 		reply = wpas_dbus_error_invalid_args(message, op);
2180 		goto out;
2181 	}
2182 
2183 	ssid = wpa_config_get_network(wpa_s->conf, id);
2184 	if (ssid == NULL) {
2185 		reply = wpas_dbus_error_persistent_group_unknown(message);
2186 		goto out;
2187 	}
2188 
2189 	wpas_notify_persistent_group_removed(wpa_s, ssid);
2190 
2191 	if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
2192 		wpa_printf(MSG_ERROR,
2193 			   "dbus: %s: error occurred when removing persistent group %d",
2194 			   __func__, id);
2195 		reply = wpas_dbus_error_unknown_error(
2196 			message,
2197 			"error removing the specified persistent group on this interface.");
2198 		goto out;
2199 	}
2200 
2201 out:
2202 	os_free(iface);
2203 	return reply;
2204 }
2205 
2206 
2207 static void remove_persistent_group(struct wpa_supplicant *wpa_s,
2208 				    struct wpa_ssid *ssid)
2209 {
2210 	wpas_notify_persistent_group_removed(wpa_s, ssid);
2211 
2212 	if (wpa_config_remove_network(wpa_s->conf, ssid->id) < 0) {
2213 		wpa_printf(MSG_ERROR,
2214 			   "dbus: %s: error occurred when removing persistent group %d",
2215 			   __func__, ssid->id);
2216 		return;
2217 	}
2218 }
2219 
2220 
2221 /**
2222  * wpas_dbus_handler_remove_all_persistent_groups - Remove all configured
2223  * persistent groups
2224  * @message: Pointer to incoming dbus message
2225  * @wpa_s: wpa_supplicant structure for a network interface
2226  * Returns: NULL on success or dbus error on failure
2227  *
2228  * Handler function for "RemoveAllPersistentGroups" method call of a
2229  * P2P Device interface.
2230  */
2231 DBusMessage * wpas_dbus_handler_remove_all_persistent_groups(
2232 	DBusMessage *message, struct wpa_supplicant *wpa_s)
2233 {
2234 	struct wpa_ssid *ssid, *next;
2235 	struct wpa_config *config;
2236 
2237 	wpa_s = wpa_s->global->p2p_init_wpa_s;
2238 
2239 	config = wpa_s->conf;
2240 	ssid = config->ssid;
2241 	while (ssid) {
2242 		next = ssid->next;
2243 		if (network_is_persistent_group(ssid))
2244 			remove_persistent_group(wpa_s, ssid);
2245 		ssid = next;
2246 	}
2247 	return NULL;
2248 }
2249 
2250 
2251 /*
2252  * Group object properties accessor methods
2253  */
2254 
2255 dbus_bool_t wpas_dbus_getter_p2p_group_members(
2256 	const struct wpa_dbus_property_desc *property_desc,
2257 	DBusMessageIter *iter, DBusError *error, void *user_data)
2258 {
2259 	struct wpa_supplicant *wpa_s = user_data;
2260 	struct wpa_ssid *ssid;
2261 	unsigned int num_members;
2262 	char **paths;
2263 	unsigned int i;
2264 	void *next = NULL;
2265 	const u8 *addr;
2266 	dbus_bool_t success = FALSE;
2267 
2268 	if (!wpa_s->parent->parent->dbus_new_path)
2269 		return FALSE;
2270 
2271 	/* Verify correct role for this property */
2272 	if (wpas_get_p2p_role(wpa_s) != WPAS_P2P_ROLE_GO) {
2273 		return wpas_dbus_simple_array_property_getter(
2274 			iter, DBUS_TYPE_OBJECT_PATH, NULL, 0, error);
2275 	}
2276 
2277 	ssid = wpa_s->conf->ssid;
2278 	/* At present WPAS P2P_GO mode only applicable for p2p_go */
2279 	if (ssid->mode != WPAS_MODE_P2P_GO &&
2280 	    ssid->mode != WPAS_MODE_AP &&
2281 	    ssid->mode != WPAS_MODE_P2P_GROUP_FORMATION)
2282 		return FALSE;
2283 
2284 	num_members = p2p_get_group_num_members(wpa_s->p2p_group);
2285 
2286 	paths = os_calloc(num_members, sizeof(char *));
2287 	if (!paths)
2288 		goto out_of_memory;
2289 
2290 	i = 0;
2291 	while ((addr = p2p_iterate_group_members(wpa_s->p2p_group, &next))) {
2292 		paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
2293 		if (!paths[i])
2294 			goto out_of_memory;
2295 		os_snprintf(paths[i], WPAS_DBUS_OBJECT_PATH_MAX,
2296 			    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART
2297 			    "/" COMPACT_MACSTR,
2298 			    wpa_s->parent->parent->dbus_new_path,
2299 			    MAC2STR(addr));
2300 		i++;
2301 	}
2302 
2303 	success = wpas_dbus_simple_array_property_getter(iter,
2304 							 DBUS_TYPE_OBJECT_PATH,
2305 							 paths, num_members,
2306 							 error);
2307 
2308 	for (i = 0; i < num_members; i++)
2309 		os_free(paths[i]);
2310 	os_free(paths);
2311 	return success;
2312 
2313 out_of_memory:
2314 	dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
2315 	if (paths) {
2316 		for (i = 0; i < num_members; i++)
2317 			os_free(paths[i]);
2318 		os_free(paths);
2319 	}
2320 	return FALSE;
2321 }
2322 
2323 
2324 dbus_bool_t wpas_dbus_getter_p2p_group_ssid(
2325 	const struct wpa_dbus_property_desc *property_desc,
2326 	DBusMessageIter *iter, DBusError *error, void *user_data)
2327 {
2328 	struct wpa_supplicant *wpa_s = user_data;
2329 
2330 	if (wpa_s->current_ssid == NULL)
2331 		return FALSE;
2332 	return wpas_dbus_simple_array_property_getter(
2333 		iter, DBUS_TYPE_BYTE, wpa_s->current_ssid->ssid,
2334 		wpa_s->current_ssid->ssid_len, error);
2335 }
2336 
2337 
2338 dbus_bool_t wpas_dbus_getter_p2p_group_bssid(
2339 	const struct wpa_dbus_property_desc *property_desc,
2340 	DBusMessageIter *iter, DBusError *error, void *user_data)
2341 {
2342 	struct wpa_supplicant *wpa_s = user_data;
2343 	u8 role = wpas_get_p2p_role(wpa_s);
2344 	u8 *p_bssid;
2345 
2346 	if (role == WPAS_P2P_ROLE_CLIENT) {
2347 		if (wpa_s->current_ssid == NULL)
2348 			return FALSE;
2349 		p_bssid = wpa_s->current_ssid->bssid;
2350 	} else {
2351 		if (wpa_s->ap_iface == NULL)
2352 			return FALSE;
2353 		p_bssid = wpa_s->ap_iface->bss[0]->own_addr;
2354 	}
2355 
2356 	return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
2357 						      p_bssid, ETH_ALEN,
2358 						      error);
2359 }
2360 
2361 
2362 dbus_bool_t wpas_dbus_getter_p2p_group_frequency(
2363 	const struct wpa_dbus_property_desc *property_desc,
2364 	DBusMessageIter *iter, DBusError *error, void *user_data)
2365 {
2366 	struct wpa_supplicant *wpa_s = user_data;
2367 	u16 op_freq;
2368 	u8 role = wpas_get_p2p_role(wpa_s);
2369 
2370 	if (role == WPAS_P2P_ROLE_CLIENT) {
2371 		if (wpa_s->go_params == NULL)
2372 			return FALSE;
2373 		op_freq = wpa_s->go_params->freq;
2374 	} else {
2375 		if (wpa_s->ap_iface == NULL)
2376 			return FALSE;
2377 		op_freq = wpa_s->ap_iface->freq;
2378 	}
2379 
2380 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
2381 						&op_freq, error);
2382 }
2383 
2384 
2385 dbus_bool_t wpas_dbus_getter_p2p_group_passphrase(
2386 	const struct wpa_dbus_property_desc *property_desc,
2387 	DBusMessageIter *iter, DBusError *error, void *user_data)
2388 {
2389 	struct wpa_supplicant *wpa_s = user_data;
2390 	struct wpa_ssid *ssid = wpa_s->current_ssid;
2391 
2392 	if (ssid == NULL)
2393 		return FALSE;
2394 
2395 	return wpas_dbus_string_property_getter(iter, ssid->passphrase, error);
2396 }
2397 
2398 
2399 dbus_bool_t wpas_dbus_getter_p2p_group_psk(
2400 	const struct wpa_dbus_property_desc *property_desc,
2401 	DBusMessageIter *iter, DBusError *error, void *user_data)
2402 {
2403 	struct wpa_supplicant *wpa_s = user_data;
2404 	u8 *p_psk = NULL;
2405 	u8 psk_len = 0;
2406 	struct wpa_ssid *ssid = wpa_s->current_ssid;
2407 
2408 	if (ssid == NULL)
2409 		return FALSE;
2410 
2411 	if (ssid->psk_set) {
2412 		p_psk = ssid->psk;
2413 		psk_len = sizeof(ssid->psk);
2414 	}
2415 
2416 	return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
2417 						      p_psk, psk_len, error);
2418 }
2419 
2420 
2421 dbus_bool_t wpas_dbus_getter_p2p_group_vendor_ext(
2422 	const struct wpa_dbus_property_desc *property_desc,
2423 	DBusMessageIter *iter, DBusError *error, void *user_data)
2424 {
2425 	struct wpa_supplicant *wpa_s = user_data;
2426 	struct hostapd_data *hapd;
2427 	struct wpabuf *vendor_ext[MAX_WPS_VENDOR_EXTENSIONS];
2428 	unsigned int i, num_vendor_ext = 0;
2429 
2430 	os_memset(vendor_ext, 0, sizeof(vendor_ext));
2431 
2432 	/* Verify correct role for this property */
2433 	if (wpas_get_p2p_role(wpa_s) == WPAS_P2P_ROLE_GO) {
2434 		if (wpa_s->ap_iface == NULL)
2435 			return FALSE;
2436 		hapd = wpa_s->ap_iface->bss[0];
2437 
2438 		/* Parse WPS Vendor Extensions sent in Beacon/Probe Response */
2439 		for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
2440 			if (hapd->conf->wps_vendor_ext[i] == NULL)
2441 				continue;
2442 			vendor_ext[num_vendor_ext++] =
2443 				hapd->conf->wps_vendor_ext[i];
2444 		}
2445 	}
2446 
2447 	/* Return vendor extensions or no data */
2448 	return wpas_dbus_simple_array_array_property_getter(iter,
2449 							    DBUS_TYPE_BYTE,
2450 							    vendor_ext,
2451 							    num_vendor_ext,
2452 							    error);
2453 }
2454 
2455 
2456 dbus_bool_t wpas_dbus_setter_p2p_group_vendor_ext(
2457 	const struct wpa_dbus_property_desc *property_desc,
2458 	DBusMessageIter *iter, DBusError *error, void *user_data)
2459 {
2460 	struct wpa_supplicant *wpa_s = user_data;
2461 	DBusMessageIter variant_iter, iter_dict, array_iter, sub;
2462 	struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
2463 	unsigned int i;
2464 	struct hostapd_data *hapd = NULL;
2465 
2466 	if (wpas_get_p2p_role(wpa_s) == WPAS_P2P_ROLE_GO &&
2467 	    wpa_s->ap_iface != NULL)
2468 		hapd = wpa_s->ap_iface->bss[0];
2469 	else
2470 		return FALSE;
2471 
2472 	dbus_message_iter_recurse(iter, &variant_iter);
2473 	if (dbus_message_iter_get_arg_type(&variant_iter) != DBUS_TYPE_ARRAY)
2474 		return FALSE;
2475 
2476 	/*
2477 	 * This is supposed to be array of bytearrays (aay), but the earlier
2478 	 * implementation used a dict with "WPSVendorExtensions" as the key in
2479 	 * this setter function which does not match the format used by the
2480 	 * getter function. For backwards compatibility, allow both formats to
2481 	 * be used in the setter.
2482 	 */
2483 	if (dbus_message_iter_get_element_type(&variant_iter) ==
2484 	    DBUS_TYPE_ARRAY) {
2485 		/* This is the proper format matching the getter */
2486 		struct wpabuf *vals[MAX_WPS_VENDOR_EXTENSIONS];
2487 
2488 		dbus_message_iter_recurse(&variant_iter, &array_iter);
2489 
2490 		if (dbus_message_iter_get_arg_type(&array_iter) !=
2491 		    DBUS_TYPE_ARRAY ||
2492 		    dbus_message_iter_get_element_type(&array_iter) !=
2493 		    DBUS_TYPE_BYTE) {
2494 			wpa_printf(MSG_DEBUG,
2495 				   "dbus: Not an array of array of bytes");
2496 			return FALSE;
2497 		}
2498 
2499 		i = 0;
2500 		os_memset(vals, 0, sizeof(vals));
2501 
2502 		while (dbus_message_iter_get_arg_type(&array_iter) ==
2503 		       DBUS_TYPE_ARRAY) {
2504 			char *val;
2505 			int len;
2506 
2507 			if (i == MAX_WPS_VENDOR_EXTENSIONS) {
2508 				wpa_printf(MSG_DEBUG,
2509 					   "dbus: Too many WPSVendorExtensions values");
2510 				i = MAX_WPS_VENDOR_EXTENSIONS + 1;
2511 				break;
2512 			}
2513 
2514 			dbus_message_iter_recurse(&array_iter, &sub);
2515 			dbus_message_iter_get_fixed_array(&sub, &val, &len);
2516 			wpa_hexdump(MSG_DEBUG, "dbus: WPSVendorExtentions[]",
2517 				    val, len);
2518 			vals[i] = wpabuf_alloc_copy(val, len);
2519 			if (vals[i] == NULL) {
2520 				i = MAX_WPS_VENDOR_EXTENSIONS + 1;
2521 				break;
2522 			}
2523 			i++;
2524 			dbus_message_iter_next(&array_iter);
2525 		}
2526 
2527 		if (i > MAX_WPS_VENDOR_EXTENSIONS) {
2528 			for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++)
2529 				wpabuf_free(vals[i]);
2530 			return FALSE;
2531 		}
2532 
2533 		for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
2534 			wpabuf_free(hapd->conf->wps_vendor_ext[i]);
2535 			hapd->conf->wps_vendor_ext[i] = vals[i];
2536 		}
2537 
2538 		hostapd_update_wps(hapd);
2539 
2540 		return TRUE;
2541 	}
2542 
2543 	if (dbus_message_iter_get_element_type(&variant_iter) !=
2544 	    DBUS_TYPE_DICT_ENTRY)
2545 		return FALSE;
2546 
2547 	wpa_printf(MSG_DEBUG,
2548 		   "dbus: Try to use backwards compatibility version of WPSVendorExtensions setter");
2549 	if (!wpa_dbus_dict_open_read(&variant_iter, &iter_dict, error))
2550 		return FALSE;
2551 
2552 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2553 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) {
2554 			dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
2555 					     "invalid message format");
2556 			return FALSE;
2557 		}
2558 
2559 		if (os_strcmp(entry.key, "WPSVendorExtensions") == 0) {
2560 			if (entry.type != DBUS_TYPE_ARRAY ||
2561 			    entry.array_type != WPAS_DBUS_TYPE_BINARRAY ||
2562 			    entry.array_len > MAX_WPS_VENDOR_EXTENSIONS)
2563 				goto error;
2564 
2565 			for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
2566 				wpabuf_free(hapd->conf->wps_vendor_ext[i]);
2567 				if (i < entry.array_len) {
2568 					hapd->conf->wps_vendor_ext[i] =
2569 						entry.binarray_value[i];
2570 					entry.binarray_value[i] = NULL;
2571 				} else
2572 					hapd->conf->wps_vendor_ext[i] = NULL;
2573 			}
2574 
2575 			hostapd_update_wps(hapd);
2576 		} else
2577 			goto error;
2578 
2579 		wpa_dbus_dict_entry_clear(&entry);
2580 	}
2581 
2582 	return TRUE;
2583 
2584 error:
2585 	wpa_dbus_dict_entry_clear(&entry);
2586 	dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
2587 			     "invalid message format");
2588 	return FALSE;
2589 }
2590 
2591 
2592 DBusMessage * wpas_dbus_handler_p2p_add_service(DBusMessage *message,
2593 						struct wpa_supplicant *wpa_s)
2594 {
2595 	DBusMessageIter iter_dict;
2596 	DBusMessage *reply = NULL;
2597 	DBusMessageIter iter;
2598 	struct wpa_dbus_dict_entry entry;
2599 	int upnp = 0;
2600 	int bonjour = 0;
2601 	char *service = NULL;
2602 	struct wpabuf *query = NULL;
2603 	struct wpabuf *resp = NULL;
2604 	u8 version = 0;
2605 
2606 	dbus_message_iter_init(message, &iter);
2607 
2608 	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
2609 		goto error;
2610 
2611 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2612 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2613 			goto error;
2614 
2615 		if (os_strcmp(entry.key, "service_type") == 0 &&
2616 		    entry.type == DBUS_TYPE_STRING) {
2617 			if (os_strcmp(entry.str_value, "upnp") == 0)
2618 				upnp = 1;
2619 			else if (os_strcmp(entry.str_value, "bonjour") == 0)
2620 				bonjour = 1;
2621 			else
2622 				goto error_clear;
2623 		} else if (os_strcmp(entry.key, "version") == 0 &&
2624 			   entry.type == DBUS_TYPE_INT32) {
2625 			version = entry.uint32_value;
2626 		} else if (os_strcmp(entry.key, "service") == 0 &&
2627 			   entry.type == DBUS_TYPE_STRING) {
2628 			os_free(service);
2629 			service = os_strdup(entry.str_value);
2630 		} else if (os_strcmp(entry.key, "query") == 0) {
2631 			if (entry.type != DBUS_TYPE_ARRAY ||
2632 			    entry.array_type != DBUS_TYPE_BYTE)
2633 				goto error_clear;
2634 			query = wpabuf_alloc_copy(
2635 				entry.bytearray_value,
2636 				entry.array_len);
2637 		} else if (os_strcmp(entry.key, "response") == 0) {
2638 			if (entry.type != DBUS_TYPE_ARRAY ||
2639 			    entry.array_type != DBUS_TYPE_BYTE)
2640 				goto error_clear;
2641 			resp = wpabuf_alloc_copy(entry.bytearray_value,
2642 						 entry.array_len);
2643 		}
2644 		wpa_dbus_dict_entry_clear(&entry);
2645 	}
2646 
2647 	if (upnp == 1) {
2648 		if (version <= 0 || service == NULL)
2649 			goto error;
2650 
2651 		if (wpas_p2p_service_add_upnp(wpa_s, version, service) != 0)
2652 			goto error;
2653 
2654 	} else if (bonjour == 1) {
2655 		if (query == NULL || resp == NULL)
2656 			goto error;
2657 
2658 		if (wpas_p2p_service_add_bonjour(wpa_s, query, resp) < 0)
2659 			goto error;
2660 		query = NULL;
2661 		resp = NULL;
2662 	} else
2663 		goto error;
2664 
2665 	os_free(service);
2666 	return reply;
2667 error_clear:
2668 	wpa_dbus_dict_entry_clear(&entry);
2669 error:
2670 	os_free(service);
2671 	wpabuf_free(query);
2672 	wpabuf_free(resp);
2673 	return wpas_dbus_error_invalid_args(message, NULL);
2674 }
2675 
2676 
2677 DBusMessage * wpas_dbus_handler_p2p_delete_service(
2678 	DBusMessage *message, struct wpa_supplicant *wpa_s)
2679 {
2680 	DBusMessageIter iter_dict;
2681 	DBusMessage *reply = NULL;
2682 	DBusMessageIter iter;
2683 	struct wpa_dbus_dict_entry entry;
2684 	int upnp = 0;
2685 	int bonjour = 0;
2686 	int ret = 0;
2687 	char *service = NULL;
2688 	struct wpabuf *query = NULL;
2689 	u8 version = 0;
2690 
2691 	dbus_message_iter_init(message, &iter);
2692 
2693 	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
2694 		goto error;
2695 
2696 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2697 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2698 			goto error;
2699 
2700 		if (os_strcmp(entry.key, "service_type") == 0 &&
2701 		    entry.type == DBUS_TYPE_STRING) {
2702 			if (os_strcmp(entry.str_value, "upnp") == 0)
2703 				upnp = 1;
2704 			else if (os_strcmp(entry.str_value, "bonjour") == 0)
2705 				bonjour = 1;
2706 			else
2707 				goto error_clear;
2708 		} else if (os_strcmp(entry.key, "version") == 0 &&
2709 			   entry.type == DBUS_TYPE_INT32) {
2710 			version = entry.uint32_value;
2711 		} else if (os_strcmp(entry.key, "service") == 0 &&
2712 			   entry.type == DBUS_TYPE_STRING) {
2713 			os_free(service);
2714 			service = os_strdup(entry.str_value);
2715 		} else if (os_strcmp(entry.key, "query") == 0) {
2716 			if (entry.type != DBUS_TYPE_ARRAY ||
2717 			    entry.array_type != DBUS_TYPE_BYTE)
2718 				goto error_clear;
2719 			wpabuf_free(query);
2720 			query = wpabuf_alloc_copy(entry.bytearray_value,
2721 						  entry.array_len);
2722 		} else {
2723 			goto error_clear;
2724 		}
2725 
2726 		wpa_dbus_dict_entry_clear(&entry);
2727 	}
2728 	if (upnp == 1) {
2729 		if (version <= 0 || service == NULL)
2730 			goto error;
2731 
2732 		ret = wpas_p2p_service_del_upnp(wpa_s, version, service);
2733 		if (ret != 0)
2734 			goto error;
2735 	} else if (bonjour == 1) {
2736 		if (query == NULL)
2737 			goto error;
2738 
2739 		ret = wpas_p2p_service_del_bonjour(wpa_s, query);
2740 		if (ret != 0)
2741 			goto error;
2742 	} else
2743 		goto error;
2744 
2745 	wpabuf_free(query);
2746 	os_free(service);
2747 	return reply;
2748 error_clear:
2749 	wpa_dbus_dict_entry_clear(&entry);
2750 error:
2751 	wpabuf_free(query);
2752 	os_free(service);
2753 	return wpas_dbus_error_invalid_args(message, NULL);
2754 }
2755 
2756 
2757 DBusMessage * wpas_dbus_handler_p2p_flush_service(DBusMessage *message,
2758 						  struct wpa_supplicant *wpa_s)
2759 {
2760 	wpas_p2p_service_flush(wpa_s);
2761 	return NULL;
2762 }
2763 
2764 
2765 DBusMessage * wpas_dbus_handler_p2p_service_sd_req(
2766 	DBusMessage *message, struct wpa_supplicant *wpa_s)
2767 {
2768 	DBusMessageIter iter_dict;
2769 	DBusMessage *reply = NULL;
2770 	DBusMessageIter iter;
2771 	struct wpa_dbus_dict_entry entry;
2772 	int upnp = 0;
2773 	char *service = NULL;
2774 	char *peer_object_path = NULL;
2775 	struct wpabuf *tlv = NULL;
2776 	u8 version = 0;
2777 	u64 ref = 0;
2778 	u8 addr_buf[ETH_ALEN], *addr;
2779 
2780 	dbus_message_iter_init(message, &iter);
2781 
2782 	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
2783 		goto error;
2784 
2785 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2786 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2787 			goto error;
2788 		if (os_strcmp(entry.key, "peer_object") == 0 &&
2789 		    entry.type == DBUS_TYPE_OBJECT_PATH) {
2790 			peer_object_path = os_strdup(entry.str_value);
2791 		} else if (os_strcmp(entry.key, "service_type") == 0 &&
2792 			   entry.type == DBUS_TYPE_STRING) {
2793 			if (os_strcmp(entry.str_value, "upnp") == 0)
2794 				upnp = 1;
2795 			else
2796 				goto error_clear;
2797 		} else if (os_strcmp(entry.key, "version") == 0 &&
2798 			   entry.type == DBUS_TYPE_INT32) {
2799 			version = entry.uint32_value;
2800 		} else if (os_strcmp(entry.key, "service") == 0 &&
2801 			   entry.type == DBUS_TYPE_STRING) {
2802 			service = os_strdup(entry.str_value);
2803 		} else if (os_strcmp(entry.key, "tlv") == 0) {
2804 			if (entry.type != DBUS_TYPE_ARRAY ||
2805 			    entry.array_type != DBUS_TYPE_BYTE)
2806 				goto error_clear;
2807 			tlv = wpabuf_alloc_copy(entry.bytearray_value,
2808 						entry.array_len);
2809 		} else
2810 			goto error_clear;
2811 
2812 		wpa_dbus_dict_entry_clear(&entry);
2813 	}
2814 
2815 	if (!peer_object_path) {
2816 		addr = NULL;
2817 	} else {
2818 		if (parse_peer_object_path(peer_object_path, addr_buf) < 0 ||
2819 		    !p2p_peer_known(wpa_s->global->p2p, addr_buf))
2820 			goto error;
2821 
2822 		addr = addr_buf;
2823 	}
2824 
2825 	if (upnp == 1) {
2826 		if (version <= 0 || service == NULL)
2827 			goto error;
2828 
2829 		ref = wpas_p2p_sd_request_upnp(wpa_s, addr, version, service);
2830 	} else {
2831 		if (tlv == NULL)
2832 			goto error;
2833 		ref = wpas_p2p_sd_request(wpa_s, addr, tlv);
2834 		wpabuf_free(tlv);
2835 	}
2836 
2837 	if (ref != 0) {
2838 		reply = dbus_message_new_method_return(message);
2839 		dbus_message_append_args(reply, DBUS_TYPE_UINT64,
2840 					 &ref, DBUS_TYPE_INVALID);
2841 	} else {
2842 		reply = wpas_dbus_error_unknown_error(
2843 			message, "Unable to send SD request");
2844 	}
2845 out:
2846 	os_free(service);
2847 	os_free(peer_object_path);
2848 	return reply;
2849 error_clear:
2850 	wpa_dbus_dict_entry_clear(&entry);
2851 error:
2852 	if (tlv)
2853 		wpabuf_free(tlv);
2854 	reply = wpas_dbus_error_invalid_args(message, NULL);
2855 	goto out;
2856 }
2857 
2858 
2859 DBusMessage * wpas_dbus_handler_p2p_service_sd_res(
2860 	DBusMessage *message, struct wpa_supplicant *wpa_s)
2861 {
2862 	DBusMessageIter iter_dict;
2863 	DBusMessage *reply = NULL;
2864 	DBusMessageIter iter;
2865 	struct wpa_dbus_dict_entry entry;
2866 	char *peer_object_path = NULL;
2867 	struct wpabuf *tlv = NULL;
2868 	int freq = 0;
2869 	int dlg_tok = 0;
2870 	u8 addr[ETH_ALEN];
2871 
2872 	dbus_message_iter_init(message, &iter);
2873 
2874 	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
2875 		goto error;
2876 
2877 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2878 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2879 			goto error;
2880 
2881 		if (os_strcmp(entry.key, "peer_object") == 0 &&
2882 		    entry.type == DBUS_TYPE_OBJECT_PATH) {
2883 			peer_object_path = os_strdup(entry.str_value);
2884 		} else if (os_strcmp(entry.key, "frequency") == 0 &&
2885 			   entry.type == DBUS_TYPE_INT32) {
2886 			freq = entry.uint32_value;
2887 		} else if (os_strcmp(entry.key, "dialog_token") == 0 &&
2888 			   (entry.type == DBUS_TYPE_UINT32 ||
2889 			    entry.type == DBUS_TYPE_INT32)) {
2890 			dlg_tok = entry.uint32_value;
2891 		} else if (os_strcmp(entry.key, "tlvs") == 0) {
2892 			if (entry.type != DBUS_TYPE_ARRAY ||
2893 			    entry.array_type != DBUS_TYPE_BYTE)
2894 				goto error_clear;
2895 			tlv = wpabuf_alloc_copy(entry.bytearray_value,
2896 						entry.array_len);
2897 		} else
2898 			goto error_clear;
2899 
2900 		wpa_dbus_dict_entry_clear(&entry);
2901 	}
2902 	if (parse_peer_object_path(peer_object_path, addr) < 0 ||
2903 	    !p2p_peer_known(wpa_s->global->p2p, addr) ||
2904 	    tlv == NULL)
2905 		goto error;
2906 
2907 	wpas_p2p_sd_response(wpa_s, freq, addr, (u8) dlg_tok, tlv);
2908 	wpabuf_free(tlv);
2909 out:
2910 	os_free(peer_object_path);
2911 	return reply;
2912 error_clear:
2913 	wpa_dbus_dict_entry_clear(&entry);
2914 error:
2915 	reply = wpas_dbus_error_invalid_args(message, NULL);
2916 	goto out;
2917 }
2918 
2919 
2920 DBusMessage * wpas_dbus_handler_p2p_service_sd_cancel_req(
2921 	DBusMessage *message, struct wpa_supplicant *wpa_s)
2922 {
2923 	DBusMessageIter iter;
2924 	u64 req = 0;
2925 
2926 	dbus_message_iter_init(message, &iter);
2927 	dbus_message_iter_get_basic(&iter, &req);
2928 
2929 	if (req == 0)
2930 		goto error;
2931 
2932 	if (wpas_p2p_sd_cancel_request(wpa_s, req) < 0)
2933 		goto error;
2934 
2935 	return NULL;
2936 error:
2937 	return wpas_dbus_error_invalid_args(message, NULL);
2938 }
2939 
2940 
2941 DBusMessage * wpas_dbus_handler_p2p_service_update(
2942 	DBusMessage *message, struct wpa_supplicant *wpa_s)
2943 {
2944 	wpas_p2p_sd_service_update(wpa_s);
2945 	return NULL;
2946 }
2947 
2948 
2949 DBusMessage * wpas_dbus_handler_p2p_serv_disc_external(
2950 	DBusMessage *message, struct wpa_supplicant *wpa_s)
2951 {
2952 	DBusMessageIter iter;
2953 	int ext = 0;
2954 
2955 	dbus_message_iter_init(message, &iter);
2956 	dbus_message_iter_get_basic(&iter, &ext);
2957 
2958 	wpa_s->p2p_sd_over_ctrl_iface = ext;
2959 
2960 	return NULL;
2961 
2962 }
2963 
2964 
2965 #ifdef CONFIG_WIFI_DISPLAY
2966 
2967 dbus_bool_t wpas_dbus_getter_global_wfd_ies(
2968 	const struct wpa_dbus_property_desc *property_desc,
2969 	DBusMessageIter *iter, DBusError *error, void *user_data)
2970 {
2971 	struct wpa_global *global = user_data;
2972 	struct wpabuf *ie;
2973 	dbus_bool_t ret;
2974 
2975 	ie = wifi_display_get_wfd_ie(global);
2976 	if (ie == NULL)
2977 		return wpas_dbus_simple_array_property_getter(iter,
2978 							      DBUS_TYPE_BYTE,
2979 							      NULL, 0, error);
2980 
2981 	ret = wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
2982 						     wpabuf_head(ie),
2983 						     wpabuf_len(ie), error);
2984 	wpabuf_free(ie);
2985 
2986 	return ret;
2987 }
2988 
2989 
2990 dbus_bool_t wpas_dbus_setter_global_wfd_ies(
2991 	const struct wpa_dbus_property_desc *property_desc,
2992 	DBusMessageIter *iter, DBusError *error, void *user_data)
2993 {
2994 	struct wpa_global *global = user_data;
2995 	DBusMessageIter variant, array;
2996 	struct wpabuf *ie = NULL;
2997 	const u8 *data;
2998 	int len;
2999 
3000 	if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_VARIANT)
3001 		goto err;
3002 
3003 	dbus_message_iter_recurse(iter, &variant);
3004 	if (dbus_message_iter_get_arg_type(&variant) != DBUS_TYPE_ARRAY)
3005 		goto err;
3006 
3007 	dbus_message_iter_recurse(&variant, &array);
3008 	dbus_message_iter_get_fixed_array(&array, &data, &len);
3009 	if (len == 0) {
3010 		wifi_display_enable(global, 0);
3011 		wifi_display_deinit(global);
3012 
3013 		return TRUE;
3014 	}
3015 
3016 	ie = wpabuf_alloc(len);
3017 	if (ie == NULL)
3018 		goto err;
3019 
3020 	wpabuf_put_data(ie, data, len);
3021 	if (wifi_display_subelem_set_from_ies(global, ie) != 0)
3022 		goto err;
3023 
3024 	if (global->wifi_display == 0)
3025 		wifi_display_enable(global, 1);
3026 
3027 	wpabuf_free(ie);
3028 
3029 	return TRUE;
3030 err:
3031 	wpabuf_free(ie);
3032 
3033 	dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
3034 			     "invalid message format");
3035 	return FALSE;
3036 }
3037 
3038 #endif /* CONFIG_WIFI_DISPLAY */
3039