From b9e2826b9d767cae7b919fa529bbdf2841ab018d Mon Sep 17 00:00:00 2001 From: Qiwei Cai Date: Mon, 9 May 2022 13:16:37 +0800 Subject: [PATCH] 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 --- src/p2p/p2p_build.c | 6 +++++- src/p2p/p2p_go_neg.c | 24 +++++++++++++++++++----- src/p2p/p2p_i.h | 2 +- src/p2p/p2p_invitation.c | 16 +++++++++++++--- src/p2p/p2p_pd.c | 20 ++++++++++++++++---- 5 files changed, 54 insertions(+), 14 deletions(-) diff --git a/src/p2p/p2p_build.c b/src/p2p/p2p_build.c index 4229d9b34..a484fb0b0 100644 --- a/src/p2p/p2p_build.c +++ b/src/p2p/p2p_build.c @@ -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); diff --git a/src/p2p/p2p_go_neg.c b/src/p2p/p2p_go_neg.c index 1d53d52f1..303aa7dd2 100644 --- a/src/p2p/p2p_go_neg.c +++ b/src/p2p/p2p_go_neg.c @@ -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); diff --git a/src/p2p/p2p_i.h b/src/p2p/p2p_i.h index aa147c614..59790de9c 100644 --- a/src/p2p/p2p_i.h +++ b/src/p2p/p2p_i.h @@ -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); diff --git a/src/p2p/p2p_invitation.c b/src/p2p/p2p_invitation.c index ab0072219..bca5b9096 100644 --- a/src/p2p/p2p_invitation.c +++ b/src/p2p/p2p_invitation.c @@ -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 diff --git a/src/p2p/p2p_pd.c b/src/p2p/p2p_pd.c index 338b47e4e..1a78e14ef 100644 --- a/src/p2p/p2p_pd.c +++ b/src/p2p/p2p_pd.c @@ -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);