From f6cb3ecd776646bf11856a379fa6efcb0cec38b8 Mon Sep 17 00:00:00 2001 From: teastep Date: Sun, 27 Aug 2006 19:13:42 +0000 Subject: [PATCH] Modularize Multi-ISP git-svn-id: https://shorewall.svn.sourceforge.net/svnroot/shorewall/trunk@4452 fbd18981-670d-0410-9b5c-8dc0c1a9a2bb --- Shorewall/compiler | 637 +--------------------------------------- Shorewall/lib.providers | 410 ++++++++++++++++++++++++++ 2 files changed, 417 insertions(+), 630 deletions(-) create mode 100644 Shorewall/lib.providers diff --git a/Shorewall/compiler b/Shorewall/compiler index ace88b396..e9c963653 100755 --- a/Shorewall/compiler +++ b/Shorewall/compiler @@ -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 <&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,10 +5680,8 @@ 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 createchain logdrop no @@ -7800,8 +7175,10 @@ __EOF__ # # [re]-Establish routing # - setup_providers $(find_file providers) - [ -n "$ROUTEMARK_INTERFACES" ] && setup_routes + 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 diff --git a/Shorewall/lib.providers b/Shorewall/lib.providers new file mode 100644 index 000000000..ec64457e3 --- /dev/null +++ b/Shorewall/lib.providers @@ -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 <&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 + +}