summaryrefslogtreecommitdiffstats
path: root/sys/netinet/in_rmx.c
diff options
context:
space:
mode:
authorbz <bz@FreeBSD.org>2010-07-31 15:31:23 +0000
committerbz <bz@FreeBSD.org>2010-07-31 15:31:23 +0000
commitf5ec1d3118207f2f24806692cce1f78fff6d53d3 (patch)
treeb3a3239586b22e5f8040657b6947106fefca5861 /sys/netinet/in_rmx.c
parent9590160d8d4c02cd45076e7dd4e583cde3cdd9e0 (diff)
downloadFreeBSD-src-f5ec1d3118207f2f24806692cce1f78fff6d53d3.zip
FreeBSD-src-f5ec1d3118207f2f24806692cce1f78fff6d53d3.tar.gz
MFp4 @181628:
Free the rtentry after we diconnected it from the FIB and are counting it as rttrash. There might still be a chance we leak it from a different code path but there is nothing we can do about this here. Sponsored by: ISPsystem (in February) Reviewed by: julian (in February) MFC after: 2 weeks
Diffstat (limited to 'sys/netinet/in_rmx.c')
-rw-r--r--sys/netinet/in_rmx.c26
1 files changed, 20 insertions, 6 deletions
diff --git a/sys/netinet/in_rmx.c b/sys/netinet/in_rmx.c
index 5b8e0f6..96406aa 100644
--- a/sys/netinet/in_rmx.c
+++ b/sys/netinet/in_rmx.c
@@ -408,14 +408,28 @@ in_ifadownkill(struct radix_node *rn, void *xap)
if (rt->rt_ifa == ap->ifa &&
(ap->del || !(rt->rt_flags & RTF_STATIC))) {
/*
- * We need to disable the automatic prune that happens
- * in this case in rtrequest() because it will blow
- * away the pointers that rn_walktree() needs in order
- * continue our descent. We will end up deleting all
- * the routes that rtrequest() would have in any case,
- * so that behavior is not needed there.
+ * Aquire a reference so that it can later be freed
+ * as the refcount would be 0 here in case of at least
+ * ap->del.
+ */
+ RT_ADDREF(rt);
+ /*
+ * Disconnect it from the tree and permit protocols
+ * to cleanup.
*/
rtexpunge(rt);
+ /*
+ * At this point it is an rttrash node, and in case
+ * the above is the only reference we must free it.
+ * If we do not noone will have a pointer and the
+ * rtentry will be leaked forever.
+ * In case someone else holds a reference, we are
+ * fine as we only decrement the refcount. In that
+ * case if the other entity calls RT_REMREF, we
+ * will still be leaking but at least we tried.
+ */
+ RTFREE_LOCKED(rt);
+ return (0);
}
RT_UNLOCK(rt);
return 0;
OpenPOWER on IntegriCloud