2 * WPA Supplicant / dbus-based control interface (P2P)
3 * Copyright (c) 2011-2012, Intel Corporation
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
11 #include "utils/includes.h"
13 #include "../config.h"
14 #include "../wpa_supplicant_i.h"
15 #include "../wps_supplicant.h"
16 #include "../notify.h"
17 #include "dbus_new_helpers.h"
19 #include "dbus_new_handlers.h"
20 #include "dbus_new_handlers_p2p.h"
21 #include "dbus_dict_helpers.h"
23 #include "common/ieee802_11_defs.h"
24 #include "ap/hostapd.h"
25 #include "ap/ap_config.h"
26 #include "ap/wps_hostapd.h"
28 #include "../p2p_supplicant.h"
31 * Parses out the mac address from the peer object path.
32 * @peer_path - object path of the form
33 * /fi/w1/wpa_supplicant1/Interfaces/n/Peers/00112233445566 (no colons)
34 * @addr - out param must be of ETH_ALEN size
35 * Returns 0 if valid (including MAC), -1 otherwise
37 static int parse_peer_object_path(char *peer_path
, u8 addr
[ETH_ALEN
])
43 p
= os_strrchr(peer_path
, '/');
47 return hwaddr_compact_aton(p
, addr
);
52 * wpas_dbus_error_persistent_group_unknown - Return a new PersistentGroupUnknown
54 * @message: Pointer to incoming dbus message this error refers to
55 * Returns: a dbus error message
57 * Convenience function to create and return an invalid persistent group error.
59 static DBusMessage
* wpas_dbus_error_persistent_group_unknown(
62 return dbus_message_new_error(message
, WPAS_DBUS_ERROR_NETWORK_UNKNOWN
,
63 "There is no such persistent group in "
68 DBusMessage
* wpas_dbus_handler_p2p_find(DBusMessage
*message
,
69 struct wpa_supplicant
*wpa_s
)
71 struct wpa_dbus_dict_entry entry
;
72 DBusMessage
*reply
= NULL
;
74 DBusMessageIter iter_dict
;
75 unsigned int timeout
= 0;
76 enum p2p_discovery_type type
= P2P_FIND_ONLY_SOCIAL
;
77 int num_req_dev_types
= 0;
79 u8
*req_dev_types
= NULL
;
81 dbus_message_iter_init(message
, &iter
);
84 if (!wpa_dbus_dict_open_read(&iter
, &iter_dict
, NULL
))
87 while (wpa_dbus_dict_has_dict_entry(&iter_dict
)) {
88 if (!wpa_dbus_dict_get_entry(&iter_dict
, &entry
))
91 if (!os_strcmp(entry
.key
, "Timeout") &&
92 (entry
.type
== DBUS_TYPE_INT32
)) {
93 timeout
= entry
.uint32_value
;
94 } else if (os_strcmp(entry
.key
, "RequestedDeviceTypes") == 0) {
95 if ((entry
.type
!= DBUS_TYPE_ARRAY
) ||
96 (entry
.array_type
!= WPAS_DBUS_TYPE_BINARRAY
))
99 os_free(req_dev_types
);
101 os_malloc(WPS_DEV_TYPE_LEN
* entry
.array_len
);
105 for (i
= 0; i
< entry
.array_len
; i
++) {
106 if (wpabuf_len(entry
.binarray_value
[i
]) !=
109 os_memcpy(req_dev_types
+ i
* WPS_DEV_TYPE_LEN
,
110 wpabuf_head(entry
.binarray_value
[i
]),
113 num_req_dev_types
= entry
.array_len
;
114 } else if (!os_strcmp(entry
.key
, "DiscoveryType") &&
115 (entry
.type
== DBUS_TYPE_STRING
)) {
116 if (!os_strcmp(entry
.str_value
, "start_with_full"))
117 type
= P2P_FIND_START_WITH_FULL
;
118 else if (!os_strcmp(entry
.str_value
, "social"))
119 type
= P2P_FIND_ONLY_SOCIAL
;
120 else if (!os_strcmp(entry
.str_value
, "progressive"))
121 type
= P2P_FIND_PROGRESSIVE
;
126 wpa_dbus_dict_entry_clear(&entry
);
129 wpas_p2p_find(wpa_s
, timeout
, type
, num_req_dev_types
, req_dev_types
,
131 os_free(req_dev_types
);
135 wpa_dbus_dict_entry_clear(&entry
);
137 os_free(req_dev_types
);
138 reply
= wpas_dbus_error_invalid_args(message
, entry
.key
);
143 DBusMessage
* wpas_dbus_handler_p2p_stop_find(DBusMessage
*message
,
144 struct wpa_supplicant
*wpa_s
)
146 wpas_p2p_stop_find(wpa_s
);
151 DBusMessage
* wpas_dbus_handler_p2p_rejectpeer(DBusMessage
*message
,
152 struct wpa_supplicant
*wpa_s
)
154 DBusMessageIter iter
;
155 char *peer_object_path
= NULL
;
156 u8 peer_addr
[ETH_ALEN
];
158 dbus_message_iter_init(message
, &iter
);
159 dbus_message_iter_get_basic(&iter
, &peer_object_path
);
161 if (parse_peer_object_path(peer_object_path
, peer_addr
) < 0)
162 return wpas_dbus_error_invalid_args(message
, NULL
);
164 if (wpas_p2p_reject(wpa_s
, peer_addr
) < 0)
165 return wpas_dbus_error_unknown_error(message
,
166 "Failed to call wpas_p2p_reject method.");
172 DBusMessage
* wpas_dbus_handler_p2p_listen(DBusMessage
*message
,
173 struct wpa_supplicant
*wpa_s
)
175 dbus_int32_t timeout
= 0;
177 if (!dbus_message_get_args(message
, NULL
, DBUS_TYPE_INT32
, &timeout
,
179 return dbus_message_new_error(message
, DBUS_ERROR_NO_MEMORY
,
182 if (wpas_p2p_listen(wpa_s
, (unsigned int)timeout
))
183 return dbus_message_new_error(message
, DBUS_ERROR_NO_MEMORY
,
190 DBusMessage
* wpas_dbus_handler_p2p_extendedlisten(
191 DBusMessage
*message
, struct wpa_supplicant
*wpa_s
)
193 unsigned int period
= 0, interval
= 0;
194 struct wpa_dbus_dict_entry entry
;
195 DBusMessageIter iter
;
196 DBusMessageIter iter_dict
;
198 dbus_message_iter_init(message
, &iter
);
201 if (!wpa_dbus_dict_open_read(&iter
, &iter_dict
, NULL
))
204 while (wpa_dbus_dict_has_dict_entry(&iter_dict
)) {
205 if (!wpa_dbus_dict_get_entry(&iter_dict
, &entry
))
208 if (!os_strcmp(entry
.key
, "period") &&
209 (entry
.type
== DBUS_TYPE_INT32
))
210 period
= entry
.uint32_value
;
211 else if (!os_strcmp(entry
.key
, "interval") &&
212 (entry
.type
== DBUS_TYPE_INT32
))
213 interval
= entry
.uint32_value
;
216 wpa_dbus_dict_entry_clear(&entry
);
219 if (wpas_p2p_ext_listen(wpa_s
, period
, interval
))
220 return wpas_dbus_error_unknown_error(
221 message
, "failed to initiate a p2p_ext_listen.");
226 wpa_dbus_dict_entry_clear(&entry
);
228 return wpas_dbus_error_invalid_args(message
, entry
.key
);
232 DBusMessage
* wpas_dbus_handler_p2p_presence_request(
233 DBusMessage
*message
, struct wpa_supplicant
*wpa_s
)
235 unsigned int dur1
= 0, int1
= 0, dur2
= 0, int2
= 0;
236 struct wpa_dbus_dict_entry entry
;
237 DBusMessageIter iter
;
238 DBusMessageIter iter_dict
;
240 dbus_message_iter_init(message
, &iter
);
243 if (!wpa_dbus_dict_open_read(&iter
, &iter_dict
, NULL
))
246 while (wpa_dbus_dict_has_dict_entry(&iter_dict
)) {
247 if (!wpa_dbus_dict_get_entry(&iter_dict
, &entry
))
250 if (!os_strcmp(entry
.key
, "duration1") &&
251 (entry
.type
== DBUS_TYPE_INT32
))
252 dur1
= entry
.uint32_value
;
253 else if (!os_strcmp(entry
.key
, "interval1") &&
254 entry
.type
== DBUS_TYPE_INT32
)
255 int1
= entry
.uint32_value
;
256 else if (!os_strcmp(entry
.key
, "duration2") &&
257 entry
.type
== DBUS_TYPE_INT32
)
258 dur2
= entry
.uint32_value
;
259 else if (!os_strcmp(entry
.key
, "interval2") &&
260 entry
.type
== DBUS_TYPE_INT32
)
261 int2
= entry
.uint32_value
;
265 wpa_dbus_dict_entry_clear(&entry
);
267 if (wpas_p2p_presence_req(wpa_s
, dur1
, int1
, dur2
, int2
) < 0)
268 return wpas_dbus_error_unknown_error(message
,
269 "Failed to invoke presence request.");
274 wpa_dbus_dict_entry_clear(&entry
);
276 return wpas_dbus_error_invalid_args(message
, entry
.key
);
280 DBusMessage
* wpas_dbus_handler_p2p_group_add(DBusMessage
*message
,
281 struct wpa_supplicant
*wpa_s
)
283 DBusMessageIter iter_dict
;
284 DBusMessage
*reply
= NULL
;
285 DBusMessageIter iter
;
286 struct wpa_dbus_dict_entry entry
;
287 char *pg_object_path
= NULL
;
288 int persistent_group
= 0;
291 char *net_id_str
= NULL
;
292 unsigned int group_id
= 0;
293 struct wpa_ssid
*ssid
;
295 dbus_message_iter_init(message
, &iter
);
297 if (!wpa_dbus_dict_open_read(&iter
, &iter_dict
, NULL
))
300 while (wpa_dbus_dict_has_dict_entry(&iter_dict
)) {
301 if (!wpa_dbus_dict_get_entry(&iter_dict
, &entry
))
304 if (!os_strcmp(entry
.key
, "persistent") &&
305 (entry
.type
== DBUS_TYPE_BOOLEAN
)) {
306 persistent_group
= (entry
.bool_value
== TRUE
) ? 1 : 0;
307 } else if (!os_strcmp(entry
.key
, "frequency") &&
308 (entry
.type
== DBUS_TYPE_INT32
)) {
309 freq
= entry
.int32_value
;
312 } else if (!os_strcmp(entry
.key
, "persistent_group_object") &&
313 entry
.type
== DBUS_TYPE_OBJECT_PATH
)
314 pg_object_path
= os_strdup(entry
.str_value
);
318 wpa_dbus_dict_entry_clear(&entry
);
321 if (pg_object_path
!= NULL
) {
323 * A persistent group Object Path is defined meaning we want
324 * to re-invoke a persistent group.
327 iface
= wpas_dbus_new_decompose_object_path(pg_object_path
, 1,
330 os_strcmp(iface
, wpa_s
->dbus_new_path
) != 0) {
332 wpas_dbus_error_invalid_args(message
,
337 group_id
= strtoul(net_id_str
, NULL
, 10);
338 if (errno
== EINVAL
) {
339 reply
= wpas_dbus_error_invalid_args(
340 message
, pg_object_path
);
344 /* Get the SSID structure from the persistent group id */
345 ssid
= wpa_config_get_network(wpa_s
->conf
, group_id
);
346 if (ssid
== NULL
|| ssid
->disabled
!= 2)
349 if (wpas_p2p_group_add_persistent(wpa_s
, ssid
, 0, freq
, 0, 0,
351 reply
= wpas_dbus_error_unknown_error(
353 "Failed to reinvoke a persistent group");
356 } else if (wpas_p2p_group_add(wpa_s
, persistent_group
, freq
, 0, 0))
360 os_free(pg_object_path
);
365 wpa_dbus_dict_entry_clear(&entry
);
367 reply
= wpas_dbus_error_invalid_args(message
, NULL
);
372 DBusMessage
* wpas_dbus_handler_p2p_disconnect(DBusMessage
*message
,
373 struct wpa_supplicant
*wpa_s
)
375 if (wpas_p2p_disconnect(wpa_s
))
376 return wpas_dbus_error_unknown_error(message
,
377 "failed to disconnect");
383 static dbus_bool_t
wpa_dbus_p2p_check_enabled(struct wpa_supplicant
*wpa_s
,
384 DBusMessage
*message
,
385 DBusMessage
**out_reply
,
388 /* Return an error message or an error if P2P isn't available */
389 if (wpa_s
->global
->p2p_disabled
|| wpa_s
->global
->p2p
== NULL
) {
391 *out_reply
= dbus_message_new_error(
392 message
, DBUS_ERROR_FAILED
,
393 "P2P is not available for this interface");
395 dbus_set_error_const(error
, DBUS_ERROR_FAILED
,
396 "P2P is not available for this "
404 DBusMessage
* wpas_dbus_handler_p2p_flush(DBusMessage
*message
,
405 struct wpa_supplicant
*wpa_s
)
407 DBusMessage
*reply
= NULL
;
409 if (!wpa_dbus_p2p_check_enabled(wpa_s
, message
, &reply
, NULL
))
412 os_memset(wpa_s
->p2p_auth_invite
, 0, ETH_ALEN
);
413 wpa_s
->force_long_sd
= 0;
414 p2p_flush(wpa_s
->global
->p2p
);
420 DBusMessage
* wpas_dbus_handler_p2p_connect(DBusMessage
*message
,
421 struct wpa_supplicant
*wpa_s
)
423 DBusMessageIter iter_dict
;
424 DBusMessage
*reply
= NULL
;
425 DBusMessageIter iter
;
426 struct wpa_dbus_dict_entry entry
;
427 char *peer_object_path
= NULL
;
428 int persistent_group
= 0;
430 int authorize_only
= 0;
435 enum p2p_wps_method wps_method
= WPS_NOT_READY
;
437 char *err_msg
= NULL
;
440 if (!wpa_dbus_p2p_check_enabled(wpa_s
, message
, &reply
, NULL
))
443 dbus_message_iter_init(message
, &iter
);
445 if (!wpa_dbus_dict_open_read(&iter
, &iter_dict
, NULL
))
448 while (wpa_dbus_dict_has_dict_entry(&iter_dict
)) {
449 if (!wpa_dbus_dict_get_entry(&iter_dict
, &entry
))
452 if (!os_strcmp(entry
.key
, "peer") &&
453 (entry
.type
== DBUS_TYPE_OBJECT_PATH
)) {
454 peer_object_path
= os_strdup(entry
.str_value
);
455 } else if (!os_strcmp(entry
.key
, "persistent") &&
456 (entry
.type
== DBUS_TYPE_BOOLEAN
)) {
457 persistent_group
= (entry
.bool_value
== TRUE
) ? 1 : 0;
458 } else if (!os_strcmp(entry
.key
, "join") &&
459 (entry
.type
== DBUS_TYPE_BOOLEAN
)) {
460 join
= (entry
.bool_value
== TRUE
) ? 1 : 0;
461 } else if (!os_strcmp(entry
.key
, "authorize_only") &&
462 (entry
.type
== DBUS_TYPE_BOOLEAN
)) {
463 authorize_only
= (entry
.bool_value
== TRUE
) ? 1 : 0;
464 } else if (!os_strcmp(entry
.key
, "frequency") &&
465 (entry
.type
== DBUS_TYPE_INT32
)) {
466 freq
= entry
.int32_value
;
469 } else if (!os_strcmp(entry
.key
, "go_intent") &&
470 (entry
.type
== DBUS_TYPE_INT32
)) {
471 go_intent
= entry
.int32_value
;
472 if ((go_intent
< 0) || (go_intent
> 15))
474 } else if (!os_strcmp(entry
.key
, "wps_method") &&
475 (entry
.type
== DBUS_TYPE_STRING
)) {
476 if (!os_strcmp(entry
.str_value
, "pbc"))
477 wps_method
= WPS_PBC
;
478 else if (!os_strcmp(entry
.str_value
, "pin"))
479 wps_method
= WPS_PIN_DISPLAY
;
480 else if (!os_strcmp(entry
.str_value
, "display"))
481 wps_method
= WPS_PIN_DISPLAY
;
482 else if (!os_strcmp(entry
.str_value
, "keypad"))
483 wps_method
= WPS_PIN_KEYPAD
;
486 } else if (!os_strcmp(entry
.key
, "pin") &&
487 (entry
.type
== DBUS_TYPE_STRING
)) {
488 pin
= os_strdup(entry
.str_value
);
492 wpa_dbus_dict_entry_clear(&entry
);
495 if (!peer_object_path
|| (wps_method
== WPS_NOT_READY
) ||
496 (parse_peer_object_path(peer_object_path
, addr
) < 0) ||
497 !p2p_peer_known(wpa_s
->global
->p2p
, addr
))
501 * Validate the wps_method specified and the pin value.
503 if ((!pin
|| !pin
[0]) && (wps_method
== WPS_PIN_KEYPAD
))
506 new_pin
= wpas_p2p_connect(wpa_s
, addr
, pin
, wps_method
,
507 persistent_group
, 0, join
, authorize_only
,
508 go_intent
, freq
, -1, 0, 0, 0);
513 os_snprintf(npin
, sizeof(npin
), "%08d", new_pin
);
514 generated_pin
= npin
;
515 reply
= dbus_message_new_method_return(message
);
516 dbus_message_append_args(reply
, DBUS_TYPE_STRING
,
517 &generated_pin
, DBUS_TYPE_INVALID
);
521 err_msg
= "connect failed due to channel "
523 iface
= WPAS_DBUS_ERROR_CONNECT_CHANNEL_UNAVAILABLE
;
527 err_msg
= "connect failed due to unsupported channel.";
528 iface
= WPAS_DBUS_ERROR_CONNECT_CHANNEL_UNSUPPORTED
;
532 err_msg
= "connect failed due to unspecified error.";
533 iface
= WPAS_DBUS_ERROR_CONNECT_UNSPECIFIED_ERROR
;
539 * Do we need specialized errors corresponding to above
540 * error conditions as against just returning a different
543 reply
= dbus_message_new_error(message
, iface
, err_msg
);
547 os_free(peer_object_path
);
551 wpa_dbus_dict_entry_clear(&entry
);
553 reply
= wpas_dbus_error_invalid_args(message
, NULL
);
558 DBusMessage
* wpas_dbus_handler_p2p_invite(DBusMessage
*message
,
559 struct wpa_supplicant
*wpa_s
)
561 DBusMessageIter iter_dict
;
562 DBusMessage
*reply
= NULL
;
563 DBusMessageIter iter
;
564 struct wpa_dbus_dict_entry entry
;
565 char *peer_object_path
= NULL
;
566 char *pg_object_path
= NULL
;
568 char *net_id_str
= NULL
;
569 u8 peer_addr
[ETH_ALEN
];
570 unsigned int group_id
= 0;
572 struct wpa_ssid
*ssid
;
574 if (!wpa_dbus_p2p_check_enabled(wpa_s
, message
, &reply
, NULL
))
577 dbus_message_iter_init(message
, &iter
);
579 if (!wpa_dbus_dict_open_read(&iter
, &iter_dict
, NULL
))
582 while (wpa_dbus_dict_has_dict_entry(&iter_dict
)) {
583 if (!wpa_dbus_dict_get_entry(&iter_dict
, &entry
))
586 if (!os_strcmp(entry
.key
, "peer") &&
587 (entry
.type
== DBUS_TYPE_OBJECT_PATH
)) {
588 peer_object_path
= os_strdup(entry
.str_value
);
589 wpa_dbus_dict_entry_clear(&entry
);
590 } else if (!os_strcmp(entry
.key
, "persistent_group_object") &&
591 (entry
.type
== DBUS_TYPE_OBJECT_PATH
)) {
592 pg_object_path
= os_strdup(entry
.str_value
);
594 wpa_dbus_dict_entry_clear(&entry
);
596 wpa_dbus_dict_entry_clear(&entry
);
601 if (!peer_object_path
||
602 (parse_peer_object_path(peer_object_path
, peer_addr
) < 0) ||
603 !p2p_peer_known(wpa_s
->global
->p2p
, peer_addr
)) {
609 * A group ID is defined meaning we want to re-invoke a
613 iface
= wpas_dbus_new_decompose_object_path(pg_object_path
, 1,
616 os_strcmp(iface
, wpa_s
->dbus_new_path
) != 0) {
617 reply
= wpas_dbus_error_invalid_args(message
,
622 group_id
= strtoul(net_id_str
, NULL
, 10);
623 if (errno
== EINVAL
) {
624 reply
= wpas_dbus_error_invalid_args(
625 message
, pg_object_path
);
629 /* Get the SSID structure from the persistent group id */
630 ssid
= wpa_config_get_network(wpa_s
->conf
, group_id
);
631 if (ssid
== NULL
|| ssid
->disabled
!= 2)
634 if (wpas_p2p_invite(wpa_s
, peer_addr
, ssid
, NULL
, 0, 0, 0, 0) <
636 reply
= wpas_dbus_error_unknown_error(
638 "Failed to reinvoke a persistent group");
643 * No group ID means propose to a peer to join my active group
645 if (wpas_p2p_invite_group(wpa_s
, wpa_s
->ifname
,
647 reply
= wpas_dbus_error_unknown_error(
648 message
, "Failed to join to an active group");
654 os_free(pg_object_path
);
655 os_free(peer_object_path
);
659 reply
= wpas_dbus_error_invalid_args(message
, NULL
);
664 DBusMessage
* wpas_dbus_handler_p2p_prov_disc_req(DBusMessage
*message
,
665 struct wpa_supplicant
*wpa_s
)
667 DBusMessageIter iter
;
668 char *peer_object_path
= NULL
;
669 char *config_method
= NULL
;
670 u8 peer_addr
[ETH_ALEN
];
672 dbus_message_iter_init(message
, &iter
);
673 dbus_message_iter_get_basic(&iter
, &peer_object_path
);
675 if (parse_peer_object_path(peer_object_path
, peer_addr
) < 0)
676 return wpas_dbus_error_invalid_args(message
, NULL
);
678 dbus_message_iter_next(&iter
);
679 dbus_message_iter_get_basic(&iter
, &config_method
);
682 * Validation checks on config_method are being duplicated here
683 * to be able to return invalid args reply since the error code
684 * from p2p module are not granular enough (yet).
686 if (os_strcmp(config_method
, "display") &&
687 os_strcmp(config_method
, "keypad") &&
688 os_strcmp(config_method
, "pbc") &&
689 os_strcmp(config_method
, "pushbutton"))
690 return wpas_dbus_error_invalid_args(message
, NULL
);
692 if (wpas_p2p_prov_disc(wpa_s
, peer_addr
, config_method
,
693 WPAS_P2P_PD_FOR_GO_NEG
) < 0)
694 return wpas_dbus_error_unknown_error(message
,
695 "Failed to send provision discovery request");
702 * P2P Device property accessor methods.
705 dbus_bool_t
wpas_dbus_getter_p2p_device_config(DBusMessageIter
*iter
,
709 struct wpa_supplicant
*wpa_s
= user_data
;
710 DBusMessageIter variant_iter
, dict_iter
;
711 DBusMessageIter iter_secdev_dict_entry
, iter_secdev_dict_val
,
712 iter_secdev_dict_array
;
713 const char *dev_name
;
714 int num_vendor_extensions
= 0;
716 const struct wpabuf
*vendor_ext
[P2P_MAX_WPS_VENDOR_EXT
];
718 if (!wpa_dbus_p2p_check_enabled(wpa_s
, NULL
, NULL
, error
))
721 if (!dbus_message_iter_open_container(iter
, DBUS_TYPE_VARIANT
,
722 "a{sv}", &variant_iter
) ||
723 !wpa_dbus_dict_open_write(&variant_iter
, &dict_iter
))
727 dev_name
= wpa_s
->conf
->device_name
;
729 !wpa_dbus_dict_append_string(&dict_iter
, "DeviceName", dev_name
))
732 /* Primary device type */
733 if (!wpa_dbus_dict_append_byte_array(&dict_iter
, "PrimaryDeviceType",
734 (char *)wpa_s
->conf
->device_type
,
738 /* Secondary device types */
739 if (wpa_s
->conf
->num_sec_device_types
) {
740 if (!wpa_dbus_dict_begin_array(&dict_iter
,
741 "SecondaryDeviceTypes",
742 DBUS_TYPE_ARRAY_AS_STRING
743 DBUS_TYPE_BYTE_AS_STRING
,
744 &iter_secdev_dict_entry
,
745 &iter_secdev_dict_val
,
746 &iter_secdev_dict_array
))
749 for (i
= 0; i
< wpa_s
->conf
->num_sec_device_types
; i
++)
750 wpa_dbus_dict_bin_array_add_element(
751 &iter_secdev_dict_array
,
752 wpa_s
->conf
->sec_device_type
[i
],
755 if (!wpa_dbus_dict_end_array(&dict_iter
,
756 &iter_secdev_dict_entry
,
757 &iter_secdev_dict_val
,
758 &iter_secdev_dict_array
))
762 /* Vendor Extensions */
763 for (i
= 0; i
< P2P_MAX_WPS_VENDOR_EXT
; i
++) {
764 if (wpa_s
->conf
->wps_vendor_ext
[i
] == NULL
)
766 vendor_ext
[num_vendor_extensions
++] =
767 wpa_s
->conf
->wps_vendor_ext
[i
];
770 if (num_vendor_extensions
&&
771 !wpa_dbus_dict_append_wpabuf_array(&dict_iter
,
774 num_vendor_extensions
))
778 if (!wpa_dbus_dict_append_uint32(&dict_iter
, "GOIntent",
779 wpa_s
->conf
->p2p_go_intent
))
782 /* Persistent Reconnect */
783 if (!wpa_dbus_dict_append_bool(&dict_iter
, "PersistentReconnect",
784 wpa_s
->conf
->persistent_reconnect
))
787 /* Listen Reg Class */
788 if (!wpa_dbus_dict_append_uint32(&dict_iter
, "ListenRegClass",
789 wpa_s
->conf
->p2p_listen_reg_class
))
793 if (!wpa_dbus_dict_append_uint32(&dict_iter
, "ListenChannel",
794 wpa_s
->conf
->p2p_listen_channel
))
798 if (!wpa_dbus_dict_append_uint32(&dict_iter
, "OperRegClass",
799 wpa_s
->conf
->p2p_oper_reg_class
))
803 if (!wpa_dbus_dict_append_uint32(&dict_iter
, "OperChannel",
804 wpa_s
->conf
->p2p_oper_channel
))
808 if (wpa_s
->conf
->p2p_ssid_postfix
&&
809 !wpa_dbus_dict_append_string(&dict_iter
, "SsidPostfix",
810 wpa_s
->conf
->p2p_ssid_postfix
))
814 if (!wpa_dbus_dict_append_bool(&dict_iter
, "IntraBss",
815 wpa_s
->conf
->p2p_intra_bss
))
819 if (!wpa_dbus_dict_append_uint32(&dict_iter
, "GroupIdle",
820 wpa_s
->conf
->p2p_group_idle
))
823 /* Dissasociation low ack */
824 if (!wpa_dbus_dict_append_uint32(&dict_iter
, "disassoc_low_ack",
825 wpa_s
->conf
->disassoc_low_ack
))
828 if (!wpa_dbus_dict_close_write(&variant_iter
, &dict_iter
) ||
829 !dbus_message_iter_close_container(iter
, &variant_iter
))
835 dbus_set_error_const(error
, DBUS_ERROR_NO_MEMORY
, "no memory");
840 dbus_bool_t
wpas_dbus_setter_p2p_device_config(DBusMessageIter
*iter
,
844 struct wpa_supplicant
*wpa_s
= user_data
;
845 DBusMessageIter variant_iter
, iter_dict
;
846 struct wpa_dbus_dict_entry entry
= {.type
= DBUS_TYPE_STRING
};
849 if (!wpa_dbus_p2p_check_enabled(wpa_s
, NULL
, NULL
, error
))
852 dbus_message_iter_recurse(iter
, &variant_iter
);
853 if (!wpa_dbus_dict_open_read(&variant_iter
, &iter_dict
, error
))
856 while (wpa_dbus_dict_has_dict_entry(&iter_dict
)) {
857 if (!wpa_dbus_dict_get_entry(&iter_dict
, &entry
)) {
858 dbus_set_error_const(error
, DBUS_ERROR_INVALID_ARGS
,
859 "invalid message format");
863 if (os_strcmp(entry
.key
, "DeviceName") == 0) {
866 if (entry
.type
!= DBUS_TYPE_STRING
)
869 devname
= os_strdup(entry
.str_value
);
871 goto err_no_mem_clear
;
873 os_free(wpa_s
->conf
->device_name
);
874 wpa_s
->conf
->device_name
= devname
;
876 wpa_s
->conf
->changed_parameters
|=
877 CFG_CHANGED_DEVICE_NAME
;
878 } else if (os_strcmp(entry
.key
, "PrimaryDeviceType") == 0) {
879 if (entry
.type
!= DBUS_TYPE_ARRAY
||
880 entry
.array_type
!= DBUS_TYPE_BYTE
||
881 entry
.array_len
!= WPS_DEV_TYPE_LEN
)
884 os_memcpy(wpa_s
->conf
->device_type
,
885 entry
.bytearray_value
,
887 wpa_s
->conf
->changed_parameters
|=
888 CFG_CHANGED_DEVICE_TYPE
;
889 } else if (os_strcmp(entry
.key
, "SecondaryDeviceTypes") == 0) {
890 if (entry
.type
!= DBUS_TYPE_ARRAY
||
891 entry
.array_type
!= WPAS_DBUS_TYPE_BINARRAY
||
892 entry
.array_len
> MAX_SEC_DEVICE_TYPES
)
895 for (i
= 0; i
< entry
.array_len
; i
++)
896 if (wpabuf_len(entry
.binarray_value
[i
]) !=
898 goto err_no_mem_clear
;
899 for (i
= 0; i
< entry
.array_len
; i
++)
900 os_memcpy(wpa_s
->conf
->sec_device_type
[i
],
901 wpabuf_head(entry
.binarray_value
[i
]),
903 wpa_s
->conf
->num_sec_device_types
= entry
.array_len
;
904 wpa_s
->conf
->changed_parameters
|=
905 CFG_CHANGED_SEC_DEVICE_TYPE
;
906 } else if (os_strcmp(entry
.key
, "VendorExtension") == 0) {
907 if ((entry
.type
!= DBUS_TYPE_ARRAY
) ||
908 (entry
.array_type
!= WPAS_DBUS_TYPE_BINARRAY
) ||
909 (entry
.array_len
> P2P_MAX_WPS_VENDOR_EXT
))
912 wpa_s
->conf
->changed_parameters
|=
913 CFG_CHANGED_VENDOR_EXTENSION
;
915 for (i
= 0; i
< P2P_MAX_WPS_VENDOR_EXT
; i
++) {
916 wpabuf_free(wpa_s
->conf
->wps_vendor_ext
[i
]);
917 if (i
< entry
.array_len
) {
918 wpa_s
->conf
->wps_vendor_ext
[i
] =
919 entry
.binarray_value
[i
];
920 entry
.binarray_value
[i
] = NULL
;
922 wpa_s
->conf
->wps_vendor_ext
[i
] = NULL
;
924 } else if ((os_strcmp(entry
.key
, "GOIntent") == 0) &&
925 (entry
.type
== DBUS_TYPE_UINT32
) &&
926 (entry
.uint32_value
<= 15))
927 wpa_s
->conf
->p2p_go_intent
= entry
.uint32_value
;
928 else if ((os_strcmp(entry
.key
, "PersistentReconnect") == 0) &&
929 (entry
.type
== DBUS_TYPE_BOOLEAN
))
930 wpa_s
->conf
->persistent_reconnect
= entry
.bool_value
;
931 else if ((os_strcmp(entry
.key
, "ListenRegClass") == 0) &&
932 (entry
.type
== DBUS_TYPE_UINT32
)) {
933 wpa_s
->conf
->p2p_listen_reg_class
= entry
.uint32_value
;
934 wpa_s
->conf
->changed_parameters
|=
935 CFG_CHANGED_P2P_LISTEN_CHANNEL
;
936 } else if ((os_strcmp(entry
.key
, "ListenChannel") == 0) &&
937 (entry
.type
== DBUS_TYPE_UINT32
)) {
938 wpa_s
->conf
->p2p_listen_channel
= entry
.uint32_value
;
939 wpa_s
->conf
->changed_parameters
|=
940 CFG_CHANGED_P2P_LISTEN_CHANNEL
;
941 } else if ((os_strcmp(entry
.key
, "OperRegClass") == 0) &&
942 (entry
.type
== DBUS_TYPE_UINT32
)) {
943 wpa_s
->conf
->p2p_oper_reg_class
= entry
.uint32_value
;
944 wpa_s
->conf
->changed_parameters
|=
945 CFG_CHANGED_P2P_OPER_CHANNEL
;
946 } else if ((os_strcmp(entry
.key
, "OperChannel") == 0) &&
947 (entry
.type
== DBUS_TYPE_UINT32
)) {
948 wpa_s
->conf
->p2p_oper_channel
= entry
.uint32_value
;
949 wpa_s
->conf
->changed_parameters
|=
950 CFG_CHANGED_P2P_OPER_CHANNEL
;
951 } else if (os_strcmp(entry
.key
, "SsidPostfix") == 0) {
954 if (entry
.type
!= DBUS_TYPE_STRING
)
957 postfix
= os_strdup(entry
.str_value
);
959 goto err_no_mem_clear
;
961 os_free(wpa_s
->conf
->p2p_ssid_postfix
);
962 wpa_s
->conf
->p2p_ssid_postfix
= postfix
;
964 wpa_s
->conf
->changed_parameters
|=
965 CFG_CHANGED_P2P_SSID_POSTFIX
;
966 } else if ((os_strcmp(entry
.key
, "IntraBss") == 0) &&
967 (entry
.type
== DBUS_TYPE_BOOLEAN
)) {
968 wpa_s
->conf
->p2p_intra_bss
= entry
.bool_value
;
969 wpa_s
->conf
->changed_parameters
|=
970 CFG_CHANGED_P2P_INTRA_BSS
;
971 } else if ((os_strcmp(entry
.key
, "GroupIdle") == 0) &&
972 (entry
.type
== DBUS_TYPE_UINT32
))
973 wpa_s
->conf
->p2p_group_idle
= entry
.uint32_value
;
974 else if (os_strcmp(entry
.key
, "disassoc_low_ack") == 0 &&
975 entry
.type
== DBUS_TYPE_UINT32
)
976 wpa_s
->conf
->disassoc_low_ack
= entry
.uint32_value
;
980 wpa_dbus_dict_entry_clear(&entry
);
983 if (wpa_s
->conf
->changed_parameters
) {
984 /* Some changed parameters requires to update config*/
985 wpa_supplicant_update_config(wpa_s
);
991 dbus_set_error_const(error
, DBUS_ERROR_INVALID_ARGS
,
992 "invalid message format");
993 wpa_dbus_dict_entry_clear(&entry
);
997 dbus_set_error_const(error
, DBUS_ERROR_NO_MEMORY
, "no memory");
998 wpa_dbus_dict_entry_clear(&entry
);
1003 dbus_bool_t
wpas_dbus_getter_p2p_peers(DBusMessageIter
*iter
, DBusError
*error
,
1006 struct wpa_supplicant
*wpa_s
= user_data
;
1007 struct p2p_data
*p2p
= wpa_s
->global
->p2p
;
1008 int next
= 0, i
= 0;
1009 int num
= 0, out_of_mem
= 0;
1011 const struct p2p_peer_info
*peer_info
= NULL
;
1012 dbus_bool_t success
= FALSE
;
1014 struct dl_list peer_objpath_list
;
1015 struct peer_objpath_node
{
1016 struct dl_list list
;
1017 char path
[WPAS_DBUS_OBJECT_PATH_MAX
];
1020 char **peer_obj_paths
= NULL
;
1022 if (!wpa_dbus_p2p_check_enabled(wpa_s
, NULL
, NULL
, error
))
1025 dl_list_init(&peer_objpath_list
);
1027 /* Get the first peer info */
1028 peer_info
= p2p_get_peer_found(p2p
, NULL
, next
);
1030 /* Get next and accumulate them */
1032 while (peer_info
!= NULL
) {
1033 node
= os_zalloc(sizeof(struct peer_objpath_node
));
1039 addr
= peer_info
->p2p_device_addr
;
1040 os_snprintf(node
->path
, WPAS_DBUS_OBJECT_PATH_MAX
,
1041 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART
1043 wpa_s
->dbus_new_path
, MAC2STR(addr
));
1044 dl_list_add_tail(&peer_objpath_list
, &node
->list
);
1047 peer_info
= p2p_get_peer_found(p2p
, addr
, next
);
1051 * Now construct the peer object paths in a form suitable for
1052 * array_property_getter helper below.
1054 peer_obj_paths
= os_calloc(num
, sizeof(char *));
1056 if (!peer_obj_paths
) {
1061 dl_list_for_each_safe(node
, tmp
, &peer_objpath_list
,
1062 struct peer_objpath_node
, list
)
1063 peer_obj_paths
[i
++] = node
->path
;
1065 success
= wpas_dbus_simple_array_property_getter(iter
,
1066 DBUS_TYPE_OBJECT_PATH
,
1067 peer_obj_paths
, num
,
1072 os_free(peer_obj_paths
);
1074 dl_list_for_each_safe(node
, tmp
, &peer_objpath_list
,
1075 struct peer_objpath_node
, list
) {
1076 dl_list_del(&node
->list
);
1080 dbus_set_error_const(error
, DBUS_ERROR_NO_MEMORY
, "no memory");
1086 enum wpas_p2p_role
{
1087 WPAS_P2P_ROLE_DEVICE
,
1089 WPAS_P2P_ROLE_CLIENT
,
1092 static enum wpas_p2p_role
wpas_get_p2p_role(struct wpa_supplicant
*wpa_s
)
1094 struct wpa_ssid
*ssid
= wpa_s
->current_ssid
;
1097 return WPAS_P2P_ROLE_DEVICE
;
1098 if (wpa_s
->wpa_state
!= WPA_COMPLETED
)
1099 return WPAS_P2P_ROLE_DEVICE
;
1101 switch (ssid
->mode
) {
1102 case WPAS_MODE_P2P_GO
:
1103 case WPAS_MODE_P2P_GROUP_FORMATION
:
1104 return WPAS_P2P_ROLE_GO
;
1105 case WPAS_MODE_INFRA
:
1106 if (ssid
->p2p_group
)
1107 return WPAS_P2P_ROLE_CLIENT
;
1108 return WPAS_P2P_ROLE_DEVICE
;
1110 return WPAS_P2P_ROLE_DEVICE
;
1115 dbus_bool_t
wpas_dbus_getter_p2p_role(DBusMessageIter
*iter
, DBusError
*error
,
1118 struct wpa_supplicant
*wpa_s
= user_data
;
1121 switch (wpas_get_p2p_role(wpa_s
)) {
1122 case WPAS_P2P_ROLE_GO
:
1125 case WPAS_P2P_ROLE_CLIENT
:
1132 return wpas_dbus_simple_property_getter(iter
, DBUS_TYPE_STRING
, &str
,
1137 dbus_bool_t
wpas_dbus_getter_p2p_group(DBusMessageIter
*iter
, DBusError
*error
,
1140 struct wpa_supplicant
*wpa_s
= user_data
;
1141 char path_buf
[WPAS_DBUS_OBJECT_PATH_MAX
];
1142 char *dbus_groupobj_path
= path_buf
;
1144 if (wpa_s
->dbus_groupobj_path
== NULL
)
1145 os_snprintf(dbus_groupobj_path
, WPAS_DBUS_OBJECT_PATH_MAX
,
1148 os_snprintf(dbus_groupobj_path
, WPAS_DBUS_OBJECT_PATH_MAX
,
1149 "%s", wpa_s
->dbus_groupobj_path
);
1151 return wpas_dbus_simple_property_getter(iter
, DBUS_TYPE_OBJECT_PATH
,
1152 &dbus_groupobj_path
, error
);
1156 dbus_bool_t
wpas_dbus_getter_p2p_peergo(DBusMessageIter
*iter
,
1157 DBusError
*error
, void *user_data
)
1159 struct wpa_supplicant
*wpa_s
= user_data
;
1160 char go_peer_obj_path
[WPAS_DBUS_OBJECT_PATH_MAX
], *path
;
1162 if (wpas_get_p2p_role(wpa_s
) != WPAS_P2P_ROLE_CLIENT
)
1163 os_snprintf(go_peer_obj_path
, WPAS_DBUS_OBJECT_PATH_MAX
, "/");
1165 os_snprintf(go_peer_obj_path
, WPAS_DBUS_OBJECT_PATH_MAX
,
1166 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART
"/"
1168 wpa_s
->dbus_new_path
, MAC2STR(wpa_s
->go_dev_addr
));
1170 path
= go_peer_obj_path
;
1171 return wpas_dbus_simple_property_getter(iter
, DBUS_TYPE_OBJECT_PATH
,
1177 * Peer object properties accessor methods
1180 dbus_bool_t
wpas_dbus_getter_p2p_peer_device_name(DBusMessageIter
*iter
,
1184 struct peer_handler_args
*peer_args
= user_data
;
1185 const struct p2p_peer_info
*info
;
1188 if (!wpa_dbus_p2p_check_enabled(peer_args
->wpa_s
, NULL
, NULL
, error
))
1191 /* get the peer info */
1192 info
= p2p_get_peer_found(peer_args
->wpa_s
->global
->p2p
,
1193 peer_args
->p2p_device_addr
, 0);
1195 dbus_set_error(error
, DBUS_ERROR_FAILED
,
1196 "failed to find peer");
1200 tmp
= os_strdup(info
->device_name
);
1202 dbus_set_error_const(error
, DBUS_ERROR_NO_MEMORY
, "no memory");
1206 if (!wpas_dbus_simple_property_getter(iter
, DBUS_TYPE_STRING
, &tmp
,
1208 dbus_set_error_const(error
, DBUS_ERROR_NO_MEMORY
, "no memory");
1218 dbus_bool_t
wpas_dbus_getter_p2p_peer_primary_device_type(
1219 DBusMessageIter
*iter
, DBusError
*error
, void *user_data
)
1221 struct peer_handler_args
*peer_args
= user_data
;
1222 const struct p2p_peer_info
*info
;
1224 info
= p2p_get_peer_found(peer_args
->wpa_s
->global
->p2p
,
1225 peer_args
->p2p_device_addr
, 0);
1227 dbus_set_error(error
, DBUS_ERROR_FAILED
,
1228 "failed to find peer");
1232 if (!wpas_dbus_simple_array_property_getter(iter
, DBUS_TYPE_BYTE
,
1235 WPS_DEV_TYPE_LEN
, error
)) {
1236 dbus_set_error_const(error
, DBUS_ERROR_NO_MEMORY
, "no memory");
1244 dbus_bool_t
wpas_dbus_getter_p2p_peer_config_method(DBusMessageIter
*iter
,
1248 struct peer_handler_args
*peer_args
= user_data
;
1249 const struct p2p_peer_info
*info
;
1251 info
= p2p_get_peer_found(peer_args
->wpa_s
->global
->p2p
,
1252 peer_args
->p2p_device_addr
, 0);
1254 dbus_set_error(error
, DBUS_ERROR_FAILED
,
1255 "failed to find peer");
1259 if (!wpas_dbus_simple_property_getter(iter
, DBUS_TYPE_UINT16
,
1260 &info
->config_methods
, error
)) {
1261 dbus_set_error_const(error
, DBUS_ERROR_NO_MEMORY
, "no memory");
1269 dbus_bool_t
wpas_dbus_getter_p2p_peer_level(DBusMessageIter
*iter
,
1273 struct peer_handler_args
*peer_args
= user_data
;
1274 const struct p2p_peer_info
*info
;
1276 info
= p2p_get_peer_found(peer_args
->wpa_s
->global
->p2p
,
1277 peer_args
->p2p_device_addr
, 0);
1279 dbus_set_error(error
, DBUS_ERROR_FAILED
,
1280 "failed to find peer");
1284 if (!wpas_dbus_simple_property_getter(iter
, DBUS_TYPE_INT32
,
1285 &info
->level
, error
)) {
1286 dbus_set_error_const(error
, DBUS_ERROR_NO_MEMORY
, "no memory");
1294 dbus_bool_t
wpas_dbus_getter_p2p_peer_device_capability(DBusMessageIter
*iter
,
1298 struct peer_handler_args
*peer_args
= user_data
;
1299 const struct p2p_peer_info
*info
;
1301 info
= p2p_get_peer_found(peer_args
->wpa_s
->global
->p2p
,
1302 peer_args
->p2p_device_addr
, 0);
1304 dbus_set_error(error
, DBUS_ERROR_FAILED
,
1305 "failed to find peer");
1309 if (!wpas_dbus_simple_property_getter(iter
, DBUS_TYPE_BYTE
,
1310 &info
->dev_capab
, error
)) {
1311 dbus_set_error_const(error
, DBUS_ERROR_NO_MEMORY
, "no memory");
1319 dbus_bool_t
wpas_dbus_getter_p2p_peer_group_capability(DBusMessageIter
*iter
,
1323 struct peer_handler_args
*peer_args
= user_data
;
1324 const struct p2p_peer_info
*info
;
1326 info
= p2p_get_peer_found(peer_args
->wpa_s
->global
->p2p
,
1327 peer_args
->p2p_device_addr
, 0);
1329 dbus_set_error(error
, DBUS_ERROR_FAILED
,
1330 "failed to find peer");
1334 if (!wpas_dbus_simple_property_getter(iter
, DBUS_TYPE_BYTE
,
1335 &info
->group_capab
, error
)) {
1336 dbus_set_error_const(error
, DBUS_ERROR_NO_MEMORY
, "no memory");
1344 dbus_bool_t
wpas_dbus_getter_p2p_peer_secondary_device_types(
1345 DBusMessageIter
*iter
, DBusError
*error
, void *user_data
)
1347 struct peer_handler_args
*peer_args
= user_data
;
1348 const struct p2p_peer_info
*info
;
1349 DBusMessageIter variant_iter
, array_iter
;
1351 info
= p2p_get_peer_found(peer_args
->wpa_s
->global
->p2p
,
1352 peer_args
->p2p_device_addr
, 0);
1354 dbus_set_error(error
, DBUS_ERROR_FAILED
,
1355 "failed to find peer");
1359 if (!dbus_message_iter_open_container(iter
, DBUS_TYPE_VARIANT
,
1360 DBUS_TYPE_ARRAY_AS_STRING
1361 DBUS_TYPE_ARRAY_AS_STRING
1362 DBUS_TYPE_BYTE_AS_STRING
,
1364 dbus_set_error(error
, DBUS_ERROR_FAILED
,
1365 "%s: failed to construct message 1", __func__
);
1369 if (!dbus_message_iter_open_container(&variant_iter
, DBUS_TYPE_ARRAY
,
1370 DBUS_TYPE_ARRAY_AS_STRING
1371 DBUS_TYPE_BYTE_AS_STRING
,
1373 dbus_set_error(error
, DBUS_ERROR_FAILED
,
1374 "%s: failed to construct message 2", __func__
);
1378 if (info
->wps_sec_dev_type_list_len
) {
1379 const u8
*sec_dev_type_list
= info
->wps_sec_dev_type_list
;
1380 int num_sec_device_types
=
1381 info
->wps_sec_dev_type_list_len
/ WPS_DEV_TYPE_LEN
;
1383 DBusMessageIter inner_array_iter
;
1385 for (i
= 0; i
< num_sec_device_types
; i
++) {
1386 if (!dbus_message_iter_open_container(
1387 &array_iter
, DBUS_TYPE_ARRAY
,
1388 DBUS_TYPE_BYTE_AS_STRING
,
1389 &inner_array_iter
)) {
1390 dbus_set_error(error
, DBUS_ERROR_FAILED
,
1391 "%s: failed to construct "
1397 if (!dbus_message_iter_append_fixed_array(
1398 &inner_array_iter
, DBUS_TYPE_BYTE
,
1399 &sec_dev_type_list
, WPS_DEV_TYPE_LEN
)) {
1400 dbus_set_error(error
, DBUS_ERROR_FAILED
,
1401 "%s: failed to construct "
1407 if (!dbus_message_iter_close_container(
1408 &array_iter
, &inner_array_iter
)) {
1409 dbus_set_error(error
, DBUS_ERROR_FAILED
,
1410 "%s: failed to construct "
1416 sec_dev_type_list
+= WPS_DEV_TYPE_LEN
;
1420 if (!dbus_message_iter_close_container(&variant_iter
, &array_iter
)) {
1421 dbus_set_error(error
, DBUS_ERROR_FAILED
,
1422 "%s: failed to construct message 6", __func__
);
1426 if (!dbus_message_iter_close_container(iter
, &variant_iter
)) {
1427 dbus_set_error(error
, DBUS_ERROR_FAILED
,
1428 "%s: failed to construct message 7", __func__
);
1436 dbus_bool_t
wpas_dbus_getter_p2p_peer_vendor_extension(DBusMessageIter
*iter
,
1440 struct wpabuf
*vendor_extension
[P2P_MAX_WPS_VENDOR_EXT
];
1442 struct peer_handler_args
*peer_args
= user_data
;
1443 const struct p2p_peer_info
*info
;
1445 info
= p2p_get_peer_found(peer_args
->wpa_s
->global
->p2p
,
1446 peer_args
->p2p_device_addr
, 0);
1448 dbus_set_error(error
, DBUS_ERROR_FAILED
,
1449 "failed to find peer");
1453 /* Add WPS vendor extensions attribute */
1454 for (i
= 0, num
= 0; i
< P2P_MAX_WPS_VENDOR_EXT
; i
++) {
1455 if (info
->wps_vendor_ext
[i
] == NULL
)
1457 vendor_extension
[num
] = info
->wps_vendor_ext
[i
];
1461 if (!wpas_dbus_simple_array_array_property_getter(iter
, DBUS_TYPE_BYTE
,
1470 dbus_bool_t
wpas_dbus_getter_p2p_peer_ies(DBusMessageIter
*iter
,
1471 DBusError
*error
, void *user_data
)
1473 dbus_bool_t success
;
1474 /* struct peer_handler_args *peer_args = user_data; */
1476 success
= wpas_dbus_simple_array_property_getter(iter
, DBUS_TYPE_BYTE
,
1483 * wpas_dbus_getter_persistent_groups - Get array of persistent group objects
1484 * @iter: Pointer to incoming dbus message iter
1485 * @error: Location to store error on failure
1486 * @user_data: Function specific data
1487 * Returns: TRUE on success, FALSE on failure
1489 * Getter for "PersistentGroups" property.
1491 dbus_bool_t
wpas_dbus_getter_persistent_groups(DBusMessageIter
*iter
,
1495 struct wpa_supplicant
*wpa_s
= user_data
;
1496 struct wpa_ssid
*ssid
;
1498 unsigned int i
= 0, num
= 0;
1499 dbus_bool_t success
= FALSE
;
1501 if (wpa_s
->conf
== NULL
) {
1502 wpa_printf(MSG_ERROR
, "dbus: %s: "
1503 "An error occurred getting persistent groups list",
1505 dbus_set_error_const(error
, DBUS_ERROR_FAILED
, "an error "
1506 "occurred getting persistent groups list");
1510 for (ssid
= wpa_s
->conf
->ssid
; ssid
; ssid
= ssid
->next
)
1511 if (network_is_persistent_group(ssid
))
1514 paths
= os_calloc(num
, sizeof(char *));
1516 dbus_set_error_const(error
, DBUS_ERROR_NO_MEMORY
, "no memory");
1520 /* Loop through configured networks and append object path of each */
1521 for (ssid
= wpa_s
->conf
->ssid
; ssid
; ssid
= ssid
->next
) {
1522 if (!network_is_persistent_group(ssid
))
1524 paths
[i
] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX
);
1525 if (paths
[i
] == NULL
) {
1526 dbus_set_error_const(error
, DBUS_ERROR_NO_MEMORY
,
1530 /* Construct the object path for this network. */
1531 os_snprintf(paths
[i
++], WPAS_DBUS_OBJECT_PATH_MAX
,
1532 "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART
"/%d",
1533 wpa_s
->dbus_new_path
, ssid
->id
);
1536 success
= wpas_dbus_simple_array_property_getter(iter
,
1537 DBUS_TYPE_OBJECT_PATH
,
1542 os_free(paths
[--i
]);
1549 * wpas_dbus_getter_persistent_group_properties - Get options for a persistent
1551 * @iter: Pointer to incoming dbus message iter
1552 * @error: Location to store error on failure
1553 * @user_data: Function specific data
1554 * Returns: TRUE on success, FALSE on failure
1556 * Getter for "Properties" property of a persistent group.
1558 dbus_bool_t
wpas_dbus_getter_persistent_group_properties(DBusMessageIter
*iter
,
1562 struct network_handler_args
*net
= user_data
;
1564 /* Leveraging the fact that persistent group object is still
1565 * represented in same manner as network within.
1567 return wpas_dbus_getter_network_properties(iter
, error
, net
);
1572 * wpas_dbus_setter_persistent_group_properties - Get options for a persistent
1574 * @iter: Pointer to incoming dbus message iter
1575 * @error: Location to store error on failure
1576 * @user_data: Function specific data
1577 * Returns: TRUE on success, FALSE on failure
1579 * Setter for "Properties" property of a persistent group.
1581 dbus_bool_t
wpas_dbus_setter_persistent_group_properties(DBusMessageIter
*iter
,
1585 struct network_handler_args
*net
= user_data
;
1586 struct wpa_ssid
*ssid
= net
->ssid
;
1587 DBusMessageIter variant_iter
;
1590 * Leveraging the fact that persistent group object is still
1591 * represented in same manner as network within.
1593 dbus_message_iter_recurse(iter
, &variant_iter
);
1594 return set_network_properties(net
->wpa_s
, ssid
, &variant_iter
, error
);
1599 * wpas_dbus_new_iface_add_persistent_group - Add a new configured
1601 * @message: Pointer to incoming dbus message
1602 * @wpa_s: wpa_supplicant structure for a network interface
1603 * Returns: A dbus message containing the object path of the new
1606 * Handler function for "AddPersistentGroup" method call of a P2P Device
1609 DBusMessage
* wpas_dbus_handler_add_persistent_group(
1610 DBusMessage
*message
, struct wpa_supplicant
*wpa_s
)
1612 DBusMessage
*reply
= NULL
;
1613 DBusMessageIter iter
;
1614 struct wpa_ssid
*ssid
= NULL
;
1615 char path_buf
[WPAS_DBUS_OBJECT_PATH_MAX
], *path
= path_buf
;
1618 dbus_message_iter_init(message
, &iter
);
1620 ssid
= wpa_config_add_network(wpa_s
->conf
);
1622 wpa_printf(MSG_ERROR
, "dbus: %s: "
1623 "Cannot add new persistent group", __func__
);
1624 reply
= wpas_dbus_error_unknown_error(
1626 "wpa_supplicant could not add "
1627 "a persistent group on this interface.");
1631 /* Mark the ssid as being a persistent group before the notification */
1633 ssid
->p2p_persistent_group
= 1;
1634 wpas_notify_persistent_group_added(wpa_s
, ssid
);
1636 wpa_config_set_network_defaults(ssid
);
1638 dbus_error_init(&error
);
1639 if (!set_network_properties(wpa_s
, ssid
, &iter
, &error
)) {
1640 wpa_printf(MSG_DEBUG
, "dbus: %s: "
1641 "Control interface could not set persistent group "
1642 "properties", __func__
);
1643 reply
= wpas_dbus_reply_new_from_error(message
, &error
,
1644 DBUS_ERROR_INVALID_ARGS
,
1645 "Failed to set network "
1647 dbus_error_free(&error
);
1651 /* Construct the object path for this network. */
1652 os_snprintf(path
, WPAS_DBUS_OBJECT_PATH_MAX
,
1653 "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART
"/%d",
1654 wpa_s
->dbus_new_path
, ssid
->id
);
1656 reply
= dbus_message_new_method_return(message
);
1657 if (reply
== NULL
) {
1658 reply
= dbus_message_new_error(message
, DBUS_ERROR_NO_MEMORY
,
1662 if (!dbus_message_append_args(reply
, DBUS_TYPE_OBJECT_PATH
, &path
,
1663 DBUS_TYPE_INVALID
)) {
1664 dbus_message_unref(reply
);
1665 reply
= dbus_message_new_error(message
, DBUS_ERROR_NO_MEMORY
,
1674 wpas_notify_persistent_group_removed(wpa_s
, ssid
);
1675 wpa_config_remove_network(wpa_s
->conf
, ssid
->id
);
1682 * wpas_dbus_handler_remove_persistent_group - Remove a configured persistent
1684 * @message: Pointer to incoming dbus message
1685 * @wpa_s: wpa_supplicant structure for a network interface
1686 * Returns: NULL on success or dbus error on failure
1688 * Handler function for "RemovePersistentGroup" method call of a P2P Device
1691 DBusMessage
* wpas_dbus_handler_remove_persistent_group(
1692 DBusMessage
*message
, struct wpa_supplicant
*wpa_s
)
1694 DBusMessage
*reply
= NULL
;
1696 char *iface
= NULL
, *persistent_group_id
= NULL
;
1698 struct wpa_ssid
*ssid
;
1700 dbus_message_get_args(message
, NULL
, DBUS_TYPE_OBJECT_PATH
, &op
,
1704 * Extract the network ID and ensure the network is actually a child of
1707 iface
= wpas_dbus_new_decompose_object_path(op
, 1,
1708 &persistent_group_id
,
1710 if (iface
== NULL
|| os_strcmp(iface
, wpa_s
->dbus_new_path
) != 0) {
1711 reply
= wpas_dbus_error_invalid_args(message
, op
);
1715 id
= strtoul(persistent_group_id
, NULL
, 10);
1716 if (errno
== EINVAL
) {
1717 reply
= wpas_dbus_error_invalid_args(message
, op
);
1721 ssid
= wpa_config_get_network(wpa_s
->conf
, id
);
1723 reply
= wpas_dbus_error_persistent_group_unknown(message
);
1727 wpas_notify_persistent_group_removed(wpa_s
, ssid
);
1729 if (wpa_config_remove_network(wpa_s
->conf
, id
) < 0) {
1730 wpa_printf(MSG_ERROR
, "dbus: %s: "
1731 "error occurred when removing persistent group %d",
1733 reply
= wpas_dbus_error_unknown_error(
1735 "error removing the specified persistent group on "
1742 os_free(persistent_group_id
);
1747 static void remove_persistent_group(struct wpa_supplicant
*wpa_s
,
1748 struct wpa_ssid
*ssid
)
1750 wpas_notify_persistent_group_removed(wpa_s
, ssid
);
1752 if (wpa_config_remove_network(wpa_s
->conf
, ssid
->id
) < 0) {
1753 wpa_printf(MSG_ERROR
, "dbus: %s: "
1754 "error occurred when removing persistent group %d",
1755 __func__
, ssid
->id
);
1762 * wpas_dbus_handler_remove_all_persistent_groups - Remove all configured
1764 * @message: Pointer to incoming dbus message
1765 * @wpa_s: wpa_supplicant structure for a network interface
1766 * Returns: NULL on success or dbus error on failure
1768 * Handler function for "RemoveAllPersistentGroups" method call of a
1769 * P2P Device interface.
1771 DBusMessage
* wpas_dbus_handler_remove_all_persistent_groups(
1772 DBusMessage
*message
, struct wpa_supplicant
*wpa_s
)
1774 struct wpa_ssid
*ssid
, *next
;
1775 struct wpa_config
*config
;
1777 config
= wpa_s
->conf
;
1778 ssid
= config
->ssid
;
1781 if (network_is_persistent_group(ssid
))
1782 remove_persistent_group(wpa_s
, ssid
);
1790 * Group object properties accessor methods
1793 dbus_bool_t
wpas_dbus_getter_p2p_group_members(DBusMessageIter
*iter
,
1797 struct wpa_supplicant
*wpa_s
= user_data
;
1798 struct wpa_ssid
*ssid
;
1799 unsigned int num_members
;
1804 dbus_bool_t success
= FALSE
;
1806 /* Verify correct role for this property */
1807 if (wpas_get_p2p_role(wpa_s
) != WPAS_P2P_ROLE_GO
) {
1808 return wpas_dbus_simple_array_property_getter(
1809 iter
, DBUS_TYPE_OBJECT_PATH
, NULL
, 0, error
);
1812 ssid
= wpa_s
->conf
->ssid
;
1813 /* At present WPAS P2P_GO mode only applicable for p2p_go */
1814 if (ssid
->mode
!= WPAS_MODE_P2P_GO
&&
1815 ssid
->mode
!= WPAS_MODE_AP
&&
1816 ssid
->mode
!= WPAS_MODE_P2P_GROUP_FORMATION
)
1819 num_members
= p2p_get_group_num_members(wpa_s
->p2p_group
);
1821 paths
= os_calloc(num_members
, sizeof(char *));
1826 while ((addr
= p2p_iterate_group_members(wpa_s
->p2p_group
, &next
))) {
1827 paths
[i
] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX
);
1830 os_snprintf(paths
[i
], WPAS_DBUS_OBJECT_PATH_MAX
,
1831 "%s/" WPAS_DBUS_NEW_P2P_GROUPMEMBERS_PART
1833 wpa_s
->dbus_groupobj_path
, MAC2STR(addr
));
1837 success
= wpas_dbus_simple_array_property_getter(iter
,
1838 DBUS_TYPE_OBJECT_PATH
,
1842 for (i
= 0; i
< num_members
; i
++)
1848 dbus_set_error_const(error
, DBUS_ERROR_NO_MEMORY
, "no memory");
1850 for (i
= 0; i
< num_members
; i
++)
1858 dbus_bool_t
wpas_dbus_getter_p2p_group_ssid(DBusMessageIter
*iter
,
1859 DBusError
*error
, void *user_data
)
1861 struct wpa_supplicant
*wpa_s
= user_data
;
1862 if (wpa_s
->current_ssid
== NULL
)
1864 return wpas_dbus_simple_array_property_getter(
1865 iter
, DBUS_TYPE_BYTE
, wpa_s
->current_ssid
->ssid
,
1866 wpa_s
->current_ssid
->ssid_len
, error
);
1870 dbus_bool_t
wpas_dbus_getter_p2p_group_bssid(DBusMessageIter
*iter
,
1874 struct wpa_supplicant
*wpa_s
= user_data
;
1875 u8 role
= wpas_get_p2p_role(wpa_s
);
1878 if (role
== WPAS_P2P_ROLE_CLIENT
) {
1879 if (wpa_s
->current_ssid
== NULL
)
1881 p_bssid
= wpa_s
->current_ssid
->bssid
;
1883 if (wpa_s
->ap_iface
== NULL
)
1885 p_bssid
= wpa_s
->ap_iface
->bss
[0]->own_addr
;
1888 return wpas_dbus_simple_array_property_getter(iter
, DBUS_TYPE_BYTE
,
1894 dbus_bool_t
wpas_dbus_getter_p2p_group_frequency(DBusMessageIter
*iter
,
1898 struct wpa_supplicant
*wpa_s
= user_data
;
1900 u8 role
= wpas_get_p2p_role(wpa_s
);
1902 if (role
== WPAS_P2P_ROLE_CLIENT
) {
1903 if (wpa_s
->go_params
== NULL
)
1905 op_freq
= wpa_s
->go_params
->freq
;
1907 if (wpa_s
->ap_iface
== NULL
)
1909 op_freq
= wpa_s
->ap_iface
->freq
;
1912 return wpas_dbus_simple_property_getter(iter
, DBUS_TYPE_UINT16
,
1917 dbus_bool_t
wpas_dbus_getter_p2p_group_passphrase(DBusMessageIter
*iter
,
1921 struct wpa_supplicant
*wpa_s
= user_data
;
1922 u8 role
= wpas_get_p2p_role(wpa_s
);
1923 char *p_pass
= NULL
;
1925 /* Verify correct role for this property */
1926 if (role
== WPAS_P2P_ROLE_GO
) {
1927 if (wpa_s
->current_ssid
== NULL
)
1929 p_pass
= wpa_s
->current_ssid
->passphrase
;
1933 return wpas_dbus_simple_property_getter(iter
, DBUS_TYPE_STRING
,
1939 dbus_bool_t
wpas_dbus_getter_p2p_group_psk(DBusMessageIter
*iter
,
1940 DBusError
*error
, void *user_data
)
1942 struct wpa_supplicant
*wpa_s
= user_data
;
1943 u8 role
= wpas_get_p2p_role(wpa_s
);
1947 /* Verify correct role for this property */
1948 if (role
== WPAS_P2P_ROLE_CLIENT
) {
1949 if (wpa_s
->current_ssid
== NULL
)
1951 p_psk
= wpa_s
->current_ssid
->psk
;
1955 return wpas_dbus_simple_array_property_getter(iter
, DBUS_TYPE_BYTE
,
1956 &p_psk
, psk_len
, error
);
1960 dbus_bool_t
wpas_dbus_getter_p2p_group_vendor_ext(DBusMessageIter
*iter
,
1964 struct wpa_supplicant
*wpa_s
= user_data
;
1965 struct hostapd_data
*hapd
;
1966 struct wpabuf
*vendor_ext
[MAX_WPS_VENDOR_EXTENSIONS
];
1967 int num_vendor_ext
= 0;
1970 /* Verify correct role for this property */
1971 if (wpas_get_p2p_role(wpa_s
) == WPAS_P2P_ROLE_GO
) {
1972 if (wpa_s
->ap_iface
== NULL
)
1974 hapd
= wpa_s
->ap_iface
->bss
[0];
1976 /* Parse WPS Vendor Extensions sent in Beacon/Probe Response */
1977 for (i
= 0; i
< MAX_WPS_VENDOR_EXTENSIONS
; i
++) {
1978 if (hapd
->conf
->wps_vendor_ext
[i
] == NULL
)
1979 vendor_ext
[i
] = NULL
;
1981 vendor_ext
[num_vendor_ext
++] =
1982 hapd
->conf
->wps_vendor_ext
[i
];
1987 /* Return vendor extensions or no data */
1988 return wpas_dbus_simple_array_array_property_getter(iter
,
1996 dbus_bool_t
wpas_dbus_setter_p2p_group_vendor_ext(DBusMessageIter
*iter
,
2000 struct wpa_supplicant
*wpa_s
= user_data
;
2001 DBusMessageIter variant_iter
, iter_dict
;
2002 struct wpa_dbus_dict_entry entry
= { .type
= DBUS_TYPE_STRING
};
2004 struct hostapd_data
*hapd
= NULL
;
2006 if (wpas_get_p2p_role(wpa_s
) == WPAS_P2P_ROLE_GO
&&
2007 wpa_s
->ap_iface
!= NULL
)
2008 hapd
= wpa_s
->ap_iface
->bss
[0];
2012 dbus_message_iter_recurse(iter
, &variant_iter
);
2013 if (!wpa_dbus_dict_open_read(&variant_iter
, &iter_dict
, error
))
2016 while (wpa_dbus_dict_has_dict_entry(&iter_dict
)) {
2017 if (!wpa_dbus_dict_get_entry(&iter_dict
, &entry
)) {
2018 dbus_set_error_const(error
, DBUS_ERROR_INVALID_ARGS
,
2019 "invalid message format");
2023 if (os_strcmp(entry
.key
, "WPSVendorExtensions") == 0) {
2024 if (entry
.type
!= DBUS_TYPE_ARRAY
||
2025 entry
.array_type
!= WPAS_DBUS_TYPE_BINARRAY
||
2026 entry
.array_len
> MAX_WPS_VENDOR_EXTENSIONS
)
2029 for (i
= 0; i
< MAX_WPS_VENDOR_EXTENSIONS
; i
++) {
2030 if (i
< entry
.array_len
) {
2031 hapd
->conf
->wps_vendor_ext
[i
] =
2032 entry
.binarray_value
[i
];
2033 entry
.binarray_value
[i
] = NULL
;
2035 hapd
->conf
->wps_vendor_ext
[i
] = NULL
;
2038 hostapd_update_wps(hapd
);
2042 wpa_dbus_dict_entry_clear(&entry
);
2048 wpa_dbus_dict_entry_clear(&entry
);
2049 dbus_set_error_const(error
, DBUS_ERROR_INVALID_ARGS
,
2050 "invalid message format");
2055 DBusMessage
* wpas_dbus_handler_p2p_add_service(DBusMessage
*message
,
2056 struct wpa_supplicant
*wpa_s
)
2058 DBusMessageIter iter_dict
;
2059 DBusMessage
*reply
= NULL
;
2060 DBusMessageIter iter
;
2061 struct wpa_dbus_dict_entry entry
;
2064 char *service
= NULL
;
2065 struct wpabuf
*query
= NULL
;
2066 struct wpabuf
*resp
= NULL
;
2069 dbus_message_iter_init(message
, &iter
);
2071 if (!wpa_dbus_dict_open_read(&iter
, &iter_dict
, NULL
))
2074 while (wpa_dbus_dict_has_dict_entry(&iter_dict
)) {
2075 if (!wpa_dbus_dict_get_entry(&iter_dict
, &entry
))
2078 if (!os_strcmp(entry
.key
, "service_type") &&
2079 (entry
.type
== DBUS_TYPE_STRING
)) {
2080 if (!os_strcmp(entry
.str_value
, "upnp"))
2082 else if (!os_strcmp(entry
.str_value
, "bonjour"))
2086 } else if (!os_strcmp(entry
.key
, "version") &&
2087 entry
.type
== DBUS_TYPE_INT32
) {
2088 version
= entry
.uint32_value
;
2089 } else if (!os_strcmp(entry
.key
, "service") &&
2090 (entry
.type
== DBUS_TYPE_STRING
)) {
2091 service
= os_strdup(entry
.str_value
);
2092 } else if (!os_strcmp(entry
.key
, "query")) {
2093 if ((entry
.type
!= DBUS_TYPE_ARRAY
) ||
2094 (entry
.array_type
!= DBUS_TYPE_BYTE
))
2096 query
= wpabuf_alloc_copy(
2097 entry
.bytearray_value
,
2099 } else if (!os_strcmp(entry
.key
, "response")) {
2100 if ((entry
.type
!= DBUS_TYPE_ARRAY
) ||
2101 (entry
.array_type
!= DBUS_TYPE_BYTE
))
2103 resp
= wpabuf_alloc_copy(entry
.bytearray_value
,
2106 wpa_dbus_dict_entry_clear(&entry
);
2110 if (version
<= 0 || service
== NULL
)
2113 if (wpas_p2p_service_add_upnp(wpa_s
, version
, service
) != 0)
2118 } else if (bonjour
== 1) {
2119 if (query
== NULL
|| resp
== NULL
)
2122 if (wpas_p2p_service_add_bonjour(wpa_s
, query
, resp
) < 0)
2131 wpa_dbus_dict_entry_clear(&entry
);
2136 return wpas_dbus_error_invalid_args(message
, NULL
);
2140 DBusMessage
* wpas_dbus_handler_p2p_delete_service(
2141 DBusMessage
*message
, struct wpa_supplicant
*wpa_s
)
2143 DBusMessageIter iter_dict
;
2144 DBusMessage
*reply
= NULL
;
2145 DBusMessageIter iter
;
2146 struct wpa_dbus_dict_entry entry
;
2150 char *service
= NULL
;
2151 struct wpabuf
*query
= NULL
;
2154 dbus_message_iter_init(message
, &iter
);
2156 if (!wpa_dbus_dict_open_read(&iter
, &iter_dict
, NULL
))
2159 if (wpa_dbus_dict_has_dict_entry(&iter_dict
)) {
2160 if (!wpa_dbus_dict_get_entry(&iter_dict
, &entry
))
2163 if (!os_strcmp(entry
.key
, "service_type") &&
2164 (entry
.type
== DBUS_TYPE_STRING
)) {
2165 if (!os_strcmp(entry
.str_value
, "upnp"))
2167 else if (!os_strcmp(entry
.str_value
, "bonjour"))
2171 wpa_dbus_dict_entry_clear(&entry
);
2175 while (wpa_dbus_dict_has_dict_entry(&iter_dict
)) {
2176 if (!wpa_dbus_dict_get_entry(&iter_dict
, &entry
))
2178 if (!os_strcmp(entry
.key
, "version") &&
2179 entry
.type
== DBUS_TYPE_INT32
)
2180 version
= entry
.uint32_value
;
2181 else if (!os_strcmp(entry
.key
, "service") &&
2182 entry
.type
== DBUS_TYPE_STRING
)
2183 service
= os_strdup(entry
.str_value
);
2187 wpa_dbus_dict_entry_clear(&entry
);
2190 if (version
<= 0 || service
== NULL
)
2193 ret
= wpas_p2p_service_del_upnp(wpa_s
, version
, service
);
2197 } else if (bonjour
== 1) {
2198 while (wpa_dbus_dict_has_dict_entry(&iter_dict
)) {
2199 if (!wpa_dbus_dict_get_entry(&iter_dict
, &entry
))
2202 if (!os_strcmp(entry
.key
, "query")) {
2203 if ((entry
.type
!= DBUS_TYPE_ARRAY
) ||
2204 (entry
.array_type
!= DBUS_TYPE_BYTE
))
2206 query
= wpabuf_alloc_copy(
2207 entry
.bytearray_value
,
2212 wpa_dbus_dict_entry_clear(&entry
);
2218 ret
= wpas_p2p_service_del_bonjour(wpa_s
, query
);
2227 wpa_dbus_dict_entry_clear(&entry
);
2229 return wpas_dbus_error_invalid_args(message
, NULL
);
2233 DBusMessage
* wpas_dbus_handler_p2p_flush_service(DBusMessage
*message
,
2234 struct wpa_supplicant
*wpa_s
)
2236 wpas_p2p_service_flush(wpa_s
);
2241 DBusMessage
* wpas_dbus_handler_p2p_service_sd_req(
2242 DBusMessage
*message
, struct wpa_supplicant
*wpa_s
)
2244 DBusMessageIter iter_dict
;
2245 DBusMessage
*reply
= NULL
;
2246 DBusMessageIter iter
;
2247 struct wpa_dbus_dict_entry entry
;
2249 char *service
= NULL
;
2250 char *peer_object_path
= NULL
;
2251 struct wpabuf
*tlv
= NULL
;
2254 u8 addr_buf
[ETH_ALEN
], *addr
;
2256 dbus_message_iter_init(message
, &iter
);
2258 if (!wpa_dbus_dict_open_read(&iter
, &iter_dict
, NULL
))
2261 while (wpa_dbus_dict_has_dict_entry(&iter_dict
)) {
2262 if (!wpa_dbus_dict_get_entry(&iter_dict
, &entry
))
2264 if (!os_strcmp(entry
.key
, "peer_object") &&
2265 entry
.type
== DBUS_TYPE_OBJECT_PATH
) {
2266 peer_object_path
= os_strdup(entry
.str_value
);
2267 } else if (!os_strcmp(entry
.key
, "service_type") &&
2268 entry
.type
== DBUS_TYPE_STRING
) {
2269 if (!os_strcmp(entry
.str_value
, "upnp"))
2273 } else if (!os_strcmp(entry
.key
, "version") &&
2274 entry
.type
== DBUS_TYPE_INT32
) {
2275 version
= entry
.uint32_value
;
2276 } else if (!os_strcmp(entry
.key
, "service") &&
2277 entry
.type
== DBUS_TYPE_STRING
) {
2278 service
= os_strdup(entry
.str_value
);
2279 } else if (!os_strcmp(entry
.key
, "tlv")) {
2280 if (entry
.type
!= DBUS_TYPE_ARRAY
||
2281 entry
.array_type
!= DBUS_TYPE_BYTE
)
2283 tlv
= wpabuf_alloc_copy(entry
.bytearray_value
,
2288 wpa_dbus_dict_entry_clear(&entry
);
2291 if (!peer_object_path
) {
2294 if (parse_peer_object_path(peer_object_path
, addr_buf
) < 0 ||
2295 !p2p_peer_known(wpa_s
->global
->p2p
, addr_buf
))
2302 if (version
<= 0 || service
== NULL
)
2305 ref
= wpas_p2p_sd_request_upnp(wpa_s
, addr
, version
, service
);
2309 ref
= wpas_p2p_sd_request(wpa_s
, addr
, tlv
);
2314 reply
= dbus_message_new_method_return(message
);
2315 dbus_message_append_args(reply
, DBUS_TYPE_UINT64
,
2316 &ref
, DBUS_TYPE_INVALID
);
2318 reply
= wpas_dbus_error_unknown_error(
2319 message
, "Unable to send SD request");
2323 os_free(peer_object_path
);
2326 wpa_dbus_dict_entry_clear(&entry
);
2330 reply
= wpas_dbus_error_invalid_args(message
, NULL
);
2335 DBusMessage
* wpas_dbus_handler_p2p_service_sd_res(
2336 DBusMessage
*message
, struct wpa_supplicant
*wpa_s
)
2338 DBusMessageIter iter_dict
;
2339 DBusMessage
*reply
= NULL
;
2340 DBusMessageIter iter
;
2341 struct wpa_dbus_dict_entry entry
;
2342 char *peer_object_path
= NULL
;
2343 struct wpabuf
*tlv
= NULL
;
2348 dbus_message_iter_init(message
, &iter
);
2350 if (!wpa_dbus_dict_open_read(&iter
, &iter_dict
, NULL
))
2353 while (wpa_dbus_dict_has_dict_entry(&iter_dict
)) {
2354 if (!wpa_dbus_dict_get_entry(&iter_dict
, &entry
))
2357 if (!os_strcmp(entry
.key
, "peer_object") &&
2358 entry
.type
== DBUS_TYPE_OBJECT_PATH
) {
2359 peer_object_path
= os_strdup(entry
.str_value
);
2360 } else if (!os_strcmp(entry
.key
, "frequency") &&
2361 entry
.type
== DBUS_TYPE_INT32
) {
2362 freq
= entry
.uint32_value
;
2363 } else if (!os_strcmp(entry
.key
, "dialog_token") &&
2364 entry
.type
== DBUS_TYPE_UINT32
) {
2365 dlg_tok
= entry
.uint32_value
;
2366 } else if (!os_strcmp(entry
.key
, "tlvs")) {
2367 if (entry
.type
!= DBUS_TYPE_ARRAY
||
2368 entry
.array_type
!= DBUS_TYPE_BYTE
)
2370 tlv
= wpabuf_alloc_copy(entry
.bytearray_value
,
2375 wpa_dbus_dict_entry_clear(&entry
);
2377 if (!peer_object_path
||
2378 (parse_peer_object_path(peer_object_path
, addr
) < 0) ||
2379 !p2p_peer_known(wpa_s
->global
->p2p
, addr
))
2385 wpas_p2p_sd_response(wpa_s
, freq
, addr
, (u8
) dlg_tok
, tlv
);
2388 os_free(peer_object_path
);
2391 wpa_dbus_dict_entry_clear(&entry
);
2393 reply
= wpas_dbus_error_invalid_args(message
, NULL
);
2398 DBusMessage
* wpas_dbus_handler_p2p_service_sd_cancel_req(
2399 DBusMessage
*message
, struct wpa_supplicant
*wpa_s
)
2401 DBusMessageIter iter
;
2404 dbus_message_iter_init(message
, &iter
);
2405 dbus_message_iter_get_basic(&iter
, &req
);
2410 if (!wpas_p2p_sd_cancel_request(wpa_s
, req
))
2415 return wpas_dbus_error_invalid_args(message
, NULL
);
2419 DBusMessage
* wpas_dbus_handler_p2p_service_update(
2420 DBusMessage
*message
, struct wpa_supplicant
*wpa_s
)
2422 wpas_p2p_sd_service_update(wpa_s
);
2427 DBusMessage
* wpas_dbus_handler_p2p_serv_disc_external(
2428 DBusMessage
*message
, struct wpa_supplicant
*wpa_s
)
2430 DBusMessageIter iter
;
2433 dbus_message_iter_init(message
, &iter
);
2434 dbus_message_iter_get_basic(&iter
, &ext
);
2436 wpa_s
->p2p_sd_over_ctrl_iface
= ext
;