1 // Copyright 2018 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 <algorithm>
6 #include <cmath>
7 #include <numeric>
8 #include <queue>
9 #include <utility>
10 
11 #include "services/network/mdns_responder.h"
12 
13 #include "base/big_endian.h"
14 #include "base/bind.h"
15 #include "base/guid.h"
16 #include "base/logging.h"
17 #include "base/metrics/histogram_macros.h"
18 #include "base/numerics/safe_conversions.h"
19 #include "base/rand_util.h"
20 #include "base/stl_util.h"
21 #include "base/strings/stringprintf.h"
22 #include "base/sys_byteorder.h"
23 #include "base/threading/sequenced_task_runner_handle.h"
24 #include "base/time/default_tick_clock.h"
25 #include "base/timer/timer.h"
26 #include "net/base/address_family.h"
27 #include "net/base/io_buffer.h"
28 #include "net/base/ip_address.h"
29 #include "net/base/net_errors.h"
30 #include "net/dns/dns_response.h"
31 #include "net/dns/dns_util.h"
32 #include "net/dns/mdns_client.h"
33 #include "net/dns/public/dns_protocol.h"
34 #include "net/dns/public/util.h"
35 #include "net/dns/record_parsed.h"
36 #include "net/dns/record_rdata.h"
37 #include "net/socket/datagram_server_socket.h"
38 #include "net/socket/udp_server_socket.h"
39 #include "services/network/public/cpp/features.h"
40 
41 // TODO(qingsi): Several features to implement:
42 //
43 // 1) Support parsing a query with multiple questions in the wire format to a
44 // DnsQuery, and bundle answers to questions in a single DnsResponse with proper
45 // rate limiting.
46 //
47 // 2) Support detecting queries for the same record within the minimal interval
48 // between responses and allow at most one response queued by the scheduler at a
49 // time for each name.
50 //
51 // 3) Support parsing the authority section of a query in the wire format to
52 // correctly implement the detection of probe queries.
53 namespace network {
54 
55 namespace {
56 
57 using MdnsResponderServiceError = MdnsResponderManager::ServiceError;
58 
59 // RFC 6762, Section 6.
60 //
61 // The multicast of responses of the same record on an interface must be at
62 // least one second apart on that particular interface.
63 const base::TimeDelta kMinIntervalBetweenSameRecord =
64     base::TimeDelta::FromSeconds(1);
65 
66 const base::TimeDelta kMinIntervalBetweenMdnsResponses =
67     base::TimeDelta::FromSeconds(1);
68 
69 // RFC 6762, Section 10.
70 const base::TimeDelta kDefaultTtlForRecordWithHostname =
71     base::TimeDelta::FromSeconds(120);
72 
73 // RFC 6762, Section 8.3.
74 const int kMinNumAnnouncementsToSend = 2;
75 
76 // Maximum number of retries for the same response due to send failure.
77 const uint8_t kMaxMdnsResponseRetries = 2;
78 // The capacity of the send queue for packets blocked by an incomplete send.
79 const uint8_t kSendQueueCapacity = 100;
80 // Maximum delay allowed for per-response rate-limited responses.
81 const base::TimeDelta kMaxScheduledDelay = base::TimeDelta::FromSeconds(10);
82 
83 // The query name of the mDNS name generator service.
84 const char kMdnsNameGeneratorServiceInstanceName[] =
85     "Generated-Names._mdns_name_generator._udp.local";
86 
87 // RFC 6763, the TXT record is recommended to be under 1300 bytes to fit in a
88 // single 1500-byte Ethernet packet.
89 //
90 // Currently we only construct a TXT record in the response to an mDNS name
91 // generator service query. The record consists of a list of owned names, and
92 // this list is truncated as necessary to stay within the size limit. See
93 // |CreateTxtRdataWithNames| below for the detail.
94 const uint16_t kMaxTxtRecordSizeInBytes = 1300;
95 // RFC 6763, Section 6.4, the key in a kv pair in a DNS-SD TXT record should be
96 // no more than 9 characters long.
97 const int kMaxKeySizeInTxtRecord = 9;
98 // The prefix of the key used in the TXT record to list mDNS names.
99 const char kKeyPrefixInTxtRecord[] = "name";
100 // Version tag in the TXT record.
101 const char kTxtversLine[] = "\x9txtvers=1";
102 
103 // RFC 6762, Section 6, a response that may contain an answer as a member of a
104 // shared resource record set, should be delayed uniformly and randomly in the
105 // range of 20-120 ms. This delay is applied in addition to the scheduled delay
106 // by rate limiting.
107 const base::TimeDelta kMinRandDelayForSharedResult =
108     base::TimeDelta::FromMilliseconds(20);
109 const base::TimeDelta kMaxRandDelayForSharedResult =
110     base::TimeDelta::FromMilliseconds(120);
111 
112 class RandomUuidNameGenerator
113     : public network::MdnsResponderManager::NameGenerator {
114  public:
CreateName()115   std::string CreateName() override { return base::GenerateGUID(); }
116 };
117 
QueryTypeAndAddressFamilyAreCompatible(uint16_t qtype,net::AddressFamily af)118 bool QueryTypeAndAddressFamilyAreCompatible(uint16_t qtype,
119                                             net::AddressFamily af) {
120   switch (qtype) {
121     case net::dns_protocol::kTypeA:
122       return af == net::ADDRESS_FAMILY_IPV4;
123     case net::dns_protocol::kTypeAAAA:
124       return af == net::ADDRESS_FAMILY_IPV6;
125     case net::dns_protocol::kTypeANY:
126       return af == net::ADDRESS_FAMILY_IPV4 || af == net::ADDRESS_FAMILY_IPV6;
127     default:
128       return false;
129   }
130 }
131 
132 // Creates a vector of A or AAAA records, where the name field of each record is
133 // given by the name in |name_addr_map|, and its mapped address is used to
134 // construct the RDATA stored in |DnsResourceRecord::owned_rdata|. |ttl|
135 // specifies the TTL of each record. With the owned RDATA, the returned records
136 // can be later used to construct a DnsResponse.
CreateAddressResourceRecords(const std::map<std::string,net::IPAddress> & name_addr_map,const base::TimeDelta & ttl)137 std::vector<net::DnsResourceRecord> CreateAddressResourceRecords(
138     const std::map<std::string, net::IPAddress>& name_addr_map,
139     const base::TimeDelta& ttl) {
140   std::vector<net::DnsResourceRecord> address_records;
141   for (const auto& name_addr_pair : name_addr_map) {
142     const auto& ip = name_addr_pair.second;
143     DCHECK(ip.IsIPv4() || ip.IsIPv6());
144     net::DnsResourceRecord record;
145     record.name = name_addr_pair.first;
146     record.type = (ip.IsIPv4() ? net::dns_protocol::kTypeA
147                                : net::dns_protocol::kTypeAAAA);
148     // Set the cache-flush bit to assert that this information is the truth and
149     // the whole truth.
150     record.klass =
151         net::dns_protocol::kClassIN | net::dns_protocol::kFlagCacheFlush;
152     // TTL in a resource record is 32-bit.
153     record.ttl = base::checked_cast<uint32_t>(ttl.InSeconds());
154     record.SetOwnedRdata(net::IPAddressToPackedString(ip));
155     address_records.push_back(std::move(record));
156   }
157   return address_records;
158 }
159 
160 // Creates an NSEC record RDATA in the wire format for the resource record type
161 // that corresponds to the address family of |addr|. The type bit map in the
162 // RDATA asserts the existence of only the address record that matches |addr|.
163 // Per RFC 3845 Section 2.1 and RFC 6762 Section 6, each RDATA has its Next
164 // Domain Name as a two-octet pointer to the name field of the NSEC resource
165 // record. |containing_nsec_rr_offset| defines the offset in the message of the
166 // NSEC resource record that would contain the returned RDATA, and its value is
167 // used to generate the correct pointer for Next Domain Name.
CreateNsecRdata(const net::IPAddress & addr,uint16_t containing_nsec_rr_offset)168 std::string CreateNsecRdata(const net::IPAddress& addr,
169                             uint16_t containing_nsec_rr_offset) {
170   DCHECK(addr.IsIPv4() || addr.IsIPv6());
171   // Each NSEC rdata in our negative response is given by 5 octets and 8
172   // octets for type A and type AAAA records, respectively:
173   //
174   // 2 octets for Next Domain Name as a pointer to the name field
175   // (DnsResourceRecord::name) of the NSEC record that will contain this RDATA;
176   // 1 octet for Window Block, which is always 0;
177   // 1 octet for Bitmap Length with value X, where X=1 for type A and X=4 for
178   // type AAAA;
179   // X octet(s) for Bitmap, 0x40 for type A and 0x00000008 for type AAAA.
180   std::string next_domain_name =
181       net::CreateNamePointer(containing_nsec_rr_offset);
182   DCHECK_EQ(2u, next_domain_name.size());
183   if (addr.IsIPv4())
184     return next_domain_name + std::string("\x00\x01\x40", 3);
185 
186   return next_domain_name + std::string("\x00\x04\x00\x00\x00\x08", 6);
187 }
188 
189 // Creates a vector of NSEC records, where the name field of each record is
190 // given by the name in |name_addr_map|, and its mapped address is used to
191 // construct the RDATA stored in |DnsResourceRecord::owned_rdata| via
192 // CreateNsecRdata above. With the owned RDATA, the returned records can be
193 // later used to construct a DnsResponse.
CreateNsecResourceRecords(const std::map<std::string,net::IPAddress> & name_addr_map,uint16_t first_nsec_rr_offset)194 std::vector<net::DnsResourceRecord> CreateNsecResourceRecords(
195     const std::map<std::string, net::IPAddress>& name_addr_map,
196     uint16_t first_nsec_rr_offset) {
197   std::vector<net::DnsResourceRecord> nsec_records;
198   uint16_t cur_rr_offset = first_nsec_rr_offset;
199   for (const auto& name_addr_pair : name_addr_map) {
200     net::DnsResourceRecord record;
201     record.name = name_addr_pair.first;
202     record.type = net::dns_protocol::kTypeNSEC;
203     // Set the cache-flush bit to assert that this information is the truth and
204     // the whole truth.
205     record.klass =
206         net::dns_protocol::kClassIN | net::dns_protocol::kFlagCacheFlush;
207     // RFC 6762, Section 6.1. TTL should be the same as that of what the record
208     // would have.
209     record.ttl = kDefaultTtlForRecordWithHostname.InSeconds();
210     record.SetOwnedRdata(CreateNsecRdata(name_addr_pair.second, cur_rr_offset));
211     cur_rr_offset += record.CalculateRecordSize();
212     nsec_records.push_back(std::move(record));
213   }
214   return nsec_records;
215 }
216 
217 // Creates TXT RDATA as a list of key-value pairs subject to a size limit. The
218 // key is in the format "name0", "name1" and so on, and the value is the name.
CreateTxtRdataWithNames(const std::set<std::string> & names,uint16_t txt_rdata_size_limit)219 std::string CreateTxtRdataWithNames(const std::set<std::string>& names,
220                                     uint16_t txt_rdata_size_limit) {
221   DCHECK(!names.empty());
222   DCHECK_GT(txt_rdata_size_limit, sizeof(kTxtversLine));
223   int remaining_budget =
224       txt_rdata_size_limit - sizeof(kTxtversLine) + 1 /* null terminator */;
225   std::string txt_rdata;
226   size_t prev_txt_rdata_size = 0;
227   uint16_t idx = 0;
228   for (const std::string& name : names) {
229     const int key_size =
230         sizeof(kKeyPrefixInTxtRecord) - 1 /* null terminator */ +
231         (idx > 0 ? static_cast<int>(log10(static_cast<double>(idx))) + 1 : 1);
232     // RFC 6763, Section 6.4, the key should be no more than nine characters
233     // long.
234     DCHECK_LE(key_size, kMaxKeySizeInTxtRecord);
235     // Each TXT line consists of a length octet followed by as many characters,
236     // and as a result each line cannot exceed 256 characters.
237     const int line_size =
238         2 /* length octet and "=" sign */ + key_size + name.size();
239     // Each name should be guaranteed to have no more than 245 characters to
240     // meet the line length limit. See the comment before |NameGenerator|.
241     DCHECK_LE(line_size - 1, std::numeric_limits<uint8_t>::max());
242     remaining_budget -= line_size;
243     if (remaining_budget <= 0) {
244       VLOG(1) << "TXT RDATA size limit exceeded. Stopped appending lines in "
245                  "the response.";
246       break;
247     }
248 
249     // Note that c_str() is null terminated.
250     //
251     // E.g. \x13name0=example.local
252     base::StringAppendF(&txt_rdata, "%c%s%d=%s", line_size - 1,
253                         kKeyPrefixInTxtRecord, idx, name.c_str());
254     DCHECK_EQ(txt_rdata.size(), prev_txt_rdata_size + line_size);
255     prev_txt_rdata_size = txt_rdata.size();
256     ++idx;
257   }
258 
259   DCHECK(!txt_rdata.empty());
260   // Note that the size of the version tag line has been deducted from the
261   // budget before we add lines of names.
262   txt_rdata += kTxtversLine;
263 
264   return txt_rdata;
265 }
266 
CreateTxtRecordWithNames(const base::TimeDelta & ttl,const std::string & service_instance_name,const std::set<std::string> & names)267 net::DnsResourceRecord CreateTxtRecordWithNames(
268     const base::TimeDelta& ttl,
269     const std::string& service_instance_name,
270     const std::set<std::string>& names) {
271   net::DnsResourceRecord txt;
272   txt.name = service_instance_name;
273   txt.type = net::dns_protocol::kTypeTXT;
274   // The cache-flush bit is not set so that the responses from other Chrome
275   // instances are not considered conflicts. See the conflict detection in
276   // |SocketHandler::HandlePacket|.
277   txt.klass = net::dns_protocol::kClassIN;
278   // TTL in a resource record is 32-bit.
279   txt.ttl = base::checked_cast<uint32_t>(ttl.InSeconds());
280   uint16_t txt_rdata_size_limit =
281       kMaxTxtRecordSizeInBytes - service_instance_name.size() -
282       net::dns_protocol::kResourceRecordSizeInBytesWithoutNameAndRData;
283   txt.SetOwnedRdata(CreateTxtRdataWithNames(names, txt_rdata_size_limit));
284   return txt;
285 }
286 
IsProbeQuery(const net::DnsQuery & query)287 bool IsProbeQuery(const net::DnsQuery& query) {
288   // TODO(qingsi): RFC 6762, the proper way to detect a probe query is
289   // to check if
290   //
291   // 1) its qtype is ANY (Section 8.1) and
292   // 2) it "contains a proposed record in the Authority Section that
293   // answers the question in the Question Section" (Section 6).
294   //
295   // Currently DnsQuery does not support the Authority section. Fix it.
296   return query.qtype() == net::dns_protocol::kTypeANY;
297 }
298 
ReportServiceError(MdnsResponderServiceError error)299 void ReportServiceError(MdnsResponderServiceError error) {
300   UMA_HISTOGRAM_ENUMERATION("NetworkService.MdnsResponder.ServiceError", error);
301 }
302 
303 struct PendingPacket {
PendingPacketnetwork::__anon8b1c82230111::PendingPacket304   PendingPacket(scoped_refptr<net::IOBufferWithSize> buf,
305                 scoped_refptr<MdnsResponseSendOption> option,
306                 const base::TimeTicks& send_ready_time)
307       : buf(std::move(buf)),
308         option(std::move(option)),
309         send_ready_time(send_ready_time) {}
310 
operator <network::__anon8b1c82230111::PendingPacket311   bool operator<(const PendingPacket& other) const {
312     return send_ready_time > other.send_ready_time;
313   }
314 
315   scoped_refptr<net::IOBufferWithSize> buf;
316   scoped_refptr<MdnsResponseSendOption> option;
317   base::TimeTicks send_ready_time;
318 };
319 
320 // Returns a random TimeDelta between |min| and |max| following the uniform
321 // distribution.
GetRandTimeDelta(const base::TimeDelta & min,const base::TimeDelta & max)322 base::TimeDelta GetRandTimeDelta(const base::TimeDelta& min,
323                                  const base::TimeDelta& max) {
324   DCHECK_LE(min, max);
325   return base::TimeDelta::FromMicroseconds(
326       base::RandInt(min.InMicroseconds(), max.InMicroseconds()));
327 }
328 
329 }  // namespace
330 
331 
332 namespace mdns_helper {
333 
CreateResolutionResponse(const base::TimeDelta & ttl,const std::map<std::string,net::IPAddress> & name_addr_map)334 scoped_refptr<net::IOBufferWithSize> CreateResolutionResponse(
335     const base::TimeDelta& ttl,
336     const std::map<std::string, net::IPAddress>& name_addr_map) {
337   DCHECK(!name_addr_map.empty());
338   std::vector<net::DnsResourceRecord> answers =
339       CreateAddressResourceRecords(name_addr_map, ttl);
340   std::vector<net::DnsResourceRecord> additional_records;
341   if (!ttl.is_zero()) {
342     uint16_t cur_size = std::accumulate(
343         answers.begin(), answers.end(), sizeof(net::dns_protocol::Header),
344         [](size_t cur_size, const net::DnsResourceRecord& answer) {
345           return cur_size + answer.CalculateRecordSize();
346         });
347     additional_records = CreateNsecResourceRecords(name_addr_map, cur_size);
348   }
349 
350   // RFC 6762.
351   //
352   // Section 6. mDNS responses MUST NOT contain any questions.
353   // Section 18.1. In mDNS responses, ID MUST be set to zero.
354   net::DnsResponse response(0 /* id */, true /* is_authoritative */, answers,
355                             {} /* authority_records */, additional_records,
356                             base::nullopt /* query */);
357   DCHECK(response.io_buffer() != nullptr);
358   auto buf =
359       base::MakeRefCounted<net::IOBufferWithSize>(response.io_buffer_size());
360   memcpy(buf->data(), response.io_buffer()->data(), response.io_buffer_size());
361   return buf;
362 }
363 
CreateNegativeResponse(const std::map<std::string,net::IPAddress> & name_addr_map)364 scoped_refptr<net::IOBufferWithSize> CreateNegativeResponse(
365     const std::map<std::string, net::IPAddress>& name_addr_map) {
366   DCHECK(!name_addr_map.empty());
367   std::vector<net::DnsResourceRecord> nsec_records = CreateNsecResourceRecords(
368       name_addr_map, sizeof(net::dns_protocol::Header));
369   std::vector<net::DnsResourceRecord> additional_records =
370       CreateAddressResourceRecords(name_addr_map,
371                                    kDefaultTtlForRecordWithHostname);
372   net::DnsResponse response(0 /* id */, true /* is_authoritative */,
373                             nsec_records, {} /* authority_records */,
374                             additional_records, base::nullopt /* query */);
375   DCHECK(response.io_buffer() != nullptr);
376   auto buf =
377       base::MakeRefCounted<net::IOBufferWithSize>(response.io_buffer_size());
378   memcpy(buf->data(), response.io_buffer()->data(), response.io_buffer_size());
379   return buf;
380 }
381 
382 scoped_refptr<net::IOBufferWithSize>
CreateResponseToMdnsNameGeneratorServiceQuery(const base::TimeDelta & ttl,const std::set<std::string> & mdns_names)383 CreateResponseToMdnsNameGeneratorServiceQuery(
384     const base::TimeDelta& ttl,
385     const std::set<std::string>& mdns_names) {
386   std::vector<net::DnsResourceRecord> answers(
387       1, CreateTxtRecordWithNames(ttl, kMdnsNameGeneratorServiceInstanceName,
388                                   mdns_names));
389 
390   net::DnsResponse response(0 /* id */, true /* is_authoritative */, answers,
391                             {} /* authority_records */,
392                             {} /* additional_records */,
393                             base::nullopt /* query */);
394   DCHECK(response.io_buffer() != nullptr);
395   auto buf =
396       base::MakeRefCounted<net::IOBufferWithSize>(response.io_buffer_size());
397   memcpy(buf->data(), response.io_buffer()->data(), response.io_buffer_size());
398   return buf;
399 }
400 
401 }  // namespace mdns_helper
402 
403 class MdnsResponderManager::SocketHandler {
404  public:
SocketHandler(uint16_t id,std::unique_ptr<net::DatagramServerSocket> socket,MdnsResponderManager * responder_manager)405   SocketHandler(uint16_t id,
406                 std::unique_ptr<net::DatagramServerSocket> socket,
407                 MdnsResponderManager* responder_manager)
408       : id_(id),
409         scheduler_(std::make_unique<ResponseScheduler>(this)),
410         socket_(std::move(socket)),
411         responder_manager_(responder_manager),
412         io_buffer_(base::MakeRefCounted<net::IOBufferWithSize>(
413             net::dns_protocol::kMaxMulticastSize + 1)) {}
414   ~SocketHandler() = default;
415 
Start()416   int Start() {
417     net::IPEndPoint end_point;
418     int rv = socket_->GetLocalAddress(&end_point);
419     if (rv != net::OK) {
420       return rv;
421     }
422     DCHECK(end_point.GetFamily() == net::ADDRESS_FAMILY_IPV4 ||
423            end_point.GetFamily() == net::ADDRESS_FAMILY_IPV6);
424     multicast_addr_ =
425         net::dns_util::GetMdnsGroupEndPoint(end_point.GetFamily());
426     int result = DoReadLoop();
427     if (result == net::ERR_IO_PENDING) {
428       // An in-progress read loop is considered a completed start.
429       return net::OK;
430     }
431     return result;
432   }
433 
434   // Returns true if the send is successfully scheduled after rate limiting on
435   // the underlying interface, and false otherwise.
436   bool Send(scoped_refptr<net::IOBufferWithSize> buf,
437             scoped_refptr<MdnsResponseSendOption> option);
438 
439   // Returns a net error code, or ERR_IO_PENDING if the IO is in progress.
440   int DoSend(PendingPacket pending_packet);
441 
id() const442   uint16_t id() const { return id_; }
443 
444   void SetTickClockForTesting(const base::TickClock* tick_clock);
445 
446  private:
447   class ResponseScheduler;
448 
449   // Returns the effective result after handling. In particular, if |result|
450   // represents a non-fatal error that is not ERR_IO_PENDING, it will be
451   // converted to net::OK and returned.
452   int HandlePacket(int result);
453 
DoReadLoop()454   int DoReadLoop() {
455     int result;
456     do {
457       // Using base::Unretained(this) is safe because the CompletionOnceCallback
458       // is automatically cancelled when |socket_| is destroyed, and the latter
459       // is owned by |this|.
460       result = socket_->RecvFrom(
461           io_buffer_.get(), io_buffer_->size(), &recv_addr_,
462           base::BindOnce(&MdnsResponderManager::SocketHandler::OnRead,
463                          base::Unretained(this)));
464       // Process synchronous return from RecvFrom.
465       result = HandlePacket(result);
466     } while (result >= 0);
467 
468     // Note that since |HandlePacket| converts a non-fatal error that is not
469     // ERR_IO_PENDING to OK, |result| returned is either ERR_IO_PENDING or a
470     // fatal error.
471     return result;
472   }
473 
474   // For the methods below, |result| indicates the number of bytes read if
475   // positive, or a network stack error code if negative. Zero indicates either
476   // net::OK or zero bytes read.
OnRead(int result)477   void OnRead(int result) {
478     result = HandlePacket(result);
479     DCHECK_NE(result, net::ERR_IO_PENDING);
480 
481     if (result >= 0)
482       result = DoReadLoop();
483 
484     if (result == net::ERR_IO_PENDING)
485       return;
486 
487     DCHECK(responder_manager_->IsFatalError(result));
488     responder_manager_->OnSocketHandlerReadError(id_, result);
489   }
490 
491   uint16_t id_;
492   std::unique_ptr<ResponseScheduler> scheduler_;
493   std::unique_ptr<net::DatagramServerSocket> socket_;
494   // A back pointer to the responder manager that owns this socket handler. The
495   // handler should be destroyed before |responder_manager_| becomes invalid or
496   // a weak reference should be used to access the manager when there is no such
497   // guarantee in an operation.
498   MdnsResponderManager* const responder_manager_;
499   scoped_refptr<net::IOBufferWithSize> io_buffer_;
500   net::IPEndPoint recv_addr_;
501   net::IPEndPoint multicast_addr_;
502 
503   base::WeakPtrFactory<SocketHandler> weak_factory_{this};
504 
505   DISALLOW_COPY_AND_ASSIGN(SocketHandler);
506 };
507 
508 // Implements the rate limiting schemes for sending responses as defined by
509 // RateLimitScheme. Specifically:
510 //
511 // 1. Announcements for new names (RFC 6762, Section 8.3) and goodbyes (RFC
512 // 6762, Section 10.1) are rate limited per response on each interface, so that
513 // the interval between sending the above responses is no less than one second
514 // on the given interface.
515 //
516 // 2. Responses containing resource records for name resolution, and also
517 // negative responses to queries for non-existing records of generated names,
518 // are rate limited per record. The delay of such a response from the last
519 // per-record rate limited response is computed as the maximum delay of all
520 // records (names) contained. Per RFC 6762, Section 6, records are sent at a
521 // maximum rate of one per each second.
522 //
523 // 3. Responses to probing queries (RFC 6762, Section 8.1) are not rate
524 // limited.
525 //
526 // Also, if the projected delay of a response exceeds the maximum scheduled
527 // delay given by kMaxScheduledDelay, the response is NOT scheduled.
528 class MdnsResponderManager::SocketHandler::ResponseScheduler {
529  public:
530   enum class RateLimitScheme {
531     // The next response will be sent at least after
532     // kMinIntervalBetweenResponses since the last response that is rate limited
533     // by the per-response scheme.
534     PER_RESPONSE,
535     // The delay of the response from the last one that is rate limited by the
536     // per-record scheme, is computed as the maximum delay of all its records
537     // (identified by names). The multicast of each record is separated by at
538     // least kMinIntervalBetweenSameRecord.
539     PER_RECORD,
540     // The response is sent immediately.
541     NO_LIMIT,
542   };
543 
ResponseScheduler(MdnsResponderManager::SocketHandler * handler)544   explicit ResponseScheduler(MdnsResponderManager::SocketHandler* handler)
545       : handler_(handler),
546         tick_clock_(base::DefaultTickClock::GetInstance()),
547         dispatch_timer_(std::make_unique<base::OneShotTimer>(tick_clock_)),
548         next_available_time_per_resp_sched_(tick_clock_->NowTicks()) {}
~ResponseScheduler()549   ~ResponseScheduler() { dispatch_timer_->Stop(); }
550 
551   // Implements the rate limit scheme on the underlying interface managed by
552   // |handler_|. Returns true if the send is scheduled on this interface.
553   //
554   // Pending sends scheduled are cancelled after |handler_| becomes invalid;
555   bool ScheduleNextSend(scoped_refptr<net::IOBufferWithSize> buf,
556                         scoped_refptr<MdnsResponseSendOption> option);
OnResponseSent(PendingPacket pending_packet,int result)557   void OnResponseSent(PendingPacket pending_packet, int result) {
558     DCHECK(send_pending_);
559     send_pending_ = false;
560     scoped_refptr<MdnsResponseSendOption>& option = pending_packet.option;
561     if (result < 0) {
562       VLOG(1) << "Socket send error, socket=" << handler_->id()
563               << ", error=" << result;
564       if (CanBeRetriedAfterSendFailure(*option)) {
565         ++option->num_send_retries_done;
566         send_queue_.push(std::move(pending_packet));
567       } else {
568         VLOG(1) << "Response cannot be sent after " << kMaxMdnsResponseRetries
569                 << " retries.";
570       }
571     }
572     DispatchPendingPackets();
573   }
574 
575   // Also resets the scheduler.
SetTickClockForTesting(const base::TickClock * tick_clock)576   void SetTickClockForTesting(const base::TickClock* tick_clock) {
577     tick_clock_ = tick_clock;
578     dispatch_timer_ = std::make_unique<base::OneShotTimer>(tick_clock_);
579     next_available_time_per_resp_sched_ = tick_clock_->NowTicks();
580     next_available_time_for_name_.clear();
581   }
582 
GetWeakPtr()583   base::WeakPtr<ResponseScheduler> GetWeakPtr() {
584     return weak_factory_.GetWeakPtr();
585   }
586 
587  private:
GetRateLimitSchemeForClass(MdnsResponseSendOption::ResponseClass klass)588   RateLimitScheme GetRateLimitSchemeForClass(
589       MdnsResponseSendOption::ResponseClass klass) {
590     switch (klass) {
591       case MdnsResponseSendOption::ResponseClass::ANNOUNCEMENT:
592       case MdnsResponseSendOption::ResponseClass::GOODBYE:
593         return RateLimitScheme::PER_RESPONSE;
594       case MdnsResponseSendOption::ResponseClass::NEGATIVE:
595       case MdnsResponseSendOption::ResponseClass::REGULAR_RESOLUTION:
596         return RateLimitScheme::PER_RECORD;
597       case MdnsResponseSendOption::ResponseClass::PROBE_RESOLUTION:
598         return RateLimitScheme::NO_LIMIT;
599       case MdnsResponseSendOption::ResponseClass::UNSPECIFIED:
600         NOTREACHED();
601         return RateLimitScheme::PER_RESPONSE;
602     }
603   }
604   // Returns null if the computed delay exceeds kMaxScheduledDelay and the next
605   // available time is not updated.
606   base::Optional<base::TimeDelta>
607   ComputeResponseDelayAndUpdateNextAvailableTime(
608       RateLimitScheme rate_limit_scheme,
609       const MdnsResponseSendOption& option);
610 
611   // Dispatches packets in the send queue serially with retries.
612   void DispatchPendingPackets();
613 
614   // Determines if a response can be retried after send failure.
CanBeRetriedAfterSendFailure(const MdnsResponseSendOption & option)615   bool CanBeRetriedAfterSendFailure(const MdnsResponseSendOption& option) {
616     if (option.num_send_retries_done >= kMaxMdnsResponseRetries)
617       return false;
618 
619     if (option.klass == MdnsResponseSendOption::ResponseClass::ANNOUNCEMENT ||
620         option.klass == MdnsResponseSendOption::ResponseClass::GOODBYE ||
621         option.klass == MdnsResponseSendOption::ResponseClass::PROBE_RESOLUTION)
622       return true;
623 
624     return false;
625   }
626 
627   // A back pointer to the socket handler that owns this scheduler. The
628   // scheduler should be destroyed before |handler_| becomes invalid or a weak
629   // reference should be used to access the handler when there is no such
630   // guarantee in an operation.
631   MdnsResponderManager::SocketHandler* const handler_;
632   const base::TickClock* tick_clock_;
633   std::unique_ptr<base::OneShotTimer> dispatch_timer_;
634   std::map<std::string, base::TimeTicks> next_available_time_for_name_;
635   base::TimeTicks next_available_time_per_resp_sched_;
636   bool send_pending_ = false;
637   // Packets with earlier ready time have higher priorities.
638   std::priority_queue<PendingPacket> send_queue_;
639 
640   base::WeakPtrFactory<ResponseScheduler> weak_factory_{this};
641 
642   DISALLOW_COPY_AND_ASSIGN(ResponseScheduler);
643 };
644 
Send(scoped_refptr<net::IOBufferWithSize> buf,scoped_refptr<MdnsResponseSendOption> option)645 bool MdnsResponderManager::SocketHandler::Send(
646     scoped_refptr<net::IOBufferWithSize> buf,
647     scoped_refptr<MdnsResponseSendOption> option) {
648   return scheduler_->ScheduleNextSend(std::move(buf), std::move(option));
649 }
650 
DoSend(PendingPacket pending_packet)651 int MdnsResponderManager::SocketHandler::DoSend(PendingPacket pending_packet) {
652   auto* buf_data = pending_packet.buf.get();
653   size_t buf_size = pending_packet.buf->size();
654   return socket_->SendTo(
655       buf_data, buf_size, multicast_addr_,
656       base::BindOnce(&ResponseScheduler::OnResponseSent,
657                      scheduler_->GetWeakPtr(), std::move(pending_packet)));
658 }
659 
SetTickClockForTesting(const base::TickClock * tick_clock)660 void MdnsResponderManager::SocketHandler::SetTickClockForTesting(
661     const base::TickClock* tick_clock) {
662   scheduler_->SetTickClockForTesting(tick_clock);
663 }
664 
ScheduleNextSend(scoped_refptr<net::IOBufferWithSize> buf,scoped_refptr<MdnsResponseSendOption> option)665 bool MdnsResponderManager::SocketHandler::ResponseScheduler::ScheduleNextSend(
666     scoped_refptr<net::IOBufferWithSize> buf,
667     scoped_refptr<MdnsResponseSendOption> option) {
668   if (send_queue_.size() >= kSendQueueCapacity) {
669     VLOG(1)
670         << "mDNS packet discarded after reaching the capacity of send queue.";
671     return false;
672   }
673 
674   auto rate_limit_scheme = GetRateLimitSchemeForClass(option->klass);
675   base::Optional<base::TimeDelta> delay;
676   if (rate_limit_scheme == RateLimitScheme::NO_LIMIT) {
677     // Skip the scheduling for this response. Currently the zero delay is only
678     // used for negative responses generated by the responder itself. Responses
679     // with positive name resolution generated by the responder and also those
680     // triggered via the Mojo connection (i.e. announcements and goodbye
681     // packets) are rate limited via the scheduled delay below.
682     delay = base::TimeDelta();
683   } else {
684     // TODO(qingsi): The computation of the delay is done statically below at
685     // schedule-time. Change it to computing dynamically so that the delay is
686     // based on the time of the last send completion.
687     delay = ComputeResponseDelayAndUpdateNextAvailableTime(rate_limit_scheme,
688                                                            *option);
689   }
690   if (!delay)
691     return false;
692 
693   PendingPacket pending_packet(std::move(buf), std::move(option),
694                                tick_clock_->NowTicks() + delay.value());
695   send_queue_.push(std::move(pending_packet));
696   DispatchPendingPackets();
697   return true;
698 }
699 
700 base::Optional<base::TimeDelta> MdnsResponderManager::SocketHandler::
ComputeResponseDelayAndUpdateNextAvailableTime(RateLimitScheme rate_limit_scheme,const MdnsResponseSendOption & option)701     ResponseScheduler::ComputeResponseDelayAndUpdateNextAvailableTime(
702         RateLimitScheme rate_limit_scheme,
703         const MdnsResponseSendOption& option) {
704   auto now = tick_clock_->NowTicks();
705   const auto extra_delay_for_shared_result =
706       option.shared_result ? GetRandTimeDelta(kMinRandDelayForSharedResult,
707                                               kMaxRandDelayForSharedResult)
708                            : base::TimeDelta();
709 
710   // RFC 6762 requires the rate limiting applied on a per-record basis. When a
711   // response contains multiple records, each identified by the name, we compute
712   // the delay as the maximum delay of records contained. See the definition of
713   // RateLimitScheme::PER_RECORD.
714   //
715   // For responses that are triggered via the Mojo connection, we perform more
716   // restrictive rate limiting on a per-response basis. See the
717   // definition of RateLimitScheme::PER_RESPONSE.
718   if (rate_limit_scheme == RateLimitScheme::PER_RESPONSE) {
719     auto delay =
720         std::max(next_available_time_per_resp_sched_ - now, base::TimeDelta()) +
721         extra_delay_for_shared_result;
722 
723     if (delay > kMaxScheduledDelay)
724       return base::nullopt;
725 
726     next_available_time_per_resp_sched_ =
727         now + delay + kMinIntervalBetweenMdnsResponses;
728     return delay;
729   }
730 
731   DCHECK(rate_limit_scheme == RateLimitScheme::PER_RECORD);
732   DCHECK(!option.names_for_rate_limit.empty());
733   auto next_available_time_for_response = now;
734   // TODO(qingsi): There are a couple of issues with computing the delay of a
735   // response as the maximum of each name contained and updating the next
736   // available time for each name accordingly.
737   //
738   // 1) It can unnecessarily delay the records with the names that are not
739   // backlogged in the schedule.
740   //
741   // 2) The update of the next available time following 1) further delays the
742   // future responses for these victim names, which could escalate the
743   // congestion until we start to drop the response after exceeding
744   // kMaxScheduledDelay.
745   //
746   // The root cause is we currently maintain a one-to-one mapping between
747   // queries and responses, such that a response answers the questions in the
748   // corresponding query entirely (note however that DnsQuery currently supports
749   // only a single question). We could mitigate this issue by splitting or
750   // merging responses. See the comment block at the beginning of this file
751   // about features to implement.
752   for (const auto& name : option.names_for_rate_limit) {
753     // The following computation assumes that we always send the address record
754     // and the negative record at the same time (as we do) for any given name.
755     next_available_time_for_response = std::max(
756         next_available_time_for_response, next_available_time_for_name_[name]);
757   }
758   base::TimeDelta delay =
759       std::max(next_available_time_for_response - now, base::TimeDelta()) +
760       extra_delay_for_shared_result;
761 
762   if (delay > kMaxScheduledDelay)
763     return base::nullopt;
764 
765   for (const auto& name : option.names_for_rate_limit) {
766     next_available_time_for_name_[name] =
767         next_available_time_for_response + kMinIntervalBetweenSameRecord;
768   }
769   return delay;
770 }
771 
772 void MdnsResponderManager::SocketHandler::ResponseScheduler::
DispatchPendingPackets()773     DispatchPendingPackets() {
774   while (!send_pending_ && !send_queue_.empty()) {
775     const auto now = tick_clock_->NowTicks();
776     const auto next_send_ready_time = send_queue_.top().send_ready_time;
777     if (now >= next_send_ready_time) {
778       auto pending_packet = std::move(send_queue_.top());
779       send_queue_.pop();
780       const auto& option = pending_packet.option;
781       if (option->cancelled_callback && option->cancelled_callback->Run())
782         continue;
783 
784       int rv = handler_->DoSend(std::move(pending_packet));
785       if (rv == net::ERR_IO_PENDING) {
786         send_pending_ = true;
787       } else if (rv < net::OK) {
788         VLOG(1) << "mDNS packet discarded due to socket send error, socket="
789                 << handler_->id() << ", error=" << rv;
790       }
791     } else {
792       // We have no packet due; post a task to flush the send queue later.
793       //
794       // Note that the owning handler of this scheduler may be removed if it
795       // encounters read error as we process in |OnSocketHandlerReadError|. We
796       // should guarantee any posted task can be cancelled if the scheduler goes
797       // away, which we do via the weak pointer.
798       const base::TimeDelta time_to_next_packet = next_send_ready_time - now;
799       dispatch_timer_->Start(
800           FROM_HERE, time_to_next_packet,
801           base::BindOnce(&MdnsResponderManager::SocketHandler::
802                              ResponseScheduler::DispatchPendingPackets,
803                          GetWeakPtr()));
804       return;
805     }
806   }
807 }
808 
809 MdnsResponseSendOption::MdnsResponseSendOption() = default;
810 MdnsResponseSendOption::~MdnsResponseSendOption() = default;
811 
MdnsResponderManager()812 MdnsResponderManager::MdnsResponderManager() : MdnsResponderManager(nullptr) {}
813 
MdnsResponderManager(net::MDnsSocketFactory * socket_factory)814 MdnsResponderManager::MdnsResponderManager(
815     net::MDnsSocketFactory* socket_factory)
816     : socket_factory_(socket_factory),
817       name_generator_(std::make_unique<RandomUuidNameGenerator>()) {
818   if (!socket_factory_) {
819     owned_socket_factory_ = net::MDnsSocketFactory::CreateDefault();
820     socket_factory_ = owned_socket_factory_.get();
821   }
822   Start();
823 }
824 
~MdnsResponderManager()825 MdnsResponderManager::~MdnsResponderManager() {
826   // Note that sending the goodbye is best-effort since it may have a non-zero
827   // delay because of backlogged responses from rate-limiting. Delayed send will
828   // be cancelled after the manager is destroyed.
829   SendGoodbyePacketForMdnsNameGeneratorServiceIfNecessary();
830   // When destroyed, each responder will send out Goodbye messages for owned
831   // names via the back pointer to the manager. As a result, we should destroy
832   // the remaining responders before the manager is destroyed.
833   responders_.clear();
834 }
835 
Start()836 void MdnsResponderManager::Start() {
837   VLOG(1) << "Starting mDNS responder manager.";
838   DCHECK(start_result_ == SocketHandlerStartResult::UNSPECIFIED);
839   DCHECK(socket_handler_by_id_.empty());
840   std::vector<std::unique_ptr<net::DatagramServerSocket>> sockets;
841   // Create and return only bound sockets.
842   socket_factory_->CreateSockets(&sockets);
843 
844   uint16_t next_available_id = 1;
845   for (std::unique_ptr<net::DatagramServerSocket>& socket : sockets) {
846     socket_handler_by_id_.emplace(
847         next_available_id,
848         std::make_unique<MdnsResponderManager::SocketHandler>(
849             next_available_id, std::move(socket), this));
850     ++next_available_id;
851   }
852 
853   for (auto it = socket_handler_by_id_.begin();
854        it != socket_handler_by_id_.end();) {
855     // Start to process untrusted input.
856     int rv = it->second->Start();
857     if (rv == net::OK) {
858       ++it;
859     } else {
860       VLOG(1) << "Start failed, socket=" << it->second->id()
861               << ", error=" << rv;
862       it = socket_handler_by_id_.erase(it);
863     }
864   }
865   size_t num_started_socket_handlers = socket_handler_by_id_.size();
866   if (socket_handler_by_id_.empty()) {
867     start_result_ = SocketHandlerStartResult::ALL_FAILURE;
868     LOG(ERROR) << "mDNS responder manager failed to start.";
869     ReportServiceError(MdnsResponderServiceError::kFailToStartManager);
870     return;
871   }
872 
873   if (num_started_socket_handlers == next_available_id) {
874     start_result_ = SocketHandlerStartResult::ALL_SUCCESS;
875     return;
876   }
877 
878   start_result_ = SocketHandlerStartResult::PARTIAL_SUCCESS;
879 }
880 
CreateMdnsResponder(mojo::PendingReceiver<mojom::MdnsResponder> receiver)881 void MdnsResponderManager::CreateMdnsResponder(
882     mojo::PendingReceiver<mojom::MdnsResponder> receiver) {
883   if (start_result_ == SocketHandlerStartResult::UNSPECIFIED ||
884       start_result_ == SocketHandlerStartResult::ALL_FAILURE) {
885     LOG(ERROR) << "The mDNS responder manager is not started yet.";
886     ReportServiceError(MdnsResponderServiceError::kFailToCreateResponder);
887     receiver = mojo::NullReceiver();
888     return;
889   }
890   auto responder = std::make_unique<MdnsResponder>(std::move(receiver), this);
891   responders_.insert(std::move(responder));
892 }
893 
Send(scoped_refptr<net::IOBufferWithSize> buf,scoped_refptr<MdnsResponseSendOption> option)894 bool MdnsResponderManager::Send(scoped_refptr<net::IOBufferWithSize> buf,
895                                 scoped_refptr<MdnsResponseSendOption> option) {
896   DCHECK(buf != nullptr);
897   bool all_success = true;
898   if (option->send_socket_handler_ids.empty()) {
899     for (auto& id_handler_pair : socket_handler_by_id_)
900       all_success &= id_handler_pair.second->Send(buf, option);
901 
902     return all_success;
903   }
904   for (auto id : option->send_socket_handler_ids) {
905     DCHECK(socket_handler_by_id_.find(id) != socket_handler_by_id_.end());
906     all_success &= socket_handler_by_id_[id]->Send(buf, option);
907   }
908   return all_success;
909 }
910 
OnMojoConnectionError(MdnsResponder * responder)911 void MdnsResponderManager::OnMojoConnectionError(MdnsResponder* responder) {
912   auto it = responders_.find(responder);
913   DCHECK(it != responders_.end());
914   responders_.erase(it);
915 }
916 
SetNameGeneratorForTesting(std::unique_ptr<MdnsResponderManager::NameGenerator> name_generator)917 void MdnsResponderManager::SetNameGeneratorForTesting(
918     std::unique_ptr<MdnsResponderManager::NameGenerator> name_generator) {
919   name_generator_ = std::move(name_generator);
920   for (auto& responder : responders_)
921     responder->SetNameGeneratorForTesting(name_generator_.get());
922 }
923 
SetTickClockForTesting(const base::TickClock * tick_clock)924 void MdnsResponderManager::SetTickClockForTesting(
925     const base::TickClock* tick_clock) {
926   for (auto& id_handler_pair : socket_handler_by_id_) {
927     id_handler_pair.second->SetTickClockForTesting(tick_clock);
928   }
929 }
930 
HandleAddressNameConflictIfAny(const std::map<std::string,std::set<net::IPAddress>> & external_maps)931 void MdnsResponderManager::HandleAddressNameConflictIfAny(
932     const std::map<std::string, std::set<net::IPAddress>>& external_maps) {
933   // Handle conflicts in names for address records.
934   for (const auto& name_to_addresses : external_maps) {
935     for (auto& responder : responders_) {
936       if (responder->HasConflictWithExternalResolution(
937               name_to_addresses.first, {name_to_addresses.second})) {
938         // In the rare case when we encounter conflicting resolutions for a
939         // randomly generated name, We close the connection and let the other
940         // side of the pipe observe and handle the error, which could possibly
941         // rebind to a responder and generate new names.
942         OnMojoConnectionError(responder.get());
943         // Since each name is uniquely owned by one instance of responders, we
944         // can stop searching for this name once we find one conflict.
945         break;
946       }
947     }
948   }
949 }
950 
HandleTxtNameConflict()951 void MdnsResponderManager::HandleTxtNameConflict() {
952   // We will no longer respond to queries to list the generated names. This also
953   // cancels the scheduled responses.
954   LOG(ERROR)
955       << "Stop responding to queries for the mDNS name generator service after "
956          "observing a name conflict from an external TXT record.";
957   should_respond_to_generator_service_query_ = false;
958 }
959 
OnMdnsQueryReceived(const net::DnsQuery & query,uint16_t recv_socket_handler_id)960 void MdnsResponderManager::OnMdnsQueryReceived(
961     const net::DnsQuery& query,
962     uint16_t recv_socket_handler_id) {
963   // TODO(qingsi): Ideally we should consolidate the handling of the service
964   // query using the same responder mechanism as after this block (i.e. there
965   // would be a responder owning the service instance name). The current
966   // responder only provides APIs to create address records, and hence limited
967   // to handle only such records. Once we have expanded the API surface to
968   // include the service publishing, the handling logic should be unified.
969   const std::string qname = net::DNSDomainToString(query.qname());
970   if (base::FeatureList::IsEnabled(
971           features::kMdnsResponderGeneratedNameListing)) {
972     if (should_respond_to_generator_service_query_ &&
973         qname == kMdnsNameGeneratorServiceInstanceName) {
974       HandleMdnsNameGeneratorServiceQuery(query, recv_socket_handler_id);
975       return;
976     }
977   }
978 
979   for (auto& responder : responders_)
980     responder->OnMdnsQueryReceived(query, recv_socket_handler_id);
981 }
982 
OnSocketHandlerReadError(uint16_t socket_handler_id,int result)983 void MdnsResponderManager::OnSocketHandlerReadError(uint16_t socket_handler_id,
984                                                     int result) {
985   VLOG(1) << "Socket read error, socket=" << socket_handler_id
986           << ", error=" << result;
987 
988   // We should not remove the socket handler for a non-fatal error.
989   DCHECK(IsFatalError(result));
990   auto it = socket_handler_by_id_.find(socket_handler_id);
991   DCHECK(it != socket_handler_by_id_.end());
992   // It is safe to remove the handler in error since the handler has exited the
993   // read loop and is done with |OnRead|.
994   socket_handler_by_id_.erase(it);
995   if (socket_handler_by_id_.empty()) {
996     LOG(ERROR)
997         << "All socket handlers failed. Restarting the mDNS responder manager.";
998     ReportServiceError(MdnsResponderServiceError::kFatalSocketHandlerError);
999     start_result_ = MdnsResponderManager::SocketHandlerStartResult::UNSPECIFIED;
1000     Start();
1001   }
1002 }
1003 
IsFatalError(int result)1004 bool MdnsResponderManager::IsFatalError(int result) {
1005   if (result >= 0)
1006     return false;
1007   if (result == net::ERR_MSG_TOO_BIG || result == net::ERR_IO_PENDING)
1008     return false;
1009 
1010   return true;
1011 }
1012 
HandleMdnsNameGeneratorServiceQuery(const net::DnsQuery & query,uint16_t recv_socket_handler_id)1013 void MdnsResponderManager::HandleMdnsNameGeneratorServiceQuery(
1014     const net::DnsQuery& query,
1015     uint16_t recv_socket_handler_id) {
1016   uint16_t qtype = query.qtype();
1017   if (qtype != net::dns_protocol::kTypeTXT && !IsProbeQuery(query)) {
1018     VLOG(1) << "The mDNS name generator service query is discarded. Only "
1019                "queries for TXT records or probe queries are supported.";
1020     return;
1021   }
1022 
1023   if (names_.empty()) {
1024     VLOG(1) << "The mDNS name generator service query is discarded. No "
1025                "registered names to respond.";
1026     return;
1027   }
1028 
1029   auto option = base::MakeRefCounted<MdnsResponseSendOption>();
1030   option->send_socket_handler_ids.insert(recv_socket_handler_id);
1031   option->names_for_rate_limit.insert(kMdnsNameGeneratorServiceInstanceName);
1032   if (IsProbeQuery(query)) {
1033     option->klass = MdnsResponseSendOption::ResponseClass::PROBE_RESOLUTION;
1034   } else {
1035     option->klass = MdnsResponseSendOption::ResponseClass::REGULAR_RESOLUTION;
1036   }
1037   // There can be other Chrome instances in the same network that would respond
1038   // to this query.
1039   option->shared_result = true;
1040   option->cancelled_callback = base::BindRepeating(
1041       [](base::WeakPtr<MdnsResponderManager> manager) {
1042         return !manager || !manager->should_respond_to_generator_service_query_;
1043       },
1044       weak_factory_.GetWeakPtr());
1045   Send(mdns_helper::CreateResponseToMdnsNameGeneratorServiceQuery(
1046            kDefaultTtlForRecordWithHostname, names_),
1047        std::move(option));
1048   names_in_last_generator_response_ = names_;
1049 }
1050 
1051 // TODO(qingsi): When the list of owned names are updated, if we have ever sent
1052 // a response to the generator service query, we should send a goodbye for the
1053 // stale list of names and an update to advertise the new list. See RFC 6762,
1054 // Section 8.4. Currently we only send the goodbye when the manager is
1055 // destroyed. See the destructor of the manager.
1056 void MdnsResponderManager::
SendGoodbyePacketForMdnsNameGeneratorServiceIfNecessary()1057     SendGoodbyePacketForMdnsNameGeneratorServiceIfNecessary() {
1058   if (names_in_last_generator_response_.empty())
1059     return;
1060 
1061   auto option = base::MakeRefCounted<MdnsResponseSendOption>();
1062   // Send on all interfaces by not setting the send socket.
1063   option->klass = MdnsResponseSendOption::ResponseClass::GOODBYE;
1064   // We do not set |shared_result| in the option for the goodbye to avoid the
1065   // random delay. The delay would guarantee the cancelling of the scheduled
1066   // send after the manager is destroyed.
1067   Send(mdns_helper::CreateResponseToMdnsNameGeneratorServiceQuery(
1068            base::TimeDelta(), names_in_last_generator_response_),
1069        std::move(option));
1070 }
1071 
HandlePacket(int result)1072 int MdnsResponderManager::SocketHandler::HandlePacket(int result) {
1073   if (result == 0 || result == net::ERR_IO_PENDING)
1074     return result;
1075   if (result < 0)
1076     return responder_manager_->IsFatalError(result) ? result : net::OK;
1077 
1078   net::DnsQuery query(io_buffer_.get());
1079   bool parsed_as_query = query.Parse(result);
1080   if (parsed_as_query) {
1081     responder_manager_->OnMdnsQueryReceived(query, id_);
1082     return result;
1083   }
1084 
1085   net::DnsResponse response(io_buffer_.get(), io_buffer_->size());
1086   if (!response.InitParseWithoutQuery(io_buffer_->size()) ||
1087       response.answer_count() == 0)
1088     return result;
1089 
1090   // There could be multiple records for the same name in the response.
1091   std::map<std::string, std::set<net::IPAddress>> external_address_maps;
1092   bool has_txt_record_conflict = false;
1093   auto parser = response.Parser();
1094   DCHECK_GT(response.answer_count(), 0u);
1095   for (size_t i = 0; i < response.answer_count(); ++i) {
1096     auto parsed_record =
1097         net::RecordParsed::CreateFrom(&parser, base::Time::Now());
1098     if (!parsed_record || !parsed_record->ttl())
1099       continue;
1100 
1101     switch (parsed_record->type()) {
1102       case net::ARecordRdata::kType:
1103         external_address_maps[parsed_record->name()].insert(
1104             parsed_record->rdata<net::ARecordRdata>()->address());
1105         break;
1106       case net::AAAARecordRdata::kType:
1107         external_address_maps[parsed_record->name()].insert(
1108             parsed_record->rdata<net::AAAARecordRdata>()->address());
1109         break;
1110       case net::TxtRecordRdata::kType: {
1111         if (parsed_record->name() == kMdnsNameGeneratorServiceInstanceName &&
1112             parsed_record->klass() & net::dns_protocol::kFlagCacheFlush)
1113           // TODO(qingsi): Do not share the instance name once we implement the
1114           // DNS-SD scheme for responding to service queries. For now we should
1115           // also validate that the TXT record follows the same key/value pair
1116           // scheme in |CreateTxtRdataWithNames| even if the cache-flush bit not
1117           // set.
1118           //
1119           // We currently allow Chrome instances to share the same instance name
1120           // for their lists of owned names, by not setting the cache-flush bit,
1121           // and hence the above conflict detection logic. If net::MdnsClient is
1122           // the intended receiver of these responses, it currently can not
1123           // merge the responses from multiple instances. Once we move to fully
1124           // implementing the DNS-SD scheme, this issue should be solved after
1125           // we use distinct instance names in the replied SRV and TXT records.
1126           has_txt_record_conflict = true;
1127         break;
1128       }
1129       default:
1130         break;
1131     }
1132   }
1133   responder_manager_->HandleAddressNameConflictIfAny(external_address_maps);
1134 
1135   if (has_txt_record_conflict)
1136     responder_manager_->HandleTxtNameConflict();
1137 
1138   return result;
1139 }
1140 
MdnsResponder(mojo::PendingReceiver<mojom::MdnsResponder> receiver,MdnsResponderManager * manager)1141 MdnsResponder::MdnsResponder(
1142     mojo::PendingReceiver<mojom::MdnsResponder> receiver,
1143     MdnsResponderManager* manager)
1144     : receiver_(this, std::move(receiver)),
1145       manager_(manager),
1146       name_generator_(manager_->name_generator()) {
1147   receiver_.set_disconnect_handler(
1148       base::BindOnce(&MdnsResponderManager::OnMojoConnectionError,
1149                      base::Unretained(manager_), this));
1150 }
1151 
~MdnsResponder()1152 MdnsResponder::~MdnsResponder() {
1153   for (const auto& name_addr_pair : name_addr_map_) {
1154     bool rv = manager_->RemoveName(name_addr_pair.first);
1155     DCHECK(rv);
1156   }
1157   SendGoodbyePacketForNameAddressMap(name_addr_map_);
1158 }
1159 
CreateNameForAddress(const net::IPAddress & address,mojom::MdnsResponder::CreateNameForAddressCallback callback)1160 void MdnsResponder::CreateNameForAddress(
1161     const net::IPAddress& address,
1162     mojom::MdnsResponder::CreateNameForAddressCallback callback) {
1163   DCHECK(address.IsValid() || address.empty());
1164   if (!address.IsValid()) {
1165     LOG(ERROR) << "Invalid IP address to create a name for";
1166     ReportServiceError(MdnsResponderServiceError::kInvalidIpToRegisterName);
1167     receiver_.reset();
1168     manager_->OnMojoConnectionError(this);
1169     return;
1170   }
1171   std::string name;
1172   auto it = FindNameCreatedForAddress(address);
1173   bool announcement_sched_at_least_once = false;
1174   if (it == name_addr_map_.end()) {
1175     name = name_generator_->CreateName() + ".local";
1176     // The name should be uniquely owned by one instance of responders.
1177     bool rv = manager_->AddName(name);
1178     DCHECK(rv);
1179     name_addr_map_[name] = address;
1180     DCHECK(name_refcount_map_.find(name) == name_refcount_map_.end());
1181     name_refcount_map_[name] = 1;
1182     // RFC 6762, Section 8.3.
1183     //
1184     // Send mDNS announcements, one second apart, for the newly created
1185     // name-address association. The scheduler will pace the announcements.
1186     std::map<std::string, net::IPAddress> map_to_announce({{name, address}});
1187     auto option = base::MakeRefCounted<MdnsResponseSendOption>();
1188     // Send on all interfaces.
1189     option->klass = MdnsResponseSendOption::ResponseClass::ANNOUNCEMENT;
1190     for (int i = 0; i < kMinNumAnnouncementsToSend; ++i) {
1191       bool announcement_scheduled = SendMdnsResponse(
1192           mdns_helper::CreateResolutionResponse(
1193               kDefaultTtlForRecordWithHostname, map_to_announce),
1194           option);
1195       announcement_sched_at_least_once |= announcement_scheduled;
1196       if (!announcement_scheduled)
1197         break;
1198     }
1199   } else {
1200     name = it->first;
1201     DCHECK(name_refcount_map_.find(name) != name_refcount_map_.end());
1202     ++name_refcount_map_[name];
1203   }
1204   std::move(callback).Run(name, announcement_sched_at_least_once);
1205 }
1206 
RemoveNameForAddress(const net::IPAddress & address,mojom::MdnsResponder::RemoveNameForAddressCallback callback)1207 void MdnsResponder::RemoveNameForAddress(
1208     const net::IPAddress& address,
1209     mojom::MdnsResponder::RemoveNameForAddressCallback callback) {
1210   DCHECK(address.IsValid() || address.empty());
1211   auto it = FindNameCreatedForAddress(address);
1212   if (it == name_addr_map_.end()) {
1213     std::move(callback).Run(false /* removed */, false /* goodbye_scheduled */);
1214     return;
1215   }
1216   std::string name = it->first;
1217   DCHECK(name_refcount_map_.find(name) != name_refcount_map_.end());
1218   auto refcount = --name_refcount_map_[name];
1219   bool goodbye_scheduled = false;
1220   if (refcount == 0) {
1221     goodbye_scheduled = SendGoodbyePacketForNameAddressMap({*it});
1222     // The name removed should be previously owned by one instance of
1223     // responders.
1224     bool rv = manager_->RemoveName(name);
1225     DCHECK(rv);
1226     name_refcount_map_.erase(name);
1227     name_addr_map_.erase(it);
1228   }
1229   DCHECK(refcount == 0 || !goodbye_scheduled);
1230   std::move(callback).Run(refcount == 0, goodbye_scheduled);
1231 }
1232 
OnMdnsQueryReceived(const net::DnsQuery & query,uint16_t recv_socket_handler_id)1233 void MdnsResponder::OnMdnsQueryReceived(const net::DnsQuery& query,
1234                                         uint16_t recv_socket_handler_id) {
1235   // Currently we only support a single question in DnsQuery.
1236   std::string dotted_name_to_resolve = net::DNSDomainToString(query.qname());
1237   auto it = name_addr_map_.find(dotted_name_to_resolve);
1238   if (it == name_addr_map_.end())
1239     return;
1240 
1241   std::map<std::string, net::IPAddress> map_to_respond({*it});
1242   auto option = base::MakeRefCounted<MdnsResponseSendOption>();
1243   option->send_socket_handler_ids.insert(recv_socket_handler_id);
1244   option->names_for_rate_limit.insert(it->first);
1245   if (!QueryTypeAndAddressFamilyAreCompatible(query.qtype(),
1246                                               GetAddressFamily(it->second))) {
1247     // The query asks for a record that does not exist for the name and we send
1248     // a negative response.
1249     option->klass = MdnsResponseSendOption::ResponseClass::NEGATIVE;
1250 
1251     SendMdnsResponse(mdns_helper::CreateNegativeResponse(map_to_respond),
1252                      std::move(option));
1253     return;
1254   }
1255   // TODO(qingsi): Once we update DnsQuery and IsProbeQuery to properly detect
1256   // probe queries (see the comment inside IsProbeQuery), we should check the
1257   // probe queries first for conflicting records of names we own, and send the
1258   // negative responses without rate limiting. In other words, the check above
1259   // with QueryTypeAndAddressFamilyAreCompatible that results in the per-record
1260   // rate limiting should not apply to negative responses to probe queries.
1261   if (IsProbeQuery(query))
1262     option->klass = MdnsResponseSendOption::ResponseClass::PROBE_RESOLUTION;
1263   else
1264     option->klass = MdnsResponseSendOption::ResponseClass::REGULAR_RESOLUTION;
1265 
1266   // Send the name resolution for the received query.
1267   SendMdnsResponse(mdns_helper::CreateResolutionResponse(
1268                        kDefaultTtlForRecordWithHostname, map_to_respond),
1269                    std::move(option));
1270 }
1271 
HasConflictWithExternalResolution(const std::string & name,const std::set<net::IPAddress> & external_mapped_addreses)1272 bool MdnsResponder::HasConflictWithExternalResolution(
1273     const std::string& name,
1274     const std::set<net::IPAddress>& external_mapped_addreses) {
1275   DCHECK(!external_mapped_addreses.empty());
1276   auto matching_record_it = name_addr_map_.find(name);
1277   if (matching_record_it == name_addr_map_.end())
1278     return false;
1279 
1280   if (external_mapped_addreses.size() == 1 &&
1281       *external_mapped_addreses.begin() == matching_record_it->second) {
1282     VLOG(1) << "Received an external response for an owned record.";
1283     return false;
1284   }
1285 
1286   LOG(ERROR) << "Received conflicting resolution for name: " << name;
1287   ReportServiceError(MdnsResponderServiceError::kConflictingNameResolution);
1288   return true;
1289 }
1290 
SendMdnsResponse(scoped_refptr<net::IOBufferWithSize> response,scoped_refptr<MdnsResponseSendOption> option)1291 bool MdnsResponder::SendMdnsResponse(
1292     scoped_refptr<net::IOBufferWithSize> response,
1293     scoped_refptr<MdnsResponseSendOption> option) {
1294   DCHECK_NE(MdnsResponseSendOption::ResponseClass::UNSPECIFIED, option->klass);
1295   return manager_->Send(std::move(response), std::move(option));
1296 }
1297 
SendGoodbyePacketForNameAddressMap(const std::map<std::string,net::IPAddress> & name_addr_map)1298 bool MdnsResponder::SendGoodbyePacketForNameAddressMap(
1299     const std::map<std::string, net::IPAddress>& name_addr_map) {
1300   if (name_addr_map.empty())
1301     return false;
1302 
1303   auto option = base::MakeRefCounted<MdnsResponseSendOption>();
1304   // Send on all interfaces.
1305   option->klass = MdnsResponseSendOption::ResponseClass::GOODBYE;
1306   return SendMdnsResponse(mdns_helper::CreateResolutionResponse(
1307                               base::TimeDelta() /* ttl */, name_addr_map),
1308                           std::move(option));
1309 }
1310 
1311 std::map<std::string, net::IPAddress>::iterator
FindNameCreatedForAddress(const net::IPAddress & address)1312 MdnsResponder::FindNameCreatedForAddress(const net::IPAddress& address) {
1313   auto ret = name_addr_map_.end();
1314   size_t count = 0;
1315   for (auto it = name_addr_map_.begin(); it != name_addr_map_.end(); ++it) {
1316     if (it->second == address) {
1317       ret = it;
1318       ++count;
1319       DCHECK_LE(count, 1u);
1320     }
1321   }
1322   return ret;
1323 }
1324 
1325 }  // namespace network
1326