xref: /minix3/minix/tests/socklib.c (revision 49bf8d5c6a022606b48ca9d706bd1c539025e3f5)
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <signal.h>
5 #include <sys/param.h>
6 #include <sys/wait.h>
7 #include <sys/socket.h>
8 #include <sys/ioctl.h>
9 #include <unistd.h>
10 #include <fcntl.h>
11 
12 #include "common.h"
13 #include "socklib.h"
14 
15 /* 0 = check, 1 = generate source, 2 = generate CSV */
16 #define SOCKLIB_SWEEP_GENERATE 0
17 
18 #if SOCKLIB_SWEEP_GENERATE
19 /* Link against minix/usr.bin/trace/error.o to make this work! */
20 const char *get_error_name(int err);
21 
22 #if SOCKLIB_SWEEP_GENERATE == 2
23 static const char *statename[S_MAX] = {
24 	"S_NEW",
25 	"S_N_SHUT_R",
26 	"S_N_SHUT_W",
27 	"S_N_SHUT_RW",
28 	"S_BOUND",
29 	"S_LISTENING",
30 	"S_L_SHUT_R",
31 	"S_L_SHUT_W",
32 	"S_L_SHUT_RW",
33 	"S_CONNECTING",
34 	"S_C_SHUT_R",
35 	"S_C_SHUT_W",
36 	"S_C_SHUT_RW",
37 	"S_CONNECTED",
38 	"S_ACCEPTED",
39 	"S_SHUT_R",
40 	"S_SHUT_W",
41 	"S_SHUT_RW",
42 	"S_RSHUT_R",
43 	"S_RSHUT_W",
44 	"S_RSHUT_RW",
45 	"S_SHUT2_R",
46 	"S_SHUT2_W",
47 	"S_SHUT2_RW",
48 	"S_PRE_EOF",
49 	"S_AT_EOF",
50 	"S_POST_EOF",
51 	"S_PRE_SHUT_R",
52 	"S_EOF_SHUT_R",
53 	"S_POST_SHUT_R",
54 	"S_PRE_SHUT_W",
55 	"S_EOF_SHUT_W",
56 	"S_POST_SHUT_W",
57 	"S_PRE_SHUT_RW",
58 	"S_EOF_SHUT_RW",
59 	"S_POST_SHUT_RW",
60 	"S_PRE_RESET",
61 	"S_AT_RESET",
62 	"S_POST_RESET",
63 	"S_FAILED",
64 	"S_POST_FAILED",
65 };
66 #endif
67 
68 static const char *callname[C_MAX] = {
69 	"C_ACCEPT",
70 	"C_BIND",
71 	"C_CONNECT",
72 	"C_GETPEERNAME",
73 	"C_GETSOCKNAME",
74 	"C_GETSOCKOPT_ERR",
75 	"C_GETSOCKOPT_KA",
76 	"C_GETSOCKOPT_RB",
77 	"C_IOCTL_NREAD",
78 	"C_LISTEN",
79 	"C_RECV",
80 	"C_RECVFROM",
81 	"C_SEND",
82 	"C_SENDTO",
83 	"C_SELECT_R",
84 	"C_SELECT_W",
85 	"C_SELECT_X",
86 	"C_SETSOCKOPT_BC",
87 	"C_SETSOCKOPT_KA",
88 	"C_SETSOCKOPT_L",
89 	"C_SETSOCKOPT_RA",
90 	"C_SHUTDOWN_R",
91 	"C_SHUTDOWN_RW",
92 	"C_SHUTDOWN_W",
93 };
94 #endif
95 
96 static int socklib_sigpipe;
97 
98 /*
99  * Signal handler for SIGPIPE signals.
100  */
101 static void
102 socklib_signal(int sig)
103 {
104 
105 	if (sig != SIGPIPE) e(0);
106 
107 	socklib_sigpipe++;
108 }
109 
110 /*
111  * The given socket file descriptor 'fd' has been set up in the desired state.
112  * Perform the given call 'call' on it, possibly using local socket address
113  * 'local_addr' (for binding) or remote socket address 'remote_addr' (for
114  * connecting or to store resulting addresses), both of size 'addr_len'.
115  * Return the result of the call, using a positive value if the call succeeded,
116  * or a negated errno code if the call failed.
117  */
118 int
119 socklib_sweep_call(enum call call, int fd, struct sockaddr * local_addr,
120 	struct sockaddr * remote_addr, socklen_t addr_len)
121 {
122 	char data[1];
123 	struct linger l;
124 	fd_set fd_set;
125 	struct timeval tv;
126 	socklen_t len;
127 	int i, r, fd2;
128 
129 	fd2 = -1;
130 
131 	switch (call) {
132 	case C_ACCEPT:
133 		r = accept(fd, remote_addr, &addr_len);
134 
135 		if (r >= 0)
136 			fd2 = r;
137 
138 		break;
139 
140 	case C_BIND:
141 		r = bind(fd, local_addr, addr_len);
142 
143 		break;
144 
145 	case C_CONNECT:
146 		r = connect(fd, remote_addr, addr_len);
147 
148 		break;
149 
150 	case C_GETPEERNAME:
151 		r = getpeername(fd, remote_addr, &addr_len);
152 
153 		break;
154 
155 	case C_GETSOCKNAME:
156 		r = getsockname(fd, remote_addr, &addr_len);
157 
158 		break;
159 
160 	case C_GETSOCKOPT_ERR:
161 		len = sizeof(i);
162 
163 		r = getsockopt(fd, SOL_SOCKET, SO_ERROR, &i, &len);
164 
165 		/*
166 		 * We assume this call always succeeds, and test against the
167 		 * pending error.
168 		 */
169 		if (r != 0) e(0);
170 		if (i != 0) {
171 			r = -1;
172 			errno = i;
173 		}
174 
175 		break;
176 
177 	case C_GETSOCKOPT_KA:
178 		len = sizeof(i);
179 
180 		r = getsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &i, &len);
181 
182 		break;
183 
184 	case C_GETSOCKOPT_RB:
185 		len = sizeof(i);
186 
187 		r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &i, &len);
188 
189 		break;
190 
191 	case C_IOCTL_NREAD:
192 		r = ioctl(fd, FIONREAD, &i);
193 
194 		/* On success, we test against the returned value here. */
195 		if (r == 0)
196 			r = i;
197 
198 		break;
199 
200 	case C_LISTEN:
201 		r = listen(fd, 1);
202 
203 		break;
204 
205 	case C_RECV:
206 		r = recv(fd, data, sizeof(data), 0);
207 
208 		break;
209 
210 	case C_RECVFROM:
211 		r = recvfrom(fd, data, sizeof(data), 0, remote_addr,
212 		    &addr_len);
213 
214 		break;
215 
216 	case C_SEND:
217 		data[0] = 0;
218 
219 		r = send(fd, data, sizeof(data), 0);
220 
221 		break;
222 
223 	case C_SENDTO:
224 		data[0] = 0;
225 
226 		r = sendto(fd, data, sizeof(data), 0, remote_addr, addr_len);
227 
228 		break;
229 
230 	case C_SETSOCKOPT_BC:
231 		i = 0;
232 
233 		r = setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &i, sizeof(i));
234 
235 		break;
236 
237 	case C_SETSOCKOPT_KA:
238 		i = 1;
239 
240 		r = setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &i, sizeof(i));
241 
242 		break;
243 
244 	case C_SETSOCKOPT_L:
245 		l.l_onoff = 1;
246 		l.l_linger = 0;
247 
248 		r = setsockopt(fd, SOL_SOCKET, SO_LINGER, &l, sizeof(l));
249 
250 		break;
251 
252 	case C_SETSOCKOPT_RA:
253 		i = 1;
254 
255 		r = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i));
256 
257 		break;
258 
259 	case C_SELECT_R:
260 	case C_SELECT_W:
261 	case C_SELECT_X:
262 		FD_ZERO(&fd_set);
263 		FD_SET(fd, &fd_set);
264 
265 		tv.tv_sec = 0;
266 		tv.tv_usec = 0;
267 
268 		r = select(fd + 1, (call == C_SELECT_R) ? &fd_set : NULL,
269 		    (call == C_SELECT_W) ? &fd_set : NULL,
270 		    (call == C_SELECT_X) ? &fd_set : NULL, &tv);
271 
272 		break;
273 
274 	case C_SHUTDOWN_R:
275 		r = shutdown(fd, SHUT_RD);
276 
277 		break;
278 
279 	case C_SHUTDOWN_W:
280 		r = shutdown(fd, SHUT_WR);
281 
282 		break;
283 
284 	case C_SHUTDOWN_RW:
285 		r = shutdown(fd, SHUT_RDWR);
286 
287 		break;
288 
289 	default:
290 		r = -1;
291 		errno = EINVAL;
292 		e(0);
293 	}
294 
295 	if (r < -1) e(0);
296 
297 	if (r == -1)
298 		r = -errno;
299 
300 	if (fd2 >= 0 && close(fd2) != 0) e(0);
301 
302 	return r;
303 }
304 
305 /*
306  * Perform a sweep of socket calls vs socket states, testing the outcomes
307  * against provided tables or (if SOCKLIB_SWEEP_GENERATE is set) reporting on
308  * the outcomes instead.  The caller must provide the following:
309  *
310  * - the socket domain, type, and protocol to test; these are simply forwarded
311  *   to the callback function (see below);
312  * - the set of S_ states to test, as array 'states' with 'nstates' elements;
313  * - unless generating output, a matrix of expected results as 'results', which
314  *   is actually a two-dimensional array with dimensions [C_MAX][nstates], with
315  *   either positive call output or a negated call errno code in each cell;
316  * - a callback function 'proc' that must set up a socket in the given state
317  *   and pass it to socklib_sweep_call().
318  *
319  * The 'states' array allows each socket sweep test to support a different set
320  * of states, because not every type of socket can be put in every possible
321  * state.  All calls are always tried in each state, though.
322  *
323  * The sweep also tests for SIGPIPE generation, which assumes that all calls on
324  * SOCK_STREAM sockets that return EPIPE, also raise a SIGPIPE signal, and that
325  * no other SIGPIPE signal is ever raised otherwise.
326  *
327  * Standard e() error throwing is used for set-up and result mismatches.
328  */
329 void
330 socklib_sweep(int domain, int type, int protocol, const enum state * states,
331 	unsigned int nstates, const int * results, int (* proc)(int domain,
332 	int type, int protocol, enum state, enum call))
333 {
334 	struct sigaction act, oact;
335 	enum state state;
336 	enum call call;
337 #if SOCKLIB_SWEEP_GENERATE
338 	const char *name;
339 	int res, *nresults;
340 #else
341 	int res, exp;
342 #endif
343 
344 	memset(&act, 0, sizeof(act));
345 	act.sa_handler = socklib_signal;
346 	if (sigaction(SIGPIPE, &act, &oact) != 0) e(0);
347 
348 #if SOCKLIB_SWEEP_GENERATE
349 	if ((nresults = malloc(nstates * C_MAX)) == NULL) e(0);
350 #endif
351 
352 	for (state = 0; state < nstates; state++) {
353 		for (call = 0; call < C_MAX; call++) {
354 			socklib_sigpipe = 0;
355 
356 			res = proc(domain, type, protocol, states[state],
357 			    call);
358 
359 			/*
360 			 * If the result was EPIPE and this is a stream-type
361 			 * socket, we must have received exactly one SIGPIPE
362 			 * signal.  Otherwise, we must not have received one.
363 			 * Note that technically, the SIGPIPE could arrive
364 			 * sometime after this check, but with regular system
365 			 * service scheduling that will never happen.
366 			 */
367 			if (socklib_sigpipe !=
368 			    (res == -EPIPE && type == SOCK_STREAM)) e(0);
369 
370 #if SOCKLIB_SWEEP_GENERATE
371 			nresults[call * nstates + state] = res;
372 #else
373 			exp = results[call * nstates + state];
374 
375 			if (res != exp) {
376 				printf("FAIL state %d call %d res %d exp %d\n",
377 				    state, call, res, exp);
378 				e(0);
379 			}
380 #endif
381 		}
382 	}
383 
384 	if (sigaction(SIGPIPE, &oact, NULL) != 0) e(0);
385 
386 #if SOCKLIB_SWEEP_GENERATE
387 #if SOCKLIB_SWEEP_GENERATE == 1
388 	/*
389 	 * Generate a table in C form, ready to be pasted into test source.
390 	 * Obviously, generated results should be hand-checked carefully before
391 	 * being pasted into a test.  Arguably these tables should be hand-made
392 	 * for maximum scrutiny, but I already checked the results from the
393 	 * CSV form (#define SOCKLIB_SWEEP_GENERATE 2) and have no desire for
394 	 * RSI -dcvmoole
395 	 */
396 	printf("\nstatic const int X_results[][__arraycount(X_states)] = {\n");
397 	for (call = 0; call < C_MAX; call++) {
398 		if ((name = callname[call]) == NULL) e(0);
399 		printf("\t[%s]%s%s%s= {", name,
400 		    (strlen(name) <= 21) ? "\t" : "",
401 		    (strlen(name) <= 13) ? "\t" : "",
402 		    (strlen(name) <= 5) ? "\t" : "");
403 		for (state = 0; state < nstates; state++) {
404 			if (state % 4 == 0)
405 				printf("\n\t\t");
406 			res = nresults[call * nstates + state];
407 			name = (res < 0) ? get_error_name(-res) : NULL;
408 			if (name != NULL) {
409 				printf("-%s,", name);
410 				if ((state + 1) % 4 != 0 &&
411 				    state < nstates - 1)
412 					printf("%s%s",
413 					    (strlen(name) <= 13) ? "\t" : "",
414 					    (strlen(name) <= 5) ? "\t" : "");
415 			} else {
416 				printf("%d,", res);
417 				if ((state + 1) % 4 != 0 &&
418 				    state < nstates - 1)
419 					printf("\t\t");
420 			}
421 		}
422 		printf("\n\t},\n");
423 	}
424 	printf("};\n");
425 #elif SOCKLIB_SWEEP_GENERATE == 2
426 	/* Generate table in CSV form. */
427 	printf("\n");
428 	for (state = 0; state < nstates; state++)
429 		printf(",%s", statename[states[state]] + 2);
430 	for (call = 0; call < C_MAX; call++) {
431 		printf("\n%s", callname[call] + 2);
432 		for (state = 0; state < nstates; state++) {
433 			res = nresults[call * nstates + state];
434 			name = (res < 0) ? get_error_name(-res) : NULL;
435 			if (name != NULL)
436 				printf(",%s", name);
437 			else
438 				printf(",%d", res);
439 		}
440 	}
441 	printf("\n");
442 #endif
443 
444 	free(nresults);
445 #endif
446 }
447 
448 /*
449  * Test for large sends and receives on stream sockets with MSG_WAITALL.
450  */
451 void
452 socklib_large_transfers(int fd[2])
453 {
454 	char *buf;
455 	pid_t pid;
456 	int i, status;
457 
458 #define LARGE_BUF	(4096*1024)
459 
460 	if ((buf = malloc(LARGE_BUF)) == NULL) e(0);
461 	memset(buf, 0, LARGE_BUF);
462 
463 	pid = fork();
464 	switch (pid) {
465 	case 0:
466 		errct = 0;
467 
468 		if (close(fd[0]) != 0) e(0);
469 
470 		/* Part 1. */
471 		if (recv(fd[1], buf, LARGE_BUF, MSG_WAITALL) != LARGE_BUF)
472 			e(0);
473 
474 		for (i = 0; i < LARGE_BUF; i++)
475 			if (buf[i] != (char)(i + (i >> 16))) e(0);
476 
477 		if (recv(fd[1], buf, LARGE_BUF,
478 		    MSG_DONTWAIT | MSG_WAITALL) != -1) e(0);
479 		if (errno != EWOULDBLOCK) e(0);
480 
481 		/* Part 2. */
482 		if (send(fd[1], buf, LARGE_BUF / 2, 0) != LARGE_BUF / 2) e(0);
483 
484 		if (shutdown(fd[1], SHUT_WR) != 0) e(0);
485 
486 		/* Part 3. */
487 		memset(buf, 'y', LARGE_BUF);
488 
489 		if (recv(fd[1], buf, LARGE_BUF, MSG_WAITALL) != LARGE_BUF - 1)
490 			e(0);
491 
492 		for (i = 0; i < LARGE_BUF - 1; i++)
493 			if (buf[i] != (char)(i + (i >> 16))) e(0);
494 		if (buf[LARGE_BUF - 1] != 'y') e(0);
495 
496 		if (recv(fd[1], buf, LARGE_BUF, MSG_WAITALL) != 0) e(0);
497 
498 		exit(errct);
499 	case -1:
500 		e(0);
501 	}
502 
503 	if (close(fd[1]) != 0) e(0);
504 
505 	/* Part 1: check that a large send fully arrives. */
506 	for (i = 0; i < LARGE_BUF; i++)
507 		buf[i] = (char)(i + (i >> 16));
508 
509 	if (send(fd[0], buf, LARGE_BUF, 0) != LARGE_BUF) e(0);
510 
511 	/* Part 2: check that remote shutdown terminates a partial receive. */
512 	memset(buf, 'x', LARGE_BUF);
513 
514 	if (recv(fd[0], buf, LARGE_BUF, MSG_WAITALL) != LARGE_BUF / 2) e(0);
515 
516 	for (i = 0; i < LARGE_BUF / 2; i++)
517 		if (buf[i] != (char)(i + (i >> 16))) e(0);
518 	for (; i < LARGE_BUF; i++)
519 		if (buf[i] != 'x') e(0);
520 
521 	if (recv(fd[0], buf, LARGE_BUF, MSG_WAITALL) != 0) e(0);
522 
523 	/* Part 3: check that remote close terminates a partial receive. */
524 	for (i = 0; i < LARGE_BUF; i++)
525 		buf[i] = (char)(i + (i >> 16));
526 
527 	if (send(fd[0], buf, LARGE_BUF - 1, 0) != LARGE_BUF - 1) e(0);
528 
529 	if (close(fd[0]) != 0) e(0);
530 
531 	if (waitpid(pid, &status, 0) != pid) e(0);
532 	if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) e(0);
533 
534 	free(buf);
535 }
536 
537 #define PRINT_STATS	0
538 
539 /*
540  * A randomized producer-consumer test for stream sockets.  As part of this,
541  * we also perform very basic bulk functionality tests of FIONREAD, MSG_PEEK,
542  * MSG_DONTWAIT, and MSG_WAITALL.
543  */
544 void
545 socklib_producer_consumer(int fd[2])
546 {
547 	char *buf;
548 	time_t t;
549 	socklen_t len, size, off;
550 	ssize_t r;
551 	pid_t pid;
552 	int i, rcvlen, status, exp, flags, num, stat[3] = { 0, 0, 0 };
553 
554 	len = sizeof(rcvlen);
555 	if (getsockopt(fd[0], SOL_SOCKET, SO_RCVBUF, &rcvlen, &len) != 0) e(0);
556 	if (len != sizeof(rcvlen)) e(0);
557 
558 	size = rcvlen * 3;
559 
560 	if ((buf = malloc(size)) == NULL) e(0);
561 
562 	t = time(NULL);
563 
564 	/*
565 	 * We vary small versus large (random) send and receive sizes,
566 	 * splitting the entire transfer in four phases along those lines.
567 	 *
568 	 * In theory, the use of an extra system call, the use of MSG_PEEK, and
569 	 * the fact that without MSG_WAITALL a receive call may return any
570 	 * partial result, all contribute to the expectation that the consumer
571 	 * side will fall behind the producer.  In order to test both filling
572 	 * and draining the receive queue, we use a somewhat larger small
573 	 * receive size for the consumer size (up to 256 bytes rather than 64)
574 	 * during each half of the four phases.  The effectiveness of these
575 	 * numbers can be verified with statistics (disabled by default).
576 	 */
577 #define TRANSFER_SIZE	(16 * 1024 * 1024)
578 
579 	pid = fork();
580 	switch (pid) {
581 	case 0:
582 		errct = 0;
583 
584 		if (close(fd[0]) != 0) e(0);
585 
586 		srand48(t + 1);
587 
588 		for (off = 0; off < TRANSFER_SIZE; ) {
589 			if (off < TRANSFER_SIZE / 2)
590 				len = lrand48() %
591 				    ((off / (TRANSFER_SIZE / 8) % 2) ? 64 :
592 				    256);
593 			else
594 				len = lrand48() % size;
595 
596 			num = lrand48() % 16;
597 			flags = 0;
598 			if (num & 1) flags |= MSG_PEEK;
599 			if (num & 2) flags |= MSG_WAITALL;
600 			if (num & 4) flags |= MSG_DONTWAIT;
601 			if (num & 8) {
602 				/*
603 				 * Obviously there are race conditions here but
604 				 * the returned number should be a lower bound.
605 				 */
606 				if (ioctl(fd[1], FIONREAD, &exp) != 0) e(0);
607 				if (exp < 0 || exp > rcvlen) e(0);
608 			} else
609 				exp = -1;
610 
611 			stat[0]++;
612 
613 			if ((r = recv(fd[1], buf, len, flags)) == -1) {
614 				if (errno != EWOULDBLOCK) e(0);
615 				if (exp > 0) e(0);
616 
617 				stat[2]++;
618 				continue;
619 			}
620 
621 			if (r < len) {
622 				stat[1]++;
623 
624 				if (exp > r) e(0);
625 			}
626 
627 			for (i = 0; i < r; i++)
628 				if (buf[i] != (char)((off + i) +
629 				    ((off + i) >> 16))) e(0);
630 
631 			if (!(flags & MSG_PEEK)) {
632 				off += r;
633 
634 				if ((flags & (MSG_DONTWAIT | MSG_WAITALL)) ==
635 				    MSG_WAITALL && r != len &&
636 				    off < TRANSFER_SIZE) e(0);
637 			}
638 		}
639 
640 #if PRINT_STATS
641 		/*
642 		 * The second and third numbers should ideally be a large but
643 		 * non-dominating fraction of the first one.
644 		 */
645 		printf("RECV: total %d short %d again %d\n",
646 		    stat[0], stat[1], stat[2]);
647 #endif
648 
649 		if (close(fd[1]) != 0) e(0);
650 		exit(errct);
651 	case -1:
652 		e(0);
653 	}
654 
655 	if (close(fd[1]) != 0) e(0);
656 
657 	srand48(t);
658 
659 	for (off = 0; off < TRANSFER_SIZE; ) {
660 		if (off < TRANSFER_SIZE / 4 ||
661 		    (off >= TRANSFER_SIZE / 2 && off < TRANSFER_SIZE * 3 / 4))
662 			len = lrand48() % 64;
663 		else
664 			len = lrand48() % size;
665 
666 		if (len > TRANSFER_SIZE - off)
667 			len = TRANSFER_SIZE - off;
668 
669 		for (i = 0; i < len; i++)
670 			buf[i] = (off + i) + ((off + i) >> 16);
671 
672 		flags = (lrand48() % 2) ? MSG_DONTWAIT : 0;
673 
674 		stat[0]++;
675 
676 		r = send(fd[0], buf, len, flags);
677 
678 		if (r != len) {
679 			if (r > (ssize_t)len) e(0);
680 			if (!(flags & MSG_DONTWAIT)) e(0);
681 			if (r == -1) {
682 				if (errno != EWOULDBLOCK) e(0);
683 				r = 0;
684 
685 				stat[2]++;
686 			} else
687 				stat[1]++;
688 		}
689 
690 		if (off / (TRANSFER_SIZE / 4) !=
691 		    (off + r) / (TRANSFER_SIZE / 4))
692 			sleep(1);
693 
694 		off += r;
695 	}
696 
697 #if PRINT_STATS
698 	/*
699 	 * The second and third numbers should ideally be a large but non-
700 	 * dominating fraction of the first one.
701 	 */
702 	printf("SEND: total %d short %d again %d\n",
703 	    stat[0], stat[1], stat[2]);
704 #endif
705 
706 	free(buf);
707 
708 	if (close(fd[0]) != 0) e(0);
709 
710 	if (waitpid(pid, &status, 0) != pid) e(0);
711 	if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) e(0);
712 }
713 
714 /*
715  * Signal handler which just needs to exist, so that invoking it will interrupt
716  * an ongoing system call.
717  */
718 static void
719 socklib_got_signal(int sig __unused)
720 {
721 
722 	/* Nothing. */
723 }
724 
725 /*
726  * Test for receiving on stream sockets.  The quick summary here is that
727  * recv(MSG_WAITALL) should keep suspending until as many bytes as requested
728  * are also received (or the call is interrupted, or no more can possibly be
729  * received - the meaning of the latter depends on the domain), and,
730  * SO_RCVLOWAT acts as an admission test for the receive: nothing is received
731  * until there are at least as many bytes are available in the receive buffer
732  * as the low receive watermark, or the whole receive request length, whichever
733  * is smaller. In addition, select(2) should use the same threshold.
734  */
735 #define MAX_BYTES	2	/* set to 3 for slightly better(?) testing */
736 #define USLEEP_TIME	250000	/* increase on wimpy platforms if needed */
737 
738 static void
739 socklib_stream_recv_sub(int (* socket_pair)(int, int, int, int *), int domain,
740 	int type, int idata, int istate, int rlowat, int len, int bits,
741 	int act, int (* break_recv)(int, const char *, size_t))
742 {
743 	const char *data = "ABCDE";	/* this limits MAX_BYTES to 3 */
744 	struct sigaction sa;
745 	struct timeval tv;
746 	fd_set fds;
747 	char buf[3];
748 	pid_t pid;
749 	int fd[2], val, flags, min, res, err;
750 	int pfd[2], edata, tstate, fl, status;
751 
752 	if (socket_pair(domain, type, 0, fd) != 0) e(0);
753 
754 	/*
755 	 * Set up the initial condition on the sockets.
756 	 */
757 	if (idata > 0)
758 		if (send(fd[1], data, idata, 0) != idata) e(0);
759 
760 	switch (istate) {
761 	case 0: break;
762 	case 1: if (shutdown(fd[0], SHUT_RD) != 0) e(0); break;
763 	case 2: if (shutdown(fd[1], SHUT_WR) != 0) e(0); break;
764 	case 3: if (close(fd[1]) != 0) e(0); break;
765 	}
766 
767 	/* Set the low receive water mark. */
768 	if (setsockopt(fd[0], SOL_SOCKET, SO_RCVLOWAT, &rlowat,
769 	    sizeof(rlowat)) != 0) e(0);
770 
771 	/* SO_RCVLOWAT is always bounded by the actual receive length. */
772 	min = MIN(len, rlowat);
773 
774 	/*
775 	 * Do a quick select test to see if its result indeed matches whether
776 	 * the available data in the receive buffer meets the threshold.
777 	 */
778 	FD_ZERO(&fds);
779 	FD_SET(fd[0], &fds);
780 	tv.tv_sec = 0;
781 	tv.tv_usec = 0;
782 	res = select(fd[0] + 1, &fds, NULL, NULL, &tv);
783 	if (res < 0 || res > 1) e(0);
784 	if (res != (idata >= rlowat || istate > 0)) e(0);
785 	if (res == 1 && !FD_ISSET(fd[0], &fds)) e(0);
786 
787 	/* Also do a quick test for ioctl(FIONREAD). */
788 	if (ioctl(fd[0], FIONREAD, &val) != 0) e(0);
789 	if (val != ((istate != 1) ? idata : 0)) e(0);
790 
791 	/* Translate the given bits to receive call flags. */
792 	flags = 0;
793 	if (bits & 1) flags |= MSG_PEEK;
794 	if (bits & 2) flags |= MSG_DONTWAIT;
795 	if (bits & 4) flags |= MSG_WAITALL;
796 
797 	/*
798 	 * Cut short a whole lot of cases, to avoid the overhead of forking,
799 	 * namely when we know the call should return immediately.  This is
800 	 * the case when MSG_DONTWAIT is set, or if a termination condition has
801 	 * been raised, or if enough initial data are available to meet the
802 	 * conditions for the receive call.
803 	 */
804 	if ((flags & MSG_DONTWAIT) || istate > 0 || (idata >= min &&
805 	    ((flags & (MSG_PEEK | MSG_WAITALL)) != MSG_WAITALL ||
806 	    idata >= len))) {
807 		res = recv(fd[0], buf, len, flags);
808 
809 		if (res == -1 && errno != EWOULDBLOCK) e(0);
810 
811 		/*
812 		 * If the socket has been shutdown locally, we will never get
813 		 * anything but zero.  Otherwise, if we meet the SO_RCVLOWAT
814 		 * test, we should have received as much as was available and
815 		 * requested.  Otherwise, if the remote end has been shut down
816 		 * or closed, we expected to get any available data or
817 		 * otherwise EOF (implied with idata==0).  If none of these
818 		 * cases apply, we should have gotten EWOULDBLOCK.
819 		 */
820 		if (istate == 1) {
821 			if (res != 0) e(0);
822 		} else if (idata >= min) {
823 			if (res != MIN(len, idata)) e(0);
824 			if (strncmp(buf, data, res)) e(0);
825 		} else if (istate > 0) {
826 			if (res != idata) e(0);
827 			if (strncmp(buf, data, res)) e(0);
828 		} else
829 			if (res != -1) e(0);
830 
831 		/* Early cleanup and return to avoid even more code clutter. */
832 		if (istate != 3 && close(fd[1]) != 0) e(0);
833 		if (close(fd[0]) != 0) e(0);
834 
835 		return;
836 	}
837 
838 	/*
839 	 * Now starts the interesting stuff: the receive call should now block,
840 	 * even though if we add MSG_DONTWAIT it may not return EWOULDBLOCK,
841 	 * because MSG_DONTWAIT overrides MSG_WAITALL.  As such, we can only
842 	 * test our expectations by actually letting the call block, in a child
843 	 * process, and waiting.  We do test as much of the above assumption as
844 	 * we can just for safety right here, but this is not a substitute for
845 	 * actually blocking even in these cases!
846 	 */
847 	if (!(flags & MSG_WAITALL)) {
848 		if (recv(fd[0], buf, len, flags | MSG_DONTWAIT) != -1) e(0);
849 		if (errno != EWOULDBLOCK) e(0);
850 	}
851 
852 	/*
853 	 * If (act < 12), we send 0, 1, or 2 extra data bytes before forcing
854 	 * the receive call to terminate in one of four ways.
855 	 *
856 	 * If (act == 12), we use a signal to interrupt the receive call.
857 	 */
858 	if (act < 12) {
859 		edata = act % 3;
860 		tstate = act / 3;
861 	} else
862 		edata = tstate = 0;
863 
864 	if (pipe2(pfd, O_NONBLOCK) != 0) e(0);
865 
866 	pid = fork();
867 	switch (pid) {
868 	case 0:
869 		errct = 0;
870 
871 		if (close(fd[1]) != 0) e(0);
872 		if (close(pfd[0]) != 0) e(0);
873 
874 		if (act == 12) {
875 			memset(&sa, 0, sizeof(sa));
876 			sa.sa_handler = socklib_got_signal;
877 			if (sigaction(SIGUSR1, &sa, NULL) != 0) e(0);
878 		}
879 
880 		res = recv(fd[0], buf, len, flags);
881 		err = errno;
882 
883 		if (write(pfd[1], &res, sizeof(res)) != sizeof(res)) e(0);
884 		if (write(pfd[1], &err, sizeof(err)) != sizeof(err)) e(0);
885 
886 		if (res > 0 && strncmp(buf, data, res)) e(0);
887 
888 		exit(errct);
889 	case -1:
890 		e(0);
891 	}
892 
893 	if (close(pfd[1]) != 0) e(0);
894 
895 	/*
896 	 * Allow the child to enter the blocking recv(2), and check the pipe
897 	 * to see if it is really blocked.
898 	 */
899 	if (usleep(USLEEP_TIME) != 0) e(0);
900 
901 	if (read(pfd[0], buf, 1) != -1) e(0);
902 	if (errno != EAGAIN) e(0);
903 
904 	if (edata > 0) {
905 		if (send(fd[1], &data[idata], edata, 0) != edata) e(0);
906 
907 		/*
908 		 * The threshold for the receive is now met if both the minimum
909 		 * is met and MSG_WAITALL was not set (or overridden by
910 		 * MSG_PEEK) or the entire request has been satisfied.
911 		 */
912 		if (idata + edata >= min &&
913 		    ((flags & (MSG_PEEK | MSG_WAITALL)) != MSG_WAITALL ||
914 		    idata + edata >= len)) {
915 			if ((fl = fcntl(pfd[0], F_GETFL, 0)) == -1) e(0);
916 			if (fcntl(pfd[0], F_SETFL, fl & ~O_NONBLOCK) != 0)
917 			    e(0);
918 
919 			if (read(pfd[0], &res, sizeof(res)) != sizeof(res))
920 			    e(0);
921 			if (read(pfd[0], &err, sizeof(err)) != sizeof(err))
922 			    e(0);
923 
924 			if (res != MIN(idata + edata, len)) e(0);
925 
926 			/* Bail out. */
927 			goto cleanup;
928 		}
929 
930 		/* Sleep and test once more. */
931 		if (usleep(USLEEP_TIME) != 0) e(0);
932 
933 		if (read(pfd[0], buf, 1) != -1) e(0);
934 		if (errno != EAGAIN) e(0);
935 	}
936 
937 	if (act < 12) {
938 		/*
939 		 * Now test various ways to terminate the receive call.
940 		 */
941 		switch (tstate) {
942 		case 0: if (shutdown(fd[0], SHUT_RD) != 0) e(0); break;
943 		case 1: if (shutdown(fd[1], SHUT_WR) != 0) e(0); break;
944 		case 2: if (close(fd[1]) != 0) e(0); fd[1] = -1; break;
945 		case 3: fd[1] = break_recv(fd[1], data, strlen(data)); break;
946 		}
947 	} else
948 		if (kill(pid, SIGUSR1) != 0) e(0);
949 
950 	if ((fl = fcntl(pfd[0], F_GETFL, 0)) == -1) e(0);
951 	if (fcntl(pfd[0], F_SETFL, fl & ~O_NONBLOCK) != 0) e(0);
952 
953 	if (read(pfd[0], &res, sizeof(res)) != sizeof(res)) e(0);
954 	if (read(pfd[0], &err, sizeof(err)) != sizeof(err)) e(0);
955 
956 	if (act < 12) {
957 		/*
958 		 * If there were any data we should have received them now;
959 		 * after all the receive minimum stops being relevant when
960 		 * another condition has been raised.  There is one exception:
961 		 * if the receive threshold was never met and we now shut down
962 		 * the socket for reading, EOF is acceptable as return value.
963 		 */
964 		if (tstate == 0 && idata + edata < min) {
965 			if (res != 0) e(0);
966 		} else if (idata + edata > 0) {
967 			if (res != MIN(idata + edata, len)) e(0);
968 		} else if (tstate == 3) {
969 			if (fd[1] == -1) {
970 				if (res != -1) e(0);
971 				if (err != ECONNRESET) e(0);
972 			} else
973 				if (res != len) e(0);
974 		} else
975 			if (res != 0) e(0);
976 	} else {
977 		/*
978 		 * If the receive met the threshold before being interrupted,
979 		 * we should have received at least something.  Otherwise, the
980 		 * receive was never admitted and should just return EINTR.
981 		 */
982 		if (idata >= min) {
983 			if (res != MIN(idata, len)) e(0);
984 		} else {
985 			if (res != -1) e(0);
986 			if (err != EINTR) e(0);
987 		}
988 	}
989 
990 cleanup:
991 	if (close(pfd[0]) != 0) e(0);
992 
993 	if (wait(&status) != pid) e(0);
994 	if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) e(0);
995 
996 	if (fd[1] != -1 && close(fd[1]) != 0) e(0);
997 	if (close(fd[0]) != 0) e(0);
998 }
999 
1000 /*
1001  * Test for receiving on stream sockets.  In particular, test SO_RCVLOWAT,
1002  * MSG_PEEK, MSG_DONTWAIT, and MSG_WAITALL.
1003  */
1004 void
1005 socklib_stream_recv(int (* socket_pair)(int, int, int, int *), int domain,
1006 	int type, int (* break_recv)(int, const char *, size_t))
1007 {
1008 	int idata, istate, rlowat, len, bits, act;
1009 
1010 	/* Insanity. */
1011 	for (idata = 0; idata <= MAX_BYTES; idata++)
1012 		for (istate = 0; istate <= 3; istate++)
1013 			for (rlowat = 1; rlowat <= MAX_BYTES; rlowat++)
1014 				for (len = 1; len <= MAX_BYTES; len++)
1015 					for (bits = 0; bits < 8; bits++)
1016 						for (act = 0; act <= 12; act++)
1017 							socklib_stream_recv_sub
1018 							    (socket_pair,
1019 							    domain, type,
1020 							    idata, istate,
1021 							    rlowat, len, bits,
1022 							    act, break_recv);
1023 }
1024