#!/bin/sh # # Shorewall Packet Filtering Firewall Control Program - V4.4 # # This program is under GPL [http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt] # # (c) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011 - # Tom Eastep (teastep@shorewall.net) # # This file should be placed in /sbin/shorewall. # # Shorewall documentation is available at http://www.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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # # For a list of supported commands, type 'shorewall help' or 'shorewall6 help' # ################################################################################################ # # Set the configuration variables from the .conf file # # $1 = Yes: read the params file # $2 = Yes: check for STARTUP_ENABLED # $3 = Yes: Check for LOGFILE # get_config() { local prog ensure_config_path if [ "$1" = Yes ]; then params=$(find_file params) if [ -f $params ]; then . $params fi fi config=$(find_file $g_program.conf) if [ -f $config ]; then if [ -r $config ]; then . $config else echo "Cannot read $config! (Hint: Are you root?)" >&2 exit 1 fi else echo "$config does not exist!" >&2 exit 2 fi ensure_config_path if [ -z "$g_export" -a "$(id -u)" = 0 ]; then # # This block is avoided for compile for export and when the user isn't root # if [ "$3" = Yes ]; then if [ -n "$LOGFILE" ]; then if [ -n "$(syslog_circular_buffer)" ]; then g_logread="logread | tac" elif [ -r $LOGFILE ]; then g_logread="tac $LOGFILE" else echo "LOGFILE ($LOGFILE) does not exist!" >&2 exit 2 fi fi fi if [ $g_family -eq 4 ]; then if [ -n "$IPTABLES" ]; then if [ ! -x "$IPTABLES" ]; then echo " ERROR: The program specified in IPTABLES does not exist or is not executable" >&2 exit 2 fi else IPTABLES=$(mywhich iptables 2> /dev/null) if [ -z "$IPTABLES" ] ; then echo " ERROR: Can't find iptables executable" >&2 exit 2 fi fi g_tool=$IPTABLES else if [ -n "$IP6TABLES" ]; then if [ ! -x "$IP6TABLES" ]; then echo " ERROR: The program specified in IP6TABLES does not exist or is not executable" >&2 exit 2 fi else IP6TABLES=$(mywhich ip6tables 2> /dev/null) if [ -z "$IP6TABLES" ] ; then echo " ERROR: Can't find ip6tables executable" >&2 exit 2 fi fi g_tool=$IP6TABLES fi if [ -n "$IP" ]; then case "$IP" in */*) if [ ! -x "$IP" ] ; then echo " ERROR: The program specified in IP ($IP) does not exist or is not executable" >&2 exit 2 fi ;; *) prog="$(mywhich $IP 2> /dev/null)" if [ -z "$prog" ] ; then echo " ERROR: Can't find $IP executable" >&2 exit 2 fi IP=$prog ;; esac else IP='ip' fi if [ -n "$IPSET" ]; then case "$IPSET" in */*) if [ ! -x "$IPSET" ] ; then echo " ERROR: The program specified in IPSET ($IPSET) does not exist or is not executable" >&2 exit 2 fi ;; *) prog="$(mywhich $IPSET 2> /dev/null)" if [ -z "$prog" ] ; then echo " ERROR: Can't find $IPSET executable" >&2 exit 2 fi IPSET=$prog ;; esac else IPSET='ipset' fi if [ -n "$TC" ]; then case "$TC" in */*) if [ ! -x "$TC" ] ; then echo " ERROR: The program specified in TC ($TC) does not exist or is not executable" >&2 exit 2 fi ;; *) prog="$(mywhich $TC 2> /dev/null)" if [ -z "$prog" ] ; then echo " ERROR: Can't find $TC executable" >&2 exit 2 fi TC=$prog ;; esac else TC='tc' fi # # Compile by non-root needs no restore file # [ -n "$RESTOREFILE" ] || RESTOREFILE=restore validate_restorefile RESTOREFILE if [ "$2" = Yes ]; then case $STARTUP_ENABLED in No|no|NO) echo " ERROR: $g_product startup is disabled. To enable startup, set STARTUP_ENABLED=Yes in ${CONFDIR}/${g_program}.conf" >&2 exit 2 ;; Yes|yes|YES) ;; *) if [ -n "$STARTUP_ENABLED" ]; then echo " ERROR: Invalid Value for STARTUP_ENABLED: $STARTUP_ENABLED" >&2 exit 2 fi ;; esac fi case ${SHOREWALL_COMPILER:=perl} in perl|Perl) ;; shell|Shell) echo " WARNING: SHOREWALL_COMPILER=shell ignored. Shorewall-shell support has been removed in this release" >&2 ;; *) echo " ERROR: Invalid value ($SHOREWALL_COMPILER) for SHOREWALL_COMPILER" >&2 exit 2 ;; esac case ${TC_ENABLED:=Internal} in No|NO|no) TC_ENABLED= ;; esac [ -z "$LOGFORMAT" ] && LOGFORMAT='Shorewall:%s.%s' [ -n "$LOGFORMAT" ] && LOGFORMAT="${LOGFORMAT%%%*}" if [ -n "$STARTUP_LOG" ]; then if [ -n "$LOG_VERBOSITY" ]; then case $LOG_VERBOSITY in -1) ;; 0|1|2) ;; *) echo " ERROR: Invalid LOG_VERBOSITY ($LOG_VERBOSITY)" >&2 exit 2; ;; esac else LOG_VERBOSITY=2; fi else LOG_VERBOSITY=-1; fi else STARTUP_LOG= LOG_VERBOSITY=-1 fi if [ -n "$SHOREWALL_SHELL" ]; then if [ ! -x "$SHOREWALL_SHELL" ]; then echo " WARNING: The program specified in SHOREWALL_SHELL does not exist or is not executable; falling back to /bin/sh" >&2 SHOREWALL_SHELL=/bin/sh fi fi case $VERBOSITY in -1|0|1|2) ;; *) if [ -n "$VERBOSITY" ]; then echo " ERROR: Invalid VERBOSITY setting ($VERBOSITY)" >&2 exit 2 else VERBOSITY=2 fi ;; esac [ -n "$g_use_verbosity" ] && VERBOSITY=$g_use_verbosity || VERBOSITY=$(($g_verbose_offset + $VERBOSITY)) if [ $VERBOSITY -lt -1 ]; then VERBOSITY=-1 elif [ $VERBOSITY -gt 2 ]; then VERBOSITY=2 fi g_hostname=$(hostname 2> /dev/null) [ -n "$RSH_COMMAND" ] || RSH_COMMAND='ssh ${root}@${system} ${command}' [ -n "$RCP_COMMAND" ] || RCP_COMMAND='scp ${files} ${root}@${system}:${destination}' case $MANGLE_ENABLED in Yes|yes) ;; No|no) MANGLE_ENABLED= ;; *) if [ -n "$MANGLE_ENABLED" ]; then echo " ERROR: Invalid MANGLE_ENABLED setting ($MANGLE_ENABLED)" >&2 exit 2 fi ;; esac case $AUTOMAKE in Yes|yes) ;; No|no) AUTOMAKE= ;; *) if [ -n "$AUTOMAKE" ]; then echo " ERROR: Invalid AUTOMAKE setting ($AUTOMAKE)" >&2 exit 1 fi ;; esac case $LOAD_HELPERS_ONLY in Yes|yes) ;; No|no) LOAD_HELPERS_ONLY= ;; *) if [ -n "$LOAD_HELPERS_ONLY" ]; then echo " ERROR: Invalid LOAD_HELPERS_ONLY setting ($LOAD_HELPERS_ONLY)" >&2 exit 1 fi ;; esac case $LEGACY_FASTSTART in Yes|yes) ;; No|no) LEGACY_FASTSTART= ;; *) if [ -n "$LEGACY_FASTSTART" ]; then echo " ERROR: Invalid LEGACY_FASTSTART setting ($LEGACY_FASTSTART)" >&2 exit 1 fi LEGACY_FASTSTART=Yes ;; esac } # # Issue an error message and die # startup_error() { echo " ERROR: $@" >&2 kill $$ exit 1 } # # Determine if there are config files newer than the passed object # uptodate() { [ -x $1 ] || return 1 local dir local ifs ifs="$IFS" IFS=':' for dir in $CONFIG_PATH; do if [ -n "$(find ${dir} -newer $1)" ]; then IFS="$ifs" return 1; fi done IFS="$ifs" return 0 } # # Run the compiler # compiler() { local pc pc=$g_libexec/shorewall/compiler.pl if [ $(id -u) -ne 0 ]; then if [ -z "$SHOREWALL_DIR" -o "$SHOREWALL_DIR" = /etc/$g_program ]; then startup_error "Ordinary users may not compile the /etc/$g_program configuration" fi fi # # We've now set SHOREWALL_DIR so recalculate CONFIG_PATH # ensure_config_path # # Get the config from $SHOREWALL_DIR # [ -n "$SHOREWALL_DIR" -a "$SHOREWALL_DIR" != /etc/$g_program ] && get_config case $COMMAND in *start|try|refresh) ;; *) STARTUP_LOG= LOG_VERBOSITY=-1 ;; esac debugflags="-w" [ -n "$g_debug" ] && debugflags='-wd' [ -n "$g_profile" ] && debugflags='-wd:DProf' # Perl compiler only takes the output file as a argument [ "$1" = debug -o "$1" = trace ] && shift; [ "$1" = nolock ] && shift; shift options="--verbose=$VERBOSITY --family=$g_family --config_path=$CONFIG_PATH" [ -n "$STARTUP_LOG" ] && options="$options --log=$STARTUP_LOG" [ -n "$LOG_VERBOSITY" ] && options="$options --log_verbosity=$LOG_VERBOSITY"; [ -n "$g_export" ] && options="$options --export" [ -n "$SHOREWALL_DIR" ] && options="$options --directory=$SHOREWALL_DIR" [ -n "$g_timestamp" ] && options="$options --timestamp" [ -n "$g_test" ] && options="$options --test" [ -n "$g_preview" ] && options="$options --preview" [ "$g_debugging" = trace ] && options="$options --debug" [ -n "$g_refreshchains" ] && options="$options --refresh=$g_refreshchains" [ -n "$g_confess" ] && options="$options --confess" [ -n "$g_update" ] && options="$options --update" [ -n "$g_convert" ] && options="$options --convert" [ -n "$g_annotate" ] && options="$options --annotate" if [ -n "$PERL" ]; then if [ ! -x "$PERL" ]; then echo " WARNING: The program specified in the PERL option does not exist or is not executable; falling back to /usr/bin/perl" >&2 PERL=/usr/bin/perl fi else PERL=/usr/bin/perl fi if [ $g_perllib = ${g_libexec}/shorewall ]; then $PERL $debugflags $pc $options $@ else PERL5LIB=$g_perllib export PERL5LIB $PERL $debugflags $pc $options $@ fi } # # Start Command Executor # start_command() { local finished finished=0 local object local rc rc=0 do_it() { if [ -n "$AUTOMAKE" ]; then [ -n "$nolock" ] || mutex_on run_it ${VARDIR}/firewall $g_debugging start rc=$? [ -n "$nolock" ] || mutex_off else progress_message3 "Compiling..." if compiler $g_debugging $nolock compile ${VARDIR}/.start; then [ -n "$nolock" ] || mutex_on run_it ${VARDIR}/.start $g_debugging start rc=$? [ -n "$nolock" ] || mutex_off else rc=$? logger -p kern.err "ERROR:$g_product start failed" fi fi exit $rc } if product_is_started; then error_message "Shorewall is already running" exit 0 fi [ -n "$STARTUP_ENABLED" ] || fatal_error "Startup is disabled" while [ $finished -eq 0 -a $# -gt 0 ]; do option=$1 case $option in -*) option=${option#-} while [ -n "$option" ]; do case $option in -) finished=1 option= ;; d*) g_debug=Yes option=${option#d} ;; f*) g_fast=Yes option=${option#f} ;; p*) [ -n "$(which conntrack)" ] || fatal_error "The '-p' option requires the conntrack utility which does not appear to be installed on this system" g_purge=Yes option=${option%p} ;; c*) AUTOMAKE= option=${option#c} ;; *) usage 1 ;; esac done shift ;; *) finished=1 ;; esac done case $# in 0) ;; 1) [ -n "$SHOREWALL_DIR" -o -n "$g_fast" ] && usage 2 if [ ! -d $1 ]; then if [ -e $1 ]; then echo "$1 is not a directory" >&2 && exit 2 else echo "Directory $1 does not exist" >&2 && exit 2 fi fi SHOREWALL_DIR=$(resolve_file $1) AUTOMAKE= ;; *) usage 1 ;; esac if [ -n "${g_fast}${AUTOMAKE}" ]; then if [ -z "$g_fast" -o -z "$LEGACY_FASTSTART" ]; then # # Automake or LEGACY_FASTSTART=No -- use the last compiled script # object=firewall else # # 'start -f' with LEGACY_FASTSTART=Yes -- use last saved configuration # object=$RESTOREFILE fi if ! uptodate ${VARDIR}/$object; then g_fast= AUTOMAKE= fi if [ -n "$g_fast" -a $object = $RESTOREFILE ]; then g_restorepath=${VARDIR}/$object [ -n "$nolock" ] || mutex_on echo Restoring Shorewall... run_it $g_restorepath restore rc=$? [ -n "$nolock" ] || mutex_off [ $rc -eq 0 ] && progress_message3 "$g_product restored from $g_restorepath" exit $rc else do_it fi else do_it fi } # # Compile Command Executor # compile_command() { local finished finished=0 while [ $finished -eq 0 ]; do [ $# -eq 0 ] && break option=$1 case $option in -*) shift option=${option#-} [ -z "$option" ] && usage 1 while [ -n "$option" ]; do case $option in e*) g_export=Yes option=${option#e} ;; p*) g_profile=Yes option=${option#p} ;; t*) g_test=Yes option=${option#t} ;; d*) g_debug=Yes; option=${option#d} ;; T*) g_confess=Yes option=${option#T} ;; -) finished=1 option= ;; *) usage 1 ;; esac done ;; *) finished=1 ;; esac done file= case $# in 0) file=${VARDIR}/firewall ;; 1) file=$1 [ -d $file ] && echo " ERROR: $file is a directory" >&2 && exit 2; ;; 2) [ -n "$SHOREWALL_DIR" ] && usage 2 if [ ! -d $1 ]; then if [ -e $1 ]; then echo "$1 is not a directory" >&2 && exit 2 else echo "Directory $1 does not exist" >&2 && exit 2 fi fi SHOREWALL_DIR=$(resolve_file $1) file=$2 ;; *) usage 1 ;; esac [ "x$file" = x- ] || progress_message3 "Compiling..." compiler $g_debugging compile $file } # # Check Command Executor # check_command() { local finished finished=0 while [ $finished -eq 0 -a $# -gt 0 ]; do option=$1 case $option in -*) option=${option#-} while [ -n "$option" ]; do case $option in -) finished=1 option= ;; e*) g_export=Yes option=${option#e} ;; p*) g_profile=Yes option=${option#p} ;; d*) g_debug=Yes; option=${option#d} ;; r*) g_preview=Yes option=${option#r} ;; T*) g_confess=Yes option=${option#T} ;; a*) g_annotate=Yes option=${option#a} ;; *) usage 1 ;; esac done shift ;; *) finished=1 ;; esac done case $# in 0) ;; 1) [ -n "$SHOREWALL_DIR" ] && usage 2 if [ ! -d $1 ]; then if [ -e $1 ]; then echo "$1 is not a directory" >&2 && exit 2 else echo "Directory $1 does not exist" >&2 && exit 2 fi fi SHOREWALL_DIR=$(resolve_file $1) ;; *) usage 1 ;; esac progress_message3 "Checking..." compiler $g_debugging $nolock check } # # Update Command Executor # update_command() { local finished finished=0 g_update=Yes while [ $finished -eq 0 -a $# -gt 0 ]; do option=$1 case $option in -*) option=${option#-} while [ -n "$option" ]; do case $option in -) finished=1 option= ;; e*) g_export=Yes option=${option#e} ;; p*) g_profile=Yes option=${option#p} ;; d*) g_debug=Yes; option=${option#d} ;; r*) g_preview=Yes option=${option#r} ;; T*) g_confess=Yes option=${option#T} ;; a*) g_annotate=Yes option=${option#a} ;; b*) g_convert=Yes option=${option#b} ;; *) usage 1 ;; esac done shift ;; *) finished=1 ;; esac done case $# in 0) ;; 1) [ -n "$SHOREWALL_DIR" ] && usage 2 if [ ! -d $1 ]; then if [ -e $1 ]; then echo "$1 is not a directory" >&2 && exit 2 else echo "Directory $1 does not exist" >&2 && exit 2 fi fi SHOREWALL_DIR=$(resolve_file $1) ;; *) usage 1 ;; esac progress_message3 "Updating..." compiler $g_debugging $nolock check } # # Restart Command Executor # restart_command() { local finished finished=0 local rc rc=0 local restorefile while [ $finished -eq 0 -a $# -gt 0 ]; do option=$1 case $option in -*) option=${option#-} while [ -n "$option" ]; do case $option in -) finished=1 option= ;; d*) g_debug=Yes option=${option#d} ;; f*) g_fast=Yes option=${option#f} ;; c*) AUTOMAKE= option=${option#c} ;; n*) g_noroutes=Yes option=${option#n} ;; p*) [ -n "$(which conntrack)" ] || fatal_error "The '-p' option requires the conntrack utility which does not appear to be installed on this system" g_purge=Yes option=${option%p} ;; *) usage 1 ;; esac done shift ;; *) finished=1 ;; esac done case $# in 0) ;; 1) [ -n "$SHOREWALL_DIR" ] && usage 2 if [ ! -d $1 ]; then if [ -e $1 ]; then echo "$1 is not a directory" >&2 && exit 2 else echo "Directory $1 does not exist" >&2 && exit 2 fi fi SHOREWALL_DIR=$(resolve_file $1) [ -n "$g_fast" ] && fatal_error "Directory may not be specified with the -f option" AUTOMAKE= ;; *) usage 1 ;; esac [ -n "$STARTUP_ENABLED" ] || fatal_error "Startup is disabled" if [ -z "$g_fast" -a -n "$AUTOMAKE" ]; then uptodate ${VARDIR}/firewall && g_fast=Yes fi if [ -z "$g_fast" ]; then progress_message3 "Compiling..." if compiler $g_debugging $nolock compile ${VARDIR}/.restart; then [ -n "$nolock" ] || mutex_on run_it ${VARDIR}/.restart $g_debugging restart rc=$? [ -n "$nolock" ] || mutex_off else rc=$? logger -p kern.err "ERROR:$g_product restart failed" fi else [ -x ${VARDIR}/firewall ] || fatal_error "No ${VARDIR}/firewall file found" [ -n "$nolock" ] || mutex_on run_it ${VARDIR}/firewall $g_debugging restart rc=$? [ -n "$nolock" ] || mutex_off fi return $rc } # # Refresh Command Executor # refresh_command() { local finished finished=0 while [ $finished -eq 0 -a $# -gt 0 ]; do option=$1 case $option in -*) option=${option#-} while [ -n "$option" ]; do case $option in -) finished=1 option= ;; *) usage 1 ;; esac done shift ;; *) finished=1 ;; esac done if [ $# -gt 0 ]; then g_refreshchains=$1 shift while [ $# -gt 0 ]; do g_refreshchains="$g_refreshchains,$1" shift done else g_refreshchains=:refresh: fi product_is_started || fatal_error "$g_product is not running" [ -n "$STARTUP_ENABLED" ] || fatal_error "Startup is disabled" progress_message3 "Compiling..." if compiler $g_debugging $nolock compile ${VARDIR}/.refresh; then [ -n "$nolock" ] || mutex_on run_it ${VARDIR}/.refresh $g_debugging refresh rc=$? [ -n "$nolock" ] || mutex_off else rc=$? fi return $rc } # # Safe-start/safe-restart Command Executor # safe_commands() { local finished finished=0 local command # test is the shell supports timed read read -t 0 junk 2> /dev/null if [ $? -eq 2 -a ! -x /bin/bash ];then echo "Your shell does not support a feature required to execute this command". exit 2 fi while [ $finished -eq 0 -a $# -gt 0 ]; do option=$1 case $option in -*) option=${option#-} while [ -n "$option" ]; do case $option in -) finished=1 option= ;; n*) g_noroutes=Yes option=${option#n} ;; *) usage 1 ;; esac done shift ;; *) finished=1 ;; esac done case $# in 0) ;; 1) [ -n "$SHOREWALL_DIR" ] && usage 2 if [ ! -d $1 ]; then if [ -e $1 ]; then echo "$1 is not a directory" >&2 && exit 2 else echo "Directory $1 does not exist" >&2 && exit 2 fi fi SHOREWALL_DIR=$(resolve_file $1) ;; *) usage 1 ;; esac [ -n "$STARTUP_ENABLED" ] || fatal_error "Startup is disabled" if product_is_started; then running=Yes else running= fi if [ "$COMMAND" = "safe-start" -a -n "$running" ]; then # the command is safe-start but the firewall is already running error_message "Shorewall is already started" exit 0 fi if [ "$COMMAND" = "safe-start" -o -z "$running" ]; then # the command is safe-start or shorewall[6] is not started yet command="start" else # the command is safe-restart and the firewall is already running command="restart" fi progress_message3 "Compiling..." if ! compiler $g_debugging nolock compile ${VARDIR}/.$command; then status=$? exit $status fi case $command in start) RESTOREFILE=NONE progress_message3 "Starting..." ;; restart) RESTOREFILE=.safe g_restorepath=${VARDIR}/.safe save_config progress_message3 "Restarting..." ;; esac [ -n "$nolock" ] || mutex_on if run_it ${VARDIR}/.$command $g_debugging $command; then echo -n "Do you want to accept the new firewall configuration? [y/n] " if read_yesno_with_timeout; then echo "New configuration has been accepted" else if [ "$command" = "restart" ]; then run_it ${VARDIR}/.safe restore else run_it ${VARDIR}/.$command clear fi [ -n "$nolock" ] || mutex_off echo "New configuration has been rejected and the old one restored" exit 2 fi fi [ -n "$nolock" ] || mutex_off } # # 'try' Command Executor # try_command() { local finished finished=0 local timeout timeout= handle_directory() { [ -n "$SHOREWALL_DIR" ] && usage 2 if [ ! -d $1 ]; then if [ -e $1 ]; then echo "$1 is not a directory" >&2 && exit 2 else echo "Directory $1 does not exist" >&2 && exit 2 fi fi SHOREWALL_DIR=$(resolve_file $1) } while [ $finished -eq 0 -a $# -gt 0 ]; do option=$1 case $option in -*) option=${option#-} while [ -n "$option" ]; do case $option in -) finished=1 option= ;; n*) g_noroutes=Yes option=${option#n} ;; *) usage 1 ;; esac done shift ;; *) finished=1 ;; esac done case $# in 0) usage 1 ;; 1) handle_directory $1 ;; 2) handle_directory $1 timeout=$2 case $timeout in *[!0-9]*) echo " ERROR: Invalid timeout ($timeout)" >&2; exit 1 ;; esac ;; *) usage 1 ;; esac [ -n "$STARTUP_ENABLED" ] || fatal_error "Startup is disabled" if product_is_started; then running=Yes else running= fi if [ -z "$running" ]; then # shorewall[6] is not started yet command="start" else # the firewall is already running command="restart" fi progress_message3 "Compiling..." if ! compiler $g_debugging $nolock compile ${VARDIR}/.$command; then status=$? exit $status fi case $command in start) RESTOREFILE=NONE progress_message3 "Starting..." ;; restart) RESTOREFILE=.try g_restorepath=${VARDIR}/.try save_config progress_message3 "Restarting..." ;; esac [ -n "$nolock" ] || mutex_on if run_it ${VARDIR}/.$command $command && [ -n "$timeout" ]; then sleep $timeout if [ "$command" = "restart" ]; then run_it ${VARDIR}/.try restore else run_it ${VARDIR}/.$command clear fi fi [ -n "$nolock" ] || mutex_off return 0 } rsh_command() { command="$*" eval $RSH_COMMAND } rcp_command() { files="$1" destination=$2 eval $RCP_COMMAND } # # [Re]load command executor # reload_command() # $* = original arguments less the command. { local verbose verbose=$(make_verbose) local file file= local capabilities capabilities= local finished finished=0 local saveit saveit= local result local directory local system local getcaps getcaps= local root root=root local libexec libexec=/usr/share litedir=/var/lib/${g_program}-lite while [ $finished -eq 0 -a $# -gt 0 ]; do option=$1 case $option in -*) option=${option#-} while [ -n "$option" ]; do case $option in -) finished=1 option= ;; s*) saveit=Yes option=${option#s} ;; c*) getcaps=Yes option=${option#c} ;; r) [ $# -gt 1 ] || fatal_error "Missing Root User name" root=$2 option= shift ;; *) usage 1 ;; esac done shift ;; *) finished=1 ;; esac done case $# in 1) directory="." system=$1 ;; 2) directory=$1 system=$2 ;; *) usage 1 ;; esac temp=$(rsh_command /sbin/${g_program}-lite show config 2> /dev/null | grep ^LITEDIR | sed 's/LITEDIR is //') [ -n "$temp" ] && litedir="$temp" temp=$(rsh_command /sbin/${g_program}-lite show config 2> /dev/null | grep ^LIBEXEC | sed 's/LIBEXEC is //') if [ -n "$temp" ]; then case $temp in /*) libexec="$temp" ;; *) libexec=/usr/$temp ;; esac fi if [ -z "$getcaps" ]; then SHOREWALL_DIR=$(resolve_file $directory) ensure_config_path capabilities=$(find_file capabilities) [ -f $capabilities ] || getcaps=Yes fi if [ -f $directory/${g_program}.conf ]; then if [ -f $directory/params ]; then . $directory/params fi . $directory/$g_program.conf ensure_config_path fi if [ -n "$getcaps" ]; then [ -n "$DONT_LOAD" ] && DONT_LOAD="$(echo $DONT_LOAD | tr ',' ' ')" progress_message "Getting Capabilities on system $system..." if [ $g_family -eq 4 ]; then if ! rsh_command "MODULESDIR=$MODULESDIR MODULE_SUFFIX=\"$MODULE_SUFFIX\" IPTABLES=$IPTABLES DONT_LOAD=\"$DONT_LOAD\" $libexec/shorewall-lite/shorecap" > $directory/capabilities; then fatal_error "Capturing capabilities on system $system failed" fi elif ! rsh_command "MODULESDIR=$MODULESDIR MODULE_SUFFIX=\"$MODULE_SUFFIX\" IP6TABLES=$IP6TABLES DONT_LOAD=\"$DONT_LOAD\" $libexec/shorewall6-lite/shorecap" > $directory/capabilities; then fatal_error "Capturing capabilities on system $system failed" fi fi file=$(resolve_file $directory/firewall) [ -n "$g_timestamp" ] && timestamp='-t' || timestamp= if $g_program $g_debugging $verbose $timestamp compile -e $directory $directory/firewall && \ progress_message3 "Copying $file and ${file}.conf to ${system}:${litedir}..." && \ rcp_command "$directory/firewall $directory/firewall.conf" ${litedir} then save=$(find_file save); [ -f $save ] && progress_message3 "Copying $save to ${system}:/etc/${g_program}-lite/" && rcp_command $save /etc/shorewall-lite/ progress_message3 "Copy complete" if [ $COMMAND = reload ]; then rsh_command "/sbin/${g_program}-lite $g_debugging $verbose $timestamp restart" && \ progress_message3 "System $system reloaded" || saveit= else rsh_command "/sbin/${g_program}-lite $g_debugging $verbose $timestamp start" && \ progress_message3 "System $system loaded" || saveit= fi if [ -n "$saveit" ]; then rsh_command "/sbin/${g_program}-lite $g_debugging $verbose $timestamp save" && \ progress_message3 "Configuration on system $system saved" fi fi } # # Export command executor # export_command() # $* = original arguments less the command. { local verbose verbose=$(make_verbose) local file file= local finished finished=0 local directory local target while [ $finished -eq 0 -a $# -gt 0 ]; do option=$1 case $option in -*) option=${option#-} while [ -n "$option" ]; do case $option in -) finished=1 option= ;; *) fatal_error "Unrecognized option \"$option\"" ;; esac done shift ;; *) finished=1 ;; esac done case $# in 1) directory="." target=$1 ;; 2) directory=$1 target=$2 ;; *) fatal_error "Invalid command syntax (\"man $g_program\" for help)" ;; esac case $target in *:*) ;; *) target=$target: ;; esac file=$(resolve_file $directory/firewall) if $g_program $g_debugging $verbose compile -e $directory $directory/firewall && \ echo "Copying $file and ${file}.conf to ${target#*@}..." && \ scp $directory/firewall $directory/firewall.conf $target then save=$(find_file save); [ -f $save ] && progress_message3 "Copying $save to ${target#*}..." && rcp_command $save $target progress_message3 "Copy complete" fi } # # Give Usage Information # usage() # $1 = exit status { echo "Usage: $(basename $0) [debug|trace] [nolock] [ -q ] [ -v[-1|{0-2}] ] [ -t ] " echo "where is one of:" echo " add [:] ... " echo " allow
..." echo " check [ -e ] [ -r ] [ -p ] [ -r ] [ -T ] [ ]" echo " clear" echo " compile [ -e ] [ -d ] [ ] [ ]" echo " delete [:] ... " echo " disable " echo " drop
..." echo " dump [ -x ]" echo " enable " echo " export [ ] [@][:]" echo " forget [ ]" echo " help" if [ $g_family -eq 4 ]; then echo " hits [ -t ]" echo " ipcalc {
/ |
}" echo " ipdecimal {
| }" echo " iprange
-
" fi echo " iptrace " echo " load [ -s ] [ -c ] [ -r ] [ ] " echo " logdrop
..." echo " logreject
..." echo " logwatch []" if [ $g_family -eq 4 ]; then echo " noiptrace " else echo " noiptrace " fi echo " refresh [ ... ]" echo " reject
..." echo " reload [ -s ] [ -c ] [ -r ] [ ] " echo " reset [ ... ]" echo " restart [ -n ] [ -p ] [-d] [ -f ] [ -c ][ ]" echo " restore [ -n ] [ ]" echo " safe-restart [ ]" echo " safe-start [ ]" echo " save [ ]" echo " show [ -x ] [ -t {filter|mangle|nat|raw|rawpost} ] [ {chain [ [ ... ]" echo " show actions" echo " show [ -f ] capabilities" echo " show classifiers" echo " show config" echo " show connections" echo " show dynamic " echo " show filters" echo " show ip" [ $g_family -eq 4 ] && echo " show ipa" echo " show [ -m ] log []" echo " show macro " echo " show macros" echo " show marks" echo " show [ -x ] mangle|nat|raw|rawpost|routing" echo " show policies" echo " show tc [ device ]" echo " show vardir" echo " show zones" echo " start [ -f ] [ -n ] [ -p ] [ -c ] [ ]" echo " status" echo " stop" echo " try [ ]" echo " update [ -b ] [ -r ] [ -T ] [ ]" echo " version [ -a ]" echo exit $1 } version_command() { local finished finished=0 local all all= local product while [ $finished -eq 0 -a $# -gt 0 ]; do option=$1 case $option in -*) option=${option#-} while [ -n "$option" ]; do case $option in -) finished=1 option= ;; a*) all=Yes option=${option#a} ;; *) usage 1 ;; esac done shift ;; *) finished=1 ;; esac done [ $# -gt 0 ] && usage 1 echo $SHOREWALL_VERSION if [ -n "$all" ]; then for product in shorewall shorewall6 shorewall-lite shorewall6-lite shorewall-init; do if [ $product != $g_program -a -f /usr/share/$product/version ]; then echo "$product: $(cat /usr/share/$product/version)" fi done fi } # # Execution begins here # g_debugging= if [ $# -gt 0 ] && [ "x$1" = "xdebug" -o "x$1" = "xtrace" ]; then g_debugging=$1 shift fi nolock= if [ $# -gt 0 ] && [ "$1" = "nolock" ]; then nolock=nolock shift fi SHOREWALL_DIR= g_noroutes= g_purge= g_ipt_options="-nv" g_fast= g_verbose_offset=0 g_use_verbosity= g_debug= g_export= g_refreshchains=:none: g_confess= g_update= g_convert= g_annotate= # # Make sure that these variables are cleared # VERBOSE= VERBOSITY= g_program=$(basename $0) if [ $g_program = shorewall6 ]; then SHAREDIR=/usr/share/shorewall6 CONFDIR=/etc/shorewall6 g_product="Shorewall6" g_family=6 g_tool= g_basedir=/usr/share/shorewall else g_program=shorewall SHAREDIR=/usr/share/shorewall CONFDIR=/etc/shorewall g_product="Shorewall" g_family=4 g_tool= g_basedir=/usr/share/shorewall fi finished=0 while [ $finished -eq 0 ]; do [ $# -eq 0 ] && usage 1 option=$1 case $option in -) finished=1 ;; -*) option=${option#-} while [ -n "$option" ]; do case $option in c) [ $# -eq 1 ] && usage 1 if [ ! -d $2 ]; then if [ -e $2 ]; then echo "$2 is not a directory" >&2 && exit 2 else echo "Directory $2 does not exist" >&2 && exit 2 fi fi SHOREWALL_DIR=$(resolve_file $2) option= shift ;; e*) g_export=Yes option=${option#e} ;; x*) g_ipt_options="-xnv" option=${option#x} ;; q*) g_verbose_offset=$(($g_verbose_offset - 1 )) option=${option#q} ;; f*) g_fast=Yes option=${option#f} ;; v*) option=${option#v} case $option in -1*) g_use_verbosity=-1 option=${option#-1} ;; 0*) g_use_verbosity=0 option=${option#0} ;; 1*) g_use_verbosity=1 option=${option#1} ;; 2*) g_use_verbosity=2 option=${option#2} ;; *) g_verbose_offset=$(($g_verbose_offset + 1 )) g_use_verbosity= ;; esac ;; n*) g_noroutes=Yes option=${option#n} ;; t*) g_timestamp=Yes option=${option#t} ;; -) finished=1 option= ;; *) usage 1 ;; esac done shift ;; *) finished=1 ;; esac done if [ $# -eq 0 ]; then usage 1 fi PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:/usr/local/sbin MUTEX_TIMEOUT= g_recovering= g_timestamp= g_libexec=/usr/share g_perllib=/usr/share/shorewall [ -f ${CONFDIR}/vardir ] && . ${CONFDIR}/vardir [ -n "${VARDIR:=/var/lib/$g_program}" ] if [ ! -f ${VARDIR}/firewall ]; then [ -f ${VARDIR}/.restore ] && cp -f ${VARDIR}/.restore ${VARDIR}/firewall fi g_firewall=${VARDIR}/firewall for library in base cli; do . /usr/share/shorewall/lib.$library done version_file=$SHAREDIR/version if [ -f $version_file ]; then SHOREWALL_VERSION=$(cat $version_file) else echo " ERROR: $g_product is not properly installed" >&2 echo " The file $version_file does not exist" >&2 exit 1 fi banner="${g_product}-${SHOREWALL_VERSION} Status at $g_hostname -" case $(echo -e) in -e*) g_ring_bell="echo \a" g_echo_e="echo" ;; *) g_ring_bell="echo -e \a" g_echo_e="echo -e" ;; esac case $(echo -n "Testing") in -n*) g_echo_n= ;; *) g_echo_n=-n ;; esac COMMAND=$1 case "$COMMAND" in start) get_config Yes Yes shift start_command $@ ;; stop|clear) [ $# -ne 1 ] && usage 1 get_config [ -x $g_firewall ] || fatal_error "$g_product has never been started" [ -n "$nolock" ] || mutex_on run_it $g_firewall $g_debugging $COMMAND [ -n "$nolock" ] || mutex_off ;; reset) get_config shift [ -n "$nolock" ] || mutex_on [ -x $g_firewall ] || fatal_error "$g_product has never been started" run_it $g_firewall $g_debugging reset $@ [ -n "$nolock" ] || mutex_off ;; compile) get_config Yes shift compile_command $@ ;; restart) get_config Yes Yes shift restart_command $@ ;; refresh) get_config Yes Yes shift refresh_command $@ ;; check) get_config Yes shift check_command $@ ;; update) get_config Yes shift update_command $@ ;; disable|enable) get_config Yes if product_is_started; then run_it ${VARDIR}/firewall $g_debugging $@ else fatal_error "Shorewall is not running" fi ;; show|list) get_config Yes No Yes shift show_command $@ ;; load|reload) get_config Yes shift reload_command $@ ;; export) get_config Yes shift export_command $@ ;; status) [ $# -eq 1 ] || usage 1 [ "$(id -u)" != 0 ] && fatal_error "The status command may only be run by root" get_config echo "${g_product}-$SHOREWALL_VERSION Status at $g_hostname - $(date)" echo if product_is_started ; then echo "$g_product is running" status=0 else echo "$g_product is stopped" status=4 fi if [ -f ${VARDIR}/state ]; then state="$(cat ${VARDIR}/state)" case $state in Stopped*|Closed*|Clear*) status=3 ;; esac else state=Unknown fi echo "State:$state" echo exit $status ;; dump) get_config Yes No Yes shift dump_command $@ ;; hits) [ $g_family -eq 6 ] && usage 1 get_config Yes No Yes [ -n "$g_debugging" ] && set -x shift hits_command $@ ;; version) shift version_command $@ ;; try) get_config Yes shift try_command $@ ;; logwatch) get_config Yes Yes Yes banner="${g_product}-$SHOREWALL_VERSION Logwatch at $g_hostname -" logwatch_command $@ ;; drop) get_config [ -n "$g_debugging" ] && set -x [ $# -eq 1 ] && usage 1 if product_is_started ; then if ! chain_exists dynamic; then echo "Dynamic blacklisting is not supported in the current $g_product configuration" exit 2 fi [ -n "$nolock" ] || mutex_on block DROP Dropped $* [ -n "$nolock" ] || mutex_off else fatal_error "$g_product is not started" fi ;; logdrop) get_config [ -n "$g_debugging" ] && set -x [ $# -eq 1 ] && usage 1 if product_is_started ; then if ! chain_exists dynamic; then echo "Dynamic blacklisting is not supported in the current $g_product configuration" exit 2 fi [ -n "$nolock" ] || mutex_on block logdrop Dropped $* [ -n "$nolock" ] || mutex_off else fatal_error "$g_product is not started" fi ;; reject|logreject) get_config [ -n "$g_debugging" ] && set -x [ $# -eq 1 ] && usage 1 if product_is_started ; then [ -n "$nolock" ] || mutex_on block $COMMAND Rejected $* [ -n "$nolock" ] || mutex_off else fatal_error "$g_product is not started" fi ;; allow) get_config allow_command $@ ;; add) get_config shift add_command $@ ;; delete) get_config shift delete_command $@ ;; save) get_config [ -n "$g_debugging" ] && set -x case $# in 1) ;; 2) RESTOREFILE="$2" validate_restorefile '' ;; *) usage 1 ;; esac g_restorepath=${VARDIR}/$RESTOREFILE [ -n "$nolock" ] || mutex_on save_config result=$? [ -n "$nolock" ] || mutex_off exit $result ;; forget) get_config case $# in 1) ;; 2) RESTOREFILE="$2" validate_restorefile '' ;; *) usage 1 ;; esac g_restorepath=${VARDIR}/$RESTOREFILE if [ -x $g_restorepath ]; then rm -f $g_restorepath rm -f ${g_restorepath}-iptables rm -f ${g_restorepath}-ipsets echo " $g_restorepath removed" elif [ -f $g_restorepath ]; then echo " $g_restorepath exists and is not a saved $g_product configuration" fi rm -f ${VARDIR}/save ;; ipcalc) [ $g_family -eq 6 ] && usage 1 [ -n "$g_debugging" ] && set -x if [ $# -eq 2 ]; then address=${2%/*} vlsm=${2#*/} elif [ $# -eq 3 ]; then address=$2 vlsm=$(ip_vlsm $3) else usage 1 fi valid_address $address || fatal_error "Invalid IP address: $address" [ -z "$vlsm" ] && exit 2 [ "x$address" = "x$vlsm" ] && usage 2 [ $vlsm -gt 32 ] && echo "Invalid VLSM: /$vlsm" >&2 && exit 2 address=$address/$vlsm echo " CIDR=$address" temp=$(ip_netmask $address); echo " NETMASK=$(encodeaddr $temp)" temp=$(ip_network $address); echo " NETWORK=$temp" temp=$(broadcastaddress $address); echo " BROADCAST=$temp" ;; iprange) [ -n "$g_debugging" ] && set -x range='' while [ $# -gt 0 ]; do shift range="${range}${1}" done case $range in *.*.*.*-*.*.*.*) for address in ${range%-*} ${range#*-}; do valid_address $address || fatal_error "Invalid IP address: $address" done ip_range $range ;; *) usage 1 ;; esac ;; ipdecimal) [ -n "$g_debugging" ] && set -x [ $# -eq 2 ] || usage 1 case $2 in *.*.*.*) valid_address $2 || fatal_error "Invalid IP address: $2" echo " $(decodeaddr $2)" ;; *) echo " $(encodeaddr $2)" ;; esac ;; restore) get_config shift restore_command $@ ;; call) get_config [ -n "$g_debugging" ] && set -x # # Undocumented way to call functions in ${SHAREDIR}/functions directly # shift $@ ;; help) shift usage ;; safe-restart|safe-start) get_config Yes shift safe_commands $@ ;; iptrace) get_config shift if shorewall_is_started ; then $g_tool -t raw -A PREROUTING $@ -j TRACE $g_tool -t raw -A OUTPUT $@ -j TRACE else fatal_error "$g_product is not started" fi ;; noiptrace) get_config shift if shorewall_is_started ; then $g_tool -t raw -D PREROUTING $@ -j TRACE $g_tool -t raw -D OUTPUT $@ -j TRACE else fatal_error "$g_product is not started" fi ;; *) usage 1 ;; esac