• 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 
30 /**
31  * Parses out the mac address from the peer object path.
32  * @peer_path - object path of the form
33  *	/fi/w1/wpa_supplicant1/Interfaces/n/Peers/00112233445566 (no colons)
34  * @addr - out param must be of ETH_ALEN size
35  * Returns 0 if valid (including MAC), -1 otherwise
36  */
parse_peer_object_path(char * peer_path,u8 addr[ETH_ALEN])37 static int parse_peer_object_path(char *peer_path, u8 addr[ETH_ALEN])
38 {
39 	char *p;
40 
41 	if (!peer_path)
42 		return -1;
43 	p = os_strrchr(peer_path, '/');
44 	if (!p)
45 		return -1;
46 	p++;
47 	return hwaddr_compact_aton(p, addr);
48 }
49 
50 
51 /**
52  * wpas_dbus_error_persistent_group_unknown - Return a new PersistentGroupUnknown
53  * error message
54  * @message: Pointer to incoming dbus message this error refers to
55  * Returns: a dbus error message
56  *
57  * Convenience function to create and return an invalid persistent group error.
58  */
wpas_dbus_error_persistent_group_unknown(DBusMessage * message)59 static DBusMessage * wpas_dbus_error_persistent_group_unknown(
60 	DBusMessage *message)
61 {
62 	return dbus_message_new_error(message, WPAS_DBUS_ERROR_NETWORK_UNKNOWN,
63 				      "There is no such persistent group in "
64 				      "this P2P device.");
65 }
66 
67 
wpas_dbus_handler_p2p_find(DBusMessage * message,struct wpa_supplicant * wpa_s)68 DBusMessage * wpas_dbus_handler_p2p_find(DBusMessage *message,
69 					 struct wpa_supplicant *wpa_s)
70 {
71 	struct wpa_dbus_dict_entry entry;
72 	DBusMessage *reply = NULL;
73 	DBusMessageIter iter;
74 	DBusMessageIter iter_dict;
75 	unsigned int timeout = 0;
76 	enum p2p_discovery_type type = P2P_FIND_ONLY_SOCIAL;
77 	int num_req_dev_types = 0;
78 	unsigned int i;
79 	u8 *req_dev_types = NULL;
80 
81 	dbus_message_iter_init(message, &iter);
82 	entry.key = NULL;
83 
84 	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
85 		goto error;
86 
87 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
88 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
89 			goto error;
90 
91 		if (!os_strcmp(entry.key, "Timeout") &&
92 		    (entry.type == DBUS_TYPE_INT32)) {
93 			timeout = entry.uint32_value;
94 		} else if (os_strcmp(entry.key, "RequestedDeviceTypes") == 0) {
95 			if ((entry.type != DBUS_TYPE_ARRAY) ||
96 			    (entry.array_type != WPAS_DBUS_TYPE_BINARRAY))
97 				goto error_clear;
98 
99 			os_free(req_dev_types);
100 			req_dev_types =
101 				os_malloc(WPS_DEV_TYPE_LEN * entry.array_len);
102 			if (!req_dev_types)
103 				goto error_clear;
104 
105 			for (i = 0; i < entry.array_len; i++) {
106 				if (wpabuf_len(entry.binarray_value[i]) !=
107 							WPS_DEV_TYPE_LEN)
108 					goto error_clear;
109 				os_memcpy(req_dev_types + i * WPS_DEV_TYPE_LEN,
110 					  wpabuf_head(entry.binarray_value[i]),
111 					  WPS_DEV_TYPE_LEN);
112 			}
113 			num_req_dev_types = entry.array_len;
114 		} else if (!os_strcmp(entry.key, "DiscoveryType") &&
115 			   (entry.type == DBUS_TYPE_STRING)) {
116 			if (!os_strcmp(entry.str_value, "start_with_full"))
117 				type = P2P_FIND_START_WITH_FULL;
118 			else if (!os_strcmp(entry.str_value, "social"))
119 				type = P2P_FIND_ONLY_SOCIAL;
120 			else if (!os_strcmp(entry.str_value, "progressive"))
121 				type = P2P_FIND_PROGRESSIVE;
122 			else
123 				goto error_clear;
124 		} else
125 			goto error_clear;
126 		wpa_dbus_dict_entry_clear(&entry);
127 	}
128 
129 	wpas_p2p_find(wpa_s, timeout, type, num_req_dev_types, req_dev_types,
130 		      NULL, 0);
131 	os_free(req_dev_types);
132 	return reply;
133 
134 error_clear:
135 	wpa_dbus_dict_entry_clear(&entry);
136 error:
137 	os_free(req_dev_types);
138 	reply = wpas_dbus_error_invalid_args(message, entry.key);
139 	return reply;
140 }
141 
142 
wpas_dbus_handler_p2p_stop_find(DBusMessage * message,struct wpa_supplicant * wpa_s)143 DBusMessage * wpas_dbus_handler_p2p_stop_find(DBusMessage *message,
144 					      struct wpa_supplicant *wpa_s)
145 {
146 	wpas_p2p_stop_find(wpa_s);
147 	return NULL;
148 }
149 
150 
wpas_dbus_handler_p2p_rejectpeer(DBusMessage * message,struct wpa_supplicant * wpa_s)151 DBusMessage * wpas_dbus_handler_p2p_rejectpeer(DBusMessage *message,
152 					       struct wpa_supplicant *wpa_s)
153 {
154 	DBusMessageIter iter;
155 	char *peer_object_path = NULL;
156 	u8 peer_addr[ETH_ALEN];
157 
158 	dbus_message_iter_init(message, &iter);
159 	dbus_message_iter_get_basic(&iter, &peer_object_path);
160 
161 	if (parse_peer_object_path(peer_object_path, peer_addr) < 0)
162 		return wpas_dbus_error_invalid_args(message, NULL);
163 
164 	if (wpas_p2p_reject(wpa_s, peer_addr) < 0)
165 		return wpas_dbus_error_unknown_error(message,
166 				"Failed to call wpas_p2p_reject method.");
167 
168 	return NULL;
169 }
170 
171 
wpas_dbus_handler_p2p_listen(DBusMessage * message,struct wpa_supplicant * wpa_s)172 DBusMessage * wpas_dbus_handler_p2p_listen(DBusMessage *message,
173 					   struct wpa_supplicant *wpa_s)
174 {
175 	dbus_int32_t timeout = 0;
176 
177 	if (!dbus_message_get_args(message, NULL, DBUS_TYPE_INT32, &timeout,
178 				   DBUS_TYPE_INVALID))
179 		return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
180 					      NULL);
181 
182 	if (wpas_p2p_listen(wpa_s, (unsigned int)timeout))
183 		return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
184 					      NULL);
185 
186 	return NULL;
187 }
188 
189 
wpas_dbus_handler_p2p_extendedlisten(DBusMessage * message,struct wpa_supplicant * wpa_s)190 DBusMessage * wpas_dbus_handler_p2p_extendedlisten(
191 	DBusMessage *message, struct wpa_supplicant *wpa_s)
192 {
193 	unsigned int period = 0, interval = 0;
194 	struct wpa_dbus_dict_entry entry;
195 	DBusMessageIter iter;
196 	DBusMessageIter iter_dict;
197 
198 	dbus_message_iter_init(message, &iter);
199 	entry.key = NULL;
200 
201 	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
202 		goto error;
203 
204 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
205 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
206 			goto error;
207 
208 		if (!os_strcmp(entry.key, "period") &&
209 		    (entry.type == DBUS_TYPE_INT32))
210 			period = entry.uint32_value;
211 		else if (!os_strcmp(entry.key, "interval") &&
212 			 (entry.type == DBUS_TYPE_INT32))
213 			interval = entry.uint32_value;
214 		else
215 			goto error_clear;
216 		wpa_dbus_dict_entry_clear(&entry);
217 	}
218 
219 	if (wpas_p2p_ext_listen(wpa_s, period, interval))
220 		return wpas_dbus_error_unknown_error(
221 			message, "failed to initiate a p2p_ext_listen.");
222 
223 	return NULL;
224 
225 error_clear:
226 	wpa_dbus_dict_entry_clear(&entry);
227 error:
228 	return wpas_dbus_error_invalid_args(message, entry.key);
229 }
230 
231 
wpas_dbus_handler_p2p_presence_request(DBusMessage * message,struct wpa_supplicant * wpa_s)232 DBusMessage * wpas_dbus_handler_p2p_presence_request(
233 	DBusMessage *message, struct wpa_supplicant *wpa_s)
234 {
235 	unsigned int dur1 = 0, int1 = 0, dur2 = 0, int2 = 0;
236 	struct wpa_dbus_dict_entry entry;
237 	DBusMessageIter iter;
238 	DBusMessageIter iter_dict;
239 
240 	dbus_message_iter_init(message, &iter);
241 	entry.key = NULL;
242 
243 	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
244 		goto error;
245 
246 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
247 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
248 			goto error;
249 
250 		if (!os_strcmp(entry.key, "duration1") &&
251 		    (entry.type == DBUS_TYPE_INT32))
252 			dur1 = entry.uint32_value;
253 		else if (!os_strcmp(entry.key, "interval1") &&
254 			 entry.type == DBUS_TYPE_INT32)
255 			int1 = entry.uint32_value;
256 		else if (!os_strcmp(entry.key, "duration2") &&
257 			 entry.type == DBUS_TYPE_INT32)
258 			dur2 = entry.uint32_value;
259 		else if (!os_strcmp(entry.key, "interval2") &&
260 			 entry.type == DBUS_TYPE_INT32)
261 			int2 = entry.uint32_value;
262 		else
263 			goto error_clear;
264 
265 		wpa_dbus_dict_entry_clear(&entry);
266 	}
267 	if (wpas_p2p_presence_req(wpa_s, dur1, int1, dur2, int2) < 0)
268 		return wpas_dbus_error_unknown_error(message,
269 				"Failed to invoke presence request.");
270 
271 	return NULL;
272 
273 error_clear:
274 	wpa_dbus_dict_entry_clear(&entry);
275 error:
276 	return wpas_dbus_error_invalid_args(message, entry.key);
277 }
278 
279 
wpas_dbus_handler_p2p_group_add(DBusMessage * message,struct wpa_supplicant * wpa_s)280 DBusMessage * wpas_dbus_handler_p2p_group_add(DBusMessage *message,
281 					      struct wpa_supplicant *wpa_s)
282 {
283 	DBusMessageIter iter_dict;
284 	DBusMessage *reply = NULL;
285 	DBusMessageIter iter;
286 	struct wpa_dbus_dict_entry entry;
287 	char *pg_object_path = NULL;
288 	int persistent_group = 0;
289 	int freq = 0;
290 	char *iface = NULL;
291 	char *net_id_str = NULL;
292 	unsigned int group_id = 0;
293 	struct wpa_ssid *ssid;
294 
295 	dbus_message_iter_init(message, &iter);
296 
297 	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
298 		goto inv_args;
299 
300 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
301 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
302 			goto inv_args;
303 
304 		if (!os_strcmp(entry.key, "persistent") &&
305 		    (entry.type == DBUS_TYPE_BOOLEAN)) {
306 			persistent_group = (entry.bool_value == TRUE) ? 1 : 0;
307 		} else if (!os_strcmp(entry.key, "frequency") &&
308 			   (entry.type == DBUS_TYPE_INT32)) {
309 			freq = entry.int32_value;
310 			if (freq <= 0)
311 				goto inv_args_clear;
312 		} else if (!os_strcmp(entry.key, "persistent_group_object") &&
313 			   entry.type == DBUS_TYPE_OBJECT_PATH)
314 			pg_object_path = os_strdup(entry.str_value);
315 		else
316 			goto inv_args_clear;
317 
318 		wpa_dbus_dict_entry_clear(&entry);
319 	}
320 
321 	if (pg_object_path != NULL) {
322 		/*
323 		 * A persistent group Object Path is defined meaning we want
324 		 * to re-invoke a persistent group.
325 		 */
326 
327 		iface = wpas_dbus_new_decompose_object_path(pg_object_path, 1,
328 							    &net_id_str, NULL);
329 		if (iface == NULL ||
330 		    os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
331 			reply =
332 			    wpas_dbus_error_invalid_args(message,
333 							 pg_object_path);
334 			goto out;
335 		}
336 
337 		group_id = strtoul(net_id_str, NULL, 10);
338 		if (errno == EINVAL) {
339 			reply = wpas_dbus_error_invalid_args(
340 						message, pg_object_path);
341 			goto out;
342 		}
343 
344 		/* Get the SSID structure from the persistent group id */
345 		ssid = wpa_config_get_network(wpa_s->conf, group_id);
346 		if (ssid == NULL || ssid->disabled != 2)
347 			goto inv_args;
348 
349 		if (wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 0)) {
350 			reply = wpas_dbus_error_unknown_error(
351 				message,
352 				"Failed to reinvoke a persistent group");
353 			goto out;
354 		}
355 	} else if (wpas_p2p_group_add(wpa_s, persistent_group, freq, 0))
356 		goto inv_args;
357 
358 out:
359 	os_free(pg_object_path);
360 	os_free(net_id_str);
361 	os_free(iface);
362 	return reply;
363 inv_args_clear:
364 	wpa_dbus_dict_entry_clear(&entry);
365 inv_args:
366 	reply = wpas_dbus_error_invalid_args(message, NULL);
367 	goto out;
368 }
369 
370 
wpas_dbus_handler_p2p_disconnect(DBusMessage * message,struct wpa_supplicant * wpa_s)371 DBusMessage * wpas_dbus_handler_p2p_disconnect(DBusMessage *message,
372 					       struct wpa_supplicant *wpa_s)
373 {
374 	if (wpas_p2p_disconnect(wpa_s))
375 		return wpas_dbus_error_unknown_error(message,
376 						"failed to disconnect");
377 
378 	return NULL;
379 }
380 
381 
wpa_dbus_p2p_check_enabled(struct wpa_supplicant * wpa_s,DBusMessage * message,DBusMessage ** out_reply,DBusError * error)382 static dbus_bool_t wpa_dbus_p2p_check_enabled(struct wpa_supplicant *wpa_s,
383 					      DBusMessage *message,
384 					      DBusMessage **out_reply,
385 					      DBusError *error)
386 {
387 	/* Return an error message or an error if P2P isn't available */
388 	if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL) {
389 		if (out_reply) {
390 			*out_reply = dbus_message_new_error(
391 				message, DBUS_ERROR_FAILED,
392 				"P2P is not available for this interface");
393 		}
394 		dbus_set_error_const(error, DBUS_ERROR_FAILED,
395 				     "P2P is not available for this "
396 				     "interface");
397 		return FALSE;
398 	}
399 	return TRUE;
400 }
401 
402 
wpas_dbus_handler_p2p_flush(DBusMessage * message,struct wpa_supplicant * wpa_s)403 DBusMessage * wpas_dbus_handler_p2p_flush(DBusMessage *message,
404 					  struct wpa_supplicant *wpa_s)
405 {
406 	DBusMessage *reply = NULL;
407 
408 	if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL))
409 		return reply;
410 
411 	os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
412 	wpa_s->force_long_sd = 0;
413 	p2p_flush(wpa_s->global->p2p);
414 
415 	return NULL;
416 }
417 
418 
wpas_dbus_handler_p2p_connect(DBusMessage * message,struct wpa_supplicant * wpa_s)419 DBusMessage * wpas_dbus_handler_p2p_connect(DBusMessage *message,
420 					    struct wpa_supplicant *wpa_s)
421 {
422 	DBusMessageIter iter_dict;
423 	DBusMessage *reply = NULL;
424 	DBusMessageIter iter;
425 	struct wpa_dbus_dict_entry entry;
426 	char *peer_object_path = NULL;
427 	int persistent_group = 0;
428 	int join = 0;
429 	int authorize_only = 0;
430 	int go_intent = -1;
431 	int freq = 0;
432 	u8 addr[ETH_ALEN];
433 	char *pin = NULL;
434 	enum p2p_wps_method wps_method = WPS_NOT_READY;
435 	int new_pin;
436 	char *err_msg = NULL;
437 	char *iface = NULL;
438 
439 	if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL))
440 		return reply;
441 
442 	dbus_message_iter_init(message, &iter);
443 
444 	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
445 		goto inv_args;
446 
447 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
448 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
449 			goto inv_args;
450 
451 		if (!os_strcmp(entry.key, "peer") &&
452 		    (entry.type == DBUS_TYPE_OBJECT_PATH)) {
453 			peer_object_path = os_strdup(entry.str_value);
454 		} else if (!os_strcmp(entry.key, "persistent") &&
455 			   (entry.type == DBUS_TYPE_BOOLEAN)) {
456 			persistent_group = (entry.bool_value == TRUE) ? 1 : 0;
457 		} else if (!os_strcmp(entry.key, "join") &&
458 			   (entry.type == DBUS_TYPE_BOOLEAN)) {
459 			join = (entry.bool_value == TRUE) ? 1 : 0;
460 		} else if (!os_strcmp(entry.key, "authorize_only") &&
461 			   (entry.type == DBUS_TYPE_BOOLEAN)) {
462 			authorize_only = (entry.bool_value == TRUE) ? 1 : 0;
463 		} else if (!os_strcmp(entry.key, "frequency") &&
464 			   (entry.type == DBUS_TYPE_INT32)) {
465 			freq = entry.int32_value;
466 			if (freq <= 0)
467 				goto inv_args_clear;
468 		} else if (!os_strcmp(entry.key, "go_intent") &&
469 			   (entry.type == DBUS_TYPE_INT32)) {
470 			go_intent = entry.int32_value;
471 			if ((go_intent < 0) || (go_intent > 15))
472 				goto inv_args_clear;
473 		} else if (!os_strcmp(entry.key, "wps_method") &&
474 			   (entry.type == DBUS_TYPE_STRING)) {
475 			if (!os_strcmp(entry.str_value, "pbc"))
476 				wps_method = WPS_PBC;
477 			else if (!os_strcmp(entry.str_value, "pin"))
478 				wps_method = WPS_PIN_DISPLAY;
479 			else if (!os_strcmp(entry.str_value, "display"))
480 				wps_method = WPS_PIN_DISPLAY;
481 			else if (!os_strcmp(entry.str_value, "keypad"))
482 				wps_method = WPS_PIN_KEYPAD;
483 			else
484 				goto inv_args_clear;
485 		} else if (!os_strcmp(entry.key, "pin") &&
486 			   (entry.type == DBUS_TYPE_STRING)) {
487 			pin = os_strdup(entry.str_value);
488 		} else
489 			goto inv_args_clear;
490 
491 		wpa_dbus_dict_entry_clear(&entry);
492 	}
493 
494 	if (!peer_object_path || (wps_method == WPS_NOT_READY) ||
495 	    (parse_peer_object_path(peer_object_path, addr) < 0) ||
496 	    !p2p_peer_known(wpa_s->global->p2p, addr))
497 		goto inv_args;
498 
499 	/*
500 	 * Validate the wps_method specified and the pin value.
501 	 */
502 	if ((!pin || !pin[0]) && (wps_method == WPS_PIN_KEYPAD))
503 		goto inv_args;
504 
505 	new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
506 				   persistent_group, 0, join, authorize_only,
507 				   go_intent, freq, -1, 0, 0);
508 
509 	if (new_pin >= 0) {
510 		char npin[9];
511 		char *generated_pin;
512 		os_snprintf(npin, sizeof(npin), "%08d", new_pin);
513 		generated_pin = npin;
514 		reply = dbus_message_new_method_return(message);
515 		dbus_message_append_args(reply, DBUS_TYPE_STRING,
516 					 &generated_pin, DBUS_TYPE_INVALID);
517 	} else {
518 		switch (new_pin) {
519 		case -2:
520 			err_msg = "connect failed due to channel "
521 				"unavailability.";
522 			iface = WPAS_DBUS_ERROR_CONNECT_CHANNEL_UNAVAILABLE;
523 			break;
524 
525 		case -3:
526 			err_msg = "connect failed due to unsupported channel.";
527 			iface = WPAS_DBUS_ERROR_CONNECT_CHANNEL_UNSUPPORTED;
528 			break;
529 
530 		default:
531 			err_msg = "connect failed due to unspecified error.";
532 			iface = WPAS_DBUS_ERROR_CONNECT_UNSPECIFIED_ERROR;
533 			break;
534 		}
535 
536 		/*
537 		 * TODO:
538 		 * Do we need specialized errors corresponding to above
539 		 * error conditions as against just returning a different
540 		 * error message?
541 		 */
542 		reply = dbus_message_new_error(message, iface, err_msg);
543 	}
544 
545 out:
546 	os_free(peer_object_path);
547 	os_free(pin);
548 	return reply;
549 inv_args_clear:
550 	wpa_dbus_dict_entry_clear(&entry);
551 inv_args:
552 	reply = wpas_dbus_error_invalid_args(message, NULL);
553 	goto out;
554 }
555 
556 
wpas_dbus_handler_p2p_invite(DBusMessage * message,struct wpa_supplicant * wpa_s)557 DBusMessage * wpas_dbus_handler_p2p_invite(DBusMessage *message,
558 					   struct wpa_supplicant *wpa_s)
559 {
560 	DBusMessageIter iter_dict;
561 	DBusMessage *reply = NULL;
562 	DBusMessageIter iter;
563 	struct wpa_dbus_dict_entry entry;
564 	char *peer_object_path = NULL;
565 	char *pg_object_path = NULL;
566 	char *iface = NULL;
567 	char *net_id_str = NULL;
568 	u8 peer_addr[ETH_ALEN];
569 	unsigned int group_id = 0;
570 	int persistent = 0;
571 	struct wpa_ssid *ssid;
572 
573 	if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL))
574 		return reply;
575 
576 	dbus_message_iter_init(message, &iter);
577 
578 	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
579 		goto err;
580 
581 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
582 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
583 			goto err;
584 
585 		if (!os_strcmp(entry.key, "peer") &&
586 		    (entry.type == DBUS_TYPE_OBJECT_PATH)) {
587 			peer_object_path = os_strdup(entry.str_value);
588 			wpa_dbus_dict_entry_clear(&entry);
589 		} else if (!os_strcmp(entry.key, "persistent_group_object") &&
590 			   (entry.type == DBUS_TYPE_OBJECT_PATH)) {
591 			pg_object_path = os_strdup(entry.str_value);
592 			persistent = 1;
593 			wpa_dbus_dict_entry_clear(&entry);
594 		} else {
595 			wpa_dbus_dict_entry_clear(&entry);
596 			goto err;
597 		}
598 	}
599 
600 	if (!peer_object_path ||
601 	    (parse_peer_object_path(peer_object_path, peer_addr) < 0) ||
602 	    !p2p_peer_known(wpa_s->global->p2p, peer_addr)) {
603 		goto err;
604 	}
605 
606 	if (persistent) {
607 		/*
608 		 * A group ID is defined meaning we want to re-invoke a
609 		 * persistent group
610 		 */
611 
612 		iface = wpas_dbus_new_decompose_object_path(pg_object_path, 1,
613 							    &net_id_str, NULL);
614 		if (iface == NULL ||
615 		    os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
616 			reply = wpas_dbus_error_invalid_args(message,
617 							     pg_object_path);
618 			goto out;
619 		}
620 
621 		group_id = strtoul(net_id_str, NULL, 10);
622 		if (errno == EINVAL) {
623 			reply = wpas_dbus_error_invalid_args(
624 				message, pg_object_path);
625 			goto out;
626 		}
627 
628 		/* Get the SSID structure from the persistent group id */
629 		ssid = wpa_config_get_network(wpa_s->conf, group_id);
630 		if (ssid == NULL || ssid->disabled != 2)
631 			goto err;
632 
633 		if (wpas_p2p_invite(wpa_s, peer_addr, ssid, NULL, 0, 0) < 0) {
634 			reply = wpas_dbus_error_unknown_error(
635 				message,
636 				"Failed to reinvoke a persistent group");
637 			goto out;
638 		}
639 	} else {
640 		/*
641 		 * No group ID means propose to a peer to join my active group
642 		 */
643 		if (wpas_p2p_invite_group(wpa_s, wpa_s->ifname,
644 					  peer_addr, NULL)) {
645 			reply = wpas_dbus_error_unknown_error(
646 				message, "Failed to join to an active group");
647 			goto out;
648 		}
649 	}
650 
651 out:
652 	os_free(pg_object_path);
653 	os_free(peer_object_path);
654 	return reply;
655 
656 err:
657 	reply = wpas_dbus_error_invalid_args(message, NULL);
658 	goto out;
659 }
660 
661 
wpas_dbus_handler_p2p_prov_disc_req(DBusMessage * message,struct wpa_supplicant * wpa_s)662 DBusMessage * wpas_dbus_handler_p2p_prov_disc_req(DBusMessage *message,
663 						  struct wpa_supplicant *wpa_s)
664 {
665 	DBusMessageIter iter;
666 	char *peer_object_path = NULL;
667 	char *config_method = NULL;
668 	u8 peer_addr[ETH_ALEN];
669 
670 	dbus_message_iter_init(message, &iter);
671 	dbus_message_iter_get_basic(&iter, &peer_object_path);
672 
673 	if (parse_peer_object_path(peer_object_path, peer_addr) < 0)
674 		return wpas_dbus_error_invalid_args(message, NULL);
675 
676 	dbus_message_iter_next(&iter);
677 	dbus_message_iter_get_basic(&iter, &config_method);
678 
679 	/*
680 	 * Validation checks on config_method are being duplicated here
681 	 * to be able to return invalid args reply since the error code
682 	 * from p2p module are not granular enough (yet).
683 	 */
684 	if (os_strcmp(config_method, "display") &&
685 	    os_strcmp(config_method, "keypad") &&
686 	    os_strcmp(config_method, "pbc") &&
687 	    os_strcmp(config_method, "pushbutton"))
688 		return wpas_dbus_error_invalid_args(message, NULL);
689 
690 	if (wpas_p2p_prov_disc(wpa_s, peer_addr, config_method,
691 			       WPAS_P2P_PD_FOR_GO_NEG) < 0)
692 		return wpas_dbus_error_unknown_error(message,
693 				"Failed to send provision discovery request");
694 
695 	return NULL;
696 }
697 
698 
699 /*
700  * P2P Device property accessor methods.
701  */
702 
wpas_dbus_getter_p2p_device_config(DBusMessageIter * iter,DBusError * error,void * user_data)703 dbus_bool_t wpas_dbus_getter_p2p_device_config(DBusMessageIter *iter,
704 					       DBusError *error,
705 					       void *user_data)
706 {
707 	struct wpa_supplicant *wpa_s = user_data;
708 	DBusMessageIter variant_iter, dict_iter;
709 	DBusMessageIter iter_secdev_dict_entry, iter_secdev_dict_val,
710 		iter_secdev_dict_array;
711 	const char *dev_name;
712 	int num_vendor_extensions = 0;
713 	int i;
714 	const struct wpabuf *vendor_ext[P2P_MAX_WPS_VENDOR_EXT];
715 
716 	if (!wpa_dbus_p2p_check_enabled(wpa_s, NULL, NULL, error))
717 		return FALSE;
718 
719 	if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
720 					      "a{sv}", &variant_iter) ||
721 	    !wpa_dbus_dict_open_write(&variant_iter, &dict_iter))
722 		goto err_no_mem;
723 
724 	/* DeviceName */
725 	dev_name = wpa_s->conf->device_name;
726 	if (dev_name &&
727 	    !wpa_dbus_dict_append_string(&dict_iter, "DeviceName", dev_name))
728 		goto err_no_mem;
729 
730 	/* Primary device type */
731 	if (!wpa_dbus_dict_append_byte_array(&dict_iter, "PrimaryDeviceType",
732 	    				     (char *)wpa_s->conf->device_type,
733 	    				     WPS_DEV_TYPE_LEN))
734 		goto err_no_mem;
735 
736 	/* Secondary device types */
737 	if (wpa_s->conf->num_sec_device_types) {
738 		if (!wpa_dbus_dict_begin_array(&dict_iter,
739 					       "SecondaryDeviceTypes",
740 					       DBUS_TYPE_ARRAY_AS_STRING
741 					       DBUS_TYPE_BYTE_AS_STRING,
742 					       &iter_secdev_dict_entry,
743 					       &iter_secdev_dict_val,
744 					       &iter_secdev_dict_array))
745 			goto err_no_mem;
746 
747 		for (i = 0; i < wpa_s->conf->num_sec_device_types; i++)
748 			wpa_dbus_dict_bin_array_add_element(
749 				&iter_secdev_dict_array,
750 				wpa_s->conf->sec_device_type[i],
751 				WPS_DEV_TYPE_LEN);
752 
753 		if (!wpa_dbus_dict_end_array(&dict_iter,
754 					     &iter_secdev_dict_entry,
755 					     &iter_secdev_dict_val,
756 					     &iter_secdev_dict_array))
757 			goto err_no_mem;
758 	}
759 
760 	/* Vendor Extensions */
761 	for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
762 		if (wpa_s->conf->wps_vendor_ext[i] == NULL)
763 			continue;
764 		vendor_ext[num_vendor_extensions++] =
765 			wpa_s->conf->wps_vendor_ext[i];
766 	}
767 
768 	if (num_vendor_extensions &&
769 	    !wpa_dbus_dict_append_wpabuf_array(&dict_iter,
770 					       "VendorExtension",
771 					       vendor_ext,
772 					       num_vendor_extensions))
773 		goto err_no_mem;
774 
775 	/* GO Intent */
776 	if (!wpa_dbus_dict_append_uint32(&dict_iter, "GOIntent",
777 					 wpa_s->conf->p2p_go_intent))
778 		goto err_no_mem;
779 
780 	/* Persistent Reconnect */
781 	if (!wpa_dbus_dict_append_bool(&dict_iter, "PersistentReconnect",
782 				       wpa_s->conf->persistent_reconnect))
783 		goto err_no_mem;
784 
785 	/* Listen Reg Class */
786 	if (!wpa_dbus_dict_append_uint32(&dict_iter, "ListenRegClass",
787 					 wpa_s->conf->p2p_listen_reg_class))
788 		goto err_no_mem;
789 
790 	/* Listen Channel */
791 	if (!wpa_dbus_dict_append_uint32(&dict_iter, "ListenChannel",
792 					 wpa_s->conf->p2p_listen_channel))
793 		goto err_no_mem;
794 
795 	/* Oper Reg Class */
796 	if (!wpa_dbus_dict_append_uint32(&dict_iter, "OperRegClass",
797 					 wpa_s->conf->p2p_oper_reg_class))
798 		goto err_no_mem;
799 
800 	/* Oper Channel */
801 	if (!wpa_dbus_dict_append_uint32(&dict_iter, "OperChannel",
802 					 wpa_s->conf->p2p_oper_channel))
803 		goto err_no_mem;
804 
805 	/* SSID Postfix */
806 	if (wpa_s->conf->p2p_ssid_postfix &&
807 	    !wpa_dbus_dict_append_string(&dict_iter, "SsidPostfix",
808 					 wpa_s->conf->p2p_ssid_postfix))
809 		goto err_no_mem;
810 
811 	/* Intra Bss */
812 	if (!wpa_dbus_dict_append_bool(&dict_iter, "IntraBss",
813 				       wpa_s->conf->p2p_intra_bss))
814 		goto err_no_mem;
815 
816 	/* Group Idle */
817 	if (!wpa_dbus_dict_append_uint32(&dict_iter, "GroupIdle",
818 					 wpa_s->conf->p2p_group_idle))
819 		goto err_no_mem;
820 
821 	/* Dissasociation low ack */
822 	if (!wpa_dbus_dict_append_uint32(&dict_iter, "disassoc_low_ack",
823 					 wpa_s->conf->disassoc_low_ack))
824 		goto err_no_mem;
825 
826 	if (!wpa_dbus_dict_close_write(&variant_iter, &dict_iter) ||
827 	    !dbus_message_iter_close_container(iter, &variant_iter))
828 		goto err_no_mem;
829 
830 	return TRUE;
831 
832 err_no_mem:
833 	dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
834 	return FALSE;
835 }
836 
837 
wpas_dbus_setter_p2p_device_config(DBusMessageIter * iter,DBusError * error,void * user_data)838 dbus_bool_t wpas_dbus_setter_p2p_device_config(DBusMessageIter *iter,
839 					       DBusError *error,
840 					       void *user_data)
841 {
842 	struct wpa_supplicant *wpa_s = user_data;
843 	DBusMessageIter variant_iter, iter_dict;
844 	struct wpa_dbus_dict_entry entry = {.type = DBUS_TYPE_STRING };
845 	unsigned int i;
846 
847 	if (!wpa_dbus_p2p_check_enabled(wpa_s, NULL, NULL, error))
848 		return FALSE;
849 
850 	dbus_message_iter_recurse(iter, &variant_iter);
851 	if (!wpa_dbus_dict_open_read(&variant_iter, &iter_dict, error))
852 		return FALSE;
853 
854 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
855 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) {
856 			dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
857 					     "invalid message format");
858 			return FALSE;
859 		}
860 
861 		if (os_strcmp(entry.key, "DeviceName") == 0) {
862 			char *devname;
863 
864 			if (entry.type != DBUS_TYPE_STRING)
865 				goto error;
866 
867 			devname = os_strdup(entry.str_value);
868 			if (devname == NULL)
869 				goto err_no_mem_clear;
870 
871 			os_free(wpa_s->conf->device_name);
872 			wpa_s->conf->device_name = devname;
873 
874 			wpa_s->conf->changed_parameters |=
875 				CFG_CHANGED_DEVICE_NAME;
876 		} else if (os_strcmp(entry.key, "PrimaryDeviceType") == 0) {
877 			if (entry.type != DBUS_TYPE_ARRAY ||
878 			    entry.array_type != DBUS_TYPE_BYTE ||
879 			    entry.array_len != WPS_DEV_TYPE_LEN)
880 				goto error;
881 
882 			os_memcpy(wpa_s->conf->device_type,
883 				  entry.bytearray_value,
884 				  WPS_DEV_TYPE_LEN);
885 			wpa_s->conf->changed_parameters |=
886 				CFG_CHANGED_DEVICE_TYPE;
887 		} else if (os_strcmp(entry.key, "SecondaryDeviceTypes") == 0) {
888 			if (entry.type != DBUS_TYPE_ARRAY ||
889 			    entry.array_type != WPAS_DBUS_TYPE_BINARRAY ||
890 			    entry.array_len > MAX_SEC_DEVICE_TYPES)
891 				goto error;
892 
893 			for (i = 0; i < entry.array_len; i++)
894 				if (wpabuf_len(entry.binarray_value[i]) !=
895 				    WPS_DEV_TYPE_LEN)
896 					goto err_no_mem_clear;
897 			for (i = 0; i < entry.array_len; i++)
898 				os_memcpy(wpa_s->conf->sec_device_type[i],
899 					  wpabuf_head(entry.binarray_value[i]),
900 					  WPS_DEV_TYPE_LEN);
901 			wpa_s->conf->num_sec_device_types = entry.array_len;
902 			wpa_s->conf->changed_parameters |=
903 					CFG_CHANGED_SEC_DEVICE_TYPE;
904 		} else if (os_strcmp(entry.key, "VendorExtension") == 0) {
905 			if ((entry.type != DBUS_TYPE_ARRAY) ||
906 			    (entry.array_type != WPAS_DBUS_TYPE_BINARRAY) ||
907 			    (entry.array_len > P2P_MAX_WPS_VENDOR_EXT))
908 				goto error;
909 
910 			wpa_s->conf->changed_parameters |=
911 				CFG_CHANGED_VENDOR_EXTENSION;
912 
913 			for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
914 				wpabuf_free(wpa_s->conf->wps_vendor_ext[i]);
915 				if (i < entry.array_len) {
916 					wpa_s->conf->wps_vendor_ext[i] =
917 						entry.binarray_value[i];
918 					entry.binarray_value[i] = NULL;
919 				} else
920 					wpa_s->conf->wps_vendor_ext[i] = NULL;
921 			}
922 		} else if ((os_strcmp(entry.key, "GOIntent") == 0) &&
923 			   (entry.type == DBUS_TYPE_UINT32) &&
924 			   (entry.uint32_value <= 15))
925 			wpa_s->conf->p2p_go_intent = entry.uint32_value;
926 		else if ((os_strcmp(entry.key, "PersistentReconnect") == 0) &&
927 			 (entry.type == DBUS_TYPE_BOOLEAN))
928 			wpa_s->conf->persistent_reconnect = entry.bool_value;
929 		else if ((os_strcmp(entry.key, "ListenRegClass") == 0) &&
930 			 (entry.type == DBUS_TYPE_UINT32)) {
931 			wpa_s->conf->p2p_listen_reg_class = entry.uint32_value;
932 			wpa_s->conf->changed_parameters |=
933 				CFG_CHANGED_P2P_LISTEN_CHANNEL;
934 		} else if ((os_strcmp(entry.key, "ListenChannel") == 0) &&
935 			   (entry.type == DBUS_TYPE_UINT32)) {
936 			wpa_s->conf->p2p_listen_channel = entry.uint32_value;
937 			wpa_s->conf->changed_parameters |=
938 				CFG_CHANGED_P2P_LISTEN_CHANNEL;
939 		} else if ((os_strcmp(entry.key, "OperRegClass") == 0) &&
940 			   (entry.type == DBUS_TYPE_UINT32)) {
941 			wpa_s->conf->p2p_oper_reg_class = entry.uint32_value;
942 			wpa_s->conf->changed_parameters |=
943 				CFG_CHANGED_P2P_OPER_CHANNEL;
944 		} else if ((os_strcmp(entry.key, "OperChannel") == 0) &&
945 			   (entry.type == DBUS_TYPE_UINT32)) {
946 			wpa_s->conf->p2p_oper_channel = entry.uint32_value;
947 			wpa_s->conf->changed_parameters |=
948 				CFG_CHANGED_P2P_OPER_CHANNEL;
949 		} else if (os_strcmp(entry.key, "SsidPostfix") == 0) {
950 			char *postfix;
951 
952 			if (entry.type != DBUS_TYPE_STRING)
953 				goto error;
954 
955 			postfix = os_strdup(entry.str_value);
956 			if (!postfix)
957 				goto err_no_mem_clear;
958 
959 			os_free(wpa_s->conf->p2p_ssid_postfix);
960 			wpa_s->conf->p2p_ssid_postfix = postfix;
961 
962 			wpa_s->conf->changed_parameters |=
963 					CFG_CHANGED_P2P_SSID_POSTFIX;
964 		} else if ((os_strcmp(entry.key, "IntraBss") == 0) &&
965 			   (entry.type == DBUS_TYPE_BOOLEAN)) {
966 			wpa_s->conf->p2p_intra_bss = entry.bool_value;
967 			wpa_s->conf->changed_parameters |=
968 				CFG_CHANGED_P2P_INTRA_BSS;
969 		} else if ((os_strcmp(entry.key, "GroupIdle") == 0) &&
970 			   (entry.type == DBUS_TYPE_UINT32))
971 			wpa_s->conf->p2p_group_idle = entry.uint32_value;
972 		else if (os_strcmp(entry.key, "disassoc_low_ack") == 0 &&
973 			 entry.type == DBUS_TYPE_UINT32)
974 			wpa_s->conf->disassoc_low_ack = entry.uint32_value;
975 		else
976 			goto error;
977 
978 		wpa_dbus_dict_entry_clear(&entry);
979 	}
980 
981 	if (wpa_s->conf->changed_parameters) {
982 		/* Some changed parameters requires to update config*/
983 		wpa_supplicant_update_config(wpa_s);
984 	}
985 
986 	return TRUE;
987 
988  error:
989 	dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
990 			     "invalid message format");
991 	wpa_dbus_dict_entry_clear(&entry);
992 	return FALSE;
993 
994  err_no_mem_clear:
995 	dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
996 	wpa_dbus_dict_entry_clear(&entry);
997 	return FALSE;
998 }
999 
1000 
wpas_dbus_getter_p2p_peers(DBusMessageIter * iter,DBusError * error,void * user_data)1001 dbus_bool_t wpas_dbus_getter_p2p_peers(DBusMessageIter *iter, DBusError *error,
1002 				       void *user_data)
1003 {
1004 	struct wpa_supplicant *wpa_s = user_data;
1005 	struct p2p_data *p2p = wpa_s->global->p2p;
1006 	int next = 0, i = 0;
1007 	int num = 0, out_of_mem = 0;
1008 	const u8 *addr;
1009 	const struct p2p_peer_info *peer_info = NULL;
1010 	dbus_bool_t success = FALSE;
1011 
1012 	struct dl_list peer_objpath_list;
1013 	struct peer_objpath_node {
1014 		struct dl_list list;
1015 		char path[WPAS_DBUS_OBJECT_PATH_MAX];
1016 	} *node, *tmp;
1017 
1018 	char **peer_obj_paths = NULL;
1019 
1020 	if (!wpa_dbus_p2p_check_enabled(wpa_s, NULL, NULL, error))
1021 		return FALSE;
1022 
1023 	dl_list_init(&peer_objpath_list);
1024 
1025 	/* Get the first peer info */
1026 	peer_info = p2p_get_peer_found(p2p, NULL, next);
1027 
1028 	/* Get next and accumulate them */
1029 	next = 1;
1030 	while (peer_info != NULL) {
1031 		node = os_zalloc(sizeof(struct peer_objpath_node));
1032 		if (!node) {
1033 			out_of_mem = 1;
1034 			goto error;
1035 		}
1036 
1037 		addr = peer_info->p2p_device_addr;
1038 		os_snprintf(node->path, WPAS_DBUS_OBJECT_PATH_MAX,
1039 			    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART
1040 			    "/" COMPACT_MACSTR,
1041 			    wpa_s->dbus_new_path, MAC2STR(addr));
1042 		dl_list_add_tail(&peer_objpath_list, &node->list);
1043 		num++;
1044 
1045 		peer_info = p2p_get_peer_found(p2p, addr, next);
1046 	}
1047 
1048 	/*
1049 	 * Now construct the peer object paths in a form suitable for
1050 	 * array_property_getter helper below.
1051 	 */
1052 	peer_obj_paths = os_calloc(num, sizeof(char *));
1053 
1054 	if (!peer_obj_paths) {
1055 		out_of_mem = 1;
1056 		goto error;
1057 	}
1058 
1059 	dl_list_for_each_safe(node, tmp, &peer_objpath_list,
1060 			      struct peer_objpath_node, list)
1061 		peer_obj_paths[i++] = node->path;
1062 
1063 	success = wpas_dbus_simple_array_property_getter(iter,
1064 							 DBUS_TYPE_OBJECT_PATH,
1065 							 peer_obj_paths, num,
1066 							 error);
1067 
1068 error:
1069 	if (peer_obj_paths)
1070 		os_free(peer_obj_paths);
1071 
1072 	dl_list_for_each_safe(node, tmp, &peer_objpath_list,
1073 			      struct peer_objpath_node, list) {
1074 		dl_list_del(&node->list);
1075 		os_free(node);
1076 	}
1077 	if (out_of_mem)
1078 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1079 
1080 	return success;
1081 }
1082 
1083 
1084 enum wpas_p2p_role {
1085 	WPAS_P2P_ROLE_DEVICE,
1086 	WPAS_P2P_ROLE_GO,
1087 	WPAS_P2P_ROLE_CLIENT,
1088 };
1089 
wpas_get_p2p_role(struct wpa_supplicant * wpa_s)1090 static enum wpas_p2p_role wpas_get_p2p_role(struct wpa_supplicant *wpa_s)
1091 {
1092 	struct wpa_ssid *ssid = wpa_s->current_ssid;
1093 
1094 	if (!ssid)
1095 		return WPAS_P2P_ROLE_DEVICE;
1096 	if (wpa_s->wpa_state != WPA_COMPLETED)
1097 		return WPAS_P2P_ROLE_DEVICE;
1098 
1099 	switch (ssid->mode) {
1100 	case WPAS_MODE_P2P_GO:
1101 	case WPAS_MODE_P2P_GROUP_FORMATION:
1102 		return WPAS_P2P_ROLE_GO;
1103 	case WPAS_MODE_INFRA:
1104 		if (ssid->p2p_group)
1105 			return WPAS_P2P_ROLE_CLIENT;
1106 		return WPAS_P2P_ROLE_DEVICE;
1107 	default:
1108 		return WPAS_P2P_ROLE_DEVICE;
1109 	}
1110 }
1111 
1112 
wpas_dbus_getter_p2p_role(DBusMessageIter * iter,DBusError * error,void * user_data)1113 dbus_bool_t wpas_dbus_getter_p2p_role(DBusMessageIter *iter, DBusError *error,
1114 				      void *user_data)
1115 {
1116 	struct wpa_supplicant *wpa_s = user_data;
1117 	char *str;
1118 
1119 	switch (wpas_get_p2p_role(wpa_s)) {
1120 	case WPAS_P2P_ROLE_GO:
1121 		str = "GO";
1122 		break;
1123 	case WPAS_P2P_ROLE_CLIENT:
1124 		str = "client";
1125 		break;
1126 	default:
1127 		str = "device";
1128 	}
1129 
1130 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &str,
1131 						error);
1132 }
1133 
1134 
wpas_dbus_getter_p2p_group(DBusMessageIter * iter,DBusError * error,void * user_data)1135 dbus_bool_t wpas_dbus_getter_p2p_group(DBusMessageIter *iter, DBusError *error,
1136 				       void *user_data)
1137 {
1138 	struct wpa_supplicant *wpa_s = user_data;
1139 	char path_buf[WPAS_DBUS_OBJECT_PATH_MAX];
1140 	char *dbus_groupobj_path = path_buf;
1141 
1142 	if (wpa_s->dbus_groupobj_path == NULL)
1143 		os_snprintf(dbus_groupobj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1144 			    "/");
1145 	else
1146 		os_snprintf(dbus_groupobj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1147 			    "%s", wpa_s->dbus_groupobj_path);
1148 
1149 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
1150 						&dbus_groupobj_path, error);
1151 }
1152 
1153 
wpas_dbus_getter_p2p_peergo(DBusMessageIter * iter,DBusError * error,void * user_data)1154 dbus_bool_t wpas_dbus_getter_p2p_peergo(DBusMessageIter *iter,
1155 					DBusError *error, void *user_data)
1156 {
1157 	struct wpa_supplicant *wpa_s = user_data;
1158 	char go_peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1159 
1160 	if (wpas_get_p2p_role(wpa_s) != WPAS_P2P_ROLE_CLIENT)
1161 		os_snprintf(go_peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
1162 	else
1163 		os_snprintf(go_peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1164 			    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
1165 			    COMPACT_MACSTR,
1166 			    wpa_s->dbus_new_path, MAC2STR(wpa_s->go_dev_addr));
1167 
1168 	path = go_peer_obj_path;
1169 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
1170 						&path, error);
1171 }
1172 
1173 
1174 /*
1175  * Peer object properties accessor methods
1176  */
1177 
wpas_dbus_getter_p2p_peer_device_name(DBusMessageIter * iter,DBusError * error,void * user_data)1178 dbus_bool_t wpas_dbus_getter_p2p_peer_device_name(DBusMessageIter *iter,
1179 						  DBusError *error,
1180 						  void *user_data)
1181 {
1182 	struct peer_handler_args *peer_args = user_data;
1183 	const struct p2p_peer_info *info;
1184 	char *tmp;
1185 
1186 	if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error))
1187 		return FALSE;
1188 
1189 	/* get the peer info */
1190 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1191 				  peer_args->p2p_device_addr, 0);
1192 	if (info == NULL) {
1193 		dbus_set_error(error, DBUS_ERROR_FAILED,
1194 			       "failed to find peer");
1195 		return FALSE;
1196 	}
1197 
1198 	tmp = os_strdup(info->device_name);
1199 	if (!tmp) {
1200 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1201 		return FALSE;
1202 	}
1203 
1204 	if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp,
1205 					      error)) {
1206 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1207 		os_free(tmp);
1208 		return FALSE;
1209 	}
1210 
1211 	os_free(tmp);
1212 	return TRUE;
1213 }
1214 
1215 
wpas_dbus_getter_p2p_peer_primary_device_type(DBusMessageIter * iter,DBusError * error,void * user_data)1216 dbus_bool_t wpas_dbus_getter_p2p_peer_primary_device_type(
1217 	DBusMessageIter *iter, DBusError *error, void *user_data)
1218 {
1219 	struct peer_handler_args *peer_args = user_data;
1220 	const struct p2p_peer_info *info;
1221 
1222 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1223 				  peer_args->p2p_device_addr, 0);
1224 	if (info == NULL) {
1225 		dbus_set_error(error, DBUS_ERROR_FAILED,
1226 			       "failed to find peer");
1227 		return FALSE;
1228 	}
1229 
1230 	if (!wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
1231 						    (char *)
1232 						    info->pri_dev_type,
1233 						    WPS_DEV_TYPE_LEN, error)) {
1234 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1235 		return FALSE;
1236 	}
1237 
1238 	return TRUE;
1239 }
1240 
1241 
wpas_dbus_getter_p2p_peer_config_method(DBusMessageIter * iter,DBusError * error,void * user_data)1242 dbus_bool_t wpas_dbus_getter_p2p_peer_config_method(DBusMessageIter *iter,
1243                                                     DBusError *error,
1244                                                     void *user_data)
1245 {
1246 	struct peer_handler_args *peer_args = user_data;
1247 	const struct p2p_peer_info *info;
1248 
1249 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1250 				  peer_args->p2p_device_addr, 0);
1251 	if (info == NULL) {
1252 		dbus_set_error(error, DBUS_ERROR_FAILED,
1253 			       "failed to find peer");
1254 		return FALSE;
1255 	}
1256 
1257 	if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
1258 					      &info->config_methods, error)) {
1259 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1260 		return FALSE;
1261 	}
1262 
1263 	return TRUE;
1264 }
1265 
1266 
wpas_dbus_getter_p2p_peer_level(DBusMessageIter * iter,DBusError * error,void * user_data)1267 dbus_bool_t wpas_dbus_getter_p2p_peer_level(DBusMessageIter *iter,
1268                                             DBusError *error,
1269                                             void *user_data)
1270 {
1271 	struct peer_handler_args *peer_args = user_data;
1272 	const struct p2p_peer_info *info;
1273 
1274 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1275 				  peer_args->p2p_device_addr, 0);
1276 	if (info == NULL) {
1277 		dbus_set_error(error, DBUS_ERROR_FAILED,
1278 			       "failed to find peer");
1279 		return FALSE;
1280 	}
1281 
1282 	if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
1283 					      &info->level, error)) {
1284 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1285 		return FALSE;
1286 	}
1287 
1288 	return TRUE;
1289 }
1290 
1291 
wpas_dbus_getter_p2p_peer_device_capability(DBusMessageIter * iter,DBusError * error,void * user_data)1292 dbus_bool_t wpas_dbus_getter_p2p_peer_device_capability(DBusMessageIter *iter,
1293                                                         DBusError *error,
1294                                                         void *user_data)
1295 {
1296 	struct peer_handler_args *peer_args = user_data;
1297 	const struct p2p_peer_info *info;
1298 
1299 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1300 				  peer_args->p2p_device_addr, 0);
1301 	if (info == NULL) {
1302 		dbus_set_error(error, DBUS_ERROR_FAILED,
1303 			       "failed to find peer");
1304 		return FALSE;
1305 	}
1306 
1307 	if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BYTE,
1308 					      &info->dev_capab, error)) {
1309 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1310 		return FALSE;
1311 	}
1312 
1313 	return TRUE;
1314 }
1315 
1316 
wpas_dbus_getter_p2p_peer_group_capability(DBusMessageIter * iter,DBusError * error,void * user_data)1317 dbus_bool_t wpas_dbus_getter_p2p_peer_group_capability(DBusMessageIter *iter,
1318 						       DBusError *error,
1319 						       void *user_data)
1320 {
1321 	struct peer_handler_args *peer_args = user_data;
1322 	const struct p2p_peer_info *info;
1323 
1324 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1325 				  peer_args->p2p_device_addr, 0);
1326 	if (info == NULL) {
1327 		dbus_set_error(error, DBUS_ERROR_FAILED,
1328 			       "failed to find peer");
1329 		return FALSE;
1330 	}
1331 
1332 	if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BYTE,
1333 					      &info->group_capab, error)) {
1334 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1335 		return FALSE;
1336 	}
1337 
1338 	return TRUE;
1339 }
1340 
1341 
wpas_dbus_getter_p2p_peer_secondary_device_types(DBusMessageIter * iter,DBusError * error,void * user_data)1342 dbus_bool_t wpas_dbus_getter_p2p_peer_secondary_device_types(
1343 	DBusMessageIter *iter, DBusError *error, void *user_data)
1344 {
1345 	struct peer_handler_args *peer_args = user_data;
1346 	const struct p2p_peer_info *info;
1347 	DBusMessageIter variant_iter, array_iter;
1348 
1349 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1350 				  peer_args->p2p_device_addr, 0);
1351 	if (info == NULL) {
1352 		dbus_set_error(error, DBUS_ERROR_FAILED,
1353 			       "failed to find peer");
1354 		return FALSE;
1355 	}
1356 
1357 	if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
1358 					      DBUS_TYPE_ARRAY_AS_STRING
1359 					      DBUS_TYPE_ARRAY_AS_STRING
1360 					      DBUS_TYPE_BYTE_AS_STRING,
1361 					      &variant_iter)) {
1362 		dbus_set_error(error, DBUS_ERROR_FAILED,
1363 		               "%s: failed to construct message 1", __func__);
1364 		return FALSE;
1365 	}
1366 
1367 	if (!dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
1368 					      DBUS_TYPE_ARRAY_AS_STRING
1369 					      DBUS_TYPE_BYTE_AS_STRING,
1370 					      &array_iter)) {
1371 		dbus_set_error(error, DBUS_ERROR_FAILED,
1372 		               "%s: failed to construct message 2", __func__);
1373 		return FALSE;
1374 	}
1375 
1376 	if (info->wps_sec_dev_type_list_len) {
1377 		const u8 *sec_dev_type_list = info->wps_sec_dev_type_list;
1378 		int num_sec_device_types =
1379 			info->wps_sec_dev_type_list_len / WPS_DEV_TYPE_LEN;
1380 		int i;
1381 		DBusMessageIter inner_array_iter;
1382 
1383 		for (i = 0; i < num_sec_device_types; i++) {
1384 			if (!dbus_message_iter_open_container(
1385 				    &array_iter, DBUS_TYPE_ARRAY,
1386 				    DBUS_TYPE_BYTE_AS_STRING,
1387 				    &inner_array_iter)) {
1388 				dbus_set_error(error, DBUS_ERROR_FAILED,
1389 					       "%s: failed to construct "
1390 					       "message 3 (%d)",
1391 					       __func__, i);
1392 				return FALSE;
1393 			}
1394 
1395 			if (!dbus_message_iter_append_fixed_array(
1396 				    &inner_array_iter, DBUS_TYPE_BYTE,
1397 				    &sec_dev_type_list, WPS_DEV_TYPE_LEN)) {
1398 				dbus_set_error(error, DBUS_ERROR_FAILED,
1399 					       "%s: failed to construct "
1400 					       "message 4 (%d)",
1401 					       __func__, i);
1402 				return FALSE;
1403 			}
1404 
1405 			if (!dbus_message_iter_close_container(
1406 				    &array_iter, &inner_array_iter)) {
1407 				dbus_set_error(error, DBUS_ERROR_FAILED,
1408 					       "%s: failed to construct "
1409 					       "message 5 (%d)",
1410 					       __func__, i);
1411 				return FALSE;
1412 			}
1413 
1414 			sec_dev_type_list += WPS_DEV_TYPE_LEN;
1415 		}
1416 	}
1417 
1418 	if (!dbus_message_iter_close_container(&variant_iter, &array_iter)) {
1419 		dbus_set_error(error, DBUS_ERROR_FAILED,
1420 		               "%s: failed to construct message 6", __func__);
1421 		return FALSE;
1422 	}
1423 
1424 	if (!dbus_message_iter_close_container(iter, &variant_iter)) {
1425 		dbus_set_error(error, DBUS_ERROR_FAILED,
1426 		               "%s: failed to construct message 7", __func__);
1427 		return FALSE;
1428 	}
1429 
1430 	return TRUE;
1431 }
1432 
1433 
wpas_dbus_getter_p2p_peer_vendor_extension(DBusMessageIter * iter,DBusError * error,void * user_data)1434 dbus_bool_t wpas_dbus_getter_p2p_peer_vendor_extension(DBusMessageIter *iter,
1435 						       DBusError *error,
1436 						       void *user_data)
1437 {
1438 	struct wpabuf *vendor_extension[P2P_MAX_WPS_VENDOR_EXT];
1439 	int i, num;
1440 	struct peer_handler_args *peer_args = user_data;
1441 	const struct p2p_peer_info *info;
1442 
1443 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1444 				  peer_args->p2p_device_addr, 0);
1445 	if (info == NULL) {
1446 		dbus_set_error(error, DBUS_ERROR_FAILED,
1447 			       "failed to find peer");
1448 		return FALSE;
1449 	}
1450 
1451 	/* Add WPS vendor extensions attribute */
1452 	for (i = 0, num = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
1453 		if (info->wps_vendor_ext[i] == NULL)
1454 			continue;
1455 		vendor_extension[num] = info->wps_vendor_ext[i];
1456 		num++;
1457 	}
1458 
1459 	if (!wpas_dbus_simple_array_array_property_getter(iter, DBUS_TYPE_BYTE,
1460 							  vendor_extension,
1461 							  num, error))
1462 		return FALSE;
1463 
1464 	return TRUE;
1465 }
1466 
1467 
wpas_dbus_getter_p2p_peer_ies(DBusMessageIter * iter,DBusError * error,void * user_data)1468 dbus_bool_t wpas_dbus_getter_p2p_peer_ies(DBusMessageIter *iter,
1469 					  DBusError *error, void *user_data)
1470 {
1471 	dbus_bool_t success;
1472 	/* struct peer_handler_args *peer_args = user_data; */
1473 
1474 	success = wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
1475 							 NULL, 0, error);
1476 	return success;
1477 }
1478 
1479 
1480 /**
1481  * wpas_dbus_getter_persistent_groups - Get array of persistent group objects
1482  * @iter: Pointer to incoming dbus message iter
1483  * @error: Location to store error on failure
1484  * @user_data: Function specific data
1485  * Returns: TRUE on success, FALSE on failure
1486  *
1487  * Getter for "PersistentGroups" property.
1488  */
wpas_dbus_getter_persistent_groups(DBusMessageIter * iter,DBusError * error,void * user_data)1489 dbus_bool_t wpas_dbus_getter_persistent_groups(DBusMessageIter *iter,
1490 					       DBusError *error,
1491 					       void *user_data)
1492 {
1493 	struct wpa_supplicant *wpa_s = user_data;
1494 	struct wpa_ssid *ssid;
1495 	char **paths;
1496 	unsigned int i = 0, num = 0;
1497 	dbus_bool_t success = FALSE;
1498 
1499 	if (wpa_s->conf == NULL) {
1500 		wpa_printf(MSG_ERROR, "dbus: %s: "
1501 			   "An error occurred getting persistent groups list",
1502 			   __func__);
1503 		dbus_set_error_const(error, DBUS_ERROR_FAILED, "an error "
1504 				     "occurred getting persistent groups list");
1505 		return FALSE;
1506 	}
1507 
1508 	for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
1509 		if (network_is_persistent_group(ssid))
1510 			num++;
1511 
1512 	paths = os_calloc(num, sizeof(char *));
1513 	if (!paths) {
1514 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1515 		return FALSE;
1516 	}
1517 
1518 	/* Loop through configured networks and append object path of each */
1519 	for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1520 		if (!network_is_persistent_group(ssid))
1521 			continue;
1522 		paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1523 		if (paths[i] == NULL) {
1524 			dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
1525 					     "no memory");
1526 			goto out;
1527 		}
1528 		/* Construct the object path for this network. */
1529 		os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
1530 			    "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%d",
1531 			    wpa_s->dbus_new_path, ssid->id);
1532 	}
1533 
1534 	success = wpas_dbus_simple_array_property_getter(iter,
1535 							 DBUS_TYPE_OBJECT_PATH,
1536 							 paths, num, error);
1537 
1538 out:
1539 	while (i)
1540 		os_free(paths[--i]);
1541 	os_free(paths);
1542 	return success;
1543 }
1544 
1545 
1546 /**
1547  * wpas_dbus_getter_persistent_group_properties - Get options for a persistent
1548  *	group
1549  * @iter: Pointer to incoming dbus message iter
1550  * @error: Location to store error on failure
1551  * @user_data: Function specific data
1552  * Returns: TRUE on success, FALSE on failure
1553  *
1554  * Getter for "Properties" property of a persistent group.
1555  */
wpas_dbus_getter_persistent_group_properties(DBusMessageIter * iter,DBusError * error,void * user_data)1556 dbus_bool_t wpas_dbus_getter_persistent_group_properties(DBusMessageIter *iter,
1557 							 DBusError *error,
1558 							 void *user_data)
1559 {
1560 	struct network_handler_args *net = user_data;
1561 
1562 	/* Leveraging the fact that persistent group object is still
1563 	 * represented in same manner as network within.
1564 	 */
1565 	return wpas_dbus_getter_network_properties(iter, error, net);
1566 }
1567 
1568 
1569 /**
1570  * wpas_dbus_setter_persistent_group_properties - Get options for a persistent
1571  *	group
1572  * @iter: Pointer to incoming dbus message iter
1573  * @error: Location to store error on failure
1574  * @user_data: Function specific data
1575  * Returns: TRUE on success, FALSE on failure
1576  *
1577  * Setter for "Properties" property of a persistent group.
1578  */
wpas_dbus_setter_persistent_group_properties(DBusMessageIter * iter,DBusError * error,void * user_data)1579 dbus_bool_t wpas_dbus_setter_persistent_group_properties(DBusMessageIter *iter,
1580 							 DBusError *error,
1581 							 void *user_data)
1582 {
1583 	struct network_handler_args *net = user_data;
1584 	struct wpa_ssid *ssid = net->ssid;
1585 	DBusMessageIter	variant_iter;
1586 
1587 	/*
1588 	 * Leveraging the fact that persistent group object is still
1589 	 * represented in same manner as network within.
1590 	 */
1591 	dbus_message_iter_recurse(iter, &variant_iter);
1592 	return set_network_properties(net->wpa_s, ssid, &variant_iter, error);
1593 }
1594 
1595 
1596 /**
1597  * wpas_dbus_new_iface_add_persistent_group - Add a new configured
1598  *	persistent_group
1599  * @message: Pointer to incoming dbus message
1600  * @wpa_s: wpa_supplicant structure for a network interface
1601  * Returns: A dbus message containing the object path of the new
1602  * persistent group
1603  *
1604  * Handler function for "AddPersistentGroup" method call of a P2P Device
1605  * interface.
1606  */
wpas_dbus_handler_add_persistent_group(DBusMessage * message,struct wpa_supplicant * wpa_s)1607 DBusMessage * wpas_dbus_handler_add_persistent_group(
1608 	DBusMessage *message, struct wpa_supplicant *wpa_s)
1609 {
1610 	DBusMessage *reply = NULL;
1611 	DBusMessageIter	iter;
1612 	struct wpa_ssid *ssid = NULL;
1613 	char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf;
1614 	DBusError error;
1615 
1616 	dbus_message_iter_init(message, &iter);
1617 
1618 	ssid = wpa_config_add_network(wpa_s->conf);
1619 	if (ssid == NULL) {
1620 		wpa_printf(MSG_ERROR, "dbus: %s: "
1621 			   "Cannot add new persistent group", __func__);
1622 		reply = wpas_dbus_error_unknown_error(
1623 			message,
1624 			"wpa_supplicant could not add "
1625 			"a persistent group on this interface.");
1626 		goto err;
1627 	}
1628 
1629 	/* Mark the ssid as being a persistent group before the notification */
1630 	ssid->disabled = 2;
1631 	ssid->p2p_persistent_group = 1;
1632 	wpas_notify_persistent_group_added(wpa_s, ssid);
1633 
1634 	wpa_config_set_network_defaults(ssid);
1635 
1636 	dbus_error_init(&error);
1637 	if (!set_network_properties(wpa_s, ssid, &iter, &error)) {
1638 		wpa_printf(MSG_DEBUG, "dbus: %s: "
1639 			   "Control interface could not set persistent group "
1640 			   "properties", __func__);
1641 		reply = wpas_dbus_reply_new_from_error(message, &error,
1642 						       DBUS_ERROR_INVALID_ARGS,
1643 						       "Failed to set network "
1644 						       "properties");
1645 		dbus_error_free(&error);
1646 		goto err;
1647 	}
1648 
1649 	/* Construct the object path for this network. */
1650 	os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
1651 		    "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%d",
1652 		    wpa_s->dbus_new_path, ssid->id);
1653 
1654 	reply = dbus_message_new_method_return(message);
1655 	if (reply == NULL) {
1656 		reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1657 					       NULL);
1658 		goto err;
1659 	}
1660 	if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
1661 				      DBUS_TYPE_INVALID)) {
1662 		dbus_message_unref(reply);
1663 		reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1664 					       NULL);
1665 		goto err;
1666 	}
1667 
1668 	return reply;
1669 
1670 err:
1671 	if (ssid) {
1672 		wpas_notify_persistent_group_removed(wpa_s, ssid);
1673 		wpa_config_remove_network(wpa_s->conf, ssid->id);
1674 	}
1675 	return reply;
1676 }
1677 
1678 
1679 /**
1680  * wpas_dbus_handler_remove_persistent_group - Remove a configured persistent
1681  *	group
1682  * @message: Pointer to incoming dbus message
1683  * @wpa_s: wpa_supplicant structure for a network interface
1684  * Returns: NULL on success or dbus error on failure
1685  *
1686  * Handler function for "RemovePersistentGroup" method call of a P2P Device
1687  * interface.
1688  */
wpas_dbus_handler_remove_persistent_group(DBusMessage * message,struct wpa_supplicant * wpa_s)1689 DBusMessage * wpas_dbus_handler_remove_persistent_group(
1690 	DBusMessage *message, struct wpa_supplicant *wpa_s)
1691 {
1692 	DBusMessage *reply = NULL;
1693 	const char *op;
1694 	char *iface = NULL, *persistent_group_id = NULL;
1695 	int id;
1696 	struct wpa_ssid *ssid;
1697 
1698 	dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
1699 			      DBUS_TYPE_INVALID);
1700 
1701 	/*
1702 	 * Extract the network ID and ensure the network is actually a child of
1703 	 * this interface.
1704 	 */
1705 	iface = wpas_dbus_new_decompose_object_path(op, 1,
1706 						    &persistent_group_id,
1707 						    NULL);
1708 	if (iface == NULL || os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
1709 		reply = wpas_dbus_error_invalid_args(message, op);
1710 		goto out;
1711 	}
1712 
1713 	id = strtoul(persistent_group_id, NULL, 10);
1714 	if (errno == EINVAL) {
1715 		reply = wpas_dbus_error_invalid_args(message, op);
1716 		goto out;
1717 	}
1718 
1719 	ssid = wpa_config_get_network(wpa_s->conf, id);
1720 	if (ssid == NULL) {
1721 		reply = wpas_dbus_error_persistent_group_unknown(message);
1722 		goto out;
1723 	}
1724 
1725 	wpas_notify_persistent_group_removed(wpa_s, ssid);
1726 
1727 	if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
1728 		wpa_printf(MSG_ERROR, "dbus: %s: "
1729 			   "error occurred when removing persistent group %d",
1730 			   __func__, id);
1731 		reply = wpas_dbus_error_unknown_error(
1732 			message,
1733 			"error removing the specified persistent group on "
1734 			"this interface.");
1735 		goto out;
1736 	}
1737 
1738 out:
1739 	os_free(iface);
1740 	os_free(persistent_group_id);
1741 	return reply;
1742 }
1743 
1744 
remove_persistent_group(struct wpa_supplicant * wpa_s,struct wpa_ssid * ssid)1745 static void remove_persistent_group(struct wpa_supplicant *wpa_s,
1746 				    struct wpa_ssid *ssid)
1747 {
1748 	wpas_notify_persistent_group_removed(wpa_s, ssid);
1749 
1750 	if (wpa_config_remove_network(wpa_s->conf, ssid->id) < 0) {
1751 		wpa_printf(MSG_ERROR, "dbus: %s: "
1752 			   "error occurred when removing persistent group %d",
1753 			   __func__, ssid->id);
1754 		return;
1755 	}
1756 }
1757 
1758 
1759 /**
1760  * wpas_dbus_handler_remove_all_persistent_groups - Remove all configured
1761  * persistent groups
1762  * @message: Pointer to incoming dbus message
1763  * @wpa_s: wpa_supplicant structure for a network interface
1764  * Returns: NULL on success or dbus error on failure
1765  *
1766  * Handler function for "RemoveAllPersistentGroups" method call of a
1767  * P2P Device interface.
1768  */
wpas_dbus_handler_remove_all_persistent_groups(DBusMessage * message,struct wpa_supplicant * wpa_s)1769 DBusMessage * wpas_dbus_handler_remove_all_persistent_groups(
1770 	DBusMessage *message, struct wpa_supplicant *wpa_s)
1771 {
1772 	struct wpa_ssid *ssid, *next;
1773 	struct wpa_config *config;
1774 
1775 	config = wpa_s->conf;
1776 	ssid = config->ssid;
1777 	while (ssid) {
1778 		next = ssid->next;
1779 		if (network_is_persistent_group(ssid))
1780 			remove_persistent_group(wpa_s, ssid);
1781 		ssid = next;
1782 	}
1783 	return NULL;
1784 }
1785 
1786 
1787 /*
1788  * Group object properties accessor methods
1789  */
1790 
wpas_dbus_getter_p2p_group_members(DBusMessageIter * iter,DBusError * error,void * user_data)1791 dbus_bool_t wpas_dbus_getter_p2p_group_members(DBusMessageIter *iter,
1792 					       DBusError *error,
1793 					       void *user_data)
1794 {
1795 	struct wpa_supplicant *wpa_s = user_data;
1796 	struct wpa_ssid *ssid;
1797 	unsigned int num_members;
1798 	char **paths;
1799 	unsigned int i;
1800 	void *next = NULL;
1801 	const u8 *addr;
1802 	dbus_bool_t success = FALSE;
1803 
1804 	/* Verify correct role for this property */
1805 	if (wpas_get_p2p_role(wpa_s) != WPAS_P2P_ROLE_GO) {
1806 		return wpas_dbus_simple_array_property_getter(
1807 			iter, DBUS_TYPE_OBJECT_PATH, NULL, 0, error);
1808 	}
1809 
1810 	ssid = wpa_s->conf->ssid;
1811 	/* At present WPAS P2P_GO mode only applicable for p2p_go */
1812 	if (ssid->mode != WPAS_MODE_P2P_GO &&
1813 	    ssid->mode != WPAS_MODE_AP &&
1814 	    ssid->mode != WPAS_MODE_P2P_GROUP_FORMATION)
1815 		return FALSE;
1816 
1817 	num_members = p2p_get_group_num_members(wpa_s->p2p_group);
1818 
1819 	paths = os_calloc(num_members, sizeof(char *));
1820 	if (!paths)
1821 		goto out_of_memory;
1822 
1823 	i = 0;
1824 	while ((addr = p2p_iterate_group_members(wpa_s->p2p_group, &next))) {
1825 		paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1826 		if (!paths[i])
1827 			goto out_of_memory;
1828 		os_snprintf(paths[i], WPAS_DBUS_OBJECT_PATH_MAX,
1829 			    "%s/" WPAS_DBUS_NEW_P2P_GROUPMEMBERS_PART
1830 			    "/" COMPACT_MACSTR,
1831 			    wpa_s->dbus_groupobj_path, MAC2STR(addr));
1832 		i++;
1833 	}
1834 
1835 	success = wpas_dbus_simple_array_property_getter(iter,
1836 							 DBUS_TYPE_OBJECT_PATH,
1837 							 paths, num_members,
1838 							 error);
1839 
1840 	for (i = 0; i < num_members; i++)
1841 		os_free(paths[i]);
1842 	os_free(paths);
1843 	return success;
1844 
1845 out_of_memory:
1846 	dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1847 	if (paths) {
1848 		for (i = 0; i < num_members; i++)
1849 			os_free(paths[i]);
1850 		os_free(paths);
1851 	}
1852 	return FALSE;
1853 }
1854 
1855 
wpas_dbus_getter_p2p_group_ssid(DBusMessageIter * iter,DBusError * error,void * user_data)1856 dbus_bool_t wpas_dbus_getter_p2p_group_ssid(DBusMessageIter *iter,
1857 					    DBusError *error, void *user_data)
1858 {
1859 	struct wpa_supplicant *wpa_s = user_data;
1860 	if (wpa_s->current_ssid == NULL)
1861 		return FALSE;
1862 	return wpas_dbus_simple_array_property_getter(
1863 		iter, DBUS_TYPE_BYTE, wpa_s->current_ssid->ssid,
1864 		wpa_s->current_ssid->ssid_len, error);
1865 }
1866 
1867 
wpas_dbus_getter_p2p_group_bssid(DBusMessageIter * iter,DBusError * error,void * user_data)1868 dbus_bool_t wpas_dbus_getter_p2p_group_bssid(DBusMessageIter *iter,
1869 					     DBusError *error,
1870 					     void *user_data)
1871 {
1872 	struct wpa_supplicant *wpa_s = user_data;
1873 	u8 role = wpas_get_p2p_role(wpa_s);
1874 	u8 *p_bssid;
1875 
1876 	if (role == WPAS_P2P_ROLE_CLIENT) {
1877 		if (wpa_s->current_ssid == NULL)
1878 			return FALSE;
1879 		p_bssid = wpa_s->current_ssid->bssid;
1880 	} else {
1881 		if (wpa_s->ap_iface == NULL)
1882 			return FALSE;
1883 		p_bssid = wpa_s->ap_iface->bss[0]->own_addr;
1884 	}
1885 
1886 	return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
1887 						      p_bssid, ETH_ALEN,
1888 						      error);
1889 }
1890 
1891 
wpas_dbus_getter_p2p_group_frequency(DBusMessageIter * iter,DBusError * error,void * user_data)1892 dbus_bool_t wpas_dbus_getter_p2p_group_frequency(DBusMessageIter *iter,
1893 						 DBusError *error,
1894 						 void *user_data)
1895 {
1896 	struct wpa_supplicant *wpa_s = user_data;
1897 	u16 op_freq;
1898 	u8 role = wpas_get_p2p_role(wpa_s);
1899 
1900 	if (role == WPAS_P2P_ROLE_CLIENT) {
1901 		if (wpa_s->go_params == NULL)
1902 			return FALSE;
1903 		op_freq = wpa_s->go_params->freq;
1904 	} else {
1905 		if (wpa_s->ap_iface == NULL)
1906 			return FALSE;
1907 		op_freq = wpa_s->ap_iface->freq;
1908 	}
1909 
1910 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
1911 						&op_freq, error);
1912 }
1913 
1914 
wpas_dbus_getter_p2p_group_passphrase(DBusMessageIter * iter,DBusError * error,void * user_data)1915 dbus_bool_t wpas_dbus_getter_p2p_group_passphrase(DBusMessageIter *iter,
1916 						  DBusError *error,
1917 						  void *user_data)
1918 {
1919 	struct wpa_supplicant *wpa_s = user_data;
1920 	u8 role = wpas_get_p2p_role(wpa_s);
1921 	char *p_pass = NULL;
1922 
1923 	/* Verify correct role for this property */
1924 	if (role == WPAS_P2P_ROLE_GO) {
1925 		if (wpa_s->current_ssid == NULL)
1926 			return FALSE;
1927 		p_pass = wpa_s->current_ssid->passphrase;
1928 	} else
1929 		p_pass = "";
1930 
1931 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
1932 						&p_pass, error);
1933 
1934 }
1935 
1936 
wpas_dbus_getter_p2p_group_psk(DBusMessageIter * iter,DBusError * error,void * user_data)1937 dbus_bool_t wpas_dbus_getter_p2p_group_psk(DBusMessageIter *iter,
1938 					   DBusError *error, void *user_data)
1939 {
1940 	struct wpa_supplicant *wpa_s = user_data;
1941 	u8 role = wpas_get_p2p_role(wpa_s);
1942 	u8 *p_psk = NULL;
1943 	u8 psk_len = 0;
1944 
1945 	/* Verify correct role for this property */
1946 	if (role == WPAS_P2P_ROLE_CLIENT) {
1947 		if (wpa_s->current_ssid == NULL)
1948 			return FALSE;
1949 		p_psk = wpa_s->current_ssid->psk;
1950 		psk_len = 32;
1951 	}
1952 
1953 	return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
1954 						      &p_psk, psk_len, error);
1955 }
1956 
1957 
wpas_dbus_getter_p2p_group_vendor_ext(DBusMessageIter * iter,DBusError * error,void * user_data)1958 dbus_bool_t wpas_dbus_getter_p2p_group_vendor_ext(DBusMessageIter *iter,
1959 						  DBusError *error,
1960 						  void *user_data)
1961 {
1962 	struct wpa_supplicant *wpa_s = user_data;
1963 	struct hostapd_data *hapd;
1964 	struct wpabuf *vendor_ext[MAX_WPS_VENDOR_EXTENSIONS];
1965 	int num_vendor_ext = 0;
1966 	int i;
1967 
1968 	/* Verify correct role for this property */
1969 	if (wpas_get_p2p_role(wpa_s) == WPAS_P2P_ROLE_GO) {
1970 		if (wpa_s->ap_iface == NULL)
1971 			return FALSE;
1972 		hapd = wpa_s->ap_iface->bss[0];
1973 
1974 		/* Parse WPS Vendor Extensions sent in Beacon/Probe Response */
1975 		for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
1976 			if (hapd->conf->wps_vendor_ext[i] == NULL)
1977 				vendor_ext[i] = NULL;
1978 			else {
1979 				vendor_ext[num_vendor_ext++] =
1980 					hapd->conf->wps_vendor_ext[i];
1981 			}
1982 		}
1983 	}
1984 
1985 	/* Return vendor extensions or no data */
1986 	return wpas_dbus_simple_array_array_property_getter(iter,
1987 							    DBUS_TYPE_BYTE,
1988 							    vendor_ext,
1989 							    num_vendor_ext,
1990 						 error);
1991 }
1992 
1993 
wpas_dbus_setter_p2p_group_vendor_ext(DBusMessageIter * iter,DBusError * error,void * user_data)1994 dbus_bool_t wpas_dbus_setter_p2p_group_vendor_ext(DBusMessageIter *iter,
1995 						  DBusError *error,
1996 						  void *user_data)
1997 {
1998 	struct wpa_supplicant *wpa_s = user_data;
1999 	DBusMessageIter variant_iter, iter_dict;
2000 	struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
2001 	unsigned int i;
2002 	struct hostapd_data *hapd = NULL;
2003 
2004 	if (wpas_get_p2p_role(wpa_s) == WPAS_P2P_ROLE_GO &&
2005 	    wpa_s->ap_iface != NULL)
2006 		hapd = wpa_s->ap_iface->bss[0];
2007 	else
2008 		return FALSE;
2009 
2010 	dbus_message_iter_recurse(iter, &variant_iter);
2011 	if (!wpa_dbus_dict_open_read(&variant_iter, &iter_dict, error))
2012 		return FALSE;
2013 
2014 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2015 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) {
2016 			dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
2017 					     "invalid message format");
2018 			return FALSE;
2019 		}
2020 
2021 		if (os_strcmp(entry.key, "WPSVendorExtensions") == 0) {
2022 			if (entry.type != DBUS_TYPE_ARRAY ||
2023 			    entry.array_type != WPAS_DBUS_TYPE_BINARRAY ||
2024 			    entry.array_len > MAX_WPS_VENDOR_EXTENSIONS)
2025 				goto error;
2026 
2027 			for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
2028 				if (i < entry.array_len) {
2029 					hapd->conf->wps_vendor_ext[i] =
2030 						entry.binarray_value[i];
2031 					entry.binarray_value[i] = NULL;
2032 				} else
2033 					hapd->conf->wps_vendor_ext[i] = NULL;
2034 			}
2035 
2036 			hostapd_update_wps(hapd);
2037 		} else
2038 			goto error;
2039 
2040 		wpa_dbus_dict_entry_clear(&entry);
2041 	}
2042 
2043 	return TRUE;
2044 
2045 error:
2046 	wpa_dbus_dict_entry_clear(&entry);
2047 	dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
2048 			     "invalid message format");
2049 	return FALSE;
2050 }
2051 
2052 
wpas_dbus_handler_p2p_add_service(DBusMessage * message,struct wpa_supplicant * wpa_s)2053 DBusMessage * wpas_dbus_handler_p2p_add_service(DBusMessage *message,
2054 						struct wpa_supplicant *wpa_s)
2055 {
2056 	DBusMessageIter iter_dict;
2057 	DBusMessage *reply = NULL;
2058 	DBusMessageIter iter;
2059 	struct wpa_dbus_dict_entry entry;
2060 	int upnp = 0;
2061 	int bonjour = 0;
2062 	char *service = NULL;
2063 	struct wpabuf *query = NULL;
2064 	struct wpabuf *resp = NULL;
2065 	u8 version = 0;
2066 
2067 	dbus_message_iter_init(message, &iter);
2068 
2069 	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
2070 		goto error;
2071 
2072 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2073 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2074 			goto error;
2075 
2076 		if (!os_strcmp(entry.key, "service_type") &&
2077 		    (entry.type == DBUS_TYPE_STRING)) {
2078 			if (!os_strcmp(entry.str_value, "upnp"))
2079 				upnp = 1;
2080 			else if (!os_strcmp(entry.str_value, "bonjour"))
2081 				bonjour = 1;
2082 			else
2083 				goto error_clear;
2084 		} else if (!os_strcmp(entry.key, "version") &&
2085 		           entry.type == DBUS_TYPE_INT32) {
2086 			version = entry.uint32_value;
2087 		} else if (!os_strcmp(entry.key, "service") &&
2088 			     (entry.type == DBUS_TYPE_STRING)) {
2089 			service = os_strdup(entry.str_value);
2090 		} else if (!os_strcmp(entry.key, "query")) {
2091 			if ((entry.type != DBUS_TYPE_ARRAY) ||
2092 			    (entry.array_type != DBUS_TYPE_BYTE))
2093 				goto error_clear;
2094 			query = wpabuf_alloc_copy(
2095 				entry.bytearray_value,
2096 				entry.array_len);
2097 		} else if (!os_strcmp(entry.key, "response")) {
2098 			if ((entry.type != DBUS_TYPE_ARRAY) ||
2099 			    (entry.array_type != DBUS_TYPE_BYTE))
2100 				goto error_clear;
2101 			resp = wpabuf_alloc_copy(entry.bytearray_value,
2102 						 entry.array_len);
2103 		}
2104 		wpa_dbus_dict_entry_clear(&entry);
2105 	}
2106 
2107 	if (upnp == 1) {
2108 		if (version <= 0 || service == NULL)
2109 			goto error;
2110 
2111 		if (wpas_p2p_service_add_upnp(wpa_s, version, service) != 0)
2112 			goto error;
2113 
2114 		os_free(service);
2115 		service = NULL;
2116 	} else if (bonjour == 1) {
2117 		if (query == NULL || resp == NULL)
2118 			goto error;
2119 
2120 		if (wpas_p2p_service_add_bonjour(wpa_s, query, resp) < 0)
2121 			goto error;
2122 		query = NULL;
2123 		resp = NULL;
2124 	} else
2125 		goto error;
2126 
2127 	return reply;
2128 error_clear:
2129 	wpa_dbus_dict_entry_clear(&entry);
2130 error:
2131 	os_free(service);
2132 	wpabuf_free(query);
2133 	wpabuf_free(resp);
2134 	return wpas_dbus_error_invalid_args(message, NULL);
2135 }
2136 
2137 
wpas_dbus_handler_p2p_delete_service(DBusMessage * message,struct wpa_supplicant * wpa_s)2138 DBusMessage * wpas_dbus_handler_p2p_delete_service(
2139 	DBusMessage *message, struct wpa_supplicant *wpa_s)
2140 {
2141 	DBusMessageIter iter_dict;
2142 	DBusMessage *reply = NULL;
2143 	DBusMessageIter iter;
2144 	struct wpa_dbus_dict_entry entry;
2145 	int upnp = 0;
2146 	int bonjour = 0;
2147 	int ret = 0;
2148 	char *service = NULL;
2149 	struct wpabuf *query = NULL;
2150 	u8 version = 0;
2151 
2152 	dbus_message_iter_init(message, &iter);
2153 
2154 	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
2155 		goto error;
2156 
2157 	if (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2158 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2159 			goto error;
2160 
2161 		if (!os_strcmp(entry.key, "service_type") &&
2162 		    (entry.type == DBUS_TYPE_STRING)) {
2163 			if (!os_strcmp(entry.str_value, "upnp"))
2164 				upnp = 1;
2165 			else if (!os_strcmp(entry.str_value, "bonjour"))
2166 				bonjour = 1;
2167 			else
2168 				goto error_clear;
2169 			wpa_dbus_dict_entry_clear(&entry);
2170 		}
2171 	}
2172 	if (upnp == 1) {
2173 		while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2174 			if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2175 				goto error;
2176 			if (!os_strcmp(entry.key, "version") &&
2177 			    entry.type == DBUS_TYPE_INT32)
2178 				version = entry.uint32_value;
2179 			else if (!os_strcmp(entry.key, "service") &&
2180 				 entry.type == DBUS_TYPE_STRING)
2181 				service = os_strdup(entry.str_value);
2182 			else
2183 				goto error_clear;
2184 
2185 			wpa_dbus_dict_entry_clear(&entry);
2186 		}
2187 
2188 		if (version <= 0 || service == NULL)
2189 			goto error;
2190 
2191 		ret = wpas_p2p_service_del_upnp(wpa_s, version, service);
2192 		os_free(service);
2193 		if (ret != 0)
2194 			goto error;
2195 	} else if (bonjour == 1) {
2196 		while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2197 			if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2198 				goto error;
2199 
2200 			if (!os_strcmp(entry.key, "query")) {
2201 				if ((entry.type != DBUS_TYPE_ARRAY) ||
2202 				    (entry.array_type != DBUS_TYPE_BYTE))
2203 					goto error_clear;
2204 				query = wpabuf_alloc_copy(
2205 					entry.bytearray_value,
2206 					entry.array_len);
2207 			} else
2208 				goto error_clear;
2209 
2210 			wpa_dbus_dict_entry_clear(&entry);
2211 		}
2212 
2213 		if (query == NULL)
2214 			goto error;
2215 
2216 		ret = wpas_p2p_service_del_bonjour(wpa_s, query);
2217 		if (ret != 0)
2218 			goto error;
2219 		wpabuf_free(query);
2220 	} else
2221 		goto error;
2222 
2223 	return reply;
2224 error_clear:
2225 	wpa_dbus_dict_entry_clear(&entry);
2226 error:
2227 	return wpas_dbus_error_invalid_args(message, NULL);
2228 }
2229 
2230 
wpas_dbus_handler_p2p_flush_service(DBusMessage * message,struct wpa_supplicant * wpa_s)2231 DBusMessage * wpas_dbus_handler_p2p_flush_service(DBusMessage *message,
2232 						  struct wpa_supplicant *wpa_s)
2233 {
2234 	wpas_p2p_service_flush(wpa_s);
2235 	return NULL;
2236 }
2237 
2238 
wpas_dbus_handler_p2p_service_sd_req(DBusMessage * message,struct wpa_supplicant * wpa_s)2239 DBusMessage * wpas_dbus_handler_p2p_service_sd_req(
2240 	DBusMessage *message, struct wpa_supplicant *wpa_s)
2241 {
2242 	DBusMessageIter iter_dict;
2243 	DBusMessage *reply = NULL;
2244 	DBusMessageIter iter;
2245 	struct wpa_dbus_dict_entry entry;
2246 	int upnp = 0;
2247 	char *service = NULL;
2248 	char *peer_object_path = NULL;
2249 	struct wpabuf *tlv = NULL;
2250 	u8 version = 0;
2251 	u64 ref = 0;
2252 	u8 addr_buf[ETH_ALEN], *addr;
2253 
2254 	dbus_message_iter_init(message, &iter);
2255 
2256 	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
2257 		goto error;
2258 
2259 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2260 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2261 			goto error;
2262 		if (!os_strcmp(entry.key, "peer_object") &&
2263 		    entry.type == DBUS_TYPE_OBJECT_PATH) {
2264 			peer_object_path = os_strdup(entry.str_value);
2265 		} else if (!os_strcmp(entry.key, "service_type") &&
2266 			   entry.type == DBUS_TYPE_STRING) {
2267 			if (!os_strcmp(entry.str_value, "upnp"))
2268 				upnp = 1;
2269 			else
2270 				goto error_clear;
2271 		} else if (!os_strcmp(entry.key, "version") &&
2272 			   entry.type == DBUS_TYPE_INT32) {
2273 			version = entry.uint32_value;
2274 		} else if (!os_strcmp(entry.key, "service") &&
2275 			   entry.type == DBUS_TYPE_STRING) {
2276 			service = os_strdup(entry.str_value);
2277 		} else if (!os_strcmp(entry.key, "tlv")) {
2278 			if (entry.type != DBUS_TYPE_ARRAY ||
2279 			    entry.array_type != DBUS_TYPE_BYTE)
2280 				goto error_clear;
2281 			tlv = wpabuf_alloc_copy(entry.bytearray_value,
2282 						entry.array_len);
2283 		} else
2284 			goto error_clear;
2285 
2286 		wpa_dbus_dict_entry_clear(&entry);
2287 	}
2288 
2289 	if (!peer_object_path) {
2290 		addr = NULL;
2291 	} else {
2292 		if (parse_peer_object_path(peer_object_path, addr_buf) < 0 ||
2293 		    !p2p_peer_known(wpa_s->global->p2p, addr_buf))
2294 			goto error;
2295 
2296 		addr = addr_buf;
2297 	}
2298 
2299 	if (upnp == 1) {
2300 		if (version <= 0 || service == NULL)
2301 			goto error;
2302 
2303 		ref = wpas_p2p_sd_request_upnp(wpa_s, addr, version, service);
2304 	} else {
2305 		if (tlv == NULL)
2306 			goto error;
2307 		ref = wpas_p2p_sd_request(wpa_s, addr, tlv);
2308 		wpabuf_free(tlv);
2309 	}
2310 
2311 	if (ref != 0) {
2312 		reply = dbus_message_new_method_return(message);
2313 		dbus_message_append_args(reply, DBUS_TYPE_UINT64,
2314 					 &ref, DBUS_TYPE_INVALID);
2315 	} else {
2316 		reply = wpas_dbus_error_unknown_error(
2317 			message, "Unable to send SD request");
2318 	}
2319 out:
2320 	os_free(service);
2321 	os_free(peer_object_path);
2322 	return reply;
2323 error_clear:
2324 	wpa_dbus_dict_entry_clear(&entry);
2325 error:
2326 	if (tlv)
2327 		wpabuf_free(tlv);
2328 	reply = wpas_dbus_error_invalid_args(message, NULL);
2329 	goto out;
2330 }
2331 
2332 
wpas_dbus_handler_p2p_service_sd_res(DBusMessage * message,struct wpa_supplicant * wpa_s)2333 DBusMessage * wpas_dbus_handler_p2p_service_sd_res(
2334 	DBusMessage *message, struct wpa_supplicant *wpa_s)
2335 {
2336 	DBusMessageIter iter_dict;
2337 	DBusMessage *reply = NULL;
2338 	DBusMessageIter iter;
2339 	struct wpa_dbus_dict_entry entry;
2340 	char *peer_object_path = NULL;
2341 	struct wpabuf *tlv = NULL;
2342 	int freq = 0;
2343 	int dlg_tok = 0;
2344 	u8 addr[ETH_ALEN];
2345 
2346 	dbus_message_iter_init(message, &iter);
2347 
2348 	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
2349 		goto error;
2350 
2351 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2352 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2353 			goto error;
2354 
2355 		if (!os_strcmp(entry.key, "peer_object") &&
2356 		    entry.type == DBUS_TYPE_OBJECT_PATH) {
2357 			peer_object_path = os_strdup(entry.str_value);
2358 		} else if (!os_strcmp(entry.key, "frequency") &&
2359 			   entry.type == DBUS_TYPE_INT32) {
2360 			freq = entry.uint32_value;
2361 		} else if (!os_strcmp(entry.key, "dialog_token") &&
2362 			   entry.type == DBUS_TYPE_UINT32) {
2363 			dlg_tok = entry.uint32_value;
2364 		} else if (!os_strcmp(entry.key, "tlvs")) {
2365 			if (entry.type != DBUS_TYPE_ARRAY ||
2366 			    entry.array_type != DBUS_TYPE_BYTE)
2367 				goto error_clear;
2368 			tlv = wpabuf_alloc_copy(entry.bytearray_value,
2369 						entry.array_len);
2370 		} else
2371 			goto error_clear;
2372 
2373 		wpa_dbus_dict_entry_clear(&entry);
2374 	}
2375 	if (!peer_object_path ||
2376 	    (parse_peer_object_path(peer_object_path, addr) < 0) ||
2377 	    !p2p_peer_known(wpa_s->global->p2p, addr))
2378 		goto error;
2379 
2380 	if (tlv == NULL)
2381 		goto error;
2382 
2383 	wpas_p2p_sd_response(wpa_s, freq, addr, (u8) dlg_tok, tlv);
2384 	wpabuf_free(tlv);
2385 out:
2386 	os_free(peer_object_path);
2387 	return reply;
2388 error_clear:
2389 	wpa_dbus_dict_entry_clear(&entry);
2390 error:
2391 	reply = wpas_dbus_error_invalid_args(message, NULL);
2392 	goto out;
2393 }
2394 
2395 
wpas_dbus_handler_p2p_service_sd_cancel_req(DBusMessage * message,struct wpa_supplicant * wpa_s)2396 DBusMessage * wpas_dbus_handler_p2p_service_sd_cancel_req(
2397 	DBusMessage *message, struct wpa_supplicant *wpa_s)
2398 {
2399 	DBusMessageIter iter;
2400 	u64 req = 0;
2401 
2402 	dbus_message_iter_init(message, &iter);
2403 	dbus_message_iter_get_basic(&iter, &req);
2404 
2405 	if (req == 0)
2406 		goto error;
2407 
2408 	if (!wpas_p2p_sd_cancel_request(wpa_s, req))
2409 		goto error;
2410 
2411 	return NULL;
2412 error:
2413 	return wpas_dbus_error_invalid_args(message, NULL);
2414 }
2415 
2416 
wpas_dbus_handler_p2p_service_update(DBusMessage * message,struct wpa_supplicant * wpa_s)2417 DBusMessage * wpas_dbus_handler_p2p_service_update(
2418 	DBusMessage *message, struct wpa_supplicant *wpa_s)
2419 {
2420 	wpas_p2p_sd_service_update(wpa_s);
2421 	return NULL;
2422 }
2423 
2424 
wpas_dbus_handler_p2p_serv_disc_external(DBusMessage * message,struct wpa_supplicant * wpa_s)2425 DBusMessage * wpas_dbus_handler_p2p_serv_disc_external(
2426 	DBusMessage *message, struct wpa_supplicant *wpa_s)
2427 {
2428 	DBusMessageIter iter;
2429 	int ext = 0;
2430 
2431 	dbus_message_iter_init(message, &iter);
2432 	dbus_message_iter_get_basic(&iter, &ext);
2433 
2434 	wpa_s->p2p_sd_over_ctrl_iface = ext;
2435 
2436 	return NULL;
2437 
2438 }
2439