This is an automated email from the ASF dual-hosted git repository.

casaroli pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 735a89c97e7b91cdd8353e6a095fa5f627dbf8c3
Author: wangjinjing1 <[email protected]>
AuthorDate: Thu May 14 22:15:14 2026 +0800

    net/can: implement getsockname for CAN sockets
    
    Add can_getsockname() to return the locally-bound CAN interface
    index via getsockname() syscall, matching Linux raw_getname()
    behavior. When CONFIG_NETDEV_IFINDEX is enabled, returns
    d_ifindex directly; otherwise extracts index from device name
    "can<N>" to mirror the bind logic.
    
    A buffer smaller than struct sockaddr_can is rejected with EINVAL, as
    in ipv4_getsockname(), and the behavior is documented in
    socketcan.rst.
    
    Assisted-by: Claude:claude-opus-5-5
    Signed-off-by: wangjinjing1 <[email protected]>
    Signed-off-by: p-szafonimateusz <[email protected]>
---
 Documentation/os/networking/socketcan.rst |  9 ++++
 net/can/can_sockif.c                      | 74 ++++++++++++++++++++++++++++++-
 2 files changed, 82 insertions(+), 1 deletion(-)

diff --git a/Documentation/os/networking/socketcan.rst 
b/Documentation/os/networking/socketcan.rst
index 8db7955979a..8e4136ad266 100644
--- a/Documentation/os/networking/socketcan.rst
+++ b/Documentation/os/networking/socketcan.rst
@@ -155,6 +155,15 @@ If the network device is not a loopback device, the stack 
loops the frame
 back itself after the driver accepted it.  Looped back frames are counted in
 the received CAN statistics.
 
+Socket Address
+--------------
+
+``getsockname()`` returns a ``struct sockaddr_can`` with ``can_family`` set
+to ``AF_CAN`` and ``can_ifindex`` set to the index of the interface the
+socket is bound to, or 0 if the socket is not bound to an interface.  The
+address buffer must be at least ``sizeof(struct sockaddr_can)`` bytes,
+otherwise ``EINVAL`` is returned.
+
 Features
 --------
 
diff --git a/net/can/can_sockif.c b/net/can/can_sockif.c
index 32cffb8f741..585dcfcf665 100644
--- a/net/can/can_sockif.c
+++ b/net/can/can_sockif.c
@@ -57,6 +57,9 @@ static sockcaps_t can_sockcaps(FAR struct socket *psock);
 static void can_addref(FAR struct socket *psock);
 static int  can_bind(FAR struct socket *psock,
                      FAR const struct sockaddr *addr, socklen_t addrlen);
+static int  can_getsockname(FAR struct socket *psock,
+                            FAR struct sockaddr *addr,
+                            FAR socklen_t *addrlen);
 static int can_poll_local(FAR struct socket *psock, FAR struct pollfd_s *fds,
                           bool setup);
 static int can_close(FAR struct socket *psock);
@@ -71,7 +74,7 @@ const struct sock_intf_s g_can_sockif =
   can_sockcaps,     /* si_sockcaps */
   can_addref,       /* si_addref */
   can_bind,         /* si_bind */
-  NULL,             /* si_getsockname */
+  can_getsockname,  /* si_getsockname */
   NULL,             /* si_getpeername */
   NULL,             /* si_listen */
   NULL,             /* si_connect */
@@ -354,6 +357,75 @@ static int can_bind(FAR struct socket *psock,
   return conn->dev == NULL && canaddr->can_ifindex != 0 ? -ENODEV : OK;
 }
 
+/****************************************************************************
+ * Name: can_getsockname
+ *
+ * Description:
+ *   The can_getsockname() function retrieves the locally-bound name of the
+ *   specified CAN socket, stores this address in the sockaddr structure
+ *   pointed to by the 'addr' argument, and stores the length of this
+ *   address in the object pointed to by the 'addrlen' argument.
+ *
+ * Input Parameters:
+ *   psock    Socket structure of the socket to be queried
+ *   addr     sockaddr structure to receive data [out]
+ *   addrlen  Length of sockaddr structure [in/out]
+ *
+ * Returned Value:
+ *   On success, 0 is returned.  Otherwise, a negated errno value is
+ *   returned.
+ *
+ ****************************************************************************/
+
+static int can_getsockname(FAR struct socket *psock,
+                           FAR struct sockaddr *addr,
+                           FAR socklen_t *addrlen)
+{
+  FAR struct sockaddr_can *canaddr;
+  FAR struct can_conn_s *conn;
+
+  /* Check if enough space has been provided for the full address */
+
+  if (*addrlen < sizeof(struct sockaddr_can))
+    {
+      /* This function is supposed to return the partial address if
+       * a smaller buffer has been provided.  This support has not
+       * been implemented.
+       */
+
+      return -EINVAL;
+    }
+
+  conn = psock->s_conn;
+
+  /* Return the address information in the address structure */
+
+  canaddr = (FAR struct sockaddr_can *)addr;
+  memset(canaddr, 0, sizeof(struct sockaddr_can));
+
+  canaddr->can_family = AF_CAN;
+
+  if (conn->dev != NULL)
+    {
+#ifdef CONFIG_NETDEV_IFINDEX
+      canaddr->can_ifindex = conn->dev->d_ifindex;
+#else
+      /* Reverse mapping: extract ifindex from device name "can<N>".
+       * This mirrors the bind logic which maps ifindex -> "can<N>".
+       */
+
+      canaddr->can_ifindex = conn->dev->d_ifname[3] - '0';
+#endif
+    }
+  else
+    {
+      canaddr->can_ifindex = 0;
+    }
+
+  *addrlen = sizeof(struct sockaddr_can);
+  return OK;
+}
+
 /****************************************************************************
  * Name: can_poll_local
  *

Reply via email to