# # Shorewall 4.4 -- /usr/share/shorewall6/lib.common. # # This program is under GPL [http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt] # # (c) 2010 - 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # # This library contains the wrapper code for running a generated script. # # # Get the Shorewall version of the passed script # get_script_version() { # $1 = script local temp local version local ifs local digits local verbosity verbosity="$VERBOSITY" VERBOSITY=0 temp=$( $SHOREWALL_SHELL $1 version | sed 's/-.*//' ) if [ -z "$temp" ]; then version=0 else ifs=$IFS IFS=. temp=$(echo $temp) IFS=$ifs digits=0 for temp in $temp; do version=${version}$(printf '%02d' $temp) digits=$(($digits + 1)) [ $digits -eq 3 ] && break done fi echo $version VERBOSITY="$verbosity" } # # Do required exports and create the required option string and run the passed script using # $SHOREWALL_SHELL # run_it() { local script local options local version export VARDIR script=$1 shift version=$(get_script_version $script) if [ $version -lt 040408 ]; then # # Old script that doesn't understand 4.4.8 script options # export RESTOREFILE= export VERBOSITY export NOROUTES=$g_noroutes export PURGE=$g_purge export TIMESTAMP=$g_timestamp export RECOVERING=$g_recovering if [ "$g_product" != Shorewall6 ]; then # # Shorewall6 Lite # export LOGFORMAT export IP6TABLES fi else # # 4.4.8 or later -- no additional exports required # if [ x$1 = xtrace -o x$1 = xdebug ]; then options="$1 -" shift; else options='-' fi [ -n "$g_noroutes" ] && options=${options}n [ -n "$g_timestamp" ] && options=${options}t [ -n "$g_purge" ] && options=${options}p [ -n "$g_recovering" ] && options=${options}r options="${options}V $VERBOSITY" [ -n "$RESTOREFILE" ] && options="${options} -R $RESTOREFILE" fi $SHOREWALL_SHELL $script $options $@ } # # Message to stderr # error_message() # $* = Error Message { echo " $@" >&2 } # # Split a colon-separated list into a space-separated list # split() { local ifs ifs=$IFS IFS=: echo $* IFS=$ifs } # # Undo the effect of 'split()' # join() { local f local o o= for f in $* ; do o="${o:+$o:}$f" done echo $o } # # Return the number of elements in a list # list_count() # $* = list { return $# } # # Search a list looking for a match -- returns zero if a match found # 1 otherwise # list_search() # $1 = element to search for , $2-$n = list { local e e=$1 while [ $# -gt 1 ]; do shift [ "x$e" = "x$1" ] && return 0 done return 1 } # # Suppress all output for a command # qt() { "$@" >/dev/null 2>&1 } # # Suppress all output and input - mainly for preventing leaked file descriptors # to avoid SELinux denials # qtnoin() { "$@" /dev/null 2>&1 } qt1() { local status while [ 1 ]; do "$@" /dev/null 2>&1 status=$? [ $status -ne 4 ] && return $status done } # # Determine if Shorewall is "running" # shorewall6_is_started() { qt1 $IP6TABLES -L shorewall -n } # # Echos the fully-qualified name of the calling shell program # my_pathname() { cd $(dirname $0) echo $PWD/$(basename $0) } # # Source a user exit file if it exists # run_user_exit() # $1 = file name { local user_exit user_exit=$(find_file $1) if [ -f $user_exit ]; then progress_message "Processing $user_exit ..." . $user_exit fi } # # Load a Kernel Module -- assumes that the variable 'moduledirectories' contains # a space-separated list of directories to search for # the module and that 'moduleloader' contains the # module loader command. # loadmodule() # $1 = module name, $2 - * arguments { local modulename modulename=$1 local modulefile local suffix if [ -d /sys/module/ ]; then if [ ! -d /sys/module/$modulename ]; then shift for suffix in $MODULE_SUFFIX ; do for directory in $moduledirectories; do modulefile=$directory/${modulename}.${suffix} if [ -f $modulefile ]; then case $moduleloader in insmod) insmod $modulefile $* ;; *) modprobe $modulename $* ;; esac break 2 fi done done fi elif ! list_search $modulename $MODULES $DONT_LOAD ; then shift for suffix in $MODULE_SUFFIX ; do for directory in $moduledirectories; do modulefile=$directory/${modulename}.${suffix} if [ -f $modulefile ]; then case $moduleloader in insmod) insmod $modulefile $* ;; *) modprobe $modulename $* ;; esac break 2 fi done done fi } # # Reload the Modules # reload_kernel_modules() { local save_modules_dir save_modules_dir=$MODULESDIR local directory local moduledirectories moduledirectories= local moduleloader moduleloader=modprobe if ! qt mywhich modprobe; then moduleloader=insmod fi [ -n "${MODULE_SUFFIX:=ko ko.gz o o.gz gz}" ] [ -z "$MODULESDIR" ] && MODULESDIR=/lib/modules/$(uname -r)/kernel/net/ipv6/netfilter:/lib/modules/$(uname -r)/kernel/net/netfilter:/lib/modules/$(uname -r)/kernel/net/sched [ -d /sys/module/ ] || MODULES=$(lsmod | cut -d ' ' -f1) for directory in $(split $MODULESDIR); do [ -d $directory ] && moduledirectories="$moduledirectories $directory" done [ -n "$moduledirectories" ] && while read command; do eval $command done MODULESDIR=$save_modules_dir } # # Load kernel modules required for Shorewall # load_kernel_modules() # $1 = Yes, if we are to save moduleinfo in $VARDIR { local save_modules_dir save_modules_dir=$MODULESDIR local directory local moduledirectories moduledirectories= local moduleloader moduleloader=modprobe local savemoduleinfo savemoduleinfo=${1:-Yes} # So old compiled scripts still work if ! qt mywhich modprobe; then moduleloader=insmod fi [ -n "${MODULE_SUFFIX:=o gz ko o.gz ko.gz}" ] [ -z "$MODULESDIR" ] && \ MODULESDIR=/lib/modules/$(uname -r)/kernel/net/ipv6/netfilter:/lib/modules/$(uname -r)/kernel/net/netfilter:/lib/modules/$(uname -r)/kernel/net/sched for directory in $(split $MODULESDIR); do [ -d $directory ] && moduledirectories="$moduledirectories $directory" done [ -n "$LOAD_HELPERS_ONLY" ] && modules=$(find_file helpers) || modules=$(find_file modules) if [ -f $modules -a -n "$moduledirectories" ]; then [ -d /sys/module/ ] || MODULES=$(lsmod | cut -d ' ' -f1) progress_message "Loading Modules..." . $modules if [ $savemoduleinfo = Yes ]; then [ -d ${VARDIR} ] || mkdir -p ${VARDIR} echo MODULESDIR="$MODULESDIR" > ${VARDIR}/.modulesdir cp -f $modules ${VARDIR}/.modules fi elif [ $savemoduleinfo = Yes ]; then [ -d ${VARDIR} ] || mkdir -p ${VARDIR} > ${VARDIR}/.modulesdir > ${VARDIR}/.modules fi MODULESDIR=$save_modules_dir } # # Query NetFilter about the existence of a filter chain # chain_exists() # $1 = chain name { qt1 $IP6TABLES -L $1 -n } # # Find the interface with the passed MAC address # find_interface_by_mac() { local mac mac=$1 local first local second local rest local dev $IP link list | while read first second rest; do case $first in *:) dev=$second ;; *) if [ "$second" = $mac ]; then echo ${dev%:} return fi esac done } # # Find interface address--returns the first IP address assigned to the passed # device # find_first_interface_address() # $1 = interface { # # get the line of output containing the first IP address # addr=$(${IP:-ip} -f inet6 addr show $1 2> /dev/null | grep 'inet6 .* global' | head -n1) # # If there wasn't one, bail out now # [ -n "$addr" ] || startup_error "Can't determine the IPv6 address of $1" # # Strip off the trailing VLSM mask (or the peer IP in case of a P-t-P link) # along with everything else on the line # echo $addr | sed 's/\s*inet6 //;s/\/.*//;s/ peer.*//' } find_first_interface_address_if_any() # $1 = interface { # # get the line of output containing the first IP address # addr=$(${IP:-ip} -f inet6 addr show $1 2> /dev/null | grep 'inet6 2.* global' | head -n1) # # Strip off the trailing VLSM mask (or the peer IP in case of a P-t-P link) # along with everything else on the line # [ -n "$addr" ] && echo $addr | sed 's/\s*inet6 //;s/\/.*//;s/ peer.*//' || echo :: } # # Internal version of 'which' # mywhich() { local dir for dir in $(split $PATH); do if [ -x $dir/$1 ]; then echo $dir/$1 return 0 fi done return 2 } # # Find a File -- For relative file name, look in each ${CONFIG_PATH} then ${CONFDIR} # find_file() { local saveifs saveifs= local directory case $1 in /*) echo $1 ;; *) for directory in $(split $CONFIG_PATH); do if [ -f $directory/$1 ]; then echo $directory/$1 return fi done echo ${CONFDIR}/$1 ;; esac } # # Set the Shorewall state # set_state () # $1 = state { if [ $# -gt 1 ]; then echo "$1 ($(date)) from $2" > ${VARDIR}/state else echo "$1 ($(date))" > ${VARDIR}/state fi } # # Perform variable substitution on the passed argument and echo the result # expand() # $@ = contents of variable which may be the name of another variable { eval echo \"$@\" } # # Function for including one file into another # INCLUDE() { . $(find_file $(expand $@)) } # Function to truncate a string -- It uses 'cut -b -' # rather than ${v:first:last} because light-weight shells like ash and # dash do not support that form of expansion. # truncate() # $1 = length { cut -b -${1} }