On Thursday 09 March 2006 12:40, Carlo Sogono wrote:
> Since our priorities are only internal web access and incoming/outgoing
> mails I have thought of periodically checking of the immediate gateways
> of both ISPs are online. If the primary gateway is down then run a
> script that changes the default route. As much as possible I would like
> to avoid using a routing protocol as these links are not that fast and
> the ISP supplied routers we have are not Cisco-enterprise-level. I do
> not know of such an app that checks if the immediate gateway is online
> then runs scripts if they are down...

What about something like this (totally untested)!!:

---- testnet.sh ----
#!/bin/bash

# Author - James Gray (do I REALLY want my name on this?)

# Genesis - Today...I think.  What IS the date today anyway?!
#           9-Mar-2006

# Purpose - Handle multi-homed gateways routing tables in a 
#           semi-intelligent manner in the case of a link
#           failing.  It handles the reverse too, when the
#           link comes back up.

# Define Gateway IP's
# ..or roll your own to rip it out of the routing table etc.
ISPGW1=1.2.3.4
ISPGW2=2.3.4.5

# Generate the info to find the state (last run status) files.
STATE_PATH=/path/to/them    # note no trailing "/"
STATE_FILES="ISP1.state ISP2.state ISPALL.state"

# Set all states to "safe" defaults
STATE1=up
STATE2=up
STATE_ALL=up

# Read in the state files - ie status of links on last run!
for FILE in $STATE_FILES
do
        [ -f $STATE_PATH/$FILE ] && . $STATE_PATH/$FILE
done

# Function to ping an IP/Host
testnet(){
        ping -c 1 $1 &>/dev/null
        echo $?
}

# What to do if ISP1 is down
ispgw1_actions(){
        if [ "$1" == "down" ]; then
                # Dump everything in here you want to do
                # if ISP1's Gateway is down, but leave these lines!
                STATE1=down
                echo "STATE1=down" > $STATE_PATH/ISP1.state
        else
                # Dump everything in here you want to do
                # when ISP1's Gateway is back up, but leave these lines!
                STATE1=up
                echo "STATE1=up" > $STATE_PATH/ISP1.state
        fi
}

# What to do if ISP2 is down
ispgw2_actions(){
        if [ "$1" == "down" ]; then
                # Dump everything in here you want to do
                # if ISP1's Gateway is down, but leave these lines!
                STATE2=down
                echo "STATE1=down" > $STATE_PATH/ISP2.state
        else
                # Dump everything in here you want to do
                # when ISP1's Gateway is back up, but leave these lines!
                STATE2=up
                echo "STATE1=up" > $STATE_PATH/ISP2.state
        fi
}

# What to to if they are BOTH down
all_actions(){
        if [ "$1" == "down" ]; then
                # Dump everything in here you want to do
                # if ISP1's Gateway is down, but leave these lines!
                STATE_ALL=down
                echo "STATE_ALL=down" > $STATE_PATH/ISPALL.state
        else
                # Dump everything in here you want to do
                # when ISP1's Gateway is back up, but leave these lines!
                STATE_ALL=down
                echo "STATE_ALL=down" > $STATE_PATH/ISPALL.state
        fi
}

#
# Check ISP1's Gateway
#
if [[ `testnet $ISPGW1` -ne 0 ]]; then
        # Hrm ISP1 gateway isn't responding...see if ISP2 is up
        if [[ `testnet $ISPGW2` -ne 0 ]]; then
                # Both ISP's down - do something useful!
                [ "$STATE_ALL" != down ] && all_actions down
        else
                # ISP1 is down - do something with routes etc.
                [ "$STATE1" != "down" ] && isp1gw_actions down
        fi
else
        #ISP1 is up - see if it was down on the last run
        [ "$STATE1" == "down" ] && ispgw1gw
fi

#
# Check ISP2's Gateway
#
if [[ `testnet $ISPGW2` -ne 0 ]]; then
        # Hrm ISP2 gateway isn't responding...see if ISP1 is up
        if [[ `testnet $ISPGW1` -ne 0 ]]; then
                # Both ISP's down - do something useful!
                [ "$STATE_ALL" != "down" ] && alldown_actions down
        else
                # ISP2 is down - do something with routes etc.
                [ "$STATE2" != "down" ] && isp2gw_actions down
        fi
else
        #ISP2 is up - see if it was down on the last run
        [ "$STATE1" == "down" ] && ispgw1gw
fi

exit 0
---- testnet.sh ----

Then make it executeable, cron it, or put it in a while loop if you need more 
than 1 minute granularity.

Flaws (among others):
1. Handling previous states (last run status) is rather rudimentary and could
   be done better.

2. Possible race conditions - not sure...looks ok, but I might have messed up
   the logic somewhere <shrug>  Be careful running this script too often.  If
   you run it with the routing tables in a state of flux/transition, this
   script will break and do horrible things to your system's nether
   regions! ;)

3. You could do more, with less code in Perl/Ruby/Python...but I just couldn't
   be bothered messing with syntax this afternoon.

4. Possibly a few typo's.

5. All this logic can be handled with BGRP....take it or leave it.

6. I've had 3 hours sleep in the last 48 hours...ABSOLUTELY NO warranty given
   or implied (I wrote this so I didn't fall asleep on the train and miss my
   stop! :P)...I did mention this script isn't tested didn't I?

BTW the lines like:
[ "$STATE_ALL" != down ] && all_actions down
...mean "only run the 'link down actions' if they weren't executed last time" 
Similar logic applies to when the link comes back up, except the logic is 
reversed (obviously).

Have fun!

James
-- 
Half a mind is a terrible thing to waste!

Attachment: pgplNiZFV1Rc8.pgp
Description: PGP signature

-- 
SLUG - Sydney Linux User's Group Mailing List - http://slug.org.au/
Subscription info and FAQs: http://slug.org.au/faq/mailinglists.html

Reply via email to