# (c) 1999-2019 - Tom Eastep (teastep@shorewall.net) # # This program is part of Shorewall. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by the # Free Software Foundation, either version 2 of the license or, at your # option, any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # 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/reload # -V Set verbosity level explicitly # -R 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 enable an optional # interface # refresh Refresh the firewall # reload Reload the firewall # restart Restart 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.runtime ################################################################################ # 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 %e %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 %e %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 %e %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 ' 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() { 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 or =Exact. 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 table $1 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 %e %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 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 ;; '*'mangle) table=mangle ;; '*'nat) table=nat ;; '*'filter) table=filter ;; esac done } interface_enabled() { status=0 if [ -f ${VARDIR}/${1}_disabled ]; then status=1 elif [ -f ${VARDIR}/${1}.status ]; then status=$(cat ${VARDIR}/${1}.status) fi return $status } distribute_load() { local provider local interface local currentload # Total load of enabled providers local load # Specified load of an enabled provider local mark # Mark of an enabled provider local totalload # Total load of all providers - usually 1.000000 local nload # Normalized load of an enabled provider totalload=$1 shift currentload=0 for provider in $@; do interface=$(cat ${VARDIR}/${provider}_interface) eval ${provider}_interface=$interface if interface_enabled $interface; then load=$(cat ${VARDIR}/${provider}_load) eval ${provider}_load=$load mark=$(cat ${VARDIR}/${provider}_mark) eval ${provider}_mark=$mark currentload=$( bc < /dev/null | fgrep 'state DOWN')" ]; then if [ "$COMMAND" != enable ]; then [ ! -f ${VARDIR}/${1}_disabled ] && run_isusable_exit $1 status=$? fi 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 2>/dev/null ) ) 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 if [ -z "$gateway" -a -n "$(mywhich nmcli)" ]; then if [ $g_family = 4 ]; then gateway=$(nmcli --fields DHCP4.OPTION,IP4.GATEWAY device show ${1} 2> /dev/null | sed -rn '/( routers = |IP4.GATEWAY:.*[1-9])/{s/.* //;p;q}') else gateway=$(nmcli --terse --fields IP6.GATEWAY device show ${1} 2> /dev/null | cut -f2- -d':') fi fi [ -n "$gateway" ] && echo $gateway } # # Detect the gateway through an interface # detect_gateway() # $1 = interface $2 = table number { 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 2>/dev/null | grep ^default)) [ -z "$gateway" -a -n "$2" ] && gateway=$(find_gateway $($IP -4 route list dev $interface table $2 2>/dev/null | 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/linkdown//g; 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/linkdown//g; s/[\]//g'` gateway=$1 if [ -n "$route" ]; then if echo $route | grep -qF ' nexthop '; then if interface_is_up $3; then gateway="nexthop $gateway" else gateway="nexthop $gateway dead" fi if eval echo $route \| fgrep -q \'$gateway\'; then eval route=\`echo $route \| sed \'s/$gateway/ /\'\` run_ip route replace table $2 $route fi 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 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 daemon.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 if [ "$COMMAND" != enable ]; then [ ! -f ${VARDIR}/${1}_disabled ] && run_isusable_exit $1 status=$? fi 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 [0-9a-f:]*//' } # # 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 [0-9a-f:]*//' } # # 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 2>/dev/null ) ) # # Maybe there's a default route through this gateway already # [ -n "$gateway" ] || gateway=$(find_gateway $($IP -6 route list dev $interface 2>/dev/null | 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 run_clear_exit set_state "Cleared" logger -p daemon.info "$g_product Cleared" } ?endif # IPv6-specific functions.