From 528f2b0aa290cd4cf38454ffb726b07a51622706 Mon Sep 17 00:00:00 2001 From: Tom Eastep Date: Thu, 25 Aug 2011 16:00:27 -0700 Subject: [PATCH] Implement enable and disable commands for IPv4 Signed-off-by: Tom Eastep --- Shorewall/Perl/Shorewall/Compiler.pm | 8 +- Shorewall/Perl/Shorewall/Misc.pm | 3 + Shorewall/Perl/Shorewall/Providers.pm | 152 +++++++++++++++++++++++++- Shorewall/Perl/prog.footer | 35 +++++- Shorewall/Perl/prog.header | 76 +++++++++++++ docs/MultiISP.xml | 76 ++++++++++++- 6 files changed, 338 insertions(+), 12 deletions(-) diff --git a/Shorewall/Perl/Shorewall/Compiler.pm b/Shorewall/Perl/Shorewall/Compiler.pm index 5f98784e5..31c0a81d1 100644 --- a/Shorewall/Perl/Shorewall/Compiler.pm +++ b/Shorewall/Perl/Shorewall/Compiler.pm @@ -263,9 +263,9 @@ sub generate_script_2() { push_indent; if ( $global_variables & NOT_RESTORE ) { - emit( 'start|restart|refresh)' ); + emit( 'start|restart|refresh|enable)' ); } else { - emit( 'start|restart|refresh|restore)' ); + emit( 'start|restart|refresh|enable|restore)' ); } push_indent; @@ -719,9 +719,9 @@ sub compiler { ); push_indent; - - setup_providers; } + + setup_providers; # # TCRules and Traffic Shaping # diff --git a/Shorewall/Perl/Shorewall/Misc.pm b/Shorewall/Perl/Shorewall/Misc.pm index 0195d0492..742122621 100644 --- a/Shorewall/Perl/Shorewall/Misc.pm +++ b/Shorewall/Perl/Shorewall/Misc.pm @@ -1937,6 +1937,9 @@ EOF refresh) logger -p kern.err "ERROR:$g_product refresh failed" ;; + enable) + logger -p kern.err "ERROR: 'enable $g_interface' failed" + ;; esac if [ "$RESTOREFILE" = NONE ]; then diff --git a/Shorewall/Perl/Shorewall/Providers.pm b/Shorewall/Perl/Shorewall/Providers.pm index 6f63c5a43..753c5d970 100644 --- a/Shorewall/Perl/Shorewall/Providers.pm +++ b/Shorewall/Perl/Shorewall/Providers.pm @@ -546,22 +546,47 @@ sub add_a_provider( ) { emit "\nadd_${table}_routing_rules"; emit "add_${table}_routes"; - emit qq(\nprogress_message " Provider $table ($number) Added"\n); + emit( '', + 'if [ $COMMAND = enable ]; then' + ); + + my ( $tbl, $weight ); + + if ( $balance || $default ) { + $tbl = $default || $config{USE_DEFAULT_RT} ? DEFAULT_TABLE : MAIN_TABLE; + $weight = $balance ? $balance : $default; + + push_indent; + + if ( $gateway ) { + emit qq(add_gateway "nexthop via $gateway dev $physical weight $weight $realm" ) . $tbl; + } else { + emit qq(add_gateway "nexthop dev $physical weight $weight $realm" ) . $tbl; + } + + pop_indent; + } + + emit ( qq( progress_message " Provider $table ($number) Started"), + 'else', + qq( progress_message2 " Provider $table ($number) Started"), + "fi\n" + ); pop_indent; emit 'else'; if ( $optional ) { if ( $shared ) { - emit ( " error_message \"WARNING: Gateway $gateway is not reachable -- Provider $table ($number) not Added\"" ); + emit ( " error_message \"WARNING: Gateway $gateway is not reachable -- Provider $table ($number) not Started\"" ); } else { - emit ( " error_message \"WARNING: Interface $physical is not usable -- Provider $table ($number) not Added\"" ); + emit ( " error_message \"WARNING: Interface $physical is not usable -- Provider $table ($number) not Started\"" ); } } else { if ( $shared ) { - emit( " fatal_error \"Gateway $gateway is not reachable -- Provider $table ($number) Cannot be Added\"" ); + emit( " fatal_error \"Gateway $gateway is not reachable -- Provider $table ($number) Cannot be Started\"" ); } else { - emit( " fatal_error \"Interface $physical is not usable -- Provider $table ($number) Cannot be Added\"" ); + emit( " fatal_error \"Interface $physical is not usable -- Provider $table ($number) Cannot be Started\"" ); } } @@ -569,7 +594,48 @@ sub add_a_provider( ) { pop_indent; - emit "}\n"; + emit "} # End of start_provider_$table()"; + + if ( $optional ) { + emit( '', + '#', + "# Stop provider $table", + '#', + "stop_provider_$table() {" ); + + push_indent; + + my $undo = "\${VARDIR}/undo_${table}_routing"; + + emit( "if [ -f $undo ]; then", + " . $undo", + " > $undo" ); + + if ( $balance || $default ) { + $tbl = $fallback || $config{USE_DEFAULT_RT} ? DEFAULT_TABLE : MAIN_TABLE; + $weight = $balance ? $balance : $default; + + my $via = 'via'; + + $via .= " $gateway" if $gateway; + $via .= " dev $physical"; + $via .= " weight $weight"; + $via .= " $realm" if $realm; + + emit( qq( delete_gateway "$via" ) . $tbl ); + } + + + emit( " progress_message2 \"Provider $table stopped\"", + 'else', + " startup_error \"$undo does not exist\"", + 'fi' + ); + + pop_indent; + + emit '}'; + } push @providers, $table; @@ -885,6 +951,80 @@ sub process_providers() { pop_indent; emit '}'; } + + emit << 'EOF';; + +# +# Enable an optional provider +# +enable_provider() { + g_interface=$1; + + case $g_interface in +EOF + + push_indent; + push_indent; + + for my $provider (@providers ) { + my $providerref = $providers{$provider}; + + emit( "$providerref->{physical})", + " if [ -z \"`\$IP -$family route ls table $providerref->{number}`\" ]; then", + " start_provider_$provider", + ' else', + ' startup_error "Interface $g_interface is already enabled"', + ' fi', + ' ;;' + ) if $providerref->{optional}; + } + + pop_indent; + pop_indent; + + emit << 'EOF';; + *) + startup_error "$g_interface is not an optional provider interface" + ;; + esac +} + +# +# Disable an optional provider +# +disable_provider() { + g_interface=$1; + + case $g_interface in +EOF + + push_indent; + push_indent; + + for my $provider (@providers ) { + my $providerref = $providers{$provider}; + + emit( "$providerref->{physical})", + " if [ -n \"`\$IP -$family route ls table $providerref->{number}`\" ]; then", + " stop_provider_$provider", + ' else', + ' startup_error "Interface $g_interface is already disabled"', + ' fi', + ' ;;' + ) if $providerref->{optional}; + } + + pop_indent; + pop_indent; + + emit << 'EOF';; + *) + startup_error "$g_interface is not an optional provider interface" + ;; + esac +} +EOF + } sub setup_providers() { diff --git a/Shorewall/Perl/prog.footer b/Shorewall/Perl/prog.footer index 7dd772331..71ac8f3a4 100644 --- a/Shorewall/Perl/prog.footer +++ b/Shorewall/Perl/prog.footer @@ -5,7 +5,21 @@ # Give Usage Information # usage() { - echo "Usage: $0 [ options ] [ start|stop|clear|down|reset|refresh|restart|status|up|version ]" + echo "Usage: $0 [ options ] " + echo + echo " is one of:" + echo " start" + echo " stop" + echo " clear" + echo " disable " + echo " down " + echo " enable " + echo " reset" + echo " refresh" + echo " restart" + echo " status" + echo " up " + echo " version" echo echo "Options are:" echo @@ -295,6 +309,25 @@ case "$COMMAND" in updown $@ status=0; ;; + enable) + detect_configuration + [ $# -eq 1 ] && exit 0 + shift + [ $# -ne 1 ] && usage 2 + if shorewall_is_started; then + enable_provider $1 + fi + status=0 + ;; + disable) + [ $# -eq 1 ] && exit 0 + shift + [ $# -ne 1 ] && usage 2 + if shorewal_is_started; then + disable_provider $1 + fi + status=0 + ;; version) [ $# -ne 1 ] && usage 2 echo $SHOREWALL_VERSION diff --git a/Shorewall/Perl/prog.header b/Shorewall/Perl/prog.header index e63df64ae..2390fb4e7 100644 --- a/Shorewall/Perl/prog.header +++ b/Shorewall/Perl/prog.header @@ -111,6 +111,17 @@ find_device() { done } +# +# Find the value 'weight' in the passed arguments then echo the next value +# + +find_weight() { + while [ $# -gt 1 ]; do + [ "x$1" = xweight ] && echo $2 && return + shift + done +} + # # Find the value 'via' in the passed arguments then echo the next value # @@ -581,6 +592,71 @@ restore_default_route() # $1 = USE_DEFAULT_RT return $result } +# +# Add an additional gateway to the default route +# +add_gateway() # $1 = Delta $2 = Table Number +{ + local route + local weight + local delta + + route=`$IP -4 -o route ls table $2 | grep ^default | sed 's/default //'` + + if [ -z "$route" ]; then + run_ip route add default scope global table $2 $1 + find_weight $1 > ${VARDIR}/weight + else + delta=$1 + + if ! echo $route | fgrep -q ' nexthop '; then + route=`echo $route | sed 's/via/nexthop via/'` + if [ -f ${VARDIR}/weight ]; then + weight=`cat ${VARDIR}/weight` + route="$route weight $weight" + rm -f ${VARDIR}/weight + fi + fi + + run_ip route replace default scope global table $2 $route $delta + fi +} + +# +# Remove a gateway from the default route +# +delete_gateway() # $! = Description of the Gateway $2 = table number +{ + local route + local gateway + local newroute + + route=`$IP -4 -o route ls table $2 | grep ^default` + gateway=$1 + + if [ -n "$route" ]; then + if echo $route | fgrep -q ' nexthop '; then + gateway="nexthop $gateway" + fi + + eval route=\`echo $route \| sed \'s/$gateway/ /\'\` + + if echo $route | fgrep -q ' via '; then + run_ip route replace table $2 $route + else + run_ip route delete default table $2 + fi + + newroute=`$IP -4 -o route ls table $2 | grep ^default` + + if echo $newroute | fgrep -q ' nexthop '; then + rm -f ${VARDIR}/weight + else + find_weight $route > ${VARDIR}/weight + fi + fi +} + # # Determine the MAC address of the passed IP through the passed interface # diff --git a/docs/MultiISP.xml b/docs/MultiISP.xml index 6da942918..4a71eb5de 100644 --- a/docs/MultiISP.xml +++ b/docs/MultiISP.xml @@ -1803,7 +1803,81 @@ echo $state > ${VARDIR}/${DEVICE}.status exit 0 -#EOF: +#EOFBeginning with Shorewall 4.4.23, it is not necessary to + restart the firewall when an interface transitions between the usable + and unusable + states./etc/lsm/script#!/bin/sh +# +# (C) 2009 Mika Ilmaranta <ilmis@nullnet.fi> +# (C) 2009 Tom Eastep <teastep@shorewall.net> +# +# License: GPLv2 +# + +STATE=${1} +NAME=${2} +CHECKIP=${3} +DEVICE=${4} +WARN_EMAIL=${5} +REPLIED=${6} +WAITING=${7} +TIMEOUT=${8} +REPLY_LATE=${9} +CONS_RCVD=${10} +CONS_WAIT=${11} +CONS_MISS=${12} +AVG_RTT=${13} + +if [ -f /usr/share/shorewall-lite/lib.base ]; then + VARDIR=/var/lib/shorewall-lite + STATEDIR=/etc/shorewall-lite +else + VARDIR=/var/lib/shorewall + STATEDIR=/etc/shorewall +fi + +[ -f ${STATEDIR}/vardir ] && . ${STATEDIR}/vardir + +cat <<EOM | mail -s "${NAME} ${STATE}, DEV ${DEVICE}" ${WARN_EMAIL} + +Hi, + +Connection ${NAME} is now ${STATE}. + +Following parameters were passed: +newstate = ${STATE} +name = ${NAME} +checkip = ${CHECKIP} +device = ${DEVICE} +warn_email = ${WARN_EMAIL} + +Packet counters: +replied = ${REPLIED} packets replied +waiting = ${WAITING} packets waiting for reply +timeout = ${TIMEOUT} packets that have timed out (= packet loss) +reply_late = ${REPLY_LATE} packets that received a reply after timeout +cons_rcvd = ${CONS_RCVD} consecutively received replies in sequence +cons_wait = ${CONS_WAIT} consecutive packets waiting for reply +cons_miss = ${CONS_MISS} consecutive packets that have timed out +avg_rtt = ${AVG_RTT} average rtt, notice that waiting and timed out packets have rtt = 0 when calculating this + +Your LSM Daemon + +EOM + +if [ ${STATE} = up ]; then + echo 0 > ${VARDIR}/${DEVICE}.status + ${VARDIR}/firewall enable ${DEVICE} +else + echo 1 > ${VARDIR}/${DEVICE}.status + ${VARDIR}/firewall disable ${DEVICE} +fi + +/sbin/shorewall show routing >> /var/log/lsm + +exit 0 + +#EOF