xref: /freebsd/tests/sys/netinet/socket_afinet.c (revision f5dc2263ab1be8a35a7e27e82103f9ccd41ae584)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2019 Bjoern A. Zeeb
5  * Copyright (c) 2024 Stormshield
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are 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 the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include <sys/param.h>
30 #include <sys/socket.h>
31 #include <sys/wait.h>
32 
33 #include <netinet/in.h>
34 #include <arpa/inet.h>
35 
36 #include <errno.h>
37 #include <poll.h>
38 #include <pwd.h>
39 #include <stdio.h>
40 #include <unistd.h>
41 
42 #include <atf-c.h>
43 
44 ATF_TC_WITHOUT_HEAD(basic);
45 ATF_TC_BODY(basic, tc)
46 {
47 	int sd;
48 
49 	sd = socket(PF_INET, SOCK_DGRAM, 0);
50 	ATF_CHECK(sd >= 0);
51 
52 	close(sd);
53 }
54 
55 ATF_TC_WITHOUT_HEAD(bind_zero);
56 ATF_TC_BODY(bind_zero, tc)
57 {
58 	int sd, rc;
59 	struct sockaddr_in sin;
60 
61 	sd = socket(PF_INET, SOCK_DGRAM, 0);
62 	ATF_CHECK(sd >= 0);
63 
64 	bzero(&sin, sizeof(sin));
65 	/*
66 	 * For AF_INET we do not check the family in in_pcbbind_setup(9),
67 	 * sa_len gets set from the syscall argument in getsockaddr(9),
68 	 * so we bind to 0:0.
69 	 */
70 	rc = bind(sd, (struct sockaddr *)&sin, sizeof(sin));
71 	ATF_CHECK_EQ(0, rc);
72 
73 	close(sd);
74 }
75 
76 ATF_TC_WITHOUT_HEAD(bind_ok);
77 ATF_TC_BODY(bind_ok, tc)
78 {
79 	int sd, rc;
80 	struct sockaddr_in sin;
81 
82 	sd = socket(PF_INET, SOCK_DGRAM, 0);
83 	ATF_CHECK(sd >= 0);
84 
85 	bzero(&sin, sizeof(sin));
86 	sin.sin_family = AF_INET;
87 	sin.sin_len = sizeof(sin);
88 	sin.sin_port = htons(0);
89 	sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
90 	rc = bind(sd, (struct sockaddr *)&sin, sizeof(sin));
91 	ATF_CHECK_EQ(0, rc);
92 
93 	close(sd);
94 }
95 
96 ATF_TC_WITHOUT_HEAD(poll_no_rdhup);
97 ATF_TC_BODY(poll_no_rdhup, tc)
98 {
99 	int ss, ss2, cs, rc;
100 	struct sockaddr_in sin;
101 	socklen_t slen;
102 	struct pollfd pfd;
103 	int one = 1;
104 
105 	/* Verify that we don't expose POLLRDHUP if not requested. */
106 
107 	/* Server setup. */
108 	ss = socket(PF_INET, SOCK_STREAM, 0);
109 	ATF_CHECK(ss >= 0);
110 	rc = setsockopt(ss, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one));
111 	ATF_CHECK_EQ(0, rc);
112 	bzero(&sin, sizeof(sin));
113 	sin.sin_family = AF_INET;
114 	sin.sin_len = sizeof(sin);
115 	sin.sin_port = htons(0);
116 	sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
117 	rc = bind(ss, (struct sockaddr *)&sin, sizeof(sin));
118 	ATF_CHECK_EQ(0, rc);
119 	rc = listen(ss, 1);
120 	ATF_CHECK_EQ(0, rc);
121 	slen = sizeof(sin);
122 	rc = getsockname(ss, (struct sockaddr *)&sin, &slen);
123 	ATF_CHECK_EQ(0, rc);
124 
125 	/* Client connects, server accepts. */
126 	cs = socket(PF_INET, SOCK_STREAM, 0);
127 	ATF_CHECK(cs >= 0);
128 	rc = connect(cs, (struct sockaddr *)&sin, sizeof(sin));
129 	ATF_CHECK_EQ(0, rc);
130 	ss2 = accept(ss, NULL, NULL);
131 	ATF_CHECK(ss2 >= 0);
132 
133 	/* Server can write, sees only POLLOUT. */
134 	pfd.fd = ss2;
135 	pfd.events = POLLIN | POLLOUT;
136 	rc = poll(&pfd, 1, 0);
137 	ATF_CHECK_EQ(1, rc);
138 	ATF_CHECK_EQ(POLLOUT, pfd.revents);
139 
140 	/* Client closes socket! */
141 	rc = close(cs);
142 	ATF_CHECK_EQ(0, rc);
143 
144 	/*
145 	 * Server now sees POLLIN, but not POLLRDHUP because we didn't ask.
146 	 * Need non-zero timeout to wait for the FIN to arrive and trigger the
147 	 * socket to become readable.
148 	 */
149 	pfd.fd = ss2;
150 	pfd.events = POLLIN;
151 	rc = poll(&pfd, 1, 60000);
152 	ATF_CHECK_EQ(1, rc);
153 	ATF_CHECK_EQ(POLLIN, pfd.revents);
154 
155 	close(ss2);
156 	close(ss);
157 }
158 
159 ATF_TC_WITHOUT_HEAD(poll_rdhup);
160 ATF_TC_BODY(poll_rdhup, tc)
161 {
162 	int ss, ss2, cs, rc;
163 	struct sockaddr_in sin;
164 	socklen_t slen;
165 	struct pollfd pfd;
166 	char buffer;
167 	int one = 1;
168 
169 	/* Verify that server sees POLLRDHUP if it asks for it. */
170 
171 	/* Server setup. */
172 	ss = socket(PF_INET, SOCK_STREAM, 0);
173 	ATF_CHECK(ss >= 0);
174 	rc = setsockopt(ss, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one));
175 	ATF_CHECK_EQ(0, rc);
176 	bzero(&sin, sizeof(sin));
177 	sin.sin_family = AF_INET;
178 	sin.sin_len = sizeof(sin);
179 	sin.sin_port = htons(0);
180 	sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
181 	rc = bind(ss, (struct sockaddr *)&sin, sizeof(sin));
182 	ATF_CHECK_EQ(0, rc);
183 	rc = listen(ss, 1);
184 	ATF_CHECK_EQ(0, rc);
185 	slen = sizeof(sin);
186 	rc = getsockname(ss, (struct sockaddr *)&sin, &slen);
187 	ATF_CHECK_EQ(0, rc);
188 
189 	/* Client connects, server accepts. */
190 	cs = socket(PF_INET, SOCK_STREAM, 0);
191 	ATF_CHECK(cs >= 0);
192 	rc = connect(cs, (struct sockaddr *)&sin, sizeof(sin));
193 	ATF_CHECK_EQ(0, rc);
194 	ss2 = accept(ss, NULL, NULL);
195 	ATF_CHECK(ss2 >= 0);
196 
197 	/* Server can write, so sees POLLOUT. */
198 	pfd.fd = ss2;
199 	pfd.events = POLLIN | POLLOUT | POLLRDHUP;
200 	rc = poll(&pfd, 1, 0);
201 	ATF_CHECK_EQ(1, rc);
202 	ATF_CHECK_EQ(POLLOUT, pfd.revents);
203 
204 	/* Client writes two bytes, server reads only one of them. */
205 	rc = write(cs, "xx", 2);
206 	ATF_CHECK_EQ(2, rc);
207 	rc = read(ss2, &buffer, 1);
208 	ATF_CHECK_EQ(1, rc);
209 
210 	/* Server can read, so sees POLLIN. */
211 	pfd.fd = ss2;
212 	pfd.events = POLLIN | POLLOUT | POLLRDHUP;
213 	rc = poll(&pfd, 1, 0);
214 	ATF_CHECK_EQ(1, rc);
215 	ATF_CHECK_EQ(POLLIN | POLLOUT, pfd.revents);
216 
217 	/* Client closes socket! */
218 	rc = close(cs);
219 	ATF_CHECK_EQ(0, rc);
220 
221 	/*
222 	 * Server sees Linux-style POLLRDHUP.  Note that this is the case even
223 	 * though one byte of data remains unread.
224 	 *
225 	 * This races against the delivery of FIN caused by the close() above.
226 	 * Sometimes (more likely when run under truss or if another system
227 	 * call is added in between) it hits the path where sopoll_generic()
228 	 * immediately sees SBS_CANTRCVMORE, and sometimes it sleeps with flag
229 	 * SB_SEL so that it's woken up almost immediately and runs again,
230 	 * which is why we need a non-zero timeout here.
231 	 */
232 	pfd.fd = ss2;
233 	pfd.events = POLLRDHUP;
234 	rc = poll(&pfd, 1, 60000);
235 	ATF_CHECK_EQ(1, rc);
236 	ATF_CHECK_EQ(POLLRDHUP, pfd.revents);
237 
238 	close(ss2);
239 	close(ss);
240 }
241 
242 ATF_TC_WITHOUT_HEAD(stream_reconnect);
243 ATF_TC_BODY(stream_reconnect, tc)
244 {
245 	struct sockaddr_in sin;
246 	socklen_t slen;
247 	int ss, cs, rc;
248 
249 	/*
250 	 * Make sure that an attempt to connect(2) a connected or disconnected
251 	 * stream socket fails with EISCONN.
252 	 */
253 
254 	/* Server setup. */
255 	ss = socket(PF_INET, SOCK_STREAM, 0);
256 	ATF_CHECK(ss >= 0);
257 	bzero(&sin, sizeof(sin));
258 	sin.sin_family = AF_INET;
259 	sin.sin_len = sizeof(sin);
260 	sin.sin_port = htons(0);
261 	sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
262 	rc = bind(ss, (struct sockaddr *)&sin, sizeof(sin));
263 	ATF_CHECK_EQ(0, rc);
264 	rc = listen(ss, 1);
265 	ATF_CHECK_EQ(0, rc);
266 	slen = sizeof(sin);
267 	rc = getsockname(ss, (struct sockaddr *)&sin, &slen);
268 	ATF_CHECK_EQ(0, rc);
269 
270 	/* Client connects, shuts down. */
271 	cs = socket(PF_INET, SOCK_STREAM, 0);
272 	ATF_CHECK(cs >= 0);
273 	rc = connect(cs, (struct sockaddr *)&sin, sizeof(sin));
274 	ATF_CHECK_EQ(0, rc);
275 	rc = shutdown(cs, SHUT_RDWR);
276 	ATF_CHECK_EQ(0, rc);
277 
278 	/* A subsequent connect(2) fails with EISCONN. */
279 	rc = connect(cs, (struct sockaddr *)&sin, sizeof(sin));
280 	ATF_CHECK_EQ(-1, rc);
281 	ATF_CHECK_EQ(errno, EISCONN);
282 
283 	rc = close(cs);
284 	ATF_CHECK_EQ(0, rc);
285 	rc = close(ss);
286 	ATF_CHECK_EQ(0, rc);
287 }
288 
289 /*
290  * Make sure that unprivileged users can't set the IP_BINDANY or IPV6_BINDANY
291  * socket options.
292  */
293 ATF_TC(bindany);
294 ATF_TC_HEAD(bindany, tc)
295 {
296 	atf_tc_set_md_var(tc, "require.user", "unprivileged");
297 }
298 ATF_TC_BODY(bindany, tc)
299 {
300 	int s;
301 
302 	s = socket(AF_INET, SOCK_STREAM, 0);
303 	ATF_REQUIRE(s >= 0);
304 	ATF_REQUIRE_ERRNO(EPERM,
305 	    setsockopt(s, IPPROTO_IP, IP_BINDANY, &(int){1}, sizeof(int)) ==
306 	    -1);
307 	ATF_REQUIRE(close(s) == 0);
308 
309 	s = socket(AF_INET, SOCK_DGRAM, 0);
310 	ATF_REQUIRE(s >= 0);
311 	ATF_REQUIRE_ERRNO(EPERM,
312 	    setsockopt(s, IPPROTO_IP, IP_BINDANY, &(int){1}, sizeof(int)) ==
313 	    -1);
314 	ATF_REQUIRE(close(s) == 0);
315 
316 	s = socket(AF_INET6, SOCK_STREAM, 0);
317 	ATF_REQUIRE(s >= 0);
318 	ATF_REQUIRE_ERRNO(EPERM,
319 	    setsockopt(s, IPPROTO_IPV6, IPV6_BINDANY, &(int){1}, sizeof(int)) ==
320 	    -1);
321 	ATF_REQUIRE(close(s) == 0);
322 
323 	s = socket(AF_INET6, SOCK_DGRAM, 0);
324 	ATF_REQUIRE(s >= 0);
325 	ATF_REQUIRE_ERRNO(EPERM,
326 	    setsockopt(s, IPPROTO_IPV6, IPV6_BINDANY, &(int){1}, sizeof(int)) ==
327 	    -1);
328 	ATF_REQUIRE(close(s) == 0);
329 }
330 
331 /*
332  * Bind a socket to the specified address, optionally dropping privileges and
333  * setting one of the SO_REUSE* options first.
334  *
335  * Expected returns for different test case scenarios are: 1) successful
336  * immediate bind(2), successful bind(2) after setting specified SO_REUSE*
337  * socket option, and bind(2) failed with EADDRINUSE.
338  */
339 static enum bind_res {
340 	BIND_FAILED = 0,
341 	SETEUID_FAIL = 1,
342 	SOCKET_FAIL = 2,
343 	BIND_INSTANT_SUCCESS = 3,
344 	BIND_BADERR1 = 4,
345 	SETSOCKOPT_FAIL = 5,
346 	BIND_REUSE_SUCCESS = 6,
347 	BIND_BADERR2 = 7,
348 }
349 child_bind(const atf_tc_t *tc, int type, struct sockaddr *sa, int opt,
350     bool unpriv)
351 {
352 	const char *user;
353 	pid_t child;
354 
355 	if (unpriv) {
356 		if (!atf_tc_has_config_var(tc, "unprivileged_user"))
357 			atf_tc_skip("unprivileged_user not set");
358 		user = atf_tc_get_config_var(tc, "unprivileged_user");
359 	} else {
360 		user = NULL;
361 	}
362 
363 	child = fork();
364 	ATF_REQUIRE(child != -1);
365 	if (child == 0) {
366 		int s;
367 
368 		if (user != NULL) {
369 			struct passwd *passwd;
370 
371 			passwd = getpwnam(user);
372 			if (seteuid(passwd->pw_uid) != 0)
373 				_exit(SETEUID_FAIL);
374 		}
375 
376 		s = socket(sa->sa_family, type, 0);
377 		if (s < 0)
378 			_exit(SOCKET_FAIL);
379 		if (bind(s, sa, sa->sa_len) == 0)
380 			_exit(BIND_INSTANT_SUCCESS);
381 		if (errno != EADDRINUSE)
382 			_exit(BIND_BADERR1);
383 		if (opt != 0) {
384 			if (setsockopt(s, SOL_SOCKET, opt, &(int){1},
385 			    sizeof(int)) != 0)
386 				_exit(SETSOCKOPT_FAIL);
387 		}
388 		if (bind(s, sa, sa->sa_len) == 0)
389 			_exit(BIND_REUSE_SUCCESS);
390 		if (errno != EADDRINUSE)
391 			_exit(BIND_BADERR1);
392 		_exit(BIND_FAILED);
393 	} else {
394 		int status;
395 
396 		ATF_REQUIRE_EQ(waitpid(child, &status, 0), child);
397 		ATF_REQUIRE(WIFEXITED(status));
398 		status = WEXITSTATUS(status);
399 		return (status);
400 	}
401 }
402 
403 static enum bind_res
404 child_bind_priv(const atf_tc_t *tc, int type, struct sockaddr *sa, int opt)
405 {
406 	return (child_bind(tc, type, sa, opt, false));
407 }
408 
409 static enum bind_res
410 child_bind_unpriv(const atf_tc_t *tc, int type, struct sockaddr *sa, int opt)
411 {
412 	return (child_bind(tc, type, sa, opt, true));
413 }
414 
415 static int
416 bind_socket(int domain, int type, int opt, bool unspec, struct sockaddr *sa)
417 {
418 	socklen_t slen;
419 	int s;
420 
421 	s = socket(domain, type, 0);
422 	ATF_REQUIRE(s >= 0);
423 
424 	if (domain == AF_INET) {
425 		struct sockaddr_in sin;
426 
427 		bzero(&sin, sizeof(sin));
428 		sin.sin_family = AF_INET;
429 		sin.sin_len = sizeof(sin);
430 		sin.sin_addr.s_addr = htonl(unspec ?
431 		    INADDR_ANY : INADDR_LOOPBACK);
432 		sin.sin_port = htons(0);
433 		ATF_REQUIRE(bind(s, (struct sockaddr *)&sin, sizeof(sin)) == 0);
434 
435 		slen = sizeof(sin);
436 	} else /* if (domain == AF_INET6) */ {
437 		struct sockaddr_in6 sin6;
438 
439 		bzero(&sin6, sizeof(sin6));
440 		sin6.sin6_family = AF_INET6;
441 		sin6.sin6_len = sizeof(sin6);
442 		sin6.sin6_addr = unspec ? in6addr_any : in6addr_loopback;
443 		sin6.sin6_port = htons(0);
444 		ATF_REQUIRE(bind(s, (struct sockaddr *)&sin6, sizeof(sin6)) == 0);
445 
446 		slen = sizeof(sin6);
447 	}
448 
449 	if (opt != 0) {
450 		ATF_REQUIRE(setsockopt(s, SOL_SOCKET, opt, &(int){1},
451 		    sizeof(int)) == 0);
452 	}
453 
454 	ATF_REQUIRE(getsockname(s, sa, &slen) == 0);
455 
456 	return (s);
457 }
458 
459 static void
460 multibind_test(const atf_tc_t *tc, int domain, int type)
461 {
462 	struct sockaddr_storage ss;
463 	int opts[4] = { 0, SO_REUSEADDR, SO_REUSEPORT, SO_REUSEPORT_LB };
464 	int s;
465 	bool flags[2] = { false, true };
466 	enum bind_res res;
467 
468 	for (size_t flagi = 0; flagi < nitems(flags); flagi++) {
469 		for (size_t opti = 0; opti < nitems(opts); opti++) {
470 			s = bind_socket(domain, type, opts[opti], flags[flagi],
471 			    (struct sockaddr *)&ss);
472 			for (size_t optj = 0; optj < nitems(opts); optj++) {
473 				int opt;
474 
475 				opt = opts[optj];
476 				res = child_bind_priv(tc, type,
477 				    (struct sockaddr *)&ss, opt);
478 				/*
479 				 * Multi-binding is only allowed when both
480 				 * sockets have SO_REUSEPORT or SO_REUSEPORT_LB
481 				 * set.
482 				 */
483 				if (opts[opti] != 0 &&
484 				    opts[opti] != SO_REUSEADDR && opti == optj)
485 					ATF_REQUIRE(res == BIND_REUSE_SUCCESS);
486 				else
487 					ATF_REQUIRE(res == BIND_FAILED);
488 
489 				res = child_bind_unpriv(tc, type,
490 				    (struct sockaddr *)&ss, opt);
491 				/*
492 				 * Multi-binding is only allowed when both
493 				 * sockets have the same owner.
494 				 */
495 				ATF_REQUIRE_MSG(res == BIND_FAILED,
496 				    "domain %u type %u opts %u:%u: "
497 				    "result %u (expected %u)",
498 				    domain, type, opts[opti], opts[optj],
499 				    res, BIND_FAILED);
500 			}
501 			ATF_REQUIRE(close(s) == 0);
502 		}
503 	}
504 }
505 
506 /*
507  * Try to bind two sockets to the same address/port tuple.  Under some
508  * conditions this is permitted.
509  */
510 ATF_TC(multibind);
511 ATF_TC_HEAD(multibind, tc)
512 {
513 	atf_tc_set_md_var(tc, "require.user", "root");
514 	atf_tc_set_md_var(tc, "require.config", "unprivileged_user");
515 }
516 ATF_TC_BODY(multibind, tc)
517 {
518 	multibind_test(tc, AF_INET, SOCK_STREAM);
519 	multibind_test(tc, AF_INET, SOCK_DGRAM);
520 	multibind_test(tc, AF_INET6, SOCK_STREAM);
521 	multibind_test(tc, AF_INET6, SOCK_DGRAM);
522 }
523 
524 /*
525  * Test operation of bind(2) in presence of a connected inpcb using the
526  * same local port.
527  */
528 static enum bind_res
529 bind_connected_port_test(const atf_tc_t *tc, int domain, int type, bool wild,
530     bool unpriv)
531 {
532 	struct sockaddr_in sin;
533 	struct sockaddr_in6 sin6;
534 	struct sockaddr *sinp;
535 	socklen_t slen;
536 	int error, ss, cs, as;
537 	enum bind_res res;
538 
539 	/*
540 	 * Create a connected socket pair.
541 	 */
542 	ss = socket(domain, type, 0);
543 	ATF_REQUIRE_MSG(ss >= 0, "socket failed: %s", strerror(errno));
544 	if (domain == PF_INET) {
545 		memset(&sin, 0, sizeof(sin));
546 		sin.sin_family = AF_INET;
547 		sin.sin_len = sizeof(sin);
548 		sin.sin_addr.s_addr = htonl(INADDR_ANY);
549 		sin.sin_port = htons(0);
550 		sinp = (struct sockaddr *)&sin;
551 	} else {
552 		ATF_REQUIRE(domain == PF_INET6);
553 		memset(&sin6, 0, sizeof(sin6));
554 		sin6.sin6_family = AF_INET6;
555 		sin6.sin6_len = sizeof(sin6);
556 		sin6.sin6_addr = in6addr_any;
557 		sin6.sin6_port = htons(0);
558 		sinp = (struct sockaddr *)&sin6;
559 	}
560 
561 	error = bind(ss, sinp, sinp->sa_len);
562 	ATF_REQUIRE_MSG(error == 0, "bind failed: %s", strerror(errno));
563 
564 	if (type == SOCK_STREAM) {
565 		error = getsockname(ss, sinp, &(socklen_t){ sinp->sa_len });
566 		ATF_REQUIRE_MSG(error == 0, "getsockname failed: %s",
567 		    strerror(errno));
568 		error = listen(ss, 1);
569 		ATF_REQUIRE_MSG(error == 0,
570 		    "listen failed: %s", strerror(errno));
571 		cs = socket(domain, type, 0);
572 		ATF_REQUIRE_MSG(cs >= 0, "socket failed: %s", strerror(errno));
573 		if (domain == PF_INET)
574 			sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
575 		else
576 			sin6.sin6_addr = in6addr_loopback;
577 		error = connect(cs, sinp, sinp->sa_len);
578 		ATF_REQUIRE_MSG(error == 0,
579 		    "connect failed: %s", strerror(errno));
580 		slen = sinp->sa_len;
581 		as = accept(ss, sinp, &slen);
582 		ATF_REQUIRE_MSG(as >= 0, "accept failed: %s", strerror(errno));
583 	} else {
584 		ATF_REQUIRE(type == SOCK_DGRAM);
585 		if (domain == PF_INET) {
586 			sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
587 			sin.sin_port = htons(6666);
588 		} else {
589 			sin6.sin6_addr = in6addr_loopback;
590 			sin6.sin6_port = htons(6666);
591 		}
592 		error = connect(ss, sinp, sinp->sa_len);
593 		ATF_REQUIRE_MSG(error == 0,
594 		    "connect failed: %s", strerror(errno));
595 		error = getsockname(ss, sinp, &(socklen_t){ sinp->sa_len });
596 		ATF_REQUIRE_MSG(error == 0, "getsockname failed: %s",
597 		    strerror(errno));
598 	}
599 
600 	if (wild) {
601 		if (domain == PF_INET)
602 			sin.sin_addr.s_addr = htonl(INADDR_ANY);
603 		else
604 			sin6.sin6_addr = in6addr_any;
605 	}
606 
607 	res = child_bind(tc, type, sinp, SO_REUSEADDR, unpriv);
608 
609 	if (type == SOCK_STREAM) {
610 		ATF_REQUIRE(close(as) == 0);
611 		ATF_REQUIRE(close(cs) == 0);
612 	}
613 	ATF_REQUIRE(close(ss) == 0);
614 
615 	return (res);
616 }
617 
618 /*
619  * Normally bind() prevents port stealing by a different user, even when
620  * SO_REUSE* are specified.  However, if the port is bound by a connected
621  * socket, then it's fair game.
622  */
623 ATF_TC(bind_connected_port);
624 ATF_TC_HEAD(bind_connected_port, tc)
625 {
626 	atf_tc_set_md_var(tc, "require.user", "root");
627 	atf_tc_set_md_var(tc, "require.config", "unprivileged_user");
628 }
629 ATF_TC_BODY(bind_connected_port, tc)
630 {
631 	struct bind_connected_port_res {
632 		int domain;
633 		int type;
634 		bool wild;
635 		bool unpriv;
636 		enum bind_res result;
637 	} tests[] = {
638 #define	x true
639 #define	o false
640 				     /* W  U */
641 	    { AF_INET,	SOCK_STREAM,	x, x, BIND_REUSE_SUCCESS },
642 	    { AF_INET,	SOCK_STREAM,	o, x, BIND_REUSE_SUCCESS },
643 	    { AF_INET,	SOCK_STREAM,	x, o, BIND_REUSE_SUCCESS },
644 	    { AF_INET,	SOCK_STREAM,	o, o, BIND_REUSE_SUCCESS },
645 	    { AF_INET6,	SOCK_STREAM,	x, x, BIND_REUSE_SUCCESS },
646 	    { AF_INET6,	SOCK_STREAM,	o, x, BIND_REUSE_SUCCESS },
647 	    { AF_INET6,	SOCK_STREAM,	x, o, BIND_REUSE_SUCCESS },
648 	    { AF_INET6,	SOCK_STREAM,	o, o, BIND_REUSE_SUCCESS },
649 	    { AF_INET,	SOCK_DGRAM,	x, x, BIND_FAILED },
650 	    { AF_INET,	SOCK_DGRAM,	o, x, BIND_FAILED },
651 	    { AF_INET,	SOCK_DGRAM,	x, o, BIND_REUSE_SUCCESS },
652 	    { AF_INET,	SOCK_DGRAM,	o, o, BIND_REUSE_SUCCESS },
653 	    { AF_INET6,	SOCK_DGRAM,	x, x, BIND_FAILED },
654 	    { AF_INET6,	SOCK_DGRAM,	o, x, BIND_FAILED },
655 	    { AF_INET6,	SOCK_DGRAM,	x, o, BIND_REUSE_SUCCESS },
656 	    { AF_INET6,	SOCK_DGRAM,	o, o, BIND_REUSE_SUCCESS },
657 #undef x
658 #undef o
659 	};
660 
661 	for (u_int i = 0; i < nitems(tests); i++) {
662 		enum bind_res res;
663 
664 		res = bind_connected_port_test(tc, tests[i].domain,
665 		    tests[i].type, tests[i].wild, tests[i].unpriv);
666 		ATF_REQUIRE_MSG(res == tests[i].result, "test #%u: "
667 		    "domain %u type %u%s %sprivileged: result %u (expected %u)",
668 		    i, tests[i].domain, tests[i].type,
669 		    tests[i].wild ? " wild" : "",
670 		    tests[i].unpriv ? "un" : "",
671 		    res, tests[i].result);
672 	}
673 }
674 
675 ATF_TP_ADD_TCS(tp)
676 {
677 	ATF_TP_ADD_TC(tp, basic);
678 	ATF_TP_ADD_TC(tp, bind_zero);
679 	ATF_TP_ADD_TC(tp, bind_ok);
680 	ATF_TP_ADD_TC(tp, poll_no_rdhup);
681 	ATF_TP_ADD_TC(tp, poll_rdhup);
682 	ATF_TP_ADD_TC(tp, stream_reconnect);
683 	ATF_TP_ADD_TC(tp, bindany);
684 	ATF_TP_ADD_TC(tp, multibind);
685 	ATF_TP_ADD_TC(tp, bind_connected_port);
686 
687 	return atf_no_error();
688 }
689