Hi,
the ftp problem is fixed now. (was not in the ftp part, but in the host 
part).

And i attached an test log.

./wget                      
ftp://134.108.34.10/pub/Mirrors/ftp.gnu.org/bash/bash-doc-2.05a.tar.gz
./wget                      
ftp://ftp-stud.fht-esslingen.de/pub/Mirrors/ftp.gnu.org/bash/bash-doc-2.05a.tar.gz
./wget --passive-ftp    
ftp://ftp-stud.fht-esslingen.de/pub/Mirrors/ftp.gnu.org/bash/bash-doc-2.05a.tar.gz
./wget  http://www.ix.de/
./wget  http://193.99.144.71/
./wget  http://www.ipv6.euronet.be/

This cases handled ok, What i seeking is an ftp server witch can use 
eprt epsv with ipv6.
Please tell me where i can test this case.

Cu Thomas Lu�nig
diff -ubr wget-1.8.1/src/connect.c wget-1.8.1_ipv6/src/connect.c
--- wget-1.8.1/src/connect.c    Tue Nov 27 14:55:40 2001
+++ wget-1.8.1_ipv6/src/connect.c       Thu Jan 17 16:26:56 2002
@@ -55,6 +55,7 @@
 extern int errno;
 #endif
 
+
 /* Variables shared by bindport and acceptport: */
 static int msock = -1;
 static struct sockaddr *addr;
@@ -78,13 +79,12 @@
 int
 connect_to_one (const unsigned char *addr, unsigned short port, int silent)
 {
-  struct sockaddr_in sock_name;
+  sockaddr64 sock_name;
   int sock, save_errno;
-
+  int sockaddr_len=get_socklen(ip_default_family);
   /* Set port and protocol */
-  sock_name.sin_family = AF_INET;
-  sock_name.sin_port = htons (port);
-  memcpy ((unsigned char *)&sock_name.sin_addr, addr, 4);
+  set_ip_address(ip_default_family,port,addr,(struct sockaddr *)&sock_name);
+
 
   if (!silent)
     {
@@ -99,15 +99,14 @@
     }
 
   /* Make an internet socket, stream type.  */
-  sock = socket (AF_INET, SOCK_STREAM, 0);
+  sock = socket (ip_default_family, SOCK_STREAM, 0);
   if (sock < 0)
     goto out;
 
   if (opt.bind_address)
     {
       /* Bind the client side to the requested address. */
-      if (bind (sock, (struct sockaddr *)opt.bind_address,
-               sizeof (*opt.bind_address)))
+      if (bind (sock, (struct sockaddr *)opt.bind_address,sockaddr_len))
        {
          close (sock);
          sock = -1;
@@ -116,7 +115,7 @@
     }
 
   /* Connect the socket to the remote host.  */
-  if (connect (sock, (struct sockaddr *)&sock_name, sizeof (sock_name)) < 0)
+  if (connect (sock, (struct sockaddr *)&sock_name,sockaddr_len) < 0)
     {
       close (sock);
       sock = -1;
@@ -151,7 +150,7 @@
   address_list_get_bounds (al, &start, &end);
   for (i = start; i < end; i++)
     {
-      unsigned char addr[4];
+      ip_address addr;
       int sock;
       address_list_copy_one (al, i, addr);
 
@@ -210,11 +209,13 @@
 bindport (unsigned short *port)
 {
   int optval = 1;
-  static struct sockaddr_in srv;
+  static sockaddr64 srv={0};
+  int sockaddr_len=get_socklen(ip_default_family);
+  
 
   msock = -1;
   addr = (struct sockaddr *) &srv;
-  if ((msock = socket (AF_INET, SOCK_STREAM, 0)) < 0)
+  if ((msock = socket (ip_default_family, SOCK_STREAM, 0)) < 0)
     return CONSOCKERR;
   if (setsockopt (msock, SOL_SOCKET, SO_REUSEADDR,
                  (char *)&optval, sizeof (optval)) < 0)
@@ -222,14 +223,13 @@
 
   if (opt.bind_address == NULL)
     {
-      srv.sin_family = AF_INET;
-      srv.sin_addr.s_addr = htonl (INADDR_ANY);
+      set_ip_address(ip_default_family,htons(*port),NULL,(struct sockaddr*)&srv);
     }
   else
     srv = *opt.bind_address;
 
-  srv.sin_port = htons (*port);
-  if (bind (msock, addr, sizeof (struct sockaddr_in)) < 0)
+  set_port(*port,(struct sockaddr*)&srv);
+  if (bind (msock, addr, sockaddr_len) < 0)
     {
       CLOSE (msock);
       msock = -1;
@@ -241,14 +241,15 @@
       /* #### addrlen should be a 32-bit type, which int is not
          guaranteed to be.  Oh, and don't try to make it a size_t,
          because that can be 64-bit.  */
-      int addrlen = sizeof (struct sockaddr_in);
+      int addrlen = sockaddr_len;
       if (getsockname (msock, addr, &addrlen) < 0)
        {
          CLOSE (msock);
          msock = -1;
          return CONPORTERR;
        }
-      *port = ntohs (srv.sin_port);
+      *port=get_port((struct sockaddr*)&srv);
+      DEBUGP (("using port %i.\n", *port));
     }
   if (listen (msock, 1) < 0)
     {
@@ -292,7 +293,7 @@
 uerr_t
 acceptport (int *sock)
 {
-  int addrlen = sizeof (struct sockaddr_in);
+  int addrlen = get_socklen(ip_default_family);
 
 #ifdef HAVE_SELECT
   if (select_fd (msock, opt.timeout, 0) <= 0)
@@ -322,17 +323,28 @@
 unsigned char *
 conaddr (int fd)
 {
-  static unsigned char res[4];
-  struct sockaddr_in mysrv;
+  static ip_address res;
+  sockaddr64  mysrv;
   struct sockaddr *myaddr;
   int addrlen = sizeof (mysrv);        /* see bindport() for discussion of
                                    using `int' here. */
-
   myaddr = (struct sockaddr *) (&mysrv);
-  if (getsockname (fd, myaddr, (int *)&addrlen) < 0)
+  if (getsockname (fd,myaddr, (int *)&addrlen) < 0)
     return NULL;
-  memcpy (res, &mysrv.sin_addr, 4);
+#ifdef IPV6
+  if(myaddr->sa_family==AF_INET6) 
+    {
+      memcpy (res, &mysrv.sin6_addr, sizeof(ip_address));
   return res;
+    }
+#endif
+  if(myaddr->sa_family==AF_INET) {
+      struct sockaddr_in *ipv4=(struct sockaddr_in *)(&mysrv);
+      memcpy (res, &ipv4->sin_addr, sizeof(ip_address));
+      map4_to_6(res,res);
+      return res;
+    }
+  return NULL;
 }
 
 /* Read at most LEN bytes from FD, storing them to BUF.  This is
diff -ubr wget-1.8.1/src/ftp-basic.c wget-1.8.1_ipv6/src/ftp-basic.c
--- wget-1.8.1/src/ftp-basic.c  Mon Dec 10 02:29:11 2001
+++ wget-1.8.1_ipv6/src/ftp-basic.c     Thu Jan 17 16:27:49 2002
@@ -235,6 +235,58 @@
   return FTPOK;
 }
 
+#ifdef IPV6
+uerr_t
+ftp_eprt (struct rbuf *rbuf)
+{
+  uerr_t err;
+  char *request, *respline;
+  unsigned char *in_addr;
+  int nwritten;
+  unsigned short port;
+  char ipv6 [100];
+  char bytes[100];
+  /* Setting port to 0 lets the system choose a free port.  */
+  port = 0;
+  /* Bind the port.  */
+  err = bindport (&port);
+  if (err != BINDOK)
+    return err;
+  /* Get the address of this side of the connection.  */
+  if (!(in_addr = conaddr (RBUF_FD (rbuf))))
+    return BINDERR;
+  inet_ntop(ip_default_family,in_addr,ipv6,128);
+  /* Construct the argument of EPRT (of the form |2|IPv6.ascii|PORT.ascii|).  */
+  snprintf (bytes,sizeof(bytes),"|2|%s|%u|",ipv6,port);
+  /* Send PORT request.  */
+  request = ftp_request ("EPRT", bytes);
+  nwritten = iwrite (RBUF_FD (rbuf), request, strlen (request));
+  if (nwritten < 0)
+    {
+      closeport(port);
+      xfree (request);
+      return WRITEFAILED;
+    }
+  xfree (request);
+  /* Get appropriate response.  */
+  err = ftp_response (rbuf, &respline);
+  if (err != FTPOK)
+    {
+      closeport(port);
+      xfree (respline);
+      return err;
+    }
+  if (*respline != '2')
+    {
+      closeport(port);
+      xfree (respline);
+      return FTPPORTERR;
+    }
+  xfree (respline);
+  return FTPOK;
+}
+#endif
+
 /* Bind a port and send the appropriate PORT command to the FTP
    server.  Use acceptport after RETR, to get the socket of data
    connection.  */
@@ -246,7 +298,11 @@
   unsigned char *in_addr;
   int nwritten;
   unsigned short port;
-
+#ifdef IPV6
+  err=ftp_eprt(rbuf);
+  if(err==FTPOK) 
+    return err;
+#endif
   /* Setting port to 0 lets the system choose a free port.  */
   port = 0;
   /* Bind the port.  */
@@ -256,6 +312,9 @@
   /* Get the address of this side of the connection.  */
   if (!(in_addr = conaddr (RBUF_FD (rbuf))))
     return BINDERR;
+  /* make an ::ffff:127.0.0.1 so that this routine handle it */
+  if(!map6_to_4(in_addr))
+    return BINDERR;
   /* Construct the argument of PORT (of the form a,b,c,d,e,f).  */
   bytes = (char *)alloca (6 * 4 + 1);
   sprintf (bytes, "%d,%d,%d,%d,%d,%d", in_addr[0], in_addr[1],
@@ -286,16 +345,88 @@
   return FTPOK;
 }
 
+#ifdef IPV6
+uerr_t
+ftp_epsv (struct rbuf *rbuf, unsigned char *addr,unsigned short *port,char *typ)
+{
+  int err;
+  char *s,*respline;
+  char *request=ftp_request ("EPSV",typ);
+  int  nwritten=iwrite (RBUF_FD (rbuf), request, strlen (request));
+  if(nwritten<0)
+    {
+      xfree (request);
+      return WRITEFAILED;
+    }
+  /* Get the server response.  */
+  err = ftp_response (rbuf, &respline);
+  if (err != FTPOK)
+    {
+      xfree (respline);
+      return err;
+    }
+  if (*respline != '2')
+    {
+      xfree (respline);
+      return FTPNOPASV;
+    }
+  /* Parse the request.  */
+  s = respline;                                        /* respline::=229 Entering 
+Extended Passive Mode (|||6446|) */
+  for (s += 4; *s && !ISDIGIT (*s); s++);
+  if (!*s)
+    return FTPINVPASV;
+  *port=0; 
+  for (; ISDIGIT (*s); s++) *port = (*s - '0') + 10 * (*port);
+  if (*s == ',') s++;
+  else {
+    xfree (respline);
+    return FTPINVPASV;
+    }
+  {
+    unsigned short port2=0;
+    for (; ISDIGIT (*s); s++) port2 = (*s - '0') + 10 * port2;
+    *port=(*port)*256+port2; 
+  }
+  xfree (respline);
+  /* Now we have the port but we need the IPv6 :-( */
+  {
+    sockaddr64 remote;
+    int len=sizeof(remote);
+    struct sockaddr_in *ipv4_sock=( struct sockaddr_in *)&remote;
+    getpeername(RBUF_FD(rbuf),(struct sockaddr*)&remote,len);
+    if(remote.sin6_family==AF_INET) map4_to_6((unsigned 
+char*)&ipv4_sock->sin_addr.s_addr,addr);
+    else                           memcpy(addr,remote.sin6_addr.in6_u.u6_addr8,16);
+  }
+  return FTPOK;
+}
+#endif
+
+
 /* Similar to ftp_port, but uses `PASV' to initiate the passive FTP
    transfer.  Reads the response from server and parses it.  Reads the
    host and port addresses and returns them.  */
 uerr_t
-ftp_pasv (struct rbuf *rbuf, unsigned char *addr)
+ftp_pasv (struct rbuf *rbuf, unsigned char *addr,unsigned short *port)
+       /*
+          Input:
+          - rbuf is an general buffer space including fd
+          - addr is an IPv4 Adresse ( at the moment )
+          */
 {
   char *request, *respline, *s;
   int nwritten, i;
   uerr_t err;
-
+#ifdef IPV6  
+  switch(ip_default_family) {
+  case AF_INET6: err=ftp_epsv(rbuf,addr,port,"2");     /* try IPv6 with EPSV */
+                if(err==FTPOK) return FTPOK;
+                err=ftp_epsv(rbuf,addr,port,"1");      /* try IPv4 with EPSV */
+                if(err==FTPOK) return FTPOK;
+  case AF_INET : break;                                        /* if this fail to try 
+PASV */
+  default      : fprintf(stderr,"Invalid Protokol\n");
+                exit(-1);
+       }
+#endif  
   /* Form the request.  */
   request = ftp_request ("PASV", NULL);
   /* And send it.  */
@@ -319,24 +450,37 @@
       return FTPNOPASV;
     }
   /* Parse the request.  */
+  /* respline::=227 Entering Passive Mode (h1,h2,h3,h4,p1,p2).         */
   s = respline;
   for (s += 4; *s && !ISDIGIT (*s); s++);
   if (!*s)
     return FTPINVPASV;
-  for (i = 0; i < 6; i++)
+  for (i = 0; i < 4; i++)
     {
       addr[i] = 0;
       for (; ISDIGIT (*s); s++)
         addr[i] = (*s - '0') + 10 * addr[i];
       if (*s == ',')
         s++;
-      else if (i < 5)
+      else
         {
-          /* When on the last number, anything can be a terminator.  */
           xfree (respline);
           return FTPINVPASV;
         }
     }
+  map4_to_6(addr,addr);                                /* evtl make an IPv4 in IPv6 
+adress if needed */
+  *port=0; 
+  for (; ISDIGIT (*s); s++) *port = (*s - '0') + 10 * (*port);
+  if (*s == ',') s++;
+  else {
+    xfree (respline);
+    return FTPINVPASV;
+    }
+  { 
+    unsigned short port2=0; 
+    for (; ISDIGIT (*s); s++) port2 = (*s - '0') + 10 * port2;
+    *port=(*port)*256+port2;
+  }
   xfree (respline);
   return FTPOK;
 }
diff -ubr wget-1.8.1/src/ftp.c wget-1.8.1_ipv6/src/ftp.c
--- wget-1.8.1/src/ftp.c        Mon Dec  3 17:22:05 2001
+++ wget-1.8.1_ipv6/src/ftp.c   Wed Jan 16 11:59:14 2002
@@ -119,7 +119,6 @@
   FILE *fp;
   char *user, *passwd, *respline;
   char *tms, *tmrate;
-  unsigned char pasv_addr[6];
   int cmd = con->cmd;
   int passive_mode_open = 0;
   long expected_bytes = 0L;
@@ -489,9 +488,11 @@
     {
       if (opt.ftp_pasv > 0)
        {
+         ip_address     pasiv_addr;
+         unsigned short pasiv_port;
          if (!opt.server_response)
            logputs (LOG_VERBOSE, "==> PASV ... ");
-         err = ftp_pasv (&con->rbuf, pasv_addr);
+         err = ftp_pasv (&con->rbuf, pasiv_addr,&pasiv_port);
          /* FTPRERR, WRITEFAILED, FTPNOPASV, FTPINVPASV */
          switch (err)
            {
@@ -525,21 +526,17 @@
            default:
              abort ();
              break;
-           }
+           }   /* switch(err) */
          if (err==FTPOK)
            {
-             unsigned short tport;
-
-             tport = (pasv_addr[4] << 8) + pasv_addr[5];
-             dtsock = connect_to_one (pasv_addr, tport, 1);
-
+             dtsock = connect_to_one (pasiv_addr, pasiv_port, 1);
              if (dtsock < 0)
                {
                  int save_errno = errno;
                  CLOSE (csock);
                  rbuf_uninitialize (&con->rbuf);
                  logprintf (LOG_VERBOSE, _("couldn't connect to %s:%hu: %s\n"),
-                            pretty_print_address (pasv_addr), tport,
+                            pretty_print_address (pasiv_addr), pasiv_port,
                             strerror (save_errno));
                  return save_errno == ECONNREFUSED ? CONREFUSED : CONERROR;
                }
diff -ubr wget-1.8.1/src/ftp.h wget-1.8.1_ipv6/src/ftp.h
--- wget-1.8.1/src/ftp.h        Thu Nov 22 00:24:27 2001
+++ wget-1.8.1_ipv6/src/ftp.h   Wed Jan 16 12:17:21 2002
@@ -36,7 +36,11 @@
 uerr_t ftp_response PARAMS ((struct rbuf *, char **));
 uerr_t ftp_login PARAMS ((struct rbuf *, const char *, const char *));
 uerr_t ftp_port PARAMS ((struct rbuf *));
-uerr_t ftp_pasv PARAMS ((struct rbuf *, unsigned char *));
+uerr_t ftp_pasv     PARAMS ((struct rbuf *, unsigned char *,unsigned short*));
+#ifdef IPV6
+uerr_t ftp_epsv     PARAMS ((struct rbuf *, unsigned char *,unsigned short *,
+                       char *));
+#endif
 uerr_t ftp_type PARAMS ((struct rbuf *, int));
 uerr_t ftp_cwd PARAMS ((struct rbuf *, const char *));
 uerr_t ftp_retr PARAMS ((struct rbuf *, const char *));
diff -ubr wget-1.8.1/src/host.c wget-1.8.1_ipv6/src/host.c
--- wget-1.8.1/src/host.c       Tue Dec 11 08:32:57 2001
+++ wget-1.8.1_ipv6/src/host.c  Thu Jan 17 16:26:44 2002
@@ -18,6 +18,7 @@
 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 #include <config.h>
+#include <netdb.h>
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -65,8 +66,13 @@
 # endif
 #endif
 
-/* An IPv4 address is simply a 4-byte quantity. */
-typedef unsigned char ipv4_address[4];
+#ifdef IPV6
+int     ip_default_family = AF_INET6;
+#else
+int     ip_default_family = AF_INET;
+#endif
+
+
 
 /* Mapping between known hosts and to lists of their addresses. */
 
@@ -77,7 +83,8 @@
 
 struct address_list {
   int count;                   /* number of adrresses */
-  ipv4_address *addresses;     /* pointer to the string of addresses */
+  int ip_family;
+  ip_address *addresses;       /* pointer to the string of addresses */
 
   int faulty;                  /* number of addresses known not to
                                   work. */
@@ -85,6 +92,132 @@
                                   not. */
 };
 
+void
+set_ip_address(int ip_family,unsigned short port,const unsigned char*addr,struct 
+sockaddr *sock_name)
+{
+  if(ip_family==AF_INET) 
+    {
+      struct sockaddr_in *ip_sock=(struct sockaddr_in *)sock_name;
+      ip_sock->sin_family=ip_family;
+      ip_sock->sin_port=htons(port);
+      if(addr==NULL) memset((unsigned char*)&ip_sock->sin_addr,0   ,4);
+      else          memcpy((unsigned char*)&ip_sock->sin_addr,addr,4);
+    }
+#ifdef IPV6
+  if(ip_family==AF_INET6) 
+    {
+      struct sockaddr_in6 *ip_sock=(struct sockaddr_in6*)sock_name;
+      ip_sock->sin6_family=AF_INET6;
+      ip_sock->sin6_port=htons(port);
+      if(addr==NULL) memset(ip_sock->sin6_addr.in6_u.u6_addr8,0   ,16);
+      else          memcpy(ip_sock->sin6_addr.in6_u.u6_addr8,addr,16);
+    }
+#endif  
+}
+void set_port(unsigned short port,struct sockaddr *sock_name)
+{
+  if(sock_name->sa_family==AF_INET)
+    {
+      struct sockaddr_in *ip_sock=(struct sockaddr_in *)&sock_name;
+      ip_sock->sin_port=htons(port);
+    }
+#ifdef IPV6
+  if(sock_name->sa_family==AF_INET6)
+    {
+      struct sockaddr_in6 *ip_sock=(struct sockaddr_in6*)&sock_name;
+      ip_sock->sin6_port=htons(port);
+    }
+#endif
+}
+void set_family(int ip_family,struct sockaddr *sock_name)
+{
+  if(ip_family==AF_INET)
+    {
+      struct sockaddr_in *ip_sock=(struct sockaddr_in *)&sock_name;
+      ip_sock->sin_family=ip_family;
+    }
+#ifdef IPV6
+  if(ip_family==AF_INET6)
+    {
+      struct sockaddr_in6 *ip_sock=(struct sockaddr_in6*)&sock_name;
+      ip_sock->sin6_family=ip_family;
+    }
+#endif
+}
+
+unsigned char *get_addr(struct sockaddr *sock_name)
+{ 
+  if(sock_name->sa_family==AF_INET)
+    {
+      struct sockaddr_in *ip_sock=(struct sockaddr_in *)&sock_name;
+      return (unsigned char*)&ip_sock->sin_addr;
+    }
+#ifdef IPV6
+  if(sock_name->sa_family==AF_INET6)
+    {
+      struct sockaddr_in6 *ip_sock=(struct sockaddr_in6*)&sock_name;
+      return ip_sock->sin6_addr.in6_u.u6_addr8;
+    }
+#endif
+  return NULL;
+}
+
+unsigned short get_port(struct sockaddr *sock_name)
+{
+  if(sock_name->sa_family==AF_INET)
+    {
+      struct sockaddr_in *ip_sock=(struct sockaddr_in *)sock_name;
+      return htons(ip_sock->sin_port);
+    }
+#ifdef IPV6
+  if(sock_name->sa_family==AF_INET6)
+    {
+      struct sockaddr_in6 *ip_sock=(struct sockaddr_in6*)sock_name;
+      return htons(ip_sock->sin6_port);
+    }
+#endif
+  return -1;
+}
+int get_socklen(int ip_family) 
+{
+  if(ip_family==AF_INET) return sizeof(struct sockaddr_in);
+#ifdef IPV6
+  if(ip_family==AF_INET6) return sizeof(struct sockaddr_in6);
+#endif
+  return 0;
+}
+
+void 
+map4_to_6(const unsigned char *IPv4,unsigned char *IPv6) 
+{
+  if(ip_default_family==AF_INET6)
+      if(IPv6!=IPv4)
+        memcpy (IPv6,IPv4,4);
+#ifdef IPV6
+  if(ip_default_family==AF_INET6)
+    {
+      unsigned char IPv64[12]={0,0,0,0, 0,0,0,0, 0,0,0xff,0xff};
+      memcpy (IPv6+12, IPv4 , 4);
+      memcpy (IPv6+ 0, IPv64,12);
+    }
+#endif
+  return;          
+}
+
+int 
+map6_to_4(unsigned char *IPv6) 
+{
+#ifdef IPV6
+  unsigned char IPv64[12]={0,0,0,0, 0,0,0,0, 0,0,0xff,0xff};
+  if(ip_default_family==AF_INET) 
+    return 1;
+  if(0!=memcmp(IPv6,IPv64,12))
+    return 0;
+  memcpy (IPv6, IPv6+12 , 4);
+#endif
+  return 1;
+}
+
 /* Get the bounds of the address list.  */
 
 void
@@ -101,7 +234,7 @@
                       unsigned char *ip_store)
 {
   assert (index >= al->faulty && index < al->count);
-  memcpy (ip_store, al->addresses + index, sizeof (ipv4_address));
+  memcpy (ip_store, al->addresses + index, sizeof (ip_address));
 }
 
 /* Check whether two address lists have all their IPs in common.  */
@@ -114,7 +247,7 @@
   if (al1->count != al2->count)
     return 0;
   return 0 == memcmp (al1->addresses, al2->addresses,
-                     al1->count * sizeof (ipv4_address));
+                     al1->count * sizeof (ip_address));
 }
 
 /* Mark the INDEXth element of AL as faulty, so that the next time
@@ -152,26 +285,25 @@
   assert (count > 0);
   al->count     = count;
   al->faulty    = 0;
-  al->addresses = xmalloc (count * sizeof (ipv4_address));
+  al->addresses = xmalloc (count * sizeof (ip_address));
   al->refcount  = 1;
 
   for (i = 0; i < count; i++)
-    memcpy (al->addresses + i, h_addr_list[i], sizeof (ipv4_address));
-
+    memcpy (al->addresses + i, h_addr_list[i], sizeof (ip_address));
   return al;
 }
 
 /* Like address_list_new, but initialized with only one address. */
 
 static struct address_list *
-address_list_new_one (const char *addr)
+address_list_new_one (const char *addr,int ip_family) 
 {
   struct address_list *al = xmalloc (sizeof (struct address_list));
   al->count     = 1;
   al->faulty    = 0;
-  al->addresses = xmalloc (sizeof (ipv4_address));
+  al->addresses = xmalloc (sizeof (ip_address));
   al->refcount  = 1;
-  memcpy (al->addresses, addr, sizeof (ipv4_address));
+  memcpy (al->addresses, addr, sizeof (ip_address));
 
   return al;
 }
@@ -201,7 +333,14 @@
 char *
 pretty_print_address (const void *addr)
 {
+#ifdef IPV6
+  char buf[128];
+  if(NULL==inet_ntop(ip_default_family,addr,buf,128)) return NULL;
+  if(0==strncmp(buf,"::ffff:",7)) return strdup(buf+7);
+  return strdup(buf);
+#else
   return inet_ntoa (*(struct in_addr *)addr);
+#endif
 }
 
 /* Add host name HOST with the address ADDR_TEXT to the cache.
@@ -233,30 +372,39 @@
 lookup_host (const char *host, int silent)
 {
   struct address_list *al = NULL;
-  unsigned long addr;
-  struct hostent *hptr;
-
-  /* If the address is of the form d.d.d.d, no further lookup is
-     needed.  */
-  addr = (unsigned long)inet_addr (host);
-  if ((int)addr != -1)
+  ip_address addr;
+  struct hostent *hptr=NULL;
+  /* If the address is of the form that if valid for <family>, 
+     no further lookup is needed.  */
+#ifdef IPV6
+  int ret;
+  ret=inet_pton(ip_default_family,host,addr);
+  if(0>ret)
+    {
+    int offset;
+#else
+  long tmp_ipv4=(long)inet_addr (host);
+  if((int)tmp_ipv4!=-1)
     {
+      int offset;
+      memcpy(addr,&tmp_ipv4,4);
+#endif
+
       /* ADDR is defined to be in network byte order, which is what
         this returns, so we can just copy it to STORE_IP.  However,
         on big endian 64-bit architectures the value will be stored
         in the *last*, not first four bytes.  OFFSET makes sure that
         we copy the correct four bytes.  */
-      int offset;
+  
 #ifdef WORDS_BIGENDIAN
-      offset = sizeof (unsigned long) - sizeof (ipv4_address);
+      offset = sizeof (unsigned long) - sizeof (ip_address);
 #else
       offset = 0;
 #endif
-      return address_list_new_one ((char *)&addr + offset);
+      return address_list_new_one ((char *)&addr + offset,ip_default_family);
     }
 
-  /* By now we know that the host name we got is not of the form
-     d.d.d.d.  Try to find it in our cache of host names.  */
+  
   if (host_name_addresses_map)
     al = hash_table_get (host_name_addresses_map, host);
 
@@ -270,8 +418,70 @@
   if (!silent)
     logprintf (LOG_VERBOSE, _("Resolving %s... "), host);
 
-  /* Look up the host using gethostbyname().  */
-  hptr = gethostbyname (host);
+  /* Look up the host using getipnodebyname().  */
+#ifdef IPV6
+#ifdef HAVE_GETADDRINFO
+#ifndef HAVE_GETHOSTBYNAME2
+  {
+    struct addrinfo hints;
+    struct addrinfo *akt;
+    struct addrinfo *res;
+    struct hostent *hprt;
+    int count,i;
+    int err;
+    memset(&hints, 0, sizeof(hints));
+    hints.ai_family   = PF_UNSPEC;
+    hints.ai_socktype = SOCK_STREAM;
+    err = getaddrinfo(host,"http",&hints, &res);
+    if (err)
+      return NULL;
+    akt=res;
+    for(count=0;NULL!=akt;count++)
+      akt=akt->ai_next;
+    hprt=xmalloc(sizeof(struct hostent));
+    hprt->h_name=NULL;
+    hprt->h_aliases=NULL;
+    hprt->h_addrtype=AF_INET6;
+    hprt->h_length=16;
+    hprt->h_addr_list=xmalloc((count+1)*sizeof(char*));
+    hprt->h_addr_list[count]=NULL;
+    akt=res;
+    for(i=0;i<count;i++)
+        {
+         hprt->h_addr_list[i]=xmalloc(16);
+         if(akt->ai_family==AF_INET6) 
+           {
+             struct sockaddr_in6 *sin6=(struct sockaddr_in6*)&(akt->ai_addr);
+             unsigned char *ipv6_ptr=(unsigned char*)&sin6->sin6_addr.in6_u.u6_addr8;
+             /* Why the fuck is here the an so odd offset required */
+             memcpy(hprt->h_addr_list[i],ipv6_ptr+12,16);
+           } 
+         else if(akt->ai_family==AF_INET)
+                   {
+             struct sockaddr_in *sin=(struct sockaddr_in*)&(akt->ai_addr);
+             unsigned char *ipv4_ptr=(unsigned char*)&sin->sin_addr;
+             map4_to_6(ipv4_ptr+12,hprt->h_addr_list[i]);
+           } 
+         else
+           {
+           hprt->h_addr_list[i]=NULL;
+           }
+        }
+    hptr=hprt;
+    freeaddrinfo(res);
+  }
+#endif
+#endif
+#endif
+
+#ifdef IPV6
+#ifdef HAVE_GETHOSTBYNAME2
+           hptr = gethostbyname2(host,ip_default_family);
+  if(!hptr) hptr = gethostbyname2(host,AF_INET);
+#endif
+#else
+  hptr = gethostbyname(host);
+#endif
   if (!hptr)
     {
       if (!silent)
@@ -284,8 +494,28 @@
 
   /* Do all systems have h_addr_list, or is it a newer thing?  If the
      latter, use address_list_new_one.  */
+#ifdef IPV6  
+  if(hptr->h_addrtype==AF_INET && ip_default_family==AF_INET6) 
+    {
+      struct hostent *hprt;
+      int count=0,i;
+      for(count=0;hptr->h_addr_list[count];count++);
+      hprt=xmalloc(sizeof(struct hostent));
+      hprt->h_name=strdup(hptr->h_name);
+      hprt->h_aliases=NULL;
+      hprt->h_addrtype=AF_INET6;
+      hprt->h_length=16;
+      hprt->h_addr_list=xmalloc((count+1)*sizeof(char*));
+      hprt->h_addr_list[count]=NULL;
+      for(i=0;i<count;i++)
+        {
+         hprt->h_addr_list[i]=xmalloc(16);
+         map4_to_6(hptr->h_addr_list[i],hprt->h_addr_list[i]);
+        }
+      hptr=hprt;
+    } 
+#endif  
   al = address_list_new (hptr->h_addr_list);
-
   /* Cache the lookup information. */
   cache_host_lookup (host, al);
 
diff -ubr wget-1.8.1/src/host.h wget-1.8.1_ipv6/src/host.h
--- wget-1.8.1/src/host.h       Tue Dec 11 08:32:58 2001
+++ wget-1.8.1_ipv6/src/host.h  Wed Jan 16 18:40:17 2002
@@ -19,6 +19,7 @@
 
 #ifndef HOST_H
 #define HOST_H
+#include <netdb.h>
 
 struct url;
 struct address_list;
@@ -43,5 +44,40 @@
 int sufmatch PARAMS ((const char **, const char *));
 
 void host_cleanup PARAMS ((void));
+void set_ip_address PARAMS((int ip_family,unsigned short port,
+               const unsigned char*addr,struct sockaddr *sock_name));
+void set_port  PARAMS((unsigned short port,struct sockaddr *sock_name));       
+void set_family PARAMS((int ip_family,struct sockaddr *sock_name));    
+unsigned char *get_addr PARAMS((struct sockaddr *sock_name));
+unsigned short       get_port PARAMS((struct sockaddr *sock_name));
+void map4_to_6 PARAMS((const unsigned char *IPv4,unsigned char *IPv6));
+int  map6_to_4 PARAMS((unsigned char *IPv6));
+
+#define IPV6
+#define HAVE_GETHOSTBYNAME2
+// #define HAVE_GETADDRINFO
+
+/*
+       IPv6 support added by Thomas Lussnig <[EMAIL PROTECTED]>
+       Date: 15.01.2002 02:36:05
+       If there are mistakes please inform me, but i will not work till the
+       morning on it.
+       Date: 16.01.2002
+       Final touch on FTP, Display, IPv4 to IPv6 converting
+       Function declaration cleanup
+*/
+
+#ifdef IPV6
+
+/* An IPv6 address is simply a 16-byte quantity. */
+typedef unsigned char ip_address[16];
+typedef struct sockaddr_in6    sockaddr64;
+#else
+/* An IPv4 address is simply a 4-byte quantity. */
+typedef unsigned char ip_address[4];
+typedef struct sockaddr_in     sockaddr64;
+#endif
+extern int     ip_default_family;      /* defined in host.c */
+
 
 #endif /* HOST_H */
diff -ubr wget-1.8.1/src/init.c wget-1.8.1_ipv6/src/init.c
--- wget-1.8.1/src/init.c       Thu Dec 13 19:19:03 2001
+++ wget-1.8.1_ipv6/src/init.c  Wed Jan 16 16:54:52 2002
@@ -526,8 +526,8 @@
 cmd_address (const char *com, const char *val, void *closure)
 {
   struct address_list *al;
-  struct sockaddr_in sin;
-  struct sockaddr_in **target = (struct sockaddr_in **)closure;
+  sockaddr64 sin;
+  sockaddr64 **target = (sockaddr64 **)closure;
 
   memset (&sin, '\0', sizeof (sin));
 
@@ -538,11 +538,10 @@
               exec_name, com, val);
       return 0;
     }
-  address_list_copy_one (al, 0, (unsigned char *)&sin.sin_addr);
+  set_family(ip_default_family,  (struct sockaddr*)&sin);
+  set_port  (0,(struct sockaddr*)&sin);
+  address_list_copy_one(al, 0,get_addr((struct sockaddr*)&sin));
   address_list_release (al);
-
-  sin.sin_family = AF_INET;
-  sin.sin_port = 0;
 
   FREE_MAYBE (*target);
 
diff -ubr wget-1.8.1/src/options.h wget-1.8.1_ipv6/src/options.h
--- wget-1.8.1/src/options.h    Fri Nov 30 07:39:08 2001
+++ wget-1.8.1_ipv6/src/options.h       Wed Jan 16 16:53:44 2002
@@ -19,6 +19,7 @@
 
 /* Needed for FDP.  */
 #include <stdio.h>
+#include "host.h"
 
 struct options
 {
@@ -153,7 +154,7 @@
   int page_requisites;         /* Whether we need to download all files
                                   necessary to display a page properly. */
 
-  struct sockaddr_in *bind_address; /* What local IP address to bind to. */
+  sockaddr64 *bind_address;    /* What local IP address to bind to. */
 
 #ifdef HAVE_SSL
   char *sslcertfile;           /* external client cert to use. */
--16:32:34--  ftp://134.108.34.10/pub/Mirrors/ftp.gnu.org/bash/bash-doc-2.05a.tar.gz
           => `bash-doc-2.05a.tar.gz.2'
Resolving 134.108.34.10... done.
Connecting to 134.108.34.10:21... connected.
Logging in as anonymous ... Logged in!
==> SYST ... done.    ==> PWD ... done.
==> TYPE I ... done.  ==> CWD /pub/Mirrors/ftp.gnu.org/bash ... done.
==> PORT ... done.    ==> RETR bash-doc-2.05a.tar.gz ... done.

    0K .......... .......... .......... .......... ..........   38.08 KB/s
    .
    .
    .
  850K .......... .......... .......... .........               91.92 KB/s

16:32:50 (67.14 KB/s) - `bash-doc-2.05a.tar.gz.2' saved [910402]

--16:32:50--  
ftp://ftp-stud.fht-esslingen.de/pub/Mirrors/ftp.gnu.org/bash/bash-doc-2.05a.tar.gz
           => `bash-doc-2.05a.tar.gz.3'
Resolving ftp-stud.fht-esslingen.de... done.
Connecting to ftp-stud.fht-esslingen.de[134.108.34.10]:21... connected.
Logging in as anonymous ... Logged in!
==> SYST ... done.    ==> PWD ... done.
==> TYPE I ... done.  ==> CWD /pub/Mirrors/ftp.gnu.org/bash ... done.
==> PORT ... done.    ==> RETR bash-doc-2.05a.tar.gz ... done.

    0K .......... .......... .......... .......... ..........   49.02 KB/s
    .
    .
    .
  850K .......... .......... .......... .........               92.13 KB/s

16:33:04 (86.29 KB/s) - `bash-doc-2.05a.tar.gz.3' saved [910402]

--16:33:04--  
ftp://ftp-stud.fht-esslingen.de/pub/Mirrors/ftp.gnu.org/bash/bash-doc-2.05a.tar.gz
           => `bash-doc-2.05a.tar.gz.4'
Resolving ftp-stud.fht-esslingen.de... done.
Connecting to ftp-stud.fht-esslingen.de[134.108.34.10]:21... connected.
Logging in as anonymous ... Logged in!
==> SYST ... done.    ==> PWD ... done.
==> TYPE I ... done.  ==> CWD /pub/Mirrors/ftp.gnu.org/bash ... done.
==> PASV ... done.    ==> RETR bash-doc-2.05a.tar.gz ... done.

    0K .......... .......... .......... .......... ..........   51.39 KB/s
    .
    .
    .
  850K .......... .......... .......... .........               92.13 KB/s

16:33:20 (86.54 KB/s) - `bash-doc-2.05a.tar.gz.4' saved [910402]

--16:33:20--  http://www.ix.de/
           => `index.html'
Resolving www.ix.de... done.
Connecting to www.ix.de[193.99.144.71]:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: unspecified [text/html]

    0K .......... .......... ....                               88.62 KB/s

16:33:21 (88.62 KB/s) - `index.html' saved [24592]

--16:33:21--  http://193.99.144.71/
           => `index.html.1'
Resolving 193.99.144.71... done.
Connecting to 193.99.144.71:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: unspecified [text/html]

    0K .......... .......... ....                               90.18 KB/s

16:33:21 (90.18 KB/s) - `index.html.1' saved [24655]

--16:33:21--  http://www.ipv6.euronet.be/
           => `index.html.2'
Resolving www.ipv6.euronet.be... done.
Connecting to www.ipv6.euronet.be[3ffe:8100:200:2::2]:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 3,610 [text/html]

    0K ...                                                   100%   10.31 KB/s

16:33:22 (10.31 KB/s) - `index.html.2' saved [3610/3610]

Attachment: smime.p7s
Description: S/MIME Cryptographic Signature

Reply via email to