| 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_response.h" | 5 #include "net/base/dns_response.h" |
| 6 | 6 |
| 7 #include "net/base/address_list.h" | |
| 8 #include "net/base/dns_util.h" | 7 #include "net/base/dns_util.h" |
| 9 #include "net/base/net_errors.h" | 8 #include "net/base/net_errors.h" |
| 10 | 9 |
| 11 namespace net { | 10 namespace net { |
| 12 | 11 |
| 13 // RFC 1035, section 4.2.1: Messages carried by UDP are restricted to 512 | 12 // RFC 1035, section 4.2.1: Messages carried by UDP are restricted to 512 |
| 14 // bytes (not counting the IP nor UDP headers). | 13 // bytes (not counting the IP nor UDP headers). |
| 15 static const int kMaxResponseSize = 512; | 14 static const int kMaxResponseSize = 512; |
| 16 | 15 |
| 17 DnsResponse::DnsResponse(DnsQuery* query) | 16 DnsResponse::DnsResponse(DnsQuery* query) |
| 18 : query_(query), | 17 : query_(query), |
| 19 io_buffer_(new IOBufferWithSize(kMaxResponseSize + 1)) { | 18 io_buffer_(new IOBufferWithSize(kMaxResponseSize + 1)) { |
| 20 DCHECK(query_); | 19 DCHECK(query_); |
| 21 DCHECK(query_->IsValid()); | |
| 22 } | 20 } |
| 23 | 21 |
| 24 DnsResponse::~DnsResponse() { | 22 DnsResponse::~DnsResponse() { |
| 25 } | 23 } |
| 26 | 24 |
| 27 int DnsResponse::Parse(int nbytes, AddressList* results) { | 25 int DnsResponse::Parse(int nbytes, std::vector<IPAddressNumber>* ip_addresses) { |
| 28 DCHECK(query_->IsValid()); | |
| 29 | |
| 30 // Response includes query, it should be at least that size. | 26 // Response includes query, it should be at least that size. |
| 31 if (nbytes < query_->io_buffer()->size() || nbytes > kMaxResponseSize) | 27 if (nbytes < query_->io_buffer()->size() || nbytes > kMaxResponseSize) |
| 32 return ERR_DNS_MALFORMED_RESPONSE; | 28 return ERR_DNS_MALFORMED_RESPONSE; |
| 33 | 29 |
| 34 DnsResponseBuffer response(reinterpret_cast<uint8*>(io_buffer_->data()), | 30 DnsResponseBuffer response(reinterpret_cast<uint8*>(io_buffer_->data()), |
| 35 io_buffer_->size()); | 31 io_buffer_->size()); |
| 36 uint16 id; | 32 uint16 id; |
| 37 if (!response.U16(&id) || id != query_->id()) // Make sure IDs match. | 33 if (!response.U16(&id) || id != query_->id()) // Make sure IDs match. |
| 38 return ERR_DNS_MALFORMED_RESPONSE; | 34 return ERR_DNS_MALFORMED_RESPONSE; |
| 39 | 35 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 52 if (!response.U16(&query_count) || | 48 if (!response.U16(&query_count) || |
| 53 !response.U16(&answer_count) || | 49 !response.U16(&answer_count) || |
| 54 !response.U16(&authority_count) || | 50 !response.U16(&authority_count) || |
| 55 !response.U16(&additional_count)) { | 51 !response.U16(&additional_count)) { |
| 56 return ERR_DNS_MALFORMED_RESPONSE; | 52 return ERR_DNS_MALFORMED_RESPONSE; |
| 57 } | 53 } |
| 58 | 54 |
| 59 if (query_count != 1) // Sent a single question, shouldn't have changed. | 55 if (query_count != 1) // Sent a single question, shouldn't have changed. |
| 60 return ERR_DNS_MALFORMED_RESPONSE; | 56 return ERR_DNS_MALFORMED_RESPONSE; |
| 61 | 57 |
| 62 std::string hostname; | 58 base::StringPiece question; // Make sure question section is echoed back. |
| 63 uint16 qtype, qclass; | 59 if (!response.Block(&question, query_->question_size()) || |
| 64 if (!response.DNSName(&hostname) || | 60 memcmp(question.data(), query_->question_data(), |
| 65 !response.U16(&qtype) || | 61 query_->question_size())) { |
| 66 !response.U16(&qclass) || | |
| 67 hostname != query_->hostname() || // Make sure Question section | |
| 68 qtype != query_->qtype() || // echoed back. | |
| 69 qclass != kClassIN) { | |
| 70 return ERR_DNS_MALFORMED_RESPONSE; | 62 return ERR_DNS_MALFORMED_RESPONSE; |
| 71 } | 63 } |
| 72 | 64 |
| 73 if (answer_count < 1) | 65 if (answer_count < 1) |
| 74 return ERR_NAME_NOT_RESOLVED; | 66 return ERR_NAME_NOT_RESOLVED; |
| 75 | 67 |
| 76 std::vector<IPAddressNumber> rdatas; | 68 std::vector<IPAddressNumber> rdatas; |
| 77 while (answer_count--) { | 69 while (answer_count--) { |
| 78 uint32 ttl; | 70 uint32 ttl; |
| 79 uint16 rdlength; | 71 uint16 rdlength, qtype, qclass; |
| 80 if (!response.DNSName(NULL) || | 72 if (!response.DNSName(NULL) || |
| 81 !response.U16(&qtype) || | 73 !response.U16(&qtype) || |
| 82 !response.U16(&qclass) || | 74 !response.U16(&qclass) || |
| 83 !response.U32(&ttl) || | 75 !response.U32(&ttl) || |
| 84 !response.U16(&rdlength)) { | 76 !response.U16(&rdlength)) { |
| 85 return ERR_DNS_MALFORMED_RESPONSE; | 77 return ERR_DNS_MALFORMED_RESPONSE; |
| 86 } | 78 } |
| 87 | |
| 88 if (qtype == query_->qtype() && | 79 if (qtype == query_->qtype() && |
| 89 qclass == kClassIN && | 80 qclass == kClassIN && |
| 90 (rdlength == kIPv4AddressSize || rdlength == kIPv6AddressSize)) { | 81 (rdlength == kIPv4AddressSize || rdlength == kIPv6AddressSize)) { |
| 91 base::StringPiece rdata; | 82 base::StringPiece rdata; |
| 92 if (!response.Block(&rdata, rdlength)) | 83 if (!response.Block(&rdata, rdlength)) |
| 93 return ERR_DNS_MALFORMED_RESPONSE; | 84 return ERR_DNS_MALFORMED_RESPONSE; |
| 94 rdatas.push_back(IPAddressNumber(rdata.begin(), rdata.end())); | 85 rdatas.push_back(IPAddressNumber(rdata.begin(), rdata.end())); |
| 95 } else if (!response.Skip(rdlength)) | 86 } else if (!response.Skip(rdlength)) |
| 96 return ERR_DNS_MALFORMED_RESPONSE; | 87 return ERR_DNS_MALFORMED_RESPONSE; |
| 97 } | 88 } |
| 98 | 89 |
| 99 if (rdatas.empty()) | 90 if (rdatas.empty()) |
| 100 return ERR_NAME_NOT_RESOLVED; | 91 return ERR_NAME_NOT_RESOLVED; |
| 101 | 92 |
| 102 *results = AddressList::CreateFromIPAddressList(rdatas, query_->port()); | 93 if (ip_addresses) |
| 94 ip_addresses->swap(rdatas); |
| 103 return OK; | 95 return OK; |
| 104 } | 96 } |
| 105 | 97 |
| 106 } // namespace net | 98 } // namespace net |
| OLD | NEW |