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:
parent
7ab42f115e
commit
e0816ff050
@ -132,6 +132,8 @@
|
|||||||
* the incoming packet */
|
* the incoming packet */
|
||||||
#define IPV6_TCLASS (__SO_PROTOCOL + 10) /* Access the Traffic Class
|
#define IPV6_TCLASS (__SO_PROTOCOL + 10) /* Access the Traffic Class
|
||||||
* field */
|
* 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 */
|
/* Values used with SIOCSIFMCFILTER and SIOCGIFMCFILTER ioctl's */
|
||||||
|
|
||||||
|
@ -651,7 +651,7 @@ ssize_t icmpv6_sendmsg(FAR struct socket *psock, FAR struct msghdr *msg,
|
|||||||
* Description:
|
* Description:
|
||||||
* Implements the socket recvfrom interface for the case of the AF_INET
|
* Implements the socket recvfrom interface for the case of the AF_INET
|
||||||
* data gram socket with the IPPROTO_ICMP6 protocol. icmpv6_recvmsg()
|
* 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
|
* 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
|
* address, this source address is filled in. The argument 'msg_namelen' is
|
||||||
|
@ -111,6 +111,7 @@ static uint16_t icmpv6_datahandler(FAR struct net_driver_s *dev,
|
|||||||
FAR struct ipv6_hdr_s *ipv6;
|
FAR struct ipv6_hdr_s *ipv6;
|
||||||
struct sockaddr_in6 inaddr;
|
struct sockaddr_in6 inaddr;
|
||||||
FAR struct iob_s *iob;
|
FAR struct iob_s *iob;
|
||||||
|
unsigned int offset;
|
||||||
uint16_t buflen;
|
uint16_t buflen;
|
||||||
int ret;
|
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));
|
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) */
|
/* Copy the ICMPv6 message into the I/O buffer chain (without waiting) */
|
||||||
|
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
#include "devif/devif.h"
|
#include "devif/devif.h"
|
||||||
#include "socket/socket.h"
|
#include "socket/socket.h"
|
||||||
#include "icmpv6/icmpv6.h"
|
#include "icmpv6/icmpv6.h"
|
||||||
|
#include "utils/utils.h"
|
||||||
|
|
||||||
#ifdef CONFIG_NET_ICMPv6_SOCKET
|
#ifdef CONFIG_NET_ICMPv6_SOCKET
|
||||||
|
|
||||||
@ -60,6 +61,7 @@ struct icmpv6_recvfrom_s
|
|||||||
* from */
|
* from */
|
||||||
FAR uint8_t *recv_buf; /* Location to return the response */
|
FAR uint8_t *recv_buf; /* Location to return the response */
|
||||||
uint16_t recv_buflen; /* Size of 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;
|
int16_t recv_result; /* >=0: receive size on success;
|
||||||
* <0: negated errno on fail */
|
* <0: negated errno on fail */
|
||||||
};
|
};
|
||||||
@ -73,8 +75,8 @@ struct icmpv6_recvfrom_s
|
|||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* This function is called with the network locked to perform the actual
|
* 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
|
* ICMPv6 message actions when polled by the lower, device interfacing
|
||||||
* interfacing layer.
|
* layer.
|
||||||
*
|
*
|
||||||
* Input Parameters:
|
* Input Parameters:
|
||||||
* dev The structure of the network driver that generated the
|
* 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;
|
psock = pstate->recv_sock;
|
||||||
DEBUGASSERT(psock != NULL && psock->s_conn != NULL);
|
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 */
|
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;
|
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
|
* buffer that the caller of sendto provided? Truncate? Error
|
||||||
* out?
|
* out?
|
||||||
*/
|
*/
|
||||||
@ -132,7 +137,7 @@ static uint16_t recvfrom_eventhandler(FAR struct net_driver_s *dev,
|
|||||||
recvsize = pstate->recv_buflen;
|
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?
|
* 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 */
|
/* 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;
|
dev->d_len = 0;
|
||||||
goto end_wait;
|
goto end_wait;
|
||||||
}
|
}
|
||||||
@ -196,9 +211,8 @@ end_wait:
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static inline ssize_t icmpv6_readahead(FAR struct icmpv6_conn_s *conn,
|
static inline ssize_t icmpv6_readahead(FAR struct icmpv6_conn_s *conn,
|
||||||
FAR void *buf, size_t buflen,
|
FAR void *buf, size_t buflen,
|
||||||
FAR struct sockaddr_in6 *from,
|
FAR struct msghdr *msg)
|
||||||
FAR socklen_t *fromlen)
|
|
||||||
{
|
{
|
||||||
FAR struct iob_s *iob;
|
FAR struct iob_s *iob;
|
||||||
ssize_t ret = -ENODATA;
|
ssize_t ret = -ENODATA;
|
||||||
@ -213,11 +227,22 @@ static inline ssize_t icmpv6_readahead(FAR struct icmpv6_conn_s *conn,
|
|||||||
|
|
||||||
/* Then get address */
|
/* 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 */
|
/* Copy to user */
|
||||||
|
|
||||||
ret = iob_copyout(buf, iob, buflen, 0);
|
ret = iob_copyout(buf, iob, buflen, 0);
|
||||||
@ -248,7 +273,7 @@ static inline ssize_t icmpv6_readahead(FAR struct icmpv6_conn_s *conn,
|
|||||||
* Description:
|
* Description:
|
||||||
* Implements the socket recvfrom interface for the case of the AF_INET
|
* Implements the socket recvfrom interface for the case of the AF_INET
|
||||||
* data gram socket with the IPPROTO_ICMP6 protocol. icmpv6_recvmsg()
|
* 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
|
* 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
|
* 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))
|
if (!IOB_QEMPTY(&conn->readahead))
|
||||||
{
|
{
|
||||||
ret = icmpv6_readahead(conn, buf, len,
|
ret = icmpv6_readahead(conn, buf, len, msg);
|
||||||
(FAR struct sockaddr_in6 *)from, fromlen);
|
|
||||||
}
|
}
|
||||||
else if (_SS_ISNONBLOCK(conn->sconn.s_flags) ||
|
else if (_SS_ISNONBLOCK(conn->sconn.s_flags) ||
|
||||||
(flags & MSG_DONTWAIT) != 0)
|
(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_result = -ENOMEM; /* Assume allocation failure */
|
||||||
state.recv_buf = buf; /* Location to return the response */
|
state.recv_buf = buf; /* Location to return the response */
|
||||||
state.recv_buflen = len; /* Size of the response */
|
state.recv_buflen = len; /* Size of the response */
|
||||||
|
state.msg = msg; /* Input message header */
|
||||||
|
|
||||||
/* Set up the callback */
|
/* Set up the callback */
|
||||||
|
|
||||||
|
@ -128,6 +128,7 @@ int ipv6_setsockopt(FAR struct socket *psock, int option,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case IPV6_RECVPKTINFO:
|
case IPV6_RECVPKTINFO:
|
||||||
|
case IPV6_RECVHOPLIMIT:
|
||||||
{
|
{
|
||||||
FAR struct socket_conn_s *conn;
|
FAR struct socket_conn_s *conn;
|
||||||
int enable;
|
int enable;
|
||||||
|
Loading…
Reference in New Issue
Block a user