OLD | NEW |
---|---|
(Empty) | |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "net/base/dns_query.h" | |
6 | |
7 #include <string> | |
8 | |
9 #include "base/rand_util.h" | |
10 #include "net/base/address_family.h" | |
11 #include "net/base/dns_util.h" | |
12 | |
13 #include <iostream> | |
14 | |
15 namespace net { | |
16 | |
17 namespace { | |
18 | |
19 void PackUint16BE(char buf[2], uint16 v) { | |
20 buf[1] = v & 0xff; | |
21 buf[0] = v >> 8; | |
22 } | |
23 | |
24 } | |
25 | |
26 // DNS query consists of a 12-byte header followed by a question section, | |
27 // for details, see RFC 1035 section 4.1.1. This header template sets RD | |
28 // bit, which directs the name server to pursue query recursively, and sets | |
29 // the QDCOUNT to 1, meaning the question section has a single entry. The | |
30 // first two bytes of the header form a 16-bit query ID to be copied in the | |
31 // corresponding reply by the name server; it's set to 0 here and is | |
32 // randomized every time the underlying buffer is fetched. | |
33 static const char kHeader[] = {0x00, 0x00, 0x01, 0x00, 0x00, 0x01, | |
34 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; | |
35 static const int kHeaderLen = arraysize(kHeader); | |
36 | |
37 DnsQuery::DnsQuery(const std::string& hostname, | |
38 AddressFamily address_family, | |
39 int port) | |
40 : port_(port), | |
41 id_(0), | |
42 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.
| |
43 qclass_(kClassIN) { | |
44 if (address_family == ADDRESS_FAMILY_IPV6) | |
45 qtype_ = kDNS_AAAA; | |
46 else if (address_family != ADDRESS_FAMILY_IPV4) | |
47 NOTREACHED(); | |
48 | |
49 if (!net::DNSDomainFromDot(hostname, &qname_)) | |
50 return; | |
51 | |
52 size_t query_size = kHeaderLen + qname_.size() + | |
53 sizeof(qtype_) + sizeof(qclass_); | |
54 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.
| |
55 | |
56 size_t iterator = 0; | |
57 memcpy(&query[iterator], kHeader, kHeaderLen); | |
58 iterator += kHeaderLen; | |
59 memcpy(&query[iterator], &qname_[0], qname_.size()); | |
60 iterator += qname_.size(); | |
61 PackUint16BE(&query[iterator], qtype_); | |
62 iterator += sizeof(qtype_); | |
63 PackUint16BE(&query[iterator], qclass_); | |
64 | |
65 io_buffer_ = new IOBufferWithSize(query.size()); | |
66 memcpy(io_buffer_->data(), &query[0], query.size()); | |
67 | |
68 RandomizeId(); | |
69 // RFC2181 section 11: A full domain name is limited to 255 octets | |
70 // (including the separators). | |
71 static const int kMaxQuerySize = kHeaderLen + 255 + | |
72 sizeof(qtype_) + sizeof(qclass_); | |
73 DCHECK(io_buffer_->size() > kHeaderLen && | |
74 io_buffer_->size() <= kMaxQuerySize); | |
75 } | |
76 | |
77 void DnsQuery::RandomizeId() { | |
78 DCHECK(IsValid()); | |
79 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
| |
80 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.
| |
81 } | |
82 | |
83 int DnsQuery::port() const { | |
84 DCHECK(IsValid()); | |
85 return port_; | |
86 } | |
87 | |
88 uint16 DnsQuery::id() const { | |
89 DCHECK(IsValid()); | |
90 return id_; | |
91 } | |
92 | |
93 uint16 DnsQuery::qtype() const { | |
94 DCHECK(IsValid()); | |
95 return qtype_; | |
96 } | |
97 | |
98 uint16 DnsQuery::qclass() const { | |
99 DCHECK(IsValid()); | |
100 return qclass_; | |
101 } | |
102 | |
103 const std::string& DnsQuery::qname() const { | |
104 DCHECK(IsValid()); | |
105 return qname_; | |
106 } | |
107 | |
108 size_t DnsQuery::size() const { | |
109 DCHECK(IsValid()); | |
110 return io_buffer_->size(); | |
111 } | |
112 | |
113 IOBuffer* DnsQuery::io_buffer() { | |
114 DCHECK(IsValid()); | |
115 RandomizeId(); | |
116 return io_buffer_.get(); | |
117 } | |
118 | |
119 char* DnsQuery::data() const { | |
120 DCHECK(IsValid()); | |
121 return io_buffer_->data(); | |
122 } | |
123 | |
124 } // namespace net | |
OLD | NEW |