Compare commits
14 Commits
Author | SHA1 | Date | |
---|---|---|---|
6f7c26d0af | |||
fdf256553c | |||
ecf7a24eac | |||
57bcb0e183 | |||
9fbf441896 | |||
01919fffd9 | |||
02e8d534b5 | |||
3626927722 | |||
2ac3944e7a | |||
a131e17a6e | |||
0e19b53e28 | |||
9ded0bb87b | |||
b0aaaa4436 | |||
6024cc15cf |
18
NEWS.md
18
NEWS.md
@ -3,6 +3,24 @@ SmartCAPWAP
|
|||||||
|
|
||||||
CAPWAP WTP and AC implementation
|
CAPWAP WTP and AC implementation
|
||||||
|
|
||||||
|
Version 1.3.1 - 11 Aug 2016
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
* fix hw queue selection for 802.11 raw frame injection
|
||||||
|
* initial Linux ftrace support
|
||||||
|
|
||||||
|
Version 1.3.0 - 08 Aug 2016
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
* forward PAE (IEEE 802.1X Authentication) frames as raw 802.11 frames to AC
|
||||||
|
* implement encryption support for group and peer temporal keys (CCMP only)
|
||||||
|
|
||||||
|
Version 1.2.1 - 06 May 2016
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
* fix Add WLAN's capability field
|
||||||
|
* fix mssing IEEE 802.11 Assigned WTP BSSID IE in Add WLAN response
|
||||||
|
|
||||||
Version 1.2.0 - 29 Apr 2016
|
Version 1.2.0 - 29 Apr 2016
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
|
28
README.md
28
README.md
@ -17,6 +17,7 @@ NOTE: The WTP has been ported to libev, the AC has not been adjusted and is ther
|
|||||||
* Local MAC
|
* Local MAC
|
||||||
* single radio, single WLAN mode
|
* single radio, single WLAN mode
|
||||||
* 802.11n ([draft-ietf-opsawg-capwap-extension-06](https://tools.ietf.org/html/draft-ietf-opsawg-capwap-extension-06))
|
* 802.11n ([draft-ietf-opsawg-capwap-extension-06](https://tools.ietf.org/html/draft-ietf-opsawg-capwap-extension-06))
|
||||||
|
* WPA2-PSK
|
||||||
|
|
||||||
Only cards with cfg80211 netlink API are supported. The following devices
|
Only cards with cfg80211 netlink API are supported. The following devices
|
||||||
have been tested:
|
have been tested:
|
||||||
@ -26,7 +27,8 @@ have been tested:
|
|||||||
|
|
||||||
### Planned WTP features:
|
### Planned WTP features:
|
||||||
|
|
||||||
* encryption (WPA2)
|
* WPA2 Enterprise
|
||||||
|
* 802.11r - BSS fast transition
|
||||||
* Hybrid-MAC ([RFC-7494](https://tools.ietf.org/html/rfc7494))
|
* Hybrid-MAC ([RFC-7494](https://tools.ietf.org/html/rfc7494))
|
||||||
|
|
||||||
## INSTALLATION
|
## INSTALLATION
|
||||||
@ -66,3 +68,27 @@ SmartCAPWAP:
|
|||||||
./configure --disable-ac
|
./configure --disable-ac
|
||||||
make
|
make
|
||||||
make install
|
make install
|
||||||
|
|
||||||
|
### Debugging / Traceing
|
||||||
|
|
||||||
|
The smartcapwap 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:
|
||||||
|
|
||||||
|
# echo 1 > /sys/kernel/debug/tracing/events/capwap/enable
|
||||||
|
# echo 1 > /sys/kernel/debug/tracing/tracing_on
|
||||||
|
# cat /sys/kernel/debug/tracing/trace_pipe
|
||||||
|
<...>-890 [000] ...1 12030.725012: sc_capwap_create: session:9e04b10c75b3c6537da18d38da5bc70d
|
||||||
|
<...>-890 [000] ...1 12030.725048: sc_capwap_sendkeepalive: session:9e04b10c75b3c6537da18d38da5bc70d
|
||||||
|
<...>-890 [000] ...1 12030.725052: sc_capwap_createkeepalive: session:9e04b10c75b3c6537da18d38da5bc70d
|
||||||
|
<...>-890 [000] ...1 12030.725053: sc_capwap_send: session:9e04b10c75b3c6537da18d38da5bc70d
|
||||||
|
ksoftirqd/0-3 [000] ..s1 12030.727270: sc_capwap_parsingpacket: session:9e04b10c75b3c6537da18d38da5bc70d skb:ffff8802306c8900
|
||||||
|
wtp-890 [001] ...1 12060.764008: sc_capwap_sendkeepalive: session:9e04b10c75b3c6537da18d38da5bc70d
|
||||||
|
wtp-890 [001] ...1 12060.764530: sc_capwap_createkeepalive: session:9e04b10c75b3c6537da18d38da5bc70d
|
||||||
|
wtp-890 [001] ...1 12060.764637: sc_capwap_send: session:9e04b10c75b3c6537da18d38da5bc70d
|
||||||
|
<idle>-0 [000] ..s2 12060.787527: sc_capwap_parsingpacket: session:9e04b10c75b3c6537da18d38da5bc70d skb:ffff8800b8a85900
|
||||||
|
wtp-890 [001] ...1 12082.953847: sc_capwap_resetsession: session:9e04b10c75b3c6537da18d38da5bc70d
|
||||||
|
wtp-890 [001] ...1 12082.954005: sc_capwap_close: session:9e04b10c75b3c6537da18d38da5bc70d
|
||||||
|
wtp-890 [001] ...1 12082.954130: sc_capwap_freesession: session:9e04b10c75b3c6537da18d38da5bc70d
|
||||||
|
# echo 0 > /sys/kernel/debug/tracing/tracing_on
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
AC_PREREQ(2.63)
|
AC_PREREQ(2.63)
|
||||||
|
|
||||||
AC_INIT([SmartCAPWAP], [1.2], [https://github.com/travelping/smartcapwap], [smartcapwap])
|
AC_INIT([SmartCAPWAP], [1.2.1], [https://github.com/travelping/smartcapwap], [smartcapwap])
|
||||||
AC_CONFIG_AUX_DIR([build])
|
AC_CONFIG_AUX_DIR([build])
|
||||||
AC_CONFIG_MACRO_DIR([m4])
|
AC_CONFIG_MACRO_DIR([m4])
|
||||||
AM_INIT_AUTOMAKE([1.11 -Wall])
|
AM_INIT_AUTOMAKE([1.11 -Wall])
|
||||||
|
@ -9,14 +9,14 @@ include $(TOPDIR)/rules.mk
|
|||||||
include $(INCLUDE_DIR)/kernel.mk
|
include $(INCLUDE_DIR)/kernel.mk
|
||||||
|
|
||||||
PKG_NAME:=smartcapwap
|
PKG_NAME:=smartcapwap
|
||||||
PKG_VERSION:=1.2
|
PKG_VERSION:=1.2.1
|
||||||
PKG_RELEASE:=1
|
PKG_RELEASE:=1
|
||||||
|
|
||||||
SRC_SMARTCAPWAP := /usr/src/tplino/components/smartcapwap
|
SRC_SMARTCAPWAP := /usr/src/tplino/components/smartcapwap
|
||||||
PKG_SOURCE_PROTO:=git
|
PKG_SOURCE_PROTO:=git
|
||||||
PKG_SOURCE_URL:=git://github.com/travelping/smartcapwap.git
|
PKG_SOURCE_URL:=git://github.com/travelping/smartcapwap.git
|
||||||
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
|
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
|
||||||
PKG_SOURCE_VERSION:=v1.2.0
|
PKG_SOURCE_VERSION:=v1.2.1
|
||||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz
|
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz
|
||||||
|
|
||||||
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
|
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
From 03b6aa026d60cd49931934338d8ca82d05acc818 Mon Sep 17 00:00:00 2001
|
From 664ed7a49f0d9f879e22e7e3da904a2e5793c33d Mon Sep 17 00:00:00 2001
|
||||||
From: Andreas Schultz <aschultz@tpip.net>
|
From: Andreas Schultz <aschultz@tpip.net>
|
||||||
Date: Thu, 4 Feb 2016 15:57:11 +0100
|
Date: Thu, 4 Feb 2016 15:57:11 +0100
|
||||||
Subject: [PATCH] support patch for smartcapwap
|
Subject: [PATCH] support patch for smartcapwap
|
||||||
@ -8,9 +8,9 @@ Allows for kernel side interception and injection of IEEE 802.11 frames.
|
|||||||
include/net/mac80211.h | 25 ++++
|
include/net/mac80211.h | 25 ++++
|
||||||
net/mac80211/ieee80211_i.h | 6 +
|
net/mac80211/ieee80211_i.h | 6 +
|
||||||
net/mac80211/iface.c | 56 +++++++++
|
net/mac80211/iface.c | 56 +++++++++
|
||||||
net/mac80211/rx.c | 81 ++++++++++--
|
net/mac80211/rx.c | 81 +++++++++++--
|
||||||
net/mac80211/tx.c | 306 +++++++++++++++++++++++++++++++++++++++++++++
|
net/mac80211/tx.c | 279 +++++++++++++++++++++++++++++++++++++++++++++
|
||||||
5 files changed, 462 insertions(+), 12 deletions(-)
|
5 files changed, 435 insertions(+), 12 deletions(-)
|
||||||
|
|
||||||
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
|
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
|
||||||
index 760bc4d..6722da6 100644
|
index 760bc4d..6722da6 100644
|
||||||
@ -334,10 +334,10 @@ index 82af407..29cc59b 100644
|
|||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
|
|
||||||
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
|
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
|
||||||
index bdc224d..3769c33 100644
|
index bdc224d..5da49f0 100644
|
||||||
--- a/net/mac80211/tx.c
|
--- a/net/mac80211/tx.c
|
||||||
+++ b/net/mac80211/tx.c
|
+++ b/net/mac80211/tx.c
|
||||||
@@ -2939,6 +2939,138 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
|
@@ -2939,6 +2939,111 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
|
||||||
return NETDEV_TX_OK;
|
return NETDEV_TX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -353,8 +353,9 @@ index bdc224d..3769c33 100644
|
|||||||
+ struct ieee80211_chanctx_conf *chanctx_conf;
|
+ struct ieee80211_chanctx_conf *chanctx_conf;
|
||||||
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||||
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||||
+ struct ieee80211_sub_if_data *tmp_sdata, *sdata;
|
+ struct ieee80211_sub_if_data *sdata;
|
||||||
+ struct cfg80211_chan_def *chandef;
|
+ struct cfg80211_chan_def *chandef;
|
||||||
|
+ int tid;
|
||||||
+ int hdrlen;
|
+ int hdrlen;
|
||||||
+
|
+
|
||||||
+ /* check for not even having the fixed 802.11 header */
|
+ /* check for not even having the fixed 802.11 header */
|
||||||
@ -367,13 +368,13 @@ index bdc224d..3769c33 100644
|
|||||||
+ if (unlikely(skb->len < hdrlen))
|
+ if (unlikely(skb->len < hdrlen))
|
||||||
+ goto fail; /* skb too short for claimed header length */
|
+ goto fail; /* skb too short for claimed header length */
|
||||||
+
|
+
|
||||||
+ skb_reset_mac_header(skb);
|
+ skb_set_mac_header(skb, 0);
|
||||||
+ /*
|
+ /*
|
||||||
+ * these are just fixed to the end of the rt area since we
|
+ * 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
|
+ * don't have any better information and at this point, nobody cares
|
||||||
+ */
|
+ */
|
||||||
+ skb_reset_network_header(skb);
|
+ skb_set_network_header(skb, hdrlen);
|
||||||
+ skb_reset_transport_header(skb);
|
+ skb_set_transport_header(skb, hdrlen);
|
||||||
+
|
+
|
||||||
+ /*
|
+ /*
|
||||||
+ * Initialize skb->protocol if the injected frame is a data frame
|
+ * Initialize skb->protocol if the injected frame is a data frame
|
||||||
@ -388,12 +389,17 @@ index bdc224d..3769c33 100644
|
|||||||
+ payload[7]);
|
+ payload[7]);
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ memset(info, 0, sizeof(*info));
|
+ 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 |
|
+ info->flags = IEEE80211_TX_CTL_REQ_TX_STATUS |
|
||||||
+ IEEE80211_TX_CTL_INJECTED;
|
+ IEEE80211_TX_CTL_INJECTED;
|
||||||
+
|
+
|
||||||
+
|
|
||||||
+ /*
|
+ /*
|
||||||
+ * we might have set these flags later.....
|
+ * we might have set these flags later.....
|
||||||
+ * info->flags &= ~IEEE80211_TX_INTFL_DONT_ENCRYPT;
|
+ * info->flags &= ~IEEE80211_TX_INTFL_DONT_ENCRYPT;
|
||||||
@ -405,46 +411,17 @@ index bdc224d..3769c33 100644
|
|||||||
+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||||
+
|
+
|
||||||
+ chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
|
+ chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
|
||||||
+ if (!chanctx_conf) {
|
+ if (!chanctx_conf)
|
||||||
+ tmp_sdata = rcu_dereference(local->monitor_sdata);
|
|
||||||
+ if (tmp_sdata)
|
|
||||||
+ chanctx_conf =
|
|
||||||
+ rcu_dereference(tmp_sdata->vif.chanctx_conf);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (chanctx_conf)
|
|
||||||
+ chandef = &chanctx_conf->def;
|
|
||||||
+ else if (!local->use_chanctx)
|
|
||||||
+ chandef = &local->_oper_chandef;
|
|
||||||
+ else
|
|
||||||
+ goto fail_rcu;
|
+ goto fail_rcu;
|
||||||
+
|
+
|
||||||
+ /*
|
+ info->band = chanctx_conf->def.chan->band;
|
||||||
+ * Frame injection is not allowed if beaconing is not allowed
|
+
|
||||||
+ * or if we need radar detection. Beaconing is usually not allowed when
|
+ ieee80211_tx_stats(dev, skb->len);
|
||||||
+ * 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))
|
|
||||||
+ goto fail_rcu;
|
|
||||||
+
|
+
|
||||||
+ info->band = chandef->chan->band;
|
|
||||||
+ ieee80211_xmit(sdata, NULL, skb);
|
+ ieee80211_xmit(sdata, NULL, skb);
|
||||||
+ rcu_read_unlock();
|
+ rcu_read_unlock();
|
||||||
+
|
+
|
||||||
+ return;
|
+ return;
|
||||||
+
|
|
||||||
+fail_rcu:
|
+fail_rcu:
|
||||||
+ rcu_read_unlock();
|
+ rcu_read_unlock();
|
||||||
+fail:
|
+fail:
|
||||||
@ -461,10 +438,6 @@ index bdc224d..3769c33 100644
|
|||||||
+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)
|
||||||
+{
|
+{
|
||||||
+ if (skb->protocol != htons(ETH_P_IP))
|
|
||||||
+ printk(KERN_DEBUG "capwap xmit %s: protocol: %04X, data: %p, MAC: %p\n",
|
|
||||||
+ dev->name, ntohs(skb->protocol), skb->data, skb_mac_header(skb));
|
|
||||||
+
|
|
||||||
+ if (skb->protocol == htons(ETH_P_CONTROL)) {
|
+ if (skb->protocol == htons(ETH_P_CONTROL)) {
|
||||||
+ __ieee80211_capwap_inject_start_xmit(skb, dev);
|
+ __ieee80211_capwap_inject_start_xmit(skb, dev);
|
||||||
+ } else
|
+ } else
|
||||||
@ -476,7 +449,7 @@ index bdc224d..3769c33 100644
|
|||||||
struct sk_buff *
|
struct sk_buff *
|
||||||
ieee80211_build_data_template(struct ieee80211_sub_if_data *sdata,
|
ieee80211_build_data_template(struct ieee80211_sub_if_data *sdata,
|
||||||
struct sk_buff *skb, u32 info_flags)
|
struct sk_buff *skb, u32 info_flags)
|
||||||
@@ -3914,3 +4046,177 @@ void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata,
|
@@ -3914,3 +4019,177 @@ void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata,
|
||||||
ieee80211_xmit(sdata, NULL, skb);
|
ieee80211_xmit(sdata, NULL, skb);
|
||||||
local_bh_enable();
|
local_bh_enable();
|
||||||
}
|
}
|
||||||
@ -655,5 +628,5 @@ index bdc224d..3769c33 100644
|
|||||||
+EXPORT_SYMBOL(ieee80211_inject_xmit);
|
+EXPORT_SYMBOL(ieee80211_inject_xmit);
|
||||||
+
|
+
|
||||||
--
|
--
|
||||||
2.7.0
|
2.8.1
|
||||||
|
|
||||||
|
@ -420,6 +420,9 @@ struct ieee80211_ie_erp {
|
|||||||
uint8_t params;
|
uint8_t params;
|
||||||
} STRUCT_PACKED;
|
} STRUCT_PACKED;
|
||||||
|
|
||||||
|
/* 802.11 RSN information element */
|
||||||
|
#define IEEE80211_IE_RSN_INFORMATION 48
|
||||||
|
|
||||||
/* 802.11 Extended Supported Rates information element */
|
/* 802.11 Extended Supported Rates information element */
|
||||||
#define IEEE80211_IE_EXTENDED_SUPPORTED_RATES 50
|
#define IEEE80211_IE_EXTENDED_SUPPORTED_RATES 50
|
||||||
#define IEEE80211_IE_EXTENDED_SUPPORTED_MIN_LENGTH 1
|
#define IEEE80211_IE_EXTENDED_SUPPORTED_MIN_LENGTH 1
|
||||||
|
@ -139,7 +139,7 @@ struct capwap_list_item* capwap_get_message_element(struct capwap_parsed_packet*
|
|||||||
while (search) {
|
while (search) {
|
||||||
struct capwap_message_element_itemlist* messageelement =
|
struct capwap_message_element_itemlist* messageelement =
|
||||||
(struct capwap_message_element_itemlist*)search->item;
|
(struct capwap_message_element_itemlist*)search->item;
|
||||||
if ((id.vendor == messageelement->id.vendor) && (id.type == messageelement->id.type))
|
if (message_element_id_eq(id, messageelement->id))
|
||||||
return search;
|
return search;
|
||||||
|
|
||||||
/* */
|
/* */
|
||||||
|
@ -10,6 +10,9 @@ struct capwap_message_element_id
|
|||||||
uint16_t type;
|
uint16_t type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define message_element_id_eq(a, b) \
|
||||||
|
(((a).vendor == (b).vendor) && ((a).type == (b).type))
|
||||||
|
|
||||||
/* */
|
/* */
|
||||||
typedef void* capwap_message_elements_handle;
|
typedef void* capwap_message_elements_handle;
|
||||||
struct capwap_write_message_elements_ops {
|
struct capwap_write_message_elements_ops {
|
||||||
|
@ -39,7 +39,9 @@ static void capwap_80211_stationkey_element_create(void* data, capwap_message_el
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* */
|
/* */
|
||||||
static void* capwap_80211_stationkey_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) {
|
static void* capwap_80211_stationkey_element_parsing(capwap_message_elements_handle handle,
|
||||||
|
struct capwap_read_message_elements_ops* func)
|
||||||
|
{
|
||||||
unsigned short length;
|
unsigned short length;
|
||||||
struct capwap_80211_stationkey_element* data;
|
struct capwap_80211_stationkey_element* data;
|
||||||
|
|
||||||
@ -53,10 +55,11 @@ static void* capwap_80211_stationkey_element_parsing(capwap_message_elements_han
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* */
|
/* */
|
||||||
data = (struct capwap_80211_stationkey_element*)capwap_alloc(sizeof(struct capwap_80211_stationkey_element));
|
data = (struct capwap_80211_stationkey_element *)
|
||||||
|
capwap_alloc(sizeof(struct capwap_80211_stationkey_element));
|
||||||
|
memset(data, 0, sizeof(struct capwap_80211_stationkey_element));
|
||||||
data->keylength = length - 20;
|
data->keylength = length - 20;
|
||||||
data->key = (uint8_t*)capwap_alloc(data->keylength);
|
data->key = (uint8_t*)capwap_alloc(data->keylength);
|
||||||
memset(data, 0, sizeof(struct capwap_80211_stationkey_element));
|
|
||||||
|
|
||||||
/* Retrieve data */
|
/* Retrieve data */
|
||||||
func->read_block(handle, data->address, MACADDRESS_EUI48_LENGTH);
|
func->read_block(handle, data->address, MACADDRESS_EUI48_LENGTH);
|
||||||
|
@ -110,6 +110,16 @@ static void wlan_delete(struct wifi_wlan* wlan)
|
|||||||
wlan->device->instance->ops->wlan_delete(wlan);
|
wlan->device->instance->ops->wlan_delete(wlan);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int wlan_set_key(struct wifi_wlan* wlan,
|
||||||
|
uint32_t alg, const uint8_t *addr,
|
||||||
|
int key_idx, int set_tx,
|
||||||
|
const uint8_t *seq, size_t seq_len,
|
||||||
|
const uint8_t *key, size_t key_len)
|
||||||
|
{
|
||||||
|
return wlan->device->instance->ops->wlan_set_key(wlan, alg, addr, key_idx, set_tx,
|
||||||
|
seq, seq_len, key, key_len);
|
||||||
|
}
|
||||||
|
|
||||||
static int station_authorize(struct wifi_wlan* wlan, struct wifi_station* station)
|
static int station_authorize(struct wifi_wlan* wlan, struct wifi_station* station)
|
||||||
{
|
{
|
||||||
return wlan->device->instance->ops->station_authorize(wlan, station);
|
return wlan->device->instance->ops->station_authorize(wlan, station);
|
||||||
@ -1342,9 +1352,19 @@ wifi_wlan_receive_station_mgmt_association_response_ack(struct wifi_wlan* wlan,
|
|||||||
/* */
|
/* */
|
||||||
station->flags |= WIFI_STATION_FLAGS_ASSOCIATE;
|
station->flags |= WIFI_STATION_FLAGS_ASSOCIATE;
|
||||||
if (station->flags & WIFI_STATION_FLAGS_AUTHORIZED) {
|
if (station->flags & WIFI_STATION_FLAGS_AUTHORIZED) {
|
||||||
|
int result;
|
||||||
|
|
||||||
/* Apply authorization if Station already authorized */
|
/* Apply authorization if Station already authorized */
|
||||||
if (station_authorize(wlan, station))
|
result = station_authorize(wlan, station);
|
||||||
|
if (!result)
|
||||||
|
result = wifi_station_set_key(wlan, station);
|
||||||
|
if (result)
|
||||||
wifi_wlan_deauthentication_station(wlan, station, IEEE80211_REASON_PREV_AUTH_NOT_VALID);
|
wifi_wlan_deauthentication_station(wlan, station, IEEE80211_REASON_PREV_AUTH_NOT_VALID);
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
/* let the timer expire, but set the action to SEND NULLFUNC */
|
||||||
|
station->timeout_action = WIFI_STATION_TIMEOUT_ACTION_SEND_NULLFUNC;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2071,6 +2091,39 @@ static int ht_opmode_from_ie(uint8_t radioid, uint8_t wlanid,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Scan AC provided IEs for RSNE settings */
|
||||||
|
static struct ieee80211_ie *rsn_from_ie(uint8_t radioid, uint8_t wlanid,
|
||||||
|
struct capwap_array *ie)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!ie)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for (i = 0; i < ie->count; i++) {
|
||||||
|
struct ieee80211_ie *rsn;
|
||||||
|
struct capwap_80211_ie_element *e =
|
||||||
|
*(struct capwap_80211_ie_element **)capwap_array_get_item_pointer(ie, i);
|
||||||
|
|
||||||
|
log_printf(LOG_DEBUG, "RSN WIFI 802.11: IE: %d:%d %02x (%p)",
|
||||||
|
radioid, wlanid, e->flags, &e->flags);
|
||||||
|
|
||||||
|
if (e->radioid != radioid ||
|
||||||
|
e->wlanid != wlanid ||
|
||||||
|
e->ielength < 2)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
rsn = (struct ieee80211_ie *)e->ie;
|
||||||
|
log_printf(LOG_DEBUG, "RSN WIFI 802.11: IE: %02d (%p)",
|
||||||
|
rsn->id, rsn);
|
||||||
|
if (rsn->id == IEEE80211_IE_RSN_INFORMATION)
|
||||||
|
return rsn;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_printf(LOG_DEBUG, "WIFI 802.11: No RSN IE present");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* */
|
/* */
|
||||||
int wifi_wlan_startap(struct wifi_wlan* wlan, struct wlan_startap_params* params)
|
int wifi_wlan_startap(struct wifi_wlan* wlan, struct wlan_startap_params* params)
|
||||||
{
|
{
|
||||||
@ -2097,6 +2150,12 @@ int wifi_wlan_startap(struct wifi_wlan* wlan, struct wlan_startap_params* params
|
|||||||
wlan->ht_opmode = ht_opmode_from_ie(wlan->radioid, wlan->wlanid,
|
wlan->ht_opmode = ht_opmode_from_ie(wlan->radioid, wlan->wlanid,
|
||||||
params->ie);
|
params->ie);
|
||||||
log_printf(LOG_DEBUG, "WIFI 802.11: HT OpMode: %04x", wlan->ht_opmode);
|
log_printf(LOG_DEBUG, "WIFI 802.11: HT OpMode: %04x", wlan->ht_opmode);
|
||||||
|
wlan->rsne = rsn_from_ie(wlan->radioid, wlan->wlanid,
|
||||||
|
params->ie);
|
||||||
|
wlan->keyindex = params->keyindex;
|
||||||
|
wlan->keylength = params->keylength;
|
||||||
|
if (params->key && params->keylength)
|
||||||
|
wlan->key = capwap_clone(params->key, params->keylength);
|
||||||
|
|
||||||
build_80211_ie(wlan->radioid, wlan->wlanid,
|
build_80211_ie(wlan->radioid, wlan->wlanid,
|
||||||
CAPWAP_IE_BEACONS_ASSOCIATED,
|
CAPWAP_IE_BEACONS_ASSOCIATED,
|
||||||
@ -2119,6 +2178,69 @@ int wifi_wlan_startap(struct wifi_wlan* wlan, struct wlan_startap_params* params
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define broadcast_ether_addr (const uint8_t *) "\xff\xff\xff\xff\xff\xff"
|
||||||
|
|
||||||
|
/* */
|
||||||
|
int wifi_wlan_updateap(struct wifi_wlan* wlan, struct wlan_updateap_params* params)
|
||||||
|
{
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
ASSERT(wlan != NULL);
|
||||||
|
ASSERT(wlan->device != NULL);
|
||||||
|
ASSERT(params != NULL);
|
||||||
|
|
||||||
|
/* Check device */
|
||||||
|
if (!(wlan->flags & WIFI_WLAN_RUNNING))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* Save configuration */
|
||||||
|
#if 0
|
||||||
|
/* TODO: handle changes in WLAN setting */
|
||||||
|
wlan->capability = params->capability;
|
||||||
|
wlan->ht_opmode = ht_opmode_from_ie(wlan->radioid, wlan->wlanid,
|
||||||
|
params->ie);
|
||||||
|
log_printf(LOG_DEBUG, "WIFI 802.11: HT OpMode: %04x", wlan->ht_opmode);
|
||||||
|
wlan->rsne = rsn_from_ie(wlan->radioid, wlan->wlanid,
|
||||||
|
params->ie);
|
||||||
|
|
||||||
|
/* TODO: handle changes in WLAN setting */
|
||||||
|
build_80211_ie(wlan->radioid, wlan->wlanid,
|
||||||
|
CAPWAP_IE_BEACONS_ASSOCIATED,
|
||||||
|
params->ie,
|
||||||
|
&wlan->beacon_ies, &wlan->beacon_ies_len);
|
||||||
|
build_80211_ie(wlan->radioid, wlan->wlanid,
|
||||||
|
CAPWAP_IE_PROBE_RESPONSE_ASSOCIATED,
|
||||||
|
params->ie,
|
||||||
|
&wlan->response_ies, &wlan->response_ies_len);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
switch (params->keystatus) {
|
||||||
|
case 3:
|
||||||
|
wlan->keyindex = params->keyindex;
|
||||||
|
wlan->keylength = params->keylength;
|
||||||
|
|
||||||
|
if (wlan->key) {
|
||||||
|
capwap_free(wlan->key);
|
||||||
|
wlan->key = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params->key && params->keylength)
|
||||||
|
wlan->key = capwap_clone(params->key, params->keylength);
|
||||||
|
|
||||||
|
result = wlan_set_key(wlan, wlan->group_cipher_suite, broadcast_ether_addr,
|
||||||
|
wlan->keyindex, 1, NULL, 0, wlan->key, wlan->keylength);
|
||||||
|
|
||||||
|
log_printf(LOG_INFO, "Update GTK on interface: %s, SSID: '%s', result: %d",
|
||||||
|
wlan->virtname, wlan->ssid, result);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/* */
|
/* */
|
||||||
void wifi_wlan_stopap(struct wifi_wlan* wlan)
|
void wifi_wlan_stopap(struct wifi_wlan* wlan)
|
||||||
{
|
{
|
||||||
@ -2334,14 +2456,21 @@ int wifi_station_authorize(struct wifi_wlan* wlan,
|
|||||||
station = wifi_station_get(wlan, params->address);
|
station = wifi_station_get(wlan, params->address);
|
||||||
if (!station)
|
if (!station)
|
||||||
return -1;
|
return -1;
|
||||||
if (station->flags & WIFI_STATION_FLAGS_AUTHORIZED)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* Station is authorized only after Authentication and Association */
|
if (params->key)
|
||||||
station->flags |= WIFI_STATION_FLAGS_AUTHORIZED;
|
station->key = (struct capwap_80211_stationkey_element *)
|
||||||
if (!(station->flags & WIFI_STATION_FLAGS_AUTHENTICATED) ||
|
capwap_element_80211_stationkey_ops.clone(params->key);
|
||||||
!(station->flags & WIFI_STATION_FLAGS_ASSOCIATE))
|
station->pairwise_cipher = params->pairwise;
|
||||||
|
|
||||||
|
if (station->flags & WIFI_STATION_FLAGS_AUTHORIZED) {
|
||||||
|
result = wifi_station_set_key(wlan, station);
|
||||||
|
if (result) {
|
||||||
|
wifi_wlan_deauthentication_station(wlan, station,
|
||||||
|
IEEE80211_REASON_PREV_AUTH_NOT_VALID);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (params->ht_cap) {
|
if (params->ht_cap) {
|
||||||
memcpy(&station->ht_cap, params->ht_cap, sizeof(station->ht_cap));
|
memcpy(&station->ht_cap, params->ht_cap, sizeof(station->ht_cap));
|
||||||
@ -2350,8 +2479,16 @@ int wifi_station_authorize(struct wifi_wlan* wlan,
|
|||||||
|
|
||||||
station->max_inactivity = params->max_inactivity;
|
station->max_inactivity = params->max_inactivity;
|
||||||
|
|
||||||
|
/* Station is authorized only after Authentication and Association */
|
||||||
|
station->flags |= WIFI_STATION_FLAGS_AUTHORIZED;
|
||||||
|
if (!(station->flags & WIFI_STATION_FLAGS_AUTHENTICATED) ||
|
||||||
|
!(station->flags & WIFI_STATION_FLAGS_ASSOCIATE))
|
||||||
|
return 0;
|
||||||
|
|
||||||
/* Station authorized */
|
/* Station authorized */
|
||||||
result = station_authorize(wlan, station);
|
result = station_authorize(wlan, station);
|
||||||
|
if (!result)
|
||||||
|
result = wifi_station_set_key(wlan, station);
|
||||||
if (result) {
|
if (result) {
|
||||||
wifi_wlan_deauthentication_station(wlan, station,
|
wifi_wlan_deauthentication_station(wlan, station,
|
||||||
IEEE80211_REASON_PREV_AUTH_NOT_VALID);
|
IEEE80211_REASON_PREV_AUTH_NOT_VALID);
|
||||||
@ -2360,9 +2497,27 @@ int wifi_station_authorize(struct wifi_wlan* wlan,
|
|||||||
|
|
||||||
/* let the timer expire, but set the action to SEND NULLFUNC */
|
/* let the timer expire, but set the action to SEND NULLFUNC */
|
||||||
station->timeout_action = WIFI_STATION_TIMEOUT_ACTION_SEND_NULLFUNC;
|
station->timeout_action = WIFI_STATION_TIMEOUT_ACTION_SEND_NULLFUNC;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* */
|
||||||
|
int wifi_station_set_key(struct wifi_wlan *wlan,
|
||||||
|
struct wifi_station* station)
|
||||||
|
{
|
||||||
|
|
||||||
|
ASSERT(wlan != NULL);
|
||||||
|
ASSERT(wlan->device != NULL);
|
||||||
|
ASSERT(station != NULL);
|
||||||
|
|
||||||
|
if (station->pairwise_cipher)
|
||||||
|
return wlan_set_key(wlan, station->pairwise_cipher, station->address,
|
||||||
|
0, 1, NULL, 0, station->key->key, station->key->keylength);
|
||||||
|
|
||||||
|
return wlan_set_key(wlan, station->pairwise_cipher, station->address,
|
||||||
|
0, 1, NULL, 0, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/* */
|
/* */
|
||||||
void wifi_station_deauthorize(struct wifi_device* device, const uint8_t* address) {
|
void wifi_station_deauthorize(struct wifi_device* device, const uint8_t* address) {
|
||||||
struct wifi_station* station;
|
struct wifi_station* station;
|
||||||
|
@ -71,6 +71,7 @@ DECLARE_OPAQUE_TYPE(wifi_device_handle);
|
|||||||
DECLARE_OPAQUE_TYPE(wifi_wlan_handle);
|
DECLARE_OPAQUE_TYPE(wifi_wlan_handle);
|
||||||
|
|
||||||
struct capwap_80211_wtpqos_element;
|
struct capwap_80211_wtpqos_element;
|
||||||
|
struct capwap_80211_stationkey_element;
|
||||||
|
|
||||||
/* */
|
/* */
|
||||||
struct device_setrates_params {
|
struct device_setrates_params {
|
||||||
@ -106,9 +107,27 @@ struct wlan_startap_params {
|
|||||||
uint8_t macmode;
|
uint8_t macmode;
|
||||||
uint8_t tunnelmode;
|
uint8_t tunnelmode;
|
||||||
|
|
||||||
|
uint8_t keyindex;
|
||||||
|
uint8_t keylength;
|
||||||
|
uint8_t *key;
|
||||||
|
|
||||||
struct capwap_array *ie;
|
struct capwap_array *ie;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct wlan_updateap_params {
|
||||||
|
uint8_t radioid;
|
||||||
|
uint8_t wlanid;
|
||||||
|
|
||||||
|
uint16_t capability;
|
||||||
|
uint8_t qos;
|
||||||
|
|
||||||
|
uint8_t keyindex;
|
||||||
|
uint8_t keystatus;
|
||||||
|
uint8_t keylength;
|
||||||
|
uint8_t *key;
|
||||||
|
|
||||||
|
struct capwap_array *ie;
|
||||||
|
};
|
||||||
|
|
||||||
/* */
|
/* */
|
||||||
struct wlan_send_frame_params {
|
struct wlan_send_frame_params {
|
||||||
@ -128,6 +147,8 @@ struct wlan_send_frame_params {
|
|||||||
struct station_add_params {
|
struct station_add_params {
|
||||||
uint8_t* address;
|
uint8_t* address;
|
||||||
struct ieee80211_ht_cap *ht_cap;
|
struct ieee80211_ht_cap *ht_cap;
|
||||||
|
uint32_t pairwise;
|
||||||
|
struct capwap_80211_stationkey_element *key;
|
||||||
int max_inactivity;
|
int max_inactivity;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -326,6 +347,12 @@ struct wifi_wlan {
|
|||||||
|
|
||||||
uint32_t aidbitfield[IEEE80211_AID_BITFIELD_SIZE];
|
uint32_t aidbitfield[IEEE80211_AID_BITFIELD_SIZE];
|
||||||
|
|
||||||
|
struct ieee80211_ie *rsne;
|
||||||
|
uint32_t group_cipher_suite;
|
||||||
|
uint8_t keyindex;
|
||||||
|
uint8_t keylength;
|
||||||
|
uint8_t *key;
|
||||||
|
|
||||||
int beacon_ies_len;
|
int beacon_ies_len;
|
||||||
uint8_t *beacon_ies;
|
uint8_t *beacon_ies;
|
||||||
int response_ies_len;
|
int response_ies_len;
|
||||||
@ -379,6 +406,8 @@ struct wifi_station {
|
|||||||
|
|
||||||
/* Authentication */
|
/* Authentication */
|
||||||
uint16_t authalgorithm;
|
uint16_t authalgorithm;
|
||||||
|
uint32_t pairwise_cipher;
|
||||||
|
struct capwap_80211_stationkey_element *key;
|
||||||
|
|
||||||
uint8_t qosinfo;
|
uint8_t qosinfo;
|
||||||
|
|
||||||
@ -410,6 +439,11 @@ struct wifi_driver_ops {
|
|||||||
int (*wlan_sendframe)(struct wifi_wlan* wlan, uint8_t* frame, int length, uint32_t frequency, uint32_t duration, int offchannel_tx_ok, int no_cck_rate, int no_wait_ack);
|
int (*wlan_sendframe)(struct wifi_wlan* wlan, uint8_t* frame, int length, uint32_t frequency, uint32_t duration, int offchannel_tx_ok, int no_cck_rate, int no_wait_ack);
|
||||||
void (*wlan_poll_station)(struct wifi_wlan* wlan, const uint8_t* address, int qos);
|
void (*wlan_poll_station)(struct wifi_wlan* wlan, const uint8_t* address, int qos);
|
||||||
void (*wlan_delete)(struct wifi_wlan* wlan);
|
void (*wlan_delete)(struct wifi_wlan* wlan);
|
||||||
|
int (*wlan_set_key)(struct wifi_wlan* wlan,
|
||||||
|
uint32_t alg, const uint8_t *addr,
|
||||||
|
int key_idx, int set_tx,
|
||||||
|
const uint8_t *seq, size_t seq_len,
|
||||||
|
const uint8_t *key, size_t key_len);
|
||||||
|
|
||||||
/* Stations functions */
|
/* Stations functions */
|
||||||
int (*station_authorize)(struct wifi_wlan* wlan, struct wifi_station* station);
|
int (*station_authorize)(struct wifi_wlan* wlan, struct wifi_station* station);
|
||||||
@ -435,6 +469,7 @@ int wifi_device_updaterates(struct wifi_device* device, uint8_t* rates, int rate
|
|||||||
/* WLAN management */
|
/* WLAN management */
|
||||||
struct wifi_wlan* wifi_wlan_create(struct wifi_device* device, const char* ifname);
|
struct wifi_wlan* wifi_wlan_create(struct wifi_device* device, const char* ifname);
|
||||||
int wifi_wlan_startap(struct wifi_wlan* wlan, struct wlan_startap_params* params);
|
int wifi_wlan_startap(struct wifi_wlan* wlan, struct wlan_startap_params* params);
|
||||||
|
int wifi_wlan_updateap(struct wifi_wlan* wlan, struct wlan_updateap_params* params);
|
||||||
void wifi_wlan_stopap(struct wifi_wlan* wlan);
|
void wifi_wlan_stopap(struct wifi_wlan* wlan);
|
||||||
int wifi_wlan_getbssid(struct wifi_wlan* wlan, uint8_t* bssid);
|
int wifi_wlan_getbssid(struct wifi_wlan* wlan, uint8_t* bssid);
|
||||||
uint16_t wifi_wlan_check_capability(struct wifi_wlan* wlan, uint16_t capability);
|
uint16_t wifi_wlan_check_capability(struct wifi_wlan* wlan, uint16_t capability);
|
||||||
@ -448,6 +483,7 @@ void wifi_wlan_receive_ac_frame(struct wifi_wlan* wlan, struct ieee80211_header*
|
|||||||
void wifi_wlan_client_probe_event(struct wifi_wlan *wlan, const uint8_t *address);
|
void wifi_wlan_client_probe_event(struct wifi_wlan *wlan, const uint8_t *address);
|
||||||
|
|
||||||
/* Station management */
|
/* Station management */
|
||||||
|
int wifi_station_set_key(struct wifi_wlan *wlan, struct wifi_station* station);
|
||||||
int wifi_station_authorize(struct wifi_wlan* wlan, struct station_add_params* params);
|
int wifi_station_authorize(struct wifi_wlan* wlan, struct station_add_params* params);
|
||||||
void wifi_station_deauthorize(struct wifi_device* device, const uint8_t* address);
|
void wifi_station_deauthorize(struct wifi_device* device, const uint8_t* address);
|
||||||
|
|
||||||
|
@ -882,6 +882,50 @@ static int nl80211_wlan_setbeacon(struct wifi_wlan* wlan) {
|
|||||||
nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT))
|
nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT))
|
||||||
goto out_err;
|
goto out_err;
|
||||||
|
|
||||||
|
/* privacy */
|
||||||
|
if (wlan->rsne)
|
||||||
|
log_printf(LOG_DEBUG, "RSNE capability: %04x", wlan->capability);
|
||||||
|
|
||||||
|
if (wlan->rsne &&
|
||||||
|
wlan->capability & IEEE80211_CAPABILITY_PRIVACY) {
|
||||||
|
uint8_t *data = (uint8_t *)(wlan->rsne + 1);
|
||||||
|
uint16_t suites_num;
|
||||||
|
uint32_t *suites;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
data += 2;
|
||||||
|
|
||||||
|
nla_put_flag(msg, NL80211_ATTR_PRIVACY);
|
||||||
|
nla_put_u32(msg, NL80211_ATTR_WPA_VERSIONS, NL80211_WPA_VERSION_2);
|
||||||
|
log_printf(LOG_ERR, "nl80211: Cipher Suite Group: %08x", ntohl(*(uint32_t *)data));
|
||||||
|
/* find a better place for the cipher suite assignment */
|
||||||
|
wlan->group_cipher_suite = ntohl(*(uint32_t *)data);
|
||||||
|
nla_put_u32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP, ntohl(*(uint32_t *)data));
|
||||||
|
data += sizeof(uint32_t);
|
||||||
|
|
||||||
|
suites_num = *(uint16_t *)data;
|
||||||
|
data += 2;
|
||||||
|
suites = alloca(suites_num * sizeof(uint32_t));
|
||||||
|
|
||||||
|
for (i = 0; i < suites_num; i++) {
|
||||||
|
suites[i] = ntohl(*(uint32_t *)data);
|
||||||
|
log_printf(LOG_ERR, "nl80211: Cipher Suite Pairwise[%d]: %08x", i, suites[i]);
|
||||||
|
data +=sizeof(uint32_t);
|
||||||
|
}
|
||||||
|
nla_put(msg, NL80211_ATTR_CIPHER_SUITES_PAIRWISE, suites_num * sizeof(uint32_t), suites);
|
||||||
|
|
||||||
|
suites_num = *(uint16_t *)data;
|
||||||
|
data += 2;
|
||||||
|
suites = alloca(suites_num * sizeof(uint32_t));
|
||||||
|
|
||||||
|
for (i = 0; i < suites_num; i++) {
|
||||||
|
suites[i] = ntohl(*(uint32_t *)data);
|
||||||
|
log_printf(LOG_ERR, "nl80211: AKM Suite[%d]: %08x", i, suites[i]);
|
||||||
|
data +=sizeof(uint32_t);
|
||||||
|
}
|
||||||
|
nla_put(msg, NL80211_ATTR_AKM_SUITES, suites_num * sizeof(uint32_t), suites);
|
||||||
|
}
|
||||||
|
|
||||||
/* Start AP */
|
/* Start AP */
|
||||||
result = nl80211_wlan_send_and_recv_msg(wlan, msg, NULL, NULL);
|
result = nl80211_wlan_send_and_recv_msg(wlan, msg, NULL, NULL);
|
||||||
if (result)
|
if (result)
|
||||||
@ -931,6 +975,115 @@ out_err:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int is_broadcast_ether_addr(const uint8_t *a)
|
||||||
|
{
|
||||||
|
return (a[0] & a[1] & a[2] & a[3] & a[4] & a[5]) == 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define broadcast_ether_addr (const uint8_t *) "\xff\xff\xff\xff\xff\xff"
|
||||||
|
|
||||||
|
static int nl80211_set_key(struct wifi_wlan* wlan,
|
||||||
|
uint32_t alg, const uint8_t *addr,
|
||||||
|
int key_idx, int set_tx,
|
||||||
|
const uint8_t *seq, size_t seq_len,
|
||||||
|
const uint8_t *key, size_t key_len)
|
||||||
|
{
|
||||||
|
struct nl_msg *msg;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
log_printf(LOG_DEBUG, "%s: ifindex=%d alg=%08x addr=%p key_idx=%d "
|
||||||
|
"set_tx=%d seq_len=%lu key_len=%lu",
|
||||||
|
__func__, wlan->virtindex, alg, addr, key_idx, set_tx,
|
||||||
|
(unsigned long) seq_len, (unsigned long) key_len);
|
||||||
|
|
||||||
|
if (alg == 0) {
|
||||||
|
msg = nl80211_wlan_msg(wlan, 0, NL80211_CMD_DEL_KEY);
|
||||||
|
if (!msg)
|
||||||
|
return -ENOBUFS;
|
||||||
|
} else {
|
||||||
|
msg = nl80211_wlan_msg(wlan, 0, NL80211_CMD_NEW_KEY);
|
||||||
|
if (!msg ||
|
||||||
|
nla_put(msg, NL80211_ATTR_KEY_DATA, key_len, key) ||
|
||||||
|
nla_put_u32(msg, NL80211_ATTR_KEY_CIPHER, alg))
|
||||||
|
goto fail;
|
||||||
|
log_hexdump(LOG_DEBUG, "nl80211: KEY_DATA", key, key_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (seq && seq_len) {
|
||||||
|
if (nla_put(msg, NL80211_ATTR_KEY_SEQ, seq_len, seq))
|
||||||
|
goto fail;
|
||||||
|
log_hexdump(LOG_DEBUG, "nl80211: KEY_SEQ", seq, seq_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addr && !is_broadcast_ether_addr(addr)) {
|
||||||
|
log_printf(LOG_DEBUG, " addr=" MACSTR, MAC2STR(addr));
|
||||||
|
if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (key_idx && !set_tx) {
|
||||||
|
log_printf(LOG_DEBUG, " RSN IBSS RX GTK");
|
||||||
|
if (nla_put_u32(msg, NL80211_ATTR_KEY_TYPE,
|
||||||
|
NL80211_KEYTYPE_GROUP))
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
} else if (addr && is_broadcast_ether_addr(addr)) {
|
||||||
|
struct nlattr *types;
|
||||||
|
|
||||||
|
log_printf(LOG_DEBUG, " broadcast key");
|
||||||
|
|
||||||
|
types = nla_nest_start(msg, NL80211_ATTR_KEY_DEFAULT_TYPES);
|
||||||
|
if (!types ||
|
||||||
|
nla_put_flag(msg, NL80211_KEY_DEFAULT_TYPE_MULTICAST))
|
||||||
|
goto fail;
|
||||||
|
nla_nest_end(msg, types);
|
||||||
|
}
|
||||||
|
if (nla_put_u8(msg, NL80211_ATTR_KEY_IDX, key_idx))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
ret = nl80211_wlan_send_and_recv_msg(wlan, msg, NULL, NULL);
|
||||||
|
if ((ret == -ENOENT || ret == -ENOLINK) && alg == 0)
|
||||||
|
ret = 0;
|
||||||
|
if (ret)
|
||||||
|
log_printf(LOG_DEBUG, "nl80211: set_key failed; err=%d %s)",
|
||||||
|
ret, strerror(-ret));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we failed or don't need to set the default TX key (below),
|
||||||
|
* we're done here.
|
||||||
|
*/
|
||||||
|
if (ret || !set_tx || alg == 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (addr && is_broadcast_ether_addr(addr)) {
|
||||||
|
struct nlattr *types;
|
||||||
|
|
||||||
|
msg = nl80211_wlan_msg(wlan, 0, NL80211_CMD_SET_KEY);
|
||||||
|
if (!msg ||
|
||||||
|
nla_put_u8(msg, NL80211_ATTR_KEY_IDX, key_idx) ||
|
||||||
|
nla_put_flag(msg, NL80211_ATTR_KEY_DEFAULT))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
types = nla_nest_start(msg, NL80211_ATTR_KEY_DEFAULT_TYPES);
|
||||||
|
if (!types ||
|
||||||
|
nla_put_flag(msg, NL80211_KEY_DEFAULT_TYPE_MULTICAST))
|
||||||
|
goto fail;
|
||||||
|
nla_nest_end(msg, types);
|
||||||
|
|
||||||
|
ret = nl80211_wlan_send_and_recv_msg(wlan, msg, NULL, NULL);
|
||||||
|
if (ret == -ENOENT)
|
||||||
|
ret = 0;
|
||||||
|
if (ret)
|
||||||
|
log_printf(LOG_DEBUG, "nl80211: set_key default failed; "
|
||||||
|
"err=%d %s)", ret, strerror(-ret));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
nlmsg_free(msg);
|
||||||
|
return -ENOBUFS;
|
||||||
|
}
|
||||||
|
|
||||||
/* */
|
/* */
|
||||||
static int nl80211_wlan_startap(struct wifi_wlan* wlan) {
|
static int nl80211_wlan_startap(struct wifi_wlan* wlan) {
|
||||||
int i;
|
int i;
|
||||||
@ -1006,6 +1159,10 @@ static int nl80211_wlan_startap(struct wifi_wlan* wlan) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (wlan->keylength && wlan->key)
|
||||||
|
nl80211_set_key(wlan, wlan->group_cipher_suite, broadcast_ether_addr,
|
||||||
|
wlan->keyindex, 1, NULL, 0, wlan->key, wlan->keylength);
|
||||||
|
|
||||||
/* Enable operation status */
|
/* Enable operation status */
|
||||||
wlan->flags |= WIFI_WLAN_OPERSTATE_RUNNING;
|
wlan->flags |= WIFI_WLAN_OPERSTATE_RUNNING;
|
||||||
netlink_set_link_status(wlanhandle->devicehandle->globalhandle->netlinkhandle, wlan->virtindex, -1, IF_OPER_UP);
|
netlink_set_link_status(wlanhandle->devicehandle->globalhandle->netlinkhandle, wlan->virtindex, -1, IF_OPER_UP);
|
||||||
@ -2282,6 +2439,7 @@ const struct wifi_driver_ops wifi_driver_nl80211_ops = {
|
|||||||
.wlan_sendframe = nl80211_wlan_sendframe,
|
.wlan_sendframe = nl80211_wlan_sendframe,
|
||||||
.wlan_poll_station = nl80211_wlan_poll_station,
|
.wlan_poll_station = nl80211_wlan_poll_station,
|
||||||
.wlan_delete = nl80211_wlan_delete,
|
.wlan_delete = nl80211_wlan_delete,
|
||||||
|
.wlan_set_key = nl80211_set_key,
|
||||||
|
|
||||||
.station_authorize = nl80211_station_authorize,
|
.station_authorize = nl80211_station_authorize,
|
||||||
.station_deauthorize = nl80211_station_deauthorize,
|
.station_deauthorize = nl80211_station_deauthorize,
|
||||||
|
@ -5,3 +5,5 @@ smartcapwap-y := \
|
|||||||
netlinkapp.o \
|
netlinkapp.o \
|
||||||
capwap.o \
|
capwap.o \
|
||||||
capwap_private.o
|
capwap_private.o
|
||||||
|
|
||||||
|
CFLAGS_capwap.o = -I$(src)
|
||||||
|
486
src/wtp/kmod/capwap-trace.h
Normal file
486
src/wtp/kmod/capwap-trace.h
Normal file
@ -0,0 +1,486 @@
|
|||||||
|
#if !defined(__CAPWAP_DRIVER_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
|
||||||
|
#define __CAPWAP_DRIVER_TRACE_H
|
||||||
|
|
||||||
|
#include <linux/tracepoint.h>
|
||||||
|
#include <net/mac80211.h>
|
||||||
|
#include "capwap.h"
|
||||||
|
|
||||||
|
#undef TRACE_SYSTEM
|
||||||
|
#define TRACE_SYSTEM capwap
|
||||||
|
|
||||||
|
#define SESSION_ENTRY __array(char, sessionid, 16)
|
||||||
|
#define SESSION_ASSIGN ((session) ? memcpy(__entry->sessionid, &session->sessionid, 16) : memset(__entry->sessionid, 0, 16))
|
||||||
|
#define SESSION_PR_FMT " session:%16phN"
|
||||||
|
#define SESSION_PR_ARG __entry->sessionid
|
||||||
|
|
||||||
|
#define SESSIONID_ENTRY __array(char, sessionid, 16)
|
||||||
|
#define SESSIONID_ASSIGN ((sessionid) ? memcpy(__entry->sessionid, sessionid, 16) : memset(__entry->sessionid, 0, 16))
|
||||||
|
#define SESSIONID_PR_FMT " session:%16phN"
|
||||||
|
#define SESSIONID_PR_ARG __entry->sessionid
|
||||||
|
|
||||||
|
#define SKB_ENTRY __field(struct sk_buff *, skb)
|
||||||
|
#define SKB_ASSIGN __entry->skb = skb
|
||||||
|
#define SKB_PR_FMT " skb:%p"
|
||||||
|
#define SKB_PR_ARG __entry->skb
|
||||||
|
|
||||||
|
#define FRAGMENT_ENTRY __field(struct sc_capwap_fragment *, fragment)
|
||||||
|
#define FRAGMENT_ASSIGN __entry->fragment = fragment
|
||||||
|
#define FRAGMENT_PR_FMT " frag:%p"
|
||||||
|
#define FRAGMENT_PR_ARG __entry->fragment
|
||||||
|
|
||||||
|
#define BSSID_ENTRY __array(char, bssid, ETH_ALEN)
|
||||||
|
#define BSSID_ASSIGN (bssid ? memcpy(__entry->bssid, bssid, ETH_ALEN) : memset(__entry->bssid, 0, ETH_ALEN))
|
||||||
|
#define BSSID_PR_FMT " BSS:%pM"
|
||||||
|
#define BSSID_PR_ARG __entry->bssid
|
||||||
|
|
||||||
|
/* capwap.c */
|
||||||
|
|
||||||
|
TRACE_EVENT(sc_capwap_fragment_free,
|
||||||
|
TP_PROTO(struct sc_capwap_fragment *fragment),
|
||||||
|
|
||||||
|
TP_ARGS(fragment),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
FRAGMENT_ENTRY
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
FRAGMENT_ASSIGN;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk(FRAGMENT_PR_FMT, FRAGMENT_PR_ARG)
|
||||||
|
);
|
||||||
|
|
||||||
|
TRACE_EVENT(sc_capwap_freesession,
|
||||||
|
TP_PROTO(struct sc_capwap_session *session),
|
||||||
|
|
||||||
|
TP_ARGS(session),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
SESSION_ENTRY
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
SESSION_ASSIGN;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk(SESSION_PR_FMT, SESSION_PR_ARG)
|
||||||
|
);
|
||||||
|
|
||||||
|
TRACE_EVENT(sc_capwap_defrag_evictor,
|
||||||
|
TP_PROTO(struct sc_capwap_session *session),
|
||||||
|
|
||||||
|
TP_ARGS(session),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
SESSION_ENTRY
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
SESSION_ASSIGN;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk(SESSION_PR_FMT, SESSION_PR_ARG)
|
||||||
|
);
|
||||||
|
|
||||||
|
TRACE_EVENT(sc_capwap_defrag_evictor_fragment_expired,
|
||||||
|
TP_PROTO(struct sc_capwap_session *session,
|
||||||
|
struct sc_capwap_fragment *fragment,
|
||||||
|
ktime_t now),
|
||||||
|
|
||||||
|
TP_ARGS(session,
|
||||||
|
fragment,
|
||||||
|
now),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
SESSION_ENTRY
|
||||||
|
FRAGMENT_ENTRY
|
||||||
|
__field(u64, now)
|
||||||
|
__field(u64, tstamp)
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
SESSION_ASSIGN;
|
||||||
|
FRAGMENT_ASSIGN;
|
||||||
|
__entry->now = now.tv64;
|
||||||
|
__entry->tstamp = fragment->tstamp.tv64;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk(SESSION_PR_FMT FRAGMENT_PR_FMT " (%llu %llu)",
|
||||||
|
SESSION_PR_ARG, FRAGMENT_PR_ARG,
|
||||||
|
__entry->now,
|
||||||
|
__entry->tstamp
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
TRACE_EVENT(sc_capwap_reasm,
|
||||||
|
TP_PROTO(struct sc_capwap_fragment *fragment),
|
||||||
|
|
||||||
|
TP_ARGS(fragment),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
FRAGMENT_ENTRY
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
FRAGMENT_ASSIGN;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk(FRAGMENT_PR_FMT, FRAGMENT_PR_ARG)
|
||||||
|
);
|
||||||
|
|
||||||
|
TRACE_EVENT(sc_capwap_defrag,
|
||||||
|
TP_PROTO(struct sc_capwap_session *session,
|
||||||
|
uint16_t id,
|
||||||
|
uint16_t offset,
|
||||||
|
uint16_t length),
|
||||||
|
|
||||||
|
TP_ARGS(session, id, offset, length),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
SESSION_ENTRY
|
||||||
|
__field(u16, id)
|
||||||
|
__field(u16, offset)
|
||||||
|
__field(u16, length)
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
SESSION_ASSIGN;
|
||||||
|
__entry->id = id;
|
||||||
|
__entry->offset = offset;
|
||||||
|
__entry->length = length;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk(
|
||||||
|
SESSION_PR_FMT " fragment id:%hu offset:%hu length:%hu",
|
||||||
|
SESSION_PR_ARG, __entry->id, __entry->offset, __entry->length
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// TRACEKMOD("** *Fragment info: id %hu offset %hu length %hu\n", frag_id, cb->frag_offset, cb->frag_length);
|
||||||
|
|
||||||
|
TRACE_EVENT(sc_capwap_8023_to_80211,
|
||||||
|
TP_PROTO(struct sk_buff *skb, const uint8_t *bssid),
|
||||||
|
|
||||||
|
TP_ARGS(skb, bssid),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
SKB_ENTRY
|
||||||
|
BSSID_ENTRY
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
SKB_ASSIGN;
|
||||||
|
BSSID_ASSIGN;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk(
|
||||||
|
SKB_PR_FMT BSSID_PR_FMT,
|
||||||
|
SKB_PR_ARG, BSSID_PR_ARG
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
TRACE_EVENT(sc_capwap_80211_to_8023,
|
||||||
|
TP_PROTO(struct sk_buff *skb),
|
||||||
|
|
||||||
|
TP_ARGS(skb),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
SKB_ENTRY
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
SKB_ASSIGN;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk(SKB_PR_FMT, SKB_PR_ARG)
|
||||||
|
);
|
||||||
|
|
||||||
|
TRACE_EVENT(sc_capwap_create,
|
||||||
|
TP_PROTO(struct sc_capwap_session *session),
|
||||||
|
|
||||||
|
TP_ARGS(session),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
SESSION_ENTRY
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
SESSION_ASSIGN;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk(SESSION_PR_FMT, SESSION_PR_ARG)
|
||||||
|
);
|
||||||
|
|
||||||
|
TRACE_EVENT(sc_capwap_close,
|
||||||
|
TP_PROTO(struct sc_capwap_session *session),
|
||||||
|
|
||||||
|
TP_ARGS(session),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
SESSION_ENTRY
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
SESSION_ASSIGN;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk(SESSION_PR_FMT, SESSION_PR_ARG)
|
||||||
|
);
|
||||||
|
|
||||||
|
TRACE_EVENT(sc_capwap_newfragmentid,
|
||||||
|
TP_PROTO(struct sc_capwap_session *session),
|
||||||
|
|
||||||
|
TP_ARGS(session),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
SESSION_ENTRY
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
SESSION_ASSIGN;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk(SESSION_PR_FMT, SESSION_PR_ARG)
|
||||||
|
);
|
||||||
|
|
||||||
|
TRACE_EVENT(sc_capwap_createkeepalive,
|
||||||
|
TP_PROTO(struct sc_capwap_sessionid_element *sessionid),
|
||||||
|
|
||||||
|
TP_ARGS(sessionid),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
SESSIONID_ENTRY
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
SESSIONID_ASSIGN;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk(SESSIONID_PR_FMT, SESSIONID_PR_ARG)
|
||||||
|
);
|
||||||
|
|
||||||
|
TRACE_EVENT(sc_capwap_parsingpacket,
|
||||||
|
TP_PROTO(struct sc_capwap_session *session,
|
||||||
|
struct sk_buff *skb),
|
||||||
|
|
||||||
|
TP_ARGS(session, skb),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
SESSION_ENTRY
|
||||||
|
SKB_ENTRY
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
SESSION_ASSIGN;
|
||||||
|
SKB_ASSIGN;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk(
|
||||||
|
SESSION_PR_FMT SKB_PR_FMT,
|
||||||
|
SESSION_PR_ARG, SKB_PR_ARG
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
TRACE_EVENT(sc_capwap_forwarddata,
|
||||||
|
TP_PROTO(struct sc_capwap_session *session,
|
||||||
|
uint8_t radioid,
|
||||||
|
uint8_t binding,
|
||||||
|
struct sk_buff *skb,
|
||||||
|
uint32_t flags,
|
||||||
|
struct sc_capwap_radio_addr *radioaddr,
|
||||||
|
int radioaddrlength,
|
||||||
|
struct sc_capwap_wireless_information *winfo),
|
||||||
|
|
||||||
|
TP_ARGS(session, radioid, binding, skb, flags, radioaddr, radioaddrlength, winfo),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
SESSION_ENTRY
|
||||||
|
__field(u8, radioid)
|
||||||
|
__field(u8, binding)
|
||||||
|
SKB_ENTRY
|
||||||
|
__field(u32, flags)
|
||||||
|
__field(int, radioaddrlength)
|
||||||
|
__array(char, radioaddr, 8)
|
||||||
|
__field(u8, rssi)
|
||||||
|
__field(u8, snr)
|
||||||
|
__field(u16, rate)
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
SESSION_ASSIGN;
|
||||||
|
__entry->radioid = radioid;
|
||||||
|
__entry->binding = binding;
|
||||||
|
SKB_ASSIGN;
|
||||||
|
__entry->binding = flags;
|
||||||
|
__entry->radioaddrlength = radioaddrlength;
|
||||||
|
((radioaddrlength != 0 && radioaddr) ? memcpy(__entry->radioaddr, radioaddr, min(radioaddrlength, 8)) : memset(__entry->radioaddr, 0, 8));
|
||||||
|
|
||||||
|
__entry->rssi = (winfo) ? ((struct sc_capwap_ieee80211_frame_info *)(winfo))->rssi : 0;
|
||||||
|
__entry->snr = (winfo) ? ((struct sc_capwap_ieee80211_frame_info *)(winfo))->snr : 0;
|
||||||
|
__entry->rate = (winfo) ? ((struct sc_capwap_ieee80211_frame_info *)(winfo))->rate : 0;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk(
|
||||||
|
SESSION_PR_FMT " radio:%d binding:%d" SKB_PR_FMT
|
||||||
|
"radioaddr:%*phC rssid:%d snr:%d rate:%d",
|
||||||
|
SESSION_PR_ARG, __entry->radioid, __entry->binding, SKB_PR_ARG,
|
||||||
|
min(__entry->radioaddrlength, 8), __entry->radioaddr,
|
||||||
|
__entry->rssi, __entry->snr, __entry->rate
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
TRACE_EVENT(sc_capwap_setradiomacaddress,
|
||||||
|
TP_PROTO(uint8_t *bssid),
|
||||||
|
|
||||||
|
TP_ARGS(bssid),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
BSSID_ENTRY
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
BSSID_ASSIGN;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk(BSSID_PR_FMT, BSSID_PR_ARG)
|
||||||
|
);
|
||||||
|
|
||||||
|
TRACE_EVENT(sc_capwap_setwinfo_frameinfo,
|
||||||
|
TP_PROTO(uint8_t rssi,
|
||||||
|
uint8_t snr,
|
||||||
|
uint16_t rate),
|
||||||
|
|
||||||
|
TP_ARGS(rssi, snr, rate),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
__field(u8, rssi)
|
||||||
|
__field(u8, snr)
|
||||||
|
__field(u16, rate)
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
__entry->rssi = rssi;
|
||||||
|
__entry->snr = snr;
|
||||||
|
__entry->rate = rate;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk(
|
||||||
|
" rssid:%d snr:%d rate:%d",
|
||||||
|
__entry->rssi, __entry->snr, __entry->rate
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
TRACE_EVENT(sc_capwap_setwinfo_destwlans,
|
||||||
|
TP_PROTO(uint16_t wlanidbitmap),
|
||||||
|
|
||||||
|
TP_ARGS(wlanidbitmap),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
__field(u16, wlanidbitmap)
|
||||||
|
),
|
||||||
|
TP_fast_assign(
|
||||||
|
__entry->wlanidbitmap = wlanidbitmap;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk(" id:%04x", __entry->wlanidbitmap)
|
||||||
|
);
|
||||||
|
|
||||||
|
/* capwap_private.c */
|
||||||
|
|
||||||
|
TRACE_EVENT(sc_capwap_resetsession,
|
||||||
|
TP_PROTO(struct sc_capwap_session *session),
|
||||||
|
|
||||||
|
TP_ARGS(session),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
SESSION_ENTRY
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
SESSION_ASSIGN;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk(SESSION_PR_FMT, SESSION_PR_ARG)
|
||||||
|
);
|
||||||
|
|
||||||
|
TRACE_EVENT(sc_capwap_sendkeepalive,
|
||||||
|
TP_PROTO(struct sc_capwap_session *session),
|
||||||
|
|
||||||
|
TP_ARGS(session),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
SESSION_ENTRY
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
SESSION_ASSIGN;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk(SESSION_PR_FMT, SESSION_PR_ARG)
|
||||||
|
);
|
||||||
|
|
||||||
|
TRACE_EVENT(sc_capwap_send,
|
||||||
|
TP_PROTO(struct sc_capwap_session *session),
|
||||||
|
|
||||||
|
TP_ARGS(session),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
SESSION_ENTRY
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
SESSION_ASSIGN;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk(SESSION_PR_FMT, SESSION_PR_ARG)
|
||||||
|
);
|
||||||
|
|
||||||
|
TRACE_EVENT(sc_send_80211,
|
||||||
|
TP_PROTO(struct sk_buff *skb, struct net_device *dev),
|
||||||
|
|
||||||
|
TP_ARGS(skb, dev),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
SKB_ENTRY
|
||||||
|
__array(char, dev_name, 32)
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
SKB_ASSIGN;
|
||||||
|
strlcpy(__entry->dev_name, dev->name, 32);
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk(" %s" SKB_PR_FMT, __entry->dev_name, SKB_PR_ARG)
|
||||||
|
);
|
||||||
|
|
||||||
|
TRACE_EVENT(sc_capwap_parsingdatapacket,
|
||||||
|
TP_PROTO(struct sc_capwap_session *session,
|
||||||
|
struct sk_buff *skb),
|
||||||
|
|
||||||
|
TP_ARGS(session, skb),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
SESSION_ENTRY
|
||||||
|
SKB_ENTRY
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
SESSION_ASSIGN;
|
||||||
|
SKB_ASSIGN;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk(
|
||||||
|
SESSION_PR_FMT SKB_PR_FMT,
|
||||||
|
SESSION_PR_ARG, SKB_PR_ARG
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
#endif /* !__CAPWAP_DRIVER_TRACE_H || TRACE_HEADER_MULTI_READ */
|
||||||
|
|
||||||
|
#undef TRACE_INCLUDE_PATH
|
||||||
|
#define TRACE_INCLUDE_PATH .
|
||||||
|
#undef TRACE_INCLUDE_FILE
|
||||||
|
#define TRACE_INCLUDE_FILE capwap-trace
|
||||||
|
#include <trace/define_trace.h>
|
@ -10,6 +10,9 @@
|
|||||||
#include "nlsmartcapwap.h"
|
#include "nlsmartcapwap.h"
|
||||||
#include "netlinkapp.h"
|
#include "netlinkapp.h"
|
||||||
|
|
||||||
|
#define CREATE_TRACE_POINTS
|
||||||
|
#include "capwap-trace.h"
|
||||||
|
|
||||||
/* Ethernet-II snap header (RFC1042 for most EtherTypes) */
|
/* Ethernet-II snap header (RFC1042 for most EtherTypes) */
|
||||||
static const unsigned char sc_rfc1042_header[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
|
static const unsigned char sc_rfc1042_header[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
|
||||||
|
|
||||||
@ -19,7 +22,7 @@ static const unsigned char sc_bridge_tunnel_header[] = { 0xaa, 0xaa, 0x03, 0x00,
|
|||||||
/* */
|
/* */
|
||||||
static void sc_capwap_fragment_free(struct sc_capwap_fragment* fragment)
|
static void sc_capwap_fragment_free(struct sc_capwap_fragment* fragment)
|
||||||
{
|
{
|
||||||
TRACEKMOD("### sc_capwap_fragment_free\n");
|
trace_sc_capwap_fragment_free(fragment);
|
||||||
|
|
||||||
/* */
|
/* */
|
||||||
list_del(&fragment->lru_list);
|
list_del(&fragment->lru_list);
|
||||||
@ -42,7 +45,7 @@ static void sc_capwap_freesession(struct sc_capwap_session* session)
|
|||||||
struct sc_capwap_fragment* fragment;
|
struct sc_capwap_fragment* fragment;
|
||||||
struct sc_station *sta;
|
struct sc_station *sta;
|
||||||
|
|
||||||
TRACEKMOD("### sc_capwap_freesession\n");
|
trace_sc_capwap_freesession(session);
|
||||||
|
|
||||||
/* Free socket buffers */
|
/* Free socket buffers */
|
||||||
list_for_each_entry_safe(fragment, temp, &session->fragments.lru_list, lru_list) {
|
list_for_each_entry_safe(fragment, temp, &session->fragments.lru_list, lru_list) {
|
||||||
@ -63,7 +66,7 @@ static void sc_capwap_defrag_evictor(struct sc_capwap_session* session, ktime_t
|
|||||||
struct sc_capwap_fragment* fragment;
|
struct sc_capwap_fragment* fragment;
|
||||||
struct list_head* list = &session->fragments.lru_list;
|
struct list_head* list = &session->fragments.lru_list;
|
||||||
|
|
||||||
TRACEKMOD("### sc_capwap_defrag_evictor\n");
|
trace_sc_capwap_defrag_evictor(session);
|
||||||
|
|
||||||
/* Light check without lock */
|
/* Light check without lock */
|
||||||
if (!list_empty(list)) {
|
if (!list_empty(list)) {
|
||||||
@ -74,7 +77,7 @@ static void sc_capwap_defrag_evictor(struct sc_capwap_session* session, ktime_t
|
|||||||
fragment = list_first_entry(list, struct sc_capwap_fragment, lru_list);
|
fragment = list_first_entry(list, struct sc_capwap_fragment, lru_list);
|
||||||
delta = ktime_sub(now, fragment->tstamp);
|
delta = ktime_sub(now, fragment->tstamp);
|
||||||
if ((delta.tv64 < -NSEC_PER_SEC) || (delta.tv64 > NSEC_PER_SEC)) {
|
if ((delta.tv64 < -NSEC_PER_SEC) || (delta.tv64 > NSEC_PER_SEC)) {
|
||||||
TRACEKMOD("*** Expired fragment %hu (%llu %llu)\n", fragment->fragmentid, now.tv64, fragment->tstamp.tv64);
|
trace_sc_capwap_defrag_evictor_fragment_expired(session, fragment, now);
|
||||||
sc_capwap_fragment_free(fragment);
|
sc_capwap_fragment_free(fragment);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -91,7 +94,7 @@ static struct sk_buff* sc_capwap_reasm(struct sc_capwap_fragment* fragment) {
|
|||||||
struct sk_buff* skbfrag;
|
struct sk_buff* skbfrag;
|
||||||
struct sc_capwap_header* header;
|
struct sc_capwap_header* header;
|
||||||
|
|
||||||
TRACEKMOD("### sc_capwap_reasm\n");
|
trace_sc_capwap_reasm(fragment);
|
||||||
|
|
||||||
/* */
|
/* */
|
||||||
skbfrag = fragment->fragments;
|
skbfrag = fragment->fragments;
|
||||||
@ -140,8 +143,6 @@ static struct sk_buff* sc_capwap_defrag(struct sc_capwap_session* session, struc
|
|||||||
struct sk_buff* skb_defrag = NULL;
|
struct sk_buff* skb_defrag = NULL;
|
||||||
struct sc_capwap_header* header = (struct sc_capwap_header*)skb->data;
|
struct sc_capwap_header* header = (struct sc_capwap_header*)skb->data;
|
||||||
|
|
||||||
TRACEKMOD("### sc_capwap_defrag\n");
|
|
||||||
|
|
||||||
/* */
|
/* */
|
||||||
headersize = GET_HLEN_HEADER(header) * 4;
|
headersize = GET_HLEN_HEADER(header) * 4;
|
||||||
if (skb->len < headersize) {
|
if (skb->len < headersize) {
|
||||||
@ -157,9 +158,10 @@ static struct sk_buff* sc_capwap_defrag(struct sc_capwap_session* session, struc
|
|||||||
cb->frag_offset = be16_to_cpu(header->frag_off);
|
cb->frag_offset = be16_to_cpu(header->frag_off);
|
||||||
cb->frag_length = skb->len - headersize;
|
cb->frag_length = skb->len - headersize;
|
||||||
|
|
||||||
|
trace_sc_capwap_defrag(session, frag_id, cb->frag_offset, cb->frag_length);
|
||||||
|
|
||||||
/* */
|
/* */
|
||||||
spin_lock(&session->fragments.lock);
|
spin_lock(&session->fragments.lock);
|
||||||
TRACEKMOD("*** Fragment info: id %hu offset %hu length %hu\n", frag_id, cb->frag_offset, cb->frag_length);
|
|
||||||
|
|
||||||
/* Get fragment */
|
/* Get fragment */
|
||||||
fragment = &session->fragments.queues[frag_id % CAPWAP_FRAGMENT_QUEUE];
|
fragment = &session->fragments.queues[frag_id % CAPWAP_FRAGMENT_QUEUE];
|
||||||
@ -266,8 +268,6 @@ error:
|
|||||||
static unsigned int sc_capwap_80211_hdrlen(__le16 fc) {
|
static unsigned int sc_capwap_80211_hdrlen(__le16 fc) {
|
||||||
unsigned int hdrlen = 24;
|
unsigned int hdrlen = 24;
|
||||||
|
|
||||||
TRACEKMOD("### sc_capwap_80211_hdrlen\n");
|
|
||||||
|
|
||||||
if (ieee80211_is_data(fc)) {
|
if (ieee80211_is_data(fc)) {
|
||||||
if (ieee80211_has_a4(fc)) {
|
if (ieee80211_has_a4(fc)) {
|
||||||
hdrlen = 30;
|
hdrlen = 30;
|
||||||
@ -301,7 +301,7 @@ int sc_capwap_8023_to_80211(struct sk_buff* skb, const uint8_t* bssid) {
|
|||||||
struct ethhdr* eh = (struct ethhdr*)skb->data;
|
struct ethhdr* eh = (struct ethhdr*)skb->data;
|
||||||
uint16_t ethertype = ntohs(eh->h_proto);
|
uint16_t ethertype = ntohs(eh->h_proto);
|
||||||
|
|
||||||
TRACEKMOD("### sc_capwap_8023_to_80211\n");
|
trace_sc_capwap_8023_to_80211(skb, bssid);
|
||||||
|
|
||||||
/* IEEE 802.11 header */
|
/* IEEE 802.11 header */
|
||||||
hdrlen = 24;
|
hdrlen = 24;
|
||||||
@ -367,7 +367,7 @@ int sc_capwap_80211_to_8023(struct sk_buff* skb) {
|
|||||||
uint8_t dst[ETH_ALEN];
|
uint8_t dst[ETH_ALEN];
|
||||||
uint8_t src[ETH_ALEN] __aligned(2);
|
uint8_t src[ETH_ALEN] __aligned(2);
|
||||||
|
|
||||||
TRACEKMOD("### sc_capwap_80211_to_8023\n");
|
trace_sc_capwap_80211_to_8023(skb);
|
||||||
|
|
||||||
/* */
|
/* */
|
||||||
hdrlen = sc_capwap_80211_hdrlen(hdr->frame_control);
|
hdrlen = sc_capwap_80211_hdrlen(hdr->frame_control);
|
||||||
@ -411,7 +411,7 @@ int sc_capwap_create(struct sc_capwap_session *session)
|
|||||||
.encap_rcv = sc_capwap_recvpacket
|
.encap_rcv = sc_capwap_recvpacket
|
||||||
};
|
};
|
||||||
|
|
||||||
TRACEKMOD("### sc_capwap_bind\n");
|
trace_sc_capwap_create(session);
|
||||||
|
|
||||||
if (session->socket)
|
if (session->socket)
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
@ -441,7 +441,7 @@ error:
|
|||||||
|
|
||||||
void sc_capwap_close(struct sc_capwap_session *session)
|
void sc_capwap_close(struct sc_capwap_session *session)
|
||||||
{
|
{
|
||||||
TRACEKMOD("### sc_capwap_close\n");
|
trace_sc_capwap_close(session);
|
||||||
|
|
||||||
if (session->socket)
|
if (session->socket)
|
||||||
udp_tunnel_sock_release(session->socket);
|
udp_tunnel_sock_release(session->socket);
|
||||||
@ -453,7 +453,7 @@ void sc_capwap_close(struct sc_capwap_session *session)
|
|||||||
/* */
|
/* */
|
||||||
static uint16_t sc_capwap_newfragmentid(struct sc_capwap_session* session)
|
static uint16_t sc_capwap_newfragmentid(struct sc_capwap_session* session)
|
||||||
{
|
{
|
||||||
TRACEKMOD("### sc_capwap_newfragmentid\n");
|
trace_sc_capwap_newfragmentid(session);
|
||||||
|
|
||||||
return atomic_inc_return(&session->fragmentid) & 0xFFFF;
|
return atomic_inc_return(&session->fragmentid) & 0xFFFF;
|
||||||
}
|
}
|
||||||
@ -465,7 +465,7 @@ int sc_capwap_createkeepalive(struct sc_capwap_sessionid_element* sessionid, uin
|
|||||||
struct sc_capwap_data_message* dataheader;
|
struct sc_capwap_data_message* dataheader;
|
||||||
struct sc_capwap_message_element* msgelement;
|
struct sc_capwap_message_element* msgelement;
|
||||||
|
|
||||||
TRACEKMOD("### sc_capwap_createkeepalive\n");
|
trace_sc_capwap_createkeepalive(sessionid);
|
||||||
|
|
||||||
/* */
|
/* */
|
||||||
if (size < CAPWAP_KEEP_ALIVE_MAX_SIZE) {
|
if (size < CAPWAP_KEEP_ALIVE_MAX_SIZE) {
|
||||||
@ -515,7 +515,7 @@ int sc_capwap_parsingpacket(struct sc_capwap_session* session,
|
|||||||
struct sc_capwap_message_element* message;
|
struct sc_capwap_message_element* message;
|
||||||
struct sc_capwap_header* header = (struct sc_capwap_header*)skb->data;
|
struct sc_capwap_header* header = (struct sc_capwap_header*)skb->data;
|
||||||
|
|
||||||
TRACEKMOD("### sc_capwap_parsingpacket\n");
|
trace_sc_capwap_parsingpacket(session, skb);
|
||||||
|
|
||||||
/* Linearize socket buffer */
|
/* Linearize socket buffer */
|
||||||
if (skb_linearize(skb)) {
|
if (skb_linearize(skb)) {
|
||||||
@ -637,7 +637,16 @@ int sc_capwap_parsingpacket(struct sc_capwap_session* session,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* */
|
/* */
|
||||||
int sc_capwap_forwarddata(struct sc_capwap_session* session, uint8_t radioid, uint8_t binding, struct sk_buff* skb, uint32_t flags, struct sc_capwap_radio_addr* radioaddr, int radioaddrlength, struct sc_capwap_wireless_information* winfo, int winfolength) {
|
int sc_capwap_forwarddata(struct sc_capwap_session* session,
|
||||||
|
uint8_t radioid,
|
||||||
|
uint8_t binding,
|
||||||
|
struct sk_buff* skb,
|
||||||
|
uint32_t flags,
|
||||||
|
struct sc_capwap_radio_addr* radioaddr,
|
||||||
|
int radioaddrlength,
|
||||||
|
struct sc_capwap_wireless_information* winfo,
|
||||||
|
int winfolength)
|
||||||
|
{
|
||||||
int err;
|
int err;
|
||||||
int size;
|
int size;
|
||||||
int length;
|
int length;
|
||||||
@ -650,7 +659,7 @@ int sc_capwap_forwarddata(struct sc_capwap_session* session, uint8_t radioid, ui
|
|||||||
struct sk_buff* clone = NULL;
|
struct sk_buff* clone = NULL;
|
||||||
int packetlength = skb->len;
|
int packetlength = skb->len;
|
||||||
|
|
||||||
TRACEKMOD("### sc_capwap_forwarddata\n");
|
trace_sc_capwap_forwarddata(session, radioid, binding, skb, flags, radioaddr, radioaddrlength, winfo);
|
||||||
|
|
||||||
/* Check headroom */
|
/* Check headroom */
|
||||||
headroom = skb_headroom(skb);
|
headroom = skb_headroom(skb);
|
||||||
@ -745,25 +754,12 @@ int sc_capwap_forwarddata(struct sc_capwap_session* session, uint8_t radioid, ui
|
|||||||
return (!packetlength ? 0 : -EIO);
|
return (!packetlength ? 0 : -EIO);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* */
|
|
||||||
void sc_capwap_sessionid_printf(const struct sc_capwap_sessionid_element* sessionid, char* string) {
|
|
||||||
int i;
|
|
||||||
char* pos = string;
|
|
||||||
|
|
||||||
for (i = 0; i < 16; i++) {
|
|
||||||
snprintf(pos, 3, "%02x", sessionid->id[i]);
|
|
||||||
pos += 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
*pos = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* */
|
/* */
|
||||||
struct sc_capwap_radio_addr* sc_capwap_setradiomacaddress(uint8_t* buffer, int size, uint8_t* bssid) {
|
struct sc_capwap_radio_addr* sc_capwap_setradiomacaddress(uint8_t* buffer, int size, uint8_t* bssid) {
|
||||||
struct sc_capwap_radio_addr* radioaddr;
|
struct sc_capwap_radio_addr* radioaddr;
|
||||||
struct sc_capwap_macaddress_eui48* addr;
|
struct sc_capwap_macaddress_eui48* addr;
|
||||||
|
|
||||||
TRACEKMOD("### sc_capwap_setwirelessinformation\n");
|
trace_sc_capwap_setradiomacaddress(bssid);
|
||||||
|
|
||||||
memset(buffer, 0, size);
|
memset(buffer, 0, size);
|
||||||
|
|
||||||
@ -781,7 +777,7 @@ struct sc_capwap_wireless_information* sc_capwap_setwinfo_frameinfo(uint8_t* buf
|
|||||||
struct sc_capwap_wireless_information* winfo;
|
struct sc_capwap_wireless_information* winfo;
|
||||||
struct sc_capwap_ieee80211_frame_info* frameinfo;
|
struct sc_capwap_ieee80211_frame_info* frameinfo;
|
||||||
|
|
||||||
TRACEKMOD("### sc_capwap_setwinfo_frameinfo\n");
|
trace_sc_capwap_setwinfo_frameinfo(rssi, snr, rate);
|
||||||
|
|
||||||
memset(buffer, 0, size);
|
memset(buffer, 0, size);
|
||||||
|
|
||||||
@ -801,7 +797,7 @@ struct sc_capwap_wireless_information* sc_capwap_setwinfo_destwlans(uint8_t* buf
|
|||||||
struct sc_capwap_wireless_information* winfo;
|
struct sc_capwap_wireless_information* winfo;
|
||||||
struct sc_capwap_destination_wlans* destwlans;
|
struct sc_capwap_destination_wlans* destwlans;
|
||||||
|
|
||||||
TRACEKMOD("### sc_capwap_setwinfo_destwlans\n");
|
trace_sc_capwap_setwinfo_destwlans(wlanidbitmap);
|
||||||
|
|
||||||
memset(buffer, 0, size);
|
memset(buffer, 0, size);
|
||||||
|
|
||||||
|
@ -50,12 +50,15 @@ union capwap_addr {
|
|||||||
struct sockaddr_storage ss;
|
struct sockaddr_storage ss;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define STA_FLAG_AKM_ONLY 0x0001
|
||||||
|
|
||||||
struct sc_station {
|
struct sc_station {
|
||||||
struct hlist_node station_list;
|
struct hlist_node station_list;
|
||||||
|
|
||||||
uint8_t radioid;
|
uint8_t radioid;
|
||||||
uint8_t mac[ETH_ALEN];
|
uint8_t mac[ETH_ALEN];
|
||||||
uint8_t wlanid;
|
uint8_t wlanid;
|
||||||
|
uint32_t flags;
|
||||||
|
|
||||||
struct rcu_head rcu_head;
|
struct rcu_head rcu_head;
|
||||||
};
|
};
|
||||||
@ -136,8 +139,6 @@ void sc_capwap_close(struct sc_capwap_session *session);
|
|||||||
int sc_capwap_8023_to_80211(struct sk_buff* skb, const uint8_t* bssid);
|
int sc_capwap_8023_to_80211(struct sk_buff* skb, const uint8_t* bssid);
|
||||||
int sc_capwap_80211_to_8023(struct sk_buff* skb);
|
int sc_capwap_80211_to_8023(struct sk_buff* skb);
|
||||||
|
|
||||||
void sc_capwap_sessionid_printf(const struct sc_capwap_sessionid_element* sessionid, char* string);
|
|
||||||
|
|
||||||
int sc_capwap_createkeepalive(struct sc_capwap_sessionid_element* sessionid, uint8_t* buffer, int size);
|
int sc_capwap_createkeepalive(struct sc_capwap_sessionid_element* sessionid, uint8_t* buffer, int size);
|
||||||
int sc_capwap_parsingpacket(struct sc_capwap_session* session, struct sk_buff* skb);
|
int sc_capwap_parsingpacket(struct sc_capwap_session* session, struct sk_buff* skb);
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "capwap.h"
|
#include "capwap.h"
|
||||||
#include "nlsmartcapwap.h"
|
#include "nlsmartcapwap.h"
|
||||||
#include "netlinkapp.h"
|
#include "netlinkapp.h"
|
||||||
|
#include "capwap-trace.h"
|
||||||
|
|
||||||
/* */
|
/* */
|
||||||
int sc_capwap_init(struct sc_capwap_session *session, struct net *net)
|
int sc_capwap_init(struct sc_capwap_session *session, struct net *net)
|
||||||
@ -42,7 +43,7 @@ int sc_capwap_init(struct sc_capwap_session *session, struct net *net)
|
|||||||
/* */
|
/* */
|
||||||
void sc_capwap_resetsession(struct sc_capwap_session *session)
|
void sc_capwap_resetsession(struct sc_capwap_session *session)
|
||||||
{
|
{
|
||||||
TRACEKMOD("### sc_capwap_resetsession\n");
|
trace_sc_capwap_resetsession(session);
|
||||||
|
|
||||||
sc_capwap_close(session);
|
sc_capwap_close(session);
|
||||||
sc_capwap_init(session, session->net);
|
sc_capwap_init(session, session->net);
|
||||||
@ -55,7 +56,7 @@ int sc_capwap_sendkeepalive(struct sc_capwap_session *session)
|
|||||||
int length;
|
int length;
|
||||||
uint8_t buffer[CAPWAP_KEEP_ALIVE_MAX_SIZE];
|
uint8_t buffer[CAPWAP_KEEP_ALIVE_MAX_SIZE];
|
||||||
|
|
||||||
TRACEKMOD("### sc_capwap_sendkeepalive\n");
|
trace_sc_capwap_sendkeepalive(session);
|
||||||
|
|
||||||
/* Build keepalive */
|
/* Build keepalive */
|
||||||
length = sc_capwap_createkeepalive(&session->sessionid, buffer, CAPWAP_KEEP_ALIVE_MAX_SIZE);
|
length = sc_capwap_createkeepalive(&session->sessionid, buffer, CAPWAP_KEEP_ALIVE_MAX_SIZE);
|
||||||
@ -80,7 +81,7 @@ int sc_capwap_send(struct sc_capwap_session *session, uint8_t* buffer, int lengt
|
|||||||
.msg_flags = MSG_DONTWAIT | MSG_NOSIGNAL,
|
.msg_flags = MSG_DONTWAIT | MSG_NOSIGNAL,
|
||||||
};
|
};
|
||||||
|
|
||||||
TRACEKMOD("### sc_capwap_send\n");
|
trace_sc_capwap_send(session);
|
||||||
|
|
||||||
return kernel_sendmsg(session->socket, &msg, &vec, 1, vec.iov_len);
|
return kernel_sendmsg(session->socket, &msg, &vec, 1, vec.iov_len);
|
||||||
}
|
}
|
||||||
@ -169,11 +170,8 @@ static void sc_send_8023(struct sk_buff *skb, struct net_device *dev)
|
|||||||
static void sc_send_80211(struct sk_buff *skb, struct net_device *dev)
|
static void sc_send_80211(struct sk_buff *skb, struct net_device *dev)
|
||||||
{
|
{
|
||||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||||
struct ieee80211_hdr *hdr;
|
|
||||||
int hdrlen;
|
|
||||||
|
|
||||||
printk(KERN_DEBUG "capwap inject: %s: hdr: %p\n",
|
trace_sc_send_80211(skb, dev);
|
||||||
dev->name, skb->data);
|
|
||||||
|
|
||||||
/* detach skb from CAPWAP */
|
/* detach skb from CAPWAP */
|
||||||
skb_orphan(skb);
|
skb_orphan(skb);
|
||||||
@ -185,17 +183,15 @@ static void sc_send_80211(struct sk_buff *skb, struct net_device *dev)
|
|||||||
/* drop conntrack reference */
|
/* drop conntrack reference */
|
||||||
nf_reset(skb);
|
nf_reset(skb);
|
||||||
|
|
||||||
hdr = (struct ieee80211_hdr *)skb->data;
|
skb_reset_mac_header(skb);
|
||||||
hdrlen = ieee80211_hdrlen(hdr->frame_control);
|
skb_reset_network_header(skb);
|
||||||
|
skb_reset_transport_header(skb);
|
||||||
|
|
||||||
skb->dev = dev;
|
skb->dev = dev;
|
||||||
|
|
||||||
skb_set_mac_header(skb, hdrlen);
|
|
||||||
skb_set_network_header(skb, hdrlen);
|
|
||||||
skb_set_transport_header(skb, hdrlen);
|
|
||||||
|
|
||||||
skb->protocol = htons(ETH_P_CONTROL);
|
skb->protocol = htons(ETH_P_CONTROL);
|
||||||
info->flags |= IEEE80211_TX_CTL_INJECTED;
|
|
||||||
|
memset(info, 0, sizeof(*info));
|
||||||
|
info->flags = IEEE80211_TX_CTL_INJECTED;
|
||||||
|
|
||||||
/* Force the device to verify it. */
|
/* Force the device to verify it. */
|
||||||
skb->ip_summed = CHECKSUM_NONE;
|
skb->ip_summed = CHECKSUM_NONE;
|
||||||
@ -217,7 +213,7 @@ void sc_capwap_parsingdatapacket(struct sc_capwap_session* session, struct sk_bu
|
|||||||
struct sc_capwap_destination_wlans* destwlan = NULL;
|
struct sc_capwap_destination_wlans* destwlan = NULL;
|
||||||
int winfosize = 0;
|
int winfosize = 0;
|
||||||
|
|
||||||
TRACEKMOD("### sc_capwap_parsingdatapacket\n");
|
trace_sc_capwap_parsingdatapacket(session, skb);
|
||||||
|
|
||||||
/* Retrieve optional attribute */
|
/* Retrieve optional attribute */
|
||||||
pos = skb->data + sizeof(struct sc_capwap_header);
|
pos = skb->data + sizeof(struct sc_capwap_header);
|
||||||
|
@ -85,32 +85,58 @@ static int sc_netlink_handler(uint32_t ifindex, struct sk_buff* skb,
|
|||||||
int err;
|
int err;
|
||||||
uint8_t radioaddrbuffer[CAPWAP_RADIO_EUI48_LENGTH_PADDED];
|
uint8_t radioaddrbuffer[CAPWAP_RADIO_EUI48_LENGTH_PADDED];
|
||||||
uint8_t winfobuffer[CAPWAP_WINFO_FRAMEINFO_LENGTH_PADDED];
|
uint8_t winfobuffer[CAPWAP_WINFO_FRAMEINFO_LENGTH_PADDED];
|
||||||
|
uint16_t hdrlen, ethertype;
|
||||||
|
uint8_t *payload;
|
||||||
struct sc_capwap_radio_addr* radioaddr = NULL;
|
struct sc_capwap_radio_addr* radioaddr = NULL;
|
||||||
struct sc_capwap_wireless_information* winfo = NULL;
|
struct sc_capwap_wireless_information* winfo = NULL;
|
||||||
|
uint32_t flags = nldev->flags;
|
||||||
|
|
||||||
/* Drop packet */
|
/* Drop packet */
|
||||||
ret = -1;
|
ret = -1;
|
||||||
|
|
||||||
|
hdrlen = ieee80211_hdrlen(hdr->frame_control);
|
||||||
|
if (!pskb_may_pull(skb, hdrlen + 8))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
payload = skb->data + hdrlen;
|
||||||
|
ethertype = (payload[6] << 8) | payload[7];
|
||||||
|
|
||||||
|
TRACEKMOD("### sc_netlink_handler, ethertype %04x\n", ethertype);
|
||||||
|
|
||||||
|
switch (ethertype) {
|
||||||
|
case ETH_P_PAE:
|
||||||
|
/* forward EAPOL as raw 802.11 frame, clear 802.3 tunnel flag */
|
||||||
|
flags &= ~NLSMARTCAPWAP_FLAGS_TUNNEL_8023;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
/* IEEE 802.11 into IEEE 802.3 */
|
/* IEEE 802.11 into IEEE 802.3 */
|
||||||
if (nldev->flags & NLSMARTCAPWAP_FLAGS_TUNNEL_8023) {
|
if (nldev->flags & NLSMARTCAPWAP_FLAGS_TUNNEL_8023) {
|
||||||
if (ieee80211_data_to_8023(skb, nldev->dev->dev_addr, NL80211_IFTYPE_AP)) {
|
if (ieee80211_data_to_8023(skb, nldev->dev->dev_addr, NL80211_IFTYPE_AP))
|
||||||
goto error;
|
goto error;
|
||||||
}
|
|
||||||
|
|
||||||
/* Create Radio Mac Address */
|
/* Create Radio Mac Address */
|
||||||
radioaddr = sc_capwap_setradiomacaddress(radioaddrbuffer, CAPWAP_RADIO_EUI48_LENGTH_PADDED, nldev->dev->dev_addr);
|
radioaddr =
|
||||||
|
sc_capwap_setradiomacaddress(radioaddrbuffer,
|
||||||
|
CAPWAP_RADIO_EUI48_LENGTH_PADDED,
|
||||||
|
nldev->dev->dev_addr);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create Wireless Information */
|
/* Create Wireless Information */
|
||||||
if (sig_dbm || rate) {
|
if (sig_dbm || rate)
|
||||||
winfo = sc_capwap_setwinfo_frameinfo(winfobuffer, CAPWAP_WINFO_FRAMEINFO_LENGTH_PADDED, (uint8_t)sig_dbm, 0, ((uint16_t)rate) * 5);
|
winfo = sc_capwap_setwinfo_frameinfo(winfobuffer,
|
||||||
}
|
CAPWAP_WINFO_FRAMEINFO_LENGTH_PADDED,
|
||||||
|
(uint8_t)sig_dbm, 0, ((uint16_t)rate) * 5);
|
||||||
|
|
||||||
/* */
|
/* */
|
||||||
CAPWAP_SKB_CB(skb)->flags = SKB_CAPWAP_FLAG_FROM_IEEE80211;
|
CAPWAP_SKB_CB(skb)->flags = SKB_CAPWAP_FLAG_FROM_IEEE80211;
|
||||||
|
|
||||||
/* Forward to AC */
|
/* Forward to AC */
|
||||||
err = sc_capwap_forwarddata(&sn->sc_acsession, nldev->radioid, nldev->binding, skb, nldev->flags, radioaddr, (radioaddr ? CAPWAP_RADIO_EUI48_LENGTH_PADDED : 0), winfo, (winfo ? CAPWAP_WINFO_FRAMEINFO_LENGTH_PADDED : 0));
|
err = sc_capwap_forwarddata(&sn->sc_acsession, nldev->radioid, nldev->binding, skb, flags,
|
||||||
|
radioaddr, (radioaddr ? CAPWAP_RADIO_EUI48_LENGTH_PADDED : 0),
|
||||||
|
winfo, (winfo ? CAPWAP_WINFO_FRAMEINFO_LENGTH_PADDED : 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
error:
|
error:
|
||||||
@ -642,7 +668,8 @@ static int sc_netlink_add_station(struct sk_buff* skb, struct genl_info* info)
|
|||||||
|
|
||||||
if (!info->attrs[NLSMARTCAPWAP_ATTR_RADIOID] ||
|
if (!info->attrs[NLSMARTCAPWAP_ATTR_RADIOID] ||
|
||||||
!info->attrs[NLSMARTCAPWAP_ATTR_MAC] ||
|
!info->attrs[NLSMARTCAPWAP_ATTR_MAC] ||
|
||||||
!info->attrs[NLSMARTCAPWAP_ATTR_WLANID])
|
!info->attrs[NLSMARTCAPWAP_ATTR_WLANID] ||
|
||||||
|
!info->attrs[NLSMARTCAPWAP_ATTR_FLAGS])
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
radioid = nla_get_u8(info->attrs[NLSMARTCAPWAP_ATTR_RADIOID]);
|
radioid = nla_get_u8(info->attrs[NLSMARTCAPWAP_ATTR_RADIOID]);
|
||||||
@ -650,12 +677,18 @@ static int sc_netlink_add_station(struct sk_buff* skb, struct genl_info* info)
|
|||||||
hash = jhash(mac, ETH_ALEN, radioid) % STA_HASH_SIZE;
|
hash = jhash(mac, ETH_ALEN, radioid) % STA_HASH_SIZE;
|
||||||
sta_head = &session->station_list[hash];
|
sta_head = &session->station_list[hash];
|
||||||
|
|
||||||
if (sc_find_station(sta_head, radioid, mac) != NULL)
|
sta = sc_find_station(sta_head, radioid, mac);
|
||||||
|
if (sta) {
|
||||||
|
if (!(info->nlhdr->nlmsg_flags & NLM_F_REPLACE))
|
||||||
return -EEXIST;
|
return -EEXIST;
|
||||||
|
|
||||||
if (info->nlhdr->nlmsg_flags & NLM_F_REPLACE)
|
if (sta->wlanid != nla_get_u8(info->attrs[NLSMARTCAPWAP_ATTR_WLANID]))
|
||||||
return -ENXIO;
|
return -ENXIO;
|
||||||
|
|
||||||
|
sta->flags = nla_get_u32(info->attrs[NLSMARTCAPWAP_ATTR_FLAGS]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
sta = kmalloc(sizeof(struct sc_station), GFP_KERNEL);
|
sta = kmalloc(sizeof(struct sc_station), GFP_KERNEL);
|
||||||
if (sta == NULL)
|
if (sta == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
@ -663,6 +696,7 @@ static int sc_netlink_add_station(struct sk_buff* skb, struct genl_info* info)
|
|||||||
sta->radioid = radioid;
|
sta->radioid = radioid;
|
||||||
memcpy(&sta->mac, mac, ETH_ALEN);
|
memcpy(&sta->mac, mac, ETH_ALEN);
|
||||||
sta->wlanid = nla_get_u8(info->attrs[NLSMARTCAPWAP_ATTR_WLANID]);
|
sta->wlanid = nla_get_u8(info->attrs[NLSMARTCAPWAP_ATTR_WLANID]);
|
||||||
|
sta->flags = nla_get_u32(info->attrs[NLSMARTCAPWAP_ATTR_FLAGS]);
|
||||||
|
|
||||||
hlist_add_head_rcu(&sta->station_list, sta_head);
|
hlist_add_head_rcu(&sta->station_list, sta_head);
|
||||||
|
|
||||||
|
@ -242,7 +242,7 @@ static void receive_ieee80211_wlan_configuration_request(struct capwap_parsed_pa
|
|||||||
/* Add message element */
|
/* Add message element */
|
||||||
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_RESULTCODE, &resultcode);
|
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_RESULTCODE, &resultcode);
|
||||||
if (resultcode.code == CAPWAP_RESULTCODE_SUCCESS &&
|
if (resultcode.code == CAPWAP_RESULTCODE_SUCCESS &&
|
||||||
memcmp(&action, &CAPWAP_ELEMENT_80211_ADD_WLAN, sizeof(CAPWAP_ELEMENT_80211_ADD_WLAN)) == 0)
|
message_element_id_eq(action, CAPWAP_ELEMENT_80211_ADD_WLAN))
|
||||||
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_ASSIGN_BSSID, &bssid);
|
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_ASSIGN_BSSID, &bssid);
|
||||||
|
|
||||||
/* CAPWAP_ELEMENT_VENDORPAYLOAD */ /* TODO */
|
/* CAPWAP_ELEMENT_VENDORPAYLOAD */ /* TODO */
|
||||||
|
@ -438,7 +438,7 @@ int wtp_kmod_leave_mac80211_device(struct wifi_wlan* wlan) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* */
|
/* */
|
||||||
int wtp_kmod_add_station(uint8_t radioid, const uint8_t *mac, uint8_t wlanid)
|
int wtp_kmod_add_station(uint8_t radioid, const uint8_t *mac, uint8_t wlanid, uint32_t flags)
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
struct nl_msg* msg;
|
struct nl_msg* msg;
|
||||||
@ -453,10 +453,12 @@ int wtp_kmod_add_station(uint8_t radioid, const uint8_t *mac, uint8_t wlanid)
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* */
|
/* */
|
||||||
genlmsg_put(msg, 0, 0, g_wtp.kmodhandle.nlsmartcapwap_id, 0, 0, NLSMARTCAPWAP_CMD_ADD_STATION, 0);
|
genlmsg_put(msg, 0, 0, g_wtp.kmodhandle.nlsmartcapwap_id, 0,
|
||||||
|
NLM_F_CREATE | NLM_F_REPLACE, NLSMARTCAPWAP_CMD_ADD_STATION, 0);
|
||||||
nla_put_u8(msg, NLSMARTCAPWAP_ATTR_RADIOID, radioid);
|
nla_put_u8(msg, NLSMARTCAPWAP_ATTR_RADIOID, radioid);
|
||||||
nla_put(msg, NLSMARTCAPWAP_ATTR_MAC, ETH_ALEN, mac);
|
nla_put(msg, NLSMARTCAPWAP_ATTR_MAC, ETH_ALEN, mac);
|
||||||
nla_put_u8(msg, NLSMARTCAPWAP_ATTR_WLANID, wlanid);
|
nla_put_u8(msg, NLSMARTCAPWAP_ATTR_WLANID, wlanid);
|
||||||
|
nla_put_u32(msg, NLSMARTCAPWAP_ATTR_FLAGS, wlanid);
|
||||||
|
|
||||||
/* */
|
/* */
|
||||||
result = wtp_kmod_send_and_recv_msg(msg, NULL, NULL);
|
result = wtp_kmod_send_and_recv_msg(msg, NULL, NULL);
|
||||||
|
@ -63,7 +63,10 @@ int wtp_kmod_join_mac80211_device(struct wifi_wlan* wlan, uint32_t flags);
|
|||||||
int wtp_kmod_leave_mac80211_device(struct wifi_wlan* wlan);
|
int wtp_kmod_leave_mac80211_device(struct wifi_wlan* wlan);
|
||||||
|
|
||||||
/* */
|
/* */
|
||||||
int wtp_kmod_add_station(uint8_t radioid, const uint8_t *mac, uint8_t wlanid);
|
#define STA_FLAG_AKM_ONLY 0x0001
|
||||||
|
|
||||||
|
/* */
|
||||||
|
int wtp_kmod_add_station(uint8_t radioid, const uint8_t *mac, uint8_t wlanid, uint32_t flags);
|
||||||
int wtp_kmod_del_station(uint8_t radioid, const uint8_t *mac);
|
int wtp_kmod_del_station(uint8_t radioid, const uint8_t *mac);
|
||||||
|
|
||||||
#endif /* __WTP_KMOD_HEADER__ */
|
#endif /* __WTP_KMOD_HEADER__ */
|
||||||
|
@ -195,7 +195,7 @@ static void wtp_radio_setconfiguration_80211(struct capwap_parsed_packet *packet
|
|||||||
|
|
||||||
/* Parsing only IEEE 802.11 message element */
|
/* Parsing only IEEE 802.11 message element */
|
||||||
if (!IS_80211_MESSAGE_ELEMENTS(messageelement->id) &&
|
if (!IS_80211_MESSAGE_ELEMENTS(messageelement->id) &&
|
||||||
memcmp(&messageelement->id, &CAPWAP_ELEMENT_80211N_RADIO_CONF, sizeof(messageelement->id)) != 0)
|
!message_element_id_eq(messageelement->id, CAPWAP_ELEMENT_80211N_RADIO_CONF))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ASSERT(messageelements != NULL);
|
ASSERT(messageelements != NULL);
|
||||||
@ -255,7 +255,7 @@ static void wtp_radio_setconfiguration_80211(struct capwap_parsed_packet *packet
|
|||||||
|
|
||||||
/* Parsing only IEEE 802.11 message element */
|
/* Parsing only IEEE 802.11 message element */
|
||||||
if (!IS_80211_MESSAGE_ELEMENTS(messageelement->id) &&
|
if (!IS_80211_MESSAGE_ELEMENTS(messageelement->id) &&
|
||||||
memcmp(&messageelement->id, &CAPWAP_ELEMENT_80211N_RADIO_CONF, sizeof(messageelement->id)) != 0)
|
!message_element_id_eq(messageelement->id, CAPWAP_ELEMENT_80211N_RADIO_CONF))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ASSERT(messageelements != NULL);
|
ASSERT(messageelements != NULL);
|
||||||
@ -652,6 +652,16 @@ void wtp_radio_receive_data_packet(uint8_t radioid, unsigned short binding, cons
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* source http://stackoverflow.com/a/16994674 */
|
||||||
|
static uint16_t reverse(register uint16_t x)
|
||||||
|
{
|
||||||
|
x = (((x & 0xaaaa) >> 1) | ((x & 0x5555) << 1));
|
||||||
|
x = (((x & 0xcccc) >> 2) | ((x & 0x3333) << 2));
|
||||||
|
x = (((x & 0xf0f0) >> 4) | ((x & 0x0f0f) << 4));
|
||||||
|
x = (((x & 0xff00) >> 8) | ((x & 0x00ff) << 8));
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
/* */
|
/* */
|
||||||
uint32_t wtp_radio_create_wlan(struct capwap_parsed_packet* packet,
|
uint32_t wtp_radio_create_wlan(struct capwap_parsed_packet* packet,
|
||||||
struct capwap_80211_assignbssid_element* bssid)
|
struct capwap_80211_assignbssid_element* bssid)
|
||||||
@ -700,11 +710,16 @@ uint32_t wtp_radio_create_wlan(struct capwap_parsed_packet* packet,
|
|||||||
params.wlanid = addwlan->wlanid;
|
params.wlanid = addwlan->wlanid;
|
||||||
params.ssid = (const char*)addwlan->ssid;
|
params.ssid = (const char*)addwlan->ssid;
|
||||||
params.ssid_hidden = addwlan->suppressssid;
|
params.ssid_hidden = addwlan->suppressssid;
|
||||||
params.capability = addwlan->capability;
|
params.capability = reverse(addwlan->capability);
|
||||||
params.qos = addwlan->qos;
|
params.qos = addwlan->qos;
|
||||||
params.authmode = addwlan->authmode;
|
params.authmode = addwlan->authmode;
|
||||||
params.macmode = addwlan->macmode;
|
params.macmode = addwlan->macmode;
|
||||||
params.tunnelmode = addwlan->tunnelmode;
|
params.tunnelmode = addwlan->tunnelmode;
|
||||||
|
|
||||||
|
params.keyindex = addwlan->keyindex;
|
||||||
|
params.keylength = addwlan->keylength;
|
||||||
|
params.key = addwlan->key;
|
||||||
|
|
||||||
params.ie = (struct capwap_array *)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_80211_IE);
|
params.ie = (struct capwap_array *)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_80211_IE);
|
||||||
|
|
||||||
/* Start AP */
|
/* Start AP */
|
||||||
@ -725,8 +740,61 @@ uint32_t wtp_radio_create_wlan(struct capwap_parsed_packet* packet,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* */
|
/* */
|
||||||
uint32_t wtp_radio_update_wlan(struct capwap_parsed_packet* packet) {
|
uint32_t wtp_radio_update_wlan(struct capwap_parsed_packet* packet)
|
||||||
/* TODO */
|
{
|
||||||
|
struct wtp_radio* radio;
|
||||||
|
struct wtp_radio_wlan* wlan;
|
||||||
|
struct wlan_updateap_params params;
|
||||||
|
struct capwap_80211_updatewlan_element* updatewlan;
|
||||||
|
|
||||||
|
ASSERT(packet != NULL);
|
||||||
|
|
||||||
|
/* Get message elements */
|
||||||
|
updatewlan = (struct capwap_80211_updatewlan_element*)
|
||||||
|
capwap_get_message_element_data(packet, CAPWAP_ELEMENT_80211_UPDATE_WLAN);
|
||||||
|
if (!updatewlan) {
|
||||||
|
log_printf(LOG_DEBUG, "Update WLAN: no wlan");
|
||||||
|
return CAPWAP_RESULTCODE_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get physical radio */
|
||||||
|
radio = wtp_radio_get_phy(updatewlan->radioid);
|
||||||
|
if (!radio) {
|
||||||
|
log_printf(LOG_DEBUG, "Update WLAN: no radio");
|
||||||
|
return CAPWAP_RESULTCODE_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if virtual interface is already exist */
|
||||||
|
wlan = wtp_radio_get_wlan(radio, updatewlan->wlanid);
|
||||||
|
if (!wlan || !wlan->wlanhandle) {
|
||||||
|
log_printf(LOG_DEBUG, "Update WLAN: invalid WLAN ID");
|
||||||
|
return CAPWAP_RESULTCODE_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!wlan->in_use) {
|
||||||
|
log_printf(LOG_DEBUG, "Update WLAN: vif does not exists");
|
||||||
|
return CAPWAP_RESULTCODE_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wlan Update Configuration */
|
||||||
|
memset(¶ms, 0, sizeof(struct wlan_updateap_params));
|
||||||
|
params.radioid = updatewlan->radioid;
|
||||||
|
params.wlanid = updatewlan->wlanid;
|
||||||
|
params.capability = reverse(updatewlan->capability);
|
||||||
|
|
||||||
|
params.keyindex = updatewlan->keyindex;
|
||||||
|
params.keystatus = updatewlan->keystatus;
|
||||||
|
params.keylength = updatewlan->keylength;
|
||||||
|
params.key = updatewlan->key;
|
||||||
|
|
||||||
|
params.ie = (struct capwap_array *)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_80211_IE);
|
||||||
|
|
||||||
|
/* Update AP */
|
||||||
|
if (wifi_wlan_updateap(wlan->wlanhandle, ¶ms)) {
|
||||||
|
log_printf(LOG_DEBUG, "Update WLAN: update AP failed");
|
||||||
|
return CAPWAP_RESULTCODE_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
return CAPWAP_RESULTCODE_SUCCESS;
|
return CAPWAP_RESULTCODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -741,11 +809,14 @@ uint32_t wtp_radio_add_station(struct capwap_parsed_packet* packet) {
|
|||||||
struct capwap_addstation_element* addstation;
|
struct capwap_addstation_element* addstation;
|
||||||
struct capwap_80211_station_element* station80211;
|
struct capwap_80211_station_element* station80211;
|
||||||
struct capwap_80211n_station_info_element *station80211n;
|
struct capwap_80211n_station_info_element *station80211n;
|
||||||
|
struct capwap_80211_stationkey_element *key;
|
||||||
|
struct capwap_array *ie;
|
||||||
struct wtp_radio* radio;
|
struct wtp_radio* radio;
|
||||||
struct wtp_radio_wlan* wlan;
|
struct wtp_radio_wlan* wlan;
|
||||||
struct station_add_params stationparams;
|
struct station_add_params stationparams;
|
||||||
struct ieee80211_ht_cap ht_cap;
|
struct ieee80211_ht_cap ht_cap;
|
||||||
int err;
|
uint32_t flags = 0;
|
||||||
|
int err, i;
|
||||||
|
|
||||||
/* Get message elements */
|
/* Get message elements */
|
||||||
addstation = (struct capwap_addstation_element*)
|
addstation = (struct capwap_addstation_element*)
|
||||||
@ -754,6 +825,10 @@ uint32_t wtp_radio_add_station(struct capwap_parsed_packet* packet) {
|
|||||||
capwap_get_message_element_data(packet, CAPWAP_ELEMENT_80211_STATION);
|
capwap_get_message_element_data(packet, CAPWAP_ELEMENT_80211_STATION);
|
||||||
station80211n = (struct capwap_80211n_station_info_element *)
|
station80211n = (struct capwap_80211n_station_info_element *)
|
||||||
capwap_get_message_element_data(packet, CAPWAP_ELEMENT_80211N_STATION_INFO);
|
capwap_get_message_element_data(packet, CAPWAP_ELEMENT_80211N_STATION_INFO);
|
||||||
|
key = (struct capwap_80211_stationkey_element *)
|
||||||
|
capwap_get_message_element_data(packet, CAPWAP_ELEMENT_80211_STATION_SESSION_KEY_PROFILE);
|
||||||
|
ie = (struct capwap_array *)
|
||||||
|
capwap_get_message_element_data(packet, CAPWAP_ELEMENT_80211_IE);
|
||||||
|
|
||||||
if (!station80211 || (addstation->radioid != station80211->radioid)) {
|
if (!station80211 || (addstation->radioid != station80211->radioid)) {
|
||||||
log_printf(LOG_DEBUG, "add_station: error no station or wrong radio");
|
log_printf(LOG_DEBUG, "add_station: error no station or wrong radio");
|
||||||
@ -818,7 +893,53 @@ uint32_t wtp_radio_add_station(struct capwap_parsed_packet* packet) {
|
|||||||
stationparams.max_inactivity = g_wtp.sta_max_inactivity;
|
stationparams.max_inactivity = g_wtp.sta_max_inactivity;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = wtp_kmod_add_station(addstation->radioid, station80211->address, station80211->wlanid);
|
if (key) {
|
||||||
|
if (memcmp(station80211->address, key->address,
|
||||||
|
MACADDRESS_EUI48_LENGTH) != 0) {
|
||||||
|
log_printf(LOG_DEBUG, "add_station: 802.11n Station Session Key MAC mismatch");
|
||||||
|
return CAPWAP_RESULTCODE_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_printf(LOG_DEBUG, "add_station: key flags: %04x", key->flags);
|
||||||
|
if (key->flags & 0x8000)
|
||||||
|
flags |= STA_FLAG_AKM_ONLY;
|
||||||
|
|
||||||
|
stationparams.key = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ie) {
|
||||||
|
for (i = 0; i < ie->count; i++) {
|
||||||
|
struct ieee80211_ie *rsn;
|
||||||
|
uint8_t *data;
|
||||||
|
|
||||||
|
struct capwap_80211_ie_element *e =
|
||||||
|
*(struct capwap_80211_ie_element **)capwap_array_get_item_pointer(ie, i);
|
||||||
|
|
||||||
|
if (e->radioid != station80211->radioid ||
|
||||||
|
e->wlanid != station80211->wlanid ||
|
||||||
|
e->ielength < 2)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
rsn = (struct ieee80211_ie *)e->ie;
|
||||||
|
if (rsn->id != IEEE80211_IE_RSN_INFORMATION)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
data = (uint8_t *)(rsn + 1);
|
||||||
|
data += 2; // RSN Version
|
||||||
|
data += 4; // Group Chipher Suite
|
||||||
|
if (*(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;
|
||||||
|
}
|
||||||
|
data +=2; // Pairwise Cipher Suiter Length
|
||||||
|
stationparams.pairwise = ntohl(*(uint32_t *)data);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = wtp_kmod_add_station(addstation->radioid, station80211->address, station80211->wlanid, flags);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
log_printf(LOG_DEBUG, "add_station: CAPWAP add_station failed with: %d", err);
|
log_printf(LOG_DEBUG, "add_station: CAPWAP add_station failed with: %d", err);
|
||||||
return CAPWAP_RESULTCODE_FAILURE;
|
return CAPWAP_RESULTCODE_FAILURE;
|
||||||
|
Reference in New Issue
Block a user