1 /* 2 * Copyright (c) 1983, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #ifndef lint 35 static const char copyright[] = 36 "@(#) Copyright (c) 1983, 1993\n\ 37 The Regents of the University of California. All rights reserved.\n"; 38 #endif /* not lint */ 39 40 #ifndef lint 41 #if 0 42 static char sccsid[] = "@(#)tftpd.c 8.1 (Berkeley) 6/4/93"; 43 #endif 44 static const char rcsid[] = 45 "$FreeBSD$"; 46 #endif /* not lint */ 47 48 /* 49 * Trivial file transfer protocol server. 50 * 51 * This version includes many modifications by Jim Guyton 52 * <guyton@rand-unix>. 53 */ 54 55 #include <sys/param.h> 56 #include <sys/ioctl.h> 57 #include <sys/stat.h> 58 #include <sys/socket.h> 59 #include <sys/types.h> 60 61 #include <netinet/in.h> 62 #include <arpa/tftp.h> 63 #include <arpa/inet.h> 64 65 #include <ctype.h> 66 #include <errno.h> 67 #include <fcntl.h> 68 #include <libutil.h> 69 #include <netdb.h> 70 #include <pwd.h> 71 #include <setjmp.h> 72 #include <signal.h> 73 #include <stdio.h> 74 #include <stdlib.h> 75 #include <string.h> 76 #include <syslog.h> 77 #include <unistd.h> 78 79 #include "tftpsubs.h" 80 81 #define TIMEOUT 5 82 #define MAX_TIMEOUTS 5 83 84 int peer; 85 int rexmtval = TIMEOUT; 86 int max_rexmtval = 2*TIMEOUT; 87 88 #define PKTSIZE SEGSIZE+4 89 char buf[PKTSIZE]; 90 char ackbuf[PKTSIZE]; 91 struct sockaddr_storage from; 92 int fromlen; 93 94 void tftp(struct tftphdr *, int); 95 static void unmappedaddr(struct sockaddr_in6 *); 96 97 /* 98 * Null-terminated directory prefix list for absolute pathname requests and 99 * search list for relative pathname requests. 100 * 101 * MAXDIRS should be at least as large as the number of arguments that 102 * inetd allows (currently 20). 103 */ 104 #define MAXDIRS 20 105 static struct dirlist { 106 char *name; 107 int len; 108 } dirs[MAXDIRS+1]; 109 static int suppress_naks; 110 static int logging; 111 static int ipchroot; 112 113 static char *errtomsg(int); 114 static void nak(int); 115 static void oack(); 116 117 int 118 main(int argc, char *argv[]) 119 { 120 struct tftphdr *tp; 121 int n; 122 int ch, on; 123 struct sockaddr_storage me; 124 int len; 125 char *chroot_dir = NULL; 126 struct passwd *nobody; 127 char *chuser = "nobody"; 128 129 openlog("tftpd", LOG_PID | LOG_NDELAY, LOG_FTP); 130 while ((ch = getopt(argc, argv, "cClns:u:")) != -1) { 131 switch (ch) { 132 case 'c': 133 ipchroot = 1; 134 break; 135 case 'C': 136 ipchroot = 2; 137 break; 138 case 'l': 139 logging = 1; 140 break; 141 case 'n': 142 suppress_naks = 1; 143 break; 144 case 's': 145 chroot_dir = optarg; 146 break; 147 case 'u': 148 chuser = optarg; 149 break; 150 default: 151 syslog(LOG_WARNING, "ignoring unknown option -%c", ch); 152 } 153 } 154 if (optind < argc) { 155 struct dirlist *dirp; 156 157 /* Get list of directory prefixes. Skip relative pathnames. */ 158 for (dirp = dirs; optind < argc && dirp < &dirs[MAXDIRS]; 159 optind++) { 160 if (argv[optind][0] == '/') { 161 dirp->name = argv[optind]; 162 dirp->len = strlen(dirp->name); 163 dirp++; 164 } 165 } 166 } 167 else if (chroot_dir) { 168 dirs->name = "/"; 169 dirs->len = 1; 170 } 171 if (ipchroot && chroot_dir == NULL) { 172 syslog(LOG_ERR, "-c requires -s"); 173 exit(1); 174 } 175 176 on = 1; 177 if (ioctl(0, FIONBIO, &on) < 0) { 178 syslog(LOG_ERR, "ioctl(FIONBIO): %m"); 179 exit(1); 180 } 181 fromlen = sizeof (from); 182 n = recvfrom(0, buf, sizeof (buf), 0, 183 (struct sockaddr *)&from, &fromlen); 184 if (n < 0) { 185 syslog(LOG_ERR, "recvfrom: %m"); 186 exit(1); 187 } 188 /* 189 * Now that we have read the message out of the UDP 190 * socket, we fork and exit. Thus, inetd will go back 191 * to listening to the tftp port, and the next request 192 * to come in will start up a new instance of tftpd. 193 * 194 * We do this so that inetd can run tftpd in "wait" mode. 195 * The problem with tftpd running in "nowait" mode is that 196 * inetd may get one or more successful "selects" on the 197 * tftp port before we do our receive, so more than one 198 * instance of tftpd may be started up. Worse, if tftpd 199 * break before doing the above "recvfrom", inetd would 200 * spawn endless instances, clogging the system. 201 */ 202 { 203 int pid; 204 int i, j; 205 206 for (i = 1; i < 20; i++) { 207 pid = fork(); 208 if (pid < 0) { 209 sleep(i); 210 /* 211 * flush out to most recently sent request. 212 * 213 * This may drop some request, but those 214 * will be resent by the clients when 215 * they timeout. The positive effect of 216 * this flush is to (try to) prevent more 217 * than one tftpd being started up to service 218 * a single request from a single client. 219 */ 220 j = sizeof from; 221 i = recvfrom(0, buf, sizeof (buf), 0, 222 (struct sockaddr *)&from, &j); 223 if (i > 0) { 224 n = i; 225 fromlen = j; 226 } 227 } else { 228 break; 229 } 230 } 231 if (pid < 0) { 232 syslog(LOG_ERR, "fork: %m"); 233 exit(1); 234 } else if (pid != 0) { 235 exit(0); 236 } 237 } 238 239 /* 240 * Since we exit here, we should do that only after the above 241 * recvfrom to keep inetd from constantly forking should there 242 * be a problem. See the above comment about system clogging. 243 */ 244 if (chroot_dir) { 245 if (ipchroot) { 246 char *tempchroot; 247 struct stat sb; 248 int statret; 249 struct sockaddr_storage ss; 250 char hbuf[NI_MAXHOST]; 251 252 memcpy(&ss, &from, from.ss_len); 253 unmappedaddr((struct sockaddr_in6 *)&ss); 254 getnameinfo((struct sockaddr *)&ss, ss.ss_len, 255 hbuf, sizeof(hbuf), NULL, 0, 256 NI_NUMERICHOST | NI_WITHSCOPEID); 257 asprintf(&tempchroot, "%s/%s", chroot_dir, hbuf); 258 statret = stat(tempchroot, &sb); 259 if ((sb.st_mode & S_IFDIR) && 260 (statret == 0 || (statret == -1 && ipchroot == 1))) 261 chroot_dir = tempchroot; 262 } 263 /* Must get this before chroot because /etc might go away */ 264 if ((nobody = getpwnam(chuser)) == NULL) { 265 syslog(LOG_ERR, "%s: no such user", chuser); 266 exit(1); 267 } 268 if (chroot(chroot_dir)) { 269 syslog(LOG_ERR, "chroot: %s: %m", chroot_dir); 270 exit(1); 271 } 272 chdir( "/" ); 273 setuid(nobody->pw_uid); 274 setgroups(1, &nobody->pw_gid); 275 } 276 277 len = sizeof(me); 278 if (getsockname(0, (struct sockaddr *)&me, &len) == 0) { 279 switch (me.ss_family) { 280 case AF_INET: 281 ((struct sockaddr_in *)&me)->sin_port = 0; 282 break; 283 case AF_INET6: 284 ((struct sockaddr_in6 *)&me)->sin6_port = 0; 285 break; 286 default: 287 /* unsupported */ 288 break; 289 } 290 } else { 291 memset(&me, 0, sizeof(me)); 292 me.ss_family = from.ss_family; 293 me.ss_len = from.ss_len; 294 } 295 alarm(0); 296 close(0); 297 close(1); 298 peer = socket(from.ss_family, SOCK_DGRAM, 0); 299 if (peer < 0) { 300 syslog(LOG_ERR, "socket: %m"); 301 exit(1); 302 } 303 if (bind(peer, (struct sockaddr *)&me, me.ss_len) < 0) { 304 syslog(LOG_ERR, "bind: %m"); 305 exit(1); 306 } 307 if (connect(peer, (struct sockaddr *)&from, from.ss_len) < 0) { 308 syslog(LOG_ERR, "connect: %m"); 309 exit(1); 310 } 311 tp = (struct tftphdr *)buf; 312 tp->th_opcode = ntohs(tp->th_opcode); 313 if (tp->th_opcode == RRQ || tp->th_opcode == WRQ) 314 tftp(tp, n); 315 exit(1); 316 } 317 318 struct formats; 319 int validate_access(char **, int); 320 void xmitfile(struct formats *); 321 void recvfile(struct formats *); 322 323 struct formats { 324 char *f_mode; 325 int (*f_validate)(char **, int); 326 void (*f_send)(struct formats *); 327 void (*f_recv)(struct formats *); 328 int f_convert; 329 } formats[] = { 330 { "netascii", validate_access, xmitfile, recvfile, 1 }, 331 { "octet", validate_access, xmitfile, recvfile, 0 }, 332 #ifdef notdef 333 { "mail", validate_user, sendmail, recvmail, 1 }, 334 #endif 335 { 0 } 336 }; 337 338 struct options { 339 char *o_type; 340 char *o_request; 341 int o_reply; /* turn into union if need be */ 342 } options[] = { 343 { "tsize" }, /* OPT_TSIZE */ 344 { "timeout" }, /* OPT_TIMEOUT */ 345 { NULL } 346 }; 347 348 enum opt_enum { 349 OPT_TSIZE = 0, 350 OPT_TIMEOUT, 351 }; 352 353 /* 354 * Handle initial connection protocol. 355 */ 356 void 357 tftp(struct tftphdr *tp, int size) 358 { 359 char *cp; 360 int i, first = 1, has_options = 0, ecode; 361 struct formats *pf; 362 char *filename, *mode, *option, *ccp; 363 364 filename = cp = tp->th_stuff; 365 again: 366 while (cp < buf + size) { 367 if (*cp == '\0') 368 break; 369 cp++; 370 } 371 if (*cp != '\0') { 372 nak(EBADOP); 373 exit(1); 374 } 375 if (first) { 376 mode = ++cp; 377 first = 0; 378 goto again; 379 } 380 for (cp = mode; *cp; cp++) 381 if (isupper(*cp)) 382 *cp = tolower(*cp); 383 for (pf = formats; pf->f_mode; pf++) 384 if (strcmp(pf->f_mode, mode) == 0) 385 break; 386 if (pf->f_mode == 0) { 387 nak(EBADOP); 388 exit(1); 389 } 390 while (++cp < buf + size) { 391 for (i = 2, ccp = cp; i > 0; ccp++) { 392 if (ccp >= buf + size) { 393 /* 394 * Don't reject the request, just stop trying 395 * to parse the option and get on with it. 396 * Some Apple OpenFirmware versions have 397 * trailing garbage on the end of otherwise 398 * valid requests. 399 */ 400 goto option_fail; 401 } else if (*ccp == '\0') 402 i--; 403 } 404 for (option = cp; *cp; cp++) 405 if (isupper(*cp)) 406 *cp = tolower(*cp); 407 for (i = 0; options[i].o_type != NULL; i++) 408 if (strcmp(option, options[i].o_type) == 0) { 409 options[i].o_request = ++cp; 410 has_options = 1; 411 } 412 cp = ccp-1; 413 } 414 415 option_fail: 416 if (options[OPT_TIMEOUT].o_request) { 417 int to = atoi(options[OPT_TIMEOUT].o_request); 418 if (to < 1 || to > 255) { 419 nak(EBADOP); 420 exit(1); 421 } 422 else if (to <= max_rexmtval) 423 options[OPT_TIMEOUT].o_reply = rexmtval = to; 424 else 425 options[OPT_TIMEOUT].o_request = NULL; 426 } 427 428 ecode = (*pf->f_validate)(&filename, tp->th_opcode); 429 if (has_options) 430 oack(); 431 if (logging) { 432 char hbuf[NI_MAXHOST]; 433 434 getnameinfo((struct sockaddr *)&from, from.ss_len, 435 hbuf, sizeof(hbuf), NULL, 0, 436 NI_WITHSCOPEID); 437 syslog(LOG_INFO, "%s: %s request for %s: %s", hbuf, 438 tp->th_opcode == WRQ ? "write" : "read", 439 filename, errtomsg(ecode)); 440 } 441 if (ecode) { 442 /* 443 * Avoid storms of naks to a RRQ broadcast for a relative 444 * bootfile pathname from a diskless Sun. 445 */ 446 if (suppress_naks && *filename != '/' && ecode == ENOTFOUND) 447 exit(0); 448 nak(ecode); 449 exit(1); 450 } 451 if (tp->th_opcode == WRQ) 452 (*pf->f_recv)(pf); 453 else 454 (*pf->f_send)(pf); 455 exit(0); 456 } 457 458 459 FILE *file; 460 461 /* 462 * Validate file access. Since we 463 * have no uid or gid, for now require 464 * file to exist and be publicly 465 * readable/writable. 466 * If we were invoked with arguments 467 * from inetd then the file must also be 468 * in one of the given directory prefixes. 469 * Note also, full path name must be 470 * given as we have no login directory. 471 */ 472 int 473 validate_access(char **filep, int mode) 474 { 475 struct stat stbuf; 476 int fd; 477 struct dirlist *dirp; 478 static char pathname[MAXPATHLEN]; 479 char *filename = *filep; 480 481 /* 482 * Prevent tricksters from getting around the directory restrictions 483 */ 484 if (strstr(filename, "/../")) 485 return (EACCESS); 486 487 if (*filename == '/') { 488 /* 489 * Allow the request if it's in one of the approved locations. 490 * Special case: check the null prefix ("/") by looking 491 * for length = 1 and relying on the arg. processing that 492 * it's a /. 493 */ 494 for (dirp = dirs; dirp->name != NULL; dirp++) { 495 if (dirp->len == 1 || 496 (!strncmp(filename, dirp->name, dirp->len) && 497 filename[dirp->len] == '/')) 498 break; 499 } 500 /* If directory list is empty, allow access to any file */ 501 if (dirp->name == NULL && dirp != dirs) 502 return (EACCESS); 503 if (stat(filename, &stbuf) < 0) 504 return (errno == ENOENT ? ENOTFOUND : EACCESS); 505 if ((stbuf.st_mode & S_IFMT) != S_IFREG) 506 return (ENOTFOUND); 507 if (mode == RRQ) { 508 if ((stbuf.st_mode & S_IROTH) == 0) 509 return (EACCESS); 510 } else { 511 if ((stbuf.st_mode & S_IWOTH) == 0) 512 return (EACCESS); 513 } 514 } else { 515 int err; 516 517 /* 518 * Relative file name: search the approved locations for it. 519 * Don't allow write requests that avoid directory 520 * restrictions. 521 */ 522 523 if (!strncmp(filename, "../", 3)) 524 return (EACCESS); 525 526 /* 527 * If the file exists in one of the directories and isn't 528 * readable, continue looking. However, change the error code 529 * to give an indication that the file exists. 530 */ 531 err = ENOTFOUND; 532 for (dirp = dirs; dirp->name != NULL; dirp++) { 533 snprintf(pathname, sizeof(pathname), "%s/%s", 534 dirp->name, filename); 535 if (stat(pathname, &stbuf) == 0 && 536 (stbuf.st_mode & S_IFMT) == S_IFREG) { 537 if ((stbuf.st_mode & S_IROTH) != 0) { 538 break; 539 } 540 err = EACCESS; 541 } 542 } 543 if (dirp->name == NULL) 544 return (err); 545 *filep = filename = pathname; 546 } 547 if (options[OPT_TSIZE].o_request) { 548 if (mode == RRQ) 549 options[OPT_TSIZE].o_reply = stbuf.st_size; 550 else 551 /* XXX Allows writes of all sizes. */ 552 options[OPT_TSIZE].o_reply = 553 atoi(options[OPT_TSIZE].o_request); 554 } 555 fd = open(filename, mode == RRQ ? O_RDONLY : O_WRONLY|O_TRUNC); 556 if (fd < 0) 557 return (errno + 100); 558 file = fdopen(fd, (mode == RRQ)? "r":"w"); 559 if (file == NULL) { 560 return errno+100; 561 } 562 return (0); 563 } 564 565 int timeouts; 566 jmp_buf timeoutbuf; 567 568 void 569 timer(int sig __unused) 570 { 571 if (++timeouts > MAX_TIMEOUTS) 572 exit(1); 573 longjmp(timeoutbuf, 1); 574 } 575 576 /* 577 * Send the requested file. 578 */ 579 void 580 xmitfile(struct formats *pf) 581 { 582 struct tftphdr *dp, *r_init(); 583 struct tftphdr *ap; /* ack packet */ 584 int size, n; 585 volatile unsigned short block; 586 587 signal(SIGALRM, timer); 588 dp = r_init(); 589 ap = (struct tftphdr *)ackbuf; 590 block = 1; 591 do { 592 size = readit(file, &dp, pf->f_convert); 593 if (size < 0) { 594 nak(errno + 100); 595 goto abort; 596 } 597 dp->th_opcode = htons((u_short)DATA); 598 dp->th_block = htons((u_short)block); 599 timeouts = 0; 600 (void)setjmp(timeoutbuf); 601 602 send_data: 603 { 604 int i, t = 1; 605 for (i = 0; ; i++){ 606 if (send(peer, dp, size + 4, 0) != size + 4) { 607 sleep(t); 608 t = (t < 32) ? t<< 1 : t; 609 if (i >= 12) { 610 syslog(LOG_ERR, "write: %m"); 611 goto abort; 612 } 613 } 614 break; 615 } 616 } 617 read_ahead(file, pf->f_convert); 618 for ( ; ; ) { 619 alarm(rexmtval); /* read the ack */ 620 n = recv(peer, ackbuf, sizeof (ackbuf), 0); 621 alarm(0); 622 if (n < 0) { 623 syslog(LOG_ERR, "read: %m"); 624 goto abort; 625 } 626 ap->th_opcode = ntohs((u_short)ap->th_opcode); 627 ap->th_block = ntohs((u_short)ap->th_block); 628 629 if (ap->th_opcode == ERROR) 630 goto abort; 631 632 if (ap->th_opcode == ACK) { 633 if (ap->th_block == block) 634 break; 635 /* Re-synchronize with the other side */ 636 (void) synchnet(peer); 637 if (ap->th_block == (block -1)) 638 goto send_data; 639 } 640 641 } 642 block++; 643 } while (size == SEGSIZE); 644 abort: 645 (void) fclose(file); 646 } 647 648 void 649 justquit(int sig __unused) 650 { 651 exit(0); 652 } 653 654 655 /* 656 * Receive a file. 657 */ 658 void 659 recvfile(struct formats *pf) 660 { 661 struct tftphdr *dp, *w_init(); 662 struct tftphdr *ap; /* ack buffer */ 663 int n, size; 664 volatile unsigned short block; 665 666 signal(SIGALRM, timer); 667 dp = w_init(); 668 ap = (struct tftphdr *)ackbuf; 669 block = 0; 670 do { 671 timeouts = 0; 672 ap->th_opcode = htons((u_short)ACK); 673 ap->th_block = htons((u_short)block); 674 block++; 675 (void) setjmp(timeoutbuf); 676 send_ack: 677 if (send(peer, ackbuf, 4, 0) != 4) { 678 syslog(LOG_ERR, "write: %m"); 679 goto abort; 680 } 681 write_behind(file, pf->f_convert); 682 for ( ; ; ) { 683 alarm(rexmtval); 684 n = recv(peer, dp, PKTSIZE, 0); 685 alarm(0); 686 if (n < 0) { /* really? */ 687 syslog(LOG_ERR, "read: %m"); 688 goto abort; 689 } 690 dp->th_opcode = ntohs((u_short)dp->th_opcode); 691 dp->th_block = ntohs((u_short)dp->th_block); 692 if (dp->th_opcode == ERROR) 693 goto abort; 694 if (dp->th_opcode == DATA) { 695 if (dp->th_block == block) { 696 break; /* normal */ 697 } 698 /* Re-synchronize with the other side */ 699 (void) synchnet(peer); 700 if (dp->th_block == (block-1)) 701 goto send_ack; /* rexmit */ 702 } 703 } 704 /* size = write(file, dp->th_data, n - 4); */ 705 size = writeit(file, &dp, n - 4, pf->f_convert); 706 if (size != (n-4)) { /* ahem */ 707 if (size < 0) nak(errno + 100); 708 else nak(ENOSPACE); 709 goto abort; 710 } 711 } while (size == SEGSIZE); 712 write_behind(file, pf->f_convert); 713 (void) fclose(file); /* close data file */ 714 715 ap->th_opcode = htons((u_short)ACK); /* send the "final" ack */ 716 ap->th_block = htons((u_short)(block)); 717 (void) send(peer, ackbuf, 4, 0); 718 719 signal(SIGALRM, justquit); /* just quit on timeout */ 720 alarm(rexmtval); 721 n = recv(peer, buf, sizeof (buf), 0); /* normally times out and quits */ 722 alarm(0); 723 if (n >= 4 && /* if read some data */ 724 dp->th_opcode == DATA && /* and got a data block */ 725 block == dp->th_block) { /* then my last ack was lost */ 726 (void) send(peer, ackbuf, 4, 0); /* resend final ack */ 727 } 728 abort: 729 return; 730 } 731 732 struct errmsg { 733 int e_code; 734 char *e_msg; 735 } errmsgs[] = { 736 { EUNDEF, "Undefined error code" }, 737 { ENOTFOUND, "File not found" }, 738 { EACCESS, "Access violation" }, 739 { ENOSPACE, "Disk full or allocation exceeded" }, 740 { EBADOP, "Illegal TFTP operation" }, 741 { EBADID, "Unknown transfer ID" }, 742 { EEXISTS, "File already exists" }, 743 { ENOUSER, "No such user" }, 744 { EOPTNEG, "Option negotiation" }, 745 { -1, 0 } 746 }; 747 748 static char * 749 errtomsg(int error) 750 { 751 static char buf[20]; 752 struct errmsg *pe; 753 if (error == 0) 754 return "success"; 755 for (pe = errmsgs; pe->e_code >= 0; pe++) 756 if (pe->e_code == error) 757 return pe->e_msg; 758 snprintf(buf, sizeof(buf), "error %d", error); 759 return buf; 760 } 761 762 /* 763 * Send a nak packet (error message). 764 * Error code passed in is one of the 765 * standard TFTP codes, or a UNIX errno 766 * offset by 100. 767 */ 768 static void 769 nak(int error) 770 { 771 struct tftphdr *tp; 772 int length; 773 struct errmsg *pe; 774 775 tp = (struct tftphdr *)buf; 776 tp->th_opcode = htons((u_short)ERROR); 777 tp->th_code = htons((u_short)error); 778 for (pe = errmsgs; pe->e_code >= 0; pe++) 779 if (pe->e_code == error) 780 break; 781 if (pe->e_code < 0) { 782 pe->e_msg = strerror(error - 100); 783 tp->th_code = EUNDEF; /* set 'undef' errorcode */ 784 } 785 strcpy(tp->th_msg, pe->e_msg); 786 length = strlen(pe->e_msg); 787 tp->th_msg[length] = '\0'; 788 length += 5; 789 if (send(peer, buf, length, 0) != length) 790 syslog(LOG_ERR, "nak: %m"); 791 } 792 793 /* translate IPv4 mapped IPv6 address to IPv4 address */ 794 static void 795 unmappedaddr(struct sockaddr_in6 *sin6) 796 { 797 struct sockaddr_in *sin4; 798 u_int32_t addr; 799 int port; 800 801 if (sin6->sin6_family != AF_INET6 || 802 !IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) 803 return; 804 sin4 = (struct sockaddr_in *)sin6; 805 addr = *(u_int32_t *)&sin6->sin6_addr.s6_addr[12]; 806 port = sin6->sin6_port; 807 memset(sin4, 0, sizeof(struct sockaddr_in)); 808 sin4->sin_addr.s_addr = addr; 809 sin4->sin_port = port; 810 sin4->sin_family = AF_INET; 811 sin4->sin_len = sizeof(struct sockaddr_in); 812 } 813 814 /* 815 * Send an oack packet (option acknowledgement). 816 */ 817 static void 818 oack(void) 819 { 820 struct tftphdr *tp, *ap; 821 int size, i, n; 822 char *bp; 823 824 tp = (struct tftphdr *)buf; 825 bp = buf + 2; 826 size = sizeof(buf) - 2; 827 tp->th_opcode = htons((u_short)OACK); 828 for (i = 0; options[i].o_type != NULL; i++) { 829 if (options[i].o_request) { 830 n = snprintf(bp, size, "%s%c%d", options[i].o_type, 831 0, options[i].o_reply); 832 bp += n+1; 833 size -= n+1; 834 if (size < 0) { 835 syslog(LOG_ERR, "oack: buffer overflow"); 836 exit(1); 837 } 838 } 839 } 840 size = bp - buf; 841 ap = (struct tftphdr *)ackbuf; 842 signal(SIGALRM, timer); 843 timeouts = 0; 844 845 (void)setjmp(timeoutbuf); 846 if (send(peer, buf, size, 0) != size) { 847 syslog(LOG_INFO, "oack: %m"); 848 exit(1); 849 } 850 851 for (;;) { 852 alarm(rexmtval); 853 n = recv(peer, ackbuf, sizeof (ackbuf), 0); 854 alarm(0); 855 if (n < 0) { 856 syslog(LOG_ERR, "recv: %m"); 857 exit(1); 858 } 859 ap->th_opcode = ntohs((u_short)ap->th_opcode); 860 ap->th_block = ntohs((u_short)ap->th_block); 861 if (ap->th_opcode == ERROR) 862 exit(1); 863 if (ap->th_opcode == ACK && ap->th_block == 0) 864 break; 865 } 866 } 867