xref: /linux/tools/testing/selftests/net/bind_wildcard.c (revision 6f9bc755c0215501c45897aa5c8b8b56fb65724e)
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 static const __u32 in4addr_any = INADDR_ANY;
10 static const __u32 in4addr_loopback = INADDR_LOOPBACK;
11 static const struct in6_addr in6addr_v4mapped_any = {
12 	.s6_addr = {
13 		0, 0, 0, 0,
14 		0, 0, 0, 0,
15 		0, 0, 255, 255,
16 		0, 0, 0, 0
17 	}
18 };
19 static const struct in6_addr in6addr_v4mapped_loopback = {
20 	.s6_addr = {
21 		0, 0, 0, 0,
22 		0, 0, 0, 0,
23 		0, 0, 255, 255,
24 		127, 0, 0, 1
25 	}
26 };
27 
28 FIXTURE(bind_wildcard)
29 {
30 	socklen_t addrlen[2];
31 	union {
32 		struct sockaddr addr;
33 		struct sockaddr_in addr4;
34 		struct sockaddr_in6 addr6;
35 	} addr[2];
36 };
37 
38 FIXTURE_VARIANT(bind_wildcard)
39 {
40 	sa_family_t family[2];
41 	const void *addr[2];
42 	int expected_errno;
43 };
44 
45 /* (IPv4, IPv6) */
46 FIXTURE_VARIANT_ADD(bind_wildcard, v4_any_v6_any)
47 {
48 	.family = {AF_INET, AF_INET6},
49 	.addr = {&in4addr_any, &in6addr_any},
50 	.expected_errno = EADDRINUSE,
51 };
52 
53 FIXTURE_VARIANT_ADD(bind_wildcard, v4_any_v6_local)
54 {
55 	.family = {AF_INET, AF_INET6},
56 	.addr = {&in4addr_any, &in6addr_loopback},
57 	.expected_errno = 0,
58 };
59 
60 FIXTURE_VARIANT_ADD(bind_wildcard, v4_any_v6_v4mapped_any)
61 {
62 	.family = {AF_INET, AF_INET6},
63 	.addr = {&in4addr_any, &in6addr_v4mapped_any},
64 	.expected_errno = EADDRINUSE,
65 };
66 
67 FIXTURE_VARIANT_ADD(bind_wildcard, v4_any_v6_v4mapped_local)
68 {
69 	.family = {AF_INET, AF_INET6},
70 	.addr = {&in4addr_any, &in6addr_v4mapped_loopback},
71 	.expected_errno = EADDRINUSE,
72 };
73 
74 FIXTURE_VARIANT_ADD(bind_wildcard, v4_local_v6_any)
75 {
76 	.family = {AF_INET, AF_INET6},
77 	.addr = {&in4addr_loopback, &in6addr_any},
78 	.expected_errno = EADDRINUSE,
79 };
80 
81 FIXTURE_VARIANT_ADD(bind_wildcard, v4_local_v6_local)
82 {
83 	.family = {AF_INET, AF_INET6},
84 	.addr = {&in4addr_loopback, &in6addr_loopback},
85 	.expected_errno = 0,
86 };
87 
88 FIXTURE_VARIANT_ADD(bind_wildcard, v4_local_v6_v4mapped_any)
89 {
90 	.family = {AF_INET, AF_INET6},
91 	.addr = {&in4addr_loopback, &in6addr_v4mapped_any},
92 	.expected_errno = EADDRINUSE,
93 };
94 
95 FIXTURE_VARIANT_ADD(bind_wildcard, v4_local_v6_v4mapped_local)
96 {
97 	.family = {AF_INET, AF_INET6},
98 	.addr = {&in4addr_loopback, &in6addr_v4mapped_loopback},
99 	.expected_errno = EADDRINUSE,
100 };
101 
102 /* (IPv6, IPv4) */
103 FIXTURE_VARIANT_ADD(bind_wildcard, v6_any_v4_any)
104 {
105 	.family = {AF_INET6, AF_INET},
106 	.addr = {&in6addr_any, &in4addr_any},
107 	.expected_errno = EADDRINUSE,
108 };
109 
110 FIXTURE_VARIANT_ADD(bind_wildcard, v6_any_v4_local)
111 {
112 	.family = {AF_INET6, AF_INET},
113 	.addr = {&in6addr_any, &in4addr_loopback},
114 	.expected_errno = EADDRINUSE,
115 };
116 
117 FIXTURE_VARIANT_ADD(bind_wildcard, v6_local_v4_any)
118 {
119 	.family = {AF_INET6, AF_INET},
120 	.addr = {&in6addr_loopback, &in4addr_any},
121 	.expected_errno = 0,
122 };
123 
124 FIXTURE_VARIANT_ADD(bind_wildcard, v6_local_v4_local)
125 {
126 	.family = {AF_INET6, AF_INET},
127 	.addr = {&in6addr_loopback, &in4addr_loopback},
128 	.expected_errno = 0,
129 };
130 
131 FIXTURE_VARIANT_ADD(bind_wildcard, v6_v4mapped_any_v4_any)
132 {
133 	.family = {AF_INET6, AF_INET},
134 	.addr = {&in6addr_v4mapped_any, &in4addr_any},
135 	.expected_errno = EADDRINUSE,
136 };
137 
138 FIXTURE_VARIANT_ADD(bind_wildcard, v6_v4mapped_any_v4_local)
139 {
140 	.family = {AF_INET6, AF_INET},
141 	.addr = {&in6addr_v4mapped_any, &in4addr_loopback},
142 	.expected_errno = EADDRINUSE,
143 };
144 
145 FIXTURE_VARIANT_ADD(bind_wildcard, v6_v4mapped_local_v4_any)
146 {
147 	.family = {AF_INET6, AF_INET},
148 	.addr = {&in6addr_v4mapped_loopback, &in4addr_any},
149 	.expected_errno = EADDRINUSE,
150 };
151 
152 FIXTURE_VARIANT_ADD(bind_wildcard, v6_v4mapped_local_v4_local)
153 {
154 	.family = {AF_INET6, AF_INET},
155 	.addr = {&in6addr_v4mapped_loopback, &in4addr_loopback},
156 	.expected_errno = EADDRINUSE,
157 };
158 
159 static void setup_addr(FIXTURE_DATA(bind_wildcard) *self, int i,
160 		       int family, const void *addr_const)
161 {
162 	if (family == AF_INET) {
163 		struct sockaddr_in *addr4 = &self->addr[i].addr4;
164 		const __u32 *addr4_const = addr_const;
165 
166 		addr4->sin_family = AF_INET;
167 		addr4->sin_port = htons(0);
168 		addr4->sin_addr.s_addr = htonl(*addr4_const);
169 
170 		self->addrlen[i] = sizeof(struct sockaddr_in);
171 	} else {
172 		struct sockaddr_in6 *addr6 = &self->addr[i].addr6;
173 		const struct in6_addr *addr6_const = addr_const;
174 
175 		addr6->sin6_family = AF_INET6;
176 		addr6->sin6_port = htons(0);
177 		addr6->sin6_addr = *addr6_const;
178 
179 		self->addrlen[i] = sizeof(struct sockaddr_in6);
180 	}
181 }
182 
183 FIXTURE_SETUP(bind_wildcard)
184 {
185 	setup_addr(self, 0, variant->family[0], variant->addr[0]);
186 	setup_addr(self, 1, variant->family[1], variant->addr[1]);
187 }
188 
189 FIXTURE_TEARDOWN(bind_wildcard)
190 {
191 }
192 
193 void bind_sockets(struct __test_metadata *_metadata,
194 		  FIXTURE_DATA(bind_wildcard) *self,
195 		  int expected_errno,
196 		  struct sockaddr *addr1, socklen_t addrlen1,
197 		  struct sockaddr *addr2, socklen_t addrlen2)
198 {
199 	int fd[2];
200 	int ret;
201 
202 	fd[0] = socket(addr1->sa_family, SOCK_STREAM, 0);
203 	ASSERT_GT(fd[0], 0);
204 
205 	ret = bind(fd[0], addr1, addrlen1);
206 	ASSERT_EQ(ret, 0);
207 
208 	ret = getsockname(fd[0], addr1, &addrlen1);
209 	ASSERT_EQ(ret, 0);
210 
211 	((struct sockaddr_in *)addr2)->sin_port = ((struct sockaddr_in *)addr1)->sin_port;
212 
213 	fd[1] = socket(addr2->sa_family, SOCK_STREAM, 0);
214 	ASSERT_GT(fd[1], 0);
215 
216 	ret = bind(fd[1], addr2, addrlen2);
217 	if (expected_errno) {
218 		ASSERT_EQ(ret, -1);
219 		ASSERT_EQ(errno, expected_errno);
220 	} else {
221 		ASSERT_EQ(ret, 0);
222 	}
223 
224 	close(fd[1]);
225 	close(fd[0]);
226 }
227 
228 TEST_F(bind_wildcard, plain)
229 {
230 	bind_sockets(_metadata, self, variant->expected_errno,
231 		     &self->addr[0].addr, self->addrlen[0],
232 		     &self->addr[1].addr, self->addrlen[1]);
233 }
234 
235 TEST_HARNESS_MAIN
236