Compare commits

...

3 Commits

Author SHA1 Message Date
Marcus Dreier
68f39e8d7e
Merge 149e52f2c5 into 1cc1536e6a 2024-04-15 15:59:06 +02:00
Erik Ekman
1cc1536e6a test/unit: fix inconsistent nullness check error
Inside a testcase, but still. Trying to address #160
2024-04-09 20:11:39 +02:00
Marcus Dreier
149e52f2c5 Patch #9977: New socket option IPV6_RECVPKTINFO 2023-08-09 16:46:06 +02:00
4 changed files with 94 additions and 22 deletions

View File

@ -1215,6 +1215,22 @@ lwip_recvfrom_udp_raw(struct lwip_sock *sock, int flags, struct msghdr *msg, u16
msg->msg_flags |= MSG_CTRUNC; msg->msg_flags |= MSG_CTRUNC;
} }
#endif /* LWIP_IPV4 */ #endif /* LWIP_IPV4 */
} else if (IP_IS_V6(&buf->toaddr)) {
#if LWIP_IPV6
if (msg->msg_controllen >= CMSG_SPACE(sizeof(struct in6_pktinfo))) {
struct cmsghdr *chdr = CMSG_FIRSTHDR(msg); /* This will always return a header!! */
struct in6_pktinfo *pkti = (struct in6_pktinfo *)CMSG_DATA(chdr);
chdr->cmsg_level = IPPROTO_IPV6;
chdr->cmsg_type = IPV6_PKTINFO;
chdr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
pkti->ipi6_ifindex = buf->p->if_idx;
inet6_addr_from_ip6addr(&pkti->ipi6_addr, ip_2_ip6(netbuf_destaddr(buf)));
msg->msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
wrote_msg = 1;
} else {
msg->msg_flags |= MSG_CTRUNC;
}
#endif /* LWIP_IPV6 */
} }
} }
#endif /* LWIP_NETBUF_RECVINFO */ #endif /* LWIP_NETBUF_RECVINFO */
@ -3711,6 +3727,16 @@ lwip_setsockopt_impl(int s, int level, int optname, const void *optval, socklen_
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IPV6, IPV6_V6ONLY, ..) -> %d\n", LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IPV6, IPV6_V6ONLY, ..) -> %d\n",
s, (netconn_get_ipv6only(sock->conn) ? 1 : 0))); s, (netconn_get_ipv6only(sock->conn) ? 1 : 0)));
break; break;
#if LWIP_NETBUF_RECVINFO
case IPV6_RECVPKTINFO:
LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_UDP);
if (*(const int *)optval) {
sock->conn->flags |= NETCONN_FLAG_PKTINFO;
} else {
sock->conn->flags &= ~NETCONN_FLAG_PKTINFO;
}
break;
#endif /* LWIP_NETBUF_RECVINFO */
#if LWIP_IPV6_MLD #if LWIP_IPV6_MLD
case IPV6_JOIN_GROUP: case IPV6_JOIN_GROUP:
case IPV6_LEAVE_GROUP: { case IPV6_LEAVE_GROUP: {

View File

@ -298,6 +298,8 @@ struct linger {
*/ */
#define IPV6_CHECKSUM 7 /* RFC3542: calculate and insert the ICMPv6 checksum for raw sockets. */ #define IPV6_CHECKSUM 7 /* RFC3542: calculate and insert the ICMPv6 checksum for raw sockets. */
#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: enables the receiving of ancillary data via setsockopt() */
#define IPV6_PKTINFO 50 /* RFC3542: ancillary data in recvmsg() received */
#endif /* LWIP_IPV6 */ #endif /* LWIP_IPV6 */
#if LWIP_UDP && LWIP_UDPLITE #if LWIP_UDP && LWIP_UDPLITE
@ -338,6 +340,13 @@ struct in_pktinfo {
}; };
#endif /* LWIP_IPV4 */ #endif /* LWIP_IPV4 */
#if LWIP_IPV6
struct in6_pktinfo {
unsigned int ipi6_ifindex; /* Interface index */
struct in6_addr ipi6_addr; /* Destination (from header) address */
};
#endif /* LWIP_IPV6 */
#if LWIP_IPV6_MLD #if LWIP_IPV6_MLD
/* /*
* Options and types related to IPv6 multicast membership * Options and types related to IPv6 multicast membership

View File

@ -10,6 +10,7 @@
#include "lwip/priv/tcp_priv.h" #include "lwip/priv/tcp_priv.h"
#include "lwip/api.h" #include "lwip/api.h"
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
static int static int
test_sockets_get_used_count(void) test_sockets_get_used_count(void)
@ -255,7 +256,7 @@ static void test_sockets_msgapi_update_iovs(struct msghdr *msg, size_t bytes)
/* note: this modifies the underlying iov_base and iov_len for a partial /* note: this modifies the underlying iov_base and iov_len for a partial
read for an individual vector. This updates the msg->msg_iov pointer read for an individual vector. This updates the msg->msg_iov pointer
to skip fully consumed vectors */ to skip fully consumed vectors */
/* process fully consumed vectors */ /* process fully consumed vectors */
for (i = 0; i < msg->msg_iovlen; i++) { for (i = 0; i < msg->msg_iovlen; i++) {
if (msg->msg_iov[i].iov_len <= bytes) { if (msg->msg_iov[i].iov_len <= bytes) {
@ -395,7 +396,7 @@ static void test_sockets_msgapi_tcp(int domain)
/* note: since we always receive after sending, there will be open /* note: since we always receive after sending, there will be open
space in the send buffer */ space in the send buffer */
fail_unless(ret > 0); fail_unless(ret > 0);
bytes_written += ret; bytes_written += ret;
if (bytes_written < TOTAL_DATA_SZ) { if (bytes_written < TOTAL_DATA_SZ) {
test_sockets_msgapi_update_iovs(&smsg, (size_t)ret); test_sockets_msgapi_update_iovs(&smsg, (size_t)ret);
@ -432,7 +433,7 @@ static void test_sockets_msgapi_tcp(int domain)
} }
} while(ret > 0); } while(ret > 0);
} }
ret = lwip_close(s1); ret = lwip_close(s1);
fail_unless(ret == 0); fail_unless(ret == 0);
ret = lwip_close(s2); ret = lwip_close(s2);
@ -544,7 +545,6 @@ static void test_sockets_msgapi_udp(int domain)
fail_unless(ret == 0); fail_unless(ret == 0);
} }
#if LWIP_IPV4
static void test_sockets_msgapi_cmsg(int domain) static void test_sockets_msgapi_cmsg(int domain)
{ {
int s, ret, enable; int s, ret, enable;
@ -553,10 +553,10 @@ static void test_sockets_msgapi_cmsg(int domain)
struct iovec iov; struct iovec iov;
struct msghdr msg; struct msghdr msg;
struct cmsghdr *cmsg; struct cmsghdr *cmsg;
struct in_pktinfo *pktinfo;
u8_t rcv_buf[4]; u8_t rcv_buf[4];
u8_t snd_buf[4] = {0xDE, 0xAD, 0xBE, 0xEF}; u8_t snd_buf[4] = {0xDE, 0xAD, 0xBE, 0xEF};
u8_t cmsg_buf[CMSG_SPACE(sizeof(struct in_pktinfo))]; u8_t cmsg_buf[CMSG_SPACE(MAX(sizeof(struct in_pktinfo),
sizeof(struct in6_pktinfo)))];
test_sockets_init_loopback_addr(domain, &addr_storage, &addr_size); test_sockets_init_loopback_addr(domain, &addr_storage, &addr_size);
@ -571,7 +571,15 @@ static void test_sockets_msgapi_cmsg(int domain)
fail_unless(ret == 0); fail_unless(ret == 0);
enable = 1; enable = 1;
ret = lwip_setsockopt(s, IPPROTO_IP, IP_PKTINFO, &enable, sizeof(enable)); if (domain == AF_INET) {
#if LWIP_IPV4
ret = lwip_setsockopt(s, IPPROTO_IP, IP_PKTINFO, &enable, sizeof(enable));
#endif
} else {
#if LWIP_IPV6
ret = lwip_setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO, &enable, sizeof(enable));
#endif
}
fail_unless(ret == 0); fail_unless(ret == 0);
/* Receive full message, including control message */ /* Receive full message, including control message */
@ -588,25 +596,42 @@ static void test_sockets_msgapi_cmsg(int domain)
memset(rcv_buf, 0, sizeof(rcv_buf)); memset(rcv_buf, 0, sizeof(rcv_buf));
ret = lwip_sendto(s, snd_buf, sizeof(snd_buf), 0, (struct sockaddr*)&addr_storage, addr_size); ret = lwip_sendto(s, snd_buf, sizeof(snd_buf), 0, (struct sockaddr*)&addr_storage, addr_size);
fail_unless(ret == sizeof(snd_buf)); fail_unless(ret == sizeof(snd_buf));
tcpip_thread_poll_one(); tcpip_thread_poll_one();
ret = lwip_recvmsg(s, &msg, 0); ret = lwip_recvmsg(s, &msg, 0);
fail_unless(ret == sizeof(rcv_buf)); fail_unless(ret == sizeof(rcv_buf));
fail_unless(!memcmp(rcv_buf, snd_buf, sizeof(rcv_buf))); fail_unless(!memcmp(rcv_buf, snd_buf, sizeof(rcv_buf)));
/* Verify message header */ /* Verify message header */
cmsg = CMSG_FIRSTHDR(&msg); cmsg = CMSG_FIRSTHDR(&msg);
fail_unless(cmsg != NULL); fail_unless(cmsg != NULL);
fail_unless(cmsg->cmsg_len > 0); fail_unless(cmsg->cmsg_len > 0);
fail_unless(cmsg->cmsg_level == IPPROTO_IP);
fail_unless(cmsg->cmsg_type == IP_PKTINFO);
/* Verify message data */ if (domain == AF_INET) {
pktinfo = (struct in_pktinfo*)CMSG_DATA(cmsg); struct in_pktinfo *pktinfo;
/* We only have loopback interface enabled */
fail_unless(pktinfo->ipi_ifindex == 1); fail_unless(cmsg->cmsg_level == IPPROTO_IP);
fail_unless(pktinfo->ipi_addr.s_addr == PP_HTONL(INADDR_LOOPBACK)); fail_unless(cmsg->cmsg_type == IP_PKTINFO);
/* Verify message data */
pktinfo = (struct in_pktinfo*)CMSG_DATA(cmsg);
/* We only have loopback interface enabled */
fail_unless(pktinfo->ipi_ifindex == 1);
fail_unless(pktinfo->ipi_addr.s_addr == PP_HTONL(INADDR_LOOPBACK));
} else {
struct in6_pktinfo *pktinfo;
struct in6_addr lo6 = IN6ADDR_LOOPBACK_INIT;
fail_unless(cmsg->cmsg_level == IPPROTO_IPV6);
fail_unless(cmsg->cmsg_type == IPV6_PKTINFO);
/* Verify message data */
pktinfo = (struct in6_pktinfo*)CMSG_DATA(cmsg);
/* We only have loopback interface enabled */
fail_unless(pktinfo->ipi6_ifindex == 1);
fail_unless(!memcmp(&pktinfo->ipi6_addr, &lo6, sizeof(pktinfo->ipi6_addr)));
}
/* Verify there are no additional messages */ /* Verify there are no additional messages */
cmsg = CMSG_NXTHDR(&msg, cmsg); cmsg = CMSG_NXTHDR(&msg, cmsg);
@ -632,7 +657,6 @@ static void test_sockets_msgapi_cmsg(int domain)
ret = lwip_close(s); ret = lwip_close(s);
fail_unless(ret == 0); fail_unless(ret == 0);
} }
#endif /* LWIP_IPV4 */
START_TEST(test_sockets_msgapis) START_TEST(test_sockets_msgapis)
{ {
@ -645,6 +669,7 @@ START_TEST(test_sockets_msgapis)
#if LWIP_IPV6 #if LWIP_IPV6
test_sockets_msgapi_udp(AF_INET6); test_sockets_msgapi_udp(AF_INET6);
test_sockets_msgapi_tcp(AF_INET6); test_sockets_msgapi_tcp(AF_INET6);
test_sockets_msgapi_cmsg(AF_INET6);
#endif #endif
} }
END_TEST END_TEST

View File

@ -88,6 +88,7 @@ START_TEST(test_pbuf_copy_zero_pbuf)
fail_unless(p2->ref == 1); fail_unless(p2->ref == 1);
p3 = pbuf_alloc(PBUF_RAW, p1->tot_len, PBUF_POOL); p3 = pbuf_alloc(PBUF_RAW, p1->tot_len, PBUF_POOL);
fail_unless(p3 != NULL);
err = pbuf_copy(p3, p1); err = pbuf_copy(p3, p1);
fail_unless(err == ERR_VAL); fail_unless(err == ERR_VAL);
@ -161,8 +162,8 @@ START_TEST(test_pbuf_copy_partial_pbuf)
b->payload = packet; b->payload = packet;
pbuf_cat(a, b); pbuf_cat(a, b);
dest = pbuf_alloc(PBUF_RAW, 14, PBUF_RAM); dest = pbuf_alloc(PBUF_RAW, 14, PBUF_RAM);
memset(dest->payload, 0, dest->len);
fail_unless(dest != NULL); fail_unless(dest != NULL);
memset(dest->payload, 0, dest->len);
/* Don't copy if data will not fit */ /* Don't copy if data will not fit */
err = pbuf_copy_partial_pbuf(dest, a, a->tot_len, 4); err = pbuf_copy_partial_pbuf(dest, a, a->tot_len, 4);
@ -198,6 +199,7 @@ START_TEST(test_pbuf_split_64k_on_small_pbufs)
LWIP_UNUSED_ARG(_i); LWIP_UNUSED_ARG(_i);
p = pbuf_alloc(PBUF_RAW, 1, PBUF_POOL); p = pbuf_alloc(PBUF_RAW, 1, PBUF_POOL);
fail_unless(p != NULL);
pbuf_split_64k(p, &rest); pbuf_split_64k(p, &rest);
fail_unless(p->tot_len == 1); fail_unless(p->tot_len == 1);
pbuf_free(p); pbuf_free(p);
@ -267,9 +269,14 @@ START_TEST(test_pbuf_take_at_edge)
u8_t *out; u8_t *out;
int i; int i;
u8_t testdata[] = { 0x01, 0x08, 0x82, 0x02 }; u8_t testdata[] = { 0x01, 0x08, 0x82, 0x02 };
struct pbuf *p = pbuf_alloc(PBUF_RAW, 1024, PBUF_POOL); struct pbuf *p;
struct pbuf *q = p->next; struct pbuf *q;
LWIP_UNUSED_ARG(_i); LWIP_UNUSED_ARG(_i);
p = pbuf_alloc(PBUF_RAW, 1024, PBUF_POOL);
fail_unless(p != NULL);
q = p->next;
/* alloc big enough to get a chain of pbufs */ /* alloc big enough to get a chain of pbufs */
fail_if(p->tot_len == p->len); fail_if(p->tot_len == p->len);
memset(p->payload, 0, p->len); memset(p->payload, 0, p->len);
@ -319,9 +326,14 @@ START_TEST(test_pbuf_get_put_at_edge)
u8_t *out; u8_t *out;
u8_t testdata = 0x01; u8_t testdata = 0x01;
u8_t getdata; u8_t getdata;
struct pbuf *p = pbuf_alloc(PBUF_RAW, 1024, PBUF_POOL); struct pbuf *p;
struct pbuf *q = p->next; struct pbuf *q;
LWIP_UNUSED_ARG(_i); LWIP_UNUSED_ARG(_i);
p = pbuf_alloc(PBUF_RAW, 1024, PBUF_POOL);
fail_unless(p != NULL);
q = p->next;
/* alloc big enough to get a chain of pbufs */ /* alloc big enough to get a chain of pbufs */
fail_if(p->tot_len == p->len); fail_if(p->tot_len == p->len);
memset(p->payload, 0, p->len); memset(p->payload, 0, p->len);