diff options
author | bz <bz@FreeBSD.org> | 2010-04-21 19:51:22 +0000 |
---|---|---|
committer | bz <bz@FreeBSD.org> | 2010-04-21 19:51:22 +0000 |
commit | e36601cbc07715392430d5c4e0028505d13e6466 (patch) | |
tree | d4da6a40cea6c9dca9f4e141d7d26ef6da5190a8 /sys/netinet6/in6.c | |
parent | fbe36a7d8f86f769ca62aef699b956b8af0a83ff (diff) | |
download | FreeBSD-src-e36601cbc07715392430d5c4e0028505d13e6466.zip FreeBSD-src-e36601cbc07715392430d5c4e0028505d13e6466.tar.gz |
MFC r206481:
Plug reference leaks in the link-layer code ("new-arp") that previously
prevented the link-layer entry from being freed.
In both in.c and in6.c (though that code path seems to be basically dead)
plug a reference leak in case of a pending callout being drained.
In if_ether.c consistently add a reference before resetting the callout
and in case we canceled a pending one remove the reference for that.
In the final case in arptimer, before freeing the expired entry, remove
the reference again and explicitly call callout_stop() to clear the active
flag.
In nd6.c:nd6_free() we are only ever called from the callout function and
thus need to remove the reference there as well before calling into
llentry_free().
In if_llatbl.c when freeing the entire tables make sure that in case we
cancel a pending callout to remove the reference as well.
Reviewed by: qingli (earlier version)
MFC after: 10 days
Problem observed, patch tested by: simon on ipv6gw.f.o,
Christian Kratzer (ck cksoft.de),
Evgenii Davidov (dado korolev-net.ru)
PR: kern/144564
Configurations still affected: with options FLOWTABLE
Diffstat (limited to 'sys/netinet6/in6.c')
-rw-r--r-- | sys/netinet6/in6.c | 6 |
1 files changed, 5 insertions, 1 deletions
diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c index 7e5d6d4..1cceb9f 100644 --- a/sys/netinet6/in6.c +++ b/sys/netinet6/in6.c @@ -2337,8 +2337,12 @@ in6_lltable_prefix_free(struct lltable *llt, &((struct sockaddr_in6 *)L3_ADDR(lle))->sin6_addr, &pfx->sin6_addr, &msk->sin6_addr)) { - callout_drain(&lle->la_timer); + int canceled; + + canceled = callout_drain(&lle->la_timer); LLE_WLOCK(lle); + if (canceled) + LLE_REMREF(lle); llentry_free(lle); } } |