Skip to content

Commit

Permalink
net: sockets: Update msg_controllen in recvmsg properly
Browse files Browse the repository at this point in the history
According to recvmsg man page, msg_controllen should be set to the sum
of the length of all control messages in the buffer.
This is missing from the current recvmsg implementation.
This commit aims to fix this by updating msg_controllen each time control
data are added to the buffer.
This commit also fixes cases where the msg_controllen is cleared
incorrectly.

Fixes zephyrproject-rtos#77303

Signed-off-by: Axel Le Bourhis <axel.lebourhis@nxp.com>
  • Loading branch information
axelnxp authored and fabiobaltieri committed Aug 23, 2024
1 parent fcf17dd commit 5d643f4
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 8 deletions.
11 changes: 11 additions & 0 deletions subsys/net/ip/net_context.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,17 @@ bool net_context_is_recv_pktinfo_set(struct net_context *context)
#endif
}

bool net_context_is_timestamping_set(struct net_context *context)
{
#if defined(CONFIG_NET_CONTEXT_TIMESTAMPING)
return (bool)(context->options.timestamping > 0);
#else
ARG_UNUSED(context);

return false;
#endif
}

#if defined(CONFIG_NET_UDP) || defined(CONFIG_NET_TCP)
static inline bool is_in_tcp_listen_state(struct net_context *context)
{
Expand Down
6 changes: 6 additions & 0 deletions subsys/net/ip/net_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ extern bool net_context_is_reuseaddr_set(struct net_context *context);
extern bool net_context_is_reuseport_set(struct net_context *context);
extern bool net_context_is_v6only_set(struct net_context *context);
extern bool net_context_is_recv_pktinfo_set(struct net_context *context);
extern bool net_context_is_timestamping_set(struct net_context *context);
extern void net_pkt_init(void);
extern void net_tc_tx_init(void);
extern void net_tc_rx_init(void);
Expand Down Expand Up @@ -115,6 +116,11 @@ static inline bool net_context_is_recv_pktinfo_set(struct net_context *context)
ARG_UNUSED(context);
return false;
}
static inline bool net_context_is_timestamping_set(struct net_context *context)
{
ARG_UNUSED(context);
return false;
}

static inline int net_context_get_local_addr(struct net_context *context,
struct sockaddr *addr,
Expand Down
32 changes: 24 additions & 8 deletions subsys/net/lib/sockets/sockets.c
Original file line number Diff line number Diff line change
Expand Up @@ -1428,6 +1428,22 @@ static int add_pktinfo(struct net_context *ctx,
return ret;
}

static int update_msg_controllen(struct msghdr *msg)
{
struct cmsghdr *cmsg;
size_t cmsg_space = 0;

for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL; cmsg = CMSG_NXTHDR(msg, cmsg)) {
if (cmsg->cmsg_len == 0) {
break;
}
cmsg_space += cmsg->cmsg_len;
}
msg->msg_controllen = cmsg_space;

return 0;
}

static inline ssize_t zsock_recv_dgram(struct net_context *ctx,
struct msghdr *msg,
void *buf,
Expand Down Expand Up @@ -1572,26 +1588,26 @@ static inline ssize_t zsock_recv_dgram(struct net_context *ctx,
if (msg != NULL) {
if (msg->msg_control != NULL) {
if (msg->msg_controllen > 0) {
bool clear_controllen = true;

if (IS_ENABLED(CONFIG_NET_CONTEXT_TIMESTAMPING)) {
clear_controllen = false;
if (IS_ENABLED(CONFIG_NET_CONTEXT_TIMESTAMPING) &&
net_context_is_timestamping_set(ctx)) {
if (add_timestamping(ctx, pkt, msg) < 0) {
msg->msg_flags |= ZSOCK_MSG_CTRUNC;
}
}

if (IS_ENABLED(CONFIG_NET_CONTEXT_RECV_PKTINFO) &&
net_context_is_recv_pktinfo_set(ctx)) {
clear_controllen = false;
if (add_pktinfo(ctx, pkt, msg) < 0) {
msg->msg_flags |= ZSOCK_MSG_CTRUNC;
}
}

if (clear_controllen) {
msg->msg_controllen = 0;
}
/* msg_controllen must be updated to reflect the total length of all
* control messages in the buffer. If there are no control data,
* msg_controllen will be cleared as expected It will also take into
* account pre-existing control data
*/
update_msg_controllen(msg);
}
} else {
msg->msg_controllen = 0U;
Expand Down

0 comments on commit 5d643f4

Please sign in to comment.