Index: kernel/linux24/net/ipv6/route.c
===================================================================
RCS file: /cvsroot/usagi/usagi/kernel/linux24/net/ipv6/route.c,v
retrieving revision 1.21
retrieving revision 1.23
diff -u -r1.21 -r1.23
--- kernel/linux24/net/ipv6/route.c	2001/08/19 18:37:42	1.21
+++ kernel/linux24/net/ipv6/route.c	2001/08/22 13:26:40	1.23
@@ -1,4 +1,4 @@
-/* $USAGI: route.c,v 1.21 2001/08/19 18:37:42 yoshfuji Exp $ */
+/* $USAGI: route.c,v 1.23 2001/08/22 13:26:40 yoshfuji Exp $ */
 
 /*
  *	Linux INET6 implementation
@@ -15,6 +15,17 @@
  *      2 of the License, or (at your option) any later version.
  */
 
+/*	Changes:
+ *
+ *	yoshfuji@USAGI
+ *		reworked default router selection.
+ *		- respect outgoing interface
+ *		- select from (probably) reachable routers (i.e.
+ *		routers in REACHABLE, STALE, DELAY or PROBE states).
+ *		- always select the same router if it is (probably)
+ *		reachable.  otherwise, round-robin the list.
+ */
+
 #include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/types.h>
@@ -254,6 +265,7 @@
 		 *	SHOULD round robin
 		 */
 		if (rt6_dflt_pointer) {
+			int ok = 0;
 			for (sprt = rt6_dflt_pointer->u.next;
 			     sprt; sprt = sprt->u.next) {
 				if (sprt->u.dst.obsolete <= 0 &&
@@ -263,25 +275,57 @@
 				}
 			}
 			for (sprt = rt;
-			     !match && sprt && sprt != rt6_dflt_pointer;
-			     sprt = sprt->u.next) {
+			     sprt; sprt = sprt->u.next) {
+				if (sprt == rt6_dflt_pointer) {
+					ok = 1;
+					break;
+				}
+				if (match)
+					continue;
 				if (sprt->u.dst.obsolete <= 0 &&
 				    sprt->u.dst.error == 0) {
 					match = sprt;
 					break;
 				}
+			}
+			if (!ok) {
+				/* rt6_dflt_router is for others */
+				match = NULL;
 			}
-			if (!match)
-				match = rt6_dflt_pointer;	/*XXX*/
 		}
 	}
 
-	if (rt6_dflt_pointer != match)
-		RT6_TRACE1(KERN_INFO 
-				"changed default router: %p->%p\n",
-				rt6_dflt_pointer, match);
-	rt6_dflt_pointer = match;
+	if (match) {
+		if (rt6_dflt_pointer != match)
+			RT6_TRACE1(KERN_INFO 
+					"changed default router: %p->%p\n",
+					rt6_dflt_pointer, match);
+		rt6_dflt_pointer = match;
+	}
 	spin_unlock(&rt6_dflt_lock);
+
+	if (!match) {
+		/*
+		 * Last Resort: if no default routers found, 
+		 * use addrconf default route.
+		 * We don't record this route.
+		 */
+		for (sprt = ip6_routing_table.leaf;
+		     sprt; sprt = sprt->u.next) {
+			if ((sprt->rt6i_flags & RTF_DEFAULT) &&
+			    (!oif ||
+			     (sprt->rt6i_dev &&
+			      sprt->rt6i_dev->ifindex == oif))) {
+				match = sprt;
+				break;
+			}
+		}
+		if (!match) {
+			/* no default route.  give up. */
+			match = &ip6_null_entry;
+		}
+	}
+
 	return match;
 }
 
