xref: /freebsd/tests/sys/kern/unix_dgram.c (revision 70d07b20897be6febcf6d2fcbe95c2f34eae48b0)
16d317723SGleb Smirnoff /*-
26d317723SGleb Smirnoff  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
36d317723SGleb Smirnoff  *
46d317723SGleb Smirnoff  * Copyright (c) 2022 Gleb Smirnoff <glebius@FreeBSD.org>
56d317723SGleb Smirnoff  *
66d317723SGleb Smirnoff  * Redistribution and use in source and binary forms, with or without
76d317723SGleb Smirnoff  * modification, are permitted provided that the following conditions
86d317723SGleb Smirnoff  * are met:
96d317723SGleb Smirnoff  * 1. Redistributions of source code must retain the above copyright
106d317723SGleb Smirnoff  *    notice, this list of conditions and the following disclaimer.
116d317723SGleb Smirnoff  * 2. Redistributions in binary form must reproduce the above copyright
126d317723SGleb Smirnoff  *    notice, this list of conditions and the following disclaimer in the
136d317723SGleb Smirnoff  *    documentation and/or other materials provided with the distribution.
146d317723SGleb Smirnoff  *
156d317723SGleb Smirnoff  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
166d317723SGleb Smirnoff  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
176d317723SGleb Smirnoff  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
186d317723SGleb Smirnoff  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
196d317723SGleb Smirnoff  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
206d317723SGleb Smirnoff  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
216d317723SGleb Smirnoff  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
226d317723SGleb Smirnoff  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
236d317723SGleb Smirnoff  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
246d317723SGleb Smirnoff  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
256d317723SGleb Smirnoff  * SUCH DAMAGE.
266d317723SGleb Smirnoff  */
276d317723SGleb Smirnoff 
286d317723SGleb Smirnoff #include <sys/time.h>
29*70d07b20SGleb Smirnoff #include <sys/event.h>
30*70d07b20SGleb Smirnoff #include <sys/ioctl.h>
31*70d07b20SGleb Smirnoff #include <sys/select.h>
326d317723SGleb Smirnoff #include <sys/socket.h>
336d317723SGleb Smirnoff #include <sys/sysctl.h>
346d317723SGleb Smirnoff #include <sys/un.h>
35*70d07b20SGleb Smirnoff #include <aio.h>
366d317723SGleb Smirnoff #include <errno.h>
376d317723SGleb Smirnoff #include <fcntl.h>
386d317723SGleb Smirnoff #include <signal.h>
396d317723SGleb Smirnoff #include <stdlib.h>
406d317723SGleb Smirnoff 
416d317723SGleb Smirnoff #include <atf-c.h>
426d317723SGleb Smirnoff 
436d317723SGleb Smirnoff static struct itimerval itv = {
446d317723SGleb Smirnoff 	.it_interval = { 0, 0 },
456d317723SGleb Smirnoff 	.it_value = { 1, 0 },	/* one second */
466d317723SGleb Smirnoff };
476d317723SGleb Smirnoff static sig_atomic_t timer_done = 0;
486d317723SGleb Smirnoff static void
496d317723SGleb Smirnoff sigalarm(int sig __unused)
506d317723SGleb Smirnoff {
516d317723SGleb Smirnoff 
526d317723SGleb Smirnoff 	timer_done = 1;
536d317723SGleb Smirnoff }
546d317723SGleb Smirnoff 
556d317723SGleb Smirnoff static struct sigaction sigact = {
566d317723SGleb Smirnoff 	.sa_handler = sigalarm,
576d317723SGleb Smirnoff };
586d317723SGleb Smirnoff 
59*70d07b20SGleb Smirnoff static struct sockaddr_un sun = {
60*70d07b20SGleb Smirnoff 	.sun_family = AF_LOCAL,
61*70d07b20SGleb Smirnoff 	.sun_len = sizeof(sun),
62*70d07b20SGleb Smirnoff 	.sun_path = "unix_dgram_listener",
63*70d07b20SGleb Smirnoff };
64*70d07b20SGleb Smirnoff 
656d317723SGleb Smirnoff /*
666d317723SGleb Smirnoff  * Fill socket to a state when next send(len) would fail.
67aa9f97afSGleb Smirnoff  *
68aa9f97afSGleb Smirnoff  * Note that every datagram is prepended with sender address,
69aa9f97afSGleb Smirnoff  * size of struct sockaddr.
706d317723SGleb Smirnoff  */
716d317723SGleb Smirnoff static void
726d317723SGleb Smirnoff fill(int fd, void *buf, ssize_t len)
736d317723SGleb Smirnoff {
746d317723SGleb Smirnoff 	unsigned long recvspace;
756d317723SGleb Smirnoff 	size_t llen = sizeof(unsigned long);
766d317723SGleb Smirnoff 	ssize_t sent;
776d317723SGleb Smirnoff 
786d317723SGleb Smirnoff 	ATF_REQUIRE(sysctlbyname("net.local.dgram.recvspace", &recvspace,
796d317723SGleb Smirnoff 	    &llen, NULL, 0) == 0);
80aa9f97afSGleb Smirnoff 	for (sent = 0;
81aa9f97afSGleb Smirnoff 	    sent + len + sizeof(struct sockaddr) < recvspace;
82aa9f97afSGleb Smirnoff 	    sent += len + sizeof(struct sockaddr))
836d317723SGleb Smirnoff 		ATF_REQUIRE(send(fd, buf, len, 0) == len);
846d317723SGleb Smirnoff }
856d317723SGleb Smirnoff 
866d317723SGleb Smirnoff ATF_TC_WITHOUT_HEAD(basic);
876d317723SGleb Smirnoff ATF_TC_BODY(basic, tc)
886d317723SGleb Smirnoff {
896d317723SGleb Smirnoff 	struct msghdr msg;
906d317723SGleb Smirnoff 	struct iovec iov[1];
916d317723SGleb Smirnoff 	unsigned long maxdgram;
926d317723SGleb Smirnoff 	size_t llen = sizeof(unsigned long);
936d317723SGleb Smirnoff 	int fd[2];
946d317723SGleb Smirnoff 	char *buf;
956d317723SGleb Smirnoff 
966d317723SGleb Smirnoff 	/* Allocate and initialize:
976d317723SGleb Smirnoff 	 * - fd[0] to send, fd[1] to receive
986d317723SGleb Smirnoff 	 * - buf[maxdgram] for data
996d317723SGleb Smirnoff 	 */
1006d317723SGleb Smirnoff 	ATF_REQUIRE(sysctlbyname("net.local.dgram.maxdgram", &maxdgram,
1016d317723SGleb Smirnoff 	    &llen, NULL, 0) == 0);
1026d317723SGleb Smirnoff 	ATF_REQUIRE(socketpair(PF_UNIX, SOCK_DGRAM, 0, fd) != -1);
1036d317723SGleb Smirnoff 	buf = malloc(maxdgram + 1);
1046d317723SGleb Smirnoff 	ATF_REQUIRE(buf);
1056d317723SGleb Smirnoff 	msg = (struct msghdr ){
1066d317723SGleb Smirnoff 		.msg_iov = iov,
1076d317723SGleb Smirnoff 		.msg_iovlen = 1,
1086d317723SGleb Smirnoff 	};
1096d317723SGleb Smirnoff 	iov[0] = (struct iovec ){
1106d317723SGleb Smirnoff 		.iov_base = buf,
1116d317723SGleb Smirnoff 	};
1126d317723SGleb Smirnoff 
1136d317723SGleb Smirnoff 	/* Fail to send > maxdgram. */
1146d317723SGleb Smirnoff 	ATF_REQUIRE(send(fd[0], buf, maxdgram + 1, 0) == -1);
1156d317723SGleb Smirnoff 	ATF_REQUIRE(errno == EMSGSIZE);
1166d317723SGleb Smirnoff 
1176d317723SGleb Smirnoff 	/* Send maxdgram. */
1186d317723SGleb Smirnoff 	ATF_REQUIRE(send(fd[0], buf, maxdgram, 0) == (ssize_t)maxdgram);
1196d317723SGleb Smirnoff 
1206d317723SGleb Smirnoff 	/* Exercise MSG_PEEK, full and truncated.. */
1216d317723SGleb Smirnoff 	ATF_REQUIRE(recv(fd[1], buf, maxdgram, MSG_PEEK) == (ssize_t)maxdgram);
1226d317723SGleb Smirnoff 	iov[0].iov_len = 42;
1236d317723SGleb Smirnoff 	ATF_REQUIRE(recvmsg(fd[1], &msg, MSG_PEEK) == 42);
1246d317723SGleb Smirnoff 	ATF_REQUIRE(msg.msg_flags == (MSG_PEEK | MSG_TRUNC));
1256d317723SGleb Smirnoff 
1266d317723SGleb Smirnoff 	/* Receive maxdgram. */
1276d317723SGleb Smirnoff 	iov[0].iov_len = maxdgram;
1286d317723SGleb Smirnoff 	ATF_REQUIRE(recvmsg(fd[1], &msg, 0) == (ssize_t)maxdgram);
1296d317723SGleb Smirnoff 	ATF_REQUIRE(msg.msg_flags == 0);
1306d317723SGleb Smirnoff 
1316d317723SGleb Smirnoff 	/* Receive truncated message. */
1326d317723SGleb Smirnoff 	ATF_REQUIRE(send(fd[0], buf, maxdgram, 0) == (ssize_t)maxdgram);
1336d317723SGleb Smirnoff 	iov[0].iov_len = maxdgram / 2;
1346d317723SGleb Smirnoff 	ATF_REQUIRE(recvmsg(fd[1], &msg, 0) == (ssize_t)maxdgram / 2);
1356d317723SGleb Smirnoff 	ATF_REQUIRE(msg.msg_flags == MSG_TRUNC);
1366d317723SGleb Smirnoff 
1376d317723SGleb Smirnoff 	/* Empty: block. */
1386d317723SGleb Smirnoff 	ATF_REQUIRE(sigaction(SIGALRM, &sigact, NULL) == 0);
1396d317723SGleb Smirnoff 	ATF_REQUIRE(timer_done == 0);
1406d317723SGleb Smirnoff 	ATF_REQUIRE(setitimer(ITIMER_REAL, &itv, NULL) == 0);
1416d317723SGleb Smirnoff 	ATF_REQUIRE(recv(fd[1], buf, maxdgram, 0) == -1);
1426d317723SGleb Smirnoff 	ATF_REQUIRE(errno == EINTR);
1436d317723SGleb Smirnoff 	ATF_REQUIRE(timer_done == 1);
1446d317723SGleb Smirnoff 
1456d317723SGleb Smirnoff 	/* Don't block with MSG_DONTWAIT. */
1466d317723SGleb Smirnoff 	ATF_REQUIRE(recv(fd[1], buf, maxdgram, MSG_DONTWAIT) == -1);
1476d317723SGleb Smirnoff 	ATF_REQUIRE(errno == EAGAIN);
1486d317723SGleb Smirnoff 
1496d317723SGleb Smirnoff 	/* Don't block with O_NONBLOCK. */
1506d317723SGleb Smirnoff 	ATF_REQUIRE(fcntl(fd[1], F_SETFL, O_NONBLOCK) != -1);
1516d317723SGleb Smirnoff 	ATF_REQUIRE(recv(fd[1], buf, maxdgram, 0) == -1);
1526d317723SGleb Smirnoff 	ATF_REQUIRE(errno == EAGAIN);
1536d317723SGleb Smirnoff 
1546d317723SGleb Smirnoff 	/* Fail with ENOBUFS on full socket. */
1556d317723SGleb Smirnoff 	fill(fd[0], buf, maxdgram);
1566d317723SGleb Smirnoff 	ATF_REQUIRE(send(fd[0], buf, maxdgram, 0) == -1);
1576d317723SGleb Smirnoff 	ATF_REQUIRE(errno == ENOBUFS);
1586d317723SGleb Smirnoff 
1596d317723SGleb Smirnoff 	/* Fail with EAGAIN with O_NONBLOCK set. */
1606d317723SGleb Smirnoff 	ATF_REQUIRE(fcntl(fd[0], F_SETFL, O_NONBLOCK) != -1);
1616d317723SGleb Smirnoff 	ATF_REQUIRE(send(fd[0], buf, maxdgram, 0) == -1);
1626d317723SGleb Smirnoff 	ATF_REQUIRE(errno == EAGAIN);
1636d317723SGleb Smirnoff 
1646d317723SGleb Smirnoff 	/* Remote side closed -> ECONNRESET. */
1656d317723SGleb Smirnoff 	close(fd[1]);
1666d317723SGleb Smirnoff 	ATF_REQUIRE(send(fd[0], buf, maxdgram, 0) == -1);
1676d317723SGleb Smirnoff 	ATF_REQUIRE(errno == ECONNRESET);
1686d317723SGleb Smirnoff }
1696d317723SGleb Smirnoff 
1706d317723SGleb Smirnoff ATF_TC_WITHOUT_HEAD(one2many);
1716d317723SGleb Smirnoff ATF_TC_BODY(one2many, tc)
1726d317723SGleb Smirnoff {
1736d317723SGleb Smirnoff 	int one, many[2], two;
1746d317723SGleb Smirnoff 	char buf[1024];
1756d317723SGleb Smirnoff 
1766d317723SGleb Smirnoff 	/* Establish one to many connection. */
1776d317723SGleb Smirnoff 	ATF_REQUIRE((one = socket(PF_UNIX, SOCK_DGRAM, 0)) > 0);
1786d317723SGleb Smirnoff 	ATF_REQUIRE(bind(one, (struct sockaddr *)&sun, sizeof(sun)) == 0);
1796d317723SGleb Smirnoff 	/* listen(2) shall fail. */
1806d317723SGleb Smirnoff 	ATF_REQUIRE(listen(one, -1) != 0);
1816d317723SGleb Smirnoff 	for (int i = 0; i < 2; i++) {
1826d317723SGleb Smirnoff 		ATF_REQUIRE((many[i] = socket(PF_UNIX, SOCK_DGRAM, 0)) > 0);
1836d317723SGleb Smirnoff 		ATF_REQUIRE(connect(many[i], (struct sockaddr *)&sun,
1846d317723SGleb Smirnoff 		    sizeof(sun)) == 0);
1856d317723SGleb Smirnoff 	}
1866d317723SGleb Smirnoff 
1876d317723SGleb Smirnoff 	/* accept() on UNIX/DGRAM is invalid. */
1886d317723SGleb Smirnoff 	ATF_REQUIRE(accept(one, NULL, NULL) == -1);
1896d317723SGleb Smirnoff 	ATF_REQUIRE(errno == EINVAL);
1906d317723SGleb Smirnoff 
1916d317723SGleb Smirnoff 	/*
1926d317723SGleb Smirnoff 	 * Connecting a bound socket to self: a strange, useless, but
1936d317723SGleb Smirnoff 	 * historically existing edge case that is not explicitly described
1946d317723SGleb Smirnoff 	 * in SuS, neither is forbidden there. Works on FreeBSD and Linux.
1956d317723SGleb Smirnoff 	 */
1966d317723SGleb Smirnoff 	ATF_REQUIRE(connect(one, (struct sockaddr *)&sun, sizeof(sun)) == 0);
1976d317723SGleb Smirnoff 	ATF_REQUIRE(send(one, buf, 42, 0) == 42);
1986d317723SGleb Smirnoff 	ATF_REQUIRE(recv(one, buf, sizeof(buf), 0) == 42);
1996d317723SGleb Smirnoff 
2006d317723SGleb Smirnoff 	/*
2016d317723SGleb Smirnoff 	 * Sending from an unconnected socket to a bound socket.  Connection is
2026d317723SGleb Smirnoff 	 * created for the duration of the syscall.
2036d317723SGleb Smirnoff 	 */
2046d317723SGleb Smirnoff 	ATF_REQUIRE((two = socket(PF_UNIX, SOCK_DGRAM, 0)) > 0);
2056d317723SGleb Smirnoff 	ATF_REQUIRE(sendto(two, buf, 43, 0, (struct sockaddr *)&sun,
2066d317723SGleb Smirnoff 	    sizeof(sun)) == 43);
2076d317723SGleb Smirnoff 	ATF_REQUIRE(recv(one, buf, sizeof(buf), 0) == 43);
2086d317723SGleb Smirnoff 
2096d317723SGleb Smirnoff 	/* One sender can fill the receive side.
2106d317723SGleb Smirnoff 	 * Current behavior which needs improvement.
2116d317723SGleb Smirnoff 	 */
2126d317723SGleb Smirnoff 	fill(many[0], buf, sizeof(buf));
2136d317723SGleb Smirnoff 	ATF_REQUIRE(send(many[1], buf, sizeof(buf), 0) == -1);
2146d317723SGleb Smirnoff 	ATF_REQUIRE(errno == ENOBUFS);
2156d317723SGleb Smirnoff 	ATF_REQUIRE(recv(one, buf, sizeof(buf), 0) == sizeof(buf));
2166d317723SGleb Smirnoff 	ATF_REQUIRE(send(many[1], buf, sizeof(buf), 0) == sizeof(buf));
2176d317723SGleb Smirnoff }
2186d317723SGleb Smirnoff 
219*70d07b20SGleb Smirnoff /*
220*70d07b20SGleb Smirnoff  * Check that various mechanism report socket as readable and having
221*70d07b20SGleb Smirnoff  * 42 bytes of data.
222*70d07b20SGleb Smirnoff  */
223*70d07b20SGleb Smirnoff static void
224*70d07b20SGleb Smirnoff test42(int fd)
225*70d07b20SGleb Smirnoff {
226*70d07b20SGleb Smirnoff 
227*70d07b20SGleb Smirnoff 	/* ioctl(FIONREAD) */
228*70d07b20SGleb Smirnoff 	int data;
229*70d07b20SGleb Smirnoff 
230*70d07b20SGleb Smirnoff 	ATF_REQUIRE(ioctl(fd, FIONREAD, &data) != -1);
231*70d07b20SGleb Smirnoff 	ATF_REQUIRE(data == 42);
232*70d07b20SGleb Smirnoff 
233*70d07b20SGleb Smirnoff 	/* select(2) */
234*70d07b20SGleb Smirnoff 	fd_set rfds;
235*70d07b20SGleb Smirnoff 
236*70d07b20SGleb Smirnoff 	FD_ZERO(&rfds);
237*70d07b20SGleb Smirnoff 	FD_SET(fd, &rfds);
238*70d07b20SGleb Smirnoff 	ATF_REQUIRE(select(fd + 1, &rfds, NULL, NULL, NULL) == 1);
239*70d07b20SGleb Smirnoff 	ATF_REQUIRE(FD_ISSET(fd, &rfds));
240*70d07b20SGleb Smirnoff 
241*70d07b20SGleb Smirnoff 	/* kevent(2) */
242*70d07b20SGleb Smirnoff 	struct kevent ev;
243*70d07b20SGleb Smirnoff 	int kq;
244*70d07b20SGleb Smirnoff 
245*70d07b20SGleb Smirnoff 	ATF_REQUIRE((kq = kqueue()) != -1);
246*70d07b20SGleb Smirnoff 	EV_SET(&ev, fd, EVFILT_READ, EV_ADD, NOTE_LOWAT, 41, NULL);
247*70d07b20SGleb Smirnoff 	ATF_REQUIRE(kevent(kq, &ev, 1, NULL, 0, NULL) == 0);
248*70d07b20SGleb Smirnoff 	ATF_REQUIRE(kevent(kq, NULL, 0, &ev, 1, NULL) == 1);
249*70d07b20SGleb Smirnoff 	ATF_REQUIRE(ev.filter == EVFILT_READ);
250*70d07b20SGleb Smirnoff 	ATF_REQUIRE(ev.data == 42);
251*70d07b20SGleb Smirnoff 
252*70d07b20SGleb Smirnoff 	/* aio(4) */
253*70d07b20SGleb Smirnoff 	char buf[50];
254*70d07b20SGleb Smirnoff 	struct aiocb aio = {
255*70d07b20SGleb Smirnoff 		.aio_nbytes = 50,
256*70d07b20SGleb Smirnoff 		.aio_fildes = fd,
257*70d07b20SGleb Smirnoff 		.aio_buf = buf,
258*70d07b20SGleb Smirnoff 	}, *aiop;
259*70d07b20SGleb Smirnoff 
260*70d07b20SGleb Smirnoff 	ATF_REQUIRE(aio_read(&aio) == 0);
261*70d07b20SGleb Smirnoff 	ATF_REQUIRE(aio_waitcomplete(&aiop, NULL) == 42);
262*70d07b20SGleb Smirnoff 	ATF_REQUIRE(aiop == &aio);
263*70d07b20SGleb Smirnoff }
264*70d07b20SGleb Smirnoff 
265*70d07b20SGleb Smirnoff /*
266*70d07b20SGleb Smirnoff  * Send data and control in connected & unconnected mode and check that
267*70d07b20SGleb Smirnoff  * various event mechanisms see the data, but don't count control bytes.
268*70d07b20SGleb Smirnoff  */
269*70d07b20SGleb Smirnoff ATF_TC_WITHOUT_HEAD(event);
270*70d07b20SGleb Smirnoff ATF_TC_BODY(event, tc)
271*70d07b20SGleb Smirnoff {
272*70d07b20SGleb Smirnoff 	int fd[2];
273*70d07b20SGleb Smirnoff 	char buf[50];
274*70d07b20SGleb Smirnoff 	struct iovec iov = {
275*70d07b20SGleb Smirnoff 		.iov_base = buf,
276*70d07b20SGleb Smirnoff 		.iov_len = 42,
277*70d07b20SGleb Smirnoff 	};
278*70d07b20SGleb Smirnoff 	struct cmsghdr cmsg = {
279*70d07b20SGleb Smirnoff 		.cmsg_len = CMSG_LEN(0),
280*70d07b20SGleb Smirnoff 		.cmsg_level = SOL_SOCKET,
281*70d07b20SGleb Smirnoff 		.cmsg_type = SCM_TIMESTAMP,
282*70d07b20SGleb Smirnoff 	};
283*70d07b20SGleb Smirnoff 	struct msghdr msghdr = {
284*70d07b20SGleb Smirnoff 		.msg_iov = &iov,
285*70d07b20SGleb Smirnoff 		.msg_iovlen = 1,
286*70d07b20SGleb Smirnoff 		.msg_control = &cmsg,
287*70d07b20SGleb Smirnoff 		.msg_controllen = CMSG_LEN(0),
288*70d07b20SGleb Smirnoff 	};
289*70d07b20SGleb Smirnoff 
290*70d07b20SGleb Smirnoff 	/* Connected socket */
291*70d07b20SGleb Smirnoff 	ATF_REQUIRE(socketpair(PF_UNIX, SOCK_DGRAM, 0, fd) != -1);
292*70d07b20SGleb Smirnoff 	ATF_REQUIRE(sendmsg(fd[0], &msghdr, 0) == 42);
293*70d07b20SGleb Smirnoff 	test42(fd[1]);
294*70d07b20SGleb Smirnoff 	close(fd[0]);
295*70d07b20SGleb Smirnoff 	close(fd[1]);
296*70d07b20SGleb Smirnoff 
297*70d07b20SGleb Smirnoff 	/* Not-connected send */
298*70d07b20SGleb Smirnoff 	ATF_REQUIRE((fd[0] = socket(PF_UNIX, SOCK_DGRAM, 0)) > 0);
299*70d07b20SGleb Smirnoff 	ATF_REQUIRE((fd[1] = socket(PF_UNIX, SOCK_DGRAM, 0)) > 0);
300*70d07b20SGleb Smirnoff 	ATF_REQUIRE(bind(fd[0], (struct sockaddr *)&sun, sizeof(sun)) == 0);
301*70d07b20SGleb Smirnoff 	ATF_REQUIRE(sendto(fd[1], buf, 42, 0, (struct sockaddr *)&sun,
302*70d07b20SGleb Smirnoff 	    sizeof(sun)) == 42);
303*70d07b20SGleb Smirnoff 	test42(fd[0]);
304*70d07b20SGleb Smirnoff }
305*70d07b20SGleb Smirnoff 
3066d317723SGleb Smirnoff ATF_TP_ADD_TCS(tp)
3076d317723SGleb Smirnoff {
3086d317723SGleb Smirnoff 
3096d317723SGleb Smirnoff 	ATF_TP_ADD_TC(tp, basic);
3106d317723SGleb Smirnoff 	ATF_TP_ADD_TC(tp, one2many);
311*70d07b20SGleb Smirnoff 	ATF_TP_ADD_TC(tp, event);
3126d317723SGleb Smirnoff 
3136d317723SGleb Smirnoff 	return (atf_no_error());
3146d317723SGleb Smirnoff }
315