[packages] add multiwan, a simple to use multi wan configuration agent

git-svn-id: svn://svn.openwrt.org/openwrt/packages@20925 3c298f89-4303-0410-b956-a3cf2f4a3e73
This commit is contained in:
jow 2010-04-16 16:05:03 +00:00
parent fe9300a06e
commit 4df8439004
4 changed files with 1080 additions and 0 deletions

41
net/multiwan/Makefile Normal file
View File

@ -0,0 +1,41 @@
#
# Copyright (C) 2010 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=multiwan
PKG_VERSION:=1.0k
PKG_RELEASE:=1
include $(INCLUDE_DIR)/package.mk
define Package/multiwan
SECTION:=net
CATEGORY:=Network
DEPENDS:=+ip +iptables +iptables-utils +iptables-mod-conntrack +iptables-mod-conntrack-extra
TITLE:=Simple multi WAN configuration
URL:=ftp://ftp.netlab7.com/
endef
define Package/multiwan/description
An agent script that makes Multi-WAN configuration simple,
easy and manageable. Complete with load balancing, failover and an easy
to manage traffic ruleset. Allows for configuration of up to 9 wan links.
endef
define Package/multiwan/conffiles
/etc/config/multiwan
endef
define Build/Compile
endef
define Package/multiwan/install
$(CP) ./files/* $(1)
endef
$(eval $(call BuildPackage,multiwan))

View File

@ -0,0 +1,63 @@
config 'multiwan' 'config'
option 'default_route' 'balancer'
option 'resolv_conf' '/tmp/resolv.conf.auto'
config 'interface' 'wan'
option 'weight' '5'
option 'health_interval' '10'
option 'icmp_hosts' 'dns'
option 'timeout' '3'
option 'health_fail_retries' '3'
option 'health_recovery_retries' '5'
option 'failover_to' 'balancer'
config 'interface' 'wan2'
option 'weight' '5'
option 'health_interval' '10'
option 'icmp_hosts' 'dns'
option 'timeout' '3'
option 'health_fail_retries' '3'
option 'health_recovery_retries' '5'
option 'failover_to' 'wan3'
config 'interface' 'wan3'
option 'weight' 'disable'
option 'health_interval' 'disable'
option 'icmp_hosts' 'gateway'
option 'timeout' '3'
option 'health_fail_retries' '3'
option 'health_recovery_retries' '5'
option 'failover_to' 'disable'
config 'interface' 'wan4'
option 'weight' '3'
option 'health_interval' '20'
option 'icmp_hosts' '208.67.222.222 208.67.220.220'
option 'timeout' '3'
option 'health_fail_retries' '3'
option 'health_recovery_retries' '5'
option 'failover_to' 'wan'
config 'mwanfw'
option 'src' '192.168.1.0/24'
option 'dst' 'ftp.netlab7.com'
option 'proto' 'tcp'
option 'ports' '21'
option 'wanrule' 'wan4'
config 'mwanfw'
option 'proto' 'tcp'
option 'ports' '21'
option 'wanrule' 'wan2'
config 'mwanfw'
option 'src' '192.168.0.3'
option 'proto' 'icmp'
option 'wanrule' 'wan'
config 'mwanfw'
option 'dst' 'www.whatismyip.com'
option 'wanrule' 'balancer'

View File

@ -0,0 +1,15 @@
#!/bin/sh /etc/rc.common
START=99
start () {
sh /usr/bin/multiwan agent
}
stop () {
sh /usr/bin/multiwan stop
}
restart () {
sh /usr/bin/multiwan restart
}

View File

@ -0,0 +1,961 @@
#!/bin/sh
. /etc/functions.sh
silencer() {
if [ -z "$debug" -o "$debug" == "0" ]; then
$* > /dev/null 2>&1
else
$*
fi
}
mwnote() {
logger "[Multi-WAN Notice]: $1"
}
failover() {
local failover_to
local failover_to_wanid
local failchk
local wanid
local existing_failover
wanid=$(query_config wanid $2)
failover_to=`uci -q -P /var/state get multiwan.${2}.failover_to`
failover_to_wanid=$(query_config wanid $failover_to)
existing_failover=$(iptables -n -L FW${wanid}MARK -t mangle | echo $(expr $(wc -l) - 2))
add() {
if [ "$existing_failover" == "2" ]; then
if [ "$failover_to" != "balancer" -a "$failover_to" != "disable" -a "$failover_to_wanid" != "$wanid" ]; then
iptables -I FW${wanid}MARK 2 -t mangle -j FW${failover_to_wanid}MARK
elif [ "$failover_to" == "balancer" ]; then
iptables -I FW${wanid}MARK 2 -t mangle -j LoadBalancer
fi
fi
mwnote "$1 has failed and is currently offline."
}
del() {
if [ "$existing_failover" == "3" ]; then
if [ "$failover_to" != "balancer" -a "failover_to" != "disable" -a "$failover_to_wanid" != "$wanid" ]; then
iptables -D FW${wanid}MARK -t mangle -j FW${failover_to_wanid}MARK
elif [ "$failover_to" == "balancer" ]; then
iptables -D FW${wanid}MARK -t mangle -j LoadBalancer
fi
fi
mwnote "$1 has recovered and is back online!"
}
case $1 in
add) add $2;;
del) del $2;;
esac
}
fail_wan() {
local failchk
local recvrychk
local new_fail_count
local health_fail_retries
local weight
health_fail_retries=`uci -q -P /var/state get multiwan.${1}.health_fail_retries`
weight=`uci -q -P /var/state get multiwan.${1}.weight`
failchk=$(query_config failchk $1)
recvrychk=$(query_config recvrychk $1)
wan_recovery_map=$(echo $wan_recovery_map | sed -e "s/${1}\[${recvrychk}\]//g")
if [ -z "$failchk" ]; then
wan_fail_map="$wan_fail_map $1[1]"
if [ "$health_fail_retries" == "1" ]; then
fail_wan $1
fi
else
if [ "$failchk" != "x" ]; then
new_fail_count=$(expr $failchk + 1)
if [ "$new_fail_count" -lt "$health_fail_retries" ]; then
wan_fail_map=$(echo $wan_fail_map | sed -e "s/${1}\[${failchk}\]/$1\[${new_fail_count}\]/g")
else
wan_fail_map=$(echo $wan_fail_map | sed -e "s/${1}\[${failchk}\]/$1\[x\]/g")
if [ "$weight" != "disable" ]; then
refresh_loadbalancer
fi
refresh_dns
failover add $1
fi
fi
fi
}
recover_wan() {
local failchk
local recvrychk
local new_fail_count
local wanid
local health_recovery_retires
local weight
health_recovery_retries=`uci -q -P /var/state get multiwan.${1}.health_recovery_retries`
weight=`uci -q -P /var/state get multiwan.${1}.weight`
failchk=$(query_config failchk $1)
recvrychk=$(query_config recvrychk $1)
wanid=$(query_config wanid $1)
if [ "$failchk" == "x" ]; then
if [ -z "$recvrychk" ]; then
wan_recovery_map="$wan_recovery_map $1[1]"
if [ "$health_recovery_retries" == "1" ]; then
recover_wan $1
fi
else
new_recovery_count=$(expr $recvrychk + 1)
if [ "$new_recovery_count" -lt "$health_recovery_retries" ]; then
wan_recovery_map=$(echo $wan_recovery_map | sed -e "s/${1}\[${recvrychk}\]/$1\[${new_recovery_count}\]/g")
else
wan_recovery_map=$(echo $wan_recovery_map | sed -e "s/${1}\[${recvrychk}\]//g")
wan_fail_map=$(echo $wan_fail_map | sed -e "s/${1}\[${failchk}\]//g")
if [ "$weight" != "disable" ]; then
refresh_loadbalancer
fi
refresh_dns
failover del $1
fi
fi
fi
}
acquire_wan_data() {
if [ $wancount -lt 9 ]; then
local ipaddr
local gateway
local ifname
local check_old_map
local get_wanid
local old_ifname
local old_ipaddr
local old_gateway
ifname=`uci -q -P /var/state get network.${1}.ifname`
ipaddr=`uci -q -P /var/state get network.${1}.ipaddr`
gateway=`uci -q -P /var/state get network.${1}.gateway`
if [ -z "$ifname" ]; then
ifname="x"
fi
if [ -z "$ipaddr" ]; then
ipaddr="x"
fi
if [ -z "$gateway" ]; then
gateway="x"
fi
check_old_map=`echo $wan_id_map 2>&1 | grep -o "$1\["`
if [ -z $check_old_map ]; then
wancount=`expr $wancount + 1`
wan_if_map="$wan_if_map $1[${ifname}] "
wan_id_map="$wan_id_map $1[${wancount}] "
wan_gw_map="$wan_gw_map $1[${gateway}] "
wan_ip_map="$wan_ip_map $1[${ipaddr}] "
else
old_ipaddr=$(query_config ipaddr $1)
old_gateway=$(query_config gateway $1)
old_ifname=$(query_config ifname $1)
get_wanid=$(query_config wanid $1)
wan_if_map=$(echo $wan_if_map | sed -e "s/${1}\[${old_ifname}\]/$1\[${ifname}\]/g")
wan_ip_map=$(echo $wan_ip_map | sed -e "s/${1}\[${old_ipaddr}\]/$1\[${ipaddr}\]/g")
wan_gw_map=$(echo $wan_gw_map | sed -e "s/${1}\[${old_gateway}\]/$1\[${gateway}\]/g")
if [ "$old_ifname" != "$ifname" ]; then
iptables -D MultiWanPreHandler -t mangle -i $old_$ifname -m state --state NEW -j FW${get_wanid}MARK
iptables -A MultiWanPreHandler -t mangle -i $ifname -m state --state NEW -j FW${get_wanid}MARK
iptables -D MultiWanPostHandler -t mangle -o $old_$ifname -m mark --mark 0x123 -j FW${get_wanid}MARK
iptables -A MultiWanPostHandler -t mangle -o $ifname -m mark --mark 0x123 -j FW${get_wanid}MARK
fi
refresh_routes
refresh_loadbalancer
refresh_dns
if [ "$ifname" != "x" -a "$ipaddr" != "x" -a "$gateway" != "x" ]; then
iprules_config $get_wanid
qos_init $1 $get_wanid
failover del $1
else
failover add $1
fi
fi
else
wancount=9
fi
}
query_config() {
case $1 in
ifname) echo $wan_if_map | grep -o "$2\[\w*.*\]" | awk -F "[" '{print $2}' | awk -F "]" '{print $1}';;
ipaddr) echo $wan_ip_map | grep -o "$2\[\w*.*\]" | awk -F "[" '{print $2}' | awk -F "]" '{print $1}';;
gateway) echo $wan_gw_map | grep -o "$2\[\w*.*\]" | awk -F "[" '{print $2}' | awk -F "]" '{print $1}';;
wanid) echo $wan_id_map | grep -o "$2\[\w*.*\]" | awk -F "[" '{print $2}' | awk -F "]" '{print $1}';;
failchk) echo $wan_fail_map | grep -o "$2\[\w*.*\]" | awk -F "[" '{print $2}' | awk -F "]" '{print $1}';;
recvrychk) echo $wan_recovery_map | grep -o "$2\[\w*.*\]" | awk -F "[" '{print $2}' | awk -F "]" '{print $1}';;
group) echo $wan_id_map | grep -o "\w*\[$2\]" | awk -F "[" '{print $1}';;
esac
}
mwan_kill() {
local otherpids
local execute
otherpids=$(ps -a 2>&1 | grep 'multiwan agent' | grep -v $$ | awk -F " " '{print $1}')
echo "$otherpids" | while read execute
do
kill -9 ${execute} > /dev/null 2>&1
done
}
stop() {
local group
local i
mwan_kill
flush
if [ "$1" != "restart" ]; then
echo "## Refreshing Interfaces ##"
i=0
while [ $i -lt $wancount ]; do
i=`expr $i + 1`
group=$(query_config group $i)
fdown $group > /dev/null 2>&1
ifup $group > /dev/null 2>&1 &
done
if [ ! -z "$CHKFORQOS" ]; then
/etc/init.d/qos restart & > /dev/null 2>&1
fi
echo "## Unloaded, updating syslog and exiting. ##"
mwnote "Succesfully Unloaded on $(exec date -R)."
else
echo "## Restarting Multi-WAN. ##"
mwnote "Reinitializing Multi-WAN Configuration."
/etc/init.d/multiwan start & > /dev/null 2>&1
fi
ip route flush cache
exit
}
clear_rules() {
local group
local i
iptables -t mangle -F PREROUTING
iptables -t mangle -F FORWARD
iptables -t mangle -F POSTROUTING
iptables -t mangle -F OUTPUT
iptables -t mangle -F MultiWan
iptables -t mangle -X MultiWan
iptables -t mangle -F MultiWanRules
iptables -t mangle -X MultiWanRules
iptables -t mangle -F MultiWanDNS
iptables -t mangle -X MultiWanDNS
iptables -t mangle -F MultiWanPreHandler
iptables -t mangle -X MultiWanPreHandler
iptables -t mangle -F MultiWanPostHandler
iptables -t mangle -X MultiWanPostHandler
iptables -t mangle -F LoadBalancer
iptables -t mangle -X LoadBalancer
i=0
while [ $i -lt $wancount ]; do
i=`expr $i + 1`
iptables -t mangle -F FW${i}MARK
done
i=0
while [ $i -lt $wancount ]; do
i=`expr $i + 1`
iptables -t mangle -X FW${i}MARK
done
if [ ! -z "$CHKFORQOS" ]; then
iptables -t mangle -F MultiWanQoS
iptables -t mangle -X MultiWanQoS
i=0
while [ $i -lt $wancount ]; do
i=`expr $i + 1`
group=$(query_config group $i)
iptables -t mangle -F MultiWanQoS_${group}
iptables -t mangle -F MultiWanQoS_${group}_ct
iptables -t mangle -X MultiWanQoS_${group}
iptables -t mangle -X MultiWanQoS_${group}_ct
done
fi
}
qos_init() {
local ifname
local queue_count
local get_wan_tc
local get_wan_iptables
local qos_done_chk
local add_qos_iptables
local add_qos_tc
local execute
local i
local p
qos_done_chk=`echo $qos_done | grep -o "$1\."`
if [ ! -z "$qos_done_chk" ]; then
return
fi
ifname=$(query_config ifname $1)
if [ "$ifname" == "x" ]; then
return
fi
queue_count=$(tc filter list dev $ifname | tail -n 1 | awk -F " " '{print $10}' | sed "s/0x//g")
if [ -z "$queue_count" ]; then
return
fi
queue_count=`expr $queue_count + 1`
iptables -t mangle -N MultiWanQoS_${1}
iptables -t mangle -N MultiWanQoS_${1}_ct
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")
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")
rm /tmp/.mwan.$1.sedfilter > /dev/null 2>&1
i=0
while [ $i -lt $queue_count ]; do
echo "s/\(0x$i \|0x$i\/0xffffffff\)/0x${2}${i} /g" >> /tmp/.mwan.$1.sedfilter
i=`expr $i + 1`
done
add_qos_iptables=$(echo "$get_wan_iptables" | sed -f /tmp/.mwan.$1.sedfilter)
echo "$add_qos_iptables" | while read execute; do ${execute}; done
rm /tmp/.mwan.$1.sedfilter
i=1
while [ $i -lt $queue_count ]; do
echo "s/0x$i /0x${2}${i} fw /g" >> /tmp/.mwan.$1.sedfilter
i=`expr $i + 1`
done
add_qos_tc=$(echo "$get_wan_tc" | sed -f /tmp/.mwan.$1.sedfilter)
echo "$add_qos_tc" | while read execute; do ${execute}; done
rm /tmp/.mwan.$1.sedfilter
i=0
while [ $i -lt $queue_count ]; do
p=`expr $i + $2 \* 10`
if [ $i -lt $(expr $queue_count - 1) ]; then
ip rule add fwmark 0x$(expr $p + 1) table $(expr $2 \* 10) prio $(expr $p + 2)
fi
iptables -t mangle -A MultiWanQoS -m mark --mark 0x$p -j MultiWanQoS_${1}
i=`expr $i + 1`
done
qos_done="$qos_done $1."
}
mwanrule() {
local src
local dst
local ports
local proto
local wanrule
config_get src $1 src
config_get dst $1 dst
config_get ports $1 ports
config_get proto $1 proto
config_get wanrule $1 wanrule
ports_first=${ports%-*}
ports_last=${ports#*-}
if [ -z "$wanrule" ]; then
return
fi
if [ "$wanrule" != "balancer" ]; then
wanrule=$(query_config wanid ${wanrule})
wanrule="FW${wanrule}MARK"
elif [ "$wanrule" == "balancer" ]; then
wanrule="LoadBalancer"
fi
if [ "$dst" == "all" ]; then
dst=$NULL
fi
if [ "$proto" == "all" ]; then
proto=$NULL
fi
if [ "$ports" == "all" ]; then
ports=$NULL
fi
if [ "$ports_first" -ne "$ports_last" ]; then
ports="$ports_first:$ports_last"
fi
add_rule() {
if [ "$proto" == "icmp" ]; then
ports=$NULL
fi
if [ "$src" == "all" ]; then
src=$NULL
fi
iptables -t mangle -A MultiWanRules -m mark --mark 0x0\
${proto:+-p $proto} \
${src:+-s $src} \
${dst:+-d $dst} \
${ports:+--dport $ports} \
-j $wanrule
}
if [ -z "$proto" -a ! -z "$ports" ]; then
proto=tcp
add_rule
proto=udp
add_rule
return
fi
add_rule
}
refresh_dns() {
local dns
local group
local ipaddr
local gateway
local ifname
local failchk
local compile_dns
local resolv_conf
local dns_server
local i
iptables -F MultiWanDNS -t mangle
rm $resolv_conf
touch $resolv_conf
echo "## Refreshing DNS Resolution and Tables ##"
i=0
while [ $i -lt $wancount ]; do
i=`expr $i + 1`
group=$(query_config group $i)
gateway=$(query_config gateway $group)
ipaddr=$(query_config ipaddr $group)
ifname=$(query_config ifname $group)
failchk=$(query_config failchk $group)
dns=`uci -q -P /var/state get network.${group}.dns`
dns=$(echo $dns | sed -e "s/ /\n/g")
if [ ! -z "$dns" -a "$failchk" != "x" -a "$ipaddr" != "x" -a "$gateway" != "x" -a "$ifname" != "x" ]; then
echo "$dns" | while read dns_server
do
iptables -t mangle -A MultiWanDNS -d $dns_server -p UDP --dport 53 -j FW${i}MARK
compile_dns="nameserver $dns_server"
echo "$compile_dns" >> $resolv_conf
done
fi
done
}
iptables_init() {
echo "## IPTables Rule Initialization ##"
local iprule
local group
local ifname
local execute
local IMQ_NFO
local default_route_id
local i
if [ ! -z "$CHKFORQOS" ]; then
echo "## QoS Initialization ##"
/etc/init.d/qos restart > /dev/null 2>&1
IMQ_NFO=`iptables -n -L PREROUTING -t mangle -v | grep IMQ | awk -F " " '{print $6,$12}'`
iptables -t mangle -F PREROUTING
iptables -t mangle -F FORWARD
iptables -t mangle -F POSTROUTING
iptables -t mangle -F OUTPUT
echo "$IMQ_NFO" | while read execute
do
iptables -t mangle -A PREROUTING -i $(echo $execute | awk -F " " '{print $1}') -j IMQ --todev $(echo $execute | awk -F " " '{print $2}')
done
iptables -t mangle -N MultiWanQoS
i=0
while [ $i -lt $wancount ]; do
i=`expr $i + 1`
qos_init $(query_config group $i) $i
done
fi
iptables -t mangle -N MultiWan
iptables -t mangle -N LoadBalancer
iptables -t mangle -N MultiWanRules
iptables -t mangle -N MultiWanDNS
iptables -t mangle -N MultiWanPreHandler
iptables -t mangle -N MultiWanPostHandler
echo "## Creating FW Rules ##"
i=0
while [ $i -lt $wancount ]; do
i=`expr $i + 1`
iprule=$(expr $i \* 10)
iptables -t mangle -N FW${i}MARK
iptables -t mangle -A FW${i}MARK -j MARK --set-mark 0x${iprule}
iptables -t mangle -A FW${i}MARK -j CONNMARK --save-mark
done
iptables -t mangle -A LoadBalancer -j MARK --set-mark 0x123
iptables -t mangle -A LoadBalancer -j CONNMARK --save-mark
iptables -t mangle -I PREROUTING -j MultiWan
iptables -t mangle -I FORWARD -j MultiWan
iptables -t mangle -I OUTPUT -j MultiWan
iptables -t mangle -I POSTROUTING -j MultiWan
iptables -t mangle -A MultiWan -j CONNMARK --restore-mark
iptables -t mangle -A MultiWan -j MultiWanPreHandler
refresh_dns
config_load "multiwan"
config_foreach mwanrule mwanfw
if [ "$default_route" != "balancer" ]; then
default_route_id=$(query_config wanid $default_route)
iptables -t mangle -A MultiWanRules -m mark --mark 0x0 -j FW${default_route_id}MARK
else
iptables -t mangle -A MultiWanRules -m mark --mark 0x0 -j LoadBalancer
fi
iptables -t mangle -A MultiWan -j MultiWanRules
iptables -t mangle -A MultiWan -j MultiWanDNS
iptables -t mangle -A MultiWan -j MultiWanPostHandler
i=0
while [ $i -lt $wancount ]; do
i=`expr $i + 1`
group=$(query_config group $i)
ifname=$(query_config ifname $group)
iptables -t mangle -A MultiWanPreHandler -i $ifname -m state --state NEW -j FW${i}MARK
iptables -t mangle -A MultiWanPostHandler -o $ifname -m mark --mark 0x123 -j FW${i}MARK
done
if [ ! -z "$CHKFORQOS" ]; then
iptables -t mangle -A MultiWan -j MultiWanQoS
fi
}
refresh_loadbalancer() {
local group
local gateway
local ifname
local failchk
local weight
local nexthop
local pre_nexthop_chk
local i
echo "## Refreshing Load Balancer ##"
CHKIPROUTE=`cat /etc/iproute2/rt_tables | grep LoadBalancer`
if [ -z "$CHKIPROUTE" ]; then
echo "123 LoadBalancer" >> /etc/iproute2/rt_tables
fi
ip rule del prio 123 > /dev/null 2>&1
ip route flush table 123 > /dev/null 2>&1
for TABLE in 123
do
ip route | grep link | while read ROUTE
do
ip route add table $TABLE to $ROUTE
done
done
i=0
while [ $i -lt $wancount ]; do
i=`expr $i + 1`
group=$(query_config group $i)
failchk=$(query_config failchk $group)
gateway=$(query_config gateway $group)
ifname=$(query_config ifname $group)
weight=`uci -q -P /var/state get multiwan.${group}.weight`
if [ "$gateway" != "x" -a "$ifname" != "x" -a "$failchk" != "x" -a "$weight" != "disable" ]; then
nexthop="$nexthop nexthop via $gateway dev $ifname weight $weight"
fi
done
pre_nexthop_chk=`echo $nexthop | awk -F "nexthop" '{print NF-1}'`
if [ "$pre_nexthop_chk" == "1" ]; then
ip route add default via $(echo $nexthop | awk -F " " '{print $3}') dev $(echo $nexthop | awk -F " " '{print $5}') proto static table 123
elif [ "$pre_nexthop_chk" -gt "1" ]; then
ip route add proto static table 123 default scope global $nexthop
fi
ip rule add fwmark 0x123 table 123 prio 123
ip route flush cache
}
refresh_routes() {
local iprule
local gateway
local group
local ifname
local ipaddr
local i
echo "## Refreshing Routing Tables ##"
i=0
while [ $i -lt $wancount ]
do
i=`expr $i + 1`
group=$(query_config group $i)
gateway=$(query_config gateway $group)
ifname=$(query_config ifname $group)
ipaddr=$(query_config ipaddr $group)
iprule=$(expr $i \* 10)
ip route flush table $iprule > /dev/null 2>&1
for TABLE in $iprule
do
ip route | grep link | while read ROUTE
do
ip route add table $TABLE to $ROUTE
done
done
if [ "$gateway" != "x" -a "$ipaddr" != "x" -a "$ifname" != "x" ]; then
ip route add default via $gateway table $iprule src $ipaddr proto static
route add default gw $gateway dev $ifname
fi
done
ip route flush cache
}
iprules_config() {
local iprule
local group
local gateway
local ipaddr
iprule=$(expr $1 \* 10)
group=$(query_config group $1)
gateway=$(query_config gateway $group)
ipaddr=$(query_config ipaddr $group)
CHKIPROUTE=`cat /etc/iproute2/rt_tables | grep MWAN${1}`
if [ -z "$CHKIPROUTE" ]; then
echo "$iprule MWAN${1}" >> /etc/iproute2/rt_tables
fi
ip rule del prio $iprule > /dev/null 2>&1
ip rule del prio $(expr $iprule + 1) > /dev/null 2>&1
if [ "$gateway" != "x" -a "$ipaddr" != "x" ]; then
ip rule add from $ipaddr table $iprule prio $iprule
ip rule add fwmark 0x${iprule} table $iprule prio $(expr $iprule + 1)
fi
}
flush() {
local iprule
local i
echo "## Flushing IP Rules & Routes ##"
ip rule flush > /dev/null 2>&1
ip rule add lookup main prio 32766 > /dev/null 2>&1
ip rule add lookup default prio 32767 > /dev/null 2>&1
ip route flush table 123 > /dev/null
i=0
while [ $i -lt $wancount ]; do
i=`expr $i + 1`
iprule=$(expr $i \* 10)
ip route del default > /dev/null 2>&1
ip route flush table $iprule > /dev/null 2>&1
done
echo "## Clearing Rules ##"
clear_rules > /dev/null 2>&1
rm $jobfile > /dev/null 2>&1
}
main_init() {
local RP_PATH
local group
local health_interval
local i
echo "## Main Initialization ##"
mwan_kill
flush
refresh_loadbalancer
echo "## IP Rules Initialization ##"
i=0
while [ $i -lt $wancount ]; do
i=`expr $i + 1`
iprules_config $i
done
refresh_routes
iptables_init
RP_PATH=/proc/sys/net/ipv4/conf
for IFACE in `ls $RP_PATH`; do
echo 0 > $RP_PATH/$IFACE/rp_filter
done
echo "## Initialization Complete, switching to background mode. ##"
mwnote "Succesfully Initialized on $(exec date -R)."
fail_start_check
stagger_health_monitors() {
i=0
while [ $i -lt $wancount ]; do
i=`expr $i + 1`
group=$(query_config group $i)
health_interval=`uci -q -P /var/state get multiwan.${group}.health_interval`
if [ ! -z "$health_interval" -a "$health_interval" != "disable" -a "$health_interval" -gt 0 ]; then
health_monitor $group &
sleep 3
fi
done
}
stagger_health_monitors &
bg_task &
exit
}
health_monitor() {
local ipaddr_cur
local gateway_cur
local ifname_cur
local ifname
local ipaddr
local gateway
local failchk
local icmp_hosts
local icmp_hosts_acquire
local default_routes_check
local icmp_test_host
local timeout
local check_test
local health_interval
local check_for_job
timeout=`uci -q -P /var/state get multiwan.${1}.timeout`
icmp_hosts=`uci -q -P /var/state get multiwan.${1}.icmp_hosts`
health_interval=`uci -q -P /var/state get multiwan.${1}.health_interval`
ifname_cur=$(query_config ifname $1)
ipaddr_cur=$(query_config ipaddr $1)
gateway_cur=$(query_config gateway $1)
while [ 1 ]; do
ifname=`uci -q -P /var/state get network.${1}.ifname`
ipaddr=`uci -q -P /var/state get network.${1}.ipaddr`
gateway=`uci -q -P /var/state get network.${1}.gateway`
if [ -z "$ifname" ]; then
ifname="x"
fi
if [ -z "$ipaddr" ]; then
ipaddr="x"
fi
if [ -z "$gateway" ]; then
gateway="x"
fi
if [ "$ifname_cur" != "$ifname" -o "$ipaddr_cur" != "$ipaddr" -o "$gateway_cur" != "$gateway" ]; then
echo $1.acquire >> $jobfile
exit
else
if [ "$gateway" != "x" ]; then
default_routes_check=`ip route | grep -o $gateway`
if [ -z "$default_routes_check" ]; then
check_for_job=`cat $jobfile 2>&1 | grep -o "route.refresh"`
if [ -z "$check_for_job" ]; then
echo route.refresh >> $jobfile
fi
fi
fi
fi
if [ "$icmp_hosts" != "disable" -a "$ifname" != "x" -a "$ipaddr" != "x" -a "$gateway" != "x" ]; then
if [ "$icmp_hosts" == "gateway" -o -z "$icmp_hosts" ]; then
icmp_hosts_acquire=$gateway
elif [ "$icmp_hosts" == "dns" ]; then
icmp_hosts_acquire=`uci -q -P /var/state get network.$1.dns`
else
icmp_hosts_acquire=$icmp_hosts
fi
icmp_hosts=$(echo $icmp_hosts_acquire | sed -e "s/\,/ /g" | sed -e "s/ /\n/g")
ping_test() {
echo "$icmp_hosts" | while read icmp_test_host
do
ping -c 1 -W $timeout -I $ifname $icmp_test_host 2>&1 | grep -o "round-trip"
done
}
check_test=$(ping_test)
if [ -z "$check_test" ]; then
echo "$1.fail" >> $jobfile
else
echo "$1.pass" >> $jobfile
fi
elif [ "$icmp_hosts" == "disable" ]; then
echo "$1.pass" >> $jobfile
fi
sleep $health_interval
done
}
bg_task() {
local check_iptables
local queued_task
local bg_counter
bg_counter=0
while [ 1 ]; do
if [ "$bg_counter" -eq 5 ]; then
check_iptables=$(iptables -n -L MultiWan -t mangle | grep "references" | awk -F "(" '{print $2}' | cut -d " " -f 1)
if [ -z "$check_iptables" -o "$check_iptables" -lt 4 ]; then
mwnote "Netfilter rules appear to of been altered."
/etc/init.d/multiwan restart &
exit
fi
bg_counter=0
fi
if [ -f $jobfile ]; then
mv $jobfile $jobfile.work
while read LINE
do
execute_task(){
case $2 in
fail) fail_wan $1;;
pass) recover_wan $1;;
acquire) acquire_wan_data $1 && health_monitor $1 &;;
refresh) refresh_routes;;
esac
}
queued_task=`echo $LINE | awk -F "." '{print $1,$2}'`
execute_task $queued_task
done < $jobfile.work
rm $jobfile.work
fi
bg_counter=$(expr $bg_counter + 1)
sleep 1
done
}
fail_start_check(){
local ipaddr
local gateway
local ifname
local group
i=0
while [ $i -lt $wancount ]; do
i=`expr $i + 1`
group=$(query_config group $i)
ifname=$(query_config ifname $group)
ipaddr=$(query_config ipaddr $group)
gateway=$(query_config gateway $group)
if [ "$ifname" == "x" -o "$ipaddr" == "x" -o "$gateway" == "x" ]; then
failover add $group
wan_fail_map="echo $wan_fail_map $group[x]"
fi
done
}
wancount=0
config_clear
config_load "multiwan"
config_get default_route config default_route
config_get resolv_conf config resolv_conf
config_get debug config debug
config_foreach acquire_wan_data interface
CHKFORQOS=`iptables -n -L Default -t mangle 2>&1 | grep "Chain Default"`
jobfile="/tmp/.mwan.jobqueue"
case $1 in
agent) silencer main_init;;
restart) silencer stop restart;;
stop) silencer stop;;
esac