tests: net: sockets: misc: Fix SO_BINDTODEVICE test

The test case for SO_BINDTODEVICE socket option was flaky, the client
socket always sent the datagram to the IP address of the second
interface, so in theory every packet should end up on that interface.
In practice though, due to imperfect loopback packet handling, the test
worked as the packet ended up on the interface it was sent from.

The test should send datagrams to the IP addresses of the interface 1
and 2 alternatively. The server socket binds to ANY address, so w/o
interface binding it should receive all datagrams, so it allows to
verify if SO_BINDTODEVICE filtering works fine.

Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
This commit is contained in:
Robert Lubos 2024-07-23 10:48:43 +02:00 committed by Anas Nashif
commit dfbdfb05da

View file

@ -166,9 +166,9 @@ NET_DEVICE_INIT(dummy_2, DEV2_NAME, NULL, NULL, &dummy_data2, NULL,
#define DST_PORT 4242
#define BIND_PORT 4240
void test_so_bindtodevice(int sock_c, int sock_s, struct sockaddr *peer_addr,
socklen_t peer_addrlen, struct sockaddr *bind_addr,
socklen_t bind_addrlen)
void test_so_bindtodevice(int sock_c, int sock_s, struct sockaddr *peer_addr_1,
struct sockaddr *peer_addr_2, socklen_t peer_addrlen,
struct sockaddr *bind_addr, socklen_t bind_addrlen)
{
int ret;
struct ifreq ifreq = { 0 };
@ -203,7 +203,7 @@ void test_so_bindtodevice(int sock_c, int sock_s, struct sockaddr *peer_addr,
zassert_equal(ret, 0, "SO_BINDTODEVICE failed, %d", errno);
ret = zsock_sendto(sock_c, send_buf, strlen(send_buf) + 1, 0,
peer_addr, peer_addrlen);
peer_addr_1, peer_addrlen);
zassert_equal(ret, strlen(send_buf) + 1, "sendto failed, %d", errno);
ret = sys_sem_take(&send_sem, K_MSEC(100));
@ -228,7 +228,7 @@ void test_so_bindtodevice(int sock_c, int sock_s, struct sockaddr *peer_addr,
zassert_equal(ret, 0, "SO_BINDTODEVICE failed, %d", errno);
ret = zsock_sendto(sock_c, send_buf, strlen(send_buf) + 1, 0,
peer_addr, peer_addrlen);
peer_addr_2, peer_addrlen);
zassert_equal(ret, strlen(send_buf) + 1, "sendto failed, %d", errno);
ret = sys_sem_take(&send_sem, K_MSEC(100));
@ -266,7 +266,7 @@ void test_so_bindtodevice(int sock_c, int sock_s, struct sockaddr *peer_addr,
zassert_equal(ret, 0, "SO_BINDTODEVICE failed, %d", errno);
ret = zsock_sendto(sock_c, send_buf, strlen(send_buf) + 1, 0,
peer_addr, peer_addrlen);
peer_addr_1, peer_addrlen);
zassert_equal(ret, strlen(send_buf) + 1, "sendto failed, %d", errno);
ret = sys_sem_take(&send_sem, K_MSEC(100));
@ -295,10 +295,18 @@ void test_so_bindtodevice(int sock_c, int sock_s, struct sockaddr *peer_addr,
void test_ipv4_so_bindtodevice(void)
{
int ret;
int sock_c;
int sock_s;
struct sockaddr_in peer_addr;
struct sockaddr_in peer_addr_1 = {
.sin_family = AF_INET,
.sin_port = htons(DST_PORT),
.sin_addr = { { { 192, 0, 2, 1 } } },
};
struct sockaddr_in peer_addr_2 = {
.sin_family = AF_INET,
.sin_port = htons(DST_PORT),
.sin_addr = { { { 192, 0, 2, 2 } } },
};
struct sockaddr_in bind_addr = {
.sin_family = AF_INET,
.sin_port = htons(DST_PORT),
@ -310,23 +318,27 @@ void test_ipv4_so_bindtodevice(void)
sock_s = zsock_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
zassert_true(sock_s >= 0, "socket open failed");
peer_addr.sin_family = AF_INET;
peer_addr.sin_port = htons(DST_PORT);
ret = zsock_inet_pton(AF_INET, TEST_PEER_IPV4_ADDR,
&peer_addr.sin_addr);
zassert_equal(ret, 1, "inet_pton failed");
test_so_bindtodevice(sock_c, sock_s, (struct sockaddr *)&peer_addr,
sizeof(peer_addr), (struct sockaddr *)&bind_addr,
sizeof(bind_addr));
test_so_bindtodevice(sock_c, sock_s, (struct sockaddr *)&peer_addr_1,
(struct sockaddr *)&peer_addr_2, sizeof(peer_addr_1),
(struct sockaddr *)&bind_addr, sizeof(bind_addr));
}
void test_ipv6_so_bindtodevice(void)
{
int ret;
int sock_c;
int sock_s;
struct sockaddr_in6 peer_addr;
struct sockaddr_in6 peer_addr_1 = {
.sin6_family = AF_INET6,
.sin6_port = htons(DST_PORT),
.sin6_addr = { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0x1 } } },
};
struct sockaddr_in6 peer_addr_2 = {
.sin6_family = AF_INET6,
.sin6_port = htons(DST_PORT),
.sin6_addr = { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0x2 } } },
};
struct sockaddr_in6 bind_addr = {
.sin6_family = AF_INET6,
.sin6_port = htons(DST_PORT),
@ -338,15 +350,9 @@ void test_ipv6_so_bindtodevice(void)
sock_s = zsock_socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
zassert_true(sock_s >= 0, "socket open failed");
peer_addr.sin6_family = AF_INET6;
peer_addr.sin6_port = htons(DST_PORT);
ret = zsock_inet_pton(AF_INET6, TEST_PEER_IPV6_ADDR,
&peer_addr.sin6_addr);
zassert_equal(ret, 1, "inet_pton failed");
test_so_bindtodevice(sock_c, sock_s, (struct sockaddr *)&peer_addr,
sizeof(peer_addr), (struct sockaddr *)&bind_addr,
sizeof(bind_addr));
test_so_bindtodevice(sock_c, sock_s, (struct sockaddr *)&peer_addr_1,
(struct sockaddr *)&peer_addr_2, sizeof(peer_addr_1),
(struct sockaddr *)&bind_addr, sizeof(bind_addr));
}
#define ADDR_SIZE(family) ((family == AF_INET) ? \