📄 dnsstub.cxx
字号:
return RR_AAAA::getRRTypeName(); }#endif else if (rr ==RR_NAPTR::getRRType()) { return RR_NAPTR::getRRTypeName(); } else if(rr == RR_SRV::getRRType()) { return RR_SRV::getRRTypeName(); } else if (RR_CNAME::getRRType()) { return RR_CNAME::getRRTypeName(); } else { return "Unknown"; }}void DnsStub::Query::go(){ StackLog(<< "DNS query of:" << mTarget << " " << typeToData(mRRType)); DnsResourceRecordsByPtr records; int status = 0; bool cached = false; Data targetToQuery = mTarget; cached = RRCache::instance()->lookup(mTarget, mRRType, mProto, records, status); if (!cached) { if (mRRType != T_CNAME) { do { DnsResourceRecordsByPtr cnames; cached = RRCache::instance()->lookup(targetToQuery, T_CNAME, mProto, cnames, status); if (cached) { targetToQuery = (dynamic_cast<DnsCnameRecord*>(cnames[0]))->cname(); } } while(cached); } } if (targetToQuery != mTarget) { StackLog(<< mTarget << " mapped to CNAME " << targetToQuery); cached = RRCache::instance()->lookup(targetToQuery, mRRType, mProto, records, status); } if (!cached) { StackLog (<< mTarget << " not cached. Doing external dns lookup"); mStub.lookupRecords(targetToQuery, mRRType, this); } else // is cached { if (mTransform && !records.empty()) { mTransform->transform(mTarget, mRRType, records); } mResultConverter->notifyUser(mTarget, status, mStub.errorMessage(status), records, mSink); mStub.removeQuery(this); delete this; }}void DnsStub::Query::process(int status, const unsigned char* abuf, const int alen){ if (status != 0) { switch (status) { case ARES_ENODATA: case ARES_EFORMERR: case ARES_ESERVFAIL: case ARES_ENOTFOUND: case ARES_ENOTIMP: case ARES_EREFUSED: if(mRRType == T_A) { in_addr address; if (mStub.mDnsProvider->hostFileLookup(mTarget.c_str(), address)) { mStub.cache(mTarget, address); mReQuery = 0; DnsResourceRecordsByPtr result; int queryStatus = 0; RRCache::instance()->lookup(mTarget, mRRType, mProto, result, queryStatus); if (mTransform) { mTransform->transform(mTarget, mRRType, result); } mResultConverter->notifyUser(mTarget, queryStatus, mStub.errorMessage(queryStatus), result, mSink); mStub.removeQuery(this); delete this; return; } } try { mStub.cacheTTL(mTarget, mRRType, status, abuf, alen); } catch (BaseException& e) { // if the response isn't parsable, we might want to consider caching // TTL anyways to delay the query attempt for this record. ErrLog(<< "Couldn't parse failure response to lookup for " << mTarget); InfoLog(<< e.getMessage()); } break; case ARES_ECONNREFUSED: case ARES_ETIMEOUT: ErrLog (<< "Connection error " << mStub.errorMessage(status) << " for " << mTarget); break; case ARES_EBADRESP: ErrLog (<< "Server response error " << mStub.errorMessage(status) << " for " << mTarget); break; case ARES_EOF: case ARES_EFILE: case ARES_ENOMEM: case ARES_EDESTRUCTION: ErrLog (<< "Error " << mStub.errorMessage(status) << " for " << mTarget); break; case ARES_EBADNAME: ErrLog(<< "Garbage hostname failed to resolve: " << mStub.errorMessage(status) << " for " << mTarget); break; case ARES_EBADQUERY: ErrLog(<< "Query was malformed (probably because hostname was " "too long) " << mStub.errorMessage(status) << " for " << mTarget); break; case ARES_EBADFAMILY: ErrLog (<< "Bad lookup type " << mStub.errorMessage(status) << " for " << mTarget); // .bwc. This should not happen. If it does, we have code to fix. assert(0); break; default: ErrLog (<< "Unknown error " << mStub.errorMessage(status) << " for " << mTarget); assert(0); break; } // For other error status values, we may also want to cacheTTL to delay // requeries. Especially if the server refuses. mResultConverter->notifyUser(mTarget, status, mStub.errorMessage(status), Empty, mSink); mReQuery = 0; mStub.removeQuery(this); delete this; return; } bool bDeleteThis = true; // skip header const unsigned char* aptr = abuf + HFIXEDSZ; int qdcount = DNS_HEADER_QDCOUNT(abuf); // questions. for (int i = 0; i < qdcount && aptr; ++i) { try { aptr = mStub.skipDNSQuestion(aptr, abuf, alen); } catch (BaseException& e) { ErrLog(<< "Error parsing DNS record for " << mTarget << ": " << e.getMessage()); mResultConverter->notifyUser(mTarget, ARES_EFORMERR, e.getMessage(), Empty, mSink); mStub.removeQuery(this); delete this; return; } } int ancount = DNS_HEADER_ANCOUNT(abuf); if (ancount == 0) { mResultConverter->notifyUser(mTarget, 0, mStub.errorMessage(0), Empty, mSink); } else { bool bGotAnswers = true; Data targetToQuery; followCname(aptr, abuf, alen, bGotAnswers, bDeleteThis, targetToQuery); if (bGotAnswers) { mReQuery = 0; DnsResourceRecordsByPtr result; int queryStatus = 0; if (mTarget != targetToQuery) DebugLog (<< mTarget << " mapped to " << targetToQuery << " and returned result"); RRCache::instance()->lookup(targetToQuery, mRRType, mProto, result, queryStatus); if (mTransform) { mTransform->transform(mTarget, mRRType, result); } mResultConverter->notifyUser(mTarget, queryStatus, mStub.errorMessage(queryStatus), result, mSink); } } if (bDeleteThis) { mStub.removeQuery(this); delete this; }}void DnsStub::Query::onDnsRaw(int status, const unsigned char* abuf, int alen){ process(status, abuf, alen);}void DnsStub::Query::followCname(const unsigned char* aptr, const unsigned char*abuf, const int alen, bool& bGotAnswers, bool& bDeleteThis, Data& targetToQuery){ bGotAnswers = true; bDeleteThis = true; char* name = 0; int len = 0; if (ARES_SUCCESS != ares_expand_name(aptr, abuf, alen, &name, &len)) { ErrLog(<< "Failed DNS preparse for " << targetToQuery); mResultConverter->notifyUser(mTarget, ARES_EFORMERR, "Failed DNS preparse", Empty, mSink); bGotAnswers = false; return; } targetToQuery = name; aptr += len; try { mStub.cache(name, abuf, alen); } catch (BaseException& e) { ErrLog(<< "Failed to cache result for " << targetToQuery << ": " << e.getMessage()); mResultConverter->notifyUser(mTarget, ARES_EFORMERR, e.getMessage(), Empty, mSink); bGotAnswers = false; return; } if (mRRType != T_CNAME) { if (DNS_RR_TYPE(aptr) == T_CNAME) { if (mFollowCname && mReQuery < MAX_REQUERIES) { ++mReQuery; int status = 0; bool cached = false; do { DnsResourceRecordsByPtr cnames; cached = RRCache::instance()->lookup(targetToQuery, T_CNAME, mProto, cnames, status); if (cached) { ++mReQuery; targetToQuery = (dynamic_cast<DnsCnameRecord*>(cnames[0]))->cname(); } } while(mReQuery < MAX_REQUERIES && cached); DnsResourceRecordsByPtr result; if (!RRCache::instance()->lookup(targetToQuery, mRRType, mProto, result, status)) { mStub.lookupRecords(targetToQuery, mRRType, this); bDeleteThis = false; bGotAnswers = false; } } else { mReQuery = 0; mResultConverter->notifyUser(mTarget, 1, mStub.errorMessage(1), Empty, mSink); bGotAnswers = false; } } } free(name);}Data DnsStub::errorMessage(int status){ return Data(Data::Take, mDnsProvider->errorMessage(status));}void DnsStub::lookupRecords(const Data& target, unsigned short type, DnsRawSink* sink){ mDnsProvider->lookup(target.c_str(), type, this, sink);}void DnsStub::handleDnsRaw(ExternalDnsRawResult res){ reinterpret_cast<DnsRawSink*>(res.userData)->onDnsRaw(res.errorCode(), res.abuf, res.alen); mDnsProvider->freeResult(res);}voidDnsStub::setEnumSuffixes(const std::vector<Data>& suffixes){ SetEnumSuffixesCommand* command = new SetEnumSuffixesCommand(*this, suffixes); mCommandFifo.add(command);}const std::vector<Data>& DnsStub::getEnumSuffixes() const{ return mEnumSuffixes;}voidDnsStub::doSetEnumSuffixes(const std::vector<Data>& suffixes){ mEnumSuffixes = suffixes;}voidDnsStub::clearDnsCache(){ ClearDnsCacheCommand* command = new ClearDnsCacheCommand(*this); mCommandFifo.add(command);}voidDnsStub::doClearDnsCache(){ RRCache::instance()->clearCache();}voidDnsStub::logDnsCache(){ LogDnsCacheCommand* command = new LogDnsCacheCommand(*this); mCommandFifo.add(command);}voidDnsStub::doLogDnsCache(){ RRCache::instance()->logCache();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -