X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/d3fc13cc89622cbc1941d369adb37a136674c994..b041ccece3687baa46a947a5695b634ef113edfd:/usr/src/usr.bin/tftp/tftp.c diff --git a/usr/src/usr.bin/tftp/tftp.c b/usr/src/usr.bin/tftp/tftp.c index e55d0a589e..e1a7e76483 100644 --- a/usr/src/usr.bin/tftp/tftp.c +++ b/usr/src/usr.bin/tftp/tftp.c @@ -1,36 +1,52 @@ -/* tftp.c 4.1 82/08/16 */ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. The Berkeley software License Agreement + * specifies the terms and conditions for redistribution. + */ + +#ifndef lint +static char sccsid[] = "@(#)tftp.c 5.1 (Berkeley) %G%"; +#endif not lint /* * TFTP User Program -- Protocol Machines */ #include -#include #include + +#include +#include +#include + #include #include #include #include -#include "tftp.h" +#include extern int errno; extern struct sockaddr_in sin; extern char mode[]; int f; int trace; -int verbose; int connected; -char buf[BUFSIZ]; +char sbuf[BUFSIZ]; /* send buffer */ +char rbuf[BUFSIZ]; /* receive buffer */ +int rexmtval; +int maxtimeout; int timeout; jmp_buf toplevel; +jmp_buf timeoutbuf; timer() { - timeout += TIMEOUT; - if (timeout >= MAXTIMEOUT) { + + timeout += rexmtval; + if (timeout >= maxtimeout) { printf("Transfer timed out.\n"); longjmp(toplevel, -1); } - alarm(TIMEOUT); + longjmp(timeoutbuf, 1); } /* @@ -40,67 +56,86 @@ sendfile(fd, name) int fd; char *name; { - register struct tftphdr *tp = (struct tftphdr *)buf; + register struct tftphdr *stp = (struct tftphdr *)sbuf; + register struct tftphdr *rtp = (struct tftphdr *)rbuf; register int block = 0, size, n, amount = 0; - struct sockaddr_in from; + struct sockaddr_in from, to; time_t start = time(0), delta; + int fromlen, aborted = 0; - size = makerequest(WRQ, name) - 4; - sigset(SIGALRM, timer); + to = sin; + signal(SIGALRM, timer); do { - if (block != 0) { - size = read(fd, tp->th_data, SEGSIZE); + if (block == 0) + size = makerequest(WRQ, name) - 4; + else { + size = read(fd, stp->th_data, SEGSIZE); if (size < 0) { - nak(errno + 100); + nak(&to, errno + 100); break; } - tp->th_opcode = htons((u_short)DATA); - tp->th_block = htons((u_short)block); + stp->th_opcode = htons((u_short)DATA); + stp->th_block = htons((u_short)block); } timeout = 0; - alarm(TIMEOUT); -rexmt: + (void) setjmp(timeoutbuf); if (trace) - tpacket("sent", tp, size + 4); - if (send(f, &sin, buf, size + 4) != size + 4) { - perror("send"); - break; + tpacket("sent", &to, stp, size + 4); + n = sendto(f, sbuf, size + 4, 0, (caddr_t)&to, sizeof (to)); + if (n != size + 4) { + perror("tftp: sendto"); + aborted = 1; + goto done; } + do { again: - n = receive(f, &from, buf, sizeof (buf)); - if (n <= 0) { - if (n == 0) - goto again; - if (errno == EINTR) - goto rexmt; + alarm(rexmtval); + do { + fromlen = sizeof (from); + n = recvfrom(f, rbuf, sizeof (rbuf), 0, + (caddr_t)&from, &fromlen); + } while (n <= 0); alarm(0); - perror("receive"); - break; - } - alarm(0); - if (trace) - tpacket("received", tp, n); -#if vax || pdp11 - tp->th_opcode = ntohs(tp->th_opcode); - tp->th_block = ntohs(tp->th_block); -#endif - if (tp->th_opcode == ERROR) { - printf("Error code %d: %s\n", tp->th_code, - tp->th_msg); - break; - } - if (tp->th_opcode != ACK || block != tp->th_block) - goto again; + if (n < 0) { + perror("tftp: recvfrom"); + aborted = 1; + goto done; + } + if (to.sin_addr.s_addr != from.sin_addr.s_addr) { + tpacket("discarded (wrong host)", + &from, rtp, n); + goto again; + } + if (to.sin_port = sin.sin_port) + to.sin_port = from.sin_port; + if (to.sin_port != from.sin_port) { + tpacket("discarded (wrong port)", + &from, rtp, n); + goto again; + } + if (trace) + tpacket("received", &from, rtp, n); + /* should verify packet came from server */ + rtp->th_opcode = ntohs(rtp->th_opcode); + rtp->th_block = ntohs(rtp->th_block); + if (rtp->th_opcode == ERROR) { + printf("Error code %d: %s\n", rtp->th_code, + rtp->th_msg); + aborted = 1; + goto done; + } + } while (rtp->th_opcode != ACK && block != rtp->th_block); if (block > 0) amount += size; block++; } while (size == SEGSIZE || block == 1); - alarm(0); - (void) close(fd); - if (amount > 0) { + if (!aborted && amount > 0) { delta = time(0) - start; printf("Sent %d bytes in %d seconds.\n", amount, delta); } +done: + (void) close(fd); + return (aborted); } /* @@ -110,90 +145,112 @@ recvfile(fd, name) int fd; char *name; { - register struct tftphdr *tp = (struct tftphdr *)buf; + register struct tftphdr *stp = (struct tftphdr *)sbuf; + register struct tftphdr *rtp = (struct tftphdr *)rbuf; register int block = 1, n, size, amount = 0; - struct sockaddr_in from; + struct sockaddr_in from, to; time_t start = time(0), delta; + int fromlen, firsttrip = 1, aborted = 0; - size = makerequest(RRQ, name); - sigset(SIGALRM, timer); - alarm(TIMEOUT); - goto rexmt; + to = sin; + signal(SIGALRM, timer); do { + if (firsttrip) { + size = makerequest(RRQ, name); + firsttrip = 0; + } else { + stp->th_opcode = htons((u_short)ACK); + stp->th_block = htons((u_short)(block)); + size = 4; + block++; + } timeout = 0; - alarm(TIMEOUT); - tp->th_opcode = htons((u_short)ACK); - tp->th_block = htons((u_short)(block)); - size = 4; - block++; -rexmt: + (void) setjmp(timeoutbuf); if (trace) - tpacket("sent", tp, size); - if (send(f, &sin, buf, size) != size) { - perror("send"); - break; + tpacket("sent", &to, stp, size); + if (sendto(f, sbuf, size, 0, (caddr_t)&to, + sizeof (to)) != size) { + alarm(0); + perror("tftp: sendto"); + aborted = 1; + goto done; } + do { again: - n = receive(f, &from, buf, sizeof (buf)); - if (n <= 0) { - if (n == 0) - goto again; - if (errno == EINTR) - goto rexmt; + alarm(rexmtval); + do { + fromlen = sizeof (from); + n = recvfrom(f, rbuf, sizeof (rbuf), 0, + (caddr_t)&from, &fromlen); + } while (n <= 0); alarm(0); - perror("receive"); - break; - } - alarm(0); - if (trace) - tpacket("received", tp, n); -#if vax || pdp11 - tp->th_opcode = ntohs(tp->th_opcode); - tp->th_block = ntohs(tp->th_block); -#endif - if (tp->th_opcode == ERROR) { - printf("Error code %d: %s\n", tp->th_code, - tp->th_msg); - break; - } - if (tp->th_opcode != DATA || block != tp->th_block) - goto again; - size = write(fd, tp->th_data, n - 4); + if (n < 0) { + perror("tftp: recvfrom"); + aborted = 1; + goto done; + } + if (to.sin_addr.s_addr != from.sin_addr.s_addr) { + tpacket("discarded (wrong host)", + &from, rtp, n); + goto again; + } + if (to.sin_port = sin.sin_port) + to.sin_port = from.sin_port; + if (to.sin_port != from.sin_port) { + tpacket("discarded (wrong port)", + &from, rtp, n); + goto again; + } + if (trace) + tpacket("received", &from, rtp, n); + rtp->th_opcode = ntohs(rtp->th_opcode); + rtp->th_block = ntohs(rtp->th_block); + if (rtp->th_opcode == ERROR) { + printf("Error code %d: %s\n", rtp->th_code, + rtp->th_msg); + aborted = 1; + goto done; + } + } while (rtp->th_opcode != DATA && rtp->th_block != block); + size = write(fd, rtp->th_data, n - 4); if (size < 0) { - nak(errno + 100); - break; + perror("tftp: write"); + nak(&to, errno + 100); + aborted = 1; + goto done; } amount += size; } while (size == SEGSIZE); - alarm(0); - tp->th_opcode = htons((u_short)ACK); - tp->th_block = htons((u_short)block); - (void) send(f, &sin, buf, 4); +done: + stp->th_opcode = htons((u_short)ACK); + stp->th_block = htons((u_short)block); + (void) sendto(f, sbuf, 4, 0, &to, sizeof (to)); (void) close(fd); - if (amount > 0) { + if (!aborted && amount > 0) { delta = time(0) - start; printf("Received %d bytes in %d seconds.\n", amount, delta); } + return (aborted); } makerequest(request, name) int request; char *name; { - register struct tftphdr *tp; + register struct tftphdr *stp; int size; register char *cp; - tp = (struct tftphdr *)buf; - tp->th_opcode = htons((u_short)request); - strcpy(tp->th_stuff, name); + stp = (struct tftphdr *)sbuf; + stp->th_opcode = htons((u_short)request); + strcpy(stp->th_stuff, name); size = strlen(name); - cp = tp->th_stuff + strlen(name); + cp = stp->th_stuff + strlen(name); *cp++ = '\0'; strcpy(cp, mode); cp += sizeof ("netascii") - 1; *cp++ = '\0'; - return (cp - buf); + return (cp - sbuf); } struct errmsg { @@ -217,31 +274,33 @@ struct errmsg { * standard TFTP codes, or a UNIX errno * offset by 100. */ -nak(error) +nak(to, error) + struct sockaddr_in *to; int error; { - register struct tftphdr *tp; + register struct tftphdr *stp; 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); + stp = (struct tftphdr *)sbuf; + stp->th_opcode = htons((u_short)ERROR); + stp->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]; - strcpy(tp->th_msg, pe->e_msg); + strcpy(stp->th_msg, pe->e_msg); length = strlen(pe->e_msg) + 4; if (trace) - tpacket("sent", tp, length); - if (send(f, &sin, buf, length) != length) - perror("nak"); + tpacket("sent", to, stp, length); + if (sendto(f, sbuf, length, 0, to, sizeof (*to)) != length) + perror("tftp: nak"); } -tpacket(s, tp, n) +tpacket(s, sin, tp, n) + struct sockaddr_in *sin; struct tftphdr *tp; int n; { @@ -251,10 +310,19 @@ tpacket(s, tp, n) u_short op = ntohs(tp->th_opcode); char *index(); + printf("%s ", s); + if (sin) { + struct hostent *hp = gethostbyaddr(&sin->sin_addr, + sizeof (sin->sin_addr), AF_INET); + + printf("%s.%d ", + hp == 0 ? inet_ntoa(sin->sin_addr) : hp->h_name, + ntohs(sin->sin_port)); + } if (op < RRQ || op > ERROR) - printf("%s opcode=%x ", s, op); + printf("opcode=%x ", op); else - printf("%s %s ", s, opcodes[op]); + printf("%s ", opcodes[op]); switch (op) { case RRQ: @@ -276,5 +344,9 @@ tpacket(s, tp, n) case ERROR: printf("\n", ntohs(tp->th_code), tp->th_msg); break; + + default: + putchar('\n'); + break; } }