14 Commits

Author SHA1 Message Date
6f7c26d0af release 1.3.1 2016-08-11 16:03:57 +02:00
fdf256553c [mac80211] remove obsolete debugging output 2016-08-11 16:00:41 +02:00
ecf7a24eac [wtp-kmod] replace some printk based tracing with ftrace events 2016-08-11 15:43:19 +02:00
57bcb0e183 fix hw queue selection for 802.11 raw frame injection
Update mac80211 support patch:
 * remove obsolte monitor sdata handling (we don't use
   a monitor interface, so accessing that data is a bug)
 * initialize the skb queue mapping to match the tid,
   at least ath9k does not like it when the tid and
   queue mapping disagree
2016-08-11 12:35:11 +02:00
9fbf441896 release 1.3.0 2016-08-08 09:28:18 +02:00
01919fffd9 update support for group key updates with Update WLAN 2016-08-08 09:25:01 +02:00
02e8d534b5 preserve QoS tid for injected QoS data frames
The TX path will overwrite the TID based on the SKB
priority. Load the QoS TID from 802.11 frames into
the skb priority to preserve it during TX handling.
2016-08-02 15:46:07 +02:00
3626927722 reset timeout_action on assoc response frame
Assoziation is complete when we get a response frame. We need to
reset the timeout action here, otherwise the client gets detached
as soon as the timer fires.
2016-08-01 18:14:00 +02:00
2ac3944e7a implement WPA2 Stations Key handling
Implement the required support for extrace the cipher
suite settings from the the RS Information Element and
set the station key based on the 802.11 Station Key
CAPWAP message element.

Group Key update handling is currently not implemented nor is
Station Key update handling.
2016-07-27 12:36:34 +02:00
a131e17a6e fix 802.11 Station Key IE handling
memsetting the data to zero right after assigning them
is obviously wrong
2016-07-27 12:17:00 +02:00
0e19b53e28 forward PAE (IEEE 802.1X Authentication) frames as raw 802.11 frames to AC 2016-05-10 17:07:46 +02:00
9ded0bb87b release 1.2.1 2016-05-06 17:58:27 +02:00
b0aaaa4436 replace memcmp on message id struct with direct compare
cset 3761122c fixed one place, but a few others remained.
This should take care of them all and fix a missing
IE in Add WLAN responses.
2016-05-06 17:52:39 +02:00
6024cc15cf fix interpretation of Add WLAN's capability field
RFC 5416 copies the order of the capability flags from the
IEEE 802.11 capability IE. However, the bit ordering assumtions
in RFC 5416 differ from IEEE 802.11 (in the RFC the MSB is
numbered 0, in IEEE 802.11 the MSB is numbere 15).

RFC 5416 therefore specifies the capability flags bit reversed
compared to IEEE 802.11.
2016-05-03 10:28:38 +02:00
22 changed files with 1162 additions and 146 deletions

18
NEWS.md
View File

@ -3,6 +3,24 @@ SmartCAPWAP
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
---------------------------

View File

@ -17,6 +17,7 @@ NOTE: The WTP has been ported to libev, the AC has not been adjusted and is ther
* Local MAC
* single radio, single WLAN mode
* 802.11n ([draft-ietf-opsawg-capwap-extension-06](https://tools.ietf.org/html/draft-ietf-opsawg-capwap-extension-06))
* WPA2-PSK
Only cards with cfg80211 netlink API are supported. The following devices
have been tested:
@ -26,7 +27,8 @@ have been tested:
### Planned WTP features:
* encryption (WPA2)
* WPA2 Enterprise
* 802.11r - BSS fast transition
* Hybrid-MAC ([RFC-7494](https://tools.ietf.org/html/rfc7494))
## INSTALLATION
@ -66,3 +68,27 @@ SmartCAPWAP:
./configure --disable-ac
make
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

View File

@ -19,7 +19,7 @@
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_MACRO_DIR([m4])
AM_INIT_AUTOMAKE([1.11 -Wall])

View File

@ -9,14 +9,14 @@ include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/kernel.mk
PKG_NAME:=smartcapwap
PKG_VERSION:=1.2
PKG_VERSION:=1.2.1
PKG_RELEASE:=1
SRC_SMARTCAPWAP := /usr/src/tplino/components/smartcapwap
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=git://github.com/travelping/smartcapwap.git
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_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)

View File

@ -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>
Date: Thu, 4 Feb 2016 15:57:11 +0100
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 ++++
net/mac80211/ieee80211_i.h | 6 +
net/mac80211/iface.c | 56 +++++++++
net/mac80211/rx.c | 81 ++++++++++--
net/mac80211/tx.c | 306 +++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 462 insertions(+), 12 deletions(-)
net/mac80211/rx.c | 81 +++++++++++--
net/mac80211/tx.c | 279 +++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 435 insertions(+), 12 deletions(-)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 760bc4d..6722da6 100644
@ -334,10 +334,10 @@ index 82af407..29cc59b 100644
rcu_read_unlock();
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
+++ 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;
}
@ -353,8 +353,9 @@ index bdc224d..3769c33 100644
+ struct ieee80211_chanctx_conf *chanctx_conf;
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+ struct ieee80211_sub_if_data *tmp_sdata, *sdata;
+ struct ieee80211_sub_if_data *sdata;
+ struct cfg80211_chan_def *chandef;
+ int tid;
+ int hdrlen;
+
+ /* check for not even having the fixed 802.11 header */
@ -367,13 +368,13 @@ index bdc224d..3769c33 100644
+ if (unlikely(skb->len < hdrlen))
+ 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
+ * don't have any better information and at this point, nobody cares
+ */
+ skb_reset_network_header(skb);
+ skb_reset_transport_header(skb);
+ skb_set_network_header(skb, hdrlen);
+ skb_set_transport_header(skb, hdrlen);
+
+ /*
+ * Initialize skb->protocol if the injected frame is a data frame
@ -388,12 +389,17 @@ index bdc224d..3769c33 100644
+ 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 |
+ IEEE80211_TX_CTL_INJECTED;
+
+
+ /*
+ * we might have set these flags later.....
+ * info->flags &= ~IEEE80211_TX_INTFL_DONT_ENCRYPT;
@ -405,46 +411,17 @@ index bdc224d..3769c33 100644
+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+ chanctx_conf = rcu_dereference(sdata->vif.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
+ if (!chanctx_conf)
+ goto fail_rcu;
+
+ /*
+ * Frame injection is not allowed if beaconing is not allowed
+ * or if we need radar detection. Beaconing is usually not allowed when
+ * the mode or operation (Adhoc, AP, Mesh) does not support DFS.
+ * Passive scan is also used in world regulatory domains where
+ * your country is not known and as such it should be treated as
+ * NO TX unless the channel is explicitly allowed in which case
+ * your current regulatory domain would not have the passive scan
+ * flag.
+ *
+ * Since AP mode uses monitor interfaces to inject/TX management
+ * frames we can make AP mode the exception to this rule once it
+ * supports radar detection as its implementation can deal with
+ * radar detection by itself. We can do that later by adding a
+ * monitor flag interfaces used for AP support.
+ */
+ if (!cfg80211_reg_can_beacon(local->hw.wiphy, chandef,
+ sdata->vif.type))
+ goto fail_rcu;
+ info->band = chanctx_conf->def.chan->band;
+
+ ieee80211_tx_stats(dev, skb->len);
+
+ info->band = chandef->chan->band;
+ ieee80211_xmit(sdata, NULL, skb);
+ rcu_read_unlock();
+
+ return;
+
+fail_rcu:
+ rcu_read_unlock();
+fail:
@ -461,10 +438,6 @@ index bdc224d..3769c33 100644
+netdev_tx_t ieee80211_capwap_subif_start_xmit(struct sk_buff *skb,
+ 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)) {
+ __ieee80211_capwap_inject_start_xmit(skb, dev);
+ } else
@ -476,7 +449,7 @@ index bdc224d..3769c33 100644
struct sk_buff *
ieee80211_build_data_template(struct ieee80211_sub_if_data *sdata,
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);
local_bh_enable();
}
@ -655,5 +628,5 @@ index bdc224d..3769c33 100644
+EXPORT_SYMBOL(ieee80211_inject_xmit);
+
--
2.7.0
2.8.1

View File

@ -420,6 +420,9 @@ struct ieee80211_ie_erp {
uint8_t params;
} STRUCT_PACKED;
/* 802.11 RSN information element */
#define IEEE80211_IE_RSN_INFORMATION 48
/* 802.11 Extended Supported Rates information element */
#define IEEE80211_IE_EXTENDED_SUPPORTED_RATES 50
#define IEEE80211_IE_EXTENDED_SUPPORTED_MIN_LENGTH 1

View File

@ -139,7 +139,7 @@ struct capwap_list_item* capwap_get_message_element(struct capwap_parsed_packet*
while (search) {
struct capwap_message_element_itemlist* messageelement =
(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;
/* */

View File

@ -10,6 +10,9 @@ struct capwap_message_element_id
uint16_t type;
};
#define message_element_id_eq(a, b) \
(((a).vendor == (b).vendor) && ((a).type == (b).type))
/* */
typedef void* capwap_message_elements_handle;
struct capwap_write_message_elements_ops {

View File

@ -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;
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->key = (uint8_t*)capwap_alloc(data->keylength);
memset(data, 0, sizeof(struct capwap_80211_stationkey_element));
/* Retrieve data */
func->read_block(handle, data->address, MACADDRESS_EUI48_LENGTH);

View File

@ -110,6 +110,16 @@ static void wlan_delete(struct wifi_wlan* 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)
{
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;
if (station->flags & WIFI_STATION_FLAGS_AUTHORIZED) {
int result;
/* 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);
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;
}
/* 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)
{
@ -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,
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);
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,
CAPWAP_IE_BEACONS_ASSOCIATED,
@ -2119,6 +2178,69 @@ int wifi_wlan_startap(struct wifi_wlan* wlan, struct wlan_startap_params* params
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)
{
@ -2334,14 +2456,21 @@ int wifi_station_authorize(struct wifi_wlan* wlan,
station = wifi_station_get(wlan, params->address);
if (!station)
return -1;
if (station->flags & WIFI_STATION_FLAGS_AUTHORIZED)
return 0;
/* 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))
if (params->key)
station->key = (struct capwap_80211_stationkey_element *)
capwap_element_80211_stationkey_ops.clone(params->key);
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;
}
if (params->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 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 */
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);
@ -2360,9 +2497,27 @@ int wifi_station_authorize(struct wifi_wlan* wlan,
/* let the timer expire, but set the action to SEND NULLFUNC */
station->timeout_action = WIFI_STATION_TIMEOUT_ACTION_SEND_NULLFUNC;
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) {
struct wifi_station* station;

View File

@ -71,6 +71,7 @@ DECLARE_OPAQUE_TYPE(wifi_device_handle);
DECLARE_OPAQUE_TYPE(wifi_wlan_handle);
struct capwap_80211_wtpqos_element;
struct capwap_80211_stationkey_element;
/* */
struct device_setrates_params {
@ -106,9 +107,27 @@ struct wlan_startap_params {
uint8_t macmode;
uint8_t tunnelmode;
uint8_t keyindex;
uint8_t keylength;
uint8_t *key;
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 {
@ -128,6 +147,8 @@ struct wlan_send_frame_params {
struct station_add_params {
uint8_t* address;
struct ieee80211_ht_cap *ht_cap;
uint32_t pairwise;
struct capwap_80211_stationkey_element *key;
int max_inactivity;
};
@ -326,6 +347,12 @@ struct wifi_wlan {
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;
uint8_t *beacon_ies;
int response_ies_len;
@ -379,6 +406,8 @@ struct wifi_station {
/* Authentication */
uint16_t authalgorithm;
uint32_t pairwise_cipher;
struct capwap_80211_stationkey_element *key;
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);
void (*wlan_poll_station)(struct wifi_wlan* wlan, const uint8_t* address, int qos);
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 */
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 */
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_updateap(struct wifi_wlan* wlan, struct wlan_updateap_params* params);
void wifi_wlan_stopap(struct wifi_wlan* wlan);
int wifi_wlan_getbssid(struct wifi_wlan* wlan, uint8_t* bssid);
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);
/* 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);
void wifi_station_deauthorize(struct wifi_device* device, const uint8_t* address);

View File

@ -882,6 +882,50 @@ static int nl80211_wlan_setbeacon(struct wifi_wlan* wlan) {
nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT))
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 */
result = nl80211_wlan_send_and_recv_msg(wlan, msg, NULL, NULL);
if (result)
@ -931,6 +975,115 @@ out_err:
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) {
int i;
@ -1006,6 +1159,10 @@ static int nl80211_wlan_startap(struct wifi_wlan* wlan) {
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 */
wlan->flags |= WIFI_WLAN_OPERSTATE_RUNNING;
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_poll_station = nl80211_wlan_poll_station,
.wlan_delete = nl80211_wlan_delete,
.wlan_set_key = nl80211_set_key,
.station_authorize = nl80211_station_authorize,
.station_deauthorize = nl80211_station_deauthorize,

View File

@ -5,3 +5,5 @@ smartcapwap-y := \
netlinkapp.o \
capwap.o \
capwap_private.o
CFLAGS_capwap.o = -I$(src)

486
src/wtp/kmod/capwap-trace.h Normal file
View 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>

View File

@ -10,6 +10,9 @@
#include "nlsmartcapwap.h"
#include "netlinkapp.h"
#define CREATE_TRACE_POINTS
#include "capwap-trace.h"
/* Ethernet-II snap header (RFC1042 for most EtherTypes) */
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)
{
TRACEKMOD("### sc_capwap_fragment_free\n");
trace_sc_capwap_fragment_free(fragment);
/* */
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_station *sta;
TRACEKMOD("### sc_capwap_freesession\n");
trace_sc_capwap_freesession(session);
/* Free socket buffers */
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 list_head* list = &session->fragments.lru_list;
TRACEKMOD("### sc_capwap_defrag_evictor\n");
trace_sc_capwap_defrag_evictor(session);
/* Light check without lock */
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);
delta = ktime_sub(now, fragment->tstamp);
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);
}
}
@ -91,7 +94,7 @@ static struct sk_buff* sc_capwap_reasm(struct sc_capwap_fragment* fragment) {
struct sk_buff* skbfrag;
struct sc_capwap_header* header;
TRACEKMOD("### sc_capwap_reasm\n");
trace_sc_capwap_reasm(fragment);
/* */
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 sc_capwap_header* header = (struct sc_capwap_header*)skb->data;
TRACEKMOD("### sc_capwap_defrag\n");
/* */
headersize = GET_HLEN_HEADER(header) * 4;
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_length = skb->len - headersize;
trace_sc_capwap_defrag(session, frag_id, cb->frag_offset, cb->frag_length);
/* */
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 */
fragment = &session->fragments.queues[frag_id % CAPWAP_FRAGMENT_QUEUE];
@ -266,8 +268,6 @@ error:
static unsigned int sc_capwap_80211_hdrlen(__le16 fc) {
unsigned int hdrlen = 24;
TRACEKMOD("### sc_capwap_80211_hdrlen\n");
if (ieee80211_is_data(fc)) {
if (ieee80211_has_a4(fc)) {
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;
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 */
hdrlen = 24;
@ -367,7 +367,7 @@ int sc_capwap_80211_to_8023(struct sk_buff* skb) {
uint8_t dst[ETH_ALEN];
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);
@ -411,7 +411,7 @@ int sc_capwap_create(struct sc_capwap_session *session)
.encap_rcv = sc_capwap_recvpacket
};
TRACEKMOD("### sc_capwap_bind\n");
trace_sc_capwap_create(session);
if (session->socket)
return -EBUSY;
@ -441,7 +441,7 @@ error:
void sc_capwap_close(struct sc_capwap_session *session)
{
TRACEKMOD("### sc_capwap_close\n");
trace_sc_capwap_close(session);
if (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)
{
TRACEKMOD("### sc_capwap_newfragmentid\n");
trace_sc_capwap_newfragmentid(session);
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_message_element* msgelement;
TRACEKMOD("### sc_capwap_createkeepalive\n");
trace_sc_capwap_createkeepalive(sessionid);
/* */
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_header* header = (struct sc_capwap_header*)skb->data;
TRACEKMOD("### sc_capwap_parsingpacket\n");
trace_sc_capwap_parsingpacket(session, skb);
/* Linearize socket buffer */
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 size;
int length;
@ -650,7 +659,7 @@ int sc_capwap_forwarddata(struct sc_capwap_session* session, uint8_t radioid, ui
struct sk_buff* clone = NULL;
int packetlength = skb->len;
TRACEKMOD("### sc_capwap_forwarddata\n");
trace_sc_capwap_forwarddata(session, radioid, binding, skb, flags, radioaddr, radioaddrlength, winfo);
/* Check headroom */
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);
}
/* */
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* radioaddr;
struct sc_capwap_macaddress_eui48* addr;
TRACEKMOD("### sc_capwap_setwirelessinformation\n");
trace_sc_capwap_setradiomacaddress(bssid);
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_ieee80211_frame_info* frameinfo;
TRACEKMOD("### sc_capwap_setwinfo_frameinfo\n");
trace_sc_capwap_setwinfo_frameinfo(rssi, snr, rate);
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_destination_wlans* destwlans;
TRACEKMOD("### sc_capwap_setwinfo_destwlans\n");
trace_sc_capwap_setwinfo_destwlans(wlanidbitmap);
memset(buffer, 0, size);

View File

@ -50,12 +50,15 @@ union capwap_addr {
struct sockaddr_storage ss;
};
#define STA_FLAG_AKM_ONLY 0x0001
struct sc_station {
struct hlist_node station_list;
uint8_t radioid;
uint8_t mac[ETH_ALEN];
uint8_t wlanid;
uint32_t flags;
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_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_parsingpacket(struct sc_capwap_session* session, struct sk_buff* skb);

View File

@ -13,6 +13,7 @@
#include "capwap.h"
#include "nlsmartcapwap.h"
#include "netlinkapp.h"
#include "capwap-trace.h"
/* */
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)
{
TRACEKMOD("### sc_capwap_resetsession\n");
trace_sc_capwap_resetsession(session);
sc_capwap_close(session);
sc_capwap_init(session, session->net);
@ -55,7 +56,7 @@ int sc_capwap_sendkeepalive(struct sc_capwap_session *session)
int length;
uint8_t buffer[CAPWAP_KEEP_ALIVE_MAX_SIZE];
TRACEKMOD("### sc_capwap_sendkeepalive\n");
trace_sc_capwap_sendkeepalive(session);
/* Build keepalive */
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,
};
TRACEKMOD("### sc_capwap_send\n");
trace_sc_capwap_send(session);
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)
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_hdr *hdr;
int hdrlen;
printk(KERN_DEBUG "capwap inject: %s: hdr: %p\n",
dev->name, skb->data);
trace_sc_send_80211(skb, dev);
/* detach skb from CAPWAP */
skb_orphan(skb);
@ -185,17 +183,15 @@ static void sc_send_80211(struct sk_buff *skb, struct net_device *dev)
/* drop conntrack reference */
nf_reset(skb);
hdr = (struct ieee80211_hdr *)skb->data;
hdrlen = ieee80211_hdrlen(hdr->frame_control);
skb_reset_mac_header(skb);
skb_reset_network_header(skb);
skb_reset_transport_header(skb);
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);
info->flags |= IEEE80211_TX_CTL_INJECTED;
memset(info, 0, sizeof(*info));
info->flags = IEEE80211_TX_CTL_INJECTED;
/* Force the device to verify it. */
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;
int winfosize = 0;
TRACEKMOD("### sc_capwap_parsingdatapacket\n");
trace_sc_capwap_parsingdatapacket(session, skb);
/* Retrieve optional attribute */
pos = skb->data + sizeof(struct sc_capwap_header);

View File

@ -85,32 +85,58 @@ static int sc_netlink_handler(uint32_t ifindex, struct sk_buff* skb,
int err;
uint8_t radioaddrbuffer[CAPWAP_RADIO_EUI48_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_wireless_information* winfo = NULL;
uint32_t flags = nldev->flags;
/* Drop packet */
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 */
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;
}
/* 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 */
if (sig_dbm || rate) {
winfo = sc_capwap_setwinfo_frameinfo(winfobuffer, CAPWAP_WINFO_FRAMEINFO_LENGTH_PADDED, (uint8_t)sig_dbm, 0, ((uint16_t)rate) * 5);
}
if (sig_dbm || rate)
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;
/* 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:
@ -642,7 +668,8 @@ static int sc_netlink_add_station(struct sk_buff* skb, struct genl_info* info)
if (!info->attrs[NLSMARTCAPWAP_ATTR_RADIOID] ||
!info->attrs[NLSMARTCAPWAP_ATTR_MAC] ||
!info->attrs[NLSMARTCAPWAP_ATTR_WLANID])
!info->attrs[NLSMARTCAPWAP_ATTR_WLANID] ||
!info->attrs[NLSMARTCAPWAP_ATTR_FLAGS])
return -EINVAL;
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;
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;
if (info->nlhdr->nlmsg_flags & NLM_F_REPLACE)
if (sta->wlanid != nla_get_u8(info->attrs[NLSMARTCAPWAP_ATTR_WLANID]))
return -ENXIO;
sta->flags = nla_get_u32(info->attrs[NLSMARTCAPWAP_ATTR_FLAGS]);
return 0;
}
sta = kmalloc(sizeof(struct sc_station), GFP_KERNEL);
if (sta == NULL)
return -ENOMEM;
@ -663,6 +696,7 @@ static int sc_netlink_add_station(struct sk_buff* skb, struct genl_info* info)
sta->radioid = radioid;
memcpy(&sta->mac, mac, ETH_ALEN);
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);

View File

@ -242,7 +242,7 @@ static void receive_ieee80211_wlan_configuration_request(struct capwap_parsed_pa
/* Add message element */
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_RESULTCODE, &resultcode);
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_ELEMENT_VENDORPAYLOAD */ /* TODO */

View File

@ -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;
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;
/* */
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(msg, NLSMARTCAPWAP_ATTR_MAC, ETH_ALEN, mac);
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);

View File

@ -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_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);
#endif /* __WTP_KMOD_HEADER__ */

View File

@ -195,7 +195,7 @@ static void wtp_radio_setconfiguration_80211(struct capwap_parsed_packet *packet
/* Parsing only IEEE 802.11 message element */
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;
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 */
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;
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,
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.ssid = (const char*)addwlan->ssid;
params.ssid_hidden = addwlan->suppressssid;
params.capability = addwlan->capability;
params.capability = reverse(addwlan->capability);
params.qos = addwlan->qos;
params.authmode = addwlan->authmode;
params.macmode = addwlan->macmode;
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);
/* 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) {
/* TODO */
uint32_t wtp_radio_update_wlan(struct capwap_parsed_packet* packet)
{
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(&params, 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, &params)) {
log_printf(LOG_DEBUG, "Update WLAN: update AP failed");
return CAPWAP_RESULTCODE_FAILURE;
}
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_80211_station_element* station80211;
struct capwap_80211n_station_info_element *station80211n;
struct capwap_80211_stationkey_element *key;
struct capwap_array *ie;
struct wtp_radio* radio;
struct wtp_radio_wlan* wlan;
struct station_add_params stationparams;
struct ieee80211_ht_cap ht_cap;
int err;
uint32_t flags = 0;
int err, i;
/* Get message elements */
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);
station80211n = (struct capwap_80211n_station_info_element *)
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)) {
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;
}
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) {
log_printf(LOG_DEBUG, "add_station: CAPWAP add_station failed with: %d", err);
return CAPWAP_RESULTCODE_FAILURE;