Merge pull request #16372 from dibdot/travelmate

travelmate: update to 2.0.5-3
This commit is contained in:
Dirk Brenken 2021-08-15 20:30:18 +02:00 committed by GitHub
commit b4a4aab5fa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 52 additions and 65 deletions

View File

@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=travelmate
PKG_VERSION:=2.0.5
PKG_RELEASE:=2
PKG_RELEASE:=3
PKG_LICENSE:=GPL-3.0-or-later
PKG_MAINTAINER:=Dirk Brenken <dev@brenken.org>

View File

@ -73,14 +73,11 @@ To avoid these kind of deadlocks, travelmate will set all station interfaces to
| trm_minquality | 35 | minimum signal quality threshold as percent for conditional uplink (dis-) connections |
| trm_maxwait | 30 | how long should travelmate wait for a successful wlan uplink connection |
| trm_timeout | 60 | overall retry timeout in seconds |
| trm_scanbuffer | 1024 | buffer size in bytes to prepare nearby scan results |
| trm_captiveurl | http://captive.apple.com | four pre-configured provider URLs that will be used for connectivity- and captive portal checks |
| trm_useragent | Mozilla/5.0 (X11; Linux x86_64... | five pre-configured user agents that will be used for connectivity- and captive portal checks |
| trm_maxautoadd | 5 | limit the max. number of automatically added open uplinks. To disable this limitation set it to '0' |
| trm_maxscan | 10 | limit nearby scan results to process only the strongest uplinks |
| trm_captiveurl | http://detectportal.firefox.com | pre-configured provider URLs that will be used for connectivity- and captive portal checks |
| trm_useragent | Mozilla/5.0 ... | pre-configured user agents that will be used for connectivity- and captive portal checks |
| trm_nice | 0, normal priority | change the priority of the travelmate background processing |
| trm_vpn | 0, disabled | automatically handle VPN (re-) connections |
| trm_vpnservice | -, not set | reference the already configured 'wireguard' or 'openvpn' client instance as vpn provider |
| trm_vpniface | -, not set | the logical vpn interface, e.g. 'wg0' or 'tun0' |
| trm_laniface | -, not set | the logical lan network interface, e.g. 'br-lan' |
| trm_mail | 0, disabled | sends notification e-mails after every succesful uplink connect |
| trm_mailreceiver | -, not set | e-mail receiver address for travelmate notifications |
| trm_mailsender | no-reply@travelmate | e-mail sender address for travelmate notifications |
@ -101,6 +98,10 @@ To avoid these kind of deadlocks, travelmate will set all station interfaces to
| con_end_expiry | 0, disabled | automatically (re-)enable the uplink after n minutes, e.g. after failed login attempts |
| script | -, not set | reference to an external auto login script for captive portals |
| script_args | -, not set | optional runtime args for the auto login script |
| macaddr | -, not set | use a specified MAC address for the uplink
| vpn | 0, disabled | automatically handle VPN (re-) connections |
| vpnservice | -, not set | reference the already configured 'wireguard' or 'openvpn' client instance as vpn provider |
| vpniface | -, not set | the logical vpn interface, e.g. 'wg0' or 'tun0' |
## VPN client setup
@ -135,11 +136,14 @@ password zzz
Finally enable E-Mail support in travelmate and add a valid E-Mail receiver address.
## Captive Portal auto-logins
For automated captive portal logins you can reference an external shell script per uplink. All login scripts should be executable and located in '/etc/travelmate' with the extension '.login'. Currently the package ships five ready to run auto-login scripts:
* 'wifionice.login' for german ICE hotspots
For automated captive portal logins you can reference an external shell script per uplink. All login scripts should be executable and located in '/etc/travelmate' with the extension '.login'. The package ships multiple ready to run auto-login scripts:
* 'wifionice.login' for ICE hotspots (DE)
* 'db-bahn.login' for german DB railway hotspots via portal login API (still WIP, only tested at Hannover central station)
* 'chs-hotel.login' for german chs hotels
* 'h-hotels.login' for Telekom hotspots in german h+hotels
* 'h-hotels.login' for Telekom hotspots in h+hotels (DE)
* 'julianahoeve.login' for Julianahoeve beach resort (NL)
* 'telekom.login' for telekom hotspots (DE)
* 'vodafone.login' for vodafone hotspots (DE)
* 'generic-user-pass.login' a template to demonstrate the optional parameter handling in login scripts
A typical and successful captive portal login looks like this:

View File

@ -22,11 +22,11 @@ trm_randomize="0"
trm_mail="0"
trm_mailpgm="/etc/travelmate/travelmate.mail"
trm_vpnpgm="/etc/travelmate/travelmate.vpn"
trm_scanbuffer="1024"
trm_minquality="35"
trm_maxretry="3"
trm_maxwait="30"
trm_maxautoadd="5"
trm_maxscan="10"
trm_timeout="60"
trm_opensta="0"
trm_radio=""
@ -51,7 +51,7 @@ trm_action="${1:-"start"}"
# load travelmate environment
#
f_env() {
local IFS check wpa_checks ubus_check result
local check wpa_checks ubus_check result
if [ "${trm_action}" = "stop" ]; then
return
@ -130,7 +130,7 @@ f_env() {
# trim helper function
#
f_trim() {
local IFS trim="${1}"
local trim="${1}"
trim="${trim#"${trim%%[![:space:]]*}"}"
trim="${trim%"${trim##*[![:space:]]}"}"
@ -140,7 +140,7 @@ f_trim() {
# status helper function
#
f_char() {
local IFS result input="${1}"
local result input="${1}"
if [ "${input}" = "1" ]; then
result="✔"
@ -153,7 +153,7 @@ f_char() {
# wifi helper function
#
f_wifi() {
local IFS radio tmp_radio cnt="0"
local radio tmp_radio cnt="0"
"${trm_wifi}" reconf
for radio in ${trm_radiolist}; do
@ -175,7 +175,7 @@ f_wifi() {
# vpn helper function
#
f_vpn() {
local IFS rc vpn vpn_service vpn_iface vpn_action="${1}"
local rc vpn vpn_service vpn_iface vpn_action="${1}"
vpn="$(f_getval "vpn")"
@ -200,7 +200,7 @@ f_vpn() {
# mac helper function
#
f_mac() {
local IFS result ifname macaddr action="${1}" section="${2}"
local result ifname macaddr action="${1}" section="${2}"
if [ "${action}" = "set" ]; then
macaddr="$(f_getval "macaddr")"
@ -224,7 +224,7 @@ f_mac() {
# set connection information
#
f_ctrack() {
local IFS expiry action="${1}"
local expiry action="${1}"
if [ -n "${trm_uplinkcfg}" ]; then
case "${action}" in
@ -282,7 +282,7 @@ f_ctrack() {
# get uplink config section
#
f_getcfg() {
local IFS t_radio t_essid t_bssid radio="${1}" essid="${2}" bssid="${3}" cnt="0"
local t_radio t_essid t_bssid radio="${1}" essid="${2}" bssid="${3}" cnt="0"
while uci_get "travelmate" "@uplink[${cnt}]" >/dev/null 2>&1; do
t_radio="$(uci_get "travelmate" "@uplink[${cnt}]" "device")"
@ -301,7 +301,7 @@ f_getcfg() {
# get travelmate option value in 'uplink' sections
#
f_getval() {
local IFS result t_option="${1}"
local result t_option="${1}"
if [ -n "${trm_uplinkcfg}" ]; then
result="$(uci_get "travelmate" "${trm_uplinkcfg}" "${t_option}")"
@ -313,7 +313,7 @@ f_getval() {
# set 'wifi-device' sections
#
f_setdev() {
local IFS disabled radio="${1}"
local disabled radio="${1}"
disabled="$(uci_get "wireless" "${radio}" "disabled")"
if [ "${disabled}" = "1" ]; then
@ -331,7 +331,7 @@ f_setdev() {
# set 'wifi-iface' sections
#
f_setif() {
local IFS mode radio essid bssid disabled status con_start con_end con_start_expiry con_end_expiry section="${1}" proactive="${2}"
local mode radio essid bssid disabled status con_start con_end con_start_expiry con_end_expiry section="${1}" proactive="${2}"
mode="$(uci_get "wireless" "${section}" "mode")"
radio="$(uci_get "wireless" "${section}" "device")"
@ -386,8 +386,7 @@ f_setif() {
# add open uplinks
#
f_addsta() {
local IFS uci_cfg new_uplink="1" offset="1" radio="${1}" essid="${2}"
local uci_cfg new_uplink="1" offset="1" radio="${1}" essid="${2}"
if [ "${trm_maxautoadd}" = "0" ] || [ "${trm_opensta:-0}" -lt "${trm_maxautoadd}" ]; then
config_cb() {
@ -448,7 +447,7 @@ f_addsta() {
# check net status
#
f_net() {
local IFS err_msg raw html_raw html_cp json_raw json_ec json_rc json_cp json_ed result="net nok"
local err_msg raw html_raw html_cp json_raw json_ec json_rc json_cp json_ed result="net nok"
raw="$(${trm_fetch} --user-agent "${trm_useragent}" --referer "http://www.example.com" --header "Cache-Control: no-cache, no-store, must-revalidate" --header "Pragma: no-cache" --header "Expires: 0" --write-out "%{json}" --silent --connect-timeout $((trm_maxwait / 10)) "${trm_captiveurl}")"
json_raw="${raw#*\{}"
@ -487,7 +486,7 @@ f_net() {
# check interface status
#
f_check() {
local IFS ifname radio dev_status result login_script login_script_args cp_domain wait_time="1" enabled="1" mode="${1}" status="${2}" sta_radio="${3}" sta_essid="${4}" sta_bssid="${5}"
local ifname radio dev_status result login_script login_script_args cp_domain wait_time="1" enabled="1" mode="${1}" status="${2}" sta_radio="${3}" sta_essid="${4}" sta_bssid="${5}"
if [ "${mode}" = "initial" ] || [ "${mode}" = "dev" ]; then
json_get_var station_id "station_id"
@ -503,8 +502,7 @@ f_check() {
enabled="$(f_getval "enabled")"
fi
if { [ "${mode}" != "initial" ] && [ "${mode}" != "dev" ] && [ "${status}" = "false" ]; } ||
{ [ "${mode}" = "dev" ] && { [ "${status}" = "false" ] ||
{ [ "${trm_ifstatus}" != "${status}" ] && [ "${enabled}" = "0" ]; }; }; }; then
{ [ "${mode}" = "dev" ] && { [ "${status}" = "false" ] || { [ "${trm_ifstatus}" != "${status}" ] && [ "${enabled}" = "0" ]; }; }; }; then
f_wifi
fi
while [ "${wait_time}" -le "${trm_maxwait}" ]; do
@ -611,21 +609,19 @@ f_check() {
# update runtime information
#
f_jsnup() {
local IFS vpn section last_date last_station sta_iface sta_radio sta_essid sta_bssid sta_mac dev_status last_status status="${trm_ifstatus}" ntp_done="0" vpn_done="0" mail_done="0"
local vpn section last_date last_station sta_iface sta_radio sta_essid sta_bssid sta_mac dev_status last_status status="${trm_ifstatus}" ntp_done="0" vpn_done="0" mail_done="0"
if [ "${status}" = "true" ]; then
vpn="$(f_getval "vpn")"
status="connected (${trm_connection:-"-"})"
dev_status="$(ubus -S call network.wireless status 2>/dev/null)"
if [ -n "${dev_status}" ]; then
section="$(printf "%s" "${dev_status}" | jsonfilter -q -l1 -e '@.*.interfaces[@.config.mode="sta"].section')"
if [ -n "${section}" ]; then
sta_iface="$(uci_get "wireless" "${section}" "network")"
sta_radio="$(uci_get "wireless" "${section}" "device")"
sta_essid="$(uci_get "wireless" "${section}" "ssid")"
sta_bssid="$(uci_get "wireless" "${section}" "bssid")"
sta_mac="$(f_mac "get" "${section}")"
fi
section="$(printf "%s" "${dev_status}" | jsonfilter -q -l1 -e '@.*.interfaces[@.config.mode="sta"].section')"
if [ -n "${section}" ]; then
sta_iface="$(uci_get "wireless" "${section}" "network")"
sta_radio="$(uci_get "wireless" "${section}" "device")"
sta_essid="$(uci_get "wireless" "${section}" "ssid")"
sta_bssid="$(uci_get "wireless" "${section}" "bssid")"
sta_mac="$(f_mac "get" "${section}")"
fi
json_get_var last_date "last_run"
json_get_var last_station "station_id"
@ -687,7 +683,7 @@ f_jsnup() {
# write to syslog
#
f_log() {
local IFS class="${1}" log_msg="${2}"
local class="${1}" log_msg="${2}"
if [ -n "${log_msg}" ] && { [ "${class}" != "debug" ] || [ "${trm_debug}" = "1" ]; }; then
if [ -x "${trm_logger}" ]; then
@ -707,7 +703,7 @@ f_log() {
# main function for connection handling
#
f_main() {
local IFS cnt retrycnt spec scan_dev scan_list scan_essid scan_bssid scan_open scan_quality
local cnt retrycnt scan_dev scan_list scan_essid scan_bssid scan_open scan_quality
local station_id section sta sta_essid sta_bssid sta_radio sta_iface sta_mac config_essid config_bssid config_radio
f_check "initial" "false"
@ -728,7 +724,7 @@ f_main() {
uci_commit "wireless"
f_check "dev" "false"
fi
f_log "debug" "f_main-3 ::: radio_list: ${trm_radiolist}, sta_list: ${trm_stalist:0:trm_scanbuffer}"
f_log "debug" "f_main-3 ::: radio_list: ${trm_radiolist:-"-"}, sta_list: ${trm_stalist:-"-"}"
# radio loop
#
@ -750,12 +746,10 @@ f_main() {
sta_bssid="$(uci_get "wireless" "${section}" "bssid")"
sta_iface="$(uci_get "wireless" "${section}" "network")"
sta_mac="$(f_mac "get" "${section}")"
if [ -z "${sta_radio}" ] || [ -z "${sta_essid}" ] || [ -z "${sta_iface}" ]; then
f_log "info" "invalid wireless section '${section}'"
continue
fi
if [ "${radio}" = "${config_radio}" ] && [ "${sta_radio}" = "${config_radio}" ] &&
[ "${sta_essid}" = "${config_essid}" ] && [ "${sta_bssid}" = "${config_bssid}" ]; then
f_ctrack "refresh"
@ -767,10 +761,10 @@ f_main() {
if [ -z "${scan_list}" ]; then
scan_dev="$(ubus -S call network.wireless status 2>/dev/null | jsonfilter -q -l1 -e "@.${radio}.interfaces[0].ifname")"
scan_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};
gsub(/,/,".",var2)}/Quality:/{split($NF,var0,"/")}/Encryption:/{if($NF=="none"){var3="+"}else{var3="-"};printf "%i,%s,%s,%s\n",(var0[1]*100/var0[2]),var1,var2,var3}' |
sort -rn | awk -v buf="${trm_scanbuffer}" 'BEGIN{ORS=","}{print substr($0,1,buf)}')"
f_log "debug" "f_main-5 ::: radio: ${radio}, scan_device: ${scan_dev}, scan_buffer: ${trm_scanbuffer}, scan_list: ${scan_list:-"-"}"
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_log "debug" "f_main-5 ::: radio: ${radio}, scan_device: ${scan_dev}, scan_max: ${trm_maxscan}"
if [ -z "${scan_list}" ]; then
f_log "info" "no scan results on '${radio}'"
continue 2
@ -779,21 +773,11 @@ f_main() {
# scan loop
#
IFS=","
for spec in ${scan_list}; do
if [ -z "${scan_quality}" ]; then
scan_quality="${spec}"
elif [ -z "${scan_bssid}" ]; then
scan_bssid="${spec}"
elif [ -z "${scan_essid}" ]; then
scan_essid="${spec}"
elif [ -z "${scan_open}" ]; then
scan_open="${spec}"
fi
if [ -n "${scan_quality}" ] && [ -n "${scan_bssid}" ] && [ -n "${scan_essid}" ] && [ -n "${scan_open}" ]; then
f_log "debug" "f_main-6 ::: radio(sta/scan): ${sta_radio}/${radio}, essid(sta/scan): \"${sta_essid//,/.}\"/${scan_essid}, bssid(sta/scan): ${sta_bssid}/${scan_bssid}, open: ${scan_open}, quality: ${scan_quality}"
printf "%s\n" "${scan_list}" | while read -r scan_quality scan_open scan_bssid scan_essid; do
if [ -n "${scan_quality}" ] && [ -n "${scan_open}" ] && [ -n "${scan_bssid}" ] && [ -n "${scan_essid}" ]; then
f_log "debug" "f_main-6 ::: radio(sta/scan): ${sta_radio}/${radio}, essid(sta/scan): \"${sta_essid}\"/${scan_essid}, bssid(sta/scan): ${sta_bssid}/${scan_bssid}, quality(min/scan): ${trm_minquality}/${scan_quality}, open: ${scan_open}"
if [ "${scan_quality}" -ge "${trm_minquality}" ]; then
if { { [ "${scan_essid}" = "\"${sta_essid//,/.}\"" ] && { [ -z "${sta_bssid}" ] || [ "${scan_bssid}" = "${sta_bssid}" ]; }; } ||
if { { [ "${scan_essid}" = "\"${sta_essid}\"" ] && { [ -z "${sta_bssid}" ] || [ "${scan_bssid}" = "${sta_bssid}" ]; }; } ||
{ [ "${scan_bssid}" = "${sta_bssid}" ] && [ "${scan_essid}" = "unknown" ]; }; } && [ "${radio}" = "${sta_radio}" ]; then
f_vpn "disable"
if [ -n "${config_radio}" ]; then
@ -813,7 +797,6 @@ f_main() {
uci_set "wireless" "${section}" "disabled" "0"
f_check "sta" "false" "${sta_radio}" "${sta_essid}" "${sta_bssid}"
if [ "${trm_ifstatus}" = "true" ]; then
unset IFS scan_list
rm -f "${trm_mailfile}"
uci_commit "wireless"
f_ctrack "start"
@ -847,7 +830,7 @@ f_main() {
fi
fi
done
unset IFS scan_quality scan_bssid scan_essid scan_open
unset scan_quality scan_bssid scan_essid scan_open
done
unset scan_list
done

View File

@ -29,7 +29,7 @@ trm_logger="$(command -v logger)"
trm_fetch="$(command -v curl)"
f_net() {
local IFS json_rc result="net nok"
local json_rc result="net nok"
json_rc="$(${trm_fetch} --user-agent "${trm_useragent}" --referer "http://www.example.com" --connect-timeout $((trm_maxwait / 10)) --header "Cache-Control: no-cache, no-store, must-revalidate" --header "Pragma: no-cache" --header "Expires: 0" --write-out "%{response_code}" --silent --output /dev/null "${trm_captiveurl}")"
if [ "${json_rc}" = "200" ] || [ "${json_rc}" = "204" ]; then