Subject: Re: kern/13311: IPv4 interface alias handling
To: None <undisclosed-recipients>
From: Jun-ichiro itojun Hagino <itojun@itojun.org>
List: tech-net
Date: 07/22/2001 12:07:15
------- Blind-Carbon-Copy

To: gnats-bugs@netbsd.org
Subject: Re: kern/13311: IPv4 interface alias handling
From: Jun-ichiro itojun Hagino <itojun@iijlab.net>
Date: Sun, 22 Jul 2001 12:07:15 +0900
Sender: itojun@itojun.org

	(this is about multiple interface address on the same interface,
	for IPv4 case)

	with the following patch, IFA_ROUTE handling will be much better on
	multiple alias case.

	previous behavior: with the following sequence, you lose 10/8 route.
	# ifconfig wi0 10.0.0.1 alias
	# ifconfig wi0 10.0.0.2 alias
	# ifconfig wi0 10.0.0.1 -alias

	now: 10/8 route will be added and removed only when necessary, and
	rt_ifa of 10/8 route will point to the existing address on the top.

	do people think it worth bringing in?

itojun


*** in.c	Sun Apr 15 01:46:21 2001
- --- /home/itojun/k/kame/netbsd/sys/netinet/in.c	Sun Jul 22 11:14:19 2001
***************
*** 135,136 ****
- --- 135,139 ----
  
+ static int in_addprefix __P((struct in_ifaddr *, int));
+ static int in_scrubprefix __P((struct in_ifaddr *));
+ 
  #ifndef SUBNETSARELOCAL
***************
*** 789,790 ****
- --- 792,796 ----
  
+ #if 1
+ 	in_scrubprefix(ia);
+ #else
  	if ((ia->ia_flags & IFA_ROUTE) == 0)
***************
*** 796,797 ****
- --- 802,804 ----
  	ia->ia_flags &= ~IFA_ROUTE;
+ #endif
  }
***************
*** 876,877 ****
- --- 883,887 ----
  	}
+ #if 1
+ 	error = in_addprefix(ia, flags);
+ #else
  	error = rtinit(&ia->ia_ifa, (int)RTM_ADD, flags);
***************
*** 882,883 ****
- --- 892,894 ----
  		error = 0;
+ #endif
  	/*
***************
*** 907,908 ****
- --- 918,1027 ----
  }
+ 
+ #define rtinitflags(x) \
+ 	(((((x)->ia_ifp->if_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) != 0) && \
+ 	  (x)->ia_dstaddr.sin_family == AF_INET) ? RTF_HOST : 0)
+ 
+ /* (may) add a route to prefix ("connected route" in cisco terminology) */
+ static int
+ in_addprefix(target, flags)
+ 	struct in_ifaddr *target;
+ 	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;
+ 
+ 	for (ia = in_ifaddr.tqh_first; ia; ia = ia->ia_list.tqe_next) {
+ 		/* 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;
+ 
+ 		/*
+ 		 * if we got a matching prefix route inserted by other
+ 		 * interface adderss, we don't need to bother
+ 		 */
+ 		if (ia->ia_flags & IFA_ROUTE)
+ 			return 0;
+ 	}
+ 
+ 	/*
+ 	 * noone seem to have prefix route.  insert it.
+ 	 */
+ 	error = rtinit(&target->ia_ifa, (int)RTM_ADD, flags);
+ 	if (!error)
+ 		target->ia_flags |= IFA_ROUTE;
+ 	return error;
+ }
+ 
+ static int
+ in_scrubprefix(target)
+ 	struct in_ifaddr *target;
+ {
+ 	struct in_ifaddr *ia;
+ 	struct in_addr prefix, mask, p;
+ 	int error;
+ 
+ 	if ((target->ia_flags & IFA_ROUTE) == 0)
+ 		return 0;
+ 
+ 	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;
+ 
+ 	for (ia = in_ifaddr.tqh_first; ia; ia = ia->ia_list.tqe_next) {
+ 		/* 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;
+ 
+ 		/*
+ 		 * if we got a matching prefix route, move IFA_ROUTE to him
+ 		 */
+ 		if ((ia->ia_flags & IFA_ROUTE) == 0) {
+ 			rtinit(&(target->ia_ifa), (int)RTM_DELETE,
+ 			    rtinitflags(target));
+ 			target->ia_flags &= ~IFA_ROUTE;
+ 
+ 			error = rtinit(&ia->ia_ifa, (int)RTM_ADD,
+ 			    rtinitflags(ia) | RTF_UP);
+ 			if (error == 0)
+ 				ia->ia_flags |= IFA_ROUTE;
+ 			return error;
+ 		}
+ 	}
+ 
+ 	/*
+ 	 * noone seem to have prefix route.  remove it.
+ 	 */
+ 	rtinit(&(target->ia_ifa), (int)RTM_DELETE, rtinitflags(target));
+ 	target->ia_flags &= ~IFA_ROUTE;
+ 	return 0;
+ }
+ 
+ #undef rtinitflags
  

------- End of Blind-Carbon-Copy