зеркало из https://github.com/mozilla/pjs.git
patch for bug 68796 "IPv6 : Some IPv4 addresses won't resolve w/IPv6 OS" patch by lorenzo@colitti.com r+sr=darin
This commit is contained in:
Родитель
53b2368452
Коммит
2eef95e2b9
|
@ -538,6 +538,14 @@ pref("network.http.proxy.ssl.connect",true);
|
|||
// are handled. IDN requires a nsIIDNService implementation.
|
||||
pref("network.enableIDN", true);
|
||||
|
||||
// This preference specifies a list of domains for which DNS lookups will be
|
||||
// IPv4 only. Works around broken DNS servers which can't handle IPv6 lookups
|
||||
// and/or allows the user to disable IPv6 on a per-domain basis. See bug 68796.
|
||||
pref("network.dns.ipv4OnlyDomains", ".doubleclick.net");
|
||||
|
||||
// This preference can be used to turn off IPv6 name lookups. See bug 68796.
|
||||
pref("network.dns.disableIPv6, false);
|
||||
|
||||
// This preference controls whether or not URLs with UTF-8 characters are
|
||||
// escaped. Set this preference to TRUE for strict RFC2396 conformance.
|
||||
pref("network.standard-url.escape-utf8", true);
|
||||
|
|
|
@ -50,10 +50,13 @@
|
|||
#include "prnetdb.h"
|
||||
#include "prmon.h"
|
||||
#include "prio.h"
|
||||
#include "plstr.h"
|
||||
|
||||
static const char kPrefDnsCacheEntries[] = "network.dnsCacheEntries";
|
||||
static const char kPrefDnsCacheExpiration[] = "network.dnsCacheExpiration";
|
||||
static const char kPrefEnableIDN[] = "network.enableIDN";
|
||||
static const char kPrefIPv4OnlyDomains[] = "network.dns.ipv4OnlyDomains";
|
||||
static const char kPrefDisableIPv6[] = "network.dns.disableIPv6";
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
@ -281,40 +284,57 @@ nsDNSService::Init()
|
|||
PRUint32 maxCacheEntries = 20;
|
||||
PRUint32 maxCacheLifetime = 1; // minutes
|
||||
PRBool enableIDN = PR_TRUE;
|
||||
PRBool disableIPv6 = PR_FALSE;
|
||||
nsAdoptingCString ipv4OnlyDomains;
|
||||
|
||||
// read prefs
|
||||
nsCOMPtr<nsIPrefBranchInternal> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
|
||||
if (prefs) {
|
||||
PRInt32 val;
|
||||
if (NS_SUCCEEDED(prefs->GetIntPref(kPrefDnsCacheEntries, &val)))
|
||||
maxCacheEntries = val;
|
||||
maxCacheEntries = (PRUint32) val;
|
||||
if (NS_SUCCEEDED(prefs->GetIntPref(kPrefDnsCacheExpiration, &val)))
|
||||
maxCacheLifetime = (val / 60); // convert from seconds to minutes
|
||||
if (NS_SUCCEEDED(prefs->GetBoolPref(kPrefEnableIDN, (PRBool*)&val)))
|
||||
enableIDN = (PRBool) val;
|
||||
}
|
||||
maxCacheLifetime = val / 60; // convert from seconds to minutes
|
||||
|
||||
// we have to null out mIDN since we might be getting re-initialized
|
||||
// as a result of a pref change.
|
||||
if (enableIDN)
|
||||
mIDN = do_GetService(NS_IDNSERVICE_CONTRACTID);
|
||||
else
|
||||
mIDN = nsnull;
|
||||
// ASSUMPTION: pref branch does not modify out params on failure
|
||||
prefs->GetBoolPref(kPrefEnableIDN, &enableIDN);
|
||||
prefs->GetBoolPref(kPrefDisableIPv6, &disableIPv6);
|
||||
prefs->GetCharPref(kPrefIPv4OnlyDomains, getter_Copies(ipv4OnlyDomains));
|
||||
}
|
||||
|
||||
if (firstTime) {
|
||||
mLock = PR_NewLock();
|
||||
if (!mLock)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
|
||||
// register as prefs observer
|
||||
prefs->AddObserver(kPrefDnsCacheEntries, this, PR_FALSE);
|
||||
prefs->AddObserver(kPrefDnsCacheExpiration, this, PR_FALSE);
|
||||
prefs->AddObserver(kPrefEnableIDN, this, PR_FALSE);
|
||||
prefs->AddObserver(kPrefIPv4OnlyDomains, this, PR_FALSE);
|
||||
prefs->AddObserver(kPrefDisableIPv6, this, PR_FALSE);
|
||||
}
|
||||
|
||||
return nsHostResolver::Create(maxCacheEntries,
|
||||
maxCacheLifetime,
|
||||
getter_AddRefs(mResolver));
|
||||
// we have to null out mIDN since we might be getting re-initialized
|
||||
// as a result of a pref change.
|
||||
nsCOMPtr<nsIIDNService> idn;
|
||||
if (enableIDN)
|
||||
idn = do_GetService(NS_IDNSERVICE_CONTRACTID);
|
||||
|
||||
nsRefPtr<nsHostResolver> res;
|
||||
nsresult rv = nsHostResolver::Create(maxCacheEntries,
|
||||
maxCacheLifetime,
|
||||
getter_AddRefs(res));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// now, set all of our member variables while holding the lock
|
||||
nsAutoLock lock(mLock);
|
||||
mResolver = res;
|
||||
mIDN = idn;
|
||||
mIPv4OnlyDomains = ipv4OnlyDomains; // exchanges buffer ownership
|
||||
mDisableIPv6 = disableIPv6;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -374,9 +394,15 @@ nsDNSService::AsyncResolve(const nsACString &hostname,
|
|||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
NS_ADDREF(*result = req);
|
||||
|
||||
PRUint16 af = GetAFForLookup(req->mHost);
|
||||
|
||||
#ifdef DEBUG_darinf
|
||||
printf(">>> using af=%hu for %s\n", af, req->mHost.get());
|
||||
#endif
|
||||
|
||||
// addref for resolver; will be released when OnLookupComplete is called.
|
||||
NS_ADDREF(req);
|
||||
rv = res->ResolveHost(req->mHost.get(), bypassCache, req);
|
||||
rv = res->ResolveHost(req->mHost.get(), bypassCache, req, af);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_RELEASE(req);
|
||||
NS_RELEASE(*result);
|
||||
|
@ -424,7 +450,9 @@ nsDNSService::Resolve(const nsACString &hostname,
|
|||
PR_EnterMonitor(mon);
|
||||
nsDNSSyncRequest syncReq(mon);
|
||||
|
||||
rv = res->ResolveHost(PromiseFlatCString(*hostPtr).get(), bypassCache, &syncReq);
|
||||
PRUint16 af = GetAFForLookup(*hostPtr);
|
||||
|
||||
rv = res->ResolveHost(PromiseFlatCString(*hostPtr).get(), bypassCache, &syncReq, af);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// wait for result
|
||||
while (!syncReq.mDone)
|
||||
|
@ -480,3 +508,58 @@ nsDNSService::Observe(nsISupports *subject, const char *topic, const PRUnichar *
|
|||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRUint16
|
||||
nsDNSService::GetAFForLookup(const nsACString &host)
|
||||
{
|
||||
if (mDisableIPv6)
|
||||
return PR_AF_INET;
|
||||
|
||||
nsAutoLock lock(mLock);
|
||||
|
||||
PRUint16 af = PR_AF_UNSPEC;
|
||||
|
||||
if (!mIPv4OnlyDomains.IsEmpty()) {
|
||||
const char *domain, *domainEnd, *end;
|
||||
PRUint32 hostLen, domainLen;
|
||||
|
||||
// see if host is in one of the IPv4-only domains
|
||||
domain = mIPv4OnlyDomains.BeginReading();
|
||||
domainEnd = mIPv4OnlyDomains.EndReading();
|
||||
|
||||
nsACString::const_iterator hostStart;
|
||||
host.BeginReading(hostStart);
|
||||
hostLen = host.Length();
|
||||
|
||||
do {
|
||||
// skip any whitespace
|
||||
while (*domain == ' ' || *domain == '\t')
|
||||
++domain;
|
||||
|
||||
// find end of this domain in the string
|
||||
end = strchr(domain, ',');
|
||||
if (!end)
|
||||
end = domainEnd;
|
||||
|
||||
// to see if the hostname is in the domain, check if the domain
|
||||
// matches the end of the hostname.
|
||||
domainLen = end - domain;
|
||||
if (domainLen && hostLen >= domainLen) {
|
||||
const char *hostTail = hostStart.get() + hostLen - domainLen;
|
||||
if (PL_strncasecmp(domain, hostTail, domainLen) == 0) {
|
||||
// now, make sure either that the hostname is a direct match or
|
||||
// that the hostname begins with a dot.
|
||||
if (hostLen == domainLen ||
|
||||
*hostTail == '.' || *(hostTail - 1) == '.') {
|
||||
af = PR_AF_INET;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
domain = end + 1;
|
||||
} while (*end);
|
||||
}
|
||||
|
||||
return af;
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include "nsIObserver.h"
|
||||
#include "nsHostResolver.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsString.h"
|
||||
#include "prlock.h"
|
||||
|
||||
class nsDNSService : public nsIDNSService
|
||||
|
@ -53,9 +54,17 @@ public:
|
|||
virtual ~nsDNSService();
|
||||
|
||||
private:
|
||||
PRUint16 GetAFForLookup(const nsACString &host);
|
||||
|
||||
nsRefPtr<nsHostResolver> mResolver;
|
||||
nsCOMPtr<nsIIDNService> mIDN;
|
||||
|
||||
// mLock protects access to mResolver and mIPv4OnlyDomains
|
||||
PRLock *mLock;
|
||||
|
||||
// mLock protects access to mResolver
|
||||
// mIPv4OnlyDomains is a comma-separated list of domains for which only
|
||||
// IPv4 DNS lookups are performed. This allows the user to disable IPv6 on
|
||||
// a per-domain basis and work around broken DNS servers. See bug 68796.
|
||||
nsAdoptingCString mIPv4OnlyDomains;
|
||||
PRBool mDisableIPv6;
|
||||
};
|
||||
|
|
|
@ -351,7 +351,8 @@ nsHostResolver::Shutdown()
|
|||
nsresult
|
||||
nsHostResolver::ResolveHost(const char *host,
|
||||
PRBool bypassCache,
|
||||
nsResolveHostCallback *callback)
|
||||
nsResolveHostCallback *callback,
|
||||
PRUint16 af = PR_AF_UNSPEC)
|
||||
{
|
||||
NS_ENSURE_TRUE(host && *host, NS_ERROR_UNEXPECTED);
|
||||
|
||||
|
@ -414,6 +415,7 @@ nsHostResolver::ResolveHost(const char *host,
|
|||
PR_APPEND_LINK(callback, &he->rec->callbacks);
|
||||
|
||||
if (!he->rec->resolving) {
|
||||
he->rec->af = af;
|
||||
rv = IssueLookup(he->rec);
|
||||
if (NS_FAILED(rv))
|
||||
PR_REMOVE_AND_INIT_LINK(callback);
|
||||
|
@ -603,10 +605,10 @@ nsHostResolver::ThreadFunc(void *arg)
|
|||
PRAddrInfo *ai;
|
||||
while (resolver->GetHostToLookup(&rec)) {
|
||||
LOG(("resolving %s ...\n", rec->host));
|
||||
ai = PR_GetAddrInfoByName(rec->host, PR_AF_UNSPEC, PR_AI_ADDRCONFIG);
|
||||
ai = PR_GetAddrInfoByName(rec->host, rec->af, PR_AI_ADDRCONFIG);
|
||||
#if defined(RES_RETRY_ON_FAILURE)
|
||||
if (!ai && rs.Reset())
|
||||
ai = PR_GetAddrInfoByName(rec->host, PR_AF_UNSPEC, PR_AI_ADDRCONFIG);
|
||||
ai = PR_GetAddrInfoByName(rec->host, rec->af, PR_AI_ADDRCONFIG);
|
||||
#endif
|
||||
// convert error code to nsresult.
|
||||
nsresult status = ai ? NS_OK : NS_ERROR_UNKNOWN_HOST;
|
||||
|
|
|
@ -81,10 +81,12 @@ public:
|
|||
* otherwise, if |addrinfo| is non-null, then it contains one or many
|
||||
* IP addresses corresponding to the given host name. if both |addrinfo|
|
||||
* and |addr| are null, then the given host has not yet been fully resolved.
|
||||
* |af| is the address family of the record we are querying for.
|
||||
*/
|
||||
char *host;
|
||||
PRAddrInfo *addrinfo;
|
||||
PRNetAddr *addr;
|
||||
PRUint16 af;
|
||||
PRUint32 expiration; /* measured in minutes since epoch */
|
||||
|
||||
PRBool HasResult() const { return (addrinfo || addr) != nsnull; }
|
||||
|
@ -163,7 +165,8 @@ public:
|
|||
*/
|
||||
nsresult ResolveHost(const char *hostname,
|
||||
PRBool bypassCache,
|
||||
nsResolveHostCallback *callback);
|
||||
nsResolveHostCallback *callback,
|
||||
PRUint16 af);
|
||||
|
||||
/**
|
||||
* removes the specified callback from the nsHostRecord for the given
|
||||
|
|
Загрузка…
Ссылка в новой задаче