Ubiquitis airmax based gear does not fallback to original port after DFS event is over. This tool triggers the fallback automatically by soft-restarting unconditionally, whenever the configured freq differs from the running. Signed-off-by: Simon Polack <spolack+git@mailbox.org>lilik-openwrt-22.03
@ -0,0 +1,46 @@ | |||
# SPDX-License-Identifier: GPL-2.0-only | |||
# | |||
# Copyright (C) 2021 Simon Polack <spolack+git@@mailbox.org> | |||
# | |||
include $(TOPDIR)/rules.mk | |||
PKG_NAME:=airos-dfs-reset | |||
PKG_VERSION:=1 | |||
PKG_RELEASE:=$(AUTORELEASE) | |||
PKG_MAINTAINER:=Simon Polack <spolack+git@mailbox.org> | |||
PKG_LICENSE:=GPL-2.0-only | |||
include $(INCLUDE_DIR)/package.mk | |||
define Package/airos-dfs-reset | |||
SECTION:=utils | |||
CATEGORY:=Utilities | |||
TITLE:=Companion app for Ubiquity AirOS to help with DFS | |||
PKGARCH:=all | |||
EXTRA_DEPENDS:=dropbear | |||
endef | |||
define Package/airos-dfs-reset/description | |||
Companion app for Ubiquity AirOS Gear to enforce fallback to original frequency after DFS event is over. | |||
It works by soft-rebooting if running-frequency doesnt match the configured frequency. | |||
endef | |||
define Package/airos-dfs-reset/conffiles | |||
/etc/config/airos-dfs-reset | |||
endef | |||
define Build/Compile | |||
endef | |||
define Package/airos-dfs-reset/install | |||
$(INSTALL_DIR) $(1)/etc/init.d | |||
$(INSTALL_BIN) ./files/airos-dfs-reset.init $(1)/etc/init.d/airos-dfs-reset | |||
$(INSTALL_DIR) $(1)/usr/bin | |||
$(INSTALL_BIN) ./files/airos-dfs-reset $(1)/usr/bin/airos-dfs-reset | |||
$(INSTALL_DIR) $(1)/etc/config | |||
$(INSTALL_DATA) ./files/airos-dfs-reset.config $(1)/etc/config/airos-dfs-reset | |||
endef | |||
$(eval $(call BuildPackage,airos-dfs-reset)) |
@ -0,0 +1,114 @@ | |||
#!/bin/sh | |||
. /lib/functions.sh | |||
log() { | |||
local msg="$1" | |||
logger -t airos-dfs-reset -s "$msg" | |||
} | |||
rexec() { | |||
local target="$1" | |||
local username="$2" | |||
local password="$3" | |||
local cmd="$4" | |||
raw=$(DROPBEAR_PASSWORD="$password" ssh -y $username@$target "$cmd") | |||
ssh_result=$? | |||
} | |||
reset_dfs() { | |||
local cmd="/usr/etc/rc.d/rc.softrestart force" | |||
rexec $* "$cmd" | |||
} | |||
get_running_freq() { | |||
local cmd="iwconfig ath0 | grep Frequency | awk -F ':' '{print \$3}' | awk '{print \$1}' | sed 's/\.//'" | |||
rexec $* "$cmd" | |||
# Append zeroes which are then cut to 4, we have to convert GHz into MHz | |||
raw="$raw"000 | |||
running_freq=${raw:0:4} | |||
} | |||
get_target_freq() { | |||
local cmd="grep 'radio.1.freq' /tmp/system.cfg | awk -F '=' '{ print \$2}'" | |||
rexec $* "$cmd" | |||
target_freq="$raw" | |||
} | |||
check_dfs() { | |||
local target="$1" | |||
local username="$2" | |||
local password="$3" | |||
get_running_freq $target $username $password | |||
if [ "$ssh_result" != 0 ]; then | |||
return | |||
fi | |||
get_target_freq $target $username $password | |||
if [ "$ssh_result" != 0 ]; then | |||
return | |||
fi | |||
log "Running freq: $running_freq - Target freq: $target_freq" | |||
[ "$running_freq" == "$target_freq" ] | |||
} | |||
reset_allowed() { | |||
local daytime_limit="$1" | |||
local start="$(echo $daytime_limit | awk -F '-' '{print $1'})" | |||
local end="$(echo $daytime_limit | awk -F '-' '{print $2'})" | |||
local cur="$(date +%H)" | |||
[ "$cur" -ge "$start" ] && [ "$cur" -le "$end" ] | |||
} | |||
handle_device() { | |||
local device="$1" | |||
config_get target "$device" target | |||
config_get username "$device" username | |||
config_get password "$device" password | |||
config_get daytime_limit "$device" daytime_limit "0-23" | |||
ssh_result=0 | |||
log "Checking Device $device" | |||
check_dfs $target $username $password | |||
freqmatch=$? | |||
if [ "$ssh_result" != 0 ]; then | |||
log "ssh exited non-zero - connect timeout?" | |||
return | |||
elif [ "$freqmatch" == 0 ]; then | |||
log "Frequency is matching. No radar event fired" | |||
else | |||
log "Frequency doesnt match. Looks like DFS activity :(" | |||
if reset_allowed $daytime_limit; then | |||
log "Initiating reset" | |||
reset_dfs $target $username $password | |||
log "Waiting $cfg_reset_sleep seconds after reset" | |||
sleep $cfg_reset_sleep | |||
else | |||
log "Resetting is forbidden at this daytime" | |||
fi | |||
fi | |||
} | |||
main() { | |||
log "started!" | |||
config_load airos-dfs-reset | |||
config_get cfg_interval general interval 600 | |||
config_get cfg_reset_sleep general reset_sleep 120 | |||
while :; | |||
do | |||
config_foreach handle_device device | |||
sleep $cfg_interval | |||
done | |||
} | |||
main |
@ -0,0 +1,15 @@ | |||
config airos-dfs-reset general | |||
option interval '600' # Check every x seconds | |||
option reset_sleep '120' # Sleep after reset to let routing protocols reconverge | |||
config device 'sample_ap' # make sure to not use dashes in name | |||
option target '192.168.1.20' | |||
option username 'ubnt' | |||
option password 'ubnt' | |||
option daytime_limit '2-7' # .. from 2:xx to 7:xx reset is allowed | |||
#config device 'sample_ap1' | |||
# option target '10.31.81.21' | |||
# option username 'ubnt' | |||
# option password '...' | |||
# option daytime_limit '0-23' |
@ -0,0 +1,18 @@ | |||
#!/bin/sh /etc/rc.common | |||
USE_PROCD=1 | |||
START=95 | |||
STOP=01 | |||
start_service() { | |||
procd_open_instance | |||
procd_set_param command /usr/bin/airos-dfs-reset | |||
procd_set_param stdout 0 | |||
procd_set_param stderr 0 | |||
procd_set_param user nobody | |||
procd_close_instance | |||
} | |||
service_stopped() { | |||
echo "airos-dfs-reset stopped!" | |||
} |