Use mnl_close() and clean up the NFNL_SUBSYS_QUEUE subsystem as nfnl_close() would have done Signed-off-by: Duncan Roe <duncan_roe@xxxxxxxxxxxxxxx> --- Changes in v3: manually merge f05b188f8b4c patch Changes in v2: - Propogate return from mnl_socket_close() - Don't free callbacks in the qh_list since nfq_close() didn't (reported as a bug) - Do a complete emulation of nfnl_close() - Add explanatory comments src/libnetfilter_queue.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/libnetfilter_queue.c b/src/libnetfilter_queue.c index b3d1835..8698431 100644 --- a/src/libnetfilter_queue.c +++ b/src/libnetfilter_queue.c @@ -577,6 +577,7 @@ EXPORT_SYMBOL int nfq_close(struct nfq_handle *h) { int ret; + int i; struct nfq_q_handle *qh; while (h->qh_list) { @@ -584,7 +585,29 @@ int nfq_close(struct nfq_handle *h) h->qh_list = qh->next; free(qh); } - ret = nfnl_close(h->nfnlh); + + ret = mnl_socket_close(h->nl); + h->nl = NULL; /* mnl_socket_close() always frees it */ + + /* Replacement code for nfnl_close(). + * It seems unlikely that we need to go through all 16 subsystems + * instead of only subsys[NFNL_SUBSYS_QUEUE] which h->nfnlssh + * conveniently points to, but better safe than sorry. + */ + for (i = 0; i < NFNL_MAX_SUBSYS; i++) { + h->nfnlh->subsys[i].subscriptions = 0; + h->nfnlh->subsys[i].cb_count = 0; + if (h->nfnlh->subsys[i].cb) { + free(h->nfnlh->subsys[i].cb); + h->nfnlh->subsys[i].cb = NULL; + } + } + if (ret == 0) + free(h->nfnlh); + + /* nfnl_close() didn't free nfnlh if close() returned an error. + * Presumably that's why nfq_close() doesn't free h in that case. + */ if (ret == 0) free(h); return ret; -- 2.39.4