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