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]
smime.p7s
Description: S/MIME Cryptographic Signature
