Created a patch for mac80211 that allows to capture the raw IEEE80211 packets

(management, control, data) of one or more wireless interfaces.
Not necessary the monitor interface. The patch allows to discriminate which
IEEE802.11 types and IEEE802.11 subtypes capture.
This commit is contained in:
vemax78 2014-06-04 22:58:34 +02:00
parent 0ebf1a434f
commit 92c86462dc
7 changed files with 586 additions and 44 deletions

View File

@ -18,6 +18,12 @@ PKG_FIXUP:=autoreconf
include $(INCLUDE_DIR)/package.mk
ifneq ($(findstring c,$(OPENWRT_VERBOSE)),)
SMARTCAPWAP_MAKE_VERBOSE := V=1
else
SMARTCAPWAP_MAKE_VERBOSE :=
endif
define Package/smartcapwap
SECTION:=net
CATEGORY:=Network
@ -44,7 +50,7 @@ define KernelPackage/smartcapwap/description
endef
TARGET_CFLAGS += -I$(STAGING_DIR)/usr/include/libnl-tiny
SRC_SMARTCAPWAP:=/mnt/hgfs/shared/smartcapwap
SRC_SMARTCAPWAP := /mnt/hgfs/shared/smartcapwap
define Build/Prepare
mkdir -p $(PKG_BUILD_DIR)
@ -69,7 +75,10 @@ define Build/Compile/kmod
KLIB_BUILD="$(LINUX_DIR)" \
KLIB="$(TARGET_MODULES_DIR)" \
KBUILD_EXTRA_SYMBOLS="$(LINUX_DIR)/../compat-wireless-2014-03-31/Module.symvers" \
LINUXINCLUDE="-I$(STAGING_DIR)/usr/include/mac80211-backport \
LINUXINCLUDE="-I$(STAGING_DIR)/usr/include/mac80211-backport/uapi \
-I$(STAGING_DIR)/usr/include/mac80211-backport \
-I$(STAGING_DIR)/usr/include/mac80211/uapi \
-I$(STAGING_DIR)/usr/include/mac80211 \
-I$(LINUX_DIR)/arch/x86/include \
-Iarch/x86/include/generated \
-Iinclude \
@ -78,9 +87,8 @@ define Build/Compile/kmod
-I$(LINUX_DIR)/include/uapi \
-Iinclude/generated/uapi \
-include $(LINUX_DIR)/include/linux/kconfig.h \
-include $(STAGING_DIR)/usr/include/mac80211-backport/backport/backport.h \
" \
V="$(V)" \
-include $(STAGING_DIR)/usr/include/mac80211-backport/backport/backport.h" \
$(SMARTCAPWAP_MAKE_VERBOSE) \
modules
endef

View File

@ -0,0 +1,301 @@
--- a/include/net/mac80211.h 2014-06-02 11:48:37.000000000 +0200
+++ b/include/net/mac80211.h 2014-06-04 21:02:25.000000000 +0200
@@ -4699,4 +4699,24 @@ int ieee80211_parse_p2p_noa(const struct
*/
void ieee80211_update_p2p_noa(struct ieee80211_noa_data *data, u32 tsf);
+/**
+ *
+ */
+struct ieee80211_pcktunnel {
+ u16 subtype_mask[3]; /* 0: MGMT, 1: CTLR, 2: DATA */
+
+ int (*handler)(struct sk_buff *skb, int sig_dbm, unsigned char rate, void *data);
+ void *data;
+};
+
+/**
+ *
+ */
+int ieee80211_pcktunnel_register(u32 ifindex, struct ieee80211_pcktunnel *handler);
+
+/**
+ *
+ */
+int ieee80211_pcktunnel_deregister(u32 ifindex, struct ieee80211_pcktunnel *handler);
+
#endif /* MAC80211_H */
--- a/net/mac80211/ieee80211_i.h 2014-06-02 11:48:37.000000000 +0200
+++ b/net/mac80211/ieee80211_i.h 2014-06-02 14:48:23.000000000 +0200
@@ -727,6 +727,9 @@ struct ieee80211_sub_if_data {
char name[IFNAMSIZ];
+ /* Packet tunnel handlers */
+ struct ieee80211_pcktunnel __rcu *pcktunnel_handlers;
+
/* Fragment table for host-based reassembly */
struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX];
unsigned int fragment_next;
--- a/net/mac80211/iface.c 2014-06-02 11:48:37.000000000 +0200
+++ b/net/mac80211/iface.c 2014-06-04 22:12:23.000000000 +0200
@@ -1850,3 +1850,80 @@ void ieee80211_iface_exit(void)
{
unregister_netdevice_notifier(&mac80211_netdev_notifier);
}
+
+
+int ieee80211_pcktunnel_register(u32 ifindex, struct ieee80211_pcktunnel *handler)
+{
+ int ret = 0;
+ struct net_device *dev;
+ struct ieee80211_sub_if_data *sdata;
+
+ /* Retrieve device from ifindex */
+ dev = dev_get_by_index(&init_net, ifindex);
+ if (!dev) {
+ return -ENODEV;
+ }
+
+ /* Check if wireless device */
+ if (!dev->ieee80211_ptr || !dev->ieee80211_ptr->wiphy) {
+ dev_put(dev);
+ return -EINVAL;
+ }
+
+ /* Add handler to list */
+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+ mutex_lock(&sdata->local->iflist_mtx);
+
+ if (rcu_dereference_protected(sdata->pcktunnel_handlers, lockdep_is_held(&sdata->local->iflist_mtx))) {
+ ret = -EBUSY;
+ } else {
+ rcu_assign_pointer(sdata->pcktunnel_handlers, handler);
+ }
+
+ mutex_unlock(&sdata->local->iflist_mtx);
+ synchronize_net();
+
+ dev_put(dev);
+ return ret;
+}
+EXPORT_SYMBOL(ieee80211_pcktunnel_register);
+
+int ieee80211_pcktunnel_deregister(u32 ifindex, struct ieee80211_pcktunnel *handler)
+{
+ int ret = -ENODEV;
+ struct net_device *dev;
+ struct ieee80211_sub_if_data *sdata;
+ struct ieee80211_pcktunnel *h;
+
+ /* Retrieve device from ifindex */
+ dev = dev_get_by_index(&init_net, ifindex);
+ if (!dev) {
+ return -ENODEV;
+ }
+
+ /* Check if wireless device */
+ if (!dev->ieee80211_ptr || !dev->ieee80211_ptr->wiphy) {
+ dev_put(dev);
+ return -EINVAL;
+ }
+
+ /* Remove handler from list */
+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+ mutex_lock(&sdata->local->iflist_mtx);
+
+ h = rcu_dereference_protected(sdata->pcktunnel_handlers, lockdep_is_held(&sdata->local->iflist_mtx));
+ if (h == handler) {
+ ret = 0;
+ rcu_assign_pointer(sdata->pcktunnel_handlers, NULL);
+ }
+
+ mutex_unlock(&sdata->local->iflist_mtx);
+ synchronize_net();
+
+ dev_put(dev);
+ return ret;
+}
+EXPORT_SYMBOL(ieee80211_pcktunnel_deregister);
+
--- a/net/mac80211/rx.c 2014-06-02 11:48:37.000000000 +0200
+++ b/net/mac80211/rx.c 2014-06-04 22:47:51.707004555 +0200
@@ -2828,6 +2828,51 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_
return RX_QUEUED;
}
+static ieee80211_rx_result debug_noinline
+ieee80211_rx_h_pcktunnel(struct ieee80211_rx_data *rx, struct ieee80211_rate *rate)
+{
+ struct ieee80211_pcktunnel *handler;
+
+ handler = rcu_dereference(rx->sdata->pcktunnel_handlers);
+ if (handler) {
+ u16 fc;
+ u16 fc_type;
+ int sig_dbm = 0;
+ unsigned char pckrate = 0;
+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
+
+ if (rx->local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
+ sig_dbm = status->signal;
+
+ if (rate && !(status->flag & (RX_FLAG_HT | RX_FLAG_VHT))) {
+ int shift = 0;
+ if (status->flag & RX_FLAG_10MHZ)
+ shift = 1;
+ else if (status->flag & RX_FLAG_5MHZ)
+ shift = 2;
+ pckrate = DIV_ROUND_UP(rate->bitrate, 5 * (1 << shift));
+ }
+
+ /* Retrieve type and subtype packet */
+ fc = le16_to_cpu(hdr->frame_control);
+ fc_type = ((fc & IEEE80211_FCTL_FTYPE) >> 2);
+ if (fc_type < 3) {
+ u16 bitmask = 1 << ((fc & IEEE80211_FCTL_STYPE) >> 4);
+
+ /* Delegate packet to external handler */
+ if (handler->subtype_mask[fc_type] & bitmask) {
+ if (handler->handler(rx->skb, sig_dbm, pckrate, handler->data)) {
+ return RX_DROP_MONITOR;
+ }
+ }
+ }
+ }
+
+ return RX_CONTINUE;
+}
+
+
/* TODO: use IEEE80211_RX_FRAGMENTED */
static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx,
struct ieee80211_rate *rate)
@@ -2935,7 +2980,8 @@ static void ieee80211_rx_handlers_result
}
static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx,
- struct sk_buff_head *frames)
+ struct sk_buff_head *frames,
+ struct ieee80211_rate *rate)
{
ieee80211_rx_result res = RX_DROP_MONITOR;
struct sk_buff *skb;
@@ -2968,6 +3014,11 @@ static void ieee80211_rx_handlers(struct
if (ieee80211_vif_is_mesh(&rx->sdata->vif))
CALL_RXH(ieee80211_rx_h_mesh_fwding);
#endif
+ /* special treatment */
+ res = ieee80211_rx_h_pcktunnel(rx, rate);
+ if (res != RX_CONTINUE)
+ goto rxh_next;
+
CALL_RXH(ieee80211_rx_h_amsdu)
CALL_RXH(ieee80211_rx_h_data)
@@ -2991,7 +3042,8 @@ static void ieee80211_rx_handlers(struct
spin_unlock_bh(&rx->local->rx_path_lock);
}
-static void ieee80211_invoke_rx_handlers(struct ieee80211_rx_data *rx)
+static void ieee80211_invoke_rx_handlers(struct ieee80211_rx_data *rx,
+ struct ieee80211_rate *rate)
{
struct sk_buff_head reorder_release;
ieee80211_rx_result res = RX_DROP_MONITOR;
@@ -3009,7 +3061,7 @@ static void ieee80211_invoke_rx_handlers
ieee80211_rx_reorder_ampdu(rx, &reorder_release);
- ieee80211_rx_handlers(rx, &reorder_release);
+ ieee80211_rx_handlers(rx, &reorder_release, rate);
return;
rxh_next:
@@ -3046,7 +3098,7 @@ void ieee80211_release_reorder_timeout(s
ieee80211_sta_reorder_release(sta->sdata, tid_agg_rx, &frames);
spin_unlock(&tid_agg_rx->reorder_lock);
- ieee80211_rx_handlers(&rx, &frames);
+ ieee80211_rx_handlers(&rx, &frames, NULL);
}
/* main receive path */
@@ -3160,7 +3212,9 @@ static bool prepare_for_handlers(struct
* or not the skb was consumed.
*/
static bool ieee80211_prepare_and_rx_handle(struct ieee80211_rx_data *rx,
- struct sk_buff *skb, bool consume)
+ struct sk_buff *skb,
+ struct ieee80211_rate *rate,
+ bool consume)
{
struct ieee80211_local *local = rx->local;
struct ieee80211_sub_if_data *sdata = rx->sdata;
@@ -3186,7 +3240,7 @@ static bool ieee80211_prepare_and_rx_han
rx->skb = skb;
}
- ieee80211_invoke_rx_handlers(rx);
+ ieee80211_invoke_rx_handlers(rx, rate);
return true;
}
@@ -3195,7 +3249,8 @@ static bool ieee80211_prepare_and_rx_han
* be called with rcu_read_lock protection.
*/
static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
- struct sk_buff *skb)
+ struct sk_buff *skb,
+ struct ieee80211_rate *rate)
{
struct ieee80211_local *local = hw_to_local(hw);
struct ieee80211_sub_if_data *sdata;
@@ -3248,7 +3303,7 @@ static void __ieee80211_rx_handle_packet
rx.sta = prev_sta;
rx.sdata = prev_sta->sdata;
- ieee80211_prepare_and_rx_handle(&rx, skb, false);
+ ieee80211_prepare_and_rx_handle(&rx, skb, rate, false);
prev_sta = sta;
}
@@ -3257,7 +3312,7 @@ static void __ieee80211_rx_handle_packet
rx.sta = prev_sta;
rx.sdata = prev_sta->sdata;
- if (ieee80211_prepare_and_rx_handle(&rx, skb, true))
+ if (ieee80211_prepare_and_rx_handle(&rx, skb, rate, true))
return;
goto out;
}
@@ -3286,7 +3341,7 @@ static void __ieee80211_rx_handle_packet
rx.sta = sta_info_get_bss(prev, hdr->addr2);
rx.sdata = prev;
- ieee80211_prepare_and_rx_handle(&rx, skb, false);
+ ieee80211_prepare_and_rx_handle(&rx, skb, rate, false);
prev = sdata;
}
@@ -3295,7 +3350,7 @@ static void __ieee80211_rx_handle_packet
rx.sta = sta_info_get_bss(prev, hdr->addr2);
rx.sdata = prev;
- if (ieee80211_prepare_and_rx_handle(&rx, skb, true))
+ if (ieee80211_prepare_and_rx_handle(&rx, skb, rate, true))
return;
}
@@ -3406,7 +3461,7 @@ void ieee80211_rx(struct ieee80211_hw *h
ieee80211_tpt_led_trig_rx(local,
((struct ieee80211_hdr *)skb->data)->frame_control,
skb->len);
- __ieee80211_rx_handle_packet(hw, skb);
+ __ieee80211_rx_handle_packet(hw, skb, rate);
rcu_read_unlock();

View File

@ -3,48 +3,138 @@
#include <linux/netlink.h>
#include <net/genetlink.h>
#include <linux/rcupdate.h>
#include <linux/err.h>
#include <net/mac80211.h>
#include "nlsmartcapwap.h"
#include "netlinkapp.h"
/* */
#define NLSMARTCAPWAP_FLAG_NEED_RTNL 0x01
struct nlsmartcapwap_device {
struct list_head list;
struct ieee80211_pcktunnel pcktunnel_handler;
u32 ifindex;
};
/* */
static u32 g_nlusermodeid = 0;
static u32 nlsmartcapwap_usermodeid = 0;
static LIST_HEAD(nlsmartcapwap_dev_list);
/* */
static int nlsmartcapwap_handler(struct sk_buff *skb, int sig_dbm, unsigned char rate, void *data) {
printk("Receive packet\n");
return 0;
}
/* */
static struct nlsmartcapwap_device* nlsmartcapwap_new_device(u32 ifindex) {
struct nlsmartcapwap_device* nldev;
/* Create device */
nldev = (struct nlsmartcapwap_device*)kzalloc(sizeof(struct nlsmartcapwap_device), GFP_KERNEL);
if (nldev) {
/* Initialize device */
nldev->pcktunnel_handler.handler = nlsmartcapwap_handler;
nldev->pcktunnel_handler.data = (void*)nldev;
nldev->ifindex = ifindex;
}
return nldev;
}
/* */
static void nlsmartcapwap_free_device(struct nlsmartcapwap_device* nldev) {
/* Disconnect device from mac80211 */
ieee80211_pcktunnel_deregister(nldev->ifindex, &nldev->pcktunnel_handler);
/* Free memory */
kfree(nldev);
}
/* */
static struct nlsmartcapwap_device* nlsmartcapwap_register_device(u32 ifindex) {
struct nlsmartcapwap_device* nldev;
ASSERT_RTNL();
/* Search device */
list_for_each_entry(nldev, &nlsmartcapwap_dev_list, list) {
if (nldev->ifindex == ifindex) {
return nldev;
}
}
/* Create device */
nldev = nlsmartcapwap_new_device(ifindex);
if (nldev) {
list_add_rcu(&nldev->list, &nlsmartcapwap_dev_list);
}
return nldev;
}
/* */
static int nlsmartcapwap_unregister_device(u32 ifindex) {
int ret = -ENODEV;
struct nlsmartcapwap_device* nldev;
ASSERT_RTNL();
/* Search device */
list_for_each_entry(nldev, &nlsmartcapwap_dev_list, list) {
if (nldev->ifindex == ifindex) {
/* Remove from list */
list_del_rcu(&nldev->list);
synchronize_net();
/* Free device */
ret = 0;
nlsmartcapwap_free_device(nldev);
break;
}
}
return ret;
}
/* */
static void nlsmartcapwap_close(void) {
struct nlsmartcapwap_device* nldev;
struct nlsmartcapwap_device* tmp;
list_for_each_entry_safe(nldev, tmp, &nlsmartcapwap_dev_list, list) {
list_del(&nldev->list);
/* Free device */
nlsmartcapwap_free_device(nldev);
}
}
/* */
static int nlsmartcapwap_pre_doit(__genl_const struct genl_ops* ops, struct sk_buff* skb, struct genl_info* info) {
int rtnl = ((ops->internal_flags & NLSMARTCAPWAP_FLAG_NEED_RTNL) ? 1 : 0);
/* */
if (rtnl) {
rtnl_lock();
}
rtnl_lock();
return 0;
}
/* */
static void nlsmartcapwap_post_doit(__genl_const struct genl_ops* ops, struct sk_buff* skb, struct genl_info* info) {
if (ops->internal_flags & NLSMARTCAPWAP_FLAG_NEED_RTNL) {
rtnl_unlock();
}
rtnl_unlock();
}
/* */
static int nlsmartcapwap_connect(struct sk_buff *skb, struct genl_info *info) {
int result = 0;
static int nlsmartcapwap_link(struct sk_buff* skb, struct genl_info* info) {
int ret = 0;
u32 portid = genl_info_snd_portid(info);
if (!g_nlusermodeid) {
g_nlusermodeid = portid;
} else if (g_nlusermodeid == portid) {
result = -EALREADY;
if (!nlsmartcapwap_usermodeid) {
nlsmartcapwap_usermodeid = portid;
} else if (nlsmartcapwap_usermodeid == portid) {
ret = -EALREADY;
} else {
result = -EBUSY;
ret = -EBUSY;
}
return result;
return ret;
}
/* */
@ -53,11 +143,14 @@ static int nlsmartcapwap_netlink_notify(struct notifier_block* nb, unsigned long
u32 portid = netlink_notify_portid(notify);
/* */
if (state = NETLINK_URELEASE) {
if (state == NETLINK_URELEASE) {
rtnl_lock();
if (g_nlusermodeid == portid) {
g_nlusermodeid = 0;
if (nlsmartcapwap_usermodeid == portid) {
nlsmartcapwap_usermodeid = 0;
/* Close all devices */
nlsmartcapwap_close();
}
rtnl_unlock();
@ -66,6 +159,68 @@ static int nlsmartcapwap_netlink_notify(struct notifier_block* nb, unsigned long
return NOTIFY_DONE;
}
/* */
static int nlsmartcapwap_join_mac80211_device(struct sk_buff* skb, struct genl_info* info) {
u32 ifindex;
struct nlsmartcapwap_device* nldev;
int ret = -EINVAL;
/* Get interface index */
if (!info->attrs[NLSMARTCAPWAP_ATTR_IFINDEX]) {
return -EINVAL;
}
ifindex = nla_get_u32(info->attrs[NLSMARTCAPWAP_ATTR_IFINDEX]);
if (!ifindex) {
return -EINVAL;
}
/* Register device */
nldev = nlsmartcapwap_register_device(ifindex);
if (!nldev) {
return -EINVAL;
}
/* Set subtype masking */
if (info->attrs[NLSMARTCAPWAP_ATTR_MGMT_SUBTYPE_MASK]) {
nldev->pcktunnel_handler.subtype_mask[0] = nla_get_u16(info->attrs[NLSMARTCAPWAP_ATTR_MGMT_SUBTYPE_MASK]);
}
if (info->attrs[NLSMARTCAPWAP_ATTR_CTRL_SUBTYPE_MASK]) {
nldev->pcktunnel_handler.subtype_mask[1] = nla_get_u16(info->attrs[NLSMARTCAPWAP_ATTR_CTRL_SUBTYPE_MASK]);
}
if (info->attrs[NLSMARTCAPWAP_ATTR_DATA_SUBTYPE_MASK]) {
nldev->pcktunnel_handler.subtype_mask[2] = nla_get_u16(info->attrs[NLSMARTCAPWAP_ATTR_DATA_SUBTYPE_MASK]);
}
/* Connect device to mac80211 */
ret = ieee80211_pcktunnel_register(ifindex, &nldev->pcktunnel_handler);
if (ret) {
nlsmartcapwap_unregister_device(ifindex);
}
return ret;
}
/* */
static int nlsmartcapwap_leave_mac80211_device(struct sk_buff* skb, struct genl_info* info) {
u32 ifindex;
/* Get interface index */
if (!info->attrs[NLSMARTCAPWAP_ATTR_IFINDEX]) {
return -EINVAL;
}
ifindex = nla_get_u32(info->attrs[NLSMARTCAPWAP_ATTR_IFINDEX]);
if (!ifindex) {
return -EINVAL;
}
/* Unregister device */
return nlsmartcapwap_unregister_device(ifindex);
}
/* Netlink Family */
static struct genl_family nlsmartcapwap_family = {
.id = GENL_ID_GENERATE,
@ -80,16 +235,30 @@ static struct genl_family nlsmartcapwap_family = {
static const struct nla_policy nlsmartcapwap_policy[NLSMARTCAPWAP_ATTR_MAX + 1] = {
[NLSMARTCAPWAP_ATTR_IFINDEX] = { .type = NLA_U32 },
[NLSMARTCAPWAP_ATTR_MGMT_SUBTYPE_MASK] = { .type = NLA_U16 },
[NLSMARTCAPWAP_ATTR_CTRL_SUBTYPE_MASK] = { .type = NLA_U16 },
[NLSMARTCAPWAP_ATTR_DATA_SUBTYPE_MASK] = { .type = NLA_U16 },
};
/* Netlink Ops */
static __genl_const struct genl_ops nlsmartcapwap_ops[] = {
{
.cmd = NLSMARTCAPWAP_CMD_CONNECT,
.doit = nlsmartcapwap_connect,
.cmd = NLSMARTCAPWAP_CMD_LINK,
.doit = nlsmartcapwap_link,
.policy = nlsmartcapwap_policy,
.flags = GENL_ADMIN_PERM,
},
{
.cmd = NLSMARTCAPWAP_CMD_JOIN_MAC80211_DEVICE,
.doit = nlsmartcapwap_join_mac80211_device,
.policy = nlsmartcapwap_policy,
.flags = GENL_ADMIN_PERM,
},
{
.cmd = NLSMARTCAPWAP_CMD_LEAVE_MAC80211_DEVICE,
.doit = nlsmartcapwap_leave_mac80211_device,
.policy = nlsmartcapwap_policy,
.flags = GENL_ADMIN_PERM,
.internal_flags = NLSMARTCAPWAP_FLAG_NEED_RTNL,
},
};
@ -100,26 +269,32 @@ static struct notifier_block nlsmartcapwap_netlink_notifier = {
/* */
int nlsmartcapwap_init(void) {
int result;
int ret;
/* Register netlink family */
result = genl_register_family_with_ops(&nlsmartcapwap_family, nlsmartcapwap_ops);
if (result) {
return result;
ret = genl_register_family_with_ops(&nlsmartcapwap_family, nlsmartcapwap_ops);
if (ret) {
return ret;
}
/* Register netlink notifier */
result = netlink_register_notifier(&nlsmartcapwap_netlink_notifier);
if (result) {
ret = netlink_register_notifier(&nlsmartcapwap_netlink_notifier);
if (ret) {
genl_unregister_family(&nlsmartcapwap_family);
return result;
return ret;
}
return result;
return ret;
}
/* */
void nlsmartcapwap_exit(void) {
/* */
rtnl_lock();
nlsmartcapwap_close();
rtnl_unlock();
/* */
netlink_unregister_notifier(&nlsmartcapwap_netlink_notifier);
genl_unregister_family(&nlsmartcapwap_family);
}

View File

@ -9,6 +9,9 @@ enum nlsmartcapwap_attrs {
NLSMARTCAPWAP_ATTR_UNSPEC,
NLSMARTCAPWAP_ATTR_IFINDEX,
NLSMARTCAPWAP_ATTR_MGMT_SUBTYPE_MASK,
NLSMARTCAPWAP_ATTR_CTRL_SUBTYPE_MASK,
NLSMARTCAPWAP_ATTR_DATA_SUBTYPE_MASK,
/* Last attribute */
__NLSMARTCAPWAP_ATTR_AFTER_LAST,
@ -19,7 +22,17 @@ enum nlsmartcapwap_attrs {
enum nlsmartcapwap_commands {
NLSMARTCAPWAP_CMD_UNSPEC,
NLSMARTCAPWAP_CMD_LINK,
NLSMARTCAPWAP_CMD_SET_AC_ADDRESS,
NLSMARTCAPWAP_CMD_CONNECT,
NLSMARTCAPWAP_CMD_TEARDOWN,
NLSMARTCAPWAP_CMD_SEND_KEEPALIVE,
NLSMARTCAPWAP_CMD_RECV_KEEPALIVE,
NLSMARTCAPWAP_CMD_JOIN_MAC80211_DEVICE,
NLSMARTCAPWAP_CMD_LEAVE_MAC80211_DEVICE,
/* Last command */
__NLSMARTCAPWAP_CMD_AFTER_LAST,

View File

@ -6,6 +6,7 @@
#include <netlink/genl/genl.h>
#include <netlink/genl/family.h>
#include <netlink/genl/ctrl.h>
#include "wtp_kmod.h"
/* Local version of nl80211 with all feature to remove the problem of frag version of nl80211 */
#include "nl80211_v3_10.h"
@ -353,7 +354,7 @@ static int nl80211_device_changefrequency(struct wifi_device* device, struct wif
/* Set wifi frequency */
result = nl80211_send_and_recv_msg(devicehandle->globalhandle, msg, NULL, NULL);
if (!result) {
capwap_logging_error("Change %s frequency %d", wlan->virtname, (int)freq->frequency);
capwap_logging_info("Change %s frequency %d", wlan->virtname, (int)freq->frequency);
} else {
capwap_logging_error("Unable set frequency %d, error code: %d", (int)freq->frequency, result);
}
@ -802,6 +803,11 @@ static int nl80211_wlan_startap(struct wifi_wlan* wlan) {
wlan->flags |= WIFI_WLAN_OPERSTATE_RUNNING;
netlink_set_link_status(wlanhandle->devicehandle->globalhandle->netlinkhandle, wlan->virtindex, -1, IF_OPER_UP);
/* */
if (!wtp_kmod_join_mac80211_device(wlan->virtindex)) {
capwap_logging_info("Joined in kernel mode the interface %d", wlan->virtindex);
}
return 0;
}

View File

@ -145,7 +145,7 @@ static int wtp_kmod_send_and_recv_msg(struct nl_msg* msg, wtp_kmod_valid_cb vali
}
/* */
static int wtp_kmod_connect(void) {
static int wtp_kmod_link(void) {
int result;
struct nl_msg* msg;
@ -156,7 +156,7 @@ static int wtp_kmod_connect(void) {
}
/* */
genlmsg_put(msg, 0, 0, g_kmodhandle.nlsmartcapwap_id, 0, 0, NLSMARTCAPWAP_CMD_CONNECT, 0);
genlmsg_put(msg, 0, 0, g_kmodhandle.nlsmartcapwap_id, 0, 0, NLSMARTCAPWAP_CMD_LINK, 0);
/* */
result = wtp_kmod_send_and_recv_msg(msg, NULL, NULL);
@ -173,6 +173,38 @@ static int wtp_kmod_connect(void) {
return result;
}
/* */
int wtp_kmod_join_mac80211_device(uint32_t ifindex) {
int result;
struct nl_msg* msg;
/* */
if (!g_kmodhandle.nlsmartcapwap_id) {
return -1;
}
/* */
msg = nlmsg_alloc();
if (!msg) {
return -1;
}
/* */
genlmsg_put(msg, 0, 0, g_kmodhandle.nlsmartcapwap_id, 0, 0, NLSMARTCAPWAP_CMD_JOIN_MAC80211_DEVICE, 0);
nla_put_u32(msg, NLSMARTCAPWAP_ATTR_IFINDEX, ifindex);
nla_put_u16(msg, NLSMARTCAPWAP_ATTR_DATA_SUBTYPE_MASK, 0xffff);
/* */
result = wtp_kmod_send_and_recv_msg(msg, NULL, NULL);
if (result) {
capwap_logging_warning("Unable to join with interface: %d", ifindex);
}
/* */
nlmsg_free(msg);
return result;
}
/* */
int wtp_kmod_init(void) {
int result;
@ -197,6 +229,7 @@ int wtp_kmod_init(void) {
/* Get nlsmartcapwap netlink family */
g_kmodhandle.nlsmartcapwap_id = genl_ctrl_resolve(g_kmodhandle.nl, SMARTCAPWAP_GENL_NAME);
if (g_kmodhandle.nlsmartcapwap_id < 0) {
capwap_logging_warning("Unable to found kernel module");
wtp_kmod_free();
return -1;
}
@ -205,8 +238,8 @@ int wtp_kmod_init(void) {
nl_cb_set(g_kmodhandle.nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, wtp_kmod_no_seq_check, NULL);
nl_cb_set(g_kmodhandle.nl_cb, NL_CB_VALID, NL_CB_CUSTOM, wtp_kmod_valid_handler, NULL);
/* Connect to kernel module */
result = wtp_kmod_connect();
/* Link to kernel module */
result = wtp_kmod_link();
if (result) {
wtp_kmod_free();
return result;
@ -224,4 +257,7 @@ void wtp_kmod_free(void) {
if (g_kmodhandle.nl_cb) {
nl_cb_put(g_kmodhandle.nl_cb);
}
/* */
memset(&g_kmodhandle, 0, sizeof(struct wtp_kmod_handle));
}

View File

@ -5,4 +5,7 @@
int wtp_kmod_init(void);
void wtp_kmod_free(void);
/* */
int wtp_kmod_join_mac80211_device(uint32_t ifindex);
#endif /* __WTP_KMOD_HEADER__ */