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