#!/bin/bash

#ADSL modem watchdog script. (Originally run from cron every 10 minutes; now just use Cron as the "watchdog's watchdog, and loop).
#If it can't ping 8.8.8.8, it reboots the modem. Note that router takes at least 3 minutes to come back up!
#Crontab:  01 * * * * /home/rjn/bin/adsl_watchdog.sh

#Pingable server. 8.8.8.8 is google's public DNS. Use 8.8.8.9 for faking a failure.
#The second site is another example; as even google's system has been known to stop responding at times.
PING_ME=8.8.8.8
PING_ME2=ping.eu

#Router IP address (accessible by telnet), user/password:
ROUTER_IP=10.0.0.1
ROUTER_USER=Administrator
ROUTER_PASSWD=YOUR_PASSWORD_GOES_HERE

#Router command. Run "reboot" to reboot, or "sysinfo" for harmless test.
ROUTER_CMD=reboot

#How often to check by pinging?
INTERVAL=60

#How long to wait for router to come back (at least 3 mins required, allow longer for admin to get in remotely).
DELAY=600

#Mail to this user.
MAILTO=rjn

#Usage
if [ $# -ne 0 ];then
	echo "This is the ADSL modem monitoring script"
	echo "It pings $PING_ME every $INTERVAL seconds; if this is inaccessible, it telnets into the router"
	echo "at $ROUTER_IP and runs the command: $ROUTER_CMD"
	echo "This script loops indefinitely, and emails $MAILTO whenever it takes action."
	echo "Only one instance runs at a time; a second will exit immediately"
	echo "Usage: $0  (no arguments)"
	exit 1
fi


#Are we already running? Exit 0 and silently, else cron will email. Lock.
SCRIPT=$(basename $0)
PIDFILE=/tmp/$SCRIPT.pid
if [ -f $PIDFILE ] ;then
	if ps -p $(cat $PIDFILE) -f | grep -q $SCRIPT; then	#Does a previous PIDfile exist, containing the right process / name ?
		#echo "Already running"		#silent, 0.
		exit 0
	fi
fi
echo $$ > $PIDFILE || echo "Error writing to PIDFILE $PIDFILE"	#Create (or overwrite) PIDFILE


echo "Starting ADSL monitoring (every $INTERVAL seconds)" | mail -s "ADSL Watchdog Starting" $MAILTO

#Loop indefinitely
while : ; do

	#Are we online?  8.8.8.8 is google's public DNS. Use 8.8.8.9 for testing failures. Try again a few seconds later, just in case.
	if fping -q $PING_ME ||  { sleep 10; fping -q $PING_ME ;}  || { sleep 10; fping -q $PING_ME2 ;} ;then
		sleep $INTERVAL
	else
		echo "Error: ADSL monitoring: cannot ping $PING_ME, assume router ($ROUTER_IP) is offline. Rebooting it." | mail -s "ADSL Watchdog Error" $MAILTO

		#Try to ping the router.
		if ! fping -q $ROUTER_IP ; then
			echo "Error: couldn't even ping the router $ROUTER_IP; giving up for now."
			sleep $INTERVAL
			continue;
		fi

		#Restart the router. Note the timings. Allow plenty of space. Don't logout for at least 20 seconds, else the reboot command gets kiled mid-way!
		{ echo "$ROUTER_USER"; sleep 1; echo "$ROUTER_PASSWD"; sleep 1;  echo "$ROUTER_CMD"; sleep 20; echo "logout" ; }| telnet $ROUTER_IP

		sleep $DELAY
	fi

done


[ -f $PIDFILE ] && rm $PIDFILE	#clean up (not that we ever get here)
