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

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


The following commit(s) were added to refs/heads/master by this push:
     new e0816ff050 in.h: add SOL_IPV6 protocol-level socket option 
IPV6_RECVHOPLIMIT
e0816ff050 is described below

commit e0816ff050f62817f2d0f13c39943f912383a443
Author: zhanghongyu <[email protected]>
AuthorDate: Fri Apr 14 18:11:12 2023 +0800

    in.h: add SOL_IPV6 protocol-level socket option IPV6_RECVHOPLIMIT
    
    added IPV6_RECVHOPLIMIT support so that fd of SOCK_RAW ICMPV6 can obtain ttl
    information, some network related tools use this feature.
    
    Signed-off-by: zhanghongyu <[email protected]>
---
 include/netinet/in.h        |  2 ++
 net/icmpv6/icmpv6.h         |  2 +-
 net/icmpv6/icmpv6_input.c   |  6 ++++-
 net/icmpv6/icmpv6_recvmsg.c | 55 ++++++++++++++++++++++++++++++++-------------
 net/inet/ipv6_setsockopt.c  |  1 +
 5 files changed, 49 insertions(+), 17 deletions(-)

diff --git a/include/netinet/in.h b/include/netinet/in.h
index 867095fcfa..3affebaa9b 100644
--- a/include/netinet/in.h
+++ b/include/netinet/in.h
@@ -132,6 +132,8 @@
                                                     * the incoming packet */
 #define IPV6_TCLASS           (__SO_PROTOCOL + 10) /* Access the Traffic Class
                                                     * field */
+#define IPV6_RECVHOPLIMIT     (__SO_PROTOCOL + 11) /* Access the hop limit 
field */
+#define IPV6_HOPLIMIT         (__SO_PROTOCOL + 12) /* Hop limit */
 
 /* Values used with SIOCSIFMCFILTER and SIOCGIFMCFILTER ioctl's */
 
diff --git a/net/icmpv6/icmpv6.h b/net/icmpv6/icmpv6.h
index 259a873bce..d930ca00d0 100644
--- a/net/icmpv6/icmpv6.h
+++ b/net/icmpv6/icmpv6.h
@@ -651,7 +651,7 @@ ssize_t icmpv6_sendmsg(FAR struct socket *psock, FAR struct 
msghdr *msg,
  * Description:
  *   Implements the socket recvfrom interface for the case of the AF_INET
  *   data gram socket with the IPPROTO_ICMP6 protocol.  icmpv6_recvmsg()
- *   receives ICMPv6 ECHO replies for the a socket.
+ *   receives ICMPv6 message for the a socket.
  *
  *   If msg_name is not NULL, and the underlying protocol provides the source
  *   address, this source address is filled in. The argument 'msg_namelen' is
diff --git a/net/icmpv6/icmpv6_input.c b/net/icmpv6/icmpv6_input.c
index 16378a7bdf..ec53103986 100644
--- a/net/icmpv6/icmpv6_input.c
+++ b/net/icmpv6/icmpv6_input.c
@@ -111,6 +111,7 @@ static uint16_t icmpv6_datahandler(FAR struct net_driver_s 
*dev,
   FAR struct ipv6_hdr_s *ipv6;
   struct sockaddr_in6 inaddr;
   FAR struct iob_s *iob;
+  unsigned int offset;
   uint16_t buflen;
   int ret;
 
@@ -132,8 +133,11 @@ static uint16_t icmpv6_datahandler(FAR struct net_driver_s 
*dev,
    */
 
   memcpy(iob->io_data, &inaddr, sizeof(struct sockaddr_in6));
+  offset = sizeof(struct sockaddr_in6);
 
-  iob_reserve(iob, sizeof(struct sockaddr_in6));
+  iob->io_data[offset++] = ipv6->ttl;
+
+  iob_reserve(iob, offset);
 
   /* Copy the ICMPv6 message into the I/O buffer chain (without waiting) */
 
diff --git a/net/icmpv6/icmpv6_recvmsg.c b/net/icmpv6/icmpv6_recvmsg.c
index ffffd2a23a..56e02bd3aa 100644
--- a/net/icmpv6/icmpv6_recvmsg.c
+++ b/net/icmpv6/icmpv6_recvmsg.c
@@ -36,6 +36,7 @@
 #include "devif/devif.h"
 #include "socket/socket.h"
 #include "icmpv6/icmpv6.h"
+#include "utils/utils.h"
 
 #ifdef CONFIG_NET_ICMPv6_SOCKET
 
@@ -60,6 +61,7 @@ struct icmpv6_recvfrom_s
                                          * from */
   FAR uint8_t *recv_buf;                /* Location to return the response */
   uint16_t recv_buflen;                 /* Size of the response */
+  FAR struct msghdr *msg;               /* Input message header */
   int16_t recv_result;                  /* >=0: receive size on success;
                                          * <0: negated errno on fail */
 };
@@ -73,8 +75,8 @@ struct icmpv6_recvfrom_s
  *
  * Description:
  *   This function is called with the network locked to perform the actual
- *   ECHO request and/or ECHO reply actions when polled by the lower, device
- *   interfacing layer.
+ *   ICMPv6 message actions when polled by the lower, device interfacing
+ *   layer.
  *
  * Input Parameters:
  *   dev        The structure of the network driver that generated the
@@ -113,15 +115,18 @@ static uint16_t recvfrom_eventhandler(FAR struct 
net_driver_s *dev,
       psock = pstate->recv_sock;
       DEBUGASSERT(psock != NULL && psock->s_conn != NULL);
 
-      /* Check if we have just received a ICMPv6 ECHO reply. */
+      /* Check if we have just received a ICMPv6 message. */
 
       if ((flags & ICMPv6_NEWDATA) != 0)    /* No incoming data */
         {
+#ifdef CONFIG_NET_SOCKOPTS
+          FAR struct icmpv6_conn_s *conn = psock->s_conn;
+#endif
           unsigned int recvsize;
 
-          ninfo("Received ICMPv6 reply\n");
+          ninfo("Received ICMPv6 message\n");
 
-          /* What should we do if the received reply is larger that the
+          /* What should we do if the received message is larger that the
            * buffer that the caller of sendto provided?  Truncate?  Error
            * out?
            */
@@ -132,7 +137,7 @@ static uint16_t recvfrom_eventhandler(FAR struct 
net_driver_s *dev,
               recvsize = pstate->recv_buflen;
             }
 
-          /* Copy the ICMPv6 ECHO reply to the user provided buffer
+          /* Copy the ICMPv6 message to the user provided buffer
            * REVISIT:  What if there are IPv6 extension headers present?
            */
 
@@ -150,7 +155,17 @@ static uint16_t recvfrom_eventhandler(FAR struct 
net_driver_s *dev,
 
           /* Indicate that the data has been consumed */
 
-          flags     &= ~ICMPv6_NEWDATA;
+          flags &= ~ICMPv6_NEWDATA;
+#ifdef CONFIG_NET_SOCKOPTS
+          if (_SO_GETOPT(conn->sconn.s_options, IPV6_RECVHOPLIMIT))
+            {
+              int hoplimit = ipv6->ttl;
+
+              cmsg_append(pstate->msg, SOL_IPV6, IPV6_HOPLIMIT,
+                          &hoplimit, sizeof(hoplimit));
+            }
+#endif
+
           dev->d_len = 0;
           goto end_wait;
         }
@@ -196,9 +211,8 @@ end_wait:
  ****************************************************************************/
 
 static inline ssize_t icmpv6_readahead(FAR struct icmpv6_conn_s *conn,
-                                     FAR void *buf, size_t buflen,
-                                     FAR struct sockaddr_in6 *from,
-                                     FAR socklen_t *fromlen)
+                                       FAR void *buf, size_t buflen,
+                                       FAR struct msghdr *msg)
 {
   FAR struct iob_s *iob;
   ssize_t ret = -ENODATA;
@@ -213,10 +227,21 @@ static inline ssize_t icmpv6_readahead(FAR struct 
icmpv6_conn_s *conn,
 
       /* Then get address */
 
-      if (from != NULL)
+      if (msg->msg_name != NULL)
         {
-          memcpy(from, iob->io_data, sizeof(struct sockaddr_in6));
+          memcpy(msg->msg_name, iob->io_data, sizeof(struct sockaddr_in6));
+        }
+
+#ifdef CONFIG_NET_SOCKOPTS
+      if (_SO_GETOPT(conn->sconn.s_options, IPV6_RECVHOPLIMIT))
+        {
+          int hoplimit;
+
+          hoplimit = iob->io_data[sizeof(struct sockaddr_in6)];
+          cmsg_append(msg, SOL_IPV6, IPV6_HOPLIMIT,
+                      &hoplimit, sizeof(hoplimit));
         }
+#endif
 
       /* Copy to user */
 
@@ -248,7 +273,7 @@ static inline ssize_t icmpv6_readahead(FAR struct 
icmpv6_conn_s *conn,
  * Description:
  *   Implements the socket recvfrom interface for the case of the AF_INET
  *   data gram socket with the IPPROTO_ICMP6 protocol.  icmpv6_recvmsg()
- *   receives ICMPv6 ECHO replies for the a socket.
+ *   receives ICMPv6 message for the a socket.
  *
  *   If msg_name is not NULL, and the underlying protocol provides the source
  *   address, this source address is filled in. The argument 'msg_namelen' is
@@ -325,8 +350,7 @@ ssize_t icmpv6_recvmsg(FAR struct socket *psock, FAR struct 
msghdr *msg,
 
   if (!IOB_QEMPTY(&conn->readahead))
     {
-      ret = icmpv6_readahead(conn, buf, len,
-                             (FAR struct sockaddr_in6 *)from, fromlen);
+      ret = icmpv6_readahead(conn, buf, len, msg);
     }
   else if (_SS_ISNONBLOCK(conn->sconn.s_flags) ||
            (flags & MSG_DONTWAIT) != 0)
@@ -346,6 +370,7 @@ ssize_t icmpv6_recvmsg(FAR struct socket *psock, FAR struct 
msghdr *msg,
       state.recv_result = -ENOMEM;  /* Assume allocation failure */
       state.recv_buf    = buf;      /* Location to return the response */
       state.recv_buflen = len;      /* Size of the response */
+      state.msg         = msg;      /* Input message header */
 
       /* Set up the callback */
 
diff --git a/net/inet/ipv6_setsockopt.c b/net/inet/ipv6_setsockopt.c
index 0dc425f9ec..69692a6da1 100644
--- a/net/inet/ipv6_setsockopt.c
+++ b/net/inet/ipv6_setsockopt.c
@@ -128,6 +128,7 @@ int ipv6_setsockopt(FAR struct socket *psock, int option,
         break;
 
       case IPV6_RECVPKTINFO:
+      case IPV6_RECVHOPLIMIT:
         {
           FAR struct socket_conn_s *conn;
           int enable;

Reply via email to