tftpd.c (86765) | tftpd.c (90333) |
---|---|
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 --- 28 unchanged lines hidden (view full) --- 37 The Regents of the University of California. All rights reserved.\n"; 38#endif /* not lint */ 39 40#ifndef lint 41#if 0 42static char sccsid[] = "@(#)tftpd.c 8.1 (Berkeley) 6/4/93"; 43#endif 44static const char rcsid[] = | 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 --- 28 unchanged lines hidden (view full) --- 37 The Regents of the University of California. All rights reserved.\n"; 38#endif /* not lint */ 39 40#ifndef lint 41#if 0 42static char sccsid[] = "@(#)tftpd.c 8.1 (Berkeley) 6/4/93"; 43#endif 44static const char rcsid[] = |
45 "$FreeBSD: head/libexec/tftpd/tftpd.c 86765 2001-11-22 05:08:35Z benno $"; | 45 "$FreeBSD: head/libexec/tftpd/tftpd.c 90333 2002-02-07 04:49:34Z imp $"; |
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 */ --- 32 unchanged lines hidden (view full) --- 86int max_rexmtval = 2*TIMEOUT; 87 88#define PKTSIZE SEGSIZE+4 89char buf[PKTSIZE]; 90char ackbuf[PKTSIZE]; 91struct sockaddr_in from; 92int fromlen; 93 | 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 */ --- 32 unchanged lines hidden (view full) --- 86int max_rexmtval = 2*TIMEOUT; 87 88#define PKTSIZE SEGSIZE+4 89char buf[PKTSIZE]; 90char ackbuf[PKTSIZE]; 91struct sockaddr_in from; 92int fromlen; 93 |
94void tftp __P((struct tftphdr *, int)); | 94void tftp(struct tftphdr *, int); |
95 96/* 97 * Null-terminated directory prefix list for absolute pathname requests and 98 * search list for relative pathname requests. 99 * 100 * MAXDIRS should be at least as large as the number of arguments that 101 * inetd allows (currently 20). 102 */ 103#define MAXDIRS 20 104static struct dirlist { 105 char *name; 106 int len; 107} dirs[MAXDIRS+1]; 108static int suppress_naks; 109static int logging; 110static int ipchroot; 111 | 95 96/* 97 * Null-terminated directory prefix list for absolute pathname requests and 98 * search list for relative pathname requests. 99 * 100 * MAXDIRS should be at least as large as the number of arguments that 101 * inetd allows (currently 20). 102 */ 103#define MAXDIRS 20 104static struct dirlist { 105 char *name; 106 int len; 107} dirs[MAXDIRS+1]; 108static int suppress_naks; 109static int logging; 110static int ipchroot; 111 |
112static char *errtomsg __P((int)); 113static void nak __P((int)); 114static void oack __P(()); | 112static char *errtomsg(int); 113static void nak(int); 114static void oack(); |
115 116int | 115 116int |
117main(argc, argv) 118 int argc; 119 char *argv[]; | 117main(int argc, char *argv[]) |
120{ | 118{ |
121 register struct tftphdr *tp; 122 register int n; | 119 struct tftphdr *tp; 120 int n; |
123 int ch, on; 124 struct sockaddr_in sin; 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) { --- 159 unchanged lines hidden (view full) --- 290 tp = (struct tftphdr *)buf; 291 tp->th_opcode = ntohs(tp->th_opcode); 292 if (tp->th_opcode == RRQ || tp->th_opcode == WRQ) 293 tftp(tp, n); 294 exit(1); 295} 296 297struct formats; | 121 int ch, on; 122 struct sockaddr_in sin; 123 char *chroot_dir = NULL; 124 struct passwd *nobody; 125 char *chuser = "nobody"; 126 127 openlog("tftpd", LOG_PID | LOG_NDELAY, LOG_FTP); 128 while ((ch = getopt(argc, argv, "cClns:u:")) != -1) { --- 159 unchanged lines hidden (view full) --- 288 tp = (struct tftphdr *)buf; 289 tp->th_opcode = ntohs(tp->th_opcode); 290 if (tp->th_opcode == RRQ || tp->th_opcode == WRQ) 291 tftp(tp, n); 292 exit(1); 293} 294 295struct formats; |
298int validate_access __P((char **, int)); 299void xmitfile __P((struct formats *)); 300void recvfile __P((struct formats *)); | 296int validate_access(char **, int); 297void xmitfile(struct formats *); 298void recvfile(struct formats *); |
301 302struct formats { 303 char *f_mode; | 299 300struct formats { 301 char *f_mode; |
304 int (*f_validate) __P((char **, int)); 305 void (*f_send) __P((struct formats *)); 306 void (*f_recv) __P((struct formats *)); | 302 int (*f_validate)(char **, int); 303 void (*f_send)(struct formats *); 304 void (*f_recv)(struct formats *); |
307 int f_convert; 308} formats[] = { 309 { "netascii", validate_access, xmitfile, recvfile, 1 }, 310 { "octet", validate_access, xmitfile, recvfile, 0 }, 311#ifdef notdef 312 { "mail", validate_user, sendmail, recvmail, 1 }, 313#endif 314 { 0 } --- 13 unchanged lines hidden (view full) --- 328 OPT_TSIZE = 0, 329 OPT_TIMEOUT, 330}; 331 332/* 333 * Handle initial connection protocol. 334 */ 335void | 305 int f_convert; 306} formats[] = { 307 { "netascii", validate_access, xmitfile, recvfile, 1 }, 308 { "octet", validate_access, xmitfile, recvfile, 0 }, 309#ifdef notdef 310 { "mail", validate_user, sendmail, recvmail, 1 }, 311#endif 312 { 0 } --- 13 unchanged lines hidden (view full) --- 326 OPT_TSIZE = 0, 327 OPT_TIMEOUT, 328}; 329 330/* 331 * Handle initial connection protocol. 332 */ 333void |
336tftp(tp, size) 337 struct tftphdr *tp; 338 int size; | 334tftp(struct tftphdr *tp, int size) |
339{ | 335{ |
340 register char *cp; | 336 char *cp; |
341 int i, first = 1, has_options = 0, ecode; | 337 int i, first = 1, has_options = 0, ecode; |
342 register struct formats *pf; | 338 struct formats *pf; |
343 char *filename, *mode, *option, *ccp; 344 345 filename = cp = tp->th_stuff; 346again: 347 while (cp < buf + size) { 348 if (*cp == '\0') 349 break; 350 cp++; --- 94 unchanged lines hidden (view full) --- 445 * readable/writable. 446 * If we were invoked with arguments 447 * from inetd then the file must also be 448 * in one of the given directory prefixes. 449 * Note also, full path name must be 450 * given as we have no login directory. 451 */ 452int | 339 char *filename, *mode, *option, *ccp; 340 341 filename = cp = tp->th_stuff; 342again: 343 while (cp < buf + size) { 344 if (*cp == '\0') 345 break; 346 cp++; --- 94 unchanged lines hidden (view full) --- 441 * readable/writable. 442 * If we were invoked with arguments 443 * from inetd then the file must also be 444 * in one of the given directory prefixes. 445 * Note also, full path name must be 446 * given as we have no login directory. 447 */ 448int |
453validate_access(filep, mode) 454 char **filep; 455 int mode; | 449validate_access(char **filep, int mode) |
456{ 457 struct stat stbuf; 458 int fd; 459 struct dirlist *dirp; 460 static char pathname[MAXPATHLEN]; 461 char *filename = *filep; 462 463 /* --- 79 unchanged lines hidden (view full) --- 543 } 544 return (0); 545} 546 547int timeouts; 548jmp_buf timeoutbuf; 549 550void | 450{ 451 struct stat stbuf; 452 int fd; 453 struct dirlist *dirp; 454 static char pathname[MAXPATHLEN]; 455 char *filename = *filep; 456 457 /* --- 79 unchanged lines hidden (view full) --- 537 } 538 return (0); 539} 540 541int timeouts; 542jmp_buf timeoutbuf; 543 544void |
551timer() | 545timer(int sig __unused) |
552{ 553 if (++timeouts > MAX_TIMEOUTS) 554 exit(1); 555 longjmp(timeoutbuf, 1); 556} 557 558/* 559 * Send the requested file. 560 */ 561void | 546{ 547 if (++timeouts > MAX_TIMEOUTS) 548 exit(1); 549 longjmp(timeoutbuf, 1); 550} 551 552/* 553 * Send the requested file. 554 */ 555void |
562xmitfile(pf) 563 struct formats *pf; | 556xmitfile(struct formats *pf) |
564{ 565 struct tftphdr *dp, *r_init(); | 557{ 558 struct tftphdr *dp, *r_init(); |
566 register struct tftphdr *ap; /* ack packet */ 567 register int size, n; | 559 struct tftphdr *ap; /* ack packet */ 560 int size, n; |
568 volatile unsigned short block; 569 570 signal(SIGALRM, timer); 571 dp = r_init(); 572 ap = (struct tftphdr *)ackbuf; 573 block = 1; 574 do { 575 size = readit(file, &dp, pf->f_convert); --- 38 unchanged lines hidden (view full) --- 614 } 615 block++; 616 } while (size == SEGSIZE); 617abort: 618 (void) fclose(file); 619} 620 621void | 561 volatile unsigned short block; 562 563 signal(SIGALRM, timer); 564 dp = r_init(); 565 ap = (struct tftphdr *)ackbuf; 566 block = 1; 567 do { 568 size = readit(file, &dp, pf->f_convert); --- 38 unchanged lines hidden (view full) --- 607 } 608 block++; 609 } while (size == SEGSIZE); 610abort: 611 (void) fclose(file); 612} 613 614void |
622justquit() | 615justquit(int sig __unused) |
623{ 624 exit(0); 625} 626 627 628/* 629 * Receive a file. 630 */ 631void | 616{ 617 exit(0); 618} 619 620 621/* 622 * Receive a file. 623 */ 624void |
632recvfile(pf) 633 struct formats *pf; | 625recvfile(struct formats *pf) |
634{ 635 struct tftphdr *dp, *w_init(); | 626{ 627 struct tftphdr *dp, *w_init(); |
636 register struct tftphdr *ap; /* ack buffer */ 637 register int n, size; | 628 struct tftphdr *ap; /* ack buffer */ 629 int n, size; |
638 volatile unsigned short block; 639 640 signal(SIGALRM, timer); 641 dp = w_init(); 642 ap = (struct tftphdr *)ackbuf; 643 block = 0; 644 do { 645 timeouts = 0; --- 69 unchanged lines hidden (view full) --- 715 { EBADID, "Unknown transfer ID" }, 716 { EEXISTS, "File already exists" }, 717 { ENOUSER, "No such user" }, 718 { EOPTNEG, "Option negotiation" }, 719 { -1, 0 } 720}; 721 722static char * | 630 volatile unsigned short block; 631 632 signal(SIGALRM, timer); 633 dp = w_init(); 634 ap = (struct tftphdr *)ackbuf; 635 block = 0; 636 do { 637 timeouts = 0; --- 69 unchanged lines hidden (view full) --- 707 { EBADID, "Unknown transfer ID" }, 708 { EEXISTS, "File already exists" }, 709 { ENOUSER, "No such user" }, 710 { EOPTNEG, "Option negotiation" }, 711 { -1, 0 } 712}; 713 714static char * |
723errtomsg(error) 724 int error; | 715errtomsg(int error) |
725{ 726 static char buf[20]; | 716{ 717 static char buf[20]; |
727 register struct errmsg *pe; | 718 struct errmsg *pe; |
728 if (error == 0) 729 return "success"; 730 for (pe = errmsgs; pe->e_code >= 0; pe++) 731 if (pe->e_code == error) 732 return pe->e_msg; 733 snprintf(buf, sizeof(buf), "error %d", error); 734 return buf; 735} 736 737/* 738 * Send a nak packet (error message). 739 * Error code passed in is one of the 740 * standard TFTP codes, or a UNIX errno 741 * offset by 100. 742 */ 743static void | 719 if (error == 0) 720 return "success"; 721 for (pe = errmsgs; pe->e_code >= 0; pe++) 722 if (pe->e_code == error) 723 return pe->e_msg; 724 snprintf(buf, sizeof(buf), "error %d", error); 725 return buf; 726} 727 728/* 729 * Send a nak packet (error message). 730 * Error code passed in is one of the 731 * standard TFTP codes, or a UNIX errno 732 * offset by 100. 733 */ 734static void |
744nak(error) 745 int error; | 735nak(int error) |
746{ | 736{ |
747 register struct tftphdr *tp; | 737 struct tftphdr *tp; |
748 int length; | 738 int length; |
749 register struct errmsg *pe; | 739 struct errmsg *pe; |
750 751 tp = (struct tftphdr *)buf; 752 tp->th_opcode = htons((u_short)ERROR); 753 tp->th_code = htons((u_short)error); 754 for (pe = errmsgs; pe->e_code >= 0; pe++) 755 if (pe->e_code == error) 756 break; 757 if (pe->e_code < 0) { --- 7 unchanged lines hidden (view full) --- 765 if (send(peer, buf, length, 0) != length) 766 syslog(LOG_ERR, "nak: %m"); 767} 768 769/* 770 * Send an oack packet (option acknowledgement). 771 */ 772static void | 740 741 tp = (struct tftphdr *)buf; 742 tp->th_opcode = htons((u_short)ERROR); 743 tp->th_code = htons((u_short)error); 744 for (pe = errmsgs; pe->e_code >= 0; pe++) 745 if (pe->e_code == error) 746 break; 747 if (pe->e_code < 0) { --- 7 unchanged lines hidden (view full) --- 755 if (send(peer, buf, length, 0) != length) 756 syslog(LOG_ERR, "nak: %m"); 757} 758 759/* 760 * Send an oack packet (option acknowledgement). 761 */ 762static void |
773oack() | 763oack(void) |
774{ 775 struct tftphdr *tp, *ap; 776 int size, i, n; 777 char *bp; 778 779 tp = (struct tftphdr *)buf; 780 bp = buf + 2; 781 size = sizeof(buf) - 2; --- 40 unchanged lines hidden --- | 764{ 765 struct tftphdr *tp, *ap; 766 int size, i, n; 767 char *bp; 768 769 tp = (struct tftphdr *)buf; 770 bp = buf + 2; 771 size = sizeof(buf) - 2; --- 40 unchanged lines hidden --- |