From 0fa364170671643680d4de0caf694f77741e4d36 Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Thu, 18 Dec 2025 10:20:42 -0400 Subject: [PATCH] MT#55283 report netlink errors by seq num Not 100% sure if this is how it's intended to be handled, as the failed requests seem to produce multiple ACK messages, but at least this fixes the immediate problem of the printed error message not matching the request which failed. Closes #2041 Change-Id: I2a6bf57ce996c134b44d4f3484164a39c68fc93c --- daemon/nftables.c | 28 ++++++++++++++-------------- lib/netfilter_api.c | 18 ++++++++++++++---- lib/netfilter_api.h | 2 +- 3 files changed, 29 insertions(+), 19 deletions(-) diff --git a/daemon/nftables.c b/daemon/nftables.c index 5a739c40e..ef999128d 100644 --- a/daemon/nftables.c +++ b/daemon/nftables.c @@ -175,13 +175,13 @@ static char *iterate_rules(nfapi_socket *nl, int family, const char *chain, if (!nfapi_send_buf(nl, b)) return g_strdup_printf("failed to write to netlink socket trying to read rules (%s) " "(attempted: \"%s\")", - strerror(errno), nfapi_buf_msg(b)); + strerror(errno), nfapi_err_msg(nl)); const char *err = nfapi_recv_iter(nl, &(nfapi_callbacks) { .rule = nftables_do_rule }, callbacks); if (err) return g_strdup_printf("error received from netlink socket reading rules (%s): %s " "(attempted: \"%s\")", - strerror(errno), err, nfapi_buf_msg(b)); + strerror(errno), err, nfapi_err_msg(nl)); if (callbacks->iterate_final) { char *e = callbacks->iterate_final(nl, family, chain, callbacks); @@ -219,13 +219,13 @@ static char *delete_rules(nfapi_socket *nl, int family, const char *chain, if (!nfapi_send_buf(nl, b)) return g_strdup_printf("failed to write to netlink socket trying to delete rule (%s) " "(attempted: \"%s\")", - strerror(errno), nfapi_buf_msg(b)); + strerror(errno), nfapi_err_msg(nl)); const char *err = nfapi_recv_iter(nl, NULL, NULL); if (err) return g_strdup_printf("error received from netlink socket trying to delete rule (%s): %s " "(attempted: \"%s\")", - strerror(errno), err, nfapi_buf_msg(b)); + strerror(errno), err, nfapi_err_msg(nl)); return NULL; } @@ -307,7 +307,7 @@ static char *add_chain(nfapi_socket *nl, int family, const char *chain, if (err) return g_strdup_printf("error returned from callback trying to add chain: %s " "(attempted: \"%s\")", - err, nfapi_buf_msg(b)); + err, nfapi_err_msg(nl)); } nfapi_batch_end(b); @@ -315,13 +315,13 @@ static char *add_chain(nfapi_socket *nl, int family, const char *chain, if (!nfapi_send_buf(nl, b)) return g_strdup_printf("failed to write to netlink socket trying to add chain (%s) " "(attempted: \"%s\")", - strerror(errno), nfapi_buf_msg(b)); + strerror(errno), nfapi_err_msg(nl)); const char *err = nfapi_recv_iter(nl, NULL, NULL); if (err) return g_strdup_printf("error received from netlink socket trying to add chain (%s): %s " "(attempted: \"%s\")", - strerror(errno), err, nfapi_buf_msg(b)); + strerror(errno), err, nfapi_err_msg(nl)); return NULL; } @@ -343,20 +343,20 @@ static char *add_rule(nfapi_socket *nl, int family, if (err) return g_strdup_printf("error returned from callback trying to add table: %s " "(attempted: \"%s\")", - err, nfapi_buf_msg(b)); + err, nfapi_err_msg(nl)); nfapi_batch_end(b); if (!nfapi_send_buf(nl, b)) return g_strdup_printf("failed to write to netlink socket trying to add rule (%s) " "(attempted: \"%s\")", - strerror(errno), nfapi_buf_msg(b)); + strerror(errno), nfapi_err_msg(nl)); err = nfapi_recv_iter(nl, NULL, NULL); if (err) return g_strdup_printf("error received from netlink socket trying to add rule (%s): %s " "(attempted: \"%s\")", - strerror(errno), err, nfapi_buf_msg(b)); + strerror(errno), err, nfapi_err_msg(nl)); return NULL; } @@ -625,13 +625,13 @@ static char *delete_chain(nfapi_socket *nl, int family, const char *chain) { if (!nfapi_send_buf(nl, b)) return g_strdup_printf("failed to write to netlink socket trying to delete chain (%s) " "(attempted: \"%s\")", - strerror(errno), nfapi_buf_msg(b)); + strerror(errno), nfapi_err_msg(nl)); const char *err = nfapi_recv_iter(nl, NULL, NULL); if (err) return g_strdup_printf("error received from netlink socket trying to delete chain (%s): %s " "(attempted: \"%s\")", - strerror(errno), err, nfapi_buf_msg(b)); + strerror(errno), err, nfapi_err_msg(nl)); return NULL; } @@ -715,13 +715,13 @@ static char *add_table(nfapi_socket *nl, int family) { if (!nfapi_send_buf(nl, b)) return g_strdup_printf("failed to write to netlink socket trying to add table (%s) " "(attempted: \"%s\")", - strerror(errno), nfapi_buf_msg(b)); + strerror(errno), nfapi_err_msg(nl)); const char *err = nfapi_recv_iter(nl, NULL, NULL); if (err) return g_strdup_printf("error received from netlink socket trying to add table (%s): %s " "(attempted: \"%s\")", - strerror(errno), err, nfapi_buf_msg(b)); + strerror(errno), err, nfapi_err_msg(nl)); return NULL; } diff --git a/lib/netfilter_api.c b/lib/netfilter_api.c index 0f9f093de..15de8f260 100644 --- a/lib/netfilter_api.c +++ b/lib/netfilter_api.c @@ -19,6 +19,8 @@ struct nfapi_socket { int fd; struct sockaddr_nl addr; // local uint16_t seq; + GHashTable *msgs; + uint16_t err_seq; }; struct nfapi_buf { @@ -55,6 +57,7 @@ nfapi_socket *nfapi_socket_open(void) { nfapi_socket *s = g_new0(__typeof(*s), 1); s->fd = fd; s->addr = saddr; + s->msgs = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_free); return s; } @@ -62,9 +65,15 @@ nfapi_socket *nfapi_socket_open(void) { void nfapi_socket_close(nfapi_socket *s) { if (s->fd != -1) close(s->fd); + g_hash_table_destroy(s->msgs); g_free(s); } +const char *nfapi_err_msg(nfapi_socket *s) { + const char *m = g_hash_table_lookup(s->msgs, GUINT_TO_POINTER(s->err_seq)); + return m ?: "?"; +} + nfapi_buf *nfapi_buf_new(nfapi_socket *s) { nfapi_buf *b = g_new0(__typeof(*b), 1); @@ -81,10 +90,6 @@ void nfapi_buf_free(nfapi_buf *b) { g_free(b); } -const char *nfapi_buf_msg(nfapi_buf *b) { - return b->readable->str; -} - static void readable_vadd(GString *r, const char *fmt, va_list va) { if (r->len > 0) @@ -193,6 +198,10 @@ void nfapi_nested_end(nfapi_buf *b) { bool nfapi_send_buf(nfapi_socket *s, nfapi_buf *b) { + char *msg = g_string_free(b->readable, FALSE); + g_hash_table_replace(s->msgs, GUINT_TO_POINTER(b->seq), msg); + b->readable = g_string_new(""); + ssize_t ret = sendto(s->fd, b->s->str, b->s->len, 0, (struct sockaddr *) &zero_nl_sockaddr, sizeof(zero_nl_sockaddr)); if (ret != b->s->len) @@ -285,6 +294,7 @@ const char *nfapi_recv_iter(nfapi_socket *s, const nfapi_callbacks *c, void *use return NULL; errno = -err->error; + s->err_seq = hdr->nlmsg_seq; return "error returned from netlink, see errno"; } else diff --git a/lib/netfilter_api.h b/lib/netfilter_api.h index 6aa946a1d..94b407abe 100644 --- a/lib/netfilter_api.h +++ b/lib/netfilter_api.h @@ -20,11 +20,11 @@ typedef struct { nfapi_socket *nfapi_socket_open(void); void nfapi_socket_close(nfapi_socket *); +const char *nfapi_err_msg(nfapi_socket *); nfapi_buf *nfapi_buf_new(nfapi_socket *); void nfapi_buf_free(nfapi_buf *); -const char *nfapi_buf_msg(nfapi_buf *); __attribute__ ((format(printf, 5, 6))) void nfapi_add_msg(nfapi_buf *, uint16_t type, uint16_t family, uint16_t flags, const char *fmt, ...);