2 * WPA Supplicant / dbus-based control interface (P2P)
3 * Copyright (c) 2011-2012, Intel Corporation
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
11 #include "utils/includes.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"
19 #include "dbus_new_handlers.h"
20 #include "dbus_new_handlers_p2p.h"
21 #include "dbus_dict_helpers.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"
28 #include "../p2p_supplicant.h"
29 #include "../wifi_display.h"
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
38 static int parse_peer_object_path(const char *peer_path, u8 addr[ETH_ALEN])
44 p = os_strrchr(peer_path, '/');
48 return hwaddr_compact_aton(p, addr);
53 * wpas_dbus_error_persistent_group_unknown - Return a new PersistentGroupUnknown
55 * @message: Pointer to incoming dbus message this error refers to
56 * Returns: a dbus error message
58 * Convenience function to create and return an invalid persistent group error.
61 wpas_dbus_error_persistent_group_unknown(DBusMessage *message)
63 return dbus_message_new_error(
64 message, WPAS_DBUS_ERROR_NETWORK_UNKNOWN,
65 "There is no such persistent group in this P2P device.");
69 DBusMessage * wpas_dbus_handler_p2p_find(DBusMessage *message,
70 struct wpa_supplicant *wpa_s)
72 struct wpa_dbus_dict_entry entry;
73 DBusMessage *reply = NULL;
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;
80 u8 *req_dev_types = NULL;
82 dbus_message_iter_init(message, &iter);
85 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
88 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
89 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
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)
100 os_free(req_dev_types);
102 os_malloc(WPS_DEV_TYPE_LEN * entry.array_len);
106 for (i = 0; i < entry.array_len; i++) {
107 if (wpabuf_len(entry.binarray_value[i]) !=
110 os_memcpy(req_dev_types + i * WPS_DEV_TYPE_LEN,
111 wpabuf_head(entry.binarray_value[i]),
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;
127 wpa_dbus_dict_entry_clear(&entry);
130 wpa_s = wpa_s->global->p2p_init_wpa_s;
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);
138 wpa_dbus_dict_entry_clear(&entry);
140 os_free(req_dev_types);
141 reply = wpas_dbus_error_invalid_args(message, entry.key);
146 DBusMessage * wpas_dbus_handler_p2p_stop_find(DBusMessage *message,
147 struct wpa_supplicant *wpa_s)
149 wpas_p2p_stop_find(wpa_s->global->p2p_init_wpa_s);
154 DBusMessage * wpas_dbus_handler_p2p_rejectpeer(DBusMessage *message,
155 struct wpa_supplicant *wpa_s)
157 DBusMessageIter iter;
158 char *peer_object_path = NULL;
159 u8 peer_addr[ETH_ALEN];
161 dbus_message_iter_init(message, &iter);
162 dbus_message_iter_get_basic(&iter, &peer_object_path);
164 if (parse_peer_object_path(peer_object_path, peer_addr) < 0)
165 return wpas_dbus_error_invalid_args(message, NULL);
167 wpa_s = wpa_s->global->p2p_init_wpa_s;
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.");
177 DBusMessage * wpas_dbus_handler_p2p_listen(DBusMessage *message,
178 struct wpa_supplicant *wpa_s)
180 dbus_int32_t timeout = 0;
182 if (!dbus_message_get_args(message, NULL, DBUS_TYPE_INT32, &timeout,
184 return wpas_dbus_error_no_memory(message);
186 wpa_s = wpa_s->global->p2p_init_wpa_s;
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");
198 DBusMessage * wpas_dbus_handler_p2p_extendedlisten(
199 DBusMessage *message, struct wpa_supplicant *wpa_s)
201 unsigned int period = 0, interval = 0;
202 struct wpa_dbus_dict_entry entry;
203 DBusMessageIter iter;
204 DBusMessageIter iter_dict;
206 dbus_message_iter_init(message, &iter);
209 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
212 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
213 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
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;
224 wpa_dbus_dict_entry_clear(&entry);
227 wpa_s = wpa_s->global->p2p_init_wpa_s;
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.");
236 wpa_dbus_dict_entry_clear(&entry);
238 return wpas_dbus_error_invalid_args(message, entry.key);
242 DBusMessage * wpas_dbus_handler_p2p_presence_request(
243 DBusMessage *message, struct wpa_supplicant *wpa_s)
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;
250 dbus_message_iter_init(message, &iter);
253 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
256 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
257 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
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;
275 wpa_dbus_dict_entry_clear(&entry);
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.");
285 wpa_dbus_dict_entry_clear(&entry);
287 return wpas_dbus_error_invalid_args(message, entry.key);
291 DBusMessage * wpas_dbus_handler_p2p_group_add(DBusMessage *message,
292 struct wpa_supplicant *wpa_s)
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;
302 unsigned int group_id = 0;
303 struct wpa_ssid *ssid;
305 dbus_message_iter_init(message, &iter);
307 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
310 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
311 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
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;
322 } else if (os_strcmp(entry.key, "persistent_group_object") ==
324 entry.type == DBUS_TYPE_OBJECT_PATH)
325 pg_object_path = os_strdup(entry.str_value);
329 wpa_dbus_dict_entry_clear(&entry);
332 wpa_s = wpa_s->global->p2p_init_wpa_s;
334 if (pg_object_path != NULL) {
338 * A persistent group Object Path is defined meaning we want
339 * to re-invoke a persistent group.
342 iface = wpas_dbus_new_decompose_object_path(
343 pg_object_path, WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART,
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) {
349 wpas_dbus_error_invalid_args(message,
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);
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)
366 if (wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 0, 0, 0,
368 reply = wpas_dbus_error_unknown_error(
370 "Failed to reinvoke a persistent group");
373 } else if (wpas_p2p_group_add(wpa_s, persistent_group, freq, 0, 0))
377 os_free(pg_object_path);
381 wpa_dbus_dict_entry_clear(&entry);
383 reply = wpas_dbus_error_invalid_args(message, NULL);
388 DBusMessage * wpas_dbus_handler_p2p_disconnect(DBusMessage *message,
389 struct wpa_supplicant *wpa_s)
391 if (wpas_p2p_disconnect(wpa_s))
392 return wpas_dbus_error_unknown_error(message,
393 "failed to disconnect");
399 static dbus_bool_t wpa_dbus_p2p_check_enabled(struct wpa_supplicant *wpa_s,
400 DBusMessage *message,
401 DBusMessage **out_reply,
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) {
407 *out_reply = dbus_message_new_error(
408 message, DBUS_ERROR_FAILED,
409 "P2P is not available for this interface");
411 dbus_set_error_const(error, DBUS_ERROR_FAILED,
412 "P2P is not available for this interface");
419 DBusMessage * wpas_dbus_handler_p2p_flush(DBusMessage *message,
420 struct wpa_supplicant *wpa_s)
422 DBusMessage *reply = NULL;
424 if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL))
427 wpa_s = wpa_s->global->p2p_init_wpa_s;
429 os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
430 wpa_s->force_long_sd = 0;
431 p2p_flush(wpa_s->global->p2p);
437 DBusMessage * wpas_dbus_handler_p2p_connect(DBusMessage *message,
438 struct wpa_supplicant *wpa_s)
440 DBusMessageIter iter_dict;
441 DBusMessage *reply = NULL;
442 DBusMessageIter iter;
443 struct wpa_dbus_dict_entry entry;
444 char *peer_object_path = NULL;
445 int persistent_group = 0;
447 int authorize_only = 0;
452 enum p2p_wps_method wps_method = WPS_NOT_READY;
454 char *err_msg = NULL;
457 if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL))
460 dbus_message_iter_init(message, &iter);
462 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
465 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
466 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
469 if (os_strcmp(entry.key, "peer") == 0 &&
470 entry.type == DBUS_TYPE_OBJECT_PATH) {
471 peer_object_path = os_strdup(entry.str_value);
472 } else if (os_strcmp(entry.key, "persistent") == 0 &&
473 entry.type == DBUS_TYPE_BOOLEAN) {
474 persistent_group = entry.bool_value;
475 } else if (os_strcmp(entry.key, "join") == 0 &&
476 entry.type == DBUS_TYPE_BOOLEAN) {
477 join = entry.bool_value;
478 } else if (os_strcmp(entry.key, "authorize_only") == 0 &&
479 entry.type == DBUS_TYPE_BOOLEAN) {
480 authorize_only = entry.bool_value;
481 } else if (os_strcmp(entry.key, "frequency") == 0 &&
482 entry.type == DBUS_TYPE_INT32) {
483 freq = entry.int32_value;
486 } else if (os_strcmp(entry.key, "go_intent") == 0 &&
487 entry.type == DBUS_TYPE_INT32) {
488 go_intent = entry.int32_value;
489 if ((go_intent < 0) || (go_intent > 15))
491 } else if (os_strcmp(entry.key, "wps_method") == 0 &&
492 entry.type == DBUS_TYPE_STRING) {
493 if (os_strcmp(entry.str_value, "pbc") == 0)
494 wps_method = WPS_PBC;
495 else if (os_strcmp(entry.str_value, "pin") == 0)
496 wps_method = WPS_PIN_DISPLAY;
497 else if (os_strcmp(entry.str_value, "display") == 0)
498 wps_method = WPS_PIN_DISPLAY;
499 else if (os_strcmp(entry.str_value, "keypad") == 0)
500 wps_method = WPS_PIN_KEYPAD;
503 } else if (os_strcmp(entry.key, "pin") == 0 &&
504 entry.type == DBUS_TYPE_STRING) {
505 pin = os_strdup(entry.str_value);
509 wpa_dbus_dict_entry_clear(&entry);
512 if (wps_method == WPS_NOT_READY ||
513 parse_peer_object_path(peer_object_path, addr) < 0 ||
514 !p2p_peer_known(wpa_s->global->p2p, addr))
518 * Validate the wps_method specified and the pin value.
520 if ((!pin || !pin[0]) && wps_method == WPS_PIN_KEYPAD)
523 wpa_s = wpa_s->global->p2p_init_wpa_s;
525 new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
526 persistent_group, 0, join, authorize_only,
527 go_intent, freq, -1, 0, 0, 0);
533 os_snprintf(npin, sizeof(npin), "%08d", new_pin);
534 generated_pin = npin;
535 reply = dbus_message_new_method_return(message);
536 dbus_message_append_args(reply, DBUS_TYPE_STRING,
537 &generated_pin, DBUS_TYPE_INVALID);
542 "connect failed due to channel unavailability.";
543 iface = WPAS_DBUS_ERROR_CONNECT_CHANNEL_UNAVAILABLE;
547 err_msg = "connect failed due to unsupported channel.";
548 iface = WPAS_DBUS_ERROR_CONNECT_CHANNEL_UNSUPPORTED;
552 err_msg = "connect failed due to unspecified error.";
553 iface = WPAS_DBUS_ERROR_CONNECT_UNSPECIFIED_ERROR;
559 * Do we need specialized errors corresponding to above
560 * error conditions as against just returning a different
563 reply = dbus_message_new_error(message, iface, err_msg);
567 os_free(peer_object_path);
571 wpa_dbus_dict_entry_clear(&entry);
573 reply = wpas_dbus_error_invalid_args(message, NULL);
579 * wpas_dbus_handler_p2p_cancel - Cancel P2P group formation
580 * @message: Pointer to incoming dbus message
581 * @wpa_s: %wpa_supplicant data structure
582 * Returns: NULL on success or DBus error on failure
584 * Handler for "Cancel" method call. Returns NULL if P2P cancel succeeds or DBus
585 * error on P2P cancel failure
587 DBusMessage * wpas_dbus_handler_p2p_cancel(DBusMessage *message,
588 struct wpa_supplicant *wpa_s)
590 if (wpas_p2p_cancel(wpa_s))
591 return wpas_dbus_error_unknown_error(message,
592 "P2P cancel failed");
598 DBusMessage * wpas_dbus_handler_p2p_invite(DBusMessage *message,
599 struct wpa_supplicant *wpa_s)
601 DBusMessageIter iter_dict;
602 DBusMessage *reply = NULL;
603 DBusMessageIter iter;
604 struct wpa_dbus_dict_entry entry;
605 char *peer_object_path = NULL;
606 char *pg_object_path = NULL;
608 u8 peer_addr[ETH_ALEN];
609 unsigned int group_id = 0;
611 struct wpa_ssid *ssid;
613 if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL))
616 dbus_message_iter_init(message, &iter);
618 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
621 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
622 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
625 if (os_strcmp(entry.key, "peer") == 0 &&
626 entry.type == DBUS_TYPE_OBJECT_PATH) {
627 peer_object_path = os_strdup(entry.str_value);
628 wpa_dbus_dict_entry_clear(&entry);
629 } else if (os_strcmp(entry.key, "persistent_group_object") ==
631 entry.type == DBUS_TYPE_OBJECT_PATH) {
632 pg_object_path = os_strdup(entry.str_value);
634 wpa_dbus_dict_entry_clear(&entry);
636 wpa_dbus_dict_entry_clear(&entry);
641 if (parse_peer_object_path(peer_object_path, peer_addr) < 0 ||
642 !p2p_peer_known(wpa_s->global->p2p, peer_addr))
645 wpa_s = wpa_s->global->p2p_init_wpa_s;
650 * A group ID is defined meaning we want to re-invoke a
654 iface = wpas_dbus_new_decompose_object_path(
656 WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART,
658 if (iface == NULL || net_id_str == NULL ||
659 !wpa_s->parent->dbus_new_path ||
660 os_strcmp(iface, wpa_s->parent->dbus_new_path) != 0) {
661 reply = wpas_dbus_error_invalid_args(message,
666 group_id = strtoul(net_id_str, NULL, 10);
667 if (errno == EINVAL) {
668 reply = wpas_dbus_error_invalid_args(
669 message, pg_object_path);
673 /* Get the SSID structure from the persistent group id */
674 ssid = wpa_config_get_network(wpa_s->conf, group_id);
675 if (ssid == NULL || ssid->disabled != 2)
678 if (wpas_p2p_invite(wpa_s, peer_addr, ssid, NULL, 0, 0, 0, 0) <
680 reply = wpas_dbus_error_unknown_error(
682 "Failed to reinvoke a persistent group");
687 * No group ID means propose to a peer to join my active group
689 if (wpas_p2p_invite_group(wpa_s, wpa_s->ifname,
691 reply = wpas_dbus_error_unknown_error(
692 message, "Failed to join to an active group");
699 os_free(pg_object_path);
700 os_free(peer_object_path);
704 reply = wpas_dbus_error_invalid_args(message, NULL);
709 DBusMessage * wpas_dbus_handler_p2p_prov_disc_req(DBusMessage *message,
710 struct wpa_supplicant *wpa_s)
712 DBusMessageIter iter;
713 char *peer_object_path = NULL;
714 char *config_method = NULL;
715 u8 peer_addr[ETH_ALEN];
717 dbus_message_iter_init(message, &iter);
718 dbus_message_iter_get_basic(&iter, &peer_object_path);
720 if (parse_peer_object_path(peer_object_path, peer_addr) < 0)
721 return wpas_dbus_error_invalid_args(message, NULL);
723 dbus_message_iter_next(&iter);
724 dbus_message_iter_get_basic(&iter, &config_method);
727 * Validation checks on config_method are being duplicated here
728 * to be able to return invalid args reply since the error code
729 * from p2p module are not granular enough (yet).
731 if (os_strcmp(config_method, "display") &&
732 os_strcmp(config_method, "keypad") &&
733 os_strcmp(config_method, "pbc") &&
734 os_strcmp(config_method, "pushbutton"))
735 return wpas_dbus_error_invalid_args(message, NULL);
737 wpa_s = wpa_s->global->p2p_init_wpa_s;
739 if (wpas_p2p_prov_disc(wpa_s, peer_addr, config_method,
740 WPAS_P2P_PD_FOR_GO_NEG, NULL) < 0)
741 return wpas_dbus_error_unknown_error(message,
742 "Failed to send provision discovery request");
749 * P2P Device property accessor methods.
752 dbus_bool_t wpas_dbus_getter_p2p_device_config(DBusMessageIter *iter,
756 struct wpa_supplicant *wpa_s = user_data;
757 DBusMessageIter variant_iter, dict_iter;
758 DBusMessageIter iter_secdev_dict_entry, iter_secdev_dict_val,
759 iter_secdev_dict_array;
760 const char *dev_name;
761 int num_vendor_extensions = 0;
763 const struct wpabuf *vendor_ext[P2P_MAX_WPS_VENDOR_EXT];
765 if (!wpa_dbus_p2p_check_enabled(wpa_s, NULL, NULL, error))
768 wpa_s = wpa_s->global->p2p_init_wpa_s;
770 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
771 "a{sv}", &variant_iter) ||
772 !wpa_dbus_dict_open_write(&variant_iter, &dict_iter))
776 dev_name = wpa_s->conf->device_name;
778 !wpa_dbus_dict_append_string(&dict_iter, "DeviceName", dev_name))
781 /* Primary device type */
782 if (!wpa_dbus_dict_append_byte_array(&dict_iter, "PrimaryDeviceType",
783 (char *) wpa_s->conf->device_type,
787 /* Secondary device types */
788 if (wpa_s->conf->num_sec_device_types) {
789 if (!wpa_dbus_dict_begin_array(&dict_iter,
790 "SecondaryDeviceTypes",
791 DBUS_TYPE_ARRAY_AS_STRING
792 DBUS_TYPE_BYTE_AS_STRING,
793 &iter_secdev_dict_entry,
794 &iter_secdev_dict_val,
795 &iter_secdev_dict_array))
798 for (i = 0; i < wpa_s->conf->num_sec_device_types; i++)
799 wpa_dbus_dict_bin_array_add_element(
800 &iter_secdev_dict_array,
801 wpa_s->conf->sec_device_type[i],
804 if (!wpa_dbus_dict_end_array(&dict_iter,
805 &iter_secdev_dict_entry,
806 &iter_secdev_dict_val,
807 &iter_secdev_dict_array))
811 /* Vendor Extensions */
812 for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
813 if (wpa_s->conf->wps_vendor_ext[i] == NULL)
815 vendor_ext[num_vendor_extensions++] =
816 wpa_s->conf->wps_vendor_ext[i];
819 if ((num_vendor_extensions &&
820 !wpa_dbus_dict_append_wpabuf_array(&dict_iter,
823 num_vendor_extensions)) ||
824 !wpa_dbus_dict_append_uint32(&dict_iter, "GOIntent",
825 wpa_s->conf->p2p_go_intent) ||
826 !wpa_dbus_dict_append_bool(&dict_iter, "PersistentReconnect",
827 wpa_s->conf->persistent_reconnect) ||
828 !wpa_dbus_dict_append_uint32(&dict_iter, "ListenRegClass",
829 wpa_s->conf->p2p_listen_reg_class) ||
830 !wpa_dbus_dict_append_uint32(&dict_iter, "ListenChannel",
831 wpa_s->conf->p2p_listen_channel) ||
832 !wpa_dbus_dict_append_uint32(&dict_iter, "OperRegClass",
833 wpa_s->conf->p2p_oper_reg_class) ||
834 !wpa_dbus_dict_append_uint32(&dict_iter, "OperChannel",
835 wpa_s->conf->p2p_oper_channel) ||
836 (wpa_s->conf->p2p_ssid_postfix &&
837 !wpa_dbus_dict_append_string(&dict_iter, "SsidPostfix",
838 wpa_s->conf->p2p_ssid_postfix)) ||
839 !wpa_dbus_dict_append_bool(&dict_iter, "IntraBss",
840 wpa_s->conf->p2p_intra_bss) ||
841 !wpa_dbus_dict_append_uint32(&dict_iter, "GroupIdle",
842 wpa_s->conf->p2p_group_idle) ||
843 !wpa_dbus_dict_append_uint32(&dict_iter, "disassoc_low_ack",
844 wpa_s->conf->disassoc_low_ack) ||
845 !wpa_dbus_dict_append_bool(&dict_iter, "NoGroupIface",
846 wpa_s->conf->p2p_no_group_iface) ||
847 !wpa_dbus_dict_append_uint32(&dict_iter, "p2p_search_delay",
848 wpa_s->conf->p2p_search_delay) ||
849 !wpa_dbus_dict_close_write(&variant_iter, &dict_iter) ||
850 !dbus_message_iter_close_container(iter, &variant_iter))
856 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
861 dbus_bool_t wpas_dbus_setter_p2p_device_config(DBusMessageIter *iter,
865 struct wpa_supplicant *wpa_s = user_data;
866 DBusMessageIter variant_iter, iter_dict;
867 struct wpa_dbus_dict_entry entry = {.type = DBUS_TYPE_STRING };
870 if (!wpa_dbus_p2p_check_enabled(wpa_s, NULL, NULL, error))
873 wpa_s = wpa_s->global->p2p_init_wpa_s;
875 dbus_message_iter_recurse(iter, &variant_iter);
876 if (!wpa_dbus_dict_open_read(&variant_iter, &iter_dict, error))
879 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
880 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) {
881 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
882 "invalid message format");
886 if (os_strcmp(entry.key, "DeviceName") == 0) {
889 if (entry.type != DBUS_TYPE_STRING)
892 devname = os_strdup(entry.str_value);
894 goto err_no_mem_clear;
896 os_free(wpa_s->conf->device_name);
897 wpa_s->conf->device_name = devname;
899 wpa_s->conf->changed_parameters |=
900 CFG_CHANGED_DEVICE_NAME;
901 } else if (os_strcmp(entry.key, "PrimaryDeviceType") == 0) {
902 if (entry.type != DBUS_TYPE_ARRAY ||
903 entry.array_type != DBUS_TYPE_BYTE ||
904 entry.array_len != WPS_DEV_TYPE_LEN)
907 os_memcpy(wpa_s->conf->device_type,
908 entry.bytearray_value,
910 wpa_s->conf->changed_parameters |=
911 CFG_CHANGED_DEVICE_TYPE;
912 } else if (os_strcmp(entry.key, "SecondaryDeviceTypes") == 0) {
913 if (entry.type != DBUS_TYPE_ARRAY ||
914 entry.array_type != WPAS_DBUS_TYPE_BINARRAY ||
915 entry.array_len > MAX_SEC_DEVICE_TYPES)
918 for (i = 0; i < entry.array_len; i++)
919 if (wpabuf_len(entry.binarray_value[i]) !=
921 goto err_no_mem_clear;
922 for (i = 0; i < entry.array_len; i++)
923 os_memcpy(wpa_s->conf->sec_device_type[i],
924 wpabuf_head(entry.binarray_value[i]),
926 wpa_s->conf->num_sec_device_types = entry.array_len;
927 wpa_s->conf->changed_parameters |=
928 CFG_CHANGED_SEC_DEVICE_TYPE;
929 } else if (os_strcmp(entry.key, "VendorExtension") == 0) {
930 if (entry.type != DBUS_TYPE_ARRAY ||
931 entry.array_type != WPAS_DBUS_TYPE_BINARRAY ||
932 (entry.array_len > P2P_MAX_WPS_VENDOR_EXT))
935 wpa_s->conf->changed_parameters |=
936 CFG_CHANGED_VENDOR_EXTENSION;
938 for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
939 wpabuf_free(wpa_s->conf->wps_vendor_ext[i]);
940 if (i < entry.array_len) {
941 wpa_s->conf->wps_vendor_ext[i] =
942 entry.binarray_value[i];
943 entry.binarray_value[i] = NULL;
945 wpa_s->conf->wps_vendor_ext[i] = NULL;
947 } else if (os_strcmp(entry.key, "GOIntent") == 0 &&
948 entry.type == DBUS_TYPE_UINT32 &&
949 (entry.uint32_value <= 15))
950 wpa_s->conf->p2p_go_intent = entry.uint32_value;
951 else if (os_strcmp(entry.key, "PersistentReconnect") == 0 &&
952 entry.type == DBUS_TYPE_BOOLEAN)
953 wpa_s->conf->persistent_reconnect = entry.bool_value;
954 else if (os_strcmp(entry.key, "ListenRegClass") == 0 &&
955 entry.type == DBUS_TYPE_UINT32) {
956 wpa_s->conf->p2p_listen_reg_class = entry.uint32_value;
957 wpa_s->conf->changed_parameters |=
958 CFG_CHANGED_P2P_LISTEN_CHANNEL;
959 } else if (os_strcmp(entry.key, "ListenChannel") == 0 &&
960 entry.type == DBUS_TYPE_UINT32) {
961 wpa_s->conf->p2p_listen_channel = entry.uint32_value;
962 wpa_s->conf->changed_parameters |=
963 CFG_CHANGED_P2P_LISTEN_CHANNEL;
964 } else if (os_strcmp(entry.key, "OperRegClass") == 0 &&
965 entry.type == DBUS_TYPE_UINT32) {
966 wpa_s->conf->p2p_oper_reg_class = entry.uint32_value;
967 wpa_s->conf->changed_parameters |=
968 CFG_CHANGED_P2P_OPER_CHANNEL;
969 } else if (os_strcmp(entry.key, "OperChannel") == 0 &&
970 entry.type == DBUS_TYPE_UINT32) {
971 wpa_s->conf->p2p_oper_channel = entry.uint32_value;
972 wpa_s->conf->changed_parameters |=
973 CFG_CHANGED_P2P_OPER_CHANNEL;
974 } else if (os_strcmp(entry.key, "SsidPostfix") == 0) {
977 if (entry.type != DBUS_TYPE_STRING)
980 postfix = os_strdup(entry.str_value);
982 goto err_no_mem_clear;
984 os_free(wpa_s->conf->p2p_ssid_postfix);
985 wpa_s->conf->p2p_ssid_postfix = postfix;
987 wpa_s->conf->changed_parameters |=
988 CFG_CHANGED_P2P_SSID_POSTFIX;
989 } else if (os_strcmp(entry.key, "IntraBss") == 0 &&
990 entry.type == DBUS_TYPE_BOOLEAN) {
991 wpa_s->conf->p2p_intra_bss = entry.bool_value;
992 wpa_s->conf->changed_parameters |=
993 CFG_CHANGED_P2P_INTRA_BSS;
994 } else if (os_strcmp(entry.key, "GroupIdle") == 0 &&
995 entry.type == DBUS_TYPE_UINT32)
996 wpa_s->conf->p2p_group_idle = entry.uint32_value;
997 else if (os_strcmp(entry.key, "disassoc_low_ack") == 0 &&
998 entry.type == DBUS_TYPE_UINT32)
999 wpa_s->conf->disassoc_low_ack = entry.uint32_value;
1000 else if (os_strcmp(entry.key, "NoGroupIface") == 0 &&
1001 entry.type == DBUS_TYPE_BOOLEAN)
1002 wpa_s->conf->p2p_no_group_iface = entry.bool_value;
1003 else if (os_strcmp(entry.key, "p2p_search_delay") == 0 &&
1004 entry.type == DBUS_TYPE_UINT32)
1005 wpa_s->conf->p2p_search_delay = entry.uint32_value;
1009 wpa_dbus_dict_entry_clear(&entry);
1012 if (wpa_s->conf->changed_parameters) {
1013 /* Some changed parameters requires to update config*/
1014 wpa_supplicant_update_config(wpa_s);
1020 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
1021 "invalid message format");
1022 wpa_dbus_dict_entry_clear(&entry);
1026 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1027 wpa_dbus_dict_entry_clear(&entry);
1032 dbus_bool_t wpas_dbus_getter_p2p_peers(DBusMessageIter *iter, DBusError *error,
1035 struct wpa_supplicant *wpa_s = user_data;
1036 struct p2p_data *p2p = wpa_s->global->p2p;
1037 int next = 0, i = 0;
1038 int num = 0, out_of_mem = 0;
1040 const struct p2p_peer_info *peer_info = NULL;
1041 dbus_bool_t success = FALSE;
1043 struct dl_list peer_objpath_list;
1044 struct peer_objpath_node {
1045 struct dl_list list;
1046 char path[WPAS_DBUS_OBJECT_PATH_MAX];
1049 char **peer_obj_paths = NULL;
1051 if (!wpa_dbus_p2p_check_enabled(wpa_s, NULL, NULL, error) ||
1052 !wpa_s->parent->parent->dbus_new_path)
1055 dl_list_init(&peer_objpath_list);
1057 /* Get the first peer info */
1058 peer_info = p2p_get_peer_found(p2p, NULL, next);
1060 /* Get next and accumulate them */
1062 while (peer_info != NULL) {
1063 node = os_zalloc(sizeof(struct peer_objpath_node));
1069 addr = peer_info->p2p_device_addr;
1070 os_snprintf(node->path, WPAS_DBUS_OBJECT_PATH_MAX,
1071 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART
1073 wpa_s->parent->parent->dbus_new_path,
1075 dl_list_add_tail(&peer_objpath_list, &node->list);
1078 peer_info = p2p_get_peer_found(p2p, addr, next);
1082 * Now construct the peer object paths in a form suitable for
1083 * array_property_getter helper below.
1085 peer_obj_paths = os_calloc(num, sizeof(char *));
1087 if (!peer_obj_paths) {
1092 dl_list_for_each_safe(node, tmp, &peer_objpath_list,
1093 struct peer_objpath_node, list)
1094 peer_obj_paths[i++] = node->path;
1096 success = wpas_dbus_simple_array_property_getter(iter,
1097 DBUS_TYPE_OBJECT_PATH,
1098 peer_obj_paths, num,
1103 os_free(peer_obj_paths);
1105 dl_list_for_each_safe(node, tmp, &peer_objpath_list,
1106 struct peer_objpath_node, list) {
1107 dl_list_del(&node->list);
1111 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1117 enum wpas_p2p_role {
1118 WPAS_P2P_ROLE_DEVICE,
1120 WPAS_P2P_ROLE_CLIENT,
1123 static enum wpas_p2p_role wpas_get_p2p_role(struct wpa_supplicant *wpa_s)
1125 struct wpa_ssid *ssid = wpa_s->current_ssid;
1128 return WPAS_P2P_ROLE_DEVICE;
1129 if (wpa_s->wpa_state != WPA_COMPLETED)
1130 return WPAS_P2P_ROLE_DEVICE;
1132 switch (ssid->mode) {
1133 case WPAS_MODE_P2P_GO:
1134 case WPAS_MODE_P2P_GROUP_FORMATION:
1135 return WPAS_P2P_ROLE_GO;
1136 case WPAS_MODE_INFRA:
1137 if (ssid->p2p_group)
1138 return WPAS_P2P_ROLE_CLIENT;
1139 return WPAS_P2P_ROLE_DEVICE;
1141 return WPAS_P2P_ROLE_DEVICE;
1146 dbus_bool_t wpas_dbus_getter_p2p_role(DBusMessageIter *iter, DBusError *error,
1149 struct wpa_supplicant *wpa_s = user_data;
1152 switch (wpas_get_p2p_role(wpa_s)) {
1153 case WPAS_P2P_ROLE_GO:
1156 case WPAS_P2P_ROLE_CLIENT:
1164 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &str,
1169 dbus_bool_t wpas_dbus_getter_p2p_group(DBusMessageIter *iter, DBusError *error,
1172 struct wpa_supplicant *wpa_s = user_data;
1173 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX];
1174 char *dbus_groupobj_path = path_buf;
1176 if (wpa_s->dbus_groupobj_path == NULL)
1177 os_snprintf(dbus_groupobj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1180 os_snprintf(dbus_groupobj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1181 "%s", wpa_s->dbus_groupobj_path);
1183 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
1184 &dbus_groupobj_path, error);
1188 dbus_bool_t wpas_dbus_getter_p2p_peergo(DBusMessageIter *iter,
1189 DBusError *error, void *user_data)
1191 struct wpa_supplicant *wpa_s = user_data;
1192 char go_peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1194 if (!wpa_s->parent->parent->dbus_new_path)
1197 if (wpas_get_p2p_role(wpa_s) != WPAS_P2P_ROLE_CLIENT)
1198 os_snprintf(go_peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
1200 os_snprintf(go_peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1201 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
1203 wpa_s->parent->parent->dbus_new_path,
1204 MAC2STR(wpa_s->go_dev_addr));
1206 path = go_peer_obj_path;
1207 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
1213 * Peer object properties accessor methods
1216 dbus_bool_t wpas_dbus_getter_p2p_peer_device_name(DBusMessageIter *iter,
1220 struct peer_handler_args *peer_args = user_data;
1221 const struct p2p_peer_info *info;
1224 if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error))
1227 /* get the peer info */
1228 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1229 peer_args->p2p_device_addr, 0);
1231 dbus_set_error(error, DBUS_ERROR_FAILED,
1232 "failed to find peer");
1236 tmp = os_strdup(info->device_name);
1238 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1242 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp,
1244 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1254 dbus_bool_t wpas_dbus_getter_p2p_peer_primary_device_type(
1255 DBusMessageIter *iter, DBusError *error, void *user_data)
1257 struct peer_handler_args *peer_args = user_data;
1258 const struct p2p_peer_info *info;
1260 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1261 peer_args->p2p_device_addr, 0);
1263 dbus_set_error(error, DBUS_ERROR_FAILED,
1264 "failed to find peer");
1268 if (!wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
1271 WPS_DEV_TYPE_LEN, error)) {
1272 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1280 dbus_bool_t wpas_dbus_getter_p2p_peer_config_method(DBusMessageIter *iter,
1284 struct peer_handler_args *peer_args = user_data;
1285 const struct p2p_peer_info *info;
1287 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1288 peer_args->p2p_device_addr, 0);
1290 dbus_set_error(error, DBUS_ERROR_FAILED,
1291 "failed to find peer");
1295 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
1296 &info->config_methods, error)) {
1297 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1305 dbus_bool_t wpas_dbus_getter_p2p_peer_level(DBusMessageIter *iter,
1309 struct peer_handler_args *peer_args = user_data;
1310 const struct p2p_peer_info *info;
1312 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1313 peer_args->p2p_device_addr, 0);
1315 dbus_set_error(error, DBUS_ERROR_FAILED,
1316 "failed to find peer");
1320 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
1321 &info->level, error)) {
1322 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1330 dbus_bool_t wpas_dbus_getter_p2p_peer_device_capability(DBusMessageIter *iter,
1334 struct peer_handler_args *peer_args = user_data;
1335 const struct p2p_peer_info *info;
1337 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1338 peer_args->p2p_device_addr, 0);
1340 dbus_set_error(error, DBUS_ERROR_FAILED,
1341 "failed to find peer");
1345 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BYTE,
1346 &info->dev_capab, error)) {
1347 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1355 dbus_bool_t wpas_dbus_getter_p2p_peer_group_capability(DBusMessageIter *iter,
1359 struct peer_handler_args *peer_args = user_data;
1360 const struct p2p_peer_info *info;
1362 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1363 peer_args->p2p_device_addr, 0);
1365 dbus_set_error(error, DBUS_ERROR_FAILED,
1366 "failed to find peer");
1370 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BYTE,
1371 &info->group_capab, error)) {
1372 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1380 dbus_bool_t wpas_dbus_getter_p2p_peer_secondary_device_types(
1381 DBusMessageIter *iter, DBusError *error, void *user_data)
1383 struct peer_handler_args *peer_args = user_data;
1384 const struct p2p_peer_info *info;
1385 DBusMessageIter variant_iter, array_iter;
1387 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1388 peer_args->p2p_device_addr, 0);
1390 dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer");
1394 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
1395 DBUS_TYPE_ARRAY_AS_STRING
1396 DBUS_TYPE_ARRAY_AS_STRING
1397 DBUS_TYPE_BYTE_AS_STRING,
1399 !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
1400 DBUS_TYPE_ARRAY_AS_STRING
1401 DBUS_TYPE_BYTE_AS_STRING,
1403 dbus_set_error(error, DBUS_ERROR_FAILED,
1404 "%s: failed to construct message 1", __func__);
1408 if (info->wps_sec_dev_type_list_len) {
1409 const u8 *sec_dev_type_list = info->wps_sec_dev_type_list;
1410 int num_sec_device_types =
1411 info->wps_sec_dev_type_list_len / WPS_DEV_TYPE_LEN;
1413 DBusMessageIter inner_array_iter;
1415 for (i = 0; i < num_sec_device_types; i++) {
1416 if (!dbus_message_iter_open_container(
1417 &array_iter, DBUS_TYPE_ARRAY,
1418 DBUS_TYPE_BYTE_AS_STRING,
1419 &inner_array_iter) ||
1420 !dbus_message_iter_append_fixed_array(
1421 &inner_array_iter, DBUS_TYPE_BYTE,
1422 &sec_dev_type_list, WPS_DEV_TYPE_LEN) ||
1423 !dbus_message_iter_close_container(
1424 &array_iter, &inner_array_iter)) {
1425 dbus_set_error(error, DBUS_ERROR_FAILED,
1426 "%s: failed to construct message 2 (%d)",
1431 sec_dev_type_list += WPS_DEV_TYPE_LEN;
1435 if (!dbus_message_iter_close_container(&variant_iter, &array_iter) ||
1436 !dbus_message_iter_close_container(iter, &variant_iter)) {
1437 dbus_set_error(error, DBUS_ERROR_FAILED,
1438 "%s: failed to construct message 3", __func__);
1446 dbus_bool_t wpas_dbus_getter_p2p_peer_vendor_extension(DBusMessageIter *iter,
1450 struct wpabuf *vendor_extension[P2P_MAX_WPS_VENDOR_EXT];
1451 unsigned int i, num = 0;
1452 struct peer_handler_args *peer_args = user_data;
1453 const struct p2p_peer_info *info;
1455 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1456 peer_args->p2p_device_addr, 0);
1458 dbus_set_error(error, DBUS_ERROR_FAILED,
1459 "failed to find peer");
1463 /* Add WPS vendor extensions attribute */
1464 os_memset(vendor_extension, 0, sizeof(vendor_extension));
1465 for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
1466 if (info->wps_vendor_ext[i] == NULL)
1468 vendor_extension[num] = info->wps_vendor_ext[i];
1472 if (!wpas_dbus_simple_array_array_property_getter(iter, DBUS_TYPE_BYTE,
1481 dbus_bool_t wpas_dbus_getter_p2p_peer_ies(DBusMessageIter *iter,
1482 DBusError *error, void *user_data)
1484 struct peer_handler_args *peer_args = user_data;
1485 const struct p2p_peer_info *info;
1487 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1488 peer_args->p2p_device_addr, 0);
1490 dbus_set_error(error, DBUS_ERROR_FAILED,
1491 "failed to find peer");
1495 if (info->wfd_subelems == NULL)
1496 return wpas_dbus_simple_array_property_getter(iter,
1500 return wpas_dbus_simple_array_property_getter(
1501 iter, DBUS_TYPE_BYTE, (char *) info->wfd_subelems->buf,
1502 info->wfd_subelems->used, error);
1506 dbus_bool_t wpas_dbus_getter_p2p_peer_device_address(DBusMessageIter *iter,
1510 struct peer_handler_args *peer_args = user_data;
1511 const struct p2p_peer_info *info;
1513 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1514 peer_args->p2p_device_addr, 0);
1516 dbus_set_error(error, DBUS_ERROR_FAILED,
1517 "failed to find peer");
1521 return wpas_dbus_simple_array_property_getter(
1522 iter, DBUS_TYPE_BYTE, (char *) info->p2p_device_addr,
1527 struct peer_group_data {
1528 struct wpa_supplicant *wpa_s;
1529 const struct p2p_peer_info *info;
1531 unsigned int nb_paths;
1536 static int match_group_where_peer_is_client(struct p2p_group *group,
1539 struct peer_group_data *data = user_data;
1540 const struct p2p_group_config *cfg;
1541 struct wpa_supplicant *wpa_s_go;
1544 if (!p2p_group_is_client_connected(group, data->info->p2p_device_addr))
1547 cfg = p2p_group_get_config(group);
1549 wpa_s_go = wpas_get_p2p_go_iface(data->wpa_s, cfg->ssid,
1551 if (wpa_s_go == NULL)
1554 paths = os_realloc_array(data->paths, data->nb_paths + 1,
1559 data->paths = paths;
1560 data->paths[data->nb_paths] = wpa_s_go->dbus_groupobj_path;
1566 data->error = ENOMEM;
1571 dbus_bool_t wpas_dbus_getter_p2p_peer_groups(DBusMessageIter *iter,
1575 struct peer_handler_args *peer_args = user_data;
1576 const struct p2p_peer_info *info;
1577 struct peer_group_data data;
1578 struct wpa_supplicant *wpa_s, *wpa_s_go;
1579 dbus_bool_t success = FALSE;
1581 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1582 peer_args->p2p_device_addr, 0);
1584 dbus_set_error(error, DBUS_ERROR_FAILED,
1585 "failed to find peer");
1589 os_memset(&data, 0, sizeof(data));
1591 wpa_s = peer_args->wpa_s;
1592 wpa_s = wpa_s->global->p2p_init_wpa_s;
1594 wpa_s_go = wpas_get_p2p_client_iface(wpa_s, info->p2p_device_addr);
1596 data.paths = os_calloc(1, sizeof(char *));
1597 if (data.paths == NULL)
1599 data.paths[0] = wpa_s_go->dbus_groupobj_path;
1603 data.wpa_s = peer_args->wpa_s;
1606 p2p_loop_on_all_groups(peer_args->wpa_s->global->p2p,
1607 match_group_where_peer_is_client, &data);
1611 if (data.paths == NULL) {
1612 return wpas_dbus_simple_array_property_getter(
1613 iter, DBUS_TYPE_OBJECT_PATH, NULL, 0, error);
1616 success = wpas_dbus_simple_array_property_getter(iter,
1617 DBUS_TYPE_OBJECT_PATH,
1619 data.nb_paths, error);
1623 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1625 os_free(data.paths);
1631 * wpas_dbus_getter_persistent_groups - Get array of persistent group objects
1632 * @iter: Pointer to incoming dbus message iter
1633 * @error: Location to store error on failure
1634 * @user_data: Function specific data
1635 * Returns: TRUE on success, FALSE on failure
1637 * Getter for "PersistentGroups" property.
1639 dbus_bool_t wpas_dbus_getter_persistent_groups(DBusMessageIter *iter,
1643 struct wpa_supplicant *wpa_s = user_data;
1644 struct wpa_ssid *ssid;
1646 unsigned int i = 0, num = 0;
1647 dbus_bool_t success = FALSE;
1649 wpa_s = wpa_s->global->p2p_init_wpa_s;
1650 if (!wpa_s->parent->dbus_new_path)
1653 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
1654 if (network_is_persistent_group(ssid))
1657 paths = os_calloc(num, sizeof(char *));
1659 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1663 /* Loop through configured networks and append object path of each */
1664 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1665 if (!network_is_persistent_group(ssid))
1667 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1668 if (paths[i] == NULL) {
1669 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
1673 /* Construct the object path for this network. */
1674 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
1675 "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%d",
1676 wpa_s->parent->dbus_new_path, ssid->id);
1679 success = wpas_dbus_simple_array_property_getter(iter,
1680 DBUS_TYPE_OBJECT_PATH,
1685 os_free(paths[--i]);
1692 * wpas_dbus_getter_persistent_group_properties - Get options for a persistent
1694 * @iter: Pointer to incoming dbus message iter
1695 * @error: Location to store error on failure
1696 * @user_data: Function specific data
1697 * Returns: TRUE on success, FALSE on failure
1699 * Getter for "Properties" property of a persistent group.
1701 dbus_bool_t wpas_dbus_getter_persistent_group_properties(DBusMessageIter *iter,
1705 struct network_handler_args *net = user_data;
1707 /* Leveraging the fact that persistent group object is still
1708 * represented in same manner as network within.
1710 return wpas_dbus_getter_network_properties(iter, error, net);
1715 * wpas_dbus_setter_persistent_group_properties - Get options for a persistent
1717 * @iter: Pointer to incoming dbus message iter
1718 * @error: Location to store error on failure
1719 * @user_data: Function specific data
1720 * Returns: TRUE on success, FALSE on failure
1722 * Setter for "Properties" property of a persistent group.
1724 dbus_bool_t wpas_dbus_setter_persistent_group_properties(DBusMessageIter *iter,
1728 struct network_handler_args *net = user_data;
1729 struct wpa_ssid *ssid = net->ssid;
1730 DBusMessageIter variant_iter;
1733 * Leveraging the fact that persistent group object is still
1734 * represented in same manner as network within.
1736 dbus_message_iter_recurse(iter, &variant_iter);
1737 return set_network_properties(net->wpa_s, ssid, &variant_iter, error);
1742 * wpas_dbus_new_iface_add_persistent_group - Add a new configured
1744 * @message: Pointer to incoming dbus message
1745 * @wpa_s: wpa_supplicant structure for a network interface
1746 * Returns: A dbus message containing the object path of the new
1749 * Handler function for "AddPersistentGroup" method call of a P2P Device
1752 DBusMessage * wpas_dbus_handler_add_persistent_group(
1753 DBusMessage *message, struct wpa_supplicant *wpa_s)
1755 DBusMessage *reply = NULL;
1756 DBusMessageIter iter;
1757 struct wpa_ssid *ssid = NULL;
1758 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf;
1761 dbus_message_iter_init(message, &iter);
1763 wpa_s = wpa_s->global->p2p_init_wpa_s;
1764 if (wpa_s->parent->dbus_new_path)
1765 ssid = wpa_config_add_network(wpa_s->conf);
1767 wpa_printf(MSG_ERROR,
1768 "dbus: %s: Cannot add new persistent group",
1770 reply = wpas_dbus_error_unknown_error(
1772 "wpa_supplicant could not add a persistent group on this interface.");
1776 /* Mark the ssid as being a persistent group before the notification */
1778 ssid->p2p_persistent_group = 1;
1779 wpas_notify_persistent_group_added(wpa_s, ssid);
1781 wpa_config_set_network_defaults(ssid);
1783 dbus_error_init(&error);
1784 if (!set_network_properties(wpa_s, ssid, &iter, &error)) {
1785 wpa_printf(MSG_DEBUG,
1786 "dbus: %s: Control interface could not set persistent group properties",
1788 reply = wpas_dbus_reply_new_from_error(
1789 message, &error, DBUS_ERROR_INVALID_ARGS,
1790 "Failed to set network properties");
1791 dbus_error_free(&error);
1795 /* Construct the object path for this network. */
1796 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
1797 "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%d",
1798 wpa_s->parent->dbus_new_path, ssid->id);
1800 reply = dbus_message_new_method_return(message);
1801 if (reply == NULL) {
1802 reply = wpas_dbus_error_no_memory(message);
1805 if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
1806 DBUS_TYPE_INVALID)) {
1807 dbus_message_unref(reply);
1808 reply = wpas_dbus_error_no_memory(message);
1816 wpas_notify_persistent_group_removed(wpa_s, ssid);
1817 wpa_config_remove_network(wpa_s->conf, ssid->id);
1824 * wpas_dbus_handler_remove_persistent_group - Remove a configured persistent
1826 * @message: Pointer to incoming dbus message
1827 * @wpa_s: wpa_supplicant structure for a network interface
1828 * Returns: NULL on success or dbus error on failure
1830 * Handler function for "RemovePersistentGroup" method call of a P2P Device
1833 DBusMessage * wpas_dbus_handler_remove_persistent_group(
1834 DBusMessage *message, struct wpa_supplicant *wpa_s)
1836 DBusMessage *reply = NULL;
1838 char *iface = NULL, *persistent_group_id;
1840 struct wpa_ssid *ssid;
1842 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
1845 wpa_s = wpa_s->global->p2p_init_wpa_s;
1848 * Extract the network ID and ensure the network is actually a child of
1851 iface = wpas_dbus_new_decompose_object_path(
1852 op, WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART,
1853 &persistent_group_id);
1854 if (iface == NULL || persistent_group_id == NULL ||
1855 !wpa_s->parent->dbus_new_path ||
1856 os_strcmp(iface, wpa_s->parent->dbus_new_path) != 0) {
1857 reply = wpas_dbus_error_invalid_args(message, op);
1861 id = strtoul(persistent_group_id, NULL, 10);
1862 if (errno == EINVAL) {
1863 reply = wpas_dbus_error_invalid_args(message, op);
1867 ssid = wpa_config_get_network(wpa_s->conf, id);
1869 reply = wpas_dbus_error_persistent_group_unknown(message);
1873 wpas_notify_persistent_group_removed(wpa_s, ssid);
1875 if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
1876 wpa_printf(MSG_ERROR,
1877 "dbus: %s: error occurred when removing persistent group %d",
1879 reply = wpas_dbus_error_unknown_error(
1881 "error removing the specified persistent group on this interface.");
1891 static void remove_persistent_group(struct wpa_supplicant *wpa_s,
1892 struct wpa_ssid *ssid)
1894 wpas_notify_persistent_group_removed(wpa_s, ssid);
1896 if (wpa_config_remove_network(wpa_s->conf, ssid->id) < 0) {
1897 wpa_printf(MSG_ERROR,
1898 "dbus: %s: error occurred when removing persistent group %d",
1899 __func__, ssid->id);
1906 * wpas_dbus_handler_remove_all_persistent_groups - Remove all configured
1908 * @message: Pointer to incoming dbus message
1909 * @wpa_s: wpa_supplicant structure for a network interface
1910 * Returns: NULL on success or dbus error on failure
1912 * Handler function for "RemoveAllPersistentGroups" method call of a
1913 * P2P Device interface.
1915 DBusMessage * wpas_dbus_handler_remove_all_persistent_groups(
1916 DBusMessage *message, struct wpa_supplicant *wpa_s)
1918 struct wpa_ssid *ssid, *next;
1919 struct wpa_config *config;
1921 wpa_s = wpa_s->global->p2p_init_wpa_s;
1923 config = wpa_s->conf;
1924 ssid = config->ssid;
1927 if (network_is_persistent_group(ssid))
1928 remove_persistent_group(wpa_s, ssid);
1936 * Group object properties accessor methods
1939 dbus_bool_t wpas_dbus_getter_p2p_group_members(DBusMessageIter *iter,
1943 struct wpa_supplicant *wpa_s = user_data;
1944 struct wpa_ssid *ssid;
1945 unsigned int num_members;
1950 dbus_bool_t success = FALSE;
1952 if (!wpa_s->parent->parent->dbus_new_path)
1955 /* Verify correct role for this property */
1956 if (wpas_get_p2p_role(wpa_s) != WPAS_P2P_ROLE_GO) {
1957 return wpas_dbus_simple_array_property_getter(
1958 iter, DBUS_TYPE_OBJECT_PATH, NULL, 0, error);
1961 ssid = wpa_s->conf->ssid;
1962 /* At present WPAS P2P_GO mode only applicable for p2p_go */
1963 if (ssid->mode != WPAS_MODE_P2P_GO &&
1964 ssid->mode != WPAS_MODE_AP &&
1965 ssid->mode != WPAS_MODE_P2P_GROUP_FORMATION)
1968 num_members = p2p_get_group_num_members(wpa_s->p2p_group);
1970 paths = os_calloc(num_members, sizeof(char *));
1975 while ((addr = p2p_iterate_group_members(wpa_s->p2p_group, &next))) {
1976 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1979 os_snprintf(paths[i], WPAS_DBUS_OBJECT_PATH_MAX,
1980 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART
1982 wpa_s->parent->parent->dbus_new_path,
1987 success = wpas_dbus_simple_array_property_getter(iter,
1988 DBUS_TYPE_OBJECT_PATH,
1992 for (i = 0; i < num_members; i++)
1998 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
2000 for (i = 0; i < num_members; i++)
2008 dbus_bool_t wpas_dbus_getter_p2p_group_ssid(DBusMessageIter *iter,
2009 DBusError *error, void *user_data)
2011 struct wpa_supplicant *wpa_s = user_data;
2013 if (wpa_s->current_ssid == NULL)
2015 return wpas_dbus_simple_array_property_getter(
2016 iter, DBUS_TYPE_BYTE, wpa_s->current_ssid->ssid,
2017 wpa_s->current_ssid->ssid_len, error);
2021 dbus_bool_t wpas_dbus_getter_p2p_group_bssid(DBusMessageIter *iter,
2025 struct wpa_supplicant *wpa_s = user_data;
2026 u8 role = wpas_get_p2p_role(wpa_s);
2029 if (role == WPAS_P2P_ROLE_CLIENT) {
2030 if (wpa_s->current_ssid == NULL)
2032 p_bssid = wpa_s->current_ssid->bssid;
2034 if (wpa_s->ap_iface == NULL)
2036 p_bssid = wpa_s->ap_iface->bss[0]->own_addr;
2039 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
2045 dbus_bool_t wpas_dbus_getter_p2p_group_frequency(DBusMessageIter *iter,
2049 struct wpa_supplicant *wpa_s = user_data;
2051 u8 role = wpas_get_p2p_role(wpa_s);
2053 if (role == WPAS_P2P_ROLE_CLIENT) {
2054 if (wpa_s->go_params == NULL)
2056 op_freq = wpa_s->go_params->freq;
2058 if (wpa_s->ap_iface == NULL)
2060 op_freq = wpa_s->ap_iface->freq;
2063 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
2068 dbus_bool_t wpas_dbus_getter_p2p_group_passphrase(DBusMessageIter *iter,
2072 struct wpa_supplicant *wpa_s = user_data;
2074 struct wpa_ssid *ssid = wpa_s->current_ssid;
2079 p_pass = ssid->passphrase;
2083 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
2089 dbus_bool_t wpas_dbus_getter_p2p_group_psk(DBusMessageIter *iter,
2090 DBusError *error, void *user_data)
2092 struct wpa_supplicant *wpa_s = user_data;
2095 struct wpa_ssid *ssid = wpa_s->current_ssid;
2100 if (ssid->psk_set) {
2102 psk_len = sizeof(ssid->psk);
2105 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
2106 p_psk, psk_len, error);
2110 dbus_bool_t wpas_dbus_getter_p2p_group_vendor_ext(DBusMessageIter *iter,
2114 struct wpa_supplicant *wpa_s = user_data;
2115 struct hostapd_data *hapd;
2116 struct wpabuf *vendor_ext[MAX_WPS_VENDOR_EXTENSIONS];
2117 unsigned int i, num_vendor_ext = 0;
2119 os_memset(vendor_ext, 0, sizeof(vendor_ext));
2121 /* Verify correct role for this property */
2122 if (wpas_get_p2p_role(wpa_s) == WPAS_P2P_ROLE_GO) {
2123 if (wpa_s->ap_iface == NULL)
2125 hapd = wpa_s->ap_iface->bss[0];
2127 /* Parse WPS Vendor Extensions sent in Beacon/Probe Response */
2128 for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
2129 if (hapd->conf->wps_vendor_ext[i] == NULL)
2131 vendor_ext[num_vendor_ext++] =
2132 hapd->conf->wps_vendor_ext[i];
2136 /* Return vendor extensions or no data */
2137 return wpas_dbus_simple_array_array_property_getter(iter,
2145 dbus_bool_t wpas_dbus_setter_p2p_group_vendor_ext(DBusMessageIter *iter,
2149 struct wpa_supplicant *wpa_s = user_data;
2150 DBusMessageIter variant_iter, iter_dict, array_iter, sub;
2151 struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
2153 struct hostapd_data *hapd = NULL;
2155 if (wpas_get_p2p_role(wpa_s) == WPAS_P2P_ROLE_GO &&
2156 wpa_s->ap_iface != NULL)
2157 hapd = wpa_s->ap_iface->bss[0];
2161 dbus_message_iter_recurse(iter, &variant_iter);
2162 if (dbus_message_iter_get_arg_type(&variant_iter) != DBUS_TYPE_ARRAY)
2166 * This is supposed to be array of bytearrays (aay), but the earlier
2167 * implementation used a dict with "WPSVendorExtensions" as the key in
2168 * this setter function which does not match the format used by the
2169 * getter function. For backwards compatibility, allow both formats to
2170 * be used in the setter.
2172 if (dbus_message_iter_get_element_type(&variant_iter) ==
2174 /* This is the proper format matching the getter */
2175 struct wpabuf *vals[MAX_WPS_VENDOR_EXTENSIONS];
2177 dbus_message_iter_recurse(&variant_iter, &array_iter);
2179 if (dbus_message_iter_get_arg_type(&array_iter) !=
2181 dbus_message_iter_get_element_type(&array_iter) !=
2183 wpa_printf(MSG_DEBUG,
2184 "dbus: Not an array of array of bytes");
2189 os_memset(vals, 0, sizeof(vals));
2191 while (dbus_message_iter_get_arg_type(&array_iter) ==
2196 if (i == MAX_WPS_VENDOR_EXTENSIONS) {
2197 wpa_printf(MSG_DEBUG,
2198 "dbus: Too many WPSVendorExtensions values");
2199 i = MAX_WPS_VENDOR_EXTENSIONS + 1;
2203 dbus_message_iter_recurse(&array_iter, &sub);
2204 dbus_message_iter_get_fixed_array(&sub, &val, &len);
2205 wpa_hexdump(MSG_DEBUG, "dbus: WPSVendorExtentions[]",
2207 vals[i] = wpabuf_alloc_copy(val, len);
2208 if (vals[i] == NULL) {
2209 i = MAX_WPS_VENDOR_EXTENSIONS + 1;
2213 dbus_message_iter_next(&array_iter);
2216 if (i > MAX_WPS_VENDOR_EXTENSIONS) {
2217 for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++)
2218 wpabuf_free(vals[i]);
2222 for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
2223 wpabuf_free(hapd->conf->wps_vendor_ext[i]);
2224 hapd->conf->wps_vendor_ext[i] = vals[i];
2227 hostapd_update_wps(hapd);
2232 if (dbus_message_iter_get_element_type(&variant_iter) !=
2233 DBUS_TYPE_DICT_ENTRY)
2236 wpa_printf(MSG_DEBUG,
2237 "dbus: Try to use backwards compatibility version of WPSVendorExtensions setter");
2238 if (!wpa_dbus_dict_open_read(&variant_iter, &iter_dict, error))
2241 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2242 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) {
2243 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
2244 "invalid message format");
2248 if (os_strcmp(entry.key, "WPSVendorExtensions") == 0) {
2249 if (entry.type != DBUS_TYPE_ARRAY ||
2250 entry.array_type != WPAS_DBUS_TYPE_BINARRAY ||
2251 entry.array_len > MAX_WPS_VENDOR_EXTENSIONS)
2254 for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
2255 wpabuf_free(hapd->conf->wps_vendor_ext[i]);
2256 if (i < entry.array_len) {
2257 hapd->conf->wps_vendor_ext[i] =
2258 entry.binarray_value[i];
2259 entry.binarray_value[i] = NULL;
2261 hapd->conf->wps_vendor_ext[i] = NULL;
2264 hostapd_update_wps(hapd);
2268 wpa_dbus_dict_entry_clear(&entry);
2274 wpa_dbus_dict_entry_clear(&entry);
2275 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
2276 "invalid message format");
2281 DBusMessage * wpas_dbus_handler_p2p_add_service(DBusMessage *message,
2282 struct wpa_supplicant *wpa_s)
2284 DBusMessageIter iter_dict;
2285 DBusMessage *reply = NULL;
2286 DBusMessageIter iter;
2287 struct wpa_dbus_dict_entry entry;
2290 char *service = NULL;
2291 struct wpabuf *query = NULL;
2292 struct wpabuf *resp = NULL;
2295 dbus_message_iter_init(message, &iter);
2297 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
2300 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2301 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2304 if (os_strcmp(entry.key, "service_type") == 0 &&
2305 entry.type == DBUS_TYPE_STRING) {
2306 if (os_strcmp(entry.str_value, "upnp") == 0)
2308 else if (os_strcmp(entry.str_value, "bonjour") == 0)
2312 } else if (os_strcmp(entry.key, "version") == 0 &&
2313 entry.type == DBUS_TYPE_INT32) {
2314 version = entry.uint32_value;
2315 } else if (os_strcmp(entry.key, "service") == 0 &&
2316 entry.type == DBUS_TYPE_STRING) {
2318 service = os_strdup(entry.str_value);
2319 } else if (os_strcmp(entry.key, "query") == 0) {
2320 if (entry.type != DBUS_TYPE_ARRAY ||
2321 entry.array_type != DBUS_TYPE_BYTE)
2323 query = wpabuf_alloc_copy(
2324 entry.bytearray_value,
2326 } else if (os_strcmp(entry.key, "response") == 0) {
2327 if (entry.type != DBUS_TYPE_ARRAY ||
2328 entry.array_type != DBUS_TYPE_BYTE)
2330 resp = wpabuf_alloc_copy(entry.bytearray_value,
2333 wpa_dbus_dict_entry_clear(&entry);
2337 if (version <= 0 || service == NULL)
2340 if (wpas_p2p_service_add_upnp(wpa_s, version, service) != 0)
2343 } else if (bonjour == 1) {
2344 if (query == NULL || resp == NULL)
2347 if (wpas_p2p_service_add_bonjour(wpa_s, query, resp) < 0)
2357 wpa_dbus_dict_entry_clear(&entry);
2362 return wpas_dbus_error_invalid_args(message, NULL);
2366 DBusMessage * wpas_dbus_handler_p2p_delete_service(
2367 DBusMessage *message, struct wpa_supplicant *wpa_s)
2369 DBusMessageIter iter_dict;
2370 DBusMessage *reply = NULL;
2371 DBusMessageIter iter;
2372 struct wpa_dbus_dict_entry entry;
2376 char *service = NULL;
2377 struct wpabuf *query = NULL;
2380 dbus_message_iter_init(message, &iter);
2382 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
2385 if (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2386 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2389 if (os_strcmp(entry.key, "service_type") == 0 &&
2390 entry.type == DBUS_TYPE_STRING) {
2391 if (os_strcmp(entry.str_value, "upnp") == 0)
2393 else if (os_strcmp(entry.str_value, "bonjour") == 0)
2397 wpa_dbus_dict_entry_clear(&entry);
2401 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2402 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2404 if (os_strcmp(entry.key, "version") == 0 &&
2405 entry.type == DBUS_TYPE_INT32)
2406 version = entry.uint32_value;
2407 else if (os_strcmp(entry.key, "service") == 0 &&
2408 entry.type == DBUS_TYPE_STRING) {
2410 service = os_strdup(entry.str_value);
2414 wpa_dbus_dict_entry_clear(&entry);
2417 if (version <= 0 || service == NULL)
2420 ret = wpas_p2p_service_del_upnp(wpa_s, version, service);
2423 } else if (bonjour == 1) {
2424 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2425 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2428 if (os_strcmp(entry.key, "query") == 0) {
2429 if (entry.type != DBUS_TYPE_ARRAY ||
2430 entry.array_type != DBUS_TYPE_BYTE)
2433 query = wpabuf_alloc_copy(
2434 entry.bytearray_value,
2439 wpa_dbus_dict_entry_clear(&entry);
2445 ret = wpas_p2p_service_del_bonjour(wpa_s, query);
2455 wpa_dbus_dict_entry_clear(&entry);
2459 return wpas_dbus_error_invalid_args(message, NULL);
2463 DBusMessage * wpas_dbus_handler_p2p_flush_service(DBusMessage *message,
2464 struct wpa_supplicant *wpa_s)
2466 wpas_p2p_service_flush(wpa_s);
2471 DBusMessage * wpas_dbus_handler_p2p_service_sd_req(
2472 DBusMessage *message, struct wpa_supplicant *wpa_s)
2474 DBusMessageIter iter_dict;
2475 DBusMessage *reply = NULL;
2476 DBusMessageIter iter;
2477 struct wpa_dbus_dict_entry entry;
2479 char *service = NULL;
2480 char *peer_object_path = NULL;
2481 struct wpabuf *tlv = NULL;
2484 u8 addr_buf[ETH_ALEN], *addr;
2486 dbus_message_iter_init(message, &iter);
2488 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
2491 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2492 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2494 if (os_strcmp(entry.key, "peer_object") == 0 &&
2495 entry.type == DBUS_TYPE_OBJECT_PATH) {
2496 peer_object_path = os_strdup(entry.str_value);
2497 } else if (os_strcmp(entry.key, "service_type") == 0 &&
2498 entry.type == DBUS_TYPE_STRING) {
2499 if (os_strcmp(entry.str_value, "upnp") == 0)
2503 } else if (os_strcmp(entry.key, "version") == 0 &&
2504 entry.type == DBUS_TYPE_INT32) {
2505 version = entry.uint32_value;
2506 } else if (os_strcmp(entry.key, "service") == 0 &&
2507 entry.type == DBUS_TYPE_STRING) {
2508 service = os_strdup(entry.str_value);
2509 } else if (os_strcmp(entry.key, "tlv") == 0) {
2510 if (entry.type != DBUS_TYPE_ARRAY ||
2511 entry.array_type != DBUS_TYPE_BYTE)
2513 tlv = wpabuf_alloc_copy(entry.bytearray_value,
2518 wpa_dbus_dict_entry_clear(&entry);
2521 if (!peer_object_path) {
2524 if (parse_peer_object_path(peer_object_path, addr_buf) < 0 ||
2525 !p2p_peer_known(wpa_s->global->p2p, addr_buf))
2532 if (version <= 0 || service == NULL)
2535 ref = wpas_p2p_sd_request_upnp(wpa_s, addr, version, service);
2539 ref = wpas_p2p_sd_request(wpa_s, addr, tlv);
2544 reply = dbus_message_new_method_return(message);
2545 dbus_message_append_args(reply, DBUS_TYPE_UINT64,
2546 &ref, DBUS_TYPE_INVALID);
2548 reply = wpas_dbus_error_unknown_error(
2549 message, "Unable to send SD request");
2553 os_free(peer_object_path);
2556 wpa_dbus_dict_entry_clear(&entry);
2560 reply = wpas_dbus_error_invalid_args(message, NULL);
2565 DBusMessage * wpas_dbus_handler_p2p_service_sd_res(
2566 DBusMessage *message, struct wpa_supplicant *wpa_s)
2568 DBusMessageIter iter_dict;
2569 DBusMessage *reply = NULL;
2570 DBusMessageIter iter;
2571 struct wpa_dbus_dict_entry entry;
2572 char *peer_object_path = NULL;
2573 struct wpabuf *tlv = NULL;
2578 dbus_message_iter_init(message, &iter);
2580 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
2583 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2584 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2587 if (os_strcmp(entry.key, "peer_object") == 0 &&
2588 entry.type == DBUS_TYPE_OBJECT_PATH) {
2589 peer_object_path = os_strdup(entry.str_value);
2590 } else if (os_strcmp(entry.key, "frequency") == 0 &&
2591 entry.type == DBUS_TYPE_INT32) {
2592 freq = entry.uint32_value;
2593 } else if (os_strcmp(entry.key, "dialog_token") == 0 &&
2594 (entry.type == DBUS_TYPE_UINT32 ||
2595 entry.type == DBUS_TYPE_INT32)) {
2596 dlg_tok = entry.uint32_value;
2597 } else if (os_strcmp(entry.key, "tlvs") == 0) {
2598 if (entry.type != DBUS_TYPE_ARRAY ||
2599 entry.array_type != DBUS_TYPE_BYTE)
2601 tlv = wpabuf_alloc_copy(entry.bytearray_value,
2606 wpa_dbus_dict_entry_clear(&entry);
2608 if (parse_peer_object_path(peer_object_path, addr) < 0 ||
2609 !p2p_peer_known(wpa_s->global->p2p, addr) ||
2613 wpas_p2p_sd_response(wpa_s, freq, addr, (u8) dlg_tok, tlv);
2616 os_free(peer_object_path);
2619 wpa_dbus_dict_entry_clear(&entry);
2621 reply = wpas_dbus_error_invalid_args(message, NULL);
2626 DBusMessage * wpas_dbus_handler_p2p_service_sd_cancel_req(
2627 DBusMessage *message, struct wpa_supplicant *wpa_s)
2629 DBusMessageIter iter;
2632 dbus_message_iter_init(message, &iter);
2633 dbus_message_iter_get_basic(&iter, &req);
2638 if (wpas_p2p_sd_cancel_request(wpa_s, req) < 0)
2643 return wpas_dbus_error_invalid_args(message, NULL);
2647 DBusMessage * wpas_dbus_handler_p2p_service_update(
2648 DBusMessage *message, struct wpa_supplicant *wpa_s)
2650 wpas_p2p_sd_service_update(wpa_s);
2655 DBusMessage * wpas_dbus_handler_p2p_serv_disc_external(
2656 DBusMessage *message, struct wpa_supplicant *wpa_s)
2658 DBusMessageIter iter;
2661 dbus_message_iter_init(message, &iter);
2662 dbus_message_iter_get_basic(&iter, &ext);
2664 wpa_s->p2p_sd_over_ctrl_iface = ext;
2671 #ifdef CONFIG_WIFI_DISPLAY
2673 dbus_bool_t wpas_dbus_getter_global_wfd_ies(DBusMessageIter *iter,
2674 DBusError *error, void *user_data)
2676 struct wpa_global *global = user_data;
2680 ie = wifi_display_get_wfd_ie(global);
2682 return wpas_dbus_simple_array_property_getter(iter,
2686 ret = wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
2688 wpabuf_len(ie), error);
2695 dbus_bool_t wpas_dbus_setter_global_wfd_ies(DBusMessageIter *iter,
2696 DBusError *error, void *user_data)
2698 struct wpa_global *global = user_data;
2699 DBusMessageIter variant, array;
2700 struct wpabuf *ie = NULL;
2704 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_VARIANT)
2707 dbus_message_iter_recurse(iter, &variant);
2708 if (dbus_message_iter_get_arg_type(&variant) != DBUS_TYPE_ARRAY)
2711 dbus_message_iter_recurse(&variant, &array);
2712 dbus_message_iter_get_fixed_array(&array, &data, &len);
2714 wifi_display_enable(global, 0);
2715 wifi_display_deinit(global);
2720 ie = wpabuf_alloc(len);
2724 wpabuf_put_data(ie, data, len);
2725 if (wifi_display_subelem_set_from_ies(global, ie) != 0)
2728 if (global->wifi_display == 0)
2729 wifi_display_enable(global, 1);
2737 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
2738 "invalid message format");
2742 #endif /* CONFIG_WIFI_DISPLAY */