arc: Move platform2/arc/network/ to platform2/patchpanel

Next step in the arc-networkd -> patchpanel rename, this patch moves the
location of the code.

BUG=b:151879931
TEST=units,flashed image to atlas
TEST=tasts arc.PlayStore, crostini.LaunchTerminal.download

Change-Id: I1b5cf8d670e1631d46f6449b725395157bf88dde
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/2115863
Tested-by: Garrick Evans <garrick@chromium.org>
Commit-Queue: Garrick Evans <garrick@chromium.org>
Reviewed-by: Hidehiko Abe <hidehiko@chromium.org>
Reviewed-by: Eric Caruso <ejcaruso@chromium.org>
Reviewed-by: Chirantan Ekbote <chirantan@chromium.org>
Reviewed-by: Hugo Benichi <hugobenichi@google.com>
diff --git a/patchpanel/dns/big_endian.cc b/patchpanel/dns/big_endian.cc
new file mode 100644
index 0000000..88cb363
--- /dev/null
+++ b/patchpanel/dns/big_endian.cc
@@ -0,0 +1,105 @@
+// Copyright 2014 The Chromium OS 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 "patchpanel/dns/big_endian.h"
+
+#include "base/strings/string_piece.h"
+
+namespace base {
+
+BigEndianReader::BigEndianReader(const char* buf, size_t len)
+    : ptr_(buf), end_(ptr_ + len) {}
+
+bool BigEndianReader::Skip(size_t len) {
+  if (ptr_ + len > end_)
+    return false;
+  ptr_ += len;
+  return true;
+}
+
+bool BigEndianReader::ReadBytes(void* out, size_t len) {
+  if (ptr_ + len > end_)
+    return false;
+  memcpy(out, ptr_, len);
+  ptr_ += len;
+  return true;
+}
+
+bool BigEndianReader::ReadPiece(base::StringPiece* out, size_t len) {
+  if (ptr_ + len > end_)
+    return false;
+  *out = base::StringPiece(ptr_, len);
+  ptr_ += len;
+  return true;
+}
+
+template <typename T>
+bool BigEndianReader::Read(T* value) {
+  if (ptr_ + sizeof(T) > end_)
+    return false;
+  ReadBigEndian<T>(ptr_, value);
+  ptr_ += sizeof(T);
+  return true;
+}
+
+bool BigEndianReader::ReadU8(uint8_t* value) {
+  return Read(value);
+}
+
+bool BigEndianReader::ReadU16(uint16_t* value) {
+  return Read(value);
+}
+
+bool BigEndianReader::ReadU32(uint32_t* value) {
+  return Read(value);
+}
+
+bool BigEndianReader::ReadU64(uint64_t* value) {
+  return Read(value);
+}
+
+BigEndianWriter::BigEndianWriter(char* buf, size_t len)
+    : ptr_(buf), end_(ptr_ + len) {}
+
+bool BigEndianWriter::Skip(size_t len) {
+  if (ptr_ + len > end_)
+    return false;
+  ptr_ += len;
+  return true;
+}
+
+bool BigEndianWriter::WriteBytes(const void* buf, size_t len) {
+  if (ptr_ + len > end_)
+    return false;
+  memcpy(ptr_, buf, len);
+  ptr_ += len;
+  return true;
+}
+
+template <typename T>
+bool BigEndianWriter::Write(T value) {
+  if (ptr_ + sizeof(T) > end_)
+    return false;
+  WriteBigEndian<T>(ptr_, value);
+  ptr_ += sizeof(T);
+  return true;
+}
+
+bool BigEndianWriter::WriteU8(uint8_t value) {
+  return Write(value);
+}
+
+bool BigEndianWriter::WriteU16(uint16_t value) {
+  return Write(value);
+}
+
+bool BigEndianWriter::WriteU32(uint32_t value) {
+  return Write(value);
+}
+
+bool BigEndianWriter::WriteU64(uint64_t value) {
+  return Write(value);
+}
+
+}  // namespace base
diff --git a/patchpanel/dns/big_endian.h b/patchpanel/dns/big_endian.h
new file mode 100644
index 0000000..c9e4f70
--- /dev/null
+++ b/patchpanel/dns/big_endian.h
@@ -0,0 +1,106 @@
+// Copyright 2014 The Chromium OS 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 PATCHPANEL_DNS_BIG_ENDIAN_H_
+#define PATCHPANEL_DNS_BIG_ENDIAN_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "base/base_export.h"
+#include "base/strings/string_piece.h"
+
+namespace base {
+
+// Read an integer (signed or unsigned) from |buf| in Big Endian order.
+// Note: this loop is unrolled with -O1 and above.
+// NOTE(szym): glibc dns-canon.c use ntohs(*(uint16_t*)ptr) which is
+// potentially unaligned.
+// This would cause SIGBUS on ARMv5 or earlier and ARMv6-M.
+template <typename T>
+inline void ReadBigEndian(const char buf[], T* out) {
+  *out = buf[0];
+  for (size_t i = 1; i < sizeof(T); ++i) {
+    *out <<= 8;
+    // Must cast to uint8_t to avoid clobbering by sign extension.
+    *out |= static_cast<uint8_t>(buf[i]);
+  }
+}
+
+// Write an integer (signed or unsigned) |val| to |buf| in Big Endian order.
+// Note: this loop is unrolled with -O1 and above.
+template <typename T>
+inline void WriteBigEndian(char buf[], T val) {
+  for (size_t i = 0; i < sizeof(T); ++i) {
+    buf[sizeof(T) - i - 1] = static_cast<char>(val & 0xFF);
+    val >>= 8;
+  }
+}
+
+// Specializations to make clang happy about the (dead code) shifts above.
+template <>
+inline void ReadBigEndian<uint8_t>(const char buf[], uint8_t* out) {
+  *out = buf[0];
+}
+
+template <>
+inline void WriteBigEndian<uint8_t>(char buf[], uint8_t val) {
+  buf[0] = static_cast<char>(val);
+}
+
+// Allows reading integers in network order (big endian) while iterating over
+// an underlying buffer. All the reading functions advance the internal pointer.
+class BASE_EXPORT BigEndianReader {
+ public:
+  BigEndianReader(const char* buf, size_t len);
+
+  const char* ptr() const { return ptr_; }
+  int remaining() const { return end_ - ptr_; }
+
+  bool Skip(size_t len);
+  bool ReadBytes(void* out, size_t len);
+  // Creates a StringPiece in |out| that points to the underlying buffer.
+  bool ReadPiece(base::StringPiece* out, size_t len);
+  bool ReadU8(uint8_t* value);
+  bool ReadU16(uint16_t* value);
+  bool ReadU32(uint32_t* value);
+  bool ReadU64(uint64_t* value);
+
+ private:
+  // Hidden to promote type safety.
+  template <typename T>
+  bool Read(T* v);
+
+  const char* ptr_;
+  const char* end_;
+};
+
+// Allows writing integers in network order (big endian) while iterating over
+// an underlying buffer. All the writing functions advance the internal pointer.
+class BASE_EXPORT BigEndianWriter {
+ public:
+  BigEndianWriter(char* buf, size_t len);
+
+  char* ptr() const { return ptr_; }
+  int remaining() const { return end_ - ptr_; }
+
+  bool Skip(size_t len);
+  bool WriteBytes(const void* buf, size_t len);
+  bool WriteU8(uint8_t value);
+  bool WriteU16(uint16_t value);
+  bool WriteU32(uint32_t value);
+  bool WriteU64(uint64_t value);
+
+ private:
+  // Hidden to promote type safety.
+  template <typename T>
+  bool Write(T v);
+
+  char* ptr_;
+  char* end_;
+};
+
+}  // namespace base
+
+#endif  // PATCHPANEL_DNS_BIG_ENDIAN_H_
diff --git a/patchpanel/dns/dns_protocol.h b/patchpanel/dns/dns_protocol.h
new file mode 100644
index 0000000..b5e8ff0
--- /dev/null
+++ b/patchpanel/dns/dns_protocol.h
@@ -0,0 +1,149 @@
+// Copyright (c) 2012 The Chromium OS 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 PATCHPANEL_DNS_DNS_PROTOCOL_H_
+#define PATCHPANEL_DNS_DNS_PROTOCOL_H_
+
+#include <stdint.h>
+
+#include "patchpanel/dns/net_export.h"
+
+namespace net {
+
+namespace dns_protocol {
+
+static const uint16_t kDefaultPort = 53;
+static const uint16_t kDefaultPortMulticast = 5353;
+
+// DNS packet consists of a header followed by questions and/or answers.
+// For the meaning of specific fields, please see RFC 1035 and 2535
+
+// Header format.
+//                                  1  1  1  1  1  1
+//    0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
+//  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+//  |                      ID                       |
+//  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+//  |QR|   Opcode  |AA|TC|RD|RA| Z|AD|CD|   RCODE   |
+//  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+//  |                    QDCOUNT                    |
+//  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+//  |                    ANCOUNT                    |
+//  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+//  |                    NSCOUNT                    |
+//  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+//  |                    ARCOUNT                    |
+//  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+// Question format.
+//                                  1  1  1  1  1  1
+//    0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
+//  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+//  |                                               |
+//  /                     QNAME                     /
+//  /                                               /
+//  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+//  |                     QTYPE                     |
+//  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+//  |                     QCLASS                    |
+//  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+// Answer format.
+//                                  1  1  1  1  1  1
+//    0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
+//  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+//  |                                               |
+//  /                                               /
+//  /                      NAME                     /
+//  |                                               |
+//  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+//  |                      TYPE                     |
+//  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+//  |                     CLASS                     |
+//  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+//  |                      TTL                      |
+//  |                                               |
+//  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+//  |                   RDLENGTH                    |
+//  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
+//  /                     RDATA                     /
+//  /                                               /
+//  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+#pragma pack(push)
+#pragma pack(1)
+
+// On-the-wire header. All uint16_t are in network order.
+struct NET_EXPORT Header {
+  uint16_t id;
+  uint16_t flags;
+  uint16_t qdcount;
+  uint16_t ancount;
+  uint16_t nscount;
+  uint16_t arcount;
+};
+
+#pragma pack(pop)
+
+static const uint8_t kLabelMask = 0xc0;
+static const uint8_t kLabelPointer = 0xc0;
+static const uint8_t kLabelDirect = 0x0;
+static const uint16_t kOffsetMask = 0x3fff;
+
+// In MDns the most significant bit of the rrclass is designated as the
+// "cache-flush bit", as described in http://www.rfc-editor.org/rfc/rfc6762.txt
+// section 10.2.
+static const uint16_t kMDnsClassMask = 0x7FFF;
+
+// RFC 1035, section 3.1: To simplify implementations, the total length of
+// a domain name (i.e., label octets and label length octets) is restricted
+// to 255 octets or less.
+static const int kMaxNameLength = 255;
+
+// RFC 1035, section 4.2.1: Messages carried by UDP are restricted to 512
+// bytes (not counting the IP nor UDP headers).
+static const int kMaxUDPSize = 512;
+
+// RFC 6762, section 17: Messages over the local link are restricted by the
+// medium's MTU, and must be under 9000 bytes
+static const int kMaxMulticastSize = 9000;
+
+// DNS class types.
+//
+// https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-2
+static const uint16_t kClassIN = 1;
+
+// DNS resource record types.
+//
+// https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-4
+static const uint16_t kTypeA = 1;
+static const uint16_t kTypeCNAME = 5;
+static const uint16_t kTypePTR = 12;
+static const uint16_t kTypeTXT = 16;
+static const uint16_t kTypeAAAA = 28;
+static const uint16_t kTypeSRV = 33;
+static const uint16_t kTypeNSEC = 47;
+
+// DNS reply codes (RCODEs).
+//
+// https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-6
+static const uint8_t kRcodeNOERROR = 0;
+static const uint8_t kRcodeFORMERR = 1;
+static const uint8_t kRcodeSERVFAIL = 2;
+static const uint8_t kRcodeNXDOMAIN = 3;
+static const uint8_t kRcodeNOTIMP = 4;
+static const uint8_t kRcodeREFUSED = 5;
+
+// DNS header flags.
+//
+// https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-12
+static const uint16_t kFlagResponse = 0x8000;
+static const uint16_t kFlagRD = 0x100;  // Recursion Desired - query flag.
+static const uint16_t kFlagTC = 0x200;  // Truncated - server flag.
+
+}  // namespace dns_protocol
+
+}  // namespace net
+
+#endif  // PATCHPANEL_DNS_DNS_PROTOCOL_H_
diff --git a/patchpanel/dns/dns_response.cc b/patchpanel/dns/dns_response.cc
new file mode 100644
index 0000000..78e59f5
--- /dev/null
+++ b/patchpanel/dns/dns_response.cc
@@ -0,0 +1,233 @@
+// Copyright (c) 2012 The Chromium OS 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 "patchpanel/dns/dns_response.h"
+
+#include <limits>
+
+#include "base/strings/string_util.h"
+#include "base/sys_byteorder.h"
+
+#include "patchpanel/dns/big_endian.h"
+#include "patchpanel/dns/dns_protocol.h"
+#include "patchpanel/dns/io_buffer.h"
+
+namespace net {
+
+namespace {
+
+const size_t kHeaderSize = sizeof(dns_protocol::Header);
+
+const uint8_t kRcodeMask = 0xf;
+
+}  // namespace
+
+DnsResourceRecord::DnsResourceRecord() = default;
+
+DnsResourceRecord::~DnsResourceRecord() = default;
+
+DnsRecordParser::DnsRecordParser() : packet_(nullptr), length_(0), cur_(0) {}
+
+DnsRecordParser::DnsRecordParser(const void* packet,
+                                 size_t length,
+                                 size_t offset)
+    : packet_(reinterpret_cast<const char*>(packet)),
+      length_(length),
+      cur_(packet_ + offset) {
+  DCHECK_LE(offset, length);
+}
+
+unsigned DnsRecordParser::ReadName(const void* const vpos,
+                                   std::string* out) const {
+  const char* const pos = reinterpret_cast<const char*>(vpos);
+  DCHECK(packet_);
+  DCHECK_LE(packet_, pos);
+  DCHECK_LE(pos, packet_ + length_);
+
+  const char* p = pos;
+  const char* end = packet_ + length_;
+  // Count number of seen bytes to detect loops.
+  unsigned seen = 0;
+  // Remember how many bytes were consumed before first jump.
+  unsigned consumed = 0;
+
+  if (pos >= end)
+    return 0;
+
+  if (out) {
+    out->clear();
+    out->reserve(dns_protocol::kMaxNameLength);
+  }
+
+  for (;;) {
+    // The first two 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.
+    switch (*p & dns_protocol::kLabelMask) {
+      case dns_protocol::kLabelPointer: {
+        if (p + sizeof(uint16_t) > end)
+          return 0;
+        if (consumed == 0) {
+          consumed = p - pos + sizeof(uint16_t);
+          if (!out)
+            return consumed;  // If name is not stored, that's all we need.
+        }
+        seen += sizeof(uint16_t);
+        // If seen the whole packet, then we must be in a loop.
+        if (seen > length_)
+          return 0;
+        uint16_t offset;
+        base::ReadBigEndian<uint16_t>(p, &offset);
+        offset &= dns_protocol::kOffsetMask;
+        p = packet_ + offset;
+        if (p >= end)
+          return 0;
+        break;
+      }
+      case dns_protocol::kLabelDirect: {
+        uint8_t label_len = *p;
+        ++p;
+        // Note: root domain (".") is NOT included.
+        if (label_len == 0) {
+          if (consumed == 0) {
+            consumed = p - pos;
+          }  // else we set |consumed| before first jump
+          return consumed;
+        }
+        if (p + label_len >= end)
+          return 0;  // Truncated or missing label.
+        if (out) {
+          if (!out->empty())
+            out->append(".");
+          out->append(p, label_len);
+        }
+        p += label_len;
+        seen += 1 + label_len;
+        break;
+      }
+      default:
+        // unhandled label type
+        return 0;
+    }
+  }
+}
+
+bool DnsRecordParser::ReadRecord(DnsResourceRecord* out) {
+  DCHECK(packet_);
+  size_t consumed = ReadName(cur_, &out->name);
+  if (!consumed)
+    return false;
+  base::BigEndianReader reader(cur_ + consumed,
+                               packet_ + length_ - (cur_ + consumed));
+  uint16_t rdlen;
+  if (reader.ReadU16(&out->type) && reader.ReadU16(&out->klass) &&
+      reader.ReadU32(&out->ttl) && reader.ReadU16(&rdlen) &&
+      reader.ReadPiece(&out->rdata, rdlen)) {
+    cur_ = reader.ptr();
+    return true;
+  }
+  return false;
+}
+
+bool DnsRecordParser::SkipQuestion() {
+  size_t consumed = ReadName(cur_, nullptr);
+  if (!consumed)
+    return false;
+
+  const char* next = cur_ + consumed + 2 * sizeof(uint16_t);  // QTYPE + QCLASS
+  if (next > packet_ + length_)
+    return false;
+
+  cur_ = next;
+
+  return true;
+}
+
+DnsResponse::DnsResponse()
+    : io_buffer_(new IOBufferWithSize(dns_protocol::kMaxUDPSize + 1)) {}
+
+DnsResponse::DnsResponse(size_t length)
+    : io_buffer_(new IOBufferWithSize(length)) {}
+
+DnsResponse::DnsResponse(const void* data, size_t length, size_t answer_offset)
+    : io_buffer_(new IOBufferWithSize(length)),
+      parser_(io_buffer_->data(), length, answer_offset) {
+  DCHECK(data);
+  memcpy(io_buffer_->data(), data, length);
+}
+
+DnsResponse::~DnsResponse() = default;
+
+bool DnsResponse::InitParseWithoutQuery(int nbytes) {
+  DCHECK_GE(nbytes, 0);
+
+  if (nbytes < static_cast<int>(kHeaderSize) || nbytes >= io_buffer_->size())
+    return false;
+
+  parser_ = DnsRecordParser(io_buffer_->data(), nbytes, kHeaderSize);
+
+  unsigned qdcount = base::NetToHost16(header()->qdcount);
+  for (unsigned i = 0; i < qdcount; ++i) {
+    if (!parser_.SkipQuestion()) {
+      parser_ = DnsRecordParser();  // Make parser invalid again.
+      return false;
+    }
+  }
+
+  return true;
+}
+
+bool DnsResponse::IsValid() const {
+  return parser_.IsValid();
+}
+
+uint16_t DnsResponse::flags() const {
+  DCHECK(parser_.IsValid());
+  return base::NetToHost16(header()->flags) & ~(kRcodeMask);
+}
+
+uint8_t DnsResponse::rcode() const {
+  DCHECK(parser_.IsValid());
+  return base::NetToHost16(header()->flags) & kRcodeMask;
+}
+
+unsigned DnsResponse::answer_count() const {
+  DCHECK(parser_.IsValid());
+  return base::NetToHost16(header()->ancount);
+}
+
+unsigned DnsResponse::additional_answer_count() const {
+  DCHECK(parser_.IsValid());
+  return base::NetToHost16(header()->arcount);
+}
+
+base::StringPiece DnsResponse::qname() const {
+  DCHECK(parser_.IsValid());
+  // The response is HEADER QNAME QTYPE QCLASS ANSWER.
+  // |parser_| is positioned at the beginning of ANSWER, so the end of QNAME is
+  // two uint16_ts before it.
+  const size_t qname_size =
+      parser_.GetOffset() - 2 * sizeof(uint16_t) - kHeaderSize;
+  return base::StringPiece(io_buffer_->data() + kHeaderSize, qname_size);
+}
+
+uint16_t DnsResponse::qtype() const {
+  DCHECK(parser_.IsValid());
+  // QTYPE starts where QNAME ends.
+  const size_t type_offset = parser_.GetOffset() - 2 * sizeof(uint16_t);
+  uint16_t type;
+  base::ReadBigEndian<uint16_t>(io_buffer_->data() + type_offset, &type);
+  return type;
+}
+
+DnsRecordParser DnsResponse::Parser() const {
+  DCHECK(parser_.IsValid());
+  // Return a copy of the parser.
+  return parser_;
+}
+
+const dns_protocol::Header* DnsResponse::header() const {
+  return reinterpret_cast<const dns_protocol::Header*>(io_buffer_->data());
+}
+
+}  // namespace net
diff --git a/patchpanel/dns/dns_response.h b/patchpanel/dns/dns_response.h
new file mode 100644
index 0000000..193fb01
--- /dev/null
+++ b/patchpanel/dns/dns_response.h
@@ -0,0 +1,163 @@
+// Copyright (c) 2012 The Chromium OS 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 PATCHPANEL_DNS_DNS_RESPONSE_H_
+#define PATCHPANEL_DNS_DNS_RESPONSE_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <string>
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/strings/string_piece.h"
+#include "base/time/time.h"
+
+#include "patchpanel/dns/io_buffer.h"
+#include "patchpanel/dns/net_export.h"
+
+namespace net {
+
+class AddressList;
+class DnsQuery;
+class IOBufferWithSize;
+
+namespace dns_protocol {
+struct Header;
+}
+
+// Structure representing a Resource Record as specified in RFC 1035, Section
+// 4.1.3.
+struct NET_EXPORT_PRIVATE DnsResourceRecord {
+  DnsResourceRecord();
+  ~DnsResourceRecord();
+
+  std::string name;  // in dotted form
+  uint16_t type;
+  uint16_t klass;
+  uint32_t ttl;
+  base::StringPiece rdata;  // points to the original response buffer
+};
+
+// Iterator to walk over resource records of the DNS response packet.
+class NET_EXPORT_PRIVATE DnsRecordParser {
+ public:
+  // Construct an uninitialized iterator.
+  DnsRecordParser();
+
+  // Construct an iterator to process the |packet| of given |length|.
+  // |offset| points to the beginning of the answer section.
+  DnsRecordParser(const void* packet, size_t length, size_t offset);
+
+  // Returns |true| if initialized.
+  bool IsValid() const { return packet_ != nullptr; }
+
+  // Returns |true| if no more bytes remain in the packet.
+  bool AtEnd() const { return cur_ == packet_ + length_; }
+
+  // Returns current offset into the packet.
+  size_t GetOffset() const { return cur_ - packet_; }
+
+  // Parses a (possibly compressed) DNS name from the packet starting at
+  // |pos|. Stores output (even partial) in |out| unless |out| is NULL. |out|
+  // is stored in the dotted form, e.g., "example.com". Returns number of bytes
+  // consumed or 0 on failure.
+  // This is exposed to allow parsing compressed names within RRDATA for TYPEs
+  // such as NS, CNAME, PTR, MX, SOA.
+  // See RFC 1035 section 4.1.4.
+  unsigned ReadName(const void* pos, std::string* out) const;
+
+  // Parses the next resource record into |record|. Returns true if succeeded.
+  bool ReadRecord(DnsResourceRecord* record);
+
+  // Skip a question section, returns true if succeeded.
+  bool SkipQuestion();
+
+ private:
+  const char* packet_;
+  size_t length_;
+  // Current offset within the packet.
+  const char* cur_;
+};
+
+// Buffer-holder for the DNS response allowing easy access to the header fields
+// and resource records. After reading into |io_buffer| must call InitParse to
+// position the RR parser.
+class NET_EXPORT_PRIVATE DnsResponse {
+ public:
+  // Possible results from ParseToAddressList.
+  enum Result {
+    DNS_PARSE_OK = 0,
+    DNS_MALFORMED_RESPONSE,    // DnsRecordParser failed before the end of
+                               // packet.
+    DNS_MALFORMED_CNAME,       // Could not parse CNAME out of RRDATA.
+    DNS_NAME_MISMATCH,         // Got an address but no ordered chain of CNAMEs
+                               // leads there.
+    DNS_SIZE_MISMATCH,         // Got an address but size does not match.
+    DNS_CNAME_AFTER_ADDRESS,   // Found CNAME after an address record.
+    DNS_ADDRESS_TTL_MISMATCH,  // OBSOLETE. No longer used.
+    DNS_NO_ADDRESSES,          // OBSOLETE. No longer used.
+    // Only add new values here.
+    DNS_PARSE_RESULT_MAX,  // Bounding value for histograms.
+  };
+
+  // Constructs a response buffer large enough to store one byte more than
+  // largest possible response, to detect malformed responses.
+  DnsResponse();
+
+  // Constructs a response buffer of given length. Used for TCP transactions.
+  explicit DnsResponse(size_t length);
+
+  // Constructs a response from |data|. Used for testing purposes only!
+  DnsResponse(const void* data, size_t length, size_t answer_offset);
+
+  ~DnsResponse();
+
+  // Internal buffer accessor into which actual bytes of response will be
+  // read.
+  IOBufferWithSize* io_buffer() { return io_buffer_.get(); }
+
+  // Assuming the internal buffer holds |nbytes| bytes, initialize the parser
+  // without matching it against an existing query.
+  bool InitParseWithoutQuery(int nbytes);
+
+  // Returns true if response is valid, that is, after successful InitParse.
+  bool IsValid() const;
+
+  // All of the methods below are valid only if the response is valid.
+
+  // Accessors for the header.
+  uint16_t flags() const;  // excluding rcode
+  uint8_t rcode() const;
+
+  unsigned answer_count() const;
+  unsigned additional_answer_count() const;
+
+  // Accessors to the question. The qname is unparsed.
+  base::StringPiece qname() const;
+  uint16_t qtype() const;
+
+  // Returns an iterator to the resource records in the answer section.
+  // The iterator is valid only in the scope of the DnsResponse.
+  // This operation is idempotent.
+  DnsRecordParser Parser() const;
+
+ private:
+  // Convenience for header access.
+  const dns_protocol::Header* header() const;
+
+  // Buffer into which response bytes are read.
+  scoped_refptr<IOBufferWithSize> io_buffer_;
+
+  // Iterator constructed after InitParse positioned at the answer section.
+  // It is never updated afterwards, so can be used in accessors.
+  DnsRecordParser parser_;
+
+  DISALLOW_COPY_AND_ASSIGN(DnsResponse);
+};
+
+}  // namespace net
+
+#endif  // PATCHPANEL_DNS_DNS_RESPONSE_H_
diff --git a/patchpanel/dns/io_buffer.cc b/patchpanel/dns/io_buffer.cc
new file mode 100644
index 0000000..a15ca72
--- /dev/null
+++ b/patchpanel/dns/io_buffer.cc
@@ -0,0 +1,171 @@
+// Copyright (c) 2011 The Chromium OS 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 "patchpanel/dns/io_buffer.h"
+
+#include "base/logging.h"
+#include "base/numerics/safe_math.h"
+
+namespace net {
+
+namespace {
+
+// TODO(eroman): IOBuffer is being converted to require buffer sizes and offsets
+// be specified as "size_t" rather than "int" (crbug.com/488553). To facilitate
+// this move (since LOTS of code needs to be updated), both "size_t" and "int
+// are being accepted. When using "size_t" this function ensures that it can be
+// safely converted to an "int" without truncation.
+void AssertValidBufferSize(size_t size) {
+  base::CheckedNumeric<int>(size).ValueOrDie();
+}
+
+void AssertValidBufferSize(int size) {
+  CHECK_GE(size, 0);
+}
+
+}  // namespace
+
+IOBuffer::IOBuffer() : data_(nullptr) {}
+
+IOBuffer::IOBuffer(int buffer_size) {
+  AssertValidBufferSize(buffer_size);
+  data_ = new char[buffer_size];
+}
+
+IOBuffer::IOBuffer(size_t buffer_size) {
+  AssertValidBufferSize(buffer_size);
+  data_ = new char[buffer_size];
+}
+
+IOBuffer::IOBuffer(char* data) : data_(data) {}
+
+IOBuffer::~IOBuffer() {
+  delete[] data_;
+  data_ = nullptr;
+}
+
+IOBufferWithSize::IOBufferWithSize(int size) : IOBuffer(size), size_(size) {
+  AssertValidBufferSize(size);
+}
+
+IOBufferWithSize::IOBufferWithSize(size_t size) : IOBuffer(size), size_(size) {
+  // Note: Size check is done in superclass' constructor.
+}
+
+IOBufferWithSize::IOBufferWithSize(char* data, int size)
+    : IOBuffer(data), size_(size) {
+  AssertValidBufferSize(size);
+}
+
+IOBufferWithSize::IOBufferWithSize(char* data, size_t size)
+    : IOBuffer(data), size_(size) {
+  AssertValidBufferSize(size);
+}
+
+IOBufferWithSize::~IOBufferWithSize() = default;
+
+StringIOBuffer::StringIOBuffer(const std::string& s)
+    : IOBuffer(nullptr), string_data_(s) {
+  AssertValidBufferSize(s.size());
+  data_ = const_cast<char*>(string_data_.data());
+}
+
+StringIOBuffer::StringIOBuffer(std::unique_ptr<std::string> s)
+    : IOBuffer(nullptr) {
+  AssertValidBufferSize(s->size());
+  string_data_.swap(*s.get());
+  data_ = const_cast<char*>(string_data_.data());
+}
+
+StringIOBuffer::~StringIOBuffer() {
+  // We haven't allocated the buffer, so remove it before the base class
+  // destructor tries to delete[] it.
+  data_ = nullptr;
+}
+
+DrainableIOBuffer::DrainableIOBuffer(IOBuffer* base, int size)
+    : IOBuffer(base->data()), base_(base), size_(size), used_(0) {
+  AssertValidBufferSize(size);
+}
+
+DrainableIOBuffer::DrainableIOBuffer(IOBuffer* base, size_t size)
+    : IOBuffer(base->data()), base_(base), size_(size), used_(0) {
+  AssertValidBufferSize(size);
+}
+
+void DrainableIOBuffer::DidConsume(int bytes) {
+  SetOffset(used_ + bytes);
+}
+
+int DrainableIOBuffer::BytesRemaining() const {
+  return size_ - used_;
+}
+
+// Returns the number of consumed bytes.
+int DrainableIOBuffer::BytesConsumed() const {
+  return used_;
+}
+
+void DrainableIOBuffer::SetOffset(int bytes) {
+  DCHECK_GE(bytes, 0);
+  DCHECK_LE(bytes, size_);
+  used_ = bytes;
+  data_ = base_->data() + used_;
+}
+
+DrainableIOBuffer::~DrainableIOBuffer() {
+  // The buffer is owned by the |base_| instance.
+  data_ = nullptr;
+}
+
+GrowableIOBuffer::GrowableIOBuffer() : IOBuffer(), capacity_(0), offset_(0) {}
+
+void GrowableIOBuffer::SetCapacity(int capacity) {
+  DCHECK_GE(capacity, 0);
+  // realloc will crash if it fails.
+  real_data_.reset(static_cast<char*>(realloc(real_data_.release(), capacity)));
+  capacity_ = capacity;
+  if (offset_ > capacity)
+    set_offset(capacity);
+  else
+    set_offset(offset_);  // The pointer may have changed.
+}
+
+void GrowableIOBuffer::set_offset(int offset) {
+  DCHECK_GE(offset, 0);
+  DCHECK_LE(offset, capacity_);
+  offset_ = offset;
+  data_ = real_data_.get() + offset;
+}
+
+int GrowableIOBuffer::RemainingCapacity() {
+  return capacity_ - offset_;
+}
+
+char* GrowableIOBuffer::StartOfBuffer() {
+  return real_data_.get();
+}
+
+GrowableIOBuffer::~GrowableIOBuffer() {
+  data_ = nullptr;
+}
+
+PickledIOBuffer::PickledIOBuffer() = default;
+
+void PickledIOBuffer::Done() {
+  data_ = const_cast<char*>(static_cast<const char*>(pickle_.data()));
+}
+
+PickledIOBuffer::~PickledIOBuffer() {
+  data_ = nullptr;
+}
+
+WrappedIOBuffer::WrappedIOBuffer(const char* data)
+    : IOBuffer(const_cast<char*>(data)) {}
+
+WrappedIOBuffer::~WrappedIOBuffer() {
+  data_ = nullptr;
+}
+
+}  // namespace net
diff --git a/patchpanel/dns/io_buffer.h b/patchpanel/dns/io_buffer.h
new file mode 100644
index 0000000..60cc840
--- /dev/null
+++ b/patchpanel/dns/io_buffer.h
@@ -0,0 +1,258 @@
+// Copyright (c) 2012 The Chromium OS 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 PATCHPANEL_DNS_IO_BUFFER_H_
+#define PATCHPANEL_DNS_IO_BUFFER_H_
+
+#include <stddef.h>
+
+#include <memory>
+#include <string>
+
+#include "patchpanel/dns/net_export.h"
+#include "base/memory/free_deleter.h"
+#include "base/memory/ref_counted.h"
+#include "base/pickle.h"
+
+namespace net {
+
+// IOBuffers are reference counted data buffers used for easier asynchronous
+// IO handling.
+//
+// They are often used as the destination buffers for Read() operations, or as
+// the source buffers for Write() operations.
+//
+// IMPORTANT: Never re-use an IOBuffer after cancelling the IO operation that
+//            was using it, since this may lead to memory corruption!
+//
+// -----------------------
+// Ownership of IOBuffers:
+// -----------------------
+//
+// Although IOBuffers are RefCountedThreadSafe, they are not intended to be
+// used as a shared buffer, nor should they be used simultaneously across
+// threads. The fact that they are reference counted is an implementation
+// detail for allowing them to outlive cancellation of asynchronous
+// operations.
+//
+// Instead, think of the underlying |char*| buffer contained by the IOBuffer
+// as having exactly one owner at a time.
+//
+// Whenever you call an asynchronous operation that takes an IOBuffer,
+// ownership is implicitly transferred to the called function, until the
+// operation has completed (at which point it transfers back to the caller).
+//
+//     ==> The IOBuffer's data should NOT be manipulated, destroyed, or read
+//         until the operation has completed.
+//
+//     ==> Cancellation does NOT count as completion. If an operation using
+//         an IOBuffer is cancelled, the caller should release their
+//         reference to this IOBuffer at the time of cancellation since
+//         they can no longer use it.
+//
+// For instance, if you were to call a Read() operation on some class which
+// takes an IOBuffer, and then delete that class (which generally will
+// trigger cancellation), the IOBuffer which had been passed to Read() should
+// never be re-used.
+//
+// This usage contract is assumed by any API which takes an IOBuffer, even
+// though it may not be explicitly mentioned in the function's comments.
+//
+// -----------------------
+// Motivation
+// -----------------------
+//
+// The motivation for transferring ownership during cancellation is
+// to make it easier to work with un-cancellable operations.
+//
+// For instance, let's say under the hood your API called out to the
+// operating system's synchronous ReadFile() function on a worker thread.
+// When cancelling through our asynchronous interface, we have no way of
+// actually aborting the in progress ReadFile(). We must let it keep running,
+// and hence the buffer it was reading into must remain alive. Using
+// reference counting we can add a reference to the IOBuffer and make sure
+// it is not destroyed until after the synchronous operation has completed.
+class NET_EXPORT IOBuffer : public base::RefCountedThreadSafe<IOBuffer> {
+ public:
+  IOBuffer();
+
+  // TODO(eroman): Deprecated. Use the size_t flavor instead. crbug.com/488553
+  explicit IOBuffer(int buffer_size);
+  explicit IOBuffer(size_t buffer_size);
+
+  char* data() const { return data_; }
+
+ protected:
+  friend class base::RefCountedThreadSafe<IOBuffer>;
+
+  // Only allow derived classes to specify data_.
+  // In all other cases, we own data_, and must delete it at destruction time.
+  explicit IOBuffer(char* data);
+
+  virtual ~IOBuffer();
+
+  char* data_;
+};
+
+// This version stores the size of the buffer so that the creator of the object
+// doesn't have to keep track of that value.
+// NOTE: This doesn't mean that we want to stop sending the size as an explicit
+// argument to IO functions. Please keep using IOBuffer* for API declarations.
+class NET_EXPORT IOBufferWithSize : public IOBuffer {
+ public:
+  // TODO(eroman): Deprecated. Use the size_t flavor instead. crbug.com/488553
+  explicit IOBufferWithSize(int size);
+  explicit IOBufferWithSize(size_t size);
+
+  int size() const { return size_; }
+
+ protected:
+  // TODO(eroman): Deprecated. Use the size_t flavor instead. crbug.com/488553
+  IOBufferWithSize(char* data, int size);
+
+  // Purpose of this constructor is to give a subclass access to the base class
+  // constructor IOBuffer(char*) thus allowing subclass to use underlying
+  // memory it does not own.
+  IOBufferWithSize(char* data, size_t size);
+  ~IOBufferWithSize() override;
+
+  int size_;
+};
+
+// This is a read only IOBuffer.  The data is stored in a string and
+// the IOBuffer interface does not provide a proper way to modify it.
+class NET_EXPORT StringIOBuffer : public IOBuffer {
+ public:
+  explicit StringIOBuffer(const std::string& s);
+  explicit StringIOBuffer(std::unique_ptr<std::string> s);
+
+  int size() const { return static_cast<int>(string_data_.size()); }
+
+ private:
+  ~StringIOBuffer() override;
+
+  std::string string_data_;
+};
+
+// This version wraps an existing IOBuffer and provides convenient functions
+// to progressively read all the data.
+//
+// DrainableIOBuffer is useful when you have an IOBuffer that contains data
+// to be written progressively, and Write() function takes an IOBuffer rather
+// than char*. DrainableIOBuffer can be used as follows:
+//
+// // payload is the IOBuffer containing the data to be written.
+// buf = new DrainableIOBuffer(payload, payload_size);
+//
+// while (buf->BytesRemaining() > 0) {
+//   // Write() takes an IOBuffer. If it takes char*, we could
+//   // simply use the regular IOBuffer like payload->data() + offset.
+//   int bytes_written = Write(buf, buf->BytesRemaining());
+//   buf->DidConsume(bytes_written);
+// }
+//
+class NET_EXPORT DrainableIOBuffer : public IOBuffer {
+ public:
+  // TODO(eroman): Deprecated. Use the size_t flavor instead. crbug.com/488553
+  DrainableIOBuffer(IOBuffer* base, int size);
+  DrainableIOBuffer(IOBuffer* base, size_t size);
+
+  // DidConsume() changes the |data_| pointer so that |data_| always points
+  // to the first unconsumed byte.
+  void DidConsume(int bytes);
+
+  // Returns the number of unconsumed bytes.
+  int BytesRemaining() const;
+
+  // Returns the number of consumed bytes.
+  int BytesConsumed() const;
+
+  // Seeks to an arbitrary point in the buffer. The notion of bytes consumed
+  // and remaining are updated appropriately.
+  void SetOffset(int bytes);
+
+  int size() const { return size_; }
+
+ private:
+  ~DrainableIOBuffer() override;
+
+  scoped_refptr<IOBuffer> base_;
+  int size_;
+  int used_;
+};
+
+// This version provides a resizable buffer and a changeable offset.
+//
+// GrowableIOBuffer is useful when you read data progressively without
+// knowing the total size in advance. GrowableIOBuffer can be used as
+// follows:
+//
+// buf = new GrowableIOBuffer;
+// buf->SetCapacity(1024);  // Initial capacity.
+//
+// while (!some_stream->IsEOF()) {
+//   // Double the capacity if the remaining capacity is empty.
+//   if (buf->RemainingCapacity() == 0)
+//     buf->SetCapacity(buf->capacity() * 2);
+//   int bytes_read = some_stream->Read(buf, buf->RemainingCapacity());
+//   buf->set_offset(buf->offset() + bytes_read);
+// }
+//
+class NET_EXPORT GrowableIOBuffer : public IOBuffer {
+ public:
+  GrowableIOBuffer();
+
+  // realloc memory to the specified capacity.
+  void SetCapacity(int capacity);
+  int capacity() { return capacity_; }
+
+  // |offset| moves the |data_| pointer, allowing "seeking" in the data.
+  void set_offset(int offset);
+  int offset() { return offset_; }
+
+  int RemainingCapacity();
+  char* StartOfBuffer();
+
+ private:
+  ~GrowableIOBuffer() override;
+
+  std::unique_ptr<char, base::FreeDeleter> real_data_;
+  int capacity_;
+  int offset_;
+};
+
+// This versions allows a pickle to be used as the storage for a write-style
+// operation, avoiding an extra data copy.
+class NET_EXPORT PickledIOBuffer : public IOBuffer {
+ public:
+  PickledIOBuffer();
+
+  base::Pickle* pickle() { return &pickle_; }
+
+  // Signals that we are done writing to the pickle and we can use it for a
+  // write-style IO operation.
+  void Done();
+
+ private:
+  ~PickledIOBuffer() override;
+
+  base::Pickle pickle_;
+};
+
+// This class allows the creation of a temporary IOBuffer that doesn't really
+// own the underlying buffer. Please use this class only as a last resort.
+// A good example is the buffer for a synchronous operation, where we can be
+// sure that nobody is keeping an extra reference to this object so the lifetime
+// of the buffer can be completely managed by its intended owner.
+class NET_EXPORT WrappedIOBuffer : public IOBuffer {
+ public:
+  explicit WrappedIOBuffer(const char* data);
+
+ protected:
+  ~WrappedIOBuffer() override;
+};
+
+}  // namespace net
+
+#endif  // PATCHPANEL_DNS_IO_BUFFER_H_
diff --git a/patchpanel/dns/net_export.h b/patchpanel/dns/net_export.h
new file mode 100644
index 0000000..03054af
--- /dev/null
+++ b/patchpanel/dns/net_export.h
@@ -0,0 +1,38 @@
+// Copyright (c) 2011 The Chromium OS 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 PATCHPANEL_DNS_NET_EXPORT_H_
+#define PATCHPANEL_DNS_NET_EXPORT_H_
+
+// Defines NET_EXPORT so that functionality implemented by the net module can
+// be exported to consumers, and NET_EXPORT_PRIVATE that allows unit tests to
+// access features not intended to be used directly by real consumers.
+
+#if defined(COMPONENT_BUILD)
+#if defined(WIN32)
+
+#if defined(NET_IMPLEMENTATION)
+#define NET_EXPORT __declspec(dllexport)
+#define NET_EXPORT_PRIVATE __declspec(dllexport)
+#else
+#define NET_EXPORT __declspec(dllimport)
+#define NET_EXPORT_PRIVATE __declspec(dllimport)
+#endif  // defined(NET_IMPLEMENTATION)
+
+#else  // defined(WIN32)
+#if defined(NET_IMPLEMENTATION)
+#define NET_EXPORT __attribute__((visibility("default")))
+#define NET_EXPORT_PRIVATE __attribute__((visibility("default")))
+#else
+#define NET_EXPORT
+#define NET_EXPORT_PRIVATE
+#endif
+#endif
+
+#else  /// defined(COMPONENT_BUILD)
+#define NET_EXPORT
+#define NET_EXPORT_PRIVATE
+#endif
+
+#endif  // PATCHPANEL_DNS_NET_EXPORT_H_