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