P2P: Advertise Persistent Reconnect group capability
The persistent_reconnect configuration parameter was used to decide whether to accept invitation to re-establish a persistent group. However, this was not being advertised in the Group Capability bitmap. Add the Persistent Reconnect bit based on this configuration to GO Negotiation frames and Beacon/Probe Response frames from the GO.
This commit is contained in:
parent
ccc12d7841
commit
acc247b260
6 changed files with 70 additions and 17 deletions
|
@ -1029,6 +1029,26 @@ static int p2p_prepare_channel(struct p2p_data *p2p, unsigned int force_freq)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void p2p_set_dev_persistent(struct p2p_device *dev,
|
||||||
|
int persistent_group)
|
||||||
|
{
|
||||||
|
switch (persistent_group) {
|
||||||
|
case 0:
|
||||||
|
dev->flags &= ~(P2P_DEV_PREFER_PERSISTENT_GROUP |
|
||||||
|
P2P_DEV_PREFER_PERSISTENT_RECONN);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
dev->flags |= P2P_DEV_PREFER_PERSISTENT_GROUP;
|
||||||
|
dev->flags &= ~P2P_DEV_PREFER_PERSISTENT_RECONN;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
dev->flags |= P2P_DEV_PREFER_PERSISTENT_GROUP |
|
||||||
|
P2P_DEV_PREFER_PERSISTENT_RECONN;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
|
int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
|
||||||
enum p2p_wps_method wps_method,
|
enum p2p_wps_method wps_method,
|
||||||
int go_intent, const u8 *own_interface_addr,
|
int go_intent, const u8 *own_interface_addr,
|
||||||
|
@ -1086,10 +1106,7 @@ int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
|
||||||
dev->connect_reqs = 0;
|
dev->connect_reqs = 0;
|
||||||
dev->go_neg_req_sent = 0;
|
dev->go_neg_req_sent = 0;
|
||||||
dev->go_state = UNKNOWN_GO;
|
dev->go_state = UNKNOWN_GO;
|
||||||
if (persistent_group)
|
p2p_set_dev_persistent(dev, persistent_group);
|
||||||
dev->flags |= P2P_DEV_PREFER_PERSISTENT_GROUP;
|
|
||||||
else
|
|
||||||
dev->flags &= ~P2P_DEV_PREFER_PERSISTENT_GROUP;
|
|
||||||
p2p->go_intent = go_intent;
|
p2p->go_intent = go_intent;
|
||||||
os_memcpy(p2p->intended_addr, own_interface_addr, ETH_ALEN);
|
os_memcpy(p2p->intended_addr, own_interface_addr, ETH_ALEN);
|
||||||
|
|
||||||
|
@ -1159,10 +1176,7 @@ int p2p_authorize(struct p2p_data *p2p, const u8 *peer_addr,
|
||||||
dev->flags &= ~P2P_DEV_USER_REJECTED;
|
dev->flags &= ~P2P_DEV_USER_REJECTED;
|
||||||
dev->go_neg_req_sent = 0;
|
dev->go_neg_req_sent = 0;
|
||||||
dev->go_state = UNKNOWN_GO;
|
dev->go_state = UNKNOWN_GO;
|
||||||
if (persistent_group)
|
p2p_set_dev_persistent(dev, persistent_group);
|
||||||
dev->flags |= P2P_DEV_PREFER_PERSISTENT_GROUP;
|
|
||||||
else
|
|
||||||
dev->flags &= ~P2P_DEV_PREFER_PERSISTENT_GROUP;
|
|
||||||
p2p->go_intent = go_intent;
|
p2p->go_intent = go_intent;
|
||||||
os_memcpy(p2p->intended_addr, own_interface_addr, ETH_ALEN);
|
os_memcpy(p2p->intended_addr, own_interface_addr, ETH_ALEN);
|
||||||
|
|
||||||
|
@ -1273,8 +1287,12 @@ void p2p_go_complete(struct p2p_data *p2p, struct p2p_device *peer)
|
||||||
os_memcpy(res.peer_device_addr, peer->info.p2p_device_addr, ETH_ALEN);
|
os_memcpy(res.peer_device_addr, peer->info.p2p_device_addr, ETH_ALEN);
|
||||||
os_memcpy(res.peer_interface_addr, peer->intended_addr, ETH_ALEN);
|
os_memcpy(res.peer_interface_addr, peer->intended_addr, ETH_ALEN);
|
||||||
res.wps_method = peer->wps_method;
|
res.wps_method = peer->wps_method;
|
||||||
if (peer->flags & P2P_DEV_PREFER_PERSISTENT_GROUP)
|
if (peer->flags & P2P_DEV_PREFER_PERSISTENT_GROUP) {
|
||||||
res.persistent_group = 1;
|
if (peer->flags & P2P_DEV_PREFER_PERSISTENT_RECONN)
|
||||||
|
res.persistent_group = 2;
|
||||||
|
else
|
||||||
|
res.persistent_group = 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (go) {
|
if (go) {
|
||||||
/* Setup AP mode for WPS provisioning */
|
/* Setup AP mode for WPS provisioning */
|
||||||
|
|
|
@ -120,6 +120,9 @@ struct p2p_go_neg_results {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* persistent_group - Whether the group should be made persistent
|
* persistent_group - Whether the group should be made persistent
|
||||||
|
* 0 = not persistent
|
||||||
|
* 1 = persistent group without persistent reconnect
|
||||||
|
* 2 = persistent group with persistent reconnect
|
||||||
*/
|
*/
|
||||||
int persistent_group;
|
int persistent_group;
|
||||||
|
|
||||||
|
@ -846,7 +849,9 @@ int p2p_listen(struct p2p_data *p2p, unsigned int timeout);
|
||||||
* @go_intent: Local GO intent value (1..15)
|
* @go_intent: Local GO intent value (1..15)
|
||||||
* @own_interface_addr: Intended interface address to use with the group
|
* @own_interface_addr: Intended interface address to use with the group
|
||||||
* @force_freq: The only allowed channel frequency in MHz or 0
|
* @force_freq: The only allowed channel frequency in MHz or 0
|
||||||
* @persistent_group: Whether to create a persistent group
|
* @persistent_group: Whether to create a persistent group (0 = no, 1 =
|
||||||
|
* persistent group without persistent reconnect, 2 = persistent group with
|
||||||
|
* persistent reconnect)
|
||||||
* Returns: 0 on success, -1 on failure
|
* Returns: 0 on success, -1 on failure
|
||||||
*/
|
*/
|
||||||
int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
|
int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
|
||||||
|
@ -862,7 +867,9 @@ int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
|
||||||
* @go_intent: Local GO intent value (1..15)
|
* @go_intent: Local GO intent value (1..15)
|
||||||
* @own_interface_addr: Intended interface address to use with the group
|
* @own_interface_addr: Intended interface address to use with the group
|
||||||
* @force_freq: The only allowed channel frequency in MHz or 0
|
* @force_freq: The only allowed channel frequency in MHz or 0
|
||||||
* @persistent_group: Whether to create a persistent group
|
* @persistent_group: Whether to create a persistent group (0 = no, 1 =
|
||||||
|
* persistent group without persistent reconnect, 2 = persistent group with
|
||||||
|
* persistent reconnect)
|
||||||
* Returns: 0 on success, -1 on failure
|
* Returns: 0 on success, -1 on failure
|
||||||
*
|
*
|
||||||
* This is like p2p_connect(), but the actual group negotiation is not
|
* This is like p2p_connect(), but the actual group negotiation is not
|
||||||
|
@ -1164,6 +1171,9 @@ struct p2p_group;
|
||||||
struct p2p_group_config {
|
struct p2p_group_config {
|
||||||
/**
|
/**
|
||||||
* persistent_group - Whether the group is persistent
|
* persistent_group - Whether the group is persistent
|
||||||
|
* 0 = not a persistent group
|
||||||
|
* 1 = persistent group without persistent reconnect
|
||||||
|
* 2 = persistent group with persistent reconnect
|
||||||
*/
|
*/
|
||||||
int persistent_group;
|
int persistent_group;
|
||||||
|
|
||||||
|
|
|
@ -152,8 +152,11 @@ static struct wpabuf * p2p_build_go_neg_req(struct p2p_data *p2p,
|
||||||
|
|
||||||
len = p2p_buf_add_ie_hdr(buf);
|
len = p2p_buf_add_ie_hdr(buf);
|
||||||
group_capab = 0;
|
group_capab = 0;
|
||||||
if (peer->flags & P2P_DEV_PREFER_PERSISTENT_GROUP)
|
if (peer->flags & P2P_DEV_PREFER_PERSISTENT_GROUP) {
|
||||||
group_capab |= P2P_GROUP_CAPAB_PERSISTENT_GROUP;
|
group_capab |= P2P_GROUP_CAPAB_PERSISTENT_GROUP;
|
||||||
|
if (peer->flags & P2P_DEV_PREFER_PERSISTENT_RECONN)
|
||||||
|
group_capab |= P2P_GROUP_CAPAB_PERSISTENT_RECONN;
|
||||||
|
}
|
||||||
if (p2p->cross_connect)
|
if (p2p->cross_connect)
|
||||||
group_capab |= P2P_GROUP_CAPAB_CROSS_CONN;
|
group_capab |= P2P_GROUP_CAPAB_CROSS_CONN;
|
||||||
if (p2p->cfg->p2p_intra_bss)
|
if (p2p->cfg->p2p_intra_bss)
|
||||||
|
@ -242,8 +245,12 @@ static struct wpabuf * p2p_build_go_neg_resp(struct p2p_data *p2p,
|
||||||
p2p_buf_add_status(buf, status);
|
p2p_buf_add_status(buf, status);
|
||||||
group_capab = 0;
|
group_capab = 0;
|
||||||
if (peer && peer->go_state == LOCAL_GO) {
|
if (peer && peer->go_state == LOCAL_GO) {
|
||||||
if (peer->flags & P2P_DEV_PREFER_PERSISTENT_GROUP)
|
if (peer->flags & P2P_DEV_PREFER_PERSISTENT_GROUP) {
|
||||||
group_capab |= P2P_GROUP_CAPAB_PERSISTENT_GROUP;
|
group_capab |= P2P_GROUP_CAPAB_PERSISTENT_GROUP;
|
||||||
|
if (peer->flags & P2P_DEV_PREFER_PERSISTENT_RECONN)
|
||||||
|
group_capab |=
|
||||||
|
P2P_GROUP_CAPAB_PERSISTENT_RECONN;
|
||||||
|
}
|
||||||
if (p2p->cross_connect)
|
if (p2p->cross_connect)
|
||||||
group_capab |= P2P_GROUP_CAPAB_CROSS_CONN;
|
group_capab |= P2P_GROUP_CAPAB_CROSS_CONN;
|
||||||
if (p2p->cfg->p2p_intra_bss)
|
if (p2p->cfg->p2p_intra_bss)
|
||||||
|
@ -673,8 +680,12 @@ static struct wpabuf * p2p_build_go_neg_conf(struct p2p_data *p2p,
|
||||||
p2p_buf_add_status(buf, status);
|
p2p_buf_add_status(buf, status);
|
||||||
group_capab = 0;
|
group_capab = 0;
|
||||||
if (peer->go_state == LOCAL_GO) {
|
if (peer->go_state == LOCAL_GO) {
|
||||||
if (peer->flags & P2P_DEV_PREFER_PERSISTENT_GROUP)
|
if (peer->flags & P2P_DEV_PREFER_PERSISTENT_GROUP) {
|
||||||
group_capab |= P2P_GROUP_CAPAB_PERSISTENT_GROUP;
|
group_capab |= P2P_GROUP_CAPAB_PERSISTENT_GROUP;
|
||||||
|
if (peer->flags & P2P_DEV_PREFER_PERSISTENT_RECONN)
|
||||||
|
group_capab |=
|
||||||
|
P2P_GROUP_CAPAB_PERSISTENT_RECONN;
|
||||||
|
}
|
||||||
if (p2p->cross_connect)
|
if (p2p->cross_connect)
|
||||||
group_capab |= P2P_GROUP_CAPAB_CROSS_CONN;
|
group_capab |= P2P_GROUP_CAPAB_CROSS_CONN;
|
||||||
if (p2p->cfg->p2p_intra_bss)
|
if (p2p->cfg->p2p_intra_bss)
|
||||||
|
|
|
@ -147,8 +147,11 @@ static void p2p_group_add_common_ies(struct p2p_group *group,
|
||||||
dev_capab |= P2P_DEV_CAPAB_SERVICE_DISCOVERY;
|
dev_capab |= P2P_DEV_CAPAB_SERVICE_DISCOVERY;
|
||||||
dev_capab |= P2P_DEV_CAPAB_INVITATION_PROCEDURE;
|
dev_capab |= P2P_DEV_CAPAB_INVITATION_PROCEDURE;
|
||||||
group_capab |= P2P_GROUP_CAPAB_GROUP_OWNER;
|
group_capab |= P2P_GROUP_CAPAB_GROUP_OWNER;
|
||||||
if (group->cfg->persistent_group)
|
if (group->cfg->persistent_group) {
|
||||||
group_capab |= P2P_GROUP_CAPAB_PERSISTENT_GROUP;
|
group_capab |= P2P_GROUP_CAPAB_PERSISTENT_GROUP;
|
||||||
|
if (group->cfg->persistent_group == 2)
|
||||||
|
group_capab |= P2P_GROUP_CAPAB_PERSISTENT_RECONN;
|
||||||
|
}
|
||||||
if (group->p2p->cfg->p2p_intra_bss)
|
if (group->p2p->cfg->p2p_intra_bss)
|
||||||
group_capab |= P2P_GROUP_CAPAB_INTRA_BSS_DIST;
|
group_capab |= P2P_GROUP_CAPAB_INTRA_BSS_DIST;
|
||||||
if (group->group_formation)
|
if (group->group_formation)
|
||||||
|
|
|
@ -89,6 +89,7 @@ struct p2p_device {
|
||||||
#define P2P_DEV_FORCE_FREQ BIT(13)
|
#define P2P_DEV_FORCE_FREQ BIT(13)
|
||||||
#define P2P_DEV_PD_FOR_JOIN BIT(14)
|
#define P2P_DEV_PD_FOR_JOIN BIT(14)
|
||||||
#define P2P_DEV_REPORTED_ONCE BIT(15)
|
#define P2P_DEV_REPORTED_ONCE BIT(15)
|
||||||
|
#define P2P_DEV_PREFER_PERSISTENT_RECONN BIT(16)
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
|
|
||||||
int status; /* enum p2p_status_code */
|
int status; /* enum p2p_status_code */
|
||||||
|
|
|
@ -756,6 +756,7 @@ static void wpas_p2p_clone_config(struct wpa_supplicant *dst,
|
||||||
|
|
||||||
d->p2p_group_idle = s->p2p_group_idle;
|
d->p2p_group_idle = s->p2p_group_idle;
|
||||||
d->p2p_intra_bss = s->p2p_intra_bss;
|
d->p2p_intra_bss = s->p2p_intra_bss;
|
||||||
|
d->persistent_reconnect = s->persistent_reconnect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2376,6 +2377,9 @@ static int wpas_p2p_start_go_neg(struct wpa_supplicant *wpa_s,
|
||||||
int go_intent, const u8 *own_interface_addr,
|
int go_intent, const u8 *own_interface_addr,
|
||||||
unsigned int force_freq, int persistent_group)
|
unsigned int force_freq, int persistent_group)
|
||||||
{
|
{
|
||||||
|
if (persistent_group && wpa_s->conf->persistent_reconnect)
|
||||||
|
persistent_group = 2;
|
||||||
|
|
||||||
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT) {
|
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT) {
|
||||||
return wpa_drv_p2p_connect(wpa_s, peer_addr, wps_method,
|
return wpa_drv_p2p_connect(wpa_s, peer_addr, wps_method,
|
||||||
go_intent, own_interface_addr,
|
go_intent, own_interface_addr,
|
||||||
|
@ -2394,6 +2398,9 @@ static int wpas_p2p_auth_go_neg(struct wpa_supplicant *wpa_s,
|
||||||
int go_intent, const u8 *own_interface_addr,
|
int go_intent, const u8 *own_interface_addr,
|
||||||
unsigned int force_freq, int persistent_group)
|
unsigned int force_freq, int persistent_group)
|
||||||
{
|
{
|
||||||
|
if (persistent_group && wpa_s->conf->persistent_reconnect)
|
||||||
|
persistent_group = 2;
|
||||||
|
|
||||||
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
|
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
@ -3210,7 +3217,10 @@ struct p2p_group * wpas_p2p_group_init(struct wpa_supplicant *wpa_s,
|
||||||
if (cfg == NULL)
|
if (cfg == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
cfg->persistent_group = persistent_group;
|
if (persistent_group && wpa_s->conf->persistent_reconnect)
|
||||||
|
cfg->persistent_group = 2;
|
||||||
|
else if (persistent_group)
|
||||||
|
cfg->persistent_group = 1;
|
||||||
os_memcpy(cfg->interface_addr, wpa_s->own_addr, ETH_ALEN);
|
os_memcpy(cfg->interface_addr, wpa_s->own_addr, ETH_ALEN);
|
||||||
if (wpa_s->max_stations &&
|
if (wpa_s->max_stations &&
|
||||||
wpa_s->max_stations < wpa_s->conf->max_num_sta)
|
wpa_s->max_stations < wpa_s->conf->max_num_sta)
|
||||||
|
|
Loading…
Reference in a new issue