Annotation of badi/public_scripts/switchgate/switchgate, revision 1.1.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>