Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 16 Oct 2004 18:05:54 +0900
From:      gnn@freebsd.org
To:        rwatson@freebsd.org
Cc:        freebsd-net@freebsd.org
Subject:   in6.c diff for your review and approval
Message-ID:  <m2lle79gnh.wl@minion.local.neville-neil.com>

next in thread | raw e-mail | index | archive | help
Hi,

	This patch fixes PR 44355 which was really an issue of FreeBSD
	not keeping up with the Kame code.  I'd like an approval from
	Robert to commit this, and comments from anyone else familiar
	with this code in case I've missed something.

	This fixes the case where removing any IPv6 address alias also
	removed the associated route, even if the were other aliases
	using that route.

	This patch is modified based on the one in the PR, as well as
	diff of the current Kame and FreeBSD code bases.

Later,
George

Index: in6.c
===================================================================
RCS file: /Volumes/exported/FreeBSD-CVS/src/sys/netinet6/in6.c,v
retrieving revision 1.48
diff -u -r1.48 in6.c
--- in6.c	23 Aug 2004 03:00:26 -0000	1.48
+++ in6.c	16 Oct 2004 08:54:56 -0000
@@ -1,4 +1,4 @@
-/*	$FreeBSD$	*/
+/*	$FreeBSD: src/sys/netinet6/in6.c,v 1.48 2004/08/23 03:00:26 rwatson Exp $	*/
 /*	$KAME: in6.c,v 1.259 2002/01/21 11:37:50 keiichi Exp $	*/
 
 /*
@@ -575,6 +575,14 @@
 		 */
 		if ((error = in6_update_ifa(ifp, ifra, ia)) != 0)
 			return (error);
+		if ((ia = in6ifa_ifpwithaddr(ifp, &ifra->ifra_addr.sin6_addr))
+		    == NULL) {
+		    	/*
+			 * this can happen when the user specify the 0 valid
+			 * lifetime.
+			 */
+			break;
+		}
 
 		/*
 		 * then, make the prefix on-link on the interface.
@@ -628,41 +636,34 @@
 				return (EINVAL); /* XXX panic here? */
 			}
 		}
-		if ((ia = in6ifa_ifpwithaddr(ifp, &ifra->ifra_addr.sin6_addr))
-		    == NULL) {
-		    	/* XXX: this should not happen! */
-			log(LOG_ERR, "in6_control: addition succeeded, but"
-			    " no ifaddr\n");
-		} else {
-			if ((ia->ia6_flags & IN6_IFF_AUTOCONF) != 0 &&
-			    ia->ia6_ndpr == NULL) { /* new autoconfed addr */
-				ia->ia6_ndpr = pr;
-				pr->ndpr_refcnt++;
-
-				/*
-				 * If this is the first autoconf address from
-				 * the prefix, create a temporary address
-				 * as well (when specified).
-				 */
-				if (ip6_use_tempaddr &&
-				    pr->ndpr_refcnt == 1) {
-					int e;
-					if ((e = in6_tmpifadd(ia, 1)) != 0) {
-						log(LOG_NOTICE, "in6_control: "
-						    "failed to create a "
-						    "temporary address, "
-						    "errno=%d\n", e);
-					}
-				}
-			}
+
+		/* relate the address to the prefix */
+		if (ia->ia6_ndpr == NULL) {
+			ia->ia6_ndpr = pr;
+			pr->ndpr_refcnt++;
 
 			/*
-			 * this might affect the status of autoconfigured
-			 * addresses, that is, this address might make
-			 * other addresses detached.
+			 * If this is the first autoconf address from the
+			 * prefix, create a temporary address as well
+			 * (when required).
 			 */
-			pfxlist_onlink_check();
+			if ((ia->ia6_flags & IN6_IFF_AUTOCONF) &&
+			    ip6_use_tempaddr && pr->ndpr_refcnt == 1) {
+				int e;
+				if ((e = in6_tmpifadd(ia, 1)) != 0) {
+					log(LOG_NOTICE, "in6_control: failed "
+					    "to create a temporary address, "
+					    "errno=%d\n", e);
+				}
+			}
 		}
+
+		/*
+		 * this might affect the status of autoconfigured addresses,
+		 * that is, this address might make other addresses detached.
+		 */
+		pfxlist_onlink_check();
+
 		if (error == 0 && ia)
 			EVENTHANDLER_INVOKE(ifaddr_event, ifp);
 		break;
@@ -670,8 +671,7 @@
 
 	case SIOCDIFADDR_IN6:
 	{
-		int i = 0;
-		struct nd_prefix pr0, *pr;
+		struct nd_prefix *pr;
 
 		/*
 		 * If the address being deleted is the only one that owns
@@ -681,37 +681,12 @@
 		 * and the prefix management.  We do this, however, to provide
 		 * as much backward compatibility as possible in terms of
 		 * the ioctl operation.
+		 * Note that in6_purgeaddr() will decrement ndpr_refcnt.
 		 */
-		bzero(&pr0, sizeof(pr0));
-		pr0.ndpr_ifp = ifp;
-		pr0.ndpr_plen = in6_mask2len(&ia->ia_prefixmask.sin6_addr,
-					     NULL);
-		if (pr0.ndpr_plen == 128)
-			goto purgeaddr;
-		pr0.ndpr_prefix = ia->ia_addr;
-		pr0.ndpr_mask = ia->ia_prefixmask.sin6_addr;
-		for (i = 0; i < 4; i++) {
-			pr0.ndpr_prefix.sin6_addr.s6_addr32[i] &=
-				ia->ia_prefixmask.sin6_addr.s6_addr32[i];
-		}
-		/*
-		 * The logic of the following condition is a bit complicated.
-		 * We expire the prefix when
-		 * 1. the address obeys autoconfiguration and it is the
-		 *    only owner of the associated prefix, or
-		 * 2. the address does not obey autoconf and there is no
-		 *    other owner of the prefix.
-		 */
-		if ((pr = nd6_prefix_lookup(&pr0)) != NULL &&
-		    (((ia->ia6_flags & IN6_IFF_AUTOCONF) != 0 &&
-		      pr->ndpr_refcnt == 1) ||
-		     ((ia->ia6_flags & IN6_IFF_AUTOCONF) == 0 &&
-		      pr->ndpr_refcnt == 0))) {
-			pr->ndpr_expire = 1; /* XXX: just for expiration */
-		}
-
-	  purgeaddr:
+		pr = ia->ia6_ndpr;
 		in6_purgeaddr(&ia->ia_ifa);
+		if (pr && pr->ndpr_refcnt == 0)
+			prelist_remove(pr);
 		EVENTHANDLER_INVOKE(ifaddr_event, ifp);
 		break;
 	}
@@ -1171,23 +1146,26 @@
 	}
 
 	/*
-	 * When an autoconfigured address is being removed, release the
-	 * reference to the base prefix.  Also, since the release might
-	 * affect the status of other (detached) addresses, call
-	 * pfxlist_onlink_check().
+	 * Release the reference to the base prefix.  There should be a
+	 * positive reference.
 	 */
-	if ((oia->ia6_flags & IN6_IFF_AUTOCONF) != 0) {
-		if (oia->ia6_ndpr == NULL) {
-			nd6log((LOG_NOTICE, "in6_unlink_ifa: autoconf'ed address "
-			    "%p has no prefix\n", oia));
-		} else {
-			oia->ia6_ndpr->ndpr_refcnt--;
-			oia->ia6_flags &= ~IN6_IFF_AUTOCONF;
-			oia->ia6_ndpr = NULL;
-		}
+	if (oia->ia6_ndpr == NULL) {
+		nd6log((LOG_NOTICE,
+		    "in6_unlink_ifa: autoconf'ed address "
+		    "%p has no prefix\n", oia));
+	} else {
+		oia->ia6_ndpr->ndpr_refcnt--;
+		oia->ia6_ndpr = NULL;
+	}
 
+	/*
+	 * Also, if the address being removed is autoconf'ed, call
+	 * pfxlist_onlink_check() since the release might affect the status of
+	 * other (detached) addresses. 
+	 */
+	if ((oia->ia6_flags & IN6_IFF_AUTOCONF))
 		pfxlist_onlink_check();
-	}
+
 
 	/*
 	 * release another refcnt for the link from in6_ifaddr.



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