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