Annotation of badi/public_scripts/switchgate/switchgate, revision 1.1

1.1     ! adi         1: #!/bin/bash
        !             2: 
        !             3: # switchhgate 0.0.3
        !             4: # (c) 2005 under GPL by Adrian Zaugg
        !             5: 
        !             6: # switchgate pings a set of hosts to determine the state of the internet connectivity. If
        !             7: # the connection is down, it can change the default gateway to an alternative gateway.
        !             8: 
        !             9: ## Settings
        !            10: #
        !            11: 
        !            12: # Where the config files reside
        !            13: CONFIG_PATH="/etc/switchgate"
        !            14: 
        !            15: # Path where to find dhcp information file from switchgate-helper,
        !            16: # the dhclient-exit-hook helper program
        !            17: DHCP_TMP_DIR=/tmp/switchgate
        !            18: 
        !            19: # Host set to ping. A file containing IP addresses, each on a single line.
        !            20: # Do not include any local hosts, list only hosts located behind your gateways.
        !            21: HOSTSET_FILE="$CONFIG_PATH/hostset"
        !            22: 
        !            23: # The file defining fixed and dynamic gateway preference
        !            24: GATEWAYS_FILE="$CONFIG_PATH/gateways"
        !            25: 
        !            26: # path to fping
        !            27: PING=/usr/sbin/fping
        !            28: 
        !            29: # answer of fping to reachable hosts
        !            30: ALIVE_ANSWER="is alive"
        !            31: 
        !            32: # set to an empty string to avoid debug output
        !            33: # to "low" for a few output and to anything else
        !            34: # for verbose output
        !            35: DEBUG=
        !            36: 
        !            37: 
        !            38: # -------- Do not edit below this line --------
        !            39: 
        !            40: PINGARGS="-A -p25 -t100"
        !            41: 
        !            42: 
        !            43: ## Function declarations
        !            44: #
        !            45: 
        !            46: # Read gateways from file
        !            47: function readgwlist {
        !            48:        if [ -f "$GATEWAYS_FILE" ]; then
        !            49:                # Ordered list of all gateways in file. Highest preference has entry with index 0, which 
        !            50:                # is your standard default gateway.
        !            51:                # dhcp[.ethX] means dhcp supplied gateways in file $CONFIG_PATH/dhcp.ethX
        !            52:                number_of_gws=0
        !            53:                if [ -n "$DEBUG" -a "$DEBUG" != "low" ]; then
        !            54:                        echo "Reading config file $GATEWAYS_FILE..."
        !            55:                fi
        !            56: 
        !            57:                allgates=`grep -ve "^[  ]*[\#]\+.*$" "$GATEWAYS_FILE" | xargs`
        !            58:                for gate in $allgates; do
        !            59:                        if [[ $(echo "$gate" | grep -c -e "^[:space:]*dhcp\..*$") -eq 1 && \
        !            60:                              -f "$CONFIG_PATH/$gate" ]]; then
        !            61:                                # Read dhcp supplied gate for a specific interface
        !            62:                                alldhcpgates=`grep -e "^[^\#].*$" "$CONFIG_PATH/$gate" | xargs`
        !            63:                        elif [[ $(echo "$gate" | grep -c -e "^[:space:]*dhcp[:space:]*$") -eq 1 ]]; then
        !            64:                                # Read all dhcp files
        !            65:                                alldhcpgates=""
        !            66:                                for dhcpfile in $(echo -n $(ls -1 $DHCP_TMP_DIR/dhcp* 2>/dev/null)); do 
        !            67:                                        alldhcpgates="$alldhcpgates `grep -e "^[^\#].*$" "$dhcpfile" | xargs`"
        !            68:                                done
        !            69:                        else
        !            70:                                # it's a fixed gateway
        !            71:                                addgw="$gate"
        !            72:                                debug_msg="fixed"
        !            73:                                addgateway
        !            74:                        fi
        !            75: 
        !            76:                        for dhcpgate in $alldhcpgates; do
        !            77:                                addgw="$dhcpgate"
        !            78:                                debug_msg="$gate"
        !            79:                                addgateway
        !            80:                        done
        !            81:                        unset alldhcpgates
        !            82:                done
        !            83:        fi
        !            84:        
        !            85:        if [ "$number_of_gws" -eq 0 ]; then
        !            86:                echo "No gateways configured. Please edit $GATEWAYS_FILE."
        !            87:                exit 1
        !            88:        elif [[ "$number_of_gws" -eq 1 && ! -z $DEBUG ]]; then
        !            89:                echo "Only 1 gateway configured. No fallback switching possible."
        !            90:        else
        !            91:                if [[ -n "$DEBUG" && "$DEBUG" != "low" ]]; then
        !            92:                        echo "... $number_of_gws gateway(s) found."
        !            93:                fi
        !            94:        fi
        !            95: }
        !            96: 
        !            97: # add a gateway to the array of all gateways to possibly switch to
        !            98: function addgateway {
        !            99:        addgw=$(echo "$addgw" | tr -d ' ')
        !           100:        # check no duplicate addition is performed
        !           101:        if [ $(echo "${GW[*]}" | grep -c "$addgw") -eq 0 ]; then
        !           102:                GW[$number_of_gws]=$addgw
        !           103:                if [[ -n "$DEBUG" && "$DEBUG" != "low" ]]; then
        !           104:                        echo -e "\tGateway $number_of_gws: $addgw ($debug_msg)"
        !           105:                fi
        !           106:                let "number_of_gws += 1"
        !           107:        fi
        !           108:        unset addgw
        !           109: }
        !           110: 
        !           111: # If one host of the HOSTSET_FILE responds, the conncetion is considered up.
        !           112: function checkconnection {
        !           113:    UP=""
        !           114:    if [ `$PING $PINGARGS < "$HOSTSET_FILE" 2> /dev/null | grep -c "$ALIVE_ANSWER"` -gt 0 ]; then
        !           115:       UP=true
        !           116:    fi
        !           117:    if [ -n "$DEBUG" ]; then
        !           118:       if [ -n "$UP" ]; then
        !           119:          echo "The connection is up."
        !           120:       else 
        !           121:          echo "The connection is down."
        !           122:       fi
        !           123:    fi
        !           124: }
        !           125: 
        !           126: # Is a certain gateway reachable?
        !           127: function checkgw {
        !           128:    if [ `$PING $PINGARGS "$NEWGW" 2> /dev/null | grep -c "$ALIVE_ANSWER"` -gt 0 ]; then
        !           129:       if [ -n "$DEBUG" ]; then
        !           130:          echo "$NEWGW is reachable."
        !           131:       fi
        !           132:     else
        !           133:       if [ -n "$DEBUG" ]; then 
        !           134:           echo "$NEWGW is not reachable."
        !           135:       fi
        !           136:       NEWGW=""
        !           137:    fi
        !           138: }
        !           139: 
        !           140: function getcurrentgw {
        !           141:    iproute_default_gw_txt="$(ip route show scope global)"
        !           142:    if [ `echo $iproute_default_gw_txt | grep -c default` -gt 1 ]; then
        !           143:       echo "No support for multiple default gateways. Exiting."
        !           144:       exit 1
        !           145:    else
        !           146:       iproute_default_gw_txt="$(echo "$iproute_default_gw_txt" | grep "default via")"
        !           147:    fi  
        !           148:    if [ -z "$iproute_default_gw_txt" ]; then
        !           149:       # no default gateway currently set, set to the highest index, to land on GW0
        !           150:       CURRENTGW_ID=0
        !           151:       CURRENTGW=${GW[$CURRENTGW_ID]}
        !           152:       CURRENTGW_DEV="unknown"
        !           153:       echo "No default gateway currently set. Setting it now to $CURRENTGW."
        !           154:       ip route add default via $CURRENTGW
        !           155:    else
        !           156:       CURRENTGW=`echo $iproute_default_gw_txt | sed "s/^default via \(\([0-9]\+\.\?\)\{4\}\).*\$/\1/"` 
        !           157:       CURRENTGW_DEV=`echo $iproute_default_gw_txt | sed "s/^default via .* dev \(eth[0-9]\+\).*\$/\1/"` 
        !           158:    fi
        !           159: 
        !           160:    # get index of current gateway
        !           161:    index=-1
        !           162:    for NEWGW in ${GW[*]}; do
        !           163:       let "index += 1"
        !           164:       if [ "$CURRENTGW" = "$NEWGW" ]; then
        !           165:          CURRENTGW_ID=$index
        !           166:         break
        !           167:       fi
        !           168:    done
        !           169:    if [ -z "$CURRENTGW_ID" ]; then
        !           170:       echo "The current gateway ($CURRENTGW) is not in the list of available gateways."
        !           171:       echo "Please edit $GATEWAYS_FILE to correct."
        !           172:       exit 1
        !           173:    fi
        !           174:    if [ "$DEBUG" = "low" ]; then
        !           175:       echo "Default gateway detected: $CURRENTGW ($CURRENTGW_ID) on dev $CURRENTGW_DEV"
        !           176:    fi
        !           177: }
        !           178: 
        !           179: # Set NEWGW and NEWGW_ID to the next gateway from GW[]
        !           180: function getnextgw {
        !           181:    if [ -z "$NEWGW_ID" ]; then
        !           182:       if [ -z "$CURRENTGW_ID" ]; then
        !           183:          getcurrentgw
        !           184:          NEWGW_ID=$CURRENTGW_ID
        !           185:       else
        !           186:          NEWGW_ID=-1
        !           187:       fi
        !           188:    fi
        !           189:    NEWGW_ID=$[ $NEWGW_ID + 1 ]
        !           190:    if [ "$NEWGW_ID" -ge "${#GW[*]}" ]; then
        !           191:       NEWGW_ID=0
        !           192:    fi
        !           193:    NEWGW=${GW[$NEWGW_ID]}
        !           194: }
        !           195: 
        !           196: # Set $NEWGW to the next working gateway
        !           197: function getnewgw {
        !           198:    getnextgw
        !           199:    # Check wheter all gateways are already tested and failed
        !           200:    if [ "$NEWGW_ID" -eq "$CURRENTGW_ID" ]; then
        !           201:       if [ -n "$DEBUG" ]; then
        !           202:          echo "All gateways tried."
        !           203:       fi
        !           204:       NEWGW=""
        !           205:       NEWGW_ID=""
        !           206:    else
        !           207:       if [ -n "$DEBUG" ]; then
        !           208:          echo -n "Trying $NEWGW..."
        !           209:       fi
        !           210:       savegw=$NEWGW
        !           211:       checkgw
        !           212:       if [ -z "$NEWGW" ]; then
        !           213:          if [ -n "$DEBUG" ]; then
        !           214:              echo "No luck. Trying next..."
        !           215:          fi
        !           216:          NEWGW=$savegw
        !           217:          getnewgw
        !           218:       else
        !           219:          if [ -n "$DEBUG" ]; then
        !           220:             echo "Successfully found a new gateway, it's $NEWGW."
        !           221:          fi
        !           222:       fi
        !           223:    fi
        !           224: }
        !           225: 
        !           226: function switchgw {
        !           227:    getnewgw
        !           228:    if [ -n "$NEWGW" ]; then
        !           229:       if [ "$DEBUG" = "low" ]; then
        !           230:          echo -n "Switching default gateway now to $NEWGW ($NEWGW_ID)..."
        !           231:       fi 
        !           232:       
        !           233:       iproute_msg="$(ip route change default via $NEWGW 2>&1 )"
        !           234:       iproute_exit=$?
        !           235: 
        !           236:       # generate some traffic to take effect
        !           237:       sleep 1
        !           238:       GARBAGE=`$PING -q -c 5 -t100 -p50 -A -f $HOSTSET_FILE 2> /dev/null`
        !           239:       sleep 1
        !           240:       
        !           241:       if [ "$DEBUG" = "low" ]; then
        !           242:          echo "done."
        !           243:       fi
        !           244: 
        !           245:       checkconnection
        !           246:       if [ -z "$UP" ]; then
        !           247:          if [ "$DEBUG" = "low" ]; then
        !           248:             echo -n "$NEWGW ($NEWGW_ID) is not working, switching back to $CURRENTGW ($CURRENTGW_ID)..."
        !           249:         fi
        !           250:         ip route change default via $CURRENTGW
        !           251:         if [ "$DEBUG" = "low" ]; then
        !           252:            echo "done."
        !           253:         fi
        !           254:         switchgw
        !           255:       elif [ "$iproute_exit" -eq 0 ]; then
        !           256:          CURRENTGW=$NEWGW
        !           257:          CURRENTGW_ID=$NEWGW_ID
        !           258:       else
        !           259:         echo "Failure from iproute: $iproute_msg"
        !           260:         echo "However, the connection is working. Continue as if nothing."
        !           261:       fi
        !           262:    else
        !           263:       if [ "$DEBUG" = "low" ]; then
        !           264:          echo "Not switching."
        !           265:       fi
        !           266:    fi
        !           267: }
        !           268: 
        !           269: 
        !           270: ## MAIN
        !           271: #
        !           272: 
        !           273: # Parse writeable dir request (hidden feature)
        !           274: if [ "$1" = "-C" ]; then
        !           275:        echo "$DHCP_TMP_DIR"
        !           276:        exit 0
        !           277: fi
        !           278: 
        !           279: # Parse debug switch (another hidden feature)
        !           280: if [ "$1" = "-d" ]; then
        !           281:        if [ "$2" != "low" ]; then
        !           282:                echo "Debug mode on."
        !           283:                DEBUG="choke"
        !           284:        else
        !           285:                #echo "Info mode on."
        !           286:                DEBUG="low"
        !           287:        fi 
        !           288: fi
        !           289: 
        !           290: # Get all gateways, we can forward traffic
        !           291: readgwlist
        !           292: 
        !           293: # Parse query for current gw  (yet another hidden feature)
        !           294: if [ "$1" = "-q" ]; then
        !           295:        DEBUG=
        !           296:        getcurrentgw
        !           297:        echo "$CURRENTGW"
        !           298:        exit 0
        !           299: fi
        !           300: 
        !           301: # get current gw
        !           302: getcurrentgw
        !           303: 
        !           304: # check wether host set file is around
        !           305: if [ ! -e $HOSTSET_FILE ]; then
        !           306:    echo "No host list found! File $HOSTSET_FILE not found."
        !           307:    exit 1
        !           308: fi
        !           309: 
        !           310: # check connection
        !           311: checkconnection
        !           312: 
        !           313: # If the connection is down, change to the nextgw
        !           314: if [ -z "$UP" ]; then
        !           315:    # Some more information of down reason: Diagnose wheter the current gateway is alive 
        !           316:    NEWGW=$CURRENTGW
        !           317:    checkgw
        !           318:    if [ -z "$NEWGW" ]; then
        !           319:       echo "Gateway $CURRENTGW is down."
        !           320:    else 
        !           321:       echo "No connection through gateway $CURRENTGW." 
        !           322:    fi
        !           323:   
        !           324:    NEWGW_ID=$CURRENTGW_ID
        !           325:    switchgw
        !           326:    
        !           327: else
        !           328:    # If the current gateway is not the standard default gateway, try if the connection 
        !           329:    # through the standard default gateway is back
        !           330:    if [ "$CURRENTGW_ID" != 0 ]; then
        !           331:       if [ "$DEBUG" = "low" ]; then
        !           332:          echo "Not operating on standard default gateway (${GW[0]}). Trying to change."
        !           333:       fi
        !           334:       NEWGW_ID=""
        !           335:       switchgw
        !           336:    else
        !           337:       # normal operation
        !           338:       if [[ -n "$DEBUG" && "$DEBUG" != "low" ]]; then
        !           339:          echo "Normal operation on standard default gateway $CURRENTGW ($CURRENTGW_ID)."
        !           340:       fi
        !           341:    fi
        !           342: fi
        !           343: 
        !           344: if [ "$DEBUG" = "low" ]; then
        !           345:    echo
        !           346:    echo "Default Gateway: $CURRENTGW ($CURRENTGW_ID)"
        !           347:    echo
        !           348: fi
        !           349: exit 0

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>