2 * WPA Supplicant / dbus-based control interface (P2P)
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
8 * Alternatively, this software may be distributed under the terms of BSD
11 * See README and COPYING for more details.
16 #include "utils/includes.h"
18 #include "../config.h"
19 #include "../wpa_supplicant_i.h"
20 #include "../wps_supplicant.h"
21 #include "dbus_new_helpers.h"
23 #include "dbus_new_handlers.h"
24 #include "dbus_new_handlers_p2p.h"
25 #include "dbus_dict_helpers.h"
27 #include "common/ieee802_11_defs.h"
28 #include "ap/hostapd.h"
29 #include "ap/ap_config.h"
30 #include "ap/wps_hostapd.h"
32 #include "../p2p_supplicant.h"
35 * Parses out the mac address from the peer object path.
36 * @peer_path - object path of the form
37 * /fi/w1/wpa_supplicant1/Interfaces/n/Peers/00112233445566 (no colons)
38 * @addr - out param must be of ETH_ALEN size
39 * Returns 0 if valid (including MAC), -1 otherwise
41 static int parse_peer_object_path(char *peer_path, u8 addr[ETH_ALEN])
47 p = strrchr(peer_path, '/');
51 return hwaddr_compact_aton(p, addr);
54 DBusMessage *wpas_dbus_handler_p2p_find(DBusMessage * message,
55 struct wpa_supplicant * wpa_s)
57 struct wpa_dbus_dict_entry entry;
58 DBusMessage *reply = NULL;
60 DBusMessageIter iter_dict;
61 unsigned int timeout = 0;
62 unsigned int searchonly = 0;
63 enum p2p_discovery_type type = P2P_FIND_ONLY_SOCIAL;
64 int num_req_dev_types = 0;
66 u8 *req_dev_types = NULL;
68 dbus_message_iter_init(message, &iter);
70 if (!wpa_dbus_dict_open_read(&iter, &iter_dict))
73 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
74 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
77 if (!os_strcmp(entry.key, "Timeout") &&
78 (entry.type == DBUS_TYPE_INT32)) {
79 timeout = entry.uint32_value;
80 } else if (!os_strcmp(entry.key, "SearchOnly") &&
81 (entry.type == DBUS_TYPE_BOOLEAN)) {
82 searchonly = (entry.bool_value == TRUE) ? 1 : 0;
83 } else if (os_strcmp(entry.key, "RequestedDeviceTypes") == 0) {
84 if ((entry.type != DBUS_TYPE_ARRAY) ||
85 (entry.array_type != WPAS_DBUS_TYPE_BINARRAY))
89 os_malloc(WPS_DEV_TYPE_LEN * entry.array_len);
93 for (i = 0; i < entry.array_len; i++) {
94 if (wpabuf_len(entry.binarray_value[i]) !=
97 os_memcpy(req_dev_types + i * WPS_DEV_TYPE_LEN,
98 wpabuf_head(entry.binarray_value[i]),
102 num_req_dev_types = entry.array_len;
105 wpa_dbus_dict_entry_clear(&entry);
108 wpas_p2p_find(wpa_s, timeout, type, num_req_dev_types, req_dev_types);
112 os_free(req_dev_types);
113 wpa_dbus_dict_entry_clear(&entry);
115 reply = wpas_dbus_error_invalid_args(message, entry.key);
119 DBusMessage *wpas_dbus_handler_p2p_stop_find(DBusMessage * message,
120 struct wpa_supplicant * wpa_s)
122 wpas_p2p_stop_find(wpa_s);
126 DBusMessage *wpas_dbus_handler_p2p_rejectpeer(DBusMessage * message,
127 struct wpa_supplicant * wpa_s)
129 DBusMessageIter iter;
130 char *peer_object_path = NULL;
131 u8 peer_addr[ETH_ALEN];
133 dbus_message_iter_init(message, &iter);
134 dbus_message_iter_get_basic(&iter, &peer_object_path);
136 if (parse_peer_object_path(peer_object_path, peer_addr) < 0)
137 return wpas_dbus_error_invalid_args(message, NULL);
139 if (wpas_p2p_reject(wpa_s, peer_addr) < 0)
140 return wpas_dbus_error_unknown_error(message,
141 "Failed to call wpas_p2p_reject method.");
146 DBusMessage *wpas_dbus_handler_p2p_listen(DBusMessage * message,
147 struct wpa_supplicant * wpa_s)
149 dbus_int32_t timeout = 0;
151 if (!dbus_message_get_args(message, NULL, DBUS_TYPE_INT32, &timeout,
153 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
156 if (wpas_p2p_listen(wpa_s, (unsigned int)timeout))
157 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
163 DBusMessage *wpas_dbus_handler_p2p_extendedlisten(DBusMessage * message,
164 struct wpa_supplicant * wpa_s)
166 unsigned int period = 0, interval = 0;
167 struct wpa_dbus_dict_entry entry;
168 DBusMessageIter iter;
169 DBusMessageIter iter_dict;
171 dbus_message_iter_init(message, &iter);
173 if (!wpa_dbus_dict_open_read(&iter, &iter_dict))
176 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
177 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
180 if (!strcmp(entry.key, "period") &&
181 (entry.type == DBUS_TYPE_INT32))
182 period = entry.uint32_value;
183 else if (!strcmp(entry.key, "interval") &&
184 (entry.type == DBUS_TYPE_INT32))
185 interval = entry.uint32_value;
188 wpa_dbus_dict_entry_clear(&entry);
191 if (wpas_p2p_ext_listen(wpa_s, period, interval))
192 return wpas_dbus_error_unknown_error(message,
193 "failed to initiate a p2p_ext_listen.");
198 wpa_dbus_dict_entry_clear(&entry);
200 return wpas_dbus_error_invalid_args(message, entry.key);
203 DBusMessage *wpas_dbus_handler_p2p_presence_request(DBusMessage * message,
204 struct wpa_supplicant *
207 unsigned int dur1 = 0, int1 = 0, dur2 = 0, int2 = 0;
208 struct wpa_dbus_dict_entry entry;
209 DBusMessageIter iter;
210 DBusMessageIter iter_dict;
212 dbus_message_iter_init(message, &iter);
214 if (!wpa_dbus_dict_open_read(&iter, &iter_dict))
217 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
218 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
221 if (!strcmp(entry.key, "duration1") &&
222 (entry.type == DBUS_TYPE_INT32))
223 dur1 = entry.uint32_value;
224 else if (!strcmp(entry.key, "interval1") &&
225 entry.type == DBUS_TYPE_INT32)
226 int1 = entry.uint32_value;
227 else if (!strcmp(entry.key, "duration2") &&
228 entry.type == DBUS_TYPE_INT32)
229 dur2 = entry.uint32_value;
230 else if (!strcmp(entry.key, "interval2") &&
231 entry.type == DBUS_TYPE_INT32)
232 int2 = entry.uint32_value;
236 wpa_dbus_dict_entry_clear(&entry);
238 if (wpas_p2p_presence_req(wpa_s, dur1, int1, dur2, int2) < 0)
239 return wpas_dbus_error_unknown_error(message,
240 "Failed to invoke presence request.");
245 wpa_dbus_dict_entry_clear(&entry);
247 return wpas_dbus_error_invalid_args(message, entry.key);
250 DBusMessage *wpas_dbus_handler_p2p_group_add(DBusMessage * message,
251 struct wpa_supplicant * wpa_s)
253 DBusMessageIter iter_dict;
254 DBusMessage *reply = NULL;
255 DBusMessageIter iter;
256 struct wpa_dbus_dict_entry entry;
257 char *network_object_path = NULL;
258 int persistent_group = 0;
261 char *net_id_str = NULL;
262 unsigned int group_id = 0;
263 struct wpa_ssid *ssid;
265 dbus_message_iter_init(message, &iter);
267 if (!wpa_dbus_dict_open_read(&iter, &iter_dict))
270 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
271 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
274 if (!strcmp(entry.key, "persistent") &&
275 (entry.type == DBUS_TYPE_BOOLEAN)) {
276 persistent_group = (entry.bool_value == TRUE) ? 1 : 0;
277 } else if (!strcmp(entry.key, "frequency") &&
278 (entry.type == DBUS_TYPE_INT32)) {
279 freq = entry.int32_value;
282 } else if (!strcmp(entry.key, "network_object") &&
283 entry.type == DBUS_TYPE_OBJECT_PATH)
284 network_object_path = os_strdup(entry.str_value);
288 wpa_dbus_dict_entry_clear(&entry);
291 if (network_object_path != NULL) {
293 * A Network Object Path is defined meaning we want to re-invoke
294 * a persisatnt group.
297 iface = wpas_dbus_new_decompose_object_path(network_object_path,
300 os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
302 wpas_dbus_error_invalid_args(message,
303 network_object_path);
307 group_id = strtoul(net_id_str, NULL, 10);
308 if (errno == EINVAL) {
309 reply = wpas_dbus_error_invalid_args(
310 message, network_object_path);
314 /* Get the SSID structure form the persistant group id */
315 ssid = wpa_config_get_network(wpa_s->conf, group_id);
316 if (ssid == NULL || ssid->disabled != 2)
319 if (wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq)) {
320 reply = wpas_dbus_error_unknown_error(message,
321 "Failed to reinvoke a persistent group");
324 } else if (wpas_p2p_group_add(wpa_s, persistent_group, freq))
328 os_free(network_object_path);
333 wpa_dbus_dict_entry_clear(&entry);
335 reply = wpas_dbus_error_invalid_args(message, NULL);
339 DBusMessage *wpas_dbus_handler_p2p_disconnect(DBusMessage *message,
340 struct wpa_supplicant *wpa_s)
342 if (wpas_p2p_disconnect(wpa_s))
343 return wpas_dbus_error_unknown_error(message,
344 "failed to disconnect");
349 DBusMessage *wpas_dbus_handler_p2p_flush(DBusMessage * message,
350 struct wpa_supplicant * wpa_s)
352 os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
353 wpa_s->force_long_sd = 0;
354 p2p_flush(wpa_s->global->p2p);
359 DBusMessage *wpas_dbus_handler_p2p_connect(DBusMessage * message,
360 struct wpa_supplicant * wpa_s)
362 DBusMessageIter iter_dict;
363 DBusMessage *reply = NULL;
364 DBusMessageIter iter;
365 struct wpa_dbus_dict_entry entry;
366 char *peer_object_path = NULL;
367 int persistent_group = 0;
369 int authorize_only = 0;
374 enum p2p_wps_method wps_method = WPS_NOT_READY;
376 char *err_msg = NULL;
379 dbus_message_iter_init(message, &iter);
381 if (!wpa_dbus_dict_open_read(&iter, &iter_dict))
384 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
385 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
388 if (!strcmp(entry.key, "peer") &&
389 (entry.type == DBUS_TYPE_OBJECT_PATH)) {
390 peer_object_path = os_strdup(entry.str_value);
391 } else if (!strcmp(entry.key, "persistent") &&
392 (entry.type == DBUS_TYPE_BOOLEAN)) {
393 persistent_group = (entry.bool_value == TRUE) ? 1 : 0;
394 } else if (!strcmp(entry.key, "join") &&
395 (entry.type == DBUS_TYPE_BOOLEAN)) {
396 join = (entry.bool_value == TRUE) ? 1 : 0;
397 } else if (!strcmp(entry.key, "authorize_only") &&
398 (entry.type == DBUS_TYPE_BOOLEAN)) {
399 authorize_only = (entry.bool_value == TRUE) ? 1 : 0;
400 } else if (!strcmp(entry.key, "frequency") &&
401 (entry.type == DBUS_TYPE_INT32)) {
402 freq = entry.int32_value;
405 } else if (!strcmp(entry.key, "go_intent") &&
406 (entry.type == DBUS_TYPE_INT32)) {
407 go_intent = entry.int32_value;
408 if ((go_intent < 0) || (go_intent > 15))
410 } else if (!strcmp(entry.key, "wps_method") &&
411 (entry.type == DBUS_TYPE_STRING)) {
412 if (!strcmp(entry.str_value, "pbc"))
413 wps_method = WPS_PBC;
414 else if (!strcmp(entry.str_value, "pin"))
415 wps_method = WPS_PIN_DISPLAY;
416 else if (!strcmp(entry.str_value, "label"))
417 wps_method = WPS_PIN_LABEL;
418 else if (!strcmp(entry.str_value, "display"))
419 wps_method = WPS_PIN_DISPLAY;
420 else if (!strcmp(entry.str_value, "keypad"))
421 wps_method = WPS_PIN_KEYPAD;
424 } else if (!strcmp(entry.key, "pin") &&
425 (entry.type == DBUS_TYPE_STRING)) {
426 pin = os_strdup(entry.str_value);
430 wpa_dbus_dict_entry_clear(&entry);
433 if (!peer_object_path || (wps_method == WPS_NOT_READY) ||
434 (parse_peer_object_path(peer_object_path, addr) < 0) ||
435 (p2p_get_peer_info(wpa_s->global->p2p, addr, 0, NULL, 0) < 0)) {
436 reply = wpas_dbus_error_invalid_args(message, NULL);
441 * Validate the wps_method specified and the pin value.
443 if ((!pin || !pin[0]) &&
444 ((wps_method == WPS_PIN_LABEL) || (wps_method == WPS_PIN_KEYPAD)))
447 new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
448 persistent_group, join, authorize_only,
452 reply = dbus_message_new_method_return(message);
453 dbus_message_append_args(reply, DBUS_TYPE_INT32,
454 &new_pin, DBUS_TYPE_INVALID);
458 err_msg = "connect failed due to"
459 " channel unavailability.";
460 iface = WPAS_DBUS_ERROR_CONNECT_CHANNEL_UNAVAILABLE;
464 err_msg = "connect failed due to"
465 " unsupported channel.";
466 iface = WPAS_DBUS_ERROR_CONNECT_CHANNEL_UNSUPPORTED;
470 err_msg = "connect failed due to"
471 " unspecified error.";
472 iface = WPAS_DBUS_ERROR_CONNECT_UNSPECIFIED_ERROR;
477 * Do we need specialized errors corresponding to above
478 * error conditions as against just returning a different
481 reply = dbus_message_new_error(message, iface, err_msg);
485 os_free(peer_object_path);
489 wpa_dbus_dict_entry_clear(&entry);
491 reply = wpas_dbus_error_invalid_args(message, NULL);
495 DBusMessage *wpas_dbus_handler_p2p_invite(DBusMessage * message,
496 struct wpa_supplicant *wpa_s)
498 DBusMessageIter iter_dict;
499 DBusMessage *reply = NULL;
500 DBusMessageIter iter;
501 struct wpa_dbus_dict_entry entry;
502 char *peer_object_path = NULL;
503 char *network_object_path = NULL;
505 char *net_id_str = NULL;
506 u8 peer_addr[ETH_ALEN];
507 unsigned int group_id = 0;
509 struct wpa_ssid *ssid;
511 dbus_message_iter_init(message, &iter);
513 if (!wpa_dbus_dict_open_read(&iter, &iter_dict))
516 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
517 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
520 if (!strcmp(entry.key, "peer") &&
521 (entry.type == DBUS_TYPE_OBJECT_PATH)) {
522 peer_object_path = os_strdup(entry.str_value);
523 wpa_dbus_dict_entry_clear(&entry);
524 } else if (!strcmp(entry.key, "network_object") &&
525 (entry.type == DBUS_TYPE_OBJECT_PATH)) {
526 network_object_path = os_strdup(entry.str_value);
528 wpa_dbus_dict_entry_clear(&entry);
530 wpa_dbus_dict_entry_clear(&entry);
535 if (!peer_object_path ||
536 (parse_peer_object_path(peer_object_path, peer_addr) < 0) ||
537 (p2p_get_peer_info(wpa_s->global->p2p,
538 peer_addr, 0, NULL, 0) < 0)) {
544 * A group ID is defined meaning we want to re-invoke a
548 iface = wpas_dbus_new_decompose_object_path(network_object_path,
551 os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
553 wpas_dbus_error_invalid_args(message,
554 network_object_path);
558 group_id = strtoul(net_id_str, NULL, 10);
559 if (errno == EINVAL) {
560 reply = wpas_dbus_error_invalid_args(
561 message, network_object_path);
565 /* Get the SSID structure form the persistant group id */
566 ssid = wpa_config_get_network(wpa_s->conf, group_id);
567 if (ssid == NULL || ssid->disabled != 2)
570 if (wpas_p2p_invite(wpa_s, peer_addr, ssid, NULL) < 0) {
571 reply = wpas_dbus_error_unknown_error(
573 "Failed to reinvoke a persistent group");
578 * No group ID means propose to a peer to join my active group
580 if (wpas_p2p_invite_group(wpa_s, wpa_s->ifname,
582 reply = wpas_dbus_error_unknown_error(
584 "Failed to join to an active group");
590 os_free(network_object_path);
591 os_free(peer_object_path);
595 reply = wpas_dbus_error_invalid_args(message, NULL);
599 DBusMessage *wpas_dbus_handler_p2p_prov_disc_req(DBusMessage * message,
600 struct wpa_supplicant *wpa_s)
602 DBusMessageIter iter;
603 char *peer_object_path = NULL;
604 char *config_method = NULL;
605 u8 peer_addr[ETH_ALEN];
607 dbus_message_iter_init(message, &iter);
608 dbus_message_iter_get_basic(&iter, &peer_object_path);
610 if (parse_peer_object_path(peer_object_path, peer_addr) < 0)
611 return wpas_dbus_error_invalid_args(message, NULL);
613 dbus_message_iter_next(&iter);
614 dbus_message_iter_get_basic(&iter, &config_method);
617 * Validation checks on config_method are being duplicated here
618 * to be able to return invalid args reply since the error code
619 * from p2p module are not granular enough (yet).
621 if (os_strcmp(config_method, "display") &&
622 os_strcmp(config_method, "keypad") &&
623 os_strcmp(config_method, "pbc") &&
624 os_strcmp(config_method, "pushbutton"))
625 return wpas_dbus_error_invalid_args(message, NULL);
627 if (wpas_p2p_prov_disc(wpa_s, peer_addr, config_method) < 0)
628 return wpas_dbus_error_unknown_error(message,
629 "Failed to send provision discovery request");
635 * P2P Device property accessor methods.
638 DBusMessage *wpas_dbus_getter_p2p_device_properties(DBusMessage * message,
639 struct wpa_supplicant *
642 DBusMessage *reply = NULL;
643 DBusMessageIter iter, variant_iter, dict_iter;
644 const char *dev_name;
645 int num_sec_dev_types = 0;
646 int num_vendor_extensions = 0;
648 const struct wpabuf *vendor_ext[P2P_MAX_WPS_VENDOR_EXT];
651 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
653 reply = dbus_message_new_method_return(message);
658 dbus_message_iter_init_append(reply, &iter);
660 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
661 "a{sv}", &variant_iter) ||
662 !wpa_dbus_dict_open_write(&variant_iter, &dict_iter))
666 dev_name = wpa_s->conf->device_name;
668 !wpa_dbus_dict_append_string(&dict_iter, "DeviceName", dev_name))
671 /* Primary device type */
672 if (!wpa_dbus_dict_append_byte_array(&dict_iter, "PrimaryDeviceType",
673 (char *)wpa_s->conf->device_type,
677 /* Secondary device types */
678 for (i = 0; i < MAX_SEC_DEVICE_TYPES; i++) {
679 if (wpa_s->conf->sec_device_type[i] == NULL)
684 if (!wpa_dbus_dict_append_string_array(
685 &dict_iter, "SecondaryDeviceTypes",
686 (const char **)wpa_s->conf->sec_device_type,
690 /* Vendor Extensions */
691 for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
692 if (wpa_s->conf->wps_vendor_ext[i] == NULL)
694 vendor_ext[num_vendor_extensions++] =
695 wpa_s->conf->wps_vendor_ext[i];
698 if (num_vendor_extensions &&
699 !wpa_dbus_dict_append_wpabuf_array(&dict_iter,
702 num_vendor_extensions))
706 if (!wpa_dbus_dict_append_uint32(&dict_iter, "GOIntent",
707 wpa_s->conf->p2p_go_intent))
710 /* Persistant Reconnect */
711 if (!wpa_dbus_dict_append_bool(&dict_iter, "PersistantReconnect",
712 wpa_s->conf->persistent_reconnect))
715 /* Listen Reg Class */
716 if (!wpa_dbus_dict_append_uint32(&dict_iter, "ListenRegClass",
717 wpa_s->conf->p2p_listen_reg_class))
721 if (!wpa_dbus_dict_append_uint32(&dict_iter, "ListenChannel",
722 wpa_s->conf->p2p_listen_channel))
726 if (!wpa_dbus_dict_append_uint32(&dict_iter, "OperRegClass",
727 wpa_s->conf->p2p_oper_reg_class))
731 if (!wpa_dbus_dict_append_uint32(&dict_iter, "OperChannel",
732 wpa_s->conf->p2p_oper_channel))
736 if (wpa_s->conf->p2p_ssid_postfix &&
737 !wpa_dbus_dict_append_string(&dict_iter, "SsidPostfix",
738 wpa_s->conf->p2p_ssid_postfix))
742 if (!wpa_dbus_dict_append_bool(&dict_iter, "IntraBss",
743 wpa_s->conf->p2p_intra_bss))
747 if (!wpa_dbus_dict_append_uint32(&dict_iter, "GroupIdle",
748 wpa_s->conf->p2p_group_idle))
751 if (!wpa_dbus_dict_close_write(&variant_iter, &dict_iter) ||
752 !dbus_message_iter_close_container(&iter, &variant_iter))
757 dbus_message_unref(reply);
758 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, NULL);
761 DBusMessage *wpas_dbus_setter_p2p_device_properties(DBusMessage * message,
762 struct wpa_supplicant *
765 DBusMessage *reply = NULL;
766 DBusMessageIter iter, variant_iter;
767 struct wpa_dbus_dict_entry entry = {.type = DBUS_TYPE_STRING };
768 DBusMessageIter iter_dict;
771 dbus_message_iter_init(message, &iter);
773 dbus_message_iter_next(&iter);
774 dbus_message_iter_next(&iter);
776 dbus_message_iter_recurse(&iter, &variant_iter);
778 if (!wpa_dbus_dict_open_read(&variant_iter, &iter_dict))
779 return wpas_dbus_error_invalid_args(message, NULL);
781 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
782 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
783 return wpas_dbus_error_invalid_args(message, NULL);
785 if (os_strcmp(entry.key, "DeviceName") == 0) {
788 if (entry.type != DBUS_TYPE_STRING)
791 devname = os_strdup(entry.str_value);
793 goto err_no_mem_clear;
795 os_free(wpa_s->conf->device_name);
796 wpa_s->conf->device_name = devname;
798 wpa_s->conf->changed_parameters |=
799 CFG_CHANGED_DEVICE_NAME;
800 } else if (os_strcmp(entry.key, "PrimaryDeviceType") == 0) {
801 if (entry.type != DBUS_TYPE_ARRAY ||
802 entry.array_type != DBUS_TYPE_BYTE ||
803 entry.array_len != WPS_DEV_TYPE_LEN)
806 os_memcpy(wpa_s->conf->device_type,
807 entry.bytearray_value,
809 wpa_s->conf->changed_parameters |=
810 CFG_CHANGED_DEVICE_TYPE;
811 } else if (os_strcmp(entry.key, "SecondaryDeviceTypes") == 0) {
812 if (entry.type != DBUS_TYPE_ARRAY ||
813 entry.array_type != WPAS_DBUS_TYPE_BINARRAY ||
814 entry.array_len > MAX_SEC_DEVICE_TYPES)
817 for (i = 0; i < entry.array_len; i++)
818 if (wpabuf_len(entry.binarray_value[i]) != WPS_DEV_TYPE_LEN)
819 goto err_no_mem_clear;
820 for (i = 0; i < entry.array_len; i++)
821 os_memcpy(wpa_s->conf->sec_device_type[i],
822 wpabuf_head(entry.binarray_value[i]),
824 wpa_s->conf->num_sec_device_types = entry.array_len;
825 wpa_s->conf->changed_parameters |=
826 CFG_CHANGED_SEC_DEVICE_TYPE;
827 } else if (os_strcmp(entry.key, "VendorExtension") == 0) {
828 if ((entry.type != DBUS_TYPE_ARRAY) ||
829 (entry.array_type != WPAS_DBUS_TYPE_BINARRAY) ||
830 (entry.array_len > P2P_MAX_WPS_VENDOR_EXT))
833 wpa_s->conf->changed_parameters |=
834 CFG_CHANGED_VENDOR_EXTENSION;
836 for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
837 wpabuf_free(wpa_s->conf->wps_vendor_ext[i]);
838 if (i < entry.array_len) {
839 wpa_s->conf->wps_vendor_ext[i] =
840 entry.binarray_value[i];
841 entry.binarray_value[i] = NULL;
843 wpa_s->conf->wps_vendor_ext[i] = NULL;
845 } else if ((os_strcmp(entry.key, "GOIntent") == 0) &&
846 (entry.type == DBUS_TYPE_UINT32) &&
847 (entry.uint32_value <= 15))
848 wpa_s->conf->p2p_go_intent = entry.uint32_value;
850 else if ((os_strcmp(entry.key, "PersistantReconnect") == 0) &&
851 (entry.type == DBUS_TYPE_BOOLEAN))
852 wpa_s->conf->persistent_reconnect = entry.bool_value;
854 else if ((os_strcmp(entry.key, "ListenRegClass") == 0) &&
855 (entry.type == DBUS_TYPE_UINT32))
856 wpa_s->conf->p2p_listen_reg_class = entry.uint32_value;
858 else if ((os_strcmp(entry.key, "ListenChannel") == 0) &&
859 (entry.type == DBUS_TYPE_UINT32))
860 wpa_s->conf->p2p_listen_channel = entry.uint32_value;
862 else if ((os_strcmp(entry.key, "OperRegClass") == 0) &&
863 (entry.type == DBUS_TYPE_UINT32))
864 wpa_s->conf->p2p_oper_reg_class = entry.uint32_value;
866 else if ((os_strcmp(entry.key, "OperChannel") == 0) &&
867 (entry.type == DBUS_TYPE_UINT32))
868 wpa_s->conf->p2p_oper_channel = entry.uint32_value;
870 else if (os_strcmp(entry.key, "SsidPostfix") == 0) {
873 if (entry.type != DBUS_TYPE_STRING)
876 postfix = os_strdup(entry.str_value);
878 goto err_no_mem_clear;
880 os_free(wpa_s->conf->p2p_ssid_postfix);
881 wpa_s->conf->p2p_ssid_postfix = postfix;
883 wpa_s->conf->changed_parameters |=
884 CFG_CHANGED_P2P_SSID_POSTFIX;
885 } else if ((os_strcmp(entry.key, "IntraBss") == 0) &&
886 (entry.type == DBUS_TYPE_BOOLEAN)) {
887 wpa_s->conf->p2p_intra_bss = entry.bool_value;
888 wpa_s->conf->changed_parameters |=
889 CFG_CHANGED_P2P_INTRA_BSS;
890 } else if ((os_strcmp(entry.key, "GroupIdle") == 0) &&
891 (entry.type == DBUS_TYPE_UINT32))
892 wpa_s->conf->p2p_group_idle = entry.uint32_value;
896 wpa_dbus_dict_entry_clear(&entry);
899 if (wpa_s->conf->changed_parameters) {
900 /* Some changed parameters requires to update config*/
901 wpa_supplicant_update_config(wpa_s);
907 wpa_dbus_dict_entry_clear(&entry);
909 reply = wpas_dbus_error_invalid_args(message, entry.key);
910 wpa_dbus_dict_entry_clear(&entry);
914 wpa_dbus_dict_entry_clear(&entry);
915 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, NULL);
918 DBusMessage *wpas_dbus_getter_p2p_peers(DBusMessage * message,
919 struct wpa_supplicant * wpa_s)
921 DBusMessage *reply = NULL;
922 struct p2p_data *p2p = wpa_s->global->p2p;
924 int num = 0, out_of_mem = 0;
926 const struct p2p_peer_info *peer_info = NULL;
928 struct dl_list peer_objpath_list;
929 struct peer_objpath_node {
931 char path[WPAS_DBUS_OBJECT_PATH_MAX];
934 char **peer_obj_paths = NULL;
936 dl_list_init(&peer_objpath_list);
938 /* Get the first peer info */
939 peer_info = p2p_get_peer_found(p2p, NULL, next);
941 /* Get next and accumulate them */
943 while (peer_info != NULL) {
944 node = os_zalloc(sizeof(struct peer_objpath_node));
950 addr = peer_info->p2p_device_addr;
951 os_snprintf(node->path, WPAS_DBUS_OBJECT_PATH_MAX,
952 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART
954 wpa_s->dbus_new_path, MAC2STR(addr));
955 dl_list_add_tail(&peer_objpath_list, &node->list);
958 peer_info = p2p_get_peer_found(p2p, addr, next);
962 * Now construct the peer object paths in a form suitable for
963 * array_property_getter helper below.
965 peer_obj_paths = os_zalloc(num * sizeof(char *));
967 if (!peer_obj_paths) {
972 dl_list_for_each_safe(node, tmp, &peer_objpath_list,
973 struct peer_objpath_node, list)
974 peer_obj_paths[i++] = node->path;
976 reply = wpas_dbus_simple_array_property_getter(message,
977 DBUS_TYPE_OBJECT_PATH,
978 peer_obj_paths, num);
982 os_free(peer_obj_paths);
984 dl_list_for_each_safe(node, tmp, &peer_objpath_list,
985 struct peer_objpath_node, list) {
986 dl_list_del(&node->list);
990 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
997 WPAS_P2P_ROLE_DEVICE,
999 WPAS_P2P_ROLE_CLIENT,
1002 static enum wpas_p2p_role wpas_get_p2p_role(struct wpa_supplicant *wpa_s)
1004 struct wpa_ssid *ssid = wpa_s->current_ssid;
1007 return WPAS_P2P_ROLE_DEVICE;
1008 if (wpa_s->wpa_state != WPA_COMPLETED)
1009 return WPAS_P2P_ROLE_DEVICE;
1011 switch (ssid->mode) {
1012 case WPAS_MODE_P2P_GO:
1013 case WPAS_MODE_P2P_GROUP_FORMATION:
1014 return WPAS_P2P_ROLE_GO;
1015 case WPAS_MODE_INFRA:
1016 if (ssid->p2p_group)
1017 return WPAS_P2P_ROLE_CLIENT;
1018 return WPAS_P2P_ROLE_DEVICE;
1020 return WPAS_P2P_ROLE_DEVICE;
1024 DBusMessage *wpas_dbus_getter_p2p_role(DBusMessage * message,
1025 struct wpa_supplicant * wpa_s)
1029 switch (wpas_get_p2p_role(wpa_s)) {
1030 case WPAS_P2P_ROLE_GO:
1033 case WPAS_P2P_ROLE_CLIENT:
1040 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_STRING,
1044 DBusMessage *wpas_dbus_getter_p2p_group(DBusMessage * message,
1045 struct wpa_supplicant * wpa_s)
1047 if (wpa_s->dbus_groupobj_path == NULL)
1050 return wpas_dbus_simple_property_getter(message,
1051 DBUS_TYPE_OBJECT_PATH,
1052 &wpa_s->dbus_groupobj_path);
1055 DBusMessage *wpas_dbus_getter_p2p_peergo(DBusMessage * message,
1056 struct wpa_supplicant * wpa_s)
1058 char go_peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1060 if (wpas_get_p2p_role(wpa_s) != WPAS_P2P_ROLE_CLIENT)
1063 os_snprintf(go_peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1064 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
1065 wpa_s->dbus_new_path, MAC2STR(wpa_s->go_dev_addr));
1066 path = go_peer_obj_path;
1067 return wpas_dbus_simple_property_getter(message,
1068 DBUS_TYPE_OBJECT_PATH, &path);
1072 * Peer object properties accessor methods
1075 DBusMessage *wpas_dbus_getter_p2p_peer_properties(DBusMessage * message,
1076 struct peer_handler_args *
1079 DBusMessage *reply = NULL;
1080 DBusMessageIter iter, variant_iter, dict_iter;
1081 const struct p2p_peer_info *info = NULL;
1082 char devtype[WPS_DEV_TYPE_BUFSIZE];
1084 /* get the peer info */
1085 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1086 peer_args->p2p_device_addr, 0);
1090 if (message == NULL)
1091 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
1093 reply = dbus_message_new_method_return(message);
1098 dbus_message_iter_init_append(reply, &iter);
1099 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
1100 "a{sv}", &variant_iter) ||
1101 !wpa_dbus_dict_open_write(&variant_iter, &dict_iter))
1104 /* Fill out the dictionary */
1105 wps_dev_type_bin2str(info->pri_dev_type, devtype, sizeof(devtype));
1106 if (!wpa_dbus_dict_append_string(&dict_iter, "DeviceName",
1109 if (!wpa_dbus_dict_append_string(&dict_iter, "PrimaryDeviceType",
1112 if (!wpa_dbus_dict_append_uint16(&dict_iter, "config_method",
1113 info->config_methods))
1115 if (!wpa_dbus_dict_append_byte(&dict_iter, "devicecapability",
1118 if (!wpa_dbus_dict_append_byte(&dict_iter, "groupcapability",
1122 if (info->wps_sec_dev_type_list_len) {
1123 char *sec_dev_types[MAX_SEC_DEVICE_TYPES];
1124 u8 *sec_dev_type_list = NULL;
1125 char secdevtype[WPS_DEV_TYPE_BUFSIZE];
1126 int num_sec_dev_types = 0;
1129 sec_dev_type_list = os_zalloc(info->wps_sec_dev_type_list_len);
1131 if (sec_dev_type_list == NULL)
1134 os_memcpy(sec_dev_type_list, info->wps_sec_dev_type_list,
1135 info->wps_sec_dev_type_list_len);
1137 for (i = 0; i < MAX_SEC_DEVICE_TYPES &&
1138 i < (int) (info->wps_sec_dev_type_list_len /
1141 sec_dev_types[i] = os_zalloc(sizeof(secdevtype));
1143 if (!sec_dev_types[i] ||
1144 wps_dev_type_bin2str(
1145 &sec_dev_type_list[i *
1148 sizeof(secdevtype)) == NULL) {
1150 os_free(sec_dev_types[i]);
1151 os_free(sec_dev_type_list);
1155 num_sec_dev_types++;
1158 os_free(sec_dev_type_list);
1160 if (num_sec_dev_types) {
1161 if (!wpa_dbus_dict_append_string_array(&dict_iter,
1162 "SecondaryDeviceTypes",
1163 (const char **)sec_dev_types,
1164 num_sec_dev_types)) {
1165 for (i = 0; i < num_sec_dev_types; i++)
1166 os_free(sec_dev_types[i]);
1170 for (i = 0; i < num_sec_dev_types; i++)
1171 os_free(sec_dev_types[i]);
1176 /* Add WPS vendor extensions attribute */
1177 const struct wpabuf *vendor_extension[P2P_MAX_WPS_VENDOR_EXT];
1180 for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
1181 if (info->wps_vendor_ext[i] == NULL)
1183 vendor_extension[num] = info->wps_vendor_ext[i];
1187 if (!wpa_dbus_dict_append_wpabuf_array(
1188 &dict_iter, "VendorExtension",
1189 vendor_extension, num))
1193 if (!wpa_dbus_dict_close_write(&variant_iter, &dict_iter) ||
1194 !dbus_message_iter_close_container(&iter, &variant_iter))
1199 dbus_message_unref(reply);
1200 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, NULL);
1203 DBusMessage *wpas_dbus_getter_p2p_peer_ies(DBusMessage * message,
1204 struct peer_handler_args * peer_args)
1211 * Group object properties accessor methods
1214 DBusMessage *wpas_dbus_getter_p2p_group_members(DBusMessage * message,
1215 struct wpa_supplicant * wpa_s)
1217 DBusMessage *reply = NULL;
1218 struct wpa_ssid *ssid;
1219 unsigned int num_members;
1225 /* Ensure we are a GO */
1226 if (wpa_s->wpa_state != WPA_COMPLETED)
1229 ssid = wpa_s->conf->ssid;
1230 /* At present WPAS P2P_GO mode only applicable for p2p_go */
1231 if (ssid->mode != WPAS_MODE_P2P_GO &&
1232 ssid->mode != WPAS_MODE_AP &&
1233 ssid->mode != WPAS_MODE_P2P_GROUP_FORMATION)
1236 num_members = p2p_get_group_num_members(wpa_s->p2p_group);
1238 paths = os_zalloc(num_members * sizeof(char *));
1243 while ((addr = p2p_iterate_group_members(wpa_s->p2p_group, &next))) {
1244 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1247 os_snprintf(paths[i], WPAS_DBUS_OBJECT_PATH_MAX,
1248 "%s/" WPAS_DBUS_NEW_P2P_GROUPMEMBERS_PART
1250 wpa_s->dbus_groupobj_path, MAC2STR(addr));
1254 reply = wpas_dbus_simple_array_property_getter(message,
1255 DBUS_TYPE_OBJECT_PATH,
1256 paths, num_members);
1259 for (i = 0; i < num_members; i++)
1265 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, NULL);
1270 DBusMessage *wpas_dbus_getter_p2p_group_properties(
1271 DBusMessage *message,
1272 struct wpa_supplicant *wpa_s)
1274 DBusMessage *reply = NULL;
1275 DBusMessageIter iter, variant_iter, dict_iter;
1276 struct hostapd_data *hapd = wpa_s->ap_iface->bss[0];
1277 const struct wpabuf *vendor_ext[MAX_WPS_VENDOR_EXTENSIONS];
1278 int num_vendor_ext = 0;
1282 reply = dbus_message_new_error(message, DBUS_ERROR_FAILED,
1287 if (message == NULL)
1288 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
1290 reply = dbus_message_new_method_return(message);
1295 dbus_message_iter_init_append(reply, &iter);
1297 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
1298 "a{sv}", &variant_iter) ||
1299 !wpa_dbus_dict_open_write(&variant_iter, &dict_iter))
1302 /* Parse WPS Vendor Extensions sent in Beacon/Probe Response */
1303 for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
1304 if (hapd->conf->wps_vendor_ext[i] == NULL)
1306 vendor_ext[num_vendor_ext++] = hapd->conf->wps_vendor_ext[i];
1309 if (!wpa_dbus_dict_append_wpabuf_array(&dict_iter,
1310 "WPSVendorExtensions",
1311 vendor_ext, num_vendor_ext))
1314 if (!wpa_dbus_dict_close_write(&variant_iter, &dict_iter) ||
1315 !dbus_message_iter_close_container(&iter, &variant_iter))
1321 dbus_message_unref(reply);
1322 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, NULL);
1325 DBusMessage *wpas_dbus_setter_p2p_group_properties(
1326 DBusMessage *message,
1327 struct wpa_supplicant *wpa_s)
1329 DBusMessage *reply = NULL;
1330 DBusMessageIter iter, variant_iter;
1331 struct wpa_dbus_dict_entry entry = {.type = DBUS_TYPE_STRING };
1332 DBusMessageIter iter_dict;
1335 struct hostapd_data *hapd = wpa_s->ap_iface->bss[0];
1340 dbus_message_iter_init(message, &iter);
1342 dbus_message_iter_next(&iter);
1343 dbus_message_iter_next(&iter);
1345 dbus_message_iter_recurse(&iter, &variant_iter);
1347 if (!wpa_dbus_dict_open_read(&variant_iter, &iter_dict))
1348 return wpas_dbus_error_invalid_args(message, NULL);
1350 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
1351 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) {
1352 reply = wpas_dbus_error_invalid_args(message, NULL);
1356 if (os_strcmp(entry.key, "WPSVendorExtensions") == 0) {
1357 if (entry.type != DBUS_TYPE_ARRAY ||
1358 entry.array_type != WPAS_DBUS_TYPE_BINARRAY ||
1359 entry.array_len > MAX_WPS_VENDOR_EXTENSIONS)
1362 for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
1363 if (i < entry.array_len) {
1364 hapd->conf->wps_vendor_ext[i] =
1365 entry.binarray_value[i];
1366 entry.binarray_value[i] = NULL;
1368 hapd->conf->wps_vendor_ext[i] = NULL;
1371 hostapd_update_wps(hapd);
1375 wpa_dbus_dict_entry_clear(&entry);
1381 reply = wpas_dbus_error_invalid_args(message, entry.key);
1382 wpa_dbus_dict_entry_clear(&entry);
1387 DBusMessage *wpas_dbus_handler_p2p_add_service(DBusMessage * message,
1388 struct wpa_supplicant * wpa_s)
1390 DBusMessageIter iter_dict;
1391 DBusMessage *reply = NULL;
1392 DBusMessageIter iter;
1393 struct wpa_dbus_dict_entry entry;
1396 char *service = NULL;
1397 struct wpabuf *query = NULL;
1398 struct wpabuf *resp = NULL;
1401 dbus_message_iter_init(message, &iter);
1403 if (!wpa_dbus_dict_open_read(&iter, &iter_dict))
1406 if (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
1407 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
1410 if (!strcmp(entry.key, "service_type") &&
1411 (entry.type == DBUS_TYPE_STRING)) {
1412 if (!strcmp(entry.str_value, "upnp"))
1414 else if (!strcmp(entry.str_value, "bonjour"))
1418 wpa_dbus_dict_entry_clear(&entry);
1423 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
1424 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
1427 if (!strcmp(entry.key, "version") &&
1428 entry.type == DBUS_TYPE_INT32)
1429 version = entry.uint32_value;
1430 else if (!strcmp(entry.key, "service") &&
1431 entry.type == DBUS_TYPE_STRING)
1432 service = os_strdup(entry.str_value);
1433 wpa_dbus_dict_entry_clear(&entry);
1435 if (version <= 0 || service == NULL)
1438 if (wpas_p2p_service_add_upnp(wpa_s, version, service) != 0)
1442 } else if (bonjour == 1) {
1443 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
1444 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
1447 if (!strcmp(entry.key, "query")) {
1448 if ((entry.type != DBUS_TYPE_ARRAY) ||
1449 (entry.array_type != DBUS_TYPE_BYTE))
1451 query = wpabuf_alloc_copy(entry.bytearray_value,
1453 } else if (!strcmp(entry.key, "response")) {
1454 if ((entry.type != DBUS_TYPE_ARRAY) ||
1455 (entry.array_type != DBUS_TYPE_BYTE))
1457 resp = wpabuf_alloc_copy(entry.bytearray_value,
1461 wpa_dbus_dict_entry_clear(&entry);
1464 if (query == NULL || resp == NULL)
1467 if (wpas_p2p_service_add_bonjour(wpa_s, query, resp) < 0) {
1477 wpa_dbus_dict_entry_clear(&entry);
1479 return wpas_dbus_error_invalid_args(message, NULL);
1482 DBusMessage *wpas_dbus_handler_p2p_delete_service(DBusMessage * message,
1483 struct wpa_supplicant * wpa_s)
1485 DBusMessageIter iter_dict;
1486 DBusMessage *reply = NULL;
1487 DBusMessageIter iter;
1488 struct wpa_dbus_dict_entry entry;
1492 char *service = NULL;
1493 struct wpabuf *query = NULL;
1496 dbus_message_iter_init(message, &iter);
1498 if (!wpa_dbus_dict_open_read(&iter, &iter_dict))
1501 if (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
1502 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
1505 if (!strcmp(entry.key, "service_type") &&
1506 (entry.type == DBUS_TYPE_STRING)) {
1507 if (!strcmp(entry.str_value, "upnp"))
1509 else if (!strcmp(entry.str_value, "bonjour"))
1513 wpa_dbus_dict_entry_clear(&entry);
1517 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
1518 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
1520 if (!strcmp(entry.key, "version") &&
1521 entry.type == DBUS_TYPE_INT32)
1522 version = entry.uint32_value;
1523 else if (!strcmp(entry.key, "service") &&
1524 entry.type == DBUS_TYPE_STRING)
1525 service = os_strdup(entry.str_value);
1529 wpa_dbus_dict_entry_clear(&entry);
1532 if (version <= 0 || service == NULL)
1535 ret = wpas_p2p_service_del_upnp(wpa_s, version, service);
1539 } else if (bonjour == 1) {
1540 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
1541 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
1544 if (!strcmp(entry.key, "query")) {
1545 if ((entry.type != DBUS_TYPE_ARRAY) ||
1546 (entry.array_type != DBUS_TYPE_BYTE))
1548 query = wpabuf_alloc_copy(entry.bytearray_value,
1553 wpa_dbus_dict_entry_clear(&entry);
1559 ret = wpas_p2p_service_del_bonjour(wpa_s, query);
1568 wpa_dbus_dict_entry_clear(&entry);
1570 return wpas_dbus_error_invalid_args(message, NULL);
1573 DBusMessage *wpas_dbus_handler_p2p_flush_service(DBusMessage * message,
1574 struct wpa_supplicant * wpa_s)
1576 wpas_p2p_service_flush(wpa_s);
1580 DBusMessage *wpas_dbus_handler_p2p_service_sd_req(DBusMessage * message,
1581 struct wpa_supplicant * wpa_s)
1583 DBusMessageIter iter_dict;
1584 DBusMessage *reply = NULL;
1585 DBusMessageIter iter;
1586 struct wpa_dbus_dict_entry entry;
1588 char *service = NULL;
1589 char *peer_object_path = NULL;
1590 struct wpabuf *tlv = NULL;
1595 dbus_message_iter_init(message, &iter);
1597 if (!wpa_dbus_dict_open_read(&iter, &iter_dict))
1600 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
1601 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
1603 if (!strcmp(entry.key, "peer_object") &&
1604 entry.type == DBUS_TYPE_OBJECT_PATH) {
1605 peer_object_path = os_strdup(entry.str_value);
1606 } else if (!strcmp(entry.key, "service_type") &&
1607 entry.type == DBUS_TYPE_STRING) {
1608 if (!strcmp(entry.str_value, "upnp"))
1612 } else if (!strcmp(entry.key, "version") &&
1613 entry.type == DBUS_TYPE_INT32) {
1614 version = entry.uint32_value;
1615 } else if (!strcmp(entry.key, "service") &&
1616 entry.type == DBUS_TYPE_STRING) {
1617 service = os_strdup(entry.str_value);
1618 } else if (!strcmp(entry.key, "tlv")) {
1619 if (entry.type != DBUS_TYPE_ARRAY ||
1620 entry.array_type != DBUS_TYPE_BYTE)
1622 tlv = wpabuf_alloc_copy(entry.bytearray_value,
1627 wpa_dbus_dict_entry_clear(&entry);
1630 if (!peer_object_path ||
1631 (parse_peer_object_path(peer_object_path, addr) < 0) ||
1632 (p2p_get_peer_info(wpa_s->global->p2p, addr, 0, NULL, 0) < 0))
1636 if (version <= 0 || service == NULL)
1639 ref = (unsigned long)wpas_p2p_sd_request_upnp(wpa_s, addr,
1644 ref = (unsigned long)wpas_p2p_sd_request(wpa_s, addr, tlv);
1649 reply = dbus_message_new_method_return(message);
1650 dbus_message_append_args(reply, DBUS_TYPE_UINT64,
1651 &ref, DBUS_TYPE_INVALID);
1653 reply = wpas_dbus_error_unknown_error(message,
1654 "Unable to send SD request");
1658 os_free(peer_object_path);
1661 wpa_dbus_dict_entry_clear(&entry);
1665 reply = wpas_dbus_error_invalid_args(message, NULL);
1669 DBusMessage *wpas_dbus_handler_p2p_service_sd_res(
1670 DBusMessage *message, struct wpa_supplicant *wpa_s)
1672 DBusMessageIter iter_dict;
1673 DBusMessage *reply = NULL;
1674 DBusMessageIter iter;
1675 struct wpa_dbus_dict_entry entry;
1676 char *peer_object_path = NULL;
1677 struct wpabuf *tlv = NULL;
1682 dbus_message_iter_init(message, &iter);
1684 if (!wpa_dbus_dict_open_read(&iter, &iter_dict))
1687 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
1688 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
1691 if (!strcmp(entry.key, "peer_object") &&
1692 entry.type == DBUS_TYPE_OBJECT_PATH) {
1693 peer_object_path = os_strdup(entry.str_value);
1694 } else if (!strcmp(entry.key, "frequency") &&
1695 entry.type == DBUS_TYPE_INT32) {
1696 freq = entry.uint32_value;
1697 } else if (!strcmp(entry.key, "dialog_token") &&
1698 entry.type == DBUS_TYPE_UINT32) {
1699 dlg_tok = entry.uint32_value;
1700 } else if (!strcmp(entry.key, "tlvs")) {
1701 if (entry.type != DBUS_TYPE_ARRAY ||
1702 entry.array_type != DBUS_TYPE_BYTE)
1704 tlv = wpabuf_alloc_copy(entry.bytearray_value,
1709 wpa_dbus_dict_entry_clear(&entry);
1711 if (!peer_object_path ||
1712 (parse_peer_object_path(peer_object_path, addr) < 0) ||
1713 (p2p_get_peer_info(wpa_s->global->p2p, addr, 0, NULL, 0) < 0))
1719 wpas_p2p_sd_response(wpa_s, freq, addr, (u8) dlg_tok, tlv);
1722 os_free(peer_object_path);
1725 wpa_dbus_dict_entry_clear(&entry);
1727 reply = wpas_dbus_error_invalid_args(message, NULL);
1731 DBusMessage *wpas_dbus_handler_p2p_service_sd_cancel_req(DBusMessage * message, struct wpa_supplicant
1734 DBusMessageIter iter;
1737 dbus_message_iter_init(message, &iter);
1738 dbus_message_iter_get_basic(&iter, &req);
1743 if (!wpas_p2p_sd_cancel_request(wpa_s, (void *)(unsigned long)req))
1748 return wpas_dbus_error_invalid_args(message, NULL);
1751 DBusMessage *wpas_dbus_handler_p2p_service_update(DBusMessage * message,
1752 struct wpa_supplicant * wpa_s)
1754 wpas_p2p_sd_service_update(wpa_s);
1758 DBusMessage *wpas_dbus_handler_p2p_serv_disc_external(DBusMessage * message,
1759 struct wpa_supplicant *
1762 DBusMessageIter iter;
1765 dbus_message_iter_init(message, &iter);
1766 dbus_message_iter_get_basic(&iter, &ext);
1768 wpa_s->p2p_sd_over_ctrl_iface = ext;