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 */
|
||||
#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 */
|
||||
|
||||
|
@ -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
|
||||
|
@ -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) */
|
||||
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user