Deleting IPv4 iface-routes from extra FIBs
Alan Somers
asomers at freebsd.org
Mon Oct 13 15:23:58 UTC 2014
On Mon, Oct 13, 2014 at 3:16 AM, Harald Schmalzbauer
<h.schmalzbauer at omnilan.de> wrote:
> Bezüglich Alexander V. Chernikov's Nachricht vom 13.10.2014 10:42
> (localtime):
>> On 13.10.2014 12:35, Harald Schmalzbauer wrote:
>>> Bezüglich Julian Elischer's Nachricht vom 23.04.2014 09:55
>>> (localtime):
> ...
>>>> yes, we made two behaviours.
>>>> Add interface routes to all active FIBS or only add them to the first
>>>> fib and let the user populate other fibs as needed.
>>>> It appears you want the second behaviour, so I suggest you use that
>>>> option and set up all your routes manually.
>>> Hello,
>>>
>>> last time I had the iface-route problem, I just reverted r248895 (for
>>> 9.3). There was inconsitent behaviour with v6 iface routes and
>>> net.add_addr_allfibs=0.
>>> Now I checked with 10.1 ans it seems net.add_addr_allfibs=0 doesn't work
>>> any more:
>>> netstat -f inet -nr
>>> Routing tables
>>>
>>> Internet:
>>> Destination Gateway Flags Netif Expire
>>> default 172.21.32.1 UGS egn
>>> 127.0.0.1 link#2 UH lo0
>>> 172.21.32.0/19 link#1 U egn
>>> 172.21.35.1 link#1 UHS lo0
>>>
>>> netstat -F 1 -f inet -nr
>>> Routing tables (fib: 1)
>>>
>>> Internet:
>>> Destination Gateway Flags Netif Expire
>>> 127.0.0.1 link#2 UH lo0
>>> 172.21.32.0/19 link#1 U egn
>>>
>>> 'sysctl net.add_addr_allfibs'
>>> net.add_addr_allfibs: 0
>> Are you sure net.add_addr_allfibs was applied before interface address
>> added?
>
> Sorry, I messed it up. Forgot that on my production systems (where I
> tested), / is read-only with /etc as union-mount.
> Adding net.add_addr_allfibs=0 to the correct sysctl.conf made the inet
> routing table stay empty.
>
> But unfortunately not the inet6 routing table :-(
> So I still need to delete iface routes for my jail setups, hence need to
> revert r248895.
What do your ipv6 routing tables look like when the sysctl is set
correctly and 248895 is in place?
>
> <Unrelated to the actual problem:
> Strage thing is that 'rcorder' shows nothing iface related before
> mountcritlocal, where I resource /etc/rc.d, so the
> 'net.add_addr_allfibs' in my union-mounted sysctl.conf should work!?!
> But that's my homemade problem ;-) />
>
> For those having similar problems, here's how I currently solve my jail
> setups:
>
> jail.conf:
>
> jail {
> allow.set_hostname;
> ...
> exec.fib = 1;
> exec.prestart = "/bin/sh /.JAIL$name/etc/rc.jails_fibprepare -f
> 1 -i inop";
> interface = inop;
> ...
>
> –––
> rc.jails_fibprepare :
>
> #!/bin/sh
> # format FIB for JAIL usage (remove all but own interface routes)
> # Does only work if on FreeBSD-9.2 if r248895 was reverted, since
> deleting iface routes is prohibited by default.
> # TODO: extend jail (8) and jail.conf for routing parameters and delete
> this ugly hack!
> # TODO: Do it the other way, not deleleting, but adding if "sysctl
> net.add_addr_allfibs=0".
> # Last edited: 20140605.0
>
>
> _help(){
> echo "Usage: rc.jails_fibprepare -f FIBNUM -i IFACENAME [-4
> defaultrouterIPv4] [-6 defaultrouterIPv6] [-h]"
> if [ "X$1" != "X" ]; then
> if [ "$1" = "-h" ]; then
> echo "Prepare routing tabel of specified FIB for jail usage."
> echo "This removes all iface routes not belonging to own interface"
> echo "and sets default route(s) if specified or automatically, if"
> echo "iface used is the same where fib 0 has set the default gateway."
> echo " -f: FIBNUM is the number of the fib whose routing
> table will be altered."
> echo " -i: IFACENAME is the name of the interface we have
> our IP on."
> echo " -4: IP (v4) of the defaultrouter."
> echo " -6: IP (v6) of the defaultrouter."
> echo " -h: This help"
> echo
> else
> echo "ERROR:"
> echo " $1"
> echo
> exit 1
> fi
> else
> echo "Type \"rc.jails_fibprepare -h\" for more help."
> exit 1
> fi
> exit 0
> }
>
> _find_unwanted_destinations(){
> # first, generate complete destination lists (separate for v4+v6)
> dest4list=`setfib ${fibnum} netstat -f inet -nr | grep -E
> '^[[:print:]]+(%[[:alnum:].]+|[[:digit:]])[[:blank:]]+U[[:print:]]+$' |
> cut -s -d ' ' -f 1`
> dest6list=`setfib ${fibnum} netstat -f inet6 -nr | grep -E
> '^[[:print:]]+(%[[:alnum:].]+|[[:digit:]])[[:blank:]]+U[[:print:]]+$' |
> cut -s -d ' ' -f 1`
> # Create lists with wanted destinations (separate for v4+v6)
> for ifn in ${ifnames}; do
> link=`setfib ${fibnum} netstat -I ${ifn} | sed -n -E
> 's/^[[:print:]]+<[lL](ink#[[:digit:]]{1,2})>[[:print:]]+$/l\1/p'`
> dest4wanted="`setfib ${fibnum} netstat -f inet -nr | grep -E
> '^[^[:blank:]]+[[:blank:]]+'"${link}"'[[:blank:]]+.*$' | cut -s -d ' '
> -f 1` ${dest4wanted:-}"
> dest6wanted="`setfib ${fibnum} netstat -f inet6 -nr | grep -E
> '^[^[:blank:]]+[[:blank:]]+'"${link}"'[[:blank:]]+.*$' | cut -s -d ' '
> -f 1` ${dest6wanted:-}"
> done
> # remove wanted destinations from v4 list
> for dest in ${dest4wanted}; do
> dest4list="`echo ${dest4list} | sed -E 's,'"${dest}"' *,,'`"
> done
> # remove wanted destinations from v6 list
> for dest in ${dest6wanted}; do
> dest6list="`echo ${dest6list} | sed -E 's,'"${dest}"' *,,'`"
> done
> }
>
> _clean_fib(){
> _find_unwanted_destinations || return 1
> # extract default gateway IPv4 if it's on one of our interfaces and
> none is set already
> for ifn in ${ifnames}; do
> if [ "X${dv4gw}" = "X" ]; then
> dv4gw="`netstat -f inet -nr | sed -n -E
> 's/^default[[:print:]]+[[:blank:]]([^[:blank:]]+[.:][^[:blank:]]+)[[:print:]]+[^[:blank:]]+[[:blank:]]+'"${ifn}"'$/\1/p'`"
> fi
> done
> # extract default gateway IPv6 if it's on one of our interfaces and
> none is set already
> for ifn in ${ifnames}; do
> if [ "X${dv6gw}" = "X" ]; then
> dv6gw="`netstat -f inet6 -nr | sed -n -E
> 's/^default[[:print:]]+[[:blank:]]([^[:blank:]]+[.:][^[:blank:]]+)[[:print:]]+[^[:blank:]]+[[:blank:]]+'"${ifn}"'$/\1/p'`"
> fi
> done
> # remove v4 destinations
> for dest in ${dest4list}; do
> route -q delete -net -inet ${dest} -fib ${fibnum} || return 1
> done
> # remove v6 destinations
> for dest in ${dest6list}; do
> route -q delete -net -inet6 ${dest} -fib ${fibnum} || return 1
> done
> # Set v4 defaultrouter
> if [ "X${dv4gw}" != "X" ]; then
> route -q add -net -inet default ${dv4gw} -fib ${fibnum} || return 1
> fi
> # Set v6 defaultrouter
> if [ "X${dv6gw}" != "X" ]; then
> route -q add -net -inet6 default ${dv6gw} -fib ${fibnum} || return 1
> fi
> }
>
> if [ $# -gt 8 ]; then
> _help "Too many arguments!"
> else
> if [ $# -lt 4 ]; then
> _help "At least \"-f FIBUM\" and \"-i IFACENAME\" is required!"
> else
> if ! expr $# % 2 >/dev/null; then
> while [ $# -gt 0 ]; do
> case "$1" in
> -f) if ! setfib ${2} true; then
> _help "FIBNUM too high!"
> else
> fibnum=$2
> fi
> ;;
> -i) if ! ifconfig ${2} >/dev/null 2>&1; then
> _help "No such interface: \"$2\""
> else
> ifnames="$2 ${ifnames:-}"
> fi
> ;;
> -4) dv4gw="$2";;
> -6) dv6gw="$2";;
> -h|*) _help "$1"
> esac
> shift 2
> done
> _clean_fib && exit 0
> else
> _help "Wrong number of arguments ($#), only even numbers can be
> valid!"
> fi
> fi
> fi
> exit 1
>
> –––
> r248895-revert patch against 10.1:
>
> --- src/sys/net/if.c 2014-10-06 12:56:27.000000000 +0200
> +++ src/sys/net/if.c 2014-10-13 10:47:51.000000000 +0200
> @@ -1371,8 +1371,7 @@
> return (0);
>
> err = rtrequest_fib(RTM_DELETE, rt_key(rt), rt->rt_gateway,
> - rt_mask(rt),
> - rt->rt_flags|RTF_RNH_LOCKED|RTF_PINNED,
> + rt_mask(rt), rt->rt_flags|RTF_RNH_LOCKED,
> (struct rtentry **) NULL, rt->rt_fibnum);
> if (err) {
> log(LOG_WARNING, "if_rtdel: error %d\n", err);
> --- src/sys/net/route.c 2014-10-06 12:56:27.000000000 +0200
> +++ src/sys/net/route.c 2014-10-13 10:47:51.000000000 +0200
> @@ -1210,14 +1210,6 @@
> error = 0;
> }
> #endif
> - if ((flags & RTF_PINNED) == 0) {
> - /* Check if target route can be deleted */
> - rt = (struct rtentry *)rnh->rnh_lookup(dst,
> - netmask, rnh);
> - if ((rt != NULL) && (rt->rt_flags & RTF_PINNED))
> - senderr(EADDRINUSE);
> - }
> -
> /*
> * Remove the item from the tree and return it.
> * Complain if it is not there and do no more processing.
> @@ -1521,7 +1513,6 @@
> int didwork = 0;
> int a_failure = 0;
> static struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK};
> - struct radix_node_head *rnh;
>
> if (flags & RTF_HOST) {
> dst = ifa->ifa_dstaddr;
> @@ -1580,6 +1571,7 @@
> */
> for ( fibnum = startfib; fibnum <= endfib; fibnum++) {
> if (cmd == RTM_DELETE) {
> + struct radix_node_head *rnh;
> struct radix_node *rn;
> /*
> * Look up an rtentry that is in the routing tree and
> @@ -1626,8 +1618,7 @@
> */
> bzero((caddr_t)&info, sizeof(info));
> info.rti_ifa = ifa;
> - info.rti_flags = flags |
> - (ifa->ifa_flags & ~IFA_RTSELF) | RTF_PINNED;
> + info.rti_flags = flags | (ifa->ifa_flags & ~IFA_RTSELF);
> info.rti_info[RTAX_DST] = dst;
> /*
> * doing this for compatibility reasons
> @@ -1639,33 +1630,6 @@
> info.rti_info[RTAX_GATEWAY] = ifa->ifa_addr;
> info.rti_info[RTAX_NETMASK] = netmask;
> error = rtrequest1_fib(cmd, &info, &rt, fibnum);
> -
> - if ((error == EEXIST) && (cmd == RTM_ADD)) {
> - /*
> - * Interface route addition failed.
> - * Atomically delete current prefix generating
> - * RTM_DELETE message, and retry adding
> - * interface prefix.
> - */
> - rnh = rt_tables_get_rnh(fibnum, dst->sa_family);
> - RADIX_NODE_HEAD_LOCK(rnh);
> -
> - /* Delete old prefix */
> - info.rti_ifa = NULL;
> - info.rti_flags = RTF_RNH_LOCKED;
> -
> - error = rtrequest1_fib(RTM_DELETE, &info, NULL, fibnum);
> - if (error == 0) {
> - info.rti_ifa = ifa;
> - info.rti_flags = flags | RTF_RNH_LOCKED |
> - (ifa->ifa_flags & ~IFA_RTSELF) | RTF_PINNED;
> - error = rtrequest1_fib(cmd, &info, &rt, fibnum);
> - }
> -
> - RADIX_NODE_HEAD_UNLOCK(rnh);
> - }
> -
> -
> if (error == 0 && rt != NULL) {
> /*
> * notify any listening routing agents of the change
> --- src/sys/net/route.h 2014-10-06 12:56:27.000000000 +0200
> +++ src/sys/net/route.h 2014-10-13 10:43:59.000000000 +0200
> @@ -148,7 +148,7 @@
> /* 0x20000 unused, was RTF_WASCLONED */
> #define RTF_PROTO3 0x40000 /* protocol specific routing flag */
> /* 0x80000 unused */
> -#define RTF_PINNED 0x100000 /* route is immutable */
> +#define RTF_PINNED 0x100000 /* future use (route is immutable,
> startintg with r248895) */
> #define RTF_LOCAL 0x200000 /* route represents a local address */
> #define RTF_BROADCAST 0x400000 /* route represents a bcast
> address */
> #define RTF_MULTICAST 0x800000 /* route represents a mcast
> address */
>
>
More information about the freebsd-net
mailing list