Deleted Added
full compact
unix_seqpacket_test.c (262871) unix_seqpacket_test.c (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>
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 262871 2014-03-06 21:47:22Z asomers $");
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
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
46void
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
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
58void
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 */
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 */
76const char*
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
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 x)
119shutdown_send_sigpipe_handler(int __unused x)
120{
121 got_sigpipe = 1;
122}
123
124/*
125 * Parameterized test function bodies
126 */
120{
121 got_sigpipe = 1;
122}
123
124/*
125 * Parameterized test function bodies
126 */
127void
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;
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;
134 char sndbuf[pktsize];
135 char sndbuf[pktsize];
135 char recv_buf[pktsize];
136 ssize_t ssize, rsize;
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 */
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 < totalsize / pktsize; i++) {
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
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
162void
162static void
163test_sendrecv_symmetric_buffers(size_t bufsize, int blocking) {
164 int s;
165 int sv[2];
163test_sendrecv_symmetric_buffers(size_t bufsize, int blocking) {
164 int s;
165 int sv[2];
166 const size_t pktsize = bufsize / 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
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
204void
204static void
205test_pipe_simulator(size_t sndbufsize, size_t rcvbufsize)
206{
205test_pipe_simulator(size_t sndbufsize, size_t rcvbufsize)
206{
207 int s, num_sent, num_received;
207 int num_sent, num_received;
208 int sv[2];
208 int sv[2];
209 const size_t pktsize = MIN(sndbufsize, rcvbufsize) / 4;
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
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
334void
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;
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 num_sent, num_received;
340 int sv[2];
341 const size_t pktsize = MIN(sndbufsize, rcvbufsize) / 4;
342 int numpkts;
343
344 /* setup the socket pair */
345 do_socketpair(sv);
346 /* Setup the buffers */
347 ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
348 sizeof(sndbufsize)));
349 ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
350 sizeof(rcvbufsize)));
351
352 /* Send a total amount of data comfortably greater than the buffers */
353 numpkts = MAX(sndbufsize, rcvbufsize) * 8 / pktsize;
354
355 /* Start the child threads */
356 writer_data.pktsize = pktsize;
357 writer_data.numpkts = numpkts;
358 writer_data.so = sv[0];
359 reader_data.pktsize = pktsize;
360 reader_data.numpkts = numpkts;
361 reader_data.so = sv[1];
362 ATF_REQUIRE_EQ(0, pthread_create(&writer, NULL, test_pipe_writer,
363 (void*)&writer_data));
364 ATF_REQUIRE_EQ(0, pthread_create(&reader, NULL, test_pipe_reader,
365 (void*)&reader_data));
366
367 /* Join the children */
368 ATF_REQUIRE_EQ(0, pthread_join(writer, NULL));
369 ATF_REQUIRE_EQ(0, pthread_join(reader, NULL));
370}
371
372
373/*
374 * Test Cases
375 */
376
377/* Create a SEQPACKET socket */
378ATF_TC_WITHOUT_HEAD(create_socket);
379ATF_TC_BODY(create_socket, tc)
380{
381 int s;
382
383 s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
384 ATF_CHECK(s >= 0);
385}
386
387/* Create SEQPACKET sockets using socketpair(2) */
388ATF_TC_WITHOUT_HEAD(create_socketpair);
389ATF_TC_BODY(create_socketpair, tc)
390{
391 int sv[2];
392 int s;
393
394 s = socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, sv);
395 ATF_CHECK_EQ(0, s);
396 ATF_CHECK(sv[0] >= 0);
397 ATF_CHECK(sv[1] >= 0);
398 ATF_CHECK(sv[0] != sv[1]);
399}
400
401/* Call listen(2) without first calling bind(2). It should fail */
402ATF_TC_WITHOUT_HEAD(listen_unbound);
403ATF_TC_BODY(listen_unbound, tc)
404{
405 int s, r;
406
407 s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
408 ATF_REQUIRE(s > 0);
409 r = listen(s, -1);
410 /* expect listen to fail since we haven't called bind(2) */
411 ATF_CHECK(r != 0);
412}
413
414/* Bind the socket to a file */
415ATF_TC_WITHOUT_HEAD(bind);
416ATF_TC_BODY(bind, tc)
417{
418 struct sockaddr_un sun;
419 /* ATF's isolation mechanisms will guarantee uniqueness of this file */
420 const char *path = "sock";
421 int s, r;
422
423 s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
424 ATF_REQUIRE(s >= 0);
425
426 bzero(&sun, sizeof(sun));
427 sun.sun_family = AF_LOCAL;
428 sun.sun_len = sizeof(sun);
429 strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
430 r = bind(s, (struct sockaddr *)&sun, sizeof(sun));
431 ATF_CHECK_EQ(0, r);
432}
433
434/* listen(2) a socket that is already bound(2) should succeed */
435ATF_TC_WITHOUT_HEAD(listen_bound);
436ATF_TC_BODY(listen_bound, tc)
437{
438 struct sockaddr_un sun;
439 /* ATF's isolation mechanisms will guarantee uniqueness of this file */
440 const char *path = "sock";
441 int s, r, l;
442
443 s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
444 ATF_REQUIRE(s >= 0);
445
446 bzero(&sun, sizeof(sun));
447 sun.sun_family = AF_LOCAL;
448 sun.sun_len = sizeof(sun);
449 strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
450 r = bind(s, (struct sockaddr *)&sun, sizeof(sun));
451 l = listen(s, -1);
452 ATF_CHECK_EQ(0, r);
453 ATF_CHECK_EQ(0, l);
454}
455
456/* connect(2) can make a connection */
457ATF_TC_WITHOUT_HEAD(connect);
458ATF_TC_BODY(connect, tc)
459{
460 struct sockaddr_un sun;
461 /* ATF's isolation mechanisms will guarantee uniqueness of this file */
462 const char *path = "sock";
463 int s, r, err, l, s2;
464
465 s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
466 ATF_REQUIRE(s >= 0);
467
468 bzero(&sun, sizeof(sun));
469 sun.sun_family = AF_LOCAL;
470 sun.sun_len = sizeof(sun);
471 strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
472 r = bind(s, (struct sockaddr *)&sun, sizeof(sun));
473 l = listen(s, -1);
474 ATF_CHECK_EQ(0, r);
475 ATF_CHECK_EQ(0, l);
476
477 /* Create the other socket */
478 s2 = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
479 ATF_REQUIRE(s2 >= 0);
480 err = connect(s2, (struct sockaddr*)&sun, sizeof(sun));
481 if (err != 0) {
482 perror("connect");
483 atf_tc_fail("connect(2) failed");
484 }
485}
486
487/* accept(2) can receive a connection */
488ATF_TC_WITHOUT_HEAD(accept);
489ATF_TC_BODY(accept, tc)
490{
491 int sv[2];
492
493 mk_pair_of_sockets(sv);
494}
495
496
497/* Set O_NONBLOCK on the socket */
498ATF_TC_WITHOUT_HEAD(fcntl_nonblock);
499ATF_TC_BODY(fcntl_nonblock, tc)
500{
501 int s;
502
503 s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
504 ATF_REQUIRE(s >= 0);
505 if (fcntl(s, F_SETFL, O_NONBLOCK) == -1) {
506 perror("fcntl");
507 atf_tc_fail("fcntl failed");
508 }
509}
510
511/* Resize the send and receive buffers */
512ATF_TC_WITHOUT_HEAD(resize_buffers);
513ATF_TC_BODY(resize_buffers, tc)
514{
515 int s;
516 int sndbuf = 12345;
517 int rcvbuf = 23456;
518 int xs, xr;
519 socklen_t sl = sizeof(xs);
520
521 s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
522 ATF_REQUIRE(s >= 0);
523
524 printf(" Socket Buffer Sizes\n");
525 printf(" | SNDBUF | RCVBUF |\n");
526 ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_SNDBUF, &xs, &sl));
527 ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_RCVBUF, &xr, &sl));
528 printf("Default | %7d | %7d |\n", xs, xr);
529
530 if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf)) != 0){
531 perror("setsockopt");
532 atf_tc_fail("setsockopt(SO_SNDBUF) failed");
533 }
534 ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_SNDBUF, &xs, &sl));
535 ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_RCVBUF, &xr, &sl));
536 printf("After changing SNDBUF | %7d | %7d |\n", xs, xr);
537
538 if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)) != 0){
539 perror("setsockopt");
540 atf_tc_fail("setsockopt(SO_RCVBUF) failed");
541 }
542 ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_SNDBUF, &xs, &sl));
543 ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_RCVBUF, &xr, &sl));
544 printf("After changing RCVBUF | %7d | %7d |\n", xs, xr);
545}
546
547/*
548 * Resize the send and receive buffers of a connected socketpair
549 * Print some useful debugging info too
550 */
551ATF_TC_WITHOUT_HEAD(resize_connected_buffers);
552ATF_TC_BODY(resize_connected_buffers, tc)
553{
554 int sv[2];
555 int sndbuf = 12345;
556 int rcvbuf = 23456;
557 int err;
558 int ls, lr, rs, rr;
559 socklen_t sl = sizeof(ls);
560
561 /* setup the socket pair */
562 do_socketpair(sv);
563
564 printf(" Socket Buffer Sizes\n");
565 printf(" | Left Socket | Right Socket |\n");
566 printf(" | SNDBUF | RCVBUF | SNDBUF | RCVBUF |\n");
567 ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &ls, &sl));
568 ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &lr, &sl));
569 ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &rs, &sl));
570 ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rr, &sl));
571 printf("Default | %7d | %7d | %7d | %7d |\n",
572 ls, lr, rs, rr);
573
574 /* Update one side's send buffer */
575 err = setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf));
576 if (err != 0){
577 perror("setsockopt");
578 atf_tc_fail("setsockopt(SO_SNDBUF) failed");
579 }
580
581 ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &ls, &sl));
582 ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &lr, &sl));
583 ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &rs, &sl));
584 ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rr, &sl));
585 printf("After changing Left's SNDBUF | %7d | %7d | %7d | %7d |\n",
586 ls, lr, rs, rr);
587
588 /* Update the same side's receive buffer */
589 err = setsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf));
590 if (err != 0){
591 perror("setsockopt");
592 atf_tc_fail("setsockopt(SO_RCVBUF) failed");
593 }
594
595 ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &ls, &sl));
596 ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &lr, &sl));
597 ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &rs, &sl));
598 ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rr, &sl));
599 printf("After changing Left's RCVBUF | %7d | %7d | %7d | %7d |\n",
600 ls, lr, rs, rr);
601}
602
603
604/* send(2) and recv(2) a single short record */
605ATF_TC_WITHOUT_HEAD(send_recv);
606ATF_TC_BODY(send_recv, tc)
607{
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{
608 int s;
609 int sv[2];
610 const int bufsize = 64;
611 const char *data = "data";
612 char recv_buf[bufsize];
607 int sv[2];
608 const int bufsize = 64;
609 const char *data = "data";
610 char recv_buf[bufsize];
613 size_t datalen;
611 ssize_t datalen;
614 ssize_t ssize, rsize;
615
616 /* setup the socket pair */
617 do_socketpair(sv);
618
619 /* send and receive a small packet */
620 datalen = strlen(data) + 1; /* +1 for the null */
621 ssize = send(sv[0], data, datalen, MSG_EOR);
622 if (ssize < 0) {
623 perror("send");
624 atf_tc_fail("send returned < 0");
625 }
626 ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd",
627 datalen, ssize);
628
629 rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL);
630 ATF_CHECK_EQ(datalen, rsize);
631}
632
633/* sendto(2) and recvfrom(2) a single short record
634 * According to The Open Group Base Specifications Issue 6 IEEE Std 1003.1, 2004
635 * Edition, sendto(2) is exactly the same as send(2) on a connection-mode socket
636 *
637 * According to the same spec, not all protocols are required to provide the
638 * source addres in recvfrom(2).
639 */
640ATF_TC_WITHOUT_HEAD(sendto_recvfrom);
641ATF_TC_BODY(sendto_recvfrom, tc)
642{
643 const char* path;
644 struct sockaddr_storage from;
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;
645 int s;
646 int sv[2];
647 const int bufsize = 64;
648 const char *data = "data";
649 char recv_buf[bufsize];
643 int sv[2];
644 const int bufsize = 64;
645 const char *data = "data";
646 char recv_buf[bufsize];
650 size_t datalen;
647 ssize_t datalen;
651 ssize_t ssize, rsize;
652 socklen_t fromlen;
653
654 /* setup the socket pair */
655 path = mk_pair_of_sockets(sv);
656
657 /* send and receive a small packet */
658 datalen = strlen(data) + 1; /* +1 for the null */
659 ssize = sendto(sv[0], data, datalen, MSG_EOR, NULL, 0);
660 if (ssize < 0) {
661 perror("send");
662 atf_tc_fail("send returned < 0");
663 }
664 ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd",
665 datalen, ssize);
666
667 fromlen = sizeof(from);
668 rsize = recvfrom(sv[1], recv_buf, bufsize, MSG_WAITALL,
669 (struct sockaddr*)&from, &fromlen);
670 if (ssize < 0) {
671 perror("recvfrom");
672 atf_tc_fail("recvfrom returned < 0");
673 }
674 ATF_CHECK_EQ(datalen, rsize);
675
676 /*
677 * FreeBSD does not currently provide the source address for SEQ_PACKET
678 * AF_UNIX sockets, and POSIX does not require it, so these two checks
679 * are disabled. If FreeBSD gains that feature in the future, then
680 * these checks may be reenabled
681 */
682 /* ATF_CHECK_EQ(PF_LOCAL, from.ss_family); */
683 /* ATF_CHECK_STREQ(path, ((struct sockaddr_un*)&from)->sun_path); */
684}
685
686/*
687 * send(2) and recv(2) a single short record with sockets created the
688 * traditional way, involving bind, listen, connect, and accept
689 */
690ATF_TC_WITHOUT_HEAD(send_recv_with_connect);
691ATF_TC_BODY(send_recv_with_connect, tc)
692{
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{
693 const char* path;
694 int sv[2];
695 const int bufsize = 64;
696 const char *data = "data";
697 char recv_buf[bufsize];
690 int sv[2];
691 const int bufsize = 64;
692 const char *data = "data";
693 char recv_buf[bufsize];
698 size_t datalen;
694 ssize_t datalen;
699 ssize_t ssize, rsize;
700
701 mk_pair_of_sockets(sv);
702
703 /* send and receive a small packet */
704 datalen = strlen(data) + 1; /* +1 for the null */
705 ssize = send(sv[0], data, datalen, MSG_EOR);
706 if (ssize < 0) {
707 perror("send");
708 atf_tc_fail("send returned < 0");
709 }
710 ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd",
711 datalen, ssize);
712
713 rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL);
714 ATF_CHECK_EQ(datalen, rsize);
715}
716
717/* send(2) should fail on a shutdown socket */
718ATF_TC_WITHOUT_HEAD(shutdown_send);
719ATF_TC_BODY(shutdown_send, tc)
720{
721 int s;
722 const char *data = "data";
723 ssize_t ssize;
724
725 s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
726 ATF_CHECK(s >= 0);
727 ATF_CHECK_EQ(0, shutdown(s, SHUT_RDWR));
728 /* USE MSG_NOSIGNAL so we don't get SIGPIPE */
729 ssize = send(s, data, sizeof(data), MSG_EOR | MSG_NOSIGNAL);
730 ATF_CHECK_EQ(EPIPE, errno);
731 ATF_CHECK_EQ(-1, ssize);
732}
733
734/* send(2) should cause SIGPIPE on a shutdown socket */
735ATF_TC_WITHOUT_HEAD(shutdown_send_sigpipe);
736ATF_TC_BODY(shutdown_send_sigpipe, tc)
737{
738 int s;
739 const char *data = "data";
740 ssize_t ssize;
741
742 s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
743 ATF_CHECK(s >= 0);
744 ATF_CHECK_EQ(0, shutdown(s, SHUT_RDWR));
745 ATF_REQUIRE(SIG_ERR != signal(SIGPIPE, shutdown_send_sigpipe_handler));
746 ssize = send(s, data, sizeof(data), MSG_EOR);
747 ATF_CHECK_EQ(1, got_sigpipe);
748}
749
750/* nonblocking send(2) and recv(2) a single short record */
751ATF_TC_WITHOUT_HEAD(send_recv_nonblocking);
752ATF_TC_BODY(send_recv_nonblocking, tc)
753{
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{
754 int s;
755 int sv[2];
756 const int bufsize = 64;
757 const char *data = "data";
758 char recv_buf[bufsize];
750 int sv[2];
751 const int bufsize = 64;
752 const char *data = "data";
753 char recv_buf[bufsize];
759 size_t datalen;
754 ssize_t datalen;
760 ssize_t ssize, rsize;
761
762 /* setup the socket pair */
763 do_socketpair_nonblocking(sv);
764
765 /* Verify that there is nothing to receive */
766 rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL);
767 ATF_CHECK_EQ(EAGAIN, errno);
768 ATF_CHECK_EQ(-1, rsize);
769
770 /* send and receive a small packet */
771 datalen = strlen(data) + 1; /* +1 for the null */
772 ssize = send(sv[0], data, datalen, MSG_EOR);
773 if (ssize < 0) {
774 perror("send");
775 atf_tc_fail("send returned < 0");
776 }
777 ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd",
778 datalen, ssize);
779
780 rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL);
781 ATF_CHECK_EQ(datalen, rsize);
782}
783
784/*
785 * We should get EMSGSIZE if we try to send a message larger than the socket
786 * buffer, with blocking sockets
787 */
788ATF_TC_WITHOUT_HEAD(emsgsize);
789ATF_TC_BODY(emsgsize, tc)
790{
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{
791 int s;
792 int sv[2];
793 const size_t sndbufsize = 8192;
794 const size_t rcvbufsize = 8192;
795 const size_t pktsize = (sndbufsize + rcvbufsize) * 2;
796 char sndbuf[pktsize];
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];
797 char recv_buf[pktsize];
798 ssize_t ssize, rsize;
791 ssize_t ssize;
799
800 /* setup the socket pair */
801 do_socketpair(sv);
802 /* Setup the buffers */
803 ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
804 sizeof(sndbufsize)));
805 ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
806 sizeof(rcvbufsize)));
807
808 ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
809 ATF_CHECK_EQ(EMSGSIZE, errno);
810 ATF_CHECK_EQ(-1, ssize);
811}
812
813/*
814 * We should get EMSGSIZE if we try to send a message larger than the socket
815 * buffer, with nonblocking sockets
816 */
817ATF_TC_WITHOUT_HEAD(emsgsize_nonblocking);
818ATF_TC_BODY(emsgsize_nonblocking, tc)
819{
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{
820 int s;
821 int sv[2];
822 const size_t sndbufsize = 8192;
823 const size_t rcvbufsize = 8192;
824 const size_t pktsize = (sndbufsize + rcvbufsize) * 2;
825 char sndbuf[pktsize];
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];
826 char recv_buf[pktsize];
827 ssize_t ssize, rsize;
818 ssize_t ssize;
828
829 /* setup the socket pair */
830 do_socketpair_nonblocking(sv);
831 /* Setup the buffers */
832 ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
833 sizeof(sndbufsize)));
834 ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
835 sizeof(rcvbufsize)));
836
837 ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
838 ATF_CHECK_EQ(EMSGSIZE, errno);
839 ATF_CHECK_EQ(-1, ssize);
840}
841
842
843/*
844 * We should get EAGAIN if we try to send a message larger than the socket
845 * buffer, with nonblocking sockets. Test with several different sockbuf sizes
846 */
847ATF_TC_WITHOUT_HEAD(eagain_8k_8k);
848ATF_TC_BODY(eagain_8k_8k, tc)
849{
850 atf_tc_expect_fail("PR kern/185812 send(2) on a UNIX domain SEQPACKET socket returns EMSGSIZE instead of EAGAIN");
851 test_eagain(8192, 8192);
852}
853ATF_TC_WITHOUT_HEAD(eagain_8k_128k);
854ATF_TC_BODY(eagain_8k_128k, tc)
855{
856 atf_tc_expect_fail("PR kern/185812 send(2) on a UNIX domain SEQPACKET socket returns EMSGSIZE instead of EAGAIN");
857 test_eagain(8192, 131072);
858}
859ATF_TC_WITHOUT_HEAD(eagain_128k_8k);
860ATF_TC_BODY(eagain_128k_8k, tc)
861{
862 atf_tc_expect_fail("PR kern/185812 send(2) on a UNIX domain SEQPACKET socket returns EMSGSIZE instead of EAGAIN");
863 test_eagain(131072, 8192);
864}
865ATF_TC_WITHOUT_HEAD(eagain_128k_128k);
866ATF_TC_BODY(eagain_128k_128k, tc)
867{
868 atf_tc_expect_fail("PR kern/185812 send(2) on a UNIX domain SEQPACKET socket returns EMSGSIZE instead of EAGAIN");
869 test_eagain(131072, 131072);
870}
871
872
873/*
874 * nonblocking send(2) and recv(2) of several records, which should collectively
875 * fill up the send buffer but not the receive buffer
876 */
877ATF_TC_WITHOUT_HEAD(rcvbuf_oversized);
878ATF_TC_BODY(rcvbuf_oversized, tc)
879{
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{
880 int s, i, j;
871 int i;
881 int sv[2];
872 int sv[2];
873 const int pktsize = 1024;
882 const size_t sndbufsize = 8192;
883 const size_t rcvbufsize = 131072;
874 const size_t sndbufsize = 8192;
875 const size_t rcvbufsize = 131072;
884 const size_t geom_mean_bufsize = 32768;
885 const int pktsize = 1024;
876 const size_t geometric_mean_bufsize = 32768;
877 const int numpkts = geometric_mean_bufsize / pktsize;
886 char sndbuf[pktsize];
887 char recv_buf[pktsize];
878 char sndbuf[pktsize];
879 char recv_buf[pktsize];
888 size_t datalen;
889 ssize_t ssize, rsize;
890
891 /* setup the socket pair */
892 do_socketpair_nonblocking(sv);
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)));
893
894 /*
895 * Send and receive packets that are collectively greater than the send
896 * buffer, but less than the receive buffer
897 */
888
889 /*
890 * Send and receive packets that are collectively greater than the send
891 * buffer, but less than the receive buffer
892 */
898 for (i=0; i < geom_mean_bufsize / pktsize; i++) {
893 for (i=0; i < numpkts; i++) {
899 /* Fill the buffer */
900 memset(sndbuf, i, pktsize);
901
902 /* send the packet */
903 ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
904 if (ssize < 0) {
905 perror("send");
906 atf_tc_fail("send returned < 0");
907 }
908 ATF_CHECK_EQ_MSG(pktsize, ssize,
909 "expected %zd=send(...) but got %zd", pktsize, ssize);
910
911 /* Receive it */
912
913 rsize = recv(sv[1], recv_buf, pktsize, MSG_WAITALL);
914 if (rsize < 0) {
915 perror("recv");
916 atf_tc_fail("recv returned < 0");
917 }
918 ATF_CHECK_EQ_MSG(pktsize, rsize,
919 "expected %zd=send(...) but got %zd", pktsize, rsize);
920
921 /* Verify the contents */
922 ATF_CHECK_EQ_MSG(0, memcmp(sndbuf, recv_buf, pktsize),
923 "Received data miscompare");
924 }
925
926 /* Trying to receive again should return EAGAIN */
927 rsize = recv(sv[1], recv_buf, pktsize, MSG_WAITALL);
928 ATF_CHECK_EQ(EAGAIN, errno);
929 ATF_CHECK_EQ(-1, rsize);
930}
931
932/*
933 * Simulate the behavior of a blocking pipe. The sender will send until his
934 * buffer fills up, then we'll simulate a scheduler switch that will allow the
935 * receiver to read until his buffer empties. Repeat the process until the
936 * transfer is complete.
937 * Repeat the test with multiple send and receive buffer sizes
938 */
939ATF_TC_WITHOUT_HEAD(pipe_simulator_8k_8k);
940ATF_TC_BODY(pipe_simulator_8k_8k, tc)
941{
942 test_pipe_simulator(8192, 8192);
943}
944
945ATF_TC_WITHOUT_HEAD(pipe_simulator_8k_128k);
946ATF_TC_BODY(pipe_simulator_8k_128k, tc)
947{
948 test_pipe_simulator(8192, 131072);
949}
950
951ATF_TC_WITHOUT_HEAD(pipe_simulator_128k_8k);
952ATF_TC_BODY(pipe_simulator_128k_8k, tc)
953{
954 atf_tc_expect_fail("PR kern/185812 SOCK_SEQPACKET AF_UNIX sockets with asymmetrical buffers drop packets");
955 test_pipe_simulator(131072, 8192);
956}
957
958ATF_TC_WITHOUT_HEAD(pipe_simulator_128k_128k);
959ATF_TC_BODY(pipe_simulator_128k_128k, tc)
960{
961 test_pipe_simulator(131072, 131072);
962}
963
964/*
965 * Test blocking I/O by passing data between two threads. The total amount of
966 * data will be >> buffer size to force blocking. Repeat the test with multiple
967 * send and receive buffer sizes
968 */
969ATF_TC_WITHOUT_HEAD(pipe_8k_8k);
970ATF_TC_BODY(pipe_8k_8k, tc)
971{
972 atf_tc_expect_fail("PR kern/185812 send(2) on a UNIX domain SEQPACKET socket returns EMSGSIZE instead of EAGAIN");
973 test_pipe(8192, 8192);
974}
975
976ATF_TC_WITHOUT_HEAD(pipe_8k_128k);
977ATF_TC_BODY(pipe_8k_128k, tc)
978{
979 atf_tc_expect_fail("PR kern/185812 send(2) on a UNIX domain SEQPACKET socket returns EMSGSIZE instead of EAGAIN");
980 test_pipe(8192, 131072);
981}
982
983ATF_TC_WITHOUT_HEAD(pipe_128k_8k);
984ATF_TC_BODY(pipe_128k_8k, tc)
985{
986 /*
987 * kern/185812 causes this test case to both fail and timeout. The
988 * atf-c-api(3) doesn't have a way to set such an expectation.
989 * If you use atf_tc_expect_fail, then it will timeout. If you use
990 * atf_tc_expect_timeout, then it will fail. If you use both, then it
991 * will show up as an unexpected pass, which is much worse
992 *
993 * https://code.google.com/p/kyua/issues/detail?id=76
994 */
995 atf_tc_expect_fail("PR kern/185812 send(2) on a UNIX domain SEQPACKET socket returns EMSGSIZE instead of EAGAIN");
996 test_pipe(131072, 8192);
997}
998
999ATF_TC_WITHOUT_HEAD(pipe_128k_128k);
1000ATF_TC_BODY(pipe_128k_128k, tc)
1001{
1002 atf_tc_expect_fail("PR kern/185812 send(2) on a UNIX domain SEQPACKET socket returns EMSGSIZE instead of EAGAIN");
1003 test_pipe(131072, 131072);
1004}
1005
1006
1007/*
1008 * Test single-packet I/O with and without blocking, with symmetric buffers of
1009 * various sizes
1010 */
1011ATF_TC_WITHOUT_HEAD(sendrecv_8k);
1012ATF_TC_BODY(sendrecv_8k, tc)
1013{
1014 test_sendrecv_symmetric_buffers(8 * 1024, true);
1015}
1016ATF_TC_WITHOUT_HEAD(sendrecv_16k);
1017ATF_TC_BODY(sendrecv_16k, tc)
1018{
1019 test_sendrecv_symmetric_buffers(16 * 1024, true);
1020}
1021ATF_TC_WITHOUT_HEAD(sendrecv_32k);
1022ATF_TC_BODY(sendrecv_32k, tc)
1023{
1024 test_sendrecv_symmetric_buffers(32 * 1024, true);
1025}
1026ATF_TC_WITHOUT_HEAD(sendrecv_64k);
1027ATF_TC_BODY(sendrecv_64k, tc)
1028{
1029 test_sendrecv_symmetric_buffers(64 * 1024, true);
1030}
1031ATF_TC_WITHOUT_HEAD(sendrecv_128k);
1032ATF_TC_BODY(sendrecv_128k, tc)
1033{
1034 test_sendrecv_symmetric_buffers(128 * 1024, true);
1035}
1036ATF_TC_WITHOUT_HEAD(sendrecv_8k_nonblocking);
1037ATF_TC_BODY(sendrecv_8k_nonblocking, tc)
1038{
1039 test_sendrecv_symmetric_buffers(8 * 1024, false);
1040}
1041ATF_TC_WITHOUT_HEAD(sendrecv_16k_nonblocking);
1042ATF_TC_BODY(sendrecv_16k_nonblocking, tc)
1043{
1044 test_sendrecv_symmetric_buffers(16 * 1024, false);
1045}
1046ATF_TC_WITHOUT_HEAD(sendrecv_32k_nonblocking);
1047ATF_TC_BODY(sendrecv_32k_nonblocking, tc)
1048{
1049 test_sendrecv_symmetric_buffers(32 * 1024, false);
1050}
1051ATF_TC_WITHOUT_HEAD(sendrecv_64k_nonblocking);
1052ATF_TC_BODY(sendrecv_64k_nonblocking, tc)
1053{
1054 test_sendrecv_symmetric_buffers(64 * 1024, false);
1055}
1056ATF_TC_WITHOUT_HEAD(sendrecv_128k_nonblocking);
1057ATF_TC_BODY(sendrecv_128k_nonblocking, tc)
1058{
1059 test_sendrecv_symmetric_buffers(128 * 1024, false);
1060}
1061
1062
1063/*
1064 * Main.
1065 */
1066
1067ATF_TP_ADD_TCS(tp)
1068{
1069 /* Basic creation and connection tests */
1070 ATF_TP_ADD_TC(tp, create_socket);
1071 ATF_TP_ADD_TC(tp, create_socketpair);
1072 ATF_TP_ADD_TC(tp, listen_unbound);
1073 ATF_TP_ADD_TC(tp, bind);
1074 ATF_TP_ADD_TC(tp, listen_bound);
1075 ATF_TP_ADD_TC(tp, connect);
1076 ATF_TP_ADD_TC(tp, accept);
1077 ATF_TP_ADD_TC(tp, fcntl_nonblock);
1078 ATF_TP_ADD_TC(tp, resize_buffers);
1079 ATF_TP_ADD_TC(tp, resize_connected_buffers);
1080
1081 /* Unthreaded I/O tests */
1082 ATF_TP_ADD_TC(tp, send_recv);
1083 ATF_TP_ADD_TC(tp, send_recv_nonblocking);
1084 ATF_TP_ADD_TC(tp, send_recv_with_connect);
1085 ATF_TP_ADD_TC(tp, sendto_recvfrom);
1086 ATF_TP_ADD_TC(tp, shutdown_send);
1087 ATF_TP_ADD_TC(tp, shutdown_send_sigpipe);
1088 ATF_TP_ADD_TC(tp, emsgsize);
1089 ATF_TP_ADD_TC(tp, emsgsize_nonblocking);
1090 ATF_TP_ADD_TC(tp, eagain_8k_8k);
1091 ATF_TP_ADD_TC(tp, eagain_8k_128k);
1092 ATF_TP_ADD_TC(tp, eagain_128k_8k);
1093 ATF_TP_ADD_TC(tp, eagain_128k_128k);
1094 ATF_TP_ADD_TC(tp, sendrecv_8k);
1095 ATF_TP_ADD_TC(tp, sendrecv_16k);
1096 ATF_TP_ADD_TC(tp, sendrecv_32k);
1097 ATF_TP_ADD_TC(tp, sendrecv_64k);
1098 ATF_TP_ADD_TC(tp, sendrecv_128k);
1099 ATF_TP_ADD_TC(tp, sendrecv_8k_nonblocking);
1100 ATF_TP_ADD_TC(tp, sendrecv_16k_nonblocking);
1101 ATF_TP_ADD_TC(tp, sendrecv_32k_nonblocking);
1102 ATF_TP_ADD_TC(tp, sendrecv_64k_nonblocking);
1103 ATF_TP_ADD_TC(tp, sendrecv_128k_nonblocking);
1104 ATF_TP_ADD_TC(tp, rcvbuf_oversized);
1105 ATF_TP_ADD_TC(tp, pipe_simulator_8k_8k);
1106 ATF_TP_ADD_TC(tp, pipe_simulator_8k_128k);
1107 ATF_TP_ADD_TC(tp, pipe_simulator_128k_8k);
1108 ATF_TP_ADD_TC(tp, pipe_simulator_128k_128k);
1109
1110 /* Threaded I/O tests with blocking sockets */
1111 ATF_TP_ADD_TC(tp, pipe_8k_8k);
1112 ATF_TP_ADD_TC(tp, pipe_8k_128k);
1113 ATF_TP_ADD_TC(tp, pipe_128k_8k);
1114 ATF_TP_ADD_TC(tp, pipe_128k_128k);
1115
1116 return atf_no_error();
1117}
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}