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,
387 0, 0, 0, NULL, 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 wpas_p2p_stop_find(wpa_s);
509 os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
510 wpa_s->force_long_sd = 0;
511 p2p_flush(wpa_s->global->p2p);
517 DBusMessage * wpas_dbus_handler_p2p_connect(DBusMessage *message,
518 struct wpa_supplicant *wpa_s)
520 DBusMessageIter iter_dict;
521 DBusMessage *reply = NULL;
522 DBusMessageIter iter;
523 struct wpa_dbus_dict_entry entry;
524 char *peer_object_path = NULL;
525 int persistent_group = 0;
527 int authorize_only = 0;
532 enum p2p_wps_method wps_method = WPS_NOT_READY;
534 char *err_msg = NULL;
538 if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL))
541 dbus_message_iter_init(message, &iter);
543 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
546 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
547 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
550 if (os_strcmp(entry.key, "peer") == 0 &&
551 entry.type == DBUS_TYPE_OBJECT_PATH) {
552 peer_object_path = os_strdup(entry.str_value);
553 } else if (os_strcmp(entry.key, "persistent") == 0 &&
554 entry.type == DBUS_TYPE_BOOLEAN) {
555 persistent_group = entry.bool_value;
556 } else if (os_strcmp(entry.key, "join") == 0 &&
557 entry.type == DBUS_TYPE_BOOLEAN) {
558 join = entry.bool_value;
559 } else if (os_strcmp(entry.key, "authorize_only") == 0 &&
560 entry.type == DBUS_TYPE_BOOLEAN) {
561 authorize_only = entry.bool_value;
562 } else if (os_strcmp(entry.key, "frequency") == 0 &&
563 entry.type == DBUS_TYPE_INT32) {
564 freq = entry.int32_value;
567 } else if (os_strcmp(entry.key, "go_intent") == 0 &&
568 entry.type == DBUS_TYPE_INT32) {
569 go_intent = entry.int32_value;
570 if ((go_intent < 0) || (go_intent > 15))
572 } else if (os_strcmp(entry.key, "wps_method") == 0 &&
573 entry.type == DBUS_TYPE_STRING) {
574 if (os_strcmp(entry.str_value, "pbc") == 0)
575 wps_method = WPS_PBC;
576 else if (os_strcmp(entry.str_value, "pin") == 0)
577 wps_method = WPS_PIN_DISPLAY;
578 else if (os_strcmp(entry.str_value, "display") == 0)
579 wps_method = WPS_PIN_DISPLAY;
580 else if (os_strcmp(entry.str_value, "keypad") == 0)
581 wps_method = WPS_PIN_KEYPAD;
584 } else if (os_strcmp(entry.key, "pin") == 0 &&
585 entry.type == DBUS_TYPE_STRING) {
586 pin = os_strdup(entry.str_value);
590 wpa_dbus_dict_entry_clear(&entry);
593 if (wps_method == WPS_NOT_READY ||
594 parse_peer_object_path(peer_object_path, addr) < 0 ||
595 !p2p_peer_known(wpa_s->global->p2p, addr))
599 * Validate the wps_method specified and the pin value.
601 if ((!pin || !pin[0]) && wps_method == WPS_PIN_KEYPAD)
604 wpa_s = wpa_s->global->p2p_init_wpa_s;
606 new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
607 persistent_group, 0, join, authorize_only,
608 go_intent, freq, 0, -1, 0, 0, 0, 0, 0,
615 ret = os_snprintf(npin, sizeof(npin), "%08d", new_pin);
616 if (os_snprintf_error(sizeof(npin), ret)) {
617 reply = wpas_dbus_error_unknown_error(message,
621 generated_pin = npin;
622 reply = dbus_message_new_method_return(message);
623 dbus_message_append_args(reply, DBUS_TYPE_STRING,
624 &generated_pin, DBUS_TYPE_INVALID);
629 "connect failed due to channel unavailability.";
630 iface = WPAS_DBUS_ERROR_CONNECT_CHANNEL_UNAVAILABLE;
634 err_msg = "connect failed due to unsupported channel.";
635 iface = WPAS_DBUS_ERROR_CONNECT_CHANNEL_UNSUPPORTED;
639 err_msg = "connect failed due to unspecified error.";
640 iface = WPAS_DBUS_ERROR_CONNECT_UNSPECIFIED_ERROR;
646 * Do we need specialized errors corresponding to above
647 * error conditions as against just returning a different
650 reply = dbus_message_new_error(message, iface, err_msg);
654 os_free(peer_object_path);
658 wpa_dbus_dict_entry_clear(&entry);
660 reply = wpas_dbus_error_invalid_args(message, NULL);
666 * wpas_dbus_handler_p2p_cancel - Cancel P2P group formation
667 * @message: Pointer to incoming dbus message
668 * @wpa_s: %wpa_supplicant data structure
669 * Returns: NULL on success or DBus error on failure
671 * Handler for "Cancel" method call. Returns NULL if P2P cancel succeeds or DBus
672 * error on P2P cancel failure
674 DBusMessage * wpas_dbus_handler_p2p_cancel(DBusMessage *message,
675 struct wpa_supplicant *wpa_s)
677 if (wpas_p2p_cancel(wpa_s))
678 return wpas_dbus_error_unknown_error(message,
679 "P2P cancel failed");
685 DBusMessage * wpas_dbus_handler_p2p_invite(DBusMessage *message,
686 struct wpa_supplicant *wpa_s)
688 DBusMessageIter iter_dict;
689 DBusMessage *reply = NULL;
690 DBusMessageIter iter;
691 struct wpa_dbus_dict_entry entry;
692 char *peer_object_path = NULL;
693 char *pg_object_path = NULL;
695 u8 peer_addr[ETH_ALEN];
696 unsigned int group_id = 0;
698 struct wpa_ssid *ssid;
700 if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL))
703 dbus_message_iter_init(message, &iter);
705 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
708 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
709 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
712 if (os_strcmp(entry.key, "peer") == 0 &&
713 entry.type == DBUS_TYPE_OBJECT_PATH) {
714 peer_object_path = os_strdup(entry.str_value);
715 wpa_dbus_dict_entry_clear(&entry);
716 } else if (os_strcmp(entry.key, "persistent_group_object") ==
718 entry.type == DBUS_TYPE_OBJECT_PATH) {
719 pg_object_path = os_strdup(entry.str_value);
721 wpa_dbus_dict_entry_clear(&entry);
723 wpa_dbus_dict_entry_clear(&entry);
728 if (parse_peer_object_path(peer_object_path, peer_addr) < 0 ||
729 !p2p_peer_known(wpa_s->global->p2p, peer_addr))
732 wpa_s = wpa_s->global->p2p_init_wpa_s;
737 * A group ID is defined meaning we want to re-invoke a
741 iface = wpas_dbus_new_decompose_object_path(
743 WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART,
745 if (iface == NULL || net_id_str == NULL ||
746 !wpa_s->parent->dbus_new_path ||
747 os_strcmp(iface, wpa_s->parent->dbus_new_path) != 0) {
748 reply = wpas_dbus_error_invalid_args(message,
753 group_id = strtoul(net_id_str, NULL, 10);
754 if (errno == EINVAL) {
755 reply = wpas_dbus_error_invalid_args(
756 message, pg_object_path);
760 /* Get the SSID structure from the persistent group id */
761 ssid = wpa_config_get_network(wpa_s->conf, group_id);
762 if (ssid == NULL || ssid->disabled != 2)
765 if (wpas_p2p_invite(wpa_s, peer_addr, ssid, NULL, 0, 0, 0, 0, 0,
767 reply = wpas_dbus_error_unknown_error(
769 "Failed to reinvoke a persistent group");
774 * No group ID means propose to a peer to join my active group
776 if (wpas_p2p_invite_group(wpa_s, wpa_s->ifname,
778 reply = wpas_dbus_error_unknown_error(
779 message, "Failed to join to an active group");
786 os_free(pg_object_path);
787 os_free(peer_object_path);
791 reply = wpas_dbus_error_invalid_args(message, NULL);
796 DBusMessage * wpas_dbus_handler_p2p_prov_disc_req(DBusMessage *message,
797 struct wpa_supplicant *wpa_s)
799 DBusMessageIter iter;
800 char *peer_object_path = NULL;
801 char *config_method = NULL;
802 u8 peer_addr[ETH_ALEN];
804 dbus_message_iter_init(message, &iter);
805 dbus_message_iter_get_basic(&iter, &peer_object_path);
807 if (parse_peer_object_path(peer_object_path, peer_addr) < 0)
808 return wpas_dbus_error_invalid_args(message, NULL);
810 dbus_message_iter_next(&iter);
811 dbus_message_iter_get_basic(&iter, &config_method);
814 * Validation checks on config_method are being duplicated here
815 * to be able to return invalid args reply since the error code
816 * from p2p module are not granular enough (yet).
818 if (os_strcmp(config_method, "display") &&
819 os_strcmp(config_method, "keypad") &&
820 os_strcmp(config_method, "pbc") &&
821 os_strcmp(config_method, "pushbutton"))
822 return wpas_dbus_error_invalid_args(message, NULL);
824 wpa_s = wpa_s->global->p2p_init_wpa_s;
826 if (wpas_p2p_prov_disc(wpa_s, peer_addr, config_method,
827 WPAS_P2P_PD_FOR_GO_NEG, NULL) < 0)
828 return wpas_dbus_error_unknown_error(message,
829 "Failed to send provision discovery request");
836 * P2P Device property accessor methods.
839 dbus_bool_t wpas_dbus_getter_p2p_device_config(
840 const struct wpa_dbus_property_desc *property_desc,
841 DBusMessageIter *iter, DBusError *error, void *user_data)
843 struct wpa_supplicant *wpa_s = user_data;
844 DBusMessageIter variant_iter, dict_iter;
845 DBusMessageIter iter_secdev_dict_entry, iter_secdev_dict_val,
846 iter_secdev_dict_array;
847 const char *dev_name;
848 int num_vendor_extensions = 0;
850 const struct wpabuf *vendor_ext[P2P_MAX_WPS_VENDOR_EXT];
852 if (!wpa_dbus_p2p_check_enabled(wpa_s, NULL, NULL, error))
855 wpa_s = wpa_s->global->p2p_init_wpa_s;
857 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
858 "a{sv}", &variant_iter) ||
859 !wpa_dbus_dict_open_write(&variant_iter, &dict_iter))
863 dev_name = wpa_s->conf->device_name;
865 !wpa_dbus_dict_append_string(&dict_iter, "DeviceName", dev_name))
868 /* Primary device type */
869 if (!wpa_dbus_dict_append_byte_array(&dict_iter, "PrimaryDeviceType",
870 (char *) wpa_s->conf->device_type,
874 /* Secondary device types */
875 if (wpa_s->conf->num_sec_device_types) {
876 if (!wpa_dbus_dict_begin_array(&dict_iter,
877 "SecondaryDeviceTypes",
878 DBUS_TYPE_ARRAY_AS_STRING
879 DBUS_TYPE_BYTE_AS_STRING,
880 &iter_secdev_dict_entry,
881 &iter_secdev_dict_val,
882 &iter_secdev_dict_array))
885 for (i = 0; i < wpa_s->conf->num_sec_device_types; i++)
886 wpa_dbus_dict_bin_array_add_element(
887 &iter_secdev_dict_array,
888 wpa_s->conf->sec_device_type[i],
891 if (!wpa_dbus_dict_end_array(&dict_iter,
892 &iter_secdev_dict_entry,
893 &iter_secdev_dict_val,
894 &iter_secdev_dict_array))
899 if (WPA_GET_BE32(wpa_s->conf->ip_addr_go) &&
900 !wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddrGo",
901 (char *) wpa_s->conf->ip_addr_go,
905 /* IP address mask */
906 if (WPA_GET_BE32(wpa_s->conf->ip_addr_mask) &&
907 !wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddrMask",
908 (char *) wpa_s->conf->ip_addr_mask,
912 /* IP address start */
913 if (WPA_GET_BE32(wpa_s->conf->ip_addr_start) &&
914 !wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddrStart",
916 wpa_s->conf->ip_addr_start,
921 if (WPA_GET_BE32(wpa_s->conf->ip_addr_end) &&
922 !wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddrEnd",
923 (char *) wpa_s->conf->ip_addr_end,
927 /* Vendor Extensions */
928 for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
929 if (wpa_s->conf->wps_vendor_ext[i] == NULL)
931 vendor_ext[num_vendor_extensions++] =
932 wpa_s->conf->wps_vendor_ext[i];
935 if ((num_vendor_extensions &&
936 !wpa_dbus_dict_append_wpabuf_array(&dict_iter,
939 num_vendor_extensions)) ||
940 !wpa_dbus_dict_append_uint32(&dict_iter, "GOIntent",
941 wpa_s->conf->p2p_go_intent) ||
942 !wpa_dbus_dict_append_bool(&dict_iter, "PersistentReconnect",
943 wpa_s->conf->persistent_reconnect) ||
944 !wpa_dbus_dict_append_uint32(&dict_iter, "ListenRegClass",
945 wpa_s->conf->p2p_listen_reg_class) ||
946 !wpa_dbus_dict_append_uint32(&dict_iter, "ListenChannel",
947 wpa_s->conf->p2p_listen_channel) ||
948 !wpa_dbus_dict_append_uint32(&dict_iter, "OperRegClass",
949 wpa_s->conf->p2p_oper_reg_class) ||
950 !wpa_dbus_dict_append_uint32(&dict_iter, "OperChannel",
951 wpa_s->conf->p2p_oper_channel) ||
952 (wpa_s->conf->p2p_ssid_postfix &&
953 !wpa_dbus_dict_append_string(&dict_iter, "SsidPostfix",
954 wpa_s->conf->p2p_ssid_postfix)) ||
955 !wpa_dbus_dict_append_bool(&dict_iter, "IntraBss",
956 wpa_s->conf->p2p_intra_bss) ||
957 !wpa_dbus_dict_append_uint32(&dict_iter, "GroupIdle",
958 wpa_s->conf->p2p_group_idle) ||
959 !wpa_dbus_dict_append_uint32(&dict_iter, "disassoc_low_ack",
960 wpa_s->conf->disassoc_low_ack) ||
961 !wpa_dbus_dict_append_bool(&dict_iter, "NoGroupIface",
962 wpa_s->conf->p2p_no_group_iface) ||
963 !wpa_dbus_dict_append_uint32(&dict_iter, "p2p_search_delay",
964 wpa_s->conf->p2p_search_delay) ||
965 !wpa_dbus_dict_close_write(&variant_iter, &dict_iter) ||
966 !dbus_message_iter_close_container(iter, &variant_iter))
972 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
977 dbus_bool_t wpas_dbus_setter_p2p_device_config(
978 const struct wpa_dbus_property_desc *property_desc,
979 DBusMessageIter *iter, DBusError *error, void *user_data)
981 struct wpa_supplicant *wpa_s = user_data;
982 DBusMessageIter variant_iter, iter_dict;
983 struct wpa_dbus_dict_entry entry = {.type = DBUS_TYPE_STRING };
986 if (!wpa_dbus_p2p_check_enabled(wpa_s, NULL, NULL, error))
989 wpa_s = wpa_s->global->p2p_init_wpa_s;
991 dbus_message_iter_recurse(iter, &variant_iter);
992 if (!wpa_dbus_dict_open_read(&variant_iter, &iter_dict, error))
995 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
996 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) {
997 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
998 "invalid message format");
1002 if (os_strcmp(entry.key, "DeviceName") == 0) {
1005 if (entry.type != DBUS_TYPE_STRING ||
1006 os_strlen(entry.str_value) > WPS_DEV_NAME_MAX_LEN)
1009 devname = os_strdup(entry.str_value);
1010 if (devname == NULL)
1011 goto err_no_mem_clear;
1013 os_free(wpa_s->conf->device_name);
1014 wpa_s->conf->device_name = devname;
1016 wpa_s->conf->changed_parameters |=
1017 CFG_CHANGED_DEVICE_NAME;
1018 } else if (os_strcmp(entry.key, "PrimaryDeviceType") == 0) {
1019 if (entry.type != DBUS_TYPE_ARRAY ||
1020 entry.array_type != DBUS_TYPE_BYTE ||
1021 entry.array_len != WPS_DEV_TYPE_LEN)
1024 os_memcpy(wpa_s->conf->device_type,
1025 entry.bytearray_value,
1027 wpa_s->conf->changed_parameters |=
1028 CFG_CHANGED_DEVICE_TYPE;
1029 } else if (os_strcmp(entry.key, "SecondaryDeviceTypes") == 0) {
1030 if (entry.type != DBUS_TYPE_ARRAY ||
1031 entry.array_type != WPAS_DBUS_TYPE_BINARRAY ||
1032 entry.array_len > MAX_SEC_DEVICE_TYPES)
1035 for (i = 0; i < entry.array_len; i++)
1036 if (wpabuf_len(entry.binarray_value[i]) !=
1038 goto err_no_mem_clear;
1039 for (i = 0; i < entry.array_len; i++)
1040 os_memcpy(wpa_s->conf->sec_device_type[i],
1041 wpabuf_head(entry.binarray_value[i]),
1043 wpa_s->conf->num_sec_device_types = entry.array_len;
1044 wpa_s->conf->changed_parameters |=
1045 CFG_CHANGED_SEC_DEVICE_TYPE;
1046 } else if (os_strcmp(entry.key, "VendorExtension") == 0) {
1047 if (entry.type != DBUS_TYPE_ARRAY ||
1048 entry.array_type != WPAS_DBUS_TYPE_BINARRAY ||
1049 (entry.array_len > P2P_MAX_WPS_VENDOR_EXT))
1052 wpa_s->conf->changed_parameters |=
1053 CFG_CHANGED_VENDOR_EXTENSION;
1055 for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
1056 wpabuf_free(wpa_s->conf->wps_vendor_ext[i]);
1057 if (i < entry.array_len) {
1058 wpa_s->conf->wps_vendor_ext[i] =
1059 entry.binarray_value[i];
1060 entry.binarray_value[i] = NULL;
1062 wpa_s->conf->wps_vendor_ext[i] = NULL;
1064 } else if (os_strcmp(entry.key, "GOIntent") == 0 &&
1065 entry.type == DBUS_TYPE_UINT32 &&
1066 (entry.uint32_value <= 15))
1067 wpa_s->conf->p2p_go_intent = entry.uint32_value;
1068 else if (os_strcmp(entry.key, "PersistentReconnect") == 0 &&
1069 entry.type == DBUS_TYPE_BOOLEAN)
1070 wpa_s->conf->persistent_reconnect = entry.bool_value;
1071 else if (os_strcmp(entry.key, "ListenRegClass") == 0 &&
1072 entry.type == DBUS_TYPE_UINT32) {
1073 wpa_s->conf->p2p_listen_reg_class = entry.uint32_value;
1074 wpa_s->conf->changed_parameters |=
1075 CFG_CHANGED_P2P_LISTEN_CHANNEL;
1076 } else if (os_strcmp(entry.key, "ListenChannel") == 0 &&
1077 entry.type == DBUS_TYPE_UINT32) {
1078 wpa_s->conf->p2p_listen_channel = entry.uint32_value;
1079 wpa_s->conf->changed_parameters |=
1080 CFG_CHANGED_P2P_LISTEN_CHANNEL;
1081 } else if (os_strcmp(entry.key, "OperRegClass") == 0 &&
1082 entry.type == DBUS_TYPE_UINT32) {
1083 wpa_s->conf->p2p_oper_reg_class = entry.uint32_value;
1084 wpa_s->conf->changed_parameters |=
1085 CFG_CHANGED_P2P_OPER_CHANNEL;
1086 } else if (os_strcmp(entry.key, "OperChannel") == 0 &&
1087 entry.type == DBUS_TYPE_UINT32) {
1088 wpa_s->conf->p2p_oper_channel = entry.uint32_value;
1089 wpa_s->conf->changed_parameters |=
1090 CFG_CHANGED_P2P_OPER_CHANNEL;
1091 } else if (os_strcmp(entry.key, "SsidPostfix") == 0) {
1094 if (entry.type != DBUS_TYPE_STRING)
1097 postfix = os_strdup(entry.str_value);
1099 goto err_no_mem_clear;
1101 os_free(wpa_s->conf->p2p_ssid_postfix);
1102 wpa_s->conf->p2p_ssid_postfix = postfix;
1104 wpa_s->conf->changed_parameters |=
1105 CFG_CHANGED_P2P_SSID_POSTFIX;
1106 } else if (os_strcmp(entry.key, "IntraBss") == 0 &&
1107 entry.type == DBUS_TYPE_BOOLEAN) {
1108 wpa_s->conf->p2p_intra_bss = entry.bool_value;
1109 wpa_s->conf->changed_parameters |=
1110 CFG_CHANGED_P2P_INTRA_BSS;
1111 } else if (os_strcmp(entry.key, "IpAddrGo") == 0) {
1112 if (!wpas_dbus_validate_dbus_ipaddr(entry))
1114 os_memcpy(wpa_s->conf->ip_addr_go,
1115 entry.bytearray_value, 4);
1116 } else if (os_strcmp(entry.key, "IpAddrMask") == 0) {
1117 if (!wpas_dbus_validate_dbus_ipaddr(entry))
1119 os_memcpy(wpa_s->conf->ip_addr_mask,
1120 entry.bytearray_value, 4);
1121 } else if (os_strcmp(entry.key, "IpAddrStart") == 0) {
1122 if (!wpas_dbus_validate_dbus_ipaddr(entry))
1124 os_memcpy(wpa_s->conf->ip_addr_start,
1125 entry.bytearray_value, 4);
1126 } else if (os_strcmp(entry.key, "IpAddrEnd") == 0) {
1127 if (!wpas_dbus_validate_dbus_ipaddr(entry))
1129 os_memcpy(wpa_s->conf->ip_addr_end,
1130 entry.bytearray_value, 4);
1131 } else if (os_strcmp(entry.key, "GroupIdle") == 0 &&
1132 entry.type == DBUS_TYPE_UINT32)
1133 wpa_s->conf->p2p_group_idle = entry.uint32_value;
1134 else if (os_strcmp(entry.key, "disassoc_low_ack") == 0 &&
1135 entry.type == DBUS_TYPE_UINT32)
1136 wpa_s->conf->disassoc_low_ack = entry.uint32_value;
1137 else if (os_strcmp(entry.key, "NoGroupIface") == 0 &&
1138 entry.type == DBUS_TYPE_BOOLEAN)
1139 wpa_s->conf->p2p_no_group_iface = entry.bool_value;
1140 else if (os_strcmp(entry.key, "p2p_search_delay") == 0 &&
1141 entry.type == DBUS_TYPE_UINT32)
1142 wpa_s->conf->p2p_search_delay = entry.uint32_value;
1146 wpa_dbus_dict_entry_clear(&entry);
1149 if (wpa_s->conf->changed_parameters) {
1150 /* Some changed parameters requires to update config*/
1151 wpa_supplicant_update_config(wpa_s);
1157 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
1158 "invalid message format");
1159 wpa_dbus_dict_entry_clear(&entry);
1163 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1164 wpa_dbus_dict_entry_clear(&entry);
1169 dbus_bool_t wpas_dbus_getter_p2p_peers(
1170 const struct wpa_dbus_property_desc *property_desc,
1171 DBusMessageIter *iter, DBusError *error, void *user_data)
1173 struct wpa_supplicant *wpa_s = user_data;
1174 struct p2p_data *p2p = wpa_s->global->p2p;
1175 int next = 0, i = 0;
1176 int num = 0, out_of_mem = 0;
1178 const struct p2p_peer_info *peer_info = NULL;
1179 dbus_bool_t success = FALSE;
1181 struct dl_list peer_objpath_list;
1182 struct peer_objpath_node {
1183 struct dl_list list;
1184 char path[WPAS_DBUS_OBJECT_PATH_MAX];
1187 char **peer_obj_paths = NULL;
1189 if (!wpa_dbus_p2p_check_enabled(wpa_s, NULL, NULL, error) ||
1190 !wpa_s->parent->parent->dbus_new_path)
1193 dl_list_init(&peer_objpath_list);
1195 /* Get the first peer info */
1196 peer_info = p2p_get_peer_found(p2p, NULL, next);
1198 /* Get next and accumulate them */
1200 while (peer_info != NULL) {
1201 node = os_zalloc(sizeof(struct peer_objpath_node));
1207 addr = peer_info->p2p_device_addr;
1208 os_snprintf(node->path, WPAS_DBUS_OBJECT_PATH_MAX,
1209 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART
1211 wpa_s->parent->parent->dbus_new_path,
1213 dl_list_add_tail(&peer_objpath_list, &node->list);
1216 peer_info = p2p_get_peer_found(p2p, addr, next);
1220 * Now construct the peer object paths in a form suitable for
1221 * array_property_getter helper below.
1223 peer_obj_paths = os_calloc(num, sizeof(char *));
1225 if (!peer_obj_paths) {
1230 dl_list_for_each_safe(node, tmp, &peer_objpath_list,
1231 struct peer_objpath_node, list)
1232 peer_obj_paths[i++] = node->path;
1234 success = wpas_dbus_simple_array_property_getter(iter,
1235 DBUS_TYPE_OBJECT_PATH,
1236 peer_obj_paths, num,
1241 os_free(peer_obj_paths);
1243 dl_list_for_each_safe(node, tmp, &peer_objpath_list,
1244 struct peer_objpath_node, list) {
1245 dl_list_del(&node->list);
1249 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1255 enum wpas_p2p_role {
1256 WPAS_P2P_ROLE_DEVICE,
1258 WPAS_P2P_ROLE_CLIENT,
1261 static enum wpas_p2p_role wpas_get_p2p_role(struct wpa_supplicant *wpa_s)
1263 struct wpa_ssid *ssid = wpa_s->current_ssid;
1266 return WPAS_P2P_ROLE_DEVICE;
1267 if (wpa_s->wpa_state != WPA_COMPLETED)
1268 return WPAS_P2P_ROLE_DEVICE;
1270 switch (ssid->mode) {
1271 case WPAS_MODE_P2P_GO:
1272 case WPAS_MODE_P2P_GROUP_FORMATION:
1273 return WPAS_P2P_ROLE_GO;
1274 case WPAS_MODE_INFRA:
1275 if (ssid->p2p_group)
1276 return WPAS_P2P_ROLE_CLIENT;
1277 return WPAS_P2P_ROLE_DEVICE;
1279 return WPAS_P2P_ROLE_DEVICE;
1284 dbus_bool_t wpas_dbus_getter_p2p_role(
1285 const struct wpa_dbus_property_desc *property_desc,
1286 DBusMessageIter *iter, DBusError *error, void *user_data)
1288 struct wpa_supplicant *wpa_s = user_data;
1291 switch (wpas_get_p2p_role(wpa_s)) {
1292 case WPAS_P2P_ROLE_GO:
1295 case WPAS_P2P_ROLE_CLIENT:
1303 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &str,
1308 dbus_bool_t wpas_dbus_getter_p2p_group(
1309 const struct wpa_dbus_property_desc *property_desc,
1310 DBusMessageIter *iter, DBusError *error, void *user_data)
1312 struct wpa_supplicant *wpa_s = user_data;
1313 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX];
1314 char *dbus_groupobj_path = path_buf;
1316 if (wpa_s->dbus_groupobj_path == NULL)
1317 os_snprintf(dbus_groupobj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1320 os_snprintf(dbus_groupobj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1321 "%s", wpa_s->dbus_groupobj_path);
1323 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
1324 &dbus_groupobj_path, error);
1328 dbus_bool_t wpas_dbus_getter_p2p_peergo(
1329 const struct wpa_dbus_property_desc *property_desc,
1330 DBusMessageIter *iter, DBusError *error, void *user_data)
1332 struct wpa_supplicant *wpa_s = user_data;
1333 char go_peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1335 if (!wpa_s->parent->parent->dbus_new_path)
1338 if (wpas_get_p2p_role(wpa_s) != WPAS_P2P_ROLE_CLIENT)
1339 os_snprintf(go_peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
1341 os_snprintf(go_peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1342 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
1344 wpa_s->parent->parent->dbus_new_path,
1345 MAC2STR(wpa_s->go_dev_addr));
1347 path = go_peer_obj_path;
1348 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
1354 * Peer object properties accessor methods
1357 dbus_bool_t wpas_dbus_getter_p2p_peer_device_name(
1358 const struct wpa_dbus_property_desc *property_desc,
1359 DBusMessageIter *iter, DBusError *error, void *user_data)
1361 struct peer_handler_args *peer_args = user_data;
1362 const struct p2p_peer_info *info;
1365 if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error))
1368 /* get the peer info */
1369 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1370 peer_args->p2p_device_addr, 0);
1372 dbus_set_error(error, DBUS_ERROR_FAILED,
1373 "failed to find peer");
1377 tmp = os_strdup(info->device_name);
1379 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1383 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp,
1385 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1395 dbus_bool_t wpas_dbus_getter_p2p_peer_manufacturer(
1396 const struct wpa_dbus_property_desc *property_desc,
1397 DBusMessageIter *iter, DBusError *error, void *user_data)
1399 struct peer_handler_args *peer_args = user_data;
1400 const struct p2p_peer_info *info;
1403 if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error))
1406 /* get the peer info */
1407 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1408 peer_args->p2p_device_addr, 0);
1410 dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer");
1414 tmp = os_strdup(info->manufacturer);
1416 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1420 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp,
1422 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1432 dbus_bool_t wpas_dbus_getter_p2p_peer_modelname(
1433 const struct wpa_dbus_property_desc *property_desc,
1434 DBusMessageIter *iter, DBusError *error, void *user_data)
1436 struct peer_handler_args *peer_args = user_data;
1437 const struct p2p_peer_info *info;
1440 if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error))
1443 /* get the peer info */
1444 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1445 peer_args->p2p_device_addr, 0);
1447 dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer");
1451 tmp = os_strdup(info->model_name);
1453 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1457 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp,
1459 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1469 dbus_bool_t wpas_dbus_getter_p2p_peer_modelnumber(
1470 const struct wpa_dbus_property_desc *property_desc,
1471 DBusMessageIter *iter, DBusError *error, void *user_data)
1473 struct peer_handler_args *peer_args = user_data;
1474 const struct p2p_peer_info *info;
1477 if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error))
1480 /* get the peer info */
1481 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1482 peer_args->p2p_device_addr, 0);
1484 dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer");
1488 tmp = os_strdup(info->model_number);
1490 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1494 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp,
1496 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1506 dbus_bool_t wpas_dbus_getter_p2p_peer_serialnumber(
1507 const struct wpa_dbus_property_desc *property_desc,
1508 DBusMessageIter *iter, DBusError *error, void *user_data)
1510 struct peer_handler_args *peer_args = user_data;
1511 const struct p2p_peer_info *info;
1514 if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error))
1517 /* get the peer info */
1518 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1519 peer_args->p2p_device_addr, 0);
1521 dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer");
1525 tmp = os_strdup(info->serial_number);
1527 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1531 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp,
1533 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1543 dbus_bool_t wpas_dbus_getter_p2p_peer_primary_device_type(
1544 const struct wpa_dbus_property_desc *property_desc,
1545 DBusMessageIter *iter, DBusError *error, void *user_data)
1547 struct peer_handler_args *peer_args = user_data;
1548 const struct p2p_peer_info *info;
1550 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1551 peer_args->p2p_device_addr, 0);
1553 dbus_set_error(error, DBUS_ERROR_FAILED,
1554 "failed to find peer");
1558 if (!wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
1561 WPS_DEV_TYPE_LEN, error)) {
1562 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1570 dbus_bool_t wpas_dbus_getter_p2p_peer_config_method(
1571 const struct wpa_dbus_property_desc *property_desc,
1572 DBusMessageIter *iter, DBusError *error, void *user_data)
1574 struct peer_handler_args *peer_args = user_data;
1575 const struct p2p_peer_info *info;
1577 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1578 peer_args->p2p_device_addr, 0);
1580 dbus_set_error(error, DBUS_ERROR_FAILED,
1581 "failed to find peer");
1585 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
1586 &info->config_methods, error)) {
1587 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1595 dbus_bool_t wpas_dbus_getter_p2p_peer_level(
1596 const struct wpa_dbus_property_desc *property_desc,
1597 DBusMessageIter *iter, DBusError *error, void *user_data)
1599 struct peer_handler_args *peer_args = user_data;
1600 const struct p2p_peer_info *info;
1602 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1603 peer_args->p2p_device_addr, 0);
1605 dbus_set_error(error, DBUS_ERROR_FAILED,
1606 "failed to find peer");
1610 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
1611 &info->level, error)) {
1612 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1620 dbus_bool_t wpas_dbus_getter_p2p_peer_device_capability(
1621 const struct wpa_dbus_property_desc *property_desc,
1622 DBusMessageIter *iter, DBusError *error, void *user_data)
1624 struct peer_handler_args *peer_args = user_data;
1625 const struct p2p_peer_info *info;
1627 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1628 peer_args->p2p_device_addr, 0);
1630 dbus_set_error(error, DBUS_ERROR_FAILED,
1631 "failed to find peer");
1635 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BYTE,
1636 &info->dev_capab, error)) {
1637 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1645 dbus_bool_t wpas_dbus_getter_p2p_peer_group_capability(
1646 const struct wpa_dbus_property_desc *property_desc,
1647 DBusMessageIter *iter, DBusError *error, void *user_data)
1649 struct peer_handler_args *peer_args = user_data;
1650 const struct p2p_peer_info *info;
1652 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1653 peer_args->p2p_device_addr, 0);
1655 dbus_set_error(error, DBUS_ERROR_FAILED,
1656 "failed to find peer");
1660 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BYTE,
1661 &info->group_capab, error)) {
1662 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1670 dbus_bool_t wpas_dbus_getter_p2p_peer_secondary_device_types(
1671 const struct wpa_dbus_property_desc *property_desc,
1672 DBusMessageIter *iter, DBusError *error, void *user_data)
1674 struct peer_handler_args *peer_args = user_data;
1675 const struct p2p_peer_info *info;
1676 DBusMessageIter variant_iter, array_iter;
1678 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1679 peer_args->p2p_device_addr, 0);
1681 dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer");
1685 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
1686 DBUS_TYPE_ARRAY_AS_STRING
1687 DBUS_TYPE_ARRAY_AS_STRING
1688 DBUS_TYPE_BYTE_AS_STRING,
1690 !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
1691 DBUS_TYPE_ARRAY_AS_STRING
1692 DBUS_TYPE_BYTE_AS_STRING,
1694 dbus_set_error(error, DBUS_ERROR_FAILED,
1695 "%s: failed to construct message 1", __func__);
1699 if (info->wps_sec_dev_type_list_len) {
1700 const u8 *sec_dev_type_list = info->wps_sec_dev_type_list;
1701 int num_sec_device_types =
1702 info->wps_sec_dev_type_list_len / WPS_DEV_TYPE_LEN;
1704 DBusMessageIter inner_array_iter;
1706 for (i = 0; i < num_sec_device_types; i++) {
1707 if (!dbus_message_iter_open_container(
1708 &array_iter, DBUS_TYPE_ARRAY,
1709 DBUS_TYPE_BYTE_AS_STRING,
1710 &inner_array_iter) ||
1711 !dbus_message_iter_append_fixed_array(
1712 &inner_array_iter, DBUS_TYPE_BYTE,
1713 &sec_dev_type_list, WPS_DEV_TYPE_LEN) ||
1714 !dbus_message_iter_close_container(
1715 &array_iter, &inner_array_iter)) {
1716 dbus_set_error(error, DBUS_ERROR_FAILED,
1717 "%s: failed to construct message 2 (%d)",
1722 sec_dev_type_list += WPS_DEV_TYPE_LEN;
1726 if (!dbus_message_iter_close_container(&variant_iter, &array_iter) ||
1727 !dbus_message_iter_close_container(iter, &variant_iter)) {
1728 dbus_set_error(error, DBUS_ERROR_FAILED,
1729 "%s: failed to construct message 3", __func__);
1737 dbus_bool_t wpas_dbus_getter_p2p_peer_vendor_extension(
1738 const struct wpa_dbus_property_desc *property_desc,
1739 DBusMessageIter *iter, DBusError *error, void *user_data)
1741 struct wpabuf *vendor_extension[P2P_MAX_WPS_VENDOR_EXT];
1742 unsigned int i, num = 0;
1743 struct peer_handler_args *peer_args = user_data;
1744 const struct p2p_peer_info *info;
1746 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1747 peer_args->p2p_device_addr, 0);
1749 dbus_set_error(error, DBUS_ERROR_FAILED,
1750 "failed to find peer");
1754 /* Add WPS vendor extensions attribute */
1755 os_memset(vendor_extension, 0, sizeof(vendor_extension));
1756 for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
1757 if (info->wps_vendor_ext[i] == NULL)
1759 vendor_extension[num] = info->wps_vendor_ext[i];
1763 if (!wpas_dbus_simple_array_array_property_getter(iter, DBUS_TYPE_BYTE,
1772 dbus_bool_t wpas_dbus_getter_p2p_peer_ies(
1773 const struct wpa_dbus_property_desc *property_desc,
1774 DBusMessageIter *iter, DBusError *error, void *user_data)
1776 struct peer_handler_args *peer_args = user_data;
1777 const struct p2p_peer_info *info;
1779 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1780 peer_args->p2p_device_addr, 0);
1782 dbus_set_error(error, DBUS_ERROR_FAILED,
1783 "failed to find peer");
1787 if (info->wfd_subelems == NULL)
1788 return wpas_dbus_simple_array_property_getter(iter,
1792 return wpas_dbus_simple_array_property_getter(
1793 iter, DBUS_TYPE_BYTE, (char *) info->wfd_subelems->buf,
1794 info->wfd_subelems->used, error);
1798 dbus_bool_t wpas_dbus_getter_p2p_peer_device_address(
1799 const struct wpa_dbus_property_desc *property_desc,
1800 DBusMessageIter *iter, DBusError *error, void *user_data)
1802 struct peer_handler_args *peer_args = user_data;
1803 const struct p2p_peer_info *info;
1805 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1806 peer_args->p2p_device_addr, 0);
1808 dbus_set_error(error, DBUS_ERROR_FAILED,
1809 "failed to find peer");
1813 return wpas_dbus_simple_array_property_getter(
1814 iter, DBUS_TYPE_BYTE, (char *) info->p2p_device_addr,
1819 struct peer_group_data {
1820 struct wpa_supplicant *wpa_s;
1821 const struct p2p_peer_info *info;
1823 unsigned int nb_paths;
1828 static int match_group_where_peer_is_client(struct p2p_group *group,
1831 struct peer_group_data *data = user_data;
1832 const struct p2p_group_config *cfg;
1833 struct wpa_supplicant *wpa_s_go;
1836 if (!p2p_group_is_client_connected(group, data->info->p2p_device_addr))
1839 cfg = p2p_group_get_config(group);
1841 wpa_s_go = wpas_get_p2p_go_iface(data->wpa_s, cfg->ssid,
1843 if (wpa_s_go == NULL)
1846 paths = os_realloc_array(data->paths, data->nb_paths + 1,
1851 data->paths = paths;
1852 data->paths[data->nb_paths] = wpa_s_go->dbus_groupobj_path;
1858 data->error = ENOMEM;
1863 dbus_bool_t wpas_dbus_getter_p2p_peer_groups(
1864 const struct wpa_dbus_property_desc *property_desc,
1865 DBusMessageIter *iter, DBusError *error, void *user_data)
1867 struct peer_handler_args *peer_args = user_data;
1868 const struct p2p_peer_info *info;
1869 struct peer_group_data data;
1870 struct wpa_supplicant *wpa_s, *wpa_s_go;
1871 dbus_bool_t success = FALSE;
1873 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1874 peer_args->p2p_device_addr, 0);
1876 dbus_set_error(error, DBUS_ERROR_FAILED,
1877 "failed to find peer");
1881 os_memset(&data, 0, sizeof(data));
1883 wpa_s = peer_args->wpa_s;
1884 wpa_s = wpa_s->global->p2p_init_wpa_s;
1886 wpa_s_go = wpas_get_p2p_client_iface(wpa_s, info->p2p_device_addr);
1888 data.paths = os_calloc(1, sizeof(char *));
1889 if (data.paths == NULL)
1891 data.paths[0] = wpa_s_go->dbus_groupobj_path;
1895 data.wpa_s = peer_args->wpa_s;
1898 p2p_loop_on_all_groups(peer_args->wpa_s->global->p2p,
1899 match_group_where_peer_is_client, &data);
1903 if (data.paths == NULL) {
1904 return wpas_dbus_simple_array_property_getter(
1905 iter, DBUS_TYPE_OBJECT_PATH, NULL, 0, error);
1908 success = wpas_dbus_simple_array_property_getter(iter,
1909 DBUS_TYPE_OBJECT_PATH,
1911 data.nb_paths, error);
1915 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1917 os_free(data.paths);
1921 dbus_bool_t wpas_dbus_getter_p2p_peer_vsie(
1922 const struct wpa_dbus_property_desc *property_desc,
1923 DBusMessageIter *iter, DBusError *error, void *user_data)
1925 struct peer_handler_args *peer_args = user_data;
1926 const struct p2p_peer_info *info;
1928 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1929 peer_args->p2p_device_addr, 0);
1931 dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer");
1935 if (!info->vendor_elems)
1936 return wpas_dbus_simple_array_property_getter(iter,
1940 return wpas_dbus_simple_array_property_getter(
1941 iter, DBUS_TYPE_BYTE, (char *) info->vendor_elems->buf,
1942 info->vendor_elems->used, error);
1947 * wpas_dbus_getter_persistent_groups - Get array of persistent group objects
1948 * @iter: Pointer to incoming dbus message iter
1949 * @error: Location to store error on failure
1950 * @user_data: Function specific data
1951 * Returns: TRUE on success, FALSE on failure
1953 * Getter for "PersistentGroups" property.
1955 dbus_bool_t wpas_dbus_getter_persistent_groups(
1956 const struct wpa_dbus_property_desc *property_desc,
1957 DBusMessageIter *iter, DBusError *error, void *user_data)
1959 struct wpa_supplicant *wpa_s = user_data;
1960 struct wpa_ssid *ssid;
1962 unsigned int i = 0, num = 0;
1963 dbus_bool_t success = FALSE;
1965 wpa_s = wpa_s->global->p2p_init_wpa_s;
1966 if (!wpa_s->parent->dbus_new_path)
1969 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
1970 if (network_is_persistent_group(ssid))
1973 paths = os_calloc(num, sizeof(char *));
1975 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1979 /* Loop through configured networks and append object path of each */
1980 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1981 if (!network_is_persistent_group(ssid))
1983 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1984 if (paths[i] == NULL) {
1985 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
1989 /* Construct the object path for this network. */
1990 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
1991 "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%d",
1992 wpa_s->parent->dbus_new_path, ssid->id);
1995 success = wpas_dbus_simple_array_property_getter(iter,
1996 DBUS_TYPE_OBJECT_PATH,
2001 os_free(paths[--i]);
2008 * wpas_dbus_getter_persistent_group_properties - Get options for a persistent
2010 * @iter: Pointer to incoming dbus message iter
2011 * @error: Location to store error on failure
2012 * @user_data: Function specific data
2013 * Returns: TRUE on success, FALSE on failure
2015 * Getter for "Properties" property of a persistent group.
2017 dbus_bool_t wpas_dbus_getter_persistent_group_properties(
2018 const struct wpa_dbus_property_desc *property_desc,
2019 DBusMessageIter *iter, DBusError *error, void *user_data)
2021 struct network_handler_args *net = user_data;
2023 /* Leveraging the fact that persistent group object is still
2024 * represented in same manner as network within.
2026 return wpas_dbus_getter_network_properties(property_desc, iter, error, net);
2031 * wpas_dbus_setter_persistent_group_properties - Set options for a persistent
2033 * @iter: Pointer to incoming dbus message iter
2034 * @error: Location to store error on failure
2035 * @user_data: Function specific data
2036 * Returns: TRUE on success, FALSE on failure
2038 * Setter for "Properties" property of a persistent group.
2040 dbus_bool_t wpas_dbus_setter_persistent_group_properties(
2041 const struct wpa_dbus_property_desc *property_desc,
2042 DBusMessageIter *iter, DBusError *error, void *user_data)
2044 struct network_handler_args *net = user_data;
2045 struct wpa_ssid *ssid = net->ssid;
2046 DBusMessageIter variant_iter;
2049 * Leveraging the fact that persistent group object is still
2050 * represented in same manner as network within.
2052 dbus_message_iter_recurse(iter, &variant_iter);
2053 return set_network_properties(net->wpa_s, ssid, &variant_iter, error);
2058 * wpas_dbus_new_iface_add_persistent_group - Add a new configured
2060 * @message: Pointer to incoming dbus message
2061 * @wpa_s: wpa_supplicant structure for a network interface
2062 * Returns: A dbus message containing the object path of the new
2065 * Handler function for "AddPersistentGroup" method call of a P2P Device
2068 DBusMessage * wpas_dbus_handler_add_persistent_group(
2069 DBusMessage *message, struct wpa_supplicant *wpa_s)
2071 DBusMessage *reply = NULL;
2072 DBusMessageIter iter;
2073 struct wpa_ssid *ssid = NULL;
2074 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf;
2077 dbus_message_iter_init(message, &iter);
2079 wpa_s = wpa_s->global->p2p_init_wpa_s;
2080 if (wpa_s->parent->dbus_new_path)
2081 ssid = wpa_config_add_network(wpa_s->conf);
2083 wpa_printf(MSG_ERROR,
2084 "dbus: %s: Cannot add new persistent group",
2086 reply = wpas_dbus_error_unknown_error(
2088 "wpa_supplicant could not add a persistent group on this interface.");
2092 /* Mark the ssid as being a persistent group before the notification */
2094 ssid->p2p_persistent_group = 1;
2095 wpas_notify_persistent_group_added(wpa_s, ssid);
2097 wpa_config_set_network_defaults(ssid);
2099 dbus_error_init(&error);
2100 if (!set_network_properties(wpa_s, ssid, &iter, &error)) {
2101 wpa_printf(MSG_DEBUG,
2102 "dbus: %s: Control interface could not set persistent group properties",
2104 reply = wpas_dbus_reply_new_from_error(
2105 message, &error, DBUS_ERROR_INVALID_ARGS,
2106 "Failed to set network properties");
2107 dbus_error_free(&error);
2111 /* Construct the object path for this network. */
2112 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
2113 "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%d",
2114 wpa_s->parent->dbus_new_path, ssid->id);
2116 reply = dbus_message_new_method_return(message);
2117 if (reply == NULL) {
2118 reply = wpas_dbus_error_no_memory(message);
2121 if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
2122 DBUS_TYPE_INVALID)) {
2123 dbus_message_unref(reply);
2124 reply = wpas_dbus_error_no_memory(message);
2132 wpas_notify_persistent_group_removed(wpa_s, ssid);
2133 wpa_config_remove_network(wpa_s->conf, ssid->id);
2140 * wpas_dbus_handler_remove_persistent_group - Remove a configured persistent
2142 * @message: Pointer to incoming dbus message
2143 * @wpa_s: wpa_supplicant structure for a network interface
2144 * Returns: NULL on success or dbus error on failure
2146 * Handler function for "RemovePersistentGroup" method call of a P2P Device
2149 DBusMessage * wpas_dbus_handler_remove_persistent_group(
2150 DBusMessage *message, struct wpa_supplicant *wpa_s)
2152 DBusMessage *reply = NULL;
2154 char *iface = NULL, *persistent_group_id;
2156 struct wpa_ssid *ssid;
2158 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
2161 wpa_s = wpa_s->global->p2p_init_wpa_s;
2164 * Extract the network ID and ensure the network is actually a child of
2167 iface = wpas_dbus_new_decompose_object_path(
2168 op, WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART,
2169 &persistent_group_id);
2170 if (iface == NULL || persistent_group_id == NULL ||
2171 !wpa_s->parent->dbus_new_path ||
2172 os_strcmp(iface, wpa_s->parent->dbus_new_path) != 0) {
2173 reply = wpas_dbus_error_invalid_args(message, op);
2177 id = strtoul(persistent_group_id, NULL, 10);
2178 if (errno == EINVAL) {
2179 reply = wpas_dbus_error_invalid_args(message, op);
2183 ssid = wpa_config_get_network(wpa_s->conf, id);
2185 reply = wpas_dbus_error_persistent_group_unknown(message);
2189 wpas_notify_persistent_group_removed(wpa_s, ssid);
2191 if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
2192 wpa_printf(MSG_ERROR,
2193 "dbus: %s: error occurred when removing persistent group %d",
2195 reply = wpas_dbus_error_unknown_error(
2197 "error removing the specified persistent group on this interface.");
2207 static void remove_persistent_group(struct wpa_supplicant *wpa_s,
2208 struct wpa_ssid *ssid)
2210 wpas_notify_persistent_group_removed(wpa_s, ssid);
2212 if (wpa_config_remove_network(wpa_s->conf, ssid->id) < 0) {
2213 wpa_printf(MSG_ERROR,
2214 "dbus: %s: error occurred when removing persistent group %d",
2215 __func__, ssid->id);
2222 * wpas_dbus_handler_remove_all_persistent_groups - Remove all configured
2224 * @message: Pointer to incoming dbus message
2225 * @wpa_s: wpa_supplicant structure for a network interface
2226 * Returns: NULL on success or dbus error on failure
2228 * Handler function for "RemoveAllPersistentGroups" method call of a
2229 * P2P Device interface.
2231 DBusMessage * wpas_dbus_handler_remove_all_persistent_groups(
2232 DBusMessage *message, struct wpa_supplicant *wpa_s)
2234 struct wpa_ssid *ssid, *next;
2235 struct wpa_config *config;
2237 wpa_s = wpa_s->global->p2p_init_wpa_s;
2239 config = wpa_s->conf;
2240 ssid = config->ssid;
2243 if (network_is_persistent_group(ssid))
2244 remove_persistent_group(wpa_s, ssid);
2252 * Group object properties accessor methods
2255 dbus_bool_t wpas_dbus_getter_p2p_group_members(
2256 const struct wpa_dbus_property_desc *property_desc,
2257 DBusMessageIter *iter, DBusError *error, void *user_data)
2259 struct wpa_supplicant *wpa_s = user_data;
2260 struct wpa_ssid *ssid;
2261 unsigned int num_members;
2266 dbus_bool_t success = FALSE;
2268 if (!wpa_s->parent->parent->dbus_new_path)
2271 /* Verify correct role for this property */
2272 if (wpas_get_p2p_role(wpa_s) != WPAS_P2P_ROLE_GO) {
2273 return wpas_dbus_simple_array_property_getter(
2274 iter, DBUS_TYPE_OBJECT_PATH, NULL, 0, error);
2277 ssid = wpa_s->conf->ssid;
2278 /* At present WPAS P2P_GO mode only applicable for p2p_go */
2279 if (ssid->mode != WPAS_MODE_P2P_GO &&
2280 ssid->mode != WPAS_MODE_AP &&
2281 ssid->mode != WPAS_MODE_P2P_GROUP_FORMATION)
2284 num_members = p2p_get_group_num_members(wpa_s->p2p_group);
2286 paths = os_calloc(num_members, sizeof(char *));
2291 while ((addr = p2p_iterate_group_members(wpa_s->p2p_group, &next))) {
2292 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
2295 os_snprintf(paths[i], WPAS_DBUS_OBJECT_PATH_MAX,
2296 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART
2298 wpa_s->parent->parent->dbus_new_path,
2303 success = wpas_dbus_simple_array_property_getter(iter,
2304 DBUS_TYPE_OBJECT_PATH,
2308 for (i = 0; i < num_members; i++)
2314 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
2316 for (i = 0; i < num_members; i++)
2324 dbus_bool_t wpas_dbus_getter_p2p_group_ssid(
2325 const struct wpa_dbus_property_desc *property_desc,
2326 DBusMessageIter *iter, DBusError *error, void *user_data)
2328 struct wpa_supplicant *wpa_s = user_data;
2330 if (wpa_s->current_ssid == NULL)
2332 return wpas_dbus_simple_array_property_getter(
2333 iter, DBUS_TYPE_BYTE, wpa_s->current_ssid->ssid,
2334 wpa_s->current_ssid->ssid_len, error);
2338 dbus_bool_t wpas_dbus_getter_p2p_group_bssid(
2339 const struct wpa_dbus_property_desc *property_desc,
2340 DBusMessageIter *iter, DBusError *error, void *user_data)
2342 struct wpa_supplicant *wpa_s = user_data;
2343 u8 role = wpas_get_p2p_role(wpa_s);
2346 if (role == WPAS_P2P_ROLE_CLIENT) {
2347 if (wpa_s->current_ssid == NULL)
2349 p_bssid = wpa_s->current_ssid->bssid;
2351 if (wpa_s->ap_iface == NULL)
2353 p_bssid = wpa_s->ap_iface->bss[0]->own_addr;
2356 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
2362 dbus_bool_t wpas_dbus_getter_p2p_group_frequency(
2363 const struct wpa_dbus_property_desc *property_desc,
2364 DBusMessageIter *iter, DBusError *error, void *user_data)
2366 struct wpa_supplicant *wpa_s = user_data;
2368 u8 role = wpas_get_p2p_role(wpa_s);
2370 if (role == WPAS_P2P_ROLE_CLIENT) {
2371 if (wpa_s->go_params == NULL)
2373 op_freq = wpa_s->go_params->freq;
2375 if (wpa_s->ap_iface == NULL)
2377 op_freq = wpa_s->ap_iface->freq;
2380 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
2385 dbus_bool_t wpas_dbus_getter_p2p_group_passphrase(
2386 const struct wpa_dbus_property_desc *property_desc,
2387 DBusMessageIter *iter, DBusError *error, void *user_data)
2389 struct wpa_supplicant *wpa_s = user_data;
2390 struct wpa_ssid *ssid = wpa_s->current_ssid;
2395 return wpas_dbus_string_property_getter(iter, ssid->passphrase, error);
2399 dbus_bool_t wpas_dbus_getter_p2p_group_psk(
2400 const struct wpa_dbus_property_desc *property_desc,
2401 DBusMessageIter *iter, DBusError *error, void *user_data)
2403 struct wpa_supplicant *wpa_s = user_data;
2406 struct wpa_ssid *ssid = wpa_s->current_ssid;
2411 if (ssid->psk_set) {
2413 psk_len = sizeof(ssid->psk);
2416 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
2417 p_psk, psk_len, error);
2421 dbus_bool_t wpas_dbus_getter_p2p_group_vendor_ext(
2422 const struct wpa_dbus_property_desc *property_desc,
2423 DBusMessageIter *iter, DBusError *error, void *user_data)
2425 struct wpa_supplicant *wpa_s = user_data;
2426 struct hostapd_data *hapd;
2427 struct wpabuf *vendor_ext[MAX_WPS_VENDOR_EXTENSIONS];
2428 unsigned int i, num_vendor_ext = 0;
2430 os_memset(vendor_ext, 0, sizeof(vendor_ext));
2432 /* Verify correct role for this property */
2433 if (wpas_get_p2p_role(wpa_s) == WPAS_P2P_ROLE_GO) {
2434 if (wpa_s->ap_iface == NULL)
2436 hapd = wpa_s->ap_iface->bss[0];
2438 /* Parse WPS Vendor Extensions sent in Beacon/Probe Response */
2439 for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
2440 if (hapd->conf->wps_vendor_ext[i] == NULL)
2442 vendor_ext[num_vendor_ext++] =
2443 hapd->conf->wps_vendor_ext[i];
2447 /* Return vendor extensions or no data */
2448 return wpas_dbus_simple_array_array_property_getter(iter,
2456 dbus_bool_t wpas_dbus_setter_p2p_group_vendor_ext(
2457 const struct wpa_dbus_property_desc *property_desc,
2458 DBusMessageIter *iter, DBusError *error, void *user_data)
2460 struct wpa_supplicant *wpa_s = user_data;
2461 DBusMessageIter variant_iter, iter_dict, array_iter, sub;
2462 struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
2464 struct hostapd_data *hapd = NULL;
2466 if (wpas_get_p2p_role(wpa_s) == WPAS_P2P_ROLE_GO &&
2467 wpa_s->ap_iface != NULL)
2468 hapd = wpa_s->ap_iface->bss[0];
2472 dbus_message_iter_recurse(iter, &variant_iter);
2473 if (dbus_message_iter_get_arg_type(&variant_iter) != DBUS_TYPE_ARRAY)
2477 * This is supposed to be array of bytearrays (aay), but the earlier
2478 * implementation used a dict with "WPSVendorExtensions" as the key in
2479 * this setter function which does not match the format used by the
2480 * getter function. For backwards compatibility, allow both formats to
2481 * be used in the setter.
2483 if (dbus_message_iter_get_element_type(&variant_iter) ==
2485 /* This is the proper format matching the getter */
2486 struct wpabuf *vals[MAX_WPS_VENDOR_EXTENSIONS];
2488 dbus_message_iter_recurse(&variant_iter, &array_iter);
2490 if (dbus_message_iter_get_arg_type(&array_iter) !=
2492 dbus_message_iter_get_element_type(&array_iter) !=
2494 wpa_printf(MSG_DEBUG,
2495 "dbus: Not an array of array of bytes");
2500 os_memset(vals, 0, sizeof(vals));
2502 while (dbus_message_iter_get_arg_type(&array_iter) ==
2507 if (i == MAX_WPS_VENDOR_EXTENSIONS) {
2508 wpa_printf(MSG_DEBUG,
2509 "dbus: Too many WPSVendorExtensions values");
2510 i = MAX_WPS_VENDOR_EXTENSIONS + 1;
2514 dbus_message_iter_recurse(&array_iter, &sub);
2515 dbus_message_iter_get_fixed_array(&sub, &val, &len);
2516 wpa_hexdump(MSG_DEBUG, "dbus: WPSVendorExtentions[]",
2518 vals[i] = wpabuf_alloc_copy(val, len);
2519 if (vals[i] == NULL) {
2520 i = MAX_WPS_VENDOR_EXTENSIONS + 1;
2524 dbus_message_iter_next(&array_iter);
2527 if (i > MAX_WPS_VENDOR_EXTENSIONS) {
2528 for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++)
2529 wpabuf_free(vals[i]);
2533 for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
2534 wpabuf_free(hapd->conf->wps_vendor_ext[i]);
2535 hapd->conf->wps_vendor_ext[i] = vals[i];
2538 hostapd_update_wps(hapd);
2543 if (dbus_message_iter_get_element_type(&variant_iter) !=
2544 DBUS_TYPE_DICT_ENTRY)
2547 wpa_printf(MSG_DEBUG,
2548 "dbus: Try to use backwards compatibility version of WPSVendorExtensions setter");
2549 if (!wpa_dbus_dict_open_read(&variant_iter, &iter_dict, error))
2552 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2553 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) {
2554 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
2555 "invalid message format");
2559 if (os_strcmp(entry.key, "WPSVendorExtensions") == 0) {
2560 if (entry.type != DBUS_TYPE_ARRAY ||
2561 entry.array_type != WPAS_DBUS_TYPE_BINARRAY ||
2562 entry.array_len > MAX_WPS_VENDOR_EXTENSIONS)
2565 for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
2566 wpabuf_free(hapd->conf->wps_vendor_ext[i]);
2567 if (i < entry.array_len) {
2568 hapd->conf->wps_vendor_ext[i] =
2569 entry.binarray_value[i];
2570 entry.binarray_value[i] = NULL;
2572 hapd->conf->wps_vendor_ext[i] = NULL;
2575 hostapd_update_wps(hapd);
2579 wpa_dbus_dict_entry_clear(&entry);
2585 wpa_dbus_dict_entry_clear(&entry);
2586 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
2587 "invalid message format");
2592 DBusMessage * wpas_dbus_handler_p2p_add_service(DBusMessage *message,
2593 struct wpa_supplicant *wpa_s)
2595 DBusMessageIter iter_dict;
2596 DBusMessage *reply = NULL;
2597 DBusMessageIter iter;
2598 struct wpa_dbus_dict_entry entry;
2601 char *service = NULL;
2602 struct wpabuf *query = NULL;
2603 struct wpabuf *resp = NULL;
2606 dbus_message_iter_init(message, &iter);
2608 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
2611 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2612 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2615 if (os_strcmp(entry.key, "service_type") == 0 &&
2616 entry.type == DBUS_TYPE_STRING) {
2617 if (os_strcmp(entry.str_value, "upnp") == 0)
2619 else if (os_strcmp(entry.str_value, "bonjour") == 0)
2623 } else if (os_strcmp(entry.key, "version") == 0 &&
2624 entry.type == DBUS_TYPE_INT32) {
2625 version = entry.uint32_value;
2626 } else if (os_strcmp(entry.key, "service") == 0 &&
2627 entry.type == DBUS_TYPE_STRING) {
2629 service = os_strdup(entry.str_value);
2630 } else if (os_strcmp(entry.key, "query") == 0) {
2631 if (entry.type != DBUS_TYPE_ARRAY ||
2632 entry.array_type != DBUS_TYPE_BYTE)
2634 query = wpabuf_alloc_copy(
2635 entry.bytearray_value,
2637 } else if (os_strcmp(entry.key, "response") == 0) {
2638 if (entry.type != DBUS_TYPE_ARRAY ||
2639 entry.array_type != DBUS_TYPE_BYTE)
2641 resp = wpabuf_alloc_copy(entry.bytearray_value,
2644 wpa_dbus_dict_entry_clear(&entry);
2648 if (version <= 0 || service == NULL)
2651 if (wpas_p2p_service_add_upnp(wpa_s, version, service) != 0)
2654 } else if (bonjour == 1) {
2655 if (query == NULL || resp == NULL)
2658 if (wpas_p2p_service_add_bonjour(wpa_s, query, resp) < 0)
2668 wpa_dbus_dict_entry_clear(&entry);
2673 return wpas_dbus_error_invalid_args(message, NULL);
2677 DBusMessage * wpas_dbus_handler_p2p_delete_service(
2678 DBusMessage *message, struct wpa_supplicant *wpa_s)
2680 DBusMessageIter iter_dict;
2681 DBusMessage *reply = NULL;
2682 DBusMessageIter iter;
2683 struct wpa_dbus_dict_entry entry;
2687 char *service = NULL;
2688 struct wpabuf *query = NULL;
2691 dbus_message_iter_init(message, &iter);
2693 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
2696 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2697 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2700 if (os_strcmp(entry.key, "service_type") == 0 &&
2701 entry.type == DBUS_TYPE_STRING) {
2702 if (os_strcmp(entry.str_value, "upnp") == 0)
2704 else if (os_strcmp(entry.str_value, "bonjour") == 0)
2708 } else if (os_strcmp(entry.key, "version") == 0 &&
2709 entry.type == DBUS_TYPE_INT32) {
2710 version = entry.uint32_value;
2711 } else if (os_strcmp(entry.key, "service") == 0 &&
2712 entry.type == DBUS_TYPE_STRING) {
2714 service = os_strdup(entry.str_value);
2715 } else if (os_strcmp(entry.key, "query") == 0) {
2716 if (entry.type != DBUS_TYPE_ARRAY ||
2717 entry.array_type != DBUS_TYPE_BYTE)
2720 query = wpabuf_alloc_copy(entry.bytearray_value,
2726 wpa_dbus_dict_entry_clear(&entry);
2729 if (version <= 0 || service == NULL)
2732 ret = wpas_p2p_service_del_upnp(wpa_s, version, service);
2735 } else if (bonjour == 1) {
2739 ret = wpas_p2p_service_del_bonjour(wpa_s, query);
2749 wpa_dbus_dict_entry_clear(&entry);
2753 return wpas_dbus_error_invalid_args(message, NULL);
2757 DBusMessage * wpas_dbus_handler_p2p_flush_service(DBusMessage *message,
2758 struct wpa_supplicant *wpa_s)
2760 wpas_p2p_service_flush(wpa_s);
2765 DBusMessage * wpas_dbus_handler_p2p_service_sd_req(
2766 DBusMessage *message, struct wpa_supplicant *wpa_s)
2768 DBusMessageIter iter_dict;
2769 DBusMessage *reply = NULL;
2770 DBusMessageIter iter;
2771 struct wpa_dbus_dict_entry entry;
2773 char *service = NULL;
2774 char *peer_object_path = NULL;
2775 struct wpabuf *tlv = NULL;
2778 u8 addr_buf[ETH_ALEN], *addr;
2780 dbus_message_iter_init(message, &iter);
2782 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
2785 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2786 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2788 if (os_strcmp(entry.key, "peer_object") == 0 &&
2789 entry.type == DBUS_TYPE_OBJECT_PATH) {
2790 peer_object_path = os_strdup(entry.str_value);
2791 } else if (os_strcmp(entry.key, "service_type") == 0 &&
2792 entry.type == DBUS_TYPE_STRING) {
2793 if (os_strcmp(entry.str_value, "upnp") == 0)
2797 } else if (os_strcmp(entry.key, "version") == 0 &&
2798 entry.type == DBUS_TYPE_INT32) {
2799 version = entry.uint32_value;
2800 } else if (os_strcmp(entry.key, "service") == 0 &&
2801 entry.type == DBUS_TYPE_STRING) {
2802 service = os_strdup(entry.str_value);
2803 } else if (os_strcmp(entry.key, "tlv") == 0) {
2804 if (entry.type != DBUS_TYPE_ARRAY ||
2805 entry.array_type != DBUS_TYPE_BYTE)
2807 tlv = wpabuf_alloc_copy(entry.bytearray_value,
2812 wpa_dbus_dict_entry_clear(&entry);
2815 if (!peer_object_path) {
2818 if (parse_peer_object_path(peer_object_path, addr_buf) < 0 ||
2819 !p2p_peer_known(wpa_s->global->p2p, addr_buf))
2826 if (version <= 0 || service == NULL)
2829 ref = wpas_p2p_sd_request_upnp(wpa_s, addr, version, service);
2833 ref = wpas_p2p_sd_request(wpa_s, addr, tlv);
2838 reply = dbus_message_new_method_return(message);
2839 dbus_message_append_args(reply, DBUS_TYPE_UINT64,
2840 &ref, DBUS_TYPE_INVALID);
2842 reply = wpas_dbus_error_unknown_error(
2843 message, "Unable to send SD request");
2847 os_free(peer_object_path);
2850 wpa_dbus_dict_entry_clear(&entry);
2854 reply = wpas_dbus_error_invalid_args(message, NULL);
2859 DBusMessage * wpas_dbus_handler_p2p_service_sd_res(
2860 DBusMessage *message, struct wpa_supplicant *wpa_s)
2862 DBusMessageIter iter_dict;
2863 DBusMessage *reply = NULL;
2864 DBusMessageIter iter;
2865 struct wpa_dbus_dict_entry entry;
2866 char *peer_object_path = NULL;
2867 struct wpabuf *tlv = NULL;
2872 dbus_message_iter_init(message, &iter);
2874 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
2877 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2878 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2881 if (os_strcmp(entry.key, "peer_object") == 0 &&
2882 entry.type == DBUS_TYPE_OBJECT_PATH) {
2883 peer_object_path = os_strdup(entry.str_value);
2884 } else if (os_strcmp(entry.key, "frequency") == 0 &&
2885 entry.type == DBUS_TYPE_INT32) {
2886 freq = entry.uint32_value;
2887 } else if (os_strcmp(entry.key, "dialog_token") == 0 &&
2888 (entry.type == DBUS_TYPE_UINT32 ||
2889 entry.type == DBUS_TYPE_INT32)) {
2890 dlg_tok = entry.uint32_value;
2891 } else if (os_strcmp(entry.key, "tlvs") == 0) {
2892 if (entry.type != DBUS_TYPE_ARRAY ||
2893 entry.array_type != DBUS_TYPE_BYTE)
2895 tlv = wpabuf_alloc_copy(entry.bytearray_value,
2900 wpa_dbus_dict_entry_clear(&entry);
2902 if (parse_peer_object_path(peer_object_path, addr) < 0 ||
2903 !p2p_peer_known(wpa_s->global->p2p, addr) ||
2907 wpas_p2p_sd_response(wpa_s, freq, addr, (u8) dlg_tok, tlv);
2910 os_free(peer_object_path);
2913 wpa_dbus_dict_entry_clear(&entry);
2915 reply = wpas_dbus_error_invalid_args(message, NULL);
2920 DBusMessage * wpas_dbus_handler_p2p_service_sd_cancel_req(
2921 DBusMessage *message, struct wpa_supplicant *wpa_s)
2923 DBusMessageIter iter;
2926 dbus_message_iter_init(message, &iter);
2927 dbus_message_iter_get_basic(&iter, &req);
2932 if (wpas_p2p_sd_cancel_request(wpa_s, req) < 0)
2937 return wpas_dbus_error_invalid_args(message, NULL);
2941 DBusMessage * wpas_dbus_handler_p2p_service_update(
2942 DBusMessage *message, struct wpa_supplicant *wpa_s)
2944 wpas_p2p_sd_service_update(wpa_s);
2949 DBusMessage * wpas_dbus_handler_p2p_serv_disc_external(
2950 DBusMessage *message, struct wpa_supplicant *wpa_s)
2952 DBusMessageIter iter;
2955 dbus_message_iter_init(message, &iter);
2956 dbus_message_iter_get_basic(&iter, &ext);
2958 wpa_s->p2p_sd_over_ctrl_iface = ext;
2965 #ifdef CONFIG_WIFI_DISPLAY
2967 dbus_bool_t wpas_dbus_getter_global_wfd_ies(
2968 const struct wpa_dbus_property_desc *property_desc,
2969 DBusMessageIter *iter, DBusError *error, void *user_data)
2971 struct wpa_global *global = user_data;
2975 ie = wifi_display_get_wfd_ie(global);
2977 return wpas_dbus_simple_array_property_getter(iter,
2981 ret = wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
2983 wpabuf_len(ie), error);
2990 dbus_bool_t wpas_dbus_setter_global_wfd_ies(
2991 const struct wpa_dbus_property_desc *property_desc,
2992 DBusMessageIter *iter, DBusError *error, void *user_data)
2994 struct wpa_global *global = user_data;
2995 DBusMessageIter variant, array;
2996 struct wpabuf *ie = NULL;
3000 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_VARIANT)
3003 dbus_message_iter_recurse(iter, &variant);
3004 if (dbus_message_iter_get_arg_type(&variant) != DBUS_TYPE_ARRAY)
3007 dbus_message_iter_recurse(&variant, &array);
3008 dbus_message_iter_get_fixed_array(&array, &data, &len);
3010 wifi_display_enable(global, 0);
3011 wifi_display_deinit(global);
3016 ie = wpabuf_alloc(len);
3020 wpabuf_put_data(ie, data, len);
3021 if (wifi_display_subelem_set_from_ies(global, ie) != 0)
3024 if (global->wifi_display == 0)
3025 wifi_display_enable(global, 1);
3033 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
3034 "invalid message format");
3038 #endif /* CONFIG_WIFI_DISPLAY */