Subject: kern/36966: routed failed to update default route
To: None <kern-bug-people@netbsd.org, gnats-admin@netbsd.org,>
From: Wolfgang Stukenbrock <Wolfgang.Stukenbrock@nagler-company.com>
List: netbsd-bugs
Date: 09/10/2007 14:15:01
>Number:         36966
>Category:       kern
>Synopsis:       routed failed to update default route
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon Sep 10 14:15:00 +0000 2007
>Originator:     Wolfgang Stukenbrock
>Release:        NetBSD 3.1
>Organization:
Dr. Nagler & Company GmbH
	
>Environment:
	
	
System: NetBSD test-s0 3.1 NetBSD 3.1 (test-s0) #0: Tue Apr 3 11:33:43 CEST 2007 root@test-s0:/usr/src/sys/arch/i386/compile/test-s0 i386
Architecture: i386
Machine: i386
>Description:
	If there are multiple Routes that offers a default route, routed
	may try to change the current default entry. It will do it by a call
	with RTM_CHANGE to the routing socket.
	Accedently this will fail with a message like "routed[312]: write(rt_sock) RTM_CHANGE 0.0.0.0         -->172.16.3.1      metric=3 flags=0x2: Too many references: can't splice"
	The problem is located in /usr/src/sys/net/rtsock.c aroud line 305,
	where a call to rn_search() is done. The netmask radix-tree needs a
	specialy prepared netmask-setup to work - e.g. <len>ffffff<mask> for
	IPv4 addresses in the sockaddr structure.
	This problem can be solved by calling rn-addmask(9 in the search mode
	that will do the search and add nothing.
	The problem should not only aply to the default route, because all
	kind of lookups may result here in an invalid mask - dependent on the
	set of other masks in the system ...
>How-To-Repeat:
	setup multiple routes and use routed to manage routing.
>Fix:
	The folloing patch to /usr/src/sys/net/rtsock.c will solve the problem.
	The call to rn_search() has been replaced by a call to rn_addmask().

*** rtsock.c.orig       Fri Sep  7 10:48:54 2007
--- rtsock.c    Mon Sep 10 16:01:43 2007
***************
*** 297,308 ****
                rt->rt_refcnt++;
                if (rtm->rtm_type != RTM_GET) {/* XXX: too grotty */
                        struct radix_node *rn;
-                       extern struct radix_node_head *mask_rnhead;
  
                        if (Bcmp(dst, rt_key(rt), dst->sa_len) != 0)
                                senderr(ESRCH);
!                       if (netmask && (rn = rn_search(netmask,
!                                           mask_rnhead->rnh_treetop)))
                                netmask = (struct sockaddr *)rn->rn_key;
                        for (rn = rt->rt_nodes; rn; rn = rn->rn_dupedkey)
                                if (netmask == (struct sockaddr *)rn->rn_mask)
--- 297,307 ----
                rt->rt_refcnt++;
                if (rtm->rtm_type != RTM_GET) {/* XXX: too grotty */
                        struct radix_node *rn;
  
                        if (Bcmp(dst, rt_key(rt), dst->sa_len) != 0)
                                senderr(ESRCH);
!                       if (netmask && (rn = rn_addmask(netmask, 1,
!                                                rnh->rnh_treetop->rn_off)))
                                netmask = (struct sockaddr *)rn->rn_key;
                        for (rn = rt->rt_nodes; rn; rn = rn->rn_dupedkey)
                                if (netmask == (struct sockaddr *)rn->rn_mask)

>Unformatted: