1 /* $OpenBSD: tftpd.c,v 1.52 2024/09/20 02:00:46 jsg Exp $ */
2
3 /*
4 * Copyright (c) 2012 David Gwynne <dlg@uq.edu.au>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 /*
20 * Copyright (c) 1983 Regents of the University of California.
21 * All rights reserved.
22 *
23 * Redistribution and use in source and binary forms, with or without
24 * modification, are permitted provided that the following conditions
25 * are met:
26 * 1. Redistributions of source code must retain the above copyright
27 * notice, this list of conditions and the following disclaimer.
28 * 2. Redistributions in binary form must reproduce the above copyright
29 * notice, this list of conditions and the following disclaimer in the
30 * documentation and/or other materials provided with the distribution.
31 * 3. Neither the name of the University nor the names of its contributors
32 * may be used to endorse or promote products derived from this software
33 * without specific prior written permission.
34 *
35 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
36 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
38 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
39 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
40 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
41 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
42 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
43 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
44 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
45 * SUCH DAMAGE.
46 */
47
48 /*
49 * Trivial file transfer protocol server.
50 *
51 * This version is based on src/libexec/tftpd which includes many
52 * modifications by Jim Guyton <guyton@rand-unix>.
53 *
54 * It was restructured to be a persistent event driven daemon
55 * supporting concurrent connections by dlg for use at the University
56 * of Queensland in the Faculty of Engineering Architecture and
57 * Information Technology.
58 */
59
60 #include <sys/types.h>
61 #include <sys/queue.h>
62 #include <sys/socket.h>
63 #include <sys/stat.h>
64 #include <sys/uio.h>
65 #include <sys/un.h>
66
67 #include <netinet/in.h>
68 #include <arpa/inet.h>
69 #include <arpa/tftp.h>
70 #include <netdb.h>
71
72 #include <err.h>
73 #include <ctype.h>
74 #include <errno.h>
75 #include <event.h>
76 #include <fcntl.h>
77 #include <paths.h>
78 #include <poll.h>
79 #include <pwd.h>
80 #include <stdio.h>
81 #include <stdlib.h>
82 #include <string.h>
83 #include <stdarg.h>
84 #include <syslog.h>
85 #include <unistd.h>
86 #include <limits.h>
87 #include <vis.h>
88
89 #define TIMEOUT 5 /* packet rexmt timeout */
90 #define TIMEOUT_MIN 1 /* minimal packet rexmt timeout */
91 #define TIMEOUT_MAX 255 /* maximal packet rexmt timeout */
92
93 #define RETRIES 5
94
95 #define SEEDPATH "/etc/random.seed"
96
97 struct formats;
98
99 enum opt_enum {
100 OPT_TSIZE = 0,
101 OPT_TIMEOUT,
102 OPT_BLKSIZE,
103 NOPT
104 };
105
106 static char *opt_names[] = {
107 "tsize",
108 "timeout",
109 "blksize"
110 };
111
112 struct opt_client {
113 char *o_request;
114 long long o_reply;
115 };
116
117
118 struct tftp_server {
119 struct event ev;
120 TAILQ_ENTRY(tftp_server) entry;
121 int s;
122 };
123
124 TAILQ_HEAD(, tftp_server) tftp_servers;
125
126 struct tftp_client {
127 char buf[SEGSIZE_MAX + 4];
128 struct event sev;
129 struct sockaddr_storage ss;
130
131 struct timeval tv;
132
133 TAILQ_ENTRY(tftp_client) entry;
134
135 struct opt_client *options;
136
137 size_t segment_size;
138 size_t packet_size;
139 size_t buflen;
140
141 FILE *file;
142 int (*fgetc)(struct tftp_client *);
143 int (*fputc)(struct tftp_client *, int);
144
145 u_int retries;
146 u_int16_t block;
147
148 int opcode;
149 int newline;
150
151 int sock;
152 };
153
154 __dead void usage(void);
155 const char *getip(void *);
156 int rdaemon(int);
157
158 void rewrite_connect(const char *);
159 void rewrite_events(void);
160 void rewrite_map(struct tftp_client *, const char *);
161 void rewrite_req(int, short, void *);
162 void rewrite_res(int, short, void *);
163
164 int tftpd_listen(const char *, const char *, int);
165 void tftpd_events(void);
166 void tftpd_recv(int, short, void *);
167 int retry(struct tftp_client *);
168 int tftp_flush(struct tftp_client *);
169
170 void tftp(struct tftp_client *, struct tftphdr *, size_t);
171 void tftp_open(struct tftp_client *, const char *);
172 void nak(struct tftp_client *, int);
173 int oack(struct tftp_client *);
174 void oack_done(int, short, void *);
175
176 void sendfile(struct tftp_client *);
177 void recvfile(struct tftp_client *);
178 int fget_octet(struct tftp_client *);
179 int fput_octet(struct tftp_client *, int);
180 int fget_netascii(struct tftp_client *);
181 int fput_netascii(struct tftp_client *, int);
182 void file_read(struct tftp_client *);
183 void tftp_send(struct tftp_client *);
184 int tftp_wrq_ack_packet(struct tftp_client *);
185 void tftp_rrq_ack(int, short, void *);
186 void tftp_wrq_ack(struct tftp_client *client);
187 void tftp_wrq(int, short, void *);
188 void tftp_wrq_end(int, short, void *);
189
190 int parse_options(struct tftp_client *, char *, size_t,
191 struct opt_client *);
192 int validate_access(struct tftp_client *, const char *);
193
194 struct tftp_client *
195 client_alloc(void);
196 void client_free(struct tftp_client *client);
197
198 struct formats {
199 const char *f_mode;
200 int (*f_getc)(struct tftp_client *);
201 int (*f_putc)(struct tftp_client *, int);
202 } formats[] = {
203 { "octet", fget_octet, fput_octet },
204 { "netascii", fget_netascii, fput_netascii },
205 { NULL, NULL }
206 };
207
208 struct errmsg {
209 int e_code;
210 const char *e_msg;
211 } errmsgs[] = {
212 { EUNDEF, "Undefined error code" },
213 { ENOTFOUND, "File not found" },
214 { EACCESS, "Access violation" },
215 { ENOSPACE, "Disk full or allocation exceeded" },
216 { EBADOP, "Illegal TFTP operation" },
217 { EBADID, "Unknown transfer ID" },
218 { EEXISTS, "File already exists" },
219 { ENOUSER, "No such user" },
220 { EOPTNEG, "Option negotiation failed" },
221 { -1, NULL }
222 };
223
224 struct loggers {
225 __dead void (*err)(int, const char *, ...)
226 __attribute__((__format__ (printf, 2, 3)));
227 __dead void (*errx)(int, const char *, ...)
228 __attribute__((__format__ (printf, 2, 3)));
229 void (*warn)(const char *, ...)
230 __attribute__((__format__ (printf, 1, 2)));
231 void (*warnx)(const char *, ...)
232 __attribute__((__format__ (printf, 1, 2)));
233 void (*info)(const char *, ...)
234 __attribute__((__format__ (printf, 1, 2)));
235 void (*debug)(const char *, ...)
236 __attribute__((__format__ (printf, 1, 2)));
237 };
238
239 const struct loggers conslogger = {
240 err,
241 errx,
242 warn,
243 warnx,
244 warnx, /* info */
245 warnx /* debug */
246 };
247
248 __dead void syslog_err(int, const char *, ...)
249 __attribute__((__format__ (printf, 2, 3)));
250 __dead void syslog_errx(int, const char *, ...)
251 __attribute__((__format__ (printf, 2, 3)));
252 void syslog_warn(const char *, ...)
253 __attribute__((__format__ (printf, 1, 2)));
254 void syslog_warnx(const char *, ...)
255 __attribute__((__format__ (printf, 1, 2)));
256 void syslog_info(const char *, ...)
257 __attribute__((__format__ (printf, 1, 2)));
258 void syslog_debug(const char *, ...)
259 __attribute__((__format__ (printf, 1, 2)));
260 void syslog_vstrerror(int, int, const char *, va_list)
261 __attribute__((__format__ (printf, 3, 0)));
262
263 const struct loggers syslogger = {
264 syslog_err,
265 syslog_errx,
266 syslog_warn,
267 syslog_warnx,
268 syslog_info,
269 syslog_debug
270 };
271
272 const struct loggers *logger = &conslogger;
273
274 #define lerr(_e, _f...) logger->err((_e), _f)
275 #define lerrx(_e, _f...) logger->errx((_e), _f)
276 #define lwarn(_f...) logger->warn(_f)
277 #define lwarnx(_f...) logger->warnx(_f)
278 #define linfo(_f...) logger->info(_f)
279 #define ldebug(_f...) logger->debug(_f)
280
281 __dead void
usage(void)282 usage(void)
283 {
284 extern char *__progname;
285 fprintf(stderr, "usage: %s [-46cdivw] [-l address] [-p port] [-r socket]"
286 " directory\n", __progname);
287 exit(1);
288 }
289
290 int cancreate = 0;
291 int canwrite = 0;
292 int verbose = 0;
293 int debug = 0;
294 int iflag = 0;
295
296 int
main(int argc,char * argv[])297 main(int argc, char *argv[])
298 {
299 extern char *__progname;
300
301 int c;
302 struct passwd *pw;
303
304 char *dir = NULL;
305 char *rewrite = NULL;
306
307 char *addr = NULL;
308 char *port = "tftp";
309 int family = AF_UNSPEC;
310 int devnull = -1;
311
312 while ((c = getopt(argc, argv, "46cdil:p:r:vw")) != -1) {
313 switch (c) {
314 case '4':
315 family = AF_INET;
316 break;
317 case '6':
318 family = AF_INET6;
319 break;
320 case 'c':
321 canwrite = cancreate = 1;
322 break;
323 case 'd':
324 verbose = debug = 1;
325 break;
326 case 'i':
327 if (rewrite != NULL)
328 errx(1, "options -i and -r are incompatible");
329 iflag = 1;
330 break;
331 case 'l':
332 addr = optarg;
333 break;
334 case 'p':
335 port = optarg;
336 break;
337 case 'r':
338 if (iflag == 1)
339 errx(1, "options -i and -r are incompatible");
340 rewrite = optarg;
341 break;
342 case 'v':
343 verbose = 1;
344 break;
345 case 'w':
346 canwrite = 1;
347 break;
348 default:
349 usage();
350 /* NOTREACHED */
351 }
352 }
353
354 argc -= optind;
355 argv += optind;
356
357 if (argc != 1)
358 usage();
359
360 dir = argv[0];
361
362 if (geteuid() != 0)
363 errx(1, "need root privileges");
364
365 pw = getpwnam("_tftpd");
366 if (pw == NULL)
367 errx(1, "no _tftpd user");
368
369 if (!debug) {
370 openlog(__progname, LOG_PID|LOG_NDELAY, LOG_DAEMON);
371 tzset();
372 logger = &syslogger;
373 devnull = open(_PATH_DEVNULL, O_RDWR);
374 if (devnull == -1)
375 err(1, "open %s", _PATH_DEVNULL);
376 }
377
378 if (rewrite != NULL)
379 rewrite_connect(rewrite);
380
381 tftpd_listen(addr, port, family);
382
383 if (chroot(dir))
384 err(1, "chroot %s", dir);
385 if (chdir("/"))
386 err(1, "chdir %s", dir);
387
388 /* drop privs */
389 if (setgroups(1, &pw->pw_gid) ||
390 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
391 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
392 errx(1, "can't drop privileges");
393
394 if (!debug && rdaemon(devnull) == -1)
395 err(1, "unable to daemonize");
396
397 if (cancreate) {
398 if (pledge("stdio rpath wpath cpath fattr dns inet", NULL) == -1)
399 lerr(1, "pledge");
400 } else if (canwrite) {
401 if (pledge("stdio rpath wpath dns inet", NULL) == -1)
402 lerr(1, "pledge");
403 } else {
404 if (pledge("stdio rpath dns inet", NULL) == -1)
405 lerr(1, "pledge");
406 }
407
408 event_init();
409
410 if (rewrite != NULL)
411 rewrite_events();
412
413 tftpd_events();
414
415 event_dispatch();
416
417 exit(0);
418 }
419
420 struct rewritemap {
421 struct event wrev;
422 struct event rdev;
423 struct evbuffer *wrbuf;
424 struct evbuffer *rdbuf;
425
426 TAILQ_HEAD(, tftp_client) clients;
427
428 int s;
429 };
430
431 struct rewritemap *rwmap = NULL;
432
433 void
rewrite_connect(const char * path)434 rewrite_connect(const char *path)
435 {
436 int s;
437 struct sockaddr_un remote;
438 size_t len;
439
440 rwmap = malloc(sizeof(*rwmap));
441 if (rwmap == NULL)
442 err(1, "rewrite event malloc");
443
444 rwmap->wrbuf = evbuffer_new();
445 if (rwmap->wrbuf == NULL)
446 err(1, "rewrite wrbuf");
447
448 rwmap->rdbuf = evbuffer_new();
449 if (rwmap->rdbuf == NULL)
450 err(1, "rewrite rdbuf");
451
452 TAILQ_INIT(&rwmap->clients);
453
454 s = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0);
455 if (s == -1)
456 err(1, "rewrite socket");
457
458 remote.sun_family = AF_UNIX;
459 len = strlcpy(remote.sun_path, path, sizeof(remote.sun_path));
460 if (len >= sizeof(remote.sun_path))
461 errx(1, "rewrite socket path is too long");
462
463 len += sizeof(remote.sun_family) + 1;
464 if (connect(s, (struct sockaddr *)&remote, len) == -1)
465 err(1, "%s", path);
466
467 rwmap->s = s;
468 }
469
470 void
rewrite_events(void)471 rewrite_events(void)
472 {
473 event_set(&rwmap->wrev, rwmap->s, EV_WRITE, rewrite_req, NULL);
474 event_set(&rwmap->rdev, rwmap->s, EV_READ | EV_PERSIST, rewrite_res, NULL);
475 event_add(&rwmap->rdev, NULL);
476 }
477
478 void
rewrite_map(struct tftp_client * client,const char * filename)479 rewrite_map(struct tftp_client *client, const char *filename)
480 {
481 char *nicebuf;
482
483 if (stravis(&nicebuf, filename, VIS_SAFE|VIS_OCTAL) == -1)
484 lerr(1, "rwmap stravis");
485
486 if (evbuffer_add_printf(rwmap->wrbuf, "%s %s %s\n", getip(&client->ss),
487 client->opcode == WRQ ? "write" : "read", nicebuf) == -1)
488 lerr(1, "rwmap printf");
489
490 free(nicebuf);
491
492 TAILQ_INSERT_TAIL(&rwmap->clients, client, entry);
493
494 event_add(&rwmap->wrev, NULL);
495 }
496
497 void
rewrite_req(int fd,short events,void * arg)498 rewrite_req(int fd, short events, void *arg)
499 {
500 if (evbuffer_write(rwmap->wrbuf, fd) == -1) {
501 switch (errno) {
502 case EINTR:
503 case EAGAIN:
504 event_add(&rwmap->wrev, NULL);
505 return;
506 }
507
508 lerr(1, "rewrite socket write");
509 }
510
511 if (EVBUFFER_LENGTH(rwmap->wrbuf))
512 event_add(&rwmap->wrev, NULL);
513 }
514
515 void
rewrite_res(int fd,short events,void * arg)516 rewrite_res(int fd, short events, void *arg)
517 {
518 struct tftp_client *client;
519 char *filename;
520 size_t len;
521
522 switch (evbuffer_read(rwmap->rdbuf, fd, PATH_MAX)) {
523 case -1:
524 switch (errno) {
525 case EINTR:
526 case EAGAIN:
527 return;
528 }
529 lerr(1, "rewrite socket read");
530 case 0:
531 lerrx(1, "rewrite socket closed");
532 default:
533 break;
534 }
535
536 while ((filename = evbuffer_readln(rwmap->rdbuf, &len,
537 EVBUFFER_EOL_LF)) != NULL) {
538 client = TAILQ_FIRST(&rwmap->clients);
539 if (client == NULL)
540 lerrx(1, "unexpected rwmap reply");
541
542 TAILQ_REMOVE(&rwmap->clients, client, entry);
543
544 tftp_open(client, filename);
545
546 free(filename);
547 }
548 }
549
550 int
tftpd_listen(const char * addr,const char * port,int family)551 tftpd_listen(const char *addr, const char *port, int family)
552 {
553 struct tftp_server *server;
554
555 struct addrinfo hints, *res, *res0;
556 int error;
557 int s;
558
559 int cerrno = EADDRNOTAVAIL;
560 const char *cause = "getaddrinfo";
561
562 int on = 1;
563
564 memset(&hints, 0, sizeof(hints));
565 hints.ai_family = family;
566 hints.ai_socktype = SOCK_DGRAM;
567 hints.ai_flags = AI_PASSIVE;
568
569 TAILQ_INIT(&tftp_servers);
570
571 error = getaddrinfo(addr, port, &hints, &res0);
572 if (error) {
573 errx(1, "%s:%s: %s", addr ? addr : "*", port,
574 gai_strerror(error));
575 }
576
577 for (res = res0; res != NULL; res = res->ai_next) {
578 s = socket(res->ai_family, res->ai_socktype | SOCK_NONBLOCK,
579 res->ai_protocol);
580 if (s == -1) {
581 cause = "socket";
582 cerrno = errno;
583 continue;
584 }
585
586 if (bind(s, res->ai_addr, res->ai_addrlen) == -1) {
587 cause = "bind";
588 cerrno = errno;
589 close(s);
590 continue;
591 }
592
593 switch (res->ai_family) {
594 case AF_INET:
595 if (setsockopt(s, IPPROTO_IP, IP_RECVDSTADDR,
596 &on, sizeof(on)) == -1)
597 err(1, "setsockopt(IP_RECVDSTADDR)");
598 break;
599 case AF_INET6:
600 if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO,
601 &on, sizeof(on)) == -1)
602 err(1, "setsockopt(IPV6_RECVPKTINFO)");
603 break;
604 }
605
606 server = malloc(sizeof(*server));
607 if (server == NULL)
608 err(1, "malloc");
609
610 server->s = s;
611 TAILQ_INSERT_TAIL(&tftp_servers, server, entry);
612 }
613
614 if (TAILQ_EMPTY(&tftp_servers))
615 errc(1, cerrno, "%s", cause);
616
617 freeaddrinfo(res0);
618 return (0);
619 }
620
621 void
tftpd_events(void)622 tftpd_events(void)
623 {
624 struct tftp_server *server;
625 TAILQ_FOREACH(server, &tftp_servers, entry) {
626 event_set(&server->ev, server->s, EV_READ | EV_PERSIST,
627 tftpd_recv, server);
628 event_add(&server->ev, NULL);
629 }
630 }
631
632 struct tftp_client *
client_alloc(void)633 client_alloc(void)
634 {
635 struct tftp_client *client;
636
637 client = calloc(1, sizeof(*client));
638 if (client == NULL)
639 return (NULL);
640
641 client->segment_size = SEGSIZE;
642 client->packet_size = SEGSIZE + 4;
643
644 client->tv.tv_sec = TIMEOUT;
645 client->tv.tv_usec = 0;
646
647 client->sock = -1;
648 client->file = NULL;
649 client->newline = 0;
650
651 return (client);
652 }
653
654 void
client_free(struct tftp_client * client)655 client_free(struct tftp_client *client)
656 {
657 free(client->options);
658
659 if (client->file != NULL)
660 fclose(client->file);
661
662 close(client->sock);
663
664 free(client);
665 }
666
667 void
tftpd_recv(int fd,short events,void * arg)668 tftpd_recv(int fd, short events, void *arg)
669 {
670 union {
671 struct cmsghdr hdr;
672 char buf[CMSG_SPACE(sizeof(struct sockaddr_storage))];
673 } cmsgbuf;
674 struct cmsghdr *cmsg;
675 struct msghdr msg;
676 struct iovec iov;
677
678 ssize_t n;
679 struct sockaddr_storage s_in;
680 int dobind = 1;
681 int on = 1;
682
683 struct tftphdr *tp;
684
685 struct tftp_client *client;
686
687 client = client_alloc();
688 if (client == NULL) {
689 char buf[SEGSIZE_MAX + 4];
690 /* no memory! flush this request... */
691 recv(fd, buf, SEGSIZE_MAX + 4, 0);
692 /* dont care if it fails */
693 return;
694 }
695
696 bzero(&msg, sizeof(msg));
697 iov.iov_base = client->buf;
698 iov.iov_len = client->packet_size;
699 msg.msg_name = &client->ss;
700 msg.msg_namelen = sizeof(client->ss);
701 msg.msg_iov = &iov;
702 msg.msg_iovlen = 1;
703 msg.msg_control = &cmsgbuf.buf;
704 msg.msg_controllen = sizeof(cmsgbuf.buf);
705
706 n = recvmsg(fd, &msg, 0);
707 if (n == -1) {
708 lwarn("recvmsg");
709 goto err;
710 }
711 if (n < 4)
712 goto err;
713
714 client->sock = socket(client->ss.ss_family,
715 SOCK_DGRAM | SOCK_NONBLOCK, 0);
716 if (client->sock == -1) {
717 lwarn("socket");
718 goto err;
719 }
720 memset(&s_in, 0, sizeof(s_in));
721 s_in.ss_family = client->ss.ss_family;
722 s_in.ss_len = client->ss.ss_len;
723
724 /* get local address if possible */
725 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
726 cmsg = CMSG_NXTHDR(&msg, cmsg)) {
727 if (cmsg->cmsg_level == IPPROTO_IP &&
728 cmsg->cmsg_type == IP_RECVDSTADDR) {
729 memcpy(&((struct sockaddr_in *)&s_in)->sin_addr,
730 CMSG_DATA(cmsg), sizeof(struct in_addr));
731 if (((struct sockaddr_in *)&s_in)->sin_addr.s_addr ==
732 INADDR_BROADCAST)
733 dobind = 0;
734 break;
735 }
736 if (cmsg->cmsg_level == IPPROTO_IPV6 &&
737 cmsg->cmsg_type == IPV6_PKTINFO) {
738 struct in6_pktinfo *ipi;
739
740 ipi = (struct in6_pktinfo *)CMSG_DATA(cmsg);
741 memcpy(&((struct sockaddr_in6 *)&s_in)->sin6_addr,
742 &ipi->ipi6_addr, sizeof(struct in6_addr));
743 if (IN6_IS_ADDR_LINKLOCAL(&ipi->ipi6_addr))
744 ((struct sockaddr_in6 *)&s_in)->sin6_scope_id =
745 ipi->ipi6_ifindex;
746 break;
747 }
748 }
749
750 if (dobind) {
751 setsockopt(client->sock, SOL_SOCKET, SO_REUSEADDR,
752 &on, sizeof(on));
753 setsockopt(client->sock, SOL_SOCKET, SO_REUSEPORT,
754 &on, sizeof(on));
755
756 if (bind(client->sock, (struct sockaddr *)&s_in,
757 s_in.ss_len) == -1) {
758 lwarn("bind to %s", getip(&s_in));
759 goto err;
760 }
761 }
762 if (connect(client->sock, (struct sockaddr *)&client->ss,
763 client->ss.ss_len) == -1) {
764 lwarn("connect to %s", getip(&client->ss));
765 goto err;
766 }
767
768 tp = (struct tftphdr *)client->buf;
769 client->opcode = ntohs(tp->th_opcode);
770 if (client->opcode != RRQ && client->opcode != WRQ) {
771 /* bad request */
772 goto err;
773 }
774
775 tftp(client, tp, n);
776
777 return;
778
779 err:
780 client_free(client);
781 }
782
783 int
parse_options(struct tftp_client * client,char * cp,size_t size,struct opt_client * options)784 parse_options(struct tftp_client *client, char *cp, size_t size,
785 struct opt_client *options)
786 {
787 char *option;
788 char *ccp;
789 int has_options = 0;
790 int i;
791
792 while (++cp < client->buf + size) {
793 for (i = 2, ccp = cp; i > 0; ccp++) {
794 if (ccp >= client->buf + size) {
795 /*
796 * Don't reject the request, just stop trying
797 * to parse the option and get on with it.
798 * Some Apple OpenFirmware versions have
799 * trailing garbage on the end of otherwise
800 * valid requests.
801 */
802 return (has_options);
803 } else if (*ccp == '\0')
804 i--;
805 }
806
807 for (option = cp; *cp; cp++)
808 *cp = tolower((unsigned char)*cp);
809
810 for (i = 0; i < NOPT; i++) {
811 if (strcmp(option, opt_names[i]) == 0) {
812 options[i].o_request = ++cp;
813 has_options = 1;
814 }
815 }
816 cp = ccp - 1;
817 }
818
819 return (has_options);
820 }
821
822 /*
823 * Handle initial connection protocol.
824 */
825 void
tftp(struct tftp_client * client,struct tftphdr * tp,size_t size)826 tftp(struct tftp_client *client, struct tftphdr *tp, size_t size)
827 {
828 struct opt_client *options;
829
830 char *cp;
831 int i, first = 1, ecode, to;
832 struct formats *pf;
833 char *mode = NULL;
834 char filename[PATH_MAX];
835 const char *errstr;
836
837 if (size < 5) {
838 ecode = EBADOP;
839 goto error;
840 }
841
842 cp = tp->th_stuff;
843 again:
844 while (cp < client->buf + size) {
845 if (*cp == '\0')
846 break;
847 cp++;
848 }
849 if (*cp != '\0') {
850 ecode = EBADOP;
851 goto error;
852 }
853 i = cp - tp->th_stuff;
854 if (i >= sizeof(filename)) {
855 ecode = EBADOP;
856 goto error;
857 }
858 memcpy(filename, tp->th_stuff, i);
859 filename[i] = '\0';
860 if (first) {
861 mode = ++cp;
862 first = 0;
863 goto again;
864 }
865 for (cp = mode; *cp; cp++)
866 *cp = tolower((unsigned char)*cp);
867
868 for (pf = formats; pf->f_mode; pf++) {
869 if (strcmp(pf->f_mode, mode) == 0)
870 break;
871 }
872 if (pf->f_mode == 0) {
873 ecode = EBADOP;
874 goto error;
875 }
876 client->fgetc = pf->f_getc;
877 client->fputc = pf->f_putc;
878
879 client->options = options = calloc(NOPT, sizeof(*client->options));
880 if (options == NULL) {
881 ecode = 100 + ENOMEM;
882 goto error;
883 }
884
885 if (parse_options(client, cp, size, options)) {
886 if (options[OPT_TIMEOUT].o_request != NULL) {
887 to = strtonum(options[OPT_TIMEOUT].o_request,
888 TIMEOUT_MIN, TIMEOUT_MAX, &errstr);
889 if (errstr) {
890 ecode = EBADOP;
891 goto error;
892 }
893 options[OPT_TIMEOUT].o_reply = client->tv.tv_sec = to;
894 }
895
896 if (options[OPT_BLKSIZE].o_request) {
897 client->segment_size = strtonum(
898 options[OPT_BLKSIZE].o_request,
899 SEGSIZE_MIN, SEGSIZE_MAX, &errstr);
900 if (errstr) {
901 ecode = EBADOP;
902 goto error;
903 }
904 client->packet_size = client->segment_size + 4;
905 options[OPT_BLKSIZE].o_reply = client->segment_size;
906 }
907 } else {
908 free(options);
909 client->options = NULL;
910 }
911
912 if (verbose) {
913 char nicebuf[PATH_MAX];
914
915 (void)strnvis(nicebuf, filename, PATH_MAX,
916 VIS_SAFE|VIS_OCTAL);
917
918 linfo("%s: %s request for '%s'", getip(&client->ss),
919 client->opcode == WRQ ? "write" : "read", nicebuf);
920 }
921
922 if (rwmap != NULL)
923 rewrite_map(client, filename);
924 else
925 tftp_open(client, filename);
926
927 return;
928
929 error:
930 nak(client, ecode);
931 }
932
933 void
tftp_open(struct tftp_client * client,const char * filename)934 tftp_open(struct tftp_client *client, const char *filename)
935 {
936 int ecode;
937
938 ecode = validate_access(client, filename);
939 if (ecode)
940 goto error;
941
942 if (client->options) {
943 if (oack(client) == -1)
944 goto error;
945
946 free(client->options);
947 client->options = NULL;
948 } else if (client->opcode == WRQ) {
949 recvfile(client);
950 } else
951 sendfile(client);
952
953 return;
954 error:
955 nak(client, ecode);
956 }
957
958 /*
959 * Validate file access. Since we
960 * have no uid or gid, for now require
961 * file to exist and be publicly
962 * readable/writable.
963 * If we were invoked with arguments
964 * from inetd then the file must also be
965 * in one of the given directory prefixes.
966 * Note also, full path name must be
967 * given as we have no login directory.
968 */
969 int
validate_access(struct tftp_client * client,const char * requested)970 validate_access(struct tftp_client *client, const char *requested)
971 {
972 int mode = client->opcode;
973 struct opt_client *options = client->options;
974 struct stat stbuf;
975 int fd, wmode;
976 const char *errstr, *filename;
977 char rewritten[PATH_MAX];
978
979 if (!canwrite && mode != RRQ)
980 return (EACCESS);
981
982 if (strcmp(requested, SEEDPATH) == 0) {
983 char *buf;
984 if (mode != RRQ)
985 return (EACCESS);
986
987 buf = client->buf + sizeof(client->buf) - 512;
988 arc4random_buf(buf, 512);
989 if (options != NULL && options[OPT_TSIZE].o_request)
990 options[OPT_TSIZE].o_reply = 512;
991 client->file = fmemopen(buf, 512, "r");
992 if (client->file == NULL)
993 return (errno + 100);
994
995 return (0);
996 }
997
998 if (iflag) {
999 int ret;
1000
1001 /*
1002 * In -i mode, look in the directory named after the
1003 * client address.
1004 */
1005 ret = snprintf(rewritten, sizeof(rewritten), "%s/%s",
1006 getip(&client->ss), requested);
1007 if (ret < 0 || ret >= sizeof(rewritten))
1008 return (ENAMETOOLONG + 100);
1009 filename = rewritten;
1010 } else {
1011 retryread:
1012 filename = requested;
1013 }
1014
1015 /*
1016 * We use a different permissions scheme if `cancreate' is
1017 * set.
1018 */
1019 wmode = O_TRUNC;
1020 if (stat(filename, &stbuf) == -1) {
1021 if (!cancreate) {
1022 /*
1023 * In -i mode, retry failed read requests from
1024 * the root directory.
1025 */
1026 if (mode == RRQ && errno == ENOENT &&
1027 filename == rewritten)
1028 goto retryread;
1029 return (errno == ENOENT ? ENOTFOUND : EACCESS);
1030 } else {
1031 if ((errno == ENOENT) && (mode != RRQ))
1032 wmode |= O_CREAT;
1033 else
1034 return (EACCESS);
1035 }
1036 } else {
1037 if (mode == RRQ) {
1038 if ((stbuf.st_mode & (S_IRUSR >> 6)) == 0)
1039 return (EACCESS);
1040 } else {
1041 if ((stbuf.st_mode & (S_IWUSR >> 6)) == 0)
1042 return (EACCESS);
1043 }
1044 }
1045
1046 if (options != NULL && options[OPT_TSIZE].o_request) {
1047 if (mode == RRQ)
1048 options[OPT_TSIZE].o_reply = stbuf.st_size;
1049 else {
1050 /* allows writes of 65535 blocks * SEGSIZE_MAX bytes */
1051 options[OPT_TSIZE].o_reply =
1052 strtonum(options[OPT_TSIZE].o_request,
1053 1, 65535LL * SEGSIZE_MAX, &errstr);
1054 if (errstr)
1055 return (EOPTNEG);
1056 }
1057 }
1058 fd = open(filename, mode == RRQ ? O_RDONLY : (O_WRONLY|wmode), 0666);
1059 if (fd == -1)
1060 return (errno + 100);
1061 /*
1062 * If the file was created, set default permissions.
1063 */
1064 if ((wmode & O_CREAT) && fchmod(fd, 0666) == -1) {
1065 int serrno = errno;
1066
1067 close(fd);
1068 unlink(filename);
1069
1070 return (serrno + 100);
1071 }
1072 client->file = fdopen(fd, mode == RRQ ? "r" : "w");
1073 if (client->file == NULL) {
1074 close(fd);
1075 return (errno + 100);
1076 }
1077
1078 return (0);
1079 }
1080
1081 int
fget_octet(struct tftp_client * client)1082 fget_octet(struct tftp_client *client)
1083 {
1084 return (getc(client->file));
1085 }
1086
1087 int
fput_octet(struct tftp_client * client,int c)1088 fput_octet(struct tftp_client *client, int c)
1089 {
1090 return (putc(c, client->file));
1091 }
1092
1093 int
fget_netascii(struct tftp_client * client)1094 fget_netascii(struct tftp_client *client)
1095 {
1096 int c = -1;
1097
1098 switch (client->newline) {
1099 case 0:
1100 c = getc(client->file);
1101 if (c == EOF)
1102 break;
1103
1104 if (c == '\n' || c == '\r') {
1105 client->newline = c;
1106 c = '\r';
1107 }
1108 break;
1109 case '\n':
1110 client->newline = 0;
1111 c = '\n';
1112 break;
1113 case '\r':
1114 client->newline = 0;
1115 c = '\0';
1116 break;
1117 }
1118
1119 return (c);
1120 }
1121
1122 int
fput_netascii(struct tftp_client * client,int c)1123 fput_netascii(struct tftp_client *client, int c)
1124 {
1125 if (client->newline == '\r') {
1126 client->newline = 0;
1127
1128 if (c == '\0')
1129 c = '\r';
1130
1131 } else if (c == '\r') {
1132 client->newline = c;
1133 return (c);
1134 }
1135
1136 return (putc(c, client->file));
1137 }
1138
1139 void
sendfile(struct tftp_client * client)1140 sendfile(struct tftp_client *client)
1141 {
1142 event_set(&client->sev, client->sock, EV_READ, tftp_rrq_ack, client);
1143 client->block = 1;
1144
1145 file_read(client);
1146 }
1147
1148 void
file_read(struct tftp_client * client)1149 file_read(struct tftp_client *client)
1150 {
1151 u_int8_t *buf;
1152 struct tftphdr *dp;
1153 int i;
1154 int c;
1155
1156 dp = (struct tftphdr *)client->buf;
1157 dp->th_opcode = htons((u_short)DATA);
1158 dp->th_block = htons(client->block);
1159 buf = (u_int8_t *)dp->th_data;
1160
1161 for (i = 0; i < client->segment_size; i++) {
1162 c = client->fgetc(client);
1163 if (c == EOF) {
1164 if (ferror(client->file)) {
1165 nak(client, 100 + EIO);
1166 return;
1167 }
1168
1169 break;
1170 }
1171 buf[i] = c;
1172 }
1173
1174 client->buflen = i + 4;
1175 client->retries = RETRIES;
1176
1177 tftp_send(client);
1178 }
1179
1180 void
tftp_send(struct tftp_client * client)1181 tftp_send(struct tftp_client *client)
1182 {
1183 if (send(client->sock, client->buf, client->buflen, 0) == -1) {
1184 lwarn("send(block)");
1185 client_free(client);
1186 return;
1187 }
1188
1189 event_add(&client->sev, &client->tv);
1190 }
1191
1192 void
tftp_rrq_ack(int fd,short events,void * arg)1193 tftp_rrq_ack(int fd, short events, void *arg)
1194 {
1195 struct tftp_client *client = arg;
1196 struct tftphdr *ap; /* ack packet */
1197 char rbuf[SEGSIZE_MIN];
1198 ssize_t n;
1199
1200 if (events & EV_TIMEOUT) {
1201 if (retry(client) == -1) {
1202 lwarn("%s: retry", getip(&client->ss));
1203 goto done;
1204 }
1205
1206 return;
1207 }
1208
1209 n = recv(fd, rbuf, sizeof(rbuf), 0);
1210 if (n == -1) {
1211 switch (errno) {
1212 case EINTR:
1213 case EAGAIN:
1214 event_add(&client->sev, &client->tv);
1215 return;
1216
1217 default:
1218 lwarn("%s: recv", getip(&client->ss));
1219 goto done;
1220 }
1221 }
1222
1223 ap = (struct tftphdr *)rbuf;
1224 ap->th_opcode = ntohs((u_short)ap->th_opcode);
1225 ap->th_block = ntohs((u_short)ap->th_block);
1226
1227 switch (ap->th_opcode) {
1228 case ACK:
1229 break;
1230 case ERROR:
1231 default: /* assume the worst */
1232 goto done;
1233 }
1234
1235 if (ap->th_block != client->block) {
1236 if (tftp_flush(client) == -1) {
1237 lwarnx("%s: flush", getip(&client->ss));
1238 goto done;
1239 }
1240
1241 if (ap->th_block != (client->block - 1))
1242 goto done;
1243
1244 tftp_send(client);
1245 return;
1246 }
1247
1248 if (client->buflen != client->packet_size) {
1249 /* this was the last packet in the stream */
1250 goto done;
1251 }
1252
1253 client->block++;
1254 file_read(client);
1255 return;
1256
1257 done:
1258 client_free(client);
1259 }
1260
1261 int
tftp_flush(struct tftp_client * client)1262 tftp_flush(struct tftp_client *client)
1263 {
1264 char rbuf[SEGSIZE_MIN];
1265 ssize_t n;
1266
1267 for (;;) {
1268 n = recv(client->sock, rbuf, sizeof(rbuf), 0);
1269 if (n == -1) {
1270 switch (errno) {
1271 case EAGAIN:
1272 return (0);
1273
1274 case EINTR:
1275 break;
1276
1277 default:
1278 return (-1);
1279 }
1280 }
1281 }
1282 }
1283
1284 void
recvfile(struct tftp_client * client)1285 recvfile(struct tftp_client *client)
1286 {
1287 event_set(&client->sev, client->sock, EV_READ, tftp_wrq, client);
1288 tftp_wrq_ack(client);
1289 }
1290
1291 int
tftp_wrq_ack_packet(struct tftp_client * client)1292 tftp_wrq_ack_packet(struct tftp_client *client)
1293 {
1294 struct tftphdr *ap; /* ack packet */
1295
1296 ap = (struct tftphdr *)client->buf;
1297 ap->th_opcode = htons((u_short)ACK);
1298 ap->th_block = htons(client->block);
1299
1300 client->buflen = 4;
1301 client->retries = RETRIES;
1302
1303 return (send(client->sock, client->buf, client->buflen, 0) != 4);
1304 }
1305
1306 void
tftp_wrq_ack(struct tftp_client * client)1307 tftp_wrq_ack(struct tftp_client *client)
1308 {
1309 if (tftp_wrq_ack_packet(client) != 0) {
1310 lwarn("tftp wrq ack");
1311 client_free(client);
1312 return;
1313 }
1314
1315 client->block++;
1316 event_add(&client->sev, &client->tv);
1317 }
1318
1319 void
tftp_wrq(int fd,short events,void * arg)1320 tftp_wrq(int fd, short events, void *arg)
1321 {
1322 char wbuf[SEGSIZE_MAX + 4];
1323 struct tftp_client *client = arg;
1324 struct tftphdr *dp;
1325 ssize_t n;
1326 int i;
1327
1328 if (events & EV_TIMEOUT) {
1329 if (retry(client) == -1) {
1330 lwarn("%s", getip(&client->ss));
1331 goto done;
1332 }
1333
1334 return;
1335 }
1336
1337 n = recv(fd, wbuf, client->packet_size, 0);
1338 if (n == -1) {
1339 switch (errno) {
1340 case EINTR:
1341 case EAGAIN:
1342 goto retry;
1343
1344 default:
1345 lwarn("tftp_wrq recv");
1346 goto done;
1347 }
1348 }
1349
1350 if (n < 4)
1351 goto done;
1352
1353 dp = (struct tftphdr *)wbuf;
1354 dp->th_opcode = ntohs((u_short)dp->th_opcode);
1355 dp->th_block = ntohs((u_short)dp->th_block);
1356
1357 switch (dp->th_opcode) {
1358 case ERROR:
1359 goto done;
1360 case DATA:
1361 break;
1362 default:
1363 goto retry;
1364 }
1365
1366 if (dp->th_block != client->block) {
1367 if (tftp_flush(client) == -1) {
1368 lwarnx("%s: flush", getip(&client->ss));
1369 goto done;
1370 }
1371
1372 if (dp->th_block != (client->block - 1))
1373 goto done;
1374
1375 goto retry;
1376 }
1377
1378 for (i = 4; i < n; i++) {
1379 if (client->fputc(client, wbuf[i]) == EOF) {
1380 lwarn("tftp wrq");
1381 goto done;
1382 }
1383 }
1384
1385 if (n < client->packet_size) {
1386 tftp_wrq_ack_packet(client);
1387 fclose(client->file);
1388 client->file = NULL;
1389 event_set(&client->sev, client->sock, EV_READ,
1390 tftp_wrq_end, client);
1391 event_add(&client->sev, &client->tv);
1392 return;
1393 }
1394
1395 tftp_wrq_ack(client);
1396 return;
1397
1398 retry:
1399 event_add(&client->sev, &client->tv);
1400 return;
1401 done:
1402 client_free(client);
1403 }
1404
1405 void
tftp_wrq_end(int fd,short events,void * arg)1406 tftp_wrq_end(int fd, short events, void *arg)
1407 {
1408 char wbuf[SEGSIZE_MAX + 4];
1409 struct tftp_client *client = arg;
1410 struct tftphdr *dp;
1411 ssize_t n;
1412
1413 if (events & EV_TIMEOUT) {
1414 /* this was the last packet, we can clean up */
1415 goto done;
1416 }
1417
1418 n = recv(fd, wbuf, client->packet_size, 0);
1419 if (n == -1) {
1420 switch (errno) {
1421 case EINTR:
1422 case EAGAIN:
1423 goto retry;
1424
1425 default:
1426 lwarn("tftp_wrq_end recv");
1427 goto done;
1428 }
1429 }
1430
1431 if (n < 4)
1432 goto done;
1433
1434 dp = (struct tftphdr *)wbuf;
1435 dp->th_opcode = ntohs((u_short)dp->th_opcode);
1436 dp->th_block = ntohs((u_short)dp->th_block);
1437
1438 switch (dp->th_opcode) {
1439 case ERROR:
1440 goto done;
1441 case DATA:
1442 break;
1443 default:
1444 goto retry;
1445 }
1446
1447 if (dp->th_block != client->block)
1448 goto done;
1449
1450 retry:
1451 if (retry(client) == -1) {
1452 lwarn("%s", getip(&client->ss));
1453 goto done;
1454 }
1455 return;
1456 done:
1457 client_free(client);
1458 return;
1459 }
1460
1461
1462 /*
1463 * Send a nak packet (error message).
1464 * Error code passed in is one of the
1465 * standard TFTP codes, or a UNIX errno
1466 * offset by 100.
1467 */
1468 void
nak(struct tftp_client * client,int error)1469 nak(struct tftp_client *client, int error)
1470 {
1471 struct tftphdr *tp;
1472 struct errmsg *pe;
1473 size_t length;
1474 ssize_t rslt;
1475
1476 tp = (struct tftphdr *)client->buf;
1477 tp->th_opcode = htons((u_short)ERROR);
1478 tp->th_code = htons((u_short)error);
1479
1480 for (pe = errmsgs; pe->e_code >= 0; pe++) {
1481 if (pe->e_code == error)
1482 break;
1483 }
1484 if (pe->e_code < 0) {
1485 pe->e_msg = strerror(error - 100);
1486 tp->th_code = htons(EUNDEF); /* set 'undef' errorcode */
1487 }
1488
1489 length = strlcpy(tp->th_msg, pe->e_msg, client->packet_size - 5) + 5;
1490 if (length > client->packet_size)
1491 length = client->packet_size;
1492
1493 linfo("%s: nak: %s", getip(&client->ss), tp->th_msg);
1494
1495 rslt = send(client->sock, client->buf, length, 0);
1496 if (rslt == -1)
1497 lwarn("%s: nak", getip(&client->ss));
1498 else if ((size_t)rslt != length)
1499 lwarnx("%s: nak: sent %zd of %zu bytes", getip(&client->ss),
1500 rslt, length);
1501
1502 client_free(client);
1503 }
1504
1505 /*
1506 * Send an oack packet (option acknowledgement).
1507 */
1508 int
oack(struct tftp_client * client)1509 oack(struct tftp_client *client)
1510 {
1511 struct opt_client *options = client->options;
1512 struct tftphdr *tp;
1513 char *bp;
1514 int i, n, size;
1515
1516 tp = (struct tftphdr *)client->buf;
1517 bp = (char *)tp->th_stuff;
1518 size = sizeof(client->buf) - 2;
1519
1520 tp->th_opcode = htons((u_short)OACK);
1521 for (i = 0; i < NOPT; i++) {
1522 if (options[i].o_request == NULL)
1523 continue;
1524
1525 n = snprintf(bp, size, "%s%c%lld", opt_names[i], '\0',
1526 options[i].o_reply);
1527 if (n < 0 || n >= size) {
1528 lwarnx("oack: no buffer space");
1529 goto error;
1530 }
1531
1532 bp += n + 1;
1533 size -= n + 1;
1534 if (size < 0) {
1535 lwarnx("oack: no buffer space");
1536 goto error;
1537 }
1538 }
1539
1540 client->buflen = bp - client->buf;
1541 client->retries = RETRIES;
1542
1543 if (send(client->sock, client->buf, client->buflen, 0) == -1) {
1544 lwarn("oack");
1545 goto error;
1546 }
1547
1548 /* no client ACK for write requests with options */
1549 if (client->opcode == WRQ) {
1550 client->block = 1;
1551 event_set(&client->sev, client->sock, EV_READ,
1552 tftp_wrq, client);
1553 } else
1554 event_set(&client->sev, client->sock, EV_READ,
1555 oack_done, client);
1556
1557 event_add(&client->sev, &client->tv);
1558 return (0);
1559
1560 error:
1561 return (-1);
1562 }
1563
1564 int
retry(struct tftp_client * client)1565 retry(struct tftp_client *client)
1566 {
1567 if (--client->retries == 0) {
1568 errno = ETIMEDOUT;
1569 return (-1);
1570 }
1571
1572 tftp_send(client);
1573
1574 return (0);
1575 }
1576
1577 void
oack_done(int fd,short events,void * arg)1578 oack_done(int fd, short events, void *arg)
1579 {
1580 struct tftp_client *client = arg;
1581 struct tftphdr *ap;
1582 ssize_t n;
1583
1584 if (events & EV_TIMEOUT) {
1585 if (retry(client) == -1) {
1586 lwarn("%s", getip(&client->ss));
1587 goto done;
1588 }
1589
1590 return;
1591 }
1592
1593 n = recv(client->sock, client->buf, client->packet_size, 0);
1594 if (n == -1) {
1595 switch (errno) {
1596 case EINTR:
1597 case EAGAIN:
1598 event_add(&client->sev, &client->tv);
1599 return;
1600
1601 default:
1602 lwarn("%s: recv", getip(&client->ss));
1603 goto done;
1604 }
1605 }
1606
1607 if (n < 4)
1608 goto done;
1609
1610 ap = (struct tftphdr *)client->buf;
1611 ap->th_opcode = ntohs((u_short)ap->th_opcode);
1612 ap->th_block = ntohs((u_short)ap->th_block);
1613
1614 if (ap->th_opcode != ACK || ap->th_block != 0)
1615 goto done;
1616
1617 sendfile(client);
1618 return;
1619
1620 done:
1621 client_free(client);
1622 }
1623
1624 const char *
getip(void * s)1625 getip(void *s)
1626 {
1627 struct sockaddr *sa = s;
1628 static char hbuf[NI_MAXHOST];
1629
1630 if (getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf),
1631 NULL, 0, NI_NUMERICHOST))
1632 strlcpy(hbuf, "0.0.0.0", sizeof(hbuf));
1633
1634 return(hbuf);
1635 }
1636
1637 /* daemon(3) clone, intended to be used in a "r"estricted environment */
1638 int
rdaemon(int devnull)1639 rdaemon(int devnull)
1640 {
1641 if (devnull == -1) {
1642 errno = EBADF;
1643 return (-1);
1644 }
1645 if (fcntl(devnull, F_GETFL) == -1)
1646 return (-1);
1647
1648 switch (fork()) {
1649 case -1:
1650 return (-1);
1651 case 0:
1652 break;
1653 default:
1654 _exit(0);
1655 }
1656
1657 if (setsid() == -1)
1658 return (-1);
1659
1660 (void)dup2(devnull, STDIN_FILENO);
1661 (void)dup2(devnull, STDOUT_FILENO);
1662 (void)dup2(devnull, STDERR_FILENO);
1663 if (devnull > 2)
1664 (void)close(devnull);
1665
1666 return (0);
1667 }
1668
1669 void
syslog_vstrerror(int e,int priority,const char * fmt,va_list ap)1670 syslog_vstrerror(int e, int priority, const char *fmt, va_list ap)
1671 {
1672 char *s;
1673
1674 if (vasprintf(&s, fmt, ap) == -1) {
1675 syslog(LOG_EMERG, "unable to alloc in syslog_vstrerror");
1676 exit(1);
1677 }
1678
1679 syslog(priority, "%s: %s", s, strerror(e));
1680
1681 free(s);
1682 }
1683
1684 void
syslog_err(int ecode,const char * fmt,...)1685 syslog_err(int ecode, const char *fmt, ...)
1686 {
1687 va_list ap;
1688
1689 va_start(ap, fmt);
1690 syslog_vstrerror(errno, LOG_CRIT, fmt, ap);
1691 va_end(ap);
1692
1693 exit(ecode);
1694 }
1695
1696 void
syslog_errx(int ecode,const char * fmt,...)1697 syslog_errx(int ecode, const char *fmt, ...)
1698 {
1699 va_list ap;
1700
1701 va_start(ap, fmt);
1702 vsyslog(LOG_CRIT, fmt, ap);
1703 va_end(ap);
1704
1705 exit(ecode);
1706 }
1707
1708 void
syslog_warn(const char * fmt,...)1709 syslog_warn(const char *fmt, ...)
1710 {
1711 va_list ap;
1712
1713 va_start(ap, fmt);
1714 syslog_vstrerror(errno, LOG_ERR, fmt, ap);
1715 va_end(ap);
1716 }
1717
1718 void
syslog_warnx(const char * fmt,...)1719 syslog_warnx(const char *fmt, ...)
1720 {
1721 va_list ap;
1722
1723 va_start(ap, fmt);
1724 vsyslog(LOG_ERR, fmt, ap);
1725 va_end(ap);
1726 }
1727
1728 void
syslog_info(const char * fmt,...)1729 syslog_info(const char *fmt, ...)
1730 {
1731 va_list ap;
1732
1733 va_start(ap, fmt);
1734 vsyslog(LOG_INFO, fmt, ap);
1735 va_end(ap);
1736 }
1737
1738 void
syslog_debug(const char * fmt,...)1739 syslog_debug(const char *fmt, ...)
1740 {
1741 va_list ap;
1742
1743 if (!debug)
1744 return;
1745
1746 va_start(ap, fmt);
1747 vsyslog(LOG_DEBUG, fmt, ap);
1748 va_end(ap);
1749 }
1750