mdns_message.h 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. /*
  2. * Copyright 2018 The WebRTC Project Authors. All rights reserved.
  3. *
  4. * Use of this source code is governed by a BSD-style license
  5. * that can be found in the LICENSE file in the root of the source
  6. * tree. An additional intellectual property rights grant can be found
  7. * in the file PATENTS. All contributing project authors may
  8. * be found in the AUTHORS file in the root of the source tree.
  9. */
  10. #ifndef P2P_BASE_MDNS_MESSAGE_H_
  11. #define P2P_BASE_MDNS_MESSAGE_H_
  12. // This file contains classes to read and write mDNSs message defined in RFC
  13. // 6762 and RFC 1025 (DNS messages). Note that it is recommended by RFC 6762 to
  14. // use the name compression scheme defined in RFC 1035 whenever possible. We
  15. // currently only implement the capability of reading compressed names in mDNS
  16. // messages in MdnsMessage::Read(); however, the MdnsMessage::Write() does not
  17. // support name compression yet.
  18. //
  19. // Fuzzer tests (test/fuzzers/mdns_parser_fuzzer.cc) MUST always be performed
  20. // after changes made to this file.
  21. #include <stdint.h>
  22. #include <string>
  23. #include <vector>
  24. #include "rtc_base/byte_buffer.h"
  25. #include "rtc_base/ip_address.h"
  26. #include "rtc_base/message_buffer_reader.h"
  27. namespace webrtc {
  28. // We use "section entry" to denote either a question or a resource record.
  29. //
  30. // RFC 1035 Section 3.2.2.
  31. enum class SectionEntryType {
  32. kA,
  33. kAAAA,
  34. // Only the above types are processed in the current implementation.
  35. kUnsupported,
  36. };
  37. // RFC 1035 Section 3.2.4.
  38. enum class SectionEntryClass {
  39. kIN,
  40. kUnsupported,
  41. };
  42. // RFC 1035, Section 4.1.1.
  43. class MdnsHeader final {
  44. public:
  45. bool Read(MessageBufferReader* buf);
  46. void Write(rtc::ByteBufferWriter* buf) const;
  47. void SetQueryOrResponse(bool is_query);
  48. bool IsQuery() const;
  49. void SetAuthoritative(bool is_authoritative);
  50. bool IsAuthoritative() const;
  51. uint16_t id = 0;
  52. uint16_t flags = 0;
  53. // Number of entries in the question section.
  54. uint16_t qdcount = 0;
  55. // Number of resource records in the answer section.
  56. uint16_t ancount = 0;
  57. // Number of name server resource records in the authority records section.
  58. uint16_t nscount = 0;
  59. // Number of resource records in the additional records section.
  60. uint16_t arcount = 0;
  61. };
  62. // Entries in each section after the header share a common structure. Note that
  63. // this is not a concept defined in RFC 1035.
  64. class MdnsSectionEntry {
  65. public:
  66. MdnsSectionEntry();
  67. MdnsSectionEntry(const MdnsSectionEntry& other);
  68. virtual ~MdnsSectionEntry();
  69. virtual bool Read(MessageBufferReader* buf) = 0;
  70. virtual bool Write(rtc::ByteBufferWriter* buf) const = 0;
  71. void SetName(const std::string& name) { name_ = name; }
  72. // Returns the fully qualified domain name in the section entry, i.e., QNAME
  73. // in a question or NAME in a resource record.
  74. std::string GetName() const { return name_; }
  75. void SetType(SectionEntryType type);
  76. SectionEntryType GetType() const;
  77. void SetClass(SectionEntryClass cls);
  78. SectionEntryClass GetClass() const;
  79. protected:
  80. std::string name_; // Fully qualified domain name.
  81. uint16_t type_ = 0;
  82. uint16_t class_ = 0;
  83. };
  84. // RFC 1035, Section 4.1.2.
  85. class MdnsQuestion final : public MdnsSectionEntry {
  86. public:
  87. MdnsQuestion();
  88. MdnsQuestion(const MdnsQuestion& other);
  89. ~MdnsQuestion() override;
  90. bool Read(MessageBufferReader* buf) override;
  91. bool Write(rtc::ByteBufferWriter* buf) const override;
  92. void SetUnicastResponse(bool should_unicast);
  93. bool ShouldUnicastResponse() const;
  94. };
  95. // RFC 1035, Section 4.1.3.
  96. class MdnsResourceRecord final : public MdnsSectionEntry {
  97. public:
  98. MdnsResourceRecord();
  99. MdnsResourceRecord(const MdnsResourceRecord& other);
  100. ~MdnsResourceRecord() override;
  101. bool Read(MessageBufferReader* buf) override;
  102. bool Write(rtc::ByteBufferWriter* buf) const override;
  103. void SetTtlSeconds(uint32_t ttl_seconds) { ttl_seconds_ = ttl_seconds; }
  104. uint32_t GetTtlSeconds() const { return ttl_seconds_; }
  105. // Returns true if |address| is in the address family AF_INET or AF_INET6 and
  106. // |address| has a valid IPv4 or IPv6 address; false otherwise.
  107. bool SetIPAddressInRecordData(const rtc::IPAddress& address);
  108. // Returns true if the record is of type A or AAAA and the record has a valid
  109. // IPv4 or IPv6 address; false otherwise. Stores the valid IP in |address|.
  110. bool GetIPAddressFromRecordData(rtc::IPAddress* address) const;
  111. private:
  112. // The list of methods reading and writing rdata can grow as we support more
  113. // types of rdata.
  114. bool ReadARData(MessageBufferReader* buf);
  115. void WriteARData(rtc::ByteBufferWriter* buf) const;
  116. bool ReadQuadARData(MessageBufferReader* buf);
  117. void WriteQuadARData(rtc::ByteBufferWriter* buf) const;
  118. uint32_t ttl_seconds_ = 0;
  119. uint16_t rdlength_ = 0;
  120. std::string rdata_;
  121. };
  122. class MdnsMessage final {
  123. public:
  124. // RFC 1035, Section 4.1.
  125. enum class Section { kQuestion, kAnswer, kAuthority, kAdditional };
  126. MdnsMessage();
  127. ~MdnsMessage();
  128. // Reads the mDNS message in |buf| and populates the corresponding fields in
  129. // MdnsMessage.
  130. bool Read(MessageBufferReader* buf);
  131. // Write an mDNS message to |buf| based on the fields in MdnsMessage.
  132. //
  133. // TODO(qingsi): Implement name compression when writing mDNS messages.
  134. bool Write(rtc::ByteBufferWriter* buf) const;
  135. void SetId(uint16_t id) { header_.id = id; }
  136. uint16_t GetId() const { return header_.id; }
  137. void SetQueryOrResponse(bool is_query) {
  138. header_.SetQueryOrResponse(is_query);
  139. }
  140. bool IsQuery() const { return header_.IsQuery(); }
  141. void SetAuthoritative(bool is_authoritative) {
  142. header_.SetAuthoritative(is_authoritative);
  143. }
  144. bool IsAuthoritative() const { return header_.IsAuthoritative(); }
  145. // Returns true if the message is a query and the unicast response is
  146. // preferred. False otherwise.
  147. bool ShouldUnicastResponse() const;
  148. void AddQuestion(const MdnsQuestion& question);
  149. // TODO(qingsi): Implement AddXRecord for name server and additional records.
  150. void AddAnswerRecord(const MdnsResourceRecord& answer);
  151. const std::vector<MdnsQuestion>& question_section() const {
  152. return question_section_;
  153. }
  154. const std::vector<MdnsResourceRecord>& answer_section() const {
  155. return answer_section_;
  156. }
  157. const std::vector<MdnsResourceRecord>& authority_section() const {
  158. return authority_section_;
  159. }
  160. const std::vector<MdnsResourceRecord>& additional_section() const {
  161. return additional_section_;
  162. }
  163. private:
  164. MdnsHeader header_;
  165. std::vector<MdnsQuestion> question_section_;
  166. std::vector<MdnsResourceRecord> answer_section_;
  167. std::vector<MdnsResourceRecord> authority_section_;
  168. std::vector<MdnsResourceRecord> additional_section_;
  169. };
  170. } // namespace webrtc
  171. #endif // P2P_BASE_MDNS_MESSAGE_H_