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:
Harald Alvestrand 2021-04-12 14:44:17 +00:00 committed by Commit Bot
parent eff79cfc75
commit c8cf0a6080
6 changed files with 0 additions and 1212 deletions

View File

@ -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",

View File

@ -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

View File

@ -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_

View File

@ -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

View File

@ -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 = [

View File

@ -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