mirror of
https://github.com/lwip-tcpip/lwip.git
synced 2024-07-02 19:08:57 +00:00
Implement IPV6_RECVHOPLIMIT socket option
Implements the IPV6_RECVHOPLIMIT socket option for receiving the hop limit in the IPv6 packet. Based on work from https://savannah.nongnu.org/patch/?9554 Co-authored-by: Christina Schoenrogge <christina.schoenrogge@garmin.com> Co-authored-by: hanhui <hanhui03@163.com>
This commit is contained in:
parent
c004029f77
commit
ea53e5aa6e
|
@ -258,14 +258,24 @@ recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p,
|
||||||
buf->ptr = p;
|
buf->ptr = p;
|
||||||
ip_addr_set(&buf->addr, addr);
|
ip_addr_set(&buf->addr, addr);
|
||||||
buf->port = port;
|
buf->port = port;
|
||||||
|
buf->flags = 0;
|
||||||
#if LWIP_NETBUF_RECVINFO
|
#if LWIP_NETBUF_RECVINFO
|
||||||
if (conn->flags & NETCONN_FLAG_PKTINFO) {
|
if (conn->flags & NETCONN_FLAG_PKTINFO) {
|
||||||
/* get the UDP header - always in the first pbuf, ensured by udp_input */
|
/* get the UDP header - always in the first pbuf, ensured by udp_input */
|
||||||
const struct udp_hdr *udphdr = (const struct udp_hdr *)ip_next_header_ptr();
|
const struct udp_hdr *udphdr = (const struct udp_hdr *)ip_next_header_ptr();
|
||||||
buf->flags = NETBUF_FLAG_DESTADDR;
|
buf->flags |= NETBUF_FLAG_DESTADDR;
|
||||||
ip_addr_set(&buf->toaddr, ip_current_dest_addr());
|
ip_addr_set(&buf->toaddr, ip_current_dest_addr());
|
||||||
buf->toport_chksum = udphdr->dest;
|
buf->toport_chksum = udphdr->dest;
|
||||||
}
|
}
|
||||||
|
#if LWIP_IPV6
|
||||||
|
if (netconn_is_flag_set(conn, NETCONN_FLAG_HOPLIMIT)) {
|
||||||
|
if (ip_current_is_v6()) {
|
||||||
|
struct ip6_hdr *ip6hdr = (struct ip6_hdr *)ip6_current_header();
|
||||||
|
buf->flags |= NETBUF_FLAG_HOPLIMIT;
|
||||||
|
buf->hoplim = IP6H_HOPLIM(ip6hdr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
#endif /* LWIP_NETBUF_RECVINFO */
|
#endif /* LWIP_NETBUF_RECVINFO */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1193,22 +1193,22 @@ lwip_recvfrom_udp_raw(struct lwip_sock *sock, int flags, struct msghdr *msg, u16
|
||||||
msg->msg_flags = 0;
|
msg->msg_flags = 0;
|
||||||
|
|
||||||
if (msg->msg_control) {
|
if (msg->msg_control) {
|
||||||
u8_t wrote_msg = 0;
|
socklen_t msg_controllen_in = msg->msg_controllen;
|
||||||
|
msg->msg_controllen = 0;
|
||||||
#if LWIP_NETBUF_RECVINFO
|
#if LWIP_NETBUF_RECVINFO
|
||||||
/* Check if packet info was recorded */
|
/* Check if packet info was recorded */
|
||||||
if (buf->flags & NETBUF_FLAG_DESTADDR) {
|
if (buf->flags & NETBUF_FLAG_DESTADDR) {
|
||||||
if (IP_IS_V4(&buf->toaddr)) {
|
if (IP_IS_V4(&buf->toaddr)) {
|
||||||
#if LWIP_IPV4
|
#if LWIP_IPV4
|
||||||
if (msg->msg_controllen >= CMSG_SPACE(sizeof(struct in_pktinfo))) {
|
if (msg_controllen_in >= msg->msg_controllen + CMSG_SPACE(sizeof(struct in_pktinfo))) {
|
||||||
struct cmsghdr *chdr = CMSG_FIRSTHDR(msg); /* This will always return a header!! */
|
struct cmsghdr *chdr = ((u8_t *)msg->msg_control + msg->msg_controllen);
|
||||||
struct in_pktinfo *pkti = (struct in_pktinfo *)CMSG_DATA(chdr);
|
struct in_pktinfo *pkti = (struct in_pktinfo *)CMSG_DATA(chdr);
|
||||||
chdr->cmsg_level = IPPROTO_IP;
|
chdr->cmsg_level = IPPROTO_IP;
|
||||||
chdr->cmsg_type = IP_PKTINFO;
|
chdr->cmsg_type = IP_PKTINFO;
|
||||||
chdr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
|
chdr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
|
||||||
pkti->ipi_ifindex = buf->p->if_idx;
|
pkti->ipi_ifindex = buf->p->if_idx;
|
||||||
inet_addr_from_ip4addr(&pkti->ipi_addr, ip_2_ip4(netbuf_destaddr(buf)));
|
inet_addr_from_ip4addr(&pkti->ipi_addr, ip_2_ip4(netbuf_destaddr(buf)));
|
||||||
msg->msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo));
|
msg->msg_controllen += CMSG_SPACE(sizeof(struct in_pktinfo));
|
||||||
wrote_msg = 1;
|
|
||||||
} else {
|
} else {
|
||||||
msg->msg_flags |= MSG_CTRUNC;
|
msg->msg_flags |= MSG_CTRUNC;
|
||||||
}
|
}
|
||||||
|
@ -1216,27 +1216,39 @@ lwip_recvfrom_udp_raw(struct lwip_sock *sock, int flags, struct msghdr *msg, u16
|
||||||
}
|
}
|
||||||
#if LWIP_IPV6
|
#if LWIP_IPV6
|
||||||
else if (IP_IS_V6(&buf->toaddr)) {
|
else if (IP_IS_V6(&buf->toaddr)) {
|
||||||
if (msg->msg_controllen >= CMSG_SPACE(sizeof(struct in6_pktinfo))) {
|
if (msg_controllen_in >= msg->msg_controllen + CMSG_SPACE(sizeof(struct in6_pktinfo))) {
|
||||||
struct cmsghdr *chdr = CMSG_FIRSTHDR(msg); /* This will always return a header!! */
|
struct cmsghdr *chdr = ((u8_t *)msg->msg_control + msg->msg_controllen);
|
||||||
struct in6_pktinfo *pkti = (struct in6_pktinfo *)CMSG_DATA(chdr);
|
struct in6_pktinfo *pkti = (struct in6_pktinfo *)CMSG_DATA(chdr);
|
||||||
chdr->cmsg_level = IPPROTO_IPV6;
|
chdr->cmsg_level = IPPROTO_IPV6;
|
||||||
chdr->cmsg_type = IPV6_PKTINFO;
|
chdr->cmsg_type = IPV6_PKTINFO;
|
||||||
chdr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
|
chdr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
|
||||||
pkti->ipi6_ifindex = buf->p->if_idx;
|
pkti->ipi6_ifindex = buf->p->if_idx;
|
||||||
inet6_addr_from_ip6addr(&pkti->ipi6_addr, ip_2_ip6(netbuf_destaddr(buf)));
|
inet6_addr_from_ip6addr(&pkti->ipi6_addr, ip_2_ip6(netbuf_destaddr(buf)));
|
||||||
msg->msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
|
msg->msg_controllen += CMSG_SPACE(sizeof(struct in6_pktinfo));
|
||||||
wrote_msg = 1;
|
|
||||||
} else {
|
} else {
|
||||||
msg->msg_flags |= MSG_CTRUNC;
|
msg->msg_flags |= MSG_CTRUNC;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* LWIP_IPV6 */
|
#endif /* LWIP_IPV6 */
|
||||||
}
|
}
|
||||||
#endif /* LWIP_NETBUF_RECVINFO */
|
#if LWIP_IPV6
|
||||||
|
if (buf->flags & NETBUF_FLAG_HOPLIMIT) {
|
||||||
if (!wrote_msg) {
|
if (IP_IS_V6(&buf->toaddr)) {
|
||||||
msg->msg_controllen = 0;
|
if (msg_controllen_in >= msg->msg_controllen + CMSG_SPACE(sizeof(int))) {
|
||||||
|
struct cmsghdr *chdr = ((u8_t *)msg->msg_control + msg->msg_controllen);
|
||||||
|
int *hoplim = (int *)CMSG_DATA(chdr);
|
||||||
|
chdr->cmsg_level = IPPROTO_IPV6;
|
||||||
|
chdr->cmsg_type = IPV6_HOPLIMIT;
|
||||||
|
chdr->cmsg_len = CMSG_LEN(sizeof(int));
|
||||||
|
*hoplim = buf->hoplim;
|
||||||
|
msg->msg_controllen += CMSG_SPACE(sizeof(int));
|
||||||
|
} else {
|
||||||
|
msg->msg_flags |= MSG_CTRUNC;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
#endif /* LWIP_NETBUF_RECVINFO */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we don't peek the incoming message: zero lastdata pointer and free the netbuf */
|
/* If we don't peek the incoming message: zero lastdata pointer and free the netbuf */
|
||||||
|
@ -3704,6 +3716,16 @@ lwip_setsockopt_impl(int s, int level, int optname, const void *optval, socklen_
|
||||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IPV6, IPV6_RECVPKTINFO, ..) -> %d\n",
|
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IPV6, IPV6_RECVPKTINFO, ..) -> %d\n",
|
||||||
s, *(const int *)optval));
|
s, *(const int *)optval));
|
||||||
break;
|
break;
|
||||||
|
case IPV6_RECVHOPLIMIT:
|
||||||
|
LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_UDP);
|
||||||
|
if (*(const int *)optval) {
|
||||||
|
netconn_set_flags(sock->conn, NETCONN_FLAG_HOPLIMIT);
|
||||||
|
} else {
|
||||||
|
netconn_clear_flags(sock->conn, NETCONN_FLAG_HOPLIMIT);
|
||||||
|
}
|
||||||
|
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, ..) -> %d\n",
|
||||||
|
s, *(const int *)optval));
|
||||||
|
break;
|
||||||
#endif /* LWIP_NETBUF_RECVINFO */
|
#endif /* LWIP_NETBUF_RECVINFO */
|
||||||
#if LWIP_MULTICAST_TX_OPTIONS && LWIP_UDP
|
#if LWIP_MULTICAST_TX_OPTIONS && LWIP_UDP
|
||||||
case IPV6_MULTICAST_IF:
|
case IPV6_MULTICAST_IF:
|
||||||
|
|
|
@ -92,6 +92,10 @@ extern "C" {
|
||||||
#endif /* LWIP_NETBUF_RECVINFO */
|
#endif /* LWIP_NETBUF_RECVINFO */
|
||||||
/** A FIN has been received but not passed to the application yet */
|
/** A FIN has been received but not passed to the application yet */
|
||||||
#define NETCONN_FIN_RX_PENDING 0x80
|
#define NETCONN_FIN_RX_PENDING 0x80
|
||||||
|
#if LWIP_NETBUF_RECVINFO
|
||||||
|
/** The hop limit will be stored for incoming packets */
|
||||||
|
#define NETCONN_FLAG_HOPLIMIT 0x100
|
||||||
|
#endif /* LWIP_NETBUF_RECVINFO */
|
||||||
|
|
||||||
/* Helpers to process several netconn_types by the same code */
|
/* Helpers to process several netconn_types by the same code */
|
||||||
#define NETCONNTYPE_GROUP(t) ((t)&0xF0)
|
#define NETCONNTYPE_GROUP(t) ((t)&0xF0)
|
||||||
|
@ -274,7 +278,7 @@ struct netconn {
|
||||||
s16_t linger;
|
s16_t linger;
|
||||||
#endif /* LWIP_SO_LINGER */
|
#endif /* LWIP_SO_LINGER */
|
||||||
/** flags holding more netconn-internal state, see NETCONN_FLAG_* defines */
|
/** flags holding more netconn-internal state, see NETCONN_FLAG_* defines */
|
||||||
u8_t flags;
|
u16_t flags;
|
||||||
#if LWIP_TCP
|
#if LWIP_TCP
|
||||||
/** TCP: when data passed to netconn_write doesn't fit into the send buffer,
|
/** TCP: when data passed to netconn_write doesn't fit into the send buffer,
|
||||||
this temporarily stores the message.
|
this temporarily stores the message.
|
||||||
|
@ -369,8 +373,8 @@ err_t netconn_gethostbyname(const char *name, ip_addr_t *addr);
|
||||||
err_t netconn_err(struct netconn *conn);
|
err_t netconn_err(struct netconn *conn);
|
||||||
#define netconn_recv_bufsize(conn) ((conn)->recv_bufsize)
|
#define netconn_recv_bufsize(conn) ((conn)->recv_bufsize)
|
||||||
|
|
||||||
#define netconn_set_flags(conn, set_flags) do { (conn)->flags = (u8_t)((conn)->flags | (set_flags)); } while(0)
|
#define netconn_set_flags(conn, set_flags) do { (conn)->flags = (u16_t)((conn)->flags | (set_flags)); } while(0)
|
||||||
#define netconn_clear_flags(conn, clr_flags) do { (conn)->flags = (u8_t)((conn)->flags & (u8_t)(~(clr_flags) & 0xff)); } while(0)
|
#define netconn_clear_flags(conn, clr_flags) do { (conn)->flags = (u16_t)((conn)->flags & (u16_t)(~(clr_flags) & 0xffff)); } while(0)
|
||||||
#define netconn_is_flag_set(conn, flag) (((conn)->flags & (flag)) != 0)
|
#define netconn_is_flag_set(conn, flag) (((conn)->flags & (flag)) != 0)
|
||||||
|
|
||||||
#define netconn_set_callback_arg(conn, arg) do { (conn)->callback_arg.ptr = (arg); } while(0)
|
#define netconn_set_callback_arg(conn, arg) do { (conn)->callback_arg.ptr = (arg); } while(0)
|
||||||
|
|
|
@ -55,6 +55,8 @@ extern "C" {
|
||||||
#define NETBUF_FLAG_DESTADDR 0x01
|
#define NETBUF_FLAG_DESTADDR 0x01
|
||||||
/** This netbuf includes a checksum */
|
/** This netbuf includes a checksum */
|
||||||
#define NETBUF_FLAG_CHKSUM 0x02
|
#define NETBUF_FLAG_CHKSUM 0x02
|
||||||
|
/** This netbuf has hop limit set */
|
||||||
|
#define NETBUF_FLAG_HOPLIMIT 0x04
|
||||||
|
|
||||||
/** "Network buffer" - contains data and addressing info */
|
/** "Network buffer" - contains data and addressing info */
|
||||||
struct netbuf {
|
struct netbuf {
|
||||||
|
@ -66,6 +68,9 @@ struct netbuf {
|
||||||
u16_t toport_chksum;
|
u16_t toport_chksum;
|
||||||
#if LWIP_NETBUF_RECVINFO
|
#if LWIP_NETBUF_RECVINFO
|
||||||
ip_addr_t toaddr;
|
ip_addr_t toaddr;
|
||||||
|
#if LWIP_IPV6
|
||||||
|
u8_t hoplim;
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
#endif /* LWIP_NETBUF_RECVINFO */
|
#endif /* LWIP_NETBUF_RECVINFO */
|
||||||
#endif /* LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY */
|
#endif /* LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY */
|
||||||
};
|
};
|
||||||
|
|
|
@ -301,6 +301,8 @@ struct linger {
|
||||||
#define IPV6_V6ONLY 27 /* RFC3493: boolean control to restrict AF_INET6 sockets to IPv6 communications only. */
|
#define IPV6_V6ONLY 27 /* RFC3493: boolean control to restrict AF_INET6 sockets to IPv6 communications only. */
|
||||||
#define IPV6_RECVPKTINFO 49 /* RFC3542: receive ancillary data for packet */
|
#define IPV6_RECVPKTINFO 49 /* RFC3542: receive ancillary data for packet */
|
||||||
#define IPV6_PKTINFO 50 /* RFC3542: ancillary data for a packet */
|
#define IPV6_PKTINFO 50 /* RFC3542: ancillary data for a packet */
|
||||||
|
#define IPV6_RECVHOPLIMIT 51 /* RFC3542: receive hop limit for packet */
|
||||||
|
#define IPV6_HOPLIMIT 52 /* RFC3542: ancillary data containing hop limit for packet */
|
||||||
#endif /* LWIP_IPV6 */
|
#endif /* LWIP_IPV6 */
|
||||||
|
|
||||||
#if LWIP_UDP && LWIP_UDPLITE
|
#if LWIP_UDP && LWIP_UDPLITE
|
||||||
|
|
Loading…
Reference in New Issue
Block a user