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