Commit 192676ca authored by jar@chromium.org's avatar jar@chromium.org

Support replacement of IP address resolutions via command line flag

Provide a command line flag that can accept a list or range of resolution IP
address (such as those for a known CDN), and place an alternative resolution
at the start of the resolution list (driving towrads a test server).

r=wtc
BUG=342116

Review URL: https://codereview.chromium.org/156963003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@252289 0039d316-1c4b-4281-b951-d872f2087c98
parent 51603113
......@@ -48,6 +48,7 @@
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/cookie_store_factory.h"
#include "net/base/host_mapping_rules.h"
#include "net/base/ip_mapping_rules.h"
#include "net/base/net_util.h"
#include "net/base/network_time_notifier.h"
#include "net/base/sdch_manager.h"
......@@ -60,6 +61,7 @@
#include "net/dns/host_cache.h"
#include "net/dns/host_resolver.h"
#include "net/dns/mapped_host_resolver.h"
#include "net/dns/mapped_ip_resolver.h"
#include "net/ftp/ftp_network_layer.h"
#include "net/http/http_auth_filter.h"
#include "net/http/http_auth_handler_factory.h"
......@@ -197,17 +199,28 @@ scoped_ptr<net::HostResolver> CreateGlobalHostResolver(net::NetLog* net_log) {
global_host_resolver->SetDefaultAddressFamily(net::ADDRESS_FAMILY_IPV4);
}
// If hostname remappings were specified on the command-line, layer these
// rules on top of the real host resolver. This allows forwarding all requests
// through a designated test server.
if (!command_line.HasSwitch(switches::kHostResolverRules))
return global_host_resolver.PassAs<net::HostResolver>();
scoped_ptr<net::MappedHostResolver> remapped_resolver(
new net::MappedHostResolver(global_host_resolver.Pass()));
remapped_resolver->SetRulesFromString(
command_line.GetSwitchValueASCII(switches::kHostResolverRules));
return remapped_resolver.PassAs<net::HostResolver>();
// If hostname or IP remappings were specified on the command-line, layer
// these rules on top of the real host resolver. Hostname remapping allows
// forwarding of all requests to hosts (matching a pattern) through a
// designated test server. IP remapping allows for all IP resolutions that
// match a given pattern, such as those destined for a specific CDN, to be
// instead directed to a specific/alternate IP address.
if (command_line.HasSwitch(switches::kHostResolverRules)) {
scoped_ptr<net::MappedHostResolver> remapped_resolver(
new net::MappedHostResolver(global_host_resolver.Pass()));
remapped_resolver->SetRulesFromString(
command_line.GetSwitchValueASCII(switches::kHostResolverRules));
global_host_resolver = remapped_resolver.Pass();
}
if (command_line.HasSwitch(switches::kIpResolverRules)) {
scoped_ptr<net::MappedIPResolver> remapped_resolver(
new net::MappedIPResolver(global_host_resolver.Pass()));
remapped_resolver->SetRulesFromString(
command_line.GetSwitchValueASCII(switches::kIpResolverRules));
global_host_resolver = remapped_resolver.Pass();
}
return global_host_resolver.Pass();
}
// TODO(willchan): Remove proxy script fetcher context since it's not necessary
......
......@@ -673,6 +673,10 @@ const char kIgnoreGpuBlacklist[] = "ignore-gpu-blacklist";
// Run the GPU process as a thread in the browser process.
const char kInProcessGPU[] = "in-process-gpu";
// These mappings only apply to the host resolver, and can insert additional
// resolutions in front of resolutions that match a pattern.
const char kIpResolverRules[] = "ip-resolver-rules";
// Specifies the flags passed to JS engine
const char kJavaScriptFlags[] = "js-flags";
......
......@@ -197,6 +197,7 @@ CONTENT_EXPORT extern const char kHostResolverRules[];
CONTENT_EXPORT extern const char kIgnoreCertificateErrors[];
CONTENT_EXPORT extern const char kIgnoreGpuBlacklist[];
extern const char kInProcessGPU[];
CONTENT_EXPORT extern const char kIpResolverRules[];
CONTENT_EXPORT extern const char kJavaScriptFlags[];
extern const char kLoadPlugin[];
CONTENT_EXPORT extern const char kLogGpuControlListDecisions[];
......
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "net/base/ip_mapping_rules.h"
#include <vector>
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_tokenizer.h"
#include "base/strings/string_util.h"
#include "net/base/address_list.h"
#include "net/base/ip_pattern.h"
namespace net {
class IPMappingRules::Rule {
public:
Rule(const IPAddressNumber& address, IPPattern* pattern)
: pattern_(pattern),
replacement_address_(address) {
}
bool Match(const IPAddressNumber& address) const {
return pattern_->Match(address);
}
const IPAddressNumber& replacement_address() const {
return replacement_address_;
}
private:
scoped_ptr<IPPattern> pattern_; // The pattern we can match.
IPAddressNumber replacement_address_; // The replacement address we provide.
DISALLOW_COPY_AND_ASSIGN(Rule);
};
IPMappingRules::IPMappingRules() {}
IPMappingRules::~IPMappingRules() {
STLDeleteElements(&rules_);
}
bool IPMappingRules::RewriteAddresses(AddressList* addresses) const {
// Last rule pushed into the list has the highest priority, and is tested
// first.
for (RuleList::const_reverse_iterator rule_it = rules_.rbegin();
rule_it != rules_.rend(); ++rule_it) {
for (AddressList::iterator address_it = addresses->begin();
address_it != addresses->end(); ++address_it) {
if (!(*rule_it)->Match(address_it->address()))
continue;
// We have a match.
int port = address_it->port();
addresses->insert(addresses->begin(),
IPEndPoint((*rule_it)->replacement_address(), port));
return true;
}
}
return false;
}
bool IPMappingRules::AddRuleFromString(const std::string& rule_string) {
std::string trimmed;
TrimWhitespaceASCII(rule_string, TRIM_ALL, &trimmed);
if (trimmed.empty())
return true; // Allow empty rules.
std::vector<std::string> parts;
base::SplitString(trimmed, ' ', &parts);
if (parts.size() != 3) {
DVLOG(1) << "Rule has wrong number of parts: " << rule_string;
return false;
}
if (!LowerCaseEqualsASCII(parts[0], "preface")) {
DVLOG(1) << "Unknown directive: " << rule_string;
return false;
}
scoped_ptr<IPPattern> pattern(new IPPattern);
if (!pattern->ParsePattern(parts[1])) {
DVLOG(1) << "Unacceptable pattern: " << rule_string;
return false;
}
IPAddressNumber address;
if (!ParseIPLiteralToNumber(parts[2], &address)) {
DVLOG(1) << "Invalid replacement address: " << rule_string;
return false;
}
if (pattern->is_ipv4() != (address.size() == kIPv4AddressSize)) {
DVLOG(1) << "Mixture of IPv4 and IPv6: " << rule_string;
return false;
}
rules_.push_back(new Rule(address, pattern.release()));
return true;
}
bool IPMappingRules::SetRulesFromString(const std::string& rules_string) {
STLDeleteElements(&rules_);
base::StringTokenizer rules(rules_string, ";");
while (rules.GetNext()) {
if (!AddRuleFromString(rules.token())) {
DVLOG(1) << "Failed parsing rule: " << rules.token();
STLDeleteElements(&rules_);
return false;
}
}
return true;
}
} // namespace net
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef NET_BASE_IP_MAPPING_RULES_H_
#define NET_BASE_IP_MAPPING_RULES_H_
#include <string>
#include <vector>
#include "base/macros.h"
#include "net/base/net_export.h"
namespace net {
class AddressList;
// This class contains a list of rules, that can be used to process (Rewrite) a
// set of DNS resolutions (IP addresses) in accordance with those rules.
// Currently the only rules supported use a pattern match against some given IP
// addresses, and may, if there is a match, place one new IP address at the
// start of the rewritten address list (re: the "PREFACE" directive). This
// supports a common use case where the matching detects an address in a given
// edge network server group, and the inserted address points to a server that
// is expected to handle all requests that would otherwise have gone to the
// given group of servers.
class NET_EXPORT_PRIVATE IPMappingRules {
public:
IPMappingRules();
~IPMappingRules();
// Modifies |*addresses| based on the current rules. Returns true if
// |addresses| was modified, false otherwise.
bool RewriteAddresses(AddressList* addresses) const;
// Adds a rule to this mapper.
// Rules are evaluated against an address list until a first matching rule is
// found that applies, causing a modification of the address list.
// Each rule consists of one or more of the following pattern and action
// directives.
//
// RULE: CHANGE_DIRECTIVE | EMPTY
// CHANGE_DIRECTIVE: "PREFACE" SPACE IP_PATTERN SPACE IP_LITERAL
// SPACE: " "
// EMPTY:
//
// IP_LITERAL: IP_V6_LITERAL | IP_V4_LITERAL
//
// IP_V4_LITERAL: OCTET "." OCTET "." OCTET "." OCTET
// OCTET: decimal number in range 0 ... 255
//
// IP_V6_LITERAL: HEX_COMPONENT | IP_V6_LITERAL ":" HEX_COMPONENT
// HEX_COMPONENT: hexadecimal values with no more than 4 hex digits
//
// IP_PATTERN: IP_V6_PATTERN | IP_V4_PATTERN
//
// IP_V6_PATTERN: HEX_PATTERN | IP_V6_PATTERN ":" HEX_PATTERN
// HEX_PATTERN: HEX_COMPONENT | "[" HEX_GROUP_PATTERN "]" | "*"
// HEX_GROUP_PATTERN: HEX_RANGE | HEX_GROUP_PATTERN "," HEX_RANGE
// HEX_RANGE: HEX_COMPONENT | HEX_COMPONENT "-" HEX_COMPONENT
//
// IP_V4_PATTERN: OCTET_PATTERN "." OCTET_PATTERN "." OCTET_PATTERN
// "." OCTET_PATTERN
// OCTET_PATTERN: OCTET | "[" OCTET_GROUP_PATTERN "]" | "*"
// OCTET_GROUP_PATTERN: OCTET_RANGE | OCTET_GROUP_PATTERN "," OCTET_RANGE
// OCTET_RANGE: OCTET | OCTET "-" OCTET
//
// All literals are required to have all their components specified (4
// components for IPv4, and 8 for IPv6). Specifically, there is currently no
// support for elided compenents in an IPv6 address (e.g., "::").
// Returns true if the rule was successfully parsed and added.
bool AddRuleFromString(const std::string& rule_string);
// Sets the rules from a semicolon separated list of rules.
// Returns true if all the rules were successfully parsed and added.
bool SetRulesFromString(const std::string& rules_string);
private:
class Rule;
typedef std::vector<Rule*> RuleList;
// We own all rules in this list, and are responsible for their destruction.
RuleList rules_;
DISALLOW_COPY_AND_ASSIGN(IPMappingRules);
};
} // namespace net
#endif // NET_BASE_IP_MAPPING_RULES_H_
This diff is collapsed.
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "net/base/ip_pattern.h"
#include <string>
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_tokenizer.h"
namespace net {
class IPPattern::ComponentPattern {
public:
ComponentPattern();
void AppendRange(uint32 min, uint32 max);
bool Match(uint32 value) const;
private:
struct Range {
public:
Range(uint32 min, uint32 max) : minimum(min), maximum(max) {}
uint32 minimum;
uint32 maximum;
};
typedef std::vector<Range> RangeVector;
RangeVector ranges_;
DISALLOW_COPY_AND_ASSIGN(ComponentPattern);
};
IPPattern::ComponentPattern::ComponentPattern() {}
void IPPattern::ComponentPattern::AppendRange(uint32 min, uint32 max) {
ranges_.push_back(Range(min, max));
}
bool IPPattern::ComponentPattern::Match(uint32 value) const {
// Simple linear search should be fine, as we usually only have very few
// distinct ranges to test.
for (RangeVector::const_iterator range_it = ranges_.begin();
range_it != ranges_.end(); ++range_it) {
if (range_it->maximum >= value && range_it->minimum <= value)
return true;
}
return false;
}
IPPattern::IPPattern() : is_ipv4_(true) {}
IPPattern::~IPPattern() {
STLDeleteElements(&component_patterns_);
}
bool IPPattern::Match(const IPAddressNumber& address) const {
if (ip_mask_.empty())
return false;
bool address_is_ipv4 = address.size() == kIPv4AddressSize;
if (address_is_ipv4 != is_ipv4_)
return false;
ComponentPatternList::const_iterator pattern_it(component_patterns_.begin());
int fixed_value_index = 0;
// IPv6 |address| vectors have 16 pieces, while our |ip_mask_| has only
// 8, so it is easier to count separately.
int address_index = 0;
for (size_t i = 0; i < ip_mask_.size(); ++i) {
uint32 value_to_test = address[address_index++];
if (!is_ipv4_) {
value_to_test = (value_to_test << 8) + address[address_index++];
}
if (ip_mask_[i]) {
if (component_values_[fixed_value_index++] != value_to_test)
return false;
continue;
}
if (!(*pattern_it)->Match(value_to_test))
return false;
++pattern_it;
}
return true;
}
bool IPPattern::ParsePattern(const std::string& ip_pattern) {
DCHECK(ip_mask_.empty());
if (ip_pattern.find(':') != std::string::npos) {
is_ipv4_ = false;
}
Strings components;
base::SplitString(ip_pattern, is_ipv4_ ? '.' : ':', &components);
if (components.size() != (is_ipv4_ ? 4u : 8u)) {
DVLOG(1) << "Invalid component count: " << ip_pattern;
return false;
}
for (Strings::iterator component_it = components.begin();
component_it != components.end(); ++component_it) {
if (component_it->empty()) {
DVLOG(1) << "Empty component: " << ip_pattern;
return false;
}
if (*component_it == "*") {
// Let standard code handle this below.
*component_it = is_ipv4_ ? "[0-255]" : "[0-FFFF]";
} else if ((*component_it)[0] != '[') {
// This value will just have a specific integer to match.
uint32 value;
if (!ValueTextToInt(*component_it, &value))
return false;
ip_mask_.push_back(true);
component_values_.push_back(value);
continue;
}
if ((*component_it)[component_it->size() - 1] != ']') {
DVLOG(1) << "Missing close bracket: " << ip_pattern;
return false;
}
// Now we know the size() is at least 2.
if (component_it->size() == 2) {
DVLOG(1) << "Empty bracket: " << ip_pattern;
return false;
}
// We'll need a pattern to match this bracketed component.
scoped_ptr<ComponentPattern> component_pattern(new ComponentPattern);
// Trim leading and trailing bracket before calling for parsing.
if (!ParseComponentPattern(base::StringPiece(component_it->data() + 1,
component_it->size() - 2), component_pattern.get())) {
return false;
}
ip_mask_.push_back(false);
component_patterns_.push_back(component_pattern.release());
}
return true;
}
bool IPPattern::ParseComponentPattern(const base::StringPiece& text,
ComponentPattern* pattern) const {
// We're given a comma separated set of ranges, some of which may be simple
// constants.
Strings ranges;
base::SplitString(text.as_string(), ',', &ranges);
for (Strings::iterator range_it = ranges.begin();
range_it != ranges.end(); ++range_it) {
base::StringTokenizer range_pair(*range_it, "-");
uint32 min = 0;
range_pair.GetNext();
if (!ValueTextToInt(range_pair.token(), &min))
return false;
uint32 max = min; // Sometimes we have no distinct max.
if (range_pair.GetNext()) {
if (!ValueTextToInt(range_pair.token(), &max))
return false;
}
if (range_pair.GetNext()) {
// Too many "-" in this range specifier.
DVLOG(1) << "Too many hyphens in range: ";
return false;
}
pattern->AppendRange(min, max);
}
return true;
}
bool IPPattern::ValueTextToInt(const base::StringPiece& input,
uint32* output) const {
bool ok = is_ipv4_ ? base::StringToUint(input, output) :
base::HexStringToUInt(input, output);
if (!ok) {
DVLOG(1) << "Could not convert value to number: " << input;
return false;
}
if (is_ipv4_ && *output > 255u) {
DVLOG(1) << "IPv4 component greater than 255";
return false;
}
if (!is_ipv4_ && *output > 0xFFFFu) {
DVLOG(1) << "IPv6 component greater than 0xFFFF";
return false;
}
return ok;
}
} // namespace net
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef NET_BASE_IP_PATTERN_H_
#define NET_BASE_IP_PATTERN_H_
#include <string>
#include <vector>
#include "base/basictypes.h"
#include "base/strings/string_piece.h"
#include "net/base/net_export.h"
#include "net/base/net_util.h"
namespace net {
// IPPatterns are used to match IP address resolutions for possible augmentation
// by a MappedIPResolver, which uses IPMappingRules.
class NET_EXPORT IPPattern {
public:
IPPattern();
~IPPattern();
// Parse a textual pattern (IP_PATTERN as defined in ip_mapping_rules.h) into
// |this| and return true if the parsing was successful.
bool ParsePattern(const std::string& ip_pattern);
// Test to see if the current pattern in |this| matches the given |address|
// and return true if it matches.
bool Match(const IPAddressNumber& address) const;
bool is_ipv4() const { return is_ipv4_; }
private:
class ComponentPattern;
typedef std::vector<std::string> Strings;
typedef std::vector<ComponentPattern*> ComponentPatternList;
// IPv6 addresses have 8 components, while IPv4 addresses have 4 components.
// ComponentPattern is used to define patterns to match individual components.
bool ParseComponentPattern(const base::StringPiece& text,
ComponentPattern* pattern) const;
// Convert IP component to an int. Assume hex vs decimal for IPV6 vs V4.
bool ValueTextToInt(const base::StringPiece& input, uint32* output) const;
bool is_ipv4_;
// The |ip_mask_| indicates, for each component, if this pattern requires an
// exact match (OCTET in IPv4, or 4 hex digits in IPv6).
// For each true element there is an entry in |component_values_|, and false
// means that an entry from our list of ComponentPattern instances must be
// applied.
std::vector<bool> ip_mask_;
// The vector of fixed values that are requried.
// Other values may be restricted by the component_patterns_;
// The class invariant is:
// ip_mask_.size() == component_patterns_.size()
// + size(our ComponentPattern list)
std::vector<uint32> component_values_;
// If only one component position was specified using a range, then this
// list will only have 1 element (i.e., we only have patterns for each element
// of ip_mask_ that is false.)
// We own these elements, and need to destroy them all when we are destroyed.
ComponentPatternList component_patterns_;
DISALLOW_COPY_AND_ASSIGN(IPPattern);
};
} // namespace net
#endif // NET_BASE_IP_PATTERN_H_
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "net/base/ip_pattern.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
namespace {
bool IsValidPattern(const std::string& pattern_text) {
IPPattern pattern;
return pattern.ParsePattern(pattern_text);
}
bool CheckForMatch(const IPPattern& pattern, std::string address_text) {
IPAddressNumber address;
EXPECT_TRUE(ParseIPLiteralToNumber(address_text, &address));
return pattern.Match(address);
}
TEST(IPPatternTest, EmptyPattern) {
IPPattern pattern;
IPAddressNumber ipv4_address1;
EXPECT_TRUE(ParseIPLiteralToNumber("1.2.3.4", &ipv4_address1));
IPAddressNumber ipv6_address1;
EXPECT_TRUE(ParseIPLiteralToNumber("1:2:3:4:5:6:7:8", &ipv6_address1));
EXPECT_FALSE(pattern.Match(ipv4_address1));
EXPECT_FALSE(pattern.Match(ipv6_address1));
}
TEST(IPPatternTest, PerfectMatchPattern) {
IPPattern pattern_v4;
std::string ipv4_text1("1.2.3.4");
EXPECT_TRUE(pattern_v4.ParsePattern(ipv4_text1));
EXPECT_TRUE(pattern_v4.is_ipv4());
EXPECT_TRUE(CheckForMatch(pattern_v4, ipv4_text1));
IPPattern pattern_v6;
std::string ipv6_text1("1:2:3:4:5:6:7:8");
EXPECT_TRUE(pattern_v6.ParsePattern(ipv6_text1));
EXPECT_FALSE(pattern_v6.is_ipv4());
EXPECT_TRUE(CheckForMatch(pattern_v6, ipv6_text1));
// Also check that there is no confusion betwene v6 and v4, despite having
// similar values in some sense.
EXPECT_FALSE(CheckForMatch(pattern_v4, ipv6_text1));
EXPECT_FALSE(CheckForMatch(pattern_v6, ipv4_text1));
}
TEST(IPPatternTest, AlternativeMatchPattern) {
IPPattern pattern_v4;
EXPECT_TRUE(pattern_v4.ParsePattern("1.2.[3,5].4"));
EXPECT_TRUE(pattern_v4.is_ipv4());
EXPECT_FALSE(CheckForMatch(pattern_v4, "1.2.2.4"));
EXPECT_TRUE(CheckForMatch(pattern_v4, "1.2.3.4"));
EXPECT_FALSE(CheckForMatch(pattern_v4, "1.2.4.4"));
EXPECT_TRUE(CheckForMatch(pattern_v4, "1.2.5.4"));
EXPECT_FALSE(CheckForMatch(pattern_v4, "1.2.6.4"));
IPPattern pattern_v6;
EXPECT_TRUE(pattern_v6.ParsePattern("1:2fab:3:4:5:[6,8]:7:8"));
EXPECT_FALSE(pattern_v6.is_ipv4());
EXPECT_FALSE(CheckForMatch(pattern_v6, "1:2fab:3:4:5:5:7:8"));
EXPECT_TRUE(CheckForMatch(pattern_v6, "1:2fab:3:4:5:6:7:8"));
EXPECT_FALSE(CheckForMatch(pattern_v6, "1:2fab:3:4:5:7:7:8"));
EXPECT_TRUE(CheckForMatch(pattern_v6, "1:2fab:3:4:5:8:7:8"));
EXPECT_FALSE(CheckForMatch(pattern_v6, "1:2fab:3:4:5:9:7:8"));
}
TEST(IPPatternTest, RangeMatchPattern) {
IPPattern pattern_v4;
EXPECT_TRUE(pattern_v4.ParsePattern("1.2.[3-5].4"));
EXPECT_TRUE(pattern_v4.is_ipv4());
EXPECT_FALSE(CheckForMatch(pattern_v4, "1.2.2.4"));
EXPECT_TRUE(CheckForMatch(pattern_v4, "1.2.3.4"));
EXPECT_TRUE(CheckForMatch(pattern_v4, "1.2.4.4"));
EXPECT_TRUE(CheckForMatch(pattern_v4, "1.2.5.4"));
EXPECT_FALSE(CheckForMatch(pattern_v4, "1.2.6.4"));
IPPattern pattern_v6;
EXPECT_TRUE(pattern_v6.ParsePattern("1:2fab:3:4:5:[6-8]:7:8"));
EXPECT_FALSE(pattern_v6.is_ipv4());
EXPECT_FALSE(CheckForMatch(pattern_v6, "1:2fab:3:4:5:5:7:8"));
EXPECT_TRUE(CheckForMatch(pattern_v6, "1:2fab:3:4:5:6:7:8"));
EXPECT_TRUE(CheckForMatch(pattern_v6, "1:2fab:3:4:5:7:7:8"));
EXPECT_TRUE(CheckForMatch(pattern_v6, "1:2fab:3:4:5:8:7:8"));
EXPECT_FALSE(CheckForMatch(pattern_v6, "1:2fab:3:4:5:9:7:8"));
}
TEST(IPPatternTest, WildCardMatchPattern) {
// Use two ranges, and check that only getting both right is a match.
IPPattern pattern_v4;
EXPECT_TRUE(pattern_v4.ParsePattern("1.2.*.4"));
EXPECT_TRUE(pattern_v4.is_ipv4());
EXPECT_FALSE(CheckForMatch(pattern_v4, "1.2.2.255"));
EXPECT_TRUE(CheckForMatch(pattern_v4, "1.2.255.4"));
EXPECT_TRUE(CheckForMatch(pattern_v4, "1.2.0.4"));
IPPattern pattern_v6;
EXPECT_TRUE(pattern_v6.ParsePattern("1:2fab:3:4:5:*:7:8"));
EXPECT_FALSE(pattern_v6.is_ipv4());
EXPECT_FALSE(CheckForMatch(pattern_v6, "1:2fab:3:4:5:5:7:8888"));
EXPECT_TRUE(CheckForMatch(pattern_v6, "1:2fab:3:4:5:FFFF:7:8"));
EXPECT_TRUE(CheckForMatch(pattern_v6, "1:2fab:3:4:5:9999:7:8"));
}
TEST(IPPatternTest, MultiRangeMatchPattern) {
// Use two ranges, and check that only getting both right is a match.
// This ensures that the right component range is matched against the desired
// component.
IPPattern pattern_v4;
EXPECT_TRUE(pattern_v4.ParsePattern("1.[2-3].3.[4-5]"));
EXPECT_TRUE(pattern_v4.is_ipv4());
EXPECT_FALSE(CheckForMatch(pattern_v4, "1.4.3.6"));
EXPECT_FALSE(CheckForMatch(pattern_v4, "1.2.3.6"));
EXPECT_FALSE(CheckForMatch(pattern_v4, "1.4.3.4"));
EXPECT_TRUE(CheckForMatch(pattern_v4, "1.2.3.4"));
IPPattern pattern_v6;
EXPECT_TRUE(pattern_v6.ParsePattern("1:2fab:3:4:[5-7]:6:7:[8-A]"));
EXPECT_FALSE(pattern_v6.is_ipv4());
EXPECT_FALSE(CheckForMatch(pattern_v6, "1:2fab:3:4:4:5:7:F"));
EXPECT_FALSE(CheckForMatch(pattern_v6, "1:2fab:3:4:5:5:7:F"));
EXPECT_FALSE(CheckForMatch(pattern_v6, "1:2fab:3:4:4:6:7:A"));
EXPECT_TRUE(CheckForMatch(pattern_v6, "1:2fab:3:4:5:6:7:A"));
}
TEST(IPPatternTest, BytoOrderInIPv6Ranges) {
IPPattern pattern_v6_low_byte;
EXPECT_TRUE(pattern_v6_low_byte.ParsePattern("1:2:3:4:5:6:7:[0-FF]"));
EXPECT_TRUE(CheckForMatch(pattern_v6_low_byte, "1:2:3:4:5:6:7:0088"));
EXPECT_FALSE(CheckForMatch(pattern_v6_low_byte, "1:2:3:4:5:6:7:8800"));
IPPattern pattern_v6_high_byte;
EXPECT_TRUE(pattern_v6_high_byte.ParsePattern("1:2:3:4:5:6:7:[0-FF00]"));
EXPECT_TRUE(CheckForMatch(pattern_v6_high_byte, "1:2:3:4:5:6:7:0088"));
EXPECT_TRUE(CheckForMatch(pattern_v6_high_byte, "1:2:3:4:5:6:7:FF00"));
EXPECT_FALSE(CheckForMatch(pattern_v6_high_byte, "1:2:3:4:5:6:7:FF01"));
}
TEST(IPPatternTest, InvalidPatterns) {
EXPECT_FALSE(IsValidPattern("1:2:3:4:5:6:7:8:9")); // Too long.
EXPECT_FALSE(IsValidPattern("1:2:3:4:5:6:7")); // Too Short
EXPECT_FALSE(IsValidPattern("1:2:3:4:5:6:7:H")); // Non-hex.
EXPECT_FALSE(IsValidPattern("1:G:3:4:5:6:7:8")); // Non-hex.
EXPECT_FALSE(IsValidPattern("1.2.3.4.5")); // Too long
EXPECT_FALSE(IsValidPattern("1.2.3")); // Too short
EXPECT_FALSE(IsValidPattern("1.2.3.A")); // Non-decimal.
EXPECT_FALSE(IsValidPattern("1.A.3.4")); // Non-decimal
EXPECT_FALSE(IsValidPattern("1.256.3.4")); // Out of range
}
} // namespace
} // namespace net
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "net/dns/mapped_ip_resolver.h"
#include "base/strings/string_util.h"
#include "net/base/net_errors.h"
#include "net/base/net_util.h"
namespace net {
MappedIPResolver::MappedIPResolver(scoped_ptr<HostResolver> impl)
: impl_(impl.Pass()),
weak_factory_(this) {
}
MappedIPResolver::~MappedIPResolver() {}
int MappedIPResolver::Resolve(const RequestInfo& info,
RequestPriority priority,
AddressList* addresses,
const CompletionCallback& callback,
RequestHandle* out_req,
const BoundNetLog& net_log) {
CompletionCallback new_callback = base::Bind(&MappedIPResolver::ApplyRules,
weak_factory_.GetWeakPtr(),
callback, addresses);
int rv = impl_->Resolve(info, priority, addresses, new_callback, out_req,
net_log);
if (rv == OK)
rules_.RewriteAddresses(addresses);
return rv;
}
int MappedIPResolver::ResolveFromCache(const RequestInfo& info,
AddressList* addresses,
const BoundNetLog& net_log) {
int rv = impl_->ResolveFromCache(info, addresses, net_log);
if (rv == OK)
rules_.RewriteAddresses(addresses);
return rv;
}
void MappedIPResolver::CancelRequest(RequestHandle req) {
impl_->CancelRequest(req);
}
void MappedIPResolver::SetDnsClientEnabled(bool enabled) {
impl_->SetDnsClientEnabled(enabled);
}
HostCache* MappedIPResolver::GetHostCache() {
return impl_->GetHostCache();
}
base::Value* MappedIPResolver::GetDnsConfigAsValue() const {
return impl_->GetDnsConfigAsValue();
}
void MappedIPResolver::ApplyRules(const CompletionCallback& original_callback,
AddressList* addresses,
int rv) const {
if (rv == OK)
rules_.RewriteAddresses(addresses);
original_callback.Run(rv);
}
} // namespace net
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef NET_DNS_MAPPED_IP_RESOLVER_H_
#define NET_DNS_MAPPED_IP_RESOLVER_H_
#include <string>
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "net/base/ip_mapping_rules.h"
#include "net/base/net_export.h"
#include "net/dns/host_resolver.h"
namespace net {
// This class wraps an existing HostResolver instance, but modifies the
// resolution response by inserting or replacing IP addresses before returning
// it. Currently, the only directive suported is a "PREFACE" directive which
// (when a match exists) inserts a single IP address at the start of a list.
class NET_EXPORT MappedIPResolver : public HostResolver {
public:
// Creates a MappedIPResolver that forwards all of its requests through
// |impl|.
explicit MappedIPResolver(scoped_ptr<HostResolver> impl);
virtual ~MappedIPResolver();
// Adds a rule to our IP mapper rules_.
// The most recently added rule "has priority" and will be used first (in
// preference to) any previous rules. Once one rule is found that matches,
// no other rules will be considered.
// See ip_mapping_rules.h for syntax and semantics.
// Returns true if the rule was successfully parsed and added.
bool AddRuleFromString(const std::string& rule_string) {
return rules_.AddRuleFromString(rule_string);
}
// Takes a semicolon separated list of rules, and assigns them to this
// resolver, discarding any previously added or set rules.
void SetRulesFromString(const std::string& rules_string) {
rules_.SetRulesFromString(rules_string);
}
// HostResolver methods:
virtual int Resolve(const RequestInfo& info,
RequestPriority priority,
AddressList* addresses,
const CompletionCallback& callback,
RequestHandle* out_req,
const BoundNetLog& net_log) OVERRIDE;
virtual int ResolveFromCache(const RequestInfo& info,
AddressList* addresses,
const BoundNetLog& net_log) OVERRIDE;
virtual void CancelRequest(RequestHandle req) OVERRIDE;
virtual void SetDnsClientEnabled(bool enabled) OVERRIDE;
virtual HostCache* GetHostCache() OVERRIDE;
virtual base::Value* GetDnsConfigAsValue() const OVERRIDE;
private:
// Modify the list of resolution |addresses| according to |rules_|, and then
// calls the |original_callback| with network error code |rv|.
void ApplyRules(const CompletionCallback& original_callback,
AddressList* addresses,
int rv) const;
scoped_ptr<HostResolver> impl_;
IPMappingRules rules_;
base::WeakPtrFactory<MappedIPResolver> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(MappedIPResolver);
};
} // namespace net
#endif // NET_DNS_MAPPED_IP_RESOLVER_H_
......@@ -138,6 +138,10 @@
'base/iovec.h',
'base/ip_endpoint.cc',
'base/ip_endpoint.h',
'base/ip_mapping_rules.cc',
'base/ip_mapping_rules.h',
'base/ip_pattern.cc',
'base/ip_pattern.h',
'base/keygen_handler.cc',
'base/keygen_handler.h',
'base/keygen_handler_mac.cc',
......@@ -499,6 +503,8 @@
'dns/host_resolver_proc.h',
'dns/mapped_host_resolver.cc',
'dns/mapped_host_resolver.h',
'dns/mapped_ip_resolver.cc',
'dns/mapped_ip_resolver.h',
'dns/mdns_cache.cc',
'dns/mdns_cache.h',
'dns/mdns_client.cc',
......@@ -1661,6 +1667,8 @@
'base/host_mapping_rules_unittest.cc',
'base/host_port_pair_unittest.cc',
'base/ip_endpoint_unittest.cc',
'base/ip_mapping_rules_unittest.cc',
'base/ip_pattern_unittest.cc',
'base/keygen_handler_unittest.cc',
'base/mime_sniffer_unittest.cc',
'base/mime_util_unittest.cc',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment