[packages] add multiwan, a simple to use multi wan configuration agent
[openwrt/svn-archive/archive.git] / net / multiwan / files / usr / bin / multiwan
1 #!/bin/sh
2
3 . /etc/functions.sh
4
5 silencer() {
6 if [ -z "$debug" -o "$debug" == "0" ]; then
7 $* > /dev/null 2>&1
8 else
9 $*
10 fi
11 }
12
13 mwnote() {
14 logger "[Multi-WAN Notice]: $1"
15 }
16
17 failover() {
18 local failover_to
19 local failover_to_wanid
20 local failchk
21 local wanid
22 local existing_failover
23
24 wanid=$(query_config wanid $2)
25 failover_to=`uci -q -P /var/state get multiwan.${2}.failover_to`
26 failover_to_wanid=$(query_config wanid $failover_to)
27
28 existing_failover=$(iptables -n -L FW${wanid}MARK -t mangle | echo $(expr $(wc -l) - 2))
29
30 add() {
31 if [ "$existing_failover" == "2" ]; then
32 if [ "$failover_to" != "balancer" -a "$failover_to" != "disable" -a "$failover_to_wanid" != "$wanid" ]; then
33 iptables -I FW${wanid}MARK 2 -t mangle -j FW${failover_to_wanid}MARK
34 elif [ "$failover_to" == "balancer" ]; then
35 iptables -I FW${wanid}MARK 2 -t mangle -j LoadBalancer
36 fi
37 fi
38 mwnote "$1 has failed and is currently offline."
39 }
40
41 del() {
42 if [ "$existing_failover" == "3" ]; then
43 if [ "$failover_to" != "balancer" -a "failover_to" != "disable" -a "$failover_to_wanid" != "$wanid" ]; then
44 iptables -D FW${wanid}MARK -t mangle -j FW${failover_to_wanid}MARK
45 elif [ "$failover_to" == "balancer" ]; then
46 iptables -D FW${wanid}MARK -t mangle -j LoadBalancer
47 fi
48 fi
49 mwnote "$1 has recovered and is back online!"
50 }
51
52 case $1 in
53 add) add $2;;
54 del) del $2;;
55 esac
56 }
57
58 fail_wan() {
59 local failchk
60 local recvrychk
61 local new_fail_count
62 local health_fail_retries
63 local weight
64
65 health_fail_retries=`uci -q -P /var/state get multiwan.${1}.health_fail_retries`
66 weight=`uci -q -P /var/state get multiwan.${1}.weight`
67
68 failchk=$(query_config failchk $1)
69 recvrychk=$(query_config recvrychk $1)
70 wan_recovery_map=$(echo $wan_recovery_map | sed -e "s/${1}\[${recvrychk}\]//g")
71
72 if [ -z "$failchk" ]; then
73 wan_fail_map="$wan_fail_map $1[1]"
74 if [ "$health_fail_retries" == "1" ]; then
75 fail_wan $1
76 fi
77 else
78 if [ "$failchk" != "x" ]; then
79 new_fail_count=$(expr $failchk + 1)
80 if [ "$new_fail_count" -lt "$health_fail_retries" ]; then
81 wan_fail_map=$(echo $wan_fail_map | sed -e "s/${1}\[${failchk}\]/$1\[${new_fail_count}\]/g")
82 else
83 wan_fail_map=$(echo $wan_fail_map | sed -e "s/${1}\[${failchk}\]/$1\[x\]/g")
84 if [ "$weight" != "disable" ]; then
85 refresh_loadbalancer
86 fi
87 refresh_dns
88 failover add $1
89 fi
90 fi
91 fi
92 }
93
94 recover_wan() {
95 local failchk
96 local recvrychk
97 local new_fail_count
98 local wanid
99 local health_recovery_retires
100 local weight
101
102 health_recovery_retries=`uci -q -P /var/state get multiwan.${1}.health_recovery_retries`
103 weight=`uci -q -P /var/state get multiwan.${1}.weight`
104
105 failchk=$(query_config failchk $1)
106 recvrychk=$(query_config recvrychk $1)
107 wanid=$(query_config wanid $1)
108
109 if [ "$failchk" == "x" ]; then
110 if [ -z "$recvrychk" ]; then
111 wan_recovery_map="$wan_recovery_map $1[1]"
112 if [ "$health_recovery_retries" == "1" ]; then
113 recover_wan $1
114 fi
115 else
116 new_recovery_count=$(expr $recvrychk + 1)
117 if [ "$new_recovery_count" -lt "$health_recovery_retries" ]; then
118 wan_recovery_map=$(echo $wan_recovery_map | sed -e "s/${1}\[${recvrychk}\]/$1\[${new_recovery_count}\]/g")
119 else
120 wan_recovery_map=$(echo $wan_recovery_map | sed -e "s/${1}\[${recvrychk}\]//g")
121 wan_fail_map=$(echo $wan_fail_map | sed -e "s/${1}\[${failchk}\]//g")
122 if [ "$weight" != "disable" ]; then
123 refresh_loadbalancer
124 fi
125 refresh_dns
126 failover del $1
127 fi
128 fi
129 fi
130 }
131
132 acquire_wan_data() {
133 if [ $wancount -lt 9 ]; then
134
135 local ipaddr
136 local gateway
137 local ifname
138 local check_old_map
139 local get_wanid
140 local old_ifname
141 local old_ipaddr
142 local old_gateway
143
144 ifname=`uci -q -P /var/state get network.${1}.ifname`
145 ipaddr=`uci -q -P /var/state get network.${1}.ipaddr`
146 gateway=`uci -q -P /var/state get network.${1}.gateway`
147
148 if [ -z "$ifname" ]; then
149 ifname="x"
150 fi
151 if [ -z "$ipaddr" ]; then
152 ipaddr="x"
153 fi
154 if [ -z "$gateway" ]; then
155 gateway="x"
156 fi
157
158 check_old_map=`echo $wan_id_map 2>&1 | grep -o "$1\["`
159
160 if [ -z $check_old_map ]; then
161 wancount=`expr $wancount + 1`
162 wan_if_map="$wan_if_map $1[${ifname}] "
163 wan_id_map="$wan_id_map $1[${wancount}] "
164 wan_gw_map="$wan_gw_map $1[${gateway}] "
165 wan_ip_map="$wan_ip_map $1[${ipaddr}] "
166 else
167 old_ipaddr=$(query_config ipaddr $1)
168 old_gateway=$(query_config gateway $1)
169 old_ifname=$(query_config ifname $1)
170 get_wanid=$(query_config wanid $1)
171
172 wan_if_map=$(echo $wan_if_map | sed -e "s/${1}\[${old_ifname}\]/$1\[${ifname}\]/g")
173 wan_ip_map=$(echo $wan_ip_map | sed -e "s/${1}\[${old_ipaddr}\]/$1\[${ipaddr}\]/g")
174 wan_gw_map=$(echo $wan_gw_map | sed -e "s/${1}\[${old_gateway}\]/$1\[${gateway}\]/g")
175
176 if [ "$old_ifname" != "$ifname" ]; then
177 iptables -D MultiWanPreHandler -t mangle -i $old_$ifname -m state --state NEW -j FW${get_wanid}MARK
178 iptables -A MultiWanPreHandler -t mangle -i $ifname -m state --state NEW -j FW${get_wanid}MARK
179 iptables -D MultiWanPostHandler -t mangle -o $old_$ifname -m mark --mark 0x123 -j FW${get_wanid}MARK
180 iptables -A MultiWanPostHandler -t mangle -o $ifname -m mark --mark 0x123 -j FW${get_wanid}MARK
181 fi
182
183 refresh_routes
184 refresh_loadbalancer
185 refresh_dns
186
187 if [ "$ifname" != "x" -a "$ipaddr" != "x" -a "$gateway" != "x" ]; then
188 iprules_config $get_wanid
189 qos_init $1 $get_wanid
190 failover del $1
191 else
192 failover add $1
193 fi
194 fi
195 else
196 wancount=9
197 fi
198 }
199
200 query_config() {
201 case $1 in
202 ifname) echo $wan_if_map | grep -o "$2\[\w*.*\]" | awk -F "[" '{print $2}' | awk -F "]" '{print $1}';;
203 ipaddr) echo $wan_ip_map | grep -o "$2\[\w*.*\]" | awk -F "[" '{print $2}' | awk -F "]" '{print $1}';;
204 gateway) echo $wan_gw_map | grep -o "$2\[\w*.*\]" | awk -F "[" '{print $2}' | awk -F "]" '{print $1}';;
205 wanid) echo $wan_id_map | grep -o "$2\[\w*.*\]" | awk -F "[" '{print $2}' | awk -F "]" '{print $1}';;
206 failchk) echo $wan_fail_map | grep -o "$2\[\w*.*\]" | awk -F "[" '{print $2}' | awk -F "]" '{print $1}';;
207 recvrychk) echo $wan_recovery_map | grep -o "$2\[\w*.*\]" | awk -F "[" '{print $2}' | awk -F "]" '{print $1}';;
208 group) echo $wan_id_map | grep -o "\w*\[$2\]" | awk -F "[" '{print $1}';;
209 esac
210 }
211
212 mwan_kill() {
213 local otherpids
214 local execute
215 otherpids=$(ps -a 2>&1 | grep 'multiwan agent' | grep -v $$ | awk -F " " '{print $1}')
216 echo "$otherpids" | while read execute
217 do
218 kill -9 ${execute} > /dev/null 2>&1
219 done
220 }
221
222 stop() {
223 local group
224 local i
225
226 mwan_kill
227 flush
228
229 if [ "$1" != "restart" ]; then
230 echo "## Refreshing Interfaces ##"
231 i=0
232 while [ $i -lt $wancount ]; do
233 i=`expr $i + 1`
234 group=$(query_config group $i)
235 fdown $group > /dev/null 2>&1
236 ifup $group > /dev/null 2>&1 &
237 done
238
239 if [ ! -z "$CHKFORQOS" ]; then
240 /etc/init.d/qos restart & > /dev/null 2>&1
241 fi
242
243 echo "## Unloaded, updating syslog and exiting. ##"
244 mwnote "Succesfully Unloaded on $(exec date -R)."
245
246 else
247
248 echo "## Restarting Multi-WAN. ##"
249 mwnote "Reinitializing Multi-WAN Configuration."
250 /etc/init.d/multiwan start & > /dev/null 2>&1
251
252 fi
253
254 ip route flush cache
255
256 exit
257 }
258
259 clear_rules() {
260 local group
261 local i
262
263 iptables -t mangle -F PREROUTING
264 iptables -t mangle -F FORWARD
265 iptables -t mangle -F POSTROUTING
266 iptables -t mangle -F OUTPUT
267 iptables -t mangle -F MultiWan
268 iptables -t mangle -X MultiWan
269 iptables -t mangle -F MultiWanRules
270 iptables -t mangle -X MultiWanRules
271 iptables -t mangle -F MultiWanDNS
272 iptables -t mangle -X MultiWanDNS
273 iptables -t mangle -F MultiWanPreHandler
274 iptables -t mangle -X MultiWanPreHandler
275 iptables -t mangle -F MultiWanPostHandler
276 iptables -t mangle -X MultiWanPostHandler
277 iptables -t mangle -F LoadBalancer
278 iptables -t mangle -X LoadBalancer
279
280 i=0
281 while [ $i -lt $wancount ]; do
282 i=`expr $i + 1`
283 iptables -t mangle -F FW${i}MARK
284 done
285
286 i=0
287 while [ $i -lt $wancount ]; do
288 i=`expr $i + 1`
289 iptables -t mangle -X FW${i}MARK
290 done
291
292 if [ ! -z "$CHKFORQOS" ]; then
293
294 iptables -t mangle -F MultiWanQoS
295 iptables -t mangle -X MultiWanQoS
296
297 i=0
298 while [ $i -lt $wancount ]; do
299 i=`expr $i + 1`
300 group=$(query_config group $i)
301 iptables -t mangle -F MultiWanQoS_${group}
302 iptables -t mangle -F MultiWanQoS_${group}_ct
303 iptables -t mangle -X MultiWanQoS_${group}
304 iptables -t mangle -X MultiWanQoS_${group}_ct
305 done
306
307 fi
308 }
309
310 qos_init() {
311 local ifname
312 local queue_count
313 local get_wan_tc
314 local get_wan_iptables
315 local qos_done_chk
316 local add_qos_iptables
317 local add_qos_tc
318 local execute
319 local i
320 local p
321
322 qos_done_chk=`echo $qos_done | grep -o "$1\."`
323
324 if [ ! -z "$qos_done_chk" ]; then
325 return
326 fi
327
328 ifname=$(query_config ifname $1)
329
330 if [ "$ifname" == "x" ]; then
331 return
332 fi
333
334 queue_count=$(tc filter list dev $ifname | tail -n 1 | awk -F " " '{print $10}' | sed "s/0x//g")
335
336 if [ -z "$queue_count" ]; then
337 return
338 fi
339
340 queue_count=`expr $queue_count + 1`
341
342 iptables -t mangle -N MultiWanQoS_${1}
343 iptables -t mangle -N MultiWanQoS_${1}_ct
344
345 get_wan_tc=$(tc filter list dev $ifname | grep "0x" | sed -e "s/filter /tc filter add dev $ifname /g" -e "s/pref/prio/g" -e "s/fw//g")
346 get_wan_iptables=$(iptables-save | egrep '(-A Default )|(-A Default_ct )' | grep -v "MultiWanQoS" | sed -e "s/Default /MultiWanQoS_${1} /g" -e "s/Default_ct /MultiWanQoS_${1}_ct /g" -e "s/-A/iptables -t mangle -A/g")
347
348 rm /tmp/.mwan.$1.sedfilter > /dev/null 2>&1
349 i=0
350 while [ $i -lt $queue_count ]; do
351 echo "s/\(0x$i \|0x$i\/0xffffffff\)/0x${2}${i} /g" >> /tmp/.mwan.$1.sedfilter
352 i=`expr $i + 1`
353 done
354
355 add_qos_iptables=$(echo "$get_wan_iptables" | sed -f /tmp/.mwan.$1.sedfilter)
356 echo "$add_qos_iptables" | while read execute; do ${execute}; done
357
358 rm /tmp/.mwan.$1.sedfilter
359 i=1
360 while [ $i -lt $queue_count ]; do
361 echo "s/0x$i /0x${2}${i} fw /g" >> /tmp/.mwan.$1.sedfilter
362 i=`expr $i + 1`
363 done
364
365 add_qos_tc=$(echo "$get_wan_tc" | sed -f /tmp/.mwan.$1.sedfilter)
366 echo "$add_qos_tc" | while read execute; do ${execute}; done
367 rm /tmp/.mwan.$1.sedfilter
368
369 i=0
370 while [ $i -lt $queue_count ]; do
371 p=`expr $i + $2 \* 10`
372 if [ $i -lt $(expr $queue_count - 1) ]; then
373 ip rule add fwmark 0x$(expr $p + 1) table $(expr $2 \* 10) prio $(expr $p + 2)
374 fi
375 iptables -t mangle -A MultiWanQoS -m mark --mark 0x$p -j MultiWanQoS_${1}
376 i=`expr $i + 1`
377 done
378
379 qos_done="$qos_done $1."
380
381 }
382
383 mwanrule() {
384 local src
385 local dst
386 local ports
387 local proto
388 local wanrule
389
390 config_get src $1 src
391 config_get dst $1 dst
392 config_get ports $1 ports
393 config_get proto $1 proto
394 config_get wanrule $1 wanrule
395 ports_first=${ports%-*}
396 ports_last=${ports#*-}
397
398 if [ -z "$wanrule" ]; then
399 return
400 fi
401
402 if [ "$wanrule" != "balancer" ]; then
403 wanrule=$(query_config wanid ${wanrule})
404 wanrule="FW${wanrule}MARK"
405 elif [ "$wanrule" == "balancer" ]; then
406 wanrule="LoadBalancer"
407 fi
408 if [ "$dst" == "all" ]; then
409 dst=$NULL
410 fi
411 if [ "$proto" == "all" ]; then
412 proto=$NULL
413 fi
414 if [ "$ports" == "all" ]; then
415 ports=$NULL
416 fi
417 if [ "$ports_first" -ne "$ports_last" ]; then
418 ports="$ports_first:$ports_last"
419 fi
420 add_rule() {
421 if [ "$proto" == "icmp" ]; then
422 ports=$NULL
423 fi
424 if [ "$src" == "all" ]; then
425 src=$NULL
426 fi
427 iptables -t mangle -A MultiWanRules -m mark --mark 0x0\
428 ${proto:+-p $proto} \
429 ${src:+-s $src} \
430 ${dst:+-d $dst} \
431 ${ports:+--dport $ports} \
432 -j $wanrule
433 }
434 if [ -z "$proto" -a ! -z "$ports" ]; then
435 proto=tcp
436 add_rule
437 proto=udp
438 add_rule
439 return
440 fi
441 add_rule
442 }
443
444 refresh_dns() {
445 local dns
446 local group
447 local ipaddr
448 local gateway
449 local ifname
450 local failchk
451 local compile_dns
452 local resolv_conf
453 local dns_server
454 local i
455
456 iptables -F MultiWanDNS -t mangle
457
458 rm $resolv_conf
459 touch $resolv_conf
460
461 echo "## Refreshing DNS Resolution and Tables ##"
462
463 i=0
464 while [ $i -lt $wancount ]; do
465 i=`expr $i + 1`
466 group=$(query_config group $i)
467 gateway=$(query_config gateway $group)
468 ipaddr=$(query_config ipaddr $group)
469 ifname=$(query_config ifname $group)
470 failchk=$(query_config failchk $group)
471
472 dns=`uci -q -P /var/state get network.${group}.dns`
473 dns=$(echo $dns | sed -e "s/ /\n/g")
474
475 if [ ! -z "$dns" -a "$failchk" != "x" -a "$ipaddr" != "x" -a "$gateway" != "x" -a "$ifname" != "x" ]; then
476 echo "$dns" | while read dns_server
477 do
478 iptables -t mangle -A MultiWanDNS -d $dns_server -p UDP --dport 53 -j FW${i}MARK
479
480 compile_dns="nameserver $dns_server"
481 echo "$compile_dns" >> $resolv_conf
482 done
483 fi
484 done
485 }
486
487 iptables_init() {
488 echo "## IPTables Rule Initialization ##"
489 local iprule
490 local group
491 local ifname
492 local execute
493 local IMQ_NFO
494 local default_route_id
495 local i
496
497 if [ ! -z "$CHKFORQOS" ]; then
498 echo "## QoS Initialization ##"
499
500 /etc/init.d/qos restart > /dev/null 2>&1
501
502 IMQ_NFO=`iptables -n -L PREROUTING -t mangle -v | grep IMQ | awk -F " " '{print $6,$12}'`
503
504 iptables -t mangle -F PREROUTING
505 iptables -t mangle -F FORWARD
506 iptables -t mangle -F POSTROUTING
507 iptables -t mangle -F OUTPUT
508
509 echo "$IMQ_NFO" | while read execute
510 do
511 iptables -t mangle -A PREROUTING -i $(echo $execute | awk -F " " '{print $1}') -j IMQ --todev $(echo $execute | awk -F " " '{print $2}')
512 done
513
514 iptables -t mangle -N MultiWanQoS
515
516 i=0
517 while [ $i -lt $wancount ]; do
518 i=`expr $i + 1`
519 qos_init $(query_config group $i) $i
520 done
521
522 fi
523
524 iptables -t mangle -N MultiWan
525 iptables -t mangle -N LoadBalancer
526 iptables -t mangle -N MultiWanRules
527 iptables -t mangle -N MultiWanDNS
528 iptables -t mangle -N MultiWanPreHandler
529 iptables -t mangle -N MultiWanPostHandler
530
531 echo "## Creating FW Rules ##"
532 i=0
533 while [ $i -lt $wancount ]; do
534 i=`expr $i + 1`
535 iprule=$(expr $i \* 10)
536 iptables -t mangle -N FW${i}MARK
537 iptables -t mangle -A FW${i}MARK -j MARK --set-mark 0x${iprule}
538 iptables -t mangle -A FW${i}MARK -j CONNMARK --save-mark
539 done
540
541 iptables -t mangle -A LoadBalancer -j MARK --set-mark 0x123
542 iptables -t mangle -A LoadBalancer -j CONNMARK --save-mark
543
544 iptables -t mangle -I PREROUTING -j MultiWan
545 iptables -t mangle -I FORWARD -j MultiWan
546 iptables -t mangle -I OUTPUT -j MultiWan
547 iptables -t mangle -I POSTROUTING -j MultiWan
548
549 iptables -t mangle -A MultiWan -j CONNMARK --restore-mark
550 iptables -t mangle -A MultiWan -j MultiWanPreHandler
551
552 refresh_dns
553
554 config_load "multiwan"
555 config_foreach mwanrule mwanfw
556
557 if [ "$default_route" != "balancer" ]; then
558 default_route_id=$(query_config wanid $default_route)
559 iptables -t mangle -A MultiWanRules -m mark --mark 0x0 -j FW${default_route_id}MARK
560 else
561 iptables -t mangle -A MultiWanRules -m mark --mark 0x0 -j LoadBalancer
562 fi
563
564 iptables -t mangle -A MultiWan -j MultiWanRules
565 iptables -t mangle -A MultiWan -j MultiWanDNS
566 iptables -t mangle -A MultiWan -j MultiWanPostHandler
567
568 i=0
569 while [ $i -lt $wancount ]; do
570 i=`expr $i + 1`
571 group=$(query_config group $i)
572 ifname=$(query_config ifname $group)
573 iptables -t mangle -A MultiWanPreHandler -i $ifname -m state --state NEW -j FW${i}MARK
574 iptables -t mangle -A MultiWanPostHandler -o $ifname -m mark --mark 0x123 -j FW${i}MARK
575 done
576
577 if [ ! -z "$CHKFORQOS" ]; then
578 iptables -t mangle -A MultiWan -j MultiWanQoS
579 fi
580 }
581
582 refresh_loadbalancer() {
583 local group
584 local gateway
585 local ifname
586 local failchk
587 local weight
588 local nexthop
589 local pre_nexthop_chk
590 local i
591
592
593 echo "## Refreshing Load Balancer ##"
594
595 CHKIPROUTE=`cat /etc/iproute2/rt_tables | grep LoadBalancer`
596 if [ -z "$CHKIPROUTE" ]; then
597 echo "123 LoadBalancer" >> /etc/iproute2/rt_tables
598 fi
599 ip rule del prio 123 > /dev/null 2>&1
600 ip route flush table 123 > /dev/null 2>&1
601
602 for TABLE in 123
603 do
604 ip route | grep link | while read ROUTE
605 do
606 ip route add table $TABLE to $ROUTE
607 done
608 done
609
610 i=0
611 while [ $i -lt $wancount ]; do
612 i=`expr $i + 1`
613 group=$(query_config group $i)
614 failchk=$(query_config failchk $group)
615 gateway=$(query_config gateway $group)
616 ifname=$(query_config ifname $group)
617
618 weight=`uci -q -P /var/state get multiwan.${group}.weight`
619
620 if [ "$gateway" != "x" -a "$ifname" != "x" -a "$failchk" != "x" -a "$weight" != "disable" ]; then
621 nexthop="$nexthop nexthop via $gateway dev $ifname weight $weight"
622 fi
623 done
624
625 pre_nexthop_chk=`echo $nexthop | awk -F "nexthop" '{print NF-1}'`
626 if [ "$pre_nexthop_chk" == "1" ]; then
627 ip route add default via $(echo $nexthop | awk -F " " '{print $3}') dev $(echo $nexthop | awk -F " " '{print $5}') proto static table 123
628 elif [ "$pre_nexthop_chk" -gt "1" ]; then
629 ip route add proto static table 123 default scope global $nexthop
630 fi
631
632 ip rule add fwmark 0x123 table 123 prio 123
633 ip route flush cache
634 }
635
636 refresh_routes() {
637 local iprule
638 local gateway
639 local group
640 local ifname
641 local ipaddr
642 local i
643
644 echo "## Refreshing Routing Tables ##"
645
646 i=0
647 while [ $i -lt $wancount ]
648 do
649 i=`expr $i + 1`
650 group=$(query_config group $i)
651 gateway=$(query_config gateway $group)
652 ifname=$(query_config ifname $group)
653 ipaddr=$(query_config ipaddr $group)
654
655 iprule=$(expr $i \* 10)
656 ip route flush table $iprule > /dev/null 2>&1
657
658 for TABLE in $iprule
659 do
660 ip route | grep link | while read ROUTE
661 do
662 ip route add table $TABLE to $ROUTE
663 done
664 done
665
666 if [ "$gateway" != "x" -a "$ipaddr" != "x" -a "$ifname" != "x" ]; then
667 ip route add default via $gateway table $iprule src $ipaddr proto static
668 route add default gw $gateway dev $ifname
669 fi
670 done
671
672 ip route flush cache
673 }
674
675 iprules_config() {
676
677 local iprule
678 local group
679 local gateway
680 local ipaddr
681
682 iprule=$(expr $1 \* 10)
683 group=$(query_config group $1)
684 gateway=$(query_config gateway $group)
685 ipaddr=$(query_config ipaddr $group)
686
687 CHKIPROUTE=`cat /etc/iproute2/rt_tables | grep MWAN${1}`
688 if [ -z "$CHKIPROUTE" ]; then
689 echo "$iprule MWAN${1}" >> /etc/iproute2/rt_tables
690 fi
691
692 ip rule del prio $iprule > /dev/null 2>&1
693 ip rule del prio $(expr $iprule + 1) > /dev/null 2>&1
694
695 if [ "$gateway" != "x" -a "$ipaddr" != "x" ]; then
696 ip rule add from $ipaddr table $iprule prio $iprule
697 ip rule add fwmark 0x${iprule} table $iprule prio $(expr $iprule + 1)
698 fi
699 }
700
701 flush() {
702 local iprule
703 local i
704
705 echo "## Flushing IP Rules & Routes ##"
706
707 ip rule flush > /dev/null 2>&1
708 ip rule add lookup main prio 32766 > /dev/null 2>&1
709 ip rule add lookup default prio 32767 > /dev/null 2>&1
710
711 ip route flush table 123 > /dev/null
712
713 i=0
714 while [ $i -lt $wancount ]; do
715 i=`expr $i + 1`
716 iprule=$(expr $i \* 10)
717 ip route del default > /dev/null 2>&1
718 ip route flush table $iprule > /dev/null 2>&1
719 done
720
721 echo "## Clearing Rules ##"
722 clear_rules > /dev/null 2>&1
723
724 rm $jobfile > /dev/null 2>&1
725 }
726
727 main_init() {
728 local RP_PATH
729 local group
730 local health_interval
731 local i
732
733 echo "## Main Initialization ##"
734
735 mwan_kill
736 flush
737
738 refresh_loadbalancer
739
740 echo "## IP Rules Initialization ##"
741 i=0
742 while [ $i -lt $wancount ]; do
743 i=`expr $i + 1`
744 iprules_config $i
745 done
746
747 refresh_routes
748 iptables_init
749
750 RP_PATH=/proc/sys/net/ipv4/conf
751 for IFACE in `ls $RP_PATH`; do
752 echo 0 > $RP_PATH/$IFACE/rp_filter
753 done
754 echo "## Initialization Complete, switching to background mode. ##"
755 mwnote "Succesfully Initialized on $(exec date -R)."
756 fail_start_check
757
758 stagger_health_monitors() {
759 i=0
760 while [ $i -lt $wancount ]; do
761 i=`expr $i + 1`
762 group=$(query_config group $i)
763 health_interval=`uci -q -P /var/state get multiwan.${group}.health_interval`
764 if [ ! -z "$health_interval" -a "$health_interval" != "disable" -a "$health_interval" -gt 0 ]; then
765 health_monitor $group &
766 sleep 3
767 fi
768 done
769 }
770
771 stagger_health_monitors &
772 bg_task &
773
774 exit
775 }
776
777 health_monitor() {
778 local ipaddr_cur
779 local gateway_cur
780 local ifname_cur
781 local ifname
782 local ipaddr
783 local gateway
784 local failchk
785 local icmp_hosts
786 local icmp_hosts_acquire
787 local default_routes_check
788 local icmp_test_host
789 local timeout
790 local check_test
791 local health_interval
792 local check_for_job
793
794 timeout=`uci -q -P /var/state get multiwan.${1}.timeout`
795 icmp_hosts=`uci -q -P /var/state get multiwan.${1}.icmp_hosts`
796 health_interval=`uci -q -P /var/state get multiwan.${1}.health_interval`
797 ifname_cur=$(query_config ifname $1)
798 ipaddr_cur=$(query_config ipaddr $1)
799 gateway_cur=$(query_config gateway $1)
800
801 while [ 1 ]; do
802
803 ifname=`uci -q -P /var/state get network.${1}.ifname`
804 ipaddr=`uci -q -P /var/state get network.${1}.ipaddr`
805 gateway=`uci -q -P /var/state get network.${1}.gateway`
806
807 if [ -z "$ifname" ]; then
808 ifname="x"
809 fi
810
811 if [ -z "$ipaddr" ]; then
812 ipaddr="x"
813 fi
814
815 if [ -z "$gateway" ]; then
816 gateway="x"
817 fi
818
819 if [ "$ifname_cur" != "$ifname" -o "$ipaddr_cur" != "$ipaddr" -o "$gateway_cur" != "$gateway" ]; then
820 echo $1.acquire >> $jobfile
821 exit
822 else
823 if [ "$gateway" != "x" ]; then
824 default_routes_check=`ip route | grep -o $gateway`
825 if [ -z "$default_routes_check" ]; then
826 check_for_job=`cat $jobfile 2>&1 | grep -o "route.refresh"`
827 if [ -z "$check_for_job" ]; then
828 echo route.refresh >> $jobfile
829 fi
830 fi
831 fi
832 fi
833
834 if [ "$icmp_hosts" != "disable" -a "$ifname" != "x" -a "$ipaddr" != "x" -a "$gateway" != "x" ]; then
835
836 if [ "$icmp_hosts" == "gateway" -o -z "$icmp_hosts" ]; then
837 icmp_hosts_acquire=$gateway
838 elif [ "$icmp_hosts" == "dns" ]; then
839 icmp_hosts_acquire=`uci -q -P /var/state get network.$1.dns`
840 else
841 icmp_hosts_acquire=$icmp_hosts
842 fi
843
844 icmp_hosts=$(echo $icmp_hosts_acquire | sed -e "s/\,/ /g" | sed -e "s/ /\n/g")
845
846 ping_test() {
847 echo "$icmp_hosts" | while read icmp_test_host
848 do
849 ping -c 1 -W $timeout -I $ifname $icmp_test_host 2>&1 | grep -o "round-trip"
850 done
851 }
852
853 check_test=$(ping_test)
854
855 if [ -z "$check_test" ]; then
856 echo "$1.fail" >> $jobfile
857 else
858 echo "$1.pass" >> $jobfile
859 fi
860
861 elif [ "$icmp_hosts" == "disable" ]; then
862 echo "$1.pass" >> $jobfile
863 fi
864
865 sleep $health_interval
866 done
867 }
868
869 bg_task() {
870 local check_iptables
871 local queued_task
872 local bg_counter
873
874 bg_counter=0
875
876 while [ 1 ]; do
877
878 if [ "$bg_counter" -eq 5 ]; then
879
880 check_iptables=$(iptables -n -L MultiWan -t mangle | grep "references" | awk -F "(" '{print $2}' | cut -d " " -f 1)
881
882 if [ -z "$check_iptables" -o "$check_iptables" -lt 4 ]; then
883 mwnote "Netfilter rules appear to of been altered."
884 /etc/init.d/multiwan restart &
885 exit
886 fi
887
888 bg_counter=0
889
890 fi
891
892 if [ -f $jobfile ]; then
893
894 mv $jobfile $jobfile.work
895
896 while read LINE
897 do
898
899 execute_task(){
900 case $2 in
901 fail) fail_wan $1;;
902 pass) recover_wan $1;;
903 acquire) acquire_wan_data $1 && health_monitor $1 &;;
904 refresh) refresh_routes;;
905 esac
906 }
907
908 queued_task=`echo $LINE | awk -F "." '{print $1,$2}'`
909 execute_task $queued_task
910 done < $jobfile.work
911
912 rm $jobfile.work
913 fi
914
915 bg_counter=$(expr $bg_counter + 1)
916
917 sleep 1
918 done
919 }
920
921 fail_start_check(){
922 local ipaddr
923 local gateway
924 local ifname
925 local group
926
927 i=0
928 while [ $i -lt $wancount ]; do
929 i=`expr $i + 1`
930 group=$(query_config group $i)
931 ifname=$(query_config ifname $group)
932 ipaddr=$(query_config ipaddr $group)
933 gateway=$(query_config gateway $group)
934
935 if [ "$ifname" == "x" -o "$ipaddr" == "x" -o "$gateway" == "x" ]; then
936 failover add $group
937 wan_fail_map="echo $wan_fail_map $group[x]"
938 fi
939 done
940 }
941
942 wancount=0
943
944 config_clear
945 config_load "multiwan"
946 config_get default_route config default_route
947 config_get resolv_conf config resolv_conf
948 config_get debug config debug
949
950 config_foreach acquire_wan_data interface
951
952 CHKFORQOS=`iptables -n -L Default -t mangle 2>&1 | grep "Chain Default"`
953
954 jobfile="/tmp/.mwan.jobqueue"
955
956 case $1 in
957 agent) silencer main_init;;
958 restart) silencer stop restart;;
959 stop) silencer stop;;
960 esac
961