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