[packages] multiwan: Tweaked probability for random packet selection
[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 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 iptables -t mangle -N MultiWanLoadBalancer
567
568 echo "## Creating FW Rules ##"
569 i=0
570 while [ $i -lt $wancount ]; do
571 i=`expr $i + 1`
572 iprule=$(expr $i \* 10)
573 iptables -t mangle -N FW${i}MARK
574 iptables -t mangle -A FW${i}MARK -j MARK --set-mark 0x${iprule}
575 iptables -t mangle -A FW${i}MARK -j CONNMARK --save-mark
576 done
577
578 iptables -t mangle -A LoadBalancer -j MARK --set-mark 0x123
579 iptables -t mangle -A LoadBalancer -j CONNMARK --save-mark
580
581 iptables -t mangle -I PREROUTING -j MultiWan
582 iptables -t mangle -I PREROUTING 2 -j MultiWanPreHandler
583 iptables -t mangle -I PREROUTING 3 -j MultiWanDNS
584 iptables -t mangle -I PREROUTING 4 -j MultiWanRules
585 iptables -t mangle -I PREROUTING 5 -j MultiWanLoadBalancer
586
587 iptables -t mangle -I FORWARD -j MultiWan
588
589 iptables -t mangle -I OUTPUT -j MultiWan
590 iptables -t mangle -I OUTPUT 2 -j MultiWanDNS
591 iptables -t mangle -I OUTPUT 3 -j MultiWanRules
592 iptables -t mangle -I OUTPUT 4 -j MultiWanLoadBalancer
593 iptables -t mangle -I OUTPUT 5 -j MultiWanPostHandler
594
595
596 iptables -t mangle -I POSTROUTING -j MultiWan
597 iptables -t mangle -I POSTROUTING 2 -j MultiWanPostHandler
598
599 iptables -t mangle -A MultiWan -j CONNMARK --restore-mark
600
601 refresh_dns
602
603 config_load "multiwan"
604 config_foreach mwanrule mwanfw
605
606 if [ "$default_route" != "balancer" ]; then
607 default_route_id=$(query_config wanid $default_route)
608 iptables -t mangle -A MultiWanRules -m mark --mark 0x0 -j FW${default_route_id}MARK
609 else
610 iptables -t mangle -A MultiWanRules -m mark --mark 0x0 -j LoadBalancer
611 fi
612
613 i=0
614 while [ $i -lt $wancount ]; do
615 i=`expr $i + 1`
616 group=$(query_config group $i)
617 ifname=$(query_config ifname $group)
618 iptables -t mangle -A MultiWanPreHandler -i $ifname -m state --state NEW -j FW${i}MARK
619 iptables -t mangle -A MultiWanPostHandler -o $ifname -m mark --mark 0x123 -j FW${i}MARK
620 done
621
622 if [ ! -z "$CHKFORQOS" ]; then
623 iptables -t mangle -I PREROUTING 6 -j MultiWanQoS
624 iptables -t mangle -A FORWARD -j MultiWanQoS
625 iptables -t mangle -A OUTPUT -j MultiWanQoS
626 iptables -t mangle -A POSTROUTING -j MultiWanQoS
627 fi
628 }
629
630 refresh_loadbalancer() {
631 local group
632 local gateway
633 local ifname
634 local failchk
635 local weight
636 local nexthop
637 local pre_nexthop_chk
638 local rand_probability
639 local last_probability
640 local total_weight
641 local i
642
643 echo "## Refreshing Load Balancer ##"
644
645 CHKIPROUTE=`cat /etc/iproute2/rt_tables | grep LoadBalancer`
646 if [ -z "$CHKIPROUTE" ]; then
647 echo "123 LoadBalancer" >> /etc/iproute2/rt_tables
648 fi
649 ip rule del prio 123 > /dev/null 2>&1
650 ip route flush table 123 > /dev/null 2>&1
651
652 for TABLE in 123
653 do
654 ip route | grep link | grep -Ev ^default | while read ROUTE
655 do
656 ip route add table $TABLE to $ROUTE
657 done
658 done
659
660 total_weight=0
661 last_probability=0
662
663 iptables -F MultiWanLoadBalancer -t mangle
664
665 i=0
666 while [ $i -lt $wancount ]; do
667 i=`expr $i + 1`
668 group=$(query_config group $i)
669 failchk=$(query_config failchk $group)
670 gateway=$(query_config gateway $group)
671 ifname=$(query_config ifname $group)
672 weight=`uci -q -P /var/state get multiwan.${group}.weight`
673 if [ "$gateway" != "x" -a "$ifname" != "x" -a "$failchk" != "x" -a "$weight" != "disable" ]; then
674 total_weight=$(expr $total_weight + $weight)
675 fi
676 done
677
678 i=0
679 while [ $i -lt $wancount ]; do
680 i=`expr $i + 1`
681 group=$(query_config group $i)
682 failchk=$(query_config failchk $group)
683 gateway=$(query_config gateway $group)
684 ifname=$(query_config ifname $group)
685
686 weight=`uci -q -P /var/state get multiwan.${group}.weight`
687
688 if [ "$gateway" != "x" -a "$ifname" != "x" -a "$failchk" != "x" -a "$weight" != "disable" ]; then
689 nexthop="$nexthop nexthop via $gateway dev $ifname weight $weight"
690 rand_probability=$(expr $(expr $weight \* 100) / $total_weight + $last_probability)
691 last_probability=$rand_probability
692
693 if [ $rand_probability -lt 10 ]; then
694 rand_probability="0.0${rand_probability}"
695 elif [ $rand_probability -lt 100 ]; then
696 rand_probability="0.${rand_probability}"
697 else
698 rand_probability="1.0"
699 fi
700
701 if [ -z "$CHKFORMODULE" ]; then
702 iptables -A MultiWanLoadBalancer -t mangle -m mark --mark 0x123 -m statistic --mode random --probability $rand_probability -j FW${i}MARK
703 fi
704 fi
705
706 done
707
708 pre_nexthop_chk=`echo $nexthop | awk -F "nexthop" '{print NF-1}'`
709 if [ "$pre_nexthop_chk" == "1" ]; then
710 ip route add default via $(echo $nexthop | awk -F " " '{print $3}') dev $(echo $nexthop | awk -F " " '{print $5}') proto static table 123
711 elif [ "$pre_nexthop_chk" -gt "1" ]; then
712 ip route add proto static table 123 default scope global $nexthop
713 fi
714
715 ip rule add fwmark 0x123 table 123 prio 123
716 ip route flush cache
717 }
718
719 refresh_routes() {
720 local iprule
721 local gateway
722 local group
723 local ifname
724 local ipaddr
725 local i
726
727 echo "## Refreshing Routing Tables ##"
728
729 i=0
730 while [ $i -lt $wancount ]
731 do
732 i=`expr $i + 1`
733 group=$(query_config group $i)
734 gateway=$(query_config gateway $group)
735 ifname=$(query_config ifname $group)
736 ipaddr=$(query_config ipaddr $group)
737
738 iprule=$(expr $i \* 10)
739 ip route flush table $iprule > /dev/null 2>&1
740
741 for TABLE in $iprule
742 do
743 ip route | grep link | grep -Ev ^default | while read ROUTE
744 do
745 ip route add table $TABLE to $ROUTE
746 done
747 done
748
749 if [ "$gateway" != "x" -a "$ipaddr" != "x" -a "$ifname" != "x" ]; then
750 ip route add default via $gateway table $iprule src $ipaddr proto static
751 route add default gw $gateway dev $ifname
752 fi
753 done
754
755 ip route flush cache
756 }
757
758 iprules_config() {
759
760 local iprule
761 local group
762 local gateway
763 local ipaddr
764
765 iprule=$(expr $1 \* 10)
766 group=$(query_config group $1)
767 gateway=$(query_config gateway $group)
768 ipaddr=$(query_config ipaddr $group)
769
770 CHKIPROUTE=`cat /etc/iproute2/rt_tables | grep MWAN${1}`
771 if [ -z "$CHKIPROUTE" ]; then
772 echo "$iprule MWAN${1}" >> /etc/iproute2/rt_tables
773 fi
774
775 ip rule del prio $iprule > /dev/null 2>&1
776 ip rule del prio $(expr $iprule + 1) > /dev/null 2>&1
777
778 if [ "$gateway" != "x" -a "$ipaddr" != "x" ]; then
779 ip rule add from $ipaddr table $iprule prio $iprule
780 ip rule add fwmark 0x${iprule} table $iprule prio $(expr $iprule + 1)
781 fi
782 }
783
784 flush() {
785 local iprule
786 local i
787
788 echo "## Flushing IP Rules & Routes ##"
789
790 ip rule flush > /dev/null 2>&1
791 ip rule add lookup main prio 32766 > /dev/null 2>&1
792 ip rule add lookup default prio 32767 > /dev/null 2>&1
793
794 ip route flush table 123 > /dev/null
795
796 i=0
797 while [ $i -lt $wancount ]; do
798 i=`expr $i + 1`
799 iprule=$(expr $i \* 10)
800 ip route del default > /dev/null 2>&1
801 ip route flush table $iprule > /dev/null 2>&1
802 done
803
804 echo "## Clearing Rules ##"
805 clear_rules > /dev/null 2>&1
806
807 rm $jobfile > /dev/null 2>&1
808 }
809
810 main_init() {
811 local RP_PATH
812 local group
813 local health_interval
814 local i
815
816 echo "## Main Initialization ##"
817
818 mkdir /tmp/.mwan > /dev/null 2>&1
819
820 mwan_kill
821 flush
822
823
824 echo "## IP Rules Initialization ##"
825 i=0
826 while [ $i -lt $wancount ]; do
827 i=`expr $i + 1`
828 iprules_config $i
829 done
830
831 refresh_routes
832 iptables_init
833
834 refresh_loadbalancer
835
836 RP_PATH=/proc/sys/net/ipv4/conf
837 for IFACE in `ls $RP_PATH`; do
838 echo 0 > $RP_PATH/$IFACE/rp_filter
839 done
840 echo "## Initialization Complete, switching to background mode. ##"
841 mwnote "Succesfully Initialized on $(exec date -R)."
842 fail_start_check
843
844 stagger_health_monitors() {
845 i=0
846 while [ $i -lt $wancount ]; do
847 i=`expr $i + 1`
848 group=$(query_config group $i)
849 health_interval=`uci -q -P /var/state get multiwan.${group}.health_interval`
850 if [ ! -z "$health_interval" -a "$health_interval" != "disable" -a "$health_interval" -gt 0 ]; then
851 health_monitor $group &
852 sleep 3
853 fi
854 done
855 }
856
857 stagger_health_monitors &
858 bg_task &
859
860 exit
861 }
862
863 health_monitor() {
864 local ipaddr_cur
865 local gateway_cur
866 local ifname_cur
867 local ifname
868 local ipaddr
869 local gateway
870 local failchk
871 local icmp_hosts
872 local icmp_hosts_acquire
873 local default_routes_check
874 local icmp_test_host
875 local timeout
876 local check_test
877 local health_interval
878 local check_for_job
879
880 . /tmp/.mwan/cache
881
882 timeout=`uci -q -P /var/state get multiwan.${1}.timeout`
883 icmp_hosts=`uci -q -P /var/state get multiwan.${1}.icmp_hosts`
884 health_interval=`uci -q -P /var/state get multiwan.${1}.health_interval`
885 ifname_cur=$(query_config ifname $1)
886 ipaddr_cur=$(query_config ipaddr $1)
887 gateway_cur=$(query_config gateway $1)
888
889 while [ 1 ]; do
890
891 ifname=`uci -q -P /var/state get network.${1}.ifname`
892 ipaddr=`uci -q -P /var/state get network.${1}.ipaddr`
893 gateway=`uci -q -P /var/state get network.${1}.gateway`
894
895 if [ -z "$ifname" ]; then
896 ifname="x"
897 fi
898
899 if [ -z "$ipaddr" ]; then
900 ipaddr="x"
901 fi
902
903 if [ -z "$gateway" ]; then
904 gateway="x"
905 fi
906
907 if [ "$ifname_cur" != "$ifname" -o "$ipaddr_cur" != "$ipaddr" -o "$gateway_cur" != "$gateway" ]; then
908 echo $1.acquire >> $jobfile
909 exit
910 else
911 if [ "$gateway" != "x" ]; then
912 default_routes_check=`ip route | grep -o $gateway`
913 if [ -z "$default_routes_check" ]; then
914 check_for_job=`cat $jobfile 2>&1 | grep -o "route.refresh"`
915 if [ -z "$check_for_job" ]; then
916 echo route.refresh >> $jobfile
917 fi
918 fi
919 fi
920 fi
921
922 if [ "$icmp_hosts" != "disable" -a "$ifname" != "x" -a "$ipaddr" != "x" -a "$gateway" != "x" ]; then
923
924 if [ "$icmp_hosts" == "gateway" -o -z "$icmp_hosts" ]; then
925 icmp_hosts_acquire=$gateway
926 elif [ "$icmp_hosts" == "dns" ]; then
927 icmp_hosts_acquire=`uci -q -P /var/state get multiwan.$1.dns`
928 if [ -z "$icmp_hosts_acquire" -o "$icmp_hosts_acquire" == "auto" ]; then
929 icmp_hosts_acquire=`uci -q -P /var/state get network.$1.dns`
930 fi
931 else
932 icmp_hosts_acquire=$icmp_hosts
933 fi
934
935 icmp_hosts=$(echo $icmp_hosts_acquire | sed -e "s/\,/ /g" | sed -e "s/ /\n/g")
936
937 ping_test() {
938 echo "$icmp_hosts" | while read icmp_test_host
939 do
940 ping -c 1 -W $timeout -I $ifname $icmp_test_host 2>&1 | grep -o "round-trip"
941 done
942 }
943
944 check_test=$(ping_test)
945
946 if [ -z "$check_test" ]; then
947 echo "$1.fail" >> $jobfile
948 else
949 echo "$1.pass" >> $jobfile
950 fi
951
952 elif [ "$icmp_hosts" == "disable" ]; then
953 echo "$1.pass" >> $jobfile
954 fi
955
956 sleep $health_interval
957 done
958 }
959
960 bg_task() {
961 local check_iptables
962 local queued_task
963 local bg_counter
964 local current_resolv_file
965
966 bg_counter=0
967
968 while [ 1 ]; do
969
970 . /tmp/.mwan/cache
971
972 if [ "$bg_counter" -eq 5 ]; then
973
974 check_iptables=$(iptables -n -L MultiWan -t mangle | grep "references" | awk -F "(" '{print $2}' | cut -d " " -f 1)
975
976 if [ -z "$check_iptables" -o "$check_iptables" -lt 4 ]; then
977 mwnote "Netfilter rules appear to of been altered."
978 /etc/init.d/multiwan restart &
979 exit
980 fi
981
982 current_resolv_file=$(ls -l -e /tmp/resolv.conf.auto | awk -F " " '{print $5, $9}')
983
984 if [ "$last_resolv_update" != "$current_resolv_file" ]; then
985 refresh_dns
986 fi
987
988 bg_counter=0
989
990 fi
991
992 if [ -f $jobfile ]; then
993
994 mv $jobfile $jobfile.work
995
996 while read LINE
997 do
998
999 execute_task(){
1000 case $2 in
1001 fail) fail_wan $1;;
1002 pass) recover_wan $1;;
1003 acquire) acquire_wan_data $1 && health_monitor $1 &;;
1004 refresh) refresh_routes;;
1005 esac
1006 }
1007
1008 queued_task=`echo $LINE | awk -F "." '{print $1,$2}'`
1009 execute_task $queued_task
1010 done < $jobfile.work
1011
1012 rm $jobfile.work
1013 fi
1014
1015 bg_counter=$(expr $bg_counter + 1)
1016
1017 sleep 1
1018 done
1019 }
1020
1021 fail_start_check(){
1022 local ipaddr
1023 local gateway
1024 local ifname
1025 local group
1026
1027 i=0
1028 while [ $i -lt $wancount ]; do
1029 i=`expr $i + 1`
1030 group=$(query_config group $i)
1031 ifname=$(query_config ifname $group)
1032 ipaddr=$(query_config ipaddr $group)
1033 gateway=$(query_config gateway $group)
1034
1035 if [ "$ifname" == "x" -o "$ipaddr" == "x" -o "$gateway" == "x" ]; then
1036 failover add $group
1037 fi
1038 done
1039 }
1040
1041 wancount=0
1042
1043 config_clear
1044 config_load "multiwan"
1045 config_get default_route config default_route
1046 config_get debug config debug
1047
1048 config_foreach acquire_wan_data interface
1049
1050 update_cache
1051
1052 CHKFORQOS=`iptables -n -L Default -t mangle 2>&1 | grep "Chain Default"`
1053 CHKFORMODULE=`iptables -m statistic 2>&1 | grep -o "File not found"`
1054
1055 jobfile="/tmp/.mwan/jobqueue"
1056
1057 case $1 in
1058 agent) silencer main_init;;
1059 restart) silencer stop restart;;
1060 stop) silencer stop;;
1061 esac
1062