diff --git a/sys/net/pfil.c b/sys/net/pfil.c index 4968bb8cc4de..66448150308f 100644 --- a/sys/net/pfil.c +++ b/sys/net/pfil.c @@ -251,6 +251,7 @@ pfil_head_unregister(pfil_head_t ph) link->link_hook->hook_links--; free(link, M_PFIL); } + free(ph, M_PFIL); PFIL_UNLOCK(); } diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c index 4f0724b7859f..9af3314782c4 100644 --- a/sys/netinet6/in6.c +++ b/sys/netinet6/in6.c @@ -1376,9 +1376,11 @@ in6_purgeifaddr(struct in6_ifaddr *ia) pr = ia->ia6_ndpr; in6_purgeaddr(&ia->ia_ifa); if (pr != NULL && pr->ndpr_addrcnt == 0) { - ND6_WLOCK(); - nd6_prefix_unlink(pr, NULL); - ND6_WUNLOCK(); + if (pr->ndpr_refcnt == 1) {: + ND6_WLOCK(); + nd6_prefix_unlink(pr, NULL); + ND6_WUNLOCK(); + } nd6_prefix_del(pr); } } diff --git a/sys/netinet6/in6_fib_algo.c b/sys/netinet6/in6_fib_algo.c index 04d194273168..ae33161e5f24 100644 --- a/sys/netinet6/in6_fib_algo.c +++ b/sys/netinet6/in6_fib_algo.c @@ -156,9 +156,42 @@ static void lradix6_destroy(void *_data) { struct lradix6_data *lr = (struct lradix6_data *)_data; + int i, j, k; + struct radix6_addr_entry *ae; + /* 2 records per addr entry */ + size_t max_items = lr->num_items * 2; if (lr->rnh != NULL) rn_detachhead((void **)&lr->rnh); + + /* rn_detachhead doesn't clean up all the rn_mklist entries properly. + * Since we know we're done, we can do a second pass here on the flat + * array of nodes to free any pointers when we see them for the first time. + */ + struct radix_mask **mask_list = malloc(max_items * sizeof(void *), M_RTABLE, 0); + memset(mask_list, 0, max_items * sizeof(void *)); + int cur_entry = 0; + for (i = 0; i < lr->num_items; i++) { + ae = (struct radix6_addr_entry *)((char *)lr->radix_mem + + (i * LRADIX6_ITEM_SZ)); + for (j = 0; j < 2; j++) { + if (ae->rn[j].rn_mklist != NULL) { + bool found = false; + for (k = 0; k < cur_entry; k++) { + if (ae->rn[j].rn_mklist == mask_list[k]) { + found = true; + break; + } + } + if (!found) { + free(ae->rn[j].rn_mklist, M_RTABLE); + mask_list[cur_entry++] = ae->rn[j].rn_mklist; + } + } + } + } + free(mask_list, M_RTABLE); + if (lr->mem != NULL) free(lr->mem, M_RTABLE); free(lr, M_RTABLE);