summaryrefslogtreecommitdiff
path: root/net/mac80211
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2026-07-24 16:21:27 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2026-07-24 16:21:27 +0200
commit8f9aa2c90530ab92301a82231ae44f3722becd93 (patch)
treefb282e955b0a880b07131a135257fe3ec764e928 /net/mac80211
parent93467b31bec6da512b51544e5e4584f2745e995e (diff)
parent155b42bec9cbb6b8cdc47dd9bd09503a81fbe493 (diff)
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/main.c3
-rw-r--r--net/mac80211/rx.c34
-rw-r--r--net/mac80211/tx.c17
-rw-r--r--net/mac80211/util.c3
4 files changed, 53 insertions, 4 deletions
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index f47dd58770ad..dba66dd964af 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -1599,7 +1599,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
sband = kmemdup(sband, sizeof(*sband), GFP_KERNEL);
if (!sband) {
result = -ENOMEM;
- goto fail_rate;
+ goto fail_band;
}
wiphy_dbg(hw->wiphy, "copying sband (band %d) due to VHT EXT NSS BW flag\n",
@@ -1675,6 +1675,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
#endif
wiphy_unregister(local->hw.wiphy);
fail_wiphy_register:
+ fail_band:
rtnl_lock();
rate_control_deinitialize(local);
ieee80211_remove_interfaces(local);
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 3fb40449c6c5..fe583636d326 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1526,6 +1526,9 @@ ieee80211_rx_h_check_dup(struct ieee80211_rx_data *rx)
if (status->flag & RX_FLAG_DUP_VALIDATED)
return RX_CONTINUE;
+ if (ieee80211_is_ext(hdr->frame_control))
+ return RX_CONTINUE;
+
/*
* Drop duplicate 802.11 retransmissions
* (IEEE 802.11-2012: 9.3.2.10 "Duplicate detection and recovery")
@@ -4487,12 +4490,16 @@ static bool ieee80211_accept_frame(struct ieee80211_rx_data *rx)
struct ieee80211_hdr *hdr = (void *)skb->data;
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
u8 *bssid = ieee80211_get_bssid(hdr, skb->len, sdata->vif.type);
- bool multicast = is_multicast_ether_addr(hdr->addr1) ||
- ieee80211_is_s1g_beacon(hdr->frame_control);
+ bool multicast;
static const u8 nan_network_id[ETH_ALEN] __aligned(2) = {
0x51, 0x6F, 0x9A, 0x01, 0x00, 0x00
};
+ if (ieee80211_is_s1g_beacon(hdr->frame_control))
+ return sdata->vif.type == NL80211_IFTYPE_STATION && bssid;
+
+ multicast = is_multicast_ether_addr(hdr->addr1);
+
switch (sdata->vif.type) {
case NL80211_IFTYPE_STATION:
if (!bssid && !sdata->u.mgd.use_4addr)
@@ -5174,6 +5181,11 @@ static bool ieee80211_prepare_and_rx_handle(struct ieee80211_rx_data *rx,
hdr = (struct ieee80211_hdr *)rx->skb->data;
}
+ if (ieee80211_is_s1g_beacon(hdr->frame_control)) {
+ ieee80211_invoke_rx_handlers(rx);
+ return true;
+ }
+
/* Store a copy of the pre-translated link addresses for SW crypto */
if (unlikely(is_unicast_ether_addr(hdr->addr1) &&
!ieee80211_is_data(hdr->frame_control)))
@@ -5263,6 +5275,13 @@ static bool ieee80211_rx_for_interface(struct ieee80211_rx_data *rx,
struct sta_info *sta;
int link_id = -1;
+ if (ieee80211_is_s1g_beacon(hdr->frame_control)) {
+ if (!ieee80211_rx_data_set_sta(rx, NULL, -1))
+ return false;
+
+ return ieee80211_prepare_and_rx_handle(rx, skb, consume);
+ }
+
/*
* Look up link station first, in case there's a
* chance that they might have a link address that
@@ -5338,6 +5357,17 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
err = -ENOBUFS;
else
err = skb_linearize(skb);
+ } else if (ieee80211_is_s1g_beacon(fc)) {
+ size_t s1g_hdr_len = offsetof(struct ieee80211_ext,
+ u.s1g_beacon.variable) +
+ ieee80211_s1g_optional_len(fc);
+
+ if (skb->len < s1g_hdr_len)
+ err = -ENOBUFS;
+ else
+ err = skb_linearize(skb);
+ } else if (ieee80211_is_ext(fc)) {
+ err = -EINVAL;
} else {
err = !pskb_may_pull(skb, ieee80211_hdrlen(fc));
}
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index ea7f63e1fc17..8e7f43ee10e5 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -2597,6 +2597,18 @@ static u16 ieee80211_store_ack_skb(struct ieee80211_local *local,
return info_id;
}
+static void ieee80211_remove_ack_skb(struct ieee80211_local *local, u16 info_id)
+{
+ struct sk_buff *ack_skb;
+ unsigned long flags;
+
+ spin_lock_irqsave(&local->ack_status_lock, flags);
+ ack_skb = idr_remove(&local->ack_status_frames, info_id);
+ spin_unlock_irqrestore(&local->ack_status_lock, flags);
+
+ kfree_skb(ack_skb);
+}
+
/**
* ieee80211_build_hdr - build 802.11 header in the given frame
* @sdata: virtual interface to build the header for
@@ -2972,7 +2984,8 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
if (ieee80211_skb_resize(sdata, skb, head_need, ENCRYPT_DATA)) {
ieee80211_free_txskb(&local->hw, skb);
skb = NULL;
- return ERR_PTR(-ENOMEM);
+ ret = -ENOMEM;
+ goto free;
}
}
@@ -3040,6 +3053,8 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
return skb;
free:
+ if (info_id)
+ ieee80211_remove_ack_skb(local, info_id);
kfree_skb(skb);
return ERR_PTR(ret);
}
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 2529b01e2cd5..5bc719222a87 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -73,6 +73,9 @@ u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len,
if (ieee80211_is_s1g_beacon(fc)) {
struct ieee80211_ext *ext = (void *) hdr;
+ if (len < offsetofend(struct ieee80211_ext, u.s1g_beacon.sa))
+ return NULL;
+
return ext->u.s1g_beacon.sa;
}