[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