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);
 

Reply via email to