diff --git a/Shorewall-perl/Shorewall/Compiler.pm b/Shorewall-perl/Shorewall/Compiler.pm index e94c4c41e..e29cfde0a 100644 --- a/Shorewall-perl/Shorewall/Compiler.pm +++ b/Shorewall-perl/Shorewall/Compiler.pm @@ -104,13 +104,6 @@ sub generate_script_1() { ); } - copy "$globals{SHAREDIRPL}lib.base"; - - emitj ( '################################################################################', - '# End of /usr/share/shorewall-perl/lib.base', - '################################################################################' - ); - emit "TEMPFILE=\n"; for my $exit qw/init start tcclear started stop stopped clear/ { diff --git a/Shorewall-perl/diff-4.0-lib.base b/Shorewall-perl/diff-4.0-lib.base new file mode 100644 index 000000000..445129bf2 --- /dev/null +++ b/Shorewall-perl/diff-4.0-lib.base @@ -0,0 +1,552 @@ +--- ../Shorewall-common/lib.base 2007-07-02 15:50:32.000000000 -0700 ++++ prog.header 2007-07-02 16:17:48.000000000 -0700 +@@ -1,48 +1,29 @@ + #!/bin/sh + # +-# Shorewall 4.0 -- /usr/share/shorewall/lib.base ++# Generated by the Shoreline Firewall (Shorewall) Packet Filtering Firewall - V3.4 + # + # This program is under GPL [http://www.gnu.org/copyleft/gpl.htm] + # +-# (c) 1999,2000,2001,2002,2003,2004,2005,2006,2007 - Tom Eastep (teastep@shorewall.net) ++# (c) 2006 - 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., 675 Mass Ave, Cambridge, MA 02139, USA +-# +-# This library contains the code common to all Shorewall components. +-# +-# - It is copied into the compiled script with the -e compiler flag is specified to +-# shorewall-shell. +-# - It is loaded by /sbin/shorewall. +-# - It is loaded by /usr/share/shorewall/firewall. +-# - It is loaded by /usr/share/shorewall-shell/compiler. +-# - It is released as part of Shorewall Lite where it is used by /sbin/shorewall-lite +-# and /usr/share/shorewall-lite/shorecap. +-# - It is released as part of Shorewall Perl where it is copied into the compiled script +-# by the compiler. +-# +- +-SHOREWALL_LIBVERSION=40000 +-SHOREWALL_CAPVERSION=30405 +- +-[ -n "${VARDIR:=/var/lib/shorewall}" ] +-[ -n "${SHAREDIR:=/usr/share/shorewall}" ] +-[ -n "${CONFDIR:=/etc/shorewall}" ] +-SHELLSHAREDIR=/usr/share/shorewall-shell +-PERLSHAREDIR=/usr/share/shorewall-perl +- ++# Options are: ++# ++# -n Don't alter Routing ++# -v and -q Standard Shorewall Verbosity control ++# ++# Commands are: ++# ++# start Starts the firewall ++# refresh Refresh the firewall ++# restart Restarts the firewall ++# reload Reload the firewall ++# clear Removes all firewall rules ++# stop Stops the firewall ++# status Displays firewall status ++# version Displays the version of Shorewall that ++# generated this program ++# + # + # Message to stderr + # +@@ -85,46 +66,6 @@ + } + + # +-# Split a colon-separated list into a space-separated list +-# +-split() { +- local 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=$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 o= +- +- for f in $* ; do +- o="${o:+$o,}$f" +- done +- +- echo $o +-} +- +-# + # Suppress all output for a command + # + qt() +@@ -148,19 +89,6 @@ + } + + # +-# Source a user exit file if it exists +-# +-run_user_exit() # $1 = file name +-{ +- local user_exit=$(find_file $1) +- +- if [ -f $user_exit ]; then +- progress_message "Processing $user_exit ..." +- . $user_exit +- fi +-} +- +-# + # Set a standard chain's policy + # + setpolicy() # $1 = name of chain, $2 = policy +@@ -310,83 +238,6 @@ + } + + # +-# 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=0 +- local 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} +-} +- +-# +-# Load an optional library +-# +-lib_load() # $1 = Name of the Library, $2 = Error Message heading if the library cannot be found +-{ +- local lib=${SHAREDIR}/lib.$1 +- local loaded +- +- eval loaded=\$LIB_${1}_LOADED +- +- if [ -z "$loaded" ]; then +- [ -f $lib ] || lib=${SHELLSHAREDIR}/lib.$1 +- +- if [ -f $lib ]; then +- progress_message "Loading library $lib..." +- . $lib +- eval LIB_${1}_LOADED=Yes +- else +- startup_error "$2 requires the Shorewall library $1 ($lib) which is not installed" +- fi +- fi +-} +- +-# +-# Determine if an optional library is available +-# +-lib_avail() # $1 = Name of the Library +-{ +- [ -f ${SHAREDIR}/lib.$1 ] +-} +- +-# + # Note: The following set of IP address manipulation functions have anomalous + # behavior when the shell only supports 32-bit signed arithmatic and + # the IP address is 128.0.0.0 or 128.0.0.1. +@@ -607,40 +458,6 @@ + fi + } + +- +-# +-# Chain name base for an interface -- replace all periods with underscores in the passed name. +-# The result is echoed (less trailing "+"). +-# +-chain_base() #$1 = interface +-{ +- local c=${1%%+} +- +- while true; do +- case $c in +- @*) +- c=at_${c#@} +- ;; +- *.*) +- c="${c%.*}_${c##*.}" +- ;; +- *-*) +- c="${c%-*}_${c##*-}" +- ;; +- *%*) +- c="${c%\%*}_${c##*%}" +- ;; +- *@*) +- c="${c%@*}_${c##*@}" +- ;; +- *) +- echo ${c:=common} +- return +- ;; +- esac +- done +-} +- + # + # Query NetFilter about the existence of a filter chain + # +@@ -879,93 +696,6 @@ + } + + # +-# Set default config path +-# +-ensure_config_path() { +- local 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= 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 +- +- 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 +@@ -1127,46 +857,6 @@ + + } + +-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 USEPKTTYPE +- report_capability1 POLICY_MATCH +- report_capability1 PHYSDEV_MATCH +- 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 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 +- +- echo CAPVERSION=$SHOREWALL_CAPVERSION +-} +- + # + # Delete IP address + # +@@ -1286,82 +976,6 @@ + cut -b -${1} + } + +-# +-# Add a logging rule. +-# +-do_log_rule_limit() # $1 = log level, $2 = chain, $3 = display Chain $4 = disposition , $5 = rate limit $6=log tag $7=command $... = predicates for the rule +-{ +- local level=$1 +- local chain=$2 +- local displayChain=$3 +- local disposition=$4 +- local rulenum= +- local limit= +- local tag= +- local command= +- local prefix +- local base=$(chain_base $displayChain) +- local pf +- +- limit="${5:-$LOGLIMIT}" # Do this here rather than in the declaration above to appease /bin/ash. +- tag=${6:+$6 } +- command=${7:--A} +- +- shift 7 +- +- if [ -n "$tag" -a -n "$LOGTAGONLY" ]; then +- displayChain=$tag +- tag= +- fi +- +- if [ -n "$LOGRULENUMBERS" ]; then +- # +- # Hack for broken printf on some lightweight shells +- # +- [ $(printf "%d" 1) = "1" ] && pf=printf || pf=$(mywhich printf) +- +- eval rulenum=\$${base}_logrules +- +- rulenum=${rulenum:-1} +- +- prefix="$($pf "$LOGFORMAT" $displayChain $rulenum $disposition)${tag}" +- +- rulenum=$(($rulenum + 1)) +- eval ${base}_logrules=$rulenum +- else +- prefix="$(printf "$LOGFORMAT" $displayChain $disposition)${tag}" +- fi +- +- if [ ${#prefix} -gt 29 ]; then +- prefix=`echo "$prefix" | truncate 29` +- error_message "WARNING: Log Prefix shortened to \"$prefix\"" +- fi +- +- case $level in +- ULOG) +- $IPTABLES $command $chain $@ $limit -j ULOG $LOGPARMS --ulog-prefix "$prefix" +- ;; +- *) +- $IPTABLES $command $chain $@ $limit -j LOG $LOGPARMS --log-level $level --log-prefix "$prefix" +- ;; +- esac +- +- if [ $? -ne 0 ] ; then +- [ -z "$STOPPING" ] && { stop_firewall; exit 2; } +- fi +-} +- +-do_log_rule() # $1 = log level, $2 = chain, $3 = disposition , $... = predicates for the rule +-{ +- local level=$1 +- local chain=$2 +- local disposition=$3 +- +- shift 3 +- +- do_log_rule_limit $level $chain $chain $disposition "$LOGLIMIT" "" -A $@ +-} +- + delete_tc1() + { + clear_one_tc() { +@@ -1496,65 +1110,3 @@ + + 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=`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 +-} diff --git a/Shorewall-perl/install.sh b/Shorewall-perl/install.sh index 8a5fb142d..a85e990c3 100755 --- a/Shorewall-perl/install.sh +++ b/Shorewall-perl/install.sh @@ -182,9 +182,6 @@ for f in Shorewall/*.pm ; do echo "Module ${f%.*} installed as ${PREFIX}/usr/share/shorewall-perl/$f" done -install_file lib.base ${PREFIX}/usr/share/shorewall-perl/lib.base 0644 -echo "Shell library lib.base installed as ${PREFIX}/usr/share/shorewall-perl/lib.base"; - # # Install the program skeleton files # diff --git a/Shorewall-perl/prog.header b/Shorewall-perl/prog.header index ac887702d..ac28248d1 100644 --- a/Shorewall-perl/prog.header +++ b/Shorewall-perl/prog.header @@ -24,3 +24,1089 @@ # version Displays the version of Shorewall that # generated this program # +# +# Message to stderr +# +error_message() # $* = Error Message +{ + echo " $@" >&2 +} + +# +# Conditionally produce message +# +progress_message() # $* = Message +{ + local timestamp= + + if [ $VERBOSE -gt 1 ]; then + [ -n "$TIMESTAMP" ] && timestamp="$(date +%H:%M:%S) " + echo "${timestamp}$@" + fi +} + +progress_message2() # $* = Message +{ + local timestamp= + + if [ $VERBOSE -gt 0 ]; then + [ -n "$TIMESTAMP" ] && timestamp="$(date +%H:%M:%S) " + echo "${timestamp}$@" + fi +} + +progress_message3() # $* = Message +{ + local timestamp= + + if [ $VERBOSE -ge 0 ]; then + [ -n "$TIMESTAMP" ] && timestamp="$(date +%H:%M:%S) " + echo "${timestamp}$@" + fi +} + +# +# 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) +} + +# +# Set a standard chain's policy +# +setpolicy() # $1 = name of chain, $2 = policy +{ + run_iptables -P $1 $2 +} + +# +# Set a standard chain to enable established and related connections +# +setcontinue() # $1 = name of chain +{ + run_iptables -A $1 -m state --state ESTABLISHED,RELATED -j ACCEPT +} + +# +# Flush one of the NAT table chains +# +flushnat() # $1 = name of chain +{ + run_iptables -t nat -F $1 +} + +# +# Flush one of the Mangle table chains +# +flushmangle() # $1 = name of chain +{ + run_iptables -t mangle -F $1 +} + +# +# Flush and delete all user-defined chains in the filter table +# +deleteallchains() { + run_iptables -F + 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=$1 + local modulefile + local suffix + + if ! list_search $modulename $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=$MODULESDIR + local directory + local moduledirectories= + local moduleloader=modprobe + + 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/ipv4/netfilter:/lib/modules/$(uname -r)/kernel/net/netfilter + 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=$MODULESDIR + local directory + local moduledirectories= + local moduleloader=modprobe + local 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/ipv4/netfilter:/lib/modules/$(uname -r)/kernel/net/netfilter + + 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 +} + +# +# Note: The following set of IP address manipulation functions have anomalous +# behavior when the shell only supports 32-bit signed arithmatic and +# the IP address is 128.0.0.0 or 128.0.0.1. +# + +LEFTSHIFT='<<' + +# +# Validate an IP address +# +valid_address() { + local x y + local 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=0 + local 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=$(($addr & 255)) + + for x in 1 2 3 ; do + addr=$(($addr >> 8)) + y=$(($addr & 255)).$y + done + + echo $y +} + +# +# 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 last l x y z 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 [ $first -gt $last ]; then + fatal_error "Invalid IP address range: $1" + fi + + l=$(( $last + 1 )) + + while [ $first -le $last ]; do + vlsm= + x=31 + y=2 + z=1 + + while [ $(( $first % $y )) -eq 0 -a $(( $first + $y )) -le $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 last + + case $1 in + [0-9]*.*.*.*-*.*.*.*) + ;; + *) + echo $1 + return + ;; + esac + + first=$(decodeaddr ${1%-*}) + last=$(decodeaddr ${1#*-}) + + if [ $first -gt $last ]; then + fatal_error "Invalid IP address range: $1" + fi + + while [ $first -le $last ]; do + echo $(encodeaddr $first) + first=$(($first + 1)) + done +} + +# +# Netmask from CIDR +# +ip_netmask() { + local vlsm=${1#*/} + + [ $vlsm -eq 0 ] && echo 0 || echo $(( -1 $LEFTSHIFT $(( 32 - $vlsm )) )) +} + +# +# Network address from CIDR +# +ip_network() { + local decodedaddr=$(decodeaddr ${1%/*}) + local 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=$(( 32 - ${1#*/} )) + + [ $x -eq 32 ] && echo -1 || echo $(( $(( 1 $LEFTSHIFT $x )) - 1 )) +} + +# +# Calculate broadcast address from CIDR +# +broadcastaddress() { + local decodedaddr=$(decodeaddr ${1%/*}) + local netmask=$(ip_netmask $1) + local broadcast=$(ip_broadcast $1) + + echo $(encodeaddr $(( $(($decodedaddr & $netmask)) | $broadcast ))) +} + +# +# Test for network membership +# +in_network() # $1 = IP address, $2 = CIDR network +{ + local netmask=$(ip_netmask $2) + + test $(( $(decodeaddr $1) & $netmask)) -eq $(( $(decodeaddr ${2%/*}) & $netmask )) +} + +# +# Netmask to VLSM +# +ip_vlsm() { + local mask=$(decodeaddr $1) + local vlsm=0 + local 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 value 'dev' in the passed arguments then echo the next value +# + +find_device() { + while [ $# -gt 1 ]; do + [ "x$1" = xdev ] && echo $2 && return + shift + done +} + +# +# Find the value 'via' in the passed arguments then echo the next value +# + +find_gateway() { + while [ $# -gt 1 ]; do + [ "x$1" = xvia ] && echo $2 && return + shift + done +} + +# +# Find the value 'mtu' in the passed arguments then echo the next value +# + +find_mtu() { + while [ $# -gt 1 ]; do + [ "x$1" = xmtu ] && echo $2 && return + shift + done +} + +# +# Find the value 'peer' in the passed arguments then echo the next value up to +# "/" +# + +find_peer() { + while [ $# -gt 1 ]; do + [ "x$1" = xpeer ] && echo ${2%/*} && return + shift + done +} + +# +# Find the interfaces that have a route to the passed address - the default +# route is not used. +# + +find_rt_interface() { + ip route ls | while read addr rest; do + case $addr in + */*) + in_network ${1%/*} $addr && echo $(find_device $rest) + ;; + default) + ;; + *) + if [ "$addr" = "$1" -o "$addr/32" = "$1" ]; then + echo $(find_device $rest) + fi + ;; + esac + done +} + +# +# Try to find the gateway through an interface looking for 'nexthop' + +find_nexthop() # $1 = interface +{ + echo $(find_gateway `ip route ls | grep "[[:space:]]nexthop.* $1"`) +} + +# +# Find the default route's interface +# +find_default_interface() { + ip route ls | while read first rest; do + [ "$first" = default ] && echo $(find_device $rest) && return + done +} + +# +# Echo the name of the interface(s) that will be used to send to the +# passed address +# + +find_interface_by_address() { + local dev="$(find_rt_interface $1)" + local first rest + + [ -z "$dev" ] && dev=$(find_default_interface) + + [ -n "$dev" ] && echo $dev +} + +# +# Find the interface with the passed MAC address +# + +find_interface_by_mac() { + local mac=$1 first second rest dev + + ip link ls | 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 +# +interface_is_up() { + [ -n "$(ip link ls 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" ] || 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 +} + +# +# Determine if interface is usable from a Netfilter prespective +# +interface_is_usable() # $1 = interface +{ + interface_is_up $1 && [ "$(find_first_interface_address_if_any $1)" != 0.0.0.0 ] +} + +# +# Find interface addresses--returns the set of addresses assigned to the passed +# device +# +find_interface_addresses() # $1 = interface +{ + ip -f inet addr show $1 2> /dev/null | grep inet\ | sed 's/\s*inet //;s/\/.*//;s/ peer.*//' +} + +# +# echo the list of networks routed out of a given interface +# +get_routed_networks() # $1 = interface name, $2-n = Fatal error message +{ + local address + local rest + + ip route show dev $1 2> /dev/null | + while read address rest; do + case "$address" in + default) + if [ $# -gt 1 ]; then + shift + fatal_error "$@" + else + echo "WARNING: default route ignored on interface $1" >&2 + fi + ;; + multicast|broadcast|prohibit|nat|throw|nexthop) + ;; + *) + [ "$address" = "${address%/*}" ] && address="${address}/32" + echo $address + ;; + esac + done +} + +get_interface_bcasts() # $1 = interface +{ + local addresses= + + 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 +} + +# +# Set the Shorewall state +# +set_state () # $1 = state +{ + echo "$1 ($(date))" > ${VARDIR}/state +} + +# +# Determine which optional facilities are supported by iptables/netfilter +# +determine_capabilities() { + qt $IPTABLES -t nat -L -n && NAT_ENABLED=Yes || NAT_ENABLED= + qt $IPTABLES -t mangle -L -n && MANGLE_ENABLED=Yes || MANGLE_ENABLED= + + CONNTRACK_MATCH= + MULTIPORT= + XMULTIPORT= + POLICY_MATCH= + PHYSDEV_MATCH= + IPRANGE_MATCH= + RECENT_MATCH= + OWNER_MATCH= + IPSET_MATCH= + CONNMARK= + XCONNMARK= + CONNMARK_MATCH= + XCONNMARK_MATCH= + RAW_TABLE= + IPP2P_MATCH= + LENGTH_MATCH= + CLASSIFY_TARGET= + ENHANCED_REJECT= + USEPKTTYPE= + KLUDGEFREE= + MARK= + XMARK= + MANGLE_FORWARD= + COMMENTS= + ADDRTYPE= + TCPMSS_MATCH= + + qt $IPTABLES -N fooX1234 + qt $IPTABLES -A fooX1234 -m conntrack --ctorigdst 192.168.1.1 -j ACCEPT && CONNTRACK_MATCH=Yes + qt $IPTABLES -A fooX1234 -p tcp -m multiport --dports 21,22 -j ACCEPT && MULTIPORT=Yes + qt $IPTABLES -A fooX1234 -p tcp -m multiport --dports 21:22 -j ACCEPT && XMULTIPORT=Yes + qt $IPTABLES -A fooX1234 -m policy --pol ipsec --mode tunnel --dir in -j ACCEPT && POLICY_MATCH=Yes + + if qt $IPTABLES -A fooX1234 -m physdev --physdev-out eth0 -j ACCEPT; then + PHYSDEV_MATCH=Yes + fi + + if qt $IPTABLES -A fooX1234 -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 fooX1234 -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 fooX1234 -m recent --update -j ACCEPT && RECENT_MATCH=Yes + qt $IPTABLES -A fooX1234 -m owner --uid-owner 0 -j ACCEPT && OWNER_MATCH=Yes + + if qt $IPTABLES -A fooX1234 -m connmark --mark 2 -j ACCEPT; then + CONNMARK_MATCH=Yes + qt $IPTABLES -A fooX1234 -m connmark --mark 2/0xFF -j ACCEPT && XCONNMARK_MATCH=Yes + fi + + qt $IPTABLES -A fooX1234 -p tcp -m ipp2p --ipp2p -j ACCEPT && IPP2P_MATCH=Yes + qt $IPTABLES -A fooX1234 -m length --length 10:20 -j ACCEPT && LENGTH_MATCH=Yes + qt $IPTABLES -A fooX1234 -j REJECT --reject-with icmp-host-prohibited && ENHANCED_REJECT=Yes + + qt $IPTABLES -A fooX1234 -j ACCEPT -m comment --comment "This is a comment" && COMMENTS=Yes + + if [ -n "$MANGLE_ENABLED" ]; then + qt $IPTABLES -t mangle -N fooX1234 + + if qt $IPTABLES -t mangle -A fooX1234 -j MARK --set-mark 1; then + MARK=Yes + qt $IPTABLES -t mangle -A fooX1234 -j MARK --and-mark 0xFF && XMARK=Yes + fi + + if qt $IPTABLES -t mangle -A fooX1234 -j CONNMARK --save-mark; then + CONNMARK=Yes + qt $IPTABLES -t mangle -A fooX1234 -j CONNMARK --save-mark --mask 0xFF && XCONNMARK=Yes + fi + + qt $IPTABLES -t mangle -A fooX1234 -j CLASSIFY --set-class 1:1 && CLASSIFY_TARGET=Yes + qt $IPTABLES -t mangle -F fooX1234 + qt $IPTABLES -t mangle -X fooX1234 + 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 fooX1234 # Just in case something went wrong the last time + + if qt ipset -N fooX1234 iphash ; then + if qt $IPTABLES -A fooX1234 -m set --set fooX1234 src -j ACCEPT; then + qt $IPTABLES -D fooX1234 -m set --set fooX1234 src -j ACCEPT + IPSET_MATCH=Yes + fi + qt ipset -X fooX1234 + fi + fi + + qt $IPTABLES -A fooX1234 -m pkttype --pkt-type broadcast -j ACCEPT && USEPKTTYPE=Yes + qt $IPTABLES -A fooX1234 -m addrtype --src-type BROADCAST -j ACCEPT && ADDRTYPE=Yes + qt $IPTABLES -A fooX1234 -p tcp --tcp-flags SYN,RST SYN -m tcpmss --mss 1000:1500 -j ACCEPT && TCPMSS_MATCH=Yes + + qt $IPTABLES -F fooX1234 + qt $IPTABLES -X fooX1234 + + CAPVERSION=$SHOREWALL_CAPVERSION +} + +report_capabilities() { + report_capability() # $1 = Capability Description , $2 Capability Setting (if any) + { + local 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 + report_capability "Packet Type Match" $USEPKTTYPE + report_capability "Policy Match" $POLICY_MATCH + report_capability "Physdev Match" $PHYSDEV_MATCH + 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 + 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 + fi + + [ -n "$PKTTYPE" ] || USEPKTTYPE= + +} + +# +# Delete IP address +# +del_ip_addr() # $1 = address, $2 = interface +{ + [ $(find_first_interface_address_if_any $2) = $1 ] || qt ip addr del $1 dev $2 +} + +# Add IP Aliases +# +add_ip_aliases() # $* = List of addresses +{ + local addresses external interface inet cidr rest val arping=$(mywhich arping) + + address_details() + { + # + # Folks feel uneasy if they don't see all of the same + # decoration on these IP addresses that they see when their + # distro's net config tool adds them. In an attempt to reduce + # the anxiety level, we have the following code which sets + # the VLSM and BRD from an existing address in the same networks + # + # Get all of the lines that contain inet addresses with broadcast + # + ip -f inet addr show $interface 2> /dev/null | grep 'inet.*brd' | while read inet cidr rest ; do + case $cidr in + */*) + if in_network $external $cidr; then + echo "/${cidr#*/} brd $(broadcastaddress $cidr)" + break + fi + ;; + esac + done + } + + do_one() + { + val=$(address_details) + + ip addr add ${external}${val} dev $interface $label + [ -n "$arping" ] && qt $arping -U -c 2 -I $interface $external + echo "$external $interface" >> $VARDIR/nat + [ -n "$label" ] && label="with $label" + progress_message " IP Address $external added to interface $interface $label" + } + + progress_message "Adding IP Addresses..." + + while [ $# -gt 0 ]; do + external=$1 + interface=$2 + label= + + if [ "$interface" != "${interface%:*}" ]; then + label="${interface#*:}" + interface="${interface%:*}" + label="label $interface:$label" + fi + + shift 2 + + list_search $external $(find_interface_addresses $interface) || do_one + done +} + +detect_gateway() # $1 = interface +{ + local interface=$1 + # + # First assume that this is some sort of point-to-point interface + # + gateway=$( find_peer $(ip addr ls $interface ) ) + # + # Maybe there's a default route through this gateway already + # + [ -n "$gateway" ] || gateway=$(find_gateway $(ip route ls dev $interface)) + # + # Last hope -- is there a load-balancing route through the interface? + # + [ -n "$gateway" ] || gateway=$(find_nexthop $interface) + # + # Be sure we found one + # + [ -n "$gateway" ] && echo $gateway +} + +# +# Disable IPV6 +# +disable_ipv6() { + local foo="$(ip -f inet6 addr ls 2> /dev/null)" + + if [ -n "$foo" ]; then + if qt mywhich ip6tables; then + ip6tables -P FORWARD DROP + ip6tables -P INPUT DROP + ip6tables -P OUTPUT DROP + ip6tables -F + ip6tables -X + ip6tables -A OUTPUT -o lo -j ACCEPT + ip6tables -A INPUT -i lo -j ACCEPT + else + error_message "WARNING: DISABLE_IPV6=Yes in shorewall.conf but this system does not appear to have ip6tables" + fi + 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} +} + +delete_tc1() +{ + clear_one_tc() { + tc qdisc del dev $1 root 2> /dev/null + tc qdisc del dev $1 ingress 2> /dev/null + + } + + run_user_exit tcclear + + run_ip link list | \ + while read inx interface details; do + case $inx in + [0-9]*) + clear_one_tc ${interface%:} + ;; + *) + ;; + esac + done +} + +# +# Detect a device's MTU -- echos the passed device's MTU +# +get_device_mtu() # $1 = device +{ + local output="$(ip link ls dev $1 2> /dev/null)" # quotes required for /bin/ash + + if [ -n "$output" ]; then + echo $(find_mtu $output) + else + echo 1500 + fi +} + +# +# Version of the above that doesn't generate any output for MTU 1500. +# Generates 'mtu ' otherwise, where is the device's MTU + 100 +# +get_device_mtu1() # $1 = device +{ + local output="$(ip link ls dev $1 2> /dev/null)" # quotes required for /bin/ash + local mtu + + if [ -n "$output" ]; then + mtu=$(find_mtu $output) + if [ -n "$mtu" ]; then + [ $mtu = 1500 ] || echo mtu $(($mtu + 100)) + fi + fi + +} + +# +# Undo changes to routing +# +undo_routing() { + + if [ -z "$NOROUTES" ]; then + # + # Restore rt_tables database + # + if [ -f ${VARDIR}/rt_tables ]; then + cp -f ${VARDIR}/rt_tables /etc/iproute2/ && progress_message "/etc/iproute2/rt_tables database restored" + rm -f ${VARDIR}/rt_tables + fi + # + # Restore the rest of the routing table + # + if [ -f ${VARDIR}/undo_routing ]; then + . ${VARDIR}/undo_routing + progress_message "Shorewall-generated routing tables and routing rules removed" + rm -f ${VARDIR}/undo_routing + fi + fi + +} + +restore_default_route() { + if [ -z "$NOROUTES" -a -f ${VARDIR}/default_route ]; then + local default_route= route + + while read route ; do + case $route in + default*) + if [ -n "$default_route" ]; then + case "$default_route" in + *metric*) + # + # Don't restore a route with a metric -- we only replace the one with metric == 0 + # + qt ip route delete default metric 0 && \ + progress_message "Default Route with metric 0 deleted" + ;; + *) + qt ip route replace $default_route && \ + progress_message "Default Route (${default_route# }) restored" + ;; + esac + + break + fi + + default_route="$default_route $route" + ;; + *) + default_route="$default_route $route" + ;; + esac + done < ${VARDIR}/default_route + + rm -f ${VARDIR}/default_route + fi +} + +# +# 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 +} diff --git a/Shorewall-perl/shorewall-perl.spec b/Shorewall-perl/shorewall-perl.spec index 901285450..5c97f7e00 100644 --- a/Shorewall-perl/shorewall-perl.spec +++ b/Shorewall-perl/shorewall-perl.spec @@ -63,7 +63,6 @@ fi %attr(755,root,root) /usr/share/shorewall-perl/buildports.pl %attr(755,root,root) /usr/share/shorewall-perl/compiler.pl -%attr(0644,root,root) /usr/share/shorewall-perl/lib.base %attr(0644,root,root) /usr/share/shorewall-perl/prog.header %attr(0644,root,root) /usr/share/shorewall-perl/prog.functions %attr(0644,root,root) /usr/share/shorewall-perl/prog.footer diff --git a/docs/Shorewall-4.xml b/docs/Shorewall-4.xml index 0b9d6b142..72119550e 100644 --- a/docs/Shorewall-4.xml +++ b/docs/Shorewall-4.xml @@ -243,14 +243,13 @@ The -C option overrides the setting in shorewall.conf. - Example:shorewall restart -C perlRegardless - of the setting of SHOREWALL_COMPILER, there is one change in Shorewall - operation that is triggered simply by installing shorewall-perl. Your - params file will be processed during compilation with the shell's '-a' - option which causes any variables that you set or create in that file to - be automatically exported. Since the params file is processed before - shorewall.conf, using -a insures that the settings of your params - variables are available to the new compiler should its use be specified in - shorewall.conf. + Example:shorewall restart -C perl + + When the Shorewall-perl compiler has been selected, the + params file is processed using the + option which causes all variables set within the file + to be exported automatically by the shell. The Shorewall-perl compiler + uses the current environmental variables to perform variable expansion + within the other Shorewall configuration files. \ No newline at end of file diff --git a/docs/Shorewall-perl.xml b/docs/Shorewall-perl.xml index 1512cecb8..12f6f6fd1 100644 --- a/docs/Shorewall-perl.xml +++ b/docs/Shorewall-perl.xml @@ -595,15 +595,14 @@ eth0 eth1:!192.168.4.9 ... The -C option overrides the setting in shorewall.conf. - Example:shorewall restart -C perlRegardless - of the setting of SHOREWALL_COMPILER, there is one change in Shorewall - operation that is triggered simply by installing shorewall-perl. Your - params file will be processed during compilation with the shell's '-a' - option which causes any variables that you set or create in that file to - be automatically exported. Since the params file is processed before - shorewall.conf, using -a insures that the settings of your params - variables are available to the new compiler should its use be specified - in shorewall.conf. + Example:shorewall restart -C perl + + When the Shorewall-perl compiler has been selected, the + params file is processed using the + option which causes all variables set within the + file to be exported automatically by the shell. The Shorewall-perl + compiler uses the current environmental variables to perform variable + expansion within the other Shorewall configuration files. \ No newline at end of file diff --git a/tools/build/buildshorewall b/tools/build/buildshorewall index c4e03d3a2..64b81509f 100755 --- a/tools/build/buildshorewall +++ b/tools/build/buildshorewall @@ -346,7 +346,6 @@ if [ -n "${BUILDTARBALL}${BUILDRPM}" ]; then do_or_die "cp $SHOREWALLDIR/modules $SHOREWALLLITEDIR >> $LOGFILE 2>&1" if [ -f $SHOREWALLDIR/lib.base ]; then do_or_die "cp $SHOREWALLDIR/lib.base $SHOREWALLLITEDIR >> $LOGFILE 2>&1" - do_or_die "cp $SHOREWALLDIR/lib.base $PERLDIR >> $LOGFILE 2>&1" if [ -f $SHOREWALLDIR/lib.cli ]; then do_or_die "cp $SHOREWALLDIR/lib.cli $SHOREWALLLITEDIR >> $LOGFILE 2>&1" fi