From 4c996ecd07e576524a98405b2af6c01c56cb83e5 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Tue, 23 Jul 2024 10:48:43 +0200 Subject: [PATCH] [nrf fromlist] 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. Upstream PR: https://github.com/zephyrproject-rtos/zephyr/pull/76150 Signed-off-by: Robert Lubos --- tests/net/socket/misc/src/main.c | 62 +++++++++++++++++--------------- 1 file changed, 34 insertions(+), 28 deletions(-) diff --git a/tests/net/socket/misc/src/main.c b/tests/net/socket/misc/src/main.c index 1ddc872ce3b..32b0430aeab 100644 --- a/tests/net/socket/misc/src/main.c +++ b/tests/net/socket/misc/src/main.c @@ -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) ? \