Backed out 4 changesets (bug 1660970, bug 1525854, bug 1663657, bug 1645108) for perma failures on test_trr_additional_section.js. CLOSED TREE

Backed out changeset ad6c2e8af09b (bug 1663657)
Backed out changeset 419e26e3f452 (bug 1525854)
Backed out changeset 55bf856faf33 (bug 1660970)
Backed out changeset c543a3a008fa (bug 1645108)
This commit is contained in:
Razvan Maries 2020-09-15 02:35:05 +03:00
parent 7c00a1f440
commit c8e604eb78
29 changed files with 146 additions and 925 deletions

View File

@ -380,14 +380,14 @@ bool nsHTTPSOnlyUtils::LoopbackOrLocalException(nsIURI* aURI) {
mozilla::net::NetAddr addr(&tempAddr);
// Loopback IPs are always exempt
if (addr.IsLoopbackAddr()) {
if (IsLoopBackAddress(&addr)) {
return true;
}
// Local IP exception can get disabled with a pref
bool upgradeLocal =
mozilla::StaticPrefs::dom_security_https_only_mode_upgrade_local();
return (!upgradeLocal && addr.IsIPAddrLocal());
return (!upgradeLocal && IsIPAddrLocal(&addr));
}
/////////////////////////////////////////////////////////////////////

View File

@ -251,7 +251,7 @@ bool nsMixedContentBlocker::IsPotentiallyTrustworthyLoopbackHost(
// address, whereas for IPv4 127.0.0.1/8 are considered as potentially
// trustworthy. We already handled "[::1]" above, so all that's remained to
// handle here are IPv4 loopback addresses.
return addr.IsIPAddrV4() && addr.IsLoopbackAddr();
return IsIPAddrV4(&addr) && IsLoopBackAddress(&addr);
}
bool nsMixedContentBlocker::IsPotentiallyTrustworthyLoopbackURL(nsIURI* aURL) {

View File

@ -498,7 +498,7 @@ static bool PACResolveToString(const nsCString& aHostName,
if (!PACResolve(aHostName, &netAddr, aTimeout)) return false;
char dottedDecimal[128];
if (!netAddr.ToStringBuffer(dottedDecimal, sizeof(dottedDecimal)))
if (!NetAddrToString(&netAddr, dottedDecimal, sizeof(dottedDecimal)))
return false;
aDottedDecimal.Assign(dottedDecimal);

View File

@ -33,7 +33,7 @@ interface nsINetAddr : nsISupports
/**
* @return Either the IP address (FAMILY_INET, FAMILY_INET6) or the path
* (FAMILY_LOCAL) in string form. IP addresses are in the format produced by
* mozilla::net::NetAddr::ToStringBuffer.
* mozilla::net::NetAddrToString.
*
* Note: Paths for FAMILY_LOCAL may have length limitations which are
* implementation dependent and not documented as part of this interface.

View File

@ -739,7 +739,7 @@ nsresult nsIOService::RecheckCaptivePortalIfLocalRedirect(nsIChannel* newChan) {
}
NetAddr netAddr(&prAddr);
if (netAddr.IsIPAddrLocal()) {
if (IsIPAddrLocal(&netAddr)) {
// Redirects to local IP addresses are probably captive portals
RecheckCaptivePortal();
}
@ -947,7 +947,7 @@ nsIOService::HostnameIsLocalIPAddress(nsIURI* aURI, bool* aResult) {
PRStatus result = PR_StringToNetAddr(host.get(), &addr);
if (result == PR_SUCCESS) {
NetAddr netAddr(&addr);
if (netAddr.IsIPAddrLocal()) {
if (IsIPAddrLocal(&netAddr)) {
*aResult = true;
}
}
@ -974,7 +974,7 @@ nsIOService::HostnameIsSharedIPAddress(nsIURI* aURI, bool* aResult) {
PRStatus result = PR_StringToNetAddr(host.get(), &addr);
if (result == PR_SUCCESS) {
NetAddr netAddr(&addr);
if (netAddr.IsIPAddrShared()) {
if (IsIPAddrShared(&netAddr)) {
*aResult = true;
}
}

View File

@ -37,12 +37,12 @@ NS_IMETHODIMP nsNetAddr::GetAddress(nsACString& aAddress) {
/* PR_NetAddrToString can handle INET and INET6, but not LOCAL. */
case AF_INET:
aAddress.SetLength(kIPv4CStrBufSize);
mAddr.ToStringBuffer(aAddress.BeginWriting(), kIPv4CStrBufSize);
NetAddrToString(&mAddr, aAddress.BeginWriting(), kIPv4CStrBufSize);
aAddress.SetLength(strlen(aAddress.BeginReading()));
break;
case AF_INET6:
aAddress.SetLength(kIPv6CStrBufSize);
mAddr.ToStringBuffer(aAddress.BeginWriting(), kIPv6CStrBufSize);
NetAddrToString(&mAddr, aAddress.BeginWriting(), kIPv6CStrBufSize);
aAddress.SetLength(strlen(aAddress.BeginReading()));
break;
#if defined(XP_UNIX)

View File

@ -892,7 +892,7 @@ nsresult nsSocketTransport::InitWithConnectedSocket(PRFileDesc* fd,
NS_ASSERTION(!mFD.IsInitialized(), "already initialized");
char buf[kNetAddrMaxCStrBufSize];
addr->ToStringBuffer(buf, sizeof(buf));
NetAddrToString(addr, buf, sizeof(buf));
mHost.Assign(buf);
uint16_t port;
@ -1310,8 +1310,8 @@ nsresult nsSocketTransport::InitiateSocket() {
#endif
if (NS_SUCCEEDED(mCondition) && xpc::AreNonLocalConnectionsDisabled() &&
!(mNetAddr.IsIPAddrAny() || mNetAddr.IsIPAddrLocal() ||
mNetAddr.IsIPAddrShared())) {
!(IsIPAddrAny(&mNetAddr) || IsIPAddrLocal(&mNetAddr) ||
IsIPAddrShared(&mNetAddr))) {
nsAutoCString ipaddr;
RefPtr<nsNetAddr> netaddr = new nsNetAddr(&mNetAddr);
netaddr->GetAddress(ipaddr);
@ -1333,12 +1333,12 @@ nsresult nsSocketTransport::InitiateSocket() {
// Hosts/Proxy Hosts that are Local IP Literals should not be speculatively
// connected - Bug 853423.
if (mConnectionFlags & nsISocketTransport::DISABLE_RFC1918 &&
mNetAddr.IsIPAddrLocal()) {
IsIPAddrLocal(&mNetAddr)) {
if (SOCKET_LOG_ENABLED()) {
nsAutoCString netAddrCString;
netAddrCString.SetLength(kIPv6CStrBufSize);
if (!mNetAddr.ToStringBuffer(netAddrCString.BeginWriting(),
kIPv6CStrBufSize))
if (!NetAddrToString(&mNetAddr, netAddrCString.BeginWriting(),
kIPv6CStrBufSize))
netAddrCString = "<IP-to-string failed>"_ns;
SOCKET_LOG(
("nsSocketTransport::InitiateSocket skipping "
@ -1522,7 +1522,7 @@ nsresult nsSocketTransport::InitiateSocket() {
if (SOCKET_LOG_ENABLED()) {
char buf[kNetAddrMaxCStrBufSize];
mNetAddr.ToStringBuffer(buf, sizeof(buf));
NetAddrToString(&mNetAddr, buf, sizeof(buf));
SOCKET_LOG((" trying address: %s\n", buf));
}
@ -2526,7 +2526,7 @@ void nsSocketTransport::IsLocal(bool* aIsLocal) {
}
#endif
*aIsLocal = mNetAddr.IsLoopbackAddr();
*aIsLocal = IsLoopBackAddress(&mNetAddr);
}
}

View File

@ -70,7 +70,7 @@ static nsresult CheckIOStatus(const NetAddr* aAddr) {
return NS_ERROR_FAILURE;
}
if (gIOService->IsOffline() && !aAddr->IsLoopbackAddr()) {
if (gIOService->IsOffline() && !IsLoopBackAddress(aAddr)) {
return NS_ERROR_OFFLINE;
}
@ -472,7 +472,7 @@ void nsUDPSocket::OnSocketDetached(PRFileDesc* fd) {
void nsUDPSocket::IsLocal(bool* aIsLocal) {
// If bound to loopback, this UDP socket only accepts local connections.
*aIsLocal = mAddr.IsLoopbackAddr();
*aIsLocal = IsLoopBackAddress(&mAddr);
}
//-----------------------------------------------------------------------------
@ -567,7 +567,7 @@ nsUDPSocket::InitWithAddress(const NetAddr* aAddr, nsIPrincipal* aPrincipal,
}
uint16_t port;
if (NS_FAILED(aAddr->GetPort(&port))) {
if (NS_FAILED(net::GetPort(aAddr, &port))) {
NS_WARNING("invalid bind address");
goto fail;
}
@ -684,7 +684,7 @@ NS_IMETHODIMP
nsUDPSocket::GetPort(int32_t* aResult) {
// no need to enter the lock here
uint16_t result;
nsresult rv = mAddr.GetPort(&result);
nsresult rv = net::GetPort(&mAddr, &result);
*aResult = static_cast<int32_t>(result);
return rv;
}

View File

@ -98,8 +98,7 @@ void NetAddrToPRNetAddr(const NetAddr* addr, PRNetAddr* prAddr) {
#endif
}
bool NetAddr::ToStringBuffer(char* buf, uint32_t bufSize) const {
const NetAddr* addr = this;
bool NetAddrToString(const NetAddr* addr, char* buf, uint32_t bufSize) {
if (addr->raw.family == AF_INET) {
if (bufSize < INET_ADDRSTRLEN) {
return false;
@ -139,8 +138,7 @@ bool NetAddr::ToStringBuffer(char* buf, uint32_t bufSize) const {
return false;
}
bool NetAddr::IsLoopbackAddr() const {
const NetAddr* addr = this;
bool IsLoopBackAddress(const NetAddr* addr) {
if (addr->raw.family == AF_INET) {
// Consider 127.0.0.1/8 as loopback
uint32_t ipv4Addr = ntohl(addr->inet.ip);
@ -159,17 +157,17 @@ bool NetAddr::IsLoopbackAddr() const {
return false;
}
bool NetAddr::IsIPAddrAny() const {
if (this->raw.family == AF_INET) {
if (this->inet.ip == htonl(INADDR_ANY)) {
bool IsIPAddrAny(const NetAddr* addr) {
if (addr->raw.family == AF_INET) {
if (addr->inet.ip == htonl(INADDR_ANY)) {
return true;
}
} else if (this->raw.family == AF_INET6) {
if (IPv6ADDR_IS_UNSPECIFIED(&this->inet6.ip)) {
} else if (addr->raw.family == AF_INET6) {
if (IPv6ADDR_IS_UNSPECIFIED(&addr->inet6.ip)) {
return true;
}
if (IPv6ADDR_IS_V4MAPPED(&this->inet6.ip) &&
IPv6ADDR_V4MAPPED_TO_IPADDR(&this->inet6.ip) == htonl(INADDR_ANY)) {
if (IPv6ADDR_IS_V4MAPPED(&addr->inet6.ip) &&
IPv6ADDR_V4MAPPED_TO_IPADDR(&addr->inet6.ip) == htonl(INADDR_ANY)) {
return true;
}
}
@ -178,17 +176,17 @@ bool NetAddr::IsIPAddrAny() const {
NetAddr::NetAddr(const PRNetAddr* prAddr) { PRNetAddrToNetAddr(prAddr, this); }
bool NetAddr::IsIPAddrV4() const { return this->raw.family == AF_INET; }
bool IsIPAddrV4(const NetAddr* addr) { return addr->raw.family == AF_INET; }
bool NetAddr::IsIPAddrV4Mapped() const {
if (this->raw.family == AF_INET6) {
return IPv6ADDR_IS_V4MAPPED(&this->inet6.ip);
bool IsIPAddrV4Mapped(const NetAddr* addr) {
if (addr->raw.family == AF_INET6) {
return IPv6ADDR_IS_V4MAPPED(&addr->inet6.ip);
}
return false;
}
bool NetAddr::IsIPAddrLocal() const {
const NetAddr* addr = this;
bool IsIPAddrLocal(const NetAddr* addr) {
MOZ_ASSERT(addr);
// IPv4 RFC1918 and Link Local Addresses.
if (addr->raw.family == AF_INET) {
@ -212,8 +210,8 @@ bool NetAddr::IsIPAddrLocal() const {
return false;
}
bool NetAddr::IsIPAddrShared() const {
const NetAddr* addr = this;
bool IsIPAddrShared(const NetAddr* addr) {
MOZ_ASSERT(addr);
// IPv4 RFC6598.
if (addr->raw.family == AF_INET) {
@ -227,12 +225,12 @@ bool NetAddr::IsIPAddrShared() const {
return false;
}
nsresult NetAddr::GetPort(uint16_t* aResult) const {
nsresult GetPort(const NetAddr* aAddr, uint16_t* aResult) {
uint16_t port;
if (this->raw.family == PR_AF_INET) {
port = this->inet.port;
} else if (this->raw.family == PR_AF_INET6) {
port = this->inet6.port;
if (aAddr->raw.family == PR_AF_INET) {
port = aAddr->inet.port;
} else if (aAddr->raw.family == PR_AF_INET6) {
port = aAddr->inet6.port;
} else {
return NS_ERROR_NOT_INITIALIZED;
}

View File

@ -134,15 +134,6 @@ union NetAddr {
NetAddr() { memset(this, 0, sizeof(NetAddr)); }
explicit NetAddr(const PRNetAddr* prAddr);
bool IsIPAddrAny() const;
bool IsLoopbackAddr() const;
bool IsIPAddrV4() const;
bool IsIPAddrV4Mapped() const;
bool IsIPAddrLocal() const;
bool IsIPAddrShared() const;
nsresult GetPort(uint16_t* aResult) const;
bool ToStringBuffer(char* buf, uint32_t bufSize) const;
};
class AddrInfo {
@ -229,6 +220,22 @@ void PRNetAddrToNetAddr(const PRNetAddr* prAddr, NetAddr* addr);
// Does not do a ptr safety check!
void NetAddrToPRNetAddr(const NetAddr* addr, PRNetAddr* prAddr);
bool NetAddrToString(const NetAddr* addr, char* buf, uint32_t bufSize);
bool IsLoopBackAddress(const NetAddr* addr);
bool IsIPAddrAny(const NetAddr* addr);
bool IsIPAddrV4(const NetAddr* addr);
bool IsIPAddrV4Mapped(const NetAddr* addr);
bool IsIPAddrLocal(const NetAddr* addr);
bool IsIPAddrShared(const NetAddr* addr);
nsresult GetPort(const NetAddr* aAddr, uint16_t* aResult);
} // namespace net
} // namespace mozilla

View File

@ -147,7 +147,7 @@ ChildDNSRecord::GetNextAddrAsString(nsACString& result) {
}
char buf[kIPv6CStrBufSize];
if (addr.ToStringBuffer(buf, sizeof(buf))) {
if (NetAddrToString(&addr, buf, sizeof(buf))) {
result.Assign(buf);
return NS_OK;
}

View File

@ -1176,139 +1176,33 @@ nsresult TRR::DohDecode(nsCString& aHost) {
uint16_t arRecords = get16bit(mResponse, 10);
LOG(("TRR Decode: %d additional resource records (%u bytes body)\n",
arRecords, mBodySize));
nsClassHashtable<nsCStringHashKey, DOHresp> additionalRecords;
while (arRecords) {
nsAutoCString qname;
rv = GetQname(qname, index);
rv = PassQName(index);
if (NS_FAILED(rv)) {
LOG(("Bad qname for additional record"));
return rv;
}
if (mBodySize < (index + 8)) {
return NS_ERROR_ILLEGAL_VALUE;
}
uint16_t type = get16bit(mResponse, index);
index += 2;
// The next two bytes encode class
// (or udpPayloadSize when type is TRRTYPE_OPT)
uint16_t cls = get16bit(mResponse, index);
index += 2;
// The next 4 bytes encode TTL
// (or extRCode + ednsVersion + flags when type is TRRTYPE_OPT)
uint32_t ttl = get32bit(mResponse, index);
index += 4;
// cls and ttl are unused when type is TRRTYPE_OPT
index += 2; // type
index += 2; // class
index += 4; // ttl
// 16 bit RDLENGTH
if (mBodySize < (index + 2)) {
LOG(("Record too small"));
return NS_ERROR_ILLEGAL_VALUE;
}
uint16_t rdlength = get16bit(mResponse, index);
uint16_t RDLENGTH = get16bit(mResponse, index);
index += 2;
if (mBodySize < (index + rdlength)) {
LOG(("rdlength too big"));
if (mBodySize < (index + RDLENGTH)) {
return NS_ERROR_ILLEGAL_VALUE;
}
auto parseRecord = [&]() {
LOG(("Parsing additional record type: %u", type));
auto& entry = additionalRecords.GetOrInsert(qname);
if (!entry) {
entry.reset(new DOHresp());
}
switch (type) {
case TRRTYPE_A:
if (kDNS_CLASS_IN != cls) {
LOG(("NOT IN - returning"));
return;
}
if (rdlength != 4) {
LOG(("TRR bad length for A (%u)\n", rdlength));
return;
}
rv = entry->Add(ttl, mResponse, index, rdlength, mAllowRFC1918);
if (NS_FAILED(rv)) {
LOG(
("TRR:DohDecode failed: local IP addresses or unknown IP "
"family\n"));
return;
}
break;
case TRRTYPE_AAAA:
if (kDNS_CLASS_IN != cls) {
LOG(("NOT IN - returning"));
return;
}
if (rdlength != 16) {
LOG(("TRR bad length for AAAA (%u)\n", rdlength));
return;
}
rv = entry->Add(ttl, mResponse, index, rdlength, mAllowRFC1918);
if (NS_FAILED(rv)) {
LOG(("TRR got unique/local IPv6 address!\n"));
return;
}
break;
case TRRTYPE_OPT: { // OPT
LOG(("Parsing opt rdlen: %u", rdlength));
unsigned int offset = 0;
while (offset + 2 <= rdlength) {
uint16_t optCode = get16bit(mResponse, index + offset);
LOG(("optCode: %u", optCode));
offset += 2;
if (offset + 2 > rdlength) {
break;
}
uint16_t optLen = get16bit(mResponse, index + offset);
LOG(("optLen: %u", optLen));
offset += 2;
if (offset + optLen > rdlength) {
LOG(("offset: %u, optLen: %u, rdlen: %u", offset, optLen,
rdlength));
break;
}
LOG(("OPT: code: %u len:%u", optCode, optLen));
if (optCode != 15) {
offset += optLen;
continue;
}
// optCode == 15; Extended DNS error
if (offset + 2 > rdlength || optLen < 2) {
break;
}
mExtendedError = get16bit(mResponse, index + offset);
LOG((
"Extended error code: %u message: %s", mExtendedError,
nsAutoCString((char*)mResponse + index + offset + 2, optLen - 2)
.get()));
offset += optLen;
}
break;
}
default:
break;
}
};
parseRecord();
index += rdlength;
index += RDLENGTH;
LOG(("done with additional rr now %u of %u\n", index, mBodySize));
arRecords--;
}
SaveAdditionalRecords(additionalRecords);
if (index != mBodySize) {
LOG(("DohDecode failed to parse entire response body, %u out of %u bytes\n",
index, mBodySize));
@ -1316,8 +1210,8 @@ nsresult TRR::DohDecode(nsCString& aHost) {
return NS_ERROR_ILLEGAL_VALUE;
}
if ((mType != TRRTYPE_NS) && mCname.IsEmpty() && mDNS.mAddresses.IsEmpty() &&
mResult.is<TypeRecordEmpty>()) {
if ((mType != TRRTYPE_NS) && mCname.IsEmpty() &&
!mDNS.mAddresses.getFirst() && mResult.is<TypeRecordEmpty>()) {
// no entries were stored!
LOG(("TRR: No entries were stored!\n"));
return NS_ERROR_FAILURE;
@ -1335,45 +1229,6 @@ nsresult TRR::DohDecode(nsCString& aHost) {
return NS_OK;
}
void TRR::SaveAdditionalRecords(
const nsClassHashtable<nsCStringHashKey, DOHresp>& aRecords) {
if (!mRec) {
return;
}
nsresult rv;
for (auto iter = aRecords.ConstIter(); !iter.Done(); iter.Next()) {
if (iter.Data() && iter.Data()->mAddresses.IsEmpty()) {
// no point in adding empty records.
continue;
}
RefPtr<nsHostRecord> hostRecord;
rv = mHostResolver->GetHostRecord(
iter.Key(), EmptyCString(), nsIDNSService::RESOLVE_TYPE_DEFAULT,
mRec->flags, AF_UNSPEC, mRec->pb, mRec->originSuffix,
getter_AddRefs(hostRecord));
if (NS_FAILED(rv)) {
LOG(("Failed to get host record for additional record %s",
nsCString(iter.Key()).get()));
continue;
}
RefPtr<AddrInfo> ai(new AddrInfo(iter.Key(), TRRTYPE_A,
std::move(iter.Data()->mAddresses),
iter.Data()->mTtl));
// Since we're not actually calling NameLookup for this record, we need
// to set these fields to avoid assertions in CompleteLookup.
// This is quite hacky, and should be fixed.
hostRecord->mResolving++;
hostRecord->mEffectiveTRRMode = mRec->mEffectiveTRRMode;
RefPtr<AddrHostRecord> addrRec = do_QueryObject(hostRecord);
addrRec->mTrrStart = TimeStamp::Now();
addrRec->mTrrA = this; // Hack!
LOG(("Completing lookup for additional: %s", nsCString(iter.Key()).get()));
(void)mHostResolver->CompleteLookup(hostRecord, NS_OK, ai, mPB,
mOriginSuffix, AddrHostRecord::TRR_OK);
}
}
nsresult TRR::ParseSvcParam(unsigned int svcbIndex, uint16_t key,
SvcFieldValue& field, uint16_t length) {
switch (key) {
@ -1515,10 +1370,21 @@ void TRR::StoreIPHintAsDNSRecord(const struct SVCB& aSVCBRecord) {
nsresult TRR::ReturnData(nsIChannel* aChannel) {
if (mType != TRRTYPE_TXT && mType != TRRTYPE_HTTPSSVC) {
// create and populate an AddrInfo instance to pass on
RefPtr<AddrInfo> ai(
new AddrInfo(mHost, mType, nsTArray<NetAddr>(), mDNS.mTtl));
DOHaddr* item;
uint32_t ttl = AddrInfo::NO_TTL_DATA;
nsTArray<NetAddr> addresses;
while ((item = static_cast<DOHaddr*>(mDNS.mAddresses.popFirst()))) {
addresses.AppendElement(item->mNet);
if (item->mTtl < ttl) {
// While the DNS packet might return individual TTLs for each address,
// we can only return one value in the AddrInfo class so pick the
// lowest number.
ttl = item->mTtl;
}
}
RefPtr<AddrInfo> ai(new AddrInfo(mHost, mType, nsTArray<NetAddr>(), ttl));
auto builder = ai->Build();
builder.SetAddresses(std::move(mDNS.mAddresses));
builder.SetAddresses(std::move(addresses));
// Set timings.
nsCOMPtr<nsITimedChannel> timedChan = do_QueryInterface(aChannel);
@ -1550,31 +1416,6 @@ nsresult TRR::ReturnData(nsIChannel* aChannel) {
return NS_OK;
}
// https://datatracker.ietf.org/doc/html/draft-ietf-dnsop-extended-error-16#section-4
// This is a list of errors for which we should not fallback to Do53.
// These are normally DNSSEC failures or explicit filtering performed by the
// recursive resolver.
bool hardFail(uint16_t code) {
const uint16_t noFallbackErrors[] = {
4, // Forged answer (malware filtering)
6, // DNSSEC Boggus
7, // Signature expired
8, // Signature not yet valid
9, // DNSKEY Missing
10, // RRSIG missing
11, // No ZONE Key Bit set
12, // NSEC Missing
17, // Filtered
};
for (const auto& err : noFallbackErrors) {
if (code == err) {
return true;
}
}
return false;
}
nsresult TRR::FailData(nsresult error) {
if (!mHostResolver) {
return NS_ERROR_FAILURE;
@ -1583,10 +1424,6 @@ nsresult TRR::FailData(nsresult error) {
// If we didn't record a reason until now, record a default one.
RecordReason(nsHostRecord::TRR_FAILED);
if (mExtendedError != UINT16_MAX && hardFail(mExtendedError)) {
error = NS_ERROR_DEFINITIVE_UNKNOWN_HOST;
}
if (mType == TRRTYPE_TXT || mType == TRRTYPE_HTTPSSVC) {
TypeRecordResultType empty(Nothing{});
(void)mHostResolver->CompleteLookupByType(mRec, error, empty, 0, mPB);
@ -1608,7 +1445,7 @@ nsresult TRR::FailData(nsresult error) {
nsresult TRR::FollowCname(nsIChannel* aChannel) {
nsresult rv = NS_OK;
nsAutoCString cname;
while (NS_SUCCEEDED(rv) && mDNS.mAddresses.IsEmpty() && !mCname.IsEmpty() &&
while (NS_SUCCEEDED(rv) && !mDNS.mAddresses.getFirst() && !mCname.IsEmpty() &&
mCnameLoop > 0) {
mCnameLoop--;
LOG(("TRR::On200Response CNAME %s => %s (%u)\n", mHost.get(), mCname.get(),
@ -1626,7 +1463,7 @@ nsresult TRR::FollowCname(nsIChannel* aChannel) {
// restore mCname as DohDecode() change it
mCname = cname;
if (NS_SUCCEEDED(rv) && !mDNS.mAddresses.IsEmpty()) {
if (NS_SUCCEEDED(rv) && mDNS.mAddresses.getFirst()) {
ReturnData(aChannel);
return NS_OK;
}
@ -1656,7 +1493,7 @@ nsresult TRR::On200Response(nsIChannel* aChannel) {
return NS_ERROR_FAILURE;
}
if (!mDNS.mAddresses.IsEmpty() || mType == TRRTYPE_TXT || mCname.IsEmpty()) {
if (mDNS.mAddresses.getFirst() || mType == TRRTYPE_TXT || mCname.IsEmpty()) {
// pass back the response data
ReturnData(aChannel);
return NS_OK;
@ -1781,42 +1618,37 @@ TRR::OnDataAvailable(nsIRequest* aRequest, nsIInputStream* aInputStream,
nsresult DOHresp::Add(uint32_t TTL, unsigned char* dns, unsigned int index,
uint16_t len, bool aLocalAllowed) {
NetAddr addr;
auto doh = MakeUnique<DOHaddr>();
NetAddr* addr = &doh->mNet;
if (4 == len) {
// IPv4
addr.inet.family = AF_INET;
addr.inet.port = 0; // unknown
addr.inet.ip = ntohl(get32bit(dns, index));
addr->inet.family = AF_INET;
addr->inet.port = 0; // unknown
addr->inet.ip = ntohl(get32bit(dns, index));
} else if (16 == len) {
// IPv6
addr.inet6.family = AF_INET6;
addr.inet6.port = 0; // unknown
addr.inet6.flowinfo = 0; // unknown
addr.inet6.scope_id = 0; // unknown
addr->inet6.family = AF_INET6;
addr->inet6.port = 0; // unknown
addr->inet6.flowinfo = 0; // unknown
addr->inet6.scope_id = 0; // unknown
for (int i = 0; i < 16; i++, index++) {
addr.inet6.ip.u8[i] = dns[index];
addr->inet6.ip.u8[i] = dns[index];
}
} else {
return NS_ERROR_UNEXPECTED;
}
if (addr.IsIPAddrLocal() && !aLocalAllowed) {
if (IsIPAddrLocal(addr) && !aLocalAllowed) {
return NS_ERROR_FAILURE;
}
// While the DNS packet might return individual TTLs for each address,
// we can only return one value in the AddrInfo class so pick the
// lowest number.
if (mTtl < TTL) {
mTtl = TTL;
}
doh->mTtl = TTL;
if (LOG_ENABLED()) {
char buf[128];
addr.ToStringBuffer(buf, sizeof(buf));
NetAddrToString(addr, buf, sizeof(buf));
LOG(("DOHresp:Add %s\n", buf));
}
mAddresses.AppendElement(addr);
mAddresses.insertBack(doh.release());
return NS_OK;
}

View File

@ -9,7 +9,6 @@
#include "mozilla/net/DNSByTypeRecord.h"
#include "mozilla/Assertions.h"
#include "nsClassHashtable.h"
#include "nsIChannel.h"
#include "nsIHttpPushListener.h"
#include "nsIInterfaceRequestor.h"
@ -27,21 +26,31 @@ enum TrrType {
TRRTYPE_NS = 2,
TRRTYPE_CNAME = 5,
TRRTYPE_AAAA = 28,
TRRTYPE_OPT = 41,
TRRTYPE_TXT = 16,
TRRTYPE_HTTPSSVC = nsIDNSService::RESOLVE_TYPE_HTTPSSVC, // 65
};
class DOHaddr : public LinkedListElement<DOHaddr> {
public:
NetAddr mNet;
uint32_t mTtl;
};
class TRRService;
class TRRServiceChannel;
extern TRRService* gTRRService;
class DOHresp {
public:
~DOHresp() {
DOHaddr* el;
while ((el = mAddresses.popLast())) {
delete el;
}
}
nsresult Add(uint32_t TTL, unsigned char* dns, unsigned int index,
uint16_t len, bool aLocalAllowed);
nsTArray<NetAddr> mAddresses;
uint32_t mTtl = UINT32_MAX;
LinkedList<DOHaddr> mAddresses;
};
class TRR : public Runnable,
@ -146,8 +155,6 @@ class TRR : public Runnable,
nsresult FollowCname(nsIChannel* aChannel);
bool UseDefaultServer();
void SaveAdditionalRecords(
const nsClassHashtable<nsCStringHashKey, DOHresp>& aRecords);
nsresult CreateChannelHelper(nsIURI* aUri, nsIChannel** aResult);
@ -172,7 +179,6 @@ class TRR : public Runnable,
uint32_t mCnameLoop = kCnameChaseMax; // loop detection counter
bool mAllowRFC1918 = false;
uint16_t mExtendedError = UINT16_MAX;
uint32_t mTTL = UINT32_MAX;
TypeRecordResultType mResult = mozilla::AsVariant(Nothing());

View File

@ -291,7 +291,7 @@ nsDNSRecord::GetNextAddrAsString(nsACString& result) {
}
char buf[kIPv6CStrBufSize];
if (addr.ToStringBuffer(buf, sizeof(buf))) {
if (NetAddrToString(&addr, buf, sizeof(buf))) {
result.Assign(buf);
return NS_OK;
}

View File

@ -311,7 +311,7 @@ bool AddrHostRecord::Blacklisted(const NetAddr* aQuery) {
}
char buf[kIPv6CStrBufSize];
if (!aQuery->ToStringBuffer(buf, sizeof(buf))) {
if (!NetAddrToString(aQuery, buf, sizeof(buf))) {
return false;
}
nsDependentCString strQuery(buf);
@ -336,7 +336,7 @@ void AddrHostRecord::ReportUnusable(const NetAddr* aAddress) {
++mBlacklistedCount;
char buf[kIPv6CStrBufSize];
if (aAddress->ToStringBuffer(buf, sizeof(buf))) {
if (NetAddrToString(aAddress, buf, sizeof(buf))) {
LOG(
("Successfully adding address [%s] to blacklist for host "
"[%s].\n",
@ -2011,9 +2011,7 @@ nsHostResolver::LookupStatus nsHostResolver::CompleteLookup(
if (NS_FAILED(addrRec->mFirstTRRresult) && NS_FAILED(status) &&
(addrRec->mFirstTRRresult != NS_ERROR_UNKNOWN_HOST) &&
(status != NS_ERROR_UNKNOWN_HOST) &&
(addrRec->mFirstTRRresult != NS_ERROR_DEFINITIVE_UNKNOWN_HOST) &&
(status != NS_ERROR_DEFINITIVE_UNKNOWN_HOST)) {
(status != NS_ERROR_UNKNOWN_HOST)) {
// the errors are not failed resolves, that means
// something else failed, consider this as *TRR not used*
// for actually trying to resolve the host
@ -2040,8 +2038,7 @@ nsHostResolver::LookupStatus nsHostResolver::CompleteLookup(
}
if (!addrRec->mTRRSuccess &&
addrRec->mEffectiveTRRMode == nsIRequest::TRR_FIRST_MODE &&
addrRec->mFirstTRRresult != NS_ERROR_DEFINITIVE_UNKNOWN_HOST) {
addrRec->mEffectiveTRRMode == nsIRequest::TRR_FIRST_MODE) {
MOZ_ASSERT(!addrRec->mResolving);
NativeLookup(addrRec);
MOZ_ASSERT(addrRec->mResolving);
@ -2106,7 +2103,7 @@ nsHostResolver::LookupStatus nsHostResolver::CompleteLookup(
if (addrRec->addr_info) {
for (const auto& elem : addrRec->addr_info->Addresses()) {
char buf[128];
elem.ToStringBuffer(buf, sizeof(buf));
NetAddrToString(&elem, buf, sizeof(buf));
LOG(("CompleteLookup: %s has %s\n", addrRec->host.get(), buf));
}
} else {
@ -2421,7 +2418,7 @@ void nsHostResolver::GetDNSCacheEntries(nsTArray<DNSCacheEntries>* args) {
MutexAutoLock lock(addrRec->addr_info_lock);
for (const auto& addr : addrRec->addr_info->Addresses()) {
char buf[kIPv6CStrBufSize];
if (addr.ToStringBuffer(buf, sizeof(buf))) {
if (NetAddrToString(&addr, buf, sizeof(buf))) {
info.hostaddr.AppendElement(buf);
}
}

View File

@ -1219,9 +1219,9 @@ nsresult nsFtpState::S_pasv() {
if (sTrans) {
nsresult rv = sTrans->GetPeerAddr(&mServerAddress);
if (NS_SUCCEEDED(rv)) {
if (!mServerAddress.IsIPAddrAny())
if (!IsIPAddrAny(&mServerAddress))
mServerIsIPv6 = (mServerAddress.raw.family == AF_INET6) &&
!mServerAddress.IsIPAddrV4Mapped();
!IsIPAddrV4Mapped(&mServerAddress);
else {
/*
* In case of SOCKS5 remote DNS resolution, we do
@ -1234,7 +1234,7 @@ nsresult nsFtpState::S_pasv() {
rv = sTrans->GetSelfAddr(&selfAddress);
if (NS_SUCCEEDED(rv))
mServerIsIPv6 = (selfAddress.raw.family == AF_INET6) &&
!selfAddress.IsIPAddrV4Mapped();
!IsIPAddrV4Mapped(&selfAddress);
}
}
}
@ -1351,9 +1351,9 @@ nsFtpState::R_pasv() {
nsCOMPtr<nsISocketTransport> strans;
nsAutoCString host;
if (!mServerAddress.IsIPAddrAny()) {
if (!IsIPAddrAny(&mServerAddress)) {
char buf[kIPv6CStrBufSize];
mServerAddress.ToStringBuffer(buf, sizeof(buf));
NetAddrToString(&mServerAddress, buf, sizeof(buf));
host.Assign(buf);
} else {
/*

View File

@ -98,7 +98,7 @@ nsresult Http3Session::Init(const nsACString& aOrigin,
return NS_ERROR_FAILURE;
}
char buf[kIPv6CStrBufSize];
selfAddr.ToStringBuffer(buf, kIPv6CStrBufSize);
NetAddrToString(&selfAddr, buf, kIPv6CStrBufSize);
nsAutoCString selfAddrStr;
if (selfAddr.raw.family == AF_INET6) {
@ -119,7 +119,7 @@ nsresult Http3Session::Init(const nsACString& aOrigin,
LOG3(("Http3Session::Init GetPeerAddr failed [this=%p]", this));
return NS_ERROR_FAILURE;
}
peerAddr.ToStringBuffer(buf, kIPv6CStrBufSize);
NetAddrToString(&peerAddr, buf, kIPv6CStrBufSize);
nsAutoCString peerAddrStr;
if (peerAddr.raw.family == AF_INET6) {

View File

@ -2491,7 +2491,7 @@ HttpBaseChannel::GetLocalAddress(nsACString& addr) {
if (mSelfAddr.raw.family == PR_AF_UNSPEC) return NS_ERROR_NOT_AVAILABLE;
addr.SetLength(kIPv6CStrBufSize);
mSelfAddr.ToStringBuffer(addr.BeginWriting(), kIPv6CStrBufSize);
NetAddrToString(&mSelfAddr, addr.BeginWriting(), kIPv6CStrBufSize);
addr.SetLength(strlen(addr.BeginReading()));
return NS_OK;
@ -2586,7 +2586,7 @@ HttpBaseChannel::GetRemoteAddress(nsACString& addr) {
if (mPeerAddr.raw.family == PR_AF_UNSPEC) return NS_ERROR_NOT_AVAILABLE;
addr.SetLength(kIPv6CStrBufSize);
mPeerAddr.ToStringBuffer(addr.BeginWriting(), kIPv6CStrBufSize);
NetAddrToString(&mPeerAddr, addr.BeginWriting(), kIPv6CStrBufSize);
addr.SetLength(strlen(addr.BeginReading()));
return NS_OK;

View File

@ -1632,7 +1632,7 @@ HttpChannelParent::OnStopRequest(nsIRequest* aRequest, nsresult aStatusCode) {
isLocal = (peerAddr.raw.family == PR_AF_LOCAL);
#endif
isLocal = isLocal || peerAddr.IsLoopbackAddr();
isLocal = isLocal || IsLoopBackAddress(&peerAddr);
if (!isLocal) {
if (!mHasSuspendedByBackPressure) {

View File

@ -559,7 +559,7 @@ bool nsHttpConnectionInfo::HostIsLocalIPLiteral() const {
return false;
}
NetAddr netAddr(&prAddr);
return netAddr.IsIPAddrLocal();
return IsIPAddrLocal(&netAddr);
}
} // namespace net

View File

@ -5296,7 +5296,8 @@ nsHttpConnectionMgr::nsHalfOpenSocket::OnTransportStatus(nsITransport* trans,
for (uint32_t i = 0; i < addressSet.Length(); ++i) {
nsCString* newKey = mEnt->mCoalescingKeys.AppendElement(nsCString());
newKey->SetLength(kIPv6CStrBufSize + 26);
addressSet[i].ToStringBuffer(newKey->BeginWriting(), kIPv6CStrBufSize);
NetAddrToString(&addressSet[i], newKey->BeginWriting(),
kIPv6CStrBufSize);
newKey->SetLength(strlen(newKey->BeginReading()));
if (mEnt->mConnInfo->GetAnonymous()) {
newKey->AppendLiteral("~A:");

View File

@ -545,7 +545,7 @@ PRStatus nsSOCKSSocketInfo::ConnectToProxy(PRFileDesc* fd) {
if (MOZ_LOG_TEST(gSOCKSLog, LogLevel::Debug)) {
char buf[kIPv6CStrBufSize];
mInternalProxyAddr.ToStringBuffer(buf, sizeof(buf));
NetAddrToString(&mInternalProxyAddr, buf, sizeof(buf));
LOGDEBUG(("socks: trying proxy server, %s:%hu", buf,
ntohs(mInternalProxyAddr.inet.port)));
}

View File

@ -147,7 +147,6 @@ class TRRDNSListener {
this.expectedAnswer,
`Checking result for ${this.name}`
);
inRecord.rewind(); // In case the caller also checks the addresses
if (this.delay !== undefined) {
Assert.greaterOrEqual(
@ -269,39 +268,23 @@ function trrQueryHandler(req, resp, url) {
function processRequest(req, resp, payload) {
let dnsQuery = global.dnsPacket.decode(payload);
let response =
let answers =
global.dns_query_answers[
`${dnsQuery.questions[0].name}/${dnsQuery.questions[0].type}`
] || {};
] || [];
let buf = global.dnsPacket.encode({
type: "response",
id: dnsQuery.id,
flags: global.dnsPacket.RECURSION_DESIRED,
questions: dnsQuery.questions,
answers: response.answers || [],
additionals: response.additionals || [],
answers,
});
let writeResponse = (resp, buf) => {
resp.setHeader("Content-Length", buf.length);
resp.writeHead(200, { "Content-Type": "application/dns-message" });
resp.write(buf);
resp.end("");
};
if (response.delay) {
setTimeout(
arg => {
writeResponse(arg[0], arg[1]);
},
response.delay,
[resp, buf]
);
return;
}
writeResponse(resp, buf);
resp.setHeader("Content-Length", buf.length);
resp.writeHead(200, { "Content-Type": "application/dns-message" });
resp.write(buf);
resp.end("");
}
}
@ -350,12 +333,10 @@ class TRRServer {
/// flush: false,
/// data: "1.2.3.4",
/// }]
async registerDoHAnswers(name, type, answers, additionals, delay = 0) {
let text = `global.dns_query_answers["${name}/${type}"] = ${JSON.stringify({
answers,
additionals,
delay,
})}`;
async registerDoHAnswers(name, type, answers) {
let text = `global.dns_query_answers["${name}/${type}"] = ${JSON.stringify(
answers
)}`;
return this.execute(text);
}
}

View File

@ -1,276 +0,0 @@
/* 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 strict";
const dns = Cc["@mozilla.org/network/dns-service;1"].getService(
Ci.nsIDNSService
);
trr_test_setup();
registerCleanupFunction(async () => {
trr_clear_prefs();
});
function makeChan(url) {
let chan = NetUtil.newChannel({
uri: url,
loadUsingSystemPrincipal: true,
}).QueryInterface(Ci.nsIHttpChannel);
return chan;
}
let processId;
function channelOpenPromise(chan) {
return new Promise(resolve => {
function finish(req, buffer) {
resolve([req, buffer]);
}
chan.asyncOpen(new ChannelListener(finish));
});
}
add_task(async function test_parse_additional_section() {
let trrServer = new TRRServer();
registerCleanupFunction(async () => trrServer.stop());
await trrServer.start();
dump(`port = ${trrServer.port}\n`);
let chan = makeChan(`https://localhost:${trrServer.port}/test?bla=some`);
let [req, resp] = await channelOpenPromise(chan);
equal(resp, "<h1> 404 Path not found: /test?bla=some</h1>");
dns.clearCache(true);
Services.prefs.setIntPref("network.trr.mode", 3);
Services.prefs.setCharPref(
"network.trr.uri",
`https://foo.example.com:${trrServer.port}/dns-query`
);
await trrServer.registerDoHAnswers(
"something.foo",
"A",
[
{
name: "something.foo",
ttl: 55,
type: "A",
flush: false,
data: "1.2.3.4",
},
],
[
{
name: "else.foo",
ttl: 55,
type: "A",
flush: false,
data: "2.3.4.5",
},
]
);
await new TRRDNSListener("something.foo", "1.2.3.4");
await new TRRDNSListener("else.foo", "2.3.4.5");
await trrServer.registerDoHAnswers(
"a.foo",
"A",
[
{
name: "a.foo",
ttl: 55,
type: "A",
flush: false,
data: "1.2.3.4",
},
],
[
{
name: "b.foo",
ttl: 55,
type: "A",
flush: false,
data: "2.3.4.5",
},
]
);
await trrServer.registerDoHAnswers("b.foo", "A", [
{
name: "b.foo",
ttl: 55,
type: "A",
flush: false,
data: "3.4.5.6",
},
]);
let req1 = new TRRDNSListener("a.foo", "1.2.3.4");
// A request for b.foo will be in progress by the time we parse the additional
// record. To keep things simple we don't end up saving the record, instead
// we wait for the in-progress request to complete.
// This check is also racy - if the response for a.foo completes before we make
// this request, we'll put the other IP in the cache. But that is very unlikely.
let req2 = new TRRDNSListener("b.foo", "3.4.5.6");
await Promise.all([req1, req2]);
// IPv6 additional
await trrServer.registerDoHAnswers(
"xyz.foo",
"A",
[
{
name: "xyz.foo",
ttl: 55,
type: "A",
flush: false,
data: "1.2.3.4",
},
],
[
{
name: "abc.foo",
ttl: 55,
type: "AAAA",
flush: false,
data: "::1:2:3:4",
},
]
);
await new TRRDNSListener("xyz.foo", "1.2.3.4");
await new TRRDNSListener("abc.foo", "::1:2:3:4");
// IPv6 additional
await trrServer.registerDoHAnswers(
"ipv6.foo",
"AAAA",
[
{
name: "ipv6.foo",
ttl: 55,
type: "AAAA",
flush: false,
data: "::abcd",
},
],
[
{
name: "def.foo",
ttl: 55,
type: "AAAA",
flush: false,
data: "::a:b:c:d",
},
]
);
await new TRRDNSListener("ipv6.foo", "::abcd");
await new TRRDNSListener("def.foo", "::a:b:c:d");
// IPv6 additional
await trrServer.registerDoHAnswers(
"ipv6b.foo",
"AAAA",
[
{
name: "ipv6b.foo",
ttl: 55,
type: "AAAA",
flush: false,
data: "::abcd",
},
],
[
{
name: "qqqq.foo",
ttl: 55,
type: "A",
flush: false,
data: "9.8.7.6",
},
]
);
await new TRRDNSListener("ipv6b.foo", "::abcd");
await new TRRDNSListener("qqqq.foo", "9.8.7.6");
// Multiple IPs and multiple additional records
await trrServer.registerDoHAnswers(
"multiple.foo",
"A",
[
{
name: "multiple.foo",
ttl: 55,
type: "A",
flush: false,
data: "9.9.9.9",
},
],
[
{
// Should be ignored, because it should be in the answer section
name: "multiple.foo",
ttl: 55,
type: "A",
flush: false,
data: "1.1.1.1",
},
{
// Is ignored, because it should be in the answer section
name: "multiple.foo",
ttl: 55,
type: "AAAA",
flush: false,
data: "::abcd",
},
{
name: "yuiop.foo",
ttl: 55,
type: "AAAA",
flush: false,
data: "::abcd",
},
{
name: "yuiop.foo",
ttl: 55,
type: "A",
flush: false,
data: "1.2.3.4",
},
]
);
let [inRequest, inRecord, inStatus] = await new TRRDNSListener(
"multiple.foo",
"9.9.9.9"
);
let IPs = [];
inRecord.QueryInterface(Ci.nsIDNSAddrRecord);
inRecord.rewind();
while (inRecord.hasMore()) {
IPs.push(inRecord.getNextAddrAsString());
}
equal(IPs.length, 1);
equal(IPs[0], "9.9.9.9");
IPs = [];
[inRequest, inRecord, inStatus] = await new TRRDNSListener(
"yuiop.foo",
undefined,
false
);
inRecord.QueryInterface(Ci.nsIDNSAddrRecord);
inRecord.rewind();
while (inRecord.hasMore()) {
IPs.push(inRecord.getNextAddrAsString());
}
equal(IPs.length, 2);
equal(IPs[0], "::abcd");
equal(IPs[1], "1.2.3.4");
await trrServer.stop();
});

View File

@ -1,304 +0,0 @@
/* 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 strict";
const dns = Cc["@mozilla.org/network/dns-service;1"].getService(
Ci.nsIDNSService
);
trr_test_setup();
registerCleanupFunction(async () => {
trr_clear_prefs();
});
function makeChan(url) {
let chan = NetUtil.newChannel({
uri: url,
loadUsingSystemPrincipal: true,
}).QueryInterface(Ci.nsIHttpChannel);
return chan;
}
let processId;
function channelOpenPromise(chan) {
return new Promise(resolve => {
function finish(req, buffer) {
resolve([req, buffer]);
}
chan.asyncOpen(new ChannelListener(finish));
});
}
let trrServer;
add_task(async function setup() {
trrServer = new TRRServer();
registerCleanupFunction(async () => trrServer.stop());
await trrServer.start();
dump(`port = ${trrServer.port}\n`);
let chan = makeChan(`https://localhost:${trrServer.port}/test?bla=some`);
let [req, resp] = await channelOpenPromise(chan);
equal(resp, "<h1> 404 Path not found: /test?bla=some</h1>");
dns.clearCache(true);
Services.prefs.setIntPref("network.trr.mode", 2);
Services.prefs.setCharPref(
"network.trr.uri",
`https://foo.example.com:${trrServer.port}/dns-query`
);
});
add_task(async function test_extended_error_bogus() {
await trrServer.registerDoHAnswers("something.foo", "A", [
{
name: "something.foo",
ttl: 55,
type: "A",
flush: false,
data: "1.2.3.4",
},
]);
await new TRRDNSListener("something.foo", "1.2.3.4");
await trrServer.registerDoHAnswers(
"a.foo",
"A",
[],
[
{
name: ".",
type: "OPT",
class: "IN",
options: [
{
code: "EDNS_ERROR",
extended_error: 6, // DNSSEC_BOGUS
text: "DNSSec bogus",
},
],
},
]
);
// Check that we don't fall back to DNS
let [, , inStatus] = await new TRRDNSListener("a.foo", undefined, false);
Assert.ok(
!Components.isSuccessCode(inStatus),
`${inStatus} should be an error code`
);
});
add_task(async function test_extended_error_filtered() {
await trrServer.registerDoHAnswers(
"b.foo",
"A",
[],
[
{
name: ".",
type: "OPT",
class: "IN",
options: [
{
code: "EDNS_ERROR",
extended_error: 17, // Filtered
text: "Filtered",
},
],
},
]
);
// Check that we don't fall back to DNS
let [, , inStatus] = await new TRRDNSListener("b.foo", undefined, false);
Assert.ok(
!Components.isSuccessCode(inStatus),
`${inStatus} should be an error code`
);
});
add_task(async function test_extended_error_not_ready() {
await trrServer.registerDoHAnswers(
"c.foo",
"A",
[],
[
{
name: ".",
type: "OPT",
class: "IN",
options: [
{
code: "EDNS_ERROR",
extended_error: 14, // Not ready
text: "Not ready",
},
],
},
]
);
// For this code it's OK to fallback
await new TRRDNSListener("c.foo", "127.0.0.1");
});
add_task(async function ipv6_answer_and_delayed_ipv4_error() {
// AAAA comes back immediately.
// A EDNS_ERROR comes back later, with a delay
await trrServer.registerDoHAnswers("delay1.com", "AAAA", [
{
name: "delay1.com",
ttl: 55,
type: "AAAA",
flush: false,
data: "::a:b:c:d",
},
]);
await trrServer.registerDoHAnswers(
"delay1.com",
"A",
[],
[
{
name: ".",
type: "OPT",
class: "IN",
options: [
{
code: "EDNS_ERROR",
extended_error: 17, // Filtered
text: "Filtered",
},
],
},
],
200 // delay
);
// Check that we don't fall back to DNS
await new TRRDNSListener("delay1.com", "::a:b:c:d");
});
add_task(async function ipv4_error_and_delayed_ipv6_answer() {
// AAAA comes back immediately delay
// A EDNS_ERROR comes back immediately
await trrServer.registerDoHAnswers(
"delay2.com",
"AAAA",
[
{
name: "delay2.com",
ttl: 55,
type: "AAAA",
flush: false,
data: "::a:b:c:d",
},
],
[],
200 // delay
);
await trrServer.registerDoHAnswers(
"delay2.com",
"A",
[],
[
{
name: ".",
type: "OPT",
class: "IN",
options: [
{
code: "EDNS_ERROR",
extended_error: 17, // Filtered
text: "Filtered",
},
],
},
]
);
// Check that we don't fall back to DNS
await new TRRDNSListener("delay2.com", "::a:b:c:d");
});
add_task(async function ipv4_answer_and_delayed_ipv6_error() {
// A comes back immediately.
// AAAA EDNS_ERROR comes back later, with a delay
await trrServer.registerDoHAnswers("delay3.com", "A", [
{
name: "delay3.com",
ttl: 55,
type: "A",
flush: false,
data: "1.2.3.4",
},
]);
await trrServer.registerDoHAnswers(
"delay3.com",
"AAAA",
[],
[
{
name: ".",
type: "OPT",
class: "IN",
options: [
{
code: "EDNS_ERROR",
extended_error: 17, // Filtered
text: "Filtered",
},
],
},
],
200 // delay
);
// Check that we don't fall back to DNS
await new TRRDNSListener("delay3.com", "1.2.3.4");
});
add_task(async function delayed_ipv4_answer_and_ipv6_error() {
// A comes back with delay.
// AAAA EDNS_ERROR comes immediately
await trrServer.registerDoHAnswers(
"delay4.com",
"A",
[
{
name: "delay4.com",
ttl: 55,
type: "A",
flush: false,
data: "1.2.3.4",
},
],
[],
200 // delay
);
await trrServer.registerDoHAnswers(
"delay4.com",
"AAAA",
[],
[
{
name: ".",
type: "OPT",
class: "IN",
options: [
{
code: "EDNS_ERROR",
extended_error: 17, // Filtered
text: "Filtered",
},
],
},
]
);
// Check that we don't fall back to DNS
await new TRRDNSListener("delay4.com", "1.2.3.4");
});

View File

@ -451,9 +451,5 @@ skip-if = asan || tsan || os == 'win' || os =='android'
skip-if = asan || tsan || os == 'win' || os =='android'
[test_use_httpssvc.js]
skip-if = os == "android"
[test_trr_additional_section.js]
skip-if = os == "android"
[test_trr_extended_error.js]
skip-if = os == "android"
[test_httpssvc_iphint.js]
skip-if = os == "android"

View File

@ -729,15 +729,6 @@ roption.encode = function (option, buf, offset) {
offset += 2
}
break
case 15: // EDNS_ERROR
const text = option.text || "";
buf.writeUInt16BE(text.length + 2, offset)
offset += 2;
buf.writeUInt16BE(option.extended_error, offset)
offset += 2;
buf.write(text, offset);
offset += option.text.length;
break;
default:
throw new Error(`Unknown roption code: ${option.code}`)
}
@ -806,8 +797,6 @@ roption.encodingLength = function (option) {
return option.length + 4
case 14: // KEY-TAG
return 4 + (option.tags.length * 2)
case 15: // EDNS_ERROR
return 4 + 2 + option.text.length
}
throw new Error(`Unknown roption code: ${option.code}`)
}

View File

@ -17,7 +17,6 @@ exports.toString = function (type) {
case 12: return 'PADDING'
case 13: return 'CHAIN'
case 14: return 'KEY_TAG'
case 15: return 'EDNS_ERROR'
case 26946: return 'DEVICEID'
}
if (type < 0) {
@ -49,7 +48,6 @@ exports.toCode = function (name) {
case 'PADDING': return 12
case 'CHAIN': return 13
case 'KEY_TAG': return 14
case 'EDNS_ERROR': return 15
case 'DEVICEID': return 26946
case 'OPTION_65535': return 65535
}

View File

@ -382,10 +382,6 @@ with modules["NETWORK"]:
# speak to a proxy server, then it will generate this error if the proxy
# hostname cannot be resolved.
errors["NS_ERROR_UNKNOWN_PROXY_HOST"] = FAILURE(42)
# This DNS error will occur when the resolver uses the Extended DNS Error
# option to indicate an error code for which we should not fall back to the
# default DNS resolver. This means the DNS failure is definitive.
errors["NS_ERROR_DEFINITIVE_UNKNOWN_HOST"] = FAILURE(43)
# Socket specific error codes: