432 lines
12 KiB
Bash
432 lines
12 KiB
Bash
#!/bin/sh
|
|
|
|
. /lib/functions.sh
|
|
|
|
# travelmate, a wlan connection manager for travel router
|
|
# written by Dirk Brenken (dev@brenken.org)
|
|
|
|
# This is free software, licensed under the GNU General Public License v3.
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
# prepare environment
|
|
#
|
|
LC_ALL=C
|
|
PATH="/usr/sbin:/usr/bin:/sbin:/bin"
|
|
trm_ver="0.3.0"
|
|
trm_enabled=1
|
|
trm_debug=0
|
|
trm_maxwait=20
|
|
trm_maxretry=1
|
|
trm_iw=1
|
|
trm_auto=$(uci -q get travelmate.global.trm_auto)
|
|
|
|
check_wwan() {
|
|
uci set travelmate.global.ssid="8"
|
|
wif=$(uci -q get travelmate.global.freq)
|
|
if [ -z "$wif" ]; then
|
|
uci set travelmate.global.freq="2"
|
|
fi
|
|
uci commit travelmate
|
|
while [ ! -e /etc/config/wireless ]
|
|
do
|
|
sleep 1
|
|
done
|
|
sleep 3
|
|
f_check "ap"
|
|
cntx=0
|
|
while [ "${trm_ifstatus}" != "true" ]; do
|
|
sleep 1
|
|
f_check "ap"
|
|
let cntx=cntx+1
|
|
if [ $cntx -ge 20 ]; then
|
|
break
|
|
fi
|
|
done
|
|
f_log "info" "AP Status ::: $trm_ifstatus"
|
|
}
|
|
|
|
count_radio() {
|
|
local config=$1
|
|
local channel
|
|
|
|
config_get channel $1 channel
|
|
if [ $channel -gt 15 ]; then
|
|
uci set travelmate.global.radio5="5.8 Ghz"
|
|
else
|
|
uci set travelmate.global.radio2="2.4 Ghz"
|
|
fi
|
|
let radcnt=radcnt+1
|
|
}
|
|
|
|
check_radio() {
|
|
radcnt=0
|
|
config_load wireless
|
|
config_foreach count_radio wifi-device
|
|
uci set travelmate.global.radcnt=$radcnt
|
|
uci commit travelmate
|
|
}
|
|
|
|
f_envload()
|
|
{
|
|
# source required system libraries
|
|
#
|
|
if [ -r "/lib/functions.sh" ]
|
|
then
|
|
. "/lib/functions.sh"
|
|
else
|
|
f_log "error" "required system library not found"
|
|
fi
|
|
|
|
# load uci config and check 'enabled' option
|
|
#
|
|
option_cb()
|
|
{
|
|
local option="${1}"
|
|
local value="${2}"
|
|
eval "${option}=\"${value}\""
|
|
}
|
|
config_load travelmate
|
|
|
|
if [ ${trm_enabled} -ne 1 ]
|
|
then
|
|
f_log "info " "status ::: Hotspot Manager is currently disabled"
|
|
exit 0
|
|
fi
|
|
|
|
# check for preferred wireless tool
|
|
#
|
|
if [ ${trm_iw} -eq 1 ]
|
|
then
|
|
trm_scanner="$(which iw)"
|
|
else
|
|
trm_scanner="$(which iwinfo)"
|
|
fi
|
|
if [ -z "${trm_scanner}" ]
|
|
then
|
|
f_log "error" "status ::: no wireless tool for wlan scanning found, please install 'iw' or 'iwinfo'"
|
|
fi
|
|
}
|
|
|
|
# function to bring down all STA interfaces
|
|
#
|
|
f_prepare()
|
|
{
|
|
local config="${1}"
|
|
local mode="$(uci -q get wireless."${config}".mode)"
|
|
local network="$(uci -q get wireless."${config}".network)"
|
|
local disabled="$(uci -q get wireless."${config}".disabled)"
|
|
|
|
if [ "${mode}" = "sta" ] && [ -n "${network}" ]
|
|
then
|
|
trm_stalist="${trm_stalist} ${config}_${network}"
|
|
if [ -z "${disabled}" ] || [ "${disabled}" = "0" ]
|
|
then
|
|
uci -q set wireless."${config}".disabled=1
|
|
f_log "debug" "prepare ::: config: ${config}, interface: ${network}"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
f_check()
|
|
{
|
|
local ifname cnt=0 mode="${1}"
|
|
trm_ifstatus="false"
|
|
|
|
while [ ${cnt} -lt ${trm_maxwait} ]
|
|
do
|
|
wif=$(uci -q get travelmate.global.freq)
|
|
RADIO=$(uci get wireless.wwan$wif.device)
|
|
ifname="$(ubus -S call network.wireless status | jsonfilter -l 1 -e "@.$RADIO.interfaces[@.config.mode=\"${mode}\"].ifname")"
|
|
if [ -z $ifname ]; then
|
|
break
|
|
fi
|
|
if [ "${mode}" = "sta" ]
|
|
then
|
|
trm_ifstatus="$(ubus -S call network.interface dump | jsonfilter -e "@.interface[@.device=\"${ifname}\"].up")"
|
|
else
|
|
trm_ifstatus="$(ubus -S call network.wireless status | jsonfilter -l1 -e '@.*.up')"
|
|
fi
|
|
if [ "${trm_ifstatus}" = "true" ]
|
|
then
|
|
break
|
|
fi
|
|
cnt=$((cnt+1))
|
|
sleep 1
|
|
done
|
|
f_log "debug" "check ::: ${mode} name: ${ifname}, status: ${trm_ifstatus}, count: ${cnt}"
|
|
}
|
|
|
|
# function to write to syslog
|
|
#
|
|
f_log()
|
|
{
|
|
local class="${1}"
|
|
local log_msg="${2}"
|
|
|
|
if [ -n "${log_msg}" ] && ([ "${class}" != "debug" ] || [ ${trm_debug} -eq 1 ])
|
|
then
|
|
wifilog "HOTSPOT-[${trm_ver}] ${class}" "${log_msg}"
|
|
if [ "${class}" = "error" ]
|
|
then
|
|
wif=$(uci -q get travelmate.global.freq)
|
|
uci set travelmate.global.ssid="1"
|
|
uci commit travelmate
|
|
uci -q set wireless.wwan@wif.ssid="Hotspot Manager Interface"
|
|
uci -q set wireless.wwan$wif.encryption="none"
|
|
uci -q set wireless.wwan$wif.key=
|
|
uci -q commit wireless
|
|
#exit 255
|
|
fi
|
|
fi
|
|
}
|
|
|
|
ssid_list=""
|
|
ap_list=""
|
|
trm_stalist=""
|
|
|
|
f_working_ap() {
|
|
f_check "ap"
|
|
wif=$(uci -q get travelmate.global.freq)
|
|
RADIO=$(uci get wireless.wwan$wif.device)
|
|
ap_list="$(ubus -S call network.wireless status | jsonfilter -e "@.$RADIO.interfaces[@.config.mode=\"ap\"].ifname")"
|
|
f_log "debug" "main ::: ap-list: ${ap_list}, sta-list: ${trm_stalist}"
|
|
if [ -z "${ap_list}" ] || [ -z "${trm_stalist}" ]
|
|
then
|
|
sleep 3
|
|
f_check "ap"
|
|
ap_list="$(ubus -S call network.wireless status | jsonfilter -e "@.$RADIO.interfaces[@.config.mode=\"ap\"].ifname")"
|
|
f_log "debug" "main ::: ap-list: ${ap_list}, sta-list: ${trm_stalist}"
|
|
fi
|
|
}
|
|
|
|
f_scan_ap() {
|
|
wif=$(uci -q get travelmate.global.freq)
|
|
radio=$(uci get wireless.wwan$wif.device)
|
|
# scan using AP radio
|
|
trm_iwinfo="$(command -v iwinfo)"
|
|
trm_maxscan="10"
|
|
scan_dev="$(ubus -S call network.wireless status 2>/dev/null | jsonfilter -q -l1 -e "@.${radio}.interfaces[0].ifname")"
|
|
ssid_list="$("${trm_iwinfo}" "${scan_dev:-${radio}}" scan 2>/dev/null |
|
|
awk 'BEGIN{FS="[[:space:]]"}/Address:/{var1=$NF}/ESSID:/{var2="";for(i=12;i<=NF;i++)if(var2==""){var2=$i}else{var2=var2" "$i}}
|
|
/Quality:/{split($NF,var0,"/")}/Encryption:/{if($NF=="none"){var3="+"}else{var3="-"};
|
|
printf "%i %s %s %s\n",(var0[1]*100/var0[2]),var3,var1,var2}' | sort -rn | head -qn "${trm_maxscan}")"
|
|
}
|
|
|
|
f_main()
|
|
{
|
|
local config network ssid cnt=0
|
|
wif=$(uci -q get travelmate.global.freq)
|
|
|
|
trm_stalist=""
|
|
# check if wwan is connected
|
|
f_check "sta"
|
|
if [ "${trm_ifstatus}" == "true" ]; then
|
|
wifi down $(uci -q get wireless.wwan$wif.device)
|
|
f_check "sta"
|
|
f_log "info" "STA ${trm_ifstatus}"
|
|
while [ "${trm_ifstatus}" == "true" ]; do
|
|
sleep 1
|
|
f_check "sta"
|
|
done
|
|
fi
|
|
if [ "${trm_ifstatus}" != "true" ] # not connected
|
|
then
|
|
uci set travelmate.global.state='1'
|
|
uci commit travelmate
|
|
f_check "ap"
|
|
f_log "info" "AP ${trm_ifstatus}"
|
|
if [ "${trm_ifstatus}" != "true" ]; then
|
|
wifi up $(uci -q get wireless.wwan$wif.device)
|
|
f_check "ap"
|
|
while [ "${trm_ifstatus}" != "true" ]; do
|
|
sleep 1
|
|
f_check "ap"
|
|
done
|
|
fi
|
|
uci set travelmate.global.bssid=""
|
|
uci set travelmate.global.ssid="2"
|
|
uci commit travelmate
|
|
uci -q set wireless.wwan$wif.ssid="Hotspot Manager Interface"
|
|
uci -q set wireless.wwan$wif.encryption="none"
|
|
uci -q set wireless.wwan$wif.key=
|
|
uci -q commit wireless
|
|
ubus call network.interface.wwan$wif up
|
|
ubus call network reload
|
|
wifi up $(uci -q get wireless.wwan$wif.device)
|
|
sleep 5
|
|
|
|
# set disabled for wwan iface
|
|
config_load wireless
|
|
config_foreach f_prepare wifi-iface
|
|
if [ -n "$(uci -q changes wireless)" ]
|
|
then
|
|
uci -q commit wireless
|
|
ubus call network reload
|
|
fi
|
|
# check if AP working
|
|
f_working_ap
|
|
# AP or STA not working
|
|
if [ -z "${ap_list}" ] || [ -z "${trm_stalist}" ]
|
|
then
|
|
f_log "error" "main ::: no usable AP/STA configuration found"
|
|
|
|
else
|
|
# single AP in list
|
|
for ap in ${ap_list}
|
|
do
|
|
#f_scan_ap
|
|
# repeat scan and connection
|
|
cnt=0
|
|
delay=10
|
|
reconn=$(uci -q get travelmate.global.reconn)
|
|
while [ ${cnt} -le $reconn ]
|
|
do
|
|
f_log "info" " Retry Count ${cnt}"
|
|
if [ $reconn -eq 99 ]; then
|
|
cnt=0
|
|
fi
|
|
f_scan_ap
|
|
f_log "info" " SSID List ${ssid_list}"
|
|
# get list of Hotspots present
|
|
if [ -n "${ssid_list}" ]; then
|
|
if [ "$trm_auto" = "1" ]; then
|
|
FILE="/etc/hotspot"
|
|
else
|
|
FILE="/tmp/hotman"
|
|
fi
|
|
if [ -f "${FILE}" ]; then
|
|
# read list of selected Hotspots
|
|
while IFS='|' read -r ssid encrypt key
|
|
do
|
|
ssidq="\"$ssid\""
|
|
# see if in scan list
|
|
if [ -n "$(printf "${ssid_list}" | grep -Fo "${ssidq}")" ]; then
|
|
# connect to Hotspot
|
|
uci set travelmate.global.bssid="$ssid"
|
|
uci set travelmate.global.ssid=">>> $ssid"
|
|
uci set travelmate.global.connecting="1"
|
|
uci commit travelmate
|
|
uci -q set wireless.wwan$wif.ssid="$ssid"
|
|
uci -q set wireless.wwan$wif.encryption=$encrypt
|
|
if [ "$encrypt" = "none" ]; then
|
|
key=""
|
|
fi
|
|
uci -q set wireless.wwan$wif.key=$key
|
|
uci -q set wireless.wwan$wif.disabled=0
|
|
uci -q commit wireless
|
|
wifi up $(uci -q get wireless.wwan$wif.device)
|
|
ubus call network.interface.wwan$wif up
|
|
ubus call network reload
|
|
f_log "info " "main ::: wwan interface connected to uplink ${ssid}"
|
|
sleep 5
|
|
# wait and check for good connection
|
|
f_check "ap"
|
|
f_log "info" "AP Status ::: $trm_ifstatus"
|
|
cntx=0
|
|
while [ "${trm_ifstatus}" != "true" ]; do
|
|
sleep 1
|
|
f_check "ap"
|
|
let cntx=cntx+1
|
|
if [ $cntx -ge $delay ]; then
|
|
break
|
|
fi
|
|
f_log "info" "AP Status ::: $trm_ifstatus"
|
|
done
|
|
cntx=0
|
|
#delay=$(uci -q get travelmate.global.delay)
|
|
f_check "sta"
|
|
f_log "info" "STA Status ${trm_ifstatus}"
|
|
while [ "${trm_ifstatus}" != "true" ]; do
|
|
sleep 1
|
|
f_check "sta"
|
|
let cntx=cntx+1
|
|
if [ $cntx -ge $delay ]; then
|
|
break
|
|
fi
|
|
f_log "info" "STA Status ${trm_ifstatus}"
|
|
done
|
|
|
|
if [ "${trm_ifstatus}" = "true" ]; then
|
|
uci set travelmate.global.ssid="$ssid"
|
|
uci set travelmate.global.connecting="0"
|
|
uci set travelmate.global.lost="0"
|
|
uci set travelmate.global.state='2'
|
|
uci set travelmate.global.key=$key
|
|
uci set travelmate.global.trm_auto="1"
|
|
uci commit travelmate
|
|
# connection good
|
|
f_log "info" "Connected $ssid"
|
|
exit 0
|
|
fi
|
|
# bad connection try next Hotspot in list
|
|
uci set travelmate.global.bssid=""
|
|
uci set travelmate.global.ssid="3"
|
|
uci commit travelmate
|
|
uci -q set wireless.wwan$wif.ssid="Hotspot Manager Interface"
|
|
uci -q set wireless.wwan$wif.encryption="none"
|
|
uci -q set wireless.wwan$wif.key=
|
|
uci -q set wireless.wwan$wif.disabled=1
|
|
uci -q commit wireless
|
|
ubus call network.interface.wwan$wif down
|
|
ubus call network reload
|
|
f_log "info" "Try next in list"
|
|
fi
|
|
done <"${FILE}"
|
|
wifi up $(uci -q get wireless.wwan$wif.device)
|
|
f_check "ap"
|
|
while [ "${trm_ifstatus}" != "true" ]; do
|
|
f_check "ap"
|
|
sleep 1
|
|
done
|
|
fi
|
|
fi
|
|
# No connection to any in list
|
|
cnt=$((cnt+1))
|
|
if [ $reconn -gt 0 ]; then
|
|
if [ ${cnt} -lt $reconn ]; then
|
|
f_log "info " "Sleep before retrying"
|
|
sleep 30
|
|
fi
|
|
fi
|
|
# repeat scan and connect
|
|
done
|
|
done
|
|
fi
|
|
# unable to connect
|
|
if [ "$trm_auto" = "1" ]; then
|
|
uci set travelmate.global.ssid="4"
|
|
else
|
|
uci set travelmate.global.ssid="5"
|
|
fi
|
|
reconn=$(uci -q get travelmate.global.reconn)
|
|
lost=$(uci -q get travelmate.global.lost)
|
|
if [ $reconn -eq 99 ]; then
|
|
lost="1"
|
|
fi
|
|
if [ $lost -gt $reconn ]; then
|
|
uci set travelmate.global.ssid="5"
|
|
fi
|
|
uci set travelmate.global.trm_enabled="0"
|
|
uci set travelmate.global.connecting="0"
|
|
uci set travelmate.global.lost="0"
|
|
uci set travelmate.global.state='0'
|
|
uci set travelmate.global.bssid=""
|
|
uci set travelmate.global.trm_auto="1"
|
|
uci commit travelmate
|
|
uci -q set wireless.wwan$wif.ssid="Hotspot Manager Interface"
|
|
uci -q set wireless.wwan$wif.encryption="none"
|
|
uci -q set wireless.wwan$wif.key=
|
|
uci -q commit wireless
|
|
f_log "info " "main ::: no wwan uplink found"
|
|
fi
|
|
# already connected
|
|
exit 0
|
|
}
|
|
|
|
check_wwan
|
|
check_radio
|
|
f_envload
|
|
f_main
|
|
|
|
exit 0 |