With --echo option, regular commands may receive large replies just like 'nft monitor' does. Avoid buffer overruns and message loss by maximizing the global nf_sock's receive buffer size upon creating, not just when calling mnl_nft_event_listener. Error reporting is tricky in nft_mnl_socket_open(), also being warned about failures during receive buffer increase adds little value to the user. So just fail silently instead. Signed-off-by: Phil Sutter <phil@xxxxxx> --- src/mnl.c | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/src/mnl.c b/src/mnl.c index 9bb712adfa3b5..2c5a26a5e3465 100644 --- a/src/mnl.c +++ b/src/mnl.c @@ -33,6 +33,26 @@ #include <utils.h> #include <nftables.h> +#define NFTABLES_NLEVENT_BUFSIZ (1 << 24) + +static void maximize_recv_buffer(struct mnl_socket *nf_sock) +{ + unsigned int bufsiz = NFTABLES_NLEVENT_BUFSIZ; + int fd = mnl_socket_get_fd(nf_sock); + + /* Set netlink socket buffer size to 16 Mbytes to reduce chances of + * message loss due to ENOBUFS. + */ + if (setsockopt(fd, SOL_SOCKET, SO_RCVBUFFORCE, + &bufsiz, sizeof(socklen_t)) < 0) { + /* If this doesn't work, try to reach the system wide maximum + * (or whatever the user requested). + */ + setsockopt(fd, SOL_SOCKET, SO_RCVBUF, + &bufsiz, sizeof(socklen_t)); + } +} + struct mnl_socket *nft_mnl_socket_open(void) { struct mnl_socket *nf_sock; @@ -44,6 +64,7 @@ struct mnl_socket *nft_mnl_socket_open(void) if (fcntl(mnl_socket_get_fd(nf_sock), F_SETFL, O_NONBLOCK)) netlink_init_error(); + maximize_recv_buffer(nf_sock); return nf_sock; } @@ -1379,37 +1400,17 @@ int mnl_nft_flowtable_del(struct netlink_ctx *ctx, const struct cmd *cmd) /* * events */ -#define NFTABLES_NLEVENT_BUFSIZ (1 << 24) int mnl_nft_event_listener(struct mnl_socket *nf_sock, unsigned int debug_mask, struct output_ctx *octx, int (*cb)(const struct nlmsghdr *nlh, void *data), void *cb_data) { - /* Set netlink socket buffer size to 16 Mbytes to reduce chances of - * message loss due to ENOBUFS. - */ - unsigned int bufsiz = NFTABLES_NLEVENT_BUFSIZ; int fd = mnl_socket_get_fd(nf_sock); char buf[NFT_NLMSG_MAXSIZE]; fd_set readfds; int ret; - ret = setsockopt(fd, SOL_SOCKET, SO_RCVBUFFORCE, &bufsiz, - sizeof(socklen_t)); - if (ret < 0) { - /* If this doesn't work, try to reach the system wide maximum - * (or whatever the user requested). - */ - ret = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &bufsiz, - sizeof(socklen_t)); - if (ret < 0) - nft_print(octx, "# Cannot increase netlink socket buffer size, expect message loss\n"); - else - nft_print(octx, "# Cannot set up netlink socket buffer size to %u bytes, falling back to %u bytes\n", - NFTABLES_NLEVENT_BUFSIZ, bufsiz); - } - while (1) { FD_ZERO(&readfds); FD_SET(fd, &readfds); -- 2.21.0