split kernel and OpenWRT/LEDE patches
The OpenWRT patches are for the mac80211 package. They are functional indentical to the kernel patches but need two modifications. 1. CONFIG_ needs to be replaced with CPTCFG_ 2. any new configuration option, need to be patched into .local-symbols This change move the kernel patches to a seperate directory, add a helper script to rebuild the OpenWRT/LEDE patches and updates those patches.
This commit is contained in:
parent
2f2a287928
commit
bf57c7a336
6
INSTALL
6
INSTALL
@ -23,12 +23,16 @@ Requirements
|
|||||||
Build
|
Build
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
Linux Kernel:
|
||||||
|
|
||||||
|
Apply the appropriate path from kernel-patches to your kernel, enable
|
||||||
|
CAPWAP WTP support and rebuild you kernel.
|
||||||
|
|
||||||
WolfSSL:
|
WolfSSL:
|
||||||
./configure --enable-dtls --enable-psk --prefix=/usr/
|
./configure --enable-dtls --enable-psk --prefix=/usr/
|
||||||
make
|
make
|
||||||
make install
|
make install
|
||||||
|
|
||||||
|
|
||||||
FreeWTP:
|
FreeWTP:
|
||||||
autoreconf -f -i
|
autoreconf -f -i
|
||||||
./configure
|
./configure
|
||||||
|
@ -47,6 +47,11 @@ NOTE: To run WTP you must have a wireless card that has Linux driver based on th
|
|||||||
|
|
||||||
### Build
|
### Build
|
||||||
|
|
||||||
|
Linux Kernel:
|
||||||
|
|
||||||
|
Apply the appropriate path from kernel-patches to your kernel, enable
|
||||||
|
CAPWAP WTP support and rebuild you kernel.
|
||||||
|
|
||||||
WolfSSL:
|
WolfSSL:
|
||||||
|
|
||||||
./configure --enable-dtls --enable-ipv6 --enable-aesgcm \
|
./configure --enable-dtls --enable-ipv6 --enable-aesgcm \
|
||||||
|
685
kernel-patches/mac80211_packet_tunnel-linux-4.4.patch
Normal file
685
kernel-patches/mac80211_packet_tunnel-linux-4.4.patch
Normal file
@ -0,0 +1,685 @@
|
|||||||
|
From 681af1c29f8276c2105ff4ce8d31ec56bd9e5b7a Mon Sep 17 00:00:00 2001
|
||||||
|
From: Andreas Schultz <aschultz@tpip.net>
|
||||||
|
Date: Thu, 4 Feb 2016 15:57:11 +0100
|
||||||
|
Subject: [PATCH] support patch for FreeWTP
|
||||||
|
|
||||||
|
Allows for kernel side interception and injection of IEEE 802.11 frames.
|
||||||
|
---
|
||||||
|
include/net/mac80211.h | 31 +++++
|
||||||
|
net/mac80211/Kconfig | 7 ++
|
||||||
|
net/mac80211/ieee80211_i.h | 12 ++
|
||||||
|
net/mac80211/iface.c | 63 ++++++++++
|
||||||
|
net/mac80211/rx.c | 92 +++++++++++++--
|
||||||
|
net/mac80211/tx.c | 286 +++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
6 files changed, 479 insertions(+), 12 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
|
||||||
|
index 760bc4d..e80b1af 100644
|
||||||
|
--- a/include/net/mac80211.h
|
||||||
|
+++ b/include/net/mac80211.h
|
||||||
|
@@ -2199,6 +2199,37 @@ ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw,
|
||||||
|
*/
|
||||||
|
void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb);
|
||||||
|
|
||||||
|
+#ifdef CONFIG_MAC80211_CAPWAP_WTP
|
||||||
|
+
|
||||||
|
+extern struct static_key_false mac80211_capwap_wtp;
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ *
|
||||||
|
+ */
|
||||||
|
+struct ieee80211_pcktunnel {
|
||||||
|
+ u16 subtype_mask[3]; /* 0: MGMT, 1: CTLR, 2: DATA */
|
||||||
|
+
|
||||||
|
+ int (*handler)(u32 ifindex, struct sk_buff *skb, int sig_dbm, unsigned char rate, void *data);
|
||||||
|
+ void *data;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ *
|
||||||
|
+ */
|
||||||
|
+int ieee80211_pcktunnel_register(struct net_device *dev, struct ieee80211_pcktunnel *handler);
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ *
|
||||||
|
+ */
|
||||||
|
+int ieee80211_pcktunnel_deregister(struct net_device *dev, struct ieee80211_pcktunnel *handler);
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ *
|
||||||
|
+ */
|
||||||
|
+netdev_tx_t ieee80211_inject_xmit(struct sk_buff* skb, struct net_device* dev);
|
||||||
|
+
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
/**
|
||||||
|
* DOC: Hardware crypto acceleration
|
||||||
|
*
|
||||||
|
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig
|
||||||
|
index 3891cbd..4ff4461 100644
|
||||||
|
--- a/net/mac80211/Kconfig
|
||||||
|
+++ b/net/mac80211/Kconfig
|
||||||
|
@@ -318,3 +318,10 @@ config MAC80211_STA_HASH_MAX_SIZE
|
||||||
|
connect more stations than the number selected here.)
|
||||||
|
|
||||||
|
If unsure, leave the default of 0.
|
||||||
|
+
|
||||||
|
+config MAC80211_CAPWAP_WTP
|
||||||
|
+ bool "Enable support functions for out-of-tree CAPWAP WTP module"
|
||||||
|
+ depends on MAC80211
|
||||||
|
+ ---help---
|
||||||
|
+ Select this to build support hooks for out-of-tree CAPWAP FreeWTP
|
||||||
|
+ module.
|
||||||
|
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
|
||||||
|
index 6837a46..e96cbff 100644
|
||||||
|
--- a/net/mac80211/ieee80211_i.h
|
||||||
|
+++ b/net/mac80211/ieee80211_i.h
|
||||||
|
@@ -180,6 +180,9 @@ typedef unsigned __bitwise__ ieee80211_rx_result;
|
||||||
|
#define RX_DROP_UNUSABLE ((__force ieee80211_rx_result) 1u)
|
||||||
|
#define RX_DROP_MONITOR ((__force ieee80211_rx_result) 2u)
|
||||||
|
#define RX_QUEUED ((__force ieee80211_rx_result) 3u)
|
||||||
|
+#ifdef CONFIG_MAC80211_CAPWAP_WTP
|
||||||
|
+#define RX_IGNORE_MONITOR ((__force ieee80211_rx_result) 4u)
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum ieee80211_packet_rx_flags - packet RX flags
|
||||||
|
@@ -835,6 +838,11 @@ struct ieee80211_sub_if_data {
|
||||||
|
|
||||||
|
char name[IFNAMSIZ];
|
||||||
|
|
||||||
|
+#ifdef CONFIG_MAC80211_CAPWAP_WTP
|
||||||
|
+ /* Packet tunnel handlers */
|
||||||
|
+ struct ieee80211_pcktunnel __rcu *pcktunnel_handlers;
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
/* Fragment table for host-based reassembly */
|
||||||
|
struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX];
|
||||||
|
unsigned int fragment_next;
|
||||||
|
@@ -1632,6 +1640,10 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
|
||||||
|
void __ieee80211_subif_start_xmit(struct sk_buff *skb,
|
||||||
|
struct net_device *dev,
|
||||||
|
u32 info_flags);
|
||||||
|
+#ifdef CONFIG_MAC80211_CAPWAP_WTP
|
||||||
|
+netdev_tx_t ieee80211_capwap_subif_start_xmit(struct sk_buff *skb,
|
||||||
|
+ struct net_device *dev);
|
||||||
|
+#endif
|
||||||
|
void ieee80211_purge_tx_queue(struct ieee80211_hw *hw,
|
||||||
|
struct sk_buff_head *skbs);
|
||||||
|
struct sk_buff *
|
||||||
|
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
|
||||||
|
index bcb0a1b..cb08ec2 100644
|
||||||
|
--- a/net/mac80211/iface.c
|
||||||
|
+++ b/net/mac80211/iface.c
|
||||||
|
@@ -1955,3 +1955,66 @@ void ieee80211_iface_exit(void)
|
||||||
|
{
|
||||||
|
unregister_netdevice_notifier(&mac80211_netdev_notifier);
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+#ifdef CONFIG_MAC80211_CAPWAP_WTP
|
||||||
|
+
|
||||||
|
+DEFINE_STATIC_KEY_FALSE(mac80211_capwap_wtp);
|
||||||
|
+
|
||||||
|
+static const struct net_device_ops ieee80211_capwapif_ops = {
|
||||||
|
+ .ndo_open = ieee80211_open,
|
||||||
|
+ .ndo_stop = ieee80211_stop,
|
||||||
|
+ .ndo_uninit = ieee80211_uninit,
|
||||||
|
+ .ndo_start_xmit = ieee80211_capwap_subif_start_xmit,
|
||||||
|
+ .ndo_set_rx_mode = ieee80211_set_multicast_list,
|
||||||
|
+ .ndo_change_mtu = ieee80211_change_mtu,
|
||||||
|
+ .ndo_set_mac_address = ieee80211_change_mac,
|
||||||
|
+ .ndo_select_queue = ieee80211_netdev_select_queue,
|
||||||
|
+ .ndo_get_stats64 = ieee80211_get_stats64,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+int ieee80211_pcktunnel_register(struct net_device *dev, struct ieee80211_pcktunnel *handler)
|
||||||
|
+{
|
||||||
|
+ int ret = 0;
|
||||||
|
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||||
|
+
|
||||||
|
+ dev->netdev_ops = &ieee80211_capwapif_ops;
|
||||||
|
+
|
||||||
|
+ mutex_lock(&sdata->local->iflist_mtx);
|
||||||
|
+
|
||||||
|
+ if (rcu_dereference_protected(sdata->pcktunnel_handlers, lockdep_is_held(&sdata->local->iflist_mtx))) {
|
||||||
|
+ ret = -EBUSY;
|
||||||
|
+ } else {
|
||||||
|
+ rcu_assign_pointer(sdata->pcktunnel_handlers, handler);
|
||||||
|
+ static_branch_enable(&mac80211_capwap_wtp);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ mutex_unlock(&sdata->local->iflist_mtx);
|
||||||
|
+ synchronize_net();
|
||||||
|
+
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+EXPORT_SYMBOL(ieee80211_pcktunnel_register);
|
||||||
|
+
|
||||||
|
+int ieee80211_pcktunnel_deregister(struct net_device *dev, struct ieee80211_pcktunnel *handler)
|
||||||
|
+{
|
||||||
|
+ int ret = -ENODEV;
|
||||||
|
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||||
|
+ struct ieee80211_pcktunnel *h;
|
||||||
|
+
|
||||||
|
+ mutex_lock(&sdata->local->iflist_mtx);
|
||||||
|
+
|
||||||
|
+ h = rcu_dereference_protected(sdata->pcktunnel_handlers, lockdep_is_held(&sdata->local->iflist_mtx));
|
||||||
|
+ if (h == handler) {
|
||||||
|
+ ret = 0;
|
||||||
|
+ static_branch_disable(&mac80211_capwap_wtp);
|
||||||
|
+ rcu_assign_pointer(sdata->pcktunnel_handlers, NULL);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ mutex_unlock(&sdata->local->iflist_mtx);
|
||||||
|
+ synchronize_net();
|
||||||
|
+
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+EXPORT_SYMBOL(ieee80211_pcktunnel_deregister);
|
||||||
|
+
|
||||||
|
+#endif
|
||||||
|
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
|
||||||
|
index a3bb8f7..07b2ff6 100644
|
||||||
|
--- a/net/mac80211/rx.c
|
||||||
|
+++ b/net/mac80211/rx.c
|
||||||
|
@@ -3058,6 +3058,56 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx)
|
||||||
|
return RX_QUEUED;
|
||||||
|
}
|
||||||
|
|
||||||
|
+#ifdef CONFIG_MAC80211_CAPWAP_WTP
|
||||||
|
+
|
||||||
|
+static ieee80211_rx_result debug_noinline
|
||||||
|
+ieee80211_rx_h_pcktunnel(struct ieee80211_rx_data *rx, struct ieee80211_rate *rate)
|
||||||
|
+{
|
||||||
|
+ struct ieee80211_pcktunnel *handler;
|
||||||
|
+
|
||||||
|
+ handler = rcu_dereference(rx->sdata->pcktunnel_handlers);
|
||||||
|
+ if (handler) {
|
||||||
|
+ u16 fc;
|
||||||
|
+ u16 fc_type;
|
||||||
|
+ int sig_dbm = 0;
|
||||||
|
+ unsigned char pckrate = 0;
|
||||||
|
+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
|
||||||
|
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
|
||||||
|
+
|
||||||
|
+ if (ieee80211_hw_check(&rx->local->hw, SIGNAL_DBM))
|
||||||
|
+ sig_dbm = status->signal;
|
||||||
|
+
|
||||||
|
+ if (rate && !(status->flag & (RX_FLAG_HT | RX_FLAG_VHT))) {
|
||||||
|
+ int shift = 0;
|
||||||
|
+ if (status->flag & RX_FLAG_10MHZ)
|
||||||
|
+ shift = 1;
|
||||||
|
+ else if (status->flag & RX_FLAG_5MHZ)
|
||||||
|
+ shift = 2;
|
||||||
|
+ pckrate = DIV_ROUND_UP(rate->bitrate, 5 * (1 << shift));
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Retrieve type and subtype packet */
|
||||||
|
+ fc = le16_to_cpu(hdr->frame_control);
|
||||||
|
+ fc_type = ((fc & IEEE80211_FCTL_FTYPE) >> 2);
|
||||||
|
+ if (fc_type < 3) {
|
||||||
|
+ u16 bitmask = 1 << ((fc & IEEE80211_FCTL_STYPE) >> 4);
|
||||||
|
+
|
||||||
|
+ /* Delegate packet to external handler */
|
||||||
|
+ if (handler->subtype_mask[fc_type] & bitmask) {
|
||||||
|
+ if (handler->handler(rx->sdata->dev->ifindex, rx->skb, sig_dbm, pckrate, handler->data)) {
|
||||||
|
+ return RX_IGNORE_MONITOR;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return RX_CONTINUE;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* TODO: use IEEE80211_RX_FRAGMENTED */
|
||||||
|
+
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx,
|
||||||
|
struct ieee80211_rate *rate)
|
||||||
|
{
|
||||||
|
@@ -3137,6 +3187,9 @@ static void ieee80211_rx_handlers_result(struct ieee80211_rx_data *rx,
|
||||||
|
if (rx->sta)
|
||||||
|
rx->sta->rx_stats.dropped++;
|
||||||
|
/* fall through */
|
||||||
|
+#ifdef CONFIG_MAC80211_CAPWAP_WTP
|
||||||
|
+ case RX_IGNORE_MONITOR:
|
||||||
|
+#endif
|
||||||
|
case RX_CONTINUE: {
|
||||||
|
struct ieee80211_rate *rate = NULL;
|
||||||
|
struct ieee80211_supported_band *sband;
|
||||||
|
@@ -3165,7 +3218,9 @@ static void ieee80211_rx_handlers_result(struct ieee80211_rx_data *rx,
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx,
|
||||||
|
- struct sk_buff_head *frames)
|
||||||
|
+ struct sk_buff_head *frames,
|
||||||
|
+ struct ieee80211_rate *rate)
|
||||||
|
+
|
||||||
|
{
|
||||||
|
ieee80211_rx_result res = RX_DROP_MONITOR;
|
||||||
|
struct sk_buff *skb;
|
||||||
|
@@ -3204,6 +3259,15 @@ static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx,
|
||||||
|
if (ieee80211_vif_is_mesh(&rx->sdata->vif))
|
||||||
|
CALL_RXH(ieee80211_rx_h_mesh_fwding);
|
||||||
|
#endif
|
||||||
|
+#ifdef CONFIG_MAC80211_CAPWAP_WTP
|
||||||
|
+ if (static_branch_unlikely(&mac80211_capwap_wtp)) {
|
||||||
|
+ /* special treatment */
|
||||||
|
+ res = ieee80211_rx_h_pcktunnel(rx, rate);
|
||||||
|
+ if (res != RX_CONTINUE)
|
||||||
|
+ goto rxh_next;
|
||||||
|
+ }
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
CALL_RXH(ieee80211_rx_h_amsdu)
|
||||||
|
CALL_RXH(ieee80211_rx_h_data)
|
||||||
|
|
||||||
|
@@ -3227,7 +3291,8 @@ static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx,
|
||||||
|
spin_unlock_bh(&rx->local->rx_path_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
-static void ieee80211_invoke_rx_handlers(struct ieee80211_rx_data *rx)
|
||||||
|
+static void ieee80211_invoke_rx_handlers(struct ieee80211_rx_data *rx,
|
||||||
|
+ struct ieee80211_rate *rate)
|
||||||
|
{
|
||||||
|
struct sk_buff_head reorder_release;
|
||||||
|
ieee80211_rx_result res = RX_DROP_MONITOR;
|
||||||
|
@@ -3246,7 +3311,7 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_rx_data *rx)
|
||||||
|
|
||||||
|
ieee80211_rx_reorder_ampdu(rx, &reorder_release);
|
||||||
|
|
||||||
|
- ieee80211_rx_handlers(rx, &reorder_release);
|
||||||
|
+ ieee80211_rx_handlers(rx, &reorder_release, rate);
|
||||||
|
return;
|
||||||
|
|
||||||
|
rxh_next:
|
||||||
|
@@ -3292,7 +3357,7 @@ void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid)
|
||||||
|
drv_event_callback(rx.local, rx.sdata, &event);
|
||||||
|
}
|
||||||
|
|
||||||
|
- ieee80211_rx_handlers(&rx, &frames);
|
||||||
|
+ ieee80211_rx_handlers(&rx, &frames, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* main receive path */
|
||||||
|
@@ -3415,7 +3480,9 @@ static bool ieee80211_accept_frame(struct ieee80211_rx_data *rx)
|
||||||
|
* or not the skb was consumed.
|
||||||
|
*/
|
||||||
|
static bool ieee80211_prepare_and_rx_handle(struct ieee80211_rx_data *rx,
|
||||||
|
- struct sk_buff *skb, bool consume)
|
||||||
|
+ struct sk_buff *skb,
|
||||||
|
+ struct ieee80211_rate *rate,
|
||||||
|
+ bool consume)
|
||||||
|
{
|
||||||
|
struct ieee80211_local *local = rx->local;
|
||||||
|
struct ieee80211_sub_if_data *sdata = rx->sdata;
|
||||||
|
@@ -3438,7 +3505,7 @@ static bool ieee80211_prepare_and_rx_handle(struct ieee80211_rx_data *rx,
|
||||||
|
rx->skb = skb;
|
||||||
|
}
|
||||||
|
|
||||||
|
- ieee80211_invoke_rx_handlers(rx);
|
||||||
|
+ ieee80211_invoke_rx_handlers(rx, rate);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -3448,7 +3515,8 @@ static bool ieee80211_prepare_and_rx_handle(struct ieee80211_rx_data *rx,
|
||||||
|
*/
|
||||||
|
static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
|
||||||
|
struct sk_buff *skb,
|
||||||
|
- struct napi_struct *napi)
|
||||||
|
+ struct napi_struct *napi,
|
||||||
|
+ struct ieee80211_rate *rate)
|
||||||
|
{
|
||||||
|
struct ieee80211_local *local = hw_to_local(hw);
|
||||||
|
struct ieee80211_sub_if_data *sdata;
|
||||||
|
@@ -3507,7 +3575,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
|
||||||
|
|
||||||
|
rx.sta = prev_sta;
|
||||||
|
rx.sdata = prev_sta->sdata;
|
||||||
|
- ieee80211_prepare_and_rx_handle(&rx, skb, false);
|
||||||
|
+ ieee80211_prepare_and_rx_handle(&rx, skb, rate, false);
|
||||||
|
|
||||||
|
prev_sta = sta;
|
||||||
|
}
|
||||||
|
@@ -3516,7 +3584,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
|
||||||
|
rx.sta = prev_sta;
|
||||||
|
rx.sdata = prev_sta->sdata;
|
||||||
|
|
||||||
|
- if (ieee80211_prepare_and_rx_handle(&rx, skb, true))
|
||||||
|
+ if (ieee80211_prepare_and_rx_handle(&rx, skb, rate, true))
|
||||||
|
return;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
@@ -3545,7 +3613,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
|
||||||
|
|
||||||
|
rx.sta = sta_info_get_bss(prev, hdr->addr2);
|
||||||
|
rx.sdata = prev;
|
||||||
|
- ieee80211_prepare_and_rx_handle(&rx, skb, false);
|
||||||
|
+ ieee80211_prepare_and_rx_handle(&rx, skb, rate, false);
|
||||||
|
|
||||||
|
prev = sdata;
|
||||||
|
}
|
||||||
|
@@ -3554,7 +3622,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
|
||||||
|
rx.sta = sta_info_get_bss(prev, hdr->addr2);
|
||||||
|
rx.sdata = prev;
|
||||||
|
|
||||||
|
- if (ieee80211_prepare_and_rx_handle(&rx, skb, true))
|
||||||
|
+ if (ieee80211_prepare_and_rx_handle(&rx, skb, rate, true))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -3666,7 +3734,7 @@ void ieee80211_rx_napi(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||||
|
ieee80211_tpt_led_trig_rx(local,
|
||||||
|
((struct ieee80211_hdr *)skb->data)->frame_control,
|
||||||
|
skb->len);
|
||||||
|
- __ieee80211_rx_handle_packet(hw, skb, napi);
|
||||||
|
+ __ieee80211_rx_handle_packet(hw, skb, napi, rate);
|
||||||
|
|
||||||
|
rcu_read_unlock();
|
||||||
|
|
||||||
|
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
|
||||||
|
index bdc224d..ee4e7c7 100644
|
||||||
|
--- a/net/mac80211/tx.c
|
||||||
|
+++ b/net/mac80211/tx.c
|
||||||
|
@@ -2939,6 +2939,115 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
|
||||||
|
return NETDEV_TX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
+#ifdef CONFIG_MAC80211_CAPWAP_WTP
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * inject raw 802.11 frame, processing is mostly identical
|
||||||
|
+ * to ieee80211_monitor_start_xmit, except for the different
|
||||||
|
+ * headers
|
||||||
|
+ */
|
||||||
|
+static void __ieee80211_capwap_inject_start_xmit(struct sk_buff *skb,
|
||||||
|
+ struct net_device *dev)
|
||||||
|
+{
|
||||||
|
+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
|
||||||
|
+ struct ieee80211_chanctx_conf *chanctx_conf;
|
||||||
|
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||||
|
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||||
|
+ struct ieee80211_sub_if_data *sdata;
|
||||||
|
+ struct cfg80211_chan_def *chandef;
|
||||||
|
+ int tid;
|
||||||
|
+ int hdrlen;
|
||||||
|
+
|
||||||
|
+ /* check for not even having the fixed 802.11 header */
|
||||||
|
+ if (unlikely(skb->len < sizeof(struct ieee80211_hdr)))
|
||||||
|
+ goto fail; /* too short to be possibly valid */
|
||||||
|
+
|
||||||
|
+ hdrlen = ieee80211_hdrlen(hdr->frame_control);
|
||||||
|
+
|
||||||
|
+ /* does the skb contain enough to deliver on the alleged length? */
|
||||||
|
+ if (unlikely(skb->len < hdrlen))
|
||||||
|
+ goto fail; /* skb too short for claimed header length */
|
||||||
|
+
|
||||||
|
+ skb_set_mac_header(skb, 0);
|
||||||
|
+ /*
|
||||||
|
+ * these are just fixed to the end of the rt area since we
|
||||||
|
+ * don't have any better information and at this point, nobody cares
|
||||||
|
+ */
|
||||||
|
+ skb_set_network_header(skb, hdrlen);
|
||||||
|
+ skb_set_transport_header(skb, hdrlen);
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * Initialize skb->protocol if the injected frame is a data frame
|
||||||
|
+ * carrying a rfc1042 header
|
||||||
|
+ */
|
||||||
|
+ if (ieee80211_is_data(hdr->frame_control) &&
|
||||||
|
+ skb->len >= hdrlen + sizeof(rfc1042_header) + 2) {
|
||||||
|
+ u8 *payload = (u8 *)hdr + hdrlen;
|
||||||
|
+
|
||||||
|
+ if (ether_addr_equal(payload, rfc1042_header))
|
||||||
|
+ skb->protocol = cpu_to_be16((payload[6] << 8) |
|
||||||
|
+ payload[7]);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (ieee80211_is_data_qos(hdr->frame_control)) {
|
||||||
|
+ u8 *p = ieee80211_get_qos_ctl(hdr);
|
||||||
|
+
|
||||||
|
+ skb->priority = *p & IEEE80211_QOS_CTL_TAG1D_MASK;
|
||||||
|
+ }
|
||||||
|
+ skb_set_queue_mapping(skb, ieee802_1d_to_ac[skb->priority]);
|
||||||
|
+
|
||||||
|
+ memset(info, 0, sizeof(*info));
|
||||||
|
+ info->flags = IEEE80211_TX_CTL_REQ_TX_STATUS |
|
||||||
|
+ IEEE80211_TX_CTL_INJECTED;
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * we might have set these flags later.....
|
||||||
|
+ * info->flags &= ~IEEE80211_TX_INTFL_DONT_ENCRYPT;
|
||||||
|
+ * info->flags &= ~IEEE80211_TX_CTL_DONTFRAG;
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+ rcu_read_lock();
|
||||||
|
+
|
||||||
|
+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||||
|
+
|
||||||
|
+ chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
|
||||||
|
+ if (!chanctx_conf)
|
||||||
|
+ goto fail_rcu;
|
||||||
|
+
|
||||||
|
+ info->band = chanctx_conf->def.chan->band;
|
||||||
|
+
|
||||||
|
+ ieee80211_tx_stats(dev, skb->len);
|
||||||
|
+
|
||||||
|
+ ieee80211_xmit(sdata, NULL, skb);
|
||||||
|
+ rcu_read_unlock();
|
||||||
|
+
|
||||||
|
+ return;
|
||||||
|
+fail_rcu:
|
||||||
|
+ rcu_read_unlock();
|
||||||
|
+fail:
|
||||||
|
+ dev_kfree_skb(skb);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * ieee80211_capwap_subif_start_xmit - netif start_xmit function for 802.3 vifs
|
||||||
|
+ * @skb: packet to be sent
|
||||||
|
+ * @dev: incoming interface
|
||||||
|
+ *
|
||||||
|
+ * On failure skb will be freed.
|
||||||
|
+ */
|
||||||
|
+netdev_tx_t ieee80211_capwap_subif_start_xmit(struct sk_buff *skb,
|
||||||
|
+ struct net_device *dev)
|
||||||
|
+{
|
||||||
|
+ if (skb->protocol == htons(ETH_P_CONTROL)) {
|
||||||
|
+ __ieee80211_capwap_inject_start_xmit(skb, dev);
|
||||||
|
+ } else
|
||||||
|
+ __ieee80211_subif_start_xmit(skb, dev, 0);
|
||||||
|
+
|
||||||
|
+ return NETDEV_TX_OK;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
struct sk_buff *
|
||||||
|
ieee80211_build_data_template(struct ieee80211_sub_if_data *sdata,
|
||||||
|
struct sk_buff *skb, u32 info_flags)
|
||||||
|
@@ -3914,3 +4023,180 @@ void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata,
|
||||||
|
ieee80211_xmit(sdata, NULL, skb);
|
||||||
|
local_bh_enable();
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+#ifdef CONFIG_MAC80211_CAPWAP_WTP
|
||||||
|
+
|
||||||
|
+netdev_tx_t ieee80211_inject_xmit(struct sk_buff* skb, struct net_device* dev) {
|
||||||
|
+ int multicast;
|
||||||
|
+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
|
||||||
|
+ struct ieee80211_chanctx_conf *chanctx_conf;
|
||||||
|
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||||
|
+ struct ieee80211_sub_if_data *sdata;
|
||||||
|
+ struct cfg80211_chan_def *chandef;
|
||||||
|
+ struct ieee80211_hdr *hdr;
|
||||||
|
+ int hdrlen;
|
||||||
|
+ int queue_index;
|
||||||
|
+
|
||||||
|
+ /* */
|
||||||
|
+ if (skb->len < hdrlen) {
|
||||||
|
+ goto error;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* */
|
||||||
|
+ skb->dev = dev;
|
||||||
|
+ skb_reset_mac_header(skb);
|
||||||
|
+ skb_reset_network_header(skb);
|
||||||
|
+ skb_reset_transport_header(skb);
|
||||||
|
+
|
||||||
|
+ hdr = (struct ieee80211_hdr *)skb->data;
|
||||||
|
+ hdrlen = ieee80211_hdrlen(hdr->frame_control);
|
||||||
|
+
|
||||||
|
+ if (skb->len < hdrlen) {
|
||||||
|
+ printk(KERN_WARNING "dropping packet (too small)\n");
|
||||||
|
+ goto error;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * Initialize skb->protocol if the injected frame is a data frame
|
||||||
|
+ * carrying a rfc1042 header
|
||||||
|
+ */
|
||||||
|
+ if (ieee80211_is_data(hdr->frame_control) &&
|
||||||
|
+ skb->len >= hdrlen + sizeof(rfc1042_header) + 2) {
|
||||||
|
+ u8 *payload = (u8 *)hdr + hdrlen;
|
||||||
|
+
|
||||||
|
+ if (ether_addr_equal(payload, rfc1042_header))
|
||||||
|
+ skb->protocol = cpu_to_be16((payload[6] << 8) |
|
||||||
|
+ payload[7]);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ memset(info, 0, sizeof(struct ieee80211_tx_info));
|
||||||
|
+
|
||||||
|
+ rcu_read_lock();
|
||||||
|
+
|
||||||
|
+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||||
|
+
|
||||||
|
+ if (sdata->vif.type != NL80211_IFTYPE_AP) {
|
||||||
|
+ printk(KERN_WARNING "dropping packet (not AP)\n");
|
||||||
|
+ goto error_rcu;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
|
||||||
|
+ if (!chanctx_conf) {
|
||||||
|
+ printk(KERN_WARNING "dropping packet (no chanCTX)\n");
|
||||||
|
+ goto error_rcu;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ chandef = &chanctx_conf->def;
|
||||||
|
+
|
||||||
|
+ queue_index = ieee80211_select_queue_80211(sdata, skb, hdr);
|
||||||
|
+ skb_set_queue_mapping(skb, queue_index);
|
||||||
|
+
|
||||||
|
+ info->band = chandef->chan->band;
|
||||||
|
+ info->hw_queue =
|
||||||
|
+ sdata->vif.hw_queue[queue_index];
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * Frame injection is not allowed if beaconing is not allowed
|
||||||
|
+ * or if we need radar detection. Beaconing is usually not allowed when
|
||||||
|
+ * the mode or operation (Adhoc, AP, Mesh) does not support DFS.
|
||||||
|
+ * Passive scan is also used in world regulatory domains where
|
||||||
|
+ * your country is not known and as such it should be treated as
|
||||||
|
+ * NO TX unless the channel is explicitly allowed in which case
|
||||||
|
+ * your current regulatory domain would not have the passive scan
|
||||||
|
+ * flag.
|
||||||
|
+ *
|
||||||
|
+ * Since AP mode uses monitor interfaces to inject/TX management
|
||||||
|
+ * frames we can make AP mode the exception to this rule once it
|
||||||
|
+ * supports radar detection as its implementation can deal with
|
||||||
|
+ * radar detection by itself. We can do that later by adding a
|
||||||
|
+ * monitor flag interfaces used for AP support.
|
||||||
|
+ */
|
||||||
|
+ if (!cfg80211_reg_can_beacon(local->hw.wiphy, chandef,
|
||||||
|
+ sdata->vif.type)) {
|
||||||
|
+ printk(KERN_WARNING "dropping packet (cannot BEACON)\n");
|
||||||
|
+ goto error_rcu;
|
||||||
|
+ }
|
||||||
|
+ /* */
|
||||||
|
+ multicast = is_multicast_ether_addr(hdr->addr1);
|
||||||
|
+ if (!multicast) {
|
||||||
|
+ struct sta_info* sta = sta_info_get(sdata, hdr->addr1);
|
||||||
|
+ if (sta && test_sta_flag(sta, WLAN_STA_AUTHORIZED)) {
|
||||||
|
+ skb->pkt_type = PACKET_OTHERHOST;
|
||||||
|
+ } else {
|
||||||
|
+ printk(KERN_WARNING "dropping packet (STA not authorized)\n");
|
||||||
|
+ goto error_rcu;
|
||||||
|
+ }
|
||||||
|
+ } else {
|
||||||
|
+ if (ether_addr_equal_64bits(hdr->addr1, dev->broadcast)) {
|
||||||
|
+ skb->pkt_type = PACKET_BROADCAST;
|
||||||
|
+ } else {
|
||||||
|
+ skb->pkt_type = PACKET_MULTICAST;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* */
|
||||||
|
+ if (unlikely(!multicast && skb->sk &&
|
||||||
|
+ skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS)) {
|
||||||
|
+ struct sk_buff *ack_skb = skb_clone_sk(skb);
|
||||||
|
+
|
||||||
|
+ if (ack_skb) {
|
||||||
|
+ unsigned long flags;
|
||||||
|
+ int id;
|
||||||
|
+ struct ieee80211_local* local = sdata->local;
|
||||||
|
+
|
||||||
|
+ spin_lock_irqsave(&local->ack_status_lock, flags);
|
||||||
|
+ id = idr_alloc(&local->ack_status_frames, ack_skb,
|
||||||
|
+ 1, 0x10000, GFP_ATOMIC);
|
||||||
|
+ spin_unlock_irqrestore(&local->ack_status_lock, flags);
|
||||||
|
+
|
||||||
|
+ if (id >= 0) {
|
||||||
|
+ info->ack_frame_id = id;
|
||||||
|
+ info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS;
|
||||||
|
+ } else {
|
||||||
|
+ kfree_skb(ack_skb);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+#if 0
|
||||||
|
+ /* If the skb is shared we need to obtain our own copy. */
|
||||||
|
+ if (skb_shared(skb)) {
|
||||||
|
+ struct sk_buff *tmp_skb = skb;
|
||||||
|
+
|
||||||
|
+ /* can't happen -- skb is a clone if info_id != 0 */
|
||||||
|
+ WARN_ON(info->ack_frame_id);
|
||||||
|
+
|
||||||
|
+ skb = skb_clone(skb, GFP_ATOMIC);
|
||||||
|
+ kfree_skb(tmp_skb);
|
||||||
|
+
|
||||||
|
+ if (!skb)
|
||||||
|
+ goto error_rcu;
|
||||||
|
+ }
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+ /* */
|
||||||
|
+ hdr->duration_id = 0;
|
||||||
|
+ hdr->seq_ctrl = 0;
|
||||||
|
+
|
||||||
|
+ /* */
|
||||||
|
+ ieee80211_tx_stats(dev, skb->len);
|
||||||
|
+
|
||||||
|
+ /* */
|
||||||
|
+/* dev->trans_start = jiffies; */
|
||||||
|
+
|
||||||
|
+ /* */
|
||||||
|
+ ieee80211_xmit(sdata, NULL, skb);
|
||||||
|
+ rcu_read_unlock();
|
||||||
|
+
|
||||||
|
+ return NETDEV_TX_OK;
|
||||||
|
+
|
||||||
|
+error_rcu:
|
||||||
|
+ rcu_read_unlock();
|
||||||
|
+
|
||||||
|
+error:
|
||||||
|
+ dev_kfree_skb(skb);
|
||||||
|
+ return NETDEV_TX_OK;
|
||||||
|
+}
|
||||||
|
+EXPORT_SYMBOL(ieee80211_inject_xmit);
|
||||||
|
+
|
||||||
|
+#endif
|
||||||
|
--
|
||||||
|
2.9.3
|
||||||
|
|
703
kernel-patches/mac80211_packet_tunnel-linux-4.8.patch
Normal file
703
kernel-patches/mac80211_packet_tunnel-linux-4.8.patch
Normal file
@ -0,0 +1,703 @@
|
|||||||
|
From c77fede6bca4d81c4db720a0ebcfa3ea6b933161 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Andreas Schultz <aschultz@tpip.net>
|
||||||
|
Date: Thu, 4 Feb 2016 15:57:11 +0100
|
||||||
|
Subject: [PATCH] support patch for FreeWTP
|
||||||
|
|
||||||
|
Allows for kernel side interception and injection of IEEE 802.11 frames.
|
||||||
|
---
|
||||||
|
include/net/mac80211.h | 31 +++++
|
||||||
|
net/mac80211/Kconfig | 7 ++
|
||||||
|
net/mac80211/ieee80211_i.h | 12 ++
|
||||||
|
net/mac80211/iface.c | 63 ++++++++++
|
||||||
|
net/mac80211/rx.c | 96 ++++++++++++---
|
||||||
|
net/mac80211/tx.c | 286 +++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
6 files changed, 481 insertions(+), 14 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
|
||||||
|
index be30b05..cc1f0e8 100644
|
||||||
|
--- a/include/net/mac80211.h
|
||||||
|
+++ b/include/net/mac80211.h
|
||||||
|
@@ -2309,6 +2309,37 @@ ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw,
|
||||||
|
*/
|
||||||
|
void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb);
|
||||||
|
|
||||||
|
+#ifdef CONFIG_MAC80211_CAPWAP_WTP
|
||||||
|
+
|
||||||
|
+extern struct static_key_false mac80211_capwap_wtp;
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ *
|
||||||
|
+ */
|
||||||
|
+struct ieee80211_pcktunnel {
|
||||||
|
+ u16 subtype_mask[3]; /* 0: MGMT, 1: CTLR, 2: DATA */
|
||||||
|
+
|
||||||
|
+ int (*handler)(u32 ifindex, struct sk_buff *skb, int sig_dbm, unsigned char rate, void *data);
|
||||||
|
+ void *data;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ *
|
||||||
|
+ */
|
||||||
|
+int ieee80211_pcktunnel_register(struct net_device *dev, struct ieee80211_pcktunnel *handler);
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ *
|
||||||
|
+ */
|
||||||
|
+int ieee80211_pcktunnel_deregister(struct net_device *dev, struct ieee80211_pcktunnel *handler);
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ *
|
||||||
|
+ */
|
||||||
|
+netdev_tx_t ieee80211_inject_xmit(struct sk_buff* skb, struct net_device* dev);
|
||||||
|
+
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
/**
|
||||||
|
* DOC: Hardware crypto acceleration
|
||||||
|
*
|
||||||
|
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig
|
||||||
|
index 3891cbd..4ff4461 100644
|
||||||
|
--- a/net/mac80211/Kconfig
|
||||||
|
+++ b/net/mac80211/Kconfig
|
||||||
|
@@ -318,3 +318,10 @@ config MAC80211_STA_HASH_MAX_SIZE
|
||||||
|
connect more stations than the number selected here.)
|
||||||
|
|
||||||
|
If unsure, leave the default of 0.
|
||||||
|
+
|
||||||
|
+config MAC80211_CAPWAP_WTP
|
||||||
|
+ bool "Enable support functions for out-of-tree CAPWAP WTP module"
|
||||||
|
+ depends on MAC80211
|
||||||
|
+ ---help---
|
||||||
|
+ Select this to build support hooks for out-of-tree CAPWAP FreeWTP
|
||||||
|
+ module.
|
||||||
|
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
|
||||||
|
index 9438c94..3ec4613 100644
|
||||||
|
--- a/net/mac80211/ieee80211_i.h
|
||||||
|
+++ b/net/mac80211/ieee80211_i.h
|
||||||
|
@@ -180,6 +180,9 @@ typedef unsigned __bitwise__ ieee80211_rx_result;
|
||||||
|
#define RX_DROP_UNUSABLE ((__force ieee80211_rx_result) 1u)
|
||||||
|
#define RX_DROP_MONITOR ((__force ieee80211_rx_result) 2u)
|
||||||
|
#define RX_QUEUED ((__force ieee80211_rx_result) 3u)
|
||||||
|
+#ifdef CONFIG_MAC80211_CAPWAP_WTP
|
||||||
|
+#define RX_IGNORE_MONITOR ((__force ieee80211_rx_result) 4u)
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum ieee80211_packet_rx_flags - packet RX flags
|
||||||
|
@@ -836,6 +839,11 @@ struct ieee80211_sub_if_data {
|
||||||
|
|
||||||
|
char name[IFNAMSIZ];
|
||||||
|
|
||||||
|
+#ifdef CONFIG_MAC80211_CAPWAP_WTP
|
||||||
|
+ /* Packet tunnel handlers */
|
||||||
|
+ struct ieee80211_pcktunnel __rcu *pcktunnel_handlers;
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
/* Fragment table for host-based reassembly */
|
||||||
|
struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX];
|
||||||
|
unsigned int fragment_next;
|
||||||
|
@@ -1655,6 +1663,10 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
|
||||||
|
void __ieee80211_subif_start_xmit(struct sk_buff *skb,
|
||||||
|
struct net_device *dev,
|
||||||
|
u32 info_flags);
|
||||||
|
+#ifdef CONFIG_MAC80211_CAPWAP_WTP
|
||||||
|
+netdev_tx_t ieee80211_capwap_subif_start_xmit(struct sk_buff *skb,
|
||||||
|
+ struct net_device *dev);
|
||||||
|
+#endif
|
||||||
|
void ieee80211_purge_tx_queue(struct ieee80211_hw *hw,
|
||||||
|
struct sk_buff_head *skbs);
|
||||||
|
struct sk_buff *
|
||||||
|
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
|
||||||
|
index c59af3e..c05f4c6 100644
|
||||||
|
--- a/net/mac80211/iface.c
|
||||||
|
+++ b/net/mac80211/iface.c
|
||||||
|
@@ -1966,3 +1966,66 @@ void ieee80211_iface_exit(void)
|
||||||
|
{
|
||||||
|
unregister_netdevice_notifier(&mac80211_netdev_notifier);
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+#ifdef CONFIG_MAC80211_CAPWAP_WTP
|
||||||
|
+
|
||||||
|
+DEFINE_STATIC_KEY_FALSE(mac80211_capwap_wtp);
|
||||||
|
+
|
||||||
|
+static const struct net_device_ops ieee80211_capwapif_ops = {
|
||||||
|
+ .ndo_open = ieee80211_open,
|
||||||
|
+ .ndo_stop = ieee80211_stop,
|
||||||
|
+ .ndo_uninit = ieee80211_uninit,
|
||||||
|
+ .ndo_start_xmit = ieee80211_capwap_subif_start_xmit,
|
||||||
|
+ .ndo_set_rx_mode = ieee80211_set_multicast_list,
|
||||||
|
+ .ndo_change_mtu = ieee80211_change_mtu,
|
||||||
|
+ .ndo_set_mac_address = ieee80211_change_mac,
|
||||||
|
+ .ndo_select_queue = ieee80211_netdev_select_queue,
|
||||||
|
+ .ndo_get_stats64 = ieee80211_get_stats64,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+int ieee80211_pcktunnel_register(struct net_device *dev, struct ieee80211_pcktunnel *handler)
|
||||||
|
+{
|
||||||
|
+ int ret = 0;
|
||||||
|
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||||
|
+
|
||||||
|
+ dev->netdev_ops = &ieee80211_capwapif_ops;
|
||||||
|
+
|
||||||
|
+ mutex_lock(&sdata->local->iflist_mtx);
|
||||||
|
+
|
||||||
|
+ if (rcu_dereference_protected(sdata->pcktunnel_handlers, lockdep_is_held(&sdata->local->iflist_mtx))) {
|
||||||
|
+ ret = -EBUSY;
|
||||||
|
+ } else {
|
||||||
|
+ rcu_assign_pointer(sdata->pcktunnel_handlers, handler);
|
||||||
|
+ static_branch_enable(&mac80211_capwap_wtp);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ mutex_unlock(&sdata->local->iflist_mtx);
|
||||||
|
+ synchronize_net();
|
||||||
|
+
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+EXPORT_SYMBOL(ieee80211_pcktunnel_register);
|
||||||
|
+
|
||||||
|
+int ieee80211_pcktunnel_deregister(struct net_device *dev, struct ieee80211_pcktunnel *handler)
|
||||||
|
+{
|
||||||
|
+ int ret = -ENODEV;
|
||||||
|
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||||
|
+ struct ieee80211_pcktunnel *h;
|
||||||
|
+
|
||||||
|
+ mutex_lock(&sdata->local->iflist_mtx);
|
||||||
|
+
|
||||||
|
+ h = rcu_dereference_protected(sdata->pcktunnel_handlers, lockdep_is_held(&sdata->local->iflist_mtx));
|
||||||
|
+ if (h == handler) {
|
||||||
|
+ ret = 0;
|
||||||
|
+ static_branch_disable(&mac80211_capwap_wtp);
|
||||||
|
+ rcu_assign_pointer(sdata->pcktunnel_handlers, NULL);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ mutex_unlock(&sdata->local->iflist_mtx);
|
||||||
|
+ synchronize_net();
|
||||||
|
+
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+EXPORT_SYMBOL(ieee80211_pcktunnel_deregister);
|
||||||
|
+
|
||||||
|
+#endif
|
||||||
|
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
|
||||||
|
index 5e65e83..4a6d2cd 100644
|
||||||
|
--- a/net/mac80211/rx.c
|
||||||
|
+++ b/net/mac80211/rx.c
|
||||||
|
@@ -3097,6 +3097,56 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx)
|
||||||
|
return RX_QUEUED;
|
||||||
|
}
|
||||||
|
|
||||||
|
+#ifdef CONFIG_MAC80211_CAPWAP_WTP
|
||||||
|
+
|
||||||
|
+static ieee80211_rx_result debug_noinline
|
||||||
|
+ieee80211_rx_h_pcktunnel(struct ieee80211_rx_data *rx, struct ieee80211_rate *rate)
|
||||||
|
+{
|
||||||
|
+ struct ieee80211_pcktunnel *handler;
|
||||||
|
+
|
||||||
|
+ handler = rcu_dereference(rx->sdata->pcktunnel_handlers);
|
||||||
|
+ if (handler) {
|
||||||
|
+ u16 fc;
|
||||||
|
+ u16 fc_type;
|
||||||
|
+ int sig_dbm = 0;
|
||||||
|
+ unsigned char pckrate = 0;
|
||||||
|
+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
|
||||||
|
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
|
||||||
|
+
|
||||||
|
+ if (ieee80211_hw_check(&rx->local->hw, SIGNAL_DBM))
|
||||||
|
+ sig_dbm = status->signal;
|
||||||
|
+
|
||||||
|
+ if (rate && !(status->flag & (RX_FLAG_HT | RX_FLAG_VHT))) {
|
||||||
|
+ int shift = 0;
|
||||||
|
+ if (status->flag & RX_FLAG_10MHZ)
|
||||||
|
+ shift = 1;
|
||||||
|
+ else if (status->flag & RX_FLAG_5MHZ)
|
||||||
|
+ shift = 2;
|
||||||
|
+ pckrate = DIV_ROUND_UP(rate->bitrate, 5 * (1 << shift));
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Retrieve type and subtype packet */
|
||||||
|
+ fc = le16_to_cpu(hdr->frame_control);
|
||||||
|
+ fc_type = ((fc & IEEE80211_FCTL_FTYPE) >> 2);
|
||||||
|
+ if (fc_type < 3) {
|
||||||
|
+ u16 bitmask = 1 << ((fc & IEEE80211_FCTL_STYPE) >> 4);
|
||||||
|
+
|
||||||
|
+ /* Delegate packet to external handler */
|
||||||
|
+ if (handler->subtype_mask[fc_type] & bitmask) {
|
||||||
|
+ if (handler->handler(rx->sdata->dev->ifindex, rx->skb, sig_dbm, pckrate, handler->data)) {
|
||||||
|
+ return RX_IGNORE_MONITOR;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return RX_CONTINUE;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* TODO: use IEEE80211_RX_FRAGMENTED */
|
||||||
|
+
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx,
|
||||||
|
struct ieee80211_rate *rate)
|
||||||
|
{
|
||||||
|
@@ -3176,6 +3226,9 @@ static void ieee80211_rx_handlers_result(struct ieee80211_rx_data *rx,
|
||||||
|
if (rx->sta)
|
||||||
|
rx->sta->rx_stats.dropped++;
|
||||||
|
/* fall through */
|
||||||
|
+#ifdef CONFIG_MAC80211_CAPWAP_WTP
|
||||||
|
+ case RX_IGNORE_MONITOR:
|
||||||
|
+#endif
|
||||||
|
case RX_CONTINUE: {
|
||||||
|
struct ieee80211_rate *rate = NULL;
|
||||||
|
struct ieee80211_supported_band *sband;
|
||||||
|
@@ -3204,7 +3257,9 @@ static void ieee80211_rx_handlers_result(struct ieee80211_rx_data *rx,
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx,
|
||||||
|
- struct sk_buff_head *frames)
|
||||||
|
+ struct sk_buff_head *frames,
|
||||||
|
+ struct ieee80211_rate *rate)
|
||||||
|
+
|
||||||
|
{
|
||||||
|
ieee80211_rx_result res = RX_DROP_MONITOR;
|
||||||
|
struct sk_buff *skb;
|
||||||
|
@@ -3243,6 +3298,15 @@ static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx,
|
||||||
|
if (ieee80211_vif_is_mesh(&rx->sdata->vif))
|
||||||
|
CALL_RXH(ieee80211_rx_h_mesh_fwding);
|
||||||
|
#endif
|
||||||
|
+#ifdef CONFIG_MAC80211_CAPWAP_WTP
|
||||||
|
+ if (static_branch_unlikely(&mac80211_capwap_wtp)) {
|
||||||
|
+ /* special treatment */
|
||||||
|
+ res = ieee80211_rx_h_pcktunnel(rx, rate);
|
||||||
|
+ if (res != RX_CONTINUE)
|
||||||
|
+ goto rxh_next;
|
||||||
|
+ }
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
CALL_RXH(ieee80211_rx_h_amsdu);
|
||||||
|
CALL_RXH(ieee80211_rx_h_data);
|
||||||
|
|
||||||
|
@@ -3266,7 +3330,8 @@ static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx,
|
||||||
|
spin_unlock_bh(&rx->local->rx_path_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
-static void ieee80211_invoke_rx_handlers(struct ieee80211_rx_data *rx)
|
||||||
|
+static void ieee80211_invoke_rx_handlers(struct ieee80211_rx_data *rx,
|
||||||
|
+ struct ieee80211_rate *rate)
|
||||||
|
{
|
||||||
|
struct sk_buff_head reorder_release;
|
||||||
|
ieee80211_rx_result res = RX_DROP_MONITOR;
|
||||||
|
@@ -3285,7 +3350,7 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_rx_data *rx)
|
||||||
|
|
||||||
|
ieee80211_rx_reorder_ampdu(rx, &reorder_release);
|
||||||
|
|
||||||
|
- ieee80211_rx_handlers(rx, &reorder_release);
|
||||||
|
+ ieee80211_rx_handlers(rx, &reorder_release, rate);
|
||||||
|
return;
|
||||||
|
|
||||||
|
rxh_next:
|
||||||
|
@@ -3331,7 +3396,7 @@ void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid)
|
||||||
|
drv_event_callback(rx.local, rx.sdata, &event);
|
||||||
|
}
|
||||||
|
|
||||||
|
- ieee80211_rx_handlers(&rx, &frames);
|
||||||
|
+ ieee80211_rx_handlers(&rx, &frames, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ieee80211_mark_rx_ba_filtered_frames(struct ieee80211_sta *pubsta, u8 tid,
|
||||||
|
@@ -3406,7 +3471,7 @@ void ieee80211_mark_rx_ba_filtered_frames(struct ieee80211_sta *pubsta, u8 tid,
|
||||||
|
release:
|
||||||
|
spin_unlock_bh(&tid_agg_rx->reorder_lock);
|
||||||
|
|
||||||
|
- ieee80211_rx_handlers(&rx, &frames);
|
||||||
|
+ ieee80211_rx_handlers(&rx, &frames, NULL);
|
||||||
|
|
||||||
|
out:
|
||||||
|
rcu_read_unlock();
|
||||||
|
@@ -3878,7 +3943,9 @@ static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx,
|
||||||
|
* or not the skb was consumed.
|
||||||
|
*/
|
||||||
|
static bool ieee80211_prepare_and_rx_handle(struct ieee80211_rx_data *rx,
|
||||||
|
- struct sk_buff *skb, bool consume)
|
||||||
|
+ struct sk_buff *skb,
|
||||||
|
+ struct ieee80211_rate *rate,
|
||||||
|
+ bool consume)
|
||||||
|
{
|
||||||
|
struct ieee80211_local *local = rx->local;
|
||||||
|
struct ieee80211_sub_if_data *sdata = rx->sdata;
|
||||||
|
@@ -3916,7 +3983,7 @@ static bool ieee80211_prepare_and_rx_handle(struct ieee80211_rx_data *rx,
|
||||||
|
rx->skb = skb;
|
||||||
|
}
|
||||||
|
|
||||||
|
- ieee80211_invoke_rx_handlers(rx);
|
||||||
|
+ ieee80211_invoke_rx_handlers(rx, rate);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -3927,7 +3994,8 @@ static bool ieee80211_prepare_and_rx_handle(struct ieee80211_rx_data *rx,
|
||||||
|
static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
|
||||||
|
struct ieee80211_sta *pubsta,
|
||||||
|
struct sk_buff *skb,
|
||||||
|
- struct napi_struct *napi)
|
||||||
|
+ struct napi_struct *napi,
|
||||||
|
+ struct ieee80211_rate *rate)
|
||||||
|
{
|
||||||
|
struct ieee80211_local *local = hw_to_local(hw);
|
||||||
|
struct ieee80211_sub_if_data *sdata;
|
||||||
|
@@ -3973,7 +4041,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
|
||||||
|
if (pubsta) {
|
||||||
|
rx.sta = container_of(pubsta, struct sta_info, sta);
|
||||||
|
rx.sdata = rx.sta->sdata;
|
||||||
|
- if (ieee80211_prepare_and_rx_handle(&rx, skb, true))
|
||||||
|
+ if (ieee80211_prepare_and_rx_handle(&rx, skb, rate, true))
|
||||||
|
return;
|
||||||
|
goto out;
|
||||||
|
} else if (ieee80211_is_data(fc)) {
|
||||||
|
@@ -3992,7 +4060,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
|
||||||
|
|
||||||
|
rx.sta = prev_sta;
|
||||||
|
rx.sdata = prev_sta->sdata;
|
||||||
|
- ieee80211_prepare_and_rx_handle(&rx, skb, false);
|
||||||
|
+ ieee80211_prepare_and_rx_handle(&rx, skb, rate, false);
|
||||||
|
|
||||||
|
prev_sta = sta;
|
||||||
|
}
|
||||||
|
@@ -4001,7 +4069,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
|
||||||
|
rx.sta = prev_sta;
|
||||||
|
rx.sdata = prev_sta->sdata;
|
||||||
|
|
||||||
|
- if (ieee80211_prepare_and_rx_handle(&rx, skb, true))
|
||||||
|
+ if (ieee80211_prepare_and_rx_handle(&rx, skb, rate, true))
|
||||||
|
return;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
@@ -4030,7 +4098,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
|
||||||
|
|
||||||
|
rx.sta = sta_info_get_bss(prev, hdr->addr2);
|
||||||
|
rx.sdata = prev;
|
||||||
|
- ieee80211_prepare_and_rx_handle(&rx, skb, false);
|
||||||
|
+ ieee80211_prepare_and_rx_handle(&rx, skb, rate, false);
|
||||||
|
|
||||||
|
prev = sdata;
|
||||||
|
}
|
||||||
|
@@ -4039,7 +4107,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
|
||||||
|
rx.sta = sta_info_get_bss(prev, hdr->addr2);
|
||||||
|
rx.sdata = prev;
|
||||||
|
|
||||||
|
- if (ieee80211_prepare_and_rx_handle(&rx, skb, true))
|
||||||
|
+ if (ieee80211_prepare_and_rx_handle(&rx, skb, rate, true))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -4152,7 +4220,7 @@ void ieee80211_rx_napi(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta,
|
||||||
|
((struct ieee80211_hdr *)skb->data)->frame_control,
|
||||||
|
skb->len);
|
||||||
|
|
||||||
|
- __ieee80211_rx_handle_packet(hw, pubsta, skb, napi);
|
||||||
|
+ __ieee80211_rx_handle_packet(hw, pubsta, skb, napi, rate);
|
||||||
|
|
||||||
|
rcu_read_unlock();
|
||||||
|
|
||||||
|
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
|
||||||
|
index 2030443..bca96a4 100644
|
||||||
|
--- a/net/mac80211/tx.c
|
||||||
|
+++ b/net/mac80211/tx.c
|
||||||
|
@@ -3213,6 +3213,115 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
|
||||||
|
return NETDEV_TX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
+#ifdef CONFIG_MAC80211_CAPWAP_WTP
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * inject raw 802.11 frame, processing is mostly identical
|
||||||
|
+ * to ieee80211_monitor_start_xmit, except for the different
|
||||||
|
+ * headers
|
||||||
|
+ */
|
||||||
|
+static void __ieee80211_capwap_inject_start_xmit(struct sk_buff *skb,
|
||||||
|
+ struct net_device *dev)
|
||||||
|
+{
|
||||||
|
+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
|
||||||
|
+ struct ieee80211_chanctx_conf *chanctx_conf;
|
||||||
|
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||||
|
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||||
|
+ struct ieee80211_sub_if_data *sdata;
|
||||||
|
+ struct cfg80211_chan_def *chandef;
|
||||||
|
+ int tid;
|
||||||
|
+ int hdrlen;
|
||||||
|
+
|
||||||
|
+ /* check for not even having the fixed 802.11 header */
|
||||||
|
+ if (unlikely(skb->len < sizeof(struct ieee80211_hdr)))
|
||||||
|
+ goto fail; /* too short to be possibly valid */
|
||||||
|
+
|
||||||
|
+ hdrlen = ieee80211_hdrlen(hdr->frame_control);
|
||||||
|
+
|
||||||
|
+ /* does the skb contain enough to deliver on the alleged length? */
|
||||||
|
+ if (unlikely(skb->len < hdrlen))
|
||||||
|
+ goto fail; /* skb too short for claimed header length */
|
||||||
|
+
|
||||||
|
+ skb_set_mac_header(skb, 0);
|
||||||
|
+ /*
|
||||||
|
+ * these are just fixed to the end of the rt area since we
|
||||||
|
+ * don't have any better information and at this point, nobody cares
|
||||||
|
+ */
|
||||||
|
+ skb_set_network_header(skb, hdrlen);
|
||||||
|
+ skb_set_transport_header(skb, hdrlen);
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * Initialize skb->protocol if the injected frame is a data frame
|
||||||
|
+ * carrying a rfc1042 header
|
||||||
|
+ */
|
||||||
|
+ if (ieee80211_is_data(hdr->frame_control) &&
|
||||||
|
+ skb->len >= hdrlen + sizeof(rfc1042_header) + 2) {
|
||||||
|
+ u8 *payload = (u8 *)hdr + hdrlen;
|
||||||
|
+
|
||||||
|
+ if (ether_addr_equal(payload, rfc1042_header))
|
||||||
|
+ skb->protocol = cpu_to_be16((payload[6] << 8) |
|
||||||
|
+ payload[7]);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (ieee80211_is_data_qos(hdr->frame_control)) {
|
||||||
|
+ u8 *p = ieee80211_get_qos_ctl(hdr);
|
||||||
|
+
|
||||||
|
+ skb->priority = *p & IEEE80211_QOS_CTL_TAG1D_MASK;
|
||||||
|
+ }
|
||||||
|
+ skb_set_queue_mapping(skb, ieee802_1d_to_ac[skb->priority]);
|
||||||
|
+
|
||||||
|
+ memset(info, 0, sizeof(*info));
|
||||||
|
+ info->flags = IEEE80211_TX_CTL_REQ_TX_STATUS |
|
||||||
|
+ IEEE80211_TX_CTL_INJECTED;
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * we might have set these flags later.....
|
||||||
|
+ * info->flags &= ~IEEE80211_TX_INTFL_DONT_ENCRYPT;
|
||||||
|
+ * info->flags &= ~IEEE80211_TX_CTL_DONTFRAG;
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+ rcu_read_lock();
|
||||||
|
+
|
||||||
|
+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||||
|
+
|
||||||
|
+ chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
|
||||||
|
+ if (!chanctx_conf)
|
||||||
|
+ goto fail_rcu;
|
||||||
|
+
|
||||||
|
+ info->band = chanctx_conf->def.chan->band;
|
||||||
|
+
|
||||||
|
+ ieee80211_tx_stats(dev, skb->len);
|
||||||
|
+
|
||||||
|
+ ieee80211_xmit(sdata, NULL, skb);
|
||||||
|
+ rcu_read_unlock();
|
||||||
|
+
|
||||||
|
+ return;
|
||||||
|
+fail_rcu:
|
||||||
|
+ rcu_read_unlock();
|
||||||
|
+fail:
|
||||||
|
+ dev_kfree_skb(skb);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * ieee80211_capwap_subif_start_xmit - netif start_xmit function for 802.3 vifs
|
||||||
|
+ * @skb: packet to be sent
|
||||||
|
+ * @dev: incoming interface
|
||||||
|
+ *
|
||||||
|
+ * On failure skb will be freed.
|
||||||
|
+ */
|
||||||
|
+netdev_tx_t ieee80211_capwap_subif_start_xmit(struct sk_buff *skb,
|
||||||
|
+ struct net_device *dev)
|
||||||
|
+{
|
||||||
|
+ if (skb->protocol == htons(ETH_P_CONTROL)) {
|
||||||
|
+ __ieee80211_capwap_inject_start_xmit(skb, dev);
|
||||||
|
+ } else
|
||||||
|
+ __ieee80211_subif_start_xmit(skb, dev, 0);
|
||||||
|
+
|
||||||
|
+ return NETDEV_TX_OK;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
struct sk_buff *
|
||||||
|
ieee80211_build_data_template(struct ieee80211_sub_if_data *sdata,
|
||||||
|
struct sk_buff *skb, u32 info_flags)
|
||||||
|
@@ -4188,3 +4297,180 @@ void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata,
|
||||||
|
ieee80211_xmit(sdata, NULL, skb);
|
||||||
|
local_bh_enable();
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+#ifdef CONFIG_MAC80211_CAPWAP_WTP
|
||||||
|
+
|
||||||
|
+netdev_tx_t ieee80211_inject_xmit(struct sk_buff* skb, struct net_device* dev) {
|
||||||
|
+ int multicast;
|
||||||
|
+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
|
||||||
|
+ struct ieee80211_chanctx_conf *chanctx_conf;
|
||||||
|
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||||
|
+ struct ieee80211_sub_if_data *sdata;
|
||||||
|
+ struct cfg80211_chan_def *chandef;
|
||||||
|
+ struct ieee80211_hdr *hdr;
|
||||||
|
+ int hdrlen;
|
||||||
|
+ int queue_index;
|
||||||
|
+
|
||||||
|
+ /* */
|
||||||
|
+ if (skb->len < hdrlen) {
|
||||||
|
+ goto error;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* */
|
||||||
|
+ skb->dev = dev;
|
||||||
|
+ skb_reset_mac_header(skb);
|
||||||
|
+ skb_reset_network_header(skb);
|
||||||
|
+ skb_reset_transport_header(skb);
|
||||||
|
+
|
||||||
|
+ hdr = (struct ieee80211_hdr *)skb->data;
|
||||||
|
+ hdrlen = ieee80211_hdrlen(hdr->frame_control);
|
||||||
|
+
|
||||||
|
+ if (skb->len < hdrlen) {
|
||||||
|
+ printk(KERN_WARNING "dropping packet (too small)\n");
|
||||||
|
+ goto error;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * Initialize skb->protocol if the injected frame is a data frame
|
||||||
|
+ * carrying a rfc1042 header
|
||||||
|
+ */
|
||||||
|
+ if (ieee80211_is_data(hdr->frame_control) &&
|
||||||
|
+ skb->len >= hdrlen + sizeof(rfc1042_header) + 2) {
|
||||||
|
+ u8 *payload = (u8 *)hdr + hdrlen;
|
||||||
|
+
|
||||||
|
+ if (ether_addr_equal(payload, rfc1042_header))
|
||||||
|
+ skb->protocol = cpu_to_be16((payload[6] << 8) |
|
||||||
|
+ payload[7]);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ memset(info, 0, sizeof(struct ieee80211_tx_info));
|
||||||
|
+
|
||||||
|
+ rcu_read_lock();
|
||||||
|
+
|
||||||
|
+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||||
|
+
|
||||||
|
+ if (sdata->vif.type != NL80211_IFTYPE_AP) {
|
||||||
|
+ printk(KERN_WARNING "dropping packet (not AP)\n");
|
||||||
|
+ goto error_rcu;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
|
||||||
|
+ if (!chanctx_conf) {
|
||||||
|
+ printk(KERN_WARNING "dropping packet (no chanCTX)\n");
|
||||||
|
+ goto error_rcu;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ chandef = &chanctx_conf->def;
|
||||||
|
+
|
||||||
|
+ queue_index = ieee80211_select_queue_80211(sdata, skb, hdr);
|
||||||
|
+ skb_set_queue_mapping(skb, queue_index);
|
||||||
|
+
|
||||||
|
+ info->band = chandef->chan->band;
|
||||||
|
+ info->hw_queue =
|
||||||
|
+ sdata->vif.hw_queue[queue_index];
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * Frame injection is not allowed if beaconing is not allowed
|
||||||
|
+ * or if we need radar detection. Beaconing is usually not allowed when
|
||||||
|
+ * the mode or operation (Adhoc, AP, Mesh) does not support DFS.
|
||||||
|
+ * Passive scan is also used in world regulatory domains where
|
||||||
|
+ * your country is not known and as such it should be treated as
|
||||||
|
+ * NO TX unless the channel is explicitly allowed in which case
|
||||||
|
+ * your current regulatory domain would not have the passive scan
|
||||||
|
+ * flag.
|
||||||
|
+ *
|
||||||
|
+ * Since AP mode uses monitor interfaces to inject/TX management
|
||||||
|
+ * frames we can make AP mode the exception to this rule once it
|
||||||
|
+ * supports radar detection as its implementation can deal with
|
||||||
|
+ * radar detection by itself. We can do that later by adding a
|
||||||
|
+ * monitor flag interfaces used for AP support.
|
||||||
|
+ */
|
||||||
|
+ if (!cfg80211_reg_can_beacon(local->hw.wiphy, chandef,
|
||||||
|
+ sdata->vif.type)) {
|
||||||
|
+ printk(KERN_WARNING "dropping packet (cannot BEACON)\n");
|
||||||
|
+ goto error_rcu;
|
||||||
|
+ }
|
||||||
|
+ /* */
|
||||||
|
+ multicast = is_multicast_ether_addr(hdr->addr1);
|
||||||
|
+ if (!multicast) {
|
||||||
|
+ struct sta_info* sta = sta_info_get(sdata, hdr->addr1);
|
||||||
|
+ if (sta && test_sta_flag(sta, WLAN_STA_AUTHORIZED)) {
|
||||||
|
+ skb->pkt_type = PACKET_OTHERHOST;
|
||||||
|
+ } else {
|
||||||
|
+ printk(KERN_WARNING "dropping packet (STA not authorized)\n");
|
||||||
|
+ goto error_rcu;
|
||||||
|
+ }
|
||||||
|
+ } else {
|
||||||
|
+ if (ether_addr_equal_64bits(hdr->addr1, dev->broadcast)) {
|
||||||
|
+ skb->pkt_type = PACKET_BROADCAST;
|
||||||
|
+ } else {
|
||||||
|
+ skb->pkt_type = PACKET_MULTICAST;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* */
|
||||||
|
+ if (unlikely(!multicast && skb->sk &&
|
||||||
|
+ skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS)) {
|
||||||
|
+ struct sk_buff *ack_skb = skb_clone_sk(skb);
|
||||||
|
+
|
||||||
|
+ if (ack_skb) {
|
||||||
|
+ unsigned long flags;
|
||||||
|
+ int id;
|
||||||
|
+ struct ieee80211_local* local = sdata->local;
|
||||||
|
+
|
||||||
|
+ spin_lock_irqsave(&local->ack_status_lock, flags);
|
||||||
|
+ id = idr_alloc(&local->ack_status_frames, ack_skb,
|
||||||
|
+ 1, 0x10000, GFP_ATOMIC);
|
||||||
|
+ spin_unlock_irqrestore(&local->ack_status_lock, flags);
|
||||||
|
+
|
||||||
|
+ if (id >= 0) {
|
||||||
|
+ info->ack_frame_id = id;
|
||||||
|
+ info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS;
|
||||||
|
+ } else {
|
||||||
|
+ kfree_skb(ack_skb);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+#if 0
|
||||||
|
+ /* If the skb is shared we need to obtain our own copy. */
|
||||||
|
+ if (skb_shared(skb)) {
|
||||||
|
+ struct sk_buff *tmp_skb = skb;
|
||||||
|
+
|
||||||
|
+ /* can't happen -- skb is a clone if info_id != 0 */
|
||||||
|
+ WARN_ON(info->ack_frame_id);
|
||||||
|
+
|
||||||
|
+ skb = skb_clone(skb, GFP_ATOMIC);
|
||||||
|
+ kfree_skb(tmp_skb);
|
||||||
|
+
|
||||||
|
+ if (!skb)
|
||||||
|
+ goto error_rcu;
|
||||||
|
+ }
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+ /* */
|
||||||
|
+ hdr->duration_id = 0;
|
||||||
|
+ hdr->seq_ctrl = 0;
|
||||||
|
+
|
||||||
|
+ /* */
|
||||||
|
+ ieee80211_tx_stats(dev, skb->len);
|
||||||
|
+
|
||||||
|
+ /* */
|
||||||
|
+/* dev->trans_start = jiffies; */
|
||||||
|
+
|
||||||
|
+ /* */
|
||||||
|
+ ieee80211_xmit(sdata, NULL, skb);
|
||||||
|
+ rcu_read_unlock();
|
||||||
|
+
|
||||||
|
+ return NETDEV_TX_OK;
|
||||||
|
+
|
||||||
|
+error_rcu:
|
||||||
|
+ rcu_read_unlock();
|
||||||
|
+
|
||||||
|
+error:
|
||||||
|
+ dev_kfree_skb(skb);
|
||||||
|
+ return NETDEV_TX_OK;
|
||||||
|
+}
|
||||||
|
+EXPORT_SYMBOL(ieee80211_inject_xmit);
|
||||||
|
+
|
||||||
|
+#endif
|
||||||
|
--
|
||||||
|
2.9.3
|
||||||
|
|
@ -21,7 +21,7 @@ index 760bc4d..e80b1af 100644
|
|||||||
*/
|
*/
|
||||||
void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb);
|
void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb);
|
||||||
|
|
||||||
+#ifdef CONFIG_MAC80211_CAPWAP_WTP
|
+#ifdef CPTCFG_MAC80211_CAPWAP_WTP
|
||||||
+
|
+
|
||||||
+extern struct static_key_false mac80211_capwap_wtp;
|
+extern struct static_key_false mac80211_capwap_wtp;
|
||||||
+
|
+
|
||||||
@ -78,7 +78,7 @@ index 6837a46..e96cbff 100644
|
|||||||
#define RX_DROP_UNUSABLE ((__force ieee80211_rx_result) 1u)
|
#define RX_DROP_UNUSABLE ((__force ieee80211_rx_result) 1u)
|
||||||
#define RX_DROP_MONITOR ((__force ieee80211_rx_result) 2u)
|
#define RX_DROP_MONITOR ((__force ieee80211_rx_result) 2u)
|
||||||
#define RX_QUEUED ((__force ieee80211_rx_result) 3u)
|
#define RX_QUEUED ((__force ieee80211_rx_result) 3u)
|
||||||
+#ifdef CONFIG_MAC80211_CAPWAP_WTP
|
+#ifdef CPTCFG_MAC80211_CAPWAP_WTP
|
||||||
+#define RX_IGNORE_MONITOR ((__force ieee80211_rx_result) 4u)
|
+#define RX_IGNORE_MONITOR ((__force ieee80211_rx_result) 4u)
|
||||||
+#endif
|
+#endif
|
||||||
|
|
||||||
@ -88,7 +88,7 @@ index 6837a46..e96cbff 100644
|
|||||||
|
|
||||||
char name[IFNAMSIZ];
|
char name[IFNAMSIZ];
|
||||||
|
|
||||||
+#ifdef CONFIG_MAC80211_CAPWAP_WTP
|
+#ifdef CPTCFG_MAC80211_CAPWAP_WTP
|
||||||
+ /* Packet tunnel handlers */
|
+ /* Packet tunnel handlers */
|
||||||
+ struct ieee80211_pcktunnel __rcu *pcktunnel_handlers;
|
+ struct ieee80211_pcktunnel __rcu *pcktunnel_handlers;
|
||||||
+#endif
|
+#endif
|
||||||
@ -100,7 +100,7 @@ index 6837a46..e96cbff 100644
|
|||||||
void __ieee80211_subif_start_xmit(struct sk_buff *skb,
|
void __ieee80211_subif_start_xmit(struct sk_buff *skb,
|
||||||
struct net_device *dev,
|
struct net_device *dev,
|
||||||
u32 info_flags);
|
u32 info_flags);
|
||||||
+#ifdef CONFIG_MAC80211_CAPWAP_WTP
|
+#ifdef CPTCFG_MAC80211_CAPWAP_WTP
|
||||||
+netdev_tx_t ieee80211_capwap_subif_start_xmit(struct sk_buff *skb,
|
+netdev_tx_t ieee80211_capwap_subif_start_xmit(struct sk_buff *skb,
|
||||||
+ struct net_device *dev);
|
+ struct net_device *dev);
|
||||||
+#endif
|
+#endif
|
||||||
@ -116,7 +116,7 @@ index bcb0a1b..cb08ec2 100644
|
|||||||
unregister_netdevice_notifier(&mac80211_netdev_notifier);
|
unregister_netdevice_notifier(&mac80211_netdev_notifier);
|
||||||
}
|
}
|
||||||
+
|
+
|
||||||
+#ifdef CONFIG_MAC80211_CAPWAP_WTP
|
+#ifdef CPTCFG_MAC80211_CAPWAP_WTP
|
||||||
+
|
+
|
||||||
+DEFINE_STATIC_KEY_FALSE(mac80211_capwap_wtp);
|
+DEFINE_STATIC_KEY_FALSE(mac80211_capwap_wtp);
|
||||||
+
|
+
|
||||||
@ -186,7 +186,7 @@ index a3bb8f7..07b2ff6 100644
|
|||||||
return RX_QUEUED;
|
return RX_QUEUED;
|
||||||
}
|
}
|
||||||
|
|
||||||
+#ifdef CONFIG_MAC80211_CAPWAP_WTP
|
+#ifdef CPTCFG_MAC80211_CAPWAP_WTP
|
||||||
+
|
+
|
||||||
+static ieee80211_rx_result debug_noinline
|
+static ieee80211_rx_result debug_noinline
|
||||||
+ieee80211_rx_h_pcktunnel(struct ieee80211_rx_data *rx, struct ieee80211_rate *rate)
|
+ieee80211_rx_h_pcktunnel(struct ieee80211_rx_data *rx, struct ieee80211_rate *rate)
|
||||||
@ -243,7 +243,7 @@ index a3bb8f7..07b2ff6 100644
|
|||||||
if (rx->sta)
|
if (rx->sta)
|
||||||
rx->sta->rx_stats.dropped++;
|
rx->sta->rx_stats.dropped++;
|
||||||
/* fall through */
|
/* fall through */
|
||||||
+#ifdef CONFIG_MAC80211_CAPWAP_WTP
|
+#ifdef CPTCFG_MAC80211_CAPWAP_WTP
|
||||||
+ case RX_IGNORE_MONITOR:
|
+ case RX_IGNORE_MONITOR:
|
||||||
+#endif
|
+#endif
|
||||||
case RX_CONTINUE: {
|
case RX_CONTINUE: {
|
||||||
@ -264,7 +264,7 @@ index a3bb8f7..07b2ff6 100644
|
|||||||
if (ieee80211_vif_is_mesh(&rx->sdata->vif))
|
if (ieee80211_vif_is_mesh(&rx->sdata->vif))
|
||||||
CALL_RXH(ieee80211_rx_h_mesh_fwding);
|
CALL_RXH(ieee80211_rx_h_mesh_fwding);
|
||||||
#endif
|
#endif
|
||||||
+#ifdef CONFIG_MAC80211_CAPWAP_WTP
|
+#ifdef CPTCFG_MAC80211_CAPWAP_WTP
|
||||||
+ if (static_branch_unlikely(&mac80211_capwap_wtp)) {
|
+ if (static_branch_unlikely(&mac80211_capwap_wtp)) {
|
||||||
+ /* special treatment */
|
+ /* special treatment */
|
||||||
+ res = ieee80211_rx_h_pcktunnel(rx, rate);
|
+ res = ieee80211_rx_h_pcktunnel(rx, rate);
|
||||||
@ -387,7 +387,7 @@ index bdc224d..ee4e7c7 100644
|
|||||||
return NETDEV_TX_OK;
|
return NETDEV_TX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
+#ifdef CONFIG_MAC80211_CAPWAP_WTP
|
+#ifdef CPTCFG_MAC80211_CAPWAP_WTP
|
||||||
+
|
+
|
||||||
+/*
|
+/*
|
||||||
+ * inject raw 802.11 frame, processing is mostly identical
|
+ * inject raw 802.11 frame, processing is mostly identical
|
||||||
@ -504,7 +504,7 @@ index bdc224d..ee4e7c7 100644
|
|||||||
local_bh_enable();
|
local_bh_enable();
|
||||||
}
|
}
|
||||||
+
|
+
|
||||||
+#ifdef CONFIG_MAC80211_CAPWAP_WTP
|
+#ifdef CPTCFG_MAC80211_CAPWAP_WTP
|
||||||
+
|
+
|
||||||
+netdev_tx_t ieee80211_inject_xmit(struct sk_buff* skb, struct net_device* dev) {
|
+netdev_tx_t ieee80211_inject_xmit(struct sk_buff* skb, struct net_device* dev) {
|
||||||
+ int multicast;
|
+ int multicast;
|
||||||
@ -683,3 +683,13 @@ index bdc224d..ee4e7c7 100644
|
|||||||
--
|
--
|
||||||
2.9.3
|
2.9.3
|
||||||
|
|
||||||
|
--- a/.local-symbols
|
||||||
|
+++ b/.local-symbols
|
||||||
|
@@ -42,6 +42,7 @@ LIB80211_CRYPT_CCMP=
|
||||||
|
LIB80211_CRYPT_TKIP=
|
||||||
|
LIB80211_DEBUG=
|
||||||
|
MAC80211=
|
||||||
|
+MAC80211_CAPWAP_WTP=
|
||||||
|
MAC80211_HAS_RC=
|
||||||
|
MAC80211_RC_MINSTREL=
|
||||||
|
MAC80211_RC_MINSTREL_HT=
|
||||||
|
@ -701,3 +701,13 @@ index 2030443..bca96a4 100644
|
|||||||
--
|
--
|
||||||
2.9.3
|
2.9.3
|
||||||
|
|
||||||
|
--- a/.local-symbols
|
||||||
|
+++ b/.local-symbols
|
||||||
|
@@ -42,6 +42,7 @@ LIB80211_CRYPT_CCMP=
|
||||||
|
LIB80211_CRYPT_TKIP=
|
||||||
|
LIB80211_DEBUG=
|
||||||
|
MAC80211=
|
||||||
|
+MAC80211_CAPWAP_WTP=
|
||||||
|
MAC80211_HAS_RC=
|
||||||
|
MAC80211_RC_MINSTREL=
|
||||||
|
MAC80211_RC_MINSTREL_HT=
|
||||||
|
32
openwrt/mac80211_patches/rebuild-patches.sh
Executable file
32
openwrt/mac80211_patches/rebuild-patches.sh
Executable file
@ -0,0 +1,32 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# The OpenWRT patches are for the mac80211 package. They are functional
|
||||||
|
# indentical to the kernel patches but need two modifications.
|
||||||
|
#
|
||||||
|
# 1. CONFIG_ needs to be replaced with CPTCFG_
|
||||||
|
# 2. any new configuration option, need to be patched into .local-symbols
|
||||||
|
#
|
||||||
|
# This script takes the pure kernel patches and make the above modifications.
|
||||||
|
#
|
||||||
|
|
||||||
|
DIR=$(dirname $0)
|
||||||
|
|
||||||
|
rebuild() {
|
||||||
|
sed -e"s|CONFIG_|CPTCFG_|g" $DIR/../../kernel-patches/$1 > $DIR/922-$1
|
||||||
|
cat >> $DIR/922-$1 <<EOF
|
||||||
|
--- a/.local-symbols
|
||||||
|
+++ b/.local-symbols
|
||||||
|
@@ -42,6 +42,7 @@ LIB80211_CRYPT_CCMP=
|
||||||
|
LIB80211_CRYPT_TKIP=
|
||||||
|
LIB80211_DEBUG=
|
||||||
|
MAC80211=
|
||||||
|
+MAC80211_CAPWAP_WTP=
|
||||||
|
MAC80211_HAS_RC=
|
||||||
|
MAC80211_RC_MINSTREL=
|
||||||
|
MAC80211_RC_MINSTREL_HT=
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
for F in $DIR/../../kernel-patches/mac80211_packet_tunnel*patch; do \
|
||||||
|
rebuild $(basename $F); \
|
||||||
|
done
|
Loading…
Reference in New Issue
Block a user