From 4f51ffc3fede007b2d1c6ce56bdf217f700eb1c7 Mon Sep 17 00:00:00 2001 From: ume Date: Thu, 11 Apr 2002 17:14:22 +0000 Subject: IPv6 support for tftp/tftpd. Obtained from: KAME MFC after: 2 weeks --- usr.bin/tftp/main.c | 167 ++++++++++++++++++++++++++++------------------------ 1 file changed, 91 insertions(+), 76 deletions(-) (limited to 'usr.bin/tftp/main.c') 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); } } -- cgit v1.1