Remove MDNS message implementation
No customers have been identified. Bug: chromium:1197965 Change-Id: Ia3063d0909c718ffb8e824225c8c60180551115a Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/214963 Reviewed-by: Taylor <deadbeef@webrtc.org> Commit-Queue: Harald Alvestrand <hta@webrtc.org> Cr-Commit-Position: refs/heads/master@{#33700}
This commit is contained in:
parent
eff79cfc75
commit
c8cf0a6080
@ -45,8 +45,6 @@ rtc_library("rtc_p2p") {
|
||||
"base/ice_credentials_iterator.h",
|
||||
"base/ice_transport_internal.cc",
|
||||
"base/ice_transport_internal.h",
|
||||
"base/mdns_message.cc",
|
||||
"base/mdns_message.h",
|
||||
"base/p2p_constants.cc",
|
||||
"base/p2p_constants.h",
|
||||
"base/p2p_transport_channel.cc",
|
||||
@ -215,7 +213,6 @@ if (rtc_include_tests) {
|
||||
"base/basic_async_resolver_factory_unittest.cc",
|
||||
"base/dtls_transport_unittest.cc",
|
||||
"base/ice_credentials_iterator_unittest.cc",
|
||||
"base/mdns_message_unittest.cc",
|
||||
"base/p2p_transport_channel_unittest.cc",
|
||||
"base/port_allocator_unittest.cc",
|
||||
"base/port_unittest.cc",
|
||||
|
||||
@ -1,396 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "p2p/base/mdns_message.h"
|
||||
|
||||
#include "rtc_base/logging.h"
|
||||
#include "rtc_base/net_helpers.h"
|
||||
#include "rtc_base/string_encode.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
namespace {
|
||||
// RFC 1035, Section 4.1.1.
|
||||
//
|
||||
// QR bit.
|
||||
constexpr uint16_t kMdnsFlagMaskQueryOrResponse = 0x8000;
|
||||
// AA bit.
|
||||
constexpr uint16_t kMdnsFlagMaskAuthoritative = 0x0400;
|
||||
// RFC 1035, Section 4.1.2, QCLASS and RFC 6762, Section 18.12, repurposing of
|
||||
// top bit of QCLASS as the unicast response bit.
|
||||
constexpr uint16_t kMdnsQClassMaskUnicastResponse = 0x8000;
|
||||
constexpr size_t kMdnsHeaderSizeBytes = 12;
|
||||
|
||||
bool ReadDomainName(MessageBufferReader* buf, std::string* name) {
|
||||
size_t name_start_pos = buf->CurrentOffset();
|
||||
uint8_t label_length;
|
||||
if (!buf->ReadUInt8(&label_length)) {
|
||||
return false;
|
||||
}
|
||||
// RFC 1035, Section 4.1.4.
|
||||
//
|
||||
// If the first two bits of the length octet are ones, the name is compressed
|
||||
// and the rest six bits with the next octet denotes its position in the
|
||||
// message by the offset from the start of the message.
|
||||
auto is_pointer = [](uint8_t octet) {
|
||||
return (octet & 0x80) && (octet & 0x40);
|
||||
};
|
||||
while (label_length && !is_pointer(label_length)) {
|
||||
// RFC 1035, Section 2.3.1, labels are restricted to 63 octets or less.
|
||||
if (label_length > 63) {
|
||||
return false;
|
||||
}
|
||||
std::string label;
|
||||
if (!buf->ReadString(&label, label_length)) {
|
||||
return false;
|
||||
}
|
||||
(*name) += label + ".";
|
||||
if (!buf->ReadUInt8(&label_length)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (is_pointer(label_length)) {
|
||||
uint8_t next_octet;
|
||||
if (!buf->ReadUInt8(&next_octet)) {
|
||||
return false;
|
||||
}
|
||||
size_t pos_jump_to = ((label_length & 0x3f) << 8) | next_octet;
|
||||
// A legitimate pointer only refers to a prior occurrence of the same name,
|
||||
// and we should only move strictly backward to a prior name field after the
|
||||
// header.
|
||||
if (pos_jump_to >= name_start_pos || pos_jump_to < kMdnsHeaderSizeBytes) {
|
||||
return false;
|
||||
}
|
||||
MessageBufferReader new_buf(buf->MessageData(), buf->MessageLength());
|
||||
if (!new_buf.Consume(pos_jump_to)) {
|
||||
return false;
|
||||
}
|
||||
return ReadDomainName(&new_buf, name);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void WriteDomainName(rtc::ByteBufferWriter* buf, const std::string& name) {
|
||||
std::vector<std::string> labels;
|
||||
rtc::tokenize(name, '.', &labels);
|
||||
for (const auto& label : labels) {
|
||||
buf->WriteUInt8(label.length());
|
||||
buf->WriteString(label);
|
||||
}
|
||||
buf->WriteUInt8(0);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void MdnsHeader::SetQueryOrResponse(bool is_query) {
|
||||
if (is_query) {
|
||||
flags &= ~kMdnsFlagMaskQueryOrResponse;
|
||||
} else {
|
||||
flags |= kMdnsFlagMaskQueryOrResponse;
|
||||
}
|
||||
}
|
||||
|
||||
void MdnsHeader::SetAuthoritative(bool is_authoritative) {
|
||||
if (is_authoritative) {
|
||||
flags |= kMdnsFlagMaskAuthoritative;
|
||||
} else {
|
||||
flags &= ~kMdnsFlagMaskAuthoritative;
|
||||
}
|
||||
}
|
||||
|
||||
bool MdnsHeader::IsAuthoritative() const {
|
||||
return flags & kMdnsFlagMaskAuthoritative;
|
||||
}
|
||||
|
||||
bool MdnsHeader::Read(MessageBufferReader* buf) {
|
||||
if (!buf->ReadUInt16(&id) || !buf->ReadUInt16(&flags) ||
|
||||
!buf->ReadUInt16(&qdcount) || !buf->ReadUInt16(&ancount) ||
|
||||
!buf->ReadUInt16(&nscount) || !buf->ReadUInt16(&arcount)) {
|
||||
RTC_LOG(LS_ERROR) << "Invalid mDNS header.";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void MdnsHeader::Write(rtc::ByteBufferWriter* buf) const {
|
||||
buf->WriteUInt16(id);
|
||||
buf->WriteUInt16(flags);
|
||||
buf->WriteUInt16(qdcount);
|
||||
buf->WriteUInt16(ancount);
|
||||
buf->WriteUInt16(nscount);
|
||||
buf->WriteUInt16(arcount);
|
||||
}
|
||||
|
||||
bool MdnsHeader::IsQuery() const {
|
||||
return !(flags & kMdnsFlagMaskQueryOrResponse);
|
||||
}
|
||||
|
||||
MdnsSectionEntry::MdnsSectionEntry() = default;
|
||||
MdnsSectionEntry::~MdnsSectionEntry() = default;
|
||||
MdnsSectionEntry::MdnsSectionEntry(const MdnsSectionEntry& other) = default;
|
||||
|
||||
void MdnsSectionEntry::SetType(SectionEntryType type) {
|
||||
switch (type) {
|
||||
case SectionEntryType::kA:
|
||||
type_ = 1;
|
||||
return;
|
||||
case SectionEntryType::kAAAA:
|
||||
type_ = 28;
|
||||
return;
|
||||
default:
|
||||
RTC_NOTREACHED();
|
||||
}
|
||||
}
|
||||
|
||||
SectionEntryType MdnsSectionEntry::GetType() const {
|
||||
switch (type_) {
|
||||
case 1:
|
||||
return SectionEntryType::kA;
|
||||
case 28:
|
||||
return SectionEntryType::kAAAA;
|
||||
default:
|
||||
return SectionEntryType::kUnsupported;
|
||||
}
|
||||
}
|
||||
|
||||
void MdnsSectionEntry::SetClass(SectionEntryClass cls) {
|
||||
switch (cls) {
|
||||
case SectionEntryClass::kIN:
|
||||
class_ = 1;
|
||||
return;
|
||||
default:
|
||||
RTC_NOTREACHED();
|
||||
}
|
||||
}
|
||||
|
||||
SectionEntryClass MdnsSectionEntry::GetClass() const {
|
||||
switch (class_) {
|
||||
case 1:
|
||||
return SectionEntryClass::kIN;
|
||||
default:
|
||||
return SectionEntryClass::kUnsupported;
|
||||
}
|
||||
}
|
||||
|
||||
MdnsQuestion::MdnsQuestion() = default;
|
||||
MdnsQuestion::MdnsQuestion(const MdnsQuestion& other) = default;
|
||||
MdnsQuestion::~MdnsQuestion() = default;
|
||||
|
||||
bool MdnsQuestion::Read(MessageBufferReader* buf) {
|
||||
if (!ReadDomainName(buf, &name_)) {
|
||||
RTC_LOG(LS_ERROR) << "Invalid name.";
|
||||
return false;
|
||||
}
|
||||
if (!buf->ReadUInt16(&type_) || !buf->ReadUInt16(&class_)) {
|
||||
RTC_LOG(LS_ERROR) << "Invalid type and class.";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MdnsQuestion::Write(rtc::ByteBufferWriter* buf) const {
|
||||
WriteDomainName(buf, name_);
|
||||
buf->WriteUInt16(type_);
|
||||
buf->WriteUInt16(class_);
|
||||
return true;
|
||||
}
|
||||
|
||||
void MdnsQuestion::SetUnicastResponse(bool should_unicast) {
|
||||
if (should_unicast) {
|
||||
class_ |= kMdnsQClassMaskUnicastResponse;
|
||||
} else {
|
||||
class_ &= ~kMdnsQClassMaskUnicastResponse;
|
||||
}
|
||||
}
|
||||
|
||||
bool MdnsQuestion::ShouldUnicastResponse() const {
|
||||
return class_ & kMdnsQClassMaskUnicastResponse;
|
||||
}
|
||||
|
||||
MdnsResourceRecord::MdnsResourceRecord() = default;
|
||||
MdnsResourceRecord::MdnsResourceRecord(const MdnsResourceRecord& other) =
|
||||
default;
|
||||
MdnsResourceRecord::~MdnsResourceRecord() = default;
|
||||
|
||||
bool MdnsResourceRecord::Read(MessageBufferReader* buf) {
|
||||
if (!ReadDomainName(buf, &name_)) {
|
||||
return false;
|
||||
}
|
||||
if (!buf->ReadUInt16(&type_) || !buf->ReadUInt16(&class_) ||
|
||||
!buf->ReadUInt32(&ttl_seconds_) || !buf->ReadUInt16(&rdlength_)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (GetType()) {
|
||||
case SectionEntryType::kA:
|
||||
return ReadARData(buf);
|
||||
case SectionEntryType::kAAAA:
|
||||
return ReadQuadARData(buf);
|
||||
case SectionEntryType::kUnsupported:
|
||||
return false;
|
||||
default:
|
||||
RTC_NOTREACHED();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool MdnsResourceRecord::ReadARData(MessageBufferReader* buf) {
|
||||
// A RDATA contains a 32-bit IPv4 address.
|
||||
return buf->ReadString(&rdata_, 4);
|
||||
}
|
||||
|
||||
bool MdnsResourceRecord::ReadQuadARData(MessageBufferReader* buf) {
|
||||
// AAAA RDATA contains a 128-bit IPv6 address.
|
||||
return buf->ReadString(&rdata_, 16);
|
||||
}
|
||||
|
||||
bool MdnsResourceRecord::Write(rtc::ByteBufferWriter* buf) const {
|
||||
WriteDomainName(buf, name_);
|
||||
buf->WriteUInt16(type_);
|
||||
buf->WriteUInt16(class_);
|
||||
buf->WriteUInt32(ttl_seconds_);
|
||||
buf->WriteUInt16(rdlength_);
|
||||
switch (GetType()) {
|
||||
case SectionEntryType::kA:
|
||||
WriteARData(buf);
|
||||
return true;
|
||||
case SectionEntryType::kAAAA:
|
||||
WriteQuadARData(buf);
|
||||
return true;
|
||||
case SectionEntryType::kUnsupported:
|
||||
return false;
|
||||
default:
|
||||
RTC_NOTREACHED();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void MdnsResourceRecord::WriteARData(rtc::ByteBufferWriter* buf) const {
|
||||
buf->WriteString(rdata_);
|
||||
}
|
||||
|
||||
void MdnsResourceRecord::WriteQuadARData(rtc::ByteBufferWriter* buf) const {
|
||||
buf->WriteString(rdata_);
|
||||
}
|
||||
|
||||
bool MdnsResourceRecord::SetIPAddressInRecordData(
|
||||
const rtc::IPAddress& address) {
|
||||
int af = address.family();
|
||||
if (af != AF_INET && af != AF_INET6) {
|
||||
return false;
|
||||
}
|
||||
char out[16] = {0};
|
||||
if (!rtc::inet_pton(af, address.ToString().c_str(), out)) {
|
||||
return false;
|
||||
}
|
||||
rdlength_ = (af == AF_INET) ? 4 : 16;
|
||||
rdata_ = std::string(out, rdlength_);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MdnsResourceRecord::GetIPAddressFromRecordData(
|
||||
rtc::IPAddress* address) const {
|
||||
if (GetType() != SectionEntryType::kA &&
|
||||
GetType() != SectionEntryType::kAAAA) {
|
||||
return false;
|
||||
}
|
||||
if (rdata_.size() != 4 && rdata_.size() != 16) {
|
||||
return false;
|
||||
}
|
||||
char out[INET6_ADDRSTRLEN] = {0};
|
||||
int af = (GetType() == SectionEntryType::kA) ? AF_INET : AF_INET6;
|
||||
if (!rtc::inet_ntop(af, rdata_.data(), out, sizeof(out))) {
|
||||
return false;
|
||||
}
|
||||
return rtc::IPFromString(std::string(out), address);
|
||||
}
|
||||
|
||||
MdnsMessage::MdnsMessage() = default;
|
||||
MdnsMessage::~MdnsMessage() = default;
|
||||
|
||||
bool MdnsMessage::Read(MessageBufferReader* buf) {
|
||||
RTC_DCHECK_EQ(0u, buf->CurrentOffset());
|
||||
if (!header_.Read(buf)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto read_question = [&buf](std::vector<MdnsQuestion>* section,
|
||||
uint16_t count) {
|
||||
section->resize(count);
|
||||
for (auto& question : (*section)) {
|
||||
if (!question.Read(buf)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
auto read_rr = [&buf](std::vector<MdnsResourceRecord>* section,
|
||||
uint16_t count) {
|
||||
section->resize(count);
|
||||
for (auto& rr : (*section)) {
|
||||
if (!rr.Read(buf)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
if (!read_question(&question_section_, header_.qdcount) ||
|
||||
!read_rr(&answer_section_, header_.ancount) ||
|
||||
!read_rr(&authority_section_, header_.nscount) ||
|
||||
!read_rr(&additional_section_, header_.arcount)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MdnsMessage::Write(rtc::ByteBufferWriter* buf) const {
|
||||
header_.Write(buf);
|
||||
|
||||
auto write_rr = [&buf](const std::vector<MdnsResourceRecord>& section) {
|
||||
for (const auto& rr : section) {
|
||||
if (!rr.Write(buf)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
for (const auto& question : question_section_) {
|
||||
if (!question.Write(buf)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!write_rr(answer_section_) || !write_rr(authority_section_) ||
|
||||
!write_rr(additional_section_)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MdnsMessage::ShouldUnicastResponse() const {
|
||||
bool should_unicast = false;
|
||||
for (const auto& question : question_section_) {
|
||||
should_unicast |= question.ShouldUnicastResponse();
|
||||
}
|
||||
return should_unicast;
|
||||
}
|
||||
|
||||
void MdnsMessage::AddQuestion(const MdnsQuestion& question) {
|
||||
question_section_.push_back(question);
|
||||
header_.qdcount = question_section_.size();
|
||||
}
|
||||
|
||||
void MdnsMessage::AddAnswerRecord(const MdnsResourceRecord& answer) {
|
||||
answer_section_.push_back(answer);
|
||||
header_.ancount = answer_section_.size();
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
@ -1,206 +0,0 @@
|
||||
/*
|
||||
* 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_
|
||||
@ -1,571 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "p2p/base/mdns_message.h"
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
#include "rtc_base/byte_buffer.h"
|
||||
#include "rtc_base/gunit.h"
|
||||
#include "rtc_base/ip_address.h"
|
||||
#include "rtc_base/socket_address.h"
|
||||
#include "test/gmock.h"
|
||||
|
||||
#define ReadMdnsMessage(X, Y) ReadMdnsMessageTestCase(X, Y, sizeof(Y))
|
||||
#define WriteMdnsMessageAndCompare(X, Y) \
|
||||
WriteMdnsMessageAndCompareWithTestCast(X, Y, sizeof(Y))
|
||||
|
||||
using ::testing::ElementsAre;
|
||||
using ::testing::Pair;
|
||||
using ::testing::UnorderedElementsAre;
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
namespace {
|
||||
|
||||
const uint8_t kSingleQuestionForIPv4AddrWithUnicastResponse[] = {
|
||||
0x12, 0x34, // ID
|
||||
0x00, 0x00, // flags
|
||||
0x00, 0x01, // number of questions
|
||||
0x00, 0x00, // number of answer rr
|
||||
0x00, 0x00, // number of name server rr
|
||||
0x00, 0x00, // number of additional rr
|
||||
0x06, 0x77, 0x65, 0x62, 0x72, 0x74, 0x63, // webrtc
|
||||
0x03, 0x6f, 0x72, 0x67, // org
|
||||
0x00, // null label
|
||||
0x00, 0x01, // type A Record
|
||||
0x80, 0x01, // class IN, unicast response
|
||||
};
|
||||
|
||||
const uint8_t kTwoQuestionsForIPv4AndIPv6AddrWithMulticastResponse[] = {
|
||||
0x12, 0x34, // ID
|
||||
0x00, 0x00, // flags
|
||||
0x00, 0x02, // number of questions
|
||||
0x00, 0x00, // number of answer rr
|
||||
0x00, 0x00, // number of name server rr
|
||||
0x00, 0x00, // number of additional rr
|
||||
0x07, 0x77, 0x65, 0x62, 0x72, 0x74, 0x63, 0x34, // webrtc4
|
||||
0x03, 0x6f, 0x72, 0x67, // org
|
||||
0x00, // null label
|
||||
0x00, 0x01, // type A Record
|
||||
0x00, 0x01, // class IN, multicast response
|
||||
0x07, 0x77, 0x65, 0x62, 0x72, 0x74, 0x63, 0x36, // webrtc6
|
||||
0x03, 0x6f, 0x72, 0x67, // org
|
||||
0x00, // null label
|
||||
0x00, 0x1C, // type AAAA Record
|
||||
0x00, 0x01, // class IN, multicast response
|
||||
};
|
||||
|
||||
const uint8_t
|
||||
kTwoQuestionsForIPv4AndIPv6AddrWithMulticastResponseAndNameCompression[] = {
|
||||
0x12, 0x34, // ID
|
||||
0x00, 0x00, // flags
|
||||
0x00, 0x02, // number of questions
|
||||
0x00, 0x00, // number of answer rr
|
||||
0x00, 0x00, // number of name server rr
|
||||
0x00, 0x00, // number of additional rr
|
||||
0x03, 0x77, 0x77, 0x77, // www
|
||||
0x06, 0x77, 0x65, 0x62, 0x72, 0x74, 0x63, // webrtc
|
||||
0x03, 0x6f, 0x72, 0x67, // org
|
||||
0x00, // null label
|
||||
0x00, 0x01, // type A Record
|
||||
0x00, 0x01, // class IN, multicast response
|
||||
0x04, 0x6d, 0x64, 0x6e, 0x73, // mdns
|
||||
0xc0, 0x10, // offset 16, webrtc.org.
|
||||
0x00, 0x1C, // type AAAA Record
|
||||
0x00, 0x01, // class IN, multicast response
|
||||
};
|
||||
|
||||
const uint8_t kThreeQuestionsWithTwoPointersToTheSameNameSuffix[] = {
|
||||
0x12, 0x34, // ID
|
||||
0x00, 0x00, // flags
|
||||
0x00, 0x03, // number of questions
|
||||
0x00, 0x00, // number of answer rr
|
||||
0x00, 0x00, // number of name server rr
|
||||
0x00, 0x00, // number of additional rr
|
||||
0x03, 0x77, 0x77, 0x77, // www
|
||||
0x06, 0x77, 0x65, 0x62, 0x72, 0x74, 0x63, // webrtc
|
||||
0x03, 0x6f, 0x72, 0x67, // org
|
||||
0x00, // null label
|
||||
0x00, 0x01, // type A Record
|
||||
0x00, 0x01, // class IN, multicast response
|
||||
0x04, 0x6d, 0x64, 0x6e, 0x73, // mdns
|
||||
0xc0, 0x10, // offset 16, webrtc.org.
|
||||
0x00, 0x1C, // type AAAA Record
|
||||
0x00, 0x01, // class IN, multicast response
|
||||
0xc0, 0x10, // offset 16, webrtc.org.
|
||||
0x00, 0x01, // type A Record
|
||||
0x00, 0x01, // class IN, multicast response
|
||||
};
|
||||
|
||||
const uint8_t kThreeQuestionsWithPointerToNameSuffixContainingAnotherPointer[] =
|
||||
{
|
||||
0x12, 0x34, // ID
|
||||
0x00, 0x00, // flags
|
||||
0x00, 0x03, // number of questions
|
||||
0x00, 0x00, // number of answer rr
|
||||
0x00, 0x00, // number of name server rr
|
||||
0x00, 0x00, // number of additional rr
|
||||
0x03, 0x77, 0x77, 0x77, // www
|
||||
0x06, 0x77, 0x65, 0x62, 0x72, 0x74, 0x63, // webrtc
|
||||
0x03, 0x6f, 0x72, 0x67, // org
|
||||
0x00, // null label
|
||||
0x00, 0x01, // type A Record
|
||||
0x00, 0x01, // class IN, multicast response
|
||||
0x04, 0x6d, 0x64, 0x6e, 0x73, // mdns
|
||||
0xc0, 0x10, // offset 16, webrtc.org.
|
||||
0x00, 0x1C, // type AAAA Record
|
||||
0x00, 0x01, // class IN, multicast response
|
||||
0x03, 0x77, 0x77, 0x77, // www
|
||||
0xc0, 0x20, // offset 32, mdns.webrtc.org.
|
||||
0x00, 0x01, // type A Record
|
||||
0x00, 0x01, // class IN, multicast response
|
||||
};
|
||||
|
||||
const uint8_t kCorruptedQuestionWithNameCompression1[] = {
|
||||
0x12, 0x34, // ID
|
||||
0x84, 0x00, // flags
|
||||
0x00, 0x01, // number of questions
|
||||
0x00, 0x00, // number of answer rr
|
||||
0x00, 0x00, // number of name server rr
|
||||
0x00, 0x00, // number of additional rr
|
||||
0xc0, 0x0c, // offset 12,
|
||||
0x00, 0x01, // type A Record
|
||||
0x00, 0x01, // class IN
|
||||
};
|
||||
|
||||
const uint8_t kCorruptedQuestionWithNameCompression2[] = {
|
||||
0x12, 0x34, // ID
|
||||
0x84, 0x00, // flags
|
||||
0x00, 0x01, // number of questions
|
||||
0x00, 0x00, // number of answer rr
|
||||
0x00, 0x00, // number of name server rr
|
||||
0x00, 0x00, // number of additional rr
|
||||
0x01, 0x77, // w
|
||||
0xc0, 0x0c, // offset 12,
|
||||
0x00, 0x01, // type A Record
|
||||
0x00, 0x01, // class IN
|
||||
};
|
||||
|
||||
const uint8_t kSingleAuthoritativeAnswerWithIPv4Addr[] = {
|
||||
0x12, 0x34, // ID
|
||||
0x84, 0x00, // flags
|
||||
0x00, 0x00, // number of questions
|
||||
0x00, 0x01, // number of answer rr
|
||||
0x00, 0x00, // number of name server rr
|
||||
0x00, 0x00, // number of additional rr
|
||||
0x06, 0x77, 0x65, 0x62, 0x72, 0x74, 0x63, // webrtc
|
||||
0x03, 0x6f, 0x72, 0x67, // org
|
||||
0x00, // null label
|
||||
0x00, 0x01, // type A Record
|
||||
0x00, 0x01, // class IN
|
||||
0x00, 0x00, 0x00, 0x78, // TTL, 120 seconds
|
||||
0x00, 0x04, // rdlength, 32 bits
|
||||
0xC0, 0xA8, 0x00, 0x01, // 192.168.0.1
|
||||
};
|
||||
|
||||
const uint8_t kTwoAuthoritativeAnswersWithIPv4AndIPv6Addr[] = {
|
||||
0x12, 0x34, // ID
|
||||
0x84, 0x00, // flags
|
||||
0x00, 0x00, // number of questions
|
||||
0x00, 0x02, // number of answer rr
|
||||
0x00, 0x00, // number of name server rr
|
||||
0x00, 0x00, // number of additional rr
|
||||
0x07, 0x77, 0x65, 0x62, 0x72, 0x74, 0x63, 0x34, // webrtc4
|
||||
0x03, 0x6f, 0x72, 0x67, // org
|
||||
0x00, // null label
|
||||
0x00, 0x01, // type A Record
|
||||
0x00, 0x01, // class IN
|
||||
0x00, 0x00, 0x00, 0x3c, // TTL, 60 seconds
|
||||
0x00, 0x04, // rdlength, 32 bits
|
||||
0xC0, 0xA8, 0x00, 0x01, // 192.168.0.1
|
||||
0x07, 0x77, 0x65, 0x62, 0x72, 0x74, 0x63, 0x36, // webrtc6
|
||||
0x03, 0x6f, 0x72, 0x67, // org
|
||||
0x00, // null label
|
||||
0x00, 0x1C, // type AAAA Record
|
||||
0x00, 0x01, // class IN
|
||||
0x00, 0x00, 0x00, 0x78, // TTL, 120 seconds
|
||||
0x00, 0x10, // rdlength, 128 bits
|
||||
0xfd, 0x12, 0x34, 0x56, 0x78, 0x9a, 0x00, 0x01, // fd12:3456:789a:1::1
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
|
||||
};
|
||||
|
||||
const uint8_t kTwoAuthoritativeAnswersWithIPv4AndIPv6AddrWithNameCompression[] =
|
||||
{
|
||||
0x12, 0x34, // ID
|
||||
0x84, 0x00, // flags
|
||||
0x00, 0x00, // number of questions
|
||||
0x00, 0x02, // number of answer rr
|
||||
0x00, 0x00, // number of name server rr
|
||||
0x00, 0x00, // number of additional rr
|
||||
0x03, 0x77, 0x77, 0x77, // www
|
||||
0x06, 0x77, 0x65, 0x62, 0x72, 0x74, 0x63, // webrtc
|
||||
0x03, 0x6f, 0x72, 0x67, // org
|
||||
0x00, // null label
|
||||
0x00, 0x01, // type A Record
|
||||
0x00, 0x01, // class IN
|
||||
0x00, 0x00, 0x00, 0x3c, // TTL, 60 seconds
|
||||
0x00, 0x04, // rdlength, 32 bits
|
||||
0xc0, 0xA8, 0x00, 0x01, // 192.168.0.1
|
||||
0xc0, 0x10, // offset 16, webrtc.org.
|
||||
0x00, 0x1C, // type AAAA Record
|
||||
0x00, 0x01, // class IN
|
||||
0x00, 0x00, 0x00, 0x78, // TTL, 120 seconds
|
||||
0x00, 0x10, // rdlength, 128 bits
|
||||
0xfd, 0x12, 0x34, 0x56, 0x78, 0x9a, 0x00, 0x01, // fd12:3456:789a:1::1
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
|
||||
};
|
||||
|
||||
const uint8_t kCorruptedAnswerWithNameCompression1[] = {
|
||||
0x12, 0x34, // ID
|
||||
0x84, 0x00, // flags
|
||||
0x00, 0x00, // number of questions
|
||||
0x00, 0x01, // number of answer rr
|
||||
0x00, 0x00, // number of name server rr
|
||||
0x00, 0x00, // number of additional rr
|
||||
0xc0, 0x0c, // offset 12,
|
||||
0x00, 0x01, // type A Record
|
||||
0x00, 0x01, // class IN
|
||||
0x00, 0x00, 0x00, 0x3c, // TTL, 60 seconds
|
||||
0x00, 0x04, // rdlength, 32 bits
|
||||
0xc0, 0xA8, 0x00, 0x01, // 192.168.0.1
|
||||
};
|
||||
|
||||
const uint8_t kCorruptedAnswerWithNameCompression2[] = {
|
||||
0x12, 0x34, // ID
|
||||
0x84, 0x00, // flags
|
||||
0x00, 0x00, // number of questions
|
||||
0x00, 0x01, // number of answer rr
|
||||
0x00, 0x00, // number of name server rr
|
||||
0x00, 0x00, // number of additional rr
|
||||
0x01, 0x77, // w
|
||||
0xc0, 0x0c, // offset 12,
|
||||
0x00, 0x01, // type A Record
|
||||
0x00, 0x01, // class IN
|
||||
0x00, 0x00, 0x00, 0x3c, // TTL, 60 seconds
|
||||
0x00, 0x04, // rdlength, 32 bits
|
||||
0xc0, 0xA8, 0x00, 0x01, // 192.168.0.1
|
||||
};
|
||||
|
||||
bool ReadMdnsMessageTestCase(MdnsMessage* msg,
|
||||
const uint8_t* testcase,
|
||||
size_t size) {
|
||||
MessageBufferReader buf(reinterpret_cast<const char*>(testcase), size);
|
||||
return msg->Read(&buf);
|
||||
}
|
||||
|
||||
void WriteMdnsMessageAndCompareWithTestCast(MdnsMessage* msg,
|
||||
const uint8_t* testcase,
|
||||
size_t size) {
|
||||
rtc::ByteBufferWriter out;
|
||||
EXPECT_TRUE(msg->Write(&out));
|
||||
EXPECT_EQ(size, out.Length());
|
||||
int len = static_cast<int>(out.Length());
|
||||
rtc::ByteBufferReader read_buf(out);
|
||||
std::string bytes;
|
||||
read_buf.ReadString(&bytes, len);
|
||||
std::string testcase_bytes(reinterpret_cast<const char*>(testcase), size);
|
||||
EXPECT_EQ(testcase_bytes, bytes);
|
||||
}
|
||||
|
||||
bool GetQueriedNames(MdnsMessage* msg, std::set<std::string>* names) {
|
||||
if (!msg->IsQuery() || msg->question_section().empty()) {
|
||||
return false;
|
||||
}
|
||||
for (const auto& question : msg->question_section()) {
|
||||
names->insert(question.GetName());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GetResolution(MdnsMessage* msg,
|
||||
std::map<std::string, rtc::IPAddress>* names) {
|
||||
if (msg->IsQuery() || msg->answer_section().empty()) {
|
||||
return false;
|
||||
}
|
||||
for (const auto& answer : msg->answer_section()) {
|
||||
rtc::IPAddress resolved_addr;
|
||||
if (!answer.GetIPAddressFromRecordData(&resolved_addr)) {
|
||||
return false;
|
||||
}
|
||||
(*names)[answer.GetName()] = resolved_addr;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST(MdnsMessageTest, ReadSingleQuestionForIPv4Address) {
|
||||
MdnsMessage msg;
|
||||
ASSERT_TRUE(
|
||||
ReadMdnsMessage(&msg, kSingleQuestionForIPv4AddrWithUnicastResponse));
|
||||
EXPECT_TRUE(msg.IsQuery());
|
||||
EXPECT_EQ(0x1234, msg.GetId());
|
||||
ASSERT_EQ(1u, msg.question_section().size());
|
||||
EXPECT_EQ(0u, msg.answer_section().size());
|
||||
EXPECT_EQ(0u, msg.authority_section().size());
|
||||
EXPECT_EQ(0u, msg.additional_section().size());
|
||||
EXPECT_TRUE(msg.ShouldUnicastResponse());
|
||||
|
||||
const auto& question = msg.question_section()[0];
|
||||
EXPECT_EQ(SectionEntryType::kA, question.GetType());
|
||||
|
||||
std::set<std::string> queried_names;
|
||||
EXPECT_TRUE(GetQueriedNames(&msg, &queried_names));
|
||||
EXPECT_THAT(queried_names, ElementsAre("webrtc.org."));
|
||||
}
|
||||
|
||||
TEST(MdnsMessageTest, ReadTwoQuestionsForIPv4AndIPv6Addr) {
|
||||
MdnsMessage msg;
|
||||
ASSERT_TRUE(ReadMdnsMessage(
|
||||
&msg, kTwoQuestionsForIPv4AndIPv6AddrWithMulticastResponse));
|
||||
EXPECT_TRUE(msg.IsQuery());
|
||||
EXPECT_EQ(0x1234, msg.GetId());
|
||||
ASSERT_EQ(2u, msg.question_section().size());
|
||||
EXPECT_EQ(0u, msg.answer_section().size());
|
||||
EXPECT_EQ(0u, msg.authority_section().size());
|
||||
EXPECT_EQ(0u, msg.additional_section().size());
|
||||
|
||||
const auto& question1 = msg.question_section()[0];
|
||||
const auto& question2 = msg.question_section()[1];
|
||||
EXPECT_EQ(SectionEntryType::kA, question1.GetType());
|
||||
EXPECT_EQ(SectionEntryType::kAAAA, question2.GetType());
|
||||
|
||||
std::set<std::string> queried_names;
|
||||
EXPECT_TRUE(GetQueriedNames(&msg, &queried_names));
|
||||
EXPECT_THAT(queried_names,
|
||||
UnorderedElementsAre("webrtc4.org.", "webrtc6.org."));
|
||||
}
|
||||
|
||||
TEST(MdnsMessageTest, ReadTwoQuestionsForIPv4AndIPv6AddrWithNameCompression) {
|
||||
MdnsMessage msg;
|
||||
ASSERT_TRUE(ReadMdnsMessage(
|
||||
&msg,
|
||||
kTwoQuestionsForIPv4AndIPv6AddrWithMulticastResponseAndNameCompression));
|
||||
|
||||
ASSERT_EQ(2u, msg.question_section().size());
|
||||
const auto& question1 = msg.question_section()[0];
|
||||
const auto& question2 = msg.question_section()[1];
|
||||
EXPECT_EQ(SectionEntryType::kA, question1.GetType());
|
||||
EXPECT_EQ(SectionEntryType::kAAAA, question2.GetType());
|
||||
|
||||
std::set<std::string> queried_names;
|
||||
EXPECT_TRUE(GetQueriedNames(&msg, &queried_names));
|
||||
EXPECT_THAT(queried_names,
|
||||
UnorderedElementsAre("www.webrtc.org.", "mdns.webrtc.org."));
|
||||
}
|
||||
|
||||
TEST(MdnsMessageTest, ReadThreeQuestionsWithTwoPointersToTheSameNameSuffix) {
|
||||
MdnsMessage msg;
|
||||
ASSERT_TRUE(
|
||||
ReadMdnsMessage(&msg, kThreeQuestionsWithTwoPointersToTheSameNameSuffix));
|
||||
|
||||
ASSERT_EQ(3u, msg.question_section().size());
|
||||
const auto& question1 = msg.question_section()[0];
|
||||
const auto& question2 = msg.question_section()[1];
|
||||
const auto& question3 = msg.question_section()[2];
|
||||
EXPECT_EQ(SectionEntryType::kA, question1.GetType());
|
||||
EXPECT_EQ(SectionEntryType::kAAAA, question2.GetType());
|
||||
EXPECT_EQ(SectionEntryType::kA, question3.GetType());
|
||||
|
||||
std::set<std::string> queried_names;
|
||||
EXPECT_TRUE(GetQueriedNames(&msg, &queried_names));
|
||||
EXPECT_THAT(queried_names,
|
||||
UnorderedElementsAre("www.webrtc.org.", "mdns.webrtc.org.",
|
||||
"webrtc.org."));
|
||||
}
|
||||
|
||||
TEST(MdnsMessageTest,
|
||||
ReadThreeQuestionsWithPointerToNameSuffixContainingAnotherPointer) {
|
||||
MdnsMessage msg;
|
||||
ASSERT_TRUE(ReadMdnsMessage(
|
||||
&msg, kThreeQuestionsWithPointerToNameSuffixContainingAnotherPointer));
|
||||
|
||||
ASSERT_EQ(3u, msg.question_section().size());
|
||||
const auto& question1 = msg.question_section()[0];
|
||||
const auto& question2 = msg.question_section()[1];
|
||||
const auto& question3 = msg.question_section()[2];
|
||||
EXPECT_EQ(SectionEntryType::kA, question1.GetType());
|
||||
EXPECT_EQ(SectionEntryType::kAAAA, question2.GetType());
|
||||
EXPECT_EQ(SectionEntryType::kA, question3.GetType());
|
||||
|
||||
std::set<std::string> queried_names;
|
||||
EXPECT_TRUE(GetQueriedNames(&msg, &queried_names));
|
||||
EXPECT_THAT(queried_names,
|
||||
UnorderedElementsAre("www.webrtc.org.", "mdns.webrtc.org.",
|
||||
"www.mdns.webrtc.org."));
|
||||
}
|
||||
|
||||
TEST(MdnsMessageTest,
|
||||
ReadQuestionWithCorruptedPointerInNameCompressionShouldFail) {
|
||||
MdnsMessage msg;
|
||||
EXPECT_FALSE(ReadMdnsMessage(&msg, kCorruptedQuestionWithNameCompression1));
|
||||
EXPECT_FALSE(ReadMdnsMessage(&msg, kCorruptedQuestionWithNameCompression2));
|
||||
}
|
||||
|
||||
TEST(MdnsMessageTest, ReadSingleAnswerForIPv4Addr) {
|
||||
MdnsMessage msg;
|
||||
ASSERT_TRUE(ReadMdnsMessage(&msg, kSingleAuthoritativeAnswerWithIPv4Addr));
|
||||
EXPECT_FALSE(msg.IsQuery());
|
||||
EXPECT_TRUE(msg.IsAuthoritative());
|
||||
EXPECT_EQ(0x1234, msg.GetId());
|
||||
EXPECT_EQ(0u, msg.question_section().size());
|
||||
ASSERT_EQ(1u, msg.answer_section().size());
|
||||
EXPECT_EQ(0u, msg.authority_section().size());
|
||||
EXPECT_EQ(0u, msg.additional_section().size());
|
||||
|
||||
const auto& answer = msg.answer_section()[0];
|
||||
EXPECT_EQ(SectionEntryType::kA, answer.GetType());
|
||||
EXPECT_EQ(120u, answer.GetTtlSeconds());
|
||||
|
||||
std::map<std::string, rtc::IPAddress> resolution;
|
||||
EXPECT_TRUE(GetResolution(&msg, &resolution));
|
||||
rtc::IPAddress expected_addr(rtc::SocketAddress("192.168.0.1", 0).ipaddr());
|
||||
EXPECT_THAT(resolution, ElementsAre(Pair("webrtc.org.", expected_addr)));
|
||||
}
|
||||
|
||||
TEST(MdnsMessageTest, ReadTwoAnswersForIPv4AndIPv6Addr) {
|
||||
MdnsMessage msg;
|
||||
ASSERT_TRUE(
|
||||
ReadMdnsMessage(&msg, kTwoAuthoritativeAnswersWithIPv4AndIPv6Addr));
|
||||
EXPECT_FALSE(msg.IsQuery());
|
||||
EXPECT_TRUE(msg.IsAuthoritative());
|
||||
EXPECT_EQ(0x1234, msg.GetId());
|
||||
EXPECT_EQ(0u, msg.question_section().size());
|
||||
ASSERT_EQ(2u, msg.answer_section().size());
|
||||
EXPECT_EQ(0u, msg.authority_section().size());
|
||||
EXPECT_EQ(0u, msg.additional_section().size());
|
||||
|
||||
const auto& answer1 = msg.answer_section()[0];
|
||||
const auto& answer2 = msg.answer_section()[1];
|
||||
EXPECT_EQ(SectionEntryType::kA, answer1.GetType());
|
||||
EXPECT_EQ(SectionEntryType::kAAAA, answer2.GetType());
|
||||
EXPECT_EQ(60u, answer1.GetTtlSeconds());
|
||||
EXPECT_EQ(120u, answer2.GetTtlSeconds());
|
||||
|
||||
std::map<std::string, rtc::IPAddress> resolution;
|
||||
EXPECT_TRUE(GetResolution(&msg, &resolution));
|
||||
rtc::IPAddress expected_addr_ipv4(
|
||||
rtc::SocketAddress("192.168.0.1", 0).ipaddr());
|
||||
rtc::IPAddress expected_addr_ipv6(
|
||||
rtc::SocketAddress("fd12:3456:789a:1::1", 0).ipaddr());
|
||||
EXPECT_THAT(resolution,
|
||||
UnorderedElementsAre(Pair("webrtc4.org.", expected_addr_ipv4),
|
||||
Pair("webrtc6.org.", expected_addr_ipv6)));
|
||||
}
|
||||
|
||||
TEST(MdnsMessageTest, ReadTwoAnswersForIPv4AndIPv6AddrWithNameCompression) {
|
||||
MdnsMessage msg;
|
||||
ASSERT_TRUE(ReadMdnsMessage(
|
||||
&msg, kTwoAuthoritativeAnswersWithIPv4AndIPv6AddrWithNameCompression));
|
||||
|
||||
std::map<std::string, rtc::IPAddress> resolution;
|
||||
EXPECT_TRUE(GetResolution(&msg, &resolution));
|
||||
rtc::IPAddress expected_addr_ipv4(
|
||||
rtc::SocketAddress("192.168.0.1", 0).ipaddr());
|
||||
rtc::IPAddress expected_addr_ipv6(
|
||||
rtc::SocketAddress("fd12:3456:789a:1::1", 0).ipaddr());
|
||||
EXPECT_THAT(resolution,
|
||||
UnorderedElementsAre(Pair("www.webrtc.org.", expected_addr_ipv4),
|
||||
Pair("webrtc.org.", expected_addr_ipv6)));
|
||||
}
|
||||
|
||||
TEST(MdnsMessageTest,
|
||||
ReadAnswerWithCorruptedPointerInNameCompressionShouldFail) {
|
||||
MdnsMessage msg;
|
||||
EXPECT_FALSE(ReadMdnsMessage(&msg, kCorruptedAnswerWithNameCompression1));
|
||||
EXPECT_FALSE(ReadMdnsMessage(&msg, kCorruptedAnswerWithNameCompression2));
|
||||
}
|
||||
|
||||
TEST(MdnsMessageTest, WriteSingleQuestionForIPv4Addr) {
|
||||
MdnsMessage msg;
|
||||
msg.SetId(0x1234);
|
||||
msg.SetQueryOrResponse(true);
|
||||
|
||||
MdnsQuestion question;
|
||||
question.SetName("webrtc.org.");
|
||||
question.SetType(SectionEntryType::kA);
|
||||
question.SetClass(SectionEntryClass::kIN);
|
||||
question.SetUnicastResponse(true);
|
||||
msg.AddQuestion(question);
|
||||
|
||||
WriteMdnsMessageAndCompare(&msg,
|
||||
kSingleQuestionForIPv4AddrWithUnicastResponse);
|
||||
}
|
||||
|
||||
TEST(MdnsMessageTest, WriteTwoQuestionsForIPv4AndIPv6Addr) {
|
||||
MdnsMessage msg;
|
||||
msg.SetId(0x1234);
|
||||
msg.SetQueryOrResponse(true);
|
||||
|
||||
MdnsQuestion question1;
|
||||
question1.SetName("webrtc4.org.");
|
||||
question1.SetType(SectionEntryType::kA);
|
||||
question1.SetClass(SectionEntryClass::kIN);
|
||||
msg.AddQuestion(question1);
|
||||
|
||||
MdnsQuestion question2;
|
||||
question2.SetName("webrtc6.org.");
|
||||
question2.SetType(SectionEntryType::kAAAA);
|
||||
question2.SetClass(SectionEntryClass::kIN);
|
||||
msg.AddQuestion(question2);
|
||||
|
||||
WriteMdnsMessageAndCompare(
|
||||
&msg, kTwoQuestionsForIPv4AndIPv6AddrWithMulticastResponse);
|
||||
}
|
||||
|
||||
TEST(MdnsMessageTest, WriteSingleAnswerToIPv4Addr) {
|
||||
MdnsMessage msg;
|
||||
msg.SetId(0x1234);
|
||||
msg.SetQueryOrResponse(false);
|
||||
msg.SetAuthoritative(true);
|
||||
|
||||
MdnsResourceRecord answer;
|
||||
answer.SetName("webrtc.org.");
|
||||
answer.SetType(SectionEntryType::kA);
|
||||
answer.SetClass(SectionEntryClass::kIN);
|
||||
EXPECT_TRUE(answer.SetIPAddressInRecordData(
|
||||
rtc::SocketAddress("192.168.0.1", 0).ipaddr()));
|
||||
answer.SetTtlSeconds(120);
|
||||
msg.AddAnswerRecord(answer);
|
||||
|
||||
WriteMdnsMessageAndCompare(&msg, kSingleAuthoritativeAnswerWithIPv4Addr);
|
||||
}
|
||||
|
||||
TEST(MdnsMessageTest, WriteTwoAnswersToIPv4AndIPv6Addr) {
|
||||
MdnsMessage msg;
|
||||
msg.SetId(0x1234);
|
||||
msg.SetQueryOrResponse(false);
|
||||
msg.SetAuthoritative(true);
|
||||
|
||||
MdnsResourceRecord answer1;
|
||||
answer1.SetName("webrtc4.org.");
|
||||
answer1.SetType(SectionEntryType::kA);
|
||||
answer1.SetClass(SectionEntryClass::kIN);
|
||||
answer1.SetIPAddressInRecordData(
|
||||
rtc::SocketAddress("192.168.0.1", 0).ipaddr());
|
||||
answer1.SetTtlSeconds(60);
|
||||
msg.AddAnswerRecord(answer1);
|
||||
|
||||
MdnsResourceRecord answer2;
|
||||
answer2.SetName("webrtc6.org.");
|
||||
answer2.SetType(SectionEntryType::kAAAA);
|
||||
answer2.SetClass(SectionEntryClass::kIN);
|
||||
answer2.SetIPAddressInRecordData(
|
||||
rtc::SocketAddress("fd12:3456:789a:1::1", 0).ipaddr());
|
||||
answer2.SetTtlSeconds(120);
|
||||
msg.AddAnswerRecord(answer2);
|
||||
|
||||
WriteMdnsMessageAndCompare(&msg, kTwoAuthoritativeAnswersWithIPv4AndIPv6Addr);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
@ -443,15 +443,6 @@ webrtc_fuzzer_test("stun_validator_fuzzer") {
|
||||
dict = "corpora/stun.tokens"
|
||||
}
|
||||
|
||||
webrtc_fuzzer_test("mdns_parser_fuzzer") {
|
||||
sources = [ "mdns_parser_fuzzer.cc" ]
|
||||
deps = [
|
||||
"../../p2p:rtc_p2p",
|
||||
"../../rtc_base:rtc_base_approved",
|
||||
]
|
||||
seed_corpus = "corpora/mdns-corpus"
|
||||
}
|
||||
|
||||
webrtc_fuzzer_test("pseudotcp_parser_fuzzer") {
|
||||
sources = [ "pseudotcp_parser_fuzzer.cc" ]
|
||||
deps = [
|
||||
|
||||
@ -1,27 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "p2p/base/mdns_message.h"
|
||||
#include "rtc_base/message_buffer_reader.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
void FuzzOneInput(const uint8_t* data, size_t size) {
|
||||
MessageBufferReader buf(reinterpret_cast<const char*>(data), size);
|
||||
auto mdns_msg = std::make_unique<MdnsMessage>();
|
||||
mdns_msg->Read(&buf);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
Loading…
x
Reference in New Issue
Block a user