#!/bin/sh # # Shorewall 4.2 -- /usr/share/shorewall/lib.base # # 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 - 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 code common to all Shorewall components. # # - It is loaded by /sbin/shorewall. # - It is loaded by /usr/share/shorewall/firewall. # - It is released as part of Shorewall Lite where it is used by /sbin/shorewall-lite # and /usr/share/shorewall-lite/shorecap. # SHOREWALL_LIBVERSION=40000 SHOREWALL_CAPVERSION=40406 [ -n "${VARDIR:=/var/lib/shorewall}" ] [ -n "${SHAREDIR:=/usr/share/shorewall}" ] [ -n "${CONFDIR:=/etc/shorewall}" ] # # Message to stderr # error_message() # $* = Error Message { echo " $@" >&2 } # # Conditionally produce message # progress_message() # $* = Message { local timestamp timestamp= if [ $VERBOSE -gt 1 ]; then [ -n "$TIMESTAMP" ] && timestamp="$(date +%H:%M:%S) " echo "${timestamp}$@" fi } progress_message2() # $* = Message { local timestamp timestamp= if [ $VERBOSE -gt 0 ]; then [ -n "$TIMESTAMP" ] && timestamp="$(date +%H:%M:%S) " echo "${timestamp}$@" fi } progress_message3() # $* = Message { local timestamp timestamp= if [ $VERBOSE -ge 0 ]; then [ -n "$TIMESTAMP" ] && timestamp="$(date +%H:%M:%S) " echo "${timestamp}$@" fi } # # Split a colon-separated list into a space-separated list # split() { local ifs ifs=$IFS IFS=: echo $* IFS=$ifs } # # 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 } # # Undo the effect of 'separate_list()' # combine_list() { local f local o o= for f in $* ; do o="${o:+$o,}$f" done echo $o } # # Suppress all output for a command # qt() { "$@" >/dev/null 2>&1 } # # Determine if Shorewall is "running" # shorewall_is_started() { qt $IPTABLES -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 ! 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 local uname if ! qt mywhich modprobe; then moduleloader=insmod fi [ -n "${MODULE_SUFFIX:=o gz ko o.gz ko.gz}" ] [ -z "$MODULESDIR" ] && \ uname=$(uname -r) && \ MODULESDIR=/lib/modules/$uname/kernel/net/ipv4/netfilter:/lib/modules/$uname/kernel/net/netfilter:/lib/modules/$uname/kernel/net/sched:/lib/modules/$uname/extra:/lib/modules/$uname/extra/ipset 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 local uname if ! qt mywhich modprobe; then moduleloader=insmod fi [ -n "${MODULE_SUFFIX:=o gz ko o.gz ko.gz}" ] [ -z "$MODULESDIR" ] && \ uname=$(uname -r) && \ MODULESDIR=/lib/modules/$uname/kernel/net/ipv4/netfilter:/lib/modules/$uname/kernel/net/netfilter:/lib/modules/$uname/kernel/net/sched:/lib/modules/$uname/extra:/lib/modules/$uname/extra/ipset for directory in $(split $MODULESDIR); do [ -d $directory ] && moduledirectories="$moduledirectories $directory" done modules=$(find_file modules) if [ -f $modules -a -n "$moduledirectories" ]; then 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 } # # Call this function to assert mutual exclusion with Shorewall. If you invoke the # /sbin/shorewall program while holding mutual exclusion, you should pass "nolock" as # the first argument. Example "shorewall nolock refresh" # # This function uses the lockfile utility from procmail if it exists. # Otherwise, it uses a somewhat race-prone algorithm to attempt to simulate the # behavior of lockfile. # mutex_on() { local try try=0 local lockf lockf=${LOCKFILE:=${VARDIR}/lock} MUTEX_TIMEOUT=${MUTEX_TIMEOUT:-60} if [ $MUTEX_TIMEOUT -gt 0 ]; then [ -d ${VARDIR} ] || mkdir -p ${VARDIR} if qt mywhich lockfile; then lockfile -${MUTEX_TIMEOUT} -r1 ${lockf} else while [ -f ${lockf} -a ${try} -lt ${MUTEX_TIMEOUT} ] ; do sleep 1 try=$((${try} + 1)) done if [ ${try} -lt ${MUTEX_TIMEOUT} ] ; then # Create the lockfile echo $$ > ${lockf} else echo "Giving up on lock file ${lockf}" >&2 fi fi fi } # # Call this function to release mutual exclusion # mutex_off() { rm -f ${LOCKFILE:=${VARDIR}/lock} } # # Note: The following set of IP address manipulation functions have anomalous # behavior when the shell only supports 32-bit signed arithmetic and # the IP address is 128.0.0.0 or 128.0.0.1. # LEFTSHIFT='<<' # # Validate an IP address # valid_address() { local x local y local ifs ifs=$IFS IFS=. for x in $1; do case $x in [0-9]|[0-9][0-9]|[1-2][0-9][0-9]) [ $x -lt 256 ] || { IFS=$ifs; return 2; } ;; *) IFS=$ifs return 2 ;; esac done IFS=$ifs return 0 } # # Convert an IP address in dot quad format to an integer # decodeaddr() { local x local temp temp=0 local ifs ifs=$IFS IFS=. for x in $1; do temp=$(( $(( $temp $LEFTSHIFT 8 )) | $x )) done echo $temp IFS=$ifs } # # convert an integer to dot quad format # encodeaddr() { addr=$1 local x local y y=$(($addr & 255)) for x in 1 2 3 ; do addr=$(($addr >> 8)) y=$(($addr & 255)).$y done echo $y } # # Miserable Hack to work around broken BusyBox ash in OpenWRT # addr_comp() { test $(bc < $2 EOF ) -eq 1 } # # Enumerate the members of an IP range -- When using a shell supporting only # 32-bit signed arithmetic, the range cannot span 128.0.0.0. # # Comes in two flavors: # # ip_range() - produces a mimimal list of network/host addresses that spans # the range. # # ip_range_explicit() - explicitly enumerates the range. # ip_range() { local first local last local l local x local y local z local vlsm case $1 in !*) # # Let iptables complain if it's a range # echo $1 return ;; [0-9]*.*.*.*-*.*.*.*) ;; *) echo $1 return ;; esac first=$(decodeaddr ${1%-*}) last=$(decodeaddr ${1#*-}) if addr_comp $first $last; then fatal_error "Invalid IP address range: $1" fi l=$(( $last + 1 )) while addr_comp $l $first; do vlsm= x=31 y=2 z=1 while [ $(( $first % $y )) -eq 0 ] && ! addr_comp $(( $first + $y )) $l; do vlsm=/$x x=$(( $x - 1 )) z=$y y=$(( $y * 2 )) done echo $(encodeaddr $first)$vlsm first=$(($first + $z)) done } ip_range_explicit() { local first local last case $1 in [0-9]*.*.*.*-*.*.*.*) ;; *) echo $1 return ;; esac first=$(decodeaddr ${1%-*}) last=$(decodeaddr ${1#*-}) if addr_comp $first $last; then fatal_error "Invalid IP address range: $1" fi while ! addr_comp $first $last; do echo $(encodeaddr $first) first=$(($first + 1)) done } # # Netmask from CIDR # ip_netmask() { local vlsm vlsm=${1#*/} [ $vlsm -eq 0 ] && echo 0 || echo $(( -1 $LEFTSHIFT $(( 32 - $vlsm )) )) } # # Network address from CIDR # ip_network() { local decodedaddr decodedaddr=$(decodeaddr ${1%/*}) local netmask netmask=$(ip_netmask $1) echo $(encodeaddr $(($decodedaddr & $netmask))) } # # The following hack is supplied to compensate for the fact that many of # the popular light-weight Bourne shell derivatives don't support XOR ("^"). # ip_broadcast() { local x x=$(( 32 - ${1#*/} )) [ $x -eq 32 ] && echo -1 || echo $(( $(( 1 $LEFTSHIFT $x )) - 1 )) } # # Calculate broadcast address from CIDR # broadcastaddress() { local decodedaddr decodedaddr=$(decodeaddr ${1%/*}) local netmask netmask=$(ip_netmask $1) local broadcast broadcast=$(ip_broadcast $1) echo $(encodeaddr $(( $(($decodedaddr & $netmask)) | $broadcast ))) } # # Test for network membership # in_network() # $1 = IP address, $2 = CIDR network { local netmask netmask=$(ip_netmask $2) # # We compare the values as strings rather than integers to work around broken BusyBox ash on OpenWRT # test $(( $(decodeaddr $1) & $netmask)) = $(( $(decodeaddr ${2%/*}) & $netmask )) } # # Netmask to VLSM # ip_vlsm() { local mask mask=$(decodeaddr $1) local vlsm vlsm=0 local x x=$(( 128 << 24 )) # 0x80000000 while [ $(( $x & $mask )) -ne 0 ]; do [ $mask -eq $x ] && mask=0 || mask=$(( $mask $LEFTSHIFT 1 )) # Not all shells shift 0x80000000 left properly. vlsm=$(($vlsm + 1)) done if [ $(( $mask & 2147483647 )) -ne 0 ]; then # 2147483647 = 0x7fffffff echo "Invalid net mask: $1" >&2 else echo $vlsm fi } # # Query NetFilter about the existence of a filter chain # chain_exists() # $1 = chain name { qt $IPTABLES -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 -f inet addr show $1 2> /dev/null | grep 'inet .* global' | head -n1) # # If there wasn't one, bail out now # [ -n "$addr" ] || fatal_error "Can't determine the IP 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*inet //;s/\/.*//;s/ peer.*//' } find_first_interface_address_if_any() # $1 = interface { # # get the line of output containing the first IP address # addr=$(ip -f inet addr show $1 2> /dev/null | grep 'inet .* 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*inet //;s/\/.*//;s/ peer.*//' || echo 0.0.0.0 } # # 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 } # # Set default config path # ensure_config_path() { local F F=${SHAREDIR}/configpath if [ -z "$CONFIG_PATH" ]; then [ -f $F ] || { echo " ERROR: $F does not exist"; exit 2; } . $F fi if [ -n "$SHOREWALL_DIR" ]; then [ "${CONFIG_PATH%%:*}" = "$SHOREWALL_DIR" ] || CONFIG_PATH=$SHOREWALL_DIR:$CONFIG_PATH fi } # # 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 } # # Get fully-qualified name of file # resolve_file() # $1 = file name { local pwd pwd=$PWD case $1 in /*) echo $1 ;; .) echo $pwd ;; ./*) echo ${pwd}${1#.} ;; ..) cd .. echo $PWD cd $pwd ;; ../*) cd .. resolve_file ${1#../} cd $pwd ;; *) echo $pwd/$1 ;; esac } # # 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 $@)) } # # Set the Shorewall state # set_state () # $1 = state { echo "$1 ($(date))" > ${VARDIR}/state } # # Determine which optional facilities are supported by iptables/netfilter # determine_capabilities() { [ -n "$IPTABLES" ] || IPTABLES=$(mywhich iptables) if [ -z "$IPTABLES" ]; then echo " ERROR: No executable iptables binary can be found on your PATH" >&2 exit 1 fi qt $IPTABLES -t nat -L -n && NAT_ENABLED=Yes || NAT_ENABLED= qt $IPTABLES -t mangle -L -n && MANGLE_ENABLED=Yes || MANGLE_ENABLED= CONNTRACK_MATCH= NEW_CONNTRACK_MATCH= OLD_CONNTRACK_MATCH= MULTIPORT= XMULTIPORT= POLICY_MATCH= PHYSDEV_MATCH= PHYSDEV_BRIDGE= IPRANGE_MATCH= RECENT_MATCH= OWNER_MATCH= IPSET_MATCH= CONNMARK= XCONNMARK= CONNMARK_MATCH= XCONNMARK_MATCH= RAW_TABLE= IPP2P_MATCH= OLD_IPP2P_MATCH= LENGTH_MATCH= CLASSIFY_TARGET= ENHANCED_REJECT= USEPKTTYPE= KLUDGEFREE= MARK= XMARK= MANGLE_FORWARD= COMMENTS= ADDRTYPE= TCPMSS_MATCH= HASHLIMIT_MATCH= NFQUEUE_TARGET= REALM_MATCH= HELPER_MATCH= CONNLIMIT_MATCH= TIME_MATCH= GOTO_TARGET= LOGMARK_TARGET= IPMARK_TARGET= LOG_TARGET=Yes PERSISTENT_SNAT= chain=fooX$$ if [ -n "$NAT_ENABLED" ]; then if qt $IPTABLES -t nat -N $chain; then qt $IPTABLES -t nat -A $chain -j SNAT --to-source 1.2.3.4 --persistent && PERSISTENT_SNAT=Yes qt $IPTABLES -t nat -F $chain qt $IPTABLES -t nat -X $chain fi fi qt $IPTABLES -F $chain qt $IPTABLES -X $chain if ! $IPTABLES -N $chain; then echo " ERROR: The command \"$IPTABLES -N $chain\" failed" >&2 exit 1 fi chain1=${chain}1 qt $IPTABLES -F $chain1 qt $IPTABLES -X $chain1 if ! $IPTABLES -N $chain1; then echo " ERROR: The command \"$IPTABLES -N $chain1\" failed" >&2 exit 1 fi if ! qt $IPTABLES -A $chain -m state --state ESTABLISHED,RELATED -j ACCEPT; then echo " ERROR: Your kernel lacks connection tracking and/or state matching -- Shorewall will not run on this system" >&2 exit 1 fi qt $IPTABLES -A $chain -m conntrack --ctorigdst 192.168.1.1 -j ACCEPT && CONNTRACK_MATCH=Yes if [ -n "$CONNTRACK_MATCH" ]; then qt $IPTABLES -A $chain -m conntrack -p tcp --ctorigdstport 22 -j ACCEPT && NEW_CONNTRACK_MATCH=Yes qt $IPTABLES -A $chain -m conntrack ! --ctorigdst 1.2.3.4 || OLD_CONNTRACK_MATCH=Yes fi if qt $IPTABLES -A $chain -p tcp -m multiport --dports 21,22 -j ACCEPT; then MULTIPORT=Yes qt $IPTABLES -A $chain -p tcp -m multiport --sports 60 -m multiport --dports 99 -j ACCEPT && KLUDEFREE=Yes fi qt $IPTABLES -A $chain -p tcp -m multiport --dports 21:22 -j ACCEPT && XMULTIPORT=Yes qt $IPTABLES -A $chain -m policy --pol ipsec --mode tunnel --dir in -j ACCEPT && POLICY_MATCH=Yes if qt $IPTABLES -A $chain -m physdev --physdev-out eth0 -j ACCEPT; then PHYSDEV_MATCH=Yes qt $IPTABLES -A $chain -m physdev --physdev-is-bridged --physdev-in eth0 --physdev-out eth0 -j ACCEPT && PHYSDEV_BRIDGE=Yes if [ -z "${KLUDGEFREE}" ]; then qt $IPTABLES -A $chain -m physdev --physdev-in eth0 -m physdev --physdev-out eth0 -j ACCEPT && KLUDGEFREE=Yes fi fi if qt $IPTABLES -A $chain -m iprange --src-range 192.168.1.5-192.168.1.124 -j ACCEPT; then IPRANGE_MATCH=Yes if [ -z "${KLUDGEFREE}" ]; then qt $IPTABLES -A $chain -m iprange --src-range 192.168.1.5-192.168.1.124 -m iprange --dst-range 192.168.1.5-192.168.1.124 -j ACCEPT && KLUDGEFREE=Yes fi fi qt $IPTABLES -A $chain -m recent --update -j ACCEPT && RECENT_MATCH=Yes qt $IPTABLES -A $chain -m owner --uid-owner 0 -j ACCEPT && OWNER_MATCH=Yes if qt $IPTABLES -A $chain -m connmark --mark 2 -j ACCEPT; then CONNMARK_MATCH=Yes qt $IPTABLES -A $chain -m connmark --mark 2/0xFF -j ACCEPT && XCONNMARK_MATCH=Yes fi qt $IPTABLES -A $chain -p tcp -m ipp2p --edk -j ACCEPT && IPP2P_MATCH=Yes if [ -n "$IPP2P_MATCH" ]; then qt $IPTABLES -A $chain -p tcp -m ipp2p --ipp2p -j ACCEPT && OLD_IPP2P_MATCH=Yes fi qt $IPTABLES -A $chain -m length --length 10:20 -j ACCEPT && LENGTH_MATCH=Yes qt $IPTABLES -A $chain -j REJECT --reject-with icmp-host-prohibited && ENHANCED_REJECT=Yes qt $IPTABLES -A $chain -j ACCEPT -m comment --comment "This is a comment" && COMMENTS=Yes if [ -n "$MANGLE_ENABLED" ]; then qt $IPTABLES -t mangle -N $chain if qt $IPTABLES -t mangle -A $chain -j MARK --set-mark 1; then MARK=Yes qt $IPTABLES -t mangle -A $chain -j MARK --and-mark 0xFF && XMARK=Yes fi if qt $IPTABLES -t mangle -A $chain -j CONNMARK --save-mark; then CONNMARK=Yes qt $IPTABLES -t mangle -A $chain -j CONNMARK --save-mark --mask 0xFF && XCONNMARK=Yes fi qt $IPTABLES -t mangle -A $chain -j CLASSIFY --set-class 1:1 && CLASSIFY_TARGET=Yes qt $IPTABLES -t mangle -A $chain -j IPMARK --addr src && IPMARK_TARGET=Yes qt $IPTABLES -t mangle -F $chain qt $IPTABLES -t mangle -X $chain qt $IPTABLES -t mangle -L FORWARD -n && MANGLE_FORWARD=Yes fi qt $IPTABLES -t raw -L -n && RAW_TABLE=Yes if qt mywhich ipset; then qt ipset -X $chain # Just in case something went wrong the last time if qt ipset -N $chain iphash ; then if qt $IPTABLES -A $chain -m set --set $chain src -j ACCEPT; then qt $IPTABLES -D $chain -m set --set $chain src -j ACCEPT IPSET_MATCH=Yes fi qt ipset -X $chain fi fi qt $IPTABLES -A $chain -m pkttype --pkt-type broadcast -j ACCEPT && USEPKTTYPE=Yes qt $IPTABLES -A $chain -m addrtype --src-type BROADCAST -j ACCEPT && ADDRTYPE=Yes qt $IPTABLES -A $chain -p tcp --tcp-flags SYN,RST SYN -m tcpmss --mss 1000:1500 -j ACCEPT && TCPMSS_MATCH=Yes qt $IPTABLES -A $chain -m hashlimit --hashlimit-upto 4 --hashlimit-burst 5 --hashlimit-name $chain --hashlimit-mode dstip -j ACCEPT && HASHLIMIT_MATCH=Yes if [ -z "$HASHLIMIT_MATCH" ]; then qt $IPTABLES -A $chain -m hashlimit --hashlimit 4 --hashlimit-burst 5 --hashlimit-name $chain --hashlimit-mode dstip -j ACCEPT && NEW_HL_MATCH=Yes HASHLIMIT_MATCH=$OLD_HL_MATCH fi qt $IPTABLES -A $chain -j NFQUEUE --queue-num 4 && NFQUEUE_TARGET=Yes qt $IPTABLES -A $chain -m realm --realm 4 && REALM_MATCH=Yes qt $IPTABLES -A $chain -m helper --helper "ftp" && HELPER_MATCH=Yes qt $IPTABLES -A $chain -m connlimit --connlimit-above 8 -j DROP && CONNLIMIT_MATCH=Yes qt $IPTABLES -A $chain -m time --timestart 23:00 -j DROP && TIME_MATCH=Yes qt $IPTABLES -A $chain -g $chain1 && GOTO_TARGET=Yes qt $IPTABLES -A $chain -j LOGMARK && LOGMARK_TARGET=Yes qt $IPTABLES -A $chain -j LOG || LOG_TARGET= qt $IPTABLES -F $chain qt $IPTABLES -X $chain qt $IPTABLES -F $chain1 qt $IPTABLES -X $chain1 CAPVERSION=$SHOREWALL_CAPVERSION KERNELVERSION=$(printf "%d%02d%02d" $(uname -r 2> /dev/null | sed -e 's/-.*//' -e 's/^\([0-9][0-9]*\)\.\([0-9][0-9]*\)\.\([0-9][0-9]*\).*$/\1 \2 \3/g')) } report_capabilities() { report_capability() # $1 = Capability Description , $2 Capability Setting (if any) { local setting setting= [ "x$2" = "xYes" ] && setting="Available" || setting="Not available" echo " " $1: $setting } if [ $VERBOSE -gt 1 ]; then echo "Shorewall has detected the following iptables/netfilter capabilities:" report_capability "NAT" $NAT_ENABLED report_capability "Packet Mangling" $MANGLE_ENABLED report_capability "Multi-port Match" $MULTIPORT [ -n "$MULTIPORT" ] && report_capability "Extended Multi-port Match" $XMULTIPORT report_capability "Connection Tracking Match" $CONNTRACK_MATCH if [ -n "$CONNTRACK_MATCH" ]; then report_capability "Extended Connection Tracking Match Support" $NEW_CONNTRACK_MATCH report_capability "Old Connection Tracking Match Syntax" $OLD_CONNTRACK_MATCH fi report_capability "Packet Type Match" $USEPKTTYPE report_capability "Policy Match" $POLICY_MATCH report_capability "Physdev Match" $PHYSDEV_MATCH report_capability "Physdev-is-bridged Support" $PHYSDEV_BRIDGE report_capability "Packet length Match" $LENGTH_MATCH report_capability "IP range Match" $IPRANGE_MATCH report_capability "Recent Match" $RECENT_MATCH report_capability "Owner Match" $OWNER_MATCH report_capability "Ipset Match" $IPSET_MATCH report_capability "CONNMARK Target" $CONNMARK [ -n "$CONNMARK" ] && report_capability "Extended CONNMARK Target" $XCONNMARK report_capability "Connmark Match" $CONNMARK_MATCH [ -n "$CONNMARK_MATCH" ] && report_capability "Extended Connmark Match" $XCONNMARK_MATCH report_capability "Raw Table" $RAW_TABLE report_capability "IPP2P Match" $IPP2P_MATCH [ -n "$IPP2P_MATCH" ] && report_capability "Old IPP2P Match Syntax" $OLD_IPP2P_MATCH report_capability "CLASSIFY Target" $CLASSIFY_TARGET report_capability "Extended REJECT" $ENHANCED_REJECT report_capability "Repeat match" $KLUDGEFREE report_capability "MARK Target" $MARK [ -n "$MARK" ] && report_capability "Extended MARK Target" $XMARK report_capability "Mangle FORWARD Chain" $MANGLE_FORWARD report_capability "Comments" $COMMENTS report_capability "Address Type Match" $ADDRTYPE report_capability "TCPMSS Match" $TCPMSS_MATCH report_capability "Hashlimit Match" $HASHLIMIT_MATCH report_capability "Old Hashlimit Match" $OLD_HL_MATCH report_capability "NFQUEUE Target" $NFQUEUE_TARGET report_capability "Realm Match" $REALM_MATCH report_capability "Helper Match" $HELPER_MATCH report_capability "Connlimit Match" $CONNLIMIT_MATCH report_capability "Time Match" $TIME_MATCH report_capability "Goto Support" $GOTO_TARGET report_capability "LOGMARK Target" $LOGMARK_TARGET report_capability "IPMARK Target" $IPMARK_TARGET report_capability "LOG Target" $LOG_TARGET report_capability "Persistent SNAT" $PERSISTENT_SNAT fi [ -n "$PKTTYPE" ] || USEPKTTYPE= } report_capabilities1() { report_capability1() # $1 = Capability { eval echo $1=\$$1 } echo "#" echo "# Shorewall $VERSION detected the following iptables/netfilter capabilities - $(date)" echo "#" report_capability1 NAT_ENABLED report_capability1 MANGLE_ENABLED report_capability1 MULTIPORT report_capability1 XMULTIPORT report_capability1 CONNTRACK_MATCH report_capability1 NEW_CONNTRACK_MATCH report_capability1 OLD_CONNTRACK_MATCH report_capability1 USEPKTTYPE report_capability1 POLICY_MATCH report_capability1 PHYSDEV_MATCH report_capability1 PHYSDEV_BRIDGE report_capability1 LENGTH_MATCH report_capability1 IPRANGE_MATCH report_capability1 RECENT_MATCH report_capability1 OWNER_MATCH report_capability1 IPSET_MATCH report_capability1 CONNMARK report_capability1 XCONNMARK report_capability1 CONNMARK_MATCH report_capability1 XCONNMARK_MATCH report_capability1 RAW_TABLE report_capability1 IPP2P_MATCH report_capability1 OLD_IPP2P_MATCH report_capability1 CLASSIFY_TARGET report_capability1 ENHANCED_REJECT report_capability1 KLUDGEFREE report_capability1 MARK report_capability1 XMARK report_capability1 MANGLE_FORWARD report_capability1 COMMENTS report_capability1 ADDRTYPE report_capability1 TCPMSS_MATCH report_capability1 HASHLIMIT_MATCH report_capability1 OLD_HL_MATCH report_capability1 NFQUEUE_TARGET report_capability1 REALM_MATCH report_capability1 HELPER_MATCH report_capability1 CONNLIMIT_MATCH report_capability1 TIME_MATCH report_capability1 GOTO_TARGET report_capability1 LOGMARK_TARGET report_capability1 IPMARK_TARGET report_capability1 LOG_TARGET report_capability1 PERSISTENT_SNAT echo CAPVERSION=$SHOREWALL_CAPVERSION echo KERNELVERSION=$KERNELVERSION } # 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} } # # Determine how to do "echo -e" # find_echo() { local result result=$(echo "a\tb") [ ${#result} -eq 3 ] && { echo echo; return; } result=$(echo -e "a\tb") [ ${#result} -eq 3 ] && { echo "echo -e"; return; } result=$(which echo) [ -n "$result" ] && { echo "$result -e"; return; } echo echo } # Determine which version of mktemp is present (if any) and set MKTEMP accortingly: # # None - No mktemp # BSD - BSD mktemp (Mandrake) # STD - mktemp.org mktemp # find_mktemp() { local mktemp mktemp=`mywhich mktemp 2> /dev/null` if [ -n "$mktemp" ]; then if qt mktemp -V ; then MKTEMP=STD else MKTEMP=BSD fi else MKTEMP=None fi } # # create a temporary file. If a directory name is passed, the file will be created in # that directory. Otherwise, it will be created in a temporary directory. # mktempfile() { [ -z "$MKTEMP" ] && find_mktemp if [ $# -gt 0 ]; then case "$MKTEMP" in BSD) mktemp $1/shorewall.XXXXXX ;; STD) mktemp -p $1 shorewall.XXXXXX ;; None) > $1/shorewall-$$ && echo $1/shorewall-$$ ;; *) error_message "ERROR:Internal error in mktempfile" ;; esac else case "$MKTEMP" in BSD) mktemp /tmp/shorewall.XXXXXX ;; STD) mktemp -t shorewall.XXXXXX ;; None) rm -f /tmp/shorewall-$$ > /tmp/shorewall-$$ && echo /tmp/shorewall-$$ ;; *) error_message "ERROR:Internal error in mktempfile" ;; esac fi }