FreeBSD Bugzilla – Attachment 16821 Details for
Bug 30710
Patch: tftpd extension --- RFC2349
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
file.diff
file.diff (text/plain), 4.94 KB, created by
Espen Skoglund
on 2001-09-21 18:20:00 UTC
(
hide
)
Description:
file.diff
Filename:
MIME Type:
Creator:
Espen Skoglund
Created:
2001-09-21 18:20:00 UTC
Size:
4.94 KB
patch
obsolete
>--- libexec/tftpd/tftpd.c.orig Fri Sep 21 18:32:14 2001 >+++ libexec/tftpd/tftpd.c Fri Sep 21 19:07:03 2001 >@@ -79,10 +79,11 @@ > #include "tftpsubs.h" > > #define TIMEOUT 5 >+#define MAX_TIMEOUTS 5 > > int peer; > int rexmtval = TIMEOUT; >-int maxtimeout = 5*TIMEOUT; >+int max_rexmtval = 2*TIMEOUT; > > #define PKTSIZE SEGSIZE+4 > char buf[PKTSIZE]; >@@ -110,6 +111,7 @@ > > static char *errtomsg __P((int)); > static void nak __P((int)); >+static void oack __P(()); > > int > main(argc, argv) >@@ -311,6 +313,21 @@ > { 0 } > }; > >+struct options { >+ char *o_type; >+ char *o_request; >+ int o_reply; /* turn into union if need be */ >+} options[] = { >+ { "tsize" }, /* OPT_TSIZE */ >+ { "timeout" }, /* OPT_TIMEOUT */ >+ { NULL } >+}; >+ >+enum opt_enum { >+ OPT_TSIZE = 0, >+ OPT_TIMEOUT, >+}; >+ > /* > * Handle initial connection protocol. > */ >@@ -320,9 +337,9 @@ > int size; > { > register char *cp; >- int first = 1, ecode; >+ int i, first = 1, has_options = 0, ecode; > register struct formats *pf; >- char *filename, *mode; >+ char *filename, *mode, *option, *ccp; > > filename = cp = tp->th_stuff; > again: >@@ -350,7 +367,40 @@ > nak(EBADOP); > exit(1); > } >+ while (++cp < buf + size) { >+ for (i = 2, ccp = cp; i > 0; ccp++) { >+ if (ccp >= buf + size) { >+ nak(EBADOP); >+ exit(1); >+ } else if (*ccp == '\0') >+ i--; >+ } >+ for (option = cp; *cp; cp++) >+ if (isupper(*cp)) >+ *cp = tolower(*cp); >+ for (i = 0; options[i].o_type != NULL; i++) >+ if (strcmp(option, options[i].o_type) == 0) { >+ options[i].o_request = ++cp; >+ has_options = 1; >+ } >+ cp = ccp-1; >+ } >+ >+ if (options[OPT_TIMEOUT].o_request) { >+ int to = atoi(options[OPT_TIMEOUT].o_request); >+ if (to < 1 || to > 255) { >+ nak(EBADOP); >+ exit(1); >+ } >+ else if (to <= max_rexmtval) >+ options[OPT_TIMEOUT].o_reply = rexmtval = to; >+ else >+ options[OPT_TIMEOUT].o_request = NULL; >+ } >+ > ecode = (*pf->f_validate)(&filename, tp->th_opcode); >+ if (has_options) >+ oack(); > if (logging) { > char host[MAXHOSTNAMELEN]; > >@@ -468,6 +518,14 @@ > return (err); > *filep = filename = pathname; > } >+ if (options[OPT_TSIZE].o_request) { >+ if (mode == RRQ) >+ options[OPT_TSIZE].o_reply = stbuf.st_size; >+ else >+ /* XXX Allows writes of all sizes. */ >+ options[OPT_TSIZE].o_reply = >+ atoi(options[OPT_TSIZE].o_request); >+ } > fd = open(filename, mode == RRQ ? O_RDONLY : O_WRONLY|O_TRUNC); > if (fd < 0) > return (errno + 100); >@@ -478,15 +536,13 @@ > return (0); > } > >-int timeout; >+int timeouts; > jmp_buf timeoutbuf; > > void > timer() > { >- >- timeout += rexmtval; >- if (timeout >= maxtimeout) >+ if (++timeouts > MAX_TIMEOUTS) > exit(1); > longjmp(timeoutbuf, 1); > } >@@ -515,7 +571,7 @@ > } > dp->th_opcode = htons((u_short)DATA); > dp->th_block = htons((u_short)block); >- timeout = 0; >+ timeouts = 0; > (void)setjmp(timeoutbuf); > > send_data: >@@ -578,7 +634,7 @@ > ap = (struct tftphdr *)ackbuf; > block = 0; > do { >- timeout = 0; >+ timeouts = 0; > ap->th_opcode = htons((u_short)ACK); > ap->th_block = htons((u_short)block); > block++; >@@ -651,6 +707,7 @@ > { EBADID, "Unknown transfer ID" }, > { EEXISTS, "File already exists" }, > { ENOUSER, "No such user" }, >+ { EOPTNEG, "Option negotiation" }, > { -1, 0 } > }; > >@@ -699,4 +756,58 @@ > length += 5; > if (send(peer, buf, length, 0) != length) > syslog(LOG_ERR, "nak: %m"); >+} >+ >+/* >+ * Send an oack packet (option acknowledgement). >+ */ >+static void >+oack() >+{ >+ struct tftphdr *tp, *ap; >+ int size, i, n; >+ char *bp; >+ >+ tp = (struct tftphdr *)buf; >+ bp = buf + 2; >+ size = sizeof(buf) - 2; >+ tp->th_opcode = htons((u_short)OACK); >+ for (i = 0; options[i].o_type != NULL; i++) { >+ if (options[i].o_request) { >+ n = snprintf(bp, size, "%s%c%d", options[i].o_type, >+ 0, options[i].o_reply); >+ bp += n+1; >+ size -= n+1; >+ if (size < 0) { >+ syslog(LOG_ERR, "oack: buffer overflow"); >+ exit(1); >+ } >+ } >+ } >+ size = bp - buf; >+ ap = (struct tftphdr *)ackbuf; >+ signal(SIGALRM, timer); >+ timeouts = 0; >+ >+ (void)setjmp(timeoutbuf); >+ if (send(peer, buf, size, 0) != size) { >+ syslog(LOG_INFO, "oack: %m"); >+ exit(1); >+ } >+ >+ for (;;) { >+ alarm(rexmtval); >+ n = recv(peer, ackbuf, sizeof (ackbuf), 0); >+ alarm(0); >+ if (n < 0) { >+ syslog(LOG_ERR, "recv: %m"); >+ exit(1); >+ } >+ ap->th_opcode = ntohs((u_short)ap->th_opcode); >+ ap->th_block = ntohs((u_short)ap->th_block); >+ if (ap->th_opcode == ERROR) >+ exit(1); >+ if (ap->th_opcode == ACK && ap->th_block == 0) >+ break; >+ } > } >--- include/arpa/tftp.h.orig Fri Sep 21 18:42:39 2001 >+++ include/arpa/tftp.h Fri Sep 21 18:43:47 2001 >@@ -49,6 +49,7 @@ > #define DATA 03 /* data packet */ > #define ACK 04 /* acknowledgement */ > #define ERROR 05 /* error code */ >+#define OACK 06 /* option acknowledgement */ > > struct tftphdr { > unsigned short th_opcode; /* packet type */ >@@ -76,5 +77,6 @@ > #define EBADID 5 /* unknown transfer ID */ > #define EEXISTS 6 /* file already exists */ > #define ENOUSER 7 /* no such user */ >+#define EOPTNEG 8 /* option negotiation failed */ > > #endif /* !_TFTP_H_ */
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 30710
: 16821