Add the multicast DNS message format.

This CL adds the utilities to generate and parse mDNS messages (RFC 1035
and RFC 6762).

TBR=phoglund@webrtc.org

Bug: webrtc:9605
Change-Id: Id6121c17926887cd3a41a2dfc829462fd15f3a4c
Reviewed-on: https://webrtc-review.googlesource.com/93241
Commit-Queue: Qingsi Wang <qingsi@google.com>
Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org>
Reviewed-by: Qingsi Wang <qingsi@webrtc.org>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Reviewed-by: Alex Loiko <aleloi@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#24505}
This commit is contained in:
Qingsi Wang
2018-08-30 10:38:44 -07:00
committed by Commit Bot
parent cc22f51988
commit 558b93b3e9
30 changed files with 1256 additions and 1 deletions

View File

@ -31,6 +31,8 @@ rtc_static_library("rtc_p2p") {
"base/dtlstransportinternal.h", "base/dtlstransportinternal.h",
"base/icetransportinternal.cc", "base/icetransportinternal.cc",
"base/icetransportinternal.h", "base/icetransportinternal.h",
"base/mdns_message.cc",
"base/mdns_message.h",
"base/p2pconstants.cc", "base/p2pconstants.cc",
"base/p2pconstants.h", "base/p2pconstants.h",
"base/p2ptransportchannel.cc", "base/p2ptransportchannel.cc",
@ -150,6 +152,7 @@ if (rtc_include_tests) {
"base/asyncstuntcpsocket_unittest.cc", "base/asyncstuntcpsocket_unittest.cc",
"base/basicasyncresolverfactory_unittest.cc", "base/basicasyncresolverfactory_unittest.cc",
"base/dtlstransport_unittest.cc", "base/dtlstransport_unittest.cc",
"base/mdns_message_unittest.cc",
"base/p2ptransportchannel_unittest.cc", "base/p2ptransportchannel_unittest.cc",
"base/packetlossestimator_unittest.cc", "base/packetlossestimator_unittest.cc",
"base/port_unittest.cc", "base/port_unittest.cc",

395
p2p/base/mdns_message.cc Normal file
View File

@ -0,0 +1,395 @@
/*
* 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/nethelpers.h"
#include "rtc_base/stringencode.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 (auto rr : section) {
if (!rr.Write(buf)) {
return false;
}
}
return true;
};
for (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

207
p2p/base/mdns_message.h Normal file
View File

@ -0,0 +1,207 @@
/*
* 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 <map>
#include <memory>
#include <set>
#include <string>
#include <vector>
#include "rtc_base/bytebuffer.h"
#include "rtc_base/ipaddress.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

@ -0,0 +1,570 @@
/*
* 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 <map>
#include <set>
#include <string>
#include "p2p/base/mdns_message.h"
#include "rtc_base/bytebuffer.h"
#include "rtc_base/gunit.h"
#include "rtc_base/ipaddress.h"
#include "rtc_base/socketaddress.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

@ -413,6 +413,7 @@ rtc_source_set("rtc_base_approved_generic") {
"ignore_wundef.h", "ignore_wundef.h",
"location.cc", "location.cc",
"location.h", "location.h",
"message_buffer_reader.h",
"numerics/histogram_percentile_counter.cc", "numerics/histogram_percentile_counter.cc",
"numerics/histogram_percentile_counter.h", "numerics/histogram_percentile_counter.h",
"numerics/mod_ops.h", "numerics/mod_ops.h",

View File

@ -185,7 +185,7 @@ class ByteBufferReader : public ByteBuffer {
// after this call. // after this call.
bool Consume(size_t size); bool Consume(size_t size);
private: protected:
void Construct(const char* bytes, size_t size); void Construct(const char* bytes, size_t size);
const char* bytes_; const char* bytes_;
@ -193,6 +193,7 @@ class ByteBufferReader : public ByteBuffer {
size_t start_; size_t start_;
size_t end_; size_t end_;
private:
RTC_DISALLOW_COPY_AND_ASSIGN(ByteBufferReader); RTC_DISALLOW_COPY_AND_ASSIGN(ByteBufferReader);
}; };

View File

@ -0,0 +1,37 @@
/*
* 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 RTC_BASE_MESSAGE_BUFFER_READER_H_
#define RTC_BASE_MESSAGE_BUFFER_READER_H_
#include "rtc_base/bytebuffer.h"
namespace webrtc {
// A simple subclass of the ByteBufferReader that exposes the starting address
// of the message and its length, so that we can recall previously parsed data.
class MessageBufferReader : public rtc::ByteBufferReader {
public:
MessageBufferReader(const char* bytes, size_t len)
: rtc::ByteBufferReader(bytes, len) {}
~MessageBufferReader() = default;
// Starting address of the message.
const char* MessageData() const { return bytes_; }
// Total length of the message. Note that this is different from Length(),
// which is the length of the remaining message from the current offset.
size_t MessageLength() const { return size_; }
// Current offset in the message.
size_t CurrentOffset() const { return start_; }
};
} // namespace webrtc
#endif // RTC_BASE_MESSAGE_BUFFER_READER_H_

View File

@ -32,6 +32,9 @@ specific_include_rules = {
"+modules/pacing/packet_router.h", "+modules/pacing/packet_router.h",
"+modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h", "+modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h",
], ],
".*mdns_parser_fuzzer\.cc": [
"+p2p/base/mdns_message.h",
],
".*pseudotcp_parser_fuzzer\.cc": [ ".*pseudotcp_parser_fuzzer\.cc": [
"+p2p/base/pseudotcp.h", "+p2p/base/pseudotcp.h",
], ],

View File

@ -438,6 +438,18 @@ webrtc_fuzzer_test("stun_validator_fuzzer") {
dict = "corpora/stun.tokens" dict = "corpora/stun.tokens"
} }
webrtc_fuzzer_test("mdns_parser_fuzzer") {
sources = [
"mdns_parser_fuzzer.cc",
]
deps = [
"../../p2p:rtc_p2p",
"../../rtc_base:rtc_base_approved",
"//third_party/abseil-cpp/absl/memory",
]
seed_corpus = "corpora/mdns-corpus"
}
webrtc_fuzzer_test("pseudotcp_parser_fuzzer") { webrtc_fuzzer_test("pseudotcp_parser_fuzzer") {
sources = [ sources = [
"pseudotcp_parser_fuzzer.cc", "pseudotcp_parser_fuzzer.cc",

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,26 @@
/*
* 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 "absl/memory/memory.h"
#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 = absl::make_unique<MDnsMessage>();
mdns_msg->Read(&buf);
}
} // namespace webrtc