Subject: in_addprefix() not handling RTF_HOST (pointtopoint) correctly.
To: None <tech-net@netbsd.org>
From: Sean Boudreau <seanb@qnx.com>
List: tech-net
Date: 06/04/2003 10:27:01
On a 1.6 box:


# ifconfig ex0
ex0: flags=8863<UP,BROADCAST,NOTRAILERS,RUNNING,SIMPLEX,MULTICAST> mtu 1500
	capabilities=7<IP4CSUM,TCP4CSUM,UDP4CSUM>
	enabled=0<>
	address: 00:04:75:dc:7e:68
	media: Ethernet autoselect (100baseTX full-duplex)
	status: active
	inet 10.7.0.131 netmask 0xff000000 broadcast 10.255.255.255
	inet6 fe80::204:75ff:fedc:7e68%ex0 prefixlen 64 scopeid 0x2
# ifconfig gif0
gif0: flags=8010<POINTOPOINT,MULTICAST> mtu 1280
# netstat -rnfinet
Routing tables

Internet:
Destination        Gateway            Flags     Refs     Use    Mtu  Interface
10                 link#2             UC          0        0      -  ex0
127                127.0.0.1          UGRS        0        0  33220  lo0
127.0.0.1          127.0.0.1          UH          1        2  33220  lo0
# ifconfig gif0 10.0.0.1 10.0.0.2
# netstat -rnfinet
Routing tables

Internet:
Destination        Gateway            Flags     Refs     Use    Mtu  Interface
10                 link#2             UC          0        0      -  ex0
127                127.0.0.1          UGRS        0        0  33220  lo0
127.0.0.1          127.0.0.1          UH          1        2  33220  lo0
# route add -host -iface 10.0.0.2 10.0.0.1
add host 10.0.0.2: gateway 10.0.0.1

^^^^^^^^^^^^^^^^^
This last step appears to be a regression from 1.5 as on that version
the route is added automatically by the kernel.


Here's a suggested diff:

-seanb



Index: netinet/in.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/in.c,v
retrieving revision 1.76
diff -c -r1.76 in.c
*** netinet/in.c	2002/05/09 06:49:15	1.76
--- netinet/in.c	2003/06/04 14:16:20
***************
*** 897,922 ****
  	int flags;
  {
  	struct in_ifaddr *ia;
! 	struct in_addr prefix, mask, p;
  	int error;
  
  	if ((flags & RTF_HOST) != 0)
  		prefix = target->ia_dstaddr.sin_addr;
! 	else
  		prefix = target->ia_addr.sin_addr;
! 	mask = target->ia_sockmask.sin_addr;
! 	prefix.s_addr &= mask.s_addr;
  
  	TAILQ_FOREACH(ia, &in_ifaddr, ia_list) {
- 		/* easy one first */
- 		if (mask.s_addr != ia->ia_sockmask.sin_addr.s_addr)
- 			continue;
- 
  		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;
  
--- 897,920 ----
  	int flags;
  {
  	struct in_ifaddr *ia;
! 	struct in_addr prefix, p;
  	int error;
  
  	if ((flags & RTF_HOST) != 0)
  		prefix = target->ia_dstaddr.sin_addr;
! 	else {
  		prefix = target->ia_addr.sin_addr;
! 		prefix.s_addr &= target->ia_sockmask.sin_addr.s_addr;
! 	}
  
  	TAILQ_FOREACH(ia, &in_ifaddr, ia_list) {
  		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;
  
***************
*** 947,953 ****
  	struct in_ifaddr *target;
  {
  	struct in_ifaddr *ia;
! 	struct in_addr prefix, mask, p;
  	int error;
  
  	if ((target->ia_flags & IFA_ROUTE) == 0)
--- 945,951 ----
  	struct in_ifaddr *target;
  {
  	struct in_ifaddr *ia;
! 	struct in_addr prefix, p;
  	int error;
  
  	if ((target->ia_flags & IFA_ROUTE) == 0)
***************
*** 955,975 ****
  
  	if (rtinitflags(target))
  		prefix = target->ia_dstaddr.sin_addr;
! 	else
  		prefix = target->ia_addr.sin_addr;
! 	mask = target->ia_sockmask.sin_addr;
! 	prefix.s_addr &= mask.s_addr;
  
  	TAILQ_FOREACH(ia, &in_ifaddr, ia_list) {
- 		/* easy one first */
- 		if (mask.s_addr != ia->ia_sockmask.sin_addr.s_addr)
- 			continue;
- 
  		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;
  
--- 953,971 ----
  
  	if (rtinitflags(target))
  		prefix = target->ia_dstaddr.sin_addr;
! 	else {
  		prefix = target->ia_addr.sin_addr;
! 		prefix.s_addr &= target->ia_sockmask.sin_addr.s_addr;
! 	}
  
  	TAILQ_FOREACH(ia, &in_ifaddr, ia_list) {
  		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;