Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

net: sockets: Update msg_controllen in recvmsg properly #77345

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
3 changes: 3 additions & 0 deletions tests/net/socket/udp/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1492,6 +1492,7 @@ static void comm_sendmsg_recvmsg(int client_sock,
io_vector[0].iov_len = sizeof(buf);

memset(msg, 0, sizeof(*msg));
memset(cmsgbuf, 0, cmsgbuf_len);
msg->msg_control = cmsgbuf;
msg->msg_controllen = cmsgbuf_len;
msg->msg_iov = io_vector;
Expand Down Expand Up @@ -1565,6 +1566,7 @@ static void comm_sendmsg_recvmsg(int client_sock,
io_vector[1].iov_len = sizeof(buf);

memset(msg, 0, sizeof(*msg));
memset(cmsgbuf, 0, cmsgbuf_len);
msg->msg_control = cmsgbuf;
msg->msg_controllen = cmsgbuf_len;
msg->msg_iov = io_vector;
Expand Down Expand Up @@ -1624,6 +1626,7 @@ static void comm_sendmsg_recvmsg(int client_sock,
io_vector[0].iov_len = sizeof(buf2);

memset(msg, 0, sizeof(*msg));
memset(cmsgbuf, 0, cmsgbuf_len);
msg->msg_control = cmsgbuf;
msg->msg_controllen = cmsgbuf_len;
msg->msg_iov = io_vector;
Expand Down
Loading