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