Skip to content

Commit

Permalink
[nrf fromlist] tests: net: sockets: misc: Fix SO_BINDTODEVICE test
Browse files Browse the repository at this point in the history
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.

Upstream PR: zephyrproject-rtos/zephyr#76150

Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
  • Loading branch information
rlubos committed Jul 24, 2024
1 parent 8587f90 commit 4c996ec
Showing 1 changed file with 34 additions and 28 deletions.
62 changes: 34 additions & 28 deletions tests/net/socket/misc/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 };
Expand Down Expand Up @@ -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));
Expand All @@ -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));
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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),
Expand All @@ -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),
Expand All @@ -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) ? \
Expand Down

0 comments on commit 4c996ec

Please sign in to comment.