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 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 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 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 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 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 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 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 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 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 * 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 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 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 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 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 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 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 1082 fget_octet(struct tftp_client *client) 1083 { 1084 return (getc(client->file)); 1085 } 1086 1087 int 1088 fput_octet(struct tftp_client *client, int c) 1089 { 1090 return (putc(c, client->file)); 1091 } 1092 1093 int 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 * 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 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 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 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 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 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 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 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 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