diff --git a/Shorewall-core/lib.cli b/Shorewall-core/lib.cli index 0801254b5..5b8c1ca29 100644 --- a/Shorewall-core/lib.cli +++ b/Shorewall-core/lib.cli @@ -2209,81 +2209,81 @@ report_capabilities() { if [ $VERBOSITY -gt 1 ]; then echo "$g_product has detected the following iptables/netfilter capabilities:" - report_capability "NAT (NAT_ENABLED)" $NAT_ENABLED - report_capability "Packet Mangling (MANGLE_ENABLED)" $MANGLE_ENABLED - report_capability "Multi-port Match (MULTIPORT)" $MULTIPORT + 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)" $CONNTRACK_MATCH + report_capability "Connection Tracking Match" $CONNTRACK_MATCH if [ -n "$CONNTRACK_MATCH" ]; then - report_capability "Extended Connection Tracking Match Support (NEW_CONNTRACK_MATCH)" $NEW_CONNTRACK_MATCH - [ -n "$OLD_CONNTRACK_MATCH" ] && report_capability "Old Connection Tracking Match Syntax (OLD_CONNTRACK_MATCH)" $OLD_CONNTRACK_MATCH + 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)" $USEPKTTYPE - report_capability "Policy Match (POLICY_MATCH)" $POLICY_MATCH - report_capability "Physdev Match (PHYSDEV_MATCH)" $PHYSDEV_MATCH - report_capability "Physdev-is-bridged Support (PHYSDEV_MATCH)" $PHYSDEV_BRIDGE - report_capability "Packet length Match (LENGTH_MATCH)" $LENGTH_MATCH - report_capability "IP range Match (IPRANGE_MATCH)" $IPRANGE_MATCH - report_capability "Recent Match (RECENT_MATCH)" $RECENT_MATCH - report_capability "Owner Match (OWNER_MATCH)" $OWNER_MATCH + 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 if [ -n "$IPSET_MATCH" ]; then - report_capability "Ipset Match (IPSET_MATCH)" $IPSET_MATCH - [ -n "$OLD_IPSET_MATCH" ] && report_capability "OLD_Ipset Match (OLD_IPSET_MATCH)" $OLD_IPSET_MATCH + report_capability "Ipset Match" $IPSET_MATCH + [ -n "$OLD_IPSET_MATCH" ] && report_capability "OLD_Ipset Match" $OLD_IPSET_MATCH fi - report_capability "CONNMARK Target (CONNMARK)" $CONNMARK - [ -n "$CONNMARK" ] && report_capability "Extended CONNMARK Target (XCONNMARK)" $XCONNMARK - report_capability "Connmark Match (CONNMARK_MATCH)" $CONNMARK_MATCH - [ -n "$CONNMARK_MATCH" ] && report_capability "Extended Connmark Match (XCONNMARK_MATCH)" $XCONNMARK_MATCH - report_capability "Raw Table (RAW_TABLE)" $RAW_TABLE - report_capability "Rawpost Table (RAWPOST_TABLE)" $RAWPOST_TABLE - report_capability "IPP2P Match (IPP2P_MATCH)" $IPP2P_MATCH - [ -n "$OLD_IPP2P_MATCH" ] && report_capability "Old IPP2P Match Syntax (OLD_IPP2P_MATCH)" $OLD_IPP2P_MATCH - report_capability "CLASSIFY Target (CLASSIFY_TARGET)" $CLASSIFY_TARGET - report_capability "Extended REJECT (ENHANCED_REJECT)" $ENHANCED_REJECT - report_capability "Repeat match (KLUDGEFREE)" $KLUDGEFREE - report_capability "MARK Target (MARK)" $MARK - [ -n "$MARK" ] && report_capability "Extended MARK Target (XMARK)" $XMARK - [ -n "$XMARK" ] && report_capability "Extended MARK Target 2 (EXMARK)" $EXMARK - report_capability "Mangle FORWARD Chain (MANGLE_FORWARD)" $MANGLE_FORWARD - report_capability "Comments (COMMENTS)" $COMMENTS - report_capability "Address Type Match (ADDRTYPE)" $ADDRTYPE - report_capability "TCPMSS Match (TCPMSS_MATCH)" $TCPMSS_MATCH - report_capability "Hashlimit Match (HASHLIMIT_MATCH)" $HASHLIMIT_MATCH - [ -n "$OLD_HL_MATCH" ] && report_capability "Old Hashlimit Match (OLD_HL_MATCH)" $OLD_HL_MATCH - report_capability "NFQUEUE Target (NFQUEUE_TARGET)" $NFQUEUE_TARGET - report_capability "Realm Match (RELM_MATCH)" $REALM_MATCH - report_capability "Helper Match (HELPER_MATCH)" $HELPER_MATCH - report_capability "Connlimit Match (CONNLIMIT_MATCH)" $CONNLIMIT_MATCH - report_capability "Time Match (TIME_MATCH)" $TIME_MATCH - report_capability "Goto Support (GOTO_TARGET)" $GOTO_TARGET - report_capability "LOGMARK Target (LOGMARK_TARGET)" $LOGMARK_TARGET - report_capability "IPMARK Target (IPMARK_TARGET)" $IPMARK_TARGET - report_capability "LOG Target (LOG_TARGET)" $LOG_TARGET - report_capability "ULOG Target (ULOG_TARGET)" $ULOG_TARGET - report_capability "NFLOG Target (NFLOG_TARGET)" $NFLOG_TARGET - report_capability "Persistent SNAT (PERSISTENT_SNAT)" $PERSISTENT_SNAT - report_capability "TPROXY Target (TPROXY_TARGET)" $TPROXY_TARGET - report_capability "FLOW Classifier (FLOW_FILTER)" $FLOW_FILTER - report_capability "fwmark route mask (FWMARK_RT_MASK)" $FWMARK_RT_MASK - report_capability "Mark in any table (MARK_ANYWHERE)" $MARK_ANYWHERE - report_capability "Header Match (HEADER_MATCH)" $HEADER_MATCH - report_capability "ACCOUNT Target (ACCOUNT_TARGET)" $ACCOUNT_TARGET - report_capability "AUDIT Target (AUDIT_TARGET)" $AUDIT_TARGET - report_capability "ipset V5 (IPSET_V5)" $IPSET_V5 - report_capability "Condition Match (CONDITION_MATCH)" $CONDITION_MATCH - report_capability "Statistic Match (STATISTIC_MATCH)" $STATISTIC_MATCH - report_capability "IMQ Target (IMQ_TARGET)" $IMQ_TARGET - report_capability "DSCP Match (DSCP_MATCH)" $DSCP_MATCH - report_capability "DSCP Target (DSCP_TARGET)" $DSCP_TARGET + 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 "Rawpost Table" $RAWPOST_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 "ULOG Target" $ULOG_TARGET + report_capability "NFLOG Target" $NFLOG_TARGET + report_capability "Persistent SNAT" $PERSISTENT_SNAT + report_capability "TPROXY Target" $TPROXY_TARGET + report_capability "FLOW Classifier" $FLOW_FILTER + report_capability "fwmark route mask" $FWMARK_RT_MASK + report_capability "Mark in any table" $MARK_ANYWHERE + report_capability "Header Match" $HEADER_MATCH + report_capability "ACCOUNT Target" $ACCOUNT_TARGET + report_capability "AUDIT Target" $AUDIT_TARGET + report_capability "ipset V5" $IPSET_V5 + report_capability "Condition Match" $CONDITION_MATCH + report_capability "Statistic Match" $STATISTIC_MATCH + report_capability "IMQ Target" $IMQ_TARGET + report_capability "DSCP Match" $DSCP_MATCH + report_capability "DSCP Target" $DSCP_TARGET if [ $g_family -eq 4 ]; then - report_capability "iptables -S (IPTABLES_S)" $IPTABLES_S + report_capability "iptables -S" $IPTABLES_S else - report_capability "ip6tables -S (IPTABLES_S)" $IPTABLES_S + report_capability "ip6tables -S" $IPTABLES_S fi - report_capability "Basic Filter (BASIC_FILTER)" $BASIC_FILTER - report_capability "CT Target (CT_TARGET)" $CT_TARGET + report_capability "Basic Filter" $BASIC_FILTER + report_capability "CT Target" $CT_TARGET fi [ -n "$PKTTYPE" ] || USEPKTTYPE= diff --git a/Shorewall/Perl/Shorewall/Config.pm b/Shorewall/Perl/Shorewall/Config.pm index 7c157674a..7e751555a 100644 --- a/Shorewall/Perl/Shorewall/Config.pm +++ b/Shorewall/Perl/Shorewall/Config.pm @@ -1470,10 +1470,7 @@ sub do_open_file( $ ) { open $currentfile, '<', $fname or fatal_error "Unable to open $fname: $!"; $currentlinenumber = 0; $ifstack = @ifstack; - # - # Must be last - # - $currentfilename = $fname; + $currentfilename = $fname; } sub open_file( $ ) { @@ -1527,7 +1524,7 @@ sub close_file() { } # -# Process an ?IF, ?ELSE, or ?ENDIF. Returns the new $omitting setting. +# Process an ?IF, ?ELSE, or ?ENDIF # sub process_conditional($$$) { my ( $omitting, $keyword, $rest ) = @_; @@ -1538,23 +1535,18 @@ sub process_conditional($$$) { fatal_error "Missing IF variable" unless $rest; my $invert = $rest =~ s/^!\s*//; - fatal_error "Invalid IF variable ($rest)" unless ( $rest =~ s/^\$// || $rest =~ /^__/ ) && $rest =~ /^\w+$/; + fatal_error "Invalid IF variable ($rest)" unless $rest =~ s/^\$// && $rest =~ /^\w+$/; push @ifstack, [ 'IF', $omitting, $currentlinenumber ]; - if ( $rest eq '__IPV4' ) { - $omitting = $family == F_IPV6; - } elsif ( $rest eq '__IPV6' ) { + if ( $rest eq '__IPV6' ) { $omitting = $family == F_IPV4; + } elsif ( $rest eq '__IPV4' ) { + $omitting = $family == F_IPV6; } else { - my $cap; - - ($cap = $rest) =~ s/^__//; - - $omitting = ! ( exists $ENV{$rest} ? $ENV{$rest} : - exists $params{$rest} ? $params{$rest} : - exists $config{$rest} ? $config{$rest} : - exists $capdesc{$cap} ? have_capability( $cap ) : 0 ); + $omitting = ! ( exists $ENV{$rest} ? $ENV{$rest} : + exists $params{$rest} ? $params{$rest} : + exists $config{$rest} ? $config{$rest} : 0 ); } $omitting = ! $omitting if $invert; diff --git a/Shorewall/action.Broadcast b/Shorewall/action.Broadcast index 3cdf559df..38fe75d0d 100644 --- a/Shorewall/action.Broadcast +++ b/Shorewall/action.Broadcast @@ -46,7 +46,7 @@ my $chainref = get_action_chain; my ( $level, $tag ) = get_action_logging; my $target = require_audit ( $action , $audit ); -?IF __ADDRTYPE +if ( have_capability( 'ADDRTYPE' ) ) { if ( $level ne '' ) { log_rule_limit $level, $chainref, 'dropBcast' , $action, '', $tag, 'add', ' -m addrtype --dst-type BROADCAST '; log_rule_limit $level, $chainref, 'dropBcast' , $action, '', $tag, 'add', ' -m addrtype --dst-type MULTICAST '; @@ -56,14 +56,14 @@ my $target = require_audit ( $action , $audit ); add_jump $chainref, $target, 0, '-m addrtype --dst-type BROADCAST '; add_jump $chainref, $target, 0, '-m addrtype --dst-type MULTICAST '; add_jump $chainref, $target, 0, '-m addrtype --dst-type ANYCAST '; -?ELSE #Begin no Addrtype support +} else { add_commands $chainref, 'for address in $ALL_BCASTS; do'; incr_cmd_level $chainref; log_rule_limit $level, $chainref, 'Broadcast' , $action, '', $tag, 'add', ' -d $address ' if $level ne ''; add_jump $chainref, $target, 0, "-d \$address "; decr_cmd_level $chainref; add_commands $chainref, 'done'; -?END #No Addrtype support +} log_rule_limit $level, $chainref, 'Broadcast' , $action, '', $tag, 'add', ' -d 224.0.0.0/4 ' if $level ne ''; add_jump $chainref, $target, 0, '-d 224.0.0.0/4 '; diff --git a/Shorewall/action.DropSmurfs b/Shorewall/action.DropSmurfs index 34c1320d5..068c05939 100644 --- a/Shorewall/action.DropSmurfs +++ b/Shorewall/action.DropSmurfs @@ -50,32 +50,32 @@ if ( $level ne '-' || $audit ne '-' ) { $target = 'DROP'; } -?IF __ADDRTYPE -?IF __IPV4 - add_ijump $chainref , j => 'RETURN', s => '0.0.0.0'; ; -?ELSE - add_ijump $chainref , j => 'RETURN', s => '::'; -?END +if ( have_capability( 'ADDRTYPE' ) ) { + if ( $family == F_IPV4 ) { + add_ijump $chainref , j => 'RETURN', s => '0.0.0.0'; ; + } else { + add_ijump $chainref , j => 'RETURN', s => '::'; + } add_ijump( $chainref, g => $target, addrtype => '--src-type BROADCAST' ) ; -?ELSE # Begin no Addrtype support -?IF __IPV4 - add_commands $chainref, 'for address in $ALL_BCASTS; do'; -?ELSE - add_commands $chainref, 'for address in $ALL_ACASTS; do'; -?END +} else { + if ( $family == F_IPV4 ) { + add_commands $chainref, 'for address in $ALL_BCASTS; do'; + } else { + add_commands $chainref, 'for address in $ALL_ACASTS; do'; + } incr_cmd_level $chainref; add_ijump( $chainref, g => $target, s => '$address' ); decr_cmd_level $chainref; add_commands $chainref, 'done'; -?END # No Addrtype support +} -?IF __IPV4 +if ( $family == F_IPV4 ) { add_ijump( $chainref, g => $target, s => '224.0.0.0/4' ); -?ELSE +} else { add_ijump( $chainref, g => $target, s => IPv6_MULTICAST ); -?END +} END PERL; diff --git a/Shorewall/lib.core b/Shorewall/lib.core index ca4f78a27..ed1a2479e 100644 --- a/Shorewall/lib.core +++ b/Shorewall/lib.core @@ -26,6 +26,658 @@ # ######################################################################################### +?IF $__IPV4 +# +# Find the value 'weight' in the passed arguments then echo the next value +# + +find_weight() { + while [ $# -gt 1 ]; do + [ "x$1" = xweight ] && 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 -4 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 +} + +# +# 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 +} + +# +# 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 -4 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 the broadcast addresses associated with an interface +# +get_interface_bcasts() # $1 = interface +{ + local addresses + addresses= + + $IP -f inet addr show dev $1 2> /dev/null | grep 'inet.*brd' | sed 's/inet.*brd //; s/scope.*//;' | sort -u +} + +# +# Delete IP address +# +del_ip_addr() # $1 = address, $2 = interface +{ + [ $(find_first_interface_address_if_any $2) = $1 ] || qtnoin $IP addr del $1 dev $2 +} + +# Add IP Aliases +# +add_ip_aliases() # $* = List of addresses +{ + local local + local addresses + local external + local interface + local inet + local cidr + local rest + local val + 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 the gateway through a PPP or DHCP-configured interface +# +detect_dynamic_gateway() { # $1 = interface + local interface + interface=$1 + local GATEWAYS + GATEWAYS= + local gateway + + gateway=$(run_findgw_exit $1); + + if [ -z "$gateway" ]; then + gateway=$( find_peer $($IP addr list $interface ) ) + fi + + if [ -z "$gateway" -a -f /var/lib/dhcpcd/dhcpcd-${1}.info ]; then + eval $(grep ^GATEWAYS= /var/lib/dhcpcd/dhcpcd-${1}.info 2> /dev/null) + [ -n "$GATEWAYS" ] && GATEWAYS=${GATEWAYS%,*} && gateway=$GATEWAYS + fi + + if [ -z "$gateway" -a -f /var/lib/dhcp/dhclient-${1}.lease ]; then + gateway=$(grep 'option routers' /var/lib/dhcp/dhclient-${1}.lease | tail -n 1 | while read j1 j2 gateway; do echo $gateway ; return 0; done) + fi + + [ -n "$gateway" ] && echo $gateway +} + +# +# Detect the gateway through an interface +# +detect_gateway() # $1 = interface +{ + local interface + interface=$1 + local gateway + # + # First assume that this is some sort of dynamic interface + # + gateway=$( detect_dynamic_gateway $interface ) + # + # Maybe there's a default route through this gateway already + # + [ -n "$gateway" ] || gateway=$(find_gateway $($IP -4 route list dev $interface | grep ^default)) + # + # 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 [ -x "$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 +} + +# +# Add an additional gateway to the default route +# +add_gateway() # $1 = Delta $2 = Table Number +{ + local route + local weight + local delta + local dev + + route=`$IP -4 -o route ls table $2 | grep ^default | sed 's/default //; s/[\]//g'` + + if [ -z "$route" ]; then + run_ip route add default scope global table $2 $1 + else + delta=$1 + + if ! echo $route | fgrep -q ' nexthop '; then + route=`echo $route | sed 's/via/nexthop via/'` + dev=$(find_device $route) + if [ -f ${VARDIR}/${dev}_weight ]; then + weight=`cat ${VARDIR}/${dev}_weight` + route="$route weight $weight" + fi + fi + + run_ip route replace default scope global table $2 $route $delta + fi +} + +# +# Remove a gateway from the default route +# +delete_gateway() # $! = Description of the Gateway $2 = table number $3 = device +{ + local route + local gateway + local dev + + route=`$IP -4 -o route ls table $2 | grep ^default | sed 's/[\]//g'` + gateway=$1 + + if [ -n "$route" ]; then + if echo $route | fgrep -q ' nexthop '; then + gateway="nexthop $gateway" + eval route=\`echo $route \| sed \'s/$gateway/ /\'\` + run_ip route replace table $2 $route + else + dev=$(find_device $route) + [ "$dev" = "$3" ] && run_ip route delete default table $2 + fi + fi +} + +# +# Determine the MAC address of the passed IP through the passed interface +# +find_mac() # $1 = IP address, $2 = interface +{ + if interface_is_usable $2 ; then + qt ping -nc 1 -t 2 -I $2 $1 + + local result + result=$($IP neigh list | awk "/^$1 / {print \$5}") + + case $result in + \<*\>) + ;; + *) + [ -n "$result" ] && echo $result + ;; + esac + fi +} + +# +# Clear Proxy Arp +# +delete_proxyarp() { + if [ -f ${VARDIR}/proxyarp ]; then + while read address interface external haveroute; do + qtnoin $IP -4 neigh del proxy $address dev $external + [ -z "${haveroute}${g_noroutes}" ] && qtnoin $IP -4 route del $address/32 dev $interface + f=/proc/sys/net/ipv4/conf/$interface/proxy_arp + [ -f $f ] && echo 0 > $f + done < ${VARDIR}/proxyarp + + rm -f ${VARDIR}/proxyarp + fi +} + +# +# Remove all Shorewall-added rules +# +clear_firewall() { + stop_firewall + + setpolicy INPUT ACCEPT + setpolicy FORWARD ACCEPT + setpolicy OUTPUT ACCEPT + + run_iptables -F + qt $IPTABLES -t raw -F + + echo 1 > /proc/sys/net/ipv4/ip_forward + + if [ -n "$DISABLE_IPV6" ]; then + if [ -x $IP6TABLES ]; then + $IP6TABLES -P INPUT ACCEPT 2> /dev/null + $IP6TABLES -P OUTPUT ACCEPT 2> /dev/null + $IP6TABLES -P FORWARD ACCEPT 2> /dev/null + fi + fi + + run_clear_exit + + set_state "Cleared" + + logger -p kern.info "$g_product Cleared" +} + +# +# Get a list of all configured broadcast addresses on the system +# +get_all_bcasts() +{ + $IP -f inet addr show 2> /dev/null | grep 'inet.*brd' | grep -v '/32 ' | sed 's/inet.*brd //; s/scope.*//;' | sort -u +} +?ELSE +# +# Get all interface addresses with VLSMs +# + +find_interface_full_addresses() # $1 = interface +{ + $IP -f inet6 addr show $1 2> /dev/null | grep 'inet6 ' | sed 's/\s*inet6 //;s/ scope.*//;s/ peer.*//' +} + +# +# Normalize an IPv6 Address by compressing out consecutive zero elements +# +normalize_address() # $1 = valid IPv6 Address +{ + local address + address=$1 + local j + + while true; do + case $address in + ::*) + address=0$address + ;; + *::*) + list_count $(split $address) + + j=$? + + if [ $j -eq 7 ]; then + address=${address%::*}:0:${address#*::} + elif [ $j -eq 8 ]; then + $address=${address%::*}:${address#*::} + break 2 + else + address=${address%::*}:0::${address#*::} + fi + ;; + *) + echo $address + break 2 + ;; + esac + done +} + +# +# Reads correctly-formed and fully-qualified host and subnet addresses from STDIN. For each +# that defines a /120 or larger network, it sends to STDOUT: +# +# The corresponding subnet-router anycast address (all host address bits are zero) +# The corresponding anycast addresses defined by RFC 2526 (the last 128 addresses in the subnet) +# +convert_to_anycast() { + local address + local badress + local vlsm + local host + local o + local m + m= + local z + z=65535 + local l + + while read address; do + case $address in + 2*|3*) + vlsm=${address#*/} + vlsm=${vlsm:=128} + + if [ $vlsm -le 120 ]; then + # + # Defines a viable subnet -- first get the subnet-router anycast address + # + host=$((128 - $vlsm)) + + address=$(normalize_address ${address%/*}) + + while [ $host -ge 16 ]; do + address=${address%:*} + host=$(($host - 16)) + done + + if [ $host -gt 0 ]; then + # + # VLSM is not a multiple of 16 + # + host=$((16 - $host)) + o=$((0x${address##*:})) + m=0 + while [ $host -gt 0 ]; do + m=$((($m >> 1) | 0x8000)) + z=$(($z >> 1)) + host=$(($host - 1)) + done + + o=$(($o & $m)) + + badress=${address%:*} + + address=$badress:$(printf %04x $o) + + z=$(($o | $z)) + + if [ $vlsm -gt 112 ]; then + z=$(($z & 0xff80)) + fi + + badress=$badress:$(printf %04x $z) + else + badress=$address + fi + # + # Note: at this point $address and $badress are the same except possibly for + # the contents of the last half-word + # + list_count $(split $address) + + l=$? + # + # Now generate the anycast addresses defined by RFC 2526 + # + if [ $l -lt 8 ]; then + # + # The subnet-router address + # + echo $address:: + + while [ $l -lt 8 ]; do + badress=$badress:ffff + l=$(($l + 1 )) + done + else + # + # The subnet-router address + # + echo $address + fi + # + # And the RFC 2526 addresses + # + echo $badress/121 + fi + ;; + esac + done +} + +# +# Generate a list of anycast addresses for a given interface +# + +get_interface_acasts() # $1 = interface +{ + local addresses + addresses= + + find_interface_full_addresses $1 | convert_to_anycast | sort -u +} + +# +# Get a list of all configured anycast addresses on the system +# +get_all_acasts() +{ + find_interface_full_addresses | convert_to_anycast | sort -u +} + +# +# Detect the gateway through an interface +# +detect_gateway() # $1 = interface +{ + local interface + interface=$1 + # + # First assume that this is some sort of point-to-point interface + # + gateway=$( find_peer $($IP -6 addr list $interface ) ) + # + # Maybe there's a default route through this gateway already + # + [ -n "$gateway" ] || gateway=$(find_gateway $($IP -6 route list dev $interface | grep '^default')) + # + # 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 +} + +# +# Add an additional gateway to the default route +# +add_gateway() # $1 = Delta $2 = Table Number +{ + local route + local weight + local delta + local dev + + run_ip route add default scope global table $2 $1 +} + +# +# Remove a gateway from the default route +# +delete_gateway() # $! = Description of the Gateway $2 = table number $3 = device +{ + local route + local gateway + local dev + + route=`$IP -6 -o route ls table $2 | grep ^default | sed 's/[\]//g'` + gateway=$1 + + dev=$(find_device $route) + [ "$dev" = "$3" ] && run_ip route delete default table $2 +} + +# +# 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 +} + +# +# Clear Proxy NDP +# +delete_proxyndp() { + if [ -f ${VARDIR}/proxyndp ]; then + while read address interface external haveroute; do + qt $IP -6 neigh del proxy $address dev $external + [ -z "${haveroute}${g_noroutes}" ] && qt $IP -6 route del $address/128 dev $interface + f=/proc/sys/net/ipv6/conf/$interface/proxy_ndp + [ -f $f ] && echo 0 > $f + done < ${VARDIR}/proxyndp + + rm -f ${VARDIR}/proxyndp + fi +} + +# +# Remove all Shorewall-added rules +# +clear_firewall() { + stop_firewall + + setpolicy INPUT ACCEPT + setpolicy FORWARD ACCEPT + setpolicy OUTPUT ACCEPT + + run_iptables -F + qt $IP6TABLES -t raw -F + + echo 1 > /proc/sys/net/ipv6/conf/all/forwarding + + run_clear_exit + + set_state "Cleared" + + logger -p kern.info "$g_product Cleared" +} + +?ENDIF + # # Conditionally produce message # @@ -631,657 +1283,3 @@ EOF done fi } - -?IF __IPV4 #Beginning of IPv4-specific functions -# -# Find the value 'weight' in the passed arguments then echo the next value -# - -find_weight() { - while [ $# -gt 1 ]; do - [ "x$1" = xweight ] && 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 -4 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 -} - -# -# 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 -} - -# -# 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 -4 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 the broadcast addresses associated with an interface -# -get_interface_bcasts() # $1 = interface -{ - local addresses - addresses= - - $IP -f inet addr show dev $1 2> /dev/null | grep 'inet.*brd' | sed 's/inet.*brd //; s/scope.*//;' | sort -u -} - -# -# Delete IP address -# -del_ip_addr() # $1 = address, $2 = interface -{ - [ $(find_first_interface_address_if_any $2) = $1 ] || qtnoin $IP addr del $1 dev $2 -} - -# Add IP Aliases -# -add_ip_aliases() # $* = List of addresses -{ - local local - local addresses - local external - local interface - local inet - local cidr - local rest - local val - 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 the gateway through a PPP or DHCP-configured interface -# -detect_dynamic_gateway() { # $1 = interface - local interface - interface=$1 - local GATEWAYS - GATEWAYS= - local gateway - - gateway=$(run_findgw_exit $1); - - if [ -z "$gateway" ]; then - gateway=$( find_peer $($IP addr list $interface ) ) - fi - - if [ -z "$gateway" -a -f /var/lib/dhcpcd/dhcpcd-${1}.info ]; then - eval $(grep ^GATEWAYS= /var/lib/dhcpcd/dhcpcd-${1}.info 2> /dev/null) - [ -n "$GATEWAYS" ] && GATEWAYS=${GATEWAYS%,*} && gateway=$GATEWAYS - fi - - if [ -z "$gateway" -a -f /var/lib/dhcp/dhclient-${1}.lease ]; then - gateway=$(grep 'option routers' /var/lib/dhcp/dhclient-${1}.lease | tail -n 1 | while read j1 j2 gateway; do echo $gateway ; return 0; done) - fi - - [ -n "$gateway" ] && echo $gateway -} - -# -# Detect the gateway through an interface -# -detect_gateway() # $1 = interface -{ - local interface - interface=$1 - local gateway - # - # First assume that this is some sort of dynamic interface - # - gateway=$( detect_dynamic_gateway $interface ) - # - # Maybe there's a default route through this gateway already - # - [ -n "$gateway" ] || gateway=$(find_gateway $($IP -4 route list dev $interface | grep ^default)) - # - # 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 [ -x "$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 -} - -# -# Add an additional gateway to the default route -# -add_gateway() # $1 = Delta $2 = Table Number -{ - local route - local weight - local delta - local dev - - route=`$IP -4 -o route ls table $2 | grep ^default | sed 's/default //; s/[\]//g'` - - if [ -z "$route" ]; then - run_ip route add default scope global table $2 $1 - else - delta=$1 - - if ! echo $route | fgrep -q ' nexthop '; then - route=`echo $route | sed 's/via/nexthop via/'` - dev=$(find_device $route) - if [ -f ${VARDIR}/${dev}_weight ]; then - weight=`cat ${VARDIR}/${dev}_weight` - route="$route weight $weight" - fi - fi - - run_ip route replace default scope global table $2 $route $delta - fi -} - -# -# Remove a gateway from the default route -# -delete_gateway() # $! = Description of the Gateway $2 = table number $3 = device -{ - local route - local gateway - local dev - - route=`$IP -4 -o route ls table $2 | grep ^default | sed 's/[\]//g'` - gateway=$1 - - if [ -n "$route" ]; then - if echo $route | fgrep -q ' nexthop '; then - gateway="nexthop $gateway" - eval route=\`echo $route \| sed \'s/$gateway/ /\'\` - run_ip route replace table $2 $route - else - dev=$(find_device $route) - [ "$dev" = "$3" ] && run_ip route delete default table $2 - fi - fi -} - -# -# Determine the MAC address of the passed IP through the passed interface -# -find_mac() # $1 = IP address, $2 = interface -{ - if interface_is_usable $2 ; then - qt ping -nc 1 -t 2 -I $2 $1 - - local result - result=$($IP neigh list | awk "/^$1 / {print \$5}") - - case $result in - \<*\>) - ;; - *) - [ -n "$result" ] && echo $result - ;; - esac - fi -} - -# -# Clear Proxy Arp -# -delete_proxyarp() { - if [ -f ${VARDIR}/proxyarp ]; then - while read address interface external haveroute; do - qtnoin $IP -4 neigh del proxy $address dev $external - [ -z "${haveroute}${g_noroutes}" ] && qtnoin $IP -4 route del $address/32 dev $interface - f=/proc/sys/net/ipv4/conf/$interface/proxy_arp - [ -f $f ] && echo 0 > $f - done < ${VARDIR}/proxyarp - - rm -f ${VARDIR}/proxyarp - fi -} - -# -# Remove all Shorewall-added rules -# -clear_firewall() { - stop_firewall - - setpolicy INPUT ACCEPT - setpolicy FORWARD ACCEPT - setpolicy OUTPUT ACCEPT - - run_iptables -F - qt $IPTABLES -t raw -F - - echo 1 > /proc/sys/net/ipv4/ip_forward - - if [ -n "$DISABLE_IPV6" ]; then - if [ -x $IP6TABLES ]; then - $IP6TABLES -P INPUT ACCEPT 2> /dev/null - $IP6TABLES -P OUTPUT ACCEPT 2> /dev/null - $IP6TABLES -P FORWARD ACCEPT 2> /dev/null - fi - fi - - run_clear_exit - - set_state "Cleared" - - logger -p kern.info "$g_product Cleared" -} - -# -# Get a list of all configured broadcast addresses on the system -# -get_all_bcasts() -{ - $IP -f inet addr show 2> /dev/null | grep 'inet.*brd' | grep -v '/32 ' | sed 's/inet.*brd //; s/scope.*//;' | sort -u -} - -?ELSE # End of IPv4 and Beginning of IPv6 - -# -# Get all interface addresses with VLSMs -# - -find_interface_full_addresses() # $1 = interface -{ - $IP -f inet6 addr show $1 2> /dev/null | grep 'inet6 ' | sed 's/\s*inet6 //;s/ scope.*//;s/ peer.*//' -} - -# -# Normalize an IPv6 Address by compressing out consecutive zero elements -# -normalize_address() # $1 = valid IPv6 Address -{ - local address - address=$1 - local j - - while true; do - case $address in - ::*) - address=0$address - ;; - *::*) - list_count $(split $address) - - j=$? - - if [ $j -eq 7 ]; then - address=${address%::*}:0:${address#*::} - elif [ $j -eq 8 ]; then - $address=${address%::*}:${address#*::} - break 2 - else - address=${address%::*}:0::${address#*::} - fi - ;; - *) - echo $address - break 2 - ;; - esac - done -} - -# -# Reads correctly-formed and fully-qualified host and subnet addresses from STDIN. For each -# that defines a /120 or larger network, it sends to STDOUT: -# -# The corresponding subnet-router anycast address (all host address bits are zero) -# The corresponding anycast addresses defined by RFC 2526 (the last 128 addresses in the subnet) -# -convert_to_anycast() { - local address - local badress - local vlsm - local host - local o - local m - m= - local z - z=65535 - local l - - while read address; do - case $address in - 2*|3*) - vlsm=${address#*/} - vlsm=${vlsm:=128} - - if [ $vlsm -le 120 ]; then - # - # Defines a viable subnet -- first get the subnet-router anycast address - # - host=$((128 - $vlsm)) - - address=$(normalize_address ${address%/*}) - - while [ $host -ge 16 ]; do - address=${address%:*} - host=$(($host - 16)) - done - - if [ $host -gt 0 ]; then - # - # VLSM is not a multiple of 16 - # - host=$((16 - $host)) - o=$((0x${address##*:})) - m=0 - while [ $host -gt 0 ]; do - m=$((($m >> 1) | 0x8000)) - z=$(($z >> 1)) - host=$(($host - 1)) - done - - o=$(($o & $m)) - - badress=${address%:*} - - address=$badress:$(printf %04x $o) - - z=$(($o | $z)) - - if [ $vlsm -gt 112 ]; then - z=$(($z & 0xff80)) - fi - - badress=$badress:$(printf %04x $z) - else - badress=$address - fi - # - # Note: at this point $address and $badress are the same except possibly for - # the contents of the last half-word - # - list_count $(split $address) - - l=$? - # - # Now generate the anycast addresses defined by RFC 2526 - # - if [ $l -lt 8 ]; then - # - # The subnet-router address - # - echo $address:: - - while [ $l -lt 8 ]; do - badress=$badress:ffff - l=$(($l + 1 )) - done - else - # - # The subnet-router address - # - echo $address - fi - # - # And the RFC 2526 addresses - # - echo $badress/121 - fi - ;; - esac - done -} - -# -# Generate a list of anycast addresses for a given interface -# - -get_interface_acasts() # $1 = interface -{ - local addresses - addresses= - - find_interface_full_addresses $1 | convert_to_anycast | sort -u -} - -# -# Get a list of all configured anycast addresses on the system -# -get_all_acasts() -{ - find_interface_full_addresses | convert_to_anycast | sort -u -} - -# -# Detect the gateway through an interface -# -detect_gateway() # $1 = interface -{ - local interface - interface=$1 - # - # First assume that this is some sort of point-to-point interface - # - gateway=$( find_peer $($IP -6 addr list $interface ) ) - # - # Maybe there's a default route through this gateway already - # - [ -n "$gateway" ] || gateway=$(find_gateway $($IP -6 route list dev $interface | grep '^default')) - # - # 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 -} - -# -# Add an additional gateway to the default route -# -add_gateway() # $1 = Delta $2 = Table Number -{ - local route - local weight - local delta - local dev - - run_ip route add default scope global table $2 $1 -} - -# -# Remove a gateway from the default route -# -delete_gateway() # $! = Description of the Gateway $2 = table number $3 = device -{ - local route - local gateway - local dev - - route=`$IP -6 -o route ls table $2 | grep ^default | sed 's/[\]//g'` - gateway=$1 - - dev=$(find_device $route) - [ "$dev" = "$3" ] && run_ip route delete default table $2 -} - -# -# 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 -} - -# -# Clear Proxy NDP -# -delete_proxyndp() { - if [ -f ${VARDIR}/proxyndp ]; then - while read address interface external haveroute; do - qt $IP -6 neigh del proxy $address dev $external - [ -z "${haveroute}${g_noroutes}" ] && qt $IP -6 route del $address/128 dev $interface - f=/proc/sys/net/ipv6/conf/$interface/proxy_ndp - [ -f $f ] && echo 0 > $f - done < ${VARDIR}/proxyndp - - rm -f ${VARDIR}/proxyndp - fi -} - -# -# Remove all Shorewall-added rules -# -clear_firewall() { - stop_firewall - - setpolicy INPUT ACCEPT - setpolicy FORWARD ACCEPT - setpolicy OUTPUT ACCEPT - - run_iptables -F - qt $IP6TABLES -t raw -F - - echo 1 > /proc/sys/net/ipv6/conf/all/forwarding - - run_clear_exit - - set_state "Cleared" - - logger -p kern.info "$g_product Cleared" -} - -?ENDIF #end if IPv6 diff --git a/docs/configuration_file_basics.xml b/docs/configuration_file_basics.xml index 502c8f625..85774c617 100644 --- a/docs/configuration_file_basics.xml +++ b/docs/configuration_file_basics.xml @@ -1485,18 +1485,9 @@ SHELL cat /etc/shorewall/rules.d/*.rules 2> /dev/null || true/etc/shorewall/params, and in options set in /etc/shorewall/shorewall.conf - in that order. If the variable is still not - found and it begins with '__', then those leading characters are stripped - off and the result is searched for in the defined - capabilities. The current set of capabilities may - be obtained by the command shorewall show capabilities - (the capability names are in parentheses). - - If it is not found in any of those places, the + in that order. If it is not found in any of those places, the variable is assumed to have a value of 0 - (false). - - If "!" is present, the result value is inverted. + (false). If "!" is present, the result of the test is inverted. The setting in /etc/shorewall/params by be overridden at runtime, provided the setting in