Compare commits

...

12 Commits

Author SHA1 Message Date
Moritz Rosenthal 8e34c700a6 Added definition of GPSACP message element (#10) 2017-05-30 16:19:46 +02:00
Andreas Schultz cc55da831b
release v1.4.1 2016-11-15 15:15:45 +01:00
Tobias Hintze 848b01e53c Merge remote-tracking branch 'gh/split-wtp-patches' 2016-11-15 12:07:27 +01:00
Andreas Schultz 890a2af6bb split STA deletion into immediate and delayed action
When sending a DeAuthentication frame to a STA we have to wait
a bit to make sure the driver has actually delivered the frame.
Once we get the DeAuthetication frame from a STA, we can stop
waiting and delete the STA.
2016-11-11 13:32:44 +01:00
Andreas Schultz bf57c7a336
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.
2016-11-09 11:15:13 +01:00
Andreas Schultz 2f2a287928
remove some left over SmaretCAPWAP messages and AC pieces 2016-11-08 15:01:08 +01:00
Andreas Schultz cd7024568f
update CAPWAP tunnel patches to new static_key API 2016-11-08 14:35:35 +01:00
Tobias Hintze b6417ff793 bump sha1 2016-10-27 11:02:26 +02:00
Tobias Hintze 17c39e441a [build] inject PKG_VERSION as VERSION
* for -V display
2016-10-05 00:06:12 +02:00
Moritz Rosenthal 7e8be72647 Fixed malformed printk statements and did some makeup (#2)
* Fixed malformed printk statements and did some makeup
2016-09-22 17:36:07 +02:00
Tobias Hintze 9d0fe1cc76 [wtp] fix argument parsing
* efd9eedd introduced a bug which made -c unusable
2016-09-22 16:18:28 +02:00
Andreas Schultz 247a65c7d5 correctly handle endianess when parseing RSNE
The length fields in the RSN elements are little endian. We
need to convert then to host order when reading.
2016-09-22 10:36:01 +02:00
20 changed files with 1647 additions and 295 deletions

27
COPYING
View File

@ -1,35 +1,32 @@
SmartCAPWAP -- An Open Source CAPWAP WTP / AC
FreeWTP -- An Open Source CAPWAP WTP
Copyright (C) 2012-2014 Massimo Vellucci <vemax78@gmail.com>
Portions (C) 2016 Travelping GmbH <info@travelping.com>
This distribution contains multiple components, some
of which fall under different licenses. By using SmartCAPWAP
of which fall under different licenses. By using FreeWTP
or any of the bundled components enumerated below, you
agree to be bound by the conditions of the license for
each respective component.
SmartCAPWAP license:
FreeWTP license:
----------------
SmartCAPWAP is distributed under the GPL license version 2.
FreeWTP is distributed under the GPL license version 2.
Libconfig license:
------------
Libconfig is Copyright (C) Mark Lindner, and is licensed under the LGPL.
Libxml2 license:
------------
Libxml2 is Copyright (C) Daniel Veillard, and is licensed under the MIT.
Libjson-c license:
------------
Libjson-c is Copyright (C) Eric Haszlakiewicz, and is licensed under the MIT.
WolfSSL License:
----------------
WolfSSL is Copyright (C) wolfSSL Inc, and is licensed under the GPL license version 2.
WolfSSL is Copyright (C) wolfSSL Inc, and is licensed under the GPL license
version 2.
libev license:
--------------
libev is Copyright (c) 2007,2008,2009,2010,2011,2012,2013 Marc Alexander
Lehmann and is licensed under BSD 2-Clause license.

23
INSTALL
View File

@ -1,12 +1,12 @@
==================================================
HOW TO BUILD AND RUN SmartCAPWAP FOR LINUX SYSTEMS
==================================================
==============================================
HOW TO BUILD AND RUN FreeWTP FOR LINUX SYSTEMS
==============================================
NOTE: To run WTP you must have a wireless card that has Linux driver based on the
Generic IEEE 802.11 Networking Stack (mac80211).
NOTE: To run WTP you must have a wireless card that has Linux driver based
on the Generic IEEE 802.11 Networking Stack (mac80211).
HOW TO BUILD AC AND WTP
HOW TO BUILD THE WTP
=======================
Requirements
@ -15,22 +15,25 @@ Requirements
* automake 1.9 or newer
* autoconf
* libconfig-dev
* libjson0-dev
* libnl-dev
* libtool
* libxml2-dev
* libev 4.22 or newer
* wolfssl 3.8 or newer
Build
-----
Linux Kernel:
Apply the appropriate path from kernel-patches to your kernel, enable
CAPWAP WTP support and rebuild you kernel.
WolfSSL:
./configure --enable-dtls --enable-psk --prefix=/usr/
make
make install
SmartCAPWAP:
FreeWTP:
autoreconf -f -i
./configure
make

View File

@ -3,6 +3,15 @@ FreeWTP
Open Source CAPWAP WTP implementation
Version 1.4.1 - 15 Nov 2016
---------------------------
* fix endianness buf in RSNE processing
* command line fixes/enhances
* updated kernel patches for plain upstream and OpenWRT/LEDE
* remove some left over references to SmartCAPWAP
* fix STA removal (make sure the DeAuthentication frame is sent)
Version 1.4.0 - 22 Aug 2016
---------------------------

View File

@ -6,8 +6,6 @@ This project started as a fork of SmartCAPWAP, but has since dropped the AC part
## STATUS
NOTE: The WTP implementation has been ported to libev
### WTP tested and working features:
* 802.11b
@ -18,6 +16,7 @@ NOTE: The WTP implementation has been ported to libev
* single radio, single WLAN mode
* 802.11n ([draft-ietf-opsawg-capwap-extension-06](https://tools.ietf.org/html/draft-ietf-opsawg-capwap-extension-06))
* WPA2-PSK
* WPA2 Enterprise
Only cards with cfg80211 netlink API are supported. The following devices
have been tested:
@ -27,7 +26,6 @@ have been tested:
### Planned WTP features:
* WPA2 Enterprise
* 802.11r - BSS fast transition
* Hybrid-MAC ([RFC-7494](https://tools.ietf.org/html/rfc7494))
@ -42,16 +40,18 @@ NOTE: To run WTP you must have a wireless card that has Linux driver based on th
* automake 1.9 or newer
* autoconf
* libconfig-dev
* libjson0-dev
* libnl-dev
* libev-dev
* libtool
* libxml2-dev
* wolfssl 3.8 or newer
### Build
Linux Kernel:
Apply the appropriate path from kernel-patches to your kernel, enable
CAPWAP WTP support and rebuild you kernel.
WolfSSL:
./configure --enable-dtls --enable-ipv6 --enable-aesgcm \
@ -71,7 +71,7 @@ FreeWTP:
### Debugging / Tracing
The smartcapwap kernel module defines a number of static ftrace events. For a detailed
The wtp capwap kernel module defines a number of static ftrace events. For a detailed
guide on how to use those, see: https://www.kernel.org/doc/Documentation/trace/ftrace.txt
A sample trace session might lock like this:

66
docs/GPSACP.md Normal file
View File

@ -0,0 +1,66 @@
# GPSACP message
GPSACP messages are defined in [WTP - SCG Reference Points](https://www.hochbahn.de/hochbahn/wcm/connect/de/1d8945fd-174c-447a-85a5-4a8424406b5a/Lieferung%2Bvon%2BWLAN%2BRoutern%2BAB%2B17.12.2016.pdf?MOD=AJPERES&CACHEID=ROOTWORKSPACE.Z18_JH8I1JC0L05M10AEB6TSP430A1-1d8945fd-174c-447a-85a5-4a8424406b5a-lLovXv0) can be sent within WTP Event Requests.
## Definition GPS Last Acquired Position
The GPS Last Acquired Position contains the output of the AT$GPSACP command from an WWAN Modem.
### Format
```
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Timestamp |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| WWAN Id | GPSACP ....
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
```
**Vendor Id** 18681 (Travelping GmbH)
**Type** 15
**Length** >= 5
**Timestamp** The WTPs time when the meassurment was recorded
**WWAN Id** WWAN Interface Id, used to differentiate between multiple WWAN interfaces, MUST be between
one (1) and 16.
**GPSACP** The full output (including the starting $GPSACP) of the AT$GPSACP command the WWAN Interface:
```
$GPSACP:<UTC>,<latitude>,<longitude>,<hdop>,<altitude>,<fix>,<cog>,<spkm>,<spkn>,<date>,<nsat>
<UTC>: HHMMSS
HH: Hour of day (00..23)
MM: Minute (00..59)
SS: Second (00..60)
<latitude>: ddmm.mmmmD
dd: Degree (00..90)
mm.mmmm: Minutes with decimal fraction (00.0000 .. 59.9999)
D: Direction (N|S)
<longitude>: dddmm.mmmmD
dd: Degree (00..180)
mm.mmmm: Minutes with decimal fraction (00.0000 .. 59.9999)
D: Direction (W|E)
<hdop>: xx.x
xx.x: Horizontal dilution of precision in m (00.0..99.9)
<altitude>: xxxx.x
xxxx.x: Altitude above sea level in m (0000.0..9999.9) - Empty value for negative values.
<fix>: x
x: Fix status (0: No fix, 1: 2D, 2: 3D)
<cog>: xxx.x
xxx.x: Course over ground (000.0 .. 359.9)
<spkm>: xxx.x
xxx.x: Horizontal speed in km/h (000.0 .. 999.9)
<spkn>: xxx.x
xxx.x: Horizontal speed in knots (000.0 .. 999.9)
<date>: ddmmyy
dd: Day (01 .. 31)
mm: Month (01 .. 12)
yy: Year (00 .. 99)
<nsat>: xx
xx: Number of satallites in view (00 .. 99)
```

View File

@ -1,90 +0,0 @@
# AC configuration file
version = "1.0";
application: {
standalone = true;
name = "ac 1";
binding = [
"802.11"
];
descriptor: {
maxstations = 20;
maxwtp = 10;
security: {
presharedkey = false;
x509 = false;
};
rmacfiled: {
supported = false;
};
dtlspolicy: {
cleardatachannel = true;
dtlsdatachannel = true;
};
info = (
{ idvendor = 12345; type = "hardware"; value = "1.0"; },
{ idvendor = 33457; type = "software"; value = "2.0"; }
);
};
ecn = "limited";
timer: {
discovery = 20;
echorequest = 30;
decrypterrorreport = 120;
idletimeout = 320;
};
wtpfallback = true;
dtls: {
enable = true;
type = "x509";
presharedkey: {
hint = "esempio";
identity = "prova";
pskkey = "123456";
};
x509: {
calist = "/etc/capwap/ca.crt";
certificate = "/etc/capwap/ac.crt";
privatekey = "/etc/capwap/ac.key";
};
};
network: {
#binding = "eth1";
#listen = "";
transport = "udp";
mtu = 1400;
};
};
backend: {
id = "1";
version = "1.0";
server: (
{ url = "http://127.0.0.1/csoap.php"; }
#{ url = "https://127.0.0.1/csoap.php"; x509: { calist = "/etc/capwap/casoap.crt"; certificate = "/etc/capwap/clientsoap.crt"; privatekey = "/etc/capwap/clientsoap.key"; }; }
);
};
logging: {
enable = true;
level = "debug";
output = (
{ mode = "stdout"; }
);
};

View File

@ -1,76 +0,0 @@
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 1 (0x1)
Signature Algorithm: sha1WithRSAEncryption
Issuer: C=IT, ST=IT, L=Rome, O=SmartCAPWAP, OU=SmartCAPWAP, CN=SmartCAPWAP CA/name=SmartCAPWAP/emailAddress=vemax78@gmail.com
Validity
Not Before: May 15 18:02:09 2014 GMT
Not After : May 12 18:02:09 2024 GMT
Subject: C=IT, ST=IT, L=Rome, O=SmartCAPWAP, OU=SmartCAPWAP, CN=ac1/name=SmartCAPWAP/emailAddress=vemax78@gmail.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (1024 bit)
Modulus:
00:c3:98:2b:82:c3:1b:aa:13:8d:16:e4:d6:7f:c0:
88:d9:f8:2a:52:46:92:be:c2:3d:91:04:07:7a:fb:
c6:d1:3b:cc:8a:a0:c2:cd:25:b8:22:9c:11:c4:d5:
ca:be:23:43:af:76:80:fd:65:bc:38:4b:66:1c:ac:
05:b1:d2:a4:5b:57:ed:c9:62:e3:67:6e:83:37:c1:
cc:38:a7:9b:0b:87:52:da:b1:83:7b:19:4d:99:48:
96:c9:a3:6d:ad:93:8f:62:ee:f1:38:8a:81:99:0e:
27:f6:70:ac:0e:93:06:3b:a4:b9:5c:6c:ed:ab:be:
27:db:52:72:f5:7e:10:36:a5
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
Netscape Cert Type:
SSL Server
Netscape Comment:
Easy-RSA Generated Server Certificate
X509v3 Subject Key Identifier:
C6:FE:48:73:99:7A:9E:24:87:8B:43:F8:13:6F:27:FB:4A:71:4D:22
X509v3 Authority Key Identifier:
keyid:B8:BE:B2:CB:C6:68:BD:0A:BB:E5:BC:DE:AE:56:FE:25:E6:E4:B3:1C
DirName:/C=IT/ST=IT/L=Rome/O=SmartCAPWAP/OU=SmartCAPWAP/CN=SmartCAPWAP CA/name=SmartCAPWAP/emailAddress=vemax78@gmail.com
serial:9A:6A:C6:B2:AA:33:22:C5
X509v3 Extended Key Usage:
TLS Web Server Authentication
X509v3 Key Usage:
Digital Signature, Non Repudiation, Key Encipherment, Data Encipherment
Signature Algorithm: sha1WithRSAEncryption
78:50:cf:ba:f0:b7:98:92:ae:e9:88:ce:10:43:79:22:03:bf:
ad:9f:1b:87:26:00:37:c0:11:21:bd:9e:e9:40:92:1a:0b:50:
a1:de:a5:00:df:8c:4b:5d:6d:09:75:6e:4e:f3:c2:4b:9e:6b:
08:fe:d0:5c:27:98:fe:30:c9:96:a9:b5:2c:dc:ed:0b:c2:2d:
3e:aa:b7:fd:54:be:17:5e:2f:35:5a:f1:8f:ae:49:3b:87:d5:
99:8e:04:3a:e6:33:fd:30:4a:70:ac:34:c5:9c:0a:57:c6:ab:
26:e7:98:bf:5d:ac:13:4a:6b:8e:e3:af:5e:e6:9b:e2:80:80:
b9:ce
-----BEGIN CERTIFICATE-----
MIIEMjCCA5ugAwIBAgIBATANBgkqhkiG9w0BAQUFADCBpjELMAkGA1UEBhMCSVQx
CzAJBgNVBAgTAklUMQ0wCwYDVQQHEwRSb21lMRQwEgYDVQQKEwtTbWFydENBUFdB
UDEUMBIGA1UECxMLU21hcnRDQVBXQVAxFzAVBgNVBAMTDlNtYXJ0Q0FQV0FQIENB
MRQwEgYDVQQpEwtTbWFydENBUFdBUDEgMB4GCSqGSIb3DQEJARYRdmVtYXg3OEBn
bWFpbC5jb20wHhcNMTQwNTE1MTgwMjA5WhcNMjQwNTEyMTgwMjA5WjCBmzELMAkG
A1UEBhMCSVQxCzAJBgNVBAgTAklUMQ0wCwYDVQQHEwRSb21lMRQwEgYDVQQKEwtT
bWFydENBUFdBUDEUMBIGA1UECxMLU21hcnRDQVBXQVAxDDAKBgNVBAMTA2FjMTEU
MBIGA1UEKRMLU21hcnRDQVBXQVAxIDAeBgkqhkiG9w0BCQEWEXZlbWF4NzhAZ21h
aWwuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDDmCuCwxuqE40W5NZ/
wIjZ+CpSRpK+wj2RBAd6+8bRO8yKoMLNJbginBHE1cq+I0OvdoD9Zbw4S2YcrAWx
0qRbV+3JYuNnboM3wcw4p5sLh1LasYN7GU2ZSJbJo22tk49i7vE4ioGZDif2cKwO
kwY7pLlcbO2rvifbUnL1fhA2pQIDAQABo4IBdzCCAXMwCQYDVR0TBAIwADARBglg
hkgBhvhCAQEEBAMCBkAwNAYJYIZIAYb4QgENBCcWJUVhc3ktUlNBIEdlbmVyYXRl
ZCBTZXJ2ZXIgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFMb+SHOZep4kh4tD+BNvJ/tK
cU0iMIHbBgNVHSMEgdMwgdCAFLi+ssvGaL0Ku+W83q5W/iXm5LMcoYGspIGpMIGm
MQswCQYDVQQGEwJJVDELMAkGA1UECBMCSVQxDTALBgNVBAcTBFJvbWUxFDASBgNV
BAoTC1NtYXJ0Q0FQV0FQMRQwEgYDVQQLEwtTbWFydENBUFdBUDEXMBUGA1UEAxMO
U21hcnRDQVBXQVAgQ0ExFDASBgNVBCkTC1NtYXJ0Q0FQV0FQMSAwHgYJKoZIhvcN
AQkBFhF2ZW1heDc4QGdtYWlsLmNvbYIJAJpqxrKqMyLFMBMGA1UdJQQMMAoGCCsG
AQUFBwMBMAsGA1UdDwQEAwIE8DANBgkqhkiG9w0BAQUFAAOBgQB4UM+68LeYkq7p
iM4QQ3kiA7+tnxuHJgA3wBEhvZ7pQJIaC1Ch3qUA34xLXW0JdW5O88JLnmsI/tBc
J5j+MMmWqbUs3O0Lwi0+qrf9VL4XXi81WvGPrkk7h9WZjgQ65jP9MEpwrDTFnApX
xqsm55i/XawTSmuO469e5pvigIC5zg==
-----END CERTIFICATE-----

View File

@ -1,16 +0,0 @@
-----BEGIN PRIVATE KEY-----
MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAMOYK4LDG6oTjRbk
1n/AiNn4KlJGkr7CPZEEB3r7xtE7zIqgws0luCKcEcTVyr4jQ692gP1lvDhLZhys
BbHSpFtX7cli42dugzfBzDinmwuHUtqxg3sZTZlIlsmjba2Tj2Lu8TiKgZkOJ/Zw
rA6TBjukuVxs7au+J9tScvV+EDalAgMBAAECgYBh1N8OjKBttVHAvb08MQVCYQpq
FLqZh3Zb7nP/Y6fSR+LLBBXrno43YXDRz02VRPY58UAbfqNiVPRCKxi+FOn3li5l
LN9ad1S510MNg652vpKFnCQjpHDrxOQPxQHGc0XNeF4Xo12IhFxh0DbktloC3/Og
PXL0UdvMhZ+X0ErQEQJBAOqLxRYeUSB9HeSFcgNejd0wkM7DKoNyFmJ0jwEb46vO
mKJuA4CFbinX6PZfei8nXbZIBN5p3IS0TA7MU/b+erMCQQDVfEsfmEPUYx7M1oec
rT4+AeSO7KzcC83zeVEmEljwP3zvbM8gn7PLsJAU3K0HEh6scocP6UosTI4o6Ohw
ppVHAkEAsjCp9RnnTKWBlmIDsqedY9RHz63amK6ObxJaqt8DYz28HHs0UeoNPeD4
7mSvMS/ZNGkWudr3XCKWPg/iIp5HnQJBAMALdtzuMZ5+qDdmiUn1QrevJjc4S2wL
pnJu4QQZny5IPpB3VoCniasjowlRVsm0kClbQYqbt2DQYVYF5wtnn4MCQQCz7Rcj
eEZN1STdLv6K03cWKW8nqk+yLgsDFOZpzhIq5ezk/oEX38+1k/KCqwy+9xlQ/oJJ
5lGEUmKCh2XYCBcq
-----END PRIVATE KEY-----

View 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

View 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

View File

@ -29,4 +29,4 @@ module_exit(smartcapwap_wtp_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Massimo Vellucci <vemax78@gmail.com>");
MODULE_DESCRIPTION("SmartCAPWAP WTP Data Channel Module");
MODULE_DESCRIPTION("FreeWTP CAPWAP Data Channel Module");

View File

@ -178,7 +178,7 @@ static struct sc_netlink_device* sc_netlink_new_device(struct net *net, uint32_t
}
/* disable IPv6 on this iface */
printk("SmartCAPWAP: disabling IPv6 on %s\n", dev->name);
printk("CAPWAP: disabling IPv6 on %s\n", dev->name);
idev->cnf.disable_ipv6 = 1;
/* Create device */
@ -996,7 +996,7 @@ int __init sc_netlink_init(void) {
if (ret)
goto unreg_genl_family;
pr_info("smartCAPWAP module loaded\n");
pr_info("CAPWAP WTP module loaded\n");
return 0;
unreg_genl_family:
@ -1006,7 +1006,7 @@ unreg_netdev_notifier:
unreg_pernet:
unregister_pernet_subsys(&sc_net_ops);
error_out:
pr_err("error loading smartCAPWAP module\n");
pr_err("error loading CAPWAP WTP module\n");
return ret;
}

View File

@ -14,7 +14,7 @@ PKG_RELEASE:=1
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=https://github.com/travelping/freewtp.git
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
PKG_SOURCE_VERSION:=a631f89729604f77a4907e5597bf15dd916f1e33
PKG_SOURCE_VERSION:=17c39e441ad7860acb211d08d8fb7eb60a84cb35
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
@ -63,6 +63,7 @@ endef
TARGET_CFLAGS += -I$(STAGING_DIR)/usr/include/libnl3
define Build/Compile/wtp
printf '#undef VERSION\n#define VERSION "'$(PKG_VERSION)'"\n' >> $(PKG_BUILD_DIR)/lib/config.h
$(MAKE) -C $(PKG_BUILD_DIR) \
$(TARGET_CONFIGURE_OPTS) \
all

View File

@ -1,4 +1,4 @@
From abc84789bd6d42fdbfe598d72177ed41d54c7bcf Mon Sep 17 00:00:00 2001
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
@ -14,16 +14,16 @@ Allows for kernel side interception and injection of IEEE 802.11 frames.
6 files changed, 479 insertions(+), 12 deletions(-)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 760bc4d..bf60d9d 100644
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
+#ifdef CPTCFG_MAC80211_CAPWAP_WTP
+
+extern struct static_key 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_MONITOR ((__force ieee80211_rx_result) 2u)
#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)
+#endif
@ -88,7 +88,7 @@ index 6837a46..e96cbff 100644
char name[IFNAMSIZ];
+#ifdef CONFIG_MAC80211_CAPWAP_WTP
+#ifdef CPTCFG_MAC80211_CAPWAP_WTP
+ /* Packet tunnel handlers */
+ struct ieee80211_pcktunnel __rcu *pcktunnel_handlers;
+#endif
@ -100,7 +100,7 @@ index 6837a46..e96cbff 100644
void __ieee80211_subif_start_xmit(struct sk_buff *skb,
struct net_device *dev,
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,
+ struct net_device *dev);
+#endif
@ -108,7 +108,7 @@ index 6837a46..e96cbff 100644
struct sk_buff_head *skbs);
struct sk_buff *
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index bcb0a1b..8e2069f 100644
index bcb0a1b..cb08ec2 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -1955,3 +1955,66 @@ void ieee80211_iface_exit(void)
@ -116,9 +116,9 @@ index bcb0a1b..8e2069f 100644
unregister_netdevice_notifier(&mac80211_netdev_notifier);
}
+
+#ifdef CONFIG_MAC80211_CAPWAP_WTP
+#ifdef CPTCFG_MAC80211_CAPWAP_WTP
+
+struct static_key mac80211_capwap_wtp __read_mostly;
+DEFINE_STATIC_KEY_FALSE(mac80211_capwap_wtp);
+
+static const struct net_device_ops ieee80211_capwapif_ops = {
+ .ndo_open = ieee80211_open,
@ -145,7 +145,7 @@ index bcb0a1b..8e2069f 100644
+ ret = -EBUSY;
+ } else {
+ rcu_assign_pointer(sdata->pcktunnel_handlers, handler);
+ static_key_slow_inc(&mac80211_capwap_wtp);
+ static_branch_enable(&mac80211_capwap_wtp);
+ }
+
+ mutex_unlock(&sdata->local->iflist_mtx);
@ -166,7 +166,7 @@ index bcb0a1b..8e2069f 100644
+ h = rcu_dereference_protected(sdata->pcktunnel_handlers, lockdep_is_held(&sdata->local->iflist_mtx));
+ if (h == handler) {
+ ret = 0;
+ static_key_slow_dec(&mac80211_capwap_wtp);
+ static_branch_disable(&mac80211_capwap_wtp);
+ rcu_assign_pointer(sdata->pcktunnel_handlers, NULL);
+ }
+
@ -179,14 +179,14 @@ index bcb0a1b..8e2069f 100644
+
+#endif
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index a3bb8f7..cbe0642 100644
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
+#ifdef CPTCFG_MAC80211_CAPWAP_WTP
+
+static ieee80211_rx_result debug_noinline
+ieee80211_rx_h_pcktunnel(struct ieee80211_rx_data *rx, struct ieee80211_rate *rate)
@ -243,7 +243,7 @@ index a3bb8f7..cbe0642 100644
if (rx->sta)
rx->sta->rx_stats.dropped++;
/* fall through */
+#ifdef CONFIG_MAC80211_CAPWAP_WTP
+#ifdef CPTCFG_MAC80211_CAPWAP_WTP
+ case RX_IGNORE_MONITOR:
+#endif
case RX_CONTINUE: {
@ -264,8 +264,8 @@ index a3bb8f7..cbe0642 100644
if (ieee80211_vif_is_mesh(&rx->sdata->vif))
CALL_RXH(ieee80211_rx_h_mesh_fwding);
#endif
+#ifdef CONFIG_MAC80211_CAPWAP_WTP
+ if (static_key_false(&mac80211_capwap_wtp)) {
+#ifdef CPTCFG_MAC80211_CAPWAP_WTP
+ if (static_branch_unlikely(&mac80211_capwap_wtp)) {
+ /* special treatment */
+ res = ieee80211_rx_h_pcktunnel(rx, rate);
+ if (res != RX_CONTINUE)
@ -380,14 +380,14 @@ index a3bb8f7..cbe0642 100644
rcu_read_unlock();
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index bdc224d..5f1f424 100644
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
+#ifdef CPTCFG_MAC80211_CAPWAP_WTP
+
+/*
+ * inject raw 802.11 frame, processing is mostly identical
@ -504,7 +504,7 @@ index bdc224d..5f1f424 100644
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) {
+ int multicast;
@ -532,7 +532,7 @@ index bdc224d..5f1f424 100644
+ hdrlen = ieee80211_hdrlen(hdr->frame_control);
+
+ if (skb->len < hdrlen) {
+ printk(KERN_WARNING, "droping packet for TO SMALL");
+ printk(KERN_WARNING "dropping packet (too small)\n");
+ goto error;
+ }
+
@ -556,13 +556,13 @@ index bdc224d..5f1f424 100644
+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+ if (sdata->vif.type != NL80211_IFTYPE_AP) {
+ printk(KERN_WARNING, "droping packet for NOT 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, "droping packet for NO CHANTX");
+ printk(KERN_WARNING "dropping packet (no chanCTX)\n");
+ goto error_rcu;
+ }
+
@ -593,7 +593,7 @@ index bdc224d..5f1f424 100644
+ */
+ if (!cfg80211_reg_can_beacon(local->hw.wiphy, chandef,
+ sdata->vif.type)) {
+ printk(KERN_WARNING, "droping packet for CAN NOT BEACON");
+ printk(KERN_WARNING "dropping packet (cannot BEACON)\n");
+ goto error_rcu;
+ }
+ /* */
@ -603,7 +603,7 @@ index bdc224d..5f1f424 100644
+ if (sta && test_sta_flag(sta, WLAN_STA_AUTHORIZED)) {
+ skb->pkt_type = PACKET_OTHERHOST;
+ } else {
+ printk(KERN_WARNING, "droping packet for STA not AUTHORIZED");
+ printk(KERN_WARNING "dropping packet (STA not authorized)\n");
+ goto error_rcu;
+ }
+ } else {
@ -683,3 +683,13 @@ index bdc224d..5f1f424 100644
--
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=

View File

@ -1,4 +1,4 @@
From 0829e230256d8f18c2d482923d16d3582311221f Mon Sep 17 00:00:00 2001
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
@ -13,15 +13,17 @@ Allows for kernel side interception and injection of IEEE 802.11 frames.
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
@@ -2323,6 +2323,37 @@ ieee80211_get_alt_retry_rate(const struc
@@ -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 CPTCFG_MAC80211_CAPWAP_WTP
+
+extern struct static_key mac80211_capwap_wtp;
+extern struct static_key_false mac80211_capwap_wtp;
+
+/**
+ *
@ -53,9 +55,11 @@ Allows for kernel side interception and injection of IEEE 802.11 frames.
/**
* 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
@@ -317,3 +317,10 @@ config MAC80211_STA_HASH_MAX_SIZE
@@ -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.
@ -66,9 +70,11 @@ Allows for kernel side interception and injection of IEEE 802.11 frames.
+ ---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
@@ -182,6 +182,9 @@ typedef unsigned __bitwise__ ieee80211_r
@@ -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)
@ -78,7 +84,7 @@ Allows for kernel side interception and injection of IEEE 802.11 frames.
/**
* enum ieee80211_packet_rx_flags - packet RX flags
@@ -847,6 +850,11 @@ struct ieee80211_sub_if_data {
@@ -836,6 +839,11 @@ struct ieee80211_sub_if_data {
char name[IFNAMSIZ];
@ -90,7 +96,7 @@ Allows for kernel side interception and injection of IEEE 802.11 frames.
/* Fragment table for host-based reassembly */
struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX];
unsigned int fragment_next;
@@ -1696,6 +1704,10 @@ netdev_tx_t ieee80211_subif_start_xmit(s
@@ -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);
@ -101,16 +107,18 @@ Allows for kernel side interception and injection of IEEE 802.11 frames.
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
@@ -2001,3 +2001,66 @@ void ieee80211_iface_exit(void)
@@ -1966,3 +1966,66 @@ void ieee80211_iface_exit(void)
{
unregister_netdevice_notifier(&mac80211_netdev_notifier);
}
+
+#ifdef CPTCFG_MAC80211_CAPWAP_WTP
+
+struct static_key mac80211_capwap_wtp __read_mostly;
+DEFINE_STATIC_KEY_FALSE(mac80211_capwap_wtp);
+
+static const struct net_device_ops ieee80211_capwapif_ops = {
+ .ndo_open = ieee80211_open,
@ -137,7 +145,7 @@ Allows for kernel side interception and injection of IEEE 802.11 frames.
+ ret = -EBUSY;
+ } else {
+ rcu_assign_pointer(sdata->pcktunnel_handlers, handler);
+ static_key_slow_inc(&mac80211_capwap_wtp);
+ static_branch_enable(&mac80211_capwap_wtp);
+ }
+
+ mutex_unlock(&sdata->local->iflist_mtx);
@ -158,7 +166,7 @@ Allows for kernel side interception and injection of IEEE 802.11 frames.
+ h = rcu_dereference_protected(sdata->pcktunnel_handlers, lockdep_is_held(&sdata->local->iflist_mtx));
+ if (h == handler) {
+ ret = 0;
+ static_key_slow_dec(&mac80211_capwap_wtp);
+ static_branch_disable(&mac80211_capwap_wtp);
+ rcu_assign_pointer(sdata->pcktunnel_handlers, NULL);
+ }
+
@ -170,9 +178,11 @@ Allows for kernel side interception and injection of IEEE 802.11 frames.
+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_
@@ -3097,6 +3097,56 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx)
return RX_QUEUED;
}
@ -229,7 +239,7 @@ Allows for kernel side interception and injection of IEEE 802.11 frames.
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
@@ -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 */
@ -239,7 +249,7 @@ Allows for kernel side interception and injection of IEEE 802.11 frames.
case RX_CONTINUE: {
struct ieee80211_rate *rate = NULL;
struct ieee80211_supported_band *sband;
@@ -3204,7 +3257,9 @@ static void ieee80211_rx_handlers_result
@@ -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,
@ -250,12 +260,12 @@ Allows for kernel side interception and injection of IEEE 802.11 frames.
{
ieee80211_rx_result res = RX_DROP_MONITOR;
struct sk_buff *skb;
@@ -3243,6 +3298,15 @@ static void ieee80211_rx_handlers(struct
@@ -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 CPTCFG_MAC80211_CAPWAP_WTP
+ if (static_key_false(&mac80211_capwap_wtp)) {
+ if (static_branch_unlikely(&mac80211_capwap_wtp)) {
+ /* special treatment */
+ res = ieee80211_rx_h_pcktunnel(rx, rate);
+ if (res != RX_CONTINUE)
@ -266,7 +276,7 @@ Allows for kernel side interception and injection of IEEE 802.11 frames.
CALL_RXH(ieee80211_rx_h_amsdu);
CALL_RXH(ieee80211_rx_h_data);
@@ -3266,7 +3330,8 @@ static void ieee80211_rx_handlers(struct
@@ -3266,7 +3330,8 @@ static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx,
spin_unlock_bh(&rx->local->rx_path_lock);
}
@ -276,7 +286,7 @@ Allows for kernel side interception and injection of IEEE 802.11 frames.
{
struct sk_buff_head reorder_release;
ieee80211_rx_result res = RX_DROP_MONITOR;
@@ -3285,7 +3350,7 @@ static void ieee80211_invoke_rx_handlers
@@ -3285,7 +3350,7 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_rx_data *rx)
ieee80211_rx_reorder_ampdu(rx, &reorder_release);
@ -285,7 +295,7 @@ Allows for kernel side interception and injection of IEEE 802.11 frames.
return;
rxh_next:
@@ -3331,7 +3396,7 @@ void ieee80211_release_reorder_timeout(s
@@ -3331,7 +3396,7 @@ void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid)
drv_event_callback(rx.local, rx.sdata, &event);
}
@ -294,7 +304,7 @@ Allows for kernel side interception and injection of IEEE 802.11 frames.
}
void ieee80211_mark_rx_ba_filtered_frames(struct ieee80211_sta *pubsta, u8 tid,
@@ -3406,7 +3471,7 @@ void ieee80211_mark_rx_ba_filtered_frame
@@ -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);
@ -303,7 +313,7 @@ Allows for kernel side interception and injection of IEEE 802.11 frames.
out:
rcu_read_unlock();
@@ -3878,7 +3943,9 @@ static bool ieee80211_invoke_fast_rx(str
@@ -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,
@ -314,7 +324,7 @@ Allows for kernel side interception and injection of IEEE 802.11 frames.
{
struct ieee80211_local *local = rx->local;
struct ieee80211_sub_if_data *sdata = rx->sdata;
@@ -3916,7 +3983,7 @@ static bool ieee80211_prepare_and_rx_han
@@ -3916,7 +3983,7 @@ static bool ieee80211_prepare_and_rx_handle(struct ieee80211_rx_data *rx,
rx->skb = skb;
}
@ -323,7 +333,7 @@ Allows for kernel side interception and injection of IEEE 802.11 frames.
return true;
}
@@ -3927,7 +3994,8 @@ static bool ieee80211_prepare_and_rx_han
@@ -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,
@ -333,7 +343,7 @@ Allows for kernel side interception and injection of IEEE 802.11 frames.
{
struct ieee80211_local *local = hw_to_local(hw);
struct ieee80211_sub_if_data *sdata;
@@ -3973,7 +4041,7 @@ static void __ieee80211_rx_handle_packet
@@ -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;
@ -342,7 +352,7 @@ Allows for kernel side interception and injection of IEEE 802.11 frames.
return;
goto out;
} else if (ieee80211_is_data(fc)) {
@@ -3992,7 +4060,7 @@ static void __ieee80211_rx_handle_packet
@@ -3992,7 +4060,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
rx.sta = prev_sta;
rx.sdata = prev_sta->sdata;
@ -351,7 +361,7 @@ Allows for kernel side interception and injection of IEEE 802.11 frames.
prev_sta = sta;
}
@@ -4001,7 +4069,7 @@ static void __ieee80211_rx_handle_packet
@@ -4001,7 +4069,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
rx.sta = prev_sta;
rx.sdata = prev_sta->sdata;
@ -360,7 +370,7 @@ Allows for kernel side interception and injection of IEEE 802.11 frames.
return;
goto out;
}
@@ -4030,7 +4098,7 @@ static void __ieee80211_rx_handle_packet
@@ -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;
@ -369,7 +379,7 @@ Allows for kernel side interception and injection of IEEE 802.11 frames.
prev = sdata;
}
@@ -4039,7 +4107,7 @@ static void __ieee80211_rx_handle_packet
@@ -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;
@ -378,7 +388,7 @@ Allows for kernel side interception and injection of IEEE 802.11 frames.
return;
}
@@ -4152,7 +4220,7 @@ void ieee80211_rx_napi(struct ieee80211_
@@ -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);
@ -387,9 +397,11 @@ Allows for kernel side interception and injection of IEEE 802.11 frames.
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
@@ -3434,6 +3434,115 @@ netdev_tx_t ieee80211_subif_start_xmit(s
@@ -3213,6 +3213,115 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
return NETDEV_TX_OK;
}
@ -505,7 +517,7 @@ Allows for kernel side interception and injection of IEEE 802.11 frames.
struct sk_buff *
ieee80211_build_data_template(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb, u32 info_flags)
@@ -4409,3 +4518,180 @@ void __ieee80211_tx_skb_tid_band(struct
@@ -4188,3 +4297,180 @@ void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata,
ieee80211_xmit(sdata, NULL, skb);
local_bh_enable();
}
@ -538,7 +550,7 @@ Allows for kernel side interception and injection of IEEE 802.11 frames.
+ hdrlen = ieee80211_hdrlen(hdr->frame_control);
+
+ if (skb->len < hdrlen) {
+ printk(KERN_WARNING, "droping packet for TO SMALL");
+ printk(KERN_WARNING "dropping packet (too small)\n");
+ goto error;
+ }
+
@ -562,13 +574,13 @@ Allows for kernel side interception and injection of IEEE 802.11 frames.
+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+ if (sdata->vif.type != NL80211_IFTYPE_AP) {
+ printk(KERN_WARNING, "droping packet for NOT 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, "droping packet for NO CHANTX");
+ printk(KERN_WARNING "dropping packet (no chanCTX)\n");
+ goto error_rcu;
+ }
+
@ -599,7 +611,7 @@ Allows for kernel side interception and injection of IEEE 802.11 frames.
+ */
+ if (!cfg80211_reg_can_beacon(local->hw.wiphy, chandef,
+ sdata->vif.type)) {
+ printk(KERN_WARNING, "droping packet for CAN NOT BEACON");
+ printk(KERN_WARNING "dropping packet (cannot BEACON)\n");
+ goto error_rcu;
+ }
+ /* */
@ -609,7 +621,7 @@ Allows for kernel side interception and injection of IEEE 802.11 frames.
+ if (sta && test_sta_flag(sta, WLAN_STA_AUTHORIZED)) {
+ skb->pkt_type = PACKET_OTHERHOST;
+ } else {
+ printk(KERN_WARNING, "droping packet for STA not AUTHORIZED");
+ printk(KERN_WARNING "dropping packet (STA not authorized)\n");
+ goto error_rcu;
+ }
+ } else {
@ -686,6 +698,9 @@ Allows for kernel side interception and injection of IEEE 802.11 frames.
+EXPORT_SYMBOL(ieee80211_inject_xmit);
+
+#endif
--
2.9.3
--- a/.local-symbols
+++ b/.local-symbols
@@ -42,6 +42,7 @@ LIB80211_CRYPT_CCMP=

View 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

View File

@ -387,6 +387,20 @@ static void wifi_station_clean(struct wifi_station* station)
station->supportedratescount = 0;
}
/* */
static void wifi_station_schedule_delete(struct wifi_station* station)
{
ASSERT(station != NULL);
/* */
log_printf(LOG_INFO, "Schedule Delete station: " MACSTR, MAC2STR(station->address));
/* Delay delete station */
station->timeout_action = WIFI_STATION_TIMEOUT_ACTION_DELETE;
station->timeout.repeat = WIFI_STATION_TIMEOUT_AFTER_DEAUTHENTICATED / 1000.0;
ev_timer_again(EV_DEFAULT_UC_ &station->timeout);
}
/* */
static void wifi_station_delete(struct wifi_station* station)
{
@ -395,13 +409,9 @@ static void wifi_station_delete(struct wifi_station* station)
/* */
log_printf(LOG_INFO, "Delete station: " MACSTR, MAC2STR(station->address));
/* */
/* Free station into hash callback function */
wifi_station_clean(station);
/* Delay delete station */
station->timeout_action = WIFI_STATION_TIMEOUT_ACTION_DELETE;
station->timeout.repeat = WIFI_STATION_TIMEOUT_AFTER_DEAUTHENTICATED / 1000.0;
ev_timer_again(EV_DEFAULT_UC_ &station->timeout);
capwap_hash_delete(g_wifiglobal.stations, station->address);
}
/* */
@ -508,7 +518,7 @@ static void wifi_wlan_deauthentication_station(struct wifi_wlan* wlan,
wifi_wlan_send_mgmt_deauthentication(wlan, station->address, reasoncode);
/* delete station */
wifi_station_delete(station);
wifi_station_schedule_delete(station);
}
/* */
@ -585,9 +595,7 @@ static void wifi_station_timeout(EV_P_ ev_timer *w, int revents)
station->timeout_action);
if (station->timeout_action == WIFI_STATION_TIMEOUT_ACTION_DELETE) {
/* Free station into hash callback function */
wifi_station_clean(station);
capwap_hash_delete(g_wifiglobal.stations, station->address);
wifi_station_delete(station);
return;
}
@ -1574,7 +1582,7 @@ wifi_wlan_receive_ac_mgmt_deauthentication(struct wifi_wlan* wlan,
/* Delete station */
station = wifi_station_get(wlan, frame->da);
if (station)
wifi_station_delete(station);
wifi_station_schedule_delete(station);
return 1;
}

View File

@ -1,3 +1,5 @@
#include <endian.h>
#include "wtp.h"
#include "array.h"
#include "list.h"
@ -903,7 +905,7 @@ static int nl80211_wlan_setbeacon(struct wifi_wlan* wlan) {
nla_put_u32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP, ntohl(*(uint32_t *)data));
data += sizeof(uint32_t);
suites_num = *(uint16_t *)data;
suites_num = le16toh(*(uint16_t *)data);
data += 2;
suites = alloca(suites_num * sizeof(uint32_t));
@ -914,7 +916,7 @@ static int nl80211_wlan_setbeacon(struct wifi_wlan* wlan) {
}
nla_put(msg, NL80211_ATTR_CIPHER_SUITES_PAIRWISE, suites_num * sizeof(uint32_t), suites);
suites_num = *(uint16_t *)data;
suites_num = le16toh(*(uint16_t *)data);
data += 2;
suites = alloca(suites_num * sizeof(uint32_t));

View File

@ -1,3 +1,5 @@
#include <endian.h>
#include "wtp.h"
#include "hash.h"
#include "list.h"
@ -970,7 +972,7 @@ uint32_t wtp_radio_add_station(struct capwap_parsed_packet* packet) {
data = (uint8_t *)(rsn + 1);
data += 2; // RSN Version
data += 4; // Group Chipher Suite
if (*(uint16_t *)data != 1) {
if (le16toh(*(uint16_t *)data) != 1) {
log_printf(LOG_DEBUG, "add_station: RSNE IE, wrong Pairwise Cipher Suite Count (%d)",
*(uint16_t *)data);
return CAPWAP_RESULTCODE_FAILURE;

View File

@ -1350,6 +1350,7 @@ static void wtp_handle_argv(int argc, char **argv) {
case 'c': {
if (strlen(optarg) < sizeof(g_configurationfile)) {
strcpy(g_configurationfile, optarg);
break;
} else {
printf("Invalid -%c argument\n", optopt);
exit(1);
@ -1506,7 +1507,7 @@ int main(int argc, char** argv) {
goto out_close_radio;
}
log_printf(LOG_INFO, "SmartCAPWAP kernel module connected");
log_printf(LOG_INFO, "CAPWAP WTP kernel module connected");
/* */
log_printf(LOG_INFO, "Startup WTP");