Modularize Multi-ISP

git-svn-id: https://shorewall.svn.sourceforge.net/svnroot/shorewall/trunk@4452 fbd18981-670d-0410-9b5c-8dc0c1a9a2bb
This commit is contained in:
teastep 2006-08-27 19:13:42 +00:00
parent 97218564ae
commit f6cb3ecd77
2 changed files with 417 additions and 630 deletions

View File

@ -411,365 +411,6 @@ deletechain() # $1 = name of chain
save_command "qt $IPTABLES -L $1 -n && qt $IPTABLES -F $1 && qt $IPTABLES -X $1"
}
#
# Process the providers file
#
setup_providers()
{
local table number mark duplicate interface gateway options provider address copy route loose addresses rulenum rulebase echobin=$(mywhich echo) balance save_indent="$INDENT" mask= first=Yes save_indent1=
copy_table() {
indent >&3 << __EOF__
ip route show table $duplicate | while read net route; do
case \$net in
default|nexthop)
;;
*)
run_ip route add table $number \$net \$route
;;
esac
done
__EOF__
}
copy_and_edit_table() {
indent >&3 << __EOF__
ip route show table $duplicate | while read net route; do
case \$net in
default|nexthop)
;;
*)
case \$(find_device \$route) in
`echo $copy\) | sed 's/ /|/g'`
run_ip route add table $number \$net \$route
;;
esac
;;
esac
done
__EOF__
}
balance_default_route() # $1 = weight
{
balance=yes
save_command
if [ -n "$first" ]; then
if [ -n "$gateway" ] ; then
save_command "DEFAULT_ROUTE=\"nexthop via $gateway dev $interface weight $1\""
else
save_command "DEFAULT_ROUTE=\"nexthop dev $interface weight $1\""
fi
first=
else
if [ -n "$gateway" ] ; then
save_command "DEFAULT_ROUTE=\"\$DEFAULT_ROUTE nexthop via $gateway dev $interface weight $1\""
else
save_command "DEFAULT_ROUTE=\"\$DEFAULT_ROUTE nexthop dev $interface weight $1\""
fi
fi
}
add_a_provider() {
local t n iface option optional=
[ -n "$MANGLE_ENABLED" ] || fatal_error "Providers require mangle support in your kernel and iptables"
for t in $PROVIDERS local main default unspec; do
if [ "$t" = "$table" ]; then
fatal_error "Duplicate Provider: $table, provider: \"$provider\""
fi
eval n=\$${t}_number
#
# The following is because the %$#@ shell doesn't accept hex numbers in '-eq' tests
#
if [ $(($n)) -eq $(($number)) ]; then
fatal_error "Duplicate Provider number: $number, provider: \"$provider\""
fi
done
eval ${table}_number=$number
indent >&3 << __EOF__
#
# Add Provider $table ($number)
#
__EOF__
save_command "if interface_is_up $interface && [ \"\$(find_first_interface_address_if_any $interface)\" != 0.0.0.0 ]; then"
save_indent1="$INDENT"
INDENT="$INDENT "
iface=$(chain_base $interface)
save_command "${iface}_up=Yes"
save_command "qt ip route flush table $number"
if [ "x${duplicate:=-}" != x- ]; then
if [ "x${copy:=-}" != "x-" ]; then
if [ "x${copy}" = xnone ]; then
copy=$interface
else
copy="$interface $(separate_list $copy)"
fi
copy_and_edit_table
else
copy_table
fi
fi
if [ "x$gateway" = xdetect ] ; then
gateway='$gateway'
indent >&3 << __EOF__
gateway=\$(detect_gateway $interface)
if [ -n "\$gateway" ]; then
run_ip route replace \$gateway src \$(find_first_interface_address $interface) dev $interface table $number
run_ip route add default via \$gateway dev $interface table $number
else
fatal_error "Unable to detect the gateway through interface $interface"
fi
__EOF__
elif [ "x$gateway" != "x-" -a -n "$gateway" ]; then
indent >&3 << __EOF__
run_ip route replace $gateway src \$(find_first_interface_address $interface) dev $interface table $number
run_ip route add default via $gateway dev $interface table $number
__EOF__
else
gateway=
save_command "run_ip route add default dev $interface table $number"
fi
if [ x${mark} != x- ]; then
verify_mark $mark
if [ $(($mark)) -lt 256 ]; then
if [ -n "$HIGH_ROUTE_MARKS" ]; then
fatal_error "Invalid Mark Value ($mark) with HIGH_ROUTE_MARKS=Yes"
fi
elif [ -z "$HIGH_ROUTE_MARKS" ]; then
fatal_error "Invalid Mark Value ($mark) with HIGH_ROUTE_MARKS=No"
fi
eval ${table}_mark=$mark
save_command "qt ip rule del fwmark $mark"
save_command "run_ip rule add fwmark $mark pref $((10000 + $mark)) table $number"
fi
loose=
for option in $(separate_list $options); do
case $option in
-)
;;
track)
list_search $interface $ROUTEMARK_INTERFACES && \
fatal_error "Interface $interface is tracked through an earlier provider"
[ x${mark} = x- ] && fatal_error "The 'track' option requires a numeric value in the MARK column - Provider \"$provider\""
eval ${iface}_routemark=$mark
ROUTEMARK_INTERFACES="$ROUTEMARK_INTERFACES $interface"
;;
balance=*)
balance_default_route ${option#*=}
;;
balance)
balance_default_route 1
;;
loose)
loose=Yes
;;
optional)
optional=Yes
;;
*)
error_message "WARNING: Invalid option ($option) ignored in provider \"$provider\""
;;
esac
done
rulenum=0
if [ -z "$loose" ]; then
rulebase=$(( 20000 + ( 256 * ($number-1) ) ))
indent >&3 << __EOF__
rulenum=0
find_interface_addresses $interface | while read address; do
qt ip rule del from \$address
run_ip rule add from \$address pref \$(( $rulebase + \$rulenum )) table $number
rulenum=\$((\$rulenum + 1))
done
__EOF__
else
indent >&3 << __EOF__
find_interface_addresses $interface | while read address; do
qt ip rule del from \$address
done
__EOF__
fi
indent >&3 << __EOF__
progress_message " Provider $table ($number) Added"
__EOF__
INDENT="$save_indent1"
save_command else
if [ -n "$optional" ]; then
save_command " error_message \"WARNING: Interface $interface is not configured -- Provider $table ($number) not Added\""
save_command " ${iface}_up="
else
save_command " fatal_error \"ERROR: Interface $interface is not configured -- Provider $table ($number) Cannot be Added\""
fi
save_command fi
save_command
}
verify_provider()
{
local p n
for p in $PROVIDERS main; do
[ "$p" = "$1" ] && return 0
eval n=\$${p}_number}
[ "$n" = "$1" ] && return 0
done
fatal_error "Unknown provider $1 in route rule \"$rule\""
}
add_an_rtrule()
{
verify_provider $provider
[ "x$source" = x- ] && source=
[ "x$dest" = x- ] && dest= || dest="to $dest"
[ -n "${source}${dest}" ] || fatal_error "You must specify either the source or destination in an rt rule: \"$rule\""
[ -n "$source" ] && case $source in
*:*)
source="iif ${source%:*} from ${source#*:}"
;;
*.*.*)
source="from $source"
;;
*)
source="iif $source"
;;
esac
case "$priority" in
[0-9][0-9][0-9][0-9]|[0-9][0-9][0-9][0-9][0-9])
;;
*)
fatal_error "Invalid priority ($priority) in rule \"$rule\""
;;
esac
priority="priority $priority"
save_command "qt ip rule del $source $dest $priority"
save_command "run_ip rule add $source $dest $priority table $provider"
progress_message "Routing rule \"$rule\" $DONE"
}
local_number=255
main_number=254
default_number=253
unspec_number=0
strip_file providers $1
if [ -s $TMP_DIR/providers ]; then
balance=
progress_message2 "$DOING $1..."
save_command
save_command "if [ -z \"\$NOROUTES\" ]; then"
INDENT="$INDENT "
save_progress_message "Adding Providers..."
save_command "DEFAULT_ROUTE="
while read table number mark duplicate interface gateway options copy; do
expandv table number mark duplicate interface gateway options copy
provider="$table $number $mark $duplicate $interface $gateway $options $copy"
add_a_provider
PROVIDERS="$PROVIDERS $table"
progress_message "Provider $provider $DONE"
done < $TMP_DIR/providers
if [ -n "$PROVIDERS" ]; then
if [ -n "$balance" ]; then
save_command "if [ -n \"\$DEFAULT_ROUTE\" ]; then"
save_command " run_ip route replace default scope global \$DEFAULT_ROUTE"
save_command " progress_message \"Default route '\$(echo \$DEFAULT_ROUTE | sed 's/\$\\s*//')' Added\""
save_command "else"
save_command " error_message \"WARNING: No Default route added (all 'balance' providers are down)\""
save_command "fi"
save_command
fi
cat >&3 << __EOF__
${INDENT}cat > /etc/iproute2/rt_tables <<EOF
#
# reserved values
#
255 local
254 main
253 default
0 unspec
#
# local
#
EOF
__EOF__
for table in $PROVIDERS; do
eval number=\$${table}_number
indent >&3 << __EOF__
\${echobin:-echo} -e "$number\t$table" >> /etc/iproute2/rt_tables
__EOF__
done
f=$(find_file route_rules)
if [ -f $f ]; then
strip_file route_rules $f
if [ -s $TMP_DIR/route_rules ]; then
progress_message2 "$DOING $f..."
save_command
while read source dest provider priority; do
expandv source dest provider priority
rule="$source $dest $priority $provider"
add_an_rtrule
done < $TMP_DIR/route_rules
fi
fi
fi
save_command "run_ip route flush cache"
INDENT="$save_indent"
save_command "fi"
save_command
fi
}
#
# validate the policy file
#
@ -2261,8 +1902,7 @@ setup_tc1() {
append_file $TC_SCRIPT
elif [ -n "$TC_ENABLED" ]; then
strip_file_and_lib_load tcdevices tc
strip_file_and_lib_load tcclasses tc
setup_traffic_shaping
strip_file_and_lib_load tcclasses tc && setup_traffic_shaping
fi
}
@ -2397,235 +2037,6 @@ compile_refresh_firewall()
}
#
# Process a record from the accounting file
#
process_accounting_rule() {
rule=
rule2=
jumpchain=
user1=
accounting_error() {
error_message "WARNING: Invalid Accounting rule" $action $chain $source $dest $proto $port $sport $user
}
accounting_interface_error() {
error_message "WARNING: Unknown interface $1 in " $action $chain $source $dest $proto $port $sport $user
}
accounting_interface_verify() {
verify_interface $1 || accounting_interface_error $1
}
jump_to_chain() {
if ! havechain $jumpchain; then
if ! createchain2 $jumpchain No; then
accounting_error
return 2
fi
fi
rule="$rule -j $jumpchain"
}
do_ipp2p() {
[ -n "$IPP2P_MATCH" ] || fatal_error "Your kernel and/or iptables does not have IPP2P match support"
case $proto in
*:*)
proto=${proto#*:}
;;
*)
proto=tcp
;;
esac
rule="$rule -p $proto -m ipp2p --${port:-ipp2p}"
}
case $source in
*:*)
accounting_interface_verify ${source%:*}
rule="$(source_ip_range ${source#*:}) $(match_source_dev ${source%:*})"
;;
*.*.*.*|+*|!+*)
rule="$(source_ip_range $source)"
;;
-|all|any)
;;
*)
if [ -n "$source" ]; then
accounting_interface_verify $source
rule="$(match_source_dev $source)"
fi
;;
esac
[ -n "$dest" ] && case $dest in
*:*)
accounting_interface_verify ${dest%:*}
rule="$rule $(dest_ip_range ${dest#*:}) $(match_dest_dev ${dest%:*})"
;;
*.*.*.*|+*|!*)
rule="$rule $(dest_ip_range $dest)"
;;
-|all|any)
;;
*)
accounting_interface_verify $dest
rule="$rule $(match_dest_dev $dest)"
;;
esac
[ -n "$proto" ] && case $proto in
-|any|all)
;;
ipp2p|IPP2P|ipp2p:*|IPP2P:*)
do_ipp2p
;;
*)
rule="$rule -p $proto"
;;
esac
multiport=
[ -n "$port" ] && case $port in
-|any|all)
;;
*)
if [ -n "$MULTIPORT" ]; then
rule="$rule -m multiport --dports $port"
multiport=Yes
else
rule="$rule --dport $port"
fi
;;
esac
[ -n "$sport" ] && case $sport in
-|any|all)
;;
*)
if [ -n "$MULTIPORT" ]; then
[ -n "$multiport" ] && rule="$rule --sports $sport" || rule="$rule -m multiport --sports $sport"
else
rule="$rule --sport $sport"
fi
;;
esac
[ -n "$user" ] && case $user in
-|any|all)
;;
*)
[ "$chain" != OUTPUT ] && \
fatal_error "Invalid use of a user/group: chain is not OUTPUT but $chain"
rule="$rule -m owner"
user1="$user"
case "$user" in
!*+*)
if [ -n "${user#*+}" ]; then
rule="$rule ! --cmd-owner ${user#*+} "
fi
user1=${user%+*}
;;
*+*)
if [ -n "${user#*+}" ]; then
rule="$rule --cmd-owner ${user#*+} "
fi
user1=${user%+*}
;;
esac
case "$user1" in
!*:*)
if [ "$user1" != "!:" ]; then
temp="${user1#!}"
temp="${temp%:*}"
[ -n "$temp" ] && rule="$rule ! --uid-owner $temp "
temp="${user1#*:}"
[ -n "$temp" ] && rule="$rule ! --gid-owner $temp "
fi
;;
*:*)
if [ "$user1" != ":" ]; then
temp="${user1%:*}"
[ -n "$temp" ] && rule="$rule --uid-owner $temp "
temp="${user1#*:}"
[ -n "$temp" ] && rule="$rule --gid-owner $temp "
fi
;;
!*)
[ "$user1" != "!" ] && rule="$rule ! --uid-owner ${user1#!} "
;;
*)
[ -n "$user1" ] && rule="$rule --uid-owner $user1 "
;;
esac
;;
esac
case $action in
COUNT)
;;
DONE)
rule="$rule -j RETURN"
;;
*:COUNT)
rule2="$rule"
jumpchain=${action%:*}
jump_to_chain || return
;;
JUMP:*)
jumpchain=${action#*:}
jump_to_chain || return
;;
*)
jumpchain=$action
jump_to_chain || return
;;
esac
[ "x${chain:=accounting}" = "x-" ] && chain=accounting
ensurechain1 $chain
if do_iptables -A $chain $(fix_bang $rule) ; then
[ -n "$rule2" ] && run_iptables2 -A $jumpchain $rule2
progress_message " Accounting rule \"$action $chain $source $dest $proto $port $sport $user\" $DONE"
save_progress_message_short " Accounting rule \\\"$action $chain $source $dest $proto $port $sport $user\\\" Added"
else
accounting_error
fi
}
#
# Set up Accounting
#
setup_accounting() # $1 = Name of accounting file
{
progress_message2 "$DOING Accounting..."
save_progress_message "Setting up Accounting..."
strip_file accounting $1
while read action chain source dest proto port sport user ; do
expandv action chain source dest proto port sport user
process_accounting_rule
done < $TMP_DIR/accounting
if havechain accounting; then
for chain in INPUT FORWARD OUTPUT; do
run_iptables -I $chain -j accounting
done
fi
}
#
# Add one Filter Rule from an action -- Helper function for the action file processor
#
@ -5469,40 +4880,6 @@ rules_chain() # $1 = source zone, $2 = destination zone
fi
}
#
# Set up Routing
#
setup_routes()
{
local mask=0xFF mark_op="--set-mark" save_indent="$INDENT"
[ -n "$HIGH_ROUTE_MARKS" ] && mask=0xFF00 && mark_op="--or-mark"
run_iptables -t mangle -A PREROUTING -m connmark ! --mark 0/$mask -j CONNMARK --restore-mark --mask $mask
run_iptables -t mangle -A OUTPUT -m connmark ! --mark 0/$mask -j CONNMARK --restore-mark --mask $mask
createmanglechain routemark
if [ -n "$ROUTEMARK_INTERFACES" ]; then
for interface in $ROUTEMARK_INTERFACES ; do
iface=$(chain_base $interface)
eval mark_value=\$${iface}_routemark
save_command
save_command "if [ -n \"\$${iface}_up\" ]; then"
INDENT="$INDENT "
run_iptables -t mangle -A PREROUTING -i $interface -m mark --mark 0/$mask -j routemark
run_iptables -t mangle -A routemark -i $interface -j MARK $mark_op $mark_value
INDENT="$save_indent"
save_command "fi"
done
save_command
fi
run_iptables -t mangle -A routemark -m mark ! --mark 0/$mask -j CONNMARK --save-mark --mask $mask
}
#
# Set up Source NAT (including masquerading)
#
@ -6303,9 +5680,7 @@ initialize_netfilter () {
run_iptables -A $chain -p udp --dport 53 -j ACCEPT
done
accounting_file=$(find_file accounting)
[ -f $accounting_file ] && setup_accounting $accounting_file
strip_file_and_lib_load accounting accounting && setup_accounting $(find_file accounting)
createchain reject no
createchain dynamic no
@ -7800,8 +7175,10 @@ __EOF__
#
# [re]-Establish routing
#
if strip_file_and_lib_load providers providers; then
setup_providers $(find_file providers)
[ -n "$ROUTEMARK_INTERFACES" ] && setup_routes
fi
progress_message2 "$DOING NAT..."; setup_nat
progress_message2 "$DOING NETMAP..."; setup_netmap

410
Shorewall/lib.providers Normal file
View File

@ -0,0 +1,410 @@
#!/bin/sh
#
# Shorewall 3.2 -- /usr/share/shorewall/lib.providers
#
# This program is under GPL [http://www.gnu.org/copyleft/gpl.htm]
#
# (c) 1999,2000,2001,2002,2003,2004,2005,2006 - Tom Eastep (teastep@shorewall.net)
#
# Complete documentation is available at http://shorewall.net
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of Version 2 of the GNU General Public License
# as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA
#
# Process the providers file
#
setup_providers()
{
local table number mark duplicate interface gateway options provider address copy route loose addresses rulenum rulebase echobin=$(mywhich echo) balance save_indent="$INDENT" mask= first=Yes save_indent1=
copy_table() {
indent >&3 << __EOF__
ip route show table $duplicate | while read net route; do
case \$net in
default|nexthop)
;;
*)
run_ip route add table $number \$net \$route
;;
esac
done
__EOF__
}
copy_and_edit_table() {
indent >&3 << __EOF__
ip route show table $duplicate | while read net route; do
case \$net in
default|nexthop)
;;
*)
case \$(find_device \$route) in
`echo $copy\) | sed 's/ /|/g'`
run_ip route add table $number \$net \$route
;;
esac
;;
esac
done
__EOF__
}
balance_default_route() # $1 = weight
{
balance=yes
save_command
if [ -n "$first" ]; then
if [ -n "$gateway" ] ; then
save_command "DEFAULT_ROUTE=\"nexthop via $gateway dev $interface weight $1\""
else
save_command "DEFAULT_ROUTE=\"nexthop dev $interface weight $1\""
fi
first=
else
if [ -n "$gateway" ] ; then
save_command "DEFAULT_ROUTE=\"\$DEFAULT_ROUTE nexthop via $gateway dev $interface weight $1\""
else
save_command "DEFAULT_ROUTE=\"\$DEFAULT_ROUTE nexthop dev $interface weight $1\""
fi
fi
}
add_a_provider() {
local t n iface option optional=
[ -n "$MANGLE_ENABLED" ] || fatal_error "Providers require mangle support in your kernel and iptables"
for t in $PROVIDERS local main default unspec; do
if [ "$t" = "$table" ]; then
fatal_error "Duplicate Provider: $table, provider: \"$provider\""
fi
eval n=\$${t}_number
#
# The following is because the %$#@ shell doesn't accept hex numbers in '-eq' tests
#
if [ $(($n)) -eq $(($number)) ]; then
fatal_error "Duplicate Provider number: $number, provider: \"$provider\""
fi
done
eval ${table}_number=$number
indent >&3 << __EOF__
#
# Add Provider $table ($number)
#
__EOF__
save_command "if interface_is_up $interface && [ \"\$(find_first_interface_address_if_any $interface)\" != 0.0.0.0 ]; then"
save_indent1="$INDENT"
INDENT="$INDENT "
iface=$(chain_base $interface)
save_command "${iface}_up=Yes"
save_command "qt ip route flush table $number"
if [ "x${duplicate:=-}" != x- ]; then
if [ "x${copy:=-}" != "x-" ]; then
if [ "x${copy}" = xnone ]; then
copy=$interface
else
copy="$interface $(separate_list $copy)"
fi
copy_and_edit_table
else
copy_table
fi
fi
if [ "x$gateway" = xdetect ] ; then
gateway='$gateway'
indent >&3 << __EOF__
gateway=\$(detect_gateway $interface)
if [ -n "\$gateway" ]; then
run_ip route replace \$gateway src \$(find_first_interface_address $interface) dev $interface table $number
run_ip route add default via \$gateway dev $interface table $number
else
fatal_error "Unable to detect the gateway through interface $interface"
fi
__EOF__
elif [ "x$gateway" != "x-" -a -n "$gateway" ]; then
indent >&3 << __EOF__
run_ip route replace $gateway src \$(find_first_interface_address $interface) dev $interface table $number
run_ip route add default via $gateway dev $interface table $number
__EOF__
else
gateway=
save_command "run_ip route add default dev $interface table $number"
fi
if [ x${mark} != x- ]; then
verify_mark $mark
if [ $(($mark)) -lt 256 ]; then
if [ -n "$HIGH_ROUTE_MARKS" ]; then
fatal_error "Invalid Mark Value ($mark) with HIGH_ROUTE_MARKS=Yes"
fi
elif [ -z "$HIGH_ROUTE_MARKS" ]; then
fatal_error "Invalid Mark Value ($mark) with HIGH_ROUTE_MARKS=No"
fi
eval ${table}_mark=$mark
save_command "qt ip rule del fwmark $mark"
save_command "run_ip rule add fwmark $mark pref $((10000 + $mark)) table $number"
fi
loose=
for option in $(separate_list $options); do
case $option in
-)
;;
track)
list_search $interface $ROUTEMARK_INTERFACES && \
fatal_error "Interface $interface is tracked through an earlier provider"
[ x${mark} = x- ] && fatal_error "The 'track' option requires a numeric value in the MARK column - Provider \"$provider\""
eval ${iface}_routemark=$mark
ROUTEMARK_INTERFACES="$ROUTEMARK_INTERFACES $interface"
;;
balance=*)
balance_default_route ${option#*=}
;;
balance)
balance_default_route 1
;;
loose)
loose=Yes
;;
optional)
optional=Yes
;;
*)
error_message "WARNING: Invalid option ($option) ignored in provider \"$provider\""
;;
esac
done
rulenum=0
if [ -z "$loose" ]; then
rulebase=$(( 20000 + ( 256 * ($number-1) ) ))
indent >&3 << __EOF__
rulenum=0
find_interface_addresses $interface | while read address; do
qt ip rule del from \$address
run_ip rule add from \$address pref \$(( $rulebase + \$rulenum )) table $number
rulenum=\$((\$rulenum + 1))
done
__EOF__
else
indent >&3 << __EOF__
find_interface_addresses $interface | while read address; do
qt ip rule del from \$address
done
__EOF__
fi
indent >&3 << __EOF__
progress_message " Provider $table ($number) Added"
__EOF__
INDENT="$save_indent1"
save_command else
if [ -n "$optional" ]; then
save_command " error_message \"WARNING: Interface $interface is not configured -- Provider $table ($number) not Added\""
save_command " ${iface}_up="
else
save_command " fatal_error \"ERROR: Interface $interface is not configured -- Provider $table ($number) Cannot be Added\""
fi
save_command fi
save_command
}
verify_provider()
{
local p n
for p in $PROVIDERS main; do
[ "$p" = "$1" ] && return 0
eval n=\$${p}_number}
[ "$n" = "$1" ] && return 0
done
fatal_error "Unknown provider $1 in route rule \"$rule\""
}
add_an_rtrule()
{
verify_provider $provider
[ "x$source" = x- ] && source=
[ "x$dest" = x- ] && dest= || dest="to $dest"
[ -n "${source}${dest}" ] || fatal_error "You must specify either the source or destination in an rt rule: \"$rule\""
[ -n "$source" ] && case $source in
*:*)
source="iif ${source%:*} from ${source#*:}"
;;
*.*.*)
source="from $source"
;;
*)
source="iif $source"
;;
esac
case "$priority" in
[0-9][0-9][0-9][0-9]|[0-9][0-9][0-9][0-9][0-9])
;;
*)
fatal_error "Invalid priority ($priority) in rule \"$rule\""
;;
esac
priority="priority $priority"
save_command "qt ip rule del $source $dest $priority"
save_command "run_ip rule add $source $dest $priority table $provider"
progress_message "Routing rule \"$rule\" $DONE"
}
local_number=255
main_number=254
default_number=253
unspec_number=0
balance=
progress_message2 "$DOING $1..."
save_command
save_command "if [ -z \"\$NOROUTES\" ]; then"
INDENT="$INDENT "
save_progress_message "Adding Providers..."
save_command "DEFAULT_ROUTE="
while read table number mark duplicate interface gateway options copy; do
expandv table number mark duplicate interface gateway options copy
provider="$table $number $mark $duplicate $interface $gateway $options $copy"
add_a_provider
PROVIDERS="$PROVIDERS $table"
progress_message "Provider $provider $DONE"
done < $TMP_DIR/providers
if [ -n "$PROVIDERS" ]; then
if [ -n "$balance" ]; then
save_command "if [ -n \"\$DEFAULT_ROUTE\" ]; then"
save_command " run_ip route replace default scope global \$DEFAULT_ROUTE"
save_command " progress_message \"Default route '\$(echo \$DEFAULT_ROUTE | sed 's/\$\\s*//')' Added\""
save_command "else"
save_command " error_message \"WARNING: No Default route added (all 'balance' providers are down)\""
save_command "fi"
save_command
fi
cat >&3 << __EOF__
${INDENT}cat > /etc/iproute2/rt_tables <<EOF
#
# reserved values
#
255 local
254 main
253 default
0 unspec
#
# local
#
EOF
__EOF__
for table in $PROVIDERS; do
eval number=\$${table}_number
indent >&3 << __EOF__
\${echobin:-echo} -e "$number\t$table" >> /etc/iproute2/rt_tables
__EOF__
done
f=$(find_file route_rules)
if [ -f $f ]; then
strip_file route_rules $f
if [ -s $TMP_DIR/route_rules ]; then
progress_message2 "$DOING $f..."
save_command
while read source dest provider priority; do
expandv source dest provider priority
rule="$source $dest $priority $provider"
add_an_rtrule
done < $TMP_DIR/route_rules
fi
fi
fi
save_command "run_ip route flush cache"
INDENT="$save_indent"
save_command "fi"
save_command
}
#
# Set up Routing
#
setup_routes()
{
local mask=0xFF mark_op="--set-mark" save_indent="$INDENT"
[ -n "$HIGH_ROUTE_MARKS" ] && mask=0xFF00 && mark_op="--or-mark"
run_iptables -t mangle -A PREROUTING -m connmark ! --mark 0/$mask -j CONNMARK --restore-mark --mask $mask
run_iptables -t mangle -A OUTPUT -m connmark ! --mark 0/$mask -j CONNMARK --restore-mark --mask $mask
createmanglechain routemark
if [ -n "$ROUTEMARK_INTERFACES" ]; then
for interface in $ROUTEMARK_INTERFACES ; do
iface=$(chain_base $interface)
eval mark_value=\$${iface}_routemark
save_command
save_command "if [ -n \"\$${iface}_up\" ]; then"
INDENT="$INDENT "
run_iptables -t mangle -A PREROUTING -i $interface -m mark --mark 0/$mask -j routemark
run_iptables -t mangle -A routemark -i $interface -j MARK $mark_op $mark_value
INDENT="$save_indent"
save_command "fi"
done
save_command
fi
run_iptables -t mangle -A routemark -m mark ! --mark 0/$mask -j CONNMARK --save-mark --mask $mask
}