Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 28 Jun 2009 09:05:33 +0900 (JST)
From:      Hiroki Sato <hrs@FreeBSD.org>
To:        bms@FreeBSD.org
Cc:        ume@FreeBSD.org, hrs@FreeBSD.org, bz@FreeBSD.org, jinmei@isc.org, rwatson@FreeBSD.org, net@FreeBSD.org
Subject:   Re: RFC: convert net.inet6.ip6.{accept_rtadv,auto_linklocal} to per-interface flags
Message-ID:  <20090628.090533.207531760.hrs@allbsd.org>
In-Reply-To: <4A44F49B.7020403@FreeBSD.org>
References:  <20090626.170006.244306978.hrs@allbsd.org> <4A44F49B.7020403@FreeBSD.org>

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

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

Bruce Simpson <bms@FreeBSD.org> wrote
  in <4A44F49B.7020403@FreeBSD.org>:

bm> Hiroki Sato wrote:
bm> >  The ip6.autolinklocal had been enabled but disabled since 6.2R by
bm> >  default because automatic configuration of L3 address is insecure.
bm> >  However, it makes IPv6 configuration complex because of no link-local
bm> >  address on an interface.  Malformed address configuration can be
bm> >  happened easily on a system with $ipv6_enable="NO". for example.  In
bm> >  addition, the rc.conf knob does not mean the IPv6 functionality is
bm> >  completely disabled.  Using an interface for IPv4-only is difficult.
bm> >
bm>
bm> The MLDv2 code will use the link-local address by default if
bm> available, otherwise if the link is in DAD it will use ::.
bm>
bm> In fact, link-local addresses are needed to make stuff like OSPFv3 and
bm> MLDv2 work properly. So we are in fact shooting ourselves in the foot
bm> over people's paranoia. Link-scope addresses starting 'fe80' don't
bm> belong in traffic beyond one L2 hop. We already have a check for
bm> 169.254.0.0/16 in ip_forward(), ip6_forward() performs a scope check.
bm>
bm> If people have legitimate security concerns about these address
bm> ranges, the place to implement that is at the perimeter, or in other
bm> forwarding policy, not by breaking IPv6 deployment for end-users.
(snip)
bm> Patch looks fine, but I'd fix the style(9) bugs before committing; &&
bm> operators, etc should be before the line break, and initializers in
bm> variable declarations are generally discouraged. Also there should be
bm> whitespace between code and variable declarations.

 Thanks, the revised patch including style(9) fix is attached.

 After I posted the previous patch I notice that setting
 ND6_IFF_IFDISABLED by default and setting ND6_IFF_AUTO_LINKLOCAL by
 rc(8) script do not work fine with userland applications which
 create/destroy cloned interfaces like gif(4) on demand.
 So, the new patch uses the following way:

 1. ND6_IFF_AUTO_LINKLOCAL is 1 by default.  The flag on an interface
    which is not in $ipv6_network_interfaces is dropped by rc(8)
    before "ifconfig up".

 2. ND6_IFF_ACCEPT_RTADV is 0 by default.  If you want to accept RAs,
    specify "ifconfig fxp0 inet6 accept_rtadv" in $ifconfig_IF.  When
    ip6_forwarding=1 accepting RAs is disabled regardless of the flag.

 3. The above default values can be changed by using
    net.inet6.ip6.auto_linklocal and net.inet6.ip6.accept_rtadv.

 4. Loopback interfaces always have ND6_IFF_AUTO_LINKLOCAL and
    !ND6_IFF_ACCEPT_RTADV.

 5. $ipv6_network_interfaces is "none" by default.

 6. If you hate IPv6, you can use "ifconfig fxp0 inet6 ifdisabled"
    that makes IPv6 functionality on that interface completely.

 Although it is still possible that manual configuration of interfaces
 not in $ipv6_network_interfaces results in a malformed address
 configuration with no link-local address, in that case "ifconfig fxp0
 inet6 auto_linklocal" will do the trick.  No up/down cycle is needed
 for ND6_IFF_AUTO_LINKLOCAL unlike net.inet6.ip6.auto_linklocal
 change.

 Also, the patch includes network-related rc(8) scripts update to
 support this change and fix/tidy up various rough edges.  The
 rc.d/network_ipv6 is integrated to rc.d/netif and rc.d/routing now.
 The stf(4) and faith(4) are handled by separated scripts rc.d/stf and
 rc.d/faith.  The rc.d/auto_linklocal is removed.  The rc.d/sysctl is
 moved to the earlier stage.

-- Hiroki

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

Index: sys/netinet6/in6_ifattach.c
===================================================================
--- sys/netinet6/in6_ifattach.c	(revision 195123)
+++ 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 195123)
+++ 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 195123)
+++ 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 195123)
+++ 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,19 @@
 	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;
+
+	/* loopback always has ND6_IFF_AUTO_LINKLOCAL */
+	if (V_ip6_auto_linklocal
+	    || (ifp->if_flags & IFF_LOOPBACK))
+		nd->flags |= ND6_IFF_AUTO_LINKLOCAL;
+
+	/* loopback does not need to accept RTADV */
+	if (V_ip6_accept_rtadv &&
+	    !(ifp->if_flags & IFF_LOOPBACK))
+		nd->flags |= ND6_IFF_ACCEPT_RTADV;
+
 	/* XXX: we cannot call nd6_setmtu since ifp is not fully initialized */
 	nd6_setmtu0(ifp, nd);

@@ -850,11 +856,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 &&
+	    ND_IFINFO(ifp)->flags & ND6_IFF_ACCEPT_RTADV) {
+		/* refresh default router list */
 		defrouter_select();

 	}
@@ -1307,6 +1311,69 @@
 			ND_IFINFO(ifp)->chlim = ND.chlim;
 		/* FALLTHROUGH */
 	case SIOCSIFINFO_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 &= ~ND6_IFF_IFDISABLED;
+				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 |= ND6_IFF_IFDISABLED;
+			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);
+		}
+
+		if (!(ND_IFINFO(ifp)->flags & ND6_IFF_AUTO_LINKLOCAL) ||
+		    (ND.flags & ND6_IFF_AUTO_LINKLOCAL)) {
+			/* auto_linklocal 0->1 transision */
+
+			/* If no link-local address on ifp, configure */
+			ND_IFINFO(ifp)->flags |= ND6_IFF_AUTO_LINKLOCAL;
+			in6_ifattach(ifp, NULL);
+		}
+	}
 		ND_IFINFO(ifp)->flags = ND.flags;
 		break;
 #undef ND
@@ -1645,7 +1712,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 &&
+	    ND_IFINFO(ifp)->flags & ND6_IFF_ACCEPT_RTADV) {
 		/*
 		 * guaranteed recursion
 		 */
Index: sys/netinet6/nd6_nbr.c
===================================================================
--- sys/netinet6/nd6_nbr.c	(revision 195123)
+++ 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/nd6.h
===================================================================
--- sys/netinet6/nd6.h	(revision 195123)
+++ 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/in6.c
===================================================================
--- sys/netinet6/in6.c	(revision 195123)
+++ 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);
@@ -1105,9 +1109,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;
@@ -2161,6 +2165,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/ip6_input.c
===================================================================
--- sys/netinet6/ip6_input.c	(revision 195123)
+++ sys/netinet6/ip6_input.c	(working copy)
@@ -197,7 +197,7 @@
 #ifdef IP6_AUTO_LINKLOCAL
 	V_ip6_auto_linklocal = IP6_AUTO_LINKLOCAL;
 #else
-	V_ip6_auto_linklocal = 1;	/* enable by default */
+	V_ip6_auto_linklocal = 1;	/* enabled by default */
 #endif
 	TUNABLE_INT_FETCH("net.inet6.ip6.auto_linklocal",
 	    &V_ip6_auto_linklocal);
@@ -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 = 0;
 	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 195123)
+++ sys/netinet6/nd6_rtr.c	(working copy)
@@ -129,7 +129,7 @@
 	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)
 		goto freeit;

 	/* Sanity checks */
@@ -216,13 +216,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 +563,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)
 		rt6_flush(&dr->rtaddr, dr->ifp);

 	if (dr->installed) {
@@ -629,10 +628,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 195123)
+++ 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 195123)
+++ 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 195123)
+++ 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,252 @@
+/*
+ * 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;
+
+	/* 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)
+		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);
+
+	nopts = 0;
+	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 195123)
+++ 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 195123)
+++ 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 195123)
+++ 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 195123)
+++ 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 195123)
+++ 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 195123)
+++ 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 195123)
+++ 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,7 +307,8 @@
 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.
@@ -315,6 +316,11 @@
 (not a router)
 for the option to be meaningful.
 Defaults to off.
+.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 195123)
+++ etc/network.subr	(working copy)
@@ -45,6 +45,7 @@
 	ifscript_up ${ifn} && cfg=0
 	ifconfig_up ${ifn} && cfg=0
 	ipv4_up ${ifn} && cfg=0
+	ipv6_up ${ifn} && cfg=0
 	ipx_up ${ifn} && cfg=0
 	childif_create ${ifn}

@@ -64,6 +65,7 @@
 	[ -z "$ifn" ] && return 1

 	ipx_down ${ifn} && cfg=0
+	ipv6_down ${ifn} && cfg=0
 	ipv4_down ${ifn} && cfg=0
 	ifconfig_down ${ifn} && cfg=0
 	ifscript_down ${ifn} && cfg=0
@@ -83,6 +85,10 @@
 {
 	_cfg=1

+	if ! ipv6if $1; then
+		ifconfig $1 inet6 -auto_linklocal
+	fi
+
 	ifconfig_args=`ifconfig_getargs $1`
 	if [ -n "${ifconfig_args}" ]; then
 		ifconfig $1 ${ifconfig_args}
@@ -281,9 +287,15 @@
 #	1 otherwise.
 ipv6if()
 {
-	if ! checkyesno ipv6_enable; then
-		return 1
-	fi
+	_if=$1
+
+	# lo0 is always IPv6-enabled
+	case $_if in
+	lo[0-9]*)
+		return 0
+		;;
+	esac
+
 	case "${ipv6_network_interfaces}" in
 	[Aa][Uu][Tt][Oo])
 		return 0
@@ -292,14 +304,40 @@
 		return 1
 		;;
 	esac
-	for v6if in ${ipv6_network_interfaces}; do
-		if [ "${v6if}" = "${1}" ]; then
+	for i in ${ipv6_network_interfaces}; do
+		if [ "$i" = "$_if" ]; then
 			return 0
 		fi
 	done
 	return 1
 }

+# ipv6_autoconfif if
+#	Returns 0 if the interface should be configured for IPv6 with
+#	Stateless Address Configuration, 1 otherwise.
+ipv6_autoconfif()
+{
+	_if=$1
+
+	if checkyesno ipv6_gateway_enable; then
+		return 1
+	fi
+	if ! ipv6if $_if; then
+		return 1
+	fi
+
+	_tmpargs=`_ifconfig_getargs $_if`
+	for _arg in $_tmpargs; do
+		case $_arg in
+		accept_rtadv)
+			return 0
+			;;
+		esac
+	done
+
+	return 1
+}
+
 # ifexists if
 #	Returns 0 if the interface exists and 1 otherwise.
 ifexists()
@@ -312,10 +350,30 @@
 ipv4_up()
 {
 	_if=$1
-	ifalias_up ${_if}
+
+	ifalias_up ${_if} inet
 	ipv4_addrs_common ${_if} alias
 }

+# ipv6_up if
+#  add IPv6 addresses to the interface $if
+ipv6_up()
+{
+	_if=$1
+
+	if ! ipv6if $_if; then
+		return
+	fi
+
+	ifalias_up ${_if} inet6
+	ipv6_prefix_hostid_addr_up ${_if}
+	ipv6_accept_rtadv_up ${_if}
+
+	# wait for DAD
+	sleep `${SYSCTL_N} net.inet6.ip6.dad_count`
+	sleep 1
+}
+
 # ipv4_down if
 #  remove IPv4 addresses from the interface $if
 ipv4_down()
@@ -343,12 +401,49 @@
 	done
 	IFS="$oldifs"

-	ifalias_down ${_if} && _ret=0
+	ifalias_down ${_if} inet && _ret=0
 	ipv4_addrs_common ${_if} -alias && _ret=0

 	return $_ret
 }

+# ipv6_down if
+#  remove IPv6 addresses from the interface $if
+ipv6_down()
+{
+	_if=$1
+	_ifs="^"
+	_ret=1
+
+	ifexists ${_if} || return 1
+
+	if ! ipv6if $_if; then
+		return 0
+	fi
+
+	ipv6_accept_rtadv_down ${_if}
+	ifalias_down ${_if} inet6 && _ret=0
+
+	inetList="`ifconfig ${_if} | grep 'inet6 ' | tr "\n" "$_ifs"`"
+
+	oldifs="$IFS"
+	IFS="$_ifs"
+	for _inet6 in $inetList ; do
+		# get rid of extraneous line
+		[ -z "$_inet6" ] && break
+
+		_inet6=`expr "$_inet6" : '.*\(inet6 \([0-9a-f:]*\)\).*'`
+
+		IFS="$oldifs"
+		ifconfig ${_if} ${_inet6} -alias
+		IFS="$_ifs"
+		_ret=0
+	done
+	IFS="$oldifs"
+
+	return $_ret
+}
+
 # ipv4_addrs_common if action
 #   Evaluate the ifconfig_if_ipv4 arguments for interface $if
 #   and use $action to add or remove IPv4 addresses from $if.
@@ -389,7 +484,7 @@
 	return $_ret
 }

-# ifalias_up if
+# ifalias_up if af
 #	Configure aliases for network interface $if.
 #	It returns 0 if at least one alias was configured or
 #	1 if there were none.
@@ -397,21 +492,95 @@
 ifalias_up()
 {
 	_ret=1
+
+	case "$2" in
+	inet|ipv4|ip4)
+		_ret=`ifalias_ipv4_up "$1"`
+		;;
+	inet6|ipv6|ip6)
+		_ret=`ifalias_ipv6_up "$1"`
+		;;
+	esac
+
+	return $_ret
+}
+
+# ifalias_ipv4_up if
+#	Helper function for ifalias_up().  Handles IPv4.
+#
+ifalias_ipv4_up()
+{
+	_ret=1
+
 	alias=0
 	while : ; do
 		ifconfig_args=`get_if_var $1 ifconfig_IF_alias${alias}`
-		if [ -n "${ifconfig_args}" ]; then
+		case "${ifconfig_args}" in
+		inet\ *)
 			ifconfig $1 ${ifconfig_args} alias
 			alias=$((${alias} + 1))
 			_ret=0
-		else
+			;;
+		*)
 			break
-		fi
+			;;
+		esac
 	done
 	return $_ret
 }

-#ifalias_down if
+# ifalias_ipv6_up if
+#	Helper function for ifalias_up().  Handles IPv6.
+#
+ifalias_ipv6_up()
+{
+	_ret=1
+
+	if checkyesno ipv6_gateway_enable ]; then
+		_ipv6_opts="-accept_rtadv auto_linklocal"
+	else
+		_ipv6_opts="auto_linklocal"
+	fi
+
+	ifconfig_args=`get_if_var $1 ipv6_ifconfig_IF`
+	if [ -n "${ifconfig_args}" ]; then
+		ifconfig $1 inet6 ${ifconfig_args} ${_ipv6_opts}
+	fi
+
+	alias=0
+	while : ; do
+		ifconfig_args=`get_if_var $1 ifconfig_IF_alias${alias}`
+		case "${ifconfig_args}" in
+		inet6\ *)
+			ifconfig $1 ${ifconfig_args} alias ${_ipv6_opts}
+			alias=$((${alias} + 1))
+			_ret=0
+			;;
+		*)
+			break
+			;;
+		esac
+	done
+
+	# backward compatibility: ipv6_ifconfig_IF_aliasN.
+	alias=0
+	while : ; do
+		ifconfig_args=`get_if_var $1 ipv6_ifconfig_IF_alias${alias}`
+		case "${ifconfig_args}" in
+		"")
+			break
+			;;
+		*)
+			ifconfig $1 inet6 ${ifconfig_args} alias ${_ipv6_opts}
+			alias=$((${alias} + 1))
+			_ret=0
+			;;
+		esac
+	done
+	return $_ret
+}
+
+# ifalias_down if af
 #	Remove aliases for network interface $if.
 #	It returns 0 if at least one alias was removed or
 #	1 if there were none.
@@ -419,20 +588,176 @@
 ifalias_down()
 {
 	_ret=1
+
+	case "$2" in
+	inet|ipv4|ip4)
+		_ret=`ifalias_ipv4_down "$1"`
+		;;
+	inet6|ipv6|ip6)
+		_ret=`ifalias_ipv6_down "$1"`
+		;;
+	esac
+
+	return $_ret
+}
+
+#ifalias_ipv4_down if
+#	Helper function for ifalias_down().  Handles IPv4.
+#
+ifalias_ipv4_down()
+{
+	_ret=1
+
 	alias=0
 	while : ; do
 		ifconfig_args=`get_if_var $1 ifconfig_IF_alias${alias}`
-		if [ -n "${ifconfig_args}" ]; then
+		case "${ifconfig_args}" in
+		inet\ *)
 			ifconfig $1 ${ifconfig_args} -alias
 			alias=$((${alias} + 1))
 			_ret=0
-		else
+			;;
+		*)
 			break
-		fi
+			;;
+		esac
 	done
 	return $_ret
 }

+#ifalias_ipv6_down if
+#	Helper function for ifalias_down().  Handles IPv6.
+#
+ifalias_ipv6_down()
+{
+	_ret=1
+
+	alias=0
+	while : ; do
+		ifconfig_args=`get_if_var $1 ifconfig_IF_alias${alias}`
+		case "${ifconfig_args}" in
+		inet6\ *)
+			ifconfig $1 ${ifconfig_args} -alias
+			alias=$((${alias} + 1))
+			_ret=0
+			;;
+		*)
+			break
+			;;
+		esac
+	done
+
+	# backward compatibility: ipv6_ifconfig_IF_aliasN.
+	while : ; do
+		ifconfig_args=`get_if_var $1 ipv6_ifconfig_IF_alias${alias}`
+		case "${ifconfig_args}" in
+		"")
+			break
+		;;
+		*)
+			ifconfig $1 inet6 ${ifconfig_args} -alias
+			alias=$((${alias} + 1))
+			_ret=0
+		esac
+	done
+	return $_ret
+}
+
+# ipv6_prefix_hostid_addr_up if
+#  add IPv6 prefix + hostid addr to the interface $if
+ipv6_prefix_hostid_addr_up()
+{
+	_if=$1
+	prefix=`get_if_var ${_if} ipv6_prefix_IF`
+
+	if [ -n "${prefix}" ]; then
+		laddr=`network6_getladdr ${_if}`
+		hostid=`expr "${laddr}" : 'fe80::\(.*\)%\(.*\)'`
+		for j in ${prefix}; do
+			address=$j\:${hostid}
+			ifconfig ${_if} inet6 ${address} prefixlen 64 alias
+
+			# if I am a router, add subnet router
+			# anycast address (RFC 2373).
+			if checkyesno ipv6_gateway_enable; then
+				ifconfig ${_if} inet6 $j:: prefixlen 64 \
+					alias anycast
+			fi
+		done
+	fi
+}
+
+# ipv6_accept_rtadv_up if
+#  Enable accepting Router Advertisement and send Router Solicitation message
+ipv6_accept_rtadv_up()
+{
+	_if=$1
+
+	if ipv6_autoconfif $_if; then
+		case ${_if} in
+			lo0|\
+			stf[0-9]*|\
+			faith[0-9]*|\
+			lp[0-9]*|\
+			sl[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]*)
+				# do nothing
+				# Note: Wireless NIC cards are virtualized
+				# through the wlan interface
+				;;
+			*)
+				ifconfig ${_if} inet6 accept_rtadv up
+				rtsol ${rtsol_flags} ${_if}
+				;;
+		esac
+	fi
+}
+
+# ipv6_accept_rtadv_down if
+#  Disabled accepting Router Advertisement
+ipv6_accept_rtadv_down()
+{
+	_if=$1
+
+	if ipv6_autoconfif $_if; then
+		case ${_if} in
+			lo0|\
+			stf[0-9]*|\
+			faith[0-9]*|\
+			lp[0-9]*|\
+			sl[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]*)
+				# do nothing
+				# Note: Wireless NIC cards are virtualized
+				# through the wlan interface
+				;;
+			*)
+				ifconfig ${_if} inet6 -accept_rtadv
+				;;
+		esac
+	fi
+}
+
 # ifscript_up if
 #	Evaluate a startup script for the $if interface.
 #	It returns 0 if a script was found and processed or
@@ -695,8 +1020,12 @@
 #	List all network interfaces. The type of interface returned
 #	can be controlled by the type argument. The type
 #	argument can be any of the following:
-#		nodhcp - all interfaces, excluding DHCP configured interfaces
-#		dhcp   - list only DHCP configured interfaces
+#		nodhcp	- all interfaces, excluding DHCP configured interfaces
+#		dhcp	- list only DHCP configured interfaces
+#		noautoconf	- all interfaces, excluding IPv6 Stateless
+#				  Address Autoconf configured interfaces
+#		autoconf	- list only IPv6 Stateless Address Autoconf
+#				  configured interfaces
 #	If no argument is specified all network interfaces are output.
 #	Note that the list will include cloned interfaces if applicable.
 #	Cloned interfaces must already exist to have a chance to appear
@@ -737,25 +1066,48 @@

 	# Separate out dhcp and non-dhcp interfaces
 	#
+	_list=
 	_aprefix=
 	_bprefix=
-	for _if in ${_tmplist} ; do
-		if dhcpif $_if; then
-			_dhcplist="${_dhcplist}${_aprefix}${_if}"
-			[ -z "$_aprefix" ] && _aprefix=' '
-		elif [ -n "`_ifconfig_getargs $_if`" ]; then
-			_nodhcplist="${_nodhcplist}${_bprefix}${_if}"
-			[ -z "$_bprefix" ] && _bprefix=' '
-		fi
-	done
-
 	case "$type" in
 	nodhcp)
-		echo $_nodhcplist
+		for _if in ${_tmplist} ; do
+			if ! dhcpif $_if && \
+			   [ -n "`_ifconfig_getargs $_if`" ]; then
+				_list="${_list}${_aprefix}${_if}"
+				[ -z "$_aprefix" ] && _aprefix=' '
+			fi
+		done
+		echo $_list
 		;;
 	dhcp)
-		echo $_dhcplist
+		for _if in ${_tmplist} ; do
+			if dhcpif $_if; then
+				_list="${_list}${_aprefix}${_if}"
+				[ -z "$_aprefix" ] && _aprefix=' '
+			fi
+		done
+		echo $_list
 		;;
+	noautoconf)
+		for _if in ${_tmplist} ; do
+			if ! ipv6_autoconfif $_if && \
+			   [ -n "`_ifconfig_getargs $_if`" ]; then
+				_list="${_list}${_aprefix}${_if}"
+				[ -z "$_aprefix" ] && _aprefix=' '
+			fi
+		done
+		echo $_list
+		;;
+	noautoconf)
+		for _if in ${_tmplist} ; do
+			if ipv6_autoconfif $_if; then
+				_list="${_list}${_aprefix}${_if}"
+				[ -z "$_aprefix" ] && _aprefix=' '
+			fi
+		done
+		echo $_list
+		;;
 	esac
 	return 0
 }
@@ -816,248 +1168,6 @@
 	echo ${str}
 }

-# Setup the interfaces for IPv6
-network6_interface_setup()
-{
-	interfaces=$*
-	rtsol_interfaces=''
-	case ${ipv6_gateway_enable} in
-	[Yy][Ee][Ss])
-		rtsol_available=no
-		;;
-	*)
-		rtsol_available=yes
-		;;
-	esac
-	for i in $interfaces; do
-		rtsol_interface=yes
-		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)
-					ifconfig $i inet6 $j:: prefixlen 64 \
-						alias anycast
-					;;
-				esac
-			done
-		fi
-		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
-
-		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]*)
-				;;
-			*)
-				rtsol_interfaces="${rtsol_interfaces} ${i}"
-				;;
-			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
-	fi
-
-	for i in $interfaces; do
-		alias=0
-		while : ; do
-			ipv6_ifconfig=`get_if_var $i ipv6_ifconfig_IF_alias${alias}`
-			if [ -z "${ipv6_ifconfig}" ]; then
-				break;
-			fi
-			ifconfig $i inet6 ${ipv6_ifconfig} alias
-			alias=$((${alias} + 1))
-		done
-	done
-}
-
-# Setup IPv6 to IPv4 mapping
-network6_stf_setup()
-{
-	case ${stf_interface_ipv4addr} in
-	[Nn][Oo] | '')
-		;;
-	*)
-		# assign IPv6 addr and interface route for 6to4 interface
-		stf_prefixlen=$((16+${stf_interface_ipv4plen:-0}))
-		OIFS="$IFS"
-		IFS=".$IFS"
-		set ${stf_interface_ipv4addr}
-		IFS="$OIFS"
-		hexfrag1=`hexprint $(($1*256 + $2))`
-		hexfrag2=`hexprint $(($3*256 + $4))`
-		ipv4_in_hexformat="${hexfrag1}:${hexfrag2}"
-		case ${stf_interface_ipv6_ifid} in
-		[Aa][Uu][Tt][Oo] | '')
-			for i in ${ipv6_network_interfaces}; do
-				laddr=`network6_getladdr ${i}`
-				case ${laddr} in
-				'')
-					;;
-				*)
-					break
-					;;
-				esac
-			done
-			stf_interface_ipv6_ifid=`expr "${laddr}" : \
-						      'fe80::\(.*\)%\(.*\)'`
-			case ${stf_interface_ipv6_ifid} in
-			'')
-				stf_interface_ipv6_ifid=0:0:0:1
-				;;
-			esac
-			;;
-		esac
-		ifconfig stf0 create >/dev/null 2>&1
-		ifconfig stf0 inet6 2002:${ipv4_in_hexformat}:${stf_interface_ipv6_slaid:-0}:${stf_interface_ipv6_ifid} \
-			prefixlen ${stf_prefixlen}
-		# disallow packets to malicious 6to4 prefix
-		route add -inet6 2002:e000:: -prefixlen 20 ::1 -reject
-		route add -inet6 2002:7f00:: -prefixlen 24 ::1 -reject
-		route add -inet6 2002:0000:: -prefixlen 24 ::1 -reject
-		route add -inet6 2002:ff00:: -prefixlen 24 ::1 -reject
-		;;
-	esac
-}
-
-# Setup static routes
-network6_static_routes_setup()
-{
-	# Set up any static routes.
-	case ${ipv6_defaultrouter} in
-	[Nn][Oo] | '')
-		;;
-	*)
-		ipv6_static_routes="default ${ipv6_static_routes}"
-		ipv6_route_default="default ${ipv6_defaultrouter}"
-		;;
-	esac
-	case ${ipv6_static_routes} in
-	[Nn][Oo] | '')
-		;;
-	*)
-		for i in ${ipv6_static_routes}; do
-			ipv6_route_args=`get_if_var $i ipv6_route_IF`
-			route add -inet6 ${ipv6_route_args}
-		done
-		;;
-	esac
-}
-
-# Setup faith
-network6_faith_setup()
-{
-	case ${ipv6_faith_prefix} in
-	[Nn][Oo] | '')
-		;;
-	*)
-		sysctl net.inet6.ip6.keepfaith=1
-		ifconfig faith0 create >/dev/null 2>&1
-		ifconfig faith0 up
-		for prefix in ${ipv6_faith_prefix}; do
-			prefixlen=`expr "${prefix}" : ".*/\(.*\)"`
-			case ${prefixlen} in
-			'')
-				prefixlen=96
-				;;
-			*)
-				prefix=`expr "${prefix}" : \
-					     "\(.*\)/${prefixlen}"`
-				;;
-			esac
-			route add -inet6 ${prefix} -prefixlen ${prefixlen} ::1
-			route change -inet6 ${prefix} -prefixlen ${prefixlen} \
-				-ifp faith0
-		done
-		;;
-	esac
-}
-
-# Install the "default interface" to kernel, which will be used
-# as the default route when there's no router.
-network6_default_interface_setup()
-{
-	# Choose IPv6 default interface if it is not clearly specified.
-	case ${ipv6_default_interface} in
-	'')
-		for i in ${ipv6_network_interfaces}; do
-			case $i in
-			lo0|faith[0-9]*)
-				continue
-				;;
-			esac
-			laddr=`network6_getladdr $i exclude_tentative`
-			case ${laddr} in
-			'')
-				;;
-			*)
-				ipv6_default_interface=$i
-				break
-				;;
-			esac
-		done
-		;;
-	esac
-
-	# Disallow unicast packets without outgoing scope identifiers,
-	# or route such packets to a "default" interface, if it is specified.
-	route add -inet6 fe80:: -prefixlen 10 ::1 -reject
-	case ${ipv6_default_interface} in
-	[Nn][Oo] | '')
-		route add -inet6 ff02:: -prefixlen 16 ::1 -reject
-		;;
-	*)
-		laddr=`network6_getladdr ${ipv6_default_interface}`
-		route add -inet6 ff02:: ${laddr} -prefixlen 16 -interface \
-			-cloning
-
-		# 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.
-		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
-			;;
-		esac
-		;;
-	esac
-}
-
 network6_getladdr()
 {
 	ifconfig $1 2>/dev/null | while read proto addr rest; do
Index: etc/rc.d/NETWORKING
===================================================================
--- etc/rc.d/NETWORKING	(revision 195123)
+++ etc/rc.d/NETWORKING	(working copy)
@@ -4,7 +4,7 @@
 #

 # PROVIDE: NETWORKING NETWORK
-# REQUIRE: netif netoptions routing network_ipv6 ppp ipfw
+# REQUIRE: netif netoptions routing ppp ipfw stf faith
 # REQUIRE: defaultroute routed mrouted route6d mroute6d resolv

 #	This is a dummy dependency, for services which require networking
Index: etc/rc.d/network_ipv6
===================================================================
--- etc/rc.d/network_ipv6	(revision 195123)
+++ etc/rc.d/network_ipv6	(working copy)
@@ -1,126 +0,0 @@
-#!/bin/sh
-#
-# Copyright (c) 2000  The KAME Project
-# 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 AUTHOR 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 AUTHOR 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.
-#
-# $FreeBSD$
-# 	From: src/etc/rc.network6,v 1.29 2002/04/06 15:15:43
-#
-
-# PROVIDE: network_ipv6
-# REQUIRE: routing ip6fw
-# KEYWORD: nojail
-
-. /etc/rc.subr
-. /etc/network.subr
-
-name="network_ipv6"
-rcvar=`set_rcvar ipv6`
-start_cmd="network_ipv6_start"
-
-network_ipv6_start()
-{
-	# disallow "internal" addresses to appear on the wire
-	route add -inet6 ::ffff:0.0.0.0 -prefixlen 96 ::1 -reject
-	route add -inet6 ::0.0.0.0 -prefixlen 96 ::1 -reject
-
-	case ${ipv6_network_interfaces} in
-	[Aa][Uu][Tt][Oo])
-		# Get a list of network interfaces
-		ipv6_network_interfaces="`ifconfig -l`"
-		;;
-	[Nn][Oo][Nn][Ee])
-		ipv6_network_interfaces=''
-		;;
-	esac
-
-	if checkyesno ipv6_gateway_enable; then
-		# act as a router
-		${SYSCTL_W} net.inet6.ip6.forwarding=1
-		${SYSCTL_W} net.inet6.ip6.accept_rtadv=0
-
-		# wait for DAD
-		for i in $ipv6_network_interfaces; do
-			ifconfig $i 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
-	fi
-
-	if [ -n "${ipv6_network_interfaces}" ]; then
-		# Setup the interfaces
-		network6_interface_setup $ipv6_network_interfaces
-
-		# wait for DAD's completion (for global addrs)
-		sleep `${SYSCTL_N} net.inet6.ip6.dad_count`
-		sleep 1
-	fi
-
-	# Filter out interfaces on which IPv6 initialization failed.
-	if checkyesno ipv6_gateway_enable; then
-		ipv6_working_interfaces=""
-		for i in ${ipv6_network_interfaces}; do
-			laddr=`network6_getladdr $i exclude_tentative`
-			case ${laddr} in
-			'')
-				;;
-			*)
-				ipv6_working_interfaces="$i \
-				    ${ipv6_working_interfaces}"
-				;;
-			esac
-		done
-		ipv6_network_interfaces=${ipv6_working_interfaces}
-	fi
-
-	# Setup IPv6 to IPv4 mapping
-	network6_stf_setup
-
-	# Install the "default interface" to kernel, which will be used
-	# as the default route when there's no router.
-	network6_default_interface_setup
-
-	# Setup static routes
-	network6_static_routes_setup
-
-	# Setup faith
-	network6_faith_setup
-
-	# Support for IPv4 address tacked onto an IPv6 address
-	if checkyesno ipv6_ipv4mapping; then
-		echo 'IPv4 mapped IPv6 address support=YES'
-		${SYSCTL_W} net.inet6.ip6.v6only=0 >/dev/null
-	else
-		echo 'IPv4 mapped IPv6 address support=NO'
-		${SYSCTL_W} net.inet6.ip6.v6only=1 >/dev/null
-	fi
-}
-
-load_rc_config $name
-run_rc_command "$1"
Index: etc/rc.d/devd
===================================================================
--- etc/rc.d/devd	(revision 195123)
+++ etc/rc.d/devd	(working copy)
@@ -4,7 +4,7 @@
 #

 # PROVIDE: devd
-# REQUIRE: netif network_ipv6
+# REQUIRE: netif
 # BEFORE: NETWORKING mountcritremote
 # KEYWORD: nojail shutdown

Index: etc/rc.d/addswap
===================================================================
--- etc/rc.d/addswap	(revision 195123)
+++ etc/rc.d/addswap	(working copy)
@@ -7,7 +7,6 @@

 # PROVIDE: addswap
 # REQUIRE: FILESYSTEMS
-# BEFORE: sysctl
 # KEYWORD: nojail

 . /etc/rc.subr
Index: etc/rc.d/sysctl
===================================================================
--- etc/rc.d/sysctl	(revision 195123)
+++ etc/rc.d/sysctl	(working copy)
@@ -5,7 +5,7 @@

 # PROVIDE: sysctl
 # REQUIRE: root
-# BEFORE:  DAEMON
+# BEFORE: FILESYSTEMS

 . /etc/rc.subr

Index: etc/rc.d/mroute6d
===================================================================
--- etc/rc.d/mroute6d	(revision 195123)
+++ etc/rc.d/mroute6d	(working copy)
@@ -4,7 +4,8 @@
 #

 # PROVIDE: mroute6d
-# REQUIRE: network_ipv6
+# REQUIRE: netif
+# BEFORE: NETWORKING
 # KEYWORD: nojail

 . /etc/rc.subr
Index: etc/rc.d/ip6addrctl
===================================================================
--- etc/rc.d/ip6addrctl	(revision 195123)
+++ etc/rc.d/ip6addrctl	(working copy)
@@ -4,8 +4,8 @@
 #

 # PROVIDE: ip6addrctl
-# REQUIRE: FILESYSTEMS netif
-# BEFORE: network_ipv6
+# REQUIRE: FILESYSTEMS
+# BEFORE: netif
 # KEYWORD: nojail

 . /etc/rc.subr
@@ -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 195123)
+++ etc/rc.d/Makefile	(working copy)
@@ -4,13 +4,13 @@

 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 \
 	dmesg dumpon \
 	encswap \
-	fsck ftp-proxy ftpd \
+	faith fsck ftp-proxy ftpd \
 	gbde geli geli2 gssd \
 	hcsecd \
 	hostapd hostid hostname \
@@ -23,7 +23,7 @@
 	mixer motd mountcritlocal mountcritremote mountlate \
 	mdconfig mdconfig2 mountd moused mroute6d mrouted msgs \
 	named natd netif netoptions \
-	network_ipv6 newsyslog nfsclient nfscbd nfsd \
+	newsyslog nfsclient nfscbd nfsd \
 	nfsserver nfsuserd nisdomain nsswitch ntpd ntpdate \
 	othermta \
 	pf pflog pfsync \
@@ -32,7 +32,7 @@
 	random rarpd resolv rfcomm_pppd_server root \
 	route6d routed routing rpcbind rtadvd rwho \
 	savecore sdpd securelevel sendmail \
-	serial sppp statd swap1 \
+	serial sppp statd stf swap1 \
 	syscons sysctl syslogd \
 	timed tmp \
 	ugidfw \
Index: etc/rc.d/route6d
===================================================================
--- etc/rc.d/route6d	(revision 195123)
+++ etc/rc.d/route6d	(working copy)
@@ -4,7 +4,7 @@
 #

 # PROVIDE: route6d
-# REQUIRE: network_ipv6
+# REQUIRE: netif routing
 # KEYWORD: nojail

 . /etc/rc.subr
Index: etc/rc.d/netoptions
===================================================================
--- etc/rc.d/netoptions	(revision 195123)
+++ etc/rc.d/netoptions	(working copy)
@@ -5,10 +5,15 @@

 # PROVIDE: netoptions
 # REQUIRE: FILESYSTEMS
+# BEFORE: netif
 # KEYWORD: nojail

 . /etc/rc.subr

+name="netoptions"
+start_cmd="netoptions_start"
+stop_cmd=:
+
 _netoptions_initdone=
 netoptions_init()
 {
@@ -18,75 +23,58 @@
 	fi
 }

-load_rc_config 'XXX'
+netoptions_start()
+{
+	if checkyesno log_in_vain; then
+		netoptions_init
+		echo -n " log_in_vain=${log_in_vain}"
+		${SYSCTL_W} net.inet.tcp.log_in_vain="${log_in_vain}" >/dev/null
+		${SYSCTL_W} net.inet.udp.log_in_vain="${log_in_vain}" >/dev/null
+	fi

-case ${log_in_vain} in
-[Nn][Oo] | '')
-	log_in_vain=0
-	;;
-[Yy][Ee][Ss])
-	log_in_vain=1
-	;;
-[0-9]*)
-	;;
-*)
-	netoptions_init
-	echo " invalid log_in_vain setting: ${log_in_vain}"
-	log_in_vain=0
-	;;
-esac
+	if checkyesno tcp_extensions; then
+		netoptions_init
+		echo -n ' rfc1323 extensions=NO'
+		${SYSCTL_W} net.inet.tcp.rfc1323=0 >/dev/null
+	fi

-if [ "${log_in_vain}" -ne 0 ]; then
-	netoptions_init
-	echo -n " log_in_vain=${log_in_vain}"
-	sysctl net.inet.tcp.log_in_vain="${log_in_vain}" >/dev/null
-	sysctl net.inet.udp.log_in_vain="${log_in_vain}" >/dev/null
-fi
+	if ! checkyesno tcp_keepalive; then
+		netoptions_init
+		echo -n ' TCP keepalive=NO'
+		${SYSCTL_W} net.inet.tcp.always_keepalive=0 >/dev/null
+	fi

-case ${tcp_extensions} in
-[Yy][Ee][Ss] | '')
-	;;
-*)
-	netoptions_init
-	echo -n ' tcp extensions=NO'
-	sysctl net.inet.tcp.rfc1323=0 >/dev/null
-	;;
-esac
+	if checkyesno tcp_drop_synfin; then
+		netoptions_init
+		echo -n ' drop SYN+FIN packets=YES'
+		${SYSCTL_W} net.inet.tcp.drop_synfin=1 >/dev/null
+	fi

-case ${tcp_keepalive} in
-[Nn][Oo])
-	netoptions_init
-	echo -n ' TCP keepalive=NO'
-	sysctl net.inet.tcp.always_keepalive=0 >/dev/null
-	;;
-esac
+	case ${ip_portrange_first} in
+	[0-9]*)
+		netoptions_init
+		echo -n " ip_portrange_first=$ip_portrange_first"
+		${SYSCTL_W} net.inet.ip.portrange.first=$ip_portrange_first >/dev/null
+		;;
+	esac

-case ${tcp_drop_synfin} in
-[Yy][Ee][Ss])
-	netoptions_init
-	echo -n ' drop SYN+FIN packets=YES'
-	sysctl net.inet.tcp.drop_synfin=1 >/dev/null
-	;;
-esac
+	case ${ip_portrange_last} in
+	[0-9]*)
+		netoptions_init
+		echo -n " ip_portrange_last=$ip_portrange_last"
+		${SYSCTL_W} net.inet.ip.portrange.last=$ip_portrange_last >/dev/null
+		;;
+	esac

-case ${ip_portrange_first} in
-[Nn][Oo] | '')
-	;;
-*)
-	netoptions_init
-	echo -n " ip_portrange_first=$ip_portrange_first"
-	sysctl net.inet.ip.portrange.first=$ip_portrange_first >/dev/null
-	;;
-esac
+	if checkyesno ipv6_ipv4mapping; then
+		${SYSCTL_W} net.inet6.ip6.v6only=0 >/dev/null
+	else
+		echo -n " no-ipv4-mapped-ipv6"
+		${SYSCTL_W} net.inet6.ip6.v6only=1 >/dev/null
+	fi

-case ${ip_portrange_last} in
-[Nn][Oo] | '')
-	;;
-*)
-	netoptions_init
-	echo -n " ip_portrange_last=$ip_portrange_last"
-	sysctl net.inet.ip.portrange.last=$ip_portrange_last >/dev/null
-	;;
-esac
+	[ -n "${_netoptions_initdone}" ] && echo '.'
+}

-[ -n "${_netoptions_initdone}" ] && echo '.'
+load_rc_config $name
+run_rc_command $1
Index: etc/rc.d/auto_linklocal
===================================================================
--- etc/rc.d/auto_linklocal	(revision 195123)
+++ 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/defaultroute
===================================================================
--- etc/rc.d/defaultroute	(revision 195123)
+++ etc/rc.d/defaultroute	(working copy)
@@ -6,7 +6,7 @@
 #

 # PROVIDE: defaultroute
-# REQUIRE: devd netif network_ipv6
+# REQUIRE: devd netif
 # KEYWORD: nojail

 . /etc/rc.subr
@@ -18,7 +18,7 @@

 defaultroute_start()
 {
-	local output carrier nocarrier
+	local output carrier nocarrier nl

 	# Return without waiting if we don't have dhcp interfaces or
 	# if none of the dhcp interfaces is plugged in.
@@ -41,6 +41,7 @@
 		if [ -n "${defif}" ]; then
 			if [ ${delay} -ne ${defaultroute_delay} ]; then
 				echo -n "($defif)"
+				nl=1
 			fi
 			break
 		fi
@@ -49,11 +50,12 @@
 		else
 			echo -n .
 		fi
+		nl=1
 		sleep 1
 		delay=`expr $delay - 1`
 	done

-	echo
+	[ -n "$nl" ] && echo
 }

 load_rc_config $name
Index: etc/rc.d/rtadvd
===================================================================
--- etc/rc.d/rtadvd	(revision 195123)
+++ etc/rc.d/rtadvd	(working copy)
@@ -40,10 +40,25 @@
 	# 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|\
+			stf[0-9]*|\
+			faith[0-9]*|\
+			lp[0-9]*|\
+			sl[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]*)
 				continue
 				;;
 			*)
Index: etc/rc.d/routing
===================================================================
--- etc/rc.d/routing	(revision 195123)
+++ etc/rc.d/routing	(working copy)
@@ -27,11 +27,69 @@

 routing_stop()
 {
+	static_stop
 	route -n flush
+	for i in ${ipv6_network_interfaces}; do
+		ifconfig $i inet6 -defaultif
+	done
 }

 static_start()
 {
+	af=$1
+
+	case ${_af} in
+	inet | ipv4 | ip4)
+		do_static ipv4 add
+		;;
+	inet6 | ipv6 | ip6)
+		do_static ipv6 add
+		;;
+	atm)
+		do_static atm add
+		;;
+	*)
+		do_static ipv4 add
+		do_static ipv6 add
+		do_static atm add
+		;;
+	esac
+}
+
+static_stop()
+{
+	af=$1
+
+	case ${_af} in
+	inet | ipv4 | ip4)
+		do_static ipv4 delete
+		;;
+	inet6 | ipv6 | ip6)
+		do_static ipv6 delete
+		;;
+	atm)
+		do_static atm delete
+		;;
+	*)
+		do_static ipv4 delete
+		do_static ipv6 delete
+		do_static atm delete
+		;;
+	esac
+}
+
+do_static()
+{
+	_af=$1
+	_action=$2
+
+	eval $1_static $2
+}
+
+ipv4_static()
+{
+	_action=$1
+
 	case ${defaultrouter} in
 	[Nn][Oo] | '')
 		;;
@@ -41,20 +99,128 @@
 		;;
 	esac

-	# Setup static routes. This should be done before router discovery.
-	#
 	if [ -n "${static_routes}" ]; then
 		for i in ${static_routes}; do
-			eval route_args=\$route_${i}
-			route add ${route_args}
+			route_args=`get_if_var $i route_IF`
+			route ${_action} ${route_args}
 		done
 	fi
-	# Now ATM static routes
-	#
+}
+
+ipv6_static()
+{
+	_action=$1
+
+	# disallow "internal" addresses to appear on the wire
+	route ${_action} -inet6 ::ffff:0.0.0.0 -prefixlen 96 ::1 -reject
+	route ${_action} -inet6 ::0.0.0.0 -prefixlen 96 ::1 -reject
+
+	case ${ipv6_defaultrouter} in
+	[Nn][Oo] | '')
+		;;
+	*)
+		ipv6_static_routes="default ${ipv6_static_routes}"
+		ipv6_route_default="default ${ipv6_defaultrouter}"
+		;;
+	esac
+
+	if [ -n "${ipv6_static_routes}" ]; then
+		for i in ${ipv6_static_routes}; do
+			ipv6_route_args=`get_if_var $i ipv6_route_IF`
+			route ${_action} -inet6 ${route_args}
+		done
+	fi
+
+	# Fixup $ipv6_network_interfaces
+	case ${ipv6_network_interfaces} in
+	[Nn][Oo][Nn][Ee])
+		ipv6_network_interfaces=''
+		;;
+	esac
+
+	if checkyesno ipv6_gateway_enable; then
+		for i in ${ipv6_network_interfaces}; do
+
+			laddr=`network6_getladdr $i exclude_tentative`
+			case ${laddr} in
+			'')
+				;;
+			*)
+				ipv6_working_interfaces="$i \
+				    ${ipv6_working_interfaces}"
+				;;
+			esac
+		done
+		ipv6_network_interfaces=${ipv6_working_interfaces}
+	fi
+
+	# Install the "default interface" to kernel, which will be used
+	# as the default route when there's no router.
+	case "${ipv6_default_interface}" in
+	[Nn][Oo] | [Nn][Oo][Nn][Ee])
+		ipv6_default_interface=""
+		;;
+	[Aa][Uu][Tt][Oo] | "")
+		for i in ${ipv6_network_interfaces}; do
+			case $i in
+			lo0|faith[0-9]*)
+				continue
+				;;
+			esac
+			laddr=`network6_getladdr $i exclude_tentative`
+			case ${laddr} in
+			'')
+				;;
+			*)
+				ipv6_default_interface=$i
+				break
+				;;
+			esac
+		done
+		;;
+	esac
+
+	# Disallow unicast packets without outgoing scope identifiers,
+	# or route such packets to a "default" interface, if it is specified.
+	route ${_action} -inet6 fe80:: -prefixlen 10 ::1 -reject
+
+	case ${ipv6_default_interface} in
+	'')
+		route ${_action} -inet6 ff02:: -prefixlen 16 ::1 -reject
+		;;
+	*)
+		laddr=`network6_getladdr ${ipv6_default_interface}`
+		route ${_action} -inet6 ff02:: ${laddr} -prefixlen 16 -interface
+
+		# Disable installing the default interface with the
+		# case net.inet6.ip6.forwarding=0 and
+		# the interface with no ND6_IFF_ACCEPT_RTADV
+		# to avoid conflict between the default router list and
+		# the manual configured default route.
+		if ! checkyesno ipv6_gateway_enable; then
+			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
+		fi
+		;;
+	esac
+}
+
+atm_static()
+{
+	_action=$1
+
 	if [ -n "${natm_static_routes}" ]; then
 		for i in ${natm_static_routes}; do
-			eval route_args=\$route_${i}
-			atmconfig natm add ${route_args}
+			route_args=`get_if_var $i route_IF`
+			atmconfig natm ${_action} ${route_args}
 		done
 	fi
 }
@@ -70,72 +236,62 @@

 options_start()
 {
-	case ${icmp_bmcastecho} in
-	[Yy][Ee][Ss])
+	if checkyesno icmp_bmcastecho; then
 		ropts_init
 		echo -n ' broadcast ping responses=YES'
 		sysctl net.inet.icmp.bmcastecho=1 >/dev/null
-		;;
-	esac
+	fi

-	case ${icmp_drop_redirect} in
-	[Yy][Ee][Ss])
+	if checkyesno icmp_drop_redirect; then
 		ropts_init
 		echo -n ' ignore ICMP redirect=YES'
 		sysctl net.inet.icmp.drop_redirect=1 >/dev/null
-		;;
-	esac
+	fi

-	case ${icmp_log_redirect} in
-	[Yy][Ee][Ss])
+	if checkyesno icmp_log_redirect; then
 		ropts_init
 		echo -n ' log ICMP redirect=YES'
 		sysctl net.inet.icmp.log_redirect=1 >/dev/null
-		;;
-	esac
+	fi

-	case ${gateway_enable} in
-	[Yy][Ee][Ss])
+	if checkyesno gateway_enable; then
 		ropts_init
-		echo -n ' IP gateway=YES'
+		echo -n ' IPv4 gateway=YES'
 		sysctl net.inet.ip.forwarding=1 >/dev/null
-		;;
-	esac
+	fi

-	case ${forward_sourceroute} in
-	[Yy][Ee][Ss])
+	if checkyesno ipv6_gateway_enable; then
 		ropts_init
+		echo -n ' IPv6 gateway=YES'
+		sysctl net.inet6.ip6.forwarding=1 >/dev/null
+	fi
+
+	if checkyesno forward_sourceroute; then
+		ropts_init
 		echo -n ' do source routing=YES'
 		sysctl net.inet.ip.sourceroute=1 >/dev/null
-		;;
-	esac
+	fi

-	case ${accept_sourceroute} in
-	[Yy][Ee][Ss])
+	if checkyesno accept_sourceroute; then
 		ropts_init
 		echo -n ' accept source routing=YES'
 		sysctl net.inet.ip.accept_sourceroute=1 >/dev/null
-		;;
-	esac
+	fi

-	case ${ipxgateway_enable} in
-	[Yy][Ee][Ss])
+	if checkyesno ipxgateway_enable; then
 		ropts_init
 		echo -n ' IPX gateway=YES'
 		sysctl net.ipx.ipx.ipxforwarding=1 >/dev/null
-		;;
-	esac
+	fi

-	case ${arpproxy_all} in
-	[Yy][Ee][Ss])
+	if checkyesno arpproxy_all; then
 		ropts_init
 		echo -n ' ARP proxyall=YES'
 		sysctl net.link.ether.inet.proxyall=1 >/dev/null
-		;;
-	esac
+	fi

 	 [ -n "${_ropts_initdone}" ] && echo '.'
 }

 load_rc_config $name
-run_rc_command "$1"
+run_rc_command "$*"
Index: etc/defaults/rc.conf
===================================================================
--- etc/defaults/rc.conf	(revision 195123)
+++ etc/defaults/rc.conf	(working copy)
@@ -197,6 +197,7 @@
 #ifconfig_lo0_alias0="inet 127.0.0.254 netmask 0xffffffff" # Sample alias entry.
 #ifconfig_ed0_ipx="ipx 0x00010010"	# Sample IPX address family entry.
 #ifconfig_fxp0_name="net0"	# Change interface name from fxp0 to net0.
+#ifconfig_ed0="inet6 fec0:0:0:5::1 prefixlen 64" # Sample IPv6 address entry
 #wlans_ath0="wlan0"		# wlan(4) interfaces for ath0 device
 #wlandebug_wlan0="scan+auth+assoc"	# Set debug flags with wlanddebug(8)
 #ipv4_addrs_fxp0="192.168.0.1/24 192.168.1.1-5/28" # example IPv4 address entry.
@@ -417,8 +418,9 @@
 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_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).
@@ -438,8 +440,6 @@
 					# Choose correct prefix value.
 #ipv6_prefix_ed0="fec0:0000:0000:0001 fec0:0000:0000:0002"  # Examples for rtr.
 #ipv6_prefix_ep0="fec0:0000:0000:0003 fec0:0000:0000:0004"  # Examples for rtr.
-#ipv6_ifconfig_ed0="fec0:0:0:5::1 prefixlen 64"	# Sample manual assign entry
-#ipv6_ifconfig_ed0_alias0="fec0:0:0:5::2 prefixlen 64" # Sample alias entry.
 ipv6_default_interface="NO"	# Default output interface for scoped addrs.
 				# Now this works only for IPv6 link local
 				# multicast addrs.

----Next_Part(Sun_Jun_28_09_05_33_2009_873)----

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

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

iEYEABECAAYFAkpGs80ACgkQTyzT2CeTzy1QFgCfRUEt0wA42XsJV/Abi0PILgmD
AUYAoJ621d3I0y6Qbs11pM6vEcpZTJ6t
=q8wv
-----END PGP SIGNATURE-----

----Security_Multipart0(Sun_Jun_28_09_05_33_2009_606)----



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