Deleted Added
full compact
tftpd.c (71926) tftpd.c (84047)
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 71926 2001-02-02 10:53:02Z asmodai $";
45 "$FreeBSD: head/libexec/tftpd/tftpd.c 84047 2001-09-27 20:50:14Z obrien $";
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 */

--- 20 unchanged lines hidden (view full) ---

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
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 */

--- 20 unchanged lines hidden (view full) ---

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
82
83int peer;
84int rexmtval = TIMEOUT;
83
84int peer;
85int rexmtval = TIMEOUT;
85int maxtimeout = 5*TIMEOUT;
86int max_rexmtval = 2*TIMEOUT;
86
87#define PKTSIZE SEGSIZE+4
88char buf[PKTSIZE];
89char ackbuf[PKTSIZE];
90struct sockaddr_in from;
91int fromlen;
92
93void tftp __P((struct tftphdr *, int));

--- 11 unchanged lines hidden (view full) ---

105 int len;
106} dirs[MAXDIRS+1];
107static int suppress_naks;
108static int logging;
109static int ipchroot;
110
111static char *errtomsg __P((int));
112static void nak __P((int));
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));

--- 11 unchanged lines hidden (view full) ---

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(());
113
114int
115main(argc, argv)
116 int argc;
117 char *argv[];
118{
119 register struct tftphdr *tp;
120 register int n;

--- 185 unchanged lines hidden (view full) ---

306 { "netascii", validate_access, xmitfile, recvfile, 1 },
307 { "octet", validate_access, xmitfile, recvfile, 0 },
308#ifdef notdef
309 { "mail", validate_user, sendmail, recvmail, 1 },
310#endif
311 { 0 }
312};
313
115
116int
117main(argc, argv)
118 int argc;
119 char *argv[];
120{
121 register struct tftphdr *tp;
122 register int n;

--- 185 unchanged lines hidden (view full) ---

308 { "netascii", validate_access, xmitfile, recvfile, 1 },
309 { "octet", validate_access, xmitfile, recvfile, 0 },
310#ifdef notdef
311 { "mail", validate_user, sendmail, recvmail, 1 },
312#endif
313 { 0 }
314};
315
316struct options {
317 char *o_type;
318 char *o_request;
319 int o_reply; /* turn into union if need be */
320} options[] = {
321 { "tsize" }, /* OPT_TSIZE */
322 { "timeout" }, /* OPT_TIMEOUT */
323 { NULL }
324};
325
326enum opt_enum {
327 OPT_TSIZE = 0,
328 OPT_TIMEOUT,
329};
330
314/*
315 * Handle initial connection protocol.
316 */
317void
318tftp(tp, size)
319 struct tftphdr *tp;
320 int size;
321{
322 register char *cp;
331/*
332 * Handle initial connection protocol.
333 */
334void
335tftp(tp, size)
336 struct tftphdr *tp;
337 int size;
338{
339 register char *cp;
323 int first = 1, ecode;
340 int i, first = 1, has_options = 0, ecode;
324 register struct formats *pf;
341 register struct formats *pf;
325 char *filename, *mode;
342 char *filename, *mode, *option, *ccp;
326
327 filename = cp = tp->th_stuff;
328again:
329 while (cp < buf + size) {
330 if (*cp == '\0')
331 break;
332 cp++;
333 }

--- 11 unchanged lines hidden (view full) ---

345 *cp = tolower(*cp);
346 for (pf = formats; pf->f_mode; pf++)
347 if (strcmp(pf->f_mode, mode) == 0)
348 break;
349 if (pf->f_mode == 0) {
350 nak(EBADOP);
351 exit(1);
352 }
343
344 filename = cp = tp->th_stuff;
345again:
346 while (cp < buf + size) {
347 if (*cp == '\0')
348 break;
349 cp++;
350 }

--- 11 unchanged lines hidden (view full) ---

362 *cp = tolower(*cp);
363 for (pf = formats; pf->f_mode; pf++)
364 if (strcmp(pf->f_mode, mode) == 0)
365 break;
366 if (pf->f_mode == 0) {
367 nak(EBADOP);
368 exit(1);
369 }
370 while (++cp < buf + size) {
371 for (i = 2, ccp = cp; i > 0; ccp++) {
372 if (ccp >= buf + size) {
373 nak(EBADOP);
374 exit(1);
375 } else if (*ccp == '\0')
376 i--;
377 }
378 for (option = cp; *cp; cp++)
379 if (isupper(*cp))
380 *cp = tolower(*cp);
381 for (i = 0; options[i].o_type != NULL; i++)
382 if (strcmp(option, options[i].o_type) == 0) {
383 options[i].o_request = ++cp;
384 has_options = 1;
385 }
386 cp = ccp-1;
387 }
388
389 if (options[OPT_TIMEOUT].o_request) {
390 int to = atoi(options[OPT_TIMEOUT].o_request);
391 if (to < 1 || to > 255) {
392 nak(EBADOP);
393 exit(1);
394 }
395 else if (to <= max_rexmtval)
396 options[OPT_TIMEOUT].o_reply = rexmtval = to;
397 else
398 options[OPT_TIMEOUT].o_request = NULL;
399 }
400
353 ecode = (*pf->f_validate)(&filename, tp->th_opcode);
401 ecode = (*pf->f_validate)(&filename, tp->th_opcode);
402 if (has_options)
403 oack();
354 if (logging) {
355 char host[MAXHOSTNAMELEN];
356
357 realhostname(host, sizeof(host) - 1, &from.sin_addr);
358 host[sizeof(host) - 1] = '\0';
359 syslog(LOG_INFO, "%s: %s request for %s: %s", host,
360 tp->th_opcode == WRQ ? "write" : "read",
361 filename, errtomsg(ecode));

--- 101 unchanged lines hidden (view full) ---

463 }
464 err = EACCESS;
465 }
466 }
467 if (dirp->name == NULL)
468 return (err);
469 *filep = filename = pathname;
470 }
404 if (logging) {
405 char host[MAXHOSTNAMELEN];
406
407 realhostname(host, sizeof(host) - 1, &from.sin_addr);
408 host[sizeof(host) - 1] = '\0';
409 syslog(LOG_INFO, "%s: %s request for %s: %s", host,
410 tp->th_opcode == WRQ ? "write" : "read",
411 filename, errtomsg(ecode));

--- 101 unchanged lines hidden (view full) ---

513 }
514 err = EACCESS;
515 }
516 }
517 if (dirp->name == NULL)
518 return (err);
519 *filep = filename = pathname;
520 }
521 if (options[OPT_TSIZE].o_request) {
522 if (mode == RRQ)
523 options[OPT_TSIZE].o_reply = stbuf.st_size;
524 else
525 /* XXX Allows writes of all sizes. */
526 options[OPT_TSIZE].o_reply =
527 atoi(options[OPT_TSIZE].o_request);
528 }
471 fd = open(filename, mode == RRQ ? O_RDONLY : O_WRONLY|O_TRUNC);
472 if (fd < 0)
473 return (errno + 100);
474 file = fdopen(fd, (mode == RRQ)? "r":"w");
475 if (file == NULL) {
476 return errno+100;
477 }
478 return (0);
479}
480
529 fd = open(filename, mode == RRQ ? O_RDONLY : O_WRONLY|O_TRUNC);
530 if (fd < 0)
531 return (errno + 100);
532 file = fdopen(fd, (mode == RRQ)? "r":"w");
533 if (file == NULL) {
534 return errno+100;
535 }
536 return (0);
537}
538
481int timeout;
539int timeouts;
482jmp_buf timeoutbuf;
483
484void
485timer()
486{
540jmp_buf timeoutbuf;
541
542void
543timer()
544{
487
488 timeout += rexmtval;
489 if (timeout >= maxtimeout)
545 if (++timeouts > MAX_TIMEOUTS)
490 exit(1);
491 longjmp(timeoutbuf, 1);
492}
493
494/*
495 * Send the requested file.
496 */
497void

--- 12 unchanged lines hidden (view full) ---

510 do {
511 size = readit(file, &dp, pf->f_convert);
512 if (size < 0) {
513 nak(errno + 100);
514 goto abort;
515 }
516 dp->th_opcode = htons((u_short)DATA);
517 dp->th_block = htons((u_short)block);
546 exit(1);
547 longjmp(timeoutbuf, 1);
548}
549
550/*
551 * Send the requested file.
552 */
553void

--- 12 unchanged lines hidden (view full) ---

566 do {
567 size = readit(file, &dp, pf->f_convert);
568 if (size < 0) {
569 nak(errno + 100);
570 goto abort;
571 }
572 dp->th_opcode = htons((u_short)DATA);
573 dp->th_block = htons((u_short)block);
518 timeout = 0;
574 timeouts = 0;
519 (void)setjmp(timeoutbuf);
520
521send_data:
522 if (send(peer, dp, size + 4, 0) != size + 4) {
523 syslog(LOG_ERR, "write: %m");
524 goto abort;
525 }
526 read_ahead(file, pf->f_convert);

--- 46 unchanged lines hidden (view full) ---

573 register int n, size;
574 volatile unsigned short block;
575
576 signal(SIGALRM, timer);
577 dp = w_init();
578 ap = (struct tftphdr *)ackbuf;
579 block = 0;
580 do {
575 (void)setjmp(timeoutbuf);
576
577send_data:
578 if (send(peer, dp, size + 4, 0) != size + 4) {
579 syslog(LOG_ERR, "write: %m");
580 goto abort;
581 }
582 read_ahead(file, pf->f_convert);

--- 46 unchanged lines hidden (view full) ---

629 register int n, size;
630 volatile unsigned short block;
631
632 signal(SIGALRM, timer);
633 dp = w_init();
634 ap = (struct tftphdr *)ackbuf;
635 block = 0;
636 do {
581 timeout = 0;
637 timeouts = 0;
582 ap->th_opcode = htons((u_short)ACK);
583 ap->th_block = htons((u_short)block);
584 block++;
585 (void) setjmp(timeoutbuf);
586send_ack:
587 if (send(peer, ackbuf, 4, 0) != 4) {
588 syslog(LOG_ERR, "write: %m");
589 goto abort;

--- 56 unchanged lines hidden (view full) ---

646 { EUNDEF, "Undefined error code" },
647 { ENOTFOUND, "File not found" },
648 { EACCESS, "Access violation" },
649 { ENOSPACE, "Disk full or allocation exceeded" },
650 { EBADOP, "Illegal TFTP operation" },
651 { EBADID, "Unknown transfer ID" },
652 { EEXISTS, "File already exists" },
653 { ENOUSER, "No such user" },
638 ap->th_opcode = htons((u_short)ACK);
639 ap->th_block = htons((u_short)block);
640 block++;
641 (void) setjmp(timeoutbuf);
642send_ack:
643 if (send(peer, ackbuf, 4, 0) != 4) {
644 syslog(LOG_ERR, "write: %m");
645 goto abort;

--- 56 unchanged lines hidden (view full) ---

702 { EUNDEF, "Undefined error code" },
703 { ENOTFOUND, "File not found" },
704 { EACCESS, "Access violation" },
705 { ENOSPACE, "Disk full or allocation exceeded" },
706 { EBADOP, "Illegal TFTP operation" },
707 { EBADID, "Unknown transfer ID" },
708 { EEXISTS, "File already exists" },
709 { ENOUSER, "No such user" },
710 { EOPTNEG, "Option negotiation" },
654 { -1, 0 }
655};
656
657static char *
658errtomsg(error)
659 int error;
660{
661 static char buf[20];

--- 33 unchanged lines hidden (view full) ---

695 }
696 strcpy(tp->th_msg, pe->e_msg);
697 length = strlen(pe->e_msg);
698 tp->th_msg[length] = '\0';
699 length += 5;
700 if (send(peer, buf, length, 0) != length)
701 syslog(LOG_ERR, "nak: %m");
702}
711 { -1, 0 }
712};
713
714static char *
715errtomsg(error)
716 int error;
717{
718 static char buf[20];

--- 33 unchanged lines hidden (view full) ---

752 }
753 strcpy(tp->th_msg, pe->e_msg);
754 length = strlen(pe->e_msg);
755 tp->th_msg[length] = '\0';
756 length += 5;
757 if (send(peer, buf, length, 0) != length)
758 syslog(LOG_ERR, "nak: %m");
759}
760
761/*
762 * Send an oack packet (option acknowledgement).
763 */
764static void
765oack()
766{
767 struct tftphdr *tp, *ap;
768 int size, i, n;
769 char *bp;
770
771 tp = (struct tftphdr *)buf;
772 bp = buf + 2;
773 size = sizeof(buf) - 2;
774 tp->th_opcode = htons((u_short)OACK);
775 for (i = 0; options[i].o_type != NULL; i++) {
776 if (options[i].o_request) {
777 n = snprintf(bp, size, "%s%c%d", options[i].o_type,
778 0, options[i].o_reply);
779 bp += n+1;
780 size -= n+1;
781 if (size < 0) {
782 syslog(LOG_ERR, "oack: buffer overflow");
783 exit(1);
784 }
785 }
786 }
787 size = bp - buf;
788 ap = (struct tftphdr *)ackbuf;
789 signal(SIGALRM, timer);
790 timeouts = 0;
791
792 (void)setjmp(timeoutbuf);
793 if (send(peer, buf, size, 0) != size) {
794 syslog(LOG_INFO, "oack: %m");
795 exit(1);
796 }
797
798 for (;;) {
799 alarm(rexmtval);
800 n = recv(peer, ackbuf, sizeof (ackbuf), 0);
801 alarm(0);
802 if (n < 0) {
803 syslog(LOG_ERR, "recv: %m");
804 exit(1);
805 }
806 ap->th_opcode = ntohs((u_short)ap->th_opcode);
807 ap->th_block = ntohs((u_short)ap->th_block);
808 if (ap->th_opcode == ERROR)
809 exit(1);
810 if (ap->th_opcode == ACK && ap->th_block == 0)
811 break;
812 }
813}