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