]> git.pld-linux.org Git - packages/ncftp.git/commitdiff
- added missing patch
authorJakub Bogusz <qboosh@pld-linux.org>
Sat, 20 Jul 2013 05:20:38 +0000 (07:20 +0200)
committerJakub Bogusz <qboosh@pld-linux.org>
Sat, 20 Jul 2013 05:20:38 +0000 (07:20 +0200)
ncftp-kame-v6.patch [new file with mode: 0644]

diff --git a/ncftp-kame-v6.patch b/ncftp-kame-v6.patch
new file mode 100644 (file)
index 0000000..03b2ef5
--- /dev/null
@@ -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@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@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>
This page took 0.172772 seconds and 4 git commands to generate.