diff options
author | qingli <qingli@FreeBSD.org> | 2009-05-20 21:07:15 +0000 |
---|---|---|
committer | qingli <qingli@FreeBSD.org> | 2009-05-20 21:07:15 +0000 |
commit | e6b86b7c8fc96c72c1f5df5a94c60e96783ecaac (patch) | |
tree | 3c5f22922fbf16f4da56611f23479ce79b4deb12 /sys/netinet6 | |
parent | 803ffe40e141533bd4dd2d51a0c7bd977f855ee7 (diff) | |
download | FreeBSD-src-e6b86b7c8fc96c72c1f5df5a94c60e96783ecaac.zip FreeBSD-src-e6b86b7c8fc96c72c1f5df5a94c60e96783ecaac.tar.gz |
When an interface address is removed and the last prefix
route is also being deleted, the link-layer address table
(arp or nd6) will flush those L2 llinfo entries that match
the removed prefix.
Reviewed by: kmacy
Diffstat (limited to 'sys/netinet6')
-rw-r--r-- | sys/netinet6/in6.c | 25 |
1 files changed, 25 insertions, 0 deletions
diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c index a2321ff..60d56a8 100644 --- a/sys/netinet6/in6.c +++ b/sys/netinet6/in6.c @@ -2284,6 +2284,30 @@ in6_lltable_free(struct lltable *llt, struct llentry *lle) free(lle, M_LLTABLE); } +static void +in6_lltable_prefix_free(struct lltable *llt, + const struct sockaddr *prefix, + const struct sockaddr *mask) +{ + const struct sockaddr_in6 *pfx = (const struct sockaddr_in6 *)prefix; + const struct sockaddr_in6 *msk = (const struct sockaddr_in6 *)mask; + struct llentry *lle, *next; + register int i; + + for (i=0; i < LLTBL_HASHTBL_SIZE; i++) { + LIST_FOREACH_SAFE(lle, &llt->lle_head[i], lle_next, next) { + if (IN6_ARE_MASKED_ADDR_EQUAL( + &((struct sockaddr_in6 *)L3_ADDR(lle))->sin6_addr, + &pfx->sin6_addr, + &msk->sin6_addr)) { + callout_drain(&lle->la_timer); + LLE_WLOCK(lle); + llentry_free(lle); + } + } + } +} + static int in6_lltable_rtcheck(struct ifnet *ifp, const struct sockaddr *l3addr) { @@ -2490,6 +2514,7 @@ in6_domifattach(struct ifnet *ifp) if (ext->lltable != NULL) { ext->lltable->llt_new = in6_lltable_new; ext->lltable->llt_free = in6_lltable_free; + ext->lltable->llt_prefix_free = in6_lltable_prefix_free; ext->lltable->llt_rtcheck = in6_lltable_rtcheck; ext->lltable->llt_lookup = in6_lltable_lookup; ext->lltable->llt_dump = in6_lltable_dump; |