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