dcwifi: Add Dual Channel Wi-Fi component packages
dcstad: Dual Channel Wi-Fi Station Daemon dcwapd: Dual Channel Wi-Fi Access Point Daemon libdcwproto: Dual Channel Wi-Fi Protocol Library libdcwsocket: Dual Channel Wi-Fi Socket Library macremapper: MAC Address Remapper Linux Kernel Module mrmctl: Userland tool to get/set remap rules Signed-off-by: Carey Sonsino <careys@edgewaterwireless.com> Signed-off-by: Carey Sonsino <csonsino@gmail.com> Much help from @neheb
This commit is contained in:
parent
4f717a6f65
commit
9129b75fff
23 changed files with 1549 additions and 0 deletions
14
net/dcwifi/README.md
Normal file
14
net/dcwifi/README.md
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
# Description
|
||||||
|
|
||||||
|
This directory contains package files for including Dual Channel Wi-Fi (dcwifi) components in an OpenWrt build.
|
||||||
|
|
||||||
|
# dcwifi Packages
|
||||||
|
|
||||||
|
The dcwifi packages can be found in the menuconfig in the following locations:
|
||||||
|
|
||||||
|
* dcstad: `Network -> Routing and Redirection`
|
||||||
|
* dcwapd: `Network -> Routing and Redirection`
|
||||||
|
* libdcwproto: `Libraries -> Networking`
|
||||||
|
* libdcwsocket: `Libraries -> Networking`
|
||||||
|
* macremapper: `Kernel modules -> Network Support` (listed as `kmod-macremapper`)
|
||||||
|
* mrmctl: `Utilities`
|
49
net/dcwifi/dcstad/Makefile
Normal file
49
net/dcwifi/dcstad/Makefile
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
#
|
||||||
|
# Copyright (C) 2019 EWSI
|
||||||
|
#
|
||||||
|
# This is free software, licensed under the GNU General Public License v2.
|
||||||
|
# See /LICENSE for more information.
|
||||||
|
#
|
||||||
|
|
||||||
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
|
PKG_NAME:=dcstad
|
||||||
|
PKG_VERSION:=1.0.0
|
||||||
|
PKG_RELEASE:=1
|
||||||
|
|
||||||
|
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||||
|
PKG_SOURCE_URL:=https://codeload.github.com/ewsi/$(PKG_NAME)/tar.gz/v$(PKG_VERSION)?
|
||||||
|
PKG_HASH:=3b146ea22bc5480d8264c5ea269831d25993673aa90a9e82dc2dc601a111da55
|
||||||
|
|
||||||
|
PKG_MAINTAINER:=Carey Sonsino <careys@edgewaterwireless.com>
|
||||||
|
PKG_LICENSE:=Apache-2.0
|
||||||
|
PKG_LICENSE_FILES:=COPYING
|
||||||
|
|
||||||
|
PKG_FIXUP:=autoreconf
|
||||||
|
PKG_INSTALL:=1
|
||||||
|
PKG_BUILD_PARALLEL:=1
|
||||||
|
|
||||||
|
include $(INCLUDE_DIR)/package.mk
|
||||||
|
|
||||||
|
define Package/dcstad
|
||||||
|
SECTION:=net
|
||||||
|
CATEGORY:=Network
|
||||||
|
SUBMENU:=Routing and Redirection
|
||||||
|
TITLE:=Dual-Channel WiFi client daemon
|
||||||
|
URL:=https://www.edgewaterwireless.com
|
||||||
|
DEPENDS:=+libdcwsocket +libdcwproto
|
||||||
|
endef
|
||||||
|
|
||||||
|
define Package/dcstad/description
|
||||||
|
Implementation of the Dual-Channel WiFi client daemon
|
||||||
|
endef
|
||||||
|
|
||||||
|
TARGET_CFLAGS += -ffunction-sections -fdata-sections -flto
|
||||||
|
TARGET_LDFLAGS += -Wl,--gc-sections
|
||||||
|
|
||||||
|
define Package/dcstad/install
|
||||||
|
$(INSTALL_DIR) $(1)/bin
|
||||||
|
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/dcstad $(1)/bin/
|
||||||
|
endef
|
||||||
|
|
||||||
|
$(eval $(call BuildPackage,dcstad))
|
11
net/dcwifi/dcstad/patches/01_replace_bzero.patch
Normal file
11
net/dcwifi/dcstad/patches/01_replace_bzero.patch
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
--- a/src/main.c
|
||||||
|
+++ b/src/main.c
|
||||||
|
@@ -190,7 +190,7 @@ main( int argc, char *argv[] ) {
|
||||||
|
rv = 1; /* failure unless proven otherwise */
|
||||||
|
|
||||||
|
/* first initialize and parse the command line */
|
||||||
|
- bzero(&cfg, sizeof(cfg));
|
||||||
|
+ memset(&cfg, 0, sizeof(cfg));
|
||||||
|
parse_cmdline(&cfg, argc, argv);
|
||||||
|
|
||||||
|
dcwloginfof("%s\n", "DCW Station Daemon Starting Up...");
|
76
net/dcwifi/dcwapd/Makefile
Normal file
76
net/dcwifi/dcwapd/Makefile
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
#
|
||||||
|
# Copyright (C) 2019 EWSI
|
||||||
|
#
|
||||||
|
# This is free software, licensed under the GNU General Public License v2.
|
||||||
|
# See /LICENSE for more information.
|
||||||
|
#
|
||||||
|
|
||||||
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
|
PKG_NAME:=dcwapd
|
||||||
|
PKG_VERSION:=1.0.0
|
||||||
|
PKG_RELEASE:=1
|
||||||
|
|
||||||
|
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||||
|
PKG_SOURCE_URL:=https://codeload.github.com/ewsi/$(PKG_NAME)/tar.gz/v$(PKG_VERSION)?
|
||||||
|
PKG_HASH:=750a08abccd88d9aeda942307f76ce5711181c06f9f3e8fded5cb5ce42bac323
|
||||||
|
|
||||||
|
PKG_MAINTAINER:=Carey Sonsino <careys@edgewaterwireless.com>
|
||||||
|
PKG_LICENSE:=Apache-2.0
|
||||||
|
PKG_LICENSE_FILES:=COPYING
|
||||||
|
|
||||||
|
PKG_FIXUP:=autoreconf
|
||||||
|
PKG_INSTALL:=1
|
||||||
|
PKG_BUILD_PARALLEL:=1
|
||||||
|
|
||||||
|
include $(INCLUDE_DIR)/uclibc++.mk
|
||||||
|
include $(INCLUDE_DIR)/package.mk
|
||||||
|
|
||||||
|
define Package/dcwapd
|
||||||
|
SECTION:=net
|
||||||
|
CATEGORY:=Network
|
||||||
|
SUBMENU:=Routing and Redirection
|
||||||
|
TITLE:=Dual-Channel WiFi AP daemon
|
||||||
|
URL:=https://www.edgewaterwireless.com
|
||||||
|
DEPENDS:=$(CXX_DEPENDS) +kmod-macremapper +libdcwsocket +libdcwproto +mrmctl +libuci
|
||||||
|
endef
|
||||||
|
|
||||||
|
define Package/dcwapd/description
|
||||||
|
Implementation of the Dual-Channel WiFi AP daemon
|
||||||
|
endef
|
||||||
|
|
||||||
|
CONFIGURE_ARGS += \
|
||||||
|
--enable-platform=linuxjsonstatic \
|
||||||
|
--enable-shared
|
||||||
|
|
||||||
|
TARGET_CXXFLAGS += -std=c++11 -DRAPIDJSON_HAS_CXX11_RVALUE_REFS=0 -ffunction-sections -fdata-sections -flto
|
||||||
|
TARGET_LDFLAGS += -ldcwproto -ldcwsocket -lmrmfilterparser -luci -Wl,--gc-sections,--as-needed
|
||||||
|
|
||||||
|
define Build/InstallDev
|
||||||
|
$(INSTALL_DIR) $(1)/usr/lib
|
||||||
|
$(CP) $(PKG_INSTALL_DIR)/usr/lib/* $(1)/usr/lib/
|
||||||
|
endef
|
||||||
|
|
||||||
|
define Package/dcwapd/install
|
||||||
|
$(INSTALL_DIR) $(1)/bin
|
||||||
|
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/$(PKG_NAME) $(1)/bin/
|
||||||
|
$(INSTALL_DIR) $(1)/usr/lib
|
||||||
|
# Note: $(INSTALL_BIN) does not keep symlinks, so use $(CP)
|
||||||
|
$(CP) $(PKG_INSTALL_DIR)/usr/lib/*.so* $(1)/usr/lib/
|
||||||
|
|
||||||
|
# Utility files
|
||||||
|
$(INSTALL_DIR) $(1)/etc/$(PKG_NAME)
|
||||||
|
$(INSTALL_DATA) ./files/*.inc $(1)/etc/$(PKG_NAME)/
|
||||||
|
$(INSTALL_BIN) ./files/*.sh $(1)/etc/$(PKG_NAME)/
|
||||||
|
# UCI config file copy - this is here for convenience and reference only
|
||||||
|
$(INSTALL_DATA) ./files/dcwapd.uci $(1)/etc/$(PKG_NAME)/
|
||||||
|
|
||||||
|
# UCI config file
|
||||||
|
$(INSTALL_DIR) $(1)/etc/config
|
||||||
|
$(INSTALL_DATA) ./files/dcwapd.uci $(1)/etc/config/dcwapd
|
||||||
|
|
||||||
|
# Init script
|
||||||
|
$(INSTALL_DIR) $(1)/etc/init.d
|
||||||
|
$(INSTALL_BIN) ./files/dcwapd.init.d $(1)/etc/init.d/dcwapd
|
||||||
|
endef
|
||||||
|
$(eval $(call BuildPackage,dcwapd))
|
256
net/dcwifi/dcwapd/files/dcwapd.inc
Normal file
256
net/dcwifi/dcwapd/files/dcwapd.inc
Normal file
|
@ -0,0 +1,256 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
#
|
||||||
|
# Dual Channel Wi-Fi Startup Script
|
||||||
|
#
|
||||||
|
# This script creates the proper network bridge configuration
|
||||||
|
# necessary for Dual Channel Wi-Fi, and starts the dcwapd daemon
|
||||||
|
#
|
||||||
|
|
||||||
|
verbose=1
|
||||||
|
|
||||||
|
uciconfig=dcwapd
|
||||||
|
|
||||||
|
result=
|
||||||
|
|
||||||
|
# NOTE: all functions write the result to the $result variable
|
||||||
|
|
||||||
|
get_channelsets()
|
||||||
|
{
|
||||||
|
# default to empty
|
||||||
|
result=
|
||||||
|
channelsets=$(uci show $uciconfig | grep "=channel-set$")
|
||||||
|
for channelset in $channelsets; do
|
||||||
|
channelset=$(echo "$channelset" | sed -rn "s/$uciconfig\.(.*)=.*/\1/p")
|
||||||
|
result="$result $channelset"
|
||||||
|
done
|
||||||
|
if [ $verbose -eq 1 ]; then
|
||||||
|
echo "Channel Sets: $result" 2>&1 | logger
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# $1 : the channel set name
|
||||||
|
get_channelset_enabled()
|
||||||
|
{
|
||||||
|
# default to disabled
|
||||||
|
result=0
|
||||||
|
if [ -n "$1" ]; then
|
||||||
|
result=$(uci get $uciconfig."$1".enabled)
|
||||||
|
fi
|
||||||
|
if [ $verbose -eq 1 ]; then
|
||||||
|
echo "Channel Set \"$1\" Enabled: $result" 2>&1 | logger
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# $1 : the channel set name
|
||||||
|
get_primary_bridge()
|
||||||
|
{
|
||||||
|
result=
|
||||||
|
if [ -n "$1" ]; then
|
||||||
|
result=$(uci get $uciconfig."$1".bridge)
|
||||||
|
fi
|
||||||
|
if [ $verbose -eq 1 ]; then
|
||||||
|
echo "Channel Set \"$1\" Primary Bridge: $result" 2>&1 | logger
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# $1 : the channel set name
|
||||||
|
get_datachannels()
|
||||||
|
{
|
||||||
|
# default to empty
|
||||||
|
result=
|
||||||
|
if [ -n "$1" ]; then
|
||||||
|
result=$(uci get $uciconfig."$1".data_channels)
|
||||||
|
fi
|
||||||
|
if [ $verbose -eq 1 ]; then
|
||||||
|
echo "Channel Set \"$1\" Data Channels: $result" 2>&1 | logger
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# $1 : the wlan interface name
|
||||||
|
get_wifi_iface_num()
|
||||||
|
{
|
||||||
|
result=
|
||||||
|
if [ -n "$1" ];then
|
||||||
|
#result=$(echo "$1" | sed -n "s/wlan//p")
|
||||||
|
result=$(echo "$1" | sed -rn "s/wlan([0-9]*).*/\1/p")
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# $1 : the bridge name
|
||||||
|
get_bridge_network_name()
|
||||||
|
{
|
||||||
|
result=
|
||||||
|
if [ -n "$1" ];then
|
||||||
|
result=$(echo "$1" | sed -n "s/br-//p")
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# $1 : the wlan interface name
|
||||||
|
set_iface_init_state()
|
||||||
|
{
|
||||||
|
result=
|
||||||
|
if [ -n "$1" ]; then
|
||||||
|
iface=$1
|
||||||
|
# need to extract the "X" from wlanX
|
||||||
|
get_wifi_iface_num "$iface"
|
||||||
|
iface_num=$result
|
||||||
|
if [ -n "$iface_num" ]; then
|
||||||
|
# get the iface network
|
||||||
|
init_net=$(uci get wireless.@wifi-iface[$iface_num].network)
|
||||||
|
if [ -n "$init_net" ]; then
|
||||||
|
# if the iface network is a bridge, but doesn't start with "br-"
|
||||||
|
# I think we need to prepend it?
|
||||||
|
net_type=$(uci get network."$init_net".type)
|
||||||
|
if [ -n "$net_type" ] && [ "$net_type" = "bridge" ]; then
|
||||||
|
prefix_ok=$(echo "$init_net" | grep "^br-")
|
||||||
|
if [ -z "$prefix_ok" ]; then
|
||||||
|
init_net="br-$init_net"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# make sure that the init_net section exists
|
||||||
|
init_net_section=$(uci get dcwapd.init_net)
|
||||||
|
if [ "$init_net_section" != "init_net" ]; then
|
||||||
|
# the section did not exist
|
||||||
|
uci set dcwapd.init_net=init_net
|
||||||
|
fi
|
||||||
|
|
||||||
|
# save the initial network
|
||||||
|
if [ $verbose -eq 1 ]; then
|
||||||
|
echo "Saving '$iface' initial network '$init_net'" 2>&1 | logger
|
||||||
|
fi
|
||||||
|
uci set $uciconfig.init_net."$iface"="$init_net"
|
||||||
|
uci commit
|
||||||
|
|
||||||
|
# save the initial network in the result variable
|
||||||
|
result=$init_net
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# $1 : the wlan interface name
|
||||||
|
get_iface_init_state()
|
||||||
|
{
|
||||||
|
result=
|
||||||
|
if [ -n "$1" ];then
|
||||||
|
init_net=$(uci get $uciconfig.init_net."$iface")
|
||||||
|
|
||||||
|
# if the response starts with "uci: ", it was an error not the real result
|
||||||
|
err=$(echo "$init_net" | grep "^uci: ")
|
||||||
|
if [ -z "$err" ]; then
|
||||||
|
# no error, set the result
|
||||||
|
result=$init_net
|
||||||
|
|
||||||
|
if [ $verbose -eq 1 ]; then
|
||||||
|
echo "Got '$iface' initial network '$init_net'" 2>&1 | logger
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# $1 : the name of the data channel name to bring up
|
||||||
|
datachannel_up()
|
||||||
|
{
|
||||||
|
if [ -n "$1" ]; then
|
||||||
|
bridge=$(uci get $uciconfig."$1".bridge)
|
||||||
|
interfaces=$(uci get $uciconfig."$1".interfaces)
|
||||||
|
if [ $verbose -eq 1 ]; then
|
||||||
|
echo "Creating Data Channel Bridge: $bridge" 2>&1 | logger
|
||||||
|
fi
|
||||||
|
|
||||||
|
get_bridge_network_name "$bridge"
|
||||||
|
netname=$result
|
||||||
|
if [ -n "$netname" ]; then
|
||||||
|
uci set network."$netname"=interface
|
||||||
|
uci set network."$netname".type=bridge
|
||||||
|
uci set network."$netname".proto=static
|
||||||
|
uci set network."$netname".bridge_empty='1'
|
||||||
|
fi
|
||||||
|
|
||||||
|
# create the bridge
|
||||||
|
uci commit
|
||||||
|
/etc/init.d/network reload
|
||||||
|
|
||||||
|
for iface in $interfaces; do
|
||||||
|
# if iface is in a bridge, the bridge name should be stored in result
|
||||||
|
set_iface_init_state "$iface"
|
||||||
|
init_bridge=$result
|
||||||
|
|
||||||
|
# update uci with the new bridge info
|
||||||
|
get_wifi_iface_num "$iface"
|
||||||
|
iface_num=$result
|
||||||
|
if [ -n "$iface_num" ]; then
|
||||||
|
uci set wireless.@wifi-iface[$iface_num].network="$netname"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# manually put the interface into the data bridge
|
||||||
|
# if iface is in a bridge, remove it before adding it to the data bridge
|
||||||
|
if [ -n "$init_bridge" ]; then
|
||||||
|
brctl delif "$init_bridge" "$iface" 2>&1 | logger
|
||||||
|
fi
|
||||||
|
brctl addif "$bridge" "$iface" 2>&1 | logger
|
||||||
|
done
|
||||||
|
|
||||||
|
# commit uci changes and reload the network
|
||||||
|
uci commit
|
||||||
|
/etc/init.d/network reload
|
||||||
|
#/etc/init.d/network restart
|
||||||
|
# while [ 1 ]; do
|
||||||
|
# ifconfig "$bridge" > /dev/null 2>&1
|
||||||
|
# if [ $? == 0 ]; then
|
||||||
|
# break;
|
||||||
|
# fi
|
||||||
|
# sleep 1
|
||||||
|
# done
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# $1 : the name of the data channel to bring down
|
||||||
|
datachannel_down()
|
||||||
|
{
|
||||||
|
if [ -n "$1" ]; then
|
||||||
|
bridge=$(uci get $uciconfig."$1".bridge)
|
||||||
|
interfaces=$(uci get $uciconfig."$1".interfaces)
|
||||||
|
for iface in $interfaces; do
|
||||||
|
if [ $verbose -eq 1 ]; then
|
||||||
|
echo "Deconfiguring Data Channel Interface: $iface" 2>&1 | logger
|
||||||
|
fi
|
||||||
|
|
||||||
|
# manually remove the interface from the data bridge
|
||||||
|
brctl delif "$bridge" "$iface" 2>&1 | logger
|
||||||
|
|
||||||
|
get_iface_init_state "$iface"
|
||||||
|
init_bridge=$result
|
||||||
|
if [ -n "$init_bridge" ]; then
|
||||||
|
# manually move the interface back to the original bridge
|
||||||
|
brctl addif "$init_bridge" "$iface" 2>&1 | logger
|
||||||
|
|
||||||
|
# update uci with the new bridge and interface configuration
|
||||||
|
get_wifi_iface_num "$iface"
|
||||||
|
iface_num=$result
|
||||||
|
get_bridge_network_name "$init_bridge"
|
||||||
|
netname=$result
|
||||||
|
if [ -n "$iface_num" ] && [ -n "$netname" ]; then
|
||||||
|
uci set wireless.@wifi-iface[$iface_num].network="$netname"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [ $verbose -eq 1 ]; then
|
||||||
|
echo "Deconfiguring Data Channel Bridge: $bridge" 2>&1 | logger
|
||||||
|
fi
|
||||||
|
|
||||||
|
# delete the bridge from uci
|
||||||
|
get_bridge_network_name "$bridge"
|
||||||
|
netname=$result
|
||||||
|
if [ -n "$netname" ]; then
|
||||||
|
uci delete network."$netname"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# commit uci changes and reload the network
|
||||||
|
uci commit
|
||||||
|
/etc/init.d/network reload
|
||||||
|
#`/etc/init.d/network restart`
|
||||||
|
fi
|
||||||
|
}
|
31
net/dcwifi/dcwapd/files/dcwapd.init.d
Executable file
31
net/dcwifi/dcwapd/files/dcwapd.init.d
Executable file
|
@ -0,0 +1,31 @@
|
||||||
|
#!/bin/sh /etc/rc.common
|
||||||
|
|
||||||
|
START=99
|
||||||
|
# Setting the stop value makes the restart script unreliable when invoked by LuCI
|
||||||
|
#STOP=0
|
||||||
|
|
||||||
|
scriptdir=/etc/dcwapd
|
||||||
|
|
||||||
|
#validate_section_dcwapd() {
|
||||||
|
# uci_validate_section dcwapd general "${1}" \
|
||||||
|
# 'enabled:bool:1'
|
||||||
|
#}
|
||||||
|
|
||||||
|
start() {
|
||||||
|
# validate_section_dcwapd dcwapd
|
||||||
|
|
||||||
|
# only run the start script if the enabled uci option is set properly
|
||||||
|
enabled=$(uci get dcwapd.general.enabled)
|
||||||
|
if [ "${enabled}" = "1" ]; then
|
||||||
|
${scriptdir}/start_dcwapd.sh
|
||||||
|
else
|
||||||
|
echo "dcwapd is disabled in UCI"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
stop() {
|
||||||
|
${scriptdir}/stop_dcwapd.sh
|
||||||
|
# Add a sleep after stopping because an immediate restat will fail otherwise
|
||||||
|
sleep 1
|
||||||
|
}
|
116
net/dcwifi/dcwapd/files/dcwapd.uci
Normal file
116
net/dcwifi/dcwapd/files/dcwapd.uci
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
######################################################
|
||||||
|
# Copyright 2018 EWSI
|
||||||
|
#
|
||||||
|
# Licensed to the public under the Apache License 2.0.
|
||||||
|
######################################################
|
||||||
|
# Dual Channel Wi-Fi AP Daemon configuration
|
||||||
|
|
||||||
|
###################
|
||||||
|
# General Options #
|
||||||
|
###################
|
||||||
|
# The "enabled" option controls the run state of the Dual Channel Wi-Fi AP Daemon
|
||||||
|
# 0 - disabled, 1 - enabled
|
||||||
|
# The "tmpdir" option MUST be specified
|
||||||
|
# option tmpdir '<path_of_temp_dir>'
|
||||||
|
|
||||||
|
config general 'general'
|
||||||
|
option enabled 0
|
||||||
|
option tmpdir '/tmp/dcwapd'
|
||||||
|
|
||||||
|
################
|
||||||
|
# Channel Sets #
|
||||||
|
################
|
||||||
|
# Sections of type "channel-set" define a Dual Channel Wi-Fi primary channel,
|
||||||
|
# along with it's associated data channels
|
||||||
|
#
|
||||||
|
# The "data_channels" option is a space-delimited list of "datachannel"-typed instance names
|
||||||
|
|
||||||
|
config channel-set 'channelset0'
|
||||||
|
option enabled 0
|
||||||
|
# option enabled 1
|
||||||
|
option ssid 'OpenWrt'
|
||||||
|
option bridge 'br-lan'
|
||||||
|
option data_channels 'datachannel0'
|
||||||
|
|
||||||
|
#config channel-set 'channelset1'
|
||||||
|
# option enabled 0
|
||||||
|
# option ssid 'OpenWrt2'
|
||||||
|
# option bridge 'br-lan'
|
||||||
|
# option data_channels 'datachannel1'
|
||||||
|
|
||||||
|
#################
|
||||||
|
# Data Channels #
|
||||||
|
#################
|
||||||
|
# Sections of type "datachannel" define a Dual Channel Wi-Fi data channel,
|
||||||
|
# along with it's associated bridge and wireless interfaces
|
||||||
|
#
|
||||||
|
# The "interfaces" option is a space-delimited list of wireless interface names
|
||||||
|
|
||||||
|
config datachannel 'datachannel0'
|
||||||
|
option ssid 'DCW0'
|
||||||
|
option bridge 'br-dc0'
|
||||||
|
option interfaces 'wlan2 wlan5'
|
||||||
|
|
||||||
|
#config datachannel 'datachannel1'
|
||||||
|
# option ssid 'DCW1'
|
||||||
|
# option bridge 'br-dc1'
|
||||||
|
# option interfaces 'wlan4'
|
||||||
|
|
||||||
|
####################
|
||||||
|
# Init Net Options #
|
||||||
|
####################
|
||||||
|
# The "init_net" section MUST be specified
|
||||||
|
# This section will be used to save and restore the state of the data interfaces
|
||||||
|
config init_net 'init_net'
|
||||||
|
|
||||||
|
###############
|
||||||
|
# Filter Sets #
|
||||||
|
###############
|
||||||
|
# Sections of type "filter-set" define a Dual Channel Wi-Fi group of filters,
|
||||||
|
# along with it's associated MAC address and filter rules
|
||||||
|
#
|
||||||
|
# The "TFP_Default" filter set MUST be defined, although it is not required
|
||||||
|
# to have any associated filter rules
|
||||||
|
# The "TFP_Default" filter mac option can have the value of '*', meaning match
|
||||||
|
# all MAC addresses
|
||||||
|
#
|
||||||
|
# The "filters" option is a space-delimited list of "filter"-typed instance names
|
||||||
|
|
||||||
|
config filter-set 'TFP_Default'
|
||||||
|
option mac '*'
|
||||||
|
option filters 'filter0 filter1'
|
||||||
|
|
||||||
|
#config filter-set 'filterset0'
|
||||||
|
# option mac '00:00:BE:EF:F0:0D'
|
||||||
|
# option filters 'filter2'
|
||||||
|
|
||||||
|
|
||||||
|
################
|
||||||
|
# Filter Rules #
|
||||||
|
################
|
||||||
|
# Sections of type "filter" define a Dual Channel Wi-Fi filter,
|
||||||
|
# along with it's associated filter parameters
|
||||||
|
#
|
||||||
|
# Any or all of the filter options may be set to '*' to match
|
||||||
|
# all values
|
||||||
|
|
||||||
|
config filter 'filter0'
|
||||||
|
option packet_size '*'
|
||||||
|
option source_ip '*'
|
||||||
|
option source_port '80'
|
||||||
|
option protocol 'tcp'
|
||||||
|
option dest_port '*'
|
||||||
|
|
||||||
|
config filter 'filter1'
|
||||||
|
option packet_size '*'
|
||||||
|
option source_ip '*'
|
||||||
|
option source_port '443'
|
||||||
|
option protocol 'tcp'
|
||||||
|
option dest_port '*'
|
||||||
|
|
||||||
|
#config filter 'filter2'
|
||||||
|
# option packet_size '*'
|
||||||
|
# option source_ip '*'
|
||||||
|
# option source_port '22'
|
||||||
|
# option protocol 'tcp'
|
||||||
|
# option dest_port '*'
|
39
net/dcwifi/dcwapd/files/start_dcwapd.sh
Executable file
39
net/dcwifi/dcwapd/files/start_dcwapd.sh
Executable file
|
@ -0,0 +1,39 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
#
|
||||||
|
# Dual Channel Wi-Fi Startup Script
|
||||||
|
#
|
||||||
|
# This script creates the proper network bridge configuration
|
||||||
|
# necessary for Dual Channel Wi-Fi, and starts the dcwapd daemon
|
||||||
|
#
|
||||||
|
|
||||||
|
# Note - shellcheck cannot deal with the dynamic sourcing
|
||||||
|
# shellcheck disable=SC1090
|
||||||
|
# which also messes with variables defined in the sourced file
|
||||||
|
# shellcheck disable=SC2154
|
||||||
|
scriptdir=$(dirname -- "$(readlink -f -- "$0")")
|
||||||
|
. "$scriptdir"/dcwapd.inc
|
||||||
|
|
||||||
|
get_channelsets
|
||||||
|
# get the list of channel sets
|
||||||
|
channelsets=$result
|
||||||
|
|
||||||
|
for channelset in $channelsets; do
|
||||||
|
if [ -n "$channelset" ]; then
|
||||||
|
get_channelset_enabled "$channelset"
|
||||||
|
enabled=$result
|
||||||
|
if [ "$enabled" = "1" ]; then
|
||||||
|
# the channel set is enabled
|
||||||
|
|
||||||
|
# get the list of data channels used by the channel set
|
||||||
|
get_datachannels "$channelset"
|
||||||
|
datachannels=$result
|
||||||
|
for datachannel in $datachannels; do
|
||||||
|
datachannel_up "$datachannel"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# start dcwapd, sending stdout and stderr to the system log
|
||||||
|
dcwapd 2>&1 | logger &
|
45
net/dcwifi/dcwapd/files/stop_dcwapd.sh
Executable file
45
net/dcwifi/dcwapd/files/stop_dcwapd.sh
Executable file
|
@ -0,0 +1,45 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
#
|
||||||
|
# Dual Channel Wi-Fi Startup Script
|
||||||
|
#
|
||||||
|
# This script creates the proper network bridge configuration
|
||||||
|
# necessary for Dual Channel Wi-Fi, and starts the dcwapd daemon
|
||||||
|
#
|
||||||
|
|
||||||
|
# Note - shellcheck cannot deal with the dynamic sourcing
|
||||||
|
# shellcheck disable=SC1090
|
||||||
|
# which also messes with variables defined in the sourced file
|
||||||
|
# shellcheck disable=SC2154
|
||||||
|
scriptdir=$(dirname -- "$(readlink -f -- "$0")")
|
||||||
|
. "$scriptdir"/dcwapd.inc
|
||||||
|
|
||||||
|
pid=$(pidof dcwapd)
|
||||||
|
if [ -n "$pid" ]; then
|
||||||
|
if [ "$verbose" -eq "1" ]; then
|
||||||
|
echo "Stopping dcwapd..." 2>&1 | logger
|
||||||
|
fi
|
||||||
|
kill "$pid"
|
||||||
|
fi
|
||||||
|
|
||||||
|
get_channelsets
|
||||||
|
# get the list of channel sets
|
||||||
|
channelsets=$result
|
||||||
|
|
||||||
|
for channelset in $channelsets; do
|
||||||
|
if [ -n "$channelset" ]; then
|
||||||
|
# we don't care if it is enabled, tear it down
|
||||||
|
# get_channelset_enabled $channelset
|
||||||
|
# enabled=$result
|
||||||
|
# if [ $enabled = "1" ]; then
|
||||||
|
# # the channel set is enabled
|
||||||
|
|
||||||
|
# get the list of data channels used by the channel set
|
||||||
|
get_datachannels "$channelset"
|
||||||
|
datachannels=$result
|
||||||
|
for datachannel in $datachannels; do
|
||||||
|
datachannel_down "$datachannel"
|
||||||
|
done
|
||||||
|
# fi
|
||||||
|
fi
|
||||||
|
done
|
475
net/dcwifi/dcwapd/patches/01_add_uci_config_provider.patch
Normal file
475
net/dcwifi/dcwapd/patches/01_add_uci_config_provider.patch
Normal file
|
@ -0,0 +1,475 @@
|
||||||
|
--- a/dev/null
|
||||||
|
+++ b/dcwlinux/uci_configuration_provider.h
|
||||||
|
@@ -0,0 +1,104 @@
|
||||||
|
+#ifndef UCI_CONFIGURATION_PROVIDER_H_INCLUDED
|
||||||
|
+#define UCI_CONFIGURATION_PROVIDER_H_INCLUDED
|
||||||
|
+
|
||||||
|
+#include "./ap_configuration.h"
|
||||||
|
+
|
||||||
|
+namespace dcwlinux {
|
||||||
|
+
|
||||||
|
+class UciConfigurationProvider : public APConfigurationProvider {
|
||||||
|
+
|
||||||
|
+ static const char *SECTION_TYPE_GENERAL;
|
||||||
|
+ static const char *SECTION_TYPE_CHANNEL_SET;
|
||||||
|
+ static const char *SECTION_TYPE_DATA_CHANNEL;
|
||||||
|
+ static const char *SECTION_TYPE_FILTER_SET;
|
||||||
|
+ static const char *SECTION_TYPE_FILTER;
|
||||||
|
+ static const char *DEFAULT_FILTER_SET_NAME;
|
||||||
|
+
|
||||||
|
+ static const char *OPTION_TMPDIR;
|
||||||
|
+ static const char *OPTION_ENABLED;
|
||||||
|
+ static const char *OPTION_SSID;
|
||||||
|
+ static const char *OPTION_BRIDGE;
|
||||||
|
+ static const char *OPTION_DATA_CHANNELS;
|
||||||
|
+ static const char *OPTION_INTERFACES;
|
||||||
|
+ static const char *OPTION_MAC_ADDRESS;
|
||||||
|
+ static const char *OPTION_FILTERS;
|
||||||
|
+ static const char *OPTION_PACKET_SIZE;
|
||||||
|
+ static const char *OPTION_SOURCE_IP;
|
||||||
|
+ static const char *OPTION_SOURCE_PORT;
|
||||||
|
+ static const char *OPTION_PROTOCOL;
|
||||||
|
+ static const char *OPTION_DEST_PORT;
|
||||||
|
+
|
||||||
|
+ static const char *FILTER_FILE_EXTENSION;
|
||||||
|
+
|
||||||
|
+ UciConfigurationProvider(const UciConfigurationProvider&); //no copy
|
||||||
|
+
|
||||||
|
+ typedef std::map<std::string, std::string> DataChannelBridgeMap;
|
||||||
|
+ struct PrimaryChannel {
|
||||||
|
+ std::string bridgeName;
|
||||||
|
+ DataChannelBridgeMap dataChannels;
|
||||||
|
+ };
|
||||||
|
+ typedef std::map<std::string, PrimaryChannel> PrimaryChannelMap;
|
||||||
|
+ typedef std::map<dcw::MacAddress, std::string> StationFilterMap;
|
||||||
|
+
|
||||||
|
+ struct uci_context *_uciContext;
|
||||||
|
+ struct uci_package *_uciPackage;
|
||||||
|
+ const char *_uciConfig;
|
||||||
|
+
|
||||||
|
+ std::string _filterDirectory;
|
||||||
|
+ PrimaryChannelMap _primaryChannels;
|
||||||
|
+ StationFilterMap _stationFilters;
|
||||||
|
+
|
||||||
|
+public:
|
||||||
|
+ UciConfigurationProvider(const char * const uciConfig); // the "config" part of UCI commands
|
||||||
|
+ virtual ~UciConfigurationProvider();
|
||||||
|
+
|
||||||
|
+ virtual void InstanciateCFileTrafficFilterProfiles(CFTFPList& output) const;
|
||||||
|
+ virtual void GetPrimarySsids(SsidSet& output) const;
|
||||||
|
+ virtual void GetDataSsids(SsidSet& output, const char * const primarySsid) const;
|
||||||
|
+ virtual const char *GetSsidIfname(const char * const ssid) const;
|
||||||
|
+ virtual void GetStationTrafficFilterProfiles(StationTFPMap& output) const;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+}; //namespace dcwlinux {
|
||||||
|
+
|
||||||
|
+#endif //#ifndef UCI_CONFIGURATION_PROVIDER_H_INCLUDED
|
||||||
|
+#ifndef UCI_CONFIGURATION_PROVIDER_H_INCLUDED
|
||||||
|
+#define UCI_CONFIGURATION_PROVIDER_H_INCLUDED
|
||||||
|
+
|
||||||
|
+#include "./ap_configuration.h"
|
||||||
|
+
|
||||||
|
+namespace dcwlinux {
|
||||||
|
+
|
||||||
|
+class UciConfigurationProvider : public APConfigurationProvider {
|
||||||
|
+ UciConfigurationProvider(const UciConfigurationProvider&); //no copy
|
||||||
|
+
|
||||||
|
+ typedef std::map<std::string, std::string> DataChannelBridgeMap;
|
||||||
|
+ struct PrimaryChannel {
|
||||||
|
+ std::string bridgeName;
|
||||||
|
+ DataChannelBridgeMap dataChannels;
|
||||||
|
+ };
|
||||||
|
+ typedef std::map<std::string, PrimaryChannel> PrimaryChannelMap;
|
||||||
|
+ typedef std::map<dcw::MacAddress, std::string> StationFilterMap;
|
||||||
|
+
|
||||||
|
+ struct uci_context *_uciContext;
|
||||||
|
+ struct uci_package *_uciPackage;
|
||||||
|
+ const char *_uciConfig;
|
||||||
|
+
|
||||||
|
+ PrimaryChannelMap _primaryChannels;
|
||||||
|
+ StationFilterMap _stationFilters;
|
||||||
|
+ CFTFPList _defaultFilters;
|
||||||
|
+
|
||||||
|
+public:
|
||||||
|
+ UciConfigurationProvider(const char * const uciConfig); // the "config" part of UCI commands
|
||||||
|
+ virtual ~UciConfigurationProvider();
|
||||||
|
+
|
||||||
|
+ virtual void InstanciateCFileTrafficFilterProfiles(CFTFPList& output) const;
|
||||||
|
+ virtual void GetPrimarySsids(SsidSet& output) const;
|
||||||
|
+ virtual void GetDataSsids(SsidSet& output, const char * const primarySsid) const;
|
||||||
|
+ virtual const char *GetSsidIfname(const char * const ssid) const;
|
||||||
|
+ virtual void GetStationTrafficFilterProfiles(StationTFPMap& output) const;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+}; //namespace dcwlinux {
|
||||||
|
+
|
||||||
|
+#endif //#ifndef UCI_CONFIGURATION_PROVIDER_H_INCLUDED
|
||||||
|
--- a/dev/null
|
||||||
|
+++ b/dcwlinux/uci_configuration_provider.cxx
|
||||||
|
@@ -0,0 +1,365 @@
|
||||||
|
+
|
||||||
|
+#include <uci.h>
|
||||||
|
+#include <string.h>
|
||||||
|
+
|
||||||
|
+#include <stdlib.h>
|
||||||
|
+#include <stdexcept>
|
||||||
|
+#include <sys/stat.h>
|
||||||
|
+#include <cerrno>
|
||||||
|
+#include <iostream>
|
||||||
|
+#include <fstream>
|
||||||
|
+
|
||||||
|
+#include "./uci_configuration_provider.h"
|
||||||
|
+
|
||||||
|
+#include "dcwposix/filterdirscanner.h"
|
||||||
|
+#include "dcw/macaddress.h"
|
||||||
|
+#include "dcw/dcwlog.h"
|
||||||
|
+
|
||||||
|
+using namespace dcwlinux;
|
||||||
|
+
|
||||||
|
+ const char *UciConfigurationProvider::SECTION_TYPE_GENERAL = "general";
|
||||||
|
+ const char *UciConfigurationProvider::SECTION_TYPE_CHANNEL_SET = "channel-set";
|
||||||
|
+ const char *UciConfigurationProvider::SECTION_TYPE_DATA_CHANNEL = "datachannel";
|
||||||
|
+ const char *UciConfigurationProvider::SECTION_TYPE_FILTER_SET = "filter-set";
|
||||||
|
+ const char *UciConfigurationProvider::SECTION_TYPE_FILTER = "filter";
|
||||||
|
+ const char *UciConfigurationProvider::DEFAULT_FILTER_SET_NAME = "TFP_Default";
|
||||||
|
+
|
||||||
|
+ const char *UciConfigurationProvider::OPTION_TMPDIR = "tmpdir";
|
||||||
|
+ const char *UciConfigurationProvider::OPTION_ENABLED = "enabled";
|
||||||
|
+ const char *UciConfigurationProvider::OPTION_SSID = "ssid";
|
||||||
|
+ const char *UciConfigurationProvider::OPTION_BRIDGE = "bridge";
|
||||||
|
+ const char *UciConfigurationProvider::OPTION_DATA_CHANNELS = "data_channels";
|
||||||
|
+ const char *UciConfigurationProvider::OPTION_INTERFACES = "interfaces";
|
||||||
|
+ const char *UciConfigurationProvider::OPTION_MAC_ADDRESS = "mac";
|
||||||
|
+ const char *UciConfigurationProvider::OPTION_FILTERS = "filters";
|
||||||
|
+ const char *UciConfigurationProvider::OPTION_PACKET_SIZE = "packet_size";
|
||||||
|
+ const char *UciConfigurationProvider::OPTION_SOURCE_IP = "source_ip";
|
||||||
|
+ const char *UciConfigurationProvider::OPTION_SOURCE_PORT = "source_port";
|
||||||
|
+ const char *UciConfigurationProvider::OPTION_PROTOCOL = "protocol";
|
||||||
|
+ const char *UciConfigurationProvider::OPTION_DEST_PORT = "dest_port";
|
||||||
|
+
|
||||||
|
+ const char *UciConfigurationProvider::FILTER_FILE_EXTENSION = ".tfp";
|
||||||
|
+
|
||||||
|
+ UciConfigurationProvider::UciConfigurationProvider(const char * const uciConfig) : _uciConfig(uciConfig) {
|
||||||
|
+
|
||||||
|
+ //printf("*** Start UciConfigurationProvider(%s)\n", _uciConfig);
|
||||||
|
+ //printf("*** About to uci_alloc_context()\n");
|
||||||
|
+
|
||||||
|
+ _uciContext = uci_alloc_context();
|
||||||
|
+
|
||||||
|
+ //printf("*** uci_alloc_context() complete\n");
|
||||||
|
+ //printf("*** About to uci_load()\n");
|
||||||
|
+
|
||||||
|
+ if (_uciContext == NULL)
|
||||||
|
+ {
|
||||||
|
+ std::string err = "Error creating UCI context ";
|
||||||
|
+ throw std::runtime_error(err);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ uci_load(_uciContext, _uciConfig, &_uciPackage);
|
||||||
|
+
|
||||||
|
+ //printf("*** uci_load complete()\n");
|
||||||
|
+
|
||||||
|
+ if (_uciPackage == NULL)
|
||||||
|
+ {
|
||||||
|
+ std::string err = "Error loading UCI package " + std::string(_uciConfig);
|
||||||
|
+ throw std::runtime_error(err);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ uci_section *generalSection = uci_lookup_section(_uciContext, _uciPackage, UciConfigurationProvider::SECTION_TYPE_GENERAL);
|
||||||
|
+ if (generalSection == NULL)
|
||||||
|
+ {
|
||||||
|
+ std::string err = "Error: A general section (" + std::string(UciConfigurationProvider::SECTION_TYPE_GENERAL) + ") must be specified!";
|
||||||
|
+ throw std::runtime_error(err);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ uci_option *opt_tmpdir = uci_lookup_option(_uciContext, generalSection, UciConfigurationProvider::OPTION_TMPDIR);
|
||||||
|
+ if (opt_tmpdir == NULL)
|
||||||
|
+ {
|
||||||
|
+ std::string err = "Error: A temporary directory (" + std::string(UciConfigurationProvider::OPTION_TMPDIR) + ") must be specified!";
|
||||||
|
+ throw std::runtime_error(err);
|
||||||
|
+ }
|
||||||
|
+ char *tmpdir = opt_tmpdir->v.string;
|
||||||
|
+ //printf(" *** Set tmpdir: %s\n", tmpdir);
|
||||||
|
+
|
||||||
|
+ // make sure that tmpdir exists
|
||||||
|
+ int status = mkdir(tmpdir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
|
||||||
|
+ if ((status != 0) && // failure
|
||||||
|
+ (errno != EEXIST)) // the failure was not that the directory already existed
|
||||||
|
+ {
|
||||||
|
+ std::string err = "Error: Unable to create the temporary directory (tmpdir), error # " + errno;
|
||||||
|
+ throw std::runtime_error(err);
|
||||||
|
+ }
|
||||||
|
+ _filterDirectory = std::string(tmpdir);
|
||||||
|
+
|
||||||
|
+ if (uci_lookup_section(_uciContext, _uciPackage, UciConfigurationProvider::DEFAULT_FILTER_SET_NAME) == NULL)
|
||||||
|
+ {
|
||||||
|
+ std::string err = "Error: A default traffic filter profile named " + std::string(UciConfigurationProvider::DEFAULT_FILTER_SET_NAME) + " MUST exist!";
|
||||||
|
+ throw std::runtime_error(err);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ // iterate over all of the sections in the package
|
||||||
|
+ uci_element *elem;
|
||||||
|
+ uci_foreach_element(&_uciPackage->sections, elem)
|
||||||
|
+ {
|
||||||
|
+ //printf("--==-- element.type: %d\n", elem->type);
|
||||||
|
+ //printf("--==-- element.name: %s\n", elem->name);
|
||||||
|
+
|
||||||
|
+ if (elem->type == UCI_TYPE_SECTION)
|
||||||
|
+ {
|
||||||
|
+ // look up the section and get it's type
|
||||||
|
+
|
||||||
|
+ uci_section *section = NULL;
|
||||||
|
+ //printf("*** Looking up section: %s\n", elem->name);
|
||||||
|
+
|
||||||
|
+ section = uci_lookup_section(_uciContext, _uciPackage, elem->name);
|
||||||
|
+
|
||||||
|
+ if ((section != NULL) && (section->type != NULL))
|
||||||
|
+ {
|
||||||
|
+ //printf(" *** Section type: %s\n", section->type);
|
||||||
|
+ if (strcmp(elem->name, UciConfigurationProvider::SECTION_TYPE_GENERAL) == 0)
|
||||||
|
+ {
|
||||||
|
+ // we already processed the general section for the tmpdir
|
||||||
|
+ }
|
||||||
|
+ else if (strcmp(section->type, UciConfigurationProvider::SECTION_TYPE_CHANNEL_SET) == 0)
|
||||||
|
+ {
|
||||||
|
+ // the section is a channel set, populate it with the specified values
|
||||||
|
+
|
||||||
|
+ uci_option *enabled = uci_lookup_option(_uciContext, section, UciConfigurationProvider::OPTION_ENABLED);
|
||||||
|
+ if ((enabled == NULL) || (strcmp(enabled->v.string, "1") != 0))
|
||||||
|
+ {
|
||||||
|
+ // found a disabled channel set, ignore it
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ uci_option *ssid = uci_lookup_option(_uciContext, section, UciConfigurationProvider::OPTION_SSID);
|
||||||
|
+ uci_option *bridge = uci_lookup_option(_uciContext, section, UciConfigurationProvider::OPTION_BRIDGE);
|
||||||
|
+ uci_option *dataChannels = uci_lookup_option(_uciContext, section, UciConfigurationProvider::OPTION_DATA_CHANNELS);
|
||||||
|
+
|
||||||
|
+ if ((ssid != NULL) && (bridge != NULL) && (dataChannels != NULL))
|
||||||
|
+ {
|
||||||
|
+ PrimaryChannel &pc = _primaryChannels[ssid->v.string];
|
||||||
|
+ pc.bridgeName = bridge->v.string;
|
||||||
|
+
|
||||||
|
+ char dataChannels_list[255];
|
||||||
|
+ // The dataChannels option is not a list
|
||||||
|
+ //if (dataChannels->type == UCI_TYPE_LIST)
|
||||||
|
+ if (dataChannels->v.string != NULL)
|
||||||
|
+ {
|
||||||
|
+ strcpy(dataChannels_list, dataChannels->v.string);
|
||||||
|
+ std::string str_dataChannels = dataChannels->v.string;
|
||||||
|
+ size_t start_pos = 0;
|
||||||
|
+ size_t pos = 0;
|
||||||
|
+ while(start_pos != std::string::npos)
|
||||||
|
+ {
|
||||||
|
+ pos = str_dataChannels.find(" ", start_pos);
|
||||||
|
+ //printf("****** start_pos: %u, pos: %u\n", start_pos, pos);
|
||||||
|
+ std::string str_dataChannel = str_dataChannels.substr(start_pos,
|
||||||
|
+ pos == std::string::npos ? pos : pos-start_pos);
|
||||||
|
+ //printf("*** dataChannel: %s\n", str_dataChannel.c_str());
|
||||||
|
+
|
||||||
|
+ // update the start position for next loop
|
||||||
|
+ start_pos = (pos == std::string::npos ? pos : pos+1);
|
||||||
|
+
|
||||||
|
+ uci_section *dcSection = uci_lookup_section(_uciContext, _uciPackage, str_dataChannel.c_str());
|
||||||
|
+ if (dcSection != NULL)
|
||||||
|
+ {
|
||||||
|
+ uci_option *dcSsid = uci_lookup_option(_uciContext, dcSection, UciConfigurationProvider::OPTION_SSID);
|
||||||
|
+ uci_option *dcBridge = uci_lookup_option(_uciContext, dcSection, UciConfigurationProvider::OPTION_BRIDGE);
|
||||||
|
+
|
||||||
|
+ // TODO: configure dcBridge and dcInterfaces
|
||||||
|
+ //uci_option *dcInterfaces = uci_lookup_option(_uciContext, dcSection, UciConfigurationProvider::OPTION_INTERFACES);
|
||||||
|
+
|
||||||
|
+ if ((dcSsid != NULL) && (dcBridge != NULL))
|
||||||
|
+ {
|
||||||
|
+ pc.dataChannels[dcSsid->v.string];
|
||||||
|
+ pc.dataChannels[dcSsid->v.string] = dcBridge->v.string;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ //printf("Section: %s, SSID: %s, Bridge: %s, Data Channels: %s\n", section->e.name, ssid->v.string, bridge->v.string, dataChannels_list);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ else if (strcmp(section->type, UciConfigurationProvider::SECTION_TYPE_DATA_CHANNEL) == 0)
|
||||||
|
+ {
|
||||||
|
+ // data channels are processed by the channel set
|
||||||
|
+ }
|
||||||
|
+ else if (strcmp(section->type, UciConfigurationProvider::SECTION_TYPE_FILTER_SET) == 0)
|
||||||
|
+ {
|
||||||
|
+ // the section is a filter set, populate it with the specified values
|
||||||
|
+ //printf("*** filter set: %s\n", elem->name);
|
||||||
|
+
|
||||||
|
+ // create a tfp file for the sectionName
|
||||||
|
+ std::ofstream tfpFile;
|
||||||
|
+ std::string tfpFilePath =
|
||||||
|
+ tmpdir + std::string("/") +
|
||||||
|
+ std::string(elem->name) +
|
||||||
|
+ std::string(UciConfigurationProvider::FILTER_FILE_EXTENSION);
|
||||||
|
+ tfpFile.open(tfpFilePath.c_str(), std::ios::out | std::ios::trunc);
|
||||||
|
+ if (!tfpFile.is_open())
|
||||||
|
+ {
|
||||||
|
+ std::string err = "Error: Unable to open the filter file: " + tfpFilePath;
|
||||||
|
+ throw std::runtime_error(err);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ const char *filterDelimiter = "\n";
|
||||||
|
+ char sFilterContents[2048];
|
||||||
|
+ sFilterContents[0] = '\0';
|
||||||
|
+
|
||||||
|
+ uci_option *filters = uci_lookup_option(_uciContext, section, UciConfigurationProvider::OPTION_FILTERS);
|
||||||
|
+ // The filters option is not a list
|
||||||
|
+ //if ((filters != NULL) && (filters->type == UCI_TYPE_LIST))
|
||||||
|
+ if (filters != NULL)
|
||||||
|
+ {
|
||||||
|
+ //printf("*** %s.filters is a list.\n", elem->name);
|
||||||
|
+ //struct uci_element *e;
|
||||||
|
+ //uci_foreach_element(&filters->v.list, e)
|
||||||
|
+
|
||||||
|
+ std::string str_filters = filters->v.string;
|
||||||
|
+ //printf("*** STR_FILTERS: %s\n", str_filters.c_str());
|
||||||
|
+ size_t start_pos = 0;
|
||||||
|
+ size_t pos = 0;
|
||||||
|
+ while(start_pos != std::string::npos)
|
||||||
|
+ {
|
||||||
|
+ pos = str_filters.find(" ", start_pos);
|
||||||
|
+ //printf("****** start_pos: %u, pos: %u\n", start_pos, pos);
|
||||||
|
+ std::string str_filter = str_filters.substr(start_pos,
|
||||||
|
+ pos == std::string::npos ? pos : pos-start_pos);
|
||||||
|
+ //printf("*** Looking for filter section named: %s ...\n", str_filter.c_str());
|
||||||
|
+
|
||||||
|
+ // update the start position for next loop
|
||||||
|
+ start_pos = (pos == std::string::npos ? pos : pos+1);
|
||||||
|
+
|
||||||
|
+ uci_section *fSection = uci_lookup_section(_uciContext, _uciPackage, str_filter.c_str());
|
||||||
|
+ if (fSection != NULL)
|
||||||
|
+ {
|
||||||
|
+ uci_option *fPacketSize = uci_lookup_option(_uciContext, fSection, UciConfigurationProvider::OPTION_PACKET_SIZE);
|
||||||
|
+ uci_option *fSourceIp = uci_lookup_option(_uciContext, fSection, UciConfigurationProvider::OPTION_SOURCE_IP);
|
||||||
|
+ uci_option *fSourcePort = uci_lookup_option(_uciContext, fSection, UciConfigurationProvider::OPTION_SOURCE_PORT);
|
||||||
|
+ uci_option *fProtocol = uci_lookup_option(_uciContext, fSection, UciConfigurationProvider::OPTION_PROTOCOL);
|
||||||
|
+ uci_option *fDestPort = uci_lookup_option(_uciContext, fSection, UciConfigurationProvider::OPTION_DEST_PORT);
|
||||||
|
+
|
||||||
|
+ if ((fPacketSize != NULL) &&
|
||||||
|
+ (fSourceIp != NULL) &&
|
||||||
|
+ (fSourcePort != NULL) &&
|
||||||
|
+ (fProtocol != NULL) &&
|
||||||
|
+ (fDestPort != NULL))
|
||||||
|
+ {
|
||||||
|
+ //printf("*** filter: %s %s:%s:%s:%s:%s\n", e->name,
|
||||||
|
+ // fPacketSize->v.string, fSourceIp->v.string, fSourcePort->v.string,
|
||||||
|
+ // fProtocol->v.string, fDestPort->v.string);
|
||||||
|
+
|
||||||
|
+ strcpy(sFilterContents, fPacketSize->v.string);
|
||||||
|
+ strcat(sFilterContents, ":");
|
||||||
|
+ strcat(sFilterContents, fSourceIp->v.string);
|
||||||
|
+ strcat(sFilterContents, ":");
|
||||||
|
+ strcat(sFilterContents, fSourcePort->v.string);
|
||||||
|
+ strcat(sFilterContents, ":");
|
||||||
|
+ strcat(sFilterContents, fProtocol->v.string);
|
||||||
|
+ strcat(sFilterContents, ":");
|
||||||
|
+ strcat(sFilterContents, fDestPort->v.string);
|
||||||
|
+ strcat(sFilterContents, filterDelimiter);
|
||||||
|
+
|
||||||
|
+ //printf("*** Writing filter contents to file: %s\n", sFilterContents);
|
||||||
|
+ tfpFile << sFilterContents;
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ std::string err = "Error parsing filter: " + str_filter;
|
||||||
|
+ throw std::runtime_error(err);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ tfpFile.close();
|
||||||
|
+
|
||||||
|
+ // if there is a MAC address for the filter set, we need to add it to the station filters list
|
||||||
|
+ uci_option *mac = uci_lookup_option(_uciContext, section, UciConfigurationProvider::OPTION_MAC_ADDRESS);
|
||||||
|
+ if (mac != NULL)
|
||||||
|
+ {
|
||||||
|
+ // ignore wildcard MAC address
|
||||||
|
+ if (strcmp(mac->v.string,"*") != 0)
|
||||||
|
+ {
|
||||||
|
+ //printf(" *** MAC Address: %s\n", mac->v.string);
|
||||||
|
+ _stationFilters[::dcw::MacAddress(mac->v.string)] = elem->name;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ else if (strcmp(section->type, UciConfigurationProvider::SECTION_TYPE_FILTER) == 0)
|
||||||
|
+ {
|
||||||
|
+ // filters are processed by the filter set
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ //std::string err = "Error: Unknown UCI section type: " + std::string(section->type);
|
||||||
|
+ //throw std::runtime_error(err);
|
||||||
|
+
|
||||||
|
+ // Don't throw an exception. It is fine for UCI to contain things that we do not know about
|
||||||
|
+ // that it may use for other purposes, like UI or internal state
|
||||||
|
+ dcwlogdbgf("Ignoring UCI section type: %s\n", section->type);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ UciConfigurationProvider::~UciConfigurationProvider() {
|
||||||
|
+ uci_free_context(_uciContext);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ void UciConfigurationProvider::InstanciateCFileTrafficFilterProfiles(CFTFPList& output) const {
|
||||||
|
+ ::dcwposix::FilterdirScanner::FileFilterProfileList ffpl;
|
||||||
|
+ ::dcwposix::FilterdirScanner dirScanner(_filterDirectory.c_str());
|
||||||
|
+ dirScanner.Scan(ffpl);
|
||||||
|
+
|
||||||
|
+ for (::dcwposix::FilterdirScanner::FileFilterProfileList::const_iterator i = ffpl.begin(); i != ffpl.end(); i++) {
|
||||||
|
+ output.push_back(new ::dcw::FileTrafficFilterProfile(*i));
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+ void UciConfigurationProvider::GetPrimarySsids(SsidSet& output) const {
|
||||||
|
+ for (PrimaryChannelMap::const_iterator i = _primaryChannels.begin(); i != _primaryChannels.end(); i++) {
|
||||||
|
+ output.insert(i->first);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ void UciConfigurationProvider::GetDataSsids(SsidSet& output, const char * const primarySsid) const {
|
||||||
|
+ const PrimaryChannelMap::const_iterator pssid = _primaryChannels.find(primarySsid);
|
||||||
|
+ if (pssid == _primaryChannels.end()) return;
|
||||||
|
+
|
||||||
|
+ for (DataChannelBridgeMap::const_iterator i = pssid->second.dataChannels.begin(); i != pssid->second.dataChannels.end(); i++) {
|
||||||
|
+ output.insert(i->first);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ const char *UciConfigurationProvider::GetSsidIfname(const char * const ssid) const {
|
||||||
|
+ PrimaryChannelMap::const_iterator pssid = _primaryChannels.find(ssid);
|
||||||
|
+ if (pssid != _primaryChannels.end()) {
|
||||||
|
+ if (pssid->second.bridgeName.empty()) {
|
||||||
|
+ return NULL;
|
||||||
|
+ }
|
||||||
|
+ return pssid->second.bridgeName.c_str();
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ for (pssid = _primaryChannels.begin(); pssid != _primaryChannels.end(); pssid++) {
|
||||||
|
+ const DataChannelBridgeMap& dataChannels = pssid->second.dataChannels;
|
||||||
|
+ const DataChannelBridgeMap::const_iterator dc = dataChannels.find(ssid);
|
||||||
|
+ if (dc == dataChannels.end()) continue;
|
||||||
|
+ if (dc->second.empty()) {
|
||||||
|
+ return NULL;
|
||||||
|
+ }
|
||||||
|
+ return dc->second.c_str();
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return NULL;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ void UciConfigurationProvider::GetStationTrafficFilterProfiles(StationTFPMap& output) const {
|
||||||
|
+ for (StationFilterMap::const_iterator i = _stationFilters.begin(); i != _stationFilters.end(); i++) {
|
||||||
|
+ output[i->first] = i->second;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ }
|
20
net/dcwifi/dcwapd/patches/02_use_uci_config_provider.patch
Normal file
20
net/dcwifi/dcwapd/patches/02_use_uci_config_provider.patch
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
--- a/dcwapd.linuxjsonstatic/main.cxx
|
||||||
|
+++ b/dcwapd.linuxjsonstatic/main.cxx
|
||||||
|
@@ -10,6 +10,7 @@
|
||||||
|
#include "dcwlinux/ap_configuration.h"
|
||||||
|
#include "dcwlinux/vap_manager.h"
|
||||||
|
#include "dcwlinux/json_configuration_provider.h"
|
||||||
|
+#include "dcwlinux/uci_configuration_provider.h"
|
||||||
|
|
||||||
|
#include "dcw/dcwlog.h"
|
||||||
|
|
||||||
|
@@ -19,7 +20,8 @@ int
|
||||||
|
main( void ) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
- dcwlinux::JsonConfigurationProvider configProvider("./dcwapdconf.json");
|
||||||
|
+ //dcwlinux::JsonConfigurationProvider configProvider("./dcwapdconf.json");
|
||||||
|
+ dcwlinux::UciConfigurationProvider configProvider("dcwapd");
|
||||||
|
|
||||||
|
dcwposix::ProcessSignalManager sigman;
|
||||||
|
dcwposix::SelectEventReactor eventReactor;
|
|
@ -0,0 +1,10 @@
|
||||||
|
--- a/dcwlinux/Makefile.am
|
||||||
|
+++ b/dcwlinux/Makefile.am
|
||||||
|
@@ -6,6 +6,7 @@ libdcwlinux_la_SOURCES =
|
||||||
|
ap_configuration.cxx \
|
||||||
|
brctlnetwork.cxx \
|
||||||
|
json_configuration_provider.cxx \
|
||||||
|
+ uci_configuration_provider.cxx \
|
||||||
|
macremapper_driver.cxx \
|
||||||
|
vap_manager.cxx \
|
||||||
|
virtual_ap.cxx
|
40
net/dcwifi/dcwapd/patches/04_uclibc++_fixes.patch
Normal file
40
net/dcwifi/dcwapd/patches/04_uclibc++_fixes.patch
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
--- a/dcw/controller.cxx
|
||||||
|
+++ b/dcw/controller.cxx
|
||||||
|
@@ -195,7 +195,7 @@ void Controller::OnStationUnjoin(const MacAddress& primaryMacAddr, const Message
|
||||||
|
//remove any channel bondings matching the provided data channel mac addresses
|
||||||
|
for (unsigned i = 0; i < m.data_macaddr_count; i++) {
|
||||||
|
const ::dcw::MacAddress dcaddr(m.data_macaddrs[i]);
|
||||||
|
- const ::dcw::TrafficPolicy::DataChannelMap::iterator dcmEntry = state.policy.dataChannels.find(dcaddr);
|
||||||
|
+ ::dcw::TrafficPolicy::DataChannelMap::iterator dcmEntry = state.policy.dataChannels.find(dcaddr);
|
||||||
|
if (dcmEntry == state.policy.dataChannels.end()) continue;
|
||||||
|
if (dcmEntry->second == NULL) {
|
||||||
|
dcwlogwarnf("Data channel MAC address %s on client %s is not currently bonded\n", dcaddr.ToString().c_str(), primaryMacAddr.ToString().c_str());
|
||||||
|
@@ -238,7 +238,7 @@ void Controller::OnStationAck(const MacAddress& primaryMacAddr, const Message& m
|
||||||
|
dcwlogdbgf("Got a station ACK from %s\n", primaryMacAddr.ToString().c_str());
|
||||||
|
|
||||||
|
// first make sure this client has actually sent a join first...
|
||||||
|
- const ClientStateMap::iterator client = _clients.find(primaryMacAddr);
|
||||||
|
+ ClientStateMap::iterator client = _clients.find(primaryMacAddr);
|
||||||
|
if (client == _clients.end()) {
|
||||||
|
dcwlogerrf("Got a client ACK without a station join from %s\n", primaryMacAddr.ToString().c_str());
|
||||||
|
Message reply(DCWMSG_AP_REJECT_STA);
|
||||||
|
--- a/dcwposix/processsignalmanager.cxx
|
||||||
|
+++ b/dcwposix/processsignalmanager.cxx
|
||||||
|
@@ -40,7 +40,7 @@ ProcessSignalManager::~ProcessSignalManager() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProcessSignalManager::RegisterEventHandler(const int signum, ::dcwposix::ProcessSignalManager::EventHandler& eventHandler) {
|
||||||
|
- const SignalMap::iterator i = _sigmap.find(signum);
|
||||||
|
+ SignalMap::iterator i = _sigmap.find(signum);
|
||||||
|
if (i == _sigmap.end()) {
|
||||||
|
//be sure to preseve the old signal when inserting a new "unseen" signal
|
||||||
|
_sigmap[signum].insert(&eventHandler);
|
||||||
|
@@ -53,7 +53,7 @@ void ProcessSignalManager::RegisterEventHandler(const int signum, ::dcwposix::Pr
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProcessSignalManager::UnRegisterEventHandler(const int signum, ::dcwposix::ProcessSignalManager::EventHandler& eventHandler) {
|
||||||
|
- const SignalMap::iterator i = _sigmap.find(signum);
|
||||||
|
+ SignalMap::iterator i = _sigmap.find(signum);
|
||||||
|
|
||||||
|
if (i == _sigmap.end()) {
|
||||||
|
dcwlogwarnf("Attempting to unregister handler %p non-registered process signal #%d\n", &eventHandler, signum);
|
11
net/dcwifi/dcwapd/patches/05_replace_bzero.patch
Normal file
11
net/dcwifi/dcwapd/patches/05_replace_bzero.patch
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
--- a/dcwlinux/macremapper_driver.cxx
|
||||||
|
+++ b/dcwlinux/macremapper_driver.cxx
|
||||||
|
@@ -174,7 +174,7 @@ void MacRemapperDriver::ApplyClientTrafficPolicy(const dcw::MacAddress& primaryA
|
||||||
|
}
|
||||||
|
|
||||||
|
//populate our remap ioctl()
|
||||||
|
- bzero(&re, sizeof(re));
|
||||||
|
+ memset(&re, 0, sizeof(re));
|
||||||
|
strncpy(re.filter_name, policy.trafficFilterProfile->GetName(), sizeof(re.filter_name));
|
||||||
|
memcpy(re.match_macaddr, primaryAddr.Value, sizeof(re.match_macaddr));
|
||||||
|
|
56
net/dcwifi/libdcwproto/Makefile
Normal file
56
net/dcwifi/libdcwproto/Makefile
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
#
|
||||||
|
# Copyright (C) 2019 EWSI
|
||||||
|
#
|
||||||
|
# This is free software, licensed under the GNU General Public License v2.
|
||||||
|
# See /LICENSE for more information.
|
||||||
|
#
|
||||||
|
|
||||||
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
|
PKG_NAME:=libdcwproto
|
||||||
|
PKG_VERSION:=1.0.0
|
||||||
|
PKG_RELEASE:=1
|
||||||
|
|
||||||
|
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||||
|
PKG_SOURCE_URL:=https://codeload.github.com/ewsi/$(PKG_NAME)/tar.gz/v$(PKG_VERSION)?
|
||||||
|
PKG_HASH:=5bda395c648aa12eb90515c29024029738fde1a8f73a2cbc553be1c6962c2629
|
||||||
|
|
||||||
|
PKG_MAINTAINER:=Carey Sonsino <careys@edgewaterwireless.com>
|
||||||
|
PKG_LICENSE:=Apache-2.0
|
||||||
|
PKG_LICENSE_FILES:=COPYING
|
||||||
|
|
||||||
|
PKG_INSTALL:=1
|
||||||
|
PKG_BUILD_PARALLEL:=1
|
||||||
|
|
||||||
|
include $(INCLUDE_DIR)/package.mk
|
||||||
|
|
||||||
|
define Package/libdcwproto
|
||||||
|
SECTION:=libs
|
||||||
|
CATEGORY:=Libraries
|
||||||
|
SUBMENU:=Networking
|
||||||
|
TITLE:=Dual-Channel WiFi messaging library
|
||||||
|
URL:=https://www.edgewaterwireless.com
|
||||||
|
DEPENDS:=+kmod-macremapper
|
||||||
|
endef
|
||||||
|
|
||||||
|
define Package/libdcwproto/description
|
||||||
|
Platform-independent C library for marshaling and serializing DCW messages
|
||||||
|
endef
|
||||||
|
|
||||||
|
TARGET_CFLAGS += -ffunction-sections -fdata-sections -flto
|
||||||
|
TARGET_LDFLAGS += -Wl,--gc-sections,--as-needed
|
||||||
|
|
||||||
|
define Build/InstallDev
|
||||||
|
$(INSTALL_DIR) $(1)/usr/include
|
||||||
|
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/include/*.h $(1)/usr/include/
|
||||||
|
$(INSTALL_DIR) $(1)/usr/lib
|
||||||
|
$(CP) $(PKG_INSTALL_DIR)/usr/lib/$(PKG_NAME)*.so* $(1)/usr/lib/
|
||||||
|
endef
|
||||||
|
|
||||||
|
define Package/libdcwproto/install
|
||||||
|
$(INSTALL_DIR) $(1)/usr/lib
|
||||||
|
# Note: $(INSTALL_BIN) does not keep symlinks, so use $(CP)
|
||||||
|
$(CP) $(PKG_INSTALL_DIR)/usr/lib/$(PKG_NAME)*.so* $(1)/usr/lib/
|
||||||
|
endef
|
||||||
|
|
||||||
|
$(eval $(call BuildPackage,libdcwproto))
|
33
net/dcwifi/libdcwproto/patches/01_replace_bzero.patch
Normal file
33
net/dcwifi/libdcwproto/patches/01_replace_bzero.patch
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
--- a/src/dcwproto.c
|
||||||
|
+++ b/src/dcwproto.c
|
||||||
|
@@ -20,12 +20,8 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-#ifdef WIN32
|
||||||
|
-#define bzero(ptr, size) memset(ptr, 0, size)
|
||||||
|
-#else
|
||||||
|
#include <config.h>
|
||||||
|
#include <strings.h>
|
||||||
|
-#endif
|
||||||
|
#include <dcwproto.h>
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
@@ -95,7 +91,7 @@ dcwmsg_marshal_sta_ack(struct dcwmsg_sta_ack * const output, const unsigned char
|
||||||
|
|
||||||
|
/* copy in the data ssid string bytes */
|
||||||
|
if (buf_len < copy_size) return 0;
|
||||||
|
- bzero(output->bonded_data_channels[i].ssid, sizeof(output->bonded_data_channels[i].ssid));
|
||||||
|
+ memset(output->bonded_data_channels[i].ssid, 0, sizeof(output->bonded_data_channels[i].ssid));
|
||||||
|
memcpy(output->bonded_data_channels[i].ssid, buf, copy_size);
|
||||||
|
buf_len -= copy_size;
|
||||||
|
buf += copy_size;
|
||||||
|
@@ -134,7 +130,7 @@ dcwmsg_marshal_ap_accept_sta(struct dcwmsg_ap_accept_sta * const output, const u
|
||||||
|
|
||||||
|
/* copy in the data ssid string bytes */
|
||||||
|
if (buf_len < copy_size) return 0;
|
||||||
|
- bzero(output->data_ssids[i], sizeof(output->data_ssids[i]));
|
||||||
|
+ memset(output->data_ssids[i], 0, sizeof(output->data_ssids[i]));
|
||||||
|
memcpy(output->data_ssids[i], buf, copy_size);
|
||||||
|
buf_len -= copy_size;
|
||||||
|
buf += copy_size;
|
56
net/dcwifi/libdcwsocket/Makefile
Normal file
56
net/dcwifi/libdcwsocket/Makefile
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
#
|
||||||
|
# Copyright (C) 2019 EWSI
|
||||||
|
#
|
||||||
|
# This is free software, licensed under the GNU General Public License v2.
|
||||||
|
# See /LICENSE for more information.
|
||||||
|
#
|
||||||
|
|
||||||
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
|
PKG_NAME:=libdcwsocket
|
||||||
|
PKG_VERSION:=1.0.0
|
||||||
|
PKG_RELEASE:=1
|
||||||
|
|
||||||
|
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||||
|
PKG_SOURCE_URL:=https://codeload.github.com/ewsi/$(PKG_NAME)/tar.gz/v$(PKG_VERSION)?
|
||||||
|
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
|
||||||
|
PKG_HASH:=c7f6c69a5246fe1f184c21585f0805ceaca09c3c087ae439ded7ed4d25c7a3fa
|
||||||
|
|
||||||
|
PKG_MAINTAINER:=Carey Sonsino <careys@edgewaterwireless.com>
|
||||||
|
PKG_LICENSE:=Apache-2.0
|
||||||
|
PKG_LICENSE_FILES:=COPYING
|
||||||
|
|
||||||
|
PKG_INSTALL:=1
|
||||||
|
PKG_BUILD_PARALLEL:=1
|
||||||
|
|
||||||
|
include $(INCLUDE_DIR)/package.mk
|
||||||
|
|
||||||
|
define Package/libdcwsocket
|
||||||
|
SECTION:=libs
|
||||||
|
CATEGORY:=Libraries
|
||||||
|
SUBMENU:=Networking
|
||||||
|
TITLE:=Dual-Channel socket library
|
||||||
|
URL:=https://www.edgewaterwireless.com
|
||||||
|
endef
|
||||||
|
|
||||||
|
define Package/libdcwsocket/description
|
||||||
|
User-land C library for sending and receiving DCW "EtherType"d messages
|
||||||
|
endef
|
||||||
|
|
||||||
|
TARGET_CFLAGS += -std=c89 -ffunction-sections -fdata-sections -flto
|
||||||
|
TARGET_LDFLAGS += -Wl,--gc-sections,--as-needed
|
||||||
|
|
||||||
|
define Build/InstallDev
|
||||||
|
$(INSTALL_DIR) $(1)/usr/include
|
||||||
|
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/include/*.h $(1)/usr/include/
|
||||||
|
$(INSTALL_DIR) $(1)/usr/lib
|
||||||
|
$(CP) $(PKG_INSTALL_DIR)/usr/lib/$(PKG_NAME)*.so* $(1)/usr/lib/
|
||||||
|
endef
|
||||||
|
|
||||||
|
define Package/libdcwsocket/install
|
||||||
|
$(INSTALL_DIR) $(1)/usr/lib
|
||||||
|
# Note: $(INSTALL_BIN) does not keep symlinks, so use $(CP)
|
||||||
|
$(CP) $(PKG_INSTALL_DIR)/usr/lib/$(PKG_NAME)*.so* $(1)/usr/lib/
|
||||||
|
endef
|
||||||
|
|
||||||
|
$(eval $(call BuildPackage,libdcwsocket))
|
45
net/dcwifi/libdcwsocket/patches/01_replace_bzero.patch
Normal file
45
net/dcwifi/libdcwsocket/patches/01_replace_bzero.patch
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
--- a/src/dcwsocket.c.linux
|
||||||
|
+++ b/src/dcwsocket.c.linux
|
||||||
|
@@ -100,10 +100,10 @@ dcwsock_open(const char * const ifname) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sanitize our data structs... defensive */
|
||||||
|
- bzero(rv, sizeof(*rv));
|
||||||
|
- bzero(&ifr, sizeof(ifr));
|
||||||
|
- bzero(&sall, sizeof(sall));
|
||||||
|
- bzero(&sfp, sizeof(sfp));
|
||||||
|
+ memset(rv, 0, sizeof(*rv));
|
||||||
|
+ memset(&ifr, 0, sizeof(ifr));
|
||||||
|
+ memset(&sall, 0, sizeof(sall));
|
||||||
|
+ memset(&sfp, 0, sizeof(sfp));
|
||||||
|
|
||||||
|
/* open a raw socket... "ETH_P_ALL" says take EVERYTHING
|
||||||
|
(this means that it is IMPERATIVE to apply a filter)
|
||||||
|
diff --git a/src/dcwsocket.c.osx b/src/dcwsocket.c.osx
|
||||||
|
index abead10..75cda2f 100644
|
||||||
|
--- a/src/dcwsocket.c.osx
|
||||||
|
+++ b/src/dcwsocket.c.osx
|
||||||
|
@@ -90,10 +90,10 @@ dcwsock_open(const char * const ifname) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sanitize our data structs... defensive */
|
||||||
|
- bzero(rv, sizeof(*rv));
|
||||||
|
- bzero(&dmx_desc, sizeof(dmx_desc));
|
||||||
|
- bzero(&proto_desc, sizeof(proto_desc));
|
||||||
|
- bzero(&snd, sizeof(snd));
|
||||||
|
+ memset(rv, 0, sizeof(*rv));
|
||||||
|
+ memset(&dmx_desc, 0, sizeof(dmx_desc));
|
||||||
|
+ memset(&proto_desc, 0, sizeof(proto_desc));
|
||||||
|
+ memset(&snd, 0, sizeof(snd));
|
||||||
|
|
||||||
|
/* open a "NDRV" socket... */
|
||||||
|
rv->fd = socket(PF_NDRV, SOCK_RAW, 0);
|
||||||
|
@@ -201,7 +201,7 @@ dcwsock_send( dcw_socket_t s, const void * const buf, const unsigned buf_size, c
|
||||||
|
fill out a link-level sockaddr cause we can only
|
||||||
|
use sendto() with PF_NDRV...
|
||||||
|
*/
|
||||||
|
- bzero(&sdl, sizeof(sdl));
|
||||||
|
+ memset(&sdl, 0, sizeof(sdl));
|
||||||
|
sdl.sdl_len = sizeof(sdl);
|
||||||
|
sdl.sdl_index = 0;
|
||||||
|
sdl.sdl_type = IFT_ETHER;
|
|
@ -0,0 +1,10 @@
|
||||||
|
--- a/src/dcwsocket.c.linux
|
||||||
|
+++ b/src/dcwsocket.c.linux
|
||||||
|
@@ -31,6 +31,7 @@
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
+#include <linux/if.h>
|
||||||
|
#include <linux/if_packet.h>
|
||||||
|
#include <linux/if_ether.h>
|
||||||
|
#include <linux/filter.h>
|
42
net/dcwifi/macremapper/Makefile
Normal file
42
net/dcwifi/macremapper/Makefile
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
#
|
||||||
|
# Copyright (C) 2019 EWSI
|
||||||
|
#
|
||||||
|
# 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:=macremapper
|
||||||
|
PKG_VERSION:=1.0.0
|
||||||
|
PKG_RELEASE:=1
|
||||||
|
|
||||||
|
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||||
|
PKG_SOURCE_URL:=https://codeload.github.com/ewsi/$(PKG_NAME)/tar.gz/v$(PKG_VERSION)?
|
||||||
|
PKG_HASH:=f054201dd805ce005b89606a507b58a5717d383a4339c69dfdc02f0202935437
|
||||||
|
|
||||||
|
PKG_MAINTAINER:=Carey Sonsino <careys@edgewaterwireless.com>
|
||||||
|
PKG_LICENSE:=GPL-2.0-only
|
||||||
|
PKG_LICENSE_FILES:=kernelmod/COPYING
|
||||||
|
|
||||||
|
include $(INCLUDE_DIR)/package.mk
|
||||||
|
|
||||||
|
define KernelPackage/macremapper
|
||||||
|
SUBMENU:=Network Support
|
||||||
|
URL:=https://www.edgewaterwireless.com
|
||||||
|
VERSION:=$(LINUX_VERSION)-$(BOARD)-$(PKG_RELEASE)
|
||||||
|
TITLE:=Dual Channel Wi-Fi macremapper Module
|
||||||
|
DEPENDS:= +kmod-cfg80211 +kmod-br-netfilter
|
||||||
|
FILES:=$(PKG_BUILD_DIR)/kernelmod/$(PKG_NAME).$(LINUX_KMOD_SUFFIX)
|
||||||
|
AUTOLOAD:=$(call AutoProbe,macremapper)
|
||||||
|
endef
|
||||||
|
|
||||||
|
define KernelPackage/macremapper/description
|
||||||
|
Linux kernel module for implementation the DCW filtering mechanism
|
||||||
|
endef
|
||||||
|
|
||||||
|
MAKE_FLAGS += KERNEL_SRC=$(LINUX_DIR)
|
||||||
|
MAKE_PATH:=kernelmod
|
||||||
|
|
||||||
|
$(eval $(call KernelPackage,macremapper))
|
27
net/dcwifi/macremapper/patches/01_fix_nf_hooks.patch
Normal file
27
net/dcwifi/macremapper/patches/01_fix_nf_hooks.patch
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
--- a/kernelmod/main.c
|
||||||
|
+++ b/kernelmod/main.c
|
||||||
|
@@ -91,8 +91,11 @@ modinit( void ) {
|
||||||
|
|
||||||
|
rv = mrm_rcdb_init();
|
||||||
|
if (rv != 0) return rv;
|
||||||
|
-
|
||||||
|
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,13,0)
|
||||||
|
nf_register_hook(&_hops);
|
||||||
|
+#else
|
||||||
|
+ nf_register_net_hook(&init_net, &_hops);
|
||||||
|
+#endif
|
||||||
|
mrm_init_ctlfile(); /* XXX not checking for failure! */
|
||||||
|
|
||||||
|
printk(KERN_INFO "MRM The MAC Address Re-Mapper is now in the kernel\n");
|
||||||
|
@@ -103,7 +106,11 @@ modinit( void ) {
|
||||||
|
static void __exit
|
||||||
|
modexit( void ) {
|
||||||
|
mrm_destroy_ctlfile();
|
||||||
|
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,13,0)
|
||||||
|
nf_unregister_hook(&_hops);
|
||||||
|
+#else
|
||||||
|
+ nf_unregister_net_hook(&init_net, &_hops);
|
||||||
|
+#endif
|
||||||
|
mrm_rcdb_destroy(); /* imperative that this happens last */
|
||||||
|
printk(KERN_INFO "MRM The MAC Address Re-Mapper gone bye-bye\n");
|
||||||
|
}
|
63
net/dcwifi/mrmctl/Makefile
Normal file
63
net/dcwifi/mrmctl/Makefile
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
#
|
||||||
|
# Copyright (C) 2019 EWSI
|
||||||
|
#
|
||||||
|
# This is free software, licensed under the GNU General Public License v2.
|
||||||
|
# See /LICENSE for more information.
|
||||||
|
#
|
||||||
|
|
||||||
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
|
PKG_NAME:=mrmctl
|
||||||
|
PKG_VERSION:=1.0.0
|
||||||
|
PKG_RELEASE:=1
|
||||||
|
|
||||||
|
PKG_SOURCE:=macremapper-$(PKG_VERSION).tar.gz
|
||||||
|
PKG_SOURCE_URL:=https://codeload.github.com/ewsi/macremapper/tar.gz/v$(PKG_VERSION)?
|
||||||
|
PKG_HASH:=f054201dd805ce005b89606a507b58a5717d383a4339c69dfdc02f0202935437
|
||||||
|
PKG_BUILD_DIR:=$(BUILD_DIR)/macremapper-$(PKG_VERSION)
|
||||||
|
|
||||||
|
PKG_MAINTAINER:=Carey Sonsino <careys@edgewaterwireless.com>
|
||||||
|
PKG_LICENSE:=Apache-2.0
|
||||||
|
PKG_LICENSE_FILES:=userland/COPYING
|
||||||
|
|
||||||
|
PKG_INSTALL:=1
|
||||||
|
PKG_BUILD_PARALLEL:=1
|
||||||
|
|
||||||
|
include $(INCLUDE_DIR)/package.mk
|
||||||
|
|
||||||
|
define Package/mrmctl
|
||||||
|
SECTION:=utils
|
||||||
|
CATEGORY:=Utilities
|
||||||
|
TITLE:=mrmctl utility (macremapper kernel module)
|
||||||
|
URL:=https://www.edgewaterwireless.com
|
||||||
|
DEPENDS:= +kmod-macremapper
|
||||||
|
endef
|
||||||
|
|
||||||
|
define Package/mrmctl/description
|
||||||
|
Command-line utility to manually manipulate the macremapper kernel module
|
||||||
|
endef
|
||||||
|
|
||||||
|
MAKE_PATH:=userland
|
||||||
|
CONFIGURE_PATH:=userland
|
||||||
|
CONFIGURE_ARGS += \
|
||||||
|
--enable-shared
|
||||||
|
|
||||||
|
TARGET_CFLAGS += -std=c89 -ffunction-sections -fdata-sections -flto
|
||||||
|
TARGET_LDFLAGS += -Wl,--gc-sections,--as-needed
|
||||||
|
|
||||||
|
define Build/InstallDev
|
||||||
|
$(INSTALL_DIR) $(1)/usr/include
|
||||||
|
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/include/*.h $(1)/usr/include/
|
||||||
|
$(INSTALL_DIR) $(1)/usr/lib
|
||||||
|
$(CP) $(PKG_INSTALL_DIR)/usr/lib/*.so* $(1)/usr/lib/
|
||||||
|
endef
|
||||||
|
|
||||||
|
define Package/mrmctl/install
|
||||||
|
$(INSTALL_DIR) $(1)/bin
|
||||||
|
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/$(PKG_NAME) $(1)/bin/
|
||||||
|
|
||||||
|
$(INSTALL_DIR) $(1)/usr/lib
|
||||||
|
$(CP) $(PKG_INSTALL_DIR)/usr/lib/*.so* $(1)/usr/lib/
|
||||||
|
endef
|
||||||
|
|
||||||
|
$(eval $(call BuildPackage,mrmctl))
|
24
net/dcwifi/mrmctl/patches/01_replace_bzero.patch
Normal file
24
net/dcwifi/mrmctl/patches/01_replace_bzero.patch
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
--- a/userland/mrmctl/mrmctl.c
|
||||||
|
+++ b/userland/mrmctl/mrmctl.c
|
||||||
|
@@ -139,7 +139,7 @@ remap(int argc, char **argv) {
|
||||||
|
if (argc < 5) return 1; /* defensive */
|
||||||
|
|
||||||
|
/* initialize variables and put things into human-readable variable names */
|
||||||
|
- bzero(&re, sizeof(re));
|
||||||
|
+ memset(&re, 0, sizeof(re));
|
||||||
|
filter_name = argv[2];
|
||||||
|
match_macaddr = argv[3];
|
||||||
|
|
||||||
|
diff --git a/userland/mrmfilterparser/mrm_filter_conf_parser.c b/userland/mrmfilterparser/mrm_filter_conf_parser.c
|
||||||
|
index 926fa76..f5c54c1 100644
|
||||||
|
--- a/userland/mrmfilterparser/mrm_filter_conf_parser.c
|
||||||
|
+++ b/userland/mrmfilterparser/mrm_filter_conf_parser.c
|
||||||
|
@@ -319,7 +319,7 @@ filter_file_loadf(struct mrm_filter_config * const output, FILE * const f) {
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
output->rules_active = 0;
|
||||||
|
- bzero(output->rules, sizeof(output->rules)); /* defensive */
|
||||||
|
+ memset(output->rules, 0, sizeof(output->rules)); /* defensive */
|
||||||
|
|
||||||
|
for (linenum = 1; fgets(buf, sizeof(buf), f) != NULL; linenum++) {
|
||||||
|
|
Loading…
Reference in a new issue