tech-net archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Remove ability for userland to toggle IPv6 tentative address flag



Hi List

Can anyone think of a use case for allowing userland to toggle the 
IN6_IFF_TENTATIVE flag for IPv6 addresses?

I can't.

The way it's presently implemented can cause a problem as well when the same 
address is added twice, because the logic is thus:

Add IPv6 address without tentative flag
Kernel checks if it's a new address, if so sets tentative flag and starts DAD 
after a random delay.
Add the same IPv6 address without tentative flag again while DAD is still 
running.
Kernel sees it's the same address, so blindly updates the flags which clears 
IN6_IFF_TENTATIVE. This then confuses the DAD process. I've seen it not notify 
userland of the flag being cleared whilst others have reported invalid 
duplicate addresses being reported.

So, can you think of a valid use case for allowing userland to toggle the 
tentative flag? Note that setting it doesn't actually start DAD, just makes 
the address unuseable.

Attached is the patch to remove the ability for userland to toggle 
IN6_IFF_TENTATIVE.

Comments as always are welcome

Roy
Index: sbin/ifconfig/af_inet6.c
===================================================================
RCS file: /cvsroot/src/sbin/ifconfig/af_inet6.c,v
retrieving revision 1.29
diff -u -p -r1.29 af_inet6.c
--- sbin/ifconfig/af_inet6.c	19 Oct 2013 15:50:26 -0000	1.29
+++ sbin/ifconfig/af_inet6.c	12 Oct 2014 20:28:32 -0000
@@ -78,7 +78,6 @@ static cmdloop_branch_t branch[2];
 
 static const struct kwinst ia6flagskw[] = {
 	  IFKW("anycast",	IN6_IFF_ANYCAST)
-	, IFKW("tentative",	IN6_IFF_TENTATIVE)
 	, IFKW("deprecated",	IN6_IFF_DEPRECATED)
 };
 
@@ -476,7 +475,7 @@ in6_usage(prop_dictionary_t env)
 {
 	fprintf(stderr,
 	    "\t[ anycast | -anycast ] [ deprecated | -deprecated ]\n"
-	    "\t[ tentative | -tentative ] [ pltime n ] [ vltime n ] "
+	    "\t[ pltime n ] [ vltime n ] "
 	    "[ eui64 ]\n");
 }
 
Index: sbin/ifconfig/ifconfig.8
===================================================================
RCS file: /cvsroot/src/sbin/ifconfig/ifconfig.8,v
retrieving revision 1.108
diff -u -p -r1.108 ifconfig.8
--- sbin/ifconfig/ifconfig.8	15 Sep 2014 06:48:05 -0000	1.108
+++ sbin/ifconfig/ifconfig.8	12 Oct 2014 20:28:32 -0000
@@ -29,7 +29,7 @@
 .\"
 .\"     @(#)ifconfig.8	8.4 (Berkeley) 6/1/94
 .\"
-.Dd September 15, 2014
+.Dd October 12, 2014
 .Dt IFCONFIG 8
 .Os
 .Sh NAME
@@ -551,12 +551,6 @@ Set the IPv6 deprecated address bit.
 .It Fl deprecated
 .Pq inet6 only
 Clear the IPv6 deprecated address bit.
-.It Cm tentative
-.Pq inet6 only
-Set the IPv6 tentative address bit.
-.It Fl tentative
-.Pq inet6 only
-Clear the IPv6 tentative address bit.
 .It Cm eui64
 .Pq inet6 only
 Fill interface index
Index: sys/netinet6/in6.c
===================================================================
RCS file: /cvsroot/src/sys/netinet6/in6.c,v
retrieving revision 1.176
diff -u -p -r1.176 in6.c
--- sys/netinet6/in6.c	9 Sep 2014 20:16:12 -0000	1.176
+++ sys/netinet6/in6.c	12 Oct 2014 20:28:33 -0000
@@ -649,6 +649,7 @@ in6_control1(struct socket *so, u_long c
 		/* reject read-only flags */
 		if ((ifra->ifra_flags & IN6_IFF_DUPLICATED) != 0 ||
 		    (ifra->ifra_flags & IN6_IFF_DETACHED) != 0 ||
+		    (ifra->ifra_flags & IN6_IFF_TENTATIVE) != 0 ||
 		    (ifra->ifra_flags & IN6_IFF_NODAD) != 0 ||
 		    (ifra->ifra_flags & IN6_IFF_AUTOCONF) != 0) {
 			return EINVAL;
@@ -834,7 +835,7 @@ in6_update_ifa1(struct ifnet *ifp, struc
 	struct in6_multi_mship *imm;
 	struct in6_multi *in6m_sol;
 	struct rtentry *rt;
-	int dad_delay;
+	int dad_delay, was_tentative;
 
 	in6m_sol = NULL;
 
@@ -1063,7 +1064,10 @@ in6_update_ifa1(struct ifnet *ifp, struc
 
 	/*
 	 * configure address flags.
+	 * We need to preserve tentative state so DAD works if
+	 * something adds the same address before DAD finishes.
 	 */
+	was_tentative = ia->ia6_flags & (IN6_IFF_TENTATIVE|IN6_IFF_DUPLICATED);
 	ia->ia6_flags = ifra->ifra_flags;
 
 	/*
@@ -1075,7 +1079,7 @@ in6_update_ifa1(struct ifnet *ifp, struc
 	if (ifp->if_link_state == LINK_STATE_DOWN) {
 		ia->ia6_flags |= IN6_IFF_DETACHED;
 		ia->ia6_flags &= ~IN6_IFF_TENTATIVE;
-	} else if (hostIsNew && in6if_do_dad(ifp))
+	} else if ((hostIsNew || was_tentative) && in6if_do_dad(ifp))
 		ia->ia6_flags |= IN6_IFF_TENTATIVE;
 
 	/*


Home | Main Index | Thread Index | Old Index