summaryrefslogtreecommitdiffstats
path: root/usr.bin/ftp
diff options
context:
space:
mode:
authorume <ume@FreeBSD.org>2000-06-14 15:26:58 +0000
committerume <ume@FreeBSD.org>2000-06-14 15:26:58 +0000
commit345437204c9f40bac859c949ec6da7010752a955 (patch)
tree97fb8a05d4265e0625d09e1a1918b74677698976 /usr.bin/ftp
parentece5849f312613df8590b3dd4967f16fdbdf977f (diff)
downloadFreeBSD-src-345437204c9f40bac859c949ec6da7010752a955.zip
FreeBSD-src-345437204c9f40bac859c949ec6da7010752a955.tar.gz
Make sure to use native IPv4 addrerss even if getaddrinfo()
returns IPv4 mapped IPv6 address. FTP is nervous about address family. Submitted by itojun and slightly modified to fit our ftp(1).
Diffstat (limited to 'usr.bin/ftp')
-rw-r--r--usr.bin/ftp/extern.h1
-rw-r--r--usr.bin/ftp/fetch.c1
-rw-r--r--usr.bin/ftp/ftp.c35
3 files changed, 37 insertions, 0 deletions
diff --git a/usr.bin/ftp/extern.h b/usr.bin/ftp/extern.h
index d935d9e..54ccd79 100644
--- a/usr.bin/ftp/extern.h
+++ b/usr.bin/ftp/extern.h
@@ -41,6 +41,7 @@ void abortpt __P((int));
void abortrecv __P((int));
void abortsend __P((int));
void account __P((int, char **));
+void ai_unmapped __P((struct addrinfo *));
void alarmtimer __P((int));
int another __P((int *, char ***, const char *));
int auto_fetch __P((int, char **));
diff --git a/usr.bin/ftp/fetch.c b/usr.bin/ftp/fetch.c
index f306406..0643e5d 100644
--- a/usr.bin/ftp/fetch.c
+++ b/usr.bin/ftp/fetch.c
@@ -217,6 +217,7 @@ url_get(origline, proxyenv)
while (1)
{
+ ai_unmapped(res);
s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (s == -1) {
res = res->ai_next;
diff --git a/usr.bin/ftp/ftp.c b/usr.bin/ftp/ftp.c
index a4c350f..8d38669 100644
--- a/usr.bin/ftp/ftp.c
+++ b/usr.bin/ftp/ftp.c
@@ -139,6 +139,13 @@ hookup(host0, port)
sizeof(hostnamebuf));
hostname = hostnamebuf;
while (1) {
+ /*
+ * make sure that ai_addr is NOT an IPv4 mapped address.
+ * IPv4 mapped address complicates too many things in FTP
+ * protocol handling, as FTP protocol is defined differently
+ * between IPv4 and IPv6.
+ */
+ ai_unmapped(res);
s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (s < 0) {
res = res->ai_next;
@@ -1928,3 +1935,31 @@ abort_remote(din)
}
(void)getreply(0);
}
+
+void
+ai_unmapped(ai)
+ struct addrinfo *ai;
+{
+ struct sockaddr_in6 *sin6;
+ struct sockaddr_in sin;
+
+ if (ai->ai_family != AF_INET6)
+ return;
+ if (ai->ai_addrlen != sizeof(struct sockaddr_in6) ||
+ sizeof(sin) > ai->ai_addrlen)
+ return;
+ sin6 = (struct sockaddr_in6 *)ai->ai_addr;
+ if (!IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr))
+ return;
+
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sin.sin_len = sizeof(struct sockaddr_in);
+ memcpy(&sin.sin_addr, &sin6->sin6_addr.s6_addr[12],
+ sizeof(sin.sin_addr));
+ sin.sin_port = sin6->sin6_port;
+
+ ai->ai_family = AF_INET;
+ memcpy(ai->ai_addr, &sin, sin.sin_len);
+ ai->ai_addrlen = sin.sin_len;
+}
OpenPOWER on IntegriCloud