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