summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/netlink.h1
-rw-r--r--include/utils.h1
-rw-r--r--src/libnftables.c7
-rw-r--r--src/mnl.c17
-rw-r--r--src/utils.c5
5 files changed, 26 insertions, 5 deletions
diff --git a/include/netlink.h b/include/netlink.h
index 0d97f71c..d52434c7 100644
--- a/include/netlink.h
+++ b/include/netlink.h
@@ -84,6 +84,7 @@ struct netlink_ctx {
const void *data;
uint32_t seqnum;
struct nftnl_batch *batch;
+ int maybe_emsgsize;
};
extern struct nftnl_expr *alloc_nft_expr(const char *name);
diff --git a/include/utils.h b/include/utils.h
index ffbe2cbb..d5073e06 100644
--- a/include/utils.h
+++ b/include/utils.h
@@ -136,5 +136,6 @@ extern void *xzalloc(size_t size);
extern void *xzalloc_array(size_t nmemb, size_t size);
extern char *xstrdup(const char *s);
extern void xstrunescape(const char *in, char *out);
+extern int round_pow_2(unsigned int value);
#endif /* NFTABLES_UTILS_H */
diff --git a/src/libnftables.c b/src/libnftables.c
index 4f538c44..de16d203 100644
--- a/src/libnftables.c
+++ b/src/libnftables.c
@@ -55,6 +55,13 @@ static int nft_netlink(struct nft_ctx *nft,
ret = mnl_batch_talk(&ctx, &err_list, num_cmds);
if (ret < 0) {
+ if (ctx.maybe_emsgsize && errno == EMSGSIZE) {
+ netlink_io_error(&ctx, NULL,
+ "Could not process rule: %s\n"
+ "Please, rise /proc/sys/net/core/wmem_max on the host namespace. Hint: %d bytes",
+ strerror(errno), round_pow_2(ctx.maybe_emsgsize));
+ goto out;
+ }
netlink_io_error(&ctx, NULL,
"Could not process rule: %s", strerror(errno));
goto out;
diff --git a/src/mnl.c b/src/mnl.c
index 26f943db..ce9e4ee1 100644
--- a/src/mnl.c
+++ b/src/mnl.c
@@ -245,9 +245,10 @@ void mnl_err_list_free(struct mnl_err *err)
xfree(err);
}
-static void mnl_set_sndbuffer(const struct mnl_socket *nl,
- struct nftnl_batch *batch)
+static void mnl_set_sndbuffer(struct netlink_ctx *ctx)
{
+ struct mnl_socket *nl = ctx->nft->nf_sock;
+ struct nftnl_batch *batch = ctx->batch;
socklen_t len = sizeof(int);
int sndnlbuffsiz = 0;
int newbuffsiz;
@@ -260,9 +261,15 @@ static void mnl_set_sndbuffer(const struct mnl_socket *nl,
return;
/* Rise sender buffer length to avoid hitting -EMSGSIZE */
+ setsockopt(mnl_socket_get_fd(nl), SOL_SOCKET, SO_SNDBUF,
+ &newbuffsiz, sizeof(socklen_t));
+
+ /* unpriviledged containers check for CAP_NET_ADMIN on the init_user_ns. */
if (setsockopt(mnl_socket_get_fd(nl), SOL_SOCKET, SO_SNDBUFFORCE,
- &newbuffsiz, sizeof(socklen_t)) < 0)
- return;
+ &newbuffsiz, sizeof(socklen_t)) < 0) {
+ if (errno == EPERM)
+ ctx->maybe_emsgsize = newbuffsiz;
+ }
}
static unsigned int nlsndbufsiz;
@@ -409,7 +416,7 @@ int mnl_batch_talk(struct netlink_ctx *ctx, struct list_head *err_list,
.nl_ctx = ctx,
};
- mnl_set_sndbuffer(ctx->nft->nf_sock, ctx->batch);
+ mnl_set_sndbuffer(ctx);
mnl_nft_batch_to_msg(ctx, &msg, &snl, iov, iov_len);
diff --git a/src/utils.c b/src/utils.c
index 925841c5..a5815018 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -100,3 +100,8 @@ void xstrunescape(const char *in, char *out)
}
out[k++] = '\0';
}
+
+int round_pow_2(unsigned int n)
+{
+ return 1UL << fls(n - 1);
+}