From owner-IPv6-jp@jp.freebsd.org  Mon Jan 31 18:16:54 2000
Received: (from daemon@localhost)
	by castle.jp.freebsd.org (8.9.3+3.2W/8.7.3) id SAA21102;
	Mon, 31 Jan 2000 18:16:54 +0900 (JST)
	(envelope-from owner-IPv6-jp@jp.FreeBSD.org)
Received: from tortoise.jp.freebsd.org (root@tortoise.jp.FreeBSD.ORG [210.157.158.41])
	by castle.jp.freebsd.org (8.9.3+3.2W/8.7.3) with ESMTP id SAA21092
	for <IPv6-jp@jp.freebsd.org>; Mon, 31 Jan 2000 18:16:45 +0900 (JST)
	(envelope-from itojun@itojun.org)
Received: from lychee.itojun.org ([3ffe:507:0:1:200:86ff:fe05:80fa])
	by tortoise.jp.freebsd.org (8.9.3+3.2W/8.7.3) with ESMTP/IPv6 id SAA03724
	for <IPv6-jp@jp.freebsd.org>; Mon, 31 Jan 2000 18:16:40 +0900 (JST)
	(envelope-from itojun@itojun.org)
Received: from kiwi.itojun.org (localhost [127.0.0.1])
	by itojun.org (8.9.3+3.2W/3.7W) with ESMTP id SAA21998
	for <IPv6-jp@jp.freebsd.org>; Mon, 31 Jan 2000 18:16:25 +0900 (JST)
To: IPv6-jp@jp.freebsd.org
In-reply-to: nakagawa's message of Mon, 31 Jan 2000 17:31:05 JST.
      <20000131173105W.nakagawa@kansai.oki.co.jp> 
X-Template-Reply-To: itojun@itojun.org
X-Template-Return-Receipt-To: itojun@itojun.org
X-PGP-Fingerprint: F8 24 B4 2C 8C 98 57 FD  90 5F B4 60 79 54 16 E2
From: Jun-ichiro itojun Hagino <itojun@iijlab.net>
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="----- =_aaaaaaaaaa0"
Content-ID: <21985.949310148.0@lychee.itojun.org>
Date: Mon, 31 Jan 2000 18:16:25 +0900
Message-ID: <21996.949310185@lychee.itojun.org>
Reply-To: IPv6-jp@jp.freebsd.org
Precedence: list
X-Distribute: distribute version 2.1 (Alpha) patchlevel 24e+990727
X-Sequence: IPv6-jp 527
Subject: [IPv6-jp 527] Re: source address selection via gif 
Errors-To: owner-IPv6-jp@jp.freebsd.org
Sender: owner-IPv6-jp@jp.freebsd.org
X-Originator: itojun@itojun.org

------- =_aaaaaaaaaa0
Content-Type: text/plain; charset="iso-2022-jp"
Content-ID: <21985.949310148.1@lychee.itojun.org>
Content-Transfer-Encoding: 7bit

>> $B$3$NLdBj$K4X$7$F$O!"$^$:$O$7$C$+$j$7$?A*Br%]%j%7!<(B($B8@$$49$($l$P2?$r$b$C(B
>> $B$F9,$;$H$9$k$+$N4p=`(B)$B$r7h$a$F!"$=$l$K$7$?$,$C$F<BAu$9$k!"$H$$$&0lHLE*(B
>> $B$J$3$H0J>e$O8@$($J$$$h$&$K;W$$$^$9!#$7$C$+$j$H7h$a$?%]%j%7!<$G$b!"$J$*(B
>> $B9,$;$K$J$l$J$$?M$b$*$=$i$/B8:_$9$k$G$7$g$&!#(B
>$B$O$$!"EvA3$=$&$$$C$?$7$C$+$j$7$?A*Br%]%j%7!<%Y!<%9$N<BAu$K$J$k$3$H$r4|(B
>$BBT$7$F$*$j$^$9!#(B
>$B$H$O$$$(!":#$N$^$^$N%3!<%I$G$O!"2f!9$N$h$&$J(B IPv6 $B=i?4<T$,!"$H$j$"$($:(B
>site-local only $B$G(B IPv6 world $B$KB-$rF'$_F~$l$h$&$H$7$?;~$K$$$-$J$j$O$^$C(B
>$B$F$7$^$&$N$G!"(BIPv6 $BIa5Z$rCY$i$;$kMW0x$K$J$k$N$G$O$J$$$+$H;W$$!"(B*$B:#$N%3!<(B
>$B%I$KHf$Y$l$P(B*$B$A$g$C$H9,$;$K$J$l$k(B patch $B$rEv$F$F$*$1$J$$$+$J$H;W$C$F=q(B
>$B$-$^$7$?!#(B

	$B$H$j$"$($:!"0J2<$N=g$GA*$V(Bpatch$B$G$9!#(B
	- $B=P8}$N%$%s%?%U%'!<%9!"F1$8(Bscope($BJ#?t$"$k$J$i(Blongest match)
	- $B=P8}$N%$%s%?%U%'!<%9!"$h$jBg$-$$(Bscope($B:G8e$K$_$D$1$?$d$D(B = $BE,Ev(B)
	- $B=P8}0J30$N%$%s%?%U%'!<%9!"F1$8(Bscope($BJ#?t$"$k$J$i(Blongest match)
	- $B=P8}0J30$N%$%s%?%U%'!<%9!"$h$jBg$-$$(Bscope($B:G8e$K$_$D$1$?$d$D(B = $BE,Ev(B)
	- (deprecated$B$,5v$5$l$F$$$k$J$i(B) $B=P8}$N%$%s%?%U%'!<%9!"(Bdeprecated
		($B:G8e$K$_$D$1$?$d$D(B = $BE,Ev(B)
	- (deprecated$B$,5v$5$l$F$$$k$J$i(B) $B=P8}0J30$N%$%s%?%U%'!<%9!"(Bdeprecated
		($B:G8e$K$_$D$1$?$d$D(B = $BE,Ev(B)
	$B$3$l$G>/$7$O$7$"$o$;EY$,8~>e$7$^$9$+(B?

	$BA0$b$C$F8@$C$F$*$-$^$9$,!"(B3$BHVL\$H(B4$BHVL\$N>r7o$rK~$?$9$?$a$KA4$F$N(B
	interface address$B$r$J$a$^$9$N$G!"(Bpseudo-device gif 1024$B$H$+$7$F(B
	$B$$$k$R$H$K$OB.EYDc2<$N860x$K$J$jF@$^$9!#(B3$BHVL\$H(B4$BHVL\$N(B
	$B>r7o0J30$O$[$H$s$I$3$l$^$G$HJQ$o$j$^$;$s!#(B

itojun

------- =_aaaaaaaaaa0
Content-Type: text/plain; charset="us-ascii"
Content-ID: <21985.949310148.2@lychee.itojun.org>
Content-Transfer-Encoding: 7bit

Index: in6.c
===================================================================
RCS file: /cvsroot/kame/kame/kame/sys/netinet6/in6.c,v
retrieving revision 1.31
diff -u -r1.31 in6.c
--- in6.c	2000/01/04 17:55:43	1.31
+++ in6.c	2000/01/31 09:11:00
@@ -1914,26 +1914,41 @@
 
 /*
  * return the best address out of the same scope
+ * XXX this function is not draft-ietf-ipngwg-default-addr-select-00 compliant
  */
-
 struct in6_ifaddr *
 in6_ifawithscope(ifp, dst)
 	register struct ifnet *ifp;
 	register struct in6_addr *dst;
 {
-	int dst_scope =	in6_addrscope(dst), blen = -1, tlen;
+	int dst_scope, scope;
+	int blen, tlen;
 	struct ifaddr *ifa;
-	struct in6_ifaddr *besta = NULL, *ia;
+	struct in6_ifaddr *samescope;
+	struct in6_ifaddr *largerscope;
+	struct in6_ifaddr *ia;
 	struct in6_ifaddr *dep[2];	/*last-resort: deprecated*/
 
-	dep[0] = dep[1] = NULL;
+	dst_scope = in6_addrscope(dst);
+	memset(&dep, 0, sizeof(dep));
 
 	/*
-	 * We first look for addresses in the same scope. 
-	 * If there is one, return it.
-	 * If two or more, return one which matches the dst longest.
-	 * If none, return one of global addresses assigned other ifs.
+	 * preferred order:
+	 * 1. same interface, same scope (longest match if there are many)
+	 * 2. same interface, larger scope
+	 * 3. different interface, same scope (longest match if there are many)
+	 * 4. different interface, larger scope
+	 * 5. same interface, deprecated (if allowed)
+	 * 6. different interface, deprecated (if allowed)
+	 *
+	 * XXX 2, 3, and 4 needs debate to death!
+	 *
+	 * We have very similar loop twice.  it is necessary to separate them
+	 * for tons-of-interface host.
 	 */
+
+	samescope = largerscope = NULL;
+
 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
 	for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
 #else
@@ -1949,34 +1964,32 @@
 		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DETACHED)
 			continue;
 		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DEPRECATED) {
-			if (ip6_use_deprecated)
-				dep[0] = (struct in6_ifaddr *)ifa;
+			dep[0] = (struct in6_ifaddr *)ifa;
 			continue;
 		}
 
-		if (dst_scope == in6_addrscope(IFA_IN6(ifa))) {
-			/*
-			 * call in6_matchlen() as few as possible
-			 */
-			if (besta) {
-				if (blen == -1)
-					blen = in6_matchlen(&besta->ia_addr.sin6_addr, dst);
+		scope = in6_addrscope(IFA_IN6(ifa));
+		if (dst_scope == scope) {
+			if (samescope) {
 				tlen = in6_matchlen(IFA_IN6(ifa), dst);
 				if (tlen > blen) {
+					samescope = (struct in6_ifaddr *)ifa;
 					blen = tlen;
-					besta = (struct in6_ifaddr *)ifa;
 				}
-			} else 
-				besta = (struct in6_ifaddr *)ifa;
-		}
+			} else {
+				samescope = (struct in6_ifaddr *)ifa;
+				blen = in6_matchlen(IFA_IN6(ifa), dst);
+			}
+		} else if (dst_scope < scope)
+			largerscope = (struct in6_ifaddr *)ifa;
 	}
-	if (besta)
-		return besta;
+	if (samescope)
+		return samescope;
+	else if (largerscope)
+		return largerscope;
 
+	samescope = largerscope = NULL;
 	for (ia = in6_ifaddr; ia; ia = ia->ia_next) {
-		if (IPV6_ADDR_SCOPE_GLOBAL != 
-		    in6_addrscope(&(ia->ia_addr.sin6_addr)))
-			continue;
 		/* XXX: is there any case to allow anycast? */
 		if ((ia->ia6_flags & IN6_IFF_ANYCAST) != 0)
 			continue;
@@ -1985,18 +1998,48 @@
 		if ((ia->ia6_flags & IN6_IFF_DETACHED) != 0)
 			continue;
 		if ((ia->ia6_flags & IN6_IFF_DEPRECATED) != 0) {
-			if (ip6_use_deprecated)
-				dep[1] = (struct in6_ifaddr *)ifa;
+			dep[1] = (struct in6_ifaddr *)ifa;
 			continue;
+		}
+
+		scope = in6_addrscope(&ia->ia_addr.sin6_addr);
+		switch (scope) {
+		case IPV6_ADDR_SCOPE_LINKLOCAL:
+		case IPV6_ADDR_SCOPE_SITELOCAL:
+			/* XXX exact scope match is required */
+			if (bcmp(&ia->ia_addr.sin6_addr.s6_addr[2],
+			    &dst->s6_addr[2], 2) != 0)
+				continue;
+			break;
+		default:
+			break;
 		}
-		return ia;
+		if (dst_scope == scope) {
+			if (samescope) {
+				tlen = in6_matchlen(IFA_IN6(ifa), dst);
+				if (tlen > blen) {
+					samescope = (struct in6_ifaddr *)ifa;
+					blen = tlen;
+				}
+			} else {
+				samescope = (struct in6_ifaddr *)ia;
+				blen = in6_matchlen(IFA_IN6(ifa), dst);
+			}
+		} else if (dst_scope < scope)
+			largerscope = (struct in6_ifaddr *)ia;
 	}
+	if (samescope)
+		return samescope;
+	else if (largerscope)
+		return largerscope;
 
 	/* use the last-resort values, that are, deprecated addresses */
-	if (dep[0])
-		return dep[0];
-	if (dep[1])
-		return dep[1];
+	if (ip6_use_deprecated) {
+		if (dep[0])
+			return dep[0];
+		if (dep[1])
+			return dep[1];
+	}
 
 	return NULL;
 }

------- =_aaaaaaaaaa0--
