mirror of
https://github.com/Ysurac/openmptcprouter.git
synced 2025-02-12 11:21:55 +00:00
Add espressobin 6.1 support
This commit is contained in:
parent
d22681c206
commit
33353bda79
2 changed files with 766 additions and 4 deletions
|
@ -0,0 +1,762 @@
|
|||
From 986e43b19ae9176093da35e0a844e65c8bf9ede7 Mon Sep 17 00:00:00 2001
|
||||
From: Felix Fietkau <nbd@nbd.name>
|
||||
Date: Mon, 13 Feb 2023 11:08:54 +0100
|
||||
Subject: [PATCH] wifi: mac80211: fix receiving A-MSDU frames on mesh
|
||||
interfaces
|
||||
|
||||
The current mac80211 mesh A-MSDU receive path fails to parse A-MSDU packets
|
||||
on mesh interfaces, because it assumes that the Mesh Control field is always
|
||||
directly after the 802.11 header.
|
||||
802.11-2020 9.3.2.2.2 Figure 9-70 shows that the Mesh Control field is
|
||||
actually part of the A-MSDU subframe header.
|
||||
This makes more sense, since it allows packets for multiple different
|
||||
destinations to be included in the same A-MSDU, as long as RA and TID are
|
||||
still the same.
|
||||
Another issue is the fact that the A-MSDU subframe length field was apparently
|
||||
accidentally defined as little-endian in the standard.
|
||||
|
||||
In order to fix this, the mesh forwarding path needs happen at a different
|
||||
point in the receive path.
|
||||
|
||||
ieee80211_data_to_8023_exthdr is changed to ignore the mesh control field
|
||||
and leave it in after the ethernet header. This also affects the source/dest
|
||||
MAC address fields, which now in the case of mesh point to the mesh SA/DA.
|
||||
|
||||
ieee80211_amsdu_to_8023s is changed to deal with the endian difference and
|
||||
to add the Mesh Control length to the subframe length, since it's not covered
|
||||
by the MSDU length field.
|
||||
|
||||
With these changes, the mac80211 will get the same packet structure for
|
||||
converted regular data packets and unpacked A-MSDU subframes.
|
||||
|
||||
The mesh forwarding checks are now only performed after the A-MSDU decap.
|
||||
For locally received packets, the Mesh Control header is stripped away.
|
||||
For forwarded packets, a new 802.11 header gets added.
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
Link: https://lore.kernel.org/r/20230213100855.34315-4-nbd@nbd.name
|
||||
[fix fortify build error]
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
.../wireless/marvell/mwifiex/11n_rxreorder.c | 2 +-
|
||||
include/net/cfg80211.h | 27 +-
|
||||
net/mac80211/rx.c | 350 ++++++++++--------
|
||||
net/wireless/util.c | 120 +++---
|
||||
4 files changed, 297 insertions(+), 202 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c
|
||||
+++ b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c
|
||||
@@ -33,7 +33,7 @@ static int mwifiex_11n_dispatch_amsdu_pk
|
||||
skb_trim(skb, le16_to_cpu(local_rx_pd->rx_pkt_length));
|
||||
|
||||
ieee80211_amsdu_to_8023s(skb, &list, priv->curr_addr,
|
||||
- priv->wdev.iftype, 0, NULL, NULL);
|
||||
+ priv->wdev.iftype, 0, NULL, NULL, false);
|
||||
|
||||
while (!skb_queue_empty(&list)) {
|
||||
struct rx_packet_hdr *rx_hdr;
|
||||
--- a/include/net/cfg80211.h
|
||||
+++ b/include/net/cfg80211.h
|
||||
@@ -6208,11 +6208,36 @@ static inline int ieee80211_data_to_8023
|
||||
* @extra_headroom: The hardware extra headroom for SKBs in the @list.
|
||||
* @check_da: DA to check in the inner ethernet header, or NULL
|
||||
* @check_sa: SA to check in the inner ethernet header, or NULL
|
||||
+ * @mesh_control: A-MSDU subframe header includes the mesh control field
|
||||
*/
|
||||
void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
|
||||
const u8 *addr, enum nl80211_iftype iftype,
|
||||
const unsigned int extra_headroom,
|
||||
- const u8 *check_da, const u8 *check_sa);
|
||||
+ const u8 *check_da, const u8 *check_sa,
|
||||
+ bool mesh_control);
|
||||
+
|
||||
+/**
|
||||
+ * ieee80211_get_8023_tunnel_proto - get RFC1042 or bridge tunnel encap protocol
|
||||
+ *
|
||||
+ * Check for RFC1042 or bridge tunnel header and fetch the encapsulated
|
||||
+ * protocol.
|
||||
+ *
|
||||
+ * @hdr: pointer to the MSDU payload
|
||||
+ * @proto: destination pointer to store the protocol
|
||||
+ * Return: true if encapsulation was found
|
||||
+ */
|
||||
+bool ieee80211_get_8023_tunnel_proto(const void *hdr, __be16 *proto);
|
||||
+
|
||||
+/**
|
||||
+ * ieee80211_strip_8023_mesh_hdr - strip mesh header from converted 802.3 frames
|
||||
+ *
|
||||
+ * Strip the mesh header, which was left in by ieee80211_data_to_8023 as part
|
||||
+ * of the MSDU data. Also move any source/destination addresses from the mesh
|
||||
+ * header to the ethernet header (if present).
|
||||
+ *
|
||||
+ * @skb: The 802.3 frame with embedded mesh header
|
||||
+ */
|
||||
+int ieee80211_strip_8023_mesh_hdr(struct sk_buff *skb);
|
||||
|
||||
/**
|
||||
* cfg80211_classify8021d - determine the 802.1p/1d tag for a data frame
|
||||
--- a/net/mac80211/rx.c
|
||||
+++ b/net/mac80211/rx.c
|
||||
@@ -2720,6 +2720,174 @@ ieee80211_deliver_skb(struct ieee80211_r
|
||||
}
|
||||
}
|
||||
|
||||
+static ieee80211_rx_result
|
||||
+ieee80211_rx_mesh_data(struct ieee80211_sub_if_data *sdata, struct sta_info *sta,
|
||||
+ struct sk_buff *skb)
|
||||
+{
|
||||
+#ifdef CPTCFG_MAC80211_MESH
|
||||
+ struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
|
||||
+ struct ieee80211_local *local = sdata->local;
|
||||
+ uint16_t fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA;
|
||||
+ struct ieee80211_hdr hdr = {
|
||||
+ .frame_control = cpu_to_le16(fc)
|
||||
+ };
|
||||
+ struct ieee80211_hdr *fwd_hdr;
|
||||
+ struct ieee80211s_hdr *mesh_hdr;
|
||||
+ struct ieee80211_tx_info *info;
|
||||
+ struct sk_buff *fwd_skb;
|
||||
+ struct ethhdr *eth;
|
||||
+ bool multicast;
|
||||
+ int tailroom = 0;
|
||||
+ int hdrlen, mesh_hdrlen;
|
||||
+ u8 *qos;
|
||||
+
|
||||
+ if (!ieee80211_vif_is_mesh(&sdata->vif))
|
||||
+ return RX_CONTINUE;
|
||||
+
|
||||
+ if (!pskb_may_pull(skb, sizeof(*eth) + 6))
|
||||
+ return RX_DROP_MONITOR;
|
||||
+
|
||||
+ mesh_hdr = (struct ieee80211s_hdr *)(skb->data + sizeof(*eth));
|
||||
+ mesh_hdrlen = ieee80211_get_mesh_hdrlen(mesh_hdr);
|
||||
+
|
||||
+ if (!pskb_may_pull(skb, sizeof(*eth) + mesh_hdrlen))
|
||||
+ return RX_DROP_MONITOR;
|
||||
+
|
||||
+ eth = (struct ethhdr *)skb->data;
|
||||
+ multicast = is_multicast_ether_addr(eth->h_dest);
|
||||
+
|
||||
+ mesh_hdr = (struct ieee80211s_hdr *)(eth + 1);
|
||||
+ if (!mesh_hdr->ttl)
|
||||
+ return RX_DROP_MONITOR;
|
||||
+
|
||||
+ /* frame is in RMC, don't forward */
|
||||
+ if (is_multicast_ether_addr(eth->h_dest) &&
|
||||
+ mesh_rmc_check(sdata, eth->h_source, mesh_hdr))
|
||||
+ return RX_DROP_MONITOR;
|
||||
+
|
||||
+ /* Frame has reached destination. Don't forward */
|
||||
+ if (ether_addr_equal(sdata->vif.addr, eth->h_dest))
|
||||
+ goto rx_accept;
|
||||
+
|
||||
+ if (!ifmsh->mshcfg.dot11MeshForwarding) {
|
||||
+ if (is_multicast_ether_addr(eth->h_dest))
|
||||
+ goto rx_accept;
|
||||
+
|
||||
+ return RX_DROP_MONITOR;
|
||||
+ }
|
||||
+
|
||||
+ /* forward packet */
|
||||
+ if (sdata->crypto_tx_tailroom_needed_cnt)
|
||||
+ tailroom = IEEE80211_ENCRYPT_TAILROOM;
|
||||
+
|
||||
+ if (!--mesh_hdr->ttl) {
|
||||
+ if (multicast)
|
||||
+ goto rx_accept;
|
||||
+
|
||||
+ IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_ttl);
|
||||
+ return RX_DROP_MONITOR;
|
||||
+ }
|
||||
+
|
||||
+ if (mesh_hdr->flags & MESH_FLAGS_AE) {
|
||||
+ struct mesh_path *mppath;
|
||||
+ char *proxied_addr;
|
||||
+
|
||||
+ if (multicast)
|
||||
+ proxied_addr = mesh_hdr->eaddr1;
|
||||
+ else if ((mesh_hdr->flags & MESH_FLAGS_AE) == MESH_FLAGS_AE_A5_A6)
|
||||
+ /* has_a4 already checked in ieee80211_rx_mesh_check */
|
||||
+ proxied_addr = mesh_hdr->eaddr2;
|
||||
+ else
|
||||
+ return RX_DROP_MONITOR;
|
||||
+
|
||||
+ rcu_read_lock();
|
||||
+ mppath = mpp_path_lookup(sdata, proxied_addr);
|
||||
+ if (!mppath) {
|
||||
+ mpp_path_add(sdata, proxied_addr, eth->h_source);
|
||||
+ } else {
|
||||
+ spin_lock_bh(&mppath->state_lock);
|
||||
+ if (!ether_addr_equal(mppath->mpp, eth->h_source))
|
||||
+ memcpy(mppath->mpp, eth->h_source, ETH_ALEN);
|
||||
+ mppath->exp_time = jiffies;
|
||||
+ spin_unlock_bh(&mppath->state_lock);
|
||||
+ }
|
||||
+ rcu_read_unlock();
|
||||
+ }
|
||||
+
|
||||
+ skb_set_queue_mapping(skb, ieee802_1d_to_ac[skb->priority]);
|
||||
+
|
||||
+ ieee80211_fill_mesh_addresses(&hdr, &hdr.frame_control,
|
||||
+ eth->h_dest, eth->h_source);
|
||||
+ hdrlen = ieee80211_hdrlen(hdr.frame_control);
|
||||
+ if (multicast) {
|
||||
+ int extra_head = sizeof(struct ieee80211_hdr) - sizeof(*eth);
|
||||
+
|
||||
+ fwd_skb = skb_copy_expand(skb, local->tx_headroom + extra_head +
|
||||
+ IEEE80211_ENCRYPT_HEADROOM,
|
||||
+ tailroom, GFP_ATOMIC);
|
||||
+ if (!fwd_skb)
|
||||
+ goto rx_accept;
|
||||
+ } else {
|
||||
+ fwd_skb = skb;
|
||||
+ skb = NULL;
|
||||
+
|
||||
+ if (skb_cow_head(fwd_skb, hdrlen - sizeof(struct ethhdr)))
|
||||
+ return RX_DROP_UNUSABLE;
|
||||
+ }
|
||||
+
|
||||
+ fwd_hdr = skb_push(fwd_skb, hdrlen - sizeof(struct ethhdr));
|
||||
+ memcpy(fwd_hdr, &hdr, hdrlen - 2);
|
||||
+ qos = ieee80211_get_qos_ctl(fwd_hdr);
|
||||
+ qos[0] = qos[1] = 0;
|
||||
+
|
||||
+ skb_reset_mac_header(fwd_skb);
|
||||
+ hdrlen += mesh_hdrlen;
|
||||
+ if (ieee80211_get_8023_tunnel_proto(fwd_skb->data + hdrlen,
|
||||
+ &fwd_skb->protocol))
|
||||
+ hdrlen += ETH_ALEN;
|
||||
+ else
|
||||
+ fwd_skb->protocol = htons(fwd_skb->len - hdrlen);
|
||||
+ skb_set_network_header(fwd_skb, hdrlen);
|
||||
+
|
||||
+ info = IEEE80211_SKB_CB(fwd_skb);
|
||||
+ memset(info, 0, sizeof(*info));
|
||||
+ info->control.flags |= IEEE80211_TX_INTCFL_NEED_TXPROCESSING;
|
||||
+ info->control.vif = &sdata->vif;
|
||||
+ info->control.jiffies = jiffies;
|
||||
+ if (multicast) {
|
||||
+ IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_mcast);
|
||||
+ memcpy(fwd_hdr->addr2, sdata->vif.addr, ETH_ALEN);
|
||||
+ /* update power mode indication when forwarding */
|
||||
+ ieee80211_mps_set_frame_flags(sdata, NULL, fwd_hdr);
|
||||
+ } else if (!mesh_nexthop_lookup(sdata, fwd_skb)) {
|
||||
+ /* mesh power mode flags updated in mesh_nexthop_lookup */
|
||||
+ IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_unicast);
|
||||
+ } else {
|
||||
+ /* unable to resolve next hop */
|
||||
+ if (sta)
|
||||
+ mesh_path_error_tx(sdata, ifmsh->mshcfg.element_ttl,
|
||||
+ hdr.addr3, 0,
|
||||
+ WLAN_REASON_MESH_PATH_NOFORWARD,
|
||||
+ sta->sta.addr);
|
||||
+ IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_no_route);
|
||||
+ kfree_skb(fwd_skb);
|
||||
+ goto rx_accept;
|
||||
+ }
|
||||
+
|
||||
+ IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_frames);
|
||||
+ fwd_skb->dev = sdata->dev;
|
||||
+ ieee80211_add_pending_skb(local, fwd_skb);
|
||||
+
|
||||
+rx_accept:
|
||||
+ if (!skb)
|
||||
+ return RX_QUEUED;
|
||||
+
|
||||
+ ieee80211_strip_8023_mesh_hdr(skb);
|
||||
+#endif
|
||||
+
|
||||
+ return RX_CONTINUE;
|
||||
+}
|
||||
+
|
||||
static ieee80211_rx_result debug_noinline
|
||||
__ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx, u8 data_offset)
|
||||
{
|
||||
@@ -2728,8 +2896,10 @@ __ieee80211_rx_h_amsdu(struct ieee80211_
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
__le16 fc = hdr->frame_control;
|
||||
struct sk_buff_head frame_list;
|
||||
+ static ieee80211_rx_result res;
|
||||
struct ethhdr ethhdr;
|
||||
const u8 *check_da = ethhdr.h_dest, *check_sa = ethhdr.h_source;
|
||||
+ bool mesh = false;
|
||||
|
||||
if (unlikely(ieee80211_has_a4(hdr->frame_control))) {
|
||||
check_da = NULL;
|
||||
@@ -2746,6 +2916,8 @@ __ieee80211_rx_h_amsdu(struct ieee80211_
|
||||
break;
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
check_sa = NULL;
|
||||
+ check_da = NULL;
|
||||
+ mesh = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -2763,17 +2935,29 @@ __ieee80211_rx_h_amsdu(struct ieee80211_
|
||||
ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr,
|
||||
rx->sdata->vif.type,
|
||||
rx->local->hw.extra_tx_headroom,
|
||||
- check_da, check_sa);
|
||||
+ check_da, check_sa, mesh);
|
||||
|
||||
while (!skb_queue_empty(&frame_list)) {
|
||||
rx->skb = __skb_dequeue(&frame_list);
|
||||
|
||||
- if (!ieee80211_frame_allowed(rx, fc)) {
|
||||
- dev_kfree_skb(rx->skb);
|
||||
+ res = ieee80211_rx_mesh_data(rx->sdata, rx->sta, rx->skb);
|
||||
+ switch (res) {
|
||||
+ case RX_QUEUED:
|
||||
continue;
|
||||
+ case RX_CONTINUE:
|
||||
+ break;
|
||||
+ default:
|
||||
+ goto free;
|
||||
}
|
||||
|
||||
+ if (!ieee80211_frame_allowed(rx, fc))
|
||||
+ goto free;
|
||||
+
|
||||
ieee80211_deliver_skb(rx);
|
||||
+ continue;
|
||||
+
|
||||
+free:
|
||||
+ dev_kfree_skb(rx->skb);
|
||||
}
|
||||
|
||||
return RX_QUEUED;
|
||||
@@ -2806,6 +2990,8 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx
|
||||
if (!rx->sdata->u.mgd.use_4addr)
|
||||
return RX_DROP_UNUSABLE;
|
||||
break;
|
||||
+ case NL80211_IFTYPE_MESH_POINT:
|
||||
+ break;
|
||||
default:
|
||||
return RX_DROP_UNUSABLE;
|
||||
}
|
||||
@@ -2834,155 +3020,6 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx
|
||||
return __ieee80211_rx_h_amsdu(rx, 0);
|
||||
}
|
||||
|
||||
-#ifdef CPTCFG_MAC80211_MESH
|
||||
-static ieee80211_rx_result
|
||||
-ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
|
||||
-{
|
||||
- struct ieee80211_hdr *fwd_hdr, *hdr;
|
||||
- struct ieee80211_tx_info *info;
|
||||
- struct ieee80211s_hdr *mesh_hdr;
|
||||
- struct sk_buff *skb = rx->skb, *fwd_skb;
|
||||
- struct ieee80211_local *local = rx->local;
|
||||
- struct ieee80211_sub_if_data *sdata = rx->sdata;
|
||||
- struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
|
||||
- u16 ac, q, hdrlen;
|
||||
- int tailroom = 0;
|
||||
-
|
||||
- hdr = (struct ieee80211_hdr *) skb->data;
|
||||
- hdrlen = ieee80211_hdrlen(hdr->frame_control);
|
||||
-
|
||||
- /* make sure fixed part of mesh header is there, also checks skb len */
|
||||
- if (!pskb_may_pull(rx->skb, hdrlen + 6))
|
||||
- return RX_DROP_MONITOR;
|
||||
-
|
||||
- mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen);
|
||||
-
|
||||
- /* make sure full mesh header is there, also checks skb len */
|
||||
- if (!pskb_may_pull(rx->skb,
|
||||
- hdrlen + ieee80211_get_mesh_hdrlen(mesh_hdr)))
|
||||
- return RX_DROP_MONITOR;
|
||||
-
|
||||
- /* reload pointers */
|
||||
- hdr = (struct ieee80211_hdr *) skb->data;
|
||||
- mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen);
|
||||
-
|
||||
- if (ieee80211_drop_unencrypted(rx, hdr->frame_control)) {
|
||||
- int offset = hdrlen + ieee80211_get_mesh_hdrlen(mesh_hdr) +
|
||||
- sizeof(rfc1042_header);
|
||||
- __be16 ethertype;
|
||||
-
|
||||
- if (!ether_addr_equal(hdr->addr1, rx->sdata->vif.addr) ||
|
||||
- skb_copy_bits(rx->skb, offset, ðertype, 2) != 0 ||
|
||||
- ethertype != rx->sdata->control_port_protocol)
|
||||
- return RX_DROP_MONITOR;
|
||||
- }
|
||||
-
|
||||
- /* frame is in RMC, don't forward */
|
||||
- if (ieee80211_is_data(hdr->frame_control) &&
|
||||
- is_multicast_ether_addr(hdr->addr1) &&
|
||||
- mesh_rmc_check(rx->sdata, hdr->addr3, mesh_hdr))
|
||||
- return RX_DROP_MONITOR;
|
||||
-
|
||||
- if (!ieee80211_is_data(hdr->frame_control))
|
||||
- return RX_CONTINUE;
|
||||
-
|
||||
- if (!mesh_hdr->ttl)
|
||||
- return RX_DROP_MONITOR;
|
||||
-
|
||||
- if (mesh_hdr->flags & MESH_FLAGS_AE) {
|
||||
- struct mesh_path *mppath;
|
||||
- char *proxied_addr;
|
||||
- char *mpp_addr;
|
||||
-
|
||||
- if (is_multicast_ether_addr(hdr->addr1)) {
|
||||
- mpp_addr = hdr->addr3;
|
||||
- proxied_addr = mesh_hdr->eaddr1;
|
||||
- } else if ((mesh_hdr->flags & MESH_FLAGS_AE) ==
|
||||
- MESH_FLAGS_AE_A5_A6) {
|
||||
- /* has_a4 already checked in ieee80211_rx_mesh_check */
|
||||
- mpp_addr = hdr->addr4;
|
||||
- proxied_addr = mesh_hdr->eaddr2;
|
||||
- } else {
|
||||
- return RX_DROP_MONITOR;
|
||||
- }
|
||||
-
|
||||
- rcu_read_lock();
|
||||
- mppath = mpp_path_lookup(sdata, proxied_addr);
|
||||
- if (!mppath) {
|
||||
- mpp_path_add(sdata, proxied_addr, mpp_addr);
|
||||
- } else {
|
||||
- spin_lock_bh(&mppath->state_lock);
|
||||
- if (!ether_addr_equal(mppath->mpp, mpp_addr))
|
||||
- memcpy(mppath->mpp, mpp_addr, ETH_ALEN);
|
||||
- mppath->exp_time = jiffies;
|
||||
- spin_unlock_bh(&mppath->state_lock);
|
||||
- }
|
||||
- rcu_read_unlock();
|
||||
- }
|
||||
-
|
||||
- /* Frame has reached destination. Don't forward */
|
||||
- if (!is_multicast_ether_addr(hdr->addr1) &&
|
||||
- ether_addr_equal(sdata->vif.addr, hdr->addr3))
|
||||
- return RX_CONTINUE;
|
||||
-
|
||||
- ac = ieee802_1d_to_ac[skb->priority];
|
||||
- skb_set_queue_mapping(skb, ac);
|
||||
-
|
||||
- if (!--mesh_hdr->ttl) {
|
||||
- if (!is_multicast_ether_addr(hdr->addr1))
|
||||
- IEEE80211_IFSTA_MESH_CTR_INC(ifmsh,
|
||||
- dropped_frames_ttl);
|
||||
- goto out;
|
||||
- }
|
||||
-
|
||||
- if (!ifmsh->mshcfg.dot11MeshForwarding)
|
||||
- goto out;
|
||||
-
|
||||
- if (sdata->crypto_tx_tailroom_needed_cnt)
|
||||
- tailroom = IEEE80211_ENCRYPT_TAILROOM;
|
||||
-
|
||||
- fwd_skb = skb_copy_expand(skb, local->tx_headroom +
|
||||
- IEEE80211_ENCRYPT_HEADROOM,
|
||||
- tailroom, GFP_ATOMIC);
|
||||
- if (!fwd_skb)
|
||||
- goto out;
|
||||
-
|
||||
- fwd_skb->dev = sdata->dev;
|
||||
- fwd_hdr = (struct ieee80211_hdr *) fwd_skb->data;
|
||||
- fwd_hdr->frame_control &= ~cpu_to_le16(IEEE80211_FCTL_RETRY);
|
||||
- info = IEEE80211_SKB_CB(fwd_skb);
|
||||
- memset(info, 0, sizeof(*info));
|
||||
- info->control.flags |= IEEE80211_TX_INTCFL_NEED_TXPROCESSING;
|
||||
- info->control.vif = &rx->sdata->vif;
|
||||
- info->control.jiffies = jiffies;
|
||||
- if (is_multicast_ether_addr(fwd_hdr->addr1)) {
|
||||
- IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_mcast);
|
||||
- memcpy(fwd_hdr->addr2, sdata->vif.addr, ETH_ALEN);
|
||||
- /* update power mode indication when forwarding */
|
||||
- ieee80211_mps_set_frame_flags(sdata, NULL, fwd_hdr);
|
||||
- } else if (!mesh_nexthop_lookup(sdata, fwd_skb)) {
|
||||
- /* mesh power mode flags updated in mesh_nexthop_lookup */
|
||||
- IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_unicast);
|
||||
- } else {
|
||||
- /* unable to resolve next hop */
|
||||
- mesh_path_error_tx(sdata, ifmsh->mshcfg.element_ttl,
|
||||
- fwd_hdr->addr3, 0,
|
||||
- WLAN_REASON_MESH_PATH_NOFORWARD,
|
||||
- fwd_hdr->addr2);
|
||||
- IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_no_route);
|
||||
- kfree_skb(fwd_skb);
|
||||
- return RX_DROP_MONITOR;
|
||||
- }
|
||||
-
|
||||
- IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_frames);
|
||||
- ieee80211_add_pending_skb(local, fwd_skb);
|
||||
- out:
|
||||
- if (is_multicast_ether_addr(hdr->addr1))
|
||||
- return RX_CONTINUE;
|
||||
- return RX_DROP_MONITOR;
|
||||
-}
|
||||
-#endif
|
||||
-
|
||||
static ieee80211_rx_result debug_noinline
|
||||
ieee80211_rx_h_data(struct ieee80211_rx_data *rx)
|
||||
{
|
||||
@@ -2991,6 +3028,7 @@ ieee80211_rx_h_data(struct ieee80211_rx_
|
||||
struct net_device *dev = sdata->dev;
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
|
||||
__le16 fc = hdr->frame_control;
|
||||
+ static ieee80211_rx_result res;
|
||||
bool port_control;
|
||||
int err;
|
||||
|
||||
@@ -3017,6 +3055,10 @@ ieee80211_rx_h_data(struct ieee80211_rx_
|
||||
if (unlikely(err))
|
||||
return RX_DROP_UNUSABLE;
|
||||
|
||||
+ res = ieee80211_rx_mesh_data(rx->sdata, rx->sta, rx->skb);
|
||||
+ if (res != RX_CONTINUE)
|
||||
+ return res;
|
||||
+
|
||||
if (!ieee80211_frame_allowed(rx, fc))
|
||||
return RX_DROP_MONITOR;
|
||||
|
||||
@@ -3987,10 +4029,6 @@ static void ieee80211_rx_handlers(struct
|
||||
CALL_RXH(ieee80211_rx_h_defragment);
|
||||
CALL_RXH(ieee80211_rx_h_michael_mic_verify);
|
||||
/* must be after MMIC verify so header is counted in MPDU mic */
|
||||
-#ifdef CPTCFG_MAC80211_MESH
|
||||
- if (ieee80211_vif_is_mesh(&rx->sdata->vif))
|
||||
- CALL_RXH(ieee80211_rx_h_mesh_fwding);
|
||||
-#endif
|
||||
CALL_RXH(ieee80211_rx_h_amsdu);
|
||||
CALL_RXH(ieee80211_rx_h_data);
|
||||
|
||||
--- a/net/wireless/util.c
|
||||
+++ b/net/wireless/util.c
|
||||
@@ -542,7 +542,7 @@ unsigned int ieee80211_get_mesh_hdrlen(s
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_get_mesh_hdrlen);
|
||||
|
||||
-static bool ieee80211_get_8023_tunnel_proto(const void *hdr, __be16 *proto)
|
||||
+bool ieee80211_get_8023_tunnel_proto(const void *hdr, __be16 *proto)
|
||||
{
|
||||
const __be16 *hdr_proto = hdr + ETH_ALEN;
|
||||
|
||||
@@ -556,6 +556,49 @@ static bool ieee80211_get_8023_tunnel_pr
|
||||
|
||||
return true;
|
||||
}
|
||||
+EXPORT_SYMBOL(ieee80211_get_8023_tunnel_proto);
|
||||
+
|
||||
+int ieee80211_strip_8023_mesh_hdr(struct sk_buff *skb)
|
||||
+{
|
||||
+ const void *mesh_addr;
|
||||
+ struct {
|
||||
+ struct ethhdr eth;
|
||||
+ u8 flags;
|
||||
+ } payload;
|
||||
+ int hdrlen;
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = skb_copy_bits(skb, 0, &payload, sizeof(payload));
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ hdrlen = sizeof(payload.eth) + __ieee80211_get_mesh_hdrlen(payload.flags);
|
||||
+
|
||||
+ if (likely(pskb_may_pull(skb, hdrlen + 8) &&
|
||||
+ ieee80211_get_8023_tunnel_proto(skb->data + hdrlen,
|
||||
+ &payload.eth.h_proto)))
|
||||
+ hdrlen += ETH_ALEN + 2;
|
||||
+ else if (!pskb_may_pull(skb, hdrlen))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ mesh_addr = skb->data + sizeof(payload.eth) + ETH_ALEN;
|
||||
+ switch (payload.flags & MESH_FLAGS_AE) {
|
||||
+ case MESH_FLAGS_AE_A4:
|
||||
+ memcpy(&payload.eth.h_source, mesh_addr, ETH_ALEN);
|
||||
+ break;
|
||||
+ case MESH_FLAGS_AE_A5_A6:
|
||||
+ memcpy(&payload.eth, mesh_addr, 2 * ETH_ALEN);
|
||||
+ break;
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ pskb_pull(skb, hdrlen - sizeof(payload.eth));
|
||||
+ memcpy(skb->data, &payload.eth, sizeof(payload.eth));
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+EXPORT_SYMBOL(ieee80211_strip_8023_mesh_hdr);
|
||||
|
||||
int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr,
|
||||
const u8 *addr, enum nl80211_iftype iftype,
|
||||
@@ -568,7 +611,6 @@ int ieee80211_data_to_8023_exthdr(struct
|
||||
} payload;
|
||||
struct ethhdr tmp;
|
||||
u16 hdrlen;
|
||||
- u8 mesh_flags = 0;
|
||||
|
||||
if (unlikely(!ieee80211_is_data_present(hdr->frame_control)))
|
||||
return -1;
|
||||
@@ -589,12 +631,6 @@ int ieee80211_data_to_8023_exthdr(struct
|
||||
memcpy(tmp.h_dest, ieee80211_get_DA(hdr), ETH_ALEN);
|
||||
memcpy(tmp.h_source, ieee80211_get_SA(hdr), ETH_ALEN);
|
||||
|
||||
- if (iftype == NL80211_IFTYPE_MESH_POINT &&
|
||||
- skb_copy_bits(skb, hdrlen, &mesh_flags, 1) < 0)
|
||||
- return -1;
|
||||
-
|
||||
- mesh_flags &= MESH_FLAGS_AE;
|
||||
-
|
||||
switch (hdr->frame_control &
|
||||
cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) {
|
||||
case cpu_to_le16(IEEE80211_FCTL_TODS):
|
||||
@@ -608,17 +644,6 @@ int ieee80211_data_to_8023_exthdr(struct
|
||||
iftype != NL80211_IFTYPE_AP_VLAN &&
|
||||
iftype != NL80211_IFTYPE_STATION))
|
||||
return -1;
|
||||
- if (iftype == NL80211_IFTYPE_MESH_POINT) {
|
||||
- if (mesh_flags == MESH_FLAGS_AE_A4)
|
||||
- return -1;
|
||||
- if (mesh_flags == MESH_FLAGS_AE_A5_A6 &&
|
||||
- skb_copy_bits(skb, hdrlen +
|
||||
- offsetof(struct ieee80211s_hdr, eaddr1),
|
||||
- tmp.h_dest, 2 * ETH_ALEN) < 0)
|
||||
- return -1;
|
||||
-
|
||||
- hdrlen += __ieee80211_get_mesh_hdrlen(mesh_flags);
|
||||
- }
|
||||
break;
|
||||
case cpu_to_le16(IEEE80211_FCTL_FROMDS):
|
||||
if ((iftype != NL80211_IFTYPE_STATION &&
|
||||
@@ -627,16 +652,6 @@ int ieee80211_data_to_8023_exthdr(struct
|
||||
(is_multicast_ether_addr(tmp.h_dest) &&
|
||||
ether_addr_equal(tmp.h_source, addr)))
|
||||
return -1;
|
||||
- if (iftype == NL80211_IFTYPE_MESH_POINT) {
|
||||
- if (mesh_flags == MESH_FLAGS_AE_A5_A6)
|
||||
- return -1;
|
||||
- if (mesh_flags == MESH_FLAGS_AE_A4 &&
|
||||
- skb_copy_bits(skb, hdrlen +
|
||||
- offsetof(struct ieee80211s_hdr, eaddr1),
|
||||
- tmp.h_source, ETH_ALEN) < 0)
|
||||
- return -1;
|
||||
- hdrlen += __ieee80211_get_mesh_hdrlen(mesh_flags);
|
||||
- }
|
||||
break;
|
||||
case cpu_to_le16(0):
|
||||
if (iftype != NL80211_IFTYPE_ADHOC &&
|
||||
@@ -646,7 +661,7 @@ int ieee80211_data_to_8023_exthdr(struct
|
||||
break;
|
||||
}
|
||||
|
||||
- if (likely(!is_amsdu &&
|
||||
+ if (likely(!is_amsdu && iftype != NL80211_IFTYPE_MESH_POINT &&
|
||||
skb_copy_bits(skb, hdrlen, &payload, sizeof(payload)) == 0 &&
|
||||
ieee80211_get_8023_tunnel_proto(&payload, &tmp.h_proto))) {
|
||||
/* remove RFC1042 or Bridge-Tunnel encapsulation */
|
||||
@@ -722,7 +737,8 @@ __ieee80211_amsdu_copy_frag(struct sk_bu
|
||||
|
||||
static struct sk_buff *
|
||||
__ieee80211_amsdu_copy(struct sk_buff *skb, unsigned int hlen,
|
||||
- int offset, int len, bool reuse_frag)
|
||||
+ int offset, int len, bool reuse_frag,
|
||||
+ int min_len)
|
||||
{
|
||||
struct sk_buff *frame;
|
||||
int cur_len = len;
|
||||
@@ -736,7 +752,7 @@ __ieee80211_amsdu_copy(struct sk_buff *s
|
||||
* in the stack later.
|
||||
*/
|
||||
if (reuse_frag)
|
||||
- cur_len = min_t(int, len, 32);
|
||||
+ cur_len = min_t(int, len, min_len);
|
||||
|
||||
/*
|
||||
* Allocate and reserve two bytes more for payload
|
||||
@@ -746,6 +762,7 @@ __ieee80211_amsdu_copy(struct sk_buff *s
|
||||
if (!frame)
|
||||
return NULL;
|
||||
|
||||
+ frame->priority = skb->priority;
|
||||
skb_reserve(frame, hlen + sizeof(struct ethhdr) + 2);
|
||||
skb_copy_bits(skb, offset, skb_put(frame, cur_len), cur_len);
|
||||
|
||||
@@ -762,23 +779,37 @@ __ieee80211_amsdu_copy(struct sk_buff *s
|
||||
void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
|
||||
const u8 *addr, enum nl80211_iftype iftype,
|
||||
const unsigned int extra_headroom,
|
||||
- const u8 *check_da, const u8 *check_sa)
|
||||
+ const u8 *check_da, const u8 *check_sa,
|
||||
+ bool mesh_control)
|
||||
{
|
||||
unsigned int hlen = ALIGN(extra_headroom, 4);
|
||||
struct sk_buff *frame = NULL;
|
||||
int offset = 0, remaining;
|
||||
- struct ethhdr eth;
|
||||
+ struct {
|
||||
+ struct ethhdr eth;
|
||||
+ uint8_t flags;
|
||||
+ } hdr;
|
||||
bool reuse_frag = skb->head_frag && !skb_has_frag_list(skb);
|
||||
bool reuse_skb = false;
|
||||
bool last = false;
|
||||
+ int copy_len = sizeof(hdr.eth);
|
||||
+
|
||||
+ if (iftype == NL80211_IFTYPE_MESH_POINT)
|
||||
+ copy_len = sizeof(hdr);
|
||||
|
||||
while (!last) {
|
||||
unsigned int subframe_len;
|
||||
- int len;
|
||||
+ int len, mesh_len = 0;
|
||||
u8 padding;
|
||||
|
||||
- skb_copy_bits(skb, offset, ð, sizeof(eth));
|
||||
- len = ntohs(eth.h_proto);
|
||||
+ skb_copy_bits(skb, offset, &hdr, copy_len);
|
||||
+ if (iftype == NL80211_IFTYPE_MESH_POINT)
|
||||
+ mesh_len = __ieee80211_get_mesh_hdrlen(hdr.flags);
|
||||
+ if (mesh_control)
|
||||
+ len = le16_to_cpu(*(__le16 *)&hdr.eth.h_proto) + mesh_len;
|
||||
+ else
|
||||
+ len = ntohs(hdr.eth.h_proto);
|
||||
+
|
||||
subframe_len = sizeof(struct ethhdr) + len;
|
||||
padding = (4 - subframe_len) & 0x3;
|
||||
|
||||
@@ -787,16 +818,16 @@ void ieee80211_amsdu_to_8023s(struct sk_
|
||||
if (subframe_len > remaining)
|
||||
goto purge;
|
||||
/* mitigate A-MSDU aggregation injection attacks */
|
||||
- if (ether_addr_equal(eth.h_dest, rfc1042_header))
|
||||
+ if (ether_addr_equal(hdr.eth.h_dest, rfc1042_header))
|
||||
goto purge;
|
||||
|
||||
offset += sizeof(struct ethhdr);
|
||||
last = remaining <= subframe_len + padding;
|
||||
|
||||
/* FIXME: should we really accept multicast DA? */
|
||||
- if ((check_da && !is_multicast_ether_addr(eth.h_dest) &&
|
||||
- !ether_addr_equal(check_da, eth.h_dest)) ||
|
||||
- (check_sa && !ether_addr_equal(check_sa, eth.h_source))) {
|
||||
+ if ((check_da && !is_multicast_ether_addr(hdr.eth.h_dest) &&
|
||||
+ !ether_addr_equal(check_da, hdr.eth.h_dest)) ||
|
||||
+ (check_sa && !ether_addr_equal(check_sa, hdr.eth.h_source))) {
|
||||
offset += len + padding;
|
||||
continue;
|
||||
}
|
||||
@@ -808,7 +839,7 @@ void ieee80211_amsdu_to_8023s(struct sk_
|
||||
reuse_skb = true;
|
||||
} else {
|
||||
frame = __ieee80211_amsdu_copy(skb, hlen, offset, len,
|
||||
- reuse_frag);
|
||||
+ reuse_frag, 32 + mesh_len);
|
||||
if (!frame)
|
||||
goto purge;
|
||||
|
||||
@@ -819,10 +850,11 @@ void ieee80211_amsdu_to_8023s(struct sk_
|
||||
frame->dev = skb->dev;
|
||||
frame->priority = skb->priority;
|
||||
|
||||
- if (likely(ieee80211_get_8023_tunnel_proto(frame->data, ð.h_proto)))
|
||||
+ if (likely(iftype != NL80211_IFTYPE_MESH_POINT &&
|
||||
+ ieee80211_get_8023_tunnel_proto(frame->data, &hdr.eth.h_proto)))
|
||||
skb_pull(frame, ETH_ALEN + 2);
|
||||
|
||||
- memcpy(skb_push(frame, sizeof(eth)), ð, sizeof(eth));
|
||||
+ memcpy(skb_push(frame, sizeof(hdr.eth)), &hdr.eth, sizeof(hdr.eth));
|
||||
__skb_queue_tail(list, frame);
|
||||
}
|
||||
|
8
build.sh
8
build.sh
|
@ -690,9 +690,9 @@ if [ "$OMR_KERNEL" = "6.1" ]; then
|
|||
rm -f package/kernel/rtl8812au-ct/patches/100-api_update.patch
|
||||
#rm -f target/linux/bcm27xx/modules/sound.mk
|
||||
rm -f package/libs/elfutils/patches/101-no-fts.patch
|
||||
rm -f package/kernel/mwlwifi/patches/001-*
|
||||
rm -f package/kernel/mwlwifi/patches/002-*
|
||||
rm -f package/kernel/mwlwifi/patches/003-*
|
||||
#rm -f package/kernel/mwlwifi/patches/001-*
|
||||
#rm -f package/kernel/mwlwifi/patches/002-*
|
||||
#rm -f package/kernel/mwlwifi/patches/003-*
|
||||
rm -rf package/kernel/mt76
|
||||
rm -rf target/linux/ipq40xx/files/drivers/net/dsa
|
||||
rm -rf target/linux/ipq40xx/files/drivers/net/ethernet
|
||||
|
@ -711,7 +711,7 @@ if [ "$OMR_KERNEL" = "6.1" ]; then
|
|||
if [ "$TARGET" = "bpi-r2" ]; then
|
||||
echo "# CONFIG_VERSION_CODE_FILENAMES is not set" >> ".config"
|
||||
fi
|
||||
if [ "$OMR_TARGET" != "x86" ] && [ "$OMR_TARGET" != "x86_64" ] && [ "$OMR_TARGET" != "r4s" ] && [ "$OMR_TARGET" != "r5s" ] && [ "$OMR_TARGET" != "qnap-301w" ] && [ "$OMR_TARGET" != "rpi4" ] && [ "$OMR_TARGET" != "rpi3" ] && [ "$OMR_TARGET" != "wrt32x" ] && [ "$OMR_TARGET" != "wrt3200acm" ] && [ "$OMR_TARGET" != "bpi-r64" ] && [ "$OMR_TARGET" != "r7800" ] && [ "$OMR_TARGET" != "rutx" ]; then
|
||||
if [ "$OMR_TARGET" != "x86" ] && [ "$OMR_TARGET" != "x86_64" ] && [ "$OMR_TARGET" != "r4s" ] && [ "$OMR_TARGET" != "r5s" ] && [ "$OMR_TARGET" != "qnap-301w" ] && [ "$OMR_TARGET" != "rpi4" ] && [ "$OMR_TARGET" != "rpi3" ] && [ "$OMR_TARGET" != "wrt32x" ] && [ "$OMR_TARGET" != "wrt3200acm" ] && [ "$OMR_TARGET" != "bpi-r64" ] && [ "$OMR_TARGET" != "r7800" ] && [ "$OMR_TARGET" != "espressobin" ] && [ "$OMR_TARGET" != "rutx" ]; then
|
||||
echo "Sorry but kernel 6.1 is not supported on your arch yet"
|
||||
NOT_SUPPORTED="1"
|
||||
#exit 1
|
||||
|
|
Loading…
Reference in a new issue