1 /* $OpenBSD: tftpd.c,v 1.44 2020/01/09 22:29:27 dlg 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 #ifdef __KAME__ 733 if (IN6_IS_ADDR_LINKLOCAL(&ipi->ipi6_addr)) 734 ((struct sockaddr_in6 *)&s_in)->sin6_scope_id = 735 ipi->ipi6_ifindex; 736 #endif 737 break; 738 } 739 } 740 741 if (dobind) { 742 setsockopt(client->sock, SOL_SOCKET, SO_REUSEADDR, 743 &on, sizeof(on)); 744 setsockopt(client->sock, SOL_SOCKET, SO_REUSEPORT, 745 &on, sizeof(on)); 746 747 if (bind(client->sock, (struct sockaddr *)&s_in, 748 s_in.ss_len) == -1) { 749 lwarn("bind to %s", getip(&s_in)); 750 goto err; 751 } 752 } 753 if (connect(client->sock, (struct sockaddr *)&client->ss, 754 client->ss.ss_len) == -1) { 755 lwarn("connect to %s", getip(&client->ss)); 756 goto err; 757 } 758 759 tp = (struct tftphdr *)client->buf; 760 client->opcode = ntohs(tp->th_opcode); 761 if (client->opcode != RRQ && client->opcode != WRQ) { 762 /* bad request */ 763 goto err; 764 } 765 766 tftp(client, tp, n); 767 768 return; 769 770 err: 771 client_free(client); 772 } 773 774 int 775 parse_options(struct tftp_client *client, char *cp, size_t size, 776 struct opt_client *options) 777 { 778 char *option; 779 char *ccp; 780 int has_options = 0; 781 int i; 782 783 while (++cp < client->buf + size) { 784 for (i = 2, ccp = cp; i > 0; ccp++) { 785 if (ccp >= client->buf + size) { 786 /* 787 * Don't reject the request, just stop trying 788 * to parse the option and get on with it. 789 * Some Apple OpenFirmware versions have 790 * trailing garbage on the end of otherwise 791 * valid requests. 792 */ 793 return (has_options); 794 } else if (*ccp == '\0') 795 i--; 796 } 797 798 for (option = cp; *cp; cp++) 799 *cp = tolower((unsigned char)*cp); 800 801 for (i = 0; i < NOPT; i++) { 802 if (strcmp(option, opt_names[i]) == 0) { 803 options[i].o_request = ++cp; 804 has_options = 1; 805 } 806 } 807 cp = ccp - 1; 808 } 809 810 return (has_options); 811 } 812 813 /* 814 * Handle initial connection protocol. 815 */ 816 void 817 tftp(struct tftp_client *client, struct tftphdr *tp, size_t size) 818 { 819 struct opt_client *options; 820 821 char *cp; 822 int i, first = 1, ecode, to; 823 struct formats *pf; 824 char *mode = NULL; 825 char filename[PATH_MAX]; 826 const char *errstr; 827 828 if (size < 5) { 829 ecode = EBADOP; 830 goto error; 831 } 832 833 cp = tp->th_stuff; 834 again: 835 while (cp < client->buf + size) { 836 if (*cp == '\0') 837 break; 838 cp++; 839 } 840 if (*cp != '\0') { 841 ecode = EBADOP; 842 goto error; 843 } 844 i = cp - tp->th_stuff; 845 if (i >= sizeof(filename)) { 846 ecode = EBADOP; 847 goto error; 848 } 849 memcpy(filename, tp->th_stuff, i); 850 filename[i] = '\0'; 851 if (first) { 852 mode = ++cp; 853 first = 0; 854 goto again; 855 } 856 for (cp = mode; *cp; cp++) 857 *cp = tolower((unsigned char)*cp); 858 859 for (pf = formats; pf->f_mode; pf++) { 860 if (strcmp(pf->f_mode, mode) == 0) 861 break; 862 } 863 if (pf->f_mode == 0) { 864 ecode = EBADOP; 865 goto error; 866 } 867 client->fgetc = pf->f_getc; 868 client->fputc = pf->f_putc; 869 870 client->options = options = calloc(NOPT, sizeof(*client->options)); 871 if (options == NULL) { 872 ecode = 100 + ENOMEM; 873 goto error; 874 } 875 876 if (parse_options(client, cp, size, options)) { 877 if (options[OPT_TIMEOUT].o_request != NULL) { 878 to = strtonum(options[OPT_TIMEOUT].o_request, 879 TIMEOUT_MIN, TIMEOUT_MAX, &errstr); 880 if (errstr) { 881 ecode = EBADOP; 882 goto error; 883 } 884 options[OPT_TIMEOUT].o_reply = client->tv.tv_sec = to; 885 } 886 887 if (options[OPT_BLKSIZE].o_request) { 888 client->segment_size = strtonum( 889 options[OPT_BLKSIZE].o_request, 890 SEGSIZE_MIN, SEGSIZE_MAX, &errstr); 891 if (errstr) { 892 ecode = EBADOP; 893 goto error; 894 } 895 client->packet_size = client->segment_size + 4; 896 options[OPT_BLKSIZE].o_reply = client->segment_size; 897 } 898 } else { 899 free(options); 900 client->options = NULL; 901 } 902 903 if (verbose) { 904 char nicebuf[PATH_MAX]; 905 906 (void)strnvis(nicebuf, filename, PATH_MAX, 907 VIS_SAFE|VIS_OCTAL); 908 909 linfo("%s: %s request for '%s'", getip(&client->ss), 910 client->opcode == WRQ ? "write" : "read", nicebuf); 911 } 912 913 if (rwmap != NULL) 914 rewrite_map(client, filename); 915 else 916 tftp_open(client, filename); 917 918 return; 919 920 error: 921 nak(client, ecode); 922 } 923 924 void 925 tftp_open(struct tftp_client *client, const char *filename) 926 { 927 int ecode; 928 929 ecode = validate_access(client, filename); 930 if (ecode) 931 goto error; 932 933 if (client->options) { 934 if (oack(client) == -1) 935 goto error; 936 937 free(client->options); 938 client->options = NULL; 939 } else if (client->opcode == WRQ) { 940 recvfile(client); 941 } else 942 sendfile(client); 943 944 return; 945 error: 946 nak(client, ecode); 947 } 948 949 /* 950 * Validate file access. Since we 951 * have no uid or gid, for now require 952 * file to exist and be publicly 953 * readable/writable. 954 * If we were invoked with arguments 955 * from inetd then the file must also be 956 * in one of the given directory prefixes. 957 * Note also, full path name must be 958 * given as we have no login directory. 959 */ 960 int 961 validate_access(struct tftp_client *client, const char *requested) 962 { 963 int mode = client->opcode; 964 struct opt_client *options = client->options; 965 struct stat stbuf; 966 int fd, wmode; 967 const char *errstr, *filename; 968 char rewritten[PATH_MAX]; 969 970 if (strcmp(requested, SEEDPATH) == 0) { 971 char *buf; 972 if (mode != RRQ) 973 return (EACCESS); 974 975 buf = client->buf + sizeof(client->buf) - 512; 976 arc4random_buf(buf, 512); 977 if (options != NULL && options[OPT_TSIZE].o_request) 978 options[OPT_TSIZE].o_reply = 512; 979 client->file = fmemopen(buf, 512, "r"); 980 if (client->file == NULL) 981 return (errno + 100); 982 983 return (0); 984 } 985 986 if (iflag) { 987 int ret; 988 989 /* 990 * In -i mode, look in the directory named after the 991 * client address. 992 */ 993 ret = snprintf(rewritten, sizeof(rewritten), "%s/%s", 994 getip(&client->ss), requested); 995 if (ret < 0 || ret >= sizeof(rewritten)) 996 return (ENAMETOOLONG + 100); 997 filename = rewritten; 998 } else { 999 retryread: 1000 filename = requested; 1001 } 1002 1003 /* 1004 * We use a different permissions scheme if `cancreate' is 1005 * set. 1006 */ 1007 wmode = O_TRUNC; 1008 if (stat(filename, &stbuf) == -1) { 1009 if (!cancreate) { 1010 /* 1011 * In -i mode, retry failed read requests from 1012 * the root directory. 1013 */ 1014 if (mode == RRQ && errno == ENOENT && 1015 filename == rewritten) 1016 goto retryread; 1017 return (errno == ENOENT ? ENOTFOUND : EACCESS); 1018 } else { 1019 if ((errno == ENOENT) && (mode != RRQ)) 1020 wmode |= O_CREAT; 1021 else 1022 return (EACCESS); 1023 } 1024 } else { 1025 if (mode == RRQ) { 1026 if ((stbuf.st_mode & (S_IRUSR >> 6)) == 0) 1027 return (EACCESS); 1028 } else { 1029 if ((stbuf.st_mode & (S_IWUSR >> 6)) == 0) 1030 return (EACCESS); 1031 } 1032 } 1033 1034 if (options != NULL && options[OPT_TSIZE].o_request) { 1035 if (mode == RRQ) 1036 options[OPT_TSIZE].o_reply = stbuf.st_size; 1037 else { 1038 /* allows writes of 65535 blocks * SEGSIZE_MAX bytes */ 1039 options[OPT_TSIZE].o_reply = 1040 strtonum(options[OPT_TSIZE].o_request, 1041 1, 65535LL * SEGSIZE_MAX, &errstr); 1042 if (errstr) 1043 return (EOPTNEG); 1044 } 1045 } 1046 fd = open(filename, mode == RRQ ? O_RDONLY : (O_WRONLY|wmode), 0666); 1047 if (fd == -1) 1048 return (errno + 100); 1049 /* 1050 * If the file was created, set default permissions. 1051 */ 1052 if ((wmode & O_CREAT) && fchmod(fd, 0666) == -1) { 1053 int serrno = errno; 1054 1055 close(fd); 1056 unlink(filename); 1057 1058 return (serrno + 100); 1059 } 1060 client->file = fdopen(fd, mode == RRQ ? "r" : "w"); 1061 if (client->file == NULL) { 1062 close(fd); 1063 return (errno + 100); 1064 } 1065 1066 return (0); 1067 } 1068 1069 int 1070 fget_octet(struct tftp_client *client) 1071 { 1072 return (getc(client->file)); 1073 } 1074 1075 int 1076 fput_octet(struct tftp_client *client, int c) 1077 { 1078 return (putc(c, client->file)); 1079 } 1080 1081 int 1082 fget_netascii(struct tftp_client *client) 1083 { 1084 int c = -1; 1085 1086 switch (client->newline) { 1087 case 0: 1088 c = getc(client->file); 1089 if (c == EOF) 1090 break; 1091 1092 if (c == '\n' || c == '\r') { 1093 client->newline = c; 1094 c = '\r'; 1095 } 1096 break; 1097 case '\n': 1098 client->newline = 0; 1099 c = '\n'; 1100 break; 1101 case '\r': 1102 client->newline = 0; 1103 c = '\0'; 1104 break; 1105 } 1106 1107 return (c); 1108 } 1109 1110 int 1111 fput_netascii(struct tftp_client *client, int c) 1112 { 1113 if (client->newline == '\r') { 1114 client->newline = 0; 1115 1116 if (c == '\0') 1117 c = '\r'; 1118 1119 } else if (c == '\r') { 1120 client->newline = c; 1121 return (c); 1122 } 1123 1124 return (putc(c, client->file)); 1125 } 1126 1127 void 1128 sendfile(struct tftp_client *client) 1129 { 1130 event_set(&client->sev, client->sock, EV_READ, tftp_rrq_ack, client); 1131 client->block = 1; 1132 1133 file_read(client); 1134 } 1135 1136 void 1137 file_read(struct tftp_client *client) 1138 { 1139 u_int8_t *buf; 1140 struct tftphdr *dp; 1141 int i; 1142 int c; 1143 1144 dp = (struct tftphdr *)client->buf; 1145 dp->th_opcode = htons((u_short)DATA); 1146 dp->th_block = htons(client->block); 1147 buf = (u_int8_t *)dp->th_data; 1148 1149 for (i = 0; i < client->segment_size; i++) { 1150 c = client->fgetc(client); 1151 if (c == EOF) { 1152 if (ferror(client->file)) { 1153 nak(client, 100 + EIO); 1154 return; 1155 } 1156 1157 break; 1158 } 1159 buf[i] = c; 1160 } 1161 1162 client->buflen = i + 4; 1163 client->retries = RETRIES; 1164 1165 tftp_send(client); 1166 } 1167 1168 void 1169 tftp_send(struct tftp_client *client) 1170 { 1171 if (send(client->sock, client->buf, client->buflen, 0) == -1) { 1172 lwarn("send(block)"); 1173 client_free(client); 1174 return; 1175 } 1176 1177 event_add(&client->sev, &client->tv); 1178 } 1179 1180 void 1181 tftp_rrq_ack(int fd, short events, void *arg) 1182 { 1183 struct tftp_client *client = arg; 1184 struct tftphdr *ap; /* ack packet */ 1185 char rbuf[SEGSIZE_MIN]; 1186 ssize_t n; 1187 1188 if (events & EV_TIMEOUT) { 1189 if (retry(client) == -1) { 1190 lwarn("%s: retry", getip(&client->ss)); 1191 goto done; 1192 } 1193 1194 return; 1195 } 1196 1197 n = recv(fd, rbuf, sizeof(rbuf), 0); 1198 if (n == -1) { 1199 switch (errno) { 1200 case EINTR: 1201 case EAGAIN: 1202 event_add(&client->sev, &client->tv); 1203 return; 1204 1205 default: 1206 lwarn("%s: recv", getip(&client->ss)); 1207 goto done; 1208 } 1209 } 1210 1211 ap = (struct tftphdr *)rbuf; 1212 ap->th_opcode = ntohs((u_short)ap->th_opcode); 1213 ap->th_block = ntohs((u_short)ap->th_block); 1214 1215 switch (ap->th_opcode) { 1216 case ACK: 1217 break; 1218 case ERROR: 1219 default: /* assume the worst */ 1220 goto done; 1221 } 1222 1223 if (ap->th_block != client->block) { 1224 if (tftp_flush(client) == -1) { 1225 lwarnx("%s: flush", getip(&client->ss)); 1226 goto done; 1227 } 1228 1229 if (ap->th_block != (client->block - 1)) 1230 goto done; 1231 1232 tftp_send(client); 1233 return; 1234 } 1235 1236 if (client->buflen != client->packet_size) { 1237 /* this was the last packet in the stream */ 1238 goto done; 1239 } 1240 1241 client->block++; 1242 file_read(client); 1243 return; 1244 1245 done: 1246 client_free(client); 1247 } 1248 1249 int 1250 tftp_flush(struct tftp_client *client) 1251 { 1252 char rbuf[SEGSIZE_MIN]; 1253 ssize_t n; 1254 1255 for (;;) { 1256 n = recv(client->sock, rbuf, sizeof(rbuf), 0); 1257 if (n == -1) { 1258 switch (errno) { 1259 case EAGAIN: 1260 return (0); 1261 1262 case EINTR: 1263 break; 1264 1265 default: 1266 return (-1); 1267 } 1268 } 1269 } 1270 } 1271 1272 void 1273 recvfile(struct tftp_client *client) 1274 { 1275 event_set(&client->sev, client->sock, EV_READ, tftp_wrq, client); 1276 tftp_wrq_ack(client); 1277 } 1278 1279 int 1280 tftp_wrq_ack_packet(struct tftp_client *client) 1281 { 1282 struct tftphdr *ap; /* ack packet */ 1283 1284 ap = (struct tftphdr *)client->buf; 1285 ap->th_opcode = htons((u_short)ACK); 1286 ap->th_block = htons(client->block); 1287 1288 client->buflen = 4; 1289 client->retries = RETRIES; 1290 1291 return (send(client->sock, client->buf, client->buflen, 0) != 4); 1292 } 1293 1294 void 1295 tftp_wrq_ack(struct tftp_client *client) 1296 { 1297 if (tftp_wrq_ack_packet(client) != 0) { 1298 lwarn("tftp wrq ack"); 1299 client_free(client); 1300 return; 1301 } 1302 1303 client->block++; 1304 event_add(&client->sev, &client->tv); 1305 } 1306 1307 void 1308 tftp_wrq(int fd, short events, void *arg) 1309 { 1310 char wbuf[SEGSIZE_MAX + 4]; 1311 struct tftp_client *client = arg; 1312 struct tftphdr *dp; 1313 ssize_t n; 1314 int i; 1315 1316 if (events & EV_TIMEOUT) { 1317 if (retry(client) == -1) { 1318 lwarn("%s", getip(&client->ss)); 1319 goto done; 1320 } 1321 1322 return; 1323 } 1324 1325 n = recv(fd, wbuf, client->packet_size, 0); 1326 if (n == -1) { 1327 switch (errno) { 1328 case EINTR: 1329 case EAGAIN: 1330 goto retry; 1331 1332 default: 1333 lwarn("tftp_wrq recv"); 1334 goto done; 1335 } 1336 } 1337 1338 if (n < 4) 1339 goto done; 1340 1341 dp = (struct tftphdr *)wbuf; 1342 dp->th_opcode = ntohs((u_short)dp->th_opcode); 1343 dp->th_block = ntohs((u_short)dp->th_block); 1344 1345 switch (dp->th_opcode) { 1346 case ERROR: 1347 goto done; 1348 case DATA: 1349 break; 1350 default: 1351 goto retry; 1352 } 1353 1354 if (dp->th_block != client->block) { 1355 if (tftp_flush(client) == -1) { 1356 lwarnx("%s: flush", getip(&client->ss)); 1357 goto done; 1358 } 1359 1360 if (dp->th_block != (client->block - 1)) 1361 goto done; 1362 1363 goto retry; 1364 } 1365 1366 for (i = 4; i < n; i++) { 1367 if (client->fputc(client, wbuf[i]) == EOF) { 1368 lwarn("tftp wrq"); 1369 goto done; 1370 } 1371 } 1372 1373 if (n < client->packet_size) { 1374 tftp_wrq_ack_packet(client); 1375 fclose(client->file); 1376 client->file = NULL; 1377 event_set(&client->sev, client->sock, EV_READ, 1378 tftp_wrq_end, client); 1379 event_add(&client->sev, &client->tv); 1380 return; 1381 } 1382 1383 tftp_wrq_ack(client); 1384 return; 1385 1386 retry: 1387 event_add(&client->sev, &client->tv); 1388 return; 1389 done: 1390 client_free(client); 1391 } 1392 1393 void 1394 tftp_wrq_end(int fd, short events, void *arg) 1395 { 1396 char wbuf[SEGSIZE_MAX + 4]; 1397 struct tftp_client *client = arg; 1398 struct tftphdr *dp; 1399 ssize_t n; 1400 1401 if (events & EV_TIMEOUT) { 1402 /* this was the last packet, we can clean up */ 1403 goto done; 1404 } 1405 1406 n = recv(fd, wbuf, client->packet_size, 0); 1407 if (n == -1) { 1408 switch (errno) { 1409 case EINTR: 1410 case EAGAIN: 1411 goto retry; 1412 1413 default: 1414 lwarn("tftp_wrq_end recv"); 1415 goto done; 1416 } 1417 } 1418 1419 if (n < 4) 1420 goto done; 1421 1422 dp = (struct tftphdr *)wbuf; 1423 dp->th_opcode = ntohs((u_short)dp->th_opcode); 1424 dp->th_block = ntohs((u_short)dp->th_block); 1425 1426 switch (dp->th_opcode) { 1427 case ERROR: 1428 goto done; 1429 case DATA: 1430 break; 1431 default: 1432 goto retry; 1433 } 1434 1435 if (dp->th_block != client->block) 1436 goto done; 1437 1438 retry: 1439 if (retry(client) == -1) { 1440 lwarn("%s", getip(&client->ss)); 1441 goto done; 1442 } 1443 return; 1444 done: 1445 client_free(client); 1446 return; 1447 } 1448 1449 1450 /* 1451 * Send a nak packet (error message). 1452 * Error code passed in is one of the 1453 * standard TFTP codes, or a UNIX errno 1454 * offset by 100. 1455 */ 1456 void 1457 nak(struct tftp_client *client, int error) 1458 { 1459 struct tftphdr *tp; 1460 struct errmsg *pe; 1461 size_t length; 1462 1463 tp = (struct tftphdr *)client->buf; 1464 tp->th_opcode = htons((u_short)ERROR); 1465 tp->th_code = htons((u_short)error); 1466 1467 for (pe = errmsgs; pe->e_code >= 0; pe++) { 1468 if (pe->e_code == error) 1469 break; 1470 } 1471 if (pe->e_code < 0) { 1472 pe->e_msg = strerror(error - 100); 1473 tp->th_code = htons(EUNDEF); /* set 'undef' errorcode */ 1474 } 1475 1476 length = strlcpy(tp->th_msg, pe->e_msg, client->packet_size - 5) + 5; 1477 if (length > client->packet_size) 1478 length = client->packet_size; 1479 1480 if (send(client->sock, client->buf, length, 0) != length) 1481 lwarn("nak"); 1482 1483 client_free(client); 1484 } 1485 1486 /* 1487 * Send an oack packet (option acknowledgement). 1488 */ 1489 int 1490 oack(struct tftp_client *client) 1491 { 1492 struct opt_client *options = client->options; 1493 struct tftphdr *tp; 1494 char *bp; 1495 int i, n, size; 1496 1497 tp = (struct tftphdr *)client->buf; 1498 bp = (char *)tp->th_stuff; 1499 size = sizeof(client->buf) - 2; 1500 1501 tp->th_opcode = htons((u_short)OACK); 1502 for (i = 0; i < NOPT; i++) { 1503 if (options[i].o_request == NULL) 1504 continue; 1505 1506 n = snprintf(bp, size, "%s%c%lld", opt_names[i], '\0', 1507 options[i].o_reply); 1508 if (n < 0 || n >= size) { 1509 lwarnx("oack: no buffer space"); 1510 goto error; 1511 } 1512 1513 bp += n + 1; 1514 size -= n + 1; 1515 if (size < 0) { 1516 lwarnx("oack: no buffer space"); 1517 goto error; 1518 } 1519 } 1520 1521 client->buflen = bp - client->buf; 1522 client->retries = RETRIES; 1523 1524 if (send(client->sock, client->buf, client->buflen, 0) == -1) { 1525 lwarn("oack"); 1526 goto error; 1527 } 1528 1529 /* no client ACK for write requests with options */ 1530 if (client->opcode == WRQ) { 1531 client->block = 1; 1532 event_set(&client->sev, client->sock, EV_READ, 1533 tftp_wrq, client); 1534 } else 1535 event_set(&client->sev, client->sock, EV_READ, 1536 oack_done, client); 1537 1538 event_add(&client->sev, &client->tv); 1539 return (0); 1540 1541 error: 1542 return (-1); 1543 } 1544 1545 int 1546 retry(struct tftp_client *client) 1547 { 1548 if (--client->retries == 0) { 1549 errno = ETIMEDOUT; 1550 return (-1); 1551 } 1552 1553 tftp_send(client); 1554 1555 return (0); 1556 } 1557 1558 void 1559 oack_done(int fd, short events, void *arg) 1560 { 1561 struct tftp_client *client = arg; 1562 struct tftphdr *ap; 1563 ssize_t n; 1564 1565 if (events & EV_TIMEOUT) { 1566 if (retry(client) == -1) { 1567 lwarn("%s", getip(&client->ss)); 1568 goto done; 1569 } 1570 1571 return; 1572 } 1573 1574 n = recv(client->sock, client->buf, client->packet_size, 0); 1575 if (n == -1) { 1576 switch (errno) { 1577 case EINTR: 1578 case EAGAIN: 1579 event_add(&client->sev, &client->tv); 1580 return; 1581 1582 default: 1583 lwarn("%s: recv", getip(&client->ss)); 1584 goto done; 1585 } 1586 } 1587 1588 if (n < 4) 1589 goto done; 1590 1591 ap = (struct tftphdr *)client->buf; 1592 ap->th_opcode = ntohs((u_short)ap->th_opcode); 1593 ap->th_block = ntohs((u_short)ap->th_block); 1594 1595 if (ap->th_opcode != ACK || ap->th_block != 0) 1596 goto done; 1597 1598 sendfile(client); 1599 return; 1600 1601 done: 1602 client_free(client); 1603 } 1604 1605 const char * 1606 getip(void *s) 1607 { 1608 struct sockaddr *sa = s; 1609 static char hbuf[NI_MAXHOST]; 1610 1611 if (getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), 1612 NULL, 0, NI_NUMERICHOST)) 1613 strlcpy(hbuf, "0.0.0.0", sizeof(hbuf)); 1614 1615 return(hbuf); 1616 } 1617 1618 /* daemon(3) clone, intended to be used in a "r"estricted environment */ 1619 int 1620 rdaemon(int devnull) 1621 { 1622 if (devnull == -1) { 1623 errno = EBADF; 1624 return (-1); 1625 } 1626 if (fcntl(devnull, F_GETFL) == -1) 1627 return (-1); 1628 1629 switch (fork()) { 1630 case -1: 1631 return (-1); 1632 case 0: 1633 break; 1634 default: 1635 _exit(0); 1636 } 1637 1638 if (setsid() == -1) 1639 return (-1); 1640 1641 (void)dup2(devnull, STDIN_FILENO); 1642 (void)dup2(devnull, STDOUT_FILENO); 1643 (void)dup2(devnull, STDERR_FILENO); 1644 if (devnull > 2) 1645 (void)close(devnull); 1646 1647 return (0); 1648 } 1649 1650 void 1651 syslog_vstrerror(int e, int priority, const char *fmt, va_list ap) 1652 { 1653 char *s; 1654 1655 if (vasprintf(&s, fmt, ap) == -1) { 1656 syslog(LOG_EMERG, "unable to alloc in syslog_vstrerror"); 1657 exit(1); 1658 } 1659 1660 syslog(priority, "%s: %s", s, strerror(e)); 1661 1662 free(s); 1663 } 1664 1665 void 1666 syslog_err(int ecode, const char *fmt, ...) 1667 { 1668 va_list ap; 1669 1670 va_start(ap, fmt); 1671 syslog_vstrerror(errno, LOG_CRIT, fmt, ap); 1672 va_end(ap); 1673 1674 exit(ecode); 1675 } 1676 1677 void 1678 syslog_errx(int ecode, const char *fmt, ...) 1679 { 1680 va_list ap; 1681 1682 va_start(ap, fmt); 1683 vsyslog(LOG_CRIT, fmt, ap); 1684 va_end(ap); 1685 1686 exit(ecode); 1687 } 1688 1689 void 1690 syslog_warn(const char *fmt, ...) 1691 { 1692 va_list ap; 1693 1694 va_start(ap, fmt); 1695 syslog_vstrerror(errno, LOG_ERR, fmt, ap); 1696 va_end(ap); 1697 } 1698 1699 void 1700 syslog_warnx(const char *fmt, ...) 1701 { 1702 va_list ap; 1703 1704 va_start(ap, fmt); 1705 vsyslog(LOG_ERR, fmt, ap); 1706 va_end(ap); 1707 } 1708 1709 void 1710 syslog_info(const char *fmt, ...) 1711 { 1712 va_list ap; 1713 1714 va_start(ap, fmt); 1715 vsyslog(LOG_INFO, fmt, ap); 1716 va_end(ap); 1717 } 1718 1719 void 1720 syslog_debug(const char *fmt, ...) 1721 { 1722 va_list ap; 1723 1724 if (!debug) 1725 return; 1726 1727 va_start(ap, fmt); 1728 vsyslog(LOG_DEBUG, fmt, ap); 1729 va_end(ap); 1730 } 1731