diff --git a/build/wtp/Makefile.am b/build/wtp/Makefile.am index 6ddf3a3..a9bce55 100755 --- a/build/wtp/Makefile.am +++ b/build/wtp/Makefile.am @@ -34,6 +34,7 @@ INCLUDES = \ -I$(top_srcdir)/build \ -I$(top_srcdir)/src/common \ -I$(top_srcdir)/src/wtp \ + -I$(top_srcdir)/src/kmod \ -I$(top_srcdir)/src/common/binding/ieee80211 \ -I$(top_srcdir)/src/wtp/binding/ieee80211 @@ -42,6 +43,7 @@ include $(top_srcdir)/build/Makefile_common.am wtp_SOURCES = \ $(capwap_SOURCES) \ $(top_srcdir)/src/wtp/wtp.c \ + $(top_srcdir)/src/wtp/wtp_kmod.c \ $(top_srcdir)/src/wtp/wtp_element_helper.c \ $(top_srcdir)/src/wtp/wtp_dfa.c \ $(top_srcdir)/src/wtp/wtp_dfa_idle.c \ diff --git a/openwrt/Makefile b/openwrt/Makefile new file mode 100644 index 0000000..f8ac141 --- /dev/null +++ b/openwrt/Makefile @@ -0,0 +1,103 @@ +# +# Copyright (C) 2006 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=smartcapwap +PKG_VERSION:=1.0 +PKG_RELEASE:=1 + +PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME) + +PKG_FIXUP:=autoreconf + +include $(INCLUDE_DIR)/package.mk + +define Package/smartcapwap + SECTION:=net + CATEGORY:=Network + TITLE:=SmartCAPWAP WTP + MAINTAINER:=Massimo Vellucci + DEPENDS:=+libnl-tiny +libconfig +libcyassl +kmod-smartcapwap +endef + +define Package/smartcapwap/description + This package contains the SmartCAPWAP WTP daemon. +endef + +define KernelPackage/smartcapwap + SUBMENU:=Network Support + TITLE:=SmartCAPWAP Data Channel Module + MAINTAINER:=Massimo Vellucci + DEPENDS:=+kmod-mac80211 + FILES:=$(PKG_BUILD_DIR)/src/kmod/smartcapwap.ko + AUTOLOAD:=$(call AutoLoad,70,smartcapwap) +endef + +define KernelPackage/smartcapwap/description + This package contains the SmartCAPWAP Data Transport kernel module. +endef + +TARGET_CFLAGS += -I$(STAGING_DIR)/usr/include/libnl-tiny +SRC_SMARTCAPWAP:=/mnt/hgfs/shared/smartcapwap + +define Build/Prepare + mkdir -p $(PKG_BUILD_DIR) + $(CP) -r $(SRC_SMARTCAPWAP)/* $(PKG_BUILD_DIR)/ +endef + +define Build/Configure + $(call Build/Configure/Default, --disable-ac) +endef + +define Build/Compile/wtp + $(MAKE) -C $(PKG_BUILD_DIR) \ + $(TARGET_CONFIGURE_OPTS) \ + all +endef + +define Build/Compile/kmod + $(MAKE) -C "$(LINUX_DIR)" \ + CROSS_COMPILE="$(KERNEL_CROSS)" \ + ARCH="$(LINUX_KARCH)" \ + SUBDIRS="$(PKG_BUILD_DIR)/src/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 \ + -I$(LINUX_DIR)/arch/x86/include \ + -Iarch/x86/include/generated \ + -Iinclude \ + -I$(LINUX_DIR)/arch/x86/include/uapi \ + -Iarch/x86/include/generated/uapi \ + -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)" \ + modules +endef + +define Build/Compile + $(Build/Compile/wtp) + $(Build/Compile/kmod) +endef + +define Package/smartcapwap/install + $(INSTALL_DIR) $(1)/etc/capwap + $(INSTALL_CONF) ./files/wtp.conf $(1)/etc/capwap/wtp.conf + $(INSTALL_CONF) ./files/ca.crt $(1)/etc/capwap/ca.crt + $(INSTALL_CONF) ./files/wtp.crt $(1)/etc/capwap/wtp.crt + $(INSTALL_CONF) ./files/wtp.key $(1)/etc/capwap/wtp.key + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/build/wtp/wtp $(1)/usr/bin +endef + +$(eval $(call BuildPackage,smartcapwap)) +$(eval $(call KernelPackage,smartcapwap)) diff --git a/openwrt/files/ca.crt b/openwrt/files/ca.crt new file mode 100644 index 0000000..f2153ab --- /dev/null +++ b/openwrt/files/ca.crt @@ -0,0 +1,23 @@ +-----BEGIN CERTIFICATE----- +MIID3TCCA0agAwIBAgIJAJpqxrKqMyLFMA0GCSqGSIb3DQEBBQUAMIGmMQswCQYD +VQQGEwJJVDELMAkGA1UECBMCSVQxDTALBgNVBAcTBFJvbWUxFDASBgNVBAoTC1Nt +YXJ0Q0FQV0FQMRQwEgYDVQQLEwtTbWFydENBUFdBUDEXMBUGA1UEAxMOU21hcnRD +QVBXQVAgQ0ExFDASBgNVBCkTC1NtYXJ0Q0FQV0FQMSAwHgYJKoZIhvcNAQkBFhF2 +ZW1heDc4QGdtYWlsLmNvbTAeFw0xNDA1MTUxODAxNDNaFw0yNDA1MTIxODAxNDNa +MIGmMQswCQYDVQQGEwJJVDELMAkGA1UECBMCSVQxDTALBgNVBAcTBFJvbWUxFDAS +BgNVBAoTC1NtYXJ0Q0FQV0FQMRQwEgYDVQQLEwtTbWFydENBUFdBUDEXMBUGA1UE +AxMOU21hcnRDQVBXQVAgQ0ExFDASBgNVBCkTC1NtYXJ0Q0FQV0FQMSAwHgYJKoZI +hvcNAQkBFhF2ZW1heDc4QGdtYWlsLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw +gYkCgYEA72PBMR4HQ+rA+ifXJdMtUujlUQX1yrtXZ0HMdKbHbAbfoY3Rvyfdwo2i +TMaZYomyCASawZRzkZJvPchu/q9au/UdLuTmeaUCDpvIkibMK5tahTgP5x90IMGu ++uzdgZQaPbv+fjYkAmMGkZYYTha8GhH+vNloSb6n8oUh2eGf1kUCAwEAAaOCAQ8w +ggELMB0GA1UdDgQWBBS4vrLLxmi9CrvlvN6uVv4l5uSzHDCB2wYDVR0jBIHTMIHQ +gBS4vrLLxmi9CrvlvN6uVv4l5uSzHKGBrKSBqTCBpjELMAkGA1UEBhMCSVQxCzAJ +BgNVBAgTAklUMQ0wCwYDVQQHEwRSb21lMRQwEgYDVQQKEwtTbWFydENBUFdBUDEU +MBIGA1UECxMLU21hcnRDQVBXQVAxFzAVBgNVBAMTDlNtYXJ0Q0FQV0FQIENBMRQw +EgYDVQQpEwtTbWFydENBUFdBUDEgMB4GCSqGSIb3DQEJARYRdmVtYXg3OEBnbWFp +bC5jb22CCQCaasayqjMixTAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GB +ANZuFab2/jLSakpGc0nZjCWAlXm29TCkL1i0yxmpjgbg/tqZrSAb1tuK5IANI7Tz +deOObRRxjjRGgSHnFLcKXmJeGjTmIdX7DLALWQALmc0GG+A1T1vHqVKc3YqjmUP3 +4X/JgFqJnF1KkKmcDLiLBmA8W4+rLPe3kKhNloKQ9G1m +-----END CERTIFICATE----- diff --git a/openwrt/files/wtp.conf b/openwrt/files/wtp.conf new file mode 100644 index 0000000..7510d3d --- /dev/null +++ b/openwrt/files/wtp.conf @@ -0,0 +1,150 @@ +# WTP configuration file + +version = "1.0"; + +application: { + standalone = true; + + name = "wtp 1"; + + location = "Ufficio"; + + binding = "802.11"; + + tunnelmode: { + nativeframe = false; + ethframe = false; + localbridging = true; + }; + + mactype = "localmac"; + + boardinfo: { + idvendor = 123456; + + element = ( + { name = "model"; value = "1.0"; }, + { name = "serial"; value = "2.0"; }, + { name = "id"; value = "3.0"; }, + { name = "revision"; value = "4.0"; }, + { name = "macaddress"; type = "interface"; value = "eth0"; } + ); + }; + + descriptor: { + encryption = [ + "802.11_AES", + "802.11_TKIP" + ]; + + info = ( + { idvendor = 23456; type = "hardware"; value = "abcde"; }, + { idvendor = 33457; type = "software"; value = "fghil"; }, + { idvendor = 43458; type = "boot"; value = "mnopq"; }, + { idvendor = 53459; type = "other"; value = "qwert"; } + ); + }; + + ecn = "limited"; + + timer: { + statistics = 120; + }; + + dtls: { + enable = true; + + dtlspolicy: { + cleardatachannel = true; + dtlsdatachannel = true; + }; + + type = "x509"; + + presharedkey: { + identity = "prova"; + pskkey = "123456"; + }; + + x509: { + calist = "/etc/capwap/ca.crt"; + certificate = "/etc/capwap/wtp.crt"; + privatekey = "/etc/capwap/wtp.key"; + }; + }; + + wlan: { + prefix = "ap"; + }; + + radio = ( + { + device = "phy0"; + enabled = true; + driver = "nl80211"; + mode = "bg"; + country = "IT"; + outdoor = false; + rtsthreshold = 2347; + shortretry = 7; + longretry = 4; + shortpreamble = true; + fragmentationthreshold = 2346; + txmsdulifetime = 512; + rxmsdulifetime = 512; + maxbssid = 1; + bssprefixname = "ap"; + dtimperiod = 2; + beaconperiod = 100; + antenna = { + diversity = false; + combiner = "omni"; + selection = [ "internal" ]; + }; + multidomaincapability = { + firstchannel = 1; + numberchannels = 11; + maxtxpower = 100; + }; + supportedrates = [ + 12, 18, 24, 36, 48, 72, 96, 108 + ]; + txpower = { + current = 100; + supported = [ 100 ]; + }; + } + ); + + network: { + #binding = "eth1"; + mtu = 1500; + + transport = "udp"; + + ipv4 = true; + ipv6 = false; + ipdualstack = true; + }; + + acdiscovery: { + search = false; + host = [ + "192.168.1.101" + ]; + }; + + acprefered: { + host = [ + "192.168.1.101" + ]; + }; +}; + +logging: { + enable = true; + level = "debug"; + output = ( + { mode = "stdout"; } + ); +}; diff --git a/openwrt/files/wtp.crt b/openwrt/files/wtp.crt new file mode 100644 index 0000000..01dec65 --- /dev/null +++ b/openwrt/files/wtp.crt @@ -0,0 +1,73 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 2 (0x2) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=IT, ST=IT, L=Rome, O=SmartCAPWAP, OU=SmartCAPWAP, CN=SmartCAPWAP CA/name=SmartCAPWAP/emailAddress=vemax78@gmail.com + Validity + Not Before: May 15 18:02:22 2014 GMT + Not After : May 12 18:02:22 2024 GMT + Subject: C=IT, ST=IT, L=Rome, O=SmartCAPWAP, OU=SmartCAPWAP, CN=wtp1/name=SmartCAPWAP/emailAddress=vemax78@gmail.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (1024 bit) + Modulus: + 00:b2:b1:a5:56:a7:ef:4d:76:76:0c:09:0f:5e:c3: + 4b:cd:9c:80:ae:1b:fa:8a:63:6b:3e:5d:df:18:e5: + 30:25:4a:bf:02:90:a0:1a:db:d9:7b:d3:c0:f2:5b: + 82:de:07:bd:4c:43:66:4d:39:6c:fe:88:d5:1a:ac: + 47:d0:4c:2d:e0:05:4d:95:80:b5:61:df:84:03:cb: + 26:f7:b3:77:8c:e5:28:9e:71:5e:4b:01:42:64:64: + d4:1f:8b:e2:c6:12:af:9f:64:de:63:f0:b2:ff:fb: + 0e:82:d8:ba:cf:a9:21:7f:43:4f:c9:19:e0:50:e1: + 90:ac:ce:d2:ab:dc:87:b9:9f + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment, Data Encipherment + Netscape Comment: + Easy-RSA Generated Certificate + X509v3 Subject Key Identifier: + 5D:1C:43:55:79:96:EC:CD:9F:81:47:7F:23:F2:88:C4:80:EF:7A:C6 + X509v3 Authority Key Identifier: + keyid:B8:BE:B2:CB:C6:68:BD:0A:BB:E5:BC:DE:AE:56:FE:25:E6:E4:B3:1C + DirName:/C=IT/ST=IT/L=Rome/O=SmartCAPWAP/OU=SmartCAPWAP/CN=SmartCAPWAP CA/name=SmartCAPWAP/emailAddress=vemax78@gmail.com + serial:9A:6A:C6:B2:AA:33:22:C5 + + X509v3 Extended Key Usage: + TLS Web Client Authentication + Signature Algorithm: sha1WithRSAEncryption + 2e:1b:fb:12:36:08:97:f4:93:2d:5e:5a:94:e0:67:a9:69:9c: + d3:24:8b:51:87:b4:fd:02:cd:29:9c:54:5f:5c:27:4c:02:08: + 6a:64:79:84:a9:dd:df:f4:9d:7d:b7:19:e9:26:a6:01:af:a7: + b4:00:50:51:9d:64:be:f6:38:6b:1d:04:e7:2d:34:16:26:75: + 88:01:98:d8:4e:db:3f:a2:f1:9d:d7:9d:cd:8a:07:8a:82:b1: + 9f:59:be:4c:e1:0f:8e:2f:ea:cc:98:0a:e1:54:6c:f4:00:a9: + 21:fa:9d:ed:81:4d:c6:1f:cd:20:bb:4a:ed:4d:61:50:be:af: + 02:f0 +-----BEGIN CERTIFICATE----- +MIIEGTCCA4KgAwIBAgIBAjANBgkqhkiG9w0BAQUFADCBpjELMAkGA1UEBhMCSVQx +CzAJBgNVBAgTAklUMQ0wCwYDVQQHEwRSb21lMRQwEgYDVQQKEwtTbWFydENBUFdB +UDEUMBIGA1UECxMLU21hcnRDQVBXQVAxFzAVBgNVBAMTDlNtYXJ0Q0FQV0FQIENB +MRQwEgYDVQQpEwtTbWFydENBUFdBUDEgMB4GCSqGSIb3DQEJARYRdmVtYXg3OEBn +bWFpbC5jb20wHhcNMTQwNTE1MTgwMjIyWhcNMjQwNTEyMTgwMjIyWjCBnDELMAkG +A1UEBhMCSVQxCzAJBgNVBAgTAklUMQ0wCwYDVQQHEwRSb21lMRQwEgYDVQQKEwtT +bWFydENBUFdBUDEUMBIGA1UECxMLU21hcnRDQVBXQVAxDTALBgNVBAMTBHd0cDEx +FDASBgNVBCkTC1NtYXJ0Q0FQV0FQMSAwHgYJKoZIhvcNAQkBFhF2ZW1heDc4QGdt +YWlsLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAsrGlVqfvTXZ2DAkP +XsNLzZyArhv6imNrPl3fGOUwJUq/ApCgGtvZe9PA8luC3ge9TENmTTls/ojVGqxH +0Ewt4AVNlYC1Yd+EA8sm97N3jOUonnFeSwFCZGTUH4vixhKvn2TeY/Cy//sOgti6 +z6khf0NPyRngUOGQrM7Sq9yHuZ8CAwEAAaOCAV0wggFZMAkGA1UdEwQCMAAwCwYD +VR0PBAQDAgTwMC0GCWCGSAGG+EIBDQQgFh5FYXN5LVJTQSBHZW5lcmF0ZWQgQ2Vy +dGlmaWNhdGUwHQYDVR0OBBYEFF0cQ1V5luzNn4FHfyPyiMSA73rGMIHbBgNVHSME +gdMwgdCAFLi+ssvGaL0Ku+W83q5W/iXm5LMcoYGspIGpMIGmMQswCQYDVQQGEwJJ +VDELMAkGA1UECBMCSVQxDTALBgNVBAcTBFJvbWUxFDASBgNVBAoTC1NtYXJ0Q0FQ +V0FQMRQwEgYDVQQLEwtTbWFydENBUFdBUDEXMBUGA1UEAxMOU21hcnRDQVBXQVAg +Q0ExFDASBgNVBCkTC1NtYXJ0Q0FQV0FQMSAwHgYJKoZIhvcNAQkBFhF2ZW1heDc4 +QGdtYWlsLmNvbYIJAJpqxrKqMyLFMBMGA1UdJQQMMAoGCCsGAQUFBwMCMA0GCSqG +SIb3DQEBBQUAA4GBAC4b+xI2CJf0ky1eWpTgZ6lpnNMki1GHtP0CzSmcVF9cJ0wC +CGpkeYSp3d/0nX23GekmpgGvp7QAUFGdZL72OGsdBOctNBYmdYgBmNhO2z+i8Z3X +nc2KB4qCsZ9ZvkzhD44v6syYCuFUbPQAqSH6ne2BTcYfzSC7Su1NYVC+rwLw +-----END CERTIFICATE----- diff --git a/openwrt/files/wtp.key b/openwrt/files/wtp.key new file mode 100644 index 0000000..4f37d12 --- /dev/null +++ b/openwrt/files/wtp.key @@ -0,0 +1,16 @@ +-----BEGIN PRIVATE KEY----- +MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALKxpVan7012dgwJ +D17DS82cgK4b+opjaz5d3xjlMCVKvwKQoBrb2XvTwPJbgt4HvUxDZk05bP6I1Rqs +R9BMLeAFTZWAtWHfhAPLJvezd4zlKJ5xXksBQmRk1B+L4sYSr59k3mPwsv/7DoLY +us+pIX9DT8kZ4FDhkKzO0qvch7mfAgMBAAECgYB3oUyChi1EG9GN3ybmFzMRdPwF +FAAYU9TBTREF1rHz1WWpLu+w64xfRPWAi1lCkcXeX6UGgDKC+VJJ6BqvzcBLgkjh +GBaWBCN/F782Ss4svt1dyRrixixUw+RfJLakKSdFPsrdIHctdSLIKsSl4wxj+9ek +NmGbOBm/2ZJazSzgEQJBAN5abmR53pRdGKgfFKeqUo+ygWSi1IDFqn0niw7DS4TU +3h/QuI9qWZQlTIK8ibguvpc7wHUK4IZ0pk7TwmN1H6cCQQDNu+4vw2Xe2CFjEkLI +X1stba8tsdqP04BGFectrxoeUhLMZtG2Y0ZCx+BjAACXTqfchsSjv+G9Fj/QHJLg +TxVJAkB8VQjBejvxrhTpfWepUV4VJ/WedkZpMx5gGUpymNWTkwwZsjZhS1CHvEuK +Fy7TJKBCJJE7YTenN3b/QP3Da2ylAkEAwVzMdR/Vcyj32EGleuYEsCHS78OlhGBo +w3Z6nTlh9vV0raBFooKT2tg5UVMDOzK2GlKgJreF104+E7+HXEN34QJAYF76xuMm +bKi3V1bI7/t8hXs87LLHjR90PHNzLdy61lWxMvb8oWe8KjDyaE253h24a6tEPzT1 +a8lIpqpuuuvTbg== +-----END PRIVATE KEY----- diff --git a/src/kmod/Makefile b/src/kmod/Makefile new file mode 100644 index 0000000..8a24b9e --- /dev/null +++ b/src/kmod/Makefile @@ -0,0 +1,5 @@ +obj-m += smartcapwap.o + +smartcapwap-y := \ + main.o \ + netlinkapp.o diff --git a/src/kmod/main.c b/src/kmod/main.c new file mode 100644 index 0000000..3fb58ee --- /dev/null +++ b/src/kmod/main.c @@ -0,0 +1,24 @@ +#include +#include +#include "netlinkapp.h" + +/* */ +static int __init smartcapwap_init(void) { + int result = 0; + + /* */ + result = nlsmartcapwap_init(); + + return result; +} +module_init(smartcapwap_init); + +/* */ +static void __exit smartcapwap_exit(void) { + nlsmartcapwap_exit(); +} +module_exit(smartcapwap_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Massimo Vellucci "); +MODULE_DESCRIPTION("SmartCAPWAP Data Channel Module"); diff --git a/src/kmod/netlinkapp.c b/src/kmod/netlinkapp.c new file mode 100644 index 0000000..d72b76b --- /dev/null +++ b/src/kmod/netlinkapp.c @@ -0,0 +1,125 @@ +#include +#include +#include +#include +#include +#include "nlsmartcapwap.h" +#include "netlinkapp.h" + +/* */ +#define NLSMARTCAPWAP_FLAG_NEED_RTNL 0x01 + +/* */ +static u32 g_nlusermodeid = 0; + +/* */ +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(); + } + + 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(); + } +} + +/* */ +static int nlsmartcapwap_connect(struct sk_buff *skb, struct genl_info *info) { + int result = 0; + u32 portid = genl_info_snd_portid(info); + + if (!g_nlusermodeid) { + g_nlusermodeid = portid; + } else if (g_nlusermodeid == portid) { + result = -EALREADY; + } else { + result = -EBUSY; + } + + return result; +} + +/* */ +static int nlsmartcapwap_netlink_notify(struct notifier_block* nb, unsigned long state, void* _notify) { + struct netlink_notify* notify = (struct netlink_notify*)_notify; + u32 portid = netlink_notify_portid(notify); + + /* */ + if (state = NETLINK_URELEASE) { + rtnl_lock(); + + if (g_nlusermodeid == portid) { + g_nlusermodeid = 0; + } + + rtnl_unlock(); + } + + return NOTIFY_DONE; +} + +/* Netlink Family */ +static struct genl_family nlsmartcapwap_family = { + .id = GENL_ID_GENERATE, + .name = SMARTCAPWAP_GENL_NAME, + .hdrsize = 0, + .version = 1, + .maxattr = NLSMARTCAPWAP_ATTR_MAX, + .netnsok = true, + .pre_doit = nlsmartcapwap_pre_doit, + .post_doit = nlsmartcapwap_post_doit, +}; + +static const struct nla_policy nlsmartcapwap_policy[NLSMARTCAPWAP_ATTR_MAX + 1] = { + [NLSMARTCAPWAP_ATTR_IFINDEX] = { .type = NLA_U32 }, +}; + +/* Netlink Ops */ +static __genl_const struct genl_ops nlsmartcapwap_ops[] = { + { + .cmd = NLSMARTCAPWAP_CMD_CONNECT, + .doit = nlsmartcapwap_connect, + .policy = nlsmartcapwap_policy, + .flags = GENL_ADMIN_PERM, + .internal_flags = NLSMARTCAPWAP_FLAG_NEED_RTNL, + }, +}; + +/* Netlink notify */ +static struct notifier_block nlsmartcapwap_netlink_notifier = { + .notifier_call = nlsmartcapwap_netlink_notify, +}; + +/* */ +int nlsmartcapwap_init(void) { + int result; + + /* Register netlink family */ + result = genl_register_family_with_ops(&nlsmartcapwap_family, nlsmartcapwap_ops); + if (result) { + return result; + } + + /* Register netlink notifier */ + result = netlink_register_notifier(&nlsmartcapwap_netlink_notifier); + if (result) { + genl_unregister_family(&nlsmartcapwap_family); + return result; + } + + return result; +} + +/* */ +void nlsmartcapwap_exit(void) { + netlink_unregister_notifier(&nlsmartcapwap_netlink_notifier); + genl_unregister_family(&nlsmartcapwap_family); +} diff --git a/src/kmod/netlinkapp.h b/src/kmod/netlinkapp.h new file mode 100644 index 0000000..e281da7 --- /dev/null +++ b/src/kmod/netlinkapp.h @@ -0,0 +1,8 @@ +#ifndef __KMOD_CAPWAP_NETLINKAPP_HEADER__ +#define __KMOD_CAPWAP_NETLINKAPP_HEADER__ + +/* */ +int nlsmartcapwap_init(void); +void nlsmartcapwap_exit(void); + +#endif /* __KMOD_CAPWAP_NETLINKAPP_HEADER__ */ diff --git a/src/kmod/nlsmartcapwap.h b/src/kmod/nlsmartcapwap.h new file mode 100644 index 0000000..3dd6066 --- /dev/null +++ b/src/kmod/nlsmartcapwap.h @@ -0,0 +1,29 @@ +#ifndef __CAPWAP_NLSMARTCAPWAP_HEADER__ +#define __CAPWAP_NLSMARTCAPWAP_HEADER__ + +/* */ +#define SMARTCAPWAP_GENL_NAME "smartcapwap" + +/* */ +enum nlsmartcapwap_attrs { + NLSMARTCAPWAP_ATTR_UNSPEC, + + NLSMARTCAPWAP_ATTR_IFINDEX, + + /* Last attribute */ + __NLSMARTCAPWAP_ATTR_AFTER_LAST, + NLSMARTCAPWAP_ATTR_MAX = __NLSMARTCAPWAP_ATTR_AFTER_LAST - 1 +}; + +/* */ +enum nlsmartcapwap_commands { + NLSMARTCAPWAP_CMD_UNSPEC, + + NLSMARTCAPWAP_CMD_CONNECT, + + /* Last command */ + __NLSMARTCAPWAP_CMD_AFTER_LAST, + NLSMARTCAPWAP_CMD_MAX = __NLSMARTCAPWAP_CMD_AFTER_LAST - 1 +}; + +#endif /* __CAPWAP_NLSMARTCAPWAP_HEADER__ */ diff --git a/src/wtp/binding/ieee80211/wifi_nl80211.c b/src/wtp/binding/ieee80211/wifi_nl80211.c index 1a89d05..dbdb642 100644 --- a/src/wtp/binding/ieee80211/wifi_nl80211.c +++ b/src/wtp/binding/ieee80211/wifi_nl80211.c @@ -45,7 +45,7 @@ struct family_data { /* Compatibility functions */ #ifdef HAVE_LIBNL_10 -static uint32_t port_bitmap[32] = { 0 }; +static uint32_t g_portbitmap[32] = { 0 }; static struct nl_sock* nl_socket_alloc_cb(void* cb) { int i; @@ -54,11 +54,11 @@ static struct nl_sock* nl_socket_alloc_cb(void* cb) { handle = nl_handle_alloc_cb(cb); for (i = 0; i < 1024; i++) { - if (port_bitmap[i / 32] & (1 << (i % 32))) { + if (g_portbitmap[i / 32] & (1 << (i % 32))) { continue; } - port_bitmap[i / 32] |= 1 << (i % 32); + g_portbitmap[i / 32] |= 1 << (i % 32); pid += i << 22; break; } @@ -71,7 +71,7 @@ static void nl_socket_free(struct nl_sock* handle) { uint32_t port = nl_socket_get_local_port(handle); port >>= 22; - port_bitmap[port / 32] &= ~(1 << (port % 32)); + g_portbitmap[port / 32] &= ~(1 << (port % 32)); nl_handle_destroy(handle); } diff --git a/src/wtp/wtp.c b/src/wtp/wtp.c index e12ba44..9736f65 100644 --- a/src/wtp/wtp.c +++ b/src/wtp/wtp.c @@ -8,6 +8,7 @@ #include "capwap_dtls.h" #include "wtp_dfa.h" #include "wtp_radio.h" +#include "wtp_kmod.h" #include #include @@ -1390,21 +1391,38 @@ int main(int argc, char** argv) { capwap_logging_info("Wait the initialization of radio interfaces"); wtp_wait_radio_ready(); - /* */ - capwap_logging_info("Startup WTP"); + /* Connect WTP with kernel module */ + value = wtp_kmod_init(); + if (!value || !g_wtp.kmodrequest) { + if (!value) { + g_wtp.kmodconnect = 1; + capwap_logging_info("SmartCAPWAP kernel module connected"); + } - /* Complete configuration WTP */ - result = wtp_configure(); - if (result == CAPWAP_SUCCESSFUL) { - /* Running WTP */ - result = wtp_dfa_running(); + /* */ + capwap_logging_info("Startup WTP"); - /* Close socket */ - capwap_close_sockets(&g_wtp.net); + /* Complete configuration WTP */ + result = wtp_configure(); + if (result == CAPWAP_SUCCESSFUL) { + /* Running WTP */ + result = wtp_dfa_running(); + + /* Close socket */ + capwap_close_sockets(&g_wtp.net); + } + + /* Disconnect kernel module */ + if (g_wtp.kmodconnect) { + wtp_kmod_free(); + } + + /* */ + capwap_logging_info("Terminate WTP"); + } else { + capwap_logging_fatal("Unable to connect with kernel module"); } - capwap_logging_info("Terminate WTP"); - /* Close radio */ wtp_radio_close(); diff --git a/src/wtp/wtp.h b/src/wtp/wtp.h index 3247e27..cfd2455 100644 --- a/src/wtp/wtp.h +++ b/src/wtp/wtp.h @@ -56,6 +56,11 @@ struct wtp_t { int standalone; int running; + /* */ + int kmodrequest; + int kmodconnect; + + /* */ char wlanprefix[IFNAMSIZ]; /* */ diff --git a/src/wtp/wtp_kmod.c b/src/wtp/wtp_kmod.c new file mode 100644 index 0000000..93361bf --- /dev/null +++ b/src/wtp/wtp_kmod.c @@ -0,0 +1,227 @@ +#include "wtp.h" +#include "wtp_kmod.h" +#include +#include +#include +#include "nlsmartcapwap.h" + +/* Compatibility functions */ +#ifdef HAVE_LIBNL_10 +#define nl_sock nl_handle +static uint32_t g_portbitmap[32] = { 0 }; + +static struct nl_sock* nl_socket_alloc_cb(void* cb) { + int i; + struct nl_sock* handle; + uint32_t pid = getpid() & 0x3FFFFF; + + handle = nl_handle_alloc_cb(cb); + for (i = 0; i < 1024; i++) { + if (g_portbitmap[i / 32] & (1 << (i % 32))) { + continue; + } + + g_portbitmap[i / 32] |= 1 << (i % 32); + pid += i << 22; + break; + } + + nl_socket_set_local_port(handle, pid); + return handle; +} + +static void nl_socket_free(struct nl_sock* handle) { + uint32_t port = nl_socket_get_local_port(handle); + + port >>= 22; + g_portbitmap[port / 32] &= ~(1 << (port % 32)); + + nl_handle_destroy(handle); +} +#endif + +/* */ +struct wtp_kmod_handle { + struct nl_sock* nl; + struct nl_cb* nl_cb; + int nlsmartcapwap_id; +}; + +/* */ +typedef int (*wtp_kmod_valid_cb)(struct nl_msg* msg, void* data); + +/* */ +static struct wtp_kmod_handle g_kmodhandle; + +/* */ +static struct nl_sock* nl_create_handle(struct nl_cb* cb) { + struct nl_sock* handle; + + handle = nl_socket_alloc_cb(cb); + if (!handle) { + return NULL; + } + + if (genl_connect(handle)) { + nl_socket_free(handle); + return NULL; + } + + return handle; +} + +/* */ +static int wtp_kmod_no_seq_check(struct nl_msg* msg, void* arg) { + return NL_OK; +} + +/* */ +static int wtp_kmod_error_handler(struct sockaddr_nl* nla, struct nlmsgerr* err, void* arg) { + *((int*)arg) = err->error; + return NL_STOP; +} + +/* */ +static int wtp_kmod_finish_handler(struct nl_msg* msg, void* arg) { + *((int*)arg) = 0; + return NL_SKIP; +} + +/* */ +static int wtp_kmod_ack_handler(struct nl_msg* msg, void* arg) { + *((int*)arg) = 0; + return NL_STOP; +} + +/* */ +static int wtp_kmod_valid_handler(struct nl_msg* msg, void* data) { + struct nlattr* tb_msg[NLSMARTCAPWAP_ATTR_MAX + 1]; + struct genlmsghdr* gnlh = nlmsg_data(nlmsg_hdr(msg)); + + nla_parse(tb_msg, NLSMARTCAPWAP_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL); + + return NL_SKIP; +} + +/* */ +static int wtp_kmod_send_and_recv(struct nl_sock* nl, struct nl_cb* nl_cb, struct nl_msg* msg, wtp_kmod_valid_cb valid_cb, void* data) { + int result; + struct nl_cb* cb; + + /* Clone netlink callback */ + cb = nl_cb_clone(nl_cb); + if (!cb) { + return -1; + } + + /* Complete send message */ + result = nl_send_auto_complete(nl, msg); + if (result < 0) { + nl_cb_put(cb); + return -1; + } + + /* Customize message callback */ + nl_cb_err(cb, NL_CB_CUSTOM, wtp_kmod_error_handler, &result); + nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, wtp_kmod_finish_handler, &result); + nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, wtp_kmod_ack_handler, &result); + + if (valid_cb) { + nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, valid_cb, data); + } + + result = 1; + while (result > 0) { + nl_recvmsgs(nl, cb); + } + + nl_cb_put(cb); + return result; +} + +/* */ +static int wtp_kmod_send_and_recv_msg(struct nl_msg* msg, wtp_kmod_valid_cb valid_cb, void* data) { + return wtp_kmod_send_and_recv(g_kmodhandle.nl, g_kmodhandle.nl_cb, msg, valid_cb, data); +} + +/* */ +static int wtp_kmod_connect(void) { + int result; + struct nl_msg* msg; + + /* */ + msg = nlmsg_alloc(); + if (!msg) { + return -1; + } + + /* */ + genlmsg_put(msg, 0, 0, g_kmodhandle.nlsmartcapwap_id, 0, 0, NLSMARTCAPWAP_CMD_CONNECT, 0); + + /* */ + result = wtp_kmod_send_and_recv_msg(msg, NULL, NULL); + if (result) { + if (result == -EALREADY) { + result = 0; + } else { + capwap_logging_warning("Unable to connect kernel module, error code: %d", result); + } + } + + /* */ + nlmsg_free(msg); + return result; +} + +/* */ +int wtp_kmod_init(void) { + int result; + + /* */ + memset(&g_kmodhandle, 0, sizeof(struct wtp_kmod_handle)); + + /* Configure netlink callback */ + g_kmodhandle.nl_cb = nl_cb_alloc(NL_CB_DEFAULT); + if (!g_kmodhandle.nl_cb) { + wtp_kmod_free(); + return -1; + } + + /* Create netlink socket */ + g_kmodhandle.nl = nl_create_handle(g_kmodhandle.nl_cb); + if (!g_kmodhandle.nl) { + wtp_kmod_free(); + return -1; + } + + /* Get nlsmartcapwap netlink family */ + g_kmodhandle.nlsmartcapwap_id = genl_ctrl_resolve(g_kmodhandle.nl, SMARTCAPWAP_GENL_NAME); + if (g_kmodhandle.nlsmartcapwap_id < 0) { + wtp_kmod_free(); + return -1; + } + + /* Configure callback function */ + 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(); + if (result) { + wtp_kmod_free(); + return result; + } + + return 0; +} + +/* */ +void wtp_kmod_free(void) { + if (g_kmodhandle.nl) { + nl_socket_free(g_kmodhandle.nl); + } + + if (g_kmodhandle.nl_cb) { + nl_cb_put(g_kmodhandle.nl_cb); + } +} diff --git a/src/wtp/wtp_kmod.h b/src/wtp/wtp_kmod.h new file mode 100644 index 0000000..1c4cc7c --- /dev/null +++ b/src/wtp/wtp_kmod.h @@ -0,0 +1,8 @@ +#ifndef __WTP_KMOD_HEADER__ +#define __WTP_KMOD_HEADER__ + +/* */ +int wtp_kmod_init(void); +void wtp_kmod_free(void); + +#endif /* __WTP_KMOD_HEADER__ */