mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 19:04:45 +00:00
Backed out 14 changesets (bug 1554976) for Windows build bustages on a CLOSED TREE.
Backed out changeset a9b209d9d880 (bug 1554976) Backed out changeset 27b4dddf9597 (bug 1554976) Backed out changeset 3e16c10bb966 (bug 1554976) Backed out changeset 6a404fca61dc (bug 1554976) Backed out changeset 77c4e76c8130 (bug 1554976) Backed out changeset 24f146b86cc4 (bug 1554976) Backed out changeset b49b4326dcfd (bug 1554976) Backed out changeset e2c837d1e0a0 (bug 1554976) Backed out changeset 24728144c263 (bug 1554976) Backed out changeset a099e69241a0 (bug 1554976) Backed out changeset 0e34595c2680 (bug 1554976) Backed out changeset a506bb40047e (bug 1554976) Backed out changeset 513026415092 (bug 1554976) Backed out changeset e0fc6a1d4332 (bug 1554976)
This commit is contained in:
parent
71c23d8716
commit
a6c5c5e3ac
23
Cargo.lock
generated
23
Cargo.lock
generated
@ -954,15 +954,6 @@ dependencies = [
|
||||
"winapi 0.3.6 (git+https://github.com/froydnj/winapi-rs?branch=aarch64)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dns-parser"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dogear"
|
||||
version = "0.3.3"
|
||||
@ -1286,7 +1277,6 @@ dependencies = [
|
||||
"kvstore 0.1.0",
|
||||
"lmdb-rkv-sys 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mdns_service 0.1.0",
|
||||
"mozurl 0.0.1",
|
||||
"mp4parse_capi 0.11.2",
|
||||
"netwerk_helper 0.0.1",
|
||||
@ -1745,18 +1735,6 @@ name = "matches"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "mdns_service"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"dns-parser 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"socket2 0.3.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "1.0.2"
|
||||
@ -3969,7 +3947,6 @@ dependencies = [
|
||||
"checksum devd-rs 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0d009f166c0d9e9f9909dc751630b3a6411ab7f85a153d32d01deb364ffe52a7"
|
||||
"checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c"
|
||||
"checksum dirs 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "88972de891f6118092b643d85a0b28e0678e0f948d7f879aa32f2d5aafe97d2a"
|
||||
"checksum dns-parser 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c4d33be9473d06f75f58220f71f7a9317aca647dc061dbd3c361b0bef505fbea"
|
||||
"checksum dogear 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "57cd6ee785daa898686f3e2fb4a2b1ce490fcd6d69665c857d16fb61b48f4aae"
|
||||
"checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab"
|
||||
"checksum dtoa-short 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "068d4026697c1a18f0b0bb8cfcad1b0c151b90d8edb9bf4c235ad68128920d1d"
|
||||
|
@ -1652,6 +1652,14 @@ PeerConnectionWrapper.prototype = {
|
||||
"usernameFragment not empty"
|
||||
);
|
||||
|
||||
// only check the m-section for the updated default addr that corresponds
|
||||
// with this candidate.
|
||||
var mSections = this.localDescription.sdp.split("\r\nm=");
|
||||
sdputils.checkSdpCLineNotDefault(
|
||||
mSections[anEvent.candidate.sdpMLineIndex + 1],
|
||||
this.label
|
||||
);
|
||||
|
||||
ok(
|
||||
typeof anEvent.candidate.sdpMLineIndex === "number",
|
||||
"SDP MLine Index needs to exist"
|
||||
|
@ -104,6 +104,7 @@ var sdputils = {
|
||||
msection.includes("a=end-of-candidates"),
|
||||
label + ": SDP contains end-of-candidates"
|
||||
);
|
||||
sdputils.checkSdpCLineNotDefault(msection, label);
|
||||
|
||||
if (!msection.startsWith("m=application")) {
|
||||
if (testOptions.rtcpmux) {
|
||||
@ -153,6 +154,16 @@ var sdputils = {
|
||||
}
|
||||
},
|
||||
|
||||
// takes sdp in string form (or possibly a fragment, say an m-section), and
|
||||
// verifies that the default 0.0.0.0 addr is not present.
|
||||
checkSdpCLineNotDefault: function(sdpStr, label) {
|
||||
info("CLINE-NO-DEFAULT-ADDR-SDP: " + JSON.stringify(sdpStr));
|
||||
ok(
|
||||
!sdpStr.includes("c=IN IP4 0.0.0.0"),
|
||||
label + ": SDP contains non-zero IP c line"
|
||||
);
|
||||
},
|
||||
|
||||
// Note, we don't bother removing the fmtp lines, which makes a good test
|
||||
// for some SDP parsing issues.
|
||||
removeCodec: function(sdp, codec) {
|
||||
|
@ -20,7 +20,6 @@ if (!("mediaDevices" in navigator)) {
|
||||
} else {
|
||||
runNetworkTest(async (options = {}) => {
|
||||
await pushPrefs(
|
||||
['media.peerconnection.ice.obfuscate_host_addresses', false],
|
||||
['media.peerconnection.nat_simulator.filtering_type', 'PORT_DEPENDENT'],
|
||||
['media.peerconnection.nat_simulator.mapping_type', 'PORT_DEPENDENT'],
|
||||
['media.getusermedia.insecure.enabled', true]);
|
||||
|
@ -19,7 +19,6 @@ if (!("mediaDevices" in navigator)) {
|
||||
} else {
|
||||
runNetworkTest(async (options = {}) => {
|
||||
await pushPrefs(
|
||||
['media.peerconnection.ice.obfuscate_host_addresses', false],
|
||||
['media.peerconnection.nat_simulator.filtering_type', 'PORT_DEPENDENT'],
|
||||
['media.peerconnection.nat_simulator.mapping_type', 'PORT_DEPENDENT'],
|
||||
['media.peerconnection.nat_simulator.block_udp', true],
|
||||
|
@ -19,7 +19,6 @@ if (!("mediaDevices" in navigator)) {
|
||||
} else {
|
||||
runNetworkTest(async (options = {}) => {
|
||||
await pushPrefs(
|
||||
['media.peerconnection.ice.obfuscate_host_addresses', false],
|
||||
['media.peerconnection.nat_simulator.filtering_type', 'PORT_DEPENDENT'],
|
||||
['media.peerconnection.nat_simulator.mapping_type', 'PORT_DEPENDENT'],
|
||||
['media.peerconnection.nat_simulator.block_udp', true],
|
||||
|
@ -20,7 +20,6 @@ if (!("mediaDevices" in navigator)) {
|
||||
} else {
|
||||
runNetworkTest(async (options = {}) => {
|
||||
await pushPrefs(
|
||||
['media.peerconnection.ice.obfuscate_host_addresses', false],
|
||||
['media.peerconnection.nat_simulator.filtering_type', 'ENDPOINT_INDEPENDENT'],
|
||||
['media.peerconnection.nat_simulator.mapping_type', 'ENDPOINT_INDEPENDENT'],
|
||||
['media.getusermedia.insecure.enabled', true]);
|
||||
|
@ -33,8 +33,7 @@ class MediaTransportParent : public dom::PMediaTransportParent {
|
||||
mozilla::ipc::IPCResult RecvSetTargetForDefaultLocalAddressLookup(
|
||||
const string& targetIp, uint16_t targetPort);
|
||||
mozilla::ipc::IPCResult RecvStartIceGathering(
|
||||
const bool& defaultRouteOnly, const bool& obfuscateAddresses,
|
||||
const net::NrIceStunAddrArray& stunAddrs);
|
||||
const bool& defaultRouteOnly, const net::NrIceStunAddrArray& stunAddrs);
|
||||
mozilla::ipc::IPCResult RecvActivateTransport(
|
||||
const string& transportId, const string& localUfrag,
|
||||
const string& localPwd, const int& componentCount,
|
||||
|
@ -59,7 +59,6 @@ parent:
|
||||
uint16_t targetPort);
|
||||
|
||||
async StartIceGathering(bool defaultRouteOnly,
|
||||
bool obfuscateHostAddresses,
|
||||
NrIceStunAddrArray stunAddrs);
|
||||
|
||||
async ActivateTransport(string transportId,
|
||||
|
@ -158,8 +158,7 @@ DEFINE_IPC_SERIALIZER_WITH_FIELDS(mozilla::dom::RTCIceServer, mCredential,
|
||||
|
||||
DEFINE_IPC_SERIALIZER_WITH_FIELDS(mozilla::CandidateInfo, mCandidate, mUfrag,
|
||||
mDefaultHostRtp, mDefaultPortRtp,
|
||||
mDefaultHostRtcp, mDefaultPortRtcp,
|
||||
mMDNSAddress, mActualAddress)
|
||||
mDefaultHostRtcp, mDefaultPortRtcp)
|
||||
|
||||
DEFINE_IPC_SERIALIZER_WITH_FIELDS(mozilla::DtlsDigest, algorithm_, value_)
|
||||
|
||||
|
@ -18,9 +18,6 @@ async protocol PStunAddrsRequest
|
||||
parent:
|
||||
async GetStunAddrs();
|
||||
|
||||
async RegisterMDNSHostname(nsCString hostname, nsCString address);
|
||||
async UnregisterMDNSHostname(nsCString hostname);
|
||||
|
||||
async __delete__();
|
||||
|
||||
child:
|
||||
|
@ -11,12 +11,6 @@
|
||||
#include "mtransport/nricemediastream.h" // needed only for including nricectx.h
|
||||
#include "mtransport/nricestunaddr.h"
|
||||
|
||||
#include "../mdns_service/mdns_service.h"
|
||||
|
||||
extern "C" {
|
||||
#include "local_addr.h"
|
||||
}
|
||||
|
||||
using namespace mozilla::ipc;
|
||||
|
||||
namespace mozilla {
|
||||
@ -30,14 +24,6 @@ StunAddrsRequestParent::StunAddrsRequestParent() : mIPCClosed(false) {
|
||||
MOZ_ASSERT(mSTSThread);
|
||||
}
|
||||
|
||||
StunAddrsRequestParent::~StunAddrsRequestParent() {
|
||||
ASSERT_ON_THREAD(mMainThread);
|
||||
|
||||
if (mSharedMDNSService) {
|
||||
mSharedMDNSService = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult StunAddrsRequestParent::RecvGetStunAddrs() {
|
||||
ASSERT_ON_THREAD(mMainThread);
|
||||
|
||||
@ -53,33 +39,6 @@ mozilla::ipc::IPCResult StunAddrsRequestParent::RecvGetStunAddrs() {
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult StunAddrsRequestParent::RecvRegisterMDNSHostname(
|
||||
const nsCString& aHostname, const nsCString& aAddress) {
|
||||
ASSERT_ON_THREAD(mMainThread);
|
||||
|
||||
if (mIPCClosed) {
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mSharedMDNSService->RegisterHostname(aHostname.BeginReading(),
|
||||
aAddress.BeginReading());
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult StunAddrsRequestParent::RecvUnregisterMDNSHostname(
|
||||
const nsCString& aHostname) {
|
||||
ASSERT_ON_THREAD(mMainThread);
|
||||
|
||||
if (mIPCClosed) {
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mSharedMDNSService->UnregisterHostname(aHostname.BeginReading());
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult StunAddrsRequestParent::Recv__delete__() {
|
||||
// see note below in ActorDestroy
|
||||
mIPCClosed = true;
|
||||
@ -120,71 +79,13 @@ void StunAddrsRequestParent::SendStunAddrs_m(const NrIceStunAddrArray& addrs) {
|
||||
return;
|
||||
}
|
||||
|
||||
// This means that the mDNS service will continue running until shutdown
|
||||
// once started. The StunAddrsRequestParent destructor does not run until
|
||||
// shutdown anyway (see Bug 1569311), so there is not much we can do about
|
||||
// this here. One option would be to add a check if there are no hostnames
|
||||
// registered after UnregisterHostname is called, and if so, stop the mDNS
|
||||
// service at that time (see Bug 1569955.)
|
||||
if (!mSharedMDNSService) {
|
||||
for (auto& addr : addrs) {
|
||||
nr_transport_addr* local_addr =
|
||||
const_cast<nr_transport_addr*>(&addr.localAddr().addr);
|
||||
if (addr.localAddr().addr.ip_version == NR_IPV4 &&
|
||||
!nr_transport_addr_is_loopback(local_addr)) {
|
||||
char addrstring[16];
|
||||
nr_transport_addr_get_addrstring(local_addr, addrstring, 16);
|
||||
mSharedMDNSService = new MDNSServiceWrapper(addrstring);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mIPCClosed = true;
|
||||
// send the new addresses back to the child
|
||||
Unused << SendOnStunAddrsAvailable(addrs);
|
||||
}
|
||||
|
||||
StaticRefPtr<StunAddrsRequestParent::MDNSServiceWrapper>
|
||||
StunAddrsRequestParent::mSharedMDNSService;
|
||||
|
||||
NS_IMPL_ADDREF(StunAddrsRequestParent)
|
||||
NS_IMPL_RELEASE(StunAddrsRequestParent)
|
||||
|
||||
StunAddrsRequestParent::MDNSServiceWrapper::MDNSServiceWrapper(
|
||||
const std::string& ifaddr)
|
||||
: ifaddr(ifaddr) {}
|
||||
|
||||
void StunAddrsRequestParent::MDNSServiceWrapper::RegisterHostname(
|
||||
const char* hostname, const char* address) {
|
||||
StartIfRequired();
|
||||
if (mMDNSService) {
|
||||
mdns_service_register_hostname(mMDNSService, hostname, address);
|
||||
}
|
||||
}
|
||||
|
||||
void StunAddrsRequestParent::MDNSServiceWrapper::UnregisterHostname(
|
||||
const char* hostname) {
|
||||
StartIfRequired();
|
||||
if (mMDNSService) {
|
||||
mdns_service_unregister_hostname(mMDNSService, hostname);
|
||||
}
|
||||
}
|
||||
|
||||
StunAddrsRequestParent::MDNSServiceWrapper::~MDNSServiceWrapper() {
|
||||
if (mMDNSService) {
|
||||
mdns_service_stop(mMDNSService);
|
||||
mMDNSService = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void StunAddrsRequestParent::MDNSServiceWrapper::StartIfRequired() {
|
||||
if (!mMDNSService) {
|
||||
mMDNSService = mdns_service_start(ifaddr.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_ADDREF(StunAddrsRequestParent::MDNSServiceWrapper)
|
||||
NS_IMPL_RELEASE(StunAddrsRequestParent::MDNSServiceWrapper)
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
@ -7,11 +7,6 @@
|
||||
|
||||
#include "mozilla/net/PStunAddrsRequestParent.h"
|
||||
|
||||
#include "nsICancelable.h"
|
||||
#include "nsIDNSServiceDiscovery.h"
|
||||
|
||||
struct MDNSService;
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
@ -27,13 +22,9 @@ class StunAddrsRequestParent : public PStunAddrsRequestParent {
|
||||
mozilla::ipc::IPCResult Recv__delete__() override;
|
||||
|
||||
protected:
|
||||
virtual ~StunAddrsRequestParent();
|
||||
virtual ~StunAddrsRequestParent() {}
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvGetStunAddrs() override;
|
||||
virtual mozilla::ipc::IPCResult RecvRegisterMDNSHostname(
|
||||
const nsCString& hostname, const nsCString& address) override;
|
||||
virtual mozilla::ipc::IPCResult RecvUnregisterMDNSHostname(
|
||||
const nsCString& hostname) override;
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override;
|
||||
|
||||
nsCOMPtr<nsIThread> mMainThread;
|
||||
@ -47,29 +38,6 @@ class StunAddrsRequestParent : public PStunAddrsRequestParent {
|
||||
|
||||
private:
|
||||
bool mIPCClosed; // true if IPDL channel has been closed (child crash)
|
||||
|
||||
class MDNSServiceWrapper {
|
||||
public:
|
||||
explicit MDNSServiceWrapper(const std::string& ifaddr);
|
||||
void RegisterHostname(const char* hostname, const char* address);
|
||||
void UnregisterHostname(const char* hostname);
|
||||
|
||||
NS_IMETHOD_(MozExternalRefCountType) AddRef();
|
||||
NS_IMETHOD_(MozExternalRefCountType) Release();
|
||||
|
||||
protected:
|
||||
ThreadSafeAutoRefCnt mRefCnt;
|
||||
NS_DECL_OWNINGTHREAD
|
||||
|
||||
private:
|
||||
virtual ~MDNSServiceWrapper();
|
||||
void StartIfRequired();
|
||||
|
||||
std::string ifaddr;
|
||||
MDNSService* mMDNSService = nullptr;
|
||||
};
|
||||
|
||||
static StaticRefPtr<MDNSServiceWrapper> mSharedMDNSService;
|
||||
};
|
||||
|
||||
} // namespace net
|
||||
|
@ -38,21 +38,7 @@ include("/ipc/chromium/chromium-config.mozbuild")
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
||||
DEFINES['R_DEFINED_INT2'] = 'int16_t'
|
||||
DEFINES['R_DEFINED_UINT2'] = 'uint16_t'
|
||||
DEFINES['R_DEFINED_INT4'] = 'int32_t'
|
||||
DEFINES['R_DEFINED_UINT4'] = 'uint32_t'
|
||||
# These are defined to avoid a conflict between typedefs in winsock2.h and
|
||||
# r_types.h. This is safe because these types are unused by the code here,
|
||||
# but still deeply unfortunate. There is similar code in the win32 version of
|
||||
# csi_platform.h, but that trick does not work here, even if that file is
|
||||
# directly included.
|
||||
DEFINES['R_DEFINED_INT8'] = 'int8_t'
|
||||
DEFINES['R_DEFINED_UINT8'] = 'uint8_t'
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'/media/mtransport/third_party/nICEr/src/net',
|
||||
'/media/mtransport/third_party/nrappkit/src/util/libekr',
|
||||
'/media/webrtc',
|
||||
'/media/webrtc/signaling/src/peerconnection',
|
||||
'/netwerk/base',
|
||||
|
@ -1,13 +0,0 @@
|
||||
[package]
|
||||
name = "mdns_service"
|
||||
version = "0.1.0"
|
||||
authors = ["Dan Minor <dminor@mozilla.com>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
byteorder = "1.3.1"
|
||||
dns-parser = "0.8.0"
|
||||
log = "0.4"
|
||||
mio = "0.6"
|
||||
socket2 = { version = "0.3.9", features = ["reuseport"] }
|
||||
uuid = { version = "0.7", features = ["v4"] }
|
@ -1,23 +0,0 @@
|
||||
#include <cstdarg>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <new>
|
||||
|
||||
struct MDNSService;
|
||||
|
||||
extern "C" {
|
||||
|
||||
void mdns_service_register_hostname(MDNSService* serv, const char* hostname,
|
||||
const char* addr);
|
||||
|
||||
MDNSService* mdns_service_start(const char* ifaddr);
|
||||
|
||||
void mdns_service_stop(MDNSService* serv);
|
||||
|
||||
void mdns_service_unregister_hostname(MDNSService* serv, const char* hostname);
|
||||
|
||||
const char* mdns_service_generate_uuid();
|
||||
|
||||
void mdns_service_free_uuid(const char* uuid);
|
||||
|
||||
} // extern "C"
|
@ -1,312 +0,0 @@
|
||||
/* -*- Mode: rust; rust-indent-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
use byteorder::{BigEndian, WriteBytesExt};
|
||||
use socket2::{Domain, Socket, Type};
|
||||
use std::collections::HashMap;
|
||||
use std::ffi::CStr;
|
||||
use std::ffi::CString;
|
||||
use std::io;
|
||||
use std::net;
|
||||
use std::os::raw::c_char;
|
||||
use std::sync::mpsc::channel;
|
||||
use std::thread;
|
||||
use std::time;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
|
||||
// This code is derived from code for creating questions in the dns-parser
|
||||
// crate. It would be nice to upstream this, or something similar.
|
||||
fn create_answer(id: u16, answers: &Vec<(String, &[u8])>) -> Result<Vec<u8>, &'static str> {
|
||||
let mut buf = Vec::with_capacity(512);
|
||||
let head = dns_parser::Header {
|
||||
id: id,
|
||||
query: false,
|
||||
opcode: dns_parser::Opcode::StandardQuery,
|
||||
authoritative: true,
|
||||
truncated: false,
|
||||
recursion_desired: false,
|
||||
recursion_available: false,
|
||||
authenticated_data: false,
|
||||
checking_disabled: false,
|
||||
response_code: dns_parser::ResponseCode::NoError,
|
||||
questions: 0,
|
||||
answers: answers.len() as u16,
|
||||
nameservers: 0,
|
||||
additional: 0,
|
||||
};
|
||||
|
||||
buf.extend([0u8; 12].iter());
|
||||
head.write(&mut buf[..12]);
|
||||
|
||||
for (name, addr) in answers {
|
||||
for part in name.split('.') {
|
||||
if part.len() > 62 {
|
||||
return Err("Name part length too long");
|
||||
}
|
||||
let ln = part.len() as u8;
|
||||
buf.push(ln);
|
||||
buf.extend(part.as_bytes());
|
||||
}
|
||||
buf.push(0);
|
||||
|
||||
if addr.len() == 4 {
|
||||
buf.write_u16::<BigEndian>(dns_parser::Type::A as u16)
|
||||
.unwrap();
|
||||
} else {
|
||||
buf.write_u16::<BigEndian>(dns_parser::Type::AAAA as u16)
|
||||
.unwrap();
|
||||
}
|
||||
// set cache flush bit
|
||||
buf.write_u16::<BigEndian>(dns_parser::Class::IN as u16 | (0x1 << 15))
|
||||
.unwrap();
|
||||
buf.write_u32::<BigEndian>(120).unwrap();
|
||||
buf.write_u16::<BigEndian>(addr.len() as u16).unwrap();
|
||||
buf.extend(*addr);
|
||||
}
|
||||
|
||||
Ok(buf)
|
||||
}
|
||||
|
||||
enum ServiceControl {
|
||||
Register { hostname: String, address: String },
|
||||
Unregister { hostname: String },
|
||||
Stop,
|
||||
}
|
||||
|
||||
pub struct MDNSService {
|
||||
sender: Option<std::sync::mpsc::Sender<ServiceControl>>,
|
||||
}
|
||||
|
||||
impl MDNSService {
|
||||
fn register_hostname(&mut self, hostname: &str, address: &str) {
|
||||
if let Some(sender) = &self.sender {
|
||||
if let Err(err) = sender.send(ServiceControl::Register {
|
||||
hostname: hostname.to_string(),
|
||||
address: address.to_string(),
|
||||
}) {
|
||||
warn!(
|
||||
"Could not send register hostname {} message: {}",
|
||||
hostname, err
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn unregister_hostname(&mut self, hostname: &str) {
|
||||
if let Some(sender) = &self.sender {
|
||||
if let Err(err) = sender.send(ServiceControl::Unregister {
|
||||
hostname: hostname.to_string(),
|
||||
}) {
|
||||
warn!(
|
||||
"Could not send unregister hostname {} message: {}",
|
||||
hostname, err
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn start(&mut self, addr: std::net::Ipv4Addr) -> io::Result<()> {
|
||||
let (sender, receiver) = channel();
|
||||
self.sender = Some(sender);
|
||||
|
||||
let port = 5353;
|
||||
|
||||
let socket = Socket::new(Domain::ipv4(), Type::dgram(), None).unwrap();
|
||||
socket.set_reuse_address(true)?;
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
socket.set_reuse_port(true)?;
|
||||
socket.bind(&socket2::SockAddr::from(std::net::SocketAddr::from((
|
||||
[0, 0, 0, 0],
|
||||
port,
|
||||
))))?;
|
||||
|
||||
let socket = socket.into_udp_socket();
|
||||
socket.set_multicast_loop_v4(true)?;
|
||||
socket.set_read_timeout(Some(time::Duration::from_millis(10)))?;
|
||||
socket.join_multicast_v4(&std::net::Ipv4Addr::new(224, 0, 0, 251), &addr)?;
|
||||
|
||||
let builder = thread::Builder::new().name("mdns_service".to_string());
|
||||
builder.spawn(move || {
|
||||
let mdns_addr = std::net::SocketAddr::from(([224, 0, 0, 251], port));
|
||||
let mut buffer: [u8; 1024] = [0; 1024];
|
||||
let mut hosts = HashMap::new();
|
||||
loop {
|
||||
match receiver.recv_timeout(time::Duration::from_millis(10)) {
|
||||
Ok(msg) => match msg {
|
||||
ServiceControl::Register { hostname, address } => {
|
||||
trace!("Registering {} for: {}", hostname, address);
|
||||
match address.parse().and_then(|ip| {
|
||||
Ok(match ip {
|
||||
net::IpAddr::V4(ip) => ip.octets().to_vec(),
|
||||
net::IpAddr::V6(ip) => ip.octets().to_vec(),
|
||||
})
|
||||
}) {
|
||||
Ok(octets) => {
|
||||
let mut v = Vec::new();
|
||||
v.extend(octets);
|
||||
hosts.insert(hostname, v);
|
||||
}
|
||||
Err(err) => {
|
||||
warn!(
|
||||
"Could not parse address for {}: {}: {}",
|
||||
hostname, address, err
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
ServiceControl::Unregister { hostname } => {
|
||||
trace!("Unregistering {}", hostname);
|
||||
hosts.remove(&hostname);
|
||||
}
|
||||
ServiceControl::Stop => {
|
||||
trace!("Stopping");
|
||||
break;
|
||||
}
|
||||
},
|
||||
Err(std::sync::mpsc::RecvTimeoutError::Disconnected) => {
|
||||
break;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
match socket.recv_from(&mut buffer) {
|
||||
Ok((amt, _)) => {
|
||||
if amt > 0 {
|
||||
let buffer = &buffer[0..amt];
|
||||
match dns_parser::Packet::parse(&buffer) {
|
||||
Ok(parsed) => {
|
||||
let mut answers: Vec<(String, &[u8])> = Vec::new();
|
||||
parsed
|
||||
.questions
|
||||
.iter()
|
||||
.filter(|question| {
|
||||
question.qtype == dns_parser::QueryType::A
|
||||
})
|
||||
.for_each(|question| {
|
||||
let qname = question.qname.to_string();
|
||||
trace!("mDNS question: {} {:?}", qname, question.qtype);
|
||||
if let Some(octets) = hosts.get(&qname) {
|
||||
trace!(
|
||||
"Sending mDNS answer for {}: {:?}",
|
||||
qname,
|
||||
octets
|
||||
);
|
||||
answers.push((qname, &octets));
|
||||
}
|
||||
});
|
||||
// TODO: If we did not answer every query
|
||||
// in this question, we should wait for a
|
||||
// random amount of time so as to not
|
||||
// collide with someone else responding to
|
||||
// this query.
|
||||
if answers.len() > 0 {
|
||||
if let Ok(buf) = create_answer(parsed.header.id, &answers) {
|
||||
if let Err(err) = socket.send_to(&buf, &mdns_addr) {
|
||||
warn!("Sending mDNS answer failed: {}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
warn!("Could not parse mDNS packet: {}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
if err.kind() != io::ErrorKind::WouldBlock
|
||||
&& err.kind() != io::ErrorKind::TimedOut
|
||||
{
|
||||
error!("Socket error: {}", err);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn stop(self) {
|
||||
if let Some(sender) = self.sender {
|
||||
if let Err(err) = sender.send(ServiceControl::Stop) {
|
||||
warn!("Could not stop mDNS Service: {}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn new() -> MDNSService {
|
||||
MDNSService { sender: None }
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn mdns_service_register_hostname(
|
||||
serv: *mut MDNSService,
|
||||
hostname: *const c_char,
|
||||
address: *const c_char,
|
||||
) {
|
||||
unsafe {
|
||||
let hostname = CStr::from_ptr(hostname).to_string_lossy();
|
||||
let address = CStr::from_ptr(address).to_string_lossy();
|
||||
(*serv).register_hostname(&hostname, &address);
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn mdns_service_start(ifaddr: *const c_char) -> *mut MDNSService {
|
||||
let mut r = Box::new(MDNSService::new());
|
||||
unsafe {
|
||||
let ifaddr = CStr::from_ptr(ifaddr).to_string_lossy();
|
||||
if let Ok(addr) = ifaddr.parse() {
|
||||
if let Err(err) = r.start(addr) {
|
||||
warn!("Could not start mDNS Service: {}", err);
|
||||
}
|
||||
} else {
|
||||
warn!("Could not parse interface address: {}", ifaddr);
|
||||
}
|
||||
}
|
||||
Box::into_raw(r)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn mdns_service_stop(serv: *mut MDNSService) {
|
||||
unsafe {
|
||||
let boxed = Box::from_raw(serv);
|
||||
boxed.stop();
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn mdns_service_unregister_hostname(
|
||||
serv: *mut MDNSService,
|
||||
hostname: *const c_char,
|
||||
) {
|
||||
unsafe {
|
||||
let hostname = CStr::from_ptr(hostname).to_string_lossy();
|
||||
(*serv).unregister_hostname(&hostname);
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn mdns_service_generate_uuid() -> *const c_char {
|
||||
let uuid = Uuid::new_v4().to_hyphenated().to_string();
|
||||
match CString::new(uuid) {
|
||||
Ok(uuid) => {
|
||||
uuid.into_raw()
|
||||
}
|
||||
Err(_) => unreachable!() // UUID should not contain 0 byte
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn mdns_service_free_uuid(uuid: *mut c_char) {
|
||||
unsafe {
|
||||
CString::from_raw(uuid);
|
||||
}
|
||||
}
|
@ -57,7 +57,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsError.h"
|
||||
#include "nsIEventTarget.h"
|
||||
#include "nsIUUIDGenerator.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
@ -97,10 +96,6 @@ extern "C" {
|
||||
#include "rlogconnector.h"
|
||||
#include "test_nr_socket.h"
|
||||
|
||||
extern "C" {
|
||||
#include "mdns_service/mdns_service.h"
|
||||
}
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
using std::shared_ptr;
|
||||
@ -280,8 +275,7 @@ NrIceCtx::NrIceCtx(const std::string& name, Policy policy)
|
||||
policy_(policy),
|
||||
nat_(nullptr),
|
||||
proxy_config_(nullptr),
|
||||
proxy_only_(false),
|
||||
obfuscate_host_addresses_(false) {}
|
||||
proxy_only_(false) {}
|
||||
|
||||
/* static */
|
||||
RefPtr<NrIceCtx> NrIceCtx::Create(const std::string& name, bool allow_loopback,
|
||||
@ -433,14 +427,10 @@ void NrIceCtx::trickle_cb(void* arg, nr_ice_ctx* ice_ctx,
|
||||
}
|
||||
|
||||
if (!candidate) {
|
||||
s->SignalCandidate(s, "", stream->ufrag, "", "");
|
||||
s->SignalCandidate(s, "", stream->ufrag);
|
||||
return;
|
||||
}
|
||||
|
||||
std::string actual_addr;
|
||||
std::string mdns_addr;
|
||||
ctx->GenerateObfuscatedAddress(candidate, &mdns_addr, &actual_addr);
|
||||
|
||||
// Format the candidate.
|
||||
char candidate_str[NR_ICE_MAX_ATTRIBUTE_SIZE];
|
||||
int r = nr_ice_format_candidate_attribute(candidate, candidate_str,
|
||||
@ -451,7 +441,7 @@ void NrIceCtx::trickle_cb(void* arg, nr_ice_ctx* ice_ctx,
|
||||
MOZ_MTLOG(ML_INFO, "NrIceCtx(" << ctx->name_ << "): trickling candidate "
|
||||
<< candidate_str);
|
||||
|
||||
s->SignalCandidate(s, candidate_str, stream->ufrag, mdns_addr, actual_addr);
|
||||
s->SignalCandidate(s, candidate_str, stream->ufrag);
|
||||
}
|
||||
|
||||
void NrIceCtx::InitializeGlobals(bool allow_loopback, bool tcp_enabled,
|
||||
@ -868,12 +858,8 @@ void NrIceCtx::SetCtxFlags(bool default_route_only, bool proxy_only) {
|
||||
}
|
||||
}
|
||||
|
||||
nsresult NrIceCtx::StartGathering(bool default_route_only, bool proxy_only,
|
||||
bool obfuscate_host_addresses) {
|
||||
nsresult NrIceCtx::StartGathering(bool default_route_only, bool proxy_only) {
|
||||
ASSERT_ON_THREAD(sts_target_);
|
||||
|
||||
obfuscate_host_addresses_ = obfuscate_host_addresses;
|
||||
|
||||
SetGatheringState(ICE_CTX_GATHER_STARTED);
|
||||
|
||||
SetCtxFlags(default_route_only, proxy_only);
|
||||
@ -1047,35 +1033,6 @@ void NrIceCtx::SetGatheringState(GatheringState state) {
|
||||
SignalGatheringStateChange(this, state);
|
||||
}
|
||||
|
||||
void NrIceCtx::GenerateObfuscatedAddress(nr_ice_candidate* candidate,
|
||||
std::string* mdns_address,
|
||||
std::string* actual_address) {
|
||||
if (candidate->type == HOST && obfuscate_host_addresses_) {
|
||||
int r;
|
||||
char addr[64];
|
||||
if ((r = nr_transport_addr_get_addrstring(&candidate->addr, addr,
|
||||
sizeof(addr)))) {
|
||||
return;
|
||||
}
|
||||
|
||||
*actual_address = addr;
|
||||
|
||||
const auto& iter = obfuscated_host_addresses_.find(*actual_address);
|
||||
if (iter != obfuscated_host_addresses_.end()) {
|
||||
*mdns_address = iter->second;
|
||||
} else {
|
||||
const char* uuid = mdns_service_generate_uuid();
|
||||
std::ostringstream o;
|
||||
o << uuid << ".local";
|
||||
*mdns_address = o.str();
|
||||
mdns_service_free_uuid(uuid);
|
||||
|
||||
obfuscated_host_addresses_[*actual_address] = *mdns_address;
|
||||
}
|
||||
candidate->mdns_addr = r_strdup(mdns_address->c_str());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
// Reimplement nr_ice_compute_codeword to avoid copyright issues
|
||||
|
@ -311,8 +311,7 @@ class NrIceCtx {
|
||||
bool proxy_only() const { return proxy_only_; }
|
||||
|
||||
// Start ICE gathering
|
||||
nsresult StartGathering(bool default_route_only, bool proxy_only,
|
||||
bool obfuscate_host_addresses);
|
||||
nsresult StartGathering(bool default_route_only, bool proxy_only);
|
||||
|
||||
// Start checking
|
||||
nsresult StartChecks();
|
||||
@ -377,10 +376,6 @@ class NrIceCtx {
|
||||
// Set the state
|
||||
void SetGatheringState(GatheringState state);
|
||||
|
||||
void GenerateObfuscatedAddress(nr_ice_candidate* candidate,
|
||||
std::string* mdns_address,
|
||||
std::string* actual_address);
|
||||
|
||||
ConnectionState connection_state_;
|
||||
GatheringState gathering_state_;
|
||||
const std::string name_;
|
||||
@ -396,8 +391,6 @@ class NrIceCtx {
|
||||
RefPtr<TestNat> nat_;
|
||||
std::shared_ptr<NrSocketProxyConfig> proxy_config_;
|
||||
bool proxy_only_;
|
||||
bool obfuscate_host_addresses_;
|
||||
std::map<std::string, std::string> obfuscated_host_addresses_;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -194,8 +194,7 @@ class NrIceMediaStream {
|
||||
// the candidate belongs to.
|
||||
const std::string& GetId() const { return id_; }
|
||||
|
||||
sigslot::signal5<NrIceMediaStream*, const std::string&, const std::string&,
|
||||
const std::string&, const std::string&>
|
||||
sigslot::signal3<NrIceMediaStream*, const std::string&, const std::string&>
|
||||
SignalCandidate; // A new ICE candidate:
|
||||
|
||||
sigslot::signal1<NrIceMediaStream*> SignalReady; // Candidate pair ready.
|
||||
|
@ -537,7 +537,7 @@ class IceTestPeer : public sigslot::has_slots<> {
|
||||
|
||||
test_utils_->sts_target()->Dispatch(
|
||||
WrapRunnableRet(&res, ice_ctx_, &NrIceCtx::StartGathering,
|
||||
default_route_only, false, false),
|
||||
default_route_only, false),
|
||||
NS_DISPATCH_SYNC);
|
||||
|
||||
ASSERT_TRUE(NS_SUCCEEDED(res));
|
||||
@ -984,9 +984,7 @@ class IceTestPeer : public sigslot::has_slots<> {
|
||||
|
||||
void CandidateInitialized(NrIceMediaStream* stream,
|
||||
const std::string& raw_candidate,
|
||||
const std::string& ufrag,
|
||||
const std::string& mdns_addr,
|
||||
const std::string& actual_addr) {
|
||||
const std::string& ufrag) {
|
||||
std::string candidate(FilterCandidate(raw_candidate));
|
||||
if (candidate.empty()) {
|
||||
return;
|
||||
|
@ -619,7 +619,7 @@ class TransportTestPeer : public sigslot::has_slots<> {
|
||||
|
||||
// Start gathering
|
||||
test_utils_->sts_target()->Dispatch(
|
||||
WrapRunnableRet(&res, ice_ctx_, &NrIceCtx::StartGathering, false, false,
|
||||
WrapRunnableRet(&res, ice_ctx_, &NrIceCtx::StartGathering, false,
|
||||
false),
|
||||
NS_DISPATCH_SYNC);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(res));
|
||||
@ -634,8 +634,7 @@ class TransportTestPeer : public sigslot::has_slots<> {
|
||||
|
||||
// New candidate
|
||||
void GotCandidate(NrIceMediaStream* stream, const std::string& candidate,
|
||||
const std::string& ufrag, const std::string& mdns_addr,
|
||||
const std::string& actual_addr) {
|
||||
const std::string& ufrag) {
|
||||
std::cerr << "Got candidate " << candidate << " (ufrag=" << ufrag << ")"
|
||||
<< std::endl;
|
||||
}
|
||||
|
@ -947,14 +947,8 @@ int nr_ice_format_candidate_attribute(nr_ice_candidate *cand, char *attr, int ma
|
||||
assert(!strcmp(nr_ice_candidate_type_names[HOST], "host"));
|
||||
assert(!strcmp(nr_ice_candidate_type_names[RELAYED], "relay"));
|
||||
|
||||
if (cand->mdns_addr) {
|
||||
/* mdns_addr is NSID_LENGTH which is 39, - 2 for removing the "{" and "}"
|
||||
+ 6 for ".local" for a total of 43. */
|
||||
strncpy(addr, cand->mdns_addr, sizeof(addr) - 1);
|
||||
} else {
|
||||
if(r=nr_transport_addr_get_addrstring(&cand->addr,addr,sizeof(addr)))
|
||||
ABORT(r);
|
||||
}
|
||||
if(r=nr_transport_addr_get_addrstring(&cand->addr,addr,sizeof(addr)))
|
||||
ABORT(r);
|
||||
if(r=nr_transport_addr_get_port(&cand->addr,&port))
|
||||
ABORT(r);
|
||||
/* https://tools.ietf.org/html/rfc6544#section-4.5 */
|
||||
|
@ -167,7 +167,7 @@ class LoopbackTransport : public MediaTransportHandler {
|
||||
// capture permissions have been granted on the window, which could easily
|
||||
// change between Init (ie; when the PC is created) and StartIceGathering
|
||||
// (ie; when we set the local description).
|
||||
void StartIceGathering(bool aDefaultRouteOnly, bool aObfuscateAddresses,
|
||||
void StartIceGathering(bool aDefaultRouteOnly,
|
||||
// TODO: It probably makes sense to look
|
||||
// this up internally
|
||||
const nsTArray<NrIceStunAddr>& aStunAddrs) override {}
|
||||
|
@ -13,8 +13,6 @@ namespace mozilla {
|
||||
// This is used both by IPDL code, and by signaling code.
|
||||
struct CandidateInfo {
|
||||
std::string mCandidate;
|
||||
std::string mMDNSAddress;
|
||||
std::string mActualAddress;
|
||||
std::string mUfrag;
|
||||
std::string mDefaultHostRtp;
|
||||
uint16_t mDefaultPortRtp = 0;
|
||||
|
@ -86,7 +86,7 @@ class MediaTransportHandlerSTS : public MediaTransportHandler,
|
||||
// capture permissions have been granted on the window, which could easily
|
||||
// change between Init (ie; when the PC is created) and StartIceGathering
|
||||
// (ie; when we set the local description).
|
||||
void StartIceGathering(bool aDefaultRouteOnly, bool aObfuscateHostAddresses,
|
||||
void StartIceGathering(bool aDefaultRouteOnly,
|
||||
// This will go away once mtransport moves to its
|
||||
// own process, because we won't need to get this
|
||||
// via IPC anymore
|
||||
@ -147,8 +147,7 @@ class MediaTransportHandlerSTS : public MediaTransportHandler,
|
||||
NrIceCtx::ConnectionState aState);
|
||||
void OnCandidateFound(NrIceMediaStream* aStream,
|
||||
const std::string& aCandidate,
|
||||
const std::string& aUfrag, const std::string& aMDNSAddr,
|
||||
const std::string& aActualAddr);
|
||||
const std::string& aUfrag);
|
||||
void OnStateChange(TransportLayer* aLayer, TransportLayer::State);
|
||||
void OnRtcpStateChange(TransportLayer* aLayer, TransportLayer::State);
|
||||
void PacketReceived(TransportLayer* aLayer, MediaPacket& aPacket);
|
||||
@ -657,8 +656,7 @@ void MediaTransportHandlerSTS::SetTargetForDefaultLocalAddressLookup(
|
||||
}
|
||||
|
||||
void MediaTransportHandlerSTS::StartIceGathering(
|
||||
bool aDefaultRouteOnly, bool aObfuscateHostAddresses,
|
||||
const nsTArray<NrIceStunAddr>& aStunAddrs) {
|
||||
bool aDefaultRouteOnly, const nsTArray<NrIceStunAddr>& aStunAddrs) {
|
||||
mInitPromise->Then(
|
||||
mStsThread, __func__,
|
||||
[=, self = RefPtr<MediaTransportHandlerSTS>(this)]() {
|
||||
@ -678,8 +676,7 @@ void MediaTransportHandlerSTS::StartIceGathering(
|
||||
|
||||
// Start gathering, but only if there are streams
|
||||
if (!mIceCtx->GetStreams().empty()) {
|
||||
mIceCtx->StartGathering(aDefaultRouteOnly, mProxyOnly,
|
||||
aObfuscateHostAddresses);
|
||||
mIceCtx->StartGathering(aDefaultRouteOnly, mProxyOnly);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1360,10 +1357,9 @@ void MediaTransportHandlerSTS::OnConnectionStateChange(
|
||||
}
|
||||
|
||||
// The stuff below here will eventually go into the MediaTransportChild class
|
||||
void MediaTransportHandlerSTS::OnCandidateFound(
|
||||
NrIceMediaStream* aStream, const std::string& aCandidate,
|
||||
const std::string& aUfrag, const std::string& aMDNSAddr,
|
||||
const std::string& aActualAddr) {
|
||||
void MediaTransportHandlerSTS::OnCandidateFound(NrIceMediaStream* aStream,
|
||||
const std::string& aCandidate,
|
||||
const std::string& aUfrag) {
|
||||
CandidateInfo info;
|
||||
info.mCandidate = aCandidate;
|
||||
MOZ_ASSERT(!aUfrag.empty());
|
||||
@ -1372,13 +1368,8 @@ void MediaTransportHandlerSTS::OnCandidateFound(
|
||||
NrIceCandidate defaultRtcpCandidate;
|
||||
nsresult rv = aStream->GetDefaultCandidate(1, &defaultRtpCandidate);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
if (!defaultRtpCandidate.mdns_addr.empty()) {
|
||||
info.mDefaultHostRtp = "0.0.0.0";
|
||||
info.mDefaultPortRtp = 9;
|
||||
} else {
|
||||
info.mDefaultHostRtp = defaultRtpCandidate.cand_addr.host;
|
||||
info.mDefaultPortRtp = defaultRtpCandidate.cand_addr.port;
|
||||
}
|
||||
info.mDefaultHostRtp = defaultRtpCandidate.cand_addr.host;
|
||||
info.mDefaultPortRtp = defaultRtpCandidate.cand_addr.port;
|
||||
} else {
|
||||
CSFLogError(LOGTAG,
|
||||
"%s: GetDefaultCandidates failed for transport id %s, "
|
||||
@ -1389,17 +1380,10 @@ void MediaTransportHandlerSTS::OnCandidateFound(
|
||||
|
||||
// Optional; component won't exist if doing rtcp-mux
|
||||
if (NS_SUCCEEDED(aStream->GetDefaultCandidate(2, &defaultRtcpCandidate))) {
|
||||
if (!defaultRtcpCandidate.mdns_addr.empty()) {
|
||||
info.mDefaultHostRtcp = defaultRtcpCandidate.mdns_addr;
|
||||
} else {
|
||||
info.mDefaultHostRtcp = defaultRtcpCandidate.cand_addr.host;
|
||||
}
|
||||
info.mDefaultHostRtcp = defaultRtcpCandidate.cand_addr.host;
|
||||
info.mDefaultPortRtcp = defaultRtcpCandidate.cand_addr.port;
|
||||
}
|
||||
|
||||
info.mMDNSAddress = aMDNSAddr;
|
||||
info.mActualAddress = aActualAddr;
|
||||
|
||||
OnCandidate(aStream->GetId(), info);
|
||||
}
|
||||
|
||||
@ -1435,8 +1419,9 @@ NS_IMPL_ISUPPORTS(MediaTransportHandlerSTS::DNSListener, nsIDNSListener);
|
||||
|
||||
nsresult MediaTransportHandlerSTS::DNSListener::OnLookupComplete(
|
||||
nsICancelable* aRequest, nsIDNSRecord* aRecord, nsresult aStatus) {
|
||||
MOZ_ASSERT(mTransportHandler.mStsThread->IsOnCurrentThread());
|
||||
|
||||
if (mCancel) {
|
||||
MOZ_ASSERT(mTransportHandler.mStsThread->IsOnCurrentThread());
|
||||
if (NS_SUCCEEDED(aStatus)) {
|
||||
nsTArray<net::NetAddr> addresses;
|
||||
aRecord->GetAddresses(addresses);
|
||||
|
@ -86,7 +86,6 @@ class MediaTransportHandler {
|
||||
// change between Init (ie; when the PC is created) and StartIceGathering
|
||||
// (ie; when we set the local description).
|
||||
virtual void StartIceGathering(bool aDefaultRouteOnly,
|
||||
bool aObfuscateHostAddresses,
|
||||
// TODO: It probably makes sense to look
|
||||
// this up internally
|
||||
const nsTArray<NrIceStunAddr>& aStunAddrs) = 0;
|
||||
|
@ -209,15 +209,14 @@ void MediaTransportHandlerIPC::SetTargetForDefaultLocalAddressLookup(
|
||||
// change between Init (ie; when the PC is created) and StartIceGathering
|
||||
// (ie; when we set the local description).
|
||||
void MediaTransportHandlerIPC::StartIceGathering(
|
||||
bool aDefaultRouteOnly, bool aObfuscateHostAddresses,
|
||||
bool aDefaultRouteOnly,
|
||||
// TODO(bug 1522205): It probably makes sense to look this up internally
|
||||
const nsTArray<NrIceStunAddr>& aStunAddrs) {
|
||||
mInitPromise->Then(
|
||||
mCallbackThread, __func__,
|
||||
[=, self = RefPtr<MediaTransportHandlerIPC>(this)](bool /*dummy*/) {
|
||||
if (mChild) {
|
||||
mChild->SendStartIceGathering(aDefaultRouteOnly,
|
||||
aObfuscateHostAddresses, aStunAddrs);
|
||||
mChild->SendStartIceGathering(aDefaultRouteOnly, aStunAddrs);
|
||||
}
|
||||
},
|
||||
[](const nsCString& aError) {});
|
||||
|
@ -43,7 +43,7 @@ class MediaTransportHandlerIPC : public MediaTransportHandler {
|
||||
// capture permissions have been granted on the window, which could easily
|
||||
// change between Init (ie; when the PC is created) and StartIceGathering
|
||||
// (ie; when we set the local description).
|
||||
void StartIceGathering(bool aDefaultRouteOnly, bool aObfuscateHostAddresses,
|
||||
void StartIceGathering(bool aDefaultRouteOnly,
|
||||
// TODO: It probably makes sense to look
|
||||
// this up internally
|
||||
const nsTArray<NrIceStunAddr>& aStunAddrs) override;
|
||||
|
@ -158,10 +158,8 @@ MediaTransportParent::RecvSetTargetForDefaultLocalAddressLookup(
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult MediaTransportParent::RecvStartIceGathering(
|
||||
const bool& defaultRouteOnly, const bool& obfuscateHostAddresses,
|
||||
const net::NrIceStunAddrArray& stunAddrs) {
|
||||
mImpl->mHandler->StartIceGathering(defaultRouteOnly, obfuscateHostAddresses,
|
||||
stunAddrs);
|
||||
const bool& defaultRouteOnly, const net::NrIceStunAddrArray& stunAddrs) {
|
||||
mImpl->mHandler->StartIceGathering(defaultRouteOnly, stunAddrs);
|
||||
return ipc::IPCResult::Ok();
|
||||
}
|
||||
|
||||
|
@ -52,6 +52,7 @@ void PeerConnectionMedia::StunAddrsHandler::OnStunAddrsAvailable(
|
||||
if (pcm_) {
|
||||
pcm_->mStunAddrs = addrs;
|
||||
pcm_->mLocalAddrsCompleted = true;
|
||||
pcm_->mStunAddrsRequest = nullptr;
|
||||
pcm_->FlushIceCtxOperationQueueIfReady();
|
||||
// If parent process returns 0 STUN addresses, change ICE connection
|
||||
// state to failed.
|
||||
@ -72,29 +73,33 @@ PeerConnectionMedia::PeerConnectionMedia(PeerConnectionImpl* parent)
|
||||
mSTSThread(mParent->GetSTSThread()),
|
||||
mProxyResolveCompleted(false),
|
||||
mProxyConfig(nullptr),
|
||||
mStunAddrsRequest(nullptr),
|
||||
mLocalAddrsCompleted(false),
|
||||
mTargetForDefaultLocalAddressLookupIsSet(false),
|
||||
mDestroyed(false) {
|
||||
if (XRE_IsContentProcess()) {
|
||||
nsCOMPtr<nsIEventTarget> target =
|
||||
mParent->GetWindow()
|
||||
? mParent->GetWindow()->EventTargetFor(TaskCategory::Other)
|
||||
: nullptr;
|
||||
|
||||
mStunAddrsRequest =
|
||||
new net::StunAddrsRequestChild(new StunAddrsHandler(this), target);
|
||||
}
|
||||
}
|
||||
mDestroyed(false) {}
|
||||
|
||||
PeerConnectionMedia::~PeerConnectionMedia() {
|
||||
MOZ_RELEASE_ASSERT(!mMainThread);
|
||||
}
|
||||
|
||||
void PeerConnectionMedia::InitLocalAddrs() {
|
||||
if (mStunAddrsRequest) {
|
||||
if (XRE_IsContentProcess()) {
|
||||
CSFLogDebug(LOGTAG, "%s: Get stun addresses via IPC",
|
||||
mParentHandle.c_str());
|
||||
|
||||
nsCOMPtr<nsIEventTarget> target =
|
||||
mParent->GetWindow()
|
||||
? mParent->GetWindow()->EventTargetFor(TaskCategory::Other)
|
||||
: nullptr;
|
||||
|
||||
// We're in the content process, so send a request over IPC for the
|
||||
// stun address discovery.
|
||||
mStunAddrsRequest =
|
||||
new net::StunAddrsRequestChild(new StunAddrsHandler(this), target);
|
||||
mStunAddrsRequest->SendGetStunAddrs();
|
||||
} else {
|
||||
// No content process, so don't need to hold up the ice event queue
|
||||
// until completion of stun address discovery. We can let the
|
||||
// discovery of stun addresses happen in the same process.
|
||||
mLocalAddrsCompleted = true;
|
||||
}
|
||||
}
|
||||
@ -299,18 +304,6 @@ bool PeerConnectionMedia::GetPrefDefaultAddressOnly() const {
|
||||
return default_address_only;
|
||||
}
|
||||
|
||||
bool PeerConnectionMedia::GetPrefObfuscateHostAddresses() const {
|
||||
ASSERT_ON_THREAD(mMainThread); // will crash on STS thread
|
||||
|
||||
uint64_t winId = mParent->GetWindow()->WindowID();
|
||||
|
||||
bool obfuscate_host_addresses = Preferences::GetBool(
|
||||
"media.peerconnection.ice.obfuscate_host_addresses", false);
|
||||
obfuscate_host_addresses &=
|
||||
!MediaManager::Get()->IsActivelyCapturingOrHasAPermission(winId);
|
||||
return obfuscate_host_addresses;
|
||||
}
|
||||
|
||||
void PeerConnectionMedia::ConnectSignals() {
|
||||
mTransportHandler->SignalGatheringStateChange.connect(
|
||||
this, &PeerConnectionMedia::IceGatheringStateChange_s);
|
||||
@ -362,8 +355,7 @@ void PeerConnectionMedia::GatherIfReady() {
|
||||
mQueuedIceCtxOperations.clear();
|
||||
nsCOMPtr<nsIRunnable> runnable(WrapRunnable(
|
||||
RefPtr<PeerConnectionMedia>(this),
|
||||
&PeerConnectionMedia::EnsureIceGathering, GetPrefDefaultAddressOnly(),
|
||||
GetPrefObfuscateHostAddresses()));
|
||||
&PeerConnectionMedia::EnsureIceGathering, GetPrefDefaultAddressOnly()));
|
||||
|
||||
PerformOrEnqueueIceCtxOperation(runnable);
|
||||
}
|
||||
@ -413,8 +405,7 @@ nsresult PeerConnectionMedia::SetTargetForDefaultLocalAddressLookup() {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void PeerConnectionMedia::EnsureIceGathering(bool aDefaultRouteOnly,
|
||||
bool aObfuscateHostAddresses) {
|
||||
void PeerConnectionMedia::EnsureIceGathering(bool aDefaultRouteOnly) {
|
||||
if (mProxyConfig) {
|
||||
// Note that this could check if PrivacyRequested() is set on the PC and
|
||||
// remove "webrtc" from the ALPN list. But that would only work if the PC
|
||||
@ -444,8 +435,7 @@ void PeerConnectionMedia::EnsureIceGathering(bool aDefaultRouteOnly,
|
||||
return;
|
||||
}
|
||||
|
||||
mTransportHandler->StartIceGathering(aDefaultRouteOnly,
|
||||
aObfuscateHostAddresses, mStunAddrs);
|
||||
mTransportHandler->StartIceGathering(aDefaultRouteOnly, mStunAddrs);
|
||||
}
|
||||
|
||||
void PeerConnectionMedia::SelfDestruct() {
|
||||
@ -456,11 +446,6 @@ void PeerConnectionMedia::SelfDestruct() {
|
||||
mDestroyed = true;
|
||||
|
||||
if (mStunAddrsRequest) {
|
||||
for (auto& hostname : mRegisteredMDNSHostnames) {
|
||||
mStunAddrsRequest->SendUnregisterMDNSHostname(
|
||||
nsCString(hostname.c_str()));
|
||||
}
|
||||
mRegisteredMDNSHostnames.clear();
|
||||
mStunAddrsRequest->Cancel();
|
||||
mStunAddrsRequest = nullptr;
|
||||
}
|
||||
@ -672,21 +657,6 @@ void PeerConnectionMedia::OnCandidateFound_m(
|
||||
if (mParent) {
|
||||
mParent->OnCandidateFound(aTransportId, aCandidateInfo);
|
||||
}
|
||||
|
||||
if (mStunAddrsRequest && !aCandidateInfo.mMDNSAddress.empty()) {
|
||||
MOZ_ASSERT(!aCandidateInfo.mActualAddress.empty());
|
||||
|
||||
auto itor = mRegisteredMDNSHostnames.find(aCandidateInfo.mMDNSAddress);
|
||||
|
||||
// We'll see the address twice if we're generating both UDP and TCP
|
||||
// candidates.
|
||||
if (itor == mRegisteredMDNSHostnames.end()) {
|
||||
mRegisteredMDNSHostnames.insert(aCandidateInfo.mMDNSAddress);
|
||||
mStunAddrsRequest->SendRegisterMDNSHostname(
|
||||
nsCString(aCandidateInfo.mMDNSAddress.c_str()),
|
||||
nsCString(aCandidateInfo.mActualAddress.c_str()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PeerConnectionMedia::AlpnNegotiated_s(const std::string& aAlpn) {
|
||||
|
@ -167,10 +167,9 @@ class PeerConnectionMedia : public sigslot::has_slots<> {
|
||||
void FlushIceCtxOperationQueueIfReady();
|
||||
void PerformOrEnqueueIceCtxOperation(nsIRunnable* runnable);
|
||||
nsresult SetTargetForDefaultLocalAddressLookup();
|
||||
void EnsureIceGathering(bool aDefaultRouteOnly, bool aObfuscateHostAddresses);
|
||||
void EnsureIceGathering(bool aDefaultRouteOnly);
|
||||
|
||||
bool GetPrefDefaultAddressOnly() const;
|
||||
bool GetPrefObfuscateHostAddresses() const;
|
||||
|
||||
void ConnectSignals();
|
||||
|
||||
@ -231,9 +230,6 @@ class PeerConnectionMedia : public sigslot::has_slots<> {
|
||||
// Set to true when the object is going to be released.
|
||||
bool mDestroyed;
|
||||
|
||||
// Used to store the mDNS hostnames that we have registered
|
||||
std::set<std::string> mRegisteredMDNSHostnames;
|
||||
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PeerConnectionMedia)
|
||||
};
|
||||
|
||||
|
@ -551,7 +551,6 @@ pref("media.videocontrols.picture-in-picture.video-toggle.always-show", false);
|
||||
pref("media.peerconnection.ice.trickle_grace_period", 5000);
|
||||
pref("media.peerconnection.ice.no_host", false);
|
||||
pref("media.peerconnection.ice.default_address_only", false);
|
||||
pref("media.peerconnection.ice.obfuscate_host_addresses", false);
|
||||
pref("media.peerconnection.ice.proxy_only_if_behind_proxy", false);
|
||||
pref("media.peerconnection.ice.proxy_only", false);
|
||||
pref("media.peerconnection.turn.disable", false);
|
||||
|
@ -254,14 +254,16 @@ def check_networking(binary):
|
||||
retcode = 0
|
||||
networking_functions = set([
|
||||
# socketpair is not concerning; it is restricted to AF_UNIX
|
||||
"connect", "accept", "listen", "getsockname", "getsockopt",
|
||||
"recv", "send",
|
||||
"socket", "connect", "accept", "bind", "listen",
|
||||
"getsockname", "getsockopt", "setsockopt",
|
||||
"recv", "recvfrom",
|
||||
"send", "sendto",
|
||||
# We would be concerned by recvmsg and sendmsg; but we believe
|
||||
# they are okay as documented in 1376621#c23
|
||||
"gethostbyname", "gethostbyaddr", "gethostent", "sethostent", "endhostent",
|
||||
"gethostent_r", "gethostbyname2", "gethostbyaddr_r", "gethostbyname_r",
|
||||
"gethostbyname2_r",
|
||||
"getservent", "getservbyname", "getservbyport", "setservent",
|
||||
"getaddrinfo", "getservent", "getservbyname", "getservbyport", "setservent",
|
||||
"getprotoent", "getprotobyname", "getprotobynumber", "setprotoent",
|
||||
"endprotoent"])
|
||||
bad_occurences_names = set()
|
||||
|
@ -1 +0,0 @@
|
||||
{"files":{"Cargo.toml":"7b47cb4d67f549cce93b578b0911177365055bbbc15790644251cac1856a11f7","LICENSE-APACHE":"c6596eb7be8581c18be736c846fb9173b69eccf6ef94c5135893ec56bd92ba08","LICENSE-MIT":"71fb06f353ef01dbb828a61a74eadbfc57ab4e1b20eaae1db68229f1647c4183","README.md":"85171334a4b9e672811377819e7f178abdd1870f09d1a1250fe25a7ffaf4b5bf","bulk.yaml":"17c2548388e0cd3a63473021a2f1e4ddedee082d79d9167cb31ad06a1890d3fc","examples/sync_tcp_client.rs":"8ba349565ae9872fc3e246469eab0f7041355d38100355d07a2c1ff2cd048476","examples/sync_udp_client.rs":"ee32137e43d6ab4da6c6f1b36d956042fb74d2704ec319acd058ca74fdc489c1","src/builder.rs":"1dc20c218e5e3b8d0d0f7cdc7ab585882d9960493881be5f17ad2ea5ce8c9dd5","src/enums.rs":"0e0afe0987805ac7361bb6fcaee8a235f375312fa372a6fc8d9b36a85710a9c9","src/error.rs":"6abc85f52724ef8aa12e1ff40a747a02b018b99ae259880a9ff222959f567200","src/header.rs":"f96466c2c0c5647fab0718e9e8289aa9933e988015e454c38ecb7d3c0b6b6813","src/lib.rs":"98994eb0dfea6864d9cf26e1c6ff32f31249e9eaec4583387524dc919e4dde49","src/name.rs":"3d80f16e473e32780e60d814ea3af54094e8c813af576743b108deaf960da27e","src/parser.rs":"02af73135af936115a0ac99da7d102d5ef3c58890abe98d0cfefcd3814b98463","src/rdata/a.rs":"a66498dc4f02af5c95b53f09e2860fed69881410eb02a30bceee0b976e8f8c41","src/rdata/aaaa.rs":"0163de1dc6a691f2ede528cb865f1197511800742879bda189e65aadd682e6c4","src/rdata/all.rs":"005b8edc4aae6f140332f75420c900bae91be66dfb2fdcdd177d51280bbc3750","src/rdata/axfr.rs":"19e18099a16baf33e34ea23905ec5913834aa367a034343551fe935a367f20db","src/rdata/cname.rs":"f31f3c490b6fcd9d5300d4c3903c398cfdd7ff89154685fc3fb182b3fa553ecf","src/rdata/hinfo.rs":"3edd6e2685a048b7d35872582490cdffa90ca7aa688ecffe1d91c46b9ccede1c","src/rdata/maila.rs":"f3f5a40cebd458ed83da7d910601cab761883eee14e991c677d325e6f2fcd968","src/rdata/mailb.rs":"6e09a86dab9a516b4022eefb6a06dcb7d9b06e15d3a80e8027db285e43e5f870","src/rdata/mb.rs":"b867aa5e0f1ec0970d8d6d6406773a8b7af5291dbcf1d8d78be9d017d8cc5a81","src/rdata/mf.rs":"2494cf316f1c2bf803237ce01e7bbbdf05a736fcac2536a06a34ebaf51c815ae","src/rdata/mg.rs":"14a1c9813bc7a33811efa4855c0ac29288cbc1ec535f7c67609333a2a8a5612b","src/rdata/minfo.rs":"72bf7b87ca494865327866ddf9733fb9b137cf2cd4222338237f107b4ff5062d","src/rdata/mod.rs":"0a6f377059eee38371893d17c31d97fb214f209c89c43f5f9302e3560150a220","src/rdata/mr.rs":"0140e5a4c1b6af5e55a61027c21e1760cd2b5a8f1929604d3884225b9433054a","src/rdata/mx.rs":"a38113e7b6efbc65831582fbfacbb6ed1937e167f1b8a19a36a27b0b600ec085","src/rdata/ns.rs":"2acf2d552f3e4f94af50b1c46a6cefc99515a930b099e2d93e9a595f4e1746b5","src/rdata/nsec.rs":"0a712e38c35c60815a2b1394e4bb4f9e229311e80bc9e59b0e854354f928d5a5","src/rdata/null.rs":"0ee8104671d5238da7885b90248ffc952f1558eaa43dfe15b60292166a992a38","src/rdata/opt.rs":"24eb3346b88b3aec18985bd2c1db6498160a59ed7fabfc8b45ce174f10638653","src/rdata/ptr.rs":"9ab2459fc87f90edb2bc7d0fbb97ab008cedf3ce62c042d1b25181914a5ee5c6","src/rdata/soa.rs":"0bf7321ff2891af8f9a3d6b58199464a77b1556e705fa1e9b52f23358bb4bf47","src/rdata/srv.rs":"7d755cb64f42d3096a763739e31959ebec439855380869cd801196bb507102aa","src/rdata/txt.rs":"9e00d2b64cfc53fa8ac510a8c624f5d42320cd90f8a50d040cfc666b530fd8ad","src/rdata/wks.rs":"abfb5572d2c270838489a6ff611c76cb0d3dc7470f44a6810fb89894febd8840","src/structs.rs":"4692edebde24c3be4a7aae81f75b8dc69a9c1ed460bf80740a75bc13f5e40b82","vagga.yaml":"3662f1f49317908fd54ab7830d53074b4bdd753ae85bc3a6fcf6fabaa6b42c70"},"package":"c4d33be9473d06f75f58220f71f7a9317aca647dc061dbd3c361b0bef505fbea"}
|
41
third_party/rust/dns-parser/Cargo.toml
vendored
41
third_party/rust/dns-parser/Cargo.toml
vendored
@ -1,41 +0,0 @@
|
||||
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
|
||||
#
|
||||
# When uploading crates to the registry Cargo will automatically
|
||||
# "normalize" Cargo.toml files for maximal compatibility
|
||||
# with all versions of Cargo and also rewrite `path` dependencies
|
||||
# to registry (e.g. crates.io) dependencies
|
||||
#
|
||||
# If you believe there's an error in this file please file an
|
||||
# issue against the rust-lang/cargo repository. If you're
|
||||
# editing this file be aware that the upstream Cargo.toml
|
||||
# will likely look very different (and much more reasonable)
|
||||
|
||||
[package]
|
||||
name = "dns-parser"
|
||||
version = "0.8.0"
|
||||
authors = ["Paul Colomiets <paul@colomiets.name>"]
|
||||
description = " Pure-rust DNS protocol parser library. This does not support network, only\n raw protocol parser.\n"
|
||||
homepage = "https://github.com/tailhook/dns-parser"
|
||||
documentation = "https://docs.rs/dns-parser"
|
||||
readme = "README.md"
|
||||
keywords = ["dns", "domain", "name", "parser"]
|
||||
categories = ["parser-implementations"]
|
||||
license = "MIT/Apache-2.0"
|
||||
[dependencies.byteorder]
|
||||
version = "1"
|
||||
|
||||
[dependencies.quick-error]
|
||||
version = "1.0.0"
|
||||
|
||||
[dependencies.serde]
|
||||
version = "1.0"
|
||||
optional = true
|
||||
|
||||
[dependencies.serde_derive]
|
||||
version = "1.0"
|
||||
optional = true
|
||||
[dev-dependencies.matches]
|
||||
version = "0.1.2"
|
||||
|
||||
[features]
|
||||
with-serde = ["serde", "serde_derive"]
|
202
third_party/rust/dns-parser/LICENSE-APACHE
vendored
202
third_party/rust/dns-parser/LICENSE-APACHE
vendored
@ -1,202 +0,0 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright {yyyy} {name of copyright owner}
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
19
third_party/rust/dns-parser/LICENSE-MIT
vendored
19
third_party/rust/dns-parser/LICENSE-MIT
vendored
@ -1,19 +0,0 @@
|
||||
Copyright (c) 2016 The dns-parser Developers
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
31
third_party/rust/dns-parser/README.md
vendored
31
third_party/rust/dns-parser/README.md
vendored
@ -1,31 +0,0 @@
|
||||
DNS Parser
|
||||
==========
|
||||
|
||||
**Status: beta**
|
||||
|
||||
[Documentation](https://docs.rs/dns-parser) |
|
||||
[Github](https://github.com/tailhook/dns-parser) |
|
||||
[Crate](https://crates.io/crates/dns-parser)
|
||||
|
||||
This is a parser of DNS protocol packets that is independent of any networking
|
||||
code.
|
||||
|
||||
|
||||
License
|
||||
=======
|
||||
|
||||
Licensed under either of
|
||||
|
||||
* Apache License, Version 2.0,
|
||||
(./LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
|
||||
* MIT license (./LICENSE-MIT or http://opensource.org/licenses/MIT)
|
||||
at your option.
|
||||
|
||||
Contribution
|
||||
------------
|
||||
|
||||
Unless you explicitly state otherwise, any contribution intentionally
|
||||
submitted for inclusion in the work by you, as defined in the Apache-2.0
|
||||
license, shall be dual licensed as above, without any additional terms or
|
||||
conditions.
|
||||
|
8
third_party/rust/dns-parser/bulk.yaml
vendored
8
third_party/rust/dns-parser/bulk.yaml
vendored
@ -1,8 +0,0 @@
|
||||
minimum-bulk: v0.4.5
|
||||
|
||||
versions:
|
||||
|
||||
- file: Cargo.toml
|
||||
block-start: ^\[package\]
|
||||
block-end: ^\[.*\]
|
||||
regex: ^version\s*=\s*"(\S+)"
|
@ -1,77 +0,0 @@
|
||||
extern crate dns_parser;
|
||||
|
||||
use std::env;
|
||||
use std::error::Error;
|
||||
use std::io::{Read, Write};
|
||||
use std::net::TcpStream;
|
||||
use std::process;
|
||||
|
||||
|
||||
use dns_parser::{Builder, Packet, RData, ResponseCode};
|
||||
use dns_parser::rdata::a::Record;
|
||||
use dns_parser::{QueryType, QueryClass};
|
||||
|
||||
|
||||
fn main() {
|
||||
let mut code = 0;
|
||||
for name in env::args().skip(1) {
|
||||
match resolve(&name) {
|
||||
Ok(()) => {},
|
||||
Err(e) => {
|
||||
eprintln!("Error resolving {:?}: {}", name, e);
|
||||
code = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
process::exit(code);
|
||||
}
|
||||
|
||||
fn resolve(name: &str) -> Result<(), Box<Error>> {
|
||||
let mut conn = TcpStream::connect("127.0.0.1:53")?;
|
||||
let mut builder = Builder::new_query(1, true);
|
||||
builder.add_question(name, false, QueryType::A, QueryClass::IN);
|
||||
let packet = builder.build().map_err(|_| "truncated packet")?;
|
||||
let psize = [((packet.len() >> 8) & 0xFF) as u8,
|
||||
(packet.len() & 0xFF) as u8];
|
||||
conn.write_all(&psize[..])?;
|
||||
conn.write_all(&packet)?;
|
||||
let mut buf = vec![0u8; 4096];
|
||||
let mut off = 0;
|
||||
let pkt = loop {
|
||||
if buf.len() - off < 4096 {
|
||||
buf.extend(&[0u8; 4096][..]);
|
||||
}
|
||||
match conn.read(&mut buf[off..]) {
|
||||
Ok(num) => {
|
||||
off += num;
|
||||
if off < 2 { continue; }
|
||||
let bytes = ((buf[0] as usize) << 8) | buf[1] as usize;
|
||||
if off < bytes + 2 {
|
||||
continue;
|
||||
}
|
||||
if num == 0 {
|
||||
return Err("Partial packet received".into());
|
||||
}
|
||||
break Packet::parse(&buf[2..off])?;
|
||||
}
|
||||
Err(e) => {
|
||||
return Err(Box::new(e));
|
||||
}
|
||||
}
|
||||
};
|
||||
if pkt.header.response_code != ResponseCode::NoError {
|
||||
return Err(pkt.header.response_code.into());
|
||||
}
|
||||
if pkt.answers.len() == 0 {
|
||||
return Err("No records received".into());
|
||||
}
|
||||
for ans in pkt.answers {
|
||||
match ans.data {
|
||||
RData::A(Record(ip)) => {
|
||||
println!("{}", ip);
|
||||
}
|
||||
_ => {} // ignore
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
extern crate dns_parser;
|
||||
|
||||
use std::env;
|
||||
use std::error::Error;
|
||||
use std::net::UdpSocket;
|
||||
use std::process;
|
||||
|
||||
|
||||
use dns_parser::{Builder, Packet, RData, ResponseCode};
|
||||
use dns_parser::rdata::a::Record;
|
||||
use dns_parser::{QueryType, QueryClass};
|
||||
|
||||
|
||||
fn main() {
|
||||
let mut code = 0;
|
||||
for name in env::args().skip(1) {
|
||||
match resolve(&name) {
|
||||
Ok(()) => {},
|
||||
Err(e) => {
|
||||
eprintln!("Error resolving {:?}: {}", name, e);
|
||||
code = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
process::exit(code);
|
||||
}
|
||||
|
||||
fn resolve(name: &str) -> Result<(), Box<Error>> {
|
||||
let sock = UdpSocket::bind("127.0.0.1:0")?;
|
||||
sock.connect("127.0.0.1:53")?;
|
||||
let mut builder = Builder::new_query(1, true);
|
||||
builder.add_question(name, false, QueryType::A, QueryClass::IN);
|
||||
let packet = builder.build().map_err(|_| "truncated packet")?;
|
||||
sock.send(&packet)?;
|
||||
let mut buf = vec![0u8; 4096];
|
||||
sock.recv(&mut buf)?;
|
||||
let pkt = Packet::parse(&buf)?;
|
||||
if pkt.header.response_code != ResponseCode::NoError {
|
||||
return Err(pkt.header.response_code.into());
|
||||
}
|
||||
if pkt.answers.len() == 0 {
|
||||
return Err("No records received".into());
|
||||
}
|
||||
for ans in pkt.answers {
|
||||
match ans.data {
|
||||
RData::A(Record(ip)) => {
|
||||
println!("{}", ip);
|
||||
}
|
||||
_ => {} // ignore
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
132
third_party/rust/dns-parser/src/builder.rs
vendored
132
third_party/rust/dns-parser/src/builder.rs
vendored
@ -1,132 +0,0 @@
|
||||
use byteorder::{ByteOrder, BigEndian, WriteBytesExt};
|
||||
|
||||
use {Opcode, ResponseCode, Header, QueryType, QueryClass};
|
||||
|
||||
/// Allows to build a DNS packet
|
||||
///
|
||||
/// Both query and answer packets may be built with this interface, although,
|
||||
/// much of functionality is not implemented yet.
|
||||
#[derive(Debug)]
|
||||
pub struct Builder {
|
||||
buf: Vec<u8>,
|
||||
}
|
||||
|
||||
impl Builder {
|
||||
/// Creates a new query
|
||||
///
|
||||
/// Initially all sections are empty. You're expected to fill
|
||||
/// the questions section with `add_question`
|
||||
pub fn new_query(id: u16, recursion: bool) -> Builder {
|
||||
let mut buf = Vec::with_capacity(512);
|
||||
let head = Header {
|
||||
id: id,
|
||||
query: true,
|
||||
opcode: Opcode::StandardQuery,
|
||||
authoritative: false,
|
||||
truncated: false,
|
||||
recursion_desired: recursion,
|
||||
recursion_available: false,
|
||||
authenticated_data: false,
|
||||
checking_disabled: false,
|
||||
response_code: ResponseCode::NoError,
|
||||
questions: 0,
|
||||
answers: 0,
|
||||
nameservers: 0,
|
||||
additional: 0,
|
||||
};
|
||||
buf.extend([0u8; 12].iter());
|
||||
head.write(&mut buf[..12]);
|
||||
Builder { buf: buf }
|
||||
}
|
||||
/// Adds a question to the packet
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// * Answers, nameservers or additional section has already been written
|
||||
/// * There are already 65535 questions in the buffer.
|
||||
/// * When name is invalid
|
||||
pub fn add_question(&mut self, qname: &str, prefer_unicast: bool,
|
||||
qtype: QueryType, qclass: QueryClass)
|
||||
-> &mut Builder
|
||||
{
|
||||
if &self.buf[6..12] != b"\x00\x00\x00\x00\x00\x00" {
|
||||
panic!("Too late to add a question");
|
||||
}
|
||||
self.write_name(qname);
|
||||
self.buf.write_u16::<BigEndian>(qtype as u16).unwrap();
|
||||
let prefer_unicast: u16 = if prefer_unicast { 0x8000 } else { 0x0000 };
|
||||
self.buf.write_u16::<BigEndian>(qclass as u16 | prefer_unicast).unwrap();
|
||||
let oldq = BigEndian::read_u16(&self.buf[4..6]);
|
||||
if oldq == 65535 {
|
||||
panic!("Too many questions");
|
||||
}
|
||||
BigEndian::write_u16(&mut self.buf[4..6], oldq+1);
|
||||
self
|
||||
}
|
||||
fn write_name(&mut self, name: &str) {
|
||||
for part in name.split('.') {
|
||||
assert!(part.len() < 63);
|
||||
let ln = part.len() as u8;
|
||||
self.buf.push(ln);
|
||||
self.buf.extend(part.as_bytes());
|
||||
}
|
||||
self.buf.push(0);
|
||||
}
|
||||
/// Returns the final packet
|
||||
///
|
||||
/// When packet is not truncated method returns `Ok(packet)`. If
|
||||
/// packet is truncated the method returns `Err(packet)`. In both
|
||||
/// cases the packet is fully valid.
|
||||
///
|
||||
/// In the server implementation you may use
|
||||
/// `x.build().unwrap_or_else(|x| x)`.
|
||||
///
|
||||
/// In the client implementation it's probably unwise to send truncated
|
||||
/// packet, as it doesn't make sense. Even panicking may be more
|
||||
/// appropriate.
|
||||
// TODO(tailhook) does the truncation make sense for TCP, and how
|
||||
// to treat it for EDNS0?
|
||||
pub fn build(mut self) -> Result<Vec<u8>,Vec<u8>> {
|
||||
// TODO(tailhook) optimize labels
|
||||
if self.buf.len() > 512 {
|
||||
Header::set_truncated(&mut self.buf[..12]);
|
||||
Err(self.buf)
|
||||
} else {
|
||||
Ok(self.buf)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use QueryType as QT;
|
||||
use QueryClass as QC;
|
||||
use super::Builder;
|
||||
|
||||
#[test]
|
||||
fn build_query() {
|
||||
let mut bld = Builder::new_query(1573, true);
|
||||
bld.add_question("example.com", false, QT::A, QC::IN);
|
||||
let result = b"\x06%\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\
|
||||
\x07example\x03com\x00\x00\x01\x00\x01";
|
||||
assert_eq!(&bld.build().unwrap()[..], &result[..]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_unicast_query() {
|
||||
let mut bld = Builder::new_query(1573, true);
|
||||
bld.add_question("example.com", true, QT::A, QC::IN);
|
||||
let result = b"\x06%\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\
|
||||
\x07example\x03com\x00\x00\x01\x80\x01";
|
||||
assert_eq!(&bld.build().unwrap()[..], &result[..]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_srv_query() {
|
||||
let mut bld = Builder::new_query(23513, true);
|
||||
bld.add_question("_xmpp-server._tcp.gmail.com", false, QT::SRV, QC::IN);
|
||||
let result = b"[\xd9\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\
|
||||
\x0c_xmpp-server\x04_tcp\x05gmail\x03com\x00\x00!\x00\x01";
|
||||
assert_eq!(&bld.build().unwrap()[..], &result[..]);
|
||||
}
|
||||
}
|
299
third_party/rust/dns-parser/src/enums.rs
vendored
299
third_party/rust/dns-parser/src/enums.rs
vendored
@ -1,299 +0,0 @@
|
||||
use {Error};
|
||||
use rdata::Record;
|
||||
use rdata::*;
|
||||
|
||||
/// The TYPE value according to RFC 1035
|
||||
///
|
||||
/// All "EXPERIMENTAL" markers here are from the RFC
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
pub enum Type {
|
||||
/// a host addresss
|
||||
A = a::Record::TYPE,
|
||||
/// an authoritative name server
|
||||
NS = ns::Record::TYPE,
|
||||
/// a mail forwarder (Obsolete - use MX)
|
||||
MF = mf::Record::TYPE,
|
||||
/// the canonical name for an alias
|
||||
CNAME = cname::Record::TYPE,
|
||||
/// marks the start of a zone of authority
|
||||
SOA = soa::Record::TYPE,
|
||||
/// a mailbox domain name (EXPERIMENTAL)
|
||||
MB = mb::Record::TYPE,
|
||||
/// a mail group member (EXPERIMENTAL)
|
||||
MG = mg::Record::TYPE,
|
||||
/// a mail rename domain name (EXPERIMENTAL)
|
||||
MR = mr::Record::TYPE,
|
||||
/// a null RR (EXPERIMENTAL)
|
||||
NULL = null::Record::TYPE,
|
||||
/// a well known service description
|
||||
WKS = wks::Record::TYPE,
|
||||
/// a domain name pointer
|
||||
PTR = ptr::Record::TYPE,
|
||||
/// host information
|
||||
HINFO = hinfo::Record::TYPE,
|
||||
/// mailbox or mail list information
|
||||
MINFO = minfo::Record::TYPE,
|
||||
/// mail exchange
|
||||
MX = mx::Record::TYPE,
|
||||
/// text strings
|
||||
TXT = txt::Record::TYPE,
|
||||
/// IPv6 host address (RFC 2782)
|
||||
AAAA = aaaa::Record::TYPE,
|
||||
/// service record (RFC 2782)
|
||||
SRV = srv::Record::TYPE,
|
||||
/// EDNS0 options (RFC 6891)
|
||||
OPT = opt::Record::TYPE,
|
||||
/// next secure record (RFC 4034, RFC 6762)
|
||||
NSEC = nsec::Record::TYPE,
|
||||
}
|
||||
|
||||
/// The QTYPE value according to RFC 1035
|
||||
///
|
||||
/// All "EXPERIMENTAL" markers here are from the RFC
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
#[cfg_attr(feature = "with-serde", derive(Serialize, Deserialize))]
|
||||
pub enum QueryType {
|
||||
/// a host addresss
|
||||
A = a::Record::TYPE,
|
||||
/// an authoritative name server
|
||||
NS = ns::Record::TYPE,
|
||||
/// a mail forwarder (Obsolete - use MX)
|
||||
MF = mf::Record::TYPE,
|
||||
/// the canonical name for an alias
|
||||
CNAME = cname::Record::TYPE,
|
||||
/// marks the start of a zone of authority
|
||||
SOA = soa::Record::TYPE,
|
||||
/// a mailbox domain name (EXPERIMENTAL)
|
||||
MB = mb::Record::TYPE,
|
||||
/// a mail group member (EXPERIMENTAL)
|
||||
MG = mg::Record::TYPE,
|
||||
/// a mail rename domain name (EXPERIMENTAL)
|
||||
MR = mr::Record::TYPE,
|
||||
/// a null RR (EXPERIMENTAL)
|
||||
NULL = null::Record::TYPE,
|
||||
/// a well known service description
|
||||
WKS = wks::Record::TYPE,
|
||||
/// a domain name pointer
|
||||
PTR = ptr::Record::TYPE,
|
||||
/// host information
|
||||
HINFO = hinfo::Record::TYPE,
|
||||
/// mailbox or mail list information
|
||||
MINFO = minfo::Record::TYPE,
|
||||
/// mail exchange
|
||||
MX = mx::Record::TYPE,
|
||||
/// text strings
|
||||
TXT = txt::Record::TYPE,
|
||||
/// IPv6 host address (RFC 2782)
|
||||
AAAA = aaaa::Record::TYPE,
|
||||
/// service record (RFC 2782)
|
||||
SRV = srv::Record::TYPE,
|
||||
/// A request for a transfer of an entire zone
|
||||
AXFR = axfr::Record::TYPE,
|
||||
/// A request for mailbox-related records (MB, MG or MR)
|
||||
MAILB = mailb::Record::TYPE,
|
||||
/// A request for mail agent RRs (Obsolete - see MX)
|
||||
MAILA = maila::Record::TYPE,
|
||||
/// A request for all records
|
||||
All = all::Record::TYPE,
|
||||
}
|
||||
|
||||
|
||||
/// The CLASS value according to RFC 1035
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
pub enum Class {
|
||||
/// the Internet
|
||||
IN = 1,
|
||||
/// the CSNET class (Obsolete - used only for examples in some obsolete
|
||||
/// RFCs)
|
||||
CS = 2,
|
||||
/// the CHAOS class
|
||||
CH = 3,
|
||||
/// Hesiod [Dyer 87]
|
||||
HS = 4,
|
||||
}
|
||||
|
||||
/// The QCLASS value according to RFC 1035
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
pub enum QueryClass {
|
||||
/// the Internet
|
||||
IN = 1,
|
||||
/// the CSNET class (Obsolete - used only for examples in some obsolete
|
||||
/// RFCs)
|
||||
CS = 2,
|
||||
/// the CHAOS class
|
||||
CH = 3,
|
||||
/// Hesiod [Dyer 87]
|
||||
HS = 4,
|
||||
/// Any class
|
||||
Any = 255,
|
||||
}
|
||||
|
||||
/// The OPCODE value according to RFC 1035
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
pub enum Opcode {
|
||||
/// Normal query
|
||||
StandardQuery,
|
||||
/// Inverse query (query a name by IP)
|
||||
InverseQuery,
|
||||
/// Server status request
|
||||
ServerStatusRequest,
|
||||
/// Reserved opcode for future use
|
||||
Reserved(u16),
|
||||
}
|
||||
|
||||
quick_error! {
|
||||
/// The RCODE value according to RFC 1035
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
#[allow(missing_docs)] // names are from spec
|
||||
pub enum ResponseCode {
|
||||
NoError
|
||||
FormatError
|
||||
ServerFailure
|
||||
NameError
|
||||
NotImplemented
|
||||
Refused
|
||||
Reserved(code: u8)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u16> for Opcode {
|
||||
fn from(code: u16) -> Opcode {
|
||||
use self::Opcode::*;
|
||||
match code {
|
||||
0 => StandardQuery,
|
||||
1 => InverseQuery,
|
||||
2 => ServerStatusRequest,
|
||||
x => Reserved(x),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Into<u16> for Opcode {
|
||||
fn into(self) -> u16 {
|
||||
use self::Opcode::*;
|
||||
match self {
|
||||
StandardQuery => 0,
|
||||
InverseQuery => 1,
|
||||
ServerStatusRequest => 2,
|
||||
Reserved(x) => x,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u8> for ResponseCode {
|
||||
fn from(code: u8) -> ResponseCode {
|
||||
use self::ResponseCode::*;
|
||||
match code {
|
||||
0 => NoError,
|
||||
1 => FormatError,
|
||||
2 => ServerFailure,
|
||||
3 => NameError,
|
||||
4 => NotImplemented,
|
||||
5 => Refused,
|
||||
6...15 => Reserved(code),
|
||||
x => panic!("Invalid response code {}", x),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Into<u8> for ResponseCode {
|
||||
fn into(self) -> u8 {
|
||||
use self::ResponseCode::*;
|
||||
match self {
|
||||
NoError => 0,
|
||||
FormatError => 1,
|
||||
ServerFailure => 2,
|
||||
NameError => 3,
|
||||
NotImplemented => 4,
|
||||
Refused => 5,
|
||||
Reserved(code) => code,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl QueryType {
|
||||
/// Parse a query type code
|
||||
pub fn parse(code: u16) -> Result<QueryType, Error> {
|
||||
use self::QueryType::*;
|
||||
match code as isize {
|
||||
a::Record::TYPE => Ok(A),
|
||||
ns::Record::TYPE => Ok(NS),
|
||||
mf::Record::TYPE => Ok(MF),
|
||||
cname::Record::TYPE => Ok(CNAME),
|
||||
soa::Record::TYPE => Ok(SOA),
|
||||
mb::Record::TYPE => Ok(MB),
|
||||
mg::Record::TYPE => Ok(MG),
|
||||
mr::Record::TYPE => Ok(MR),
|
||||
null::Record::TYPE => Ok(NULL),
|
||||
wks::Record::TYPE => Ok(WKS),
|
||||
ptr::Record::TYPE => Ok(PTR),
|
||||
hinfo::Record::TYPE => Ok(HINFO),
|
||||
minfo::Record::TYPE => Ok(MINFO),
|
||||
mx::Record::TYPE => Ok(MX),
|
||||
txt::Record::TYPE => Ok(TXT),
|
||||
aaaa::Record::TYPE => Ok(AAAA),
|
||||
srv::Record::TYPE => Ok(SRV),
|
||||
axfr::Record::TYPE => Ok(AXFR),
|
||||
mailb::Record::TYPE => Ok(MAILB),
|
||||
maila::Record::TYPE => Ok(MAILA),
|
||||
all::Record::TYPE => Ok(All),
|
||||
x => Err(Error::InvalidQueryType(x as u16)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl QueryClass {
|
||||
/// Parse a query class code
|
||||
pub fn parse(code: u16) -> Result<QueryClass, Error> {
|
||||
use self::QueryClass::*;
|
||||
match code {
|
||||
1 => Ok(IN),
|
||||
2 => Ok(CS),
|
||||
3 => Ok(CH),
|
||||
4 => Ok(HS),
|
||||
255 => Ok(Any),
|
||||
x => Err(Error::InvalidQueryClass(x)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Type {
|
||||
/// Parse a type code
|
||||
pub fn parse(code: u16) -> Result<Type, Error> {
|
||||
use self::Type::*;
|
||||
match code as isize {
|
||||
a::Record::TYPE => Ok(A),
|
||||
ns::Record::TYPE => Ok(NS),
|
||||
mf::Record::TYPE => Ok(MF),
|
||||
cname::Record::TYPE => Ok(CNAME),
|
||||
soa::Record::TYPE => Ok(SOA),
|
||||
mb::Record::TYPE => Ok(MB),
|
||||
mg::Record::TYPE => Ok(MG),
|
||||
mr::Record::TYPE => Ok(MR),
|
||||
null::Record::TYPE => Ok(NULL),
|
||||
wks::Record::TYPE => Ok(WKS),
|
||||
ptr::Record::TYPE => Ok(PTR),
|
||||
hinfo::Record::TYPE => Ok(HINFO),
|
||||
minfo::Record::TYPE => Ok(MINFO),
|
||||
mx::Record::TYPE => Ok(MX),
|
||||
txt::Record::TYPE => Ok(TXT),
|
||||
aaaa::Record::TYPE => Ok(AAAA),
|
||||
srv::Record::TYPE => Ok(SRV),
|
||||
opt::Record::TYPE => Ok(OPT),
|
||||
nsec::Record::TYPE => Ok(NSEC),
|
||||
x => Err(Error::InvalidType(x as u16)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Class {
|
||||
/// Parse a class code
|
||||
pub fn parse(code: u16) -> Result<Class, Error> {
|
||||
use self::Class::*;
|
||||
match code {
|
||||
1 => Ok(IN),
|
||||
2 => Ok(CS),
|
||||
3 => Ok(CH),
|
||||
4 => Ok(HS),
|
||||
x => Err(Error::InvalidClass(x)),
|
||||
}
|
||||
}
|
||||
}
|
71
third_party/rust/dns-parser/src/error.rs
vendored
71
third_party/rust/dns-parser/src/error.rs
vendored
@ -1,71 +0,0 @@
|
||||
use std::str::Utf8Error;
|
||||
|
||||
quick_error! {
|
||||
/// Error parsing DNS packet
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
/// Invalid compression pointer not pointing backwards
|
||||
/// when parsing label
|
||||
BadPointer {
|
||||
description("invalid compression pointer not pointing backwards \
|
||||
when parsing label")
|
||||
}
|
||||
/// Packet is smaller than header size
|
||||
HeaderTooShort {
|
||||
description("packet is smaller than header size")
|
||||
}
|
||||
/// Packet ihas incomplete data
|
||||
UnexpectedEOF {
|
||||
description("packet is has incomplete data")
|
||||
}
|
||||
/// Wrong (too short or too long) size of RDATA
|
||||
WrongRdataLength {
|
||||
description("wrong (too short or too long) size of RDATA")
|
||||
}
|
||||
/// Packet has non-zero reserved bits
|
||||
ReservedBitsAreNonZero {
|
||||
description("packet has non-zero reserved bits")
|
||||
}
|
||||
/// Label in domain name has unknown label format
|
||||
UnknownLabelFormat {
|
||||
description("label in domain name has unknown label format")
|
||||
}
|
||||
/// Query type code is invalid
|
||||
InvalidQueryType(code: u16) {
|
||||
description("query type code is invalid")
|
||||
display("query type {} is invalid", code)
|
||||
}
|
||||
/// Query class code is invalid
|
||||
InvalidQueryClass(code: u16) {
|
||||
description("query class code is invalid")
|
||||
display("query class {} is invalid", code)
|
||||
}
|
||||
/// Type code is invalid
|
||||
InvalidType(code: u16) {
|
||||
description("type code is invalid")
|
||||
display("type {} is invalid", code)
|
||||
}
|
||||
/// Class code is invalid
|
||||
InvalidClass(code: u16) {
|
||||
description("class code is invalid")
|
||||
display("class {} is invalid", code)
|
||||
}
|
||||
/// Invalid characters encountered while reading label
|
||||
LabelIsNotAscii {
|
||||
description("invalid characters encountered while reading label")
|
||||
}
|
||||
/// Invalid characters encountered while reading TXT
|
||||
TxtDataIsNotUTF8(error: Utf8Error) {
|
||||
description("invalid characters encountered while reading TXT")
|
||||
display("{:?}", error)
|
||||
}
|
||||
/// Parser is in the wrong state
|
||||
WrongState {
|
||||
description("parser is in the wrong state")
|
||||
}
|
||||
/// Additional OPT record found
|
||||
AdditionalOPT {
|
||||
description("additional OPT record found")
|
||||
}
|
||||
}
|
||||
}
|
203
third_party/rust/dns-parser/src/header.rs
vendored
203
third_party/rust/dns-parser/src/header.rs
vendored
@ -1,203 +0,0 @@
|
||||
use byteorder::{BigEndian, ByteOrder};
|
||||
|
||||
use {Error, ResponseCode, Opcode};
|
||||
|
||||
mod flag {
|
||||
pub const QUERY: u16 = 0b1000_0000_0000_0000;
|
||||
pub const OPCODE_MASK: u16 = 0b0111_1000_0000_0000;
|
||||
pub const AUTHORITATIVE: u16 = 0b0000_0100_0000_0000;
|
||||
pub const TRUNCATED: u16 = 0b0000_0010_0000_0000;
|
||||
pub const RECURSION_DESIRED: u16 = 0b0000_0001_0000_0000;
|
||||
pub const RECURSION_AVAILABLE: u16 = 0b0000_0000_1000_0000;
|
||||
pub const AUTHENTICATED_DATA: u16 = 0b0000_0000_0010_0000;
|
||||
pub const CHECKING_DISABLED: u16 = 0b0000_0000_0001_0000;
|
||||
pub const RESERVED_MASK: u16 = 0b0000_0000_0100_0000;
|
||||
pub const RESPONSE_CODE_MASK: u16 = 0b0000_0000_0000_1111;
|
||||
}
|
||||
|
||||
/// Represents parsed header of the packet
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
#[allow(missing_docs)] // fields are from the spec I think
|
||||
pub struct Header {
|
||||
pub id: u16,
|
||||
pub query: bool,
|
||||
pub opcode: Opcode,
|
||||
pub authoritative: bool,
|
||||
pub truncated: bool,
|
||||
pub recursion_desired: bool,
|
||||
pub recursion_available: bool,
|
||||
pub authenticated_data: bool,
|
||||
pub checking_disabled: bool,
|
||||
pub response_code: ResponseCode,
|
||||
pub questions: u16,
|
||||
pub answers: u16,
|
||||
pub nameservers: u16,
|
||||
pub additional: u16,
|
||||
}
|
||||
|
||||
impl Header {
|
||||
/// Parse the header into a header structure
|
||||
pub fn parse(data: &[u8]) -> Result<Header, Error> {
|
||||
if data.len() < 12 {
|
||||
return Err(Error::HeaderTooShort);
|
||||
}
|
||||
let flags = BigEndian::read_u16(&data[2..4]);
|
||||
if flags & flag::RESERVED_MASK != 0 {
|
||||
return Err(Error::ReservedBitsAreNonZero);
|
||||
}
|
||||
let header = Header {
|
||||
id: BigEndian::read_u16(&data[..2]),
|
||||
query: flags & flag::QUERY == 0,
|
||||
opcode: ((flags & flag::OPCODE_MASK)
|
||||
>> flag::OPCODE_MASK.trailing_zeros()).into(),
|
||||
authoritative: flags & flag::AUTHORITATIVE != 0,
|
||||
truncated: flags & flag::TRUNCATED != 0,
|
||||
recursion_desired: flags & flag::RECURSION_DESIRED != 0,
|
||||
recursion_available: flags & flag::RECURSION_AVAILABLE != 0,
|
||||
authenticated_data: flags & flag::AUTHENTICATED_DATA != 0,
|
||||
checking_disabled: flags & flag::CHECKING_DISABLED != 0,
|
||||
response_code: From::from((flags&flag::RESPONSE_CODE_MASK) as u8),
|
||||
questions: BigEndian::read_u16(&data[4..6]),
|
||||
answers: BigEndian::read_u16(&data[6..8]),
|
||||
nameservers: BigEndian::read_u16(&data[8..10]),
|
||||
additional: BigEndian::read_u16(&data[10..12]),
|
||||
};
|
||||
Ok(header)
|
||||
}
|
||||
/// Write a header to a buffer slice
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// When buffer size is not exactly 12 bytes
|
||||
pub fn write(&self, data: &mut [u8]) {
|
||||
if data.len() != 12 {
|
||||
panic!("Header size is exactly 12 bytes");
|
||||
}
|
||||
let mut flags = 0u16;
|
||||
flags |= Into::<u16>::into(self.opcode)
|
||||
<< flag::OPCODE_MASK.trailing_zeros();
|
||||
flags |= Into::<u8>::into(self.response_code) as u16;
|
||||
if !self.query { flags |= flag::QUERY; }
|
||||
if self.authoritative { flags |= flag::AUTHORITATIVE; }
|
||||
if self.recursion_desired { flags |= flag::RECURSION_DESIRED; }
|
||||
if self.recursion_available { flags |= flag::RECURSION_AVAILABLE; }
|
||||
if self.truncated { flags |= flag::TRUNCATED; }
|
||||
BigEndian::write_u16(&mut data[..2], self.id);
|
||||
BigEndian::write_u16(&mut data[2..4], flags);
|
||||
BigEndian::write_u16(&mut data[4..6], self.questions);
|
||||
BigEndian::write_u16(&mut data[6..8], self.answers);
|
||||
BigEndian::write_u16(&mut data[8..10], self.nameservers);
|
||||
BigEndian::write_u16(&mut data[10..12], self.additional);
|
||||
}
|
||||
/// Set "truncated flag" in the raw data
|
||||
// shouldn't this method be non-public?
|
||||
pub fn set_truncated(data: &mut [u8]) {
|
||||
let oldflags = BigEndian::read_u16(&data[2..4]);
|
||||
BigEndian::write_u16(&mut data[2..4], oldflags & flag::TRUNCATED);
|
||||
}
|
||||
/// Returns a size of the header (always 12 bytes)
|
||||
pub fn size() -> usize { 12 }
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
|
||||
use {Header};
|
||||
use Opcode::*;
|
||||
use ResponseCode::NoError;
|
||||
|
||||
#[test]
|
||||
fn parse_example_query() {
|
||||
let query = b"\x06%\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\
|
||||
\x07example\x03com\x00\x00\x01\x00\x01";
|
||||
let header = Header::parse(query).unwrap();
|
||||
assert_eq!(header, Header {
|
||||
id: 1573,
|
||||
query: true,
|
||||
opcode: StandardQuery,
|
||||
authoritative: false,
|
||||
truncated: false,
|
||||
recursion_desired: true,
|
||||
recursion_available: false,
|
||||
authenticated_data: false,
|
||||
checking_disabled: false,
|
||||
response_code: NoError,
|
||||
questions: 1,
|
||||
answers: 0,
|
||||
nameservers: 0,
|
||||
additional: 0,
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_example_response() {
|
||||
let response = b"\x06%\x81\x80\x00\x01\x00\x01\x00\x00\x00\x00\
|
||||
\x07example\x03com\x00\x00\x01\x00\x01\
|
||||
\xc0\x0c\x00\x01\x00\x01\x00\x00\x04\xf8\
|
||||
\x00\x04]\xb8\xd8\"";
|
||||
let header = Header::parse(response).unwrap();
|
||||
assert_eq!(header, Header {
|
||||
id: 1573,
|
||||
query: false,
|
||||
opcode: StandardQuery,
|
||||
authoritative: false,
|
||||
truncated: false,
|
||||
recursion_desired: true,
|
||||
recursion_available: true,
|
||||
authenticated_data: false,
|
||||
checking_disabled: false,
|
||||
response_code: NoError,
|
||||
questions: 1,
|
||||
answers: 1,
|
||||
nameservers: 0,
|
||||
additional: 0,
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_query_with_ad_set() {
|
||||
let query = b"\x06%\x01\x20\x00\x01\x00\x00\x00\x00\x00\x00\
|
||||
\x07example\x03com\x00\x00\x01\x00\x01";
|
||||
let header = Header::parse(query).unwrap();
|
||||
assert_eq!(header, Header {
|
||||
id: 1573,
|
||||
query: true,
|
||||
opcode: StandardQuery,
|
||||
authoritative: false,
|
||||
truncated: false,
|
||||
recursion_desired: true,
|
||||
recursion_available: false,
|
||||
authenticated_data: true,
|
||||
checking_disabled: false,
|
||||
response_code: NoError,
|
||||
questions: 1,
|
||||
answers: 0,
|
||||
nameservers: 0,
|
||||
additional: 0,
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_query_with_cd_set() {
|
||||
let query = b"\x06%\x01\x10\x00\x01\x00\x00\x00\x00\x00\x00\
|
||||
\x07example\x03com\x00\x00\x01\x00\x01";
|
||||
let header = Header::parse(query).unwrap();
|
||||
assert_eq!(header, Header {
|
||||
id: 1573,
|
||||
query: true,
|
||||
opcode: StandardQuery,
|
||||
authoritative: false,
|
||||
truncated: false,
|
||||
recursion_desired: true,
|
||||
recursion_available: false,
|
||||
authenticated_data: false,
|
||||
checking_disabled: true,
|
||||
response_code: NoError,
|
||||
questions: 1,
|
||||
answers: 0,
|
||||
nameservers: 0,
|
||||
additional: 0,
|
||||
});
|
||||
}
|
||||
}
|
39
third_party/rust/dns-parser/src/lib.rs
vendored
39
third_party/rust/dns-parser/src/lib.rs
vendored
@ -1,39 +0,0 @@
|
||||
#![recursion_limit="100"]
|
||||
//! The network-agnostic DNS parser library
|
||||
//!
|
||||
//! [Documentation](https://docs.rs/dns-parser) |
|
||||
//! [Github](https://github.com/tailhook/dns-parser) |
|
||||
//! [Crate](https://crates.io/crates/dns-parser)
|
||||
//!
|
||||
//! Use [`Builder`] to create a new outgoing packet.
|
||||
//!
|
||||
//! Use [`Packet::parse`] to parse a packet into a data structure.
|
||||
//!
|
||||
//! [`Builder`]: struct.Builder.html
|
||||
//! [`Packet::parse`]: struct.Packet.html#method.parse
|
||||
//!
|
||||
#![warn(missing_docs)]
|
||||
#![warn(missing_debug_implementations)]
|
||||
|
||||
extern crate byteorder;
|
||||
#[cfg(test)] #[macro_use] extern crate matches;
|
||||
#[macro_use(quick_error)] extern crate quick_error;
|
||||
#[cfg(feature = "with-serde")] #[macro_use] extern crate serde_derive;
|
||||
|
||||
mod enums;
|
||||
mod structs;
|
||||
mod name;
|
||||
mod parser;
|
||||
mod error;
|
||||
mod header;
|
||||
mod builder;
|
||||
|
||||
pub mod rdata;
|
||||
|
||||
pub use enums::{Type, QueryType, Class, QueryClass, ResponseCode, Opcode};
|
||||
pub use structs::{Question, ResourceRecord, Packet};
|
||||
pub use name::{Name};
|
||||
pub use error::{Error};
|
||||
pub use header::{Header};
|
||||
pub use rdata::{RData};
|
||||
pub use builder::{Builder};
|
183
third_party/rust/dns-parser/src/name.rs
vendored
183
third_party/rust/dns-parser/src/name.rs
vendored
@ -1,183 +0,0 @@
|
||||
use std::fmt;
|
||||
use std::fmt::Write;
|
||||
use std::str::from_utf8;
|
||||
|
||||
// Deprecated since rustc 1.23
|
||||
#[allow(unused_imports, deprecated)]
|
||||
use std::ascii::AsciiExt;
|
||||
|
||||
use byteorder::{BigEndian, ByteOrder};
|
||||
|
||||
use {Error};
|
||||
|
||||
/// The DNS name as stored in the original packet
|
||||
///
|
||||
/// This contains just a reference to a slice that contains the data.
|
||||
/// You may turn this into a string using `.to_string()`
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Name<'a>{
|
||||
labels: &'a [u8],
|
||||
/// This is the original buffer size. The compressed names in original
|
||||
/// are calculated in this buffer
|
||||
original: &'a [u8],
|
||||
}
|
||||
|
||||
impl<'a> Name<'a> {
|
||||
/// Scan the data to get Name object
|
||||
///
|
||||
/// The `data` should be a part of `original` where name should start.
|
||||
/// The `original` is the data starting a the start of a packet, so
|
||||
/// that offsets in compressed name starts from the `original`.
|
||||
pub fn scan(data: &'a[u8], original: &'a[u8]) -> Result<Name<'a>, Error> {
|
||||
let mut parse_data = data;
|
||||
let mut return_pos = None;
|
||||
let mut pos = 0;
|
||||
if parse_data.len() <= pos {
|
||||
return Err(Error::UnexpectedEOF);
|
||||
}
|
||||
// By setting the largest_pos to be the original len, a side effect
|
||||
// is that the pos variable can move forwards in the buffer once.
|
||||
let mut largest_pos = original.len();
|
||||
let mut byte = parse_data[pos];
|
||||
while byte != 0 {
|
||||
if parse_data.len() <= pos {
|
||||
return Err(Error::UnexpectedEOF);
|
||||
}
|
||||
if byte & 0b1100_0000 == 0b1100_0000 {
|
||||
if parse_data.len() < pos+2 {
|
||||
return Err(Error::UnexpectedEOF);
|
||||
}
|
||||
let off = (BigEndian::read_u16(&parse_data[pos..pos+2])
|
||||
& !0b1100_0000_0000_0000) as usize;
|
||||
if off >= original.len() {
|
||||
return Err(Error::UnexpectedEOF);
|
||||
}
|
||||
// Set value for return_pos which is the pos in the original
|
||||
// data buffer that should be used to return after validating
|
||||
// the offsetted labels.
|
||||
if let None = return_pos {
|
||||
return_pos = Some(pos);
|
||||
}
|
||||
|
||||
// Check then set largest_pos to ensure we never go backwards
|
||||
// in the buffer.
|
||||
if off >= largest_pos {
|
||||
return Err(Error::BadPointer);
|
||||
}
|
||||
largest_pos = off;
|
||||
pos = 0;
|
||||
parse_data = &original[off..];
|
||||
} else if byte & 0b1100_0000 == 0 {
|
||||
let end = pos + byte as usize + 1;
|
||||
if parse_data.len() < end {
|
||||
return Err(Error::UnexpectedEOF);
|
||||
}
|
||||
if !parse_data[pos+1..end].is_ascii() {
|
||||
return Err(Error::LabelIsNotAscii);
|
||||
}
|
||||
pos = end;
|
||||
if parse_data.len() <= pos {
|
||||
return Err(Error::UnexpectedEOF);
|
||||
}
|
||||
} else {
|
||||
return Err(Error::UnknownLabelFormat);
|
||||
}
|
||||
byte = parse_data[pos];
|
||||
}
|
||||
if let Some(return_pos) = return_pos {
|
||||
return Ok(Name {labels: &data[..return_pos+2], original: original});
|
||||
} else {
|
||||
return Ok(Name {labels: &data[..pos+1], original: original });
|
||||
}
|
||||
}
|
||||
/// Number of bytes serialized name occupies
|
||||
pub fn byte_len(&self) -> usize {
|
||||
self.labels.len()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> fmt::Display for Name<'a> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
let data = self.labels;
|
||||
let original = self.original;
|
||||
let mut pos = 0;
|
||||
loop {
|
||||
let byte = data[pos];
|
||||
if byte == 0 {
|
||||
return Ok(());
|
||||
} else if byte & 0b1100_0000 == 0b1100_0000 {
|
||||
let off = (BigEndian::read_u16(&data[pos..pos+2])
|
||||
& !0b1100_0000_0000_0000) as usize;
|
||||
if pos != 0 {
|
||||
try!(fmt.write_char('.'));
|
||||
}
|
||||
return fmt::Display::fmt(
|
||||
&Name::scan(&original[off..], original).unwrap(), fmt)
|
||||
} else if byte & 0b1100_0000 == 0 {
|
||||
if pos != 0 {
|
||||
try!(fmt.write_char('.'));
|
||||
}
|
||||
let end = pos + byte as usize + 1;
|
||||
try!(fmt.write_str(from_utf8(&data[pos+1..end]).unwrap()));
|
||||
pos = end;
|
||||
continue;
|
||||
} else {
|
||||
unreachable!();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<'a> fmt::Debug for Name<'a> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt.debug_tuple("Name")
|
||||
.field(&format!("{}", self))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use Error;
|
||||
use Name;
|
||||
|
||||
#[test]
|
||||
fn parse_badpointer_same_offset() {
|
||||
// A buffer where an offset points to itself,
|
||||
// which is a bad compression pointer.
|
||||
let same_offset = vec![192, 2, 192, 2];
|
||||
let is_match = matches!(Name::scan(&same_offset, &same_offset),
|
||||
Err(Error::BadPointer));
|
||||
|
||||
assert!(is_match);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_badpointer_forward_offset() {
|
||||
// A buffer where the offsets points back to each other which causes
|
||||
// infinite recursion if never checked, a bad compression pointer.
|
||||
let forwards_offset = vec![192, 2, 192, 4, 192, 2];
|
||||
let is_match = matches!(Name::scan(&forwards_offset, &forwards_offset),
|
||||
Err(Error::BadPointer));
|
||||
|
||||
assert!(is_match);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn nested_names() {
|
||||
// A buffer where an offset points to itself, a bad compression pointer.
|
||||
let buf = b"\x02xx\x00\x02yy\xc0\x00\x02zz\xc0\x04";
|
||||
|
||||
assert_eq!(Name::scan(&buf[..], buf).unwrap().to_string(),
|
||||
"xx");
|
||||
assert_eq!(Name::scan(&buf[..], buf).unwrap().labels,
|
||||
b"\x02xx\x00");
|
||||
assert_eq!(Name::scan(&buf[4..], buf).unwrap().to_string(),
|
||||
"yy.xx");
|
||||
assert_eq!(Name::scan(&buf[4..], buf).unwrap().labels,
|
||||
b"\x02yy\xc0\x00");
|
||||
assert_eq!(Name::scan(&buf[9..], buf).unwrap().to_string(),
|
||||
"zz.yy.xx");
|
||||
assert_eq!(Name::scan(&buf[9..], buf).unwrap().labels,
|
||||
b"\x02zz\xc0\x04");
|
||||
}
|
||||
}
|
455
third_party/rust/dns-parser/src/parser.rs
vendored
455
third_party/rust/dns-parser/src/parser.rs
vendored
@ -1,455 +0,0 @@
|
||||
use std::i32;
|
||||
|
||||
use byteorder::{BigEndian, ByteOrder};
|
||||
|
||||
use {Header, Packet, Error, Question, Name, QueryType, QueryClass};
|
||||
use {Type, Class, ResourceRecord, RData};
|
||||
use rdata::opt::Record as Opt;
|
||||
|
||||
const OPT_RR_START: [u8; 3] = [0, 0, 41];
|
||||
|
||||
impl<'a> Packet<'a> {
|
||||
/// Parse a full DNS Packet and return a structure that has all the
|
||||
/// data borrowed from the passed buffer.
|
||||
pub fn parse(data: &[u8]) -> Result<Packet, Error> {
|
||||
let header = try!(Header::parse(data));
|
||||
let mut offset = Header::size();
|
||||
let mut questions = Vec::with_capacity(header.questions as usize);
|
||||
for _ in 0..header.questions {
|
||||
let name = try!(Name::scan(&data[offset..], data));
|
||||
offset += name.byte_len();
|
||||
if offset + 4 > data.len() {
|
||||
return Err(Error::UnexpectedEOF);
|
||||
}
|
||||
let qtype = try!(QueryType::parse(
|
||||
BigEndian::read_u16(&data[offset..offset+2])));
|
||||
offset += 2;
|
||||
|
||||
let (prefer_unicast, qclass) = try!(parse_qclass_code(
|
||||
BigEndian::read_u16(&data[offset..offset+2])));
|
||||
offset += 2;
|
||||
|
||||
questions.push(Question {
|
||||
qname: name,
|
||||
qtype: qtype,
|
||||
prefer_unicast: prefer_unicast,
|
||||
qclass: qclass,
|
||||
});
|
||||
}
|
||||
let mut answers = Vec::with_capacity(header.answers as usize);
|
||||
for _ in 0..header.answers {
|
||||
answers.push(try!(parse_record(data, &mut offset)));
|
||||
}
|
||||
let mut nameservers = Vec::with_capacity(header.nameservers as usize);
|
||||
for _ in 0..header.nameservers {
|
||||
nameservers.push(try!(parse_record(data, &mut offset)));
|
||||
}
|
||||
let mut additional = Vec::with_capacity(header.additional as usize);
|
||||
let mut opt = None;
|
||||
for _ in 0..header.additional {
|
||||
if offset + 3 <= data.len() && data[offset..offset+3] == OPT_RR_START {
|
||||
if opt.is_none() {
|
||||
opt = Some(try!(parse_opt_record(data, &mut offset)));
|
||||
} else {
|
||||
return Err(Error::AdditionalOPT);
|
||||
}
|
||||
} else {
|
||||
additional.push(try!(parse_record(data, &mut offset)));
|
||||
}
|
||||
}
|
||||
Ok(Packet {
|
||||
header: header,
|
||||
questions: questions,
|
||||
answers: answers,
|
||||
nameservers: nameservers,
|
||||
additional: additional,
|
||||
opt: opt,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_qclass_code(value: u16) -> Result<(bool, QueryClass), Error> {
|
||||
let prefer_unicast = value & 0x8000 == 0x8000;
|
||||
let qclass_code = value & 0x7FFF;
|
||||
|
||||
let qclass = try!(QueryClass::parse(qclass_code));
|
||||
Ok((prefer_unicast, qclass))
|
||||
}
|
||||
|
||||
fn parse_class_code(value: u16) -> Result<(bool, Class), Error> {
|
||||
let is_unique = value & 0x8000 == 0x8000;
|
||||
let class_code = value & 0x7FFF;
|
||||
|
||||
let cls = try!(Class::parse(class_code));
|
||||
Ok((is_unique, cls))
|
||||
}
|
||||
|
||||
// Generic function to parse answer, nameservers, and additional records.
|
||||
fn parse_record<'a>(data: &'a [u8], offset: &mut usize) -> Result<ResourceRecord<'a>, Error> {
|
||||
let name = try!(Name::scan(&data[*offset..], data));
|
||||
*offset += name.byte_len();
|
||||
if *offset + 10 > data.len() {
|
||||
return Err(Error::UnexpectedEOF);
|
||||
}
|
||||
let typ = try!(Type::parse(
|
||||
BigEndian::read_u16(&data[*offset..*offset+2])));
|
||||
*offset += 2;
|
||||
|
||||
let class_code = BigEndian::read_u16(&data[*offset..*offset+2]);
|
||||
let (multicast_unique, cls) = try!(parse_class_code(class_code));
|
||||
*offset += 2;
|
||||
|
||||
let mut ttl = BigEndian::read_u32(&data[*offset..*offset+4]);
|
||||
if ttl > i32::MAX as u32 {
|
||||
ttl = 0;
|
||||
}
|
||||
*offset += 4;
|
||||
let rdlen = BigEndian::read_u16(&data[*offset..*offset+2]) as usize;
|
||||
*offset += 2;
|
||||
if *offset + rdlen > data.len() {
|
||||
return Err(Error::UnexpectedEOF);
|
||||
}
|
||||
let data = try!(RData::parse(typ,
|
||||
&data[*offset..*offset+rdlen], data));
|
||||
*offset += rdlen;
|
||||
Ok(ResourceRecord {
|
||||
name: name,
|
||||
multicast_unique: multicast_unique,
|
||||
cls: cls,
|
||||
ttl: ttl,
|
||||
data: data,
|
||||
})
|
||||
}
|
||||
|
||||
// Function to parse an RFC 6891 OPT Pseudo RR
|
||||
fn parse_opt_record<'a>(data: &'a [u8], offset: &mut usize) -> Result<Opt<'a>, Error> {
|
||||
if *offset + 11 > data.len() {
|
||||
return Err(Error::UnexpectedEOF);
|
||||
}
|
||||
*offset += 1;
|
||||
let typ = try!(Type::parse(
|
||||
BigEndian::read_u16(&data[*offset..*offset+2])));
|
||||
if typ != Type::OPT {
|
||||
return Err(Error::InvalidType(typ as u16));
|
||||
}
|
||||
*offset += 2;
|
||||
let udp = BigEndian::read_u16(&data[*offset..*offset+2]);
|
||||
*offset += 2;
|
||||
let extrcode = data[*offset];
|
||||
*offset += 1;
|
||||
let version = data[*offset];
|
||||
*offset += 1;
|
||||
let flags = BigEndian::read_u16(&data[*offset..*offset+2]);
|
||||
*offset += 2;
|
||||
let rdlen = BigEndian::read_u16(&data[*offset..*offset+2]) as usize;
|
||||
*offset += 2;
|
||||
if *offset + rdlen > data.len() {
|
||||
return Err(Error::UnexpectedEOF);
|
||||
}
|
||||
let data = try!(RData::parse(typ,
|
||||
&data[*offset..*offset+rdlen], data));
|
||||
*offset += rdlen;
|
||||
|
||||
Ok(Opt {
|
||||
udp: udp,
|
||||
extrcode: extrcode,
|
||||
version: version,
|
||||
flags: flags,
|
||||
data: data,
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
|
||||
use std::net::Ipv4Addr;
|
||||
use {Packet, Header};
|
||||
use Opcode::*;
|
||||
use ResponseCode::NoError;
|
||||
use QueryType as QT;
|
||||
use QueryClass as QC;
|
||||
use Class as C;
|
||||
use RData;
|
||||
|
||||
#[test]
|
||||
fn parse_example_query() {
|
||||
let query = b"\x06%\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\
|
||||
\x07example\x03com\x00\x00\x01\x00\x01";
|
||||
let packet = Packet::parse(query).unwrap();
|
||||
assert_eq!(packet.header, Header {
|
||||
id: 1573,
|
||||
query: true,
|
||||
opcode: StandardQuery,
|
||||
authoritative: false,
|
||||
truncated: false,
|
||||
recursion_desired: true,
|
||||
recursion_available: false,
|
||||
authenticated_data: false,
|
||||
checking_disabled: false,
|
||||
response_code: NoError,
|
||||
questions: 1,
|
||||
answers: 0,
|
||||
nameservers: 0,
|
||||
additional: 0,
|
||||
});
|
||||
assert_eq!(packet.questions.len(), 1);
|
||||
assert_eq!(packet.questions[0].qtype, QT::A);
|
||||
assert_eq!(packet.questions[0].qclass, QC::IN);
|
||||
assert_eq!(&packet.questions[0].qname.to_string()[..], "example.com");
|
||||
assert_eq!(packet.answers.len(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_example_response() {
|
||||
let response = b"\x06%\x81\x80\x00\x01\x00\x01\x00\x00\x00\x00\
|
||||
\x07example\x03com\x00\x00\x01\x00\x01\
|
||||
\xc0\x0c\x00\x01\x00\x01\x00\x00\x04\xf8\
|
||||
\x00\x04]\xb8\xd8\"";
|
||||
let packet = Packet::parse(response).unwrap();
|
||||
assert_eq!(packet.header, Header {
|
||||
id: 1573,
|
||||
query: false,
|
||||
opcode: StandardQuery,
|
||||
authoritative: false,
|
||||
truncated: false,
|
||||
recursion_desired: true,
|
||||
recursion_available: true,
|
||||
authenticated_data: false,
|
||||
checking_disabled: false,
|
||||
response_code: NoError,
|
||||
questions: 1,
|
||||
answers: 1,
|
||||
nameservers: 0,
|
||||
additional: 0,
|
||||
});
|
||||
assert_eq!(packet.questions.len(), 1);
|
||||
assert_eq!(packet.questions[0].qtype, QT::A);
|
||||
assert_eq!(packet.questions[0].qclass, QC::IN);
|
||||
assert_eq!(&packet.questions[0].qname.to_string()[..], "example.com");
|
||||
assert_eq!(packet.answers.len(), 1);
|
||||
assert_eq!(&packet.answers[0].name.to_string()[..], "example.com");
|
||||
assert_eq!(packet.answers[0].multicast_unique, false);
|
||||
assert_eq!(packet.answers[0].cls, C::IN);
|
||||
assert_eq!(packet.answers[0].ttl, 1272);
|
||||
match packet.answers[0].data {
|
||||
RData::A(addr) => {
|
||||
assert_eq!(addr.0, Ipv4Addr::new(93, 184, 216, 34));
|
||||
}
|
||||
ref x => panic!("Wrong rdata {:?}", x),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_response_with_multicast_unique() {
|
||||
let response = b"\x06%\x81\x80\x00\x01\x00\x01\x00\x00\x00\x00\
|
||||
\x07example\x03com\x00\x00\x01\x00\x01\
|
||||
\xc0\x0c\x00\x01\x80\x01\x00\x00\x04\xf8\
|
||||
\x00\x04]\xb8\xd8\"";
|
||||
let packet = Packet::parse(response).unwrap();
|
||||
|
||||
assert_eq!(packet.answers.len(), 1);
|
||||
assert_eq!(packet.answers[0].multicast_unique, true);
|
||||
assert_eq!(packet.answers[0].cls, C::IN);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_additional_record_response() {
|
||||
let response = b"\x4a\xf0\x81\x80\x00\x01\x00\x01\x00\x01\x00\x01\
|
||||
\x03www\x05skype\x03com\x00\x00\x01\x00\x01\
|
||||
\xc0\x0c\x00\x05\x00\x01\x00\x00\x0e\x10\
|
||||
\x00\x1c\x07\x6c\x69\x76\x65\x63\x6d\x73\x0e\x74\
|
||||
\x72\x61\x66\x66\x69\x63\x6d\x61\x6e\x61\x67\x65\
|
||||
\x72\x03\x6e\x65\x74\x00\
|
||||
\xc0\x42\x00\x02\x00\x01\x00\x01\xd5\xd3\x00\x11\
|
||||
\x01\x67\x0c\x67\x74\x6c\x64\x2d\x73\x65\x72\x76\x65\x72\x73\
|
||||
\xc0\x42\
|
||||
\x01\x61\xc0\x55\x00\x01\x00\x01\x00\x00\xa3\x1c\
|
||||
\x00\x04\xc0\x05\x06\x1e";
|
||||
let packet = Packet::parse(response).unwrap();
|
||||
assert_eq!(packet.header, Header {
|
||||
id: 19184,
|
||||
query: false,
|
||||
opcode: StandardQuery,
|
||||
authoritative: false,
|
||||
truncated: false,
|
||||
recursion_desired: true,
|
||||
recursion_available: true,
|
||||
authenticated_data: false,
|
||||
checking_disabled: false,
|
||||
response_code: NoError,
|
||||
questions: 1,
|
||||
answers: 1,
|
||||
nameservers: 1,
|
||||
additional: 1,
|
||||
});
|
||||
assert_eq!(packet.questions.len(), 1);
|
||||
assert_eq!(packet.questions[0].qtype, QT::A);
|
||||
assert_eq!(packet.questions[0].qclass, QC::IN);
|
||||
assert_eq!(&packet.questions[0].qname.to_string()[..], "www.skype.com");
|
||||
assert_eq!(packet.answers.len(), 1);
|
||||
assert_eq!(&packet.answers[0].name.to_string()[..], "www.skype.com");
|
||||
assert_eq!(packet.answers[0].cls, C::IN);
|
||||
assert_eq!(packet.answers[0].ttl, 3600);
|
||||
match packet.answers[0].data {
|
||||
RData::CNAME(cname) => {
|
||||
assert_eq!(&cname.0.to_string()[..], "livecms.trafficmanager.net");
|
||||
}
|
||||
ref x => panic!("Wrong rdata {:?}", x),
|
||||
}
|
||||
assert_eq!(packet.nameservers.len(), 1);
|
||||
assert_eq!(&packet.nameservers[0].name.to_string()[..], "net");
|
||||
assert_eq!(packet.nameservers[0].cls, C::IN);
|
||||
assert_eq!(packet.nameservers[0].ttl, 120275);
|
||||
match packet.nameservers[0].data {
|
||||
RData::NS(ns) => {
|
||||
assert_eq!(&ns.0.to_string()[..], "g.gtld-servers.net");
|
||||
}
|
||||
ref x => panic!("Wrong rdata {:?}", x),
|
||||
}
|
||||
assert_eq!(packet.additional.len(), 1);
|
||||
assert_eq!(&packet.additional[0].name.to_string()[..], "a.gtld-servers.net");
|
||||
assert_eq!(packet.additional[0].cls, C::IN);
|
||||
assert_eq!(packet.additional[0].ttl, 41756);
|
||||
match packet.additional[0].data {
|
||||
RData::A(addr) => {
|
||||
assert_eq!(addr.0, Ipv4Addr::new(192, 5, 6, 30));
|
||||
}
|
||||
ref x => panic!("Wrong rdata {:?}", x),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_multiple_answers() {
|
||||
let response = b"\x9d\xe9\x81\x80\x00\x01\x00\x06\x00\x00\x00\x00\
|
||||
\x06google\x03com\x00\x00\x01\x00\x01\xc0\x0c\
|
||||
\x00\x01\x00\x01\x00\x00\x00\xef\x00\x04@\xe9\
|
||||
\xa4d\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\xef\
|
||||
\x00\x04@\xe9\xa4\x8b\xc0\x0c\x00\x01\x00\x01\
|
||||
\x00\x00\x00\xef\x00\x04@\xe9\xa4q\xc0\x0c\x00\
|
||||
\x01\x00\x01\x00\x00\x00\xef\x00\x04@\xe9\xa4f\
|
||||
\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\xef\x00\x04@\
|
||||
\xe9\xa4e\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\xef\
|
||||
\x00\x04@\xe9\xa4\x8a";
|
||||
let packet = Packet::parse(response).unwrap();
|
||||
assert_eq!(packet.header, Header {
|
||||
id: 40425,
|
||||
query: false,
|
||||
opcode: StandardQuery,
|
||||
authoritative: false,
|
||||
truncated: false,
|
||||
recursion_desired: true,
|
||||
recursion_available: true,
|
||||
authenticated_data: false,
|
||||
checking_disabled: false,
|
||||
response_code: NoError,
|
||||
questions: 1,
|
||||
answers: 6,
|
||||
nameservers: 0,
|
||||
additional: 0,
|
||||
});
|
||||
assert_eq!(packet.questions.len(), 1);
|
||||
assert_eq!(packet.questions[0].qtype, QT::A);
|
||||
assert_eq!(packet.questions[0].qclass, QC::IN);
|
||||
assert_eq!(&packet.questions[0].qname.to_string()[..], "google.com");
|
||||
assert_eq!(packet.answers.len(), 6);
|
||||
let ips = vec![
|
||||
Ipv4Addr::new(64, 233, 164, 100),
|
||||
Ipv4Addr::new(64, 233, 164, 139),
|
||||
Ipv4Addr::new(64, 233, 164, 113),
|
||||
Ipv4Addr::new(64, 233, 164, 102),
|
||||
Ipv4Addr::new(64, 233, 164, 101),
|
||||
Ipv4Addr::new(64, 233, 164, 138),
|
||||
];
|
||||
for i in 0..6 {
|
||||
assert_eq!(&packet.answers[i].name.to_string()[..], "google.com");
|
||||
assert_eq!(packet.answers[i].cls, C::IN);
|
||||
assert_eq!(packet.answers[i].ttl, 239);
|
||||
match packet.answers[i].data {
|
||||
RData::A(addr) => {
|
||||
assert_eq!(addr.0, ips[i]);
|
||||
}
|
||||
ref x => panic!("Wrong rdata {:?}", x),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_srv_query() {
|
||||
let query = b"[\xd9\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\
|
||||
\x0c_xmpp-server\x04_tcp\x05gmail\x03com\x00\x00!\x00\x01";
|
||||
let packet = Packet::parse(query).unwrap();
|
||||
assert_eq!(packet.header, Header {
|
||||
id: 23513,
|
||||
query: true,
|
||||
opcode: StandardQuery,
|
||||
authoritative: false,
|
||||
truncated: false,
|
||||
recursion_desired: true,
|
||||
recursion_available: false,
|
||||
authenticated_data: false,
|
||||
checking_disabled: false,
|
||||
response_code: NoError,
|
||||
questions: 1,
|
||||
answers: 0,
|
||||
nameservers: 0,
|
||||
additional: 0,
|
||||
});
|
||||
assert_eq!(packet.questions.len(), 1);
|
||||
assert_eq!(packet.questions[0].qtype, QT::SRV);
|
||||
assert_eq!(packet.questions[0].qclass, QC::IN);
|
||||
assert_eq!(packet.questions[0].prefer_unicast, false);
|
||||
assert_eq!(&packet.questions[0].qname.to_string()[..],
|
||||
"_xmpp-server._tcp.gmail.com");
|
||||
assert_eq!(packet.answers.len(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_multicast_prefer_unicast_query() {
|
||||
let query = b"\x06%\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\
|
||||
\x07example\x03com\x00\x00\x01\x80\x01";
|
||||
let packet = Packet::parse(query).unwrap();
|
||||
|
||||
assert_eq!(packet.questions.len(), 1);
|
||||
assert_eq!(packet.questions[0].qtype, QT::A);
|
||||
assert_eq!(packet.questions[0].qclass, QC::IN);
|
||||
assert_eq!(packet.questions[0].prefer_unicast, true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_example_query_edns() {
|
||||
let query = b"\x95\xce\x01\x00\x00\x01\x00\x00\x00\x00\x00\x01\
|
||||
\x06google\x03com\x00\x00\x01\x00\
|
||||
\x01\x00\x00\x29\x10\x00\x00\x00\x00\x00\x00\x00";
|
||||
let packet = Packet::parse(query).unwrap();
|
||||
assert_eq!(packet.header, Header {
|
||||
id: 38350,
|
||||
query: true,
|
||||
opcode: StandardQuery,
|
||||
authoritative: false,
|
||||
truncated: false,
|
||||
recursion_desired: true,
|
||||
recursion_available: false,
|
||||
authenticated_data: false,
|
||||
checking_disabled: false,
|
||||
response_code: NoError,
|
||||
questions: 1,
|
||||
answers: 0,
|
||||
nameservers: 0,
|
||||
additional: 1,
|
||||
});
|
||||
assert_eq!(packet.questions.len(), 1);
|
||||
assert_eq!(packet.questions[0].qtype, QT::A);
|
||||
assert_eq!(packet.questions[0].qclass, QC::IN);
|
||||
assert_eq!(&packet.questions[0].qname.to_string()[..], "google.com");
|
||||
assert_eq!(packet.answers.len(), 0);
|
||||
match packet.opt {
|
||||
Some(opt) => {
|
||||
assert_eq!(opt.udp, 4096);
|
||||
assert_eq!(opt.extrcode, 0);
|
||||
assert_eq!(opt.version, 0);
|
||||
assert_eq!(opt.flags, 0);
|
||||
},
|
||||
None => panic!("Missing OPT RR")
|
||||
}
|
||||
}
|
||||
}
|
21
third_party/rust/dns-parser/src/rdata/a.rs
vendored
21
third_party/rust/dns-parser/src/rdata/a.rs
vendored
@ -1,21 +0,0 @@
|
||||
use std::net::Ipv4Addr;
|
||||
|
||||
use Error;
|
||||
use byteorder::{BigEndian, ByteOrder};
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
pub struct Record(pub Ipv4Addr);
|
||||
|
||||
impl<'a> super::Record<'a> for Record {
|
||||
|
||||
const TYPE: isize = 1;
|
||||
|
||||
fn parse(rdata: &'a [u8], _original: &'a [u8]) -> super::RDataResult<'a> {
|
||||
if rdata.len() != 4 {
|
||||
return Err(Error::WrongRdataLength);
|
||||
}
|
||||
let address = Ipv4Addr::from(BigEndian::read_u32(rdata));
|
||||
let record = Record(address);
|
||||
Ok(super::RData::A(record))
|
||||
}
|
||||
}
|
85
third_party/rust/dns-parser/src/rdata/aaaa.rs
vendored
85
third_party/rust/dns-parser/src/rdata/aaaa.rs
vendored
@ -1,85 +0,0 @@
|
||||
use std::net::Ipv6Addr;
|
||||
|
||||
use Error;
|
||||
use byteorder::{BigEndian, ByteOrder};
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
pub struct Record(pub Ipv6Addr);
|
||||
|
||||
impl<'a> super::Record<'a> for Record {
|
||||
|
||||
const TYPE: isize = 28;
|
||||
|
||||
fn parse(rdata: &'a [u8], _record: &'a [u8]) -> super::RDataResult<'a> {
|
||||
if rdata.len() != 16 {
|
||||
return Err(Error::WrongRdataLength);
|
||||
}
|
||||
let address = Ipv6Addr::new(
|
||||
BigEndian::read_u16(&rdata[0..2]),
|
||||
BigEndian::read_u16(&rdata[2..4]),
|
||||
BigEndian::read_u16(&rdata[4..6]),
|
||||
BigEndian::read_u16(&rdata[6..8]),
|
||||
BigEndian::read_u16(&rdata[8..10]),
|
||||
BigEndian::read_u16(&rdata[10..12]),
|
||||
BigEndian::read_u16(&rdata[12..14]),
|
||||
BigEndian::read_u16(&rdata[14..16]),
|
||||
);
|
||||
let record = Record(address);
|
||||
Ok(super::RData::AAAA(record))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
|
||||
use {Packet, Header};
|
||||
use Opcode::*;
|
||||
use ResponseCode::NoError;
|
||||
use QueryType as QT;
|
||||
use QueryClass as QC;
|
||||
use Class as C;
|
||||
use RData;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn parse_response() {
|
||||
let response = b"\xa9\xd9\x81\x80\x00\x01\x00\x01\x00\x00\x00\x00\x06\
|
||||
google\x03com\x00\x00\x1c\x00\x01\xc0\x0c\x00\x1c\x00\x01\x00\x00\
|
||||
\x00\x8b\x00\x10*\x00\x14P@\t\x08\x12\x00\x00\x00\x00\x00\x00 \x0e";
|
||||
|
||||
let packet = Packet::parse(response).unwrap();
|
||||
assert_eq!(packet.header, Header {
|
||||
id: 43481,
|
||||
query: false,
|
||||
opcode: StandardQuery,
|
||||
authoritative: false,
|
||||
truncated: false,
|
||||
recursion_desired: true,
|
||||
recursion_available: true,
|
||||
authenticated_data: false,
|
||||
checking_disabled: false,
|
||||
response_code: NoError,
|
||||
questions: 1,
|
||||
answers: 1,
|
||||
nameservers: 0,
|
||||
additional: 0,
|
||||
});
|
||||
|
||||
assert_eq!(packet.questions.len(), 1);
|
||||
assert_eq!(packet.questions[0].qtype, QT::AAAA);
|
||||
assert_eq!(packet.questions[0].qclass, QC::IN);
|
||||
assert_eq!(&packet.questions[0].qname.to_string()[..], "google.com");
|
||||
assert_eq!(packet.answers.len(), 1);
|
||||
assert_eq!(&packet.answers[0].name.to_string()[..], "google.com");
|
||||
assert_eq!(packet.answers[0].cls, C::IN);
|
||||
assert_eq!(packet.answers[0].ttl, 139);
|
||||
match packet.answers[0].data {
|
||||
RData::AAAA(addr) => {
|
||||
assert_eq!(addr.0, Ipv6Addr::new(
|
||||
0x2A00, 0x1450, 0x4009, 0x812, 0, 0, 0, 0x200e)
|
||||
);
|
||||
}
|
||||
ref x => panic!("Wrong rdata {:?}", x),
|
||||
}
|
||||
}
|
||||
}
|
11
third_party/rust/dns-parser/src/rdata/all.rs
vendored
11
third_party/rust/dns-parser/src/rdata/all.rs
vendored
@ -1,11 +0,0 @@
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
pub struct Record;
|
||||
|
||||
impl<'a> super::Record<'a> for Record {
|
||||
|
||||
const TYPE: isize = 255;
|
||||
|
||||
fn parse(_rdata: &'a [u8], _original: &'a [u8]) -> super::RDataResult<'a> {
|
||||
unimplemented!();
|
||||
}
|
||||
}
|
11
third_party/rust/dns-parser/src/rdata/axfr.rs
vendored
11
third_party/rust/dns-parser/src/rdata/axfr.rs
vendored
@ -1,11 +0,0 @@
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
pub struct Record;
|
||||
|
||||
impl<'a> super::Record<'a> for Record {
|
||||
|
||||
const TYPE: isize = 252;
|
||||
|
||||
fn parse(_rdata: &'a [u8], _original: &'a [u8]) -> super::RDataResult<'a> {
|
||||
unimplemented!();
|
||||
}
|
||||
}
|
102
third_party/rust/dns-parser/src/rdata/cname.rs
vendored
102
third_party/rust/dns-parser/src/rdata/cname.rs
vendored
@ -1,102 +0,0 @@
|
||||
use Name;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct Record<'a>(pub Name<'a>);
|
||||
|
||||
impl<'a> ToString for Record<'a> {
|
||||
#[inline]
|
||||
fn to_string(&self) -> String {
|
||||
self.0.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> super::Record<'a> for Record<'a> {
|
||||
|
||||
const TYPE: isize = 5;
|
||||
|
||||
fn parse(rdata: &'a [u8], original: &'a [u8]) -> super::RDataResult<'a> {
|
||||
let name = Name::scan(rdata, original)?;
|
||||
let record = Record(name);
|
||||
Ok(super::RData::CNAME(record))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
|
||||
use std::net::Ipv4Addr;
|
||||
use {Packet, Header};
|
||||
use Opcode::*;
|
||||
use ResponseCode::NoError;
|
||||
use QueryType as QT;
|
||||
use QueryClass as QC;
|
||||
use Class as C;
|
||||
use RData;
|
||||
|
||||
#[test]
|
||||
fn parse_response() {
|
||||
let response = b"\xfc\x9d\x81\x80\x00\x01\x00\x06\x00\x02\x00\x02\x03\
|
||||
cdn\x07sstatic\x03net\x00\x00\x01\x00\x01\xc0\x0c\x00\x05\x00\x01\
|
||||
\x00\x00\x00f\x00\x02\xc0\x10\xc0\x10\x00\x01\x00\x01\x00\x00\x00\
|
||||
f\x00\x04h\x10g\xcc\xc0\x10\x00\x01\x00\x01\x00\x00\x00f\x00\x04h\
|
||||
\x10k\xcc\xc0\x10\x00\x01\x00\x01\x00\x00\x00f\x00\x04h\x10h\xcc\
|
||||
\xc0\x10\x00\x01\x00\x01\x00\x00\x00f\x00\x04h\x10j\xcc\xc0\x10\
|
||||
\x00\x01\x00\x01\x00\x00\x00f\x00\x04h\x10i\xcc\xc0\x10\x00\x02\
|
||||
\x00\x01\x00\x00\x99L\x00\x0b\x08cf-dns02\xc0\x10\xc0\x10\x00\x02\
|
||||
\x00\x01\x00\x00\x99L\x00\x0b\x08cf-dns01\xc0\x10\xc0\xa2\x00\x01\
|
||||
\x00\x01\x00\x00\x99L\x00\x04\xad\xf5:5\xc0\x8b\x00\x01\x00\x01\x00\
|
||||
\x00\x99L\x00\x04\xad\xf5;\x04";
|
||||
|
||||
let packet = Packet::parse(response).unwrap();
|
||||
assert_eq!(packet.header, Header {
|
||||
id: 64669,
|
||||
query: false,
|
||||
opcode: StandardQuery,
|
||||
authoritative: false,
|
||||
truncated: false,
|
||||
recursion_desired: true,
|
||||
recursion_available: true,
|
||||
authenticated_data: false,
|
||||
checking_disabled: false,
|
||||
response_code: NoError,
|
||||
questions: 1,
|
||||
answers: 6,
|
||||
nameservers: 2,
|
||||
additional: 2,
|
||||
});
|
||||
|
||||
assert_eq!(packet.questions.len(), 1);
|
||||
assert_eq!(packet.questions[0].qtype, QT::A);
|
||||
assert_eq!(packet.questions[0].qclass, QC::IN);
|
||||
assert_eq!(&packet.questions[0].qname.to_string()[..], "cdn.sstatic.net");
|
||||
assert_eq!(packet.answers.len(), 6);
|
||||
assert_eq!(&packet.answers[0].name.to_string()[..], "cdn.sstatic.net");
|
||||
assert_eq!(packet.answers[0].cls, C::IN);
|
||||
assert_eq!(packet.answers[0].ttl, 102);
|
||||
match packet.answers[0].data {
|
||||
RData::CNAME(cname) => {
|
||||
assert_eq!(&cname.0.to_string(), "sstatic.net");
|
||||
}
|
||||
ref x => panic!("Wrong rdata {:?}", x),
|
||||
}
|
||||
|
||||
let ips = vec![
|
||||
Ipv4Addr::new(104, 16, 103, 204),
|
||||
Ipv4Addr::new(104, 16, 107, 204),
|
||||
Ipv4Addr::new(104, 16, 104, 204),
|
||||
Ipv4Addr::new(104, 16, 106, 204),
|
||||
Ipv4Addr::new(104, 16, 105, 204),
|
||||
];
|
||||
for i in 1..6 {
|
||||
assert_eq!(&packet.answers[i].name.to_string()[..], "sstatic.net");
|
||||
assert_eq!(packet.answers[i].cls, C::IN);
|
||||
assert_eq!(packet.answers[i].ttl, 102);
|
||||
match packet.answers[i].data {
|
||||
RData::A(addr) => {
|
||||
assert_eq!(addr.0, ips[i-1]);
|
||||
}
|
||||
ref x => panic!("Wrong rdata {:?}", x),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
11
third_party/rust/dns-parser/src/rdata/hinfo.rs
vendored
11
third_party/rust/dns-parser/src/rdata/hinfo.rs
vendored
@ -1,11 +0,0 @@
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
pub struct Record;
|
||||
|
||||
impl<'a> super::Record<'a> for Record {
|
||||
|
||||
const TYPE: isize = 13;
|
||||
|
||||
fn parse(_rdata: &'a [u8], _original: &'a [u8]) -> super::RDataResult<'a> {
|
||||
unimplemented!();
|
||||
}
|
||||
}
|
11
third_party/rust/dns-parser/src/rdata/maila.rs
vendored
11
third_party/rust/dns-parser/src/rdata/maila.rs
vendored
@ -1,11 +0,0 @@
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
pub struct Record;
|
||||
|
||||
impl<'a> super::Record<'a> for Record {
|
||||
|
||||
const TYPE: isize = 254;
|
||||
|
||||
fn parse(_rdata: &'a [u8], _original: &'a [u8]) -> super::RDataResult<'a> {
|
||||
unimplemented!();
|
||||
}
|
||||
}
|
11
third_party/rust/dns-parser/src/rdata/mailb.rs
vendored
11
third_party/rust/dns-parser/src/rdata/mailb.rs
vendored
@ -1,11 +0,0 @@
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
pub struct Record;
|
||||
|
||||
impl<'a> super::Record<'a> for Record {
|
||||
|
||||
const TYPE: isize = 253;
|
||||
|
||||
fn parse(_rdata: &'a [u8], _original: &'a [u8]) -> super::RDataResult<'a> {
|
||||
unimplemented!();
|
||||
}
|
||||
}
|
11
third_party/rust/dns-parser/src/rdata/mb.rs
vendored
11
third_party/rust/dns-parser/src/rdata/mb.rs
vendored
@ -1,11 +0,0 @@
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
pub struct Record;
|
||||
|
||||
impl<'a> super::Record<'a> for Record {
|
||||
|
||||
const TYPE: isize = 7;
|
||||
|
||||
fn parse(_rdata: &'a [u8], _original: &'a [u8]) -> super::RDataResult<'a> {
|
||||
unimplemented!();
|
||||
}
|
||||
}
|
11
third_party/rust/dns-parser/src/rdata/mf.rs
vendored
11
third_party/rust/dns-parser/src/rdata/mf.rs
vendored
@ -1,11 +0,0 @@
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
pub struct Record;
|
||||
|
||||
impl<'a> super::Record<'a> for Record {
|
||||
|
||||
const TYPE: isize = 4;
|
||||
|
||||
fn parse(_rdata: &'a [u8], _original: &'a [u8]) -> super::RDataResult<'a> {
|
||||
unimplemented!();
|
||||
}
|
||||
}
|
11
third_party/rust/dns-parser/src/rdata/mg.rs
vendored
11
third_party/rust/dns-parser/src/rdata/mg.rs
vendored
@ -1,11 +0,0 @@
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
pub struct Record;
|
||||
|
||||
impl<'a> super::Record<'a> for Record {
|
||||
|
||||
const TYPE: isize = 8;
|
||||
|
||||
fn parse(_rdata: &'a [u8], _original: &'a [u8]) -> super::RDataResult<'a> {
|
||||
unimplemented!();
|
||||
}
|
||||
}
|
11
third_party/rust/dns-parser/src/rdata/minfo.rs
vendored
11
third_party/rust/dns-parser/src/rdata/minfo.rs
vendored
@ -1,11 +0,0 @@
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
pub struct Record;
|
||||
|
||||
impl<'a> super::Record<'a> for Record {
|
||||
|
||||
const TYPE: isize = 14;
|
||||
|
||||
fn parse(_rdata: &'a [u8], _original: &'a [u8]) -> super::RDataResult<'a> {
|
||||
unimplemented!();
|
||||
}
|
||||
}
|
83
third_party/rust/dns-parser/src/rdata/mod.rs
vendored
83
third_party/rust/dns-parser/src/rdata/mod.rs
vendored
@ -1,83 +0,0 @@
|
||||
//! Data types and methods for handling the RData field
|
||||
|
||||
#![allow(missing_docs)] // resource records are pretty self-descriptive
|
||||
|
||||
pub mod a;
|
||||
pub mod aaaa;
|
||||
pub mod all;
|
||||
pub mod axfr;
|
||||
pub mod cname;
|
||||
pub mod hinfo;
|
||||
pub mod maila;
|
||||
pub mod mailb;
|
||||
pub mod mb;
|
||||
pub mod mf;
|
||||
pub mod mg;
|
||||
pub mod minfo;
|
||||
pub mod mr;
|
||||
pub mod mx;
|
||||
pub mod ns;
|
||||
pub mod nsec;
|
||||
pub mod null;
|
||||
pub mod opt;
|
||||
pub mod ptr;
|
||||
pub mod soa;
|
||||
pub mod srv;
|
||||
pub mod txt;
|
||||
pub mod wks;
|
||||
|
||||
use {Type, Error};
|
||||
|
||||
pub use self::a::Record as A;
|
||||
pub use self::aaaa::Record as Aaaa;
|
||||
pub use self::cname::Record as Cname;
|
||||
pub use self::mx::Record as Mx;
|
||||
pub use self::ns::Record as Ns;
|
||||
pub use self::nsec::Record as Nsec;
|
||||
pub use self::opt::Record as Opt;
|
||||
pub use self::ptr::Record as Ptr;
|
||||
pub use self::soa::Record as Soa;
|
||||
pub use self::srv::Record as Srv;
|
||||
pub use self::txt::Record as Txt;
|
||||
|
||||
pub type RDataResult<'a> = Result<RData<'a>, Error>;
|
||||
|
||||
/// The enumeration that represents known types of DNS resource records data
|
||||
#[derive(Debug)]
|
||||
pub enum RData<'a> {
|
||||
A(A),
|
||||
AAAA(Aaaa),
|
||||
CNAME(Cname<'a>),
|
||||
MX(Mx<'a>),
|
||||
NS(Ns<'a>),
|
||||
PTR(Ptr<'a>),
|
||||
SOA(Soa<'a>),
|
||||
SRV(Srv<'a>),
|
||||
TXT(Txt<'a>),
|
||||
/// Anything that can't be parsed yet
|
||||
Unknown(&'a [u8]),
|
||||
}
|
||||
|
||||
pub (crate) trait Record<'a> {
|
||||
const TYPE: isize;
|
||||
|
||||
fn parse(rdata: &'a [u8], original: &'a [u8]) -> RDataResult<'a>;
|
||||
}
|
||||
|
||||
impl<'a> RData<'a> {
|
||||
/// Parse an RR data and return RData enumeration
|
||||
pub fn parse(typ: Type, rdata: &'a [u8], original: &'a [u8]) -> RDataResult<'a> {
|
||||
match typ {
|
||||
Type::A => A::parse(rdata, original),
|
||||
Type::AAAA => Aaaa::parse(rdata, original),
|
||||
Type::CNAME => Cname::parse(rdata, original),
|
||||
Type::NS => Ns::parse(rdata, original),
|
||||
Type::MX => Mx::parse(rdata, original),
|
||||
Type::PTR => Ptr::parse(rdata, original),
|
||||
Type::SOA => Soa::parse(rdata, original),
|
||||
Type::SRV => Srv::parse(rdata, original),
|
||||
Type::TXT => Txt::parse(rdata, original),
|
||||
_ => Ok(RData::Unknown(rdata)),
|
||||
}
|
||||
}
|
||||
}
|
11
third_party/rust/dns-parser/src/rdata/mr.rs
vendored
11
third_party/rust/dns-parser/src/rdata/mr.rs
vendored
@ -1,11 +0,0 @@
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
pub struct Record;
|
||||
|
||||
impl<'a> super::Record<'a> for Record {
|
||||
|
||||
const TYPE: isize = 9;
|
||||
|
||||
fn parse(_rdata: &'a [u8], _original: &'a [u8]) -> super::RDataResult<'a> {
|
||||
unimplemented!();
|
||||
}
|
||||
}
|
92
third_party/rust/dns-parser/src/rdata/mx.rs
vendored
92
third_party/rust/dns-parser/src/rdata/mx.rs
vendored
@ -1,92 +0,0 @@
|
||||
use {Name, Error};
|
||||
use byteorder::{BigEndian, ByteOrder};
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct Record<'a> {
|
||||
pub preference: u16,
|
||||
pub exchange: Name<'a>,
|
||||
}
|
||||
|
||||
impl<'a> super::Record<'a> for Record<'a> {
|
||||
|
||||
const TYPE: isize = 15;
|
||||
|
||||
fn parse(rdata: &'a [u8], original: &'a [u8]) -> super::RDataResult<'a> {
|
||||
if rdata.len() < 3 {
|
||||
return Err(Error::WrongRdataLength);
|
||||
}
|
||||
let record = Record {
|
||||
preference: BigEndian::read_u16(&rdata[..2]),
|
||||
exchange: Name::scan(&rdata[2..], original)?,
|
||||
};
|
||||
Ok(super::RData::MX(record))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
|
||||
use {Packet, Header};
|
||||
use Opcode::*;
|
||||
use ResponseCode::NoError;
|
||||
use QueryType as QT;
|
||||
use QueryClass as QC;
|
||||
use Class as C;
|
||||
use RData;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn parse_response() {
|
||||
let response = b"\xe3\xe8\x81\x80\x00\x01\x00\x05\x00\x00\x00\x00\
|
||||
\x05gmail\x03com\x00\x00\x0f\x00\x01\xc0\x0c\x00\x0f\x00\x01\
|
||||
\x00\x00\x04|\x00\x1b\x00\x05\rgmail-smtp-in\x01l\x06google\xc0\
|
||||
\x12\xc0\x0c\x00\x0f\x00\x01\x00\x00\x04|\x00\t\x00\
|
||||
\n\x04alt1\xc0)\xc0\x0c\x00\x0f\x00\x01\x00\x00\x04|\
|
||||
\x00\t\x00(\x04alt4\xc0)\xc0\x0c\x00\x0f\x00\x01\x00\
|
||||
\x00\x04|\x00\t\x00\x14\x04alt2\xc0)\xc0\x0c\x00\x0f\
|
||||
\x00\x01\x00\x00\x04|\x00\t\x00\x1e\x04alt3\xc0)";
|
||||
let packet = Packet::parse(response).unwrap();
|
||||
assert_eq!(packet.header, Header {
|
||||
id: 58344,
|
||||
query: false,
|
||||
opcode: StandardQuery,
|
||||
authoritative: false,
|
||||
truncated: false,
|
||||
recursion_desired: true,
|
||||
recursion_available: true,
|
||||
authenticated_data: false,
|
||||
checking_disabled: false,
|
||||
response_code: NoError,
|
||||
questions: 1,
|
||||
answers: 5,
|
||||
nameservers: 0,
|
||||
additional: 0,
|
||||
});
|
||||
assert_eq!(packet.questions.len(), 1);
|
||||
assert_eq!(packet.questions[0].qtype, QT::MX);
|
||||
assert_eq!(packet.questions[0].qclass, QC::IN);
|
||||
assert_eq!(&packet.questions[0].qname.to_string()[..],
|
||||
"gmail.com");
|
||||
assert_eq!(packet.answers.len(), 5);
|
||||
let items = vec![
|
||||
( 5, "gmail-smtp-in.l.google.com"),
|
||||
(10, "alt1.gmail-smtp-in.l.google.com"),
|
||||
(40, "alt4.gmail-smtp-in.l.google.com"),
|
||||
(20, "alt2.gmail-smtp-in.l.google.com"),
|
||||
(30, "alt3.gmail-smtp-in.l.google.com"),
|
||||
];
|
||||
for i in 0..5 {
|
||||
assert_eq!(&packet.answers[i].name.to_string()[..],
|
||||
"gmail.com");
|
||||
assert_eq!(packet.answers[i].cls, C::IN);
|
||||
assert_eq!(packet.answers[i].ttl, 1148);
|
||||
match *&packet.answers[i].data {
|
||||
RData::MX( Record { preference, exchange }) => {
|
||||
assert_eq!(preference, items[i].0);
|
||||
assert_eq!(exchange.to_string(), (items[i].1).to_string());
|
||||
}
|
||||
ref x => panic!("Wrong rdata {:?}", x),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
88
third_party/rust/dns-parser/src/rdata/ns.rs
vendored
88
third_party/rust/dns-parser/src/rdata/ns.rs
vendored
@ -1,88 +0,0 @@
|
||||
use Name;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct Record<'a>(pub Name<'a>);
|
||||
|
||||
impl<'a> ToString for Record<'a> {
|
||||
#[inline]
|
||||
fn to_string(&self) -> String {
|
||||
self.0.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> super::Record<'a> for Record<'a> {
|
||||
|
||||
const TYPE: isize = 2;
|
||||
|
||||
fn parse(rdata: &'a [u8], original: &'a [u8]) -> super::RDataResult<'a> {
|
||||
let name = Name::scan(rdata, original)?;
|
||||
let record = Record(name);
|
||||
Ok(super::RData::NS(record))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
|
||||
use {Packet, Header};
|
||||
use Opcode::*;
|
||||
use ResponseCode::NoError;
|
||||
use QueryType as QT;
|
||||
use QueryClass as QC;
|
||||
use Class as C;
|
||||
use RData;
|
||||
|
||||
#[test]
|
||||
fn parse_response() {
|
||||
let response = b"\x4a\xf0\x81\x80\x00\x01\x00\x01\x00\x01\x00\x00\
|
||||
\x03www\x05skype\x03com\x00\x00\x01\x00\x01\
|
||||
\xc0\x0c\x00\x05\x00\x01\x00\x00\x0e\x10\
|
||||
\x00\x1c\x07\x6c\x69\x76\x65\x63\x6d\x73\x0e\x74\
|
||||
\x72\x61\x66\x66\x69\x63\x6d\x61\x6e\x61\x67\x65\
|
||||
\x72\x03\x6e\x65\x74\x00\
|
||||
\xc0\x42\x00\x02\x00\x01\x00\x01\xd5\xd3\x00\x11\
|
||||
\x01\x67\x0c\x67\x74\x6c\x64\x2d\x73\x65\x72\x76\x65\x72\x73\
|
||||
\xc0\x42";
|
||||
let packet = Packet::parse(response).unwrap();
|
||||
assert_eq!(packet.header, Header {
|
||||
id: 19184,
|
||||
query: false,
|
||||
opcode: StandardQuery,
|
||||
authoritative: false,
|
||||
truncated: false,
|
||||
recursion_desired: true,
|
||||
recursion_available: true,
|
||||
authenticated_data: false,
|
||||
checking_disabled: false,
|
||||
response_code: NoError,
|
||||
questions: 1,
|
||||
answers: 1,
|
||||
nameservers: 1,
|
||||
additional: 0,
|
||||
});
|
||||
assert_eq!(packet.questions.len(), 1);
|
||||
assert_eq!(packet.questions[0].qtype, QT::A);
|
||||
assert_eq!(packet.questions[0].qclass, QC::IN);
|
||||
assert_eq!(&packet.questions[0].qname.to_string()[..], "www.skype.com");
|
||||
assert_eq!(packet.answers.len(), 1);
|
||||
assert_eq!(&packet.answers[0].name.to_string()[..], "www.skype.com");
|
||||
assert_eq!(packet.answers[0].cls, C::IN);
|
||||
assert_eq!(packet.answers[0].ttl, 3600);
|
||||
match packet.answers[0].data {
|
||||
RData::CNAME(cname) => {
|
||||
assert_eq!(&cname.0.to_string()[..], "livecms.trafficmanager.net");
|
||||
}
|
||||
ref x => panic!("Wrong rdata {:?}", x),
|
||||
}
|
||||
assert_eq!(packet.nameservers.len(), 1);
|
||||
assert_eq!(&packet.nameservers[0].name.to_string()[..], "net");
|
||||
assert_eq!(packet.nameservers[0].cls, C::IN);
|
||||
assert_eq!(packet.nameservers[0].ttl, 120275);
|
||||
match packet.nameservers[0].data {
|
||||
RData::NS(ns) => {
|
||||
assert_eq!(&ns.0.to_string()[..], "g.gtld-servers.net");
|
||||
}
|
||||
ref x => panic!("Wrong rdata {:?}", x),
|
||||
}
|
||||
}
|
||||
}
|
11
third_party/rust/dns-parser/src/rdata/nsec.rs
vendored
11
third_party/rust/dns-parser/src/rdata/nsec.rs
vendored
@ -1,11 +0,0 @@
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
pub struct Record;
|
||||
|
||||
impl<'a> super::Record<'a> for Record {
|
||||
|
||||
const TYPE: isize = 47;
|
||||
|
||||
fn parse(_rdata: &'a [u8], _original: &'a [u8]) -> super::RDataResult<'a> {
|
||||
unimplemented!();
|
||||
}
|
||||
}
|
11
third_party/rust/dns-parser/src/rdata/null.rs
vendored
11
third_party/rust/dns-parser/src/rdata/null.rs
vendored
@ -1,11 +0,0 @@
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
pub struct Record;
|
||||
|
||||
impl<'a> super::Record<'a> for Record {
|
||||
|
||||
const TYPE: isize = 10;
|
||||
|
||||
fn parse(_rdata: &'a [u8], _original: &'a [u8]) -> super::RDataResult<'a> {
|
||||
unimplemented!();
|
||||
}
|
||||
}
|
18
third_party/rust/dns-parser/src/rdata/opt.rs
vendored
18
third_party/rust/dns-parser/src/rdata/opt.rs
vendored
@ -1,18 +0,0 @@
|
||||
/// RFC 6891 OPT RR
|
||||
#[derive(Debug)]
|
||||
pub struct Record<'a> {
|
||||
pub udp: u16,
|
||||
pub extrcode: u8,
|
||||
pub version: u8,
|
||||
pub flags: u16,
|
||||
pub data: super::RData<'a>,
|
||||
}
|
||||
|
||||
impl<'a> super::Record<'a> for Record<'a> {
|
||||
|
||||
const TYPE: isize = 41;
|
||||
|
||||
fn parse(_rdata: &'a [u8], _original: &'a [u8]) -> super::RDataResult<'a> {
|
||||
unimplemented!();
|
||||
}
|
||||
}
|
74
third_party/rust/dns-parser/src/rdata/ptr.rs
vendored
74
third_party/rust/dns-parser/src/rdata/ptr.rs
vendored
@ -1,74 +0,0 @@
|
||||
use Name;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct Record<'a>(pub Name<'a>);
|
||||
|
||||
impl<'a> ToString for Record<'a> {
|
||||
#[inline]
|
||||
fn to_string(&self) -> String {
|
||||
self.0.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> super::Record<'a> for Record<'a> {
|
||||
|
||||
const TYPE: isize = 12;
|
||||
|
||||
fn parse(rdata: &'a [u8], original: &'a [u8]) -> super::RDataResult<'a> {
|
||||
let name = Name::scan(rdata, original)?;
|
||||
let record = Record(name);
|
||||
Ok(super::RData::PTR(record))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
|
||||
use {Packet, Header};
|
||||
use Opcode::*;
|
||||
use ResponseCode::NoError;
|
||||
use QueryType as QT;
|
||||
use QueryClass as QC;
|
||||
use Class as C;
|
||||
use RData;
|
||||
|
||||
#[test]
|
||||
fn parse_response() {
|
||||
let response = b"\x53\xd6\x81\x80\x00\x01\x00\x01\x00\x00\x00\x00\
|
||||
\x0269\x0293\x0275\x0272\x07in-addr\x04arpa\x00\
|
||||
\x00\x0c\x00\x01\
|
||||
\xc0\x0c\x00\x0c\x00\x01\x00\x01\x51\x80\x00\x1e\
|
||||
\x10pool-72-75-93-69\x07verizon\x03net\x00";
|
||||
let packet = Packet::parse(response).unwrap();
|
||||
assert_eq!(packet.header, Header {
|
||||
id: 21462,
|
||||
query: false,
|
||||
opcode: StandardQuery,
|
||||
authoritative: false,
|
||||
truncated: false,
|
||||
recursion_desired: true,
|
||||
recursion_available: true,
|
||||
authenticated_data: false,
|
||||
checking_disabled: false,
|
||||
response_code: NoError,
|
||||
questions: 1,
|
||||
answers: 1,
|
||||
nameservers: 0,
|
||||
additional: 0,
|
||||
});
|
||||
assert_eq!(packet.questions.len(), 1);
|
||||
assert_eq!(packet.questions[0].qtype, QT::PTR);
|
||||
assert_eq!(packet.questions[0].qclass, QC::IN);
|
||||
assert_eq!(&packet.questions[0].qname.to_string()[..], "69.93.75.72.in-addr.arpa");
|
||||
assert_eq!(packet.answers.len(), 1);
|
||||
assert_eq!(&packet.answers[0].name.to_string()[..], "69.93.75.72.in-addr.arpa");
|
||||
assert_eq!(packet.answers[0].cls, C::IN);
|
||||
assert_eq!(packet.answers[0].ttl, 86400);
|
||||
match packet.answers[0].data {
|
||||
RData::PTR(name) => {
|
||||
assert_eq!(&name.0.to_string()[..], "pool-72-75-93-69.verizon.net");
|
||||
}
|
||||
ref x => panic!("Wrong rdata {:?}", x),
|
||||
}
|
||||
}
|
||||
}
|
101
third_party/rust/dns-parser/src/rdata/soa.rs
vendored
101
third_party/rust/dns-parser/src/rdata/soa.rs
vendored
@ -1,101 +0,0 @@
|
||||
use {Name, Error};
|
||||
use byteorder::{BigEndian, ByteOrder};
|
||||
|
||||
/// The SOA (Start of Authority) record
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct Record<'a> {
|
||||
pub primary_ns: Name<'a>,
|
||||
pub mailbox: Name<'a>,
|
||||
pub serial: u32,
|
||||
pub refresh: u32,
|
||||
pub retry: u32,
|
||||
pub expire: u32,
|
||||
pub minimum_ttl: u32,
|
||||
}
|
||||
|
||||
impl<'a> super::Record<'a> for Record<'a> {
|
||||
|
||||
const TYPE: isize = 6;
|
||||
|
||||
fn parse(rdata: &'a [u8], original: &'a [u8]) -> super::RDataResult<'a> {
|
||||
let mut pos = 0;
|
||||
let primary_name_server = try!(Name::scan(rdata, original));
|
||||
pos += primary_name_server.byte_len();
|
||||
let mailbox = try!(Name::scan(&rdata[pos..], original));
|
||||
pos += mailbox.byte_len();
|
||||
if rdata[pos..].len() < 20 {
|
||||
return Err(Error::WrongRdataLength);
|
||||
}
|
||||
let record = Record {
|
||||
primary_ns: primary_name_server,
|
||||
mailbox: mailbox,
|
||||
serial: BigEndian::read_u32(&rdata[pos..(pos+4)]),
|
||||
refresh: BigEndian::read_u32(&rdata[(pos+4)..(pos+8)]),
|
||||
retry: BigEndian::read_u32(&rdata[(pos+8)..(pos+12)]),
|
||||
expire: BigEndian::read_u32(&rdata[(pos+12)..(pos+16)]),
|
||||
minimum_ttl: BigEndian::read_u32(&rdata[(pos+16)..(pos+20)]),
|
||||
};
|
||||
Ok(super::RData::SOA(record))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
|
||||
use {Packet, Header};
|
||||
use Opcode::*;
|
||||
use ResponseCode::NameError;
|
||||
use QueryType as QT;
|
||||
use QueryClass as QC;
|
||||
use Class as C;
|
||||
use RData;
|
||||
|
||||
#[test]
|
||||
fn parse_response() {
|
||||
let response = b"\x9f\xc5\x85\x83\x00\x01\x00\x00\x00\x01\x00\x00\
|
||||
\x0edlkfjkdjdslfkj\x07youtube\x03com\x00\x00\x01\x00\x01\
|
||||
\xc0\x1b\x00\x06\x00\x01\x00\x00\x2a\x30\x00\x1e\xc0\x1b\
|
||||
\x05admin\xc0\x1b\x77\xed\x2a\x73\x00\x00\x51\x80\x00\x00\
|
||||
\x0e\x10\x00\x00\x3a\x80\x00\x00\x2a\x30";
|
||||
let packet = Packet::parse(response).unwrap();
|
||||
assert_eq!(packet.header, Header {
|
||||
id: 40901,
|
||||
query: false,
|
||||
opcode: StandardQuery,
|
||||
authoritative: true,
|
||||
truncated: false,
|
||||
recursion_desired: true,
|
||||
recursion_available: true,
|
||||
authenticated_data: false,
|
||||
checking_disabled: false,
|
||||
response_code: NameError,
|
||||
questions: 1,
|
||||
answers: 0,
|
||||
nameservers: 1,
|
||||
additional: 0,
|
||||
});
|
||||
assert_eq!(packet.questions.len(), 1);
|
||||
assert_eq!(packet.questions[0].qtype, QT::A);
|
||||
assert_eq!(packet.questions[0].qclass, QC::IN);
|
||||
assert_eq!(&packet.questions[0].qname.to_string()[..], "dlkfjkdjdslfkj.youtube.com");
|
||||
assert_eq!(packet.answers.len(), 0);
|
||||
|
||||
assert_eq!(packet.nameservers.len(), 1);
|
||||
assert_eq!(&packet.nameservers[0].name.to_string()[..], "youtube.com");
|
||||
assert_eq!(packet.nameservers[0].cls, C::IN);
|
||||
assert_eq!(packet.nameservers[0].multicast_unique, false);
|
||||
assert_eq!(packet.nameservers[0].ttl, 10800);
|
||||
match packet.nameservers[0].data {
|
||||
RData::SOA(ref soa_rec) => {
|
||||
assert_eq!(&soa_rec.primary_ns.to_string()[..], "youtube.com");
|
||||
assert_eq!(&soa_rec.mailbox.to_string()[..], "admin.youtube.com");
|
||||
assert_eq!(soa_rec.serial, 2012031603);
|
||||
assert_eq!(soa_rec.refresh, 20864);
|
||||
assert_eq!(soa_rec.retry, 3600);
|
||||
assert_eq!(soa_rec.expire, 14976);
|
||||
assert_eq!(soa_rec.minimum_ttl, 10800);
|
||||
}
|
||||
ref x => panic!("Wrong rdata {:?}", x),
|
||||
}
|
||||
}
|
||||
}
|
102
third_party/rust/dns-parser/src/rdata/srv.rs
vendored
102
third_party/rust/dns-parser/src/rdata/srv.rs
vendored
@ -1,102 +0,0 @@
|
||||
use {Name, Error};
|
||||
use byteorder::{BigEndian, ByteOrder};
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct Record<'a> {
|
||||
pub priority: u16,
|
||||
pub weight: u16,
|
||||
pub port: u16,
|
||||
pub target: Name<'a>,
|
||||
}
|
||||
|
||||
impl<'a> super::Record<'a> for Record<'a> {
|
||||
|
||||
const TYPE: isize = 33;
|
||||
|
||||
fn parse(rdata: &'a [u8], original: &'a [u8]) -> super::RDataResult<'a> {
|
||||
if rdata.len() < 7 {
|
||||
return Err(Error::WrongRdataLength);
|
||||
}
|
||||
let record = Record {
|
||||
priority: BigEndian::read_u16(&rdata[..2]),
|
||||
weight: BigEndian::read_u16(&rdata[2..4]),
|
||||
port: BigEndian::read_u16(&rdata[4..6]),
|
||||
target: Name::scan(&rdata[6..], original)?,
|
||||
};
|
||||
Ok(super::RData::SRV(record))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
|
||||
use {Packet, Header};
|
||||
use Opcode::*;
|
||||
use ResponseCode::NoError;
|
||||
use QueryType as QT;
|
||||
use QueryClass as QC;
|
||||
use Class as C;
|
||||
use RData;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn parse_response() {
|
||||
let response = b"[\xd9\x81\x80\x00\x01\x00\x05\x00\x00\x00\x00\
|
||||
\x0c_xmpp-server\x04_tcp\x05gmail\x03com\x00\x00!\x00\x01\
|
||||
\xc0\x0c\x00!\x00\x01\x00\x00\x03\x84\x00 \x00\x05\x00\x00\
|
||||
\x14\x95\x0bxmpp-server\x01l\x06google\x03com\x00\xc0\x0c\x00!\
|
||||
\x00\x01\x00\x00\x03\x84\x00%\x00\x14\x00\x00\x14\x95\
|
||||
\x04alt3\x0bxmpp-server\x01l\x06google\x03com\x00\
|
||||
\xc0\x0c\x00!\x00\x01\x00\x00\x03\x84\x00%\x00\x14\x00\x00\
|
||||
\x14\x95\x04alt1\x0bxmpp-server\x01l\x06google\x03com\x00\
|
||||
\xc0\x0c\x00!\x00\x01\x00\x00\x03\x84\x00%\x00\x14\x00\x00\
|
||||
\x14\x95\x04alt2\x0bxmpp-server\x01l\x06google\x03com\x00\
|
||||
\xc0\x0c\x00!\x00\x01\x00\x00\x03\x84\x00%\x00\x14\x00\x00\
|
||||
\x14\x95\x04alt4\x0bxmpp-server\x01l\x06google\x03com\x00";
|
||||
let packet = Packet::parse(response).unwrap();
|
||||
assert_eq!(packet.header, Header {
|
||||
id: 23513,
|
||||
query: false,
|
||||
opcode: StandardQuery,
|
||||
authoritative: false,
|
||||
truncated: false,
|
||||
recursion_desired: true,
|
||||
recursion_available: true,
|
||||
authenticated_data: false,
|
||||
checking_disabled: false,
|
||||
response_code: NoError,
|
||||
questions: 1,
|
||||
answers: 5,
|
||||
nameservers: 0,
|
||||
additional: 0,
|
||||
});
|
||||
assert_eq!(packet.questions.len(), 1);
|
||||
assert_eq!(packet.questions[0].qtype, QT::SRV);
|
||||
assert_eq!(packet.questions[0].qclass, QC::IN);
|
||||
assert_eq!(&packet.questions[0].qname.to_string()[..],
|
||||
"_xmpp-server._tcp.gmail.com");
|
||||
assert_eq!(packet.answers.len(), 5);
|
||||
let items = vec![
|
||||
(5, 0, 5269, "xmpp-server.l.google.com"),
|
||||
(20, 0, 5269, "alt3.xmpp-server.l.google.com"),
|
||||
(20, 0, 5269, "alt1.xmpp-server.l.google.com"),
|
||||
(20, 0, 5269, "alt2.xmpp-server.l.google.com"),
|
||||
(20, 0, 5269, "alt4.xmpp-server.l.google.com"),
|
||||
];
|
||||
for i in 0..5 {
|
||||
assert_eq!(&packet.answers[i].name.to_string()[..],
|
||||
"_xmpp-server._tcp.gmail.com");
|
||||
assert_eq!(packet.answers[i].cls, C::IN);
|
||||
assert_eq!(packet.answers[i].ttl, 900);
|
||||
match *&packet.answers[i].data {
|
||||
RData::SRV(Record { priority, weight, port, target }) => {
|
||||
assert_eq!(priority, items[i].0);
|
||||
assert_eq!(weight, items[i].1);
|
||||
assert_eq!(port, items[i].2);
|
||||
assert_eq!(target.to_string(), (items[i].3).to_string());
|
||||
}
|
||||
ref x => panic!("Wrong rdata {:?}", x),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
125
third_party/rust/dns-parser/src/rdata/txt.rs
vendored
125
third_party/rust/dns-parser/src/rdata/txt.rs
vendored
@ -1,125 +0,0 @@
|
||||
use Error;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Record<'a> {
|
||||
bytes: &'a [u8],
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct RecordIter<'a> {
|
||||
bytes: &'a [u8],
|
||||
}
|
||||
|
||||
impl<'a> Iterator for RecordIter<'a> {
|
||||
type Item = &'a [u8];
|
||||
fn next(&mut self) -> Option<&'a [u8]> {
|
||||
if self.bytes.len() >= 1 {
|
||||
let len = self.bytes[0] as usize;
|
||||
debug_assert!(self.bytes.len() >= len+1);
|
||||
let (head, tail) = self.bytes[1..].split_at(len);
|
||||
self.bytes = tail;
|
||||
return Some(head);
|
||||
}
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Record<'a> {
|
||||
|
||||
// Returns iterator over text chunks
|
||||
pub fn iter(&self) -> RecordIter<'a> {
|
||||
RecordIter {
|
||||
bytes: self.bytes,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> super::Record<'a> for Record<'a> {
|
||||
|
||||
const TYPE: isize = 16;
|
||||
|
||||
fn parse(rdata: &'a [u8], _original: &'a [u8]) -> super::RDataResult<'a> {
|
||||
// Just a quick check that record is valid
|
||||
let len = rdata.len();
|
||||
if len < 1 {
|
||||
return Err(Error::WrongRdataLength);
|
||||
}
|
||||
let mut pos = 0;
|
||||
while pos < len {
|
||||
let rdlen = rdata[pos] as usize;
|
||||
pos += 1;
|
||||
if len < rdlen + pos {
|
||||
return Err(Error::WrongRdataLength);
|
||||
}
|
||||
pos += rdlen;
|
||||
}
|
||||
Ok(super::RData::TXT(Record {
|
||||
bytes: rdata,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
|
||||
use std::str::from_utf8;
|
||||
|
||||
use {Packet, Header};
|
||||
use Opcode::*;
|
||||
use ResponseCode::NoError;
|
||||
use QueryType as QT;
|
||||
use QueryClass as QC;
|
||||
use Class as C;
|
||||
use RData;
|
||||
|
||||
#[test]
|
||||
fn parse_response_multiple_strings() {
|
||||
let response = b"\x06%\x81\x80\x00\x01\x00\x01\x00\x00\x00\x00\
|
||||
\x08facebook\x03com\x00\x00\x10\x00\x01\
|
||||
\xc0\x0c\x00\x10\x00\x01\x00\x01\x51\x3d\x00\x23\
|
||||
\x15\x76\x3d\x73\x70\x66\x31\x20\x72\x65\x64\x69\
|
||||
\x72\x65\x63\x74\x3d\x5f\x73\x70\x66\x2e\
|
||||
\x0c\x66\x61\x63\x65\x62\x6f\x6f\x6b\x2e\x63\x6f\x6d";
|
||||
|
||||
let packet = Packet::parse(response).unwrap();
|
||||
assert_eq!(packet.header, Header {
|
||||
id: 1573,
|
||||
query: false,
|
||||
opcode: StandardQuery,
|
||||
authoritative: false,
|
||||
truncated: false,
|
||||
recursion_desired: true,
|
||||
recursion_available: true,
|
||||
authenticated_data: false,
|
||||
checking_disabled: false,
|
||||
response_code: NoError,
|
||||
questions: 1,
|
||||
answers: 1,
|
||||
nameservers: 0,
|
||||
additional: 0,
|
||||
});
|
||||
assert_eq!(packet.questions.len(), 1);
|
||||
assert_eq!(packet.questions[0].qtype, QT::TXT);
|
||||
assert_eq!(packet.questions[0].qclass, QC::IN);
|
||||
assert_eq!(&packet.questions[0].qname.to_string()[..], "facebook.com");
|
||||
assert_eq!(packet.answers.len(), 1);
|
||||
assert_eq!(&packet.answers[0].name.to_string()[..], "facebook.com");
|
||||
assert_eq!(packet.answers[0].multicast_unique, false);
|
||||
assert_eq!(packet.answers[0].cls, C::IN);
|
||||
assert_eq!(packet.answers[0].ttl, 86333);
|
||||
match packet.answers[0].data {
|
||||
RData::TXT(ref text) => {
|
||||
assert_eq!(text.iter()
|
||||
.map(|x| from_utf8(x).unwrap())
|
||||
.collect::<Vec<_>>()
|
||||
.concat(), "v=spf1 redirect=_spf.facebook.com");
|
||||
|
||||
// also assert boundaries are kept
|
||||
assert_eq!(text.iter().collect::<Vec<_>>(),
|
||||
["v=spf1 redirect=_spf.".as_bytes(),
|
||||
"facebook.com".as_bytes()]);
|
||||
}
|
||||
ref x => panic!("Wrong rdata {:?}", x),
|
||||
}
|
||||
}
|
||||
}
|
11
third_party/rust/dns-parser/src/rdata/wks.rs
vendored
11
third_party/rust/dns-parser/src/rdata/wks.rs
vendored
@ -1,11 +0,0 @@
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
pub struct Record;
|
||||
|
||||
impl<'a> super::Record<'a> for Record {
|
||||
|
||||
const TYPE: isize = 11;
|
||||
|
||||
fn parse(_rdata: &'a [u8], _original: &'a [u8]) -> super::RDataResult<'a> {
|
||||
unimplemented!();
|
||||
}
|
||||
}
|
50
third_party/rust/dns-parser/src/structs.rs
vendored
50
third_party/rust/dns-parser/src/structs.rs
vendored
@ -1,50 +0,0 @@
|
||||
use {QueryType, QueryClass, Name, Class, Header, RData};
|
||||
use rdata::opt;
|
||||
|
||||
|
||||
/// Parsed DNS packet
|
||||
#[derive(Debug)]
|
||||
#[allow(missing_docs)] // should be covered by spec
|
||||
pub struct Packet<'a> {
|
||||
pub header: Header,
|
||||
pub questions: Vec<Question<'a>>,
|
||||
pub answers: Vec<ResourceRecord<'a>>,
|
||||
pub nameservers: Vec<ResourceRecord<'a>>,
|
||||
pub additional: Vec<ResourceRecord<'a>>,
|
||||
/// Optional Pseudo-RR
|
||||
/// When present it is sent as an RR in the additional section. In this RR
|
||||
/// the `class` and `ttl` fields store max udp packet size and flags
|
||||
/// respectively. To keep `ResourceRecord` clean we store the OPT record
|
||||
/// here.
|
||||
pub opt: Option<opt::Record<'a>>,
|
||||
}
|
||||
|
||||
/// A parsed chunk of data in the Query section of the packet
|
||||
#[derive(Debug)]
|
||||
#[allow(missing_docs)] // should be covered by spec
|
||||
pub struct Question<'a> {
|
||||
pub qname: Name<'a>,
|
||||
/// Whether or not we prefer unicast responses.
|
||||
/// This is used in multicast DNS.
|
||||
pub prefer_unicast: bool,
|
||||
pub qtype: QueryType,
|
||||
pub qclass: QueryClass,
|
||||
}
|
||||
|
||||
/// A single DNS record
|
||||
///
|
||||
/// We aim to provide whole range of DNS records available. But as time is
|
||||
/// limited we have some types of packets which are parsed and other provided
|
||||
/// as unparsed slice of bytes.
|
||||
#[derive(Debug)]
|
||||
#[allow(missing_docs)] // should be covered by spec
|
||||
pub struct ResourceRecord<'a> {
|
||||
pub name: Name<'a>,
|
||||
/// Whether or not the set of resource records is fully contained in the
|
||||
/// packet, or whether there will be more resource records in future
|
||||
/// packets. Only used for multicast DNS.
|
||||
pub multicast_unique: bool,
|
||||
pub cls: Class,
|
||||
pub ttl: u32,
|
||||
pub data: RData<'a>,
|
||||
}
|
44
third_party/rust/dns-parser/vagga.yaml
vendored
44
third_party/rust/dns-parser/vagga.yaml
vendored
@ -1,44 +0,0 @@
|
||||
commands:
|
||||
|
||||
cargo: !Command
|
||||
description: Run any cargo command
|
||||
container: ubuntu
|
||||
run: [cargo]
|
||||
|
||||
make: !Command
|
||||
description: Build the library
|
||||
container: ubuntu
|
||||
run: [cargo, build]
|
||||
|
||||
test: !Command
|
||||
description: Run the tests
|
||||
container: ubuntu
|
||||
environ:
|
||||
RUST_BACKTRACE: 1
|
||||
run: [cargo, test]
|
||||
|
||||
_bulk: !Command
|
||||
description: Run `bulk` command (for version bookkeeping)
|
||||
container: ubuntu
|
||||
run: [bulk]
|
||||
|
||||
containers:
|
||||
|
||||
ubuntu:
|
||||
setup:
|
||||
- !Ubuntu xenial
|
||||
- !UbuntuUniverse
|
||||
- !Install [ca-certificates, build-essential, vim]
|
||||
|
||||
- !TarInstall
|
||||
url: "https://static.rust-lang.org/dist/rust-1.28.0-x86_64-unknown-linux-gnu.tar.gz"
|
||||
script: "./install.sh --prefix=/usr \
|
||||
--components=rustc,rust-std-x86_64-unknown-linux-gnu,cargo"
|
||||
- &bulk !Tar
|
||||
url: "https://github.com/tailhook/bulk/releases/download/v0.4.11/bulk-v0.4.11.tar.gz"
|
||||
sha256: b718bb8448e726690c94d98d004bf7575f7a429106ec26ad3faf11e0fd9a7978
|
||||
path: /
|
||||
|
||||
environ:
|
||||
HOME: /work/target
|
||||
USER: pc
|
@ -43,7 +43,6 @@ storage = { path = "../../../../storage/rust" }
|
||||
bookmark_sync = { path = "../../../components/places/bookmark_sync", optional = true }
|
||||
shift_or_euc_c = "0.1.0"
|
||||
audio_thread_priority = "0.19.1"
|
||||
mdns_service = { path="../../../../media/mtransport/mdns_service" }
|
||||
|
||||
[build-dependencies]
|
||||
rustc_version = "0.2"
|
||||
|
@ -52,8 +52,6 @@ extern crate arrayvec;
|
||||
|
||||
extern crate audio_thread_priority;
|
||||
|
||||
extern crate mdns_service;
|
||||
|
||||
use std::boxed::Box;
|
||||
use std::env;
|
||||
use std::ffi::{CStr, CString};
|
||||
|
Loading…
Reference in New Issue
Block a user