123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206 |
- /*
- * Copyright 2018 The WebRTC Project Authors. All rights reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
- #ifndef P2P_BASE_MDNS_MESSAGE_H_
- #define P2P_BASE_MDNS_MESSAGE_H_
- // This file contains classes to read and write mDNSs message defined in RFC
- // 6762 and RFC 1025 (DNS messages). Note that it is recommended by RFC 6762 to
- // use the name compression scheme defined in RFC 1035 whenever possible. We
- // currently only implement the capability of reading compressed names in mDNS
- // messages in MdnsMessage::Read(); however, the MdnsMessage::Write() does not
- // support name compression yet.
- //
- // Fuzzer tests (test/fuzzers/mdns_parser_fuzzer.cc) MUST always be performed
- // after changes made to this file.
- #include <stdint.h>
- #include <string>
- #include <vector>
- #include "rtc_base/byte_buffer.h"
- #include "rtc_base/ip_address.h"
- #include "rtc_base/message_buffer_reader.h"
- namespace webrtc {
- // We use "section entry" to denote either a question or a resource record.
- //
- // RFC 1035 Section 3.2.2.
- enum class SectionEntryType {
- kA,
- kAAAA,
- // Only the above types are processed in the current implementation.
- kUnsupported,
- };
- // RFC 1035 Section 3.2.4.
- enum class SectionEntryClass {
- kIN,
- kUnsupported,
- };
- // RFC 1035, Section 4.1.1.
- class MdnsHeader final {
- public:
- bool Read(MessageBufferReader* buf);
- void Write(rtc::ByteBufferWriter* buf) const;
- void SetQueryOrResponse(bool is_query);
- bool IsQuery() const;
- void SetAuthoritative(bool is_authoritative);
- bool IsAuthoritative() const;
- uint16_t id = 0;
- uint16_t flags = 0;
- // Number of entries in the question section.
- uint16_t qdcount = 0;
- // Number of resource records in the answer section.
- uint16_t ancount = 0;
- // Number of name server resource records in the authority records section.
- uint16_t nscount = 0;
- // Number of resource records in the additional records section.
- uint16_t arcount = 0;
- };
- // Entries in each section after the header share a common structure. Note that
- // this is not a concept defined in RFC 1035.
- class MdnsSectionEntry {
- public:
- MdnsSectionEntry();
- MdnsSectionEntry(const MdnsSectionEntry& other);
- virtual ~MdnsSectionEntry();
- virtual bool Read(MessageBufferReader* buf) = 0;
- virtual bool Write(rtc::ByteBufferWriter* buf) const = 0;
- void SetName(const std::string& name) { name_ = name; }
- // Returns the fully qualified domain name in the section entry, i.e., QNAME
- // in a question or NAME in a resource record.
- std::string GetName() const { return name_; }
- void SetType(SectionEntryType type);
- SectionEntryType GetType() const;
- void SetClass(SectionEntryClass cls);
- SectionEntryClass GetClass() const;
- protected:
- std::string name_; // Fully qualified domain name.
- uint16_t type_ = 0;
- uint16_t class_ = 0;
- };
- // RFC 1035, Section 4.1.2.
- class MdnsQuestion final : public MdnsSectionEntry {
- public:
- MdnsQuestion();
- MdnsQuestion(const MdnsQuestion& other);
- ~MdnsQuestion() override;
- bool Read(MessageBufferReader* buf) override;
- bool Write(rtc::ByteBufferWriter* buf) const override;
- void SetUnicastResponse(bool should_unicast);
- bool ShouldUnicastResponse() const;
- };
- // RFC 1035, Section 4.1.3.
- class MdnsResourceRecord final : public MdnsSectionEntry {
- public:
- MdnsResourceRecord();
- MdnsResourceRecord(const MdnsResourceRecord& other);
- ~MdnsResourceRecord() override;
- bool Read(MessageBufferReader* buf) override;
- bool Write(rtc::ByteBufferWriter* buf) const override;
- void SetTtlSeconds(uint32_t ttl_seconds) { ttl_seconds_ = ttl_seconds; }
- uint32_t GetTtlSeconds() const { return ttl_seconds_; }
- // Returns true if |address| is in the address family AF_INET or AF_INET6 and
- // |address| has a valid IPv4 or IPv6 address; false otherwise.
- bool SetIPAddressInRecordData(const rtc::IPAddress& address);
- // Returns true if the record is of type A or AAAA and the record has a valid
- // IPv4 or IPv6 address; false otherwise. Stores the valid IP in |address|.
- bool GetIPAddressFromRecordData(rtc::IPAddress* address) const;
- private:
- // The list of methods reading and writing rdata can grow as we support more
- // types of rdata.
- bool ReadARData(MessageBufferReader* buf);
- void WriteARData(rtc::ByteBufferWriter* buf) const;
- bool ReadQuadARData(MessageBufferReader* buf);
- void WriteQuadARData(rtc::ByteBufferWriter* buf) const;
- uint32_t ttl_seconds_ = 0;
- uint16_t rdlength_ = 0;
- std::string rdata_;
- };
- class MdnsMessage final {
- public:
- // RFC 1035, Section 4.1.
- enum class Section { kQuestion, kAnswer, kAuthority, kAdditional };
- MdnsMessage();
- ~MdnsMessage();
- // Reads the mDNS message in |buf| and populates the corresponding fields in
- // MdnsMessage.
- bool Read(MessageBufferReader* buf);
- // Write an mDNS message to |buf| based on the fields in MdnsMessage.
- //
- // TODO(qingsi): Implement name compression when writing mDNS messages.
- bool Write(rtc::ByteBufferWriter* buf) const;
- void SetId(uint16_t id) { header_.id = id; }
- uint16_t GetId() const { return header_.id; }
- void SetQueryOrResponse(bool is_query) {
- header_.SetQueryOrResponse(is_query);
- }
- bool IsQuery() const { return header_.IsQuery(); }
- void SetAuthoritative(bool is_authoritative) {
- header_.SetAuthoritative(is_authoritative);
- }
- bool IsAuthoritative() const { return header_.IsAuthoritative(); }
- // Returns true if the message is a query and the unicast response is
- // preferred. False otherwise.
- bool ShouldUnicastResponse() const;
- void AddQuestion(const MdnsQuestion& question);
- // TODO(qingsi): Implement AddXRecord for name server and additional records.
- void AddAnswerRecord(const MdnsResourceRecord& answer);
- const std::vector<MdnsQuestion>& question_section() const {
- return question_section_;
- }
- const std::vector<MdnsResourceRecord>& answer_section() const {
- return answer_section_;
- }
- const std::vector<MdnsResourceRecord>& authority_section() const {
- return authority_section_;
- }
- const std::vector<MdnsResourceRecord>& additional_section() const {
- return additional_section_;
- }
- private:
- MdnsHeader header_;
- std::vector<MdnsQuestion> question_section_;
- std::vector<MdnsResourceRecord> answer_section_;
- std::vector<MdnsResourceRecord> authority_section_;
- std::vector<MdnsResourceRecord> additional_section_;
- };
- } // namespace webrtc
- #endif // P2P_BASE_MDNS_MESSAGE_H_
|