aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2008-07-08 17:14:44 -0400
committerH. Peter Anvin <hpa@zytor.com>2008-07-08 17:14:44 -0400
commit22accddda0b5a47cb2f6ace54a359e102c31ec02 (patch)
tree5704229813beaa717bce4fb06d46d510dd03fa1f
parent62533e74411a579e5d24e33b50c5ba750b88ae35 (diff)
downloadtftp-hpa-22accddda0b5a47cb2f6ace54a359e102c31ec02.tar.gz
Reformat the source code
The source code was a mix of different styles; normalize on NASM style; basically K&R style with 4 space indentation.
-rw-r--r--common/tftpsubs.c374
-rw-r--r--common/tftpsubs.h13
-rw-r--r--config.h8
-rw-r--r--lib/bsdsignal.c27
-rw-r--r--lib/daemon.c43
-rw-r--r--lib/dup2.c18
-rw-r--r--lib/xmalloc.c12
-rw-r--r--lib/xstrdup.c12
-rw-r--r--tftp/extern.h4
-rw-r--r--tftp/main.c1412
-rw-r--r--tftp/tftp.c669
-rw-r--r--tftpd/misc.c51
-rw-r--r--tftpd/recvfrom.c188
-rw-r--r--tftpd/recvfrom.h6
-rw-r--r--tftpd/remap.c681
-rw-r--r--tftpd/remap.h11
-rw-r--r--tftpd/tftpd.c2201
-rw-r--r--tftpd/tftpd.h2
18 files changed, 2853 insertions, 2879 deletions
diff --git a/common/tftpsubs.c b/common/tftpsubs.c
index b2eae71..b266efe 100644
--- a/common/tftpsubs.c
+++ b/common/tftpsubs.c
@@ -41,9 +41,8 @@
#ifndef lint
/* static char sccsid[] = "@(#)tftpsubs.c 8.1 (Berkeley) 6/6/93"; */
/* static char rcsid[] = "$OpenBSD: tftpsubs.c,v 1.2 1996/06/26 05:40:36 deraadt Exp $"; */
-static const char *rcsid UNUSED =
-"tftp-hpa: $Id$";
-#endif /* not lint */
+static const char *rcsid UNUSED = "tftp-hpa: $Id$";
+#endif /* not lint */
/* Simple minded read-ahead/write-behind subroutines for tftp user and
server. Written originally with multiple buffers in mind, but current
@@ -58,127 +57,130 @@ static const char *rcsid UNUSED =
#include <sys/ioctl.h>
-#define PKTSIZE MAX_SEGSIZE+4 /* should be moved to tftp.h */
+#define PKTSIZE MAX_SEGSIZE+4 /* should be moved to tftp.h */
-int segsize = SEGSIZE; /* Default segsize */
+int segsize = SEGSIZE; /* Default segsize */
struct bf {
- int counter; /* size of data in buffer, or flag */
- char buf[PKTSIZE]; /* room for data packet */
+ int counter; /* size of data in buffer, or flag */
+ char buf[PKTSIZE]; /* room for data packet */
} bfs[2];
- /* Values for bf.counter */
+ /* Values for bf.counter */
#define BF_ALLOC -3 /* alloc'd but not yet filled */
#define BF_FREE -2 /* free */
/* [-1 .. segsize] = size of data in the data buffer */
-static int nextone; /* index of next buffer to use */
-static int current; /* index of buffer in use */
+static int nextone; /* index of next buffer to use */
+static int current; /* index of buffer in use */
- /* control flags for crlf conversions */
-int newline = 0; /* fillbuf: in middle of newline expansion */
-int prevchar = -1; /* putbuf: previous char (cr check) */
+ /* control flags for crlf conversions */
+int newline = 0; /* fillbuf: in middle of newline expansion */
+int prevchar = -1; /* putbuf: previous char (cr check) */
static struct tftphdr *rw_init(int);
-struct tftphdr *w_init() { return rw_init(0); } /* write-behind */
-struct tftphdr *r_init() { return rw_init(1); } /* read-ahead */
+struct tftphdr *w_init()
+{
+ return rw_init(0);
+} /* write-behind */
+
+struct tftphdr *r_init()
+{
+ return rw_init(1);
+} /* read-ahead */
/* init for either read-ahead or write-behind */
/* x == zero for write-behind, one for read-head */
-static struct tftphdr *
-rw_init(int x)
+static struct tftphdr *rw_init(int x)
{
- newline = 0; /* init crlf flag */
- prevchar = -1;
- bfs[0].counter = BF_ALLOC; /* pass out the first buffer */
- current = 0;
- bfs[1].counter = BF_FREE;
- nextone = x; /* ahead or behind? */
- return (struct tftphdr *)bfs[0].buf;
+ newline = 0; /* init crlf flag */
+ prevchar = -1;
+ bfs[0].counter = BF_ALLOC; /* pass out the first buffer */
+ current = 0;
+ bfs[1].counter = BF_FREE;
+ nextone = x; /* ahead or behind? */
+ return (struct tftphdr *)bfs[0].buf;
}
-
/* Have emptied current buffer by sending to net and getting ack.
Free it and return next buffer filled with data.
*/
-int
-readit(FILE *file, struct tftphdr **dpp, int convert)
+int readit(FILE * file, struct tftphdr **dpp, int convert)
{
- struct bf *b;
+ struct bf *b;
- bfs[current].counter = BF_FREE; /* free old one */
- current = !current; /* "incr" current */
+ bfs[current].counter = BF_FREE; /* free old one */
+ current = !current; /* "incr" current */
- b = &bfs[current]; /* look at new buffer */
- if (b->counter == BF_FREE) /* if it's empty */
- read_ahead(file, convert); /* fill it */
-/* assert(b->counter != BF_FREE);*//* check */
- *dpp = (struct tftphdr *)b->buf; /* set caller's ptr */
- return b->counter;
+ b = &bfs[current]; /* look at new buffer */
+ if (b->counter == BF_FREE) /* if it's empty */
+ read_ahead(file, convert); /* fill it */
+ /* assert(b->counter != BF_FREE);*//* check */
+ *dpp = (struct tftphdr *)b->buf; /* set caller's ptr */
+ return b->counter;
}
/*
* fill the input buffer, doing ascii conversions if requested
* conversions are lf -> cr,lf and cr -> cr, nul
*/
-void
-read_ahead(FILE *file, int convert)
+void read_ahead(FILE * file, int convert)
{
- int i;
- char *p;
- int c;
- struct bf *b;
- struct tftphdr *dp;
-
- b = &bfs[nextone]; /* look at "next" buffer */
- if (b->counter != BF_FREE) /* nop if not free */
- return;
- nextone = !nextone; /* "incr" next buffer ptr */
-
- dp = (struct tftphdr *)b->buf;
-
- if (convert == 0) {
- b->counter = read(fileno(file), dp->th_data, segsize);
- return;
- }
-
- p = dp->th_data;
- for (i = 0 ; i < segsize; i++) {
- if (newline) {
- if (prevchar == '\n')
- c = '\n'; /* lf to cr,lf */
- else c = '\0'; /* cr to cr,nul */
- newline = 0;
- }
- else {
- c = getc(file);
- if (c == EOF) break;
- if (c == '\n' || c == '\r') {
- prevchar = c;
- c = '\r';
- newline = 1;
- }
- }
- *p++ = c;
- }
- b->counter = (int)(p - dp->th_data);
+ int i;
+ char *p;
+ int c;
+ struct bf *b;
+ struct tftphdr *dp;
+
+ b = &bfs[nextone]; /* look at "next" buffer */
+ if (b->counter != BF_FREE) /* nop if not free */
+ return;
+ nextone = !nextone; /* "incr" next buffer ptr */
+
+ dp = (struct tftphdr *)b->buf;
+
+ if (convert == 0) {
+ b->counter = read(fileno(file), dp->th_data, segsize);
+ return;
+ }
+
+ p = dp->th_data;
+ for (i = 0; i < segsize; i++) {
+ if (newline) {
+ if (prevchar == '\n')
+ c = '\n'; /* lf to cr,lf */
+ else
+ c = '\0'; /* cr to cr,nul */
+ newline = 0;
+ } else {
+ c = getc(file);
+ if (c == EOF)
+ break;
+ if (c == '\n' || c == '\r') {
+ prevchar = c;
+ c = '\r';
+ newline = 1;
+ }
+ }
+ *p++ = c;
+ }
+ b->counter = (int)(p - dp->th_data);
}
/* Update count associated with the buffer, get new buffer
from the queue. Calls write_behind only if next buffer not
available.
*/
-int
-writeit(FILE *file, struct tftphdr **dpp, int ct, int convert)
+int writeit(FILE * file, struct tftphdr **dpp, int ct, int convert)
{
- bfs[current].counter = ct; /* set size of data to write */
- current = !current; /* switch to other buffer */
- if (bfs[current].counter != BF_FREE) /* if not free */
- (void)write_behind(file, convert); /* flush it */
- bfs[current].counter = BF_ALLOC; /* mark as alloc'd */
- *dpp = (struct tftphdr *)bfs[current].buf;
- return ct; /* this is a lie of course */
+ bfs[current].counter = ct; /* set size of data to write */
+ current = !current; /* switch to other buffer */
+ if (bfs[current].counter != BF_FREE) /* if not free */
+ (void)write_behind(file, convert); /* flush it */
+ bfs[current].counter = BF_ALLOC; /* mark as alloc'd */
+ *dpp = (struct tftphdr *)bfs[current].buf;
+ return ct; /* this is a lie of course */
}
/*
@@ -187,52 +189,50 @@ writeit(FILE *file, struct tftphdr **dpp, int ct, int convert)
* Note spec is undefined if we get CR as last byte of file or a
* CR followed by anything else. In this case we leave it alone.
*/
-int
-write_behind(FILE *file, int convert)
+int write_behind(FILE * file, int convert)
{
- char *buf;
- int count;
- int ct;
- char *p;
- int c; /* current character */
- struct bf *b;
- struct tftphdr *dp;
-
- b = &bfs[nextone];
- if (b->counter < -1) /* anything to flush? */
- return 0; /* just nop if nothing to do */
-
- count = b->counter; /* remember byte count */
- b->counter = BF_FREE; /* reset flag */
- dp = (struct tftphdr *)b->buf;
- nextone = !nextone; /* incr for next time */
- buf = dp->th_data;
-
- if (count <= 0) return -1; /* nak logic? */
-
- if (convert == 0)
- return write(fileno(file), buf, count);
-
- p = buf;
- ct = count;
- while (ct--) { /* loop over the buffer */
- c = *p++; /* pick up a character */
- if (prevchar == '\r') { /* if prev char was cr */
- if (c == '\n') /* if have cr,lf then just */
- fseek(file, -1, 1); /* smash lf on top of the cr */
- else
- if (c == '\0') /* if have cr,nul then */
- goto skipit; /* just skip over the putc */
- /* else just fall through and allow it */
- }
- putc(c, file);
-skipit:
- prevchar = c;
- }
- return count;
+ char *buf;
+ int count;
+ int ct;
+ char *p;
+ int c; /* current character */
+ struct bf *b;
+ struct tftphdr *dp;
+
+ b = &bfs[nextone];
+ if (b->counter < -1) /* anything to flush? */
+ return 0; /* just nop if nothing to do */
+
+ count = b->counter; /* remember byte count */
+ b->counter = BF_FREE; /* reset flag */
+ dp = (struct tftphdr *)b->buf;
+ nextone = !nextone; /* incr for next time */
+ buf = dp->th_data;
+
+ if (count <= 0)
+ return -1; /* nak logic? */
+
+ if (convert == 0)
+ return write(fileno(file), buf, count);
+
+ p = buf;
+ ct = count;
+ while (ct--) { /* loop over the buffer */
+ c = *p++; /* pick up a character */
+ if (prevchar == '\r') { /* if prev char was cr */
+ if (c == '\n') /* if have cr,lf then just */
+ fseek(file, -1, 1); /* smash lf on top of the cr */
+ else if (c == '\0') /* if have cr,nul then */
+ goto skipit; /* just skip over the putc */
+ /* else just fall through and allow it */
+ }
+ putc(c, file);
+ skipit:
+ prevchar = c;
+ }
+ return count;
}
-
/* When an error has occurred, it is possible that the two sides
* are out of synch. Ie: that what I think is the other side's
* response to packet N is really their response to packet N-1.
@@ -244,69 +244,69 @@ skipit:
* when trace is active).
*/
-int
-synchnet(int f) /* socket to flush */
-{
- int pktcount = 0;
- char rbuf[PKTSIZE];
- struct sockaddr_in from;
- socklen_t fromlen;
- fd_set socketset;
- struct timeval notime;
-
- while ( 1 ) {
- notime.tv_sec = notime.tv_usec = 0;
-
- FD_ZERO(&socketset);
- FD_SET(f, &socketset);
-
- if ( select(f, &socketset, NULL, NULL, &notime) <= 0 )
- break; /* Nothing to read */
-
- /* Otherwise drain the packet */
- pktcount++;
- fromlen = sizeof from;
- (void) recvfrom(f, rbuf, sizeof (rbuf), 0,
- (struct sockaddr *)&from, &fromlen);
- }
-
- return pktcount; /* Return packets drained */
-}
+int synchnet(int f)
+{ /* socket to flush */
+ int pktcount = 0;
+ char rbuf[PKTSIZE];
+ struct sockaddr_in from;
+ socklen_t fromlen;
+ fd_set socketset;
+ struct timeval notime;
+
+ while (1) {
+ notime.tv_sec = notime.tv_usec = 0;
+
+ FD_ZERO(&socketset);
+ FD_SET(f, &socketset);
+
+ if (select(f, &socketset, NULL, NULL, &notime) <= 0)
+ break; /* Nothing to read */
+
+ /* Otherwise drain the packet */
+ pktcount++;
+ fromlen = sizeof from;
+ (void)recvfrom(f, rbuf, sizeof(rbuf), 0,
+ (struct sockaddr *)&from, &fromlen);
+ }
+ return pktcount; /* Return packets drained */
+}
-int pick_port_bind(int sockfd, struct sockaddr_in *myaddr, unsigned int port_range_from, unsigned int port_range_to)
+int pick_port_bind(int sockfd, struct sockaddr_in *myaddr,
+ unsigned int port_range_from,
+ unsigned int port_range_to)
{
- unsigned int port, firstport;
- int port_range = 0;
-
- if (port_range_from != 0 && port_range_to != 0) {
- port_range = 1;
- }
-
- firstport = port_range
- ? port_range_from + rand() % (port_range_to-port_range_from+1)
- : 0;
-
- port = firstport;
-
- do {
- myaddr->sin_port = htons(port);
-
- if (bind(sockfd, (struct sockaddr *)myaddr, sizeof *myaddr) < 0) {
- /* Some versions of Linux return EINVAL instead of EADDRINUSE */
- if ( !(port_range && (errno == EINVAL || errno == EADDRINUSE)) )
- return -1;
-
- /* Normally, we shouldn't have to loop, but some situations involving
- aborted transfers make it possible. */
- } else {
- return 0;
+ unsigned int port, firstport;
+ int port_range = 0;
+
+ if (port_range_from != 0 && port_range_to != 0) {
+ port_range = 1;
}
- port++;
- if ( port > port_range_to )
- port = port_range_from;
- } while ( port != firstport );
+ firstport = port_range
+ ? port_range_from + rand() % (port_range_to - port_range_from + 1)
+ : 0;
+
+ port = firstport;
+
+ do {
+ myaddr->sin_port = htons(port);
+
+ if (bind(sockfd, (struct sockaddr *)myaddr, sizeof *myaddr) < 0) {
+ /* Some versions of Linux return EINVAL instead of EADDRINUSE */
+ if (!(port_range && (errno == EINVAL || errno == EADDRINUSE)))
+ return -1;
+
+ /* Normally, we shouldn't have to loop, but some situations involving
+ aborted transfers make it possible. */
+ } else {
+ return 0;
+ }
+
+ port++;
+ if (port > port_range_to)
+ port = port_range_from;
+ } while (port != firstport);
- return -1;
+ return -1;
}
diff --git a/common/tftpsubs.h b/common/tftpsubs.h
index f986afc..f1269fd 100644
--- a/common/tftpsubs.h
+++ b/common/tftpsubs.h
@@ -50,18 +50,19 @@
struct tftphdr;
struct tftphdr *r_init(void);
-void read_ahead(FILE *, int);
-int readit(FILE *, struct tftphdr **, int);
+void read_ahead(FILE *, int);
+int readit(FILE *, struct tftphdr **, int);
-int synchnet(int);
+int synchnet(int);
struct tftphdr *w_init(void);
-int write_behind(FILE *, int);
-int writeit(FILE *, struct tftphdr **, int, int);
+int write_behind(FILE *, int);
+int writeit(FILE *, struct tftphdr **, int, int);
extern int segsize;
#define MAX_SEGSIZE 65464
-int pick_port_bind(int sockfd, struct sockaddr_in *myaddr, unsigned int from, unsigned int to);
+int pick_port_bind(int sockfd, struct sockaddr_in *myaddr,
+ unsigned int from, unsigned int to);
#endif
diff --git a/config.h b/config.h
index e4c5cc2..9c973b7 100644
--- a/config.h
+++ b/config.h
@@ -1,5 +1,5 @@
/* -*- c -*- ------------------------------------------------------------- *
- *
+ *
* Copyright 2001-2006 H. Peter Anvin - All Rights Reserved
*
* This program is free software available under the same license
@@ -19,7 +19,7 @@
#define CONFIG_H 1
/* Must be included before we include any system headers! */
-#include "aconfig.h" /* autogenerated configuration header */
+#include "aconfig.h" /* autogenerated configuration header */
/* Standard includes */
@@ -54,7 +54,7 @@
#ifdef HAVE_STRINGS_H
#include <strings.h>
-#endif
+#endif
#ifdef HAVE_INTTYPES_H
#ifdef INTTYPES_H_IS_SANE
@@ -293,7 +293,7 @@ void *xmalloc(size_t);
char *xstrdup(const char *);
#ifndef HAVE_BSD_SIGNAL
-void (*bsd_signal(int, void (*)(int)))(int);
+void (*bsd_signal(int, void (*)(int))) (int);
#endif
#ifndef HAVE_DUP2
int dup2(int, int);
diff --git a/lib/bsdsignal.c b/lib/bsdsignal.c
index 92de999..0aae136 100644
--- a/lib/bsdsignal.c
+++ b/lib/bsdsignal.c
@@ -6,23 +6,22 @@
#include "config.h"
-void (*bsd_signal(int signum, void (*handler)(int)))(int)
-{
- struct sigaction action, oldaction;
+void (*bsd_signal(int signum, void (*handler) (int))) (int) {
+ struct sigaction action, oldaction;
- memset(&action, 0, sizeof action);
- action.sa_handler = handler;
- sigemptyset(&action.sa_mask);
- sigaddset(&action.sa_mask, signum);
- action.sa_flags = SA_RESTART;
-
- if (sigaction(signum, &action, &oldaction) == -1) {
+ memset(&action, 0, sizeof action);
+ action.sa_handler = handler;
+ sigemptyset(&action.sa_mask);
+ sigaddset(&action.sa_mask, signum);
+ action.sa_flags = SA_RESTART;
+
+ if (sigaction(signum, &action, &oldaction) == -1) {
#ifdef SIG_ERR
- return SIG_ERR;
+ return SIG_ERR;
#else
- return NULL;
+ return NULL;
#endif
- }
+ }
- return oldaction.sa_handler;
+ return oldaction.sa_handler;
}
diff --git a/lib/daemon.c b/lib/daemon.c
index c3106b5..0eb39c9 100644
--- a/lib/daemon.c
+++ b/lib/daemon.c
@@ -6,32 +6,31 @@
int daemon(int nochdir, int noclose)
{
- int nullfd;
- pid_t f;
-
- if (!nochdir) {
- if (chdir("/"))
- return -1;
- }
+ int nullfd;
+ pid_t f;
- if (!noclose) {
- if ((nullfd = open("/dev/null", O_RDWR)) < 0 ||
- dup2(nullfd, 0) < 0 ||
- dup2(nullfd, 1) < 0 ||
- dup2(nullfd, 2) < 0)
- return -1;
- close(nullfd);
- }
+ if (!nochdir) {
+ if (chdir("/"))
+ return -1;
+ }
- f = fork();
- if (f < 0)
- return -1;
- else if (f > 0)
- _exit(0);
+ if (!noclose) {
+ if ((nullfd = open("/dev/null", O_RDWR)) < 0 ||
+ dup2(nullfd, 0) < 0 ||
+ dup2(nullfd, 1) < 0 || dup2(nullfd, 2) < 0)
+ return -1;
+ close(nullfd);
+ }
+
+ f = fork();
+ if (f < 0)
+ return -1;
+ else if (f > 0)
+ _exit(0);
#ifdef HAVE_SETSID
- return setsid();
+ return setsid();
#else
- return 0;
+ return 0;
#endif
}
diff --git a/lib/dup2.c b/lib/dup2.c
index bdf3325..bba45c4 100644
--- a/lib/dup2.c
+++ b/lib/dup2.c
@@ -8,18 +8,16 @@
int dup2(int oldfd, int newfd)
{
- int rv, nfd;
+ int rv, nfd;
- close(newfd);
+ close(newfd);
- nfd = rv = dup(oldfd);
+ nfd = rv = dup(oldfd);
- if (rv >= 0 && rv != newfd) {
- rv = dup2(oldfd, newfd);
- close(nfd);
- }
+ if (rv >= 0 && rv != newfd) {
+ rv = dup2(oldfd, newfd);
+ close(nfd);
+ }
- return rv;
+ return rv;
}
-
-
diff --git a/lib/xmalloc.c b/lib/xmalloc.c
index f234a46..30704f3 100644
--- a/lib/xmalloc.c
+++ b/lib/xmalloc.c
@@ -9,12 +9,12 @@
void *xmalloc(size_t size)
{
- void *p = malloc(size);
+ void *p = malloc(size);
- if ( !p ) {
- fprintf(stderr, "Out of memory!\n");
- exit(128);
- }
+ if (!p) {
+ fprintf(stderr, "Out of memory!\n");
+ exit(128);
+ }
- return p;
+ return p;
}
diff --git a/lib/xstrdup.c b/lib/xstrdup.c
index 036b3b2..05e3054 100644
--- a/lib/xstrdup.c
+++ b/lib/xstrdup.c
@@ -9,12 +9,12 @@
char *xstrdup(const char *s)
{
- char *p = strdup(s);
+ char *p = strdup(s);
- if ( !p ) {
- fprintf(stderr, "Out of memory!\n");
- exit(128);
- }
+ if (!p) {
+ fprintf(stderr, "Out of memory!\n");
+ exit(128);
+ }
- return p;
+ return p;
}
diff --git a/tftp/extern.h b/tftp/extern.h
index 401608e..bfe9a97 100644
--- a/tftp/extern.h
+++ b/tftp/extern.h
@@ -41,7 +41,7 @@
#ifndef RECVFILE_H
#define RECVFILE_H
-void tftp_recvfile (int, const char *, const char *);
-void tftp_sendfile (int, const char *, const char *);
+void tftp_recvfile(int, const char *, const char *);
+void tftp_sendfile(int, const char *, const char *);
#endif
diff --git a/tftp/main.c b/tftp/main.c
index 6bc7c44..bd041a8 100644
--- a/tftp/main.c
+++ b/tftp/main.c
@@ -37,14 +37,12 @@
#include "common/tftpsubs.h"
#ifndef lint
-static const char *copyright UNUSED =
-"@(#) Copyright (c) 1983, 1993\n\
+static const char *copyright UNUSED = "@(#) Copyright (c) 1983, 1993\n\
The Regents of the University of California. All rights reserved.\n";
/* static char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/6/93"; */
/* static char rcsid[] = "$OpenBSD: main.c,v 1.4 1997/01/17 07:13:30 millert Exp $"; */
-static const char *rcsid UNUSED =
- "tftp-hpa $Id$";
-#endif /* not lint */
+static const char *rcsid UNUSED = "tftp-hpa $Id$";
+#endif /* not lint */
/* Many bug fixes are from Jim Guyton <guyton@rand-unix> */
@@ -63,131 +61,132 @@ static const char *rcsid UNUSED =
#include "extern.h"
-#define TIMEOUT 5 /* secs between rexmt's */
-#define LBUFLEN 200 /* size of input buffer */
+#define TIMEOUT 5 /* secs between rexmt's */
+#define LBUFLEN 200 /* size of input buffer */
struct modes {
- const char *m_name;
- const char *m_mode;
- int m_openflags;
+ const char *m_name;
+ const char *m_mode;
+ int m_openflags;
};
static const struct modes modes[] = {
- { "netascii", "netascii", O_TEXT },
- { "ascii", "netascii", O_TEXT },
- { "octet", "octet", O_BINARY },
- { "binary", "octet", O_BINARY },
- { "image", "octet", O_BINARY },
- { 0, 0, 0 }
+ {"netascii", "netascii", O_TEXT},
+ {"ascii", "netascii", O_TEXT},
+ {"octet", "octet", O_BINARY},
+ {"binary", "octet", O_BINARY},
+ {"image", "octet", O_BINARY},
+ {0, 0, 0}
};
+
#define MODE_OCTET (&modes[2])
#define MODE_NETASCII (&modes[0])
#define MODE_DEFAULT MODE_NETASCII
-struct sockaddr_in peeraddr;
-int f;
+struct sockaddr_in peeraddr;
+int f;
u_short port;
-int trace;
-int verbose;
-int literal;
-int connected;
+int trace;
+int verbose;
+int literal;
+int connected;
const struct modes *mode;
#ifdef WITH_READLINE
-char *line = NULL;
+char *line = NULL;
#else
-char line[LBUFLEN];
+char line[LBUFLEN];
#endif
-int margc;
-char *margv[20];
+int margc;
+char *margv[20];
const char *prompt = "tftp> ";
-sigjmp_buf toplevel;
-void intr(int);
-struct servent *sp;
+sigjmp_buf toplevel;
+void intr(int);
+struct servent *sp;
int portrange = 0;
unsigned int portrange_from = 0;
-unsigned int portrange_to = 0;
-
-void get (int, char **);
-void help (int, char **);
-void modecmd (int, char **);
-void put (int, char **);
-void quit (int, char **);
-void setascii (int, char **);
-void setbinary (int, char **);
-void setpeer (int, char **);
-void setrexmt (int, char **);
-void settimeout (int, char **);
-void settrace (int, char **);
-void setverbose (int, char **);
-void status (int, char **);
-void setliteral (int, char **);
-
-static void command (void);
-
-static void getusage (char *);
-static void makeargv (void);
-static void putusage (char *);
-static void settftpmode (const struct modes *);
+unsigned int portrange_to = 0;
+
+void get(int, char **);
+void help(int, char **);
+void modecmd(int, char **);
+void put(int, char **);
+void quit(int, char **);
+void setascii(int, char **);
+void setbinary(int, char **);
+void setpeer(int, char **);
+void setrexmt(int, char **);
+void settimeout(int, char **);
+void settrace(int, char **);
+void setverbose(int, char **);
+void status(int, char **);
+void setliteral(int, char **);
+
+static void command(void);
+
+static void getusage(char *);
+static void makeargv(void);
+static void putusage(char *);
+static void settftpmode(const struct modes *);
#define HELPINDENT (sizeof("connect"))
struct cmd {
- const char *name;
- const char *help;
- void (*handler) (int, char **);
+ const char *name;
+ const char *help;
+ void (*handler) (int, char **);
};
struct cmd cmdtab[] = {
- { "connect",
- "connect to remote tftp",
- setpeer },
- { "mode",
- "set file transfer mode",
- modecmd },
- { "put",
- "send file",
- put },
- { "get",
- "receive file",
- get },
- { "quit",
- "exit tftp",
- quit },
- { "verbose",
- "toggle verbose mode",
- setverbose },
- { "trace",
- "toggle packet tracing",
- settrace },
- { "literal",
- "toggle literal mode, ignore ':' in file name",
- setliteral },
- { "status",
- "show current status",
- status },
- { "binary",
- "set mode to octet",
- setbinary },
- { "ascii",
- "set mode to netascii",
- setascii },
- { "rexmt",
- "set per-packet transmission timeout",
- setrexmt },
- { "timeout",
- "set total retransmission timeout",
- settimeout },
- { "?",
- "print help information",
- help },
- { "help",
- "print help information",
- help },
- { 0, 0, 0 }
+ {"connect",
+ "connect to remote tftp",
+ setpeer},
+ {"mode",
+ "set file transfer mode",
+ modecmd},
+ {"put",
+ "send file",
+ put},
+ {"get",
+ "receive file",
+ get},
+ {"quit",
+ "exit tftp",
+ quit},
+ {"verbose",
+ "toggle verbose mode",
+ setverbose},
+ {"trace",
+ "toggle packet tracing",
+ settrace},
+ {"literal",
+ "toggle literal mode, ignore ':' in file name",
+ setliteral},
+ {"status",
+ "show current status",
+ status},
+ {"binary",
+ "set mode to octet",
+ setbinary},
+ {"ascii",
+ "set mode to netascii",
+ setascii},
+ {"rexmt",
+ "set per-packet transmission timeout",
+ setrexmt},
+ {"timeout",
+ "set total retransmission timeout",
+ settimeout},
+ {"?",
+ "print help information",
+ help},
+ {"help",
+ "print help information",
+ help},
+ {0, 0, 0}
};
-struct cmd *getcmd(char *);
-char *tail(char *);
+struct cmd *getcmd(char *);
+char *tail(char *);
char *xstrdup(const char *);
@@ -195,722 +194,717 @@ const char *program;
static inline void usage(int errcode)
{
- fprintf(stderr, "Usage: %s [-v][-l][-m mode] [host [port]] [-c command]\n", program);
- exit(errcode);
+ fprintf(stderr,
+ "Usage: %s [-v][-l][-m mode] [host [port]] [-c command]\n",
+ program);
+ exit(errcode);
}
-int
-main(int argc, char *argv[])
+int main(int argc, char *argv[])
{
- struct sockaddr_in s_in;
- int arg;
- static int pargc, peerargc;
- static int iscmd = 0;
- char **pargv;
- const char *optx;
- char *peerargv[3];
-
- program = argv[0];
-
- mode = MODE_DEFAULT;
-
- peerargv[0] = argv[0];
- peerargc = 1;
-
- for ( arg = 1 ; !iscmd && arg < argc ; arg++ ) {
- if ( argv[arg][0] == '-' ) {
- for ( optx = &argv[arg][1] ; *optx ; optx++ ) {
- switch ( *optx ) {
- case 'v':
- verbose = 1;
- break;
- case 'V':
- /* Print version and configuration to stdout and exit */
- printf("%s\n", TFTP_CONFIG_STR);
- exit(0);
- case 'l':
- literal = 1;
- break;
- case 'm':
- if ( ++arg >= argc )
- usage(EX_USAGE);
- {
- const struct modes *p;
-
- for ( p = modes ; p->m_name ; p++ ) {
- if (!strcmp(argv[arg], p->m_name))
- break;
- }
- if (p->m_name) {
- settftpmode(p);
- } else {
- fprintf(stderr, "%s: invalid mode: %s\n", argv[0], argv[arg]);
- exit(EX_USAGE);
- }
- }
- break;
- case 'c':
- iscmd = 1;
- break;
- case 'R':
- if ( ++arg >= argc )
- usage(EX_USAGE);
- if ( sscanf(argv[arg], "%u:%u", &portrange_from, &portrange_to) != 2 ||
- portrange_from > portrange_to || portrange_to > 65535 ) {
- fprintf(stderr, "Bad port range: %s\n", argv[arg]);
- exit(EX_USAGE);
- }
- portrange = 1;
- break;
- case 'h':
- default:
- usage(*optx == 'h' ? 0 : EX_USAGE);
- }
- }
- } else {
- if ( peerargc >= 3 )
- usage(EX_USAGE);
-
- peerargv[peerargc++] = argv[arg];
- }
- }
-
- pargv = argv + arg;
- pargc = argc - arg;
-
- sp = getservbyname("tftp", "udp");
- if (sp == 0) {
- /* Use canned values */
- if (verbose)
- fprintf(stderr, "tftp: tftp/udp: unknown service, faking it...\n");
- sp = xmalloc(sizeof(struct servent));
- sp->s_name = (char *)"tftp";
- sp->s_aliases = NULL;
- sp->s_port = htons(IPPORT_TFTP);
- sp->s_proto = (char *)"udp";
- }
- port = sp->s_port; /* Default port */
- f = socket(AF_INET, SOCK_DGRAM, 0);
- if (f < 0) {
- perror("tftp: socket");
- exit(EX_OSERR);
- }
- bzero((char *)&s_in, sizeof (s_in));
- s_in.sin_family = AF_INET;
- if (pick_port_bind(f, &s_in, portrange_from, portrange_to)) {
- perror("tftp: bind");
- exit(EX_OSERR);
- }
- bsd_signal(SIGINT, intr);
-
- if ( peerargc ) {
- /* Set peer */
- if (sigsetjmp(toplevel,1) != 0)
- exit(EX_NOHOST);
- setpeer(peerargc, peerargv);
- }
-
- if ( iscmd && pargc ) {
- /* -c specified; execute command and exit */
- struct cmd *c;
-
- if (sigsetjmp(toplevel,1) != 0)
- exit(EX_UNAVAILABLE);
-
- c = getcmd(pargv[0]);
- if ( c == (struct cmd *)-1 || c == (struct cmd *)0 ) {
- fprintf(stderr, "%s: invalid command: %s\n", argv[0], pargv[1]);
- exit(EX_USAGE);
- }
- (*c->handler)(pargc, pargv);
- exit(0);
- }
-
+ struct sockaddr_in s_in;
+ int arg;
+ static int pargc, peerargc;
+ static int iscmd = 0;
+ char **pargv;
+ const char *optx;
+ char *peerargv[3];
+
+ program = argv[0];
+
+ mode = MODE_DEFAULT;
+
+ peerargv[0] = argv[0];
+ peerargc = 1;
+
+ for (arg = 1; !iscmd && arg < argc; arg++) {
+ if (argv[arg][0] == '-') {
+ for (optx = &argv[arg][1]; *optx; optx++) {
+ switch (*optx) {
+ case 'v':
+ verbose = 1;
+ break;
+ case 'V':
+ /* Print version and configuration to stdout and exit */
+ printf("%s\n", TFTP_CONFIG_STR);
+ exit(0);
+ case 'l':
+ literal = 1;
+ break;
+ case 'm':
+ if (++arg >= argc)
+ usage(EX_USAGE);
+ {
+ const struct modes *p;
+
+ for (p = modes; p->m_name; p++) {
+ if (!strcmp(argv[arg], p->m_name))
+ break;
+ }
+ if (p->m_name) {
+ settftpmode(p);
+ } else {
+ fprintf(stderr, "%s: invalid mode: %s\n",
+ argv[0], argv[arg]);
+ exit(EX_USAGE);
+ }
+ }
+ break;
+ case 'c':
+ iscmd = 1;
+ break;
+ case 'R':
+ if (++arg >= argc)
+ usage(EX_USAGE);
+ if (sscanf
+ (argv[arg], "%u:%u", &portrange_from,
+ &portrange_to) != 2
+ || portrange_from > portrange_to
+ || portrange_to > 65535) {
+ fprintf(stderr, "Bad port range: %s\n", argv[arg]);
+ exit(EX_USAGE);
+ }
+ portrange = 1;
+ break;
+ case 'h':
+ default:
+ usage(*optx == 'h' ? 0 : EX_USAGE);
+ }
+ }
+ } else {
+ if (peerargc >= 3)
+ usage(EX_USAGE);
+
+ peerargv[peerargc++] = argv[arg];
+ }
+ }
+
+ pargv = argv + arg;
+ pargc = argc - arg;
+
+ sp = getservbyname("tftp", "udp");
+ if (sp == 0) {
+ /* Use canned values */
+ if (verbose)
+ fprintf(stderr,
+ "tftp: tftp/udp: unknown service, faking it...\n");
+ sp = xmalloc(sizeof(struct servent));
+ sp->s_name = (char *)"tftp";
+ sp->s_aliases = NULL;
+ sp->s_port = htons(IPPORT_TFTP);
+ sp->s_proto = (char *)"udp";
+ }
+ port = sp->s_port; /* Default port */
+ f = socket(AF_INET, SOCK_DGRAM, 0);
+ if (f < 0) {
+ perror("tftp: socket");
+ exit(EX_OSERR);
+ }
+ bzero((char *)&s_in, sizeof(s_in));
+ s_in.sin_family = AF_INET;
+ if (pick_port_bind(f, &s_in, portrange_from, portrange_to)) {
+ perror("tftp: bind");
+ exit(EX_OSERR);
+ }
+ bsd_signal(SIGINT, intr);
+
+ if (peerargc) {
+ /* Set peer */
+ if (sigsetjmp(toplevel, 1) != 0)
+ exit(EX_NOHOST);
+ setpeer(peerargc, peerargv);
+ }
+
+ if (iscmd && pargc) {
+ /* -c specified; execute command and exit */
+ struct cmd *c;
+
+ if (sigsetjmp(toplevel, 1) != 0)
+ exit(EX_UNAVAILABLE);
+
+ c = getcmd(pargv[0]);
+ if (c == (struct cmd *)-1 || c == (struct cmd *)0) {
+ fprintf(stderr, "%s: invalid command: %s\n", argv[0],
+ pargv[1]);
+ exit(EX_USAGE);
+ }
+ (*c->handler) (pargc, pargv);
+ exit(0);
+ }
#ifdef WITH_READLINE
#ifdef HAVE_READLINE_HISTORY_H
- using_history();
+ using_history();
#endif
#endif
-
- if (sigsetjmp(toplevel,1) != 0)
- (void)putchar('\n');
- command();
-
- return 0; /* Never reached */
+
+ if (sigsetjmp(toplevel, 1) != 0)
+ (void)putchar('\n');
+ command();
+
+ return 0; /* Never reached */
}
-char *hostname;
+char *hostname;
/* Called when a command is incomplete; modifies
the global variable "line" */
-static void
-getmoreargs(const char *partial, const char *mprompt)
+static void getmoreargs(const char *partial, const char *mprompt)
{
#ifdef WITH_READLINE
- char *eline;
- int len, elen;
-
- len = strlen(partial);
- eline = readline(mprompt);
- if (!eline)
- exit(0); /* EOF */
-
- elen = strlen(eline);
-
- if (line) {
- free(line);
- line = NULL;
- }
- line = xmalloc(len+elen+1);
- strcpy(line, partial);
- strcpy(line+len, eline);
- free(eline);
+ char *eline;
+ int len, elen;
+
+ len = strlen(partial);
+ eline = readline(mprompt);
+ if (!eline)
+ exit(0); /* EOF */
+
+ elen = strlen(eline);
+
+ if (line) {
+ free(line);
+ line = NULL;
+ }
+ line = xmalloc(len + elen + 1);
+ strcpy(line, partial);
+ strcpy(line + len, eline);
+ free(eline);
#ifdef HAVE_READLINE_HISTORY_H
- add_history(line);
+ add_history(line);
#endif
#else
- int len = strlen(partial);
-
- strcpy(line, partial);
- fputs(mprompt, stdout);
- if ( fgets(line+len, LBUFLEN-len, stdin) == 0 )
- if ( feof(stdin) )
- exit(0); /* EOF */
+ int len = strlen(partial);
+
+ strcpy(line, partial);
+ fputs(mprompt, stdout);
+ if (fgets(line + len, LBUFLEN - len, stdin) == 0)
+ if (feof(stdin))
+ exit(0); /* EOF */
#endif
}
-void
-setpeer(int argc, char *argv[])
+void setpeer(int argc, char *argv[])
{
- struct hostent *host;
-
- if (argc < 2) {
- getmoreargs("connect ", "(to) ");
- makeargv();
- argc = margc;
- argv = margv;
- }
- if ((argc < 2) || (argc > 3)) {
- printf("usage: %s host-name [port]\n", argv[0]);
- return;
- }
-
- host = gethostbyname(argv[1]);
- if (host == 0) {
- connected = 0;
- printf("%s: unknown host\n", argv[1]);
- return;
- }
- peeraddr.sin_family = host->h_addrtype;
- bcopy(host->h_addr, &peeraddr.sin_addr, host->h_length);
- hostname = xstrdup(host->h_name);
-
- port = sp->s_port;
- if (argc == 3) {
- struct servent *usp;
- usp = getservbyname(argv[2], "udp");
- if ( usp ) {
- port = usp->s_port;
- } else {
- unsigned long myport;
- char *ep;
- myport = strtoul(argv[2], &ep, 10);
- if (*ep || myport > 65535UL) {
- printf("%s: bad port number\n", argv[2]);
- connected = 0;
- return;
- }
- port = htons((u_short)myport);
- }
- }
-
- if (verbose) {
- printf("Connected to %s (%s), port %u\n",
- hostname, inet_ntoa(peeraddr.sin_addr),
- (unsigned int)ntohs(port));
- }
- connected = 1;
+ struct hostent *host;
+
+ if (argc < 2) {
+ getmoreargs("connect ", "(to) ");
+ makeargv();
+ argc = margc;
+ argv = margv;
+ }
+ if ((argc < 2) || (argc > 3)) {
+ printf("usage: %s host-name [port]\n", argv[0]);
+ return;
+ }
+
+ host = gethostbyname(argv[1]);
+ if (host == 0) {
+ connected = 0;
+ printf("%s: unknown host\n", argv[1]);
+ return;
+ }
+ peeraddr.sin_family = host->h_addrtype;
+ bcopy(host->h_addr, &peeraddr.sin_addr, host->h_length);
+ hostname = xstrdup(host->h_name);
+
+ port = sp->s_port;
+ if (argc == 3) {
+ struct servent *usp;
+ usp = getservbyname(argv[2], "udp");
+ if (usp) {
+ port = usp->s_port;
+ } else {
+ unsigned long myport;
+ char *ep;
+ myport = strtoul(argv[2], &ep, 10);
+ if (*ep || myport > 65535UL) {
+ printf("%s: bad port number\n", argv[2]);
+ connected = 0;
+ return;
+ }
+ port = htons((u_short) myport);
+ }
+ }
+
+ if (verbose) {
+ printf("Connected to %s (%s), port %u\n",
+ hostname, inet_ntoa(peeraddr.sin_addr),
+ (unsigned int)ntohs(port));
+ }
+ connected = 1;
}
-void
-modecmd(int argc, char *argv[])
+void modecmd(int argc, char *argv[])
{
- const struct modes *p;
- const char *sep;
-
- if (argc < 2) {
- printf("Using %s mode to transfer files.\n", mode->m_mode);
- return;
- }
- if (argc == 2) {
- for (p = modes; p->m_name; p++)
- if (strcmp(argv[1], p->m_name) == 0)
- break;
- if (p->m_name) {
- settftpmode(p);
- return;
- }
- printf("%s: unknown mode\n", argv[1]);
- /* drop through and print usage message */
- }
-
- printf("usage: %s [", argv[0]);
- sep = " ";
- for (p = modes; p->m_name; p++) {
- printf("%s%s", sep, p->m_name);
- if (*sep == ' ')
- sep = " | ";
- }
- printf(" ]\n");
- return;
-}
+ const struct modes *p;
+ const char *sep;
+
+ if (argc < 2) {
+ printf("Using %s mode to transfer files.\n", mode->m_mode);
+ return;
+ }
+ if (argc == 2) {
+ for (p = modes; p->m_name; p++)
+ if (strcmp(argv[1], p->m_name) == 0)
+ break;
+ if (p->m_name) {
+ settftpmode(p);
+ return;
+ }
+ printf("%s: unknown mode\n", argv[1]);
+ /* drop through and print usage message */
+ }
-void
-setbinary(int argc, char *argv[])
-{
- (void)argc; (void)argv; /* Quiet unused warning */
- settftpmode(MODE_OCTET);
+ printf("usage: %s [", argv[0]);
+ sep = " ";
+ for (p = modes; p->m_name; p++) {
+ printf("%s%s", sep, p->m_name);
+ if (*sep == ' ')
+ sep = " | ";
+ }
+ printf(" ]\n");
+ return;
}
-void
-setascii(int argc, char *argv[])
+void setbinary(int argc, char *argv[])
{
- (void)argc; (void)argv; /* Quiet unused warning */
- settftpmode(MODE_NETASCII);
+ (void)argc;
+ (void)argv; /* Quiet unused warning */
+ settftpmode(MODE_OCTET);
}
-static void
-settftpmode(const struct modes *newmode)
+void setascii(int argc, char *argv[])
{
- mode = newmode;
- if (verbose)
- printf("mode set to %s\n", mode->m_mode);
+ (void)argc;
+ (void)argv; /* Quiet unused warning */
+ settftpmode(MODE_NETASCII);
}
+static void settftpmode(const struct modes *newmode)
+{
+ mode = newmode;
+ if (verbose)
+ printf("mode set to %s\n", mode->m_mode);
+}
/*
* Send file(s).
*/
-void
-put(int argc, char *argv[])
+void put(int argc, char *argv[])
{
- int fd;
- int n;
- char *cp, *targ;
-
- if (argc < 2) {
- getmoreargs("send ", "(file) ");
- makeargv();
- argc = margc;
- argv = margv;
- }
- if (argc < 2) {
- putusage(argv[0]);
- return;
- }
- targ = argv[argc - 1];
- if (!literal && strchr(argv[argc - 1], ':')) {
- struct hostent *hp;
-
- for (n = 1; n < argc - 1; n++)
- if (strchr(argv[n], ':')) {
- putusage(argv[0]);
- return;
- }
- cp = argv[argc - 1];
- targ = strchr(cp, ':');
- *targ++ = 0;
- hp = gethostbyname(cp);
- if (hp == NULL) {
- fprintf(stderr, "tftp: %s: ", cp);
- herror((char *)NULL);
- return;
- }
- bcopy(hp->h_addr, &peeraddr.sin_addr, hp->h_length);
- peeraddr.sin_family = hp->h_addrtype;
- connected = 1;
- hostname = xstrdup(hp->h_name);
- }
- if (!connected) {
- printf("No target machine specified.\n");
- return;
- }
- if (argc < 4) {
- cp = argc == 2 ? tail(targ) : argv[1];
- fd = open(cp, O_RDONLY|mode->m_openflags);
- if (fd < 0) {
- fprintf(stderr, "tftp: "); perror(cp);
- return;
- }
- if (verbose)
- printf("putting %s to %s:%s [%s]\n",
- cp, hostname, targ, mode->m_mode);
- peeraddr.sin_port = port;
- tftp_sendfile(fd, targ, mode->m_mode);
- return;
- }
- /* this assumes the target is a directory */
- /* on a remote unix system. hmmmm. */
- cp = strchr(targ, '\0');
- *cp++ = '/';
- for (n = 1; n < argc - 1; n++) {
- strcpy(cp, tail(argv[n]));
- fd = open(argv[n], O_RDONLY|mode->m_openflags);
- if (fd < 0) {
- fprintf(stderr, "tftp: "); perror(argv[n]);
- continue;
- }
- if (verbose)
- printf("putting %s to %s:%s [%s]\n",
- argv[n], hostname, targ, mode->m_mode);
- peeraddr.sin_port = port;
- tftp_sendfile(fd, targ, mode->m_mode);
- }
+ int fd;
+ int n;
+ char *cp, *targ;
+
+ if (argc < 2) {
+ getmoreargs("send ", "(file) ");
+ makeargv();
+ argc = margc;
+ argv = margv;
+ }
+ if (argc < 2) {
+ putusage(argv[0]);
+ return;
+ }
+ targ = argv[argc - 1];
+ if (!literal && strchr(argv[argc - 1], ':')) {
+ struct hostent *hp;
+
+ for (n = 1; n < argc - 1; n++)
+ if (strchr(argv[n], ':')) {
+ putusage(argv[0]);
+ return;
+ }
+ cp = argv[argc - 1];
+ targ = strchr(cp, ':');
+ *targ++ = 0;
+ hp = gethostbyname(cp);
+ if (hp == NULL) {
+ fprintf(stderr, "tftp: %s: ", cp);
+ herror((char *)NULL);
+ return;
+ }
+ bcopy(hp->h_addr, &peeraddr.sin_addr, hp->h_length);
+ peeraddr.sin_family = hp->h_addrtype;
+ connected = 1;
+ hostname = xstrdup(hp->h_name);
+ }
+ if (!connected) {
+ printf("No target machine specified.\n");
+ return;
+ }
+ if (argc < 4) {
+ cp = argc == 2 ? tail(targ) : argv[1];
+ fd = open(cp, O_RDONLY | mode->m_openflags);
+ if (fd < 0) {
+ fprintf(stderr, "tftp: ");
+ perror(cp);
+ return;
+ }
+ if (verbose)
+ printf("putting %s to %s:%s [%s]\n",
+ cp, hostname, targ, mode->m_mode);
+ peeraddr.sin_port = port;
+ tftp_sendfile(fd, targ, mode->m_mode);
+ return;
+ }
+ /* this assumes the target is a directory */
+ /* on a remote unix system. hmmmm. */
+ cp = strchr(targ, '\0');
+ *cp++ = '/';
+ for (n = 1; n < argc - 1; n++) {
+ strcpy(cp, tail(argv[n]));
+ fd = open(argv[n], O_RDONLY | mode->m_openflags);
+ if (fd < 0) {
+ fprintf(stderr, "tftp: ");
+ perror(argv[n]);
+ continue;
+ }
+ if (verbose)
+ printf("putting %s to %s:%s [%s]\n",
+ argv[n], hostname, targ, mode->m_mode);
+ peeraddr.sin_port = port;
+ tftp_sendfile(fd, targ, mode->m_mode);
+ }
}
-static void
-putusage(char *s)
+static void putusage(char *s)
{
- printf("usage: %s file ... host:target, or\n", s);
- printf(" %s file ... target (when already connected)\n", s);
+ printf("usage: %s file ... host:target, or\n", s);
+ printf(" %s file ... target (when already connected)\n", s);
}
/*
* Receive file(s).
*/
-void
-get(int argc, char *argv[])
+void get(int argc, char *argv[])
{
- int fd;
- int n;
- char *cp;
- char *src;
-
- if (argc < 2) {
- getmoreargs("get ", "(files) ");
- makeargv();
- argc = margc;
- argv = margv;
- }
- if (argc < 2) {
- getusage(argv[0]);
- return;
- }
- if (!connected) {
- for (n = 1; n < argc ; n++)
- if (literal || strchr(argv[n], ':') == 0) {
- getusage(argv[0]);
- return;
- }
- }
- for (n = 1; n < argc ; n++) {
- src = strchr(argv[n], ':');
- if (literal || src == NULL)
- src = argv[n];
- else {
- struct hostent *hp;
-
- *src++ = 0;
- hp = gethostbyname(argv[n]);
- if (hp == NULL) {
- fprintf(stderr, "tftp: %s: ", argv[n]);
- herror((char *)NULL);
- continue;
- }
- bcopy(hp->h_addr, (caddr_t)&peeraddr.sin_addr,
- hp->h_length);
- peeraddr.sin_family = hp->h_addrtype;
- connected = 1;
- hostname = xstrdup(hp->h_name);
- }
- if (argc < 4) {
- cp = argc == 3 ? argv[2] : tail(src);
- fd = open(cp, O_WRONLY|O_CREAT|O_TRUNC|mode->m_openflags, 0666);
- if (fd < 0) {
- fprintf(stderr, "tftp: "); perror(cp);
- return;
- }
- if (verbose)
- printf("getting from %s:%s to %s [%s]\n",
- hostname, src, cp, mode->m_mode);
- peeraddr.sin_port = port;
- tftp_recvfile(fd, src, mode->m_mode);
- break;
- }
- cp = tail(src); /* new .. jdg */
- fd = open(cp, O_WRONLY|O_CREAT|O_TRUNC|mode->m_openflags, 0666);
- if (fd < 0) {
- fprintf(stderr, "tftp: "); perror(cp);
- continue;
- }
- if (verbose)
- printf("getting from %s:%s to %s [%s]\n",
- hostname, src, cp, mode->m_mode);
- peeraddr.sin_port = port;
- tftp_recvfile(fd, src, mode->m_mode);
- }
+ int fd;
+ int n;
+ char *cp;
+ char *src;
+
+ if (argc < 2) {
+ getmoreargs("get ", "(files) ");
+ makeargv();
+ argc = margc;
+ argv = margv;
+ }
+ if (argc < 2) {
+ getusage(argv[0]);
+ return;
+ }
+ if (!connected) {
+ for (n = 1; n < argc; n++)
+ if (literal || strchr(argv[n], ':') == 0) {
+ getusage(argv[0]);
+ return;
+ }
+ }
+ for (n = 1; n < argc; n++) {
+ src = strchr(argv[n], ':');
+ if (literal || src == NULL)
+ src = argv[n];
+ else {
+ struct hostent *hp;
+
+ *src++ = 0;
+ hp = gethostbyname(argv[n]);
+ if (hp == NULL) {
+ fprintf(stderr, "tftp: %s: ", argv[n]);
+ herror((char *)NULL);
+ continue;
+ }
+ bcopy(hp->h_addr, (caddr_t) & peeraddr.sin_addr, hp->h_length);
+ peeraddr.sin_family = hp->h_addrtype;
+ connected = 1;
+ hostname = xstrdup(hp->h_name);
+ }
+ if (argc < 4) {
+ cp = argc == 3 ? argv[2] : tail(src);
+ fd = open(cp, O_WRONLY | O_CREAT | O_TRUNC | mode->m_openflags,
+ 0666);
+ if (fd < 0) {
+ fprintf(stderr, "tftp: ");
+ perror(cp);
+ return;
+ }
+ if (verbose)
+ printf("getting from %s:%s to %s [%s]\n",
+ hostname, src, cp, mode->m_mode);
+ peeraddr.sin_port = port;
+ tftp_recvfile(fd, src, mode->m_mode);
+ break;
+ }
+ cp = tail(src); /* new .. jdg */
+ fd = open(cp, O_WRONLY | O_CREAT | O_TRUNC | mode->m_openflags,
+ 0666);
+ if (fd < 0) {
+ fprintf(stderr, "tftp: ");
+ perror(cp);
+ continue;
+ }
+ if (verbose)
+ printf("getting from %s:%s to %s [%s]\n",
+ hostname, src, cp, mode->m_mode);
+ peeraddr.sin_port = port;
+ tftp_recvfile(fd, src, mode->m_mode);
+ }
}
-static void
-getusage(char *s)
+static void getusage(char *s)
{
- printf("usage: %s host:file host:file ... file, or\n", s);
- printf(" %s file file ... file if connected\n", s);
+ printf("usage: %s host:file host:file ... file, or\n", s);
+ printf(" %s file file ... file if connected\n", s);
}
-int rexmtval = TIMEOUT;
+int rexmtval = TIMEOUT;
-void
-setrexmt(int argc, char *argv[])
+void setrexmt(int argc, char *argv[])
{
- int t;
-
- if (argc < 2) {
- getmoreargs("rexmt-timeout ", "(value) ");
- makeargv();
- argc = margc;
- argv = margv;
- }
- if (argc != 2) {
- printf("usage: %s value\n", argv[0]);
- return;
- }
- t = atoi(argv[1]);
- if (t < 0)
- printf("%s: bad value\n", argv[1]);
- else
- rexmtval = t;
+ int t;
+
+ if (argc < 2) {
+ getmoreargs("rexmt-timeout ", "(value) ");
+ makeargv();
+ argc = margc;
+ argv = margv;
+ }
+ if (argc != 2) {
+ printf("usage: %s value\n", argv[0]);
+ return;
+ }
+ t = atoi(argv[1]);
+ if (t < 0)
+ printf("%s: bad value\n", argv[1]);
+ else
+ rexmtval = t;
}
-int maxtimeout = 5 * TIMEOUT;
+int maxtimeout = 5 * TIMEOUT;
-void
-settimeout(int argc, char *argv[])
+void settimeout(int argc, char *argv[])
{
- int t;
-
- if (argc < 2) {
- getmoreargs("maximum-timeout ", "(value) ");
- makeargv();
- argc = margc;
- argv = margv;
- }
- if (argc != 2) {
- printf("usage: %s value\n", argv[0]);
- return;
- }
- t = atoi(argv[1]);
- if (t < 0)
- printf("%s: bad value\n", argv[1]);
- else
- maxtimeout = t;
+ int t;
+
+ if (argc < 2) {
+ getmoreargs("maximum-timeout ", "(value) ");
+ makeargv();
+ argc = margc;
+ argv = margv;
+ }
+ if (argc != 2) {
+ printf("usage: %s value\n", argv[0]);
+ return;
+ }
+ t = atoi(argv[1]);
+ if (t < 0)
+ printf("%s: bad value\n", argv[1]);
+ else
+ maxtimeout = t;
}
-void
-setliteral(int argc, char *argv[])
+void setliteral(int argc, char *argv[])
{
- (void)argc; (void)argv; /* Quiet unused warning */
- literal = !literal;
- printf("Literal mode %s.\n", literal ? "on" : "off");
+ (void)argc;
+ (void)argv; /* Quiet unused warning */
+ literal = !literal;
+ printf("Literal mode %s.\n", literal ? "on" : "off");
}
-void
-status(int argc, char *argv[])
+void status(int argc, char *argv[])
{
- (void)argc; (void)argv; /* Quiet unused warning */
- if (connected)
- printf("Connected to %s.\n", hostname);
- else
- printf("Not connected.\n");
- printf("Mode: %s Verbose: %s Tracing: %s Literal: %s\n", mode->m_mode,
- verbose ? "on" : "off", trace ? "on" : "off", literal ? "on" : "off");
- printf("Rexmt-interval: %d seconds, Max-timeout: %d seconds\n",
- rexmtval, maxtimeout);
+ (void)argc;
+ (void)argv; /* Quiet unused warning */
+ if (connected)
+ printf("Connected to %s.\n", hostname);
+ else
+ printf("Not connected.\n");
+ printf("Mode: %s Verbose: %s Tracing: %s Literal: %s\n", mode->m_mode,
+ verbose ? "on" : "off", trace ? "on" : "off",
+ literal ? "on" : "off");
+ printf("Rexmt-interval: %d seconds, Max-timeout: %d seconds\n",
+ rexmtval, maxtimeout);
}
-void
-intr(int sig)
+void intr(int sig)
{
- (void)sig; /* Quiet unused warning */
+ (void)sig; /* Quiet unused warning */
- bsd_signal(SIGALRM, SIG_IGN);
- alarm(0);
- siglongjmp(toplevel, -1);
+ bsd_signal(SIGALRM, SIG_IGN);
+ alarm(0);
+ siglongjmp(toplevel, -1);
}
-char *
-tail(char *filename)
+char *tail(char *filename)
{
- char *s;
-
- while (*filename) {
- s = strrchr(filename, '/');
- if (s == NULL)
- break;
- if (s[1])
- return (s + 1);
- *s = '\0';
- }
- return (filename);
+ char *s;
+
+ while (*filename) {
+ s = strrchr(filename, '/');
+ if (s == NULL)
+ break;
+ if (s[1])
+ return (s + 1);
+ *s = '\0';
+ }
+ return (filename);
}
/*
* Command parser.
*/
-static void
-command(void)
+static void command(void)
{
- struct cmd *c;
+ struct cmd *c;
- for (;;) {
+ for (;;) {
#ifdef WITH_READLINE
- if ( line ) {
- free(line);
- line = NULL;
- }
- line = readline(prompt);
- if ( !line )
- exit(0); /* EOF */
+ if (line) {
+ free(line);
+ line = NULL;
+ }
+ line = readline(prompt);
+ if (!line)
+ exit(0); /* EOF */
#else
- fputs(prompt, stdout);
- if (fgets(line, LBUFLEN, stdin) == 0) {
- if (feof(stdin)) {
- exit(0);
- } else {
- continue;
- }
- }
+ fputs(prompt, stdout);
+ if (fgets(line, LBUFLEN, stdin) == 0) {
+ if (feof(stdin)) {
+ exit(0);
+ } else {
+ continue;
+ }
+ }
#endif
- if ((line[0] == 0) || (line[0] == '\n'))
- continue;
+ if ((line[0] == 0) || (line[0] == '\n'))
+ continue;
#ifdef WITH_READLINE
#ifdef HAVE_READLINE_HISTORY_H
- add_history(line);
+ add_history(line);
#endif
#endif
- makeargv();
- if (margc == 0)
- continue;
-
- c = getcmd(margv[0]);
- if (c == (struct cmd *)-1) {
- printf("?Ambiguous command\n");
- continue;
- }
- if (c == 0) {
- printf("?Invalid command\n");
- continue;
- }
- (*c->handler)(margc, margv);
- }
+ makeargv();
+ if (margc == 0)
+ continue;
+
+ c = getcmd(margv[0]);
+ if (c == (struct cmd *)-1) {
+ printf("?Ambiguous command\n");
+ continue;
+ }
+ if (c == 0) {
+ printf("?Invalid command\n");
+ continue;
+ }
+ (*c->handler) (margc, margv);
+ }
}
-struct cmd *
-getcmd(char *name)
+struct cmd *getcmd(char *name)
{
- const char *p;
- char *q;
- struct cmd *c, *found;
- int nmatches, longest;
-
- longest = 0;
- nmatches = 0;
- found = 0;
- for (c = cmdtab; (p = c->name) != NULL; c++) {
- for (q = name; *q == *p++; q++)
- if (*q == 0) /* exact match? */
- return (c);
- if (!*q) { /* the name was a prefix */
- if (q - name > longest) {
- longest = q - name;
- nmatches = 1;
- found = c;
- } else if (q - name == longest)
- nmatches++;
- }
- }
- if (nmatches > 1)
- return ((struct cmd *)-1);
- return (found);
+ const char *p;
+ char *q;
+ struct cmd *c, *found;
+ int nmatches, longest;
+
+ longest = 0;
+ nmatches = 0;
+ found = 0;
+ for (c = cmdtab; (p = c->name) != NULL; c++) {
+ for (q = name; *q == *p++; q++)
+ if (*q == 0) /* exact match? */
+ return (c);
+ if (!*q) { /* the name was a prefix */
+ if (q - name > longest) {
+ longest = q - name;
+ nmatches = 1;
+ found = c;
+ } else if (q - name == longest)
+ nmatches++;
+ }
+ }
+ if (nmatches > 1)
+ return ((struct cmd *)-1);
+ return (found);
}
/*
* Slice a string up into argc/argv.
*/
-static void
-makeargv(void)
+static void makeargv(void)
{
- char *cp;
- char **argp = margv;
-
- margc = 0;
- for (cp = line; *cp;) {
- while (isspace(*cp))
- cp++;
- if (*cp == '\0')
- break;
- *argp++ = cp;
- margc += 1;
- while (*cp != '\0' && !isspace(*cp))
- cp++;
- if (*cp == '\0')
- break;
- *cp++ = '\0';
- }
- *argp++ = 0;
+ char *cp;
+ char **argp = margv;
+
+ margc = 0;
+ for (cp = line; *cp;) {
+ while (isspace(*cp))
+ cp++;
+ if (*cp == '\0')
+ break;
+ *argp++ = cp;
+ margc += 1;
+ while (*cp != '\0' && !isspace(*cp))
+ cp++;
+ if (*cp == '\0')
+ break;
+ *cp++ = '\0';
+ }
+ *argp++ = 0;
}
-void
-quit(int argc, char *argv[])
+void quit(int argc, char *argv[])
{
- (void)argc; (void)argv; /* Quiet unused warning */
- exit(0);
+ (void)argc;
+ (void)argv; /* Quiet unused warning */
+ exit(0);
}
/*
* Help command.
*/
-void
-help(int argc, char *argv[])
+void help(int argc, char *argv[])
{
- struct cmd *c;
-
- printf("%s\n", VERSION);
-
- if (argc == 1) {
- printf("Commands may be abbreviated. Commands are:\n\n");
- for (c = cmdtab; c->name; c++)
- printf("%-*s\t%s\n", (int)HELPINDENT, c->name, c->help);
- return;
- }
- while (--argc > 0) {
- char *arg;
- arg = *++argv;
- c = getcmd(arg);
- if (c == (struct cmd *)-1)
- printf("?Ambiguous help command %s\n", arg);
- else if (c == (struct cmd *)0)
- printf("?Invalid help command %s\n", arg);
- else
- printf("%s\n", c->help);
- }
+ struct cmd *c;
+
+ printf("%s\n", VERSION);
+
+ if (argc == 1) {
+ printf("Commands may be abbreviated. Commands are:\n\n");
+ for (c = cmdtab; c->name; c++)
+ printf("%-*s\t%s\n", (int)HELPINDENT, c->name, c->help);
+ return;
+ }
+ while (--argc > 0) {
+ char *arg;
+ arg = *++argv;
+ c = getcmd(arg);
+ if (c == (struct cmd *)-1)
+ printf("?Ambiguous help command %s\n", arg);
+ else if (c == (struct cmd *)0)
+ printf("?Invalid help command %s\n", arg);
+ else
+ printf("%s\n", c->help);
+ }
}
-void
-settrace(int argc, char *argv[])
+void settrace(int argc, char *argv[])
{
- (void)argc; (void)argv; /* Quiet unused warning */
+ (void)argc;
+ (void)argv; /* Quiet unused warning */
- trace = !trace;
- printf("Packet tracing %s.\n", trace ? "on" : "off");
+ trace = !trace;
+ printf("Packet tracing %s.\n", trace ? "on" : "off");
}
-void
-setverbose(int argc, char *argv[])
+void setverbose(int argc, char *argv[])
{
- (void)argc; (void)argv; /* Quiet unused warning */
+ (void)argc;
+ (void)argv; /* Quiet unused warning */
- verbose = !verbose;
- printf("Verbose mode %s.\n", verbose ? "on" : "off");
+ verbose = !verbose;
+ printf("Verbose mode %s.\n", verbose ? "on" : "off");
}
diff --git a/tftp/tftp.c b/tftp/tftp.c
index 8dfec29..41c6fbd 100644
--- a/tftp/tftp.c
+++ b/tftp/tftp.c
@@ -39,9 +39,8 @@
#ifndef lint
/* static char sccsid[] = "@(#)tftp.c 8.1 (Berkeley) 6/6/93"; */
/* static char rcsid[] = "$OpenBSD: tftp.c,v 1.4 1997/08/06 06:43:45 deraadt Exp $"; */
-static const char *rcsid UNUSED =
-"tftp-hpa $Id$";
-#endif /* not lint */
+static const char *rcsid UNUSED = "tftp-hpa $Id$";
+#endif /* not lint */
/* Many bug fixes are from Jim Guyton <guyton@rand-unix> */
@@ -50,18 +49,18 @@ static const char *rcsid UNUSED =
*/
#include "extern.h"
-extern struct sockaddr_in peeraddr; /* filled in by main */
-extern int f; /* the opened socket */
-extern int trace;
-extern int verbose;
-extern int rexmtval;
-extern int maxtimeout;
+extern struct sockaddr_in peeraddr; /* filled in by main */
+extern int f; /* the opened socket */
+extern int trace;
+extern int verbose;
+extern int rexmtval;
+extern int maxtimeout;
#define PKTSIZE SEGSIZE+4
-char ackbuf[PKTSIZE];
-int timeout;
-sigjmp_buf toplevel;
-sigjmp_buf timeoutbuf;
+char ackbuf[PKTSIZE];
+int timeout;
+sigjmp_buf toplevel;
+sigjmp_buf timeoutbuf;
static void nak(int, const char *);
static int makerequest(int, const char *, struct tftphdr *, const char *);
@@ -74,251 +73,247 @@ static void tpacket(const char *, struct tftphdr *, int);
/*
* Send the requested file.
*/
-void
-tftp_sendfile(int fd, const char *name, const char *mode)
+void tftp_sendfile(int fd, const char *name, const char *mode)
{
- struct tftphdr *ap; /* data and ack packets */
- struct tftphdr *dp;
- int n;
- volatile int is_request;
- volatile u_short block;
- volatile int size, convert;
- volatile off_t amount;
- struct sockaddr_in from;
- socklen_t fromlen;
- FILE *file;
- u_short ap_opcode, ap_block;
-
- startclock(); /* start stat's clock */
- dp = r_init(); /* reset fillbuf/read-ahead code */
- ap = (struct tftphdr *)ackbuf;
- convert = !strcmp(mode, "netascii");
- file = fdopen(fd, convert ? "rt" : "rb");
- block = 0;
- is_request = 1; /* First packet is the actual WRQ */
- amount = 0;
-
- bsd_signal(SIGALRM, timer);
- do {
- if (is_request) {
- size = makerequest(WRQ, name, dp, mode) - 4;
- } else {
- /* size = read(fd, dp->th_data, SEGSIZE); */
- size = readit(file, &dp, convert);
- if (size < 0) {
- nak(errno + 100, NULL);
- break;
- }
- dp->th_opcode = htons((u_short)DATA);
- dp->th_block = htons((u_short)block);
- }
- timeout = 0;
- (void) sigsetjmp(timeoutbuf,1);
-
- if (trace)
- tpacket("sent", dp, size + 4);
- n = sendto(f, dp, size + 4, 0,
- (struct sockaddr *)&peeraddr, sizeof(peeraddr));
- if (n != size + 4) {
- perror("tftp: sendto");
- goto abort;
- }
- read_ahead(file, convert);
- for ( ; ; ) {
- alarm(rexmtval);
- do {
- fromlen = sizeof(from);
- n = recvfrom(f, ackbuf, sizeof(ackbuf), 0,
- (struct sockaddr *)&from, &fromlen);
- } while (n <= 0);
- alarm(0);
- if (n < 0) {
- perror("tftp: recvfrom");
- goto abort;
- }
- peeraddr.sin_port = from.sin_port; /* added */
- if (trace)
- tpacket("received", ap, n);
- /* should verify packet came from server */
- ap_opcode = ntohs((u_short)ap->th_opcode);
- ap_block = ntohs((u_short)ap->th_block);
- if (ap_opcode == ERROR) {
- printf("Error code %d: %s\n", ap_block,
- ap->th_msg);
- goto abort;
- }
- if (ap_opcode == ACK) {
- int j;
-
- if (ap_block == block) {
- break;
- }
- /* On an error, try to synchronize
- * both sides.
- */
- j = synchnet(f);
- if (j && trace) {
- printf("discarded %d packets\n",
- j);
- }
- /*
- * RFC1129/RFC1350: We MUST NOT re-send the DATA
- * packet in response to an invalid ACK. Doing so
- * would cause the Sorcerer's Apprentice bug.
- */
- }
- }
- if ( !is_request )
- amount += size;
- is_request = 0;
- block++;
- } while (size == SEGSIZE || block == 1);
-abort:
- fclose(file);
- stopclock();
- if (amount > 0)
- printstats("Sent", amount);
+ struct tftphdr *ap; /* data and ack packets */
+ struct tftphdr *dp;
+ int n;
+ volatile int is_request;
+ volatile u_short block;
+ volatile int size, convert;
+ volatile off_t amount;
+ struct sockaddr_in from;
+ socklen_t fromlen;
+ FILE *file;
+ u_short ap_opcode, ap_block;
+
+ startclock(); /* start stat's clock */
+ dp = r_init(); /* reset fillbuf/read-ahead code */
+ ap = (struct tftphdr *)ackbuf;
+ convert = !strcmp(mode, "netascii");
+ file = fdopen(fd, convert ? "rt" : "rb");
+ block = 0;
+ is_request = 1; /* First packet is the actual WRQ */
+ amount = 0;
+
+ bsd_signal(SIGALRM, timer);
+ do {
+ if (is_request) {
+ size = makerequest(WRQ, name, dp, mode) - 4;
+ } else {
+ /* size = read(fd, dp->th_data, SEGSIZE); */
+ size = readit(file, &dp, convert);
+ if (size < 0) {
+ nak(errno + 100, NULL);
+ break;
+ }
+ dp->th_opcode = htons((u_short) DATA);
+ dp->th_block = htons((u_short) block);
+ }
+ timeout = 0;
+ (void)sigsetjmp(timeoutbuf, 1);
+
+ if (trace)
+ tpacket("sent", dp, size + 4);
+ n = sendto(f, dp, size + 4, 0,
+ (struct sockaddr *)&peeraddr, sizeof(peeraddr));
+ if (n != size + 4) {
+ perror("tftp: sendto");
+ goto abort;
+ }
+ read_ahead(file, convert);
+ for (;;) {
+ alarm(rexmtval);
+ do {
+ fromlen = sizeof(from);
+ n = recvfrom(f, ackbuf, sizeof(ackbuf), 0,
+ (struct sockaddr *)&from, &fromlen);
+ } while (n <= 0);
+ alarm(0);
+ if (n < 0) {
+ perror("tftp: recvfrom");
+ goto abort;
+ }
+ peeraddr.sin_port = from.sin_port; /* added */
+ if (trace)
+ tpacket("received", ap, n);
+ /* should verify packet came from server */
+ ap_opcode = ntohs((u_short) ap->th_opcode);
+ ap_block = ntohs((u_short) ap->th_block);
+ if (ap_opcode == ERROR) {
+ printf("Error code %d: %s\n", ap_block, ap->th_msg);
+ goto abort;
+ }
+ if (ap_opcode == ACK) {
+ int j;
+
+ if (ap_block == block) {
+ break;
+ }
+ /* On an error, try to synchronize
+ * both sides.
+ */
+ j = synchnet(f);
+ if (j && trace) {
+ printf("discarded %d packets\n", j);
+ }
+ /*
+ * RFC1129/RFC1350: We MUST NOT re-send the DATA
+ * packet in response to an invalid ACK. Doing so
+ * would cause the Sorcerer's Apprentice bug.
+ */
+ }
+ }
+ if (!is_request)
+ amount += size;
+ is_request = 0;
+ block++;
+ } while (size == SEGSIZE || block == 1);
+ abort:
+ fclose(file);
+ stopclock();
+ if (amount > 0)
+ printstats("Sent", amount);
}
/*
* Receive a file.
*/
-void
-tftp_recvfile(int fd, const char *name, const char *mode)
+void tftp_recvfile(int fd, const char *name, const char *mode)
{
- struct tftphdr *ap;
- struct tftphdr *dp;
- int n;
- volatile u_short block;
- volatile int size, firsttrip;
- volatile unsigned long amount;
- struct sockaddr_in from;
- socklen_t fromlen;
- FILE *file;
- volatile int convert; /* true if converting crlf -> lf */
- u_short dp_opcode, dp_block;
-
- startclock();
- dp = w_init();
- ap = (struct tftphdr *)ackbuf;
- convert = !strcmp(mode, "netascii");
- file = fdopen(fd, convert ?"wt":"wb");
- block = 1;
- firsttrip = 1;
- amount = 0;
-
- bsd_signal(SIGALRM, timer);
- do {
- if (firsttrip) {
- size = makerequest(RRQ, name, ap, mode);
- firsttrip = 0;
- } else {
- ap->th_opcode = htons((u_short)ACK);
- ap->th_block = htons((u_short)block);
- size = 4;
- block++;
- }
- timeout = 0;
- (void) sigsetjmp(timeoutbuf,1);
-send_ack:
- if (trace)
- tpacket("sent", ap, size);
- if (sendto(f, ackbuf, size, 0, (struct sockaddr *)&peeraddr,
- sizeof(peeraddr)) != size) {
- alarm(0);
- perror("tftp: sendto");
- goto abort;
- }
- write_behind(file, convert);
- for ( ; ; ) {
- alarm(rexmtval);
- do {
- fromlen = sizeof(from);
- n = recvfrom(f, dp, PKTSIZE, 0,
- (struct sockaddr *)&from, &fromlen);
- } while (n <= 0);
- alarm(0);
- if (n < 0) {
- perror("tftp: recvfrom");
- goto abort;
- }
- peeraddr.sin_port = from.sin_port; /* added */
- if (trace)
- tpacket("received", dp, n);
- /* should verify client address */
- dp_opcode = ntohs((u_short)dp->th_opcode);
- dp_block = ntohs((u_short)dp->th_block);
- if (dp_opcode == ERROR) {
- printf("Error code %d: %s\n", dp_block, dp->th_msg);
- goto abort;
- }
- if (dp_opcode == DATA) {
- int j;
-
- if (dp_block == block) {
- break; /* have next packet */
- }
- /* On an error, try to synchronize
- * both sides.
- */
- j = synchnet(f);
- if (j && trace) {
- printf("discarded %d packets\n", j);
- }
- if (dp_block == (block-1)) {
- goto send_ack; /* resend ack */
- }
- }
- }
- /* size = write(fd, dp->th_data, n - 4); */
- size = writeit(file, &dp, n - 4, convert);
- if (size < 0) {
- nak(errno + 100, NULL);
- break;
- }
- amount += size;
- } while (size == SEGSIZE);
-abort: /* ok to ack, since user */
- ap->th_opcode = htons((u_short)ACK); /* has seen err msg */
- ap->th_block = htons((u_short)block);
- (void) sendto(f, ackbuf, 4, 0, (struct sockaddr *)&peeraddr,
- sizeof(peeraddr));
- write_behind(file, convert); /* flush last buffer */
- fclose(file);
- stopclock();
- if (amount > 0)
- printstats("Received", amount);
+ struct tftphdr *ap;
+ struct tftphdr *dp;
+ int n;
+ volatile u_short block;
+ volatile int size, firsttrip;
+ volatile unsigned long amount;
+ struct sockaddr_in from;
+ socklen_t fromlen;
+ FILE *file;
+ volatile int convert; /* true if converting crlf -> lf */
+ u_short dp_opcode, dp_block;
+
+ startclock();
+ dp = w_init();
+ ap = (struct tftphdr *)ackbuf;
+ convert = !strcmp(mode, "netascii");
+ file = fdopen(fd, convert ? "wt" : "wb");
+ block = 1;
+ firsttrip = 1;
+ amount = 0;
+
+ bsd_signal(SIGALRM, timer);
+ do {
+ if (firsttrip) {
+ size = makerequest(RRQ, name, ap, mode);
+ firsttrip = 0;
+ } else {
+ ap->th_opcode = htons((u_short) ACK);
+ ap->th_block = htons((u_short) block);
+ size = 4;
+ block++;
+ }
+ timeout = 0;
+ (void)sigsetjmp(timeoutbuf, 1);
+ send_ack:
+ if (trace)
+ tpacket("sent", ap, size);
+ if (sendto(f, ackbuf, size, 0, (struct sockaddr *)&peeraddr,
+ sizeof(peeraddr)) != size) {
+ alarm(0);
+ perror("tftp: sendto");
+ goto abort;
+ }
+ write_behind(file, convert);
+ for (;;) {
+ alarm(rexmtval);
+ do {
+ fromlen = sizeof(from);
+ n = recvfrom(f, dp, PKTSIZE, 0,
+ (struct sockaddr *)&from, &fromlen);
+ } while (n <= 0);
+ alarm(0);
+ if (n < 0) {
+ perror("tftp: recvfrom");
+ goto abort;
+ }
+ peeraddr.sin_port = from.sin_port; /* added */
+ if (trace)
+ tpacket("received", dp, n);
+ /* should verify client address */
+ dp_opcode = ntohs((u_short) dp->th_opcode);
+ dp_block = ntohs((u_short) dp->th_block);
+ if (dp_opcode == ERROR) {
+ printf("Error code %d: %s\n", dp_block, dp->th_msg);
+ goto abort;
+ }
+ if (dp_opcode == DATA) {
+ int j;
+
+ if (dp_block == block) {
+ break; /* have next packet */
+ }
+ /* On an error, try to synchronize
+ * both sides.
+ */
+ j = synchnet(f);
+ if (j && trace) {
+ printf("discarded %d packets\n", j);
+ }
+ if (dp_block == (block - 1)) {
+ goto send_ack; /* resend ack */
+ }
+ }
+ }
+ /* size = write(fd, dp->th_data, n - 4); */
+ size = writeit(file, &dp, n - 4, convert);
+ if (size < 0) {
+ nak(errno + 100, NULL);
+ break;
+ }
+ amount += size;
+ } while (size == SEGSIZE);
+ abort: /* ok to ack, since user */
+ ap->th_opcode = htons((u_short) ACK); /* has seen err msg */
+ ap->th_block = htons((u_short) block);
+ (void)sendto(f, ackbuf, 4, 0, (struct sockaddr *)&peeraddr,
+ sizeof(peeraddr));
+ write_behind(file, convert); /* flush last buffer */
+ fclose(file);
+ stopclock();
+ if (amount > 0)
+ printstats("Received", amount);
}
static int
makerequest(int request, const char *name,
- struct tftphdr *tp, const char *mode)
+ struct tftphdr *tp, const char *mode)
{
- char *cp;
-
- tp->th_opcode = htons((u_short)request);
- cp = (char *) &(tp->th_stuff);
- strcpy(cp, name);
- cp += strlen(name);
- *cp++ = '\0';
- strcpy(cp, mode);
- cp += strlen(mode);
- *cp++ = '\0';
- return (cp - (char *)tp);
+ char *cp;
+
+ tp->th_opcode = htons((u_short) request);
+ cp = (char *)&(tp->th_stuff);
+ strcpy(cp, name);
+ cp += strlen(name);
+ *cp++ = '\0';
+ strcpy(cp, mode);
+ cp += strlen(mode);
+ *cp++ = '\0';
+ return (cp - (char *)tp);
}
-static const char * const errmsgs[] =
-{
- "Undefined error code", /* 0 - EUNDEF */
- "File not found", /* 1 - ENOTFOUND */
- "Access denied", /* 2 - EACCESS */
- "Disk full or allocation exceeded", /* 3 - ENOSPACE */
- "Illegal TFTP operation", /* 4 - EBADOP */
- "Unknown transfer ID", /* 5 - EBADID */
- "File already exists", /* 6 - EEXISTS */
- "No such user", /* 7 - ENOUSER */
- "Failure to negotiate RFC2347 options" /* 8 - EOPTNEG */
+static const char *const errmsgs[] = {
+ "Undefined error code", /* 0 - EUNDEF */
+ "File not found", /* 1 - ENOTFOUND */
+ "Access denied", /* 2 - EACCESS */
+ "Disk full or allocation exceeded", /* 3 - ENOSPACE */
+ "Illegal TFTP operation", /* 4 - EBADOP */
+ "Unknown transfer ID", /* 5 - EBADID */
+ "File already exists", /* 6 - EEXISTS */
+ "No such user", /* 7 - ENOUSER */
+ "Failure to negotiate RFC2347 options" /* 8 - EOPTNEG */
};
+
#define ERR_CNT (sizeof(errmsgs)/sizeof(const char *))
/*
@@ -327,121 +322,115 @@ static const char * const errmsgs[] =
* standard TFTP codes, or a UNIX errno
* offset by 100.
*/
-static void
-nak(int error, const char *msg)
+static void nak(int error, const char *msg)
{
- struct tftphdr *tp;
- int length;
-
- tp = (struct tftphdr *)ackbuf;
- tp->th_opcode = htons((u_short)ERROR);
- tp->th_code = htons((u_short)error);
-
- if ( error >= 100 ) {
- /* This is a Unix errno+100 */
- if ( !msg )
- msg = strerror(error - 100);
- error = EUNDEF;
- } else {
- if ( (unsigned)error >= ERR_CNT )
- error = EUNDEF;
-
- if ( !msg )
- msg = errmsgs[error];
- }
-
- tp->th_code = htons((u_short)error);
-
- length = strlen(msg)+1;
- memcpy(tp->th_msg, msg, length);
- length += 4; /* Add space for header */
-
- if (trace)
- tpacket("sent", tp, length);
- if (sendto(f, ackbuf, length, 0, (struct sockaddr *)&peeraddr,
- sizeof(peeraddr)) != length)
- perror("nak");
+ struct tftphdr *tp;
+ int length;
+
+ tp = (struct tftphdr *)ackbuf;
+ tp->th_opcode = htons((u_short) ERROR);
+ tp->th_code = htons((u_short) error);
+
+ if (error >= 100) {
+ /* This is a Unix errno+100 */
+ if (!msg)
+ msg = strerror(error - 100);
+ error = EUNDEF;
+ } else {
+ if ((unsigned)error >= ERR_CNT)
+ error = EUNDEF;
+
+ if (!msg)
+ msg = errmsgs[error];
+ }
+
+ tp->th_code = htons((u_short) error);
+
+ length = strlen(msg) + 1;
+ memcpy(tp->th_msg, msg, length);
+ length += 4; /* Add space for header */
+
+ if (trace)
+ tpacket("sent", tp, length);
+ if (sendto(f, ackbuf, length, 0, (struct sockaddr *)&peeraddr,
+ sizeof(peeraddr)) != length)
+ perror("nak");
}
-static void
-tpacket(const char *s, struct tftphdr *tp, int n)
+static void tpacket(const char *s, struct tftphdr *tp, int n)
{
- static const char *opcodes[] =
- { "#0", "RRQ", "WRQ", "DATA", "ACK", "ERROR", "OACK" };
- char *cp, *file;
- u_short op = ntohs((u_short)tp->th_opcode);
-
- if (op < RRQ || op > ERROR)
- printf("%s opcode=%x ", s, op);
- else
- printf("%s %s ", s, opcodes[op]);
- switch (op) {
-
- case RRQ:
- case WRQ:
- n -= 2;
- file = cp = (char *) &(tp->th_stuff);
- cp = strchr(cp, '\0');
- printf("<file=%s, mode=%s>\n", file, cp + 1);
- break;
-
- case DATA:
- printf("<block=%d, %d bytes>\n", ntohs(tp->th_block), n - 4);
- break;
-
- case ACK:
- printf("<block=%d>\n", ntohs(tp->th_block));
- break;
-
- case ERROR:
- printf("<code=%d, msg=%s>\n", ntohs(tp->th_code), tp->th_msg);
- break;
- }
+ static const char *opcodes[] =
+ { "#0", "RRQ", "WRQ", "DATA", "ACK", "ERROR", "OACK" };
+ char *cp, *file;
+ u_short op = ntohs((u_short) tp->th_opcode);
+
+ if (op < RRQ || op > ERROR)
+ printf("%s opcode=%x ", s, op);
+ else
+ printf("%s %s ", s, opcodes[op]);
+ switch (op) {
+
+ case RRQ:
+ case WRQ:
+ n -= 2;
+ file = cp = (char *)&(tp->th_stuff);
+ cp = strchr(cp, '\0');
+ printf("<file=%s, mode=%s>\n", file, cp + 1);
+ break;
+
+ case DATA:
+ printf("<block=%d, %d bytes>\n", ntohs(tp->th_block), n - 4);
+ break;
+
+ case ACK:
+ printf("<block=%d>\n", ntohs(tp->th_block));
+ break;
+
+ case ERROR:
+ printf("<code=%d, msg=%s>\n", ntohs(tp->th_code), tp->th_msg);
+ break;
+ }
}
struct timeval tstart;
struct timeval tstop;
-static void
-startclock(void)
+static void startclock(void)
{
- (void)gettimeofday(&tstart, NULL);
+ (void)gettimeofday(&tstart, NULL);
}
-static void
-stopclock(void)
+static void stopclock(void)
{
- (void)gettimeofday(&tstop, NULL);
+ (void)gettimeofday(&tstop, NULL);
}
-static void
-printstats(const char *direction, unsigned long amount)
+static void printstats(const char *direction, unsigned long amount)
{
- double delta;
-
- delta = (tstop.tv_sec+(tstop.tv_usec/100000.0)) -
- (tstart.tv_sec+(tstart.tv_usec/100000.0));
- if (verbose) {
- printf("%s %lu bytes in %.1f seconds", direction, amount, delta);
- printf(" [%.0f bit/s]", (amount*8.)/delta);
- putchar('\n');
- }
+ double delta;
+
+ delta = (tstop.tv_sec + (tstop.tv_usec / 100000.0)) -
+ (tstart.tv_sec + (tstart.tv_usec / 100000.0));
+ if (verbose) {
+ printf("%s %lu bytes in %.1f seconds", direction, amount, delta);
+ printf(" [%.0f bit/s]", (amount * 8.) / delta);
+ putchar('\n');
+ }
}
-static void
-timer(int sig)
+static void timer(int sig)
{
- int save_errno = errno;
-
- (void)sig; /* Shut up unused warning */
-
- timeout += rexmtval;
- if (timeout >= maxtimeout) {
- printf("Transfer timed out.\n");
- errno = save_errno;
- siglongjmp(toplevel, -1);
- }
- errno = save_errno;
- siglongjmp(timeoutbuf, 1);
+ int save_errno = errno;
+
+ (void)sig; /* Shut up unused warning */
+
+ timeout += rexmtval;
+ if (timeout >= maxtimeout) {
+ printf("Transfer timed out.\n");
+ errno = save_errno;
+ siglongjmp(toplevel, -1);
+ }
+ errno = save_errno;
+ siglongjmp(timeoutbuf, 1);
}
diff --git a/tftpd/misc.c b/tftpd/misc.c
index 4f88978..07684dd 100644
--- a/tftpd/misc.c
+++ b/tftpd/misc.c
@@ -1,5 +1,5 @@
/* ----------------------------------------------------------------------- *
- *
+ *
* Copyright 2001-2007 H. Peter Anvin - All Rights Reserved
*
* This program is free software available under the same license
@@ -14,7 +14,7 @@
* Minor help routines.
*/
-#include "config.h" /* Must be included first! */
+#include "config.h" /* Must be included first! */
#include <syslog.h>
#include "tftpd.h"
@@ -22,19 +22,19 @@
* Set the signal handler and flags. Basically a user-friendly
* wrapper around sigaction().
*/
-void set_signal(int signum, void (*handler)(int), int flags)
+void set_signal(int signum, void (*handler) (int), int flags)
{
- struct sigaction sa;
+ struct sigaction sa;
+
+ memset(&sa, 0, sizeof sa);
+ sa.sa_handler = handler;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = flags;
- memset(&sa, 0, sizeof sa);
- sa.sa_handler = handler;
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = flags;
-
- if ( sigaction(signum, &sa, NULL) ) {
- syslog(LOG_ERR, "sigaction: %m");
- exit(EX_OSERR);
- }
+ if (sigaction(signum, &sa, NULL)) {
+ syslog(LOG_ERR, "sigaction: %m");
+ exit(EX_OSERR);
+ }
}
/*
@@ -42,14 +42,14 @@ void set_signal(int signum, void (*handler)(int), int flags)
*/
void *tfmalloc(size_t size)
{
- void *p = malloc(size);
+ void *p = malloc(size);
- if ( !p ) {
- syslog(LOG_ERR, "malloc: %m");
- exit(EX_OSERR);
- }
+ if (!p) {
+ syslog(LOG_ERR, "malloc: %m");
+ exit(EX_OSERR);
+ }
- return p;
+ return p;
}
/*
@@ -57,13 +57,12 @@ void *tfmalloc(size_t size)
*/
char *tfstrdup(const char *str)
{
- char *p = strdup(str);
+ char *p = strdup(str);
- if ( !p ) {
- syslog(LOG_ERR, "strdup: %m");
- exit(EX_OSERR);
- }
+ if (!p) {
+ syslog(LOG_ERR, "strdup: %m");
+ exit(EX_OSERR);
+ }
- return p;
+ return p;
}
-
diff --git a/tftpd/recvfrom.c b/tftpd/recvfrom.c
index ba8d648..fee6d03 100644
--- a/tftpd/recvfrom.c
+++ b/tftpd/recvfrom.c
@@ -1,5 +1,5 @@
/* ----------------------------------------------------------------------- *
- *
+ *
* Copyright 2001-2006 H. Peter Anvin - All Rights Reserved
*
* This program is free software available under the same license
@@ -17,11 +17,11 @@
*
*/
-#include "config.h" /* Must be included first! */
+#include "config.h" /* Must be included first! */
#include "recvfrom.h"
#include "common/tftpsubs.h"
#ifdef HAVE_MACHINE_PARAM_H
-#include <machine/param.h> /* Needed on some versions of FreeBSD */
+#include <machine/param.h> /* Needed on some versions of FreeBSD */
#endif
#if defined(HAVE_RECVMSG) && defined(HAVE_MSGHDR_MSG_CONTROL)
@@ -33,12 +33,12 @@
# ifdef __linux__
/* Assume this version of glibc simply lacks the definition */
struct in_pktinfo {
- int ipi_ifindex;
- struct in_addr ipi_spec_dst;
- struct in_addr ipi_addr;
+ int ipi_ifindex;
+ struct in_addr ipi_spec_dst;
+ struct in_addr ipi_addr;
};
# else
-# undef IP_PKTINFO /* No definition, no way to get it */
+# undef IP_PKTINFO /* No definition, no way to get it */
# endif
# endif
#endif
@@ -57,141 +57,141 @@ struct in_pktinfo {
*/
static int address_is_local(const struct sockaddr_in *addr)
{
- struct sockaddr_in sin;
- int sockfd = -1;
- int e;
- int rv = 0;
- socklen_t addrlen;
+ struct sockaddr_in sin;
+ int sockfd = -1;
+ int e;
+ int rv = 0;
+ socklen_t addrlen;
+
+ /* Multicast or universal broadcast address? */
+ if (ntohl(addr->sin_addr.s_addr) >= (224UL << 24))
+ return 0;
- /* Multicast or universal broadcast address? */
- if (ntohl(addr->sin_addr.s_addr) >= (224UL << 24))
- return 0;
+ sockfd = socket(PF_INET, SOCK_DGRAM, 0);
+ if (sockfd < 0)
+ goto err;
- sockfd = socket(PF_INET, SOCK_DGRAM, 0);
- if (sockfd < 0)
- goto err;
+ if (connect(sockfd, (const struct sockaddr *)addr, sizeof *addr))
+ goto err;
- if (connect(sockfd, (const struct sockaddr *)addr, sizeof *addr))
- goto err;
+ addrlen = sizeof sin;
+ if (getsockname(sockfd, (struct sockaddr *)&sin, &addrlen))
+ goto err;
- addrlen = sizeof sin;
- if (getsockname(sockfd, (struct sockaddr *)&sin, &addrlen))
- goto err;
+ rv = sin.sin_addr.s_addr == addr->sin_addr.s_addr;
- rv = sin.sin_addr.s_addr == addr->sin_addr.s_addr;
+ err:
+ e = errno;
- err:
- e = errno;
-
- if (sockfd >= 0)
- close(sockfd);
+ if (sockfd >= 0)
+ close(sockfd);
- errno = e;
- return rv;
+ errno = e;
+ return rv;
}
-
int
myrecvfrom(int s, void *buf, int len, unsigned int flags,
- struct sockaddr *from, socklen_t *fromlen,
- struct sockaddr_in *myaddr)
+ struct sockaddr *from, socklen_t * fromlen,
+ struct sockaddr_in *myaddr)
{
- struct msghdr msg;
- struct iovec iov;
- int n;
- struct cmsghdr *cmptr;
- union {
- struct cmsghdr cm;
+ struct msghdr msg;
+ struct iovec iov;
+ int n;
+ struct cmsghdr *cmptr;
+ union {
+ struct cmsghdr cm;
#ifdef IP_PKTINFO
- char control[CMSG_SPACE(sizeof(struct in_addr)) +
- CMSG_SPACE(sizeof(struct in_pktinfo))];
+ char control[CMSG_SPACE(sizeof(struct in_addr)) +
+ CMSG_SPACE(sizeof(struct in_pktinfo))];
#else
- char control[CMSG_SPACE(sizeof(struct in_addr))];
+ char control[CMSG_SPACE(sizeof(struct in_addr))];
#endif
- } control_un;
- int on = 1;
+ } control_un;
+ int on = 1;
#ifdef IP_PKTINFO
- struct in_pktinfo pktinfo;
+ struct in_pktinfo pktinfo;
#endif
- /* Try to enable getting the return address */
+ /* Try to enable getting the return address */
#ifdef IP_RECVDSTADDR
- setsockopt(s, IPPROTO_IP, IP_RECVDSTADDR, &on, sizeof(on));
+ setsockopt(s, IPPROTO_IP, IP_RECVDSTADDR, &on, sizeof(on));
#endif
#ifdef IP_PKTINFO
- setsockopt(s, IPPROTO_IP, IP_PKTINFO, &on, sizeof(on));
+ setsockopt(s, IPPROTO_IP, IP_PKTINFO, &on, sizeof(on));
#endif
- bzero(&msg, sizeof msg); /* Clear possible system-dependent fields */
- msg.msg_control = control_un.control;
- msg.msg_controllen = sizeof(control_un.control);
- msg.msg_flags = 0;
+ bzero(&msg, sizeof msg); /* Clear possible system-dependent fields */
+ msg.msg_control = control_un.control;
+ msg.msg_controllen = sizeof(control_un.control);
+ msg.msg_flags = 0;
- msg.msg_name = from;
- msg.msg_namelen = *fromlen;
- iov.iov_base = buf;
- iov.iov_len = len;
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
+ msg.msg_name = from;
+ msg.msg_namelen = *fromlen;
+ iov.iov_base = buf;
+ iov.iov_len = len;
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
- if ( (n = recvmsg(s, &msg, flags)) < 0 )
- return n; /* Error */
+ if ((n = recvmsg(s, &msg, flags)) < 0)
+ return n; /* Error */
- *fromlen = msg.msg_namelen;
+ *fromlen = msg.msg_namelen;
- if ( myaddr ) {
- bzero(myaddr, sizeof(struct sockaddr_in));
- myaddr->sin_family = AF_INET;
+ if (myaddr) {
+ bzero(myaddr, sizeof(struct sockaddr_in));
+ myaddr->sin_family = AF_INET;
- if ( msg.msg_controllen < sizeof(struct cmsghdr) ||
- (msg.msg_flags & MSG_CTRUNC) )
- return n; /* No information available */
+ if (msg.msg_controllen < sizeof(struct cmsghdr) ||
+ (msg.msg_flags & MSG_CTRUNC))
+ return n; /* No information available */
- for ( cmptr = CMSG_FIRSTHDR(&msg) ; cmptr != NULL ;
- cmptr = CMSG_NXTHDR(&msg, cmptr) ) {
+ for (cmptr = CMSG_FIRSTHDR(&msg); cmptr != NULL;
+ cmptr = CMSG_NXTHDR(&msg, cmptr)) {
#ifdef IP_RECVDSTADDR
- if ( cmptr->cmsg_level == IPPROTO_IP &&
- cmptr->cmsg_type == IP_RECVDSTADDR ) {
- memcpy(&myaddr->sin_addr, CMSG_DATA(cmptr),
- sizeof(struct in_addr));
- }
+ if (cmptr->cmsg_level == IPPROTO_IP &&
+ cmptr->cmsg_type == IP_RECVDSTADDR) {
+ memcpy(&myaddr->sin_addr, CMSG_DATA(cmptr),
+ sizeof(struct in_addr));
+ }
#endif
#ifdef IP_PKTINFO
- if ( cmptr->cmsg_level == IPPROTO_IP &&
- cmptr->cmsg_type == IP_PKTINFO ) {
- memcpy(&pktinfo, CMSG_DATA(cmptr), sizeof(struct in_pktinfo));
- memcpy(&myaddr->sin_addr, &pktinfo.ipi_addr, sizeof(struct in_addr));
- }
+ if (cmptr->cmsg_level == IPPROTO_IP &&
+ cmptr->cmsg_type == IP_PKTINFO) {
+ memcpy(&pktinfo, CMSG_DATA(cmptr),
+ sizeof(struct in_pktinfo));
+ memcpy(&myaddr->sin_addr, &pktinfo.ipi_addr,
+ sizeof(struct in_addr));
+ }
#endif
+ }
}
- }
- /* If the address is not a valid local address, then bind to any address... */
- if (address_is_local(myaddr) != 1)
- myaddr->sin_addr.s_addr = INADDR_ANY;
+ /* If the address is not a valid local address, then bind to any address... */
+ if (address_is_local(myaddr) != 1)
+ myaddr->sin_addr.s_addr = INADDR_ANY;
- return n;
+ return n;
}
-#else /* pointless... */
+#else /* pointless... */
int
myrecvfrom(int s, void *buf, int len, unsigned int flags,
- struct sockaddr *from, int *fromlen,
- struct sockaddr_in *myaddr)
+ struct sockaddr *from, int *fromlen, struct sockaddr_in *myaddr)
{
- /* There is no way we can get the local address, fudge it */
+ /* There is no way we can get the local address, fudge it */
- bzero(myaddr, sizeof(struct sockaddr_in));
- myaddr->sin_family = AF_INET;
+ bzero(myaddr, sizeof(struct sockaddr_in));
+ myaddr->sin_family = AF_INET;
- myaddr->sin_port = htons(IPPORT_TFTP);
- bzero(&myaddr->sin_addr, sizeof(myaddr->sin_addr));
+ myaddr->sin_port = htons(IPPORT_TFTP);
+ bzero(&myaddr->sin_addr, sizeof(myaddr->sin_addr));
- return recvfrom(s,buf,len,flags,from,fromlen);
+ return recvfrom(s, buf, len, flags, from, fromlen);
}
#endif
diff --git a/tftpd/recvfrom.h b/tftpd/recvfrom.h
index 35ad05b..fda65c0 100644
--- a/tftpd/recvfrom.h
+++ b/tftpd/recvfrom.h
@@ -1,5 +1,5 @@
/* ----------------------------------------------------------------------- *
- *
+ *
* Copyright 2001-2006 H. Peter Anvin - All Rights Reserved
*
* This program is free software available under the same license
@@ -19,5 +19,5 @@
int
myrecvfrom(int s, void *buf, int len, unsigned int flags,
- struct sockaddr *from, socklen_t *fromlen,
- struct sockaddr_in *myaddr);
+ struct sockaddr *from, socklen_t * fromlen,
+ struct sockaddr_in *myaddr);
diff --git a/tftpd/remap.c b/tftpd/remap.c
index bb10fd0..cdb9062 100644
--- a/tftpd/remap.c
+++ b/tftpd/remap.c
@@ -1,5 +1,5 @@
/* ----------------------------------------------------------------------- *
- *
+ *
* Copyright 2001-2007 H. Peter Anvin - All Rights Reserved
*
* This program is free software available under the same license
@@ -14,7 +14,7 @@
* Perform regular-expression based filename remapping.
*/
-#include "config.h" /* Must be included first! */
+#include "config.h" /* Must be included first! */
#include <ctype.h>
#include <syslog.h>
#include <regex.h>
@@ -23,123 +23,131 @@
#include "remap.h"
#define DEADMAN_MAX_STEPS 1024 /* Timeout after this many steps */
-#define MAXLINE 16384 /* Truncate a line at this many bytes */
+#define MAXLINE 16384 /* Truncate a line at this many bytes */
-#define RULE_REWRITE 0x01 /* This is a rewrite rule */
-#define RULE_GLOBAL 0x02 /* Global rule (repeat until no match) */
-#define RULE_EXIT 0x04 /* Exit after matching this rule */
-#define RULE_RESTART 0x08 /* Restart at the top after matching this rule */
-#define RULE_ABORT 0x10 /* Terminate processing with an error */
-#define RULE_GETONLY 0x20 /* Applicable to GET only */
-#define RULE_PUTONLY 0x40 /* Applicable to PUT only */
-#define RULE_INVERSE 0x80 /* Execute if regex *doesn't* match */
+#define RULE_REWRITE 0x01 /* This is a rewrite rule */
+#define RULE_GLOBAL 0x02 /* Global rule (repeat until no match) */
+#define RULE_EXIT 0x04 /* Exit after matching this rule */
+#define RULE_RESTART 0x08 /* Restart at the top after matching this rule */
+#define RULE_ABORT 0x10 /* Terminate processing with an error */
+#define RULE_GETONLY 0x20 /* Applicable to GET only */
+#define RULE_PUTONLY 0x40 /* Applicable to PUT only */
+#define RULE_INVERSE 0x80 /* Execute if regex *doesn't* match */
struct rule {
- struct rule *next;
- int nrule;
- int rule_flags;
- regex_t rx;
- const char *pattern;
+ struct rule *next;
+ int nrule;
+ int rule_flags;
+ regex_t rx;
+ const char *pattern;
};
static int xform_null(int c)
{
- return c;
+ return c;
}
static int xform_toupper(int c)
{
- return toupper(c);
+ return toupper(c);
}
static int xform_tolower(int c)
{
- return tolower(c);
+ return tolower(c);
}
/* Do \-substitution. Call with string == NULL to get length only. */
-static int genmatchstring(char *string, const char *pattern, const char *input,
- const regmatch_t *pmatch, match_pattern_callback macrosub)
+static int genmatchstring(char *string, const char *pattern,
+ const char *input, const regmatch_t * pmatch,
+ match_pattern_callback macrosub)
{
- int (*xform)(int) = xform_null;
- int len = 0;
- int n, mlen, sublen;
- int endbytes;
-
- /* Get section before match; note pmatch[0] is the whole match */
- endbytes = strlen(input) - pmatch[0].rm_eo;
- len = pmatch[0].rm_so + endbytes;
- if ( string ) {
- memcpy(string, input, pmatch[0].rm_so);
- string += pmatch[0].rm_so;
- }
-
- /* Transform matched section */
- while ( *pattern ) {
- mlen = 0;
-
- if ( *pattern == '\\' && pattern[1] != '\0' ) {
- char macro = pattern[1];
- switch ( macro ) {
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- n = pattern[1] - '0';
-
- if ( pmatch[n].rm_so != -1 ) {
- mlen = pmatch[n].rm_eo - pmatch[n].rm_so;
- len += mlen;
- if ( string ) {
- const char *p = input+pmatch[n].rm_so;
- while ( mlen-- )
- *string++ = xform(*p++);
- }
- }
- break;
-
- case 'L':
- xform = xform_tolower;
- break;
-
- case 'U':
- xform = xform_toupper;
- break;
-
- case 'E':
- xform = xform_null;
- break;
-
- default:
- if ( macrosub &&
- (sublen = macrosub(macro, string)) >= 0 ) {
- while ( sublen-- ) {
- len++;
- if ( string ) {
- *string = xform(*string);
- string++;
- }
- }
- } else {
- len++;
- if ( string )
- *string++ = xform(pattern[1]);
- }
- }
- pattern += 2;
- } else {
- len++;
- if ( string )
- *string++ = xform(*pattern);
- pattern++;
+ int (*xform) (int) = xform_null;
+ int len = 0;
+ int n, mlen, sublen;
+ int endbytes;
+
+ /* Get section before match; note pmatch[0] is the whole match */
+ endbytes = strlen(input) - pmatch[0].rm_eo;
+ len = pmatch[0].rm_so + endbytes;
+ if (string) {
+ memcpy(string, input, pmatch[0].rm_so);
+ string += pmatch[0].rm_so;
}
- }
- /* Copy section after match */
- if ( string ) {
- memcpy(string, input+pmatch[0].rm_eo, endbytes);
- string[endbytes] = '\0';
- }
+ /* Transform matched section */
+ while (*pattern) {
+ mlen = 0;
+
+ if (*pattern == '\\' && pattern[1] != '\0') {
+ char macro = pattern[1];
+ switch (macro) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ n = pattern[1] - '0';
+
+ if (pmatch[n].rm_so != -1) {
+ mlen = pmatch[n].rm_eo - pmatch[n].rm_so;
+ len += mlen;
+ if (string) {
+ const char *p = input + pmatch[n].rm_so;
+ while (mlen--)
+ *string++ = xform(*p++);
+ }
+ }
+ break;
+
+ case 'L':
+ xform = xform_tolower;
+ break;
+
+ case 'U':
+ xform = xform_toupper;
+ break;
+
+ case 'E':
+ xform = xform_null;
+ break;
+
+ default:
+ if (macrosub && (sublen = macrosub(macro, string)) >= 0) {
+ while (sublen--) {
+ len++;
+ if (string) {
+ *string = xform(*string);
+ string++;
+ }
+ }
+ } else {
+ len++;
+ if (string)
+ *string++ = xform(pattern[1]);
+ }
+ }
+ pattern += 2;
+ } else {
+ len++;
+ if (string)
+ *string++ = xform(*pattern);
+ pattern++;
+ }
+ }
- return len;
+ /* Copy section after match */
+ if (string) {
+ memcpy(string, input + pmatch[0].rm_eo, endbytes);
+ string[endbytes] = '\0';
+ }
+
+ return len;
}
/*
@@ -149,277 +157,284 @@ static int genmatchstring(char *string, const char *pattern, const char *input,
*/
static int readescstring(char *buf, char **str)
{
- char *p = *str;
- int wasbs = 0, len = 0;
+ char *p = *str;
+ int wasbs = 0, len = 0;
+
+ while (*p && isspace(*p))
+ p++;
- while ( *p && isspace(*p) )
- p++;
+ if (!*p) {
+ *buf = '\0';
+ *str = p;
+ return 0;
+ }
+
+ while (*p) {
+ if (!wasbs && (isspace(*p) || *p == '#')) {
+ *buf = '\0';
+ *str = p;
+ return len;
+ }
+ /* Important: two backslashes leave us in the !wasbs state! */
+ wasbs = !wasbs && (*p == '\\');
+ *buf++ = *p++;
+ len++;
+ }
- if ( ! *p ) {
*buf = '\0';
*str = p;
- return 0;
- }
-
- while ( *p ) {
- if ( !wasbs && (isspace(*p) || *p == '#') ) {
- *buf = '\0';
- *str = p;
- return len;
- }
- /* Important: two backslashes leave us in the !wasbs state! */
- wasbs = !wasbs && ( *p == '\\' );
- *buf++ = *p++;
- len++;
- }
-
- *buf = '\0';
- *str = p;
- return len;
+ return len;
}
/* Parse a line into a set of instructions */
static int parseline(char *line, struct rule *r, int lineno)
{
- char buffer[MAXLINE];
- char *p;
- int rv;
- int rxflags = REG_EXTENDED;
- static int nrule;
-
- memset(r, 0, sizeof *r);
- r->nrule = nrule;
-
- if ( !readescstring(buffer, &line) )
- return 0; /* No rule found */
-
- for ( p = buffer ; *p ; p++ ) {
- switch(*p) {
- case 'r':
- r->rule_flags |= RULE_REWRITE;
- break;
- case 'g':
- r->rule_flags |= RULE_GLOBAL;
- break;
- case 'e':
- r->rule_flags |= RULE_EXIT;
- break;
- case 's':
- r->rule_flags |= RULE_RESTART;
- break;
- case 'a':
- r->rule_flags |= RULE_ABORT;
- break;
- case 'i':
- rxflags |= REG_ICASE;
- break;
- case 'G':
- r->rule_flags |= RULE_GETONLY;
- break;
- case 'P':
- r->rule_flags |= RULE_PUTONLY;
- break;
- case '~':
- r->rule_flags |= RULE_INVERSE;
- break;
- default:
- syslog(LOG_ERR, "Remap command \"%s\" on line %d contains invalid char \"%c\"",
- buffer, lineno, *p);
- return -1; /* Error */
- break;
+ char buffer[MAXLINE];
+ char *p;
+ int rv;
+ int rxflags = REG_EXTENDED;
+ static int nrule;
+
+ memset(r, 0, sizeof *r);
+ r->nrule = nrule;
+
+ if (!readescstring(buffer, &line))
+ return 0; /* No rule found */
+
+ for (p = buffer; *p; p++) {
+ switch (*p) {
+ case 'r':
+ r->rule_flags |= RULE_REWRITE;
+ break;
+ case 'g':
+ r->rule_flags |= RULE_GLOBAL;
+ break;
+ case 'e':
+ r->rule_flags |= RULE_EXIT;
+ break;
+ case 's':
+ r->rule_flags |= RULE_RESTART;
+ break;
+ case 'a':
+ r->rule_flags |= RULE_ABORT;
+ break;
+ case 'i':
+ rxflags |= REG_ICASE;
+ break;
+ case 'G':
+ r->rule_flags |= RULE_GETONLY;
+ break;
+ case 'P':
+ r->rule_flags |= RULE_PUTONLY;
+ break;
+ case '~':
+ r->rule_flags |= RULE_INVERSE;
+ break;
+ default:
+ syslog(LOG_ERR,
+ "Remap command \"%s\" on line %d contains invalid char \"%c\"",
+ buffer, lineno, *p);
+ return -1; /* Error */
+ break;
+ }
+ }
+
+ /* RULE_GLOBAL only applies when RULE_REWRITE specified */
+ if (!(r->rule_flags & RULE_REWRITE))
+ r->rule_flags &= ~RULE_GLOBAL;
+
+ if ((r->rule_flags & (RULE_INVERSE | RULE_REWRITE)) ==
+ (RULE_INVERSE | RULE_REWRITE)) {
+ syslog(LOG_ERR, "r rules cannot be inverted, line %d: %s\n",
+ lineno, line);
+ return -1; /* Error */
}
- }
-
- /* RULE_GLOBAL only applies when RULE_REWRITE specified */
- if ( !(r->rule_flags & RULE_REWRITE) )
- r->rule_flags &= ~RULE_GLOBAL;
-
- if ( (r->rule_flags & (RULE_INVERSE|RULE_REWRITE)) ==
- (RULE_INVERSE|RULE_REWRITE) ) {
- syslog(LOG_ERR, "r rules cannot be inverted, line %d: %s\n", lineno, line);
- return -1; /* Error */
- }
-
- /* Read and compile the regex */
- if ( !readescstring(buffer, &line) ) {
- syslog(LOG_ERR, "No regex on remap line %d: %s\n", lineno, line);
- return -1; /* Error */
- }
-
- if ( (rv = regcomp(&r->rx, buffer, rxflags)) != 0 ) {
- char errbuf[BUFSIZ];
- regerror(rv, &r->rx, errbuf, BUFSIZ);
- syslog(LOG_ERR, "Bad regex in remap line %d: %s\n", lineno, errbuf);
- return -1; /* Error */
- }
-
- /* Read the rewrite pattern, if any */
- if ( readescstring(buffer, &line) ) {
- r->pattern = tfstrdup(buffer);
- } else {
- r->pattern = "";
- }
-
- nrule++;
- return 1; /* Rule found */
+
+ /* Read and compile the regex */
+ if (!readescstring(buffer, &line)) {
+ syslog(LOG_ERR, "No regex on remap line %d: %s\n", lineno, line);
+ return -1; /* Error */
+ }
+
+ if ((rv = regcomp(&r->rx, buffer, rxflags)) != 0) {
+ char errbuf[BUFSIZ];
+ regerror(rv, &r->rx, errbuf, BUFSIZ);
+ syslog(LOG_ERR, "Bad regex in remap line %d: %s\n", lineno,
+ errbuf);
+ return -1; /* Error */
+ }
+
+ /* Read the rewrite pattern, if any */
+ if (readescstring(buffer, &line)) {
+ r->pattern = tfstrdup(buffer);
+ } else {
+ r->pattern = "";
+ }
+
+ nrule++;
+ return 1; /* Rule found */
}
/* Read a rule file */
-struct rule *parserulefile(FILE *f)
+struct rule *parserulefile(FILE * f)
{
- char line[MAXLINE];
- struct rule *first_rule = NULL;
- struct rule **last_rule = &first_rule;
- struct rule *this_rule = tfmalloc(sizeof(struct rule));
- int rv;
- int lineno = 0;
- int err = 0;
-
- while ( lineno++, fgets(line, MAXLINE, f) ) {
- rv = parseline(line, this_rule, lineno);
- if ( rv < 0 )
- err = 1;
- if ( rv > 0 ) {
- *last_rule = this_rule;
- last_rule = &this_rule->next;
- this_rule = tfmalloc(sizeof(struct rule));
+ char line[MAXLINE];
+ struct rule *first_rule = NULL;
+ struct rule **last_rule = &first_rule;
+ struct rule *this_rule = tfmalloc(sizeof(struct rule));
+ int rv;
+ int lineno = 0;
+ int err = 0;
+
+ while (lineno++, fgets(line, MAXLINE, f)) {
+ rv = parseline(line, this_rule, lineno);
+ if (rv < 0)
+ err = 1;
+ if (rv > 0) {
+ *last_rule = this_rule;
+ last_rule = &this_rule->next;
+ this_rule = tfmalloc(sizeof(struct rule));
+ }
}
- }
- free(this_rule); /* Last one is always unused */
+ free(this_rule); /* Last one is always unused */
- if ( err ) {
- /* Bail on error, we have already logged an error message */
- exit(EX_CONFIG);
- }
+ if (err) {
+ /* Bail on error, we have already logged an error message */
+ exit(EX_CONFIG);
+ }
- return first_rule;
+ return first_rule;
}
/* Destroy a rule file data structure */
void freerules(struct rule *r)
{
- struct rule *next;
+ struct rule *next;
- while ( r ) {
- next = r->next;
+ while (r) {
+ next = r->next;
- regfree(&r->rx);
+ regfree(&r->rx);
- /* "" patterns aren't allocated by malloc() */
- if ( r->pattern && *r->pattern )
- free((void *)r->pattern);
-
- free(r);
+ /* "" patterns aren't allocated by malloc() */
+ if (r->pattern && *r->pattern)
+ free((void *)r->pattern);
- r = next;
- }
+ free(r);
+
+ r = next;
+ }
}
/* Execute a rule set on a string; returns a malloc'd new string. */
char *rewrite_string(const char *input, const struct rule *rules,
- int is_put, match_pattern_callback macrosub,
- const char **errmsg)
+ int is_put, match_pattern_callback macrosub,
+ const char **errmsg)
{
- char *current = tfstrdup(input);
- char *newstr;
- const struct rule *ruleptr = rules;
- regmatch_t pmatch[10];
- int len;
- int was_match = 0;
- int deadman = DEADMAN_MAX_STEPS;
-
- /* Default error */
- *errmsg = "Remap table failure";
-
- if ( verbosity >= 3 ) {
- syslog(LOG_INFO, "remap: input: %s", current);
- }
-
- for ( ruleptr = rules ; ruleptr ; ruleptr = ruleptr->next ) {
- if ( ((ruleptr->rule_flags & RULE_GETONLY) && is_put) ||
- ((ruleptr->rule_flags & RULE_PUTONLY) && !is_put) ) {
- continue; /* Rule not applicable, try next */
+ char *current = tfstrdup(input);
+ char *newstr;
+ const struct rule *ruleptr = rules;
+ regmatch_t pmatch[10];
+ int len;
+ int was_match = 0;
+ int deadman = DEADMAN_MAX_STEPS;
+
+ /* Default error */
+ *errmsg = "Remap table failure";
+
+ if (verbosity >= 3) {
+ syslog(LOG_INFO, "remap: input: %s", current);
}
- if ( ! deadman-- ) {
- syslog(LOG_WARNING, "remap: Breaking loop, input = %s, last = %s",
- input, current);
- free(current);
- return NULL; /* Did not terminate! */
+ for (ruleptr = rules; ruleptr; ruleptr = ruleptr->next) {
+ if (((ruleptr->rule_flags & RULE_GETONLY) && is_put) ||
+ ((ruleptr->rule_flags & RULE_PUTONLY) && !is_put)) {
+ continue; /* Rule not applicable, try next */
+ }
+
+ if (!deadman--) {
+ syslog(LOG_WARNING,
+ "remap: Breaking loop, input = %s, last = %s", input,
+ current);
+ free(current);
+ return NULL; /* Did not terminate! */
+ }
+
+ do {
+ if (regexec(&ruleptr->rx, current, 10, pmatch, 0) ==
+ (ruleptr->rule_flags & RULE_INVERSE ? REG_NOMATCH : 0)) {
+ /* Match on this rule */
+ was_match = 1;
+
+ if (ruleptr->rule_flags & RULE_INVERSE) {
+ /* No actual match, so clear out the pmatch array */
+ int i;
+ for (i = 0; i < 10; i++)
+ pmatch[i].rm_so = pmatch[i].rm_eo = -1;
+ }
+
+ if (ruleptr->rule_flags & RULE_ABORT) {
+ if (verbosity >= 3) {
+ syslog(LOG_INFO, "remap: rule %d: abort: %s",
+ ruleptr->nrule, current);
+ }
+ if (ruleptr->pattern[0]) {
+ /* Custom error message */
+ len =
+ genmatchstring(NULL, ruleptr->pattern, current,
+ pmatch, macrosub);
+ newstr = tfmalloc(len + 1);
+ genmatchstring(newstr, ruleptr->pattern, current,
+ pmatch, macrosub);
+ *errmsg = newstr;
+ } else {
+ *errmsg = NULL;
+ }
+ free(current);
+ return (NULL);
+ }
+
+ if (ruleptr->rule_flags & RULE_REWRITE) {
+ len = genmatchstring(NULL, ruleptr->pattern, current,
+ pmatch, macrosub);
+ newstr = tfmalloc(len + 1);
+ genmatchstring(newstr, ruleptr->pattern, current,
+ pmatch, macrosub);
+ free(current);
+ current = newstr;
+ if (verbosity >= 3) {
+ syslog(LOG_INFO, "remap: rule %d: rewrite: %s",
+ ruleptr->nrule, current);
+ }
+ }
+ } else {
+ break; /* No match, terminate unconditionally */
+ }
+ /* If the rule is global, keep going until no match */
+ } while (ruleptr->rule_flags & RULE_GLOBAL);
+
+ if (was_match) {
+ was_match = 0;
+
+ if (ruleptr->rule_flags & RULE_EXIT) {
+ if (verbosity >= 3) {
+ syslog(LOG_INFO, "remap: rule %d: exit",
+ ruleptr->nrule);
+ }
+ return current; /* Exit here, we're done */
+ } else if (ruleptr->rule_flags & RULE_RESTART) {
+ ruleptr = rules; /* Start from the top */
+ if (verbosity >= 3) {
+ syslog(LOG_INFO, "remap: rule %d: restart",
+ ruleptr->nrule);
+ }
+ }
+ }
}
- do {
- if ( regexec(&ruleptr->rx, current, 10, pmatch, 0) ==
- (ruleptr->rule_flags & RULE_INVERSE ? REG_NOMATCH : 0) ) {
- /* Match on this rule */
- was_match = 1;
-
- if ( ruleptr->rule_flags & RULE_INVERSE ) {
- /* No actual match, so clear out the pmatch array */
- int i;
- for ( i = 0 ; i < 10 ; i++ )
- pmatch[i].rm_so = pmatch[i].rm_eo = -1;
- }
-
- if ( ruleptr->rule_flags & RULE_ABORT ) {
- if ( verbosity >= 3 ) {
- syslog(LOG_INFO, "remap: rule %d: abort: %s",
- ruleptr->nrule, current);
- }
- if ( ruleptr->pattern[0] ) {
- /* Custom error message */
- len = genmatchstring(NULL, ruleptr->pattern, current,
- pmatch, macrosub);
- newstr = tfmalloc(len+1);
- genmatchstring(newstr, ruleptr->pattern, current,
- pmatch, macrosub);
- *errmsg = newstr;
- } else {
- *errmsg = NULL;
- }
- free(current);
- return(NULL);
- }
-
- if ( ruleptr->rule_flags & RULE_REWRITE ) {
- len = genmatchstring(NULL, ruleptr->pattern, current,
- pmatch, macrosub);
- newstr = tfmalloc(len+1);
- genmatchstring(newstr, ruleptr->pattern, current,
- pmatch, macrosub);
- free(current);
- current = newstr;
- if ( verbosity >= 3 ) {
- syslog(LOG_INFO, "remap: rule %d: rewrite: %s",
- ruleptr->nrule, current);
- }
- }
- } else {
- break; /* No match, terminate unconditionally */
- }
- /* If the rule is global, keep going until no match */
- } while ( ruleptr->rule_flags & RULE_GLOBAL );
-
- if ( was_match ) {
- was_match = 0;
-
- if ( ruleptr->rule_flags & RULE_EXIT ) {
- if ( verbosity >= 3 ) {
- syslog(LOG_INFO, "remap: rule %d: exit", ruleptr->nrule);
- }
- return current; /* Exit here, we're done */
- } else if ( ruleptr->rule_flags & RULE_RESTART ) {
- ruleptr = rules; /* Start from the top */
- if ( verbosity >= 3 ) {
- syslog(LOG_INFO, "remap: rule %d: restart", ruleptr->nrule);
- }
- }
+ if (verbosity >= 3) {
+ syslog(LOG_INFO, "remap: done");
}
- }
-
- if ( verbosity >= 3 ) {
- syslog(LOG_INFO, "remap: done");
- }
- return current;
+ return current;
}
diff --git a/tftpd/remap.h b/tftpd/remap.h
index a00094c..3830b5c 100644
--- a/tftpd/remap.h
+++ b/tftpd/remap.h
@@ -1,5 +1,5 @@
/* ----------------------------------------------------------------------- *
- *
+ *
* Copyright 2001-2007 H. Peter Anvin - All Rights Reserved
*
* This program is free software available under the same license
@@ -26,7 +26,7 @@ struct rule;
macro character is passed as the first argument; the output buffer,
if any, is passed as the second argument. The function should return
the number of characters output, or -1 on failure. */
-typedef int (*match_pattern_callback)(char, char *);
+typedef int (*match_pattern_callback) (char, char *);
/* Read a rule file */
struct rule *parserulefile(FILE *);
@@ -36,8 +36,7 @@ void freerules(struct rule *);
/* Execute a rule set on a string; returns a malloc'd new string. */
char *rewrite_string(const char *, const struct rule *, int,
- match_pattern_callback, const char **);
-
-#endif /* WITH_REGEX */
-#endif /* TFTPD_REMAP_H */
+ match_pattern_callback, const char **);
+#endif /* WITH_REGEX */
+#endif /* TFTPD_REMAP_H */
diff --git a/tftpd/tftpd.c b/tftpd/tftpd.c
index 92a6889..92b7c67 100644
--- a/tftpd/tftpd.c
+++ b/tftpd/tftpd.c
@@ -33,19 +33,9 @@
* SUCH DAMAGE.
*/
-#include "config.h" /* Must be included first */
+#include "config.h" /* Must be included first */
#include "tftpd.h"
-#ifndef lint
-static const char *copyright UNUSED =
-"@(#) Copyright (c) 1983 Regents of the University of California.\n\
- All rights reserved.\n";
-/*static char sccsid[] = "from: @(#)tftpd.c 5.13 (Berkeley) 2/26/91";*/
-/*static char rcsid[] = "$OpenBSD: tftpd.c,v 1.13 1999/06/23 17:01:36 deraadt Exp $: tftpd.c,v 1.6 1997/02/16 23:49:21 deraadt Exp $";*/
-static const char *rcsid UNUSED =
-"tftp-hpa $Id$";
-#endif /* not lint */
-
/*
* Trivial file transfer protocol server.
*
@@ -65,49 +55,49 @@ static const char *rcsid UNUSED =
#include "remap.h"
#ifdef HAVE_SYS_FILIO_H
-#include <sys/filio.h> /* Necessary for FIONBIO on Solaris */
+#include <sys/filio.h> /* Necessary for FIONBIO on Solaris */
#endif
#ifdef HAVE_TCPWRAPPERS
#include <tcpd.h>
-int deny_severity = LOG_WARNING;
-int allow_severity = -1; /* Don't log at all */
+int deny_severity = LOG_WARNING;
+int allow_severity = -1; /* Don't log at all */
struct request_info wrap_request;
#endif
-#define TIMEOUT 1000000 /* Default timeout (us) */
-#define TRIES 6 /* Number of attempts to send each packet */
+#define TIMEOUT 1000000 /* Default timeout (us) */
+#define TRIES 6 /* Number of attempts to send each packet */
#define TIMEOUT_LIMIT ((1 << TRIES)-1)
-const char *__progname;
-int peer;
-unsigned long timeout = TIMEOUT; /* Current timeout value */
-unsigned long rexmtval = TIMEOUT; /* Basic timeout value */
-unsigned long maxtimeout = TIMEOUT_LIMIT*TIMEOUT;
-int timeout_quit = 0;
-sigjmp_buf timeoutbuf;
+const char *__progname;
+int peer;
+unsigned long timeout = TIMEOUT; /* Current timeout value */
+unsigned long rexmtval = TIMEOUT; /* Basic timeout value */
+unsigned long maxtimeout = TIMEOUT_LIMIT * TIMEOUT;
+int timeout_quit = 0;
+sigjmp_buf timeoutbuf;
#define PKTSIZE MAX_SEGSIZE+4
-char buf[PKTSIZE];
-char ackbuf[PKTSIZE];
-unsigned int max_blksize = MAX_SEGSIZE;
+char buf[PKTSIZE];
+char ackbuf[PKTSIZE];
+unsigned int max_blksize = MAX_SEGSIZE;
struct sockaddr_in from;
-socklen_t fromlen;
-off_t tsize;
-int tsize_ok;
+socklen_t fromlen;
+off_t tsize;
+int tsize_ok;
-int ndirs;
-const char **dirs;
+int ndirs;
+const char **dirs;
-int secure = 0;
-int cancreate = 0;
-int unixperms = 0;
-int portrange = 0;
-unsigned int portrange_from, portrange_to;
-int verbosity = 0;
+int secure = 0;
+int cancreate = 0;
+int unixperms = 0;
+int portrange = 0;
+unsigned int portrange_from, portrange_to;
+int verbosity = 0;
struct formats;
#ifdef WITH_REGEX
@@ -127,91 +117,80 @@ int set_timeout(char *, char **);
int set_utimeout(char *, char **);
struct options {
- const char *o_opt;
- int (*o_fnc)(char *, char **);
+ const char *o_opt;
+ int (*o_fnc) (char *, char **);
} options[] = {
- { "blksize", set_blksize },
- { "blksize2", set_blksize2 },
- { "tsize", set_tsize },
- { "timeout", set_timeout },
- { "utimeout", set_utimeout },
- { NULL, NULL }
+ {
+ "blksize", set_blksize}, {
+ "blksize2", set_blksize2}, {
+ "tsize", set_tsize}, {
+ "timeout", set_timeout}, {
+ "utimeout", set_utimeout}, {
+ NULL, NULL}
};
/* Simple handler for SIGHUP */
static volatile sig_atomic_t caught_sighup = 0;
static void handle_sighup(int sig)
{
- (void)sig; /* Suppress unused warning */
- caught_sighup = 1;
+ (void)sig; /* Suppress unused warning */
+ caught_sighup = 1;
}
-
/* Handle timeout signal or timeout event */
-void
-timer(int sig)
+void timer(int sig)
{
- (void)sig; /* Suppress unused warning */
- timeout <<= 1;
- if (timeout >= maxtimeout || timeout_quit)
- exit(0);
- siglongjmp(timeoutbuf, 1);
+ (void)sig; /* Suppress unused warning */
+ timeout <<= 1;
+ if (timeout >= maxtimeout || timeout_quit)
+ exit(0);
+ siglongjmp(timeoutbuf, 1);
}
-static void
-usage(void)
+#ifdef WITH_REGEX
+static struct rule *read_remap_rules(const char *file)
{
- syslog(LOG_ERR, "Usage: %s [-vcl][-a address][-m mappings][-u user][-t inetd_timeout][-T pkt_timeout][-r option...] [-s] [directory ...]",
- __progname);
- exit(EX_USAGE);
-}
+ FILE *f;
+ struct rule *rulep;
+ f = fopen(file, "rt");
+ if (!f) {
+ syslog(LOG_ERR, "Cannot open map file: %s: %m", file);
+ exit(EX_NOINPUT);
+ }
+ rulep = parserulefile(f);
+ fclose(f);
-#ifdef WITH_REGEX
-static struct rule *
-read_remap_rules(const char *file)
-{
- FILE *f;
- struct rule *rulep;
-
- f = fopen(file, "rt");
- if ( !f ) {
- syslog(LOG_ERR, "Cannot open map file: %s: %m", file);
- exit(EX_NOINPUT);
- }
- rulep = parserulefile(f);
- fclose(f);
-
- return rulep;
+ return rulep;
}
#endif
-static void
-set_socket_nonblock(int fd, int flag)
+static void set_socket_nonblock(int fd, int flag)
{
- int err;
- int flags;
+ int err;
+ int flags;
#if defined(HAVE_FCNTL) && defined(HAVE_O_NONBLOCK_DEFINITION)
- /* Posixly correct */
- err = ((flags = fcntl(fd, F_GETFL, 0)) < 0) ||
- (fcntl(fd, F_SETFL, flag ? flags|O_NONBLOCK : flags&~O_NONBLOCK) < 0);
+ /* Posixly correct */
+ err = ((flags = fcntl(fd, F_GETFL, 0)) < 0) ||
+ (fcntl
+ (fd, F_SETFL,
+ flag ? flags | O_NONBLOCK : flags & ~O_NONBLOCK) < 0);
#else
- flags = flag ? 1 : 0;
- err = (ioctl(fd, FIONBIO, &flags) < 0);
+ flags = flag ? 1 : 0;
+ err = (ioctl(fd, FIONBIO, &flags) < 0);
#endif
- if ( err ) {
- syslog(LOG_ERR, "Cannot set nonblock flag on socket: %m");
- exit(EX_OSERR);
- }
+ if (err) {
+ syslog(LOG_ERR, "Cannot set nonblock flag on socket: %m");
+ exit(EX_OSERR);
+ }
}
-static void
-pmtu_discovery_off(int fd)
+static void pmtu_discovery_off(int fd)
{
#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
- int pmtu = IP_PMTUDISC_DONT;
+ int pmtu = IP_PMTUDISC_DONT;
- setsockopt(fd, IPPROTO_IP, IP_MTU_DISCOVER, &pmtu, sizeof(pmtu));
+ setsockopt(fd, IPPROTO_IP, IP_MTU_DISCOVER, &pmtu, sizeof(pmtu));
#endif
}
@@ -220,617 +199,630 @@ pmtu_discovery_off(int fd)
* to account for time spent waiting.
*/
static int recv_time(int s, void *rbuf, int len, unsigned int flags,
- unsigned long *timeout_us_p)
+ unsigned long *timeout_us_p)
{
- fd_set fdset;
- struct timeval tmv, t0, t1;
- int rv, err;
- unsigned long timeout_us = *timeout_us_p;
- unsigned long timeout_left, dt;
-
- gettimeofday(&t0, NULL);
- timeout_left = timeout_us;
-
- for ( ; ; ) {
- FD_ZERO(&fdset);
- FD_SET(s, &fdset);
-
- do {
- tmv.tv_sec = timeout_left / 1000000;
- tmv.tv_usec = timeout_left % 1000000;
-
- rv = select(s+1, &fdset, NULL, NULL, &tmv);
- err = errno;
-
- gettimeofday(&t1, NULL);
-
- dt = (t1.tv_sec - t0.tv_sec)*1000000 + (t1.tv_usec - t0.tv_usec);
- *timeout_us_p = timeout_left = ( dt >= timeout_us ) ? 1 : (timeout_us - dt);
- } while ( rv == -1 && err == EINTR );
-
- if ( rv == 0 ) {
- timer(0); /* Should not return */
- return -1;
- }
-
- set_socket_nonblock(s, 1);
- rv = recv(s, rbuf, len, flags);
- err = errno;
- set_socket_nonblock(s, 0);
-
- if ( rv < 0 ) {
- if ( E_WOULD_BLOCK(err) || err == EINTR ) {
- continue; /* Once again, with feeling... */
- } else {
- errno = err;
- return rv;
- }
- } else {
- return rv;
+ fd_set fdset;
+ struct timeval tmv, t0, t1;
+ int rv, err;
+ unsigned long timeout_us = *timeout_us_p;
+ unsigned long timeout_left, dt;
+
+ gettimeofday(&t0, NULL);
+ timeout_left = timeout_us;
+
+ for (;;) {
+ FD_ZERO(&fdset);
+ FD_SET(s, &fdset);
+
+ do {
+ tmv.tv_sec = timeout_left / 1000000;
+ tmv.tv_usec = timeout_left % 1000000;
+
+ rv = select(s + 1, &fdset, NULL, NULL, &tmv);
+ err = errno;
+
+ gettimeofday(&t1, NULL);
+
+ dt = (t1.tv_sec - t0.tv_sec) * 1000000 + (t1.tv_usec -
+ t0.tv_usec);
+ *timeout_us_p = timeout_left =
+ (dt >= timeout_us) ? 1 : (timeout_us - dt);
+ } while (rv == -1 && err == EINTR);
+
+ if (rv == 0) {
+ timer(0); /* Should not return */
+ return -1;
+ }
+
+ set_socket_nonblock(s, 1);
+ rv = recv(s, rbuf, len, flags);
+ err = errno;
+ set_socket_nonblock(s, 0);
+
+ if (rv < 0) {
+ if (E_WOULD_BLOCK(err) || err == EINTR) {
+ continue; /* Once again, with feeling... */
+ } else {
+ errno = err;
+ return rv;
+ }
+ } else {
+ return rv;
+ }
}
- }
}
-
-int
-main(int argc, char **argv)
+int main(int argc, char **argv)
{
- struct tftphdr *tp;
- struct passwd *pw;
- struct options *opt;
- struct sockaddr_in myaddr;
- struct sockaddr_in bindaddr;
- int n;
- int fd = 0;
- int standalone = 0; /* Standalone (listen) mode */
- int nodaemon = 0; /* Do not detach process */
- char *address = NULL; /* Address to listen to */
- pid_t pid;
- mode_t my_umask = 0;
- int spec_umask = 0;
- int c;
- int setrv;
- int waittime = 900; /* Default time to wait for a connect*/
- const char *user = "nobody"; /* Default user */
- char *p, *ep;
+ struct tftphdr *tp;
+ struct passwd *pw;
+ struct options *opt;
+ struct sockaddr_in myaddr;
+ struct sockaddr_in bindaddr;
+ int n;
+ int fd = 0;
+ int standalone = 0; /* Standalone (listen) mode */
+ int nodaemon = 0; /* Do not detach process */
+ char *address = NULL; /* Address to listen to */
+ pid_t pid;
+ mode_t my_umask = 0;
+ int spec_umask = 0;
+ int c;
+ int setrv;
+ int waittime = 900; /* Default time to wait for a connect */
+ const char *user = "nobody"; /* Default user */
+ char *p, *ep;
#ifdef WITH_REGEX
- char *rewrite_file = NULL;
+ char *rewrite_file = NULL;
#endif
- u_short tp_opcode;
-
- /* basename() is way too much of a pain from a portability standpoint */
-
- p = strrchr(argv[0], '/');
- __progname = (p && p[1]) ? p+1 : argv[0];
-
- openlog(__progname, LOG_PID|LOG_NDELAY, LOG_DAEMON);
-
- srand(time(NULL) ^ getpid());
-
- while ((c = getopt(argc, argv, "cspvVlLa:B:u:U:r:t:T:R:m:")) != -1)
- switch (c) {
- case 'c':
- cancreate = 1;
- break;
- case 's':
- secure = 1;
- break;
- case 'p':
- unixperms = 1;
- break;
- case 'l':
- standalone = 1;
- break;
- case 'L':
- standalone = 1;
- nodaemon = 1;
- break;
- case 'a':
- address = optarg;
- break;
- case 't':
- waittime = atoi(optarg);
- break;
- case 'B':
- {
- char *vp;
- max_blksize = (unsigned int)strtoul(optarg, &vp, 10);
- if ( max_blksize < 512 || max_blksize > MAX_SEGSIZE || *vp ) {
- syslog(LOG_ERR, "Bad maximum blocksize value (range 512-%d): %s",
- MAX_SEGSIZE, optarg);
- exit(EX_USAGE);
- }
- }
- break;
- case 'T':
- {
- char *vp;
- unsigned long tov = strtoul(optarg, &vp, 10);
- if ( tov < 10000UL || tov > 255000000UL || *vp ) {
- syslog(LOG_ERR, "Bad timeout value: %s", optarg);
- exit(EX_USAGE);
- }
- rexmtval = timeout = tov;
- maxtimeout = rexmtval*TIMEOUT_LIMIT;
- }
- break;
- case 'R':
- {
- if ( sscanf(optarg, "%u:%u", &portrange_from, &portrange_to) != 2 ||
- portrange_from > portrange_to || portrange_to >= 65535 ) {
- syslog(LOG_ERR, "Bad port range: %s", optarg);
- exit(EX_USAGE);
- }
- portrange = 1;
- }
- break;
- case 'u':
- user = optarg;
- break;
- case 'U':
- my_umask = strtoul(optarg, &ep, 8);
- if ( *ep ) {
- syslog(LOG_ERR, "Invalid umask: %s", optarg);
- exit(EX_USAGE);
- }
- spec_umask = 1;
- break;
- case 'r':
- for ( opt = options ; opt->o_opt ; opt++ ) {
- if ( !strcasecmp(optarg, opt->o_opt) ) {
- opt->o_opt = ""; /* Don't support this option */
- break;
- }
- }
- if ( !opt->o_opt ) {
- syslog(LOG_ERR, "Unknown option: %s", optarg);
- exit(EX_USAGE);
- }
- break;
+ u_short tp_opcode;
+
+ /* basename() is way too much of a pain from a portability standpoint */
+
+ p = strrchr(argv[0], '/');
+ __progname = (p && p[1]) ? p + 1 : argv[0];
+
+ openlog(__progname, LOG_PID | LOG_NDELAY, LOG_DAEMON);
+
+ srand(time(NULL) ^ getpid());
+
+ while ((c = getopt(argc, argv, "cspvVlLa:B:u:U:r:t:T:R:m:")) != -1)
+ switch (c) {
+ case 'c':
+ cancreate = 1;
+ break;
+ case 's':
+ secure = 1;
+ break;
+ case 'p':
+ unixperms = 1;
+ break;
+ case 'l':
+ standalone = 1;
+ break;
+ case 'L':
+ standalone = 1;
+ nodaemon = 1;
+ break;
+ case 'a':
+ address = optarg;
+ break;
+ case 't':
+ waittime = atoi(optarg);
+ break;
+ case 'B':
+ {
+ char *vp;
+ max_blksize = (unsigned int)strtoul(optarg, &vp, 10);
+ if (max_blksize < 512 || max_blksize > MAX_SEGSIZE || *vp) {
+ syslog(LOG_ERR,
+ "Bad maximum blocksize value (range 512-%d): %s",
+ MAX_SEGSIZE, optarg);
+ exit(EX_USAGE);
+ }
+ }
+ break;
+ case 'T':
+ {
+ char *vp;
+ unsigned long tov = strtoul(optarg, &vp, 10);
+ if (tov < 10000UL || tov > 255000000UL || *vp) {
+ syslog(LOG_ERR, "Bad timeout value: %s", optarg);
+ exit(EX_USAGE);
+ }
+ rexmtval = timeout = tov;
+ maxtimeout = rexmtval * TIMEOUT_LIMIT;
+ }
+ break;
+ case 'R':
+ {
+ if (sscanf(optarg, "%u:%u", &portrange_from, &portrange_to)
+ != 2 || portrange_from > portrange_to
+ || portrange_to >= 65535) {
+ syslog(LOG_ERR, "Bad port range: %s", optarg);
+ exit(EX_USAGE);
+ }
+ portrange = 1;
+ }
+ break;
+ case 'u':
+ user = optarg;
+ break;
+ case 'U':
+ my_umask = strtoul(optarg, &ep, 8);
+ if (*ep) {
+ syslog(LOG_ERR, "Invalid umask: %s", optarg);
+ exit(EX_USAGE);
+ }
+ spec_umask = 1;
+ break;
+ case 'r':
+ for (opt = options; opt->o_opt; opt++) {
+ if (!strcasecmp(optarg, opt->o_opt)) {
+ opt->o_opt = ""; /* Don't support this option */
+ break;
+ }
+ }
+ if (!opt->o_opt) {
+ syslog(LOG_ERR, "Unknown option: %s", optarg);
+ exit(EX_USAGE);
+ }
+ break;
#ifdef WITH_REGEX
- case 'm':
- if ( rewrite_file ) {
- syslog(LOG_ERR, "Multiple -m options");
- exit(EX_USAGE);
- }
- rewrite_file = optarg;
- break;
+ case 'm':
+ if (rewrite_file) {
+ syslog(LOG_ERR, "Multiple -m options");
+ exit(EX_USAGE);
+ }
+ rewrite_file = optarg;
+ break;
#endif
- case 'v':
- verbosity++;
- break;
- case 'V':
- /* Print configuration to stdout and exit */
- printf("%s\n", TFTPD_CONFIG_STR);
- exit(0);
- break;
- default:
- usage();
- break;
+ case 'v':
+ verbosity++;
+ break;
+ case 'V':
+ /* Print configuration to stdout and exit */
+ printf("%s\n", TFTPD_CONFIG_STR);
+ exit(0);
+ break;
+ default:
+ syslog(LOG_ERR, "Unknown option: '%c'", optopt);
+ break;
+ }
+
+ dirs = xmalloc((argc - optind + 1) * sizeof(char *));
+ for (ndirs = 0; optind != argc; optind++)
+ dirs[ndirs++] = argv[optind];
+
+ dirs[ndirs] = NULL;
+
+ if (secure) {
+ if (ndirs == 0) {
+ syslog(LOG_ERR, "no -s directory");
+ exit(EX_USAGE);
+ }
+ if (ndirs > 1) {
+ syslog(LOG_ERR, "too many -s directories");
+ exit(EX_USAGE);
+ }
+ if (chdir(dirs[0])) {
+ syslog(LOG_ERR, "%s: %m", dirs[0]);
+ exit(EX_NOINPUT);
+ }
}
- dirs = xmalloc((argc-optind+1)*sizeof(char *));
- for ( ndirs = 0 ; optind != argc ; optind++ )
- dirs[ndirs++] = argv[optind];
-
- dirs[ndirs] = NULL;
-
- if (secure) {
- if (ndirs == 0) {
- syslog(LOG_ERR, "no -s directory");
- exit(EX_USAGE);
- }
- if (ndirs > 1) {
- syslog(LOG_ERR, "too many -s directories");
- exit(EX_USAGE);
- }
- if (chdir(dirs[0])) {
- syslog(LOG_ERR, "%s: %m", dirs[0]);
- exit(EX_NOINPUT);
+ pw = getpwnam(user);
+ if (!pw) {
+ syslog(LOG_ERR, "no user %s: %m", user);
+ exit(EX_NOUSER);
}
- }
-
- pw = getpwnam(user);
- if (!pw) {
- syslog(LOG_ERR, "no user %s: %m", user);
- exit(EX_NOUSER);
- }
-
- if ( spec_umask || !unixperms )
- umask(my_umask);
-
- /* Note: on Cygwin, select() on a nonblocking socket becomes
- a nonblocking select. */
+
+ if (spec_umask || !unixperms)
+ umask(my_umask);
+
+ /* Note: on Cygwin, select() on a nonblocking socket becomes
+ a nonblocking select. */
#ifndef __CYGWIN__
- set_socket_nonblock(fd, 1);
+ set_socket_nonblock(fd, 1);
#endif
#ifdef WITH_REGEX
- if ( rewrite_file )
- rewrite_rules = read_remap_rules(rewrite_file);
+ if (rewrite_file)
+ rewrite_rules = read_remap_rules(rewrite_file);
#endif
- /* If we're running standalone, set up the input port */
- if ( standalone ) {
- fd = socket(PF_INET, SOCK_DGRAM, 0);
-
- memset(&bindaddr, 0, sizeof bindaddr);
- bindaddr.sin_family = AF_INET;
- bindaddr.sin_addr.s_addr = INADDR_ANY;
- bindaddr.sin_port = htons(IPPORT_TFTP);
-
- if ( address ) {
- char *portptr, *eportptr;
- struct hostent *hostent;
- struct servent *servent;
- unsigned long port;
-
- address = tfstrdup(address);
- portptr = strrchr(address, ':');
- if ( portptr )
- *portptr++ = '\0';
-
- if ( *address ) {
- hostent = gethostbyname(address);
- if ( !hostent || hostent->h_addrtype != AF_INET ) {
- syslog(LOG_ERR, "cannot resolve local bind address: %s", address);
- exit(EX_NOINPUT);
- }
- memcpy(&bindaddr.sin_addr, hostent->h_addr, hostent->h_length);
- } else {
- /* Default to using INADDR_ANY */
- }
-
- if ( portptr && *portptr ) {
- servent = getservbyname(portptr, "udp");
- if ( servent ) {
- bindaddr.sin_port = servent->s_port;
- } else if ( (port = strtoul(portptr, &eportptr, 0)) && !*eportptr ) {
- bindaddr.sin_port = htons(port);
- } else if ( !strcmp(portptr, "tftp") ) {
- /* It's TFTP, we're OK */
- } else {
- syslog(LOG_ERR, "cannot resolve local bind port: %s", portptr);
- exit(EX_NOINPUT);
- }
- }
- }
-
- if (bind(fd, (struct sockaddr *)&bindaddr, sizeof bindaddr) < 0) {
- syslog(LOG_ERR, "cannot bind to local socket: %m");
- exit(EX_OSERR);
- }
-
- /* Daemonize this process */
- /* Note: when running in secure mode (-s), we must not chroot, since
- we are already in the proper directory. */
- if (!nodaemon && daemon(secure, 0) < 0) {
- syslog(LOG_ERR, "cannot daemonize: %m");
- exit(EX_OSERR);
+ /* If we're running standalone, set up the input port */
+ if (standalone) {
+ fd = socket(PF_INET, SOCK_DGRAM, 0);
+
+ memset(&bindaddr, 0, sizeof bindaddr);
+ bindaddr.sin_family = AF_INET;
+ bindaddr.sin_addr.s_addr = INADDR_ANY;
+ bindaddr.sin_port = htons(IPPORT_TFTP);
+
+ if (address) {
+ char *portptr, *eportptr;
+ struct hostent *hostent;
+ struct servent *servent;
+ unsigned long port;
+
+ address = tfstrdup(address);
+ portptr = strrchr(address, ':');
+ if (portptr)
+ *portptr++ = '\0';
+
+ if (*address) {
+ hostent = gethostbyname(address);
+ if (!hostent || hostent->h_addrtype != AF_INET) {
+ syslog(LOG_ERR,
+ "cannot resolve local bind address: %s",
+ address);
+ exit(EX_NOINPUT);
+ }
+ memcpy(&bindaddr.sin_addr, hostent->h_addr,
+ hostent->h_length);
+ } else {
+ /* Default to using INADDR_ANY */
+ }
+
+ if (portptr && *portptr) {
+ servent = getservbyname(portptr, "udp");
+ if (servent) {
+ bindaddr.sin_port = servent->s_port;
+ } else if ((port = strtoul(portptr, &eportptr, 0))
+ && !*eportptr) {
+ bindaddr.sin_port = htons(port);
+ } else if (!strcmp(portptr, "tftp")) {
+ /* It's TFTP, we're OK */
+ } else {
+ syslog(LOG_ERR, "cannot resolve local bind port: %s",
+ portptr);
+ exit(EX_NOINPUT);
+ }
+ }
+ }
+
+ if (bind(fd, (struct sockaddr *)&bindaddr, sizeof bindaddr) < 0) {
+ syslog(LOG_ERR, "cannot bind to local socket: %m");
+ exit(EX_OSERR);
+ }
+
+ /* Daemonize this process */
+ /* Note: when running in secure mode (-s), we must not chroot, since
+ we are already in the proper directory. */
+ if (!nodaemon && daemon(secure, 0) < 0) {
+ syslog(LOG_ERR, "cannot daemonize: %m");
+ exit(EX_OSERR);
+ }
+ } else {
+ /* 0 is our socket descriptor */
+ close(1);
+ close(2);
}
- } else {
- /* 0 is our socket descriptor */
- close(1); close(2);
- }
- /* Disable path MTU discovery */
- pmtu_discovery_off(0);
+ /* Disable path MTU discovery */
+ pmtu_discovery_off(0);
- /* This means we don't want to wait() for children */
+ /* This means we don't want to wait() for children */
#ifdef SA_NOCLDWAIT
- set_signal(SIGCHLD, SIG_IGN, SA_NOCLDSTOP|SA_NOCLDWAIT);
+ set_signal(SIGCHLD, SIG_IGN, SA_NOCLDSTOP | SA_NOCLDWAIT);
#else
- set_signal(SIGCHLD, SIG_IGN, SA_NOCLDSTOP);
+ set_signal(SIGCHLD, SIG_IGN, SA_NOCLDSTOP);
#endif
- /* Take SIGHUP and use it to set a variable. This
- is polled synchronously to make sure we don't
- lose packets as a result. */
- set_signal(SIGHUP, handle_sighup, 0);
-
- while ( 1 ) {
- fd_set readset;
- struct timeval tv_waittime;
- int rv;
-
- if ( caught_sighup ) {
- caught_sighup = 0;
- if ( standalone ) {
+ /* Take SIGHUP and use it to set a variable. This
+ is polled synchronously to make sure we don't
+ lose packets as a result. */
+ set_signal(SIGHUP, handle_sighup, 0);
+
+ while (1) {
+ fd_set readset;
+ struct timeval tv_waittime;
+ int rv;
+
+ if (caught_sighup) {
+ caught_sighup = 0;
+ if (standalone) {
#ifdef WITH_REGEX
- if ( rewrite_file ) {
- freerules(rewrite_rules);
- rewrite_rules = read_remap_rules(rewrite_file);
- }
+ if (rewrite_file) {
+ freerules(rewrite_rules);
+ rewrite_rules = read_remap_rules(rewrite_file);
+ }
#endif
- } else {
- /* Return to inetd for respawn */
- exit(0);
- }
- }
-
- FD_ZERO(&readset);
- FD_SET(fd, &readset);
- tv_waittime.tv_sec = waittime;
- tv_waittime.tv_usec = 0;
-
+ } else {
+ /* Return to inetd for respawn */
+ exit(0);
+ }
+ }
+
+ FD_ZERO(&readset);
+ FD_SET(fd, &readset);
+ tv_waittime.tv_sec = waittime;
+ tv_waittime.tv_usec = 0;
+
#ifdef __CYGWIN__
- /* On Cygwin, select() on a nonblocking socket returns immediately,
- with a rv of 0! */
- set_socket_nonblock(fd, 0);
-#endif
-
- /* Never time out if we're in standalone mode */
- rv = select(fd+1, &readset, NULL, NULL, standalone ? NULL : &tv_waittime);
- if ( rv == -1 && errno == EINTR )
- continue; /* Signal caught, reloop */
- if ( rv == -1 ) {
- syslog(LOG_ERR, "select loop: %m");
- exit(EX_IOERR);
- } else if ( rv == 0 ) {
- exit(0); /* Timeout, return to inetd */
- }
+ /* On Cygwin, select() on a nonblocking socket returns immediately,
+ with a rv of 0! */
+ set_socket_nonblock(fd, 0);
+#endif
+ /* Never time out if we're in standalone mode */
+ rv = select(fd + 1, &readset, NULL, NULL,
+ standalone ? NULL : &tv_waittime);
+ if (rv == -1 && errno == EINTR)
+ continue; /* Signal caught, reloop */
+ if (rv == -1) {
+ syslog(LOG_ERR, "select loop: %m");
+ exit(EX_IOERR);
+ } else if (rv == 0) {
+ exit(0); /* Timeout, return to inetd */
+ }
#ifdef __CYGWIN__
- set_socket_nonblock(fd, 1);
-#endif
-
- fromlen = sizeof (from);
- n = myrecvfrom(fd, buf, sizeof (buf), 0,
- (struct sockaddr *)&from, &fromlen,
- &myaddr);
-
- if ( n < 0 ) {
- if ( E_WOULD_BLOCK(errno) || errno == EINTR ) {
- continue; /* Again, from the top */
- } else {
- syslog(LOG_ERR, "recvfrom: %m");
- exit(EX_IOERR);
- }
- }
+ set_socket_nonblock(fd, 1);
+#endif
- if ( from.sin_family != AF_INET ) {
- syslog(LOG_ERR, "received address was not AF_INET, please check your inetd config");
- exit(EX_PROTOCOL);
+ fromlen = sizeof(from);
+ n = myrecvfrom(fd, buf, sizeof(buf), 0,
+ (struct sockaddr *)&from, &fromlen, &myaddr);
+
+ if (n < 0) {
+ if (E_WOULD_BLOCK(errno) || errno == EINTR) {
+ continue; /* Again, from the top */
+ } else {
+ syslog(LOG_ERR, "recvfrom: %m");
+ exit(EX_IOERR);
+ }
+ }
+
+ if (from.sin_family != AF_INET) {
+ syslog(LOG_ERR,
+ "received address was not AF_INET, please check your inetd config");
+ exit(EX_PROTOCOL);
+ }
+
+ if (standalone && myaddr.sin_addr.s_addr == INADDR_ANY) {
+ /* myrecvfrom() didn't capture the source address; but we might
+ have bound to a specific address, if so we should use it */
+ memcpy(&myaddr.sin_addr, &bindaddr.sin_addr,
+ sizeof bindaddr.sin_addr);
+ }
+
+ /*
+ * Now that we have read the request packet from the UDP
+ * socket, we fork and go back to listening to the socket.
+ */
+ pid = fork();
+ if (pid < 0) {
+ syslog(LOG_ERR, "fork: %m");
+ exit(EX_OSERR); /* Return to inetd, just in case */
+ } else if (pid == 0)
+ break; /* Child exit, parent loop */
}
- if ( standalone && myaddr.sin_addr.s_addr == INADDR_ANY ) {
- /* myrecvfrom() didn't capture the source address; but we might
- have bound to a specific address, if so we should use it */
- memcpy(&myaddr.sin_addr, &bindaddr.sin_addr, sizeof bindaddr.sin_addr);
- }
+ /* Child process: handle the actual request here */
+
+ /* Ignore SIGHUP */
+ set_signal(SIGHUP, SIG_IGN, 0);
- /*
- * Now that we have read the request packet from the UDP
- * socket, we fork and go back to listening to the socket.
- */
- pid = fork();
- if (pid < 0) {
- syslog(LOG_ERR, "fork: %m");
- exit(EX_OSERR); /* Return to inetd, just in case */
- } else if ( pid == 0 )
- break; /* Child exit, parent loop */
- }
-
- /* Child process: handle the actual request here */
-
- /* Ignore SIGHUP */
- set_signal(SIGHUP, SIG_IGN, 0);
-
#ifdef HAVE_TCPWRAPPERS
- /* Verify if this was a legal request for us. This has to be
- done before the chroot, while /etc is still accessible. */
- request_init(&wrap_request,
- RQ_DAEMON, __progname,
- RQ_FILE, fd,
- RQ_CLIENT_SIN, &from,
- RQ_SERVER_SIN, &myaddr,
- 0);
- sock_methods(&wrap_request);
- if ( hosts_access(&wrap_request) == 0 ) {
- if ( deny_severity != -1 )
- syslog(deny_severity, "connection refused from %s",
- inet_ntoa(from.sin_addr));
- exit(EX_NOPERM); /* Access denied */
- } else if ( allow_severity != -1 ) {
- syslog(allow_severity, "connect from %s",
- inet_ntoa(from.sin_addr));
- }
+ /* Verify if this was a legal request for us. This has to be
+ done before the chroot, while /etc is still accessible. */
+ request_init(&wrap_request,
+ RQ_DAEMON, __progname,
+ RQ_FILE, fd,
+ RQ_CLIENT_SIN, &from, RQ_SERVER_SIN, &myaddr, 0);
+ sock_methods(&wrap_request);
+ if (hosts_access(&wrap_request) == 0) {
+ if (deny_severity != -1)
+ syslog(deny_severity, "connection refused from %s",
+ inet_ntoa(from.sin_addr));
+ exit(EX_NOPERM); /* Access denied */
+ } else if (allow_severity != -1) {
+ syslog(allow_severity, "connect from %s",
+ inet_ntoa(from.sin_addr));
+ }
#endif
- /* Close file descriptors we don't need */
- close(fd);
-
- /* Get a socket. This has to be done before the chroot(), since
- some systems require access to /dev to create a socket. */
-
- peer = socket(AF_INET, SOCK_DGRAM, 0);
- if (peer < 0) {
- syslog(LOG_ERR, "socket: %m");
- exit(EX_IOERR);
- }
-
- /* Set up the supplementary group access list if possible */
- /* /etc/group still need to be accessible at this point */
+ /* Close file descriptors we don't need */
+ close(fd);
+
+ /* Get a socket. This has to be done before the chroot(), since
+ some systems require access to /dev to create a socket. */
+
+ peer = socket(AF_INET, SOCK_DGRAM, 0);
+ if (peer < 0) {
+ syslog(LOG_ERR, "socket: %m");
+ exit(EX_IOERR);
+ }
+
+ /* Set up the supplementary group access list if possible */
+ /* /etc/group still need to be accessible at this point */
#ifdef HAVE_INITGROUPS
- setrv = initgroups(user, pw->pw_gid);
- if ( setrv ) {
- syslog(LOG_ERR, "cannot set groups for user %s", user);
- exit(EX_OSERR);
- }
+ setrv = initgroups(user, pw->pw_gid);
+ if (setrv) {
+ syslog(LOG_ERR, "cannot set groups for user %s", user);
+ exit(EX_OSERR);
+ }
#else
#ifdef HAVE_SETGROUPS
- if ( setgroups(0, NULL) ) {
- syslog(LOG_ERR, "cannot clear group list");
- }
+ if (setgroups(0, NULL)) {
+ syslog(LOG_ERR, "cannot clear group list");
+ }
#endif
#endif
- /* Chroot and drop privileges */
- if (secure) {
- if (chroot(".")) {
- syslog(LOG_ERR, "chroot: %m");
- exit(EX_OSERR);
- }
+ /* Chroot and drop privileges */
+ if (secure) {
+ if (chroot(".")) {
+ syslog(LOG_ERR, "chroot: %m");
+ exit(EX_OSERR);
+ }
#ifdef __CYGWIN__
- chdir("/"); /* Cygwin chroot() bug workaround */
+ chdir("/"); /* Cygwin chroot() bug workaround */
#endif
- }
-
+ }
#ifdef HAVE_SETREGID
- setrv = setregid(pw->pw_gid, pw->pw_gid);
+ setrv = setregid(pw->pw_gid, pw->pw_gid);
#else
- setrv = setegid(pw->pw_gid) || setgid(pw->pw_gid);
+ setrv = setegid(pw->pw_gid) || setgid(pw->pw_gid);
#endif
-
+
#ifdef HAVE_SETREUID
- setrv = setrv || setreuid(pw->pw_uid, pw->pw_uid);
+ setrv = setrv || setreuid(pw->pw_uid, pw->pw_uid);
#else
- /* Important: setuid() must come first */
- setrv = setrv || setuid(pw->pw_uid) ||
- (geteuid() != pw->pw_uid && seteuid(pw->pw_uid));
+ /* Important: setuid() must come first */
+ setrv = setrv || setuid(pw->pw_uid) ||
+ (geteuid() != pw->pw_uid && seteuid(pw->pw_uid));
#endif
-
- if ( setrv ) {
- syslog(LOG_ERR, "cannot drop privileges: %m");
- exit(EX_OSERR);
- }
-
- /* Other basic setup */
- from.sin_family = AF_INET;
-
- /* Process the request... */
- if (pick_port_bind(peer, &myaddr, portrange_from, portrange_to) < 0) {
- syslog(LOG_ERR, "bind: %m");
- exit(EX_IOERR);
- }
-
- if (connect(peer, (struct sockaddr *)&from, sizeof from) < 0) {
- syslog(LOG_ERR, "connect: %m");
- exit(EX_IOERR);
- }
-
- /* Disable path MTU discovery */
- pmtu_discovery_off(0);
-
- tp = (struct tftphdr *)buf;
- tp_opcode = ntohs(tp->th_opcode);
- if (tp_opcode == RRQ || tp_opcode == WRQ)
- tftp(tp, n);
- exit(0);
+
+ if (setrv) {
+ syslog(LOG_ERR, "cannot drop privileges: %m");
+ exit(EX_OSERR);
+ }
+
+ /* Other basic setup */
+ from.sin_family = AF_INET;
+
+ /* Process the request... */
+ if (pick_port_bind(peer, &myaddr, portrange_from, portrange_to) < 0) {
+ syslog(LOG_ERR, "bind: %m");
+ exit(EX_IOERR);
+ }
+
+ if (connect(peer, (struct sockaddr *)&from, sizeof from) < 0) {
+ syslog(LOG_ERR, "connect: %m");
+ exit(EX_IOERR);
+ }
+
+ /* Disable path MTU discovery */
+ pmtu_discovery_off(0);
+
+ tp = (struct tftphdr *)buf;
+ tp_opcode = ntohs(tp->th_opcode);
+ if (tp_opcode == RRQ || tp_opcode == WRQ)
+ tftp(tp, n);
+ exit(0);
}
-char *rewrite_access(char *, int, const char **);
-int validate_access(char *, int, struct formats *, const char **);
-void tftp_sendfile(struct formats *, struct tftphdr *, int);
-void tftp_recvfile(struct formats *, struct tftphdr *, int);
+char *rewrite_access(char *, int, const char **);
+int validate_access(char *, int, struct formats *, const char **);
+void tftp_sendfile(struct formats *, struct tftphdr *, int);
+void tftp_recvfile(struct formats *, struct tftphdr *, int);
struct formats {
- const char *f_mode;
- char *(*f_rewrite)(char *, int, const char **);
- int (*f_validate)(char *, int, struct formats *, const char **);
- void (*f_send)(struct formats *, struct tftphdr *, int);
- void (*f_recv)(struct formats *, struct tftphdr *, int);
- int f_convert;
+ const char *f_mode;
+ char *(*f_rewrite) (char *, int, const char **);
+ int (*f_validate) (char *, int, struct formats *, const char **);
+ void (*f_send) (struct formats *, struct tftphdr *, int);
+ void (*f_recv) (struct formats *, struct tftphdr *, int);
+ int f_convert;
} formats[] = {
- { "netascii", rewrite_access, validate_access, tftp_sendfile, tftp_recvfile, 1 },
- { "octet", rewrite_access, validate_access, tftp_sendfile, tftp_recvfile, 0 },
- { NULL, NULL, NULL, NULL, NULL, 0 }
+ {
+ "netascii", rewrite_access, validate_access, tftp_sendfile,
+ tftp_recvfile, 1}, {
+ "octet", rewrite_access, validate_access, tftp_sendfile,
+ tftp_recvfile, 0}, {
+ NULL, NULL, NULL, NULL, NULL, 0}
};
/*
* Handle initial connection protocol.
*/
-int
-tftp(struct tftphdr *tp, int size)
+int tftp(struct tftphdr *tp, int size)
{
- char *cp, *end;
- int argn, ecode;
- struct formats *pf = NULL;
- char *origfilename;
- char *filename, *mode = NULL;
- const char *errmsgptr;
- u_short tp_opcode = ntohs(tp->th_opcode);
-
- char *val = NULL, *opt = NULL;
- char *ap = ackbuf + 2;
-
- ((struct tftphdr *)ackbuf)->th_opcode = htons(OACK);
-
- origfilename = cp = (char *) &(tp->th_stuff);
- argn = 0;
-
- end = (char *)tp + size;
-
- while ( cp < end && *cp ) {
- do {
- cp++;
- } while (cp < end && *cp);
-
- if ( *cp ) {
- nak(EBADOP, "Request not null-terminated");
- exit(0);
+ char *cp, *end;
+ int argn, ecode;
+ struct formats *pf = NULL;
+ char *origfilename;
+ char *filename, *mode = NULL;
+ const char *errmsgptr;
+ u_short tp_opcode = ntohs(tp->th_opcode);
+
+ char *val = NULL, *opt = NULL;
+ char *ap = ackbuf + 2;
+
+ ((struct tftphdr *)ackbuf)->th_opcode = htons(OACK);
+
+ origfilename = cp = (char *)&(tp->th_stuff);
+ argn = 0;
+
+ end = (char *)tp + size;
+
+ while (cp < end && *cp) {
+ do {
+ cp++;
+ } while (cp < end && *cp);
+
+ if (*cp) {
+ nak(EBADOP, "Request not null-terminated");
+ exit(0);
+ }
+
+ argn++;
+ if (argn == 1) {
+ mode = ++cp;
+ } else if (argn == 2) {
+ for (cp = mode; *cp; cp++)
+ *cp = tolower(*cp);
+ for (pf = formats; pf->f_mode; pf++) {
+ if (!strcmp(pf->f_mode, mode))
+ break;
+ }
+ if (!pf->f_mode) {
+ nak(EBADOP, "Unknown mode");
+ exit(0);
+ }
+ if (!(filename =
+ (*pf->f_rewrite) (origfilename, tp_opcode,
+ &errmsgptr))) {
+ nak(EACCESS, errmsgptr); /* File denied by mapping rule */
+ exit(0);
+ }
+ if (verbosity >= 1) {
+ if (filename == origfilename
+ || !strcmp(filename, origfilename))
+ syslog(LOG_NOTICE, "%s from %s filename %s\n",
+ tp_opcode == WRQ ? "WRQ" : "RRQ",
+ inet_ntoa(from.sin_addr), filename);
+ else
+ syslog(LOG_NOTICE,
+ "%s from %s filename %s remapped to %s\n",
+ tp_opcode == WRQ ? "WRQ" : "RRQ",
+ inet_ntoa(from.sin_addr), origfilename,
+ filename);
+ }
+ ecode =
+ (*pf->f_validate) (filename, tp_opcode, pf, &errmsgptr);
+ if (ecode) {
+ nak(ecode, errmsgptr);
+ exit(0);
+ }
+ opt = ++cp;
+ } else if (argn & 1) {
+ val = ++cp;
+ } else {
+ do_opt(opt, val, &ap);
+ opt = ++cp;
+ }
+ }
+
+ if (!pf) {
+ nak(EBADOP, "Missing mode");
+ exit(0);
}
-
- argn++;
- if (argn == 1) {
- mode = ++cp;
- } else if (argn == 2) {
- for (cp = mode; *cp; cp++)
- *cp = tolower(*cp);
- for (pf = formats; pf->f_mode; pf++) {
- if (!strcmp(pf->f_mode, mode))
- break;
- }
- if (!pf->f_mode) {
- nak(EBADOP, "Unknown mode");
- exit(0);
- }
- if ( !(filename =
- (*pf->f_rewrite)(origfilename, tp_opcode, &errmsgptr)) ) {
- nak(EACCESS, errmsgptr); /* File denied by mapping rule */
- exit(0);
- }
- if ( verbosity >= 1 ) {
- if ( filename == origfilename || !strcmp(filename, origfilename) )
- syslog(LOG_NOTICE, "%s from %s filename %s\n",
- tp_opcode == WRQ ? "WRQ" : "RRQ",
- inet_ntoa(from.sin_addr), filename);
- else
- syslog(LOG_NOTICE, "%s from %s filename %s remapped to %s\n",
- tp_opcode == WRQ ? "WRQ" : "RRQ",
- inet_ntoa(from.sin_addr), origfilename, filename);
- }
- ecode = (*pf->f_validate)(filename, tp_opcode, pf, &errmsgptr);
- if (ecode) {
- nak(ecode, errmsgptr);
- exit(0);
- }
- opt = ++cp;
- } else if ( argn & 1 ) {
- val = ++cp;
+
+ if (ap != (ackbuf + 2)) {
+ if (tp_opcode == WRQ)
+ (*pf->f_recv) (pf, (struct tftphdr *)ackbuf, ap - ackbuf);
+ else
+ (*pf->f_send) (pf, (struct tftphdr *)ackbuf, ap - ackbuf);
} else {
- do_opt(opt, val, &ap);
- opt = ++cp;
+ if (tp_opcode == WRQ)
+ (*pf->f_recv) (pf, NULL, 0);
+ else
+ (*pf->f_send) (pf, NULL, 0);
}
- }
-
- if (!pf) {
- nak(EBADOP, "Missing mode");
- exit(0);
- }
-
- if ( ap != (ackbuf+2) ) {
- if ( tp_opcode == WRQ )
- (*pf->f_recv)(pf, (struct tftphdr *)ackbuf, ap-ackbuf);
- else
- (*pf->f_send)(pf, (struct tftphdr *)ackbuf, ap-ackbuf);
- } else {
- if (tp_opcode == WRQ)
- (*pf->f_recv)(pf, NULL, 0);
- else
- (*pf->f_send)(pf, NULL, 0);
- }
- exit(0); /* Request completed */
+ exit(0); /* Request completed */
}
static int blksize_set;
@@ -838,66 +830,64 @@ static int blksize_set;
/*
* Set a non-standard block size (c.f. RFC2348)
*/
-int
-set_blksize(char *val, char **ret)
+int set_blksize(char *val, char **ret)
{
- static char b_ret[6];
- unsigned int sz;
- char *vend;
-
- sz = (unsigned int)strtoul(val, &vend, 10);
-
- if ( blksize_set || *vend )
- return 0;
-
- if (sz < 8)
- return(0);
- else if (sz > max_blksize)
- sz = max_blksize;
-
- segsize = sz;
- sprintf(*ret = b_ret, "%u", sz);
-
- blksize_set = 1;
-
- return(1);
+ static char b_ret[6];
+ unsigned int sz;
+ char *vend;
+
+ sz = (unsigned int)strtoul(val, &vend, 10);
+
+ if (blksize_set || *vend)
+ return 0;
+
+ if (sz < 8)
+ return (0);
+ else if (sz > max_blksize)
+ sz = max_blksize;
+
+ segsize = sz;
+ sprintf(*ret = b_ret, "%u", sz);
+
+ blksize_set = 1;
+
+ return (1);
}
/*
* Set a power-of-two block size (nonstandard)
*/
-int
-set_blksize2(char *val, char **ret)
+int set_blksize2(char *val, char **ret)
{
- static char b_ret[6];
- unsigned int sz;
- char *vend;
-
- sz = (unsigned int)strtoul(val, &vend, 10);
-
- if ( blksize_set || *vend )
- return 0;
-
- if (sz < 8)
- return(0);
- else if (sz > max_blksize)
- sz = max_blksize;
-
- /* Convert to a power of two */
- if ( sz & (sz-1) ) {
- unsigned int sz1 = 1;
- /* Not a power of two - need to convert */
- while ( sz >>= 1 )
- sz1 <<= 1;
- sz = sz1;
- }
-
- segsize = sz;
- sprintf(*ret = b_ret, "%u", sz);
-
- blksize_set = 1;
-
- return(1);
+ static char b_ret[6];
+ unsigned int sz;
+ char *vend;
+
+ sz = (unsigned int)strtoul(val, &vend, 10);
+
+ if (blksize_set || *vend)
+ return 0;
+
+ if (sz < 8)
+ return (0);
+ else if (sz > max_blksize)
+ sz = max_blksize;
+
+ /* Convert to a power of two */
+ if (sz & (sz - 1)) {
+ unsigned int sz1 = 1;
+ /* Not a power of two - need to convert */
+ while (sz >>= 1)
+ sz1 <<= 1;
+ sz = sz1;
+ }
+
+ segsize = sz;
+ sprintf(*ret = b_ret, "%u", sz);
+
+ blksize_set = 1;
+
+ return (1);
}
/*
@@ -905,23 +895,22 @@ set_blksize2(char *val, char **ret)
* For netascii mode, we don't know the size ahead of time;
* so reject the option.
*/
-int
-set_tsize(char *val, char **ret)
+int set_tsize(char *val, char **ret)
{
- static char b_ret[sizeof(uintmax_t)*CHAR_BIT/3+2];
- uintmax_t sz;
- char *vend;
-
- sz = strtoumax(val, &vend, 10);
-
- if ( !tsize_ok || *vend )
- return 0;
-
- if (sz == 0)
- sz = (uintmax_t)tsize;
-
- sprintf(*ret = b_ret, "%"PRIuMAX, sz);
- return(1);
+ static char b_ret[sizeof(uintmax_t) * CHAR_BIT / 3 + 2];
+ uintmax_t sz;
+ char *vend;
+
+ sz = strtoumax(val, &vend, 10);
+
+ if (!tsize_ok || *vend)
+ return 0;
+
+ if (sz == 0)
+ sz = (uintmax_t) tsize;
+
+ sprintf(*ret = b_ret, "%" PRIuMAX, sz);
+ return (1);
}
/*
@@ -929,76 +918,74 @@ set_tsize(char *val, char **ret)
* to be the (default) retransmission timeout, but being an
* integer in seconds it seems a bit limited.
*/
-int
-set_timeout(char *val, char **ret)
+int set_timeout(char *val, char **ret)
{
- static char b_ret[4];
- unsigned long to;
- char *vend;
-
- to = strtoul(val, &vend, 10);
-
- if ( to < 1 || to > 255 || *vend )
- return 0;
-
- rexmtval = timeout = to*1000000UL;
- maxtimeout = rexmtval*TIMEOUT_LIMIT;
-
- sprintf(*ret = b_ret, "%lu", to);
- return(1);
+ static char b_ret[4];
+ unsigned long to;
+ char *vend;
+
+ to = strtoul(val, &vend, 10);
+
+ if (to < 1 || to > 255 || *vend)
+ return 0;
+
+ rexmtval = timeout = to * 1000000UL;
+ maxtimeout = rexmtval * TIMEOUT_LIMIT;
+
+ sprintf(*ret = b_ret, "%lu", to);
+ return (1);
}
/* Similar, but in microseconds. We allow down to 10 ms. */
-int
-set_utimeout(char *val, char **ret)
+int set_utimeout(char *val, char **ret)
{
- static char b_ret[4];
- unsigned long to;
- char *vend;
-
- to = strtoul(val, &vend, 10);
-
- if ( to < 10000UL || to > 255000000UL || *vend )
- return 0;
-
- rexmtval = timeout = to;
- maxtimeout = rexmtval*TIMEOUT_LIMIT;
-
- sprintf(*ret = b_ret, "%lu", to);
- return(1);
+ static char b_ret[4];
+ unsigned long to;
+ char *vend;
+
+ to = strtoul(val, &vend, 10);
+
+ if (to < 10000UL || to > 255000000UL || *vend)
+ return 0;
+
+ rexmtval = timeout = to;
+ maxtimeout = rexmtval * TIMEOUT_LIMIT;
+
+ sprintf(*ret = b_ret, "%lu", to);
+ return (1);
}
+
/*
* Parse RFC2347 style options
*/
-void
-do_opt(char *opt, char *val, char **ap)
+void do_opt(char *opt, char *val, char **ap)
{
- struct options *po;
- char *ret;
-
- /* Global option-parsing variables initialization */
- blksize_set = 0;
-
- if ( !*opt )
+ struct options *po;
+ char *ret;
+
+ /* Global option-parsing variables initialization */
+ blksize_set = 0;
+
+ if (!*opt)
+ return;
+
+ for (po = options; po->o_opt; po++)
+ if (!strcasecmp(po->o_opt, opt)) {
+ if (po->o_fnc(val, &ret)) {
+ if (*ap + strlen(opt) + strlen(ret) + 2 >=
+ ackbuf + sizeof(ackbuf)) {
+ nak(EOPTNEG, "Insufficient space for options");
+ exit(0);
+ }
+ *ap = strrchr(strcpy(strrchr(strcpy(*ap, opt), '\0') + 1,
+ ret), '\0') + 1;
+ } else {
+ nak(EOPTNEG, "Unsupported option(s) requested");
+ exit(0);
+ }
+ break;
+ }
return;
-
- for (po = options; po->o_opt; po++)
- if (!strcasecmp(po->o_opt, opt)) {
- if (po->o_fnc(val, &ret)) {
- if (*ap + strlen(opt) + strlen(ret) + 2 >=
- ackbuf + sizeof(ackbuf)) {
- nak(EOPTNEG, "Insufficient space for options");
- exit(0);
- }
- *ap = strrchr(strcpy(strrchr(strcpy(*ap, opt),'\0') + 1,
- ret),'\0') + 1;
- } else {
- nak(EOPTNEG, "Unsupported option(s) requested");
- exit(0);
- }
- break;
- }
- return;
}
#ifdef WITH_REGEX
@@ -1010,52 +997,50 @@ do_opt(char *opt, char *val, char **ap)
*
* Return -1 on failure.
*/
-int
-rewrite_macros(char macro, char *output);
+int rewrite_macros(char macro, char *output);
-int
-rewrite_macros(char macro, char *output)
+int rewrite_macros(char macro, char *output)
{
- char *p;
-
- switch (macro) {
- case 'i':
- p = inet_ntoa(from.sin_addr);
- if ( output )
- strcpy(output, p);
- return strlen(p);
-
- case 'x':
- if ( output )
- sprintf(output, "%08lX", (unsigned long)ntohl(from.sin_addr.s_addr));
- return 8;
-
- default:
- return -1;
- }
+ char *p;
+
+ switch (macro) {
+ case 'i':
+ p = inet_ntoa(from.sin_addr);
+ if (output)
+ strcpy(output, p);
+ return strlen(p);
+
+ case 'x':
+ if (output)
+ sprintf(output, "%08lX",
+ (unsigned long)ntohl(from.sin_addr.s_addr));
+ return 8;
+
+ default:
+ return -1;
+ }
}
/*
* Modify the filename, if applicable. If it returns NULL, deny the access.
*/
-char *
-rewrite_access(char *filename, int mode, const char **msg)
+char *rewrite_access(char *filename, int mode, const char **msg)
{
- if ( rewrite_rules ) {
- char *newname = rewrite_string(filename, rewrite_rules, mode != RRQ,
- rewrite_macros, msg);
- filename = newname;
- }
- return filename;
+ if (rewrite_rules) {
+ char *newname =
+ rewrite_string(filename, rewrite_rules, mode != RRQ,
+ rewrite_macros, msg);
+ filename = newname;
+ }
+ return filename;
}
#else
-char *
-rewrite_access(char *filename, int mode, const char **msg)
+char *rewrite_access(char *filename, int mode, const char **msg)
{
- (void)mode; /* Avoid warning */
- (void)msg;
- return filename;
+ (void)mode; /* Avoid warning */
+ (void)msg;
+ return filename;
}
#endif
@@ -1073,316 +1058,313 @@ FILE *file;
*/
int
validate_access(char *filename, int mode,
- struct formats *pf, const char **errmsg)
+ struct formats *pf, const char **errmsg)
{
- struct stat stbuf;
- int i, len;
- int fd, wmode, rmode;
- char *cp;
- const char **dirp;
- char stdio_mode[3];
-
- tsize_ok = 0;
- *errmsg = NULL;
-
- if (!secure) {
- if (*filename != '/') {
- *errmsg = "Only absolute filenames allowed";
- return (EACCESS);
+ struct stat stbuf;
+ int i, len;
+ int fd, wmode, rmode;
+ char *cp;
+ const char **dirp;
+ char stdio_mode[3];
+
+ tsize_ok = 0;
+ *errmsg = NULL;
+
+ if (!secure) {
+ if (*filename != '/') {
+ *errmsg = "Only absolute filenames allowed";
+ return (EACCESS);
+ }
+
+ /*
+ * prevent tricksters from getting around the directory
+ * restrictions
+ */
+ len = strlen(filename);
+ for (i = 1; i < len - 3; i++) {
+ cp = filename + i;
+ if (*cp == '.' && memcmp(cp - 1, "/../", 4) == 0) {
+ *errmsg = "Reverse path not allowed";
+ return (EACCESS);
+ }
+ }
+
+ for (dirp = dirs; *dirp; dirp++)
+ if (strncmp(filename, *dirp, strlen(*dirp)) == 0)
+ break;
+ if (*dirp == 0 && dirp != dirs) {
+ *errmsg = "Forbidden directory";
+ return (EACCESS);
+ }
}
/*
- * prevent tricksters from getting around the directory
- * restrictions
+ * We use different a different permissions scheme if `cancreate' is
+ * set.
*/
- len = strlen(filename);
- for ( i = 1 ; i < len-3 ; i++ ) {
- cp = filename + i;
- if ( *cp == '.' && memcmp(cp-1, "/../", 4) == 0 ) {
- *errmsg = "Reverse path not allowed";
- return(EACCESS);
- }
+ wmode = O_WRONLY |
+ (cancreate ? O_CREAT : 0) |
+ (unixperms ? O_TRUNC : 0) | (pf->f_convert ? O_TEXT : O_BINARY);
+ rmode = O_RDONLY | (pf->f_convert ? O_TEXT : O_BINARY);
+
+ fd = open(filename, mode == RRQ ? rmode : wmode, 0666);
+ if (fd < 0) {
+ switch (errno) {
+ case ENOENT:
+ case ENOTDIR:
+ return ENOTFOUND;
+ case ENOSPC:
+ return ENOSPACE;
+ case EEXIST:
+ return EEXISTS;
+ default:
+ return errno + 100;
+ }
}
- for (dirp = dirs; *dirp; dirp++)
- if (strncmp(filename, *dirp, strlen(*dirp)) == 0)
- break;
- if (*dirp==0 && dirp!=dirs) {
- *errmsg = "Forbidden directory";
- return (EACCESS);
- }
- }
-
- /*
- * We use different a different permissions scheme if `cancreate' is
- * set.
- */
- wmode = O_WRONLY |
- (cancreate ? O_CREAT : 0) |
- (unixperms ? O_TRUNC : 0) |
- (pf->f_convert ? O_TEXT : O_BINARY);
- rmode = O_RDONLY |
- (pf->f_convert ? O_TEXT : O_BINARY);
-
- fd = open(filename, mode == RRQ ? rmode : wmode, 0666);
- if (fd < 0) {
- switch (errno) {
- case ENOENT:
- case ENOTDIR:
- return ENOTFOUND;
- case ENOSPC:
- return ENOSPACE;
- case EEXIST:
- return EEXISTS;
- default:
- return errno+100;
- }
- }
-
- if ( fstat(fd, &stbuf) < 0 )
- exit(EX_OSERR); /* This shouldn't happen */
+ if (fstat(fd, &stbuf) < 0)
+ exit(EX_OSERR); /* This shouldn't happen */
+
+ if (mode == RRQ) {
+ if (!unixperms && (stbuf.st_mode & (S_IREAD >> 6)) == 0) {
+ *errmsg = "File must have global read permissions";
+ return (EACCESS);
+ }
+ tsize = stbuf.st_size;
+ /* We don't know the tsize if conversion is needed */
+ tsize_ok = !pf->f_convert;
+ } else {
+ if (!unixperms) {
+ if ((stbuf.st_mode & (S_IWRITE >> 6)) == 0) {
+ *errmsg = "File must have global write permissions";
+ return (EACCESS);
+ }
- if (mode == RRQ) {
- if ( !unixperms && (stbuf.st_mode & (S_IREAD >> 6)) == 0 ) {
- *errmsg = "File must have global read permissions";
- return (EACCESS);
- }
- tsize = stbuf.st_size;
- /* We don't know the tsize if conversion is needed */
- tsize_ok = !pf->f_convert;
- } else {
- if ( !unixperms ) {
- if ( (stbuf.st_mode & (S_IWRITE >> 6)) == 0 ) {
- *errmsg = "File must have global write permissions";
- return (EACCESS);
- }
-
- /* We didn't get to truncate the file at open() time */
+ /* We didn't get to truncate the file at open() time */
#ifdef HAVE_FTRUNCATE
- if ( ftruncate(fd, (off_t)0) ) {
- *errmsg = "Cannot reset file size";
- return(EACCESS);
- }
+ if (ftruncate(fd, (off_t) 0)) {
+ *errmsg = "Cannot reset file size";
+ return (EACCESS);
+ }
#endif
+ }
+ tsize = 0;
+ tsize_ok = 1;
}
- tsize = 0;
- tsize_ok = 1;
- }
- stdio_mode[0] = (mode == RRQ) ? 'r':'w';
- stdio_mode[1] = (pf->f_convert) ? 't':'b';
- stdio_mode[2] = '\0';
+ stdio_mode[0] = (mode == RRQ) ? 'r' : 'w';
+ stdio_mode[1] = (pf->f_convert) ? 't' : 'b';
+ stdio_mode[2] = '\0';
- file = fdopen(fd, stdio_mode);
- if (file == NULL)
- exit(EX_OSERR); /* Internal error */
+ file = fdopen(fd, stdio_mode);
+ if (file == NULL)
+ exit(EX_OSERR); /* Internal error */
- return (0);
+ return (0);
}
/*
* Send the requested file.
*/
-void
-tftp_sendfile(struct formats *pf, struct tftphdr *oap, int oacklen)
+void tftp_sendfile(struct formats *pf, struct tftphdr *oap, int oacklen)
{
- struct tftphdr *dp;
- struct tftphdr *ap; /* ack packet */
- static u_short block = 1; /* Static to avoid longjmp funnies */
- u_short ap_opcode, ap_block;
- unsigned long r_timeout;
- int size, n;
-
- if (oap) {
- timeout = rexmtval;
- (void)sigsetjmp(timeoutbuf,1);
- oack:
- r_timeout = timeout;
- if (send(peer, oap, oacklen, 0) != oacklen) {
- syslog(LOG_WARNING, "tftpd: oack: %m\n");
- goto abort;
- }
- for ( ; ; ) {
- n = recv_time(peer, ackbuf, sizeof(ackbuf), 0, &r_timeout);
- if (n < 0) {
- syslog(LOG_WARNING, "tftpd: read: %m\n");
- goto abort;
- }
- ap = (struct tftphdr *)ackbuf;
- ap_opcode = ntohs((u_short)ap->th_opcode);
- ap_block = ntohs((u_short)ap->th_block);
-
- if (ap_opcode == ERROR) {
- syslog(LOG_WARNING, "tftp: client does not accept options\n");
- goto abort;
- }
- if (ap_opcode == ACK) {
- if (ap_block == 0)
- break;
- /* Resynchronize with the other side */
- (void)synchnet(peer);
- goto oack;
- }
- }
- }
-
- dp = r_init();
- do {
- size = readit(file, &dp, pf->f_convert);
- if (size < 0) {
- nak(errno + 100, NULL);
- goto abort;
- }
- dp->th_opcode = htons((u_short)DATA);
- dp->th_block = htons((u_short)block);
- timeout = rexmtval;
- (void) sigsetjmp(timeoutbuf,1);
-
- r_timeout = timeout;
- if (send(peer, dp, size + 4, 0) != size + 4) {
- syslog(LOG_WARNING, "tftpd: write: %m");
- goto abort;
- }
- read_ahead(file, pf->f_convert);
- for ( ; ; ) {
- n = recv_time(peer, ackbuf, sizeof (ackbuf), 0, &r_timeout);
- if (n < 0) {
- syslog(LOG_WARNING, "tftpd: read(ack): %m");
- goto abort;
- }
- ap = (struct tftphdr *)ackbuf;
- ap_opcode = ntohs((u_short)ap->th_opcode);
- ap_block = ntohs((u_short)ap->th_block);
-
- if (ap_opcode == ERROR)
- goto abort;
-
- if (ap_opcode == ACK) {
- if (ap_block == block) {
- break;
- }
- /* Re-synchronize with the other side */
- (void) synchnet(peer);
- /*
- * RFC1129/RFC1350: We MUST NOT re-send the DATA
- * packet in response to an invalid ACK. Doing so
- * would cause the Sorcerer's Apprentice bug.
- */
- }
-
+ struct tftphdr *dp;
+ struct tftphdr *ap; /* ack packet */
+ static u_short block = 1; /* Static to avoid longjmp funnies */
+ u_short ap_opcode, ap_block;
+ unsigned long r_timeout;
+ int size, n;
+
+ if (oap) {
+ timeout = rexmtval;
+ (void)sigsetjmp(timeoutbuf, 1);
+ oack:
+ r_timeout = timeout;
+ if (send(peer, oap, oacklen, 0) != oacklen) {
+ syslog(LOG_WARNING, "tftpd: oack: %m\n");
+ goto abort;
+ }
+ for (;;) {
+ n = recv_time(peer, ackbuf, sizeof(ackbuf), 0, &r_timeout);
+ if (n < 0) {
+ syslog(LOG_WARNING, "tftpd: read: %m\n");
+ goto abort;
+ }
+ ap = (struct tftphdr *)ackbuf;
+ ap_opcode = ntohs((u_short) ap->th_opcode);
+ ap_block = ntohs((u_short) ap->th_block);
+
+ if (ap_opcode == ERROR) {
+ syslog(LOG_WARNING,
+ "tftp: client does not accept options\n");
+ goto abort;
+ }
+ if (ap_opcode == ACK) {
+ if (ap_block == 0)
+ break;
+ /* Resynchronize with the other side */
+ (void)synchnet(peer);
+ goto oack;
+ }
+ }
}
- block++;
- } while (size == segsize);
- abort:
- (void) fclose(file);
+
+ dp = r_init();
+ do {
+ size = readit(file, &dp, pf->f_convert);
+ if (size < 0) {
+ nak(errno + 100, NULL);
+ goto abort;
+ }
+ dp->th_opcode = htons((u_short) DATA);
+ dp->th_block = htons((u_short) block);
+ timeout = rexmtval;
+ (void)sigsetjmp(timeoutbuf, 1);
+
+ r_timeout = timeout;
+ if (send(peer, dp, size + 4, 0) != size + 4) {
+ syslog(LOG_WARNING, "tftpd: write: %m");
+ goto abort;
+ }
+ read_ahead(file, pf->f_convert);
+ for (;;) {
+ n = recv_time(peer, ackbuf, sizeof(ackbuf), 0, &r_timeout);
+ if (n < 0) {
+ syslog(LOG_WARNING, "tftpd: read(ack): %m");
+ goto abort;
+ }
+ ap = (struct tftphdr *)ackbuf;
+ ap_opcode = ntohs((u_short) ap->th_opcode);
+ ap_block = ntohs((u_short) ap->th_block);
+
+ if (ap_opcode == ERROR)
+ goto abort;
+
+ if (ap_opcode == ACK) {
+ if (ap_block == block) {
+ break;
+ }
+ /* Re-synchronize with the other side */
+ (void)synchnet(peer);
+ /*
+ * RFC1129/RFC1350: We MUST NOT re-send the DATA
+ * packet in response to an invalid ACK. Doing so
+ * would cause the Sorcerer's Apprentice bug.
+ */
+ }
+
+ }
+ block++;
+ } while (size == segsize);
+ abort:
+ (void)fclose(file);
}
/* Bail out signal handler */
-void
-justquit(int sig)
+void justquit(int sig)
{
- (void)sig; /* Suppress unused warning */
- exit(0);
+ (void)sig; /* Suppress unused warning */
+ exit(0);
}
-
/*
* Receive a file.
*/
-void
-tftp_recvfile(struct formats *pf, struct tftphdr *oap, int oacklen)
+void tftp_recvfile(struct formats *pf, struct tftphdr *oap, int oacklen)
{
- struct tftphdr *dp;
- int n, size;
- /* These are "static" to avoid longjmp funnies */
- static struct tftphdr *ap; /* ack buffer */
- static u_short block = 0;
- static int acksize;
- u_short dp_opcode, dp_block;
- unsigned long r_timeout;
-
- dp = w_init();
- do {
- timeout = rexmtval;
-
- if (!block && oap) {
- ap = (struct tftphdr *)ackbuf;
- acksize = oacklen;
- } else {
- ap = (struct tftphdr *)ackbuf;
- ap->th_opcode = htons((u_short)ACK);
- ap->th_block = htons((u_short)block);
- acksize = 4;
- }
- block++;
- (void) sigsetjmp(timeoutbuf,1);
- send_ack:
- r_timeout = timeout;
- if (send(peer, ackbuf, acksize, 0) != acksize) {
- syslog(LOG_WARNING, "tftpd: write(ack): %m");
- goto abort;
- }
+ struct tftphdr *dp;
+ int n, size;
+ /* These are "static" to avoid longjmp funnies */
+ static struct tftphdr *ap; /* ack buffer */
+ static u_short block = 0;
+ static int acksize;
+ u_short dp_opcode, dp_block;
+ unsigned long r_timeout;
+
+ dp = w_init();
+ do {
+ timeout = rexmtval;
+
+ if (!block && oap) {
+ ap = (struct tftphdr *)ackbuf;
+ acksize = oacklen;
+ } else {
+ ap = (struct tftphdr *)ackbuf;
+ ap->th_opcode = htons((u_short) ACK);
+ ap->th_block = htons((u_short) block);
+ acksize = 4;
+ }
+ block++;
+ (void)sigsetjmp(timeoutbuf, 1);
+ send_ack:
+ r_timeout = timeout;
+ if (send(peer, ackbuf, acksize, 0) != acksize) {
+ syslog(LOG_WARNING, "tftpd: write(ack): %m");
+ goto abort;
+ }
+ write_behind(file, pf->f_convert);
+ for (;;) {
+ n = recv_time(peer, dp, PKTSIZE, 0, &r_timeout);
+ if (n < 0) { /* really? */
+ syslog(LOG_WARNING, "tftpd: read: %m");
+ goto abort;
+ }
+ dp_opcode = ntohs((u_short) dp->th_opcode);
+ dp_block = ntohs((u_short) dp->th_block);
+ if (dp_opcode == ERROR)
+ goto abort;
+ if (dp_opcode == DATA) {
+ if (dp_block == block) {
+ break; /* normal */
+ }
+ /* Re-synchronize with the other side */
+ (void)synchnet(peer);
+ if (dp_block == (block - 1))
+ goto send_ack; /* rexmit */
+ }
+ }
+ /* size = write(file, dp->th_data, n - 4); */
+ size = writeit(file, &dp, n - 4, pf->f_convert);
+ if (size != (n - 4)) { /* ahem */
+ if (size < 0)
+ nak(errno + 100, NULL);
+ else
+ nak(ENOSPACE, NULL);
+ goto abort;
+ }
+ } while (size == segsize);
write_behind(file, pf->f_convert);
- for ( ; ; ) {
- n = recv_time(peer, dp, PKTSIZE, 0, &r_timeout);
- if (n < 0) { /* really? */
- syslog(LOG_WARNING, "tftpd: read: %m");
- goto abort;
- }
- dp_opcode = ntohs((u_short)dp->th_opcode);
- dp_block = ntohs((u_short)dp->th_block);
- if (dp_opcode == ERROR)
- goto abort;
- if (dp_opcode == DATA) {
- if (dp_block == block) {
- break; /* normal */
- }
- /* Re-synchronize with the other side */
- (void) synchnet(peer);
- if (dp_block == (block-1))
- goto send_ack; /* rexmit */
- }
- }
- /* size = write(file, dp->th_data, n - 4); */
- size = writeit(file, &dp, n - 4, pf->f_convert);
- if (size != (n-4)) { /* ahem */
- if (size < 0) nak(errno + 100, NULL);
- else nak(ENOSPACE, NULL);
- goto abort;
+ (void)fclose(file); /* close data file */
+
+ ap->th_opcode = htons((u_short) ACK); /* send the "final" ack */
+ ap->th_block = htons((u_short) (block));
+ (void)send(peer, ackbuf, 4, 0);
+
+ timeout_quit = 1; /* just quit on timeout */
+ n = recv_time(peer, buf, sizeof(buf), 0, &timeout); /* normally times out and quits */
+ timeout_quit = 0;
+
+ if (n >= 4 && /* if read some data */
+ dp_opcode == DATA && /* and got a data block */
+ block == dp_block) { /* then my last ack was lost */
+ (void)send(peer, ackbuf, 4, 0); /* resend final ack */
}
- } while (size == segsize);
- write_behind(file, pf->f_convert);
- (void) fclose(file); /* close data file */
-
- ap->th_opcode = htons((u_short)ACK); /* send the "final" ack */
- ap->th_block = htons((u_short)(block));
- (void) send(peer, ackbuf, 4, 0);
-
- timeout_quit = 1; /* just quit on timeout */
- n = recv_time(peer, buf, sizeof (buf), 0, &timeout); /* normally times out and quits */
- timeout_quit = 0;
-
- if (n >= 4 && /* if read some data */
- dp_opcode == DATA && /* and got a data block */
- block == dp_block) { /* then my last ack was lost */
- (void) send(peer, ackbuf, 4, 0); /* resend final ack */
- }
- abort:
- return;
+ abort:
+ return;
}
-static const char * const errmsgs[] =
-{
- "Undefined error code", /* 0 - EUNDEF */
- "File not found", /* 1 - ENOTFOUND */
- "Access denied", /* 2 - EACCESS */
- "Disk full or allocation exceeded", /* 3 - ENOSPACE */
- "Illegal TFTP operation", /* 4 - EBADOP */
- "Unknown transfer ID", /* 5 - EBADID */
- "File already exists", /* 6 - EEXISTS */
- "No such user", /* 7 - ENOUSER */
- "Failure to negotiate RFC2347 options" /* 8 - EOPTNEG */
+static const char *const errmsgs[] = {
+ "Undefined error code", /* 0 - EUNDEF */
+ "File not found", /* 1 - ENOTFOUND */
+ "Access denied", /* 2 - EACCESS */
+ "Disk full or allocation exceeded", /* 3 - ENOSPACE */
+ "Illegal TFTP operation", /* 4 - EBADOP */
+ "Unknown transfer ID", /* 5 - EBADID */
+ "File already exists", /* 6 - EEXISTS */
+ "No such user", /* 7 - ENOUSER */
+ "Failure to negotiate RFC2347 options" /* 8 - EOPTNEG */
};
+
#define ERR_CNT (sizeof(errmsgs)/sizeof(const char *))
/*
@@ -1391,39 +1373,38 @@ static const char * const errmsgs[] =
* standard TFTP codes, or a UNIX errno
* offset by 100.
*/
-static void
-nak(int error, const char *msg)
+static void nak(int error, const char *msg)
{
- struct tftphdr *tp;
- int length;
-
- tp = (struct tftphdr *)buf;
- tp->th_opcode = htons((u_short)ERROR);
-
- if ( error >= 100 ) {
- /* This is a Unix errno+100 */
- if ( !msg )
- msg = strerror(error - 100);
- error = EUNDEF;
- } else {
- if ( (unsigned)error >= ERR_CNT )
- error = EUNDEF;
-
- if ( !msg )
- msg = errmsgs[error];
- }
-
- tp->th_code = htons((u_short)error);
-
- length = strlen(msg)+1;
- memcpy(tp->th_msg, msg, length);
- length += 4; /* Add space for header */
-
- if ( verbosity >= 2 ) {
- syslog(LOG_INFO, "sending NAK (%d, %s) to %s",
- error, tp->th_msg, inet_ntoa(from.sin_addr));
- }
-
- if (send(peer, buf, length, 0) != length)
- syslog(LOG_WARNING, "nak: %m");
+ struct tftphdr *tp;
+ int length;
+
+ tp = (struct tftphdr *)buf;
+ tp->th_opcode = htons((u_short) ERROR);
+
+ if (error >= 100) {
+ /* This is a Unix errno+100 */
+ if (!msg)
+ msg = strerror(error - 100);
+ error = EUNDEF;
+ } else {
+ if ((unsigned)error >= ERR_CNT)
+ error = EUNDEF;
+
+ if (!msg)
+ msg = errmsgs[error];
+ }
+
+ tp->th_code = htons((u_short) error);
+
+ length = strlen(msg) + 1;
+ memcpy(tp->th_msg, msg, length);
+ length += 4; /* Add space for header */
+
+ if (verbosity >= 2) {
+ syslog(LOG_INFO, "sending NAK (%d, %s) to %s",
+ error, tp->th_msg, inet_ntoa(from.sin_addr));
+ }
+
+ if (send(peer, buf, length, 0) != length)
+ syslog(LOG_WARNING, "nak: %m");
}
diff --git a/tftpd/tftpd.h b/tftpd/tftpd.h
index 789ee94..4413729 100644
--- a/tftpd/tftpd.h
+++ b/tftpd/tftpd.h
@@ -1,6 +1,6 @@
/* $Id$ */
/* ----------------------------------------------------------------------- *
- *
+ *
* Copyright 2001 H. Peter Anvin - All Rights Reserved
*
* This program is free software available under the same license