summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormglocker <mglocker@openbsd.org>2006-07-20 09:42:44 +0000
committermglocker <mglocker@openbsd.org>2006-07-20 09:42:44 +0000
commit3e7729ddb4bf5659c12057e895b089f5a8979d8b (patch)
tree8665bfb7cc82c32352481edf392a202f70319871
parentupdate for the new ADMtek PCI ids. (diff)
downloadwireguard-openbsd-3e7729ddb4bf5659c12057e895b089f5a8979d8b.tar.xz
wireguard-openbsd-3e7729ddb4bf5659c12057e895b089f5a8979d8b.zip
Add blksize option support for tftpd according to RFC 2348.
Note: While testing the new option, we noticed that our stable tftpd has a problem if any option is set (e.g. tsize) and you try to put a file. This has nothing todo with our new blksize option. We fix this as next. ok claudio@
-rw-r--r--include/arpa/tftp.h4
-rw-r--r--libexec/tftpd/tftpd.c80
-rw-r--r--usr.bin/tftp/tftp.c8
-rw-r--r--usr.bin/tftp/tftpsubs.c21
-rw-r--r--usr.bin/tftp/tftpsubs.h6
5 files changed, 77 insertions, 42 deletions
diff --git a/include/arpa/tftp.h b/include/arpa/tftp.h
index 62808559899..0f6fe83ae25 100644
--- a/include/arpa/tftp.h
+++ b/include/arpa/tftp.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: tftp.h,v 1.5 2004/01/27 02:25:30 deraadt Exp $ */
+/* $OpenBSD: tftp.h,v 1.6 2006/07/20 09:42:44 mglocker Exp $ */
/* $NetBSD: tftp.h,v 1.3 1994/10/26 00:56:48 cgd Exp $ */
/*
@@ -39,6 +39,8 @@
* Trivial File Transfer Protocol (IEN-133)
*/
#define SEGSIZE 512 /* data segment size */
+#define SEGSIZE_MIN 8 /* minimal data segment size */
+#define SEGSIZE_MAX 65464 /* maximal data segment size */
/*
* Packet types.
diff --git a/libexec/tftpd/tftpd.c b/libexec/tftpd/tftpd.c
index 1adb8ce9c3e..a351ce6bb4b 100644
--- a/libexec/tftpd/tftpd.c
+++ b/libexec/tftpd/tftpd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tftpd.c,v 1.46 2006/07/14 22:57:46 mglocker Exp $ */
+/* $OpenBSD: tftpd.c,v 1.47 2006/07/20 09:42:44 mglocker Exp $ */
/*
* Copyright (c) 1983 Regents of the University of California.
@@ -37,7 +37,7 @@ char copyright[] =
#ifndef lint
/*static char sccsid[] = "from: @(#)tftpd.c 5.13 (Berkeley) 2/26/91";*/
-static char rcsid[] = "$OpenBSD: tftpd.c,v 1.46 2006/07/14 22:57:46 mglocker Exp $";
+static char rcsid[] = "$OpenBSD: tftpd.c,v 1.47 2006/07/20 09:42:44 mglocker Exp $";
#endif /* not lint */
/*
@@ -70,12 +70,11 @@ static char rcsid[] = "$OpenBSD: tftpd.c,v 1.46 2006/07/14 22:57:46 mglocker Exp
#define TIMEOUT 5
#define MAX_TIMEOUTS 5
-#define PKTSIZE SEGSIZE + 4
struct formats;
-int readit(FILE *, struct tftphdr **, int);
-void read_ahead(FILE *, int);
+int readit(FILE *, struct tftphdr **, int, int);
+void read_ahead(FILE *, int, int);
int writeit(FILE *, struct tftphdr **, int, int);
int write_behind(FILE *, int);
int synchnet(int);
@@ -94,13 +93,15 @@ struct sockaddr_storage s_in;
int peer;
int rexmtval = TIMEOUT;
int max_rexmtval = 2 * TIMEOUT;
-char buf[PKTSIZE];
-char ackbuf[PKTSIZE];
+char *buf;
+char *ackbuf;
struct sockaddr_storage from;
int ndirs;
char **dirs;
int secure;
int cancreate;
+unsigned int segment_size = SEGSIZE;
+unsigned int packet_size = SEGSIZE + 4;
struct formats {
const char *f_mode;
@@ -121,12 +122,14 @@ struct options {
} options[] = {
{ "tsize", NULL, 0 }, /* OPT_TSIZE */
{ "timeout", NULL, 0 }, /* OPT_TIMEOUT */
+ { "blksize", NULL, 0 }, /* OPT_BLKSIZE */
{ NULL, NULL, 0 }
};
enum opt_enum {
OPT_TSIZE = 0,
- OPT_TIMEOUT
+ OPT_TIMEOUT,
+ OPT_BLKSIZE
};
struct errmsg {
@@ -254,9 +257,18 @@ main(int argc, char *argv[])
break;
}
+ if ((buf = malloc(packet_size)) == NULL) {
+ syslog(LOG_ERR, "malloc: %m");
+ exit(1);
+ }
+ if ((ackbuf = malloc(packet_size)) == NULL) {
+ syslog(LOG_ERR, "malloc: %m");
+ exit(1);
+ }
+
bzero(&msg, sizeof(msg));
iov.iov_base = buf;
- iov.iov_len = sizeof(buf);
+ iov.iov_len = packet_size;
msg.msg_name = &from;
msg.msg_namelen = sizeof(from);
msg.msg_iov = &iov;
@@ -300,7 +312,7 @@ main(int argc, char *argv[])
*/
bzero(&msg, sizeof(msg));
iov.iov_base = buf;
- iov.iov_len = sizeof(buf);
+ iov.iov_len = packet_size;
msg.msg_name = &from;
msg.msg_namelen = sizeof(from);
msg.msg_iov = &iov;
@@ -374,8 +386,9 @@ tftp(struct tftphdr *tp, int size)
char *cp;
int i, first = 1, has_options = 0, ecode;
struct formats *pf;
- char *filename, *mode = NULL, *option, *ccp;
+ char *filename, *mode = NULL, *option, *ccp, *newp = NULL;
char fnbuf[MAXPATHLEN], nicebuf[MAXPATHLEN];
+ const char *errstr;
cp = tp->th_stuff;
again:
@@ -448,6 +461,27 @@ option_fail:
options[OPT_TIMEOUT].o_request = NULL;
}
+ if (options[OPT_BLKSIZE].o_request) {
+ segment_size = strtonum(options[OPT_BLKSIZE].o_request,
+ SEGSIZE_MIN, SEGSIZE_MAX, &errstr);
+ if (errstr) {
+ nak(EBADOP);
+ exit(1);
+ }
+ packet_size = segment_size + 4;
+ if ((newp = realloc(buf, packet_size)) == NULL) {
+ syslog(LOG_ERR, "realloc: %m");
+ exit(1);
+ }
+ buf = newp;
+ if ((newp = realloc(ackbuf, packet_size)) == NULL) {
+ syslog(LOG_ERR, "realloc: %m");
+ exit(1);
+ }
+ ackbuf = newp;
+ options[OPT_BLKSIZE].o_reply = segment_size;
+ }
+
(void)strnvis(nicebuf, filename, MAXPATHLEN, VIS_SAFE|VIS_OCTAL);
ecode = (*pf->f_validate)(filename, tp->th_opcode);
if (has_options)
@@ -573,7 +607,7 @@ sendfile(struct formats *pf)
do {
/* read data from file */
- size = readit(file, &dp, pf->f_convert);
+ size = readit(file, &dp, pf->f_convert, segment_size);
if (size < 0) {
nak(errno + 100);
goto abort;
@@ -591,7 +625,7 @@ sendfile(struct formats *pf)
syslog(LOG_ERR, "send: %m");
goto abort;
}
- read_ahead(file, pf->f_convert);
+ read_ahead(file, pf->f_convert, segment_size);
}
error = 0;
@@ -609,7 +643,7 @@ sendfile(struct formats *pf)
syslog(LOG_ERR, "poll: %m");
goto abort;
}
- n = recv(peer, ackbuf, sizeof(ackbuf), 0);
+ n = recv(peer, ackbuf, packet_size, 0);
if (n == -1) {
error = 1;
if (errno == EINTR)
@@ -634,7 +668,7 @@ sendfile(struct formats *pf)
}
block++;
- } while (size == SEGSIZE);
+ } while (size == segment_size);
abort:
fclose(file);
@@ -690,7 +724,7 @@ recvfile(struct formats *pf)
syslog(LOG_ERR, "poll: %m");
goto abort;
}
- n = recv(peer, dp, PKTSIZE, 0);
+ n = recv(peer, dp, packet_size, 0);
if (n == -1) {
error = 1;
if (errno == EINTR)
@@ -723,7 +757,7 @@ recvfile(struct formats *pf)
nak(ENOSPACE);
goto abort;
}
- } while (size == SEGSIZE);
+ } while (size == segment_size);
/* close data file */
write_behind(file, pf->f_convert);
@@ -740,7 +774,7 @@ recvfile(struct formats *pf)
nfds = poll(pfd, 1, TIMEOUT * 1000);
if (nfds < 1)
exit(1);
- n = recv(peer, buf, sizeof(buf), 0);
+ n = recv(peer, buf, packet_size, 0);
/*
* If read some data and got a data block then my last ack was lost
* resend final ack.
@@ -775,9 +809,9 @@ nak(int error)
pe->e_msg = strerror(error - 100);
tp->th_code = EUNDEF; /* set 'undef' errorcode */
}
- length = strlcpy(tp->th_msg, pe->e_msg, sizeof(buf)) + 5;
- if (length > sizeof(buf))
- length = sizeof(buf);
+ length = strlcpy(tp->th_msg, pe->e_msg, packet_size) + 5;
+ if (length > packet_size)
+ length = packet_size;
if (send(peer, buf, length, 0) != length)
syslog(LOG_ERR, "nak: %m");
}
@@ -795,7 +829,7 @@ oack(void)
tp = (struct tftphdr *)buf;
bp = buf + 2;
- size = sizeof(buf) - 2;
+ size = packet_size - 2;
tp->th_opcode = htons((u_short)OACK);
for (i = 0; options[i].o_type != NULL; i++) {
if (options[i].o_request) {
@@ -843,7 +877,7 @@ oack(void)
syslog(LOG_ERR, "poll: %m");
exit(1);
}
- n = recv(peer, ackbuf, sizeof(ackbuf), 0);
+ n = recv(peer, ackbuf, packet_size, 0);
if (n == -1) {
error = 1;
if (errno == EINTR)
diff --git a/usr.bin/tftp/tftp.c b/usr.bin/tftp/tftp.c
index 6a4c8fc3e3e..38b575708bc 100644
--- a/usr.bin/tftp/tftp.c
+++ b/usr.bin/tftp/tftp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tftp.c,v 1.17 2006/07/12 16:58:51 mglocker Exp $ */
+/* $OpenBSD: tftp.c,v 1.18 2006/07/20 09:42:44 mglocker Exp $ */
/* $NetBSD: tftp.c,v 1.5 1995/04/29 05:55:25 cgd Exp $ */
/*
@@ -35,7 +35,7 @@
static char sccsid[] = "@(#)tftp.c 8.1 (Berkeley) 6/6/93";
#endif
static const char rcsid[] =
- "$OpenBSD: tftp.c,v 1.17 2006/07/12 16:58:51 mglocker Exp $";
+ "$OpenBSD: tftp.c,v 1.18 2006/07/20 09:42:44 mglocker Exp $";
#endif /* not lint */
/*
@@ -127,7 +127,7 @@ sendfile(int fd, char *name, char *mode)
if (!block)
size = makerequest(WRQ, name, dp, mode) - 4;
else {
- size = readit(file, &dp, convert);
+ size = readit(file, &dp, convert, SEGSIZE);
if (size < 0) {
nak(errno + 100);
break;
@@ -152,7 +152,7 @@ sendfile(int fd, char *name, char *mode)
warn("sendto");
goto abort;
}
- read_ahead(file, convert);
+ read_ahead(file, convert, SEGSIZE);
}
error = 0;
diff --git a/usr.bin/tftp/tftpsubs.c b/usr.bin/tftp/tftpsubs.c
index f8a00a79301..15896a78655 100644
--- a/usr.bin/tftp/tftpsubs.c
+++ b/usr.bin/tftp/tftpsubs.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tftpsubs.c,v 1.10 2006/07/12 16:58:51 mglocker Exp $ */
+/* $OpenBSD: tftpsubs.c,v 1.11 2006/07/20 09:42:44 mglocker Exp $ */
/* $NetBSD: tftpsubs.c,v 1.3 1994/12/08 09:51:31 jtc Exp $ */
/*
@@ -35,7 +35,7 @@
static char sccsid[] = "@(#)tftpsubs.c 8.1 (Berkeley) 6/6/93";
#endif
static const char rcsid[] =
- "$OpenBSD: tftpsubs.c,v 1.10 2006/07/12 16:58:51 mglocker Exp $";
+ "$OpenBSD: tftpsubs.c,v 1.11 2006/07/20 09:42:44 mglocker Exp $";
#endif /* not lint */
/*
@@ -62,7 +62,6 @@ static const char rcsid[] =
#include "tftpsubs.h"
-#define PKTSIZE SEGSIZE + 4 /* should be moved to tftp.h */
/* values for bf.counter */
#define BF_ALLOC -3 /* alloc'd but not yet filled */
#define BF_FREE -2 /* free */
@@ -71,8 +70,8 @@ static const char rcsid[] =
static struct tftphdr *rw_init(int);
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[SEGSIZE_MAX + 4]; /* room for data packet */
} bfs[2];
static int nextone; /* index of next buffer to use */
@@ -115,7 +114,7 @@ rw_init(int x)
* Free it and return next buffer filled with data.
*/
int
-readit(FILE *file, struct tftphdr **dpp, int convert)
+readit(FILE *file, struct tftphdr **dpp, int convert, int segment_size)
{
struct bf *b;
@@ -124,7 +123,7 @@ readit(FILE *file, struct tftphdr **dpp, int convert)
b = &bfs[current]; /* look at new buffer */
if (b->counter == BF_FREE) /* if it's empty */
- read_ahead(file, convert); /* fill it */
+ read_ahead(file, convert, segment_size); /* fill it */
/* assert(b->counter != BF_FREE); */ /* check */
*dpp = (struct tftphdr *)b->buf; /* set caller's ptr */
@@ -136,7 +135,7 @@ readit(FILE *file, struct tftphdr **dpp, int convert)
* Conversions are lf -> cr, lf and cr -> cr, nul.
*/
void
-read_ahead(FILE *file, int convert)
+read_ahead(FILE *file, int convert, int segment_size)
{
int i;
char *p;
@@ -152,12 +151,12 @@ read_ahead(FILE *file, int convert)
dp = (struct tftphdr *)b->buf;
if (convert == 0) {
- b->counter = read(fileno(file), dp->th_data, SEGSIZE);
+ b->counter = read(fileno(file), dp->th_data, segment_size);
return;
}
p = dp->th_data;
- for (i = 0; i < SEGSIZE; i++) {
+ for (i = 0; i < segment_size; i++) {
if (newline) {
if (prevchar == '\n')
c = '\n'; /* lf to cr, lf */
@@ -266,7 +265,7 @@ int
synchnet(int f)
{
int i, j = 0;
- char rbuf[PKTSIZE];
+ char rbuf[SEGSIZE_MIN];
struct sockaddr_in from;
socklen_t fromlen;
diff --git a/usr.bin/tftp/tftpsubs.h b/usr.bin/tftp/tftpsubs.h
index bd6f55adf13..3e14b1f0997 100644
--- a/usr.bin/tftp/tftpsubs.h
+++ b/usr.bin/tftp/tftpsubs.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: tftpsubs.h,v 1.5 2006/07/12 16:58:51 mglocker Exp $ */
+/* $OpenBSD: tftpsubs.h,v 1.6 2006/07/20 09:42:44 mglocker Exp $ */
/* $NetBSD: tftpsubs.h,v 1.2 1994/12/08 09:51:32 jtc Exp $ */
/*
@@ -37,8 +37,8 @@
* server.
*/
struct tftphdr *r_init(void);
-void read_ahead(FILE *, int);
-int readit(FILE *, struct tftphdr **, int);
+void read_ahead(FILE *, int, int);
+int readit(FILE *, struct tftphdr **, int, int);
int synchnet(int);