1261081Sasomers/*-
2261081Sasomers * Copyright (c) 2014 Spectra Logic Corporation. All rights reserved.
3261081Sasomers * Redistribution and use in source and binary forms, with or without
4261081Sasomers * modification, are permitted provided that the following conditions
5261081Sasomers * are met:
6261081Sasomers * 1. Redistributions of source code must retain the above copyright
7261081Sasomers *    notice, this list of conditions and the following disclaimer.
8261081Sasomers * 2. Redistributions in binary form must reproduce the above copyright
9261081Sasomers *    notice, this list of conditions and the following disclaimer in the
10261081Sasomers *    documentation and/or other materials provided with the distribution.
11261081Sasomers *
12261081Sasomers * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
13261081Sasomers * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14261081Sasomers * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
15261081Sasomers * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
16261081Sasomers * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
17261081Sasomers * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
18261081Sasomers * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
19261081Sasomers * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
20261081Sasomers * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
21261081Sasomers * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
22261081Sasomers * SUCH DAMAGE.
23261081Sasomers */
24261081Sasomers
25261081Sasomers#include <sys/cdefs.h>
26261081Sasomers__FBSDID("$FreeBSD: stable/11/tests/sys/kern/unix_seqpacket_test.c 321165 2017-07-18 18:51:34Z ngie $");
27261081Sasomers
28261081Sasomers#include <errno.h>
29261081Sasomers#include <fcntl.h>
30261081Sasomers#include <pthread.h>
31261081Sasomers#include <signal.h>
32261081Sasomers#include <sys/socket.h>
33261081Sasomers#include <sys/un.h>
34261081Sasomers
35261081Sasomers#include <stdio.h>
36261081Sasomers
37261081Sasomers#include <atf-c.h>
38261081Sasomers
39261081Sasomers/*
40261081Sasomers * Helper functions
41261081Sasomers */
42261081Sasomers
43261081Sasomers#define MIN(x, y)	((x) < (y) ? (x) : (y))
44261081Sasomers#define MAX(x, y)	((x) > (y) ? (x) : (y))
45261081Sasomers
46262894Sasomersstatic void
47261081Sasomersdo_socketpair(int *sv)
48261081Sasomers{
49261081Sasomers	int s;
50292820Sngie
51261081Sasomers	s = socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, sv);
52261081Sasomers	ATF_REQUIRE_EQ(0, s);
53261081Sasomers	ATF_REQUIRE(sv[0] >= 0);
54261081Sasomers	ATF_REQUIRE(sv[1] >= 0);
55261081Sasomers	ATF_REQUIRE(sv[0] != sv[1]);
56261081Sasomers}
57261081Sasomers
58262894Sasomersstatic void
59261081Sasomersdo_socketpair_nonblocking(int *sv)
60261081Sasomers{
61261081Sasomers	int s;
62292820Sngie
63261081Sasomers	s = socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, sv);
64261081Sasomers	ATF_REQUIRE_EQ(0, s);
65261081Sasomers	ATF_REQUIRE(sv[0] >= 0);
66261081Sasomers	ATF_REQUIRE(sv[1] >= 0);
67261081Sasomers	ATF_REQUIRE(sv[0] != sv[1]);
68261081Sasomers	ATF_REQUIRE(-1 != fcntl(sv[0], F_SETFL, O_NONBLOCK));
69261081Sasomers	ATF_REQUIRE(-1 != fcntl(sv[1], F_SETFL, O_NONBLOCK));
70261081Sasomers}
71261081Sasomers
72292820Sngie/*
73261081Sasomers * Returns a pair of sockets made the hard way: bind, listen, connect & accept
74261081Sasomers * @return	const char* The path to the socket
75261081Sasomers */
76262894Sasomersstatic const char*
77261081Sasomersmk_pair_of_sockets(int *sv)
78261081Sasomers{
79261081Sasomers	struct sockaddr_un sun;
80261081Sasomers	/* ATF's isolation mechanisms will guarantee uniqueness of this file */
81261081Sasomers	const char *path = "sock";
82261081Sasomers	int s, err, s2, s1;
83261081Sasomers
84261081Sasomers	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
85261081Sasomers	ATF_REQUIRE(s >= 0);
86261081Sasomers
87261081Sasomers	bzero(&sun, sizeof(sun));
88261081Sasomers	sun.sun_family = AF_LOCAL;
89261081Sasomers	sun.sun_len = sizeof(sun);
90261081Sasomers	strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
91261081Sasomers	err = bind(s, (struct sockaddr *)&sun, sizeof(sun));
92261081Sasomers	err = listen(s, -1);
93261081Sasomers	ATF_CHECK_EQ(0, err);
94261081Sasomers
95261081Sasomers	/* Create the other socket */
96261081Sasomers	s2 = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
97261081Sasomers	ATF_REQUIRE(s2 >= 0);
98261081Sasomers	err = connect(s2, (struct sockaddr*)&sun, sizeof(sun));
99261081Sasomers	if (err != 0) {
100261081Sasomers		perror("connect");
101261081Sasomers		atf_tc_fail("connect(2) failed");
102261081Sasomers	}
103292820Sngie
104261081Sasomers	/* Accept it */
105261081Sasomers	s1 = accept(s, NULL, NULL);
106261081Sasomers	if (s1 == -1) {
107261081Sasomers		perror("accept");
108261081Sasomers		atf_tc_fail("accept(2) failed");
109261081Sasomers	}
110261081Sasomers
111261081Sasomers	sv[0] = s1;
112261081Sasomers	sv[1] = s2;
113270228Sasomers
114270228Sasomers	close(s);
115270228Sasomers
116261081Sasomers	return (path);
117261081Sasomers}
118261081Sasomers
119261081Sasomersstatic volatile sig_atomic_t got_sigpipe = 0;
120261081Sasomersstatic void
121262894Sasomersshutdown_send_sigpipe_handler(int __unused x)
122261081Sasomers{
123261081Sasomers	got_sigpipe = 1;
124261081Sasomers}
125261081Sasomers
126261081Sasomers/*
127261081Sasomers * Parameterized test function bodies
128261081Sasomers */
129262894Sasomersstatic void
130317831Sbrookstest_eagain(int sndbufsize, int rcvbufsize)
131261081Sasomers{
132261081Sasomers	int i;
133261081Sasomers	int sv[2];
134261081Sasomers	const size_t totalsize = (sndbufsize + rcvbufsize) * 2;
135261081Sasomers	const size_t pktsize = MIN(sndbufsize, rcvbufsize) / 4;
136262894Sasomers	const int numpkts = totalsize / pktsize;
137261081Sasomers	char sndbuf[pktsize];
138262894Sasomers	ssize_t ssize;
139261081Sasomers
140261081Sasomers	/* setup the socket pair */
141262133Sasomers	do_socketpair_nonblocking(sv);
142261081Sasomers	/* Setup the buffers */
143261081Sasomers	ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
144261081Sasomers	    sizeof(sndbufsize)));
145261081Sasomers	ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
146261081Sasomers	    sizeof(rcvbufsize)));
147261081Sasomers
148261081Sasomers	bzero(sndbuf, pktsize);
149261081Sasomers	/* Send data until we get EAGAIN */
150262894Sasomers	for(i=0; i < numpkts; i++) {
151261081Sasomers		ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
152261081Sasomers		if (ssize == -1) {
153270228Sasomers			if (errno == EAGAIN) {
154270228Sasomers				close(sv[0]);
155270228Sasomers				close(sv[1]);
156261081Sasomers				atf_tc_pass();
157270228Sasomers			}
158261081Sasomers			else {
159261081Sasomers				perror("send");
160261081Sasomers				atf_tc_fail("send returned < 0 but not EAGAIN");
161261081Sasomers			}
162261081Sasomers		}
163261081Sasomers	}
164261081Sasomers	atf_tc_fail("Never got EAGAIN");
165261081Sasomers}
166261081Sasomers
167262894Sasomersstatic void
168317831Sbrookstest_sendrecv_symmetric_buffers(int bufsize, int blocking) {
169261081Sasomers	int s;
170261081Sasomers	int sv[2];
171262894Sasomers	const ssize_t pktsize = bufsize / 2;
172261081Sasomers	char sndbuf[pktsize];
173261081Sasomers	char recv_buf[pktsize];
174261081Sasomers	ssize_t ssize, rsize;
175261081Sasomers
176261081Sasomers	/* setup the socket pair */
177261081Sasomers	if (blocking)
178261081Sasomers		do_socketpair(sv);
179261081Sasomers	else
180261081Sasomers		do_socketpair_nonblocking(sv);
181261081Sasomers
182261081Sasomers	/* Setup the buffers */
183261081Sasomers	s = setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize));
184261081Sasomers	ATF_REQUIRE_EQ(0, s);
185261081Sasomers	s = setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(bufsize));
186261081Sasomers	ATF_REQUIRE_EQ(0, s);
187261081Sasomers
188261081Sasomers	/* Fill the send buffer */
189261081Sasomers	bzero(sndbuf, pktsize);
190261081Sasomers
191261081Sasomers	/* send and receive the packet */
192261081Sasomers	ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
193261081Sasomers	if (ssize < 0) {
194261081Sasomers		perror("send");
195261081Sasomers		atf_tc_fail("send returned < 0");
196261081Sasomers	}
197261081Sasomers	ATF_CHECK_EQ_MSG(pktsize, ssize, "expected %zd=send(...) but got %zd",
198261081Sasomers	    pktsize, ssize);
199261081Sasomers
200261081Sasomers	rsize = recv(sv[1], recv_buf, pktsize, MSG_WAITALL);
201261081Sasomers	if (rsize < 0) {
202261081Sasomers		perror("recv");
203261081Sasomers		atf_tc_fail("recv returned < 0");
204261081Sasomers	}
205261081Sasomers	ATF_CHECK_EQ_MSG(pktsize, rsize, "expected %zd=send(...) but got %zd",
206261081Sasomers	    pktsize, rsize);
207270228Sasomers	close(sv[0]);
208270228Sasomers	close(sv[1]);
209261081Sasomers}
210261081Sasomers
211262894Sasomersstatic void
212317831Sbrookstest_pipe_simulator(int sndbufsize, int rcvbufsize)
213261081Sasomers{
214262894Sasomers	int num_sent, num_received;
215261081Sasomers	int sv[2];
216262894Sasomers	const ssize_t pktsize = MIN(sndbufsize, rcvbufsize) / 4;
217261081Sasomers	int numpkts;
218261081Sasomers	char sndbuf[pktsize];
219261081Sasomers	char rcvbuf[pktsize];
220261081Sasomers	char comparebuf[pktsize];
221261081Sasomers	ssize_t ssize, rsize;
222261081Sasomers	bool currently_sending = true;
223261081Sasomers
224261081Sasomers	/* setup the socket pair */
225261081Sasomers	do_socketpair_nonblocking(sv);
226261081Sasomers	/* Setup the buffers */
227261081Sasomers	ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
228261081Sasomers	    sizeof(sndbufsize)));
229261081Sasomers	ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
230261081Sasomers	    sizeof(rcvbufsize)));
231261081Sasomers
232261081Sasomers	/* Send a total amount of data comfortably greater than the buffers */
233261081Sasomers	numpkts = MAX(sndbufsize, rcvbufsize) * 8 / pktsize;
234261081Sasomers	for (num_sent=0, num_received=0;
235261081Sasomers	     num_sent < numpkts || num_received < numpkts; ) {
236261081Sasomers		if (currently_sending && num_sent < numpkts) {
237261081Sasomers			/* The simulated sending process */
238261081Sasomers			/* fill the buffer */
239261081Sasomers			memset(sndbuf, num_sent, pktsize);
240261081Sasomers			ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
241261081Sasomers			if (ssize < 0) {
242292820Sngie				/*
243261081Sasomers				 * XXX: This is bug-compatible with the kernel.
244261081Sasomers				 * The kernel returns EMSGSIZE when it should
245261081Sasomers				 * return EAGAIN
246261081Sasomers				 */
247261081Sasomers				if (errno == EAGAIN || errno == EMSGSIZE)
248261081Sasomers					currently_sending = false;
249261081Sasomers				else {
250261081Sasomers					perror("send");
251261081Sasomers					atf_tc_fail("send failed");
252261081Sasomers				}
253261081Sasomers			} else  {
254261081Sasomers				ATF_CHECK_EQ_MSG(pktsize, ssize,
255261081Sasomers				    "expected %zd=send(...) but got %zd",
256261081Sasomers				    pktsize, ssize);
257261081Sasomers				num_sent++;
258261081Sasomers			}
259261081Sasomers		} else {
260261081Sasomers			/* The simulated receiving process */
261261081Sasomers			rsize = recv(sv[1], rcvbuf, pktsize, MSG_WAITALL);
262261081Sasomers			if (rsize < 0) {
263261081Sasomers				if (errno == EAGAIN) {
264261081Sasomers					currently_sending = true;
265261081Sasomers					ATF_REQUIRE_MSG(num_sent < numpkts,
266261081Sasomers					    "Packets were lost!");
267261081Sasomers				}
268261081Sasomers				else {
269261081Sasomers					perror("recv");
270261081Sasomers					atf_tc_fail("recv failed");
271261081Sasomers				}
272261081Sasomers			} else  {
273261081Sasomers				ATF_CHECK_EQ_MSG(pktsize, rsize,
274261081Sasomers				    "expected %zd=recv(...) but got %zd",
275261081Sasomers				    pktsize, rsize);
276261081Sasomers				memset(comparebuf, num_received, pktsize);
277261081Sasomers				ATF_CHECK_EQ_MSG(0, memcmp(comparebuf, rcvbuf,
278292820Sngie				    			   pktsize),
279261081Sasomers				    "Received data miscompare");
280261081Sasomers				num_received++;
281261081Sasomers			}
282261081Sasomers		}
283261081Sasomers	}
284270228Sasomers	close(sv[0]);
285270228Sasomers	close(sv[1]);
286261081Sasomers}
287261081Sasomers
288261081Sasomerstypedef struct {
289261081Sasomers	ssize_t	pktsize;
290261081Sasomers	int	numpkts;
291261081Sasomers	int	so;
292261081Sasomers} test_pipe_thread_data_t;
293261081Sasomers
294261081Sasomersstatic void*
295261081Sasomerstest_pipe_writer(void* args)
296261081Sasomers{
297261081Sasomers	test_pipe_thread_data_t* td = args;
298261081Sasomers	char sndbuf[td->pktsize];
299261081Sasomers	ssize_t ssize;
300261081Sasomers	int i;
301261081Sasomers
302261081Sasomers	for(i=0; i < td->numpkts; i++) {
303261081Sasomers			memset(sndbuf, i, td->pktsize);
304261081Sasomers			ssize = send(td->so, sndbuf, td->pktsize, MSG_EOR);
305261081Sasomers			if (ssize < 0) {
306261081Sasomers				perror("send");
307261081Sasomers				atf_tc_fail("send returned < 0");
308261081Sasomers			}
309261081Sasomers			ATF_CHECK_EQ_MSG(td->pktsize, ssize,
310261081Sasomers			    		 "expected %zd=send(...) but got %zd",
311261081Sasomers			    		  td->pktsize, ssize);
312261081Sasomers	}
313261081Sasomers	return (0);
314261081Sasomers}
315261081Sasomers
316261081Sasomersstatic void*
317261081Sasomerstest_pipe_reader(void* args)
318261081Sasomers{
319261081Sasomers	test_pipe_thread_data_t* td = args;
320261081Sasomers	char rcvbuf[td->pktsize];
321261081Sasomers	char comparebuf[td->pktsize];
322261081Sasomers	ssize_t rsize;
323261081Sasomers	int i, d;
324261081Sasomers
325261081Sasomers	for(i=0; i < td->numpkts; i++) {
326261081Sasomers		memset(comparebuf, i, td->pktsize);
327261081Sasomers		rsize = recv(td->so, rcvbuf, td->pktsize, MSG_WAITALL);
328261081Sasomers		if (rsize < 0) {
329261081Sasomers			perror("recv");
330261081Sasomers			atf_tc_fail("recv returned < 0");
331261081Sasomers		}
332261081Sasomers		ATF_CHECK_EQ_MSG(td->pktsize, rsize,
333261081Sasomers		    		 "expected %zd=send(...) but got %zd",
334261081Sasomers				 td->pktsize, rsize);
335261081Sasomers		d = memcmp(comparebuf, rcvbuf, td->pktsize);
336292820Sngie		ATF_CHECK_EQ_MSG(0, d,
337261081Sasomers		    		 "Received data miscompare on packet %d", i);
338261081Sasomers	}
339261081Sasomers	return (0);
340261081Sasomers}
341261081Sasomers
342261081Sasomers
343262894Sasomersstatic void
344317831Sbrookstest_pipe(int sndbufsize, int rcvbufsize)
345261081Sasomers{
346261081Sasomers	test_pipe_thread_data_t writer_data, reader_data;
347261081Sasomers	pthread_t writer, reader;
348261081Sasomers	int sv[2];
349261081Sasomers	const size_t pktsize = MIN(sndbufsize, rcvbufsize) / 4;
350261081Sasomers	int numpkts;
351261081Sasomers
352261081Sasomers	/* setup the socket pair */
353261081Sasomers	do_socketpair(sv);
354261081Sasomers	/* Setup the buffers */
355261081Sasomers	ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
356261081Sasomers	    sizeof(sndbufsize)));
357261081Sasomers	ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
358261081Sasomers	    sizeof(rcvbufsize)));
359261081Sasomers
360261081Sasomers	/* Send a total amount of data comfortably greater than the buffers */
361261081Sasomers	numpkts = MAX(sndbufsize, rcvbufsize) * 8 / pktsize;
362261081Sasomers
363261081Sasomers	/* Start the child threads */
364261081Sasomers	writer_data.pktsize = pktsize;
365261081Sasomers	writer_data.numpkts = numpkts;
366261081Sasomers	writer_data.so = sv[0];
367261081Sasomers	reader_data.pktsize = pktsize;
368261081Sasomers	reader_data.numpkts = numpkts;
369261081Sasomers	reader_data.so = sv[1];
370261081Sasomers	ATF_REQUIRE_EQ(0, pthread_create(&writer, NULL, test_pipe_writer,
371261081Sasomers	    				 (void*)&writer_data));
372292820Sngie	/*
373262867Sasomers	 * Give the writer time to start writing, and hopefully block, before
374262867Sasomers	 * starting the reader.  This increases the likelihood of the test case
375262867Sasomers	 * failing due to PR kern/185812
376262867Sasomers	 */
377262867Sasomers	usleep(1000);
378261081Sasomers	ATF_REQUIRE_EQ(0, pthread_create(&reader, NULL, test_pipe_reader,
379261081Sasomers	    				 (void*)&reader_data));
380261081Sasomers
381261081Sasomers	/* Join the children */
382261081Sasomers	ATF_REQUIRE_EQ(0, pthread_join(writer, NULL));
383261081Sasomers	ATF_REQUIRE_EQ(0, pthread_join(reader, NULL));
384270228Sasomers	close(sv[0]);
385270228Sasomers	close(sv[1]);
386261081Sasomers}
387261081Sasomers
388261081Sasomers
389261081Sasomers/*
390261081Sasomers * Test Cases
391261081Sasomers */
392261081Sasomers
393261081Sasomers/* Create a SEQPACKET socket */
394261081SasomersATF_TC_WITHOUT_HEAD(create_socket);
395261081SasomersATF_TC_BODY(create_socket, tc)
396261081Sasomers{
397261081Sasomers	int s;
398261081Sasomers
399261081Sasomers	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
400271397Sasomers	ATF_REQUIRE(s >= 0);
401270228Sasomers	close(s);
402261081Sasomers}
403261081Sasomers
404261081Sasomers/* Create SEQPACKET sockets using socketpair(2) */
405261081SasomersATF_TC_WITHOUT_HEAD(create_socketpair);
406261081SasomersATF_TC_BODY(create_socketpair, tc)
407261081Sasomers{
408261081Sasomers	int sv[2];
409261081Sasomers	int s;
410261081Sasomers
411261081Sasomers	s = socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, sv);
412261081Sasomers	ATF_CHECK_EQ(0, s);
413261081Sasomers	ATF_CHECK(sv[0] >= 0);
414261081Sasomers	ATF_CHECK(sv[1] >= 0);
415261081Sasomers	ATF_CHECK(sv[0] != sv[1]);
416270228Sasomers	close(sv[0]);
417270228Sasomers	close(sv[1]);
418261081Sasomers}
419261081Sasomers
420261081Sasomers/* Call listen(2) without first calling bind(2).  It should fail */
421261081SasomersATF_TC_WITHOUT_HEAD(listen_unbound);
422261081SasomersATF_TC_BODY(listen_unbound, tc)
423261081Sasomers{
424261081Sasomers	int s, r;
425261081Sasomers
426261081Sasomers	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
427261081Sasomers	ATF_REQUIRE(s > 0);
428261081Sasomers	r = listen(s, -1);
429261081Sasomers	/* expect listen to fail since we haven't called bind(2) */
430261081Sasomers	ATF_CHECK(r != 0);
431270228Sasomers	close(s);
432261081Sasomers}
433261081Sasomers
434261081Sasomers/* Bind the socket to a file */
435261081SasomersATF_TC_WITHOUT_HEAD(bind);
436261081SasomersATF_TC_BODY(bind, tc)
437261081Sasomers{
438261081Sasomers	struct sockaddr_un sun;
439261081Sasomers	/* ATF's isolation mechanisms will guarantee uniqueness of this file */
440261081Sasomers	const char *path = "sock";
441261081Sasomers	int s, r;
442261081Sasomers
443261081Sasomers	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
444261081Sasomers	ATF_REQUIRE(s >= 0);
445261081Sasomers
446261081Sasomers	bzero(&sun, sizeof(sun));
447261081Sasomers	sun.sun_family = AF_LOCAL;
448261081Sasomers	sun.sun_len = sizeof(sun);
449261081Sasomers	strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
450261081Sasomers	r = bind(s, (struct sockaddr *)&sun, sizeof(sun));
451261081Sasomers	ATF_CHECK_EQ(0, r);
452270228Sasomers	close(s);
453261081Sasomers}
454261081Sasomers
455261081Sasomers/* listen(2) a socket that is already bound(2) should succeed */
456261081SasomersATF_TC_WITHOUT_HEAD(listen_bound);
457261081SasomersATF_TC_BODY(listen_bound, tc)
458261081Sasomers{
459261081Sasomers	struct sockaddr_un sun;
460261081Sasomers	/* ATF's isolation mechanisms will guarantee uniqueness of this file */
461261081Sasomers	const char *path = "sock";
462261081Sasomers	int s, r, l;
463261081Sasomers
464261081Sasomers	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
465261081Sasomers	ATF_REQUIRE(s >= 0);
466261081Sasomers
467261081Sasomers	bzero(&sun, sizeof(sun));
468261081Sasomers	sun.sun_family = AF_LOCAL;
469261081Sasomers	sun.sun_len = sizeof(sun);
470261081Sasomers	strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
471261081Sasomers	r = bind(s, (struct sockaddr *)&sun, sizeof(sun));
472261081Sasomers	l = listen(s, -1);
473261081Sasomers	ATF_CHECK_EQ(0, r);
474261081Sasomers	ATF_CHECK_EQ(0, l);
475270228Sasomers	close(s);
476261081Sasomers}
477261081Sasomers
478261081Sasomers/* connect(2) can make a connection */
479261081SasomersATF_TC_WITHOUT_HEAD(connect);
480261081SasomersATF_TC_BODY(connect, tc)
481261081Sasomers{
482261081Sasomers	struct sockaddr_un sun;
483261081Sasomers	/* ATF's isolation mechanisms will guarantee uniqueness of this file */
484261081Sasomers	const char *path = "sock";
485261081Sasomers	int s, r, err, l, s2;
486261081Sasomers
487261081Sasomers	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
488261081Sasomers	ATF_REQUIRE(s >= 0);
489261081Sasomers
490261081Sasomers	bzero(&sun, sizeof(sun));
491261081Sasomers	sun.sun_family = AF_LOCAL;
492261081Sasomers	sun.sun_len = sizeof(sun);
493261081Sasomers	strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
494261081Sasomers	r = bind(s, (struct sockaddr *)&sun, sizeof(sun));
495261081Sasomers	l = listen(s, -1);
496261081Sasomers	ATF_CHECK_EQ(0, r);
497261081Sasomers	ATF_CHECK_EQ(0, l);
498261081Sasomers
499261081Sasomers	/* Create the other socket */
500261081Sasomers	s2 = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
501261081Sasomers	ATF_REQUIRE(s2 >= 0);
502261081Sasomers	err = connect(s2, (struct sockaddr*)&sun, sizeof(sun));
503261081Sasomers	if (err != 0) {
504261081Sasomers		perror("connect");
505261081Sasomers		atf_tc_fail("connect(2) failed");
506261081Sasomers	}
507270228Sasomers	close(s);
508270228Sasomers	close(s2);
509261081Sasomers}
510261081Sasomers
511261081Sasomers/* accept(2) can receive a connection */
512261081SasomersATF_TC_WITHOUT_HEAD(accept);
513261081SasomersATF_TC_BODY(accept, tc)
514261081Sasomers{
515261081Sasomers	int sv[2];
516261081Sasomers
517261081Sasomers	mk_pair_of_sockets(sv);
518270228Sasomers	close(sv[0]);
519270228Sasomers	close(sv[1]);
520261081Sasomers}
521261081Sasomers
522261081Sasomers
523261081Sasomers/* Set O_NONBLOCK on the socket */
524261081SasomersATF_TC_WITHOUT_HEAD(fcntl_nonblock);
525261081SasomersATF_TC_BODY(fcntl_nonblock, tc)
526261081Sasomers{
527261081Sasomers	int s;
528261081Sasomers
529261081Sasomers	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
530261081Sasomers	ATF_REQUIRE(s >= 0);
531261081Sasomers	if (fcntl(s, F_SETFL, O_NONBLOCK) == -1) {
532261081Sasomers		perror("fcntl");
533261081Sasomers		atf_tc_fail("fcntl failed");
534261081Sasomers	}
535270228Sasomers	close(s);
536261081Sasomers}
537261081Sasomers
538261081Sasomers/* Resize the send and receive buffers */
539261081SasomersATF_TC_WITHOUT_HEAD(resize_buffers);
540261081SasomersATF_TC_BODY(resize_buffers, tc)
541261081Sasomers{
542261081Sasomers	int s;
543261081Sasomers	int sndbuf = 12345;
544261081Sasomers	int rcvbuf = 23456;
545261081Sasomers	int xs, xr;
546261081Sasomers	socklen_t sl = sizeof(xs);
547261081Sasomers
548261081Sasomers	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
549261081Sasomers	ATF_REQUIRE(s >= 0);
550261081Sasomers
551261081Sasomers	printf("                       Socket Buffer Sizes\n");
552261081Sasomers	printf("                              | SNDBUF  | RCVBUF  |\n");
553261081Sasomers	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_SNDBUF, &xs, &sl));
554261081Sasomers	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_RCVBUF, &xr, &sl));
555261081Sasomers	printf("Default                       | %7d | %7d |\n", xs, xr);
556261081Sasomers
557261081Sasomers	if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf)) != 0){
558261081Sasomers		perror("setsockopt");
559261081Sasomers		atf_tc_fail("setsockopt(SO_SNDBUF) failed");
560261081Sasomers	}
561261081Sasomers	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_SNDBUF, &xs, &sl));
562261081Sasomers	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_RCVBUF, &xr, &sl));
563261081Sasomers	printf("After changing SNDBUF         | %7d | %7d |\n", xs, xr);
564292820Sngie
565261081Sasomers	if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)) != 0){
566261081Sasomers		perror("setsockopt");
567261081Sasomers		atf_tc_fail("setsockopt(SO_RCVBUF) failed");
568261081Sasomers	}
569261081Sasomers	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_SNDBUF, &xs, &sl));
570261081Sasomers	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_RCVBUF, &xr, &sl));
571261081Sasomers	printf("After changing RCVBUF         | %7d | %7d |\n", xs, xr);
572270228Sasomers	close(s);
573261081Sasomers}
574261081Sasomers
575261081Sasomers/*
576261081Sasomers * Resize the send and receive buffers of a connected socketpair
577261081Sasomers * Print some useful debugging info too
578261081Sasomers */
579261081SasomersATF_TC_WITHOUT_HEAD(resize_connected_buffers);
580261081SasomersATF_TC_BODY(resize_connected_buffers, tc)
581261081Sasomers{
582261081Sasomers	int sv[2];
583261081Sasomers	int sndbuf = 12345;
584261081Sasomers	int rcvbuf = 23456;
585261081Sasomers	int err;
586261081Sasomers	int ls, lr, rs, rr;
587261081Sasomers	socklen_t sl = sizeof(ls);
588261081Sasomers
589261081Sasomers	/* setup the socket pair */
590261081Sasomers	do_socketpair(sv);
591261081Sasomers
592261081Sasomers	printf("                       Socket Buffer Sizes\n");
593261081Sasomers	printf("                              | Left Socket       | Right Socket      |\n");
594261081Sasomers	printf("                              | SNDBUF  | RCVBUF  | SNDBUF  | RCVBUF  |\n");
595261081Sasomers	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &ls, &sl));
596261081Sasomers	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &lr, &sl));
597261081Sasomers	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &rs, &sl));
598261081Sasomers	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rr, &sl));
599261081Sasomers	printf("Default                       | %7d | %7d | %7d | %7d |\n",
600261081Sasomers	    ls, lr, rs, rr);
601261081Sasomers
602261081Sasomers	/* Update one side's send buffer */
603261081Sasomers	err = setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf));
604261081Sasomers	if (err != 0){
605261081Sasomers		perror("setsockopt");
606261081Sasomers		atf_tc_fail("setsockopt(SO_SNDBUF) failed");
607261081Sasomers	}
608261081Sasomers
609261081Sasomers	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &ls, &sl));
610261081Sasomers	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &lr, &sl));
611261081Sasomers	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &rs, &sl));
612261081Sasomers	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rr, &sl));
613261081Sasomers	printf("After changing Left's SNDBUF  | %7d | %7d | %7d | %7d |\n",
614261081Sasomers	    ls, lr, rs, rr);
615261081Sasomers
616261081Sasomers	/* Update the same side's receive buffer */
617261081Sasomers	err = setsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf));
618261081Sasomers	if (err != 0){
619261081Sasomers		perror("setsockopt");
620261081Sasomers		atf_tc_fail("setsockopt(SO_RCVBUF) failed");
621261081Sasomers	}
622261081Sasomers
623261081Sasomers	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &ls, &sl));
624261081Sasomers	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &lr, &sl));
625261081Sasomers	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &rs, &sl));
626261081Sasomers	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rr, &sl));
627261081Sasomers	printf("After changing Left's RCVBUF  | %7d | %7d | %7d | %7d |\n",
628261081Sasomers	    ls, lr, rs, rr);
629270228Sasomers	close(sv[0]);
630270228Sasomers	close(sv[1]);
631261081Sasomers}
632261081Sasomers
633261081Sasomers
634261081Sasomers/* send(2) and recv(2) a single short record */
635261081SasomersATF_TC_WITHOUT_HEAD(send_recv);
636261081SasomersATF_TC_BODY(send_recv, tc)
637261081Sasomers{
638261081Sasomers	int sv[2];
639261081Sasomers	const int bufsize = 64;
640261081Sasomers	const char *data = "data";
641261081Sasomers	char recv_buf[bufsize];
642262894Sasomers	ssize_t datalen;
643261081Sasomers	ssize_t ssize, rsize;
644261081Sasomers
645261081Sasomers	/* setup the socket pair */
646261081Sasomers	do_socketpair(sv);
647261081Sasomers
648261081Sasomers	/* send and receive a small packet */
649261081Sasomers	datalen = strlen(data) + 1;	/* +1 for the null */
650261081Sasomers	ssize = send(sv[0], data, datalen, MSG_EOR);
651261081Sasomers	if (ssize < 0) {
652261081Sasomers		perror("send");
653261081Sasomers		atf_tc_fail("send returned < 0");
654261081Sasomers	}
655261081Sasomers	ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd",
656261081Sasomers	    datalen, ssize);
657261081Sasomers
658261081Sasomers	rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL);
659261081Sasomers	ATF_CHECK_EQ(datalen, rsize);
660270228Sasomers	close(sv[0]);
661270228Sasomers	close(sv[1]);
662261081Sasomers}
663261081Sasomers
664261081Sasomers/* sendto(2) and recvfrom(2) a single short record
665261081Sasomers * According to The Open Group Base Specifications Issue 6 IEEE Std 1003.1, 2004
666261081Sasomers * Edition, sendto(2) is exactly the same as send(2) on a connection-mode socket
667261081Sasomers *
668261081Sasomers * According to the same spec, not all protocols are required to provide the
669261081Sasomers * source addres in recvfrom(2).
670261081Sasomers */
671261081SasomersATF_TC_WITHOUT_HEAD(sendto_recvfrom);
672261081SasomersATF_TC_BODY(sendto_recvfrom, tc)
673261081Sasomers{
674292821Sngie#ifdef TEST_SEQ_PACKET_SOURCE_ADDRESS
675261081Sasomers	const char* path;
676292821Sngie#endif
677261081Sasomers	struct sockaddr_storage from;
678261081Sasomers	int sv[2];
679261081Sasomers	const int bufsize = 64;
680261081Sasomers	const char *data = "data";
681261081Sasomers	char recv_buf[bufsize];
682262894Sasomers	ssize_t datalen;
683261081Sasomers	ssize_t ssize, rsize;
684261081Sasomers	socklen_t fromlen;
685261081Sasomers
686261081Sasomers	/* setup the socket pair */
687292821Sngie#ifdef TEST_SEQ_PACKET_SOURCE_ADDRESS
688292821Sngie	path =
689292821Sngie#endif
690292821Sngie		mk_pair_of_sockets(sv);
691261081Sasomers
692261081Sasomers	/* send and receive a small packet */
693261081Sasomers	datalen = strlen(data) + 1;	/* +1 for the null */
694261081Sasomers	ssize = sendto(sv[0], data, datalen, MSG_EOR, NULL, 0);
695261081Sasomers	if (ssize < 0) {
696261081Sasomers		perror("send");
697261081Sasomers		atf_tc_fail("send returned < 0");
698261081Sasomers	}
699261081Sasomers	ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd",
700261081Sasomers	    datalen, ssize);
701261081Sasomers
702261081Sasomers	fromlen = sizeof(from);
703261081Sasomers	rsize = recvfrom(sv[1], recv_buf, bufsize, MSG_WAITALL,
704261081Sasomers	    (struct sockaddr*)&from, &fromlen);
705261081Sasomers	if (ssize < 0) {
706261081Sasomers		perror("recvfrom");
707261081Sasomers		atf_tc_fail("recvfrom returned < 0");
708261081Sasomers	}
709261081Sasomers	ATF_CHECK_EQ(datalen, rsize);
710261081Sasomers
711292821Sngie#ifdef TEST_SEQ_PACKET_SOURCE_ADDRESS
712292820Sngie	/*
713261081Sasomers	 * FreeBSD does not currently provide the source address for SEQ_PACKET
714261081Sasomers	 * AF_UNIX sockets, and POSIX does not require it, so these two checks
715261081Sasomers	 * are disabled.  If FreeBSD gains that feature in the future, then
716261081Sasomers	 * these checks may be reenabled
717261081Sasomers	 */
718292821Sngie	ATF_CHECK_EQ(PF_LOCAL, from.ss_family);
719292821Sngie	ATF_CHECK_STREQ(path, ((struct sockaddr_un*)&from)->sun_path);
720292821Sngie#endif
721270228Sasomers	close(sv[0]);
722270228Sasomers	close(sv[1]);
723261081Sasomers}
724261081Sasomers
725292820Sngie/*
726261081Sasomers * send(2) and recv(2) a single short record with sockets created the
727261081Sasomers * traditional way, involving bind, listen, connect, and accept
728261081Sasomers */
729261081SasomersATF_TC_WITHOUT_HEAD(send_recv_with_connect);
730261081SasomersATF_TC_BODY(send_recv_with_connect, tc)
731261081Sasomers{
732261081Sasomers	int sv[2];
733261081Sasomers	const int bufsize = 64;
734261081Sasomers	const char *data = "data";
735261081Sasomers	char recv_buf[bufsize];
736262894Sasomers	ssize_t datalen;
737261081Sasomers	ssize_t ssize, rsize;
738261081Sasomers
739261081Sasomers	mk_pair_of_sockets(sv);
740261081Sasomers
741261081Sasomers	/* send and receive a small packet */
742261081Sasomers	datalen = strlen(data) + 1;	/* +1 for the null */
743261081Sasomers	ssize = send(sv[0], data, datalen, MSG_EOR);
744261081Sasomers	if (ssize < 0) {
745261081Sasomers		perror("send");
746261081Sasomers		atf_tc_fail("send returned < 0");
747261081Sasomers	}
748261081Sasomers	ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd",
749261081Sasomers	    datalen, ssize);
750261081Sasomers
751261081Sasomers	rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL);
752261081Sasomers	ATF_CHECK_EQ(datalen, rsize);
753270228Sasomers	close(sv[0]);
754270228Sasomers	close(sv[1]);
755261081Sasomers}
756261081Sasomers
757261081Sasomers/* send(2) should fail on a shutdown socket */
758261081SasomersATF_TC_WITHOUT_HEAD(shutdown_send);
759261081SasomersATF_TC_BODY(shutdown_send, tc)
760261081Sasomers{
761286011Spluknet	struct sockaddr_un sun;
762286011Spluknet	/* ATF's isolation mechanisms will guarantee uniqueness of this file */
763286011Spluknet	const char *path = "sock";
764286011Spluknet	const char *data = "data";
765321165Sngie	ssize_t datalen, ssize;
766286011Spluknet	int s, err, s2;
767261081Sasomers
768261081Sasomers	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
769270228Sasomers	ATF_REQUIRE(s >= 0);
770286011Spluknet
771286011Spluknet	bzero(&sun, sizeof(sun));
772286011Spluknet	sun.sun_family = AF_LOCAL;
773286011Spluknet	sun.sun_len = sizeof(sun);
774286011Spluknet	strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
775286011Spluknet	err = bind(s, (struct sockaddr *)&sun, sizeof(sun));
776286011Spluknet	err = listen(s, -1);
777286011Spluknet	ATF_CHECK_EQ(0, err);
778286011Spluknet
779286011Spluknet	/* Create the other socket */
780286011Spluknet	s2 = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
781286011Spluknet	ATF_REQUIRE(s2 >= 0);
782286011Spluknet	err = connect(s2, (struct sockaddr*)&sun, sizeof(sun));
783286011Spluknet	if (err != 0) {
784286011Spluknet		perror("connect");
785286011Spluknet		atf_tc_fail("connect(2) failed");
786286011Spluknet	}
787286011Spluknet
788286011Spluknet	ATF_CHECK_EQ(0, shutdown(s2, SHUT_RDWR));
789321165Sngie	datalen = strlen(data) + 1;	/* +1 for the null */
790261081Sasomers	/* USE MSG_NOSIGNAL so we don't get SIGPIPE */
791321165Sngie	ssize = send(s2, data, datalen, MSG_EOR | MSG_NOSIGNAL);
792261081Sasomers	ATF_CHECK_EQ(EPIPE, errno);
793261081Sasomers	ATF_CHECK_EQ(-1, ssize);
794270228Sasomers	close(s);
795286011Spluknet	close(s2);
796261081Sasomers}
797261081Sasomers
798261081Sasomers/* send(2) should cause SIGPIPE on a shutdown socket */
799261081SasomersATF_TC_WITHOUT_HEAD(shutdown_send_sigpipe);
800261081SasomersATF_TC_BODY(shutdown_send_sigpipe, tc)
801261081Sasomers{
802286011Spluknet	struct sockaddr_un sun;
803286011Spluknet	/* ATF's isolation mechanisms will guarantee uniqueness of this file */
804286011Spluknet	const char *path = "sock";
805286011Spluknet	const char *data = "data";
806321165Sngie	ssize_t datalen;
807286011Spluknet	int s, err, s2;
808261081Sasomers
809261081Sasomers	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
810270228Sasomers	ATF_REQUIRE(s >= 0);
811286011Spluknet
812286011Spluknet	bzero(&sun, sizeof(sun));
813286011Spluknet	sun.sun_family = AF_LOCAL;
814286011Spluknet	sun.sun_len = sizeof(sun);
815286011Spluknet	strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
816286011Spluknet	err = bind(s, (struct sockaddr *)&sun, sizeof(sun));
817286011Spluknet	err = listen(s, -1);
818286011Spluknet	ATF_CHECK_EQ(0, err);
819286011Spluknet
820286011Spluknet	/* Create the other socket */
821286011Spluknet	s2 = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
822286011Spluknet	ATF_REQUIRE(s2 >= 0);
823286011Spluknet	err = connect(s2, (struct sockaddr*)&sun, sizeof(sun));
824286011Spluknet	if (err != 0) {
825286011Spluknet		perror("connect");
826286011Spluknet		atf_tc_fail("connect(2) failed");
827286011Spluknet	}
828286011Spluknet
829286011Spluknet	ATF_CHECK_EQ(0, shutdown(s2, SHUT_RDWR));
830261081Sasomers	ATF_REQUIRE(SIG_ERR != signal(SIGPIPE, shutdown_send_sigpipe_handler));
831321165Sngie	datalen = strlen(data) + 1;	/* +1 for the null */
832321165Sngie	(void)send(s2, data, sizeof(*data), MSG_EOR);
833261081Sasomers	ATF_CHECK_EQ(1, got_sigpipe);
834270228Sasomers	close(s);
835286011Spluknet	close(s2);
836261081Sasomers}
837261081Sasomers
838261081Sasomers/* nonblocking send(2) and recv(2) a single short record */
839261081SasomersATF_TC_WITHOUT_HEAD(send_recv_nonblocking);
840261081SasomersATF_TC_BODY(send_recv_nonblocking, tc)
841261081Sasomers{
842261081Sasomers	int sv[2];
843261081Sasomers	const int bufsize = 64;
844261081Sasomers	const char *data = "data";
845261081Sasomers	char recv_buf[bufsize];
846262894Sasomers	ssize_t datalen;
847261081Sasomers	ssize_t ssize, rsize;
848261081Sasomers
849261081Sasomers	/* setup the socket pair */
850261081Sasomers	do_socketpair_nonblocking(sv);
851261081Sasomers
852261081Sasomers	/* Verify that there is nothing to receive */
853261081Sasomers	rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL);
854261081Sasomers	ATF_CHECK_EQ(EAGAIN, errno);
855261081Sasomers	ATF_CHECK_EQ(-1, rsize);
856261081Sasomers
857261081Sasomers	/* send and receive a small packet */
858261081Sasomers	datalen = strlen(data) + 1;	/* +1 for the null */
859261081Sasomers	ssize = send(sv[0], data, datalen, MSG_EOR);
860261081Sasomers	if (ssize < 0) {
861261081Sasomers		perror("send");
862261081Sasomers		atf_tc_fail("send returned < 0");
863261081Sasomers	}
864261081Sasomers	ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd",
865261081Sasomers	    datalen, ssize);
866261081Sasomers
867261081Sasomers	rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL);
868261081Sasomers	ATF_CHECK_EQ(datalen, rsize);
869270228Sasomers	close(sv[0]);
870270228Sasomers	close(sv[1]);
871261081Sasomers}
872261081Sasomers
873292820Sngie/*
874261081Sasomers * We should get EMSGSIZE if we try to send a message larger than the socket
875261081Sasomers * buffer, with blocking sockets
876261081Sasomers */
877261081SasomersATF_TC_WITHOUT_HEAD(emsgsize);
878261081SasomersATF_TC_BODY(emsgsize, tc)
879261081Sasomers{
880261081Sasomers	int sv[2];
881317831Sbrooks	const int sndbufsize = 8192;
882317831Sbrooks	const int rcvbufsize = 8192;
883261081Sasomers	const size_t pktsize = (sndbufsize + rcvbufsize) * 2;
884261081Sasomers	char sndbuf[pktsize];
885262894Sasomers	ssize_t ssize;
886261081Sasomers
887261081Sasomers	/* setup the socket pair */
888261081Sasomers	do_socketpair(sv);
889261081Sasomers	/* Setup the buffers */
890261081Sasomers	ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
891261081Sasomers	    sizeof(sndbufsize)));
892261081Sasomers	ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
893261081Sasomers	    sizeof(rcvbufsize)));
894261081Sasomers
895261081Sasomers	ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
896261081Sasomers	ATF_CHECK_EQ(EMSGSIZE, errno);
897261081Sasomers	ATF_CHECK_EQ(-1, ssize);
898270228Sasomers	close(sv[0]);
899270228Sasomers	close(sv[1]);
900261081Sasomers}
901261081Sasomers
902292820Sngie/*
903261081Sasomers * We should get EMSGSIZE if we try to send a message larger than the socket
904261081Sasomers * buffer, with nonblocking sockets
905261081Sasomers */
906261081SasomersATF_TC_WITHOUT_HEAD(emsgsize_nonblocking);
907261081SasomersATF_TC_BODY(emsgsize_nonblocking, tc)
908261081Sasomers{
909261081Sasomers	int sv[2];
910317831Sbrooks	const int sndbufsize = 8192;
911317831Sbrooks	const int rcvbufsize = 8192;
912261081Sasomers	const size_t pktsize = (sndbufsize + rcvbufsize) * 2;
913261081Sasomers	char sndbuf[pktsize];
914262894Sasomers	ssize_t ssize;
915261081Sasomers
916261081Sasomers	/* setup the socket pair */
917261081Sasomers	do_socketpair_nonblocking(sv);
918261081Sasomers	/* Setup the buffers */
919261081Sasomers	ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
920261081Sasomers	    sizeof(sndbufsize)));
921261081Sasomers	ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
922261081Sasomers	    sizeof(rcvbufsize)));
923261081Sasomers
924261081Sasomers	ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
925261081Sasomers	ATF_CHECK_EQ(EMSGSIZE, errno);
926261081Sasomers	ATF_CHECK_EQ(-1, ssize);
927270228Sasomers	close(sv[0]);
928270228Sasomers	close(sv[1]);
929261081Sasomers}
930261081Sasomers
931261081Sasomers
932292820Sngie/*
933261081Sasomers * We should get EAGAIN if we try to send a message larger than the socket
934261081Sasomers * buffer, with nonblocking sockets.  Test with several different sockbuf sizes
935261081Sasomers */
936261081SasomersATF_TC_WITHOUT_HEAD(eagain_8k_8k);
937261081SasomersATF_TC_BODY(eagain_8k_8k, tc)
938261081Sasomers{
939261081Sasomers	test_eagain(8192, 8192);
940261081Sasomers}
941261081SasomersATF_TC_WITHOUT_HEAD(eagain_8k_128k);
942261081SasomersATF_TC_BODY(eagain_8k_128k, tc)
943261081Sasomers{
944261081Sasomers	test_eagain(8192, 131072);
945261081Sasomers}
946261081SasomersATF_TC_WITHOUT_HEAD(eagain_128k_8k);
947261081SasomersATF_TC_BODY(eagain_128k_8k, tc)
948261081Sasomers{
949261081Sasomers	test_eagain(131072, 8192);
950261081Sasomers}
951261081SasomersATF_TC_WITHOUT_HEAD(eagain_128k_128k);
952261081SasomersATF_TC_BODY(eagain_128k_128k, tc)
953261081Sasomers{
954261081Sasomers	test_eagain(131072, 131072);
955261081Sasomers}
956261081Sasomers
957261081Sasomers
958292820Sngie/*
959261081Sasomers * nonblocking send(2) and recv(2) of several records, which should collectively
960261081Sasomers * fill up the send buffer but not the receive buffer
961261081Sasomers */
962261081SasomersATF_TC_WITHOUT_HEAD(rcvbuf_oversized);
963261081SasomersATF_TC_BODY(rcvbuf_oversized, tc)
964261081Sasomers{
965262894Sasomers	int i;
966261081Sasomers	int sv[2];
967264133Sjmmv	const ssize_t pktsize = 1024;
968317831Sbrooks	const int sndbufsize = 8192;
969317831Sbrooks	const int rcvbufsize = 131072;
970262894Sasomers	const size_t geometric_mean_bufsize = 32768;
971262894Sasomers	const int numpkts = geometric_mean_bufsize / pktsize;
972261081Sasomers	char sndbuf[pktsize];
973261081Sasomers	char recv_buf[pktsize];
974261081Sasomers	ssize_t ssize, rsize;
975261081Sasomers
976261081Sasomers	/* setup the socket pair */
977261081Sasomers	do_socketpair_nonblocking(sv);
978262894Sasomers	ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
979262894Sasomers	    sizeof(sndbufsize)));
980262894Sasomers	ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
981262894Sasomers	    sizeof(rcvbufsize)));
982261081Sasomers
983292820Sngie	/*
984261081Sasomers	 * Send and receive packets that are collectively greater than the send
985261081Sasomers	 * buffer, but less than the receive buffer
986261081Sasomers	 */
987262894Sasomers	for (i=0; i < numpkts; i++) {
988261081Sasomers		/* Fill the buffer */
989261081Sasomers		memset(sndbuf, i, pktsize);
990261081Sasomers
991261081Sasomers		/* send the packet */
992261081Sasomers		ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
993261081Sasomers		if (ssize < 0) {
994261081Sasomers			perror("send");
995261081Sasomers			atf_tc_fail("send returned < 0");
996261081Sasomers		}
997261081Sasomers		ATF_CHECK_EQ_MSG(pktsize, ssize,
998261081Sasomers		    "expected %zd=send(...) but got %zd", pktsize, ssize);
999261081Sasomers
1000261081Sasomers		/* Receive it */
1001261081Sasomers
1002261081Sasomers		rsize = recv(sv[1], recv_buf, pktsize, MSG_WAITALL);
1003261081Sasomers		if (rsize < 0) {
1004261081Sasomers			perror("recv");
1005261081Sasomers			atf_tc_fail("recv returned < 0");
1006261081Sasomers		}
1007261081Sasomers		ATF_CHECK_EQ_MSG(pktsize, rsize,
1008261081Sasomers		    "expected %zd=send(...) but got %zd", pktsize, rsize);
1009261081Sasomers
1010261081Sasomers		/* Verify the contents */
1011292820Sngie		ATF_CHECK_EQ_MSG(0, memcmp(sndbuf, recv_buf, pktsize),
1012261081Sasomers		    "Received data miscompare");
1013261081Sasomers	}
1014261081Sasomers
1015261081Sasomers	/* Trying to receive again should return EAGAIN */
1016261081Sasomers	rsize = recv(sv[1], recv_buf, pktsize, MSG_WAITALL);
1017261081Sasomers	ATF_CHECK_EQ(EAGAIN, errno);
1018261081Sasomers	ATF_CHECK_EQ(-1, rsize);
1019270228Sasomers	close(sv[0]);
1020270228Sasomers	close(sv[1]);
1021261081Sasomers}
1022261081Sasomers
1023292820Sngie/*
1024261081Sasomers * Simulate the behavior of a blocking pipe.  The sender will send until his
1025261081Sasomers * buffer fills up, then we'll simulate a scheduler switch that will allow the
1026261081Sasomers * receiver to read until his buffer empties.  Repeat the process until the
1027261081Sasomers * transfer is complete.
1028261081Sasomers * Repeat the test with multiple send and receive buffer sizes
1029261081Sasomers */
1030261081SasomersATF_TC_WITHOUT_HEAD(pipe_simulator_8k_8k);
1031261081SasomersATF_TC_BODY(pipe_simulator_8k_8k, tc)
1032261081Sasomers{
1033261081Sasomers	test_pipe_simulator(8192, 8192);
1034261081Sasomers}
1035261081Sasomers
1036261081SasomersATF_TC_WITHOUT_HEAD(pipe_simulator_8k_128k);
1037261081SasomersATF_TC_BODY(pipe_simulator_8k_128k, tc)
1038261081Sasomers{
1039261081Sasomers	test_pipe_simulator(8192, 131072);
1040261081Sasomers}
1041261081Sasomers
1042261081SasomersATF_TC_WITHOUT_HEAD(pipe_simulator_128k_8k);
1043261081SasomersATF_TC_BODY(pipe_simulator_128k_8k, tc)
1044261081Sasomers{
1045261081Sasomers	test_pipe_simulator(131072, 8192);
1046261081Sasomers}
1047261081Sasomers
1048261081SasomersATF_TC_WITHOUT_HEAD(pipe_simulator_128k_128k);
1049261081SasomersATF_TC_BODY(pipe_simulator_128k_128k, tc)
1050261081Sasomers{
1051261081Sasomers	test_pipe_simulator(131072, 131072);
1052261081Sasomers}
1053261081Sasomers
1054292820Sngie/*
1055261081Sasomers * Test blocking I/O by passing data between two threads.  The total amount of
1056261081Sasomers * data will be >> buffer size to force blocking.  Repeat the test with multiple
1057261081Sasomers * send and receive buffer sizes
1058261081Sasomers */
1059261081SasomersATF_TC_WITHOUT_HEAD(pipe_8k_8k);
1060261081SasomersATF_TC_BODY(pipe_8k_8k, tc)
1061261081Sasomers{
1062261081Sasomers	test_pipe(8192, 8192);
1063261081Sasomers}
1064261081Sasomers
1065261081SasomersATF_TC_WITHOUT_HEAD(pipe_8k_128k);
1066261081SasomersATF_TC_BODY(pipe_8k_128k, tc)
1067261081Sasomers{
1068261081Sasomers	test_pipe(8192, 131072);
1069261081Sasomers}
1070261081Sasomers
1071261081SasomersATF_TC_WITHOUT_HEAD(pipe_128k_8k);
1072261081SasomersATF_TC_BODY(pipe_128k_8k, tc)
1073261081Sasomers{
1074261081Sasomers	test_pipe(131072, 8192);
1075261081Sasomers}
1076261081Sasomers
1077261081SasomersATF_TC_WITHOUT_HEAD(pipe_128k_128k);
1078261081SasomersATF_TC_BODY(pipe_128k_128k, tc)
1079261081Sasomers{
1080261081Sasomers	test_pipe(131072, 131072);
1081261081Sasomers}
1082261081Sasomers
1083261081Sasomers
1084261081Sasomers/*
1085261081Sasomers * Test single-packet I/O with and without blocking, with symmetric buffers of
1086261081Sasomers * various sizes
1087261081Sasomers */
1088261081SasomersATF_TC_WITHOUT_HEAD(sendrecv_8k);
1089261081SasomersATF_TC_BODY(sendrecv_8k, tc)
1090261081Sasomers{
1091261081Sasomers	test_sendrecv_symmetric_buffers(8 * 1024, true);
1092261081Sasomers}
1093261081SasomersATF_TC_WITHOUT_HEAD(sendrecv_16k);
1094261081SasomersATF_TC_BODY(sendrecv_16k, tc)
1095261081Sasomers{
1096261081Sasomers	test_sendrecv_symmetric_buffers(16 * 1024, true);
1097261081Sasomers}
1098261081SasomersATF_TC_WITHOUT_HEAD(sendrecv_32k);
1099261081SasomersATF_TC_BODY(sendrecv_32k, tc)
1100261081Sasomers{
1101261081Sasomers	test_sendrecv_symmetric_buffers(32 * 1024, true);
1102261081Sasomers}
1103261081SasomersATF_TC_WITHOUT_HEAD(sendrecv_64k);
1104261081SasomersATF_TC_BODY(sendrecv_64k, tc)
1105261081Sasomers{
1106261081Sasomers	test_sendrecv_symmetric_buffers(64 * 1024, true);
1107261081Sasomers}
1108261081SasomersATF_TC_WITHOUT_HEAD(sendrecv_128k);
1109261081SasomersATF_TC_BODY(sendrecv_128k, tc)
1110261081Sasomers{
1111261081Sasomers	test_sendrecv_symmetric_buffers(128 * 1024, true);
1112261081Sasomers}
1113261081SasomersATF_TC_WITHOUT_HEAD(sendrecv_8k_nonblocking);
1114261081SasomersATF_TC_BODY(sendrecv_8k_nonblocking, tc)
1115261081Sasomers{
1116261081Sasomers	test_sendrecv_symmetric_buffers(8 * 1024, false);
1117261081Sasomers}
1118261081SasomersATF_TC_WITHOUT_HEAD(sendrecv_16k_nonblocking);
1119261081SasomersATF_TC_BODY(sendrecv_16k_nonblocking, tc)
1120261081Sasomers{
1121261081Sasomers	test_sendrecv_symmetric_buffers(16 * 1024, false);
1122261081Sasomers}
1123261081SasomersATF_TC_WITHOUT_HEAD(sendrecv_32k_nonblocking);
1124261081SasomersATF_TC_BODY(sendrecv_32k_nonblocking, tc)
1125261081Sasomers{
1126261081Sasomers	test_sendrecv_symmetric_buffers(32 * 1024, false);
1127261081Sasomers}
1128261081SasomersATF_TC_WITHOUT_HEAD(sendrecv_64k_nonblocking);
1129261081SasomersATF_TC_BODY(sendrecv_64k_nonblocking, tc)
1130261081Sasomers{
1131261081Sasomers	test_sendrecv_symmetric_buffers(64 * 1024, false);
1132261081Sasomers}
1133261081SasomersATF_TC_WITHOUT_HEAD(sendrecv_128k_nonblocking);
1134261081SasomersATF_TC_BODY(sendrecv_128k_nonblocking, tc)
1135261081Sasomers{
1136261081Sasomers	test_sendrecv_symmetric_buffers(128 * 1024, false);
1137261081Sasomers}
1138261081Sasomers
1139261081Sasomers
1140261081Sasomers/*
1141261081Sasomers * Main.
1142261081Sasomers */
1143261081Sasomers
1144261081SasomersATF_TP_ADD_TCS(tp)
1145261081Sasomers{
1146261081Sasomers	/* Basic creation and connection tests */
1147261081Sasomers	ATF_TP_ADD_TC(tp, create_socket);
1148261081Sasomers	ATF_TP_ADD_TC(tp, create_socketpair);
1149261081Sasomers	ATF_TP_ADD_TC(tp, listen_unbound);
1150261081Sasomers	ATF_TP_ADD_TC(tp, bind);
1151261081Sasomers	ATF_TP_ADD_TC(tp, listen_bound);
1152261081Sasomers	ATF_TP_ADD_TC(tp, connect);
1153261081Sasomers	ATF_TP_ADD_TC(tp, accept);
1154261081Sasomers	ATF_TP_ADD_TC(tp, fcntl_nonblock);
1155261081Sasomers	ATF_TP_ADD_TC(tp, resize_buffers);
1156261081Sasomers	ATF_TP_ADD_TC(tp, resize_connected_buffers);
1157261081Sasomers
1158261081Sasomers	/* Unthreaded I/O tests */
1159261081Sasomers	ATF_TP_ADD_TC(tp, send_recv);
1160261081Sasomers	ATF_TP_ADD_TC(tp, send_recv_nonblocking);
1161261081Sasomers	ATF_TP_ADD_TC(tp, send_recv_with_connect);
1162261081Sasomers	ATF_TP_ADD_TC(tp, sendto_recvfrom);
1163261081Sasomers	ATF_TP_ADD_TC(tp, shutdown_send);
1164261081Sasomers	ATF_TP_ADD_TC(tp, shutdown_send_sigpipe);
1165261081Sasomers	ATF_TP_ADD_TC(tp, emsgsize);
1166261081Sasomers	ATF_TP_ADD_TC(tp, emsgsize_nonblocking);
1167261081Sasomers	ATF_TP_ADD_TC(tp, eagain_8k_8k);
1168261081Sasomers	ATF_TP_ADD_TC(tp, eagain_8k_128k);
1169261081Sasomers	ATF_TP_ADD_TC(tp, eagain_128k_8k);
1170261081Sasomers	ATF_TP_ADD_TC(tp, eagain_128k_128k);
1171261081Sasomers	ATF_TP_ADD_TC(tp, sendrecv_8k);
1172261081Sasomers	ATF_TP_ADD_TC(tp, sendrecv_16k);
1173261081Sasomers	ATF_TP_ADD_TC(tp, sendrecv_32k);
1174261081Sasomers	ATF_TP_ADD_TC(tp, sendrecv_64k);
1175261081Sasomers	ATF_TP_ADD_TC(tp, sendrecv_128k);
1176261081Sasomers	ATF_TP_ADD_TC(tp, sendrecv_8k_nonblocking);
1177261081Sasomers	ATF_TP_ADD_TC(tp, sendrecv_16k_nonblocking);
1178261081Sasomers	ATF_TP_ADD_TC(tp, sendrecv_32k_nonblocking);
1179261081Sasomers	ATF_TP_ADD_TC(tp, sendrecv_64k_nonblocking);
1180261081Sasomers	ATF_TP_ADD_TC(tp, sendrecv_128k_nonblocking);
1181261081Sasomers	ATF_TP_ADD_TC(tp, rcvbuf_oversized);
1182261081Sasomers	ATF_TP_ADD_TC(tp, pipe_simulator_8k_8k);
1183261081Sasomers	ATF_TP_ADD_TC(tp, pipe_simulator_8k_128k);
1184261081Sasomers	ATF_TP_ADD_TC(tp, pipe_simulator_128k_8k);
1185261081Sasomers	ATF_TP_ADD_TC(tp, pipe_simulator_128k_128k);
1186261081Sasomers
1187261081Sasomers	/* Threaded I/O tests with blocking sockets */
1188261081Sasomers	ATF_TP_ADD_TC(tp, pipe_8k_8k);
1189261081Sasomers	ATF_TP_ADD_TC(tp, pipe_8k_128k);
1190261081Sasomers	ATF_TP_ADD_TC(tp, pipe_128k_8k);
1191261081Sasomers	ATF_TP_ADD_TC(tp, pipe_128k_128k);
1192261081Sasomers
1193261081Sasomers	return atf_no_error();
1194261081Sasomers}
1195