Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 26 Jun 2009 17:00:06 +0900 (JST)
From:      Hiroki Sato <hrs@FreeBSD.org>
To:        net@FreeBSD.org
Cc:        ume@FreeBSD.org, hrs@FreeBSD.org, bz@FreeBSD.org, jinmei@isc.org, rwatson@FreeBSD.org
Subject:   RFC: convert net.inet6.ip6.{accept_rtadv,auto_linklocal} to per-interface flags
Message-ID:  <20090626.170006.244306978.hrs@allbsd.org>

next in thread | raw e-mail | index | archive | help
----Security_Multipart0(Fri_Jun_26_17_00_06_2009_834)--
Content-Type: Multipart/Mixed;
	boundary="--Next_Part(Fri_Jun_26_17_00_06_2009_451)--"
Content-Transfer-Encoding: 7bit

----Next_Part(Fri_Jun_26_17_00_06_2009_451)--
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Hi all,

 I want to convert net.inet6.ip6.{accept_rtadv,auto_linklocal} to
 per-interface flags to nuke rc.d/auto_linklocal.  The motivations and
 changes are as follow.  If you are using IPv6 and/or familiar with
 the IPv6 implementation, please let me know your comments.

 The ip6.autolinklocal had been enabled but disabled since 6.2R by
 default because automatic configuration of L3 address is insecure.
 However, it makes IPv6 configuration complex because of no link-local
 address on an interface.  Malformed address configuration can be
 happened easily on a system with $ipv6_enable="NO". for example.  In
 addition, the rc.conf knob does not mean the IPv6 functionality is
 completely disabled.  Using an interface for IPv4-only is difficult.

 So, I want to add the following changes:

 1. Use per-interface ND6 flag "ifdisabled" as a flag for if it is
    IPv6-enabled or not.  Set it by default.

 2. Automatic link-local address configuration is performed when the
    ifdisabled flag is clear, not at attach time of the interface.
    This is implemented as a per-interface flag "auto_linklocal".

 3. Accepting Router Advertisement message is also controlled by
    per-interface flag "accept_rtadv".

 4. ip6.auto_linklocal and ip6.accept_rtadv sysctls are for default
    values of the per-interface flags, not global ones that can
    override them.

 User-visible changes are:

 * for IPv4-only people

   None.  IPv6 is disabled by default and no IPv6 packet will be sent
   even if an AF_INET6 address is configured on a network interface.

 * for IPv6-only people

   $ipv6_enable knob is removed.  To enable IPv6, add interfaces to
   $ipv6_network_interfaces.  The variable is set "none" by default.

   To configure IPv6 interface manually, doing "ifconfig fxp0 inet6
   -ifdisabled" is needed.  $ipv6_network_interfaces will do it
   automatically.

   The net.inet6.ip6.accept_rtadv and net.inet6.ip6.auto_linklocal are
   no longer global flags to control the functionality.

 * for people using both IPv4 and IPv6 on the same system:

   IPv6 can be disabled by "ifdisabled" flag.  Accept of Router
   Advertisement message can be disabled by "accept_rtadv" flag.

 The patch for the latest current is attached.  Thanks.

-- Hiroki

----Next_Part(Fri_Jun_26_17_00_06_2009_451)--
Content-Type: Text/X-Patch; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="ipv6_20090626.diff"

Index: sys/netinet6/in6_ifattach.c
===================================================================
--- sys/netinet6/in6_ifattach.c	(revision 195002)
+++ sys/netinet6/in6_ifattach.c	(working copy)
@@ -68,7 +68,6 @@

 #ifdef VIMAGE_GLOBALS
 unsigned long in6_maxmtu;
-int ip6_auto_linklocal;
 struct callout in6_tmpaddrtimer_ch;
 extern struct inpcbinfo ripcbinfo;
 #endif
@@ -751,16 +750,21 @@
 	}

 	/*
-	 * assign a link-local address, if there's none.
+	 * assign a link-local address, if there's none,
+	 * the interface has !ND6_IFF_IFDISABLED && ND6_IFF_AUTO_LINKLOCAL.
 	 */
-	if (V_ip6_auto_linklocal && ifp->if_type != IFT_BRIDGE) {
+	if (ifp->if_type != IFT_BRIDGE
+	    && !(ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED)
+	    && ND_IFINFO(ifp)->flags & ND6_IFF_AUTO_LINKLOCAL) {
+		int error;
+
 		ia = in6ifa_ifpforlinklocal(ifp, 0);
 		if (ia == NULL) {
-			if (in6_ifattach_linklocal(ifp, altifp) == 0) {
-				/* linklocal address assigned */
-			} else {
-				/* failed to assign linklocal address. bark? */
-			}
+			error = in6_ifattach_linklocal(ifp, altifp);
+			if (error)
+				log(LOG_NOTICE, "in6_ifattach_linklocal: "
+				    "failed to add a link-local addr to %s\n",
+				    if_name(ifp));
 		} else
 			ifa_free(&ia->ia_ifa);
 	}
Index: sys/netinet6/ip6_var.h
===================================================================
--- sys/netinet6/ip6_var.h	(revision 195002)
+++ sys/netinet6/ip6_var.h	(working copy)
@@ -306,7 +306,7 @@
 extern int	ip6_sendredirects;	/* send IP redirects when forwarding? */
 extern int	ip6_maxfragpackets; /* Maximum packets in reassembly queue */
 extern int	ip6_maxfrags;	/* Maximum fragments in reassembly queue */
-extern int	ip6_accept_rtadv;	/* Acts as a host not a router */
+extern int	ip6_accept_rtadv;	/* default of ND6_IFF_ACCEPT_RTADV */
 extern int	ip6_keepfaith;		/* Firewall Aided Internet Translator */
 extern int	ip6_log_interval;
 extern time_t	ip6_log_time;
Index: sys/netinet6/in6_proto.c
===================================================================
--- sys/netinet6/in6_proto.c	(revision 195002)
+++ sys/netinet6/in6_proto.c	(working copy)
@@ -387,6 +387,7 @@
 int	ip6_defhlim;
 int	ip6_defmcasthlim;
 int	ip6_accept_rtadv;
+int	ip6_auto_linklocal;
 int	ip6_maxfragpackets;
 int	ip6_maxfrags;
 int	ip6_log_interval;
@@ -503,7 +504,9 @@
 SYSCTL_V_INT(V_NET, vnet_inet6, _net_inet6_ip6, IPV6CTL_MAXFRAGPACKETS,
 	maxfragpackets, CTLFLAG_RW,	ip6_maxfragpackets,	0, "");
 SYSCTL_V_INT(V_NET, vnet_inet6, _net_inet6_ip6, IPV6CTL_ACCEPT_RTADV,
-	accept_rtadv, CTLFLAG_RW,	ip6_accept_rtadv,	0, "");
+	accept_rtadv, CTLFLAG_RW, ip6_accept_rtadv, 0,
+	"default value of per-interface flag for accepting ICMPv6 Router"
+	"Advertisement message");
 SYSCTL_V_INT(V_NET, vnet_inet6, _net_inet6_ip6, IPV6CTL_KEEPFAITH,
 	keepfaith, CTLFLAG_RW,		ip6_keepfaith,	0, "");
 SYSCTL_V_INT(V_NET, vnet_inet6, _net_inet6_ip6, IPV6CTL_LOG_INTERVAL,
@@ -533,7 +536,9 @@
 SYSCTL_V_INT(V_NET, vnet_inet6, _net_inet6_ip6, IPV6CTL_V6ONLY,
 	v6only,	CTLFLAG_RW,	ip6_v6only,			0, "");
 SYSCTL_V_INT(V_NET, vnet_inet6, _net_inet6_ip6, IPV6CTL_AUTO_LINKLOCAL,
-	auto_linklocal, CTLFLAG_RW, ip6_auto_linklocal,	0, "");
+	auto_linklocal, CTLFLAG_RW, ip6_auto_linklocal,	0,
+	"default value of per-interface flag for adding an IPv6 link-local"
+	" address to interfaces automatically when attached");
 SYSCTL_V_STRUCT(V_NET, vnet_inet6, _net_inet6_ip6, IPV6CTL_RIP6STATS,
 	rip6stats, CTLFLAG_RD, rip6stat, rip6stat, "");
 SYSCTL_V_INT(V_NET, vnet_inet6, _net_inet6_ip6, IPV6CTL_PREFER_TEMPADDR,
Index: sys/netinet6/nd6.c
===================================================================
--- sys/netinet6/nd6.c	(revision 195002)
+++ sys/netinet6/nd6.c	(working copy)
@@ -68,9 +68,9 @@
 #include <netinet/if_ether.h>
 #include <netinet6/in6_var.h>
 #include <netinet/ip6.h>
-#include <netinet6/ip6_var.h>
 #include <netinet6/scope6_var.h>
 #include <netinet6/nd6.h>
+#include <netinet6/in6_ifattach.h>
 #include <netinet/icmp6.h>
 #include <netinet6/vinet6.h>

@@ -214,13 +214,16 @@
 	nd->basereachable = REACHABLE_TIME;
 	nd->reachable = ND_COMPUTE_RTIME(nd->basereachable);
 	nd->retrans = RETRANS_TIMER;
-	/*
-	 * Note that the default value of ip6_accept_rtadv is 0, which means
-	 * we won't accept RAs by default even if we set ND6_IFF_ACCEPT_RTADV
-	 * here.
-	 */
-	nd->flags = (ND6_IFF_PERFORMNUD | ND6_IFF_ACCEPT_RTADV);

+	nd->flags = ND6_IFF_PERFORMNUD;
+	if (V_ip6_auto_linklocal)
+		nd->flags |= ND6_IFF_AUTO_LINKLOCAL;
+	if (V_ip6_accept_rtadv)
+		nd->flags |= ND6_IFF_ACCEPT_RTADV;
+	/* disable NDP on interfaces other than loopback by default */
+	if (!(ifp->if_flags & IFF_LOOPBACK))
+		nd->flags |= ND6_IFF_IFDISABLED;
+
 	/* XXX: we cannot call nd6_setmtu since ifp is not fully initialized */
 	nd6_setmtu0(ifp, nd);

@@ -850,11 +853,9 @@
 	if (V_nd6_defifindex == ifp->if_index)
 		nd6_setdefaultiface(0);

-	if (!V_ip6_forwarding && V_ip6_accept_rtadv) { /* XXX: too restrictive? */
-		/* refresh default router list
-		 *
-		 *
-		 */
+	if (V_ip6_forwarding == 0
+	    && ND_IFINFO(ifp)->flags & ND6_IFF_ACCEPT_RTADV) {
+		/* refresh default router list */
 		defrouter_select();

 	}
@@ -1307,7 +1308,60 @@
 			ND_IFINFO(ifp)->chlim = ND.chlim;
 		/* FALLTHROUGH */
 	case SIOCSIFINFO_FLAGS:
-		ND_IFINFO(ifp)->flags = ND.flags;
+	{
+		struct ifaddr *ifa;
+		struct in6_ifaddr *ia;
+		if ((ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED)
+		    && !(ND.flags & ND6_IFF_IFDISABLED)) {
+			/* ifdisabled 1->0 transision */
+
+			/*
+			 * If the interface is marked as ND6_IFF_IFDISABLED and
+			 * has an link-local address with IN6_IFF_DUPLICATED,
+			 * do not clear ND6_IFF_IFDISABLED.
+			 * See RFC 4862, Section 5.4.5.
+			 */
+			int duplicated_linklocal = 0;
+
+			IF_ADDR_LOCK(ifp);
+			TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
+				if (ifa->ifa_addr->sa_family != AF_INET6)
+					continue;
+				ia = (struct in6_ifaddr *)ifa;
+				if ((ia->ia6_flags & IN6_IFF_DUPLICATED)
+				    && IN6_IS_ADDR_LINKLOCAL(&ia->ia_addr.sin6_addr)) {
+					duplicated_linklocal = 0;
+					break;
+				}
+			}
+			IF_ADDR_UNLOCK(ifp);
+
+			if (duplicated_linklocal) {
+				ND_IFINFO(ifp)->flags = ND.flags & ~ND6_IFF_IFDISABLED;
+				log(LOG_ERR, "cannot enable an interface"
+				    " with an link-local address marked"
+				    " duplicated.\n");
+			} else {
+				ND_IFINFO(ifp)->flags = ND.flags;
+				in6_if_up(ifp);
+			}
+		} else if (!(ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED)
+		    && (ND.flags & ND6_IFF_IFDISABLED)) {
+			/* ifdisabled 0->1 transision */
+			/* mark all IPv6 address as tentative */
+
+			ND_IFINFO(ifp)->flags = ND.flags;
+			IF_ADDR_LOCK(ifp);
+			TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
+				if (ifa->ifa_addr->sa_family != AF_INET6)
+					continue;
+				ia = (struct in6_ifaddr *)ifa;
+				ia->ia6_flags |= IN6_IFF_TENTATIVE;
+			}
+			IF_ADDR_UNLOCK(ifp);
+		} else
+			ND_IFINFO(ifp)->flags = ND.flags;
+	}
 		break;
 #undef ND
 	case SIOCSNDFLUSH_IN6:	/* XXX: the ioctl name is confusing... */
@@ -1645,7 +1699,10 @@
 	 * for those are not autoconfigured hosts, we explicitly avoid such
 	 * cases for safety.
 	 */
-	if (do_update && router && !V_ip6_forwarding && V_ip6_accept_rtadv) {
+	if (do_update
+	    && router
+	    && V_ip6_forwarding == 0
+	    && ND_IFINFO(ifp)->flags & ND6_IFF_ACCEPT_RTADV) {
 		/*
 		 * guaranteed recursion
 		 */
Index: sys/netinet6/nd6_nbr.c
===================================================================
--- sys/netinet6/nd6_nbr.c	(revision 195002)
+++ sys/netinet6/nd6_nbr.c	(working copy)
@@ -1204,6 +1204,9 @@
 	if (!(ifa->ifa_ifp->if_flags & IFF_UP)) {
 		return;
 	}
+	if (ND_IFINFO(ifa->ifa_ifp)->flags & ND6_IFF_IFDISABLED) {
+		return;
+	}
 	if (nd6_dad_find(ifa) != NULL) {
 		/* DAD already in progress */
 		return;
@@ -1411,7 +1414,7 @@
 	 * identifier based on the hardware address which is supposed to be
 	 * uniquely assigned (e.g., EUI-64 for an Ethernet interface), IP
 	 * operation on the interface SHOULD be disabled.
-	 * [rfc2462bis-03 Section 5.4.5]
+	 * [RFC 4862, Section 5.4.5]
 	 */
 	if (IN6_IS_ADDR_LINKLOCAL(&ia->ia_addr.sin6_addr)) {
 		struct in6_addr in6;
Index: sys/netinet6/in6.c
===================================================================
--- sys/netinet6/in6.c	(revision 195002)
+++ sys/netinet6/in6.c	(working copy)
@@ -921,6 +921,10 @@
 	if (hostIsNew && in6if_do_dad(ifp))
 		ia->ia6_flags |= IN6_IFF_TENTATIVE;

+	/* DAD should be performed after ND6_IFF_IFDISABLED is cleared */
+	if (ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED)
+		ia->ia6_flags |= IN6_IFF_TENTATIVE;
+
 	/*
 	 * We are done if we have simply modified an existing address.
 	 */
@@ -958,7 +962,7 @@
 			 * being configured.  It also means delaying
 			 * transmission of the corresponding MLD report to
 			 * avoid report collision.
-			 * [draft-ietf-ipv6-rfc2462bis-02.txt]
+			 * [RFC 4861, Section 6.3.7]
 			 */
 			delay = arc4random() %
 			    (MAX_RTR_SOLICITATION_DELAY * hz);
@@ -1106,9 +1110,9 @@
 	 * XXX It may be of use, if we can administratively
 	 * disable DAD.
 	 */
-	if (in6if_do_dad(ifp) && ((ifra->ifra_flags & IN6_IFF_NODAD) == 0) &&
-	    (ia->ia6_flags & IN6_IFF_TENTATIVE))
-	{
+	if (in6if_do_dad(ifp)
+	    && ((ifra->ifra_flags & IN6_IFF_NODAD) == 0)
+	    && (ia->ia6_flags & IN6_IFF_TENTATIVE)) {
 		int mindelay, maxdelay;

 		delay = 0;
@@ -2158,6 +2162,9 @@
 	if ((ifp->if_flags & IFF_LOOPBACK) != 0)
 		return (0);

+	if (ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED)
+		return (0);
+
 	switch (ifp->if_type) {
 #ifdef IFT_DUMMY
 	case IFT_DUMMY:
Index: sys/netinet6/nd6.h
===================================================================
--- sys/netinet6/nd6.h	(revision 195002)
+++ sys/netinet6/nd6.h	(working copy)
@@ -84,6 +84,7 @@
 				     * DAD failure.  (XXX: not ND-specific)
 				     */
 #define ND6_IFF_DONT_SET_IFROUTE	0x10
+#define ND6_IFF_AUTO_LINKLOCAL	0x20

 #define	ND6_CREATE		LLE_CREATE
 #define	ND6_EXCLUSIVE		LLE_EXCLUSIVE
Index: sys/netinet6/ip6_input.c
===================================================================
--- sys/netinet6/ip6_input.c	(revision 195002)
+++ sys/netinet6/ip6_input.c	(working copy)
@@ -218,7 +218,7 @@
 	V_ip6_sendredirects = IPV6_SENDREDIRECTS;
 	V_ip6_defhlim = IPV6_DEFHLIM;
 	V_ip6_defmcasthlim = IPV6_DEFAULT_MULTICAST_HOPS;
-	V_ip6_accept_rtadv = 0;	 /* "IPV6FORWARDING ? 0 : 1" is dangerous */
+	V_ip6_accept_rtadv = 1;
 	V_ip6_log_interval = 5;
 	V_ip6_hdrnestlimit = 15; /* How many header options will we process? */
 	V_ip6_dad_count = 1;	 /* DupAddrDetectionTransmits */
Index: sys/netinet6/nd6_rtr.c
===================================================================
--- sys/netinet6/nd6_rtr.c	(revision 195002)
+++ sys/netinet6/nd6_rtr.c	(working copy)
@@ -129,7 +129,8 @@
 	char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN];

 	/* If I'm not a router, ignore it. */
-	if (V_ip6_accept_rtadv != 0 || V_ip6_forwarding != 1)
+	if (V_ip6_forwarding
+	    || !(ND_IFINFO(ifp)->flags & ND6_IFF_ACCEPT_RTADV))
 		goto freeit;

 	/* Sanity checks */
@@ -216,13 +217,12 @@

 	/*
 	 * We only accept RAs only when
-	 * the system-wide variable allows the acceptance, and
+	 * the node is not a router and
 	 * per-interface variable allows RAs on the receiving interface.
 	 */
-	if (V_ip6_accept_rtadv == 0)
+	if (V_ip6_forwarding
+	    || !(ndi->flags & ND6_IFF_ACCEPT_RTADV))
 		goto freeit;
-	if (!(ndi->flags & ND6_IFF_ACCEPT_RTADV))
-		goto freeit;

 	if (ip6->ip6_hlim != 255) {
 		nd6log((LOG_ERR,
@@ -564,7 +564,7 @@
 	 * Flush all the routing table entries that use the router
 	 * as a next hop.
 	 */
-	if (!V_ip6_forwarding && V_ip6_accept_rtadv) /* XXX: better condition? */
+	if (V_ip6_forwarding == 0)
 		rt6_flush(&dr->rtaddr, dr->ifp);

 	if (dr->installed) {
@@ -629,10 +629,10 @@
 	 * if the node is not an autoconfigured host, we explicitly exclude
 	 * such cases here for safety.
 	 */
-	if (V_ip6_forwarding || !V_ip6_accept_rtadv) {
+	if (V_ip6_forwarding) {
 		nd6log((LOG_WARNING,
-		    "defrouter_select: called unexpectedly (forwarding=%d, "
-		    "accept_rtadv=%d)\n", V_ip6_forwarding, V_ip6_accept_rtadv));
+		    "defrouter_select: called unexpectedly (forwarding=%d)\n",
+		    V_ip6_forwarding));
 		splx(s);
 		return;
 	}
Index: sbin/ifconfig/ifconfig.8
===================================================================
--- sbin/ifconfig/ifconfig.8	(revision 195002)
+++ sbin/ifconfig/ifconfig.8	(working copy)
@@ -28,7 +28,7 @@
 .\"     From: @(#)ifconfig.8	8.3 (Berkeley) 1/5/94
 .\" $FreeBSD$
 .\"
-.Dd June 24, 2009
+.Dd June 25, 2009
 .Dt IFCONFIG 8
 .Os
 .Sh NAME
@@ -598,6 +598,48 @@
 the hardware will be re-initialized.
 .El
 .Pp
+The following parameters are for ICMPv6 Neightbor Discovery Protocol:
+.Bl -tag -width indent
+.It Cm accept_rtadv
+Set a flag to enable accepting ICMPv6 Router Advertisement messages.
+.It Cm -accept_rtadv
+Clear a flag
+.Cm accept_rtadv .
+.It Cm auto_linklocal
+Set a flag to perform automatic link-local address configuration when
+the interface becomes avalilable.
+.It Cm -auto_linklocal
+Clear a flag
+.Cm auto_linklocal .
+.It Cm defaultif
+Set the specified interface as the default route when there is no
+default router.
+.It Cm -defaultif
+Clear a flag
+.Cm defaultif .
+.It Cm ifdisabled
+Set a flag to disable all of IPv6 network communications on the
+specified interface.
+.It Cm -ifdisabled
+Clear a flag
+.Cm ifdisabled .
+When this flag is cleared and
+.Cm auto_linklocal
+flag is enabled, automatic configuration of a link-local address is
+performed.
+.It Cm nud
+Set a flag to enable Neighbor Unreachability Detection.
+.It Cm -nud
+Clear a flag
+.Cm nud .
+.It Cm prefer_source
+Set a flag to prefer addesses on the interface as candidates of the
+source address for outgoing packets.
+.It Cm -prefer_source
+Clear a flag
+.Cm prefer_source .
+.El
+.Pp
 The following parameters are specific to cloning
 IEEE 802.11 wireless interfaces with the
 .Cm create
@@ -2112,6 +2154,24 @@
 Another name for the
 .Fl tunnel
 parameter.
+.It Cm accept_rev_ethip_ver
+Set a flag to acccept both correct EtherIP packets and ones
+with reversed version field.  Enabled by default.
+This is for backward compatibility with
+.Fx 6.1 ,
+6.2, 6.3, 7.0, and 7.1.
+.It Cm -accept_rev_ethip_ver
+Clear a flag
+.Cm accept_rev_ethip_ver .
+.It Cm send_rev_ethip_ver
+Set a flag to send EtherIP packets with reversed version
+field intentionally.  Disabled by default.
+This is for backward compatibility with
+.Fx 6.1 ,
+6.2, 6.3, 7.0, and 7.1.
+.It Cm -send_rev_ethip_ver
+Clear a flag
+.Cm send_rev_ethip_ver .
 .El
 .Pp
 The following parameters are specific to GRE tunnel interfaces,
@@ -2336,6 +2396,9 @@
 .Li ed0 :
 .Dl # ifconfig ed0 inet 192.0.2.45 -alias
 .Pp
+Enable IPv6 functionality of the interface:
+.Dl # ifconfig em0 inet6 -ifdisabled
+.Pp
 Add the IPv6 address
 .Li 2001:DB8:DBDB::123/48
 to the interface
@@ -2372,6 +2435,8 @@
 .Sh SEE ALSO
 .Xr netstat 1 ,
 .Xr carp 4 ,
+.Xr gif 4 ,
+.Xr gre 4 ,
 .Xr netintro 4 ,
 .Xr pfsync 4 ,
 .Xr polling 4 ,
@@ -2390,12 +2455,13 @@
 Basic IPv6 node operation requires a link-local address on each
 interface configured for IPv6.
 Normally, such an address is automatically configured by the
-kernel on each interface added to the system; this behaviour may
-be disabled by setting the sysctl MIB variable
-.Va net.inet6.ip6.auto_linklocal
-to 0.
+kernel on each interface added to the system or enabled; this behavior may
+be disabled by setting per-interface flag
+.Cm auto_linklocal .
+The default value of this flag is 1 and can be disabled by using the sysctl
+MIB variable
+.Va net.inet6.ip6.auto_linklocal .
 .Pp
-If you delete such an address using
-.Nm ,
-the kernel may act very odd.
-Do this at your own risk.
+Do not configure IPv6 addresses with no link-local address by using
+.Nm .
+It can result in unexpected behaviors of the kernel.
Index: sbin/ifconfig/af_inet6.c
===================================================================
--- sbin/ifconfig/af_inet6.c	(revision 195002)
+++ sbin/ifconfig/af_inet6.c	(working copy)
@@ -67,6 +67,9 @@
 static	char *sec2str(time_t);
 static	int explicit_prefix = 0;

+extern void setnd6flags(const char *, int, int, const struct afswtch *);
+extern void setnd6defif(const char *, int, int, const struct afswtch *);
+
 static	char addr_buf[MAXHOSTNAMELEN *2 + 1];	/*for getnameinfo()*/

 static void
@@ -493,6 +496,18 @@
 	DEF_CMD("-deprecated", -IN6_IFF_DEPRECATED,	setip6flags),
 	DEF_CMD("autoconf",	IN6_IFF_AUTOCONF,	setip6flags),
 	DEF_CMD("-autoconf",	-IN6_IFF_AUTOCONF,	setip6flags),
+	DEF_CMD("accept_rtadv",	ND6_IFF_ACCEPT_RTADV,	setnd6flags),
+	DEF_CMD("-accept_rtadv",-ND6_IFF_ACCEPT_RTADV,	setnd6flags),
+	DEF_CMD("defaultif",	1,			setnd6defif),
+	DEF_CMD("-defaultif",	-1,			setnd6defif),
+	DEF_CMD("ifdisabled",	ND6_IFF_IFDISABLED,	setnd6flags),
+	DEF_CMD("-ifdisabled",	-ND6_IFF_IFDISABLED,	setnd6flags),
+	DEF_CMD("nud",		ND6_IFF_PERFORMNUD,	setnd6flags),
+	DEF_CMD("-nud",		-ND6_IFF_PERFORMNUD,	setnd6flags),
+	DEF_CMD("prefer_source",ND6_IFF_PREFER_SOURCE,	setnd6flags),
+	DEF_CMD("-prefer_source",-ND6_IFF_PREFER_SOURCE,setnd6flags),
+	DEF_CMD("auto_linklocal",ND6_IFF_AUTO_LINKLOCAL,setnd6flags),
+	DEF_CMD("-auto_linklocal",-ND6_IFF_AUTO_LINKLOCAL,setnd6flags),
 	DEF_CMD_ARG("pltime",        			setip6pltime),
 	DEF_CMD_ARG("vltime",        			setip6vltime),
 	DEF_CMD("eui64",	0,			setip6eui64),
Index: sbin/ifconfig/Makefile
===================================================================
--- sbin/ifconfig/Makefile	(revision 195002)
+++ sbin/ifconfig/Makefile	(working copy)
@@ -18,6 +18,7 @@
 SRCS+=	af_inet.c		# IPv4 support
 SRCS+=	af_inet6.c		# IPv6 support
 SRCS+=	af_atalk.c		# AppleTalk support
+SRCS+=	af_nd6.c		# ND6 support

 SRCS+=	ifclone.c		# clone device support
 SRCS+=	ifmac.c			# MAC support
Index: sbin/ifconfig/af_nd6.c
===================================================================
--- sbin/ifconfig/af_nd6.c	(revision 0)
+++ sbin/ifconfig/af_nd6.c	(revision 0)
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 2009 Hiroki Sato.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static const char rcsid[] =
+  "$FreeBSD$";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+#include <net/if.h>
+#include <net/route.h>
+
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <ifaddrs.h>
+
+#include <arpa/inet.h>
+
+#include <netinet/in.h>
+#include <net/if_var.h>
+#include <netinet/in_var.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#include <netinet6/nd6.h>
+
+#include "ifconfig.h"
+
+#define MAX_SYSCTL_TRY	5
+
+static struct nd6_opt_list {
+	const char *label;
+	u_int mask;
+} nd6_opts[]  = {
+	{ "IFDISABLED",		ND6_IFF_IFDISABLED, },
+	{ "PERFORMNUD",		ND6_IFF_PERFORMNUD, },
+	{ "ACCEPT_RTADV",	ND6_IFF_ACCEPT_RTADV,	},
+	{ "PREFER_SOURCE",	ND6_IFF_PREFER_SOURCE,	},
+	{ "AUTO_LINKLOCAL",	ND6_IFF_AUTO_LINKLOCAL,	},
+};
+
+static int isnd6defif(int);
+void setnd6flags(const char *, int, int, const struct afswtch *);
+void setnd6defif(const char *, int, int, const struct afswtch *);
+
+void
+setnd6flags(const char *dummyaddr __unused,
+	int d, int s,
+	const struct afswtch *afp)
+{
+	struct in6_ndireq nd;
+	int error;
+
+	memset(&nd, 0, sizeof(nd));
+	strncpy(nd.ifname, ifr.ifr_name, sizeof(nd.ifname));
+
+	error = ioctl(s, SIOCGIFINFO_IN6, &nd);
+	if (error) {
+		warn("ioctl(SIOCGIFINFO_IN6)");
+		return;
+	}
+
+	if (d < 0)
+		nd.ndi.flags &= ~(-d);
+	else
+		nd.ndi.flags |= d;
+
+	error = ioctl(s, SIOCSIFINFO_IN6, (caddr_t)&nd);
+	if (error)
+		warn("ioctl(SIOCSIFINFO_IN6)");
+}
+
+void
+setnd6defif(const char *dummyaddr __unused,
+	int d, int s,
+	const struct afswtch *afp)
+{
+	struct in6_ndifreq ndifreq;
+	int ifindex;
+	int error;
+
+	memset(&ndifreq, 0, sizeof(ndifreq));
+	strncpy(ndifreq.ifname, ifr.ifr_name, sizeof(ndifreq.ifname));
+
+	if (d < 0) {
+		if (isnd6defif(s))
+			/* ifindex = 0 means to remove default if */
+			ifindex = 0;
+		else
+			return;
+	} else if ((ifindex = if_nametoindex(ndifreq.ifname)) == 0) {
+		warn("if_nametoindex(%s)", ndifreq.ifname);
+		return;
+	}
+
+	ndifreq.ifindex = ifindex;
+	error = ioctl(s, SIOCSDEFIFACE_IN6, (caddr_t)&ndifreq);
+	if (error)
+		warn("ioctl(SIOCSDEFIFACE_IN6)");
+}
+
+static int
+isnd6defif(int s)
+{
+	struct in6_ndifreq ndifreq;
+	unsigned int ifindex;
+	int error;
+
+	memset(&ndifreq, 0, sizeof(ndifreq));
+	strncpy(ndifreq.ifname, ifr.ifr_name, sizeof(ndifreq.ifname));
+	ifindex = if_nametoindex(ndifreq.ifname);
+
+	error = ioctl(s, SIOCGDEFIFACE_IN6, (caddr_t)&ndifreq);
+	if (error) {
+		warn("ioctl(SIOCGDEFIFACE_IN6)");
+		return (error);
+	}
+	return (ndifreq.ifindex == ifindex);
+}
+
+static void
+nd6_status(int s)
+{
+	struct in6_ndireq nd;
+	struct rt_msghdr *rtm;
+	size_t needed;
+	char *buf, *next;
+	int mib[6], ntry;
+	int s6;
+	int i, error;
+	int isinet6, isdefif;
+	int nopts = 0;
+
+	/* check if the interface has at least one IPv6 address */
+	mib[0] = CTL_NET;
+	mib[1] = PF_ROUTE;
+	mib[2] = 0;
+	mib[3] = AF_INET6;
+	mib[4] = NET_RT_IFLIST;
+	mib[5] = if_nametoindex(ifr.ifr_name);
+
+	/* try to prevent a race between two sysctls */
+	ntry = 0;
+	do {
+		error = sysctl(mib, 6, NULL, &needed, NULL, 0);
+		if (error) {
+			warn("sysctl(NET_RT_IFLIST)/estimate");
+			return;
+		}
+		buf = malloc(needed);
+		if (buf == NULL) {
+			warn("malloc for sysctl(NET_RT_IFLIST) failed");
+			return;
+		}
+		if ((error = sysctl(mib, 6, buf, &needed, NULL, 0)) < 0) {
+			if (errno != ENOMEM || ++ntry >= MAX_SYSCTL_TRY) {
+				warn("sysctl(NET_RT_IFLIST)/get");
+				free(buf);
+				return;
+			}
+			free(buf);
+			buf = NULL;
+		}
+	} while (buf == NULL);
+
+	isinet6 = 0;
+	for (next = buf; next < buf + needed; next += rtm->rtm_msglen) {
+		rtm = (struct rt_msghdr *)next;
+
+		if (rtm->rtm_version != RTM_VERSION)
+			continue;
+		if (rtm->rtm_type == RTM_NEWADDR) {
+			isinet6 = 1;
+			break;
+		}
+	}
+	free(buf);
+	if (isinet6 == 0)
+		return;
+
+	memset(&nd, 0, sizeof(nd));
+	strncpy(nd.ifname, ifr.ifr_name, sizeof(nd.ifname));
+	if ((s6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
+		warn("socket(AF_INET6, SOCK_DGRAM)");
+		return;
+	}
+	error = ioctl(s6, SIOCGIFINFO_IN6, &nd);
+	if (error) {
+		warn("ioctl(SIOCGIFINFO_IN6)");
+		close(s6);
+		return;
+	}
+	isdefif = isnd6defif(s6);
+	close(s6);
+
+	printf("\tnd6 options=%d<", nd.ndi.flags);
+	for (i=0; i < sizeof(nd6_opts)/sizeof(nd6_opts[0]); i++) {
+		if (nd.ndi.flags & nd6_opts[i].mask) {
+			if (nopts++)
+				printf(",");
+			printf("%s", nd6_opts[i].label);
+		}
+	}
+	if (isdefif) {
+		if (nopts++)
+			printf(",");
+		printf("DEFAULTIF");
+	}
+	printf(">\n");
+}
+
+static struct afswtch af_nd6 = {
+	.af_name	= "nd6",
+	.af_af		= AF_LOCAL,
+	.af_other_status= nd6_status,
+};
+
+static __constructor void
+nd6_ctor(void)
+{
+	af_register(&af_nd6);
+}
Index: usr.sbin/ndp/ndp.c
===================================================================
--- usr.sbin/ndp/ndp.c	(revision 195002)
+++ usr.sbin/ndp/ndp.c	(working copy)
@@ -1004,6 +1004,9 @@
 #ifdef ND6_IFF_ACCEPT_RTADV
 		SETFLAG("accept_rtadv", ND6_IFF_ACCEPT_RTADV);
 #endif
+#ifdef ND6_IFF_AUTO_LINKLOCAL
+		SETFLAG("auto_linklocal", ND6_IFF_AUTO_LINKLOCAL);
+#endif
 #ifdef ND6_IFF_PREFER_SOURCE
 		SETFLAG("prefer_source", ND6_IFF_PREFER_SOURCE);
 #endif
@@ -1076,6 +1079,10 @@
 		if ((ND.flags & ND6_IFF_ACCEPT_RTADV))
 			printf("accept_rtadv ");
 #endif
+#ifdef ND6_IFF_AUTO_LINKLOCAL
+		if ((ND.flags & ND6_IFF_AUTO_LINKLOCAL))
+			printf("auto_linklocal ");
+#endif
 #ifdef ND6_IFF_PREFER_SOURCE
 		if ((ND.flags & ND6_IFF_PREFER_SOURCE))
 			printf("prefer_source ");
Index: usr.sbin/ndp/ndp.8
===================================================================
--- usr.sbin/ndp/ndp.8	(revision 195002)
+++ usr.sbin/ndp/ndp.8	(working copy)
@@ -29,7 +29,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd May 17, 1998
+.Dd Jun 19, 2009
 .Dt NDP 8
 .Os
 .\"
@@ -182,11 +182,16 @@
 Specify whether or not to accept Router Advertisement messages
 received on the
 .Ar interface .
-Note that the kernel does not accept Router Advertisement messages
-unless the
-.Li net.inet6.ip6.accept_rtadv
-variable is non-0, even if the flag is on.
-This flag is set to 1 by default.
+This flag is set by
+.Va net.inet6.ip6.accept_rtadv
+sysctl variable.
+.It Ic auto_linklocal
+Specify whether or not to perform automatic link-local address configuration
+on
+.Ar interface .
+This flag is set by
+.Va net.inet6.ip6.auto_linklocal
+sysctl variable.
 .It Ic prefer_source
 Prefer addresses on the
 .Ar interface
@@ -204,9 +209,8 @@
 application.
 This flag is typically set automatically in the kernel as a result of
 a certain failure of Duplicate Address Detection.
-While the flag can be set or cleared by hand with the
-.Nm
-command, it is not generally advisable to modify this flag manually.
+If the auto_linklocal per-interface flag is set, automatic link-local
+address configuration is performed again when this flag is cleared.
 .It Ic basereachable Ns Li = Ns Pq Ar number
 Specify the BaseReachbleTimer on the interface in millisecond.
 .It Ic retrans Ns Li = Ns Pq Ar number
@@ -253,6 +257,10 @@
 The
 .Nm
 utility first appeared in the WIDE Hydrangea IPv6 protocol stack kit.
+The
+.Fl I Ar auto_linklocal
+flag first appeared in
+.Fx 8.0 .
 .\"
 .\" .Sh BUGS
 .\" (to be written)
Index: usr.sbin/rtsold/if.c
===================================================================
--- usr.sbin/rtsold/if.c	(revision 195002)
+++ usr.sbin/rtsold/if.c	(working copy)
@@ -48,6 +48,7 @@
 #include <netinet/icmp6.h>

 #include <netinet6/in6_var.h>
+#include <netinet6/nd6.h>

 #include <stdio.h>
 #include <unistd.h>
@@ -78,9 +79,15 @@
 interface_up(char *name)
 {
 	struct ifreq ifr;
+	struct in6_ndireq nd;
 	int llflag;
+	int s;
+	int error;

+	memset(&ifr, 0, sizeof(ifr));
 	strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+	memset(&nd, 0, sizeof(nd));
+	strlcpy(nd.ifname, name, sizeof(nd.ifname));

 	if (ioctl(ifsock, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) {
 		warnmsg(LOG_WARNING, __func__, "ioctl(SIOCGIFFLAGS): %s",
@@ -94,9 +101,54 @@
 			    "ioctl(SIOCSIFFLAGS): %s", strerror(errno));
 		return(-1);
 	}
+	if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
+		warnmsg(LOG_WARNING, __func__, "socket(AF_INET6, SOCK_DGRAM): %s",
+		    strerror(errno));
+		return(-1);
+	}
+	if (ioctl(s, SIOCGIFINFO_IN6, (caddr_t)&nd) < 0) {
+		warnmsg(LOG_WARNING, __func__, "ioctl(SIOCGIFINFO_IN6): %s",
+		    strerror(errno));
+		close(s);
+		return(-1);
+	}

 	warnmsg(LOG_DEBUG, __func__, "checking if %s is ready...", name);

+	if (nd.ndi.flags & ND6_IFF_IFDISABLED) {
+		if (Fflag) {
+			nd.ndi.flags &= ~ND6_IFF_IFDISABLED;
+			if (ioctl(s, SIOCSIFINFO_IN6, (caddr_t)&nd)) {
+				warnmsg(LOG_WARNING, __func__, "ioctl(SIOCSIFINFO_IN6): %s",
+		    		    strerror(errno));
+				close(s);
+				return(-1);
+			}
+		} else {
+			warnmsg(LOG_WARNING, __func__,
+			    "%s is disabled.", name);
+			close(s);
+			return(-1);
+		}
+	}
+	if (!(nd.ndi.flags & ND6_IFF_ACCEPT_RTADV)) {
+		if (Fflag) {
+			nd.ndi.flags |= ND6_IFF_ACCEPT_RTADV;
+			if (ioctl(s, SIOCSIFINFO_IN6, (caddr_t)&nd)) {
+				warnmsg(LOG_WARNING, __func__, "ioctl(SIOCSIFINFO_IN6): %s",
+		    		    strerror(errno));
+				close(s);
+				return(-1);
+			}
+		} else {
+			warnmsg(LOG_WARNING, __func__,
+			    "%s does not accept Router Advertisement.", name);
+			close(s);
+			return(-1);
+		}
+	}
+	close(s);
+
 	llflag = get_llflag(name);
 	if (llflag < 0) {
 		warnmsg(LOG_WARNING, __func__,
Index: usr.sbin/rtsold/rtsold.c
===================================================================
--- usr.sbin/rtsold/rtsold.c	(revision 195002)
+++ usr.sbin/rtsold/rtsold.c	(working copy)
@@ -62,8 +62,8 @@
 struct timeval tm_max =	{0x7fffffff, 0x7fffffff};
 static int log_upto = 999;
 static int fflag = 0;
-static int Fflag = 0;	/* force setting sysctl parameters */

+int Fflag = 0;	/* force setting sysctl parameters */
 int aflag = 0;
 int dflag = 0;

@@ -197,12 +197,8 @@
 #endif

 	if (Fflag) {
-		setinet6sysctl(IPV6CTL_ACCEPT_RTADV, 1);
 		setinet6sysctl(IPV6CTL_FORWARDING, 0);
 	} else {
-		/* warn if accept_rtadv is down */
-		if (!getinet6sysctl(IPV6CTL_ACCEPT_RTADV))
-			warnx("kernel is configured not to accept RAs");
 		/* warn if forwarding is up */
 		if (getinet6sysctl(IPV6CTL_FORWARDING))
 			warnx("kernel is configured as a router, not a host");
Index: usr.sbin/rtsold/rtsold.8
===================================================================
--- usr.sbin/rtsold/rtsold.8	(revision 195002)
+++ usr.sbin/rtsold/rtsold.8	(working copy)
@@ -186,7 +186,9 @@
 warning messages will be generated,
 but Router Solicitations will still be sent.
 The settings may be changed manually with
-.Xr sysctl 8 .
+.Xr sysctl 8
+and
+.Xr ifconfig 8 .
 .It Fl m
 Enable mobility support.
 If this option is specified,
Index: usr.sbin/rtsold/rtsold.h
===================================================================
--- usr.sbin/rtsold/rtsold.h	(revision 195002)
+++ usr.sbin/rtsold/rtsold.h	(working copy)
@@ -67,6 +67,7 @@
 extern struct timeval tm_max;
 extern int dflag;
 extern int aflag;
+extern int Fflag;
 extern char *otherconf_script;
 extern int ifconfig(char *);
 extern void iflist_init(void);
Index: share/man/man4/inet6.4
===================================================================
--- share/man/man4/inet6.4	(revision 195002)
+++ share/man/man4/inet6.4	(working copy)
@@ -29,7 +29,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd January 29, 1999
+.Dd June 19, 2009
 .Dt INET6 4
 .Os
 .Sh NAME
@@ -307,14 +307,20 @@
 The flag is provided basically for avoiding possible DoS attacks.
 .It Dv IPV6CTL_ACCEPT_RTADV
 .Pq ip6.accept_rtadv
-Boolean: enable/disable receiving of
+Boolean: the default value of a per-interface flag to
+enable/disable receiving of
 .Tn ICMPv6
 router advertisement packets,
 and autoconfiguration of address prefixes and default routers.
 The node must be a host
 (not a router)
 for the option to be meaningful.
-Defaults to off.
+Defaults to on.
+.It Dv IPV6CTL_AUTO_LINKLOCAL
+.Pq ip6.auto_linklocal
+Boolean: the default value of a per-interface flag to
+enable/disable performing automatic link-local address configuration.
+Defaults to on.
 .It Dv IPV6CTL_KEEPFAITH
 .Pq ip6.keepfaith
 Boolean: enable/disable
Index: etc/network.subr
===================================================================
--- etc/network.subr	(revision 195044)
+++ etc/network.subr	(working copy)
@@ -820,72 +820,82 @@
 network6_interface_setup()
 {
 	interfaces=$*
-	rtsol_interfaces=''
-	case ${ipv6_gateway_enable} in
-	[Yy][Ee][Ss])
-		rtsol_available=no
-		;;
-	*)
-		rtsol_available=yes
-		;;
-	esac
+	_f_rtadv=""
+
+	if checkyesno ipv6_gateway_enable ]; then
+		_f_rtadv="-accept_rtadv"
+	fi
+
 	for i in $interfaces; do
-		rtsol_interface=yes
+		# enable ND6
+		ifconfig $i inet6 -ifdisabled ${_f_rtadv}
+
+		# add an address based on ipv6_prefix_IF + hostid
+		# if the ipv6_prefix_IF is defined.
 		prefix=`get_if_var $i ipv6_prefix_IF`
 		if [ -n "${prefix}" ]; then
-			rtsol_available=no
-			rtsol_interface=no
 			laddr=`network6_getladdr $i`
 			hostid=`expr "${laddr}" : 'fe80::\(.*\)%\(.*\)'`
 			for j in ${prefix}; do
 				address=$j\:${hostid}
 				ifconfig $i inet6 ${address} prefixlen 64 alias

-				case ${ipv6_gateway_enable} in
-				[Yy][Ee][Ss])
-					# subnet-router anycast address
-					# (rfc2373)
+				# if I am a router, add subnet router
+				# anycast address (RFC 2373).
+				if checkyesno ipv6_gateway_enable; then
 					ifconfig $i inet6 $j:: prefixlen 64 \
 						alias anycast
-					;;
-				esac
+				fi
 			done
 		fi
+
+		# manual configuration if ipv6_ifconfig_IF is defined.
 		ipv6_ifconfig=`get_if_var $i ipv6_ifconfig_IF`
 		if [ -n "${ipv6_ifconfig}" ]; then
-			rtsol_available=no
-			rtsol_interface=no
 			ifconfig $i inet6 ${ipv6_ifconfig} alias
 		fi
+	done

-		if [ ${rtsol_available} = yes -a ${rtsol_interface} = yes ]
-		then
-			case ${i} in
-			lo0|gif[0-9]*|stf[0-9]*|faith[0-9]*|lp[0-9]*|sl[0-9]*|tun[0-9]*|pflog[0-9]*|pfsync[0-9]*)
-				;;
-			# Wireless NIC cards are virtualized through the wlan interface
-			an[0-9]*|ath[0-9]*|ipw[0-9]*|iwi[0-9]*|iwn[0-9]*|ral[0-9]*|wi[0-9]*|wl[0-9]*|wpi[0-9]*)
-				;;
+	# invoke rtsol if ipv6_rtsol_interfaces is defined.
+	if ! checkyesno ipv6_gateway_enable \
+	   && [ -n "${ipv6_rtsol_interfaces}" ]; then
+		# Act as endhost - automatically configured.
+		for IF in ${ipv6_rtsol_interfaces}
+		do
+			case ${IF} in
+			[Nn][Oo][Nn][Ee])
+				break
+			;;
+			lo0|\
+			gif[0-9]*|\
+			stf[0-9]*|\
+			faith[0-9]*|\
+			lp[0-9]*|\
+			sl[0-9]*|\
+			tun[0-9]*|\
+			pflog[0-9]*|\
+			pfsync[0-9]*|\
+			an[0-9]*|\
+			ath[0-9]*|\
+			ipw[0-9]*|\
+			iwi[0-9]*|\
+			iwn[0-9]*|\
+			ral[0-9]*|\
+			wi[0-9]*|\
+			wl[0-9]*|\
+			wpi[0-9]*)
+				# Wireless NIC cards are virtualized through the wlan interface
+				# do nothing
+			;;
 			*)
-				rtsol_interfaces="${rtsol_interfaces} ${i}"
-				;;
+				ifconfig ${IF} inet6 accept_rtadv up
+				rtsol ${rtsol_flags} ${IF}
+			;;
 			esac
-		else
-			ifconfig $i inet6
-		fi
-	done
-
-	if [ ${rtsol_available} = yes -a -n "${rtsol_interfaces}" ]; then
-		# Act as endhost - automatically configured.
-		# You can configure only single interface, as
-		# specification assumes that autoconfigured host has
-		# single interface only.
-		sysctl net.inet6.ip6.accept_rtadv=1
-		set ${rtsol_interfaces}
-		ifconfig $1 up
-		rtsol ${rtsol_flags} $1
+		done
 	fi

+	# add aliases if ipv6_ifconfig_IF_alias is defined.
 	for i in $interfaces; do
 		alias=0
 		while : ; do
@@ -1041,17 +1051,23 @@

 		# Disable installing the default interface with the
 		# case net.inet6.ip6.forwarding=0 and
-		# net.inet6.ip6.accept_rtadv=0, due to avoid conflict
-		# between the default router list and the manual
-		# configured default route.
+		# the interface with no ND6_IFF_ACCEPT_RTADV
+		# to avoid conflict between the default router list and
+		# the manual configured default route.
 		case ${ipv6_gateway_enable} in
 		[Yy][Ee][Ss])
 			;;
 		*)
-			if [ `sysctl -n net.inet6.ip6.accept_rtadv` -eq 1 ]
-			then
-				ndp -I ${ipv6_default_interface}
-			fi
+			ifconfig ${ipv6_default_interface} nd6 | \
+			while read proto options
+			do
+				case "${proto}:${options}" in
+				nd6:*ACCEPT_RTADV*)
+					ifconfig ${ipv6_default_interface} inet6 defaultif
+					break
+				;;
+				esac
+			done
 			;;
 		esac
 		;;
Index: etc/rc.d/network_ipv6
===================================================================
--- etc/rc.d/network_ipv6	(revision 195044)
+++ etc/rc.d/network_ipv6	(working copy)
@@ -36,7 +36,6 @@
 . /etc/network.subr

 name="network_ipv6"
-rcvar=`set_rcvar ipv6`
 start_cmd="network_ipv6_start"

 network_ipv6_start()
@@ -62,15 +61,14 @@

 		# wait for DAD
 		for i in $ipv6_network_interfaces; do
-			ifconfig $i up
+			ifconfig $i inet6 -ifdisabled up
 		done
 		sleep `${SYSCTL_N} net.inet6.ip6.dad_count`
 		sleep 1
 	else
 		# act as endhost - start with manual configuration
-		# Setup of net.inet6.ip6.accept_rtadv is done later by
-		# network6_interface_setup.
 		${SYSCTL_W} net.inet6.ip6.forwarding=0
+		${SYSCTL_W} net.inet6.ip6.accept_rtadv=1
 	fi

 	if [ -n "${ipv6_network_interfaces}" ]; then
Index: etc/rc.d/ip6addrctl
===================================================================
--- etc/rc.d/ip6addrctl	(revision 195044)
+++ etc/rc.d/ip6addrctl	(working copy)
@@ -52,7 +52,7 @@
 			ip6addrctl install /etc/ip6addrctl.conf
 			checkyesno ip6addrctl_verbose && ip6addrctl
 		else
-			if checkyesno ipv6_enable; then
+			if checkyesno ipv6_prefer; then
 				ip6addrctl_prefer_ipv6
 			else
 				ip6addrctl_prefer_ipv4
Index: etc/rc.d/Makefile
===================================================================
--- etc/rc.d/Makefile	(revision 195044)
+++ etc/rc.d/Makefile	(working copy)
@@ -4,7 +4,7 @@

 FILES=	DAEMON FILESYSTEMS LOGIN NETWORKING SERVERS \
 	abi accounting addswap adjkerntz amd \
-	apm apmd archdep atm1 atm2 atm3 auditd auto_linklocal \
+	apm apmd archdep atm1 atm2 atm3 auditd \
 	bgfsck bluetooth bootparams bridge bsnmpd bthidd \
 	ccd cleanvar cleartmp cron \
 	ddb defaultroute devd devfs dhclient \
Index: etc/rc.d/auto_linklocal
===================================================================
--- etc/rc.d/auto_linklocal	(revision 195044)
+++ etc/rc.d/auto_linklocal	(working copy)
@@ -1,33 +0,0 @@
-#!/bin/sh
-#
-# $FreeBSD$
-#
-
-# PROVIDE: auto_linklocal
-# REQUIRE: root
-# BEFORE:  sysctl
-# KEYWORD: nojail
-
-. /etc/rc.subr
-. /etc/network.subr
-
-name="auto_linklocal"
-start_cmd="auto_linklocal_start"
-stop_cmd=":"
-
-auto_linklocal_start()
-{
-	if ! checkyesno ipv6_enable && ${SYSCTL} net.inet6 > /dev/null 2>&1; then
-		if ! ${SYSCTL_W} net.inet6.ip6.auto_linklocal=0 >/dev/null 2>&1; then
-			warn "failed to set sysctl(8)"
-			return 1
-		fi
-		laddr=`network6_getladdr lo0`
-		if [ -z "${laddr}" ]; then
-			ifconfig lo0 inet6 fe80::1 prefixlen 64
-		fi
-	fi
-}
-
-load_rc_config $name
-run_rc_command "$1"
Index: etc/rc.d/rtadvd
===================================================================
--- etc/rc.d/rtadvd	(revision 195044)
+++ etc/rc.d/rtadvd	(working copy)
@@ -40,10 +40,16 @@
 	# get a list of interfaces and enable it on them
 	#
 	case ${rtadvd_interfaces} in
-	'')
+	[Aa][Uu][Tt][Oo]|'')
 		for i in `ifconfig -l` ; do
 			case $i in
-			lo0|gif[0-9]*|stf[0-9]*|faith[0-9]*|lp[0-9]*|sl[0-9]*|tun[0-9]*)
+			lo0|\
+			gif[0-9]*|\
+			stf[0-9]*|\
+			faith[0-9]*|\
+			lp[0-9]*|\
+			sl[0-9]*|\
+			tun[0-9]*)
 				continue
 				;;
 			*)
Index: etc/defaults/rc.conf
===================================================================
--- etc/defaults/rc.conf	(revision 195044)
+++ etc/defaults/rc.conf	(working copy)
@@ -417,8 +417,11 @@
 icmp_bmcastecho="NO"	# respond to broadcast ping packets

 ### IPv6 options: ###
-ipv6_enable="NO"		# Set to YES to set up for IPv6.
-ipv6_network_interfaces="auto"	# List of network interfaces (or "auto").
+ipv6_network_interfaces="none"	# List of IPv6 network interfaces
+				# (or "auto" or "none").
+ipv6_rtsol_interfaces="none"	# List of IPv6 network interfaces for
+				# sending ICMPv6 Router Solicitation message.
+ipv6_prefer="NO"		# Use IPv6 when both IPv4 and IPv6 can be used
 ipv6_defaultrouter="NO"		# Set to IPv6 default gateway (or NO).
 #ipv6_defaultrouter="2002:c058:6301::"	# Use this for 6to4 (RFC 3068)
 ipv6_static_routes=""		# Set to static route list (or leave empty).

----Next_Part(Fri_Jun_26_17_00_06_2009_451)----

----Security_Multipart0(Fri_Jun_26_17_00_06_2009_834)--
Content-Type: application/pgp-signature
Content-Transfer-Encoding: 7bit

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (FreeBSD)

iEYEABECAAYFAkpEgAYACgkQTyzT2CeTzy3lSQCgiXg8C6IU+0dLNI+sVe9AtUKq
pjwAn25U6TSIOsO2iaqm9Rd4lszUjgnn
=DKI5
-----END PGP SIGNATURE-----

----Security_Multipart0(Fri_Jun_26_17_00_06_2009_834)----



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20090626.170006.244306978.hrs>