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(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.
60 static DBusMessage * wpas_dbus_error_persistent_group_unknown(
63 return dbus_message_new_error(message, WPAS_DBUS_ERROR_NETWORK_UNKNOWN,
64 "There is no such persistent group in "
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") &&
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") &&
116 (entry.type == DBUS_TYPE_STRING)) {
117 if (!os_strcmp(entry.str_value, "start_with_full"))
118 type = P2P_FIND_START_WITH_FULL;
119 else if (!os_strcmp(entry.str_value, "social"))
120 type = P2P_FIND_ONLY_SOCIAL;
121 else if (!os_strcmp(entry.str_value, "progressive"))
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 dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
193 wpa_s = wpa_s->p2p_dev;
195 if (wpas_p2p_listen(wpa_s, (unsigned int)timeout))
196 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
203 DBusMessage * wpas_dbus_handler_p2p_extendedlisten(
204 DBusMessage *message, struct wpa_supplicant *wpa_s)
206 unsigned int period = 0, interval = 0;
207 struct wpa_dbus_dict_entry entry;
208 DBusMessageIter iter;
209 DBusMessageIter iter_dict;
211 dbus_message_iter_init(message, &iter);
214 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
217 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
218 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
221 if (!os_strcmp(entry.key, "period") &&
222 (entry.type == DBUS_TYPE_INT32))
223 period = entry.uint32_value;
224 else if (!os_strcmp(entry.key, "interval") &&
225 (entry.type == DBUS_TYPE_INT32))
226 interval = entry.uint32_value;
229 wpa_dbus_dict_entry_clear(&entry);
233 wpa_s = wpa_s->p2p_dev;
235 if (wpas_p2p_ext_listen(wpa_s, period, interval))
236 return wpas_dbus_error_unknown_error(
237 message, "failed to initiate a p2p_ext_listen.");
242 wpa_dbus_dict_entry_clear(&entry);
244 return wpas_dbus_error_invalid_args(message, entry.key);
248 DBusMessage * wpas_dbus_handler_p2p_presence_request(
249 DBusMessage *message, struct wpa_supplicant *wpa_s)
251 unsigned int dur1 = 0, int1 = 0, dur2 = 0, int2 = 0;
252 struct wpa_dbus_dict_entry entry;
253 DBusMessageIter iter;
254 DBusMessageIter iter_dict;
256 dbus_message_iter_init(message, &iter);
259 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
262 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
263 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
266 if (!os_strcmp(entry.key, "duration1") &&
267 (entry.type == DBUS_TYPE_INT32))
268 dur1 = entry.uint32_value;
269 else if (!os_strcmp(entry.key, "interval1") &&
270 entry.type == DBUS_TYPE_INT32)
271 int1 = entry.uint32_value;
272 else if (!os_strcmp(entry.key, "duration2") &&
273 entry.type == DBUS_TYPE_INT32)
274 dur2 = entry.uint32_value;
275 else if (!os_strcmp(entry.key, "interval2") &&
276 entry.type == DBUS_TYPE_INT32)
277 int2 = entry.uint32_value;
281 wpa_dbus_dict_entry_clear(&entry);
285 wpa_s = wpa_s->p2p_dev;
287 if (wpas_p2p_presence_req(wpa_s, dur1, int1, dur2, int2) < 0)
288 return wpas_dbus_error_unknown_error(message,
289 "Failed to invoke presence request.");
294 wpa_dbus_dict_entry_clear(&entry);
296 return wpas_dbus_error_invalid_args(message, entry.key);
300 DBusMessage * wpas_dbus_handler_p2p_group_add(DBusMessage *message,
301 struct wpa_supplicant *wpa_s)
303 DBusMessageIter iter_dict;
304 DBusMessage *reply = NULL;
305 DBusMessageIter iter;
306 struct wpa_dbus_dict_entry entry;
307 char *pg_object_path = NULL;
308 int persistent_group = 0;
311 char *net_id_str = NULL;
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") &&
325 (entry.type == DBUS_TYPE_BOOLEAN)) {
326 persistent_group = (entry.bool_value == TRUE) ? 1 : 0;
327 } else if (!os_strcmp(entry.key, "frequency") &&
328 (entry.type == DBUS_TYPE_INT32)) {
329 freq = entry.int32_value;
332 } else if (!os_strcmp(entry.key, "persistent_group_object") &&
333 entry.type == DBUS_TYPE_OBJECT_PATH)
334 pg_object_path = os_strdup(entry.str_value);
338 wpa_dbus_dict_entry_clear(&entry);
342 wpa_s = wpa_s->p2p_dev;
344 if (pg_object_path != NULL) {
346 * A persistent group Object Path is defined meaning we want
347 * to re-invoke a persistent group.
350 iface = wpas_dbus_new_decompose_object_path(pg_object_path, 1,
353 os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
355 wpas_dbus_error_invalid_args(message,
360 group_id = strtoul(net_id_str, NULL, 10);
361 if (errno == EINVAL) {
362 reply = wpas_dbus_error_invalid_args(
363 message, pg_object_path);
367 /* Get the SSID structure from the persistent group id */
368 ssid = wpa_config_get_network(wpa_s->conf, group_id);
369 if (ssid == NULL || ssid->disabled != 2)
372 if (wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 0, 0, 0,
374 reply = wpas_dbus_error_unknown_error(
376 "Failed to reinvoke a persistent group");
379 } else if (wpas_p2p_group_add(wpa_s, persistent_group, freq, 0, 0))
383 os_free(pg_object_path);
388 wpa_dbus_dict_entry_clear(&entry);
390 reply = wpas_dbus_error_invalid_args(message, NULL);
395 DBusMessage * wpas_dbus_handler_p2p_disconnect(DBusMessage *message,
396 struct wpa_supplicant *wpa_s)
398 if (wpas_p2p_disconnect(wpa_s))
399 return wpas_dbus_error_unknown_error(message,
400 "failed to disconnect");
406 static dbus_bool_t wpa_dbus_p2p_check_enabled(struct wpa_supplicant *wpa_s,
407 DBusMessage *message,
408 DBusMessage **out_reply,
411 /* Return an error message or an error if P2P isn't available */
412 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL) {
414 *out_reply = dbus_message_new_error(
415 message, DBUS_ERROR_FAILED,
416 "P2P is not available for this interface");
418 dbus_set_error_const(error, DBUS_ERROR_FAILED,
419 "P2P is not available for this "
427 DBusMessage * wpas_dbus_handler_p2p_flush(DBusMessage *message,
428 struct wpa_supplicant *wpa_s)
430 DBusMessage *reply = NULL;
432 if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL))
436 wpa_s = wpa_s->p2p_dev;
438 os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
439 wpa_s->force_long_sd = 0;
440 p2p_flush(wpa_s->global->p2p);
446 DBusMessage * wpas_dbus_handler_p2p_connect(DBusMessage *message,
447 struct wpa_supplicant *wpa_s)
449 DBusMessageIter iter_dict;
450 DBusMessage *reply = NULL;
451 DBusMessageIter iter;
452 struct wpa_dbus_dict_entry entry;
453 char *peer_object_path = NULL;
454 int persistent_group = 0;
456 int authorize_only = 0;
461 enum p2p_wps_method wps_method = WPS_NOT_READY;
463 char *err_msg = NULL;
466 if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL))
469 dbus_message_iter_init(message, &iter);
471 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
474 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
475 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
478 if (!os_strcmp(entry.key, "peer") &&
479 (entry.type == DBUS_TYPE_OBJECT_PATH)) {
480 peer_object_path = os_strdup(entry.str_value);
481 } else if (!os_strcmp(entry.key, "persistent") &&
482 (entry.type == DBUS_TYPE_BOOLEAN)) {
483 persistent_group = (entry.bool_value == TRUE) ? 1 : 0;
484 } else if (!os_strcmp(entry.key, "join") &&
485 (entry.type == DBUS_TYPE_BOOLEAN)) {
486 join = (entry.bool_value == TRUE) ? 1 : 0;
487 } else if (!os_strcmp(entry.key, "authorize_only") &&
488 (entry.type == DBUS_TYPE_BOOLEAN)) {
489 authorize_only = (entry.bool_value == TRUE) ? 1 : 0;
490 } else if (!os_strcmp(entry.key, "frequency") &&
491 (entry.type == DBUS_TYPE_INT32)) {
492 freq = entry.int32_value;
495 } else if (!os_strcmp(entry.key, "go_intent") &&
496 (entry.type == DBUS_TYPE_INT32)) {
497 go_intent = entry.int32_value;
498 if ((go_intent < 0) || (go_intent > 15))
500 } else if (!os_strcmp(entry.key, "wps_method") &&
501 (entry.type == DBUS_TYPE_STRING)) {
502 if (!os_strcmp(entry.str_value, "pbc"))
503 wps_method = WPS_PBC;
504 else if (!os_strcmp(entry.str_value, "pin"))
505 wps_method = WPS_PIN_DISPLAY;
506 else if (!os_strcmp(entry.str_value, "display"))
507 wps_method = WPS_PIN_DISPLAY;
508 else if (!os_strcmp(entry.str_value, "keypad"))
509 wps_method = WPS_PIN_KEYPAD;
512 } else if (!os_strcmp(entry.key, "pin") &&
513 (entry.type == DBUS_TYPE_STRING)) {
514 pin = os_strdup(entry.str_value);
518 wpa_dbus_dict_entry_clear(&entry);
521 if (!peer_object_path || (wps_method == WPS_NOT_READY) ||
522 (parse_peer_object_path(peer_object_path, addr) < 0) ||
523 !p2p_peer_known(wpa_s->global->p2p, addr))
527 * Validate the wps_method specified and the pin value.
529 if ((!pin || !pin[0]) && (wps_method == WPS_PIN_KEYPAD))
533 wpa_s = wpa_s->p2p_dev;
535 new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
536 persistent_group, 0, join, authorize_only,
537 go_intent, freq, -1, 0, 0, 0);
542 os_snprintf(npin, sizeof(npin), "%08d", new_pin);
543 generated_pin = npin;
544 reply = dbus_message_new_method_return(message);
545 dbus_message_append_args(reply, DBUS_TYPE_STRING,
546 &generated_pin, DBUS_TYPE_INVALID);
550 err_msg = "connect failed due to channel "
552 iface = WPAS_DBUS_ERROR_CONNECT_CHANNEL_UNAVAILABLE;
556 err_msg = "connect failed due to unsupported channel.";
557 iface = WPAS_DBUS_ERROR_CONNECT_CHANNEL_UNSUPPORTED;
561 err_msg = "connect failed due to unspecified error.";
562 iface = WPAS_DBUS_ERROR_CONNECT_UNSPECIFIED_ERROR;
568 * Do we need specialized errors corresponding to above
569 * error conditions as against just returning a different
572 reply = dbus_message_new_error(message, iface, err_msg);
576 os_free(peer_object_path);
580 wpa_dbus_dict_entry_clear(&entry);
582 reply = wpas_dbus_error_invalid_args(message, NULL);
587 DBusMessage * wpas_dbus_handler_p2p_invite(DBusMessage *message,
588 struct wpa_supplicant *wpa_s)
590 DBusMessageIter iter_dict;
591 DBusMessage *reply = NULL;
592 DBusMessageIter iter;
593 struct wpa_dbus_dict_entry entry;
594 char *peer_object_path = NULL;
595 char *pg_object_path = NULL;
597 char *net_id_str = NULL;
598 u8 peer_addr[ETH_ALEN];
599 unsigned int group_id = 0;
601 struct wpa_ssid *ssid;
603 if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL))
606 dbus_message_iter_init(message, &iter);
608 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
611 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
612 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
615 if (!os_strcmp(entry.key, "peer") &&
616 (entry.type == DBUS_TYPE_OBJECT_PATH)) {
617 peer_object_path = os_strdup(entry.str_value);
618 wpa_dbus_dict_entry_clear(&entry);
619 } else if (!os_strcmp(entry.key, "persistent_group_object") &&
620 (entry.type == DBUS_TYPE_OBJECT_PATH)) {
621 pg_object_path = os_strdup(entry.str_value);
623 wpa_dbus_dict_entry_clear(&entry);
625 wpa_dbus_dict_entry_clear(&entry);
630 if (!peer_object_path ||
631 (parse_peer_object_path(peer_object_path, peer_addr) < 0) ||
632 !p2p_peer_known(wpa_s->global->p2p, peer_addr)) {
637 wpa_s = wpa_s->p2p_dev;
641 * A group ID is defined meaning we want to re-invoke a
645 iface = wpas_dbus_new_decompose_object_path(pg_object_path, 1,
648 os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
649 reply = wpas_dbus_error_invalid_args(message,
654 group_id = strtoul(net_id_str, NULL, 10);
655 if (errno == EINVAL) {
656 reply = wpas_dbus_error_invalid_args(
657 message, pg_object_path);
661 /* Get the SSID structure from the persistent group id */
662 ssid = wpa_config_get_network(wpa_s->conf, group_id);
663 if (ssid == NULL || ssid->disabled != 2)
666 if (wpas_p2p_invite(wpa_s, peer_addr, ssid, NULL, 0, 0, 0, 0) <
668 reply = wpas_dbus_error_unknown_error(
670 "Failed to reinvoke a persistent group");
675 * No group ID means propose to a peer to join my active group
677 if (wpas_p2p_invite_group(wpa_s, wpa_s->ifname,
679 reply = wpas_dbus_error_unknown_error(
680 message, "Failed to join to an active group");
686 os_free(pg_object_path);
687 os_free(peer_object_path);
691 reply = wpas_dbus_error_invalid_args(message, NULL);
696 DBusMessage * wpas_dbus_handler_p2p_prov_disc_req(DBusMessage *message,
697 struct wpa_supplicant *wpa_s)
699 DBusMessageIter iter;
700 char *peer_object_path = NULL;
701 char *config_method = NULL;
702 u8 peer_addr[ETH_ALEN];
704 dbus_message_iter_init(message, &iter);
705 dbus_message_iter_get_basic(&iter, &peer_object_path);
707 if (parse_peer_object_path(peer_object_path, peer_addr) < 0)
708 return wpas_dbus_error_invalid_args(message, NULL);
710 dbus_message_iter_next(&iter);
711 dbus_message_iter_get_basic(&iter, &config_method);
714 * Validation checks on config_method are being duplicated here
715 * to be able to return invalid args reply since the error code
716 * from p2p module are not granular enough (yet).
718 if (os_strcmp(config_method, "display") &&
719 os_strcmp(config_method, "keypad") &&
720 os_strcmp(config_method, "pbc") &&
721 os_strcmp(config_method, "pushbutton"))
722 return wpas_dbus_error_invalid_args(message, NULL);
725 wpa_s = wpa_s->p2p_dev;
727 if (wpas_p2p_prov_disc(wpa_s, peer_addr, config_method,
728 WPAS_P2P_PD_FOR_GO_NEG) < 0)
729 return wpas_dbus_error_unknown_error(message,
730 "Failed to send provision discovery request");
737 * P2P Device property accessor methods.
740 dbus_bool_t wpas_dbus_getter_p2p_device_config(DBusMessageIter *iter,
744 struct wpa_supplicant *wpa_s = user_data;
745 DBusMessageIter variant_iter, dict_iter;
746 DBusMessageIter iter_secdev_dict_entry, iter_secdev_dict_val,
747 iter_secdev_dict_array;
748 const char *dev_name;
749 int num_vendor_extensions = 0;
751 const struct wpabuf *vendor_ext[P2P_MAX_WPS_VENDOR_EXT];
753 if (!wpa_dbus_p2p_check_enabled(wpa_s, NULL, NULL, error))
757 wpa_s = wpa_s->p2p_dev;
759 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
760 "a{sv}", &variant_iter) ||
761 !wpa_dbus_dict_open_write(&variant_iter, &dict_iter))
765 dev_name = wpa_s->conf->device_name;
767 !wpa_dbus_dict_append_string(&dict_iter, "DeviceName", dev_name))
770 /* Primary device type */
771 if (!wpa_dbus_dict_append_byte_array(&dict_iter, "PrimaryDeviceType",
772 (char *)wpa_s->conf->device_type,
776 /* Secondary device types */
777 if (wpa_s->conf->num_sec_device_types) {
778 if (!wpa_dbus_dict_begin_array(&dict_iter,
779 "SecondaryDeviceTypes",
780 DBUS_TYPE_ARRAY_AS_STRING
781 DBUS_TYPE_BYTE_AS_STRING,
782 &iter_secdev_dict_entry,
783 &iter_secdev_dict_val,
784 &iter_secdev_dict_array))
787 for (i = 0; i < wpa_s->conf->num_sec_device_types; i++)
788 wpa_dbus_dict_bin_array_add_element(
789 &iter_secdev_dict_array,
790 wpa_s->conf->sec_device_type[i],
793 if (!wpa_dbus_dict_end_array(&dict_iter,
794 &iter_secdev_dict_entry,
795 &iter_secdev_dict_val,
796 &iter_secdev_dict_array))
800 /* Vendor Extensions */
801 for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
802 if (wpa_s->conf->wps_vendor_ext[i] == NULL)
804 vendor_ext[num_vendor_extensions++] =
805 wpa_s->conf->wps_vendor_ext[i];
808 if (num_vendor_extensions &&
809 !wpa_dbus_dict_append_wpabuf_array(&dict_iter,
812 num_vendor_extensions))
816 if (!wpa_dbus_dict_append_uint32(&dict_iter, "GOIntent",
817 wpa_s->conf->p2p_go_intent))
820 /* Persistent Reconnect */
821 if (!wpa_dbus_dict_append_bool(&dict_iter, "PersistentReconnect",
822 wpa_s->conf->persistent_reconnect))
825 /* Listen Reg Class */
826 if (!wpa_dbus_dict_append_uint32(&dict_iter, "ListenRegClass",
827 wpa_s->conf->p2p_listen_reg_class))
831 if (!wpa_dbus_dict_append_uint32(&dict_iter, "ListenChannel",
832 wpa_s->conf->p2p_listen_channel))
836 if (!wpa_dbus_dict_append_uint32(&dict_iter, "OperRegClass",
837 wpa_s->conf->p2p_oper_reg_class))
841 if (!wpa_dbus_dict_append_uint32(&dict_iter, "OperChannel",
842 wpa_s->conf->p2p_oper_channel))
846 if (wpa_s->conf->p2p_ssid_postfix &&
847 !wpa_dbus_dict_append_string(&dict_iter, "SsidPostfix",
848 wpa_s->conf->p2p_ssid_postfix))
852 if (!wpa_dbus_dict_append_bool(&dict_iter, "IntraBss",
853 wpa_s->conf->p2p_intra_bss))
857 if (!wpa_dbus_dict_append_uint32(&dict_iter, "GroupIdle",
858 wpa_s->conf->p2p_group_idle))
861 /* Dissasociation low ack */
862 if (!wpa_dbus_dict_append_uint32(&dict_iter, "disassoc_low_ack",
863 wpa_s->conf->disassoc_low_ack))
867 if (!wpa_dbus_dict_append_bool(&dict_iter, "NoGroupIface",
868 wpa_s->conf->p2p_no_group_iface))
871 /* P2P Search Delay */
872 if (!wpa_dbus_dict_append_uint32(&dict_iter, "p2p_search_delay",
873 wpa_s->conf->p2p_search_delay))
876 if (!wpa_dbus_dict_close_write(&variant_iter, &dict_iter) ||
877 !dbus_message_iter_close_container(iter, &variant_iter))
883 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
888 dbus_bool_t wpas_dbus_setter_p2p_device_config(DBusMessageIter *iter,
892 struct wpa_supplicant *wpa_s = user_data;
893 DBusMessageIter variant_iter, iter_dict;
894 struct wpa_dbus_dict_entry entry = {.type = DBUS_TYPE_STRING };
897 if (!wpa_dbus_p2p_check_enabled(wpa_s, NULL, NULL, error))
901 wpa_s = wpa_s->p2p_dev;
903 dbus_message_iter_recurse(iter, &variant_iter);
904 if (!wpa_dbus_dict_open_read(&variant_iter, &iter_dict, error))
907 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
908 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) {
909 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
910 "invalid message format");
914 if (os_strcmp(entry.key, "DeviceName") == 0) {
917 if (entry.type != DBUS_TYPE_STRING)
920 devname = os_strdup(entry.str_value);
922 goto err_no_mem_clear;
924 os_free(wpa_s->conf->device_name);
925 wpa_s->conf->device_name = devname;
927 wpa_s->conf->changed_parameters |=
928 CFG_CHANGED_DEVICE_NAME;
929 } else if (os_strcmp(entry.key, "PrimaryDeviceType") == 0) {
930 if (entry.type != DBUS_TYPE_ARRAY ||
931 entry.array_type != DBUS_TYPE_BYTE ||
932 entry.array_len != WPS_DEV_TYPE_LEN)
935 os_memcpy(wpa_s->conf->device_type,
936 entry.bytearray_value,
938 wpa_s->conf->changed_parameters |=
939 CFG_CHANGED_DEVICE_TYPE;
940 } else if (os_strcmp(entry.key, "SecondaryDeviceTypes") == 0) {
941 if (entry.type != DBUS_TYPE_ARRAY ||
942 entry.array_type != WPAS_DBUS_TYPE_BINARRAY ||
943 entry.array_len > MAX_SEC_DEVICE_TYPES)
946 for (i = 0; i < entry.array_len; i++)
947 if (wpabuf_len(entry.binarray_value[i]) !=
949 goto err_no_mem_clear;
950 for (i = 0; i < entry.array_len; i++)
951 os_memcpy(wpa_s->conf->sec_device_type[i],
952 wpabuf_head(entry.binarray_value[i]),
954 wpa_s->conf->num_sec_device_types = entry.array_len;
955 wpa_s->conf->changed_parameters |=
956 CFG_CHANGED_SEC_DEVICE_TYPE;
957 } else if (os_strcmp(entry.key, "VendorExtension") == 0) {
958 if ((entry.type != DBUS_TYPE_ARRAY) ||
959 (entry.array_type != WPAS_DBUS_TYPE_BINARRAY) ||
960 (entry.array_len > P2P_MAX_WPS_VENDOR_EXT))
963 wpa_s->conf->changed_parameters |=
964 CFG_CHANGED_VENDOR_EXTENSION;
966 for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
967 wpabuf_free(wpa_s->conf->wps_vendor_ext[i]);
968 if (i < entry.array_len) {
969 wpa_s->conf->wps_vendor_ext[i] =
970 entry.binarray_value[i];
971 entry.binarray_value[i] = NULL;
973 wpa_s->conf->wps_vendor_ext[i] = NULL;
975 } else if ((os_strcmp(entry.key, "GOIntent") == 0) &&
976 (entry.type == DBUS_TYPE_UINT32) &&
977 (entry.uint32_value <= 15))
978 wpa_s->conf->p2p_go_intent = entry.uint32_value;
979 else if ((os_strcmp(entry.key, "PersistentReconnect") == 0) &&
980 (entry.type == DBUS_TYPE_BOOLEAN))
981 wpa_s->conf->persistent_reconnect = entry.bool_value;
982 else if ((os_strcmp(entry.key, "ListenRegClass") == 0) &&
983 (entry.type == DBUS_TYPE_UINT32)) {
984 wpa_s->conf->p2p_listen_reg_class = entry.uint32_value;
985 wpa_s->conf->changed_parameters |=
986 CFG_CHANGED_P2P_LISTEN_CHANNEL;
987 } else if ((os_strcmp(entry.key, "ListenChannel") == 0) &&
988 (entry.type == DBUS_TYPE_UINT32)) {
989 wpa_s->conf->p2p_listen_channel = entry.uint32_value;
990 wpa_s->conf->changed_parameters |=
991 CFG_CHANGED_P2P_LISTEN_CHANNEL;
992 } else if ((os_strcmp(entry.key, "OperRegClass") == 0) &&
993 (entry.type == DBUS_TYPE_UINT32)) {
994 wpa_s->conf->p2p_oper_reg_class = entry.uint32_value;
995 wpa_s->conf->changed_parameters |=
996 CFG_CHANGED_P2P_OPER_CHANNEL;
997 } else if ((os_strcmp(entry.key, "OperChannel") == 0) &&
998 (entry.type == DBUS_TYPE_UINT32)) {
999 wpa_s->conf->p2p_oper_channel = entry.uint32_value;
1000 wpa_s->conf->changed_parameters |=
1001 CFG_CHANGED_P2P_OPER_CHANNEL;
1002 } else if (os_strcmp(entry.key, "SsidPostfix") == 0) {
1005 if (entry.type != DBUS_TYPE_STRING)
1008 postfix = os_strdup(entry.str_value);
1010 goto err_no_mem_clear;
1012 os_free(wpa_s->conf->p2p_ssid_postfix);
1013 wpa_s->conf->p2p_ssid_postfix = postfix;
1015 wpa_s->conf->changed_parameters |=
1016 CFG_CHANGED_P2P_SSID_POSTFIX;
1017 } else if ((os_strcmp(entry.key, "IntraBss") == 0) &&
1018 (entry.type == DBUS_TYPE_BOOLEAN)) {
1019 wpa_s->conf->p2p_intra_bss = entry.bool_value;
1020 wpa_s->conf->changed_parameters |=
1021 CFG_CHANGED_P2P_INTRA_BSS;
1022 } else if ((os_strcmp(entry.key, "GroupIdle") == 0) &&
1023 (entry.type == DBUS_TYPE_UINT32))
1024 wpa_s->conf->p2p_group_idle = entry.uint32_value;
1025 else if (os_strcmp(entry.key, "disassoc_low_ack") == 0 &&
1026 entry.type == DBUS_TYPE_UINT32)
1027 wpa_s->conf->disassoc_low_ack = entry.uint32_value;
1028 else if (os_strcmp(entry.key, "NoGroupIface") == 0 &&
1029 entry.type == DBUS_TYPE_BOOLEAN)
1030 wpa_s->conf->p2p_no_group_iface = entry.bool_value;
1031 else if (os_strcmp(entry.key, "p2p_search_delay") == 0 &&
1032 entry.type == DBUS_TYPE_UINT32)
1033 wpa_s->conf->p2p_search_delay = entry.uint32_value;
1037 wpa_dbus_dict_entry_clear(&entry);
1040 if (wpa_s->conf->changed_parameters) {
1041 /* Some changed parameters requires to update config*/
1042 wpa_supplicant_update_config(wpa_s);
1048 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
1049 "invalid message format");
1050 wpa_dbus_dict_entry_clear(&entry);
1054 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1055 wpa_dbus_dict_entry_clear(&entry);
1060 dbus_bool_t wpas_dbus_getter_p2p_peers(DBusMessageIter *iter, DBusError *error,
1063 struct wpa_supplicant *wpa_s = user_data;
1064 struct p2p_data *p2p = wpa_s->global->p2p;
1065 int next = 0, i = 0;
1066 int num = 0, out_of_mem = 0;
1068 const struct p2p_peer_info *peer_info = NULL;
1069 dbus_bool_t success = FALSE;
1071 struct dl_list peer_objpath_list;
1072 struct peer_objpath_node {
1073 struct dl_list list;
1074 char path[WPAS_DBUS_OBJECT_PATH_MAX];
1077 char **peer_obj_paths = NULL;
1079 if (!wpa_dbus_p2p_check_enabled(wpa_s, NULL, NULL, error))
1082 dl_list_init(&peer_objpath_list);
1084 /* Get the first peer info */
1085 peer_info = p2p_get_peer_found(p2p, NULL, next);
1087 /* Get next and accumulate them */
1089 while (peer_info != NULL) {
1090 node = os_zalloc(sizeof(struct peer_objpath_node));
1096 addr = peer_info->p2p_device_addr;
1097 os_snprintf(node->path, WPAS_DBUS_OBJECT_PATH_MAX,
1098 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART
1100 wpa_s->dbus_new_path, MAC2STR(addr));
1101 dl_list_add_tail(&peer_objpath_list, &node->list);
1104 peer_info = p2p_get_peer_found(p2p, addr, next);
1108 * Now construct the peer object paths in a form suitable for
1109 * array_property_getter helper below.
1111 peer_obj_paths = os_calloc(num, sizeof(char *));
1113 if (!peer_obj_paths) {
1118 dl_list_for_each_safe(node, tmp, &peer_objpath_list,
1119 struct peer_objpath_node, list)
1120 peer_obj_paths[i++] = node->path;
1122 success = wpas_dbus_simple_array_property_getter(iter,
1123 DBUS_TYPE_OBJECT_PATH,
1124 peer_obj_paths, num,
1129 os_free(peer_obj_paths);
1131 dl_list_for_each_safe(node, tmp, &peer_objpath_list,
1132 struct peer_objpath_node, list) {
1133 dl_list_del(&node->list);
1137 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1143 enum wpas_p2p_role {
1144 WPAS_P2P_ROLE_DEVICE,
1146 WPAS_P2P_ROLE_CLIENT,
1149 static enum wpas_p2p_role wpas_get_p2p_role(struct wpa_supplicant *wpa_s)
1151 struct wpa_ssid *ssid = wpa_s->current_ssid;
1154 return WPAS_P2P_ROLE_DEVICE;
1155 if (wpa_s->wpa_state != WPA_COMPLETED)
1156 return WPAS_P2P_ROLE_DEVICE;
1158 switch (ssid->mode) {
1159 case WPAS_MODE_P2P_GO:
1160 case WPAS_MODE_P2P_GROUP_FORMATION:
1161 return WPAS_P2P_ROLE_GO;
1162 case WPAS_MODE_INFRA:
1163 if (ssid->p2p_group)
1164 return WPAS_P2P_ROLE_CLIENT;
1165 return WPAS_P2P_ROLE_DEVICE;
1167 return WPAS_P2P_ROLE_DEVICE;
1172 dbus_bool_t wpas_dbus_getter_p2p_role(DBusMessageIter *iter, DBusError *error,
1175 struct wpa_supplicant *wpa_s = user_data;
1178 switch (wpas_get_p2p_role(wpa_s)) {
1179 case WPAS_P2P_ROLE_GO:
1182 case WPAS_P2P_ROLE_CLIENT:
1190 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &str,
1195 dbus_bool_t wpas_dbus_getter_p2p_group(DBusMessageIter *iter, DBusError *error,
1198 struct wpa_supplicant *wpa_s = user_data;
1199 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX];
1200 char *dbus_groupobj_path = path_buf;
1202 if (wpa_s->dbus_groupobj_path == NULL)
1203 os_snprintf(dbus_groupobj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1206 os_snprintf(dbus_groupobj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1207 "%s", wpa_s->dbus_groupobj_path);
1209 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
1210 &dbus_groupobj_path, error);
1214 dbus_bool_t wpas_dbus_getter_p2p_peergo(DBusMessageIter *iter,
1215 DBusError *error, void *user_data)
1217 struct wpa_supplicant *wpa_s = user_data;
1218 char go_peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1220 if (wpas_get_p2p_role(wpa_s) != WPAS_P2P_ROLE_CLIENT)
1221 os_snprintf(go_peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
1223 os_snprintf(go_peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1224 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
1226 wpa_s->dbus_new_path, MAC2STR(wpa_s->go_dev_addr));
1228 path = go_peer_obj_path;
1229 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
1235 * Peer object properties accessor methods
1238 dbus_bool_t wpas_dbus_getter_p2p_peer_device_name(DBusMessageIter *iter,
1242 struct peer_handler_args *peer_args = user_data;
1243 const struct p2p_peer_info *info;
1246 if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error))
1249 /* get the peer info */
1250 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1251 peer_args->p2p_device_addr, 0);
1253 dbus_set_error(error, DBUS_ERROR_FAILED,
1254 "failed to find peer");
1258 tmp = os_strdup(info->device_name);
1260 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1264 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp,
1266 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1276 dbus_bool_t wpas_dbus_getter_p2p_peer_primary_device_type(
1277 DBusMessageIter *iter, DBusError *error, void *user_data)
1279 struct peer_handler_args *peer_args = user_data;
1280 const struct p2p_peer_info *info;
1282 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1283 peer_args->p2p_device_addr, 0);
1285 dbus_set_error(error, DBUS_ERROR_FAILED,
1286 "failed to find peer");
1290 if (!wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
1293 WPS_DEV_TYPE_LEN, error)) {
1294 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1302 dbus_bool_t wpas_dbus_getter_p2p_peer_config_method(DBusMessageIter *iter,
1306 struct peer_handler_args *peer_args = user_data;
1307 const struct p2p_peer_info *info;
1309 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1310 peer_args->p2p_device_addr, 0);
1312 dbus_set_error(error, DBUS_ERROR_FAILED,
1313 "failed to find peer");
1317 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
1318 &info->config_methods, error)) {
1319 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1327 dbus_bool_t wpas_dbus_getter_p2p_peer_level(DBusMessageIter *iter,
1331 struct peer_handler_args *peer_args = user_data;
1332 const struct p2p_peer_info *info;
1334 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1335 peer_args->p2p_device_addr, 0);
1337 dbus_set_error(error, DBUS_ERROR_FAILED,
1338 "failed to find peer");
1342 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
1343 &info->level, error)) {
1344 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1352 dbus_bool_t wpas_dbus_getter_p2p_peer_device_capability(DBusMessageIter *iter,
1356 struct peer_handler_args *peer_args = user_data;
1357 const struct p2p_peer_info *info;
1359 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1360 peer_args->p2p_device_addr, 0);
1362 dbus_set_error(error, DBUS_ERROR_FAILED,
1363 "failed to find peer");
1367 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BYTE,
1368 &info->dev_capab, error)) {
1369 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1377 dbus_bool_t wpas_dbus_getter_p2p_peer_group_capability(DBusMessageIter *iter,
1381 struct peer_handler_args *peer_args = user_data;
1382 const struct p2p_peer_info *info;
1384 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1385 peer_args->p2p_device_addr, 0);
1387 dbus_set_error(error, DBUS_ERROR_FAILED,
1388 "failed to find peer");
1392 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BYTE,
1393 &info->group_capab, error)) {
1394 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1402 dbus_bool_t wpas_dbus_getter_p2p_peer_secondary_device_types(
1403 DBusMessageIter *iter, DBusError *error, void *user_data)
1405 struct peer_handler_args *peer_args = user_data;
1406 const struct p2p_peer_info *info;
1407 DBusMessageIter variant_iter, array_iter;
1409 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1410 peer_args->p2p_device_addr, 0);
1412 dbus_set_error(error, DBUS_ERROR_FAILED,
1413 "failed to find peer");
1417 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
1418 DBUS_TYPE_ARRAY_AS_STRING
1419 DBUS_TYPE_ARRAY_AS_STRING
1420 DBUS_TYPE_BYTE_AS_STRING,
1422 dbus_set_error(error, DBUS_ERROR_FAILED,
1423 "%s: failed to construct message 1", __func__);
1427 if (!dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
1428 DBUS_TYPE_ARRAY_AS_STRING
1429 DBUS_TYPE_BYTE_AS_STRING,
1431 dbus_set_error(error, DBUS_ERROR_FAILED,
1432 "%s: failed to construct message 2", __func__);
1436 if (info->wps_sec_dev_type_list_len) {
1437 const u8 *sec_dev_type_list = info->wps_sec_dev_type_list;
1438 int num_sec_device_types =
1439 info->wps_sec_dev_type_list_len / WPS_DEV_TYPE_LEN;
1441 DBusMessageIter inner_array_iter;
1443 for (i = 0; i < num_sec_device_types; i++) {
1444 if (!dbus_message_iter_open_container(
1445 &array_iter, DBUS_TYPE_ARRAY,
1446 DBUS_TYPE_BYTE_AS_STRING,
1447 &inner_array_iter)) {
1448 dbus_set_error(error, DBUS_ERROR_FAILED,
1449 "%s: failed to construct "
1455 if (!dbus_message_iter_append_fixed_array(
1456 &inner_array_iter, DBUS_TYPE_BYTE,
1457 &sec_dev_type_list, WPS_DEV_TYPE_LEN)) {
1458 dbus_set_error(error, DBUS_ERROR_FAILED,
1459 "%s: failed to construct "
1465 if (!dbus_message_iter_close_container(
1466 &array_iter, &inner_array_iter)) {
1467 dbus_set_error(error, DBUS_ERROR_FAILED,
1468 "%s: failed to construct "
1474 sec_dev_type_list += WPS_DEV_TYPE_LEN;
1478 if (!dbus_message_iter_close_container(&variant_iter, &array_iter)) {
1479 dbus_set_error(error, DBUS_ERROR_FAILED,
1480 "%s: failed to construct message 6", __func__);
1484 if (!dbus_message_iter_close_container(iter, &variant_iter)) {
1485 dbus_set_error(error, DBUS_ERROR_FAILED,
1486 "%s: failed to construct message 7", __func__);
1494 dbus_bool_t wpas_dbus_getter_p2p_peer_vendor_extension(DBusMessageIter *iter,
1498 struct wpabuf *vendor_extension[P2P_MAX_WPS_VENDOR_EXT];
1499 unsigned int i, num = 0;
1500 struct peer_handler_args *peer_args = user_data;
1501 const struct p2p_peer_info *info;
1503 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1504 peer_args->p2p_device_addr, 0);
1506 dbus_set_error(error, DBUS_ERROR_FAILED,
1507 "failed to find peer");
1511 /* Add WPS vendor extensions attribute */
1512 os_memset(vendor_extension, 0, sizeof(vendor_extension));
1513 for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
1514 if (info->wps_vendor_ext[i] == NULL)
1516 vendor_extension[num] = info->wps_vendor_ext[i];
1520 if (!wpas_dbus_simple_array_array_property_getter(iter, DBUS_TYPE_BYTE,
1529 dbus_bool_t wpas_dbus_getter_p2p_peer_ies(DBusMessageIter *iter,
1530 DBusError *error, void *user_data)
1532 struct peer_handler_args *peer_args = user_data;
1533 const struct p2p_peer_info *info;
1535 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1536 peer_args->p2p_device_addr, 0);
1538 dbus_set_error(error, DBUS_ERROR_FAILED,
1539 "failed to find peer");
1543 if (info->wfd_subelems == NULL)
1544 return wpas_dbus_simple_array_property_getter(iter,
1548 return wpas_dbus_simple_array_property_getter(
1549 iter, DBUS_TYPE_BYTE, (char *) info->wfd_subelems->buf,
1550 info->wfd_subelems->used, error);
1554 dbus_bool_t wpas_dbus_getter_p2p_peer_device_address(DBusMessageIter *iter,
1558 struct peer_handler_args *peer_args = user_data;
1559 const struct p2p_peer_info *info;
1561 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1562 peer_args->p2p_device_addr, 0);
1564 dbus_set_error(error, DBUS_ERROR_FAILED,
1565 "failed to find peer");
1569 return wpas_dbus_simple_array_property_getter(
1570 iter, DBUS_TYPE_BYTE, (char *) info->p2p_device_addr,
1575 struct peer_group_data {
1576 struct wpa_supplicant *wpa_s;
1577 const struct p2p_peer_info *info;
1579 unsigned int nb_paths;
1584 static int match_group_where_peer_is_client(struct p2p_group *group,
1587 struct peer_group_data *data = user_data;
1588 const struct p2p_group_config *cfg;
1589 struct wpa_supplicant *wpa_s_go;
1592 if (!p2p_group_is_client_connected(group, data->info->p2p_device_addr))
1595 cfg = p2p_group_get_config(group);
1597 wpa_s_go = wpas_get_p2p_go_iface(data->wpa_s, cfg->ssid,
1599 if (wpa_s_go == NULL)
1602 paths = os_realloc_array(data->paths, data->nb_paths + 1,
1607 data->paths = paths;
1608 data->paths[data->nb_paths] = wpa_s_go->dbus_groupobj_path;
1614 data->error = ENOMEM;
1619 dbus_bool_t wpas_dbus_getter_p2p_peer_groups(DBusMessageIter *iter,
1623 struct peer_handler_args *peer_args = user_data;
1624 const struct p2p_peer_info *info;
1625 struct peer_group_data data;
1626 struct wpa_supplicant *wpa_s, *wpa_s_go;
1627 dbus_bool_t success = FALSE;
1629 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1630 peer_args->p2p_device_addr, 0);
1632 dbus_set_error(error, DBUS_ERROR_FAILED,
1633 "failed to find peer");
1637 os_memset(&data, 0, sizeof(data));
1639 wpa_s = peer_args->wpa_s;
1641 wpa_s = wpa_s->p2p_dev;
1643 wpa_s_go = wpas_get_p2p_client_iface(wpa_s, info->p2p_device_addr);
1645 data.paths = os_calloc(1, sizeof(char *));
1646 if (data.paths == NULL)
1648 data.paths[0] = wpa_s_go->dbus_groupobj_path;
1652 data.wpa_s = peer_args->wpa_s;
1655 p2p_loop_on_all_groups(peer_args->wpa_s->global->p2p,
1656 match_group_where_peer_is_client, &data);
1660 if (data.paths == NULL) {
1661 return wpas_dbus_simple_array_property_getter(
1662 iter, DBUS_TYPE_OBJECT_PATH, NULL, 0, error);
1665 success = wpas_dbus_simple_array_property_getter(iter,
1666 DBUS_TYPE_OBJECT_PATH,
1668 data.nb_paths, error);
1672 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1674 os_free(data.paths);
1680 * wpas_dbus_getter_persistent_groups - Get array of persistent group objects
1681 * @iter: Pointer to incoming dbus message iter
1682 * @error: Location to store error on failure
1683 * @user_data: Function specific data
1684 * Returns: TRUE on success, FALSE on failure
1686 * Getter for "PersistentGroups" property.
1688 dbus_bool_t wpas_dbus_getter_persistent_groups(DBusMessageIter *iter,
1692 struct wpa_supplicant *wpa_s = user_data;
1693 struct wpa_ssid *ssid;
1695 unsigned int i = 0, num = 0;
1696 dbus_bool_t success = FALSE;
1698 if (wpa_s->conf == NULL) {
1699 wpa_printf(MSG_ERROR, "dbus: %s: "
1700 "An error occurred getting persistent groups list",
1702 dbus_set_error_const(error, DBUS_ERROR_FAILED, "an error "
1703 "occurred getting persistent groups list");
1707 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
1708 if (network_is_persistent_group(ssid))
1711 paths = os_calloc(num, sizeof(char *));
1713 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1717 /* Loop through configured networks and append object path of each */
1718 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1719 if (!network_is_persistent_group(ssid))
1721 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1722 if (paths[i] == NULL) {
1723 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
1727 /* Construct the object path for this network. */
1728 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
1729 "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%d",
1730 wpa_s->dbus_new_path, ssid->id);
1733 success = wpas_dbus_simple_array_property_getter(iter,
1734 DBUS_TYPE_OBJECT_PATH,
1739 os_free(paths[--i]);
1746 * wpas_dbus_getter_persistent_group_properties - Get options for a persistent
1748 * @iter: Pointer to incoming dbus message iter
1749 * @error: Location to store error on failure
1750 * @user_data: Function specific data
1751 * Returns: TRUE on success, FALSE on failure
1753 * Getter for "Properties" property of a persistent group.
1755 dbus_bool_t wpas_dbus_getter_persistent_group_properties(DBusMessageIter *iter,
1759 struct network_handler_args *net = user_data;
1761 /* Leveraging the fact that persistent group object is still
1762 * represented in same manner as network within.
1764 return wpas_dbus_getter_network_properties(iter, error, net);
1769 * wpas_dbus_setter_persistent_group_properties - Get options for a persistent
1771 * @iter: Pointer to incoming dbus message iter
1772 * @error: Location to store error on failure
1773 * @user_data: Function specific data
1774 * Returns: TRUE on success, FALSE on failure
1776 * Setter for "Properties" property of a persistent group.
1778 dbus_bool_t wpas_dbus_setter_persistent_group_properties(DBusMessageIter *iter,
1782 struct network_handler_args *net = user_data;
1783 struct wpa_ssid *ssid = net->ssid;
1784 DBusMessageIter variant_iter;
1787 * Leveraging the fact that persistent group object is still
1788 * represented in same manner as network within.
1790 dbus_message_iter_recurse(iter, &variant_iter);
1791 return set_network_properties(net->wpa_s, ssid, &variant_iter, error);
1796 * wpas_dbus_new_iface_add_persistent_group - Add a new configured
1798 * @message: Pointer to incoming dbus message
1799 * @wpa_s: wpa_supplicant structure for a network interface
1800 * Returns: A dbus message containing the object path of the new
1803 * Handler function for "AddPersistentGroup" method call of a P2P Device
1806 DBusMessage * wpas_dbus_handler_add_persistent_group(
1807 DBusMessage *message, struct wpa_supplicant *wpa_s)
1809 DBusMessage *reply = NULL;
1810 DBusMessageIter iter;
1811 struct wpa_ssid *ssid = NULL;
1812 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf;
1815 dbus_message_iter_init(message, &iter);
1817 ssid = wpa_config_add_network(wpa_s->conf);
1819 wpa_printf(MSG_ERROR, "dbus: %s: "
1820 "Cannot add new persistent group", __func__);
1821 reply = wpas_dbus_error_unknown_error(
1823 "wpa_supplicant could not add "
1824 "a persistent group on this interface.");
1828 /* Mark the ssid as being a persistent group before the notification */
1830 ssid->p2p_persistent_group = 1;
1831 wpas_notify_persistent_group_added(wpa_s, ssid);
1833 wpa_config_set_network_defaults(ssid);
1835 dbus_error_init(&error);
1836 if (!set_network_properties(wpa_s, ssid, &iter, &error)) {
1837 wpa_printf(MSG_DEBUG, "dbus: %s: "
1838 "Control interface could not set persistent group "
1839 "properties", __func__);
1840 reply = wpas_dbus_reply_new_from_error(message, &error,
1841 DBUS_ERROR_INVALID_ARGS,
1842 "Failed to set network "
1844 dbus_error_free(&error);
1848 /* Construct the object path for this network. */
1849 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
1850 "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%d",
1851 wpa_s->dbus_new_path, ssid->id);
1853 reply = dbus_message_new_method_return(message);
1854 if (reply == NULL) {
1855 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1859 if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
1860 DBUS_TYPE_INVALID)) {
1861 dbus_message_unref(reply);
1862 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1871 wpas_notify_persistent_group_removed(wpa_s, ssid);
1872 wpa_config_remove_network(wpa_s->conf, ssid->id);
1879 * wpas_dbus_handler_remove_persistent_group - Remove a configured persistent
1881 * @message: Pointer to incoming dbus message
1882 * @wpa_s: wpa_supplicant structure for a network interface
1883 * Returns: NULL on success or dbus error on failure
1885 * Handler function for "RemovePersistentGroup" method call of a P2P Device
1888 DBusMessage * wpas_dbus_handler_remove_persistent_group(
1889 DBusMessage *message, struct wpa_supplicant *wpa_s)
1891 DBusMessage *reply = NULL;
1893 char *iface = NULL, *persistent_group_id = NULL;
1895 struct wpa_ssid *ssid;
1897 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
1901 * Extract the network ID and ensure the network is actually a child of
1904 iface = wpas_dbus_new_decompose_object_path(op, 1,
1905 &persistent_group_id,
1907 if (iface == NULL || os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
1908 reply = wpas_dbus_error_invalid_args(message, op);
1912 id = strtoul(persistent_group_id, NULL, 10);
1913 if (errno == EINVAL) {
1914 reply = wpas_dbus_error_invalid_args(message, op);
1918 ssid = wpa_config_get_network(wpa_s->conf, id);
1920 reply = wpas_dbus_error_persistent_group_unknown(message);
1924 wpas_notify_persistent_group_removed(wpa_s, ssid);
1926 if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
1927 wpa_printf(MSG_ERROR, "dbus: %s: "
1928 "error occurred when removing persistent group %d",
1930 reply = wpas_dbus_error_unknown_error(
1932 "error removing the specified persistent group on "
1939 os_free(persistent_group_id);
1944 static void remove_persistent_group(struct wpa_supplicant *wpa_s,
1945 struct wpa_ssid *ssid)
1947 wpas_notify_persistent_group_removed(wpa_s, ssid);
1949 if (wpa_config_remove_network(wpa_s->conf, ssid->id) < 0) {
1950 wpa_printf(MSG_ERROR, "dbus: %s: "
1951 "error occurred when removing persistent group %d",
1952 __func__, ssid->id);
1959 * wpas_dbus_handler_remove_all_persistent_groups - Remove all configured
1961 * @message: Pointer to incoming dbus message
1962 * @wpa_s: wpa_supplicant structure for a network interface
1963 * Returns: NULL on success or dbus error on failure
1965 * Handler function for "RemoveAllPersistentGroups" method call of a
1966 * P2P Device interface.
1968 DBusMessage * wpas_dbus_handler_remove_all_persistent_groups(
1969 DBusMessage *message, struct wpa_supplicant *wpa_s)
1971 struct wpa_ssid *ssid, *next;
1972 struct wpa_config *config;
1974 config = wpa_s->conf;
1975 ssid = config->ssid;
1978 if (network_is_persistent_group(ssid))
1979 remove_persistent_group(wpa_s, ssid);
1987 * Group object properties accessor methods
1990 dbus_bool_t wpas_dbus_getter_p2p_group_members(DBusMessageIter *iter,
1994 struct wpa_supplicant *wpa_s = user_data;
1995 struct wpa_ssid *ssid;
1996 unsigned int num_members;
2001 dbus_bool_t success = FALSE;
2003 /* Verify correct role for this property */
2004 if (wpas_get_p2p_role(wpa_s) != WPAS_P2P_ROLE_GO) {
2005 return wpas_dbus_simple_array_property_getter(
2006 iter, DBUS_TYPE_OBJECT_PATH, NULL, 0, error);
2009 ssid = wpa_s->conf->ssid;
2010 /* At present WPAS P2P_GO mode only applicable for p2p_go */
2011 if (ssid->mode != WPAS_MODE_P2P_GO &&
2012 ssid->mode != WPAS_MODE_AP &&
2013 ssid->mode != WPAS_MODE_P2P_GROUP_FORMATION)
2016 num_members = p2p_get_group_num_members(wpa_s->p2p_group);
2018 paths = os_calloc(num_members, sizeof(char *));
2023 while ((addr = p2p_iterate_group_members(wpa_s->p2p_group, &next))) {
2024 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
2027 os_snprintf(paths[i], WPAS_DBUS_OBJECT_PATH_MAX,
2028 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART
2030 wpa_s->parent->dbus_new_path, MAC2STR(addr));
2034 success = wpas_dbus_simple_array_property_getter(iter,
2035 DBUS_TYPE_OBJECT_PATH,
2039 for (i = 0; i < num_members; i++)
2045 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
2047 for (i = 0; i < num_members; i++)
2055 dbus_bool_t wpas_dbus_getter_p2p_group_ssid(DBusMessageIter *iter,
2056 DBusError *error, void *user_data)
2058 struct wpa_supplicant *wpa_s = user_data;
2059 if (wpa_s->current_ssid == NULL)
2061 return wpas_dbus_simple_array_property_getter(
2062 iter, DBUS_TYPE_BYTE, wpa_s->current_ssid->ssid,
2063 wpa_s->current_ssid->ssid_len, error);
2067 dbus_bool_t wpas_dbus_getter_p2p_group_bssid(DBusMessageIter *iter,
2071 struct wpa_supplicant *wpa_s = user_data;
2072 u8 role = wpas_get_p2p_role(wpa_s);
2075 if (role == WPAS_P2P_ROLE_CLIENT) {
2076 if (wpa_s->current_ssid == NULL)
2078 p_bssid = wpa_s->current_ssid->bssid;
2080 if (wpa_s->ap_iface == NULL)
2082 p_bssid = wpa_s->ap_iface->bss[0]->own_addr;
2085 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
2091 dbus_bool_t wpas_dbus_getter_p2p_group_frequency(DBusMessageIter *iter,
2095 struct wpa_supplicant *wpa_s = user_data;
2097 u8 role = wpas_get_p2p_role(wpa_s);
2099 if (role == WPAS_P2P_ROLE_CLIENT) {
2100 if (wpa_s->go_params == NULL)
2102 op_freq = wpa_s->go_params->freq;
2104 if (wpa_s->ap_iface == NULL)
2106 op_freq = wpa_s->ap_iface->freq;
2109 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
2114 dbus_bool_t wpas_dbus_getter_p2p_group_passphrase(DBusMessageIter *iter,
2118 struct wpa_supplicant *wpa_s = user_data;
2119 u8 role = wpas_get_p2p_role(wpa_s);
2120 char *p_pass = NULL;
2122 /* Verify correct role for this property */
2123 if (role == WPAS_P2P_ROLE_GO) {
2124 if (wpa_s->current_ssid == NULL)
2126 p_pass = wpa_s->current_ssid->passphrase;
2130 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
2136 dbus_bool_t wpas_dbus_getter_p2p_group_psk(DBusMessageIter *iter,
2137 DBusError *error, void *user_data)
2139 struct wpa_supplicant *wpa_s = user_data;
2140 u8 role = wpas_get_p2p_role(wpa_s);
2144 /* Verify correct role for this property */
2145 if (role == WPAS_P2P_ROLE_CLIENT) {
2146 if (wpa_s->current_ssid == NULL)
2148 p_psk = wpa_s->current_ssid->psk;
2152 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
2153 &p_psk, psk_len, error);
2157 dbus_bool_t wpas_dbus_getter_p2p_group_vendor_ext(DBusMessageIter *iter,
2161 struct wpa_supplicant *wpa_s = user_data;
2162 struct hostapd_data *hapd;
2163 struct wpabuf *vendor_ext[MAX_WPS_VENDOR_EXTENSIONS];
2164 unsigned int i, num_vendor_ext = 0;
2166 os_memset(vendor_ext, 0, sizeof(vendor_ext));
2168 /* Verify correct role for this property */
2169 if (wpas_get_p2p_role(wpa_s) == WPAS_P2P_ROLE_GO) {
2170 if (wpa_s->ap_iface == NULL)
2172 hapd = wpa_s->ap_iface->bss[0];
2174 /* Parse WPS Vendor Extensions sent in Beacon/Probe Response */
2175 for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
2176 if (hapd->conf->wps_vendor_ext[i] == NULL)
2178 vendor_ext[num_vendor_ext++] =
2179 hapd->conf->wps_vendor_ext[i];
2183 /* Return vendor extensions or no data */
2184 return wpas_dbus_simple_array_array_property_getter(iter,
2192 dbus_bool_t wpas_dbus_setter_p2p_group_vendor_ext(DBusMessageIter *iter,
2196 struct wpa_supplicant *wpa_s = user_data;
2197 DBusMessageIter variant_iter, iter_dict;
2198 struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
2200 struct hostapd_data *hapd = NULL;
2202 if (wpas_get_p2p_role(wpa_s) == WPAS_P2P_ROLE_GO &&
2203 wpa_s->ap_iface != NULL)
2204 hapd = wpa_s->ap_iface->bss[0];
2208 dbus_message_iter_recurse(iter, &variant_iter);
2209 if (!wpa_dbus_dict_open_read(&variant_iter, &iter_dict, error))
2212 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2213 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) {
2214 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
2215 "invalid message format");
2219 if (os_strcmp(entry.key, "WPSVendorExtensions") == 0) {
2220 if (entry.type != DBUS_TYPE_ARRAY ||
2221 entry.array_type != WPAS_DBUS_TYPE_BINARRAY ||
2222 entry.array_len > MAX_WPS_VENDOR_EXTENSIONS)
2225 for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
2226 if (i < entry.array_len) {
2227 hapd->conf->wps_vendor_ext[i] =
2228 entry.binarray_value[i];
2229 entry.binarray_value[i] = NULL;
2231 hapd->conf->wps_vendor_ext[i] = NULL;
2234 hostapd_update_wps(hapd);
2238 wpa_dbus_dict_entry_clear(&entry);
2244 wpa_dbus_dict_entry_clear(&entry);
2245 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
2246 "invalid message format");
2251 DBusMessage * wpas_dbus_handler_p2p_add_service(DBusMessage *message,
2252 struct wpa_supplicant *wpa_s)
2254 DBusMessageIter iter_dict;
2255 DBusMessage *reply = NULL;
2256 DBusMessageIter iter;
2257 struct wpa_dbus_dict_entry entry;
2260 char *service = NULL;
2261 struct wpabuf *query = NULL;
2262 struct wpabuf *resp = NULL;
2265 dbus_message_iter_init(message, &iter);
2267 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
2270 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2271 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2274 if (!os_strcmp(entry.key, "service_type") &&
2275 (entry.type == DBUS_TYPE_STRING)) {
2276 if (!os_strcmp(entry.str_value, "upnp"))
2278 else if (!os_strcmp(entry.str_value, "bonjour"))
2282 } else if (!os_strcmp(entry.key, "version") &&
2283 entry.type == DBUS_TYPE_INT32) {
2284 version = entry.uint32_value;
2285 } else if (!os_strcmp(entry.key, "service") &&
2286 (entry.type == DBUS_TYPE_STRING)) {
2287 service = os_strdup(entry.str_value);
2288 } else if (!os_strcmp(entry.key, "query")) {
2289 if ((entry.type != DBUS_TYPE_ARRAY) ||
2290 (entry.array_type != DBUS_TYPE_BYTE))
2292 query = wpabuf_alloc_copy(
2293 entry.bytearray_value,
2295 } else if (!os_strcmp(entry.key, "response")) {
2296 if ((entry.type != DBUS_TYPE_ARRAY) ||
2297 (entry.array_type != DBUS_TYPE_BYTE))
2299 resp = wpabuf_alloc_copy(entry.bytearray_value,
2302 wpa_dbus_dict_entry_clear(&entry);
2306 if (version <= 0 || service == NULL)
2309 if (wpas_p2p_service_add_upnp(wpa_s, version, service) != 0)
2314 } else if (bonjour == 1) {
2315 if (query == NULL || resp == NULL)
2318 if (wpas_p2p_service_add_bonjour(wpa_s, query, resp) < 0)
2327 wpa_dbus_dict_entry_clear(&entry);
2332 return wpas_dbus_error_invalid_args(message, NULL);
2336 DBusMessage * wpas_dbus_handler_p2p_delete_service(
2337 DBusMessage *message, struct wpa_supplicant *wpa_s)
2339 DBusMessageIter iter_dict;
2340 DBusMessage *reply = NULL;
2341 DBusMessageIter iter;
2342 struct wpa_dbus_dict_entry entry;
2346 char *service = NULL;
2347 struct wpabuf *query = NULL;
2350 dbus_message_iter_init(message, &iter);
2352 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
2355 if (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2356 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2359 if (!os_strcmp(entry.key, "service_type") &&
2360 (entry.type == DBUS_TYPE_STRING)) {
2361 if (!os_strcmp(entry.str_value, "upnp"))
2363 else if (!os_strcmp(entry.str_value, "bonjour"))
2367 wpa_dbus_dict_entry_clear(&entry);
2371 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2372 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2374 if (!os_strcmp(entry.key, "version") &&
2375 entry.type == DBUS_TYPE_INT32)
2376 version = entry.uint32_value;
2377 else if (!os_strcmp(entry.key, "service") &&
2378 entry.type == DBUS_TYPE_STRING)
2379 service = os_strdup(entry.str_value);
2383 wpa_dbus_dict_entry_clear(&entry);
2386 if (version <= 0 || service == NULL)
2389 ret = wpas_p2p_service_del_upnp(wpa_s, version, service);
2393 } else if (bonjour == 1) {
2394 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2395 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2398 if (!os_strcmp(entry.key, "query")) {
2399 if ((entry.type != DBUS_TYPE_ARRAY) ||
2400 (entry.array_type != DBUS_TYPE_BYTE))
2402 query = wpabuf_alloc_copy(
2403 entry.bytearray_value,
2408 wpa_dbus_dict_entry_clear(&entry);
2414 ret = wpas_p2p_service_del_bonjour(wpa_s, query);
2423 wpa_dbus_dict_entry_clear(&entry);
2425 return wpas_dbus_error_invalid_args(message, NULL);
2429 DBusMessage * wpas_dbus_handler_p2p_flush_service(DBusMessage *message,
2430 struct wpa_supplicant *wpa_s)
2432 wpas_p2p_service_flush(wpa_s);
2437 DBusMessage * wpas_dbus_handler_p2p_service_sd_req(
2438 DBusMessage *message, struct wpa_supplicant *wpa_s)
2440 DBusMessageIter iter_dict;
2441 DBusMessage *reply = NULL;
2442 DBusMessageIter iter;
2443 struct wpa_dbus_dict_entry entry;
2445 char *service = NULL;
2446 char *peer_object_path = NULL;
2447 struct wpabuf *tlv = NULL;
2450 u8 addr_buf[ETH_ALEN], *addr;
2452 dbus_message_iter_init(message, &iter);
2454 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
2457 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2458 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2460 if (!os_strcmp(entry.key, "peer_object") &&
2461 entry.type == DBUS_TYPE_OBJECT_PATH) {
2462 peer_object_path = os_strdup(entry.str_value);
2463 } else if (!os_strcmp(entry.key, "service_type") &&
2464 entry.type == DBUS_TYPE_STRING) {
2465 if (!os_strcmp(entry.str_value, "upnp"))
2469 } else if (!os_strcmp(entry.key, "version") &&
2470 entry.type == DBUS_TYPE_INT32) {
2471 version = entry.uint32_value;
2472 } else if (!os_strcmp(entry.key, "service") &&
2473 entry.type == DBUS_TYPE_STRING) {
2474 service = os_strdup(entry.str_value);
2475 } else if (!os_strcmp(entry.key, "tlv")) {
2476 if (entry.type != DBUS_TYPE_ARRAY ||
2477 entry.array_type != DBUS_TYPE_BYTE)
2479 tlv = wpabuf_alloc_copy(entry.bytearray_value,
2484 wpa_dbus_dict_entry_clear(&entry);
2487 if (!peer_object_path) {
2490 if (parse_peer_object_path(peer_object_path, addr_buf) < 0 ||
2491 !p2p_peer_known(wpa_s->global->p2p, addr_buf))
2498 if (version <= 0 || service == NULL)
2501 ref = wpas_p2p_sd_request_upnp(wpa_s, addr, version, service);
2505 ref = wpas_p2p_sd_request(wpa_s, addr, tlv);
2510 reply = dbus_message_new_method_return(message);
2511 dbus_message_append_args(reply, DBUS_TYPE_UINT64,
2512 &ref, DBUS_TYPE_INVALID);
2514 reply = wpas_dbus_error_unknown_error(
2515 message, "Unable to send SD request");
2519 os_free(peer_object_path);
2522 wpa_dbus_dict_entry_clear(&entry);
2526 reply = wpas_dbus_error_invalid_args(message, NULL);
2531 DBusMessage * wpas_dbus_handler_p2p_service_sd_res(
2532 DBusMessage *message, struct wpa_supplicant *wpa_s)
2534 DBusMessageIter iter_dict;
2535 DBusMessage *reply = NULL;
2536 DBusMessageIter iter;
2537 struct wpa_dbus_dict_entry entry;
2538 char *peer_object_path = NULL;
2539 struct wpabuf *tlv = NULL;
2544 dbus_message_iter_init(message, &iter);
2546 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
2549 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2550 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2553 if (!os_strcmp(entry.key, "peer_object") &&
2554 entry.type == DBUS_TYPE_OBJECT_PATH) {
2555 peer_object_path = os_strdup(entry.str_value);
2556 } else if (!os_strcmp(entry.key, "frequency") &&
2557 entry.type == DBUS_TYPE_INT32) {
2558 freq = entry.uint32_value;
2559 } else if (!os_strcmp(entry.key, "dialog_token") &&
2560 entry.type == DBUS_TYPE_UINT32) {
2561 dlg_tok = entry.uint32_value;
2562 } else if (!os_strcmp(entry.key, "tlvs")) {
2563 if (entry.type != DBUS_TYPE_ARRAY ||
2564 entry.array_type != DBUS_TYPE_BYTE)
2566 tlv = wpabuf_alloc_copy(entry.bytearray_value,
2571 wpa_dbus_dict_entry_clear(&entry);
2573 if (!peer_object_path ||
2574 (parse_peer_object_path(peer_object_path, addr) < 0) ||
2575 !p2p_peer_known(wpa_s->global->p2p, addr))
2581 wpas_p2p_sd_response(wpa_s, freq, addr, (u8) dlg_tok, tlv);
2584 os_free(peer_object_path);
2587 wpa_dbus_dict_entry_clear(&entry);
2589 reply = wpas_dbus_error_invalid_args(message, NULL);
2594 DBusMessage * wpas_dbus_handler_p2p_service_sd_cancel_req(
2595 DBusMessage *message, struct wpa_supplicant *wpa_s)
2597 DBusMessageIter iter;
2600 dbus_message_iter_init(message, &iter);
2601 dbus_message_iter_get_basic(&iter, &req);
2606 if (wpas_p2p_sd_cancel_request(wpa_s, req) < 0)
2611 return wpas_dbus_error_invalid_args(message, NULL);
2615 DBusMessage * wpas_dbus_handler_p2p_service_update(
2616 DBusMessage *message, struct wpa_supplicant *wpa_s)
2618 wpas_p2p_sd_service_update(wpa_s);
2623 DBusMessage * wpas_dbus_handler_p2p_serv_disc_external(
2624 DBusMessage *message, struct wpa_supplicant *wpa_s)
2626 DBusMessageIter iter;
2629 dbus_message_iter_init(message, &iter);
2630 dbus_message_iter_get_basic(&iter, &ext);
2632 wpa_s->p2p_sd_over_ctrl_iface = ext;
2639 #ifdef CONFIG_WIFI_DISPLAY
2641 dbus_bool_t wpas_dbus_getter_global_wfd_ies(DBusMessageIter *iter,
2642 DBusError *error, void *user_data)
2644 struct wpa_global *global = user_data;
2648 ie = wifi_display_get_wfd_ie(global);
2650 return wpas_dbus_simple_array_property_getter(iter,
2654 ret = wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
2656 wpabuf_len(ie), error);
2663 dbus_bool_t wpas_dbus_setter_global_wfd_ies(DBusMessageIter *iter,
2664 DBusError *error, void *user_data)
2666 struct wpa_global *global = user_data;
2667 DBusMessageIter variant, array;
2668 struct wpabuf *ie = NULL;
2672 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_VARIANT)
2675 dbus_message_iter_recurse(iter, &variant);
2676 if (dbus_message_iter_get_arg_type(&variant) != DBUS_TYPE_ARRAY)
2679 dbus_message_iter_recurse(&variant, &array);
2680 dbus_message_iter_get_fixed_array(&array, &data, &len);
2682 wifi_display_enable(global, 0);
2683 wifi_display_deinit(global);
2688 ie = wpabuf_alloc(len);
2692 wpabuf_put_data(ie, data, len);
2693 if (wifi_display_subelem_set_from_ies(global, ie) != 0)
2696 if (global->wifi_display == 0)
2697 wifi_display_enable(global, 1);
2705 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
2706 "invalid message format");
2710 #endif /* CONFIG_WIFI_DISPLAY */