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"
31 * Parses out the mac address from the peer object path.
32 * @peer_path - object path of the form
33 * /fi/w1/wpa_supplicant1/Interfaces/n/Peers/00112233445566 (no colons)
34 * @addr - out param must be of ETH_ALEN size
35 * Returns 0 if valid (including MAC), -1 otherwise
37 static int parse_peer_object_path(char *peer_path, u8 addr[ETH_ALEN])
43 p = os_strrchr(peer_path, '/');
47 return hwaddr_compact_aton(p, addr);
52 * wpas_dbus_error_persistent_group_unknown - Return a new PersistentGroupUnknown
54 * @message: Pointer to incoming dbus message this error refers to
55 * Returns: a dbus error message
57 * Convenience function to create and return an invalid persistent group error.
59 static DBusMessage * wpas_dbus_error_persistent_group_unknown(
62 return dbus_message_new_error(message, WPAS_DBUS_ERROR_NETWORK_UNKNOWN,
63 "There is no such persistent group in "
68 DBusMessage * wpas_dbus_handler_p2p_find(DBusMessage *message,
69 struct wpa_supplicant *wpa_s)
71 struct wpa_dbus_dict_entry entry;
72 DBusMessage *reply = NULL;
74 DBusMessageIter iter_dict;
75 unsigned int timeout = 0;
76 enum p2p_discovery_type type = P2P_FIND_ONLY_SOCIAL;
77 int num_req_dev_types = 0;
79 u8 *req_dev_types = NULL;
81 dbus_message_iter_init(message, &iter);
84 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
87 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
88 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
91 if (!os_strcmp(entry.key, "Timeout") &&
92 (entry.type == DBUS_TYPE_INT32)) {
93 timeout = entry.uint32_value;
94 } else if (os_strcmp(entry.key, "RequestedDeviceTypes") == 0) {
95 if ((entry.type != DBUS_TYPE_ARRAY) ||
96 (entry.array_type != WPAS_DBUS_TYPE_BINARRAY))
99 os_free(req_dev_types);
101 os_malloc(WPS_DEV_TYPE_LEN * entry.array_len);
105 for (i = 0; i < entry.array_len; i++) {
106 if (wpabuf_len(entry.binarray_value[i]) !=
109 os_memcpy(req_dev_types + i * WPS_DEV_TYPE_LEN,
110 wpabuf_head(entry.binarray_value[i]),
113 num_req_dev_types = entry.array_len;
114 } else if (!os_strcmp(entry.key, "DiscoveryType") &&
115 (entry.type == DBUS_TYPE_STRING)) {
116 if (!os_strcmp(entry.str_value, "start_with_full"))
117 type = P2P_FIND_START_WITH_FULL;
118 else if (!os_strcmp(entry.str_value, "social"))
119 type = P2P_FIND_ONLY_SOCIAL;
120 else if (!os_strcmp(entry.str_value, "progressive"))
121 type = P2P_FIND_PROGRESSIVE;
126 wpa_dbus_dict_entry_clear(&entry);
129 wpas_p2p_find(wpa_s, timeout, type, num_req_dev_types, req_dev_types,
131 os_free(req_dev_types);
135 wpa_dbus_dict_entry_clear(&entry);
137 os_free(req_dev_types);
138 reply = wpas_dbus_error_invalid_args(message, entry.key);
143 DBusMessage * wpas_dbus_handler_p2p_stop_find(DBusMessage *message,
144 struct wpa_supplicant *wpa_s)
146 wpas_p2p_stop_find(wpa_s);
151 DBusMessage * wpas_dbus_handler_p2p_rejectpeer(DBusMessage *message,
152 struct wpa_supplicant *wpa_s)
154 DBusMessageIter iter;
155 char *peer_object_path = NULL;
156 u8 peer_addr[ETH_ALEN];
158 dbus_message_iter_init(message, &iter);
159 dbus_message_iter_get_basic(&iter, &peer_object_path);
161 if (parse_peer_object_path(peer_object_path, peer_addr) < 0)
162 return wpas_dbus_error_invalid_args(message, NULL);
164 if (wpas_p2p_reject(wpa_s, peer_addr) < 0)
165 return wpas_dbus_error_unknown_error(message,
166 "Failed to call wpas_p2p_reject method.");
172 DBusMessage * wpas_dbus_handler_p2p_listen(DBusMessage *message,
173 struct wpa_supplicant *wpa_s)
175 dbus_int32_t timeout = 0;
177 if (!dbus_message_get_args(message, NULL, DBUS_TYPE_INT32, &timeout,
179 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
182 if (wpas_p2p_listen(wpa_s, (unsigned int)timeout))
183 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
190 DBusMessage * wpas_dbus_handler_p2p_extendedlisten(
191 DBusMessage *message, struct wpa_supplicant *wpa_s)
193 unsigned int period = 0, interval = 0;
194 struct wpa_dbus_dict_entry entry;
195 DBusMessageIter iter;
196 DBusMessageIter iter_dict;
198 dbus_message_iter_init(message, &iter);
201 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
204 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
205 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
208 if (!os_strcmp(entry.key, "period") &&
209 (entry.type == DBUS_TYPE_INT32))
210 period = entry.uint32_value;
211 else if (!os_strcmp(entry.key, "interval") &&
212 (entry.type == DBUS_TYPE_INT32))
213 interval = entry.uint32_value;
216 wpa_dbus_dict_entry_clear(&entry);
219 if (wpas_p2p_ext_listen(wpa_s, period, interval))
220 return wpas_dbus_error_unknown_error(
221 message, "failed to initiate a p2p_ext_listen.");
226 wpa_dbus_dict_entry_clear(&entry);
228 return wpas_dbus_error_invalid_args(message, entry.key);
232 DBusMessage * wpas_dbus_handler_p2p_presence_request(
233 DBusMessage *message, struct wpa_supplicant *wpa_s)
235 unsigned int dur1 = 0, int1 = 0, dur2 = 0, int2 = 0;
236 struct wpa_dbus_dict_entry entry;
237 DBusMessageIter iter;
238 DBusMessageIter iter_dict;
240 dbus_message_iter_init(message, &iter);
243 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
246 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
247 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
250 if (!os_strcmp(entry.key, "duration1") &&
251 (entry.type == DBUS_TYPE_INT32))
252 dur1 = entry.uint32_value;
253 else if (!os_strcmp(entry.key, "interval1") &&
254 entry.type == DBUS_TYPE_INT32)
255 int1 = entry.uint32_value;
256 else if (!os_strcmp(entry.key, "duration2") &&
257 entry.type == DBUS_TYPE_INT32)
258 dur2 = entry.uint32_value;
259 else if (!os_strcmp(entry.key, "interval2") &&
260 entry.type == DBUS_TYPE_INT32)
261 int2 = entry.uint32_value;
265 wpa_dbus_dict_entry_clear(&entry);
267 if (wpas_p2p_presence_req(wpa_s, dur1, int1, dur2, int2) < 0)
268 return wpas_dbus_error_unknown_error(message,
269 "Failed to invoke presence request.");
274 wpa_dbus_dict_entry_clear(&entry);
276 return wpas_dbus_error_invalid_args(message, entry.key);
280 DBusMessage * wpas_dbus_handler_p2p_group_add(DBusMessage *message,
281 struct wpa_supplicant *wpa_s)
283 DBusMessageIter iter_dict;
284 DBusMessage *reply = NULL;
285 DBusMessageIter iter;
286 struct wpa_dbus_dict_entry entry;
287 char *pg_object_path = NULL;
288 int persistent_group = 0;
291 char *net_id_str = NULL;
292 unsigned int group_id = 0;
293 struct wpa_ssid *ssid;
295 dbus_message_iter_init(message, &iter);
297 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
300 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
301 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
304 if (!os_strcmp(entry.key, "persistent") &&
305 (entry.type == DBUS_TYPE_BOOLEAN)) {
306 persistent_group = (entry.bool_value == TRUE) ? 1 : 0;
307 } else if (!os_strcmp(entry.key, "frequency") &&
308 (entry.type == DBUS_TYPE_INT32)) {
309 freq = entry.int32_value;
312 } else if (!os_strcmp(entry.key, "persistent_group_object") &&
313 entry.type == DBUS_TYPE_OBJECT_PATH)
314 pg_object_path = os_strdup(entry.str_value);
318 wpa_dbus_dict_entry_clear(&entry);
321 if (pg_object_path != NULL) {
323 * A persistent group Object Path is defined meaning we want
324 * to re-invoke a persistent group.
327 iface = wpas_dbus_new_decompose_object_path(pg_object_path, 1,
330 os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
332 wpas_dbus_error_invalid_args(message,
337 group_id = strtoul(net_id_str, NULL, 10);
338 if (errno == EINVAL) {
339 reply = wpas_dbus_error_invalid_args(
340 message, pg_object_path);
344 /* Get the SSID structure from the persistent group id */
345 ssid = wpa_config_get_network(wpa_s->conf, group_id);
346 if (ssid == NULL || ssid->disabled != 2)
349 if (wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 0, 0, 0,
351 reply = wpas_dbus_error_unknown_error(
353 "Failed to reinvoke a persistent group");
356 } else if (wpas_p2p_group_add(wpa_s, persistent_group, freq, 0, 0))
360 os_free(pg_object_path);
365 wpa_dbus_dict_entry_clear(&entry);
367 reply = wpas_dbus_error_invalid_args(message, NULL);
372 DBusMessage * wpas_dbus_handler_p2p_disconnect(DBusMessage *message,
373 struct wpa_supplicant *wpa_s)
375 if (wpas_p2p_disconnect(wpa_s))
376 return wpas_dbus_error_unknown_error(message,
377 "failed to disconnect");
383 static dbus_bool_t wpa_dbus_p2p_check_enabled(struct wpa_supplicant *wpa_s,
384 DBusMessage *message,
385 DBusMessage **out_reply,
388 /* Return an error message or an error if P2P isn't available */
389 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL) {
391 *out_reply = dbus_message_new_error(
392 message, DBUS_ERROR_FAILED,
393 "P2P is not available for this interface");
395 dbus_set_error_const(error, DBUS_ERROR_FAILED,
396 "P2P is not available for this "
404 DBusMessage * wpas_dbus_handler_p2p_flush(DBusMessage *message,
405 struct wpa_supplicant *wpa_s)
407 DBusMessage *reply = NULL;
409 if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL))
412 os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
413 wpa_s->force_long_sd = 0;
414 p2p_flush(wpa_s->global->p2p);
420 DBusMessage * wpas_dbus_handler_p2p_connect(DBusMessage *message,
421 struct wpa_supplicant *wpa_s)
423 DBusMessageIter iter_dict;
424 DBusMessage *reply = NULL;
425 DBusMessageIter iter;
426 struct wpa_dbus_dict_entry entry;
427 char *peer_object_path = NULL;
428 int persistent_group = 0;
430 int authorize_only = 0;
435 enum p2p_wps_method wps_method = WPS_NOT_READY;
437 char *err_msg = NULL;
440 if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL))
443 dbus_message_iter_init(message, &iter);
445 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
448 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
449 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
452 if (!os_strcmp(entry.key, "peer") &&
453 (entry.type == DBUS_TYPE_OBJECT_PATH)) {
454 peer_object_path = os_strdup(entry.str_value);
455 } else if (!os_strcmp(entry.key, "persistent") &&
456 (entry.type == DBUS_TYPE_BOOLEAN)) {
457 persistent_group = (entry.bool_value == TRUE) ? 1 : 0;
458 } else if (!os_strcmp(entry.key, "join") &&
459 (entry.type == DBUS_TYPE_BOOLEAN)) {
460 join = (entry.bool_value == TRUE) ? 1 : 0;
461 } else if (!os_strcmp(entry.key, "authorize_only") &&
462 (entry.type == DBUS_TYPE_BOOLEAN)) {
463 authorize_only = (entry.bool_value == TRUE) ? 1 : 0;
464 } else if (!os_strcmp(entry.key, "frequency") &&
465 (entry.type == DBUS_TYPE_INT32)) {
466 freq = entry.int32_value;
469 } else if (!os_strcmp(entry.key, "go_intent") &&
470 (entry.type == DBUS_TYPE_INT32)) {
471 go_intent = entry.int32_value;
472 if ((go_intent < 0) || (go_intent > 15))
474 } else if (!os_strcmp(entry.key, "wps_method") &&
475 (entry.type == DBUS_TYPE_STRING)) {
476 if (!os_strcmp(entry.str_value, "pbc"))
477 wps_method = WPS_PBC;
478 else if (!os_strcmp(entry.str_value, "pin"))
479 wps_method = WPS_PIN_DISPLAY;
480 else if (!os_strcmp(entry.str_value, "display"))
481 wps_method = WPS_PIN_DISPLAY;
482 else if (!os_strcmp(entry.str_value, "keypad"))
483 wps_method = WPS_PIN_KEYPAD;
486 } else if (!os_strcmp(entry.key, "pin") &&
487 (entry.type == DBUS_TYPE_STRING)) {
488 pin = os_strdup(entry.str_value);
492 wpa_dbus_dict_entry_clear(&entry);
495 if (!peer_object_path || (wps_method == WPS_NOT_READY) ||
496 (parse_peer_object_path(peer_object_path, addr) < 0) ||
497 !p2p_peer_known(wpa_s->global->p2p, addr))
501 * Validate the wps_method specified and the pin value.
503 if ((!pin || !pin[0]) && (wps_method == WPS_PIN_KEYPAD))
506 new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
507 persistent_group, 0, join, authorize_only,
508 go_intent, freq, -1, 0, 0, 0);
513 os_snprintf(npin, sizeof(npin), "%08d", new_pin);
514 generated_pin = npin;
515 reply = dbus_message_new_method_return(message);
516 dbus_message_append_args(reply, DBUS_TYPE_STRING,
517 &generated_pin, DBUS_TYPE_INVALID);
521 err_msg = "connect failed due to channel "
523 iface = WPAS_DBUS_ERROR_CONNECT_CHANNEL_UNAVAILABLE;
527 err_msg = "connect failed due to unsupported channel.";
528 iface = WPAS_DBUS_ERROR_CONNECT_CHANNEL_UNSUPPORTED;
532 err_msg = "connect failed due to unspecified error.";
533 iface = WPAS_DBUS_ERROR_CONNECT_UNSPECIFIED_ERROR;
539 * Do we need specialized errors corresponding to above
540 * error conditions as against just returning a different
543 reply = dbus_message_new_error(message, iface, err_msg);
547 os_free(peer_object_path);
551 wpa_dbus_dict_entry_clear(&entry);
553 reply = wpas_dbus_error_invalid_args(message, NULL);
558 DBusMessage * wpas_dbus_handler_p2p_invite(DBusMessage *message,
559 struct wpa_supplicant *wpa_s)
561 DBusMessageIter iter_dict;
562 DBusMessage *reply = NULL;
563 DBusMessageIter iter;
564 struct wpa_dbus_dict_entry entry;
565 char *peer_object_path = NULL;
566 char *pg_object_path = NULL;
568 char *net_id_str = NULL;
569 u8 peer_addr[ETH_ALEN];
570 unsigned int group_id = 0;
572 struct wpa_ssid *ssid;
574 if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL))
577 dbus_message_iter_init(message, &iter);
579 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
582 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
583 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
586 if (!os_strcmp(entry.key, "peer") &&
587 (entry.type == DBUS_TYPE_OBJECT_PATH)) {
588 peer_object_path = os_strdup(entry.str_value);
589 wpa_dbus_dict_entry_clear(&entry);
590 } else if (!os_strcmp(entry.key, "persistent_group_object") &&
591 (entry.type == DBUS_TYPE_OBJECT_PATH)) {
592 pg_object_path = os_strdup(entry.str_value);
594 wpa_dbus_dict_entry_clear(&entry);
596 wpa_dbus_dict_entry_clear(&entry);
601 if (!peer_object_path ||
602 (parse_peer_object_path(peer_object_path, peer_addr) < 0) ||
603 !p2p_peer_known(wpa_s->global->p2p, peer_addr)) {
609 * A group ID is defined meaning we want to re-invoke a
613 iface = wpas_dbus_new_decompose_object_path(pg_object_path, 1,
616 os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
617 reply = wpas_dbus_error_invalid_args(message,
622 group_id = strtoul(net_id_str, NULL, 10);
623 if (errno == EINVAL) {
624 reply = wpas_dbus_error_invalid_args(
625 message, pg_object_path);
629 /* Get the SSID structure from the persistent group id */
630 ssid = wpa_config_get_network(wpa_s->conf, group_id);
631 if (ssid == NULL || ssid->disabled != 2)
634 if (wpas_p2p_invite(wpa_s, peer_addr, ssid, NULL, 0, 0, 0, 0) <
636 reply = wpas_dbus_error_unknown_error(
638 "Failed to reinvoke a persistent group");
643 * No group ID means propose to a peer to join my active group
645 if (wpas_p2p_invite_group(wpa_s, wpa_s->ifname,
647 reply = wpas_dbus_error_unknown_error(
648 message, "Failed to join to an active group");
654 os_free(pg_object_path);
655 os_free(peer_object_path);
659 reply = wpas_dbus_error_invalid_args(message, NULL);
664 DBusMessage * wpas_dbus_handler_p2p_prov_disc_req(DBusMessage *message,
665 struct wpa_supplicant *wpa_s)
667 DBusMessageIter iter;
668 char *peer_object_path = NULL;
669 char *config_method = NULL;
670 u8 peer_addr[ETH_ALEN];
672 dbus_message_iter_init(message, &iter);
673 dbus_message_iter_get_basic(&iter, &peer_object_path);
675 if (parse_peer_object_path(peer_object_path, peer_addr) < 0)
676 return wpas_dbus_error_invalid_args(message, NULL);
678 dbus_message_iter_next(&iter);
679 dbus_message_iter_get_basic(&iter, &config_method);
682 * Validation checks on config_method are being duplicated here
683 * to be able to return invalid args reply since the error code
684 * from p2p module are not granular enough (yet).
686 if (os_strcmp(config_method, "display") &&
687 os_strcmp(config_method, "keypad") &&
688 os_strcmp(config_method, "pbc") &&
689 os_strcmp(config_method, "pushbutton"))
690 return wpas_dbus_error_invalid_args(message, NULL);
692 if (wpas_p2p_prov_disc(wpa_s, peer_addr, config_method,
693 WPAS_P2P_PD_FOR_GO_NEG) < 0)
694 return wpas_dbus_error_unknown_error(message,
695 "Failed to send provision discovery request");
702 * P2P Device property accessor methods.
705 dbus_bool_t wpas_dbus_getter_p2p_device_config(DBusMessageIter *iter,
709 struct wpa_supplicant *wpa_s = user_data;
710 DBusMessageIter variant_iter, dict_iter;
711 DBusMessageIter iter_secdev_dict_entry, iter_secdev_dict_val,
712 iter_secdev_dict_array;
713 const char *dev_name;
714 int num_vendor_extensions = 0;
716 const struct wpabuf *vendor_ext[P2P_MAX_WPS_VENDOR_EXT];
718 if (!wpa_dbus_p2p_check_enabled(wpa_s, NULL, NULL, error))
721 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
722 "a{sv}", &variant_iter) ||
723 !wpa_dbus_dict_open_write(&variant_iter, &dict_iter))
727 dev_name = wpa_s->conf->device_name;
729 !wpa_dbus_dict_append_string(&dict_iter, "DeviceName", dev_name))
732 /* Primary device type */
733 if (!wpa_dbus_dict_append_byte_array(&dict_iter, "PrimaryDeviceType",
734 (char *)wpa_s->conf->device_type,
738 /* Secondary device types */
739 if (wpa_s->conf->num_sec_device_types) {
740 if (!wpa_dbus_dict_begin_array(&dict_iter,
741 "SecondaryDeviceTypes",
742 DBUS_TYPE_ARRAY_AS_STRING
743 DBUS_TYPE_BYTE_AS_STRING,
744 &iter_secdev_dict_entry,
745 &iter_secdev_dict_val,
746 &iter_secdev_dict_array))
749 for (i = 0; i < wpa_s->conf->num_sec_device_types; i++)
750 wpa_dbus_dict_bin_array_add_element(
751 &iter_secdev_dict_array,
752 wpa_s->conf->sec_device_type[i],
755 if (!wpa_dbus_dict_end_array(&dict_iter,
756 &iter_secdev_dict_entry,
757 &iter_secdev_dict_val,
758 &iter_secdev_dict_array))
762 /* Vendor Extensions */
763 for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
764 if (wpa_s->conf->wps_vendor_ext[i] == NULL)
766 vendor_ext[num_vendor_extensions++] =
767 wpa_s->conf->wps_vendor_ext[i];
770 if (num_vendor_extensions &&
771 !wpa_dbus_dict_append_wpabuf_array(&dict_iter,
774 num_vendor_extensions))
778 if (!wpa_dbus_dict_append_uint32(&dict_iter, "GOIntent",
779 wpa_s->conf->p2p_go_intent))
782 /* Persistent Reconnect */
783 if (!wpa_dbus_dict_append_bool(&dict_iter, "PersistentReconnect",
784 wpa_s->conf->persistent_reconnect))
787 /* Listen Reg Class */
788 if (!wpa_dbus_dict_append_uint32(&dict_iter, "ListenRegClass",
789 wpa_s->conf->p2p_listen_reg_class))
793 if (!wpa_dbus_dict_append_uint32(&dict_iter, "ListenChannel",
794 wpa_s->conf->p2p_listen_channel))
798 if (!wpa_dbus_dict_append_uint32(&dict_iter, "OperRegClass",
799 wpa_s->conf->p2p_oper_reg_class))
803 if (!wpa_dbus_dict_append_uint32(&dict_iter, "OperChannel",
804 wpa_s->conf->p2p_oper_channel))
808 if (wpa_s->conf->p2p_ssid_postfix &&
809 !wpa_dbus_dict_append_string(&dict_iter, "SsidPostfix",
810 wpa_s->conf->p2p_ssid_postfix))
814 if (!wpa_dbus_dict_append_bool(&dict_iter, "IntraBss",
815 wpa_s->conf->p2p_intra_bss))
819 if (!wpa_dbus_dict_append_uint32(&dict_iter, "GroupIdle",
820 wpa_s->conf->p2p_group_idle))
823 /* Dissasociation low ack */
824 if (!wpa_dbus_dict_append_uint32(&dict_iter, "disassoc_low_ack",
825 wpa_s->conf->disassoc_low_ack))
829 if (!wpa_dbus_dict_append_bool(&dict_iter, "NoGroupIface",
830 wpa_s->conf->p2p_no_group_iface))
833 if (!wpa_dbus_dict_close_write(&variant_iter, &dict_iter) ||
834 !dbus_message_iter_close_container(iter, &variant_iter))
837 /* P2P Search Delay */
838 if (!wpa_dbus_dict_append_uint32(&dict_iter, "p2p_search_delay",
839 wpa_s->conf->p2p_search_delay))
845 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
850 dbus_bool_t wpas_dbus_setter_p2p_device_config(DBusMessageIter *iter,
854 struct wpa_supplicant *wpa_s = user_data;
855 DBusMessageIter variant_iter, iter_dict;
856 struct wpa_dbus_dict_entry entry = {.type = DBUS_TYPE_STRING };
859 if (!wpa_dbus_p2p_check_enabled(wpa_s, NULL, NULL, error))
862 dbus_message_iter_recurse(iter, &variant_iter);
863 if (!wpa_dbus_dict_open_read(&variant_iter, &iter_dict, error))
866 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
867 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) {
868 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
869 "invalid message format");
873 if (os_strcmp(entry.key, "DeviceName") == 0) {
876 if (entry.type != DBUS_TYPE_STRING)
879 devname = os_strdup(entry.str_value);
881 goto err_no_mem_clear;
883 os_free(wpa_s->conf->device_name);
884 wpa_s->conf->device_name = devname;
886 wpa_s->conf->changed_parameters |=
887 CFG_CHANGED_DEVICE_NAME;
888 } else if (os_strcmp(entry.key, "PrimaryDeviceType") == 0) {
889 if (entry.type != DBUS_TYPE_ARRAY ||
890 entry.array_type != DBUS_TYPE_BYTE ||
891 entry.array_len != WPS_DEV_TYPE_LEN)
894 os_memcpy(wpa_s->conf->device_type,
895 entry.bytearray_value,
897 wpa_s->conf->changed_parameters |=
898 CFG_CHANGED_DEVICE_TYPE;
899 } else if (os_strcmp(entry.key, "SecondaryDeviceTypes") == 0) {
900 if (entry.type != DBUS_TYPE_ARRAY ||
901 entry.array_type != WPAS_DBUS_TYPE_BINARRAY ||
902 entry.array_len > MAX_SEC_DEVICE_TYPES)
905 for (i = 0; i < entry.array_len; i++)
906 if (wpabuf_len(entry.binarray_value[i]) !=
908 goto err_no_mem_clear;
909 for (i = 0; i < entry.array_len; i++)
910 os_memcpy(wpa_s->conf->sec_device_type[i],
911 wpabuf_head(entry.binarray_value[i]),
913 wpa_s->conf->num_sec_device_types = entry.array_len;
914 wpa_s->conf->changed_parameters |=
915 CFG_CHANGED_SEC_DEVICE_TYPE;
916 } else if (os_strcmp(entry.key, "VendorExtension") == 0) {
917 if ((entry.type != DBUS_TYPE_ARRAY) ||
918 (entry.array_type != WPAS_DBUS_TYPE_BINARRAY) ||
919 (entry.array_len > P2P_MAX_WPS_VENDOR_EXT))
922 wpa_s->conf->changed_parameters |=
923 CFG_CHANGED_VENDOR_EXTENSION;
925 for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
926 wpabuf_free(wpa_s->conf->wps_vendor_ext[i]);
927 if (i < entry.array_len) {
928 wpa_s->conf->wps_vendor_ext[i] =
929 entry.binarray_value[i];
930 entry.binarray_value[i] = NULL;
932 wpa_s->conf->wps_vendor_ext[i] = NULL;
934 } else if ((os_strcmp(entry.key, "GOIntent") == 0) &&
935 (entry.type == DBUS_TYPE_UINT32) &&
936 (entry.uint32_value <= 15))
937 wpa_s->conf->p2p_go_intent = entry.uint32_value;
938 else if ((os_strcmp(entry.key, "PersistentReconnect") == 0) &&
939 (entry.type == DBUS_TYPE_BOOLEAN))
940 wpa_s->conf->persistent_reconnect = entry.bool_value;
941 else if ((os_strcmp(entry.key, "ListenRegClass") == 0) &&
942 (entry.type == DBUS_TYPE_UINT32)) {
943 wpa_s->conf->p2p_listen_reg_class = entry.uint32_value;
944 wpa_s->conf->changed_parameters |=
945 CFG_CHANGED_P2P_LISTEN_CHANNEL;
946 } else if ((os_strcmp(entry.key, "ListenChannel") == 0) &&
947 (entry.type == DBUS_TYPE_UINT32)) {
948 wpa_s->conf->p2p_listen_channel = entry.uint32_value;
949 wpa_s->conf->changed_parameters |=
950 CFG_CHANGED_P2P_LISTEN_CHANNEL;
951 } else if ((os_strcmp(entry.key, "OperRegClass") == 0) &&
952 (entry.type == DBUS_TYPE_UINT32)) {
953 wpa_s->conf->p2p_oper_reg_class = entry.uint32_value;
954 wpa_s->conf->changed_parameters |=
955 CFG_CHANGED_P2P_OPER_CHANNEL;
956 } else if ((os_strcmp(entry.key, "OperChannel") == 0) &&
957 (entry.type == DBUS_TYPE_UINT32)) {
958 wpa_s->conf->p2p_oper_channel = entry.uint32_value;
959 wpa_s->conf->changed_parameters |=
960 CFG_CHANGED_P2P_OPER_CHANNEL;
961 } else if (os_strcmp(entry.key, "SsidPostfix") == 0) {
964 if (entry.type != DBUS_TYPE_STRING)
967 postfix = os_strdup(entry.str_value);
969 goto err_no_mem_clear;
971 os_free(wpa_s->conf->p2p_ssid_postfix);
972 wpa_s->conf->p2p_ssid_postfix = postfix;
974 wpa_s->conf->changed_parameters |=
975 CFG_CHANGED_P2P_SSID_POSTFIX;
976 } else if ((os_strcmp(entry.key, "IntraBss") == 0) &&
977 (entry.type == DBUS_TYPE_BOOLEAN)) {
978 wpa_s->conf->p2p_intra_bss = entry.bool_value;
979 wpa_s->conf->changed_parameters |=
980 CFG_CHANGED_P2P_INTRA_BSS;
981 } else if ((os_strcmp(entry.key, "GroupIdle") == 0) &&
982 (entry.type == DBUS_TYPE_UINT32))
983 wpa_s->conf->p2p_group_idle = entry.uint32_value;
984 else if (os_strcmp(entry.key, "disassoc_low_ack") == 0 &&
985 entry.type == DBUS_TYPE_UINT32)
986 wpa_s->conf->disassoc_low_ack = entry.uint32_value;
987 else if (os_strcmp(entry.key, "NoGroupIface") == 0 &&
988 entry.type == DBUS_TYPE_BOOLEAN)
989 wpa_s->conf->p2p_no_group_iface = entry.bool_value;
990 else if (os_strcmp(entry.key, "p2p_search_delay") == 0 &&
991 entry.type == DBUS_TYPE_UINT32)
992 wpa_s->conf->p2p_search_delay = entry.uint32_value;
996 wpa_dbus_dict_entry_clear(&entry);
999 if (wpa_s->conf->changed_parameters) {
1000 /* Some changed parameters requires to update config*/
1001 wpa_supplicant_update_config(wpa_s);
1007 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
1008 "invalid message format");
1009 wpa_dbus_dict_entry_clear(&entry);
1013 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1014 wpa_dbus_dict_entry_clear(&entry);
1019 dbus_bool_t wpas_dbus_getter_p2p_peers(DBusMessageIter *iter, DBusError *error,
1022 struct wpa_supplicant *wpa_s = user_data;
1023 struct p2p_data *p2p = wpa_s->global->p2p;
1024 int next = 0, i = 0;
1025 int num = 0, out_of_mem = 0;
1027 const struct p2p_peer_info *peer_info = NULL;
1028 dbus_bool_t success = FALSE;
1030 struct dl_list peer_objpath_list;
1031 struct peer_objpath_node {
1032 struct dl_list list;
1033 char path[WPAS_DBUS_OBJECT_PATH_MAX];
1036 char **peer_obj_paths = NULL;
1038 if (!wpa_dbus_p2p_check_enabled(wpa_s, NULL, NULL, error))
1041 dl_list_init(&peer_objpath_list);
1043 /* Get the first peer info */
1044 peer_info = p2p_get_peer_found(p2p, NULL, next);
1046 /* Get next and accumulate them */
1048 while (peer_info != NULL) {
1049 node = os_zalloc(sizeof(struct peer_objpath_node));
1055 addr = peer_info->p2p_device_addr;
1056 os_snprintf(node->path, WPAS_DBUS_OBJECT_PATH_MAX,
1057 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART
1059 wpa_s->dbus_new_path, MAC2STR(addr));
1060 dl_list_add_tail(&peer_objpath_list, &node->list);
1063 peer_info = p2p_get_peer_found(p2p, addr, next);
1067 * Now construct the peer object paths in a form suitable for
1068 * array_property_getter helper below.
1070 peer_obj_paths = os_calloc(num, sizeof(char *));
1072 if (!peer_obj_paths) {
1077 dl_list_for_each_safe(node, tmp, &peer_objpath_list,
1078 struct peer_objpath_node, list)
1079 peer_obj_paths[i++] = node->path;
1081 success = wpas_dbus_simple_array_property_getter(iter,
1082 DBUS_TYPE_OBJECT_PATH,
1083 peer_obj_paths, num,
1088 os_free(peer_obj_paths);
1090 dl_list_for_each_safe(node, tmp, &peer_objpath_list,
1091 struct peer_objpath_node, list) {
1092 dl_list_del(&node->list);
1096 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1102 enum wpas_p2p_role {
1103 WPAS_P2P_ROLE_DEVICE,
1105 WPAS_P2P_ROLE_CLIENT,
1108 static enum wpas_p2p_role wpas_get_p2p_role(struct wpa_supplicant *wpa_s)
1110 struct wpa_ssid *ssid = wpa_s->current_ssid;
1113 return WPAS_P2P_ROLE_DEVICE;
1114 if (wpa_s->wpa_state != WPA_COMPLETED)
1115 return WPAS_P2P_ROLE_DEVICE;
1117 switch (ssid->mode) {
1118 case WPAS_MODE_P2P_GO:
1119 case WPAS_MODE_P2P_GROUP_FORMATION:
1120 return WPAS_P2P_ROLE_GO;
1121 case WPAS_MODE_INFRA:
1122 if (ssid->p2p_group)
1123 return WPAS_P2P_ROLE_CLIENT;
1124 return WPAS_P2P_ROLE_DEVICE;
1126 return WPAS_P2P_ROLE_DEVICE;
1131 dbus_bool_t wpas_dbus_getter_p2p_role(DBusMessageIter *iter, DBusError *error,
1134 struct wpa_supplicant *wpa_s = user_data;
1137 switch (wpas_get_p2p_role(wpa_s)) {
1138 case WPAS_P2P_ROLE_GO:
1141 case WPAS_P2P_ROLE_CLIENT:
1149 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &str,
1154 dbus_bool_t wpas_dbus_getter_p2p_group(DBusMessageIter *iter, DBusError *error,
1157 struct wpa_supplicant *wpa_s = user_data;
1158 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX];
1159 char *dbus_groupobj_path = path_buf;
1161 if (wpa_s->dbus_groupobj_path == NULL)
1162 os_snprintf(dbus_groupobj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1165 os_snprintf(dbus_groupobj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1166 "%s", wpa_s->dbus_groupobj_path);
1168 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
1169 &dbus_groupobj_path, error);
1173 dbus_bool_t wpas_dbus_getter_p2p_peergo(DBusMessageIter *iter,
1174 DBusError *error, void *user_data)
1176 struct wpa_supplicant *wpa_s = user_data;
1177 char go_peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1179 if (wpas_get_p2p_role(wpa_s) != WPAS_P2P_ROLE_CLIENT)
1180 os_snprintf(go_peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
1182 os_snprintf(go_peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1183 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
1185 wpa_s->dbus_new_path, MAC2STR(wpa_s->go_dev_addr));
1187 path = go_peer_obj_path;
1188 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
1194 * Peer object properties accessor methods
1197 dbus_bool_t wpas_dbus_getter_p2p_peer_device_name(DBusMessageIter *iter,
1201 struct peer_handler_args *peer_args = user_data;
1202 const struct p2p_peer_info *info;
1205 if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error))
1208 /* get the peer info */
1209 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1210 peer_args->p2p_device_addr, 0);
1212 dbus_set_error(error, DBUS_ERROR_FAILED,
1213 "failed to find peer");
1217 tmp = os_strdup(info->device_name);
1219 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1223 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp,
1225 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1235 dbus_bool_t wpas_dbus_getter_p2p_peer_primary_device_type(
1236 DBusMessageIter *iter, DBusError *error, void *user_data)
1238 struct peer_handler_args *peer_args = user_data;
1239 const struct p2p_peer_info *info;
1241 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1242 peer_args->p2p_device_addr, 0);
1244 dbus_set_error(error, DBUS_ERROR_FAILED,
1245 "failed to find peer");
1249 if (!wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
1252 WPS_DEV_TYPE_LEN, error)) {
1253 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1261 dbus_bool_t wpas_dbus_getter_p2p_peer_config_method(DBusMessageIter *iter,
1265 struct peer_handler_args *peer_args = user_data;
1266 const struct p2p_peer_info *info;
1268 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1269 peer_args->p2p_device_addr, 0);
1271 dbus_set_error(error, DBUS_ERROR_FAILED,
1272 "failed to find peer");
1276 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
1277 &info->config_methods, error)) {
1278 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1286 dbus_bool_t wpas_dbus_getter_p2p_peer_level(DBusMessageIter *iter,
1290 struct peer_handler_args *peer_args = user_data;
1291 const struct p2p_peer_info *info;
1293 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1294 peer_args->p2p_device_addr, 0);
1296 dbus_set_error(error, DBUS_ERROR_FAILED,
1297 "failed to find peer");
1301 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
1302 &info->level, error)) {
1303 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1311 dbus_bool_t wpas_dbus_getter_p2p_peer_device_capability(DBusMessageIter *iter,
1315 struct peer_handler_args *peer_args = user_data;
1316 const struct p2p_peer_info *info;
1318 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1319 peer_args->p2p_device_addr, 0);
1321 dbus_set_error(error, DBUS_ERROR_FAILED,
1322 "failed to find peer");
1326 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BYTE,
1327 &info->dev_capab, error)) {
1328 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1336 dbus_bool_t wpas_dbus_getter_p2p_peer_group_capability(DBusMessageIter *iter,
1340 struct peer_handler_args *peer_args = user_data;
1341 const struct p2p_peer_info *info;
1343 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1344 peer_args->p2p_device_addr, 0);
1346 dbus_set_error(error, DBUS_ERROR_FAILED,
1347 "failed to find peer");
1351 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BYTE,
1352 &info->group_capab, error)) {
1353 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1361 dbus_bool_t wpas_dbus_getter_p2p_peer_secondary_device_types(
1362 DBusMessageIter *iter, DBusError *error, void *user_data)
1364 struct peer_handler_args *peer_args = user_data;
1365 const struct p2p_peer_info *info;
1366 DBusMessageIter variant_iter, array_iter;
1368 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1369 peer_args->p2p_device_addr, 0);
1371 dbus_set_error(error, DBUS_ERROR_FAILED,
1372 "failed to find peer");
1376 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
1377 DBUS_TYPE_ARRAY_AS_STRING
1378 DBUS_TYPE_ARRAY_AS_STRING
1379 DBUS_TYPE_BYTE_AS_STRING,
1381 dbus_set_error(error, DBUS_ERROR_FAILED,
1382 "%s: failed to construct message 1", __func__);
1386 if (!dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
1387 DBUS_TYPE_ARRAY_AS_STRING
1388 DBUS_TYPE_BYTE_AS_STRING,
1390 dbus_set_error(error, DBUS_ERROR_FAILED,
1391 "%s: failed to construct message 2", __func__);
1395 if (info->wps_sec_dev_type_list_len) {
1396 const u8 *sec_dev_type_list = info->wps_sec_dev_type_list;
1397 int num_sec_device_types =
1398 info->wps_sec_dev_type_list_len / WPS_DEV_TYPE_LEN;
1400 DBusMessageIter inner_array_iter;
1402 for (i = 0; i < num_sec_device_types; i++) {
1403 if (!dbus_message_iter_open_container(
1404 &array_iter, DBUS_TYPE_ARRAY,
1405 DBUS_TYPE_BYTE_AS_STRING,
1406 &inner_array_iter)) {
1407 dbus_set_error(error, DBUS_ERROR_FAILED,
1408 "%s: failed to construct "
1414 if (!dbus_message_iter_append_fixed_array(
1415 &inner_array_iter, DBUS_TYPE_BYTE,
1416 &sec_dev_type_list, WPS_DEV_TYPE_LEN)) {
1417 dbus_set_error(error, DBUS_ERROR_FAILED,
1418 "%s: failed to construct "
1424 if (!dbus_message_iter_close_container(
1425 &array_iter, &inner_array_iter)) {
1426 dbus_set_error(error, DBUS_ERROR_FAILED,
1427 "%s: failed to construct "
1433 sec_dev_type_list += WPS_DEV_TYPE_LEN;
1437 if (!dbus_message_iter_close_container(&variant_iter, &array_iter)) {
1438 dbus_set_error(error, DBUS_ERROR_FAILED,
1439 "%s: failed to construct message 6", __func__);
1443 if (!dbus_message_iter_close_container(iter, &variant_iter)) {
1444 dbus_set_error(error, DBUS_ERROR_FAILED,
1445 "%s: failed to construct message 7", __func__);
1453 dbus_bool_t wpas_dbus_getter_p2p_peer_vendor_extension(DBusMessageIter *iter,
1457 struct wpabuf *vendor_extension[P2P_MAX_WPS_VENDOR_EXT];
1459 struct peer_handler_args *peer_args = user_data;
1460 const struct p2p_peer_info *info;
1462 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1463 peer_args->p2p_device_addr, 0);
1465 dbus_set_error(error, DBUS_ERROR_FAILED,
1466 "failed to find peer");
1470 /* Add WPS vendor extensions attribute */
1471 for (i = 0, num = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
1472 if (info->wps_vendor_ext[i] == NULL)
1474 vendor_extension[num] = info->wps_vendor_ext[i];
1478 if (!wpas_dbus_simple_array_array_property_getter(iter, DBUS_TYPE_BYTE,
1487 dbus_bool_t wpas_dbus_getter_p2p_peer_ies(DBusMessageIter *iter,
1488 DBusError *error, void *user_data)
1490 struct peer_handler_args *peer_args = user_data;
1491 const struct p2p_peer_info *info;
1493 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1494 peer_args->p2p_device_addr, 0);
1496 dbus_set_error(error, DBUS_ERROR_FAILED,
1497 "failed to find peer");
1501 if (info->wfd_subelems == NULL)
1502 return wpas_dbus_simple_array_property_getter(iter,
1506 return wpas_dbus_simple_array_property_getter(
1507 iter, DBUS_TYPE_BYTE, (char *) info->wfd_subelems->buf,
1508 info->wfd_subelems->used, error);
1512 dbus_bool_t wpas_dbus_getter_p2p_peer_device_address(DBusMessageIter *iter,
1516 struct peer_handler_args *peer_args = user_data;
1517 const struct p2p_peer_info *info;
1519 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1520 peer_args->p2p_device_addr, 0);
1522 dbus_set_error(error, DBUS_ERROR_FAILED,
1523 "failed to find peer");
1527 return wpas_dbus_simple_array_property_getter(
1528 iter, DBUS_TYPE_BYTE, (char *) info->p2p_device_addr,
1534 * wpas_dbus_getter_persistent_groups - Get array of persistent group objects
1535 * @iter: Pointer to incoming dbus message iter
1536 * @error: Location to store error on failure
1537 * @user_data: Function specific data
1538 * Returns: TRUE on success, FALSE on failure
1540 * Getter for "PersistentGroups" property.
1542 dbus_bool_t wpas_dbus_getter_persistent_groups(DBusMessageIter *iter,
1546 struct wpa_supplicant *wpa_s = user_data;
1547 struct wpa_ssid *ssid;
1549 unsigned int i = 0, num = 0;
1550 dbus_bool_t success = FALSE;
1552 if (wpa_s->conf == NULL) {
1553 wpa_printf(MSG_ERROR, "dbus: %s: "
1554 "An error occurred getting persistent groups list",
1556 dbus_set_error_const(error, DBUS_ERROR_FAILED, "an error "
1557 "occurred getting persistent groups list");
1561 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
1562 if (network_is_persistent_group(ssid))
1565 paths = os_calloc(num, sizeof(char *));
1567 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1571 /* Loop through configured networks and append object path of each */
1572 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1573 if (!network_is_persistent_group(ssid))
1575 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1576 if (paths[i] == NULL) {
1577 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
1581 /* Construct the object path for this network. */
1582 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
1583 "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%d",
1584 wpa_s->dbus_new_path, ssid->id);
1587 success = wpas_dbus_simple_array_property_getter(iter,
1588 DBUS_TYPE_OBJECT_PATH,
1593 os_free(paths[--i]);
1600 * wpas_dbus_getter_persistent_group_properties - Get options for a persistent
1602 * @iter: Pointer to incoming dbus message iter
1603 * @error: Location to store error on failure
1604 * @user_data: Function specific data
1605 * Returns: TRUE on success, FALSE on failure
1607 * Getter for "Properties" property of a persistent group.
1609 dbus_bool_t wpas_dbus_getter_persistent_group_properties(DBusMessageIter *iter,
1613 struct network_handler_args *net = user_data;
1615 /* Leveraging the fact that persistent group object is still
1616 * represented in same manner as network within.
1618 return wpas_dbus_getter_network_properties(iter, error, net);
1623 * wpas_dbus_setter_persistent_group_properties - Get options for a persistent
1625 * @iter: Pointer to incoming dbus message iter
1626 * @error: Location to store error on failure
1627 * @user_data: Function specific data
1628 * Returns: TRUE on success, FALSE on failure
1630 * Setter for "Properties" property of a persistent group.
1632 dbus_bool_t wpas_dbus_setter_persistent_group_properties(DBusMessageIter *iter,
1636 struct network_handler_args *net = user_data;
1637 struct wpa_ssid *ssid = net->ssid;
1638 DBusMessageIter variant_iter;
1641 * Leveraging the fact that persistent group object is still
1642 * represented in same manner as network within.
1644 dbus_message_iter_recurse(iter, &variant_iter);
1645 return set_network_properties(net->wpa_s, ssid, &variant_iter, error);
1650 * wpas_dbus_new_iface_add_persistent_group - Add a new configured
1652 * @message: Pointer to incoming dbus message
1653 * @wpa_s: wpa_supplicant structure for a network interface
1654 * Returns: A dbus message containing the object path of the new
1657 * Handler function for "AddPersistentGroup" method call of a P2P Device
1660 DBusMessage * wpas_dbus_handler_add_persistent_group(
1661 DBusMessage *message, struct wpa_supplicant *wpa_s)
1663 DBusMessage *reply = NULL;
1664 DBusMessageIter iter;
1665 struct wpa_ssid *ssid = NULL;
1666 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf;
1669 dbus_message_iter_init(message, &iter);
1671 ssid = wpa_config_add_network(wpa_s->conf);
1673 wpa_printf(MSG_ERROR, "dbus: %s: "
1674 "Cannot add new persistent group", __func__);
1675 reply = wpas_dbus_error_unknown_error(
1677 "wpa_supplicant could not add "
1678 "a persistent group on this interface.");
1682 /* Mark the ssid as being a persistent group before the notification */
1684 ssid->p2p_persistent_group = 1;
1685 wpas_notify_persistent_group_added(wpa_s, ssid);
1687 wpa_config_set_network_defaults(ssid);
1689 dbus_error_init(&error);
1690 if (!set_network_properties(wpa_s, ssid, &iter, &error)) {
1691 wpa_printf(MSG_DEBUG, "dbus: %s: "
1692 "Control interface could not set persistent group "
1693 "properties", __func__);
1694 reply = wpas_dbus_reply_new_from_error(message, &error,
1695 DBUS_ERROR_INVALID_ARGS,
1696 "Failed to set network "
1698 dbus_error_free(&error);
1702 /* Construct the object path for this network. */
1703 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
1704 "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%d",
1705 wpa_s->dbus_new_path, ssid->id);
1707 reply = dbus_message_new_method_return(message);
1708 if (reply == NULL) {
1709 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1713 if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
1714 DBUS_TYPE_INVALID)) {
1715 dbus_message_unref(reply);
1716 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1725 wpas_notify_persistent_group_removed(wpa_s, ssid);
1726 wpa_config_remove_network(wpa_s->conf, ssid->id);
1733 * wpas_dbus_handler_remove_persistent_group - Remove a configured persistent
1735 * @message: Pointer to incoming dbus message
1736 * @wpa_s: wpa_supplicant structure for a network interface
1737 * Returns: NULL on success or dbus error on failure
1739 * Handler function for "RemovePersistentGroup" method call of a P2P Device
1742 DBusMessage * wpas_dbus_handler_remove_persistent_group(
1743 DBusMessage *message, struct wpa_supplicant *wpa_s)
1745 DBusMessage *reply = NULL;
1747 char *iface = NULL, *persistent_group_id = NULL;
1749 struct wpa_ssid *ssid;
1751 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
1755 * Extract the network ID and ensure the network is actually a child of
1758 iface = wpas_dbus_new_decompose_object_path(op, 1,
1759 &persistent_group_id,
1761 if (iface == NULL || os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
1762 reply = wpas_dbus_error_invalid_args(message, op);
1766 id = strtoul(persistent_group_id, NULL, 10);
1767 if (errno == EINVAL) {
1768 reply = wpas_dbus_error_invalid_args(message, op);
1772 ssid = wpa_config_get_network(wpa_s->conf, id);
1774 reply = wpas_dbus_error_persistent_group_unknown(message);
1778 wpas_notify_persistent_group_removed(wpa_s, ssid);
1780 if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
1781 wpa_printf(MSG_ERROR, "dbus: %s: "
1782 "error occurred when removing persistent group %d",
1784 reply = wpas_dbus_error_unknown_error(
1786 "error removing the specified persistent group on "
1793 os_free(persistent_group_id);
1798 static void remove_persistent_group(struct wpa_supplicant *wpa_s,
1799 struct wpa_ssid *ssid)
1801 wpas_notify_persistent_group_removed(wpa_s, ssid);
1803 if (wpa_config_remove_network(wpa_s->conf, ssid->id) < 0) {
1804 wpa_printf(MSG_ERROR, "dbus: %s: "
1805 "error occurred when removing persistent group %d",
1806 __func__, ssid->id);
1813 * wpas_dbus_handler_remove_all_persistent_groups - Remove all configured
1815 * @message: Pointer to incoming dbus message
1816 * @wpa_s: wpa_supplicant structure for a network interface
1817 * Returns: NULL on success or dbus error on failure
1819 * Handler function for "RemoveAllPersistentGroups" method call of a
1820 * P2P Device interface.
1822 DBusMessage * wpas_dbus_handler_remove_all_persistent_groups(
1823 DBusMessage *message, struct wpa_supplicant *wpa_s)
1825 struct wpa_ssid *ssid, *next;
1826 struct wpa_config *config;
1828 config = wpa_s->conf;
1829 ssid = config->ssid;
1832 if (network_is_persistent_group(ssid))
1833 remove_persistent_group(wpa_s, ssid);
1841 * Group object properties accessor methods
1844 dbus_bool_t wpas_dbus_getter_p2p_group_members(DBusMessageIter *iter,
1848 struct wpa_supplicant *wpa_s = user_data;
1849 struct wpa_ssid *ssid;
1850 unsigned int num_members;
1855 dbus_bool_t success = FALSE;
1857 /* Verify correct role for this property */
1858 if (wpas_get_p2p_role(wpa_s) != WPAS_P2P_ROLE_GO) {
1859 return wpas_dbus_simple_array_property_getter(
1860 iter, DBUS_TYPE_OBJECT_PATH, NULL, 0, error);
1863 ssid = wpa_s->conf->ssid;
1864 /* At present WPAS P2P_GO mode only applicable for p2p_go */
1865 if (ssid->mode != WPAS_MODE_P2P_GO &&
1866 ssid->mode != WPAS_MODE_AP &&
1867 ssid->mode != WPAS_MODE_P2P_GROUP_FORMATION)
1870 num_members = p2p_get_group_num_members(wpa_s->p2p_group);
1872 paths = os_calloc(num_members, sizeof(char *));
1877 while ((addr = p2p_iterate_group_members(wpa_s->p2p_group, &next))) {
1878 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1881 os_snprintf(paths[i], WPAS_DBUS_OBJECT_PATH_MAX,
1882 "%s/" WPAS_DBUS_NEW_P2P_GROUPMEMBERS_PART
1884 wpa_s->dbus_groupobj_path, MAC2STR(addr));
1888 success = wpas_dbus_simple_array_property_getter(iter,
1889 DBUS_TYPE_OBJECT_PATH,
1893 for (i = 0; i < num_members; i++)
1899 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1901 for (i = 0; i < num_members; i++)
1909 dbus_bool_t wpas_dbus_getter_p2p_group_ssid(DBusMessageIter *iter,
1910 DBusError *error, void *user_data)
1912 struct wpa_supplicant *wpa_s = user_data;
1913 if (wpa_s->current_ssid == NULL)
1915 return wpas_dbus_simple_array_property_getter(
1916 iter, DBUS_TYPE_BYTE, wpa_s->current_ssid->ssid,
1917 wpa_s->current_ssid->ssid_len, error);
1921 dbus_bool_t wpas_dbus_getter_p2p_group_bssid(DBusMessageIter *iter,
1925 struct wpa_supplicant *wpa_s = user_data;
1926 u8 role = wpas_get_p2p_role(wpa_s);
1929 if (role == WPAS_P2P_ROLE_CLIENT) {
1930 if (wpa_s->current_ssid == NULL)
1932 p_bssid = wpa_s->current_ssid->bssid;
1934 if (wpa_s->ap_iface == NULL)
1936 p_bssid = wpa_s->ap_iface->bss[0]->own_addr;
1939 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
1945 dbus_bool_t wpas_dbus_getter_p2p_group_frequency(DBusMessageIter *iter,
1949 struct wpa_supplicant *wpa_s = user_data;
1951 u8 role = wpas_get_p2p_role(wpa_s);
1953 if (role == WPAS_P2P_ROLE_CLIENT) {
1954 if (wpa_s->go_params == NULL)
1956 op_freq = wpa_s->go_params->freq;
1958 if (wpa_s->ap_iface == NULL)
1960 op_freq = wpa_s->ap_iface->freq;
1963 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
1968 dbus_bool_t wpas_dbus_getter_p2p_group_passphrase(DBusMessageIter *iter,
1972 struct wpa_supplicant *wpa_s = user_data;
1973 u8 role = wpas_get_p2p_role(wpa_s);
1974 char *p_pass = NULL;
1976 /* Verify correct role for this property */
1977 if (role == WPAS_P2P_ROLE_GO) {
1978 if (wpa_s->current_ssid == NULL)
1980 p_pass = wpa_s->current_ssid->passphrase;
1984 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
1990 dbus_bool_t wpas_dbus_getter_p2p_group_psk(DBusMessageIter *iter,
1991 DBusError *error, void *user_data)
1993 struct wpa_supplicant *wpa_s = user_data;
1994 u8 role = wpas_get_p2p_role(wpa_s);
1998 /* Verify correct role for this property */
1999 if (role == WPAS_P2P_ROLE_CLIENT) {
2000 if (wpa_s->current_ssid == NULL)
2002 p_psk = wpa_s->current_ssid->psk;
2006 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
2007 &p_psk, psk_len, error);
2011 dbus_bool_t wpas_dbus_getter_p2p_group_vendor_ext(DBusMessageIter *iter,
2015 struct wpa_supplicant *wpa_s = user_data;
2016 struct hostapd_data *hapd;
2017 struct wpabuf *vendor_ext[MAX_WPS_VENDOR_EXTENSIONS];
2018 int num_vendor_ext = 0;
2021 /* Verify correct role for this property */
2022 if (wpas_get_p2p_role(wpa_s) == WPAS_P2P_ROLE_GO) {
2023 if (wpa_s->ap_iface == NULL)
2025 hapd = wpa_s->ap_iface->bss[0];
2027 /* Parse WPS Vendor Extensions sent in Beacon/Probe Response */
2028 for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
2029 if (hapd->conf->wps_vendor_ext[i] == NULL)
2031 vendor_ext[num_vendor_ext++] =
2032 hapd->conf->wps_vendor_ext[i];
2036 /* Return vendor extensions or no data */
2037 return wpas_dbus_simple_array_array_property_getter(iter,
2045 dbus_bool_t wpas_dbus_setter_p2p_group_vendor_ext(DBusMessageIter *iter,
2049 struct wpa_supplicant *wpa_s = user_data;
2050 DBusMessageIter variant_iter, iter_dict;
2051 struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
2053 struct hostapd_data *hapd = NULL;
2055 if (wpas_get_p2p_role(wpa_s) == WPAS_P2P_ROLE_GO &&
2056 wpa_s->ap_iface != NULL)
2057 hapd = wpa_s->ap_iface->bss[0];
2061 dbus_message_iter_recurse(iter, &variant_iter);
2062 if (!wpa_dbus_dict_open_read(&variant_iter, &iter_dict, error))
2065 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2066 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) {
2067 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
2068 "invalid message format");
2072 if (os_strcmp(entry.key, "WPSVendorExtensions") == 0) {
2073 if (entry.type != DBUS_TYPE_ARRAY ||
2074 entry.array_type != WPAS_DBUS_TYPE_BINARRAY ||
2075 entry.array_len > MAX_WPS_VENDOR_EXTENSIONS)
2078 for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
2079 if (i < entry.array_len) {
2080 hapd->conf->wps_vendor_ext[i] =
2081 entry.binarray_value[i];
2082 entry.binarray_value[i] = NULL;
2084 hapd->conf->wps_vendor_ext[i] = NULL;
2087 hostapd_update_wps(hapd);
2091 wpa_dbus_dict_entry_clear(&entry);
2097 wpa_dbus_dict_entry_clear(&entry);
2098 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
2099 "invalid message format");
2104 DBusMessage * wpas_dbus_handler_p2p_add_service(DBusMessage *message,
2105 struct wpa_supplicant *wpa_s)
2107 DBusMessageIter iter_dict;
2108 DBusMessage *reply = NULL;
2109 DBusMessageIter iter;
2110 struct wpa_dbus_dict_entry entry;
2113 char *service = NULL;
2114 struct wpabuf *query = NULL;
2115 struct wpabuf *resp = NULL;
2118 dbus_message_iter_init(message, &iter);
2120 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
2123 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2124 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2127 if (!os_strcmp(entry.key, "service_type") &&
2128 (entry.type == DBUS_TYPE_STRING)) {
2129 if (!os_strcmp(entry.str_value, "upnp"))
2131 else if (!os_strcmp(entry.str_value, "bonjour"))
2135 } else if (!os_strcmp(entry.key, "version") &&
2136 entry.type == DBUS_TYPE_INT32) {
2137 version = entry.uint32_value;
2138 } else if (!os_strcmp(entry.key, "service") &&
2139 (entry.type == DBUS_TYPE_STRING)) {
2140 service = os_strdup(entry.str_value);
2141 } else if (!os_strcmp(entry.key, "query")) {
2142 if ((entry.type != DBUS_TYPE_ARRAY) ||
2143 (entry.array_type != DBUS_TYPE_BYTE))
2145 query = wpabuf_alloc_copy(
2146 entry.bytearray_value,
2148 } else if (!os_strcmp(entry.key, "response")) {
2149 if ((entry.type != DBUS_TYPE_ARRAY) ||
2150 (entry.array_type != DBUS_TYPE_BYTE))
2152 resp = wpabuf_alloc_copy(entry.bytearray_value,
2155 wpa_dbus_dict_entry_clear(&entry);
2159 if (version <= 0 || service == NULL)
2162 if (wpas_p2p_service_add_upnp(wpa_s, version, service) != 0)
2167 } else if (bonjour == 1) {
2168 if (query == NULL || resp == NULL)
2171 if (wpas_p2p_service_add_bonjour(wpa_s, query, resp) < 0)
2180 wpa_dbus_dict_entry_clear(&entry);
2185 return wpas_dbus_error_invalid_args(message, NULL);
2189 DBusMessage * wpas_dbus_handler_p2p_delete_service(
2190 DBusMessage *message, struct wpa_supplicant *wpa_s)
2192 DBusMessageIter iter_dict;
2193 DBusMessage *reply = NULL;
2194 DBusMessageIter iter;
2195 struct wpa_dbus_dict_entry entry;
2199 char *service = NULL;
2200 struct wpabuf *query = NULL;
2203 dbus_message_iter_init(message, &iter);
2205 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
2208 if (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2209 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2212 if (!os_strcmp(entry.key, "service_type") &&
2213 (entry.type == DBUS_TYPE_STRING)) {
2214 if (!os_strcmp(entry.str_value, "upnp"))
2216 else if (!os_strcmp(entry.str_value, "bonjour"))
2220 wpa_dbus_dict_entry_clear(&entry);
2224 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2225 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2227 if (!os_strcmp(entry.key, "version") &&
2228 entry.type == DBUS_TYPE_INT32)
2229 version = entry.uint32_value;
2230 else if (!os_strcmp(entry.key, "service") &&
2231 entry.type == DBUS_TYPE_STRING)
2232 service = os_strdup(entry.str_value);
2236 wpa_dbus_dict_entry_clear(&entry);
2239 if (version <= 0 || service == NULL)
2242 ret = wpas_p2p_service_del_upnp(wpa_s, version, service);
2246 } else if (bonjour == 1) {
2247 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2248 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2251 if (!os_strcmp(entry.key, "query")) {
2252 if ((entry.type != DBUS_TYPE_ARRAY) ||
2253 (entry.array_type != DBUS_TYPE_BYTE))
2255 query = wpabuf_alloc_copy(
2256 entry.bytearray_value,
2261 wpa_dbus_dict_entry_clear(&entry);
2267 ret = wpas_p2p_service_del_bonjour(wpa_s, query);
2276 wpa_dbus_dict_entry_clear(&entry);
2278 return wpas_dbus_error_invalid_args(message, NULL);
2282 DBusMessage * wpas_dbus_handler_p2p_flush_service(DBusMessage *message,
2283 struct wpa_supplicant *wpa_s)
2285 wpas_p2p_service_flush(wpa_s);
2290 DBusMessage * wpas_dbus_handler_p2p_service_sd_req(
2291 DBusMessage *message, struct wpa_supplicant *wpa_s)
2293 DBusMessageIter iter_dict;
2294 DBusMessage *reply = NULL;
2295 DBusMessageIter iter;
2296 struct wpa_dbus_dict_entry entry;
2298 char *service = NULL;
2299 char *peer_object_path = NULL;
2300 struct wpabuf *tlv = NULL;
2303 u8 addr_buf[ETH_ALEN], *addr;
2305 dbus_message_iter_init(message, &iter);
2307 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
2310 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2311 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2313 if (!os_strcmp(entry.key, "peer_object") &&
2314 entry.type == DBUS_TYPE_OBJECT_PATH) {
2315 peer_object_path = os_strdup(entry.str_value);
2316 } else if (!os_strcmp(entry.key, "service_type") &&
2317 entry.type == DBUS_TYPE_STRING) {
2318 if (!os_strcmp(entry.str_value, "upnp"))
2322 } else if (!os_strcmp(entry.key, "version") &&
2323 entry.type == DBUS_TYPE_INT32) {
2324 version = entry.uint32_value;
2325 } else if (!os_strcmp(entry.key, "service") &&
2326 entry.type == DBUS_TYPE_STRING) {
2327 service = os_strdup(entry.str_value);
2328 } else if (!os_strcmp(entry.key, "tlv")) {
2329 if (entry.type != DBUS_TYPE_ARRAY ||
2330 entry.array_type != DBUS_TYPE_BYTE)
2332 tlv = wpabuf_alloc_copy(entry.bytearray_value,
2337 wpa_dbus_dict_entry_clear(&entry);
2340 if (!peer_object_path) {
2343 if (parse_peer_object_path(peer_object_path, addr_buf) < 0 ||
2344 !p2p_peer_known(wpa_s->global->p2p, addr_buf))
2351 if (version <= 0 || service == NULL)
2354 ref = wpas_p2p_sd_request_upnp(wpa_s, addr, version, service);
2358 ref = wpas_p2p_sd_request(wpa_s, addr, tlv);
2363 reply = dbus_message_new_method_return(message);
2364 dbus_message_append_args(reply, DBUS_TYPE_UINT64,
2365 &ref, DBUS_TYPE_INVALID);
2367 reply = wpas_dbus_error_unknown_error(
2368 message, "Unable to send SD request");
2372 os_free(peer_object_path);
2375 wpa_dbus_dict_entry_clear(&entry);
2379 reply = wpas_dbus_error_invalid_args(message, NULL);
2384 DBusMessage * wpas_dbus_handler_p2p_service_sd_res(
2385 DBusMessage *message, struct wpa_supplicant *wpa_s)
2387 DBusMessageIter iter_dict;
2388 DBusMessage *reply = NULL;
2389 DBusMessageIter iter;
2390 struct wpa_dbus_dict_entry entry;
2391 char *peer_object_path = NULL;
2392 struct wpabuf *tlv = NULL;
2397 dbus_message_iter_init(message, &iter);
2399 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
2402 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2403 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2406 if (!os_strcmp(entry.key, "peer_object") &&
2407 entry.type == DBUS_TYPE_OBJECT_PATH) {
2408 peer_object_path = os_strdup(entry.str_value);
2409 } else if (!os_strcmp(entry.key, "frequency") &&
2410 entry.type == DBUS_TYPE_INT32) {
2411 freq = entry.uint32_value;
2412 } else if (!os_strcmp(entry.key, "dialog_token") &&
2413 entry.type == DBUS_TYPE_UINT32) {
2414 dlg_tok = entry.uint32_value;
2415 } else if (!os_strcmp(entry.key, "tlvs")) {
2416 if (entry.type != DBUS_TYPE_ARRAY ||
2417 entry.array_type != DBUS_TYPE_BYTE)
2419 tlv = wpabuf_alloc_copy(entry.bytearray_value,
2424 wpa_dbus_dict_entry_clear(&entry);
2426 if (!peer_object_path ||
2427 (parse_peer_object_path(peer_object_path, addr) < 0) ||
2428 !p2p_peer_known(wpa_s->global->p2p, addr))
2434 wpas_p2p_sd_response(wpa_s, freq, addr, (u8) dlg_tok, tlv);
2437 os_free(peer_object_path);
2440 wpa_dbus_dict_entry_clear(&entry);
2442 reply = wpas_dbus_error_invalid_args(message, NULL);
2447 DBusMessage * wpas_dbus_handler_p2p_service_sd_cancel_req(
2448 DBusMessage *message, struct wpa_supplicant *wpa_s)
2450 DBusMessageIter iter;
2453 dbus_message_iter_init(message, &iter);
2454 dbus_message_iter_get_basic(&iter, &req);
2459 if (wpas_p2p_sd_cancel_request(wpa_s, req) < 0)
2464 return wpas_dbus_error_invalid_args(message, NULL);
2468 DBusMessage * wpas_dbus_handler_p2p_service_update(
2469 DBusMessage *message, struct wpa_supplicant *wpa_s)
2471 wpas_p2p_sd_service_update(wpa_s);
2476 DBusMessage * wpas_dbus_handler_p2p_serv_disc_external(
2477 DBusMessage *message, struct wpa_supplicant *wpa_s)
2479 DBusMessageIter iter;
2482 dbus_message_iter_init(message, &iter);
2483 dbus_message_iter_get_basic(&iter, &ext);
2485 wpa_s->p2p_sd_over_ctrl_iface = ext;