From Qing.Li@windriver.com  Thu May 30 16:02:08 2002
Return-Path: <Qing.Li@windriver.com>
Received: from mail.wrs.com (unknown-1-11.windriver.com [147.11.1.11])
	by hub.freebsd.org (Postfix) with ESMTP id A00C037B403
	for <FreeBSD-gnats-submit@freebsd.org>; Thu, 30 May 2002 16:02:07 -0700 (PDT)
Received: from heavygear (heavygear [147.11.38.42])
	by mail.wrs.com (8.9.3/8.9.1) with SMTP id QAA00507
	for <FreeBSD-gnats-submit@freebsd.org>; Thu, 30 May 2002 16:00:56 -0700 (PDT)
Message-Id: <DMEGKJAJNLKBGDDBEAIPMEFPFCAA.Qing.Li@windriver.com>
Date: Thu, 30 May 2002 16:01:36 -0700
From: "Qing Li" <Qing.Li@windriver.com>
To: <FreeBSD-gnats-submit@freebsd.org>
Subject: rn_walktree_from not halting at the right node

>Number:         38752
>Category:       kern
>Synopsis:       rn_walktree_from not halting at the right node
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    qingli
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu May 30 16:10:02 PDT 2002
>Closed-Date:    Mon Sep 18 23:14:04 GMT 2006
>Last-Modified:  Mon Sep 18 23:14:04 GMT 2006
>Originator:     Qing Li
>Release:        FreeBSD 4.6-PRERELEASE i386
>Organization:
>Environment:
System: FreeBSD a.b.c 4.6-PRERELEASE FreeBSD 4.6-PRERELEASE #0: Wed May 15
16:17:16 GMT 2002 root@:/usr/obj/usr/src/sys/GENERIC i386

	CPU: Pentium II/Pentium II Xeon/Celeron (265.37-MHz 686-class CPU)
	     Origin = "GenuineIntel"  Id = 0x634  Stepping = 4

Features=0x80f9ff<FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,SEP,MTRR,PGE,MCA,CMOV,M
MX>
	real memory  = 167772160 (163840K bytes)
	avail memory = 158183424 (154476K bytes)

>Description:

      The code in "rn_walktree_from" that checks if we backed up too far
      did not stop at the right node.

	<snip>

        while (!stopping) {
                /* printf("node %p (%d)\n", rn, rn->rn_bit); */
                base = rn;
                /* If at right child go back up, otherwise, go right */
                while (rn->rn_parent->rn_right == rn
                       && !(rn->rn_flags & RNF_ROOT)) {
                        rn = rn->rn_parent;

                        /* if went up beyond last, stop */
                        if (rn->rn_bit < lastb) {
			      ^^^^^^^^^^^^^^^^^^^^^^^
			      |||||||||||||||||||||||
                                stopping = 1;
                                /* printf("up too far\n"); */
                        }
                }

                /* Find the next *leaf* since next node might vanish, too */
                for (rn = rn->rn_parent->rn_right; rn->rn_bit >= 0;)
                        rn = rn->rn_left;

	<snip>

	The IF statement will be true after the complete traversal of
	the right branch of its parent, due to the
	"rn = rn->rn_parent->rn_right" assignment in the following FOR loop.

	One additional problem is the insertion of the default route will
	traverse the entire tree.


>How-To-Repeat:

     Problem 1, Construct the routing tree to shape as the following:

			   ROOT
		           [o]
                            |
                            |
                    [o] ____|_______
                     |
                     |
                     |
       (lastb) [o]------------[o]
                |              |
                |              |
                |              |
           [o]-----{LF}   {LF}------{LF}
            |
            |
            |
     {LF}------{LF}


     Problem 2, enable IPv6, and after system initialization, add
     a default route as in

     route add -net -inet6 default -inet6
fe80::2c0:4fff:fe8d:63b9%xl0 -netmask -inet6 default


>Fix:

*** radix.c	Tue Apr 30 14:09:48 2002
--- radix.c.new	Thu May 30 14:22:44 2002
***************
*** 942,952 ****
  			rn = rn->rn_parent;

  			/* if went up beyond last, stop */
! 			if (rn->rn_bit < lastb) {
  				stopping = 1;
  				/* printf("up too far\n"); */
  			}
  		}

  		/* Find the next *leaf* since next node might vanish, too */
  		for (rn = rn->rn_parent->rn_right; rn->rn_bit >= 0;)
--- 942,955 ----
  			rn = rn->rn_parent;

  			/* if went up beyond last, stop */
! 			if (rn->rn_bit <= lastb) {
  				stopping = 1;
  				/* printf("up too far\n"); */
  			}
  		}
+
+ 		if (rn->rn_parent->rn_flags & RNF_ROOT)
+ 	 	    stopping = 1;

  		/* Find the next *leaf* since next node might vanish, too */
  		for (rn = rn->rn_parent->rn_right; rn->rn_bit >= 0;)














>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->freebsd-net 
Responsible-Changed-By: arved 
Responsible-Changed-When: Thu Aug 26 20:23:36 GMT 2004 
Responsible-Changed-Why:  
Over to freebsd-net for review. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=38752 
Responsible-Changed-From-To: freebsd-net->andre 
Responsible-Changed-By: andre 
Responsible-Changed-When: Thu Aug 26 21:40:24 GMT 2004 
Responsible-Changed-Why:  
Take over. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=38752 
Responsible-Changed-From-To: andre->qingli 
Responsible-Changed-By: andre 
Responsible-Changed-When: Sat Feb 18 16:35:17 UTC 2006 
Responsible-Changed-Why:  
Submittor has become committer.  Let him clean up his own PRs. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=38752 
State-Changed-From-To: open->closed 
State-Changed-By: qingli 
State-Changed-When: Mon Sep 18 23:11:08 UTC 2006 
State-Changed-Why:  
The fix has been made in radix.c version 1.38 o Feb 7 2006. 
The fix was also MFC'd into RELENG_5 and RELENG_6. 


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