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 <zhanghongyu@xiaomi.com>
This commit is contained in:
zhanghongyu 2023-04-14 18:11:12 +08:00 committed by Xiang Xiao
parent 7ab42f115e
commit e0816ff050
5 changed files with 49 additions and 17 deletions

View File

@ -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 */

View File

@ -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

View File

@ -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) */

View File

@ -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,11 +227,22 @@ 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 */
ret = iob_copyout(buf, iob, buflen, 0);
@ -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 */

View File

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