diff options
author | vandebo@chromium.org <vandebo@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-23 17:47:10 +0000 |
---|---|---|
committer | vandebo@chromium.org <vandebo@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-23 17:47:10 +0000 |
commit | 2f3bc65c0d7abb88bc3f9c88d32625eceaa7f5bc (patch) | |
tree | 748f318e00982b2a3a2ca3591cbd6cdb4f5c1b6b /net | |
parent | 5ce20320ef59981866de5f51ef2ddc671ea205e8 (diff) | |
download | chromium_src-2f3bc65c0d7abb88bc3f9c88d32625eceaa7f5bc.zip chromium_src-2f3bc65c0d7abb88bc3f9c88d32625eceaa7f5bc.tar.gz chromium_src-2f3bc65c0d7abb88bc3f9c88d32625eceaa7f5bc.tar.bz2 |
[Linux] Enable connecting to localhost when offline.
Add a utility function to determine if only loopback address are configured.
Add a mechanism to add supplemental HostResolverFlags in the HostResolver.
Change the resolver on Linux to not use AI_ADDRCONFIG if only loopback addresses are configured.
BUG=41408
TEST=localhost works when offline
Review URL: http://codereview.chromium.org/3036011
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@53487 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r-- | net/base/address_family.h | 8 | ||||
-rw-r--r-- | net/base/host_cache_unittest.cc | 12 | ||||
-rw-r--r-- | net/base/host_resolver_impl.cc | 16 | ||||
-rw-r--r-- | net/base/host_resolver_impl.h | 3 | ||||
-rw-r--r-- | net/base/host_resolver_proc.cc | 6 | ||||
-rw-r--r-- | net/base/net_util.cc | 34 | ||||
-rw-r--r-- | net/base/net_util.h | 4 |
7 files changed, 78 insertions, 5 deletions
diff --git a/net/base/address_family.h b/net/base/address_family.h index fee0584..a9302d9 100644 --- a/net/base/address_family.h +++ b/net/base/address_family.h @@ -15,10 +15,12 @@ enum AddressFamily { ADDRESS_FAMILY_IPV6, // AF_INET6 }; -// HostResolverFlags is a bitflag enum wrapper around the addrinfo.ai_flags -// supported by host resolver procedures. +// HostResolverFlags is a bitflag enum used by host resolver procedures to +// determine the value of addrinfo.ai_flags. enum { - HOST_RESOLVER_CANONNAME = 1 << 0, // 0x1, AI_CANONNAME + HOST_RESOLVER_CANONNAME = 1 << 0, // AI_CANONNAME + // Hint to the resolver proc that only loopback addresses are configured. + HOST_RESOLVER_LOOPBACK_ONLY = 1 << 1, }; typedef int HostResolverFlags; diff --git a/net/base/host_cache_unittest.cc b/net/base/host_cache_unittest.cc index a851c0b..54a64c4 100644 --- a/net/base/host_cache_unittest.cc +++ b/net/base/host_cache_unittest.cc @@ -314,9 +314,12 @@ TEST(HostCacheTest, HostResolverFlagsArePartOfKey) { HostCache::Key key1("foobar.com", ADDRESS_FAMILY_IPV4, 0); HostCache::Key key2("foobar.com", ADDRESS_FAMILY_IPV4, HOST_RESOLVER_CANONNAME); + HostCache::Key key3("foobar.com", ADDRESS_FAMILY_IPV4, + HOST_RESOLVER_LOOPBACK_ONLY); const HostCache::Entry* entry1 = NULL; // Entry for key1 const HostCache::Entry* entry2 = NULL; // Entry for key2 + const HostCache::Entry* entry3 = NULL; // Entry for key3 EXPECT_EQ(0U, cache.size()); @@ -334,9 +337,18 @@ TEST(HostCacheTest, HostResolverFlagsArePartOfKey) { EXPECT_FALSE(entry2 == NULL); EXPECT_EQ(2U, cache.size()); + // Add an entry for ("foobar.com", IPV4, LOOPBACK_ONLY) at t=0. + EXPECT_TRUE(cache.Lookup(key3, base::TimeTicks()) == NULL); + cache.Set(key3, OK, AddressList(), now); + entry3 = cache.Lookup(key3, base::TimeTicks()); + EXPECT_FALSE(entry3 == NULL); + EXPECT_EQ(3U, cache.size()); + // Even though the hostnames were the same, we should have two unique // entries (because the HostResolverFlags differ). EXPECT_NE(entry1, entry2); + EXPECT_NE(entry1, entry3); + EXPECT_NE(entry2, entry3); } TEST(HostCacheTest, NoCache) { diff --git a/net/base/host_resolver_impl.cc b/net/base/host_resolver_impl.cc index ffba57f..0f2e5f0 100644 --- a/net/base/host_resolver_impl.cc +++ b/net/base/host_resolver_impl.cc @@ -715,7 +715,8 @@ HostResolverImpl::HostResolverImpl( resolver_proc_(resolver_proc), default_address_family_(ADDRESS_FAMILY_UNSPECIFIED), shutdown_(false), - ipv6_probe_monitoring_(false) { + ipv6_probe_monitoring_(false), + additional_resolver_flags_(0) { DCHECK_GT(max_jobs, 0u); // It is cumbersome to expose all of the constraints in the constructor, @@ -725,6 +726,10 @@ HostResolverImpl::HostResolverImpl( #if defined(OS_WIN) EnsureWinsockInit(); #endif +#if defined(OS_LINUX) + if (HaveOnlyLoopbackAddresses()) + additional_resolver_flags_ |= HOST_RESOLVER_LOOPBACK_ONLY; +#endif NetworkChangeNotifier::AddObserver(this); } @@ -1054,6 +1059,13 @@ void HostResolverImpl::OnIPAddressChanged() { ipv6_probe_job_ = new IPv6ProbeJob(this); ipv6_probe_job_->Start(); } +#if defined(OS_LINUX) + if (HaveOnlyLoopbackAddresses()) { + additional_resolver_flags_ |= HOST_RESOLVER_LOOPBACK_ONLY; + } else { + additional_resolver_flags_ &= ~HOST_RESOLVER_LOOPBACK_ONLY; + } +#endif } void HostResolverImpl::DiscardIPv6ProbeJob() { @@ -1124,7 +1136,7 @@ HostResolverImpl::Key HostResolverImpl::GetEffectiveKeyForRequest( if (effective_address_family == ADDRESS_FAMILY_UNSPECIFIED) effective_address_family = default_address_family_; return Key(info.hostname(), effective_address_family, - info.host_resolver_flags()); + info.host_resolver_flags() | additional_resolver_flags_); } HostResolverImpl::Job* HostResolverImpl::CreateAndStartJob(Request* req) { diff --git a/net/base/host_resolver_impl.h b/net/base/host_resolver_impl.h index 28526d1..199ddcf 100644 --- a/net/base/host_resolver_impl.h +++ b/net/base/host_resolver_impl.h @@ -252,6 +252,9 @@ class HostResolverImpl : public HostResolver, // The last un-cancelled IPv6ProbeJob (if any). scoped_refptr<IPv6ProbeJob> ipv6_probe_job_; + // Any resolver flags that should be added to a request by default. + HostResolverFlags additional_resolver_flags_; + DISALLOW_COPY_AND_ASSIGN(HostResolverImpl); }; diff --git a/net/base/host_resolver_proc.cc b/net/base/host_resolver_proc.cc index 804135c..8e8034f 100644 --- a/net/base/host_resolver_proc.cc +++ b/net/base/host_resolver_proc.cc @@ -216,6 +216,12 @@ int SystemHostResolverProc(const std::string& host, hints.ai_flags = AI_ADDRCONFIG; #endif + // On Linux AI_ADDRCONFIG doesn't consider loopback addreses, even if only + // loopback addresses are configured. So don't use it when there are only + // loopback addresses. + if (host_resolver_flags & HOST_RESOLVER_LOOPBACK_ONLY) + hints.ai_flags &= ~AI_ADDRCONFIG; + if (host_resolver_flags & HOST_RESOLVER_CANONNAME) hints.ai_flags |= AI_CANONNAME; diff --git a/net/base/net_util.cc b/net/base/net_util.cc index d521439..961023a 100644 --- a/net/base/net_util.cc +++ b/net/base/net_util.cc @@ -1776,6 +1776,40 @@ bool IPv6Supported() { #endif // defined(various platforms) } +bool HaveOnlyLoopbackAddresses() { +#if defined(OS_POSIX) + struct ifaddrs* interface_addr = NULL; + int rv = getifaddrs(&interface_addr); + if (rv != 0) { + DLOG(INFO) << "getifaddrs() failed with errno = " << errno; + return false; + } + + bool result = true; + for (struct ifaddrs* interface = interface_addr; + interface != NULL; + interface = interface->ifa_next) { + if (!(IFF_UP & interface->ifa_flags)) + continue; + if (IFF_LOOPBACK & interface->ifa_flags) + continue; + const struct sockaddr* addr = interface->ifa_addr; + if (!addr) + continue; + if (addr->sa_family != AF_INET6 && addr->sa_family != AF_INET) + continue; + + result = false; + break; + } + freeifaddrs(interface_addr); + return result; +#else + NOTIMPLEMENTED(); + return false; +#endif // defined(various platforms) +} + bool ParseIPLiteralToNumber(const std::string& ip_literal, IPAddressNumber* ip_number) { // |ip_literal| could be either a IPv4 or an IPv6 literal. If it contains diff --git a/net/base/net_util.h b/net/base/net_util.h index 5633c11..978d4fb 100644 --- a/net/base/net_util.h +++ b/net/base/net_util.h @@ -327,6 +327,10 @@ void SetExplicitlyAllowedPorts(const std::wstring& allowed_ports); // TODO(jar): Make test more in-depth as needed. bool IPv6Supported(); +// Returns true if it can determine that only loopback addresses are configured. +// i.e. if only 127.0.0.1 and ::1 are routable. +bool HaveOnlyLoopbackAddresses(); + // IPAddressNumber is used to represent an IP address's numeric value as an // array of bytes, from most significant to least significant. This is the // network byte ordering. |