xref: /freebsd/libexec/tftpd/tests/functional.c (revision c57c26179033f64c2011a2d2a904ee3fa62e826a)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2018 Alan Somers.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27 
28 #include <sys/param.h>
29 #include <sys/socket.h>
30 #include <sys/stat.h>
31 #include <sys/time.h>
32 #include <sys/wait.h>
33 
34 #include <netinet/in.h>
35 
36 #include <errno.h>
37 #include <fcntl.h>
38 #include <signal.h>
39 #include <stdalign.h>
40 #include <stdio.h>
41 #include <unistd.h>
42 
43 #include <atf-c.h>
44 #include <libutil.h>
45 
46 static const uint16_t BASEPORT = 6969;
47 static const char pidfile[] = "tftpd.pid";
48 static int protocol = PF_UNSPEC;
49 static int s = -1;	/* tftp client socket */
50 static struct sockaddr_storage addr; /* Destination address for the client */
51 static bool s_flag = false;	/* Pass -s to tftpd */
52 static bool w_flag = false;	/* Pass -w to tftpd */
53 
54 /* Helper functions*/
55 static void require_bufeq(const char *expected, size_t expected_len,
56     const char *actual, size_t len);
57 
58 /*
59  * Receive a response from tftpd
60  * @param	hdr		The reply's expected header, as a char array
61  * @param	contents	The reply's expected contents, as a char array
62  * @param	contents_len	Length of contents
63  */
64 #define RECV(hdr, contents, contents_len) do {				\
65 	char buffer[1024];						\
66 	struct sockaddr_storage from;					\
67 	socklen_t fromlen = sizeof(from);				\
68 	ssize_t r = recvfrom(s, buffer, sizeof(buffer), 0,		\
69 	    (struct sockaddr *)&from, &fromlen);			\
70 	ATF_REQUIRE(r > 0);						\
71 	require_bufeq((hdr), sizeof(hdr), buffer,			\
72 	    MIN((size_t)r, sizeof(hdr)));				\
73 	require_bufeq((const char *) (contents), (contents_len),	\
74 	    &buffer[sizeof(hdr)], r - sizeof(hdr));			\
75 	if (protocol == PF_INET) {					\
76 		((struct sockaddr_in *)&addr)->sin_port =		\
77 		    ((struct sockaddr_in *)&from)->sin_port;		\
78 	} else {							\
79 		((struct sockaddr_in6 *)&addr)->sin6_port =		\
80 		    ((struct sockaddr_in6 *)&from)->sin6_port;		\
81 	}								\
82 } while(0)
83 
84 static void
85 recv_ack(uint16_t blocknum)
86 {
87 	char hdr[] = {0, 4, blocknum >> 8, blocknum & 0xFF};
88 	RECV(hdr, NULL, 0);
89 }
90 
91 static void
92 recv_oack(const char *options, size_t options_len)
93 {
94 	char hdr[] = {0, 6};
95 	RECV(hdr, options, options_len);
96 }
97 
98 /*
99  * Receive a data packet from tftpd
100  * @param	blocknum	Expected block number to be received
101  * @param	contents	Pointer to expected contents
102  * @param	contents_len	Length of contents expected to receive
103  */
104 static void
105 recv_data(uint16_t blocknum, const char *contents, size_t contents_len)
106 {
107 	char hdr[] = {0, 3, blocknum >> 8, blocknum & 0xFF};
108 	RECV(hdr, contents, contents_len);
109 }
110 
111 #define RECV_ERROR(code, msg) do {					\
112 	char hdr[] = {0, 5, code >> 8, code & 0xFF};			\
113 	RECV(hdr, msg, sizeof(msg));					\
114 } while (0)
115 
116 /*
117  * send a command to tftpd.
118  * @param	cmd		Command to send, as a char array
119  */
120 static void
121 send_bytes(const void *cmd, size_t len)
122 {
123 	ssize_t r;
124 
125 	r = sendto(s, cmd, len, 0, (struct sockaddr *)(&addr), addr.ss_len);
126 	ATF_REQUIRE(r >= 0);
127 	ATF_REQUIRE_EQ(len, (size_t)r);
128 }
129 
130 static void
131 send_data(uint16_t blocknum, const char *contents, size_t contents_len)
132 {
133 	char buffer[1024];
134 
135 	buffer[0] = 0;	/* DATA opcode high byte */
136 	buffer[1] = 3;	/* DATA opcode low byte */
137 	buffer[2] = blocknum >> 8;
138 	buffer[3] = blocknum & 0xFF;
139 	memmove(&buffer[4], contents, contents_len);
140 	send_bytes(buffer, 4 + contents_len);
141 }
142 
143 /*
144  * send a command to tftpd.
145  * @param	cmd		Command to send, as a const string
146  *				(terminating NUL will be ignored)
147  */
148 #define SEND_STR(cmd)							\
149 	ATF_REQUIRE_EQ(sizeof(cmd) - 1,					\
150 	    sendto(s, (cmd), sizeof(cmd) - 1, 0,			\
151 	    (struct sockaddr *)(&addr), addr.ss_len))
152 
153 /*
154  * Acknowledge block blocknum
155  */
156 static void
157 send_ack(uint16_t blocknum)
158 {
159 	char packet[] = {
160 		0, 4,		/* ACK opcode in BE */
161 		blocknum >> 8,
162 		blocknum & 0xFF
163 	};
164 
165 	send_bytes(packet, sizeof(packet));
166 }
167 
168 /*
169  * build an option string
170  */
171 #define OPTION_STR(name, value)	name "\000" value "\000"
172 
173 /*
174  * send a read request to tftpd.
175  * @param	filename	filename as a string, absolute or relative
176  * @param	mode		either "octet" or "netascii"
177  */
178 #define SEND_RRQ(filename, mode)					\
179 	SEND_STR("\0\001" filename "\0" mode "\0")
180 
181 /*
182  * send a read request with options
183  */
184 #define SEND_RRQ_OPT(filename, mode, options)				\
185 	SEND_STR("\0\001" filename "\0" mode "\000" options)
186 
187 /*
188  * send a write request to tftpd.
189  * @param	filename	filename as a string, absolute or relative
190  * @param	mode		either "octet" or "netascii"
191  */
192 #define SEND_WRQ(filename, mode)					\
193 	SEND_STR("\0\002" filename "\0" mode "\0")
194 
195 /*
196  * send a write request with options
197  */
198 #define SEND_WRQ_OPT(filename, mode, options)				\
199 	SEND_STR("\0\002" filename "\0" mode "\000" options)
200 
201 /* Define a test case, for both IPv4 and IPv6 */
202 #define TFTPD_TC_DEFINE(name, head, ...)				\
203 static void								\
204 name ## _body(void);							\
205 ATF_TC_WITH_CLEANUP(name ## _v4);					\
206 ATF_TC_HEAD(name ## _v4, tc)						\
207 {									\
208 	head								\
209 }									\
210 ATF_TC_BODY(name ## _v4, tc)						\
211 {									\
212 	int exitcode = 0;						\
213 	__VA_ARGS__;							\
214 	protocol = AF_INET;						\
215 	s = setup(&addr, __COUNTER__);					\
216 	name ## _body();						\
217 	close(s);							\
218 	if (exitcode >= 0)						\
219 		check_server(exitcode);					\
220 }									\
221 ATF_TC_CLEANUP(name ## _v4, tc)						\
222 {									\
223 	cleanup();							\
224 }									\
225 ATF_TC_WITH_CLEANUP(name ## _v6);					\
226 ATF_TC_HEAD(name ## _v6, tc)						\
227 {									\
228 	head								\
229 }									\
230 ATF_TC_BODY(name ## _v6, tc)						\
231 {									\
232 	int exitcode = 0;						\
233 	__VA_ARGS__;							\
234 	protocol = AF_INET6;						\
235 	s = setup(&addr, __COUNTER__);					\
236 	name ## _body();						\
237 	close(s);							\
238 	if (exitcode >= 0)						\
239 		check_server(exitcode);					\
240 }									\
241 ATF_TC_CLEANUP(name ## _v6, tc)						\
242 {									\
243 	cleanup();							\
244 }									\
245 static void								\
246 name ## _body(void)
247 
248 /* Add the IPv4 and IPv6 versions of a test case */
249 #define TFTPD_TC_ADD(tp, name) do {					\
250 	ATF_TP_ADD_TC(tp, name ## _v4);					\
251 	ATF_TP_ADD_TC(tp, name ## _v6);					\
252 } while (0)
253 
254 static void
255 sigalrm(int signo __unused)
256 {
257 }
258 
259 /* Check that server exits with specific exit code */
260 static void
261 check_server(int exitcode)
262 {
263 	struct sigaction sa = { .sa_handler = sigalrm };
264 	struct itimerval it = { .it_value = { .tv_sec = 30 } };
265 	FILE *f;
266 	pid_t pid;
267 	int wstatus;
268 
269 	f = fopen(pidfile, "r");
270 	ATF_REQUIRE(f != NULL);
271 	ATF_REQUIRE_INTEQ(1, fscanf(f, "%d", &pid));
272 	ATF_CHECK_INTEQ(0, fclose(f));
273 	ATF_REQUIRE_INTEQ(0, sigaction(SIGALRM, &sa, NULL));
274 	ATF_REQUIRE_EQ(0, setitimer(ITIMER_REAL, &it, NULL));
275 	ATF_REQUIRE_EQ(pid, waitpid(pid, &wstatus, 0));
276 	ATF_CHECK(WIFEXITED(wstatus));
277 	ATF_CHECK_INTEQ(exitcode, WEXITSTATUS(wstatus));
278 	unlink(pidfile);
279 }
280 
281 /* Standard cleanup used by all testcases */
282 static void
283 cleanup(void)
284 {
285 	FILE *f;
286 	pid_t pid;
287 
288 	f = fopen(pidfile, "r");
289 	if (f == NULL)
290 		return;
291 	unlink(pidfile);
292 	if (fscanf(f, "%d", &pid) == 1) {
293 		kill(pid, SIGTERM);
294 		waitpid(pid, NULL, 0);
295 	}
296 	fclose(f);
297 }
298 
299 /* Assert that two binary buffers are identical */
300 static void
301 require_bufeq(const char *expected, size_t expected_len,
302     const char *actual, size_t len)
303 {
304 	size_t i;
305 
306 	ATF_REQUIRE_EQ_MSG(expected_len, len,
307 	    "Expected %zu bytes but got %zu", expected_len, len);
308 	for (i = 0; i < len; i++) {
309 		ATF_REQUIRE_EQ_MSG(expected[i], actual[i],
310 		    "Expected %#hhx at position %zu; got %hhx instead",
311 		    expected[i], i, actual[i]);
312 	}
313 }
314 
315 /*
316  * Start tftpd and return its communicating socket
317  * @param	to	Will be filled in for use with sendto
318  * @param	idx	Unique identifier of the test case
319  * @return		Socket ready to use
320  */
321 static int
322 setup(struct sockaddr_storage *to, uint16_t idx)
323 {
324 	int client_s, server_s, pid, argv_idx;
325 	char execname[] = "/usr/libexec/tftpd";
326 	char s_flag_str[] = "-s";
327 	char w_flag_str[] = "-w";
328 	char pwd[MAXPATHLEN];
329 	char *argv[10];
330 	struct sockaddr_in addr4;
331 	struct sockaddr_in6 addr6;
332 	struct sockaddr *server_addr;
333 	struct pidfh *pfh;
334 	uint16_t port = BASEPORT + idx;
335 	socklen_t len;
336 	int pd[2];
337 
338 	ATF_REQUIRE_EQ(0, pipe2(pd, O_CLOEXEC));
339 
340 	if (protocol == PF_INET) {
341 		len = sizeof(addr4);
342 		bzero(&addr4, len);
343 		addr4.sin_len = len;
344 		addr4.sin_family = PF_INET;
345 		addr4.sin_port = htons(port);
346 		server_addr = (struct sockaddr *)&addr4;
347 	} else {
348 		len = sizeof(addr6);
349 		bzero(&addr6, len);
350 		addr6.sin6_len = len;
351 		addr6.sin6_family = PF_INET6;
352 		addr6.sin6_port = htons(port);
353 		server_addr = (struct sockaddr *)&addr6;
354 	}
355 
356 	ATF_REQUIRE_EQ(pwd, getcwd(pwd, sizeof(pwd)));
357 
358 	/* Must bind(2) pre-fork so it happens before the client's send(2) */
359 	server_s = socket(protocol, SOCK_DGRAM, 0);
360 	if (server_s < 0 && errno == EAFNOSUPPORT) {
361 		atf_tc_skip("This test requires IPv%d support",
362 		    protocol == PF_INET ? 4 : 6);
363 	}
364 	ATF_REQUIRE_MSG(server_s >= 0,
365 	    "socket failed with error %s", strerror(errno));
366 	ATF_REQUIRE_EQ_MSG(0, bind(server_s, server_addr, len),
367 	    "bind failed with error %s", strerror(errno));
368 
369 	pid = fork();
370 	switch (pid) {
371 	case -1:
372 		atf_tc_fail("fork failed");
373 		break;
374 	case 0:
375 		/* In child */
376 		pfh = pidfile_open(pidfile, 0644, NULL);
377 		ATF_REQUIRE_MSG(pfh != NULL,
378 		    "pidfile_open: %s", strerror(errno));
379 		ATF_REQUIRE_EQ(0, pidfile_write(pfh));
380 		ATF_REQUIRE_EQ(0, pidfile_close(pfh));
381 
382 		bzero(argv, sizeof(argv));
383 		argv[0] = execname;
384 		argv_idx = 1;
385 		if (w_flag)
386 			argv[argv_idx++] = w_flag_str;
387 		if (s_flag)
388 			argv[argv_idx++] = s_flag_str;
389 		argv[argv_idx++] = pwd;
390 		ATF_REQUIRE_EQ(STDOUT_FILENO, dup2(server_s, STDOUT_FILENO));
391 		ATF_REQUIRE_EQ(STDIN_FILENO, dup2(server_s, STDIN_FILENO));
392 		ATF_REQUIRE_EQ(STDERR_FILENO, dup2(server_s, STDERR_FILENO));
393 		execv(execname, argv);
394 		atf_tc_fail("exec failed");
395 		break;
396 	default:
397 		/* In parent */
398 		ATF_REQUIRE_INTEQ(0, close(pd[1]));
399 		/* block until other end is closed on exec() or exit() */
400 		ATF_REQUIRE_INTEQ(0, read(pd[0], &pd[1], sizeof(pd[1])));
401 		ATF_REQUIRE_INTEQ(0, close(pd[0]));
402 		bzero(to, sizeof(*to));
403 		if (protocol == PF_INET) {
404 			struct sockaddr_in *to4 = (struct sockaddr_in *)to;
405 			to4->sin_len = sizeof(*to4);
406 			to4->sin_family = PF_INET;
407 			to4->sin_port = htons(port);
408 			to4->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
409 		} else {
410 			struct in6_addr loopback = IN6ADDR_LOOPBACK_INIT;
411 			struct sockaddr_in6 *to6 = (struct sockaddr_in6 *)to;
412 			to6->sin6_len = sizeof(*to6);
413 			to6->sin6_family = PF_INET6;
414 			to6->sin6_port = htons(port);
415 			to6->sin6_addr = loopback;
416 		}
417 
418 		ATF_REQUIRE_INTEQ(0, close(server_s));
419 		ATF_REQUIRE((client_s = socket(protocol, SOCK_DGRAM, 0)) > 0);
420 		break;
421 	}
422 
423 	/* Clear the client's umask.  Test cases will specify exact modes */
424 	umask(0000);
425 
426 	return (client_s);
427 }
428 
429 /* Like write(2), but never returns less than the requested length */
430 static void
431 write_all(int fd, const void *buf, size_t nbytes)
432 {
433 	ssize_t r;
434 
435 	while (nbytes > 0) {
436 		r = write(fd, buf, nbytes);
437 		ATF_REQUIRE(r > 0);
438 		nbytes -= (size_t)r;
439 		buf = (const char *)buf + (size_t)r;
440 	}
441 }
442 
443 
444 /*
445  * Test Cases
446  */
447 
448 /*
449  * Read a file, specified by absolute pathname.
450  */
451 TFTPD_TC_DEFINE(abspath,)
452 {
453 	int fd;
454 	char command[1024];
455 	size_t pathlen;
456 	char suffix[] = {'\0', 'o', 'c', 't', 'e', 't', '\0'};
457 
458 	command[0] = 0;		/* RRQ high byte */
459 	command[1] = 1;		/* RRQ low byte */
460 	ATF_REQUIRE(getcwd(&command[2], sizeof(command) - 2) != NULL);
461 	pathlen = strlcat(&command[2], "/abspath.txt", sizeof(command) - 2);
462 	ATF_REQUIRE(pathlen + sizeof(suffix) < sizeof(command) - 2);
463 	memmove(&command[2 + pathlen], suffix, sizeof(suffix));
464 
465 	fd = open("abspath.txt", O_CREAT | O_RDONLY, 0644);
466 	ATF_REQUIRE(fd >= 0);
467 	close(fd);
468 
469 	send_bytes(command, 2 + pathlen + sizeof(suffix));
470 	recv_data(1, NULL, 0);
471 	send_ack(1);
472 }
473 
474 /*
475  * Attempt to read a file outside of the allowed directory(ies)
476  */
477 TFTPD_TC_DEFINE(dotdot,)
478 {
479 	ATF_REQUIRE_EQ(0, mkdir("subdir", 0777));
480 	SEND_RRQ("../disallowed.txt", "octet");
481 	RECV_ERROR(2, "Access violation");
482 	s = setup(&addr, __COUNTER__);
483 	SEND_RRQ("subdir/../../disallowed.txt", "octet");
484 	RECV_ERROR(2, "Access violation");
485 	s = setup(&addr, __COUNTER__);
486 	SEND_RRQ("/etc/passwd", "octet");
487 	RECV_ERROR(2, "Access violation");
488 }
489 
490 /*
491  * With "-s", tftpd should chroot to the specified directory
492  */
493 TFTPD_TC_DEFINE(s_flag,
494     atf_tc_set_md_var(tc, "require.user", "root");,
495     s_flag = true)
496 {
497 	int fd;
498 	char contents[] = "small";
499 
500 	fd = open("small.txt", O_RDWR | O_CREAT, 0644);
501 	ATF_REQUIRE(fd >= 0);
502 	write_all(fd, contents, strlen(contents) + 1);
503 	close(fd);
504 
505 	SEND_RRQ("/small.txt", "octet");
506 	recv_data(1, contents, strlen(contents) + 1);
507 	send_ack(1);
508 }
509 
510 /*
511  * Read a file, and simulate a dropped ACK packet
512  */
513 TFTPD_TC_DEFINE(rrq_dropped_ack,)
514 {
515 	int fd;
516 	char contents[] = "small";
517 
518 	fd = open("small.txt", O_RDWR | O_CREAT, 0644);
519 	ATF_REQUIRE(fd >= 0);
520 	write_all(fd, contents, strlen(contents) + 1);
521 	close(fd);
522 
523 	SEND_RRQ("small.txt", "octet");
524 	recv_data(1, contents, strlen(contents) + 1);
525 	/*
526 	 * client "sends" the ack, but network drops it
527 	 * Eventually, tftpd should resend the data packet
528 	 */
529 	recv_data(1, contents, strlen(contents) + 1);
530 	send_ack(1);
531 }
532 
533 /*
534  * Read a file, and simulate a dropped DATA packet
535  */
536 TFTPD_TC_DEFINE(rrq_dropped_data,)
537 {
538 	int fd;
539 	size_t i;
540 	uint32_t contents[192];
541 	char buffer[1024];
542 
543 	for (i = 0; i < nitems(contents); i++)
544 		contents[i] = i;
545 
546 	fd = open("medium.txt", O_RDWR | O_CREAT, 0644);
547 	ATF_REQUIRE(fd >= 0);
548 	write_all(fd, contents, sizeof(contents));
549 	close(fd);
550 
551 	SEND_RRQ("medium.txt", "octet");
552 	recv_data(1, (const char *)&contents[0], 512);
553 	send_ack(1);
554 	(void) recvfrom(s, buffer, sizeof(buffer), 0, NULL, NULL);
555 	/*
556 	 * server "sends" the data, but network drops it
557 	 * Eventually, client should resend the last ACK
558 	 */
559 	send_ack(1);
560 	recv_data(2, (const char *)&contents[128], 256);
561 	send_ack(2);
562 }
563 
564 /*
565  * Read a medium file, and simulate a duplicated ACK packet
566  */
567 TFTPD_TC_DEFINE(rrq_duped_ack,)
568 {
569 	int fd;
570 	size_t i;
571 	uint32_t contents[192];
572 
573 	for (i = 0; i < nitems(contents); i++)
574 		contents[i] = i;
575 
576 	fd = open("medium.txt", O_RDWR | O_CREAT, 0644);
577 	ATF_REQUIRE(fd >= 0);
578 	write_all(fd, contents, sizeof(contents));
579 	close(fd);
580 
581 	SEND_RRQ("medium.txt", "octet");
582 	recv_data(1, (const char *)&contents[0], 512);
583 	send_ack(1);
584 	send_ack(1);	/* Dupe an ACK packet */
585 	recv_data(2, (const char *)&contents[128], 256);
586 	recv_data(2, (const char *)&contents[128], 256);
587 	send_ack(2);
588 }
589 
590 
591 /*
592  * Attempt to read a file without read permissions
593  */
594 TFTPD_TC_DEFINE(rrq_eaccess,)
595 {
596 	int fd;
597 
598 	fd = open("empty.txt", O_CREAT | O_RDONLY, 0000);
599 	ATF_REQUIRE(fd >= 0);
600 	close(fd);
601 
602 	SEND_RRQ("empty.txt", "octet");
603 	RECV_ERROR(2, "Access violation");
604 }
605 
606 /*
607  * Read an empty file
608  */
609 TFTPD_TC_DEFINE(rrq_empty,)
610 {
611 	int fd;
612 
613 	fd = open("empty.txt", O_CREAT | O_RDONLY, 0644);
614 	ATF_REQUIRE(fd >= 0);
615 	close(fd);
616 
617 	SEND_RRQ("empty.txt", "octet");
618 	recv_data(1, NULL, 0);
619 	send_ack(1);
620 }
621 
622 /*
623  * Read a medium file of more than one block
624  */
625 TFTPD_TC_DEFINE(rrq_medium,)
626 {
627 	int fd;
628 	size_t i;
629 	uint32_t contents[192];
630 
631 	for (i = 0; i < nitems(contents); i++)
632 		contents[i] = i;
633 
634 	fd = open("medium.txt", O_RDWR | O_CREAT, 0644);
635 	ATF_REQUIRE(fd >= 0);
636 	write_all(fd, contents, sizeof(contents));
637 	close(fd);
638 
639 	SEND_RRQ("medium.txt", "octet");
640 	recv_data(1, (const char *)&contents[0], 512);
641 	send_ack(1);
642 	recv_data(2, (const char *)&contents[128], 256);
643 	send_ack(2);
644 }
645 
646 /*
647  * Read a medium file with a window size of 2.
648  */
649 TFTPD_TC_DEFINE(rrq_medium_window,)
650 {
651 	int fd;
652 	size_t i;
653 	uint32_t contents[192];
654 	char options[] = OPTION_STR("windowsize", "2");
655 
656 	for (i = 0; i < nitems(contents); i++)
657 		contents[i] = i;
658 
659 	fd = open("medium.txt", O_RDWR | O_CREAT, 0644);
660 	ATF_REQUIRE(fd >= 0);
661 	write_all(fd, contents, sizeof(contents));
662 	close(fd);
663 
664 	SEND_RRQ_OPT("medium.txt", "octet", OPTION_STR("windowsize", "2"));
665 	recv_oack(options, sizeof(options) - 1);
666 	send_ack(0);
667 	recv_data(1, (const char *)&contents[0], 512);
668 	recv_data(2, (const char *)&contents[128], 256);
669 	send_ack(2);
670 }
671 
672 /*
673  * Read a file in netascii format
674  */
675 TFTPD_TC_DEFINE(rrq_netascii,)
676 {
677 	int fd;
678 	char contents[] = "foo\nbar\rbaz\n";
679 	/*
680 	 * Weirdly, RFC-764 says that CR must be followed by NUL if a line feed
681 	 * is not intended
682 	 */
683 	char expected[] = "foo\r\nbar\r\0baz\r\n";
684 
685 	fd = open("unix.txt", O_RDWR | O_CREAT, 0644);
686 	ATF_REQUIRE(fd >= 0);
687 	write_all(fd, contents, strlen(contents) + 1);
688 	close(fd);
689 
690 	SEND_RRQ("unix.txt", "netascii");
691 	recv_data(1, expected, sizeof(expected));
692 	send_ack(1);
693 }
694 
695 /*
696  * Read a file that doesn't exist
697  */
698 TFTPD_TC_DEFINE(rrq_nonexistent,)
699 {
700 	SEND_RRQ("nonexistent.txt", "octet");
701 	RECV_ERROR(1, "File not found");
702 }
703 
704 /*
705  * Attempt to read a file whose name exceeds PATH_MAX
706  */
707 TFTPD_TC_DEFINE(rrq_path_max,)
708 {
709 #define AReallyBigFileName \
710 	    "AReallyBigFileNameXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"\
711 	    "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"\
712 	    "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"\
713 	    "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"\
714 	    "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"\
715 	    "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"\
716 	    "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"\
717 	    "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"\
718 	    "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"\
719 	    "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"\
720 	    "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"\
721 	    "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"\
722 	    "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"\
723 	    "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"\
724 	    "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"\
725 	    "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"\
726 	    ".txt"
727 	ATF_REQUIRE_MSG(strlen(AReallyBigFileName) > PATH_MAX,
728 	    "Somebody increased PATH_MAX.  Update the test");
729 	SEND_RRQ(AReallyBigFileName, "octet");
730 	RECV_ERROR(4, "Illegal TFTP operation");
731 }
732 
733 /*
734  * Read a small file of less than one block
735  */
736 TFTPD_TC_DEFINE(rrq_small,)
737 {
738 	int fd;
739 	char contents[] = "small";
740 
741 	fd = open("small.txt", O_RDWR | O_CREAT, 0644);
742 	ATF_REQUIRE(fd >= 0);
743 	write_all(fd, contents, strlen(contents) + 1);
744 	close(fd);
745 
746 	SEND_RRQ("small.txt", "octet");
747 	recv_data(1, contents, strlen(contents) + 1);
748 	send_ack(1);
749 }
750 
751 /*
752  * Read a file following the example in RFC 7440.
753  */
754 TFTPD_TC_DEFINE(rrq_window_rfc7440,)
755 {
756 	int fd;
757 	size_t i;
758 	char options[] = OPTION_STR("windowsize", "4");
759 	alignas(uint32_t) char contents[13 * 512 - 4];
760 	uint32_t *u32p;
761 
762 	u32p = (uint32_t *)contents;
763 	for (i = 0; i < sizeof(contents) / sizeof(uint32_t); i++)
764 		u32p[i] = i;
765 
766 	fd = open("rfc7440.txt", O_RDWR | O_CREAT, 0644);
767 	ATF_REQUIRE(fd >= 0);
768 	write_all(fd, contents, sizeof(contents));
769 	close(fd);
770 
771 	SEND_RRQ_OPT("rfc7440.txt", "octet", OPTION_STR("windowsize", "4"));
772 	recv_oack(options, sizeof(options) - 1);
773 	send_ack(0);
774 	recv_data(1, &contents[0 * 512], 512);
775 	recv_data(2, &contents[1 * 512], 512);
776 	recv_data(3, &contents[2 * 512], 512);
777 	recv_data(4, &contents[3 * 512], 512);
778 	send_ack(4);
779 	recv_data(5, &contents[4 * 512], 512);
780 	recv_data(6, &contents[5 * 512], 512);
781 	recv_data(7, &contents[6 * 512], 512);
782 	recv_data(8, &contents[7 * 512], 512);
783 
784 	/* ACK 5 as if 6-8 were dropped. */
785 	send_ack(5);
786 	recv_data(6, &contents[5 * 512], 512);
787 	recv_data(7, &contents[6 * 512], 512);
788 	recv_data(8, &contents[7 * 512], 512);
789 	recv_data(9, &contents[8 * 512], 512);
790 	send_ack(9);
791 	recv_data(10, &contents[9 * 512], 512);
792 	recv_data(11, &contents[10 * 512], 512);
793 	recv_data(12, &contents[11 * 512], 512);
794 	recv_data(13, &contents[12 * 512], 508);
795 
796 	/* Drop ACK and after timeout receive 10-13. */
797 	recv_data(10, &contents[9 * 512], 512);
798 	recv_data(11, &contents[10 * 512], 512);
799 	recv_data(12, &contents[11 * 512], 512);
800 	recv_data(13, &contents[12 * 512], 508);
801 	send_ack(13);
802 }
803 
804 /*
805  * Try to transfer a file with an unknown mode.
806  */
807 TFTPD_TC_DEFINE(unknown_modes,)
808 {
809 	SEND_RRQ("foo.txt", "ascii");	/* Misspelling of "ascii" */
810 	RECV_ERROR(4, "Illegal TFTP operation");
811 	s = setup(&addr, __COUNTER__);
812 	SEND_RRQ("foo.txt", "binary");	/* Obsolete.  Use "octet" instead */
813 	RECV_ERROR(4, "Illegal TFTP operation");
814 	s = setup(&addr, __COUNTER__);
815 	SEND_RRQ("foo.txt", "en_US.UTF-8");
816 	RECV_ERROR(4, "Illegal TFTP operation");
817 	s = setup(&addr, __COUNTER__);
818 	SEND_RRQ("foo.txt", "mail");	/* Obsolete in RFC-1350 */
819 	RECV_ERROR(4, "Illegal TFTP operation");
820 }
821 
822 /*
823  * Send an unknown opcode.  tftpd should respond with the appropriate error
824  */
825 TFTPD_TC_DEFINE(unknown_opcode,)
826 {
827 	/* Looks like an RRQ or WRQ request, but with a bad opcode */
828 	SEND_STR("\0\007foo.txt\0octet\0");
829 	RECV_ERROR(4, "Illegal TFTP operation");
830 }
831 
832 /*
833  * Invoke tftpd with "-w" and write to a nonexistent file.
834  */
835 TFTPD_TC_DEFINE(w_flag,, w_flag = 1;)
836 {
837 	int fd;
838 	ssize_t r;
839 	char contents[] = "small";
840 	char buffer[1024];
841 	size_t contents_len;
842 
843 	contents_len = strlen(contents) + 1;
844 	SEND_WRQ("small.txt", "octet");
845 	recv_ack(0);
846 	send_data(1, contents, contents_len);
847 	recv_ack(1);
848 
849 	fd = open("small.txt", O_RDONLY);
850 	ATF_REQUIRE(fd >= 0);
851 	r = read(fd, buffer, sizeof(buffer));
852 	ATF_REQUIRE(r > 0);
853 	close(fd);
854 	require_bufeq(contents, contents_len, buffer, (size_t)r);
855 }
856 
857 /*
858  * Write a medium file, and simulate a dropped ACK packet
859  */
860 TFTPD_TC_DEFINE(wrq_dropped_ack,)
861 {
862 	int fd;
863 	size_t i;
864 	ssize_t r;
865 	uint32_t contents[192];
866 	char buffer[1024];
867 
868 	for (i = 0; i < nitems(contents); i++)
869 		contents[i] = i;
870 
871 	fd = open("medium.txt", O_RDWR | O_CREAT, 0666);
872 	ATF_REQUIRE(fd >= 0);
873 	close(fd);
874 
875 	SEND_WRQ("medium.txt", "octet");
876 	recv_ack(0);
877 	send_data(1, (const char *)&contents[0], 512);
878 	/*
879 	 * Servers "sends" an ACK packet, but network drops it.
880 	 * Eventually, server should resend the last ACK
881 	 */
882 	(void) recvfrom(s, buffer, sizeof(buffer), 0, NULL, NULL);
883 	recv_ack(1);
884 	send_data(2, (const char *)&contents[128], 256);
885 	recv_ack(2);
886 
887 	fd = open("medium.txt", O_RDONLY);
888 	ATF_REQUIRE(fd >= 0);
889 	r = read(fd, buffer, sizeof(buffer));
890 	ATF_REQUIRE(r > 0);
891 	close(fd);
892 	require_bufeq((const char *)contents, 768, buffer, (size_t)r);
893 }
894 
895 /*
896  * Write a small file, and simulate a dropped DATA packet
897  */
898 TFTPD_TC_DEFINE(wrq_dropped_data,)
899 {
900 	int fd;
901 	ssize_t r;
902 	char contents[] = "small";
903 	size_t contents_len;
904 	char buffer[1024];
905 
906 	fd = open("small.txt", O_RDWR | O_CREAT, 0666);
907 	ATF_REQUIRE(fd >= 0);
908 	close(fd);
909 	contents_len = strlen(contents) + 1;
910 
911 	SEND_WRQ("small.txt", "octet");
912 	recv_ack(0);
913 	/*
914 	 * Client "sends" a DATA packet, but network drops it.
915 	 * Eventually, server should resend the last ACK
916 	 */
917 	recv_ack(0);
918 	send_data(1, contents, contents_len);
919 	recv_ack(1);
920 
921 	fd = open("small.txt", O_RDONLY);
922 	ATF_REQUIRE(fd >= 0);
923 	r = read(fd, buffer, sizeof(buffer));
924 	ATF_REQUIRE(r > 0);
925 	close(fd);
926 	require_bufeq(contents, contents_len, buffer, (size_t)r);
927 }
928 
929 /*
930  * Write a medium file, and simulate a duplicated DATA packet
931  */
932 TFTPD_TC_DEFINE(wrq_duped_data,)
933 {
934 	int fd;
935 	size_t i;
936 	ssize_t r;
937 	uint32_t contents[192];
938 	char buffer[1024];
939 
940 	for (i = 0; i < nitems(contents); i++)
941 		contents[i] = i;
942 
943 	fd = open("medium.txt", O_RDWR | O_CREAT, 0666);
944 	ATF_REQUIRE(fd >= 0);
945 	close(fd);
946 
947 	SEND_WRQ("medium.txt", "octet");
948 	recv_ack(0);
949 	send_data(1, (const char *)&contents[0], 512);
950 	send_data(1, (const char *)&contents[0], 512);
951 	recv_ack(1);
952 	recv_ack(1);
953 	send_data(2, (const char *)&contents[128], 256);
954 	recv_ack(2);
955 
956 	fd = open("medium.txt", O_RDONLY);
957 	ATF_REQUIRE(fd >= 0);
958 	r = read(fd, buffer, sizeof(buffer));
959 	ATF_REQUIRE(r > 0);
960 	close(fd);
961 	require_bufeq((const char *)contents, 768, buffer, (size_t)r);
962 }
963 
964 /*
965  * Attempt to write a file without write permissions
966  */
967 TFTPD_TC_DEFINE(wrq_eaccess,)
968 {
969 	int fd;
970 
971 	fd = open("empty.txt", O_CREAT | O_RDONLY, 0440);
972 	ATF_REQUIRE(fd >= 0);
973 	close(fd);
974 
975 	SEND_WRQ("empty.txt", "octet");
976 	RECV_ERROR(2, "Access violation");
977 }
978 
979 /*
980  * Attempt to write a file without world write permissions, but with world
981  * read permissions
982  */
983 TFTPD_TC_DEFINE(wrq_eaccess_world_readable,)
984 {
985 	int fd;
986 
987 	fd = open("empty.txt", O_CREAT | O_RDONLY, 0444);
988 	ATF_REQUIRE(fd >= 0);
989 	close(fd);
990 
991 	SEND_WRQ("empty.txt", "octet");
992 	RECV_ERROR(2, "Access violation");
993 }
994 
995 
996 /*
997  * Write a medium file of more than one block
998  */
999 TFTPD_TC_DEFINE(wrq_medium,)
1000 {
1001 	int fd;
1002 	size_t i;
1003 	ssize_t r;
1004 	uint32_t contents[192];
1005 	char buffer[1024];
1006 
1007 	for (i = 0; i < nitems(contents); i++)
1008 		contents[i] = i;
1009 
1010 	fd = open("medium.txt", O_RDWR | O_CREAT, 0666);
1011 	ATF_REQUIRE(fd >= 0);
1012 	close(fd);
1013 
1014 	SEND_WRQ("medium.txt", "octet");
1015 	recv_ack(0);
1016 	send_data(1, (const char *)&contents[0], 512);
1017 	recv_ack(1);
1018 	send_data(2, (const char *)&contents[128], 256);
1019 	recv_ack(2);
1020 
1021 	fd = open("medium.txt", O_RDONLY);
1022 	ATF_REQUIRE(fd >= 0);
1023 	r = read(fd, buffer, sizeof(buffer));
1024 	ATF_REQUIRE(r > 0);
1025 	close(fd);
1026 	require_bufeq((const char *)contents, 768, buffer, (size_t)r);
1027 }
1028 
1029 /*
1030  * Write a medium file with a window size of 2.
1031  */
1032 TFTPD_TC_DEFINE(wrq_medium_window,)
1033 {
1034 	int fd;
1035 	size_t i;
1036 	ssize_t r;
1037 	uint32_t contents[192];
1038 	char buffer[1024];
1039 	char options[] = OPTION_STR("windowsize", "2");
1040 
1041 	for (i = 0; i < nitems(contents); i++)
1042 		contents[i] = i;
1043 
1044 	fd = open("medium.txt", O_RDWR | O_CREAT, 0666);
1045 	ATF_REQUIRE(fd >= 0);
1046 	close(fd);
1047 
1048 	SEND_WRQ_OPT("medium.txt", "octet", OPTION_STR("windowsize", "2"));
1049 	recv_oack(options, sizeof(options) - 1);
1050 	send_data(1, (const char *)&contents[0], 512);
1051 	send_data(2, (const char *)&contents[128], 256);
1052 	recv_ack(2);
1053 
1054 	fd = open("medium.txt", O_RDONLY);
1055 	ATF_REQUIRE(fd >= 0);
1056 	r = read(fd, buffer, sizeof(buffer));
1057 	ATF_REQUIRE(r > 0);
1058 	close(fd);
1059 	require_bufeq((const char *)contents, 768, buffer, (size_t)r);
1060 }
1061 
1062 /*
1063  * Write a file in netascii format
1064  */
1065 TFTPD_TC_DEFINE(wrq_netascii,)
1066 {
1067 	int fd;
1068 	ssize_t r;
1069 	/*
1070 	 * Weirdly, RFC-764 says that CR must be followed by NUL if a line feed
1071 	 * is not intended
1072 	 */
1073 	char contents[] = "foo\r\nbar\r\0baz\r\n";
1074 	char expected[] = "foo\nbar\rbaz\n";
1075 	size_t contents_len;
1076 	char buffer[1024];
1077 
1078 	fd = open("unix.txt", O_RDWR | O_CREAT, 0666);
1079 	ATF_REQUIRE(fd >= 0);
1080 	close(fd);
1081 	contents_len = sizeof(contents);
1082 
1083 	SEND_WRQ("unix.txt", "netascii");
1084 	recv_ack(0);
1085 	send_data(1, contents, contents_len);
1086 	recv_ack(1);
1087 
1088 	fd = open("unix.txt", O_RDONLY);
1089 	ATF_REQUIRE(fd >= 0);
1090 	r = read(fd, buffer, sizeof(buffer));
1091 	ATF_REQUIRE(r > 0);
1092 	close(fd);
1093 	require_bufeq(expected, sizeof(expected), buffer, (size_t)r);
1094 }
1095 
1096 /*
1097  * Attempt to write to a nonexistent file.  With the default options, this
1098  * isn't allowed.
1099  */
1100 TFTPD_TC_DEFINE(wrq_nonexistent,)
1101 {
1102 	SEND_WRQ("nonexistent.txt", "octet");
1103 	RECV_ERROR(1, "File not found");
1104 }
1105 
1106 /*
1107  * Write a small file of less than one block
1108  */
1109 TFTPD_TC_DEFINE(wrq_small,)
1110 {
1111 	int fd;
1112 	ssize_t r;
1113 	char contents[] = "small";
1114 	size_t contents_len;
1115 	char buffer[1024];
1116 
1117 	fd = open("small.txt", O_RDWR | O_CREAT, 0666);
1118 	ATF_REQUIRE(fd >= 0);
1119 	close(fd);
1120 	contents_len = strlen(contents) + 1;
1121 
1122 	SEND_WRQ("small.txt", "octet");
1123 	recv_ack(0);
1124 	send_data(1, contents, contents_len);
1125 	recv_ack(1);
1126 
1127 	fd = open("small.txt", O_RDONLY);
1128 	ATF_REQUIRE(fd >= 0);
1129 	r = read(fd, buffer, sizeof(buffer));
1130 	ATF_REQUIRE(r > 0);
1131 	close(fd);
1132 	require_bufeq(contents, contents_len, buffer, (size_t)r);
1133 }
1134 
1135 /*
1136  * Write an empty file over a non-empty one
1137  */
1138 TFTPD_TC_DEFINE(wrq_truncate,)
1139 {
1140 	int fd;
1141 	char contents[] = "small";
1142 	struct stat sb;
1143 
1144 	fd = open("small.txt", O_RDWR | O_CREAT, 0666);
1145 	ATF_REQUIRE(fd >= 0);
1146 	write_all(fd, contents, strlen(contents) + 1);
1147 	close(fd);
1148 
1149 	SEND_WRQ("small.txt", "octet");
1150 	recv_ack(0);
1151 	send_data(1, NULL, 0);
1152 	recv_ack(1);
1153 
1154 	ATF_REQUIRE_EQ(0, stat("small.txt", &sb));
1155 	ATF_REQUIRE_EQ(0, sb.st_size);
1156 }
1157 
1158 /*
1159  * Write a file following the example in RFC 7440.
1160  */
1161 TFTPD_TC_DEFINE(wrq_window_rfc7440,)
1162 {
1163 	int fd;
1164 	size_t i;
1165 	ssize_t r;
1166 	char options[] = OPTION_STR("windowsize", "4");
1167 	alignas(uint32_t) char contents[13 * 512 - 4];
1168 	char buffer[sizeof(contents)];
1169 	uint32_t *u32p;
1170 
1171 	u32p = (uint32_t *)contents;
1172 	for (i = 0; i < sizeof(contents) / sizeof(uint32_t); i++)
1173 		u32p[i] = i;
1174 
1175 	fd = open("rfc7440.txt", O_RDWR | O_CREAT, 0666);
1176 	ATF_REQUIRE(fd >= 0);
1177 	close(fd);
1178 
1179 	SEND_WRQ_OPT("rfc7440.txt", "octet", OPTION_STR("windowsize", "4"));
1180 	recv_oack(options, sizeof(options) - 1);
1181 	send_data(1, &contents[0 * 512], 512);
1182 	send_data(2, &contents[1 * 512], 512);
1183 	send_data(3, &contents[2 * 512], 512);
1184 	send_data(4, &contents[3 * 512], 512);
1185 	recv_ack(4);
1186 	send_data(5, &contents[4 * 512], 512);
1187 
1188 	/* Drop 6-8. */
1189 	recv_ack(5);
1190 	send_data(6, &contents[5 * 512], 512);
1191 	send_data(7, &contents[6 * 512], 512);
1192 	send_data(8, &contents[7 * 512], 512);
1193 	send_data(9, &contents[8 * 512], 512);
1194 	recv_ack(9);
1195 
1196 	/* Drop 11. */
1197 	send_data(10, &contents[9 * 512], 512);
1198 	send_data(12, &contents[11 * 512], 512);
1199 
1200 	/*
1201 	 * We can't send 13 here as tftpd has probably already seen 12
1202 	 * and sent the ACK of 10 if running locally.  While it would
1203 	 * recover by sending another ACK of 10, our state machine
1204 	 * would be out of sync.
1205 	 */
1206 
1207 	/* Ignore ACK for 10 and resend 10-13. */
1208 	recv_ack(10);
1209 	send_data(10, &contents[9 * 512], 512);
1210 	send_data(11, &contents[10 * 512], 512);
1211 	send_data(12, &contents[11 * 512], 512);
1212 	send_data(13, &contents[12 * 512], 508);
1213 	recv_ack(13);
1214 
1215 	fd = open("rfc7440.txt", O_RDONLY);
1216 	ATF_REQUIRE(fd >= 0);
1217 	r = read(fd, buffer, sizeof(buffer));
1218 	ATF_REQUIRE(r > 0);
1219 	close(fd);
1220 	require_bufeq(contents, sizeof(contents), buffer, (size_t)r);
1221 }
1222 
1223 /*
1224  * Send less than four bytes
1225  */
1226 TFTPD_TC_DEFINE(short_packet1, /* no head */, exitcode = 1)
1227 {
1228 	SEND_STR("\1");
1229 }
1230 TFTPD_TC_DEFINE(short_packet2, /* no head */, exitcode = 1)
1231 {
1232 	SEND_STR("\1\2");
1233 }
1234 TFTPD_TC_DEFINE(short_packet3, /* no head */, exitcode = 1)
1235 {
1236 	SEND_STR("\1\2\3");
1237 }
1238 
1239 
1240 /*
1241  * Main
1242  */
1243 
1244 ATF_TP_ADD_TCS(tp)
1245 {
1246 	TFTPD_TC_ADD(tp, abspath);
1247 	TFTPD_TC_ADD(tp, dotdot);
1248 	TFTPD_TC_ADD(tp, s_flag);
1249 	TFTPD_TC_ADD(tp, rrq_dropped_ack);
1250 	TFTPD_TC_ADD(tp, rrq_dropped_data);
1251 	TFTPD_TC_ADD(tp, rrq_duped_ack);
1252 	TFTPD_TC_ADD(tp, rrq_eaccess);
1253 	TFTPD_TC_ADD(tp, rrq_empty);
1254 	TFTPD_TC_ADD(tp, rrq_medium);
1255 	TFTPD_TC_ADD(tp, rrq_medium_window);
1256 	TFTPD_TC_ADD(tp, rrq_netascii);
1257 	TFTPD_TC_ADD(tp, rrq_nonexistent);
1258 	TFTPD_TC_ADD(tp, rrq_path_max);
1259 	TFTPD_TC_ADD(tp, rrq_small);
1260 	TFTPD_TC_ADD(tp, rrq_window_rfc7440);
1261 	TFTPD_TC_ADD(tp, unknown_modes);
1262 	TFTPD_TC_ADD(tp, unknown_opcode);
1263 	TFTPD_TC_ADD(tp, w_flag);
1264 	TFTPD_TC_ADD(tp, wrq_dropped_ack);
1265 	TFTPD_TC_ADD(tp, wrq_dropped_data);
1266 	TFTPD_TC_ADD(tp, wrq_duped_data);
1267 	TFTPD_TC_ADD(tp, wrq_eaccess);
1268 	TFTPD_TC_ADD(tp, wrq_eaccess_world_readable);
1269 	TFTPD_TC_ADD(tp, wrq_medium);
1270 	TFTPD_TC_ADD(tp, wrq_medium_window);
1271 	TFTPD_TC_ADD(tp, wrq_netascii);
1272 	TFTPD_TC_ADD(tp, wrq_nonexistent);
1273 	TFTPD_TC_ADD(tp, wrq_small);
1274 	TFTPD_TC_ADD(tp, wrq_truncate);
1275 	TFTPD_TC_ADD(tp, wrq_window_rfc7440);
1276 	TFTPD_TC_ADD(tp, short_packet1);
1277 	TFTPD_TC_ADD(tp, short_packet2);
1278 	TFTPD_TC_ADD(tp, short_packet3);
1279 
1280 	return (atf_no_error());
1281 }
1282