diff --git a/Shorewall/Perl/Shorewall/Compiler.pm b/Shorewall/Perl/Shorewall/Compiler.pm index 52d4e1abe..49771ef3d 100644 --- a/Shorewall/Perl/Shorewall/Compiler.pm +++ b/Shorewall/Perl/Shorewall/Compiler.pm @@ -349,7 +349,7 @@ sub generate_script_3($) { ' [ -x "$IPSET" ] || fatal_error "IPSET=$IPSET does not exist or is not executable"', ' ;;', ' *)', - ' IPSET="$(which ipset)"', + ' IPSET="$(which $IPSET)"', ' [ -n "$IPSET" ] || fatal_error "The ipset utility cannot be located"' , ' ;;', 'esac', diff --git a/Shorewall/Perl/Shorewall/Config.pm b/Shorewall/Perl/Shorewall/Config.pm index 564f9ad1e..3fc3d9df3 100644 --- a/Shorewall/Perl/Shorewall/Config.pm +++ b/Shorewall/Perl/Shorewall/Config.pm @@ -358,7 +358,7 @@ sub initialize( $ ) { IPTABLES => undef, IP => undef, TC => undef, - IPSEC => undef, + IPSET => undef, # #PATH is inherited # diff --git a/Shorewall/lib.base b/Shorewall/lib.base index e045d2e7b..c7a3f57f6 100644 --- a/Shorewall/lib.base +++ b/Shorewall/lib.base @@ -161,46 +161,6 @@ run_user_exit() # $1 = file name fi } -# -# 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 @@ -373,38 +333,6 @@ 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 - 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 arithmetic and @@ -662,41 +590,6 @@ ip_vlsm() { 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 - 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 # @@ -705,224 +598,6 @@ 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 list | 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 list | grep "[[:space:]]nexthop.* $1"`) -} - -# -# Find the default route's interface -# -find_default_interface() { - ip route list | 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 - dev="$(find_rt_interface $1)" - local first - local 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 - 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 -# -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" ] || 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 -{ - 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' # @@ -1329,125 +1004,6 @@ report_capabilities1() { echo CAPVERSION=$SHOREWALL_CAPVERSION } -# -# 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 - local external - local interface - local inet - local cidr - local rest - local val1 - local arping - 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 - interface=$1 - # - # First assume that this is some sort of point-to-point interface - # - gateway=$( find_peer $(ip addr list $interface ) ) - # - # Maybe there's a default route through this gateway already - # - [ -n "$gateway" ] || gateway=$(find_gateway $(ip route list 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 - foo="$(ip -f inet6 addr list 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. @@ -1458,214 +1014,6 @@ truncate() # $1 = length 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 - level=$1 - local chain - chain=$2 - local displayChain - displayChain=$3 - local disposition - disposition=$4 - local rulenum - rulenum= - local limit - limit= - local tag - tag= - local command - command= - local prefix - local base - 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 28` " - 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 - level=$1 - local chain - chain=$2 - local disposition - disposition=$3 - - shift 3 - - do_log_rule_limit $level $chain $chain $disposition "$LOGLIMIT" "" -A $@ -} - -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 - output="$(ip link list 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 - output="$(ip link list 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 - [ -w /etc/iproute2/rt_table -a -z "$KEEP_RT_TABLES" ] && 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 - default_route= - local 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" # diff --git a/Shorewall/lib.cli b/Shorewall/lib.cli index 266c92501..dbe2339b1 100644 --- a/Shorewall/lib.cli +++ b/Shorewall/lib.cli @@ -1062,8 +1062,13 @@ add_command() { exit 2; fi - [ -n "$(mywhich ipset)" ] || fatal_error "The ipset utility cannot be located" - + case "$IPSET" in + */*) + ;; + *) + [ -n "$(mywhich $IPSET)" ] || fatal_error "The $IPSET utility cannot be located" + ;; + esac # # Normalize host list # @@ -1090,13 +1095,13 @@ add_command() { ipset=${zone}_${interface}; - if ! qt ipset -L $ipset -n; then + if ! qt $IPSET -L $ipset -n; then fatal_error "Zone $zone, interface $interface is does not have a dynamic host list" fi host=${host#*:} - if ipset -A $ipset $host; then + if $IPSET -A $ipset $host; then echo "Host $interface:$host added to zone $zone" else fatal_error "Unable to add $interface:$host to zone $zone" @@ -1115,7 +1120,13 @@ delete_command() { exit 2; fi - [ -n "$(mywhich ipset)" ] || fatal_error "The ipset utility cannot be located" + case "$IPSET" in + */*) + ;; + *) + [ -n "$(mywhich $IPSET)" ] || fatal_error "The $IPSET utility cannot be located" + ;; + esac # # Normalize host list @@ -1143,13 +1154,13 @@ delete_command() { ipset=${zone}_${interface}; - if ! qt ipset -L $ipset -n; then + if ! qt $IPSET -L $ipset -n; then fatal_error "Zone $zone, interface $interface is does not have a dynamic host list" fi host=${hostent#*:} - if ipset -D $ipset $host; then + if $IPSET -D $ipset $host; then echo "Host $hostend deleted from zone $zone" else echo " WARNING: Unable to delete host $hostent to zone $zone" >&2 diff --git a/Shorewall/shorewall b/Shorewall/shorewall index 80c6b82c9..f02fdf17d 100755 --- a/Shorewall/shorewall +++ b/Shorewall/shorewall @@ -125,6 +125,7 @@ # # get_config() { + local prog ensure_config_path @@ -186,6 +187,75 @@ get_config() { export IPTABLES + if [ -n "$IP" ]; then + case "$IP" in + */*) + if [ ! -x "$IP" ] ; then + echo " ERROR: The program specified in IP ($IP) does not exist or is not executable" >&2 + exit 2 + fi + ;; + *) + prog="$(mywhich $IP 2> /dev/null)" + if [ -z "$prog" ] ; then + echo " ERROR: Can't find $IP executable" >&2 + exit 2 + fi + IP=$prog + ;; + esac + else + IP='ip' + fi + + export IP + + if [ -n "$IPSET" ]; then + case "$IPSET" in + */*) + if [ ! -x "$IPSET" ] ; then + echo " ERROR: The program specified in IPSET ($IPSET) does not exist or is not executable" >&2 + exit 2 + fi + ;; + *) + prog="$(mywhich $IPSET 2> /dev/null)" + if [ -z "$prog" ] ; then + echo " ERROR: Can't find $IPSET executable" >&2 + exit 2 + fi + IPSET=$prog + ;; + esac + else + IPSET='ipset' + fi + + export IPSET + + if [ -n "$TC" ]; then + case "$TC" in + */*) + if [ ! -x "$TC" ] ; then + echo " ERROR: The program specified in TC ($TC) does not exist or is not executable" >&2 + exit 2 + fi + ;; + *) + prog="$(mywhich $TC 2> /dev/null)" + if [ -z "$prog" ] ; then + echo " ERROR: Can't find $TC executable" >&2 + exit 2 + fi + TC=$prog + ;; + esac + else + TC='tc' + fi + + export TC + # # Compile by non-root needs no restore file # @@ -1808,7 +1878,7 @@ case "$COMMAND" in delete) get_config shift - add_command $@ + delete_command $@ ;; save) get_config