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