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