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 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
1699 if (network_is_persistent_group(ssid))
1702 paths = os_calloc(num, sizeof(char *));
1704 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1708 /* Loop through configured networks and append object path of each */
1709 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1710 if (!network_is_persistent_group(ssid))
1712 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1713 if (paths[i] == NULL) {
1714 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
1718 /* Construct the object path for this network. */
1719 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
1720 "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%d",
1721 wpa_s->dbus_new_path, ssid->id);
1724 success = wpas_dbus_simple_array_property_getter(iter,
1725 DBUS_TYPE_OBJECT_PATH,
1730 os_free(paths[--i]);
1737 * wpas_dbus_getter_persistent_group_properties - Get options for a persistent
1739 * @iter: Pointer to incoming dbus message iter
1740 * @error: Location to store error on failure
1741 * @user_data: Function specific data
1742 * Returns: TRUE on success, FALSE on failure
1744 * Getter for "Properties" property of a persistent group.
1746 dbus_bool_t wpas_dbus_getter_persistent_group_properties(DBusMessageIter *iter,
1750 struct network_handler_args *net = user_data;
1752 /* Leveraging the fact that persistent group object is still
1753 * represented in same manner as network within.
1755 return wpas_dbus_getter_network_properties(iter, error, net);
1760 * wpas_dbus_setter_persistent_group_properties - Get options for a persistent
1762 * @iter: Pointer to incoming dbus message iter
1763 * @error: Location to store error on failure
1764 * @user_data: Function specific data
1765 * Returns: TRUE on success, FALSE on failure
1767 * Setter for "Properties" property of a persistent group.
1769 dbus_bool_t wpas_dbus_setter_persistent_group_properties(DBusMessageIter *iter,
1773 struct network_handler_args *net = user_data;
1774 struct wpa_ssid *ssid = net->ssid;
1775 DBusMessageIter variant_iter;
1778 * Leveraging the fact that persistent group object is still
1779 * represented in same manner as network within.
1781 dbus_message_iter_recurse(iter, &variant_iter);
1782 return set_network_properties(net->wpa_s, ssid, &variant_iter, error);
1787 * wpas_dbus_new_iface_add_persistent_group - Add a new configured
1789 * @message: Pointer to incoming dbus message
1790 * @wpa_s: wpa_supplicant structure for a network interface
1791 * Returns: A dbus message containing the object path of the new
1794 * Handler function for "AddPersistentGroup" method call of a P2P Device
1797 DBusMessage * wpas_dbus_handler_add_persistent_group(
1798 DBusMessage *message, struct wpa_supplicant *wpa_s)
1800 DBusMessage *reply = NULL;
1801 DBusMessageIter iter;
1802 struct wpa_ssid *ssid = NULL;
1803 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf;
1806 dbus_message_iter_init(message, &iter);
1808 ssid = wpa_config_add_network(wpa_s->conf);
1810 wpa_printf(MSG_ERROR, "dbus: %s: "
1811 "Cannot add new persistent group", __func__);
1812 reply = wpas_dbus_error_unknown_error(
1814 "wpa_supplicant could not add "
1815 "a persistent group on this interface.");
1819 /* Mark the ssid as being a persistent group before the notification */
1821 ssid->p2p_persistent_group = 1;
1822 wpas_notify_persistent_group_added(wpa_s, ssid);
1824 wpa_config_set_network_defaults(ssid);
1826 dbus_error_init(&error);
1827 if (!set_network_properties(wpa_s, ssid, &iter, &error)) {
1828 wpa_printf(MSG_DEBUG, "dbus: %s: "
1829 "Control interface could not set persistent group "
1830 "properties", __func__);
1831 reply = wpas_dbus_reply_new_from_error(message, &error,
1832 DBUS_ERROR_INVALID_ARGS,
1833 "Failed to set network "
1835 dbus_error_free(&error);
1839 /* Construct the object path for this network. */
1840 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
1841 "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%d",
1842 wpa_s->dbus_new_path, ssid->id);
1844 reply = dbus_message_new_method_return(message);
1845 if (reply == NULL) {
1846 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1850 if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
1851 DBUS_TYPE_INVALID)) {
1852 dbus_message_unref(reply);
1853 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1862 wpas_notify_persistent_group_removed(wpa_s, ssid);
1863 wpa_config_remove_network(wpa_s->conf, ssid->id);
1870 * wpas_dbus_handler_remove_persistent_group - Remove a configured persistent
1872 * @message: Pointer to incoming dbus message
1873 * @wpa_s: wpa_supplicant structure for a network interface
1874 * Returns: NULL on success or dbus error on failure
1876 * Handler function for "RemovePersistentGroup" method call of a P2P Device
1879 DBusMessage * wpas_dbus_handler_remove_persistent_group(
1880 DBusMessage *message, struct wpa_supplicant *wpa_s)
1882 DBusMessage *reply = NULL;
1884 char *iface = NULL, *persistent_group_id = NULL;
1886 struct wpa_ssid *ssid;
1888 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
1892 * Extract the network ID and ensure the network is actually a child of
1895 iface = wpas_dbus_new_decompose_object_path(op, 1,
1896 &persistent_group_id,
1898 if (iface == NULL || os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
1899 reply = wpas_dbus_error_invalid_args(message, op);
1903 id = strtoul(persistent_group_id, NULL, 10);
1904 if (errno == EINVAL) {
1905 reply = wpas_dbus_error_invalid_args(message, op);
1909 ssid = wpa_config_get_network(wpa_s->conf, id);
1911 reply = wpas_dbus_error_persistent_group_unknown(message);
1915 wpas_notify_persistent_group_removed(wpa_s, ssid);
1917 if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
1918 wpa_printf(MSG_ERROR, "dbus: %s: "
1919 "error occurred when removing persistent group %d",
1921 reply = wpas_dbus_error_unknown_error(
1923 "error removing the specified persistent group on "
1930 os_free(persistent_group_id);
1935 static void remove_persistent_group(struct wpa_supplicant *wpa_s,
1936 struct wpa_ssid *ssid)
1938 wpas_notify_persistent_group_removed(wpa_s, ssid);
1940 if (wpa_config_remove_network(wpa_s->conf, ssid->id) < 0) {
1941 wpa_printf(MSG_ERROR, "dbus: %s: "
1942 "error occurred when removing persistent group %d",
1943 __func__, ssid->id);
1950 * wpas_dbus_handler_remove_all_persistent_groups - Remove all configured
1952 * @message: Pointer to incoming dbus message
1953 * @wpa_s: wpa_supplicant structure for a network interface
1954 * Returns: NULL on success or dbus error on failure
1956 * Handler function for "RemoveAllPersistentGroups" method call of a
1957 * P2P Device interface.
1959 DBusMessage * wpas_dbus_handler_remove_all_persistent_groups(
1960 DBusMessage *message, struct wpa_supplicant *wpa_s)
1962 struct wpa_ssid *ssid, *next;
1963 struct wpa_config *config;
1965 config = wpa_s->conf;
1966 ssid = config->ssid;
1969 if (network_is_persistent_group(ssid))
1970 remove_persistent_group(wpa_s, ssid);
1978 * Group object properties accessor methods
1981 dbus_bool_t wpas_dbus_getter_p2p_group_members(DBusMessageIter *iter,
1985 struct wpa_supplicant *wpa_s = user_data;
1986 struct wpa_ssid *ssid;
1987 unsigned int num_members;
1992 dbus_bool_t success = FALSE;
1994 /* Verify correct role for this property */
1995 if (wpas_get_p2p_role(wpa_s) != WPAS_P2P_ROLE_GO) {
1996 return wpas_dbus_simple_array_property_getter(
1997 iter, DBUS_TYPE_OBJECT_PATH, NULL, 0, error);
2000 ssid = wpa_s->conf->ssid;
2001 /* At present WPAS P2P_GO mode only applicable for p2p_go */
2002 if (ssid->mode != WPAS_MODE_P2P_GO &&
2003 ssid->mode != WPAS_MODE_AP &&
2004 ssid->mode != WPAS_MODE_P2P_GROUP_FORMATION)
2007 num_members = p2p_get_group_num_members(wpa_s->p2p_group);
2009 paths = os_calloc(num_members, sizeof(char *));
2014 while ((addr = p2p_iterate_group_members(wpa_s->p2p_group, &next))) {
2015 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
2018 os_snprintf(paths[i], WPAS_DBUS_OBJECT_PATH_MAX,
2019 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART
2021 wpa_s->parent->dbus_new_path, MAC2STR(addr));
2025 success = wpas_dbus_simple_array_property_getter(iter,
2026 DBUS_TYPE_OBJECT_PATH,
2030 for (i = 0; i < num_members; i++)
2036 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
2038 for (i = 0; i < num_members; i++)
2046 dbus_bool_t wpas_dbus_getter_p2p_group_ssid(DBusMessageIter *iter,
2047 DBusError *error, void *user_data)
2049 struct wpa_supplicant *wpa_s = user_data;
2050 if (wpa_s->current_ssid == NULL)
2052 return wpas_dbus_simple_array_property_getter(
2053 iter, DBUS_TYPE_BYTE, wpa_s->current_ssid->ssid,
2054 wpa_s->current_ssid->ssid_len, error);
2058 dbus_bool_t wpas_dbus_getter_p2p_group_bssid(DBusMessageIter *iter,
2062 struct wpa_supplicant *wpa_s = user_data;
2063 u8 role = wpas_get_p2p_role(wpa_s);
2066 if (role == WPAS_P2P_ROLE_CLIENT) {
2067 if (wpa_s->current_ssid == NULL)
2069 p_bssid = wpa_s->current_ssid->bssid;
2071 if (wpa_s->ap_iface == NULL)
2073 p_bssid = wpa_s->ap_iface->bss[0]->own_addr;
2076 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
2082 dbus_bool_t wpas_dbus_getter_p2p_group_frequency(DBusMessageIter *iter,
2086 struct wpa_supplicant *wpa_s = user_data;
2088 u8 role = wpas_get_p2p_role(wpa_s);
2090 if (role == WPAS_P2P_ROLE_CLIENT) {
2091 if (wpa_s->go_params == NULL)
2093 op_freq = wpa_s->go_params->freq;
2095 if (wpa_s->ap_iface == NULL)
2097 op_freq = wpa_s->ap_iface->freq;
2100 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
2105 dbus_bool_t wpas_dbus_getter_p2p_group_passphrase(DBusMessageIter *iter,
2109 struct wpa_supplicant *wpa_s = user_data;
2110 u8 role = wpas_get_p2p_role(wpa_s);
2111 char *p_pass = NULL;
2113 /* Verify correct role for this property */
2114 if (role == WPAS_P2P_ROLE_GO) {
2115 if (wpa_s->current_ssid == NULL)
2117 p_pass = wpa_s->current_ssid->passphrase;
2121 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
2127 dbus_bool_t wpas_dbus_getter_p2p_group_psk(DBusMessageIter *iter,
2128 DBusError *error, void *user_data)
2130 struct wpa_supplicant *wpa_s = user_data;
2131 u8 role = wpas_get_p2p_role(wpa_s);
2135 /* Verify correct role for this property */
2136 if (role == WPAS_P2P_ROLE_CLIENT) {
2137 if (wpa_s->current_ssid == NULL)
2139 p_psk = wpa_s->current_ssid->psk;
2143 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
2144 &p_psk, psk_len, error);
2148 dbus_bool_t wpas_dbus_getter_p2p_group_vendor_ext(DBusMessageIter *iter,
2152 struct wpa_supplicant *wpa_s = user_data;
2153 struct hostapd_data *hapd;
2154 struct wpabuf *vendor_ext[MAX_WPS_VENDOR_EXTENSIONS];
2155 unsigned int i, num_vendor_ext = 0;
2157 os_memset(vendor_ext, 0, sizeof(vendor_ext));
2159 /* Verify correct role for this property */
2160 if (wpas_get_p2p_role(wpa_s) == WPAS_P2P_ROLE_GO) {
2161 if (wpa_s->ap_iface == NULL)
2163 hapd = wpa_s->ap_iface->bss[0];
2165 /* Parse WPS Vendor Extensions sent in Beacon/Probe Response */
2166 for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
2167 if (hapd->conf->wps_vendor_ext[i] == NULL)
2169 vendor_ext[num_vendor_ext++] =
2170 hapd->conf->wps_vendor_ext[i];
2174 /* Return vendor extensions or no data */
2175 return wpas_dbus_simple_array_array_property_getter(iter,
2183 dbus_bool_t wpas_dbus_setter_p2p_group_vendor_ext(DBusMessageIter *iter,
2187 struct wpa_supplicant *wpa_s = user_data;
2188 DBusMessageIter variant_iter, iter_dict, array_iter, sub;
2189 struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
2191 struct hostapd_data *hapd = NULL;
2193 if (wpas_get_p2p_role(wpa_s) == WPAS_P2P_ROLE_GO &&
2194 wpa_s->ap_iface != NULL)
2195 hapd = wpa_s->ap_iface->bss[0];
2199 dbus_message_iter_recurse(iter, &variant_iter);
2200 if (dbus_message_iter_get_arg_type(&variant_iter) != DBUS_TYPE_ARRAY)
2204 * This is supposed to be array of bytearrays (aay), but the earlier
2205 * implementation used a dict with "WPSVendorExtensions" as the key in
2206 * this setter function which does not match the format used by the
2207 * getter function. For backwards compatibility, allow both formats to
2208 * be used in the setter.
2210 if (dbus_message_iter_get_element_type(&variant_iter) ==
2212 /* This is the proper format matching the getter */
2213 struct wpabuf *vals[MAX_WPS_VENDOR_EXTENSIONS];
2215 dbus_message_iter_recurse(&variant_iter, &array_iter);
2217 if (dbus_message_iter_get_arg_type(&array_iter) !=
2219 dbus_message_iter_get_element_type(&array_iter) !=
2221 wpa_printf(MSG_DEBUG,
2222 "dbus: Not an array of array of bytes");
2227 os_memset(vals, 0, sizeof(vals));
2229 while (dbus_message_iter_get_arg_type(&array_iter) ==
2234 if (i == MAX_WPS_VENDOR_EXTENSIONS) {
2235 wpa_printf(MSG_DEBUG,
2236 "dbus: Too many WPSVendorExtensions values");
2237 i = MAX_WPS_VENDOR_EXTENSIONS + 1;
2241 dbus_message_iter_recurse(&array_iter, &sub);
2242 dbus_message_iter_get_fixed_array(&sub, &val, &len);
2243 wpa_hexdump(MSG_DEBUG, "dbus: WPSVendorExtentions[]",
2245 vals[i] = wpabuf_alloc_copy(val, len);
2246 if (vals[i] == NULL) {
2247 i = MAX_WPS_VENDOR_EXTENSIONS + 1;
2251 dbus_message_iter_next(&array_iter);
2254 if (i > MAX_WPS_VENDOR_EXTENSIONS) {
2255 for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++)
2256 wpabuf_free(vals[i]);
2260 for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
2261 wpabuf_free(hapd->conf->wps_vendor_ext[i]);
2262 hapd->conf->wps_vendor_ext[i] = vals[i];
2265 hostapd_update_wps(hapd);
2270 if (dbus_message_iter_get_element_type(&variant_iter) !=
2271 DBUS_TYPE_DICT_ENTRY)
2274 wpa_printf(MSG_DEBUG,
2275 "dbus: Try to use backwards compatibility version of WPSVendorExtensions setter");
2276 if (!wpa_dbus_dict_open_read(&variant_iter, &iter_dict, error))
2279 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2280 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) {
2281 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
2282 "invalid message format");
2286 if (os_strcmp(entry.key, "WPSVendorExtensions") == 0) {
2287 if (entry.type != DBUS_TYPE_ARRAY ||
2288 entry.array_type != WPAS_DBUS_TYPE_BINARRAY ||
2289 entry.array_len > MAX_WPS_VENDOR_EXTENSIONS)
2292 for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
2293 wpabuf_free(hapd->conf->wps_vendor_ext[i]);
2294 if (i < entry.array_len) {
2295 hapd->conf->wps_vendor_ext[i] =
2296 entry.binarray_value[i];
2297 entry.binarray_value[i] = NULL;
2299 hapd->conf->wps_vendor_ext[i] = NULL;
2302 hostapd_update_wps(hapd);
2306 wpa_dbus_dict_entry_clear(&entry);
2312 wpa_dbus_dict_entry_clear(&entry);
2313 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
2314 "invalid message format");
2319 DBusMessage * wpas_dbus_handler_p2p_add_service(DBusMessage *message,
2320 struct wpa_supplicant *wpa_s)
2322 DBusMessageIter iter_dict;
2323 DBusMessage *reply = NULL;
2324 DBusMessageIter iter;
2325 struct wpa_dbus_dict_entry entry;
2328 char *service = NULL;
2329 struct wpabuf *query = NULL;
2330 struct wpabuf *resp = NULL;
2333 dbus_message_iter_init(message, &iter);
2335 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
2338 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2339 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2342 if (!os_strcmp(entry.key, "service_type") &&
2343 (entry.type == DBUS_TYPE_STRING)) {
2344 if (!os_strcmp(entry.str_value, "upnp"))
2346 else if (!os_strcmp(entry.str_value, "bonjour"))
2350 } else if (!os_strcmp(entry.key, "version") &&
2351 entry.type == DBUS_TYPE_INT32) {
2352 version = entry.uint32_value;
2353 } else if (!os_strcmp(entry.key, "service") &&
2354 (entry.type == DBUS_TYPE_STRING)) {
2356 service = os_strdup(entry.str_value);
2357 } else if (!os_strcmp(entry.key, "query")) {
2358 if ((entry.type != DBUS_TYPE_ARRAY) ||
2359 (entry.array_type != DBUS_TYPE_BYTE))
2361 query = wpabuf_alloc_copy(
2362 entry.bytearray_value,
2364 } else if (!os_strcmp(entry.key, "response")) {
2365 if ((entry.type != DBUS_TYPE_ARRAY) ||
2366 (entry.array_type != DBUS_TYPE_BYTE))
2368 resp = wpabuf_alloc_copy(entry.bytearray_value,
2371 wpa_dbus_dict_entry_clear(&entry);
2375 if (version <= 0 || service == NULL)
2378 if (wpas_p2p_service_add_upnp(wpa_s, version, service) != 0)
2381 } else if (bonjour == 1) {
2382 if (query == NULL || resp == NULL)
2385 if (wpas_p2p_service_add_bonjour(wpa_s, query, resp) < 0)
2395 wpa_dbus_dict_entry_clear(&entry);
2400 return wpas_dbus_error_invalid_args(message, NULL);
2404 DBusMessage * wpas_dbus_handler_p2p_delete_service(
2405 DBusMessage *message, struct wpa_supplicant *wpa_s)
2407 DBusMessageIter iter_dict;
2408 DBusMessage *reply = NULL;
2409 DBusMessageIter iter;
2410 struct wpa_dbus_dict_entry entry;
2414 char *service = NULL;
2415 struct wpabuf *query = NULL;
2418 dbus_message_iter_init(message, &iter);
2420 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
2423 if (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2424 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2427 if (!os_strcmp(entry.key, "service_type") &&
2428 (entry.type == DBUS_TYPE_STRING)) {
2429 if (!os_strcmp(entry.str_value, "upnp"))
2431 else if (!os_strcmp(entry.str_value, "bonjour"))
2435 wpa_dbus_dict_entry_clear(&entry);
2439 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2440 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2442 if (!os_strcmp(entry.key, "version") &&
2443 entry.type == DBUS_TYPE_INT32)
2444 version = entry.uint32_value;
2445 else if (!os_strcmp(entry.key, "service") &&
2446 entry.type == DBUS_TYPE_STRING) {
2448 service = os_strdup(entry.str_value);
2452 wpa_dbus_dict_entry_clear(&entry);
2455 if (version <= 0 || service == NULL)
2458 ret = wpas_p2p_service_del_upnp(wpa_s, version, service);
2461 } else if (bonjour == 1) {
2462 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2463 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2466 if (!os_strcmp(entry.key, "query")) {
2467 if ((entry.type != DBUS_TYPE_ARRAY) ||
2468 (entry.array_type != DBUS_TYPE_BYTE))
2471 query = wpabuf_alloc_copy(
2472 entry.bytearray_value,
2477 wpa_dbus_dict_entry_clear(&entry);
2483 ret = wpas_p2p_service_del_bonjour(wpa_s, query);
2493 wpa_dbus_dict_entry_clear(&entry);
2497 return wpas_dbus_error_invalid_args(message, NULL);
2501 DBusMessage * wpas_dbus_handler_p2p_flush_service(DBusMessage *message,
2502 struct wpa_supplicant *wpa_s)
2504 wpas_p2p_service_flush(wpa_s);
2509 DBusMessage * wpas_dbus_handler_p2p_service_sd_req(
2510 DBusMessage *message, struct wpa_supplicant *wpa_s)
2512 DBusMessageIter iter_dict;
2513 DBusMessage *reply = NULL;
2514 DBusMessageIter iter;
2515 struct wpa_dbus_dict_entry entry;
2517 char *service = NULL;
2518 char *peer_object_path = NULL;
2519 struct wpabuf *tlv = NULL;
2522 u8 addr_buf[ETH_ALEN], *addr;
2524 dbus_message_iter_init(message, &iter);
2526 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
2529 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2530 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2532 if (!os_strcmp(entry.key, "peer_object") &&
2533 entry.type == DBUS_TYPE_OBJECT_PATH) {
2534 peer_object_path = os_strdup(entry.str_value);
2535 } else if (!os_strcmp(entry.key, "service_type") &&
2536 entry.type == DBUS_TYPE_STRING) {
2537 if (!os_strcmp(entry.str_value, "upnp"))
2541 } else if (!os_strcmp(entry.key, "version") &&
2542 entry.type == DBUS_TYPE_INT32) {
2543 version = entry.uint32_value;
2544 } else if (!os_strcmp(entry.key, "service") &&
2545 entry.type == DBUS_TYPE_STRING) {
2546 service = os_strdup(entry.str_value);
2547 } else if (!os_strcmp(entry.key, "tlv")) {
2548 if (entry.type != DBUS_TYPE_ARRAY ||
2549 entry.array_type != DBUS_TYPE_BYTE)
2551 tlv = wpabuf_alloc_copy(entry.bytearray_value,
2556 wpa_dbus_dict_entry_clear(&entry);
2559 if (!peer_object_path) {
2562 if (parse_peer_object_path(peer_object_path, addr_buf) < 0 ||
2563 !p2p_peer_known(wpa_s->global->p2p, addr_buf))
2570 if (version <= 0 || service == NULL)
2573 ref = wpas_p2p_sd_request_upnp(wpa_s, addr, version, service);
2577 ref = wpas_p2p_sd_request(wpa_s, addr, tlv);
2582 reply = dbus_message_new_method_return(message);
2583 dbus_message_append_args(reply, DBUS_TYPE_UINT64,
2584 &ref, DBUS_TYPE_INVALID);
2586 reply = wpas_dbus_error_unknown_error(
2587 message, "Unable to send SD request");
2591 os_free(peer_object_path);
2594 wpa_dbus_dict_entry_clear(&entry);
2598 reply = wpas_dbus_error_invalid_args(message, NULL);
2603 DBusMessage * wpas_dbus_handler_p2p_service_sd_res(
2604 DBusMessage *message, struct wpa_supplicant *wpa_s)
2606 DBusMessageIter iter_dict;
2607 DBusMessage *reply = NULL;
2608 DBusMessageIter iter;
2609 struct wpa_dbus_dict_entry entry;
2610 char *peer_object_path = NULL;
2611 struct wpabuf *tlv = NULL;
2616 dbus_message_iter_init(message, &iter);
2618 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
2621 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2622 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2625 if (!os_strcmp(entry.key, "peer_object") &&
2626 entry.type == DBUS_TYPE_OBJECT_PATH) {
2627 peer_object_path = os_strdup(entry.str_value);
2628 } else if (!os_strcmp(entry.key, "frequency") &&
2629 entry.type == DBUS_TYPE_INT32) {
2630 freq = entry.uint32_value;
2631 } else if (!os_strcmp(entry.key, "dialog_token") &&
2632 (entry.type == DBUS_TYPE_UINT32 ||
2633 entry.type == DBUS_TYPE_INT32)) {
2634 dlg_tok = entry.uint32_value;
2635 } else if (!os_strcmp(entry.key, "tlvs")) {
2636 if (entry.type != DBUS_TYPE_ARRAY ||
2637 entry.array_type != DBUS_TYPE_BYTE)
2639 tlv = wpabuf_alloc_copy(entry.bytearray_value,
2644 wpa_dbus_dict_entry_clear(&entry);
2646 if (!peer_object_path ||
2647 (parse_peer_object_path(peer_object_path, addr) < 0) ||
2648 !p2p_peer_known(wpa_s->global->p2p, addr))
2654 wpas_p2p_sd_response(wpa_s, freq, addr, (u8) dlg_tok, tlv);
2657 os_free(peer_object_path);
2660 wpa_dbus_dict_entry_clear(&entry);
2662 reply = wpas_dbus_error_invalid_args(message, NULL);
2667 DBusMessage * wpas_dbus_handler_p2p_service_sd_cancel_req(
2668 DBusMessage *message, struct wpa_supplicant *wpa_s)
2670 DBusMessageIter iter;
2673 dbus_message_iter_init(message, &iter);
2674 dbus_message_iter_get_basic(&iter, &req);
2679 if (wpas_p2p_sd_cancel_request(wpa_s, req) < 0)
2684 return wpas_dbus_error_invalid_args(message, NULL);
2688 DBusMessage * wpas_dbus_handler_p2p_service_update(
2689 DBusMessage *message, struct wpa_supplicant *wpa_s)
2691 wpas_p2p_sd_service_update(wpa_s);
2696 DBusMessage * wpas_dbus_handler_p2p_serv_disc_external(
2697 DBusMessage *message, struct wpa_supplicant *wpa_s)
2699 DBusMessageIter iter;
2702 dbus_message_iter_init(message, &iter);
2703 dbus_message_iter_get_basic(&iter, &ext);
2705 wpa_s->p2p_sd_over_ctrl_iface = ext;
2712 #ifdef CONFIG_WIFI_DISPLAY
2714 dbus_bool_t wpas_dbus_getter_global_wfd_ies(DBusMessageIter *iter,
2715 DBusError *error, void *user_data)
2717 struct wpa_global *global = user_data;
2721 ie = wifi_display_get_wfd_ie(global);
2723 return wpas_dbus_simple_array_property_getter(iter,
2727 ret = wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
2729 wpabuf_len(ie), error);
2736 dbus_bool_t wpas_dbus_setter_global_wfd_ies(DBusMessageIter *iter,
2737 DBusError *error, void *user_data)
2739 struct wpa_global *global = user_data;
2740 DBusMessageIter variant, array;
2741 struct wpabuf *ie = NULL;
2745 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_VARIANT)
2748 dbus_message_iter_recurse(iter, &variant);
2749 if (dbus_message_iter_get_arg_type(&variant) != DBUS_TYPE_ARRAY)
2752 dbus_message_iter_recurse(&variant, &array);
2753 dbus_message_iter_get_fixed_array(&array, &data, &len);
2755 wifi_display_enable(global, 0);
2756 wifi_display_deinit(global);
2761 ie = wpabuf_alloc(len);
2765 wpabuf_put_data(ie, data, len);
2766 if (wifi_display_subelem_set_from_ies(global, ie) != 0)
2769 if (global->wifi_display == 0)
2770 wifi_display_enable(global, 1);
2778 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
2779 "invalid message format");
2783 #endif /* CONFIG_WIFI_DISPLAY */