diff --git a/sys/net/if_llatbl.c b/sys/net/if_llatbl.c index f934af5d6755..c9b41f9bd376 100644 --- a/sys/net/if_llatbl.c +++ b/sys/net/if_llatbl.c @@ -170,9 +170,12 @@ lltable_free(struct lltable *llt) for (i=0; i < LLTBL_HASHTBL_SIZE; i++) { LIST_FOREACH_SAFE(lle, &llt->lle_head[i], lle_next, next) { + int canceled; - callout_drain(&lle->la_timer); + canceled = callout_drain(&lle->la_timer); LLE_WLOCK(lle); + if (canceled) + LLE_REMREF(lle); llentry_free(lle); } } diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c index 97152a72dbe2..25fba9f10eb1 100644 --- a/sys/netinet/if_ether.c +++ b/sys/netinet/if_ether.c @@ -180,6 +180,8 @@ arptimer(void *arg) else { if (!callout_pending(&lle->la_timer) && callout_active(&lle->la_timer)) { + callout_stop(&lle->la_timer); + LLE_REMREF(lle); (void) llentry_free(lle); ARPSTAT_INC(timeouts); } @@ -382,9 +384,14 @@ retry: EHOSTUNREACH : EHOSTDOWN; if (renew) { + int canceled; + LLE_ADDREF(la); la->la_expire = time_second + V_arpt_down; - callout_reset(&la->la_timer, hz * V_arpt_down, arptimer, la); + canceled = callout_reset(&la->la_timer, hz * V_arpt_down, + arptimer, la); + if (canceled) + LLE_REMREF(la); la->la_asked++; LLE_WUNLOCK(la); arprequest(ifp, NULL, &SIN(dst)->sin_addr, @@ -696,9 +703,14 @@ match: EVENTHANDLER_INVOKE(arp_update_event, la); if (!(la->la_flags & LLE_STATIC)) { + int canceled; + + LLE_ADDREF(la); la->la_expire = time_second + V_arpt_keep; - callout_reset(&la->la_timer, hz * V_arpt_keep, - arptimer, la); + canceled = callout_reset(&la->la_timer, + hz * V_arpt_keep, arptimer, la); + if (canceled) + LLE_REMREF(la); } la->la_asked = 0; la->la_preempt = V_arp_maxtries; diff --git a/sys/netinet/in.c b/sys/netinet/in.c index 319ec953d99b..0a0fe472590c 100644 --- a/sys/netinet/in.c +++ b/sys/netinet/in.c @@ -1357,8 +1357,12 @@ in_lltable_prefix_free(struct lltable *llt, if (IN_ARE_MASKED_ADDR_EQUAL((struct sockaddr_in *)L3_ADDR(lle), pfx, msk)) { - callout_drain(&lle->la_timer); + int canceled; + + canceled = callout_drain(&lle->la_timer); LLE_WLOCK(lle); + if (canceled) + LLE_REMREF(lle); llentry_free(lle); } } diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c index c839efdc8df5..74c15d58a4ae 100644 --- a/sys/netinet6/in6.c +++ b/sys/netinet6/in6.c @@ -2344,8 +2344,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); } } diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c index 5c250f4417b6..a0ef2040de12 100644 --- a/sys/netinet6/nd6.c +++ b/sys/netinet6/nd6.c @@ -1125,6 +1125,7 @@ nd6_free(struct llentry *ln, int gc) ifp = ln->lle_tbl->llt_ifp; IF_AFDATA_LOCK(ifp); LLE_WLOCK(ln); + LLE_REMREF(ln); llentry_free(ln); IF_AFDATA_UNLOCK(ifp);