[packages/ncftp] - added missing patch

qboosh qboosh at pld-linux.org
Sat Jul 20 07:20:33 CEST 2013


commit a1a0fcca17077a30625a9509cd9e0b1e7dde0eea
Author: Jakub Bogusz <qboosh at pld-linux.org>
Date:   Sat Jul 20 07:20:38 2013 +0200

    - added missing patch

 ncftp-kame-v6.patch | 2977 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 2977 insertions(+)
---
diff --git a/ncftp-kame-v6.patch b/ncftp-kame-v6.patch
new file mode 100644
index 0000000..03b2ef5
--- /dev/null
+++ b/ncftp-kame-v6.patch
@@ -0,0 +1,2977 @@
+Index: ncftp3/README.v6
+diff -u /dev/null ncftp3/README.v6:1.1
+--- /dev/null	Mon Nov  9 21:52:32 2009
++++ ncftp3/README.v6	Tue Aug  6 14:06:35 2002
+@@ -0,0 +1,2 @@
++If you have problem/trouble/suggestion for IPv6 related code,
++Please contact to core at kame.net
+Index: ncftp3/configure.in
+diff -u ncftp3/configure.in:1.1.1.17 ncftp3/configure.in:1.28
+--- ncftp3/configure.in:1.1.1.17	Thu Nov  5 16:20:41 2009
++++ ncftp3/configure.in	Thu Nov  5 16:47:08 2009
+@@ -13,8 +13,6 @@
+ wi_ARG_ENABLE_SSP
+ wi_ARG_DISABLE_MACOSX_UNIVERSAL
+ 
+-
+-
+ dnl ---------------------------------------------------------------------------
+ dnl Environment and compiler settings.
+ dnl ---------------------------------------------------------------------------
+@@ -113,6 +111,81 @@
+ wi_HEADER_SYS_SELECT_H	dnl				# sio
+ 
+ 
++dnl ---------------------------------------------------------------------------
++dnl Checks for IPv6.
++dnl ---------------------------------------------------------------------------
++dnl
++AC_MSG_CHECKING([whether to enable ipv6])
++AC_ARG_ENABLE(ipv6,
++[  --enable-ipv6		Enable ipv6 (with ipv4) support
++  --disable-ipv6		Disable ipv6 support],
++[ case "$enableval" in
++  no)
++       AC_MSG_RESULT(no)
++       ipv6=no
++       ;;
++  *)   AC_MSG_RESULT(yes)
++       AC_DEFINE(ENABLE_IPV6)
++       ipv6=yes
++       ;;
++  esac ],
++
++  AC_TRY_RUN([ /* AF_INET6 avalable check */
++#define INET6
++#include <sys/types.h>
++#include <sys/socket.h>
++main()
++{
++ if (socket(AF_INET6, SOCK_STREAM, 0) < 0)
++   exit(1);
++ else
++   exit(0);
++}
++],
++  AC_MSG_RESULT(yes)
++  AC_DEFINE(ENABLE_IPV6)
++  ipv6=yes,
++  AC_MSG_RESULT(no)
++  ipv6=no,
++  AC_MSG_RESULT(no)
++  ipv6=no
++))
++
++AC_CHECK_FUNC(getaddrinfo, [
++  AC_DEFINE(HAVE_GETADDRINFO)], [
++  LIBOBJS="$LIBOBJS getaddrinfo.o"
++  LIBSOBJS="$LIBSOBJS getaddrinfo.so"
++])
++
++AC_CHECK_FUNC(getnameinfo, [
++  AC_DEFINE(HAVE_GETNAMEINFO)], [
++  LIBOBJS="$LIBOBJS getnameinfo.o"
++  LIBSOBJS="$LIBSOBJS getnameinfo.so"
++])
++
++# check if sockaddr has sa_len member
++AC_MSG_CHECKING(if sockaddr has sa_len member)
++AC_TRY_COMPILE([#include <sys/types.h>
++#include <sys/socket.h>],
++[struct sockaddr x;
++x.sa_len = 0;],
++       AC_MSG_RESULT(yes)
++       AC_DEFINE(HAVE_SOCKADDR_SA_LEN),
++       AC_MSG_RESULT(no))
++
++# check if sockaddr_storage has ss_family member
++AC_MSG_CHECKING(if sockaddr_storage has ss_family member)
++AC_TRY_COMPILE([#include <sys/types.h>
++#include <sys/socket.h>],
++[struct sockaddr_storage x;
++x.__ss_family = 0;],
++	AC_MSG_RESULT(yes)
++	AC_DEFINE(HAVE_SOCKADDR_STORAGE_SS_FAMILY),
++	AC_MSG_RESULT(no)
++	AC_DEFINE(HAVE_SOCKADDR_STORAGE___SS_FAMILY)
++	CPPFLAGS="$CPPFLAGS -D__ss_family=ss_family -D__ss_len=ss_len")
++
++CPPFLAGS="-I$MAINDIR $CPPFLAGS"
+ 
+ dnl ---------------------------------------------------------------------------
+ dnl Checks for library functions.
+@@ -258,6 +331,8 @@
+ AC_SUBST(Z30)
+ AC_SUBST(Z31)
+ AC_SUBST(LIBSET)
++AC_SUBST(LIBOBJS)
++AC_SUBST(LIBSOBJS)
+ AC_SUBST(MAINDIR)
+ AC_SUBST(NCFTP_VERSION)
+ AC_SUBST(LIBNCFTP_VERSION)
+Index: ncftp3/Strn/tester
+Index: ncftp3/libncftp/addrinfo.h
+diff -u /dev/null ncftp3/libncftp/addrinfo.h:1.2
+--- /dev/null	Mon Nov  9 21:52:32 2009
++++ ncftp3/libncftp/addrinfo.h	Tue Nov 20 02:53:11 2001
+@@ -0,0 +1,104 @@
++/*
++ * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in the
++ *    documentation and/or other materials provided with the distribution.
++ * 3. Neither the name of the project nor the names of its contributors
++ *    may be used to endorse or promote products derived from this software
++ *    without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
++ * SUCH DAMAGE.
++ */
++
++#ifndef HAVE_GETADDRINFO
++
++/*
++ * Error return codes from getaddrinfo()
++ */
++#define	EAI_ADDRFAMILY	 1	/* address family for hostname not supported */
++#define	EAI_AGAIN	 2	/* temporary failure in name resolution */
++#define	EAI_BADFLAGS	 3	/* invalid value for ai_flags */
++#define	EAI_FAIL	 4	/* non-recoverable failure in name resolution */
++#define	EAI_FAMILY	 5	/* ai_family not supported */
++#define	EAI_MEMORY	 6	/* memory allocation failure */
++#define	EAI_NODATA	 7	/* no address associated with hostname */
++#define	EAI_NONAME	 8	/* hostname nor servname provided, or not known */
++#define	EAI_SERVICE	 9	/* servname not supported for ai_socktype */
++#define	EAI_SOCKTYPE	10	/* ai_socktype not supported */
++#define	EAI_SYSTEM	11	/* system error returned in errno */
++#define EAI_BADHINTS	12
++#define EAI_PROTOCOL	13
++#define EAI_MAX		14
++
++/*
++ * Flag values for getaddrinfo()
++ */
++#define	AI_PASSIVE	0x00000001 /* get address to use bind() */
++#define	AI_CANONNAME	0x00000002 /* fill ai_canonname */
++#define	AI_NUMERICHOST	0x00000004 /* prevent name resolution */
++/* valid flags for addrinfo */
++#define	AI_MASK		(AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST)
++
++#define	AI_ALL		0x00000100 /* IPv6 and IPv4-mapped (with AI_V4MAPPED) */
++#define	AI_V4MAPPED_CFG	0x00000200 /* accept IPv4-mapped if kernel supports */
++#define	AI_ADDRCONFIG	0x00000400 /* only if any address is assigned */
++#define	AI_V4MAPPED	0x00000800 /* accept IPv4-mapped IPv6 address */
++/* special recommended flags for getipnodebyname */
++#define	AI_DEFAULT	(AI_V4MAPPED_CFG | AI_ADDRCONFIG)
++
++/*
++ * Constants for getnameinfo()
++ */
++#define	NI_MAXHOST	1025
++#define	NI_MAXSERV	32
++
++/*
++ * Flag values for getnameinfo()
++ */
++#define	NI_NOFQDN	0x00000001
++#define	NI_NUMERICHOST	0x00000002
++#define	NI_NAMEREQD	0x00000004
++#define	NI_NUMERICSERV	0x00000008
++#define	NI_DGRAM	0x00000010
++
++struct addrinfo {
++	int	ai_flags;	/* AI_PASSIVE, AI_CANONNAME */
++	int	ai_family;	/* PF_xxx */
++	int	ai_socktype;	/* SOCK_xxx */
++	int	ai_protocol;	/* 0 or IPPROTO_xxx for IPv4 and IPv6 */
++	size_t	ai_addrlen;	/* length of ai_addr */
++	char	*ai_canonname;	/* canonical name for hostname */
++	struct sockaddr *ai_addr;	/* binary address */
++	struct addrinfo *ai_next;	/* next structure in linked list */
++};
++
++struct sockaddr_storage {
++#ifdef HAVE_SOCKADDR_SA_LEN
++	u_int8_t	ss_len;		/* address length */
++	u_int8_t	ss_family;	/* address family */
++#else
++	u_int16_t	ss_family;
++#endif
++	u_int8_t fill[126];
++};
++
++extern void freehostent __P((struct hostent *));
++extern char *gai_strerror __P((int));
++#endif
+--- ncftp-3.2.5/libncftp/ftp.c.orig	2009-10-24 01:31:22.000000000 +0200
++++ ncftp-3.2.5/libncftp/ftp.c	2011-03-27 15:36:20.209737273 +0200
+@@ -50,6 +50,18 @@
+ #	define DisposeSocket(a) close(a)
+ #endif
+ 
++#ifndef HAVE_SOCKADDR_SA_LEN
++#ifndef SA_LEN
++#ifdef ENABLE_IPV6
++#define SA_LEN(x) (((x)->sa_family == AF_INET6) ? sizeof(struct sockaddr_in6) \
++		: (((x)->sa_family == AF_INET) ? sizeof(struct sockaddr_in) \
++		: -1))
++#else  /* ENABLE_IPV6 */
++#define SA_LEN(x) (((x)->sa_family == AF_INET) ? sizeof(struct sockaddr_in) : -1)
++#endif /* ENABLE_IPV6 */
++#endif /* SA_LEN */
++#endif /* HAVE_SOCKADDR_SA_LEN */
++
+ static const char *gPrivateNetworks[] = {
+ 	"192.168.",
+ 	"10.",
+@@ -101,9 +113,9 @@
+ 
+ 
+ static int
+-GetSocketAddress(const FTPCIPtr cip, int sockfd, struct sockaddr_in *saddr)
++GetSocketAddress(const FTPCIPtr cip, int sockfd, struct sockaddr *saddr)
+ {
+-	sockaddr_size_t len = (sockaddr_size_t) sizeof (struct sockaddr_in);
++	sockaddr_size_t len = (sockaddr_size_t) sizeof (struct sockaddr_storage);
+ 	int result = 0;
+ 
+ 	if (getsockname(sockfd, (struct sockaddr *)saddr, &len) < 0) {
+@@ -138,16 +150,16 @@
+ OpenControlConnection(const FTPCIPtr cip, char *host, unsigned int port)
+ {
+ 	struct sockaddr_in localAddr;
+-	struct in_addr ip_address;
+ 	int err = 0;
+ 	int result;
+ 	int oerrno;
+ 	volatile int sockfd = -1;
+ 	volatile int sock2fd = -1;
+ 	ResponsePtr rp = NULL;
+-	char **volatile curaddr;
+-	int hpok, hprc;
+-	struct hostent hp;
++	struct addrinfo hints;
++	struct addrinfo *res, *res0;
++	int error;
++	char buf[NI_MAXHOST];
+ 	char *volatile fhost;
+ 	unsigned int fport;
+ #ifndef NO_SIGNALS
+@@ -181,35 +193,17 @@
+ 	cip->cin = NULL;
+ 	cip->cout = NULL;
+ 
+-	/* Make sure we use network byte-order. */
+-	fport = (unsigned int) htons((unsigned short) fport);
+-
+-	cip->servCtlAddr.sin_port = (unsigned short) fport;
+-
+-	hprc = GetHostEntry(&hp, fhost, &ip_address, cip->buf, cip->bufSize);
+-	if (hprc != 0) {
+-		hpok = 0;
+-		/* Okay, no Host entry, but maybe we have a numeric address
+-		 * in ip_address we can try.
+-		 */
+-#ifdef DNSSEC_LOCAL_VALIDATION
+-		if (hprc == -2) {
+-			FTPLogError(cip, kDontPerror, "%s: untrusted DNS response.\n", fhost);
+-			cip->errNo = kErrHostUnknown;
+-			return (kErrHostUnknown);
+-		}
+-#endif
+-		if (ip_address.s_addr == INADDR_NONE) {
+-			FTPLogError(cip, kDontPerror, "%s: unknown host.\n", fhost);
+-			cip->errNo = kErrHostUnknown;
+-			return (kErrHostUnknown);
+-		}
+-		cip->servCtlAddr.sin_family = AF_INET;
+-		cip->servCtlAddr.sin_addr.s_addr = ip_address.s_addr;
+-	} else {
+-		hpok = 1;
+-		cip->servCtlAddr.sin_family = hp.h_addrtype;
+-		/* We'll fill in the rest of the structure below. */
++	memset(&hints, 0, sizeof(hints));
++	hints.ai_flags = AI_CANONNAME;
++	hints.ai_family = PF_UNSPEC;
++	hints.ai_socktype = SOCK_STREAM;
++	hints.ai_protocol = IPPROTO_TCP;
++	sprintf(buf, "%d\0", fport);
++	error = getaddrinfo(fhost, buf, &hints, &res0);
++	if (error) {
++		FTPLogError(cip, kDontPerror, "%s: %s.\n", fhost, gai_strerror(error));
++		cip->errNo = kErrHostUnknown;
++		return (kErrHostUnknown);
+ 	}
+ 	
+ 	/* After obtaining a socket, try to connect it to a remote
+@@ -218,23 +212,24 @@
+ 	 * every address in the list from the host entry.
+ 	 */
+ 
+-	if (hpok == 0) {
+-		/* Since we're given a single raw address, and not a host entry,
+-		 * we can only try this one address and not any other addresses
+-		 * that could be present for a site with a host entry.
+-		 */
+-
+-		if ((sockfd = socket(cip->servCtlAddr.sin_family, SOCK_STREAM, 0)) < 0) {
++	/* We can try each address in the list.  We'll quit when we
++	 * run out of addresses to try or get a successful connection.
++	 */
++	for (res = res0; res; res = res->ai_next) {
++		(void) memcpy(&cip->servCtlAddr, res->ai_addr, (size_t)res->ai_addrlen);
++		if ((sockfd = socket(cip->servCtlAddr.ss_family, SOCK_STREAM, 0)) < 0) {
++			if (res0->ai_next)
++				continue;
+ 			FTPLogError(cip, kDoPerror, "Could not get a socket.\n");
+ 			cip->errNo = kErrNewStreamSocket;
+ 			return (kErrNewStreamSocket);
+ 		}
+ 
+ 		/* On rare occasions, the user may specify a local IP address to use. */
+-		if (cip->preferredLocalAddr.sin_family != 0) {
++		if (cip->preferredLocalAddr.sin_family == AF_INET) {
+ 			localAddr = cip->preferredLocalAddr;
+ 			localAddr.sin_port = 0;
+-			if (BindToEphemeralPortNumber(sockfd, &localAddr, (int) cip->ephemLo, (int) cip->ephemHi) < 0) {
++			if (BindToEphemeralPortNumber(sockfd, (struct sockaddr *)&localAddr, (int) cip->ephemLo, (int) cip->ephemHi) < 0) {
+ 				FTPLogError(cip, kDoPerror, "Could not bind the control socket");
+ 				result = kErrBindCtrlSocket;
+ 				cip->errNo = kErrBindCtrlSocket;
+@@ -251,14 +246,14 @@
+ 		(void) SetSocketBufSize(sockfd, cip->ctrlSocketRBufSize, cip->ctrlSocketSBufSize);
+ 
+ #ifdef NO_SIGNALS
+-		err = SConnect(sockfd, &cip->servCtlAddr, (int) cip->connTimeout);
++		err = SConnect(sockfd, (struct sockaddr *)&cip->servCtlAddr, (int) cip->connTimeout);
+ 
+-		if (err < 0) {
+-			oerrno = errno;
+-			(void) SClose(sockfd, 3);
+-			errno = oerrno;
+-			sockfd = -1;
+-		}
++		if (err == 0)
++			break;
++		oerrno = errno;
++		(void) SClose(sockfd, 3);
++		errno = oerrno;
++		sockfd = -1;
+ #else	/* NO_SIGNALS */
+ 		osigint = (volatile FTPSigProc) signal(SIGINT, CancelConnect);
+ 		if (cip->connTimeout > 0) {
+@@ -287,6 +282,8 @@
+ 				Error(vcip, kDontPerror, "Connection attempt canceled.\n");
+ 				(void) kill(getpid(), SIGINT);
+ 			} else if (gGotSig == SIGALRM) {
++				if (res0->ai_next)
++					continue;
+ 				result = vcip->errNo = kErrConnectRetryableErr;
+ 				Error(vcip, kDontPerror, "Connection attempt timed-out.\n");
+ 				(void) kill(getpid(), SIGALRM);
+@@ -297,7 +294,12 @@
+ 			return (result);
+ 		} else  {
+ 			err = connect(sockfd, (struct sockaddr *) &cip->servCtlAddr,
+-				      (int) sizeof (cip->servCtlAddr));
++#ifdef HAVE_SOCKADDR_SA_LEN
++				      cip->servCtlAddr.ss_len
++#else
++				      SA_LEN((struct sockaddr *)&cip->servCtlAddr)
++#endif
++				);
+ 			if (cip->connTimeout > 0) {
+ 				(void) alarm(0);
+ 				(void) signal(SIGALRM, (FTPSigProc) osigalrm);
+@@ -311,106 +313,7 @@
+ 			errno = oerrno;
+ 			sockfd = -1;
+ 		}
+-#endif	/* NO_SIGNALS */
+-	} else {
+-		/* We can try each address in the list.  We'll quit when we
+-		 * run out of addresses to try or get a successful connection.
+-		 */
+-		for (curaddr = hp.h_addr_list; *curaddr != NULL; curaddr++) {
+-			if ((sockfd = socket(cip->servCtlAddr.sin_family, SOCK_STREAM, 0)) < 0) {
+-				FTPLogError(cip, kDoPerror, "Could not get a socket.\n");
+-				cip->errNo = kErrNewStreamSocket;
+-				return (kErrNewStreamSocket);
+-			}
+-			/* This could overwrite the address field in the structure,
+-			 * but this is okay because the structure has a junk field
+-			 * just for this purpose.
+-			 */
+-			(void) memcpy(&cip->servCtlAddr.sin_addr, *curaddr, (size_t) hp.h_length);
+-
+-			/* On rare occasions, the user may specify a local IP address to use. */
+-			if (cip->preferredLocalAddr.sin_family != 0) {
+-				localAddr = cip->preferredLocalAddr;
+-				localAddr.sin_port = 0;
+-				if (BindToEphemeralPortNumber(sockfd, &localAddr, (int) cip->ephemLo, (int) cip->ephemHi) < 0) {
+-					FTPLogError(cip, kDoPerror, "Could not bind the control socket");
+-					result = kErrBindCtrlSocket;
+-					cip->errNo = kErrBindCtrlSocket;
+-					(void) SClose(sockfd, 3);
+-					return (kErrBindCtrlSocket);
+-				}
+-			}
+-
+-			/* This doesn't do anything if you left these
+-			 * at their defaults (zero).  Otherwise it
+-			 * tries to set the buffer size to the
+-			 * size specified.
+-			 */
+-			(void) SetSocketBufSize(sockfd, cip->ctrlSocketRBufSize, cip->ctrlSocketSBufSize);
+-
+-#ifdef NO_SIGNALS
+-			err = SConnect(sockfd, &cip->servCtlAddr, (int) cip->connTimeout);
+-
+-			if (err == 0)
+-				break;
+-			oerrno = errno;
+-			(void) SClose(sockfd, 3);
+-			errno = oerrno;
+-			sockfd = -1;
+-#else	/* NO_SIGNALS */
+-
+-			osigint = (volatile FTPSigProc) signal(SIGINT, CancelConnect);
+-			if (cip->connTimeout > 0) {
+-				osigalrm = (volatile FTPSigProc) signal(SIGALRM, CancelConnect);
+-				(void) alarm(cip->connTimeout);
+-			}
+-
+-			vcip = cip;
+-#ifdef HAVE_SIGSETJMP
+-			sj = sigsetjmp(gCancelConnectJmp, 1);
+-#else
+-			sj = setjmp(gCancelConnectJmp);
+-#endif	/* HAVE_SIGSETJMP */
+-
+-			if (sj != 0) {
+-				/* Interrupted by a signal. */
+-				(void) DisposeSocket(sockfd);
+-				(void) signal(SIGINT, (FTPSigProc) osigint);
+-				if (vcip->connTimeout > 0) {
+-					(void) alarm(0);
+-					(void) signal(SIGALRM, (FTPSigProc) osigalrm);
+-				}
+-				if (gGotSig == SIGINT) {
+-					result = vcip->errNo = kErrConnectMiscErr;
+-					Error(vcip, kDontPerror, "Connection attempt canceled.\n");
+-					(void) kill(getpid(), SIGINT);
+-				} else if (gGotSig == SIGALRM) {
+-					result = vcip->errNo = kErrConnectRetryableErr;
+-					Error(vcip, kDontPerror, "Connection attempt timed-out.\n");
+-					(void) kill(getpid(), SIGALRM);
+-				} else {
+-					result = vcip->errNo = kErrConnectMiscErr;
+-					Error(vcip, kDontPerror, "Connection attempt failed due to an unexpected signal (%d).\n", gGotSig);
+-				}
+-				return (result);
+-			} else {
+-				err = connect(sockfd, (struct sockaddr *) &cip->servCtlAddr,
+-					      (int) sizeof (cip->servCtlAddr));
+-				if (cip->connTimeout > 0) {
+-					(void) alarm(0);
+-					(void) signal(SIGALRM, (FTPSigProc) osigalrm);
+-				}
+-				(void) signal(SIGINT, (FTPSigProc) osigint);
+-			}
+-
+-			if (err == 0)
+-				break;
+-			oerrno = errno;
+-			(void) DisposeSocket(sockfd);
+-			errno = oerrno;
+-			sockfd = -1;
+ #endif /* NO_SIGNALS */
+-		}
+ 	}
+ 	
+ 	if (err < 0) {
+@@ -469,7 +372,7 @@
+ 	}
+ 
+ 	/* Get our end of the socket address for later use. */
+-	if ((result = GetSocketAddress(cip, sockfd, &cip->ourCtlAddr)) < 0)
++	if ((result = GetSocketAddress(cip, sockfd, (struct sockaddr *)&cip->ourCtlAddr)) < 0)
+ 		goto fatal;
+ 
+ 	/* We want Out-of-band data to appear in the regular stream,
+@@ -540,11 +443,20 @@
+ #endif
+ #endif	/* NO_SIGNALS */
+ 
+-	InetNtoA(cip->ip, &cip->servCtlAddr.sin_addr, sizeof(cip->ip));
+-	if ((hpok == 0) || (hp.h_name == NULL))
++	getnameinfo((struct sockaddr*)&cip->servCtlAddr,
++#ifdef HAVE_SOCKADDR_SA_LEN
++		    cip->servCtlAddr.ss_len,
++#else
++		    SA_LEN((struct sockaddr *)&cip->servCtlAddr),
++#endif
++		     buf, sizeof(buf), NULL, 0, NI_NUMERICHOST);
++	(void) STRNCPY(cip->ip, buf);
++	if ((res0 == NULL) || (res0->ai_canonname == NULL))
+ 		(void) STRNCPY(cip->actualHost, fhost);
+ 	else
+-		(void) STRNCPY(cip->actualHost, (char *) hp.h_name);
++		(void) STRNCPY(cip->actualHost, (char *) res0->ai_canonname);
++	freeaddrinfo(res0);
++	res0 = NULL;
+ 
+ 	/* Read the startup message from the server. */	
+ 	rp = InitResponse();
+@@ -648,6 +560,10 @@
+ 	CloseFile(&cip->cout);
+ 	cip->ctrlSocketR = kClosedFileDescriptor;
+ 	cip->ctrlSocketW = kClosedFileDescriptor;
++	if (res0) {
++		freeaddrinfo(res0);
++		res0 = NULL;
++	}
+ 	return (result);
+ }	/* OpenControlConnection */
+ 
+@@ -741,11 +657,15 @@
+ 
+ 
+ int
+-FTPSendPort(const FTPCIPtr cip, struct sockaddr_in *saddr)
++FTPSendPort(const FTPCIPtr cip, struct sockaddr *saddr)
+ {
+ 	char *a, *p;
+ 	int result;
+ 	ResponsePtr rp;
++	struct sockaddr_in *saddr4;
++#ifdef ENABLE_IPV6
++	struct sockaddr_in6 *saddr6;
++#endif
+ 
+ 	rp = InitResponse();
+ 	if (rp == NULL) {
+@@ -754,16 +674,46 @@
+ 		return (cip->errNo);
+ 	}
+ 
+-	/* These will point to data in network byte order. */
+-	a = (char *) &saddr->sin_addr;
+-	p = (char *) &saddr->sin_port;
+ #define UC(x) (int) (((int) x) & 0xff)
++#ifdef ENABLE_IPV6
++	if (saddr->sa_family == AF_INET6) {
++		char host[NI_MAXHOST];
++		char port[NI_MAXSERV];
++
++		getnameinfo(saddr, sizeof(struct sockaddr_in6), host, sizeof(host),
++			    port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV);
++
++		saddr6 = (struct sockaddr_in6 *)saddr;
++		/* These will point to data in network byte order. */
++		a = (char *) &saddr6->sin6_addr;
++		p = (char *) &saddr6->sin6_port;
++		/* Need to tell the other side which host (the address) and
++		 * which process (port) on that host to send data to.
++		 */
++		result = RCmd(cip, rp, "EPRT |2|%s|%s|", host, port);
++		if (result != 2) {
++			result = RCmd(cip, rp, "LPRT 6,16,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,2,%d,%d",
++				      UC(a[ 0]), UC(a[ 1]), UC(a[ 2]), UC(a[ 3]),
++				      UC(a[ 4]), UC(a[ 5]), UC(a[ 6]), UC(a[ 7]),
++				      UC(a[ 8]), UC(a[ 9]), UC(a[10]), UC(a[11]),
++				      UC(a[12]), UC(a[13]), UC(a[14]), UC(a[15]),
++				      UC(p[0]), UC(p[1]));
++		}
++	} else {
++#endif
++		saddr4 = (struct sockaddr_in *)saddr;
++		/* These will point to data in network byte order. */
++		a = (char *) &saddr4->sin_addr;
++		p = (char *) &saddr4->sin_port;
+ 
+-	/* Need to tell the other side which host (the address) and
+-	 * which process (port) on that host to send data to.
+-	 */
+-	result = RCmd(cip, rp, "PORT %d,%d,%d,%d,%d,%d",
+-		UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1]));
++		/* Need to tell the other side which host (the address) and
++		 * which process (port) on that host to send data to.
++		 */
++		result = RCmd(cip, rp, "PORT %d,%d,%d,%d,%d,%d",
++			      UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1]));
++#ifdef ENABLE_IPV6
++	}
++#endif
+ 
+ 	DoneWithResponse(cip, rp);
+ 	if (result < 0) {
+@@ -780,13 +730,18 @@
+ 
+ 
+ int
+-FTPSendPassive(const FTPCIPtr cip, struct sockaddr_in *saddr, int *weird)
++FTPSendPassive(const FTPCIPtr cip, struct sockaddr *saddr, int *weird)
+ {
+ 	ResponsePtr rp;
+-	int i[6], j;
+-	unsigned char n[6];
++	int i[18], j;
++	unsigned char n[18];
+ 	char *cp;
+ 	int result;
++	struct sockaddr_in *saddr4 = (struct sockaddr_in *)saddr;
++#ifdef ENABLE_IPV6
++	struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)saddr;
++#endif
++	unsigned short port;
+ 
+ 	rp = InitResponse();
+ 	if (rp == NULL) {
+@@ -795,56 +750,162 @@
+ 		return (cip->errNo);
+ 	}
+ 
+-	result = RCmd(cip, rp, "PASV");
+-	if (result < 0)
+-		goto done;
+-
+-	if (rp->codeType != 2) {
+-		/* Didn't understand or didn't want passive port selection. */
+-		cip->errNo = result = kErrPASVFailed;
+-		goto done;
+-	}
+-
+-	/* The other side returns a specification in the form of
+-	 * an internet address as the first four integers (each
+-	 * integer stands for 8-bits of the real 32-bit address),
+-	 * and two more integers for the port (16-bit port).
+-	 *
+-	 * It should give us something like:
+-	 * "Entering Passive Mode (129,93,33,1,10,187)", so look for
+-	 * digits with sscanf() starting 24 characters down the string.
+-	 */
++	result = RCmd(cip, rp, "EPSV");
++	if (result != 2)
++		goto next;
++
++	if (rp->codeType != 2)
++		goto next;
++
+ 	for (cp = rp->msg.first->line; ; cp++) {
+ 		if (*cp == '\0') {
+-			FTPLogError(cip, kDontPerror, "Cannot parse PASV response: %s\n", rp->msg.first->line);
+-			goto done;
++			FTPLogError(cip, kDontPerror, "Cannot parse EPSV response: %s\n", rp->msg.first->line);
++			goto next;
+ 		}
+ 		if (isdigit((int) *cp))
+ 			break;
+ 	}
++	if (sscanf(cp, "%hd|", &port) != 1) {
++		FTPLogError(cip, kDontPerror, "Cannot parse EPSV response: %s\n", rp->msg.first->line);
++		goto next;
++	}
++
+ 
+-	if (sscanf(cp, "%d,%d,%d,%d,%d,%d",
+-			&i[0], &i[1], &i[2], &i[3], &i[4], &i[5]) != 6) {
+-		FTPLogError(cip, kDontPerror, "Cannot parse PASV response: %s\n", rp->msg.first->line);
+-		goto done;
++#ifdef ENABLE_IPV6
++	if (saddr->sa_family == AF_INET6) {
++		saddr6->sin6_addr =
++			((struct sockaddr_in6 *)&cip->servCtlAddr)->sin6_addr;
++		saddr6->sin6_port = htons(port);
++	} else {
++#endif
++		saddr4->sin_addr =
++			((struct sockaddr_in *)&cip->servCtlAddr)->sin_addr;
++		saddr4->sin_port = htons(port);
++#ifdef ENABLE_IPV6
+ 	}
++#endif
++	goto done;
+ 
+-	if (weird != (int *) 0)
+-		*weird = 0;
+-		
+-	for (j=0; j<6; j++) {
+-		/* Some ftp servers return bogus port octets, such as
+-		 * boombox.micro.umn.edu.  Let the caller know if we got a
+-		 * weird looking octet.
+-		 */
+-		if (((i[j] < 0) || (i[j] > 255)) && (weird != (int *) 0))
+-			*weird = *weird + 1;
+-		n[j] = (unsigned char) (i[j] & 0xff);
++ next:
++	rp = InitResponse();
++	if (rp == NULL) {
++		FTPLogError(cip, kDontPerror, "Malloc failed.\n");
++		cip->errNo = kErrMallocFailed;
++		return (cip->errNo);
+ 	}
+ 	
+-	(void) memcpy(&saddr->sin_addr, &n[0], (size_t) 4);
+-	(void) memcpy(&saddr->sin_port, &n[4], (size_t) 2);
++#ifdef ENABLE_IPV6
++	if (saddr->sa_family == AF_INET6) {
++		int af, hal, pal;
++
++		result = RCmd(cip, rp, "LPSV");
++		if (result < 0)
++			goto done;
++
++		if (rp->codeType != 2) {
++			/* Didn't understand or didn't want passive port selection. */
++			cip->errNo = result = kErrPASVFailed;
++			goto done;
++		}
++
++		/* The other side returns a specification in the form of
++		 * an internet address as the first four integers (each
++		 * integer stands for 8-bits of the real 32-bit address),
++		 * and two more integers for the port (16-bit port).
++		 *
++		 * It should give us something like:
++		 * "Entering Passive Mode (129,93,33,1,10,187)", so look for
++		 * digits with sscanf() starting 24 characters down the string.
++		 */
++		for (cp = rp->msg.first->line; ; cp++) {
++			if (*cp == '\0') {
++				FTPLogError(cip, kDontPerror, "Cannot parse LPSV response: %s\n", rp->msg.first->line);
++				goto done;
++			}
++			if (isdigit((int) *cp))
++				break;
++		}
+ 
++		if (sscanf(cp, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
++			   &af, &hal,
++			   &i[ 0], &i[ 1], &i[ 2], &i[ 3],
++			   &i[ 4], &i[ 5], &i[ 6], &i[ 7],
++			   &i[ 8], &i[ 9], &i[10], &i[11],
++			   &i[12], &i[13], &i[14], &i[15],
++			   &pal,
++			   &i[16], &i[17]) != 21) {
++			FTPLogError(cip, kDontPerror, "Cannot parse LPSV response: %s\n", rp->msg.first->line);
++			goto done;
++		}
++		if (af != 6 || hal != 16 || pal != 2) {
++			FTPLogError(cip, kDontPerror, "Cannot parse LPSV response: %s\n", rp->msg.first->line);
++			goto done;
++		}
++
++		for (j=0, *weird = 0; j<18; j++) {
++			/* Some ftp servers return bogus port octets, such as
++			 * boombox.micro.umn.edu.  Let the caller know if we got a
++			 * weird looking octet.
++			 */
++			if ((i[j] < 0) || (i[j] > 255))
++				*weird = *weird + 1;
++			n[j] = (unsigned char) (i[j] & 0xff);
++		}
++		(void) memcpy(&saddr6->sin6_addr, &n[ 0], (size_t) 16);
++		(void) memcpy(&saddr6->sin6_port, &n[16], (size_t) 2);
++	} else {
++#endif
++		result = RCmd(cip, rp, "PASV");
++		if (result < 0)
++			goto done;
++
++		if (rp->codeType != 2) {
++			/* Didn't understand or didn't want passive port selection. */
++			cip->errNo = result = kErrPASVFailed;
++			goto done;
++		}
++
++		/* The other side returns a specification in the form of
++		 * an internet address as the first four integers (each
++		 * integer stands for 8-bits of the real 32-bit address),
++		 * and two more integers for the port (16-bit port).
++		 *
++		 * It should give us something like:
++		 * "Entering Passive Mode (129,93,33,1,10,187)", so look for
++		 * digits with sscanf() starting 24 characters down the string.
++		 */
++		for (cp = rp->msg.first->line; ; cp++) {
++			if (*cp == '\0') {
++				FTPLogError(cip, kDontPerror, "Cannot parse PASV response: %s\n", rp->msg.first->line);
++				goto done;
++			}
++			if (isdigit((int) *cp))
++				break;
++		}
++
++		if (sscanf(cp, "%d,%d,%d,%d,%d,%d",
++			   &i[0], &i[1], &i[2], &i[3], &i[4], &i[5]) != 6) {
++			FTPLogError(cip, kDontPerror, "Cannot parse PASV response: %s\n", rp->msg.first->line);
++			goto done;
++		}
++
++		if (weird != (int *) 0)
++			*weird = 0;
++		
++		for (j=0; j<6; j++) {
++			/* Some ftp servers return bogus port octets, such as
++			 * boombox.micro.umn.edu.  Let the caller know if we got a
++			 * weird looking octet.
++			 */
++			if (((i[j] < 0) || (i[j] > 255)) && (weird != (int *) 0))
++				*weird = *weird + 1;
++			n[j] = (unsigned char) (i[j] & 0xff);
++		}
++		(void) memcpy(&saddr4->sin_addr, &n[0], (size_t) 4);
++		(void) memcpy(&saddr4->sin_port, &n[4], (size_t) 2);
++#ifdef ENABLE_IPV6
++	}
++#endif
+ 	result = kNoErr;
+ done:
+ 	DoneWithResponse(cip, rp);
+@@ -861,8 +922,8 @@
+ 	char maybePrivateAddrStr[64];
+ 	char knownNonPrivateAddrToUseIfNeededStr[64];
+ 
+-	AddrToAddrStr(maybePrivateAddrStr, sizeof(maybePrivateAddrStr), maybePrivateAddr, 0, "%h");
+-	AddrToAddrStr(knownNonPrivateAddrToUseIfNeededStr, sizeof(knownNonPrivateAddrToUseIfNeededStr), knownNonPrivateAddrToUseIfNeeded, 0, "%h");
++	AddrToAddrStr(maybePrivateAddrStr, sizeof(maybePrivateAddrStr), (struct sockaddr *)maybePrivateAddr, 0, "%h");
++	AddrToAddrStr(knownNonPrivateAddrToUseIfNeededStr, sizeof(knownNonPrivateAddrToUseIfNeededStr), (struct sockaddr *)knownNonPrivateAddrToUseIfNeeded, 0, "%h");
+ 
+ 	if (strcmp(maybePrivateAddrStr, knownNonPrivateAddrToUseIfNeededStr) == 0)
+ 		return (0);		/* Assume if we could reach the Ctl, we can reach Data. */
+@@ -892,10 +953,10 @@
+ 	char servDataAddrStr[64];
+ 	char newDataAddrStr[64];
+ 
+-	memcpy(&oldServDataAddr, &cip->servDataAddr, sizeof(oldServDataAddr));
+-	if (FTPFixPrivateAddr(&cip->servDataAddr, &cip->servCtlAddr)) {
+-		AddrToAddrStr(servDataAddrStr, sizeof(servDataAddrStr), &oldServDataAddr, 0, NULL);
+-		AddrToAddrStr(newDataAddrStr, sizeof(newDataAddrStr), &cip->servDataAddr, 0, NULL);
++	memcpy(&oldServDataAddr, (struct sockaddr_in *)&cip->servDataAddr, sizeof(oldServDataAddr));
++	if (FTPFixPrivateAddr((struct sockaddr_in *)&cip->servDataAddr, (struct sockaddr_in *)&cip->servCtlAddr)) {
++		AddrToAddrStr(servDataAddrStr, sizeof(servDataAddrStr), (struct sockaddr *)&oldServDataAddr, 0, NULL);
++		AddrToAddrStr(newDataAddrStr, sizeof(newDataAddrStr), (struct sockaddr *)&cip->servDataAddr, 0, NULL);
+ 		PrintF(cip, "Fixing bogus PASV data address from %s to %s.\n", servDataAddrStr, newDataAddrStr);
+ 	}
+ }	/* FTPFixServerDataAddr */
+@@ -914,11 +975,11 @@
+ 		return;
+ 
+ 	memcpy(&oldClientDataAddr, &cip->ourDataAddr, sizeof(oldClientDataAddr));
+-	if (FTPFixPrivateAddr(&cip->ourDataAddr, &cip->clientKnownExternalAddr)) {
++	if (FTPFixPrivateAddr((struct sockaddr_in *)&cip->ourDataAddr, (struct sockaddr_in *)&cip->clientKnownExternalAddr)) {
+ 		memcpy(&newClientDataAddr, &cip->clientKnownExternalAddr, sizeof(newClientDataAddr));
+-		newClientDataAddr.sin_port = cip->ourDataAddr.sin_port;
+-		AddrToAddrStr(ourDataAddrStr, sizeof(ourDataAddrStr), &oldClientDataAddr, 0, NULL);
+-		AddrToAddrStr(newDataAddrStr, sizeof(newDataAddrStr), &newClientDataAddr, 0, NULL);
++		newClientDataAddr.sin_port = ((struct sockaddr_in *)&cip->ourDataAddr)->sin_port;
++		AddrToAddrStr(ourDataAddrStr, sizeof(ourDataAddrStr), (struct sockaddr *)&oldClientDataAddr, 0, NULL);
++		AddrToAddrStr(newDataAddrStr, sizeof(newDataAddrStr), (struct sockaddr *)&newClientDataAddr, 0, NULL);
+ 		PrintF(cip, "Fixing what would have been a bogus PORT data address from %s to %s.\n", ourDataAddrStr, newDataAddrStr);
+ 	}
+ }	/* FTPFixClientDataAddr */
+@@ -927,30 +988,45 @@
+ 
+ 
+ int
+-BindToEphemeralPortNumber(const int sockfd, struct sockaddr_in *const addrp, const int ephemLo, const int ephemHi)
++BindToEphemeralPortNumber(const int sockfd, struct sockaddr *const addrp, const int ephemLo, const int ephemHi)
+ {
+ 	int i;
+ 	int result;
+ 	int rangesize;
+ 	unsigned short port;
+ 
+-	addrp->sin_family = AF_INET;
+ 	if (((int) ephemLo == 0) || ((int) ephemLo >= (int) ephemHi)) {
+ 		/* Do it the normal way.  System will
+ 		 * pick one, typically in the range
+ 		 * of 1024-4999.
+ 		 */
+-		addrp->sin_port = 0;	/* Let system pick one. */
+-
+-		result = bind(sockfd, (struct sockaddr *) addrp, sizeof(struct sockaddr_in));
++#ifdef ENABLE_IPV6
++		if (addrp->sa_family == AF_INET6)
++			((struct sockaddr_in6 *)addrp)->sin6_port = 0;	/* Let system pick one. */
++		else
++#endif
++			((struct sockaddr_in *)addrp)->sin_port = 0;	/* Let system pick one. */
++#ifdef HAVE_SOCKADDR_SA_LEN
++		result = bind(sockfd, addrp, addrp->sa_len);
++#else
++		result = bind(sockfd, addrp, SA_LEN(addrp));
++#endif
+ 	} else {
+ 		rangesize = (int) ((int) ephemHi - (int) ephemLo);
+ 		result = 0;
+ 		for (i=0; i<10; i++) {
+ 			port = (unsigned short) (((int) rand() % rangesize) + (int) ephemLo);
+-			addrp->sin_port = htons(port);
+-
+-			result = bind(sockfd, (struct sockaddr *) addrp, sizeof(struct sockaddr_in));
++#ifdef ENABLE_IPV6
++			if (addrp->sa_family == AF_INET6)
++				((struct sockaddr_in6 *)addrp)->sin6_port = htons(port);
++			else
++#endif
++				((struct sockaddr_in *)addrp)->sin_port = htons(port);
++#ifdef HAVE_SOCKADDR_SA_LEN
++			result = bind(sockfd, addrp, addrp->sa_len);
++#else
++			result = bind(sockfd, addrp, SA_LEN(addrp));
++#endif
+ 			if (result == 0)
+ 				break;
+ 			sleep(1);
+@@ -989,7 +1065,11 @@
+ 	result = 0;
+ 	CloseDataConnection(cip);	/* In case we didn't before... */
+ 
++#ifdef ENABLE_IPV6
++	dataSocket = socket(cip->ourCtlAddr.ss_family, SOCK_STREAM, 0);
++#else
+ 	dataSocket = socket(AF_INET, SOCK_STREAM, 0);
++#endif
+ 	if (dataSocket < 0) {
+ 		FTPLogError(cip, kDoPerror, "Could not get a data socket.\n");
+ 		result = kErrNewStreamSocket;
+@@ -1023,7 +1103,6 @@
+ 		 * which may have been set to something explicitly.
+ 		 */
+ 		cip->ourDataAddr = cip->ourCtlAddr;
+-		cip->ourDataAddr.sin_family = AF_INET;
+ 
+ #ifdef HAVE_LIBSOCKS
+ 		cip->ourDataAddr.sin_port = 0;
+@@ -1031,7 +1110,7 @@
+ 			(int) sizeof (cip->ourDataAddr),
+ 			cip->servCtlAddr.sin_addr.s_addr) < 0) 
+ #else
+-		if (BindToEphemeralPortNumber(dataSocket, &cip->ourDataAddr, (int) cip->ephemLo, (int) cip->ephemHi) < 0)
++		if (BindToEphemeralPortNumber(dataSocket, (struct sockaddr *)&cip->ourDataAddr, (int) cip->ephemLo, (int) cip->ephemHi) < 0)
+ #endif
+ 		{
+ 			FTPLogError(cip, kDoPerror, "Could not bind the data socket");
+@@ -1043,7 +1122,7 @@
+ 		/* Need to do this so we can figure out which port the system
+ 		 * gave to us.
+ 		 */
+-		if ((result = GetSocketAddress(cip, dataSocket, &cip->ourDataAddr)) < 0)
++		if ((result = GetSocketAddress(cip, dataSocket, (struct sockaddr *)&cip->ourDataAddr)) < 0)
+ 			goto bad;
+ 	
+ 		if (listen(dataSocket, 1) < 0) {
+@@ -1053,8 +1132,9 @@
+ 			goto bad;
+ 		}
+ 
+-		FTPFixClientDataAddr(cip);
+-		if ((result = FTPSendPort(cip, &cip->ourDataAddr)) < 0)
++		if (cip->ourDataAddr.ss_family == AF_INET)
++			FTPFixClientDataAddr(cip);
++		if ((result = FTPSendPort(cip, (struct sockaddr *)&cip->ourDataAddr)) < 0)
+ 			goto bad;
+ 	
+ 		cip->dataPortMode = kSendPortMode;
+@@ -1063,11 +1143,9 @@
+ 	
+ 		while (--passiveAttemptsRemaining >= 0) {
+ 			cip->servDataAddr = cip->servCtlAddr;
+-			cip->servDataAddr.sin_family = AF_INET;
+ 			cip->ourDataAddr = cip->ourCtlAddr;
+-			cip->ourDataAddr.sin_family = AF_INET;
+ 
+-			if (FTPSendPassive(cip, &cip->servDataAddr, &weirdPort) < 0) {
++			if (FTPSendPassive(cip, (struct sockaddr *)&cip->servDataAddr, &weirdPort) < 0) {
+ 				FTPLogError(cip, kDontPerror, "Passive mode refused.\n");
+ 				cip->hasPASV = kCommandNotAvailable;
+ 				
+@@ -1084,7 +1162,8 @@
+ 				cip->errNo = kErrPassiveModeFailed;
+ 				goto bad;
+ 			}
+-			FTPFixServerDataAddr(cip);
++			if (cip->servDataAddr.ss_family == AF_INET)
++				FTPFixServerDataAddr(cip);
+ 
+ #ifdef HAVE_LIBSOCKS
+ 			cip->ourDataAddr.sin_port = 0;
+@@ -1092,7 +1171,7 @@
+ 				(int) sizeof (cip->ourDataAddr),
+ 				cip->servCtlAddr.sin_addr.s_addr) < 0) 
+ #else
+-			if (BindToEphemeralPortNumber(dataSocket, &cip->ourDataAddr, (int) cip->ephemLo, (int) cip->ephemHi) < 0)
++			if (BindToEphemeralPortNumber(dataSocket, (struct sockaddr *)&cip->ourDataAddr, (int) cip->ephemLo, (int) cip->ephemHi) < 0)
+ #endif
+ 			{
+ 				FTPLogError(cip, kDoPerror, "Could not bind the data socket");
+@@ -1100,8 +1179,13 @@
+ 				cip->errNo = kErrBindDataSocket;
+ 				goto bad;
+ 			}
+-
+-			result = SConnect(dataSocket, &cip->servDataAddr, (int) cip->connTimeout);
++	
++			/* Need to do this so we can figure out which port the system
++			 * gave to us.
++			 */
++			if ((result = GetSocketAddress(cip, dataSocket, (struct sockaddr *)&cip->ourDataAddr)) < 0)
++				goto bad;
++			result = SConnect(dataSocket, (struct sockaddr *)&cip->servDataAddr, (int) cip->connTimeout);
+ 
+ 			if (result == kTimeoutErr) {
+ 				if (mode == kFallBackToSendPortMode) {
+@@ -1164,7 +1248,7 @@
+ 			if (dataSocket != kClosedFileDescriptor)
+ 				(void) DisposeSocket(dataSocket);
+ 
+-			dataSocket = socket(AF_INET, SOCK_STREAM, 0);
++			dataSocket = socket(cip->ourCtlAddr.ss_family, SOCK_STREAM, 0);
+ 			if (dataSocket < 0) {
+ 				FTPLogError(cip, kDoPerror, "Could not get a data socket.\n");
+ 				result = kErrNewStreamSocket;
+@@ -1180,7 +1264,7 @@
+ 		/* Need to do this so we can figure out which port the system
+ 		 * gave to us.
+ 		 */
+-		if ((result = GetSocketAddress(cip, dataSocket, &cip->ourDataAddr)) < 0)
++		if ((result = GetSocketAddress(cip, dataSocket, (struct sockaddr *) &cip->ourDataAddr)) < 0)
+ 			goto bad;
+ 
+ 		cip->hasPASV = kCommandAvailable;
+@@ -1225,9 +1309,9 @@
+ 		memset(&cip->servDataAddr, 0, sizeof(cip->servDataAddr));
+ 
+ #ifdef NO_SIGNALS
+-		newSocket = SAccept(cip->dataSocket, &cip->servDataAddr, (int) cip->connTimeout);
++		newSocket = SAccept(cip->dataSocket, (struct sockaddr *)&cip->servDataAddr, (int) cip->connTimeout);
+ #else	/* NO_SIGNALS */
+-		len = (int) sizeof(cip->servDataAddr);
++		len = (int) sizeof(struct sockaddr_storage);
+ 		if (cip->connTimeout > 0)
+ 			(void) alarm(cip->connTimeout);
+ 		newSocket = accept(cip->dataSocket, (struct sockaddr *) &cip->servDataAddr, &len);
+@@ -1242,11 +1326,10 @@
+ 			cip->errNo = kErrAcceptDataSocket;
+ 			return (kErrAcceptDataSocket);
+ 		}
+-	
+ 		if (cip->allowProxyForPORT == 0) {
+-			if (memcmp(&cip->servDataAddr.sin_addr.s_addr, &cip->servCtlAddr.sin_addr.s_addr, sizeof(cip->servDataAddr.sin_addr.s_addr)) != 0) {
+-				AddrToAddrStr(ctrlAddrStr, sizeof(ctrlAddrStr), &cip->servCtlAddr, 0, NULL);
+-				AddrToAddrStr(dataAddrStr, sizeof(dataAddrStr), &cip->servDataAddr, 0, NULL);
++			AddrToAddrStr(ctrlAddrStr, sizeof(ctrlAddrStr), (struct sockaddr *)&cip->servCtlAddr, 0, "%h");
++			AddrToAddrStr(dataAddrStr, sizeof(dataAddrStr), (struct sockaddr *)&cip->servDataAddr, 0, "%h");
++			if (strcmp(ctrlAddrStr, dataAddrStr) != 0) {
+ 				FTPLogError(cip, kDontPerror, "Data connection from %s did not originate from remote server %s!\n", dataAddrStr, ctrlAddrStr);
+ 				(void) DisposeSocket(newSocket);
+ 				cip->dataSocket = kClosedFileDescriptor;
+@@ -1254,21 +1337,57 @@
+ 				return (kErrProxyDataConnectionsDisabled);
+ 			}
+ 		}
+-
+ 		if (cip->require20 != 0) {
+-			remoteDataPort = ntohs(cip->servDataAddr.sin_port);
+-			remoteCtrlPort = ntohs(cip->servCtlAddr.sin_port);
+-			if ((int) remoteDataPort != ((int) remoteCtrlPort - 1)) {
+-				FTPLogError(cip, kDontPerror, "Data connection did not originate on correct port (expecting %d, got %d)!\n", (int) remoteCtrlPort - 1, (int) remoteDataPort);
+-				(void) DisposeSocket(newSocket);
+-				cip->dataSocket = kClosedFileDescriptor;
+-				cip->errNo = kErrDataConnOriginatedFromBadPort;
+-				return (kErrDataConnOriginatedFromBadPort);
++#ifdef ENABLE_IPV6
++			if (cip->servDataAddr.ss_family == AF_INET6) {
++				struct sockaddr_in6 *servDataAddr =
++					(struct sockaddr_in6 *) &cip->servDataAddr;
++				struct sockaddr_in6 *servCtlAddr =
++					(struct sockaddr_in6 *) &cip->servCtlAddr;
++
++				remoteDataPort = ntohs(servDataAddr->sin6_port);
++				remoteCtrlPort = ntohs(servCtlAddr->sin6_port);
++				if ((int) remoteDataPort != ((int) remoteCtrlPort - 1)) {
++					FTPLogError(cip, kDontPerror, "Data connection did not originate on correct port!\n");
++					(void) DisposeSocket(newSocket);
++					cip->dataSocket = kClosedFileDescriptor;
++					cip->errNo = kErrAcceptDataSocket;
++					return (kErrAcceptDataSocket);
++				} else if (memcmp(&servDataAddr->sin6_addr, &servCtlAddr->sin6_addr, sizeof(servDataAddr->sin6_addr)) != 0) {
++					FTPLogError(cip, kDontPerror, "Data connection did not originate from remote server!\n");
++					(void) DisposeSocket(newSocket);
++					cip->dataSocket = kClosedFileDescriptor;
++					cip->errNo = kErrAcceptDataSocket;
++					return (kErrAcceptDataSocket);
++				}
++			} else {
++#endif
++				struct sockaddr_in *servDataAddr =
++					(struct sockaddr_in *) &cip->servDataAddr;
++				struct sockaddr_in *servCtlAddr =
++					(struct sockaddr_in *) &cip->servCtlAddr;
++
++				remoteDataPort = ntohs(servDataAddr->sin_port);
++				remoteCtrlPort = ntohs(servCtlAddr->sin_port);
++				if ((int) remoteDataPort != ((int) remoteCtrlPort - 1)) {
++					FTPLogError(cip, kDontPerror, "Data connection did not originate on correct port!\n");
++					(void) DisposeSocket(newSocket);
++					cip->dataSocket = kClosedFileDescriptor;
++					cip->errNo = kErrAcceptDataSocket;
++					return (kErrAcceptDataSocket);
++				} else if (memcmp(&servDataAddr->sin_addr.s_addr, &servCtlAddr->sin_addr.s_addr, sizeof(servDataAddr->sin_addr.s_addr)) != 0) {
++					FTPLogError(cip, kDontPerror, "Data connection did not originate on correct port (expecting %d, got %d)!\n", (int) remoteCtrlPort - 1, (int) remoteDataPort);
++					(void) DisposeSocket(newSocket);
++					cip->errNo = kErrDataConnOriginatedFromBadPort;
++					cip->errNo = kErrAcceptDataSocket;
++					return (kErrDataConnOriginatedFromBadPort);
++				}
++#ifdef ENABLE_IPV6
+ 			}
++#endif		
+ 		}
+ 		cip->dataSocket = newSocket;
+ 	}
+-
+ 	return (0);
+ }	/* AcceptDataConnection */
+ 
+Index: ncftp3/libncftp/getaddrinfo.c
+diff -u /dev/null ncftp3/libncftp/getaddrinfo.c:1.1
+--- /dev/null	Mon Nov  9 21:52:32 2009
++++ ncftp3/libncftp/getaddrinfo.c	Tue Nov  6 23:50:46 2001
+@@ -0,0 +1,607 @@
++/*
++ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in the
++ *    documentation and/or other materials provided with the distribution.
++ * 3. Neither the name of the project nor the names of its contributors
++ *    may be used to endorse or promote products derived from this software
++ *    without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
++ * SUCH DAMAGE.
++ */
++
++/*
++ * "#ifdef FAITH" part is local hack for supporting IPv4-v6 translator.
++ *
++ * Issues to be discussed:
++ * - Thread safe-ness must be checked.
++ * - Return values.  There are nonstandard return values defined and used
++ *   in the source code.  This is because RFC2133 is silent about which error
++ *   code must be returned for which situation.
++ * - PF_UNSPEC case would be handled in getipnodebyname() with the AI_ALL flag.
++ */
++
++#include <sys/types.h>
++#include <sys/param.h>
++#include <sys/sysctl.h>
++#include <sys/socket.h>
++#include <netinet/in.h>
++#include <arpa/inet.h>
++#include <arpa/nameser.h>
++#include <netdb.h>
++#include <resolv.h>
++#include <string.h>
++#include <stdlib.h>
++#include <stddef.h>
++#include <ctype.h>
++#include <unistd.h>
++
++#include "addrinfo.h"
++
++#if defined(__KAME__) && defined(INET6)
++# define FAITH
++#endif
++
++#define SUCCESS 0
++#define ANY 0
++#define YES 1
++#define NO  0
++
++#ifdef FAITH
++static int translate = NO;
++static struct in6_addr faith_prefix = IN6ADDR_ANY_INIT;
++#endif
++
++static const char in_addrany[] = { 0, 0, 0, 0 };
++static const char in6_addrany[] = {
++	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
++};
++static const char in_loopback[] = { 127, 0, 0, 1 }; 
++static const char in6_loopback[] = {
++	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
++};
++
++struct sockinet {
++	u_char	si_len;
++	u_char	si_family;
++	u_short	si_port;
++};
++
++static struct afd {
++	int a_af;
++	int a_addrlen;
++	int a_socklen;
++	int a_off;
++	const char *a_addrany;
++	const char *a_loopback;	
++} afdl [] = {
++#ifdef INET6
++#define N_INET6 0
++	{PF_INET6, sizeof(struct in6_addr),
++	 sizeof(struct sockaddr_in6),
++	 offsetof(struct sockaddr_in6, sin6_addr),
++	 in6_addrany, in6_loopback},
++#define N_INET  1
++#else
++#define N_INET  0
++#endif
++	{PF_INET, sizeof(struct in_addr),
++	 sizeof(struct sockaddr_in),
++	 offsetof(struct sockaddr_in, sin_addr),
++	 in_addrany, in_loopback},
++	{0, 0, 0, 0, NULL, NULL},
++};
++
++#ifdef INET6
++#define PTON_MAX	16
++#else
++#define PTON_MAX	4
++#endif
++
++
++static int get_name __P((const char *, struct afd *,
++			  struct addrinfo **, char *, struct addrinfo *,
++			  int));
++static int get_addr __P((const char *, int, struct addrinfo **,
++			struct addrinfo *, int));
++static int str_isnumber __P((const char *));
++	
++static char *ai_errlist[] = {
++	"success.",
++	"address family for hostname not supported.",	/* EAI_ADDRFAMILY */
++	"temporary failure in name resolution.",	/* EAI_AGAIN      */
++	"invalid value for ai_flags.",		       	/* EAI_BADFLAGS   */
++	"non-recoverable failure in name resolution.", 	/* EAI_FAIL       */
++	"ai_family not supported.",			/* EAI_FAMILY     */
++	"memory allocation failure.", 			/* EAI_MEMORY     */
++	"no address associated with hostname.", 	/* EAI_NODATA     */
++	"hostname nor servname provided, or not known.",/* EAI_NONAME     */
++	"servname not supported for ai_socktype.",	/* EAI_SERVICE    */
++	"ai_socktype not supported.", 			/* EAI_SOCKTYPE   */
++	"system error returned in errno.", 		/* EAI_SYSTEM     */
++	"invalid value for hints.",			/* EAI_BADHINTS	  */
++	"resolved protocol is unknown.",		/* EAI_PROTOCOL   */
++	"unknown error.", 				/* EAI_MAX        */
++};
++
++#define GET_CANONNAME(ai, str) \
++if (pai->ai_flags & AI_CANONNAME) {\
++	if (((ai)->ai_canonname = (char *)malloc(strlen(str) + 1)) != NULL) {\
++		strcpy((ai)->ai_canonname, (str));\
++	} else {\
++		error = EAI_MEMORY;\
++		goto free;\
++	}\
++}
++
++#define GET_AI(ai, afd, addr, port) {\
++	char *p;\
++	if (((ai) = (struct addrinfo *)malloc(sizeof(struct addrinfo) +\
++					      ((afd)->a_socklen)))\
++	    == NULL) goto free;\
++	memcpy(ai, pai, sizeof(struct addrinfo));\
++	(ai)->ai_addr = (struct sockaddr *)((ai) + 1);\
++	memset((ai)->ai_addr, 0, (afd)->a_socklen);\
++	(ai)->ai_addr->sa_len = (ai)->ai_addrlen = (afd)->a_socklen;\
++	(ai)->ai_addr->sa_family = (ai)->ai_family = (afd)->a_af;\
++	((struct sockinet *)(ai)->ai_addr)->si_port = port;\
++	p = (char *)((ai)->ai_addr);\
++	memcpy(p + (afd)->a_off, (addr), (afd)->a_addrlen);\
++}
++
++#define ERR(err) { error = (err); goto bad; }
++
++char *
++gai_strerror(ecode)
++	int ecode;
++{
++	if (ecode < 0 || ecode > EAI_MAX)
++		ecode = EAI_MAX;
++	return ai_errlist[ecode];
++}
++
++void
++freeaddrinfo(ai)
++	struct addrinfo *ai;
++{
++	struct addrinfo *next;
++
++	do {
++		next = ai->ai_next;
++		if (ai->ai_canonname)
++			free(ai->ai_canonname);
++		/* no need to free(ai->ai_addr) */
++		free(ai);
++	} while ((ai = next) != NULL);
++}
++
++static int
++str_isnumber(p)
++	const char *p;
++{
++	char *q = (char *)p;
++	while (*q) {
++		if (! isdigit(*q))
++			return NO;
++		q++;
++	}
++	return YES;
++}
++
++int
++getaddrinfo(hostname, servname, hints, res)
++	const char *hostname, *servname;
++	const struct addrinfo *hints;
++	struct addrinfo **res;
++{
++	struct addrinfo sentinel;
++	struct addrinfo *top = NULL;
++	struct addrinfo *cur;
++	int i, error = 0;
++	char pton[PTON_MAX];
++	struct addrinfo ai;
++	struct addrinfo *pai;
++	u_short port;
++
++#ifdef FAITH
++	static int firsttime = 1;
++
++	if (firsttime) {
++		/* translator hack */
++		{
++			char *q = getenv("GAI");
++			if (q && inet_pton(AF_INET6, q, &faith_prefix) == 1)
++				translate = YES;
++		}
++		firsttime = 0;
++	}
++#endif
++
++	/* initialize file static vars */
++	sentinel.ai_next = NULL;
++	cur = &sentinel;
++	pai = &ai;
++	pai->ai_flags = 0;
++	pai->ai_family = PF_UNSPEC;
++	pai->ai_socktype = ANY;
++	pai->ai_protocol = ANY;
++	pai->ai_addrlen = 0;
++	pai->ai_canonname = NULL;
++	pai->ai_addr = NULL;
++	pai->ai_next = NULL;
++	port = ANY;
++	
++	if (hostname == NULL && servname == NULL)
++		return EAI_NONAME;
++	if (hints) {
++		/* error check for hints */
++		if (hints->ai_addrlen || hints->ai_canonname ||
++		    hints->ai_addr || hints->ai_next)
++			ERR(EAI_BADHINTS); /* xxx */
++		if (hints->ai_flags & ~AI_MASK)
++			ERR(EAI_BADFLAGS);
++		switch (hints->ai_family) {
++		case PF_UNSPEC:
++		case PF_INET:
++#ifdef INET6
++		case PF_INET6:
++#endif
++			break;
++		default:
++			ERR(EAI_FAMILY);
++		}
++		memcpy(pai, hints, sizeof(*pai));
++		switch (pai->ai_socktype) {
++		case ANY:
++			switch (pai->ai_protocol) {
++			case ANY:
++				break;
++			case IPPROTO_UDP:
++				pai->ai_socktype = SOCK_DGRAM;
++				break;
++			case IPPROTO_TCP:
++				pai->ai_socktype = SOCK_STREAM;
++				break;
++			default:
++				pai->ai_socktype = SOCK_RAW;
++				break;
++			}
++			break;
++		case SOCK_RAW:
++			break;
++		case SOCK_DGRAM:
++			if (pai->ai_protocol != IPPROTO_UDP &&
++			    pai->ai_protocol != ANY)
++				ERR(EAI_BADHINTS);	/*xxx*/
++			pai->ai_protocol = IPPROTO_UDP;
++			break;
++		case SOCK_STREAM:
++			if (pai->ai_protocol != IPPROTO_TCP &&
++			    pai->ai_protocol != ANY)
++				ERR(EAI_BADHINTS);	/*xxx*/
++			pai->ai_protocol = IPPROTO_TCP;
++			break;
++		default:
++			ERR(EAI_SOCKTYPE);
++			break;
++		}
++	}
++
++	/*
++	 * service port
++	 */
++	if (servname) {
++		if (str_isnumber(servname)) {
++			if (pai->ai_socktype == ANY) {
++				/* caller accept *ANY* socktype */
++				pai->ai_socktype = SOCK_DGRAM;
++				pai->ai_protocol = IPPROTO_UDP;
++			}
++			port = htons(atoi(servname));
++		} else {
++			struct servent *sp;
++			char *proto;
++
++			proto = NULL;
++			switch (pai->ai_socktype) {
++			case ANY:
++				proto = NULL;
++				break;
++			case SOCK_DGRAM:
++				proto = "udp";
++				break;
++			case SOCK_STREAM:
++				proto = "tcp";
++				break;
++			default:
++				fprintf(stderr, "panic!\n");
++				break;
++			}
++			if ((sp = getservbyname(servname, proto)) == NULL)
++				ERR(EAI_SERVICE);
++			port = sp->s_port;
++			if (pai->ai_socktype == ANY)
++				if (strcmp(sp->s_proto, "udp") == 0) {
++					pai->ai_socktype = SOCK_DGRAM;
++					pai->ai_protocol = IPPROTO_UDP;
++				} else if (strcmp(sp->s_proto, "tcp") == 0) {
++					pai->ai_socktype = SOCK_STREAM;
++					pai->ai_protocol = IPPROTO_TCP;
++				} else
++					ERR(EAI_PROTOCOL);	/*xxx*/
++		}
++	}
++	
++	/*
++	 * hostname == NULL.
++	 * passive socket -> anyaddr (0.0.0.0 or ::)
++	 * non-passive socket -> localhost (127.0.0.1 or ::1)
++	 */
++	if (hostname == NULL) {
++		struct afd *afd;
++
++		for (afd = &afdl[0]; afd->a_af; afd++) {
++			if (!(pai->ai_family == PF_UNSPEC
++			   || pai->ai_family == afd->a_af)) {
++				continue;
++			}
++
++			if (pai->ai_flags & AI_PASSIVE) {
++				GET_AI(cur->ai_next, afd, afd->a_addrany, port);
++				/* xxx meaningless?
++				 * GET_CANONNAME(cur->ai_next, "anyaddr");
++				 */
++			} else {
++				GET_AI(cur->ai_next, afd, afd->a_loopback,
++					port);
++				/* xxx meaningless?
++				 * GET_CANONNAME(cur->ai_next, "localhost");
++				 */
++			}
++			cur = cur->ai_next;
++		}
++		top = sentinel.ai_next;
++		if (top)
++			goto good;
++		else
++			ERR(EAI_FAMILY);
++	}
++	
++	/* hostname as numeric name */
++	for (i = 0; afdl[i].a_af; i++) {
++		if (inet_pton(afdl[i].a_af, hostname, pton)) {
++			u_long v4a;
++			u_char pfx;
++
++			switch (afdl[i].a_af) {
++			case AF_INET:
++				v4a = ((struct in_addr *)pton)->s_addr;
++				if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
++					pai->ai_flags &= ~AI_CANONNAME;
++				v4a >>= IN_CLASSA_NSHIFT;
++				if (v4a == 0 || v4a == IN_LOOPBACKNET)
++					pai->ai_flags &= ~AI_CANONNAME;
++				break;
++#ifdef INET6
++			case AF_INET6:
++				pfx = ((struct in6_addr *)pton)->s6_addr8[0];
++				if (pfx == 0 || pfx == 0xfe || pfx == 0xff)
++					pai->ai_flags &= ~AI_CANONNAME;
++				break;
++#endif
++			}
++			
++			if (pai->ai_family == afdl[i].a_af ||
++			    pai->ai_family == PF_UNSPEC) {
++				if (! (pai->ai_flags & AI_CANONNAME)) {
++					GET_AI(top, &afdl[i], pton, port);
++					goto good;
++				}
++				/*
++				 * if AI_CANONNAME and if reverse lookup
++				 * fail, return ai anyway to pacify
++				 * calling application.
++				 *
++				 * XXX getaddrinfo() is a name->address
++				 * translation function, and it looks strange
++				 * that we do addr->name translation here.
++				 */
++				get_name(pton, &afdl[i], &top, pton, pai, port);
++				goto good;
++			} else 
++				ERR(EAI_FAMILY);	/*xxx*/
++		}
++	}
++
++	if (pai->ai_flags & AI_NUMERICHOST)
++		ERR(EAI_NONAME);
++
++	/* hostname as alphabetical name */
++	error = get_addr(hostname, pai->ai_family, &top, pai, port);
++	if (error == 0) {
++		if (top) {
++ good:
++			*res = top;
++			return SUCCESS;
++		} else
++			error = EAI_FAIL;
++	}
++ free:
++	if (top)
++		freeaddrinfo(top);
++ bad:
++	*res = NULL;
++	return error;
++}
++
++static int
++get_name(addr, afd, res, numaddr, pai, port0)
++	const char *addr;
++	struct afd *afd;
++	struct addrinfo **res;
++	char *numaddr;
++	struct addrinfo *pai;
++	int port0;
++{
++	u_short port = port0 & 0xffff;
++	struct hostent *hp;
++	struct addrinfo *cur;
++	int error = 0, h_error;
++	
++#ifdef INET6
++	hp = getipnodebyaddr(addr, afd->a_addrlen, afd->a_af, &h_error);
++#else
++	hp = gethostbyaddr(addr, afd->a_addrlen, AF_INET);
++#endif
++	if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) {
++		GET_AI(cur, afd, hp->h_addr_list[0], port);
++		GET_CANONNAME(cur, hp->h_name);
++	} else
++		GET_AI(cur, afd, numaddr, port);
++	
++#ifdef INET6
++	if (hp)
++		freehostent(hp);
++#endif
++	*res = cur;
++	return SUCCESS;
++ free:
++	if (cur)
++		freeaddrinfo(cur);
++#ifdef INET6
++	if (hp)
++		freehostent(hp);
++#endif
++ /* bad: */
++	*res = NULL;
++	return error;
++}
++
++static int
++get_addr(hostname, af, res, pai, port0)
++	const char *hostname;
++	int af;
++	struct addrinfo **res;
++	struct addrinfo *pai;
++	int port0;
++{
++	u_short port = port0 & 0xffff;
++	struct addrinfo sentinel;
++	struct hostent *hp;
++	struct addrinfo *top, *cur;
++	struct afd *afd;
++	int i, error = 0, h_error;
++	char *ap;
++#ifndef INET6
++	extern int h_errno;
++#endif
++
++	top = NULL;
++	sentinel.ai_next = NULL;
++	cur = &sentinel;
++#ifdef INET6
++	if (af == AF_UNSPEC) {
++		hp = getipnodebyname(hostname, AF_INET6,
++				AI_ADDRCONFIG|AI_ALL|AI_V4MAPPED, &h_error);
++	} else
++		hp = getipnodebyname(hostname, af, AI_ADDRCONFIG, &h_error);
++#else
++	hp = gethostbyname(hostname);
++	h_error = h_errno;
++#endif
++	if (hp == NULL) {
++		switch (h_error) {
++		case HOST_NOT_FOUND:
++		case NO_DATA:
++			error = EAI_NODATA;
++			break;
++		case TRY_AGAIN:
++			error = EAI_AGAIN;
++			break;
++		case NO_RECOVERY:
++		default:
++			error = EAI_FAIL;
++			break;
++		}
++		goto bad;
++	}
++
++	if ((hp->h_name == NULL) || (hp->h_name[0] == 0) ||
++	    (hp->h_addr_list[0] == NULL))
++		ERR(EAI_FAIL);
++	
++	for (i = 0; (ap = hp->h_addr_list[i]) != NULL; i++) {
++		switch (af) {
++#ifdef INET6
++		case AF_INET6:
++			afd = &afdl[N_INET6];
++			break;
++#endif
++#ifndef INET6
++		default:	/* AF_UNSPEC */
++#endif
++		case AF_INET:
++			afd = &afdl[N_INET];
++			break;
++#ifdef INET6
++		default:	/* AF_UNSPEC */
++			if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ap)) {
++				ap += sizeof(struct in6_addr) -
++					sizeof(struct in_addr);
++				afd = &afdl[N_INET];
++			} else
++				afd = &afdl[N_INET6];
++			break;
++#endif
++		}
++#ifdef FAITH
++		if (translate && afd->a_af == AF_INET) {
++			struct in6_addr *in6;
++
++			GET_AI(cur->ai_next, &afdl[N_INET6], ap, port);
++			in6 = &((struct sockaddr_in6 *)cur->ai_next->ai_addr)->sin6_addr;
++			memcpy(&in6->s6_addr32[0], &faith_prefix,
++			    sizeof(struct in6_addr) - sizeof(struct in_addr));
++			memcpy(&in6->s6_addr32[3], ap, sizeof(struct in_addr));
++		} else
++#endif /* FAITH */
++		GET_AI(cur->ai_next, afd, ap, port);
++		if (cur == &sentinel) {
++			top = cur->ai_next;
++			GET_CANONNAME(top, hp->h_name);
++		}
++		cur = cur->ai_next;
++	}
++#ifdef INET6
++	freehostent(hp);
++#endif
++	*res = top;
++	return SUCCESS;
++ free:
++	if (top)
++		freeaddrinfo(top);
++#ifdef INET6
++	if (hp)
++		freehostent(hp);
++#endif
++ bad:
++	*res = NULL;
++	return error;
++}
+Index: ncftp3/libncftp/getnameinfo.c
+diff -u /dev/null ncftp3/libncftp/getnameinfo.c:1.1
+--- /dev/null	Mon Nov  9 21:52:32 2009
++++ ncftp3/libncftp/getnameinfo.c	Tue Nov  6 23:50:47 2001
+@@ -0,0 +1,203 @@
++/*
++ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
++ * All rights reserved.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in the
++ *    documentation and/or other materials provided with the distribution.
++ * 3. Neither the name of the project nor the names of its contributors
++ *    may be used to endorse or promote products derived from this software
++ *    without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
++ * SUCH DAMAGE.
++ */
++
++/*
++ * Issues to be discussed:
++ * - Thread safe-ness must be checked
++ * - Return values.  There seems to be no standard for return value (RFC2133)
++ *   but INRIA implementation returns EAI_xxx defined for getaddrinfo().
++ */
++
++#include <sys/types.h>
++#include <sys/socket.h>
++#include <netinet/in.h>
++#include <arpa/inet.h>
++#include <arpa/nameser.h>
++#include <netdb.h>
++#include <resolv.h>
++#include <string.h>
++#include <stddef.h>
++
++#include "addrinfo.h"
++
++#define SUCCESS 0
++#define ANY 0
++#define YES 1
++#define NO  0
++
++static struct afd {
++	int a_af;
++	int a_addrlen;
++	int a_socklen;
++	int a_off;
++} afdl [] = {
++#ifdef INET6
++	{PF_INET6, sizeof(struct in6_addr), sizeof(struct sockaddr_in6),
++		offsetof(struct sockaddr_in6, sin6_addr)},
++#endif
++	{PF_INET, sizeof(struct in_addr), sizeof(struct sockaddr_in),
++		offsetof(struct sockaddr_in, sin_addr)},
++	{0, 0, 0},
++};
++
++struct sockinet {
++	u_char	si_len;
++	u_char	si_family;
++	u_short	si_port;
++};
++
++#define ENI_NOSOCKET 	0
++#define ENI_NOSERVNAME	1
++#define ENI_NOHOSTNAME	2
++#define ENI_MEMORY	3
++#define ENI_SYSTEM	4
++#define ENI_FAMILY	5
++#define ENI_SALEN	6
++
++int
++getnameinfo(sa, salen, host, hostlen, serv, servlen, flags)
++	const struct sockaddr *sa;
++	size_t salen;
++	char *host;
++	size_t hostlen;
++	char *serv;
++	size_t servlen;
++	int flags;
++{
++	struct afd *afd;
++	struct servent *sp;
++	struct hostent *hp;
++	u_short port;
++	int family, len, i;
++	char *addr, *p;
++	u_long v4a;
++	u_char pfx;
++	int h_error;
++	char numserv[512];
++	char numaddr[512];
++
++	if (sa == NULL)
++		return ENI_NOSOCKET;
++
++	len = sa->sa_len;
++	if (len != salen) return ENI_SALEN;
++	
++	family = sa->sa_family;
++	for (i = 0; afdl[i].a_af; i++)
++		if (afdl[i].a_af == family) {
++			afd = &afdl[i];
++			goto found;
++		}
++	return ENI_FAMILY;
++	
++ found:
++	if (len != afd->a_socklen) return ENI_SALEN;
++	
++	port = ((struct sockinet *)sa)->si_port; /* network byte order */
++	addr = (char *)sa + afd->a_off;
++
++	if (serv == NULL || servlen == 0) {
++		/* what we should do? */
++	} else if (flags & NI_NUMERICSERV) {
++		snprintf(numserv, sizeof(numserv), "%d", ntohs(port));
++		if (strlen(numserv) > servlen)
++			return ENI_MEMORY;
++		strcpy(serv, numserv);
++	} else {
++		sp = getservbyport(port, (flags & NI_DGRAM) ? "udp" : "tcp");
++		if (sp) {
++			if (strlen(sp->s_name) > servlen)
++				return ENI_MEMORY;
++			strcpy(serv, sp->s_name);
++		} else
++			return ENI_NOSERVNAME;
++	}
++
++	switch (sa->sa_family) {
++	case AF_INET:
++		v4a = ((struct sockaddr_in *)sa)->sin_addr.s_addr;
++		if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
++			flags |= NI_NUMERICHOST;
++		v4a >>= IN_CLASSA_NSHIFT;
++		if (v4a == 0 || v4a == IN_LOOPBACKNET)
++			flags |= NI_NUMERICHOST;			
++		break;
++#ifdef INET6
++	case AF_INET6:
++		pfx = ((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr8[0];
++		if (pfx == 0 || pfx == 0xfe || pfx == 0xff)
++			flags |= NI_NUMERICHOST;
++		break;
++#endif
++	}
++	if (host == NULL || hostlen == 0) {
++		/* what should we do? */
++	} else if (flags & NI_NUMERICHOST) {
++		if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
++		    == NULL)
++			return ENI_SYSTEM;
++		if (strlen(numaddr) > hostlen)
++			return ENI_MEMORY;
++		strcpy(host, numaddr);
++	} else {
++#ifdef INET6
++		hp = getipnodebyaddr(addr, afd->a_addrlen, afd->a_af, &h_error);
++#else
++		hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af);
++		h_error = h_errno;
++#endif
++
++		if (hp) {
++			if (flags & NI_NOFQDN) {
++				p = strchr(hp->h_name, '.');
++				if (p) *p = '\0';
++			}
++			if (strlen(hp->h_name) > hostlen) {
++#ifdef INET6
++				freehostent(hp);
++#endif
++				return ENI_MEMORY;
++			}
++			strcpy(host, hp->h_name);
++#ifdef INET6
++			freehostent(hp);
++#endif
++		} else {
++			if (flags & NI_NAMEREQD)
++				return ENI_NOHOSTNAME;
++			if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
++			    == NULL)
++				return ENI_NOHOSTNAME;
++			if (strlen(numaddr) > hostlen)
++				return ENI_MEMORY;
++			strcpy(host, numaddr);
++		}
++	}
++	return SUCCESS;
++}
+Index: ncftp3/libncftp/ncftp.h
+diff -u ncftp3/libncftp/ncftp.h:1.1.1.23 ncftp3/libncftp/ncftp.h:1.28
+--- ncftp3/libncftp/ncftp.h:1.1.1.23	Thu Nov  5 16:20:41 2009
++++ ncftp3/libncftp/ncftp.h	Thu Nov  5 16:47:09 2009
+@@ -378,11 +378,10 @@
+ 	int mlsFeatures;			/* Do not modify this field. */
+ 	int STATfileParamWorks;			/* Do not modify this field. */
+ 	int NLSTfileParamWorks;			/* Do not modify this field. */
+-
+-	struct sockaddr_in servCtlAddr;		/* Do not modify this field. */
+-	struct sockaddr_in servDataAddr;	/* Do not modify this field. */
+-	struct sockaddr_in ourCtlAddr;		/* Do not modify this field. */
+-	struct sockaddr_in ourDataAddr;		/* Do not modify this field. */
++	struct sockaddr_storage servCtlAddr;	/* Do not modify this field. */
++	struct sockaddr_storage servDataAddr;	/* Do not modify this field. */
++	struct sockaddr_storage ourCtlAddr;	/* Do not modify this field. */
++	struct sockaddr_storage ourDataAddr;	/* Do not modify this field. */
+ 	int netMode;				/* Do not use or modify. */
+ 	char *buf;				/* Do not modify this field. */
+ 	size_t bufSize;				/* Do not modify this field. */
+@@ -997,8 +996,8 @@
+ 
+ /* Everything else below are private routines, or stuff for testing */
+ int FTPInitConnectionInfo2(const FTPLIPtr lip, const FTPCIPtr cip, char *const buf, size_t bufSize);
+-int FTPSendPort(const FTPCIPtr cip, struct sockaddr_in *saddr);
+-int FTPSendPassive(const FTPCIPtr cip, struct sockaddr_in *saddr, int *weird);
++int FTPSendPort(const FTPCIPtr cip, struct sockaddr *saddr);
++int FTPSendPassive(const FTPCIPtr cip, struct sockaddr *saddr, int *weird);
+ int FTPSetStartOffset(const FTPCIPtr cip, longest_int restartPt);
+ void FTPCloseControlConnection(const FTPCIPtr cip);
+ int FTPSendCommandStr(const FTPCIPtr cip, char *const command, const size_t siz);
+@@ -1060,7 +1059,7 @@
+ int FTPFileExists2(const FTPCIPtr cip, const char *const file, const int tryMDTM, const int trySIZE, const int tryMLST, const int trySTAT, const int tryNLST);
+ 
+ void FTPGetDateStr(time_t t, const char *fmt, char *const ltstr1, const size_t ltstr1size, char *const gtstr1, const size_t gtstr1size);
+-int BindToEphemeralPortNumber(const int sockfd, struct sockaddr_in *const addrp, const int ephemLo, const int ephemHi);
++int BindToEphemeralPortNumber(const int sockfd, struct sockaddr *const addrp, const int ephemLo, const int ephemHi);
+ int BufferGets(char *, size_t, int, char *, char **, char **, size_t);
+ void DisposeFileInfoListContents(FTPFileInfoListPtr);
+ void InitFileInfoList(FTPFileInfoListPtr);
+Index: ncftp3/libncftp/syshdrs.h
+diff -u ncftp3/libncftp/syshdrs.h:1.1.1.15 ncftp3/libncftp/syshdrs.h:1.14
+--- ncftp3/libncftp/syshdrs.h:1.1.1.15	Thu Nov  5 16:20:41 2009
++++ ncftp3/libncftp/syshdrs.h	Thu Nov  5 16:47:09 2009
+@@ -24,6 +24,10 @@
+ #		define _WIN32_WINNT 0x0400
+ #	endif
+ #	include <windows.h>		/* includes <winsock2.h> if _WIN32_WINNT >= 0x400 */
++#	ifdef ENABLE_IPV6
++#	include <ws2tcpip.h>
++#	define INET6_ADDRSTRLEN 46
++#	endif /* ENABLE_IPV6 */
+ #	include <shlobj.h>
+ #	include <io.h>
+ #	include <conio.h>
+@@ -164,6 +168,9 @@
+ #		include <resolv.h>
+ #	endif
+ 
++#	ifndef HAVE_GETADDRINFO
++#	include "addrinfo.h"
++#	endif
+ #	ifdef CAN_USE_SYS_SELECT_H
+ #		include <sys/select.h>
+ #	endif
+--- ncftp-3.2.5/ncftp/cmds.c.orig	2010-04-05 21:33:21.000000000 +0200
++++ ncftp-3.2.5/ncftp/cmds.c	2011-03-27 15:37:19.813736435 +0200
+@@ -2580,8 +2580,7 @@
+                         return (-1);
+                 }
+ #endif
+-		(void) STRNCPY(gConn.host, ipstr);
+-		OpenMsg("Connecting to %s...", ipstr);
++		OpenMsg("Connecting to %s...", gConn.host);
+ 	} else {
+ 		OpenMsg("Connecting to %s via %s...", gConn.host, gConn.firewallHost);
+ 		Trace(0, "Fw: %s  Type: %d  User: %s  Pass: %s  Port: %u\n", 
+@@ -3784,8 +3783,8 @@
+ 	char preferredLocalAddrStr[64];
+ 
+ 	preferredLocalAddrStr[0] = '\0';
+-	if (gConn.preferredLocalAddr.sin_family != 0)
+-		AddrToAddrStr(preferredLocalAddrStr, sizeof(preferredLocalAddrStr), &gConn.preferredLocalAddr, 0, "%h");
++	if (gConn.preferredLocalAddr.sin_family == AF_INET)
++		AddrToAddrStr(preferredLocalAddrStr, sizeof(preferredLocalAddrStr), (struct sockaddr *)&gConn.preferredLocalAddr, 0, "%h");
+ 
+ 	if (ftwip->depth >= 50) {
+ 		Trace(-1, "Aborting -- recursion depth is %u.\nPerhaps an infinite loop exists on the remote filesystem?", (unsigned int) ftwip->depth);
+@@ -3952,8 +3951,8 @@
+ 	char preferredLocalAddrStr[64];
+ 
+ 	preferredLocalAddrStr[0] = '\0';
+-	if (gConn.preferredLocalAddr.sin_family != 0)
+-		AddrToAddrStr(preferredLocalAddrStr, sizeof(preferredLocalAddrStr), &gConn.preferredLocalAddr, 0, "%h");
++	if (gConn.preferredLocalAddr.sin_family == AF_INET)
++		AddrToAddrStr(preferredLocalAddrStr, sizeof(preferredLocalAddrStr), (struct sockaddr *)&gConn.preferredLocalAddr, 0, "%h");
+ 
+ 	cinfo.xtype = gBm.xferType;
+ 	cinfo.deleteFlag = kDeleteNo;
+@@ -4160,8 +4159,8 @@
+ 	char preferredLocalAddrStr[64];
+ 
+ 	preferredLocalAddrStr[0] = '\0';
+-	if (gConn.preferredLocalAddr.sin_family != 0)
+-		AddrToAddrStr(preferredLocalAddrStr, sizeof(preferredLocalAddrStr), &gConn.preferredLocalAddr, 0, "%h");
++	if (gConn.preferredLocalAddr.sin_family == AF_INET)
++		AddrToAddrStr(preferredLocalAddrStr, sizeof(preferredLocalAddrStr), (struct sockaddr *)&gConn.preferredLocalAddr, 0, "%h");
+ 
+ 	cinfop = (SpoolCmdInfo *) ftwip->userdata;
+ 	/* rerpath = ftwip->curPath + ftwip->startPathLen + 1; */
+@@ -4321,8 +4320,8 @@
+ 	char preferredLocalAddrStr[64];
+ 
+ 	preferredLocalAddrStr[0] = '\0';
+-	if (gConn.preferredLocalAddr.sin_family != 0)
+-		AddrToAddrStr(preferredLocalAddrStr, sizeof(preferredLocalAddrStr), &gConn.preferredLocalAddr, 0, "%h");
++	if (gConn.preferredLocalAddr.sin_family == AF_INET)
++		AddrToAddrStr(preferredLocalAddrStr, sizeof(preferredLocalAddrStr), (struct sockaddr *)&gConn.preferredLocalAddr, 0, "%h");
+ 
+ 	cinfo.xtype = gBm.xferType;
+ 	cinfo.deleteFlag = kDeleteNo;
+Index: ncftp3/ncftp/syshdrs.h
+diff -u ncftp3/ncftp/syshdrs.h:1.1.1.15 ncftp3/ncftp/syshdrs.h:1.13
+--- ncftp3/ncftp/syshdrs.h:1.1.1.15	Thu Nov  5 16:20:41 2009
++++ ncftp3/ncftp/syshdrs.h	Thu Nov  5 16:47:09 2009
+@@ -33,6 +33,9 @@
+ #		define _WIN32_WINNT 0x0400
+ #	endif
+ #	include <windows.h>		/* includes <winsock2.h> if _WIN32_WINNT >= 0x400 */
++#ifdef ENABLE_IPV6
++#	include <ws2tcpip.h>
++#endif /* ENABLE_IPV6 */
+ #	include <shlobj.h>
+ #	include <process.h>
+ #	include <direct.h>
+@@ -174,6 +177,9 @@
+ #	include <time.h>
+ #	include <pwd.h>
+ #	include <fcntl.h>
++#	ifndef HAVE_GETADDRINFO
++#		include "addrinfo.h"
++#	endif
+ #	if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_TERMIOS_H)
+ #		include <sys/ioctl.h>
+ #		include <termios.h>
+--- ncftp-3.2.5/ncftp/util.c.orig	2010-10-30 23:34:25.000000000 +0200
++++ ncftp-3.2.5/ncftp/util.c	2011-03-27 15:41:18.901729730 +0200
+@@ -666,47 +666,29 @@
+ int
+ MyGetHostByName(char *const volatile dst, size_t dsize, const char *const hn, int t)
+ {
++	struct addrinfo hints;
++	struct addrinfo *res;
++	int error;
+ #if (defined(WIN32) || defined(_WINDOWS)) && !defined(__CYGWIN__)
+-	struct hostent *hp;
+-	struct in_addr ina;
+-
+-	if (inet_addr(hn) != (unsigned long) 0xFFFFFFFF) {
+-		/* Address is an IP address string, which is what we want. */
+-		(void) Strncpy(dst, hn, dsize);
+-		return (0);
+-	}
+-
+-	hp = gethostbyname(hn);
+-	if (hp != NULL) {
+-		(void) memcpy(&ina.s_addr, hp->h_addr_list[0], (size_t) hp->h_length);
+-		InetNtoA(dst, ((struct in_addr **) hp->h_addr_list)[0], dsize);
++	memset(&hints, 0, sizeof(hints));
++	hints.ai_family = PF_UNSPEC;
++	hints.ai_socktype = SOCK_STREAM;
++	error = getaddrinfo(hn, NULL, &hints, &res);
++
++	if (error == 0) {
++		char buf[NI_MAXHOST];
++
++		getnameinfo(res->ai_addr, res->ai_addrlen,
++			    buf, sizeof(buf),
++			    NULL, 0, NI_NUMERICHOST);
++		(void) Strncpy(dst, buf, dsize);
++		freeaddrinfo(res);
+ 		return (0);
+ 	}
+ 
+ #else
+ 	int sj;
+ 	vsigproc_t osigpipe, osigint, osigalrm;
+-	struct hostent *hp;
+-#ifdef HAVE_INET_ATON
+-	struct in_addr ina;
+-#endif
+-#ifdef DNSSEC_LOCAL_VALIDATION
+-        val_status_t val_status;
+-#endif
+-
+-#ifdef HAVE_INET_ATON
+-	if (inet_aton(hn, &ina) != 0) {
+-		/* Address is an IP address string, which is what we want. */
+-		(void) Strncpy(dst, hn, dsize);
+-		return (0);
+-	}
+-#else
+-	if (inet_addr(hn) != (unsigned long) 0xFFFFFFFF) {
+-		/* Address is an IP address string, which is what we want. */
+-		(void) Strncpy(dst, hn, dsize);
+-		return (0);
+-	}
+-#endif
+ 
+ #ifdef HAVE_SIGSETJMP
+ 	osigpipe = osigint = osigalrm = (sigproc_t) 0;
+@@ -731,30 +713,27 @@
+ 		osigalrm = NcSignal(SIGALRM, CancelGetHostByName);
+ 		if (t > 0)
+ 			(void) alarm((unsigned int) t);
+-#ifndef DNSSEC_LOCAL_VALIDATION
+-		hp = gethostbyname(hn);
+-#else
+-                hp = val_gethostbyname(NULL, hn, &val_status);
+-#endif
++		memset(&hints, 0, sizeof(hints));
++		hints.ai_flags = 0;
++		hints.ai_family = PF_UNSPEC;
++		hints.ai_socktype = SOCK_STREAM;
++		hints.ai_protocol = 0;
++		error = getaddrinfo(hn, NULL, &hints, &res);
+ 		if (t > 0)
+ 			(void) alarm(0);
+ 		(void) NcSignal(SIGPIPE, osigpipe);
+ 		(void) NcSignal(SIGINT, osigint);
+ 		(void) NcSignal(SIGALRM, osigalrm);
+-#ifdef DNSSEC_LOCAL_VALIDATION
+-                /*
+-                 * It would be nice to pass a little more information back,
+-                 * but that would mean an API change to MyGetHostByName.
+-                 */
+-                if ((hp != NULL) && ! val_istrusted(val_status)) {
+-                    *dst = '\0';
+-                    return (-2);
+-                }
+-#endif
+-		if (hp != NULL) {
+-			InetNtoA(dst, ((struct in_addr **) hp->h_addr_list)[0], dsize);
+-			return (0);
+-		}
++		if (error == 0) {
++			char buf[NI_MAXHOST];
++
++			getnameinfo(res->ai_addr, res->ai_addrlen,
++				    buf, sizeof(buf),
++				    NULL, 0, NI_NUMERICHOST);
++			(void) Strncpy(dst, buf, dsize);
++			freeaddrinfo(res);
++ 			return (0);
++ 		}
+ 	}
+ #endif	/* !Windows */
+ 
+Index: ncftp3/sh_util/ncftpbatch.c
+diff -u ncftp3/sh_util/ncftpbatch.c:1.1.1.20 ncftp3/sh_util/ncftpbatch.c:1.2
+--- ncftp3/sh_util/ncftpbatch.c:1.1.1.20	Thu Nov  5 16:20:41 2009
++++ ncftp3/sh_util/ncftpbatch.c	Mon Nov  9 21:51:14 2009
+@@ -1203,7 +1203,7 @@
+ 		}
+ 
+ 		if (gSourceAddrStr[0] != '\0')
+-			(void) AddrStrToAddr(gSourceAddrStr, &gConn.preferredLocalAddr, 21);
++			(void) AddrStrToAddr(gSourceAddrStr, (struct sockaddr *)&gConn.preferredLocalAddr, 21);
+ 		
+ 		gConn.connTimeout = 30;
+ 		gConn.ctrlTimeout = 135;
+Index: ncftp3/sh_util/ncftpget.c
+diff -u ncftp3/sh_util/ncftpget.c:1.1.1.19 ncftp3/sh_util/ncftpget.c:1.2
+--- ncftp3/sh_util/ncftpget.c:1.1.1.19	Thu Nov  5 16:20:41 2009
++++ ncftp3/sh_util/ncftpget.c	Mon Nov  9 21:51:14 2009
+@@ -371,7 +371,7 @@
+ 			ftpcat = 2;
+ 			break;
+ 		case 'I':
+-			if (AddrStrToAddr(opt.arg, &fi.preferredLocalAddr, 21) < 0) {
++			if (AddrStrToAddr(opt.arg, (struct sockaddr *)&fi.preferredLocalAddr, 21) < 0) {
+ 				fprintf(stderr, "Bad IP address (\"%s\") used with -I.\n", opt.arg);
+ 				Usage();
+ 			}
+Index: ncftp3/sh_util/ncftpls.c
+diff -u ncftp3/sh_util/ncftpls.c:1.1.1.16 ncftp3/sh_util/ncftpls.c:1.2
+--- ncftp3/sh_util/ncftpls.c:1.1.1.16	Thu Nov  5 16:20:41 2009
++++ ncftp3/sh_util/ncftpls.c	Mon Nov  9 21:51:14 2009
+@@ -489,7 +489,7 @@
+ 			do_listings = 0;
+ 			break;
+ 		case 'I':
+-			if (AddrStrToAddr(opt.arg, &fi.preferredLocalAddr, 21) < 0) {
++			if (AddrStrToAddr(opt.arg, (struct sockaddr *)&fi.preferredLocalAddr, 21) < 0) {
+ 				fprintf(stderr, "Bad IP address (\"%s\") used with -I.\n", opt.arg);
+ 				Usage();
+ 			}
+Index: ncftp3/sh_util/ncftpput.c
+diff -u ncftp3/sh_util/ncftpput.c:1.1.1.18 ncftp3/sh_util/ncftpput.c:1.2
+--- ncftp3/sh_util/ncftpput.c:1.1.1.18	Thu Nov  5 16:20:41 2009
++++ ncftp3/sh_util/ncftpput.c	Mon Nov  9 21:51:14 2009
+@@ -388,7 +388,7 @@
+ 			STRNCAT(postcmd, "\n");
+ 			break;
+ 		case 'I':
+-			if (AddrStrToAddr(opt.arg, &fi.preferredLocalAddr, 21) < 0) {
++			if (AddrStrToAddr(opt.arg, (struct sockaddr *)&fi.preferredLocalAddr, 21) < 0) {
+ 				fprintf(stderr, "Bad IP address (\"%s\") used with -I.\n", opt.arg);
+ 				Usage();
+ 			}
+Index: ncftp3/sh_util/syshdrs.h
+diff -u ncftp3/sh_util/syshdrs.h:1.1.1.11 ncftp3/sh_util/syshdrs.h:1.11
+--- ncftp3/sh_util/syshdrs.h:1.1.1.11	Thu Nov  5 16:20:41 2009
++++ ncftp3/sh_util/syshdrs.h	Thu Nov  5 16:47:09 2009
+@@ -33,6 +33,9 @@
+ #		define _WIN32_WINNT 0x0400
+ #	endif
+ #	include <windows.h>		/* includes <winsock2.h> if _WIN32_WINNT >= 0x400 */
++#ifdef ENABLE_IPV6
++#	include <ws2tcpip.h>
++#endif /* ENABLE_IPV6 */
+ #	include <shlobj.h>
+ #	include <tchar.h>
+ #	include <process.h>
+@@ -167,6 +170,9 @@
+ #	include <pwd.h>
+ #	include <fcntl.h>
+ #	include <dirent.h>
++#	ifndef HAVE_GETADDRINFO
++#		include "addrinfo.h"
++#	endif
+ #	ifdef HAVE_LOCALE_H
+ #		include <locale.h>
+ #	endif
+Index: ncftp3/sio/SAccept.c
+diff -u ncftp3/sio/SAccept.c:1.1.1.1 ncftp3/sio/SAccept.c:1.4
+--- ncftp3/sio/SAccept.c:1.1.1.1	Thu Jan  8 19:51:19 2004
++++ ncftp3/sio/SAccept.c	Wed Aug 25 21:33:11 2004
+@@ -3,8 +3,20 @@
+ #	pragma hdrstop
+ #endif
+ 
++#ifndef HAVE_SOCKADDR_SA_LEN
++#ifndef SA_LEN
++#ifdef ENABLE_IPV6
++#define SA_LEN(x) (((x)->sa_family == AF_INET6) ? sizeof(struct sockaddr_in6) \
++		: (((x)->sa_family == AF_INET) ? sizeof(struct sockaddr_in) \
++		: -1))
++#else  /* ENABLE_IPV6 */
++#define SA_LEN(x) (((x)->sa_family == AF_INET) ? sizeof(struct sockaddr_in) : -1)
++#endif /* ENABLE_IPV6 */
++#endif /* SA_LEN */
++#endif /* HAVE_SOCKADDR_SA_LEN */
++
+ int
+-SAccept(int sfd, struct sockaddr_in *const addr, int tlen)
++SAccept(int sfd, struct sockaddr *const addr, int tlen)
+ {
+ 	int result;
+ 	fd_set ss;
+@@ -22,7 +34,7 @@
+ 	if (tlen <= 0) {
+ 		errno = 0;
+ 		for (;;) {
+-			size = (sockaddr_size_t) sizeof(struct sockaddr_in);
++			size = (sockaddr_size_t) sizeof(struct sockaddr_storage);
+ 			result = accept(sfd, (struct sockaddr *) addr, &size);
+ 			if ((result >= 0) || (errno != EINTR)) {
+ 				RESTORE_SIGPIPE
+@@ -61,7 +73,7 @@
+ 	}
+ 
+ 	do {
+-		size = (sockaddr_size_t) sizeof(struct sockaddr_in);
++		size = (sockaddr_size_t) sizeof(struct sockaddr_storage);
+ 		result = accept(sfd, (struct sockaddr *) addr, &size);
+ 	} while ((result < 0) && (errno == EINTR));
+ 
+Index: ncftp3/sio/SConnect.c
+diff -u ncftp3/sio/SConnect.c:1.1.1.10 ncftp3/sio/SConnect.c:1.18
+--- ncftp3/sio/SConnect.c:1.1.1.10	Thu Nov  5 16:20:41 2009
++++ ncftp3/sio/SConnect.c	Thu Nov  5 16:47:09 2009
+@@ -3,14 +3,30 @@
+ #	pragma hdrstop
+ #endif
+ 
+-int _SConnect(const int sfd, const struct sockaddr_in *const addr, const size_t saddrsiz, const int tlen);
++int _SConnect(const int sfd, const struct sockaddr *const addr, const size_t saddrsiz, const int tlen);
++
++#ifndef HAVE_SOCKADDR_SA_LEN
++#ifndef SA_LEN
++#ifdef ENABLE_IPV6
++#define SA_LEN(x) (((x)->sa_family == AF_INET6) ? sizeof(struct sockaddr_in6) \
++		: (((x)->sa_family == AF_INET) ? sizeof(struct sockaddr_in) \
++		: -1))
++#else  /* ENABLE_IPV6 */
++#define SA_LEN(x) (((x)->sa_family == AF_INET) ? sizeof(struct sockaddr_in) : -1)
++#endif /* ENABLE_IPV6 */
++#endif /* SA_LEN */
++#endif /* HAVE_SOCKADDR_SA_LEN */
+ 
+ int
+-SConnect(int sfd, const struct sockaddr_in *const addr, int tlen)
++SConnect(int sfd, const struct sockaddr *const addr, int tlen)
+ {
+ 	int result;
+ 	
+-	result = _SConnect(sfd, addr, (size_t) sizeof(struct sockaddr_in), tlen);
++#ifdef HAVE_SOCKADDR_SA_LEN
++	result = _SConnect(sfd, addr, addr->sa_len, tlen);
++#else
++	result = _SConnect(sfd, addr, SA_LEN(addr), tlen);
++#endif
+ 	return (result);
+ }	/* SConnect */
+ 
+@@ -54,7 +70,7 @@
+ 
+ 
+ int
+-_SConnect(const int sfd, const struct sockaddr_in *const addr, const size_t saddrsiz, const int tlen)
++_SConnect(const int sfd, const struct sockaddr *const addr, const size_t saddrsiz, const int tlen)
+ {
+ 	fd_set ss, xx;
+ 	struct timeval tv;
+Index: ncftp3/sio/SConnectByName.c
+diff -u ncftp3/sio/SConnectByName.c:1.1.1.3 ncftp3/sio/SConnectByName.c:1.3
+--- ncftp3/sio/SConnectByName.c:1.1.1.3	Thu Jan  8 19:51:16 2004
++++ ncftp3/sio/SConnectByName.c	Thu Jan  8 20:09:33 2004
+@@ -7,15 +7,15 @@
+ SConnectByName(int sfd, const char * const addrStr, const int tlen)
+ {
+ 	int result;
+-	struct sockaddr_in remoteAddr;
++	struct sockaddr_storage remoteAddr;
+ 	
+ 	if (addrStr == NULL) {
+ 		errno = EINVAL;
+ 		return (-1);
+ 	}
+ 
+-	if ((result = AddrStrToAddr(addrStr, &remoteAddr, -1)) == 0) {
+-		result = SConnect(sfd, &remoteAddr, tlen);
++	if ((result = AddrStrToAddr(addrStr, (struct sockaddr *)&remoteAddr, -1)) == 0) {
++		result = SConnect(sfd, (struct sockaddr *)&remoteAddr, tlen);
+ 	}
+ 	return (result);
+ }	/* SConnectByName */
+Index: ncftp3/sio/SRecvfrom.c
+diff -u ncftp3/sio/SRecvfrom.c:1.1.1.5 ncftp3/sio/SRecvfrom.c:1.4
+--- ncftp3/sio/SRecvfrom.c:1.1.1.5	Thu Jan  8 19:51:18 2004
++++ ncftp3/sio/SRecvfrom.c	Thu Jan  8 20:09:33 2004
+@@ -4,7 +4,7 @@
+ #endif
+ 
+ int
+-SRecvfrom(int sfd, char *const buf, size_t size, int fl, struct sockaddr_in *const fromAddr, int tlen)
++SRecvfrom(int sfd, char *const buf, size_t size, int fl, struct sockaddr *const fromAddr, int tlen)
+ {
+ 	recv_return_t nread;
+ 	int tleft;
+@@ -56,7 +56,7 @@
+ 
+ 		IGNORE_SIGPIPE
+ 		nread = recvfrom(sfd, buf, (recv_size_t) size, fl,
+-			(struct sockaddr *) fromAddr, &alen);
++			fromAddr, &alen);
+ 		RESTORE_SIGPIPE
+ 
+ 		if (nread >= 0)
+Index: ncftp3/sio/SSendto.c
+diff -u ncftp3/sio/SSendto.c:1.1.1.5 ncftp3/sio/SSendto.c:1.5
+--- ncftp3/sio/SSendto.c:1.1.1.5	Thu Jan  8 19:51:18 2004
++++ ncftp3/sio/SSendto.c	Thu Jan  8 20:09:33 2004
+@@ -3,8 +3,21 @@
+ #	pragma hdrstop
+ #endif
+ 
++#ifndef HAVE_SOCKADDR_SA_LEN
++#ifndef SA_LEN
++#ifdef ENABLE_IPV6
++#define SA_LEN(x) (((x)->sa_family == AF_INET6) ? sizeof(struct sockaddr_in6) \
++		                : (((x)->sa_family == AF_INET) ? sizeof(struct sockaddr_in) \
++					                : -1))
++#else  /* ENABLE_IPV6 */
++#define SA_LEN(x) (((x)->sa_family == AF_INET) ? sizeof(struct sockaddr_in) : -1)
++#endif /* ENABLE_IPV6 */
++#endif /* SA_LEN */
++#endif /* HAVE_SOCKADDR_SA_LEN */
++
++
+ int
+-SSendto(int sfd, const char *const buf, size_t size, int fl, const struct sockaddr_in *const toAddr, int tlen)
++SSendto(int sfd, const char *const buf, size_t size, int fl, const struct sockaddr *const toAddr, int tlen)
+ {
+ 	send_return_t nwrote;
+ 	int tleft;
+@@ -58,9 +71,15 @@
+ 		}
+ 
+ 		IGNORE_SIGPIPE
++#ifdef HAVE_SOCKADDR_SA_LEN
++		nwrote = sendto(sfd, buf, (send_size_t) size, fl,
++			toAddr,
++			toAddr->sa_len);
++#else
+ 		nwrote = sendto(sfd, buf, (send_size_t) size, fl,
+-			(const struct sockaddr *) toAddr,
+-			(sockaddr_size_t) sizeof(struct sockaddr_in));
++                        toAddr,
++                        SA_LEN(toAddr));
++#endif
+ 		RESTORE_SIGPIPE
+ 
+ 		if (nwrote >= 0)
+@@ -77,7 +96,7 @@
+ 
+ 
+ int
+-Sendto(int sfd, const char *const buf, size_t size, const struct sockaddr_in *const toAddr)
++Sendto(int sfd, const char *const buf, size_t size, const struct sockaddr *toAddr)
+ {
+ 	int result;
+ 	DECL_SIGPIPE_VARS
+@@ -89,9 +108,15 @@
+ 	
+ 	IGNORE_SIGPIPE
+ 	do {
++#ifdef HAVE_SOCKADDR_SA_LEN
++		result = (int) sendto(sfd, buf, (send_size_t) size, 0,
++				toAddr,
++				toAddr->sa_len);
++#else
+ 		result = (int) sendto(sfd, buf, (send_size_t) size, 0,
+-				(const struct sockaddr *) toAddr,
+-				(sockaddr_size_t) sizeof(struct sockaddr_in));
++                                toAddr,
++                                SA_LEN(toAddr));
++#endif
+ 	} while ((result < 0) && (errno == EINTR));
+ 	RESTORE_SIGPIPE
+ 	return (result);
+Index: ncftp3/sio/SSendtoByName.c
+diff -u ncftp3/sio/SSendtoByName.c:1.1.1.5 ncftp3/sio/SSendtoByName.c:1.4
+--- ncftp3/sio/SSendtoByName.c:1.1.1.5	Thu Jan  8 19:51:18 2004
++++ ncftp3/sio/SSendtoByName.c	Thu Jan  8 20:09:33 2004
+@@ -11,7 +11,7 @@
+ 	time_t done, now;
+ 	fd_set ss;
+ 	struct timeval tv;
+-	struct sockaddr_in toAddr;
++	struct sockaddr_storage toAddr;
+ 	DECL_SIGPIPE_VARS
+ 	
+ 	if ((buf == NULL) || (size == 0) || (toAddrStr == NULL) || (toAddrStr[0] == '\0') || (tlen <= 0)) {
+@@ -19,7 +19,7 @@
+ 		return (-1);
+ 	}
+ 
+-	if ((result = AddrStrToAddr(toAddrStr, &toAddr, -1)) < 0) {
++	if ((result = AddrStrToAddr(toAddrStr, (struct sockaddr *)&toAddr, -1)) < 0) {
+ 		return (result);
+ 	}
+ 
+@@ -81,7 +81,7 @@
+ SendtoByName(int sfd, const char *const buf, size_t size, const char *const toAddrStr)
+ {
+ 	int result;
+-	struct sockaddr_in toAddr;
++	struct sockaddr_storage toAddr;
+ 	DECL_SIGPIPE_VARS
+ 	
+ 	if ((buf == NULL) || (size == 0) || (toAddrStr == NULL)) {
+@@ -89,8 +89,7 @@
+ 		return (-1);
+ 	}
+ 	
+-
+-	if ((result = AddrStrToAddr(toAddrStr, &toAddr, -1)) < 0) {
++	if ((result = AddrStrToAddr(toAddrStr, (struct sockaddr *)&toAddr, -1)) < 0) {
+ 		return (result);
+ 	}
+ 
+--- ncftp-3.2.5/sio/StrAddr.c.orig	2009-10-24 01:31:23.000000000 +0200
++++ ncftp-3.2.5/sio/StrAddr.c	2011-03-27 15:42:56.665738111 +0200
+@@ -6,6 +6,19 @@
+ #	pragma hdrstop
+ #endif
+ 
++#ifndef HAVE_SOCKADDR_SA_LEN
++#ifndef SA_LEN
++#ifdef ENABLE_IPV6
++#define SA_LEN(x) (((x)->sa_family == AF_INET6) ? sizeof(struct sockaddr_in6) \
++		                : (((x)->sa_family == AF_INET) ? sizeof(struct sockaddr_in) \
++					                : -1))
++#else  /* ENABLE_IPV6 */
++#define SA_LEN(x) (((x)->sa_family == AF_INET) ? sizeof(struct sockaddr_in) : -1)
++#endif /* ENABLE_IPV6 */
++#endif /* SA_LEN */
++#endif /* HAVE_SOCKADDR_SA_LEN */
++
++
+ #ifndef INADDR_ANY
+ #	define INADDR_ANY              ((unsigned long int) 0x00000000)
+ #endif
+@@ -25,14 +38,10 @@
+ {
+ 	char str[64];
+ 	char *cp;
+-#if defined(HAVE_GETSERVBYNAME_R) && (defined(AIX) || defined(TRU64UNIX) || defined(DIGITAL_UNIX))
+-	struct servent *sp;
+-#elif defined(HAVE_GETSERVBYNAME_R) && (defined(LINUX) || defined(SOLARIS) || defined(IRIX) || defined(BSDOS))
+-	struct servent se, *sp;
+-	char spbuf[256];
+-#else
+-	struct servent *sp;
+-#endif
++	struct addrinfo hints, *res;
++	int error;
++	unsigned int port;
++
+ 	strncpy(str, s, sizeof(str) - 1);
+ 	str[sizeof(str) - 1] = '\0';
+ 	cp = str;
+@@ -49,55 +58,29 @@
+ 	}
+ 	*cp = '\0';
+ 
+-	sp = NULL;
+-#if defined(HAVE_GETSERVBYNAME_R) && (defined(SOLARIS) || defined(IRIX) || defined(BSDOS))
+-	if ((sp == NULL) && ((proto == 0) || (proto == 't'))) {
+-		memset(spbuf, 0, sizeof(spbuf));
+-		sp = getservbyname_r(str, "tcp", &se, spbuf, sizeof(spbuf));
+-	}
+-	if ((sp == NULL) && ((proto == 0) || (proto == 'u'))) {
+-		memset(spbuf, 0, sizeof(spbuf));
+-		sp = getservbyname_r(str, "udp", &se, spbuf, sizeof(spbuf));
+-	}
+-#elif defined(HAVE_GETSERVBYNAME_R) && defined(LINUX)
+-	if ((sp == NULL) && ((proto == 0) || (proto == 't'))) {
+-		memset(spbuf, 0, sizeof(spbuf));
+-		if (getservbyname_r(str, "tcp", &se, spbuf, sizeof(spbuf), &sp) != 0)
+-			sp = NULL;
+-	}
+-	if ((sp == NULL) && ((proto == 0) || (proto == 'u'))) {
+-		memset(spbuf, 0, sizeof(spbuf));
+-		if (getservbyname_r(str, "udp", &se, spbuf, sizeof(spbuf), &sp) != 0)
+-			sp = NULL;
+-	}
+-#elif defined(HAVE_GETSERVBYNAME_R) && defined(AIX)
+-	{
+-		struct servent_data sed;
+-		if ((sp == NULL) && ((proto == 0) || (proto == 't'))) {
+-			memset(&sed, 0, sizeof(sed));
+-			if (getservbyname_r(str, "tcp", sp, &sed) != 0)
+-				sp = NULL;
+-		}
+-		if ((sp == NULL) && ((proto == 0) || (proto == 'u'))) {
+-			memset(&sed, 0, sizeof(sed));
+-			if (getservbyname_r(str, "udp", sp, &sed) != 0)
+-				sp = NULL;
+-		}
+-	}
+-#else
+-	/* Note: getservbyname is already threadsafe on: HP-UX, Tru64 */
+-	if ((sp == NULL) && ((proto == 0) || (proto == 't'))) {
+-		sp = getservbyname(str, "tcp");
+-	}
+-	if ((sp == NULL) && ((proto == 0) || (proto == 'u'))) {
+-		sp = getservbyname(str, "udp");
+-	}
+-#endif
+-
+-	if (sp != NULL) {
+-		return ((unsigned int) ntohs((unsigned short) sp->s_port));
++	error = 1;
++	memset(&hints, 0, sizeof(hints));
++	hints.ai_family = PF_UNSPEC;
++	if ((error != 0) && ((proto == 0) || (proto == 't'))) {
++		hints.ai_socktype = SOCK_STREAM;
++		error = getaddrinfo(NULL, str, &hints, &res);
++	}
++	if ((error != 0) && ((proto == 0) || (proto == 'u'))) {
++		hints.ai_socktype = SOCK_DGRAM;
++		error = getaddrinfo(NULL, str, &hints, &res);
++	}
++	if (error != 0) {
++		return (0);	/* error */
++	}
++	if (res->ai_addr->sa_family == AF_INET) {
++		port = ((struct sockaddr_in *)res->ai_addr)->sin_port;
++	} else if (res->ai_addr->sa_family == AF_INET6) {
++		port = ((struct sockaddr_in6 *)res->ai_addr)->sin6_port;
++	} else {
++		port = 0;	/* error */
+ 	}
+-	return (0);	/* error */
++	freeaddrinfo(res);
++	return ((unsigned int) ntohs((unsigned short) port));
+ }	/* ServiceNameToPortNumber */
+ 
+ 
+@@ -203,15 +186,13 @@
+ 
+ 
+ int
+-AddrStrToAddr(const char * const s, struct sockaddr_in * const sa, const int defaultport)
++AddrStrToAddr(const char * const s, struct sockaddr * const sa, const int defaultport)
+ {
+-	char portstr[128];
+-	unsigned int ipnum;
+-	unsigned int port;
+-	struct hostent *hp;
+-	char *hostcp, *atsign, *colon, *cp, *p2;
++	char portstr[128], portstr2[128];
++	struct addrinfo hints, *res;
++	char *hostcp, *atsign, *colon, *cp, *p2, *portp;
++	int error;
+ 
+-	memset(sa, 0, sizeof(struct sockaddr_in));
+ 	strncpy(portstr, s, sizeof(portstr));
+ 	portstr[sizeof(portstr) - 1] = '\0';
+ 
+@@ -219,7 +200,6 @@
+ 		/* Does it look like a URL?  http://host ? */
+ 		if ((colon[1] == '/') && (colon[2] == '/')) {
+ 			*colon = '\0';
+-			port = 0;
+ 			hostcp = colon + 3;
+ 			for (cp = hostcp; *cp != '\0'; cp++) {
+ 				if ((!ISALNUM(*cp)) && (*cp != '.')) {
+@@ -230,29 +210,27 @@
+ 						while (isdigit((int) *cp))
+ 							cp++;
+ 						*cp = '\0';
+-						port = atoi(p2);
+ 					}
+ 					*cp = '\0';
+ 					break;
+ 				}
+ 			}
+-			if (port == 0)
+-				port = ServiceNameToPortNumber(portstr, 0);
+ 		} else {
+ 			/* Look for host.name.domain:port */
+ 			*colon = '\0';
+ 			hostcp = portstr;
+-			port = (unsigned int) atoi(colon + 1);
+ 		}
++		portp = portstr;
+ 	} else if ((atsign = strchr(portstr, '@')) != NULL) {
+ 		/* Look for port at host.name.domain */
+ 		*atsign = '\0';
+ 		hostcp = atsign + 1;
+-		port = (unsigned int) atoi(portstr);
++		portp = portstr;
+ 	} else if (defaultport > 0) {
+ 		/* Have just host.name.domain, use that w/ default port. */
+-		port = (unsigned int) defaultport;
++		sprintf(portstr2, "%d", defaultport);
+ 		hostcp = portstr;
++		portp = portstr2;
+ 	} else {
+ 		/* If defaultport <= 0, they must supply a port number
+ 		 * in the host/port string.
+@@ -260,33 +238,14 @@
+ 		errno = EADDRNOTAVAIL;
+ 		return (kAddrStrToAddrMiscErr);
+ 	}
+-
+-	sa->sin_port = htons((short) port);
+-
+-	ipnum = inet_addr(hostcp);
+-	if (ipnum != INADDR_NONE) {
+-		sa->sin_family = AF_INET;
+-		sa->sin_addr.s_addr = ipnum;
+-	} else {
+-#ifdef DNSSEC_LOCAL_VALIDATION
+-		val_status_t val_status;
+-		errno = 0;
+-		hp = val_gethostbyname(NULL,hostcp,&val_status);
+-		if ((hp != NULL) && (!val_istrusted(val_status)))
+-			hp = NULL;
+-#else
+-		errno = 0;
+-		hp = gethostbyname(hostcp);
+-#endif
+-		if (hp == NULL) {
+-			if (errno == 0)
+-				errno = ENOENT;
+-			return (kAddrStrToAddrBadHost);
+-		}
+-		sa->sin_family = hp->h_addrtype;
+-		memcpy(&sa->sin_addr.s_addr, hp->h_addr_list[0],
+-			(size_t) hp->h_length);
+-	}
++	memset(&hints, 0, sizeof(hints));
++	hints.ai_family = PF_UNSPEC;
++	hints.ai_socktype = SOCK_STREAM;
++	error = getaddrinfo(hostcp, portp, &hints, &res);
++	if (error != 0)
++		return (kAddrStrToAddrBadHost);
++	memcpy(sa, res->ai_addr, res->ai_addrlen);
++	freeaddrinfo(res);
+ 	return (0);
+ }	/* AddrStrToAddr */
+ 
+@@ -294,12 +253,12 @@
+ 
+ 
+ char *
+-AddrToAddrStr(char *const dst, size_t dsize, struct sockaddr_in * const saddrp, int dns, const char *fmt)
++AddrToAddrStr(char *const dst, size_t dsize, struct sockaddr * const saddrp, int dns, const char *fmt)
+ {
+ 	char addrName[128];
+ 	char *addrNamePtr;
+-	struct hostent *hp;
+-	char str[128];
++	char portName[128];
++	char portNum[128];
+ 	char s_name[64];
+ 	char *dlim, *dp;
+ 	const char *cp;
+@@ -308,26 +267,25 @@
+ 		return NULL;
+ 	memset(dst, 0, dsize);
+ 
+-	addrNamePtr = NULL;
+-	if (dns == 0) {
+-		InetNtoA(addrName, &saddrp->sin_addr, sizeof(addrName));
+-		addrNamePtr = addrName;
+-	} else {
+-#ifdef DNSSEC_LOCAL_VALIDATION
+-		val_status_t val_status;
+-		hp = val_gethostbyaddr(NULL, (const char*)&saddrp->sin_addr, sizeof(struct in_addr), AF_INET, &val_status);
+-		if ((hp != NULL) && (!val_istrusted(val_status)))
+-			hp = NULL;
++	addrNamePtr = addrName;
++	if (dns == 0)
++		dns = NI_NUMERICHOST;
++	else
++		dns = 0;
++	getnameinfo(saddrp,
++#ifdef HAVE_SOCKADDR_SA_LEN
++		    saddrp->sa_len,
+ #else
+-		hp = gethostbyaddr((gethost_addrptr_t) &saddrp->sin_addr, sizeof(struct in_addr), AF_INET);
++		    SA_LEN(saddrp),
+ #endif
+-		if ((hp != NULL) && (hp->h_name != NULL) && (hp->h_name[0] != '\0')) {
+-			addrNamePtr = hp->h_name;
+-		} else {
+-			InetNtoA(addrName, &saddrp->sin_addr, sizeof(addrName));
+-			addrNamePtr = addrName;
+-		}
+-	}
++		    addrName, sizeof(addrName), portName, sizeof(portName), dns);
++	getnameinfo(saddrp,
++#ifdef HAVE_SOCKADDR_SA_LEN
++		    saddrp->sa_len,
++#else
++		    SA_LEN(saddrp),
++#endif
++		    NULL, 0, portNum, sizeof(portNum), NI_NUMERICSERV);
+ 	if (fmt == NULL)
+ 		fmt = "%h:%p";
+ 	for (dp = dst, dlim = dp + dsize - 1; ; fmt++) {
+@@ -339,8 +297,7 @@
+ 				if (dp < dlim)
+ 					*dp++ = '%';
+ 			} else if (*fmt == 'p') {
+-				sprintf(str, "%u", (unsigned int) ntohs(saddrp->sin_port));
+-				for (cp = str; *cp != '\0'; cp++)
++				for (cp = portNum; *cp != '\0'; cp++)
+ 					if (dp < dlim)
+ 						*dp++ = *cp;
+ 				*dp = '\0';
+@@ -355,16 +312,20 @@
+ 						*dp++ = *cp;
+ 				*dp = '\0';
+ 			} else if (*fmt == 's') {
+-				cp = s_name;
+-				(void) ServicePortNumberToName(ntohs(saddrp->sin_port), s_name, sizeof(s_name), 0);
+-				for ( ; *cp != '\0'; cp++)
++				for (cp = portName ; *cp != '\0'; cp++)
+ 					if (dp < dlim)
+ 						*dp++ = *cp;
+ 				/* endservent(); */
+ 				*dp = '\0';
+ 			} else if ((*fmt == 't') || (*fmt == 'u')) {
+ 				cp = s_name;
+-				(void) ServicePortNumberToName(ntohs(saddrp->sin_port), s_name, sizeof(s_name), (int) *fmt);
++				if (saddrp->sa_family == AF_INET) {
++					(void) ServicePortNumberToName(ntohs(((struct sockaddr_in *)saddrp)->sin_port), s_name, sizeof(s_name), (int) *fmt);
++				} else if (saddrp->sa_family == AF_INET6) {
++					(void) ServicePortNumberToName(ntohs(((struct sockaddr_in6 *)saddrp)->sin6_port), s_name, sizeof(s_name), (int) *fmt);
++				} else {
++					cp = '\0';
++				}
+ 				for ( ; *cp != '\0'; cp++)
+ 					if (dp < dlim)
+ 						*dp++ = *cp;
+@@ -391,16 +352,16 @@
+ AddrStrToIPStr(char *const dst, size_t dsize, const char *const src, const int defaultport)
+ {
+ 	int rc;
+-	struct sockaddr_in sa;
++	struct sockaddr_storage ss;
+ 
+ 	if (dsize == 0)
+ 		return NULL;
+ 	memset(dst, 0, dsize);
+ 
+-	rc = AddrStrToAddr(src, &sa, (defaultport <= 0) ? 21 : defaultport);
++	rc = AddrStrToAddr(src, (struct sockaddr *)&ss, (defaultport <= 0) ? 21 : defaultport);
+ 	if (rc < 0)
+ 		return (NULL);
+ 
+-	AddrToAddrStr(dst, dsize, &sa, 0, (defaultport <= 0) ? "%h" : "%h:%p");
++	AddrToAddrStr(dst, dsize, (struct sockaddr *)&ss, 0, (defaultport <= 0) ? "%h" : "%h:%p");
+ 	return (dst);
+ }	/* AddrStrToIPStr */
+Index: ncftp3/sio/sio.h
+diff -u ncftp3/sio/sio.h:1.1.1.10 ncftp3/sio/sio.h:1.14
+--- ncftp3/sio/sio.h:1.1.1.10	Mon Aug 11 15:38:23 2008
++++ ncftp3/sio/sio.h	Mon Aug 11 16:24:16 2008
+@@ -197,7 +197,7 @@
+ int PWrite(int, const char *const, size_t);
+ 
+ /* SAccept.c */
+-int SAccept(int, struct sockaddr_in *const, int);
++int SAccept(int, struct sockaddr *const, int);
+ 
+ /* SBind.c */
+ int SBind(int, const int, const int, const int);
+@@ -208,7 +208,7 @@
+ int SClose(int, int);
+ 
+ /* SConnect.c */
+-int SConnect(int, const struct sockaddr_in *const, int);
++int SConnect(int, const struct sockaddr *const, int);
+ 
+ /* SConnectByName.c */
+ int SConnectByName(int, const char *const, const int);
+@@ -232,7 +232,7 @@
+ int SRecv(int, char *const, size_t, int, int, int);
+ 
+ /* SRecvfrom.c */
+-int SRecvfrom(int, char *const, size_t, int, struct sockaddr_in *const, int);
++int SRecvfrom(int, char *const, size_t, int, struct sockaddr *const, int);
+ 
+ /* SRecvmsg.c */
+ int SRecvmsg(int, void *const, int, int);
+@@ -248,8 +248,8 @@
+ int SSend(int, char *, size_t, int, int);
+ 
+ /* SSendto.c */
+-int SSendto(int, const char *const, size_t, int, const struct sockaddr_in *const, int);
+-int Sendto(int, const char *const, size_t, const struct sockaddr_in *const);
++int SSendto(int, const char *const, size_t, int, const struct sockaddr *const, int);
++int Sendto(int, const char *const, size_t, const struct sockaddr *const);
+ 
+ /* SSendtoByName.c */
+ int SSendtoByName(int, const char *const, size_t, int, const char *const, int);
+@@ -280,8 +280,8 @@
+ unsigned int ServiceNameToPortNumber(const char *const s, const int proto);
+ int ServicePortNumberToName(unsigned short port, char *const dst, const size_t dsize, const int proto);
+ void InetNtoA(char *dst, struct in_addr *ia, size_t siz);
+-int AddrStrToAddr(const char *const, struct sockaddr_in *const, const int);
+-char *AddrToAddrStr(char *const dst, size_t dsize, struct sockaddr_in * const saddrp, int dns, const char *fmt);
++int AddrStrToAddr(const char *const, struct sockaddr *const, const int);
++char *AddrToAddrStr(char *const dst, size_t dsize, struct sockaddr * const saddrp, int dns, const char *fmt);
+ char *AddrStrToIPStr(char *const dst, size_t dsize, const char *const src, const int defaultport);
+ 
+ /* SError.c */
+Index: ncftp3/sio/syshdrs.h
+diff -u ncftp3/sio/syshdrs.h:1.1.1.9 ncftp3/sio/syshdrs.h:1.10
+--- ncftp3/sio/syshdrs.h:1.1.1.9	Mon Aug 11 15:38:23 2008
++++ ncftp3/sio/syshdrs.h	Mon Aug 11 16:24:16 2008
+@@ -20,6 +20,9 @@
+ #	define WINVER 0x0400
+ #	define _WIN32_WINNT 0x0400
+ #	include <windows.h>		/* includes <winsock2.h> if _WIN32_WINNT >= 0x400 */
++#ifdef ENABLE_IPV6
++#	include <ws2tcpip.h>
++#endif /* ENABLE_IPV6 */
+ #	include <io.h>
+ #	include <errno.h>
+ #	include <stdio.h>
+Index: ncftp3/vis/syshdrs.h
+diff -u ncftp3/vis/syshdrs.h:1.1.1.10 ncftp3/vis/syshdrs.h:1.7
+--- ncftp3/vis/syshdrs.h:1.1.1.10	Thu Nov  5 16:20:41 2009
++++ ncftp3/vis/syshdrs.h	Thu Nov  5 16:47:09 2009
+@@ -94,6 +94,9 @@
+ #include <time.h>
+ #include <pwd.h>
+ #include <fcntl.h>
++#ifndef HAVE_GETADDRINFO
++#	include "addrinfo.h"
++#endif
+ 
+ #ifdef HAVE_LOCALE_H
+ #	include <locale.h>
================================================================

---- gitweb:

http://git.pld-linux.org/gitweb.cgi/packages/ncftp.git/commitdiff/a1a0fcca17077a30625a9509cd9e0b1e7dde0eea



More information about the pld-cvs-commit mailing list