# # Shorewall 4.5 -- /usr/share/shorewall/lib.base # # This program is under GPL [http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt] # # (c) 1999-2012 - Tom Eastep (teastep@shorewall.net) # # Complete documentation is available at http://shorewall.net # # This program is free software; you can redistribute it and/or modify # it under the terms of Version 2 of the GNU General Public License # as published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # # This library contains the code common to all Shorewall components. # # - It is loaded by /sbin/shorewall. # - It is released as part of Shorewall[6] Lite where it is used by /sbin/shorewall[6]-lite # and /usr/share/shorewall[6]-lite/shorecap. # SHOREWALL_LIBVERSION=40502 SHOREWALL_CAPVERSION=40507 [ -n "${g_program:=shorewall}" ] if [ -z "$g_readrc" ]; then # # This is modified by the installer when ${SHAREDIR} != /usr/share # . /usr/share/shorewall/shorewallrc g_libexec="$LIBEXECDIR" g_sharedir="$SHAREDIR"/$g_program g_sbindir="$SBINDIR" g_perllib="$PERLLIBDIR" g_confdir="$CONFDIR"/$g_program g_readrc=1 fi g_basedir=${SHAREDIR}/shorewall case $g_program in shorewall) g_product="Shorewall" g_family=4 g_tool= g_lite= ;; shorewall6) g_product="Shorewall6" g_family=6 g_tool= 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 ;; esac if [ -z "${VARLIB}" ]; then VARLIB=${VARDIR} VARDIR=${VARLIB}/$g_program elif [ -z "${VARDIR}" ]; then VARDIR="${VARLIB}/${PRODUCT}" fi # # 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 <<EOF $1 > $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 how to do "echo -e" # find_echo() { local result result=$(echo "a\tb") [ ${#result} -eq 3 ] && { echo echo; return; } result=$(echo -e "a\tb") [ ${#result} -eq 3 ] && { echo "echo -e"; return; } result=$(which echo) [ -n "$result" ] && { echo "$result -e"; return; } echo echo } # Determine which version of mktemp is present (if any) and set MKTEMP accortingly: # # None - No mktemp # BSD - BSD mktemp (Mandrake) # STD - mktemp.org mktemp # find_mktemp() { local mktemp mktemp=`mywhich mktemp 2> /dev/null` if [ -n "$mktemp" ]; then if qt mktemp -V ; then MKTEMP=STD else MKTEMP=BSD fi else MKTEMP=None fi } # # create a temporary file. If a directory name is passed, the file will be created in # that directory. Otherwise, it will be created in a temporary directory. # mktempfile() { [ -z "$MKTEMP" ] && find_mktemp if [ $# -gt 0 ]; then case "$MKTEMP" in BSD) mktemp $1/shorewall.XXXXXX ;; STD) mktemp -p $1 shorewall.XXXXXX ;; None) > $1/shorewall-$$ && echo $1/shorewall-$$ ;; *) error_message "ERROR:Internal error in mktempfile" ;; esac else case "$MKTEMP" in BSD) mktemp ${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 }