IPv6 support for tftp/tftpd.
Obtained from: KAME MFC after: 2 weeks
This commit is contained in:
parent
0d36f49e63
commit
4dac6235cf
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=94443
@ -88,10 +88,11 @@ int max_rexmtval = 2*TIMEOUT;
|
||||
#define PKTSIZE SEGSIZE+4
|
||||
char buf[PKTSIZE];
|
||||
char ackbuf[PKTSIZE];
|
||||
struct sockaddr_in from;
|
||||
struct sockaddr_storage from;
|
||||
int fromlen;
|
||||
|
||||
void tftp(struct tftphdr *, int);
|
||||
static void unmappedaddr(struct sockaddr_in6 *);
|
||||
|
||||
/*
|
||||
* Null-terminated directory prefix list for absolute pathname requests and
|
||||
@ -119,7 +120,8 @@ main(int argc, char *argv[])
|
||||
struct tftphdr *tp;
|
||||
int n;
|
||||
int ch, on;
|
||||
struct sockaddr_in sin;
|
||||
struct sockaddr_storage me;
|
||||
int len;
|
||||
char *chroot_dir = NULL;
|
||||
struct passwd *nobody;
|
||||
char *chuser = "nobody";
|
||||
@ -244,9 +246,15 @@ main(int argc, char *argv[])
|
||||
char *tempchroot;
|
||||
struct stat sb;
|
||||
int statret;
|
||||
struct sockaddr_storage ss;
|
||||
char hbuf[NI_MAXHOST];
|
||||
|
||||
tempchroot = inet_ntoa(from.sin_addr);
|
||||
asprintf(&tempchroot, "%s/%s", chroot_dir, tempchroot);
|
||||
memcpy(&ss, &from, from.ss_len);
|
||||
unmappedaddr((struct sockaddr_in6 *)&ss);
|
||||
getnameinfo((struct sockaddr *)&ss, ss.ss_len,
|
||||
hbuf, sizeof(hbuf), NULL, 0,
|
||||
NI_NUMERICHOST | NI_WITHSCOPEID);
|
||||
asprintf(&tempchroot, "%s/%s", chroot_dir, hbuf);
|
||||
statret = stat(tempchroot, &sb);
|
||||
if ((sb.st_mode & S_IFDIR) &&
|
||||
(statret == 0 || (statret == -1 && ipchroot == 1)))
|
||||
@ -266,22 +274,37 @@ main(int argc, char *argv[])
|
||||
setgroups(1, &nobody->pw_gid);
|
||||
}
|
||||
|
||||
from.sin_family = AF_INET;
|
||||
len = sizeof(me);
|
||||
if (getsockname(0, (struct sockaddr *)&me, &len) == 0) {
|
||||
switch (me.ss_family) {
|
||||
case AF_INET:
|
||||
((struct sockaddr_in *)&me)->sin_port = 0;
|
||||
break;
|
||||
case AF_INET6:
|
||||
((struct sockaddr_in6 *)&me)->sin6_port = 0;
|
||||
break;
|
||||
default:
|
||||
/* unsupported */
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
memset(&me, 0, sizeof(me));
|
||||
me.ss_family = from.ss_family;
|
||||
me.ss_len = from.ss_len;
|
||||
}
|
||||
alarm(0);
|
||||
close(0);
|
||||
close(1);
|
||||
peer = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
peer = socket(from.ss_family, SOCK_DGRAM, 0);
|
||||
if (peer < 0) {
|
||||
syslog(LOG_ERR, "socket: %m");
|
||||
exit(1);
|
||||
}
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_family = AF_INET;
|
||||
if (bind(peer, (struct sockaddr *)&sin, sizeof (sin)) < 0) {
|
||||
if (bind(peer, (struct sockaddr *)&me, me.ss_len) < 0) {
|
||||
syslog(LOG_ERR, "bind: %m");
|
||||
exit(1);
|
||||
}
|
||||
if (connect(peer, (struct sockaddr *)&from, sizeof(from)) < 0) {
|
||||
if (connect(peer, (struct sockaddr *)&from, from.ss_len) < 0) {
|
||||
syslog(LOG_ERR, "connect: %m");
|
||||
exit(1);
|
||||
}
|
||||
@ -406,11 +429,12 @@ tftp(struct tftphdr *tp, int size)
|
||||
if (has_options)
|
||||
oack();
|
||||
if (logging) {
|
||||
char host[MAXHOSTNAMELEN];
|
||||
char hbuf[NI_MAXHOST];
|
||||
|
||||
realhostname(host, sizeof(host) - 1, &from.sin_addr);
|
||||
host[sizeof(host) - 1] = '\0';
|
||||
syslog(LOG_INFO, "%s: %s request for %s: %s", host,
|
||||
getnameinfo((struct sockaddr *)&from, from.ss_len,
|
||||
hbuf, sizeof(hbuf), NULL, 0,
|
||||
NI_WITHSCOPEID);
|
||||
syslog(LOG_INFO, "%s: %s request for %s: %s", hbuf,
|
||||
tp->th_opcode == WRQ ? "write" : "read",
|
||||
filename, errtomsg(ecode));
|
||||
}
|
||||
@ -766,6 +790,27 @@ nak(int error)
|
||||
syslog(LOG_ERR, "nak: %m");
|
||||
}
|
||||
|
||||
/* translate IPv4 mapped IPv6 address to IPv4 address */
|
||||
static void
|
||||
unmappedaddr(struct sockaddr_in6 *sin6)
|
||||
{
|
||||
struct sockaddr_in *sin4;
|
||||
u_int32_t addr;
|
||||
int port;
|
||||
|
||||
if (sin6->sin6_family != AF_INET6 ||
|
||||
!IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr))
|
||||
return;
|
||||
sin4 = (struct sockaddr_in *)sin6;
|
||||
addr = *(u_int32_t *)&sin6->sin6_addr.s6_addr[12];
|
||||
port = sin6->sin6_port;
|
||||
memset(sin4, 0, sizeof(struct sockaddr_in));
|
||||
sin4->sin_addr.s_addr = addr;
|
||||
sin4->sin_port = port;
|
||||
sin4->sin_family = AF_INET;
|
||||
sin4->sin_len = sizeof(struct sockaddr_in);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send an oack packet (option acknowledgement).
|
||||
*/
|
||||
|
@ -77,9 +77,8 @@ __FBSDID("$FreeBSD$");
|
||||
#define MAXLINE 200
|
||||
#define TIMEOUT 5 /* secs between rexmt's */
|
||||
|
||||
struct sockaddr_in peeraddr;
|
||||
struct sockaddr_storage peeraddr;
|
||||
int f;
|
||||
short port;
|
||||
int trace;
|
||||
int verbose;
|
||||
int connected;
|
||||
@ -88,7 +87,6 @@ char line[MAXLINE];
|
||||
int margc;
|
||||
char *margv[20];
|
||||
jmp_buf toplevel;
|
||||
struct servent *sp;
|
||||
|
||||
void get(int, char **);
|
||||
void help(int, char **);
|
||||
@ -98,6 +96,7 @@ void put(int, char **);
|
||||
void quit(int, char **);
|
||||
void setascii(int, char **);
|
||||
void setbinary(int, char **);
|
||||
void setpeer0(char *, char *);
|
||||
void setpeer(int, char **);
|
||||
void setrexmt(int, char **);
|
||||
void settimeout(int, char **);
|
||||
@ -160,18 +159,7 @@ main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
struct sockaddr_in lsin;
|
||||
|
||||
sp = getservbyname("tftp", "udp");
|
||||
if (sp == 0)
|
||||
errx(1, "udp/tftp: unknown service");
|
||||
f = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (f < 0)
|
||||
err(3, "socket");
|
||||
bzero((char *)&lsin, sizeof(lsin));
|
||||
lsin.sin_family = AF_INET;
|
||||
if (bind(f, (struct sockaddr *)&lsin, sizeof(lsin)) < 0)
|
||||
err(1, "bind");
|
||||
f = -1;
|
||||
strcpy(mode, "netascii");
|
||||
signal(SIGINT, intr);
|
||||
if (argc > 1) {
|
||||
@ -186,12 +174,79 @@ main(argc, argv)
|
||||
|
||||
char hostname[MAXHOSTNAMELEN];
|
||||
|
||||
void
|
||||
setpeer0(host, port)
|
||||
char *host;
|
||||
char *port;
|
||||
{
|
||||
struct addrinfo hints, *res0, *res;
|
||||
int error;
|
||||
struct sockaddr_storage ss;
|
||||
char *cause = "unknown";
|
||||
|
||||
if (connected) {
|
||||
close(f);
|
||||
f = -1;
|
||||
}
|
||||
connected = 0;
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = PF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_DGRAM;
|
||||
hints.ai_protocol = IPPROTO_UDP;
|
||||
hints.ai_flags = AI_CANONNAME;
|
||||
if (!port)
|
||||
port = "tftp";
|
||||
error = getaddrinfo(host, port, &hints, &res0);
|
||||
if (error) {
|
||||
warnx("%s", gai_strerror(error));
|
||||
return;
|
||||
}
|
||||
|
||||
for (res = res0; res; res = res->ai_next) {
|
||||
if (res->ai_addrlen > sizeof(peeraddr))
|
||||
continue;
|
||||
f = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
|
||||
if (f < 0) {
|
||||
cause = "socket";
|
||||
continue;
|
||||
}
|
||||
|
||||
memset(&ss, 0, sizeof(ss));
|
||||
ss.ss_family = res->ai_family;
|
||||
ss.ss_len = res->ai_addrlen;
|
||||
if (bind(f, (struct sockaddr *)&ss, ss.ss_len) < 0) {
|
||||
cause = "bind";
|
||||
close(f);
|
||||
f = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (f < 0)
|
||||
warn("%s", cause);
|
||||
else {
|
||||
/* res->ai_addr <= sizeof(peeraddr) is guaranteed */
|
||||
memcpy(&peeraddr, res->ai_addr, res->ai_addrlen);
|
||||
if (res->ai_canonname) {
|
||||
(void) strncpy(hostname, res->ai_canonname,
|
||||
sizeof(hostname));
|
||||
} else
|
||||
(void) strncpy(hostname, host, sizeof(hostname));
|
||||
hostname[sizeof(hostname)-1] = 0;
|
||||
connected = 1;
|
||||
}
|
||||
|
||||
freeaddrinfo(res0);
|
||||
}
|
||||
|
||||
void
|
||||
setpeer(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
struct hostent *host;
|
||||
|
||||
if (argc < 2) {
|
||||
strcpy(line, "Connect ");
|
||||
@ -205,34 +260,10 @@ setpeer(argc, argv)
|
||||
printf("usage: %s host-name [port]\n", argv[0]);
|
||||
return;
|
||||
}
|
||||
host = gethostbyname(argv[1]);
|
||||
if (host) {
|
||||
peeraddr.sin_family = host->h_addrtype;
|
||||
bcopy(host->h_addr, &peeraddr.sin_addr,
|
||||
MIN(sizeof(peeraddr.sin_addr), (size_t)host->h_length));
|
||||
strncpy(hostname, host->h_name, sizeof(hostname));
|
||||
} else {
|
||||
peeraddr.sin_family = AF_INET;
|
||||
peeraddr.sin_addr.s_addr = inet_addr(argv[1]);
|
||||
if (peeraddr.sin_addr.s_addr == INADDR_NONE) {
|
||||
connected = 0;
|
||||
printf("%s: unknown host\n", argv[1]);
|
||||
return;
|
||||
}
|
||||
strncpy(hostname, argv[1], sizeof(hostname));
|
||||
}
|
||||
hostname[sizeof(hostname) - 1] = '\0';
|
||||
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;
|
||||
if (argc == 3)
|
||||
setpeer0(argv[1], NULL);
|
||||
else
|
||||
setpeer0(argv[1], argv[2]);
|
||||
}
|
||||
|
||||
struct modes {
|
||||
@ -336,9 +367,8 @@ put(argc, argv)
|
||||
return;
|
||||
}
|
||||
targ = argv[argc - 1];
|
||||
if (index(argv[argc - 1], ':')) {
|
||||
if (rindex(argv[argc - 1], ':')) {
|
||||
char *lcp;
|
||||
struct hostent *hp;
|
||||
|
||||
for (n = 1; n < argc - 1; n++)
|
||||
if (index(argv[n], ':')) {
|
||||
@ -346,20 +376,13 @@ put(argc, argv)
|
||||
return;
|
||||
}
|
||||
lcp = argv[argc - 1];
|
||||
targ = index(lcp, ':');
|
||||
targ = rindex(lcp, ':');
|
||||
*targ++ = 0;
|
||||
hp = gethostbyname(lcp);
|
||||
if (hp == NULL) {
|
||||
fprintf(stderr, "tftp: %s: ", lcp);
|
||||
herror((char *)NULL);
|
||||
return;
|
||||
if (lcp[0] == '[' && lcp[strlen(lcp) - 1] == ']') {
|
||||
lcp[strlen(lcp) - 1] = '\0';
|
||||
lcp++;
|
||||
}
|
||||
bcopy(hp->h_addr, (caddr_t)&peeraddr.sin_addr,
|
||||
MIN(sizeof(peeraddr.sin_addr), (size_t)hp->h_length));
|
||||
peeraddr.sin_family = hp->h_addrtype;
|
||||
connected = 1;
|
||||
strncpy(hostname, hp->h_name, sizeof(hostname));
|
||||
hostname[sizeof(hostname) - 1] = '\0';
|
||||
setpeer0(lcp, NULL);
|
||||
}
|
||||
if (!connected) {
|
||||
printf("No target machine specified.\n");
|
||||
@ -375,7 +398,6 @@ put(argc, argv)
|
||||
if (verbose)
|
||||
printf("putting %s to %s:%s [%s]\n",
|
||||
cp, hostname, targ, mode);
|
||||
peeraddr.sin_port = port;
|
||||
xmitfile(fd, targ, mode);
|
||||
return;
|
||||
}
|
||||
@ -393,7 +415,6 @@ put(argc, argv)
|
||||
if (verbose)
|
||||
printf("putting %s to %s:%s [%s]\n",
|
||||
argv[n], hostname, targ, mode);
|
||||
peeraddr.sin_port = port;
|
||||
xmitfile(fd, targ, mode);
|
||||
}
|
||||
}
|
||||
@ -433,31 +454,27 @@ get(argc, argv)
|
||||
}
|
||||
if (!connected) {
|
||||
for (n = 1; n < argc ; n++)
|
||||
if (index(argv[n], ':') == 0) {
|
||||
if (rindex(argv[n], ':') == 0) {
|
||||
getusage(argv[0]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (n = 1; n < argc ; n++) {
|
||||
src = index(argv[n], ':');
|
||||
src = rindex(argv[n], ':');
|
||||
if (src == NULL)
|
||||
src = argv[n];
|
||||
else {
|
||||
struct hostent *hp;
|
||||
char *lcp;
|
||||
|
||||
*src++ = 0;
|
||||
hp = gethostbyname(argv[n]);
|
||||
if (hp == NULL) {
|
||||
fprintf(stderr, "tftp: %s: ", argv[n]);
|
||||
herror((char *)NULL);
|
||||
continue;
|
||||
lcp = argv[n];
|
||||
if (lcp[0] == '[' && lcp[strlen(lcp) - 1] == ']') {
|
||||
lcp[strlen(lcp) - 1] = '\0';
|
||||
lcp++;
|
||||
}
|
||||
bcopy(hp->h_addr, (caddr_t)&peeraddr.sin_addr,
|
||||
MIN(sizeof(peeraddr.sin_addr), (size_t)hp->h_length));
|
||||
peeraddr.sin_family = hp->h_addrtype;
|
||||
connected = 1;
|
||||
strncpy(hostname, hp->h_name, sizeof(hostname));
|
||||
hostname[sizeof(hostname) - 1] = '\0';
|
||||
setpeer0(lcp, NULL);
|
||||
if (!connected)
|
||||
continue;
|
||||
}
|
||||
if (argc < 4) {
|
||||
cp = argc == 3 ? argv[2] : tail(src);
|
||||
@ -469,7 +486,6 @@ get(argc, argv)
|
||||
if (verbose)
|
||||
printf("getting from %s:%s to %s [%s]\n",
|
||||
hostname, src, cp, mode);
|
||||
peeraddr.sin_port = port;
|
||||
recvfile(fd, src, mode);
|
||||
break;
|
||||
}
|
||||
@ -482,7 +498,6 @@ get(argc, argv)
|
||||
if (verbose)
|
||||
printf("getting from %s:%s to %s [%s]\n",
|
||||
hostname, src, cp, mode);
|
||||
peeraddr.sin_port = port;
|
||||
recvfile(fd, src, mode);
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
.\" Copyright (c) 1990, 1993, 1994
|
||||
.\" $NetBSD: tftp.1,v 1.11 1999/12/13 04:44:55 itojun Exp $
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
@ -137,6 +137,11 @@ If the remote-directory form is used, the remote host is
|
||||
assumed to be a
|
||||
.Tn UNIX
|
||||
machine.
|
||||
If you need to specify IPv6 numeric address to
|
||||
.Ar hosts ,
|
||||
wrap them using square bracket like
|
||||
.Ar [hosts]:filename
|
||||
to disambiguate the colon.
|
||||
.Pp
|
||||
.It Cm quit
|
||||
Exit
|
||||
|
@ -61,11 +61,12 @@ __FBSDID("$FreeBSD$");
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#include "extern.h"
|
||||
#include "tftpsubs.h"
|
||||
|
||||
extern struct sockaddr_in peeraddr; /* filled in by main */
|
||||
extern struct sockaddr_storage peeraddr; /* filled in by main */
|
||||
extern int f; /* the opened socket */
|
||||
extern int trace;
|
||||
extern int verbose;
|
||||
@ -78,13 +79,14 @@ int timeout;
|
||||
jmp_buf toplevel;
|
||||
jmp_buf timeoutbuf;
|
||||
|
||||
static void nak(int);
|
||||
static void nak(int, struct sockaddr *);
|
||||
static int makerequest(int, const char *, struct tftphdr *, const char *);
|
||||
static void printstats(const char *, unsigned long);
|
||||
static void startclock(void);
|
||||
static void stopclock(void);
|
||||
static void timer(int);
|
||||
static void tpacket(const char *, struct tftphdr *, int);
|
||||
static int cmpport(struct sockaddr *, struct sockaddr *);
|
||||
|
||||
/*
|
||||
* Send the requested file.
|
||||
@ -101,9 +103,11 @@ xmitfile(fd, name, mode)
|
||||
volatile unsigned short block;
|
||||
volatile int size, convert;
|
||||
volatile unsigned long amount;
|
||||
struct sockaddr_in from;
|
||||
struct sockaddr_storage from;
|
||||
int fromlen;
|
||||
FILE *file;
|
||||
struct sockaddr_storage peer;
|
||||
struct sockaddr_storage serv; /* valid server port number */
|
||||
|
||||
startclock(); /* start stat's clock */
|
||||
dp = r_init(); /* reset fillbuf/read-ahead code */
|
||||
@ -112,6 +116,8 @@ xmitfile(fd, name, mode)
|
||||
convert = !strcmp(mode, "netascii");
|
||||
block = 0;
|
||||
amount = 0;
|
||||
memcpy(&peer, &peeraddr, peeraddr.ss_len);
|
||||
memset(&serv, 0, sizeof(serv));
|
||||
|
||||
signal(SIGALRM, timer);
|
||||
do {
|
||||
@ -121,7 +127,7 @@ xmitfile(fd, name, mode)
|
||||
/* size = read(fd, dp->th_data, SEGSIZE); */
|
||||
size = readit(file, &dp, convert);
|
||||
if (size < 0) {
|
||||
nak(errno + 100);
|
||||
nak(errno + 100, (struct sockaddr *)&peer);
|
||||
break;
|
||||
}
|
||||
dp->th_opcode = htons((u_short)DATA);
|
||||
@ -133,7 +139,7 @@ xmitfile(fd, name, mode)
|
||||
if (trace)
|
||||
tpacket("sent", dp, size + 4);
|
||||
n = sendto(f, dp, size + 4, 0,
|
||||
(struct sockaddr *)&peeraddr, sizeof(peeraddr));
|
||||
(struct sockaddr *)&peer, peer.ss_len);
|
||||
if (n != size + 4) {
|
||||
warn("sendto");
|
||||
goto abort;
|
||||
@ -151,7 +157,14 @@ xmitfile(fd, name, mode)
|
||||
warn("recvfrom");
|
||||
goto abort;
|
||||
}
|
||||
peeraddr.sin_port = from.sin_port; /* added */
|
||||
if (!serv.ss_family)
|
||||
serv = from;
|
||||
else if (!cmpport((struct sockaddr *)&serv,
|
||||
(struct sockaddr *)&from)) {
|
||||
warn("server port mismatch");
|
||||
goto abort;
|
||||
}
|
||||
peer = from;
|
||||
if (trace)
|
||||
tpacket("received", ap, n);
|
||||
/* should verify packet came from server */
|
||||
@ -207,10 +220,12 @@ recvfile(fd, name, mode)
|
||||
volatile unsigned short block;
|
||||
volatile int size, firsttrip;
|
||||
volatile unsigned long amount;
|
||||
struct sockaddr_in from;
|
||||
struct sockaddr_storage from;
|
||||
int fromlen;
|
||||
FILE *file;
|
||||
volatile int convert; /* true if converting crlf -> lf */
|
||||
struct sockaddr_storage peer;
|
||||
struct sockaddr_storage serv; /* valid server port number */
|
||||
|
||||
startclock();
|
||||
dp = w_init();
|
||||
@ -220,6 +235,8 @@ recvfile(fd, name, mode)
|
||||
block = 1;
|
||||
firsttrip = 1;
|
||||
amount = 0;
|
||||
memcpy(&peer, &peeraddr, peeraddr.ss_len);
|
||||
memset(&serv, 0, sizeof(serv));
|
||||
|
||||
signal(SIGALRM, timer);
|
||||
do {
|
||||
@ -237,8 +254,8 @@ recvfile(fd, name, mode)
|
||||
send_ack:
|
||||
if (trace)
|
||||
tpacket("sent", ap, size);
|
||||
if (sendto(f, ackbuf, size, 0, (struct sockaddr *)&peeraddr,
|
||||
sizeof(peeraddr)) != size) {
|
||||
if (sendto(f, ackbuf, size, 0, (struct sockaddr *)&peer,
|
||||
peer.ss_len) != size) {
|
||||
alarm(0);
|
||||
warn("sendto");
|
||||
goto abort;
|
||||
@ -256,7 +273,14 @@ recvfile(fd, name, mode)
|
||||
warn("recvfrom");
|
||||
goto abort;
|
||||
}
|
||||
peeraddr.sin_port = from.sin_port; /* added */
|
||||
if (!serv.ss_family)
|
||||
serv = from;
|
||||
else if (!cmpport((struct sockaddr *)&serv,
|
||||
(struct sockaddr *)&from)) {
|
||||
warn("server port mismatch");
|
||||
goto abort;
|
||||
}
|
||||
peer = from;
|
||||
if (trace)
|
||||
tpacket("received", dp, n);
|
||||
/* should verify client address */
|
||||
@ -288,7 +312,7 @@ recvfile(fd, name, mode)
|
||||
/* size = write(fd, dp->th_data, n - 4); */
|
||||
size = writeit(file, &dp, n - 4, convert);
|
||||
if (size < 0) {
|
||||
nak(errno + 100);
|
||||
nak(errno + 100, (struct sockaddr *)&peer);
|
||||
break;
|
||||
}
|
||||
amount += size;
|
||||
@ -296,8 +320,8 @@ recvfile(fd, name, mode)
|
||||
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));
|
||||
(void) sendto(f, ackbuf, 4, 0, (struct sockaddr *)&peer,
|
||||
peer.ss_len);
|
||||
write_behind(file, convert); /* flush last buffer */
|
||||
fclose(file);
|
||||
stopclock();
|
||||
@ -347,8 +371,9 @@ struct errmsg {
|
||||
* offset by 100.
|
||||
*/
|
||||
static void
|
||||
nak(error)
|
||||
nak(error, peer)
|
||||
int error;
|
||||
struct sockaddr *peer;
|
||||
{
|
||||
struct errmsg *pe;
|
||||
struct tftphdr *tp;
|
||||
@ -368,8 +393,7 @@ nak(error)
|
||||
length = strlen(pe->e_msg) + 4;
|
||||
if (trace)
|
||||
tpacket("sent", tp, length);
|
||||
if (sendto(f, ackbuf, length, 0, (struct sockaddr *)&peeraddr,
|
||||
sizeof(peeraddr)) != length)
|
||||
if (sendto(f, ackbuf, length, 0, peer, peer->sa_len) != length)
|
||||
warn("nak");
|
||||
}
|
||||
|
||||
@ -457,3 +481,20 @@ timer(sig)
|
||||
}
|
||||
longjmp(timeoutbuf, 1);
|
||||
}
|
||||
|
||||
static int
|
||||
cmpport(sa, sb)
|
||||
struct sockaddr *sa;
|
||||
struct sockaddr *sb;
|
||||
{
|
||||
char a[NI_MAXSERV], b[NI_MAXSERV];
|
||||
|
||||
if (getnameinfo(sa, sa->sa_len, NULL, 0, a, sizeof(a), NI_NUMERICSERV))
|
||||
return 0;
|
||||
if (getnameinfo(sb, sb->sa_len, NULL, 0, b, sizeof(b), NI_NUMERICSERV))
|
||||
return 0;
|
||||
if (strcmp(a, b) != 0)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -260,7 +260,7 @@ synchnet(f)
|
||||
{
|
||||
int i, j = 0;
|
||||
char rbuf[PKTSIZE];
|
||||
struct sockaddr_in from;
|
||||
struct sockaddr_storage from;
|
||||
int fromlen;
|
||||
|
||||
while (1) {
|
||||
|
Loading…
Reference in New Issue
Block a user