2 * WPA Supplicant / dbus-based control interface (P2P)
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
8 * Alternatively, this software may be distributed under the terms of BSD
11 * See README and COPYING for more details.
16 #include "utils/includes.h"
18 #include "../config.h"
19 #include "../wpa_supplicant_i.h"
20 #include "../wps_supplicant.h"
21 #include "dbus_new_helpers.h"
23 #include "dbus_new_handlers.h"
24 #include "dbus_new_handlers_p2p.h"
25 #include "dbus_dict_helpers.h"
27 #include "common/ieee802_11_defs.h"
28 #include "ap/hostapd.h"
29 #include "ap/ap_config.h"
30 #include "ap/wps_hostapd.h"
32 #include "../p2p_supplicant.h"
35 * Parses out the mac address from the peer object path.
36 * @peer_path - object path of the form
37 * /fi/w1/wpa_supplicant1/Interfaces/n/Peers/00112233445566 (no colons)
38 * @addr - out param must be of ETH_ALEN size
39 * Returns 0 if valid (including MAC), -1 otherwise
41 static int parse_peer_object_path(char *peer_path
, u8 addr
[ETH_ALEN
])
47 p
= strrchr(peer_path
, '/');
51 return hwaddr_compact_aton(p
, addr
);
54 DBusMessage
*wpas_dbus_handler_p2p_find(DBusMessage
* message
,
55 struct wpa_supplicant
* wpa_s
)
57 struct wpa_dbus_dict_entry entry
;
58 DBusMessage
*reply
= NULL
;
60 DBusMessageIter iter_dict
;
61 unsigned int timeout
= 0;
62 unsigned int searchonly
= 0;
63 enum p2p_discovery_type type
= P2P_FIND_ONLY_SOCIAL
;
64 int num_req_dev_types
= 0;
66 u8
*req_dev_types
= NULL
;
68 dbus_message_iter_init(message
, &iter
);
70 if (!wpa_dbus_dict_open_read(&iter
, &iter_dict
))
73 while (wpa_dbus_dict_has_dict_entry(&iter_dict
)) {
74 if (!wpa_dbus_dict_get_entry(&iter_dict
, &entry
))
77 if (!os_strcmp(entry
.key
, "Timeout") &&
78 (entry
.type
== DBUS_TYPE_INT32
)) {
79 timeout
= entry
.uint32_value
;
80 } else if (!os_strcmp(entry
.key
, "SearchOnly") &&
81 (entry
.type
== DBUS_TYPE_BOOLEAN
)) {
82 searchonly
= (entry
.bool_value
== TRUE
) ? 1 : 0;
83 } else if (os_strcmp(entry
.key
, "RequestedDeviceTypes") == 0) {
84 if ((entry
.type
!= DBUS_TYPE_ARRAY
) ||
85 (entry
.array_type
!= WPAS_DBUS_TYPE_BINARRAY
))
89 os_malloc(WPS_DEV_TYPE_LEN
* entry
.array_len
);
93 for (i
= 0; i
< entry
.array_len
; i
++) {
94 if (wpabuf_len(entry
.binarray_value
[i
]) !=
97 os_memcpy(req_dev_types
+ i
* WPS_DEV_TYPE_LEN
,
98 wpabuf_head(entry
.binarray_value
[i
]),
102 num_req_dev_types
= entry
.array_len
;
105 wpa_dbus_dict_entry_clear(&entry
);
108 wpas_p2p_find(wpa_s
, timeout
, type
, num_req_dev_types
, req_dev_types
);
112 os_free(req_dev_types
);
113 wpa_dbus_dict_entry_clear(&entry
);
115 reply
= wpas_dbus_error_invalid_args(message
, entry
.key
);
119 DBusMessage
*wpas_dbus_handler_p2p_stop_find(DBusMessage
* message
,
120 struct wpa_supplicant
* wpa_s
)
122 wpas_p2p_stop_find(wpa_s
);
126 DBusMessage
*wpas_dbus_handler_p2p_rejectpeer(DBusMessage
* message
,
127 struct wpa_supplicant
* wpa_s
)
129 DBusMessageIter iter
;
130 char *peer_object_path
= NULL
;
131 u8 peer_addr
[ETH_ALEN
];
133 dbus_message_iter_init(message
, &iter
);
134 dbus_message_iter_get_basic(&iter
, &peer_object_path
);
136 if (parse_peer_object_path(peer_object_path
, peer_addr
) < 0)
137 return wpas_dbus_error_invalid_args(message
, NULL
);
139 if (wpas_p2p_reject(wpa_s
, peer_addr
) < 0)
140 return wpas_dbus_error_unknown_error(message
,
141 "Failed to call wpas_p2p_reject method.");
146 DBusMessage
*wpas_dbus_handler_p2p_listen(DBusMessage
* message
,
147 struct wpa_supplicant
* wpa_s
)
149 dbus_int32_t timeout
= 0;
151 if (!dbus_message_get_args(message
, NULL
, DBUS_TYPE_INT32
, &timeout
,
153 return dbus_message_new_error(message
, DBUS_ERROR_NO_MEMORY
,
156 if (wpas_p2p_listen(wpa_s
, (unsigned int)timeout
))
157 return dbus_message_new_error(message
, DBUS_ERROR_NO_MEMORY
,
163 DBusMessage
*wpas_dbus_handler_p2p_extendedlisten(DBusMessage
* message
,
164 struct wpa_supplicant
* wpa_s
)
166 unsigned int period
= 0, interval
= 0;
167 struct wpa_dbus_dict_entry entry
;
168 DBusMessageIter iter
;
169 DBusMessageIter iter_dict
;
171 dbus_message_iter_init(message
, &iter
);
173 if (!wpa_dbus_dict_open_read(&iter
, &iter_dict
))
176 while (wpa_dbus_dict_has_dict_entry(&iter_dict
)) {
177 if (!wpa_dbus_dict_get_entry(&iter_dict
, &entry
))
180 if (!strcmp(entry
.key
, "period") &&
181 (entry
.type
== DBUS_TYPE_INT32
))
182 period
= entry
.uint32_value
;
183 else if (!strcmp(entry
.key
, "interval") &&
184 (entry
.type
== DBUS_TYPE_INT32
))
185 interval
= entry
.uint32_value
;
188 wpa_dbus_dict_entry_clear(&entry
);
191 if (wpas_p2p_ext_listen(wpa_s
, period
, interval
))
192 return wpas_dbus_error_unknown_error(message
,
193 "failed to initiate a p2p_ext_listen.");
198 wpa_dbus_dict_entry_clear(&entry
);
200 return wpas_dbus_error_invalid_args(message
, entry
.key
);
203 DBusMessage
*wpas_dbus_handler_p2p_presence_request(DBusMessage
* message
,
204 struct wpa_supplicant
*
207 unsigned int dur1
= 0, int1
= 0, dur2
= 0, int2
= 0;
208 struct wpa_dbus_dict_entry entry
;
209 DBusMessageIter iter
;
210 DBusMessageIter iter_dict
;
212 dbus_message_iter_init(message
, &iter
);
214 if (!wpa_dbus_dict_open_read(&iter
, &iter_dict
))
217 while (wpa_dbus_dict_has_dict_entry(&iter_dict
)) {
218 if (!wpa_dbus_dict_get_entry(&iter_dict
, &entry
))
221 if (!strcmp(entry
.key
, "duration1") &&
222 (entry
.type
== DBUS_TYPE_INT32
))
223 dur1
= entry
.uint32_value
;
224 else if (!strcmp(entry
.key
, "interval1") &&
225 entry
.type
== DBUS_TYPE_INT32
)
226 int1
= entry
.uint32_value
;
227 else if (!strcmp(entry
.key
, "duration2") &&
228 entry
.type
== DBUS_TYPE_INT32
)
229 dur2
= entry
.uint32_value
;
230 else if (!strcmp(entry
.key
, "interval2") &&
231 entry
.type
== DBUS_TYPE_INT32
)
232 int2
= entry
.uint32_value
;
236 wpa_dbus_dict_entry_clear(&entry
);
238 if (wpas_p2p_presence_req(wpa_s
, dur1
, int1
, dur2
, int2
) < 0)
239 return wpas_dbus_error_unknown_error(message
,
240 "Failed to invoke presence request.");
245 wpa_dbus_dict_entry_clear(&entry
);
247 return wpas_dbus_error_invalid_args(message
, entry
.key
);
250 DBusMessage
*wpas_dbus_handler_p2p_group_add(DBusMessage
* message
,
251 struct wpa_supplicant
* wpa_s
)
253 DBusMessageIter iter_dict
;
254 DBusMessage
*reply
= NULL
;
255 DBusMessageIter iter
;
256 struct wpa_dbus_dict_entry entry
;
257 char *network_object_path
= NULL
;
258 int persistent_group
= 0;
261 char *net_id_str
= NULL
;
262 unsigned int group_id
= 0;
263 struct wpa_ssid
*ssid
;
265 dbus_message_iter_init(message
, &iter
);
267 if (!wpa_dbus_dict_open_read(&iter
, &iter_dict
))
270 while (wpa_dbus_dict_has_dict_entry(&iter_dict
)) {
271 if (!wpa_dbus_dict_get_entry(&iter_dict
, &entry
))
274 if (!strcmp(entry
.key
, "persistent") &&
275 (entry
.type
== DBUS_TYPE_BOOLEAN
)) {
276 persistent_group
= (entry
.bool_value
== TRUE
) ? 1 : 0;
277 } else if (!strcmp(entry
.key
, "frequency") &&
278 (entry
.type
== DBUS_TYPE_INT32
)) {
279 freq
= entry
.int32_value
;
282 } else if (!strcmp(entry
.key
, "network_object") &&
283 entry
.type
== DBUS_TYPE_OBJECT_PATH
)
284 network_object_path
= os_strdup(entry
.str_value
);
288 wpa_dbus_dict_entry_clear(&entry
);
291 if (network_object_path
!= NULL
) {
293 * A Network Object Path is defined meaning we want to re-invoke
294 * a persisatnt group.
297 iface
= wpas_dbus_new_decompose_object_path(network_object_path
,
300 os_strcmp(iface
, wpa_s
->dbus_new_path
) != 0) {
302 wpas_dbus_error_invalid_args(message
,
303 network_object_path
);
307 group_id
= strtoul(net_id_str
, NULL
, 10);
308 if (errno
== EINVAL
) {
309 reply
= wpas_dbus_error_invalid_args(
310 message
, network_object_path
);
314 /* Get the SSID structure form the persistant group id */
315 ssid
= wpa_config_get_network(wpa_s
->conf
, group_id
);
316 if (ssid
== NULL
|| ssid
->disabled
!= 2)
319 if (wpas_p2p_group_add_persistent(wpa_s
, ssid
, 0, freq
)) {
320 reply
= wpas_dbus_error_unknown_error(message
,
321 "Failed to reinvoke a persistent group");
324 } else if (wpas_p2p_group_add(wpa_s
, persistent_group
, freq
))
328 os_free(network_object_path
);
333 wpa_dbus_dict_entry_clear(&entry
);
335 reply
= wpas_dbus_error_invalid_args(message
, NULL
);
339 DBusMessage
*wpas_dbus_handler_p2p_disconnect(DBusMessage
*message
,
340 struct wpa_supplicant
*wpa_s
)
342 if (wpas_p2p_disconnect(wpa_s
))
343 return wpas_dbus_error_unknown_error(message
,
344 "failed to disconnect");
349 DBusMessage
*wpas_dbus_handler_p2p_flush(DBusMessage
* message
,
350 struct wpa_supplicant
* wpa_s
)
352 os_memset(wpa_s
->p2p_auth_invite
, 0, ETH_ALEN
);
353 wpa_s
->force_long_sd
= 0;
354 p2p_flush(wpa_s
->global
->p2p
);
359 DBusMessage
*wpas_dbus_handler_p2p_connect(DBusMessage
* message
,
360 struct wpa_supplicant
* wpa_s
)
362 DBusMessageIter iter_dict
;
363 DBusMessage
*reply
= NULL
;
364 DBusMessageIter iter
;
365 struct wpa_dbus_dict_entry entry
;
366 char *peer_object_path
= NULL
;
367 int persistent_group
= 0;
369 int authorize_only
= 0;
374 enum p2p_wps_method wps_method
= WPS_NOT_READY
;
376 char *err_msg
= NULL
;
379 dbus_message_iter_init(message
, &iter
);
381 if (!wpa_dbus_dict_open_read(&iter
, &iter_dict
))
384 while (wpa_dbus_dict_has_dict_entry(&iter_dict
)) {
385 if (!wpa_dbus_dict_get_entry(&iter_dict
, &entry
))
388 if (!strcmp(entry
.key
, "peer") &&
389 (entry
.type
== DBUS_TYPE_OBJECT_PATH
)) {
390 peer_object_path
= os_strdup(entry
.str_value
);
391 } else if (!strcmp(entry
.key
, "persistent") &&
392 (entry
.type
== DBUS_TYPE_BOOLEAN
)) {
393 persistent_group
= (entry
.bool_value
== TRUE
) ? 1 : 0;
394 } else if (!strcmp(entry
.key
, "join") &&
395 (entry
.type
== DBUS_TYPE_BOOLEAN
)) {
396 join
= (entry
.bool_value
== TRUE
) ? 1 : 0;
397 } else if (!strcmp(entry
.key
, "authorize_only") &&
398 (entry
.type
== DBUS_TYPE_BOOLEAN
)) {
399 authorize_only
= (entry
.bool_value
== TRUE
) ? 1 : 0;
400 } else if (!strcmp(entry
.key
, "frequency") &&
401 (entry
.type
== DBUS_TYPE_INT32
)) {
402 freq
= entry
.int32_value
;
405 } else if (!strcmp(entry
.key
, "go_intent") &&
406 (entry
.type
== DBUS_TYPE_INT32
)) {
407 go_intent
= entry
.int32_value
;
408 if ((go_intent
< 0) || (go_intent
> 15))
410 } else if (!strcmp(entry
.key
, "wps_method") &&
411 (entry
.type
== DBUS_TYPE_STRING
)) {
412 if (!strcmp(entry
.str_value
, "pbc"))
413 wps_method
= WPS_PBC
;
414 else if (!strcmp(entry
.str_value
, "pin"))
415 wps_method
= WPS_PIN_DISPLAY
;
416 else if (!strcmp(entry
.str_value
, "label"))
417 wps_method
= WPS_PIN_LABEL
;
418 else if (!strcmp(entry
.str_value
, "display"))
419 wps_method
= WPS_PIN_DISPLAY
;
420 else if (!strcmp(entry
.str_value
, "keypad"))
421 wps_method
= WPS_PIN_KEYPAD
;
424 } else if (!strcmp(entry
.key
, "pin") &&
425 (entry
.type
== DBUS_TYPE_STRING
)) {
426 pin
= os_strdup(entry
.str_value
);
430 wpa_dbus_dict_entry_clear(&entry
);
433 if (!peer_object_path
|| (wps_method
== WPS_NOT_READY
) ||
434 (parse_peer_object_path(peer_object_path
, addr
) < 0) ||
435 (p2p_get_peer_info(wpa_s
->global
->p2p
, addr
, 0, NULL
, 0) < 0)) {
436 reply
= wpas_dbus_error_invalid_args(message
, NULL
);
441 * Validate the wps_method specified and the pin value.
443 if ((!pin
|| !pin
[0]) &&
444 ((wps_method
== WPS_PIN_LABEL
) || (wps_method
== WPS_PIN_KEYPAD
)))
447 new_pin
= wpas_p2p_connect(wpa_s
, addr
, pin
, wps_method
,
448 persistent_group
, join
, authorize_only
,
452 reply
= dbus_message_new_method_return(message
);
453 dbus_message_append_args(reply
, DBUS_TYPE_INT32
,
454 &new_pin
, DBUS_TYPE_INVALID
);
458 err_msg
= "connect failed due to"
459 " channel unavailability.";
460 iface
= WPAS_DBUS_ERROR_CONNECT_CHANNEL_UNAVAILABLE
;
464 err_msg
= "connect failed due to"
465 " unsupported channel.";
466 iface
= WPAS_DBUS_ERROR_CONNECT_CHANNEL_UNSUPPORTED
;
470 err_msg
= "connect failed due to"
471 " unspecified error.";
472 iface
= WPAS_DBUS_ERROR_CONNECT_UNSPECIFIED_ERROR
;
477 * Do we need specialized errors corresponding to above
478 * error conditions as against just returning a different
481 reply
= dbus_message_new_error(message
, iface
, err_msg
);
485 os_free(peer_object_path
);
489 wpa_dbus_dict_entry_clear(&entry
);
491 reply
= wpas_dbus_error_invalid_args(message
, NULL
);
495 DBusMessage
*wpas_dbus_handler_p2p_invite(DBusMessage
* message
,
496 struct wpa_supplicant
*wpa_s
)
498 DBusMessageIter iter_dict
;
499 DBusMessage
*reply
= NULL
;
500 DBusMessageIter iter
;
501 struct wpa_dbus_dict_entry entry
;
502 char *peer_object_path
= NULL
;
503 char *network_object_path
= NULL
;
505 char *net_id_str
= NULL
;
506 u8 peer_addr
[ETH_ALEN
];
507 unsigned int group_id
= 0;
509 struct wpa_ssid
*ssid
;
511 dbus_message_iter_init(message
, &iter
);
513 if (!wpa_dbus_dict_open_read(&iter
, &iter_dict
))
516 while (wpa_dbus_dict_has_dict_entry(&iter_dict
)) {
517 if (!wpa_dbus_dict_get_entry(&iter_dict
, &entry
))
520 if (!strcmp(entry
.key
, "peer") &&
521 (entry
.type
== DBUS_TYPE_OBJECT_PATH
)) {
522 peer_object_path
= os_strdup(entry
.str_value
);
523 wpa_dbus_dict_entry_clear(&entry
);
524 } else if (!strcmp(entry
.key
, "network_object") &&
525 (entry
.type
== DBUS_TYPE_OBJECT_PATH
)) {
526 network_object_path
= os_strdup(entry
.str_value
);
528 wpa_dbus_dict_entry_clear(&entry
);
530 wpa_dbus_dict_entry_clear(&entry
);
535 if (!peer_object_path
||
536 (parse_peer_object_path(peer_object_path
, peer_addr
) < 0) ||
537 (p2p_get_peer_info(wpa_s
->global
->p2p
,
538 peer_addr
, 0, NULL
, 0) < 0)) {
544 * A group ID is defined meaning we want to re-invoke a
548 iface
= wpas_dbus_new_decompose_object_path(network_object_path
,
551 os_strcmp(iface
, wpa_s
->dbus_new_path
) != 0) {
553 wpas_dbus_error_invalid_args(message
,
554 network_object_path
);
558 group_id
= strtoul(net_id_str
, NULL
, 10);
559 if (errno
== EINVAL
) {
560 reply
= wpas_dbus_error_invalid_args(
561 message
, network_object_path
);
565 /* Get the SSID structure form the persistant group id */
566 ssid
= wpa_config_get_network(wpa_s
->conf
, group_id
);
567 if (ssid
== NULL
|| ssid
->disabled
!= 2)
570 if (wpas_p2p_invite(wpa_s
, peer_addr
, ssid
, NULL
) < 0) {
571 reply
= wpas_dbus_error_unknown_error(
573 "Failed to reinvoke a persistent group");
578 * No group ID means propose to a peer to join my active group
580 if (wpas_p2p_invite_group(wpa_s
, wpa_s
->ifname
,
582 reply
= wpas_dbus_error_unknown_error(
584 "Failed to join to an active group");
590 os_free(network_object_path
);
591 os_free(peer_object_path
);
595 reply
= wpas_dbus_error_invalid_args(message
, NULL
);
599 DBusMessage
*wpas_dbus_handler_p2p_prov_disc_req(DBusMessage
* message
,
600 struct wpa_supplicant
*wpa_s
)
602 DBusMessageIter iter
;
603 char *peer_object_path
= NULL
;
604 char *config_method
= NULL
;
605 u8 peer_addr
[ETH_ALEN
];
607 dbus_message_iter_init(message
, &iter
);
608 dbus_message_iter_get_basic(&iter
, &peer_object_path
);
610 if (parse_peer_object_path(peer_object_path
, peer_addr
) < 0)
611 return wpas_dbus_error_invalid_args(message
, NULL
);
613 dbus_message_iter_next(&iter
);
614 dbus_message_iter_get_basic(&iter
, &config_method
);
617 * Validation checks on config_method are being duplicated here
618 * to be able to return invalid args reply since the error code
619 * from p2p module are not granular enough (yet).
621 if (os_strcmp(config_method
, "display") &&
622 os_strcmp(config_method
, "keypad") &&
623 os_strcmp(config_method
, "pbc") &&
624 os_strcmp(config_method
, "pushbutton"))
625 return wpas_dbus_error_invalid_args(message
, NULL
);
627 if (wpas_p2p_prov_disc(wpa_s
, peer_addr
, config_method
) < 0)
628 return wpas_dbus_error_unknown_error(message
,
629 "Failed to send provision discovery request");
635 * P2P Device property accessor methods.
638 DBusMessage
*wpas_dbus_getter_p2p_device_properties(DBusMessage
* message
,
639 struct wpa_supplicant
*
642 DBusMessage
*reply
= NULL
;
643 DBusMessageIter iter
, variant_iter
, dict_iter
;
644 const char *dev_name
;
645 int num_sec_dev_types
= 0;
646 int num_vendor_extensions
= 0;
648 const struct wpabuf
*vendor_ext
[P2P_MAX_WPS_VENDOR_EXT
];
651 reply
= dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL
);
653 reply
= dbus_message_new_method_return(message
);
658 dbus_message_iter_init_append(reply
, &iter
);
660 if (!dbus_message_iter_open_container(&iter
, DBUS_TYPE_VARIANT
,
661 "a{sv}", &variant_iter
) ||
662 !wpa_dbus_dict_open_write(&variant_iter
, &dict_iter
))
666 dev_name
= wpa_s
->conf
->device_name
;
668 !wpa_dbus_dict_append_string(&dict_iter
, "DeviceName", dev_name
))
671 /* Primary device type */
672 if (!wpa_dbus_dict_append_byte_array(&dict_iter
, "PrimaryDeviceType",
673 (char *)wpa_s
->conf
->device_type
,
677 /* Secondary device types */
678 for (i
= 0; i
< MAX_SEC_DEVICE_TYPES
; i
++) {
679 if (wpa_s
->conf
->sec_device_type
[i
] == NULL
)
684 if (!wpa_dbus_dict_append_string_array(
685 &dict_iter
, "SecondaryDeviceTypes",
686 (const char **)wpa_s
->conf
->sec_device_type
,
690 /* Vendor Extensions */
691 for (i
= 0; i
< P2P_MAX_WPS_VENDOR_EXT
; i
++) {
692 if (wpa_s
->conf
->wps_vendor_ext
[i
] == NULL
)
694 vendor_ext
[num_vendor_extensions
++] =
695 wpa_s
->conf
->wps_vendor_ext
[i
];
698 if (num_vendor_extensions
&&
699 !wpa_dbus_dict_append_wpabuf_array(&dict_iter
,
702 num_vendor_extensions
))
706 if (!wpa_dbus_dict_append_uint32(&dict_iter
, "GOIntent",
707 wpa_s
->conf
->p2p_go_intent
))
710 /* Persistant Reconnect */
711 if (!wpa_dbus_dict_append_bool(&dict_iter
, "PersistantReconnect",
712 wpa_s
->conf
->persistent_reconnect
))
715 /* Listen Reg Class */
716 if (!wpa_dbus_dict_append_uint32(&dict_iter
, "ListenRegClass",
717 wpa_s
->conf
->p2p_listen_reg_class
))
721 if (!wpa_dbus_dict_append_uint32(&dict_iter
, "ListenChannel",
722 wpa_s
->conf
->p2p_listen_channel
))
726 if (!wpa_dbus_dict_append_uint32(&dict_iter
, "OperRegClass",
727 wpa_s
->conf
->p2p_oper_reg_class
))
731 if (!wpa_dbus_dict_append_uint32(&dict_iter
, "OperChannel",
732 wpa_s
->conf
->p2p_oper_channel
))
736 if (wpa_s
->conf
->p2p_ssid_postfix
&&
737 !wpa_dbus_dict_append_string(&dict_iter
, "SsidPostfix",
738 wpa_s
->conf
->p2p_ssid_postfix
))
742 if (!wpa_dbus_dict_append_bool(&dict_iter
, "IntraBss",
743 wpa_s
->conf
->p2p_intra_bss
))
747 if (!wpa_dbus_dict_append_uint32(&dict_iter
, "GroupIdle",
748 wpa_s
->conf
->p2p_group_idle
))
751 /* Dissasociation low ack */
752 if (!wpa_dbus_dict_append_uint32(&dict_iter
, "disassoc_low_ack",
753 wpa_s
->conf
->disassoc_low_ack
))
756 if (!wpa_dbus_dict_close_write(&variant_iter
, &dict_iter
) ||
757 !dbus_message_iter_close_container(&iter
, &variant_iter
))
762 dbus_message_unref(reply
);
763 return dbus_message_new_error(message
, DBUS_ERROR_NO_MEMORY
, NULL
);
766 DBusMessage
*wpas_dbus_setter_p2p_device_properties(DBusMessage
* message
,
767 struct wpa_supplicant
*
770 DBusMessage
*reply
= NULL
;
771 DBusMessageIter iter
, variant_iter
;
772 struct wpa_dbus_dict_entry entry
= {.type
= DBUS_TYPE_STRING
};
773 DBusMessageIter iter_dict
;
776 dbus_message_iter_init(message
, &iter
);
778 dbus_message_iter_next(&iter
);
779 dbus_message_iter_next(&iter
);
781 dbus_message_iter_recurse(&iter
, &variant_iter
);
783 if (!wpa_dbus_dict_open_read(&variant_iter
, &iter_dict
))
784 return wpas_dbus_error_invalid_args(message
, NULL
);
786 while (wpa_dbus_dict_has_dict_entry(&iter_dict
)) {
787 if (!wpa_dbus_dict_get_entry(&iter_dict
, &entry
))
788 return wpas_dbus_error_invalid_args(message
, NULL
);
790 if (os_strcmp(entry
.key
, "DeviceName") == 0) {
793 if (entry
.type
!= DBUS_TYPE_STRING
)
796 devname
= os_strdup(entry
.str_value
);
798 goto err_no_mem_clear
;
800 os_free(wpa_s
->conf
->device_name
);
801 wpa_s
->conf
->device_name
= devname
;
803 wpa_s
->conf
->changed_parameters
|=
804 CFG_CHANGED_DEVICE_NAME
;
805 } else if (os_strcmp(entry
.key
, "PrimaryDeviceType") == 0) {
806 if (entry
.type
!= DBUS_TYPE_ARRAY
||
807 entry
.array_type
!= DBUS_TYPE_BYTE
||
808 entry
.array_len
!= WPS_DEV_TYPE_LEN
)
811 os_memcpy(wpa_s
->conf
->device_type
,
812 entry
.bytearray_value
,
814 wpa_s
->conf
->changed_parameters
|=
815 CFG_CHANGED_DEVICE_TYPE
;
816 } else if (os_strcmp(entry
.key
, "SecondaryDeviceTypes") == 0) {
817 if (entry
.type
!= DBUS_TYPE_ARRAY
||
818 entry
.array_type
!= WPAS_DBUS_TYPE_BINARRAY
||
819 entry
.array_len
> MAX_SEC_DEVICE_TYPES
)
822 for (i
= 0; i
< entry
.array_len
; i
++)
823 if (wpabuf_len(entry
.binarray_value
[i
]) != WPS_DEV_TYPE_LEN
)
824 goto err_no_mem_clear
;
825 for (i
= 0; i
< entry
.array_len
; i
++)
826 os_memcpy(wpa_s
->conf
->sec_device_type
[i
],
827 wpabuf_head(entry
.binarray_value
[i
]),
829 wpa_s
->conf
->num_sec_device_types
= entry
.array_len
;
830 wpa_s
->conf
->changed_parameters
|=
831 CFG_CHANGED_SEC_DEVICE_TYPE
;
832 } else if (os_strcmp(entry
.key
, "VendorExtension") == 0) {
833 if ((entry
.type
!= DBUS_TYPE_ARRAY
) ||
834 (entry
.array_type
!= WPAS_DBUS_TYPE_BINARRAY
) ||
835 (entry
.array_len
> P2P_MAX_WPS_VENDOR_EXT
))
838 wpa_s
->conf
->changed_parameters
|=
839 CFG_CHANGED_VENDOR_EXTENSION
;
841 for (i
= 0; i
< P2P_MAX_WPS_VENDOR_EXT
; i
++) {
842 wpabuf_free(wpa_s
->conf
->wps_vendor_ext
[i
]);
843 if (i
< entry
.array_len
) {
844 wpa_s
->conf
->wps_vendor_ext
[i
] =
845 entry
.binarray_value
[i
];
846 entry
.binarray_value
[i
] = NULL
;
848 wpa_s
->conf
->wps_vendor_ext
[i
] = NULL
;
850 } else if ((os_strcmp(entry
.key
, "GOIntent") == 0) &&
851 (entry
.type
== DBUS_TYPE_UINT32
) &&
852 (entry
.uint32_value
<= 15))
853 wpa_s
->conf
->p2p_go_intent
= entry
.uint32_value
;
855 else if ((os_strcmp(entry
.key
, "PersistantReconnect") == 0) &&
856 (entry
.type
== DBUS_TYPE_BOOLEAN
))
857 wpa_s
->conf
->persistent_reconnect
= entry
.bool_value
;
859 else if ((os_strcmp(entry
.key
, "ListenRegClass") == 0) &&
860 (entry
.type
== DBUS_TYPE_UINT32
))
861 wpa_s
->conf
->p2p_listen_reg_class
= entry
.uint32_value
;
863 else if ((os_strcmp(entry
.key
, "ListenChannel") == 0) &&
864 (entry
.type
== DBUS_TYPE_UINT32
))
865 wpa_s
->conf
->p2p_listen_channel
= entry
.uint32_value
;
867 else if ((os_strcmp(entry
.key
, "OperRegClass") == 0) &&
868 (entry
.type
== DBUS_TYPE_UINT32
))
869 wpa_s
->conf
->p2p_oper_reg_class
= entry
.uint32_value
;
871 else if ((os_strcmp(entry
.key
, "OperChannel") == 0) &&
872 (entry
.type
== DBUS_TYPE_UINT32
))
873 wpa_s
->conf
->p2p_oper_channel
= entry
.uint32_value
;
875 else if (os_strcmp(entry
.key
, "SsidPostfix") == 0) {
878 if (entry
.type
!= DBUS_TYPE_STRING
)
881 postfix
= os_strdup(entry
.str_value
);
883 goto err_no_mem_clear
;
885 os_free(wpa_s
->conf
->p2p_ssid_postfix
);
886 wpa_s
->conf
->p2p_ssid_postfix
= postfix
;
888 wpa_s
->conf
->changed_parameters
|=
889 CFG_CHANGED_P2P_SSID_POSTFIX
;
890 } else if ((os_strcmp(entry
.key
, "IntraBss") == 0) &&
891 (entry
.type
== DBUS_TYPE_BOOLEAN
)) {
892 wpa_s
->conf
->p2p_intra_bss
= entry
.bool_value
;
893 wpa_s
->conf
->changed_parameters
|=
894 CFG_CHANGED_P2P_INTRA_BSS
;
895 } else if ((os_strcmp(entry
.key
, "GroupIdle") == 0) &&
896 (entry
.type
== DBUS_TYPE_UINT32
))
897 wpa_s
->conf
->p2p_group_idle
= entry
.uint32_value
;
898 else if (os_strcmp(entry
.key
, "disassoc_low_ack") == 0 &&
899 entry
.type
== DBUS_TYPE_UINT32
)
900 wpa_s
->conf
->disassoc_low_ack
= entry
.uint32_value
;
904 wpa_dbus_dict_entry_clear(&entry
);
907 if (wpa_s
->conf
->changed_parameters
) {
908 /* Some changed parameters requires to update config*/
909 wpa_supplicant_update_config(wpa_s
);
915 wpa_dbus_dict_entry_clear(&entry
);
917 reply
= wpas_dbus_error_invalid_args(message
, entry
.key
);
918 wpa_dbus_dict_entry_clear(&entry
);
922 wpa_dbus_dict_entry_clear(&entry
);
923 return dbus_message_new_error(message
, DBUS_ERROR_NO_MEMORY
, NULL
);
926 DBusMessage
*wpas_dbus_getter_p2p_peers(DBusMessage
* message
,
927 struct wpa_supplicant
* wpa_s
)
929 DBusMessage
*reply
= NULL
;
930 struct p2p_data
*p2p
= wpa_s
->global
->p2p
;
932 int num
= 0, out_of_mem
= 0;
934 const struct p2p_peer_info
*peer_info
= NULL
;
936 struct dl_list peer_objpath_list
;
937 struct peer_objpath_node
{
939 char path
[WPAS_DBUS_OBJECT_PATH_MAX
];
942 char **peer_obj_paths
= NULL
;
944 dl_list_init(&peer_objpath_list
);
946 /* Get the first peer info */
947 peer_info
= p2p_get_peer_found(p2p
, NULL
, next
);
949 /* Get next and accumulate them */
951 while (peer_info
!= NULL
) {
952 node
= os_zalloc(sizeof(struct peer_objpath_node
));
958 addr
= peer_info
->p2p_device_addr
;
959 os_snprintf(node
->path
, WPAS_DBUS_OBJECT_PATH_MAX
,
960 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART
962 wpa_s
->dbus_new_path
, MAC2STR(addr
));
963 dl_list_add_tail(&peer_objpath_list
, &node
->list
);
966 peer_info
= p2p_get_peer_found(p2p
, addr
, next
);
970 * Now construct the peer object paths in a form suitable for
971 * array_property_getter helper below.
973 peer_obj_paths
= os_zalloc(num
* sizeof(char *));
975 if (!peer_obj_paths
) {
980 dl_list_for_each_safe(node
, tmp
, &peer_objpath_list
,
981 struct peer_objpath_node
, list
)
982 peer_obj_paths
[i
++] = node
->path
;
984 reply
= wpas_dbus_simple_array_property_getter(message
,
985 DBUS_TYPE_OBJECT_PATH
,
986 peer_obj_paths
, num
);
990 os_free(peer_obj_paths
);
992 dl_list_for_each_safe(node
, tmp
, &peer_objpath_list
,
993 struct peer_objpath_node
, list
) {
994 dl_list_del(&node
->list
);
998 reply
= dbus_message_new_error(message
, DBUS_ERROR_NO_MEMORY
,
1004 enum wpas_p2p_role
{
1005 WPAS_P2P_ROLE_DEVICE
,
1007 WPAS_P2P_ROLE_CLIENT
,
1010 static enum wpas_p2p_role
wpas_get_p2p_role(struct wpa_supplicant
*wpa_s
)
1012 struct wpa_ssid
*ssid
= wpa_s
->current_ssid
;
1015 return WPAS_P2P_ROLE_DEVICE
;
1016 if (wpa_s
->wpa_state
!= WPA_COMPLETED
)
1017 return WPAS_P2P_ROLE_DEVICE
;
1019 switch (ssid
->mode
) {
1020 case WPAS_MODE_P2P_GO
:
1021 case WPAS_MODE_P2P_GROUP_FORMATION
:
1022 return WPAS_P2P_ROLE_GO
;
1023 case WPAS_MODE_INFRA
:
1024 if (ssid
->p2p_group
)
1025 return WPAS_P2P_ROLE_CLIENT
;
1026 return WPAS_P2P_ROLE_DEVICE
;
1028 return WPAS_P2P_ROLE_DEVICE
;
1032 DBusMessage
*wpas_dbus_getter_p2p_role(DBusMessage
* message
,
1033 struct wpa_supplicant
* wpa_s
)
1037 switch (wpas_get_p2p_role(wpa_s
)) {
1038 case WPAS_P2P_ROLE_GO
:
1041 case WPAS_P2P_ROLE_CLIENT
:
1048 return wpas_dbus_simple_property_getter(message
, DBUS_TYPE_STRING
,
1052 DBusMessage
*wpas_dbus_getter_p2p_group(DBusMessage
* message
,
1053 struct wpa_supplicant
* wpa_s
)
1055 if (wpa_s
->dbus_groupobj_path
== NULL
)
1058 return wpas_dbus_simple_property_getter(message
,
1059 DBUS_TYPE_OBJECT_PATH
,
1060 &wpa_s
->dbus_groupobj_path
);
1063 DBusMessage
*wpas_dbus_getter_p2p_peergo(DBusMessage
* message
,
1064 struct wpa_supplicant
* wpa_s
)
1066 char go_peer_obj_path
[WPAS_DBUS_OBJECT_PATH_MAX
], *path
;
1068 if (wpas_get_p2p_role(wpa_s
) != WPAS_P2P_ROLE_CLIENT
)
1071 os_snprintf(go_peer_obj_path
, WPAS_DBUS_OBJECT_PATH_MAX
,
1072 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART
"/" COMPACT_MACSTR
,
1073 wpa_s
->dbus_new_path
, MAC2STR(wpa_s
->go_dev_addr
));
1074 path
= go_peer_obj_path
;
1075 return wpas_dbus_simple_property_getter(message
,
1076 DBUS_TYPE_OBJECT_PATH
, &path
);
1080 * Peer object properties accessor methods
1083 DBusMessage
*wpas_dbus_getter_p2p_peer_properties(DBusMessage
* message
,
1084 struct peer_handler_args
*
1087 DBusMessage
*reply
= NULL
;
1088 DBusMessageIter iter
, variant_iter
, dict_iter
;
1089 const struct p2p_peer_info
*info
= NULL
;
1090 char devtype
[WPS_DEV_TYPE_BUFSIZE
];
1092 /* get the peer info */
1093 info
= p2p_get_peer_found(peer_args
->wpa_s
->global
->p2p
,
1094 peer_args
->p2p_device_addr
, 0);
1098 if (message
== NULL
)
1099 reply
= dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL
);
1101 reply
= dbus_message_new_method_return(message
);
1106 dbus_message_iter_init_append(reply
, &iter
);
1107 if (!dbus_message_iter_open_container(&iter
, DBUS_TYPE_VARIANT
,
1108 "a{sv}", &variant_iter
) ||
1109 !wpa_dbus_dict_open_write(&variant_iter
, &dict_iter
))
1112 /* Fill out the dictionary */
1113 wps_dev_type_bin2str(info
->pri_dev_type
, devtype
, sizeof(devtype
));
1114 if (!wpa_dbus_dict_append_string(&dict_iter
, "DeviceName",
1117 if (!wpa_dbus_dict_append_string(&dict_iter
, "PrimaryDeviceType",
1120 if (!wpa_dbus_dict_append_uint16(&dict_iter
, "config_method",
1121 info
->config_methods
))
1123 if (!wpa_dbus_dict_append_int32(&dict_iter
, "level",
1126 if (!wpa_dbus_dict_append_byte(&dict_iter
, "devicecapability",
1129 if (!wpa_dbus_dict_append_byte(&dict_iter
, "groupcapability",
1133 if (info
->wps_sec_dev_type_list_len
) {
1134 char *sec_dev_types
[MAX_SEC_DEVICE_TYPES
];
1135 u8
*sec_dev_type_list
= NULL
;
1136 char secdevtype
[WPS_DEV_TYPE_BUFSIZE
];
1137 int num_sec_dev_types
= 0;
1140 sec_dev_type_list
= os_zalloc(info
->wps_sec_dev_type_list_len
);
1142 if (sec_dev_type_list
== NULL
)
1145 os_memcpy(sec_dev_type_list
, info
->wps_sec_dev_type_list
,
1146 info
->wps_sec_dev_type_list_len
);
1148 for (i
= 0; i
< MAX_SEC_DEVICE_TYPES
&&
1149 i
< (int) (info
->wps_sec_dev_type_list_len
/
1152 sec_dev_types
[i
] = os_zalloc(sizeof(secdevtype
));
1154 if (!sec_dev_types
[i
] ||
1155 wps_dev_type_bin2str(
1156 &sec_dev_type_list
[i
*
1159 sizeof(secdevtype
)) == NULL
) {
1161 os_free(sec_dev_types
[i
]);
1162 os_free(sec_dev_type_list
);
1166 num_sec_dev_types
++;
1169 os_free(sec_dev_type_list
);
1171 if (num_sec_dev_types
) {
1172 if (!wpa_dbus_dict_append_string_array(&dict_iter
,
1173 "SecondaryDeviceTypes",
1174 (const char **)sec_dev_types
,
1175 num_sec_dev_types
)) {
1176 for (i
= 0; i
< num_sec_dev_types
; i
++)
1177 os_free(sec_dev_types
[i
]);
1181 for (i
= 0; i
< num_sec_dev_types
; i
++)
1182 os_free(sec_dev_types
[i
]);
1187 /* Add WPS vendor extensions attribute */
1188 const struct wpabuf
*vendor_extension
[P2P_MAX_WPS_VENDOR_EXT
];
1191 for (i
= 0; i
< P2P_MAX_WPS_VENDOR_EXT
; i
++) {
1192 if (info
->wps_vendor_ext
[i
] == NULL
)
1194 vendor_extension
[num
] = info
->wps_vendor_ext
[i
];
1198 if (!wpa_dbus_dict_append_wpabuf_array(
1199 &dict_iter
, "VendorExtension",
1200 vendor_extension
, num
))
1204 if (!wpa_dbus_dict_close_write(&variant_iter
, &dict_iter
) ||
1205 !dbus_message_iter_close_container(&iter
, &variant_iter
))
1210 dbus_message_unref(reply
);
1211 return dbus_message_new_error(message
, DBUS_ERROR_NO_MEMORY
, NULL
);
1214 DBusMessage
*wpas_dbus_getter_p2p_peer_ies(DBusMessage
* message
,
1215 struct peer_handler_args
* peer_args
)
1222 * wpas_dbus_getter_persistent_groups - Get array of peristent group objects
1223 * @message: Pointer to incoming dbus message
1224 * @wpa_s: wpa_supplicant structure for a network interface
1225 * Returns: a dbus message containing an array of all persistent group
1226 * dbus object paths.
1228 * Getter for "Networks" property.
1230 DBusMessage
* wpas_dbus_getter_persistent_groups(DBusMessage
*message
,
1231 struct wpa_supplicant
*wpa_s
)
1233 DBusMessage
*reply
= NULL
;
1234 struct wpa_ssid
*ssid
;
1236 unsigned int i
= 0, num
= 0;
1238 if (wpa_s
->conf
== NULL
) {
1239 wpa_printf(MSG_ERROR
, "dbus: "
1240 "wpas_dbus_getter_persistent_groups: "
1241 "An error occurred getting persistent groups list");
1242 return wpas_dbus_error_unknown_error(message
, NULL
);
1245 for (ssid
= wpa_s
->conf
->ssid
; ssid
; ssid
= ssid
->next
)
1246 if (network_is_persistent_group(ssid
))
1249 paths
= os_zalloc(num
* sizeof(char *));
1251 return dbus_message_new_error(message
, DBUS_ERROR_NO_MEMORY
,
1255 /* Loop through configured networks and append object path of each */
1256 for (ssid
= wpa_s
->conf
->ssid
; ssid
; ssid
= ssid
->next
) {
1257 if (!network_is_persistent_group(ssid
))
1259 paths
[i
] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX
);
1260 if (paths
[i
] == NULL
) {
1261 reply
= dbus_message_new_error(message
,
1262 DBUS_ERROR_NO_MEMORY
,
1266 /* Construct the object path for this network. */
1267 os_snprintf(paths
[i
++], WPAS_DBUS_OBJECT_PATH_MAX
,
1268 "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART
"/%d",
1269 wpa_s
->dbus_new_path
, ssid
->id
);
1272 reply
= wpas_dbus_simple_array_property_getter(message
,
1273 DBUS_TYPE_OBJECT_PATH
,
1278 os_free(paths
[--i
]);
1285 * wpas_dbus_getter_persistent_group_properties - Get options for a persistent
1287 * @message: Pointer to incoming dbus message
1288 * @net: wpa_supplicant structure for a network interface and
1289 * wpa_ssid structure for a configured persistent group (internally network)
1290 * Returns: DBus message with network properties or DBus error on failure
1292 * Getter for "Properties" property of a persistent group.
1294 DBusMessage
* wpas_dbus_getter_persistent_group_properties(
1295 DBusMessage
*message
, struct network_handler_args
*net
)
1298 * Leveraging the fact that persistent group object is still
1299 * represented in same manner as network within.
1301 return wpas_dbus_getter_network_properties(message
, net
);
1306 * Group object properties accessor methods
1309 DBusMessage
*wpas_dbus_getter_p2p_group_members(DBusMessage
* message
,
1310 struct wpa_supplicant
* wpa_s
)
1312 DBusMessage
*reply
= NULL
;
1313 struct wpa_ssid
*ssid
;
1314 unsigned int num_members
;
1320 /* Ensure we are a GO */
1321 if (wpa_s
->wpa_state
!= WPA_COMPLETED
)
1324 ssid
= wpa_s
->conf
->ssid
;
1325 /* At present WPAS P2P_GO mode only applicable for p2p_go */
1326 if (ssid
->mode
!= WPAS_MODE_P2P_GO
&&
1327 ssid
->mode
!= WPAS_MODE_AP
&&
1328 ssid
->mode
!= WPAS_MODE_P2P_GROUP_FORMATION
)
1331 num_members
= p2p_get_group_num_members(wpa_s
->p2p_group
);
1333 paths
= os_zalloc(num_members
* sizeof(char *));
1338 while ((addr
= p2p_iterate_group_members(wpa_s
->p2p_group
, &next
))) {
1339 paths
[i
] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX
);
1342 os_snprintf(paths
[i
], WPAS_DBUS_OBJECT_PATH_MAX
,
1343 "%s/" WPAS_DBUS_NEW_P2P_GROUPMEMBERS_PART
1345 wpa_s
->dbus_groupobj_path
, MAC2STR(addr
));
1349 reply
= wpas_dbus_simple_array_property_getter(message
,
1350 DBUS_TYPE_OBJECT_PATH
,
1351 paths
, num_members
);
1354 for (i
= 0; i
< num_members
; i
++)
1360 reply
= dbus_message_new_error(message
, DBUS_ERROR_NO_MEMORY
, NULL
);
1365 DBusMessage
*wpas_dbus_getter_p2p_group_properties(
1366 DBusMessage
*message
,
1367 struct wpa_supplicant
*wpa_s
)
1369 DBusMessage
*reply
= NULL
;
1370 DBusMessageIter iter
, variant_iter
, dict_iter
;
1371 struct hostapd_data
*hapd
= wpa_s
->ap_iface
->bss
[0];
1372 const struct wpabuf
*vendor_ext
[MAX_WPS_VENDOR_EXTENSIONS
];
1373 int num_vendor_ext
= 0;
1377 reply
= dbus_message_new_error(message
, DBUS_ERROR_FAILED
,
1382 if (message
== NULL
)
1383 reply
= dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL
);
1385 reply
= dbus_message_new_method_return(message
);
1390 dbus_message_iter_init_append(reply
, &iter
);
1392 if (!dbus_message_iter_open_container(&iter
, DBUS_TYPE_VARIANT
,
1393 "a{sv}", &variant_iter
) ||
1394 !wpa_dbus_dict_open_write(&variant_iter
, &dict_iter
))
1397 /* Parse WPS Vendor Extensions sent in Beacon/Probe Response */
1398 for (i
= 0; i
< MAX_WPS_VENDOR_EXTENSIONS
; i
++) {
1399 if (hapd
->conf
->wps_vendor_ext
[i
] == NULL
)
1401 vendor_ext
[num_vendor_ext
++] = hapd
->conf
->wps_vendor_ext
[i
];
1404 if (!wpa_dbus_dict_append_wpabuf_array(&dict_iter
,
1405 "WPSVendorExtensions",
1406 vendor_ext
, num_vendor_ext
))
1409 if (!wpa_dbus_dict_close_write(&variant_iter
, &dict_iter
) ||
1410 !dbus_message_iter_close_container(&iter
, &variant_iter
))
1416 dbus_message_unref(reply
);
1417 return dbus_message_new_error(message
, DBUS_ERROR_NO_MEMORY
, NULL
);
1420 DBusMessage
*wpas_dbus_setter_p2p_group_properties(
1421 DBusMessage
*message
,
1422 struct wpa_supplicant
*wpa_s
)
1424 DBusMessage
*reply
= NULL
;
1425 DBusMessageIter iter
, variant_iter
;
1426 struct wpa_dbus_dict_entry entry
= {.type
= DBUS_TYPE_STRING
};
1427 DBusMessageIter iter_dict
;
1430 struct hostapd_data
*hapd
= wpa_s
->ap_iface
->bss
[0];
1435 dbus_message_iter_init(message
, &iter
);
1437 dbus_message_iter_next(&iter
);
1438 dbus_message_iter_next(&iter
);
1440 dbus_message_iter_recurse(&iter
, &variant_iter
);
1442 if (!wpa_dbus_dict_open_read(&variant_iter
, &iter_dict
))
1443 return wpas_dbus_error_invalid_args(message
, NULL
);
1445 while (wpa_dbus_dict_has_dict_entry(&iter_dict
)) {
1446 if (!wpa_dbus_dict_get_entry(&iter_dict
, &entry
)) {
1447 reply
= wpas_dbus_error_invalid_args(message
, NULL
);
1451 if (os_strcmp(entry
.key
, "WPSVendorExtensions") == 0) {
1452 if (entry
.type
!= DBUS_TYPE_ARRAY
||
1453 entry
.array_type
!= WPAS_DBUS_TYPE_BINARRAY
||
1454 entry
.array_len
> MAX_WPS_VENDOR_EXTENSIONS
)
1457 for (i
= 0; i
< MAX_WPS_VENDOR_EXTENSIONS
; i
++) {
1458 if (i
< entry
.array_len
) {
1459 hapd
->conf
->wps_vendor_ext
[i
] =
1460 entry
.binarray_value
[i
];
1461 entry
.binarray_value
[i
] = NULL
;
1463 hapd
->conf
->wps_vendor_ext
[i
] = NULL
;
1466 hostapd_update_wps(hapd
);
1470 wpa_dbus_dict_entry_clear(&entry
);
1476 reply
= wpas_dbus_error_invalid_args(message
, entry
.key
);
1477 wpa_dbus_dict_entry_clear(&entry
);
1482 DBusMessage
*wpas_dbus_handler_p2p_add_service(DBusMessage
* message
,
1483 struct wpa_supplicant
* wpa_s
)
1485 DBusMessageIter iter_dict
;
1486 DBusMessage
*reply
= NULL
;
1487 DBusMessageIter iter
;
1488 struct wpa_dbus_dict_entry entry
;
1491 char *service
= NULL
;
1492 struct wpabuf
*query
= NULL
;
1493 struct wpabuf
*resp
= NULL
;
1496 dbus_message_iter_init(message
, &iter
);
1498 if (!wpa_dbus_dict_open_read(&iter
, &iter_dict
))
1501 if (wpa_dbus_dict_has_dict_entry(&iter_dict
)) {
1502 if (!wpa_dbus_dict_get_entry(&iter_dict
, &entry
))
1505 if (!strcmp(entry
.key
, "service_type") &&
1506 (entry
.type
== DBUS_TYPE_STRING
)) {
1507 if (!strcmp(entry
.str_value
, "upnp"))
1509 else if (!strcmp(entry
.str_value
, "bonjour"))
1513 wpa_dbus_dict_entry_clear(&entry
);
1518 while (wpa_dbus_dict_has_dict_entry(&iter_dict
)) {
1519 if (!wpa_dbus_dict_get_entry(&iter_dict
, &entry
))
1522 if (!strcmp(entry
.key
, "version") &&
1523 entry
.type
== DBUS_TYPE_INT32
)
1524 version
= entry
.uint32_value
;
1525 else if (!strcmp(entry
.key
, "service") &&
1526 entry
.type
== DBUS_TYPE_STRING
)
1527 service
= os_strdup(entry
.str_value
);
1528 wpa_dbus_dict_entry_clear(&entry
);
1530 if (version
<= 0 || service
== NULL
)
1533 if (wpas_p2p_service_add_upnp(wpa_s
, version
, service
) != 0)
1537 } else if (bonjour
== 1) {
1538 while (wpa_dbus_dict_has_dict_entry(&iter_dict
)) {
1539 if (!wpa_dbus_dict_get_entry(&iter_dict
, &entry
))
1542 if (!strcmp(entry
.key
, "query")) {
1543 if ((entry
.type
!= DBUS_TYPE_ARRAY
) ||
1544 (entry
.array_type
!= DBUS_TYPE_BYTE
))
1546 query
= wpabuf_alloc_copy(entry
.bytearray_value
,
1548 } else if (!strcmp(entry
.key
, "response")) {
1549 if ((entry
.type
!= DBUS_TYPE_ARRAY
) ||
1550 (entry
.array_type
!= DBUS_TYPE_BYTE
))
1552 resp
= wpabuf_alloc_copy(entry
.bytearray_value
,
1556 wpa_dbus_dict_entry_clear(&entry
);
1559 if (query
== NULL
|| resp
== NULL
)
1562 if (wpas_p2p_service_add_bonjour(wpa_s
, query
, resp
) < 0) {
1572 wpa_dbus_dict_entry_clear(&entry
);
1574 return wpas_dbus_error_invalid_args(message
, NULL
);
1577 DBusMessage
*wpas_dbus_handler_p2p_delete_service(DBusMessage
* message
,
1578 struct wpa_supplicant
* wpa_s
)
1580 DBusMessageIter iter_dict
;
1581 DBusMessage
*reply
= NULL
;
1582 DBusMessageIter iter
;
1583 struct wpa_dbus_dict_entry entry
;
1587 char *service
= NULL
;
1588 struct wpabuf
*query
= NULL
;
1591 dbus_message_iter_init(message
, &iter
);
1593 if (!wpa_dbus_dict_open_read(&iter
, &iter_dict
))
1596 if (wpa_dbus_dict_has_dict_entry(&iter_dict
)) {
1597 if (!wpa_dbus_dict_get_entry(&iter_dict
, &entry
))
1600 if (!strcmp(entry
.key
, "service_type") &&
1601 (entry
.type
== DBUS_TYPE_STRING
)) {
1602 if (!strcmp(entry
.str_value
, "upnp"))
1604 else if (!strcmp(entry
.str_value
, "bonjour"))
1608 wpa_dbus_dict_entry_clear(&entry
);
1612 while (wpa_dbus_dict_has_dict_entry(&iter_dict
)) {
1613 if (!wpa_dbus_dict_get_entry(&iter_dict
, &entry
))
1615 if (!strcmp(entry
.key
, "version") &&
1616 entry
.type
== DBUS_TYPE_INT32
)
1617 version
= entry
.uint32_value
;
1618 else if (!strcmp(entry
.key
, "service") &&
1619 entry
.type
== DBUS_TYPE_STRING
)
1620 service
= os_strdup(entry
.str_value
);
1624 wpa_dbus_dict_entry_clear(&entry
);
1627 if (version
<= 0 || service
== NULL
)
1630 ret
= wpas_p2p_service_del_upnp(wpa_s
, version
, service
);
1634 } else if (bonjour
== 1) {
1635 while (wpa_dbus_dict_has_dict_entry(&iter_dict
)) {
1636 if (!wpa_dbus_dict_get_entry(&iter_dict
, &entry
))
1639 if (!strcmp(entry
.key
, "query")) {
1640 if ((entry
.type
!= DBUS_TYPE_ARRAY
) ||
1641 (entry
.array_type
!= DBUS_TYPE_BYTE
))
1643 query
= wpabuf_alloc_copy(entry
.bytearray_value
,
1648 wpa_dbus_dict_entry_clear(&entry
);
1654 ret
= wpas_p2p_service_del_bonjour(wpa_s
, query
);
1663 wpa_dbus_dict_entry_clear(&entry
);
1665 return wpas_dbus_error_invalid_args(message
, NULL
);
1668 DBusMessage
*wpas_dbus_handler_p2p_flush_service(DBusMessage
* message
,
1669 struct wpa_supplicant
* wpa_s
)
1671 wpas_p2p_service_flush(wpa_s
);
1675 DBusMessage
*wpas_dbus_handler_p2p_service_sd_req(DBusMessage
* message
,
1676 struct wpa_supplicant
* wpa_s
)
1678 DBusMessageIter iter_dict
;
1679 DBusMessage
*reply
= NULL
;
1680 DBusMessageIter iter
;
1681 struct wpa_dbus_dict_entry entry
;
1683 char *service
= NULL
;
1684 char *peer_object_path
= NULL
;
1685 struct wpabuf
*tlv
= NULL
;
1690 dbus_message_iter_init(message
, &iter
);
1692 if (!wpa_dbus_dict_open_read(&iter
, &iter_dict
))
1695 while (wpa_dbus_dict_has_dict_entry(&iter_dict
)) {
1696 if (!wpa_dbus_dict_get_entry(&iter_dict
, &entry
))
1698 if (!strcmp(entry
.key
, "peer_object") &&
1699 entry
.type
== DBUS_TYPE_OBJECT_PATH
) {
1700 peer_object_path
= os_strdup(entry
.str_value
);
1701 } else if (!strcmp(entry
.key
, "service_type") &&
1702 entry
.type
== DBUS_TYPE_STRING
) {
1703 if (!strcmp(entry
.str_value
, "upnp"))
1707 } else if (!strcmp(entry
.key
, "version") &&
1708 entry
.type
== DBUS_TYPE_INT32
) {
1709 version
= entry
.uint32_value
;
1710 } else if (!strcmp(entry
.key
, "service") &&
1711 entry
.type
== DBUS_TYPE_STRING
) {
1712 service
= os_strdup(entry
.str_value
);
1713 } else if (!strcmp(entry
.key
, "tlv")) {
1714 if (entry
.type
!= DBUS_TYPE_ARRAY
||
1715 entry
.array_type
!= DBUS_TYPE_BYTE
)
1717 tlv
= wpabuf_alloc_copy(entry
.bytearray_value
,
1722 wpa_dbus_dict_entry_clear(&entry
);
1725 if (!peer_object_path
||
1726 (parse_peer_object_path(peer_object_path
, addr
) < 0) ||
1727 (p2p_get_peer_info(wpa_s
->global
->p2p
, addr
, 0, NULL
, 0) < 0))
1731 if (version
<= 0 || service
== NULL
)
1734 ref
= (unsigned long)wpas_p2p_sd_request_upnp(wpa_s
, addr
,
1739 ref
= (unsigned long)wpas_p2p_sd_request(wpa_s
, addr
, tlv
);
1744 reply
= dbus_message_new_method_return(message
);
1745 dbus_message_append_args(reply
, DBUS_TYPE_UINT64
,
1746 &ref
, DBUS_TYPE_INVALID
);
1748 reply
= wpas_dbus_error_unknown_error(message
,
1749 "Unable to send SD request");
1753 os_free(peer_object_path
);
1756 wpa_dbus_dict_entry_clear(&entry
);
1760 reply
= wpas_dbus_error_invalid_args(message
, NULL
);
1764 DBusMessage
*wpas_dbus_handler_p2p_service_sd_res(
1765 DBusMessage
*message
, struct wpa_supplicant
*wpa_s
)
1767 DBusMessageIter iter_dict
;
1768 DBusMessage
*reply
= NULL
;
1769 DBusMessageIter iter
;
1770 struct wpa_dbus_dict_entry entry
;
1771 char *peer_object_path
= NULL
;
1772 struct wpabuf
*tlv
= NULL
;
1777 dbus_message_iter_init(message
, &iter
);
1779 if (!wpa_dbus_dict_open_read(&iter
, &iter_dict
))
1782 while (wpa_dbus_dict_has_dict_entry(&iter_dict
)) {
1783 if (!wpa_dbus_dict_get_entry(&iter_dict
, &entry
))
1786 if (!strcmp(entry
.key
, "peer_object") &&
1787 entry
.type
== DBUS_TYPE_OBJECT_PATH
) {
1788 peer_object_path
= os_strdup(entry
.str_value
);
1789 } else if (!strcmp(entry
.key
, "frequency") &&
1790 entry
.type
== DBUS_TYPE_INT32
) {
1791 freq
= entry
.uint32_value
;
1792 } else if (!strcmp(entry
.key
, "dialog_token") &&
1793 entry
.type
== DBUS_TYPE_UINT32
) {
1794 dlg_tok
= entry
.uint32_value
;
1795 } else if (!strcmp(entry
.key
, "tlvs")) {
1796 if (entry
.type
!= DBUS_TYPE_ARRAY
||
1797 entry
.array_type
!= DBUS_TYPE_BYTE
)
1799 tlv
= wpabuf_alloc_copy(entry
.bytearray_value
,
1804 wpa_dbus_dict_entry_clear(&entry
);
1806 if (!peer_object_path
||
1807 (parse_peer_object_path(peer_object_path
, addr
) < 0) ||
1808 (p2p_get_peer_info(wpa_s
->global
->p2p
, addr
, 0, NULL
, 0) < 0))
1814 wpas_p2p_sd_response(wpa_s
, freq
, addr
, (u8
) dlg_tok
, tlv
);
1817 os_free(peer_object_path
);
1820 wpa_dbus_dict_entry_clear(&entry
);
1822 reply
= wpas_dbus_error_invalid_args(message
, NULL
);
1826 DBusMessage
*wpas_dbus_handler_p2p_service_sd_cancel_req(DBusMessage
* message
, struct wpa_supplicant
1829 DBusMessageIter iter
;
1832 dbus_message_iter_init(message
, &iter
);
1833 dbus_message_iter_get_basic(&iter
, &req
);
1838 if (!wpas_p2p_sd_cancel_request(wpa_s
, (void *)(unsigned long)req
))
1843 return wpas_dbus_error_invalid_args(message
, NULL
);
1846 DBusMessage
*wpas_dbus_handler_p2p_service_update(DBusMessage
* message
,
1847 struct wpa_supplicant
* wpa_s
)
1849 wpas_p2p_sd_service_update(wpa_s
);
1853 DBusMessage
*wpas_dbus_handler_p2p_serv_disc_external(DBusMessage
* message
,
1854 struct wpa_supplicant
*
1857 DBusMessageIter iter
;
1860 dbus_message_iter_init(message
, &iter
);
1861 dbus_message_iter_get_basic(&iter
, &ext
);
1863 wpa_s
->p2p_sd_over_ctrl_iface
= ext
;