| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/dns/dns_response.h" | 5 #include "net/dns/dns_response.h" |
| 6 | 6 |
| 7 #include <limits> |
| 8 |
| 7 #include "base/big_endian.h" | 9 #include "base/big_endian.h" |
| 8 #include "base/strings/string_util.h" | 10 #include "base/strings/string_util.h" |
| 9 #include "base/sys_byteorder.h" | 11 #include "base/sys_byteorder.h" |
| 10 #include "net/base/address_list.h" | 12 #include "net/base/address_list.h" |
| 11 #include "net/base/io_buffer.h" | 13 #include "net/base/io_buffer.h" |
| 12 #include "net/base/net_errors.h" | 14 #include "net/base/net_errors.h" |
| 13 #include "net/dns/dns_protocol.h" | 15 #include "net/dns/dns_protocol.h" |
| 14 #include "net/dns/dns_query.h" | 16 #include "net/dns/dns_query.h" |
| 15 #include "net/dns/dns_util.h" | 17 #include "net/dns/dns_util.h" |
| 16 | 18 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 54 if (out) { | 56 if (out) { |
| 55 out->clear(); | 57 out->clear(); |
| 56 out->reserve(dns_protocol::kMaxNameLength); | 58 out->reserve(dns_protocol::kMaxNameLength); |
| 57 } | 59 } |
| 58 | 60 |
| 59 for (;;) { | 61 for (;;) { |
| 60 // The first two bits of the length give the type of the length. It's | 62 // The first two bits of the length give the type of the length. It's |
| 61 // either a direct length or a pointer to the remainder of the name. | 63 // either a direct length or a pointer to the remainder of the name. |
| 62 switch (*p & dns_protocol::kLabelMask) { | 64 switch (*p & dns_protocol::kLabelMask) { |
| 63 case dns_protocol::kLabelPointer: { | 65 case dns_protocol::kLabelPointer: { |
| 64 if (p + sizeof(uint16) > end) | 66 if (p + sizeof(uint16_t) > end) |
| 65 return 0; | 67 return 0; |
| 66 if (consumed == 0) { | 68 if (consumed == 0) { |
| 67 consumed = p - pos + sizeof(uint16); | 69 consumed = p - pos + sizeof(uint16_t); |
| 68 if (!out) | 70 if (!out) |
| 69 return consumed; // If name is not stored, that's all we need. | 71 return consumed; // If name is not stored, that's all we need. |
| 70 } | 72 } |
| 71 seen += sizeof(uint16); | 73 seen += sizeof(uint16_t); |
| 72 // If seen the whole packet, then we must be in a loop. | 74 // If seen the whole packet, then we must be in a loop. |
| 73 if (seen > length_) | 75 if (seen > length_) |
| 74 return 0; | 76 return 0; |
| 75 uint16 offset; | 77 uint16_t offset; |
| 76 base::ReadBigEndian<uint16>(p, &offset); | 78 base::ReadBigEndian<uint16_t>(p, &offset); |
| 77 offset &= dns_protocol::kOffsetMask; | 79 offset &= dns_protocol::kOffsetMask; |
| 78 p = packet_ + offset; | 80 p = packet_ + offset; |
| 79 if (p >= end) | 81 if (p >= end) |
| 80 return 0; | 82 return 0; |
| 81 break; | 83 break; |
| 82 } | 84 } |
| 83 case dns_protocol::kLabelDirect: { | 85 case dns_protocol::kLabelDirect: { |
| 84 uint8 label_len = *p; | 86 uint8_t label_len = *p; |
| 85 ++p; | 87 ++p; |
| 86 // Note: root domain (".") is NOT included. | 88 // Note: root domain (".") is NOT included. |
| 87 if (label_len == 0) { | 89 if (label_len == 0) { |
| 88 if (consumed == 0) { | 90 if (consumed == 0) { |
| 89 consumed = p - pos; | 91 consumed = p - pos; |
| 90 } // else we set |consumed| before first jump | 92 } // else we set |consumed| before first jump |
| 91 return consumed; | 93 return consumed; |
| 92 } | 94 } |
| 93 if (p + label_len >= end) | 95 if (p + label_len >= end) |
| 94 return 0; // Truncated or missing label. | 96 return 0; // Truncated or missing label. |
| (...skipping 13 matching lines...) Expand all Loading... |
| 108 } | 110 } |
| 109 } | 111 } |
| 110 | 112 |
| 111 bool DnsRecordParser::ReadRecord(DnsResourceRecord* out) { | 113 bool DnsRecordParser::ReadRecord(DnsResourceRecord* out) { |
| 112 DCHECK(packet_); | 114 DCHECK(packet_); |
| 113 size_t consumed = ReadName(cur_, &out->name); | 115 size_t consumed = ReadName(cur_, &out->name); |
| 114 if (!consumed) | 116 if (!consumed) |
| 115 return false; | 117 return false; |
| 116 base::BigEndianReader reader(cur_ + consumed, | 118 base::BigEndianReader reader(cur_ + consumed, |
| 117 packet_ + length_ - (cur_ + consumed)); | 119 packet_ + length_ - (cur_ + consumed)); |
| 118 uint16 rdlen; | 120 uint16_t rdlen; |
| 119 if (reader.ReadU16(&out->type) && | 121 if (reader.ReadU16(&out->type) && |
| 120 reader.ReadU16(&out->klass) && | 122 reader.ReadU16(&out->klass) && |
| 121 reader.ReadU32(&out->ttl) && | 123 reader.ReadU32(&out->ttl) && |
| 122 reader.ReadU16(&rdlen) && | 124 reader.ReadU16(&rdlen) && |
| 123 reader.ReadPiece(&out->rdata, rdlen)) { | 125 reader.ReadPiece(&out->rdata, rdlen)) { |
| 124 cur_ = reader.ptr(); | 126 cur_ = reader.ptr(); |
| 125 return true; | 127 return true; |
| 126 } | 128 } |
| 127 return false; | 129 return false; |
| 128 } | 130 } |
| 129 | 131 |
| 130 bool DnsRecordParser::SkipQuestion() { | 132 bool DnsRecordParser::SkipQuestion() { |
| 131 size_t consumed = ReadName(cur_, NULL); | 133 size_t consumed = ReadName(cur_, NULL); |
| 132 if (!consumed) | 134 if (!consumed) |
| 133 return false; | 135 return false; |
| 134 | 136 |
| 135 const char* next = cur_ + consumed + 2 * sizeof(uint16); // QTYPE + QCLASS | 137 const char* next = cur_ + consumed + 2 * sizeof(uint16_t); // QTYPE + QCLASS |
| 136 if (next > packet_ + length_) | 138 if (next > packet_ + length_) |
| 137 return false; | 139 return false; |
| 138 | 140 |
| 139 cur_ = next; | 141 cur_ = next; |
| 140 | 142 |
| 141 return true; | 143 return true; |
| 142 } | 144 } |
| 143 | 145 |
| 144 DnsResponse::DnsResponse() | 146 DnsResponse::DnsResponse() |
| 145 : io_buffer_(new IOBufferWithSize(dns_protocol::kMaxUDPSize + 1)) { | 147 : io_buffer_(new IOBufferWithSize(dns_protocol::kMaxUDPSize + 1)) { |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 209 } | 211 } |
| 210 } | 212 } |
| 211 | 213 |
| 212 return true; | 214 return true; |
| 213 } | 215 } |
| 214 | 216 |
| 215 bool DnsResponse::IsValid() const { | 217 bool DnsResponse::IsValid() const { |
| 216 return parser_.IsValid(); | 218 return parser_.IsValid(); |
| 217 } | 219 } |
| 218 | 220 |
| 219 uint16 DnsResponse::flags() const { | 221 uint16_t DnsResponse::flags() const { |
| 220 DCHECK(parser_.IsValid()); | 222 DCHECK(parser_.IsValid()); |
| 221 return base::NetToHost16(header()->flags) & ~(dns_protocol::kRcodeMask); | 223 return base::NetToHost16(header()->flags) & ~(dns_protocol::kRcodeMask); |
| 222 } | 224 } |
| 223 | 225 |
| 224 uint8 DnsResponse::rcode() const { | 226 uint8_t DnsResponse::rcode() const { |
| 225 DCHECK(parser_.IsValid()); | 227 DCHECK(parser_.IsValid()); |
| 226 return base::NetToHost16(header()->flags) & dns_protocol::kRcodeMask; | 228 return base::NetToHost16(header()->flags) & dns_protocol::kRcodeMask; |
| 227 } | 229 } |
| 228 | 230 |
| 229 unsigned DnsResponse::answer_count() const { | 231 unsigned DnsResponse::answer_count() const { |
| 230 DCHECK(parser_.IsValid()); | 232 DCHECK(parser_.IsValid()); |
| 231 return base::NetToHost16(header()->ancount); | 233 return base::NetToHost16(header()->ancount); |
| 232 } | 234 } |
| 233 | 235 |
| 234 unsigned DnsResponse::additional_answer_count() const { | 236 unsigned DnsResponse::additional_answer_count() const { |
| 235 DCHECK(parser_.IsValid()); | 237 DCHECK(parser_.IsValid()); |
| 236 return base::NetToHost16(header()->arcount); | 238 return base::NetToHost16(header()->arcount); |
| 237 } | 239 } |
| 238 | 240 |
| 239 base::StringPiece DnsResponse::qname() const { | 241 base::StringPiece DnsResponse::qname() const { |
| 240 DCHECK(parser_.IsValid()); | 242 DCHECK(parser_.IsValid()); |
| 241 // The response is HEADER QNAME QTYPE QCLASS ANSWER. | 243 // The response is HEADER QNAME QTYPE QCLASS ANSWER. |
| 242 // |parser_| is positioned at the beginning of ANSWER, so the end of QNAME is | 244 // |parser_| is positioned at the beginning of ANSWER, so the end of QNAME is |
| 243 // two uint16s before it. | 245 // two uint16_ts before it. |
| 244 const size_t hdr_size = sizeof(dns_protocol::Header); | 246 const size_t hdr_size = sizeof(dns_protocol::Header); |
| 245 const size_t qname_size = parser_.GetOffset() - 2 * sizeof(uint16) - hdr_size; | 247 const size_t qname_size = |
| 248 parser_.GetOffset() - 2 * sizeof(uint16_t) - hdr_size; |
| 246 return base::StringPiece(io_buffer_->data() + hdr_size, qname_size); | 249 return base::StringPiece(io_buffer_->data() + hdr_size, qname_size); |
| 247 } | 250 } |
| 248 | 251 |
| 249 uint16 DnsResponse::qtype() const { | 252 uint16_t DnsResponse::qtype() const { |
| 250 DCHECK(parser_.IsValid()); | 253 DCHECK(parser_.IsValid()); |
| 251 // QTYPE starts where QNAME ends. | 254 // QTYPE starts where QNAME ends. |
| 252 const size_t type_offset = parser_.GetOffset() - 2 * sizeof(uint16); | 255 const size_t type_offset = parser_.GetOffset() - 2 * sizeof(uint16_t); |
| 253 uint16 type; | 256 uint16_t type; |
| 254 base::ReadBigEndian<uint16>(io_buffer_->data() + type_offset, &type); | 257 base::ReadBigEndian<uint16_t>(io_buffer_->data() + type_offset, &type); |
| 255 return type; | 258 return type; |
| 256 } | 259 } |
| 257 | 260 |
| 258 std::string DnsResponse::GetDottedName() const { | 261 std::string DnsResponse::GetDottedName() const { |
| 259 return DNSDomainToString(qname()); | 262 return DNSDomainToString(qname()); |
| 260 } | 263 } |
| 261 | 264 |
| 262 DnsRecordParser DnsResponse::Parser() const { | 265 DnsRecordParser DnsResponse::Parser() const { |
| 263 DCHECK(parser_.IsValid()); | 266 DCHECK(parser_.IsValid()); |
| 264 // Return a copy of the parser. | 267 // Return a copy of the parser. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 275 DCHECK(IsValid()); | 278 DCHECK(IsValid()); |
| 276 // DnsTransaction already verified that |response| matches the issued query. | 279 // DnsTransaction already verified that |response| matches the issued query. |
| 277 // We still need to determine if there is a valid chain of CNAMEs from the | 280 // We still need to determine if there is a valid chain of CNAMEs from the |
| 278 // query name to the RR owner name. | 281 // query name to the RR owner name. |
| 279 // We err on the side of caution with the assumption that if we are too picky, | 282 // We err on the side of caution with the assumption that if we are too picky, |
| 280 // we can always fall back to the system getaddrinfo. | 283 // we can always fall back to the system getaddrinfo. |
| 281 | 284 |
| 282 // Expected owner of record. No trailing dot. | 285 // Expected owner of record. No trailing dot. |
| 283 std::string expected_name = GetDottedName(); | 286 std::string expected_name = GetDottedName(); |
| 284 | 287 |
| 285 uint16 expected_type = qtype(); | 288 uint16_t expected_type = qtype(); |
| 286 DCHECK(expected_type == dns_protocol::kTypeA || | 289 DCHECK(expected_type == dns_protocol::kTypeA || |
| 287 expected_type == dns_protocol::kTypeAAAA); | 290 expected_type == dns_protocol::kTypeAAAA); |
| 288 | 291 |
| 289 size_t expected_size = (expected_type == dns_protocol::kTypeAAAA) | 292 size_t expected_size = (expected_type == dns_protocol::kTypeAAAA) |
| 290 ? kIPv6AddressSize : kIPv4AddressSize; | 293 ? kIPv6AddressSize : kIPv4AddressSize; |
| 291 | 294 |
| 292 uint32 ttl_sec = kuint32max; | 295 uint32_t ttl_sec = std::numeric_limits<uint32_t>::max(); |
| 293 IPAddressList ip_addresses; | 296 IPAddressList ip_addresses; |
| 294 DnsRecordParser parser = Parser(); | 297 DnsRecordParser parser = Parser(); |
| 295 DnsResourceRecord record; | 298 DnsResourceRecord record; |
| 296 unsigned ancount = answer_count(); | 299 unsigned ancount = answer_count(); |
| 297 for (unsigned i = 0; i < ancount; ++i) { | 300 for (unsigned i = 0; i < ancount; ++i) { |
| 298 if (!parser.ReadRecord(&record)) | 301 if (!parser.ReadRecord(&record)) |
| 299 return DNS_MALFORMED_RESPONSE; | 302 return DNS_MALFORMED_RESPONSE; |
| 300 | 303 |
| 301 if (record.type == dns_protocol::kTypeCNAME) { | 304 if (record.type == dns_protocol::kTypeCNAME) { |
| 302 // Following the CNAME chain, only if no addresses seen. | 305 // Following the CNAME chain, only if no addresses seen. |
| (...skipping 25 matching lines...) Expand all Loading... |
| 328 | 331 |
| 329 // getcanonname in eglibc returns the first owner name of an A or AAAA RR. | 332 // getcanonname in eglibc returns the first owner name of an A or AAAA RR. |
| 330 // If the response passed all the checks so far, then |expected_name| is it. | 333 // If the response passed all the checks so far, then |expected_name| is it. |
| 331 *addr_list = AddressList::CreateFromIPAddressList(ip_addresses, | 334 *addr_list = AddressList::CreateFromIPAddressList(ip_addresses, |
| 332 expected_name); | 335 expected_name); |
| 333 *ttl = base::TimeDelta::FromSeconds(ttl_sec); | 336 *ttl = base::TimeDelta::FromSeconds(ttl_sec); |
| 334 return DNS_PARSE_OK; | 337 return DNS_PARSE_OK; |
| 335 } | 338 } |
| 336 | 339 |
| 337 } // namespace net | 340 } // namespace net |
| OLD | NEW |