Subject: Re: Mozilla and IPv6
To: None <thorpej@zembu.com>
From: Shin'ichiro TAYA <taya@ba2.so-net.ne.jp>
List: tech-pkg
Date: 07/07/2001 10:24:14
From: Jason R Thorpe <thorpej@zembu.com>
Subject: Re: Mozilla and IPv6
Date: Fri, 6 Jul 2001 09:32:11 -0700
> On Fri, Jul 06, 2001 at 08:50:36AM +0200, Emmanuel Dreyfus wrote:
>
> > Is it a config problem, or should it be fixed in Mozilla?
>
> Mozilla needs to be fixed. It's horribly broken in this regard. It
> won't try multiple addresses at all.
I made a patch for this bug.
It's only a quick hack and should be carefully reviewed.
I only tested to connect www.netbsd.org & www.kame.net (both have v4 & v6 address)
Index: nsSocketTransport.cpp
===================================================================
RCS file: /cvsroot/mozilla/netwerk/base/src/nsSocketTransport.cpp,v
retrieving revision 1.208
diff -u -r1.208 nsSocketTransport.cpp
--- nsSocketTransport.cpp 2001/06/18 21:26:16 1.208
+++ nsSocketTransport.cpp 2001/07/07 01:23:39
@@ -170,8 +170,12 @@
//
// Set up Internet defaults...
//
+#if 0
memset(&mNetAddress, 0, sizeof(mNetAddress));
PR_SetNetAddr(PR_IpAddrAny, PR_AF_INET6, 0, &mNetAddress);
+#else
+ mNetAddressList = NULL;
+#endif
//
// Initialize the global connect timeout value if necessary...
@@ -220,6 +224,13 @@
nsAutoMonitor::DestroyMonitor(mMonitor);
mMonitor = nsnull;
}
+
+ PRNetAddrList *p, *next;;
+ for(p = mNetAddressList; p; ){
+ next = p->next;
+ delete p;
+ p = next;
+ }
}
@@ -603,14 +614,20 @@
//
// The hostname has not been resolved yet...
//
+#if 0
if (PR_IsNetAddrType(&mNetAddress, PR_IpAddrAny)) {
+#else
+ if (mNetAddressList == NULL) {
+#endif
//
// Initialize the port used for the connection...
//
// XXX: The list of ports must be restricted - see net_bad_ports_table[] in
// mozilla/network/main/mkconect.c
//
+#if 0
mNetAddress.ipv6.port = PR_htons(((mProxyPort != -1 && !mProxyTransparent) ? mProxyPort : mPort));
+#endif
NS_WITH_SERVICE(nsIDNSService,
pDNSService,
@@ -637,7 +654,11 @@
//
// The DNS lookup has finished... It has either failed or succeeded.
//
+#if 0
if (NS_FAILED(mStatus) || !PR_IsNetAddrType(&mNetAddress, PR_IpAddrAny)) {
+#else
+ if (NS_FAILED(mStatus) || mNetAddressList != NULL) {
+#endif
mDNSRequest = 0;
rv = mStatus;
}
@@ -798,7 +819,12 @@
// This is only done the first time doConnection(...) is called.
//
if (NS_SUCCEEDED(rv)) {
+#if 0
status = PR_Connect(mSocketFD, &mNetAddress, gConnectTimeout);
+#else
+try_again:
+ status = PR_Connect(mSocketFD, &(mNetAddressp->mNetAddress), gConnectTimeout);
+#endif
if (PR_SUCCESS != status) {
PRErrorCode code = PR_GetError();
//
@@ -823,6 +849,9 @@
//
else {
// Connection refused...
+ if((mNetAddressp = mNetAddressp->next)){
+ goto try_again;
+ }
LOG(("nsSocketTransport: Connection Refused [%s:%d %x]. PRErrorCode = %x\n",
mHostName, mPort, this, code));
rv = NS_ERROR_CONNECTION_REFUSED;
@@ -836,11 +865,17 @@
//
else if (aSelectFlags) {
if (PR_POLL_EXCEPT & aSelectFlags) {
+ if((mNetAddressp = mNetAddressp->next)){
+ goto try_again;
+ }
LOG(("nsSocketTransport: Connection Refused via PR_POLL_EXCEPT. [%s:%d %x].\n",
mHostName, mPort, this));
rv = NS_ERROR_CONNECTION_REFUSED;
}
else if (PR_POLL_HUP & aSelectFlags) {
+ if((mNetAddressp = mNetAddressp->next)){
+ goto try_again;
+ }
LOG(("nsSocketTransport: Connection Refused via PR_POLL_HUP. [%s:%d %x].\n",
mHostName, mPort, this));
rv = NS_ERROR_CONNECTION_REFUSED;
@@ -883,7 +918,11 @@
//
// The hostname has not been resolved yet...
//
+#if 0
if (PR_IsNetAddrType(&mNetAddress, PR_IpAddrAny)) {
+#else
+ if (mNetAddressList == NULL) {
+#endif
NS_WITH_SERVICE(nsIDNSService,
pDNSService,
kDNSService,
@@ -905,6 +944,7 @@
return NS_ERROR_FAILURE;
}
+#if 0
if (addr.raw.family == PR_AF_INET)
PR_ConvertIPv4AddrToIPv6(addr.inet.ip, &mNetAddress.ipv6.ip);
else
@@ -915,6 +955,21 @@
LOG(("address { family=%hu, port=%hu }\n",
mNetAddress.ipv6.family, PR_ntohs(mNetAddress.ipv6.port)));
+#else
+/****************/
+ mNetAddressList = new PRNetAddrList;
+ mNetAddressList->next = NULL;
+ if (addr.raw.family == PR_AF_INET)
+ PR_ConvertIPv4AddrToIPv6(addr.inet.ip, &(mNetAddressList->mNetAddress.ipv6.ip));
+ else
+ memcpy(&(mNetAddressList->mNetAddress.ipv6.ip), &addr.ipv6.ip, sizeof(mNetAddressList->mNetAddress.ipv6.ip));
+
+ mNetAddressList->mNetAddress.ipv6.port
+ = PR_htons(((mProxyPort != -1 && !mProxyTransparent) ? mProxyPort : mPort));
+
+ LOG(("address { family=%hu, port=%hu }\n",
+ mNetAddressList->mNetAddress.ipv6.family, PR_ntohs(mNetAddressList->mNetAddress.ipv6.port)));
+#endif
}
//
@@ -1346,6 +1401,7 @@
return NS_OK;
}
+#if 0
NS_IMETHODIMP
nsSocketTransport::OnFound(nsISupports *aContext,
const char* aHostName,
@@ -1382,6 +1438,53 @@
return rv;
}
+#else
+static unsigned char v4addr_hdr[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff};
+
+NS_IMETHODIMP
+nsSocketTransport::OnFound(nsISupports *aContext,
+ const char* aHostName,
+ nsHostEnt *aHostEnt)
+{
+ // Enter the socket transport lock...
+ nsAutoMonitor mon(mMonitor);
+ nsresult rv = NS_OK;
+ char **p;
+ PRNetAddrList **addrp = &mNetAddressList;
+
+ if (aHostEnt->hostEnt.h_addr_list && aHostEnt->hostEnt.h_addr_list[0]) {
+ for(p = aHostEnt->hostEnt.h_addr_list; *p; p++){
+ *addrp = new PRNetAddrList;
+ (*addrp)->next = NULL;
+ (*addrp)->mNetAddress.ipv6.port = PR_htons(((mProxyPort != -1 && !mProxyTransparent) ? mProxyPort : mPort));
+ (*addrp)->mNetAddress.raw.family = PR_AF_INET6;
+ memcpy(&((*addrp)->mNetAddress.ipv6.ip), *p, sizeof((*addrp)->mNetAddress.ipv6.ip));
+#if 0
+ char addrbuf[50];
+ PR_NetAddrToString(&((*addrp)->mNetAddress), addrbuf, sizeof(addrbuf));
+ LOG(("nsSocketTransport: OnFound(...) [%s:%d %x]."
+ " DNS lookup succeeded => %s (%s)\n",
+ mHostName, mPort, this,
+ aHostEnt->hostEnt.h_name,
+ addrbuf));
+#endif
+ addrp = &((*addrp)->next);
+ }
+ mNetAddressp = mNetAddressList;
+ } else {
+ // XXX: What should happen here? The GetHostByName(...) succeeded but
+ // there are *no* A records...
+ rv = NS_ERROR_FAILURE;
+
+ LOG(("nsSocketTransport: OnFound(...) [%s:%d %x]."
+ " DNS lookup succeeded (%s) but no address returned!",
+ mHostName, mPort, this,
+ aHostEnt->hostEnt.h_name));
+ }
+
+ return rv;
+}
+#endif
NS_IMETHODIMP
nsSocketTransport::OnStopLookup(nsISupports *aContext,
@@ -1401,7 +1504,11 @@
// If the lookup failed, set the status...
if (NS_FAILED(aStatus))
mStatus = aStatus;
+#if 0
else if (PR_IsNetAddrType(&mNetAddress, PR_IpAddrAny))
+#else
+ else if (mNetAddressList == NULL)
+#endif
mStatus = NS_ERROR_ABORT;
// Start processing the transport again - if necessary...
@@ -1728,7 +1835,11 @@
*_retval = (char*)nsMemory::Alloc(aLen);
if (!*_retval) return NS_ERROR_FAILURE;
+#if 0
PRStatus status = PR_NetAddrToString(&mNetAddress, *_retval, aLen);
+#else
+ PRStatus status = PR_NetAddrToString(&mNetAddressList->mNetAddress, *_retval, aLen);
+#endif
if (PR_FAILURE == status) {
nsMemory::Free(*_retval);
Index: nsSocketTransport.h
===================================================================
RCS file: /cvsroot/mozilla/netwerk/base/src/nsSocketTransport.h,v
retrieving revision 1.89
diff -u -r1.89 nsSocketTransport.h
--- nsSocketTransport.h 2001/05/11 21:03:21 1.89
+++ nsSocketTransport.h 2001/07/07 01:23:49
@@ -107,6 +107,11 @@
eSocketDNS_Wait = 0x2020
};
+typedef struct PRNetAddrList{
+ PRNetAddr mNetAddress;
+ struct PRNetAddrList *next;
+} PRNetAddrList;
+
//
// This is the default timeout value (in milliseconds) for sockets which have
// no activity...
@@ -231,7 +236,12 @@
PRIntervalTime mLastActiveTime;
PRCList mListLink;
PRMonitor* mMonitor;
+#if 0
PRNetAddr mNetAddress;
+#else
+ PRNetAddrList *mNetAddressList;
+ PRNetAddrList *mNetAddressp;
+#endif
nsSocketOperation mOperation;
nsCOMPtr<nsISupports> mSecurityInfo;