|
reSIProcate/rutil
9694
|
00001 #ifdef HAVE_CONFIG_H 00002 #include "config.h" 00003 #endif 00004 00005 // WINCE -- stl headers have to be defined before standard c headers because of 00006 // MS non-consistent declaration of time_t. we defined _USE_32BIT_TIME_T 00007 // in all projects and that solved the issue with beta compiler, however 00008 // release version messes time_t definition again 00009 #include <set> 00010 #include <vector> 00011 #include <cassert> 00012 00013 #include "AresCompat.hxx" 00014 00015 #ifndef WIN32 00016 #ifndef __CYGWIN__ 00017 #include <arpa/nameser.h> 00018 #endif 00019 #endif 00020 00021 #include "rutil/FdPoll.hxx" 00022 #include "rutil/Logger.hxx" 00023 #include "rutil/Socket.hxx" 00024 #include "rutil/compat.hxx" 00025 #include "rutil/BaseException.hxx" 00026 #include "rutil/Data.hxx" 00027 #include "rutil/Inserter.hxx" 00028 #include "rutil/dns/DnsStub.hxx" 00029 #include "rutil/dns/ExternalDns.hxx" 00030 #include "rutil/dns/ExternalDnsFactory.hxx" 00031 #include "rutil/dns/QueryTypes.hxx" 00032 #include "rutil/WinLeakCheck.hxx" 00033 00034 using namespace resip; 00035 using namespace std; 00036 00037 #define RESIPROCATE_SUBSYSTEM resip::Subsystem::DNS 00038 00039 DnsStub::DnsResourceRecordsByPtr DnsStub::Query::Empty; 00040 00041 DnsStub::NameserverList DnsStub::EmptyNameserverList; 00042 int DnsStub::mDnsTimeout = 0; 00043 int DnsStub::mDnsTries = 0; 00044 unsigned int DnsStub::mDnsFeatures = 0; 00045 00046 void 00047 DnsResultSink::onLogDnsResult(const DNSResult<DnsHostRecord>& rr) 00048 { 00049 DebugLog (<< rr); 00050 } 00051 00052 void 00053 DnsResultSink::onLogDnsResult(const DNSResult<DnsAAAARecord>& rr) 00054 { 00055 #if defined(USE_IPV6) 00056 DebugLog (<< rr); 00057 #else 00058 ErrLog(<< "Something called " 00059 "DnsResultSink::onLogDnsResult(const DNSResult<DnsAAAARecord>& rr)" 00060 " when ipv6 support was disabled."); 00061 #endif 00062 } 00063 00064 void 00065 DnsResultSink::onLogDnsResult(const DNSResult<DnsSrvRecord>& rr) 00066 { 00067 DebugLog (<< rr); 00068 } 00069 00070 void 00071 DnsResultSink::onLogDnsResult(const DNSResult<DnsNaptrRecord>& rr) 00072 { 00073 DebugLog (<< rr); 00074 } 00075 00076 void 00077 DnsResultSink::onLogDnsResult(const DNSResult<DnsCnameRecord>& rr) 00078 { 00079 DebugLog (<< rr); 00080 } 00081 00082 DnsStub::DnsStub(const NameserverList& additional, 00083 AfterSocketCreationFuncPtr socketFunc, 00084 AsyncProcessHandler* asyncProcessHandler, 00085 FdPollGrp *pollGrp) : 00086 mInterruptorHandle(0), 00087 mCommandFifo(&mSelectInterruptor), 00088 mTransform(0), 00089 mDnsProvider(ExternalDnsFactory::createExternalDns()), 00090 mPollGrp(0), 00091 mAsyncProcessHandler(asyncProcessHandler) 00092 { 00093 setPollGrp(pollGrp); 00094 00095 int retCode = mDnsProvider->init(additional, socketFunc, mDnsTimeout, mDnsTries, mDnsFeatures); 00096 if (retCode != ExternalDns::Success) 00097 { 00098 if (retCode == ExternalDns::BuildMismatch) 00099 { 00100 assert(0); 00101 throw DnsStubException("Library was not build w/ required capabilities(probably USE_IPV6 resip/ares mismatch", 00102 __FILE__,__LINE__); 00103 } 00104 00105 Data err(Data::Take, mDnsProvider->errorMessage(retCode)); 00106 ErrLog (<< "Failed to initialize async dns library: " << err); 00107 00108 throw DnsStubException("Failed to initialize async dns library " + err, __FILE__,__LINE__); 00109 } 00110 } 00111 00112 DnsStub::~DnsStub() 00113 { 00114 for (set<Query*>::iterator it = mQueries.begin(); it != mQueries.end(); ++it) 00115 { 00116 delete *it; 00117 } 00118 00119 setPollGrp(0); 00120 delete mDnsProvider; 00121 } 00122 00123 unsigned int 00124 DnsStub::getTimeTillNextProcessMS() 00125 { 00126 if(mCommandFifo.size() > 0) return 0; 00127 return mDnsProvider->getTimeTillNextProcessMS(); 00128 } 00129 00130 void 00131 DnsStub::buildFdSet(FdSet& fdset) 00132 { 00133 mDnsProvider->buildFdSet(fdset.read, fdset.write, fdset.size); 00134 mSelectInterruptor.buildFdSet(fdset); 00135 } 00136 00137 void 00138 DnsStub::processFifo() 00139 { 00140 while (mCommandFifo.messageAvailable()) 00141 { 00142 Command* command = mCommandFifo.getNext(); 00143 command->execute(); 00144 delete command; 00145 } 00146 } 00147 00148 void 00149 DnsStub::process(FdSet& fdset) 00150 { 00151 mSelectInterruptor.process(fdset); 00152 processFifo(); 00153 mDnsProvider->process(fdset.read, fdset.write); 00154 } 00155 00156 void 00157 DnsStub::processTimers() 00158 { 00159 // the fifo is captures as a timer within getTimeTill... above 00160 processFifo(); 00161 mDnsProvider->processTimers(); 00162 } 00163 00164 void 00165 DnsStub::cache(const Data& key, 00166 in_addr addr) 00167 { 00168 DnsHostRecord record(key, addr); 00169 mRRCache.updateCacheFromHostFile(record); 00170 } 00171 00172 void 00173 DnsStub::cache(const Data& key, 00174 const unsigned char* abuf, 00175 int alen) 00176 { 00177 00178 vector<RROverlay> overlays; 00179 00180 // skip header 00181 const unsigned char* aptr = abuf + HFIXEDSZ; 00182 00183 int qdcount = DNS_HEADER_QDCOUNT(abuf); // questions. 00184 for (int i = 0; i < qdcount && aptr; ++i) 00185 { 00186 aptr = skipDNSQuestion(aptr, abuf, alen); 00187 } 00188 00189 // answers. 00190 int ancount = DNS_HEADER_ANCOUNT(abuf); 00191 for (int i = 0; i < ancount; i++) 00192 { 00193 aptr = createOverlay(abuf, alen, aptr, overlays); 00194 } 00195 00196 // name server records. 00197 int nscount = DNS_HEADER_NSCOUNT(abuf); 00198 for (int i = 0; i < nscount; i++) 00199 { 00200 aptr = createOverlay(abuf, alen, aptr, overlays, true); 00201 } 00202 00203 // additional records. 00204 int arcount = DNS_HEADER_ARCOUNT(abuf); 00205 for (int i = 0; i < arcount; i++) 00206 { 00207 aptr = createOverlay(abuf, alen, aptr, overlays); 00208 } 00209 00210 // sort overlays by type. 00211 sort(overlays.begin(), overlays.end()); 00212 00213 vector<RROverlay>::iterator itLow = lower_bound(overlays.begin(), overlays.end(), *overlays.begin()); 00214 vector<RROverlay>::iterator itHigh = upper_bound(overlays.begin(), overlays.end(), *overlays.begin()); 00215 while (itLow != overlays.end()) 00216 { 00217 mRRCache.updateCache(key, (*itLow).type(), itLow, itHigh); 00218 itLow = itHigh; 00219 if (itHigh != overlays.end()) 00220 { 00221 itHigh = upper_bound(itLow, overlays.end(), *itLow); 00222 } 00223 } 00224 } 00225 00226 void 00227 DnsStub::cacheTTL(const Data& key, 00228 int rrType, 00229 int status, 00230 const unsigned char* abuf, 00231 int alen) 00232 { 00233 // skip header 00234 const unsigned char* aptr = abuf + HFIXEDSZ; 00235 00236 int qdcount = DNS_HEADER_QDCOUNT(abuf); // questions. 00237 for (int i = 0; i < qdcount && aptr; ++i) 00238 { 00239 aptr = skipDNSQuestion(aptr, abuf, alen); 00240 } 00241 00242 vector<RROverlay> overlays; 00243 00244 // answers. 00245 int ancount = DNS_HEADER_ANCOUNT(abuf); 00246 if (ancount != 0) return; 00247 00248 // name server records. 00249 int nscount = DNS_HEADER_NSCOUNT(abuf); 00250 if (nscount == 0) return; 00251 vector<RROverlay> soa; 00252 aptr = createOverlay(abuf, alen, aptr, soa); 00253 if(soa.empty()) 00254 { 00255 return; 00256 } 00257 00258 mRRCache.cacheTTL(key, rrType, status, soa[0]); 00259 } 00260 00261 const unsigned char* 00262 DnsStub::skipDNSQuestion(const unsigned char *aptr, 00263 const unsigned char *abuf, 00264 int alen) 00265 { 00266 char *name=0; 00267 int status=0; 00268 long len = 0; 00269 00270 // Parse the question name. 00271 status = ares_expand_name(aptr, abuf, alen, &name, &len); 00272 if (status != ARES_SUCCESS) 00273 { 00274 throw DnsStubException("Failed DNS preparse", __FILE__, __LINE__); 00275 } 00276 aptr += len; 00277 00278 // Make sure there's enough data after the name for the fixed part 00279 // of the question. 00280 if (aptr + QFIXEDSZ > abuf + alen) 00281 { 00282 free(name); 00283 throw DnsStubException("Failed DNS preparse", __FILE__, __LINE__); 00284 } 00285 00286 aptr += QFIXEDSZ; 00287 free(name); 00288 return aptr; 00289 } 00290 00291 bool 00292 DnsStub::checkDnsChange() 00293 { 00294 return mDnsProvider ? mDnsProvider->checkDnsChange() : false; 00295 } 00296 00297 bool 00298 DnsStub::supportedType(int type) 00299 { 00300 if(mDnsProvider && mDnsProvider->hostFileLookupLookupOnlyMode()) 00301 { 00302 return (T_A == type); 00303 } 00304 #ifdef USE_IPV6 00305 return (T_A == type || 00306 T_AAAA == type || 00307 T_NAPTR == type || 00308 T_SRV == type || 00309 T_CNAME == type || 00310 T_SOA == type); 00311 #else 00312 return (T_A == type || 00313 T_NAPTR == type || 00314 T_SRV == type || 00315 T_CNAME == type || 00316 T_SOA == type); 00317 #endif 00318 } 00319 00320 const unsigned char* 00321 DnsStub::createOverlay(const unsigned char* abuf, 00322 const int alen, 00323 const unsigned char* aptr, 00324 vector<RROverlay>& overlays, 00325 bool discard) 00326 { 00327 const unsigned char* rptr = aptr; 00328 char* name = 0; 00329 long len = 0; 00330 00331 int status = ares_expand_name(aptr, abuf, alen, &name, &len); 00332 if (ARES_SUCCESS != status) 00333 { 00334 throw DnsStubException("Failed overlay creation", __FILE__, __LINE__); 00335 } 00336 free(name); 00337 aptr += len; 00338 int type = DNS_RR_TYPE(aptr); 00339 int dlen = DNS_RR_LEN(aptr); 00340 if (!supportedType(type)) 00341 { 00342 aptr += RRFIXEDSZ; 00343 aptr += dlen; 00344 return aptr; 00345 } 00346 // rewind before handing it off to overlay. 00347 aptr -= len; 00348 if (!discard) 00349 { 00350 RROverlay overlay(aptr, abuf, alen); 00351 overlays.push_back(overlay); 00352 } 00353 return rptr + len + RRFIXEDSZ + dlen; 00354 } 00355 00356 void 00357 DnsStub::removeQuery(Query* query) 00358 { 00359 set<Query*>::iterator it = mQueries.find(query); 00360 if (it != mQueries.end()) 00361 { 00362 mQueries.erase(it); 00363 } 00364 } 00365 00366 void 00367 DnsStub::setResultTransform(ResultTransform* transform) 00368 { 00369 mTransform = transform; 00370 } 00371 00372 void 00373 DnsStub::removeResultTransform() 00374 { 00375 mTransform = 0; 00376 } 00377 00378 void 00379 DnsStub::setPollGrp(FdPollGrp* pollGrp) 00380 { 00381 if(mPollGrp) 00382 { 00383 // unregister our select interruptor 00384 mPollGrp->delPollItem(mInterruptorHandle); 00385 mInterruptorHandle=0; 00386 } 00387 00388 mPollGrp=pollGrp; 00389 00390 if (mPollGrp) 00391 { 00392 mInterruptorHandle = mPollGrp->addPollItem(mSelectInterruptor.getReadSocket(), FPEM_Read, &mSelectInterruptor); 00393 } 00394 00395 mDnsProvider->setPollGrp(mPollGrp); 00396 } 00397 00398 DnsStub::Query::Query(DnsStub& stub, ResultTransform* transform, ResultConverter* resultConv, 00399 const Data& target, int rrType, 00400 bool followCname, int proto, DnsResultSink* s) 00401 : mRRType(rrType), 00402 mStub(stub), 00403 mTransform(transform), 00404 mResultConverter(resultConv), 00405 mTarget(target), 00406 mProto(proto), 00407 mReQuery(0), 00408 mSink(s), 00409 mFollowCname(followCname) 00410 { 00411 assert(s); 00412 } 00413 00414 DnsStub::Query::~Query() 00415 { 00416 delete mResultConverter; //.dcm. flyweight? 00417 } 00418 00419 static Data 00420 typeToData(int rr) 00421 { 00422 // !dcm! fix this 00423 if (rr == RR_A::getRRType()) 00424 { 00425 return RR_A::getRRTypeName(); 00426 } 00427 #if defined(USE_IPV6) 00428 else if(rr == RR_AAAA::getRRType()) 00429 { 00430 return RR_AAAA::getRRTypeName(); 00431 } 00432 #endif 00433 else if (rr ==RR_NAPTR::getRRType()) 00434 { 00435 return RR_NAPTR::getRRTypeName(); 00436 } 00437 else if(rr == RR_SRV::getRRType()) 00438 { 00439 return RR_SRV::getRRTypeName(); 00440 } 00441 else if (RR_CNAME::getRRType()) 00442 { 00443 return RR_CNAME::getRRTypeName(); 00444 } 00445 else 00446 { 00447 return "Unknown"; 00448 } 00449 } 00450 00451 void 00452 DnsStub::Query::go() 00453 { 00454 StackLog(<< "DNS query of:" << mTarget << " " << typeToData(mRRType)); 00455 00456 DnsResourceRecordsByPtr records; 00457 int status = 0; 00458 bool cached = false; 00459 Data targetToQuery = mTarget; 00460 cached = mStub.mRRCache.lookup(mTarget, mRRType, mProto, records, status); 00461 00462 if (!cached) 00463 { 00464 if (mRRType != T_CNAME) 00465 { 00466 do 00467 { 00468 DnsResourceRecordsByPtr cnames; 00469 cached = mStub.mRRCache.lookup(targetToQuery, T_CNAME, mProto, cnames, status); 00470 if (cached) 00471 { 00472 targetToQuery = (dynamic_cast<DnsCnameRecord*>(cnames[0]))->cname(); 00473 } 00474 } while(cached); 00475 } 00476 } 00477 00478 if (targetToQuery != mTarget) 00479 { 00480 StackLog(<< mTarget << " mapped to CNAME " << targetToQuery); 00481 cached = mStub.mRRCache.lookup(targetToQuery, mRRType, mProto, records, status); 00482 } 00483 00484 if (!cached) 00485 { 00486 if(mStub.mDnsProvider && mStub.mDnsProvider->hostFileLookupLookupOnlyMode()) 00487 { 00488 assert(mRRType == T_A); 00489 StackLog (<< targetToQuery << " not cached. Doing hostfile lookup"); 00490 in_addr address; 00491 if (mStub.mDnsProvider->hostFileLookup(targetToQuery.c_str(), address)) 00492 { 00493 mStub.cache(mTarget, address); 00494 DnsResourceRecordsByPtr result; 00495 int queryStatus = 0; 00496 00497 mStub.mRRCache.lookup(mTarget, mRRType, mProto, result, queryStatus); 00498 if (mTransform) 00499 { 00500 mTransform->transform(mTarget, mRRType, result); 00501 } 00502 mResultConverter->notifyUser(mTarget, queryStatus, mStub.errorMessage(queryStatus), result, mSink); 00503 } 00504 else 00505 { 00506 // Not in hosts file - return error - or.. we could fallback to doing the lookupRecords call on the local named 00507 mResultConverter->notifyUser(mTarget, ARES_ENOTFOUND, mStub.errorMessage(ARES_ENOTFOUND), Empty, mSink); 00508 } 00509 mReQuery = 0; 00510 mStub.removeQuery(this); 00511 delete this; 00512 return; 00513 } 00514 else 00515 { 00516 StackLog (<< targetToQuery << " not cached. Doing external dns lookup"); 00517 mStub.lookupRecords(targetToQuery, mRRType, this); 00518 } 00519 } 00520 else // is cached 00521 { 00522 if (mTransform && !records.empty()) 00523 { 00524 mTransform->transform(mTarget, mRRType, records); 00525 } 00526 mResultConverter->notifyUser(mTarget, status, mStub.errorMessage(status), records, mSink); 00527 00528 mStub.removeQuery(this); 00529 delete this; 00530 } 00531 } 00532 00533 void 00534 DnsStub::Query::process(int status, const unsigned char* abuf, const int alen) 00535 { 00536 if (status != 0) 00537 { 00538 switch (status) 00539 { 00540 case ARES_ENODATA: 00541 case ARES_EFORMERR: 00542 case ARES_ESERVFAIL: 00543 case ARES_ENOTFOUND: 00544 case ARES_ENOTIMP: 00545 case ARES_EREFUSED: 00546 if(mRRType == T_A) 00547 { 00548 in_addr address; 00549 if (mStub.mDnsProvider->hostFileLookup(mTarget.c_str(), address)) 00550 { 00551 mStub.cache(mTarget, address); 00552 mReQuery = 0; 00553 DnsResourceRecordsByPtr result; 00554 int queryStatus = 0; 00555 00556 mStub.mRRCache.lookup(mTarget, mRRType, mProto, result, queryStatus); 00557 if (mTransform) 00558 { 00559 mTransform->transform(mTarget, mRRType, result); 00560 } 00561 mResultConverter->notifyUser(mTarget, queryStatus, mStub.errorMessage(queryStatus), result, mSink); 00562 mStub.removeQuery(this); 00563 delete this; 00564 return; 00565 } 00566 } 00567 try 00568 { 00569 mStub.cacheTTL(mTarget, mRRType, status, abuf, alen); 00570 } 00571 catch (BaseException& e) 00572 { 00573 // if the response isn't parsable, we might want to consider caching 00574 // TTL anyways to delay the query attempt for this record. 00575 ErrLog(<< "Couldn't parse failure response to lookup for " << mTarget); 00576 InfoLog(<< e.getMessage()); 00577 } 00578 break; 00579 00580 case ARES_ECONNREFUSED: 00581 case ARES_ETIMEOUT: 00582 ErrLog (<< "Connection error " << mStub.errorMessage(status) << " for " << mTarget); 00583 break; 00584 case ARES_EBADRESP: 00585 ErrLog (<< "Server response error " << mStub.errorMessage(status) << " for " << mTarget); 00586 break; 00587 case ARES_EOF: 00588 case ARES_EFILE: 00589 case ARES_ENOMEM: 00590 case ARES_EDESTRUCTION: 00591 ErrLog (<< "Error " << mStub.errorMessage(status) << " for " << mTarget); 00592 break; 00593 case ARES_EBADNAME: 00594 ErrLog(<< "Garbage hostname failed to resolve: " << mStub.errorMessage(status) << " for " << mTarget); 00595 break; 00596 case ARES_EBADQUERY: 00597 ErrLog(<< "Query was malformed (probably because hostname was " 00598 "too long) " << mStub.errorMessage(status) << " for " 00599 << mTarget); 00600 break; 00601 case ARES_EBADFAMILY: 00602 ErrLog (<< "Bad lookup type " << mStub.errorMessage(status) << " for " << mTarget); 00603 // .bwc. This should not happen. If it does, we have code to fix. 00604 assert(0); 00605 break; 00606 default: 00607 ErrLog (<< "Unknown error " << mStub.errorMessage(status) << " for " << mTarget); 00608 assert(0); 00609 break; 00610 } 00611 00612 // For other error status values, we may also want to cacheTTL to delay 00613 // requeries. Especially if the server refuses. 00614 mResultConverter->notifyUser(mTarget, status, mStub.errorMessage(status), Empty, mSink); 00615 mReQuery = 0; 00616 mStub.removeQuery(this); 00617 delete this; 00618 return; 00619 } 00620 00621 bool bDeleteThis = true; 00622 00623 // skip header 00624 const unsigned char* aptr = abuf + HFIXEDSZ; 00625 00626 int qdcount = DNS_HEADER_QDCOUNT(abuf); // questions. 00627 for (int i = 0; i < qdcount && aptr; ++i) 00628 { 00629 try 00630 { 00631 aptr = mStub.skipDNSQuestion(aptr, abuf, alen); 00632 } 00633 catch (BaseException& e) 00634 { 00635 ErrLog(<< "Error parsing DNS record for " << mTarget << ": " << e.getMessage()); 00636 mResultConverter->notifyUser(mTarget, ARES_EFORMERR, e.getMessage(), Empty, mSink); 00637 mStub.removeQuery(this); 00638 delete this; 00639 return; 00640 } 00641 } 00642 00643 int ancount = DNS_HEADER_ANCOUNT(abuf); 00644 if (ancount == 0) 00645 { 00646 mResultConverter->notifyUser(mTarget, 0, mStub.errorMessage(0), Empty, mSink); 00647 } 00648 else 00649 { 00650 bool bGotAnswers = true; 00651 Data targetToQuery; 00652 followCname(aptr, abuf, alen, bGotAnswers, bDeleteThis, targetToQuery); 00653 00654 if (bGotAnswers) 00655 { 00656 mReQuery = 0; 00657 DnsResourceRecordsByPtr result; 00658 int queryStatus = 0; 00659 00660 if (mTarget != targetToQuery) DebugLog (<< mTarget << " mapped to " << targetToQuery << " and returned result"); 00661 mStub.mRRCache.lookup(targetToQuery, mRRType, mProto, result, queryStatus); 00662 if (mTransform) 00663 { 00664 mTransform->transform(mTarget, mRRType, result); 00665 } 00666 mResultConverter->notifyUser(mTarget, queryStatus, mStub.errorMessage(queryStatus), result, mSink); 00667 } 00668 } 00669 00670 if (bDeleteThis) 00671 { 00672 mStub.removeQuery(this); 00673 delete this; 00674 } 00675 } 00676 00677 void 00678 DnsStub::Query::onDnsRaw(int status, const unsigned char* abuf, int alen) 00679 { 00680 process(status, abuf, alen); 00681 } 00682 00683 void 00684 DnsStub::Query::followCname(const unsigned char* aptr, const unsigned char*abuf, const int alen, bool& bGotAnswers, bool& bDeleteThis, Data& targetToQuery) 00685 { 00686 bGotAnswers = true; 00687 bDeleteThis = true; 00688 00689 char* name = 0; 00690 long len = 0; 00691 00692 if (ARES_SUCCESS != ares_expand_name(aptr, abuf, alen, &name, &len)) 00693 { 00694 ErrLog(<< "Failed DNS preparse for " << targetToQuery); 00695 mResultConverter->notifyUser(mTarget, ARES_EFORMERR, "Failed DNS preparse", Empty, mSink); 00696 bGotAnswers = false; 00697 return; 00698 } 00699 00700 targetToQuery = name; 00701 aptr += len; 00702 00703 try 00704 { 00705 mStub.cache(name, abuf, alen); 00706 } 00707 catch (BaseException& e) 00708 { 00709 ErrLog(<< "Failed to cache result for " << targetToQuery << ": " << e.getMessage()); 00710 mResultConverter->notifyUser(mTarget, ARES_EFORMERR, e.getMessage(), Empty, mSink); 00711 bGotAnswers = false; 00712 return; 00713 } 00714 00715 if (mRRType != T_CNAME) 00716 { 00717 if (DNS_RR_TYPE(aptr) == T_CNAME) 00718 { 00719 if (mFollowCname && mReQuery < MAX_REQUERIES) 00720 { 00721 ++mReQuery; 00722 int status = 0; 00723 bool cached = false; 00724 00725 do 00726 { 00727 DnsResourceRecordsByPtr cnames; 00728 cached = mStub.mRRCache.lookup(targetToQuery, T_CNAME, mProto, cnames, status); 00729 if (cached) 00730 { 00731 ++mReQuery; 00732 targetToQuery = (dynamic_cast<DnsCnameRecord*>(cnames[0]))->cname(); 00733 } 00734 } while(mReQuery < MAX_REQUERIES && cached); 00735 00736 DnsResourceRecordsByPtr result; 00737 if (!mStub.mRRCache.lookup(targetToQuery, mRRType, mProto, result, status)) 00738 { 00739 mStub.lookupRecords(targetToQuery, mRRType, this); 00740 bDeleteThis = false; 00741 bGotAnswers = false; 00742 } 00743 } 00744 else 00745 { 00746 mReQuery = 0; 00747 mResultConverter->notifyUser(mTarget, 1, mStub.errorMessage(1), Empty, mSink); 00748 bGotAnswers = false; 00749 } 00750 } 00751 } 00752 00753 free(name); 00754 } 00755 00756 Data 00757 DnsStub::errorMessage(int status) 00758 { 00759 return Data(Data::Take, mDnsProvider->errorMessage(status)); 00760 } 00761 00762 void 00763 DnsStub::lookupRecords(const Data& target, unsigned short type, DnsRawSink* sink) 00764 { 00765 mDnsProvider->lookup(target.c_str(), type, this, sink); 00766 } 00767 00768 void 00769 DnsStub::handleDnsRaw(ExternalDnsRawResult res) 00770 { 00771 reinterpret_cast<DnsRawSink*>(res.userData)->onDnsRaw(res.errorCode(), res.abuf, res.alen); 00772 mDnsProvider->freeResult(res); 00773 } 00774 00775 void 00776 DnsStub::setEnumSuffixes(const std::vector<Data>& suffixes) 00777 { 00778 SetEnumSuffixesCommand* command = new SetEnumSuffixesCommand(*this, suffixes); 00779 mCommandFifo.add(command); 00780 00781 if (mAsyncProcessHandler) 00782 { 00783 mAsyncProcessHandler->handleProcessNotification(); 00784 } 00785 } 00786 00787 const std::vector<Data>& 00788 DnsStub::getEnumSuffixes() const 00789 { 00790 return mEnumSuffixes; 00791 } 00792 00793 void 00794 DnsStub::doSetEnumSuffixes(const std::vector<Data>& suffixes) 00795 { 00796 mEnumSuffixes = suffixes; 00797 } 00798 00799 void 00800 DnsStub::clearDnsCache() 00801 { 00802 ClearDnsCacheCommand* command = new ClearDnsCacheCommand(*this); 00803 mCommandFifo.add(command); 00804 00805 if (mAsyncProcessHandler) 00806 { 00807 mAsyncProcessHandler->handleProcessNotification(); 00808 } 00809 } 00810 00811 void 00812 DnsStub::doClearDnsCache() 00813 { 00814 mRRCache.clearCache(); 00815 } 00816 00817 void 00818 DnsStub::logDnsCache() 00819 { 00820 LogDnsCacheCommand* command = new LogDnsCacheCommand(*this); 00821 mCommandFifo.add(command); 00822 00823 if (mAsyncProcessHandler) 00824 { 00825 mAsyncProcessHandler->handleProcessNotification(); 00826 } 00827 } 00828 00829 void 00830 DnsStub::doLogDnsCache() 00831 { 00832 mRRCache.logCache(); 00833 } 00834 00835 void 00836 DnsStub::getDnsCacheDump(std::pair<unsigned long, unsigned long> key, GetDnsCacheDumpHandler* handler) 00837 { 00838 GetDnsCacheDumpCommand* command = new GetDnsCacheDumpCommand(*this, key, handler); 00839 mCommandFifo.add(command); 00840 00841 if (mAsyncProcessHandler) 00842 { 00843 mAsyncProcessHandler->handleProcessNotification(); 00844 } 00845 } 00846 00847 void 00848 DnsStub::doGetDnsCacheDump(std::pair<unsigned long, unsigned long> key, GetDnsCacheDumpHandler* handler) 00849 { 00850 assert(handler != 0); 00851 Data dnsCacheDump; 00852 mRRCache.getCacheDump(dnsCacheDump); 00853 handler->onDnsCacheDumpRetrieved(key, dnsCacheDump); 00854 } 00855 00856 void 00857 DnsStub::setDnsCacheTTL(int ttl) 00858 { 00859 mRRCache.setTTL(ttl); 00860 } 00861 00862 void 00863 DnsStub::setDnsCacheSize(int size) 00864 { 00865 mRRCache.setSize(size); 00866 } 00867 00868 /* ==================================================================== 00869 * The Vovida Software License, Version 1.0 00870 * 00871 * Copyright (c) 2000-2005 Vovida Networks, Inc. All rights reserved. 00872 * 00873 * Redistribution and use in source and binary forms, with or without 00874 * modification, are permitted provided that the following conditions 00875 * are met: 00876 * 00877 * 1. Redistributions of source code must retain the above copyright 00878 * notice, this list of conditions and the following disclaimer. 00879 * 00880 * 2. Redistributions in binary form must reproduce the above copyright 00881 * notice, this list of conditions and the following disclaimer in 00882 * the documentation and/or other materials provided with the 00883 * distribution. 00884 * 00885 * 3. The names "VOCAL", "Vovida Open Communication Application Library", 00886 * and "Vovida Open Communication Application Library (VOCAL)" must 00887 * not be used to endorse or promote products derived from this 00888 * software without prior written permission. For written 00889 * permission, please contact vocal@vovida.org. 00890 * 00891 * 4. Products derived from this software may not be called "VOCAL", nor 00892 * may "VOCAL" appear in their name, without prior written 00893 * permission of Vovida Networks, Inc. 00894 * 00895 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED 00896 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00897 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND 00898 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA 00899 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES 00900 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, 00901 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00902 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00903 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 00904 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00905 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 00906 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 00907 * DAMAGE. 00908 * 00909 * ==================================================================== 00910 * 00911 * This software consists of voluntary contributions made by Vovida 00912 * Networks, Inc. and many individuals on behalf of Vovida Networks, 00913 * Inc. For more information on Vovida Networks, Inc., please see 00914 * <http://www.vovida.org/>. 00915 * 00916 */ 00917
1.7.5.1