Do not always try to rtfree(9) route entries inside rtdeletemsg(9).
authormpi <mpi@openbsd.org>
Mon, 26 Jan 2015 11:36:38 +0000 (11:36 +0000)
committermpi <mpi@openbsd.org>
Mon, 26 Jan 2015 11:36:38 +0000 (11:36 +0000)
Instead check the error code returned by this function and let the
caller free the route entry when appropriate.

ok bluhm@

sys/net/route.c
sys/netinet/if_ether.c

index 640e523..6fd74df 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: route.c,v 1.201 2015/01/21 21:32:42 bluhm Exp $       */
+/*     $OpenBSD: route.c,v 1.202 2015/01/26 11:36:38 mpi Exp $ */
 /*     $NetBSD: route.c,v 1.14 1996/02/13 22:00:46 christos Exp $      */
 
 /*
@@ -544,11 +544,6 @@ rtdeletemsg(struct rtentry *rt, u_int tableid)
 
        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;
 }
 
@@ -1631,8 +1634,17 @@ rt_if_remove_rtdelete(struct radix_node *rn, void *vifp, u_int id)
        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 0145883..6ff4877 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if_ether.c,v 1.141 2015/01/13 12:16:18 mpi Exp $      */
+/*     $OpenBSD: if_ether.c,v 1.142 2015/01/26 11:36:38 mpi Exp $      */
 /*     $NetBSD: if_ether.c,v 1.31 1996/05/11 12:59:58 mycroft Exp $    */
 
 /*
@@ -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);
+       }
 }
 
 /*