]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
P2P: Filter 6 GHz channels if peer doesn't support them
authorQiwei Cai <quic_qcai@quicinc.com>
Mon, 9 May 2022 05:16:37 +0000 (13:16 +0800)
committerJouni Malinen <j@w1.fi>
Tue, 31 May 2022 09:41:48 +0000 (12:41 +0300)
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>
src/p2p/p2p_build.c
src/p2p/p2p_go_neg.c
src/p2p/p2p_i.h
src/p2p/p2p_invitation.c
src/p2p/p2p_pd.c

index 4229d9b3487369638f0c3e230a91b2b69aefb9d4..a484fb0b0f123796e95071e1e134691d5067b7b1 100644 (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);
index 1d53d52f1f8e7d92837c57baf7f406e2ed6d1baf..303aa7dd2aefcb88a611cdced7040f53e4bdf9f6 100644 (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);
index aa147c614fc53bd1084ac36178a5f583c821c363..59790de9c0643951e564904e49f29e9a30f34cc0 100644 (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);
index ab0072219d2e16422bf3f6733664e4cbbe983c29..bca5b90963608abc9f8ee1c3bc8306455902e1de 100644 (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
index 338b47e4e36b4884ba7485ae535ca84b65735f8c..1a78e14ef1a39c35efabcfe06900ac5ac593b519 100644 (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);