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