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