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