xref: /freebsd/tests/sys/netinet/so_reuseport_lb_test.c (revision 1dd66c6ac2c146f540b2ff825fbee442354aeee5)
1 /*-
2  * Copyright (c) 2018 The FreeBSD Foundation
3  *
4  * This software was developed by Mark Johnston under sponsorship from
5  * the FreeBSD Foundation.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are
9  * met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in
14  *    the documentation and/or other materials provided with the
15  *    distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29 
30 #include <sys/param.h>
31 #include <sys/event.h>
32 #include <sys/filio.h>
33 #include <sys/ioccom.h>
34 #include <sys/socket.h>
35 
36 #include <netinet/in.h>
37 #include <netinet/tcp.h>
38 
39 #include <err.h>
40 #include <errno.h>
41 #include <pthread.h>
42 #include <stdatomic.h>
43 #include <stdlib.h>
44 #include <unistd.h>
45 
46 #include <atf-c.h>
47 
48 /*
49  * Given an array of non-blocking listening sockets configured in a LB group
50  * for "addr", try connecting to "addr" in a loop and verify that connections
51  * are roughly balanced across the sockets.
52  */
53 static void
lb_simple_accept_loop(int domain,const struct sockaddr * addr,int sds[],size_t nsds,int nconns)54 lb_simple_accept_loop(int domain, const struct sockaddr *addr, int sds[],
55     size_t nsds, int nconns)
56 {
57 	size_t i;
58 	int *acceptcnt;
59 	int csd, error, excnt, sd;
60 	const struct linger lopt = { 1, 0 };
61 
62 	/*
63 	 * We expect each listening socket to accept roughly nconns/nsds
64 	 * connections, but allow for some error.
65 	 */
66 	excnt = nconns / nsds / 8;
67 	acceptcnt = calloc(nsds, sizeof(*acceptcnt));
68 	ATF_REQUIRE_MSG(acceptcnt != NULL, "calloc() failed: %s",
69 	    strerror(errno));
70 
71 	while (nconns-- > 0) {
72 		sd = socket(domain, SOCK_STREAM, 0);
73 		ATF_REQUIRE_MSG(sd >= 0, "socket() failed: %s",
74 		    strerror(errno));
75 
76 		error = connect(sd, addr, addr->sa_len);
77 		ATF_REQUIRE_MSG(error == 0, "connect() failed: %s",
78 		    strerror(errno));
79 
80 		error = setsockopt(sd, SOL_SOCKET, SO_LINGER, &lopt, sizeof(lopt));
81 		ATF_REQUIRE_MSG(error == 0, "Setting linger failed: %s",
82 		    strerror(errno));
83 
84 		/*
85 		 * Poll the listening sockets.
86 		 */
87 		do {
88 			for (i = 0; i < nsds; i++) {
89 				csd = accept(sds[i], NULL, NULL);
90 				if (csd < 0) {
91 					ATF_REQUIRE_MSG(errno == EWOULDBLOCK ||
92 					    errno == EAGAIN,
93 					    "accept() failed: %s",
94 					    strerror(errno));
95 					continue;
96 				}
97 
98 				error = close(csd);
99 				ATF_REQUIRE_MSG(error == 0,
100 				    "close() failed: %s", strerror(errno));
101 
102 				acceptcnt[i]++;
103 				break;
104 			}
105 		} while (i == nsds);
106 
107 		error = close(sd);
108 		ATF_REQUIRE_MSG(error == 0, "close() failed: %s",
109 		    strerror(errno));
110 	}
111 
112 	for (i = 0; i < nsds; i++)
113 		ATF_REQUIRE_MSG(acceptcnt[i] > excnt, "uneven balancing");
114 }
115 
116 static int
lb_listen_socket(int domain,int flags)117 lb_listen_socket(int domain, int flags)
118 {
119 	int one;
120 	int error, sd;
121 
122 	sd = socket(domain, SOCK_STREAM | flags, 0);
123 	ATF_REQUIRE_MSG(sd >= 0, "socket() failed: %s", strerror(errno));
124 
125 	one = 1;
126 	error = setsockopt(sd, SOL_SOCKET, SO_REUSEPORT_LB, &one, sizeof(one));
127 	ATF_REQUIRE_MSG(error == 0, "setsockopt(SO_REUSEPORT_LB) failed: %s",
128 	    strerror(errno));
129 
130 	return (sd);
131 }
132 
133 ATF_TC_WITHOUT_HEAD(basic_ipv4);
ATF_TC_BODY(basic_ipv4,tc)134 ATF_TC_BODY(basic_ipv4, tc)
135 {
136 	struct sockaddr_in addr;
137 	socklen_t slen;
138 	size_t i;
139 	const int nconns = 16384;
140 	int error, sds[16];
141 	uint16_t port;
142 
143 	sds[0] = lb_listen_socket(PF_INET, SOCK_NONBLOCK);
144 
145 	memset(&addr, 0, sizeof(addr));
146 	addr.sin_len = sizeof(addr);
147 	addr.sin_family = AF_INET;
148 	addr.sin_port = htons(0);
149 	addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
150 	error = bind(sds[0], (const struct sockaddr *)&addr, sizeof(addr));
151 	ATF_REQUIRE_MSG(error == 0, "bind() failed: %s", strerror(errno));
152 	error = listen(sds[0], 1);
153 	ATF_REQUIRE_MSG(error == 0, "listen() failed: %s", strerror(errno));
154 
155 	slen = sizeof(addr);
156 	error = getsockname(sds[0], (struct sockaddr *)&addr, &slen);
157 	ATF_REQUIRE_MSG(error == 0, "getsockname() failed: %s",
158 	    strerror(errno));
159 	ATF_REQUIRE_MSG(slen == sizeof(addr), "sockaddr size changed");
160 	port = addr.sin_port;
161 
162 	memset(&addr, 0, sizeof(addr));
163 	addr.sin_len = sizeof(addr);
164 	addr.sin_family = AF_INET;
165 	addr.sin_port = port;
166 	addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
167 	for (i = 1; i < nitems(sds); i++) {
168 		sds[i] = lb_listen_socket(PF_INET, SOCK_NONBLOCK);
169 
170 		error = bind(sds[i], (const struct sockaddr *)&addr,
171 		    sizeof(addr));
172 		ATF_REQUIRE_MSG(error == 0, "bind() failed: %s",
173 		    strerror(errno));
174 		error = listen(sds[i], 1);
175 		ATF_REQUIRE_MSG(error == 0, "listen() failed: %s",
176 		    strerror(errno));
177 	}
178 
179 	lb_simple_accept_loop(PF_INET, (struct sockaddr *)&addr, sds,
180 	    nitems(sds), nconns);
181 	for (i = 0; i < nitems(sds); i++) {
182 		error = close(sds[i]);
183 		ATF_REQUIRE_MSG(error == 0, "close() failed: %s",
184 		    strerror(errno));
185 	}
186 }
187 
188 ATF_TC_WITHOUT_HEAD(basic_ipv6);
ATF_TC_BODY(basic_ipv6,tc)189 ATF_TC_BODY(basic_ipv6, tc)
190 {
191 	const struct in6_addr loopback6 = IN6ADDR_LOOPBACK_INIT;
192 	struct sockaddr_in6 addr;
193 	socklen_t slen;
194 	size_t i;
195 	const int nconns = 16384;
196 	int error, sds[16];
197 	uint16_t port;
198 
199 	sds[0] = lb_listen_socket(PF_INET6, SOCK_NONBLOCK);
200 
201 	memset(&addr, 0, sizeof(addr));
202 	addr.sin6_len = sizeof(addr);
203 	addr.sin6_family = AF_INET6;
204 	addr.sin6_port = htons(0);
205 	addr.sin6_addr = loopback6;
206 	error = bind(sds[0], (const struct sockaddr *)&addr, sizeof(addr));
207 	ATF_REQUIRE_MSG(error == 0, "bind() failed: %s", strerror(errno));
208 	error = listen(sds[0], 1);
209 	ATF_REQUIRE_MSG(error == 0, "listen() failed: %s", strerror(errno));
210 
211 	slen = sizeof(addr);
212 	error = getsockname(sds[0], (struct sockaddr *)&addr, &slen);
213 	ATF_REQUIRE_MSG(error == 0, "getsockname() failed: %s",
214 	    strerror(errno));
215 	ATF_REQUIRE_MSG(slen == sizeof(addr), "sockaddr size changed");
216 	port = addr.sin6_port;
217 
218 	memset(&addr, 0, sizeof(addr));
219 	addr.sin6_len = sizeof(addr);
220 	addr.sin6_family = AF_INET6;
221 	addr.sin6_port = port;
222 	addr.sin6_addr = loopback6;
223 	for (i = 1; i < nitems(sds); i++) {
224 		sds[i] = lb_listen_socket(PF_INET6, SOCK_NONBLOCK);
225 
226 		error = bind(sds[i], (const struct sockaddr *)&addr,
227 		    sizeof(addr));
228 		ATF_REQUIRE_MSG(error == 0, "bind() failed: %s",
229 		    strerror(errno));
230 		error = listen(sds[i], 1);
231 		ATF_REQUIRE_MSG(error == 0, "listen() failed: %s",
232 		    strerror(errno));
233 	}
234 
235 	lb_simple_accept_loop(PF_INET6, (struct sockaddr *)&addr, sds,
236 	    nitems(sds), nconns);
237 	for (i = 0; i < nitems(sds); i++) {
238 		error = close(sds[i]);
239 		ATF_REQUIRE_MSG(error == 0, "close() failed: %s",
240 		    strerror(errno));
241 	}
242 }
243 
244 struct concurrent_add_softc {
245 	struct sockaddr_storage ss;
246 	int socks[128];
247 	int kq;
248 };
249 
250 static void *
listener(void * arg)251 listener(void *arg)
252 {
253 	for (struct concurrent_add_softc *sc = arg;;) {
254 		struct kevent kev;
255 		ssize_t n;
256 		int error, count, cs, s;
257 		uint8_t b;
258 
259 		count = kevent(sc->kq, NULL, 0, &kev, 1, NULL);
260 		ATF_REQUIRE_MSG(count == 1,
261 		    "kevent() failed: %s", strerror(errno));
262 
263 		s = (int)kev.ident;
264 		cs = accept(s, NULL, NULL);
265 		ATF_REQUIRE_MSG(cs >= 0,
266 		    "accept() failed: %s", strerror(errno));
267 
268 		b = 'M';
269 		n = write(cs, &b, sizeof(b));
270 		ATF_REQUIRE_MSG(n >= 0, "write() failed: %s", strerror(errno));
271 		ATF_REQUIRE(n == 1);
272 
273 		error = close(cs);
274 		ATF_REQUIRE_MSG(error == 0 || errno == ECONNRESET,
275 		    "close() failed: %s", strerror(errno));
276 	}
277 }
278 
279 static void *
connector(void * arg)280 connector(void *arg)
281 {
282 	for (struct concurrent_add_softc *sc = arg;;) {
283 		ssize_t n;
284 		int error, s;
285 		uint8_t b;
286 
287 		s = socket(sc->ss.ss_family, SOCK_STREAM, 0);
288 		ATF_REQUIRE_MSG(s >= 0, "socket() failed: %s", strerror(errno));
289 
290 		error = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (int[]){1},
291 		    sizeof(int));
292 
293 		error = connect(s, (struct sockaddr *)&sc->ss, sc->ss.ss_len);
294 		ATF_REQUIRE_MSG(error == 0, "connect() failed: %s",
295 		    strerror(errno));
296 
297 		n = read(s, &b, sizeof(b));
298 		ATF_REQUIRE_MSG(n >= 0, "read() failed: %s",
299 		    strerror(errno));
300 		ATF_REQUIRE(n == 1);
301 		ATF_REQUIRE(b == 'M');
302 		error = close(s);
303 		ATF_REQUIRE_MSG(error == 0,
304 		    "close() failed: %s", strerror(errno));
305 	}
306 }
307 
308 /*
309  * Run three threads.  One accepts connections from listening sockets on a
310  * kqueue, while the other makes connections.  The third thread slowly adds
311  * sockets to the LB group.  This is meant to help flush out race conditions.
312  */
313 ATF_TC_WITHOUT_HEAD(concurrent_add);
ATF_TC_BODY(concurrent_add,tc)314 ATF_TC_BODY(concurrent_add, tc)
315 {
316 	struct concurrent_add_softc sc;
317 	struct sockaddr_in *sin;
318 	pthread_t threads[4];
319 	int error;
320 
321 	sc.kq = kqueue();
322 	ATF_REQUIRE_MSG(sc.kq >= 0, "kqueue() failed: %s", strerror(errno));
323 
324 	error = pthread_create(&threads[0], NULL, listener, &sc);
325 	ATF_REQUIRE_MSG(error == 0, "pthread_create() failed: %s",
326 	    strerror(error));
327 
328 	sin = (struct sockaddr_in *)&sc.ss;
329 	memset(sin, 0, sizeof(*sin));
330 	sin->sin_len = sizeof(*sin);
331 	sin->sin_family = AF_INET;
332 	sin->sin_port = htons(0);
333 	sin->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
334 
335 	for (size_t i = 0; i < nitems(sc.socks); i++) {
336 		struct kevent kev;
337 		int s;
338 
339 		sc.socks[i] = s = socket(AF_INET, SOCK_STREAM, 0);
340 		ATF_REQUIRE_MSG(s >= 0, "socket() failed: %s", strerror(errno));
341 
342 		error = setsockopt(s, SOL_SOCKET, SO_REUSEPORT_LB, (int[]){1},
343 		    sizeof(int));
344 		ATF_REQUIRE_MSG(error == 0,
345 		    "setsockopt(SO_REUSEPORT_LB) failed: %s", strerror(errno));
346 
347 		error = bind(s, (struct sockaddr *)sin, sizeof(*sin));
348 		ATF_REQUIRE_MSG(error == 0, "bind() failed: %s",
349 		    strerror(errno));
350 
351 		error = listen(s, 5);
352 		ATF_REQUIRE_MSG(error == 0, "listen() failed: %s",
353 		    strerror(errno));
354 
355 		EV_SET(&kev, s, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, 0);
356 		error = kevent(sc.kq, &kev, 1, NULL, 0, NULL);
357 		ATF_REQUIRE_MSG(error == 0, "kevent() failed: %s",
358 		    strerror(errno));
359 
360 		if (i == 0) {
361 			socklen_t slen = sizeof(sc.ss);
362 
363 			error = getsockname(sc.socks[i],
364 			    (struct sockaddr *)&sc.ss, &slen);
365 			ATF_REQUIRE_MSG(error == 0, "getsockname() failed: %s",
366 			    strerror(errno));
367 			ATF_REQUIRE(sc.ss.ss_family == AF_INET);
368 
369 			for (size_t j = 1; j < nitems(threads); j++) {
370 				error = pthread_create(&threads[j], NULL,
371 				    connector, &sc);
372 				ATF_REQUIRE_MSG(error == 0,
373 				    "pthread_create() failed: %s",
374 				    strerror(error));
375 			}
376 		}
377 
378 		usleep(20000);
379 	}
380 
381 	for (size_t j = nitems(threads); j > 0; j--) {
382 		ATF_REQUIRE(pthread_cancel(threads[j - 1]) == 0);
383 		ATF_REQUIRE(pthread_join(threads[j - 1], NULL) == 0);
384 	}
385 }
386 
387 /*
388  * Try calling listen(2) twice on a socket with SO_REUSEPORT_LB set.
389  */
390 ATF_TC_WITHOUT_HEAD(double_listen_ipv4);
ATF_TC_BODY(double_listen_ipv4,tc)391 ATF_TC_BODY(double_listen_ipv4, tc)
392 {
393 	struct sockaddr_in sin;
394 	int error, s;
395 
396 	s = lb_listen_socket(PF_INET, 0);
397 
398 	memset(&sin, 0, sizeof(sin));
399 	sin.sin_len = sizeof(sin);
400 	sin.sin_family = AF_INET;
401 	sin.sin_port = htons(0);
402 	sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
403 	error = bind(s, (struct sockaddr *)&sin, sizeof(sin));
404 	ATF_REQUIRE_MSG(error == 0, "bind() failed: %s", strerror(errno));
405 
406 	error = listen(s, 1);
407 	ATF_REQUIRE_MSG(error == 0, "listen() failed: %s", strerror(errno));
408 	error = listen(s, 2);
409 	ATF_REQUIRE_MSG(error == 0, "listen() failed: %s", strerror(errno));
410 
411 	error = close(s);
412 	ATF_REQUIRE_MSG(error == 0, "close() failed: %s", strerror(errno));
413 }
414 
415 /*
416  * Try calling listen(2) twice on a socket with SO_REUSEPORT_LB set.
417  */
418 ATF_TC_WITHOUT_HEAD(double_listen_ipv6);
ATF_TC_BODY(double_listen_ipv6,tc)419 ATF_TC_BODY(double_listen_ipv6, tc)
420 {
421 	struct sockaddr_in6 sin6;
422 	int error, s;
423 
424 	s = lb_listen_socket(PF_INET6, 0);
425 
426 	memset(&sin6, 0, sizeof(sin6));
427 	sin6.sin6_len = sizeof(sin6);
428 	sin6.sin6_family = AF_INET6;
429 	sin6.sin6_port = htons(0);
430 	sin6.sin6_addr = in6addr_loopback;
431 	error = bind(s, (struct sockaddr *)&sin6, sizeof(sin6));
432 	ATF_REQUIRE_MSG(error == 0, "bind() failed: %s", strerror(errno));
433 
434 	error = listen(s, 1);
435 	ATF_REQUIRE_MSG(error == 0, "listen() failed: %s", strerror(errno));
436 	error = listen(s, 2);
437 	ATF_REQUIRE_MSG(error == 0, "listen() failed: %s", strerror(errno));
438 
439 	error = close(s);
440 	ATF_REQUIRE_MSG(error == 0, "close() failed: %s", strerror(errno));
441 }
442 
443 /*
444  * Try binding many sockets to the same lbgroup without calling listen(2) on
445  * them.
446  */
447 ATF_TC_WITHOUT_HEAD(bind_without_listen);
ATF_TC_BODY(bind_without_listen,tc)448 ATF_TC_BODY(bind_without_listen, tc)
449 {
450 	const int nsockets = 100;
451 	struct sockaddr_in sin;
452 	socklen_t socklen;
453 	int error, s, s2[nsockets];
454 
455 	s = lb_listen_socket(PF_INET, 0);
456 
457 	memset(&sin, 0, sizeof(sin));
458 	sin.sin_len = sizeof(sin);
459 	sin.sin_family = AF_INET;
460 	sin.sin_port = htons(0);
461 	sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
462 	error = bind(s, (struct sockaddr *)&sin, sizeof(sin));
463 	ATF_REQUIRE_MSG(error == 0, "bind() failed: %s", strerror(errno));
464 
465 	socklen = sizeof(sin);
466 	error = getsockname(s, (struct sockaddr *)&sin, &socklen);
467 	ATF_REQUIRE_MSG(error == 0, "getsockname() failed: %s",
468 	    strerror(errno));
469 
470 	for (int i = 0; i < nsockets; i++) {
471 		s2[i] = lb_listen_socket(PF_INET, 0);
472 		error = bind(s2[i], (struct sockaddr *)&sin, sizeof(sin));
473 		ATF_REQUIRE_MSG(error == 0, "bind() failed: %s", strerror(errno));
474 	}
475 	for (int i = 0; i < nsockets; i++) {
476 		error = listen(s2[i], 1);
477 		ATF_REQUIRE_MSG(error == 0, "listen() failed: %s", strerror(errno));
478 	}
479 	for (int i = 0; i < nsockets; i++) {
480 		error = close(s2[i]);
481 		ATF_REQUIRE_MSG(error == 0, "close() failed: %s", strerror(errno));
482 	}
483 
484 	error = close(s);
485 	ATF_REQUIRE_MSG(error == 0, "close() failed: %s", strerror(errno));
486 }
487 
488 /*
489  * Check that SO_REUSEPORT_LB doesn't mess with connect(2).
490  * Two sockets:
491  * 1) auxiliary peer socket 'p', where we connect to
492  * 2) test socket 's', that sets SO_REUSEPORT_LB and then connect(2)s to 'p'
493  */
494 ATF_TC_WITHOUT_HEAD(connect_not_bound);
ATF_TC_BODY(connect_not_bound,tc)495 ATF_TC_BODY(connect_not_bound, tc)
496 {
497 	struct sockaddr_in sin = {
498 		.sin_family = AF_INET,
499 		.sin_len = sizeof(sin),
500 		.sin_addr = { htonl(INADDR_LOOPBACK) },
501 	};
502 	socklen_t slen = sizeof(struct sockaddr_in);
503 	int p, s, rv;
504 
505 	ATF_REQUIRE((p = socket(PF_INET, SOCK_STREAM, 0)) > 0);
506 	ATF_REQUIRE(bind(p, (struct sockaddr *)&sin, sizeof(sin)) == 0);
507 	ATF_REQUIRE(listen(p, 1) == 0);
508 	ATF_REQUIRE(getsockname(p, (struct sockaddr *)&sin, &slen) == 0);
509 
510 	s = lb_listen_socket(PF_INET, 0);
511 	rv = connect(s, (struct sockaddr *)&sin, sizeof(sin));
512 	ATF_REQUIRE_MSG(rv == -1 && errno == EOPNOTSUPP,
513 	    "Expected EOPNOTSUPP on connect(2) not met. Got %d, errno %d",
514 	    rv, errno);
515 	rv = sendto(s, "test", 4, 0, (struct sockaddr *)&sin,
516 	    sizeof(sin));
517 	ATF_REQUIRE_MSG(rv == -1 && errno == EOPNOTSUPP,
518 	    "Expected EOPNOTSUPP on sendto(2) not met. Got %d, errno %d",
519 	    rv, errno);
520 
521 	close(p);
522 	close(s);
523 }
524 
525 /*
526  * Same as above, but we also bind(2) between setsockopt(2) of SO_REUSEPORT_LB
527  * and the connect(2).
528  */
529 ATF_TC_WITHOUT_HEAD(connect_bound);
ATF_TC_BODY(connect_bound,tc)530 ATF_TC_BODY(connect_bound, tc)
531 {
532 	struct sockaddr_in sin = {
533 		.sin_family = AF_INET,
534 		.sin_len = sizeof(sin),
535 		.sin_addr = { htonl(INADDR_LOOPBACK) },
536 	};
537 	socklen_t slen = sizeof(struct sockaddr_in);
538 	int p, s, rv;
539 
540 	ATF_REQUIRE((p = socket(PF_INET, SOCK_STREAM, 0)) > 0);
541 	ATF_REQUIRE(bind(p, (struct sockaddr *)&sin, sizeof(sin)) == 0);
542 	ATF_REQUIRE(listen(p, 1) == 0);
543 
544 	s = lb_listen_socket(PF_INET, 0);
545 	ATF_REQUIRE(bind(s, (struct sockaddr *)&sin, sizeof(sin)) == 0);
546 	ATF_REQUIRE(getsockname(p, (struct sockaddr *)&sin, &slen) == 0);
547 	rv = connect(s, (struct sockaddr *)&sin, sizeof(sin));
548 	ATF_REQUIRE_MSG(rv == -1 && errno == EOPNOTSUPP,
549 	    "Expected EOPNOTSUPP on connect(2) not met. Got %d, errno %d",
550 	    rv, errno);
551 	rv = sendto(s, "test", 4, 0, (struct sockaddr *)&sin,
552 	    sizeof(sin));
553 	ATF_REQUIRE_MSG(rv == -1 && errno == EOPNOTSUPP,
554 	    "Expected EOPNOTSUPP on sendto(2) not met. Got %d, errno %d",
555 	    rv, errno);
556 
557 	close(p);
558 	close(s);
559 }
560 
561 /*
562  * The kernel erroneously permits calling connect() on a UDP socket with
563  * SO_REUSEPORT_LB set.  Verify that packets sent to the bound address are
564  * dropped unless they come from the connected address.
565  */
566 ATF_TC_WITHOUT_HEAD(connect_udp);
ATF_TC_BODY(connect_udp,tc)567 ATF_TC_BODY(connect_udp, tc)
568 {
569 	struct sockaddr_in sin = {
570 		.sin_family = AF_INET,
571 		.sin_len = sizeof(sin),
572 		.sin_addr = { htonl(INADDR_LOOPBACK) },
573 	};
574 	ssize_t n;
575 	int error, len, s1, s2, s3;
576 	char ch;
577 
578 	s1 = socket(PF_INET, SOCK_DGRAM, 0);
579 	ATF_REQUIRE(s1 >= 0);
580 	s2 = socket(PF_INET, SOCK_DGRAM, 0);
581 	ATF_REQUIRE(s2 >= 0);
582 	s3 = socket(PF_INET, SOCK_DGRAM, 0);
583 	ATF_REQUIRE(s3 >= 0);
584 
585 	error = setsockopt(s1, SOL_SOCKET, SO_REUSEPORT_LB, (int[]){1},
586 	    sizeof(int));
587 	ATF_REQUIRE_MSG(error == 0,
588 	    "setsockopt(SO_REUSEPORT_LB) failed: %s", strerror(errno));
589 	error = bind(s1, (struct sockaddr *)&sin, sizeof(sin));
590 	ATF_REQUIRE_MSG(error == 0, "bind() failed: %s", strerror(errno));
591 
592 	error = bind(s2, (struct sockaddr *)&sin, sizeof(sin));
593 	ATF_REQUIRE_MSG(error == 0, "bind() failed: %s", strerror(errno));
594 
595 	error = bind(s3, (struct sockaddr *)&sin, sizeof(sin));
596 	ATF_REQUIRE_MSG(error == 0, "bind() failed: %s", strerror(errno));
597 
598 	/* Connect to an address not owned by s2. */
599 	error = getsockname(s3, (struct sockaddr *)&sin,
600 	    (socklen_t[]){sizeof(sin)});
601 	ATF_REQUIRE(error == 0);
602 	error = connect(s1, (struct sockaddr *)&sin, sizeof(sin));
603 	ATF_REQUIRE_MSG(error == 0, "connect() failed: %s", strerror(errno));
604 
605 	/* Try to send a packet to s1 from s2. */
606 	error = getsockname(s1, (struct sockaddr *)&sin,
607 	    (socklen_t[]){sizeof(sin)});
608 	ATF_REQUIRE(error == 0);
609 
610 	ch = 42;
611 	n = sendto(s2, &ch, sizeof(ch), 0, (struct sockaddr *)&sin,
612 	    sizeof(sin));
613 	ATF_REQUIRE(n == 1);
614 
615 	/* Give the packet some time to arrive. */
616 	usleep(100000);
617 
618 	/* s1 is connected to s3 and shouldn't receive from s2. */
619 	error = ioctl(s1, FIONREAD, &len);
620 	ATF_REQUIRE(error == 0);
621 	ATF_REQUIRE_MSG(len == 0, "unexpected data available");
622 
623 	/* ... but s3 can of course send to s1. */
624 	n = sendto(s3, &ch, sizeof(ch), 0, (struct sockaddr *)&sin,
625 	    sizeof(sin));
626 	ATF_REQUIRE(n == 1);
627 	usleep(100000);
628 	error = ioctl(s1, FIONREAD, &len);
629 	ATF_REQUIRE(error == 0);
630 	ATF_REQUIRE_MSG(len == 1, "expected data available");
631 }
632 
633 /*
634  * The kernel erroneously permits calling connect() on a UDP socket with
635  * SO_REUSEPORT_LB set.  Verify that packets sent to the bound address are
636  * dropped unless they come from the connected address.
637  */
638 ATF_TC_WITHOUT_HEAD(connect_udp6);
ATF_TC_BODY(connect_udp6,tc)639 ATF_TC_BODY(connect_udp6, tc)
640 {
641 	struct sockaddr_in6 sin6 = {
642 		.sin6_family = AF_INET6,
643 		.sin6_len = sizeof(sin6),
644 		.sin6_addr = IN6ADDR_LOOPBACK_INIT,
645 	};
646 	ssize_t n;
647 	int error, len, s1, s2, s3;
648 	char ch;
649 
650 	s1 = socket(PF_INET6, SOCK_DGRAM, 0);
651 	ATF_REQUIRE(s1 >= 0);
652 	s2 = socket(PF_INET6, SOCK_DGRAM, 0);
653 	ATF_REQUIRE(s2 >= 0);
654 	s3 = socket(PF_INET6, SOCK_DGRAM, 0);
655 	ATF_REQUIRE(s3 >= 0);
656 
657 	error = setsockopt(s1, SOL_SOCKET, SO_REUSEPORT_LB, (int[]){1},
658 	    sizeof(int));
659 	ATF_REQUIRE_MSG(error == 0,
660 	    "setsockopt(SO_REUSEPORT_LB) failed: %s", strerror(errno));
661 	error = bind(s1, (struct sockaddr *)&sin6, sizeof(sin6));
662 	ATF_REQUIRE_MSG(error == 0, "bind() failed: %s", strerror(errno));
663 
664 	error = bind(s2, (struct sockaddr *)&sin6, sizeof(sin6));
665 	ATF_REQUIRE_MSG(error == 0, "bind() failed: %s", strerror(errno));
666 
667 	error = bind(s3, (struct sockaddr *)&sin6, sizeof(sin6));
668 	ATF_REQUIRE_MSG(error == 0, "bind() failed: %s", strerror(errno));
669 
670 	/* Connect to an address not owned by s2. */
671 	error = getsockname(s3, (struct sockaddr *)&sin6,
672 	    (socklen_t[]){sizeof(sin6)});
673 	ATF_REQUIRE(error == 0);
674 	error = connect(s1, (struct sockaddr *)&sin6, sizeof(sin6));
675 	ATF_REQUIRE_MSG(error == 0, "connect() failed: %s", strerror(errno));
676 
677 	/* Try to send a packet to s1 from s2. */
678 	error = getsockname(s1, (struct sockaddr *)&sin6,
679 	    (socklen_t[]){sizeof(sin6)});
680 	ATF_REQUIRE(error == 0);
681 
682 	ch = 42;
683 	n = sendto(s2, &ch, sizeof(ch), 0, (struct sockaddr *)&sin6,
684 	    sizeof(sin6));
685 	ATF_REQUIRE(n == 1);
686 
687 	/* Give the packet some time to arrive. */
688 	usleep(100000);
689 
690 	/* s1 is connected to s3 and shouldn't receive from s2. */
691 	error = ioctl(s1, FIONREAD, &len);
692 	ATF_REQUIRE(error == 0);
693 	ATF_REQUIRE_MSG(len == 0, "unexpected data available");
694 
695 	/* ... but s3 can of course send to s1. */
696 	n = sendto(s3, &ch, sizeof(ch), 0, (struct sockaddr *)&sin6,
697 	    sizeof(sin6));
698 	ATF_REQUIRE(n == 1);
699 	usleep(100000);
700 	error = ioctl(s1, FIONREAD, &len);
701 	ATF_REQUIRE(error == 0);
702 	ATF_REQUIRE_MSG(len == 1, "expected data available");
703 }
704 
ATF_TP_ADD_TCS(tp)705 ATF_TP_ADD_TCS(tp)
706 {
707 	ATF_TP_ADD_TC(tp, basic_ipv4);
708 	ATF_TP_ADD_TC(tp, basic_ipv6);
709 	ATF_TP_ADD_TC(tp, concurrent_add);
710 	ATF_TP_ADD_TC(tp, double_listen_ipv4);
711 	ATF_TP_ADD_TC(tp, double_listen_ipv6);
712 	ATF_TP_ADD_TC(tp, bind_without_listen);
713 	ATF_TP_ADD_TC(tp, connect_not_bound);
714 	ATF_TP_ADD_TC(tp, connect_bound);
715 	ATF_TP_ADD_TC(tp, connect_udp);
716 	ATF_TP_ADD_TC(tp, connect_udp6);
717 
718 	return (atf_no_error());
719 }
720