kern/95031: [patch] routing table doesn't update corectly while adding new interface address

Bartłomiej Leszak fixer at 2a.pl
Tue Mar 28 09:20:18 UTC 2006


>Number:         95031
>Category:       kern
>Synopsis:       [patch] routing table doesn't update corectly while adding new interface address
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue Mar 28 09:20:16 GMT 2006
>Closed-Date:
>Last-Modified:
>Originator:     Bartłomiej Leszak
>Release:        6.0
>Organization:
>Environment:
FreeBSD six.2a.pl 6.0-RELEASE-p4 FreeBSD 6.0-RELEASE-p4 #3: Tue Mar 28 08:41:50 CEST 2006     root at six.2a.pl:/usr/obj/usr/src/sys/SIX  i386
>Description:
While adding new address to the interface the routing table doesn't update if the network address has the same prefix as the existing route. It's not a problem if it's the same interface, but could be really annoying with machines with many interfaces. Problem occurred in 5.4 and later.
>How-To-Repeat:
Add to rc.conf:
ifconfig_em0="inet 10.0.0.91  netmask 255.255.0.0"
ifconfig_em1="inet 10.1.0.1 netmask 255.0.0.0"
reboot, and look at "netstat -nr"
>Fix:
Down the interface and up it again with: ifconfig em0 down && ifconfig em0 up or change your network configuration in the way, that none of the networks will have the same prefixes in the routing table:
ifconfig_em0="inet 10.2.0.91  netmask 255.255.0.0"
ifconfig_em1="inet 10.1.0.1 netmask 255.0.0.0"
for the above.
The problem is that layout of /usr/src/sys/netinet/in.c changed in 5.4. While adding new address to the interace the in_addprefix() function is invoked to update routing table. This function checks only the prefixes in routing table which is correct in most cases.
The code that does it is like this:
>From line 809 in /usr/src/sys/netinet/in.c:
                if (rtinitflags(ia))
                        p = ia->ia_dstaddr.sin_addr;
                else {
                        p = ia->ia_addr.sin_addr;
                        p.s_addr &= ia->ia_sockmask.sin_addr.s_addr;
                }

                if (prefix.s_addr != p.s_addr)
                        continue;
To make it working the check "if (prefix.s_addr != p.s_addr)" needs to be changed to something like this: 
"if ((prefix.s_addr != p.s_addr) | (!((prefix.s_addr == p.s_addr) &&(mask.s_addr == ia->ia_sockmask.sin_addr.s_addr))))"
 to make sure we really don't have the same route.
>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list