On 5/26/2015 12:24 PM, Tom Eastep wrote:
> On 5/26/2015 9:45 AM, Antonio Eugenio Burriel wrote:
>> Hi Tom and sorry for the late answer,
>>
>>
>>> If you mean that the *sum* of the normalized probabilities exceeds 1.0,
>>> that is to be expected. Remember that those packets that have been given
>>> a mark for an interface are not passed on to the rule for the remaining
>>> interfaces . So, in your example with DSL3 'enabled', the normalized
>>> probabilities are:
>>>
>>> DSL1 = 0.25000000
>>> DSL2 = 0.33333333
>>> DSL3 = 1.00000000
>> Exactly, that's what I meant.
>>
>> But, with the previous three providers, Shorewall computes these:
>> Interface dsl0 probability=.25000000
>> Interface dsl1 probability=.33333333
>> Interface dsl2 probability=1.19999999
>>
>> So iptables complains:
>> iptables v1.4.20: statistic: bad value for option "--probability", or
>> out of range (0-1).
>>
>> Try `iptables -h' or 'iptables --help' for more information.
>>    ERROR: Command "/sbin/iptables -t mangle -A ~dsl2 -m statistic
>> --mode random --probability 1.19999999 -j MARK --set-mark
>> 0x30000/0xff0000"
>>
>> I haven't yet got the time to think about this, buy maybe it will be
>> enough to clamp $load before passing it to iptables
> I committed such a change several days ago:
>
> http://sourceforge.net/p/shorewall/code/ci/c851e03313a7006e1c080fa2de9a49e4ed4f6d7f
>
I've also determined the flaw in the current algorithm -- we should be
subtracting the original load from totalload, not the normalized load.
We should also not be adding an updated rule for interfaces that aren't
enabled.

In my current lib.core is attached. I renamed some variables in addition
to correcting the calculations.

-Tom

-- 
Tom Eastep        \ When I die, I want to go like my Grandfather who
Shoreline,         \ died peacefully in his sleep. Not screaming like
Washington, USA     \ all of the passengers in his car
http://shorewall.net \________________________________________________

#   (c) 1999-2015 - Tom Eastep ([email protected])
#
#       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 <http://www.gnu.org/licenses/>.
#
#       Options are:
#
#           -n                          Do not alter Routing
#           -v and -q                   Standard Shorewall Verbosity control
#           -t                          Timestamp progress messages
#           -p                          Purge conntrack table
#           -r                          Recover from failed start/restart
#           -V <verbosity>              Set verbosity level explicitly
#           -R <restore>                Overrides RESTOREFILE setting
#
#       Commands are:
#
#           clear                       Removes all firewall rules
#           disable                     Disable an optional interface
#           down                        Stop an optional interface
#           enable                      Enable an optional interface
#           help                        Show command syntax
#           reenable                    Disable then nable an optional
#                                       interface
#           refresh                     Refresh the firewall
#           reload                      Reload the firewall
#           restart                     Restarts the firewall
#           restore                     Restore a saved configuration
#           reset                       Reset byte and packet counters
#           run                         Call a function in this program
#           savesets                    Save the ipset contents
#           status                      Displays firewall status
#           start                       Starts the firewall
#           stop                        Stops the firewall
#           up                          Start an optional interface
#           version                     Displays the version of Shorewall that
#                                       generated this program
#
################################################################################
# Functions imported from /usr/share/shorewall/lib.core
################################################################################
#                     Address family-neutral Functions
################################################################################
#
# 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

    if [ $LOG_VERBOSITY -gt 1 ]; then
        timestamp="$(date +'%b %_d %T') "
        echo "${timestamp}$@" >> $STARTUP_LOG
    fi
}

progress_message2() # $* = Message
{
    local timestamp
    timestamp=

    if [ $VERBOSITY -gt 0 ]; then
        [ -n "$g_timestamp" ] && timestamp="$(date +%H:%M:%S) "
        echo "${timestamp}$@"
    fi

    if [ $LOG_VERBOSITY -gt 0 ]; then
        timestamp="$(date +'%b %_d %T') "
        echo "${timestamp}$@" >> $STARTUP_LOG
    fi
}

progress_message3() # $* = Message
{
    local timestamp
    timestamp=

    if [ $VERBOSITY -ge 0 ]; then
        [ -n "$g_timestamp" ] && timestamp="$(date +%H:%M:%S) "
        echo "${timestamp}$@"
    fi

    if [ $LOG_VERBOSITY -ge 0 ]; then
        timestamp="$(date +'%b %_d %T') "
        echo "${timestamp}$@" >> $STARTUP_LOG
    fi
}

#
# Set a standard chain's policy
#
setpolicy() # $1 = name of chain, $2 = policy
{
    run_iptables -P $1 $2
}

#
# Generate a list of all network interfaces on the system
#
find_all_interfaces() {
    ${IP:-ip} link list | egrep '^[[:digit:]]+:' | cut -d ' ' -f2 | sed -r 
's/(@.*)?:$//'
}

#
# Generate a list of all network interfaces on the system that have an ipvX 
address
#
find_all_interfaces1() {
    ${IP:-ip} -$g_family addr list | egrep '^[[:digit:]]+:' | cut -d ' ' -f2 | 
sed -r 's/(@.*)?:$//'
}

#
# 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
}

#
# Try to find the gateway through an interface looking for 'nexthop'

find_nexthop() # $1 = interface
{
    echo $(find_gateway `$IP -$g_family route list | grep "[[:space:]]nexthop.* 
$1"`)
}

#
# Find the default route's interface
#
find_default_interface() {
    $IP -$g_family route list | while read first rest; do
        [ "$first" = default ] && echo $(find_device $rest) && return
    done
}

#
# Determine if Interface is up
#
interface_is_up() {
    [ -n "$($IP -$g_family link list dev $1 2> /dev/null | grep -e 
'[<,]UP[,>]')" ]
}

#
#  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
    local mask

    [ $g_family -eq 4 ] && mask=32 || mask=128

    $IP -$g_family 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)
                    ;;
                [2-3]*)
                    [ "$address" = "${address%/*}" ] && 
address="${address}/${mask}"
                    echo $address
                    ;;
                *)
                    if [ $g_family -eq 4 ]; then
                        [ "$address" = "${address%/*}" ] && 
address="${address}/${mask}"
                        echo $address
                    fi
                    ;;
            esac
        done
}

#
# Clear the current traffic shaping configuration
#

delete_tc1()
{
    clear_one_tc() {
        $TC qdisc del dev ${1%@*} root 2> /dev/null
        $TC qdisc del dev ${1%@*} ingress 2> /dev/null

    }

    run_tcclear_exit

    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 <mtu+>' otherwise, where <mtu+> 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() {
    local undofiles
    local f

    if [ -z "$g_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
        #
        undofiles="$(ls ${VARDIR}/undo_*routing 2> /dev/null)"

        if [ -n "$undofiles" ]; then
            for f in $undofiles; do
                . $f
            done

            rm -f $undofiles

            progress_message "Shorewall-generated routing tables and routing 
rules removed"
        fi
    fi

}

#
# Save the default route
#
save_default_route() {
    awk \
    'BEGIN        {defroute=0;};
     /^default /  {defroute=1; print; next};
     /nexthop/    {if (defroute == 1 ) {print ; next} };
                  { defroute=0; };'
}

#
# Restore the default route that was in place before the initial 'shorewall 
start'
#
replace_default_route() # $1 = USE_DEFAULT_RT
{
    #
    # default_route and result are inherited from the caller
    #
    if [ -n "$default_route" ]; then
        case "$default_route" in
            *metric*)
                #
                # Don't restore a default route with a metric unless 
USE_DEFAULT_RT=Yes. Otherwise, we only replace the one with metric 0
                #
                [ -n "$1" ] && qt $IP -$g_family route replace $default_route 
&& progress_message "Default Route (${default_route# }) restored"
                default_route=
                ;;
            *)
                qt $IP -$g_family route replace $default_route && 
progress_message "Default Route (${default_route# }) restored"
                result=0
                default_route=
                ;;
        esac
    fi
}

#
# Delete default routes with metric 0 from the passed routing table
#
delete_default_routes() # $1 = table number
{
    $IP -$g_family route ls table $1 | grep -F default | grep -vF metric | 
while read route; do
        qt $IP -$g_family route del $route
    done
} 

restore_default_route() # $1 = USE_DEFAULT_RT
{
    local result
    result=1

    if [ -z "$g_noroutes" -a -f ${VARDIR}/default_route ]; then
        local default_route
        default_route=
        local route

        while read route ; do
            case $route in
                default*)
                    replace_default_route $1
                    default_route="$default_route $route"
                    ;;
                *)
                    default_route="$default_route $route"
                    ;;
            esac
        done < ${VARDIR}/default_route

        replace_default_route $1

        if [ $result = 1 ]; then
            #
            # We didn't restore a default route with metric 0
            #
            if $IP -$g_family -o route list 2> /dev/null | grep -F default | 
grep -qvF metric; then
               #
               # But we added a default route with metric 0
               #
               qt $IP -$g_family route del default metric 0 && progress_message 
"Default route with metric 0 deleted"
            fi
        fi

        rm -f ${VARDIR}/default_route
    fi

    return $result
}

#
# Flush the conntrack table if $g_purge is non-empty
#
conditionally_flush_conntrack() {

    if [ -n "$g_purge" ]; then
        if [ -n $(mywhich conntrack) ]; then
            conntrack -F
        else
            error_message "WARNING: The '-p' option requires the conntrack 
utility which does not appear to be installed on this system"
        fi
    fi
}

#
# Issue a message and stop/restore the firewall.
#
fatal_error()
{
    echo "   ERROR: $@" >&2

    if [ $LOG_VERBOSITY -ge 0 ]; then
        timestamp="$(date +'%_b %d %T') "
        echo "${timestamp}  ERROR: $@" >> $STARTUP_LOG
    fi

    stop_firewall
    [ -n "$TEMPFILE" ] && rm -f $TEMPFILE
    mutex_off
    exit 2
}

#
# Run iptables/ip6tables and if an error occurs, stop/restore the firewall
#
run_iptables()
{
    local status

    while [ 1 ]; do
        eval $g_tool $@
        status=$?
        [ $status -ne 4 ] && break
    done

    if [ $status -ne 0 ]; then
        error_message "ERROR: Command \"$g_tool $@\" Failed"
        stop_firewall
        exit 2
    fi
}

#
# Run iptables/ip6tables retrying exit status 4
#
do_iptables()
{
    local status

    while [ 1 ]; do
        $g_tool $@
        status=$?
        [ $status -ne 4 ] && return $status;
    done
}

#
# Run ip and if an error occurs, stop/restore the firewall
#
run_ip()
{
    if ! $IP -$g_family $@; then
        error_message "ERROR: Command \"$IP -$g_family $@\" Failed"
        stop_firewall
        exit 2
    fi
}

#
# Run tc and if an error occurs, stop/restore the firewall
#
run_tc() {
    if ! $TC $@ ; then
        error_message "ERROR: Command \"$TC $@\" Failed"
        stop_firewall
        exit 2
    fi
}

#
# Run the .iptables_restore_input as a set of discrete iptables commands
#
debug_restore_input() {
    local first second rest table chain
    #
    # Clear the ruleset
    #
    qt1 $g_tool -t mangle -F
    qt1 $g_tool -t mangle -X

    for chain in PREROUTING INPUT FORWARD POSTROUTING; do
        qt1 $g_tool -t mangle -P $chain ACCEPT
    done

    qt1 $g_tool -t raw    -F
    qt1 $g_tool -t raw    -X

    for chain in PREROUTING OUTPUT; do
        qt1 $g_tool -t raw -P $chain ACCEPT
    done

    qt1 $g_tool -t rawpost -F
    qt1 $g_tool -t rawpost    -X

    for chain in POSTROUTING; do
        qt1 $g_tool -t rawpost -P $chain ACCEPT
    done

    qt1 $g_tool -t nat    -F
    qt1 $g_tool -t nat    -X

    for chain in PREROUTING POSTROUTING; do
        qt1 $g_tool -t nat -P $chain ACCEPT
    done

    qt1 $g_tool -t filter -F
    qt1 $g_tool -t filter -X

    for chain in INPUT FORWARD OUTPUT; do
        qt1 $g_tool -t filter -P $chain -P ACCEPT
    done

    while read first second rest; do
        case $first in
            -*)
                #
                # We can't call run_iptables() here because the rules may 
contain quoted strings
                #
                eval $g_tool -t $table $first $second $rest

                if [ $? -ne 0 ]; then
                    error_message "ERROR: Command \"$g_tool -t $table $first 
$second $rest\" Failed"
                    stop_firewall
                    exit 2
                fi
                ;;
            :*)
                chain=${first#:}

                if [ "x$second" = x- ]; then
                    do_iptables -t $table -N $chain
                else
                    do_iptables -t $table -P $chain $second
                fi

                if [ $? -ne 0 ]; then
                    error_message "ERROR: Command \"$g_tool $first $second 
$rest\" Failed"
                    stop_firewall
                    exit 2
                fi
                ;;
            #
            # This grotesque hack with the table names works around a 
bug/feature with ash
            #
            '*'raw)
                table=raw
                ;;
            '*'rawpost)
                table=rawpost
                ;;
            '*'mangle)
                table=mangle
                ;;
            '*'nat)
                table=nat
                ;;
            '*'filter)
                table=filter
                ;;
        esac
    done
}

interface_enabled() {
    return $(cat ${VARDIR}/$1.status)
}

distribute_load() {
    local interface
    local currentload
    local load
    local mark
    local totalload
    local temp

    totalload=$1
    shift

    currentload=0

    for interface in $@; do
        if interface_enabled $interface; then
            load=$(cat ${VARDIR}/${interface}_load)
            eval ${interface}_load=$load
            mark=$(cat ${VARDIR}/${interface}_mark)
            eval ${interface}_mark=$mark
            currentload=$( bc <<EOF
scale=8
$currentload + $load
EOF
)
        fi
    done

    if [ $currentload ]; then
        for interface in $@; do
            qt $g_tool -t mangle -F ~$interface

            if interface_enabled $interface; then
                eval load=\$${interface}_load
                eval mark=\$${interface}_mark

                if [ -n "$load" ]; then
                    temp=$load
                    load=$(bc <<EOF
scale=8
( $load / $currentload ) * $totalload
EOF
)
                    currentload=$(bc <<EOF
scale=8
$currentload - $temp
EOF
)

                    case $load in
                        .*|0.*)
                            run_iptables -t mangle -A ~$interface -m statistic 
--mode random --probability $load -j MARK --set-mark $mark
                            ;;
                        *)
                            run_iptables -t mangle -A ~$interface -j MARK 
--set-mark $mark
                            ;;
                    esac
                fi
            fi
        done
    fi
}

?if __IPV4
#################################################################################
#                        IPv4-specific Functions
#################################################################################
#
# Determine if interface is usable from a Netfilter perspective
#
interface_is_usable() # $1 = interface
{
    local status;
    status=0

    if ! loopback_interface $1; then
        if interface_is_up $1 && [ "$(find_first_interface_address_if_any $1)" 
!= 0.0.0.0 ]; then
            [ "$COMMAND" = enable ] || run_isusable_exit $1
            status=$?
        else
            status=1
        fi
    fi

    return $status
}

#
# 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.*//'
}

#
# 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 network
        #
        # 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
    local file

    gateway=$(run_findgw_exit $1);

    if [ -z "$gateway" ]; then
        gateway=$( find_peer $($IP addr list $interface ) )
    fi

    file="${VARLIB}/dhcpcd/dhcpcd-${1}.info"
    if [ -z "$gateway" -a -f "${file}" ]; then
        eval $(grep ^GATEWAYS= "${file}" 2> /dev/null)
        [ -n "$GATEWAYS" ] && GATEWAYS=${GATEWAYS%,*} && gateway=$GATEWAYS
    fi

    for file in \
        "${VARLIB}/dhcp/dhclient-${1}.lease" \
        "${VARLIB}/dhcp/dhclient.${1}.leases"
    do
        [ -n "$gateway" ] && break
        if [ -f "${file}" ]; then
            gateway=$(grep 'option routers' "${file}" | tail -n 1 | while read 
j1 j2 gateway; do echo "${gateway%\;}" ; return 0; done)
        fi
    done

    [ -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 temp
    temp="$($IP -f inet6 addr list 2> /dev/null)"

    if [ -n "$temp" ]; then
        if [ -x "$IP6TABLES" ]; then
            $IP6TABLES -P FORWARD DROP
            $IP6TABLES -P INPUT DROP
            $IP6TABLES -P OUTPUT DROP
            $IP6TABLES -F
            $IP6TABLES -X

            for temp in $(find_loopback_interfaces); do
                $IP6TABLES -A OUTPUT -o $temp -j ACCEPT
                $IP6TABLES -A INPUT  -i $temp -j ACCEPT
            done
        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 | grep -qF ' nexthop '; then
            if echo $route | grep -qF via; then
                route=`echo $route | sed 's/via/nexthop via/'`
            else
                route="nexthop $route"
            fi

            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 | grep -qF ' 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
#################################################################################
#                        IPv6-specific Functions
#################################################################################
#
# Determine if interface is usable from a Netfilter perspective
#
interface_is_usable() # $1 = interface
{
    local status;
    status=0

    if [ "$1" != lo ]; then
        if interface_is_up $1 && [ "$(find_first_interface_address_if_any $1)" 
!= :: ]; then
            [ "$COMMAND" = enable ] || run_isusable_exit $1
            status=$?
        else
            status=1
        fi
    fi

    return $status
}

#
# Find interface addresses--returns the set of addresses assigned to the passed 
device
#
find_interface_addresses() # $1 = interface
{
    $IP -f inet6 addr show $1 2> /dev/null | grep 'inet6 2' | sed 's/\s*inet6 
//;s/\/.*//;s/ peer.*//'
}

#
# 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
}

#
# 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 # IPv6-specific functions.

Attachment: signature.asc
Description: OpenPGP digital signature

------------------------------------------------------------------------------
_______________________________________________
Shorewall-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/shorewall-devel

Reply via email to