Subject: Re: misc/33793: network stop & start breaks IPv6
To: None <tech-net@NetBSD.org>
From: David Young <dyoung@pobox.com>
List: tech-net
Date: 06/22/2006 11:57:13
On Thu, Jun 22, 2006 at 04:05:42PM +0000, Thomas E. Spanjaard wrote:
> As can be read in the PR, IPv6 breaks after an /etc/rc.d/network stop & 
> start. Now, first I though it was because the stop routine only deletes 
> inet addresses, and not inet6 before flushing routes. However, further 
> inspection of the rc.d script show it only deletes addresses that are 
> configured as ifaliases_$int in either /etc/rc.conf or /etc/ifaliases. 
> Now, I don't use either of them, I use /etc/ifconfig.$int files, both 
> for IPv4 and IPv6. So if I read things right, IPv4 addresses aren't 
> deleted prior to route flushing either, which brings me to the question, 
> why does IPv4 work after a stop & start, and IPv6 doesn't?

Here are a few ways to understand the problem.

The problem is that, after stop/start, the IPv6 stack starts dropping on
the floor any packets addressed to an interface's link-local address,
because the flags on the link-local address's routing table entry are
wrong (RTF_CLONED is present).

The problem is that '/etc/rc.d/network stop' removes the link-local
addresses (fe80::/16) from the interfaces, but 'network start' does not
add them back.

The problem is that a link-local host routing entry created by cloning
fe80::/16%sip0 (say) cannot "sink" packets; the KAME stack drops packets
matching the route entry in ip6_input:

        /*
         * Accept the packet if the forwarding interface to the destination
         * according to the routing table is the loopback interface,
         * unless the associated route has a gateway.
         * Note that this approach causes to accept a packet if there is a
         * route to the loopback interface for the destination of the packet.
         * But we think it's even useful in some situations, e.g. when using
         * a special daemon which wants to intercept the packet.
         */     
        if (ip6_forward_rt.ro_rt &&
            (ip6_forward_rt.ro_rt->rt_flags &
             (RTF_HOST|RTF_GATEWAY)) == RTF_HOST &&
            !(ip6_forward_rt.ro_rt->rt_flags & RTF_CLONED) &&
/* #if 0 sources abridged -dyoung */
            ip6_forward_rt.ro_rt->rt_ifp->if_type == IFT_LOOP) {

The problem is that the kernel does not add back an interface's link-local
IPv6 address, if it is missing, on a !IFF_UP->IFF_UP transition.
I believe that by addressing this last problem, the bug will be fixed.

Dave

-- 
David Young             OJC Technologies
dyoung@ojctech.com      Urbana, IL * (217) 278-3933