On Tue, 2009-03-03 at 22:47 +0000, Roy Marples wrote: > To make ammends, attached is a patch to fix this. It is intended for > pullup to netbsd-5. And here is a different patch. We add a new function, rt_ifa_connected which returns 1 if the route is the connected route (prefix, subnet, etc) for the ifa. This makes the code in rtsock.c and route.c a lot simpler. I've also added some debug messages via the existing RT_DPRINTF define. For reference, I've also added a patch which applies this before my origonal patch was comitted to show the intent of what we're trying to do here. I think this pretty much covers everything now. Anyone have any issues with this before I commit? Thanks Roy
Index: sys/net/route.h
===================================================================
RCS file: /cvsroot/src/sys/net/route.h,v
retrieving revision 1.72
diff -u -p -r1.72 route.h
--- sys/net/route.h 11 Jan 2009 02:45:54 -0000 1.72
+++ sys/net/route.h 9 Mar 2009 09:55:15 -0000
@@ -342,6 +342,7 @@ void rt_ieee80211msg(struct ifnet *, in
void rt_ifmsg(struct ifnet *);
void rt_maskedcopy(const struct sockaddr *,
struct sockaddr *, const struct sockaddr *);
+int rt_ifa_connected(const struct rtentry *, const struct ifaddr *);
void rt_missmsg(int, struct rt_addrinfo *, int, int);
struct mbuf *rt_msg1(int, struct rt_addrinfo *, void *, int);
void rt_newaddrmsg(int, struct ifaddr *, int, struct rtentry *);
Index: sys/net/route.c
===================================================================
RCS file: /cvsroot/src/sys/net/route.c,v
retrieving revision 1.115
diff -u -p -r1.115 route.c
--- sys/net/route.c 20 Feb 2009 10:57:19 -0000 1.115
+++ sys/net/route.c 9 Mar 2009 09:55:15 -0000
@@ -672,8 +672,17 @@ rtrequest1(int req, struct rt_addrinfo *
rt->rt_parent = NULL;
}
rt->rt_flags &= ~RTF_UP;
- if ((ifa = rt->rt_ifa) && ifa->ifa_rtrequest)
- ifa->ifa_rtrequest(RTM_DELETE, rt, info);
+ if ((ifa = rt->rt_ifa)) {
+ if (ifa->ifa_flags & IFA_ROUTE &&
+ rt_ifa_connected(rt, ifa)) {
+ RT_DPRINTF("rt->_rt_key = %p, "
+ "deleted IFA_ROUTE\n",
+ (void *)rt->_rt_key);
+ ifa->ifa_flags &= ~IFA_ROUTE;
+ }
+ if (ifa->ifa_rtrequest)
+ ifa->ifa_rtrequest(RTM_DELETE, rt, info);
+ }
rttrash++;
if (ret_nrt)
*ret_nrt = rt;
@@ -690,9 +699,8 @@ rtrequest1(int req, struct rt_addrinfo *
senderr(EINVAL);
ifa = rt->rt_ifa;
flags = rt->rt_flags & ~(RTF_CLONING | RTF_STATIC);
- flags |= RTF_CLONED;
+ flags |= RTF_CLONED | RTF_HOST;
gateway = rt->rt_gateway;
- flags |= RTF_HOST;
goto makeroute;
case RTM_ADD:
@@ -859,6 +867,30 @@ rt_maskedcopy(const struct sockaddr *src
}
/*
+ * Is this route the connected route for the ifa?
+ */
+int
+rt_ifa_connected(const struct rtentry *rt, const struct ifaddr *ifa)
+{
+ const struct sockaddr *key, *dst, *odst;
+ struct sockaddr_storage maskeddst;
+
+ key = rt_getkey(rt);
+ dst = rt->rt_flags & RTF_HOST ? ifa->ifa_dstaddr : ifa->ifa_addr;
+ if (dst == NULL ||
+ dst->sa_family != key->sa_family ||
+ dst->sa_len != key->sa_len)
+ return 0;
+ if ((rt->rt_flags & RTF_HOST) == 0 && ifa->ifa_netmask) {
+ odst = dst;
+ dst = (struct sockaddr *)&maskeddst;
+ rt_maskedcopy(odst, (struct sockaddr *)&maskeddst,
+ ifa->ifa_netmask);
+ }
+ return (memcmp(dst, key, dst->sa_len) == 0);
+}
+
+/*
* Set up or tear down a routing table entry, normally
* for an interface.
*/
Index: sys/net/rtsock.c
===================================================================
RCS file: /cvsroot/src/sys/net/rtsock.c,v
retrieving revision 1.123
diff -u -p -r1.123 rtsock.c
--- sys/net/rtsock.c 20 Feb 2009 10:54:57 -0000 1.123
+++ sys/net/rtsock.c 9 Mar 2009 09:55:15 -0000
@@ -222,7 +222,7 @@ route_output(struct mbuf *m, ...)
struct rtentry *rt = NULL;
struct rtentry *saved_nrt = NULL;
struct rt_addrinfo info;
- int len, error = 0, ifa_route = 0;
+ int len, error = 0;
struct ifnet *ifp = NULL;
struct ifaddr *ifa = NULL, *oifa;
struct socket *so;
@@ -301,12 +301,6 @@ route_output(struct mbuf *m, ...)
error = rtrequest1(rtm->rtm_type, &info, &saved_nrt);
if (error == 0) {
(rt = saved_nrt)->rt_refcnt++;
- ifa = rt_get_ifa(rt);
- /*
- * If deleting an automatic route, scrub the flag.
- */
- if (ifa->ifa_flags & IFA_ROUTE)
- ifa->ifa_flags &= ~IFA_ROUTE;
goto report;
}
break;
@@ -360,12 +354,12 @@ route_output(struct mbuf *m, ...)
if (info.rti_info[RTAX_IFA]->sa_family ==
AF_INET) {
printf("%s: copying out RTAX_IFA %s ",
- __func__, inet_ntoa(
+ __func__, inet_ntoa((
(const struct sockaddr_in *)
- info.rti_info[RTAX_IFA])->sin_addr);
+
info.rti_info[RTAX_IFA])->sin_addr));
printf("for info.rti_info[RTAX_DST] %s "
"ifa_getifa %p ifa_seqno %p\n",
- inet_ntoa(
+ inet_ntoa((
(const struct sockaddr_in *)
info.rti_info[RTAX_DST])->sin_addr),
(void *)rtifa->ifa_getifa,
@@ -425,30 +419,26 @@ route_output(struct mbuf *m, ...)
ifp = ifa->ifa_ifp;
}
oifa = rt->rt_ifa;
- if (oifa && oifa->ifa_flags & IFA_ROUTE) {
- /*
- * If changing an automatically added route,
- * remove the flag and store the fact.
- */
- oifa->ifa_flags &= ~IFA_ROUTE;
- ifa_route = 1;
- }
- if (ifa) {
- if (oifa != ifa) {
- if (oifa && oifa->ifa_rtrequest) {
- oifa->ifa_rtrequest(RTM_DELETE,
- rt, &info);
- }
- /*
- * If changing an automatically added
- * route, store this if not static.
- */
- if (ifa_route &&
- !(rt->rt_flags & RTF_STATIC))
+ if (ifa && oifa != ifa) {
+ if (oifa && oifa->ifa_rtrequest)
+ oifa->ifa_rtrequest(RTM_DELETE,
+ rt, &info);
+ if (oifa && oifa->ifa_flags & IFA_ROUTE &&
+ rt_ifa_connected(rt, oifa))
+ {
+ RT_DPRINTF("rt->_rt_key = %p, "
+ "change deleted IFA_ROUTE\n",
+ (void *)rt->_rt_key);
+ oifa->ifa_flags &= ~IFA_ROUTE;
+ if (rt_ifa_connected(rt, ifa)) {
+ RT_DPRINTF("rt->_rt_key = %p, "
+ "change added IFA_ROUTE\n",
+ (void *)rt->_rt_key);
ifa->ifa_flags |= IFA_ROUTE;
- rt_replace_ifa(rt, ifa);
- rt->rt_ifp = ifp;
+ }
}
+ rt_replace_ifa(rt, ifa);
+ rt->rt_ifp = ifp;
}
rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx,
&rt->rt_rmx);
Index: sys/netinet/in.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/in.c,v
retrieving revision 1.131
diff -u -p -r1.131 in.c
--- sys/netinet/in.c 12 Feb 2009 19:05:36 -0000 1.131
+++ sys/netinet/in.c 9 Mar 2009 09:55:15 -0000
@@ -993,16 +993,13 @@ in_addprefix(struct in_ifaddr *target, i
/*
* noone seem to have prefix route. insert it.
+ * if it already exists, don't report back an error.
*/
error = rtinit(&target->ia_ifa, RTM_ADD, flags);
if (error == 0)
target->ia_flags |= IFA_ROUTE;
- else if (error == EEXIST) {
- /*
- * the fact the route already exists is not an error.
- */
- error = 0;
- }
+ else if (error == EEXIST)
+ return 0;
return error;
}
Index: sys/net/route.h
===================================================================
RCS file: /cvsroot/src/sys/net/route.h,v
retrieving revision 1.72
diff -u -p -r1.72 route.h
--- sys/net/route.h 11 Jan 2009 02:45:54 -0000 1.72
+++ sys/net/route.h 9 Mar 2009 10:02:23 -0000
@@ -342,6 +342,7 @@ void rt_ieee80211msg(struct ifnet *, in
void rt_ifmsg(struct ifnet *);
void rt_maskedcopy(const struct sockaddr *,
struct sockaddr *, const struct sockaddr *);
+int rt_ifa_connected(const struct rtentry *, const struct ifaddr *);
void rt_missmsg(int, struct rt_addrinfo *, int, int);
struct mbuf *rt_msg1(int, struct rt_addrinfo *, void *, int);
void rt_newaddrmsg(int, struct ifaddr *, int, struct rtentry *);
Index: sys/net/route.c
===================================================================
RCS file: /cvsroot/src/sys/net/route.c,v
retrieving revision 1.115
diff -u -p -r1.115 route.c
--- sys/net/route.c 20 Feb 2009 10:57:19 -0000 1.115
+++ sys/net/route.c 9 Mar 2009 10:02:42 -0000
@@ -672,8 +672,17 @@ rtrequest1(int req, struct rt_addrinfo *
rt->rt_parent = NULL;
}
rt->rt_flags &= ~RTF_UP;
- if ((ifa = rt->rt_ifa) && ifa->ifa_rtrequest)
- ifa->ifa_rtrequest(RTM_DELETE, rt, info);
+ if ((ifa = rt->rt_ifa)) {
+ if (ifa->ifa_flags & IFA_ROUTE &&
+ rt_ifa_connected(rt, ifa)) {
+ RT_DPRINTF("rt->_rt_key = %p, "
+ "deleted IFA_ROUTE\n",
+ (void *)rt->_rt_key);
+ ifa->ifa_flags &= ~IFA_ROUTE;
+ }
+ if (ifa->ifa_rtrequest)
+ ifa->ifa_rtrequest(RTM_DELETE, rt, info);
+ }
rttrash++;
if (ret_nrt)
*ret_nrt = rt;
@@ -690,9 +699,8 @@ rtrequest1(int req, struct rt_addrinfo *
senderr(EINVAL);
ifa = rt->rt_ifa;
flags = rt->rt_flags & ~(RTF_CLONING | RTF_STATIC);
- flags |= RTF_CLONED;
+ flags |= RTF_CLONED | RTF_HOST;
gateway = rt->rt_gateway;
- flags |= RTF_HOST;
goto makeroute;
case RTM_ADD:
@@ -859,6 +867,30 @@ rt_maskedcopy(const struct sockaddr *src
}
/*
+ * Is this route the connected route for the ifa?
+ */
+int
+rt_ifa_connected(const struct rtentry *rt, const struct ifaddr *ifa)
+{
+ const struct sockaddr *key, *dst, *odst;
+ struct sockaddr_storage maskeddst;
+
+ key = rt_getkey(rt);
+ dst = rt->rt_flags & RTF_HOST ? ifa->ifa_dstaddr : ifa->ifa_addr;
+ if (dst == NULL ||
+ dst->sa_family != key->sa_family ||
+ dst->sa_len != key->sa_len)
+ return 0;
+ if ((rt->rt_flags & RTF_HOST) == 0 && ifa->ifa_netmask) {
+ odst = dst;
+ dst = (struct sockaddr *)&maskeddst;
+ rt_maskedcopy(odst, (struct sockaddr *)&maskeddst,
+ ifa->ifa_netmask);
+ }
+ return (memcmp(dst, key, dst->sa_len) == 0);
+}
+
+/*
* Set up or tear down a routing table entry, normally
* for an interface.
*/
Index: sys/net/rtsock.c
===================================================================
RCS file: /cvsroot/src/sys/net/rtsock.c,v
retrieving revision 1.118
diff -u -p -r1.118 rtsock.c
--- sys/net/rtsock.c 17 Dec 2008 20:51:37 -0000 1.118
+++ sys/net/rtsock.c 9 Mar 2009 10:03:54 -0000
@@ -215,7 +224,7 @@ route_output(struct mbuf *m, ...)
struct rt_addrinfo info;
int len, error = 0;
struct ifnet *ifp = NULL;
- struct ifaddr *ifa = NULL;
+ struct ifaddr *ifa = NULL, *oifa;
struct socket *so;
va_list ap;
sa_family_t family;
@@ -345,12 +354,12 @@ route_output(struct mbuf *m, ...)
if (info.rti_info[RTAX_IFA]->sa_family ==
AF_INET) {
printf("%s: copying out RTAX_IFA %s ",
- __func__, inet_ntoa(
+ __func__, inet_ntoa((
(const struct sockaddr_in *)
- info.rti_info[RTAX_IFA])->sin_addr);
+
info.rti_info[RTAX_IFA])->sin_addr));
printf("for info.rti_info[RTAX_DST] %s "
"ifa_getifa %p ifa_seqno %p\n",
- inet_ntoa(
+ inet_ntoa((
(const struct sockaddr_in *)
info.rti_info[RTAX_DST])->sin_addr),
(void *)rtifa->ifa_getifa,
@@ -409,16 +418,27 @@ route_output(struct mbuf *m, ...)
rt_getkey(rt), info.rti_info[RTAX_GATEWAY])))) {
ifp = ifa->ifa_ifp;
}
- if (ifa) {
- struct ifaddr *oifa = rt->rt_ifa;
- if (oifa != ifa) {
- if (oifa && oifa->ifa_rtrequest) {
- oifa->ifa_rtrequest(RTM_DELETE,
- rt, &info);
+ oifa = rt->rt_ifa;
+ if (ifa && oifa != ifa) {
+ if (oifa && oifa->ifa_rtrequest)
+ oifa->ifa_rtrequest(RTM_DELETE,
+ rt, &info);
+ if (oifa && oifa->ifa_flags & IFA_ROUTE &&
+ rt_ifa_connected(rt, oifa))
+ {
+ RT_DPRINTF("rt->_rt_key = %p, "
+ "change deleted IFA_ROUTE\n",
+ (void *)rt->_rt_key);
+ oifa->ifa_flags &= ~IFA_ROUTE;
+ if (rt_ifa_connected(rt, ifa)) {
+ RT_DPRINTF("rt->_rt_key = %p, "
+ "change added IFA_ROUTE\n",
+ (void *)rt->_rt_key);
+ ifa->ifa_flags |= IFA_ROUTE;
}
- rt_replace_ifa(rt, ifa);
- rt->rt_ifp = ifp;
}
+ rt_replace_ifa(rt, ifa);
+ rt->rt_ifp = ifp;
}
rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx,
&rt->rt_rmx);
Index: sys/netinet/in.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/in.c,v
retrieving revision 1.129
diff -u -p -r1.129 in.c
--- sys/netinet/in.c 17 Dec 2008 20:51:37 -0000 1.129
+++ sys/netinet/in.c 9 Mar 2009 10:06:17 -0000
@@ -1000,10 +993,13 @@ in_addprefix(struct in_ifaddr *target, i
/*
* noone seem to have prefix route. insert it.
+ * if it already exists, don't report back an error.
*/
error = rtinit(&target->ia_ifa, RTM_ADD, flags);
if (error == 0)
target->ia_flags |= IFA_ROUTE;
+ else if (error == EEXIST)
+ return 0;
return error;
}
Attachment:
signature.asc
Description: This is a digitally signed message part