xref: /freebsd/tests/sys/netinet/fibs_multibind_test.c (revision 328110da2661a8841f12000b99fea27ceacdd5b2)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2024-2025 Stormshield
5  */
6 
7 #include <sys/types.h>
8 #include <sys/ioctl.h>
9 #include <sys/socket.h>
10 #include <sys/sysctl.h>
11 
12 #include <netinet/in.h>
13 #include <netinet/ip.h>
14 #include <netinet/ip6.h>
15 #include <netinet/ip_icmp.h>
16 #include <netinet/icmp6.h>
17 
18 #include <errno.h>
19 #include <fcntl.h>
20 #include <pwd.h>
21 #include <stdio.h>
22 #include <string.h>
23 
24 #include <atf-c.h>
25 
26 #define	MAKETEST_TCP(name)			\
27 ATF_TC_WITHOUT_HEAD(name ## _tcp);		\
28 ATF_TC_BODY(name ## _tcp, tc)			\
29 {						\
30 	name(PF_INET, SOCK_STREAM, tc);		\
31 }						\
32 ATF_TC_WITHOUT_HEAD(name ## _tcp6);		\
33 ATF_TC_BODY(name ## _tcp6, tc)			\
34 {						\
35 	name(PF_INET6, SOCK_STREAM, tc);	\
36 }
37 #define	MAKETEST_UDP(name)			\
38 ATF_TC_WITHOUT_HEAD(name ## _udp);		\
39 ATF_TC_BODY(name ## _udp, tc)			\
40 {						\
41 	name(PF_INET, SOCK_DGRAM, tc);		\
42 }						\
43 ATF_TC_WITHOUT_HEAD(name ## _udp6);		\
44 ATF_TC_BODY(name ## _udp6, tc)			\
45 {						\
46 	name(PF_INET6, SOCK_DGRAM, tc);		\
47 }
48 #define	MAKETEST_RAW(name)			\
49 ATF_TC(name ## _raw);				\
50 ATF_TC_HEAD(name ## _raw, tc)			\
51 {						\
52 	atf_tc_set_md_var(tc, "require.user",	\
53 	    "root");				\
54 }						\
55 ATF_TC_BODY(name ## _raw, tc)			\
56 {						\
57 	name(PF_INET, SOCK_RAW, tc);		\
58 }						\
59 ATF_TC(name ## _raw6);				\
60 ATF_TC_HEAD(name ## _raw6, tc)			\
61 {						\
62 	atf_tc_set_md_var(tc, "require.user",	\
63 	    "root");				\
64 }						\
65 ATF_TC_BODY(name ## _raw6, tc)			\
66 {						\
67 	name(PF_INET6, SOCK_RAW, tc);		\
68 }
69 
70 #define	MAKETEST(name)				\
71 	MAKETEST_TCP(name)			\
72 	MAKETEST_UDP(name)
73 
74 #define	LISTTEST_TCP(name)			\
75 	ATF_TP_ADD_TC(tp, name ## _tcp);	\
76 	ATF_TP_ADD_TC(tp, name ## _tcp6);
77 #define	LISTTEST_UDP(name)			\
78 	ATF_TP_ADD_TC(tp, name ## _udp);	\
79 	ATF_TP_ADD_TC(tp, name ## _udp6);
80 #define	LISTTEST_RAW(name)			\
81 	ATF_TP_ADD_TC(tp, name ## _raw);	\
82 	ATF_TP_ADD_TC(tp, name ## _raw6);
83 #define	LISTTEST(name)				\
84 	LISTTEST_TCP(name)			\
85 	LISTTEST_UDP(name)
86 
87 static void
88 checked_close(int s)
89 {
90 	int error;
91 
92 	error = close(s);
93 	ATF_REQUIRE_MSG(error == 0, "close failed: %s", strerror(errno));
94 }
95 
96 static int
97 mksockp(int domain, int type, int fib, int proto)
98 {
99 	int error, s;
100 
101 	s = socket(domain, type, proto);
102 	ATF_REQUIRE(s != -1);
103 	error = setsockopt(s, SOL_SOCKET, SO_SETFIB, &fib, sizeof(fib));
104 	ATF_REQUIRE_MSG(error == 0, "setsockopt failed: %s", strerror(errno));
105 
106 	return (s);
107 }
108 
109 static int
110 mksock(int domain, int type, int fib)
111 {
112 	return (mksockp(domain, type, fib, 0));
113 }
114 
115 static void
116 require_fibs_multibind(int socktype, int minfibs)
117 {
118 	const char *sysctl;
119 	size_t sz;
120 	int error, fibs, multibind;
121 
122 	fibs = 0;
123 	sz = sizeof(fibs);
124 	error = sysctlbyname("net.fibs", &fibs, &sz, NULL, 0);
125 	ATF_REQUIRE_MSG(error == 0, "sysctlbyname failed: %s", strerror(errno));
126 	ATF_REQUIRE_MSG(fibs >= 1, "strange FIB count %d", fibs);
127 	if (fibs == 1)
128 		atf_tc_skip("multiple FIBs not enabled");
129 	if (fibs < minfibs)
130 		atf_tc_skip("not enough FIBs, need %d", minfibs);
131 
132 	switch (socktype) {
133 	case SOCK_STREAM:
134 		sysctl = "net.inet.tcp.bind_all_fibs";
135 		break;
136 	case SOCK_DGRAM:
137 		sysctl = "net.inet.udp.bind_all_fibs";
138 		break;
139 	case SOCK_RAW:
140 		sysctl = "net.inet.raw.bind_all_fibs";
141 		break;
142 	default:
143 		atf_tc_fail("unknown socket type %d", socktype);
144 		break;
145 	}
146 
147 	multibind = -1;
148 	sz = sizeof(multibind);
149 	error = sysctlbyname(sysctl, &multibind, &sz, NULL, 0);
150 	ATF_REQUIRE_MSG(error == 0, "sysctlbyname failed: %s", strerror(errno));
151 	if (multibind != 0)
152 		atf_tc_skip("FIB multibind not configured (%s)", sysctl);
153 }
154 
155 /*
156  * Make sure that different users can't bind to the same port from different
157  * FIBs.
158  */
159 static void
160 multibind_different_user(int domain, int type, const atf_tc_t *tc)
161 {
162 	struct sockaddr_storage ss;
163 	struct passwd *passwd;
164 	const char *user;
165 	socklen_t sslen;
166 	int error, s[2];
167 
168 	if (geteuid() != 0)
169 		atf_tc_skip("need root privileges");
170 	if (!atf_tc_has_config_var(tc, "unprivileged_user"))
171 		atf_tc_skip("unprivileged_user not set");
172 
173 	ATF_REQUIRE(domain == PF_INET || domain == PF_INET6);
174 	sslen = domain == PF_INET ? sizeof(struct sockaddr_in) :
175 	    sizeof(struct sockaddr_in6);
176 
177 	require_fibs_multibind(type, 2);
178 
179 	s[0] = mksock(domain, type, 0);
180 
181 	memset(&ss, 0, sizeof(ss));
182 	ss.ss_family = domain;
183 	ss.ss_len = sslen;
184 	error = bind(s[0], (struct sockaddr *)&ss, sslen);
185 	ATF_REQUIRE_MSG(error == 0, "bind failed: %s", strerror(errno));
186 
187 	error = getsockname(s[0], (struct sockaddr *)&ss, &sslen);
188 	ATF_REQUIRE_MSG(error == 0, "getsockname failed: %s", strerror(errno));
189 
190 	/*
191 	 * Create a second socket in a different FIB, and bind it to the same
192 	 * address/port tuple.  This should succeed if done as the same user as
193 	 * the first socket, and should fail otherwise.
194 	 */
195 	s[1] = mksock(domain, type, 1);
196 	error = bind(s[1], (struct sockaddr *)&ss, sslen);
197 	ATF_REQUIRE_MSG(error == 0, "bind failed: %s", strerror(errno));
198 	ATF_REQUIRE_MSG(close(s[1]) == 0, "close failed: %s", strerror(errno));
199 
200 	user = atf_tc_get_config_var(tc, "unprivileged_user");
201 	passwd = getpwnam(user);
202 	ATF_REQUIRE(passwd != NULL);
203 	error = seteuid(passwd->pw_uid);
204 	ATF_REQUIRE_MSG(error == 0, "seteuid failed: %s", strerror(errno));
205 
206 	/* Repeat the bind as a different user. */
207 	s[1] = mksock(domain, type, 1);
208 	error = bind(s[1], (struct sockaddr *)&ss, sslen);
209 	ATF_REQUIRE_ERRNO(EADDRINUSE, error == -1);
210 	ATF_REQUIRE_MSG(close(s[1]) == 0, "close failed: %s", strerror(errno));
211 }
212 MAKETEST(multibind_different_user);
213 
214 /*
215  * Verify that a listening socket only accepts connections originating from the
216  * same FIB.
217  */
218 static void
219 per_fib_listening_socket(int domain, int type, const atf_tc_t *tc __unused)
220 {
221 	struct sockaddr_storage ss;
222 	socklen_t sslen;
223 	int cs1, cs2, error, fib1, fib2, ls1, ls2, ns;
224 
225 	ATF_REQUIRE(type == SOCK_STREAM);
226 	ATF_REQUIRE(domain == PF_INET || domain == PF_INET6);
227 	require_fibs_multibind(type, 2);
228 
229 	fib1 = 0;
230 	fib2 = 1;
231 
232 	ls1 = mksock(domain, type, fib1);
233 	ls2 = mksock(domain, type, fib2);
234 
235 	sslen = domain == PF_INET ? sizeof(struct sockaddr_in) :
236 	    sizeof(struct sockaddr_in6);
237 
238 	memset(&ss, 0, sizeof(ss));
239 	ss.ss_family = domain;
240 	ss.ss_len = sslen;
241 	error = bind(ls1, (struct sockaddr *)&ss, sslen);
242 	ATF_REQUIRE_MSG(error == 0, "bind failed: %s", strerror(errno));
243 
244 	error = getsockname(ls1, (struct sockaddr *)&ss, &sslen);
245 	ATF_REQUIRE_MSG(error == 0, "getsockname failed: %s", strerror(errno));
246 
247 	error = listen(ls1, 5);
248 	ATF_REQUIRE_MSG(error == 0, "listen failed: %s", strerror(errno));
249 
250 	cs1 = mksock(domain, type, fib1);
251 	cs2 = mksock(domain, type, fib2);
252 
253 	/*
254 	 * Make sure we can connect from the same FIB.
255 	 */
256 	error = connect(cs1, (struct sockaddr *)&ss, sslen);
257 	ATF_REQUIRE_MSG(error == 0, "connect failed: %s", strerror(errno));
258 	ns = accept(ls1, NULL, NULL);
259 	ATF_REQUIRE_MSG(ns != -1, "accept failed: %s", strerror(errno));
260 	checked_close(ns);
261 	checked_close(cs1);
262 	cs1 = mksock(domain, type, fib1);
263 
264 	/*
265 	 * ... but not from a different FIB.
266 	 */
267 	error = connect(cs2, (struct sockaddr *)&ss, sslen);
268 	ATF_REQUIRE_MSG(error == -1, "connect succeeded unexpectedly");
269 	ATF_REQUIRE_MSG(errno == ECONNREFUSED, "unexpected error %d", errno);
270 	checked_close(cs2);
271 	cs2 = mksock(domain, type, fib2);
272 
273 	/*
274 	 * ... but if there are multiple listening sockets, we always connect to
275 	 * the same FIB.
276 	 */
277 	error = bind(ls2, (struct sockaddr *)&ss, sslen);
278 	ATF_REQUIRE_MSG(error == 0, "bind failed: %s", strerror(errno));
279 	error = listen(ls2, 5);
280 	ATF_REQUIRE_MSG(error == 0, "listen failed: %s", strerror(errno));
281 
282 	for (int i = 0; i < 10; i++) {
283 		error = connect(cs1, (struct sockaddr *)&ss, sslen);
284 		ATF_REQUIRE_MSG(error == 0, "connect failed: %s",
285 		    strerror(errno));
286 		ns = accept(ls1, NULL, NULL);
287 		ATF_REQUIRE_MSG(ns != -1, "accept failed: %s", strerror(errno));
288 
289 		checked_close(ns);
290 		checked_close(cs1);
291 		cs1 = mksock(domain, type, fib1);
292 	}
293 	for (int i = 0; i < 10; i++) {
294 		error = connect(cs2, (struct sockaddr *)&ss, sslen);
295 		ATF_REQUIRE_MSG(error == 0, "connect failed: %s",
296 		    strerror(errno));
297 		ns = accept(ls2, NULL, NULL);
298 		ATF_REQUIRE_MSG(ns != -1, "accept failed: %s", strerror(errno));
299 
300 		checked_close(ns);
301 		checked_close(cs2);
302 		cs2 = mksock(domain, type, fib2);
303 	}
304 
305 	/*
306 	 * ... and if we close one of the listening sockets, we're back to only
307 	 * being able to connect from the same FIB.
308 	 */
309 	checked_close(ls1);
310 	error = connect(cs1, (struct sockaddr *)&ss, sslen);
311 	ATF_REQUIRE_MSG(error == -1, "connect succeeded unexpectedly");
312 	ATF_REQUIRE_MSG(errno == ECONNREFUSED, "unexpected error %d", errno);
313 	checked_close(cs1);
314 
315 	error = connect(cs2, (struct sockaddr *)&ss, sslen);
316 	ATF_REQUIRE_MSG(error == 0, "connect failed: %s", strerror(errno));
317 	ns = accept(ls2, NULL, NULL);
318 	ATF_REQUIRE_MSG(ns != -1, "accept failed: %s", strerror(errno));
319 	checked_close(ns);
320 	checked_close(cs2);
321 	checked_close(ls2);
322 }
323 MAKETEST_TCP(per_fib_listening_socket);
324 
325 /*
326  * Verify that a bound datagram socket only accepts data from the same FIB.
327  */
328 static void
329 per_fib_dgram_socket(int domain, int type, const atf_tc_t *tc __unused)
330 {
331 	struct sockaddr_storage ss;
332 	struct sockaddr_in6 *sin6p;
333 	socklen_t sslen;
334 	ssize_t n;
335 	int error, cs1, cs2, fib1, fib2, ss1, ss2;
336 	char b;
337 
338 	ATF_REQUIRE(type == SOCK_DGRAM);
339 	ATF_REQUIRE(domain == PF_INET || domain == PF_INET6);
340 	require_fibs_multibind(type, 2);
341 
342 	fib1 = 0;
343 	fib2 = 1;
344 
345 	cs1 = mksock(domain, type, fib1);
346 	cs2 = mksock(domain, type, fib2);
347 
348 	ss1 = mksock(domain, type, fib1);
349 	ss2 = mksock(domain, type, fib2);
350 
351 	sslen = domain == PF_INET ? sizeof(struct sockaddr_in) :
352 	    sizeof(struct sockaddr_in6);
353 
354 	memset(&ss, 0, sizeof(ss));
355 	ss.ss_family = domain;
356 	ss.ss_len = sslen;
357 	error = bind(ss1, (struct sockaddr *)&ss, sslen);
358 	ATF_REQUIRE_MSG(error == 0, "bind failed: %s", strerror(errno));
359 
360 	error = getsockname(ss1, (struct sockaddr *)&ss, &sslen);
361 	ATF_REQUIRE_MSG(error == 0, "getsockname failed: %s", strerror(errno));
362 
363 	if (domain == PF_INET6) {
364 		sin6p = (struct sockaddr_in6 *)&ss;
365 		sin6p->sin6_addr = in6addr_loopback;
366 	}
367 
368 	/* If we send a byte from cs1, it should be recieved by ss1. */
369 	b = 42;
370 	n = sendto(cs1, &b, sizeof(b), 0, (struct sockaddr *)&ss, sslen);
371 	ATF_REQUIRE_MSG(n == 1, "sendto failed: %s", strerror(errno));
372 	n = recv(ss1, &b, sizeof(b), 0);
373 	ATF_REQUIRE(n == 1);
374 	ATF_REQUIRE(b == 42);
375 
376 	/* If we send a byte from cs2, it should not be received by ss1. */
377 	b = 42;
378 	n = sendto(cs2, &b, sizeof(b), 0, (struct sockaddr *)&ss, sslen);
379 	ATF_REQUIRE_MSG(n == 1, "sendto failed: %s", strerror(errno));
380 	usleep(10000);
381 	n = recv(ss1, &b, sizeof(b), MSG_DONTWAIT);
382 	ATF_REQUIRE_ERRNO(EWOULDBLOCK, n == -1);
383 
384 	error = bind(ss2, (struct sockaddr *)&ss, sslen);
385 	ATF_REQUIRE_MSG(error == 0, "bind failed: %s", strerror(errno));
386 
387 	/* Repeat now that ss2 is bound. */
388 	b = 42;
389 	n = sendto(cs1, &b, sizeof(b), 0, (struct sockaddr *)&ss, sslen);
390 	ATF_REQUIRE_MSG(n == 1, "sendto failed: %s", strerror(errno));
391 	n = recv(ss1, &b, sizeof(b), 0);
392 	ATF_REQUIRE(n == 1);
393 	ATF_REQUIRE(b == 42);
394 
395 	b = 42;
396 	n = sendto(cs2, &b, sizeof(b), 0, (struct sockaddr *)&ss, sslen);
397 	ATF_REQUIRE_MSG(n == 1, "sendto failed: %s", strerror(errno));
398 	n = recv(ss2, &b, sizeof(b), 0);
399 	ATF_REQUIRE(n == 1);
400 	ATF_REQUIRE(b == 42);
401 
402 	checked_close(ss1);
403 	checked_close(ss2);
404 	checked_close(cs1);
405 	checked_close(cs2);
406 }
407 MAKETEST_UDP(per_fib_dgram_socket);
408 
409 static size_t
410 ping(int s, const struct sockaddr *sa, socklen_t salen)
411 {
412 	struct {
413 		struct icmphdr icmp;
414 		char data[64];
415 	} icmp;
416 	ssize_t n;
417 
418 	memset(&icmp, 0, sizeof(icmp));
419 	icmp.icmp.icmp_type = ICMP_ECHO;
420 	icmp.icmp.icmp_code = 0;
421 	icmp.icmp.icmp_cksum = htons((unsigned short)~(ICMP_ECHO << 8));
422 	n = sendto(s, &icmp, sizeof(icmp), 0, sa, salen);
423 	ATF_REQUIRE_MSG(n == (ssize_t)sizeof(icmp), "sendto failed: %s",
424 	    strerror(errno));
425 
426 	return (sizeof(icmp) + sizeof(struct ip));
427 }
428 
429 static size_t
430 ping6(int s, const struct sockaddr *sa, socklen_t salen)
431 {
432 	struct {
433 		struct icmp6_hdr icmp6;
434 		char data[64];
435 	} icmp6;
436 	ssize_t n;
437 
438 	memset(&icmp6, 0, sizeof(icmp6));
439 	icmp6.icmp6.icmp6_type = ICMP6_ECHO_REQUEST;
440 	icmp6.icmp6.icmp6_code = 0;
441 	icmp6.icmp6.icmp6_cksum =
442 	    htons((unsigned short)~(ICMP6_ECHO_REQUEST << 8));
443 	n = sendto(s, &icmp6, sizeof(icmp6), 0, sa, salen);
444 	ATF_REQUIRE_MSG(n == (ssize_t)sizeof(icmp6), "sendto failed: %s",
445 	    strerror(errno));
446 
447 	return (sizeof(icmp6));
448 }
449 
450 static void
451 per_fib_raw_socket(int domain, int type, const atf_tc_t *tc __unused)
452 {
453 	struct sockaddr_in sin;
454 	struct sockaddr_in6 sin6;
455 	ssize_t n;
456 	size_t sz;
457 	int error, cs, s[2], proto;
458 	uint8_t b[256];
459 
460 	ATF_REQUIRE(type == SOCK_RAW);
461 	ATF_REQUIRE(domain == PF_INET || domain == PF_INET6);
462 	require_fibs_multibind(type, 2);
463 
464 	proto = domain == PF_INET ? IPPROTO_ICMP : IPPROTO_ICMPV6;
465 	s[0] = mksockp(domain, type, 0, proto);
466 	s[1] = mksockp(domain, type, 1, proto);
467 
468 	if (domain == PF_INET) {
469 		memset(&sin, 0, sizeof(sin));
470 		sin.sin_family = domain;
471 		sin.sin_len = sizeof(sin);
472 		sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
473 		error = bind(s[0], (struct sockaddr *)&sin, sizeof(sin));
474 	} else /* if (domain == PF_INET6) */ {
475 		memset(&sin6, 0, sizeof(sin6));
476 		sin6.sin6_family = domain;
477 		sin6.sin6_len = sizeof(sin6);
478 		sin6.sin6_addr = in6addr_loopback;
479 		error = bind(s[0], (struct sockaddr *)&sin6, sizeof(sin6));
480 	}
481 	ATF_REQUIRE_MSG(error == 0, "bind failed: %s", strerror(errno));
482 
483 	for (int i = 0; i < 2; i++) {
484 		cs = mksockp(domain, type, i, proto);
485 		if (domain == PF_INET) {
486 			sz = ping(cs, (struct sockaddr *)&sin, sizeof(sin));
487 		} else /* if (domain == PF_INET6) */ {
488 			sz = ping6(cs, (struct sockaddr *)&sin6, sizeof(sin6));
489 		}
490 		n = recv(s[i], b, sizeof(b), 0);
491 		ATF_REQUIRE_MSG(n > 0, "recv failed: %s", strerror(errno));
492 		ATF_REQUIRE_MSG(n == (ssize_t)sz,
493 		    "short packet received: %zd", n);
494 
495 		if (domain == PF_INET6) {
496 			/* Get the echo reply as well. */
497 			n = recv(s[i], b, sizeof(b), 0);
498 			ATF_REQUIRE_MSG(n > 0,
499 			    "recv failed: %s", strerror(errno));
500 			ATF_REQUIRE_MSG(n == (ssize_t)sz,
501 			    "short packet received: %zd", n);
502 		}
503 
504 		/* Make sure that the other socket didn't receive anything. */
505 		n = recv(s[1 - i], b, sizeof(b), MSG_DONTWAIT);
506 		printf("n = %zd i = %d\n", n, i);
507 		ATF_REQUIRE_ERRNO(EWOULDBLOCK, n == -1);
508 
509 		checked_close(cs);
510 	}
511 
512 	checked_close(s[0]);
513 	checked_close(s[1]);
514 }
515 MAKETEST_RAW(per_fib_raw_socket);
516 
517 /*
518  * Create a pair of load-balancing listening socket groups, one in each FIB, and
519  * make sure that connections to the group are only load-balanced within the
520  * same FIB.
521  */
522 static void
523 multibind_lbgroup_stream(int domain, int type, const atf_tc_t *tc __unused)
524 {
525 	struct sockaddr_storage ss;
526 	socklen_t sslen;
527 	int error, as, cs, s[3];
528 
529 	ATF_REQUIRE(type == SOCK_STREAM);
530 	ATF_REQUIRE(domain == PF_INET || domain == PF_INET6);
531 	require_fibs_multibind(type, 2);
532 
533 	s[0] = mksock(domain, type, 0);
534 	ATF_REQUIRE(setsockopt(s[0], SOL_SOCKET, SO_REUSEPORT_LB, &(int){1},
535 	    sizeof(int)) == 0);
536 	ATF_REQUIRE(fcntl(s[0], F_SETFL, O_NONBLOCK) == 0);
537 	s[1] = mksock(domain, type, 0);
538 	ATF_REQUIRE(setsockopt(s[1], SOL_SOCKET, SO_REUSEPORT_LB, &(int){1},
539 	    sizeof(int)) == 0);
540 	ATF_REQUIRE(fcntl(s[1], F_SETFL, O_NONBLOCK) == 0);
541 	s[2] = mksock(domain, type, 1);
542 	ATF_REQUIRE(setsockopt(s[2], SOL_SOCKET, SO_REUSEPORT_LB, &(int){1},
543 	    sizeof(int)) == 0);
544 
545 	sslen = domain == PF_INET ? sizeof(struct sockaddr_in) :
546 	    sizeof(struct sockaddr_in6);
547 	memset(&ss, 0, sizeof(ss));
548 	ss.ss_family = domain;
549 	ss.ss_len = sslen;
550 	error = bind(s[0], (struct sockaddr *)&ss, sslen);
551 	ATF_REQUIRE_MSG(error == 0, "bind failed: %s", strerror(errno));
552 	error = listen(s[0], 5);
553 	ATF_REQUIRE_MSG(error == 0, "listen failed: %s", strerror(errno));
554 	error = getsockname(s[0], (struct sockaddr *)&ss, &sslen);
555 	ATF_REQUIRE_MSG(error == 0, "getsockname failed: %s", strerror(errno));
556 
557 	error = bind(s[1], (struct sockaddr *)&ss, sslen);
558 	ATF_REQUIRE_MSG(error == 0, "bind failed: %s", strerror(errno));
559 	error = listen(s[1], 5);
560 	ATF_REQUIRE_MSG(error == 0, "listen failed: %s", strerror(errno));
561 
562 	error = bind(s[2], (struct sockaddr *)&ss, sslen);
563 	ATF_REQUIRE_MSG(error == 0, "bind failed: %s", strerror(errno));
564 	error = listen(s[2], 5);
565 	ATF_REQUIRE_MSG(error == 0, "listen failed: %s", strerror(errno));
566 
567 	/*
568 	 * Initiate connections from FIB 0, make sure they go to s[0] or s[1].
569 	 */
570 	for (int count = 0; count < 100; count++) {
571 		cs = mksock(domain, type, 0);
572 		error = connect(cs, (struct sockaddr *)&ss, sslen);
573 		ATF_REQUIRE_MSG(error == 0, "connect failed: %s",
574 		    strerror(errno));
575 
576 		do {
577 			as = accept(s[0], NULL, NULL);
578 			if (as == -1) {
579 				ATF_REQUIRE_MSG(errno == EWOULDBLOCK,
580 				    "accept failed: %s", strerror(errno));
581 				as = accept(s[1], NULL, NULL);
582 				if (as == -1) {
583 					ATF_REQUIRE_MSG(errno == EWOULDBLOCK,
584 					    "accept failed: %s",
585 					    strerror(errno));
586 				}
587 			}
588 		} while (as == -1);
589 		checked_close(as);
590 		checked_close(cs);
591 	}
592 
593 	/*
594 	 * Initiate connections from FIB 1, make sure they go to s[2].
595 	 */
596 	for (int count = 0; count < 100; count++) {
597 		cs = mksock(domain, type, 1);
598 		error = connect(cs, (struct sockaddr *)&ss, sslen);
599 		ATF_REQUIRE_MSG(error == 0, "connect failed: %s",
600 		    strerror(errno));
601 
602 		as = accept(s[2], NULL, NULL);
603 		ATF_REQUIRE_MSG(as != -1, "accept failed: %s", strerror(errno));
604 		checked_close(as);
605 		checked_close(cs);
606 	}
607 
608 	checked_close(s[0]);
609 	checked_close(s[1]);
610 	checked_close(s[2]);
611 }
612 MAKETEST_TCP(multibind_lbgroup_stream);
613 
614 static void
615 multibind_lbgroup_dgram(int domain, int type, const atf_tc_t *tc __unused)
616 {
617 	struct sockaddr_storage ss;
618 	struct sockaddr_in6 *sin6p;
619 	socklen_t sslen;
620 	ssize_t n;
621 	int error, cs, s[3];
622 	char b;
623 
624 	ATF_REQUIRE(type == SOCK_DGRAM);
625 	ATF_REQUIRE(domain == PF_INET || domain == PF_INET6);
626 	require_fibs_multibind(type, 2);
627 
628 	s[0] = mksock(domain, type, 0);
629 	ATF_REQUIRE(setsockopt(s[0], SOL_SOCKET, SO_REUSEPORT_LB, &(int){1},
630 	    sizeof(int)) == 0);
631 	s[1] = mksock(domain, type, 0);
632 	ATF_REQUIRE(setsockopt(s[1], SOL_SOCKET, SO_REUSEPORT_LB, &(int){1},
633 	    sizeof(int)) == 0);
634 	s[2] = mksock(domain, type, 1);
635 	ATF_REQUIRE(setsockopt(s[2], SOL_SOCKET, SO_REUSEPORT_LB, &(int){1},
636 	    sizeof(int)) == 0);
637 
638 	sslen = domain == PF_INET ? sizeof(struct sockaddr_in) :
639 	    sizeof(struct sockaddr_in6);
640 	memset(&ss, 0, sizeof(ss));
641 	ss.ss_family = domain;
642 	ss.ss_len = sslen;
643 	error = bind(s[0], (struct sockaddr *)&ss, sslen);
644 	ATF_REQUIRE_MSG(error == 0, "bind failed: %s", strerror(errno));
645 	error = getsockname(s[0], (struct sockaddr *)&ss, &sslen);
646 	ATF_REQUIRE_MSG(error == 0, "getsockname failed: %s", strerror(errno));
647 
648 	error = bind(s[1], (struct sockaddr *)&ss, sslen);
649 	ATF_REQUIRE_MSG(error == 0, "bind failed: %s", strerror(errno));
650 	error = bind(s[2], (struct sockaddr *)&ss, sslen);
651 	ATF_REQUIRE_MSG(error == 0, "bind failed: %s", strerror(errno));
652 
653 	if (domain == PF_INET6) {
654 		sin6p = (struct sockaddr_in6 *)&ss;
655 		sin6p->sin6_addr = in6addr_loopback;
656 	}
657 
658 	/*
659 	 * Send a packet from FIB 0, make sure it goes to s[0] or s[1].
660 	 */
661 	cs = mksock(domain, type, 0);
662 	for (int count = 0; count < 100; count++) {
663 		int bytes, rs;
664 
665 		b = 42;
666 		n = sendto(cs, &b, sizeof(b), 0, (struct sockaddr *)&ss, sslen);
667 		ATF_REQUIRE_MSG(n == 1, "sendto failed: %s", strerror(errno));
668 		usleep(1000);
669 
670 		error = ioctl(s[0], FIONREAD, &bytes);
671 		ATF_REQUIRE_MSG(error == 0, "ioctl failed: %s",
672 		    strerror(errno));
673 		if (bytes == 0) {
674 			error = ioctl(s[1], FIONREAD, &bytes);
675 			ATF_REQUIRE_MSG(error == 0, "ioctl failed: %s",
676 			    strerror(errno));
677 			rs = s[1];
678 		} else {
679 			rs = s[0];
680 		}
681 		n = recv(rs, &b, sizeof(b), 0);
682 		ATF_REQUIRE(n == 1);
683 		ATF_REQUIRE(b == 42);
684 		ATF_REQUIRE(bytes == 1);
685 	}
686 	checked_close(cs);
687 
688 	/*
689 	 * Send a packet from FIB 1, make sure it goes to s[2].
690 	 */
691 	cs = mksock(domain, type, 1);
692 	for (int count = 0; count < 100; count++) {
693 		b = 42;
694 		n = sendto(cs, &b, sizeof(b), 0, (struct sockaddr *)&ss, sslen);
695 		ATF_REQUIRE_MSG(n == 1, "sendto failed: %s", strerror(errno));
696 		usleep(1000);
697 
698 		n = recv(s[2], &b, sizeof(b), 0);
699 		ATF_REQUIRE(n == 1);
700 		ATF_REQUIRE(b == 42);
701 	}
702 	checked_close(cs);
703 
704 	checked_close(s[0]);
705 	checked_close(s[1]);
706 	checked_close(s[2]);
707 }
708 MAKETEST_UDP(multibind_lbgroup_dgram);
709 
710 /*
711  * Make sure that we can't change the FIB of a bound socket.
712  */
713 static void
714 no_setfib_after_bind(int domain, int type, const atf_tc_t *tc __unused)
715 {
716 	struct sockaddr_storage ss;
717 	socklen_t sslen;
718 	int error, s;
719 
720 	ATF_REQUIRE(domain == PF_INET || domain == PF_INET6);
721 	require_fibs_multibind(type, 2);
722 
723 	s = mksock(domain, type, 0);
724 
725 	sslen = domain == PF_INET ? sizeof(struct sockaddr_in) :
726 	    sizeof(struct sockaddr_in6);
727 	memset(&ss, 0, sizeof(ss));
728 	ss.ss_family = domain;
729 	ss.ss_len = sslen;
730 	error = bind(s, (struct sockaddr *)&ss, sslen);
731 	ATF_REQUIRE_MSG(error == 0, "bind failed: %s", strerror(errno));
732 
733 	error = setsockopt(s, SOL_SOCKET, SO_SETFIB, &(int){1}, sizeof(int));
734 	ATF_REQUIRE_ERRNO(EISCONN, error == -1);
735 
736 	/* It's ok to set the FIB number to its current value. */
737 	error = setsockopt(s, SOL_SOCKET, SO_SETFIB, &(int){0}, sizeof(int));
738 	ATF_REQUIRE_MSG(error == 0, "setsockopt failed: %s", strerror(errno));
739 
740 	checked_close(s);
741 }
742 MAKETEST(no_setfib_after_bind);
743 
744 ATF_TP_ADD_TCS(tp)
745 {
746 	LISTTEST(multibind_different_user);
747 	LISTTEST_TCP(per_fib_listening_socket);
748 	LISTTEST_UDP(per_fib_dgram_socket);
749 	LISTTEST_RAW(per_fib_raw_socket);
750 	LISTTEST_TCP(multibind_lbgroup_stream);
751 	LISTTEST_UDP(multibind_lbgroup_dgram);
752 	LISTTEST(no_setfib_after_bind);
753 
754 	return (atf_no_error());
755 }
756