From nobody@FreeBSD.org  Mon Oct 21 12:01:26 2002
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125])
	by hub.freebsd.org (Postfix) with ESMTP id 0FB6F37B49D
	for <freebsd-gnats-submit@FreeBSD.org>; Mon, 21 Oct 2002 12:01:25 -0700 (PDT)
Received: from www.freebsd.org (www.freebsd.org [216.136.204.117])
	by mx1.FreeBSD.org (Postfix) with ESMTP id B613B43E6A
	for <freebsd-gnats-submit@FreeBSD.org>; Mon, 21 Oct 2002 12:01:24 -0700 (PDT)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (localhost [127.0.0.1])
	by www.freebsd.org (8.12.6/8.12.6) with ESMTP id g9LJ1O7R006868
	for <freebsd-gnats-submit@FreeBSD.org>; Mon, 21 Oct 2002 12:01:24 -0700 (PDT)
	(envelope-from nobody@www.freebsd.org)
Received: (from nobody@localhost)
	by www.freebsd.org (8.12.6/8.12.6/Submit) id g9LJ1ObS006867;
	Mon, 21 Oct 2002 12:01:24 -0700 (PDT)
Message-Id: <200210211901.g9LJ1ObS006867@www.freebsd.org>
Date: Mon, 21 Oct 2002 12:01:24 -0700 (PDT)
From: "Dmitry Y. Bordakov" <dmitry_bordakov@agilent.com>
To: freebsd-gnats-submit@FreeBSD.org
Subject: After deletion of an IPv6 alias, the route to the whole subnet is removed too.
X-Send-Pr-Version: www-1.0

>Number:         44355
>Category:       kern
>Synopsis:       After deletion of an IPv6 alias, the route to the whole subnet is removed too.
>Confidential:   no
>Severity:       serious
>Priority:       low
>Responsible:    gnn
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Mon Oct 21 12:10:01 PDT 2002
>Closed-Date:    Mon Jul 10 13:16:58 GMT 2006
>Last-Modified:  Mon Jul 10 13:16:58 GMT 2006
>Originator:     Dmitry Y. Bordakov
>Release:        4.4-RELEASE
>Organization:
Agilent Technologies, Inc.
>Environment:
FreeBSD qar1 4.4-RELEASE FreeBSD 4.4-RELEASE #14: Fri Oct 11 19:55:37 GMT 2002     root@qar1:/usr/src/sys/compile/QAR44GENERIC.znb  i386

>Description:
You configured several IPv6 aliases in one subnet (with the same prefix) on one network interface, for example, 3ffe::1, 3ffe::2, 3ffe::3, etc, all on fxp0.
During the first alias configuration, the network stack automatically configured an appropriate route to the network, in our example, 3ffe::/64 -> link#1 .
Deletion of one of the aliases causes deletion of the route and, therefore, unreachability of the remote addresses in the same subnet, for example, ping6 3ffe::123 returns "No route to host".

>How-To-Repeat:
ifconfig lo0 inet6 add 3ffe::1
ifconfig lo0 inet6 add 3ffe::2
netstat -nr | grep lo0
                          ...
                          3ffe::/64       fe80::1%lo0   Uc    lo0
                          3ffe::1         link#2        UHL   lo0
                          3ffe::2         link#2        UHL   lo0
                          ...
ifconfig lo0 inet6 delete 3ffe::1
netstat -nr | grep lo0
                          ...
                          3ffe::2         link#2        UHL   lo0
                          ...


>Fix:
begin 644 in6.c.diff
M+2TM(&EN-BYC+BXP;W)I9VEN86P)5V5D($]C="`@.2`R,3HT,SHS-"`R,#`R
M#0HK*RL@:6XV+F,)5&AU($]C="`Q,"`R,3HU,#HQ-B`R,#`R#0I`0"`M-CDS
M+#8@*S8Y,RPX($!`#0H@"0D)"0D)("`@(&4I.PT*(`D)"0D)?0T*(`D)"0E]
M#0HK"0D)?65L<V5[#0HK"0D)"2LK<'(M/FYD<')?<F5F8VYT.PT*(`D)"7T-
M"B`-"B`)"0DO*@T*0$`@+3<P,BPV("LW,#0L-R!`0`T*(`D)"2`J+PT*(`D)
M"7!F>&QI<W1?;VYL:6YK7V-H96-K*"D[#0H@"0E]#0HK#0H@"0EB<F5A:SL-
M"B`)?0T*(`T*0$`@+3<S.2PQ-B`K-S0R+#(S($!`#0H@"0D@*B`R+B!T:&4@
M861D<F5S<R!D;V5S(&YO="!O8F5Y(&%U=&]C;VYF(&%N9"!T:&5R92!I<R!N
M;PT*(`D)("H@("`@;W1H97(@;W=N97(@;V8@=&AE('!R969I>"X-"B`)"2`J
M+PT*+0D):68@*"AP<B`](&YD-E]P<F5F:7A?;&]O:W5P*"9P<C`I*2`A/2!.
M54Q,("8F#0HM"0D@("`@*"@H:6$M/FEA-E]F;&%G<R`F($E.-E])1D9?0554
M3T-/3D8I("$](#`@)B8-"BT)"2`@("`@('!R+3YN9'!R7W)E9F-N="`]/2`Q
M*2!\?`T*+0D)("`@("`H*&EA+3YI839?9FQA9W,@)B!)3C9?249&7T%55$]#
M3TY&*2`]/2`P("8F#0HM"0D@("`@("!P<BT^;F1P<E]R969C;G0@/3T@,"DI
M*2![#0HM"0D)<'(M/FYD<')?97AP:7)E(#T@,3L@+RH@6%A8.B!J=7-T(&9O
M<B!E>'!I<F%T:6]N("HO#0HK#0HK"0EI9B@@*'!R(#T@;F0V7W!R969I>%]L
M;V]K=7`H)G!R,"DI("$]($Y53$P@*7L-"BL-"BL)"0EI9B@@*"AI82T^:6$V
M7V9L86=S("8@24XV7TE&1E]!551/0T].1BD@/3T@,"D@)B8-"BL)"0D@("`@
M*'!R+3YN9'!R7W)E9F-N="`^(#`I("D@+2UP<BT^;F1P<E]R969C;G0[#0HK
M#0HK"0D):68@*"@H:6$M/FEA-E]F;&%G<R`F($E.-E])1D9?05543T-/3D8I
M("$](#`@)B8-"BL)"0D@("`@("!P<BT^;F1P<E]R969C;G0@/3T@,2D@?'P-
M"BL)"0D@("`@("@H:6$M/FEA-E]F;&%G<R`F($E.-E])1D9?05543T-/3D8I
M(#T](#`@)B8-"BL)"0D@("`@("!P<BT^;F1P<E]R969C;G0@/3T@,"DI('L-
M"BL)"0D)<'(M/FYD<')?97AP:7)E(#T@,3L@+RH@6%A8.B!J=7-T(&9O<B!E
M>'!I<F%T:6]N("HO#0HK"0D)?0T*(`D)?0T*(`T*(`D@('!U<F=E861D<CH-
M"B`)"6EN-E]P=7)G96%D9'(H)FEA+3YI85]I9F$I.PT**PT*(`D)8G)E86L[
*#0H@"7T-"B`-"@``
`
end

begin 644 in6_ifattach.c.diff
M+2TM(&EN-E]I9F%T=&%C:"YC+BXP;W)I9VEN86P)1G)I($]C="`Q,2`Q.3HU
M,CHR-"`R,#`R#0HK*RL@:6XV7VEF871T86-H+F,)1G)I($]C="`Q,2`Q.3HU
M,CHR-"`R,#`R#0I`0"`M-#(Y+#8@*S0R.2PW($!`#0H@"7-T<G5C="!I;C9?
M:69A9&1R("II83L-"B`)<W1R=6-T(&EN-E]A;&EA<W)E<2!I9G)A.PT*(`ES
M=')U8W0@;F1?<')E9FEX('!R,#L-"BL)<W1R=6-T(&YD7W!R969I>"H@<'([
M#0H@"6EN="!I+"!E<G)O<CL-"B`-"B`)+RH-"D!`("TU-30L,3$@*S4U-2PQ
M.2!`0`T*(`D@*B!A9&1R97-S+"!A;F0@=&AE;B!R96-O;F9I9W5R92!A;F]T
M:&5R(&]N92P@=&AE('!R969I>"!I<R!S=&EL;`T*(`D@*B!V86QI9"!W:71H
M(')E9F5R<FEN9R!T;R!T:&4@;VQD(&QI;FLM;&]C86P@861D<F5S<RX-"B`)
M("HO#0HM"6EF("AN9#9?<')E9FEX7VQO;VMU<"@F<'(P*2`]/2!.54Q,*2![
M#0HM"0EI9B`H*&5R<F]R(#T@;F0V7W!R96QI<W1?861D*"9P<C`L($Y53$PL
M($Y53$PI*2`A/2`P*0T**PEI9B@@*'!R(#T@;F0V7W!R969I>%]L;V]K=7`H
M)G!R,"DI(#T]($Y53$P@*7L-"BL)"6EF("@H97)R;W(@/2!N9#9?<')E;&ES
M=%]A9&0H)G!R,"P@3E5,3"P@)G!R*2D@(3T@,"D-"B`)"0ER971U<FXH97)R
M;W(I.PT*(`E]#0H@#0HK"6EF*"!P<B`]/2!.54Q,("E[#0HK#0HK"0EL;V<H
M($Q/1U]%4E(L(")N9#9?<')E;&ES=%]A9&0H*2!S=6-C961E9"!B=70@;F\@
M<')E9FEX7&XB("D[#0HK"0ER971U<FX@14E.5D%,.R`O*B!P86YI8R!H97)E
M/R`J+PT**PE]96QS97L-"BL)"2LK<'(M/FYD<')?<F5F8VYT.PT**PE]#0HK
7"0T*(`ER971U<FX@,#L-"B!]#0H@#0H`
`
end

>Release-Note:
>Audit-Trail:

From: Peter Pentchev <roam@ringlet.net>
To: "Dmitry Y. Bordakov" <dmitry_bordakov@agilent.com>
Cc: bug-followup@FreeBSD.org
Subject: Re: kern/44355: After deletion of an IPv6 alias, the route to the whole subnet is removed too.
Date: Mon, 21 Oct 2002 22:13:37 +0300

 On Mon, Oct 21, 2002 at 12:01:24PM -0700, Dmitry Y. Bordakov wrote:
 > 
 > >Number:         44355
 > >Category:       kern
 > >Synopsis:       After deletion of an IPv6 alias, the route to the whole subnet is removed too.
 > >Originator:     Dmitry Y. Bordakov
 > >Release:        4.4-RELEASE
 > >Organization:
 > Agilent Technologies, Inc.
 > >Environment:
 > FreeBSD qar1 4.4-RELEASE FreeBSD 4.4-RELEASE #14: Fri Oct 11 19:55:37 GMT 2002     root@qar1:/usr/src/sys/compile/QAR44GENERIC.znb  i386
 > 
 > >Description:
 > You configured several IPv6 aliases in one subnet (with the same prefix) on one network interface, for example, 3ffe::1, 3ffe::2, 3ffe::3, etc, all on fxp0.
 > During the first alias configuration, the network stack automatically configured an appropriate route to the network, in our example, 3ffe::/64 -> link#1 .
 > Deletion of one of the aliases causes deletion of the route and, therefore, unreachability of the remote addresses in the same subnet, for example, ping6 3ffe::123 returns "No route to host".
 > 
 > >How-To-Repeat:
 > ifconfig lo0 inet6 add 3ffe::1
 > ifconfig lo0 inet6 add 3ffe::2
 > netstat -nr | grep lo0
 >                           ...
 >                           3ffe::/64       fe80::1%lo0   Uc    lo0
 >                           3ffe::1         link#2        UHL   lo0
 >                           3ffe::2         link#2        UHL   lo0
 >                           ...
 > ifconfig lo0 inet6 delete 3ffe::1
 > netstat -nr | grep lo0
 >                           ...
 >                           3ffe::2         link#2        UHL   lo0
 >                           ...
 
 Is there a reason for you not to set a prefixlen 128 on each alias, just
 as you are supposed to set a netmask of 0xffffffff on each IPv4 alias in
 the same subnet as another address on the interface?
 
 Could you try setting a prefixlen 128 on all aliases except for the
 "primary" address (yeah, yeah, I know.. but it helps to talk of a
 "primary" address sometimes), and check if the problem persists?
 
 G'luck,
 Peter
 
 -- 
 Peter Pentchev	roam@ringlet.net	roam@FreeBSD.org
 PGP key:	http://people.FreeBSD.org/~roam/roam.key.asc
 Key fingerprint	FDBA FD79 C26F 3C51 C95E  DF9E ED18 B68D 1619 4553
 I am not the subject of this sentence.

From: Peter Pentchev <roam@ringlet.net>
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/44355: After deletion of an IPv6 alias, the route to the whole subnet is removed too.
Date: Tue, 22 Oct 2002 08:19:54 +0300

 Adding the originator's response to the PR audit trail..
 
 ----- Forwarded message from dmitry_bordakov@agilent.com -----
 
 From: dmitry_bordakov@agilent.com
 To: roam@ringlet.net
 Subject: RE: kern/44355: After deletion of an IPv6 alias, the route to the
 	 whole subnet is removed too.
 Date: Mon, 21 Oct 2002 14:38:30 -0600
 
 Hello,
 
 
 > Is there a reason for you not to set a prefixlen 128 on each alias, just
 > as you are supposed to set a netmask of 0xffffffff on each IPv4 alias in
 > the same subnet as another address on the interface?
 
 Mmmm... I see no general reasons for this. It came from some non-standard usage of the network stack.
 
 > Could you try setting a prefixlen 128 on all aliases except for the
 > "primary" address (yeah, yeah, I know.. but it helps to talk of a
 > "primary" address sometimes), and check if the problem persists?
 
 No, there is no problem in this case (until you delete the "primary" address").
 
 IPv4 stack also requires the same workaround (primary address + 32bit-masked aliases).
 Is it by design?
 
 
 Thank you,
 Dmitry Bordakov.
Responsible-Changed-From-To: freebsd-bugs->freebsd-net 
Responsible-Changed-By: arved 
Responsible-Changed-When: Fri Aug 27 12:38:53 GMT 2004 
Responsible-Changed-Why:  
Old patches against IPv6, over to freebsd-net to decide if this PR is still  
relevant 

http://www.freebsd.org/cgi/query-pr.cgi?pr=44355 

From: JINMEI Tatuya / =?ISO-2022-JP?B?GyRCP0BMQEMjOkgbKEI=?= <jinmei@isl.rdc.toshiba.co.jp>
To: Tilman Linneweh <arved@FreeBSD.org>
Cc: freebsd-bugs@FreeBSD.org, freebsd-net@FreeBSD.org
Subject: Re: kern/44355: After deletion of an IPv6 alias, the route to the	whole subnet is removed too.
Date: Sun, 29 Aug 2004 22:02:07 +0900

 >>>>> On Fri, 27 Aug 2004 12:39:39 GMT, 
 >>>>> Tilman Linneweh <arved@FreeBSD.org> said:
 
 > Synopsis: After deletion of an IPv6 alias, the route to the whole subnet is removed too.
 > Responsible-Changed-From-To: freebsd-bugs->freebsd-net
 > Responsible-Changed-By: arved
 > Responsible-Changed-When: Fri Aug 27 12:38:53 GMT 2004
 > Responsible-Changed-Why: 
 > Old patches against IPv6, over to freebsd-net to decide if this PR is still 
 > relevant
 
 > http://www.freebsd.org/cgi/query-pr.cgi?pr=44355
 
 Hmm, this seems to be the same issue as that reported to the KAME
 project almost two years ago.  The problem was then fixed there, but
 the fix does not seem to be merged to the FreeBSD repository.
 
 The attached diff below is a similar fix for 5.2.1R.  It cannot
 be applied to 4.x directly, but I guess it's easy to modify.
 
 It would be nice if some committers could review the diff and (if
 appropriate) merge to the FreeBSD repository.
 
 Thanks,
 
 					JINMEI, Tatuya
 					Communication Platform Lab.
 					Corporate R&D Center, Toshiba Corp.
 					jinmei@isl.rdc.toshiba.co.jp
 
 Index: in6.c
 ===================================================================
 RCS file: /home/ncvs/src/sys/netinet6/in6.c,v
 retrieving revision 1.40
 diff -u -r1.40 in6.c
 --- in6.c	8 Nov 2003 23:36:32 -0000	1.40
 +++ in6.c	29 Aug 2004 12:45:15 -0000
 @@ -1,5 +1,5 @@
  /*	$FreeBSD: src/sys/netinet6/in6.c,v 1.40 2003/11/08 23:36:32 sam Exp $	*/
 -/*	$KAME: in6.c,v 1.259 2002/01/21 11:37:50 keiichi Exp $	*/
 +/*	$KAME: in6.c,v 1.334 2002/12/05 15:33:26 jinmei Exp $	*/
  
  /*
   * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
 @@ -579,6 +579,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.
 @@ -617,6 +625,15 @@
  		    ((ifra->ifra_flags & IN6_IFF_AUTOCONF) != 0);
  		pr0.ndpr_vltime = ifra->ifra_lifetime.ia6t_vltime;
  		pr0.ndpr_pltime = ifra->ifra_lifetime.ia6t_pltime;
 +		if ((error = in6_init_prefix_ltimes(&pr0)) != 0) {
 +			/*
 +			 * Validation for lifetimes should have been done, so
 +			 * this should always succeed.
 +			 */
 +			log(LOG_ERR, "in6_control: failed to initialize prefix"
 +			    " lifetimes\n");
 +			return (error);
 +		}
  
  		/* add the prefix if not yet. */
  		if ((pr = nd6_prefix_lookup(&pr0)) == NULL) {
 @@ -632,48 +649,40 @@
  				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();
 +
  		break;
  	}
  
  	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
 @@ -683,37 +692,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);
  		break;
  	}
  
 @@ -1177,24 +1161,26 @@
  		in6_prefix_remove_ifid(iilen, oia);
  	}
  
 -	/*
 -	 * 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.
Responsible-Changed-From-To: freebsd-net->gnn@freebsd.org 
Responsible-Changed-By: gnn 
Responsible-Changed-When: Thu Oct 14 11:34:13 GMT 2004 
Responsible-Changed-Why:  
Took responsibility for patching and testing this. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=44355 

From: gnn@FreeBSD.org
To: freebsd-gnats-submit@FreeBSD.org, dmitry_bordakov@agilent.com
Cc:  
Subject: Re: kern/44355: After deletion of an IPv6 alias, the route to the whole subnet is removed too.
Date: Sat, 16 Oct 2004 18:11:26 +0900

 Here is a patch against CURRENT for this that I am awaiting approval
 on:
 
 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.
Responsible-Changed-From-To: gnn@freebsd.org->gnn 
Responsible-Changed-By: linimon 
Responsible-Changed-When: Sat Aug 6 18:29:04 GMT 2005 
Responsible-Changed-Why:  
Switch to canonical assignment. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=44355 
State-Changed-From-To: open->feedback 
State-Changed-By: gnn 
State-Changed-When: Thu Jun 22 13:27:06 UTC 2006 
State-Changed-Why:  
Can those who saw this test to see if this is fixed?  The code has been  
in for a while. 


http://www.freebsd.org/cgi/query-pr.cgi?pr=44355 
State-Changed-From-To: feedback->closed 
State-Changed-By: gnn 
State-Changed-When: Mon Jul 10 13:14:09 UTC 2006 
State-Changed-Why:  
Bug fix in HEAD and STABLE branches, no feedback. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=44355 
>Unformatted:
