Index: net/base/dns_util.cc |
diff --git a/net/base/dns_util.cc b/net/base/dns_util.cc |
index d97d3d2c9eca4dedd07059df19b0e73bef217431..8051ca1ede10ea7dd1fc72dc55f81baca18c843d 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 |