summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorvandebo@chromium.org <vandebo@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-23 17:47:10 +0000
committervandebo@chromium.org <vandebo@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-23 17:47:10 +0000
commit2f3bc65c0d7abb88bc3f9c88d32625eceaa7f5bc (patch)
tree748f318e00982b2a3a2ca3591cbd6cdb4f5c1b6b /net
parent5ce20320ef59981866de5f51ef2ddc671ea205e8 (diff)
downloadchromium_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.h8
-rw-r--r--net/base/host_cache_unittest.cc12
-rw-r--r--net/base/host_resolver_impl.cc16
-rw-r--r--net/base/host_resolver_impl.h3
-rw-r--r--net/base/host_resolver_proc.cc6
-rw-r--r--net/base/net_util.cc34
-rw-r--r--net/base/net_util.h4
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.