#!/bin/sh # # Shorewall WAN Interface monitor - V4.2 # # Inspired by Angsuman Chakraborty's gwping script. # # This program is under GPL [http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt] # # (c) 2009 - Tom Eastep (teastep@shorewall.net) # # This program is free software; you can redistribute it and/or modify # it under the terms of Version 2 of the GNU General Public License # as published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # # For information about this script, see http://www.shorewall.net/MultiISP.html#swping. # ########################################################################################### # # IP Family == 4 or 6 # FAMILY=4 # # The command to run when the status of a line changes. Can include multiple commands # separated by semicolons (";"). # COMMAND= if [ $FAMILY -eq 4 ]; then if [ -f /usr/share/shorewall-lite/lib.base ]; then . /usr/share/shorewall-lite/lib.base [ -f /etc/shorewall-lite/params ] && . /etc/shorewall-lite/params [ -n "${COMMAND:="/sbin/shorewall-lite restart; /sbin/ip -4 route ls"}" ] STATEDIR=/etc/shorewall-lite elif [ -f /usr/share/shorewall/lib.base ]; then . /usr/share/shorewall/lib.base [ -f /etc/shorewall/params ] && . /etc/shorewall/params [ -n "${COMMAND:="/sbin/shorewall restart -f; /sbin/ip -4 route ls"}" ] STATEDIR=/etc/shorewall fi else if [ -f /usr/share/shorewall6-lite/lib.base ]; then . /usr/share/shorewall6-lite/lib.base [ -f /etc/shorewall6-lite/params ] && . /etc/shorewall6-lite/params [ -n "${COMMAND:="/sbin/shorewall6-lite restart; /sbin/ip -4 route ls"}" ] STATEDIR=/etc/shorewall6-lite elif [ -f /usr/share/shorewall6/lib.base ]; then . /usr/share/shorewal6l/lib.base [ -f /etc/shorewall6/params ] && . /etc/shorewall6/params [ -n "${COMMAND:="/sbin/shorewall6 restart -f; /sbin/ip -4 route ls"}" ] STATEDIR=/etc/shorewall6 fi fi # # Interfaces to monitor -- you may use shell variables from your params file # IF1=eth0 IF2=eth1 # # Sites to Ping. Must depend only on routes in the 'main' routing table. If not specified, # the interface is assumed to be managed by dhcpcd and the script uses the gateway address # from /var/lib/dhcpcd/dhcpcd-${IFx}.info # TARGET1=xxx.xxx.xxx.xxx TARGET2=yyy.yyy.yyy.yyy # # How often to ping # PING_INTERVAL=5 # # Value for ping's -W option # PING_TIMEOUT=2 # # This many successive pings must succeed for the interface to be marked up when it is down # UP_COUNT=5 # # This many successive pings must fail for the interface to be marked down when it is up # DOWN_COUNT=2 ################################################################################################# # Variables private to the script ################################################################################################# up=0 down=1 if1_state=$up if2_state=$up last_if1_ping=$up last_if2_ping=$up state_changed= current_if1_ping= current_if2_ping= count1=0 count2=0 [ $FAMILY -eq 4 ] && ping=ping || ping=ping6 ################################################################################################# # Determine the GATEWAY of a DHCP interface ################################################################################################# get_target() { local GATEWAYS GATEWAYS= if [ -f /var/lib/dhcpcd/dhcpcd-${1}.info ]; then eval $(grep ^GATEWAYS= /var/lib/dhcpcd/dhcpcd-${1}.info 2> /dev/null) [ -n "$GATEWAYS" ] && GATEWAYS=${GATEWAYS%,*} && echo $GATEWAYS fi } # # Script starts here # rm -f $STATEDIR/${IF1}.status rm -f $STATEDIR/${IF2}.status while : ; do target=$TARGET1 [ -n "$target" ] || target=$(get_target $IF1) if [ -n "$target" ]; then $ping -n -W $PING_TIMEOUT -I $IF1 -c 1 $target > /dev/null 2>&1 && current_if1_ping=0 || current_if1_ping=1 else current_if1_ping=1 fi if [ $current_if1_ping -ne $last_if1_ping ]; then last_if1_ping=$current_if1_ping count1=1 elif [ $current_if1_ping -ne $if1_state ]; then count1=$(($count1 + 1 )) fi case $if1_state in 0) # # Interface is currently up # if [ $count1 -ge $DOWN_COUNT ]; then state_changed=Yes count1=0 echo "$IF1 is Down!" if1_state=1 fi ;; 1) # # Interface is currently down # if [ $count1 -ge $UP_COUNT ]; then state_changed=Yes count1=0 echo "$IF1 is Up!" if1_state=0 fi ;; esac target=$TARGET2 [ -n "$target" ] || target=$(get_target $IF2) if [ -n "$target" ]; then $ping -n -W $PING_TIMEOUT -I $IF2 -c 1 $target > /dev/null 2>&1 && current_if2_ping=0 || current_if2_ping=1 else current_if2_ping=1 fi if [ $current_if2_ping -ne $last_if2_ping ]; then last_if2_ping=$current_if2_ping count2=1 elif [ $current_if2_ping -ne $if2_state ]; then count2=$(($count2 + 1 )) fi case $if2_state in 0) # # Interface is currently up # if [ $count2 -ge $DOWN_COUNT ]; then state_changed=Yes count2=0 echo "$IF2 is Down!" if2_state=1 fi ;; 1) # # Interface is currently down # if [ $count2 -ge $UP_COUNT ]; then state_changed=Yes count2=0 echo "$IF2 is Up!" if2_state=0 fi ;; esac if [ -n "$state_changed" ]; then # # One of the interfaces changed state -- restart Shorewall # echo $if1_state > $STATEDIR/${IF1}.status echo $if2_state > $STATEDIR/${IF2}.status eval $COMMAND state_changed= fi sleep $PING_INTERVAL done