diff options
Diffstat (limited to 'gpxe/contrib/tftp')
-rw-r--r-- | gpxe/contrib/tftp/Makefile | 56 | ||||
-rw-r--r-- | gpxe/contrib/tftp/README | 28 | ||||
-rw-r--r-- | gpxe/contrib/tftp/arpa/tftp.h | 80 | ||||
-rw-r--r-- | gpxe/contrib/tftp/main.c | 684 | ||||
-rw-r--r-- | gpxe/contrib/tftp/tftp.1 | 159 | ||||
-rw-r--r-- | gpxe/contrib/tftp/tftp.c | 536 | ||||
-rw-r--r-- | gpxe/contrib/tftp/tftpd.8 | 75 | ||||
-rw-r--r-- | gpxe/contrib/tftp/tftpd.c | 742 | ||||
-rw-r--r-- | gpxe/contrib/tftp/tftpsubs.c | 260 |
9 files changed, 0 insertions, 2620 deletions
diff --git a/gpxe/contrib/tftp/Makefile b/gpxe/contrib/tftp/Makefile deleted file mode 100644 index bd427cd0..00000000 --- a/gpxe/contrib/tftp/Makefile +++ /dev/null @@ -1,56 +0,0 @@ -# -# Copyright (c) 1987 Regents of the University of California. -# All rights reserved. -# -# Redistribution and use in source and binary forms are permitted -# provided that the above copyright notice and this paragraph are -# duplicated in all such forms and that any documentation, -# advertising materials, and other materials related to such -# distribution and use acknowledge that the software was developed -# by the University of California, Berkeley. The name of the -# University may not be used to endorse or promote products derived -# from this software without specific prior written permission. -# THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR -# IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED -# WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. -# -# @(#)Makefile 5.8 (Berkeley) 9/20/88 -# -# We override /usr/include/arpa/tftp.h with our own because -# we want tu_block to be unsigned short, not short as on most platforms -# -CFLAGS= -I. -O2 -Dsin=sin_x -SRCS= main.c tftp.c tftpsubs.c tftpd.c -OBJS= main.o tftp.o tftpsubs.o -DOBJS= tftpd.o tftpsubs.o -CC= gcc -LIBS= # -linet - -all: tftp tftpd - -tftp: ${OBJS} - ${CC} -o $@ ${CFLAGS} ${OBJS} # -linet - -tftpd: ${DOBJS} - ${CC} -o $@ ${CFLAGS} ${DOBJS} ${LIBS} - -clean: - rm -f ${OBJS} ${DOBJS} core tftp tftpd - -cleandir: clean - rm -f tags .depend - -depend: ${SRCS} - mkdep ${CFLAGS} ${SRCS} - -install: - install -s -o root -g root -m 755 tftp /usr/bin/tftp - install -c -o root -g root -m 444 tftp.1 /usr/man/man1 - install -s -o root -g root -m 755 tftpd /usr/sbin/in.tftpd - install -c -o root -g root -m 444 tftpd.8 /usr/man/man8 - -lint: ${SRCS} - lint ${CFLAGS} ${SRCS} - -tags: ${SRCS} - ctags ${SRCS} diff --git a/gpxe/contrib/tftp/README b/gpxe/contrib/tftp/README deleted file mode 100644 index e4957202..00000000 --- a/gpxe/contrib/tftp/README +++ /dev/null @@ -1,28 +0,0 @@ -This is a copy of the TFTP client as available from -ftp://sunsite.unc.edu/pub/linux/system/Network/file-transfer; I -modified the code, so that it understands RFC1782 and RFC1783 -extensions to the TFTP protocol. This allows for negotating an -extended transfer block size of up to 1432 bytes (as oppossed to the -standard 512 bytes). On busy networks, this will result in -considerably improved throughput and less load on the network. - -For further information and for licensing conditions, please have a -look at the header of the source files. - -Markus Gutschke <gutschk@math.uni-muenster.de> - -This is a copy of the TFTP server as available from -ftp://sunsite.unc.edu/pub/linux/system/Network/file-transfer; I -modified the code, so that it understands RFC1782 and RFC1783 -extensions to the TFTP protocol. This allows for negotating an -extended transfer block size of up to 1432 bytes (as oppossed to the -standard 512 bytes). On busy networks, this will result in -considerably improved throughput and less load on the network. - -I also added two command line options for changing the root directory -and for enabling debugging output. - -For further information and for licensing conditions, please have a -look at the header of the source files. - -Markus Gutschke <gutschk@math.uni-muenster.de> diff --git a/gpxe/contrib/tftp/arpa/tftp.h b/gpxe/contrib/tftp/arpa/tftp.h deleted file mode 100644 index 0904407c..00000000 --- a/gpxe/contrib/tftp/arpa/tftp.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 1983, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)tftp.h 8.1 (Berkeley) 6/2/93 - */ - -#ifndef _ARPA_TFTP_H -#define _ARPA_TFTP_H 1 - -/* - * Trivial File Transfer Protocol (IEN-133) - */ -#define SEGSIZE 512 /* data segment size */ - -/* - * Packet types. - */ -#define RRQ 01 /* read request */ -#define WRQ 02 /* write request */ -#define DATA 03 /* data packet */ -#define ACK 04 /* acknowledgement */ -#define ERROR 05 /* error code */ - -struct tftphdr { - short th_opcode; /* packet type */ - union { - unsigned short tu_block; /* block # */ - short tu_code; /* error code */ - char tu_stuff[1]; /* request packet stuff */ - } th_u; - char th_data[1]; /* data or error string */ -}; - -#define th_block th_u.tu_block -#define th_code th_u.tu_code -#define th_stuff th_u.tu_stuff -#define th_msg th_data - -/* - * Error codes. - */ -#define EUNDEF 0 /* not defined */ -#define ENOTFOUND 1 /* file not found */ -#define EACCESS 2 /* access violation */ -#define ENOSPACE 3 /* disk full or allocation exceeded */ -#define EBADOP 4 /* illegal TFTP operation */ -#define EBADID 5 /* unknown transfer ID */ -#define EEXISTS 6 /* file already exists */ -#define ENOUSER 7 /* no such user */ - -#endif /* arpa/tftp.h */ diff --git a/gpxe/contrib/tftp/main.c b/gpxe/contrib/tftp/main.c deleted file mode 100644 index ca4427a1..00000000 --- a/gpxe/contrib/tftp/main.c +++ /dev/null @@ -1,684 +0,0 @@ -/* - * Copyright (c) 1983 Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by the University of California, Berkeley. The name of the - * University may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ - -#ifndef lint -char copyright[] = -"@(#) Copyright (c) 1983 Regents of the University of California.\n\ - All rights reserved.\n"; -#endif /* not lint */ - -#ifndef lint -static char sccsid[] = "@(#)main.c 5.8 (Berkeley) 10/11/88"; -#endif /* not lint */ - -/* Many bug fixes are from Jim Guyton <guyton@rand-unix> */ - -/* - * TFTP User Program -- Command Interface. - */ -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/file.h> - -#include <netinet/in.h> - -#include <signal.h> -#include <stdio.h> -#include <errno.h> -#include <setjmp.h> -#include <ctype.h> -#include <netdb.h> - -#define TIMEOUT 5 /* secs between rexmt's */ - -struct sockaddr_in sin; -int f; -short port; -int trace; -int verbose; -int connected; -char mode[32]; -char line[200]; -int margc; -char *margv[20]; -char *prompt = "tftp"; -jmp_buf toplevel; -void intr(int); -struct servent *sp; - -int segsize = 512; - -int quit(), help(), setverbose(), settrace(), status(); -int get(), put(), setpeer(), modecmd(), setrexmt(), settimeout(); -int setbinary(), setascii(), setblocksize(); - -#define HELPINDENT (sizeof("connect")) - -struct cmd { - char *name; - char *help; - int (*handler)(); -}; - -char vhelp[] = "toggle verbose mode"; -char thelp[] = "toggle packet tracing"; -char chelp[] = "connect to remote tftp"; -char qhelp[] = "exit tftp"; -char hhelp[] = "print help information"; -char shelp[] = "send file"; -char rhelp[] = "receive file"; -char mhelp[] = "set file transfer mode"; -char sthelp[] = "show current status"; -char xhelp[] = "set per-packet retransmission timeout"; -char ihelp[] = "set total retransmission timeout"; -char ashelp[] = "set mode to netascii"; -char bnhelp[] = "set mode to octet"; -char bshelp[] = "set blocksize for next transfer"; - -struct cmd cmdtab[] = { - { "connect", chelp, setpeer }, - { "mode", mhelp, modecmd }, - { "put", shelp, put }, - { "get", rhelp, get }, - { "quit", qhelp, quit }, - { "verbose", vhelp, setverbose }, - { "trace", thelp, settrace }, - { "status", sthelp, status }, - { "binary", bnhelp, setbinary }, - { "ascii", ashelp, setascii }, - { "rexmt", xhelp, setrexmt }, - { "timeout", ihelp, settimeout }, - { "blocksize", bshelp, setblocksize }, - { "?", hhelp, help }, - 0 -}; - -struct cmd *getcmd(); -char *tail(); -char *index(); -char *rindex(); - -main(argc, argv) - char *argv[]; -{ - struct sockaddr_in sin; - int top; - - sp = getservbyname("tftp", "udp"); - if (sp == 0) { - fprintf(stderr, "tftp: udp/tftp: unknown service\n"); - exit(1); - } - f = socket(AF_INET, SOCK_DGRAM, 0); - if (f < 0) { - perror("tftp: socket"); - exit(3); - } - bzero((char *)&sin, sizeof (sin)); - sin.sin_family = AF_INET; - if (bind(f, (struct sockaddr *)&sin, sizeof (sin)) < 0) { - perror("tftp: bind"); - exit(1); - } - strcpy(mode, "netascii"); - signal(SIGINT, intr); - if (argc > 1) { - if (setjmp(toplevel) != 0) - exit(0); - setpeer(argc, argv); - } - top = setjmp(toplevel) == 0; - for (;;) - command(top); -} - -char hostname[100]; - -setpeer(argc, argv) - int argc; - char *argv[]; -{ - struct hostent *host; - - if (argc < 2) { - strcpy(line, "Connect "); - printf("(to) "); - fgets(&line[strlen(line)], sizeof(line) - strlen(line) - 1, stdin); - makeargv(); - argc = margc; - argv = margv; - } - if (argc > 3) { - printf("usage: %s host-name [port]\n", argv[0]); - return; - } - host = gethostbyname(argv[1]); - if (host) { - sin.sin_family = host->h_addrtype; - bcopy(host->h_addr, &sin.sin_addr, host->h_length); - strcpy(hostname, host->h_name); - } else { - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = inet_addr(argv[1]); - if (sin.sin_addr.s_addr == -1) { - connected = 0; - printf("%s: unknown host\n", argv[1]); - return; - } - strcpy(hostname, argv[1]); - } - port = sp->s_port; - if (argc == 3) { - port = atoi(argv[2]); - if (port < 0) { - printf("%s: bad port number\n", argv[2]); - connected = 0; - return; - } - port = htons(port); - } - connected = 1; -} - -struct modes { - char *m_name; - char *m_mode; -} modes[] = { - { "ascii", "netascii" }, - { "netascii", "netascii" }, - { "binary", "octet" }, - { "image", "octet" }, - { "octet", "octet" }, -/* { "mail", "mail" }, */ - { 0, 0 } -}; - -modecmd(argc, argv) - char *argv[]; -{ - register struct modes *p; - char *sep; - - if (argc < 2) { - printf("Using %s mode to transfer files.\n", 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) { - setmode(p->m_mode); - 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; -} - -setbinary(argc, argv) -char *argv[]; -{ setmode("octet"); -} - -setascii(argc, argv) -char *argv[]; -{ setmode("netascii"); -} - -setmode(newmode) -char *newmode; -{ - strcpy(mode, newmode); - if (verbose) - printf("mode set to %s\n", mode); -} - - -/* - * Send file(s). - */ -put(argc, argv) - char *argv[]; -{ - int fd; - register int n; - register char *cp, *targ; - - if (argc < 2) { - strcpy(line, "send "); - printf("(file) "); - fgets(&line[strlen(line)], sizeof(line) - strlen(line) - 1, stdin); - makeargv(); - argc = margc; - argv = margv; - } - if (argc < 2) { - putusage(argv[0]); - return; - } - targ = argv[argc - 1]; - if (index(argv[argc - 1], ':')) { - char *cp; - struct hostent *hp; - - for (n = 1; n < argc - 1; n++) - if (index(argv[n], ':')) { - putusage(argv[0]); - return; - } - cp = argv[argc - 1]; - targ = index(cp, ':'); - *targ++ = 0; - hp = gethostbyname(cp); - if (hp == NULL) { - fprintf(stderr, "tftp: %s: ", cp); - herror((char *)NULL); - return; - } - bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length); - sin.sin_family = hp->h_addrtype; - connected = 1; - strcpy(hostname, 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); - if (fd < 0) { - fprintf(stderr, "tftp: "); perror(cp); - return; - } - if (verbose) - printf("putting %s to %s:%s [%s]\n", - cp, hostname, targ, mode); - sin.sin_port = port; - sendfile(fd, targ, mode); - return; - } - /* this assumes the target is a directory */ - /* on a remote unix system. hmmmm. */ - cp = index(targ, '\0'); - *cp++ = '/'; - for (n = 1; n < argc - 1; n++) { - strcpy(cp, tail(argv[n])); - fd = open(argv[n], O_RDONLY); - 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); - sin.sin_port = port; - sendfile(fd, targ, mode); - } -} - -putusage(s) - char *s; -{ - printf("usage: %s file ... host:target, or\n", s); - printf(" %s file ... target (when already connected)\n", s); -} - -/* - * Receive file(s). - */ -get(argc, argv) - char *argv[]; -{ - int fd; - register int n; - register char *cp; - char *src; - - if (argc < 2) { - strcpy(line, "get "); - printf("(files) "); - fgets(&line[strlen(line)], sizeof(line) - strlen(line) - 1, stdin); - makeargv(); - argc = margc; - argv = margv; - } - if (argc < 2) { - getusage(argv[0]); - return; - } - if (!connected) { - for (n = 1; n < argc ; n++) - if (index(argv[n], ':') == 0) { - getusage(argv[0]); - return; - } - } - for (n = 1; n < argc ; n++) { - src = index(argv[n], ':'); - if (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)&sin.sin_addr, hp->h_length); - sin.sin_family = hp->h_addrtype; - connected = 1; - strcpy(hostname, hp->h_name); - } - if (argc < 4) { - cp = argc == 3 ? argv[2] : tail(src); - fd = creat(cp, 0644); - if (fd < 0) { - fprintf(stderr, "tftp: "); perror(cp); - return; - } - if (verbose) - printf("getting from %s:%s to %s [%s]\n", - hostname, src, cp, mode); - sin.sin_port = port; - recvfile(fd, src, mode); - break; - } - cp = tail(src); /* new .. jdg */ - fd = creat(cp, 0644); - if (fd < 0) { - fprintf(stderr, "tftp: "); perror(cp); - continue; - } - if (verbose) - printf("getting from %s:%s to %s [%s]\n", - hostname, src, cp, mode); - sin.sin_port = port; - recvfile(fd, src, mode); - } -} - -getusage(s) -char * s; -{ - printf("usage: %s host:file host:file ... file, or\n", s); - printf(" %s file file ... file if connected\n", s); -} - -int rexmtval = TIMEOUT; - -setrexmt(argc, argv) - char *argv[]; -{ - int t; - - if (argc < 2) { - strcpy(line, "Rexmt-timeout "); - printf("(value) "); - fgets(&line[strlen(line)], sizeof(line) - strlen(line) - 1, stdin); - makeargv(); - argc = margc; - argv = margv; - } - if (argc != 2) { - printf("usage: %s value\n", argv[0]); - return; - } - t = atoi(argv[1]); - if (t < 0) - printf("%d: bad value\n", t); - else - rexmtval = t; -} - -int maxtimeout = 5 * TIMEOUT; - -settimeout(argc, argv) - char *argv[]; -{ - int t; - - if (argc < 2) { - strcpy(line, "Maximum-timeout "); - printf("(value) "); - fgets(&line[strlen(line)], sizeof(line) - strlen(line) - 1, stdin); - makeargv(); - argc = margc; - argv = margv; - } - if (argc != 2) { - printf("usage: %s value\n", argv[0]); - return; - } - t = atoi(argv[1]); - if (t < 0) - printf("%d: bad value\n", t); - else - maxtimeout = t; -} - -status(argc, argv) - char *argv[]; -{ - if (connected) - printf("Connected to %s.\n", hostname); - else - printf("Not connected.\n"); - printf("Mode: %s Verbose: %s Tracing: %s\n", mode, - verbose ? "on" : "off", trace ? "on" : "off"); - printf("Rexmt-interval: %d seconds, Max-timeout: %d seconds\n", - rexmtval, maxtimeout); -} - -void intr(int sig) -{ - signal(SIGALRM, SIG_IGN); - alarm(0); - longjmp(toplevel, -1); -} - -char * -tail(filename) - char *filename; -{ - register char *s; - - while (*filename) { - s = rindex(filename, '/'); - if (s == NULL) - break; - if (s[1]) - return (s + 1); - *s = '\0'; - } - return (filename); -} - -/* - * Command parser. - */ -command(top) - int top; -{ - register struct cmd *c; - - if (!top) - putchar('\n'); - for (;;) { - printf("%s> ", prompt); - if (fgets(line, sizeof(line), stdin) == 0) { - if (feof(stdin)) { - quit(); - } else { - continue; - } - } - if (line[0] == 0) - continue; - makeargv(); - 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(name) - register char *name; -{ - register char *p, *q; - register struct cmd *c, *found; - register int nmatches, longest; - - longest = 0; - nmatches = 0; - found = 0; - for (c = cmdtab; p = c->name; 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. - */ -makeargv() -{ - register char *cp; - register 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; -} - -/*VARARGS*/ -quit() -{ - exit(0); -} - -/* - * Help command. - */ -help(argc, argv) - int argc; - char *argv[]; -{ - register struct cmd *c; - - if (argc == 1) { - printf("Commands may be abbreviated. Commands are:\n\n"); - for (c = cmdtab; c->name; c++) - printf("%-*s\t%s\n", HELPINDENT, c->name, c->help); - return; - } - while (--argc > 0) { - register 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); - } -} - -/*VARARGS*/ -settrace() -{ - trace = !trace; - printf("Packet tracing %s.\n", trace ? "on" : "off"); -} - -/*VARARGS*/ -setverbose() -{ - verbose = !verbose; - printf("Verbose mode %s.\n", verbose ? "on" : "off"); -} - -setblocksize(argc, argv) - char *argv[]; -{ - int t; - - if (argc < 2) { - strcpy(line, "blocksize "); - printf("(value) "); - fgets(&line[strlen(line)], sizeof(line) - strlen(line) - 1, stdin); - makeargv(); - argc = margc; - argv = margv; - } - if (argc != 2) { - printf("usage: %s value\n", argv[0]); - return; - } - t = atoi(argv[1]); - if (t < 8 || t > 1432) - printf("%d: bad value\n", t); - else - segsize = t; -} diff --git a/gpxe/contrib/tftp/tftp.1 b/gpxe/contrib/tftp/tftp.1 deleted file mode 100644 index fc235b2a..00000000 --- a/gpxe/contrib/tftp/tftp.1 +++ /dev/null @@ -1,159 +0,0 @@ -.\" Copyright (c) 1986 The Regents of the University of California. -.\" All rights reserved. -.\" -.\" Redistribution and use in source and binary forms are permitted -.\" provided that the above copyright notice and this paragraph are -.\" duplicated in all such forms and that any documentation, -.\" advertising materials, and other materials related to such -.\" distribution and use acknowledge that the software was developed -.\" by the University of California, Berkeley. The name of the -.\" University may not be used to endorse or promote products derived -.\" from this software without specific prior written permission. -.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR -.\" IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED -.\" WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. -.\" -.\" @(#)tftp.1 5.3 (Berkeley) 9/20/88 -.\" -.TH TFTP 1 "September 20, 1988" -.UC 6 -.SH NAME -tftp \- trivial file transfer program -.SH SYNOPSIS -.B tftp -[ -host -] -.SH DESCRIPTION -.I Tftp -is the user interface to the Internet TFTP -(Trivial File Transfer Protocol), -which allows users to transfer files to and from a remote machine. -The remote -.I host -may be specified on the command line, in which case -.I tftp -uses -.I host -as the default host for future transfers (see the -.B connect -command below). -.SH COMMANDS -Once -.I tftp -is running, it issues the prompt -.B tftp> -and recognizes the following commands: -.TP -\fBconnect\fP \fIhost-name\fP [ \fIport\fP ] -Set the -.I host -(and optionally -.IR port ) -for transfers. -Note that the TFTP protocol, unlike the FTP protocol, -does not maintain connections betweeen transfers; thus, the -.I connect -command does not actually create a connection, -but merely remembers what host is to be used for transfers. -You do not have to use the -.I connect -command; the remote host can be specified as part of the -.I get -or -.I put -commands. -.TP -\fBmode\fP \fItransfer-mode\fP -Set the mode for transfers; -.I transfer-mode -may be one of -.IR ascii -or -.IR binary . -The default is -.IR ascii . -.TP -\fBput\fP \fIfile\fP -.ns -.TP -\fBput\fP \fIlocalfile remotefile\fP -.ns -.TP -\fBput\fP \fIfile1 file2 ... fileN remote-directory\fP -Put a file or set of files to the specified -remote file or directory. -The destination -can be in one of two forms: -a filename on the remote host, if the host has already been specified, -or a string of the form -.I host:filename -to specify both a host and filename at the same time. -If the latter form is used, -the hostname specified becomes the default for future transfers. -If the remote-directory form is used, the remote host is -assumed to be a -.I UNIX -machine. -.TP -\fBget\fP \fIfilename\fP -.ns -.TP -\fBget\fP \fIremotename\fP \fIlocalname\fP -.ns -.TP -\fBget\fP \fIfile1\fP \fIfile2\fP ... \fIfileN\fP -Get a file or set of files from the specified -.IR sources . -.I Source -can be in one of two forms: -a filename on the remote host, if the host has already been specified, -or a string of the form -.I host:filename -to specify both a host and filename at the same time. -If the latter form is used, -the last hostname specified becomes the default for future transfers. -.TP -.B quit -Exit -.IR tftp . -An end of file also exits. -.TP -.B verbose -Toggle verbose mode. -.TP -.B trace -Toggle packet tracing. -.TP -.B status -Show current status. -.TP -\fBrexmt\fP \fIretransmission-timeout\fP -Set the per-packet retransmission timeout, in seconds. -.TP -\fBtimeout\fP \fItotal-transmission-timeout\fP -Set the total transmission timeout, in seconds. -.TP -.B ascii -Shorthand for "mode ascii" -.TP -.B binary -Shorthand for "mode binary" -.TP -\fBblocksize\fP \fItransfer-blocksize\fP -Set the blocksize that is used for transfers. This assumes that the -server knows about RFC1782 and RFC1783 extensions to the TFTP -protocol; automatic fallback is supported and will result in a default -blocksize of 512 octets. -.TP -\fB?\fP \ [ \fIcommand-name\fP ... ] -Print help information. -.SH BUGS -.PP -Because there is no user-login or validation within -the -.I TFTP -protocol, the remote site will probably have some -sort of file-access restrictions in place. The -exact methods are specific to each site and therefore -difficult to document here. diff --git a/gpxe/contrib/tftp/tftp.c b/gpxe/contrib/tftp/tftp.c deleted file mode 100644 index 894e535e..00000000 --- a/gpxe/contrib/tftp/tftp.c +++ /dev/null @@ -1,536 +0,0 @@ -/* - * Copyright (c) 1983 Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by the University of California, Berkeley. The name of the - * University may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ - -#ifndef lint -static char sccsid[] = "@(#)tftp.c 5.7 (Berkeley) 6/29/88"; -#endif /* not lint */ - -/* Many bug fixes are from Jim Guyton <guyton@rand-unix> */ - -/* - * TFTP User Program -- Protocol Machines - */ -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/time.h> - -#include <netinet/in.h> - -#include <arpa/tftp.h> - -#include <signal.h> -#include <stdio.h> -#include <errno.h> -#include <setjmp.h> - -extern int errno; - -extern struct sockaddr_in sin; /* filled in by main */ -extern int f; /* the opened socket */ -extern int trace; -extern int verbose; -extern int rexmtval; -extern int maxtimeout; -extern int segsize; - -#define PKTSIZE (1432+4) /* SEGSIZE+4 */ -char ackbuf[PKTSIZE]; -int timeout; -jmp_buf toplevel; -jmp_buf timeoutbuf; - -#ifndef OACK -#define OACK 6 -#endif - -void timer(int sig) -{ - - signal(SIGALRM, timer); - timeout += rexmtval; - if (timeout >= maxtimeout) { - printf("Transfer timed out.\n"); - longjmp(toplevel, -1); - } - longjmp(timeoutbuf, 1); -} - -strnlen(s, n) - char *s; - int n; -{ - int i = 0; - - while (n-- > 0 && *s++) i++; - return(i); -} - -/* - * Parse an OACK package and set blocksize accordingly - */ -parseoack(cp, sz) - char *cp; - int sz; -{ - int n; - - segsize = 512; - while (sz > 0 && *cp) { - n = strnlen(cp, sz); - if (n == 7 && !strncmp("blksize", cp, 7)) { - cp += 8; - sz -= 8; - if (sz <= 0) - break; - for (segsize = 0, n = strnlen(cp, sz); n > 0; - n--, cp++, sz--) { - if (*cp < '0' || *cp > '9') - break; - segsize = 10*segsize + *cp - '0'; } - } - cp += n + 1; - sz -= n + 1; - } - if (segsize < 8 || segsize > 1432) { - printf("Remote host negotiated illegal blocksize %d\n", - segsize); - segsize = 512; - longjmp(timeoutbuf, -1); - } -} - -/* - * Send the requested file. - */ -sendfile(fd, name, mode) - int fd; - char *name; - char *mode; -{ - register struct tftphdr *ap; /* data and ack packets */ - struct tftphdr *r_init(), *dp; - register int size, n; - u_short block = 0; - register unsigned long amount = 0; - struct sockaddr_in from; - int fromlen; - int convert; /* true if doing nl->crlf conversion */ - FILE *file; - - startclock(); /* start stat's clock */ - dp = r_init(); /* reset fillbuf/read-ahead code */ - ap = (struct tftphdr *)ackbuf; - file = fdopen(fd, "r"); - convert = !strcmp(mode, "netascii"); - - signal(SIGALRM, timer); - do { - if (block == 0) - 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); - break; - } - dp->th_opcode = htons((u_short)DATA); - dp->th_block = htons(block); - } - timeout = 0; - (void) setjmp(timeoutbuf); -send_data: - if (trace) - tpacket("sent", dp, size + 4); - n = sendto(f, dp, size + 4, 0, (struct sockaddr *)&sin, - sizeof (sin)); - if (n != size + 4) { - perror("tftp: sendto"); - goto abort; - } - if (block) /* do not start reading until the blocksize - has been negotiated */ - 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; - } - sin.sin_port = from.sin_port; /* added */ - if (trace) - tpacket("received", ap, n); - /* should verify packet came from server */ - ap->th_opcode = ntohs(ap->th_opcode); - if (ap->th_opcode == ERROR) { - printf("Error code %d: %s\n", ap->th_code, - ap->th_msg); - goto abort; - } - if (ap->th_opcode == ACK) { - int j; - - ap->th_block = ntohs(ap->th_block); - - if (block == 0) { - if (trace) - printf("server does not know " - "about RFC1782; reset" - "ting blocksize\n"); - segsize = 512; - } - if (ap->th_block == block) { - break; - } - /* On an error, try to synchronize - * both sides. - */ - j = synchnet(f); - if (j && trace) { - printf("discarded %d packets\n", - j); - } - if (ap->th_block == (block-1)) { - goto send_data; - } - } - else if (ap->th_opcode == OACK) { - if (block) { - printf("protocol violation\n"); - longjmp(toplevel, -1); - } - parseoack(&ap->th_stuff, n - 2); - break; - } - } - if (block > 0) - amount += size; - else - read_ahead(file, convert); - block++; - } while (size == segsize || block == 1); -abort: - fclose(file); - stopclock(); - if (amount > 0) - printstats("Sent", amount); -} - -/* - * Receive a file. - */ -recvfile(fd, name, mode) - int fd; - char *name; - char *mode; -{ - register struct tftphdr *ap; - struct tftphdr *dp, *w_init(); - register int n, size; - u_short block = 1; - unsigned long amount = 0; - struct sockaddr_in from; - int fromlen, firsttrip = 1; - FILE *file; - int convert; /* true if converting crlf -> lf */ - int waitforoack = 1; - - startclock(); - dp = w_init(); - ap = (struct tftphdr *)ackbuf; - file = fdopen(fd, "w"); - convert = !strcmp(mode, "netascii"); - - 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(block); - size = 4; - block++; - } - timeout = 0; - (void) setjmp(timeoutbuf); -send_ack: - if (trace) - tpacket("sent", ap, size); - if (sendto(f, ackbuf, size, 0, (struct sockaddr *)&sin, - sizeof (sin)) != size) { - alarm(0); - perror("tftp: sendto"); - goto abort; - } - if (!waitforoack) - 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; - } - sin.sin_port = from.sin_port; /* added */ - if (trace) - tpacket("received", dp, n); - /* should verify client address */ - dp->th_opcode = ntohs(dp->th_opcode); - if (dp->th_opcode == ERROR) { - printf("Error code %d: %s\n", dp->th_code, - dp->th_msg); - goto abort; - } - if (dp->th_opcode == DATA) { - int j; - - if (waitforoack) { - if (trace) - printf("server does not know " - "about RFC1782; reset" - "ting blocksize\n"); - waitforoack = 0; - segsize = 512; - } - dp->th_block = ntohs(dp->th_block); - if (dp->th_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->th_block == (block-1)) { - goto send_ack; /* resend ack */ - } - } - else if (dp->th_opcode == OACK) { - if (block != 1 || !waitforoack) { - printf("protocol violation\n"); - longjmp(toplevel, -1); - } - waitforoack = 0; - parseoack(&dp->th_stuff, n - 2); - ap->th_opcode = htons((u_short)ACK); - ap->th_block = htons(0); - size = 4; - goto send_ack; - } - } - /* size = write(fd, dp->th_data, n - 4); */ - size = writeit(file, &dp, n - 4, convert); - if (size < 0) { - nak(errno + 100); - 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(block); - (void) sendto(f, ackbuf, 4, 0, (struct sockaddr *)&sin, sizeof (sin)); - write_behind(file, convert); /* flush last buffer */ - fclose(file); - stopclock(); - if (amount > 0) - printstats("Received", amount); -} - -makerequest(request, name, tp, mode) - int request; - char *name, *mode; - struct tftphdr *tp; -{ - register char *cp; - - tp->th_opcode = htons((u_short)request); - cp = tp->th_stuff; - strcpy(cp, name); - cp += strlen(name); - *cp++ = '\0'; - strcpy(cp, mode); - cp += strlen(mode); - *cp++ = '\0'; - strcpy(cp, "blksize"); - cp += 7; - *cp++ = '\0'; - sprintf(cp, "%d", segsize); - cp += strlen(cp) + 1; - return (cp - (char *)tp); -} - -struct errmsg { - int e_code; - const char *e_msg; -} errmsgs[] = { - { EUNDEF, "Undefined error code" }, - { ENOTFOUND, "File not found" }, - { EACCESS, "Access violation" }, - { ENOSPACE, "Disk full or allocation exceeded" }, - { EBADOP, "Illegal TFTP operation" }, - { EBADID, "Unknown transfer ID" }, - { EEXISTS, "File already exists" }, - { ENOUSER, "No such user" }, - { -1, 0 } -}; - -/* - * Send a nak packet (error message). - * Error code passed in is one of the - * standard TFTP codes, or a UNIX errno - * offset by 100. - */ -nak(error) - int error; -{ - register struct tftphdr *tp; - int length; - register struct errmsg *pe; -/* extern char *sys_errlist[]; */ - - tp = (struct tftphdr *)ackbuf; - tp->th_opcode = htons((u_short)ERROR); - tp->th_code = htons((u_short)error); - for (pe = errmsgs; pe->e_code >= 0; pe++) - if (pe->e_code == error) - break; - if (pe->e_code < 0) { - pe->e_msg = sys_errlist[error - 100]; - tp->th_code = EUNDEF; - } - strcpy(tp->th_msg, pe->e_msg); - length = strlen(pe->e_msg) + 4; - if (trace) - tpacket("sent", tp, length); - if (sendto(f, ackbuf, length, 0, (struct sockaddr *)&sin, sizeof (sin)) - != length) - perror("nak"); -} - -topts(cp, sz) - char *cp; - int sz; -{ - int n, i = 0; - - while (sz > 0 && *cp) { - n = strnlen(cp, sz); - if (n > 0) { - printf("%s%s=", i++ ? ", " : "", cp); - cp += n + 1; - sz -= n + 1; - if (sz <= 0) - break; - n = strnlen(cp, sz); - if (n > 0) - printf("%s", cp); - } - cp += n + 1; - sz -= n + 1; - } -} - -tpacket(s, tp, n) - char *s; - struct tftphdr *tp; - int n; -{ - static char *opcodes[] = - { "#0", "RRQ", "WRQ", "DATA", "ACK", "ERROR", "OACK" }; - register char *cp, *file; - u_short op = ntohs(tp->th_opcode); - char *index(); - - if (op < RRQ || op > OACK) - printf("%s opcode=%x ", s, op); - else - printf("%s %s ", s, opcodes[op]); - switch (op) { - - case RRQ: - case WRQ: - n -= 2; - file = cp = tp->th_stuff; - cp = index(cp, '\0'); - printf("<file=%s, mode=%s, opts: ", file, cp + 1); - topts(index(cp + 1, '\000') + 1, n - strlen(file) - - strlen(cp + 1) - 2); - printf(">\n"); - 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; - case OACK: - printf("<"); - topts(tp->th_stuff, n - 2); - printf(">\n"); - break; - } -} - -struct timeval tstart; -struct timeval tstop; -struct timezone zone; - -startclock() { - gettimeofday(&tstart, &zone); -} - -stopclock() { - gettimeofday(&tstop, &zone); -} - -printstats(direction, amount) -char *direction; -unsigned long amount; -{ - double delta; - /* compute delta in 1/10's second units */ - delta = ((tstop.tv_sec*10.)+(tstop.tv_usec/100000)) - - ((tstart.tv_sec*10.)+(tstart.tv_usec/100000)); - delta = delta/10.; /* back to seconds */ - printf("%s %ld bytes in %.1f seconds", direction, amount, delta); - if ((verbose) && (delta >= 0.1)) - printf(" [%.0f bits/sec]", (amount*8.)/delta); - putchar('\n'); -} - diff --git a/gpxe/contrib/tftp/tftpd.8 b/gpxe/contrib/tftp/tftpd.8 deleted file mode 100644 index 6a154c10..00000000 --- a/gpxe/contrib/tftp/tftpd.8 +++ /dev/null @@ -1,75 +0,0 @@ -.\" Copyright (c) 1983 The Regents of the University of California. -.\" All rights reserved. -.\" -.\" Redistribution and use in source and binary forms are permitted -.\" provided that the above copyright notice and this paragraph are -.\" duplicated in all such forms and that any documentation, -.\" advertising materials, and other materials related to such -.\" distribution and use acknowledge that the software was developed -.\" by the University of California, Berkeley. The name of the -.\" University may not be used to endorse or promote products derived -.\" from this software without specific prior written permission. -.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR -.\" IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED -.\" WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. -.\" -.\" @(#)tftpd.8 6.3 (Berkeley) 9/20/88 -.\" -.TH TFTPD 8 "September 20, 1988" -.UC 5 -.SH NAME -tftpd \- DARPA Trivial File Transfer Protocol server -.SH SYNOPSIS -.B /etc/tftpd -[ -.SM \-c -<rootdir> ] [ -.SM \-d -] [ -.SM \-r -<filter> ] -.SH DESCRIPTION -.I Tftpd -is a server which supports the DARPA Trivial File Transfer -Protocol. -The TFTP server operates -at the port indicated in the ``tftp'' service description; -see -.IR services (5). -The server is normally started by -.IR inetd (8). -.PP -The use of -.I tftp -does not require an account or password on the remote system. -Due to the lack of authentication information, -.I tftpd -will allow only publicly readable files to be -accessed. -Files may be written only if they already exist and are publicly writable. -Note that this extends the concept of ``public'' to include -all users on all hosts that can be reached through the network; -this may not be appropriate on all systems, and its implications -should be considered before enabling tftp service. -The server should have the user ID with the lowest possible privilege. -.SH OPTIONS -.TP -.B \-c -Pathname of a directory that is considered the rootdirectory for all -transfers. N.B. -.I tftpd -does not actually perform a -.IR chroot (2) -call; you should be aware of the security implications and you -probably should run the server from an unpriviledged account. -.TP -.B \-d -Increased debugging level. -.TP -.B \-r -Pathname of a file that is considered to be a filter program. Whenever -a client tries to download this file, the filter will be started and -its output is send to the client. An arbitrary amount of these -filters can be specified. -.SH "SEE ALSO" -tftp(1), inetd(8) diff --git a/gpxe/contrib/tftp/tftpd.c b/gpxe/contrib/tftp/tftpd.c deleted file mode 100644 index 325a7134..00000000 --- a/gpxe/contrib/tftp/tftpd.c +++ /dev/null @@ -1,742 +0,0 @@ -/* - * Copyright (c) 1983 Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by the University of California, Berkeley. The name of the - * University may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ - -#ifndef lint -char copyright[] = -"@(#) Copyright (c) 1983 Regents of the University of California.\n\ - All rights reserved.\n"; -#endif /* not lint */ - -#ifndef lint -static char sccsid[] = "@(#)tftpd.c 5.8 (Berkeley) 6/18/88"; -#endif /* not lint */ - -/* - * Trivial file transfer protocol server. - * - * This version includes many modifications by Jim Guyton <guyton@rand-unix> - * - * Further modifications by Markus Gutschke <gutschk@math.uni-muenster.de> - * - RFC1782 option parsing - * - RFC1783 extended blocksize - * - "-c" option for changing the root directory - * - "-d" option for debugging output - */ - -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/ioctl.h> -#include <sys/wait.h> -#include <sys/stat.h> - -#include <netinet/in.h> - -#include <arpa/tftp.h> - -#include <alloca.h> -#include <string.h> -#include <signal.h> -#include <stdio.h> -#include <errno.h> -#include <ctype.h> -#include <netdb.h> -#include <setjmp.h> -#include <syslog.h> - -#define TIMEOUT 5 - -#ifndef OACK -#define OACK 06 -#endif - -#ifndef EOPTNEG -#define EOPTNEG 8 -#endif - -extern int errno; -struct sockaddr_in sin = { AF_INET }; -int peer; -int rexmtval = TIMEOUT; -int maxtimeout = 5*TIMEOUT; - -#define PKTSIZE (1432+4) /* SEGSIZE+4 */ -int segsize = SEGSIZE; -char buf[PKTSIZE]; -char ackbuf[PKTSIZE]; -struct sockaddr_in from; -int fromlen; - -char *rootdir = NULL; -int debug = 0; - -struct filters { - struct filters *next; - char *fname; -} *filters = NULL; -int isfilter = 0; - -main(argc, argv) - char *argv[]; -{ - register struct tftphdr *tp; - register int n; - int on = 1; - extern int optind; - extern char *optarg; - - openlog(argv[0], LOG_PID, LOG_DAEMON); - - while ((n = getopt(argc, argv, "c:dr:")) >= 0) { - switch (n) { - case 'c': - if (rootdir) - goto usage; - rootdir = optarg; - break; - case 'd': - debug++; - break; - case 'r': { - struct filters *fp = (void *) - malloc(sizeof(struct filters) + - strlen(optarg) + 1); - fp->next = filters; - fp->fname = (char *)(fp + 1); - strcpy(fp->fname, optarg); - filters = fp; - break; } - default: - usage: - syslog(LOG_ERR, "Usage: %s [-c chroot] " - "[-r readfilter] [-d]\n", - argv[0]); - exit(1); - } - } - if (argc-optind != 0) - goto usage; - - ioctl(0, FIONBIO, &on); -/* if (ioctl(0, FIONBIO, &on) < 0) { - syslog(LOG_ERR, "ioctl(FIONBIO): %m\n"); - exit(1); - } -*/ - fromlen = sizeof (from); - n = recvfrom(0, buf, segsize+4, 0, - (struct sockaddr *)&from, &fromlen); - if (n < 0) { - syslog(LOG_ERR, "recvfrom: %m\n"); - exit(1); - } - /* - * Now that we have read the message out of the UDP - * socket, we fork and exit. Thus, inetd will go back - * to listening to the tftp port, and the next request - * to come in will start up a new instance of tftpd. - * - * We do this so that inetd can run tftpd in "wait" mode. - * The problem with tftpd running in "nowait" mode is that - * inetd may get one or more successful "selects" on the - * tftp port before we do our receive, so more than one - * instance of tftpd may be started up. Worse, if tftpd - * break before doing the above "recvfrom", inetd would - * spawn endless instances, clogging the system. - */ - { - int pid; - int i, j; - - for (i = 1; i < 20; i++) { - pid = fork(); - if (pid < 0) { - sleep(i); - /* - * flush out to most recently sent request. - * - * This may drop some request, but those - * will be resent by the clients when - * they timeout. The positive effect of - * this flush is to (try to) prevent more - * than one tftpd being started up to service - * a single request from a single client. - */ - j = sizeof from; - i = recvfrom(0, buf, segsize+4, 0, - (struct sockaddr *)&from, &j); - if (i > 0) { - n = i; - fromlen = j; - } - } else { - break; - } - } - if (pid < 0) { - syslog(LOG_ERR, "fork: %m\n"); - exit(1); - } else if (pid != 0) { - exit(0); - } - } - from.sin_family = AF_INET; - alarm(0); - close(0); - close(1); - peer = socket(AF_INET, SOCK_DGRAM, 0); - if (peer < 0) { - syslog(LOG_ERR, "socket: %m\n"); - exit(1); - } - if (bind(peer, (struct sockaddr *)&sin, sizeof (sin)) < 0) { - syslog(LOG_ERR, "bind: %m\n"); - exit(1); - } - if (connect(peer, (struct sockaddr *)&from, sizeof(from)) < 0) { - syslog(LOG_ERR, "connect: %m\n"); - exit(1); - } - tp = (struct tftphdr *)buf; - tp->th_opcode = ntohs(tp->th_opcode); - if (tp->th_opcode == RRQ || tp->th_opcode == WRQ) - tftp(tp, n); - exit(1); -} - -int validate_access(); -int sendfile(), recvfile(); - -struct formats { - char *f_mode; - int (*f_validate)(); - int (*f_send)(); - int (*f_recv)(); - int f_convert; -} formats[] = { - { "netascii", validate_access, sendfile, recvfile, 1 }, - { "octet", validate_access, sendfile, recvfile, 0 }, -#ifdef notdef - { "mail", validate_user, sendmail, recvmail, 1 }, -#endif - { 0 } -}; - -int set_blksize(); - -struct options { - char *o_opt; - int (*o_fnc)(); -} options[] = { - { "blksize", set_blksize }, - { 0 } -}; - -/* - * Set a non-standard block size (c.f. RFC1783) - */ - -set_blksize(val, ret) - char *val; - char **ret; -{ - static char b_ret[5]; - int sz = atoi(val); - - if (sz < 8) { - if (debug) - syslog(LOG_ERR, "Requested packetsize %d < 8\n", sz); - return(0); - } else if (sz > PKTSIZE-4) { - if (debug) - syslog(LOG_INFO, "Requested packetsize %d > %d\n", - sz, PKTSIZE-4); - sz = PKTSIZE-4; - } else if (debug) - syslog(LOG_INFO, "Adjusted packetsize to %d octets\n", sz); - - segsize = sz; - sprintf(*ret = b_ret, "%d", sz); - return(1); -} - -/* - * Parse RFC1782 style options - */ - -do_opt(opt, val, ap) - char *opt; - char *val; - char **ap; -{ - struct options *po; - char *ret; - - for (po = options; po->o_opt; po++) - if (strcasecmp(po->o_opt, opt) == 0) { - if (po->o_fnc(val, &ret)) { - if (*ap + strlen(opt) + strlen(ret) + 2 >= - ackbuf + sizeof(ackbuf)) { - if (debug) - syslog(LOG_ERR, - "Ackbuf overflow\n"); - nak(ENOSPACE); - exit(1); - } - *ap = strrchr(strcpy(strrchr(strcpy(*ap, opt), - '\000')+1, val), - '\000')+1; - } else { - nak(EOPTNEG); - exit(1); - } - break; - } - if (debug && !po->o_opt) - syslog(LOG_WARNING, "Unhandled option: %d = %d\n", opt, val); - return; -} - -/* - * Handle initial connection protocol. - */ -tftp(tp, size) - struct tftphdr *tp; - int size; -{ - register char *cp; - int argn = 0, ecode; - register struct formats *pf; - char *filename, *mode; - char *val, *opt; - char *ap = ackbuf+2; - int isopts; - - ((struct tftphdr *)ackbuf)->th_opcode = ntohs(OACK); - filename = cp = tp->th_stuff; -again: - while (cp < buf + size) { - if (*cp == '\0') - break; - cp++; - } - if (*cp != '\0') { - if (debug) - syslog(LOG_WARNING, "Received illegal request\n"); - nak(EBADOP); - exit(1); - } - if (!argn++) { - mode = ++cp; - goto again; - } else { - if (debug && argn == 3) - syslog(LOG_INFO, "Found RFC1782 style options\n"); - *(argn & 1 ? &val : &opt) = ++cp; - if (argn & 1) - do_opt(opt, val, &ap); - if (cp < buf + size && *cp != '\000') - goto again; - } - - for (cp = mode; *cp; cp++) - if (isupper(*cp)) - *cp = tolower(*cp); - for (pf = formats; pf->f_mode; pf++) - if (strcmp(pf->f_mode, mode) == 0) - break; - if (pf->f_mode == 0) { - if (debug) - syslog(LOG_WARNING, "Unknown data format: %s\n", mode); - nak(EBADOP); - exit(1); - } - - if (rootdir) { - cp = alloca(strlen(rootdir) + strlen(filename) + 1); - if (cp == NULL) { - nak(100+ENOMEM); - exit(1); - } - if (*filename != '/') { - if (debug) - syslog(LOG_ERR, - "Filename has to be absolute: %s\n", - filename); - nak(EACCESS); - exit(1); - } - filename = strcat(strcpy(cp, rootdir), filename); - } - - ecode = (*pf->f_validate)(filename, tp->th_opcode); - if (ecode) { - nak(ecode, ERROR); - exit(1); - } - isopts = ap != (ackbuf+2); - (tp->th_opcode == WRQ ? *pf->f_recv : *pf->f_send) - (pf, isopts ? ackbuf : NULL, isopts ? ap-ackbuf : 0); - exit(0); -} - - -FILE *file; - -/* - * Validate file access. Since we - * have no uid or gid, for now require - * file to exist and be publicly - * readable/writable. - * Note also, full path name must be - * given as we have no login directory. - */ -validate_access(filename, mode) - char *filename; - int mode; -{ - struct stat stbuf; - int fd; - char *cp; - - isfilter = 0; - if (mode == RRQ) { - struct filters *fp = filters; - for (; fp; fp = fp->next) { - if (!strcmp(fp->fname, - filename + - (rootdir ? strlen(rootdir) : 0))) { - if (debug) - syslog(LOG_INFO, "Opening input " - "filter: %s\n", filename); - if ((file = popen(filename, "r")) == NULL) { - syslog(LOG_ERR, "Failed to open input " - "filter\n"); - return (EACCESS); } - fd = fileno(file); - isfilter = 1; - return (0); - } - } - } - - if (*filename != '/') { - if (debug) - syslog(LOG_ERR, "Filename has to be absolute: %s\n", - filename); - return (EACCESS); - } - for (cp = filename; *cp; cp++) - if (*cp == '~' || *cp == '$' || - (*cp == '/' && cp[1] == '.' && cp[2] == '.')) { - if (debug) - syslog(LOG_ERR, "Illegal filename: %s\n", - filename); - return (EACCESS); - } - if (debug) - syslog(LOG_INFO, "Validating \"%s\" for %sing\n", - filename, mode == RRQ ? "read" : "writ"); - if (stat(filename, &stbuf) < 0) - return (errno == ENOENT ? ENOTFOUND : EACCESS); - if (mode == RRQ) { - if ((stbuf.st_mode&(S_IREAD >> 6)) == 0) - return (EACCESS); - } else { - if ((stbuf.st_mode&(S_IWRITE >> 6)) == 0) - return (EACCESS); - } - fd = open(filename, mode == RRQ ? 0 : 1); - if (fd < 0) - return (errno + 100); - file = fdopen(fd, (mode == RRQ)? "r":"w"); - if (file == NULL) { - return errno+100; - } - return (0); -} - -int timeout; -jmp_buf timeoutbuf; - -void timer(int sig) -{ - - timeout += rexmtval; - if (timeout >= maxtimeout) { - if (debug) - syslog(LOG_WARNING, "Timeout!\n"); - exit(1); - } - longjmp(timeoutbuf, 1); -} - -/* - * Send the requested file. - */ -sendfile(pf, oap, oacklen) - struct formats *pf; - struct tftphdr *oap; - int oacklen; -{ - struct tftphdr *dp, *r_init(); - register struct tftphdr *ap; /* ack packet */ - register int size, n; - u_short block = 1; - - signal(SIGALRM, timer); - - ap = (struct tftphdr *)ackbuf; - - if (oap) { - timeout = 0; - (void) setjmp(timeoutbuf); - oack: - if (send(peer, oap, oacklen, 0) != oacklen) { - syslog(LOG_ERR, "tftpd: write: %m\n"); - goto abort; - } - for ( ; ; ) { - alarm(rexmtval); - n = recv(peer, ackbuf, sizeof (ackbuf), 0); - alarm(0); - if (n < 0) { - syslog(LOG_ERR, "tftpd: read: %m\n"); - goto abort; - } - ap->th_opcode = ntohs((u_short)ap->th_opcode); - ap->th_block = ntohs(ap->th_block); - - if (ap->th_opcode == ERROR) { - if (debug) - syslog(LOG_ERR, "Client does not " - "accept options\n"); - goto abort; } - - if (ap->th_opcode == ACK) { - if (ap->th_block == 0) { - if (debug) - syslog(LOG_DEBUG, - "RFC1782 option " - "negotiation " - "succeeded\n"); - break; - } - /* Re-synchronize 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); - goto abort; - } - dp->th_opcode = htons((u_short)DATA); - dp->th_block = htons(block); - timeout = 0; - (void) setjmp(timeoutbuf); - -send_data: - if (send(peer, dp, size + 4, 0) != size + 4) { - syslog(LOG_ERR, "tftpd: write: %m\n"); - goto abort; - } - read_ahead(file, pf->f_convert); - for ( ; ; ) { - alarm(rexmtval); /* read the ack */ - n = recv(peer, ackbuf, sizeof (ackbuf), 0); - alarm(0); - if (n < 0) { - syslog(LOG_ERR, "tftpd: read: %m\n"); - goto abort; - } - ap->th_opcode = ntohs((u_short)ap->th_opcode); - ap->th_block = ntohs(ap->th_block); - - if (ap->th_opcode == ERROR) - goto abort; - - if (ap->th_opcode == ACK) { - if (ap->th_block == block) { - break; - } - /* Re-synchronize with the other side */ - (void) synchnet(peer); - if (ap->th_block == (block -1)) { - goto send_data; - } - } - - } - block++; - } while (size == segsize); -abort: - if (isfilter) - pclose(file); - else - (void) fclose(file); - isfilter = 0; -} - -void justquit(int sig) -{ - exit(0); -} - - -/* - * Receive a file. - */ -recvfile(pf, oap, oacklen) - struct formats *pf; - struct tftphdr *oap; - int oacklen; -{ - struct tftphdr *dp, *w_init(); - register struct tftphdr *ap; /* ack buffer */ - register int acksize, n, size; - u_short block = 0; - - signal(SIGALRM, timer); - dp = w_init(); - do { - timeout = 0; - - if (!block++ && oap) { - ap = (struct tftphdr *)oap; - acksize = oacklen; - } else { - ap = (struct tftphdr *)ackbuf; - ap->th_opcode = htons((u_short)ACK); - ap->th_block = htons(block-1); - acksize = 4; - } - (void) setjmp(timeoutbuf); -send_ack: - if (send(peer, (char *)ap, acksize, 0) != acksize) { - syslog(LOG_ERR, "tftpd: write: %m\n"); - goto abort; - } - write_behind(file, pf->f_convert); - for ( ; ; ) { - alarm(rexmtval); - n = recv(peer, dp, segsize+4, 0); - alarm(0); - if (n < 0) { /* really? */ - syslog(LOG_ERR, "tftpd: read: %m\n"); - goto abort; - } - dp->th_opcode = ntohs((u_short)dp->th_opcode); - dp->th_block = ntohs(dp->th_block); - if (dp->th_opcode == ERROR) - goto abort; - if (dp->th_opcode == DATA) { - if (dp->th_block == block) { - break; /* normal */ - } - /* Re-synchronize with the other side */ - (void) synchnet(peer); - if (dp->th_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); - else nak(ENOSPACE); - goto abort; - } - } while (size == segsize); - write_behind(file, pf->f_convert); - if (isfilter) - pclose(file); - else - (void) fclose(file); /* close data file */ - isfilter = 0; - - ap = (struct tftphdr *)ackbuf; - ap->th_opcode = htons((u_short)ACK); /* send the "final" ack */ - ap->th_block = htons(block); - (void) send(peer, ackbuf, 4, 0); - - signal(SIGALRM, justquit); /* just quit on timeout */ - alarm(rexmtval); - n = recv(peer, buf, segsize, 0); /* normally times out and quits */ - alarm(0); - if (n >= 4 && /* if read some data */ - dp->th_opcode == DATA && /* and got a data block */ - block == dp->th_block) { /* then my last ack was lost */ - (void) send(peer, ackbuf, 4, 0); /* resend final ack */ - } -abort: - return; -} - -struct errmsg { - int e_code; - const char *e_msg; -} errmsgs[] = { - { EUNDEF, "Undefined error code" }, - { ENOTFOUND, "File not found" }, - { EACCESS, "Access violation" }, - { ENOSPACE, "Disk full or allocation exceeded" }, - { EBADOP, "Illegal TFTP operation" }, - { EBADID, "Unknown transfer ID" }, - { EEXISTS, "File already exists" }, - { ENOUSER, "No such user" }, - { EOPTNEG, "Failure to negotiate RFC1782 options" }, - { -1, 0 } -}; - -/* - * Send a nak packet (error message). - * Error code passed in is one of the - * standard TFTP codes, or a UNIX errno - * offset by 100. - */ -nak(error) - int error; -{ - register struct tftphdr *tp; - int length; - register struct errmsg *pe; -/* extern char *sys_errlist[]; */ - - tp = (struct tftphdr *)buf; - tp->th_opcode = htons((u_short)ERROR); - tp->th_code = htons((u_short)error); - for (pe = errmsgs; pe->e_code >= 0; pe++) - if (pe->e_code == error) - break; - if (pe->e_code < 0) { - pe->e_msg = sys_errlist[error -100]; - tp->th_code = EUNDEF; /* set 'undef' errorcode */ - } - strcpy(tp->th_msg, pe->e_msg); - length = strlen(pe->e_msg); - tp->th_msg[length] = '\0'; - length += 5; - if (debug) - syslog(LOG_ERR, "Negative acknowledge: %s\n", tp->th_msg); - if (send(peer, buf, length, 0) != length) - syslog(LOG_ERR, "nak: %m\n"); -} diff --git a/gpxe/contrib/tftp/tftpsubs.c b/gpxe/contrib/tftp/tftpsubs.c deleted file mode 100644 index 608d64ec..00000000 --- a/gpxe/contrib/tftp/tftpsubs.c +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright (c) 1983 Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by the University of California, Berkeley. The name of the - * University may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ - -#ifndef lint -static char sccsid[] = "@(#)tftpsubs.c 5.4 (Berkeley) 6/29/88"; -#endif /* not lint */ - -/* Simple minded read-ahead/write-behind subroutines for tftp user and - server. Written originally with multiple buffers in mind, but current - implementation has two buffer logic wired in. - - Todo: add some sort of final error check so when the write-buffer - is finally flushed, the caller can detect if the disk filled up - (or had an i/o error) and return a nak to the other side. - - Jim Guyton 10/85 - */ - -#include <errno.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/ioctl.h> -#include <netinet/in.h> -#include <arpa/tftp.h> -#include <stdio.h> - -#define PKTSIZE (1432+4) /* SEGSIZE+4 */ /* should be moved to tftp.h */ - -struct bf { - int counter; /* size of data in buffer, or flag */ - char buf[PKTSIZE]; /* room for data packet */ -} bfs[2]; - - /* 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 */ - -extern int segsize; - -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) */ - -struct tftphdr *rw_init(); - -struct tftphdr *w_init() { return rw_init(0); } /* write-behind */ -struct tftphdr *r_init() { return rw_init(1); } /* read-ahead */ - -struct tftphdr * -rw_init(x) /* init for either read-ahead or write-behind */ -int x; /* zero for write-behind, one for read-head */ -{ - 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. - */ -readit(file, dpp, convert) - FILE *file; /* file opened for read */ - struct tftphdr **dpp; - int convert; /* if true, convert to ascii */ -{ - struct bf *b; - - 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; -} - -/* - * fill the input buffer, doing ascii conversions if requested - * conversions are lf -> cr,lf and cr -> cr, nul - */ -read_ahead(file, convert) - FILE *file; /* file opened for read */ - int convert; /* if true, convert to ascii */ -{ - register int i; - register char *p; - register 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) { - int i; - b->counter = 0; - do { - i = read(fileno(file), dp->th_data + b->counter, - segsize - b->counter); - if (i > 0) - b->counter += i; - } while (i != 0 && !(i < 0 && errno != EINTR) && - b->counter < 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. - */ -writeit(file, dpp, ct, convert) - FILE *file; - struct tftphdr **dpp; - 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 */ - 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 */ -} - -/* - * Output a buffer to a file, converting from netascii if requested. - * CR,NUL -> CR and CR,LF => LF. - * 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. - */ -write_behind(file, convert) - FILE *file; - int convert; -{ - char *buf; - int count; - register int ct; - register char *p; - register 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. - * - * So, to try to prevent that, we flush all the input queued up - * for us on the network connection on our host. - * - * We return the number of packets we flushed (mostly for reporting - * when trace is active). - */ - -int -synchnet(f) -int f; /* socket to flush */ -{ - int i, j = 0; - char rbuf[PKTSIZE]; - struct sockaddr_in from; - int fromlen; - - while (1) { - (void) ioctl(f, FIONREAD, &i); - if (i) { - j++; - fromlen = sizeof from; - (void) recvfrom(f, rbuf, sizeof (rbuf), 0, - (struct sockaddr *)&from, &fromlen); - } else { - return(j); - } - } -} |