17 Commits

Author SHA1 Message Date
76cd5d7484 release 1.3.2 2016-08-15 15:39:06 +02:00
a488af66cf add vendor VSA to set additional key and IGTK support
IGTK == Management Frame Protection
2016-08-15 15:30:29 +02:00
ac135e16c4 add VSA to report supported ciphers per radio 2016-08-12 12:08:06 +02:00
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
33 changed files with 1656 additions and 236 deletions

23
NEWS.md
View File

@ -3,6 +3,29 @@ SmartCAPWAP
CAPWAP WTP and AC implementation
Version 1.3.2 - 15 Aug 2016
---------------------------
* support management frame protection
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.3.2
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.3.2
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,26 @@ struct ieee80211_ie_erp {
uint8_t params;
} STRUCT_PACKED;
/* 802.11 RSN information element */
#define IEEE80211_IE_RSN_INFORMATION 48
/* cipher suite selectors */
#define IEEE80211_CIPHER_SUITE_USE_GROUP 0x000FAC00
#define IEEE80211_CIPHER_SUITE_WEP40 0x000FAC01
#define IEEE80211_CIPHER_SUITE_TKIP 0x000FAC02
/* reserved: 0x000FAC03 */
#define IEEE80211_CIPHER_SUITE_CCMP 0x000FAC04
#define IEEE80211_CIPHER_SUITE_WEP104 0x000FAC05
#define IEEE80211_CIPHER_SUITE_AES_CMAC 0x000FAC06
#define IEEE80211_CIPHER_SUITE_NO_GROUP_ADDR 0x000FAC07
#define IEEE80211_CIPHER_SUITE_GCMP 0x000FAC08
#define IEEE80211_CIPHER_SUITE_GCMP_256 0x000FAC09
#define IEEE80211_CIPHER_SUITE_CCMP_256 0x000FAC0A
#define IEEE80211_CIPHER_SUITE_BIP_GMAC_128 0x000FAC0B
#define IEEE80211_CIPHER_SUITE_BIP_GMAC_256 0x000FAC0C
#define IEEE80211_CIPHER_SUITE_BIP_CMAC_256 0x000FAC0D
/* 802.11 Extended Supported Rates information element */
#define IEEE80211_IE_EXTENDED_SUPPORTED_RATES 50
#define IEEE80211_IE_EXTENDED_SUPPORTED_MIN_LENGTH 1

View File

@ -93,7 +93,9 @@ static const struct capwap_message_elements_ops * capwap_80211_message_elements[
static const struct capwap_message_elements_ops * capwap_vendor_travelping_message_elements[] = {
element_ops(CAPWAP_ELEMENT_VENDOR_TRAVELPING_WTP_TIMESTAMP_TYPE, capwap_element_vendor_travelping_wtp_timestamp_ops),
element_ops(CAPWAP_ELEMENT_80211N_RADIO_CONF_TYPE, capwap_element_80211n_radioconf_ops),
element_ops(CAPWAP_ELEMENT_80211N_STATION_INFO_TYPE, capwap_element_80211n_station_info_ops)
element_ops(CAPWAP_ELEMENT_80211N_STATION_INFO_TYPE, capwap_element_80211n_station_info_ops),
element_ops(CAPWAP_ELEMENT_VENDOR_TRAVELPING_80211_ENCRYPTION_CAPABILITY_TYPE, capwap_element_vendor_travelping_80211_encryption_capability_ops),
element_ops(CAPWAP_ELEMENT_VENDOR_TRAVELPING_80211_UPDATE_KEY_TYPE, capwap_element_vendor_travelping_80211_update_key_ops)
};
#undef element_ops
@ -139,7 +141,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

@ -0,0 +1,103 @@
#include "capwap.h"
#include "capwap_element.h"
/*
* The IEEE 802.11 Encryption Capability message element is used by
* the WTP to inform the AC of the support cipher suites. It contains
* a list of suites as defined by IEEE 802.11 Sect. 8.4.2.27.2.
* The message element contains the following fields.
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Radio ID | Cipher Suites... |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* IEEE 802.11 Encryption Capability
*
* Vendor Id: 18681 (Travelping GmbH)
* Type: 18
*
*/
/* */
static void
capwap_vendor_travelping_80211_encryption_capability_element_create(void *data,
capwap_message_elements_handle handle,
struct capwap_write_message_elements_ops *func)
{
int i;
struct capwap_vendor_travelping_80211_encryption_capability_element *element =
(struct capwap_vendor_travelping_80211_encryption_capability_element *)data;
ASSERT(data != NULL);
func->write_u8(handle, element->radioid);
for (i = 0; i < element->suites_count; i++)
func->write_u32(handle, element->suites[i]);
}
/* */
static void *
capwap_vendor_travelping_80211_encryption_capability_element_parsing(capwap_message_elements_handle handle,
struct capwap_read_message_elements_ops *func)
{
struct capwap_vendor_travelping_80211_encryption_capability_element *data;
int suites_length, i;
ASSERT(handle != NULL);
ASSERT(func != NULL);
if (func->read_ready(handle) < 1) {
log_printf(LOG_DEBUG, "Invalid Vendor Travelping WTP 802.11 Encryption Capability element");
return NULL;
}
suites_length = func->read_ready(handle) - 1;
if ((suites_length % sizeof(uint32_t)) != 0) {
log_printf(LOG_DEBUG, "Invalid Vendor Travelping WTP 802.11 Encryption Capability element");
return NULL;
}
/* */
data = (struct capwap_vendor_travelping_80211_encryption_capability_element *)
capwap_alloc(sizeof(struct capwap_vendor_travelping_80211_encryption_capability_element) + suites_length);
/* Retrieve data */
func->read_u8(handle, &data->radioid);
data->suites_count = suites_length / sizeof(uint32_t);
for (i = 0; i < data->suites_count; i++)
func->read_u32(handle, &data->suites[i]);
return data;
}
/* */
static void *
capwap_vendor_travelping_80211_encryption_capability_element_clone(void *data)
{
struct capwap_vendor_travelping_80211_encryption_capability_element *element =
(struct capwap_vendor_travelping_80211_encryption_capability_element *)data;
ASSERT(data != NULL);
return capwap_clone(data, sizeof(struct capwap_vendor_travelping_80211_encryption_capability_element)
+ element->suites_count * sizeof(uint32_t));
}
/* */
static void
capwap_vendor_travelping_80211_encryption_capability_element_free(void* data)
{
ASSERT(data != NULL);
capwap_free(data);
}
/* */
const struct capwap_message_elements_ops capwap_element_vendor_travelping_80211_encryption_capability_ops = {
.category = CAPWAP_MESSAGE_ELEMENT_ARRAY,
.create = capwap_vendor_travelping_80211_encryption_capability_element_create,
.parse = capwap_vendor_travelping_80211_encryption_capability_element_parsing,
.clone = capwap_vendor_travelping_80211_encryption_capability_element_clone,
.free = capwap_vendor_travelping_80211_encryption_capability_element_free
};

View File

@ -0,0 +1,21 @@
#ifndef __CAPWAP_ELEMENT_VENDOR_TRAVELPING_80211_ENCRYPTION_CAPABILITY_HEADER__
#define __CAPWAP_ELEMENT_VENDOR_TRAVELPING_80211_ENCRYPTION_CAPABILITY_HEADER__
#define CAPWAP_ELEMENT_VENDOR_TRAVELPING_80211_ENCRYPTION_CAPABILITY_VENDOR CAPWAP_VENDOR_TRAVELPING_ID
#define CAPWAP_ELEMENT_VENDOR_TRAVELPING_80211_ENCRYPTION_CAPABILITY_TYPE 18
#define CAPWAP_ELEMENT_VENDOR_TRAVELPING_80211_ENCRYPTION_CAPABILITY \
(struct capwap_message_element_id){ \
.vendor = CAPWAP_ELEMENT_VENDOR_TRAVELPING_80211_ENCRYPTION_CAPABILITY_VENDOR, \
.type = CAPWAP_ELEMENT_VENDOR_TRAVELPING_80211_ENCRYPTION_CAPABILITY_TYPE \
}
struct capwap_vendor_travelping_80211_encryption_capability_element {
uint8_t radioid;
size_t suites_count;
uint32_t suites[];
};
extern const struct capwap_message_elements_ops capwap_element_vendor_travelping_80211_encryption_capability_ops;
#endif /* __CAPWAP_ELEMENT_VENDOR_TRAVELPING_80211_ENCRYPTION_CAPABILITY_HEADER__ */

View File

@ -0,0 +1,108 @@
#include "capwap.h"
#include "capwap_element.h"
/*
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Radio ID | WLAN ID | Key Index | Key Status |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Cipher Suite |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Key... |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* IEEE 802.11 Update Key
*
* Vendor Id: 18681 (Travelping GmbH)
* Type: 19
*
* Length: >= 6
*
*/
/* */
static void
capwap_vendor_travelping_80211_update_key_element_create(void *data,
capwap_message_elements_handle handle,
struct capwap_write_message_elements_ops *func)
{
struct capwap_vendor_travelping_80211_update_key_element *element =
(struct capwap_vendor_travelping_80211_update_key_element*)data;
ASSERT(data != NULL);
func->write_u8(handle, element->radioid);
func->write_u8(handle, element->wlanid);
func->write_u8(handle, element->keyindex);
func->write_u8(handle, element->keystatus);
func->write_u32(handle, element->ciphersuite);
if (element->keylength > 0)
func->write_block(handle, element->key, element->keylength);
}
/* */
static void *
capwap_vendor_travelping_80211_update_key_element_parsing(capwap_message_elements_handle handle,
struct capwap_read_message_elements_ops *func)
{
unsigned short length;
struct capwap_vendor_travelping_80211_update_key_element *data;
ASSERT(handle != NULL);
ASSERT(func != NULL);
length = func->read_ready(handle);
if (length < 8) {
log_printf(LOG_DEBUG, "Invalid Vendor Travelping IEEE 802.11 Update Key element");
return NULL;
}
length -= 8;
/* */
data = (struct capwap_vendor_travelping_80211_update_key_element *)
capwap_alloc(sizeof(struct capwap_vendor_travelping_80211_update_key_element) + length);
memset(data, 0, sizeof(struct capwap_vendor_travelping_80211_update_key_element) + length);
/* Retrieve data */
func->read_u8(handle, &data->radioid);
func->read_u8(handle, &data->wlanid);
func->read_u8(handle, &data->keyindex);
func->read_u8(handle, &data->keystatus);
func->read_u32(handle, &data->ciphersuite);
data->keylength = length;
func->read_block(handle, data->key, data->keylength);
return data;
}
/* */
static void *capwap_vendor_travelping_80211_update_key_element_clone(void *data)
{
struct capwap_vendor_travelping_80211_update_key_element *element =
(struct capwap_vendor_travelping_80211_update_key_element*)data;
ASSERT(data != NULL);
return capwap_clone(data, sizeof(struct capwap_vendor_travelping_80211_update_key_element) +
element->keylength);
}
/* */
static void capwap_vendor_travelping_80211_update_key_element_free(void *data)
{
ASSERT(data != NULL);
capwap_free(data);
}
/* */
const struct capwap_message_elements_ops capwap_element_vendor_travelping_80211_update_key_ops = {
.category = CAPWAP_MESSAGE_ELEMENT_ARRAY,
.create = capwap_vendor_travelping_80211_update_key_element_create,
.parse = capwap_vendor_travelping_80211_update_key_element_parsing,
.clone = capwap_vendor_travelping_80211_update_key_element_clone,
.free = capwap_vendor_travelping_80211_update_key_element_free
};

View File

@ -0,0 +1,27 @@
#ifndef __CAPWAP_ELEMENT_VENDOR_TRAVELPING_80211_UPDATE_KEY_HEADER__
#define __CAPWAP_ELEMENT_VENDOR_TRAVELPING_80211_UPDATE_KEY_HEADER__
#define CAPWAP_ELEMENT_VENDOR_TRAVELPING_80211_UPDATE_KEY_VENDOR CAPWAP_VENDOR_TRAVELPING_ID
#define CAPWAP_ELEMENT_VENDOR_TRAVELPING_80211_UPDATE_KEY_TYPE 19
#define CAPWAP_ELEMENT_VENDOR_TRAVELPING_80211_UPDATE_KEY \
(struct capwap_message_element_id){ \
.vendor = CAPWAP_ELEMENT_VENDOR_TRAVELPING_80211_UPDATE_KEY_VENDOR, \
.type = CAPWAP_ELEMENT_VENDOR_TRAVELPING_80211_UPDATE_KEY_TYPE \
}
#define CAPWAP_UPDATE_WLAN_KEY_STATUS_REKEYING 2
#define CAPWAP_UPDATE_WLAN_KEY_STATUS_COMPLETE 3
struct capwap_vendor_travelping_80211_update_key_element {
uint8_t radioid;
uint8_t wlanid;
uint8_t keyindex;
uint8_t keystatus;
uint32_t ciphersuite;
uint16_t keylength;
uint8_t key[];
};
extern const struct capwap_message_elements_ops capwap_element_vendor_travelping_80211_update_key_ops;
#endif /* __CAPWAP_ELEMENT_VENDOR_TRAVELPING_80211_UPDATE_KEY_HEADER__ */

View File

@ -35,9 +35,11 @@ Length: >= 33
********************************************************************/
/* */
static void capwap_wtpdescriptor_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) {
static void capwap_wtpdescriptor_element_create(void *data, capwap_message_elements_handle handle,
struct capwap_write_message_elements_ops *func)
{
int i;
struct capwap_wtpdescriptor_element* element = (struct capwap_wtpdescriptor_element*)data;
struct capwap_wtpdescriptor_element *element = (struct capwap_wtpdescriptor_element *)data;
ASSERT(data != NULL);
ASSERT(element->maxradios >= element->radiosinuse);
@ -51,7 +53,9 @@ static void capwap_wtpdescriptor_element_create(void* data, capwap_message_eleme
/* */
for (i = 0; i < element->encryptsubelement->count; i++) {
struct capwap_wtpdescriptor_encrypt_subelement* desc = (struct capwap_wtpdescriptor_encrypt_subelement*)capwap_array_get_item_pointer(element->encryptsubelement, i);
struct capwap_wtpdescriptor_encrypt_subelement *desc =
(struct capwap_wtpdescriptor_encrypt_subelement *)
capwap_array_get_item_pointer(element->encryptsubelement, i);
ASSERT((desc->wbid & CAPWAP_WTPDESC_SUBELEMENT_WBID_MASK) == desc->wbid);
@ -62,9 +66,12 @@ static void capwap_wtpdescriptor_element_create(void* data, capwap_message_eleme
/* */
for (i = 0; i < element->descsubelement->count; i++) {
uint16_t length;
struct capwap_wtpdescriptor_desc_subelement* desc = (struct capwap_wtpdescriptor_desc_subelement*)capwap_array_get_item_pointer(element->descsubelement, i);
struct capwap_wtpdescriptor_desc_subelement *desc =
(struct capwap_wtpdescriptor_desc_subelement *)
capwap_array_get_item_pointer(element->descsubelement, i);
ASSERT((desc->type >= CAPWAP_WTPDESC_SUBELEMENT_TYPE_FIRST) && (desc->type <= CAPWAP_WTPDESC_SUBELEMENT_TYPE_LAST));
ASSERT((desc->type >= CAPWAP_WTPDESC_SUBELEMENT_TYPE_FIRST) &&
(desc->type <= CAPWAP_WTPDESC_SUBELEMENT_TYPE_LAST));
length = strlen((char*)desc->data);
ASSERT(length > 0);
@ -77,38 +84,48 @@ static void capwap_wtpdescriptor_element_create(void* data, capwap_message_eleme
}
/* */
static void* capwap_wtpdescriptor_element_clone(void* data) {
static void *capwap_wtpdescriptor_element_clone(void *data)
{
int i;
struct capwap_wtpdescriptor_element* cloneelement;
struct capwap_wtpdescriptor_element* element = (struct capwap_wtpdescriptor_element*)data;
struct capwap_wtpdescriptor_element *cloneelement;
struct capwap_wtpdescriptor_element *element = (struct capwap_wtpdescriptor_element*)data;
ASSERT(data != NULL);
cloneelement = capwap_clone(data, sizeof(struct capwap_wtpdescriptor_element));
cloneelement->encryptsubelement = capwap_array_create(sizeof(struct capwap_wtpdescriptor_encrypt_subelement), 0, 0);
for (i = 0; i < element->encryptsubelement->count; i++) {
memcpy(capwap_array_get_item_pointer(cloneelement->encryptsubelement, i), capwap_array_get_item_pointer(element->encryptsubelement, i), sizeof(struct capwap_wtpdescriptor_encrypt_subelement));
}
cloneelement->encryptsubelement =
capwap_array_create(sizeof(struct capwap_wtpdescriptor_encrypt_subelement), 0, 0);
for (i = 0; i < element->encryptsubelement->count; i++)
memcpy(capwap_array_get_item_pointer(cloneelement->encryptsubelement, i),
capwap_array_get_item_pointer(element->encryptsubelement, i),
sizeof(struct capwap_wtpdescriptor_encrypt_subelement));
cloneelement->descsubelement =
capwap_array_create(sizeof(struct capwap_wtpdescriptor_desc_subelement), 0, 1);
cloneelement->descsubelement = capwap_array_create(sizeof(struct capwap_wtpdescriptor_desc_subelement), 0, 1);
for (i = 0; i < element->descsubelement->count; i++) {
struct capwap_wtpdescriptor_desc_subelement* desc = (struct capwap_wtpdescriptor_desc_subelement*)capwap_array_get_item_pointer(element->descsubelement, i);
struct capwap_wtpdescriptor_desc_subelement* clonedesc = (struct capwap_wtpdescriptor_desc_subelement*)capwap_array_get_item_pointer(cloneelement->descsubelement, i);
struct capwap_wtpdescriptor_desc_subelement *desc =
(struct capwap_wtpdescriptor_desc_subelement *)
capwap_array_get_item_pointer(element->descsubelement, i);
struct capwap_wtpdescriptor_desc_subelement *clonedesc =
(struct capwap_wtpdescriptor_desc_subelement *)
capwap_array_get_item_pointer(cloneelement->descsubelement, i);
memcpy(clonedesc, desc, sizeof(struct capwap_wtpdescriptor_desc_subelement));
if (desc->data) {
clonedesc->data = (uint8_t*)capwap_duplicate_string((char*)desc->data);
}
if (desc->data)
clonedesc->data = (uint8_t*)capwap_duplicate_string((char *)desc->data);
}
return cloneelement;
}
/* */
static void capwap_wtpdescriptor_element_free(void* data) {
static void capwap_wtpdescriptor_element_free(void *data)
{
int i;
struct capwap_wtpdescriptor_element* element = (struct capwap_wtpdescriptor_element*)data;
struct capwap_wtpdescriptor_element *element = (struct capwap_wtpdescriptor_element *)data;
ASSERT(data != NULL);
ASSERT(element->encryptsubelement != NULL);
@ -116,11 +133,12 @@ static void capwap_wtpdescriptor_element_free(void* data) {
/* */
for (i = 0; i < element->descsubelement->count; i++) {
struct capwap_wtpdescriptor_desc_subelement* desc = (struct capwap_wtpdescriptor_desc_subelement*)capwap_array_get_item_pointer(element->descsubelement, i);
struct capwap_wtpdescriptor_desc_subelement *desc =
(struct capwap_wtpdescriptor_desc_subelement *)
capwap_array_get_item_pointer(element->descsubelement, i);
if (desc->data) {
if (desc->data)
capwap_free(desc->data);
}
}
capwap_array_free(element->encryptsubelement);
@ -129,10 +147,12 @@ static void capwap_wtpdescriptor_element_free(void* data) {
}
/* */
static void* capwap_wtpdescriptor_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) {
static void *capwap_wtpdescriptor_element_parsing(capwap_message_elements_handle handle,
struct capwap_read_message_elements_ops *func)
{
uint8_t i;
uint8_t encryptlength;
struct capwap_wtpdescriptor_element* data;
struct capwap_wtpdescriptor_element *data;
ASSERT(handle != NULL);
ASSERT(func != NULL);
@ -165,7 +185,7 @@ static void* capwap_wtpdescriptor_element_parsing(capwap_message_elements_handle
/* Encryption Subelement */
for (i = 0; i < encryptlength; i++) {
struct capwap_wtpdescriptor_encrypt_subelement* desc;
struct capwap_wtpdescriptor_encrypt_subelement *desc;
/* Check */
if (func->read_ready(handle) < 3) {
@ -175,7 +195,8 @@ static void* capwap_wtpdescriptor_element_parsing(capwap_message_elements_handle
}
/* */
desc = (struct capwap_wtpdescriptor_encrypt_subelement*)capwap_array_get_item_pointer(data->encryptsubelement, data->encryptsubelement->count);
desc = (struct capwap_wtpdescriptor_encrypt_subelement *)
capwap_array_get_item_pointer(data->encryptsubelement, data->encryptsubelement->count);
func->read_u8(handle, &desc->wbid);
func->read_u16(handle, &desc->capabilities);
@ -190,7 +211,7 @@ static void* capwap_wtpdescriptor_element_parsing(capwap_message_elements_handle
while (func->read_ready(handle) > 0) {
unsigned short length;
uint16_t lengthdesc;
struct capwap_wtpdescriptor_desc_subelement* desc;
struct capwap_wtpdescriptor_desc_subelement *desc;
/* Check */
if (func->read_ready(handle) < 8) {
@ -200,12 +221,14 @@ static void* capwap_wtpdescriptor_element_parsing(capwap_message_elements_handle
}
/* */
desc = (struct capwap_wtpdescriptor_desc_subelement*)capwap_array_get_item_pointer(data->descsubelement, data->descsubelement->count);
desc = (struct capwap_wtpdescriptor_desc_subelement *)
capwap_array_get_item_pointer(data->descsubelement, data->descsubelement->count);
func->read_u32(handle, &desc->vendor);
func->read_u16(handle, &desc->type);
func->read_u16(handle, &lengthdesc);
if ((desc->type < CAPWAP_WTPDESC_SUBELEMENT_TYPE_FIRST) || (desc->type > CAPWAP_WTPDESC_SUBELEMENT_TYPE_LAST)) {
if ((desc->type < CAPWAP_WTPDESC_SUBELEMENT_TYPE_FIRST) ||
(desc->type > CAPWAP_WTPDESC_SUBELEMENT_TYPE_LAST)) {
log_printf(LOG_DEBUG, "Invalid WTP Descriptor subelement: invalid type");
capwap_wtpdescriptor_element_free(data);
return NULL;
@ -213,7 +236,9 @@ static void* capwap_wtpdescriptor_element_parsing(capwap_message_elements_handle
/* Check buffer size */
length = func->read_ready(handle);
if (!length || (length > CAPWAP_WTPDESC_SUBELEMENT_MAXDATA) || (length < lengthdesc)) {
if (!length ||
(length > CAPWAP_WTPDESC_SUBELEMENT_MAXDATA) ||
(length < lengthdesc)) {
log_printf(LOG_DEBUG, "Invalid WTP Descriptor element");
capwap_wtpdescriptor_element_free(data);
return NULL;

View File

@ -4,6 +4,8 @@
#define CAPWAP_VENDOR_TRAVELPING_ID 18681
#include "capwap_element_vendor_travelping_wtp_timestamp.h"
#include "capwap_element_vendor_travelping_80211_encryption_capability.h"
#include "capwap_element_vendor_travelping_80211_update_key.h"
/* draft-ietf-opsawg-capwap-extension-06 */
#include "capwap_element_80211n_radioconf.h"

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;
}
}
}
@ -1645,7 +1665,7 @@ void wifi_driver_free(void)
}
if (device->capability->ciphers)
capwap_array_free(device->capability->ciphers);
capwap_free(device->capability->ciphers);
capwap_free(device->capability);
}
@ -1741,7 +1761,6 @@ struct wifi_device* wifi_device_connect(const char* ifname, const char* driver)
device->capability = (struct wifi_capability*)capwap_alloc(sizeof(struct wifi_capability));
memset(device->capability, 0, sizeof(struct wifi_capability));
device->capability->bands = capwap_array_create(sizeof(struct wifi_band_capability), 0, 1);
device->capability->ciphers = capwap_array_create(sizeof(struct wifi_cipher_capability), 0, 1);
/* Retrieve device capability */
device_getcapability(device, device->capability);
@ -2071,6 +2090,74 @@ 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;
}
#define broadcast_ether_addr (const uint8_t *) "\xff\xff\xff\xff\xff\xff"
static int update_keys(struct wifi_wlan* wlan, struct capwap_array *keys)
{
int i, result = 0;
log_printf(LOG_DEBUG, "Wifi Update Keys: %p", keys);
if (!keys)
return 0;
log_printf(LOG_DEBUG, "Wifi Update Keys: #%ld", keys->count);
for (i = 0; i < keys->count; i++) {
struct capwap_vendor_travelping_80211_update_key_element *key =
*(struct capwap_vendor_travelping_80211_update_key_element **)
capwap_array_get_item_pointer(keys, i);
log_printf(LOG_DEBUG, "Wifi Update Keys: Update: Status: %d, CipherSuite: %08x, Index: %d, Len: %d",
key->keystatus, key->ciphersuite, key->keyindex, key->keylength);
switch (key->keystatus) {
case 3:
result = wlan_set_key(wlan, key->ciphersuite, broadcast_ether_addr,
key->keyindex, 1, NULL, 0,
key->keylength ? key->key : NULL, key->keylength);
log_printf(LOG_INFO, "Update KEY on interface: %s, SSID: '%s', result: %d",
wlan->virtname, wlan->ssid, result);
break;
default:
break;
}
}
return result;
}
/* */
int wifi_wlan_startap(struct wifi_wlan* wlan, struct wlan_startap_params* params)
{
@ -2097,6 +2184,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,
@ -2109,13 +2202,80 @@ int wifi_wlan_startap(struct wifi_wlan* wlan, struct wlan_startap_params* params
/* Start AP */
result = wlan_startap(wlan);
if (!result) {
wlan->device->wlanactive++;
log_printf(LOG_INFO, "Configured interface: %s, SSID: '%s'", wlan->virtname, wlan->ssid);
} else {
if (result) {
wifi_wlan_stopap(wlan);
return result;
}
update_keys(wlan, params->updatekeys);
wlan->device->wlanactive++;
log_printf(LOG_INFO, "Configured interface: %s, SSID: '%s'", wlan->virtname, wlan->ssid);
return result;
}
/* */
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;
}
if (!result)
update_keys(wlan, params->updatekeys);
return result;
}
@ -2334,14 +2494,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 +2517,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 +2535,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

@ -50,15 +50,6 @@
#define RATE_CAPABILITY_SHORTPREAMBLE 0x00000001
#define CIPHER_CAPABILITY_UNKNOWN 0
#define CIPHER_CAPABILITY_WEP40 1
#define CIPHER_CAPABILITY_WEP104 2
#define CIPHER_CAPABILITY_TKIP 3
#define CIPHER_CAPABILITY_CCMP 4
#define CIPHER_CAPABILITY_CMAC 5
#define CIPHER_CAPABILITY_GCMP 6
#define CIPHER_CAPABILITY_WPI_SMS4 7
#define IEEE80211_DFS_USABLE 0
#define IEEE80211_DFS_UNAVAILABLE 1
#define IEEE80211_DFS_AVAILABLE 2
@ -71,6 +62,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 +98,29 @@ struct wlan_startap_params {
uint8_t macmode;
uint8_t tunnelmode;
uint8_t keyindex;
uint8_t keylength;
uint8_t *key;
struct capwap_array *ie;
struct capwap_array *updatekeys;
};
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 capwap_array *updatekeys;
};
/* */
struct wlan_send_frame_params {
@ -128,6 +140,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;
};
@ -168,11 +182,6 @@ struct wifi_commands_capability {
unsigned int poll_command_supported:1;
};
/* */
struct wifi_cipher_capability {
unsigned long cipher;
};
/* */
struct wifi_capability {
struct wifi_device* device;
@ -196,7 +205,8 @@ struct wifi_capability {
struct wifi_commands_capability supp_cmds;
/* WIFI_CAPABILITY_CIPHERS */
struct capwap_array* ciphers;
int ciphers_count;
uint32_t *ciphers;
/* WIFI_CAPABILITY_MAX_SCAN_SSIDS */
uint8_t maxscanssids;
@ -326,6 +336,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 +395,8 @@ struct wifi_station {
/* Authentication */
uint16_t authalgorithm;
uint32_t pairwise_cipher;
struct capwap_80211_stationkey_element *key;
uint8_t qosinfo;
@ -410,6 +428,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 +458,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 +472,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,120 @@ 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, (alg == IEEE80211_CIPHER_SUITE_AES_CMAC ||
alg == IEEE80211_CIPHER_SUITE_BIP_GMAC_128 ||
alg == IEEE80211_CIPHER_SUITE_BIP_GMAC_256 ||
alg == IEEE80211_CIPHER_SUITE_BIP_CMAC_256) ?
NL80211_ATTR_KEY_DEFAULT_MGMT :
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 +1164,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);
@ -1611,49 +1773,21 @@ static void phydevice_capability_supp_cmds(struct wifi_commands_capability *cmd_
static void phydevice_capability_cipher_suites(struct wifi_capability *capability,
struct nlattr *tb)
{
int count, i;
uint32_t *ciphers;
size_t size;
if (tb == NULL)
return;
/* */
count = nla_len(tb) / sizeof(uint32_t);
if (count == 0)
size = nla_len(tb);
if (size == 0 || (size % sizeof(uint32_t)) != 0)
return;
capability->ciphers = capwap_clone(nla_data(tb), size);
if (!capability->ciphers)
return;
capability->ciphers_count = size / sizeof(uint32_t);
capability->flags |= WIFI_CAPABILITY_CIPHERS;
ciphers = (uint32_t *)nla_data(tb);
for (i = 0; i < count; i++) {
struct wifi_cipher_capability *ciphercap = (struct wifi_cipher_capability *)
capwap_array_get_item_pointer(capability->ciphers, capability->ciphers->count);
switch (ciphers[i]) {
case 0x000fac01:
ciphercap->cipher = CIPHER_CAPABILITY_WEP40;
case 0x000fac05:
ciphercap->cipher = CIPHER_CAPABILITY_WEP104;
case 0x000fac02:
ciphercap->cipher = CIPHER_CAPABILITY_TKIP;
case 0x000fac04:
ciphercap->cipher = CIPHER_CAPABILITY_CCMP;
case 0x000fac06:
ciphercap->cipher = CIPHER_CAPABILITY_CMAC;
case 0x000fac08:
ciphercap->cipher = CIPHER_CAPABILITY_GCMP;
case 0x00147201:
ciphercap->cipher = CIPHER_CAPABILITY_WPI_SMS4;
default:
ciphercap->cipher = CIPHER_CAPABILITY_UNKNOWN;
}
}
}
static void phydevice_capability_freq(struct wifi_capability *capability,
@ -2282,6 +2416,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;
/* 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)) {
goto error;
}
hdrlen = ieee80211_hdrlen(hdr->frame_control);
if (!pskb_may_pull(skb, hdrlen + 8))
goto error;
/* Create Radio Mac Address */
radioaddr = sc_capwap_setradiomacaddress(radioaddrbuffer, CAPWAP_RADIO_EUI48_LENGTH_PADDED, nldev->dev->dev_addr);
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))
goto error;
/* Create Radio Mac Address */
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,11 +677,17 @@ 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)
return -EEXIST;
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)
return -ENXIO;
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)
@ -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

@ -172,5 +172,11 @@ int wtp_update_radio_in_use();
void wtp_create_radioadmstate_element(struct capwap_packet_txmng* txmngpacket);
void wtp_create_radioopsstate_element(struct capwap_packet_txmng* txmngpacket);
void wtp_create_80211_wtpradioinformation_element(struct capwap_packet_txmng* txmngpacket);
void wtp_create_80211_encryption_capability_elements(struct capwap_packet_txmng *txmngpacket);
struct wtp_radio;
void wtp_create_80211_encryption_capability_element(struct capwap_packet_txmng *txmngpacket,
struct wtp_radio *radio);
#endif /* __CAPWAP_WTP_HEADER__ */

View File

@ -28,6 +28,8 @@ static void cfg_binding_add_ieee80211(struct capwap_packet_txmng* txmngpacket)
CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION,
&radio->radioinformation);
wtp_create_80211_encryption_capability_element(txmngpacket, radio);
if (radio->radioid == radio->radioinformation.radioid)
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_ANTENNA, &radio->antenna);

View File

@ -50,6 +50,7 @@ static void wtp_send_discovery_request()
if (g_wtp.binding == CAPWAP_WIRELESS_BINDING_IEEE80211) {
wtp_create_80211_wtpradioinformation_element(txmngpacket);
wtp_create_80211_encryption_capability_elements(txmngpacket);
}
/* CAPWAP_ELEMENT_MTUDISCOVERY */ /* TODO */

View File

@ -45,8 +45,10 @@ void wtp_dfa_state_join_enter(void)
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_WTPFRAMETUNNELMODE, &g_wtp.mactunnel);
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_WTPMACTYPE, &g_wtp.mactype);
if (g_wtp.binding == CAPWAP_WIRELESS_BINDING_IEEE80211)
if (g_wtp.binding == CAPWAP_WIRELESS_BINDING_IEEE80211) {
wtp_create_80211_wtpradioinformation_element(txmngpacket);
wtp_create_80211_encryption_capability_elements(txmngpacket);
}
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_ECNSUPPORT, &g_wtp.ecn);

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

@ -63,3 +63,39 @@ void wtp_create_80211_wtpradioinformation_element(struct capwap_packet_txmng* tx
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION, &element);
}
}
/* */
void wtp_create_80211_encryption_capability_element(struct capwap_packet_txmng *txmngpacket,
struct wtp_radio *radio)
{
struct capwap_vendor_travelping_80211_encryption_capability_element *element;
if (!radio->devicehandle->capability->ciphers ||
radio->devicehandle->capability->ciphers_count == 0)
return;
element = alloca(sizeof(struct capwap_vendor_travelping_80211_encryption_capability_element) +
32 * sizeof(uint32_t));
/* Set message element */
element->radioid = radio->radioid;
element->suites_count = radio->devicehandle->capability->ciphers_count;
memcpy(element->suites, radio->devicehandle->capability->ciphers,
radio->devicehandle->capability->ciphers_count * sizeof(uint32_t));
capwap_packet_txmng_add_message_element(txmngpacket,
CAPWAP_ELEMENT_VENDOR_TRAVELPING_80211_ENCRYPTION_CAPABILITY, element);
}
/* */
void wtp_create_80211_encryption_capability_elements(struct capwap_packet_txmng *txmngpacket)
{
int i;
struct wtp_radio* radio;
for (i = 0; i < g_wtp.radios->count; i++) {
radio = (struct wtp_radio*)capwap_array_get_item_pointer(g_wtp.radios, i);
wtp_create_80211_encryption_capability_element(txmngpacket, radio);
}
}

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,57 @@ void wtp_radio_receive_data_packet(uint8_t radioid, unsigned short binding, cons
}
}
static struct capwap_array *wtp_radio_set_update_keys(struct capwap_parsed_packet *packet,
uint8_t radioid, uint8_t wlanid)
{
int i;
struct capwap_array *keys;
struct capwap_array *updatekeys = NULL;
ASSERT(packet != NULL);
keys = (struct capwap_array *)
capwap_get_message_element_data(packet, CAPWAP_ELEMENT_VENDOR_TRAVELPING_80211_UPDATE_KEY);
log_printf(LOG_DEBUG, "Set Update Keys: %p", keys);
if (!keys)
return NULL;
log_printf(LOG_DEBUG, "Set Update Keys: #%ld", keys->count);
for (i = 0; i < keys->count; i++) {
struct capwap_vendor_travelping_80211_update_key_element *key =
*(struct capwap_vendor_travelping_80211_update_key_element **)
capwap_array_get_item_pointer(keys, i);
log_printf(LOG_DEBUG, "RadioId: %d .. %d, WlanId: %d .. %d",
key->radioid, radioid,
key->wlanid, wlanid);
if (key->radioid != radioid || key->wlanid != wlanid)
continue;
if (!updatekeys)
updatekeys = capwap_array_create(sizeof(void *), 0, 0);
if (!updatekeys) {
log_printf(LOG_DEBUG, "Update WLAN: Out of Memory");
return NULL;
}
*(void **)capwap_array_get_item_pointer(updatekeys, updatekeys->count) = key;
log_printf(LOG_DEBUG, "Set Update Keys: Update #%ld", updatekeys->count);
}
return updatekeys;
}
/* 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,12 +751,18 @@ 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);
params.updatekeys = wtp_radio_set_update_keys(packet, addwlan->radioid, addwlan->wlanid);
/* Start AP */
if (wifi_wlan_startap(wlan->wlanhandle, &params)) {
@ -725,8 +782,62 @@ 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);
params.updatekeys = wtp_radio_set_update_keys(packet, updatewlan->radioid, updatewlan->wlanid);
/* 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 +852,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 +868,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 +936,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;