From 92c86462dcd91eb6fc3eaafece128ae1d469116d Mon Sep 17 00:00:00 2001 From: vemax78 Date: Wed, 4 Jun 2014 22:58:34 +0200 Subject: [PATCH] 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. --- openwrt/Makefile | 18 +- .../920-mac80211_packet_tunnel.patch | 301 ++++++++++++++++++ src/kmod/netlinkapp.c | 243 ++++++++++++-- src/kmod/nlsmartcapwap.h | 13 + src/wtp/binding/ieee80211/wifi_nl80211.c | 8 +- src/wtp/wtp_kmod.c | 44 ++- src/wtp/wtp_kmod.h | 3 + 7 files changed, 586 insertions(+), 44 deletions(-) create mode 100644 openwrt/mac80211_patchs/920-mac80211_packet_tunnel.patch diff --git a/openwrt/Makefile b/openwrt/Makefile index f8ac141..fc1f786 100644 --- a/openwrt/Makefile +++ b/openwrt/Makefile @@ -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 diff --git a/openwrt/mac80211_patchs/920-mac80211_packet_tunnel.patch b/openwrt/mac80211_patchs/920-mac80211_packet_tunnel.patch new file mode 100644 index 0000000..933a67a --- /dev/null +++ b/openwrt/mac80211_patchs/920-mac80211_packet_tunnel.patch @@ -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(); + diff --git a/src/kmod/netlinkapp.c b/src/kmod/netlinkapp.c index d72b76b..9b34305 100644 --- a/src/kmod/netlinkapp.c +++ b/src/kmod/netlinkapp.c @@ -3,48 +3,138 @@ #include #include #include +#include +#include #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); } diff --git a/src/kmod/nlsmartcapwap.h b/src/kmod/nlsmartcapwap.h index 3dd6066..3e73eb6 100644 --- a/src/kmod/nlsmartcapwap.h +++ b/src/kmod/nlsmartcapwap.h @@ -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, diff --git a/src/wtp/binding/ieee80211/wifi_nl80211.c b/src/wtp/binding/ieee80211/wifi_nl80211.c index dbdb642..05b4b86 100644 --- a/src/wtp/binding/ieee80211/wifi_nl80211.c +++ b/src/wtp/binding/ieee80211/wifi_nl80211.c @@ -6,6 +6,7 @@ #include #include #include +#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; } diff --git a/src/wtp/wtp_kmod.c b/src/wtp/wtp_kmod.c index 93361bf..d7fb7d8 100644 --- a/src/wtp/wtp_kmod.c +++ b/src/wtp/wtp_kmod.c @@ -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)); } diff --git a/src/wtp/wtp_kmod.h b/src/wtp/wtp_kmod.h index 1c4cc7c..eae9667 100644 --- a/src/wtp/wtp_kmod.h +++ b/src/wtp/wtp_kmod.h @@ -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__ */