Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/bin/sh
- # Initial release: 2015 shibby
- # changes/fixes: 2018-2021 - pedro
- # v1.023 revised: 2022 - rs232
- PID=$$
- PIDFILE="/var/run/watchdog.pid"
- IPLISTFILE="/tmp/watchdog.iplist"
- MWAN=$(nvram get mwan_num)
- IPLIST=""
- MWANTABLE="wan"
- white="\033[1;37m"
- black="\033[0;40m"
- green="\e[30m\033[42m"
- red="\e[0;30m\033[41m"
- now=$(date +%s)
- echo -e "${white}
- ──────────── FreshTomato WatchDog ────────────${black}
- ${white}── Current default gateway/s ───────────────────${black}
- $(ip r | grep default)
- ${white}── Probing ─────────────────────────────────────${black}"
- i=1
- while [ $i -le $MWAN ]; do
- [ "$i" -gt 1 ] && MWANTABLE="$MWANTABLE wan$i"
- i=$((i+1))
- done
- LOGS="logger -t watchdog[$PID]"
- [ "$(nvram get mwan_debug)" -gt 0 ] && DEBUG="logger -p DEBUG -t watchdog[$PID] *** " || DEBUG="echo -e"
- timeout() {
- local cmd_pid sleep_pid retval
- (shift; "$@") &
- cmd_pid=$!
- (sleep "$1"; kill "$cmd_pid" 2>/dev/null) &
- sleep_pid=$!
- wait "$cmd_pid"
- retval=$?
- kill "$sleep_pid" 2>/dev/null
- return "$retval"
- }
- findHost() {
- local host ip
- local dst=$(nvram get mwan_ckdst)
- local hostlist=$(echo $dst | sed 's/,/ /')
- for host in $hostlist; do
- echo $host | grep -Eo '((([a-zA-Z]{1,2})|([0-9]{1,2})|([a-zA-Z0-9]{1,2})|([a-zA-Z0-9][a-zA-Z0-9-]{1,61}[a-zA-Z0-9]))\.)+[a-zA-Z]{2,6}' && {
- ip=$(nslookup $host 127.0.0.1 2>/dev/null | tail +5 | grep -v :: | awk '{print $3} | tail -1')
- IPLIST="${IPLIST} $ip"
- } || IPLIST="${IPLIST} $host"
- done
- echo "$IPLIST" > $IPLISTFILE # because we're in subshell
- }
- dhcpFix() {
- dhcpc-release $PREFIX
- sleep 1
- dhcpc-renew $PREFIX
- }
- ipCheck() {
- [ "$PROTO" == "dhcp" -a $(ifconfig $IFACE | grep inet | grep -Eo '((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)' | wc -l ) -eq 0 ] && { dhcpFix $PREFIX; sleep 3; }
- [ $(ifconfig $IFACE | grep inet | grep -Eo '((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)' | wc -l ) -eq 0 ] && {
- $DEBUG "$PREFIX doesn't have an IP address. Skipping..."
- echo "2" >> $STATE_FILE
- echo "$now 2" >> $STATE_FILE_LOG
- continue;
- }
- }
- resultsOut() {
- for PREFIX in $MWANTABLE; do
- STATE_FILE_LOG="/var/lib/misc/"$PREFIX"_state_log"
- echo -e "───── ${red}$PREFIX ─ Last 10 results${black} (since boot) ─────"
- cat $STATE_FILE_LOG | tail -10 | awk '{print strftime("%c",$0)}{print $2}'
- echo ""
- done
- exit
- }
- resultsOutDown() {
- for PREFIX in $MWANTABLE; do
- STATE_FILE_LOG="/var/lib/misc/"$PREFIX"_state_log"
- echo -e "───── ${red}$PREFIX ─ Last 10 failures${black} (since boot) ─────"
- cat $STATE_FILE_LOG | grep -E '\ 0$' | tail -10 | awk '{print strftime("%c",$0)}{print $2}'
- echo ""
- done
- exit
- }
- # loadBalancing=0
- # for PREFIX in $MWANTABLE; do
- # WEIGHT=$(nvram get "$PREFIX"_weight)
- # [ $WEIGHT -eq 0 ] && continue || loadBalancing="$((loadBalancing+1))"
- # done
- # [ $loadBalancing -ge 2 ] && {
- # routing="ip route add default scope global "
- # for PREFIX in $MWANTABLE; do
- # # GW=$(nvram get "$PREFIX"_gateway)
- # IFACE=$(nvram get "$PREFIX"_iface)
- # WEIGHT=$(nvram get "$PREFIX"_weight)
- # routing="${routing} nexthop dev $IFACE weight $WEIGHT "
- # done
- # }
- watchdogRun() {
- for PREFIX in $MWANTABLE; do
- IFACE=$(nvram get "$PREFIX"_iface) #eth1, vlan2, etc
- ISPPPD=$([ -f /tmp/ppp/pppd$PREFIX ] && echo 1 || echo 0)
- WEIGHT=$(nvram get "$PREFIX"_weight)
- METHOD=$(nvram get "$PREFIX"_ckmtd)
- PROTO=$(nvram get "$PREFIX"_proto)
- DEMAND=$(nvram get "$PREFIX"_ppp_demand)
- RESULT=0
- # PREFIX_MWAN=$PREFIX #wan, wan2, etc
- STATE_FILE="/var/lib/misc/"$PREFIX"_state"
- STATE_FILE_LOG="/var/lib/misc/"$PREFIX"_state_log"
- [ "$(nvram get "$PREFIX"_ck_pause)" -eq 1 ] && {
- $DEBUG "${white}Watchdog paused for $PREFIX - skipping ...${black}"
- continue
- }
- cp $STATE_FILE "$STATE_FILE"_pre 2>/dev/null
- [ "$PROTO" != "disabled" ] && {
- [ "$(nvram get mwan_debug)" -gt 0 ] && {
- ISUP=$(wanuptime "$PREFIX")
- ISGW=$(ip route | grep $IFACE | grep -v "link" | wc -l)
- $DEBUG "prefix=$PREFIX, iface=$IFACE, uptime=$ISUP, ISGW=$ISGW, WEIGHT=$WEIGHT"
- }
- sed -i -e :a -e '$q;N;1000,$D;ba' $STATE_FILE_LOG
- ipCheck
- DEFAULT_ROUTE_FRAGMENT=$(ip route | grep default | cut -d' ' -f2-)
- GATEWAY="$(nvram get "$PREFIX"_gateway)"
- [ "$ISPPPD" -eq 1 ] && GATEWAY_FRAGMENT=""
- $DEBUG "${white}>─ Testing $(printf "%4s%-s\n" $PREFIX) ─ Weight: $(printf "%2s%-s\n" $WEIGHT) ──────────────────<${black}"
- [ -s $STATE_FILE_LOG ] && echo -e "Previous test results > $(tail -23 $STATE_FILE_LOG | awk '{print $2}' | tr -d "\n" | awk '{ for (i=NF; i>1; i--) printf("%s ",$i); print $1; }')"
- # [ -z "$DEFAULT_ROUTE_FRAGMENT" ] && { #default gateway missing...??? I'll add it manually.
- # echo "shit"
- # for PREFIX in $MWANTABLE; do
- # [ $(nvram get "$PREFIX"_weight) -ge 1 ] && {
- # ip route add default via $GATEWAY dev $IFACE
- # # echo "ip route add default dev $IFACE"
- # break
- # }
- # done
- # }
- for IP in $IPLIST; do
- # ipCheck
- [ ! -z "$DEFAULT_ROUTE_FRAGMENT" ] && {
- ROUTE_EXEC="ip route add $IP/32 via $GATEWAY dev $IFACE"
- # $DEBUG "a. Injecting: $ROUTE_EXEC"
- $ROUTE_EXEC 2>/dev/null
- }
- ROUTE_EXEC="ip route add $IP dev $IFACE $GATEWAY_FRAGMENT metric 50000"
- # $DEBUG "a. Injecting: $ROUTE_EXEC"
- $ROUTE_EXEC 2>/dev/null
- done
- if [ "$METHOD" -eq 1 ]; then
- ckping
- elif [ "$METHOD" -eq 2 ]; then
- cktracert
- else
- ckcurl
- fi
- for IP in $IPLIST; do
- [ ! -z "$DEFAULT_ROUTE_FRAGMENT" ] && {
- ROUTE_EXEC="ip route del $IP/32 via $GATEWAY dev $IFACE"
- # $DEBUG "c. Removing: $ROUTE_EXEC"
- $ROUTE_EXEC 2>/dev/null
- }
- ROUTE_EXEC="ip route del $IP dev $IFACE $GATEWAY_FRAGMENT metric 50000"
- # $DEBUG "c. Removing: $ROUTE_EXEC"
- $ROUTE_EXEC 2>/dev/null
- done
- # wan is down
- [ "$RESULT" -eq 0 ] && {
- $DEBUG "${red}>>> Connection $PREFIX is down! <<<${black}
- "
- [ "$PROTO" == "lte" ] && {
- $LOGS "Connection $PREFIX DOWN - Reconnecting ..."
- echo "0" > $STATE_FILE
- echo "$now 0" >> $STATE_FILE_LOG
- switch4g $PREFIX
- } || {
- [ "$PREFIX" == "wan" -a "$MWAN" -gt 1 ] && PREFIX_MWAN="wan1" # "wan" means restart all WANs, but we only want restart one
- [ "$(nvram get action_service)" == "wan-restart" -o "$(nvram get action_service)" == $PREFIX"-restart" -o "$(nvram get action_service)" == "wan-restart-c" -o "$(nvram get action_service)" == $PREFIX"-restart-c" ] && {
- $LOGS "Connection $PREFIX DOWN - Reconnect is already in progress ..."
- } || {
- echo "0" > $STATE_FILE
- echo "$now 0" >> $STATE_FILE_LOG
- if [ "$PROTO" == "pppoe" -o "$PROTO" == "pptp" -o "$PROTO" == "l2tp" -o "$PROTO" == "ppp3g" ] && [ "$DEMAND" -eq 1 -a "$ISPPPD" -eq 0 ]; then
- $LOGS "Killing orphaned connect-on-demand listen process ..."
- LISTEN_PID=$(ps | grep listen | grep $PREFIX | awk '{print $1}' | head -n1)
- [ -n $LISTEN_PID ] && {
- kill -9 $LISTEN_PID
- $LOGS "Killed $LISTEN_PID"
- } || {
- $LOGS "Connect-on-demand listen not running"
- }
- $LOGS "Connection $PREFIX DOWN - Reconnecting ..."
- service $PREFIX restart
- else
- $LOGS "Connection $PREFIX DOWN - Reconnect will be handled by another process ..."
- fi
- }
- }
- } || {
- [ "$PROTO" == "dhcp" -a "$(cat $STATE_FILE)" -eq 0 ] && { # connected + DHCP + previous status - disconnected? release/renew
- dhcpFix
- }
- $DEBUG "${green}<<< Connection $PREFIX is up! >>>${black}
- "
- echo "1" > $STATE_FILE
- echo "$now 1" >> $STATE_FILE_LOG
- }
- }
- done
- }
- cktracert() {
- local RXBYTES1=$(cat /sys/class/net/$IFACE/statistics/rx_bytes)
- local RXBYTES2 IP
- # $DEBUG "a. ${white}traceroute${black} test for $PREFIX ($IFACE):."
- $DEBUG "a.traceroute -i $IFACE -n -w 1 -m 5 -q 1 -z $IP"
- for IP in $IPLIST; do
- # we need only send/receive few packages to be sure is connection works.
- traceroute -i $IFACE -n -w 1 -m 4 -q 1 -z 1 $IP > /dev/null 2>&1
- usleep 200
- done
- RXBYTES2=$(cat /sys/class/net/$IFACE/statistics/rx_bytes)
- [ "$RXBYTES2" -gt "$RXBYTES1" ] && RESULT=1
- $DEBUG "b. $traceroute for $IFACE: RX2=$RXBYTES2 RX1=$RXBYTES1"
- [ "$RESULT" -gt 0 ] && $DEBUG "c. Test result: ${white}PASSED${black}" || $DEBUG "c. Test result: ${white}!! FAILED !!${black}"
- }
- ckping() {
- local IP CHECK
- $DEBUG "a. ${white}ping${black} test for $PREFIX ($IFACE):"
- i=0
- for IP in $IPLIST; do
- #$DEBUG " b. ping -c 2 -A -w 4 -q -I $IFACE $IP"
- # "0" means 100% loss - not receive any package
- i=$((i+1))
- ping -c $((i+1)) -A -W $((i+2)) -q -I $IFACE $IP >/dev/null && RESULT=$((RESULT+1))
- $DEBUG "b${i}. ping -c $((i+1)) -A -W $((i+2)) -q -I $IFACE $IP == $RESULT"
- [ "$RESULT" -gt 0 ] && break;
- sleep $i
- done
- [ "$RESULT" -gt 0 ] && $DEBUG "c. Test result: ${white}PASSED${black}" || $DEBUG "c. Test result: ${white}!! FAILED !!${black}"
- }
- ckcurl() {
- local IP CHECK
- $DEBUG "a. ${white}curl${black} test for $PREFIX ($IFACE):"
- i=0
- for IP in $IPLIST; do
- # $DEBUG " b. curl $IP --interface $IFACE --connect-timeout 5 -ksfI"
- i=$((i+1))
- curl $IP --interface $IFACE --connect-timeout $((i+3)) -ksfI -o /dev/null && RESULT=$((RESULT+1))
- $DEBUG "b.${i} curl $IP --interface $IFACE --connect-timeout $((i+3)) -ksfI == $RESULT"
- [ $RESULT -gt 0 ] && break
- sleep $i
- done
- [ "$RESULT" -gt 0 ] && $DEBUG "c. Test result: ${white}PASSED${black}" || $DEBUG "c. Test result: ${white}!! FAILED !!${black}"
- }
- watchdogAdd() {
- local CKTIME=$(nvram get mwan_cktime)
- local MINS=$((CKTIME/60))
- [ "$MINS" -gt 0 ] && {
- cru l | grep watchdogJob >/dev/null && cru a watchdogJob "*/$MINS * * * * /usr/sbin/watchdog"
- }
- }
- watchdogDel() {
- cru l | grep watchdogJob >/dev/null && cru d watchdogJob
- }
- mwanJob() {
- cru l | grep mwanJob >/dev/null && cru d mwanJob || cru a mwanJob "*/1 * * * * /usr/sbin/watchdog alive"
- }
- mwanAlive() {
- [ "$MWAN" -gt 1 ] && {
- ps | grep [m]wanroute >/dev/null && $DEBUG "mwanroute is running" || {
- $LOGS "mwanroute not found, launch process"
- mwanroute
- }
- }
- }
- checkPid() {
- local PIDNO
- [ -f $PIDFILE ] && {
- PIDNO=$(cat $PIDFILE)
- cat "/proc/$PIDNO/cmdline" > /dev/null 2>&1
- [ $? -eq 0 ] && {
- $LOGS "Another process in action - Exiting ..."
- exit 0
- } || {
- # Process not found assume not running
- echo $PID > $PIDFILE
- [ $? -ne 0 ] && {
- $LOGS "Could not create PID file"
- exit 0
- }
- }
- } || {
- echo $PID > $PIDFILE
- [ $? -ne 0 ] && {
- $LOGS "Could not create PID file"
- exit 0
- }
- }
- }
- checkPidSwitch() {
- local SPREFIX
- for SPREFIX in $MWANTABLE; do
- [ -f /var/run/switch3g_$SPREFIX.pid ] && {
- ps | grep [s]witch3g && {
- $LOGS "Switch3g ($SPREFIX) script in action - Exiting ..."
- rm -f $PIDFILE > /dev/null 2>&1
- exit 0
- } || {
- # pid file exists but process doesn't
- rm /var/run/switch3g_$SPREFIX.pid
- }
- }
- [ -f /var/run/switch4g_$SPREFIX.pid ] && {
- ps | grep [s]witch4g && {
- $LOGS "Switch4g ($SPREFIX) script in action - Exiting ..."
- rm -f $PIDFILE > /dev/null 2>&1
- exit 0
- } || {
- # pid file exists but process doesn't
- rm /var/run/switch4g_$SPREFIX.pid
- }
- }
- done
- }
- helpOut() {
- echo -e " List of supported parameters:
- ${white}help${black} = this screen
- ${white}status${black} = Last 10 recorded resultson each wan
- ${white}status-down${black} = Last 10 failures on each wan
- ${white}────────────────────────────────────────────────${black}
- "
- exit
- }
- ###################################################
- if [ "$1" == "add" ]; then
- watchdogAdd
- mwanJob
- elif [ "$1" == "del" ]; then
- watchdogDel
- elif [ "$1" == "alive" ]; then
- mwanAlive
- elif [ "$1" == "test" ]; then
- watchdogRun
- elif [ "$1" == "status" ]; then
- resultsOut
- elif [ "$1" == "status-down" ]; then
- resultsOutDown
- elif [ "$1" == "help" ]; then
- helpOut
- else
- checkPid
- checkPidSwitch
- mwanJob
- # run with a 10 sec timeout to not hang
- timeout 10 findHost
- [ -f $IPLISTFILE ] && IPLIST=$(cat $IPLISTFILE)
- [ -z "$IPLIST" ] && IPLIST="192.0.43.10 4.2.2.4 139.130.4.5 198.153.194.2" # resilient IP if the list is empty
- for IP in $IPLIST; do
- for dns in $(nvram show 2>/dev/null | grep -E ^wan.?_dns= | cut -f2 -d= | tr "\n" " " | grep -Ev ^$); do
- [ $dns == $IP ] && BADIPLIST="${BADIPLIST} $IP"
- done
- done
- [[ ! -v ${BADIPLIST} ]] && {
- IIPLIST=$(echo $IPLIST | tr " " "\n" | for i in $BADIPLIST; do grep -v $i; done | tr "\n" " " | tr -s ' ')
- IPLIST=$IIPLIST
- }
- echo " TEST IPs =$IPLIST
- "
- watchdogRun
- [ -f $IPLISTFILE ] && rm $IPLISTFILE
- fi
- echo -e "${white}────────────────────────────────────────────────${black}"
- # Recivery (if needed#
- for PREFIX in $MWANTABLE; do
- STATE_FILE="/var/lib/misc/"$PREFIX"_state"
- [ $(cat "$STATE_FILE" 2>/dev/null) != $(cat "$STATE_FILE"_pre 2>/dev/null) ] && MODIFIED=$((MODIFIED+1));
- done
- [ ! -z ${MODIFIED} ] && {
- [ $(nvram get tinc_wanup) -eq 1 ] && {
- echo -e "${white} != Change of status detected! !=${black} Performing recovery actions..."
- sleep 10
- ( ps w | grep -E [t]inc && service tinc restart ; ) >/dev/null 2>&1
- ( ps w | grep -E [v]pn | awk '{print $5}' | cut -d/ -f4 | while read line; do service $line restart; done; ) > /dev/null 2>&1
- }
- } || echo -e " ${white}== No changes ==${black} Same status as last run...";
- echo -e "${white}────────────────────────────────────────────────${black}
- "
- rm /var/lib/misc/*_pre > /dev/null 2>&1
- rm -f $PIDFILE > /dev/null 2>&1
Add Comment
Please, Sign In to add comment