summaryrefslogtreecommitdiffstats
path: root/usr.bin/ftp
diff options
context:
space:
mode:
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