# # Shorewall 5.1 -- /usr/share/shorewall/lib.core # # (c) 1999-2017 - Tom Eastep (teastep@shorewall.net) # # Complete documentation is available at http://shorewall.net # # This program is part of Shorewall. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by the # Free Software Foundation, either version 2 of the license or, at your # option, any later version. # # 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, see . # # This library contains the code common to all Shorewall components except the # generated scripts. # SHOREWALL_LIBVERSION=50108 # # Fatal Error # fatal_error() # $@ = Message { echo " ERROR: $@" >&2 exit 2 } setup_product_environment() { # $1 = if non-empty, source shorewallrc again now that we have the correct product g_basedir=${SHAREDIR}/shorewall g_sharedir="$SHAREDIR"/$PRODUCT g_confdir="$CONFDIR"/$PRODUCT case $PRODUCT in shorewall) g_product="Shorewall" g_family=4 g_tool=iptables g_lite= ;; shorewall6) g_product="Shorewall6" g_family=6 g_tool=ip6tables g_lite= ;; shorewall-lite) g_product="Shorewall Lite" g_family=4 g_tool=iptables g_lite=Yes ;; shorewall6-lite) g_product="Shorewall6 Lite" g_family=6 g_tool=ip6tables g_lite=Yes ;; *) fatal_error "Unknown PRODUCT ($PRODUCT)" ;; esac [ -f ${SHAREDIR}/${PRODUCT}/version ] || fatal_error "$g_product does not appear to be installed on this system" # # We need to do this again, now that we have the correct product # [ -n "$1" ] && . ${g_basedir}/shorewallrc if [ -z "${VARLIB}" ]; then VARLIB=${VARDIR} VARDIR=${VARLIB}/${PRODUCT} elif [ -z "${VARDIR}" ]; then VARDIR="${VARLIB}/${PRODUCT}" fi } set_default_product() { case $(basename $0) in shorewall6) PRODUCT=shorewall6 ;; shorewall4) PRODUCT=shorewall ;; shorewall-lite) PRODUCT=shorewall-lite ;; shorewall6-lite) PRODUCT=shorewall6-lite ;; *) if [ -f ${g_basedir}/version ]; then PRODUCT=shorewall elif [ -f ${SHAREDIR}/shorewall-lite/version ]; then PRODUCT=shorewall-lite elif [ -f ${SHAREDIR}/shorewall6-lite/version ]; then PRODUCT=shorewall6-lite else fatal_error "No Shorewall firewall product is installed" fi ;; esac } # Not configured Error # not_configured_error() # $@ = Message { echo " ERROR: $@" >&2 exit 6 } # # Conditionally produce message # progress_message() # $* = Message { local timestamp timestamp= if [ $VERBOSITY -gt 1 ]; then [ -n "$g_timestamp" ] && timestamp="$(date +%H:%M:%S) " echo "${timestamp}$@" fi } progress_message2() # $* = Message { local timestamp timestamp= if [ $VERBOSITY -gt 0 ]; then [ -n "$g_timestamp" ] && timestamp="$(date +%H:%M:%S) " echo "${timestamp}$@" fi } progress_message3() # $* = Message { local timestamp timestamp= if [ $VERBOSITY -ge 0 ]; then [ -n "$g_timestamp" ] && timestamp="$(date +%H:%M:%S) " echo "${timestamp}$@" fi } # # Undo the effect of 'separate_list()' # combine_list() { local f local o o= for f in $* ; do o="${o:+$o,}$f" done echo $o } # # Validate an IP address # valid_address() { local x local y local ifs ifs=$IFS IFS=. for x in $1; do case $x in [0-9]|[0-9][0-9]|[1-2][0-9][0-9]) [ $x -lt 256 ] || { IFS=$ifs; return 2; } ;; *) IFS=$ifs return 2 ;; esac done IFS=$ifs return 0 } # # Miserable Hack to work around broken BusyBox ash in OpenWRT # addr_comp() { test $(bc < $2 EOF ) -eq 1 } # # Enumerate the members of an IP range -- When using a shell supporting only # 32-bit signed arithmetic, the range cannot span 128.0.0.0. # # Comes in two flavors: # # ip_range() - produces a mimimal list of network/host addresses that spans # the range. # # ip_range_explicit() - explicitly enumerates the range. # ip_range() { local first local last local l local x local y local z local vlsm case $1 in !*) # # Let iptables complain if it's a range # echo $1 return ;; [0-9]*.*.*.*-*.*.*.*) ;; *) echo $1 return ;; esac first=$(decodeaddr ${1%-*}) last=$(decodeaddr ${1#*-}) if addr_comp $first $last; then fatal_error "Invalid IP address range: $1" fi l=$(( $last + 1 )) while addr_comp $l $first; do vlsm= x=31 y=2 z=1 while [ $(( $first % $y )) -eq 0 ] && ! addr_comp $(( $first + $y )) $l; do vlsm=/$x x=$(( $x - 1 )) z=$y y=$(( $y * 2 )) done echo $(encodeaddr $first)$vlsm first=$(($first + $z)) done } ip_range_explicit() { local first local last case $1 in [0-9]*.*.*.*-*.*.*.*) ;; *) echo $1 return ;; esac first=$(decodeaddr ${1%-*}) last=$(decodeaddr ${1#*-}) if addr_comp $first $last; then fatal_error "Invalid IP address range: $1" fi while ! addr_comp $first $last; do echo $(encodeaddr $first) first=$(($first + 1)) done } [ -z "$LEFTSHIFT" ] && . ${g_basedir}/lib.common # # Netmask to VLSM # ip_vlsm() { local mask mask=$(decodeaddr $1) local vlsm vlsm=0 local x x=$(( 128 << 24 )) # 0x80000000 while [ $(( $x & $mask )) -ne 0 ]; do [ $mask -eq $x ] && mask=0 || mask=$(( $mask $LEFTSHIFT 1 )) # Not all shells shift 0x80000000 left properly. vlsm=$(($vlsm + 1)) done if [ $(( $mask & 2147483647 )) -ne 0 ]; then # 2147483647 = 0x7fffffff echo "Invalid net mask: $1" >&2 else echo $vlsm fi } # # Set default config path # ensure_config_path() { local F F=${g_sharedir}/configpath if [ -z "$CONFIG_PATH" ]; then [ -f $F ] || { echo " ERROR: $F does not exist"; exit 2; } . $F fi if [ -n "$g_shorewalldir" ]; then [ "${CONFIG_PATH%%:*}" = "$g_shorewalldir" ] || CONFIG_PATH=$g_shorewalldir:$CONFIG_PATH fi } # # Get fully-qualified name of file # resolve_file() # $1 = file name { local pwd pwd=$PWD case $1 in /*) echo $1 ;; .) echo $pwd ;; ./*) echo ${pwd}${1#.} ;; ..) cd .. echo $PWD cd $pwd ;; ../*) cd .. resolve_file ${1#../} cd $pwd ;; *) echo $pwd/$1 ;; esac } # Determine which version of mktemp is present (if any) and set MKTEMP accortingly: # # None - No mktemp # BSD - BSD mktemp (Mandrake) # STD - mktemp.org mktemp # find_mktemp() { local mktemp mktemp=`mywhich mktemp 2> /dev/null` if [ -n "$mktemp" ]; then if qt mktemp -V ; then MKTEMP=STD else MKTEMP=BSD fi else MKTEMP=None fi } # # create a temporary file. If a directory name is passed, the file will be created in # that directory. Otherwise, it will be created in a temporary directory. # mktempfile() { [ -z "$MKTEMP" ] && find_mktemp if [ $# -gt 0 ]; then case "$MKTEMP" in BSD) mktemp $1/shorewall.XXXXXX ;; STD) mktemp -p $1 shorewall.XXXXXX ;; None) > $1/shorewall-$$ && echo $1/shorewall-$$ ;; *) error_message "ERROR:Internal error in mktempfile" ;; esac else case "$MKTEMP" in BSD) mktemp ${TMPDIR:-/tmp}/shorewall.XXXXXX ;; STD) mktemp -t shorewall.XXXXXX ;; None) rm -f ${TMPDIR:-/tmp}/shorewall-$$ > ${TMPDIR:-}/shorewall-$$ && echo ${TMPDIR:-/tmp}/shorewall-$$ ;; *) error_message "ERROR:Internal error in mktempfile" ;; esac fi }