On 19/01/15(Mon) 09:35, Todd C. Miller wrote:
> On Mon, 19 Jan 2015 11:49:53 +0100, Martin Pieuchot wrote:
>
> > Instead of rerolling rtrequest1(RTM_DELETE...) code in various places,
> > simply use rtdeletemsg() which also notify userland that the route entry
> > is going away.
>
> Since rtdeletemsg() may call rtfree() doesn't this mean that we can
> end up calling rtfree() twice? Or is rt->rt_refcnt never going to
> be zero in this case?
It is indeed confusing. I tried to check every cases but in the end I
think that it might be better to decouple the removal from the routing
table and the rtfree(). Updated diff below does that.
Another advantage I can see to this approach is to be more strict about
the reference counter on a per-rt basic.
Index: net/route.c
===================================================================
RCS file: /home/ncvs/src/sys/net/route.c,v
retrieving revision 1.200
diff -u -p -r1.200 route.c
--- net/route.c 18 Jan 2015 14:51:43 -0000 1.200
+++ net/route.c 21 Jan 2015 12:17:21 -0000
@@ -544,11 +544,6 @@ rtdeletemsg(struct rtentry *rt, u_int ta
rt_missmsg(RTM_DELETE, &info, info.rti_flags, ifp, error, tableid);
- /* Adjust the refcount */
- if (error == 0 && rt->rt_refcnt <= 0) {
- rt->rt_refcnt++;
- rtfree(rt);
- }
return (error);
}
@@ -556,11 +551,19 @@ int
rtflushclone1(struct radix_node *rn, void *arg, u_int id)
{
struct rtentry *rt, *parent;
+ int error;
rt = (struct rtentry *)rn;
parent = (struct rtentry *)arg;
- if ((rt->rt_flags & RTF_CLONED) != 0 && rt->rt_parent == parent)
- rtdeletemsg(rt, id);
+ if ((rt->rt_flags & RTF_CLONED) != 0 && rt->rt_parent == parent) {
+ error = rtdeletemsg(rt, id);
+
+ /* Adjust the refcount */
+ if (error == 0 && rt->rt_refcnt <= 0) {
+ rt->rt_refcnt++;
+ rtfree(rt);
+ }
+ }
return 0;
}
@@ -1632,8 +1635,17 @@ rt_if_remove_rtdelete(struct radix_node
if (rt->rt_ifp == ifp) {
int cloning = (rt->rt_flags & RTF_CLONING);
- if (rtdeletemsg(rt, id) == 0 && cloning)
- return (EAGAIN);
+ if (rtdeletemsg(rt, id) == 0) {
+
+ /* Adjust the refcount */
+ if (rt->rt_refcnt <= 0) {
+ rt->rt_refcnt++;
+ rtfree(rt);
+ }
+
+ if (cloning)
+ return (EAGAIN);
+ }
}
/*
Index: netinet/if_ether.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/if_ether.c,v
retrieving revision 1.141
diff -u -p -r1.141 if_ether.c
--- netinet/if_ether.c 13 Jan 2015 12:16:18 -0000 1.141
+++ netinet/if_ether.c 21 Jan 2015 12:17:21 -0000
@@ -789,6 +789,7 @@ arptfree(struct llinfo_arp *la)
struct rtentry *rt = la->la_rt;
struct sockaddr_dl *sdl;
u_int tid = 0;
+ int error;
if (rt == NULL)
panic("arptfree");
@@ -803,7 +804,13 @@ arptfree(struct llinfo_arp *la)
if (rt->rt_ifp)
tid = rt->rt_ifp->if_rdomain;
- rtdeletemsg(rt, tid);
+ error = rtdeletemsg(rt, tid);
+
+ /* Adjust the refcount */
+ if (error == 0 && rt->rt_refcnt <= 0) {
+ rt->rt_refcnt++;
+ rtfree(rt);
+ }
}
/*
Index: netinet/ip_icmp.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/ip_icmp.c,v
retrieving revision 1.129
diff -u -p -r1.129 ip_icmp.c
--- netinet/ip_icmp.c 22 Dec 2014 11:05:53 -0000 1.129
+++ netinet/ip_icmp.c 21 Jan 2015 12:17:21 -0000
@@ -1031,20 +1031,12 @@ icmp_mtudisc_timeout(struct rtentry *rt,
(RTF_DYNAMIC | RTF_HOST)) {
void *(*ctlfunc)(int, struct sockaddr *, u_int, void *);
struct sockaddr_in sa;
- struct rt_addrinfo info;
int s;
- memset(&info, 0, 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;
- info.rti_flags = rt->rt_flags;
-
sa = *(struct sockaddr_in *)rt_key(rt);
s = splsoftnet();
- rtrequest1(RTM_DELETE, &info, rt->rt_priority, NULL,
- r->rtt_tableid);
+ rtdeletemsg(rt, r->rtt_tableid);
/* Notify TCP layer of increased Path MTU estimate */
ctlfunc = inetsw[ip_protox[IPPROTO_TCP]].pr_ctlinput;
@@ -1083,18 +1075,10 @@ icmp_redirect_timeout(struct rtentry *rt
if ((rt->rt_flags & (RTF_DYNAMIC | RTF_HOST)) ==
(RTF_DYNAMIC | RTF_HOST)) {
- struct rt_addrinfo info;
int s;
- memset(&info, 0, 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;
- info.rti_flags = rt->rt_flags;
-
s = splsoftnet();
- rtrequest1(RTM_DELETE, &info, rt->rt_priority, NULL,
- r->rtt_tableid);
+ rtdeletemsg(rt, r->rtt_tableid);
splx(s);
}
}
Index: netinet6/icmp6.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet6/icmp6.c,v
retrieving revision 1.153
diff -u -p -r1.153 icmp6.c
--- netinet6/icmp6.c 19 Jan 2015 13:53:55 -0000 1.153
+++ netinet6/icmp6.c 21 Jan 2015 12:17:21 -0000
@@ -1983,18 +1983,10 @@ icmp6_mtudisc_timeout(struct rtentry *rt
panic("icmp6_mtudisc_timeout: bad route to timeout");
if ((rt->rt_flags & (RTF_DYNAMIC | RTF_HOST)) ==
(RTF_DYNAMIC | RTF_HOST)) {
- struct rt_addrinfo info;
int s;
- bzero(&info, sizeof(info));
- info.rti_flags = rt->rt_flags;
- info.rti_info[RTAX_DST] = rt_key(rt);
- info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
- info.rti_info[RTAX_NETMASK] = rt_mask(rt);
-
s = splsoftnet();
- rtrequest1(RTM_DELETE, &info, rt->rt_priority, NULL,
- r->rtt_tableid);
+ rtdeletemsg(rt, r->rtt_tableid);
splx(s);
} else {
if (!(rt->rt_rmx.rmx_locks & RTV_MTU))
@@ -2009,18 +2001,10 @@ icmp6_redirect_timeout(struct rtentry *r
panic("icmp6_redirect_timeout: bad route to timeout");
if ((rt->rt_flags & (RTF_GATEWAY | RTF_DYNAMIC | RTF_HOST)) ==
(RTF_GATEWAY | RTF_DYNAMIC | RTF_HOST)) {
- struct rt_addrinfo info;
int s;
- bzero(&info, sizeof(info));
- info.rti_flags = rt->rt_flags;
- info.rti_info[RTAX_DST] = rt_key(rt);
- info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
- info.rti_info[RTAX_NETMASK] = rt_mask(rt);
-
s = splsoftnet();
- rtrequest1(RTM_DELETE, &info, rt->rt_priority, NULL,
- r->rtt_tableid);
+ rtdeletemsg(rt, r->rtt_tableid);
splx(s);
}
}
Index: netinet6/in6_ifattach.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet6/in6_ifattach.c,v
retrieving revision 1.81
diff -u -p -r1.81 in6_ifattach.c
--- netinet6/in6_ifattach.c 10 Jan 2015 11:43:37 -0000 1.81
+++ netinet6/in6_ifattach.c 21 Jan 2015 12:17:21 -0000
@@ -666,15 +666,7 @@ in6_ifdetach(struct ifnet *ifp)
sin6.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
rt = rtalloc(sin6tosa(&sin6), 0, ifp->if_rdomain);
if (rt && rt->rt_ifp == ifp) {
- struct rt_addrinfo info;
-
- bzero(&info, sizeof(info));
- info.rti_flags = rt->rt_flags;
- info.rti_info[RTAX_DST] = rt_key(rt);
- info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
- info.rti_info[RTAX_NETMASK] = rt_mask(rt);
- rtrequest1(RTM_DELETE, &info, rt->rt_priority, NULL,
- ifp->if_rdomain);
+ rtdeletemsg(rt, ifp->if_rdomain);
rtfree(rt);
}
@@ -686,15 +678,7 @@ in6_ifdetach(struct ifnet *ifp)
sin6.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
rt = rtalloc(sin6tosa(&sin6), 0, ifp->if_rdomain);
if (rt && rt->rt_ifp == ifp) {
- struct rt_addrinfo info;
-
- bzero(&info, sizeof(info));
- info.rti_flags = rt->rt_flags;
- info.rti_info[RTAX_DST] = rt_key(rt);
- info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
- info.rti_info[RTAX_NETMASK] = rt_mask(rt);
- rtrequest1(RTM_DELETE, &info, rt->rt_priority, NULL,
- ifp->if_rdomain);
+ rtdeletemsg(rt, ifp->if_rdomain);
rtfree(rt);
}