From patchwork Fri Jul 19 04:40:05 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shivani Baranwal X-Patchwork-Id: 1962298 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; secure) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20210309 header.b=rnQ67Hx+; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=quicinc.com header.i=@quicinc.com header.a=rsa-sha256 header.s=qcppdkim1 header.b=LiGk5S21; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.infradead.org (client-ip=2607:7c80:54:3::133; helo=bombadil.infradead.org; envelope-from=hostap-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=patchwork.ozlabs.org) Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:3::133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4WQH8C0Rftz20B2 for ; Fri, 19 Jul 2024 14:42:03 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:CC:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=ok5N9S8OwnqPA+qGXD30wOXFap2Ay7Xc+KFHQSMjwGM=; b=rnQ67Hx++VdlPl kbktYVF4/4832Ke6u5l7TR019rcl7WyC1Dx7KSFNOy5/60cU4mPrA6C1v02fZk0dOgtbjRnm2fQI2 NsGgPuN9yYbqIxGzc1jkjjfXULJwR1YEOIOST9hgEFFn3t6y7ID4QQcsy7EepKFECX4Q7BhwqVsBA ks+mo0q62h6iLAiHlo65XVNSIB41tQGgwTGQEnLywwA/UmAVilgxeI/tsjXpdMb1eKIl+3FkF77FY GcCE4L+TvHUPgrMOPGbX3DduKxkb/lU4DwDH2GzGJ5ERuVVCBJ6Kf6k95QRiXowff1iCQ5Ul83oI/ ETtV+L2ubd/yLEenBdwQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1sUfR4-00000001Xjb-2k4H; Fri, 19 Jul 2024 04:41:38 +0000 Received: from mx0b-0031df01.pphosted.com ([205.220.180.131]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1sUfQd-00000001XOP-4AIP for hostap@lists.infradead.org; Fri, 19 Jul 2024 04:41:16 +0000 Received: from pps.filterd (m0279873.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 46J0tFwj028113 for ; Fri, 19 Jul 2024 04:41:11 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= cc:content-type:date:from:in-reply-to:message-id:mime-version :references:subject:to; s=qcppdkim1; bh=AWmclC+XDsMxdI1y17EC2Ame yjku93VgzCqtiiZl/Xk=; b=LiGk5S2187TnUA8WSItA8NrQ/W/JHXhUd+ufCrZw gOAMzfKkOpDddtmNv/YgAeludrrdkJuez2xO+26m676EoKTUGXbRVdCKQsh3SVDZ kuEABEGvSzQaDbL2C9+ABNpB7j0N1FOerQlUdDsf5RAF+qA7A9v7znDeuLaOKsjs h5BD7eFZZNQL74b59A1TcxNlLw+5EzAH0qukV8uRF0Ftj59rM9Uqyn3DDaDtrSlf KC4pqiYz7ei6BkeADIBZ5KX5KbBw/R8RXWA41VjtbrH5FO1Awx1b3ZY/kH1uh/NR q/iene3csnfS/2cmavonGu7vHPxiwSf1dUs6DYoGj5juTQ== Received: from nalasppmta05.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 40fe1arce6-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Fri, 19 Jul 2024 04:41:10 +0000 (GMT) Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com [10.47.209.196]) by NALASPPMTA05.qualcomm.com (8.17.1.19/8.17.1.19) with ESMTPS id 46J4f9ao021412 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Fri, 19 Jul 2024 04:41:09 GMT Received: from hu-shivbara-hyd.qualcomm.com (10.80.80.8) by nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Thu, 18 Jul 2024 21:41:08 -0700 From: Shivani Baranwal To: CC: Subject: [PATCH v2 13/14] P2P: Add support for Assited DFS for P2P2 GO in 5GHz Date: Fri, 19 Jul 2024 10:10:05 +0530 Message-ID: <1721364006-21658-14-git-send-email-quic_shivbara@quicinc.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1721364006-21658-1-git-send-email-quic_shivbara@quicinc.com> References: <1721364006-21658-1-git-send-email-quic_shivbara@quicinc.com> MIME-Version: 1.0 X-Originating-IP: [10.80.80.8] X-ClientProxiedBy: nasanex01a.na.qualcomm.com (10.52.223.231) To nalasex01a.na.qualcomm.com (10.47.209.196) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-GUID: kkNc4ztRLzdh1UbpeWlyRi-uedfVkXXb X-Proofpoint-ORIG-GUID: kkNc4ztRLzdh1UbpeWlyRi-uedfVkXXb X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1039,Hydra:6.0.680,FMLib:17.12.28.16 definitions=2024-07-19_01,2024-07-18_01,2024-05-17_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 impostorscore=0 mlxscore=0 spamscore=0 phishscore=0 mlxlogscore=999 priorityscore=1501 adultscore=0 lowpriorityscore=0 malwarescore=0 clxscore=1015 bulkscore=0 suspectscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2407110000 definitions=main-2407190035 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240718_214112_280124_CC5B90F3 X-CRM114-Status: GOOD ( 31.59 ) X-Spam-Score: -2.1 (--) X-Spam-Report: Spam detection software, running on the system "bombadil.infradead.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Signed-off-by: Shivani Baranwal --- src/ap/hostapd.c | 15 ++++- src/ap/hostapd.h | 3 + src/ap/hw_features.c | 3 +- src/common/ieee802_11_common.c | 14 ++--- src/common/ieee [...] Content analysis details: (-2.1 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 SPF_PASS SPF: sender matches SPF record -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] X-BeenThere: hostap@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Hostap" Errors-To: hostap-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org Signed-off-by: Shivani Baranwal --- src/ap/hostapd.c | 15 ++++- src/ap/hostapd.h | 3 + src/ap/hw_features.c | 3 +- src/common/ieee802_11_common.c | 14 ++--- src/common/ieee802_11_defs.h | 9 +++ src/p2p/p2p.c | 116 +++++++++++++++++++++++++++++++++++++- src/p2p/p2p.h | 22 ++++++++ src/p2p/p2p_build.c | 44 +++++++++++++++ src/p2p/p2p_go_neg.c | 68 ++++++++++++++++++++++ src/p2p/p2p_group.c | 11 ++++ src/p2p/p2p_i.h | 15 ++++- src/p2p/p2p_parse.c | 9 +++ src/p2p/p2p_utils.c | 50 ++++++++++++++++ wpa_supplicant/ap.c | 1 + wpa_supplicant/config.c | 2 + wpa_supplicant/config.h | 2 + wpa_supplicant/ctrl_iface.c | 5 ++ wpa_supplicant/events.c | 8 +++ wpa_supplicant/p2p_supplicant.c | 52 +++++++++++++++-- wpa_supplicant/p2p_supplicant.h | 7 +++ wpa_supplicant/wpa_supplicant_i.h | 1 + 21 files changed, 440 insertions(+), 17 deletions(-) diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c index 84a943e..81c13bf 100644 --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c @@ -2493,8 +2493,17 @@ static int hostapd_setup_interface_complete_sync(struct hostapd_iface *iface, iface->conf->channel, iface->freq); #ifdef NEED_AP_MLME - /* Handle DFS only if it is not offloaded to the driver */ - if (!(iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD)) { + if (iface->assisted_dfs_go) { + if (!(iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD)) { + wpa_printf(MSG_DEBUG, + "Fail: Offload not supported for assisted DFS P2P GO"); + goto fail; + } + // FIXME: Check with shivani if this is correct or not + wpa_printf(MSG_DEBUG, + "Request for Assisted DFS P2P GO"); + } else if (!(iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD)) { + /* Handle DFS only if it is not offloaded to the driver */ /* Check DFS */ res = hostapd_handle_dfs(iface); if (res <= 0) { @@ -2643,7 +2652,7 @@ static int hostapd_setup_interface_complete_sync(struct hostapd_iface *iface, } if ((iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) && - !res_dfs_offload) { + !res_dfs_offload && !iface->assisted_dfs_go) { /* * If freq is DFS, and DFS is offloaded to the driver, then wait * for CAC to complete. diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h index dcf395c..66239dc 100644 --- a/src/ap/hostapd.h +++ b/src/ap/hostapd.h @@ -711,6 +711,9 @@ struct hostapd_iface { bool is_no_ir; bool is_ch_switch_dfs; /* Channel switch from ACS to DFS */ + + /* P2P GO in assisted DFS mode */ + bool assisted_dfs_go; }; /* hostapd.c */ diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c index c455660..23b193b 100644 --- a/src/ap/hw_features.c +++ b/src/ap/hw_features.c @@ -142,7 +142,8 @@ int hostapd_get_hw_features(struct hostapd_iface *iface) } else if (((feature->channels[j].flag & HOSTAPD_CHAN_RADAR) && !(iface->drv_flags & - WPA_DRIVER_FLAGS_DFS_OFFLOAD)) || + WPA_DRIVER_FLAGS_DFS_OFFLOAD) && + !iface->assisted_dfs_go) || (feature->channels[j].flag & HOSTAPD_CHAN_NO_IR)) { feature->channels[j].flag |= diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c index 71a812c..fb8bebc 100644 --- a/src/common/ieee802_11_common.c +++ b/src/common/ieee802_11_common.c @@ -2049,7 +2049,7 @@ int ieee80211_is_dfs(int freq, const struct hostapd_hw_modes *modes, */ int is_dfs_global_op_class(u8 op_class) { - return (op_class >= 118) && (op_class <= 123); + return (op_class >= 118) && (op_class <= 130); } @@ -2405,12 +2405,12 @@ const struct oper_class_map global_op_class[] = { { HOSTAPD_MODE_IEEE80211A, 115, 36, 48, 4, BW20, P2P_SUPP }, { HOSTAPD_MODE_IEEE80211A, 116, 36, 44, 8, BW40PLUS, P2P_SUPP }, { HOSTAPD_MODE_IEEE80211A, 117, 40, 48, 8, BW40MINUS, P2P_SUPP }, - { HOSTAPD_MODE_IEEE80211A, 118, 52, 64, 4, BW20, NO_P2P_SUPP }, - { HOSTAPD_MODE_IEEE80211A, 119, 52, 60, 8, BW40PLUS, NO_P2P_SUPP }, - { HOSTAPD_MODE_IEEE80211A, 120, 56, 64, 8, BW40MINUS, NO_P2P_SUPP }, - { HOSTAPD_MODE_IEEE80211A, 121, 100, 144, 4, BW20, NO_P2P_SUPP }, - { HOSTAPD_MODE_IEEE80211A, 122, 100, 140, 8, BW40PLUS, NO_P2P_SUPP }, - { HOSTAPD_MODE_IEEE80211A, 123, 104, 144, 8, BW40MINUS, NO_P2P_SUPP }, + { HOSTAPD_MODE_IEEE80211A, 118, 52, 64, 4, BW20, P2P_SUPP }, + { HOSTAPD_MODE_IEEE80211A, 119, 52, 60, 8, BW40PLUS, P2P_SUPP }, + { HOSTAPD_MODE_IEEE80211A, 120, 56, 64, 8, BW40MINUS, P2P_SUPP }, + { HOSTAPD_MODE_IEEE80211A, 121, 100, 144, 4, BW20, P2P_SUPP }, + { HOSTAPD_MODE_IEEE80211A, 122, 100, 140, 8, BW40PLUS, P2P_SUPP }, + { HOSTAPD_MODE_IEEE80211A, 123, 104, 144, 8, BW40MINUS, P2P_SUPP }, { HOSTAPD_MODE_IEEE80211A, 124, 149, 161, 4, BW20, P2P_SUPP }, { HOSTAPD_MODE_IEEE80211A, 125, 149, 177, 4, BW20, P2P_SUPP }, { HOSTAPD_MODE_IEEE80211A, 126, 149, 173, 8, BW40PLUS, P2P_SUPP }, diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h index 7e3233d..90b3fdc 100644 --- a/src/common/ieee802_11_defs.h +++ b/src/common/ieee802_11_defs.h @@ -1746,6 +1746,7 @@ enum p2p_attr_id { P2P_ATTR_FEATURE_CAPABILITY = 27, P2P_ATTR_PERSISTENT_GROUP = 28, P2P_ATTR_CAPABILITY_EXTENSION = 29, + P2P_ATTR_WLAN_AP_INFORMATION = 30, P2P_ATTR_DEVICE_IDENTITY_KEY = 31, P2P_ATTR_DEVICE_IDENTITY_RESOLUTION = 32, P2P_ATTR_PAIRING_AND_BOOTSTRAPPING = 33, @@ -3098,6 +3099,14 @@ struct ieee80211_s1g_beacon_compat { le32 tsf_completion; } STRUCT_PACKED; +struct ieee80211_dfs_ap_info_list { + u8 flag; + u8 bssid[ETH_ALEN]; + u8 country[3]; + u8 op_class; + u8 op_chan; +}; + #ifdef _MSC_VER #pragma pack(pop) #endif /* _MSC_VER */ diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c index a609dca..946cccd 100644 --- a/src/p2p/p2p.c +++ b/src/p2p/p2p.c @@ -1427,7 +1427,15 @@ static int p2p_prepare_channel_pref(struct p2p_data *p2p, p2p_dbg(p2p, "Prepare channel pref - force_freq=%u pref_freq=%u go=%d", force_freq, pref_freq, go); - if (p2p_freq_to_channel(freq, &op_class, &op_channel) < 0) { + + if (p2p->cfg->is_p2p_dfs_chan && + p2p->cfg->is_p2p_dfs_chan(p2p->cfg->cb_ctx, freq, 0, 0)) { + if (ieee80211_freq_to_channel_ext(freq, 0, CONF_OPER_CHWIDTH_80MHZ, + &op_class, &op_channel) == NUM_HOSTAPD_MODES) { + p2p_dbg(p2p, "Unsupported frequency %u MHz", freq); + return -1; + } + } else if (p2p_freq_to_channel(freq, &op_class, &op_channel) < 0) { p2p_dbg(p2p, "Unsupported frequency %u MHz", freq); return -1; } @@ -1566,6 +1574,8 @@ static void p2p_prepare_channel_best(struct p2p_data *p2p) int p2p_prepare_channel(struct p2p_data *p2p, struct p2p_device *dev, unsigned int force_freq, unsigned int pref_freq, int go) { + struct p2p_channels p2p_chanlist; + p2p_dbg(p2p, "Prepare channel - force_freq=%u pref_freq=%u go=%d", force_freq, pref_freq, go); if (force_freq || pref_freq) { @@ -1575,6 +1585,18 @@ int p2p_prepare_channel(struct p2p_data *p2p, struct p2p_device *dev, } else { p2p_prepare_channel_best(p2p); } + + if (p2p->cfg->is_p2p_dfs_chan && + p2p->cfg->is_p2p_dfs_chan(p2p->cfg->cb_ctx, 0, + p2p->op_reg_class, p2p->op_channel)) { + p2p_dfs_channel_filter(p2p, &p2p->channels, p2p->dfs_ap_list, + p2p->num_dfs_ap, &p2p_chanlist); + p2p_channels_dump(p2p, "channel list after filtering DFS " + " channels with WLAN AP info attr channles", + &p2p_chanlist); + p2p_copy_channels(&p2p->channels, &p2p_chanlist, p2p->allow_6ghz); + } + p2p_channels_dump(p2p, "prepared channels", &p2p->channels); if (go) p2p_channels_remove_freqs(&p2p->channels, &p2p->no_go_freq); @@ -2777,6 +2799,20 @@ int p2p_assoc_req_ie(struct p2p_data *p2p, const u8 *bssid, u8 *buf, p2p_buf_add_device_info(tmp, p2p, peer); p2p_buf_update_ie_hdr(tmp, lpos); + if (p2p->cfg->is_p2p_dfs_chan && + p2p->cfg->is_p2p_dfs_chan(p2p->cfg->cb_ctx, 0, p2p->op_reg_class, + p2p->op_channel) && + !is_p2p_dfs_owner(p2p)) { + struct wpabuf *p2p2_ie; + + p2p2_ie = wpabuf_alloc(255); + if (!p2p2_ie) + return -1; + + p2p_group_build_p2p2_ie(p2p, p2p2_ie, 0); + tmp = wpabuf_concat(p2p2_ie, tmp); + } + tmplen = wpabuf_len(tmp); if (tmplen > len) res = -1; @@ -3043,6 +3079,84 @@ bool is_p2p_6ghz_disabled(struct p2p_data *p2p) return false; } + +bool is_p2p_dfs_chan_enabled(struct p2p_data *p2p) +{ + if (p2p) + return p2p->cfg->dfs_chan_enable; + return false; +} + + +bool is_p2p_dfs_owner(struct p2p_data *p2p) +{ + if (p2p) + return p2p->cfg->dfs_owner; + return false; +} + + +void p2p_remove_wlan_ap_info(struct p2p_data *p2p, u8 val) +{ + p2p->cfg->remove_wlan_ap_info = val; +} + + +struct ieee80211_dfs_ap_info_list * p2p_dfs_get_ap_info(struct p2p_data *p2p, + const u8 *bssid) +{ + size_t i; + + if (!p2p->dfs_ap_list) + return NULL; + + for (i = 0; i < p2p->num_dfs_ap; i++) { + struct ieee80211_dfs_ap_info_list *dfs_ap = + &p2p->dfs_ap_list[i]; + if (ether_addr_equal(dfs_ap->bssid, bssid)) + return dfs_ap; + } + return NULL; +} + + +void p2p_update_dfs_ap_info(struct p2p_data *p2p, const u8 *bssid, int freq, + int flag) +{ + struct ieee80211_dfs_ap_info_list *dfs_ap; + + dfs_ap = p2p_dfs_get_ap_info(p2p, bssid); + + if (dfs_ap) { + wpa_printf(MSG_DEBUG, "Update the existing DFS AP info"); + } else { + dfs_ap = os_realloc_array(p2p->dfs_ap_list, p2p->num_dfs_ap + 1, + sizeof(struct ieee80211_dfs_ap_info_list)); + if (!dfs_ap) { + wpa_printf(MSG_DEBUG, "Unable to allocate dfs_ap memory"); + return; + } + + p2p->dfs_ap_list = dfs_ap; + dfs_ap = &p2p->dfs_ap_list[p2p->num_dfs_ap]; + p2p->num_dfs_ap++; + os_memset(dfs_ap, 0, sizeof(*dfs_ap)); + } + dfs_ap->flag = flag; + os_memcpy(dfs_ap->bssid, bssid, ETH_ALEN); + + //TO-DO: update country string correctly + dfs_ap->country[0] = 0; + dfs_ap->country[1] = 0; + + dfs_ap->country[2] = 0x04; + ieee80211_freq_to_channel_ext(freq, 0, + CONF_OPER_CHWIDTH_80MHZ, + &dfs_ap->op_class, + &dfs_ap->op_chan); +} + + int p2p_pairing_info_init(struct p2p_data *p2p) { struct p2p_pairing_info *pairing_info; diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h index b52dbe1..4ada7a2 100644 --- a/src/p2p/p2p.h +++ b/src/p2p/p2p.h @@ -696,6 +696,11 @@ struct p2p_config { bool dfs_owner; /** + * dfs_chan_enable - Enable p2p Go to operate on dfs channel + */ + bool dfs_chan_enable; + + /** * twt_power_mgmt - Enable TWT based power mgmt for P2P */ bool twt_power_mgmt; @@ -706,6 +711,10 @@ struct p2p_config { */ u16 comeback_after; + /** + * remove_wlan_ap_info - Flag not to include wlan ap info in frames + */ + u8 remove_wlan_ap_info; /** * cb_ctx - Context to use with callback functions @@ -1313,6 +1322,14 @@ struct p2p_config { int (*pasn_update_extra_ies)(void *ctx, const u8 *peer_addr, bool dira); int (*pasn_parse_encrypted_data)(void *ctx, const u8 *data, size_t len); + + /** + * + * is_p2p_dfs_chan - DFS channel check + * + * To check if a channel is DFS channel or not. + */ + int (*is_p2p_dfs_chan)(void *ctx, int freq, int op_class, int op_chan); }; @@ -2643,4 +2660,9 @@ int p2p_pasn_parse_encrypted_data(struct p2p_data *p2p, const u8 *data, size_t len); int p2p_pasn_auth_tx_status(struct p2p_data *p2p, const u8 *data, size_t data_len, u8 acked, bool verify); +bool is_p2p_dfs_chan_enabled(struct p2p_data *p2p); +bool is_p2p_dfs_owner(struct p2p_data *p2p); +void p2p_remove_wlan_ap_info(struct p2p_data *p2p, u8 val); +void p2p_update_dfs_ap_info(struct p2p_data *p2p, const u8 *bssid, int freq, + int flag); #endif /* P2P_H */ diff --git a/src/p2p/p2p_build.c b/src/p2p/p2p_build.c index 33c90ed..f3e5212 100644 --- a/src/p2p/p2p_build.c +++ b/src/p2p/p2p_build.c @@ -1052,3 +1052,47 @@ struct wpabuf *p2p_encaps_p2p_vendor_ie(struct p2p_data *p2p, return ie; } + +void p2p_buf_add_wlan_ap_info(struct wpabuf *buf, + struct ieee80211_dfs_ap_info_list *dfs_ap_list, + size_t list_size) +{ + u8 *len; + size_t i, size; + + if (!list_size) + return; + + wpabuf_put_u8(buf, P2P_ATTR_WLAN_AP_INFORMATION); + /* IE length to be filled */ + len = wpabuf_put(buf, 2); + + for (i = 0; i < list_size; i++) { + if (dfs_ap_list[i].flag != 1) + continue; + + wpabuf_put_u8(buf, dfs_ap_list[i].flag); + wpabuf_put_data(buf, dfs_ap_list[i].bssid, ETH_ALEN); + wpabuf_put_data(buf, dfs_ap_list[i].country, 3); + wpabuf_put_u8(buf, dfs_ap_list[i].op_class); + wpabuf_put_u8(buf, dfs_ap_list[i].op_chan); + } + + if (list_size > 4) + size = 4; + else + size = list_size; + + for (i = 0; i < size; i++) { + if (dfs_ap_list[i].flag == 1) + continue; + wpabuf_put_u8(buf, dfs_ap_list[i].flag); + wpabuf_put_data(buf, dfs_ap_list[i].bssid, ETH_ALEN); + wpabuf_put_data(buf, dfs_ap_list[i].country, 3); + wpabuf_put_u8(buf, dfs_ap_list[i].op_class); + wpabuf_put_u8(buf, dfs_ap_list[i].op_chan); + } + + /* Update attribute length */ + WPA_PUT_LE16(len, (u8 *)wpabuf_put(buf, 0) - len - 2); +} diff --git a/src/p2p/p2p_go_neg.c b/src/p2p/p2p_go_neg.c index 84f39d2..5a3756c 100644 --- a/src/p2p/p2p_go_neg.c +++ b/src/p2p/p2p_go_neg.c @@ -138,6 +138,7 @@ static const char * p2p_wps_method_str(enum p2p_wps_method wps_method) struct wpabuf * p2p_build_go_neg_req(struct p2p_data *p2p, struct p2p_device *peer) { + u8 *len; u8 group_capab; size_t extra = 0; u16 pw_id; @@ -227,6 +228,15 @@ struct wpabuf * p2p_build_go_neg_req(struct p2p_data *p2p, if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_REQ]) wpabuf_put_buf(buf2, p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_REQ]); + + if (p2p->cfg->is_p2p_dfs_chan && + p2p->cfg->is_p2p_dfs_chan(p2p->cfg->cb_ctx, 0, + p2p->op_reg_class, p2p->op_channel)) { + len = p2p_buf_add_p2p2_ie_hdr(buf2); + p2p_buf_add_wlan_ap_info(buf2, p2p->dfs_ap_list, + p2p->num_dfs_ap); + p2p_buf_update_p2p2_ie_hdr(buf2, len); + } buf = wpabuf_concat(buf2, buf); return buf; @@ -298,6 +308,7 @@ static struct wpabuf * p2p_build_go_neg_resp(struct p2p_data *p2p, u8 dialog_token, u8 status, u8 tie_breaker) { + u8 *len; u8 group_capab; size_t extra = 0; u16 pw_id; @@ -415,6 +426,15 @@ static struct wpabuf * p2p_build_go_neg_resp(struct p2p_data *p2p, if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_RESP]) wpabuf_put_buf(buf2, p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_RESP]); + + if (p2p->cfg->is_p2p_dfs_chan && + p2p->cfg->is_p2p_dfs_chan(p2p->cfg->cb_ctx, 0, + p2p->op_reg_class, p2p->op_channel)) { + len = p2p_buf_add_p2p2_ie_hdr(buf2); + p2p_buf_add_wlan_ap_info(buf2, p2p->dfs_ap_list, + p2p->num_dfs_ap); + p2p_buf_update_p2p2_ie_hdr(buf2, len); + } buf = wpabuf_concat(buf2, buf); return buf; @@ -1089,6 +1109,24 @@ skip: */ p2p_check_pref_chan(p2p, go, dev, &msg); + if (msg.wlan_ap_info) { + u8 *pos = (u8 *)msg.wlan_ap_info, match = 0, i; + if (p2p->cfg->is_p2p_dfs_chan && + p2p->cfg->is_p2p_dfs_chan(p2p->cfg->cb_ctx, 0, + p2p->op_reg_class, + p2p->op_channel)) { + for (i = 0; i < msg.wlan_ap_info_len; i += 12) { + if (*(pos + 10) == p2p->op_reg_class && + *(pos + 11) == p2p->op_channel) { + match = 1; + break; + } + } + if (match == 0) + goto fail; + } + } + if (msg.config_timeout) { dev->go_timeout = msg.config_timeout[0]; dev->client_timeout = msg.config_timeout[1]; @@ -1176,6 +1214,7 @@ static struct wpabuf * p2p_build_go_neg_conf(struct p2p_data *p2p, u8 dialog_token, u8 status, const u8 *resp_chan, int go) { + u8 *len; struct p2p_channels res; u8 group_capab; size_t extra = 0; @@ -1246,6 +1285,15 @@ static struct wpabuf * p2p_build_go_neg_conf(struct p2p_data *p2p, if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_CONF]) wpabuf_put_buf(buf2, p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_CONF]); + if (p2p->cfg->is_p2p_dfs_chan && + p2p->cfg->is_p2p_dfs_chan(p2p->cfg->cb_ctx, 0, + p2p->op_reg_class, p2p->op_channel)) { + len = p2p_buf_add_p2p2_ie_hdr(buf2); + p2p_buf_add_wlan_ap_info(buf2, p2p->dfs_ap_list, + p2p->num_dfs_ap); + p2p_buf_update_p2p2_ie_hdr(buf2, len); + } + buf = wpabuf_concat(buf2, buf); return buf; @@ -1485,6 +1533,26 @@ skip: if (go) p2p_check_pref_chan(p2p, go, dev, &msg); + if (msg.wlan_ap_info) { + u16 match = 0, i; + const u8 *pos = msg.wlan_ap_info; + + if (p2p->cfg->is_p2p_dfs_chan && + p2p->cfg->is_p2p_dfs_chan(p2p->cfg->cb_ctx, 0, + p2p->op_reg_class, + p2p->op_channel)) { + for (i = 0; i < msg.wlan_ap_info_len; i += 12) { + if (*(pos + 10) == p2p->op_reg_class && + *(pos + 11) == p2p->op_channel) { + match = 1; + break; + } + } + if (match == 0) + goto fail; + } + } + p2p_set_state(p2p, P2P_GO_NEG); p2p_clear_timeout(p2p); diff --git a/src/p2p/p2p_group.c b/src/p2p/p2p_group.c index 4822c28..d07f41e 100644 --- a/src/p2p/p2p_group.c +++ b/src/p2p/p2p_group.c @@ -217,6 +217,17 @@ struct wpabuf * p2p_group_build_p2p2_ie(struct p2p_data *p2p, wpabuf_put_be32(p2p2_ie, P2P2_IE_VENDOR_TYPE); wpa_printf(MSG_DEBUG, "P2P: * P2P2 IE header"); p2p_buf_add_pcea(p2p2_ie, p2p); + if (p2p->cfg->remove_wlan_ap_info) + goto out; + + if (p2p->cfg->is_p2p_dfs_chan && + p2p->cfg->is_p2p_dfs_chan(p2p->cfg->cb_ctx, freq, p2p->op_reg_class, + p2p->op_channel) && + !is_p2p_dfs_owner(p2p)) { + p2p_buf_add_wlan_ap_info(p2p2_ie, p2p->dfs_ap_list, + p2p->num_dfs_ap); + } +out: *len = (u8 *)wpabuf_put(p2p2_ie, 0) - len - 1; return p2p2_ie; diff --git a/src/p2p/p2p_i.h b/src/p2p/p2p_i.h index 80e1988..2309dc8 100644 --- a/src/p2p/p2p_i.h +++ b/src/p2p/p2p_i.h @@ -698,6 +698,10 @@ struct p2p_data { * Indicate that auto go is enabled for this device */ u8 auto_go; + + /* list of dfs APs */ + struct ieee80211_dfs_ap_info_list *dfs_ap_list; + size_t num_dfs_ap; }; /** @@ -816,6 +820,9 @@ struct p2p_message { const u8 *dira; size_t dira_len; + + const u8 *wlan_ap_info; + size_t wlan_ap_info_len; }; @@ -1086,7 +1093,13 @@ void p2p_pref_channel_filter(const struct p2p_channels *a, void p2p_sd_query_cb(struct p2p_data *p2p, int success); void p2p_pasn_initialize(struct p2p_data *p2p, struct p2p_device *dev, const u8 *addr, int freq); - +void p2p_dfs_channel_filter(struct p2p_data *p2p, + const struct p2p_channels *p2p_chan, + const struct ieee80211_dfs_ap_info_list *ap_list, + size_t num_dfs_ap, struct p2p_channels *res); +void p2p_buf_add_wlan_ap_info(struct wpabuf *buf, + struct ieee80211_dfs_ap_info_list *dfs_ap_list, + size_t list_size); void p2p_dbg(struct p2p_data *p2p, const char *fmt, ...) PRINTF_FORMAT(2, 3); void p2p_info(struct p2p_data *p2p, const char *fmt, ...) diff --git a/src/p2p/p2p_parse.c b/src/p2p/p2p_parse.c index de2a43f..d863b72 100644 --- a/src/p2p/p2p_parse.c +++ b/src/p2p/p2p_parse.c @@ -457,6 +457,15 @@ static int p2p_parse_attribute(u8 id, const u8 *data, u16 len, msg->dira_len = len; wpa_printf(MSG_DEBUG, "P2P: * DIRA (length=%u)", len); break; + case P2P_ATTR_WLAN_AP_INFORMATION: + if (len < 1) { + wpa_printf(MSG_DEBUG, "P2P: Too short WLAN AP info (length %d)", + len); + return -1; + } + msg->wlan_ap_info = data; + msg->wlan_ap_info_len = len; + break; default: wpa_printf(MSG_DEBUG, "P2P: Skipped unknown attribute %d " "(length %d)", id, len); diff --git a/src/p2p/p2p_utils.c b/src/p2p/p2p_utils.c index c1f0084..35cbb16 100644 --- a/src/p2p/p2p_utils.c +++ b/src/p2p/p2p_utils.c @@ -611,3 +611,53 @@ void p2p_pref_channel_filter(const struct p2p_channels *p2p_chan, res_reg->reg_class = reg->reg_class; } } + + +static int +p2p_check_dfs_channel(int channel, u8 op_class, + const struct ieee80211_dfs_ap_info_list *ap_list, + unsigned int num_dfs_ap) +{ + unsigned int i; + + for (i = 0; i < num_dfs_ap; i++) { + if (op_class == ap_list[i].op_class && + channel == ap_list[i].op_chan) + return 0; + } + return -1; +} + + +void p2p_dfs_channel_filter(struct p2p_data *p2p, + const struct p2p_channels *p2p_chan, + const struct ieee80211_dfs_ap_info_list *ap_list, + size_t num_dfs_ap, struct p2p_channels *res) +{ + size_t i, j; + + os_memset(res, 0, sizeof(*res)); + + for (i = 0; i < p2p_chan->reg_classes; i++) { + const struct p2p_reg_class *reg = &p2p_chan->reg_class[i]; + struct p2p_reg_class *res_reg = &res->reg_class[i]; + + for (j = 0; j < reg->channels; j++) { + if (p2p->cfg->is_p2p_dfs_chan(p2p->cfg->cb_ctx, 0, + reg->reg_class, + reg->channel[j]) && + p2p_check_dfs_channel(reg->channel[j], + reg->reg_class, ap_list, + num_dfs_ap) < 0) + continue; + + res_reg->channel[res_reg->channels++] = + reg->channel[j]; + } + + if (res_reg->channels == 0) + continue; + res->reg_classes++; + res_reg->reg_class = reg->reg_class; + } +} diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c index 69a0e5e..9ca266a 100644 --- a/wpa_supplicant/ap.c +++ b/wpa_supplicant/ap.c @@ -1072,6 +1072,7 @@ int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s, hapd_iface->extended_capa_mask = wpa_s->extended_capa_mask; hapd_iface->extended_capa_len = wpa_s->extended_capa_len; hapd_iface->drv_max_acl_mac_addrs = wpa_s->drv_max_acl_mac_addrs; + hapd_iface->assisted_dfs_go = wpa_s->assisted_dfs_go; wpa_s->ap_iface->conf = conf = hostapd_config_defaults(); if (conf == NULL) { diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index 24861c6..db17c3f 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -5486,6 +5486,8 @@ static const struct global_parse_data global_fields[] = { { FUNC(p2p_device_persistent_mac_addr), 0 }, { INT(p2p_interface_random_mac_addr), 0 }, { INT(p2p_6ghz_disable), 0 }, + { INT(p2p_dfs_chan_enable), 0 }, + { INT(p2p_dfs_owner), 0 }, #endif /* CONFIG_P2P */ { FUNC(country), CFG_CHANGED_COUNTRY }, { INT(bss_max_count), 0 }, diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h index 8981305..2dd6b72 100644 --- a/wpa_supplicant/config.h +++ b/wpa_supplicant/config.h @@ -858,6 +858,8 @@ struct wpa_config { int p2p_optimize_listen_chan; int p2p_6ghz_disable; + int p2p_dfs_chan_enable; + int p2p_dfs_owner; struct wpabuf *wps_vendor_ext_m1; diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 3f247a7..76ba48b 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -7748,6 +7748,11 @@ static int p2p_ctrl_set(struct wpa_supplicant *wpa_s, char *cmd) return 0; } + if (os_strcmp(cmd, "remove_wlan_ap_info") == 0) { + p2p_remove_wlan_ap_info(wpa_s->global->p2p, atoi(param)); + return 0; + } + wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown P2P_SET field value '%s'", cmd); diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index a198674..687591e 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -390,6 +390,7 @@ void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s) sme_clear_on_disassoc(wpa_s); wpa_s->current_bss = NULL; wpa_s->assoc_freq = 0; + wpa_s->assisted_dfs_go = 0; if (bssid_changed) wpas_notify_bssid_changed(wpa_s); @@ -2514,6 +2515,7 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s, wpas_notify_scan_done(wpa_s, 1); + wpas_p2p_update_dfs_ap_info_list(wpa_s, scan_res); if (ap) { wpa_dbg(wpa_s, MSG_DEBUG, "Ignore scan results in AP mode"); #ifdef CONFIG_AP @@ -3699,6 +3701,12 @@ no_pfs: } wpa_s->assoc_freq = data->assoc_info.freq; + if (ieee80211_is_dfs(wpa_s->assoc_freq, wpa_s->hw.modes, + wpa_s->hw.num_modes)) { + wpa_s->assisted_dfs_go = 1; + p2p_update_dfs_ap_info(wpa_s->global->p2p, bssid, + wpa_s->assoc_freq, 1); + } #ifndef CONFIG_NO_ROBUST_AV wpas_handle_assoc_resp_qos_mgmt(wpa_s, data->assoc_info.resp_ies, diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index 7283719..d55a439 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -2518,6 +2518,7 @@ wpas_p2p_init_group_interface(struct wpa_supplicant *wpa_s, int go) wpas_p2p_clone_config(group_wpa_s, wpa_s); group_wpa_s->p2p2 = wpa_s->p2p2; + group_wpa_s->assisted_dfs_go = wpa_s->assisted_dfs_go; if (wpa_s->conf->p2p_interface_random_mac_addr) { if (wpa_drv_set_mac_addr(group_wpa_s, @@ -4191,8 +4192,11 @@ static int wpas_p2p_setup_channels(struct wpa_supplicant *wpa_s, const struct oper_class_map *o = &global_op_class[op]; unsigned int ch; struct p2p_reg_class *reg = NULL, *cli_reg = NULL; + bool check_dfs_supported = + (is_p2p_dfs_chan_enabled(wpa_s->global->p2p) && + is_dfs_global_op_class(o->op_class)); - if (o->p2p == NO_P2P_SUPP || + if ((!check_dfs_supported && o->p2p == NO_P2P_SUPP) || (is_6ghz_op_class(o->op_class) && p2p_disable_6ghz)) continue; @@ -4210,10 +4214,11 @@ static int wpas_p2p_setup_channels(struct wpa_supplicant *wpa_s, if ((o->op_class >= 128 && o->op_class <= 130) && ch < 149 && ch + o->inc > 149) ch = 149; - + //FIXME + wpa_s->p2p_go_allow_dfs = 1; res = wpas_p2p_verify_channel(wpa_s, mode, o->op_class, ch, o->bw); - if (res == ALLOWED) { + if (res == ALLOWED || (res == RADAR && check_dfs_supported)) { if (reg == NULL) { if (cla == P2P_MAX_REG_CLASSES) continue; @@ -5347,6 +5352,19 @@ int wpas_p2p_mac_setup(struct wpa_supplicant *wpa_s) } +static int wpas_p2p_dfs_chan(void *ctx, int freq, int op_class, int op_chan) +{ + struct wpa_supplicant *wpa_s = ctx; + + if (freq == 0) + freq = ieee80211_chan_to_freq(NULL, op_class, op_chan); + if (ieee80211_is_dfs(freq, wpa_s->hw.modes, wpa_s->hw.num_modes)) + return 1; + + return 0; +} + + /** * wpas_p2p_init - Initialize P2P module for %wpa_supplicant * @global: Pointer to global data from wpa_supplicant_init() @@ -5415,6 +5433,11 @@ int wpas_p2p_init(struct wpa_global *global, struct wpa_supplicant *wpa_s) p2p.pasn_send_mgmt = wpas_p2p_pasn_send_mlme; p2p.pasn_update_extra_ies = wpas_p2p_pasn_update_extra_ies; p2p.pasn_parse_encrypted_data = wpas_p2p_pasn_parse_encrypted_data; + p2p.is_p2p_dfs_chan = wpas_p2p_dfs_chan; + // FIXME: Dont hardcode dfs_chan_enable +// p2p.dfs_chan_enable = wpa_s->conf->p2p_dfs_chan_enable; + p2p.dfs_chan_enable = 1; + p2p.dfs_owner = wpa_s->conf->p2p_dfs_owner; os_memcpy(wpa_s->global->p2p_dev_addr, wpa_s->own_addr, ETH_ALEN); os_memcpy(p2p.dev_addr, wpa_s->global->p2p_dev_addr, ETH_ALEN); @@ -6328,7 +6351,7 @@ static int wpas_p2p_setup_freqs(struct wpa_supplicant *wpa_s, int freq, else ret = p2p_supported_freq_cli(wpa_s->global->p2p, freq); if (!ret) { - if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) && + if (is_p2p_dfs_chan_enabled(wpa_s->global->p2p) && ieee80211_is_dfs(freq, wpa_s->hw.modes, wpa_s->hw.num_modes)) { /* @@ -10874,3 +10897,24 @@ int wpas_p2p_pasn_auth_rx(struct wpa_supplicant *wpa_s, return -2; return p2p_pasn_auth_rx(p2p, mgmt, len, freq); } + +void wpas_p2p_update_dfs_ap_info_list(struct wpa_supplicant *wpa_s, + struct wpa_scan_results *scan_res) +{ + size_t i; + + for (i = 0; i < scan_res->num; i++) { + if (!ieee80211_is_dfs(scan_res->res[i]->freq, wpa_s->hw.modes, + wpa_s->hw.num_modes)) + continue; + if (scan_res->res[i]->flags & BIT(5)) { + p2p_update_dfs_ap_info(wpa_s->global->p2p, + scan_res->res[i]->bssid, + scan_res->res[i]->freq, 1); + } else { + p2p_update_dfs_ap_info(wpa_s->global->p2p, + scan_res->res[i]->bssid, + scan_res->res[i]->freq, 0); + } + } +} diff --git a/wpa_supplicant/p2p_supplicant.h b/wpa_supplicant/p2p_supplicant.h index 1e5f77a..9156e5a 100644 --- a/wpa_supplicant/p2p_supplicant.h +++ b/wpa_supplicant/p2p_supplicant.h @@ -233,6 +233,8 @@ struct wpabuf * wpas_p2p_usd_elems(struct wpa_supplicant *wpa_s); int wpas_p2p_pasn_auth_rx(struct wpa_supplicant *wpa_s, const struct ieee80211_mgmt *mgmt, size_t len, int freq); +void wpas_p2p_update_dfs_ap_info_list(struct wpa_supplicant *wpa_s, + struct wpa_scan_results *scan_res); #else /* CONFIG_P2P */ static inline int @@ -370,6 +372,11 @@ wpas_p2p_pasn_auth_rx(struct wpa_supplicant *wpa_s, return 0; } +static inline void +wpas_p2p_update_dfs_ap_info_list(struct wpa_supplicant *wpa_s, + struct wpa_scan_results *scan_res) +{ +} #endif /* CONFIG_P2P */ #endif /* P2P_SUPPLICANT_H */ diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 4e87247..ba4b899 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -1601,6 +1601,7 @@ struct wpa_supplicant { bool last_scan_all_chan; bool last_scan_non_coloc_6ghz; bool support_6ghz; + u8 assisted_dfs_go; struct wpa_signal_info last_signal_info;