From patchwork Tue Apr 23 05:31:24 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aditya Kumar Singh X-Patchwork-Id: 1926364 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=hqIjUV5q; dkim=fail reason="signature verification failed" (2048-bit key; secure) header.d=infradead.org header.i=@infradead.org header.a=rsa-sha256 header.s=desiato.20200630 header.b=YFaT0bwv; 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=OG1N6+Qr; 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 4VNrPg2sD5z1yZP for ; Tue, 23 Apr 2024 15:33:27 +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=ndzIDURMS/whrqt9Z5JVq7/6iB57jWuycBP6y+HUGdc=; b=hqIjUV5qQF29bp bvAMHwWl2yoIVNTLbzxRDJwnp/hX/zYV7XFrA22qwkMfcGuvcUdwuWl2aYvtTHaEuVCB2EhNNt62y Zk4j5/NUQj3WdSu64IxukwCM6X+y0wzZzGn3kobBigX0pQGRn03lhLyfmEZOqPr6IQzsc6Dpgmbni yv/Vmj4DEbV7mMsKXmiVr9VaWRgUeVAX8sw8yGsXlfgsmwmp0kK3orXHQMrT03S+kUwySeEvx63Xd HFV4QCkuuniB4el/TzZAYQCljITkZf2/jyIMmB1n4x28TdoJ7nqTSoPDui5EBjQOHYp2YK4IF5U45 PIZsABtGxt04roVGrZqQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1rz8mC-0000000G2hP-3snX; Tue, 23 Apr 2024 05:33:08 +0000 Received: from desiato.infradead.org ([2001:8b0:10b:1:d65d:64ff:fe57:4e05]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1rz8mA-0000000G2fo-2A2M for hostap@bombadil.infradead.org; Tue, 23 Apr 2024 05:33:06 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=desiato.20200630; h=Content-Type:Content-Transfer-Encoding :MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From: Sender:Reply-To:Content-ID:Content-Description; bh=udiu4BEPRmAh80N3XtpbTPiPYKII8+NhynTgsLg2+6M=; b=YFaT0bwvpnoEPCvxR+yRPOo8N9 S0+uEmqGiiEHUX0imwDYwwyr2n4R7ARi5uEC9ra7sCbMX/AiJvKcTPHSB3lA7YzSahwsi6gqWojy4 z0IAz7XNIUU48yFMJb6cYZEK7R9M2y0lJl1i1HU79yzt/SeewLvXjaxzsRS9VVDJ8O+zcgqqyINth ARVyHbKznQl3El2mNCgnR3EUZ4JVGF0iRDp4LChIFpjmhGBfBba6a2uvS0jbAt494sOQ9sB8BxcI1 JDMyQAs8Hj46uQaHKUvrrjIEfx/T6AOTWl7WYb9HfDvH6UpPf943+jMhRzP0ImY+aHr4PO3EotaJm XbSt1rsQ==; Received: from mx0b-0031df01.pphosted.com ([205.220.180.131]) by desiato.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1rz8m4-0000000Dv8B-0qwK for hostap@lists.infradead.org; Tue, 23 Apr 2024 05:33:04 +0000 Received: from pps.filterd (m0279870.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 43N5Fpwk025476 for ; Tue, 23 Apr 2024 05:31:48 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding:content-type; s= qcppdkim1; bh=udiu4BEPRmAh80N3XtpbTPiPYKII8+NhynTgsLg2+6M=; b=OG 1N6+Qru58RIAIjk9g5tv2/tq+boICR8Z0Ybl66NjCkLJLXRbdXVO1bDqbgWYgNLy UrErui6VSKc3DvdVboHQaEh8ycqzuFDMW8F+DXXHIGZ/ldQhW5WFRt1SFJgNfJyh Z+RUMYcLHoHIjGWrR+mkosHk+afthqixhDqJ4daoiATmxyyLA05nXL4ysY1YJYeT zwt2N/lJLY1MONYsOGpZwEtcC6ZPHkxEuabMdZK6dMb3QxVOTOZ7BUOkSvZdz2n1 vzeTx+TuiLpJa3cFN2Gc/YZYp3BAfVV8zSmDMhS+oPiiN96XOeZUhX+IM+7N14Cu +uyL9WS87AndvlSBAi4w== Received: from nalasppmta04.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 3xp3a5rbu9-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Tue, 23 Apr 2024 05:31:48 +0000 (GMT) Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com [10.47.209.196]) by NALASPPMTA04.qualcomm.com (8.17.1.5/8.17.1.5) with ESMTPS id 43N5Vl4c005003 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Tue, 23 Apr 2024 05:31:47 GMT Received: from hu-adisi-blr.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; Mon, 22 Apr 2024 22:31:46 -0700 From: Aditya Kumar Singh To: CC: Aditya Kumar Singh Subject: [PATCH 2/6] ctrl_iface: MLO: introduce MLD level socket Date: Tue, 23 Apr 2024 11:01:24 +0530 Message-ID: <20240423053128.129322-3-quic_adisi@quicinc.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240423053128.129322-1-quic_adisi@quicinc.com> References: <20240423053128.129322-1-quic_adisi@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: LcCtgkW1Jf99gaWjBMg6QTzSO25dhd2e X-Proofpoint-ORIG-GUID: LcCtgkW1Jf99gaWjBMg6QTzSO25dhd2e X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1011,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2024-04-23_03,2024-04-22_01,2023-05-22_02 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 suspectscore=0 malwarescore=0 impostorscore=0 mlxscore=0 spamscore=0 clxscore=1015 phishscore=0 lowpriorityscore=0 mlxlogscore=999 bulkscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2404010003 definitions=main-2404230012 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240423_063301_720836_85B5A4E3 X-CRM114-Status: GOOD ( 25.15 ) X-Spam-Score: -0.2 (/) X-Spam-Report: Spam detection software, running on the system "desiato.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: With MLO, each link have socket created with "_link" under the control interface directory. Introduce a MLD level socket - "" as well under the same control interface directory. This socket can be used to pass the command to its partner links directly instead of using the link level [...] Content analysis details: (-0.2 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 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 With MLO, each link have socket created with "_link" under the control interface directory. Introduce a MLD level socket - "" as well under the same control interface directory. This socket can be used to pass the command to its partner links directly instead of using the link level socket. Link ID needs to be passed with the command. The structure of the command is - " LINKID " Directory looks something like this - $ ls /var/run/hostapd/ wlan0 wlan0_link0 wlan0_link1 wlan0 here is the MLD level socket. Rest are each link level. This would also help to maintain backwards compatibility with applications which looks for under the control interface directory.` Signed-off-by: Aditya Kumar Singh --- hostapd/ctrl_iface.c | 335 +++++++++++++++++++++++++++++++++++++++++++ hostapd/ctrl_iface.h | 4 + hostapd/main.c | 5 + src/ap/hostapd.c | 11 ++ src/ap/hostapd.h | 6 + 5 files changed, 361 insertions(+) diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c index d4bb8a055ef2..4654766b4014 100644 --- a/hostapd/ctrl_iface.c +++ b/hostapd/ctrl_iface.c @@ -4569,6 +4569,341 @@ done: } +#ifdef CONFIG_IEEE80211BE +#ifndef CONFIG_CTRL_IFACE_UDP +static int hostapd_mld_ctrl_iface_attach(struct hostapd_mld *mld, + struct sockaddr_storage *from, + socklen_t fromlen, const char *input) +{ + return ctrl_iface_attach(&mld->ctrl_dst, from, fromlen, input); +} + + +static int hostapd_mld_ctrl_iface_detach(struct hostapd_mld *mld, + struct sockaddr_storage *from, + socklen_t fromlen) +{ + return ctrl_iface_detach(&mld->ctrl_dst, from, fromlen); +} + + +static int hostapd_mld_ctrl_iface_receive_process(struct hostapd_mld *mld, + char *buf, char *reply, + int reply_size, + struct sockaddr_storage *from, + socklen_t fromlen) +{ + struct hostapd_data *link_hapd, *link_itr; + int reply_len, link_id = -1; + char *link_cmd; + bool found = false; + + os_memcpy(reply, "OK\n", 3); + reply_len = 3; + + /* Check if link id is provided in the command or not */ + link_cmd = os_strstr(buf, "LINKID"); + if (link_cmd) { + /* Trim the link id part now */ + *(link_cmd - 1) = '\0'; + + link_cmd += 7; + link_id = atoi(link_cmd); + + if (link_id < 0 || link_id >= 15) { + os_memcpy(reply, "INVALID LINK ID\n", 16); + reply_len = 16; + return reply_len; + } + + link_hapd = mld->fbss; + if (!link_hapd) { + os_memcpy(reply, "NO LINKS ACTIVE\n", 16); + reply_len = 16; + return reply_len; + } + + for_each_mld_link(link_itr, link_hapd) { + if (link_itr->mld_link_id == link_id) { + found = true; + break; + } + } + + if (!found) { + os_memcpy(reply, "FAIL\n", 5); + reply_len = 5; + return reply_len; + } + + link_hapd = link_itr; + } else { + link_hapd = mld->fbss; + } + + if (os_strcmp(buf, "PING") == 0) { + os_memcpy(reply, "PONG\n", 5); + reply_len = 5; + } else if (os_strcmp(buf, "ATTACH") == 0) { + if (hostapd_mld_ctrl_iface_attach(mld, from, fromlen, NULL)) + reply_len = -1; + } else if (os_strncmp(buf, "ATTACH ", 7) == 0) { + if (hostapd_mld_ctrl_iface_attach(mld, from, fromlen, buf + 7)) + reply_len = -1; + } else if (os_strcmp(buf, "DETACH") == 0) { + if (hostapd_mld_ctrl_iface_detach(mld, from, fromlen)) + reply_len = -1; + } else { + if (link_id == -1) + wpa_printf(MSG_DEBUG, "Link ID not provided, using first link BSS (if available)"); + + if (!link_hapd) + reply_len = -1; + else + reply_len = + hostapd_ctrl_iface_receive_process(link_hapd, buf, + reply, reply_size, + from, fromlen); + } + + if (reply_len < 0) { + os_memcpy(reply, "FAIL\n", 5); + reply_len = 5; + } + + return reply_len; +} + + +static void hostapd_mld_ctrl_iface_receive(int sock, void *eloop_ctx, + void *sock_ctx) +{ + struct hostapd_mld *mld = eloop_ctx; + char buf[4096]; + int res; + struct sockaddr_storage from; + socklen_t fromlen = sizeof(from); + char *reply, *pos = buf; + const int reply_size = 4096; + int reply_len; + int level = MSG_DEBUG; + + res = recvfrom(sock, buf, sizeof(buf) - 1, 0, + (struct sockaddr *) &from, &fromlen); + if (res < 0) { + wpa_printf(MSG_ERROR, "recvfrom(mld ctrl_iface): %s", + strerror(errno)); + return; + } + buf[res] = '\0'; + + reply = os_malloc(reply_size); + if (reply == NULL) { + if (sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from, + fromlen) < 0) { + wpa_printf(MSG_DEBUG, "MLD CTRL: sendto failed: %s", + strerror(errno)); + } + return; + } + + if (os_strcmp(pos, "PING") == 0) + level = MSG_EXCESSIVE; + + wpa_hexdump_ascii(level, "RX MLD ctrl_iface", pos, res); + + reply_len = hostapd_mld_ctrl_iface_receive_process(mld, pos, + reply, reply_size, + &from, fromlen); + + if (sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, + fromlen) < 0) { + wpa_printf(MSG_DEBUG, "MLD CTRL: sendto failed: %s", + strerror(errno)); + } + os_free(reply); +} + + +static char * hostapd_mld_ctrl_iface_path(struct hostapd_mld *mld) +{ + char *buf; + size_t len; + + if (!mld->ctrl_interface) + return NULL; + + len = os_strlen(mld->ctrl_interface) + os_strlen(mld->name) + 2; + + buf = os_malloc(len); + if (buf == NULL) + return NULL; + + os_snprintf(buf, len, "%s/%s", mld->ctrl_interface, mld->name); + buf[len - 1] = '\0'; + return buf; +} +#endif /* !CONFIG_CTRL_IFACE_UDP */ + + +int hostapd_mld_ctrl_iface_init(struct hostapd_mld *mld) +{ +#ifndef CONFIG_CTRL_IFACE_UDP + struct sockaddr_un addr; + int s = -1; + char *fname = NULL; + + if (!mld) + return -1; + + if (mld->ctrl_sock > -1) { + wpa_printf(MSG_DEBUG, "MLD %s ctrl_iface already exists!", + mld->name); + return 0; + } + + dl_list_init(&mld->ctrl_dst); + + if (mld->ctrl_interface == NULL) + return 0; + + if (mkdir(mld->ctrl_interface, S_IRWXU | S_IRWXG) < 0) { + if (errno == EEXIST) { + wpa_printf(MSG_DEBUG, "Using existing control " + "interface directory."); + } else { + wpa_printf(MSG_ERROR, "mkdir[ctrl_interface]: %s", + strerror(errno)); + goto fail; + } + } + + if (os_strlen(mld->ctrl_interface) + 1 + + os_strlen(mld->name) >= sizeof(addr.sun_path)) + goto fail; + + s = socket(PF_UNIX, SOCK_DGRAM, 0); + if (s < 0) { + wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno)); + goto fail; + } + + os_memset(&addr, 0, sizeof(addr)); +#ifdef __FreeBSD__ + addr.sun_len = sizeof(addr); +#endif /* __FreeBSD__ */ + addr.sun_family = AF_UNIX; + + fname = hostapd_mld_ctrl_iface_path(mld); + if (fname == NULL) + goto fail; + + os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path)); + + wpa_printf(MSG_DEBUG, "Setting up MLD %s ctrl_iface", mld->name); + + if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { + wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s", + strerror(errno)); + if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { + wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not" + " allow connections - assuming it was left" + "over from forced program termination"); + if (unlink(fname) < 0) { + wpa_printf(MSG_ERROR, + "Could not unlink existing ctrl_iface socket '%s': %s", + fname, strerror(errno)); + goto fail; + } + if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < + 0) { + wpa_printf(MSG_ERROR, + "hostapd-ctrl-iface: bind(PF_UNIX): %s", + strerror(errno)); + goto fail; + } + wpa_printf(MSG_DEBUG, "Successfully replaced leftover " + "ctrl_iface socket '%s'", fname); + } else { + wpa_printf(MSG_INFO, "ctrl_iface exists and seems to " + "be in use - cannot override it"); + wpa_printf(MSG_INFO, "Delete '%s' manually if it is " + "not used anymore", fname); + os_free(fname); + fname = NULL; + goto fail; + } + } + + if (chmod(fname, S_IRWXU | S_IRWXG) < 0) { + wpa_printf(MSG_ERROR, "chmod[ctrl_interface/ifname]: %s", + strerror(errno)); + goto fail; + } + os_free(fname); + + mld->ctrl_sock = s; + + if (eloop_register_read_sock(s, hostapd_mld_ctrl_iface_receive, mld, + NULL) < 0) + return -1; + + return 0; + +fail: + if (s >= 0) + close(s); + if (fname) { + unlink(fname); + os_free(fname); + } + return -1; +#endif /* !CONFIG_CTRL_IFACE_UDP */ + return 0; +} + + +void hostapd_mld_ctrl_iface_deinit(struct hostapd_mld *mld) +{ +#ifndef CONFIG_CTRL_IFACE_UDP + struct wpa_ctrl_dst *dst, *prev; + + if (mld->ctrl_sock > -1) { + char *fname; + eloop_unregister_read_sock(mld->ctrl_sock); + close(mld->ctrl_sock); + mld->ctrl_sock = -1; + + fname = hostapd_mld_ctrl_iface_path(mld); + if (fname) + unlink(fname); + os_free(fname); + + if (mld->ctrl_interface && + rmdir(mld->ctrl_interface) < 0) { + if (errno == ENOTEMPTY) { + wpa_printf(MSG_DEBUG, "MLD Control interface " + "directory not empty - leaving it " + "behind"); + } else { + wpa_printf(MSG_ERROR, + "rmdir[ctrl_interface=%s]: %s", + mld->ctrl_interface, + strerror(errno)); + } + } + } + + dl_list_for_each_safe(dst, prev, &mld->ctrl_dst, struct wpa_ctrl_dst, + list) + os_free(dst); +#endif /* !CONFIG_CTRL_IFACE_UDP */ + + os_free(mld->ctrl_interface); +} +#endif /* CONFIG_IEEE80211BE */ + + #ifndef CONFIG_CTRL_IFACE_UDP static char * hostapd_ctrl_iface_path(struct hostapd_data *hapd) { diff --git a/hostapd/ctrl_iface.h b/hostapd/ctrl_iface.h index 3341a66bdc6c..ec5a95be785c 100644 --- a/hostapd/ctrl_iface.h +++ b/hostapd/ctrl_iface.h @@ -14,6 +14,10 @@ int hostapd_ctrl_iface_init(struct hostapd_data *hapd); void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd); int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface); void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interface); +#ifdef CONFIG_IEEE80211BE +int hostapd_mld_ctrl_iface_init(struct hostapd_mld *mld); +void hostapd_mld_ctrl_iface_deinit(struct hostapd_mld *mld); +#endif /* CONFIG_IEEE80211BE */ #else /* CONFIG_NO_CTRL_IFACE */ static inline int hostapd_ctrl_iface_init(struct hostapd_data *hapd) { diff --git a/hostapd/main.c b/hostapd/main.c index 58cc86a08c1f..a0bca3dd5dd0 100644 --- a/hostapd/main.c +++ b/hostapd/main.c @@ -748,6 +748,7 @@ static void hostapd_global_cleanup_mld(struct hapd_interfaces *interfaces) if (!interfaces->mld[i]) continue; + interfaces->mld_ctrl_iface_deinit(interfaces->mld[i]); os_free(interfaces->mld[i]); interfaces->mld[i] = NULL; } @@ -793,6 +794,10 @@ int main(int argc, char *argv[]) interfaces.global_iface_path = NULL; interfaces.global_iface_name = NULL; interfaces.global_ctrl_sock = -1; +#ifdef CONFIG_IEEE80211BE + interfaces.mld_ctrl_iface_init = hostapd_mld_ctrl_iface_init; + interfaces.mld_ctrl_iface_deinit = hostapd_mld_ctrl_iface_deinit; +#endif /* CONFIG_IEEE80211BE */ dl_list_init(&interfaces.global_ctrl_dst); #ifdef CONFIG_ETH_P_OUI dl_list_init(&interfaces.eth_p_oui); diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c index ebdf445831ab..9cd492752e99 100644 --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c @@ -3060,9 +3060,18 @@ static void hostapd_bss_setup_multi_link(struct hostapd_data *hapd, os_strlcpy(mld->name, conf->iface, sizeof(conf->iface)); dl_list_init(&mld->links); + mld->ctrl_sock = -1; + mld->ctrl_interface = os_strdup(hapd->conf->ctrl_interface); wpa_printf(MSG_DEBUG, "AP MLD %s created", mld->name); + /* + * Initialize MLD control interfaces early to allow external monitoring of + * link setup operations. + */ + if (interfaces->mld_ctrl_iface_init(mld)) + goto fail; + hapd->mld = mld; hostapd_mld_ref_inc(mld); hostapd_bss_alloc_link_id(hapd); @@ -3122,6 +3131,8 @@ static void hostapd_cleanup_unused_mlds(struct hapd_interfaces *interfaces) if (!remove && !forced_remove) continue; + interfaces->mld_ctrl_iface_deinit(mld); + wpa_printf(MSG_DEBUG, "AP MLD %s: Freed%s", mld->name, forced_remove ? " (forced)" : ""); os_free(mld); diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h index 4b87a8b76262..052e8f072255 100644 --- a/src/ap/hostapd.h +++ b/src/ap/hostapd.h @@ -97,6 +97,8 @@ struct hapd_interfaces { #ifdef CONFIG_IEEE80211BE struct hostapd_mld **mld; size_t mld_count; + int (*mld_ctrl_iface_init)(struct hostapd_mld *mld); + void (*mld_ctrl_iface_deinit)(struct hostapd_mld *mld); #endif /* CONFIG_IEEE80211BE */ }; @@ -519,6 +521,10 @@ struct hostapd_mld { struct hostapd_data *fbss; struct dl_list links; /* List head of all affiliated links */ + + int ctrl_sock; + struct dl_list ctrl_dst; + char *ctrl_interface; /* directory for UNIX domain sockets */ }; #define HOSTAPD_MLD_MAX_REF_COUNT 0xFF