unix_seqpacket_test.c revision 262133
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: head/tests/sys/kern/unix_seqpacket_test.c 262133 2014-02-17 22:06:52Z asomers $");
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
46261081Sasomersvoid
47261081Sasomersdo_socketpair(int *sv)
48261081Sasomers{
49261081Sasomers	int s;
50261081Sasomers
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
58261081Sasomersvoid
59261081Sasomersdo_socketpair_nonblocking(int *sv)
60261081Sasomers{
61261081Sasomers	int s;
62261081Sasomers
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
72261081Sasomers/*
73261081Sasomers * Returns a pair of sockets made the hard way: bind, listen, connect & accept
74261081Sasomers * @return	const char* The path to the socket
75261081Sasomers */
76261081Sasomersconst 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	ATF_CHECK_EQ(0, err);
95261081Sasomers
96261081Sasomers	/* Create the other socket */
97261081Sasomers	s2 = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
98261081Sasomers	ATF_REQUIRE(s2 >= 0);
99261081Sasomers	err = connect(s2, (struct sockaddr*)&sun, sizeof(sun));
100261081Sasomers	if (err != 0) {
101261081Sasomers		perror("connect");
102261081Sasomers		atf_tc_fail("connect(2) failed");
103261081Sasomers	}
104261081Sasomers
105261081Sasomers	/* Accept it */
106261081Sasomers	s1 = accept(s, NULL, NULL);
107261081Sasomers	if (s1 == -1) {
108261081Sasomers		perror("accept");
109261081Sasomers		atf_tc_fail("accept(2) failed");
110261081Sasomers	}
111261081Sasomers
112261081Sasomers	sv[0] = s1;
113261081Sasomers	sv[1] = s2;
114261081Sasomers	return (path);
115261081Sasomers}
116261081Sasomers
117261081Sasomersstatic volatile sig_atomic_t got_sigpipe = 0;
118261081Sasomersstatic void
119261081Sasomersshutdown_send_sigpipe_handler(int x)
120261081Sasomers{
121261081Sasomers	got_sigpipe = 1;
122261081Sasomers}
123261081Sasomers
124261081Sasomers/*
125261081Sasomers * Parameterized test function bodies
126261081Sasomers */
127261081Sasomersvoid
128261081Sasomerstest_eagain(size_t sndbufsize, size_t rcvbufsize)
129261081Sasomers{
130261081Sasomers	int i;
131261081Sasomers	int sv[2];
132261081Sasomers	const size_t totalsize = (sndbufsize + rcvbufsize) * 2;
133261081Sasomers	const size_t pktsize = MIN(sndbufsize, rcvbufsize) / 4;
134261081Sasomers	char sndbuf[pktsize];
135261081Sasomers	char recv_buf[pktsize];
136261081Sasomers	ssize_t ssize, rsize;
137261081Sasomers
138261081Sasomers	/* setup the socket pair */
139262133Sasomers	do_socketpair_nonblocking(sv);
140261081Sasomers	/* Setup the buffers */
141261081Sasomers	ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
142261081Sasomers	    sizeof(sndbufsize)));
143261081Sasomers	ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
144261081Sasomers	    sizeof(rcvbufsize)));
145261081Sasomers
146261081Sasomers	bzero(sndbuf, pktsize);
147261081Sasomers	/* Send data until we get EAGAIN */
148261081Sasomers	for(i=0; i < totalsize / pktsize; i++) {
149261081Sasomers		ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
150261081Sasomers		if (ssize == -1) {
151261081Sasomers			if (errno == EAGAIN)
152261081Sasomers				atf_tc_pass();
153261081Sasomers			else {
154261081Sasomers				perror("send");
155261081Sasomers				atf_tc_fail("send returned < 0 but not EAGAIN");
156261081Sasomers			}
157261081Sasomers		}
158261081Sasomers	}
159261081Sasomers	atf_tc_fail("Never got EAGAIN");
160261081Sasomers}
161261081Sasomers
162261081Sasomersvoid
163261081Sasomerstest_sendrecv_symmetric_buffers(size_t bufsize, int blocking) {
164261081Sasomers	int s;
165261081Sasomers	int sv[2];
166261081Sasomers	const size_t pktsize = bufsize / 2;
167261081Sasomers	char sndbuf[pktsize];
168261081Sasomers	char recv_buf[pktsize];
169261081Sasomers	ssize_t ssize, rsize;
170261081Sasomers
171261081Sasomers	/* setup the socket pair */
172261081Sasomers	if (blocking)
173261081Sasomers		do_socketpair(sv);
174261081Sasomers	else
175261081Sasomers		do_socketpair_nonblocking(sv);
176261081Sasomers
177261081Sasomers	/* Setup the buffers */
178261081Sasomers	s = setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize));
179261081Sasomers	ATF_REQUIRE_EQ(0, s);
180261081Sasomers	s = setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(bufsize));
181261081Sasomers	ATF_REQUIRE_EQ(0, s);
182261081Sasomers
183261081Sasomers	/* Fill the send buffer */
184261081Sasomers	bzero(sndbuf, pktsize);
185261081Sasomers
186261081Sasomers	/* send and receive the packet */
187261081Sasomers	ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
188261081Sasomers	if (ssize < 0) {
189261081Sasomers		perror("send");
190261081Sasomers		atf_tc_fail("send returned < 0");
191261081Sasomers	}
192261081Sasomers	ATF_CHECK_EQ_MSG(pktsize, ssize, "expected %zd=send(...) but got %zd",
193261081Sasomers	    pktsize, ssize);
194261081Sasomers
195261081Sasomers	rsize = recv(sv[1], recv_buf, pktsize, MSG_WAITALL);
196261081Sasomers	if (rsize < 0) {
197261081Sasomers		perror("recv");
198261081Sasomers		atf_tc_fail("recv returned < 0");
199261081Sasomers	}
200261081Sasomers	ATF_CHECK_EQ_MSG(pktsize, rsize, "expected %zd=send(...) but got %zd",
201261081Sasomers	    pktsize, rsize);
202261081Sasomers}
203261081Sasomers
204261081Sasomersvoid
205261081Sasomerstest_pipe_simulator(size_t sndbufsize, size_t rcvbufsize)
206261081Sasomers{
207261081Sasomers	int s, num_sent, num_received;
208261081Sasomers	int sv[2];
209261081Sasomers	const size_t pktsize = MIN(sndbufsize, rcvbufsize) / 4;
210261081Sasomers	int numpkts;
211261081Sasomers	char sndbuf[pktsize];
212261081Sasomers	char rcvbuf[pktsize];
213261081Sasomers	char comparebuf[pktsize];
214261081Sasomers	ssize_t ssize, rsize;
215261081Sasomers	bool currently_sending = true;
216261081Sasomers
217261081Sasomers	/* setup the socket pair */
218261081Sasomers	do_socketpair_nonblocking(sv);
219261081Sasomers	/* Setup the buffers */
220261081Sasomers	ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
221261081Sasomers	    sizeof(sndbufsize)));
222261081Sasomers	ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
223261081Sasomers	    sizeof(rcvbufsize)));
224261081Sasomers
225261081Sasomers	/* Send a total amount of data comfortably greater than the buffers */
226261081Sasomers	numpkts = MAX(sndbufsize, rcvbufsize) * 8 / pktsize;
227261081Sasomers	for (num_sent=0, num_received=0;
228261081Sasomers	     num_sent < numpkts || num_received < numpkts; ) {
229261081Sasomers		if (currently_sending && num_sent < numpkts) {
230261081Sasomers			/* The simulated sending process */
231261081Sasomers			/* fill the buffer */
232261081Sasomers			memset(sndbuf, num_sent, pktsize);
233261081Sasomers			ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
234261081Sasomers			if (ssize < 0) {
235261081Sasomers				/*
236261081Sasomers				 * XXX: This is bug-compatible with the kernel.
237261081Sasomers				 * The kernel returns EMSGSIZE when it should
238261081Sasomers				 * return EAGAIN
239261081Sasomers				 */
240261081Sasomers				if (errno == EAGAIN || errno == EMSGSIZE)
241261081Sasomers					currently_sending = false;
242261081Sasomers				else {
243261081Sasomers					perror("send");
244261081Sasomers					atf_tc_fail("send failed");
245261081Sasomers				}
246261081Sasomers			} else  {
247261081Sasomers				ATF_CHECK_EQ_MSG(pktsize, ssize,
248261081Sasomers				    "expected %zd=send(...) but got %zd",
249261081Sasomers				    pktsize, ssize);
250261081Sasomers				num_sent++;
251261081Sasomers			}
252261081Sasomers		} else {
253261081Sasomers			/* The simulated receiving process */
254261081Sasomers			rsize = recv(sv[1], rcvbuf, pktsize, MSG_WAITALL);
255261081Sasomers			if (rsize < 0) {
256261081Sasomers				if (errno == EAGAIN) {
257261081Sasomers					currently_sending = true;
258261081Sasomers					ATF_REQUIRE_MSG(num_sent < numpkts,
259261081Sasomers					    "Packets were lost!");
260261081Sasomers				}
261261081Sasomers				else {
262261081Sasomers					perror("recv");
263261081Sasomers					atf_tc_fail("recv failed");
264261081Sasomers				}
265261081Sasomers			} else  {
266261081Sasomers				ATF_CHECK_EQ_MSG(pktsize, rsize,
267261081Sasomers				    "expected %zd=recv(...) but got %zd",
268261081Sasomers				    pktsize, rsize);
269261081Sasomers				memset(comparebuf, num_received, pktsize);
270261081Sasomers				ATF_CHECK_EQ_MSG(0, memcmp(comparebuf, rcvbuf,
271261081Sasomers				    			   pktsize),
272261081Sasomers				    "Received data miscompare");
273261081Sasomers				num_received++;
274261081Sasomers			}
275261081Sasomers		}
276261081Sasomers	}
277261081Sasomers}
278261081Sasomers
279261081Sasomerstypedef struct {
280261081Sasomers	ssize_t	pktsize;
281261081Sasomers	int	numpkts;
282261081Sasomers	int	so;
283261081Sasomers} test_pipe_thread_data_t;
284261081Sasomers
285261081Sasomersstatic void*
286261081Sasomerstest_pipe_writer(void* args)
287261081Sasomers{
288261081Sasomers	test_pipe_thread_data_t* td = args;
289261081Sasomers	char sndbuf[td->pktsize];
290261081Sasomers	ssize_t ssize;
291261081Sasomers	int i;
292261081Sasomers
293261081Sasomers	for(i=0; i < td->numpkts; i++) {
294261081Sasomers			memset(sndbuf, i, td->pktsize);
295261081Sasomers			ssize = send(td->so, sndbuf, td->pktsize, MSG_EOR);
296261081Sasomers			if (ssize < 0) {
297261081Sasomers				perror("send");
298261081Sasomers				atf_tc_fail("send returned < 0");
299261081Sasomers			}
300261081Sasomers			ATF_CHECK_EQ_MSG(td->pktsize, ssize,
301261081Sasomers			    		 "expected %zd=send(...) but got %zd",
302261081Sasomers			    		  td->pktsize, ssize);
303261081Sasomers	}
304261081Sasomers	return (0);
305261081Sasomers}
306261081Sasomers
307261081Sasomersstatic void*
308261081Sasomerstest_pipe_reader(void* args)
309261081Sasomers{
310261081Sasomers	test_pipe_thread_data_t* td = args;
311261081Sasomers	char rcvbuf[td->pktsize];
312261081Sasomers	char comparebuf[td->pktsize];
313261081Sasomers	ssize_t rsize;
314261081Sasomers	int i, d;
315261081Sasomers
316261081Sasomers	for(i=0; i < td->numpkts; i++) {
317261081Sasomers		memset(comparebuf, i, td->pktsize);
318261081Sasomers		rsize = recv(td->so, rcvbuf, td->pktsize, MSG_WAITALL);
319261081Sasomers		if (rsize < 0) {
320261081Sasomers			perror("recv");
321261081Sasomers			atf_tc_fail("recv returned < 0");
322261081Sasomers		}
323261081Sasomers		ATF_CHECK_EQ_MSG(td->pktsize, rsize,
324261081Sasomers		    		 "expected %zd=send(...) but got %zd",
325261081Sasomers				 td->pktsize, rsize);
326261081Sasomers		d = memcmp(comparebuf, rcvbuf, td->pktsize);
327261081Sasomers		ATF_CHECK_EQ_MSG(0, d,
328261081Sasomers		    		 "Received data miscompare on packet %d", i);
329261081Sasomers	}
330261081Sasomers	return (0);
331261081Sasomers}
332261081Sasomers
333261081Sasomers
334261081Sasomersvoid
335261081Sasomerstest_pipe(size_t sndbufsize, size_t rcvbufsize)
336261081Sasomers{
337261081Sasomers	test_pipe_thread_data_t writer_data, reader_data;
338261081Sasomers	pthread_t writer, reader;
339261081Sasomers	int num_sent, num_received;
340261081Sasomers	int sv[2];
341261081Sasomers	const size_t pktsize = MIN(sndbufsize, rcvbufsize) / 4;
342261081Sasomers	int numpkts;
343261081Sasomers
344261081Sasomers	/* setup the socket pair */
345261081Sasomers	do_socketpair(sv);
346261081Sasomers	/* Setup the buffers */
347261081Sasomers	ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
348261081Sasomers	    sizeof(sndbufsize)));
349261081Sasomers	ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
350261081Sasomers	    sizeof(rcvbufsize)));
351261081Sasomers
352261081Sasomers	/* Send a total amount of data comfortably greater than the buffers */
353261081Sasomers	numpkts = MAX(sndbufsize, rcvbufsize) * 8 / pktsize;
354261081Sasomers
355261081Sasomers	/* Start the child threads */
356261081Sasomers	writer_data.pktsize = pktsize;
357261081Sasomers	writer_data.numpkts = numpkts;
358261081Sasomers	writer_data.so = sv[0];
359261081Sasomers	reader_data.pktsize = pktsize;
360261081Sasomers	reader_data.numpkts = numpkts;
361261081Sasomers	reader_data.so = sv[1];
362261081Sasomers	ATF_REQUIRE_EQ(0, pthread_create(&writer, NULL, test_pipe_writer,
363261081Sasomers	    				 (void*)&writer_data));
364261081Sasomers	ATF_REQUIRE_EQ(0, pthread_create(&reader, NULL, test_pipe_reader,
365261081Sasomers	    				 (void*)&reader_data));
366261081Sasomers
367261081Sasomers	/* Join the children */
368261081Sasomers	ATF_REQUIRE_EQ(0, pthread_join(writer, NULL));
369261081Sasomers	ATF_REQUIRE_EQ(0, pthread_join(reader, NULL));
370261081Sasomers}
371261081Sasomers
372261081Sasomers
373261081Sasomers/*
374261081Sasomers * Test Cases
375261081Sasomers */
376261081Sasomers
377261081Sasomers/* Create a SEQPACKET socket */
378261081SasomersATF_TC_WITHOUT_HEAD(create_socket);
379261081SasomersATF_TC_BODY(create_socket, tc)
380261081Sasomers{
381261081Sasomers	int s;
382261081Sasomers
383261081Sasomers	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
384261081Sasomers	ATF_CHECK(s >= 0);
385261081Sasomers}
386261081Sasomers
387261081Sasomers/* Create SEQPACKET sockets using socketpair(2) */
388261081SasomersATF_TC_WITHOUT_HEAD(create_socketpair);
389261081SasomersATF_TC_BODY(create_socketpair, tc)
390261081Sasomers{
391261081Sasomers	int sv[2];
392261081Sasomers	int s;
393261081Sasomers
394261081Sasomers	s = socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, sv);
395261081Sasomers	ATF_CHECK_EQ(0, s);
396261081Sasomers	ATF_CHECK(sv[0] >= 0);
397261081Sasomers	ATF_CHECK(sv[1] >= 0);
398261081Sasomers	ATF_CHECK(sv[0] != sv[1]);
399261081Sasomers}
400261081Sasomers
401261081Sasomers/* Call listen(2) without first calling bind(2).  It should fail */
402261081SasomersATF_TC_WITHOUT_HEAD(listen_unbound);
403261081SasomersATF_TC_BODY(listen_unbound, tc)
404261081Sasomers{
405261081Sasomers	int s, r;
406261081Sasomers
407261081Sasomers	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
408261081Sasomers	ATF_REQUIRE(s > 0);
409261081Sasomers	r = listen(s, -1);
410261081Sasomers	/* expect listen to fail since we haven't called bind(2) */
411261081Sasomers	ATF_CHECK(r != 0);
412261081Sasomers}
413261081Sasomers
414261081Sasomers/* Bind the socket to a file */
415261081SasomersATF_TC_WITHOUT_HEAD(bind);
416261081SasomersATF_TC_BODY(bind, tc)
417261081Sasomers{
418261081Sasomers	struct sockaddr_un sun;
419261081Sasomers	/* ATF's isolation mechanisms will guarantee uniqueness of this file */
420261081Sasomers	const char *path = "sock";
421261081Sasomers	int s, r;
422261081Sasomers
423261081Sasomers	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
424261081Sasomers	ATF_REQUIRE(s >= 0);
425261081Sasomers
426261081Sasomers	bzero(&sun, sizeof(sun));
427261081Sasomers	sun.sun_family = AF_LOCAL;
428261081Sasomers	sun.sun_len = sizeof(sun);
429261081Sasomers	strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
430261081Sasomers	r = bind(s, (struct sockaddr *)&sun, sizeof(sun));
431261081Sasomers	ATF_CHECK_EQ(0, r);
432261081Sasomers}
433261081Sasomers
434261081Sasomers/* listen(2) a socket that is already bound(2) should succeed */
435261081SasomersATF_TC_WITHOUT_HEAD(listen_bound);
436261081SasomersATF_TC_BODY(listen_bound, 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, l;
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	l = listen(s, -1);
452261081Sasomers	ATF_CHECK_EQ(0, r);
453261081Sasomers	ATF_CHECK_EQ(0, l);
454261081Sasomers}
455261081Sasomers
456261081Sasomers/* connect(2) can make a connection */
457261081SasomersATF_TC_WITHOUT_HEAD(connect);
458261081SasomersATF_TC_BODY(connect, tc)
459261081Sasomers{
460261081Sasomers	struct sockaddr_un sun;
461261081Sasomers	/* ATF's isolation mechanisms will guarantee uniqueness of this file */
462261081Sasomers	const char *path = "sock";
463261081Sasomers	int s, r, err, l, s2;
464261081Sasomers
465261081Sasomers	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
466261081Sasomers	ATF_REQUIRE(s >= 0);
467261081Sasomers
468261081Sasomers	bzero(&sun, sizeof(sun));
469261081Sasomers	sun.sun_family = AF_LOCAL;
470261081Sasomers	sun.sun_len = sizeof(sun);
471261081Sasomers	strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
472261081Sasomers	r = bind(s, (struct sockaddr *)&sun, sizeof(sun));
473261081Sasomers	l = listen(s, -1);
474261081Sasomers	ATF_CHECK_EQ(0, r);
475261081Sasomers	ATF_CHECK_EQ(0, l);
476261081Sasomers
477261081Sasomers	/* Create the other socket */
478261081Sasomers	s2 = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
479261081Sasomers	ATF_REQUIRE(s2 >= 0);
480261081Sasomers	err = connect(s2, (struct sockaddr*)&sun, sizeof(sun));
481261081Sasomers	if (err != 0) {
482261081Sasomers		perror("connect");
483261081Sasomers		atf_tc_fail("connect(2) failed");
484261081Sasomers	}
485261081Sasomers}
486261081Sasomers
487261081Sasomers/* accept(2) can receive a connection */
488261081SasomersATF_TC_WITHOUT_HEAD(accept);
489261081SasomersATF_TC_BODY(accept, tc)
490261081Sasomers{
491261081Sasomers	int sv[2];
492261081Sasomers
493261081Sasomers	mk_pair_of_sockets(sv);
494261081Sasomers}
495261081Sasomers
496261081Sasomers
497261081Sasomers/* Set O_NONBLOCK on the socket */
498261081SasomersATF_TC_WITHOUT_HEAD(fcntl_nonblock);
499261081SasomersATF_TC_BODY(fcntl_nonblock, tc)
500261081Sasomers{
501261081Sasomers	int s;
502261081Sasomers
503261081Sasomers	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
504261081Sasomers	ATF_REQUIRE(s >= 0);
505261081Sasomers	if (fcntl(s, F_SETFL, O_NONBLOCK) == -1) {
506261081Sasomers		perror("fcntl");
507261081Sasomers		atf_tc_fail("fcntl failed");
508261081Sasomers	}
509261081Sasomers}
510261081Sasomers
511261081Sasomers/* Resize the send and receive buffers */
512261081SasomersATF_TC_WITHOUT_HEAD(resize_buffers);
513261081SasomersATF_TC_BODY(resize_buffers, tc)
514261081Sasomers{
515261081Sasomers	int s;
516261081Sasomers	int sndbuf = 12345;
517261081Sasomers	int rcvbuf = 23456;
518261081Sasomers	int xs, xr;
519261081Sasomers	socklen_t sl = sizeof(xs);
520261081Sasomers
521261081Sasomers	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
522261081Sasomers	ATF_REQUIRE(s >= 0);
523261081Sasomers
524261081Sasomers	printf("                       Socket Buffer Sizes\n");
525261081Sasomers	printf("                              | SNDBUF  | RCVBUF  |\n");
526261081Sasomers	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_SNDBUF, &xs, &sl));
527261081Sasomers	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_RCVBUF, &xr, &sl));
528261081Sasomers	printf("Default                       | %7d | %7d |\n", xs, xr);
529261081Sasomers
530261081Sasomers	if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf)) != 0){
531261081Sasomers		perror("setsockopt");
532261081Sasomers		atf_tc_fail("setsockopt(SO_SNDBUF) failed");
533261081Sasomers	}
534261081Sasomers	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_SNDBUF, &xs, &sl));
535261081Sasomers	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_RCVBUF, &xr, &sl));
536261081Sasomers	printf("After changing SNDBUF         | %7d | %7d |\n", xs, xr);
537261081Sasomers
538261081Sasomers	if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)) != 0){
539261081Sasomers		perror("setsockopt");
540261081Sasomers		atf_tc_fail("setsockopt(SO_RCVBUF) failed");
541261081Sasomers	}
542261081Sasomers	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_SNDBUF, &xs, &sl));
543261081Sasomers	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_RCVBUF, &xr, &sl));
544261081Sasomers	printf("After changing RCVBUF         | %7d | %7d |\n", xs, xr);
545261081Sasomers}
546261081Sasomers
547261081Sasomers/*
548261081Sasomers * Resize the send and receive buffers of a connected socketpair
549261081Sasomers * Print some useful debugging info too
550261081Sasomers */
551261081SasomersATF_TC_WITHOUT_HEAD(resize_connected_buffers);
552261081SasomersATF_TC_BODY(resize_connected_buffers, tc)
553261081Sasomers{
554261081Sasomers	int sv[2];
555261081Sasomers	int sndbuf = 12345;
556261081Sasomers	int rcvbuf = 23456;
557261081Sasomers	int err;
558261081Sasomers	int ls, lr, rs, rr;
559261081Sasomers	socklen_t sl = sizeof(ls);
560261081Sasomers
561261081Sasomers	/* setup the socket pair */
562261081Sasomers	do_socketpair(sv);
563261081Sasomers
564261081Sasomers	printf("                       Socket Buffer Sizes\n");
565261081Sasomers	printf("                              | Left Socket       | Right Socket      |\n");
566261081Sasomers	printf("                              | SNDBUF  | RCVBUF  | SNDBUF  | RCVBUF  |\n");
567261081Sasomers	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &ls, &sl));
568261081Sasomers	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &lr, &sl));
569261081Sasomers	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &rs, &sl));
570261081Sasomers	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rr, &sl));
571261081Sasomers	printf("Default                       | %7d | %7d | %7d | %7d |\n",
572261081Sasomers	    ls, lr, rs, rr);
573261081Sasomers
574261081Sasomers	/* Update one side's send buffer */
575261081Sasomers	err = setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf));
576261081Sasomers	if (err != 0){
577261081Sasomers		perror("setsockopt");
578261081Sasomers		atf_tc_fail("setsockopt(SO_SNDBUF) failed");
579261081Sasomers	}
580261081Sasomers
581261081Sasomers	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &ls, &sl));
582261081Sasomers	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &lr, &sl));
583261081Sasomers	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &rs, &sl));
584261081Sasomers	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rr, &sl));
585261081Sasomers	printf("After changing Left's SNDBUF  | %7d | %7d | %7d | %7d |\n",
586261081Sasomers	    ls, lr, rs, rr);
587261081Sasomers
588261081Sasomers	/* Update the same side's receive buffer */
589261081Sasomers	err = setsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf));
590261081Sasomers	if (err != 0){
591261081Sasomers		perror("setsockopt");
592261081Sasomers		atf_tc_fail("setsockopt(SO_RCVBUF) failed");
593261081Sasomers	}
594261081Sasomers
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("After changing Left's RCVBUF  | %7d | %7d | %7d | %7d |\n",
600261081Sasomers	    ls, lr, rs, rr);
601261081Sasomers}
602261081Sasomers
603261081Sasomers
604261081Sasomers/* send(2) and recv(2) a single short record */
605261081SasomersATF_TC_WITHOUT_HEAD(send_recv);
606261081SasomersATF_TC_BODY(send_recv, tc)
607261081Sasomers{
608261081Sasomers	int s;
609261081Sasomers	int sv[2];
610261081Sasomers	const int bufsize = 64;
611261081Sasomers	const char *data = "data";
612261081Sasomers	char recv_buf[bufsize];
613261081Sasomers	size_t datalen;
614261081Sasomers	ssize_t ssize, rsize;
615261081Sasomers
616261081Sasomers	/* setup the socket pair */
617261081Sasomers	do_socketpair(sv);
618261081Sasomers
619261081Sasomers	/* send and receive a small packet */
620261081Sasomers	datalen = strlen(data) + 1;	/* +1 for the null */
621261081Sasomers	ssize = send(sv[0], data, datalen, MSG_EOR);
622261081Sasomers	if (ssize < 0) {
623261081Sasomers		perror("send");
624261081Sasomers		atf_tc_fail("send returned < 0");
625261081Sasomers	}
626261081Sasomers	ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd",
627261081Sasomers	    datalen, ssize);
628261081Sasomers
629261081Sasomers	rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL);
630261081Sasomers	ATF_CHECK_EQ(datalen, rsize);
631261081Sasomers}
632261081Sasomers
633261081Sasomers/* sendto(2) and recvfrom(2) a single short record
634261081Sasomers * According to The Open Group Base Specifications Issue 6 IEEE Std 1003.1, 2004
635261081Sasomers * Edition, sendto(2) is exactly the same as send(2) on a connection-mode socket
636261081Sasomers *
637261081Sasomers * According to the same spec, not all protocols are required to provide the
638261081Sasomers * source addres in recvfrom(2).
639261081Sasomers */
640261081SasomersATF_TC_WITHOUT_HEAD(sendto_recvfrom);
641261081SasomersATF_TC_BODY(sendto_recvfrom, tc)
642261081Sasomers{
643261081Sasomers	const char* path;
644261081Sasomers	struct sockaddr_storage from;
645261081Sasomers	int s;
646261081Sasomers	int sv[2];
647261081Sasomers	const int bufsize = 64;
648261081Sasomers	const char *data = "data";
649261081Sasomers	char recv_buf[bufsize];
650261081Sasomers	size_t datalen;
651261081Sasomers	ssize_t ssize, rsize;
652261081Sasomers	socklen_t fromlen;
653261081Sasomers
654261081Sasomers	/* setup the socket pair */
655261081Sasomers	path = mk_pair_of_sockets(sv);
656261081Sasomers
657261081Sasomers	/* send and receive a small packet */
658261081Sasomers	datalen = strlen(data) + 1;	/* +1 for the null */
659261081Sasomers	ssize = sendto(sv[0], data, datalen, MSG_EOR, NULL, 0);
660261081Sasomers	if (ssize < 0) {
661261081Sasomers		perror("send");
662261081Sasomers		atf_tc_fail("send returned < 0");
663261081Sasomers	}
664261081Sasomers	ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd",
665261081Sasomers	    datalen, ssize);
666261081Sasomers
667261081Sasomers	fromlen = sizeof(from);
668261081Sasomers	rsize = recvfrom(sv[1], recv_buf, bufsize, MSG_WAITALL,
669261081Sasomers	    (struct sockaddr*)&from, &fromlen);
670261081Sasomers	if (ssize < 0) {
671261081Sasomers		perror("recvfrom");
672261081Sasomers		atf_tc_fail("recvfrom returned < 0");
673261081Sasomers	}
674261081Sasomers	ATF_CHECK_EQ(datalen, rsize);
675261081Sasomers
676261081Sasomers	/*
677261081Sasomers	 * FreeBSD does not currently provide the source address for SEQ_PACKET
678261081Sasomers	 * AF_UNIX sockets, and POSIX does not require it, so these two checks
679261081Sasomers	 * are disabled.  If FreeBSD gains that feature in the future, then
680261081Sasomers	 * these checks may be reenabled
681261081Sasomers	 */
682261081Sasomers	/* ATF_CHECK_EQ(PF_LOCAL, from.ss_family); */
683261081Sasomers	/* ATF_CHECK_STREQ(path, ((struct sockaddr_un*)&from)->sun_path); */
684261081Sasomers}
685261081Sasomers
686261081Sasomers/*
687261081Sasomers * send(2) and recv(2) a single short record with sockets created the
688261081Sasomers * traditional way, involving bind, listen, connect, and accept
689261081Sasomers */
690261081SasomersATF_TC_WITHOUT_HEAD(send_recv_with_connect);
691261081SasomersATF_TC_BODY(send_recv_with_connect, tc)
692261081Sasomers{
693261081Sasomers	const char* path;
694261081Sasomers	int sv[2];
695261081Sasomers	const int bufsize = 64;
696261081Sasomers	const char *data = "data";
697261081Sasomers	char recv_buf[bufsize];
698261081Sasomers	size_t datalen;
699261081Sasomers	ssize_t ssize, rsize;
700261081Sasomers
701261081Sasomers	mk_pair_of_sockets(sv);
702261081Sasomers
703261081Sasomers	/* send and receive a small packet */
704261081Sasomers	datalen = strlen(data) + 1;	/* +1 for the null */
705261081Sasomers	ssize = send(sv[0], data, datalen, MSG_EOR);
706261081Sasomers	if (ssize < 0) {
707261081Sasomers		perror("send");
708261081Sasomers		atf_tc_fail("send returned < 0");
709261081Sasomers	}
710261081Sasomers	ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd",
711261081Sasomers	    datalen, ssize);
712261081Sasomers
713261081Sasomers	rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL);
714261081Sasomers	ATF_CHECK_EQ(datalen, rsize);
715261081Sasomers}
716261081Sasomers
717261081Sasomers/* send(2) should fail on a shutdown socket */
718261081SasomersATF_TC_WITHOUT_HEAD(shutdown_send);
719261081SasomersATF_TC_BODY(shutdown_send, tc)
720261081Sasomers{
721261081Sasomers	int s;
722261081Sasomers	const char *data = "data";
723261081Sasomers	ssize_t ssize;
724261081Sasomers
725261081Sasomers	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
726261081Sasomers	ATF_CHECK(s >= 0);
727261081Sasomers	ATF_CHECK_EQ(0, shutdown(s, SHUT_RDWR));
728261081Sasomers	/* USE MSG_NOSIGNAL so we don't get SIGPIPE */
729261081Sasomers	ssize = send(s, data, sizeof(data), MSG_EOR | MSG_NOSIGNAL);
730261081Sasomers	ATF_CHECK_EQ(EPIPE, errno);
731261081Sasomers	ATF_CHECK_EQ(-1, ssize);
732261081Sasomers}
733261081Sasomers
734261081Sasomers/* send(2) should cause SIGPIPE on a shutdown socket */
735261081SasomersATF_TC_WITHOUT_HEAD(shutdown_send_sigpipe);
736261081SasomersATF_TC_BODY(shutdown_send_sigpipe, tc)
737261081Sasomers{
738261081Sasomers	int s;
739261081Sasomers	const char *data = "data";
740261081Sasomers	ssize_t ssize;
741261081Sasomers
742261081Sasomers	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
743261081Sasomers	ATF_CHECK(s >= 0);
744261081Sasomers	ATF_CHECK_EQ(0, shutdown(s, SHUT_RDWR));
745261081Sasomers	ATF_REQUIRE(SIG_ERR != signal(SIGPIPE, shutdown_send_sigpipe_handler));
746261081Sasomers	ssize = send(s, data, sizeof(data), MSG_EOR);
747261081Sasomers	ATF_CHECK_EQ(1, got_sigpipe);
748261081Sasomers}
749261081Sasomers
750261081Sasomers/* nonblocking send(2) and recv(2) a single short record */
751261081SasomersATF_TC_WITHOUT_HEAD(send_recv_nonblocking);
752261081SasomersATF_TC_BODY(send_recv_nonblocking, tc)
753261081Sasomers{
754261081Sasomers	int s;
755261081Sasomers	int sv[2];
756261081Sasomers	const int bufsize = 64;
757261081Sasomers	const char *data = "data";
758261081Sasomers	char recv_buf[bufsize];
759261081Sasomers	size_t datalen;
760261081Sasomers	ssize_t ssize, rsize;
761261081Sasomers
762261081Sasomers	/* setup the socket pair */
763261081Sasomers	do_socketpair_nonblocking(sv);
764261081Sasomers
765261081Sasomers	/* Verify that there is nothing to receive */
766261081Sasomers	rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL);
767261081Sasomers	ATF_CHECK_EQ(EAGAIN, errno);
768261081Sasomers	ATF_CHECK_EQ(-1, rsize);
769261081Sasomers
770261081Sasomers	/* send and receive a small packet */
771261081Sasomers	datalen = strlen(data) + 1;	/* +1 for the null */
772261081Sasomers	ssize = send(sv[0], data, datalen, MSG_EOR);
773261081Sasomers	if (ssize < 0) {
774261081Sasomers		perror("send");
775261081Sasomers		atf_tc_fail("send returned < 0");
776261081Sasomers	}
777261081Sasomers	ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd",
778261081Sasomers	    datalen, ssize);
779261081Sasomers
780261081Sasomers	rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL);
781261081Sasomers	ATF_CHECK_EQ(datalen, rsize);
782261081Sasomers}
783261081Sasomers
784261081Sasomers/*
785261081Sasomers * We should get EMSGSIZE if we try to send a message larger than the socket
786261081Sasomers * buffer, with blocking sockets
787261081Sasomers */
788261081SasomersATF_TC_WITHOUT_HEAD(emsgsize);
789261081SasomersATF_TC_BODY(emsgsize, tc)
790261081Sasomers{
791261081Sasomers	int s;
792261081Sasomers	int sv[2];
793261081Sasomers	const size_t sndbufsize = 8192;
794261081Sasomers	const size_t rcvbufsize = 8192;
795261081Sasomers	const size_t pktsize = (sndbufsize + rcvbufsize) * 2;
796261081Sasomers	char sndbuf[pktsize];
797261081Sasomers	char recv_buf[pktsize];
798261081Sasomers	ssize_t ssize, rsize;
799261081Sasomers
800261081Sasomers	/* setup the socket pair */
801261081Sasomers	do_socketpair(sv);
802261081Sasomers	/* Setup the buffers */
803261081Sasomers	ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
804261081Sasomers	    sizeof(sndbufsize)));
805261081Sasomers	ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
806261081Sasomers	    sizeof(rcvbufsize)));
807261081Sasomers
808261081Sasomers	ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
809261081Sasomers	ATF_CHECK_EQ(EMSGSIZE, errno);
810261081Sasomers	ATF_CHECK_EQ(-1, ssize);
811261081Sasomers}
812261081Sasomers
813261081Sasomers/*
814261081Sasomers * We should get EMSGSIZE if we try to send a message larger than the socket
815261081Sasomers * buffer, with nonblocking sockets
816261081Sasomers */
817261081SasomersATF_TC_WITHOUT_HEAD(emsgsize_nonblocking);
818261081SasomersATF_TC_BODY(emsgsize_nonblocking, tc)
819261081Sasomers{
820261081Sasomers	int s;
821261081Sasomers	int sv[2];
822261081Sasomers	const size_t sndbufsize = 8192;
823261081Sasomers	const size_t rcvbufsize = 8192;
824261081Sasomers	const size_t pktsize = (sndbufsize + rcvbufsize) * 2;
825261081Sasomers	char sndbuf[pktsize];
826261081Sasomers	char recv_buf[pktsize];
827261081Sasomers	ssize_t ssize, rsize;
828261081Sasomers
829261081Sasomers	/* setup the socket pair */
830261081Sasomers	do_socketpair_nonblocking(sv);
831261081Sasomers	/* Setup the buffers */
832261081Sasomers	ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
833261081Sasomers	    sizeof(sndbufsize)));
834261081Sasomers	ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
835261081Sasomers	    sizeof(rcvbufsize)));
836261081Sasomers
837261081Sasomers	ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
838261081Sasomers	ATF_CHECK_EQ(EMSGSIZE, errno);
839261081Sasomers	ATF_CHECK_EQ(-1, ssize);
840261081Sasomers}
841261081Sasomers
842261081Sasomers
843261081Sasomers/*
844261081Sasomers * We should get EAGAIN if we try to send a message larger than the socket
845261081Sasomers * buffer, with nonblocking sockets.  Test with several different sockbuf sizes
846261081Sasomers */
847261081SasomersATF_TC_WITHOUT_HEAD(eagain_8k_8k);
848261081SasomersATF_TC_BODY(eagain_8k_8k, tc)
849261081Sasomers{
850261081Sasomers	atf_tc_expect_fail("PR kern/185812 send(2) on a UNIX domain SEQPACKET socket returns EMSGSIZE instead of EAGAIN");
851261081Sasomers	test_eagain(8192, 8192);
852261081Sasomers}
853261081SasomersATF_TC_WITHOUT_HEAD(eagain_8k_128k);
854261081SasomersATF_TC_BODY(eagain_8k_128k, tc)
855261081Sasomers{
856261081Sasomers	atf_tc_expect_fail("PR kern/185812 send(2) on a UNIX domain SEQPACKET socket returns EMSGSIZE instead of EAGAIN");
857261081Sasomers	test_eagain(8192, 131072);
858261081Sasomers}
859261081SasomersATF_TC_WITHOUT_HEAD(eagain_128k_8k);
860261081SasomersATF_TC_BODY(eagain_128k_8k, tc)
861261081Sasomers{
862261081Sasomers	atf_tc_expect_fail("PR kern/185812 send(2) on a UNIX domain SEQPACKET socket returns EMSGSIZE instead of EAGAIN");
863261081Sasomers	test_eagain(131072, 8192);
864261081Sasomers}
865261081SasomersATF_TC_WITHOUT_HEAD(eagain_128k_128k);
866261081SasomersATF_TC_BODY(eagain_128k_128k, tc)
867261081Sasomers{
868261081Sasomers	atf_tc_expect_fail("PR kern/185812 send(2) on a UNIX domain SEQPACKET socket returns EMSGSIZE instead of EAGAIN");
869261081Sasomers	test_eagain(131072, 131072);
870261081Sasomers}
871261081Sasomers
872261081Sasomers
873261081Sasomers/*
874261081Sasomers * nonblocking send(2) and recv(2) of several records, which should collectively
875261081Sasomers * fill up the send buffer but not the receive buffer
876261081Sasomers */
877261081SasomersATF_TC_WITHOUT_HEAD(rcvbuf_oversized);
878261081SasomersATF_TC_BODY(rcvbuf_oversized, tc)
879261081Sasomers{
880261081Sasomers	int s, i, j;
881261081Sasomers	int sv[2];
882261081Sasomers	const size_t sndbufsize = 8192;
883261081Sasomers	const size_t rcvbufsize = 131072;
884261081Sasomers	const size_t geom_mean_bufsize = 32768;
885261081Sasomers	const int pktsize = 1024;
886261081Sasomers	char sndbuf[pktsize];
887261081Sasomers	char recv_buf[pktsize];
888261081Sasomers	size_t datalen;
889261081Sasomers	ssize_t ssize, rsize;
890261081Sasomers
891261081Sasomers	/* setup the socket pair */
892261081Sasomers	do_socketpair_nonblocking(sv);
893261081Sasomers
894261081Sasomers	/*
895261081Sasomers	 * Send and receive packets that are collectively greater than the send
896261081Sasomers	 * buffer, but less than the receive buffer
897261081Sasomers	 */
898261081Sasomers	for (i=0; i < geom_mean_bufsize / pktsize; i++) {
899261081Sasomers		/* Fill the buffer */
900261081Sasomers		memset(sndbuf, i, pktsize);
901261081Sasomers
902261081Sasomers		/* send the packet */
903261081Sasomers		ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
904261081Sasomers		if (ssize < 0) {
905261081Sasomers			perror("send");
906261081Sasomers			atf_tc_fail("send returned < 0");
907261081Sasomers		}
908261081Sasomers		ATF_CHECK_EQ_MSG(pktsize, ssize,
909261081Sasomers		    "expected %zd=send(...) but got %zd", pktsize, ssize);
910261081Sasomers
911261081Sasomers		/* Receive it */
912261081Sasomers
913261081Sasomers		rsize = recv(sv[1], recv_buf, pktsize, MSG_WAITALL);
914261081Sasomers		if (rsize < 0) {
915261081Sasomers			perror("recv");
916261081Sasomers			atf_tc_fail("recv returned < 0");
917261081Sasomers		}
918261081Sasomers		ATF_CHECK_EQ_MSG(pktsize, rsize,
919261081Sasomers		    "expected %zd=send(...) but got %zd", pktsize, rsize);
920261081Sasomers
921261081Sasomers		/* Verify the contents */
922261081Sasomers		ATF_CHECK_EQ_MSG(0, memcmp(sndbuf, recv_buf, pktsize),
923261081Sasomers		    "Received data miscompare");
924261081Sasomers	}
925261081Sasomers
926261081Sasomers	/* Trying to receive again should return EAGAIN */
927261081Sasomers	rsize = recv(sv[1], recv_buf, pktsize, MSG_WAITALL);
928261081Sasomers	ATF_CHECK_EQ(EAGAIN, errno);
929261081Sasomers	ATF_CHECK_EQ(-1, rsize);
930261081Sasomers}
931261081Sasomers
932261081Sasomers/*
933261081Sasomers * Simulate the behavior of a blocking pipe.  The sender will send until his
934261081Sasomers * buffer fills up, then we'll simulate a scheduler switch that will allow the
935261081Sasomers * receiver to read until his buffer empties.  Repeat the process until the
936261081Sasomers * transfer is complete.
937261081Sasomers * Repeat the test with multiple send and receive buffer sizes
938261081Sasomers */
939261081SasomersATF_TC_WITHOUT_HEAD(pipe_simulator_8k_8k);
940261081SasomersATF_TC_BODY(pipe_simulator_8k_8k, tc)
941261081Sasomers{
942261081Sasomers	test_pipe_simulator(8192, 8192);
943261081Sasomers}
944261081Sasomers
945261081SasomersATF_TC_WITHOUT_HEAD(pipe_simulator_8k_128k);
946261081SasomersATF_TC_BODY(pipe_simulator_8k_128k, tc)
947261081Sasomers{
948261081Sasomers	test_pipe_simulator(8192, 131072);
949261081Sasomers}
950261081Sasomers
951261081SasomersATF_TC_WITHOUT_HEAD(pipe_simulator_128k_8k);
952261081SasomersATF_TC_BODY(pipe_simulator_128k_8k, tc)
953261081Sasomers{
954261081Sasomers	atf_tc_expect_fail("PR kern/185812 SOCK_SEQPACKET AF_UNIX sockets with asymmetrical buffers drop packets");
955261081Sasomers	test_pipe_simulator(131072, 8192);
956261081Sasomers}
957261081Sasomers
958261081SasomersATF_TC_WITHOUT_HEAD(pipe_simulator_128k_128k);
959261081SasomersATF_TC_BODY(pipe_simulator_128k_128k, tc)
960261081Sasomers{
961261081Sasomers	test_pipe_simulator(131072, 131072);
962261081Sasomers}
963261081Sasomers
964261081Sasomers/*
965261081Sasomers * Test blocking I/O by passing data between two threads.  The total amount of
966261081Sasomers * data will be >> buffer size to force blocking.  Repeat the test with multiple
967261081Sasomers * send and receive buffer sizes
968261081Sasomers */
969261081SasomersATF_TC_WITHOUT_HEAD(pipe_8k_8k);
970261081SasomersATF_TC_BODY(pipe_8k_8k, tc)
971261081Sasomers{
972261081Sasomers	atf_tc_expect_fail("PR kern/185812 send(2) on a UNIX domain SEQPACKET socket returns EMSGSIZE instead of EAGAIN");
973261081Sasomers	test_pipe(8192, 8192);
974261081Sasomers}
975261081Sasomers
976261081SasomersATF_TC_WITHOUT_HEAD(pipe_8k_128k);
977261081SasomersATF_TC_BODY(pipe_8k_128k, tc)
978261081Sasomers{
979261081Sasomers	atf_tc_expect_fail("PR kern/185812 send(2) on a UNIX domain SEQPACKET socket returns EMSGSIZE instead of EAGAIN");
980261081Sasomers	test_pipe(8192, 131072);
981261081Sasomers}
982261081Sasomers
983261081SasomersATF_TC_WITHOUT_HEAD(pipe_128k_8k);
984261081SasomersATF_TC_BODY(pipe_128k_8k, tc)
985261081Sasomers{
986261081Sasomers	/*
987261081Sasomers	 * kern/185812 causes this test case to both fail and timeout.  The
988261081Sasomers	 * atf-c-api(3) doesn't have a way to set such an expectation.
989261081Sasomers	 * If you use atf_tc_expect_fail, then it will timeout.  If you use
990261081Sasomers	 * atf_tc_expect_timeout, then it will fail.  If you use both, then it
991261081Sasomers	 * will show up as an unexpected pass, which is much worse
992261081Sasomers	 *
993261081Sasomers	 * https://code.google.com/p/kyua/issues/detail?id=76
994261081Sasomers	 */
995261081Sasomers	atf_tc_expect_fail("PR kern/185812 send(2) on a UNIX domain SEQPACKET socket returns EMSGSIZE instead of EAGAIN");
996261081Sasomers	test_pipe(131072, 8192);
997261081Sasomers}
998261081Sasomers
999261081SasomersATF_TC_WITHOUT_HEAD(pipe_128k_128k);
1000261081SasomersATF_TC_BODY(pipe_128k_128k, tc)
1001261081Sasomers{
1002261081Sasomers	atf_tc_expect_fail("PR kern/185812 send(2) on a UNIX domain SEQPACKET socket returns EMSGSIZE instead of EAGAIN");
1003261081Sasomers	test_pipe(131072, 131072);
1004261081Sasomers}
1005261081Sasomers
1006261081Sasomers
1007261081Sasomers/*
1008261081Sasomers * Test single-packet I/O with and without blocking, with symmetric buffers of
1009261081Sasomers * various sizes
1010261081Sasomers */
1011261081SasomersATF_TC_WITHOUT_HEAD(sendrecv_8k);
1012261081SasomersATF_TC_BODY(sendrecv_8k, tc)
1013261081Sasomers{
1014261081Sasomers	test_sendrecv_symmetric_buffers(8 * 1024, true);
1015261081Sasomers}
1016261081SasomersATF_TC_WITHOUT_HEAD(sendrecv_16k);
1017261081SasomersATF_TC_BODY(sendrecv_16k, tc)
1018261081Sasomers{
1019261081Sasomers	test_sendrecv_symmetric_buffers(16 * 1024, true);
1020261081Sasomers}
1021261081SasomersATF_TC_WITHOUT_HEAD(sendrecv_32k);
1022261081SasomersATF_TC_BODY(sendrecv_32k, tc)
1023261081Sasomers{
1024261081Sasomers	test_sendrecv_symmetric_buffers(32 * 1024, true);
1025261081Sasomers}
1026261081SasomersATF_TC_WITHOUT_HEAD(sendrecv_64k);
1027261081SasomersATF_TC_BODY(sendrecv_64k, tc)
1028261081Sasomers{
1029261081Sasomers	test_sendrecv_symmetric_buffers(64 * 1024, true);
1030261081Sasomers}
1031261081SasomersATF_TC_WITHOUT_HEAD(sendrecv_128k);
1032261081SasomersATF_TC_BODY(sendrecv_128k, tc)
1033261081Sasomers{
1034261081Sasomers	test_sendrecv_symmetric_buffers(128 * 1024, true);
1035261081Sasomers}
1036261081SasomersATF_TC_WITHOUT_HEAD(sendrecv_8k_nonblocking);
1037261081SasomersATF_TC_BODY(sendrecv_8k_nonblocking, tc)
1038261081Sasomers{
1039261081Sasomers	test_sendrecv_symmetric_buffers(8 * 1024, false);
1040261081Sasomers}
1041261081SasomersATF_TC_WITHOUT_HEAD(sendrecv_16k_nonblocking);
1042261081SasomersATF_TC_BODY(sendrecv_16k_nonblocking, tc)
1043261081Sasomers{
1044261081Sasomers	test_sendrecv_symmetric_buffers(16 * 1024, false);
1045261081Sasomers}
1046261081SasomersATF_TC_WITHOUT_HEAD(sendrecv_32k_nonblocking);
1047261081SasomersATF_TC_BODY(sendrecv_32k_nonblocking, tc)
1048261081Sasomers{
1049261081Sasomers	test_sendrecv_symmetric_buffers(32 * 1024, false);
1050261081Sasomers}
1051261081SasomersATF_TC_WITHOUT_HEAD(sendrecv_64k_nonblocking);
1052261081SasomersATF_TC_BODY(sendrecv_64k_nonblocking, tc)
1053261081Sasomers{
1054261081Sasomers	test_sendrecv_symmetric_buffers(64 * 1024, false);
1055261081Sasomers}
1056261081SasomersATF_TC_WITHOUT_HEAD(sendrecv_128k_nonblocking);
1057261081SasomersATF_TC_BODY(sendrecv_128k_nonblocking, tc)
1058261081Sasomers{
1059261081Sasomers	test_sendrecv_symmetric_buffers(128 * 1024, false);
1060261081Sasomers}
1061261081Sasomers
1062261081Sasomers
1063261081Sasomers/*
1064261081Sasomers * Main.
1065261081Sasomers */
1066261081Sasomers
1067261081SasomersATF_TP_ADD_TCS(tp)
1068261081Sasomers{
1069261081Sasomers	/* Basic creation and connection tests */
1070261081Sasomers	ATF_TP_ADD_TC(tp, create_socket);
1071261081Sasomers	ATF_TP_ADD_TC(tp, create_socketpair);
1072261081Sasomers	ATF_TP_ADD_TC(tp, listen_unbound);
1073261081Sasomers	ATF_TP_ADD_TC(tp, bind);
1074261081Sasomers	ATF_TP_ADD_TC(tp, listen_bound);
1075261081Sasomers	ATF_TP_ADD_TC(tp, connect);
1076261081Sasomers	ATF_TP_ADD_TC(tp, accept);
1077261081Sasomers	ATF_TP_ADD_TC(tp, fcntl_nonblock);
1078261081Sasomers	ATF_TP_ADD_TC(tp, resize_buffers);
1079261081Sasomers	ATF_TP_ADD_TC(tp, resize_connected_buffers);
1080261081Sasomers
1081261081Sasomers	/* Unthreaded I/O tests */
1082261081Sasomers	ATF_TP_ADD_TC(tp, send_recv);
1083261081Sasomers	ATF_TP_ADD_TC(tp, send_recv_nonblocking);
1084261081Sasomers	ATF_TP_ADD_TC(tp, send_recv_with_connect);
1085261081Sasomers	ATF_TP_ADD_TC(tp, sendto_recvfrom);
1086261081Sasomers	ATF_TP_ADD_TC(tp, shutdown_send);
1087261081Sasomers	ATF_TP_ADD_TC(tp, shutdown_send_sigpipe);
1088261081Sasomers	ATF_TP_ADD_TC(tp, emsgsize);
1089261081Sasomers	ATF_TP_ADD_TC(tp, emsgsize_nonblocking);
1090261081Sasomers	ATF_TP_ADD_TC(tp, eagain_8k_8k);
1091261081Sasomers	ATF_TP_ADD_TC(tp, eagain_8k_128k);
1092261081Sasomers	ATF_TP_ADD_TC(tp, eagain_128k_8k);
1093261081Sasomers	ATF_TP_ADD_TC(tp, eagain_128k_128k);
1094261081Sasomers	ATF_TP_ADD_TC(tp, sendrecv_8k);
1095261081Sasomers	ATF_TP_ADD_TC(tp, sendrecv_16k);
1096261081Sasomers	ATF_TP_ADD_TC(tp, sendrecv_32k);
1097261081Sasomers	ATF_TP_ADD_TC(tp, sendrecv_64k);
1098261081Sasomers	ATF_TP_ADD_TC(tp, sendrecv_128k);
1099261081Sasomers	ATF_TP_ADD_TC(tp, sendrecv_8k_nonblocking);
1100261081Sasomers	ATF_TP_ADD_TC(tp, sendrecv_16k_nonblocking);
1101261081Sasomers	ATF_TP_ADD_TC(tp, sendrecv_32k_nonblocking);
1102261081Sasomers	ATF_TP_ADD_TC(tp, sendrecv_64k_nonblocking);
1103261081Sasomers	ATF_TP_ADD_TC(tp, sendrecv_128k_nonblocking);
1104261081Sasomers	ATF_TP_ADD_TC(tp, rcvbuf_oversized);
1105261081Sasomers	ATF_TP_ADD_TC(tp, pipe_simulator_8k_8k);
1106261081Sasomers	ATF_TP_ADD_TC(tp, pipe_simulator_8k_128k);
1107261081Sasomers	ATF_TP_ADD_TC(tp, pipe_simulator_128k_8k);
1108261081Sasomers	ATF_TP_ADD_TC(tp, pipe_simulator_128k_128k);
1109261081Sasomers
1110261081Sasomers	/* Threaded I/O tests with blocking sockets */
1111261081Sasomers	ATF_TP_ADD_TC(tp, pipe_8k_8k);
1112261081Sasomers	ATF_TP_ADD_TC(tp, pipe_8k_128k);
1113261081Sasomers	ATF_TP_ADD_TC(tp, pipe_128k_8k);
1114261081Sasomers	ATF_TP_ADD_TC(tp, pipe_128k_128k);
1115261081Sasomers
1116261081Sasomers	return atf_no_error();
1117261081Sasomers}
1118