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>