So I started to play with the routine table and I'm slowly trying to
unify the various code paths to add and delete route entries. The
diff below is a first step, it splits rtinit() into rt_add() and
rt_delete() there should be no functional change.
ok?
Index: net/if.c
===================================================================
RCS file: /cvs/src/sys/net/if.c,v
retrieving revision 1.262
diff -u -p -r1.262 if.c
--- net/if.c 20 Aug 2013 09:14:22 -0000 1.262
+++ net/if.c 27 Aug 2013 13:33:03 -0000
@@ -353,7 +353,7 @@ if_free_sadl(struct ifnet *ifp)
return;
s = splnet();
- rtinit(ifa, RTM_DELETE, 0);
+ rt_del(ifa, 0);
#if 0
ifa_del(ifp, ifa);
ifp->if_lladdr = NULL;
Index: net/route.c
===================================================================
RCS file: /cvs/src/sys/net/route.c,v
retrieving revision 1.144
diff -u -p -r1.144 route.c
--- net/route.c 28 Mar 2013 23:10:05 -0000 1.144
+++ net/route.c 27 Aug 2013 13:33:03 -0000
@@ -1069,11 +1069,10 @@ rt_maskedcopy(struct sockaddr *src, stru
* for an interface.
*/
int
-rtinit(struct ifaddr *ifa, int cmd, int flags)
+rt_add(struct ifaddr *ifa, int flags)
{
struct rtentry *rt;
- struct sockaddr *dst, *deldst;
- struct mbuf *m = NULL;
+ struct sockaddr *dst;
struct rtentry *nrt = NULL;
int error;
struct rt_addrinfo info;
@@ -1081,35 +1080,11 @@ rtinit(struct ifaddr *ifa, int cmd, int
u_short rtableid = ifa->ifa_ifp->if_rdomain;
dst = flags & RTF_HOST ? ifa->ifa_dstaddr : ifa->ifa_addr;
- if (cmd == RTM_DELETE) {
- if ((flags & RTF_HOST) == 0 && ifa->ifa_netmask) {
- m = m_get(M_DONTWAIT, MT_SONAME);
- if (m == NULL)
- return (ENOBUFS);
- deldst = mtod(m, struct sockaddr *);
- rt_maskedcopy(dst, deldst, ifa->ifa_netmask);
- dst = deldst;
- }
- if ((rt = rtalloc1(dst, 0, rtableid)) != NULL) {
- rt->rt_refcnt--;
- /* try to find the right route */
- while (rt && rt->rt_ifa != ifa)
- rt = (struct rtentry *)
- ((struct radix_node *)rt)->rn_dupedkey;
- if (!rt) {
- if (m != NULL)
- (void) m_free(m);
- return (flags & RTF_HOST ? EHOSTUNREACH
- : ENETUNREACH);
- }
- }
- }
bzero(&info, sizeof(info));
info.rti_ifa = ifa;
info.rti_flags = flags | ifa->ifa_flags;
info.rti_info[RTAX_DST] = dst;
- if (cmd == RTM_ADD)
- info.rti_info[RTAX_GATEWAY] = ifa->ifa_addr;
+ info.rti_info[RTAX_GATEWAY] = ifa->ifa_addr;
info.rti_info[RTAX_LABEL] =
rtlabel_id2sa(ifa->ifa_ifp->if_rtlabelid, &sa_rl);
@@ -1120,22 +1095,11 @@ rtinit(struct ifaddr *ifa, int cmd, int
* change it to meet bsdi4 behavior.
*/
info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask;
- error = rtrequest1(cmd, &info, RTP_CONNECTED, &nrt, rtableid);
- if (cmd == RTM_DELETE) {
- if (error == 0 && (rt = nrt) != NULL) {
- rt_newaddrmsg(cmd, ifa, error, nrt);
- if (rt->rt_refcnt <= 0) {
- rt->rt_refcnt++;
- rtfree(rt);
- }
- }
- if (m != NULL)
- (void) m_free(m);
- }
- if (cmd == RTM_ADD && error == 0 && (rt = nrt) != NULL) {
+ error = rtrequest1(RTM_ADD, &info, RTP_CONNECTED, &nrt, rtableid);
+ if (error == 0 && (rt = nrt) != NULL) {
rt->rt_refcnt--;
if (rt->rt_ifa != ifa) {
- printf("rtinit: wrong ifa (%p) was (%p)\n",
+ printf("%s: wrong ifa (%p) was (%p)\n", __func__,
ifa, rt->rt_ifa);
if (rt->rt_ifa->ifa_rtrequest)
rt->rt_ifa->ifa_rtrequest(RTM_DELETE, rt, NULL);
@@ -1146,8 +1110,68 @@ rtinit(struct ifaddr *ifa, int cmd, int
if (ifa->ifa_rtrequest)
ifa->ifa_rtrequest(RTM_ADD, rt, NULL);
}
- rt_newaddrmsg(cmd, ifa, error, nrt);
+ rt_newaddrmsg(RTM_ADD, ifa, error, nrt);
+ }
+
+ return (error);
+}
+
+int
+rt_del(struct ifaddr *ifa, int flags)
+{
+ struct rtentry *rt;
+ struct sockaddr *dst, *deldst;
+ struct mbuf *m = NULL;
+ struct rtentry *nrt = NULL;
+ int error;
+ struct rt_addrinfo info;
+ u_short rtableid = ifa->ifa_ifp->if_rdomain;
+
+ dst = flags & RTF_HOST ? ifa->ifa_dstaddr : ifa->ifa_addr;
+ if ((flags & RTF_HOST) == 0 && ifa->ifa_netmask) {
+ m = m_get(M_DONTWAIT, MT_SONAME);
+ if (m == NULL)
+ return (ENOBUFS);
+ deldst = mtod(m, struct sockaddr *);
+ rt_maskedcopy(dst, deldst, ifa->ifa_netmask);
+ dst = deldst;
}
+ if ((rt = rtalloc1(dst, 0, rtableid)) != NULL) {
+ rt->rt_refcnt--;
+ /* try to find the right route */
+ while (rt && rt->rt_ifa != ifa)
+ rt = (struct rtentry *)
+ ((struct radix_node *)rt)->rn_dupedkey;
+ if (!rt) {
+ if (m != NULL)
+ m_free(m);
+ return (flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH);
+ }
+ }
+
+ bzero(&info, sizeof(info));
+ info.rti_ifa = ifa;
+ info.rti_flags = flags | ifa->ifa_flags;
+ info.rti_info[RTAX_DST] = dst;
+
+ /*
+ * 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(RTM_DELETE, &info, RTP_CONNECTED, &nrt, rtableid);
+ if (error == 0 && (rt = nrt) != NULL) {
+ rt_newaddrmsg(RTM_DELETE, ifa, error, nrt);
+ if (rt->rt_refcnt <= 0) {
+ rt->rt_refcnt++;
+ rtfree(rt);
+ }
+ }
+ if (m != NULL)
+ (void) m_free(m);
+
return (error);
}
Index: net/route.h
===================================================================
RCS file: /cvs/src/sys/net/route.h,v
retrieving revision 1.78
diff -u -p -r1.78 route.h
--- net/route.h 19 Sep 2012 16:14:01 -0000 1.78
+++ net/route.h 27 Aug 2013 13:33:03 -0000
@@ -396,7 +396,8 @@ struct rtentry *
rtalloc1(struct sockaddr *, int, u_int);
void rtfree(struct rtentry *);
int rt_getifa(struct rt_addrinfo *, u_int);
-int rtinit(struct ifaddr *, int, int);
+int rt_add(struct ifaddr *, int);
+int rt_del(struct ifaddr *, int);
int rtioctl(u_long, caddr_t, struct proc *);
void rtredirect(struct sockaddr *, struct sockaddr *,
struct sockaddr *, int, struct sockaddr *,
Index: netinet/in.c
===================================================================
RCS file: /cvs/src/sys/netinet/in.c,v
retrieving revision 1.83
diff -u -p -r1.83 in.c
--- netinet/in.c 19 Aug 2013 08:45:34 -0000 1.83
+++ netinet/in.c 27 Aug 2013 13:33:04 -0000
@@ -323,9 +323,9 @@ in_control(struct socket *so, u_long cmd
}
if (ia->ia_flags & IFA_ROUTE) {
ia->ia_ifa.ifa_dstaddr = sintosa(&oldaddr);
- rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
+ rt_del(&ia->ia_ifa, RTF_HOST);
ia->ia_ifa.ifa_dstaddr = sintosa(&ia->ia_dstaddr);
- rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
+ rt_add(&ia->ia_ifa, RTF_HOST | RTF_UP);
}
splx(s);
break;
@@ -777,8 +777,7 @@ in_addprefix(struct in_ifaddr *target, i
/* move to a real interface instead of carp interface */
if (ia->ia_ifp->if_type == IFT_CARP &&
target->ia_ifp->if_type != IFT_CARP) {
- rtinit(&(ia->ia_ifa), (int)RTM_DELETE,
- rtinitflags(ia));
+ rt_del(&ia->ia_ifa, rtinitflags(ia));
ia->ia_flags &= ~IFA_ROUTE;
break;
}
@@ -793,7 +792,7 @@ in_addprefix(struct in_ifaddr *target, i
/*
* noone seem to have prefix route. insert it.
*/
- error = rtinit(&target->ia_ifa, (int)RTM_ADD, flags);
+ error = rt_add(&target->ia_ifa, flags);
if (!error)
target->ia_flags |= IFA_ROUTE;
return error;
@@ -842,12 +841,10 @@ in_scrubprefix(struct in_ifaddr *target)
* 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));
+ rt_del(&target->ia_ifa, rtinitflags(target));
target->ia_flags &= ~IFA_ROUTE;
- error = rtinit(&ia->ia_ifa, (int)RTM_ADD,
- rtinitflags(ia) | RTF_UP);
+ error = rt_add(&ia->ia_ifa, rtinitflags(ia) | RTF_UP);
if (error == 0)
ia->ia_flags |= IFA_ROUTE;
return error;
@@ -857,7 +854,7 @@ in_scrubprefix(struct in_ifaddr *target)
/*
* noone seem to have prefix route. remove it.
*/
- rtinit(&(target->ia_ifa), (int)RTM_DELETE, rtinitflags(target));
+ rt_del(&target->ia_ifa, rtinitflags(target));
target->ia_flags &= ~IFA_ROUTE;
return 0;
}
Index: netinet6/in6.c
===================================================================
RCS file: /cvs/src/sys/netinet6/in6.c,v
retrieving revision 1.118
diff -u -p -r1.118 in6.c
--- netinet6/in6.c 26 Aug 2013 07:15:58 -0000 1.118
+++ netinet6/in6.c 27 Aug 2013 13:33:04 -0000
@@ -200,7 +200,7 @@ in6_ifloop_request(int cmd, struct ifadd
/*
* Report the addition/removal of the address to the routing socket.
- * XXX: since we called rtinit for a p2p interface with a destination,
+ * XXX: since we called rt_add for a p2p interface with a destination,
* we end up reporting twice in such a case. Should we rather
* omit the second report?
*/
@@ -932,7 +932,7 @@ in6_update_ifa(struct ifnet *ifp, struct
int e;
if ((ia->ia_flags & IFA_ROUTE) != 0 &&
- (e = rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST)) !=
0) {
+ (e = rt_del(&ia->ia_ifa, RTF_HOST)) != 0) {
nd6log((LOG_ERR, "in6_update_ifa: failed to remove "
"a route to the old destination: %s\n",
ip6_sprintf(&ia->ia_addr.sin6_addr)));
@@ -1193,8 +1193,7 @@ in6_purgeaddr(struct ifaddr *ifa)
if ((ia->ia_flags & IFA_ROUTE) != 0 && ia->ia_dstaddr.sin6_len != 0) {
int e;
- if ((e = rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST))
- != 0) {
+ if ((e = rt_del(&ia->ia_ifa, RTF_HOST)) != 0) {
log(LOG_ERR, "in6_purgeaddr: failed to remove "
"a route to the p2p destination: %s on %s, "
"errno=%d\n",
@@ -1535,8 +1534,7 @@ in6_ifinit(struct ifnet *ifp, struct in6
*/
plen = in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL); /* XXX */
if (plen == 128 && ia->ia_dstaddr.sin6_family == AF_INET6) {
- if ((error = rtinit(&(ia->ia_ifa), (int)RTM_ADD,
- RTF_UP | RTF_HOST)) != 0)
+ if ((error = rt_add(&ia->ia_ifa, RTF_UP | RTF_HOST)) != 0)
return (error);
ia->ia_flags |= IFA_ROUTE;
}