2 * WPA Supplicant / dbus-based control interface (P2P)
3 * Copyright (c) 2011-2012, Intel Corporation
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
11 #include "utils/includes.h"
13 #include "../config.h"
14 #include "../wpa_supplicant_i.h"
15 #include "../wps_supplicant.h"
16 #include "../notify.h"
17 #include "dbus_new_helpers.h"
19 #include "dbus_new_handlers.h"
20 #include "dbus_new_handlers_p2p.h"
21 #include "dbus_dict_helpers.h"
23 #include "common/ieee802_11_defs.h"
24 #include "ap/hostapd.h"
25 #include "ap/ap_config.h"
26 #include "ap/wps_hostapd.h"
28 #include "../p2p_supplicant.h"
29 #include "../wifi_display.h"
32 static int wpas_dbus_validate_dbus_ipaddr(struct wpa_dbus_dict_entry entry)
34 if (entry.type != DBUS_TYPE_ARRAY ||
35 entry.array_type != DBUS_TYPE_BYTE ||
44 * Parses out the mac address from the peer object path.
45 * @peer_path - object path of the form
46 * /fi/w1/wpa_supplicant1/Interfaces/n/Peers/00112233445566 (no colons)
47 * @addr - out param must be of ETH_ALEN size
48 * Returns 0 if valid (including MAC), -1 otherwise
50 static int parse_peer_object_path(const char *peer_path, u8 addr[ETH_ALEN])
56 p = os_strrchr(peer_path, '/');
60 return hwaddr_compact_aton(p, addr);
65 * wpas_dbus_error_persistent_group_unknown - Return a new PersistentGroupUnknown
67 * @message: Pointer to incoming dbus message this error refers to
68 * Returns: a dbus error message
70 * Convenience function to create and return an invalid persistent group error.
73 wpas_dbus_error_persistent_group_unknown(DBusMessage *message)
75 return dbus_message_new_error(
76 message, WPAS_DBUS_ERROR_NETWORK_UNKNOWN,
77 "There is no such persistent group in this P2P device.");
81 DBusMessage * wpas_dbus_handler_p2p_find(DBusMessage *message,
82 struct wpa_supplicant *wpa_s)
84 struct wpa_dbus_dict_entry entry;
85 DBusMessage *reply = NULL;
87 DBusMessageIter iter_dict;
88 unsigned int timeout = 0;
89 enum p2p_discovery_type type = P2P_FIND_START_WITH_FULL;
90 int num_req_dev_types = 0;
92 u8 *req_dev_types = NULL;
93 unsigned int freq = 0;
95 dbus_message_iter_init(message, &iter);
98 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
101 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
102 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
105 if (os_strcmp(entry.key, "Timeout") == 0 &&
106 entry.type == DBUS_TYPE_INT32) {
107 timeout = entry.uint32_value;
108 } else if (os_strcmp(entry.key, "RequestedDeviceTypes") == 0) {
109 if (entry.type != DBUS_TYPE_ARRAY ||
110 entry.array_type != WPAS_DBUS_TYPE_BINARRAY)
113 os_free(req_dev_types);
115 os_malloc(WPS_DEV_TYPE_LEN * entry.array_len);
119 for (i = 0; i < entry.array_len; i++) {
120 if (wpabuf_len(entry.binarray_value[i]) !=
123 os_memcpy(req_dev_types + i * WPS_DEV_TYPE_LEN,
124 wpabuf_head(entry.binarray_value[i]),
127 num_req_dev_types = entry.array_len;
128 } else if (os_strcmp(entry.key, "DiscoveryType") == 0 &&
129 entry.type == DBUS_TYPE_STRING) {
130 if (os_strcmp(entry.str_value, "start_with_full") == 0)
131 type = P2P_FIND_START_WITH_FULL;
132 else if (os_strcmp(entry.str_value, "social") == 0)
133 type = P2P_FIND_ONLY_SOCIAL;
134 else if (os_strcmp(entry.str_value, "progressive") == 0)
135 type = P2P_FIND_PROGRESSIVE;
138 } else if (os_strcmp(entry.key, "freq") == 0 &&
139 (entry.type == DBUS_TYPE_INT32 ||
140 entry.type == DBUS_TYPE_UINT32)) {
141 freq = entry.uint32_value;
144 wpa_dbus_dict_entry_clear(&entry);
147 wpa_s = wpa_s->global->p2p_init_wpa_s;
149 if (wpas_p2p_find(wpa_s, timeout, type, num_req_dev_types,
150 req_dev_types, NULL, 0, 0, NULL, freq))
151 reply = wpas_dbus_error_unknown_error(
152 message, "Could not start P2P find");
154 os_free(req_dev_types);
158 wpa_dbus_dict_entry_clear(&entry);
160 os_free(req_dev_types);
161 reply = wpas_dbus_error_invalid_args(message, entry.key);
166 DBusMessage * wpas_dbus_handler_p2p_stop_find(DBusMessage *message,
167 struct wpa_supplicant *wpa_s)
169 wpas_p2p_stop_find(wpa_s->global->p2p_init_wpa_s);
174 DBusMessage * wpas_dbus_handler_p2p_rejectpeer(DBusMessage *message,
175 struct wpa_supplicant *wpa_s)
177 DBusMessageIter iter;
178 char *peer_object_path = NULL;
179 u8 peer_addr[ETH_ALEN];
181 dbus_message_iter_init(message, &iter);
182 dbus_message_iter_get_basic(&iter, &peer_object_path);
184 if (parse_peer_object_path(peer_object_path, peer_addr) < 0)
185 return wpas_dbus_error_invalid_args(message, NULL);
187 wpa_s = wpa_s->global->p2p_init_wpa_s;
189 if (wpas_p2p_reject(wpa_s, peer_addr) < 0)
190 return wpas_dbus_error_unknown_error(message,
191 "Failed to call wpas_p2p_reject method.");
197 DBusMessage * wpas_dbus_handler_p2p_listen(DBusMessage *message,
198 struct wpa_supplicant *wpa_s)
200 dbus_int32_t timeout = 0;
202 if (!dbus_message_get_args(message, NULL, DBUS_TYPE_INT32, &timeout,
204 return wpas_dbus_error_no_memory(message);
206 wpa_s = wpa_s->global->p2p_init_wpa_s;
208 if (wpas_p2p_listen(wpa_s, (unsigned int) timeout)) {
209 return dbus_message_new_error(message,
210 WPAS_DBUS_ERROR_UNKNOWN_ERROR,
211 "Could not start P2P listen");
218 DBusMessage * wpas_dbus_handler_p2p_extendedlisten(
219 DBusMessage *message, struct wpa_supplicant *wpa_s)
221 unsigned int period = 0, interval = 0;
222 struct wpa_dbus_dict_entry entry;
223 DBusMessageIter iter;
224 DBusMessageIter iter_dict;
226 dbus_message_iter_init(message, &iter);
229 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
232 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
233 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
236 if (os_strcmp(entry.key, "period") == 0 &&
237 entry.type == DBUS_TYPE_INT32)
238 period = entry.uint32_value;
239 else if (os_strcmp(entry.key, "interval") == 0 &&
240 entry.type == DBUS_TYPE_INT32)
241 interval = entry.uint32_value;
244 wpa_dbus_dict_entry_clear(&entry);
247 wpa_s = wpa_s->global->p2p_init_wpa_s;
249 if (wpas_p2p_ext_listen(wpa_s, period, interval))
250 return wpas_dbus_error_unknown_error(
251 message, "failed to initiate a p2p_ext_listen.");
256 wpa_dbus_dict_entry_clear(&entry);
258 return wpas_dbus_error_invalid_args(message, entry.key);
262 DBusMessage * wpas_dbus_handler_p2p_presence_request(
263 DBusMessage *message, struct wpa_supplicant *wpa_s)
265 unsigned int dur1 = 0, int1 = 0, dur2 = 0, int2 = 0;
266 struct wpa_dbus_dict_entry entry;
267 DBusMessageIter iter;
268 DBusMessageIter iter_dict;
270 dbus_message_iter_init(message, &iter);
273 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
276 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
277 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
280 if (os_strcmp(entry.key, "duration1") == 0 &&
281 entry.type == DBUS_TYPE_INT32)
282 dur1 = entry.uint32_value;
283 else if (os_strcmp(entry.key, "interval1") == 0 &&
284 entry.type == DBUS_TYPE_INT32)
285 int1 = entry.uint32_value;
286 else if (os_strcmp(entry.key, "duration2") == 0 &&
287 entry.type == DBUS_TYPE_INT32)
288 dur2 = entry.uint32_value;
289 else if (os_strcmp(entry.key, "interval2") == 0 &&
290 entry.type == DBUS_TYPE_INT32)
291 int2 = entry.uint32_value;
295 wpa_dbus_dict_entry_clear(&entry);
298 if (wpas_p2p_presence_req(wpa_s, dur1, int1, dur2, int2) < 0)
299 return wpas_dbus_error_unknown_error(message,
300 "Failed to invoke presence request.");
305 wpa_dbus_dict_entry_clear(&entry);
307 return wpas_dbus_error_invalid_args(message, entry.key);
311 DBusMessage * wpas_dbus_handler_p2p_group_add(DBusMessage *message,
312 struct wpa_supplicant *wpa_s)
314 DBusMessageIter iter_dict;
315 DBusMessage *reply = NULL;
316 DBusMessageIter iter;
317 struct wpa_dbus_dict_entry entry;
318 char *pg_object_path = NULL;
319 int persistent_group = 0;
322 unsigned int group_id = 0;
323 struct wpa_ssid *ssid;
325 dbus_message_iter_init(message, &iter);
327 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
330 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
331 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
334 if (os_strcmp(entry.key, "persistent") == 0 &&
335 entry.type == DBUS_TYPE_BOOLEAN) {
336 persistent_group = entry.bool_value;
337 } else if (os_strcmp(entry.key, "frequency") == 0 &&
338 entry.type == DBUS_TYPE_INT32) {
339 freq = entry.int32_value;
342 } else if (os_strcmp(entry.key, "persistent_group_object") ==
344 entry.type == DBUS_TYPE_OBJECT_PATH)
345 pg_object_path = os_strdup(entry.str_value);
349 wpa_dbus_dict_entry_clear(&entry);
352 wpa_s = wpa_s->global->p2p_init_wpa_s;
354 if (pg_object_path != NULL) {
358 * A persistent group Object Path is defined meaning we want
359 * to re-invoke a persistent group.
362 iface = wpas_dbus_new_decompose_object_path(
363 pg_object_path, WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART,
365 if (iface == NULL || net_id_str == NULL ||
366 !wpa_s->parent->dbus_new_path ||
367 os_strcmp(iface, wpa_s->parent->dbus_new_path) != 0) {
369 wpas_dbus_error_invalid_args(message,
374 group_id = strtoul(net_id_str, NULL, 10);
375 if (errno == EINVAL) {
376 reply = wpas_dbus_error_invalid_args(
377 message, pg_object_path);
381 /* Get the SSID structure from the persistent group id */
382 ssid = wpa_config_get_network(wpa_s->conf, group_id);
383 if (ssid == NULL || ssid->disabled != 2)
386 if (wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 0, 0, 0,
388 reply = wpas_dbus_error_unknown_error(
390 "Failed to reinvoke a persistent group");
393 } else if (wpas_p2p_group_add(wpa_s, persistent_group, freq, 0, 0, 0,
398 os_free(pg_object_path);
402 wpa_dbus_dict_entry_clear(&entry);
404 reply = wpas_dbus_error_invalid_args(message, NULL);
409 DBusMessage * wpas_dbus_handler_p2p_disconnect(DBusMessage *message,
410 struct wpa_supplicant *wpa_s)
412 if (wpas_p2p_disconnect(wpa_s))
413 return wpas_dbus_error_unknown_error(message,
414 "failed to disconnect");
420 static dbus_bool_t wpa_dbus_p2p_check_enabled(struct wpa_supplicant *wpa_s,
421 DBusMessage *message,
422 DBusMessage **out_reply,
425 /* Return an error message or an error if P2P isn't available */
426 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL) {
428 *out_reply = dbus_message_new_error(
429 message, DBUS_ERROR_FAILED,
430 "P2P is not available for this interface");
432 dbus_set_error_const(error, DBUS_ERROR_FAILED,
433 "P2P is not available for this interface");
440 DBusMessage * wpas_dbus_handler_p2p_remove_client(DBusMessage *message,
441 struct wpa_supplicant *wpa_s)
443 DBusMessageIter iter_dict;
444 DBusMessage *reply = NULL;
445 DBusMessageIter iter;
446 struct wpa_dbus_dict_entry entry;
447 char *peer_object_path = NULL;
448 char *interface_addr = NULL;
449 u8 peer_addr[ETH_ALEN];
451 if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL))
454 dbus_message_iter_init(message, &iter);
456 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
459 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
460 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
463 if (os_strcmp(entry.key, "peer") == 0 &&
464 entry.type == DBUS_TYPE_OBJECT_PATH) {
465 os_free(peer_object_path);
466 peer_object_path = os_strdup(entry.str_value);
467 wpa_dbus_dict_entry_clear(&entry);
468 } else if (os_strcmp(entry.key, "iface") == 0 &&
469 entry.type == DBUS_TYPE_STRING) {
470 os_free(interface_addr);
471 interface_addr = os_strdup(entry.str_value);
472 wpa_dbus_dict_entry_clear(&entry);
474 wpa_dbus_dict_entry_clear(&entry);
479 if ((!peer_object_path && !interface_addr) ||
481 (parse_peer_object_path(peer_object_path, peer_addr) < 0 ||
482 !p2p_peer_known(wpa_s->global->p2p, peer_addr))) ||
483 (interface_addr && hwaddr_aton(interface_addr, peer_addr) < 0))
486 wpas_p2p_remove_client(wpa_s, peer_addr, interface_addr != NULL);
489 os_free(peer_object_path);
490 os_free(interface_addr);
493 reply = wpas_dbus_error_invalid_args(message, "Invalid address format");
498 DBusMessage * wpas_dbus_handler_p2p_flush(DBusMessage *message,
499 struct wpa_supplicant *wpa_s)
501 DBusMessage *reply = NULL;
503 if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL))
506 wpa_s = wpa_s->global->p2p_init_wpa_s;
508 os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
509 wpa_s->force_long_sd = 0;
510 p2p_flush(wpa_s->global->p2p);
516 DBusMessage * wpas_dbus_handler_p2p_connect(DBusMessage *message,
517 struct wpa_supplicant *wpa_s)
519 DBusMessageIter iter_dict;
520 DBusMessage *reply = NULL;
521 DBusMessageIter iter;
522 struct wpa_dbus_dict_entry entry;
523 char *peer_object_path = NULL;
524 int persistent_group = 0;
526 int authorize_only = 0;
531 enum p2p_wps_method wps_method = WPS_NOT_READY;
533 char *err_msg = NULL;
536 if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL))
539 dbus_message_iter_init(message, &iter);
541 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
544 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
545 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
548 if (os_strcmp(entry.key, "peer") == 0 &&
549 entry.type == DBUS_TYPE_OBJECT_PATH) {
550 peer_object_path = os_strdup(entry.str_value);
551 } else if (os_strcmp(entry.key, "persistent") == 0 &&
552 entry.type == DBUS_TYPE_BOOLEAN) {
553 persistent_group = entry.bool_value;
554 } else if (os_strcmp(entry.key, "join") == 0 &&
555 entry.type == DBUS_TYPE_BOOLEAN) {
556 join = entry.bool_value;
557 } else if (os_strcmp(entry.key, "authorize_only") == 0 &&
558 entry.type == DBUS_TYPE_BOOLEAN) {
559 authorize_only = entry.bool_value;
560 } else if (os_strcmp(entry.key, "frequency") == 0 &&
561 entry.type == DBUS_TYPE_INT32) {
562 freq = entry.int32_value;
565 } else if (os_strcmp(entry.key, "go_intent") == 0 &&
566 entry.type == DBUS_TYPE_INT32) {
567 go_intent = entry.int32_value;
568 if ((go_intent < 0) || (go_intent > 15))
570 } else if (os_strcmp(entry.key, "wps_method") == 0 &&
571 entry.type == DBUS_TYPE_STRING) {
572 if (os_strcmp(entry.str_value, "pbc") == 0)
573 wps_method = WPS_PBC;
574 else if (os_strcmp(entry.str_value, "pin") == 0)
575 wps_method = WPS_PIN_DISPLAY;
576 else if (os_strcmp(entry.str_value, "display") == 0)
577 wps_method = WPS_PIN_DISPLAY;
578 else if (os_strcmp(entry.str_value, "keypad") == 0)
579 wps_method = WPS_PIN_KEYPAD;
582 } else if (os_strcmp(entry.key, "pin") == 0 &&
583 entry.type == DBUS_TYPE_STRING) {
584 pin = os_strdup(entry.str_value);
588 wpa_dbus_dict_entry_clear(&entry);
591 if (wps_method == WPS_NOT_READY ||
592 parse_peer_object_path(peer_object_path, addr) < 0 ||
593 !p2p_peer_known(wpa_s->global->p2p, addr))
597 * Validate the wps_method specified and the pin value.
599 if ((!pin || !pin[0]) && wps_method == WPS_PIN_KEYPAD)
602 wpa_s = wpa_s->global->p2p_init_wpa_s;
604 new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
605 persistent_group, 0, join, authorize_only,
606 go_intent, freq, 0, -1, 0, 0, 0, 0, NULL, 0);
612 os_snprintf(npin, sizeof(npin), "%08d", new_pin);
613 generated_pin = npin;
614 reply = dbus_message_new_method_return(message);
615 dbus_message_append_args(reply, DBUS_TYPE_STRING,
616 &generated_pin, DBUS_TYPE_INVALID);
621 "connect failed due to channel unavailability.";
622 iface = WPAS_DBUS_ERROR_CONNECT_CHANNEL_UNAVAILABLE;
626 err_msg = "connect failed due to unsupported channel.";
627 iface = WPAS_DBUS_ERROR_CONNECT_CHANNEL_UNSUPPORTED;
631 err_msg = "connect failed due to unspecified error.";
632 iface = WPAS_DBUS_ERROR_CONNECT_UNSPECIFIED_ERROR;
638 * Do we need specialized errors corresponding to above
639 * error conditions as against just returning a different
642 reply = dbus_message_new_error(message, iface, err_msg);
646 os_free(peer_object_path);
650 wpa_dbus_dict_entry_clear(&entry);
652 reply = wpas_dbus_error_invalid_args(message, NULL);
658 * wpas_dbus_handler_p2p_cancel - Cancel P2P group formation
659 * @message: Pointer to incoming dbus message
660 * @wpa_s: %wpa_supplicant data structure
661 * Returns: NULL on success or DBus error on failure
663 * Handler for "Cancel" method call. Returns NULL if P2P cancel succeeds or DBus
664 * error on P2P cancel failure
666 DBusMessage * wpas_dbus_handler_p2p_cancel(DBusMessage *message,
667 struct wpa_supplicant *wpa_s)
669 if (wpas_p2p_cancel(wpa_s))
670 return wpas_dbus_error_unknown_error(message,
671 "P2P cancel failed");
677 DBusMessage * wpas_dbus_handler_p2p_invite(DBusMessage *message,
678 struct wpa_supplicant *wpa_s)
680 DBusMessageIter iter_dict;
681 DBusMessage *reply = NULL;
682 DBusMessageIter iter;
683 struct wpa_dbus_dict_entry entry;
684 char *peer_object_path = NULL;
685 char *pg_object_path = NULL;
687 u8 peer_addr[ETH_ALEN];
688 unsigned int group_id = 0;
690 struct wpa_ssid *ssid;
692 if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL))
695 dbus_message_iter_init(message, &iter);
697 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
700 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
701 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
704 if (os_strcmp(entry.key, "peer") == 0 &&
705 entry.type == DBUS_TYPE_OBJECT_PATH) {
706 peer_object_path = os_strdup(entry.str_value);
707 wpa_dbus_dict_entry_clear(&entry);
708 } else if (os_strcmp(entry.key, "persistent_group_object") ==
710 entry.type == DBUS_TYPE_OBJECT_PATH) {
711 pg_object_path = os_strdup(entry.str_value);
713 wpa_dbus_dict_entry_clear(&entry);
715 wpa_dbus_dict_entry_clear(&entry);
720 if (parse_peer_object_path(peer_object_path, peer_addr) < 0 ||
721 !p2p_peer_known(wpa_s->global->p2p, peer_addr))
724 wpa_s = wpa_s->global->p2p_init_wpa_s;
729 * A group ID is defined meaning we want to re-invoke a
733 iface = wpas_dbus_new_decompose_object_path(
735 WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART,
737 if (iface == NULL || net_id_str == NULL ||
738 !wpa_s->parent->dbus_new_path ||
739 os_strcmp(iface, wpa_s->parent->dbus_new_path) != 0) {
740 reply = wpas_dbus_error_invalid_args(message,
745 group_id = strtoul(net_id_str, NULL, 10);
746 if (errno == EINVAL) {
747 reply = wpas_dbus_error_invalid_args(
748 message, pg_object_path);
752 /* Get the SSID structure from the persistent group id */
753 ssid = wpa_config_get_network(wpa_s->conf, group_id);
754 if (ssid == NULL || ssid->disabled != 2)
757 if (wpas_p2p_invite(wpa_s, peer_addr, ssid, NULL, 0, 0, 0, 0, 0,
759 reply = wpas_dbus_error_unknown_error(
761 "Failed to reinvoke a persistent group");
766 * No group ID means propose to a peer to join my active group
768 if (wpas_p2p_invite_group(wpa_s, wpa_s->ifname,
770 reply = wpas_dbus_error_unknown_error(
771 message, "Failed to join to an active group");
778 os_free(pg_object_path);
779 os_free(peer_object_path);
783 reply = wpas_dbus_error_invalid_args(message, NULL);
788 DBusMessage * wpas_dbus_handler_p2p_prov_disc_req(DBusMessage *message,
789 struct wpa_supplicant *wpa_s)
791 DBusMessageIter iter;
792 char *peer_object_path = NULL;
793 char *config_method = NULL;
794 u8 peer_addr[ETH_ALEN];
796 dbus_message_iter_init(message, &iter);
797 dbus_message_iter_get_basic(&iter, &peer_object_path);
799 if (parse_peer_object_path(peer_object_path, peer_addr) < 0)
800 return wpas_dbus_error_invalid_args(message, NULL);
802 dbus_message_iter_next(&iter);
803 dbus_message_iter_get_basic(&iter, &config_method);
806 * Validation checks on config_method are being duplicated here
807 * to be able to return invalid args reply since the error code
808 * from p2p module are not granular enough (yet).
810 if (os_strcmp(config_method, "display") &&
811 os_strcmp(config_method, "keypad") &&
812 os_strcmp(config_method, "pbc") &&
813 os_strcmp(config_method, "pushbutton"))
814 return wpas_dbus_error_invalid_args(message, NULL);
816 wpa_s = wpa_s->global->p2p_init_wpa_s;
818 if (wpas_p2p_prov_disc(wpa_s, peer_addr, config_method,
819 WPAS_P2P_PD_FOR_GO_NEG, NULL) < 0)
820 return wpas_dbus_error_unknown_error(message,
821 "Failed to send provision discovery request");
828 * P2P Device property accessor methods.
831 dbus_bool_t wpas_dbus_getter_p2p_device_config(
832 const struct wpa_dbus_property_desc *property_desc,
833 DBusMessageIter *iter, DBusError *error, void *user_data)
835 struct wpa_supplicant *wpa_s = user_data;
836 DBusMessageIter variant_iter, dict_iter;
837 DBusMessageIter iter_secdev_dict_entry, iter_secdev_dict_val,
838 iter_secdev_dict_array;
839 const char *dev_name;
840 int num_vendor_extensions = 0;
842 const struct wpabuf *vendor_ext[P2P_MAX_WPS_VENDOR_EXT];
844 if (!wpa_dbus_p2p_check_enabled(wpa_s, NULL, NULL, error))
847 wpa_s = wpa_s->global->p2p_init_wpa_s;
849 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
850 "a{sv}", &variant_iter) ||
851 !wpa_dbus_dict_open_write(&variant_iter, &dict_iter))
855 dev_name = wpa_s->conf->device_name;
857 !wpa_dbus_dict_append_string(&dict_iter, "DeviceName", dev_name))
860 /* Primary device type */
861 if (!wpa_dbus_dict_append_byte_array(&dict_iter, "PrimaryDeviceType",
862 (char *) wpa_s->conf->device_type,
866 /* Secondary device types */
867 if (wpa_s->conf->num_sec_device_types) {
868 if (!wpa_dbus_dict_begin_array(&dict_iter,
869 "SecondaryDeviceTypes",
870 DBUS_TYPE_ARRAY_AS_STRING
871 DBUS_TYPE_BYTE_AS_STRING,
872 &iter_secdev_dict_entry,
873 &iter_secdev_dict_val,
874 &iter_secdev_dict_array))
877 for (i = 0; i < wpa_s->conf->num_sec_device_types; i++)
878 wpa_dbus_dict_bin_array_add_element(
879 &iter_secdev_dict_array,
880 wpa_s->conf->sec_device_type[i],
883 if (!wpa_dbus_dict_end_array(&dict_iter,
884 &iter_secdev_dict_entry,
885 &iter_secdev_dict_val,
886 &iter_secdev_dict_array))
891 if (WPA_GET_BE32(wpa_s->conf->ip_addr_go) &&
892 !wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddrGo",
893 (char *) wpa_s->conf->ip_addr_go,
897 /* IP address mask */
898 if (WPA_GET_BE32(wpa_s->conf->ip_addr_mask) &&
899 !wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddrMask",
900 (char *) wpa_s->conf->ip_addr_mask,
904 /* IP address start */
905 if (WPA_GET_BE32(wpa_s->conf->ip_addr_start) &&
906 !wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddrStart",
908 wpa_s->conf->ip_addr_start,
913 if (WPA_GET_BE32(wpa_s->conf->ip_addr_end) &&
914 !wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddrEnd",
915 (char *) wpa_s->conf->ip_addr_end,
919 /* Vendor Extensions */
920 for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
921 if (wpa_s->conf->wps_vendor_ext[i] == NULL)
923 vendor_ext[num_vendor_extensions++] =
924 wpa_s->conf->wps_vendor_ext[i];
927 if ((num_vendor_extensions &&
928 !wpa_dbus_dict_append_wpabuf_array(&dict_iter,
931 num_vendor_extensions)) ||
932 !wpa_dbus_dict_append_uint32(&dict_iter, "GOIntent",
933 wpa_s->conf->p2p_go_intent) ||
934 !wpa_dbus_dict_append_bool(&dict_iter, "PersistentReconnect",
935 wpa_s->conf->persistent_reconnect) ||
936 !wpa_dbus_dict_append_uint32(&dict_iter, "ListenRegClass",
937 wpa_s->conf->p2p_listen_reg_class) ||
938 !wpa_dbus_dict_append_uint32(&dict_iter, "ListenChannel",
939 wpa_s->conf->p2p_listen_channel) ||
940 !wpa_dbus_dict_append_uint32(&dict_iter, "OperRegClass",
941 wpa_s->conf->p2p_oper_reg_class) ||
942 !wpa_dbus_dict_append_uint32(&dict_iter, "OperChannel",
943 wpa_s->conf->p2p_oper_channel) ||
944 (wpa_s->conf->p2p_ssid_postfix &&
945 !wpa_dbus_dict_append_string(&dict_iter, "SsidPostfix",
946 wpa_s->conf->p2p_ssid_postfix)) ||
947 !wpa_dbus_dict_append_bool(&dict_iter, "IntraBss",
948 wpa_s->conf->p2p_intra_bss) ||
949 !wpa_dbus_dict_append_uint32(&dict_iter, "GroupIdle",
950 wpa_s->conf->p2p_group_idle) ||
951 !wpa_dbus_dict_append_uint32(&dict_iter, "disassoc_low_ack",
952 wpa_s->conf->disassoc_low_ack) ||
953 !wpa_dbus_dict_append_bool(&dict_iter, "NoGroupIface",
954 wpa_s->conf->p2p_no_group_iface) ||
955 !wpa_dbus_dict_append_uint32(&dict_iter, "p2p_search_delay",
956 wpa_s->conf->p2p_search_delay) ||
957 !wpa_dbus_dict_close_write(&variant_iter, &dict_iter) ||
958 !dbus_message_iter_close_container(iter, &variant_iter))
964 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
969 dbus_bool_t wpas_dbus_setter_p2p_device_config(
970 const struct wpa_dbus_property_desc *property_desc,
971 DBusMessageIter *iter, DBusError *error, void *user_data)
973 struct wpa_supplicant *wpa_s = user_data;
974 DBusMessageIter variant_iter, iter_dict;
975 struct wpa_dbus_dict_entry entry = {.type = DBUS_TYPE_STRING };
978 if (!wpa_dbus_p2p_check_enabled(wpa_s, NULL, NULL, error))
981 wpa_s = wpa_s->global->p2p_init_wpa_s;
983 dbus_message_iter_recurse(iter, &variant_iter);
984 if (!wpa_dbus_dict_open_read(&variant_iter, &iter_dict, error))
987 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
988 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) {
989 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
990 "invalid message format");
994 if (os_strcmp(entry.key, "DeviceName") == 0) {
997 if (entry.type != DBUS_TYPE_STRING ||
998 os_strlen(entry.str_value) > WPS_DEV_NAME_MAX_LEN)
1001 devname = os_strdup(entry.str_value);
1002 if (devname == NULL)
1003 goto err_no_mem_clear;
1005 os_free(wpa_s->conf->device_name);
1006 wpa_s->conf->device_name = devname;
1008 wpa_s->conf->changed_parameters |=
1009 CFG_CHANGED_DEVICE_NAME;
1010 } else if (os_strcmp(entry.key, "PrimaryDeviceType") == 0) {
1011 if (entry.type != DBUS_TYPE_ARRAY ||
1012 entry.array_type != DBUS_TYPE_BYTE ||
1013 entry.array_len != WPS_DEV_TYPE_LEN)
1016 os_memcpy(wpa_s->conf->device_type,
1017 entry.bytearray_value,
1019 wpa_s->conf->changed_parameters |=
1020 CFG_CHANGED_DEVICE_TYPE;
1021 } else if (os_strcmp(entry.key, "SecondaryDeviceTypes") == 0) {
1022 if (entry.type != DBUS_TYPE_ARRAY ||
1023 entry.array_type != WPAS_DBUS_TYPE_BINARRAY ||
1024 entry.array_len > MAX_SEC_DEVICE_TYPES)
1027 for (i = 0; i < entry.array_len; i++)
1028 if (wpabuf_len(entry.binarray_value[i]) !=
1030 goto err_no_mem_clear;
1031 for (i = 0; i < entry.array_len; i++)
1032 os_memcpy(wpa_s->conf->sec_device_type[i],
1033 wpabuf_head(entry.binarray_value[i]),
1035 wpa_s->conf->num_sec_device_types = entry.array_len;
1036 wpa_s->conf->changed_parameters |=
1037 CFG_CHANGED_SEC_DEVICE_TYPE;
1038 } else if (os_strcmp(entry.key, "VendorExtension") == 0) {
1039 if (entry.type != DBUS_TYPE_ARRAY ||
1040 entry.array_type != WPAS_DBUS_TYPE_BINARRAY ||
1041 (entry.array_len > P2P_MAX_WPS_VENDOR_EXT))
1044 wpa_s->conf->changed_parameters |=
1045 CFG_CHANGED_VENDOR_EXTENSION;
1047 for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
1048 wpabuf_free(wpa_s->conf->wps_vendor_ext[i]);
1049 if (i < entry.array_len) {
1050 wpa_s->conf->wps_vendor_ext[i] =
1051 entry.binarray_value[i];
1052 entry.binarray_value[i] = NULL;
1054 wpa_s->conf->wps_vendor_ext[i] = NULL;
1056 } else if (os_strcmp(entry.key, "GOIntent") == 0 &&
1057 entry.type == DBUS_TYPE_UINT32 &&
1058 (entry.uint32_value <= 15))
1059 wpa_s->conf->p2p_go_intent = entry.uint32_value;
1060 else if (os_strcmp(entry.key, "PersistentReconnect") == 0 &&
1061 entry.type == DBUS_TYPE_BOOLEAN)
1062 wpa_s->conf->persistent_reconnect = entry.bool_value;
1063 else if (os_strcmp(entry.key, "ListenRegClass") == 0 &&
1064 entry.type == DBUS_TYPE_UINT32) {
1065 wpa_s->conf->p2p_listen_reg_class = entry.uint32_value;
1066 wpa_s->conf->changed_parameters |=
1067 CFG_CHANGED_P2P_LISTEN_CHANNEL;
1068 } else if (os_strcmp(entry.key, "ListenChannel") == 0 &&
1069 entry.type == DBUS_TYPE_UINT32) {
1070 wpa_s->conf->p2p_listen_channel = entry.uint32_value;
1071 wpa_s->conf->changed_parameters |=
1072 CFG_CHANGED_P2P_LISTEN_CHANNEL;
1073 } else if (os_strcmp(entry.key, "OperRegClass") == 0 &&
1074 entry.type == DBUS_TYPE_UINT32) {
1075 wpa_s->conf->p2p_oper_reg_class = entry.uint32_value;
1076 wpa_s->conf->changed_parameters |=
1077 CFG_CHANGED_P2P_OPER_CHANNEL;
1078 } else if (os_strcmp(entry.key, "OperChannel") == 0 &&
1079 entry.type == DBUS_TYPE_UINT32) {
1080 wpa_s->conf->p2p_oper_channel = entry.uint32_value;
1081 wpa_s->conf->changed_parameters |=
1082 CFG_CHANGED_P2P_OPER_CHANNEL;
1083 } else if (os_strcmp(entry.key, "SsidPostfix") == 0) {
1086 if (entry.type != DBUS_TYPE_STRING)
1089 postfix = os_strdup(entry.str_value);
1091 goto err_no_mem_clear;
1093 os_free(wpa_s->conf->p2p_ssid_postfix);
1094 wpa_s->conf->p2p_ssid_postfix = postfix;
1096 wpa_s->conf->changed_parameters |=
1097 CFG_CHANGED_P2P_SSID_POSTFIX;
1098 } else if (os_strcmp(entry.key, "IntraBss") == 0 &&
1099 entry.type == DBUS_TYPE_BOOLEAN) {
1100 wpa_s->conf->p2p_intra_bss = entry.bool_value;
1101 wpa_s->conf->changed_parameters |=
1102 CFG_CHANGED_P2P_INTRA_BSS;
1103 } else if (os_strcmp(entry.key, "IpAddrGo") == 0) {
1104 if (!wpas_dbus_validate_dbus_ipaddr(entry))
1106 os_memcpy(wpa_s->conf->ip_addr_go,
1107 entry.bytearray_value, 4);
1108 } else if (os_strcmp(entry.key, "IpAddrMask") == 0) {
1109 if (!wpas_dbus_validate_dbus_ipaddr(entry))
1111 os_memcpy(wpa_s->conf->ip_addr_mask,
1112 entry.bytearray_value, 4);
1113 } else if (os_strcmp(entry.key, "IpAddrStart") == 0) {
1114 if (!wpas_dbus_validate_dbus_ipaddr(entry))
1116 os_memcpy(wpa_s->conf->ip_addr_start,
1117 entry.bytearray_value, 4);
1118 } else if (os_strcmp(entry.key, "IpAddrEnd") == 0) {
1119 if (!wpas_dbus_validate_dbus_ipaddr(entry))
1121 os_memcpy(wpa_s->conf->ip_addr_end,
1122 entry.bytearray_value, 4);
1123 } else if (os_strcmp(entry.key, "GroupIdle") == 0 &&
1124 entry.type == DBUS_TYPE_UINT32)
1125 wpa_s->conf->p2p_group_idle = entry.uint32_value;
1126 else if (os_strcmp(entry.key, "disassoc_low_ack") == 0 &&
1127 entry.type == DBUS_TYPE_UINT32)
1128 wpa_s->conf->disassoc_low_ack = entry.uint32_value;
1129 else if (os_strcmp(entry.key, "NoGroupIface") == 0 &&
1130 entry.type == DBUS_TYPE_BOOLEAN)
1131 wpa_s->conf->p2p_no_group_iface = entry.bool_value;
1132 else if (os_strcmp(entry.key, "p2p_search_delay") == 0 &&
1133 entry.type == DBUS_TYPE_UINT32)
1134 wpa_s->conf->p2p_search_delay = entry.uint32_value;
1138 wpa_dbus_dict_entry_clear(&entry);
1141 if (wpa_s->conf->changed_parameters) {
1142 /* Some changed parameters requires to update config*/
1143 wpa_supplicant_update_config(wpa_s);
1149 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
1150 "invalid message format");
1151 wpa_dbus_dict_entry_clear(&entry);
1155 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1156 wpa_dbus_dict_entry_clear(&entry);
1161 dbus_bool_t wpas_dbus_getter_p2p_peers(
1162 const struct wpa_dbus_property_desc *property_desc,
1163 DBusMessageIter *iter, DBusError *error, void *user_data)
1165 struct wpa_supplicant *wpa_s = user_data;
1166 struct p2p_data *p2p = wpa_s->global->p2p;
1167 int next = 0, i = 0;
1168 int num = 0, out_of_mem = 0;
1170 const struct p2p_peer_info *peer_info = NULL;
1171 dbus_bool_t success = FALSE;
1173 struct dl_list peer_objpath_list;
1174 struct peer_objpath_node {
1175 struct dl_list list;
1176 char path[WPAS_DBUS_OBJECT_PATH_MAX];
1179 char **peer_obj_paths = NULL;
1181 if (!wpa_dbus_p2p_check_enabled(wpa_s, NULL, NULL, error) ||
1182 !wpa_s->parent->parent->dbus_new_path)
1185 dl_list_init(&peer_objpath_list);
1187 /* Get the first peer info */
1188 peer_info = p2p_get_peer_found(p2p, NULL, next);
1190 /* Get next and accumulate them */
1192 while (peer_info != NULL) {
1193 node = os_zalloc(sizeof(struct peer_objpath_node));
1199 addr = peer_info->p2p_device_addr;
1200 os_snprintf(node->path, WPAS_DBUS_OBJECT_PATH_MAX,
1201 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART
1203 wpa_s->parent->parent->dbus_new_path,
1205 dl_list_add_tail(&peer_objpath_list, &node->list);
1208 peer_info = p2p_get_peer_found(p2p, addr, next);
1212 * Now construct the peer object paths in a form suitable for
1213 * array_property_getter helper below.
1215 peer_obj_paths = os_calloc(num, sizeof(char *));
1217 if (!peer_obj_paths) {
1222 dl_list_for_each_safe(node, tmp, &peer_objpath_list,
1223 struct peer_objpath_node, list)
1224 peer_obj_paths[i++] = node->path;
1226 success = wpas_dbus_simple_array_property_getter(iter,
1227 DBUS_TYPE_OBJECT_PATH,
1228 peer_obj_paths, num,
1233 os_free(peer_obj_paths);
1235 dl_list_for_each_safe(node, tmp, &peer_objpath_list,
1236 struct peer_objpath_node, list) {
1237 dl_list_del(&node->list);
1241 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1247 enum wpas_p2p_role {
1248 WPAS_P2P_ROLE_DEVICE,
1250 WPAS_P2P_ROLE_CLIENT,
1253 static enum wpas_p2p_role wpas_get_p2p_role(struct wpa_supplicant *wpa_s)
1255 struct wpa_ssid *ssid = wpa_s->current_ssid;
1258 return WPAS_P2P_ROLE_DEVICE;
1259 if (wpa_s->wpa_state != WPA_COMPLETED)
1260 return WPAS_P2P_ROLE_DEVICE;
1262 switch (ssid->mode) {
1263 case WPAS_MODE_P2P_GO:
1264 case WPAS_MODE_P2P_GROUP_FORMATION:
1265 return WPAS_P2P_ROLE_GO;
1266 case WPAS_MODE_INFRA:
1267 if (ssid->p2p_group)
1268 return WPAS_P2P_ROLE_CLIENT;
1269 return WPAS_P2P_ROLE_DEVICE;
1271 return WPAS_P2P_ROLE_DEVICE;
1276 dbus_bool_t wpas_dbus_getter_p2p_role(
1277 const struct wpa_dbus_property_desc *property_desc,
1278 DBusMessageIter *iter, DBusError *error, void *user_data)
1280 struct wpa_supplicant *wpa_s = user_data;
1283 switch (wpas_get_p2p_role(wpa_s)) {
1284 case WPAS_P2P_ROLE_GO:
1287 case WPAS_P2P_ROLE_CLIENT:
1295 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &str,
1300 dbus_bool_t wpas_dbus_getter_p2p_group(
1301 const struct wpa_dbus_property_desc *property_desc,
1302 DBusMessageIter *iter, DBusError *error, void *user_data)
1304 struct wpa_supplicant *wpa_s = user_data;
1305 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX];
1306 char *dbus_groupobj_path = path_buf;
1308 if (wpa_s->dbus_groupobj_path == NULL)
1309 os_snprintf(dbus_groupobj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1312 os_snprintf(dbus_groupobj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1313 "%s", wpa_s->dbus_groupobj_path);
1315 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
1316 &dbus_groupobj_path, error);
1320 dbus_bool_t wpas_dbus_getter_p2p_peergo(
1321 const struct wpa_dbus_property_desc *property_desc,
1322 DBusMessageIter *iter, DBusError *error, void *user_data)
1324 struct wpa_supplicant *wpa_s = user_data;
1325 char go_peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1327 if (!wpa_s->parent->parent->dbus_new_path)
1330 if (wpas_get_p2p_role(wpa_s) != WPAS_P2P_ROLE_CLIENT)
1331 os_snprintf(go_peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
1333 os_snprintf(go_peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1334 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
1336 wpa_s->parent->parent->dbus_new_path,
1337 MAC2STR(wpa_s->go_dev_addr));
1339 path = go_peer_obj_path;
1340 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
1346 * Peer object properties accessor methods
1349 dbus_bool_t wpas_dbus_getter_p2p_peer_device_name(
1350 const struct wpa_dbus_property_desc *property_desc,
1351 DBusMessageIter *iter, DBusError *error, void *user_data)
1353 struct peer_handler_args *peer_args = user_data;
1354 const struct p2p_peer_info *info;
1357 if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error))
1360 /* get the peer info */
1361 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1362 peer_args->p2p_device_addr, 0);
1364 dbus_set_error(error, DBUS_ERROR_FAILED,
1365 "failed to find peer");
1369 tmp = os_strdup(info->device_name);
1371 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1375 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp,
1377 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1387 dbus_bool_t wpas_dbus_getter_p2p_peer_manufacturer(
1388 const struct wpa_dbus_property_desc *property_desc,
1389 DBusMessageIter *iter, DBusError *error, void *user_data)
1391 struct peer_handler_args *peer_args = user_data;
1392 const struct p2p_peer_info *info;
1395 if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error))
1398 /* get the peer info */
1399 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1400 peer_args->p2p_device_addr, 0);
1402 dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer");
1406 tmp = os_strdup(info->manufacturer);
1408 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1412 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp,
1414 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1424 dbus_bool_t wpas_dbus_getter_p2p_peer_modelname(
1425 const struct wpa_dbus_property_desc *property_desc,
1426 DBusMessageIter *iter, DBusError *error, void *user_data)
1428 struct peer_handler_args *peer_args = user_data;
1429 const struct p2p_peer_info *info;
1432 if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error))
1435 /* get the peer info */
1436 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1437 peer_args->p2p_device_addr, 0);
1439 dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer");
1443 tmp = os_strdup(info->model_name);
1445 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1449 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp,
1451 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1461 dbus_bool_t wpas_dbus_getter_p2p_peer_modelnumber(
1462 const struct wpa_dbus_property_desc *property_desc,
1463 DBusMessageIter *iter, DBusError *error, void *user_data)
1465 struct peer_handler_args *peer_args = user_data;
1466 const struct p2p_peer_info *info;
1469 if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error))
1472 /* get the peer info */
1473 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1474 peer_args->p2p_device_addr, 0);
1476 dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer");
1480 tmp = os_strdup(info->model_number);
1482 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1486 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp,
1488 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1498 dbus_bool_t wpas_dbus_getter_p2p_peer_serialnumber(
1499 const struct wpa_dbus_property_desc *property_desc,
1500 DBusMessageIter *iter, DBusError *error, void *user_data)
1502 struct peer_handler_args *peer_args = user_data;
1503 const struct p2p_peer_info *info;
1506 if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error))
1509 /* get the peer info */
1510 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1511 peer_args->p2p_device_addr, 0);
1513 dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer");
1517 tmp = os_strdup(info->serial_number);
1519 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1523 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp,
1525 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1535 dbus_bool_t wpas_dbus_getter_p2p_peer_primary_device_type(
1536 const struct wpa_dbus_property_desc *property_desc,
1537 DBusMessageIter *iter, DBusError *error, void *user_data)
1539 struct peer_handler_args *peer_args = user_data;
1540 const struct p2p_peer_info *info;
1542 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1543 peer_args->p2p_device_addr, 0);
1545 dbus_set_error(error, DBUS_ERROR_FAILED,
1546 "failed to find peer");
1550 if (!wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
1553 WPS_DEV_TYPE_LEN, error)) {
1554 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1562 dbus_bool_t wpas_dbus_getter_p2p_peer_config_method(
1563 const struct wpa_dbus_property_desc *property_desc,
1564 DBusMessageIter *iter, DBusError *error, void *user_data)
1566 struct peer_handler_args *peer_args = user_data;
1567 const struct p2p_peer_info *info;
1569 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1570 peer_args->p2p_device_addr, 0);
1572 dbus_set_error(error, DBUS_ERROR_FAILED,
1573 "failed to find peer");
1577 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
1578 &info->config_methods, error)) {
1579 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1587 dbus_bool_t wpas_dbus_getter_p2p_peer_level(
1588 const struct wpa_dbus_property_desc *property_desc,
1589 DBusMessageIter *iter, DBusError *error, void *user_data)
1591 struct peer_handler_args *peer_args = user_data;
1592 const struct p2p_peer_info *info;
1594 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1595 peer_args->p2p_device_addr, 0);
1597 dbus_set_error(error, DBUS_ERROR_FAILED,
1598 "failed to find peer");
1602 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
1603 &info->level, error)) {
1604 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1612 dbus_bool_t wpas_dbus_getter_p2p_peer_device_capability(
1613 const struct wpa_dbus_property_desc *property_desc,
1614 DBusMessageIter *iter, DBusError *error, void *user_data)
1616 struct peer_handler_args *peer_args = user_data;
1617 const struct p2p_peer_info *info;
1619 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1620 peer_args->p2p_device_addr, 0);
1622 dbus_set_error(error, DBUS_ERROR_FAILED,
1623 "failed to find peer");
1627 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BYTE,
1628 &info->dev_capab, error)) {
1629 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1637 dbus_bool_t wpas_dbus_getter_p2p_peer_group_capability(
1638 const struct wpa_dbus_property_desc *property_desc,
1639 DBusMessageIter *iter, DBusError *error, void *user_data)
1641 struct peer_handler_args *peer_args = user_data;
1642 const struct p2p_peer_info *info;
1644 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1645 peer_args->p2p_device_addr, 0);
1647 dbus_set_error(error, DBUS_ERROR_FAILED,
1648 "failed to find peer");
1652 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BYTE,
1653 &info->group_capab, error)) {
1654 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1662 dbus_bool_t wpas_dbus_getter_p2p_peer_secondary_device_types(
1663 const struct wpa_dbus_property_desc *property_desc,
1664 DBusMessageIter *iter, DBusError *error, void *user_data)
1666 struct peer_handler_args *peer_args = user_data;
1667 const struct p2p_peer_info *info;
1668 DBusMessageIter variant_iter, array_iter;
1670 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1671 peer_args->p2p_device_addr, 0);
1673 dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer");
1677 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
1678 DBUS_TYPE_ARRAY_AS_STRING
1679 DBUS_TYPE_ARRAY_AS_STRING
1680 DBUS_TYPE_BYTE_AS_STRING,
1682 !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
1683 DBUS_TYPE_ARRAY_AS_STRING
1684 DBUS_TYPE_BYTE_AS_STRING,
1686 dbus_set_error(error, DBUS_ERROR_FAILED,
1687 "%s: failed to construct message 1", __func__);
1691 if (info->wps_sec_dev_type_list_len) {
1692 const u8 *sec_dev_type_list = info->wps_sec_dev_type_list;
1693 int num_sec_device_types =
1694 info->wps_sec_dev_type_list_len / WPS_DEV_TYPE_LEN;
1696 DBusMessageIter inner_array_iter;
1698 for (i = 0; i < num_sec_device_types; i++) {
1699 if (!dbus_message_iter_open_container(
1700 &array_iter, DBUS_TYPE_ARRAY,
1701 DBUS_TYPE_BYTE_AS_STRING,
1702 &inner_array_iter) ||
1703 !dbus_message_iter_append_fixed_array(
1704 &inner_array_iter, DBUS_TYPE_BYTE,
1705 &sec_dev_type_list, WPS_DEV_TYPE_LEN) ||
1706 !dbus_message_iter_close_container(
1707 &array_iter, &inner_array_iter)) {
1708 dbus_set_error(error, DBUS_ERROR_FAILED,
1709 "%s: failed to construct message 2 (%d)",
1714 sec_dev_type_list += WPS_DEV_TYPE_LEN;
1718 if (!dbus_message_iter_close_container(&variant_iter, &array_iter) ||
1719 !dbus_message_iter_close_container(iter, &variant_iter)) {
1720 dbus_set_error(error, DBUS_ERROR_FAILED,
1721 "%s: failed to construct message 3", __func__);
1729 dbus_bool_t wpas_dbus_getter_p2p_peer_vendor_extension(
1730 const struct wpa_dbus_property_desc *property_desc,
1731 DBusMessageIter *iter, DBusError *error, void *user_data)
1733 struct wpabuf *vendor_extension[P2P_MAX_WPS_VENDOR_EXT];
1734 unsigned int i, num = 0;
1735 struct peer_handler_args *peer_args = user_data;
1736 const struct p2p_peer_info *info;
1738 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1739 peer_args->p2p_device_addr, 0);
1741 dbus_set_error(error, DBUS_ERROR_FAILED,
1742 "failed to find peer");
1746 /* Add WPS vendor extensions attribute */
1747 os_memset(vendor_extension, 0, sizeof(vendor_extension));
1748 for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
1749 if (info->wps_vendor_ext[i] == NULL)
1751 vendor_extension[num] = info->wps_vendor_ext[i];
1755 if (!wpas_dbus_simple_array_array_property_getter(iter, DBUS_TYPE_BYTE,
1764 dbus_bool_t wpas_dbus_getter_p2p_peer_ies(
1765 const struct wpa_dbus_property_desc *property_desc,
1766 DBusMessageIter *iter, DBusError *error, void *user_data)
1768 struct peer_handler_args *peer_args = user_data;
1769 const struct p2p_peer_info *info;
1771 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1772 peer_args->p2p_device_addr, 0);
1774 dbus_set_error(error, DBUS_ERROR_FAILED,
1775 "failed to find peer");
1779 if (info->wfd_subelems == NULL)
1780 return wpas_dbus_simple_array_property_getter(iter,
1784 return wpas_dbus_simple_array_property_getter(
1785 iter, DBUS_TYPE_BYTE, (char *) info->wfd_subelems->buf,
1786 info->wfd_subelems->used, error);
1790 dbus_bool_t wpas_dbus_getter_p2p_peer_device_address(
1791 const struct wpa_dbus_property_desc *property_desc,
1792 DBusMessageIter *iter, DBusError *error, void *user_data)
1794 struct peer_handler_args *peer_args = user_data;
1795 const struct p2p_peer_info *info;
1797 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1798 peer_args->p2p_device_addr, 0);
1800 dbus_set_error(error, DBUS_ERROR_FAILED,
1801 "failed to find peer");
1805 return wpas_dbus_simple_array_property_getter(
1806 iter, DBUS_TYPE_BYTE, (char *) info->p2p_device_addr,
1811 struct peer_group_data {
1812 struct wpa_supplicant *wpa_s;
1813 const struct p2p_peer_info *info;
1815 unsigned int nb_paths;
1820 static int match_group_where_peer_is_client(struct p2p_group *group,
1823 struct peer_group_data *data = user_data;
1824 const struct p2p_group_config *cfg;
1825 struct wpa_supplicant *wpa_s_go;
1828 if (!p2p_group_is_client_connected(group, data->info->p2p_device_addr))
1831 cfg = p2p_group_get_config(group);
1833 wpa_s_go = wpas_get_p2p_go_iface(data->wpa_s, cfg->ssid,
1835 if (wpa_s_go == NULL)
1838 paths = os_realloc_array(data->paths, data->nb_paths + 1,
1843 data->paths = paths;
1844 data->paths[data->nb_paths] = wpa_s_go->dbus_groupobj_path;
1850 data->error = ENOMEM;
1855 dbus_bool_t wpas_dbus_getter_p2p_peer_groups(
1856 const struct wpa_dbus_property_desc *property_desc,
1857 DBusMessageIter *iter, DBusError *error, void *user_data)
1859 struct peer_handler_args *peer_args = user_data;
1860 const struct p2p_peer_info *info;
1861 struct peer_group_data data;
1862 struct wpa_supplicant *wpa_s, *wpa_s_go;
1863 dbus_bool_t success = FALSE;
1865 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1866 peer_args->p2p_device_addr, 0);
1868 dbus_set_error(error, DBUS_ERROR_FAILED,
1869 "failed to find peer");
1873 os_memset(&data, 0, sizeof(data));
1875 wpa_s = peer_args->wpa_s;
1876 wpa_s = wpa_s->global->p2p_init_wpa_s;
1878 wpa_s_go = wpas_get_p2p_client_iface(wpa_s, info->p2p_device_addr);
1880 data.paths = os_calloc(1, sizeof(char *));
1881 if (data.paths == NULL)
1883 data.paths[0] = wpa_s_go->dbus_groupobj_path;
1887 data.wpa_s = peer_args->wpa_s;
1890 p2p_loop_on_all_groups(peer_args->wpa_s->global->p2p,
1891 match_group_where_peer_is_client, &data);
1895 if (data.paths == NULL) {
1896 return wpas_dbus_simple_array_property_getter(
1897 iter, DBUS_TYPE_OBJECT_PATH, NULL, 0, error);
1900 success = wpas_dbus_simple_array_property_getter(iter,
1901 DBUS_TYPE_OBJECT_PATH,
1903 data.nb_paths, error);
1907 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1909 os_free(data.paths);
1915 * wpas_dbus_getter_persistent_groups - Get array of persistent group objects
1916 * @iter: Pointer to incoming dbus message iter
1917 * @error: Location to store error on failure
1918 * @user_data: Function specific data
1919 * Returns: TRUE on success, FALSE on failure
1921 * Getter for "PersistentGroups" property.
1923 dbus_bool_t wpas_dbus_getter_persistent_groups(
1924 const struct wpa_dbus_property_desc *property_desc,
1925 DBusMessageIter *iter, DBusError *error, void *user_data)
1927 struct wpa_supplicant *wpa_s = user_data;
1928 struct wpa_ssid *ssid;
1930 unsigned int i = 0, num = 0;
1931 dbus_bool_t success = FALSE;
1933 wpa_s = wpa_s->global->p2p_init_wpa_s;
1934 if (!wpa_s->parent->dbus_new_path)
1937 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
1938 if (network_is_persistent_group(ssid))
1941 paths = os_calloc(num, sizeof(char *));
1943 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1947 /* Loop through configured networks and append object path of each */
1948 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1949 if (!network_is_persistent_group(ssid))
1951 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1952 if (paths[i] == NULL) {
1953 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
1957 /* Construct the object path for this network. */
1958 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
1959 "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%d",
1960 wpa_s->parent->dbus_new_path, ssid->id);
1963 success = wpas_dbus_simple_array_property_getter(iter,
1964 DBUS_TYPE_OBJECT_PATH,
1969 os_free(paths[--i]);
1976 * wpas_dbus_getter_persistent_group_properties - Get options for a persistent
1978 * @iter: Pointer to incoming dbus message iter
1979 * @error: Location to store error on failure
1980 * @user_data: Function specific data
1981 * Returns: TRUE on success, FALSE on failure
1983 * Getter for "Properties" property of a persistent group.
1985 dbus_bool_t wpas_dbus_getter_persistent_group_properties(
1986 const struct wpa_dbus_property_desc *property_desc,
1987 DBusMessageIter *iter, DBusError *error, void *user_data)
1989 struct network_handler_args *net = user_data;
1991 /* Leveraging the fact that persistent group object is still
1992 * represented in same manner as network within.
1994 return wpas_dbus_getter_network_properties(property_desc, iter, error, net);
1999 * wpas_dbus_setter_persistent_group_properties - Set options for a persistent
2001 * @iter: Pointer to incoming dbus message iter
2002 * @error: Location to store error on failure
2003 * @user_data: Function specific data
2004 * Returns: TRUE on success, FALSE on failure
2006 * Setter for "Properties" property of a persistent group.
2008 dbus_bool_t wpas_dbus_setter_persistent_group_properties(
2009 const struct wpa_dbus_property_desc *property_desc,
2010 DBusMessageIter *iter, DBusError *error, void *user_data)
2012 struct network_handler_args *net = user_data;
2013 struct wpa_ssid *ssid = net->ssid;
2014 DBusMessageIter variant_iter;
2017 * Leveraging the fact that persistent group object is still
2018 * represented in same manner as network within.
2020 dbus_message_iter_recurse(iter, &variant_iter);
2021 return set_network_properties(net->wpa_s, ssid, &variant_iter, error);
2026 * wpas_dbus_new_iface_add_persistent_group - Add a new configured
2028 * @message: Pointer to incoming dbus message
2029 * @wpa_s: wpa_supplicant structure for a network interface
2030 * Returns: A dbus message containing the object path of the new
2033 * Handler function for "AddPersistentGroup" method call of a P2P Device
2036 DBusMessage * wpas_dbus_handler_add_persistent_group(
2037 DBusMessage *message, struct wpa_supplicant *wpa_s)
2039 DBusMessage *reply = NULL;
2040 DBusMessageIter iter;
2041 struct wpa_ssid *ssid = NULL;
2042 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf;
2045 dbus_message_iter_init(message, &iter);
2047 wpa_s = wpa_s->global->p2p_init_wpa_s;
2048 if (wpa_s->parent->dbus_new_path)
2049 ssid = wpa_config_add_network(wpa_s->conf);
2051 wpa_printf(MSG_ERROR,
2052 "dbus: %s: Cannot add new persistent group",
2054 reply = wpas_dbus_error_unknown_error(
2056 "wpa_supplicant could not add a persistent group on this interface.");
2060 /* Mark the ssid as being a persistent group before the notification */
2062 ssid->p2p_persistent_group = 1;
2063 wpas_notify_persistent_group_added(wpa_s, ssid);
2065 wpa_config_set_network_defaults(ssid);
2067 dbus_error_init(&error);
2068 if (!set_network_properties(wpa_s, ssid, &iter, &error)) {
2069 wpa_printf(MSG_DEBUG,
2070 "dbus: %s: Control interface could not set persistent group properties",
2072 reply = wpas_dbus_reply_new_from_error(
2073 message, &error, DBUS_ERROR_INVALID_ARGS,
2074 "Failed to set network properties");
2075 dbus_error_free(&error);
2079 /* Construct the object path for this network. */
2080 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
2081 "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%d",
2082 wpa_s->parent->dbus_new_path, ssid->id);
2084 reply = dbus_message_new_method_return(message);
2085 if (reply == NULL) {
2086 reply = wpas_dbus_error_no_memory(message);
2089 if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
2090 DBUS_TYPE_INVALID)) {
2091 dbus_message_unref(reply);
2092 reply = wpas_dbus_error_no_memory(message);
2100 wpas_notify_persistent_group_removed(wpa_s, ssid);
2101 wpa_config_remove_network(wpa_s->conf, ssid->id);
2108 * wpas_dbus_handler_remove_persistent_group - Remove a configured persistent
2110 * @message: Pointer to incoming dbus message
2111 * @wpa_s: wpa_supplicant structure for a network interface
2112 * Returns: NULL on success or dbus error on failure
2114 * Handler function for "RemovePersistentGroup" method call of a P2P Device
2117 DBusMessage * wpas_dbus_handler_remove_persistent_group(
2118 DBusMessage *message, struct wpa_supplicant *wpa_s)
2120 DBusMessage *reply = NULL;
2122 char *iface = NULL, *persistent_group_id;
2124 struct wpa_ssid *ssid;
2126 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
2129 wpa_s = wpa_s->global->p2p_init_wpa_s;
2132 * Extract the network ID and ensure the network is actually a child of
2135 iface = wpas_dbus_new_decompose_object_path(
2136 op, WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART,
2137 &persistent_group_id);
2138 if (iface == NULL || persistent_group_id == NULL ||
2139 !wpa_s->parent->dbus_new_path ||
2140 os_strcmp(iface, wpa_s->parent->dbus_new_path) != 0) {
2141 reply = wpas_dbus_error_invalid_args(message, op);
2145 id = strtoul(persistent_group_id, NULL, 10);
2146 if (errno == EINVAL) {
2147 reply = wpas_dbus_error_invalid_args(message, op);
2151 ssid = wpa_config_get_network(wpa_s->conf, id);
2153 reply = wpas_dbus_error_persistent_group_unknown(message);
2157 wpas_notify_persistent_group_removed(wpa_s, ssid);
2159 if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
2160 wpa_printf(MSG_ERROR,
2161 "dbus: %s: error occurred when removing persistent group %d",
2163 reply = wpas_dbus_error_unknown_error(
2165 "error removing the specified persistent group on this interface.");
2175 static void remove_persistent_group(struct wpa_supplicant *wpa_s,
2176 struct wpa_ssid *ssid)
2178 wpas_notify_persistent_group_removed(wpa_s, ssid);
2180 if (wpa_config_remove_network(wpa_s->conf, ssid->id) < 0) {
2181 wpa_printf(MSG_ERROR,
2182 "dbus: %s: error occurred when removing persistent group %d",
2183 __func__, ssid->id);
2190 * wpas_dbus_handler_remove_all_persistent_groups - Remove all configured
2192 * @message: Pointer to incoming dbus message
2193 * @wpa_s: wpa_supplicant structure for a network interface
2194 * Returns: NULL on success or dbus error on failure
2196 * Handler function for "RemoveAllPersistentGroups" method call of a
2197 * P2P Device interface.
2199 DBusMessage * wpas_dbus_handler_remove_all_persistent_groups(
2200 DBusMessage *message, struct wpa_supplicant *wpa_s)
2202 struct wpa_ssid *ssid, *next;
2203 struct wpa_config *config;
2205 wpa_s = wpa_s->global->p2p_init_wpa_s;
2207 config = wpa_s->conf;
2208 ssid = config->ssid;
2211 if (network_is_persistent_group(ssid))
2212 remove_persistent_group(wpa_s, ssid);
2220 * Group object properties accessor methods
2223 dbus_bool_t wpas_dbus_getter_p2p_group_members(
2224 const struct wpa_dbus_property_desc *property_desc,
2225 DBusMessageIter *iter, DBusError *error, void *user_data)
2227 struct wpa_supplicant *wpa_s = user_data;
2228 struct wpa_ssid *ssid;
2229 unsigned int num_members;
2234 dbus_bool_t success = FALSE;
2236 if (!wpa_s->parent->parent->dbus_new_path)
2239 /* Verify correct role for this property */
2240 if (wpas_get_p2p_role(wpa_s) != WPAS_P2P_ROLE_GO) {
2241 return wpas_dbus_simple_array_property_getter(
2242 iter, DBUS_TYPE_OBJECT_PATH, NULL, 0, error);
2245 ssid = wpa_s->conf->ssid;
2246 /* At present WPAS P2P_GO mode only applicable for p2p_go */
2247 if (ssid->mode != WPAS_MODE_P2P_GO &&
2248 ssid->mode != WPAS_MODE_AP &&
2249 ssid->mode != WPAS_MODE_P2P_GROUP_FORMATION)
2252 num_members = p2p_get_group_num_members(wpa_s->p2p_group);
2254 paths = os_calloc(num_members, sizeof(char *));
2259 while ((addr = p2p_iterate_group_members(wpa_s->p2p_group, &next))) {
2260 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
2263 os_snprintf(paths[i], WPAS_DBUS_OBJECT_PATH_MAX,
2264 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART
2266 wpa_s->parent->parent->dbus_new_path,
2271 success = wpas_dbus_simple_array_property_getter(iter,
2272 DBUS_TYPE_OBJECT_PATH,
2276 for (i = 0; i < num_members; i++)
2282 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
2284 for (i = 0; i < num_members; i++)
2292 dbus_bool_t wpas_dbus_getter_p2p_group_ssid(
2293 const struct wpa_dbus_property_desc *property_desc,
2294 DBusMessageIter *iter, DBusError *error, void *user_data)
2296 struct wpa_supplicant *wpa_s = user_data;
2298 if (wpa_s->current_ssid == NULL)
2300 return wpas_dbus_simple_array_property_getter(
2301 iter, DBUS_TYPE_BYTE, wpa_s->current_ssid->ssid,
2302 wpa_s->current_ssid->ssid_len, error);
2306 dbus_bool_t wpas_dbus_getter_p2p_group_bssid(
2307 const struct wpa_dbus_property_desc *property_desc,
2308 DBusMessageIter *iter, DBusError *error, void *user_data)
2310 struct wpa_supplicant *wpa_s = user_data;
2311 u8 role = wpas_get_p2p_role(wpa_s);
2314 if (role == WPAS_P2P_ROLE_CLIENT) {
2315 if (wpa_s->current_ssid == NULL)
2317 p_bssid = wpa_s->current_ssid->bssid;
2319 if (wpa_s->ap_iface == NULL)
2321 p_bssid = wpa_s->ap_iface->bss[0]->own_addr;
2324 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
2330 dbus_bool_t wpas_dbus_getter_p2p_group_frequency(
2331 const struct wpa_dbus_property_desc *property_desc,
2332 DBusMessageIter *iter, DBusError *error, void *user_data)
2334 struct wpa_supplicant *wpa_s = user_data;
2336 u8 role = wpas_get_p2p_role(wpa_s);
2338 if (role == WPAS_P2P_ROLE_CLIENT) {
2339 if (wpa_s->go_params == NULL)
2341 op_freq = wpa_s->go_params->freq;
2343 if (wpa_s->ap_iface == NULL)
2345 op_freq = wpa_s->ap_iface->freq;
2348 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
2353 dbus_bool_t wpas_dbus_getter_p2p_group_passphrase(
2354 const struct wpa_dbus_property_desc *property_desc,
2355 DBusMessageIter *iter, DBusError *error, void *user_data)
2357 struct wpa_supplicant *wpa_s = user_data;
2358 struct wpa_ssid *ssid = wpa_s->current_ssid;
2363 return wpas_dbus_string_property_getter(iter, ssid->passphrase, error);
2367 dbus_bool_t wpas_dbus_getter_p2p_group_psk(
2368 const struct wpa_dbus_property_desc *property_desc,
2369 DBusMessageIter *iter, DBusError *error, void *user_data)
2371 struct wpa_supplicant *wpa_s = user_data;
2374 struct wpa_ssid *ssid = wpa_s->current_ssid;
2379 if (ssid->psk_set) {
2381 psk_len = sizeof(ssid->psk);
2384 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
2385 p_psk, psk_len, error);
2389 dbus_bool_t wpas_dbus_getter_p2p_group_vendor_ext(
2390 const struct wpa_dbus_property_desc *property_desc,
2391 DBusMessageIter *iter, DBusError *error, void *user_data)
2393 struct wpa_supplicant *wpa_s = user_data;
2394 struct hostapd_data *hapd;
2395 struct wpabuf *vendor_ext[MAX_WPS_VENDOR_EXTENSIONS];
2396 unsigned int i, num_vendor_ext = 0;
2398 os_memset(vendor_ext, 0, sizeof(vendor_ext));
2400 /* Verify correct role for this property */
2401 if (wpas_get_p2p_role(wpa_s) == WPAS_P2P_ROLE_GO) {
2402 if (wpa_s->ap_iface == NULL)
2404 hapd = wpa_s->ap_iface->bss[0];
2406 /* Parse WPS Vendor Extensions sent in Beacon/Probe Response */
2407 for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
2408 if (hapd->conf->wps_vendor_ext[i] == NULL)
2410 vendor_ext[num_vendor_ext++] =
2411 hapd->conf->wps_vendor_ext[i];
2415 /* Return vendor extensions or no data */
2416 return wpas_dbus_simple_array_array_property_getter(iter,
2424 dbus_bool_t wpas_dbus_setter_p2p_group_vendor_ext(
2425 const struct wpa_dbus_property_desc *property_desc,
2426 DBusMessageIter *iter, DBusError *error, void *user_data)
2428 struct wpa_supplicant *wpa_s = user_data;
2429 DBusMessageIter variant_iter, iter_dict, array_iter, sub;
2430 struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
2432 struct hostapd_data *hapd = NULL;
2434 if (wpas_get_p2p_role(wpa_s) == WPAS_P2P_ROLE_GO &&
2435 wpa_s->ap_iface != NULL)
2436 hapd = wpa_s->ap_iface->bss[0];
2440 dbus_message_iter_recurse(iter, &variant_iter);
2441 if (dbus_message_iter_get_arg_type(&variant_iter) != DBUS_TYPE_ARRAY)
2445 * This is supposed to be array of bytearrays (aay), but the earlier
2446 * implementation used a dict with "WPSVendorExtensions" as the key in
2447 * this setter function which does not match the format used by the
2448 * getter function. For backwards compatibility, allow both formats to
2449 * be used in the setter.
2451 if (dbus_message_iter_get_element_type(&variant_iter) ==
2453 /* This is the proper format matching the getter */
2454 struct wpabuf *vals[MAX_WPS_VENDOR_EXTENSIONS];
2456 dbus_message_iter_recurse(&variant_iter, &array_iter);
2458 if (dbus_message_iter_get_arg_type(&array_iter) !=
2460 dbus_message_iter_get_element_type(&array_iter) !=
2462 wpa_printf(MSG_DEBUG,
2463 "dbus: Not an array of array of bytes");
2468 os_memset(vals, 0, sizeof(vals));
2470 while (dbus_message_iter_get_arg_type(&array_iter) ==
2475 if (i == MAX_WPS_VENDOR_EXTENSIONS) {
2476 wpa_printf(MSG_DEBUG,
2477 "dbus: Too many WPSVendorExtensions values");
2478 i = MAX_WPS_VENDOR_EXTENSIONS + 1;
2482 dbus_message_iter_recurse(&array_iter, &sub);
2483 dbus_message_iter_get_fixed_array(&sub, &val, &len);
2484 wpa_hexdump(MSG_DEBUG, "dbus: WPSVendorExtentions[]",
2486 vals[i] = wpabuf_alloc_copy(val, len);
2487 if (vals[i] == NULL) {
2488 i = MAX_WPS_VENDOR_EXTENSIONS + 1;
2492 dbus_message_iter_next(&array_iter);
2495 if (i > MAX_WPS_VENDOR_EXTENSIONS) {
2496 for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++)
2497 wpabuf_free(vals[i]);
2501 for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
2502 wpabuf_free(hapd->conf->wps_vendor_ext[i]);
2503 hapd->conf->wps_vendor_ext[i] = vals[i];
2506 hostapd_update_wps(hapd);
2511 if (dbus_message_iter_get_element_type(&variant_iter) !=
2512 DBUS_TYPE_DICT_ENTRY)
2515 wpa_printf(MSG_DEBUG,
2516 "dbus: Try to use backwards compatibility version of WPSVendorExtensions setter");
2517 if (!wpa_dbus_dict_open_read(&variant_iter, &iter_dict, error))
2520 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2521 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) {
2522 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
2523 "invalid message format");
2527 if (os_strcmp(entry.key, "WPSVendorExtensions") == 0) {
2528 if (entry.type != DBUS_TYPE_ARRAY ||
2529 entry.array_type != WPAS_DBUS_TYPE_BINARRAY ||
2530 entry.array_len > MAX_WPS_VENDOR_EXTENSIONS)
2533 for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
2534 wpabuf_free(hapd->conf->wps_vendor_ext[i]);
2535 if (i < entry.array_len) {
2536 hapd->conf->wps_vendor_ext[i] =
2537 entry.binarray_value[i];
2538 entry.binarray_value[i] = NULL;
2540 hapd->conf->wps_vendor_ext[i] = NULL;
2543 hostapd_update_wps(hapd);
2547 wpa_dbus_dict_entry_clear(&entry);
2553 wpa_dbus_dict_entry_clear(&entry);
2554 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
2555 "invalid message format");
2560 DBusMessage * wpas_dbus_handler_p2p_add_service(DBusMessage *message,
2561 struct wpa_supplicant *wpa_s)
2563 DBusMessageIter iter_dict;
2564 DBusMessage *reply = NULL;
2565 DBusMessageIter iter;
2566 struct wpa_dbus_dict_entry entry;
2569 char *service = NULL;
2570 struct wpabuf *query = NULL;
2571 struct wpabuf *resp = NULL;
2574 dbus_message_iter_init(message, &iter);
2576 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
2579 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2580 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2583 if (os_strcmp(entry.key, "service_type") == 0 &&
2584 entry.type == DBUS_TYPE_STRING) {
2585 if (os_strcmp(entry.str_value, "upnp") == 0)
2587 else if (os_strcmp(entry.str_value, "bonjour") == 0)
2591 } else if (os_strcmp(entry.key, "version") == 0 &&
2592 entry.type == DBUS_TYPE_INT32) {
2593 version = entry.uint32_value;
2594 } else if (os_strcmp(entry.key, "service") == 0 &&
2595 entry.type == DBUS_TYPE_STRING) {
2597 service = os_strdup(entry.str_value);
2598 } else if (os_strcmp(entry.key, "query") == 0) {
2599 if (entry.type != DBUS_TYPE_ARRAY ||
2600 entry.array_type != DBUS_TYPE_BYTE)
2602 query = wpabuf_alloc_copy(
2603 entry.bytearray_value,
2605 } else if (os_strcmp(entry.key, "response") == 0) {
2606 if (entry.type != DBUS_TYPE_ARRAY ||
2607 entry.array_type != DBUS_TYPE_BYTE)
2609 resp = wpabuf_alloc_copy(entry.bytearray_value,
2612 wpa_dbus_dict_entry_clear(&entry);
2616 if (version <= 0 || service == NULL)
2619 if (wpas_p2p_service_add_upnp(wpa_s, version, service) != 0)
2622 } else if (bonjour == 1) {
2623 if (query == NULL || resp == NULL)
2626 if (wpas_p2p_service_add_bonjour(wpa_s, query, resp) < 0)
2636 wpa_dbus_dict_entry_clear(&entry);
2641 return wpas_dbus_error_invalid_args(message, NULL);
2645 DBusMessage * wpas_dbus_handler_p2p_delete_service(
2646 DBusMessage *message, struct wpa_supplicant *wpa_s)
2648 DBusMessageIter iter_dict;
2649 DBusMessage *reply = NULL;
2650 DBusMessageIter iter;
2651 struct wpa_dbus_dict_entry entry;
2655 char *service = NULL;
2656 struct wpabuf *query = NULL;
2659 dbus_message_iter_init(message, &iter);
2661 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
2664 if (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2665 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2668 if (os_strcmp(entry.key, "service_type") == 0 &&
2669 entry.type == DBUS_TYPE_STRING) {
2670 if (os_strcmp(entry.str_value, "upnp") == 0)
2672 else if (os_strcmp(entry.str_value, "bonjour") == 0)
2676 wpa_dbus_dict_entry_clear(&entry);
2680 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2681 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2683 if (os_strcmp(entry.key, "version") == 0 &&
2684 entry.type == DBUS_TYPE_INT32)
2685 version = entry.uint32_value;
2686 else if (os_strcmp(entry.key, "service") == 0 &&
2687 entry.type == DBUS_TYPE_STRING) {
2689 service = os_strdup(entry.str_value);
2693 wpa_dbus_dict_entry_clear(&entry);
2696 if (version <= 0 || service == NULL)
2699 ret = wpas_p2p_service_del_upnp(wpa_s, version, service);
2702 } else if (bonjour == 1) {
2703 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2704 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2707 if (os_strcmp(entry.key, "query") == 0) {
2708 if (entry.type != DBUS_TYPE_ARRAY ||
2709 entry.array_type != DBUS_TYPE_BYTE)
2712 query = wpabuf_alloc_copy(
2713 entry.bytearray_value,
2718 wpa_dbus_dict_entry_clear(&entry);
2724 ret = wpas_p2p_service_del_bonjour(wpa_s, query);
2734 wpa_dbus_dict_entry_clear(&entry);
2738 return wpas_dbus_error_invalid_args(message, NULL);
2742 DBusMessage * wpas_dbus_handler_p2p_flush_service(DBusMessage *message,
2743 struct wpa_supplicant *wpa_s)
2745 wpas_p2p_service_flush(wpa_s);
2750 DBusMessage * wpas_dbus_handler_p2p_service_sd_req(
2751 DBusMessage *message, struct wpa_supplicant *wpa_s)
2753 DBusMessageIter iter_dict;
2754 DBusMessage *reply = NULL;
2755 DBusMessageIter iter;
2756 struct wpa_dbus_dict_entry entry;
2758 char *service = NULL;
2759 char *peer_object_path = NULL;
2760 struct wpabuf *tlv = NULL;
2763 u8 addr_buf[ETH_ALEN], *addr;
2765 dbus_message_iter_init(message, &iter);
2767 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
2770 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2771 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2773 if (os_strcmp(entry.key, "peer_object") == 0 &&
2774 entry.type == DBUS_TYPE_OBJECT_PATH) {
2775 peer_object_path = os_strdup(entry.str_value);
2776 } else if (os_strcmp(entry.key, "service_type") == 0 &&
2777 entry.type == DBUS_TYPE_STRING) {
2778 if (os_strcmp(entry.str_value, "upnp") == 0)
2782 } else if (os_strcmp(entry.key, "version") == 0 &&
2783 entry.type == DBUS_TYPE_INT32) {
2784 version = entry.uint32_value;
2785 } else if (os_strcmp(entry.key, "service") == 0 &&
2786 entry.type == DBUS_TYPE_STRING) {
2787 service = os_strdup(entry.str_value);
2788 } else if (os_strcmp(entry.key, "tlv") == 0) {
2789 if (entry.type != DBUS_TYPE_ARRAY ||
2790 entry.array_type != DBUS_TYPE_BYTE)
2792 tlv = wpabuf_alloc_copy(entry.bytearray_value,
2797 wpa_dbus_dict_entry_clear(&entry);
2800 if (!peer_object_path) {
2803 if (parse_peer_object_path(peer_object_path, addr_buf) < 0 ||
2804 !p2p_peer_known(wpa_s->global->p2p, addr_buf))
2811 if (version <= 0 || service == NULL)
2814 ref = wpas_p2p_sd_request_upnp(wpa_s, addr, version, service);
2818 ref = wpas_p2p_sd_request(wpa_s, addr, tlv);
2823 reply = dbus_message_new_method_return(message);
2824 dbus_message_append_args(reply, DBUS_TYPE_UINT64,
2825 &ref, DBUS_TYPE_INVALID);
2827 reply = wpas_dbus_error_unknown_error(
2828 message, "Unable to send SD request");
2832 os_free(peer_object_path);
2835 wpa_dbus_dict_entry_clear(&entry);
2839 reply = wpas_dbus_error_invalid_args(message, NULL);
2844 DBusMessage * wpas_dbus_handler_p2p_service_sd_res(
2845 DBusMessage *message, struct wpa_supplicant *wpa_s)
2847 DBusMessageIter iter_dict;
2848 DBusMessage *reply = NULL;
2849 DBusMessageIter iter;
2850 struct wpa_dbus_dict_entry entry;
2851 char *peer_object_path = NULL;
2852 struct wpabuf *tlv = NULL;
2857 dbus_message_iter_init(message, &iter);
2859 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
2862 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2863 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2866 if (os_strcmp(entry.key, "peer_object") == 0 &&
2867 entry.type == DBUS_TYPE_OBJECT_PATH) {
2868 peer_object_path = os_strdup(entry.str_value);
2869 } else if (os_strcmp(entry.key, "frequency") == 0 &&
2870 entry.type == DBUS_TYPE_INT32) {
2871 freq = entry.uint32_value;
2872 } else if (os_strcmp(entry.key, "dialog_token") == 0 &&
2873 (entry.type == DBUS_TYPE_UINT32 ||
2874 entry.type == DBUS_TYPE_INT32)) {
2875 dlg_tok = entry.uint32_value;
2876 } else if (os_strcmp(entry.key, "tlvs") == 0) {
2877 if (entry.type != DBUS_TYPE_ARRAY ||
2878 entry.array_type != DBUS_TYPE_BYTE)
2880 tlv = wpabuf_alloc_copy(entry.bytearray_value,
2885 wpa_dbus_dict_entry_clear(&entry);
2887 if (parse_peer_object_path(peer_object_path, addr) < 0 ||
2888 !p2p_peer_known(wpa_s->global->p2p, addr) ||
2892 wpas_p2p_sd_response(wpa_s, freq, addr, (u8) dlg_tok, tlv);
2895 os_free(peer_object_path);
2898 wpa_dbus_dict_entry_clear(&entry);
2900 reply = wpas_dbus_error_invalid_args(message, NULL);
2905 DBusMessage * wpas_dbus_handler_p2p_service_sd_cancel_req(
2906 DBusMessage *message, struct wpa_supplicant *wpa_s)
2908 DBusMessageIter iter;
2911 dbus_message_iter_init(message, &iter);
2912 dbus_message_iter_get_basic(&iter, &req);
2917 if (wpas_p2p_sd_cancel_request(wpa_s, req) < 0)
2922 return wpas_dbus_error_invalid_args(message, NULL);
2926 DBusMessage * wpas_dbus_handler_p2p_service_update(
2927 DBusMessage *message, struct wpa_supplicant *wpa_s)
2929 wpas_p2p_sd_service_update(wpa_s);
2934 DBusMessage * wpas_dbus_handler_p2p_serv_disc_external(
2935 DBusMessage *message, struct wpa_supplicant *wpa_s)
2937 DBusMessageIter iter;
2940 dbus_message_iter_init(message, &iter);
2941 dbus_message_iter_get_basic(&iter, &ext);
2943 wpa_s->p2p_sd_over_ctrl_iface = ext;
2950 #ifdef CONFIG_WIFI_DISPLAY
2952 dbus_bool_t wpas_dbus_getter_global_wfd_ies(
2953 const struct wpa_dbus_property_desc *property_desc,
2954 DBusMessageIter *iter, DBusError *error, void *user_data)
2956 struct wpa_global *global = user_data;
2960 ie = wifi_display_get_wfd_ie(global);
2962 return wpas_dbus_simple_array_property_getter(iter,
2966 ret = wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
2968 wpabuf_len(ie), error);
2975 dbus_bool_t wpas_dbus_setter_global_wfd_ies(
2976 const struct wpa_dbus_property_desc *property_desc,
2977 DBusMessageIter *iter, DBusError *error, void *user_data)
2979 struct wpa_global *global = user_data;
2980 DBusMessageIter variant, array;
2981 struct wpabuf *ie = NULL;
2985 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_VARIANT)
2988 dbus_message_iter_recurse(iter, &variant);
2989 if (dbus_message_iter_get_arg_type(&variant) != DBUS_TYPE_ARRAY)
2992 dbus_message_iter_recurse(&variant, &array);
2993 dbus_message_iter_get_fixed_array(&array, &data, &len);
2995 wifi_display_enable(global, 0);
2996 wifi_display_deinit(global);
3001 ie = wpabuf_alloc(len);
3005 wpabuf_put_data(ie, data, len);
3006 if (wifi_display_subelem_set_from_ies(global, ie) != 0)
3009 if (global->wifi_display == 0)
3010 wifi_display_enable(global, 1);
3018 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
3019 "invalid message format");
3023 #endif /* CONFIG_WIFI_DISPLAY */