Skip to content

Commit

Permalink
tests: net: socket: udp: Add IP_LOCAL_PORT_RANGE socket option tests
Browse files Browse the repository at this point in the history
Make sure that the IP_LOCAL_PORT_RANGE socket option works
as expected.

Signed-off-by: Jukka Rissanen <[email protected]>
  • Loading branch information
jukkar committed Nov 19, 2024
1 parent 5c3c8c6 commit 001c71e
Show file tree
Hide file tree
Showing 3 changed files with 171 additions and 1 deletion.
2 changes: 1 addition & 1 deletion tests/net/socket/udp/prj.conf
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ CONFIG_TEST_RANDOM_GENERATOR=y

CONFIG_MAIN_STACK_SIZE=2048
CONFIG_ZTEST_STACK_SIZE=2048
CONFIG_HEAP_MEM_POOL_SIZE=256
CONFIG_HEAP_MEM_POOL_SIZE=512

CONFIG_ZTEST=y
CONFIG_NET_TEST=y
Expand Down
167 changes: 167 additions & 0 deletions tests/net/socket/udp/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -2925,6 +2925,173 @@ ZTEST(net_socket_udp, test_39_ipv4_multicast_ifindex)
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;
size_t addr_len;
size_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 after(void *arg)
{
ARG_UNUSED(arg);
Expand Down
3 changes: 3 additions & 0 deletions tests/net/socket/udp/testcase.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ tests:
net.socket.udp.pktinfo:
extra_configs:
- CONFIG_NET_CONTEXT_RECV_PKTINFO=y
net.socket.udp.port_range:
extra_configs:
- CONFIG_NET_CONTEXT_CLAMP_PORT_RANGE=y
net.socket.udp.ttl:
extra_configs:
- CONFIG_NET_SOCKETS_PACKET=y
Expand Down

0 comments on commit 001c71e

Please sign in to comment.