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 /* Dissasociation low ack */
752 if (!wpa_dbus_dict_append_uint32(&dict_iter, "disassoc_low_ack",
753 wpa_s->conf->disassoc_low_ack))
756 if (!wpa_dbus_dict_close_write(&variant_iter, &dict_iter) ||
757 !dbus_message_iter_close_container(&iter, &variant_iter))
762 dbus_message_unref(reply);
763 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, NULL);
766 DBusMessage *wpas_dbus_setter_p2p_device_properties(DBusMessage * message,
767 struct wpa_supplicant *
770 DBusMessage *reply = NULL;
771 DBusMessageIter iter, variant_iter;
772 struct wpa_dbus_dict_entry entry = {.type = DBUS_TYPE_STRING };
773 DBusMessageIter iter_dict;
776 dbus_message_iter_init(message, &iter);
778 dbus_message_iter_next(&iter);
779 dbus_message_iter_next(&iter);
781 dbus_message_iter_recurse(&iter, &variant_iter);
783 if (!wpa_dbus_dict_open_read(&variant_iter, &iter_dict))
784 return wpas_dbus_error_invalid_args(message, NULL);
786 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
787 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
788 return wpas_dbus_error_invalid_args(message, NULL);
790 if (os_strcmp(entry.key, "DeviceName") == 0) {
793 if (entry.type != DBUS_TYPE_STRING)
796 devname = os_strdup(entry.str_value);
798 goto err_no_mem_clear;
800 os_free(wpa_s->conf->device_name);
801 wpa_s->conf->device_name = devname;
803 wpa_s->conf->changed_parameters |=
804 CFG_CHANGED_DEVICE_NAME;
805 } else if (os_strcmp(entry.key, "PrimaryDeviceType") == 0) {
806 if (entry.type != DBUS_TYPE_ARRAY ||
807 entry.array_type != DBUS_TYPE_BYTE ||
808 entry.array_len != WPS_DEV_TYPE_LEN)
811 os_memcpy(wpa_s->conf->device_type,
812 entry.bytearray_value,
814 wpa_s->conf->changed_parameters |=
815 CFG_CHANGED_DEVICE_TYPE;
816 } else if (os_strcmp(entry.key, "SecondaryDeviceTypes") == 0) {
817 if (entry.type != DBUS_TYPE_ARRAY ||
818 entry.array_type != WPAS_DBUS_TYPE_BINARRAY ||
819 entry.array_len > MAX_SEC_DEVICE_TYPES)
822 for (i = 0; i < entry.array_len; i++)
823 if (wpabuf_len(entry.binarray_value[i]) != WPS_DEV_TYPE_LEN)
824 goto err_no_mem_clear;
825 for (i = 0; i < entry.array_len; i++)
826 os_memcpy(wpa_s->conf->sec_device_type[i],
827 wpabuf_head(entry.binarray_value[i]),
829 wpa_s->conf->num_sec_device_types = entry.array_len;
830 wpa_s->conf->changed_parameters |=
831 CFG_CHANGED_SEC_DEVICE_TYPE;
832 } else if (os_strcmp(entry.key, "VendorExtension") == 0) {
833 if ((entry.type != DBUS_TYPE_ARRAY) ||
834 (entry.array_type != WPAS_DBUS_TYPE_BINARRAY) ||
835 (entry.array_len > P2P_MAX_WPS_VENDOR_EXT))
838 wpa_s->conf->changed_parameters |=
839 CFG_CHANGED_VENDOR_EXTENSION;
841 for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
842 wpabuf_free(wpa_s->conf->wps_vendor_ext[i]);
843 if (i < entry.array_len) {
844 wpa_s->conf->wps_vendor_ext[i] =
845 entry.binarray_value[i];
846 entry.binarray_value[i] = NULL;
848 wpa_s->conf->wps_vendor_ext[i] = NULL;
850 } else if ((os_strcmp(entry.key, "GOIntent") == 0) &&
851 (entry.type == DBUS_TYPE_UINT32) &&
852 (entry.uint32_value <= 15))
853 wpa_s->conf->p2p_go_intent = entry.uint32_value;
855 else if ((os_strcmp(entry.key, "PersistantReconnect") == 0) &&
856 (entry.type == DBUS_TYPE_BOOLEAN))
857 wpa_s->conf->persistent_reconnect = entry.bool_value;
859 else if ((os_strcmp(entry.key, "ListenRegClass") == 0) &&
860 (entry.type == DBUS_TYPE_UINT32))
861 wpa_s->conf->p2p_listen_reg_class = entry.uint32_value;
863 else if ((os_strcmp(entry.key, "ListenChannel") == 0) &&
864 (entry.type == DBUS_TYPE_UINT32))
865 wpa_s->conf->p2p_listen_channel = entry.uint32_value;
867 else if ((os_strcmp(entry.key, "OperRegClass") == 0) &&
868 (entry.type == DBUS_TYPE_UINT32))
869 wpa_s->conf->p2p_oper_reg_class = entry.uint32_value;
871 else if ((os_strcmp(entry.key, "OperChannel") == 0) &&
872 (entry.type == DBUS_TYPE_UINT32))
873 wpa_s->conf->p2p_oper_channel = entry.uint32_value;
875 else if (os_strcmp(entry.key, "SsidPostfix") == 0) {
878 if (entry.type != DBUS_TYPE_STRING)
881 postfix = os_strdup(entry.str_value);
883 goto err_no_mem_clear;
885 os_free(wpa_s->conf->p2p_ssid_postfix);
886 wpa_s->conf->p2p_ssid_postfix = postfix;
888 wpa_s->conf->changed_parameters |=
889 CFG_CHANGED_P2P_SSID_POSTFIX;
890 } else if ((os_strcmp(entry.key, "IntraBss") == 0) &&
891 (entry.type == DBUS_TYPE_BOOLEAN)) {
892 wpa_s->conf->p2p_intra_bss = entry.bool_value;
893 wpa_s->conf->changed_parameters |=
894 CFG_CHANGED_P2P_INTRA_BSS;
895 } else if ((os_strcmp(entry.key, "GroupIdle") == 0) &&
896 (entry.type == DBUS_TYPE_UINT32))
897 wpa_s->conf->p2p_group_idle = entry.uint32_value;
898 else if (os_strcmp(entry.key, "disassoc_low_ack") == 0 &&
899 entry.type == DBUS_TYPE_UINT32)
900 wpa_s->conf->disassoc_low_ack = entry.uint32_value;
904 wpa_dbus_dict_entry_clear(&entry);
907 if (wpa_s->conf->changed_parameters) {
908 /* Some changed parameters requires to update config*/
909 wpa_supplicant_update_config(wpa_s);
915 wpa_dbus_dict_entry_clear(&entry);
917 reply = wpas_dbus_error_invalid_args(message, entry.key);
918 wpa_dbus_dict_entry_clear(&entry);
922 wpa_dbus_dict_entry_clear(&entry);
923 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, NULL);
926 DBusMessage *wpas_dbus_getter_p2p_peers(DBusMessage * message,
927 struct wpa_supplicant * wpa_s)
929 DBusMessage *reply = NULL;
930 struct p2p_data *p2p = wpa_s->global->p2p;
932 int num = 0, out_of_mem = 0;
934 const struct p2p_peer_info *peer_info = NULL;
936 struct dl_list peer_objpath_list;
937 struct peer_objpath_node {
939 char path[WPAS_DBUS_OBJECT_PATH_MAX];
942 char **peer_obj_paths = NULL;
944 dl_list_init(&peer_objpath_list);
946 /* Get the first peer info */
947 peer_info = p2p_get_peer_found(p2p, NULL, next);
949 /* Get next and accumulate them */
951 while (peer_info != NULL) {
952 node = os_zalloc(sizeof(struct peer_objpath_node));
958 addr = peer_info->p2p_device_addr;
959 os_snprintf(node->path, WPAS_DBUS_OBJECT_PATH_MAX,
960 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART
962 wpa_s->dbus_new_path, MAC2STR(addr));
963 dl_list_add_tail(&peer_objpath_list, &node->list);
966 peer_info = p2p_get_peer_found(p2p, addr, next);
970 * Now construct the peer object paths in a form suitable for
971 * array_property_getter helper below.
973 peer_obj_paths = os_zalloc(num * sizeof(char *));
975 if (!peer_obj_paths) {
980 dl_list_for_each_safe(node, tmp, &peer_objpath_list,
981 struct peer_objpath_node, list)
982 peer_obj_paths[i++] = node->path;
984 reply = wpas_dbus_simple_array_property_getter(message,
985 DBUS_TYPE_OBJECT_PATH,
986 peer_obj_paths, num);
990 os_free(peer_obj_paths);
992 dl_list_for_each_safe(node, tmp, &peer_objpath_list,
993 struct peer_objpath_node, list) {
994 dl_list_del(&node->list);
998 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1004 enum wpas_p2p_role {
1005 WPAS_P2P_ROLE_DEVICE,
1007 WPAS_P2P_ROLE_CLIENT,
1010 static enum wpas_p2p_role wpas_get_p2p_role(struct wpa_supplicant *wpa_s)
1012 struct wpa_ssid *ssid = wpa_s->current_ssid;
1015 return WPAS_P2P_ROLE_DEVICE;
1016 if (wpa_s->wpa_state != WPA_COMPLETED)
1017 return WPAS_P2P_ROLE_DEVICE;
1019 switch (ssid->mode) {
1020 case WPAS_MODE_P2P_GO:
1021 case WPAS_MODE_P2P_GROUP_FORMATION:
1022 return WPAS_P2P_ROLE_GO;
1023 case WPAS_MODE_INFRA:
1024 if (ssid->p2p_group)
1025 return WPAS_P2P_ROLE_CLIENT;
1026 return WPAS_P2P_ROLE_DEVICE;
1028 return WPAS_P2P_ROLE_DEVICE;
1032 DBusMessage *wpas_dbus_getter_p2p_role(DBusMessage * message,
1033 struct wpa_supplicant * wpa_s)
1037 switch (wpas_get_p2p_role(wpa_s)) {
1038 case WPAS_P2P_ROLE_GO:
1041 case WPAS_P2P_ROLE_CLIENT:
1048 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_STRING,
1052 DBusMessage *wpas_dbus_getter_p2p_group(DBusMessage * message,
1053 struct wpa_supplicant * wpa_s)
1055 if (wpa_s->dbus_groupobj_path == NULL)
1058 return wpas_dbus_simple_property_getter(message,
1059 DBUS_TYPE_OBJECT_PATH,
1060 &wpa_s->dbus_groupobj_path);
1063 DBusMessage *wpas_dbus_getter_p2p_peergo(DBusMessage * message,
1064 struct wpa_supplicant * wpa_s)
1066 char go_peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1068 if (wpas_get_p2p_role(wpa_s) != WPAS_P2P_ROLE_CLIENT)
1071 os_snprintf(go_peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1072 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
1073 wpa_s->dbus_new_path, MAC2STR(wpa_s->go_dev_addr));
1074 path = go_peer_obj_path;
1075 return wpas_dbus_simple_property_getter(message,
1076 DBUS_TYPE_OBJECT_PATH, &path);
1080 * Peer object properties accessor methods
1083 DBusMessage *wpas_dbus_getter_p2p_peer_properties(DBusMessage * message,
1084 struct peer_handler_args *
1087 DBusMessage *reply = NULL;
1088 DBusMessageIter iter, variant_iter, dict_iter;
1089 const struct p2p_peer_info *info = NULL;
1090 char devtype[WPS_DEV_TYPE_BUFSIZE];
1092 /* get the peer info */
1093 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1094 peer_args->p2p_device_addr, 0);
1098 if (message == NULL)
1099 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
1101 reply = dbus_message_new_method_return(message);
1106 dbus_message_iter_init_append(reply, &iter);
1107 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
1108 "a{sv}", &variant_iter) ||
1109 !wpa_dbus_dict_open_write(&variant_iter, &dict_iter))
1112 /* Fill out the dictionary */
1113 wps_dev_type_bin2str(info->pri_dev_type, devtype, sizeof(devtype));
1114 if (!wpa_dbus_dict_append_string(&dict_iter, "DeviceName",
1117 if (!wpa_dbus_dict_append_string(&dict_iter, "PrimaryDeviceType",
1120 if (!wpa_dbus_dict_append_uint16(&dict_iter, "config_method",
1121 info->config_methods))
1123 if (!wpa_dbus_dict_append_int32(&dict_iter, "level",
1126 if (!wpa_dbus_dict_append_byte(&dict_iter, "devicecapability",
1129 if (!wpa_dbus_dict_append_byte(&dict_iter, "groupcapability",
1133 if (info->wps_sec_dev_type_list_len) {
1134 char *sec_dev_types[MAX_SEC_DEVICE_TYPES];
1135 u8 *sec_dev_type_list = NULL;
1136 char secdevtype[WPS_DEV_TYPE_BUFSIZE];
1137 int num_sec_dev_types = 0;
1140 sec_dev_type_list = os_zalloc(info->wps_sec_dev_type_list_len);
1142 if (sec_dev_type_list == NULL)
1145 os_memcpy(sec_dev_type_list, info->wps_sec_dev_type_list,
1146 info->wps_sec_dev_type_list_len);
1148 for (i = 0; i < MAX_SEC_DEVICE_TYPES &&
1149 i < (int) (info->wps_sec_dev_type_list_len /
1152 sec_dev_types[i] = os_zalloc(sizeof(secdevtype));
1154 if (!sec_dev_types[i] ||
1155 wps_dev_type_bin2str(
1156 &sec_dev_type_list[i *
1159 sizeof(secdevtype)) == NULL) {
1161 os_free(sec_dev_types[i]);
1162 os_free(sec_dev_type_list);
1166 num_sec_dev_types++;
1169 os_free(sec_dev_type_list);
1171 if (num_sec_dev_types) {
1172 if (!wpa_dbus_dict_append_string_array(&dict_iter,
1173 "SecondaryDeviceTypes",
1174 (const char **)sec_dev_types,
1175 num_sec_dev_types)) {
1176 for (i = 0; i < num_sec_dev_types; i++)
1177 os_free(sec_dev_types[i]);
1181 for (i = 0; i < num_sec_dev_types; i++)
1182 os_free(sec_dev_types[i]);
1187 /* Add WPS vendor extensions attribute */
1188 const struct wpabuf *vendor_extension[P2P_MAX_WPS_VENDOR_EXT];
1191 for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
1192 if (info->wps_vendor_ext[i] == NULL)
1194 vendor_extension[num] = info->wps_vendor_ext[i];
1198 if (!wpa_dbus_dict_append_wpabuf_array(
1199 &dict_iter, "VendorExtension",
1200 vendor_extension, num))
1204 if (!wpa_dbus_dict_close_write(&variant_iter, &dict_iter) ||
1205 !dbus_message_iter_close_container(&iter, &variant_iter))
1210 dbus_message_unref(reply);
1211 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, NULL);
1214 DBusMessage *wpas_dbus_getter_p2p_peer_ies(DBusMessage * message,
1215 struct peer_handler_args * peer_args)
1222 * wpas_dbus_getter_persistent_groups - Get array of peristent group objects
1223 * @message: Pointer to incoming dbus message
1224 * @wpa_s: wpa_supplicant structure for a network interface
1225 * Returns: a dbus message containing an array of all persistent group
1226 * dbus object paths.
1228 * Getter for "Networks" property.
1230 DBusMessage * wpas_dbus_getter_persistent_groups(DBusMessage *message,
1231 struct wpa_supplicant *wpa_s)
1233 DBusMessage *reply = NULL;
1234 struct wpa_ssid *ssid;
1236 unsigned int i = 0, num = 0;
1238 if (wpa_s->conf == NULL) {
1239 wpa_printf(MSG_ERROR, "dbus: "
1240 "wpas_dbus_getter_persistent_groups: "
1241 "An error occurred getting persistent groups list");
1242 return wpas_dbus_error_unknown_error(message, NULL);
1245 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
1246 if (network_is_persistent_group(ssid))
1249 paths = os_zalloc(num * sizeof(char *));
1251 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1255 /* Loop through configured networks and append object path of each */
1256 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1257 if (!network_is_persistent_group(ssid))
1259 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1260 if (paths[i] == NULL) {
1261 reply = dbus_message_new_error(message,
1262 DBUS_ERROR_NO_MEMORY,
1266 /* Construct the object path for this network. */
1267 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
1268 "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%d",
1269 wpa_s->dbus_new_path, ssid->id);
1272 reply = wpas_dbus_simple_array_property_getter(message,
1273 DBUS_TYPE_OBJECT_PATH,
1278 os_free(paths[--i]);
1285 * wpas_dbus_getter_persistent_group_properties - Get options for a persistent
1287 * @message: Pointer to incoming dbus message
1288 * @net: wpa_supplicant structure for a network interface and
1289 * wpa_ssid structure for a configured persistent group (internally network)
1290 * Returns: DBus message with network properties or DBus error on failure
1292 * Getter for "Properties" property of a persistent group.
1294 DBusMessage * wpas_dbus_getter_persistent_group_properties(
1295 DBusMessage *message, struct network_handler_args *net)
1298 * Leveraging the fact that persistent group object is still
1299 * represented in same manner as network within.
1301 return wpas_dbus_getter_network_properties(message, net);
1306 * Group object properties accessor methods
1309 DBusMessage *wpas_dbus_getter_p2p_group_members(DBusMessage * message,
1310 struct wpa_supplicant * wpa_s)
1312 DBusMessage *reply = NULL;
1313 struct wpa_ssid *ssid;
1314 unsigned int num_members;
1320 /* Ensure we are a GO */
1321 if (wpa_s->wpa_state != WPA_COMPLETED)
1324 ssid = wpa_s->conf->ssid;
1325 /* At present WPAS P2P_GO mode only applicable for p2p_go */
1326 if (ssid->mode != WPAS_MODE_P2P_GO &&
1327 ssid->mode != WPAS_MODE_AP &&
1328 ssid->mode != WPAS_MODE_P2P_GROUP_FORMATION)
1331 num_members = p2p_get_group_num_members(wpa_s->p2p_group);
1333 paths = os_zalloc(num_members * sizeof(char *));
1338 while ((addr = p2p_iterate_group_members(wpa_s->p2p_group, &next))) {
1339 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1342 os_snprintf(paths[i], WPAS_DBUS_OBJECT_PATH_MAX,
1343 "%s/" WPAS_DBUS_NEW_P2P_GROUPMEMBERS_PART
1345 wpa_s->dbus_groupobj_path, MAC2STR(addr));
1349 reply = wpas_dbus_simple_array_property_getter(message,
1350 DBUS_TYPE_OBJECT_PATH,
1351 paths, num_members);
1354 for (i = 0; i < num_members; i++)
1360 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, NULL);
1365 DBusMessage *wpas_dbus_getter_p2p_group_properties(
1366 DBusMessage *message,
1367 struct wpa_supplicant *wpa_s)
1369 DBusMessage *reply = NULL;
1370 DBusMessageIter iter, variant_iter, dict_iter;
1371 struct hostapd_data *hapd = wpa_s->ap_iface->bss[0];
1372 const struct wpabuf *vendor_ext[MAX_WPS_VENDOR_EXTENSIONS];
1373 int num_vendor_ext = 0;
1377 reply = dbus_message_new_error(message, DBUS_ERROR_FAILED,
1382 if (message == NULL)
1383 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
1385 reply = dbus_message_new_method_return(message);
1390 dbus_message_iter_init_append(reply, &iter);
1392 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
1393 "a{sv}", &variant_iter) ||
1394 !wpa_dbus_dict_open_write(&variant_iter, &dict_iter))
1397 /* Parse WPS Vendor Extensions sent in Beacon/Probe Response */
1398 for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
1399 if (hapd->conf->wps_vendor_ext[i] == NULL)
1401 vendor_ext[num_vendor_ext++] = hapd->conf->wps_vendor_ext[i];
1404 if (!wpa_dbus_dict_append_wpabuf_array(&dict_iter,
1405 "WPSVendorExtensions",
1406 vendor_ext, num_vendor_ext))
1409 if (!wpa_dbus_dict_close_write(&variant_iter, &dict_iter) ||
1410 !dbus_message_iter_close_container(&iter, &variant_iter))
1416 dbus_message_unref(reply);
1417 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, NULL);
1420 DBusMessage *wpas_dbus_setter_p2p_group_properties(
1421 DBusMessage *message,
1422 struct wpa_supplicant *wpa_s)
1424 DBusMessage *reply = NULL;
1425 DBusMessageIter iter, variant_iter;
1426 struct wpa_dbus_dict_entry entry = {.type = DBUS_TYPE_STRING };
1427 DBusMessageIter iter_dict;
1430 struct hostapd_data *hapd = wpa_s->ap_iface->bss[0];
1435 dbus_message_iter_init(message, &iter);
1437 dbus_message_iter_next(&iter);
1438 dbus_message_iter_next(&iter);
1440 dbus_message_iter_recurse(&iter, &variant_iter);
1442 if (!wpa_dbus_dict_open_read(&variant_iter, &iter_dict))
1443 return wpas_dbus_error_invalid_args(message, NULL);
1445 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
1446 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) {
1447 reply = wpas_dbus_error_invalid_args(message, NULL);
1451 if (os_strcmp(entry.key, "WPSVendorExtensions") == 0) {
1452 if (entry.type != DBUS_TYPE_ARRAY ||
1453 entry.array_type != WPAS_DBUS_TYPE_BINARRAY ||
1454 entry.array_len > MAX_WPS_VENDOR_EXTENSIONS)
1457 for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
1458 if (i < entry.array_len) {
1459 hapd->conf->wps_vendor_ext[i] =
1460 entry.binarray_value[i];
1461 entry.binarray_value[i] = NULL;
1463 hapd->conf->wps_vendor_ext[i] = NULL;
1466 hostapd_update_wps(hapd);
1470 wpa_dbus_dict_entry_clear(&entry);
1476 reply = wpas_dbus_error_invalid_args(message, entry.key);
1477 wpa_dbus_dict_entry_clear(&entry);
1482 DBusMessage *wpas_dbus_handler_p2p_add_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;
1491 char *service = NULL;
1492 struct wpabuf *query = NULL;
1493 struct wpabuf *resp = 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);
1518 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
1519 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
1522 if (!strcmp(entry.key, "version") &&
1523 entry.type == DBUS_TYPE_INT32)
1524 version = entry.uint32_value;
1525 else if (!strcmp(entry.key, "service") &&
1526 entry.type == DBUS_TYPE_STRING)
1527 service = os_strdup(entry.str_value);
1528 wpa_dbus_dict_entry_clear(&entry);
1530 if (version <= 0 || service == NULL)
1533 if (wpas_p2p_service_add_upnp(wpa_s, version, service) != 0)
1537 } else if (bonjour == 1) {
1538 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
1539 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
1542 if (!strcmp(entry.key, "query")) {
1543 if ((entry.type != DBUS_TYPE_ARRAY) ||
1544 (entry.array_type != DBUS_TYPE_BYTE))
1546 query = wpabuf_alloc_copy(entry.bytearray_value,
1548 } else if (!strcmp(entry.key, "response")) {
1549 if ((entry.type != DBUS_TYPE_ARRAY) ||
1550 (entry.array_type != DBUS_TYPE_BYTE))
1552 resp = wpabuf_alloc_copy(entry.bytearray_value,
1556 wpa_dbus_dict_entry_clear(&entry);
1559 if (query == NULL || resp == NULL)
1562 if (wpas_p2p_service_add_bonjour(wpa_s, query, resp) < 0) {
1572 wpa_dbus_dict_entry_clear(&entry);
1574 return wpas_dbus_error_invalid_args(message, NULL);
1577 DBusMessage *wpas_dbus_handler_p2p_delete_service(DBusMessage * message,
1578 struct wpa_supplicant * wpa_s)
1580 DBusMessageIter iter_dict;
1581 DBusMessage *reply = NULL;
1582 DBusMessageIter iter;
1583 struct wpa_dbus_dict_entry entry;
1587 char *service = NULL;
1588 struct wpabuf *query = NULL;
1591 dbus_message_iter_init(message, &iter);
1593 if (!wpa_dbus_dict_open_read(&iter, &iter_dict))
1596 if (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
1597 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
1600 if (!strcmp(entry.key, "service_type") &&
1601 (entry.type == DBUS_TYPE_STRING)) {
1602 if (!strcmp(entry.str_value, "upnp"))
1604 else if (!strcmp(entry.str_value, "bonjour"))
1608 wpa_dbus_dict_entry_clear(&entry);
1612 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
1613 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
1615 if (!strcmp(entry.key, "version") &&
1616 entry.type == DBUS_TYPE_INT32)
1617 version = entry.uint32_value;
1618 else if (!strcmp(entry.key, "service") &&
1619 entry.type == DBUS_TYPE_STRING)
1620 service = os_strdup(entry.str_value);
1624 wpa_dbus_dict_entry_clear(&entry);
1627 if (version <= 0 || service == NULL)
1630 ret = wpas_p2p_service_del_upnp(wpa_s, version, service);
1634 } else if (bonjour == 1) {
1635 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
1636 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
1639 if (!strcmp(entry.key, "query")) {
1640 if ((entry.type != DBUS_TYPE_ARRAY) ||
1641 (entry.array_type != DBUS_TYPE_BYTE))
1643 query = wpabuf_alloc_copy(entry.bytearray_value,
1648 wpa_dbus_dict_entry_clear(&entry);
1654 ret = wpas_p2p_service_del_bonjour(wpa_s, query);
1663 wpa_dbus_dict_entry_clear(&entry);
1665 return wpas_dbus_error_invalid_args(message, NULL);
1668 DBusMessage *wpas_dbus_handler_p2p_flush_service(DBusMessage * message,
1669 struct wpa_supplicant * wpa_s)
1671 wpas_p2p_service_flush(wpa_s);
1675 DBusMessage *wpas_dbus_handler_p2p_service_sd_req(DBusMessage * message,
1676 struct wpa_supplicant * wpa_s)
1678 DBusMessageIter iter_dict;
1679 DBusMessage *reply = NULL;
1680 DBusMessageIter iter;
1681 struct wpa_dbus_dict_entry entry;
1683 char *service = NULL;
1684 char *peer_object_path = NULL;
1685 struct wpabuf *tlv = NULL;
1690 dbus_message_iter_init(message, &iter);
1692 if (!wpa_dbus_dict_open_read(&iter, &iter_dict))
1695 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
1696 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
1698 if (!strcmp(entry.key, "peer_object") &&
1699 entry.type == DBUS_TYPE_OBJECT_PATH) {
1700 peer_object_path = os_strdup(entry.str_value);
1701 } else if (!strcmp(entry.key, "service_type") &&
1702 entry.type == DBUS_TYPE_STRING) {
1703 if (!strcmp(entry.str_value, "upnp"))
1707 } else if (!strcmp(entry.key, "version") &&
1708 entry.type == DBUS_TYPE_INT32) {
1709 version = entry.uint32_value;
1710 } else if (!strcmp(entry.key, "service") &&
1711 entry.type == DBUS_TYPE_STRING) {
1712 service = os_strdup(entry.str_value);
1713 } else if (!strcmp(entry.key, "tlv")) {
1714 if (entry.type != DBUS_TYPE_ARRAY ||
1715 entry.array_type != DBUS_TYPE_BYTE)
1717 tlv = wpabuf_alloc_copy(entry.bytearray_value,
1722 wpa_dbus_dict_entry_clear(&entry);
1725 if (!peer_object_path ||
1726 (parse_peer_object_path(peer_object_path, addr) < 0) ||
1727 (p2p_get_peer_info(wpa_s->global->p2p, addr, 0, NULL, 0) < 0))
1731 if (version <= 0 || service == NULL)
1734 ref = (unsigned long)wpas_p2p_sd_request_upnp(wpa_s, addr,
1739 ref = (unsigned long)wpas_p2p_sd_request(wpa_s, addr, tlv);
1744 reply = dbus_message_new_method_return(message);
1745 dbus_message_append_args(reply, DBUS_TYPE_UINT64,
1746 &ref, DBUS_TYPE_INVALID);
1748 reply = wpas_dbus_error_unknown_error(message,
1749 "Unable to send SD request");
1753 os_free(peer_object_path);
1756 wpa_dbus_dict_entry_clear(&entry);
1760 reply = wpas_dbus_error_invalid_args(message, NULL);
1764 DBusMessage *wpas_dbus_handler_p2p_service_sd_res(
1765 DBusMessage *message, struct wpa_supplicant *wpa_s)
1767 DBusMessageIter iter_dict;
1768 DBusMessage *reply = NULL;
1769 DBusMessageIter iter;
1770 struct wpa_dbus_dict_entry entry;
1771 char *peer_object_path = NULL;
1772 struct wpabuf *tlv = NULL;
1777 dbus_message_iter_init(message, &iter);
1779 if (!wpa_dbus_dict_open_read(&iter, &iter_dict))
1782 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
1783 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
1786 if (!strcmp(entry.key, "peer_object") &&
1787 entry.type == DBUS_TYPE_OBJECT_PATH) {
1788 peer_object_path = os_strdup(entry.str_value);
1789 } else if (!strcmp(entry.key, "frequency") &&
1790 entry.type == DBUS_TYPE_INT32) {
1791 freq = entry.uint32_value;
1792 } else if (!strcmp(entry.key, "dialog_token") &&
1793 entry.type == DBUS_TYPE_UINT32) {
1794 dlg_tok = entry.uint32_value;
1795 } else if (!strcmp(entry.key, "tlvs")) {
1796 if (entry.type != DBUS_TYPE_ARRAY ||
1797 entry.array_type != DBUS_TYPE_BYTE)
1799 tlv = wpabuf_alloc_copy(entry.bytearray_value,
1804 wpa_dbus_dict_entry_clear(&entry);
1806 if (!peer_object_path ||
1807 (parse_peer_object_path(peer_object_path, addr) < 0) ||
1808 (p2p_get_peer_info(wpa_s->global->p2p, addr, 0, NULL, 0) < 0))
1814 wpas_p2p_sd_response(wpa_s, freq, addr, (u8) dlg_tok, tlv);
1817 os_free(peer_object_path);
1820 wpa_dbus_dict_entry_clear(&entry);
1822 reply = wpas_dbus_error_invalid_args(message, NULL);
1826 DBusMessage *wpas_dbus_handler_p2p_service_sd_cancel_req(DBusMessage * message, struct wpa_supplicant
1829 DBusMessageIter iter;
1832 dbus_message_iter_init(message, &iter);
1833 dbus_message_iter_get_basic(&iter, &req);
1838 if (!wpas_p2p_sd_cancel_request(wpa_s, (void *)(unsigned long)req))
1843 return wpas_dbus_error_invalid_args(message, NULL);
1846 DBusMessage *wpas_dbus_handler_p2p_service_update(DBusMessage * message,
1847 struct wpa_supplicant * wpa_s)
1849 wpas_p2p_sd_service_update(wpa_s);
1853 DBusMessage *wpas_dbus_handler_p2p_serv_disc_external(DBusMessage * message,
1854 struct wpa_supplicant *
1857 DBusMessageIter iter;
1860 dbus_message_iter_init(message, &iter);
1861 dbus_message_iter_get_basic(&iter, &ext);
1863 wpa_s->p2p_sd_over_ctrl_iface = ext;