Subject: kern/33279: /etc/rc.d/network restart stops delivery of ipv6 packets
To: None <kern-bug-people@netbsd.org, gnats-admin@netbsd.org,>
From: None <dyoung@netbsd.org>
List: netbsd-bugs
Date: 04/18/2006 04:15:00
>Number:         33279
>Category:       kern
>Synopsis:       /etc/rc.d/network restart stops delivery of ipv6 packets
>Confidential:   no
>Severity:       critical
>Priority:       high
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Tue Apr 18 04:15:00 +0000 2006
>Originator:     David Young
>Release:        NetBSD 2.99.10
>Organization:
OJC Technologies
>Environment:
System: NetBSD cuw.ojctech.com 2.99.10 NetBSD 2.99.10 (GENERIC.cuw) #0: Sun Nov 14 15:35:49 CST 2004 dyoung@cuw.ojctech.com:/u3/dyoung/pristine-nbsd/O/sys/arch/i386/compile/GENERIC.cuw i386
Architecture: i386
Machine: i386
>Description:
If I restart networking on a NetBSD host with '/etc/rc.d/network restart',
IPv6 stops working.  The reason is that the host routes corresponding to
the IPv6 addresses assigned to every interface get deleted.  Those routes
have flags UHL before they are deleted.  As the host sends/receives IPv6
packets, it creates "cloned" routes (flags UHLc) for the IPv6 addresses
on its interfaces.  The way that NetBSD's IPv6 stack works is that it
will not locally deliver packets whose destination address resolves to a
cloning route, not even if the route points at the loopback interface,
and not even if the destination address is assigned to some interface.
See src/sys/netinet6/ip6_input.c, revision 1.78, line 497.

It is possible to recover by running 'ifconfig ifN inet6 addr delete'
for each IPv6 address on each interface, and then 'ifconfig ifN inet6
addr' to add them back again.

It seems that the kernel is being too strict, but consider the comments
in KAME's src/sys/netinet6/ip6_input.c,

         * XXX: some OSes automatically make a cloned route for the destination
         * of an outgoing packet.  If the outgoing interface of the packet
         * is a loopback one, the kernel would consider the packet to be
         * accepted, even if we have no such address assinged on the interface.
         * We check the cloned flag of the route entry to reject such cases,
         * assuming that route entries for our own addresses are not made by
         * cloning (it should be true because in6_addloop explicitly installs
         * the host route).  However, we might have to do an explicit check
         * while it would be less efficient.  Or, should we rather install a
         * reject route for such a case?

>How-To-Repeat:
local# /etc/rc.d/network restart
remote# ping6 local	<-- no response

>Fix:
Call in6_ifattach_linklocal on ->IFF_UP transition?