travelmate: update 1.4.12
authorDirk Brenken <dev@brenken.org>
Thu, 29 Aug 2019 12:03:23 +0000 (14:03 +0200)
committerDirk Brenken <dev@brenken.org>
Fri, 30 Aug 2019 05:41:13 +0000 (07:41 +0200)
* automatically add open uplinks to your wireless config,
  e.g. hotel captive portals (disabled by default)
* shift net status check in a separate function
* (s)hellcheck cosmetics

Signed-off-by: Dirk Brenken <dev@brenken.org>
(cherry picked from commit 1d90509b0351458f66c68d8106f7a8e9bfdd904d)

net/travelmate/Makefile
net/travelmate/files/README.md
net/travelmate/files/travelmate.conf
net/travelmate/files/travelmate.sh

index 17eb903b8fe8fa522d4fe4d69526a823aef93152..2d961144d12d3d4d880e31b60babc42c51630a47 100644 (file)
@@ -6,7 +6,7 @@
 include $(TOPDIR)/rules.mk
 
 PKG_NAME:=travelmate
-PKG_VERSION:=1.4.11
+PKG_VERSION:=1.4.12
 PKG_RELEASE:=1
 PKG_LICENSE:=GPL-3.0+
 PKG_MAINTAINER:=Dirk Brenken <dev@brenken.org>
index f84fffa73e8169bc11c56146a74ecd84f4eb7d29..4f7eab676a94b891c801794403af0c06ab9177c6 100644 (file)
@@ -12,6 +12,7 @@ To avoid these kind of deadlocks, travelmate will set all station interfaces to
 * fast uplink connections
 * support all kinds of uplinks, incl. hidden and enterprise uplinks
 * continuously checks the existing uplink connection (quality), e.g. for conditional uplink (dis-) connections
+* automatically add open uplinks to your wireless config, e.g. hotel captive portals
 * captive portal detection with internet online check and a 'heartbeat' function to keep the uplink connection up & running
 * captive portal auto-login hook (configured via uci/LuCI), you could reference an external script for captive portal auto-logins (see example below)
 * proactively scan and switch to a higher prioritized uplink, despite of an already existing connection
@@ -47,6 +48,7 @@ To avoid these kind of deadlocks, travelmate will set all station interfaces to
     * trm\_debug => enable/disable debug logging (bool/default: '0', disabled)
     * trm\_captive => enable/disable the captive portal detection (bool/default: '1', enabled)
     * trm\_proactive => enable/disable the proactive uplink switch (bool/default: '1', enabled)
+    * trm\_autoadd => automatically add open uplinks to your wireless config (bool/default: '0', disabled)
     * trm\_minquality => minimum signal quality threshold as percent for conditional uplink (dis-) connections (int/default: '35', valid range: 20-80)
     * trm\_maxwait => how long (in seconds) should travelmate wait for a successful wlan interface reload action (int/default: '30', valid range: 20-40)
     * trm\_maxretry => how many times should travelmate try to connect to an uplink (int/default: '3', valid range: 1-10)
@@ -56,9 +58,9 @@ To avoid these kind of deadlocks, travelmate will set all station interfaces to
     * trm\_triggerdelay => additional trigger delay in seconds before travelmate processing begins (int/default: '2')
 
 ## Captive Portal auto-logins
-For automated captive portal logins you could reference external shell scripts. All login scripts should be executable and located in '/etc/travelmate' with the extension '.login'. The provided 'wifionice.login' script example requires curl and automates the login to german ICE hotspots, it also explains the principle approach to extract runtime data like security tokens for a succesful login. Hopefully more scripts for different captive portals will be provided by the community ...
+For automated captive portal logins you could reference external shell scripts. All login scripts should be executable and located in '/etc/travelmate' with the extension '.login'. The provided 'wifionice.login' script example requires curl and automates the login to german ICE hotspots, it also explains the principle approach to extract runtime data like security tokens for a successful login. Hopefully more scripts for different captive portals will be provided by the community ...
 
-A typical/succesful captive portal login looks like this:
+A typical/successful captive portal login looks like this:
 <pre><code>
 [...]
 Mon Aug  5 10:15:48 2019 user.info travelmate-1.4.10[1481]: travelmate instance started ::: action: start, pid: 1481
index 1833b92a7a59f50ae989bbb8763a23bc865e0800..ce9eb5f97ae60781b02d813c4f1fbdf6eed54ee9 100644 (file)
@@ -6,6 +6,7 @@ config travelmate 'global'
        option trm_captive '1'
        option trm_proactive '1'
        option trm_netcheck '0'
+       option trm_autoadd '0'
        option trm_iface 'trm_wwan'
        option trm_triggerdelay '2'
        option trm_debug '0'
index 1e00179a21fe258ded029346678999cb1e07506b..8cd1f3841250b713efffa6493a44ca20a95505a9 100755 (executable)
@@ -6,18 +6,21 @@
 # You should have received a copy of the GNU General Public License
 # along with this program. If not, see <http://www.gnu.org/licenses/>.
 
+# (s)hellcheck exceptions
+# shellcheck disable=1091 disable=2039 disable=2143 disable=2181 disable=2188
+
 # set initial defaults
 #
 LC_ALL=C
 PATH="/usr/sbin:/usr/bin:/sbin:/bin"
-trm_ver="1.4.11"
-trm_sysver="unknown"
+trm_ver="1.4.12"
 trm_enabled=0
 trm_debug=0
 trm_iface="trm_wwan"
 trm_captive=1
 trm_proactive=1
 trm_netcheck=0
+trm_autoadd=0
 trm_captiveurl="http://captive.apple.com"
 trm_scanbuffer=1024
 trm_minquality=35
@@ -49,7 +52,7 @@ f_trim()
 #
 f_envload()
 {
-       local IFS sys_call sys_desc sys_model
+       local IFS
 
        # (re-)initialize global list variables
        #
@@ -57,17 +60,12 @@ f_envload()
 
        # get system information
        #
-       sys_call="$(ubus -S call system board 2>/dev/null)"
-       if [ -n "${sys_call}" ]
-       then
-               sys_desc="$(printf '%s' "${sys_call}" | jsonfilter -e '@.release.description')"
-               sys_model="$(printf '%s' "${sys_call}" | jsonfilter -e '@.model')"
-               trm_sysver="${sys_model}, ${sys_desc}"
-       fi
+       trm_sysver="$(ubus -S call system board 2>/dev/null | jsonfilter -e '@.model' -e '@.release.description' | \
+               awk 'BEGIN{ORS=", "}{print $0}' | awk '{print substr($0,1,length($0)-2)}')"
 
        # get eap capabilities
        #
-       trm_eap="$("${trm_wpa}" -veap >/dev/null 2>&1; printf "%u" ${?})"
+       trm_eap="$("${trm_wpa}" -veap >/dev/null 2>&1; printf "%u" "${?}")"
 
        # load config and check 'enabled' option
        #
@@ -137,11 +135,11 @@ f_prep()
 {
        local IFS mode network radio disabled eaptype config="${1}" proactive="${2}"
 
-       mode="$(uci_get wireless "${config}" mode)"
-       network="$(uci_get wireless "${config}" network)"
-       radio="$(uci_get wireless "${config}" device)"
-       disabled="$(uci_get wireless "${config}" disabled)"
-       eaptype="$(uci_get wireless "${config}" eap_type)"
+       mode="$(uci_get "wireless" "${config}" "mode")"
+       network="$(uci_get "wireless" "${config}" "network")"
+       radio="$(uci_get "wireless" "${config}" "device")"
+       disabled="$(uci_get "wireless" "${config}" "disabled")"
+       eaptype="$(uci_get "wireless" "${config}" "eap_type")"
 
        if [ -n "${config}" ] && [ -n "${radio}" ] && [ -n "${mode}" ] && [ -n "${network}" ]
        then
@@ -171,17 +169,29 @@ f_prep()
        f_log "debug" "f_prep ::: config: ${config}, mode: ${mode}, network: ${network}, radio: ${radio}, trm_radio: ${trm_radio:-"-"}, trm_active_sta: ${trm_active_sta:-"-"}, proactive: ${proactive}, trm_eap: ${trm_eap:-"-"}, disabled: ${disabled}"
 }
 
+# check net status
+#
+f_net()
+{
+       local IFS result
+
+       result="$(${trm_fetch} --timeout=$((trm_maxwait/6)) "${trm_captiveurl}" -O /dev/null 2>&1 | \
+               awk '/^Failed to redirect|^Redirected/{printf "%s" "net cp \047"$NF"\047";exit}/^Download completed/{printf "%s" "net ok";exit}/^Failed|Connection error/{printf "%s" "net nok";exit}')"
+       printf "%s" "${result}"
+       f_log "debug" "f_net  ::: fetch: ${trm_fetch}, timeout: $((trm_maxwait/6)), url: ${trm_captiveurl}, result: ${result}"
+}
+
 # check interface status
 #
 f_check()
 {
-       local IFS ifname radio dev_status config sta_essid sta_bssid result uci_essid uci_bssid login_command bg_pid wait_time mode="${1}" status="${2:-"false"}" cp_domain="${3:-"false"}"
+       local IFS ifname radio dev_status config sta_essid sta_bssid result uci_essid uci_bssid login_command wait_time mode="${1}" status="${2:-"false"}" cp_domain="${3:-"false"}"
 
        if [ "${mode}" != "initial" ] && [ "${status}" = "false" ]
        then
                ubus call network reload
                wait_time=$((trm_maxwait/6))
-               sleep ${wait_time}
+               sleep "${wait_time}"
        fi
 
        wait_time=1
@@ -222,13 +232,12 @@ f_check()
                                        trm_ifquality="$(${trm_iwinfo} "${ifname}" info 2>/dev/null | awk -F "[ ]" '/Link Quality:/{split($NF,var0,"/");printf "%i\n",(var0[1]*100/var0[2])}')"
                                        if [ "${mode}" = "initial" ] && [ "${trm_captive}" -eq 1 ]
                                        then
-                                               result="$(${trm_fetch} --timeout=$((trm_maxwait/6)) "${trm_captiveurl}" -O /dev/null 2>&1 | \
-                                                       awk '/^Failed to redirect|^Redirected/{printf "%s" "net cp \047"$NF"\047";exit}/^Download completed/{printf "%s" "net ok";exit}/^Failed|Connection error/{printf "%s" "net nok";exit}')"
+                                               result="$(f_net)"
                                                if [ "${cp_domain}" = "true" ]
                                                then
                                                        cp_domain="$(printf "%s" "${result}" | awk -F "[\\'| ]" '/^net cp/{printf "%s" $4}')"
                                                        uci_essid="$(printf "%s" "${dev_status}" | jsonfilter -l1 -e '@.*.interfaces[@.config.mode="sta"].config.ssid')"
-                                                       uci_essid="$(printf "%s" "${uci_essid//[^[:alnum:]_]/_}" | awk '{print tolower($1)}')"
+                                                       uci_essid="${uci_essid//[^[:alnum:]_]/_}"
                                                        uci_bssid="$(printf "%s" "${dev_status}" | jsonfilter -l1 -e '@.*.interfaces[@.config.mode="sta"].config.bssid')"
                                                        uci_bssid="${uci_bssid//[^[:alnum:]_]/_}"
                                                fi
@@ -242,11 +251,10 @@ f_check()
                                                        then
                                                                while true
                                                                do
-                                                                       result="$(${trm_fetch} --timeout=$((trm_maxwait/6)) "${trm_captiveurl}" -O /dev/null 2>&1 | \
-                                                                               awk '/^Failed to redirect|^Redirected/{printf "%s" "net cp \047"$NF"\047";exit}/^Download completed/{printf "%s" "net ok";exit}/^Failed|Connection error/{printf "%s" "net nok";exit}')"
+                                                                       result="$(f_net)"
                                                                        cp_domain="$(printf "%s" "${result}" | awk -F "[\\'| ]" '/^net cp/{printf "%s" $4}')"
                                                                        uci_essid="$(printf "%s" "${dev_status}" | jsonfilter -l1 -e '@.*.interfaces[@.config.mode="sta"].config.ssid')"
-                                                                       uci_essid="$(printf "%s" "${uci_essid//[^[:alnum:]_]/_}" | awk '{print tolower($1)}')"
+                                                                       uci_essid="${uci_essid//[^[:alnum:]_]/_}"
                                                                        uci_bssid="$(printf "%s" "${dev_status}" | jsonfilter -l1 -e '@.*.interfaces[@.config.mode="sta"].config.bssid')"
                                                                        uci_bssid="${uci_bssid//[^[:alnum:]_]/_}"
                                                                        if [ "${trm_netcheck}" -eq 1 ] && [ "${result}" = "net nok" ]
@@ -255,34 +263,34 @@ f_check()
                                                                                f_jsnup
                                                                                break 2
                                                                        fi
-                                                                       if [ -z "${cp_domain}" ] || [ -n "$(uci_get dhcp "@dnsmasq[0]" rebind_domain | grep -Fo "${cp_domain}")" ]
+                                                                       if [ -z "${cp_domain}" ] || [ -n "$(uci_get "dhcp" "@dnsmasq[0]" "rebind_domain" | grep -Fo "${cp_domain}")" ]
                                                                        then
                                                                                break
                                                                        fi
                                                                        uci -q add_list dhcp.@dnsmasq[0].rebind_domain="${cp_domain}"
                                                                        f_log "info" "captive portal domain '${cp_domain}' added to to dhcp rebind whitelist"
-                                                                       if [ -z "$(uci_get travelmate "${uci_essid}${uci_bssid}")" ]
+                                                                       if [ -z "$(uci_get "travelmate" "${uci_essid}${uci_bssid}")" ]
                                                                        then
                                                                                uci_add travelmate "login" "${uci_essid}${uci_bssid}"
                                                                                uci_set travelmate "${uci_essid}${uci_bssid}" "command" "none"
                                                                                f_log "info" "captive portal login section '${uci_essid}${uci_bssid}' added to travelmate config section"
                                                                        fi
                                                                done
-                                                               if [ -n "$(uci -q changes dhcp)" ]
+                                                               if [ -n "$(uci -q changes "dhcp")" ]
                                                                then
-                                                                       uci_commit dhcp
+                                                                       uci_commit "dhcp"
                                                                        /etc/init.d/dnsmasq reload
                                                                fi
-                                                               if [ -n "$(uci -q changes travelmate)" ]
+                                                               if [ -n "$(uci -q changes "travelmate")" ]
                                                                then
-                                                                       uci_commit travelmate
+                                                                       uci_commit "travelmate"
                                                                fi
                                                        fi
                                                        if [ -n "${cp_domain}" ] && [ "${cp_domain}" != "false" ] && [ -n "${uci_essid}" ] && [ "${trm_captive}" -eq 1 ]
                                                        then
                                                                trm_connection="${result:-"-"}/${trm_ifquality}"
                                                                f_jsnup
-                                                               login_command="$(uci_get travelmate "${uci_essid}${uci_bssid}" command)"
+                                                               login_command="$(uci_get "travelmate" "${uci_essid}${uci_bssid}" "command")"
                                                                if [ -x "${login_command}" ]
                                                                then
                                                                        "${login_command}" >/dev/null 2>&1
@@ -290,8 +298,7 @@ f_check()
                                                                        f_log "info" "captive portal login '${login_command:0:40}' for '${cp_domain}' has been executed with rc '${rc}'"
                                                                        if [ "${rc}" -eq 0 ]
                                                                        then
-                                                                               result="$(${trm_fetch} --timeout=$((trm_maxwait/6)) "${trm_captiveurl}" -O /dev/null 2>&1 | \
-                                                                                       awk '/^Failed to redirect|^Redirected/{printf "%s" "net cp \047"$NF"\047";exit}/^Download completed/{printf "%s" "net ok";exit}/^Failed|Connection error/{printf "%s" "net nok";exit}')"
+                                                                               result="$(f_net)"
                                                                        fi
                                                                fi
                                                        fi
@@ -352,10 +359,10 @@ f_jsnup()
                config="$(printf "%s" "${dev_status}" | jsonfilter -l1 -e '@.*.interfaces[@.config.mode="sta"].section')"
                if [ -n "${config}" ]
                then
-                       sta_iface="$(uci_get wireless "${config}" network)"
-                       sta_radio="$(uci_get wireless "${config}" device)"
-                       sta_essid="$(uci_get wireless "${config}" ssid)"
-                       sta_bssid="$(uci_get wireless "${config}" bssid)"
+                       sta_iface="$(uci_get "wireless" "${config}" "network")"
+                       sta_radio="$(uci_get "wireless" "${config}" "device")"
+                       sta_essid="$(uci_get "wireless" "${config}" "ssid")"
+                       sta_bssid="$(uci_get "wireless" "${config}" "bssid")"
                fi
        fi
 
@@ -436,7 +443,7 @@ f_log()
 #
 f_main()
 {
-       local IFS cnt dev config spec scan_list scan_essid scan_bssid scan_quality faulty_list
+       local IFS cnt dev config spec scan_list scan_essid scan_bssid scan_open scan_quality uci_essid cfg_essid faulty_list
        local station_id sta sta_essid sta_bssid sta_radio sta_iface active_essid active_bssid active_radio
 
        f_check "initial" "false" "true"
@@ -455,7 +462,7 @@ f_main()
                        f_check "dev" "true"
                        f_log "debug" "f_main ::: active_radio: ${active_radio}, active_essid: \"${active_essid}\", active_bssid: ${active_bssid:-"-"}"
                else
-                       uci_commit wireless
+                       uci_commit "wireless"
                        f_check "dev"
                fi
                json_get_var faulty_list "faulty_stations"
@@ -475,9 +482,9 @@ f_main()
                        do
                                config="${sta%%-*}"
                                sta_radio="${sta##*-}"
-                               sta_essid="$(uci_get wireless "${config}" ssid)"
-                               sta_bssid="$(uci_get wireless "${config}" bssid)"
-                               sta_iface="$(uci_get wireless "${config}" network)"
+                               sta_essid="$(uci_get "wireless" "${config}" "ssid")"
+                               sta_bssid="$(uci_get "wireless" "${config}" "bssid")"
+                               sta_iface="$(uci_get "wireless" "${config}" "network")"
                                json_get_var faulty_list "faulty_stations"
                                if [ -n "$(printf "%s" "${faulty_list}" | grep -Fo "${sta_radio}/${sta_essid}/${sta_bssid}")" ]
                                then
@@ -493,8 +500,8 @@ f_main()
                                if [ -z "${scan_list}" ]
                                then
                                        scan_list="$("${trm_iwinfo}" "${dev}" scan 2>/dev/null | \
-                                               awk 'BEGIN{FS="[ ]"}/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,"/");printf "%i,%s,%s\n",(var0[1]*100/var0[2]),var1,var2}' | \
+                                               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 ::: scan_buffer: ${trm_scanbuffer}, scan_list: ${scan_list}"
                                        if [ -z "${scan_list}" ]
@@ -517,36 +524,40 @@ f_main()
                                        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}" ]
+                                       if [ -n "${scan_quality}" ] && [ -n "${scan_bssid}" ] && [ -n "${scan_essid}" ] && [ -n "${scan_open}" ]
                                        then
                                                if [ "${scan_quality}" -ge "${trm_minquality}" ]
                                                then
                                                        if { { [ "${scan_essid}" = "\"${sta_essid//,/.}\"" ] && { [ -z "${sta_bssid}" ] || [ "${scan_bssid}" = "${sta_bssid}" ]; } } || \
                                                                { [ "${scan_bssid}" = "${sta_bssid}" ] && [ "${scan_essid}" = "unknown" ]; } } && [ "${dev}" = "${sta_radio}" ]
                                                        then
-                                                               f_log "debug" "f_main ::: scan_quality: ${scan_quality}, scan_essid: ${scan_essid}, scan_bssid: ${scan_bssid:-"-"}"
+                                                               f_log "debug" "f_main ::: scan_quality: ${scan_quality}, scan_essid: ${scan_essid}, scan_bssid: ${scan_bssid:-"-"}, scan_open: ${scan_open}"
                                                                if [ "${dev}" = "${active_radio}" ]
                                                                then
+                                                                       uci_set "wireless" "${trm_active_sta}" "disabled" "1"
+                                                                       uci_commit "wireless"
+                                                                       f_log "debug" "f_main ::: active uplink connection '${active_radio}/${active_essid}/${active_bssid:-"-"}' terminated"
                                                                        unset trm_connection active_radio active_essid active_bssid
-                                                                       uci_set wireless "${trm_active_sta}" disabled 1
-                                                                       uci_commit wireless
                                                                fi
                                                                # retry loop
                                                                #
                                                                cnt=1
                                                                while [ "${cnt}" -le "${trm_maxretry}" ]
                                                                do
-                                                                       uci_set wireless "${config}" disabled 0
+                                                                       uci_set "wireless" "${config}" "disabled" "0"
                                                                        f_check "sta"
                                                                        if [ "${trm_ifstatus}" = "true" ]
                                                                        then
                                                                                unset IFS scan_list
-                                                                               uci_commit wireless
+                                                                               uci_commit "wireless"
                                                                                f_log "info" "connected to uplink '${sta_radio}/${sta_essid}/${sta_bssid:-"-"}' (${cnt}/${trm_maxretry}, ${trm_sysver})"
                                                                                return 0
                                                                        else
-                                                                               uci -q revert wireless
+                                                                               uci -q revert "wireless"
                                                                                f_check "rev"
                                                                                if [ "${cnt}" -eq "${trm_maxretry}" ]
                                                                                then
@@ -562,17 +573,33 @@ f_main()
                                                                        cnt=$((cnt+1))
                                                                        sleep $((trm_maxwait/6))
                                                                done
-                                                       else
-                                                               unset scan_quality scan_bssid scan_essid
-                                                               continue
+                                                       elif [ "${trm_autoadd}" -eq 1 ] && [ "${scan_open}" = "+" ] && [ "${scan_essid}" != "unknown" ]
+                                                       then
+                                                               cfg_essid="${scan_essid#*\"}"
+                                                               cfg_essid="${cfg_essid%\"*}"
+                                                               uci_essid="${cfg_essid//[^[:alnum:]_]/_}"
+                                                               if [ -z "$(uci_get "wireless" "trm_${uci_essid}")" ]
+                                                               then
+                                                                       uci_add "wireless" "wifi-iface" "trm_${uci_essid}"
+                                                                       uci_set "wireless" "trm_${uci_essid}" "mode" "sta"
+                                                                       uci_set "wireless" "trm_${uci_essid}" "network" "${trm_iface}"
+                                                                       uci_set "wireless" "trm_${uci_essid}" "device" "${sta_radio}"
+                                                                       uci_set "wireless" "trm_${uci_essid}" "ssid" "${cfg_essid}"
+                                                                       uci_set "wireless" "trm_${uci_essid}" "encryption" "none"
+                                                                       uci_set "wireless" "trm_${uci_essid}" "disabled" "1"
+                                                                       uci_commit "wireless"
+                                                                       f_log "info" "open uplink '${sta_radio}/${cfg_essid}' added to wireless config"
+                                                               fi
                                                        fi
+                                                       unset scan_quality scan_bssid scan_essid scan_open
+                                                       continue
                                                else
-                                                       unset scan_quality scan_bssid scan_essid
+                                                       unset scan_quality scan_bssid scan_essid scan_open
                                                        continue
                                                fi
                                        fi
                                done
-                               unset IFS scan_quality scan_bssid scan_essid
+                               unset IFS scan_quality scan_bssid scan_essid scan_open
                        done
                        unset scan_list
                done