diff options
-rw-r--r-- | net/base/dns_util.cc | 118 | ||||
-rw-r--r-- | net/base/dns_util.h | 32 | ||||
-rw-r--r-- | net/base/dnsrr_resolver.cc | 138 |
3 files changed, 150 insertions, 138 deletions
diff --git a/net/base/dns_util.cc b/net/base/dns_util.cc index d97d3d2..8051ca1 100644 --- a/net/base/dns_util.cc +++ b/net/base/dns_util.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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. @@ -96,4 +96,120 @@ std::string TrimEndingDot(const std::string& host) { return host_trimmed; } +bool DnsResponseBuffer::U8(uint8* v) { + if (len_ < 1) + return false; + *v = *p_; + p_++; + len_--; + return true; +} + +bool DnsResponseBuffer::U16(uint16* v) { + if (len_ < 2) + return false; + *v = static_cast<uint16>(p_[0]) << 8 | + static_cast<uint16>(p_[1]); + p_ += 2; + len_ -= 2; + return true; +} + +bool DnsResponseBuffer::U32(uint32* v) { + if (len_ < 4) + return false; + *v = static_cast<uint32>(p_[0]) << 24 | + static_cast<uint32>(p_[1]) << 16 | + static_cast<uint32>(p_[2]) << 8 | + static_cast<uint32>(p_[3]); + p_ += 4; + len_ -= 4; + return true; +} + +bool DnsResponseBuffer::Skip(unsigned n) { + if (len_ < n) + return false; + p_ += n; + len_ -= n; + return true; +} + +bool DnsResponseBuffer::Block(base::StringPiece* out, unsigned len) { + if (len_ < len) + return false; + *out = base::StringPiece(reinterpret_cast<const char*>(p_), len); + p_ += len; + len_ -= len; + return true; +} + +// DNSName parses a (possibly compressed) DNS name from the packet. If |name| +// is not NULL, then the name is written into it. See RFC 1035 section 4.1.4. +bool DnsResponseBuffer::DNSName(std::string* name) { + unsigned jumps = 0; + const uint8* p = p_; + unsigned len = len_; + + if (name) + name->clear(); + + for (;;) { + if (len < 1) + return false; + uint8 d = *p; + p++; + len--; + + // The two couple of bits of the length give the type of the length. It's + // either a direct length or a pointer to the remainder of the name. + if ((d & 0xc0) == 0xc0) { + // This limit matches the depth limit in djbdns. + if (jumps > 100) + return false; + if (len < 1) + return false; + uint16 offset = static_cast<uint16>(d) << 8 | + static_cast<uint16>(p[0]); + offset &= 0x3ff; + p++; + len--; + + if (jumps == 0) { + p_ = p; + len_ = len; + } + jumps++; + + if (offset >= packet_len_) + return false; + p = &packet_[offset]; + len = packet_len_ - offset; + } else if ((d & 0xc0) == 0) { + uint8 label_len = d; + if (len < label_len) + return false; + if (name && label_len) { + if (!name->empty()) + name->append("."); + name->append(reinterpret_cast<const char*>(p), label_len); + } + p += label_len; + len -= label_len; + + if (jumps == 0) { + p_ = p; + len_ = len; + } + + if (label_len == 0) + break; + } else { + return false; + } + } + + return true; +} + } // namespace net diff --git a/net/base/dns_util.h b/net/base/dns_util.h index bf4c330..781c104 100644 --- a/net/base/dns_util.h +++ b/net/base/dns_util.h @@ -9,6 +9,7 @@ #include <string> #include "base/basictypes.h" +#include "base/string_piece.h" #include "net/base/net_api.h" namespace net { @@ -54,6 +55,37 @@ static const uint8 kDNSSEC_RSA_SHA256 = 8; static const uint8 kDNSSEC_SHA1 = 1; static const uint8 kDNSSEC_SHA256 = 2; +// A Buffer is used for walking over a DNS response packet. +class DnsResponseBuffer { + public: + DnsResponseBuffer(const uint8* p, unsigned len) + : p_(p), + packet_(p), + len_(len), + packet_len_(len) { + } + + bool U8(uint8* v); + bool U16(uint16* v); + bool U32(uint32* v); + bool Skip(unsigned n); + + bool Block(base::StringPiece* out, unsigned len); + + // DNSName parses a (possibly compressed) DNS name from the packet. If |name| + // is not NULL, then the name is written into it. See RFC 1035 section 4.1.4. + bool DNSName(std::string* name); + + private: + const uint8* p_; + const uint8* const packet_; + unsigned len_; + const unsigned packet_len_; + + DISALLOW_COPY_AND_ASSIGN(DnsResponseBuffer); +}; + + } // namespace net #endif // NET_BASE_DNS_UTIL_H_ diff --git a/net/base/dnsrr_resolver.cc b/net/base/dnsrr_resolver.cc index b07df69..454a9fe 100644 --- a/net/base/dnsrr_resolver.cc +++ b/net/base/dnsrr_resolver.cc @@ -400,142 +400,6 @@ class RRResolverWorker { DISALLOW_COPY_AND_ASSIGN(RRResolverWorker); }; - -// A Buffer is used for walking over a DNS packet. -class Buffer { - public: - Buffer(const uint8* p, unsigned len) - : p_(p), - packet_(p), - len_(len), - packet_len_(len) { - } - - bool U8(uint8* v) { - if (len_ < 1) - return false; - *v = *p_; - p_++; - len_--; - return true; - } - - bool U16(uint16* v) { - if (len_ < 2) - return false; - *v = static_cast<uint16>(p_[0]) << 8 | - static_cast<uint16>(p_[1]); - p_ += 2; - len_ -= 2; - return true; - } - - bool U32(uint32* v) { - if (len_ < 4) - return false; - *v = static_cast<uint32>(p_[0]) << 24 | - static_cast<uint32>(p_[1]) << 16 | - static_cast<uint32>(p_[2]) << 8 | - static_cast<uint32>(p_[3]); - p_ += 4; - len_ -= 4; - return true; - } - - bool Skip(unsigned n) { - if (len_ < n) - return false; - p_ += n; - len_ -= n; - return true; - } - - bool Block(base::StringPiece* out, unsigned len) { - if (len_ < len) - return false; - *out = base::StringPiece(reinterpret_cast<const char*>(p_), len); - p_ += len; - len_ -= len; - return true; - } - - // DNSName parses a (possibly compressed) DNS name from the packet. If |name| - // is not NULL, then the name is written into it. See RFC 1035 section 4.1.4. - bool DNSName(std::string* name) { - unsigned jumps = 0; - const uint8* p = p_; - unsigned len = len_; - - if (name) - name->clear(); - - for (;;) { - if (len < 1) - return false; - uint8 d = *p; - p++; - len--; - - // The two couple of bits of the length give the type of the length. It's - // either a direct length or a pointer to the remainder of the name. - if ((d & 0xc0) == 0xc0) { - // This limit matches the depth limit in djbdns. - if (jumps > 100) - return false; - if (len < 1) - return false; - uint16 offset = static_cast<uint16>(d) << 8 | - static_cast<uint16>(p[0]); - offset &= 0x3ff; - p++; - len--; - - if (jumps == 0) { - p_ = p; - len_ = len; - } - jumps++; - - if (offset >= packet_len_) - return false; - p = &packet_[offset]; - len = packet_len_ - offset; - } else if ((d & 0xc0) == 0) { - uint8 label_len = d; - if (len < label_len) - return false; - if (name && label_len) { - if (!name->empty()) - name->append("."); - name->append(reinterpret_cast<const char*>(p), label_len); - } - p += label_len; - len -= label_len; - - if (jumps == 0) { - p_ = p; - len_ = len; - } - - if (label_len == 0) - break; - } else { - return false; - } - } - - return true; - } - - private: - const uint8* p_; - const uint8* const packet_; - unsigned len_; - const unsigned packet_len_; - - DISALLOW_COPY_AND_ASSIGN(Buffer); -}; - bool RRResponse::HasExpired(const base::Time current_time) const { const base::TimeDelta delta(base::TimeDelta::FromSeconds(ttl)); const base::Time expiry = fetch_time + delta; @@ -554,7 +418,7 @@ bool RRResponse::ParseFromResponse(const uint8* p, unsigned len, // RFC 1035 section 4.4.1 uint8 flags2; - Buffer buf(p, len); + DnsResponseBuffer buf(p, len); if (!buf.Skip(2) || // skip id !buf.Skip(1) || // skip first flags byte !buf.U8(&flags2)) { |