P2P: Filter 6 GHz channels if peer doesn't support them

When 6 GHz channels are included in channel list of P2P Action frames
but some peer devices don't support the 6 GHz feature and cannot parse
P2P IE data correctly, P2P handshake will fail.

Remove 6 GHz channels from the P2P Action frames if the peer doesn't
support 6 GHz feature to avoid such failures.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
This commit is contained in:
Qiwei Cai 2022-05-09 13:16:37 +08:00 committed by Jouni Malinen
parent d5a9944b84
commit b9e2826b9d
5 changed files with 54 additions and 14 deletions

View file

@ -10,6 +10,7 @@
#include "common.h"
#include "common/ieee802_11_defs.h"
#include "common/ieee802_11_common.h"
#include "common/qca-vendor.h"
#include "wps/wps_i.h"
#include "p2p_i.h"
@ -149,7 +150,7 @@ void p2p_buf_add_pref_channel_list(struct wpabuf *buf,
void p2p_buf_add_channel_list(struct wpabuf *buf, const char *country,
struct p2p_channels *chan)
struct p2p_channels *chan, bool is_6ghz_capab)
{
u8 *len;
size_t i;
@ -161,6 +162,9 @@ void p2p_buf_add_channel_list(struct wpabuf *buf, const char *country,
for (i = 0; i < chan->reg_classes; i++) {
struct p2p_reg_class *c = &chan->reg_class[i];
if (is_6ghz_op_class(c->reg_class) && !is_6ghz_capab)
continue;
wpabuf_put_u8(buf, c->reg_class);
wpabuf_put_u8(buf, c->channels);
wpabuf_put_data(buf, c->channel, c->channels);

View file

@ -142,6 +142,7 @@ static struct wpabuf * p2p_build_go_neg_req(struct p2p_data *p2p,
u8 group_capab;
size_t extra = 0;
u16 pw_id;
bool is_6ghz_capab;
#ifdef CONFIG_WIFI_DISPLAY
if (p2p->wfd_ie_go_neg)
@ -179,7 +180,10 @@ static struct wpabuf * p2p_build_go_neg_req(struct p2p_data *p2p,
p2p_buf_add_ext_listen_timing(buf, p2p->ext_listen_period,
p2p->ext_listen_interval);
p2p_buf_add_intended_addr(buf, p2p->intended_addr);
p2p_buf_add_channel_list(buf, p2p->cfg->country, &p2p->channels);
is_6ghz_capab = is_p2p_6ghz_capable(p2p) &&
p2p_is_peer_6ghz_capab(p2p, peer->info.p2p_device_addr);
p2p_buf_add_channel_list(buf, p2p->cfg->country, &p2p->channels,
is_6ghz_capab);
p2p_buf_add_device_info(buf, p2p, peer);
p2p_buf_add_operating_channel(buf, p2p->cfg->country,
p2p->op_reg_class, p2p->op_channel);
@ -278,6 +282,7 @@ static struct wpabuf * p2p_build_go_neg_resp(struct p2p_data *p2p,
u8 group_capab;
size_t extra = 0;
u16 pw_id;
bool is_6ghz_capab;
p2p_dbg(p2p, "Building GO Negotiation Response");
@ -330,15 +335,21 @@ static struct wpabuf * p2p_build_go_neg_resp(struct p2p_data *p2p,
p2p_buf_add_intended_addr(buf, p2p->intended_addr);
if (status || peer == NULL) {
p2p_buf_add_channel_list(buf, p2p->cfg->country,
&p2p->channels);
&p2p->channels, false);
} else if (peer->go_state == REMOTE_GO) {
is_6ghz_capab = is_p2p_6ghz_capable(p2p) &&
p2p_is_peer_6ghz_capab(p2p, peer->info.p2p_device_addr);
p2p_buf_add_channel_list(buf, p2p->cfg->country,
&p2p->channels);
&p2p->channels, is_6ghz_capab);
} else {
struct p2p_channels res;
is_6ghz_capab = is_p2p_6ghz_capable(p2p) &&
p2p_is_peer_6ghz_capab(p2p, peer->info.p2p_device_addr);
p2p_channels_intersect(&p2p->channels, &peer->channels,
&res);
p2p_buf_add_channel_list(buf, p2p->cfg->country, &res);
p2p_buf_add_channel_list(buf, p2p->cfg->country, &res,
is_6ghz_capab);
}
p2p_buf_add_device_info(buf, p2p, peer);
if (peer && peer->go_state == LOCAL_GO) {
@ -1085,6 +1096,7 @@ static struct wpabuf * p2p_build_go_neg_conf(struct p2p_data *p2p,
struct p2p_channels res;
u8 group_capab;
size_t extra = 0;
bool is_6ghz_capab;
p2p_dbg(p2p, "Building GO Negotiation Confirm");
@ -1128,7 +1140,9 @@ static struct wpabuf * p2p_build_go_neg_conf(struct p2p_data *p2p,
p2p_buf_add_operating_channel(buf, (const char *) resp_chan,
resp_chan[3], resp_chan[4]);
p2p_channels_intersect(&p2p->channels, &peer->channels, &res);
p2p_buf_add_channel_list(buf, p2p->cfg->country, &res);
is_6ghz_capab = is_p2p_6ghz_capable(p2p) &&
p2p_is_peer_6ghz_capab(p2p, peer->info.p2p_device_addr);
p2p_buf_add_channel_list(buf, p2p->cfg->country, &res, is_6ghz_capab);
if (go) {
p2p_buf_add_group_id(buf, p2p->cfg->dev_addr, p2p->ssid,
p2p->ssid_len);

View file

@ -758,7 +758,7 @@ void p2p_buf_add_listen_channel(struct wpabuf *buf, const char *country,
void p2p_buf_add_operating_channel(struct wpabuf *buf, const char *country,
u8 reg_class, u8 channel);
void p2p_buf_add_channel_list(struct wpabuf *buf, const char *country,
struct p2p_channels *chan);
struct p2p_channels *chan, bool is_6ghz_capab);
void p2p_buf_add_config_timeout(struct wpabuf *buf, u8 go_timeout,
u8 client_timeout);
void p2p_buf_add_intended_addr(struct wpabuf *buf, const u8 *interface_addr);

View file

@ -24,6 +24,7 @@ static struct wpabuf * p2p_build_invitation_req(struct p2p_data *p2p,
u8 *len;
const u8 *dev_addr;
size_t extra = 0;
bool is_6ghz_capab;
#ifdef CONFIG_WIFI_DISPLAY
struct wpabuf *wfd_ie = p2p->wfd_ie_invitation;
@ -74,7 +75,10 @@ static struct wpabuf * p2p_build_invitation_req(struct p2p_data *p2p,
p2p->op_channel);
if (p2p->inv_bssid_set)
p2p_buf_add_group_bssid(buf, p2p->inv_bssid);
p2p_buf_add_channel_list(buf, p2p->cfg->country, &p2p->channels);
is_6ghz_capab = is_p2p_6ghz_capable(p2p) &&
p2p_is_peer_6ghz_capab(p2p, peer->info.p2p_device_addr);
p2p_buf_add_channel_list(buf, p2p->cfg->country, &p2p->channels,
is_6ghz_capab);
if (go_dev_addr)
dev_addr = go_dev_addr;
else if (p2p->inv_role == P2P_INVITE_ROLE_CLIENT)
@ -155,8 +159,14 @@ static struct wpabuf * p2p_build_invitation_resp(struct p2p_data *p2p,
reg_class, channel);
if (group_bssid)
p2p_buf_add_group_bssid(buf, group_bssid);
if (channels)
p2p_buf_add_channel_list(buf, p2p->cfg->country, channels);
if (channels) {
bool is_6ghz_capab;
is_6ghz_capab = is_p2p_6ghz_capable(p2p) &&
p2p_is_peer_6ghz_capab(p2p, peer->info.p2p_device_addr);
p2p_buf_add_channel_list(buf, p2p->cfg->country, channels,
is_6ghz_capab);
}
p2p_buf_update_ie_hdr(buf, len);
#ifdef CONFIG_WIFI_DISPLAY

View file

@ -124,9 +124,15 @@ static void p2ps_add_pd_req_attrs(struct p2p_data *p2p, struct p2p_device *dev,
}
if (shared_group ||
(prov->conncap & (P2PS_SETUP_CLIENT | P2PS_SETUP_NEW)))
(prov->conncap & (P2PS_SETUP_CLIENT | P2PS_SETUP_NEW))) {
bool is_6ghz_capab;
is_6ghz_capab = is_p2p_6ghz_capable(p2p) &&
p2p_is_peer_6ghz_capab(
p2p, dev->info.p2p_device_addr);
p2p_buf_add_channel_list(buf, p2p->cfg->country,
&p2p->channels);
&p2p->channels, is_6ghz_capab);
}
if ((shared_group && !is_zero_ether_addr(intended_addr)) ||
(prov->conncap & (P2PS_SETUP_GROUP_OWNER | P2PS_SETUP_NEW)))
@ -356,9 +362,15 @@ static struct wpabuf * p2p_build_prov_disc_resp(struct p2p_data *p2p,
}
if (persist ||
(conncap & (P2PS_SETUP_CLIENT | P2PS_SETUP_GROUP_OWNER)))
(conncap & (P2PS_SETUP_CLIENT | P2PS_SETUP_GROUP_OWNER))) {
bool is_6ghz_capab;
is_6ghz_capab = is_p2p_6ghz_capable(p2p) &&
p2p_is_peer_6ghz_capab(
p2p, dev->info.p2p_device_addr);
p2p_buf_add_channel_list(buf, p2p->cfg->country,
&p2p->channels);
&p2p->channels, is_6ghz_capab);
}
if (!persist && conncap)
p2p_buf_add_connection_capability(buf, conncap);