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 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 | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/libnetfilter_queue.c b/src/libnetfilter_queue.c index bfb6482..0483780 100644 --- a/src/libnetfilter_queue.c +++ b/src/libnetfilter_queue.c @@ -577,8 +577,30 @@ EXPORT_SYMBOL int nfq_close(struct nfq_handle *h) { int ret; + int i; + + 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); - ret = nfnl_close(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.35.8