/*
* WPA Supplicant / dbus-based control interface (P2P)
+ * Copyright (c) 2011-2012, Intel Corporation
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*/
#include "includes.h"
#include "ap/wps_hostapd.h"
#include "../p2p_supplicant.h"
+#include "../wifi_display.h"
/**
* Parses out the mac address from the peer object path.
DBusMessageIter iter;
DBusMessageIter iter_dict;
unsigned int timeout = 0;
- enum p2p_discovery_type type = P2P_FIND_ONLY_SOCIAL;
+ enum p2p_discovery_type type = P2P_FIND_START_WITH_FULL;
int num_req_dev_types = 0;
unsigned int i;
u8 *req_dev_types = NULL;
wpa_dbus_dict_entry_clear(&entry);
}
+ if (wpa_s->p2p_dev)
+ wpa_s = wpa_s->p2p_dev;
+
wpas_p2p_find(wpa_s, timeout, type, num_req_dev_types, req_dev_types,
- NULL);
+ NULL, 0);
os_free(req_dev_types);
return reply;
DBusMessage * wpas_dbus_handler_p2p_stop_find(DBusMessage *message,
struct wpa_supplicant *wpa_s)
{
+ if (wpa_s->p2p_dev)
+ wpa_s = wpa_s->p2p_dev;
+
wpas_p2p_stop_find(wpa_s);
return NULL;
}
if (parse_peer_object_path(peer_object_path, peer_addr) < 0)
return wpas_dbus_error_invalid_args(message, NULL);
+ if (wpa_s->p2p_dev)
+ wpa_s = wpa_s->p2p_dev;
+
if (wpas_p2p_reject(wpa_s, peer_addr) < 0)
return wpas_dbus_error_unknown_error(message,
"Failed to call wpas_p2p_reject method.");
return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
NULL);
+ if (wpa_s->p2p_dev)
+ wpa_s = wpa_s->p2p_dev;
+
if (wpas_p2p_listen(wpa_s, (unsigned int)timeout))
return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
NULL);
wpa_dbus_dict_entry_clear(&entry);
}
+ if (wpa_s->p2p_dev)
+ wpa_s = wpa_s->p2p_dev;
+
if (wpas_p2p_ext_listen(wpa_s, period, interval))
return wpas_dbus_error_unknown_error(
message, "failed to initiate a p2p_ext_listen.");
wpa_dbus_dict_entry_clear(&entry);
}
+
+ if (wpa_s->p2p_dev)
+ wpa_s = wpa_s->p2p_dev;
+
if (wpas_p2p_presence_req(wpa_s, dur1, int1, dur2, int2) < 0)
return wpas_dbus_error_unknown_error(message,
"Failed to invoke presence request.");
wpa_dbus_dict_entry_clear(&entry);
}
+ if (wpa_s->p2p_dev)
+ wpa_s = wpa_s->p2p_dev;
+
if (pg_object_path != NULL) {
/*
* A persistent group Object Path is defined meaning we want
if (ssid == NULL || ssid->disabled != 2)
goto inv_args;
- if (wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq)) {
+ if (wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 0, 0, 0,
+ NULL, 0)) {
reply = wpas_dbus_error_unknown_error(
message,
"Failed to reinvoke a persistent group");
goto out;
}
- } else if (wpas_p2p_group_add(wpa_s, persistent_group, freq))
+ } else if (wpas_p2p_group_add(wpa_s, persistent_group, freq, 0, 0))
goto inv_args;
out:
if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL))
return reply;
+ if (wpa_s->p2p_dev)
+ wpa_s = wpa_s->p2p_dev;
+
os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
wpa_s->force_long_sd = 0;
p2p_flush(wpa_s->global->p2p);
if ((!pin || !pin[0]) && (wps_method == WPS_PIN_KEYPAD))
goto inv_args;
+ if (wpa_s->p2p_dev)
+ wpa_s = wpa_s->p2p_dev;
+
new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
persistent_group, 0, join, authorize_only,
- go_intent, freq);
+ go_intent, freq, -1, 0, 0, 0);
if (new_pin >= 0) {
char npin[9];
goto err;
}
+ if (wpa_s->p2p_dev)
+ wpa_s = wpa_s->p2p_dev;
+
if (persistent) {
/*
* A group ID is defined meaning we want to re-invoke a
if (ssid == NULL || ssid->disabled != 2)
goto err;
- if (wpas_p2p_invite(wpa_s, peer_addr, ssid, NULL) < 0) {
+ if (wpas_p2p_invite(wpa_s, peer_addr, ssid, NULL, 0, 0, 0, 0) <
+ 0) {
reply = wpas_dbus_error_unknown_error(
message,
"Failed to reinvoke a persistent group");
os_strcmp(config_method, "pushbutton"))
return wpas_dbus_error_invalid_args(message, NULL);
- if (wpas_p2p_prov_disc(wpa_s, peer_addr, config_method, 0) < 0)
+ if (wpa_s->p2p_dev)
+ wpa_s = wpa_s->p2p_dev;
+
+ if (wpas_p2p_prov_disc(wpa_s, peer_addr, config_method,
+ WPAS_P2P_PD_FOR_GO_NEG) < 0)
return wpas_dbus_error_unknown_error(message,
"Failed to send provision discovery request");
if (!wpa_dbus_p2p_check_enabled(wpa_s, NULL, NULL, error))
return FALSE;
+ if (wpa_s->p2p_dev)
+ wpa_s = wpa_s->p2p_dev;
+
if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
"a{sv}", &variant_iter) ||
!wpa_dbus_dict_open_write(&variant_iter, &dict_iter))
wpa_s->conf->disassoc_low_ack))
goto err_no_mem;
+ /* No Group Iface */
+ if (!wpa_dbus_dict_append_bool(&dict_iter, "NoGroupIface",
+ wpa_s->conf->p2p_no_group_iface))
+ goto err_no_mem;
+
+ /* P2P Search Delay */
+ if (!wpa_dbus_dict_append_uint32(&dict_iter, "p2p_search_delay",
+ wpa_s->conf->p2p_search_delay))
+ goto err_no_mem;
+
if (!wpa_dbus_dict_close_write(&variant_iter, &dict_iter) ||
!dbus_message_iter_close_container(iter, &variant_iter))
goto err_no_mem;
if (!wpa_dbus_p2p_check_enabled(wpa_s, NULL, NULL, error))
return FALSE;
+ if (wpa_s->p2p_dev)
+ wpa_s = wpa_s->p2p_dev;
+
dbus_message_iter_recurse(iter, &variant_iter);
if (!wpa_dbus_dict_open_read(&variant_iter, &iter_dict, error))
return FALSE;
else if (os_strcmp(entry.key, "disassoc_low_ack") == 0 &&
entry.type == DBUS_TYPE_UINT32)
wpa_s->conf->disassoc_low_ack = entry.uint32_value;
+ else if (os_strcmp(entry.key, "NoGroupIface") == 0 &&
+ entry.type == DBUS_TYPE_BOOLEAN)
+ wpa_s->conf->p2p_no_group_iface = entry.bool_value;
+ else if (os_strcmp(entry.key, "p2p_search_delay") == 0 &&
+ entry.type == DBUS_TYPE_UINT32)
+ wpa_s->conf->p2p_search_delay = entry.uint32_value;
else
goto error;
* Now construct the peer object paths in a form suitable for
* array_property_getter helper below.
*/
- peer_obj_paths = os_zalloc(num * sizeof(char *));
+ peer_obj_paths = os_calloc(num, sizeof(char *));
if (!peer_obj_paths) {
out_of_mem = 1;
break;
default:
str = "device";
+ break;
}
return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &str,
void *user_data)
{
struct wpabuf *vendor_extension[P2P_MAX_WPS_VENDOR_EXT];
- int i, num;
+ unsigned int i, num = 0;
struct peer_handler_args *peer_args = user_data;
const struct p2p_peer_info *info;
}
/* Add WPS vendor extensions attribute */
- for (i = 0, num = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
+ os_memset(vendor_extension, 0, sizeof(vendor_extension));
+ for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
if (info->wps_vendor_ext[i] == NULL)
continue;
vendor_extension[num] = info->wps_vendor_ext[i];
dbus_bool_t wpas_dbus_getter_p2p_peer_ies(DBusMessageIter *iter,
DBusError *error, void *user_data)
{
- dbus_bool_t success;
- /* struct peer_handler_args *peer_args = user_data; */
+ struct peer_handler_args *peer_args = user_data;
+ const struct p2p_peer_info *info;
+
+ info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
+ peer_args->p2p_device_addr, 0);
+ if (info == NULL) {
+ dbus_set_error(error, DBUS_ERROR_FAILED,
+ "failed to find peer");
+ return FALSE;
+ }
+
+ if (info->wfd_subelems == NULL)
+ return wpas_dbus_simple_array_property_getter(iter,
+ DBUS_TYPE_BYTE,
+ NULL, 0, error);
+
+ return wpas_dbus_simple_array_property_getter(
+ iter, DBUS_TYPE_BYTE, (char *) info->wfd_subelems->buf,
+ info->wfd_subelems->used, error);
+}
+
+
+dbus_bool_t wpas_dbus_getter_p2p_peer_device_address(DBusMessageIter *iter,
+ DBusError *error,
+ void *user_data)
+{
+ struct peer_handler_args *peer_args = user_data;
+ const struct p2p_peer_info *info;
+
+ info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
+ peer_args->p2p_device_addr, 0);
+ if (info == NULL) {
+ dbus_set_error(error, DBUS_ERROR_FAILED,
+ "failed to find peer");
+ return FALSE;
+ }
+
+ return wpas_dbus_simple_array_property_getter(
+ iter, DBUS_TYPE_BYTE, (char *) info->p2p_device_addr,
+ ETH_ALEN, error);
+}
+
+
+struct peer_group_data {
+ struct wpa_supplicant *wpa_s;
+ const struct p2p_peer_info *info;
+ char **paths;
+ unsigned int nb_paths;
+ int error;
+};
+
+
+static int match_group_where_peer_is_client(struct p2p_group *group,
+ void *user_data)
+{
+ struct peer_group_data *data = user_data;
+ const struct p2p_group_config *cfg;
+ struct wpa_supplicant *wpa_s_go;
+ char **paths;
+
+ if (!p2p_group_is_client_connected(group, data->info->p2p_device_addr))
+ return 1;
+
+ cfg = p2p_group_get_config(group);
+
+ wpa_s_go = wpas_get_p2p_go_iface(data->wpa_s, cfg->ssid,
+ cfg->ssid_len);
+ if (wpa_s_go == NULL)
+ return 1;
+
+ paths = os_realloc_array(data->paths, data->nb_paths + 1,
+ sizeof(char *));
+ if (paths == NULL)
+ goto out_of_memory;
+
+ data->paths = paths;
+ data->paths[data->nb_paths] = wpa_s_go->dbus_groupobj_path;
+ data->nb_paths++;
+
+ return 1;
+
+out_of_memory:
+ data->error = ENOMEM;
+ return 0;
+}
+
+
+dbus_bool_t wpas_dbus_getter_p2p_peer_groups(DBusMessageIter *iter,
+ DBusError *error,
+ void *user_data)
+{
+ struct peer_handler_args *peer_args = user_data;
+ const struct p2p_peer_info *info;
+ struct peer_group_data data;
+ struct wpa_supplicant *wpa_s, *wpa_s_go;
+ dbus_bool_t success = FALSE;
+
+ info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
+ peer_args->p2p_device_addr, 0);
+ if (info == NULL) {
+ dbus_set_error(error, DBUS_ERROR_FAILED,
+ "failed to find peer");
+ return FALSE;
+ }
+
+ os_memset(&data, 0, sizeof(data));
+
+ wpa_s = peer_args->wpa_s;
+ if (wpa_s->p2p_dev)
+ wpa_s = wpa_s->p2p_dev;
+
+ wpa_s_go = wpas_get_p2p_client_iface(wpa_s, info->p2p_device_addr);
+ if (wpa_s_go) {
+ data.paths = os_calloc(1, sizeof(char *));
+ if (data.paths == NULL)
+ goto out_of_memory;
+ data.paths[0] = wpa_s_go->dbus_groupobj_path;
+ data.nb_paths = 1;
+ }
- success = wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
- NULL, 0, error);
+ data.wpa_s = peer_args->wpa_s;
+ data.info = info;
+
+ p2p_loop_on_all_groups(peer_args->wpa_s->global->p2p,
+ match_group_where_peer_is_client, &data);
+ if (data.error)
+ goto out_of_memory;
+
+ if (data.paths == NULL) {
+ return wpas_dbus_simple_array_property_getter(
+ iter, DBUS_TYPE_OBJECT_PATH, NULL, 0, error);
+ }
+
+ success = wpas_dbus_simple_array_property_getter(iter,
+ DBUS_TYPE_OBJECT_PATH,
+ data.paths,
+ data.nb_paths, error);
+ goto out;
+
+out_of_memory:
+ dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
+out:
+ os_free(data.paths);
return success;
}
unsigned int i = 0, num = 0;
dbus_bool_t success = FALSE;
- if (wpa_s->conf == NULL) {
- wpa_printf(MSG_ERROR, "dbus: %s: "
- "An error occurred getting persistent groups list",
- __func__);
- dbus_set_error_const(error, DBUS_ERROR_FAILED, "an error "
- "occurred getting persistent groups list");
- return FALSE;
- }
-
for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
if (network_is_persistent_group(ssid))
num++;
- paths = os_zalloc(num * sizeof(char *));
+ paths = os_calloc(num, sizeof(char *));
if (!paths) {
dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
return FALSE;
num_members = p2p_get_group_num_members(wpa_s->p2p_group);
- paths = os_zalloc(num_members * sizeof(char *));
+ paths = os_calloc(num_members, sizeof(char *));
if (!paths)
goto out_of_memory;
if (!paths[i])
goto out_of_memory;
os_snprintf(paths[i], WPAS_DBUS_OBJECT_PATH_MAX,
- "%s/" WPAS_DBUS_NEW_P2P_GROUPMEMBERS_PART
+ "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART
"/" COMPACT_MACSTR,
- wpa_s->dbus_groupobj_path, MAC2STR(addr));
+ wpa_s->parent->dbus_new_path, MAC2STR(addr));
i++;
}
struct wpa_supplicant *wpa_s = user_data;
struct hostapd_data *hapd;
struct wpabuf *vendor_ext[MAX_WPS_VENDOR_EXTENSIONS];
- int num_vendor_ext = 0;
- int i;
+ unsigned int i, num_vendor_ext = 0;
+
+ os_memset(vendor_ext, 0, sizeof(vendor_ext));
/* Verify correct role for this property */
if (wpas_get_p2p_role(wpa_s) == WPAS_P2P_ROLE_GO) {
/* Parse WPS Vendor Extensions sent in Beacon/Probe Response */
for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
if (hapd->conf->wps_vendor_ext[i] == NULL)
- vendor_ext[i] = NULL;
- else {
- vendor_ext[num_vendor_ext++] =
- hapd->conf->wps_vendor_ext[i];
- }
+ continue;
+ vendor_ext[num_vendor_ext++] =
+ hapd->conf->wps_vendor_ext[i];
}
}
DBUS_TYPE_BYTE,
vendor_ext,
num_vendor_ext,
- error);
+ error);
}
void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
- DBusMessageIter variant_iter, iter_dict;
+ DBusMessageIter variant_iter, iter_dict, array_iter, sub;
struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
unsigned int i;
struct hostapd_data *hapd = NULL;
return FALSE;
dbus_message_iter_recurse(iter, &variant_iter);
+ if (dbus_message_iter_get_arg_type(&variant_iter) != DBUS_TYPE_ARRAY)
+ return FALSE;
+
+ /*
+ * This is supposed to be array of bytearrays (aay), but the earlier
+ * implementation used a dict with "WPSVendorExtensions" as the key in
+ * this setter function which does not match the format used by the
+ * getter function. For backwards compatibility, allow both formats to
+ * be used in the setter.
+ */
+ if (dbus_message_iter_get_element_type(&variant_iter) ==
+ DBUS_TYPE_ARRAY) {
+ /* This is the proper format matching the getter */
+ struct wpabuf *vals[MAX_WPS_VENDOR_EXTENSIONS];
+
+ dbus_message_iter_recurse(&variant_iter, &array_iter);
+
+ if (dbus_message_iter_get_arg_type(&array_iter) !=
+ DBUS_TYPE_ARRAY ||
+ dbus_message_iter_get_element_type(&array_iter) !=
+ DBUS_TYPE_BYTE) {
+ wpa_printf(MSG_DEBUG,
+ "dbus: Not an array of array of bytes");
+ return FALSE;
+ }
+
+ i = 0;
+ os_memset(vals, 0, sizeof(vals));
+
+ while (dbus_message_iter_get_arg_type(&array_iter) ==
+ DBUS_TYPE_ARRAY) {
+ char *val;
+ int len;
+
+ if (i == MAX_WPS_VENDOR_EXTENSIONS) {
+ wpa_printf(MSG_DEBUG,
+ "dbus: Too many WPSVendorExtensions values");
+ i = MAX_WPS_VENDOR_EXTENSIONS + 1;
+ break;
+ }
+
+ dbus_message_iter_recurse(&array_iter, &sub);
+ dbus_message_iter_get_fixed_array(&sub, &val, &len);
+ wpa_hexdump(MSG_DEBUG, "dbus: WPSVendorExtentions[]",
+ val, len);
+ vals[i] = wpabuf_alloc_copy(val, len);
+ if (vals[i] == NULL) {
+ i = MAX_WPS_VENDOR_EXTENSIONS + 1;
+ break;
+ }
+ i++;
+ dbus_message_iter_next(&array_iter);
+ }
+
+ if (i > MAX_WPS_VENDOR_EXTENSIONS) {
+ for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++)
+ wpabuf_free(vals[i]);
+ return FALSE;
+ }
+
+ for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
+ wpabuf_free(hapd->conf->wps_vendor_ext[i]);
+ hapd->conf->wps_vendor_ext[i] = vals[i];
+ }
+
+ hostapd_update_wps(hapd);
+
+ return TRUE;
+ }
+
+ if (dbus_message_iter_get_element_type(&variant_iter) !=
+ DBUS_TYPE_DICT_ENTRY)
+ return FALSE;
+
+ wpa_printf(MSG_DEBUG,
+ "dbus: Try to use backwards compatibility version of WPSVendorExtensions setter");
if (!wpa_dbus_dict_open_read(&variant_iter, &iter_dict, error))
return FALSE;
goto error;
for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
+ wpabuf_free(hapd->conf->wps_vendor_ext[i]);
if (i < entry.array_len) {
hapd->conf->wps_vendor_ext[i] =
entry.binarray_value[i];
if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
goto error;
- if (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
+ while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
goto error;
bonjour = 1;
else
goto error_clear;
- wpa_dbus_dict_entry_clear(&entry);
+ } else if (!os_strcmp(entry.key, "version") &&
+ entry.type == DBUS_TYPE_INT32) {
+ version = entry.uint32_value;
+ } else if (!os_strcmp(entry.key, "service") &&
+ (entry.type == DBUS_TYPE_STRING)) {
+ os_free(service);
+ service = os_strdup(entry.str_value);
+ } else if (!os_strcmp(entry.key, "query")) {
+ if ((entry.type != DBUS_TYPE_ARRAY) ||
+ (entry.array_type != DBUS_TYPE_BYTE))
+ goto error_clear;
+ query = wpabuf_alloc_copy(
+ entry.bytearray_value,
+ entry.array_len);
+ } else if (!os_strcmp(entry.key, "response")) {
+ if ((entry.type != DBUS_TYPE_ARRAY) ||
+ (entry.array_type != DBUS_TYPE_BYTE))
+ goto error_clear;
+ resp = wpabuf_alloc_copy(entry.bytearray_value,
+ entry.array_len);
}
+ wpa_dbus_dict_entry_clear(&entry);
}
if (upnp == 1) {
- while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
- if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
- goto error;
-
- if (!os_strcmp(entry.key, "version") &&
- entry.type == DBUS_TYPE_INT32)
- version = entry.uint32_value;
- else if (!os_strcmp(entry.key, "service") &&
- entry.type == DBUS_TYPE_STRING)
- service = os_strdup(entry.str_value);
- wpa_dbus_dict_entry_clear(&entry);
- }
if (version <= 0 || service == NULL)
goto error;
if (wpas_p2p_service_add_upnp(wpa_s, version, service) != 0)
goto error;
- os_free(service);
} else if (bonjour == 1) {
- while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
- if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
- goto error;
-
- if (!os_strcmp(entry.key, "query")) {
- if ((entry.type != DBUS_TYPE_ARRAY) ||
- (entry.array_type != DBUS_TYPE_BYTE))
- goto error_clear;
- query = wpabuf_alloc_copy(
- entry.bytearray_value,
- entry.array_len);
- } else if (!os_strcmp(entry.key, "response")) {
- if ((entry.type != DBUS_TYPE_ARRAY) ||
- (entry.array_type != DBUS_TYPE_BYTE))
- goto error_clear;
- resp = wpabuf_alloc_copy(entry.bytearray_value,
- entry.array_len);
- }
-
- wpa_dbus_dict_entry_clear(&entry);
- }
-
if (query == NULL || resp == NULL)
goto error;
- if (wpas_p2p_service_add_bonjour(wpa_s, query, resp) < 0) {
- wpabuf_free(query);
- wpabuf_free(resp);
+ if (wpas_p2p_service_add_bonjour(wpa_s, query, resp) < 0)
goto error;
- }
+ query = NULL;
+ resp = NULL;
} else
goto error;
+ os_free(service);
return reply;
error_clear:
wpa_dbus_dict_entry_clear(&entry);
error:
+ os_free(service);
+ wpabuf_free(query);
+ wpabuf_free(resp);
return wpas_dbus_error_invalid_args(message, NULL);
}
entry.type == DBUS_TYPE_INT32)
version = entry.uint32_value;
else if (!os_strcmp(entry.key, "service") &&
- entry.type == DBUS_TYPE_STRING)
+ entry.type == DBUS_TYPE_STRING) {
+ os_free(service);
service = os_strdup(entry.str_value);
- else
+ } else
goto error_clear;
wpa_dbus_dict_entry_clear(&entry);
goto error;
ret = wpas_p2p_service_del_upnp(wpa_s, version, service);
- os_free(service);
if (ret != 0)
goto error;
} else if (bonjour == 1) {
if ((entry.type != DBUS_TYPE_ARRAY) ||
(entry.array_type != DBUS_TYPE_BYTE))
goto error_clear;
+ wpabuf_free(query);
query = wpabuf_alloc_copy(
entry.bytearray_value,
entry.array_len);
ret = wpas_p2p_service_del_bonjour(wpa_s, query);
if (ret != 0)
goto error;
- wpabuf_free(query);
} else
goto error;
+ wpabuf_free(query);
+ os_free(service);
return reply;
error_clear:
wpa_dbus_dict_entry_clear(&entry);
error:
+ wpabuf_free(query);
+ os_free(service);
return wpas_dbus_error_invalid_args(message, NULL);
}
struct wpabuf *tlv = NULL;
u8 version = 0;
u64 ref = 0;
- u8 addr[ETH_ALEN];
+ u8 addr_buf[ETH_ALEN], *addr;
dbus_message_iter_init(message, &iter);
wpa_dbus_dict_entry_clear(&entry);
}
- if (!peer_object_path ||
- (parse_peer_object_path(peer_object_path, addr) < 0) ||
- !p2p_peer_known(wpa_s->global->p2p, addr))
- goto error;
+ if (!peer_object_path) {
+ addr = NULL;
+ } else {
+ if (parse_peer_object_path(peer_object_path, addr_buf) < 0 ||
+ !p2p_peer_known(wpa_s->global->p2p, addr_buf))
+ goto error;
+
+ addr = addr_buf;
+ }
if (upnp == 1) {
if (version <= 0 || service == NULL)
entry.type == DBUS_TYPE_INT32) {
freq = entry.uint32_value;
} else if (!os_strcmp(entry.key, "dialog_token") &&
- entry.type == DBUS_TYPE_UINT32) {
+ (entry.type == DBUS_TYPE_UINT32 ||
+ entry.type == DBUS_TYPE_INT32)) {
dlg_tok = entry.uint32_value;
} else if (!os_strcmp(entry.key, "tlvs")) {
if (entry.type != DBUS_TYPE_ARRAY ||
if (req == 0)
goto error;
- if (!wpas_p2p_sd_cancel_request(wpa_s, req))
+ if (wpas_p2p_sd_cancel_request(wpa_s, req) < 0)
goto error;
return NULL;
return NULL;
}
+
+
+#ifdef CONFIG_WIFI_DISPLAY
+
+dbus_bool_t wpas_dbus_getter_global_wfd_ies(DBusMessageIter *iter,
+ DBusError *error, void *user_data)
+{
+ struct wpa_global *global = user_data;
+ struct wpabuf *ie;
+ dbus_bool_t ret;
+
+ ie = wifi_display_get_wfd_ie(global);
+ if (ie == NULL)
+ return wpas_dbus_simple_array_property_getter(iter,
+ DBUS_TYPE_BYTE,
+ NULL, 0, error);
+
+ ret = wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
+ wpabuf_head(ie),
+ wpabuf_len(ie), error);
+ wpabuf_free(ie);
+
+ return ret;
+}
+
+
+dbus_bool_t wpas_dbus_setter_global_wfd_ies(DBusMessageIter *iter,
+ DBusError *error, void *user_data)
+{
+ struct wpa_global *global = user_data;
+ DBusMessageIter variant, array;
+ struct wpabuf *ie = NULL;
+ const u8 *data;
+ int len;
+
+ if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_VARIANT)
+ goto err;
+
+ dbus_message_iter_recurse(iter, &variant);
+ if (dbus_message_iter_get_arg_type(&variant) != DBUS_TYPE_ARRAY)
+ goto err;
+
+ dbus_message_iter_recurse(&variant, &array);
+ dbus_message_iter_get_fixed_array(&array, &data, &len);
+ if (len == 0) {
+ wifi_display_enable(global, 0);
+ wifi_display_deinit(global);
+
+ return TRUE;
+ }
+
+ ie = wpabuf_alloc(len);
+ if (ie == NULL)
+ goto err;
+
+ wpabuf_put_data(ie, data, len);
+ if (wifi_display_subelem_set_from_ies(global, ie) != 0)
+ goto err;
+
+ if (global->wifi_display == 0)
+ wifi_display_enable(global, 1);
+
+ wpabuf_free(ie);
+
+ return TRUE;
+err:
+ wpabuf_free(ie);
+
+ dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
+ "invalid message format");
+ return FALSE;
+}
+
+#endif /* CONFIG_WIFI_DISPLAY */