| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/mdns_client_impl.h" | 5 #include "net/dns/mdns_client_impl.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/message_loop/message_loop_proxy.h" | 8 #include "base/message_loop/message_loop_proxy.h" |
| 9 #include "base/stl_util.h" | 9 #include "base/stl_util.h" |
| 10 #include "base/time/default_clock.h" | 10 #include "base/time/default_clock.h" |
| 11 #include "net/base/dns_util.h" | 11 #include "net/base/dns_util.h" |
| 12 #include "net/base/net_errors.h" | 12 #include "net/base/net_errors.h" |
| 13 #include "net/base/net_log.h" | 13 #include "net/base/net_log.h" |
| 14 #include "net/base/rand_callback.h" | 14 #include "net/base/rand_callback.h" |
| 15 #include "net/dns/dns_protocol.h" | 15 #include "net/dns/dns_protocol.h" |
| 16 #include "net/dns/record_rdata.h" | 16 #include "net/dns/record_rdata.h" |
| 17 #include "net/udp/datagram_socket.h" | 17 #include "net/udp/datagram_socket.h" |
| 18 | 18 |
| 19 // TODO(gene): Remove this temporary method of disabling NSEC support once it | 19 // TODO(gene): Remove this temporary method of disabling NSEC support once it |
| 20 // becomes clear whether this feature should be | 20 // becomes clear whether this feature should be |
| 21 // supported. http://crbug.com/255232 | 21 // supported. http://crbug.com/255232 |
| 22 #define ENABLE_NSEC | 22 #define ENABLE_NSEC |
| 23 | 23 |
| 24 namespace net { | 24 namespace net { |
| 25 | 25 |
| 26 namespace { | 26 namespace { |
| 27 |
| 27 const unsigned MDnsTransactionTimeoutSeconds = 3; | 28 const unsigned MDnsTransactionTimeoutSeconds = 3; |
| 29 |
| 30 int Bind(const IPEndPoint& multicast_addr, DatagramServerSocket* socket) { |
| 31 IPAddressNumber address_any(multicast_addr.address().size()); |
| 32 IPEndPoint bind_endpoint(address_any, multicast_addr.port()); |
| 33 |
| 34 socket->AllowAddressReuse(); |
| 35 int rv = socket->Listen(bind_endpoint); |
| 36 if (rv < OK) |
| 37 return rv; |
| 38 |
| 39 socket->SetMulticastLoopbackMode(false); |
| 40 return socket->JoinGroup(multicast_addr.address()); |
| 28 } | 41 } |
| 29 | 42 |
| 43 void CreateAndBindSocket(AddressFamily address_family, |
| 44 ScopedVector<DatagramServerSocket>* sockets) { |
| 45 scoped_ptr<DatagramServerSocket> socket( |
| 46 new UDPServerSocket(NULL, NetLog::Source())); |
| 47 |
| 48 IPEndPoint multicast_addr = GetMDnsIPEndPoint(address_family); |
| 49 int rv = Bind(multicast_addr, socket.get()); |
| 50 if (rv == OK) { |
| 51 sockets->push_back(socket.release()); |
| 52 } else { |
| 53 VLOG(1) << "Bind failed, endpoint=" << multicast_addr.ToStringWithoutPort() |
| 54 << ", error=" << rv; |
| 55 } |
| 56 } |
| 57 |
| 58 } // namespace |
| 59 |
| 60 void MDnsSocketFactoryImpl::CreateSockets( |
| 61 ScopedVector<DatagramServerSocket>* sockets) { |
| 62 CreateAndBindSocket(ADDRESS_FAMILY_IPV4, sockets); |
| 63 CreateAndBindSocket(ADDRESS_FAMILY_IPV6, sockets); |
| 64 } |
| 65 |
| 66 |
| 67 |
| 30 MDnsConnection::SocketHandler::SocketHandler( | 68 MDnsConnection::SocketHandler::SocketHandler( |
| 31 MDnsConnection* connection, const IPEndPoint& multicast_addr, | 69 scoped_ptr<DatagramServerSocket> socket, |
| 32 MDnsConnection::SocketFactory* socket_factory) | 70 MDnsConnection* connection) |
| 33 : socket_(socket_factory->CreateSocket()), connection_(connection), | 71 : socket_(socket.Pass()), |
| 34 response_(new DnsResponse(dns_protocol::kMaxMulticastSize)), | 72 connection_(connection), |
| 35 multicast_addr_(multicast_addr) { | 73 response_(dns_protocol::kMaxMulticastSize) { |
| 36 } | 74 } |
| 37 | 75 |
| 38 MDnsConnection::SocketHandler::~SocketHandler() { | 76 MDnsConnection::SocketHandler::~SocketHandler() { |
| 39 } | 77 } |
| 40 | 78 |
| 41 int MDnsConnection::SocketHandler::Start() { | 79 int MDnsConnection::SocketHandler::Start() { |
| 80 IPEndPoint end_point; |
| 81 int rv = socket_->GetLocalAddress(&end_point); |
| 82 if (rv != OK) |
| 83 return rv; |
| 84 DCHECK(end_point.GetFamily() == ADDRESS_FAMILY_IPV4 || |
| 85 end_point.GetFamily() == ADDRESS_FAMILY_IPV6); |
| 86 multicast_addr_ = GetMDnsIPEndPoint(end_point.GetFamily()); |
| 42 return DoLoop(0); | 87 return DoLoop(0); |
| 43 } | 88 } |
| 44 | 89 |
| 45 int MDnsConnection::SocketHandler::DoLoop(int rv) { | 90 int MDnsConnection::SocketHandler::DoLoop(int rv) { |
| 46 do { | 91 do { |
| 47 if (rv > 0) | 92 if (rv > 0) |
| 48 connection_->OnDatagramReceived(response_.get(), recv_addr_, rv); | 93 connection_->OnDatagramReceived(&response_, recv_addr_, rv); |
| 49 | 94 |
| 50 rv = socket_->RecvFrom( | 95 rv = socket_->RecvFrom( |
| 51 response_->io_buffer(), | 96 response_.io_buffer(), |
| 52 response_->io_buffer()->size(), | 97 response_.io_buffer()->size(), |
| 53 &recv_addr_, | 98 &recv_addr_, |
| 54 base::Bind(&MDnsConnection::SocketHandler::OnDatagramReceived, | 99 base::Bind(&MDnsConnection::SocketHandler::OnDatagramReceived, |
| 55 base::Unretained(this))); | 100 base::Unretained(this))); |
| 56 } while (rv > 0); | 101 } while (rv > 0); |
| 57 | 102 |
| 58 if (rv != ERR_IO_PENDING) | 103 if (rv != ERR_IO_PENDING) |
| 59 return rv; | 104 return rv; |
| 60 | 105 |
| 61 return OK; | 106 return OK; |
| 62 } | 107 } |
| 63 | 108 |
| 64 void MDnsConnection::SocketHandler::OnDatagramReceived(int rv) { | 109 void MDnsConnection::SocketHandler::OnDatagramReceived(int rv) { |
| 65 if (rv >= OK) | 110 if (rv >= OK) |
| 66 rv = DoLoop(rv); | 111 rv = DoLoop(rv); |
| 67 | 112 |
| 68 if (rv != OK) | 113 if (rv != OK) |
| 69 connection_->OnError(this, rv); | 114 connection_->OnError(this, rv); |
| 70 } | 115 } |
| 71 | 116 |
| 72 int MDnsConnection::SocketHandler::Send(IOBuffer* buffer, unsigned size) { | 117 int MDnsConnection::SocketHandler::Send(IOBuffer* buffer, unsigned size) { |
| 73 return socket_->SendTo( | 118 return socket_->SendTo(buffer, size, multicast_addr_, |
| 74 buffer, size, multicast_addr_, | 119 base::Bind(&MDnsConnection::SocketHandler::SendDone, |
| 75 base::Bind(&MDnsConnection::SocketHandler::SendDone, | 120 base::Unretained(this) )); |
| 76 base::Unretained(this) )); | |
| 77 } | 121 } |
| 78 | 122 |
| 79 void MDnsConnection::SocketHandler::SendDone(int rv) { | 123 void MDnsConnection::SocketHandler::SendDone(int rv) { |
| 80 // TODO(noamsml): Retry logic. | 124 // TODO(noamsml): Retry logic. |
| 81 } | 125 } |
| 82 | 126 |
| 83 int MDnsConnection::SocketHandler::Bind() { | |
| 84 IPAddressNumber address_any(multicast_addr_.address().size()); | |
| 85 | |
| 86 IPEndPoint bind_endpoint(address_any, multicast_addr_.port()); | |
| 87 | |
| 88 socket_->AllowAddressReuse(); | |
| 89 int rv = socket_->Listen(bind_endpoint); | |
| 90 | |
| 91 if (rv < OK) return rv; | |
| 92 | |
| 93 socket_->SetMulticastLoopbackMode(false); | |
| 94 | |
| 95 return socket_->JoinGroup(multicast_addr_.address()); | |
| 96 } | |
| 97 | |
| 98 MDnsConnection::MDnsConnection(MDnsConnection::Delegate* delegate) : | 127 MDnsConnection::MDnsConnection(MDnsConnection::Delegate* delegate) : |
| 99 delegate_(delegate) { | 128 delegate_(delegate) { |
| 100 } | 129 } |
| 101 | 130 |
| 102 MDnsConnection::~MDnsConnection() { | 131 MDnsConnection::~MDnsConnection() { |
| 103 } | 132 } |
| 104 | 133 |
| 105 bool MDnsConnection::Init(MDnsConnection::SocketFactory* socket_factory) { | 134 bool MDnsConnection::Init(MDnsSocketFactory* socket_factory) { |
| 106 // TODO(vitalybuka): crbug.com/297690 Make socket_factory return list | 135 ScopedVector<DatagramServerSocket> sockets; |
| 107 // of initialized sockets. | 136 socket_factory->CreateSockets(&sockets); |
| 108 socket_handlers_.push_back( | |
| 109 new SocketHandler(this, GetMDnsIPEndPoint(ADDRESS_FAMILY_IPV4), | |
| 110 socket_factory)); | |
| 111 socket_handlers_.push_back( | |
| 112 new SocketHandler(this, GetMDnsIPEndPoint(ADDRESS_FAMILY_IPV6), | |
| 113 socket_factory)); | |
| 114 | 137 |
| 115 for (size_t i = 0; i < socket_handlers_.size();) { | 138 for (size_t i = 0; i < sockets.size(); ++i) { |
| 116 int rv = socket_handlers_[i]->Bind(); | 139 socket_handlers_.push_back( |
| 117 if (rv != OK) { | 140 new MDnsConnection::SocketHandler(make_scoped_ptr(sockets[i]), this)); |
| 118 socket_handlers_.erase(socket_handlers_.begin() + i); | |
| 119 VLOG(1) << "Bind failed, socket=" << i << ", error=" << rv; | |
| 120 } else { | |
| 121 ++i; | |
| 122 } | |
| 123 } | 141 } |
| 142 sockets.weak_clear(); |
| 124 | 143 |
| 125 // All unbound sockets need to be bound before processing untrusted input. | 144 // All unbound sockets need to be bound before processing untrusted input. |
| 126 // This is done for security reasons, so that an attacker can't get an unbound | 145 // This is done for security reasons, so that an attacker can't get an unbound |
| 127 // socket. | 146 // socket. |
| 128 for (size_t i = 0; i < socket_handlers_.size();) { | 147 for (size_t i = 0; i < socket_handlers_.size();) { |
| 129 int rv = socket_handlers_[i]->Start(); | 148 int rv = socket_handlers_[i]->Start(); |
| 130 if (rv != OK) { | 149 if (rv != OK) { |
| 131 socket_handlers_.erase(socket_handlers_.begin() + i); | 150 socket_handlers_.erase(socket_handlers_.begin() + i); |
| 132 VLOG(1) << "Start failed, socket=" << i << ", error=" << rv; | 151 VLOG(1) << "Start failed, socket=" << i << ", error=" << rv; |
| 133 } else { | 152 } else { |
| (...skipping 26 matching lines...) Expand all Loading... |
| 160 | 179 |
| 161 void MDnsConnection::OnDatagramReceived( | 180 void MDnsConnection::OnDatagramReceived( |
| 162 DnsResponse* response, | 181 DnsResponse* response, |
| 163 const IPEndPoint& recv_addr, | 182 const IPEndPoint& recv_addr, |
| 164 int bytes_read) { | 183 int bytes_read) { |
| 165 // TODO(noamsml): More sophisticated error handling. | 184 // TODO(noamsml): More sophisticated error handling. |
| 166 DCHECK_GT(bytes_read, 0); | 185 DCHECK_GT(bytes_read, 0); |
| 167 delegate_->HandlePacket(response, bytes_read); | 186 delegate_->HandlePacket(response, bytes_read); |
| 168 } | 187 } |
| 169 | 188 |
| 170 class MDnsConnectionSocketFactoryImpl | |
| 171 : public MDnsConnection::SocketFactory { | |
| 172 public: | |
| 173 MDnsConnectionSocketFactoryImpl(); | |
| 174 virtual ~MDnsConnectionSocketFactoryImpl(); | |
| 175 | |
| 176 virtual scoped_ptr<DatagramServerSocket> CreateSocket() OVERRIDE; | |
| 177 }; | |
| 178 | |
| 179 MDnsConnectionSocketFactoryImpl::MDnsConnectionSocketFactoryImpl() { | |
| 180 } | |
| 181 | |
| 182 MDnsConnectionSocketFactoryImpl::~MDnsConnectionSocketFactoryImpl() { | |
| 183 } | |
| 184 | |
| 185 scoped_ptr<DatagramServerSocket> | |
| 186 MDnsConnectionSocketFactoryImpl::CreateSocket() { | |
| 187 return scoped_ptr<DatagramServerSocket>(new UDPServerSocket( | |
| 188 NULL, NetLog::Source())); | |
| 189 } | |
| 190 | |
| 191 // static | |
| 192 scoped_ptr<MDnsConnection::SocketFactory> | |
| 193 MDnsConnection::SocketFactory::CreateDefault() { | |
| 194 return scoped_ptr<MDnsConnection::SocketFactory>( | |
| 195 new MDnsConnectionSocketFactoryImpl); | |
| 196 } | |
| 197 | |
| 198 MDnsClientImpl::Core::Core(MDnsClientImpl* client) | 189 MDnsClientImpl::Core::Core(MDnsClientImpl* client) |
| 199 : client_(client), connection_(new MDnsConnection(this)) { | 190 : client_(client), connection_(new MDnsConnection(this)) { |
| 200 } | 191 } |
| 201 | 192 |
| 202 MDnsClientImpl::Core::~Core() { | 193 MDnsClientImpl::Core::~Core() { |
| 203 STLDeleteValues(&listeners_); | 194 STLDeleteValues(&listeners_); |
| 204 } | 195 } |
| 205 | 196 |
| 206 bool MDnsClientImpl::Core::Init(MDnsConnection::SocketFactory* socket_factory) { | 197 bool MDnsClientImpl::Core::Init(MDnsSocketFactory* socket_factory) { |
| 207 return connection_->Init(socket_factory); | 198 return connection_->Init(socket_factory); |
| 208 } | 199 } |
| 209 | 200 |
| 210 bool MDnsClientImpl::Core::SendQuery(uint16 rrtype, std::string name) { | 201 bool MDnsClientImpl::Core::SendQuery(uint16 rrtype, std::string name) { |
| 211 std::string name_dns; | 202 std::string name_dns; |
| 212 if (!DNSDomainFromDot(name, &name_dns)) | 203 if (!DNSDomainFromDot(name, &name_dns)) |
| 213 return false; | 204 return false; |
| 214 | 205 |
| 215 DnsQuery query(0, name_dns, rrtype); | 206 DnsQuery query(0, name_dns, rrtype); |
| 216 query.set_flags(0); // Remove the RD flag from the query. It is unneeded. | 207 query.set_flags(0); // Remove the RD flag from the query. It is unneeded. |
| (...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 427 AlertListeners(MDnsListener::RECORD_REMOVED, | 418 AlertListeners(MDnsListener::RECORD_REMOVED, |
| 428 ListenerKey(record->name(), record->type()), record); | 419 ListenerKey(record->name(), record->type()), record); |
| 429 } | 420 } |
| 430 | 421 |
| 431 void MDnsClientImpl::Core::QueryCache( | 422 void MDnsClientImpl::Core::QueryCache( |
| 432 uint16 rrtype, const std::string& name, | 423 uint16 rrtype, const std::string& name, |
| 433 std::vector<const RecordParsed*>* records) const { | 424 std::vector<const RecordParsed*>* records) const { |
| 434 cache_.FindDnsRecords(rrtype, name, records, base::Time::Now()); | 425 cache_.FindDnsRecords(rrtype, name, records, base::Time::Now()); |
| 435 } | 426 } |
| 436 | 427 |
| 437 MDnsClientImpl::MDnsClientImpl( | 428 MDnsClientImpl::MDnsClientImpl() { |
| 438 scoped_ptr<MDnsConnection::SocketFactory> socket_factory) | |
| 439 : socket_factory_(socket_factory.Pass()) { | |
| 440 } | 429 } |
| 441 | 430 |
| 442 MDnsClientImpl::~MDnsClientImpl() { | 431 MDnsClientImpl::~MDnsClientImpl() { |
| 443 } | 432 } |
| 444 | 433 |
| 445 bool MDnsClientImpl::StartListening() { | 434 bool MDnsClientImpl::StartListening(MDnsSocketFactory* socket_factory) { |
| 446 DCHECK(!core_.get()); | 435 DCHECK(!core_.get()); |
| 447 core_.reset(new Core(this)); | 436 core_.reset(new Core(this)); |
| 448 if (!core_->Init(socket_factory_.get())) { | 437 if (!core_->Init(socket_factory)) { |
| 449 core_.reset(); | 438 core_.reset(); |
| 450 return false; | 439 return false; |
| 451 } | 440 } |
| 452 return true; | 441 return true; |
| 453 } | 442 } |
| 454 | 443 |
| 455 void MDnsClientImpl::StopListening() { | 444 void MDnsClientImpl::StopListening() { |
| 456 core_.reset(); | 445 core_.reset(); |
| 457 } | 446 } |
| 458 | 447 |
| (...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 664 | 653 |
| 665 void MDnsTransactionImpl::OnNsecRecord(const std::string& name, unsigned type) { | 654 void MDnsTransactionImpl::OnNsecRecord(const std::string& name, unsigned type) { |
| 666 TriggerCallback(RESULT_NSEC, NULL); | 655 TriggerCallback(RESULT_NSEC, NULL); |
| 667 } | 656 } |
| 668 | 657 |
| 669 void MDnsTransactionImpl::OnCachePurged() { | 658 void MDnsTransactionImpl::OnCachePurged() { |
| 670 // TODO(noamsml): Cache purge situations not yet implemented | 659 // TODO(noamsml): Cache purge situations not yet implemented |
| 671 } | 660 } |
| 672 | 661 |
| 673 } // namespace net | 662 } // namespace net |
| OLD | NEW |