unix_seqpacket_test.c revision 263572
1/*-
2 * Copyright (c) 2014 Spectra Logic Corporation. All rights reserved.
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions
5 * are met:
6 * 1. Redistributions of source code must retain the above copyright
7 *    notice, this list of conditions and the following disclaimer.
8 * 2. Redistributions in binary form must reproduce the above copyright
9 *    notice, this list of conditions and the following disclaimer in the
10 *    documentation and/or other materials provided with the distribution.
11 *
12 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
13 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
15 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
16 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
17 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
18 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
19 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
20 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
21 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
22 * SUCH DAMAGE.
23 */
24
25#include <sys/cdefs.h>
26__FBSDID("$FreeBSD: stable/10/tests/sys/kern/unix_seqpacket_test.c 263572 2014-03-21 22:43:00Z asomers $");
27
28#include <errno.h>
29#include <fcntl.h>
30#include <pthread.h>
31#include <signal.h>
32#include <sys/socket.h>
33#include <sys/un.h>
34
35#include <stdio.h>
36
37#include <atf-c.h>
38
39/*
40 * Helper functions
41 */
42
43#define MIN(x, y)	((x) < (y) ? (x) : (y))
44#define MAX(x, y)	((x) > (y) ? (x) : (y))
45
46static void
47do_socketpair(int *sv)
48{
49	int s;
50
51	s = socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, sv);
52	ATF_REQUIRE_EQ(0, s);
53	ATF_REQUIRE(sv[0] >= 0);
54	ATF_REQUIRE(sv[1] >= 0);
55	ATF_REQUIRE(sv[0] != sv[1]);
56}
57
58static void
59do_socketpair_nonblocking(int *sv)
60{
61	int s;
62
63	s = socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, sv);
64	ATF_REQUIRE_EQ(0, s);
65	ATF_REQUIRE(sv[0] >= 0);
66	ATF_REQUIRE(sv[1] >= 0);
67	ATF_REQUIRE(sv[0] != sv[1]);
68	ATF_REQUIRE(-1 != fcntl(sv[0], F_SETFL, O_NONBLOCK));
69	ATF_REQUIRE(-1 != fcntl(sv[1], F_SETFL, O_NONBLOCK));
70}
71
72/*
73 * Returns a pair of sockets made the hard way: bind, listen, connect & accept
74 * @return	const char* The path to the socket
75 */
76static const char*
77mk_pair_of_sockets(int *sv)
78{
79	struct sockaddr_un sun;
80	/* ATF's isolation mechanisms will guarantee uniqueness of this file */
81	const char *path = "sock";
82	int s, err, s2, s1;
83
84	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
85	ATF_REQUIRE(s >= 0);
86
87	bzero(&sun, sizeof(sun));
88	sun.sun_family = AF_LOCAL;
89	sun.sun_len = sizeof(sun);
90	strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
91	err = bind(s, (struct sockaddr *)&sun, sizeof(sun));
92	err = listen(s, -1);
93	ATF_CHECK_EQ(0, err);
94	ATF_CHECK_EQ(0, err);
95
96	/* Create the other socket */
97	s2 = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
98	ATF_REQUIRE(s2 >= 0);
99	err = connect(s2, (struct sockaddr*)&sun, sizeof(sun));
100	if (err != 0) {
101		perror("connect");
102		atf_tc_fail("connect(2) failed");
103	}
104
105	/* Accept it */
106	s1 = accept(s, NULL, NULL);
107	if (s1 == -1) {
108		perror("accept");
109		atf_tc_fail("accept(2) failed");
110	}
111
112	sv[0] = s1;
113	sv[1] = s2;
114	return (path);
115}
116
117static volatile sig_atomic_t got_sigpipe = 0;
118static void
119shutdown_send_sigpipe_handler(int __unused x)
120{
121	got_sigpipe = 1;
122}
123
124/*
125 * Parameterized test function bodies
126 */
127static void
128test_eagain(size_t sndbufsize, size_t rcvbufsize)
129{
130	int i;
131	int sv[2];
132	const size_t totalsize = (sndbufsize + rcvbufsize) * 2;
133	const size_t pktsize = MIN(sndbufsize, rcvbufsize) / 4;
134	const int numpkts = totalsize / pktsize;
135	char sndbuf[pktsize];
136	ssize_t ssize;
137
138	/* setup the socket pair */
139	do_socketpair_nonblocking(sv);
140	/* Setup the buffers */
141	ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
142	    sizeof(sndbufsize)));
143	ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
144	    sizeof(rcvbufsize)));
145
146	bzero(sndbuf, pktsize);
147	/* Send data until we get EAGAIN */
148	for(i=0; i < numpkts; i++) {
149		ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
150		if (ssize == -1) {
151			if (errno == EAGAIN)
152				atf_tc_pass();
153			else {
154				perror("send");
155				atf_tc_fail("send returned < 0 but not EAGAIN");
156			}
157		}
158	}
159	atf_tc_fail("Never got EAGAIN");
160}
161
162static void
163test_sendrecv_symmetric_buffers(size_t bufsize, int blocking) {
164	int s;
165	int sv[2];
166	const ssize_t pktsize = bufsize / 2;
167	char sndbuf[pktsize];
168	char recv_buf[pktsize];
169	ssize_t ssize, rsize;
170
171	/* setup the socket pair */
172	if (blocking)
173		do_socketpair(sv);
174	else
175		do_socketpair_nonblocking(sv);
176
177	/* Setup the buffers */
178	s = setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize));
179	ATF_REQUIRE_EQ(0, s);
180	s = setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(bufsize));
181	ATF_REQUIRE_EQ(0, s);
182
183	/* Fill the send buffer */
184	bzero(sndbuf, pktsize);
185
186	/* send and receive the packet */
187	ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
188	if (ssize < 0) {
189		perror("send");
190		atf_tc_fail("send returned < 0");
191	}
192	ATF_CHECK_EQ_MSG(pktsize, ssize, "expected %zd=send(...) but got %zd",
193	    pktsize, ssize);
194
195	rsize = recv(sv[1], recv_buf, pktsize, MSG_WAITALL);
196	if (rsize < 0) {
197		perror("recv");
198		atf_tc_fail("recv returned < 0");
199	}
200	ATF_CHECK_EQ_MSG(pktsize, rsize, "expected %zd=send(...) but got %zd",
201	    pktsize, rsize);
202}
203
204static void
205test_pipe_simulator(size_t sndbufsize, size_t rcvbufsize)
206{
207	int num_sent, num_received;
208	int sv[2];
209	const ssize_t pktsize = MIN(sndbufsize, rcvbufsize) / 4;
210	int numpkts;
211	char sndbuf[pktsize];
212	char rcvbuf[pktsize];
213	char comparebuf[pktsize];
214	ssize_t ssize, rsize;
215	bool currently_sending = true;
216
217	/* setup the socket pair */
218	do_socketpair_nonblocking(sv);
219	/* Setup the buffers */
220	ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
221	    sizeof(sndbufsize)));
222	ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
223	    sizeof(rcvbufsize)));
224
225	/* Send a total amount of data comfortably greater than the buffers */
226	numpkts = MAX(sndbufsize, rcvbufsize) * 8 / pktsize;
227	for (num_sent=0, num_received=0;
228	     num_sent < numpkts || num_received < numpkts; ) {
229		if (currently_sending && num_sent < numpkts) {
230			/* The simulated sending process */
231			/* fill the buffer */
232			memset(sndbuf, num_sent, pktsize);
233			ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
234			if (ssize < 0) {
235				/*
236				 * XXX: This is bug-compatible with the kernel.
237				 * The kernel returns EMSGSIZE when it should
238				 * return EAGAIN
239				 */
240				if (errno == EAGAIN || errno == EMSGSIZE)
241					currently_sending = false;
242				else {
243					perror("send");
244					atf_tc_fail("send failed");
245				}
246			} else  {
247				ATF_CHECK_EQ_MSG(pktsize, ssize,
248				    "expected %zd=send(...) but got %zd",
249				    pktsize, ssize);
250				num_sent++;
251			}
252		} else {
253			/* The simulated receiving process */
254			rsize = recv(sv[1], rcvbuf, pktsize, MSG_WAITALL);
255			if (rsize < 0) {
256				if (errno == EAGAIN) {
257					currently_sending = true;
258					ATF_REQUIRE_MSG(num_sent < numpkts,
259					    "Packets were lost!");
260				}
261				else {
262					perror("recv");
263					atf_tc_fail("recv failed");
264				}
265			} else  {
266				ATF_CHECK_EQ_MSG(pktsize, rsize,
267				    "expected %zd=recv(...) but got %zd",
268				    pktsize, rsize);
269				memset(comparebuf, num_received, pktsize);
270				ATF_CHECK_EQ_MSG(0, memcmp(comparebuf, rcvbuf,
271				    			   pktsize),
272				    "Received data miscompare");
273				num_received++;
274			}
275		}
276	}
277}
278
279typedef struct {
280	ssize_t	pktsize;
281	int	numpkts;
282	int	so;
283} test_pipe_thread_data_t;
284
285static void*
286test_pipe_writer(void* args)
287{
288	test_pipe_thread_data_t* td = args;
289	char sndbuf[td->pktsize];
290	ssize_t ssize;
291	int i;
292
293	for(i=0; i < td->numpkts; i++) {
294			memset(sndbuf, i, td->pktsize);
295			ssize = send(td->so, sndbuf, td->pktsize, MSG_EOR);
296			if (ssize < 0) {
297				perror("send");
298				atf_tc_fail("send returned < 0");
299			}
300			ATF_CHECK_EQ_MSG(td->pktsize, ssize,
301			    		 "expected %zd=send(...) but got %zd",
302			    		  td->pktsize, ssize);
303	}
304	return (0);
305}
306
307static void*
308test_pipe_reader(void* args)
309{
310	test_pipe_thread_data_t* td = args;
311	char rcvbuf[td->pktsize];
312	char comparebuf[td->pktsize];
313	ssize_t rsize;
314	int i, d;
315
316	for(i=0; i < td->numpkts; i++) {
317		memset(comparebuf, i, td->pktsize);
318		rsize = recv(td->so, rcvbuf, td->pktsize, MSG_WAITALL);
319		if (rsize < 0) {
320			perror("recv");
321			atf_tc_fail("recv returned < 0");
322		}
323		ATF_CHECK_EQ_MSG(td->pktsize, rsize,
324		    		 "expected %zd=send(...) but got %zd",
325				 td->pktsize, rsize);
326		d = memcmp(comparebuf, rcvbuf, td->pktsize);
327		ATF_CHECK_EQ_MSG(0, d,
328		    		 "Received data miscompare on packet %d", i);
329	}
330	return (0);
331}
332
333
334static void
335test_pipe(size_t sndbufsize, size_t rcvbufsize)
336{
337	test_pipe_thread_data_t writer_data, reader_data;
338	pthread_t writer, reader;
339	int sv[2];
340	const size_t pktsize = MIN(sndbufsize, rcvbufsize) / 4;
341	int numpkts;
342
343	/* setup the socket pair */
344	do_socketpair(sv);
345	/* Setup the buffers */
346	ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
347	    sizeof(sndbufsize)));
348	ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
349	    sizeof(rcvbufsize)));
350
351	/* Send a total amount of data comfortably greater than the buffers */
352	numpkts = MAX(sndbufsize, rcvbufsize) * 8 / pktsize;
353
354	/* Start the child threads */
355	writer_data.pktsize = pktsize;
356	writer_data.numpkts = numpkts;
357	writer_data.so = sv[0];
358	reader_data.pktsize = pktsize;
359	reader_data.numpkts = numpkts;
360	reader_data.so = sv[1];
361	ATF_REQUIRE_EQ(0, pthread_create(&writer, NULL, test_pipe_writer,
362	    				 (void*)&writer_data));
363	ATF_REQUIRE_EQ(0, pthread_create(&reader, NULL, test_pipe_reader,
364	    				 (void*)&reader_data));
365
366	/* Join the children */
367	ATF_REQUIRE_EQ(0, pthread_join(writer, NULL));
368	ATF_REQUIRE_EQ(0, pthread_join(reader, NULL));
369}
370
371
372/*
373 * Test Cases
374 */
375
376/* Create a SEQPACKET socket */
377ATF_TC_WITHOUT_HEAD(create_socket);
378ATF_TC_BODY(create_socket, tc)
379{
380	int s;
381
382	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
383	ATF_CHECK(s >= 0);
384}
385
386/* Create SEQPACKET sockets using socketpair(2) */
387ATF_TC_WITHOUT_HEAD(create_socketpair);
388ATF_TC_BODY(create_socketpair, tc)
389{
390	int sv[2];
391	int s;
392
393	s = socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, sv);
394	ATF_CHECK_EQ(0, s);
395	ATF_CHECK(sv[0] >= 0);
396	ATF_CHECK(sv[1] >= 0);
397	ATF_CHECK(sv[0] != sv[1]);
398}
399
400/* Call listen(2) without first calling bind(2).  It should fail */
401ATF_TC_WITHOUT_HEAD(listen_unbound);
402ATF_TC_BODY(listen_unbound, tc)
403{
404	int s, r;
405
406	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
407	ATF_REQUIRE(s > 0);
408	r = listen(s, -1);
409	/* expect listen to fail since we haven't called bind(2) */
410	ATF_CHECK(r != 0);
411}
412
413/* Bind the socket to a file */
414ATF_TC_WITHOUT_HEAD(bind);
415ATF_TC_BODY(bind, tc)
416{
417	struct sockaddr_un sun;
418	/* ATF's isolation mechanisms will guarantee uniqueness of this file */
419	const char *path = "sock";
420	int s, r;
421
422	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
423	ATF_REQUIRE(s >= 0);
424
425	bzero(&sun, sizeof(sun));
426	sun.sun_family = AF_LOCAL;
427	sun.sun_len = sizeof(sun);
428	strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
429	r = bind(s, (struct sockaddr *)&sun, sizeof(sun));
430	ATF_CHECK_EQ(0, r);
431}
432
433/* listen(2) a socket that is already bound(2) should succeed */
434ATF_TC_WITHOUT_HEAD(listen_bound);
435ATF_TC_BODY(listen_bound, tc)
436{
437	struct sockaddr_un sun;
438	/* ATF's isolation mechanisms will guarantee uniqueness of this file */
439	const char *path = "sock";
440	int s, r, l;
441
442	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
443	ATF_REQUIRE(s >= 0);
444
445	bzero(&sun, sizeof(sun));
446	sun.sun_family = AF_LOCAL;
447	sun.sun_len = sizeof(sun);
448	strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
449	r = bind(s, (struct sockaddr *)&sun, sizeof(sun));
450	l = listen(s, -1);
451	ATF_CHECK_EQ(0, r);
452	ATF_CHECK_EQ(0, l);
453}
454
455/* connect(2) can make a connection */
456ATF_TC_WITHOUT_HEAD(connect);
457ATF_TC_BODY(connect, tc)
458{
459	struct sockaddr_un sun;
460	/* ATF's isolation mechanisms will guarantee uniqueness of this file */
461	const char *path = "sock";
462	int s, r, err, l, s2;
463
464	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
465	ATF_REQUIRE(s >= 0);
466
467	bzero(&sun, sizeof(sun));
468	sun.sun_family = AF_LOCAL;
469	sun.sun_len = sizeof(sun);
470	strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
471	r = bind(s, (struct sockaddr *)&sun, sizeof(sun));
472	l = listen(s, -1);
473	ATF_CHECK_EQ(0, r);
474	ATF_CHECK_EQ(0, l);
475
476	/* Create the other socket */
477	s2 = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
478	ATF_REQUIRE(s2 >= 0);
479	err = connect(s2, (struct sockaddr*)&sun, sizeof(sun));
480	if (err != 0) {
481		perror("connect");
482		atf_tc_fail("connect(2) failed");
483	}
484}
485
486/* accept(2) can receive a connection */
487ATF_TC_WITHOUT_HEAD(accept);
488ATF_TC_BODY(accept, tc)
489{
490	int sv[2];
491
492	mk_pair_of_sockets(sv);
493}
494
495
496/* Set O_NONBLOCK on the socket */
497ATF_TC_WITHOUT_HEAD(fcntl_nonblock);
498ATF_TC_BODY(fcntl_nonblock, tc)
499{
500	int s;
501
502	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
503	ATF_REQUIRE(s >= 0);
504	if (fcntl(s, F_SETFL, O_NONBLOCK) == -1) {
505		perror("fcntl");
506		atf_tc_fail("fcntl failed");
507	}
508}
509
510/* Resize the send and receive buffers */
511ATF_TC_WITHOUT_HEAD(resize_buffers);
512ATF_TC_BODY(resize_buffers, tc)
513{
514	int s;
515	int sndbuf = 12345;
516	int rcvbuf = 23456;
517	int xs, xr;
518	socklen_t sl = sizeof(xs);
519
520	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
521	ATF_REQUIRE(s >= 0);
522
523	printf("                       Socket Buffer Sizes\n");
524	printf("                              | SNDBUF  | RCVBUF  |\n");
525	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_SNDBUF, &xs, &sl));
526	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_RCVBUF, &xr, &sl));
527	printf("Default                       | %7d | %7d |\n", xs, xr);
528
529	if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf)) != 0){
530		perror("setsockopt");
531		atf_tc_fail("setsockopt(SO_SNDBUF) failed");
532	}
533	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_SNDBUF, &xs, &sl));
534	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_RCVBUF, &xr, &sl));
535	printf("After changing SNDBUF         | %7d | %7d |\n", xs, xr);
536
537	if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)) != 0){
538		perror("setsockopt");
539		atf_tc_fail("setsockopt(SO_RCVBUF) failed");
540	}
541	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_SNDBUF, &xs, &sl));
542	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_RCVBUF, &xr, &sl));
543	printf("After changing RCVBUF         | %7d | %7d |\n", xs, xr);
544}
545
546/*
547 * Resize the send and receive buffers of a connected socketpair
548 * Print some useful debugging info too
549 */
550ATF_TC_WITHOUT_HEAD(resize_connected_buffers);
551ATF_TC_BODY(resize_connected_buffers, tc)
552{
553	int sv[2];
554	int sndbuf = 12345;
555	int rcvbuf = 23456;
556	int err;
557	int ls, lr, rs, rr;
558	socklen_t sl = sizeof(ls);
559
560	/* setup the socket pair */
561	do_socketpair(sv);
562
563	printf("                       Socket Buffer Sizes\n");
564	printf("                              | Left Socket       | Right Socket      |\n");
565	printf("                              | SNDBUF  | RCVBUF  | SNDBUF  | RCVBUF  |\n");
566	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &ls, &sl));
567	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &lr, &sl));
568	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &rs, &sl));
569	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rr, &sl));
570	printf("Default                       | %7d | %7d | %7d | %7d |\n",
571	    ls, lr, rs, rr);
572
573	/* Update one side's send buffer */
574	err = setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf));
575	if (err != 0){
576		perror("setsockopt");
577		atf_tc_fail("setsockopt(SO_SNDBUF) failed");
578	}
579
580	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &ls, &sl));
581	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &lr, &sl));
582	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &rs, &sl));
583	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rr, &sl));
584	printf("After changing Left's SNDBUF  | %7d | %7d | %7d | %7d |\n",
585	    ls, lr, rs, rr);
586
587	/* Update the same side's receive buffer */
588	err = setsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf));
589	if (err != 0){
590		perror("setsockopt");
591		atf_tc_fail("setsockopt(SO_RCVBUF) failed");
592	}
593
594	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &ls, &sl));
595	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &lr, &sl));
596	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &rs, &sl));
597	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rr, &sl));
598	printf("After changing Left's RCVBUF  | %7d | %7d | %7d | %7d |\n",
599	    ls, lr, rs, rr);
600}
601
602
603/* send(2) and recv(2) a single short record */
604ATF_TC_WITHOUT_HEAD(send_recv);
605ATF_TC_BODY(send_recv, tc)
606{
607	int sv[2];
608	const int bufsize = 64;
609	const char *data = "data";
610	char recv_buf[bufsize];
611	ssize_t datalen;
612	ssize_t ssize, rsize;
613
614	/* setup the socket pair */
615	do_socketpair(sv);
616
617	/* send and receive a small packet */
618	datalen = strlen(data) + 1;	/* +1 for the null */
619	ssize = send(sv[0], data, datalen, MSG_EOR);
620	if (ssize < 0) {
621		perror("send");
622		atf_tc_fail("send returned < 0");
623	}
624	ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd",
625	    datalen, ssize);
626
627	rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL);
628	ATF_CHECK_EQ(datalen, rsize);
629}
630
631/* sendto(2) and recvfrom(2) a single short record
632 * According to The Open Group Base Specifications Issue 6 IEEE Std 1003.1, 2004
633 * Edition, sendto(2) is exactly the same as send(2) on a connection-mode socket
634 *
635 * According to the same spec, not all protocols are required to provide the
636 * source addres in recvfrom(2).
637 */
638ATF_TC_WITHOUT_HEAD(sendto_recvfrom);
639ATF_TC_BODY(sendto_recvfrom, tc)
640{
641	const char* path;
642	struct sockaddr_storage from;
643	int sv[2];
644	const int bufsize = 64;
645	const char *data = "data";
646	char recv_buf[bufsize];
647	ssize_t datalen;
648	ssize_t ssize, rsize;
649	socklen_t fromlen;
650
651	/* setup the socket pair */
652	path = mk_pair_of_sockets(sv);
653
654	/* send and receive a small packet */
655	datalen = strlen(data) + 1;	/* +1 for the null */
656	ssize = sendto(sv[0], data, datalen, MSG_EOR, NULL, 0);
657	if (ssize < 0) {
658		perror("send");
659		atf_tc_fail("send returned < 0");
660	}
661	ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd",
662	    datalen, ssize);
663
664	fromlen = sizeof(from);
665	rsize = recvfrom(sv[1], recv_buf, bufsize, MSG_WAITALL,
666	    (struct sockaddr*)&from, &fromlen);
667	if (ssize < 0) {
668		perror("recvfrom");
669		atf_tc_fail("recvfrom returned < 0");
670	}
671	ATF_CHECK_EQ(datalen, rsize);
672
673	/*
674	 * FreeBSD does not currently provide the source address for SEQ_PACKET
675	 * AF_UNIX sockets, and POSIX does not require it, so these two checks
676	 * are disabled.  If FreeBSD gains that feature in the future, then
677	 * these checks may be reenabled
678	 */
679	/* ATF_CHECK_EQ(PF_LOCAL, from.ss_family); */
680	/* ATF_CHECK_STREQ(path, ((struct sockaddr_un*)&from)->sun_path); */
681}
682
683/*
684 * send(2) and recv(2) a single short record with sockets created the
685 * traditional way, involving bind, listen, connect, and accept
686 */
687ATF_TC_WITHOUT_HEAD(send_recv_with_connect);
688ATF_TC_BODY(send_recv_with_connect, tc)
689{
690	int sv[2];
691	const int bufsize = 64;
692	const char *data = "data";
693	char recv_buf[bufsize];
694	ssize_t datalen;
695	ssize_t ssize, rsize;
696
697	mk_pair_of_sockets(sv);
698
699	/* send and receive a small packet */
700	datalen = strlen(data) + 1;	/* +1 for the null */
701	ssize = send(sv[0], data, datalen, MSG_EOR);
702	if (ssize < 0) {
703		perror("send");
704		atf_tc_fail("send returned < 0");
705	}
706	ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd",
707	    datalen, ssize);
708
709	rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL);
710	ATF_CHECK_EQ(datalen, rsize);
711}
712
713/* send(2) should fail on a shutdown socket */
714ATF_TC_WITHOUT_HEAD(shutdown_send);
715ATF_TC_BODY(shutdown_send, tc)
716{
717	int s;
718	const char *data = "data";
719	ssize_t ssize;
720
721	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
722	ATF_CHECK(s >= 0);
723	ATF_CHECK_EQ(0, shutdown(s, SHUT_RDWR));
724	/* USE MSG_NOSIGNAL so we don't get SIGPIPE */
725	ssize = send(s, data, sizeof(data), MSG_EOR | MSG_NOSIGNAL);
726	ATF_CHECK_EQ(EPIPE, errno);
727	ATF_CHECK_EQ(-1, ssize);
728}
729
730/* send(2) should cause SIGPIPE on a shutdown socket */
731ATF_TC_WITHOUT_HEAD(shutdown_send_sigpipe);
732ATF_TC_BODY(shutdown_send_sigpipe, tc)
733{
734	int s;
735	const char *data = "data";
736	ssize_t ssize;
737
738	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
739	ATF_CHECK(s >= 0);
740	ATF_CHECK_EQ(0, shutdown(s, SHUT_RDWR));
741	ATF_REQUIRE(SIG_ERR != signal(SIGPIPE, shutdown_send_sigpipe_handler));
742	ssize = send(s, data, sizeof(data), MSG_EOR);
743	ATF_CHECK_EQ(1, got_sigpipe);
744}
745
746/* nonblocking send(2) and recv(2) a single short record */
747ATF_TC_WITHOUT_HEAD(send_recv_nonblocking);
748ATF_TC_BODY(send_recv_nonblocking, tc)
749{
750	int sv[2];
751	const int bufsize = 64;
752	const char *data = "data";
753	char recv_buf[bufsize];
754	ssize_t datalen;
755	ssize_t ssize, rsize;
756
757	/* setup the socket pair */
758	do_socketpair_nonblocking(sv);
759
760	/* Verify that there is nothing to receive */
761	rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL);
762	ATF_CHECK_EQ(EAGAIN, errno);
763	ATF_CHECK_EQ(-1, rsize);
764
765	/* send and receive a small packet */
766	datalen = strlen(data) + 1;	/* +1 for the null */
767	ssize = send(sv[0], data, datalen, MSG_EOR);
768	if (ssize < 0) {
769		perror("send");
770		atf_tc_fail("send returned < 0");
771	}
772	ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd",
773	    datalen, ssize);
774
775	rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL);
776	ATF_CHECK_EQ(datalen, rsize);
777}
778
779/*
780 * We should get EMSGSIZE if we try to send a message larger than the socket
781 * buffer, with blocking sockets
782 */
783ATF_TC_WITHOUT_HEAD(emsgsize);
784ATF_TC_BODY(emsgsize, tc)
785{
786	int sv[2];
787	const size_t sndbufsize = 8192;
788	const size_t rcvbufsize = 8192;
789	const size_t pktsize = (sndbufsize + rcvbufsize) * 2;
790	char sndbuf[pktsize];
791	ssize_t ssize;
792
793	/* setup the socket pair */
794	do_socketpair(sv);
795	/* Setup the buffers */
796	ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
797	    sizeof(sndbufsize)));
798	ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
799	    sizeof(rcvbufsize)));
800
801	ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
802	ATF_CHECK_EQ(EMSGSIZE, errno);
803	ATF_CHECK_EQ(-1, ssize);
804}
805
806/*
807 * We should get EMSGSIZE if we try to send a message larger than the socket
808 * buffer, with nonblocking sockets
809 */
810ATF_TC_WITHOUT_HEAD(emsgsize_nonblocking);
811ATF_TC_BODY(emsgsize_nonblocking, tc)
812{
813	int sv[2];
814	const size_t sndbufsize = 8192;
815	const size_t rcvbufsize = 8192;
816	const size_t pktsize = (sndbufsize + rcvbufsize) * 2;
817	char sndbuf[pktsize];
818	ssize_t ssize;
819
820	/* setup the socket pair */
821	do_socketpair_nonblocking(sv);
822	/* Setup the buffers */
823	ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
824	    sizeof(sndbufsize)));
825	ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
826	    sizeof(rcvbufsize)));
827
828	ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
829	ATF_CHECK_EQ(EMSGSIZE, errno);
830	ATF_CHECK_EQ(-1, ssize);
831}
832
833
834/*
835 * We should get EAGAIN if we try to send a message larger than the socket
836 * buffer, with nonblocking sockets.  Test with several different sockbuf sizes
837 */
838ATF_TC_WITHOUT_HEAD(eagain_8k_8k);
839ATF_TC_BODY(eagain_8k_8k, tc)
840{
841	atf_tc_expect_fail("PR kern/185812 send(2) on a UNIX domain SEQPACKET socket returns EMSGSIZE instead of EAGAIN");
842	test_eagain(8192, 8192);
843}
844ATF_TC_WITHOUT_HEAD(eagain_8k_128k);
845ATF_TC_BODY(eagain_8k_128k, tc)
846{
847	atf_tc_expect_fail("PR kern/185812 send(2) on a UNIX domain SEQPACKET socket returns EMSGSIZE instead of EAGAIN");
848	test_eagain(8192, 131072);
849}
850ATF_TC_WITHOUT_HEAD(eagain_128k_8k);
851ATF_TC_BODY(eagain_128k_8k, tc)
852{
853	atf_tc_expect_fail("PR kern/185812 send(2) on a UNIX domain SEQPACKET socket returns EMSGSIZE instead of EAGAIN");
854	test_eagain(131072, 8192);
855}
856ATF_TC_WITHOUT_HEAD(eagain_128k_128k);
857ATF_TC_BODY(eagain_128k_128k, tc)
858{
859	atf_tc_expect_fail("PR kern/185812 send(2) on a UNIX domain SEQPACKET socket returns EMSGSIZE instead of EAGAIN");
860	test_eagain(131072, 131072);
861}
862
863
864/*
865 * nonblocking send(2) and recv(2) of several records, which should collectively
866 * fill up the send buffer but not the receive buffer
867 */
868ATF_TC_WITHOUT_HEAD(rcvbuf_oversized);
869ATF_TC_BODY(rcvbuf_oversized, tc)
870{
871	int i;
872	int sv[2];
873	const int pktsize = 1024;
874	const size_t sndbufsize = 8192;
875	const size_t rcvbufsize = 131072;
876	const size_t geometric_mean_bufsize = 32768;
877	const int numpkts = geometric_mean_bufsize / pktsize;
878	char sndbuf[pktsize];
879	char recv_buf[pktsize];
880	ssize_t ssize, rsize;
881
882	/* setup the socket pair */
883	do_socketpair_nonblocking(sv);
884	ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
885	    sizeof(sndbufsize)));
886	ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
887	    sizeof(rcvbufsize)));
888
889	/*
890	 * Send and receive packets that are collectively greater than the send
891	 * buffer, but less than the receive buffer
892	 */
893	for (i=0; i < numpkts; i++) {
894		/* Fill the buffer */
895		memset(sndbuf, i, pktsize);
896
897		/* send the packet */
898		ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
899		if (ssize < 0) {
900			perror("send");
901			atf_tc_fail("send returned < 0");
902		}
903		ATF_CHECK_EQ_MSG(pktsize, ssize,
904		    "expected %zd=send(...) but got %zd", pktsize, ssize);
905
906		/* Receive it */
907
908		rsize = recv(sv[1], recv_buf, pktsize, MSG_WAITALL);
909		if (rsize < 0) {
910			perror("recv");
911			atf_tc_fail("recv returned < 0");
912		}
913		ATF_CHECK_EQ_MSG(pktsize, rsize,
914		    "expected %zd=send(...) but got %zd", pktsize, rsize);
915
916		/* Verify the contents */
917		ATF_CHECK_EQ_MSG(0, memcmp(sndbuf, recv_buf, pktsize),
918		    "Received data miscompare");
919	}
920
921	/* Trying to receive again should return EAGAIN */
922	rsize = recv(sv[1], recv_buf, pktsize, MSG_WAITALL);
923	ATF_CHECK_EQ(EAGAIN, errno);
924	ATF_CHECK_EQ(-1, rsize);
925}
926
927/*
928 * Simulate the behavior of a blocking pipe.  The sender will send until his
929 * buffer fills up, then we'll simulate a scheduler switch that will allow the
930 * receiver to read until his buffer empties.  Repeat the process until the
931 * transfer is complete.
932 * Repeat the test with multiple send and receive buffer sizes
933 */
934ATF_TC_WITHOUT_HEAD(pipe_simulator_8k_8k);
935ATF_TC_BODY(pipe_simulator_8k_8k, tc)
936{
937	test_pipe_simulator(8192, 8192);
938}
939
940ATF_TC_WITHOUT_HEAD(pipe_simulator_8k_128k);
941ATF_TC_BODY(pipe_simulator_8k_128k, tc)
942{
943	test_pipe_simulator(8192, 131072);
944}
945
946ATF_TC_WITHOUT_HEAD(pipe_simulator_128k_8k);
947ATF_TC_BODY(pipe_simulator_128k_8k, tc)
948{
949	atf_tc_expect_fail("PR kern/185812 SOCK_SEQPACKET AF_UNIX sockets with asymmetrical buffers drop packets");
950	test_pipe_simulator(131072, 8192);
951}
952
953ATF_TC_WITHOUT_HEAD(pipe_simulator_128k_128k);
954ATF_TC_BODY(pipe_simulator_128k_128k, tc)
955{
956	test_pipe_simulator(131072, 131072);
957}
958
959/*
960 * Test blocking I/O by passing data between two threads.  The total amount of
961 * data will be >> buffer size to force blocking.  Repeat the test with multiple
962 * send and receive buffer sizes
963 */
964ATF_TC_WITHOUT_HEAD(pipe_8k_8k);
965ATF_TC_BODY(pipe_8k_8k, tc)
966{
967	atf_tc_expect_fail("PR kern/185812 send(2) on a UNIX domain SEQPACKET socket returns EMSGSIZE instead of EAGAIN");
968	test_pipe(8192, 8192);
969}
970
971ATF_TC_WITHOUT_HEAD(pipe_8k_128k);
972ATF_TC_BODY(pipe_8k_128k, tc)
973{
974	atf_tc_expect_fail("PR kern/185812 send(2) on a UNIX domain SEQPACKET socket returns EMSGSIZE instead of EAGAIN");
975	test_pipe(8192, 131072);
976}
977
978ATF_TC_WITHOUT_HEAD(pipe_128k_8k);
979ATF_TC_BODY(pipe_128k_8k, tc)
980{
981	/*
982	 * kern/185812 causes this test case to both fail and timeout.  The
983	 * atf-c-api(3) doesn't have a way to set such an expectation.
984	 * If you use atf_tc_expect_fail, then it will timeout.  If you use
985	 * atf_tc_expect_timeout, then it will fail.  If you use both, then it
986	 * will show up as an unexpected pass, which is much worse
987	 *
988	 * https://code.google.com/p/kyua/issues/detail?id=76
989	 */
990	atf_tc_expect_fail("PR kern/185812 send(2) on a UNIX domain SEQPACKET socket returns EMSGSIZE instead of EAGAIN");
991	test_pipe(131072, 8192);
992}
993
994ATF_TC_WITHOUT_HEAD(pipe_128k_128k);
995ATF_TC_BODY(pipe_128k_128k, tc)
996{
997	atf_tc_expect_fail("PR kern/185812 send(2) on a UNIX domain SEQPACKET socket returns EMSGSIZE instead of EAGAIN");
998	test_pipe(131072, 131072);
999}
1000
1001
1002/*
1003 * Test single-packet I/O with and without blocking, with symmetric buffers of
1004 * various sizes
1005 */
1006ATF_TC_WITHOUT_HEAD(sendrecv_8k);
1007ATF_TC_BODY(sendrecv_8k, tc)
1008{
1009	test_sendrecv_symmetric_buffers(8 * 1024, true);
1010}
1011ATF_TC_WITHOUT_HEAD(sendrecv_16k);
1012ATF_TC_BODY(sendrecv_16k, tc)
1013{
1014	test_sendrecv_symmetric_buffers(16 * 1024, true);
1015}
1016ATF_TC_WITHOUT_HEAD(sendrecv_32k);
1017ATF_TC_BODY(sendrecv_32k, tc)
1018{
1019	test_sendrecv_symmetric_buffers(32 * 1024, true);
1020}
1021ATF_TC_WITHOUT_HEAD(sendrecv_64k);
1022ATF_TC_BODY(sendrecv_64k, tc)
1023{
1024	test_sendrecv_symmetric_buffers(64 * 1024, true);
1025}
1026ATF_TC_WITHOUT_HEAD(sendrecv_128k);
1027ATF_TC_BODY(sendrecv_128k, tc)
1028{
1029	test_sendrecv_symmetric_buffers(128 * 1024, true);
1030}
1031ATF_TC_WITHOUT_HEAD(sendrecv_8k_nonblocking);
1032ATF_TC_BODY(sendrecv_8k_nonblocking, tc)
1033{
1034	test_sendrecv_symmetric_buffers(8 * 1024, false);
1035}
1036ATF_TC_WITHOUT_HEAD(sendrecv_16k_nonblocking);
1037ATF_TC_BODY(sendrecv_16k_nonblocking, tc)
1038{
1039	test_sendrecv_symmetric_buffers(16 * 1024, false);
1040}
1041ATF_TC_WITHOUT_HEAD(sendrecv_32k_nonblocking);
1042ATF_TC_BODY(sendrecv_32k_nonblocking, tc)
1043{
1044	test_sendrecv_symmetric_buffers(32 * 1024, false);
1045}
1046ATF_TC_WITHOUT_HEAD(sendrecv_64k_nonblocking);
1047ATF_TC_BODY(sendrecv_64k_nonblocking, tc)
1048{
1049	test_sendrecv_symmetric_buffers(64 * 1024, false);
1050}
1051ATF_TC_WITHOUT_HEAD(sendrecv_128k_nonblocking);
1052ATF_TC_BODY(sendrecv_128k_nonblocking, tc)
1053{
1054	test_sendrecv_symmetric_buffers(128 * 1024, false);
1055}
1056
1057
1058/*
1059 * Main.
1060 */
1061
1062ATF_TP_ADD_TCS(tp)
1063{
1064	/* Basic creation and connection tests */
1065	ATF_TP_ADD_TC(tp, create_socket);
1066	ATF_TP_ADD_TC(tp, create_socketpair);
1067	ATF_TP_ADD_TC(tp, listen_unbound);
1068	ATF_TP_ADD_TC(tp, bind);
1069	ATF_TP_ADD_TC(tp, listen_bound);
1070	ATF_TP_ADD_TC(tp, connect);
1071	ATF_TP_ADD_TC(tp, accept);
1072	ATF_TP_ADD_TC(tp, fcntl_nonblock);
1073	ATF_TP_ADD_TC(tp, resize_buffers);
1074	ATF_TP_ADD_TC(tp, resize_connected_buffers);
1075
1076	/* Unthreaded I/O tests */
1077	ATF_TP_ADD_TC(tp, send_recv);
1078	ATF_TP_ADD_TC(tp, send_recv_nonblocking);
1079	ATF_TP_ADD_TC(tp, send_recv_with_connect);
1080	ATF_TP_ADD_TC(tp, sendto_recvfrom);
1081	ATF_TP_ADD_TC(tp, shutdown_send);
1082	ATF_TP_ADD_TC(tp, shutdown_send_sigpipe);
1083	ATF_TP_ADD_TC(tp, emsgsize);
1084	ATF_TP_ADD_TC(tp, emsgsize_nonblocking);
1085	ATF_TP_ADD_TC(tp, eagain_8k_8k);
1086	ATF_TP_ADD_TC(tp, eagain_8k_128k);
1087	ATF_TP_ADD_TC(tp, eagain_128k_8k);
1088	ATF_TP_ADD_TC(tp, eagain_128k_128k);
1089	ATF_TP_ADD_TC(tp, sendrecv_8k);
1090	ATF_TP_ADD_TC(tp, sendrecv_16k);
1091	ATF_TP_ADD_TC(tp, sendrecv_32k);
1092	ATF_TP_ADD_TC(tp, sendrecv_64k);
1093	ATF_TP_ADD_TC(tp, sendrecv_128k);
1094	ATF_TP_ADD_TC(tp, sendrecv_8k_nonblocking);
1095	ATF_TP_ADD_TC(tp, sendrecv_16k_nonblocking);
1096	ATF_TP_ADD_TC(tp, sendrecv_32k_nonblocking);
1097	ATF_TP_ADD_TC(tp, sendrecv_64k_nonblocking);
1098	ATF_TP_ADD_TC(tp, sendrecv_128k_nonblocking);
1099	ATF_TP_ADD_TC(tp, rcvbuf_oversized);
1100	ATF_TP_ADD_TC(tp, pipe_simulator_8k_8k);
1101	ATF_TP_ADD_TC(tp, pipe_simulator_8k_128k);
1102	ATF_TP_ADD_TC(tp, pipe_simulator_128k_8k);
1103	ATF_TP_ADD_TC(tp, pipe_simulator_128k_128k);
1104
1105	/* Threaded I/O tests with blocking sockets */
1106	ATF_TP_ADD_TC(tp, pipe_8k_8k);
1107	ATF_TP_ADD_TC(tp, pipe_8k_128k);
1108	ATF_TP_ADD_TC(tp, pipe_128k_8k);
1109	ATF_TP_ADD_TC(tp, pipe_128k_128k);
1110
1111	return atf_no_error();
1112}
1113