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