]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
AP MLD: Use hostapd-based ACL for MLO cases
authorChenming Huang <chenhuan@qti.qualcomm.com>
Fri, 16 May 2025 01:57:27 +0000 (07:27 +0530)
committerJouni Malinen <j@w1.fi>
Thu, 5 Jun 2025 10:05:48 +0000 (13:05 +0300)
Currently NL80211_CMD_SET_MAC_ACL is not supported for MLO cases.
Since this command has no upstream driver support, further extension
might not be accepted and this command itself may be removed in the
future, too.

To support the same ACL setting from hostapd control interface, use
hostapd-based ACL instead when comes to MLO case. In addition, verify
both the link addresses and MLD MAC addresses of the non-AP MLD.

Signed-off-by: Chenming Huang <chenhuan@qti.qualcomm.com>
src/ap/ctrl_iface_ap.c
src/ap/drv_callbacks.c
src/ap/hostapd.c
src/ap/ieee802_11.c

index 441995bcbd2d7ceb56477ad5f99190a40237498d..799aff76597c598da877d5097159614003865354 100644 (file)
@@ -1644,6 +1644,11 @@ int hostapd_disassoc_deny_mac(struct hostapd_data *hapd)
        struct vlan_description vlan_id;
 
        for (sta = hapd->sta_list; sta; sta = sta->next) {
+#ifdef CONFIG_IEEE80211BE
+               int link_id;
+               struct mld_link_info *info;
+#endif /* CONFIG_IEEE80211BE */
+
                if (hostapd_maclist_found(hapd->conf->deny_mac,
                                          hapd->conf->num_deny_mac, sta->addr,
                                          &vlan_id) &&
@@ -1651,6 +1656,24 @@ int hostapd_disassoc_deny_mac(struct hostapd_data *hapd)
                     !vlan_compare(&vlan_id, sta->vlan_desc)))
                        ap_sta_disconnect(hapd, sta, sta->addr,
                                          WLAN_REASON_UNSPECIFIED);
+#ifdef CONFIG_IEEE80211BE
+               for (link_id = 0; hapd->conf->mld_ap &&
+                            link_id < MAX_NUM_MLD_LINKS &&
+                            sta->mld_info.mld_sta; link_id++) {
+                       info = &sta->mld_info.links[link_id];
+                       if (!info->valid || link_id != hapd->mld_link_id)
+                               continue;
+
+                       if (hostapd_maclist_found(hapd->conf->deny_mac,
+                                                 hapd->conf->num_deny_mac,
+                                                 info->peer_addr,
+                                                 &vlan_id) &&
+                           (!vlan_id.notempty ||
+                            !vlan_compare(&vlan_id, sta->vlan_desc)))
+                               ap_sta_disconnect(hapd, sta, sta->addr,
+                                                 WLAN_REASON_UNSPECIFIED);
+               }
+#endif /* CONFIG_IEEE80211BE */
        }
 
        return 0;
index f3aeb2236617785f32c4b3f8a080c14bf590100b..b54bb4f9e3c256ab9471a0acf0005d02455117d5 100644 (file)
@@ -330,6 +330,7 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
        struct hostapd_iface *iface = hapd->iface;
 #endif /* CONFIG_OWE */
        bool updated = false;
+       bool driver_acl;
 
        if (addr == NULL) {
                /*
@@ -460,13 +461,56 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
         * ACL if the driver supports ACL offload to avoid potentially
         * conflicting ACL rules.
         */
-       if (hapd->iface->drv_max_acl_mac_addrs == 0 &&
+       driver_acl = hapd->iface->drv_max_acl_mac_addrs > 0;
+#ifdef CONFIG_IEEE80211BE
+       if (hapd->conf->mld_ap)
+               driver_acl = false;
+#endif /* CONFIG_IEEE80211BE */
+       if (!driver_acl &&
            hostapd_check_acl(hapd, addr, NULL) != HOSTAPD_ACL_ACCEPT) {
                wpa_printf(MSG_INFO, "STA " MACSTR " not allowed to connect",
                           MAC2STR(addr));
                reason = WLAN_REASON_UNSPECIFIED;
                goto fail;
        }
+#ifdef CONFIG_IEEE80211BE
+       /*
+        * The idea is that ACL is per link. For MLO associations, check
+        * whether peer MLD MAC address is acceptable in all requested links.
+        * For each peer link address, check the corresponding association
+        * local link's ACL configuration whether it is acceptable.
+        */
+       if (!driver_acl && hapd->conf->mld_ap && link_addr) {
+               int link_id;
+               struct mld_link_info *info;
+               struct hostapd_data *bss;
+
+               for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
+                       info = &sta->mld_info.links[link_id];
+                       if (!info->valid)
+                               continue;
+
+                       bss = hostapd_mld_get_link_bss(hapd, link_id);
+                       if (bss != hapd &&
+                           hostapd_check_acl(bss, addr, NULL) !=
+                           HOSTAPD_ACL_ACCEPT) {
+                               wpa_printf(MSG_INFO, "STA " MACSTR
+                                          " not allowed to connect",
+                                          MAC2STR(addr));
+                               reason = WLAN_REASON_UNSPECIFIED;
+                               goto fail;
+                       }
+                       if (hostapd_check_acl(bss, info->peer_addr, NULL) !=
+                           HOSTAPD_ACL_ACCEPT) {
+                               wpa_printf(MSG_INFO, "link addr" MACSTR
+                                          " not allowed to connect",
+                                          MAC2STR(info->peer_addr));
+                               reason = WLAN_REASON_UNSPECIFIED;
+                               goto fail;
+                       }
+               }
+       }
+#endif /* CONFIG_IEEE80211BE */
 
 #ifdef CONFIG_P2P
        if (elems.p2p) {
index 7f2ebecb87647ebb6a2ece8b674245ba55713e62..0dd2b89bb88bb3d9d26eaae0e3364ab77ceda05f 100644 (file)
@@ -1809,6 +1809,14 @@ int hostapd_set_acl(struct hostapd_data *hapd)
        if (hapd->iface->drv_max_acl_mac_addrs == 0)
                return 0;
 
+#ifdef CONFIG_IEEE80211BE
+       if (hapd->conf->mld_ap) {
+               wpa_printf(MSG_DEBUG,
+                          "Kernel doesn't support offloaded ACL for AP MLD. Use hostapd based ACL instead.");
+               return 0;
+       }
+#endif /* CONFIG_IEEE80211BE */
+
        if (conf->macaddr_acl == DENY_UNLESS_ACCEPTED) {
                accept_acl = 1;
                err = hostapd_set_acl_list(hapd, conf->accept_mac,
index 53c32b0efee0195348add0790f792d600c9f2d96..bf36d7f9e3cf493f6982fbeb493f62638f54738d 100644 (file)
@@ -3301,6 +3301,23 @@ static void handle_auth(struct hostapd_data *hapd,
        if (res == HOSTAPD_ACL_PENDING)
                return;
 
+#ifdef CONFIG_IEEE80211BE
+       if (mld_sta) {
+               res = ieee802_11_allowed_address(hapd, mgmt->sa,
+                                                (const u8 *) mgmt, len,
+                                                &rad_info);
+               if (res == HOSTAPD_ACL_REJECT) {
+                       wpa_msg(hapd->msg_ctx, MSG_DEBUG,
+                               "Ignore Authentication frame from " MACSTR
+                               " due to ACL reject", MAC2STR(mgmt->sa));
+                       resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
+                       goto fail;
+               }
+               if (res == HOSTAPD_ACL_PENDING)
+                       return;
+       }
+#endif /* CONFIG_IEEE80211BE */
+
 #ifdef CONFIG_SAE
        if (auth_alg == WLAN_AUTH_SAE && !from_queue &&
            (auth_transaction == 1 ||