From 50330f71f6c3d1f32764a727e61f9c1eb8300c4e Mon Sep 17 00:00:00 2001 From: Tom Eastep Date: Thu, 4 Mar 2010 12:38:02 -0800 Subject: [PATCH] Move many routines into lib.common. Signed-off-by: Tom Eastep --- Shorewall/Perl/prog.header | 447 +-------------------- Shorewall/lib.base | 774 +------------------------------------ Shorewall/lib.cli | 335 ++++++++++++++++ Shorewall/lib.common | 460 +++++++++++++++++++++- 4 files changed, 797 insertions(+), 1219 deletions(-) diff --git a/Shorewall/Perl/prog.header b/Shorewall/Perl/prog.header index e2c701c47..9d9aaad85 100644 --- a/Shorewall/Perl/prog.header +++ b/Shorewall/Perl/prog.header @@ -1,3 +1,5 @@ +#!/bin/sh +# # This program is under GPL [http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt] # # (c) 1999-2009 - Tom Eastep (teastep@shorewall.net) @@ -22,14 +24,6 @@ ################################################################################ # Functions imported from /usr/share/shorewall/prog.header ################################################################################ -# -# Message to stderr -# -error_message() # $* = Error Message -{ - echo " $@" >&2 -} - # # Conditionally produce message # @@ -81,42 +75,6 @@ progress_message3() # $* = Message 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 -} - -# -# Suppress all output for a command -# -qt() -{ - "$@" >/dev/null 2>&1 -} - qt1() { local status @@ -128,35 +86,6 @@ qt1() done } -# -# Determine if Shorewall is "running" -# -shorewall_is_started() { - qt1 $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 -} - # # Set a standard chain's policy # @@ -197,243 +126,6 @@ deleteallchains() { run_iptables -X } -# -# 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 $DONT_LOAD $MODULES; 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 - - [ -n "$LOAD_HELPERS_ONLY" ] && modules=$(find_file helpers) || 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 -} - -# -# 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='<<' - -# -# 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 -} - -# -# 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) - # - # Use string comparison to work around a broken BusyBox ash in OpenWRT - # - test $(( $(decodeaddr $1) & $netmask)) = $(( $(decodeaddr ${2%/*}) & $netmask )) -} - -# -# Query NetFilter about the existence of a filter chain -# -chain_exists() # $1 = chain name -{ - qt1 $IPTABLES -L $1 -n -} - # # Find the value 'dev' in the passed arguments then echo the next value # @@ -534,32 +226,6 @@ find_interface_by_address() { [ -n "$dev" ] && echo $dev } -# -# 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 -} - # # Determine if Interface is up # @@ -567,40 +233,6 @@ interface_is_up() { [ -n "$($IP link list dev $1 2> /dev/null | grep -e '[<,]UP[,>]')" ] } -# -# 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" ] || startup_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 -} - # # Determine if interface is usable from a Netfilter prespective # @@ -659,71 +291,6 @@ get_interface_bcasts() # $1 = interface $IP -f inet addr show dev $1 2> /dev/null | grep 'inet.*brd' | sed 's/inet.*brd //; s/scope.*//;' | sort -u } -# -# 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 -{ - echo "$1 ($(date))" > ${VARDIR}/state -} - -# -# 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 $@)) -} - # # Delete IP address # @@ -876,16 +443,6 @@ disable_ipv6() { fi } -# 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} -} - # # Clear the current traffic shaping configuration # diff --git a/Shorewall/lib.base b/Shorewall/lib.base index f044341fc..39a91d590 100644 --- a/Shorewall/lib.base +++ b/Shorewall/lib.base @@ -35,14 +35,6 @@ SHOREWALL_CAPVERSION=40408 [ -n "${SHAREDIR:=/usr/share/shorewall}" ] [ -n "${CONFDIR:=/etc/shorewall}" ] -# -# Message to stderr -# -error_message() # $* = Error Message -{ - echo " $@" >&2 -} - # # Conditionally produce message # @@ -79,34 +71,6 @@ progress_message3() # $* = Message 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()' # @@ -123,167 +87,6 @@ combine_list() 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 - - [ -n "$LOAD_HELPERS_ONLY" ] && modules=$(find_file helpers) || 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 @@ -332,13 +135,7 @@ 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='<<' +[ -z "$LEFTSHIFT" ] && . ${SHAREDIR}/lib.common # # Validate an IP address @@ -368,44 +165,6 @@ valid_address() { 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 # @@ -506,66 +265,6 @@ ip_range_explicit() { 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 # @@ -589,90 +288,6 @@ ip_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 # @@ -689,32 +304,6 @@ ensure_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 # @@ -749,21 +338,6 @@ resolve_file() # $1 = file name 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 # @@ -772,355 +346,11 @@ 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 - - [ "$TC" = tc -o -z "$TC" ] && TC=$(which tc) - - [ -n "$TC" -a -x "$TC" ] || TC= - - 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= - EXMARK= - TPROXY_TARGET= - 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= - FLOW_FILTER= - - 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 - qt $IPTABLES -t mangle -A $chain -j MARK --set-mark 1/0xFF && EXMARK=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 -A $chain -p tcp -j TPROXY --on-port 0 --tproxy-mark 1 && TPROXY_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 && OLD_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 - - [ -n "$TC" ] && $TC filter add flow help 2>&1 | grep -q ^Usage && FLOW_FILTER=Yes - - 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 [ $VERBOSITY -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 - [ -n "$OLD_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 "$OLD_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 - [ -n "$XMARK" ] && report_capability "Extended MARK Target 2" $EXMARK - 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 - [ -n "$OLD_HL_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 - report_capability "TPROXY Target" $TPROXY_TARGET - report_capability "FLOW Classifier" $FLOW_FILTER - fi - - [ -n "$PKTTYPE" ] || USEPKTTYPE= - -} - -report_capabilities1() { - report_capability1() # $1 = Capability - { - eval echo $1=\$$1 - } - - echo "#" - echo "# Shorewall $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 EXMARK - 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 - report_capability1 TPROXY_TARGET - report_capability1 FLOW_FILTER - - 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 @@ -1198,3 +428,5 @@ mktempfile() { esac fi } + +. ${SHAREDIR}/lib.common diff --git a/Shorewall/lib.cli b/Shorewall/lib.cli index d9e44559f..5d24e6789 100644 --- a/Shorewall/lib.cli +++ b/Shorewall/lib.cli @@ -1427,3 +1427,338 @@ logwatch_command() { usage 1 fi } + +# +# 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 + + [ "$TC" = tc -o -z "$TC" ] && TC=$(which tc) + + [ -n "$TC" -a -x "$TC" ] || TC= + + 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= + EXMARK= + TPROXY_TARGET= + 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= + FLOW_FILTER= + + 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 + qt $IPTABLES -t mangle -A $chain -j MARK --set-mark 1/0xFF && EXMARK=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 -A $chain -p tcp -j TPROXY --on-port 0 --tproxy-mark 1 && TPROXY_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 && OLD_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 + + [ -n "$TC" ] && $TC filter add flow help 2>&1 | grep -q ^Usage && FLOW_FILTER=Yes + + 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 [ $VERBOSITY -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 + [ -n "$OLD_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 "$OLD_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 + [ -n "$XMARK" ] && report_capability "Extended MARK Target 2" $EXMARK + 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 + [ -n "$OLD_HL_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 + report_capability "TPROXY Target" $TPROXY_TARGET + report_capability "FLOW Classifier" $FLOW_FILTER + fi + + [ -n "$PKTTYPE" ] || USEPKTTYPE= + +} + +report_capabilities1() { + report_capability1() # $1 = Capability + { + eval echo $1=\$$1 + } + + echo "#" + echo "# Shorewall $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 EXMARK + 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 + report_capability1 TPROXY_TARGET + report_capability1 FLOW_FILTER + + echo CAPVERSION=$SHOREWALL_CAPVERSION + echo KERNELVERSION=$KERNELVERSION +} diff --git a/Shorewall/lib.common b/Shorewall/lib.common index 2a7e1312d..711362d0c 100644 --- a/Shorewall/lib.common +++ b/Shorewall/lib.common @@ -21,9 +21,9 @@ # 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 will gradually replace lib.base. It's purpose is to hold those functions -# used by both the CLI and by the generated firewall scripts. To avoid versioning issues, -# it is copied into generated scripts rather than loaded at run-time. +# The purpose of is library is to hold those functions used by both the CLI and by the +# generated firewall scripts. To avoid versioning issues, it is copied into generated +# scripts rather than loaded at run-time. # # @@ -108,6 +108,460 @@ run_it() { $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 +} + +# +# 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 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 $DONT_LOAD $MODULES; 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 + + [ -n "$LOAD_HELPERS_ONLY" ] && modules=$(find_file helpers) || 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 +} + +# +# 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='<<' + +# +# 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 +} + +# +# 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) + # + # Use string comparison to work around a broken BusyBox ash in OpenWRT + # + test $(( $(decodeaddr $1) & $netmask)) = $(( $(decodeaddr ${2%/*}) & $netmask )) +} + +# +# 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" ] || startup_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 +} + +# +# Query NetFilter about the existence of a filter chain +# +chain_exists() # $1 = chain name +{ + qt1 $IPTABLES -L $1 -n +} + +# +# 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 +{ + echo "$1 ($(date))" > ${VARDIR}/state +} + +# +# 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} +} + ################################################################################# # End of lib.common #################################################################################