Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tcp: Add selftest for bind() and TIME_WAIT.

bhash2 split the bind() validation logic into wildcard and non-wildcard
cases. Let's add a test to catch future regression.

Before the previous patch:

# ./bind_timewait
TAP version 13
1..2
# Starting 2 tests from 3 test cases.
# RUN bind_timewait.localhost.1 ...
# bind_timewait.c:87:1:Expected ret (0) == -1 (-1)
# 1: Test terminated by assertion
# FAIL bind_timewait.localhost.1
not ok 1 bind_timewait.localhost.1
# RUN bind_timewait.addrany.1 ...
# OK bind_timewait.addrany.1
ok 2 bind_timewait.addrany.1
# FAILED: 1 / 2 tests passed.
# Totals: pass:1 fail:1 xfail:0 xpass:0 skip:0 error:0

After:

# ./bind_timewait
TAP version 13
1..2
# Starting 2 tests from 3 test cases.
# RUN bind_timewait.localhost.1 ...
# OK bind_timewait.localhost.1
ok 1 bind_timewait.localhost.1
# RUN bind_timewait.addrany.1 ...
# OK bind_timewait.addrany.1
ok 2 bind_timewait.addrany.1
# PASSED: 2 / 2 tests passed.
# Totals: pass:2 fail:0 xfail:0 xpass:0 skip:0 error:0

Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Acked-by: Joanne Koong <joannelkoong@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Kuniyuki Iwashima and committed by
David S. Miller
2c042e8e 936a192f

+93
+1
tools/testing/selftests/net/.gitignore
··· 1 1 # SPDX-License-Identifier: GPL-2.0-only 2 2 bind_bhash 3 + bind_timewait 3 4 csum 4 5 cmsg_sender 5 6 diag_uid
+92
tools/testing/selftests/net/bind_timewait.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright Amazon.com Inc. or its affiliates. */ 3 + 4 + #include <sys/socket.h> 5 + #include <netinet/in.h> 6 + 7 + #include "../kselftest_harness.h" 8 + 9 + FIXTURE(bind_timewait) 10 + { 11 + struct sockaddr_in addr; 12 + socklen_t addrlen; 13 + }; 14 + 15 + FIXTURE_VARIANT(bind_timewait) 16 + { 17 + __u32 addr_const; 18 + }; 19 + 20 + FIXTURE_VARIANT_ADD(bind_timewait, localhost) 21 + { 22 + .addr_const = INADDR_LOOPBACK 23 + }; 24 + 25 + FIXTURE_VARIANT_ADD(bind_timewait, addrany) 26 + { 27 + .addr_const = INADDR_ANY 28 + }; 29 + 30 + FIXTURE_SETUP(bind_timewait) 31 + { 32 + self->addr.sin_family = AF_INET; 33 + self->addr.sin_port = 0; 34 + self->addr.sin_addr.s_addr = htonl(variant->addr_const); 35 + self->addrlen = sizeof(self->addr); 36 + } 37 + 38 + FIXTURE_TEARDOWN(bind_timewait) 39 + { 40 + } 41 + 42 + void create_timewait_socket(struct __test_metadata *_metadata, 43 + FIXTURE_DATA(bind_timewait) *self) 44 + { 45 + int server_fd, client_fd, child_fd, ret; 46 + struct sockaddr_in addr; 47 + socklen_t addrlen; 48 + 49 + server_fd = socket(AF_INET, SOCK_STREAM, 0); 50 + ASSERT_GT(server_fd, 0); 51 + 52 + ret = bind(server_fd, (struct sockaddr *)&self->addr, self->addrlen); 53 + ASSERT_EQ(ret, 0); 54 + 55 + ret = listen(server_fd, 1); 56 + ASSERT_EQ(ret, 0); 57 + 58 + ret = getsockname(server_fd, (struct sockaddr *)&self->addr, &self->addrlen); 59 + ASSERT_EQ(ret, 0); 60 + 61 + client_fd = socket(AF_INET, SOCK_STREAM, 0); 62 + ASSERT_GT(client_fd, 0); 63 + 64 + ret = connect(client_fd, (struct sockaddr *)&self->addr, self->addrlen); 65 + ASSERT_EQ(ret, 0); 66 + 67 + addrlen = sizeof(addr); 68 + child_fd = accept(server_fd, (struct sockaddr *)&addr, &addrlen); 69 + ASSERT_GT(child_fd, 0); 70 + 71 + close(child_fd); 72 + close(client_fd); 73 + close(server_fd); 74 + } 75 + 76 + TEST_F(bind_timewait, 1) 77 + { 78 + int fd, ret; 79 + 80 + create_timewait_socket(_metadata, self); 81 + 82 + fd = socket(AF_INET, SOCK_STREAM, 0); 83 + ASSERT_GT(fd, 0); 84 + 85 + ret = bind(fd, (struct sockaddr *)&self->addr, self->addrlen); 86 + ASSERT_EQ(ret, -1); 87 + ASSERT_EQ(errno, EADDRINUSE); 88 + 89 + close(fd); 90 + } 91 + 92 + TEST_HARNESS_MAIN