This is an automated email from the ASF dual-hosted git repository. xiaoxiang781216 pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit d17f5c91e4fb363434bbf485c450d81999c727a2 Author: raiden00pl <[email protected]> AuthorDate: Fri Oct 23 09:22:05 2026 +0200 net/can: Do not deliver CAN FD frames to classic CAN sockets. include/nuttx/can.h: CAN_RAW_FD_FRAMES "Allow CAN FD frames (default:off)", but CAN FD frames were queued for classic sockets and can_readahead() returned 0, so a non-blocking recv() blocked. Skip sockets without the option in can_active(); return a queued frame larger than the buffer truncated, POSIX recvmsg(): "MSG_TRUNC Normal data was truncated." Assisted-by: Claude:claude-opus-5-5 Signed-off-by: raiden00pl <[email protected]> --- net/can/can_conn.c | 13 +++++++++++++ net/can/can_recvmsg.c | 42 +++++++++++------------------------------- 2 files changed, 24 insertions(+), 31 deletions(-) diff --git a/net/can/can_conn.c b/net/can/can_conn.c index 67e00b81f1d..e14f256b8eb 100644 --- a/net/can/can_conn.c +++ b/net/can/can_conn.c @@ -304,6 +304,19 @@ FAR struct can_conn_s *can_active(FAR struct net_driver_s *dev, continue; } #endif + + /* Do not pass CAN FD frames to a classic CAN socket */ + +#if defined(CONFIG_NET_CANPROTO_OPTIONS) && defined(CONFIG_NET_CAN_CANFD) + if (!_SO_GETOPT(conn->sconn.s_options, CAN_RAW_FD_FRAMES)) +#endif + { + if (dev->d_len > sizeof(struct can_frame)) + { + continue; + } + } + break; } } diff --git a/net/can/can_recvmsg.c b/net/can/can_recvmsg.c index 4c04a749eae..f8bf9574f26 100644 --- a/net/can/can_recvmsg.c +++ b/net/can/can_recvmsg.c @@ -276,7 +276,14 @@ static inline int can_readahead(struct can_recvfrom_s *pstate) pstate->pr_recvlen = recvlen; - /* We should have taken all of the data from the I/O buffer chain, + /* The rest of a frame larger than the user buffer is discarded */ + + if (iob->io_pktlen > pstate->pr_msg->msg_iov->iov_len) + { + pstate->pr_msg->msg_flags |= MSG_TRUNC; + } + + /* We have taken all of the data we need from the I/O buffer chain, * so release it. There is no trimming needed, since One CAN/CANFD * frame can always fit in one IOB. */ @@ -287,17 +294,6 @@ static inline int can_readahead(struct can_recvfrom_s *pstate) iob_free_chain(iob); - /* do not pass frames with DLC > 8 to a legacy socket */ -#if defined(CONFIG_NET_CANPROTO_OPTIONS) && defined(CONFIG_NET_CAN_CANFD) - if (!_SO_GETOPT(conn->sconn.s_options, CAN_RAW_FD_FRAMES)) -#endif - { - if (recvlen > sizeof(struct can_frame)) - { - return 0; - } - } - return recvlen; } @@ -313,27 +309,11 @@ static uint32_t can_recvfrom_eventhandler(FAR struct net_driver_s *dev, if (pstate) { -#if defined(CONFIG_NET_CANPROTO_OPTIONS) && defined(CONFIG_NET_CAN_CANFD) - struct can_conn_s *conn = pstate->pr_conn; -#endif - if ((flags & CAN_NEWDATA) != 0) { - /* do not pass frames with DLC > 8 to a legacy socket */ -#if defined(CONFIG_NET_CANPROTO_OPTIONS) && defined(CONFIG_NET_CAN_CANFD) - if (!_SO_GETOPT(conn->sconn.s_options, CAN_RAW_FD_FRAMES)) -#endif - { - if (dev->d_len > sizeof(struct can_frame)) - { - /* DO WE NEED TO CLEAR FLAGS?? */ - - flags &= ~CAN_NEWDATA; - return flags; - } - } - - /* Copy the packet */ + /* Copy the packet. can_active() does not deliver CAN FD frames + * to a classic CAN socket. + */ can_newdata(dev, pstate);
