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