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 #endif /* not lint */ 45 #include <sys/cdefs.h> 46 __FBSDID("$FreeBSD$"); 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 60 #include <netinet/in.h> 61 #include <arpa/tftp.h> 62 63 #include <ctype.h> 64 #include <errno.h> 65 #include <fcntl.h> 66 #include <netdb.h> 67 #include <pwd.h> 68 #include <stdint.h> 69 #include <stdio.h> 70 #include <stdlib.h> 71 #include <string.h> 72 #include <syslog.h> 73 #include <tcpd.h> 74 #include <unistd.h> 75 76 #include "tftp-file.h" 77 #include "tftp-io.h" 78 #include "tftp-utils.h" 79 #include "tftp-transfer.h" 80 #include "tftp-options.h" 81 82 static void tftp_wrq(int peer, char *, ssize_t); 83 static void tftp_rrq(int peer, char *, ssize_t); 84 85 /* 86 * Null-terminated directory prefix list for absolute pathname requests and 87 * search list for relative pathname requests. 88 * 89 * MAXDIRS should be at least as large as the number of arguments that 90 * inetd allows (currently 20). 91 */ 92 #define MAXDIRS 20 93 static struct dirlist { 94 const char *name; 95 int len; 96 } dirs[MAXDIRS+1]; 97 static int suppress_naks; 98 static int logging; 99 static int ipchroot; 100 static int create_new = 0; 101 static const char *newfile_format = "%Y%m%d"; 102 static int increase_name = 0; 103 static mode_t mask = S_IWGRP | S_IWOTH; 104 105 struct formats; 106 static void tftp_recvfile(int peer, const char *mode); 107 static void tftp_xmitfile(int peer, const char *mode); 108 static int validate_access(int peer, char **, int); 109 static char peername[NI_MAXHOST]; 110 111 static FILE *file; 112 113 static struct formats { 114 const char *f_mode; 115 int f_convert; 116 } formats[] = { 117 { "netascii", 1 }, 118 { "octet", 0 }, 119 { NULL, 0 } 120 }; 121 122 int 123 main(int argc, char *argv[]) 124 { 125 struct tftphdr *tp; 126 int peer; 127 socklen_t peerlen, len; 128 ssize_t n; 129 int ch; 130 char *chroot_dir = NULL; 131 struct passwd *nobody; 132 const char *chuser = "nobody"; 133 char recvbuffer[MAXPKTSIZE]; 134 int allow_ro = 1, allow_wo = 1; 135 136 tzset(); /* syslog in localtime */ 137 acting_as_client = 0; 138 139 tftp_openlog("tftpd", LOG_PID | LOG_NDELAY, LOG_FTP); 140 while ((ch = getopt(argc, argv, "cCd:F:lnoOp:s:u:U:wW")) != -1) { 141 switch (ch) { 142 case 'c': 143 ipchroot = 1; 144 break; 145 case 'C': 146 ipchroot = 2; 147 break; 148 case 'd': 149 if (atoi(optarg) != 0) 150 debug += atoi(optarg); 151 else 152 debug |= debug_finds(optarg); 153 break; 154 case 'F': 155 newfile_format = optarg; 156 break; 157 case 'l': 158 logging = 1; 159 break; 160 case 'n': 161 suppress_naks = 1; 162 break; 163 case 'o': 164 options_rfc_enabled = 0; 165 break; 166 case 'O': 167 options_extra_enabled = 0; 168 break; 169 case 'p': 170 packetdroppercentage = atoi(optarg); 171 tftp_log(LOG_INFO, 172 "Randomly dropping %d out of 100 packets", 173 packetdroppercentage); 174 break; 175 case 's': 176 chroot_dir = optarg; 177 break; 178 case 'u': 179 chuser = optarg; 180 break; 181 case 'U': 182 mask = strtol(optarg, NULL, 0); 183 break; 184 case 'w': 185 create_new = 1; 186 break; 187 case 'W': 188 create_new = 1; 189 increase_name = 1; 190 break; 191 default: 192 tftp_log(LOG_WARNING, 193 "ignoring unknown option -%c", ch); 194 } 195 } 196 if (optind < argc) { 197 struct dirlist *dirp; 198 199 /* Get list of directory prefixes. Skip relative pathnames. */ 200 for (dirp = dirs; optind < argc && dirp < &dirs[MAXDIRS]; 201 optind++) { 202 if (argv[optind][0] == '/') { 203 dirp->name = argv[optind]; 204 dirp->len = strlen(dirp->name); 205 dirp++; 206 } 207 } 208 } 209 else if (chroot_dir) { 210 dirs->name = "/"; 211 dirs->len = 1; 212 } 213 if (ipchroot > 0 && chroot_dir == NULL) { 214 tftp_log(LOG_ERR, "-c requires -s"); 215 exit(1); 216 } 217 218 umask(mask); 219 220 { 221 int on = 1; 222 if (ioctl(0, FIONBIO, &on) < 0) { 223 tftp_log(LOG_ERR, "ioctl(FIONBIO): %s", strerror(errno)); 224 exit(1); 225 } 226 } 227 228 /* Find out who we are talking to and what we are going to do */ 229 peerlen = sizeof(peer_sock); 230 n = recvfrom(0, recvbuffer, MAXPKTSIZE, 0, 231 (struct sockaddr *)&peer_sock, &peerlen); 232 if (n < 0) { 233 tftp_log(LOG_ERR, "recvfrom: %s", strerror(errno)); 234 exit(1); 235 } 236 getnameinfo((struct sockaddr *)&peer_sock, peer_sock.ss_len, 237 peername, sizeof(peername), NULL, 0, NI_NUMERICHOST); 238 239 /* 240 * Now that we have read the message out of the UDP 241 * socket, we fork and exit. Thus, inetd will go back 242 * to listening to the tftp port, and the next request 243 * to come in will start up a new instance of tftpd. 244 * 245 * We do this so that inetd can run tftpd in "wait" mode. 246 * The problem with tftpd running in "nowait" mode is that 247 * inetd may get one or more successful "selects" on the 248 * tftp port before we do our receive, so more than one 249 * instance of tftpd may be started up. Worse, if tftpd 250 * break before doing the above "recvfrom", inetd would 251 * spawn endless instances, clogging the system. 252 */ 253 { 254 int i, pid; 255 256 for (i = 1; i < 20; i++) { 257 pid = fork(); 258 if (pid < 0) { 259 sleep(i); 260 /* 261 * flush out to most recently sent request. 262 * 263 * This may drop some request, but those 264 * will be resent by the clients when 265 * they timeout. The positive effect of 266 * this flush is to (try to) prevent more 267 * than one tftpd being started up to service 268 * a single request from a single client. 269 */ 270 peerlen = sizeof peer_sock; 271 i = recvfrom(0, recvbuffer, MAXPKTSIZE, 0, 272 (struct sockaddr *)&peer_sock, &peerlen); 273 if (i > 0) { 274 n = i; 275 } 276 } else { 277 break; 278 } 279 } 280 if (pid < 0) { 281 tftp_log(LOG_ERR, "fork: %s", strerror(errno)); 282 exit(1); 283 } else if (pid != 0) { 284 exit(0); 285 } 286 } 287 288 /* 289 * See if the client is allowed to talk to me. 290 * (This needs to be done before the chroot()) 291 */ 292 { 293 struct request_info req; 294 295 request_init(&req, RQ_CLIENT_ADDR, peername, 0); 296 request_set(&req, RQ_DAEMON, "tftpd", 0); 297 298 if (hosts_access(&req) == 0) { 299 if (debug&DEBUG_ACCESS) 300 tftp_log(LOG_WARNING, 301 "Access denied by 'tftpd' entry " 302 "in /etc/hosts.allow"); 303 304 /* 305 * Full access might be disabled, but maybe the 306 * client is allowed to do read-only access. 307 */ 308 request_set(&req, RQ_DAEMON, "tftpd-ro", 0); 309 allow_ro = hosts_access(&req); 310 311 request_set(&req, RQ_DAEMON, "tftpd-wo", 0); 312 allow_wo = hosts_access(&req); 313 314 if (allow_ro == 0 && allow_wo == 0) { 315 tftp_log(LOG_WARNING, 316 "Unauthorized access from %s", peername); 317 exit(1); 318 } 319 320 if (debug&DEBUG_ACCESS) { 321 if (allow_ro) 322 tftp_log(LOG_WARNING, 323 "But allowed readonly access " 324 "via 'tftpd-ro' entry"); 325 if (allow_wo) 326 tftp_log(LOG_WARNING, 327 "But allowed writeonly access " 328 "via 'tftpd-wo' entry"); 329 } 330 } else 331 if (debug&DEBUG_ACCESS) 332 tftp_log(LOG_WARNING, 333 "Full access allowed" 334 "in /etc/hosts.allow"); 335 } 336 337 /* 338 * Since we exit here, we should do that only after the above 339 * recvfrom to keep inetd from constantly forking should there 340 * be a problem. See the above comment about system clogging. 341 */ 342 if (chroot_dir) { 343 if (ipchroot > 0) { 344 char *tempchroot; 345 struct stat sb; 346 int statret; 347 struct sockaddr_storage ss; 348 char hbuf[NI_MAXHOST]; 349 350 statret = -1; 351 memcpy(&ss, &peer_sock, peer_sock.ss_len); 352 unmappedaddr((struct sockaddr_in6 *)&ss); 353 getnameinfo((struct sockaddr *)&ss, ss.ss_len, 354 hbuf, sizeof(hbuf), NULL, 0, 355 NI_NUMERICHOST); 356 asprintf(&tempchroot, "%s/%s", chroot_dir, hbuf); 357 if (ipchroot == 2) 358 statret = stat(tempchroot, &sb); 359 if (ipchroot == 1 || 360 (statret == 0 && (sb.st_mode & S_IFDIR))) 361 chroot_dir = tempchroot; 362 } 363 /* Must get this before chroot because /etc might go away */ 364 if ((nobody = getpwnam(chuser)) == NULL) { 365 tftp_log(LOG_ERR, "%s: no such user", chuser); 366 exit(1); 367 } 368 if (chroot(chroot_dir)) { 369 tftp_log(LOG_ERR, "chroot: %s: %s", 370 chroot_dir, strerror(errno)); 371 exit(1); 372 } 373 chdir("/"); 374 setgroups(1, &nobody->pw_gid); 375 if (setuid(nobody->pw_uid) != 0) { 376 tftp_log(LOG_ERR, "setuid failed"); 377 exit(1); 378 } 379 } 380 381 len = sizeof(me_sock); 382 if (getsockname(0, (struct sockaddr *)&me_sock, &len) == 0) { 383 switch (me_sock.ss_family) { 384 case AF_INET: 385 ((struct sockaddr_in *)&me_sock)->sin_port = 0; 386 break; 387 case AF_INET6: 388 ((struct sockaddr_in6 *)&me_sock)->sin6_port = 0; 389 break; 390 default: 391 /* unsupported */ 392 break; 393 } 394 } else { 395 memset(&me_sock, 0, sizeof(me_sock)); 396 me_sock.ss_family = peer_sock.ss_family; 397 me_sock.ss_len = peer_sock.ss_len; 398 } 399 close(0); 400 close(1); 401 peer = socket(peer_sock.ss_family, SOCK_DGRAM, 0); 402 if (peer < 0) { 403 tftp_log(LOG_ERR, "socket: %s", strerror(errno)); 404 exit(1); 405 } 406 if (bind(peer, (struct sockaddr *)&me_sock, me_sock.ss_len) < 0) { 407 tftp_log(LOG_ERR, "bind: %s", strerror(errno)); 408 exit(1); 409 } 410 411 tp = (struct tftphdr *)recvbuffer; 412 tp->th_opcode = ntohs(tp->th_opcode); 413 if (tp->th_opcode == RRQ) { 414 if (allow_ro) 415 tftp_rrq(peer, tp->th_stuff, n - 1); 416 else { 417 tftp_log(LOG_WARNING, 418 "%s read access denied", peername); 419 exit(1); 420 } 421 } 422 if (tp->th_opcode == WRQ) { 423 if (allow_wo) 424 tftp_wrq(peer, tp->th_stuff, n - 1); 425 else { 426 tftp_log(LOG_WARNING, 427 "%s write access denied", peername); 428 exit(1); 429 } 430 } 431 exit(1); 432 } 433 434 static void 435 reduce_path(char *fn) 436 { 437 char *slash, *ptr; 438 439 /* Reduce all "/+./" to "/" (just in case we've got "/./../" later */ 440 while ((slash = strstr(fn, "/./")) != NULL) { 441 for (ptr = slash; ptr > fn && ptr[-1] == '/'; ptr--) 442 ; 443 slash += 2; 444 while (*slash) 445 *++ptr = *++slash; 446 } 447 448 /* Now reduce all "/something/+../" to "/" */ 449 while ((slash = strstr(fn, "/../")) != NULL) { 450 if (slash == fn) 451 break; 452 for (ptr = slash; ptr > fn && ptr[-1] == '/'; ptr--) 453 ; 454 for (ptr--; ptr >= fn; ptr--) 455 if (*ptr == '/') 456 break; 457 if (ptr < fn) 458 break; 459 slash += 3; 460 while (*slash) 461 *++ptr = *++slash; 462 } 463 } 464 465 static char * 466 parse_header(int peer, char *recvbuffer, ssize_t size, 467 char **filename, char **mode) 468 { 469 char *cp; 470 int i; 471 struct formats *pf; 472 473 *mode = NULL; 474 cp = recvbuffer; 475 476 i = get_field(peer, recvbuffer, size); 477 if (i >= PATH_MAX) { 478 tftp_log(LOG_ERR, "Bad option - filename too long"); 479 send_error(peer, EBADOP); 480 exit(1); 481 } 482 *filename = recvbuffer; 483 tftp_log(LOG_INFO, "Filename: '%s'", *filename); 484 cp += i; 485 486 i = get_field(peer, cp, size); 487 *mode = cp; 488 cp += i; 489 490 /* Find the file transfer mode */ 491 for (cp = *mode; *cp; cp++) 492 if (isupper(*cp)) 493 *cp = tolower(*cp); 494 for (pf = formats; pf->f_mode; pf++) 495 if (strcmp(pf->f_mode, *mode) == 0) 496 break; 497 if (pf->f_mode == NULL) { 498 tftp_log(LOG_ERR, 499 "Bad option - Unknown transfer mode (%s)", *mode); 500 send_error(peer, EBADOP); 501 exit(1); 502 } 503 tftp_log(LOG_INFO, "Mode: '%s'", *mode); 504 505 return (cp + 1); 506 } 507 508 /* 509 * WRQ - receive a file from the client 510 */ 511 void 512 tftp_wrq(int peer, char *recvbuffer, ssize_t size) 513 { 514 char *cp; 515 int has_options = 0, ecode; 516 char *filename, *mode; 517 char fnbuf[PATH_MAX]; 518 519 cp = parse_header(peer, recvbuffer, size, &filename, &mode); 520 size -= (cp - recvbuffer) + 1; 521 522 strcpy(fnbuf, filename); 523 reduce_path(fnbuf); 524 filename = fnbuf; 525 526 if (size > 0) { 527 if (options_rfc_enabled) 528 has_options = !parse_options(peer, cp, size); 529 else 530 tftp_log(LOG_INFO, "Options found but not enabled"); 531 } 532 533 ecode = validate_access(peer, &filename, WRQ); 534 if (ecode == 0) { 535 if (has_options) 536 send_oack(peer); 537 else 538 send_ack(peer, 0); 539 } 540 if (logging) { 541 tftp_log(LOG_INFO, "%s: write request for %s: %s", peername, 542 filename, errtomsg(ecode)); 543 } 544 545 tftp_recvfile(peer, mode); 546 exit(0); 547 } 548 549 /* 550 * RRQ - send a file to the client 551 */ 552 void 553 tftp_rrq(int peer, char *recvbuffer, ssize_t size) 554 { 555 char *cp; 556 int has_options = 0, ecode; 557 char *filename, *mode; 558 char fnbuf[PATH_MAX]; 559 560 cp = parse_header(peer, recvbuffer, size, &filename, &mode); 561 size -= (cp - recvbuffer) + 1; 562 563 strcpy(fnbuf, filename); 564 reduce_path(fnbuf); 565 filename = fnbuf; 566 567 if (size > 0) { 568 if (options_rfc_enabled) 569 has_options = !parse_options(peer, cp, size); 570 else 571 tftp_log(LOG_INFO, "Options found but not enabled"); 572 } 573 574 ecode = validate_access(peer, &filename, RRQ); 575 if (ecode == 0) { 576 if (has_options) { 577 int n; 578 char lrecvbuffer[MAXPKTSIZE]; 579 struct tftphdr *rp = (struct tftphdr *)lrecvbuffer; 580 581 send_oack(peer); 582 n = receive_packet(peer, lrecvbuffer, MAXPKTSIZE, 583 NULL, timeoutpacket); 584 if (n < 0) { 585 if (debug&DEBUG_SIMPLE) 586 tftp_log(LOG_DEBUG, "Aborting: %s", 587 rp_strerror(n)); 588 return; 589 } 590 if (rp->th_opcode != ACK) { 591 if (debug&DEBUG_SIMPLE) 592 tftp_log(LOG_DEBUG, 593 "Expected ACK, got %s on OACK", 594 packettype(rp->th_opcode)); 595 return; 596 } 597 } 598 } 599 600 if (logging) 601 tftp_log(LOG_INFO, "%s: read request for %s: %s", peername, 602 filename, errtomsg(ecode)); 603 604 if (ecode) { 605 /* 606 * Avoid storms of naks to a RRQ broadcast for a relative 607 * bootfile pathname from a diskless Sun. 608 */ 609 if (suppress_naks && *filename != '/' && ecode == ENOTFOUND) 610 exit(0); 611 send_error(peer, ecode); 612 exit(1); 613 } 614 tftp_xmitfile(peer, mode); 615 } 616 617 /* 618 * Find the next value for YYYYMMDD.nn when the file to be written should 619 * be unique. Due to the limitations of nn, we will fail if nn reaches 100. 620 * Besides, that is four updates per hour on a file, which is kind of 621 * execessive anyway. 622 */ 623 static int 624 find_next_name(char *filename, int *fd) 625 { 626 int i; 627 time_t tval; 628 size_t len; 629 struct tm lt; 630 char yyyymmdd[MAXPATHLEN]; 631 char newname[MAXPATHLEN]; 632 633 /* Create the YYYYMMDD part of the filename */ 634 time(&tval); 635 lt = *localtime(&tval); 636 len = strftime(yyyymmdd, sizeof(yyyymmdd), newfile_format, <); 637 if (len == 0) { 638 syslog(LOG_WARNING, 639 "Filename suffix too long (%d characters maximum)", 640 MAXPATHLEN); 641 return (EACCESS); 642 } 643 644 /* Make sure the new filename is not too long */ 645 if (strlen(filename) > MAXPATHLEN - len - 5) { 646 syslog(LOG_WARNING, 647 "Filename too long (%zd characters, %zd maximum)", 648 strlen(filename), MAXPATHLEN - len - 5); 649 return (EACCESS); 650 } 651 652 /* Find the first file which doesn't exist */ 653 for (i = 0; i < 100; i++) { 654 sprintf(newname, "%s.%s.%02d", filename, yyyymmdd, i); 655 *fd = open(newname, 656 O_WRONLY | O_CREAT | O_EXCL, 657 S_IRUSR | S_IWUSR | S_IRGRP | 658 S_IWGRP | S_IROTH | S_IWOTH); 659 if (*fd > 0) 660 return 0; 661 } 662 663 return (EEXIST); 664 } 665 666 /* 667 * Validate file access. Since we 668 * have no uid or gid, for now require 669 * file to exist and be publicly 670 * readable/writable. 671 * If we were invoked with arguments 672 * from inetd then the file must also be 673 * in one of the given directory prefixes. 674 * Note also, full path name must be 675 * given as we have no login directory. 676 */ 677 int 678 validate_access(int peer, char **filep, int mode) 679 { 680 struct stat stbuf; 681 int fd; 682 int error; 683 struct dirlist *dirp; 684 static char pathname[MAXPATHLEN]; 685 char *filename = *filep; 686 687 /* 688 * Prevent tricksters from getting around the directory restrictions 689 */ 690 if (strstr(filename, "/../")) 691 return (EACCESS); 692 693 if (*filename == '/') { 694 /* 695 * Allow the request if it's in one of the approved locations. 696 * Special case: check the null prefix ("/") by looking 697 * for length = 1 and relying on the arg. processing that 698 * it's a /. 699 */ 700 for (dirp = dirs; dirp->name != NULL; dirp++) { 701 if (dirp->len == 1 || 702 (!strncmp(filename, dirp->name, dirp->len) && 703 filename[dirp->len] == '/')) 704 break; 705 } 706 /* If directory list is empty, allow access to any file */ 707 if (dirp->name == NULL && dirp != dirs) 708 return (EACCESS); 709 if (stat(filename, &stbuf) < 0) 710 return (errno == ENOENT ? ENOTFOUND : EACCESS); 711 if ((stbuf.st_mode & S_IFMT) != S_IFREG) 712 return (ENOTFOUND); 713 if (mode == RRQ) { 714 if ((stbuf.st_mode & S_IROTH) == 0) 715 return (EACCESS); 716 } else { 717 if ((stbuf.st_mode & S_IWOTH) == 0) 718 return (EACCESS); 719 } 720 } else { 721 int err; 722 723 /* 724 * Relative file name: search the approved locations for it. 725 * Don't allow write requests that avoid directory 726 * restrictions. 727 */ 728 729 if (!strncmp(filename, "../", 3)) 730 return (EACCESS); 731 732 /* 733 * If the file exists in one of the directories and isn't 734 * readable, continue looking. However, change the error code 735 * to give an indication that the file exists. 736 */ 737 err = ENOTFOUND; 738 for (dirp = dirs; dirp->name != NULL; dirp++) { 739 snprintf(pathname, sizeof(pathname), "%s/%s", 740 dirp->name, filename); 741 if (stat(pathname, &stbuf) == 0 && 742 (stbuf.st_mode & S_IFMT) == S_IFREG) { 743 if ((stbuf.st_mode & S_IROTH) != 0) { 744 break; 745 } 746 err = EACCESS; 747 } 748 } 749 if (dirp->name != NULL) 750 *filep = filename = pathname; 751 else if (mode == RRQ) 752 return (err); 753 } 754 755 /* 756 * This option is handled here because it (might) require(s) the 757 * size of the file. 758 */ 759 option_tsize(peer, NULL, mode, &stbuf); 760 761 if (mode == RRQ) 762 fd = open(filename, O_RDONLY); 763 else { 764 if (create_new) { 765 if (increase_name) { 766 error = find_next_name(filename, &fd); 767 if (error > 0) 768 return (error + 100); 769 } else 770 fd = open(filename, 771 O_WRONLY | O_TRUNC | O_CREAT, 772 S_IRUSR | S_IWUSR | S_IRGRP | 773 S_IWGRP | S_IROTH | S_IWOTH ); 774 } else 775 fd = open(filename, O_WRONLY | O_TRUNC); 776 } 777 if (fd < 0) 778 return (errno + 100); 779 file = fdopen(fd, (mode == RRQ)? "r":"w"); 780 if (file == NULL) { 781 close(fd); 782 return (errno + 100); 783 } 784 return (0); 785 } 786 787 static void 788 tftp_xmitfile(int peer, const char *mode) 789 { 790 uint16_t block; 791 time_t now; 792 struct tftp_stats ts; 793 794 now = time(NULL); 795 if (debug&DEBUG_SIMPLE) 796 tftp_log(LOG_DEBUG, "Transmitting file"); 797 798 read_init(0, file, mode); 799 block = 1; 800 tftp_send(peer, &block, &ts); 801 read_close(); 802 if (debug&DEBUG_SIMPLE) 803 tftp_log(LOG_INFO, "Sent %jd bytes in %jd seconds", 804 (intmax_t)ts.amount, (intmax_t)time(NULL) - now); 805 } 806 807 static void 808 tftp_recvfile(int peer, const char *mode) 809 { 810 uint16_t block; 811 struct timeval now1, now2; 812 struct tftp_stats ts; 813 814 gettimeofday(&now1, NULL); 815 if (debug&DEBUG_SIMPLE) 816 tftp_log(LOG_DEBUG, "Receiving file"); 817 818 write_init(0, file, mode); 819 820 block = 0; 821 tftp_receive(peer, &block, &ts, NULL, 0); 822 823 write_close(); 824 gettimeofday(&now2, NULL); 825 826 if (debug&DEBUG_SIMPLE) { 827 double f; 828 if (now1.tv_usec > now2.tv_usec) { 829 now2.tv_usec += 1000000; 830 now2.tv_sec--; 831 } 832 833 f = now2.tv_sec - now1.tv_sec + 834 (now2.tv_usec - now1.tv_usec) / 100000.0; 835 tftp_log(LOG_INFO, 836 "Download of %jd bytes in %d blocks completed after %0.1f seconds\n", 837 (intmax_t)ts.amount, block, f); 838 } 839 840 return; 841 } 842