xref: /freebsd/lib/libc/tests/sys/sendfile_test.c (revision b29e142648453f93bea592b5379ae141137397ee)
1*b29e1426SEnji Cooper /*-
2*b29e1426SEnji Cooper  * Copyright (c) 2018 Enji Cooper.
3*b29e1426SEnji Cooper  * All rights reserved.
4*b29e1426SEnji Cooper  *
5*b29e1426SEnji Cooper  * Redistribution and use in source and binary forms, with or without
6*b29e1426SEnji Cooper  * modification, are permitted provided that the following conditions
7*b29e1426SEnji Cooper  * are met:
8*b29e1426SEnji Cooper  * 1. Redistributions of source code must retain the above copyright
9*b29e1426SEnji Cooper  *    notice, this list of conditions and the following disclaimer.
10*b29e1426SEnji Cooper  * 2. Redistributions in binary form must reproduce the above copyright
11*b29e1426SEnji Cooper  *    notice, this list of conditions and the following disclaimer in the
12*b29e1426SEnji Cooper  *    documentation and/or other materials provided with the distribution.
13*b29e1426SEnji Cooper  *
14*b29e1426SEnji Cooper  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15*b29e1426SEnji Cooper  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16*b29e1426SEnji Cooper  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17*b29e1426SEnji Cooper  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18*b29e1426SEnji Cooper  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19*b29e1426SEnji Cooper  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20*b29e1426SEnji Cooper  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21*b29e1426SEnji Cooper  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22*b29e1426SEnji Cooper  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23*b29e1426SEnji Cooper  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24*b29e1426SEnji Cooper  * SUCH DAMAGE.
25*b29e1426SEnji Cooper  */
26*b29e1426SEnji Cooper 
27*b29e1426SEnji Cooper #include <sys/cdefs.h>
28*b29e1426SEnji Cooper __FBSDID("$FreeBSD$");
29*b29e1426SEnji Cooper 
30*b29e1426SEnji Cooper #include <sys/param.h>
31*b29e1426SEnji Cooper #include <sys/mman.h>
32*b29e1426SEnji Cooper #include <sys/socket.h>
33*b29e1426SEnji Cooper #include <sys/stat.h>
34*b29e1426SEnji Cooper #include <sys/sysctl.h>
35*b29e1426SEnji Cooper #include <sys/uio.h>
36*b29e1426SEnji Cooper #include <err.h>
37*b29e1426SEnji Cooper #include <errno.h>
38*b29e1426SEnji Cooper #include <fcntl.h>
39*b29e1426SEnji Cooper #include <netdb.h>
40*b29e1426SEnji Cooper #include <paths.h>
41*b29e1426SEnji Cooper #include <stdio.h>
42*b29e1426SEnji Cooper #include <stdlib.h>
43*b29e1426SEnji Cooper #include <string.h>
44*b29e1426SEnji Cooper #include <unistd.h>
45*b29e1426SEnji Cooper 
46*b29e1426SEnji Cooper #include <atf-c.h>
47*b29e1426SEnji Cooper 
48*b29e1426SEnji Cooper const char DETERMINISTIC_PATTERN[] =
49*b29e1426SEnji Cooper     "The past is already gone, the future is not yet here. There's only one moment for you to live.\n";
50*b29e1426SEnji Cooper 
51*b29e1426SEnji Cooper #define	SOURCE_FILE		"source"
52*b29e1426SEnji Cooper #define	DESTINATION_FILE	"dest"
53*b29e1426SEnji Cooper 
54*b29e1426SEnji Cooper #define	PORTRANGE_FIRST	"net.inet.ip.portrange.first"
55*b29e1426SEnji Cooper #define	PORTRANGE_LAST	"net.inet.ip.portrange.last"
56*b29e1426SEnji Cooper 
57*b29e1426SEnji Cooper static int portrange_first, portrange_last;
58*b29e1426SEnji Cooper 
59*b29e1426SEnji Cooper static int
60*b29e1426SEnji Cooper get_int_via_sysctlbyname(const char *oidname)
61*b29e1426SEnji Cooper {
62*b29e1426SEnji Cooper 	size_t oldlen;
63*b29e1426SEnji Cooper 	int int_value;
64*b29e1426SEnji Cooper 
65*b29e1426SEnji Cooper 	ATF_REQUIRE_EQ_MSG(sysctlbyname(oidname, &int_value, &oldlen, NULL, 0),
66*b29e1426SEnji Cooper 	    0, "sysctlbyname(%s, ...) failed: %s", oidname, strerror(errno));
67*b29e1426SEnji Cooper 	ATF_REQUIRE_EQ_MSG(sizeof(int_value), oldlen, "sanity check failed");
68*b29e1426SEnji Cooper 
69*b29e1426SEnji Cooper 	return (int_value);
70*b29e1426SEnji Cooper }
71*b29e1426SEnji Cooper 
72*b29e1426SEnji Cooper static int
73*b29e1426SEnji Cooper generate_random_port(int seed)
74*b29e1426SEnji Cooper {
75*b29e1426SEnji Cooper 	int random_port;
76*b29e1426SEnji Cooper 
77*b29e1426SEnji Cooper 	printf("Generating a random port with seed=%d\n", seed);
78*b29e1426SEnji Cooper 	if (portrange_first == 0) {
79*b29e1426SEnji Cooper 		portrange_first = get_int_via_sysctlbyname(PORTRANGE_FIRST);
80*b29e1426SEnji Cooper 		printf("Port range lower bound: %d\n", portrange_first);
81*b29e1426SEnji Cooper 	}
82*b29e1426SEnji Cooper 
83*b29e1426SEnji Cooper 	if (portrange_last == 0) {
84*b29e1426SEnji Cooper 		portrange_last = get_int_via_sysctlbyname(PORTRANGE_LAST);
85*b29e1426SEnji Cooper 		printf("Port range upper bound: %d\n", portrange_last);
86*b29e1426SEnji Cooper 	}
87*b29e1426SEnji Cooper 
88*b29e1426SEnji Cooper 	srand((unsigned)seed);
89*b29e1426SEnji Cooper 
90*b29e1426SEnji Cooper 	random_port = rand() % (portrange_last - portrange_first) +
91*b29e1426SEnji Cooper 	    portrange_first;
92*b29e1426SEnji Cooper 
93*b29e1426SEnji Cooper 	printf("Random port generated: %d\n", random_port);
94*b29e1426SEnji Cooper 	return (random_port);
95*b29e1426SEnji Cooper }
96*b29e1426SEnji Cooper 
97*b29e1426SEnji Cooper static void
98*b29e1426SEnji Cooper resolve_localhost(struct addrinfo **res, int domain, int type, int port)
99*b29e1426SEnji Cooper {
100*b29e1426SEnji Cooper 	char *serv;
101*b29e1426SEnji Cooper 	struct addrinfo hints;
102*b29e1426SEnji Cooper 	int error;
103*b29e1426SEnji Cooper 
104*b29e1426SEnji Cooper 	ATF_REQUIRE_MSG(domain == AF_INET || domain == AF_INET6,
105*b29e1426SEnji Cooper 	    "unhandled domain: %d", domain);
106*b29e1426SEnji Cooper 
107*b29e1426SEnji Cooper 	ATF_REQUIRE_MSG(asprintf(&serv, "%d", port) >= 0,
108*b29e1426SEnji Cooper 	    "asprintf failed: %s", strerror(errno));
109*b29e1426SEnji Cooper 
110*b29e1426SEnji Cooper 	memset(&hints, 0, sizeof(hints));
111*b29e1426SEnji Cooper 	hints.ai_family = domain;
112*b29e1426SEnji Cooper 	hints.ai_flags = AI_ADDRCONFIG|AI_NUMERICSERV;
113*b29e1426SEnji Cooper 	hints.ai_socktype = type;
114*b29e1426SEnji Cooper 
115*b29e1426SEnji Cooper 	error = getaddrinfo("localhost", serv, &hints, res);
116*b29e1426SEnji Cooper 	ATF_REQUIRE_EQ_MSG(error, 0,
117*b29e1426SEnji Cooper 	    "getaddrinfo failed: %s", gai_strerror(errno));
118*b29e1426SEnji Cooper 	free(serv);
119*b29e1426SEnji Cooper }
120*b29e1426SEnji Cooper 
121*b29e1426SEnji Cooper static int
122*b29e1426SEnji Cooper make_socket(int domain, int type, int protocol)
123*b29e1426SEnji Cooper {
124*b29e1426SEnji Cooper 	int sock;
125*b29e1426SEnji Cooper 
126*b29e1426SEnji Cooper 	sock = socket(domain, type, protocol);
127*b29e1426SEnji Cooper 	ATF_REQUIRE_MSG(sock != -1, "socket(%d, %d, 0) failed: %s",
128*b29e1426SEnji Cooper 	    domain, type, strerror(errno));
129*b29e1426SEnji Cooper 
130*b29e1426SEnji Cooper 	return (sock);
131*b29e1426SEnji Cooper }
132*b29e1426SEnji Cooper 
133*b29e1426SEnji Cooper static int
134*b29e1426SEnji Cooper setup_client(int domain, int type, int port)
135*b29e1426SEnji Cooper {
136*b29e1426SEnji Cooper 	struct addrinfo *res;
137*b29e1426SEnji Cooper 	char host[NI_MAXHOST+1];
138*b29e1426SEnji Cooper 	int error, sock;
139*b29e1426SEnji Cooper 
140*b29e1426SEnji Cooper 	resolve_localhost(&res, domain, type, port);
141*b29e1426SEnji Cooper 	error = getnameinfo(
142*b29e1426SEnji Cooper 	    (const struct sockaddr*)res->ai_addr, res->ai_addrlen,
143*b29e1426SEnji Cooper 	    host, nitems(host) - 1, NULL, 0, NI_NUMERICHOST);
144*b29e1426SEnji Cooper 	ATF_REQUIRE_EQ_MSG(error, 0,
145*b29e1426SEnji Cooper 	    "getnameinfo failed: %s", gai_strerror(error));
146*b29e1426SEnji Cooper 	printf(
147*b29e1426SEnji Cooper 	    "Will try to connect to host='%s', address_family=%d, "
148*b29e1426SEnji Cooper 	    "socket_type=%d\n",
149*b29e1426SEnji Cooper 	    host, res->ai_family, res->ai_socktype);
150*b29e1426SEnji Cooper 	sock = make_socket(res->ai_family, res->ai_socktype, res->ai_protocol);
151*b29e1426SEnji Cooper 	error = connect(sock, (struct sockaddr*)res->ai_addr, res->ai_addrlen);
152*b29e1426SEnji Cooper 	freeaddrinfo(res);
153*b29e1426SEnji Cooper 	ATF_REQUIRE_EQ_MSG(error, 0, "connect failed: %s", strerror(errno));
154*b29e1426SEnji Cooper 	return (sock);
155*b29e1426SEnji Cooper }
156*b29e1426SEnji Cooper 
157*b29e1426SEnji Cooper /*
158*b29e1426SEnji Cooper  * XXX: use linear probing to find a free port and eliminate `port` argument as
159*b29e1426SEnji Cooper  * a [const] int (it will need to be a pointer so it can be passed back out of
160*b29e1426SEnji Cooper  * the function and can influence which port `setup_client(..)` connects on.
161*b29e1426SEnji Cooper  */
162*b29e1426SEnji Cooper static int
163*b29e1426SEnji Cooper setup_server(int domain, int type, int port)
164*b29e1426SEnji Cooper {
165*b29e1426SEnji Cooper 	struct addrinfo *res;
166*b29e1426SEnji Cooper 	char host[NI_MAXHOST+1];
167*b29e1426SEnji Cooper 	int error, sock;
168*b29e1426SEnji Cooper 
169*b29e1426SEnji Cooper 	resolve_localhost(&res, domain, type, port);
170*b29e1426SEnji Cooper 	sock = make_socket(res->ai_family, res->ai_socktype, res->ai_protocol);
171*b29e1426SEnji Cooper 
172*b29e1426SEnji Cooper 	error = getnameinfo(
173*b29e1426SEnji Cooper 	    (const struct sockaddr*)res->ai_addr, res->ai_addrlen,
174*b29e1426SEnji Cooper 	    host, nitems(host) - 1, NULL, 0, NI_NUMERICHOST);
175*b29e1426SEnji Cooper 	ATF_REQUIRE_EQ_MSG(error, 0,
176*b29e1426SEnji Cooper 	    "getnameinfo failed: %s", gai_strerror(error));
177*b29e1426SEnji Cooper 	printf(
178*b29e1426SEnji Cooper 	    "Will try to bind socket to host='%s', address_family=%d, "
179*b29e1426SEnji Cooper 	    "socket_type=%d\n",
180*b29e1426SEnji Cooper 	    host, res->ai_family, res->ai_socktype);
181*b29e1426SEnji Cooper 	error = bind(sock, res->ai_addr, res->ai_addrlen);
182*b29e1426SEnji Cooper 	freeaddrinfo(res);
183*b29e1426SEnji Cooper 	ATF_REQUIRE_EQ_MSG(error, 0, "bind failed: %s", strerror(errno));
184*b29e1426SEnji Cooper 	error = listen(sock, 1);
185*b29e1426SEnji Cooper 	ATF_REQUIRE_EQ_MSG(error, 0, "listen failed: %s", strerror(errno));
186*b29e1426SEnji Cooper 
187*b29e1426SEnji Cooper 	return (sock);
188*b29e1426SEnji Cooper }
189*b29e1426SEnji Cooper 
190*b29e1426SEnji Cooper /*
191*b29e1426SEnji Cooper  * This function is a helper routine for taking data being sent by `sendfile` via
192*b29e1426SEnji Cooper  * `server_sock`, and pushing the received stream out to a file, denoted by
193*b29e1426SEnji Cooper  * `dest_filename`.
194*b29e1426SEnji Cooper  */
195*b29e1426SEnji Cooper static void
196*b29e1426SEnji Cooper server_cat(const char *dest_filename, int server_sock, size_t len)
197*b29e1426SEnji Cooper {
198*b29e1426SEnji Cooper 	void *buffer;
199*b29e1426SEnji Cooper 	int recv_sock;
200*b29e1426SEnji Cooper 	ssize_t received_bytes;
201*b29e1426SEnji Cooper 
202*b29e1426SEnji Cooper 	buffer = calloc(len + 1, sizeof(char));
203*b29e1426SEnji Cooper 	if (buffer == NULL)
204*b29e1426SEnji Cooper 		err(1, "malloc failed");
205*b29e1426SEnji Cooper 
206*b29e1426SEnji Cooper 	recv_sock = accept(server_sock, NULL, 0);
207*b29e1426SEnji Cooper 	if (recv_sock == -1)
208*b29e1426SEnji Cooper 		err(1, "accept failed");
209*b29e1426SEnji Cooper 
210*b29e1426SEnji Cooper 	/*
211*b29e1426SEnji Cooper 	 * XXX: this assumes the simplest case where all data is received in a
212*b29e1426SEnji Cooper 	 * single recv(2) call.
213*b29e1426SEnji Cooper 	 */
214*b29e1426SEnji Cooper 	if (recv(recv_sock, buffer, len, 0) == -1)
215*b29e1426SEnji Cooper 		err(1, "recv failed");
216*b29e1426SEnji Cooper 
217*b29e1426SEnji Cooper 	atf_utils_create_file(dest_filename, "%s", buffer);
218*b29e1426SEnji Cooper 
219*b29e1426SEnji Cooper 	/*
220*b29e1426SEnji Cooper 	 * This recv(2) call helps ensure the amount of sent data is exactly
221*b29e1426SEnji Cooper 	 * what was specified by `len`.
222*b29e1426SEnji Cooper 	 */
223*b29e1426SEnji Cooper 	received_bytes = recv(recv_sock, buffer, len, 0);
224*b29e1426SEnji Cooper 	switch (received_bytes) {
225*b29e1426SEnji Cooper 	case -1:
226*b29e1426SEnji Cooper 		err(1, "recv failed");
227*b29e1426SEnji Cooper 	case 0:
228*b29e1426SEnji Cooper 		break;
229*b29e1426SEnji Cooper 	default:
230*b29e1426SEnji Cooper 		errx(1, "received unexpected data: %s", buffer);
231*b29e1426SEnji Cooper 	}
232*b29e1426SEnji Cooper 
233*b29e1426SEnji Cooper 	(void)close(recv_sock);
234*b29e1426SEnji Cooper 	(void)close(server_sock);
235*b29e1426SEnji Cooper 	free(buffer);
236*b29e1426SEnji Cooper }
237*b29e1426SEnji Cooper 
238*b29e1426SEnji Cooper static int
239*b29e1426SEnji Cooper setup_tcp_server(int domain, int port)
240*b29e1426SEnji Cooper {
241*b29e1426SEnji Cooper 
242*b29e1426SEnji Cooper 	return (setup_server(domain, SOCK_STREAM, port));
243*b29e1426SEnji Cooper }
244*b29e1426SEnji Cooper 
245*b29e1426SEnji Cooper static int
246*b29e1426SEnji Cooper setup_tcp_client(int domain, int port)
247*b29e1426SEnji Cooper {
248*b29e1426SEnji Cooper 
249*b29e1426SEnji Cooper 	return (setup_client(domain, SOCK_STREAM, port));
250*b29e1426SEnji Cooper }
251*b29e1426SEnji Cooper 
252*b29e1426SEnji Cooper static off_t
253*b29e1426SEnji Cooper file_size_from_fd(int fd)
254*b29e1426SEnji Cooper {
255*b29e1426SEnji Cooper 	struct stat st;
256*b29e1426SEnji Cooper 
257*b29e1426SEnji Cooper 	ATF_REQUIRE_EQ_MSG(0, fstat(fd, &st),
258*b29e1426SEnji Cooper 	    "fstat failed: %s", strerror(errno));
259*b29e1426SEnji Cooper 
260*b29e1426SEnji Cooper 	return (st.st_size);
261*b29e1426SEnji Cooper }
262*b29e1426SEnji Cooper 
263*b29e1426SEnji Cooper /*
264*b29e1426SEnji Cooper  * NB: `nbytes` == 0 has special connotations given the sendfile(2) API
265*b29e1426SEnji Cooper  * contract. In short, "send the whole file" (paraphrased).
266*b29e1426SEnji Cooper  */
267*b29e1426SEnji Cooper static void
268*b29e1426SEnji Cooper verify_source_and_dest(const char* dest_filename, int src_fd, off_t offset,
269*b29e1426SEnji Cooper     size_t nbytes)
270*b29e1426SEnji Cooper {
271*b29e1426SEnji Cooper 	void *dest_pointer, *src_pointer;
272*b29e1426SEnji Cooper 	off_t dest_file_size, src_file_size;
273*b29e1426SEnji Cooper 	size_t length;
274*b29e1426SEnji Cooper 	int dest_fd;
275*b29e1426SEnji Cooper 
276*b29e1426SEnji Cooper 	atf_utils_cat_file(dest_filename, "dest_file: ");
277*b29e1426SEnji Cooper 
278*b29e1426SEnji Cooper 	dest_fd = open(dest_filename, O_RDONLY);
279*b29e1426SEnji Cooper 	ATF_REQUIRE_MSG(dest_fd != -1, "open failed");
280*b29e1426SEnji Cooper 
281*b29e1426SEnji Cooper 	dest_file_size = file_size_from_fd(dest_fd);
282*b29e1426SEnji Cooper 	src_file_size = file_size_from_fd(src_fd);
283*b29e1426SEnji Cooper 
284*b29e1426SEnji Cooper 	/*
285*b29e1426SEnji Cooper 	 * Per sendfile(2), "send the whole file" (paraphrased). This means
286*b29e1426SEnji Cooper 	 * that we need to grab the file size, as passing in length = 0 with
287*b29e1426SEnji Cooper 	 * mmap(2) will result in a failure with EINVAL (length = 0 is invalid).
288*b29e1426SEnji Cooper 	 */
289*b29e1426SEnji Cooper 	length = (nbytes == 0) ? (size_t)(src_file_size - offset) : nbytes;
290*b29e1426SEnji Cooper 
291*b29e1426SEnji Cooper 	ATF_REQUIRE_EQ_MSG(dest_file_size, length,
292*b29e1426SEnji Cooper 	    "number of bytes written out to %s (%ju) doesn't match the "
293*b29e1426SEnji Cooper 	    "expected number of bytes (%ju)", dest_filename, dest_file_size,
294*b29e1426SEnji Cooper 	    length);
295*b29e1426SEnji Cooper 
296*b29e1426SEnji Cooper 	ATF_REQUIRE_EQ_MSG(0, lseek(src_fd, offset, SEEK_SET),
297*b29e1426SEnji Cooper 	    "lseek failed: %s", strerror(errno));
298*b29e1426SEnji Cooper 
299*b29e1426SEnji Cooper 	dest_pointer = mmap(NULL, length, PROT_READ, MAP_PRIVATE, dest_fd, 0);
300*b29e1426SEnji Cooper 	ATF_REQUIRE_MSG(dest_pointer != MAP_FAILED, "mmap failed: %s",
301*b29e1426SEnji Cooper 	    strerror(errno));
302*b29e1426SEnji Cooper 
303*b29e1426SEnji Cooper 	printf("Will mmap in the source file from offset=%jd to length=%zu\n",
304*b29e1426SEnji Cooper 	    offset, length);
305*b29e1426SEnji Cooper 
306*b29e1426SEnji Cooper 	src_pointer = mmap(NULL, length, PROT_READ, MAP_PRIVATE, src_fd, offset);
307*b29e1426SEnji Cooper 	ATF_REQUIRE_MSG(src_pointer != MAP_FAILED, "mmap failed: %s",
308*b29e1426SEnji Cooper 	    strerror(errno));
309*b29e1426SEnji Cooper 
310*b29e1426SEnji Cooper 	ATF_REQUIRE_EQ_MSG(0, memcmp(src_pointer, dest_pointer, length),
311*b29e1426SEnji Cooper 	    "Contents of source and destination do not match. '%s' != '%s'",
312*b29e1426SEnji Cooper 	    src_pointer, dest_pointer);
313*b29e1426SEnji Cooper 
314*b29e1426SEnji Cooper 	(void)munmap(src_pointer, length);
315*b29e1426SEnji Cooper 	(void)munmap(dest_pointer, length);
316*b29e1426SEnji Cooper 	(void)close(dest_fd);
317*b29e1426SEnji Cooper }
318*b29e1426SEnji Cooper 
319*b29e1426SEnji Cooper static void
320*b29e1426SEnji Cooper fd_positive_file_test(int domain)
321*b29e1426SEnji Cooper {
322*b29e1426SEnji Cooper 	off_t offset;
323*b29e1426SEnji Cooper 	size_t nbytes, pattern_size;
324*b29e1426SEnji Cooper 	int client_sock, error, fd, port, server_sock;
325*b29e1426SEnji Cooper 	pid_t server_pid;
326*b29e1426SEnji Cooper 
327*b29e1426SEnji Cooper 	pattern_size = strlen(DETERMINISTIC_PATTERN);
328*b29e1426SEnji Cooper 
329*b29e1426SEnji Cooper 	atf_utils_create_file(SOURCE_FILE, "%s", DETERMINISTIC_PATTERN);
330*b29e1426SEnji Cooper 	fd = open(SOURCE_FILE, O_RDONLY);
331*b29e1426SEnji Cooper 	ATF_REQUIRE_MSG(fd != -1, "open failed: %s", strerror(errno));
332*b29e1426SEnji Cooper 
333*b29e1426SEnji Cooper 	port = generate_random_port(__LINE__ + domain);
334*b29e1426SEnji Cooper 	server_sock = setup_tcp_server(domain, port);
335*b29e1426SEnji Cooper 	client_sock = setup_tcp_client(domain, port);
336*b29e1426SEnji Cooper 
337*b29e1426SEnji Cooper 	server_pid = atf_utils_fork();
338*b29e1426SEnji Cooper 	if (server_pid == 0) {
339*b29e1426SEnji Cooper 		(void)close(client_sock);
340*b29e1426SEnji Cooper 		server_cat(DESTINATION_FILE, server_sock, pattern_size);
341*b29e1426SEnji Cooper 		_exit(0);
342*b29e1426SEnji Cooper 	} else
343*b29e1426SEnji Cooper 		(void)close(server_sock);
344*b29e1426SEnji Cooper 
345*b29e1426SEnji Cooper 	nbytes = 0;
346*b29e1426SEnji Cooper 	offset = 0;
347*b29e1426SEnji Cooper 	error = sendfile(fd, client_sock, offset, nbytes, NULL, NULL,
348*b29e1426SEnji Cooper 	    SF_FLAGS(0, 0));
349*b29e1426SEnji Cooper 	ATF_REQUIRE_EQ_MSG(0, error, "sendfile failed: %s", strerror(errno));
350*b29e1426SEnji Cooper 	(void)close(client_sock);
351*b29e1426SEnji Cooper 
352*b29e1426SEnji Cooper 	atf_utils_wait(server_pid, 0, "", "");
353*b29e1426SEnji Cooper 	verify_source_and_dest(DESTINATION_FILE, fd, offset, nbytes);
354*b29e1426SEnji Cooper 
355*b29e1426SEnji Cooper 	(void)close(fd);
356*b29e1426SEnji Cooper }
357*b29e1426SEnji Cooper 
358*b29e1426SEnji Cooper ATF_TC(fd_positive_file_v4);
359*b29e1426SEnji Cooper ATF_TC_HEAD(fd_positive_file_v4, tc)
360*b29e1426SEnji Cooper {
361*b29e1426SEnji Cooper 
362*b29e1426SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
363*b29e1426SEnji Cooper 	    "Verify regular file as file descriptor support (IPv4)");
364*b29e1426SEnji Cooper }
365*b29e1426SEnji Cooper ATF_TC_BODY(fd_positive_file_v4, tc)
366*b29e1426SEnji Cooper {
367*b29e1426SEnji Cooper 
368*b29e1426SEnji Cooper 	fd_positive_file_test(AF_INET);
369*b29e1426SEnji Cooper }
370*b29e1426SEnji Cooper 
371*b29e1426SEnji Cooper ATF_TC(fd_positive_file_v6);
372*b29e1426SEnji Cooper ATF_TC_HEAD(fd_positive_file_v6, tc)
373*b29e1426SEnji Cooper {
374*b29e1426SEnji Cooper 
375*b29e1426SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
376*b29e1426SEnji Cooper 	    "Verify regular file as file descriptor support (IPv6)");
377*b29e1426SEnji Cooper }
378*b29e1426SEnji Cooper ATF_TC_BODY(fd_positive_file_v6, tc)
379*b29e1426SEnji Cooper {
380*b29e1426SEnji Cooper 
381*b29e1426SEnji Cooper 	fd_positive_file_test(AF_INET6);
382*b29e1426SEnji Cooper }
383*b29e1426SEnji Cooper 
384*b29e1426SEnji Cooper static void
385*b29e1426SEnji Cooper fd_positive_shm_test(int domain)
386*b29e1426SEnji Cooper {
387*b29e1426SEnji Cooper 	void *shm_pointer;
388*b29e1426SEnji Cooper 	off_t offset;
389*b29e1426SEnji Cooper 	size_t nbytes, pattern_size;
390*b29e1426SEnji Cooper 	pid_t server_pid;
391*b29e1426SEnji Cooper 	int client_sock, error, fd, port, server_sock;
392*b29e1426SEnji Cooper 
393*b29e1426SEnji Cooper 	pattern_size = strlen(DETERMINISTIC_PATTERN);
394*b29e1426SEnji Cooper 
395*b29e1426SEnji Cooper 	printf("pattern size: %zu\n", pattern_size);
396*b29e1426SEnji Cooper 
397*b29e1426SEnji Cooper 	fd = shm_open(SHM_ANON, O_RDWR|O_CREAT, 0600);
398*b29e1426SEnji Cooper 	ATF_REQUIRE_MSG(fd != -1, "shm_open failed: %s", strerror(errno));
399*b29e1426SEnji Cooper 	ATF_REQUIRE_EQ_MSG(0, ftruncate(fd, pattern_size),
400*b29e1426SEnji Cooper 	    "ftruncate failed: %s", strerror(errno));
401*b29e1426SEnji Cooper 	shm_pointer = mmap(NULL, pattern_size, PROT_READ|PROT_WRITE,
402*b29e1426SEnji Cooper 	    MAP_SHARED, fd, 0);
403*b29e1426SEnji Cooper 	ATF_REQUIRE_MSG(shm_pointer != MAP_FAILED,
404*b29e1426SEnji Cooper 	    "mmap failed: %s", strerror(errno));
405*b29e1426SEnji Cooper 	memcpy(shm_pointer, DETERMINISTIC_PATTERN, pattern_size);
406*b29e1426SEnji Cooper 	ATF_REQUIRE_EQ_MSG(0,
407*b29e1426SEnji Cooper 	    memcmp(shm_pointer, DETERMINISTIC_PATTERN, pattern_size),
408*b29e1426SEnji Cooper 	    "memcmp showed data mismatch: '%s' != '%s'",
409*b29e1426SEnji Cooper 	    DETERMINISTIC_PATTERN, shm_pointer);
410*b29e1426SEnji Cooper 
411*b29e1426SEnji Cooper 	port = generate_random_port(__LINE__ + domain);
412*b29e1426SEnji Cooper 	server_sock = setup_tcp_server(domain, port);
413*b29e1426SEnji Cooper 	client_sock = setup_tcp_client(domain, port);
414*b29e1426SEnji Cooper 
415*b29e1426SEnji Cooper 	server_pid = atf_utils_fork();
416*b29e1426SEnji Cooper 	if (server_pid == 0) {
417*b29e1426SEnji Cooper 		(void)close(client_sock);
418*b29e1426SEnji Cooper 		server_cat(DESTINATION_FILE, server_sock, pattern_size);
419*b29e1426SEnji Cooper 		_exit(0);
420*b29e1426SEnji Cooper 	} else
421*b29e1426SEnji Cooper 		(void)close(server_sock);
422*b29e1426SEnji Cooper 
423*b29e1426SEnji Cooper 	nbytes = 0;
424*b29e1426SEnji Cooper 	offset = 0;
425*b29e1426SEnji Cooper 	error = sendfile(fd, client_sock, offset, nbytes, NULL, NULL,
426*b29e1426SEnji Cooper 	    SF_FLAGS(0, 0));
427*b29e1426SEnji Cooper 	ATF_REQUIRE_EQ_MSG(0, error, "sendfile failed: %s", strerror(errno));
428*b29e1426SEnji Cooper 	(void)close(client_sock);
429*b29e1426SEnji Cooper 
430*b29e1426SEnji Cooper 	atf_utils_wait(server_pid, 0, "", "");
431*b29e1426SEnji Cooper 	verify_source_and_dest(DESTINATION_FILE, fd, offset, nbytes);
432*b29e1426SEnji Cooper 
433*b29e1426SEnji Cooper 	(void)munmap(shm_pointer, sizeof(DETERMINISTIC_PATTERN));
434*b29e1426SEnji Cooper 	(void)close(fd);
435*b29e1426SEnji Cooper }
436*b29e1426SEnji Cooper 
437*b29e1426SEnji Cooper ATF_TC(fd_positive_shm_v4);
438*b29e1426SEnji Cooper ATF_TC_HEAD(fd_positive_shm_v4, tc)
439*b29e1426SEnji Cooper {
440*b29e1426SEnji Cooper 
441*b29e1426SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
442*b29e1426SEnji Cooper 	    "Verify shared memory as file descriptor support (IPv4)");
443*b29e1426SEnji Cooper }
444*b29e1426SEnji Cooper ATF_TC_BODY(fd_positive_shm_v4, tc)
445*b29e1426SEnji Cooper {
446*b29e1426SEnji Cooper 
447*b29e1426SEnji Cooper 	fd_positive_shm_test(AF_INET);
448*b29e1426SEnji Cooper }
449*b29e1426SEnji Cooper 
450*b29e1426SEnji Cooper ATF_TC(fd_positive_shm_v6);
451*b29e1426SEnji Cooper ATF_TC_HEAD(fd_positive_shm_v6, tc)
452*b29e1426SEnji Cooper {
453*b29e1426SEnji Cooper 
454*b29e1426SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
455*b29e1426SEnji Cooper 	    "Verify shared memory as file descriptor support (IPv6))");
456*b29e1426SEnji Cooper }
457*b29e1426SEnji Cooper ATF_TC_BODY(fd_positive_shm_v6, tc)
458*b29e1426SEnji Cooper {
459*b29e1426SEnji Cooper 
460*b29e1426SEnji Cooper 	fd_positive_shm_test(AF_INET6);
461*b29e1426SEnji Cooper }
462*b29e1426SEnji Cooper 
463*b29e1426SEnji Cooper static void
464*b29e1426SEnji Cooper fd_negative_bad_fd_test(int domain)
465*b29e1426SEnji Cooper {
466*b29e1426SEnji Cooper 	int client_sock, error, fd, port, server_sock;
467*b29e1426SEnji Cooper 
468*b29e1426SEnji Cooper 	port = generate_random_port(__LINE__ + domain);
469*b29e1426SEnji Cooper 	server_sock = setup_tcp_server(domain, port);
470*b29e1426SEnji Cooper 	client_sock = setup_tcp_client(domain, port);
471*b29e1426SEnji Cooper 
472*b29e1426SEnji Cooper 	fd = -1;
473*b29e1426SEnji Cooper 
474*b29e1426SEnji Cooper 	error = sendfile(fd, client_sock, 0, 0, NULL, NULL, SF_FLAGS(0, 0));
475*b29e1426SEnji Cooper 	ATF_REQUIRE_ERRNO(EBADF, error == -1);
476*b29e1426SEnji Cooper 
477*b29e1426SEnji Cooper 	(void)close(client_sock);
478*b29e1426SEnji Cooper 	(void)close(server_sock);
479*b29e1426SEnji Cooper }
480*b29e1426SEnji Cooper 
481*b29e1426SEnji Cooper ATF_TC(fd_negative_bad_fd_v4);
482*b29e1426SEnji Cooper ATF_TC_HEAD(fd_negative_bad_fd_v4, tc)
483*b29e1426SEnji Cooper {
484*b29e1426SEnji Cooper 
485*b29e1426SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
486*b29e1426SEnji Cooper 	    "Verify bad file descriptor returns EBADF (IPv4)");
487*b29e1426SEnji Cooper }
488*b29e1426SEnji Cooper ATF_TC_BODY(fd_negative_bad_fd_v4, tc)
489*b29e1426SEnji Cooper {
490*b29e1426SEnji Cooper 
491*b29e1426SEnji Cooper 	fd_negative_bad_fd_test(AF_INET);
492*b29e1426SEnji Cooper }
493*b29e1426SEnji Cooper 
494*b29e1426SEnji Cooper ATF_TC(fd_negative_bad_fd_v6);
495*b29e1426SEnji Cooper ATF_TC_HEAD(fd_negative_bad_fd_v6, tc)
496*b29e1426SEnji Cooper {
497*b29e1426SEnji Cooper 
498*b29e1426SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
499*b29e1426SEnji Cooper 	    "Verify bad file descriptor returns EBADF (IPv6)");
500*b29e1426SEnji Cooper }
501*b29e1426SEnji Cooper ATF_TC_BODY(fd_negative_bad_fd_v6, tc)
502*b29e1426SEnji Cooper {
503*b29e1426SEnji Cooper 
504*b29e1426SEnji Cooper 	fd_negative_bad_fd_test(AF_INET6);
505*b29e1426SEnji Cooper }
506*b29e1426SEnji Cooper 
507*b29e1426SEnji Cooper static void
508*b29e1426SEnji Cooper flags_test(int domain)
509*b29e1426SEnji Cooper {
510*b29e1426SEnji Cooper 	off_t offset;
511*b29e1426SEnji Cooper 	size_t nbytes, pattern_size;
512*b29e1426SEnji Cooper 	int client_sock, error, fd, i, port, server_sock;
513*b29e1426SEnji Cooper 	pid_t server_pid;
514*b29e1426SEnji Cooper 	int16_t number_pages = 10;
515*b29e1426SEnji Cooper 
516*b29e1426SEnji Cooper 	pattern_size = strlen(DETERMINISTIC_PATTERN);
517*b29e1426SEnji Cooper 
518*b29e1426SEnji Cooper 	struct testcase {
519*b29e1426SEnji Cooper 		int16_t readahead_pages, flags;
520*b29e1426SEnji Cooper 	} testcases[] = {
521*b29e1426SEnji Cooper 		/* This is covered in `:fd_positive_file` */
522*b29e1426SEnji Cooper #if 0
523*b29e1426SEnji Cooper 		{
524*b29e1426SEnji Cooper 			.readahead_pages = 0,
525*b29e1426SEnji Cooper 			.flags = 0
526*b29e1426SEnji Cooper 		},
527*b29e1426SEnji Cooper #endif
528*b29e1426SEnji Cooper 		{
529*b29e1426SEnji Cooper 			.readahead_pages = 0,
530*b29e1426SEnji Cooper 			.flags = SF_NOCACHE
531*b29e1426SEnji Cooper 		},
532*b29e1426SEnji Cooper #ifdef SF_USER_READAHEAD
533*b29e1426SEnji Cooper 		{
534*b29e1426SEnji Cooper 			.readahead_pages = 0,
535*b29e1426SEnji Cooper 			.flags = SF_NOCACHE|SF_USER_READAHEAD
536*b29e1426SEnji Cooper 		},
537*b29e1426SEnji Cooper 		{
538*b29e1426SEnji Cooper 			.readahead_pages = 0,
539*b29e1426SEnji Cooper 			.flags = SF_USER_READAHEAD
540*b29e1426SEnji Cooper 		},
541*b29e1426SEnji Cooper #endif
542*b29e1426SEnji Cooper 		{
543*b29e1426SEnji Cooper 			.readahead_pages = number_pages,
544*b29e1426SEnji Cooper 			.flags = 0
545*b29e1426SEnji Cooper 		},
546*b29e1426SEnji Cooper 		{
547*b29e1426SEnji Cooper 			.readahead_pages = number_pages,
548*b29e1426SEnji Cooper 			.flags = SF_NOCACHE
549*b29e1426SEnji Cooper 		},
550*b29e1426SEnji Cooper #ifdef SF_USER_READAHEAD
551*b29e1426SEnji Cooper 		{
552*b29e1426SEnji Cooper 			.readahead_pages = number_pages,
553*b29e1426SEnji Cooper 			.flags = SF_NOCACHE|SF_USER_READAHEAD
554*b29e1426SEnji Cooper 		},
555*b29e1426SEnji Cooper #endif
556*b29e1426SEnji Cooper 		{
557*b29e1426SEnji Cooper 			.readahead_pages = number_pages,
558*b29e1426SEnji Cooper 			.flags = SF_NOCACHE
559*b29e1426SEnji Cooper 		},
560*b29e1426SEnji Cooper 		{
561*b29e1426SEnji Cooper 			.readahead_pages = number_pages,
562*b29e1426SEnji Cooper 			.flags = SF_NODISKIO
563*b29e1426SEnji Cooper 		}
564*b29e1426SEnji Cooper 	};
565*b29e1426SEnji Cooper 
566*b29e1426SEnji Cooper 	atf_utils_create_file(SOURCE_FILE, "%s", DETERMINISTIC_PATTERN);
567*b29e1426SEnji Cooper 	for (i = 0; i < nitems(testcases); i++) {
568*b29e1426SEnji Cooper 		fd = open(SOURCE_FILE, O_RDONLY);
569*b29e1426SEnji Cooper 		ATF_REQUIRE_MSG(fd != -1, "open failed: %s", strerror(errno));
570*b29e1426SEnji Cooper 
571*b29e1426SEnji Cooper 		port = generate_random_port(i * __LINE__ + domain);
572*b29e1426SEnji Cooper 		server_sock = setup_tcp_server(domain, port);
573*b29e1426SEnji Cooper 		client_sock = setup_tcp_client(domain, port);
574*b29e1426SEnji Cooper 
575*b29e1426SEnji Cooper 		server_pid = atf_utils_fork();
576*b29e1426SEnji Cooper 		if (server_pid == 0) {
577*b29e1426SEnji Cooper 			(void)close(client_sock);
578*b29e1426SEnji Cooper 			server_cat(DESTINATION_FILE, server_sock, pattern_size);
579*b29e1426SEnji Cooper 			_exit(0);
580*b29e1426SEnji Cooper 		} else
581*b29e1426SEnji Cooper 			(void)close(server_sock);
582*b29e1426SEnji Cooper 
583*b29e1426SEnji Cooper 		nbytes = 0;
584*b29e1426SEnji Cooper 		offset = 0;
585*b29e1426SEnji Cooper 		error = sendfile(fd, client_sock, offset, nbytes, NULL, NULL,
586*b29e1426SEnji Cooper 		    SF_FLAGS(testcases[i].readahead_pages, testcases[i].flags));
587*b29e1426SEnji Cooper 		ATF_CHECK_EQ_MSG(error, 0, "sendfile testcase #%d failed: %s",
588*b29e1426SEnji Cooper 		    i, strerror(errno));
589*b29e1426SEnji Cooper 		(void)close(client_sock);
590*b29e1426SEnji Cooper 
591*b29e1426SEnji Cooper 		atf_utils_wait(server_pid, 0, "", "");
592*b29e1426SEnji Cooper 		verify_source_and_dest(DESTINATION_FILE, fd, offset, nbytes);
593*b29e1426SEnji Cooper 
594*b29e1426SEnji Cooper 		(void)close(fd);
595*b29e1426SEnji Cooper 	}
596*b29e1426SEnji Cooper }
597*b29e1426SEnji Cooper 
598*b29e1426SEnji Cooper ATF_TC(flags_v4);
599*b29e1426SEnji Cooper ATF_TC_HEAD(flags_v4, tc)
600*b29e1426SEnji Cooper {
601*b29e1426SEnji Cooper 
602*b29e1426SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Verify flags functionality (IPv4)");
603*b29e1426SEnji Cooper }
604*b29e1426SEnji Cooper ATF_TC_BODY(flags_v4, tc)
605*b29e1426SEnji Cooper {
606*b29e1426SEnji Cooper 
607*b29e1426SEnji Cooper 	flags_test(AF_INET);
608*b29e1426SEnji Cooper }
609*b29e1426SEnji Cooper 
610*b29e1426SEnji Cooper ATF_TC(flags_v6);
611*b29e1426SEnji Cooper ATF_TC_HEAD(flags_v6, tc)
612*b29e1426SEnji Cooper {
613*b29e1426SEnji Cooper 
614*b29e1426SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Verify flags functionality (IPv6)");
615*b29e1426SEnji Cooper }
616*b29e1426SEnji Cooper ATF_TC_BODY(flags_v6, tc)
617*b29e1426SEnji Cooper {
618*b29e1426SEnji Cooper 
619*b29e1426SEnji Cooper 	flags_test(AF_INET6);
620*b29e1426SEnji Cooper }
621*b29e1426SEnji Cooper 
622*b29e1426SEnji Cooper static void
623*b29e1426SEnji Cooper hdtr_positive_test(int domain)
624*b29e1426SEnji Cooper {
625*b29e1426SEnji Cooper 	struct iovec headers[1], trailers[1];
626*b29e1426SEnji Cooper 	struct testcase {
627*b29e1426SEnji Cooper 		bool include_headers, include_trailers;
628*b29e1426SEnji Cooper 	} testcases[] = {
629*b29e1426SEnji Cooper 		/* This is covered in `:fd_positive_file` */
630*b29e1426SEnji Cooper #if 0
631*b29e1426SEnji Cooper 		{
632*b29e1426SEnji Cooper 			.include_headers = false,
633*b29e1426SEnji Cooper 			.include_trailers = false
634*b29e1426SEnji Cooper 		},
635*b29e1426SEnji Cooper #endif
636*b29e1426SEnji Cooper 		{
637*b29e1426SEnji Cooper 			.include_headers = true,
638*b29e1426SEnji Cooper 			.include_trailers = false
639*b29e1426SEnji Cooper 		},
640*b29e1426SEnji Cooper 		{
641*b29e1426SEnji Cooper 			.include_headers = false,
642*b29e1426SEnji Cooper 			.include_trailers = true
643*b29e1426SEnji Cooper 		},
644*b29e1426SEnji Cooper 		{
645*b29e1426SEnji Cooper 			.include_headers = true,
646*b29e1426SEnji Cooper 			.include_trailers = true
647*b29e1426SEnji Cooper 		}
648*b29e1426SEnji Cooper 	};
649*b29e1426SEnji Cooper 	off_t offset;
650*b29e1426SEnji Cooper 	size_t nbytes;
651*b29e1426SEnji Cooper 	int client_sock, error, fd, fd2, i, port, rc, server_sock;
652*b29e1426SEnji Cooper 	pid_t server_pid;
653*b29e1426SEnji Cooper 
654*b29e1426SEnji Cooper 	headers[0].iov_base = "This is a header";
655*b29e1426SEnji Cooper 	headers[0].iov_len = strlen(headers[0].iov_base);
656*b29e1426SEnji Cooper 	trailers[0].iov_base = "This is a trailer";
657*b29e1426SEnji Cooper 	trailers[0].iov_len = strlen(trailers[0].iov_base);
658*b29e1426SEnji Cooper 	offset = 0;
659*b29e1426SEnji Cooper 	nbytes = 0;
660*b29e1426SEnji Cooper 
661*b29e1426SEnji Cooper 	atf_tc_expect_fail(
662*b29e1426SEnji Cooper 	    "The header/trailer testcases fail today with a data mismatch; "
663*b29e1426SEnji Cooper 	    "bug # 234809");
664*b29e1426SEnji Cooper 
665*b29e1426SEnji Cooper 	for (i = 0; i < nitems(testcases); i++) {
666*b29e1426SEnji Cooper 		struct sf_hdtr hdtr;
667*b29e1426SEnji Cooper 		char *pattern;
668*b29e1426SEnji Cooper 
669*b29e1426SEnji Cooper 		if (testcases[i].include_headers) {
670*b29e1426SEnji Cooper 			hdtr.headers = headers;
671*b29e1426SEnji Cooper 			hdtr.hdr_cnt = nitems(headers);
672*b29e1426SEnji Cooper 		} else {
673*b29e1426SEnji Cooper 			hdtr.headers = NULL;
674*b29e1426SEnji Cooper 			hdtr.hdr_cnt = 0;
675*b29e1426SEnji Cooper 		}
676*b29e1426SEnji Cooper 
677*b29e1426SEnji Cooper 		if (testcases[i].include_trailers) {
678*b29e1426SEnji Cooper 			hdtr.trailers = trailers;
679*b29e1426SEnji Cooper 			hdtr.trl_cnt = nitems(trailers);
680*b29e1426SEnji Cooper 		} else {
681*b29e1426SEnji Cooper 			hdtr.trailers = NULL;
682*b29e1426SEnji Cooper 			hdtr.trl_cnt = 0;
683*b29e1426SEnji Cooper 		}
684*b29e1426SEnji Cooper 
685*b29e1426SEnji Cooper 		port = generate_random_port(i * __LINE__ + domain);
686*b29e1426SEnji Cooper 		server_sock = setup_tcp_server(domain, port);
687*b29e1426SEnji Cooper 		client_sock = setup_tcp_client(domain, port);
688*b29e1426SEnji Cooper 
689*b29e1426SEnji Cooper 		rc = asprintf(&pattern, "%s%s%s",
690*b29e1426SEnji Cooper 		    testcases[i].include_headers ? headers[0].iov_base : "",
691*b29e1426SEnji Cooper 		    DETERMINISTIC_PATTERN,
692*b29e1426SEnji Cooper 		    testcases[i].include_trailers ? trailers[0].iov_base : "");
693*b29e1426SEnji Cooper 		ATF_REQUIRE_MSG(rc != -1, "asprintf failed: %s", strerror(errno));
694*b29e1426SEnji Cooper 
695*b29e1426SEnji Cooper 		atf_utils_create_file(SOURCE_FILE ".full", "%s", pattern);
696*b29e1426SEnji Cooper 		atf_utils_create_file(SOURCE_FILE, "%s", DETERMINISTIC_PATTERN);
697*b29e1426SEnji Cooper 
698*b29e1426SEnji Cooper 		fd = open(SOURCE_FILE, O_RDONLY);
699*b29e1426SEnji Cooper 		ATF_REQUIRE_MSG(fd != -1, "open failed: %s", strerror(errno));
700*b29e1426SEnji Cooper 
701*b29e1426SEnji Cooper 		fd2 = open(SOURCE_FILE ".full", O_RDONLY);
702*b29e1426SEnji Cooper 		ATF_REQUIRE_MSG(fd2 != -1, "open failed: %s", strerror(errno));
703*b29e1426SEnji Cooper 
704*b29e1426SEnji Cooper 		server_pid = atf_utils_fork();
705*b29e1426SEnji Cooper 		if (server_pid == 0) {
706*b29e1426SEnji Cooper 			(void)close(client_sock);
707*b29e1426SEnji Cooper 			server_cat(DESTINATION_FILE, server_sock,
708*b29e1426SEnji Cooper 			    strlen(pattern));
709*b29e1426SEnji Cooper 			_exit(0);
710*b29e1426SEnji Cooper 		} else
711*b29e1426SEnji Cooper 			(void)close(server_sock);
712*b29e1426SEnji Cooper 
713*b29e1426SEnji Cooper 		error = sendfile(fd, client_sock, offset, nbytes, &hdtr,
714*b29e1426SEnji Cooper 		    NULL, SF_FLAGS(0, 0));
715*b29e1426SEnji Cooper 		ATF_CHECK_EQ_MSG(error, 0, "sendfile testcase #%d failed: %s",
716*b29e1426SEnji Cooper 		    i, strerror(errno));
717*b29e1426SEnji Cooper 		(void)close(client_sock);
718*b29e1426SEnji Cooper 
719*b29e1426SEnji Cooper 		atf_utils_wait(server_pid, 0, "", "");
720*b29e1426SEnji Cooper 		verify_source_and_dest(DESTINATION_FILE, fd2, offset, nbytes);
721*b29e1426SEnji Cooper 
722*b29e1426SEnji Cooper 		(void)close(fd);
723*b29e1426SEnji Cooper 		(void)close(fd2);
724*b29e1426SEnji Cooper 		free(pattern);
725*b29e1426SEnji Cooper 		pattern = NULL;
726*b29e1426SEnji Cooper 	}
727*b29e1426SEnji Cooper }
728*b29e1426SEnji Cooper 
729*b29e1426SEnji Cooper ATF_TC(hdtr_positive_v4);
730*b29e1426SEnji Cooper ATF_TC_HEAD(hdtr_positive_v4, tc)
731*b29e1426SEnji Cooper {
732*b29e1426SEnji Cooper 
733*b29e1426SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
734*b29e1426SEnji Cooper 	    "Verify positive hdtr functionality (IPv4)");
735*b29e1426SEnji Cooper }
736*b29e1426SEnji Cooper ATF_TC_BODY(hdtr_positive_v4, tc)
737*b29e1426SEnji Cooper {
738*b29e1426SEnji Cooper 
739*b29e1426SEnji Cooper 	hdtr_positive_test(AF_INET);
740*b29e1426SEnji Cooper }
741*b29e1426SEnji Cooper 
742*b29e1426SEnji Cooper ATF_TC(hdtr_positive_v6);
743*b29e1426SEnji Cooper ATF_TC_HEAD(hdtr_positive_v6, tc)
744*b29e1426SEnji Cooper {
745*b29e1426SEnji Cooper 
746*b29e1426SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
747*b29e1426SEnji Cooper 	    "Verify positive hdtr functionality (IPv6)");
748*b29e1426SEnji Cooper }
749*b29e1426SEnji Cooper ATF_TC_BODY(hdtr_positive_v6, tc)
750*b29e1426SEnji Cooper {
751*b29e1426SEnji Cooper 
752*b29e1426SEnji Cooper 	hdtr_positive_test(AF_INET);
753*b29e1426SEnji Cooper }
754*b29e1426SEnji Cooper 
755*b29e1426SEnji Cooper static void
756*b29e1426SEnji Cooper hdtr_negative_bad_pointers_test(int domain)
757*b29e1426SEnji Cooper {
758*b29e1426SEnji Cooper 	int client_sock, error, fd, port, server_sock;
759*b29e1426SEnji Cooper 	struct sf_hdtr *hdtr1, hdtr2, hdtr3;
760*b29e1426SEnji Cooper 
761*b29e1426SEnji Cooper 	port = generate_random_port(__LINE__ + domain);
762*b29e1426SEnji Cooper 
763*b29e1426SEnji Cooper 	hdtr1 = (struct sf_hdtr*)-1;
764*b29e1426SEnji Cooper 
765*b29e1426SEnji Cooper 	memset(&hdtr2, 0, sizeof(hdtr2));
766*b29e1426SEnji Cooper 	hdtr2.hdr_cnt = 1;
767*b29e1426SEnji Cooper 	hdtr2.headers = (struct iovec*)-1;
768*b29e1426SEnji Cooper 
769*b29e1426SEnji Cooper 	memset(&hdtr3, 0, sizeof(hdtr3));
770*b29e1426SEnji Cooper 	hdtr3.trl_cnt = 1;
771*b29e1426SEnji Cooper 	hdtr3.trailers = (struct iovec*)-1;
772*b29e1426SEnji Cooper 
773*b29e1426SEnji Cooper 	fd = open(SOURCE_FILE, O_CREAT|O_RDWR);
774*b29e1426SEnji Cooper 	ATF_REQUIRE_MSG(fd != -1, "open failed: %s", strerror(errno));
775*b29e1426SEnji Cooper 
776*b29e1426SEnji Cooper 	server_sock = setup_tcp_server(domain, port);
777*b29e1426SEnji Cooper 	client_sock = setup_tcp_client(domain, port);
778*b29e1426SEnji Cooper 
779*b29e1426SEnji Cooper 	error = sendfile(fd, client_sock, 0, 0, hdtr1, NULL, SF_FLAGS(0, 0));
780*b29e1426SEnji Cooper 	ATF_CHECK_ERRNO(EFAULT, error == -1);
781*b29e1426SEnji Cooper 
782*b29e1426SEnji Cooper 	error = sendfile(fd, client_sock, 0, 0, &hdtr2, NULL, SF_FLAGS(0, 0));
783*b29e1426SEnji Cooper 	ATF_CHECK_ERRNO(EFAULT, error == -1);
784*b29e1426SEnji Cooper 
785*b29e1426SEnji Cooper 	error = sendfile(fd, client_sock, 0, 0, &hdtr3, NULL, SF_FLAGS(0, 0));
786*b29e1426SEnji Cooper 	ATF_CHECK_ERRNO(EFAULT, error == -1);
787*b29e1426SEnji Cooper 
788*b29e1426SEnji Cooper 	(void)close(fd);
789*b29e1426SEnji Cooper 	(void)close(client_sock);
790*b29e1426SEnji Cooper 	(void)close(server_sock);
791*b29e1426SEnji Cooper }
792*b29e1426SEnji Cooper 
793*b29e1426SEnji Cooper ATF_TC(hdtr_negative_bad_pointers_v4);
794*b29e1426SEnji Cooper ATF_TC_HEAD(hdtr_negative_bad_pointers_v4, tc)
795*b29e1426SEnji Cooper {
796*b29e1426SEnji Cooper 
797*b29e1426SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
798*b29e1426SEnji Cooper 	    "Verify that bad pointers for hdtr storage result in EFAULT (IPv4)");
799*b29e1426SEnji Cooper }
800*b29e1426SEnji Cooper ATF_TC_BODY(hdtr_negative_bad_pointers_v4, tc)
801*b29e1426SEnji Cooper {
802*b29e1426SEnji Cooper 
803*b29e1426SEnji Cooper 	hdtr_negative_bad_pointers_test(AF_INET);
804*b29e1426SEnji Cooper }
805*b29e1426SEnji Cooper 
806*b29e1426SEnji Cooper ATF_TC(hdtr_negative_bad_pointers_v6);
807*b29e1426SEnji Cooper ATF_TC_HEAD(hdtr_negative_bad_pointers_v6, tc)
808*b29e1426SEnji Cooper {
809*b29e1426SEnji Cooper 
810*b29e1426SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
811*b29e1426SEnji Cooper 	    "Verify that bad pointers for hdtr storage result in EFAULT (IPv6)");
812*b29e1426SEnji Cooper }
813*b29e1426SEnji Cooper ATF_TC_BODY(hdtr_negative_bad_pointers_v6, tc)
814*b29e1426SEnji Cooper {
815*b29e1426SEnji Cooper 
816*b29e1426SEnji Cooper 	hdtr_negative_bad_pointers_test(AF_INET6);
817*b29e1426SEnji Cooper }
818*b29e1426SEnji Cooper 
819*b29e1426SEnji Cooper static void
820*b29e1426SEnji Cooper offset_negative_value_less_than_zero_test(int domain)
821*b29e1426SEnji Cooper {
822*b29e1426SEnji Cooper 	int client_sock, error, fd, port, server_sock;
823*b29e1426SEnji Cooper 
824*b29e1426SEnji Cooper 	port = generate_random_port(__LINE__ + domain);
825*b29e1426SEnji Cooper 	server_sock = setup_tcp_server(domain, port);
826*b29e1426SEnji Cooper 	client_sock = setup_tcp_client(domain, port);
827*b29e1426SEnji Cooper 
828*b29e1426SEnji Cooper 	fd = open(SOURCE_FILE, O_CREAT|O_RDWR);
829*b29e1426SEnji Cooper 	ATF_REQUIRE_MSG(fd != -1, "open failed: %s", strerror(errno));
830*b29e1426SEnji Cooper 
831*b29e1426SEnji Cooper 	error = sendfile(fd, client_sock, -1, 0, NULL, NULL, SF_FLAGS(0, 0));
832*b29e1426SEnji Cooper 	ATF_REQUIRE_ERRNO(EINVAL, error == -1);
833*b29e1426SEnji Cooper 
834*b29e1426SEnji Cooper 	(void)close(fd);
835*b29e1426SEnji Cooper 	(void)close(client_sock);
836*b29e1426SEnji Cooper 	(void)close(server_sock);
837*b29e1426SEnji Cooper }
838*b29e1426SEnji Cooper 
839*b29e1426SEnji Cooper ATF_TC(offset_negative_value_less_than_zero_v4);
840*b29e1426SEnji Cooper ATF_TC_HEAD(offset_negative_value_less_than_zero_v4, tc)
841*b29e1426SEnji Cooper {
842*b29e1426SEnji Cooper 
843*b29e1426SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
844*b29e1426SEnji Cooper 	    "Verify that a negative offset results in EINVAL (IPv4)");
845*b29e1426SEnji Cooper }
846*b29e1426SEnji Cooper ATF_TC_BODY(offset_negative_value_less_than_zero_v4, tc)
847*b29e1426SEnji Cooper {
848*b29e1426SEnji Cooper 
849*b29e1426SEnji Cooper 	offset_negative_value_less_than_zero_test(AF_INET);
850*b29e1426SEnji Cooper }
851*b29e1426SEnji Cooper 
852*b29e1426SEnji Cooper ATF_TC(offset_negative_value_less_than_zero_v6);
853*b29e1426SEnji Cooper ATF_TC_HEAD(offset_negative_value_less_than_zero_v6, tc)
854*b29e1426SEnji Cooper {
855*b29e1426SEnji Cooper 
856*b29e1426SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
857*b29e1426SEnji Cooper 	    "Verify that a negative offset results in EINVAL (IPv6)");
858*b29e1426SEnji Cooper }
859*b29e1426SEnji Cooper ATF_TC_BODY(offset_negative_value_less_than_zero_v6, tc)
860*b29e1426SEnji Cooper {
861*b29e1426SEnji Cooper 
862*b29e1426SEnji Cooper 	offset_negative_value_less_than_zero_test(AF_INET6);
863*b29e1426SEnji Cooper }
864*b29e1426SEnji Cooper 
865*b29e1426SEnji Cooper static void
866*b29e1426SEnji Cooper sbytes_positive_test(int domain)
867*b29e1426SEnji Cooper {
868*b29e1426SEnji Cooper 	size_t pattern_size = strlen(DETERMINISTIC_PATTERN);
869*b29e1426SEnji Cooper 	off_t sbytes;
870*b29e1426SEnji Cooper 	int client_sock, error, fd, port, server_sock;
871*b29e1426SEnji Cooper 
872*b29e1426SEnji Cooper 	port = generate_random_port(__LINE__ + domain);
873*b29e1426SEnji Cooper 	server_sock = setup_tcp_server(domain, port);
874*b29e1426SEnji Cooper 	client_sock = setup_tcp_client(domain, port);
875*b29e1426SEnji Cooper 
876*b29e1426SEnji Cooper 	atf_utils_create_file(SOURCE_FILE, "%s", DETERMINISTIC_PATTERN);
877*b29e1426SEnji Cooper 	fd = open(SOURCE_FILE, O_RDONLY);
878*b29e1426SEnji Cooper 	ATF_REQUIRE_MSG(fd != -1, "open failed: %s", strerror(errno));
879*b29e1426SEnji Cooper 
880*b29e1426SEnji Cooper 	error = sendfile(fd, client_sock, 0, 0, NULL, &sbytes, SF_FLAGS(0, 0));
881*b29e1426SEnji Cooper 	ATF_CHECK_EQ_MSG(error, 0, "sendfile failed: %s", strerror(errno));
882*b29e1426SEnji Cooper 
883*b29e1426SEnji Cooper 	(void)close(fd);
884*b29e1426SEnji Cooper 	(void)close(client_sock);
885*b29e1426SEnji Cooper 	(void)close(server_sock);
886*b29e1426SEnji Cooper 
887*b29e1426SEnji Cooper 	ATF_CHECK_EQ_MSG(pattern_size, sbytes,
888*b29e1426SEnji Cooper 	    "the value returned by sbytes does not match the expected pattern "
889*b29e1426SEnji Cooper 	    "size");
890*b29e1426SEnji Cooper }
891*b29e1426SEnji Cooper 
892*b29e1426SEnji Cooper ATF_TC(sbytes_positive_v4);
893*b29e1426SEnji Cooper ATF_TC_HEAD(sbytes_positive_v4, tc)
894*b29e1426SEnji Cooper {
895*b29e1426SEnji Cooper 
896*b29e1426SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
897*b29e1426SEnji Cooper 	    "Verify positive `sbytes` functionality (IPv4)");
898*b29e1426SEnji Cooper }
899*b29e1426SEnji Cooper ATF_TC_BODY(sbytes_positive_v4, tc)
900*b29e1426SEnji Cooper {
901*b29e1426SEnji Cooper 
902*b29e1426SEnji Cooper 	sbytes_positive_test(AF_INET);
903*b29e1426SEnji Cooper }
904*b29e1426SEnji Cooper 
905*b29e1426SEnji Cooper ATF_TC(sbytes_positive_v6);
906*b29e1426SEnji Cooper ATF_TC_HEAD(sbytes_positive_v6, tc)
907*b29e1426SEnji Cooper {
908*b29e1426SEnji Cooper 
909*b29e1426SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
910*b29e1426SEnji Cooper 	    "Verify positive `sbytes` functionality (IPv6)");
911*b29e1426SEnji Cooper }
912*b29e1426SEnji Cooper ATF_TC_BODY(sbytes_positive_v6, tc)
913*b29e1426SEnji Cooper {
914*b29e1426SEnji Cooper 
915*b29e1426SEnji Cooper 	sbytes_positive_test(AF_INET6);
916*b29e1426SEnji Cooper }
917*b29e1426SEnji Cooper 
918*b29e1426SEnji Cooper static void
919*b29e1426SEnji Cooper sbytes_negative_test(int domain)
920*b29e1426SEnji Cooper {
921*b29e1426SEnji Cooper 	off_t *sbytes_p = (off_t*)-1;
922*b29e1426SEnji Cooper 	int client_sock, error, fd, port, server_sock;
923*b29e1426SEnji Cooper 
924*b29e1426SEnji Cooper 	port = generate_random_port(__LINE__ + domain);
925*b29e1426SEnji Cooper 	server_sock = setup_tcp_server(domain, port);
926*b29e1426SEnji Cooper 	client_sock = setup_tcp_client(domain, port);
927*b29e1426SEnji Cooper 
928*b29e1426SEnji Cooper 	atf_utils_create_file(SOURCE_FILE, "%s", DETERMINISTIC_PATTERN);
929*b29e1426SEnji Cooper 	fd = open(SOURCE_FILE, O_RDONLY);
930*b29e1426SEnji Cooper 	ATF_REQUIRE_MSG(fd != -1, "open failed: %s", strerror(errno));
931*b29e1426SEnji Cooper 
932*b29e1426SEnji Cooper 	atf_tc_expect_fail(
933*b29e1426SEnji Cooper 	    "bug 232210: EFAULT assert fails because copyout(9) call is not checked");
934*b29e1426SEnji Cooper 
935*b29e1426SEnji Cooper 	error = sendfile(fd, client_sock, 0, 0, NULL, sbytes_p, SF_FLAGS(0, 0));
936*b29e1426SEnji Cooper 	ATF_REQUIRE_ERRNO(EFAULT, error == -1);
937*b29e1426SEnji Cooper 
938*b29e1426SEnji Cooper 	(void)close(fd);
939*b29e1426SEnji Cooper 	(void)close(client_sock);
940*b29e1426SEnji Cooper 	(void)close(server_sock);
941*b29e1426SEnji Cooper }
942*b29e1426SEnji Cooper 
943*b29e1426SEnji Cooper ATF_TC(sbytes_negative_v4);
944*b29e1426SEnji Cooper ATF_TC_HEAD(sbytes_negative_v4, tc)
945*b29e1426SEnji Cooper {
946*b29e1426SEnji Cooper 
947*b29e1426SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
948*b29e1426SEnji Cooper 	    "Verify negative `sbytes` functionality (IPv4)");
949*b29e1426SEnji Cooper }
950*b29e1426SEnji Cooper ATF_TC_BODY(sbytes_negative_v4, tc)
951*b29e1426SEnji Cooper {
952*b29e1426SEnji Cooper 
953*b29e1426SEnji Cooper 	sbytes_negative_test(AF_INET);
954*b29e1426SEnji Cooper }
955*b29e1426SEnji Cooper 
956*b29e1426SEnji Cooper ATF_TC(sbytes_negative_v6);
957*b29e1426SEnji Cooper ATF_TC_HEAD(sbytes_negative_v6, tc)
958*b29e1426SEnji Cooper {
959*b29e1426SEnji Cooper 
960*b29e1426SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
961*b29e1426SEnji Cooper 	    "Verify negative `sbytes` functionality (IPv6)");
962*b29e1426SEnji Cooper }
963*b29e1426SEnji Cooper ATF_TC_BODY(sbytes_negative_v6, tc)
964*b29e1426SEnji Cooper {
965*b29e1426SEnji Cooper 
966*b29e1426SEnji Cooper 	sbytes_negative_test(AF_INET6);
967*b29e1426SEnji Cooper }
968*b29e1426SEnji Cooper 
969*b29e1426SEnji Cooper static void
970*b29e1426SEnji Cooper s_negative_not_connected_socket_test(int domain)
971*b29e1426SEnji Cooper {
972*b29e1426SEnji Cooper 	int client_sock, error, fd, port;
973*b29e1426SEnji Cooper 
974*b29e1426SEnji Cooper 	port = generate_random_port(__LINE__ + domain);
975*b29e1426SEnji Cooper 	client_sock = setup_tcp_server(domain, port);
976*b29e1426SEnji Cooper 
977*b29e1426SEnji Cooper 	fd = open(SOURCE_FILE, O_CREAT|O_RDWR);
978*b29e1426SEnji Cooper 	ATF_REQUIRE_MSG(fd != -1, "open failed: %s", strerror(errno));
979*b29e1426SEnji Cooper 
980*b29e1426SEnji Cooper 	error = sendfile(fd, client_sock, 0, 0, NULL, NULL, SF_FLAGS(0, 0));
981*b29e1426SEnji Cooper 	ATF_REQUIRE_ERRNO(ENOTCONN, error == -1);
982*b29e1426SEnji Cooper 
983*b29e1426SEnji Cooper 	(void)close(fd);
984*b29e1426SEnji Cooper 	(void)close(client_sock);
985*b29e1426SEnji Cooper }
986*b29e1426SEnji Cooper 
987*b29e1426SEnji Cooper ATF_TC(s_negative_not_connected_socket_v4);
988*b29e1426SEnji Cooper ATF_TC_HEAD(s_negative_not_connected_socket_v4, tc)
989*b29e1426SEnji Cooper {
990*b29e1426SEnji Cooper 
991*b29e1426SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
992*b29e1426SEnji Cooper 	    "Verify that a non-connected SOCK_STREAM socket results in ENOTCONN (IPv4)");
993*b29e1426SEnji Cooper }
994*b29e1426SEnji Cooper 
995*b29e1426SEnji Cooper ATF_TC_BODY(s_negative_not_connected_socket_v4, tc)
996*b29e1426SEnji Cooper {
997*b29e1426SEnji Cooper 
998*b29e1426SEnji Cooper 	s_negative_not_connected_socket_test(AF_INET);
999*b29e1426SEnji Cooper }
1000*b29e1426SEnji Cooper 
1001*b29e1426SEnji Cooper ATF_TC(s_negative_not_connected_socket_v6);
1002*b29e1426SEnji Cooper ATF_TC_HEAD(s_negative_not_connected_socket_v6, tc)
1003*b29e1426SEnji Cooper {
1004*b29e1426SEnji Cooper 
1005*b29e1426SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
1006*b29e1426SEnji Cooper 	    "Verify that a non-connected SOCK_STREAM socket results in ENOTCONN (IPv6)");
1007*b29e1426SEnji Cooper }
1008*b29e1426SEnji Cooper 
1009*b29e1426SEnji Cooper ATF_TC_BODY(s_negative_not_connected_socket_v6, tc)
1010*b29e1426SEnji Cooper {
1011*b29e1426SEnji Cooper 
1012*b29e1426SEnji Cooper 	s_negative_not_connected_socket_test(AF_INET6);
1013*b29e1426SEnji Cooper }
1014*b29e1426SEnji Cooper 
1015*b29e1426SEnji Cooper ATF_TC(s_negative_not_descriptor);
1016*b29e1426SEnji Cooper ATF_TC_HEAD(s_negative_not_descriptor, tc)
1017*b29e1426SEnji Cooper {
1018*b29e1426SEnji Cooper 
1019*b29e1426SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
1020*b29e1426SEnji Cooper 	    "Verify that an invalid file descriptor, e.g., -1, fails with EBADF");
1021*b29e1426SEnji Cooper }
1022*b29e1426SEnji Cooper 
1023*b29e1426SEnji Cooper ATF_TC_BODY(s_negative_not_descriptor, tc)
1024*b29e1426SEnji Cooper {
1025*b29e1426SEnji Cooper 	int client_sock, error, fd;
1026*b29e1426SEnji Cooper 
1027*b29e1426SEnji Cooper 	client_sock = -1;
1028*b29e1426SEnji Cooper 
1029*b29e1426SEnji Cooper 	fd = open(SOURCE_FILE, O_CREAT|O_RDWR);
1030*b29e1426SEnji Cooper 	ATF_REQUIRE_MSG(fd != -1, "open failed: %s", strerror(errno));
1031*b29e1426SEnji Cooper 
1032*b29e1426SEnji Cooper 	error = sendfile(fd, client_sock, 0, 0, NULL, NULL, SF_FLAGS(0, 0));
1033*b29e1426SEnji Cooper 	ATF_REQUIRE_ERRNO(EBADF, error == -1);
1034*b29e1426SEnji Cooper 
1035*b29e1426SEnji Cooper 	(void)close(fd);
1036*b29e1426SEnji Cooper }
1037*b29e1426SEnji Cooper 
1038*b29e1426SEnji Cooper ATF_TC(s_negative_not_socket_file_descriptor);
1039*b29e1426SEnji Cooper ATF_TC_HEAD(s_negative_not_socket_file_descriptor, tc)
1040*b29e1426SEnji Cooper {
1041*b29e1426SEnji Cooper 
1042*b29e1426SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
1043*b29e1426SEnji Cooper 	    "Verify that a non-socket file descriptor fails with ENOTSOCK");
1044*b29e1426SEnji Cooper }
1045*b29e1426SEnji Cooper 
1046*b29e1426SEnji Cooper ATF_TC_BODY(s_negative_not_socket_file_descriptor, tc)
1047*b29e1426SEnji Cooper {
1048*b29e1426SEnji Cooper 	int client_sock, error, fd;
1049*b29e1426SEnji Cooper 
1050*b29e1426SEnji Cooper 	fd = open(SOURCE_FILE, O_CREAT|O_RDWR);
1051*b29e1426SEnji Cooper 	ATF_REQUIRE_MSG(fd != -1, "open failed: %s", strerror(errno));
1052*b29e1426SEnji Cooper 
1053*b29e1426SEnji Cooper 	client_sock = open(_PATH_DEVNULL, O_WRONLY);
1054*b29e1426SEnji Cooper 	ATF_REQUIRE_MSG(fd != -1, "open failed: %s", strerror(errno));
1055*b29e1426SEnji Cooper 
1056*b29e1426SEnji Cooper 	error = sendfile(fd, client_sock, 0, 0, NULL, NULL, SF_FLAGS(0, 0));
1057*b29e1426SEnji Cooper 	ATF_REQUIRE_ERRNO(ENOTSOCK, error == -1);
1058*b29e1426SEnji Cooper 
1059*b29e1426SEnji Cooper 	(void)close(fd);
1060*b29e1426SEnji Cooper 	(void)close(client_sock);
1061*b29e1426SEnji Cooper }
1062*b29e1426SEnji Cooper 
1063*b29e1426SEnji Cooper static void
1064*b29e1426SEnji Cooper s_negative_udp_socket_test(int domain)
1065*b29e1426SEnji Cooper {
1066*b29e1426SEnji Cooper 	int client_sock, error, fd, port;
1067*b29e1426SEnji Cooper 
1068*b29e1426SEnji Cooper 	port = generate_random_port(__LINE__ + domain);
1069*b29e1426SEnji Cooper 	client_sock = setup_client(domain, SOCK_DGRAM, port);
1070*b29e1426SEnji Cooper 
1071*b29e1426SEnji Cooper 	fd = open(SOURCE_FILE, O_CREAT|O_RDWR);
1072*b29e1426SEnji Cooper 	ATF_REQUIRE_MSG(fd != -1, "open failed: %s", strerror(errno));
1073*b29e1426SEnji Cooper 
1074*b29e1426SEnji Cooper 	error = sendfile(fd, client_sock, 0, 0, NULL, NULL, SF_FLAGS(0, 0));
1075*b29e1426SEnji Cooper 	ATF_REQUIRE_ERRNO(EINVAL, error == -1);
1076*b29e1426SEnji Cooper 
1077*b29e1426SEnji Cooper 	(void)close(fd);
1078*b29e1426SEnji Cooper 	(void)close(client_sock);
1079*b29e1426SEnji Cooper }
1080*b29e1426SEnji Cooper 
1081*b29e1426SEnji Cooper ATF_TC(s_negative_udp_socket_v4);
1082*b29e1426SEnji Cooper ATF_TC_HEAD(s_negative_udp_socket_v4, tc)
1083*b29e1426SEnji Cooper {
1084*b29e1426SEnji Cooper 
1085*b29e1426SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
1086*b29e1426SEnji Cooper 	    "Verify that a non-SOCK_STREAM type socket results in EINVAL (IPv4)");
1087*b29e1426SEnji Cooper }
1088*b29e1426SEnji Cooper ATF_TC_BODY(s_negative_udp_socket_v4, tc)
1089*b29e1426SEnji Cooper {
1090*b29e1426SEnji Cooper 
1091*b29e1426SEnji Cooper 	s_negative_udp_socket_test(AF_INET);
1092*b29e1426SEnji Cooper }
1093*b29e1426SEnji Cooper 
1094*b29e1426SEnji Cooper ATF_TC(s_negative_udp_socket_v6);
1095*b29e1426SEnji Cooper ATF_TC_HEAD(s_negative_udp_socket_v6, tc)
1096*b29e1426SEnji Cooper {
1097*b29e1426SEnji Cooper 
1098*b29e1426SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
1099*b29e1426SEnji Cooper 	    "Verify that a non-SOCK_STREAM type socket results in EINVAL (IPv6)");
1100*b29e1426SEnji Cooper }
1101*b29e1426SEnji Cooper ATF_TC_BODY(s_negative_udp_socket_v6, tc)
1102*b29e1426SEnji Cooper {
1103*b29e1426SEnji Cooper 
1104*b29e1426SEnji Cooper 	s_negative_udp_socket_test(AF_INET6);
1105*b29e1426SEnji Cooper }
1106*b29e1426SEnji Cooper 
1107*b29e1426SEnji Cooper ATF_TP_ADD_TCS(tp)
1108*b29e1426SEnji Cooper {
1109*b29e1426SEnji Cooper 
1110*b29e1426SEnji Cooper 	ATF_TP_ADD_TC(tp, fd_positive_file_v4);
1111*b29e1426SEnji Cooper 	ATF_TP_ADD_TC(tp, fd_positive_file_v6);
1112*b29e1426SEnji Cooper 	ATF_TP_ADD_TC(tp, fd_positive_shm_v4);
1113*b29e1426SEnji Cooper 	ATF_TP_ADD_TC(tp, fd_positive_shm_v6);
1114*b29e1426SEnji Cooper 	ATF_TP_ADD_TC(tp, fd_negative_bad_fd_v4);
1115*b29e1426SEnji Cooper 	ATF_TP_ADD_TC(tp, fd_negative_bad_fd_v6);
1116*b29e1426SEnji Cooper 	ATF_TP_ADD_TC(tp, flags_v4);
1117*b29e1426SEnji Cooper 	ATF_TP_ADD_TC(tp, flags_v6);
1118*b29e1426SEnji Cooper 	/*
1119*b29e1426SEnji Cooper 	 * TODO: the negative case for SF_NODISKIO (returns EBUSY if file in
1120*b29e1426SEnji Cooper 	 * use) is not covered yet.
1121*b29e1426SEnji Cooper 	 *
1122*b29e1426SEnji Cooper 	 * Need to lock a file in a subprocess in write mode, then try and
1123*b29e1426SEnji Cooper 	 * send the data in read mode with sendfile.
1124*b29e1426SEnji Cooper 	 *
1125*b29e1426SEnji Cooper 	 * This should work with FFS/UFS, but there are no guarantees about
1126*b29e1426SEnji Cooper 	 * other filesystem implementations of sendfile(2), e.g., ZFS.
1127*b29e1426SEnji Cooper 	 */
1128*b29e1426SEnji Cooper 	ATF_TP_ADD_TC(tp, hdtr_positive_v4);
1129*b29e1426SEnji Cooper 	ATF_TP_ADD_TC(tp, hdtr_positive_v6);
1130*b29e1426SEnji Cooper 	ATF_TP_ADD_TC(tp, hdtr_negative_bad_pointers_v4);
1131*b29e1426SEnji Cooper 	ATF_TP_ADD_TC(tp, hdtr_negative_bad_pointers_v6);
1132*b29e1426SEnji Cooper 	ATF_TP_ADD_TC(tp, offset_negative_value_less_than_zero_v4);
1133*b29e1426SEnji Cooper 	ATF_TP_ADD_TC(tp, offset_negative_value_less_than_zero_v6);
1134*b29e1426SEnji Cooper 	ATF_TP_ADD_TC(tp, sbytes_positive_v4);
1135*b29e1426SEnji Cooper 	ATF_TP_ADD_TC(tp, sbytes_positive_v6);
1136*b29e1426SEnji Cooper 	ATF_TP_ADD_TC(tp, sbytes_negative_v4);
1137*b29e1426SEnji Cooper 	ATF_TP_ADD_TC(tp, sbytes_negative_v6);
1138*b29e1426SEnji Cooper 	ATF_TP_ADD_TC(tp, s_negative_not_connected_socket_v4);
1139*b29e1426SEnji Cooper 	ATF_TP_ADD_TC(tp, s_negative_not_connected_socket_v6);
1140*b29e1426SEnji Cooper 	ATF_TP_ADD_TC(tp, s_negative_not_descriptor);
1141*b29e1426SEnji Cooper 	ATF_TP_ADD_TC(tp, s_negative_not_socket_file_descriptor);
1142*b29e1426SEnji Cooper 	ATF_TP_ADD_TC(tp, s_negative_udp_socket_v4);
1143*b29e1426SEnji Cooper 	ATF_TP_ADD_TC(tp, s_negative_udp_socket_v6);
1144*b29e1426SEnji Cooper 
1145*b29e1426SEnji Cooper 	return (atf_no_error());
1146*b29e1426SEnji Cooper }
1147