summaryrefslogtreecommitdiffstats
path: root/usr.bin/tftp/main.c
diff options
context:
space:
mode:
authorume <ume@FreeBSD.org>2002-04-11 17:14:22 +0000
committerume <ume@FreeBSD.org>2002-04-11 17:14:22 +0000
commit4f51ffc3fede007b2d1c6ce56bdf217f700eb1c7 (patch)
tree17221edddfe751134988e362f0829a38aa1ab240 /usr.bin/tftp/main.c
parentf8786d960f554dc901bb184a3bf33ca3ebf0eea2 (diff)
downloadFreeBSD-src-4f51ffc3fede007b2d1c6ce56bdf217f700eb1c7.zip
FreeBSD-src-4f51ffc3fede007b2d1c6ce56bdf217f700eb1c7.tar.gz
IPv6 support for tftp/tftpd.
Obtained from: KAME MFC after: 2 weeks
Diffstat (limited to 'usr.bin/tftp/main.c')
-rw-r--r--usr.bin/tftp/main.c167
1 files changed, 91 insertions, 76 deletions
diff --git a/usr.bin/tftp/main.c b/usr.bin/tftp/main.c
index 38b376c..251abf5 100644
--- a/usr.bin/tftp/main.c
+++ b/usr.bin/tftp/main.c
@@ -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) {
@@ -187,11 +175,78 @@ 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);
}
}
OpenPOWER on IntegriCloud