blob: b4f57ec18254662fc1f39308f9929fc27e200955 [file] [log] [blame]
/*
* Copyright (c) 2017 Linaro Limited
* Copyright (c) 2021 Nordic Semiconductor
* Copyright 2025 NXP
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(net_test, CONFIG_NET_SOCKETS_LOG_LEVEL);
#include <stdio.h>
#include <zephyr/sys/mutex.h>
#include <zephyr/ztest_assert.h>
#include <zephyr/net/socket.h>
#include <zephyr/net/ethernet.h>
#include <zephyr/net/net_mgmt.h>
#include <zephyr/net/net_event.h>
#include "ipv6.h"
#include "net_private.h"
#include "../../socket_helpers.h"
#if defined(CONFIG_NET_SOCKETS_LOG_LEVEL_DBG)
#define DBG(fmt, ...) printk(fmt, ##__VA_ARGS__)
#else
#define DBG(fmt, ...)
#endif
#define BUF_AND_SIZE(buf) buf, sizeof(buf) - 1
#define STRLEN(buf) (sizeof(buf) - 1)
#define TEST_STR_SMALL "test"
/* More than 256 bytes, to use >1 net_buf. */
#define TEST_STR2 \
"The Zephyr Project, a Linux Foundation hosted Collaboration " \
"Project, is an open source collaborative effort uniting leaders " \
"from across the industry to build a best-in-breed small, scalable, " \
"real-time operating system (RTOS) optimized for resource-" \
"constrained devices, across multiple architectures."
/* More than available TX buffers */
static const char test_str_all_tx_bufs[] =
#include <string_all_tx_bufs.inc>
"!"
;
#define MY_IPV4_ADDR "127.0.0.1"
#define MY_IPV4_MAPPED_ADDR "::ffff:127.0.0.1"
#define MY_IPV6_ADDR "::1"
#define MY_MCAST_IPV4_ADDR "224.0.0.1"
#define MY_MCAST_IPV6_ADDR "ff01::1"
#define ANY_IPV6_ADDR "::"
#define ANY_PORT 0
#define SERVER_PORT 4242
#define CLIENT_PORT 9898
static ZTEST_BMEM char rx_buf[NET_ETH_MTU + 1];
/* Common routine to communicate packets over pair of sockets. */
static void comm_sendto_recvfrom(int client_sock,
struct sockaddr *client_addr,
socklen_t client_addrlen,
int server_sock,
struct sockaddr *server_addr,
socklen_t server_addrlen)
{
int avail;
ssize_t sent = 0;
ssize_t recved = 0;
struct sockaddr addr;
socklen_t addrlen;
struct sockaddr addr2;
socklen_t addrlen2;
zassert_not_null(client_addr, "null client addr");
zassert_not_null(server_addr, "null server addr");
/*
* Test client -> server sending
*/
sent = zsock_sendto(client_sock, TEST_STR_SMALL, strlen(TEST_STR_SMALL),
0, server_addr, server_addrlen);
zassert_equal(sent, strlen(TEST_STR_SMALL), "sendto failed");
k_msleep(100);
avail = 42;
zassert_ok(zsock_ioctl(server_sock, ZFD_IOCTL_FIONREAD, &avail));
zassert_equal(avail, strlen(TEST_STR_SMALL));
/* Test recvfrom(MSG_PEEK) */
addrlen = sizeof(addr);
clear_buf(rx_buf);
recved = zsock_recvfrom(server_sock, rx_buf, sizeof(rx_buf),
ZSOCK_MSG_PEEK, &addr, &addrlen);
zassert_true(recved >= 0, "recvfrom fail");
zassert_equal(recved, strlen(TEST_STR_SMALL),
"unexpected received bytes");
zassert_mem_equal(rx_buf, BUF_AND_SIZE(TEST_STR_SMALL), "wrong data");
zassert_equal(addrlen, client_addrlen, "unexpected addrlen");
/* Test normal recvfrom() */
addrlen = sizeof(addr);
clear_buf(rx_buf);
recved = zsock_recvfrom(server_sock, rx_buf, sizeof(rx_buf),
0, &addr, &addrlen);
zassert_true(recved >= 0, "recvfrom fail");
zassert_equal(recved, strlen(TEST_STR_SMALL),
"unexpected received bytes");
zassert_mem_equal(rx_buf, BUF_AND_SIZE(TEST_STR_SMALL), "wrong data");
zassert_equal(addrlen, client_addrlen, "unexpected addrlen");
/* Check the client port */
if (net_sin(client_addr)->sin_port != ANY_PORT) {
zassert_equal(net_sin(client_addr)->sin_port,
net_sin(&addr)->sin_port,
"unexpected client port");
}
/*
* Test server -> client sending
*/
sent = zsock_sendto(server_sock, TEST_STR2, sizeof(TEST_STR2) - 1,
0, &addr, addrlen);
zassert_equal(sent, STRLEN(TEST_STR2), "sendto failed");
/* Test normal recvfrom() */
addrlen2 = sizeof(addr);
clear_buf(rx_buf);
recved = zsock_recvfrom(client_sock, rx_buf, sizeof(rx_buf),
0, &addr2, &addrlen2);
zassert_true(recved >= 0, "recvfrom fail");
zassert_equal(recved, STRLEN(TEST_STR2),
"unexpected received bytes");
zassert_mem_equal(rx_buf, BUF_AND_SIZE(TEST_STR2), "wrong data");
zassert_equal(addrlen2, server_addrlen, "unexpected addrlen");
/* Check the server port */
zassert_equal(net_sin(server_addr)->sin_port,
net_sin(&addr2)->sin_port,
"unexpected server port");
/* Test that unleft leftover data from datagram is discarded. */
/* Send 2 datagrams */
sent = zsock_sendto(server_sock, TEST_STR2, sizeof(TEST_STR2) - 1,
0, &addr, addrlen);
zassert_equal(sent, STRLEN(TEST_STR2), "sendto failed");
sent = zsock_sendto(server_sock, TEST_STR_SMALL, sizeof(TEST_STR_SMALL) - 1,
0, &addr, addrlen);
zassert_equal(sent, STRLEN(TEST_STR_SMALL), "sendto failed");
/* Receive just beginning of 1st datagram */
addrlen2 = sizeof(addr);
clear_buf(rx_buf);
recved = zsock_recvfrom(client_sock, rx_buf, 16, 0, &addr2, &addrlen2);
zassert_true(recved == 16, "recvfrom fail");
zassert_mem_equal(rx_buf, TEST_STR2, 16, "wrong data");
/* Make sure that now we receive 2nd datagram */
addrlen2 = sizeof(addr);
clear_buf(rx_buf);
recved = zsock_recvfrom(client_sock, rx_buf, 16, 0, &addr2, &addrlen2);
zassert_true(recved == STRLEN(TEST_STR_SMALL), "recvfrom fail");
zassert_mem_equal(rx_buf, BUF_AND_SIZE(TEST_STR_SMALL), "wrong data");
}
ZTEST(net_socket_udp, test_02_v4_sendto_recvfrom)
{
int rv;
int client_sock;
int server_sock;
struct sockaddr_in client_addr;
struct sockaddr_in server_addr;
prepare_sock_udp_v4(MY_IPV4_ADDR, ANY_PORT, &client_sock, &client_addr);
prepare_sock_udp_v4(MY_IPV4_ADDR, SERVER_PORT, &server_sock, &server_addr);
rv = zsock_bind(server_sock,
(struct sockaddr *)&server_addr,
sizeof(server_addr));
zassert_equal(rv, 0, "bind failed");
comm_sendto_recvfrom(client_sock,
(struct sockaddr *)&client_addr,
sizeof(client_addr),
server_sock,
(struct sockaddr *)&server_addr,
sizeof(server_addr));
rv = zsock_close(client_sock);
zassert_equal(rv, 0, "close failed");
rv = zsock_close(server_sock);
zassert_equal(rv, 0, "close failed");
}
ZTEST(net_socket_udp, test_03_v6_sendto_recvfrom)
{
int rv;
int client_sock;
int server_sock;
struct sockaddr_in6 client_addr;
struct sockaddr_in6 server_addr;
prepare_sock_udp_v6(MY_IPV6_ADDR, ANY_PORT, &client_sock, &client_addr);
prepare_sock_udp_v6(MY_IPV6_ADDR, SERVER_PORT, &server_sock, &server_addr);
rv = zsock_bind(server_sock,
(struct sockaddr *)&server_addr, sizeof(server_addr));
zassert_equal(rv, 0, "bind failed");
comm_sendto_recvfrom(client_sock,
(struct sockaddr *)&client_addr,
sizeof(client_addr),
server_sock,
(struct sockaddr *)&server_addr,
sizeof(server_addr));
rv = zsock_close(client_sock);
zassert_equal(rv, 0, "close failed");
rv = zsock_close(server_sock);
zassert_equal(rv, 0, "close failed");
}
ZTEST(net_socket_udp, test_04_v4_bind_sendto)
{
int rv;
int client_sock;
int server_sock;
struct sockaddr_in client_addr;
struct sockaddr_in server_addr;
prepare_sock_udp_v4(MY_IPV4_ADDR, CLIENT_PORT, &client_sock, &client_addr);
prepare_sock_udp_v4(MY_IPV4_ADDR, SERVER_PORT, &server_sock, &server_addr);
rv = zsock_bind(client_sock,
(struct sockaddr *)&client_addr, sizeof(client_addr));
zassert_equal(rv, 0, "bind failed");
rv = zsock_bind(server_sock,
(struct sockaddr *)&server_addr, sizeof(server_addr));
zassert_equal(rv, 0, "bind failed");
comm_sendto_recvfrom(client_sock,
(struct sockaddr *)&client_addr,
sizeof(client_addr),
server_sock,
(struct sockaddr *)&server_addr,
sizeof(server_addr));
rv = zsock_close(client_sock);
zassert_equal(rv, 0, "close failed");
rv = zsock_close(server_sock);
zassert_equal(rv, 0, "close failed");
}
ZTEST(net_socket_udp, test_05_v6_bind_sendto)
{
int rv;
int client_sock;
int server_sock;
struct sockaddr_in6 client_addr;
struct sockaddr_in6 server_addr;
prepare_sock_udp_v6(MY_IPV6_ADDR, CLIENT_PORT, &client_sock, &client_addr);
prepare_sock_udp_v6(MY_IPV6_ADDR, SERVER_PORT, &server_sock, &server_addr);
rv = zsock_bind(client_sock,
(struct sockaddr *)&client_addr, sizeof(client_addr));
zassert_equal(rv, 0, "bind failed");
rv = zsock_bind(server_sock,
(struct sockaddr *)&server_addr, sizeof(server_addr));
zassert_equal(rv, 0, "bind failed");
comm_sendto_recvfrom(client_sock,
(struct sockaddr *)&client_addr,
sizeof(client_addr),
server_sock,
(struct sockaddr *)&server_addr,
sizeof(server_addr));
rv = zsock_close(client_sock);
zassert_equal(rv, 0, "close failed");
rv = zsock_close(server_sock);
zassert_equal(rv, 0, "close failed");
}
ZTEST(net_socket_udp, test_01_send_recv_2_sock)
{
int sock1, sock2;
struct sockaddr_in bind_addr, conn_addr;
char buf[10];
int len, rv;
prepare_sock_udp_v4(MY_IPV4_ADDR, 55555, &sock1, &bind_addr);
prepare_sock_udp_v4(MY_IPV4_ADDR, 55555, &sock2, &conn_addr);
rv = zsock_bind(sock1, (struct sockaddr *)&bind_addr, sizeof(bind_addr));
zassert_equal(rv, 0, "bind failed");
rv = zsock_connect(sock2, (struct sockaddr *)&conn_addr, sizeof(conn_addr));
zassert_equal(rv, 0, "connect failed");
len = zsock_send(sock2, TEST_STR_SMALL, sizeof(TEST_STR_SMALL) - 1, 0);
zassert_equal(len, STRLEN(TEST_STR_SMALL), "invalid send len");
clear_buf(buf);
len = zsock_recv(sock1, buf, sizeof(buf), ZSOCK_MSG_PEEK);
zassert_equal(len, STRLEN(TEST_STR_SMALL), "Invalid recv len");
zassert_mem_equal(buf, BUF_AND_SIZE(TEST_STR_SMALL), "Wrong data");
clear_buf(buf);
len = zsock_recv(sock1, buf, sizeof(buf), 0);
zassert_equal(len, STRLEN(TEST_STR_SMALL), "Invalid recv len");
zassert_mem_equal(buf, BUF_AND_SIZE(TEST_STR_SMALL), "Wrong data");
rv = zsock_close(sock1);
zassert_equal(rv, 0, "close failed");
rv = zsock_close(sock2);
zassert_equal(rv, 0, "close failed");
}
ZTEST(net_socket_udp, test_07_so_priority)
{
struct sockaddr_in bind_addr4;
struct sockaddr_in6 bind_addr6;
int sock1, sock2, rv;
uint8_t optval;
prepare_sock_udp_v4(MY_IPV4_ADDR, 55555, &sock1, &bind_addr4);
prepare_sock_udp_v6(MY_IPV6_ADDR, 55555, &sock2, &bind_addr6);
rv = zsock_bind(sock1, (struct sockaddr *)&bind_addr4, sizeof(bind_addr4));
zassert_equal(rv, 0, "bind failed");
rv = zsock_bind(sock2, (struct sockaddr *)&bind_addr6, sizeof(bind_addr6));
zassert_equal(rv, 0, "bind failed");
optval = 2;
rv = zsock_setsockopt(sock1, SOL_SOCKET, SO_PRIORITY, &optval,
sizeof(optval));
zassert_equal(rv, 0, "setsockopt failed (%d)", errno);
optval = 6;
rv = zsock_setsockopt(sock2, SOL_SOCKET, SO_PRIORITY, &optval,
sizeof(optval));
zassert_equal(rv, 0, "setsockopt failed");
rv = zsock_close(sock1);
zassert_equal(rv, 0, "close failed");
rv = zsock_close(sock2);
zassert_equal(rv, 0, "close failed");
}
static void comm_sendmsg_recvfrom(int client_sock,
struct sockaddr *client_addr,
socklen_t client_addrlen,
const struct msghdr *client_msg,
int server_sock,
struct sockaddr *server_addr,
socklen_t server_addrlen)
{
ssize_t sent;
ssize_t recved;
struct sockaddr addr;
socklen_t addrlen;
int len, i;
zassert_not_null(client_addr, "null client addr");
zassert_not_null(server_addr, "null server addr");
/*
* Test client -> server sending
*/
sent = zsock_sendmsg(client_sock, client_msg, 0);
zassert_true(sent > 0, "sendmsg failed (%d)", -errno);
for (i = 0, len = 0; i < client_msg->msg_iovlen; i++) {
len += client_msg->msg_iov[i].iov_len;
}
zassert_equal(sent, len, "iovec len (%d) vs sent (%d)", len, sent);
/* Test recvfrom(MSG_PEEK) */
addrlen = sizeof(addr);
clear_buf(rx_buf);
recved = zsock_recvfrom(server_sock, rx_buf, sizeof(rx_buf),
ZSOCK_MSG_PEEK, &addr, &addrlen);
zassert_true(recved >= 0, "recvfrom fail");
zassert_equal(recved, strlen(TEST_STR_SMALL),
"unexpected received bytes");
zassert_equal(sent, recved, "sent(%d)/received(%d) mismatch",
sent, recved);
zassert_mem_equal(rx_buf, BUF_AND_SIZE(TEST_STR_SMALL),
"wrong data (%s)", rx_buf);
zassert_equal(addrlen, client_addrlen, "unexpected addrlen");
/* Test normal recvfrom() */
addrlen = sizeof(addr);
clear_buf(rx_buf);
recved = zsock_recvfrom(server_sock, rx_buf, sizeof(rx_buf),
0, &addr, &addrlen);
zassert_true(recved >= 0, "recvfrom fail");
zassert_equal(recved, strlen(TEST_STR_SMALL),
"unexpected received bytes");
zassert_mem_equal(rx_buf, BUF_AND_SIZE(TEST_STR_SMALL), "wrong data");
zassert_equal(addrlen, client_addrlen, "unexpected addrlen");
/* Check the client port */
if (net_sin(client_addr)->sin_port != ANY_PORT) {
zassert_equal(net_sin(client_addr)->sin_port,
net_sin(&addr)->sin_port,
"unexpected client port");
}
}
ZTEST_USER(net_socket_udp, test_12_v4_sendmsg_recvfrom)
{
int rv;
int client_sock;
int server_sock;
struct sockaddr_in client_addr;
struct sockaddr_in server_addr;
struct msghdr msg;
struct cmsghdr *cmsg;
struct iovec io_vector[1];
union {
struct cmsghdr hdr;
unsigned char buf[CMSG_SPACE(sizeof(int))];
} cmsgbuf;
prepare_sock_udp_v4(MY_IPV4_ADDR, ANY_PORT, &client_sock, &client_addr);
prepare_sock_udp_v4(MY_IPV4_ADDR, SERVER_PORT, &server_sock, &server_addr);
rv = zsock_bind(server_sock,
(struct sockaddr *)&server_addr,
sizeof(server_addr));
zassert_equal(rv, 0, "server bind failed");
rv = zsock_bind(client_sock,
(struct sockaddr *)&client_addr,
sizeof(client_addr));
zassert_equal(rv, 0, "client bind failed");
io_vector[0].iov_base = TEST_STR_SMALL;
io_vector[0].iov_len = strlen(TEST_STR_SMALL);
memset(&msg, 0, sizeof(msg));
msg.msg_control = &cmsgbuf.buf;
msg.msg_controllen = sizeof(cmsgbuf.buf);
msg.msg_iov = io_vector;
msg.msg_iovlen = 1;
msg.msg_name = &server_addr;
msg.msg_namelen = sizeof(server_addr);
cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = 1122;
*(int *)CMSG_DATA(cmsg) = 42;
comm_sendmsg_recvfrom(client_sock,
(struct sockaddr *)&client_addr,
sizeof(client_addr),
&msg,
server_sock,
(struct sockaddr *)&server_addr,
sizeof(server_addr));
rv = zsock_close(client_sock);
zassert_equal(rv, 0, "close failed");
rv = zsock_close(server_sock);
zassert_equal(rv, 0, "close failed");
}
ZTEST_USER(net_socket_udp, test_13_v4_sendmsg_recvfrom_no_aux_data)
{
int rv;
int client_sock;
int server_sock;
struct sockaddr_in client_addr;
struct sockaddr_in server_addr;
struct msghdr msg;
struct iovec io_vector[1];
prepare_sock_udp_v4(MY_IPV4_ADDR, ANY_PORT, &client_sock, &client_addr);
prepare_sock_udp_v4(MY_IPV4_ADDR, SERVER_PORT, &server_sock, &server_addr);
rv = zsock_bind(server_sock,
(struct sockaddr *)&server_addr,
sizeof(server_addr));
zassert_equal(rv, 0, "server bind failed");
rv = zsock_bind(client_sock,
(struct sockaddr *)&client_addr,
sizeof(client_addr));
zassert_equal(rv, 0, "client bind failed");
io_vector[0].iov_base = TEST_STR_SMALL;
io_vector[0].iov_len = strlen(TEST_STR_SMALL);
memset(&msg, 0, sizeof(msg));
msg.msg_iov = io_vector;
msg.msg_iovlen = 1;
msg.msg_name = &server_addr;
msg.msg_namelen = sizeof(server_addr);
comm_sendmsg_recvfrom(client_sock,
(struct sockaddr *)&client_addr,
sizeof(client_addr),
&msg,
server_sock,
(struct sockaddr *)&server_addr,
sizeof(server_addr));
rv = zsock_close(client_sock);
zassert_equal(rv, 0, "close failed");
rv = zsock_close(server_sock);
zassert_equal(rv, 0, "close failed");
}
ZTEST_USER(net_socket_udp, test_14_v6_sendmsg_recvfrom)
{
int rv;
int client_sock;
int server_sock;
struct sockaddr_in6 client_addr;
struct sockaddr_in6 server_addr;
struct msghdr msg;
struct cmsghdr *cmsg;
struct iovec io_vector[1];
union {
struct cmsghdr hdr;
unsigned char buf[CMSG_SPACE(sizeof(int))];
} cmsgbuf;
prepare_sock_udp_v6(MY_IPV6_ADDR, ANY_PORT, &client_sock, &client_addr);
prepare_sock_udp_v6(MY_IPV6_ADDR, SERVER_PORT, &server_sock, &server_addr);
rv = zsock_bind(server_sock,
(struct sockaddr *)&server_addr, sizeof(server_addr));
zassert_equal(rv, 0, "server bind failed");
rv = zsock_bind(client_sock,
(struct sockaddr *)&client_addr,
sizeof(client_addr));
zassert_equal(rv, 0, "client bind failed");
io_vector[0].iov_base = TEST_STR_SMALL;
io_vector[0].iov_len = strlen(TEST_STR_SMALL);
memset(&msg, 0, sizeof(msg));
msg.msg_control = &cmsgbuf.buf;
msg.msg_controllen = sizeof(cmsgbuf.buf);
msg.msg_iov = io_vector;
msg.msg_iovlen = 1;
msg.msg_name = &server_addr;
msg.msg_namelen = sizeof(server_addr);
cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = 1122;
*(int *)CMSG_DATA(cmsg) = 42;
comm_sendmsg_recvfrom(client_sock,
(struct sockaddr *)&client_addr,
sizeof(client_addr),
&msg,
server_sock,
(struct sockaddr *)&server_addr,
sizeof(server_addr));
rv = zsock_close(client_sock);
zassert_equal(rv, 0, "close failed");
rv = zsock_close(server_sock);
zassert_equal(rv, 0, "close failed");
}
ZTEST_USER(net_socket_udp, test_15_v4_sendmsg_recvfrom_connected)
{
int rv;
int client_sock;
int server_sock;
struct sockaddr_in client_addr;
struct sockaddr_in server_addr;
struct msghdr msg;
struct cmsghdr *cmsg;
struct iovec io_vector[1];
union {
struct cmsghdr hdr;
unsigned char buf[CMSG_SPACE(sizeof(int))];
} cmsgbuf;
prepare_sock_udp_v4(MY_IPV4_ADDR, ANY_PORT, &client_sock, &client_addr);
prepare_sock_udp_v4(MY_IPV4_ADDR, SERVER_PORT, &server_sock, &server_addr);
rv = zsock_bind(server_sock,
(struct sockaddr *)&server_addr,
sizeof(server_addr));
zassert_equal(rv, 0, "server bind failed");
rv = zsock_bind(client_sock,
(struct sockaddr *)&client_addr,
sizeof(client_addr));
zassert_equal(rv, 0, "client bind failed");
rv = zsock_connect(client_sock, (struct sockaddr *)&server_addr,
sizeof(server_addr));
zassert_equal(rv, 0, "connect failed");
io_vector[0].iov_base = TEST_STR_SMALL;
io_vector[0].iov_len = strlen(TEST_STR_SMALL);
memset(&msg, 0, sizeof(msg));
msg.msg_control = &cmsgbuf.buf;
msg.msg_controllen = sizeof(cmsgbuf.buf);
msg.msg_iov = io_vector;
msg.msg_iovlen = 1;
cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = 1122;
*(int *)CMSG_DATA(cmsg) = 42;
comm_sendmsg_recvfrom(client_sock,
(struct sockaddr *)&client_addr,
sizeof(client_addr),
&msg,
server_sock,
(struct sockaddr *)&server_addr,
sizeof(server_addr));
rv = zsock_close(client_sock);
zassert_equal(rv, 0, "close failed");
rv = zsock_close(server_sock);
zassert_equal(rv, 0, "close failed");
}
ZTEST_USER(net_socket_udp, test_06_v6_sendmsg_recvfrom_connected)
{
int rv;
int client_sock;
int server_sock;
struct sockaddr_in6 client_addr;
struct sockaddr_in6 server_addr;
struct msghdr msg;
struct cmsghdr *cmsg;
struct iovec io_vector[1];
union {
struct cmsghdr hdr;
unsigned char buf[CMSG_SPACE(sizeof(int))];
} cmsgbuf;
prepare_sock_udp_v6(MY_IPV6_ADDR, ANY_PORT, &client_sock, &client_addr);
prepare_sock_udp_v6(MY_IPV6_ADDR, SERVER_PORT, &server_sock, &server_addr);
rv = zsock_bind(server_sock,
(struct sockaddr *)&server_addr, sizeof(server_addr));
zassert_equal(rv, 0, "server bind failed");
rv = zsock_bind(client_sock,
(struct sockaddr *)&client_addr,
sizeof(client_addr));
zassert_equal(rv, 0, "client bind failed");
rv = zsock_connect(client_sock, (struct sockaddr *)&server_addr,
sizeof(server_addr));
zassert_equal(rv, 0, "connect failed");
io_vector[0].iov_base = TEST_STR_SMALL;
io_vector[0].iov_len = strlen(TEST_STR_SMALL);
memset(&msg, 0, sizeof(msg));
msg.msg_control = &cmsgbuf.buf;
msg.msg_controllen = sizeof(cmsgbuf.buf);
msg.msg_iov = io_vector;
msg.msg_iovlen = 1;
cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = 1122;
*(int *)CMSG_DATA(cmsg) = 42;
comm_sendmsg_recvfrom(client_sock,
(struct sockaddr *)&client_addr,
sizeof(client_addr),
&msg,
server_sock,
(struct sockaddr *)&server_addr,
sizeof(server_addr));
rv = zsock_close(client_sock);
zassert_equal(rv, 0, "close failed");
rv = zsock_close(server_sock);
zassert_equal(rv, 0, "close failed");
}
ZTEST(net_socket_udp, test_06_so_type)
{
struct sockaddr_in bind_addr4;
struct sockaddr_in6 bind_addr6;
int sock1, sock2, rv;
int optval;
socklen_t optsize = sizeof(optval);
prepare_sock_udp_v4(MY_IPV4_ADDR, 55555, &sock1, &bind_addr4);
prepare_sock_udp_v6(MY_IPV6_ADDR, 55555, &sock2, &bind_addr6);
rv = zsock_getsockopt(sock1, SOL_SOCKET, SO_TYPE, &optval, &optsize);
zassert_equal(rv, 0, "getsockopt failed (%d)", errno);
zassert_equal(optval, SOCK_DGRAM, "getsockopt got invalid type");
zassert_equal(optsize, sizeof(optval), "getsockopt got invalid size");
rv = zsock_getsockopt(sock2, SOL_SOCKET, SO_TYPE, &optval, &optsize);
zassert_equal(rv, 0, "getsockopt failed (%d)", errno);
zassert_equal(optval, SOCK_DGRAM, "getsockopt got invalid type");
zassert_equal(optsize, sizeof(optval), "getsockopt got invalid size");
rv = zsock_close(sock1);
zassert_equal(rv, 0, "close failed");
rv = zsock_close(sock2);
zassert_equal(rv, 0, "close failed");
}
ZTEST(net_socket_udp, test_08_so_txtime)
{
struct sockaddr_in bind_addr4;
struct sockaddr_in6 bind_addr6;
int sock1, sock2, rv;
socklen_t optlen;
int optval;
prepare_sock_udp_v4(MY_IPV4_ADDR, 55555, &sock1, &bind_addr4);
prepare_sock_udp_v6(MY_IPV6_ADDR, 55555, &sock2, &bind_addr6);
rv = zsock_bind(sock1, (struct sockaddr *)&bind_addr4, sizeof(bind_addr4));
zassert_equal(rv, 0, "bind failed");
rv = zsock_bind(sock2, (struct sockaddr *)&bind_addr6, sizeof(bind_addr6));
zassert_equal(rv, 0, "bind failed");
optval = true;
rv = zsock_setsockopt(sock1, SOL_SOCKET, SO_TXTIME, &optval,
sizeof(optval));
zassert_equal(rv, 0, "setsockopt failed (%d)", errno);
optval = false;
rv = zsock_setsockopt(sock2, SOL_SOCKET, SO_TXTIME, &optval,
sizeof(optval));
zassert_equal(rv, 0, "setsockopt failed");
optlen = sizeof(optval);
rv = zsock_getsockopt(sock1, SOL_SOCKET, SO_TXTIME, &optval, &optlen);
zassert_equal(rv, 0, "getsockopt failed (%d)", errno);
zassert_equal(optlen, sizeof(optval), "invalid optlen %d vs %d",
optlen, sizeof(optval));
zassert_equal(optval, true, "getsockopt txtime");
optlen = sizeof(optval);
rv = zsock_getsockopt(sock2, SOL_SOCKET, SO_TXTIME, &optval, &optlen);
zassert_equal(rv, 0, "getsockopt failed (%d)", errno);
zassert_equal(optlen, sizeof(optval), "invalid optlen %d vs %d",
optlen, sizeof(optval));
zassert_equal(optval, false, "getsockopt txtime");
rv = zsock_close(sock1);
zassert_equal(rv, 0, "close failed");
rv = zsock_close(sock2);
zassert_equal(rv, 0, "close failed");
}
ZTEST(net_socket_udp, test_09_so_rcvtimeo)
{
struct sockaddr_in bind_addr4;
struct sockaddr_in6 bind_addr6;
int sock1, sock2, rv;
ssize_t recved = 0;
struct sockaddr addr;
socklen_t addrlen;
uint32_t start_time, time_diff;
struct timeval optval = {
.tv_sec = 0,
.tv_usec = 300000,
};
prepare_sock_udp_v4(MY_IPV4_ADDR, 55555, &sock1, &bind_addr4);
prepare_sock_udp_v6(MY_IPV6_ADDR, 55555, &sock2, &bind_addr6);
rv = zsock_bind(sock1, (struct sockaddr *)&bind_addr4, sizeof(bind_addr4));
zassert_equal(rv, 0, "bind failed");
rv = zsock_bind(sock2, (struct sockaddr *)&bind_addr6, sizeof(bind_addr6));
zassert_equal(rv, 0, "bind failed");
rv = zsock_setsockopt(sock1, SOL_SOCKET, SO_RCVTIMEO, &optval,
sizeof(optval));
zassert_equal(rv, 0, "setsockopt failed (%d)", errno);
optval.tv_usec = 400000;
rv = zsock_setsockopt(sock2, SOL_SOCKET, SO_RCVTIMEO, &optval,
sizeof(optval));
zassert_equal(rv, 0, "setsockopt failed (%d)", errno);
addrlen = sizeof(addr);
clear_buf(rx_buf);
start_time = k_uptime_get_32();
recved = zsock_recvfrom(sock1, rx_buf, sizeof(rx_buf),
0, &addr, &addrlen);
time_diff = k_uptime_get_32() - start_time;
zassert_equal(recved, -1, "Unexpected return code");
zassert_equal(errno, EAGAIN, "Unexpected errno value: %d", errno);
zassert_true(time_diff >= 300, "Expected timeout after 300ms but "
"was %dms", time_diff);
start_time = k_uptime_get_32();
recved = zsock_recvfrom(sock2, rx_buf, sizeof(rx_buf),
0, &addr, &addrlen);
time_diff = k_uptime_get_32() - start_time;
zassert_equal(recved, -1, "Unexpected return code");
zassert_equal(errno, EAGAIN, "Unexpected errno value: %d", errno);
zassert_true(time_diff >= 400, "Expected timeout after 400ms but "
"was %dms", time_diff);
rv = zsock_close(sock1);
zassert_equal(rv, 0, "close failed");
rv = zsock_close(sock2);
zassert_equal(rv, 0, "close failed");
}
ZTEST(net_socket_udp, test_10_so_sndtimeo)
{
struct sockaddr_in bind_addr4;
struct sockaddr_in6 bind_addr6;
int sock1, sock2, rv;
struct timeval optval = {
.tv_sec = 2,
.tv_usec = 500000,
};
prepare_sock_udp_v4(MY_IPV4_ADDR, 55555, &sock1, &bind_addr4);
prepare_sock_udp_v6(MY_IPV6_ADDR, 55555, &sock2, &bind_addr6);
rv = zsock_bind(sock1, (struct sockaddr *)&bind_addr4, sizeof(bind_addr4));
zassert_equal(rv, 0, "bind failed");
rv = zsock_bind(sock2, (struct sockaddr *)&bind_addr6, sizeof(bind_addr6));
zassert_equal(rv, 0, "bind failed");
rv = zsock_setsockopt(sock1, SOL_SOCKET, SO_SNDTIMEO, &optval,
sizeof(optval));
zassert_equal(rv, 0, "setsockopt failed (%d)", errno);
optval.tv_usec = 0;
rv = zsock_setsockopt(sock2, SOL_SOCKET, SO_SNDTIMEO, &optval,
sizeof(optval));
zassert_equal(rv, 0, "setsockopt failed");
rv = zsock_close(sock1);
zassert_equal(rv, 0, "close failed");
rv = zsock_close(sock2);
zassert_equal(rv, 0, "close failed");
}
ZTEST(net_socket_udp, test_11_so_protocol)
{
struct sockaddr_in bind_addr4;
struct sockaddr_in6 bind_addr6;
int sock1, sock2, rv;
int optval;
socklen_t optsize = sizeof(optval);
prepare_sock_udp_v4(MY_IPV4_ADDR, 55555, &sock1, &bind_addr4);
prepare_sock_udp_v6(MY_IPV6_ADDR, 55555, &sock2, &bind_addr6);
rv = zsock_getsockopt(sock1, SOL_SOCKET, SO_PROTOCOL, &optval, &optsize);
zassert_equal(rv, 0, "getsockopt failed (%d)", errno);
zassert_equal(optval, IPPROTO_UDP, "getsockopt got invalid protocol");
zassert_equal(optsize, sizeof(optval), "getsockopt got invalid size");
rv = zsock_getsockopt(sock2, SOL_SOCKET, SO_PROTOCOL, &optval, &optsize);
zassert_equal(rv, 0, "getsockopt failed (%d)", errno);
zassert_equal(optval, IPPROTO_UDP, "getsockopt got invalid protocol");
zassert_equal(optsize, sizeof(optval), "getsockopt got invalid size");
rv = zsock_close(sock1);
zassert_equal(rv, 0, "close failed");
rv = zsock_close(sock2);
zassert_equal(rv, 0, "close failed");
}
static void comm_sendmsg_with_txtime(int client_sock,
struct sockaddr *client_addr,
socklen_t client_addrlen,
const struct msghdr *client_msg)
{
ssize_t sent;
int len, i;
zassert_not_null(client_addr, "null client addr");
/*
* Test client -> server sending
*/
sent = zsock_sendmsg(client_sock, client_msg, 0);
zassert_true(sent > 0, "sendmsg failed (%d)", -errno);
for (i = 0, len = 0; i < client_msg->msg_iovlen; i++) {
len += client_msg->msg_iov[i].iov_len;
}
zassert_equal(sent, len, "iovec len (%d) vs sent (%d)", len, sent);
}
/* In order to verify that the network device driver is able to receive
* the TXTIME option, create a separate network device and catch the packets
* we are sending.
*/
struct eth_fake_context {
struct net_if *iface;
uint8_t mac_address[6];
};
static struct eth_fake_context eth_fake_data;
static ZTEST_BMEM struct sockaddr_in6 udp_server_addr;
/* The semaphore is there to wait the data to be received. */
static ZTEST_BMEM SYS_MUTEX_DEFINE(wait_data);
static struct net_if *eth_iface;
static struct net_if *lo0;
static ZTEST_BMEM bool test_started;
static ZTEST_BMEM bool test_failed;
static struct in6_addr my_addr1 = { { { 0x20, 0x01, 0x0d, 0xb8, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0x1 } } };
static struct in_addr my_addr2 = { { { 192, 0, 2, 2 } } };
static struct in6_addr my_addr3 = { { { 0x20, 0x01, 0x0d, 0xb8, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0x3 } } };
static struct in6_addr my_mcast_addr1 = { { { 0xff, 0x01, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0x1 } } };
static struct in_addr my_mcast_addr2 = { { { 224, 0, 0, 2 } } };
static struct net_linkaddr server_link_addr = {
.addr = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 },
.len = NET_ETH_ADDR_LEN,
};
#define MY_IPV6_ADDR_ETH "2001:db8:100::1"
#define PEER_IPV6_ADDR_ETH "2001:db8:100::2"
#define TEST_TXTIME INT64_MAX
#define WAIT_TIME K_MSEC(250)
#define WAIT_TIME_LONG K_MSEC(1000)
static void eth_fake_iface_init(struct net_if *iface)
{
const struct device *dev = net_if_get_device(iface);
struct eth_fake_context *ctx = dev->data;
ctx->iface = iface;
net_if_set_link_addr(iface, ctx->mac_address,
sizeof(ctx->mac_address),
NET_LINK_ETHERNET);
ethernet_init(iface);
}
static int eth_fake_send(const struct device *dev, struct net_pkt *pkt)
{
net_time_t txtime;
ARG_UNUSED(dev);
ARG_UNUSED(pkt);
if (!test_started) {
return 0;
}
txtime = net_pkt_timestamp_ns(pkt);
if (txtime != TEST_TXTIME) {
test_failed = true;
} else {
test_failed = false;
}
sys_mutex_unlock(&wait_data);
return 0;
}
static struct ethernet_api eth_fake_api_funcs = {
.iface_api.init = eth_fake_iface_init,
.send = eth_fake_send,
};
ETH_NET_DEVICE_INIT(eth_fake, "eth_fake", NULL, NULL, &eth_fake_data, NULL,
CONFIG_ETH_INIT_PRIORITY, &eth_fake_api_funcs, NET_ETH_MTU);
static void iface_cb(struct net_if *iface, void *user_data)
{
struct net_if **my_iface = user_data;
if (net_if_l2(iface) == &NET_L2_GET_NAME(ETHERNET)) {
if (PART_OF_ARRAY(NET_IF_GET_NAME(eth_fake, 0), iface)) {
*my_iface = iface;
}
}
if (net_if_l2(iface) == &NET_L2_GET_NAME(DUMMY)) {
lo0 = iface;
net_if_set_default(iface);
}
}
ZTEST(net_socket_udp, test_17_setup_eth_for_ipv6)
{
struct net_if_addr *ifaddr;
int ret;
net_if_foreach(iface_cb, &eth_iface);
zassert_not_null(eth_iface, "No ethernet interface found");
ifaddr = net_if_ipv6_addr_add(eth_iface, &my_addr1,
NET_ADDR_MANUAL, 0);
if (!ifaddr) {
DBG("Cannot add IPv6 address %s\n",
net_sprint_ipv6_addr(&my_addr1));
zassert_not_null(ifaddr, "addr1");
}
net_if_up(eth_iface);
(void)memset(&udp_server_addr, 0, sizeof(udp_server_addr));
udp_server_addr.sin6_family = AF_INET6;
udp_server_addr.sin6_port = htons(1234);
ret = zsock_inet_pton(AF_INET6, PEER_IPV6_ADDR_ETH, &udp_server_addr.sin6_addr);
zassert_equal(ret, 1, "inet_pton failed");
/* In order to avoid neighbor discovery, populate neighbor cache */
net_ipv6_nbr_add(eth_iface, &udp_server_addr.sin6_addr, &server_link_addr,
true, NET_IPV6_NBR_STATE_REACHABLE);
}
ZTEST_USER(net_socket_udp, test_18_v6_sendmsg_with_txtime)
{
int rv;
int client_sock;
int optval;
net_time_t txtime;
struct sockaddr_in6 client_addr;
struct msghdr msg;
struct cmsghdr *cmsg;
struct iovec io_vector[1];
union {
struct cmsghdr hdr;
unsigned char buf[CMSG_SPACE(sizeof(uint64_t))];
} cmsgbuf;
prepare_sock_udp_v6(MY_IPV6_ADDR_ETH, ANY_PORT, &client_sock, &client_addr);
rv = zsock_bind(client_sock,
(struct sockaddr *)&client_addr,
sizeof(client_addr));
zassert_equal(rv, 0, "client bind failed");
io_vector[0].iov_base = TEST_STR_SMALL;
io_vector[0].iov_len = strlen(TEST_STR_SMALL);
memset(&msg, 0, sizeof(msg));
msg.msg_control = &cmsgbuf.buf;
msg.msg_controllen = sizeof(cmsgbuf.buf);
msg.msg_iov = io_vector;
msg.msg_iovlen = 1;
msg.msg_name = &udp_server_addr;
msg.msg_namelen = sizeof(udp_server_addr);
txtime = TEST_TXTIME;
cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_len = CMSG_LEN(sizeof(txtime));
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_TXTIME;
*(net_time_t *)CMSG_DATA(cmsg) = txtime;
optval = true;
rv = zsock_setsockopt(client_sock, SOL_SOCKET, SO_TXTIME, &optval,
sizeof(optval));
test_started = true;
comm_sendmsg_with_txtime(client_sock,
(struct sockaddr *)&client_addr,
sizeof(client_addr),
&msg);
rv = zsock_close(client_sock);
zassert_equal(rv, 0, "close failed");
if (sys_mutex_lock(&wait_data, WAIT_TIME)) {
zassert_true(false, "Timeout DNS query not received");
}
zassert_false(test_failed, "Invalid txtime received");
test_started = false;
}
void test_msg_trunc(int sock_c, int sock_s, struct sockaddr *addr_c,
socklen_t addrlen_c, struct sockaddr *addr_s,
socklen_t addrlen_s)
{
int rv;
uint8_t str_buf[sizeof(TEST_STR_SMALL) - 1];
rv = zsock_bind(sock_s, addr_s, addrlen_s);
zassert_equal(rv, 0, "server bind failed");
rv = zsock_bind(sock_c, addr_c, addrlen_c);
zassert_equal(rv, 0, "client bind failed");
rv = zsock_connect(sock_c, addr_s, addrlen_s);
zassert_equal(rv, 0, "connect failed");
/* MSG_TRUNC */
rv = zsock_send(sock_c, TEST_STR_SMALL, sizeof(TEST_STR_SMALL) - 1, 0);
zassert_equal(rv, sizeof(TEST_STR_SMALL) - 1, "send failed");
memset(str_buf, 0, sizeof(str_buf));
rv = zsock_recv(sock_s, str_buf, 2, ZSOCK_MSG_TRUNC);
zassert_equal(rv, sizeof(TEST_STR_SMALL) - 1, "MSG_TRUNC flag failed");
zassert_mem_equal(str_buf, TEST_STR_SMALL, 2, "invalid rx data");
zassert_equal(str_buf[2], 0, "received more than requested");
/* The remaining data should've been discarded */
rv = zsock_recv(sock_s, str_buf, sizeof(str_buf), ZSOCK_MSG_DONTWAIT);
zassert_equal(rv, -1, "consecutive recv should've failed");
zassert_equal(errno, EAGAIN, "incorrect errno value");
/* MSG_TRUNC & MSG_PEEK combo */
rv = zsock_send(sock_c, TEST_STR_SMALL, sizeof(TEST_STR_SMALL) - 1, 0);
zassert_equal(rv, sizeof(TEST_STR_SMALL) - 1, "send failed");
memset(str_buf, 0, sizeof(str_buf));
rv = zsock_recv(sock_s, str_buf, 2, ZSOCK_MSG_TRUNC | ZSOCK_MSG_PEEK);
zassert_equal(rv, sizeof(TEST_STR_SMALL) - 1, "MSG_TRUNC flag failed");
/* The packet should still be available due to MSG_PEEK */
rv = zsock_recv(sock_s, str_buf, sizeof(str_buf), ZSOCK_MSG_TRUNC);
zassert_equal(rv, sizeof(TEST_STR_SMALL) - 1,
"recv after MSG_PEEK failed");
zassert_mem_equal(str_buf, BUF_AND_SIZE(TEST_STR_SMALL),
"invalid rx data");
rv = zsock_close(sock_c);
zassert_equal(rv, 0, "close failed");
rv = zsock_close(sock_s);
zassert_equal(rv, 0, "close failed");
}
ZTEST(net_socket_udp, test_19_v4_msg_trunc)
{
int client_sock;
int server_sock;
struct sockaddr_in client_addr;
struct sockaddr_in server_addr;
prepare_sock_udp_v4(MY_IPV4_ADDR, ANY_PORT, &client_sock, &client_addr);
prepare_sock_udp_v4(MY_IPV4_ADDR, SERVER_PORT, &server_sock, &server_addr);
test_msg_trunc(client_sock, server_sock,
(struct sockaddr *)&client_addr, sizeof(client_addr),
(struct sockaddr *)&server_addr, sizeof(server_addr));
}
ZTEST(net_socket_udp, test_20_v6_msg_trunc)
{
int client_sock;
int server_sock;
struct sockaddr_in6 client_addr;
struct sockaddr_in6 server_addr;
prepare_sock_udp_v6(MY_IPV6_ADDR, ANY_PORT, &client_sock, &client_addr);
prepare_sock_udp_v6(MY_IPV6_ADDR, SERVER_PORT, &server_sock, &server_addr);
test_msg_trunc(client_sock, server_sock,
(struct sockaddr *)&client_addr, sizeof(client_addr),
(struct sockaddr *)&server_addr, sizeof(server_addr));
}
static void test_dgram_overflow(int sock_c, int sock_s,
struct sockaddr *addr_c, socklen_t addrlen_c,
struct sockaddr *addr_s, socklen_t addrlen_s,
const void *buf, size_t buf_size)
{
int rv;
rv = zsock_bind(sock_s, addr_s, addrlen_s);
zassert_equal(rv, 0, "server bind failed");
rv = zsock_bind(sock_c, addr_c, addrlen_c);
zassert_equal(rv, 0, "client bind failed");
rv = zsock_connect(sock_c, addr_s, addrlen_s);
zassert_equal(rv, 0, "connect failed");
rv = zsock_send(sock_c, buf, buf_size, 0);
zassert_equal(rv, -1, "send succeeded");
zassert_equal(errno, ENOMEM, "incorrect errno value");
rv = zsock_close(sock_c);
zassert_equal(rv, 0, "close failed");
rv = zsock_close(sock_s);
zassert_equal(rv, 0, "close failed");
}
static void test_dgram_fragmented(int sock_c, int sock_s,
struct sockaddr *addr_c, socklen_t addrlen_c,
struct sockaddr *addr_s, socklen_t addrlen_s,
const void *buf, size_t buf_size)
{
int rv;
rv = zsock_bind(sock_s, addr_s, addrlen_s);
zassert_equal(rv, 0, "server bind failed");
rv = zsock_bind(sock_c, addr_c, addrlen_c);
zassert_equal(rv, 0, "client bind failed");
rv = zsock_connect(sock_c, addr_s, addrlen_s);
zassert_equal(rv, 0, "connect failed");
rv = zsock_send(sock_c, buf, buf_size, 0);
zassert_equal(rv, buf_size, "send failed");
memset(rx_buf, 0, sizeof(rx_buf));
rv = zsock_recv(sock_s, rx_buf, sizeof(rx_buf), 0);
zassert_equal(rv, buf_size, "recv failed");
zassert_mem_equal(rx_buf, buf, buf_size, "wrong data");
rv = zsock_close(sock_c);
zassert_equal(rv, 0, "close failed");
rv = zsock_close(sock_s);
zassert_equal(rv, 0, "close failed");
}
ZTEST(net_socket_udp, test_21_v4_dgram_overflow)
{
int client_sock;
int server_sock;
struct sockaddr_in client_addr;
struct sockaddr_in server_addr;
prepare_sock_udp_v4(MY_IPV4_ADDR, ANY_PORT, &client_sock, &client_addr);
prepare_sock_udp_v4(MY_IPV4_ADDR, SERVER_PORT, &server_sock, &server_addr);
test_dgram_overflow(client_sock, server_sock,
(struct sockaddr *)&client_addr, sizeof(client_addr),
(struct sockaddr *)&server_addr, sizeof(server_addr),
test_str_all_tx_bufs, NET_ETH_MTU + 1);
}
ZTEST(net_socket_udp, test_22_v6_dgram_fragmented_or_overflow)
{
int client_sock;
int server_sock;
struct sockaddr_in6 client_addr;
struct sockaddr_in6 server_addr;
prepare_sock_udp_v6(MY_IPV6_ADDR, ANY_PORT, &client_sock, &client_addr);
prepare_sock_udp_v6(MY_IPV6_ADDR, SERVER_PORT, &server_sock, &server_addr);
if (IS_ENABLED(CONFIG_NET_IPV6_FRAGMENT)) {
test_dgram_fragmented(client_sock, server_sock,
(struct sockaddr *)&client_addr, sizeof(client_addr),
(struct sockaddr *)&server_addr, sizeof(server_addr),
test_str_all_tx_bufs, NET_ETH_MTU + 1);
} else {
test_dgram_overflow(client_sock, server_sock,
(struct sockaddr *)&client_addr, sizeof(client_addr),
(struct sockaddr *)&server_addr, sizeof(server_addr),
test_str_all_tx_bufs, NET_ETH_MTU + 1);
}
}
ZTEST(net_socket_udp, test_23_v6_dgram_overflow)
{
int client_sock;
int server_sock;
struct sockaddr_in6 client_addr;
struct sockaddr_in6 server_addr;
prepare_sock_udp_v6(MY_IPV6_ADDR, ANY_PORT, &client_sock, &client_addr);
prepare_sock_udp_v6(MY_IPV6_ADDR, SERVER_PORT, &server_sock, &server_addr);
test_dgram_overflow(client_sock, server_sock,
(struct sockaddr *)&client_addr, sizeof(client_addr),
(struct sockaddr *)&server_addr, sizeof(server_addr),
BUF_AND_SIZE(test_str_all_tx_bufs));
}
static void test_dgram_connected(int sock_c, int sock_s1, int sock_s2,
struct sockaddr *addr_c, socklen_t addrlen_c,
struct sockaddr *addr_s1, socklen_t addrlen_s1,
struct sockaddr *addr_s2, socklen_t addrlen_s2)
{
uint8_t tx_buf = 0xab;
uint8_t rx_buf;
int rv;
rv = zsock_bind(sock_c, addr_c, addrlen_c);
zassert_equal(rv, 0, "client bind failed");
rv = zsock_bind(sock_s1, addr_s1, addrlen_s1);
zassert_equal(rv, 0, "server bind failed");
rv = zsock_bind(sock_s2, addr_s2, addrlen_s2);
zassert_equal(rv, 0, "server bind failed");
rv = zsock_connect(sock_c, addr_s1, addrlen_s1);
zassert_equal(rv, 0, "connect failed");
/* Verify that a datagram can be received from the connected address */
rv = zsock_sendto(sock_s1, &tx_buf, sizeof(tx_buf), 0, addr_c, addrlen_c);
zassert_equal(rv, sizeof(tx_buf), "send failed %d", errno);
/* Give the packet a chance to go through the net stack */
k_msleep(10);
rx_buf = 0;
rv = zsock_recv(sock_c, &rx_buf, sizeof(rx_buf), ZSOCK_MSG_DONTWAIT);
zassert_equal(rv, sizeof(rx_buf), "recv failed");
zassert_equal(rx_buf, tx_buf, "wrong data");
/* Verify that a datagram is not received from other address */
rv = zsock_sendto(sock_s2, &tx_buf, sizeof(tx_buf), 0, addr_c, addrlen_c);
zassert_equal(rv, sizeof(tx_buf), "send failed");
/* Give the packet a chance to go through the net stack */
k_msleep(10);
rv = zsock_recv(sock_c, &rx_buf, sizeof(rx_buf), ZSOCK_MSG_DONTWAIT);
zassert_equal(rv, -1, "recv should've failed");
zassert_equal(errno, EAGAIN, "incorrect errno");
rv = zsock_close(sock_c);
zassert_equal(rv, 0, "close failed");
rv = zsock_close(sock_s1);
zassert_equal(rv, 0, "close failed");
rv = zsock_close(sock_s2);
zassert_equal(rv, 0, "close failed");
}
ZTEST(net_socket_udp, test_24_v4_dgram_connected)
{
int client_sock;
int server_sock_1;
int server_sock_2;
struct sockaddr_in client_addr;
struct sockaddr_in server_addr_1;
struct sockaddr_in server_addr_2;
prepare_sock_udp_v4(MY_IPV4_ADDR, CLIENT_PORT, &client_sock, &client_addr);
prepare_sock_udp_v4(MY_IPV4_ADDR, SERVER_PORT, &server_sock_1, &server_addr_1);
prepare_sock_udp_v4(MY_IPV4_ADDR, SERVER_PORT + 1, &server_sock_2, &server_addr_2);
test_dgram_connected(client_sock, server_sock_1, server_sock_2,
(struct sockaddr *)&client_addr, sizeof(client_addr),
(struct sockaddr *)&server_addr_1, sizeof(server_addr_1),
(struct sockaddr *)&server_addr_2, sizeof(server_addr_2));
}
ZTEST(net_socket_udp, test_25_v6_dgram_connected)
{
int client_sock;
int server_sock_1;
int server_sock_2;
struct sockaddr_in6 client_addr;
struct sockaddr_in6 server_addr_1;
struct sockaddr_in6 server_addr_2;
prepare_sock_udp_v6(MY_IPV6_ADDR, CLIENT_PORT, &client_sock, &client_addr);
prepare_sock_udp_v6(MY_IPV6_ADDR, SERVER_PORT, &server_sock_1, &server_addr_1);
prepare_sock_udp_v6(MY_IPV6_ADDR, SERVER_PORT + 1, &server_sock_2, &server_addr_2);
test_dgram_connected(client_sock, server_sock_1, server_sock_2,
(struct sockaddr *)&client_addr, sizeof(client_addr),
(struct sockaddr *)&server_addr_1, sizeof(server_addr_1),
(struct sockaddr *)&server_addr_2, sizeof(server_addr_2));
}
ZTEST_USER(net_socket_udp, test_26_recvmsg_invalid)
{
struct msghdr msg;
struct sockaddr_in6 server_addr;
struct cmsghdr *cmsg;
struct iovec io_vector[1];
union {
struct cmsghdr hdr;
unsigned char buf[CMSG_SPACE(sizeof(int))];
} cmsgbuf;
int ret;
/* Userspace is needed for this test */
Z_TEST_SKIP_IFNDEF(CONFIG_USERSPACE);
io_vector[0].iov_base = TEST_STR_SMALL;
io_vector[0].iov_len = strlen(TEST_STR_SMALL);
ret = zsock_recvmsg(0, NULL, 0);
zassert_true(ret < 0 && errno == EINVAL, "Wrong errno (%d)", errno);
/* Set various pointers to NULL or invalid value which should cause failure */
memset(&msg, 0, sizeof(msg));
msg.msg_controllen = sizeof(cmsgbuf.buf);
ret = zsock_recvmsg(0, &msg, 0);
zassert_true(ret < 0, "recvmsg() succeed");
msg.msg_control = &cmsgbuf.buf;
ret = zsock_recvmsg(0, &msg, 0);
zassert_true(ret < 0 && errno == ENOMEM, "Wrong errno (%d)", errno);
msg.msg_iov = io_vector;
msg.msg_iovlen = 1;
msg.msg_name = (void *)1;
msg.msg_namelen = sizeof(server_addr);
cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = 1122;
*(int *)CMSG_DATA(cmsg) = 42;
ret = zsock_recvmsg(0, &msg, 0);
zassert_true(ret < 0, "recvmsg() succeed");
}
static void comm_sendmsg_recvmsg(int client_sock,
struct sockaddr *client_addr,
socklen_t client_addrlen,
const struct msghdr *client_msg,
int server_sock,
struct sockaddr *server_addr,
socklen_t server_addrlen,
struct msghdr *msg,
void *cmsgbuf, int cmsgbuf_len,
bool expect_control_data)
{
#define MAX_BUF_LEN 64
#define SMALL_BUF_LEN (sizeof(TEST_STR_SMALL) - 1 - 2)
char buf[MAX_BUF_LEN];
char buf2[SMALL_BUF_LEN];
struct iovec io_vector[2];
ssize_t sent;
ssize_t recved;
struct sockaddr addr;
socklen_t addrlen = server_addrlen;
int len, i;
zassert_not_null(client_addr, "null client addr");
zassert_not_null(server_addr, "null server addr");
/*
* Test client -> server sending
*/
sent = zsock_sendmsg(client_sock, client_msg, 0);
zassert_true(sent > 0, "sendmsg failed, %s (%d)", strerror(errno), -errno);
/* One negative test with invalid msg_iov */
memset(msg, 0, sizeof(*msg));
recved = zsock_recvmsg(server_sock, msg, 0);
zassert_true(recved < 0 && errno == ENOMEM, "Wrong errno (%d)", errno);
for (i = 0, len = 0; i < client_msg->msg_iovlen; i++) {
len += client_msg->msg_iov[i].iov_len;
}
zassert_equal(sent, len, "iovec len (%d) vs sent (%d)", len, sent);
/* Test first with one iovec */
io_vector[0].iov_base = buf;
io_vector[0].iov_len = sizeof(buf);
memset(msg, 0, sizeof(*msg));
if (cmsgbuf != NULL) {
memset(cmsgbuf, 0, cmsgbuf_len);
}
msg->msg_control = cmsgbuf;
msg->msg_controllen = cmsgbuf_len;
msg->msg_iov = io_vector;
msg->msg_iovlen = 1;
msg->msg_name = &addr;
msg->msg_namelen = addrlen;
/* Test recvmsg(MSG_PEEK) */
recved = zsock_recvmsg(server_sock, msg, ZSOCK_MSG_PEEK);
zassert_true(recved > 0, "recvmsg fail, %s (%d)", strerror(errno), -errno);
zassert_equal(recved, len, "unexpected received bytes (%d vs %d)",
recved, len);
zassert_equal(sent, recved, "sent(%d)/received(%d) mismatch",
sent, recved);
zassert_equal(msg->msg_iovlen, 1, "recvmsg should not modify msg_iovlen");
zassert_equal(msg->msg_iov[0].iov_len, sizeof(buf),
"recvmsg should not modify buffer length");
zassert_mem_equal(buf, TEST_STR_SMALL, len,
"wrong data (%s)", rx_buf);
zassert_equal(addrlen, client_addrlen, "unexpected addrlen");
/* Test normal recvmsg() */
clear_buf(rx_buf);
recved = zsock_recvmsg(server_sock, msg, 0);
zassert_true(recved > 0, "recvfrom fail");
zassert_equal(recved, len, "unexpected received bytes");
zassert_equal(msg->msg_iovlen, 1, "recvmsg should not modify msg_iovlen");
zassert_equal(msg->msg_iov[0].iov_len, sizeof(buf),
"recvmsg should not modify buffer length");
zassert_mem_equal(buf, TEST_STR_SMALL, len,
"wrong data (%s)", rx_buf);
zassert_equal(addrlen, client_addrlen, "unexpected addrlen");
/* Control data should be empty */
if (!expect_control_data) {
zassert_equal(msg->msg_controllen, 0,
"We received control data (%u vs %zu)",
0U, msg->msg_controllen);
}
/* Check the client port */
if (addr.sa_family == AF_INET) {
if (net_sin(client_addr)->sin_port != ANY_PORT) {
zassert_equal(net_sin(client_addr)->sin_port,
net_sin(&addr)->sin_port,
"unexpected client port");
}
}
if (addr.sa_family == AF_INET6) {
if (net_sin6(client_addr)->sin6_port != ANY_PORT) {
zassert_equal(net_sin6(client_addr)->sin6_port,
net_sin6(&addr)->sin6_port,
"unexpected client port");
}
}
/* Then send the message again and verify that we could receive
* the full message in smaller chunks too.
*/
sent = zsock_sendmsg(client_sock, client_msg, 0);
zassert_true(sent > 0, "sendmsg failed (%d)", -errno);
for (i = 0, len = 0; i < client_msg->msg_iovlen; i++) {
len += client_msg->msg_iov[i].iov_len;
}
zassert_equal(sent, len, "iovec len (%d) vs sent (%d)", len, sent);
/* and then test with two iovec */
io_vector[0].iov_base = buf2;
io_vector[0].iov_len = sizeof(buf2);
io_vector[1].iov_base = buf;
io_vector[1].iov_len = sizeof(buf);
memset(msg, 0, sizeof(*msg));
if (cmsgbuf != NULL) {
memset(cmsgbuf, 0, cmsgbuf_len);
}
msg->msg_control = cmsgbuf;
msg->msg_controllen = cmsgbuf_len;
msg->msg_iov = io_vector;
msg->msg_iovlen = 2;
msg->msg_name = &addr;
msg->msg_namelen = addrlen;
/* Test recvmsg(MSG_PEEK) */
recved = zsock_recvmsg(server_sock, msg, ZSOCK_MSG_PEEK);
zassert_true(recved >= 0, "recvfrom fail (errno %d)", errno);
zassert_equal(recved, len,
"unexpected received bytes (%d vs %d)", recved, len);
zassert_equal(sent, recved, "sent(%d)/received(%d) mismatch",
sent, recved);
zassert_equal(msg->msg_iovlen, 2, "recvmsg should not modify msg_iovlen");
zassert_equal(msg->msg_iov[0].iov_len, sizeof(buf2),
"recvmsg should not modify buffer length");
zassert_equal(msg->msg_iov[1].iov_len, sizeof(buf),
"recvmsg should not modify buffer length");
zassert_mem_equal(msg->msg_iov[0].iov_base, TEST_STR_SMALL, msg->msg_iov[0].iov_len,
"wrong data in %s", "iov[0]");
zassert_mem_equal(msg->msg_iov[1].iov_base, &TEST_STR_SMALL[msg->msg_iov[0].iov_len],
len - msg->msg_iov[0].iov_len,
"wrong data in %s", "iov[1]");
zassert_equal(addrlen, client_addrlen, "unexpected addrlen");
/* Test normal recvfrom() */
recved = zsock_recvmsg(server_sock, msg, ZSOCK_MSG_PEEK);
zassert_true(recved >= 0, "recvfrom fail (errno %d)", errno);
zassert_equal(recved, len,
"unexpected received bytes (%d vs %d)", recved, len);
zassert_equal(sent, recved, "sent(%d)/received(%d) mismatch",
sent, recved);
zassert_equal(msg->msg_iovlen, 2, "recvmsg should not modify msg_iovlen");
zassert_equal(msg->msg_iov[0].iov_len, sizeof(buf2),
"recvmsg should not modify buffer length");
zassert_equal(msg->msg_iov[1].iov_len, sizeof(buf),
"recvmsg should not modify buffer length");
zassert_mem_equal(msg->msg_iov[0].iov_base, TEST_STR_SMALL, msg->msg_iov[0].iov_len,
"wrong data in %s", "iov[0]");
zassert_mem_equal(msg->msg_iov[1].iov_base, &TEST_STR_SMALL[msg->msg_iov[0].iov_len],
len - msg->msg_iov[0].iov_len,
"wrong data in %s", "iov[1]");
zassert_equal(addrlen, client_addrlen, "unexpected addrlen");
/* Control data should be empty */
if (!expect_control_data) {
zassert_equal(msg->msg_controllen, 0,
"We received control data (%u vs %zu)",
0U, msg->msg_controllen);
}
/* Then check that the trucation flag is set correctly */
sent = zsock_sendmsg(client_sock, client_msg, 0);
zassert_true(sent > 0, "sendmsg failed (%d)", -errno);
for (i = 0, len = 0; i < client_msg->msg_iovlen; i++) {
len += client_msg->msg_iov[i].iov_len;
}
zassert_equal(sent, len, "iovec len (%d) vs sent (%d)", len, sent);
/* Test first with one iovec */
io_vector[0].iov_base = buf2;
io_vector[0].iov_len = sizeof(buf2);
memset(msg, 0, sizeof(*msg));
if (cmsgbuf != NULL) {
memset(cmsgbuf, 0, cmsgbuf_len);
}
msg->msg_control = cmsgbuf;
msg->msg_controllen = cmsgbuf_len;
msg->msg_iov = io_vector;
msg->msg_iovlen = 1;
msg->msg_name = &addr;
msg->msg_namelen = addrlen;
/* Test recvmsg */
recved = zsock_recvmsg(server_sock, msg, 0);
zassert_true(recved > 0, "recvmsg fail, %s (%d)", strerror(errno), errno);
zassert_equal(recved, sizeof(buf2),
"unexpected received bytes (%d vs %d)",
recved, sizeof(buf2));
zassert_true(msg->msg_flags & ZSOCK_MSG_TRUNC, "Message not truncated");
zassert_equal(msg->msg_iovlen, 1, "recvmsg should not modify msg_iovlen");
zassert_equal(msg->msg_iov[0].iov_len, sizeof(buf2),
"recvmsg should not modify buffer length");
zassert_mem_equal(buf2, TEST_STR_SMALL, sizeof(buf2),
"wrong data (%s)", buf2);
zassert_equal(addrlen, client_addrlen, "unexpected addrlen");
/* Control data should be empty */
if (!expect_control_data) {
zassert_equal(msg->msg_controllen, 0,
"We received control data (%u vs %zu)",
0U, msg->msg_controllen);
}
}
ZTEST_USER(net_socket_udp, test_27_recvmsg_user)
{
int rv;
int client_sock;
int server_sock;
struct sockaddr_in client_addr;
struct sockaddr_in server_addr;
struct msghdr msg, server_msg;
struct iovec io_vector[1];
prepare_sock_udp_v4(MY_IPV4_ADDR, ANY_PORT, &client_sock, &client_addr);
prepare_sock_udp_v4(MY_IPV4_ADDR, SERVER_PORT, &server_sock, &server_addr);
rv = zsock_bind(server_sock,
(struct sockaddr *)&server_addr,
sizeof(server_addr));
zassert_equal(rv, 0, "server bind failed");
rv = zsock_bind(client_sock,
(struct sockaddr *)&client_addr,
sizeof(client_addr));
zassert_equal(rv, 0, "client bind failed");
io_vector[0].iov_base = TEST_STR_SMALL;
io_vector[0].iov_len = strlen(TEST_STR_SMALL);
memset(&msg, 0, sizeof(msg));
msg.msg_iov = io_vector;
msg.msg_iovlen = 1;
msg.msg_name = &server_addr;
msg.msg_namelen = sizeof(server_addr);
comm_sendmsg_recvmsg(client_sock,
(struct sockaddr *)&client_addr,
sizeof(client_addr),
&msg,
server_sock,
(struct sockaddr *)&server_addr,
sizeof(server_addr),
&server_msg, NULL, 0, false);
rv = zsock_close(client_sock);
zassert_equal(rv, 0, "close failed");
rv = zsock_close(server_sock);
zassert_equal(rv, 0, "close failed");
}
static void run_ancillary_recvmsg_test(int client_sock,
struct sockaddr *client_addr,
int client_addr_len,
int server_sock,
struct sockaddr *server_addr,
int server_addr_len)
{
int rv;
int opt;
int ifindex = 0;
socklen_t optlen;
struct sockaddr addr = { 0 };
struct net_if *iface;
struct msghdr msg;
struct msghdr server_msg;
struct iovec io_vector[1];
struct cmsghdr *cmsg, *prevcmsg;
union {
struct cmsghdr hdr;
unsigned char buf[CMSG_SPACE(sizeof(struct in6_pktinfo))];
} cmsgbuf;
#define SMALL_BUF_LEN (sizeof(TEST_STR_SMALL) - 1 - 2)
char buf[MAX_BUF_LEN];
Z_TEST_SKIP_IFNDEF(CONFIG_NET_CONTEXT_RECV_PKTINFO);
rv = zsock_bind(server_sock, server_addr, server_addr_len);
zassert_equal(rv, 0, "server bind failed");
rv = zsock_bind(client_sock, client_addr, client_addr_len);
zassert_equal(rv, 0, "client bind failed");
io_vector[0].iov_base = TEST_STR_SMALL;
io_vector[0].iov_len = strlen(TEST_STR_SMALL);
memset(&cmsgbuf, 0, sizeof(cmsgbuf));
memset(&msg, 0, sizeof(msg));
msg.msg_iov = io_vector;
msg.msg_iovlen = 1;
msg.msg_name = server_addr;
msg.msg_namelen = server_addr_len;
comm_sendmsg_recvmsg(client_sock,
client_addr,
client_addr_len,
&msg,
server_sock,
server_addr,
server_addr_len,
&server_msg,
&cmsgbuf.buf,
sizeof(cmsgbuf.buf),
true);
for (prevcmsg = NULL, cmsg = CMSG_FIRSTHDR(&server_msg);
cmsg != NULL && prevcmsg != cmsg;
prevcmsg = cmsg, cmsg = CMSG_NXTHDR(&server_msg, cmsg)) {
if (cmsg->cmsg_level == IPPROTO_IP &&
cmsg->cmsg_type == IP_PKTINFO) {
net_sin(&addr)->sin_addr = ((struct in_pktinfo *)CMSG_DATA(cmsg))->ipi_addr;
break;
}
}
/* As we have not set the socket option, the address should not be set */
if (server_addr->sa_family == AF_INET) {
zassert_equal(net_sin(&addr)->sin_addr.s_addr, INADDR_ANY, "Source address set!");
}
if (server_addr->sa_family == AF_INET6) {
zassert_true(net_sin6(&addr)->sin6_addr.s6_addr32[0] == 0 &&
net_sin6(&addr)->sin6_addr.s6_addr32[1] == 0 &&
net_sin6(&addr)->sin6_addr.s6_addr32[2] == 0 &&
net_sin6(&addr)->sin6_addr.s6_addr32[3] == 0,
"Source address set!");
}
opt = 1;
optlen = sizeof(opt);
if (server_addr->sa_family == AF_INET) {
rv = zsock_setsockopt(server_sock, IPPROTO_IP, IP_PKTINFO, &opt, optlen);
} else {
rv = zsock_setsockopt(server_sock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &opt, optlen);
}
zassert_equal(rv, 0, "setsockopt failed (%d)", -errno);
memset(&cmsgbuf, 0, sizeof(cmsgbuf));
memset(&msg, 0, sizeof(msg));
msg.msg_iov = io_vector;
msg.msg_iovlen = 1;
msg.msg_name = server_addr;
msg.msg_namelen = server_addr_len;
comm_sendmsg_recvmsg(client_sock,
client_addr,
client_addr_len,
&msg,
server_sock,
server_addr,
server_addr_len,
&server_msg,
&cmsgbuf.buf,
sizeof(cmsgbuf.buf),
true);
for (cmsg = CMSG_FIRSTHDR(&server_msg); cmsg != NULL;
cmsg = CMSG_NXTHDR(&server_msg, cmsg)) {
if (cmsg->cmsg_level == IPPROTO_IP &&
cmsg->cmsg_type == IP_PKTINFO) {
net_sin(&addr)->sin_addr =
((struct in_pktinfo *)CMSG_DATA(cmsg))->ipi_addr;
ifindex = ((struct in_pktinfo *)CMSG_DATA(cmsg))->ipi_ifindex;
break;
}
if (cmsg->cmsg_level == IPPROTO_IPV6 &&
cmsg->cmsg_type == IPV6_PKTINFO) {
net_ipaddr_copy(&net_sin6(&addr)->sin6_addr,
&((struct in6_pktinfo *)CMSG_DATA(cmsg))->ipi6_addr);
ifindex = ((struct in6_pktinfo *)CMSG_DATA(cmsg))->ipi6_ifindex;
break;
}
}
if (server_addr->sa_family == AF_INET) {
zassert_equal(net_sin(&addr)->sin_addr.s_addr,
net_sin(server_addr)->sin_addr.s_addr,
"Source address not set properly!");
}
if (server_addr->sa_family == AF_INET6) {
zassert_mem_equal(&net_sin6(&addr)->sin6_addr,
&net_sin6(server_addr)->sin6_addr,
sizeof(struct in6_addr),
"Source address not set properly!");
}
if (!k_is_user_context()) {
iface = net_if_get_default();
zassert_equal(ifindex, net_if_get_by_iface(iface));
}
/* Make sure that the recvmsg() fails if control area is too small */
rv = zsock_sendto(client_sock, TEST_STR_SMALL, sizeof(TEST_STR_SMALL) - 1, 0,
server_addr, server_addr_len);
zassert_equal(rv, STRLEN(TEST_STR_SMALL), "sendto failed (%d)", -errno);
io_vector[0].iov_base = buf;
io_vector[0].iov_len = sizeof(buf);
memset(&msg, 0, sizeof(msg));
msg.msg_control = &cmsgbuf.buf;
msg.msg_controllen = 1; /* making sure the control buf is always too small */
msg.msg_iov = io_vector;
msg.msg_iovlen = 1;
rv = zsock_recvmsg(server_sock, &msg, 0);
zassert_true(rv, "recvmsg succeed (%d)", rv);
zassert_true(msg.msg_flags & ZSOCK_MSG_CTRUNC, "Control message not truncated");
rv = zsock_close(client_sock);
zassert_equal(rv, 0, "close failed");
rv = zsock_close(server_sock);
zassert_equal(rv, 0, "close failed");
}
ZTEST_USER(net_socket_udp, test_28_recvmsg_ancillary_ipv4_pktinfo_data_user)
{
struct sockaddr_in client_addr;
struct sockaddr_in server_addr;
int client_sock;
int server_sock;
prepare_sock_udp_v4(MY_IPV4_ADDR, ANY_PORT, &client_sock, &client_addr);
prepare_sock_udp_v4(MY_IPV4_ADDR, SERVER_PORT, &server_sock, &server_addr);
run_ancillary_recvmsg_test(client_sock,
(struct sockaddr *)&client_addr,
sizeof(client_addr),
server_sock,
(struct sockaddr *)&server_addr,
sizeof(server_addr));
}
ZTEST_USER(net_socket_udp, test_29_recvmsg_ancillary_ipv6_pktinfo_data_user)
{
struct sockaddr_in6 client_addr;
struct sockaddr_in6 server_addr;
int client_sock;
int server_sock;
prepare_sock_udp_v6(MY_IPV6_ADDR, ANY_PORT, &client_sock, &client_addr);
prepare_sock_udp_v6(MY_IPV6_ADDR, SERVER_PORT, &server_sock, &server_addr);
run_ancillary_recvmsg_test(client_sock,
(struct sockaddr *)&client_addr,
sizeof(client_addr),
server_sock,
(struct sockaddr *)&server_addr,
sizeof(server_addr));
}
ZTEST(net_socket_udp, test_30_setup_eth_for_ipv4)
{
struct net_if_addr *ifaddr;
net_if_foreach(iface_cb, &eth_iface);
zassert_not_null(eth_iface, "No ethernet interface found");
net_if_down(eth_iface);
ifaddr = net_if_ipv4_addr_add(eth_iface, &my_addr2,
NET_ADDR_MANUAL, 0);
if (!ifaddr) {
DBG("Cannot add IPv4 address %s\n",
net_sprint_ipv4_addr(&my_addr2));
zassert_not_null(ifaddr, "addr2");
}
net_if_up(eth_iface);
}
static int bind_socket(int sock, struct net_if *iface)
{
struct sockaddr_ll addr;
memset(&addr, 0, sizeof(addr));
addr.sll_ifindex = net_if_get_by_iface(iface);
addr.sll_family = AF_PACKET;
return zsock_bind(sock, (struct sockaddr *)&addr, sizeof(addr));
}
static void test_check_ttl(int sock_c, int sock_s, int sock_p,
struct sockaddr *addr_c, socklen_t addrlen_c,
struct sockaddr *addr_s, socklen_t addrlen_s,
struct sockaddr *addr_sendto, socklen_t addrlen_sendto,
sa_family_t family, uint8_t expected_ttl,
uint8_t expected_mcast_ttl)
{
uint8_t tx_buf = 0xab;
uint8_t rx_buf;
int ret, count = 10, opt;
#define IPV4_HDR_SIZE sizeof(struct net_ipv4_hdr)
#define IPV6_HDR_SIZE sizeof(struct net_ipv6_hdr)
#define UDP_HDR_SIZE sizeof(struct net_udp_hdr)
#define V4_HDR_SIZE (IPV4_HDR_SIZE + UDP_HDR_SIZE)
#define V6_HDR_SIZE (IPV6_HDR_SIZE + UDP_HDR_SIZE)
#define MAX_HDR_SIZE (IPV6_HDR_SIZE + UDP_HDR_SIZE)
uint8_t data_to_receive[sizeof(tx_buf) + MAX_HDR_SIZE];
struct sockaddr_ll src;
socklen_t addrlen;
char ifname[CONFIG_NET_INTERFACE_NAME_LEN];
struct ifreq ifreq = { 0 };
struct timeval timeo_optval = {
.tv_sec = 0,
.tv_usec = 100000,
};
#if defined(CONFIG_NET_STATISTICS)
struct net_stats_ip ipv4_stats_before, ipv4_stats_after;
struct net_stats_ip ipv6_stats_before, ipv6_stats_after;
#endif
Z_TEST_SKIP_IFNDEF(CONFIG_NET_INTERFACE_NAME);
ret = zsock_bind(sock_c, addr_c, addrlen_c);
zassert_equal(ret, 0, "client bind failed");
ret = net_if_get_name(lo0, ifname, sizeof(ifname));
zassert_true(ret > 0, "cannot get interface name (%d)", ret);
strncpy(ifreq.ifr_name, ifname, sizeof(ifreq.ifr_name));
ret = zsock_setsockopt(sock_c, SOL_SOCKET, SO_BINDTODEVICE, &ifreq,
sizeof(ifreq));
zassert_equal(ret, 0, "SO_BINDTODEVICE failed, %d", -errno);
ret = zsock_connect(sock_c, addr_s, addrlen_s);
zassert_equal(ret, 0, "connect failed");
ret = zsock_setsockopt(sock_s, SOL_SOCKET, SO_RCVTIMEO,
&timeo_optval, sizeof(timeo_optval));
zassert_equal(ret, 0, "Cannot set receive timeout (%d)", -errno);
while (count > 0) {
ret = zsock_sendto(sock_c, &tx_buf, sizeof(tx_buf), 0,
addr_sendto, addrlen_sendto);
zassert_equal(ret, sizeof(tx_buf), "send failed (%d)", -errno);
ret = zsock_recv(sock_s, &rx_buf, sizeof(rx_buf), ZSOCK_MSG_DONTWAIT);
if (ret > 0) {
zassert_equal(ret, sizeof(rx_buf), "recv failed (%d)", ret);
zassert_equal(rx_buf, tx_buf, "wrong data");
}
ret = zsock_recvfrom(sock_p, data_to_receive, sizeof(data_to_receive), 0,
(struct sockaddr *)&src, &addrlen);
if (ret > 0) {
int hdr_size = family == AF_INET ?
V4_HDR_SIZE : V6_HDR_SIZE;
zassert_equal(ret, sizeof(tx_buf) + hdr_size,
"Cannot receive all data (%d vs %zd) (%d)",
ret, sizeof(tx_buf), -errno);
zassert_mem_equal(&data_to_receive[hdr_size], &tx_buf,
sizeof(tx_buf),
"Sent and received buffers do not match");
if (family == AF_INET) {
struct net_ipv4_hdr *ipv4 =
(struct net_ipv4_hdr *)&data_to_receive[0];
if (expected_ttl > 0) {
zassert_equal(ipv4->ttl, expected_ttl,
"Invalid ttl (%d vs %d)",
ipv4->ttl, expected_ttl);
} else if (expected_mcast_ttl > 0) {
zassert_equal(ipv4->ttl, expected_mcast_ttl,
"Invalid mcast ttl (%d vs %d)",
ipv4->ttl, expected_mcast_ttl);
}
} else if (family == AF_INET6) {
struct net_ipv6_hdr *ipv6 =
(struct net_ipv6_hdr *)&data_to_receive[0];
if (expected_ttl > 0) {
zassert_equal(ipv6->hop_limit, expected_ttl,
"Invalid hop limit (%d vs %d)",
ipv6->hop_limit, expected_ttl);
} else if (expected_mcast_ttl > 0) {
zassert_equal(ipv6->hop_limit, expected_mcast_ttl,
"Invalid mcast hop limit (%d vs %d)",
ipv6->hop_limit, expected_mcast_ttl);
}
} else {
zassert_true(false, "Invalid address family (%d)",
family);
}
break;
}
count--;
}
zassert_true(count > 0, "timeout while waiting data");
if (family == AF_INET) {
/* Set TTL to 0 and make sure the packet is dropped and not
* received
*/
int option;
if (expected_ttl > 0) {
option = IP_TTL;
} else {
option = IP_MULTICAST_TTL;
}
opt = 0;
ret = zsock_setsockopt(sock_c, IPPROTO_IP, option, &opt, sizeof(opt));
zassert_equal(ret, 0, "Cannot set %s TTL (%d)",
option == IP_TTL ? "unicast" : "multicast",
-errno);
#if defined(CONFIG_NET_STATISTICS)
/* Get IPv4 stats and verify they are updated for dropped
* packets.
*/
net_mgmt(NET_REQUEST_STATS_GET_IPV4, lo0,
&ipv4_stats_before, sizeof(ipv4_stats_before));
#endif
ret = zsock_sendto(sock_c, &tx_buf, sizeof(tx_buf), 0,
addr_sendto, addrlen_sendto);
zassert_equal(ret, sizeof(tx_buf), "send failed (%d)", -errno);
#if defined(CONFIG_NET_STATISTICS)
net_mgmt(NET_REQUEST_STATS_GET_IPV4, lo0,
&ipv4_stats_after, sizeof(ipv4_stats_after));
zassert_equal(ipv4_stats_before.drop + 1,
ipv4_stats_after.drop,
"Dropped statistics not updated (%d vs %d)",
ipv4_stats_before.drop + 1,
ipv4_stats_after.drop);
#endif
ret = zsock_recv(sock_s, &rx_buf, sizeof(rx_buf), 0);
zassert_true(ret < 0 && errno == EAGAIN, "recv succeed (%d)", -errno);
}
if (family == AF_INET6) {
/* Set hoplimit to 0 and make sure the packet is dropped and not
* received.
*/
int option;
if (expected_ttl > 0) {
option = IPV6_UNICAST_HOPS;
} else {
option = IPV6_MULTICAST_HOPS;
}
opt = 0;
ret = zsock_setsockopt(sock_c, IPPROTO_IPV6, option,
&opt, sizeof(opt));
zassert_equal(ret, 0, "Cannot set %s hops (%d)",
option == IPV6_UNICAST_HOPS ? "unicast" : "multicast",
-errno);
#if defined(CONFIG_NET_STATISTICS)
/* Get IPv6 stats and verify they are updated for dropped
* packets.
*/
net_mgmt(NET_REQUEST_STATS_GET_IPV6, lo0,
&ipv6_stats_before, sizeof(ipv6_stats_before));
#endif
ret = zsock_sendto(sock_c, &tx_buf, sizeof(tx_buf), 0,
addr_sendto, addrlen_sendto);
zassert_equal(ret, sizeof(tx_buf), "send failed (%d)", -errno);
#if defined(CONFIG_NET_STATISTICS)
net_mgmt(NET_REQUEST_STATS_GET_IPV6, lo0,
&ipv6_stats_after, sizeof(ipv6_stats_after));
zassert_equal(ipv6_stats_before.drop + 1,
ipv6_stats_after.drop,
"Dropped statistics not updated (%d vs %d)",
ipv6_stats_before.drop + 1,
ipv6_stats_after.drop);
#endif
ret = zsock_recv(sock_s, &rx_buf, sizeof(rx_buf), 0);
zassert_true(ret < 0 && errno == EAGAIN, "recv succeed (%d)", -errno);
}
ret = zsock_close(sock_c);
zassert_equal(ret, 0, "close failed");
ret = zsock_close(sock_s);
zassert_equal(ret, 0, "close failed");
ret = zsock_close(sock_p);
zassert_equal(ret, 0, "close failed");
}
ZTEST(net_socket_udp, test_31_v4_ttl)
{
int ret;
int client_sock;
int server_sock;
int packet_sock;
int ttl, verify;
socklen_t optlen;
struct sockaddr_in client_addr;
struct sockaddr_in server_addr;
Z_TEST_SKIP_IFNDEF(CONFIG_NET_SOCKETS_PACKET);
prepare_sock_udp_v4(MY_IPV4_ADDR, CLIENT_PORT, &client_sock, &client_addr);
prepare_sock_udp_v4(MY_IPV4_ADDR, SERVER_PORT, &server_sock, &server_addr);
packet_sock = zsock_socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
zassert_true(packet_sock >= 0, "Cannot create packet socket (%d)", -errno);
ret = bind_socket(packet_sock, lo0);
zassert_equal(ret, 0, "packet socket bind failed");
zassert_not_null(lo0->config.ip.ipv4,
"Interface %d (%p) no IPv4 configured",
net_if_get_by_iface(lo0), lo0);
ttl = 16;
net_if_ipv4_set_ttl(lo0, ttl);
verify = net_if_ipv4_get_ttl(lo0);
zassert_equal(verify, ttl, "Different TTLs (%d vs %d)", ttl, verify);
ttl = 128;
ret = zsock_setsockopt(client_sock, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl));
zassert_equal(ret, 0, "Cannot set unicast TTL (%d)", -errno);
optlen = sizeof(verify);
ret = zsock_getsockopt(client_sock, IPPROTO_IP, IP_TTL, &verify, &optlen);
zassert_equal(ret, 0, "Cannot get unicast TTL (%d)", -errno);
zassert_equal(verify, ttl, "Different unicast TTL (%d vs %d)",
ttl, verify);
test_check_ttl(client_sock, server_sock, packet_sock,
(struct sockaddr *)&client_addr, sizeof(client_addr),
(struct sockaddr *)&server_addr, sizeof(server_addr),
(struct sockaddr *)&server_addr, sizeof(server_addr),
AF_INET, ttl, 0);
}
ZTEST(net_socket_udp, test_32_v4_mcast_ttl)
{
int ret;
int client_sock;
int server_sock;
int packet_sock;
int mcast_ttl, verify;
socklen_t optlen;
struct sockaddr_in client_addr;
struct sockaddr_in server_addr;
struct sockaddr_in sendto_addr;
Z_TEST_SKIP_IFNDEF(CONFIG_NET_SOCKETS_PACKET);
prepare_sock_udp_v4(MY_IPV4_ADDR, CLIENT_PORT, &client_sock, &client_addr);
prepare_sock_udp_v4(MY_IPV4_ADDR, SERVER_PORT, &server_sock, &server_addr);
packet_sock = zsock_socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
zassert_true(packet_sock >= 0, "Cannot create packet socket (%d)", -errno);
ret = bind_socket(packet_sock, lo0);
zassert_equal(ret, 0, "packet socket bind failed");
zassert_not_null(lo0->config.ip.ipv4,
"Interface %d (%p) no IPv4 configured",
net_if_get_by_iface(lo0), lo0);
mcast_ttl = 8;
ret = zsock_setsockopt(client_sock, IPPROTO_IP, IP_MULTICAST_TTL, &mcast_ttl,
sizeof(mcast_ttl));
zassert_equal(ret, 0, "Cannot set multicast ttl (%d)", -errno);
optlen = sizeof(verify);
ret = zsock_getsockopt(client_sock, IPPROTO_IP, IP_MULTICAST_TTL, &verify,
&optlen);
zassert_equal(ret, 0, "Cannot get multicast ttl (%d)", -errno);
zassert_equal(verify, mcast_ttl, "Different multicast TTLs (%d vs %d)",
mcast_ttl, verify);
ret = net_addr_pton(AF_INET, MY_MCAST_IPV4_ADDR, &sendto_addr.sin_addr);
zassert_equal(ret, 0, "Cannot get IPv4 address (%d)", ret);
test_check_ttl(client_sock, server_sock, packet_sock,
(struct sockaddr *)&client_addr, sizeof(client_addr),
(struct sockaddr *)&server_addr, sizeof(server_addr),
(struct sockaddr *)&sendto_addr, sizeof(sendto_addr),
AF_INET, 0, mcast_ttl);
}
ZTEST(net_socket_udp, test_33_v6_mcast_hops)
{
int ret;
int client_sock;
int server_sock;
int packet_sock;
int mcast_hops, if_mcast_hops;
int verify, opt;
socklen_t optlen;
struct sockaddr_in6 client_addr;
struct sockaddr_in6 server_addr;
struct sockaddr_in6 sendto_addr;
Z_TEST_SKIP_IFNDEF(CONFIG_NET_SOCKETS_PACKET);
prepare_sock_udp_v6(MY_IPV6_ADDR, CLIENT_PORT, &client_sock, &client_addr);
prepare_sock_udp_v6(MY_IPV6_ADDR, SERVER_PORT, &server_sock, &server_addr);
packet_sock = zsock_socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
zassert_true(packet_sock >= 0, "Cannot create packet socket (%d)", -errno);
ret = bind_socket(packet_sock, lo0);
zassert_equal(ret, 0, "packet socket bind failed");
zassert_not_null(lo0->config.ip.ipv6,
"Interface %d (%p) no IPv6 configured",
net_if_get_by_iface(lo0), lo0);
/* First make sure setting hop limit to -1 works as expected (route default
* value should be used).
*/
if_mcast_hops = net_if_ipv6_get_mcast_hop_limit(lo0);
opt = -1;
ret = zsock_setsockopt(client_sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &opt,
sizeof(opt));
zassert_equal(ret, 0, "Cannot set multicast hop limit (%d)", -errno);
optlen = sizeof(verify);
ret = zsock_getsockopt(client_sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &verify,
&optlen);
zassert_equal(ret, 0, "Cannot get multicast hop limit (%d)", -errno);
zassert_equal(verify, if_mcast_hops, "Different multicast hop limit (%d vs %d)",
if_mcast_hops, verify);
/* Then test the normal case where we set the value */
mcast_hops = 8;
ret = zsock_setsockopt(client_sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &mcast_hops,
sizeof(mcast_hops));
zassert_equal(ret, 0, "Cannot set multicast hop limit (%d)", -errno);
optlen = sizeof(verify);
ret = zsock_getsockopt(client_sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &verify,
&optlen);
zassert_equal(ret, 0, "Cannot get multicast hop limit (%d)", -errno);
zassert_equal(verify, mcast_hops, "Different multicast hop limit (%d vs %d)",
mcast_hops, verify);
ret = net_addr_pton(AF_INET6, MY_MCAST_IPV6_ADDR, &sendto_addr.sin6_addr);
zassert_equal(ret, 0, "Cannot get IPv6 address (%d)", ret);
test_check_ttl(client_sock, server_sock, packet_sock,
(struct sockaddr *)&client_addr, sizeof(client_addr),
(struct sockaddr *)&server_addr, sizeof(server_addr),
(struct sockaddr *)&sendto_addr, sizeof(sendto_addr),
AF_INET6, 0, mcast_hops);
}
ZTEST(net_socket_udp, test_34_v6_hops)
{
int ret;
int client_sock;
int server_sock;
int packet_sock;
int hops, verify;
socklen_t optlen;
struct sockaddr_in6 client_addr;
struct sockaddr_in6 server_addr;
Z_TEST_SKIP_IFNDEF(CONFIG_NET_SOCKETS_PACKET);
prepare_sock_udp_v6(MY_IPV6_ADDR, CLIENT_PORT, &client_sock, &client_addr);
prepare_sock_udp_v6(MY_IPV6_ADDR, SERVER_PORT, &server_sock, &server_addr);
packet_sock = zsock_socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
zassert_true(packet_sock >= 0, "Cannot create packet socket (%d)", -errno);
ret = bind_socket(packet_sock, lo0);
zassert_equal(ret, 0, "packet socket bind failed");
zassert_not_null(lo0->config.ip.ipv6,
"Interface %d (%p) no IPv6 configured",
net_if_get_by_iface(lo0), lo0);
hops = 16;
net_if_ipv6_set_hop_limit(lo0, hops);
verify = net_if_ipv6_get_hop_limit(lo0);
zassert_equal(verify, hops, "Different hop limit (%d vs %d)", hops, verify);
hops = 8;
ret = zsock_setsockopt(client_sock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &hops,
sizeof(hops));
zassert_equal(ret, 0, "Cannot set unicast hops (%d)", -errno);
optlen = sizeof(verify);
ret = zsock_getsockopt(client_sock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &verify,
&optlen);
zassert_equal(ret, 0, "Cannot get unicast hops (%d)", -errno);
zassert_equal(verify, hops, "Different unicast hops (%d vs %d)",
hops, verify);
test_check_ttl(client_sock, server_sock, packet_sock,
(struct sockaddr *)&client_addr, sizeof(client_addr),
(struct sockaddr *)&server_addr, sizeof(server_addr),
(struct sockaddr *)&server_addr, sizeof(server_addr),
AF_INET6, hops, 0);
}
ZTEST_USER(net_socket_udp, test_35_recvmsg_msg_controllen_update)
{
int rv;
int client_sock;
int server_sock;
struct sockaddr_in client_addr;
struct sockaddr_in server_addr;
struct msghdr msg, server_msg;
struct iovec io_vector[1];
union {
struct cmsghdr hdr;
unsigned char buf[CMSG_SPACE(sizeof(struct in6_pktinfo))];
} cmsgbuf;
prepare_sock_udp_v4(MY_IPV4_ADDR, ANY_PORT, &client_sock, &client_addr);
prepare_sock_udp_v4(MY_IPV4_ADDR, SERVER_PORT, &server_sock, &server_addr);
rv = zsock_bind(server_sock,
(struct sockaddr *)&server_addr,
sizeof(server_addr));
zassert_equal(rv, 0, "server bind failed");
rv = zsock_bind(client_sock,
(struct sockaddr *)&client_addr,
sizeof(client_addr));
zassert_equal(rv, 0, "client bind failed");
memset(&cmsgbuf, 0, sizeof(cmsgbuf));
io_vector[0].iov_base = TEST_STR_SMALL;
io_vector[0].iov_len = strlen(TEST_STR_SMALL);
memset(&msg, 0, sizeof(msg));
msg.msg_iov = io_vector;
msg.msg_iovlen = 1;
msg.msg_name = &server_addr;
msg.msg_namelen = sizeof(server_addr);
comm_sendmsg_recvmsg(client_sock,
(struct sockaddr *)&client_addr,
sizeof(client_addr),
&msg,
server_sock,
(struct sockaddr *)&server_addr,
sizeof(server_addr),
&server_msg,
&cmsgbuf.buf,
sizeof(cmsgbuf.buf),
false);
rv = zsock_close(client_sock);
zassert_equal(rv, 0, "close failed");
rv = zsock_close(server_sock);
zassert_equal(rv, 0, "close failed");
}
ZTEST(net_socket_udp, test_36_v6_address_removal)
{
int ret;
bool status;
int client_sock;
struct sockaddr_in6 client_addr;
struct net_if_addr *ifaddr;
struct net_if *iface;
if (!IS_ENABLED(CONFIG_NET_IPV6_PE)) {
return;
}
ifaddr = net_if_ipv6_addr_lookup(&my_addr1, &iface);
zassert_equal(ifaddr->atomic_ref, 1, "Ref count is wrong (%ld vs %d)",
ifaddr->atomic_ref, 1);
prepare_sock_udp_v6(MY_IPV6_ADDR_ETH, CLIENT_PORT, &client_sock, &client_addr);
ret = zsock_bind(client_sock,
(struct sockaddr *)&client_addr,
sizeof(client_addr));
zassert_equal(ret, 0, "client bind failed");
status = net_if_ipv6_addr_rm(eth_iface, &my_addr1);
zassert_false(status, "Address could be removed");
ifaddr = net_if_ipv6_addr_lookup(&my_addr1, &iface);
zassert_not_null(ifaddr, "Address %s not found",
net_sprint_ipv6_addr(&my_addr1));
ret = zsock_close(client_sock);
zassert_equal(ret, 0, "close failed");
ifaddr = net_if_ipv6_addr_lookup(&my_addr1, &iface);
zassert_equal(iface, eth_iface, "Invalid interface %p vs %p",
iface, eth_iface);
zassert_is_null(ifaddr, "Address %s found",
net_sprint_ipv6_addr(&my_addr1));
}
static void check_ipv6_address_preferences(struct net_if *iface,
uint16_t preference,
const struct in6_addr *addr,
const struct in6_addr *dest)
{
const struct in6_addr *selected;
socklen_t optlen;
int optval;
int sock;
int ret;
sock = zsock_socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
zassert_true(sock >= 0, "Cannot create socket (%d)", -errno);
optval = preference;
ret = zsock_setsockopt(sock, IPPROTO_IPV6, IPV6_ADDR_PREFERENCES,
&optval, sizeof(optval));
zassert_equal(ret, 0, "setsockopt failed (%d)", errno);
optval = 0; optlen = 0U;
ret = zsock_getsockopt(sock, IPPROTO_IPV6, IPV6_ADDR_PREFERENCES,
&optval, &optlen);
zassert_equal(ret, 0, "setsockopt failed (%d)", errno);
zassert_equal(optlen, sizeof(optval), "invalid optlen %d vs %d",
optlen, sizeof(optval));
zassert_equal(optval, preference,
"getsockopt address preferences");
selected = net_if_ipv6_select_src_addr_hint(iface,
dest,
preference);
ret = net_ipv6_addr_cmp(addr, selected);
zassert_true(ret, "Wrong address %s selected, expected %s",
net_sprint_ipv6_addr(selected),
net_sprint_ipv6_addr(addr));
ret = zsock_close(sock);
zassert_equal(sock, 0, "Cannot close socket (%d)", -errno);
}
ZTEST(net_socket_udp, test_37_ipv6_src_addr_select)
{
struct net_if_addr *ifaddr;
const struct in6_addr dest = { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0x2 } } };
net_if_foreach(iface_cb, &eth_iface);
zassert_not_null(eth_iface, "No ethernet interface found");
ifaddr = net_if_ipv6_addr_add(eth_iface, &my_addr1,
NET_ADDR_AUTOCONF, 0);
if (!ifaddr) {
DBG("Cannot add IPv6 address %s\n",
net_sprint_ipv6_addr(&my_addr1));
zassert_not_null(ifaddr, "addr1");
}
ifaddr->is_temporary = false;
ifaddr = net_if_ipv6_addr_add(eth_iface, &my_addr3,
NET_ADDR_AUTOCONF, 0);
if (!ifaddr) {
DBG("Cannot add IPv6 address %s\n",
net_sprint_ipv6_addr(&my_addr3));
zassert_not_null(ifaddr, "addr1");
}
ifaddr->is_temporary = true;
net_if_up(eth_iface);
check_ipv6_address_preferences(NULL, IPV6_PREFER_SRC_PUBLIC,
&my_addr1, &dest);
check_ipv6_address_preferences(NULL, IPV6_PREFER_SRC_TMP,
&my_addr3, &dest);
}
ZTEST(net_socket_udp, test_38_ipv6_multicast_ifindex)
{
struct sockaddr_in6 saddr6 = {
.sin6_family = AF_INET6,
.sin6_port = htons(SERVER_PORT),
.sin6_addr = my_mcast_addr1,
};
struct net_if_mcast_addr *ifmaddr;
struct net_if_addr *ifaddr;
int server_sock;
socklen_t addrlen;
socklen_t optlen;
int ifindex;
int optval;
int sock;
int ret;
int err;
net_if_foreach(iface_cb, &eth_iface);
zassert_not_null(eth_iface, "No ethernet interface found");
ifmaddr = net_if_ipv6_maddr_add(eth_iface, &my_mcast_addr1);
if (!ifmaddr) {
DBG("Cannot add IPv6 multicast address %s\n",
net_sprint_ipv6_addr(&my_mcast_addr1));
zassert_not_null(ifmaddr, "mcast_addr1");
}
ifaddr = net_if_ipv6_addr_add(eth_iface, &my_addr3,
NET_ADDR_AUTOCONF, 0);
if (!ifaddr) {
DBG("Cannot add IPv6 address %s\n",
net_sprint_ipv6_addr(&my_addr3));
zassert_not_null(ifaddr, "addr1");
}
net_if_up(eth_iface);
/* Check that we get the default interface */
sock = zsock_socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
zassert_true(sock >= 0, "Cannot create socket (%d)", -errno);
optval = 0; optlen = 0U;
ret = zsock_getsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_IF,
&optval, &optlen);
zexpect_equal(ret, 0, "setsockopt failed (%d)", errno);
zexpect_equal(optlen, sizeof(optval), "invalid optlen %d vs %d",
optlen, sizeof(optval));
ifindex = net_if_get_by_iface(net_if_get_default());
zexpect_equal(optval, ifindex,
"getsockopt multicast ifindex (expected %d got %d)",
ifindex, optval);
ret = zsock_close(sock);
zassert_equal(sock, 0, "Cannot close socket (%d)", -errno);
/* Check failure for IPv4 socket */
sock = zsock_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
zassert_true(sock >= 0, "Cannot create socket (%d)", -errno);
optval = 0; optlen = 0U;
ret = zsock_getsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_IF,
&optval, &optlen);
err = -errno;
zexpect_equal(ret, -1, "setsockopt failed (%d)", errno);
zexpect_equal(err, -EAFNOSUPPORT, "setsockopt failed (%d)", errno);
zexpect_equal(optlen, 0U, "setsockopt optlen (%d)", optlen);
ret = zsock_close(sock);
zassert_equal(sock, 0, "Cannot close socket (%d)", -errno);
/* Check that we can set the interface */
sock = zsock_socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
zassert_true(sock >= 0, "Cannot create socket (%d)", -errno);
/* Clear any existing interface value by setting it to 0 */
optval = 0; optlen = sizeof(int);
ret = zsock_setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_IF,
&optval, optlen);
err = -errno;
zexpect_equal(ret, 0, "setsockopt failed (%d)", err);
zexpect_equal(optlen, sizeof(optval), "invalid optlen %d vs %d",
optlen, sizeof(optval));
/* Set the output multicast packet interface to the default interface */
optval = net_if_get_by_iface(net_if_get_default()); optlen = sizeof(int);
ret = zsock_setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_IF,
&optval, optlen);
zexpect_equal(ret, 0, "setsockopt failed (%d)", errno);
zexpect_equal(optlen, sizeof(optval), "invalid optlen %d vs %d",
optlen, sizeof(optval));
optval = 0; optlen = 0U;
ret = zsock_getsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_IF,
&optval, &optlen);
err = -errno;
zexpect_equal(ret, 0, "setsockopt failed (%d)", err);
zexpect_equal(optlen, sizeof(int), "setsockopt optlen (%d)", optlen);
zexpect_equal(optval, net_if_get_by_iface(net_if_get_default()),
"getsockopt multicast ifindex (expected %d got %d)",
net_if_get_by_iface(net_if_get_default()), optval);
server_sock = prepare_listen_sock_udp_v6(&saddr6);
zassert_not_equal(server_sock, -1, "Cannot create server socket (%d)", -errno);
test_started = true;
loopback_enable_address_swap(false);
ret = zsock_sendto(sock, TEST_STR_SMALL, sizeof(TEST_STR_SMALL) - 1, 0,
(struct sockaddr *)&saddr6, sizeof(saddr6));
zexpect_equal(ret, STRLEN(TEST_STR_SMALL),
"invalid send len (was %d expected %d) (%d)",
ret, STRLEN(TEST_STR_SMALL), -errno);
/* Test that the sent data is received from default interface and
* not the Ethernet one.
*/
addrlen = sizeof(saddr6);
ret = zsock_recvfrom(server_sock, rx_buf, sizeof(rx_buf),
0, (struct sockaddr *)&saddr6, &addrlen);
zexpect_true(ret >= 0, "recvfrom fail");
zexpect_equal(ret, strlen(TEST_STR_SMALL),
"unexpected received bytes");
zexpect_mem_equal(rx_buf, TEST_STR_SMALL, sizeof(TEST_STR_SMALL) - 1,
"wrong data");
ret = zsock_close(sock);
zassert_equal(ret, 0, "Cannot close socket (%d)", -errno);
ret = zsock_close(server_sock);
zassert_equal(ret, 0, "Cannot close socket (%d)", -errno);
test_started = false;
loopback_enable_address_swap(true);
}
ZTEST(net_socket_udp, test_39_ipv4_multicast_ifindex)
{
struct sockaddr_in saddr4 = {
.sin_family = AF_INET,
.sin_port = htons(SERVER_PORT),
.sin_addr = my_mcast_addr2,
};
struct sockaddr_in dst_addr = {
.sin_family = AF_INET,
.sin_port = htons(SERVER_PORT),
.sin_addr = my_mcast_addr2,
};
struct net_if_mcast_addr *ifmaddr;
struct net_if_addr *ifaddr;
struct in_addr addr = { 0 };
struct ip_mreqn mreqn;
struct ip_mreq mreq;
struct net_if *iface;
int server_sock;
socklen_t addrlen;
socklen_t optlen;
int ifindex;
int sock;
int ret;
int err;
net_if_foreach(iface_cb, &eth_iface);
zassert_not_null(eth_iface, "No ethernet interface found");
ifmaddr = net_if_ipv4_maddr_add(eth_iface, &my_mcast_addr2);
if (!ifmaddr) {
DBG("Cannot add IPv4 multicast address %s\n",
net_sprint_ipv4_addr(&my_mcast_addr2));
zassert_not_null(ifmaddr, "mcast_addr2");
}
ifaddr = net_if_ipv4_addr_add(eth_iface, &my_addr2,
NET_ADDR_MANUAL, 0);
if (!ifaddr) {
DBG("Cannot add IPv4 address %s\n",
net_sprint_ipv4_addr(&my_addr2));
zassert_not_null(ifaddr, "addr2");
}
net_if_up(eth_iface);
/* Check that we get the default interface */
sock = zsock_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
zassert_true(sock >= 0, "Cannot create socket (%d)", -errno);
optlen = sizeof(addr);
ret = zsock_getsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF,
&addr, &optlen);
zexpect_equal(ret, 0, "setsockopt failed (%d)", errno);
zexpect_equal(optlen, sizeof(addr), "invalid optlen %d vs %d",
optlen, sizeof(addr));
ifindex = net_if_get_by_iface(net_if_get_default());
ret = net_if_ipv4_addr_lookup_by_index(&addr);
zexpect_equal(ret, ifindex,
"getsockopt multicast ifindex (expected %d got %d)",
ifindex, ret);
ret = zsock_close(sock);
zassert_equal(sock, 0, "Cannot close socket (%d)", -errno);
/* Check failure for IPv6 socket */
sock = zsock_socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
zassert_true(sock >= 0, "Cannot create socket (%d)", -errno);
optlen = 0U;
ret = zsock_getsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF,
&addr, &optlen);
err = -errno;
zexpect_equal(ret, -1, "setsockopt failed (%d)", errno);
zexpect_equal(err, -EAFNOSUPPORT, "setsockopt failed (%d)", errno);
zexpect_equal(optlen, 0U, "setsockopt optlen (%d)", optlen);
ret = zsock_close(sock);
zassert_equal(sock, 0, "Cannot close socket (%d)", -errno);
/* Check that we can set the interface */
sock = zsock_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
zassert_true(sock >= 0, "Cannot create socket (%d)", -errno);
/* Clear any existing interface value by setting it to 0 */
optlen = sizeof(mreqn);
mreqn.imr_ifindex = 0;
mreqn.imr_address.s_addr = 0;
ret = zsock_setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF,
&mreqn, optlen);
err = -errno;
zexpect_equal(ret, 0, "setsockopt failed (%d)", err);
/* Verify that we get the empty value */
optlen = sizeof(addr);
ret = zsock_getsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF,
&addr, &optlen);
err = -errno;
zexpect_equal(ret, 0, "setsockopt failed (%d)", err);
zexpect_equal(optlen, sizeof(addr), "setsockopt optlen (%d)", optlen);
/* Set the output multicast packet interface to the default interface */
optlen = sizeof(mreqn);
mreqn.imr_ifindex = net_if_get_by_iface(net_if_get_default());
mreqn.imr_address.s_addr = 0;
ret = zsock_setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF,
&mreqn, optlen);
err = -errno;
zexpect_equal(ret, 0, "setsockopt failed (%d)", err);
/* Verify that we get the default interface */
optlen = sizeof(addr);
memset(&addr, 0, sizeof(addr));
ret = zsock_getsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF,
&addr, &optlen);
err = -errno;
zexpect_equal(ret, 0, "setsockopt failed (%d)", err);
zexpect_equal(optlen, sizeof(addr), "setsockopt optlen (%d)", optlen);
ifaddr = net_if_ipv4_addr_lookup(&addr, &iface);
zexpect_not_null(ifaddr, "Address %s not found",
net_sprint_ipv4_addr(&addr));
zexpect_equal(net_if_get_by_iface(iface),
net_if_get_by_iface(net_if_get_default()),
"Invalid interface %d vs %d",
net_if_get_by_iface(iface),
net_if_get_by_iface(net_if_get_default()));
/* Now send a packet and verify that it is sent via the default
* interface instead of the Ethernet interface.
*/
server_sock = prepare_listen_sock_udp_v4(&saddr4);
zassert_not_equal(server_sock, -1, "Cannot create server socket (%d)", -errno);
test_started = true;
loopback_enable_address_swap(false);
ret = zsock_sendto(sock, TEST_STR_SMALL, sizeof(TEST_STR_SMALL) - 1, 0,
(struct sockaddr *)&dst_addr, sizeof(dst_addr));
zexpect_equal(ret, STRLEN(TEST_STR_SMALL),
"invalid send len (was %d expected %d) (%d)",
ret, STRLEN(TEST_STR_SMALL), -errno);
/* Test that the sent data is received from Ethernet interface. */
addrlen = sizeof(saddr4);
ret = zsock_recvfrom(server_sock, rx_buf, sizeof(rx_buf),
0, (struct sockaddr *)&saddr4, &addrlen);
zexpect_true(ret >= 0, "recvfrom fail");
zexpect_equal(ret, strlen(TEST_STR_SMALL),
"unexpected received bytes");
zexpect_mem_equal(rx_buf, TEST_STR_SMALL, sizeof(TEST_STR_SMALL) - 1,
"wrong data");
/* Clear the old interface value by setting it to 0 */
optlen = sizeof(mreqn);
mreqn.imr_ifindex = 0;
mreqn.imr_address.s_addr = 0;
ret = zsock_setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF,
&mreqn, optlen);
err = -errno;
zexpect_equal(ret, 0, "setsockopt failed (%d)", err);
/* Then do it the other way around, set the address but leave the
* interface number unassigned.
*/
optlen = sizeof(mreqn);
mreqn.imr_ifindex = 0;
/* Get the address of default interface and set it as a target
* interface.
*/
ifaddr = net_if_ipv4_addr_get_first_by_index(net_if_get_by_iface(net_if_get_default()));
zexpect_not_null(ifaddr, "No address found for interface %d",
net_if_get_by_iface(net_if_get_default()));
mreqn.imr_address.s_addr = ifaddr->address.in_addr.s_addr;
ret = zsock_setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF,
&mreqn, optlen);
zexpect_equal(ret, 0, "setsockopt failed (%d)", errno);
/* Verify that we get the default interface address */
optlen = sizeof(struct in_addr);
ret = zsock_getsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF,
&addr, &optlen);
err = -errno;
zexpect_equal(ret, 0, "setsockopt failed (%d)", err);
zexpect_equal(optlen, sizeof(struct in_addr), "setsockopt optlen (%d)", optlen);
ret = net_if_ipv4_addr_lookup_by_index(&addr);
zexpect_equal(ret, net_if_get_by_iface(net_if_get_default()),
"getsockopt multicast ifindex (expected %d got %d)",
net_if_get_by_iface(net_if_get_default()), ret);
zexpect_equal(ifaddr->address.in_addr.s_addr,
addr.s_addr,
"getsockopt iface address mismatch (expected %s got %s)",
net_sprint_ipv4_addr(&ifaddr->address.in_addr),
net_sprint_ipv4_addr(&addr));
ret = zsock_sendto(sock, TEST_STR_SMALL, sizeof(TEST_STR_SMALL) - 1, 0,
(struct sockaddr *)&dst_addr, sizeof(dst_addr));
zexpect_equal(ret, STRLEN(TEST_STR_SMALL),
"invalid send len (was %d expected %d) (%d)",
ret, STRLEN(TEST_STR_SMALL), -errno);
/* Test that the sent data is received from default interface. */
addrlen = sizeof(saddr4);
ret = zsock_recvfrom(server_sock, rx_buf, sizeof(rx_buf),
0, (struct sockaddr *)&saddr4, &addrlen);
zexpect_true(ret >= 0, "recvfrom fail");
zexpect_equal(ret, strlen(TEST_STR_SMALL),
"unexpected received bytes");
zexpect_mem_equal(rx_buf, TEST_STR_SMALL, sizeof(TEST_STR_SMALL) - 1,
"wrong data");
/* Then use mreq structure to set the interface */
optlen = sizeof(mreq);
ifaddr = net_if_ipv4_addr_get_first_by_index(net_if_get_by_iface(net_if_get_default()));
zexpect_not_null(ifaddr, "No address found for interface %d",
net_if_get_by_iface(net_if_get_default()));
mreq.imr_interface.s_addr = ifaddr->address.in_addr.s_addr;
ret = zsock_setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF,
&mreq, optlen);
zexpect_equal(ret, 0, "setsockopt failed (%d)", errno);
ret = zsock_sendto(sock, TEST_STR_SMALL, sizeof(TEST_STR_SMALL) - 1, 0,
(struct sockaddr *)&dst_addr, sizeof(dst_addr));
zexpect_equal(ret, STRLEN(TEST_STR_SMALL),
"invalid send len (was %d expected %d) (%d)",
ret, STRLEN(TEST_STR_SMALL), -errno);
/* Test that the sent data is received from default interface. */
addrlen = sizeof(saddr4);
ret = zsock_recvfrom(server_sock, rx_buf, sizeof(rx_buf),
0, (struct sockaddr *)&saddr4, &addrlen);
zexpect_true(ret >= 0, "recvfrom fail");
zexpect_equal(ret, strlen(TEST_STR_SMALL),
"unexpected received bytes");
zexpect_mem_equal(rx_buf, TEST_STR_SMALL, sizeof(TEST_STR_SMALL) - 1,
"wrong data");
ret = zsock_close(sock);
zassert_equal(ret, 0, "Cannot close socket (%d)", -errno);
ret = zsock_close(server_sock);
zassert_equal(ret, 0, "Cannot close socket (%d)", -errno);
test_started = false;
loopback_enable_address_swap(true);
}
#if defined(CONFIG_NET_CONTEXT_CLAMP_PORT_RANGE)
#define PORT_RANGE(lower, upper) \
(uint32_t)(((uint16_t)(upper) << 16) | (uint16_t)(lower))
static void check_port_range(struct sockaddr *my_addr,
size_t my_addr_len,
struct sockaddr *local_addr,
size_t local_addr_len)
{
sa_family_t family = AF_UNSPEC;
uint32_t optval;
socklen_t addr_len;
socklen_t optlen;
int sock;
int ret, err;
addr_len = local_addr_len;
if (my_addr->sa_family == AF_INET) {
family = AF_INET;
} else if (my_addr->sa_family == AF_INET6) {
family = AF_INET6;
} else {
zassert_true(false, "Invalid address family %d",
my_addr->sa_family);
}
sock = zsock_socket(family, SOCK_DGRAM, IPPROTO_UDP);
zassert_true(sock >= 0, "Cannot create socket (%d)", -errno);
optval = PORT_RANGE(1024, 1500);
ret = zsock_setsockopt(sock, IPPROTO_IP, IP_LOCAL_PORT_RANGE,
&optval, sizeof(optval));
err = -errno;
zexpect_equal(ret, 0, "setsockopt failed (%d)", err);
optval = 0; optlen = 0U;
ret = zsock_setsockopt(sock, IPPROTO_IP, IP_LOCAL_PORT_RANGE,
&optval, optlen);
err = -errno;
zexpect_equal(ret, -1, "setsockopt failed (%d)", err);
optval = 0; optlen = sizeof(uint64_t);
ret = zsock_setsockopt(sock, IPPROTO_IP, IP_LOCAL_PORT_RANGE,
&optval, optlen);
err = -errno;
zexpect_equal(ret, -1, "setsockopt failed (%d)", err);
optval = PORT_RANGE(0, 0);
ret = zsock_setsockopt(sock, IPPROTO_IP, IP_LOCAL_PORT_RANGE,
&optval, sizeof(optval));
zexpect_equal(ret, 0, "setsockopt failed (%d)", err);
/* Linux allows setting the invalid port range but that is not
* then taken into use when we bind the socket.
*/
optval = PORT_RANGE(1024, 0);
ret = zsock_setsockopt(sock, IPPROTO_IP, IP_LOCAL_PORT_RANGE,
&optval, sizeof(optval));
zexpect_equal(ret, 0, "setsockopt failed (%d)", err);
optval = PORT_RANGE(0, 1024);
ret = zsock_setsockopt(sock, IPPROTO_IP, IP_LOCAL_PORT_RANGE,
&optval, sizeof(optval));
zexpect_equal(ret, 0, "setsockopt failed (%d)", err);
/* Then set a valid range and verify that bound socket is using it */
optval = PORT_RANGE(10000, 10010);
ret = zsock_setsockopt(sock, IPPROTO_IP, IP_LOCAL_PORT_RANGE,
&optval, sizeof(optval));
zexpect_equal(ret, 0, "setsockopt failed (%d)", err);
optval = 0; optlen = sizeof(optval);
ret = zsock_getsockopt(sock, IPPROTO_IP, IP_LOCAL_PORT_RANGE,
&optval, &optlen);
zexpect_equal(ret, 0, "setsockopt failed (%d)", err);
zexpect_equal(optval, PORT_RANGE(10000, 10010), "Invalid port range");
ret = zsock_bind(sock, my_addr, my_addr_len);
err = -errno;
zexpect_equal(ret, 0, "bind failed (%d)", err);
ret = zsock_getsockname(sock, local_addr, &addr_len);
err = -errno;
zexpect_equal(ret, 0, "getsockname failed (%d)", err);
/* The port should be in the range */
zexpect_true(ntohs(net_sin(local_addr)->sin_port) >= 10000 &&
ntohs(net_sin(local_addr)->sin_port) <= 10010,
"Invalid port %d", ntohs(net_sin(local_addr)->sin_port));
(void)zsock_close(sock);
/* Try setting invalid range and verify that we do not net a port from that
* range.
*/
sock = zsock_socket(family, SOCK_DGRAM, IPPROTO_UDP);
zassert_true(sock >= 0, "Cannot create socket (%d)", -errno);
optval = PORT_RANGE(1001, 1000);
ret = zsock_setsockopt(sock, IPPROTO_IP, IP_LOCAL_PORT_RANGE,
&optval, sizeof(optval));
err = -errno;
zexpect_equal(ret, -1, "setsockopt failed (%d)", err);
zexpect_equal(err, -EINVAL, "Invalid errno (%d)", -err);
/* Port range cannot be just one port */
optval = PORT_RANGE(1001, 1001);
ret = zsock_setsockopt(sock, IPPROTO_IP, IP_LOCAL_PORT_RANGE,
&optval, sizeof(optval));
err = -errno;
zexpect_equal(ret, -1, "setsockopt failed (%d)", err);
zexpect_equal(err, -EINVAL, "Invalid errno (%d)", -err);
optval = PORT_RANGE(0, 1000);
ret = zsock_setsockopt(sock, IPPROTO_IP, IP_LOCAL_PORT_RANGE,
&optval, sizeof(optval));
err = -errno;
zexpect_equal(ret, 0, "setsockopt failed (%d)", err);
ret = zsock_bind(sock, my_addr, my_addr_len);
err = -errno;
zexpect_equal(ret, 0, "bind failed (%d)", err);
addr_len = local_addr_len;
ret = zsock_getsockname(sock, local_addr, &addr_len);
err = -errno;
zexpect_equal(ret, 0, "getsockname failed (%d)", err);
/* The port should not be in the range */
zexpect_false(ntohs(net_sin(local_addr)->sin_port) >= 1000 &&
ntohs(net_sin(local_addr)->sin_port) <= 1001,
"Invalid port %d", ntohs(net_sin(local_addr)->sin_port));
(void)zsock_close(sock);
}
#endif
ZTEST(net_socket_udp, test_40_clamp_udp_tcp_port_range)
{
#if defined(CONFIG_NET_CONTEXT_CLAMP_PORT_RANGE)
struct sockaddr_in my_addr4 = {
.sin_family = AF_INET,
.sin_port = 0,
.sin_addr = { { { 192, 0, 2, 2 } } },
};
struct sockaddr_in6 my_addr6 = {
.sin6_family = AF_INET6,
.sin6_port = 0,
.sin6_addr = in6addr_loopback,
};
struct sockaddr_in local_addr4;
struct sockaddr_in6 local_addr6;
/* First try with a IPv4 socket */
check_port_range((struct sockaddr *)&my_addr4, sizeof(my_addr4),
(struct sockaddr *)&local_addr4, sizeof(local_addr4));
/* Finally try with a IPv6 socket */
check_port_range((struct sockaddr *)&my_addr6, sizeof(my_addr6),
(struct sockaddr *)&local_addr6, sizeof(local_addr6));
#else
ztest_test_skip();
#endif
}
static void test_dgram_peer_addr_reset(int sock_c, int sock_s1, int sock_s2,
struct sockaddr *addr_c, socklen_t addrlen_c,
struct sockaddr *addr_s1, socklen_t addrlen_s1,
struct sockaddr *addr_s2, socklen_t addrlen_s2)
{
uint8_t tx_buf = 0xab;
uint8_t rx_buf;
struct sockaddr_storage unspec = {
.ss_family = AF_UNSPEC,
};
int rv;
rv = zsock_bind(sock_c, addr_c, addrlen_c);
zassert_equal(rv, 0, "client bind failed");
rv = zsock_bind(sock_s1, addr_s1, addrlen_s1);
zassert_equal(rv, 0, "server bind failed");
rv = zsock_bind(sock_s2, addr_s2, addrlen_s2);
zassert_equal(rv, 0, "server bind failed");
/* Connect client socket to a specific peer address. */
rv = zsock_connect(sock_c, addr_s1, addrlen_s1);
zassert_equal(rv, 0, "connect failed");
/* Verify that a datagram is not received from other address */
rv = zsock_sendto(sock_s2, &tx_buf, sizeof(tx_buf), 0, addr_c, addrlen_c);
zassert_equal(rv, sizeof(tx_buf), "send failed");
/* Give the packet a chance to go through the net stack */
k_msleep(10);
rv = zsock_recv(sock_c, &rx_buf, sizeof(rx_buf), ZSOCK_MSG_DONTWAIT);
zassert_equal(rv, -1, "recv should've failed");
zassert_equal(errno, EAGAIN, "incorrect errno");
/* Reset peer address */
rv = zsock_connect(sock_c, (struct sockaddr *)&unspec, sizeof(unspec));
zassert_equal(rv, 0, "connect failed");
/* Verify that a datagram can be received from other address */
rv = zsock_sendto(sock_s2, &tx_buf, sizeof(tx_buf), 0, addr_c, addrlen_c);
zassert_equal(rv, sizeof(tx_buf), "send failed");
/* Give the packet a chance to go through the net stack */
k_msleep(10);
rx_buf = 0;
rv = zsock_recv(sock_c, &rx_buf, sizeof(rx_buf), ZSOCK_MSG_DONTWAIT);
zassert_equal(rv, sizeof(rx_buf), "recv failed %d", errno);
zassert_equal(rx_buf, tx_buf, "wrong data");
rv = zsock_close(sock_c);
zassert_equal(rv, 0, "close failed");
rv = zsock_close(sock_s1);
zassert_equal(rv, 0, "close failed");
rv = zsock_close(sock_s2);
zassert_equal(rv, 0, "close failed");
}
ZTEST(net_socket_udp, test_41_v4_dgram_peer_addr_reset)
{
int client_sock;
int server_sock_1;
int server_sock_2;
struct sockaddr_in client_addr;
struct sockaddr_in server_addr_1;
struct sockaddr_in server_addr_2;
prepare_sock_udp_v4(MY_IPV4_ADDR, CLIENT_PORT, &client_sock, &client_addr);
prepare_sock_udp_v4(MY_IPV4_ADDR, SERVER_PORT, &server_sock_1, &server_addr_1);
prepare_sock_udp_v4(MY_IPV4_ADDR, SERVER_PORT + 1, &server_sock_2, &server_addr_2);
test_dgram_peer_addr_reset(client_sock, server_sock_1, server_sock_2,
(struct sockaddr *)&client_addr, sizeof(client_addr),
(struct sockaddr *)&server_addr_1, sizeof(server_addr_1),
(struct sockaddr *)&server_addr_2, sizeof(server_addr_2));
}
ZTEST(net_socket_udp, test_42_v6_dgram_peer_addr_reset)
{
int client_sock;
int server_sock_1;
int server_sock_2;
struct sockaddr_in6 client_addr;
struct sockaddr_in6 server_addr_1;
struct sockaddr_in6 server_addr_2;
prepare_sock_udp_v6(MY_IPV6_ADDR, CLIENT_PORT, &client_sock, &client_addr);
prepare_sock_udp_v6(MY_IPV6_ADDR, SERVER_PORT, &server_sock_1, &server_addr_1);
prepare_sock_udp_v6(MY_IPV6_ADDR, SERVER_PORT + 1, &server_sock_2, &server_addr_2);
test_dgram_peer_addr_reset(client_sock, server_sock_1, server_sock_2,
(struct sockaddr *)&client_addr, sizeof(client_addr),
(struct sockaddr *)&server_addr_1, sizeof(server_addr_1),
(struct sockaddr *)&server_addr_2, sizeof(server_addr_2));
}
static void comm_sendmsg_recvmsg_hop_limit(int client_sock,
struct sockaddr *client_addr,
socklen_t client_addrlen,
const struct msghdr *client_msg,
int server_sock,
struct sockaddr *server_addr,
socklen_t server_addrlen,
struct msghdr *msg,
void *cmsgbuf, int cmsgbuf_len,
bool expect_control_data)
{
#define MAX_BUF_LEN 64
char buf[MAX_BUF_LEN];
struct iovec io_vector[1];
ssize_t sent;
ssize_t recved;
struct sockaddr addr;
socklen_t addrlen = server_addrlen;
int len, i;
zassert_not_null(client_addr, "null client addr");
zassert_not_null(server_addr, "null server addr");
/*
* Test client -> server sending
*/
sent = zsock_sendmsg(client_sock, client_msg, 0);
zassert_true(sent > 0, "sendmsg failed, %s (%d)", strerror(errno), -errno);
/* One negative test with invalid msg_iov */
memset(msg, 0, sizeof(*msg));
recved = zsock_recvmsg(server_sock, msg, 0);
zassert_true(recved < 0 && errno == ENOMEM, "Wrong errno (%d)", errno);
for (i = 0, len = 0; i < client_msg->msg_iovlen; i++) {
len += client_msg->msg_iov[i].iov_len;
}
zassert_equal(sent, len, "iovec len (%d) vs sent (%d)", len, sent);
/* Test first with one iovec */
io_vector[0].iov_base = buf;
io_vector[0].iov_len = sizeof(buf);
memset(msg, 0, sizeof(*msg));
if (cmsgbuf != NULL) {
memset(cmsgbuf, 0, cmsgbuf_len);
}
msg->msg_control = cmsgbuf;
msg->msg_controllen = cmsgbuf_len;
msg->msg_iov = io_vector;
msg->msg_iovlen = 1;
msg->msg_name = &addr;
msg->msg_namelen = addrlen;
/* Test normal recvmsg() */
clear_buf(rx_buf);
recved = zsock_recvmsg(server_sock, msg, 0);
zassert_true(recved > 0, "recvfrom fail");
zassert_equal(recved, len, "unexpected received bytes");
zassert_equal(msg->msg_iovlen, 1, "recvmsg should not modify msg_iovlen");
zassert_equal(msg->msg_iov[0].iov_len, sizeof(buf),
"recvmsg should not modify buffer length");
zassert_mem_equal(buf, TEST_STR_SMALL, len,
"wrong data (%s)", rx_buf);
zassert_equal(addrlen, client_addrlen, "unexpected addrlen");
/* Control data should be empty */
if (!expect_control_data) {
zassert_equal(msg->msg_controllen, 0,
"We received control data (%u vs %zu)",
0U, msg->msg_controllen);
}
}
static void run_ancillary_recvmsg_hoplimit_test(int client_sock,
struct sockaddr *client_addr,
int client_addr_len,
int server_sock,
struct sockaddr *server_addr,
int server_addr_len)
{
int rv;
int opt;
socklen_t optlen;
struct msghdr msg;
struct msghdr server_msg;
struct iovec io_vector[1];
struct cmsghdr *cmsg, *prevcmsg;
int send_hop_limit = 90, recv_hop_limit = 0;
union {
struct cmsghdr hdr;
unsigned char buf[CMSG_SPACE(sizeof(int))];
} cmsgbuf;
Z_TEST_SKIP_IFNDEF(CONFIG_NET_CONTEXT_RECV_HOPLIMIT);
rv = zsock_bind(server_sock, server_addr, server_addr_len);
zassert_equal(rv, 0, "server bind failed");
rv = zsock_bind(client_sock, client_addr, client_addr_len);
zassert_equal(rv, 0, "client bind failed");
io_vector[0].iov_base = TEST_STR_SMALL;
io_vector[0].iov_len = strlen(TEST_STR_SMALL);
memset(&cmsgbuf, 0, sizeof(cmsgbuf));
memset(&msg, 0, sizeof(msg));
msg.msg_name = server_addr;
msg.msg_namelen = server_addr_len;
msg.msg_iov = io_vector;
msg.msg_iovlen = 1;
msg.msg_control = &cmsgbuf.buf;
msg.msg_controllen = sizeof(cmsgbuf.buf);
cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
if (client_addr->sa_family == AF_INET) {
cmsg->cmsg_level = IPPROTO_IP;
cmsg->cmsg_type = IP_TTL;
} else {
cmsg->cmsg_level = IPPROTO_IPV6;
cmsg->cmsg_type = IPV6_HOPLIMIT;
}
*(int *)CMSG_DATA(cmsg) = send_hop_limit;
comm_sendmsg_recvmsg_hop_limit(client_sock,
client_addr,
client_addr_len,
&msg,
server_sock,
server_addr,
server_addr_len,
&server_msg,
&cmsgbuf.buf,
sizeof(cmsgbuf.buf),
true);
for (prevcmsg = NULL, cmsg = CMSG_FIRSTHDR(&server_msg);
cmsg != NULL && prevcmsg != cmsg;
prevcmsg = cmsg, cmsg = CMSG_NXTHDR(&server_msg, cmsg)) {
if (client_addr->sa_family == AF_INET) {
if (cmsg->cmsg_level == IPPROTO_IP &&
cmsg->cmsg_type == IP_TTL) {
recv_hop_limit = *(int *)CMSG_DATA(cmsg);
break;
}
} else {
if (cmsg->cmsg_level == IPPROTO_IPV6 &&
cmsg->cmsg_type == IPV6_HOPLIMIT) {
recv_hop_limit = *(int *)CMSG_DATA(cmsg);
break;
}
}
}
/* As we have not set the socket option, the hop_limit should not be set */
zassert_equal(recv_hop_limit, 0, "Hop limit set!");
opt = 1;
optlen = sizeof(opt);
if (server_addr->sa_family == AF_INET) {
rv = zsock_setsockopt(server_sock, IPPROTO_IP, IP_RECVTTL, &opt, optlen);
} else {
rv = zsock_setsockopt(server_sock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &opt, optlen);
}
zassert_equal(rv, 0, "setsockopt failed (%d)", -errno);
memset(&cmsgbuf, 0, sizeof(cmsgbuf));
memset(&msg, 0, sizeof(msg));
msg.msg_name = server_addr;
msg.msg_namelen = server_addr_len;
msg.msg_iov = io_vector;
msg.msg_iovlen = 1;
msg.msg_control = &cmsgbuf.buf;
msg.msg_controllen = sizeof(cmsgbuf.buf);
cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
if (client_addr->sa_family == AF_INET) {
cmsg->cmsg_level = IPPROTO_IP;
cmsg->cmsg_type = IP_TTL;
} else {
cmsg->cmsg_level = IPPROTO_IPV6;
cmsg->cmsg_type = IPV6_HOPLIMIT;
}
*(int *)CMSG_DATA(cmsg) = send_hop_limit;
comm_sendmsg_recvmsg_hop_limit(client_sock,
client_addr,
client_addr_len,
&msg,
server_sock,
server_addr,
server_addr_len,
&server_msg,
&cmsgbuf.buf,
sizeof(cmsgbuf.buf),
true);
for (prevcmsg = NULL, cmsg = CMSG_FIRSTHDR(&server_msg);
cmsg != NULL && prevcmsg != cmsg;
prevcmsg = cmsg, cmsg = CMSG_NXTHDR(&server_msg, cmsg)) {
if (client_addr->sa_family == AF_INET) {
if (cmsg->cmsg_level == IPPROTO_IP &&
cmsg->cmsg_type == IP_TTL) {
recv_hop_limit = *(int *)CMSG_DATA(cmsg);
break;
}
} else {
if (cmsg->cmsg_level == IPPROTO_IPV6 &&
cmsg->cmsg_type == IPV6_HOPLIMIT) {
recv_hop_limit = *(int *)CMSG_DATA(cmsg);
break;
}
}
}
zassert_equal(send_hop_limit, recv_hop_limit, "Hop limit not parsed correctly");
}
ZTEST_USER(net_socket_udp, test_43_recvmsg_ancillary_ipv4_hoplimit_data_user)
{
struct sockaddr_in client_addr;
struct sockaddr_in server_addr;
int client_sock;
int server_sock;
prepare_sock_udp_v4(MY_IPV4_ADDR, ANY_PORT, &client_sock, &client_addr);
prepare_sock_udp_v4(MY_IPV4_ADDR, SERVER_PORT, &server_sock, &server_addr);
run_ancillary_recvmsg_hoplimit_test(client_sock,
(struct sockaddr *)&client_addr,
sizeof(client_addr),
server_sock,
(struct sockaddr *)&server_addr,
sizeof(server_addr));
}
ZTEST_USER(net_socket_udp, test_44_recvmsg_ancillary_ipv6_hoplimit_data_user)
{
struct sockaddr_in6 client_addr;
struct sockaddr_in6 server_addr;
int client_sock;
int server_sock;
prepare_sock_udp_v6(MY_IPV6_ADDR, ANY_PORT, &client_sock, &client_addr);
prepare_sock_udp_v6(MY_IPV6_ADDR, SERVER_PORT, &server_sock, &server_addr);
run_ancillary_recvmsg_hoplimit_test(client_sock,
(struct sockaddr *)&client_addr,
sizeof(client_addr),
server_sock,
(struct sockaddr *)&server_addr,
sizeof(server_addr));
}
static void sendto_recvfrom(int client_sock,
struct sockaddr *client_addr,
socklen_t client_addrlen,
int server_sock,
struct sockaddr *server_addr,
socklen_t server_addrlen,
bool expect_failure)
{
ssize_t sent = 0;
ssize_t recved = 0;
struct sockaddr addr;
socklen_t addrlen;
struct sockaddr addr2;
socklen_t addrlen2;
zassert_not_null(client_addr, "null client addr");
zassert_not_null(server_addr, "null server addr");
/*
* Test client -> server sending
*/
sent = zsock_sendto(client_sock, TEST_STR_SMALL, strlen(TEST_STR_SMALL),
0, server_addr, server_addrlen);
zassert_equal(sent, strlen(TEST_STR_SMALL), "sendto failed");
k_msleep(100);
/* Test normal recvfrom() */
addrlen = sizeof(addr);
clear_buf(rx_buf);
recved = zsock_recvfrom(server_sock, rx_buf, sizeof(rx_buf),
0, &addr, &addrlen);
zassert_true(recved >= 0, "recvfrom fail");
zassert_equal(recved, strlen(TEST_STR_SMALL),
"unexpected received bytes");
zassert_mem_equal(rx_buf, BUF_AND_SIZE(TEST_STR_SMALL), "wrong data");
zassert_equal(addrlen, client_addrlen, "unexpected addrlen");
/*
* Test server -> client sending
*/
sent = zsock_sendto(server_sock, TEST_STR2, sizeof(TEST_STR2) - 1,
0, &addr, addrlen);
zassert_equal(sent, STRLEN(TEST_STR2), "sendto failed");
/* Test normal recvfrom() */
addrlen2 = sizeof(addr);
clear_buf(rx_buf);
recved = zsock_recvfrom(client_sock, rx_buf, sizeof(rx_buf),
expect_failure ? ZSOCK_MSG_DONTWAIT : 0,
&addr2, &addrlen2);
if (!expect_failure) {
zassert_true(recved >= 0, "recvfrom fail");
zassert_equal(recved, STRLEN(TEST_STR2),
"unexpected received bytes");
zassert_mem_equal(rx_buf, BUF_AND_SIZE(TEST_STR2), "wrong data");
zassert_equal(addrlen2, server_addrlen, "unexpected addrlen");
} else {
/* We should not receive anything as the socket is shutdown for
* receiving.
*/
zassert_equal(recved, -1, "recvfrom should fail (got %d)", recved);
}
}
ZTEST_USER(net_socket_udp, test_45_udp_shutdown_recv)
{
int rv;
int client_sock;
int server_sock;
struct sockaddr_in client_addr;
struct sockaddr_in server_addr;
prepare_sock_udp_v4(MY_IPV4_ADDR, ANY_PORT, &client_sock, &client_addr);
prepare_sock_udp_v4(MY_IPV4_ADDR, SERVER_PORT, &server_sock, &server_addr);
rv = zsock_bind(server_sock,
(struct sockaddr *)&server_addr,
sizeof(server_addr));
zassert_equal(rv, 0, "bind failed");
sendto_recvfrom(client_sock,
(struct sockaddr *)&client_addr,
sizeof(client_addr),
server_sock,
(struct sockaddr *)&server_addr,
sizeof(server_addr),
false);
/* Shutdown UDP socket for receiving and verify that we do not get any data. */
rv = zsock_shutdown(client_sock, ZSOCK_SHUT_RD);
zassert_equal(rv, 0, "shutdown failed (%d)", -errno);
sendto_recvfrom(client_sock,
(struct sockaddr *)&client_addr,
sizeof(client_addr),
server_sock,
(struct sockaddr *)&server_addr,
sizeof(server_addr),
true);
rv = zsock_close(client_sock);
zassert_equal(rv, 0, "close failed");
rv = zsock_close(server_sock);
zassert_equal(rv, 0, "close failed");
}
enum ipv4_mapped_to_ipv6_send_mode {
IPV4_MAPPED_TO_IPV6_SENDTO,
IPV4_MAPPED_TO_IPV6_SENDMSG,
};
void test_ipv4_mapped_to_ipv6_send_common(enum ipv4_mapped_to_ipv6_send_mode test_mode)
{
int off = 0;
int ret;
int sock_s, sock_c;
socklen_t addrlen;
struct sockaddr_in addr_c4 = { 0 };
struct sockaddr_in addr_s4 = { 0 };
struct sockaddr_in6 addr_s6 = { 0 };
struct sockaddr_in6 addr_recv = { 0 };
struct in6_addr mapped_address = { 0 };
/* Create IPv4 client socket */
prepare_sock_udp_v4(MY_IPV4_ADDR, CLIENT_PORT, &sock_c, &addr_c4);
/* Create IPv6 server socket */
prepare_sock_udp_v6(ANY_IPV6_ADDR, SERVER_PORT, &sock_s, &addr_s6);
/* Prepare server's IPv4 address and expected mapped address */
addr_s4.sin_family = AF_INET;
addr_s4.sin_port = htons(SERVER_PORT);
ret = zsock_inet_pton(AF_INET, MY_IPV4_ADDR, &addr_s4.sin_addr);
zassert_equal(ret, 1, "inet_pton failed");
ret = zsock_inet_pton(AF_INET6, MY_IPV4_MAPPED_ADDR, &mapped_address);
zassert_equal(ret, 1, "inet_pton failed");
/* Bind the client socket to ensure we check the correct address */
ret = zsock_bind(sock_c, (struct sockaddr *)&addr_c4, sizeof(addr_c4));
zassert_ok(ret, "bind failed, %d", errno);
/* Turn off IPV6_V6ONLY on the server socket, so the socket becomes
* dual-stack.
*/
ret = zsock_setsockopt(sock_s, IPPROTO_IPV6, IPV6_V6ONLY, &off, sizeof(off));
zassert_ok(ret, "setsockopt failed, %d", errno);
/* And bind it to ANY address */
ret = zsock_bind(sock_s, (struct sockaddr *)&addr_s6, sizeof(addr_s6));
zassert_ok(ret, "bind failed, %d", errno);
/* Send datagram from IPv4 client socket to dual-stack server */
ret = zsock_sendto(sock_c, TEST_STR_SMALL, sizeof(TEST_STR_SMALL) - 1, 0,
(struct sockaddr *)&addr_s4, sizeof(addr_s4));
zexpect_equal(ret, sizeof(TEST_STR_SMALL) - 1,
"invalid send len (was %d expected %d) (%d)",
ret, sizeof(TEST_STR_SMALL) - 1, errno);
/* Give the packet a chance to go through the net stack */
k_msleep(10);
/* Server should get the datagram, with IPv4-to-IPv6 mapped address */
addrlen = sizeof(addr_recv);
clear_buf(rx_buf);
ret = zsock_recvfrom(sock_s, rx_buf, sizeof(rx_buf), ZSOCK_MSG_DONTWAIT,
(struct sockaddr *)&addr_recv, &addrlen);
zassert_true(ret >= 0, "recvfrom fail (%d)", errno);
zassert_equal(ret, sizeof(TEST_STR_SMALL) - 1, "unexpected received bytes");
zassert_mem_equal(rx_buf, BUF_AND_SIZE(TEST_STR_SMALL), "wrong data");
zassert_equal(addrlen, sizeof(struct sockaddr_in6), "unexpected addrlen");
zassert_equal(addr_recv.sin6_family, AF_INET6,
"IPv4-to-IPv6 mapped address should be AF_INET6");
zassert_equal(addr_recv.sin6_port, htons(CLIENT_PORT), "invalid port");
zassert_mem_equal(&addr_recv.sin6_addr, &mapped_address,
sizeof(mapped_address), "invalid mapped address");
/* Echo data back */
if (test_mode == IPV4_MAPPED_TO_IPV6_SENDTO) {
ret = zsock_sendto(sock_s, TEST_STR_SMALL, sizeof(TEST_STR_SMALL) - 1, 0,
(struct sockaddr *)&addr_recv, addrlen);
zexpect_equal(ret, sizeof(TEST_STR_SMALL) - 1,
"invalid send len (was %d expected %d) (%d)",
ret, sizeof(TEST_STR_SMALL) - 1, errno);
} else if (test_mode == IPV4_MAPPED_TO_IPV6_SENDMSG) {
struct msghdr msg = { 0 };
struct iovec io_vector[1] = { 0 };
io_vector[0].iov_base = TEST_STR_SMALL;
io_vector[0].iov_len = strlen(TEST_STR_SMALL);
msg.msg_iov = io_vector;
msg.msg_iovlen = 1;
msg.msg_name = &addr_recv;
msg.msg_namelen = addrlen;
ret = zsock_sendmsg(sock_s, &msg, 0);
zexpect_equal(ret, sizeof(TEST_STR_SMALL) - 1,
"invalid send len (was %d expected %d) (%d)",
ret, sizeof(TEST_STR_SMALL) - 1, errno);
} else {
zassert_unreachable("invalid test mode");
}
/* Give the packet a chance to go through the net stack */
k_msleep(10);
/* Client should get the echoed datagram */
clear_buf(rx_buf);
ret = zsock_recv(sock_c, rx_buf, sizeof(rx_buf), ZSOCK_MSG_DONTWAIT);
zassert_true(ret >= 0, "recvfrom fail (%d)", errno);
zassert_equal(ret, sizeof(TEST_STR_SMALL) - 1, "unexpected received bytes");
zassert_mem_equal(rx_buf, BUF_AND_SIZE(TEST_STR_SMALL), "wrong data");
ret = zsock_close(sock_c);
zassert_ok(ret, "close failed, %d", errno);
ret = zsock_close(sock_s);
zassert_ok(ret, "close failed, %d", errno);
}
ZTEST(net_socket_udp, test_46_ipv4_mapped_to_ipv6_sendto)
{
Z_TEST_SKIP_IFNDEF(CONFIG_NET_IPV4_MAPPING_TO_IPV6);
test_ipv4_mapped_to_ipv6_send_common(IPV4_MAPPED_TO_IPV6_SENDTO);
}
ZTEST(net_socket_udp, test_47_ipv4_mapped_to_ipv6_sendmsg)
{
Z_TEST_SKIP_IFNDEF(CONFIG_NET_IPV4_MAPPING_TO_IPV6);
test_ipv4_mapped_to_ipv6_send_common(IPV4_MAPPED_TO_IPV6_SENDMSG);
}
static void after(void *arg)
{
ARG_UNUSED(arg);
for (int i = 0; i < CONFIG_ZVFS_OPEN_MAX; ++i) {
(void)zsock_close(i);
}
}
ZTEST_SUITE(net_socket_udp, NULL, NULL, NULL, after, NULL);