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