OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/base/dns_query.h" | 5 #include "net/base/dns_query.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "base/rand_util.h" | 9 #include "base/rand_util.h" |
10 #include "net/base/address_family.h" | |
11 #include "net/base/dns_util.h" | 10 #include "net/base/dns_util.h" |
12 | 11 |
13 namespace net { | 12 namespace net { |
14 | 13 |
15 namespace { | 14 namespace { |
16 | 15 |
17 void PackUint16BE(char buf[2], uint16 v) { | 16 void PackUint16BE(char buf[2], uint16 v) { |
18 buf[0] = v >> 8; | 17 buf[0] = v >> 8; |
19 buf[1] = v & 0xff; | 18 buf[1] = v & 0xff; |
20 } | 19 } |
21 | 20 |
22 uint16 QTypeFromAddressFamily(AddressFamily address_family) { | 21 uint16 UnpackUint16BE(char buf[2]) { |
23 switch (address_family) { | 22 return static_cast<uint8>(buf[0]) << 8 | static_cast<uint8>(buf[1]); |
24 case ADDRESS_FAMILY_IPV4: | |
25 return kDNS_A; | |
26 case ADDRESS_FAMILY_IPV6: | |
27 return kDNS_AAAA; | |
28 default: | |
29 NOTREACHED() << "Bad address family"; | |
30 return kDNS_A; | |
31 } | |
32 } | 23 } |
33 | 24 |
34 } // namespace | 25 } // namespace |
35 | 26 |
36 // DNS query consists of a 12-byte header followed by a question section. | 27 // DNS query consists of a 12-byte header followed by a question section. |
37 // For details, see RFC 1035 section 4.1.1. This header template sets RD | 28 // For details, see RFC 1035 section 4.1.1. This header template sets RD |
38 // bit, which directs the name server to pursue query recursively, and sets | 29 // bit, which directs the name server to pursue query recursively, and sets |
39 // the QDCOUNT to 1, meaning the question section has a single entry. The | 30 // the QDCOUNT to 1, meaning the question section has a single entry. The |
40 // first two bytes of the header form a 16-bit random query ID to be copied | 31 // first two bytes of the header form a 16-bit random query ID to be copied |
41 // in the corresponding reply by the name server -- randomized during | 32 // in the corresponding reply by the name server -- randomized during |
42 // DnsQuery construction. | 33 // DnsQuery construction. |
43 static const char kHeader[] = {0x00, 0x00, 0x01, 0x00, 0x00, 0x01, | 34 static const char kHeader[] = {0x00, 0x00, 0x01, 0x00, 0x00, 0x01, |
44 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; | 35 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; |
45 static const size_t kHeaderLen = arraysize(kHeader); | 36 static const size_t kHeaderSize = arraysize(kHeader); |
46 | 37 |
47 DnsQuery::DnsQuery(const std::string& hostname, | 38 DnsQuery::DnsQuery(const std::string& dns_name, uint16 qtype) |
48 AddressFamily address_family, | 39 : dns_name_size_(dns_name.size()) { |
49 int port) | 40 DCHECK(DnsResponseBuffer(reinterpret_cast<const uint8*>(dns_name.c_str()), |
50 : port_(port), | 41 dns_name.size()).DNSName(NULL)); |
51 id_(0), | 42 DCHECK(qtype == kDNS_A || qtype == kDNS_AAAA); |
52 qtype_(QTypeFromAddressFamily(address_family)), | |
53 hostname_(hostname) { | |
54 std::string qname; | |
55 if (!net::DNSDomainFromDot(hostname, &qname)) | |
56 return; | |
57 | 43 |
58 size_t query_size = kHeaderLen + qname.size() + | 44 io_buffer_ = new IOBufferWithSize(kHeaderSize + question_size()); |
59 sizeof(qtype_) + sizeof(kClassIN); | |
60 | |
61 io_buffer_ = new IOBufferWithSize(query_size); | |
62 | 45 |
63 int byte_offset = 0; | 46 int byte_offset = 0; |
64 char* buffer_head = io_buffer_->data(); | 47 char* buffer_head = io_buffer_->data(); |
65 memcpy(&buffer_head[byte_offset], kHeader, kHeaderLen); | 48 memcpy(&buffer_head[byte_offset], kHeader, kHeaderSize); |
66 byte_offset += kHeaderLen; | 49 byte_offset += kHeaderSize; |
67 memcpy(&buffer_head[byte_offset], &qname[0], qname.size()); | 50 memcpy(&buffer_head[byte_offset], &dns_name[0], dns_name_size_); |
68 byte_offset += qname.size(); | 51 byte_offset += dns_name_size_; |
69 PackUint16BE(&buffer_head[byte_offset], qtype_); | 52 PackUint16BE(&buffer_head[byte_offset], qtype); |
70 byte_offset += sizeof(qtype_); | 53 byte_offset += sizeof(qtype); |
71 PackUint16BE(&buffer_head[byte_offset], kClassIN); | 54 PackUint16BE(&buffer_head[byte_offset], kClassIN); |
55 RandomizeId(); | |
56 } | |
72 | 57 |
73 // Randomize ID, first two bytes. | 58 DnsQuery::DnsQuery(const DnsQuery& rhs) { |
cbentzel
2011/06/09 01:16:06
Use initializer arguments rather than assignment w
agayev
2011/06/09 14:23:02
Done.
| |
74 id_ = base::RandUint64() & 0xffff; | 59 dns_name_size_ = rhs.dns_name_size_; |
75 PackUint16BE(&buffer_head[0], id_); | 60 io_buffer_ = new IOBufferWithSize(rhs.io_buffer()->size()); |
61 memcpy(io_buffer_->data(), rhs.io_buffer()->data(), rhs.io_buffer()->size()); | |
62 RandomizeId(); | |
76 } | 63 } |
77 | 64 |
78 DnsQuery::~DnsQuery() { | 65 DnsQuery::~DnsQuery() { |
79 } | 66 } |
80 | 67 |
81 int DnsQuery::port() const { | |
82 DCHECK(IsValid()); | |
83 return port_; | |
84 } | |
85 | |
86 uint16 DnsQuery::id() const { | 68 uint16 DnsQuery::id() const { |
87 DCHECK(IsValid()); | 69 return UnpackUint16BE(&io_buffer_->data()[0]); |
88 return id_; | |
89 } | 70 } |
90 | 71 |
91 uint16 DnsQuery::qtype() const { | 72 uint16 DnsQuery::qtype() const { |
92 DCHECK(IsValid()); | 73 return UnpackUint16BE(&io_buffer_->data()[kHeaderSize + dns_name_size_]); |
93 return qtype_; | |
94 } | 74 } |
95 | 75 |
96 AddressFamily DnsQuery::address_family() const { | 76 DnsQuery* DnsQuery::CloneWithNewId() const { |
97 DCHECK(IsValid()); | 77 return new DnsQuery(*this); |
98 return address_family_; | |
99 } | 78 } |
100 | 79 |
101 const std::string& DnsQuery::hostname() const { | 80 size_t DnsQuery::question_size() const { |
102 DCHECK(IsValid()); | 81 return dns_name_size_ // QNAME |
103 return hostname_; | 82 + sizeof(uint16) // QTYPE |
83 + sizeof(uint16); // QCLASS | |
104 } | 84 } |
105 | 85 |
106 IOBufferWithSize* DnsQuery::io_buffer() const { | 86 char* DnsQuery::question_data() const { |
107 DCHECK(IsValid()); | 87 return &io_buffer_->data()[kHeaderSize]; |
108 return io_buffer_.get(); | 88 } |
89 | |
90 void DnsQuery::RandomizeId() { | |
91 PackUint16BE(&io_buffer_->data()[0], base::RandUint64() & 0xffff); | |
109 } | 92 } |
110 | 93 |
111 } // namespace net | 94 } // namespace net |
OLD | NEW |