diff --git a/include/netlink/utils.h b/include/netlink/utils.h index ac448c5b1..c8b4d2ec5 100644 --- a/include/netlink/utils.h +++ b/include/netlink/utils.h @@ -135,6 +135,14 @@ enum { NL_CAPABILITY_VERSION_3_2_26 = 7, #define NL_CAPABILITY_VERSION_3_2_26 NL_CAPABILITY_VERSION_3_2_26 + /** + * nl_recv() fails with NLE_MSG_TRUNC if a message got truncated + * with NL_MSG_PEEK disabled. Previously, the failed message was wrongly + * discarded and the next message received. + */ + NL_CAPABILITY_NL_RECV_FAIL_TRUNK_NO_PEEK = 8, +#define NL_CAPABILITY_NL_RECV_FAIL_TRUNK_NO_PEEK NL_CAPABILITY_NL_RECV_FAIL_TRUNK_NO_PEEK + __NL_CAPABILITY_MAX, NL_CAPABILITY_MAX = (__NL_CAPABILITY_MAX - 1), #define NL_CAPABILITY_MAX NL_CAPABILITY_MAX diff --git a/lib/nl.c b/lib/nl.c index 8fc9ec104..f06e9a0a3 100644 --- a/lib/nl.c +++ b/lib/nl.c @@ -725,6 +725,13 @@ int nl_recv(struct nl_sock *sk, struct sockaddr_nl *nla, if (iov.iov_len < n || (msg.msg_flags & MSG_TRUNC)) { void *tmp; + + /* respond with error to an incomplete message */ + if (!(sk->s_flags & NL_MSG_PEEK)) { + retval = -NLE_MSG_TRUNC; + goto abort; + } + /* Provided buffer is not long enough, enlarge it * to size of n (which should be total length of the message) * and try again. */ diff --git a/lib/utils.c b/lib/utils.c index 82f14ace5..aa0d1e111 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -1150,7 +1150,7 @@ int nl_has_capability (int capability) NL_CAPABILITY_ROUTE_LINK_GET_KERNEL_FAIL_OPNOTSUPP, NL_CAPABILITY_ROUTE_ADDR_COMPARE_CACHEINFO, NL_CAPABILITY_VERSION_3_2_26, - 0), + NL_CAPABILITY_NL_RECV_FAIL_TRUNK_NO_PEEK), /* IMPORTANT: these capability numbers are intended to be universal and stable * for libnl3. Don't allocate new numbers on your own that differ from upstream * libnl3.