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);
131 wpa_s = wpa_s->p2p_dev;
133 wpas_p2p_find(wpa_s, timeout, type, num_req_dev_types, req_dev_types,
135 os_free(req_dev_types);
139 wpa_dbus_dict_entry_clear(&entry);
141 os_free(req_dev_types);
142 reply = wpas_dbus_error_invalid_args(message, entry.key);
147 DBusMessage * wpas_dbus_handler_p2p_stop_find(DBusMessage *message,
148 struct wpa_supplicant *wpa_s)
151 wpa_s = wpa_s->p2p_dev;
153 wpas_p2p_stop_find(wpa_s);
158 DBusMessage * wpas_dbus_handler_p2p_rejectpeer(DBusMessage *message,
159 struct wpa_supplicant *wpa_s)
161 DBusMessageIter iter;
162 char *peer_object_path = NULL;
163 u8 peer_addr[ETH_ALEN];
165 dbus_message_iter_init(message, &iter);
166 dbus_message_iter_get_basic(&iter, &peer_object_path);
168 if (parse_peer_object_path(peer_object_path, peer_addr) < 0)
169 return wpas_dbus_error_invalid_args(message, NULL);
172 wpa_s = wpa_s->p2p_dev;
174 if (wpas_p2p_reject(wpa_s, peer_addr) < 0)
175 return wpas_dbus_error_unknown_error(message,
176 "Failed to call wpas_p2p_reject method.");
182 DBusMessage * wpas_dbus_handler_p2p_listen(DBusMessage *message,
183 struct wpa_supplicant *wpa_s)
185 dbus_int32_t timeout = 0;
187 if (!dbus_message_get_args(message, NULL, DBUS_TYPE_INT32, &timeout,
189 return wpas_dbus_error_no_memory(message);
192 wpa_s = wpa_s->p2p_dev;
194 if (wpas_p2p_listen(wpa_s, (unsigned int) timeout)) {
195 return dbus_message_new_error(message,
196 WPAS_DBUS_ERROR_UNKNOWN_ERROR,
197 "Could not start P2P listen");
204 DBusMessage * wpas_dbus_handler_p2p_extendedlisten(
205 DBusMessage *message, struct wpa_supplicant *wpa_s)
207 unsigned int period = 0, interval = 0;
208 struct wpa_dbus_dict_entry entry;
209 DBusMessageIter iter;
210 DBusMessageIter iter_dict;
212 dbus_message_iter_init(message, &iter);
215 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
218 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
219 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
222 if (os_strcmp(entry.key, "period") == 0 &&
223 entry.type == DBUS_TYPE_INT32)
224 period = entry.uint32_value;
225 else if (os_strcmp(entry.key, "interval") == 0 &&
226 entry.type == DBUS_TYPE_INT32)
227 interval = entry.uint32_value;
230 wpa_dbus_dict_entry_clear(&entry);
234 wpa_s = wpa_s->p2p_dev;
236 if (wpas_p2p_ext_listen(wpa_s, period, interval))
237 return wpas_dbus_error_unknown_error(
238 message, "failed to initiate a p2p_ext_listen.");
243 wpa_dbus_dict_entry_clear(&entry);
245 return wpas_dbus_error_invalid_args(message, entry.key);
249 DBusMessage * wpas_dbus_handler_p2p_presence_request(
250 DBusMessage *message, struct wpa_supplicant *wpa_s)
252 unsigned int dur1 = 0, int1 = 0, dur2 = 0, int2 = 0;
253 struct wpa_dbus_dict_entry entry;
254 DBusMessageIter iter;
255 DBusMessageIter iter_dict;
257 dbus_message_iter_init(message, &iter);
260 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
263 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
264 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
267 if (os_strcmp(entry.key, "duration1") == 0 &&
268 entry.type == DBUS_TYPE_INT32)
269 dur1 = entry.uint32_value;
270 else if (os_strcmp(entry.key, "interval1") == 0 &&
271 entry.type == DBUS_TYPE_INT32)
272 int1 = entry.uint32_value;
273 else if (os_strcmp(entry.key, "duration2") == 0 &&
274 entry.type == DBUS_TYPE_INT32)
275 dur2 = entry.uint32_value;
276 else if (os_strcmp(entry.key, "interval2") == 0 &&
277 entry.type == DBUS_TYPE_INT32)
278 int2 = entry.uint32_value;
282 wpa_dbus_dict_entry_clear(&entry);
286 wpa_s = wpa_s->p2p_dev;
288 if (wpas_p2p_presence_req(wpa_s, dur1, int1, dur2, int2) < 0)
289 return wpas_dbus_error_unknown_error(message,
290 "Failed to invoke presence request.");
295 wpa_dbus_dict_entry_clear(&entry);
297 return wpas_dbus_error_invalid_args(message, entry.key);
301 DBusMessage * wpas_dbus_handler_p2p_group_add(DBusMessage *message,
302 struct wpa_supplicant *wpa_s)
304 DBusMessageIter iter_dict;
305 DBusMessage *reply = NULL;
306 DBusMessageIter iter;
307 struct wpa_dbus_dict_entry entry;
308 char *pg_object_path = NULL;
309 int persistent_group = 0;
312 unsigned int group_id = 0;
313 struct wpa_ssid *ssid;
315 dbus_message_iter_init(message, &iter);
317 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
320 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
321 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
324 if (os_strcmp(entry.key, "persistent") == 0 &&
325 entry.type == DBUS_TYPE_BOOLEAN) {
326 persistent_group = entry.bool_value;
327 } else if (os_strcmp(entry.key, "frequency") == 0 &&
328 entry.type == DBUS_TYPE_INT32) {
329 freq = entry.int32_value;
332 } else if (os_strcmp(entry.key, "persistent_group_object") ==
334 entry.type == DBUS_TYPE_OBJECT_PATH)
335 pg_object_path = os_strdup(entry.str_value);
339 wpa_dbus_dict_entry_clear(&entry);
343 wpa_s = wpa_s->p2p_dev;
345 if (pg_object_path != NULL) {
349 * A persistent group Object Path is defined meaning we want
350 * to re-invoke a persistent group.
353 iface = wpas_dbus_new_decompose_object_path(
354 pg_object_path, WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART,
356 if (iface == NULL || net_id_str == NULL ||
357 os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
359 wpas_dbus_error_invalid_args(message,
364 group_id = strtoul(net_id_str, NULL, 10);
365 if (errno == EINVAL) {
366 reply = wpas_dbus_error_invalid_args(
367 message, pg_object_path);
371 /* Get the SSID structure from the persistent group id */
372 ssid = wpa_config_get_network(wpa_s->conf, group_id);
373 if (ssid == NULL || ssid->disabled != 2)
376 if (wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 0, 0, 0,
378 reply = wpas_dbus_error_unknown_error(
380 "Failed to reinvoke a persistent group");
383 } else if (wpas_p2p_group_add(wpa_s, persistent_group, freq, 0, 0))
387 os_free(pg_object_path);
391 wpa_dbus_dict_entry_clear(&entry);
393 reply = wpas_dbus_error_invalid_args(message, NULL);
398 DBusMessage * wpas_dbus_handler_p2p_disconnect(DBusMessage *message,
399 struct wpa_supplicant *wpa_s)
401 if (wpas_p2p_disconnect(wpa_s))
402 return wpas_dbus_error_unknown_error(message,
403 "failed to disconnect");
409 static dbus_bool_t wpa_dbus_p2p_check_enabled(struct wpa_supplicant *wpa_s,
410 DBusMessage *message,
411 DBusMessage **out_reply,
414 /* Return an error message or an error if P2P isn't available */
415 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL) {
417 *out_reply = dbus_message_new_error(
418 message, DBUS_ERROR_FAILED,
419 "P2P is not available for this interface");
421 dbus_set_error_const(error, DBUS_ERROR_FAILED,
422 "P2P is not available for this interface");
429 DBusMessage * wpas_dbus_handler_p2p_flush(DBusMessage *message,
430 struct wpa_supplicant *wpa_s)
432 DBusMessage *reply = NULL;
434 if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL))
438 wpa_s = wpa_s->p2p_dev;
440 os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
441 wpa_s->force_long_sd = 0;
442 p2p_flush(wpa_s->global->p2p);
448 DBusMessage * wpas_dbus_handler_p2p_connect(DBusMessage *message,
449 struct wpa_supplicant *wpa_s)
451 DBusMessageIter iter_dict;
452 DBusMessage *reply = NULL;
453 DBusMessageIter iter;
454 struct wpa_dbus_dict_entry entry;
455 char *peer_object_path = NULL;
456 int persistent_group = 0;
458 int authorize_only = 0;
463 enum p2p_wps_method wps_method = WPS_NOT_READY;
465 char *err_msg = NULL;
468 if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL))
471 dbus_message_iter_init(message, &iter);
473 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
476 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
477 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
480 if (os_strcmp(entry.key, "peer") == 0 &&
481 entry.type == DBUS_TYPE_OBJECT_PATH) {
482 peer_object_path = os_strdup(entry.str_value);
483 } else if (os_strcmp(entry.key, "persistent") == 0 &&
484 entry.type == DBUS_TYPE_BOOLEAN) {
485 persistent_group = entry.bool_value;
486 } else if (os_strcmp(entry.key, "join") == 0 &&
487 entry.type == DBUS_TYPE_BOOLEAN) {
488 join = entry.bool_value;
489 } else if (os_strcmp(entry.key, "authorize_only") == 0 &&
490 entry.type == DBUS_TYPE_BOOLEAN) {
491 authorize_only = entry.bool_value;
492 } else if (os_strcmp(entry.key, "frequency") == 0 &&
493 entry.type == DBUS_TYPE_INT32) {
494 freq = entry.int32_value;
497 } else if (os_strcmp(entry.key, "go_intent") == 0 &&
498 entry.type == DBUS_TYPE_INT32) {
499 go_intent = entry.int32_value;
500 if ((go_intent < 0) || (go_intent > 15))
502 } else if (os_strcmp(entry.key, "wps_method") == 0 &&
503 entry.type == DBUS_TYPE_STRING) {
504 if (os_strcmp(entry.str_value, "pbc") == 0)
505 wps_method = WPS_PBC;
506 else if (os_strcmp(entry.str_value, "pin") == 0)
507 wps_method = WPS_PIN_DISPLAY;
508 else if (os_strcmp(entry.str_value, "display") == 0)
509 wps_method = WPS_PIN_DISPLAY;
510 else if (os_strcmp(entry.str_value, "keypad") == 0)
511 wps_method = WPS_PIN_KEYPAD;
514 } else if (os_strcmp(entry.key, "pin") == 0 &&
515 entry.type == DBUS_TYPE_STRING) {
516 pin = os_strdup(entry.str_value);
520 wpa_dbus_dict_entry_clear(&entry);
523 if (wps_method == WPS_NOT_READY ||
524 parse_peer_object_path(peer_object_path, addr) < 0 ||
525 !p2p_peer_known(wpa_s->global->p2p, addr))
529 * Validate the wps_method specified and the pin value.
531 if ((!pin || !pin[0]) && wps_method == WPS_PIN_KEYPAD)
535 wpa_s = wpa_s->p2p_dev;
537 new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
538 persistent_group, 0, join, authorize_only,
539 go_intent, freq, -1, 0, 0, 0);
545 os_snprintf(npin, sizeof(npin), "%08d", new_pin);
546 generated_pin = npin;
547 reply = dbus_message_new_method_return(message);
548 dbus_message_append_args(reply, DBUS_TYPE_STRING,
549 &generated_pin, DBUS_TYPE_INVALID);
554 "connect failed due to channel unavailability.";
555 iface = WPAS_DBUS_ERROR_CONNECT_CHANNEL_UNAVAILABLE;
559 err_msg = "connect failed due to unsupported channel.";
560 iface = WPAS_DBUS_ERROR_CONNECT_CHANNEL_UNSUPPORTED;
564 err_msg = "connect failed due to unspecified error.";
565 iface = WPAS_DBUS_ERROR_CONNECT_UNSPECIFIED_ERROR;
571 * Do we need specialized errors corresponding to above
572 * error conditions as against just returning a different
575 reply = dbus_message_new_error(message, iface, err_msg);
579 os_free(peer_object_path);
583 wpa_dbus_dict_entry_clear(&entry);
585 reply = wpas_dbus_error_invalid_args(message, NULL);
590 DBusMessage * wpas_dbus_handler_p2p_invite(DBusMessage *message,
591 struct wpa_supplicant *wpa_s)
593 DBusMessageIter iter_dict;
594 DBusMessage *reply = NULL;
595 DBusMessageIter iter;
596 struct wpa_dbus_dict_entry entry;
597 char *peer_object_path = NULL;
598 char *pg_object_path = NULL;
600 u8 peer_addr[ETH_ALEN];
601 unsigned int group_id = 0;
603 struct wpa_ssid *ssid;
605 if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL))
608 dbus_message_iter_init(message, &iter);
610 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
613 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
614 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
617 if (os_strcmp(entry.key, "peer") == 0 &&
618 entry.type == DBUS_TYPE_OBJECT_PATH) {
619 peer_object_path = os_strdup(entry.str_value);
620 wpa_dbus_dict_entry_clear(&entry);
621 } else if (os_strcmp(entry.key, "persistent_group_object") ==
623 entry.type == DBUS_TYPE_OBJECT_PATH) {
624 pg_object_path = os_strdup(entry.str_value);
626 wpa_dbus_dict_entry_clear(&entry);
628 wpa_dbus_dict_entry_clear(&entry);
633 if (parse_peer_object_path(peer_object_path, peer_addr) < 0 ||
634 !p2p_peer_known(wpa_s->global->p2p, peer_addr))
638 wpa_s = wpa_s->p2p_dev;
643 * A group ID is defined meaning we want to re-invoke a
647 iface = wpas_dbus_new_decompose_object_path(
649 WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART,
651 if (iface == NULL || net_id_str == NULL ||
652 os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
653 reply = wpas_dbus_error_invalid_args(message,
658 group_id = strtoul(net_id_str, NULL, 10);
659 if (errno == EINVAL) {
660 reply = wpas_dbus_error_invalid_args(
661 message, pg_object_path);
665 /* Get the SSID structure from the persistent group id */
666 ssid = wpa_config_get_network(wpa_s->conf, group_id);
667 if (ssid == NULL || ssid->disabled != 2)
670 if (wpas_p2p_invite(wpa_s, peer_addr, ssid, NULL, 0, 0, 0, 0) <
672 reply = wpas_dbus_error_unknown_error(
674 "Failed to reinvoke a persistent group");
679 * No group ID means propose to a peer to join my active group
681 if (wpas_p2p_invite_group(wpa_s, wpa_s->ifname,
683 reply = wpas_dbus_error_unknown_error(
684 message, "Failed to join to an active group");
691 os_free(pg_object_path);
692 os_free(peer_object_path);
696 reply = wpas_dbus_error_invalid_args(message, NULL);
701 DBusMessage * wpas_dbus_handler_p2p_prov_disc_req(DBusMessage *message,
702 struct wpa_supplicant *wpa_s)
704 DBusMessageIter iter;
705 char *peer_object_path = NULL;
706 char *config_method = NULL;
707 u8 peer_addr[ETH_ALEN];
709 dbus_message_iter_init(message, &iter);
710 dbus_message_iter_get_basic(&iter, &peer_object_path);
712 if (parse_peer_object_path(peer_object_path, peer_addr) < 0)
713 return wpas_dbus_error_invalid_args(message, NULL);
715 dbus_message_iter_next(&iter);
716 dbus_message_iter_get_basic(&iter, &config_method);
719 * Validation checks on config_method are being duplicated here
720 * to be able to return invalid args reply since the error code
721 * from p2p module are not granular enough (yet).
723 if (os_strcmp(config_method, "display") &&
724 os_strcmp(config_method, "keypad") &&
725 os_strcmp(config_method, "pbc") &&
726 os_strcmp(config_method, "pushbutton"))
727 return wpas_dbus_error_invalid_args(message, NULL);
730 wpa_s = wpa_s->p2p_dev;
732 if (wpas_p2p_prov_disc(wpa_s, peer_addr, config_method,
733 WPAS_P2P_PD_FOR_GO_NEG) < 0)
734 return wpas_dbus_error_unknown_error(message,
735 "Failed to send provision discovery request");
742 * P2P Device property accessor methods.
745 dbus_bool_t wpas_dbus_getter_p2p_device_config(DBusMessageIter *iter,
749 struct wpa_supplicant *wpa_s = user_data;
750 DBusMessageIter variant_iter, dict_iter;
751 DBusMessageIter iter_secdev_dict_entry, iter_secdev_dict_val,
752 iter_secdev_dict_array;
753 const char *dev_name;
754 int num_vendor_extensions = 0;
756 const struct wpabuf *vendor_ext[P2P_MAX_WPS_VENDOR_EXT];
758 if (!wpa_dbus_p2p_check_enabled(wpa_s, NULL, NULL, error))
762 wpa_s = wpa_s->p2p_dev;
764 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
765 "a{sv}", &variant_iter) ||
766 !wpa_dbus_dict_open_write(&variant_iter, &dict_iter))
770 dev_name = wpa_s->conf->device_name;
772 !wpa_dbus_dict_append_string(&dict_iter, "DeviceName", dev_name))
775 /* Primary device type */
776 if (!wpa_dbus_dict_append_byte_array(&dict_iter, "PrimaryDeviceType",
777 (char *) wpa_s->conf->device_type,
781 /* Secondary device types */
782 if (wpa_s->conf->num_sec_device_types) {
783 if (!wpa_dbus_dict_begin_array(&dict_iter,
784 "SecondaryDeviceTypes",
785 DBUS_TYPE_ARRAY_AS_STRING
786 DBUS_TYPE_BYTE_AS_STRING,
787 &iter_secdev_dict_entry,
788 &iter_secdev_dict_val,
789 &iter_secdev_dict_array))
792 for (i = 0; i < wpa_s->conf->num_sec_device_types; i++)
793 wpa_dbus_dict_bin_array_add_element(
794 &iter_secdev_dict_array,
795 wpa_s->conf->sec_device_type[i],
798 if (!wpa_dbus_dict_end_array(&dict_iter,
799 &iter_secdev_dict_entry,
800 &iter_secdev_dict_val,
801 &iter_secdev_dict_array))
805 /* Vendor Extensions */
806 for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
807 if (wpa_s->conf->wps_vendor_ext[i] == NULL)
809 vendor_ext[num_vendor_extensions++] =
810 wpa_s->conf->wps_vendor_ext[i];
813 if ((num_vendor_extensions &&
814 !wpa_dbus_dict_append_wpabuf_array(&dict_iter,
817 num_vendor_extensions)) ||
818 !wpa_dbus_dict_append_uint32(&dict_iter, "GOIntent",
819 wpa_s->conf->p2p_go_intent) ||
820 !wpa_dbus_dict_append_bool(&dict_iter, "PersistentReconnect",
821 wpa_s->conf->persistent_reconnect) ||
822 !wpa_dbus_dict_append_uint32(&dict_iter, "ListenRegClass",
823 wpa_s->conf->p2p_listen_reg_class) ||
824 !wpa_dbus_dict_append_uint32(&dict_iter, "ListenChannel",
825 wpa_s->conf->p2p_listen_channel) ||
826 !wpa_dbus_dict_append_uint32(&dict_iter, "OperRegClass",
827 wpa_s->conf->p2p_oper_reg_class) ||
828 !wpa_dbus_dict_append_uint32(&dict_iter, "OperChannel",
829 wpa_s->conf->p2p_oper_channel) ||
830 (wpa_s->conf->p2p_ssid_postfix &&
831 !wpa_dbus_dict_append_string(&dict_iter, "SsidPostfix",
832 wpa_s->conf->p2p_ssid_postfix)) ||
833 !wpa_dbus_dict_append_bool(&dict_iter, "IntraBss",
834 wpa_s->conf->p2p_intra_bss) ||
835 !wpa_dbus_dict_append_uint32(&dict_iter, "GroupIdle",
836 wpa_s->conf->p2p_group_idle) ||
837 !wpa_dbus_dict_append_uint32(&dict_iter, "disassoc_low_ack",
838 wpa_s->conf->disassoc_low_ack) ||
839 !wpa_dbus_dict_append_bool(&dict_iter, "NoGroupIface",
840 wpa_s->conf->p2p_no_group_iface) ||
841 !wpa_dbus_dict_append_uint32(&dict_iter, "p2p_search_delay",
842 wpa_s->conf->p2p_search_delay) ||
843 !wpa_dbus_dict_close_write(&variant_iter, &dict_iter) ||
844 !dbus_message_iter_close_container(iter, &variant_iter))
850 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
855 dbus_bool_t wpas_dbus_setter_p2p_device_config(DBusMessageIter *iter,
859 struct wpa_supplicant *wpa_s = user_data;
860 DBusMessageIter variant_iter, iter_dict;
861 struct wpa_dbus_dict_entry entry = {.type = DBUS_TYPE_STRING };
864 if (!wpa_dbus_p2p_check_enabled(wpa_s, NULL, NULL, error))
868 wpa_s = wpa_s->p2p_dev;
870 dbus_message_iter_recurse(iter, &variant_iter);
871 if (!wpa_dbus_dict_open_read(&variant_iter, &iter_dict, error))
874 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
875 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) {
876 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
877 "invalid message format");
881 if (os_strcmp(entry.key, "DeviceName") == 0) {
884 if (entry.type != DBUS_TYPE_STRING)
887 devname = os_strdup(entry.str_value);
889 goto err_no_mem_clear;
891 os_free(wpa_s->conf->device_name);
892 wpa_s->conf->device_name = devname;
894 wpa_s->conf->changed_parameters |=
895 CFG_CHANGED_DEVICE_NAME;
896 } else if (os_strcmp(entry.key, "PrimaryDeviceType") == 0) {
897 if (entry.type != DBUS_TYPE_ARRAY ||
898 entry.array_type != DBUS_TYPE_BYTE ||
899 entry.array_len != WPS_DEV_TYPE_LEN)
902 os_memcpy(wpa_s->conf->device_type,
903 entry.bytearray_value,
905 wpa_s->conf->changed_parameters |=
906 CFG_CHANGED_DEVICE_TYPE;
907 } else if (os_strcmp(entry.key, "SecondaryDeviceTypes") == 0) {
908 if (entry.type != DBUS_TYPE_ARRAY ||
909 entry.array_type != WPAS_DBUS_TYPE_BINARRAY ||
910 entry.array_len > MAX_SEC_DEVICE_TYPES)
913 for (i = 0; i < entry.array_len; i++)
914 if (wpabuf_len(entry.binarray_value[i]) !=
916 goto err_no_mem_clear;
917 for (i = 0; i < entry.array_len; i++)
918 os_memcpy(wpa_s->conf->sec_device_type[i],
919 wpabuf_head(entry.binarray_value[i]),
921 wpa_s->conf->num_sec_device_types = entry.array_len;
922 wpa_s->conf->changed_parameters |=
923 CFG_CHANGED_SEC_DEVICE_TYPE;
924 } else if (os_strcmp(entry.key, "VendorExtension") == 0) {
925 if (entry.type != DBUS_TYPE_ARRAY ||
926 entry.array_type != WPAS_DBUS_TYPE_BINARRAY ||
927 (entry.array_len > P2P_MAX_WPS_VENDOR_EXT))
930 wpa_s->conf->changed_parameters |=
931 CFG_CHANGED_VENDOR_EXTENSION;
933 for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
934 wpabuf_free(wpa_s->conf->wps_vendor_ext[i]);
935 if (i < entry.array_len) {
936 wpa_s->conf->wps_vendor_ext[i] =
937 entry.binarray_value[i];
938 entry.binarray_value[i] = NULL;
940 wpa_s->conf->wps_vendor_ext[i] = NULL;
942 } else if (os_strcmp(entry.key, "GOIntent") == 0 &&
943 entry.type == DBUS_TYPE_UINT32 &&
944 (entry.uint32_value <= 15))
945 wpa_s->conf->p2p_go_intent = entry.uint32_value;
946 else if (os_strcmp(entry.key, "PersistentReconnect") == 0 &&
947 entry.type == DBUS_TYPE_BOOLEAN)
948 wpa_s->conf->persistent_reconnect = entry.bool_value;
949 else if (os_strcmp(entry.key, "ListenRegClass") == 0 &&
950 entry.type == DBUS_TYPE_UINT32) {
951 wpa_s->conf->p2p_listen_reg_class = entry.uint32_value;
952 wpa_s->conf->changed_parameters |=
953 CFG_CHANGED_P2P_LISTEN_CHANNEL;
954 } else if (os_strcmp(entry.key, "ListenChannel") == 0 &&
955 entry.type == DBUS_TYPE_UINT32) {
956 wpa_s->conf->p2p_listen_channel = entry.uint32_value;
957 wpa_s->conf->changed_parameters |=
958 CFG_CHANGED_P2P_LISTEN_CHANNEL;
959 } else if (os_strcmp(entry.key, "OperRegClass") == 0 &&
960 entry.type == DBUS_TYPE_UINT32) {
961 wpa_s->conf->p2p_oper_reg_class = entry.uint32_value;
962 wpa_s->conf->changed_parameters |=
963 CFG_CHANGED_P2P_OPER_CHANNEL;
964 } else if (os_strcmp(entry.key, "OperChannel") == 0 &&
965 entry.type == DBUS_TYPE_UINT32) {
966 wpa_s->conf->p2p_oper_channel = entry.uint32_value;
967 wpa_s->conf->changed_parameters |=
968 CFG_CHANGED_P2P_OPER_CHANNEL;
969 } else if (os_strcmp(entry.key, "SsidPostfix") == 0) {
972 if (entry.type != DBUS_TYPE_STRING)
975 postfix = os_strdup(entry.str_value);
977 goto err_no_mem_clear;
979 os_free(wpa_s->conf->p2p_ssid_postfix);
980 wpa_s->conf->p2p_ssid_postfix = postfix;
982 wpa_s->conf->changed_parameters |=
983 CFG_CHANGED_P2P_SSID_POSTFIX;
984 } else if (os_strcmp(entry.key, "IntraBss") == 0 &&
985 entry.type == DBUS_TYPE_BOOLEAN) {
986 wpa_s->conf->p2p_intra_bss = entry.bool_value;
987 wpa_s->conf->changed_parameters |=
988 CFG_CHANGED_P2P_INTRA_BSS;
989 } else if (os_strcmp(entry.key, "GroupIdle") == 0 &&
990 entry.type == DBUS_TYPE_UINT32)
991 wpa_s->conf->p2p_group_idle = entry.uint32_value;
992 else if (os_strcmp(entry.key, "disassoc_low_ack") == 0 &&
993 entry.type == DBUS_TYPE_UINT32)
994 wpa_s->conf->disassoc_low_ack = entry.uint32_value;
995 else if (os_strcmp(entry.key, "NoGroupIface") == 0 &&
996 entry.type == DBUS_TYPE_BOOLEAN)
997 wpa_s->conf->p2p_no_group_iface = entry.bool_value;
998 else if (os_strcmp(entry.key, "p2p_search_delay") == 0 &&
999 entry.type == DBUS_TYPE_UINT32)
1000 wpa_s->conf->p2p_search_delay = entry.uint32_value;
1004 wpa_dbus_dict_entry_clear(&entry);
1007 if (wpa_s->conf->changed_parameters) {
1008 /* Some changed parameters requires to update config*/
1009 wpa_supplicant_update_config(wpa_s);
1015 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
1016 "invalid message format");
1017 wpa_dbus_dict_entry_clear(&entry);
1021 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1022 wpa_dbus_dict_entry_clear(&entry);
1027 dbus_bool_t wpas_dbus_getter_p2p_peers(DBusMessageIter *iter, DBusError *error,
1030 struct wpa_supplicant *wpa_s = user_data;
1031 struct p2p_data *p2p = wpa_s->global->p2p;
1032 int next = 0, i = 0;
1033 int num = 0, out_of_mem = 0;
1035 const struct p2p_peer_info *peer_info = NULL;
1036 dbus_bool_t success = FALSE;
1038 struct dl_list peer_objpath_list;
1039 struct peer_objpath_node {
1040 struct dl_list list;
1041 char path[WPAS_DBUS_OBJECT_PATH_MAX];
1044 char **peer_obj_paths = NULL;
1046 if (!wpa_dbus_p2p_check_enabled(wpa_s, NULL, NULL, error))
1049 dl_list_init(&peer_objpath_list);
1051 /* Get the first peer info */
1052 peer_info = p2p_get_peer_found(p2p, NULL, next);
1054 /* Get next and accumulate them */
1056 while (peer_info != NULL) {
1057 node = os_zalloc(sizeof(struct peer_objpath_node));
1063 addr = peer_info->p2p_device_addr;
1064 os_snprintf(node->path, WPAS_DBUS_OBJECT_PATH_MAX,
1065 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART
1067 wpa_s->dbus_new_path, MAC2STR(addr));
1068 dl_list_add_tail(&peer_objpath_list, &node->list);
1071 peer_info = p2p_get_peer_found(p2p, addr, next);
1075 * Now construct the peer object paths in a form suitable for
1076 * array_property_getter helper below.
1078 peer_obj_paths = os_calloc(num, sizeof(char *));
1080 if (!peer_obj_paths) {
1085 dl_list_for_each_safe(node, tmp, &peer_objpath_list,
1086 struct peer_objpath_node, list)
1087 peer_obj_paths[i++] = node->path;
1089 success = wpas_dbus_simple_array_property_getter(iter,
1090 DBUS_TYPE_OBJECT_PATH,
1091 peer_obj_paths, num,
1096 os_free(peer_obj_paths);
1098 dl_list_for_each_safe(node, tmp, &peer_objpath_list,
1099 struct peer_objpath_node, list) {
1100 dl_list_del(&node->list);
1104 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1110 enum wpas_p2p_role {
1111 WPAS_P2P_ROLE_DEVICE,
1113 WPAS_P2P_ROLE_CLIENT,
1116 static enum wpas_p2p_role wpas_get_p2p_role(struct wpa_supplicant *wpa_s)
1118 struct wpa_ssid *ssid = wpa_s->current_ssid;
1121 return WPAS_P2P_ROLE_DEVICE;
1122 if (wpa_s->wpa_state != WPA_COMPLETED)
1123 return WPAS_P2P_ROLE_DEVICE;
1125 switch (ssid->mode) {
1126 case WPAS_MODE_P2P_GO:
1127 case WPAS_MODE_P2P_GROUP_FORMATION:
1128 return WPAS_P2P_ROLE_GO;
1129 case WPAS_MODE_INFRA:
1130 if (ssid->p2p_group)
1131 return WPAS_P2P_ROLE_CLIENT;
1132 return WPAS_P2P_ROLE_DEVICE;
1134 return WPAS_P2P_ROLE_DEVICE;
1139 dbus_bool_t wpas_dbus_getter_p2p_role(DBusMessageIter *iter, DBusError *error,
1142 struct wpa_supplicant *wpa_s = user_data;
1145 switch (wpas_get_p2p_role(wpa_s)) {
1146 case WPAS_P2P_ROLE_GO:
1149 case WPAS_P2P_ROLE_CLIENT:
1157 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &str,
1162 dbus_bool_t wpas_dbus_getter_p2p_group(DBusMessageIter *iter, DBusError *error,
1165 struct wpa_supplicant *wpa_s = user_data;
1166 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX];
1167 char *dbus_groupobj_path = path_buf;
1169 if (wpa_s->dbus_groupobj_path == NULL)
1170 os_snprintf(dbus_groupobj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1173 os_snprintf(dbus_groupobj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1174 "%s", wpa_s->dbus_groupobj_path);
1176 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
1177 &dbus_groupobj_path, error);
1181 dbus_bool_t wpas_dbus_getter_p2p_peergo(DBusMessageIter *iter,
1182 DBusError *error, void *user_data)
1184 struct wpa_supplicant *wpa_s = user_data;
1185 char go_peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1187 if (wpas_get_p2p_role(wpa_s) != WPAS_P2P_ROLE_CLIENT)
1188 os_snprintf(go_peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
1190 os_snprintf(go_peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1191 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
1193 wpa_s->dbus_new_path, MAC2STR(wpa_s->go_dev_addr));
1195 path = go_peer_obj_path;
1196 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
1202 * Peer object properties accessor methods
1205 dbus_bool_t wpas_dbus_getter_p2p_peer_device_name(DBusMessageIter *iter,
1209 struct peer_handler_args *peer_args = user_data;
1210 const struct p2p_peer_info *info;
1213 if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error))
1216 /* get the peer info */
1217 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1218 peer_args->p2p_device_addr, 0);
1220 dbus_set_error(error, DBUS_ERROR_FAILED,
1221 "failed to find peer");
1225 tmp = os_strdup(info->device_name);
1227 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1231 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp,
1233 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1243 dbus_bool_t wpas_dbus_getter_p2p_peer_primary_device_type(
1244 DBusMessageIter *iter, DBusError *error, void *user_data)
1246 struct peer_handler_args *peer_args = user_data;
1247 const struct p2p_peer_info *info;
1249 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1250 peer_args->p2p_device_addr, 0);
1252 dbus_set_error(error, DBUS_ERROR_FAILED,
1253 "failed to find peer");
1257 if (!wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
1260 WPS_DEV_TYPE_LEN, error)) {
1261 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1269 dbus_bool_t wpas_dbus_getter_p2p_peer_config_method(DBusMessageIter *iter,
1273 struct peer_handler_args *peer_args = user_data;
1274 const struct p2p_peer_info *info;
1276 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1277 peer_args->p2p_device_addr, 0);
1279 dbus_set_error(error, DBUS_ERROR_FAILED,
1280 "failed to find peer");
1284 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
1285 &info->config_methods, error)) {
1286 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1294 dbus_bool_t wpas_dbus_getter_p2p_peer_level(DBusMessageIter *iter,
1298 struct peer_handler_args *peer_args = user_data;
1299 const struct p2p_peer_info *info;
1301 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1302 peer_args->p2p_device_addr, 0);
1304 dbus_set_error(error, DBUS_ERROR_FAILED,
1305 "failed to find peer");
1309 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
1310 &info->level, error)) {
1311 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1319 dbus_bool_t wpas_dbus_getter_p2p_peer_device_capability(DBusMessageIter *iter,
1323 struct peer_handler_args *peer_args = user_data;
1324 const struct p2p_peer_info *info;
1326 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1327 peer_args->p2p_device_addr, 0);
1329 dbus_set_error(error, DBUS_ERROR_FAILED,
1330 "failed to find peer");
1334 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BYTE,
1335 &info->dev_capab, error)) {
1336 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1344 dbus_bool_t wpas_dbus_getter_p2p_peer_group_capability(DBusMessageIter *iter,
1348 struct peer_handler_args *peer_args = user_data;
1349 const struct p2p_peer_info *info;
1351 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1352 peer_args->p2p_device_addr, 0);
1354 dbus_set_error(error, DBUS_ERROR_FAILED,
1355 "failed to find peer");
1359 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BYTE,
1360 &info->group_capab, error)) {
1361 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1369 dbus_bool_t wpas_dbus_getter_p2p_peer_secondary_device_types(
1370 DBusMessageIter *iter, DBusError *error, void *user_data)
1372 struct peer_handler_args *peer_args = user_data;
1373 const struct p2p_peer_info *info;
1374 DBusMessageIter variant_iter, array_iter;
1376 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1377 peer_args->p2p_device_addr, 0);
1379 dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer");
1383 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
1384 DBUS_TYPE_ARRAY_AS_STRING
1385 DBUS_TYPE_ARRAY_AS_STRING
1386 DBUS_TYPE_BYTE_AS_STRING,
1388 !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
1389 DBUS_TYPE_ARRAY_AS_STRING
1390 DBUS_TYPE_BYTE_AS_STRING,
1392 dbus_set_error(error, DBUS_ERROR_FAILED,
1393 "%s: failed to construct message 1", __func__);
1397 if (info->wps_sec_dev_type_list_len) {
1398 const u8 *sec_dev_type_list = info->wps_sec_dev_type_list;
1399 int num_sec_device_types =
1400 info->wps_sec_dev_type_list_len / WPS_DEV_TYPE_LEN;
1402 DBusMessageIter inner_array_iter;
1404 for (i = 0; i < num_sec_device_types; i++) {
1405 if (!dbus_message_iter_open_container(
1406 &array_iter, DBUS_TYPE_ARRAY,
1407 DBUS_TYPE_BYTE_AS_STRING,
1408 &inner_array_iter) ||
1409 !dbus_message_iter_append_fixed_array(
1410 &inner_array_iter, DBUS_TYPE_BYTE,
1411 &sec_dev_type_list, WPS_DEV_TYPE_LEN) ||
1412 !dbus_message_iter_close_container(
1413 &array_iter, &inner_array_iter)) {
1414 dbus_set_error(error, DBUS_ERROR_FAILED,
1415 "%s: failed to construct message 2 (%d)",
1420 sec_dev_type_list += WPS_DEV_TYPE_LEN;
1424 if (!dbus_message_iter_close_container(&variant_iter, &array_iter) ||
1425 !dbus_message_iter_close_container(iter, &variant_iter)) {
1426 dbus_set_error(error, DBUS_ERROR_FAILED,
1427 "%s: failed to construct message 3", __func__);
1435 dbus_bool_t wpas_dbus_getter_p2p_peer_vendor_extension(DBusMessageIter *iter,
1439 struct wpabuf *vendor_extension[P2P_MAX_WPS_VENDOR_EXT];
1440 unsigned int i, num = 0;
1441 struct peer_handler_args *peer_args = user_data;
1442 const struct p2p_peer_info *info;
1444 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1445 peer_args->p2p_device_addr, 0);
1447 dbus_set_error(error, DBUS_ERROR_FAILED,
1448 "failed to find peer");
1452 /* Add WPS vendor extensions attribute */
1453 os_memset(vendor_extension, 0, sizeof(vendor_extension));
1454 for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
1455 if (info->wps_vendor_ext[i] == NULL)
1457 vendor_extension[num] = info->wps_vendor_ext[i];
1461 if (!wpas_dbus_simple_array_array_property_getter(iter, DBUS_TYPE_BYTE,
1470 dbus_bool_t wpas_dbus_getter_p2p_peer_ies(DBusMessageIter *iter,
1471 DBusError *error, void *user_data)
1473 struct peer_handler_args *peer_args = user_data;
1474 const struct p2p_peer_info *info;
1476 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1477 peer_args->p2p_device_addr, 0);
1479 dbus_set_error(error, DBUS_ERROR_FAILED,
1480 "failed to find peer");
1484 if (info->wfd_subelems == NULL)
1485 return wpas_dbus_simple_array_property_getter(iter,
1489 return wpas_dbus_simple_array_property_getter(
1490 iter, DBUS_TYPE_BYTE, (char *) info->wfd_subelems->buf,
1491 info->wfd_subelems->used, error);
1495 dbus_bool_t wpas_dbus_getter_p2p_peer_device_address(DBusMessageIter *iter,
1499 struct peer_handler_args *peer_args = user_data;
1500 const struct p2p_peer_info *info;
1502 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1503 peer_args->p2p_device_addr, 0);
1505 dbus_set_error(error, DBUS_ERROR_FAILED,
1506 "failed to find peer");
1510 return wpas_dbus_simple_array_property_getter(
1511 iter, DBUS_TYPE_BYTE, (char *) info->p2p_device_addr,
1516 struct peer_group_data {
1517 struct wpa_supplicant *wpa_s;
1518 const struct p2p_peer_info *info;
1520 unsigned int nb_paths;
1525 static int match_group_where_peer_is_client(struct p2p_group *group,
1528 struct peer_group_data *data = user_data;
1529 const struct p2p_group_config *cfg;
1530 struct wpa_supplicant *wpa_s_go;
1533 if (!p2p_group_is_client_connected(group, data->info->p2p_device_addr))
1536 cfg = p2p_group_get_config(group);
1538 wpa_s_go = wpas_get_p2p_go_iface(data->wpa_s, cfg->ssid,
1540 if (wpa_s_go == NULL)
1543 paths = os_realloc_array(data->paths, data->nb_paths + 1,
1548 data->paths = paths;
1549 data->paths[data->nb_paths] = wpa_s_go->dbus_groupobj_path;
1555 data->error = ENOMEM;
1560 dbus_bool_t wpas_dbus_getter_p2p_peer_groups(DBusMessageIter *iter,
1564 struct peer_handler_args *peer_args = user_data;
1565 const struct p2p_peer_info *info;
1566 struct peer_group_data data;
1567 struct wpa_supplicant *wpa_s, *wpa_s_go;
1568 dbus_bool_t success = FALSE;
1570 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1571 peer_args->p2p_device_addr, 0);
1573 dbus_set_error(error, DBUS_ERROR_FAILED,
1574 "failed to find peer");
1578 os_memset(&data, 0, sizeof(data));
1580 wpa_s = peer_args->wpa_s;
1582 wpa_s = wpa_s->p2p_dev;
1584 wpa_s_go = wpas_get_p2p_client_iface(wpa_s, info->p2p_device_addr);
1586 data.paths = os_calloc(1, sizeof(char *));
1587 if (data.paths == NULL)
1589 data.paths[0] = wpa_s_go->dbus_groupobj_path;
1593 data.wpa_s = peer_args->wpa_s;
1596 p2p_loop_on_all_groups(peer_args->wpa_s->global->p2p,
1597 match_group_where_peer_is_client, &data);
1601 if (data.paths == NULL) {
1602 return wpas_dbus_simple_array_property_getter(
1603 iter, DBUS_TYPE_OBJECT_PATH, NULL, 0, error);
1606 success = wpas_dbus_simple_array_property_getter(iter,
1607 DBUS_TYPE_OBJECT_PATH,
1609 data.nb_paths, error);
1613 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1615 os_free(data.paths);
1621 * wpas_dbus_getter_persistent_groups - Get array of persistent group objects
1622 * @iter: Pointer to incoming dbus message iter
1623 * @error: Location to store error on failure
1624 * @user_data: Function specific data
1625 * Returns: TRUE on success, FALSE on failure
1627 * Getter for "PersistentGroups" property.
1629 dbus_bool_t wpas_dbus_getter_persistent_groups(DBusMessageIter *iter,
1633 struct wpa_supplicant *wpa_s = user_data;
1634 struct wpa_ssid *ssid;
1636 unsigned int i = 0, num = 0;
1637 dbus_bool_t success = FALSE;
1639 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
1640 if (network_is_persistent_group(ssid))
1643 paths = os_calloc(num, sizeof(char *));
1645 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1649 /* Loop through configured networks and append object path of each */
1650 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1651 if (!network_is_persistent_group(ssid))
1653 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1654 if (paths[i] == NULL) {
1655 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
1659 /* Construct the object path for this network. */
1660 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
1661 "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%d",
1662 wpa_s->dbus_new_path, ssid->id);
1665 success = wpas_dbus_simple_array_property_getter(iter,
1666 DBUS_TYPE_OBJECT_PATH,
1671 os_free(paths[--i]);
1678 * wpas_dbus_getter_persistent_group_properties - Get options for a persistent
1680 * @iter: Pointer to incoming dbus message iter
1681 * @error: Location to store error on failure
1682 * @user_data: Function specific data
1683 * Returns: TRUE on success, FALSE on failure
1685 * Getter for "Properties" property of a persistent group.
1687 dbus_bool_t wpas_dbus_getter_persistent_group_properties(DBusMessageIter *iter,
1691 struct network_handler_args *net = user_data;
1693 /* Leveraging the fact that persistent group object is still
1694 * represented in same manner as network within.
1696 return wpas_dbus_getter_network_properties(iter, error, net);
1701 * wpas_dbus_setter_persistent_group_properties - Get options for a persistent
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
1708 * Setter for "Properties" property of a persistent group.
1710 dbus_bool_t wpas_dbus_setter_persistent_group_properties(DBusMessageIter *iter,
1714 struct network_handler_args *net = user_data;
1715 struct wpa_ssid *ssid = net->ssid;
1716 DBusMessageIter variant_iter;
1719 * Leveraging the fact that persistent group object is still
1720 * represented in same manner as network within.
1722 dbus_message_iter_recurse(iter, &variant_iter);
1723 return set_network_properties(net->wpa_s, ssid, &variant_iter, error);
1728 * wpas_dbus_new_iface_add_persistent_group - Add a new configured
1730 * @message: Pointer to incoming dbus message
1731 * @wpa_s: wpa_supplicant structure for a network interface
1732 * Returns: A dbus message containing the object path of the new
1735 * Handler function for "AddPersistentGroup" method call of a P2P Device
1738 DBusMessage * wpas_dbus_handler_add_persistent_group(
1739 DBusMessage *message, struct wpa_supplicant *wpa_s)
1741 DBusMessage *reply = NULL;
1742 DBusMessageIter iter;
1743 struct wpa_ssid *ssid = NULL;
1744 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf;
1747 dbus_message_iter_init(message, &iter);
1749 ssid = wpa_config_add_network(wpa_s->conf);
1751 wpa_printf(MSG_ERROR,
1752 "dbus: %s: Cannot add new persistent group",
1754 reply = wpas_dbus_error_unknown_error(
1756 "wpa_supplicant could not add a persistent group on this interface.");
1760 /* Mark the ssid as being a persistent group before the notification */
1762 ssid->p2p_persistent_group = 1;
1763 wpas_notify_persistent_group_added(wpa_s, ssid);
1765 wpa_config_set_network_defaults(ssid);
1767 dbus_error_init(&error);
1768 if (!set_network_properties(wpa_s, ssid, &iter, &error)) {
1769 wpa_printf(MSG_DEBUG,
1770 "dbus: %s: Control interface could not set persistent group properties",
1772 reply = wpas_dbus_reply_new_from_error(
1773 message, &error, DBUS_ERROR_INVALID_ARGS,
1774 "Failed to set network properties");
1775 dbus_error_free(&error);
1779 /* Construct the object path for this network. */
1780 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
1781 "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%d",
1782 wpa_s->dbus_new_path, ssid->id);
1784 reply = dbus_message_new_method_return(message);
1785 if (reply == NULL) {
1786 reply = wpas_dbus_error_no_memory(message);
1789 if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
1790 DBUS_TYPE_INVALID)) {
1791 dbus_message_unref(reply);
1792 reply = wpas_dbus_error_no_memory(message);
1800 wpas_notify_persistent_group_removed(wpa_s, ssid);
1801 wpa_config_remove_network(wpa_s->conf, ssid->id);
1808 * wpas_dbus_handler_remove_persistent_group - Remove a configured persistent
1810 * @message: Pointer to incoming dbus message
1811 * @wpa_s: wpa_supplicant structure for a network interface
1812 * Returns: NULL on success or dbus error on failure
1814 * Handler function for "RemovePersistentGroup" method call of a P2P Device
1817 DBusMessage * wpas_dbus_handler_remove_persistent_group(
1818 DBusMessage *message, struct wpa_supplicant *wpa_s)
1820 DBusMessage *reply = NULL;
1822 char *iface = NULL, *persistent_group_id;
1824 struct wpa_ssid *ssid;
1826 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
1830 * Extract the network ID and ensure the network is actually a child of
1833 iface = wpas_dbus_new_decompose_object_path(
1834 op, WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART,
1835 &persistent_group_id);
1836 if (iface == NULL || persistent_group_id == NULL ||
1837 os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
1838 reply = wpas_dbus_error_invalid_args(message, op);
1842 id = strtoul(persistent_group_id, NULL, 10);
1843 if (errno == EINVAL) {
1844 reply = wpas_dbus_error_invalid_args(message, op);
1848 ssid = wpa_config_get_network(wpa_s->conf, id);
1850 reply = wpas_dbus_error_persistent_group_unknown(message);
1854 wpas_notify_persistent_group_removed(wpa_s, ssid);
1856 if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
1857 wpa_printf(MSG_ERROR,
1858 "dbus: %s: error occurred when removing persistent group %d",
1860 reply = wpas_dbus_error_unknown_error(
1862 "error removing the specified persistent group on this interface.");
1872 static void remove_persistent_group(struct wpa_supplicant *wpa_s,
1873 struct wpa_ssid *ssid)
1875 wpas_notify_persistent_group_removed(wpa_s, ssid);
1877 if (wpa_config_remove_network(wpa_s->conf, ssid->id) < 0) {
1878 wpa_printf(MSG_ERROR,
1879 "dbus: %s: error occurred when removing persistent group %d",
1880 __func__, ssid->id);
1887 * wpas_dbus_handler_remove_all_persistent_groups - Remove all configured
1889 * @message: Pointer to incoming dbus message
1890 * @wpa_s: wpa_supplicant structure for a network interface
1891 * Returns: NULL on success or dbus error on failure
1893 * Handler function for "RemoveAllPersistentGroups" method call of a
1894 * P2P Device interface.
1896 DBusMessage * wpas_dbus_handler_remove_all_persistent_groups(
1897 DBusMessage *message, struct wpa_supplicant *wpa_s)
1899 struct wpa_ssid *ssid, *next;
1900 struct wpa_config *config;
1902 config = wpa_s->conf;
1903 ssid = config->ssid;
1906 if (network_is_persistent_group(ssid))
1907 remove_persistent_group(wpa_s, ssid);
1915 * Group object properties accessor methods
1918 dbus_bool_t wpas_dbus_getter_p2p_group_members(DBusMessageIter *iter,
1922 struct wpa_supplicant *wpa_s = user_data;
1923 struct wpa_ssid *ssid;
1924 unsigned int num_members;
1929 dbus_bool_t success = FALSE;
1931 /* Verify correct role for this property */
1932 if (wpas_get_p2p_role(wpa_s) != WPAS_P2P_ROLE_GO) {
1933 return wpas_dbus_simple_array_property_getter(
1934 iter, DBUS_TYPE_OBJECT_PATH, NULL, 0, error);
1937 ssid = wpa_s->conf->ssid;
1938 /* At present WPAS P2P_GO mode only applicable for p2p_go */
1939 if (ssid->mode != WPAS_MODE_P2P_GO &&
1940 ssid->mode != WPAS_MODE_AP &&
1941 ssid->mode != WPAS_MODE_P2P_GROUP_FORMATION)
1944 num_members = p2p_get_group_num_members(wpa_s->p2p_group);
1946 paths = os_calloc(num_members, sizeof(char *));
1951 while ((addr = p2p_iterate_group_members(wpa_s->p2p_group, &next))) {
1952 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1955 os_snprintf(paths[i], WPAS_DBUS_OBJECT_PATH_MAX,
1956 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART
1958 wpa_s->parent->dbus_new_path, MAC2STR(addr));
1962 success = wpas_dbus_simple_array_property_getter(iter,
1963 DBUS_TYPE_OBJECT_PATH,
1967 for (i = 0; i < num_members; i++)
1973 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1975 for (i = 0; i < num_members; i++)
1983 dbus_bool_t wpas_dbus_getter_p2p_group_ssid(DBusMessageIter *iter,
1984 DBusError *error, void *user_data)
1986 struct wpa_supplicant *wpa_s = user_data;
1988 if (wpa_s->current_ssid == NULL)
1990 return wpas_dbus_simple_array_property_getter(
1991 iter, DBUS_TYPE_BYTE, wpa_s->current_ssid->ssid,
1992 wpa_s->current_ssid->ssid_len, error);
1996 dbus_bool_t wpas_dbus_getter_p2p_group_bssid(DBusMessageIter *iter,
2000 struct wpa_supplicant *wpa_s = user_data;
2001 u8 role = wpas_get_p2p_role(wpa_s);
2004 if (role == WPAS_P2P_ROLE_CLIENT) {
2005 if (wpa_s->current_ssid == NULL)
2007 p_bssid = wpa_s->current_ssid->bssid;
2009 if (wpa_s->ap_iface == NULL)
2011 p_bssid = wpa_s->ap_iface->bss[0]->own_addr;
2014 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
2020 dbus_bool_t wpas_dbus_getter_p2p_group_frequency(DBusMessageIter *iter,
2024 struct wpa_supplicant *wpa_s = user_data;
2026 u8 role = wpas_get_p2p_role(wpa_s);
2028 if (role == WPAS_P2P_ROLE_CLIENT) {
2029 if (wpa_s->go_params == NULL)
2031 op_freq = wpa_s->go_params->freq;
2033 if (wpa_s->ap_iface == NULL)
2035 op_freq = wpa_s->ap_iface->freq;
2038 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
2043 dbus_bool_t wpas_dbus_getter_p2p_group_passphrase(DBusMessageIter *iter,
2047 struct wpa_supplicant *wpa_s = user_data;
2049 struct wpa_ssid *ssid = wpa_s->current_ssid;
2054 p_pass = ssid->passphrase;
2058 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
2064 dbus_bool_t wpas_dbus_getter_p2p_group_psk(DBusMessageIter *iter,
2065 DBusError *error, void *user_data)
2067 struct wpa_supplicant *wpa_s = user_data;
2070 struct wpa_ssid *ssid = wpa_s->current_ssid;
2075 if (ssid->psk_set) {
2077 psk_len = sizeof(ssid->psk);
2080 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
2081 p_psk, psk_len, error);
2085 dbus_bool_t wpas_dbus_getter_p2p_group_vendor_ext(DBusMessageIter *iter,
2089 struct wpa_supplicant *wpa_s = user_data;
2090 struct hostapd_data *hapd;
2091 struct wpabuf *vendor_ext[MAX_WPS_VENDOR_EXTENSIONS];
2092 unsigned int i, num_vendor_ext = 0;
2094 os_memset(vendor_ext, 0, sizeof(vendor_ext));
2096 /* Verify correct role for this property */
2097 if (wpas_get_p2p_role(wpa_s) == WPAS_P2P_ROLE_GO) {
2098 if (wpa_s->ap_iface == NULL)
2100 hapd = wpa_s->ap_iface->bss[0];
2102 /* Parse WPS Vendor Extensions sent in Beacon/Probe Response */
2103 for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
2104 if (hapd->conf->wps_vendor_ext[i] == NULL)
2106 vendor_ext[num_vendor_ext++] =
2107 hapd->conf->wps_vendor_ext[i];
2111 /* Return vendor extensions or no data */
2112 return wpas_dbus_simple_array_array_property_getter(iter,
2120 dbus_bool_t wpas_dbus_setter_p2p_group_vendor_ext(DBusMessageIter *iter,
2124 struct wpa_supplicant *wpa_s = user_data;
2125 DBusMessageIter variant_iter, iter_dict, array_iter, sub;
2126 struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
2128 struct hostapd_data *hapd = NULL;
2130 if (wpas_get_p2p_role(wpa_s) == WPAS_P2P_ROLE_GO &&
2131 wpa_s->ap_iface != NULL)
2132 hapd = wpa_s->ap_iface->bss[0];
2136 dbus_message_iter_recurse(iter, &variant_iter);
2137 if (dbus_message_iter_get_arg_type(&variant_iter) != DBUS_TYPE_ARRAY)
2141 * This is supposed to be array of bytearrays (aay), but the earlier
2142 * implementation used a dict with "WPSVendorExtensions" as the key in
2143 * this setter function which does not match the format used by the
2144 * getter function. For backwards compatibility, allow both formats to
2145 * be used in the setter.
2147 if (dbus_message_iter_get_element_type(&variant_iter) ==
2149 /* This is the proper format matching the getter */
2150 struct wpabuf *vals[MAX_WPS_VENDOR_EXTENSIONS];
2152 dbus_message_iter_recurse(&variant_iter, &array_iter);
2154 if (dbus_message_iter_get_arg_type(&array_iter) !=
2156 dbus_message_iter_get_element_type(&array_iter) !=
2158 wpa_printf(MSG_DEBUG,
2159 "dbus: Not an array of array of bytes");
2164 os_memset(vals, 0, sizeof(vals));
2166 while (dbus_message_iter_get_arg_type(&array_iter) ==
2171 if (i == MAX_WPS_VENDOR_EXTENSIONS) {
2172 wpa_printf(MSG_DEBUG,
2173 "dbus: Too many WPSVendorExtensions values");
2174 i = MAX_WPS_VENDOR_EXTENSIONS + 1;
2178 dbus_message_iter_recurse(&array_iter, &sub);
2179 dbus_message_iter_get_fixed_array(&sub, &val, &len);
2180 wpa_hexdump(MSG_DEBUG, "dbus: WPSVendorExtentions[]",
2182 vals[i] = wpabuf_alloc_copy(val, len);
2183 if (vals[i] == NULL) {
2184 i = MAX_WPS_VENDOR_EXTENSIONS + 1;
2188 dbus_message_iter_next(&array_iter);
2191 if (i > MAX_WPS_VENDOR_EXTENSIONS) {
2192 for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++)
2193 wpabuf_free(vals[i]);
2197 for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
2198 wpabuf_free(hapd->conf->wps_vendor_ext[i]);
2199 hapd->conf->wps_vendor_ext[i] = vals[i];
2202 hostapd_update_wps(hapd);
2207 if (dbus_message_iter_get_element_type(&variant_iter) !=
2208 DBUS_TYPE_DICT_ENTRY)
2211 wpa_printf(MSG_DEBUG,
2212 "dbus: Try to use backwards compatibility version of WPSVendorExtensions setter");
2213 if (!wpa_dbus_dict_open_read(&variant_iter, &iter_dict, error))
2216 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2217 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) {
2218 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
2219 "invalid message format");
2223 if (os_strcmp(entry.key, "WPSVendorExtensions") == 0) {
2224 if (entry.type != DBUS_TYPE_ARRAY ||
2225 entry.array_type != WPAS_DBUS_TYPE_BINARRAY ||
2226 entry.array_len > MAX_WPS_VENDOR_EXTENSIONS)
2229 for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
2230 wpabuf_free(hapd->conf->wps_vendor_ext[i]);
2231 if (i < entry.array_len) {
2232 hapd->conf->wps_vendor_ext[i] =
2233 entry.binarray_value[i];
2234 entry.binarray_value[i] = NULL;
2236 hapd->conf->wps_vendor_ext[i] = NULL;
2239 hostapd_update_wps(hapd);
2243 wpa_dbus_dict_entry_clear(&entry);
2249 wpa_dbus_dict_entry_clear(&entry);
2250 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
2251 "invalid message format");
2256 DBusMessage * wpas_dbus_handler_p2p_add_service(DBusMessage *message,
2257 struct wpa_supplicant *wpa_s)
2259 DBusMessageIter iter_dict;
2260 DBusMessage *reply = NULL;
2261 DBusMessageIter iter;
2262 struct wpa_dbus_dict_entry entry;
2265 char *service = NULL;
2266 struct wpabuf *query = NULL;
2267 struct wpabuf *resp = NULL;
2270 dbus_message_iter_init(message, &iter);
2272 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
2275 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2276 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2279 if (os_strcmp(entry.key, "service_type") == 0 &&
2280 entry.type == DBUS_TYPE_STRING) {
2281 if (os_strcmp(entry.str_value, "upnp") == 0)
2283 else if (os_strcmp(entry.str_value, "bonjour") == 0)
2287 } else if (os_strcmp(entry.key, "version") == 0 &&
2288 entry.type == DBUS_TYPE_INT32) {
2289 version = entry.uint32_value;
2290 } else if (os_strcmp(entry.key, "service") == 0 &&
2291 entry.type == DBUS_TYPE_STRING) {
2293 service = os_strdup(entry.str_value);
2294 } else if (os_strcmp(entry.key, "query") == 0) {
2295 if (entry.type != DBUS_TYPE_ARRAY ||
2296 entry.array_type != DBUS_TYPE_BYTE)
2298 query = wpabuf_alloc_copy(
2299 entry.bytearray_value,
2301 } else if (os_strcmp(entry.key, "response") == 0) {
2302 if (entry.type != DBUS_TYPE_ARRAY ||
2303 entry.array_type != DBUS_TYPE_BYTE)
2305 resp = wpabuf_alloc_copy(entry.bytearray_value,
2308 wpa_dbus_dict_entry_clear(&entry);
2312 if (version <= 0 || service == NULL)
2315 if (wpas_p2p_service_add_upnp(wpa_s, version, service) != 0)
2318 } else if (bonjour == 1) {
2319 if (query == NULL || resp == NULL)
2322 if (wpas_p2p_service_add_bonjour(wpa_s, query, resp) < 0)
2332 wpa_dbus_dict_entry_clear(&entry);
2337 return wpas_dbus_error_invalid_args(message, NULL);
2341 DBusMessage * wpas_dbus_handler_p2p_delete_service(
2342 DBusMessage *message, struct wpa_supplicant *wpa_s)
2344 DBusMessageIter iter_dict;
2345 DBusMessage *reply = NULL;
2346 DBusMessageIter iter;
2347 struct wpa_dbus_dict_entry entry;
2351 char *service = NULL;
2352 struct wpabuf *query = NULL;
2355 dbus_message_iter_init(message, &iter);
2357 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
2360 if (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2361 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2364 if (os_strcmp(entry.key, "service_type") == 0 &&
2365 entry.type == DBUS_TYPE_STRING) {
2366 if (os_strcmp(entry.str_value, "upnp") == 0)
2368 else if (os_strcmp(entry.str_value, "bonjour") == 0)
2372 wpa_dbus_dict_entry_clear(&entry);
2376 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2377 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2379 if (os_strcmp(entry.key, "version") == 0 &&
2380 entry.type == DBUS_TYPE_INT32)
2381 version = entry.uint32_value;
2382 else if (os_strcmp(entry.key, "service") == 0 &&
2383 entry.type == DBUS_TYPE_STRING) {
2385 service = os_strdup(entry.str_value);
2389 wpa_dbus_dict_entry_clear(&entry);
2392 if (version <= 0 || service == NULL)
2395 ret = wpas_p2p_service_del_upnp(wpa_s, version, service);
2398 } else if (bonjour == 1) {
2399 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2400 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2403 if (os_strcmp(entry.key, "query") == 0) {
2404 if (entry.type != DBUS_TYPE_ARRAY ||
2405 entry.array_type != DBUS_TYPE_BYTE)
2408 query = wpabuf_alloc_copy(
2409 entry.bytearray_value,
2414 wpa_dbus_dict_entry_clear(&entry);
2420 ret = wpas_p2p_service_del_bonjour(wpa_s, query);
2430 wpa_dbus_dict_entry_clear(&entry);
2434 return wpas_dbus_error_invalid_args(message, NULL);
2438 DBusMessage * wpas_dbus_handler_p2p_flush_service(DBusMessage *message,
2439 struct wpa_supplicant *wpa_s)
2441 wpas_p2p_service_flush(wpa_s);
2446 DBusMessage * wpas_dbus_handler_p2p_service_sd_req(
2447 DBusMessage *message, struct wpa_supplicant *wpa_s)
2449 DBusMessageIter iter_dict;
2450 DBusMessage *reply = NULL;
2451 DBusMessageIter iter;
2452 struct wpa_dbus_dict_entry entry;
2454 char *service = NULL;
2455 char *peer_object_path = NULL;
2456 struct wpabuf *tlv = NULL;
2459 u8 addr_buf[ETH_ALEN], *addr;
2461 dbus_message_iter_init(message, &iter);
2463 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
2466 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2467 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2469 if (os_strcmp(entry.key, "peer_object") == 0 &&
2470 entry.type == DBUS_TYPE_OBJECT_PATH) {
2471 peer_object_path = os_strdup(entry.str_value);
2472 } else if (os_strcmp(entry.key, "service_type") == 0 &&
2473 entry.type == DBUS_TYPE_STRING) {
2474 if (os_strcmp(entry.str_value, "upnp") == 0)
2478 } else if (os_strcmp(entry.key, "version") == 0 &&
2479 entry.type == DBUS_TYPE_INT32) {
2480 version = entry.uint32_value;
2481 } else if (os_strcmp(entry.key, "service") == 0 &&
2482 entry.type == DBUS_TYPE_STRING) {
2483 service = os_strdup(entry.str_value);
2484 } else if (os_strcmp(entry.key, "tlv") == 0) {
2485 if (entry.type != DBUS_TYPE_ARRAY ||
2486 entry.array_type != DBUS_TYPE_BYTE)
2488 tlv = wpabuf_alloc_copy(entry.bytearray_value,
2493 wpa_dbus_dict_entry_clear(&entry);
2496 if (!peer_object_path) {
2499 if (parse_peer_object_path(peer_object_path, addr_buf) < 0 ||
2500 !p2p_peer_known(wpa_s->global->p2p, addr_buf))
2507 if (version <= 0 || service == NULL)
2510 ref = wpas_p2p_sd_request_upnp(wpa_s, addr, version, service);
2514 ref = wpas_p2p_sd_request(wpa_s, addr, tlv);
2519 reply = dbus_message_new_method_return(message);
2520 dbus_message_append_args(reply, DBUS_TYPE_UINT64,
2521 &ref, DBUS_TYPE_INVALID);
2523 reply = wpas_dbus_error_unknown_error(
2524 message, "Unable to send SD request");
2528 os_free(peer_object_path);
2531 wpa_dbus_dict_entry_clear(&entry);
2535 reply = wpas_dbus_error_invalid_args(message, NULL);
2540 DBusMessage * wpas_dbus_handler_p2p_service_sd_res(
2541 DBusMessage *message, struct wpa_supplicant *wpa_s)
2543 DBusMessageIter iter_dict;
2544 DBusMessage *reply = NULL;
2545 DBusMessageIter iter;
2546 struct wpa_dbus_dict_entry entry;
2547 char *peer_object_path = NULL;
2548 struct wpabuf *tlv = NULL;
2553 dbus_message_iter_init(message, &iter);
2555 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
2558 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2559 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2562 if (os_strcmp(entry.key, "peer_object") == 0 &&
2563 entry.type == DBUS_TYPE_OBJECT_PATH) {
2564 peer_object_path = os_strdup(entry.str_value);
2565 } else if (os_strcmp(entry.key, "frequency") == 0 &&
2566 entry.type == DBUS_TYPE_INT32) {
2567 freq = entry.uint32_value;
2568 } else if (os_strcmp(entry.key, "dialog_token") == 0 &&
2569 (entry.type == DBUS_TYPE_UINT32 ||
2570 entry.type == DBUS_TYPE_INT32)) {
2571 dlg_tok = entry.uint32_value;
2572 } else if (os_strcmp(entry.key, "tlvs") == 0) {
2573 if (entry.type != DBUS_TYPE_ARRAY ||
2574 entry.array_type != DBUS_TYPE_BYTE)
2576 tlv = wpabuf_alloc_copy(entry.bytearray_value,
2581 wpa_dbus_dict_entry_clear(&entry);
2583 if (parse_peer_object_path(peer_object_path, addr) < 0 ||
2584 !p2p_peer_known(wpa_s->global->p2p, addr) ||
2588 wpas_p2p_sd_response(wpa_s, freq, addr, (u8) dlg_tok, tlv);
2591 os_free(peer_object_path);
2594 wpa_dbus_dict_entry_clear(&entry);
2596 reply = wpas_dbus_error_invalid_args(message, NULL);
2601 DBusMessage * wpas_dbus_handler_p2p_service_sd_cancel_req(
2602 DBusMessage *message, struct wpa_supplicant *wpa_s)
2604 DBusMessageIter iter;
2607 dbus_message_iter_init(message, &iter);
2608 dbus_message_iter_get_basic(&iter, &req);
2613 if (wpas_p2p_sd_cancel_request(wpa_s, req) < 0)
2618 return wpas_dbus_error_invalid_args(message, NULL);
2622 DBusMessage * wpas_dbus_handler_p2p_service_update(
2623 DBusMessage *message, struct wpa_supplicant *wpa_s)
2625 wpas_p2p_sd_service_update(wpa_s);
2630 DBusMessage * wpas_dbus_handler_p2p_serv_disc_external(
2631 DBusMessage *message, struct wpa_supplicant *wpa_s)
2633 DBusMessageIter iter;
2636 dbus_message_iter_init(message, &iter);
2637 dbus_message_iter_get_basic(&iter, &ext);
2639 wpa_s->p2p_sd_over_ctrl_iface = ext;
2646 #ifdef CONFIG_WIFI_DISPLAY
2648 dbus_bool_t wpas_dbus_getter_global_wfd_ies(DBusMessageIter *iter,
2649 DBusError *error, void *user_data)
2651 struct wpa_global *global = user_data;
2655 ie = wifi_display_get_wfd_ie(global);
2657 return wpas_dbus_simple_array_property_getter(iter,
2661 ret = wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
2663 wpabuf_len(ie), error);
2670 dbus_bool_t wpas_dbus_setter_global_wfd_ies(DBusMessageIter *iter,
2671 DBusError *error, void *user_data)
2673 struct wpa_global *global = user_data;
2674 DBusMessageIter variant, array;
2675 struct wpabuf *ie = NULL;
2679 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_VARIANT)
2682 dbus_message_iter_recurse(iter, &variant);
2683 if (dbus_message_iter_get_arg_type(&variant) != DBUS_TYPE_ARRAY)
2686 dbus_message_iter_recurse(&variant, &array);
2687 dbus_message_iter_get_fixed_array(&array, &data, &len);
2689 wifi_display_enable(global, 0);
2690 wifi_display_deinit(global);
2695 ie = wpabuf_alloc(len);
2699 wpabuf_put_data(ie, data, len);
2700 if (wifi_display_subelem_set_from_ies(global, ie) != 0)
2703 if (global->wifi_display == 0)
2704 wifi_display_enable(global, 1);
2712 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
2713 "invalid message format");
2717 #endif /* CONFIG_WIFI_DISPLAY */