Index: net/base/dns_query.cc |
diff --git a/net/base/dns_query.cc b/net/base/dns_query.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..4b2d4c83d041683576e0f169ae05c751470102b0 |
--- /dev/null |
+++ b/net/base/dns_query.cc |
@@ -0,0 +1,124 @@ |
+// 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. |
+ |
+#include "net/base/dns_query.h" |
+ |
+#include <string> |
+ |
+#include "base/rand_util.h" |
+#include "net/base/address_family.h" |
+#include "net/base/dns_util.h" |
+ |
+#include <iostream> |
+ |
+namespace net { |
+ |
+namespace { |
+ |
+void PackUint16BE(char buf[2], uint16 v) { |
+ buf[1] = v & 0xff; |
+ buf[0] = v >> 8; |
+} |
+ |
+} |
+ |
+// DNS query consists of a 12-byte header followed by a question section, |
+// for details, see RFC 1035 section 4.1.1. This header template sets RD |
+// bit, which directs the name server to pursue query recursively, and sets |
+// the QDCOUNT to 1, meaning the question section has a single entry. The |
+// first two bytes of the header form a 16-bit query ID to be copied in the |
+// corresponding reply by the name server; it's set to 0 here and is |
+// randomized every time the underlying buffer is fetched. |
+static const char kHeader[] = {0x00, 0x00, 0x01, 0x00, 0x00, 0x01, |
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; |
+static const int kHeaderLen = arraysize(kHeader); |
+ |
+DnsQuery::DnsQuery(const std::string& hostname, |
+ AddressFamily address_family, |
+ int port) |
+ : port_(port), |
+ id_(0), |
+ qtype_(kDNS_A), |
cbentzel
2011/05/26 17:32:40
I'd add a function such as QtypeFromAddressFamily(
agayev
2011/05/26 22:55:55
Done.
|
+ qclass_(kClassIN) { |
+ if (address_family == ADDRESS_FAMILY_IPV6) |
+ qtype_ = kDNS_AAAA; |
+ else if (address_family != ADDRESS_FAMILY_IPV4) |
+ NOTREACHED(); |
+ |
+ if (!net::DNSDomainFromDot(hostname, &qname_)) |
+ return; |
+ |
+ size_t query_size = kHeaderLen + qname_.size() + |
+ sizeof(qtype_) + sizeof(qclass_); |
+ std::vector<char> query(query_size); |
cbentzel
2011/05/26 17:32:40
Why don't you do this directly into the IOBuffer?
agayev
2011/05/26 22:55:55
Done.
|
+ |
+ size_t iterator = 0; |
+ memcpy(&query[iterator], kHeader, kHeaderLen); |
+ iterator += kHeaderLen; |
+ memcpy(&query[iterator], &qname_[0], qname_.size()); |
+ iterator += qname_.size(); |
+ PackUint16BE(&query[iterator], qtype_); |
+ iterator += sizeof(qtype_); |
+ PackUint16BE(&query[iterator], qclass_); |
+ |
+ io_buffer_ = new IOBufferWithSize(query.size()); |
+ memcpy(io_buffer_->data(), &query[0], query.size()); |
+ |
+ RandomizeId(); |
+ // RFC2181 section 11: A full domain name is limited to 255 octets |
+ // (including the separators). |
+ static const int kMaxQuerySize = kHeaderLen + 255 + |
+ sizeof(qtype_) + sizeof(qclass_); |
+ DCHECK(io_buffer_->size() > kHeaderLen && |
+ io_buffer_->size() <= kMaxQuerySize); |
+} |
+ |
+void DnsQuery::RandomizeId() { |
+ DCHECK(IsValid()); |
+ id_ = base::RandUint64() & 0xffff; |
cbentzel
2011/05/26 17:32:40
Is this random enough? I haven't looked.
agayev
2011/05/26 22:55:55
This is the primitive used by all other randomness
|
+ PackUint16BE(io_buffer_->data(), id_); |
cbentzel
2011/05/26 17:32:40
You should probably use htons here.
agayev
2011/05/26 22:55:55
No, since I'm doing it big-endian anyway.
|
+} |
+ |
+int DnsQuery::port() const { |
+ DCHECK(IsValid()); |
+ return port_; |
+} |
+ |
+uint16 DnsQuery::id() const { |
+ DCHECK(IsValid()); |
+ return id_; |
+} |
+ |
+uint16 DnsQuery::qtype() const { |
+ DCHECK(IsValid()); |
+ return qtype_; |
+} |
+ |
+uint16 DnsQuery::qclass() const { |
+ DCHECK(IsValid()); |
+ return qclass_; |
+} |
+ |
+const std::string& DnsQuery::qname() const { |
+ DCHECK(IsValid()); |
+ return qname_; |
+} |
+ |
+size_t DnsQuery::size() const { |
+ DCHECK(IsValid()); |
+ return io_buffer_->size(); |
+} |
+ |
+IOBuffer* DnsQuery::io_buffer() { |
+ DCHECK(IsValid()); |
+ RandomizeId(); |
+ return io_buffer_.get(); |
+} |
+ |
+char* DnsQuery::data() const { |
+ DCHECK(IsValid()); |
+ return io_buffer_->data(); |
+} |
+ |
+} // namespace net |