Subject: sys/net/route.c:rtrequest1() from post-4.4 changes
To: None <tech-net@netbsd.org>
From: Jun-ichiro itojun Hagino <itojun@iijlab.net>
List: tech-net
Date: 01/15/2001 19:52:13
the following patch should introduce two things from post 4.4BSD
changes (found in BSD/OS 4.2, in UCB copyrighted portion):
- sys/net/route.c:rtrequest1()
- sys/net/route.c:rt_getifa()
the idea is to pass rt_addrinfo all the way down to rtrequest1().
if we introduce the following change, we can pass RTAX_IFP with no
problem from routing socket. in effect, the following command should
now honor "-ifp" argument:
# route add -inet6 default ::1 -ifp gif0
at this moment we need two commands to do this.
# route add -inet6 default ::1
# route change -inet6 default ::1 -ifp gif0
does it sound good to introduce the change?
also, we may want to change two more things:
- change 3rd arg to ifa->ifa_rtrequest() to struct rt_addrinfo.
(after checking misteryous use of 3rd arg)
- change calls to rtreqeust() to rtrequest1() as much as possible.
i believe i've already rewrote enough.
itojun
Index: route.c
===================================================================
RCS file: /cvsroot/kame/kame/netbsd/sys/net/route.c,v
retrieving revision 1.10
retrieving revision 1.15
diff -u -r1.10 -r1.15
--- route.c 2000/12/27 09:50:47 1.10
+++ route.c 2001/01/15 10:46:24 1.15
@@ -202,6 +202,17 @@
msgtype = RTM_RESOLVE;
goto miss;
}
+ /* Inform listeners of the new route */
+ bzero(&info, sizeof(info));
+ info.rti_info[RTAX_DST] = rt_key(rt);
+ info.rti_info[RTAX_NETMASK] = rt_mask(rt);
+ info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
+ if (rt->rt_ifp != NULL) {
+ info.rti_info[RTAX_IFP] =
+ rt->rt_ifp->if_addrlist.tqh_first->ifa_addr;
+ info.rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr;
+ }
+ rt_missmsg(RTM_ADD, &info, rt->rt_flags, 0);
} else
rt->rt_refcnt++;
} else {
@@ -317,10 +328,18 @@
* Create new route, rather than smashing route to net.
*/
create:
+ if (rt)
+ rtfree(rt);
flags |= RTF_GATEWAY | RTF_DYNAMIC;
- error = rtrequest((int)RTM_ADD, dst, gateway,
- netmask, flags,
- (struct rtentry **)0);
+ info.rti_info[RTAX_DST] = dst;
+ info.rti_info[RTAX_GATEWAY] = gateway;
+ info.rti_info[RTAX_NETMASK] = netmask;
+ info.rti_ifa = ifa;
+ info.rti_flags = flags;
+ rt = NULL;
+ error = rtrequest1(RTM_ADD, &info, &rt);
+ if (rt != NULL)
+ flags = rt->rt_flags;
stat = &rtstat.rts_dynamic;
} else {
/*
@@ -420,6 +439,70 @@
struct sockaddr *dst, *gateway, *netmask;
struct rtentry **ret_nrt;
{
+ struct rt_addrinfo info;
+
+ bzero(&info, sizeof(info));
+ info.rti_flags = flags;
+ info.rti_info[RTAX_DST] = dst;
+ info.rti_info[RTAX_GATEWAY] = gateway;
+ info.rti_info[RTAX_NETMASK] = netmask;
+ return rtrequest1(req, &info, ret_nrt);
+}
+
+/*
+ * These (questionable) definitions of apparent local variables apply
+ * to the next function. XXXXXX!!!
+ */
+#define dst info->rti_info[RTAX_DST]
+#define gateway info->rti_info[RTAX_GATEWAY]
+#define netmask info->rti_info[RTAX_NETMASK]
+#define ifaaddr info->rti_info[RTAX_IFA]
+#define ifpaddr info->rti_info[RTAX_IFP]
+#define flags info->rti_flags
+
+int
+rt_getifa(info)
+ struct rt_addrinfo *info;
+{
+ struct ifaddr *ifa;
+ int error = 0;
+
+ /*
+ * ifp may be specified by sockaddr_dl when protocol address
+ * is ambiguous
+ */
+ if (info->rti_ifp == NULL && ifpaddr != NULL
+ && ifpaddr->sa_family == AF_LINK &&
+ (ifa = ifa_ifwithnet((struct sockaddr *)ifpaddr)) != NULL)
+ info->rti_ifp = ifa->ifa_ifp;
+ if (info->rti_ifa == NULL && ifaaddr != NULL)
+ info->rti_ifa = ifa_ifwithaddr(ifaaddr);
+ if (info->rti_ifa == NULL) {
+ struct sockaddr *sa;
+
+ sa = ifaaddr != NULL ? ifaaddr :
+ (gateway != NULL ? gateway : dst);
+ if (sa != NULL && info->rti_ifp != NULL)
+ info->rti_ifa = ifaof_ifpforaddr(sa, info->rti_ifp);
+ else if (dst != NULL && gateway != NULL)
+ info->rti_ifa = ifa_ifwithroute(flags, dst, gateway);
+ else if (sa != NULL)
+ info->rti_ifa = ifa_ifwithroute(flags, sa, sa);
+ }
+ if ((ifa = info->rti_ifa) != NULL) {
+ if (info->rti_ifp == NULL)
+ info->rti_ifp = ifa->ifa_ifp;
+ } else
+ error = ENETUNREACH;
+ return (error);
+}
+
+int
+rtrequest1(req, info, ret_nrt)
+ int req;
+ struct rt_addrinfo *info;
+ struct rtentry **ret_nrt;
+{
int s = splsoftnet(); int error = 0;
struct rtentry *rt;
struct radix_node *rn;
@@ -466,8 +549,9 @@
goto makeroute;
case RTM_ADD:
- if ((ifa = ifa_ifwithroute(flags, dst, gateway)) == 0)
- senderr(ENETUNREACH);
+ if (info->rti_ifa == 0 && (error = rt_getifa(info)))
+ senderr(error);
+ ifa = info->rti_ifa;
makeroute:
rt = pool_get(&rtentry_pool, PR_NOWAIT);
if (rt == 0)
@@ -519,6 +603,13 @@
return (error);
}
+#undef dst
+#undef gateway
+#undef netmask
+#undef ifaaddr
+#undef ifpaddr
+#undef flags
+
int
rt_setgate(rt0, dst, gate)
struct rtentry *rt0;
@@ -599,6 +690,7 @@
struct sockaddr_storage deldst;
struct rtentry *nrt = 0;
int error;
+ struct rt_addrinfo info;
dst = flags & RTF_HOST ? ifa->ifa_dstaddr : ifa->ifa_addr;
if (cmd == RTM_DELETE) {
@@ -615,8 +707,19 @@
: ENETUNREACH);
}
}
- error = rtrequest(cmd, dst, ifa->ifa_addr, ifa->ifa_netmask,
- flags | ifa->ifa_flags, &nrt);
+ bzero(&info, sizeof(info));
+ info.rti_ifa = ifa;
+ info.rti_flags = flags | ifa->ifa_flags;
+ info.rti_info[RTAX_DST] = dst;
+ info.rti_info[RTAX_GATEWAY] = ifa->ifa_addr;
+ /*
+ * XXX here, it seems that we are assuming that ifa_netmask is NULL
+ * for RTF_HOST. bsdi4 passes NULL explicitly (via intermediate
+ * variable) when RTF_HOST is 1. still not sure if i can safely
+ * change it to meet bsdi4 behavior.
+ */
+ info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask;
+ error = rtrequest1(cmd, &info, &nrt);
if (cmd == RTM_DELETE && error == 0 && (rt = nrt)) {
rt_newaddrmsg(cmd, ifa, error, nrt);
if (rt->rt_refcnt <= 0) {
Index: route.h
===================================================================
RCS file: /cvsroot/kame/kame/netbsd/sys/net/route.h,v
retrieving revision 1.9
retrieving revision 1.11
diff -u -r1.9 -r1.11
--- route.h 2000/12/27 09:51:18 1.9
+++ route.h 2001/01/15 09:47:14 1.11
@@ -240,6 +240,10 @@
struct rt_addrinfo {
int rti_addrs;
struct sockaddr *rti_info[RTAX_MAX];
+ int rti_flags;
+ struct ifaddr *rti_ifa;
+ struct ifnet *rti_ifp;
+ struct rt_msghdr *rti_rtm;
};
struct route_cb {
@@ -319,12 +323,14 @@
struct rtentry *
rtalloc1 __P((struct sockaddr *, int));
void rtfree __P((struct rtentry *));
+int rt_getifa __P((struct rt_addrinfo *));
int rtinit __P((struct ifaddr *, int, int));
int rtioctl __P((u_long, caddr_t, struct proc *));
void rtredirect __P((struct sockaddr *, struct sockaddr *,
struct sockaddr *, int, struct sockaddr *, struct rtentry **));
int rtrequest __P((int, struct sockaddr *,
struct sockaddr *, struct sockaddr *, int, struct rtentry **));
+int rtrequest1 __P((int, struct rt_addrinfo *, struct rtentry **));
#ifdef MIP6
void rt_mip6msg __P((int, struct ifnet *, struct rtentry *));
Index: rtsock.c
===================================================================
RCS file: /cvsroot/kame/kame/netbsd/sys/net/rtsock.c,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- rtsock.c 2000/12/02 07:30:42 1.10
+++ rtsock.c 2001/01/15 09:47:14 1.11
@@ -221,7 +221,6 @@
so = va_arg(ap, struct socket *);
va_end(ap);
- bzero(&info, sizeof(info));
#define senderr(e) do { error = e; goto flush;} while (0)
if (m == 0 || ((m->m_len < sizeof(int32_t)) &&
(m = m_pullup(m, sizeof(int32_t))) == 0))
@@ -245,8 +244,10 @@
senderr(EPROTONOSUPPORT);
}
rtm->rtm_pid = curproc->p_pid;
+ bzero(&info, sizeof(info));
info.rti_addrs = rtm->rtm_addrs;
rt_xaddrs((caddr_t)(rtm + 1), len + (caddr_t)rtm, &info);
+ info.rti_flags = rtm->rtm_flags;
if (dst == 0 || (dst->sa_family >= AF_MAX))
senderr(EINVAL);
if (gate != 0 && (gate->sa_family >= AF_MAX))
@@ -273,8 +274,7 @@
case RTM_ADD:
if (gate == 0)
senderr(EINVAL);
- error = rtrequest(RTM_ADD, dst, gate, netmask,
- rtm->rtm_flags, &saved_nrt);
+ error = rtrequest1(rtm->rtm_type, &info, &saved_nrt);
if (error == 0 && saved_nrt) {
rt_setmetrics(rtm->rtm_inits,
&rtm->rtm_rmx, &saved_nrt->rt_rmx);
@@ -284,8 +284,7 @@
break;
case RTM_DELETE:
- error = rtrequest(RTM_DELETE, dst, gate, netmask,
- rtm->rtm_flags, &saved_nrt);
+ error = rtrequest1(rtm->rtm_type, &info, &saved_nrt);
if (error == 0) {
(rt = saved_nrt)->rt_refcnt++;
goto report;
@@ -345,6 +344,13 @@
break;
case RTM_CHANGE:
+ /*
+ * new gateway could require new ifaddr, ifp;
+ * flags may also be different; ifp may be specified
+ * by ll sockaddr when protocol address is ambiguous
+ */
+ if ((error = rt_getifa(&info)) != 0)
+ senderr(error);
if (gate && rt_setgate(rt, rt_key(rt), gate))
senderr(EDQUOT);
/* new gateway could require new ifaddr, ifp;