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