reSIProcate
SIP stack, Dialog Usage Manager and related libraries
Loading...
Searching...
No Matches
DnsStub.cxx
Go to the documentation of this file.
1#ifdef HAVE_CONFIG_H
2#include "config.h"
3#endif
4
5// WINCE -- stl headers have to be defined before standard c headers because of
6// MS non-consistent declaration of time_t. we defined _USE_32BIT_TIME_T
7// in all projects and that solved the issue with beta compiler, however
8// release version messes time_t definition again
9#include <set>
10#include <vector>
11#include "rutil/ResipAssert.h"
12
13#include "AresCompat.hxx"
14
15#ifndef WIN32
16#ifndef __CYGWIN__
17#include <arpa/nameser.h>
18#endif
19#endif
20
21#include "rutil/FdPoll.hxx"
22#include "rutil/Logger.hxx"
23#include "rutil/Socket.hxx"
24#include "rutil/compat.hxx"
26#include "rutil/Data.hxx"
27#include "rutil/Inserter.hxx"
28#include "rutil/dns/DnsStub.hxx"
33
34using namespace resip;
35using namespace std;
36
37#define RESIPROCATE_SUBSYSTEM resip::Subsystem::DNS
38
39DnsStub::DnsResourceRecordsByPtr DnsStub::Query::Empty;
40
42int DnsStub::mDnsTimeout = 0;
43int DnsStub::mDnsTries = 0;
44unsigned int DnsStub::mDnsFeatures = 0;
45
46void
48{
49 DebugLog(<< "Host(A) Result: " << rr);
50}
51
52void
54{
55#if defined(USE_IPV6)
56 DebugLog(<< "Host(AAAA) Result: " << rr);
57#else
58 ErrLog(<< "Something called "
59 "DnsResultSink::onLogDnsResult(const DNSResult<DnsAAAARecord>& rr)"
60 " when ipv6 support was disabled.");
61#endif
62}
63
64void
66{
67 DebugLog(<< "SRV Result: " << rr);
68}
69
70void
72{
73 DebugLog(<< "NAPTR Result: " << rr);
74}
75
76void
78{
79 DebugLog(<< "CNAME Result: " << rr);
80}
81
84 AsyncProcessHandler* asyncProcessHandler,
85 FdPollGrp *pollGrp) :
86 mInterruptorHandle(0),
87 mCommandFifo(&mSelectInterruptor),
88 mTransform(0),
89 mDnsProvider(ExternalDnsFactory::createExternalDns()),
90 mPollGrp(0),
91 mAsyncProcessHandler(asyncProcessHandler)
92{
93 setPollGrp(pollGrp);
94
95 int retCode = mDnsProvider->init(additional, socketFunc, mDnsTimeout, mDnsTries, mDnsFeatures);
96 if (retCode != ExternalDns::Success)
97 {
98 if (retCode == ExternalDns::BuildMismatch)
99 {
100 resip_assert(0);
101 throw DnsStubException("Library was not build w/ required capabilities(probably USE_IPV6 resip/ares mismatch",
102 __FILE__,__LINE__);
103 }
104
105 Data err(Data::Take, mDnsProvider->errorMessage(retCode));
106 ErrLog (<< "Failed to initialize async dns library: " << err);
107
108 throw DnsStubException("Failed to initialize async dns library " + err, __FILE__,__LINE__);
109 }
110}
111
113{
114 for (set<Query*>::iterator it = mQueries.begin(); it != mQueries.end(); ++it)
115 {
116 delete *it;
117 }
118
119 setPollGrp(0);
120 delete mDnsProvider;
121}
122
123unsigned int
125{
126 if(mCommandFifo.size() > 0) return 0;
127 return mDnsProvider->getTimeTillNextProcessMS();
128}
129
130void
132{
133 mDnsProvider->buildFdSet(fdset.read, fdset.write, fdset.size);
134 mSelectInterruptor.buildFdSet(fdset);
135}
136
137void
138DnsStub::processFifo()
139{
140 while (mCommandFifo.messageAvailable())
141 {
142 Command* command = mCommandFifo.getNext();
143 command->execute();
144 delete command;
145 }
146}
147
148void
150{
151 mSelectInterruptor.process(fdset);
152 processFifo();
153 mDnsProvider->process(fdset.read, fdset.write);
154}
155
156void
158{
159 // the fifo is captures as a timer within getTimeTill... above
160 processFifo();
161 mDnsProvider->processTimers();
162}
163
164void
166{
167 mCommandFifo.add(command);
168
169 // Wake up fifo reader
170 if (mAsyncProcessHandler)
171 {
172 mAsyncProcessHandler->handleProcessNotification();
173 }
174}
175
176void
178 in_addr addr)
179{
180 DnsHostRecord record(key, addr);
181 mRRCache.updateCacheFromHostFile(record);
182}
183
184void
186 const unsigned char* abuf,
187 int alen)
188{
189
190 vector<RROverlay> overlays;
191
192 // skip header
193 const unsigned char* aptr = abuf + HFIXEDSZ;
194
195 int qdcount = DNS_HEADER_QDCOUNT(abuf); // questions.
196 for (int i = 0; i < qdcount && aptr; ++i)
197 {
198 aptr = skipDNSQuestion(aptr, abuf, alen);
199 }
200
201 // answers.
202 int ancount = DNS_HEADER_ANCOUNT(abuf);
203 for (int i = 0; i < ancount; i++)
204 {
205 aptr = createOverlay(abuf, alen, aptr, overlays);
206 }
207
208 // name server records.
209 int nscount = DNS_HEADER_NSCOUNT(abuf);
210 for (int i = 0; i < nscount; i++)
211 {
212 aptr = createOverlay(abuf, alen, aptr, overlays, true);
213 }
214
215 // additional records.
216 int arcount = DNS_HEADER_ARCOUNT(abuf);
217 for (int i = 0; i < arcount; i++)
218 {
219 aptr = createOverlay(abuf, alen, aptr, overlays);
220 }
221
222 if (overlays.size() > 0)
223 {
224 // sort overlays by type.
225 sort(overlays.begin(), overlays.end());
226
227 vector<RROverlay>::iterator itLow = lower_bound(overlays.begin(), overlays.end(), *overlays.begin());
228 vector<RROverlay>::iterator itHigh = upper_bound(overlays.begin(), overlays.end(), *overlays.begin());
229 while (itLow != overlays.end())
230 {
231 mRRCache.updateCache(key, (*itLow).type(), itLow, itHigh);
232 itLow = itHigh;
233 if (itHigh != overlays.end())
234 {
235 itHigh = upper_bound(itLow, overlays.end(), *itLow);
236 }
237 }
238 }
239}
240
241void
243 int rrType,
244 int status,
245 const unsigned char* abuf,
246 int alen)
247{
248 // skip header
249 const unsigned char* aptr = abuf + HFIXEDSZ;
250
251 int qdcount = DNS_HEADER_QDCOUNT(abuf); // questions.
252 for (int i = 0; i < qdcount && aptr; ++i)
253 {
254 aptr = skipDNSQuestion(aptr, abuf, alen);
255 }
256
257 vector<RROverlay> overlays;
258
259 // answers.
260 int ancount = DNS_HEADER_ANCOUNT(abuf);
261 if (ancount != 0) return;
262
263 // name server records.
264 int nscount = DNS_HEADER_NSCOUNT(abuf);
265 if (nscount == 0) return;
266 vector<RROverlay> soa;
267 aptr = createOverlay(abuf, alen, aptr, soa);
268 if(soa.empty())
269 {
270 return;
271 }
272
273 mRRCache.cacheTTL(key, rrType, status, soa[0]);
274}
275
276const unsigned char*
277DnsStub::skipDNSQuestion(const unsigned char *aptr,
278 const unsigned char *abuf,
279 int alen)
280{
281 char *name=0;
282 int status=0;
283 long len = 0;
284
285 // Parse the question name.
286 status = ares_expand_name(aptr, abuf, alen, &name, &len);
287 if (status != ARES_SUCCESS)
288 {
289 throw DnsStubException("Failed DNS preparse", __FILE__, __LINE__);
290 }
291 aptr += len;
292
293 // Make sure there's enough data after the name for the fixed part
294 // of the question.
295 if (aptr + QFIXEDSZ > abuf + alen)
296 {
297 free(name);
298 throw DnsStubException("Failed DNS preparse", __FILE__, __LINE__);
299 }
300
301 aptr += QFIXEDSZ;
302 free(name);
303 return aptr;
304}
305
306bool
308{
309 if(mDnsProvider)
310 {
311 mDnsProvider->changeNameServers(additional);
312 return mDnsProvider->checkDnsChange();
313 }
314 return false;
315}
316
317bool
319{
320 return mDnsProvider ? mDnsProvider->checkDnsChange() : false;
321}
322
323bool
325{
326 if(mDnsProvider && mDnsProvider->hostFileLookupLookupOnlyMode())
327 {
328 return (T_A == type);
329 }
330#ifdef USE_IPV6
331 return (T_A == type ||
332 T_AAAA == type ||
333 T_NAPTR == type ||
334 T_SRV == type ||
335 T_CNAME == type ||
336 T_SOA == type);
337#else
338 return (T_A == type ||
339 T_NAPTR == type ||
340 T_SRV == type ||
341 T_CNAME == type ||
342 T_SOA == type);
343#endif
344}
345
346const unsigned char*
347DnsStub::createOverlay(const unsigned char* abuf,
348 const int alen,
349 const unsigned char* aptr,
350 vector<RROverlay>& overlays,
351 bool discard)
352{
353 const unsigned char* rptr = aptr;
354 char* name = 0;
355 long len = 0;
356
357 int status = ares_expand_name(aptr, abuf, alen, &name, &len);
358 if (ARES_SUCCESS != status)
359 {
360 throw DnsStubException("Failed overlay creation", __FILE__, __LINE__);
361 }
362 free(name);
363 aptr += len;
364 if (aptr + RRFIXEDSZ > abuf + alen)
365 {
366 throw DnsStubException("Failed overlay creation", __FILE__, __LINE__);
367 }
368 int type = DNS_RR_TYPE(aptr);
369 int dlen = DNS_RR_LEN(aptr);
370 if (!supportedType(type))
371 {
372 aptr += RRFIXEDSZ;
373 aptr += dlen;
374 return aptr;
375 }
376 // rewind before handing it off to overlay.
377 aptr -= len;
378 if (!discard)
379 {
380 RROverlay overlay(aptr, abuf, alen);
381 overlays.push_back(overlay);
382 }
383 return rptr + len + RRFIXEDSZ + dlen;
384}
385
386void
387DnsStub::removeQuery(Query* query)
388{
389 set<Query*>::iterator it = mQueries.find(query);
390 if (it != mQueries.end())
391 {
392 mQueries.erase(it);
393 }
394}
395
396void
398{
399 mTransform = transform;
400}
401
402void
404{
405 mTransform = 0;
406}
407
408void
410{
411 if(mPollGrp)
412 {
413 // unregister our select interruptor
414 mPollGrp->delPollItem(mInterruptorHandle);
415 mInterruptorHandle=0;
416 }
417
418 mPollGrp=pollGrp;
419
420 if (mPollGrp)
421 {
422 mInterruptorHandle = mPollGrp->addPollItem(mSelectInterruptor.getReadSocket(), FPEM_Read, &mSelectInterruptor);
423 }
424
425 mDnsProvider->setPollGrp(mPollGrp);
426}
427
428DnsStub::Query::Query(DnsStub& stub, ResultTransform* transform, ResultConverter* resultConv,
429 const Data& target, int rrType,
430 bool followCname, int proto, DnsResultSink* s)
431 : mRRType(rrType),
432 mStub(stub),
433 mTransform(transform),
434 mResultConverter(resultConv),
435 mTarget(target),
436 mProto(proto),
437 mReQuery(0),
438 mSink(s),
439 mFollowCname(followCname)
440{
441 resip_assert(s);
442}
443
444DnsStub::Query::~Query()
445{
446 delete mResultConverter; //.dcm. flyweight?
447}
448
449static Data
451{
452 // !dcm! fix this
453 if (rr == RR_A::getRRType())
454 {
455 return RR_A::getRRTypeName();
456 }
457#if defined(USE_IPV6)
458 else if(rr == RR_AAAA::getRRType())
459 {
460 return RR_AAAA::getRRTypeName();
461 }
462#endif
463 else if (rr ==RR_NAPTR::getRRType())
464 {
465 return RR_NAPTR::getRRTypeName();
466 }
467 else if(rr == RR_SRV::getRRType())
468 {
469 return RR_SRV::getRRTypeName();
470 }
471 else if (rr == RR_CNAME::getRRType())
472 {
473 return RR_CNAME::getRRTypeName();
474 }
475 else
476 {
477 return "Unknown";
478 }
479}
480
481void
482DnsStub::Query::go()
483{
484 StackLog(<< "DNS query: target=" << mTarget << ", type=" << typeToData(mRRType));
485
486 DnsResourceRecordsByPtr records;
487 int status = 0;
488 bool cached = false;
489 Data targetToQuery = mTarget;
490 bool newTargetToQuery = false;
491
492 cached = mStub.mRRCache.lookup(mTarget, mRRType, mProto, records, status);
493 if (!cached)
494 {
495 if (mRRType != T_CNAME)
496 {
497 int numRequeries = 0;
498 do
499 {
500 DnsResourceRecordsByPtr cnames;
501 if(mStub.mRRCache.lookup(targetToQuery, T_CNAME, mProto, cnames, status) && cnames.size() > 0)
502 {
503 targetToQuery = (dynamic_cast<DnsCnameRecord*>(cnames[0]))->cname();
504 newTargetToQuery = true;
505 }
506 else
507 {
508 // No more CNames to follow
509 break;
510 }
511 } while(++numRequeries < MAX_REQUERIES);
512 }
513 }
514
515 if (newTargetToQuery)
516 {
517 StackLog(<< mTarget << " mapped to CNAME " << targetToQuery);
518 cached = mStub.mRRCache.lookup(targetToQuery, mRRType, mProto, records, status);
519 }
520
521 if (!cached)
522 {
523 if(mStub.mDnsProvider && mStub.mDnsProvider->hostFileLookupLookupOnlyMode())
524 {
525 resip_assert(mRRType == T_A);
526 StackLog (<< targetToQuery << " not cached. Doing hostfile lookup");
527 in_addr address;
528 if (mStub.mDnsProvider->hostFileLookup(targetToQuery.c_str(), address))
529 {
530 mStub.cache(mTarget, address);
531 DnsResourceRecordsByPtr result;
532 int queryStatus = 0;
533
534 mStub.mRRCache.lookup(mTarget, mRRType, mProto, result, queryStatus);
535 if (mTransform)
536 {
537 mTransform->transform(mTarget, mRRType, result);
538 }
539 mResultConverter->notifyUser(mTarget, queryStatus, mStub.errorMessage(queryStatus), result, mSink);
540 }
541 else
542 {
543 // Not in hosts file - return error - or.. we could fallback to doing the lookupRecords call on the local named
544 mResultConverter->notifyUser(mTarget, ARES_ENOTFOUND, mStub.errorMessage(ARES_ENOTFOUND), Empty, mSink);
545 }
546 mReQuery = 0;
547 mStub.removeQuery(this);
548 delete this;
549 return;
550 }
551 else
552 {
553 StackLog (<< targetToQuery << " not cached. Doing external dns lookup, type=" << typeToData(mRRType));
554 mStub.lookupRecords(targetToQuery, mRRType, this);
555 }
556 }
557 else // is cached
558 {
559 if (mTransform && !records.empty())
560 {
561 mTransform->transform(mTarget, mRRType, records);
562 }
563 mResultConverter->notifyUser(mTarget, status, mStub.errorMessage(status), records, mSink);
564
565 mStub.removeQuery(this);
566 delete this;
567 }
568}
569
570void
571DnsStub::Query::process(int status, const unsigned char* abuf, const int alen)
572{
573 if (status != 0)
574 {
575 switch (status)
576 {
577 case ARES_ENODATA:
578 case ARES_EFORMERR:
579 case ARES_ESERVFAIL:
580 case ARES_ENOTFOUND:
581 case ARES_ENOTIMP:
582 case ARES_EREFUSED:
583 if(mRRType == T_A)
584 {
585 in_addr address;
586 if (mStub.mDnsProvider->hostFileLookup(mTarget.c_str(), address))
587 {
588 mStub.cache(mTarget, address);
589 mReQuery = 0;
590 DnsResourceRecordsByPtr result;
591 int queryStatus = 0;
592
593 mStub.mRRCache.lookup(mTarget, mRRType, mProto, result, queryStatus);
594 if (mTransform)
595 {
596 mTransform->transform(mTarget, mRRType, result);
597 }
598 mResultConverter->notifyUser(mTarget, queryStatus, mStub.errorMessage(queryStatus), result, mSink);
599 mStub.removeQuery(this);
600 delete this;
601 return;
602 }
603 }
604 try
605 {
606 mStub.cacheTTL(mTarget, mRRType, status, abuf, alen);
607 }
608 catch (BaseException& e)
609 {
610 // if the response isn't parsable, we might want to consider caching
611 // TTL anyways to delay the query attempt for this record.
612 ErrLog(<< "Couldn't parse failure response to lookup for " << mTarget);
613 InfoLog(<< e.getMessage());
614 }
615 break;
616
618 case ARES_ETIMEOUT:
619 ErrLog (<< "Connection error " << mStub.errorMessage(status) << " for " << mTarget);
620 break;
621 case ARES_EBADRESP:
622 ErrLog (<< "Server response error " << mStub.errorMessage(status) << " for " << mTarget);
623 break;
624 case ARES_EOF:
625 case ARES_EFILE:
626 case ARES_ENOMEM:
628 ErrLog (<< "Error " << mStub.errorMessage(status) << " for " << mTarget);
629 break;
630 case ARES_EBADNAME:
631 ErrLog(<< "Garbage hostname failed to resolve: " << mStub.errorMessage(status) << " for " << mTarget);
632 break;
633 case ARES_EBADQUERY:
634 ErrLog(<< "Query was malformed (probably because hostname was "
635 "too long) " << mStub.errorMessage(status) << " for "
636 << mTarget);
637 break;
638 case ARES_EBADFAMILY:
639 ErrLog (<< "Bad lookup type " << mStub.errorMessage(status) << " for " << mTarget);
640 // .bwc. This should not happen. If it does, we have code to fix.
641 resip_assert(0);
642 break;
643 default:
644 ErrLog (<< "Unknown error " << mStub.errorMessage(status) << " for " << mTarget);
645 resip_assert(0);
646 break;
647 }
648
649 // For other error status values, we may also want to cacheTTL to delay
650 // requeries. Especially if the server refuses.
651 mResultConverter->notifyUser(mTarget, status, mStub.errorMessage(status), Empty, mSink);
652 mReQuery = 0;
653 mStub.removeQuery(this);
654 delete this;
655 return;
656 }
657
658 bool bDeleteThis = true;
659
660 // skip header
661 const unsigned char* aptr = abuf + HFIXEDSZ;
662
663 int qdcount = DNS_HEADER_QDCOUNT(abuf); // questions.
664 for (int i = 0; i < qdcount && aptr; ++i)
665 {
666 try
667 {
668 aptr = mStub.skipDNSQuestion(aptr, abuf, alen);
669 }
670 catch (BaseException& e)
671 {
672 ErrLog(<< "Error parsing DNS record for " << mTarget << ": " << e.getMessage());
673 mResultConverter->notifyUser(mTarget, ARES_EFORMERR, e.getMessage(), Empty, mSink);
674 mStub.removeQuery(this);
675 delete this;
676 return;
677 }
678 }
679
680 int ancount = DNS_HEADER_ANCOUNT(abuf);
681 if (ancount == 0)
682 {
683 mResultConverter->notifyUser(mTarget, 0, mStub.errorMessage(0), Empty, mSink);
684 }
685 else
686 {
687 bool bGotAnswers = true;
688 Data targetToQuery;
689 followCname(aptr, abuf, alen, bGotAnswers, bDeleteThis, targetToQuery);
690
691 if (bGotAnswers)
692 {
693 mReQuery = 0;
694 DnsResourceRecordsByPtr result;
695 int queryStatus = 0;
696
697 if (mTarget != targetToQuery) DebugLog (<< mTarget << " mapped to " << targetToQuery << " and returned result");
698 mStub.mRRCache.lookup(targetToQuery, mRRType, mProto, result, queryStatus);
699 if (mTransform)
700 {
701 mTransform->transform(mTarget, mRRType, result);
702 }
703 mResultConverter->notifyUser(mTarget, queryStatus, mStub.errorMessage(queryStatus), result, mSink);
704 }
705 }
706
707 if (bDeleteThis)
708 {
709 mStub.removeQuery(this);
710 delete this;
711 }
712}
713
714void
715DnsStub::Query::onDnsRaw(int status, const unsigned char* abuf, int alen)
716{
717 process(status, abuf, alen);
718}
719
720void
721DnsStub::Query::followCname(const unsigned char* aptr, const unsigned char*abuf, const int alen, bool& bGotAnswers, bool& bDeleteThis, Data& targetToQuery)
722{
723 bGotAnswers = true;
724 bDeleteThis = true;
725
726 char* name = 0;
727 long len = 0;
728
729 if (ARES_SUCCESS != ares_expand_name(aptr, abuf, alen, &name, &len))
730 {
731 ErrLog(<< "Failed DNS preparse for " << targetToQuery);
732 mResultConverter->notifyUser(mTarget, ARES_EFORMERR, "Failed DNS preparse", Empty, mSink);
733 bGotAnswers = false;
734 return;
735 }
736
737 targetToQuery = name;
738 aptr += len;
739
740 try
741 {
742 mStub.cache(name, abuf, alen);
743 }
744 catch (BaseException& e)
745 {
746 ErrLog(<< "Failed to cache result for " << targetToQuery << ": " << e.getMessage());
747 mResultConverter->notifyUser(mTarget, ARES_EFORMERR, e.getMessage(), Empty, mSink);
748 bGotAnswers = false;
749 free(name);
750 return;
751 }
752
753 if (mRRType != T_CNAME)
754 {
755 if (DNS_RR_TYPE(aptr) == T_CNAME)
756 {
757 if (mFollowCname && mReQuery < MAX_REQUERIES)
758 {
759 ++mReQuery;
760 int status = 0;
761 bool cached = false;
762
763 do
764 {
765 DnsResourceRecordsByPtr cnames;
766 if(mStub.mRRCache.lookup(targetToQuery, T_CNAME, mProto, cnames, status) && cnames.size() > 0)
767 {
768 targetToQuery = (dynamic_cast<DnsCnameRecord*>(cnames[0]))->cname();
769 }
770 else
771 {
772 // No more CNames to follow
773 break;
774 }
775 } while(++mReQuery < MAX_REQUERIES);
776
777 DnsResourceRecordsByPtr result;
778 if (!mStub.mRRCache.lookup(targetToQuery, mRRType, mProto, result, status))
779 {
780 StackLog(<< targetToQuery << " not cached. Doing external dns lookup, type=" << typeToData(mRRType));
781 mStub.lookupRecords(targetToQuery, mRRType, this);
782 bDeleteThis = false;
783 bGotAnswers = false;
784 }
785 }
786 else
787 {
788 mReQuery = 0;
789 mResultConverter->notifyUser(mTarget, 1, mStub.errorMessage(1), Empty, mSink);
790 bGotAnswers = false;
791 }
792 }
793 }
794
795 free(name);
796}
797
798Data
799DnsStub::errorMessage(int status)
800{
801 return Data(Data::Take, mDnsProvider->errorMessage(status));
802}
803
804void
805DnsStub::lookupRecords(const Data& target, unsigned short type, DnsRawSink* sink)
806{
807 mDnsProvider->lookup(target.c_str(), type, this, sink);
808}
809
810void
812{
813 reinterpret_cast<DnsRawSink*>(res.userData)->onDnsRaw(res.errorCode(), res.abuf, res.alen);
814 mDnsProvider->freeResult(res);
815}
816
817void
818DnsStub::setEnumSuffixes(const std::vector<Data>& suffixes)
819{
820 SetEnumSuffixesCommand* command = new SetEnumSuffixesCommand(*this, suffixes);
821 queueCommand(command);
822}
823
824const std::vector<Data>&
826{
827 return mEnumSuffixes;
828}
829
830void
831DnsStub::doSetEnumSuffixes(const std::vector<Data>& suffixes)
832{
833 mEnumSuffixes = suffixes;
834}
835
836void
837DnsStub::setEnumDomains(const std::map<Data,Data>& domains)
838{
839 SetEnumDomainsCommand* command = new SetEnumDomainsCommand(*this, domains);
840 queueCommand(command);
841}
842
843const std::map<Data,Data>&
845{
846 return mEnumDomains;
847}
848
849void
850DnsStub::doSetEnumDomains(const std::map<Data,Data>& domains)
851{
852 mEnumDomains = domains;
853}
854
855void
857{
858 ClearDnsCacheCommand* command = new ClearDnsCacheCommand(*this);
859 queueCommand(command);
860}
861
862void
863DnsStub::doClearDnsCache()
864{
865 mRRCache.clearCache();
866}
867
868void
870{
871 LogDnsCacheCommand* command = new LogDnsCacheCommand(*this);
872 queueCommand(command);
873}
874
875void
876DnsStub::doLogDnsCache()
877{
878 mRRCache.logCache();
879}
880
881void
882DnsStub::getDnsCacheDump(std::pair<unsigned long, unsigned long> key, GetDnsCacheDumpHandler* handler)
883{
884 GetDnsCacheDumpCommand* command = new GetDnsCacheDumpCommand(*this, key, handler);
885 queueCommand(command);
886}
887
888void
889DnsStub::doGetDnsCacheDump(std::pair<unsigned long, unsigned long> key, GetDnsCacheDumpHandler* handler)
890{
891 resip_assert(handler != 0);
892 Data dnsCacheDump;
893 mRRCache.getCacheDump(dnsCacheDump);
894 handler->onDnsCacheDumpRetrieved(key, dnsCacheDump);
895}
896
897void
899{
900 ReloadDnsServersCommand* command = new ReloadDnsServersCommand(*this);
901 queueCommand(command);
902}
903
904void
905DnsStub::doReloadDnsServers()
906{
907 bool changed = mDnsProvider->checkDnsChange();
908 if (changed)
909 {
910 doClearDnsCache();
911
912 mDnsProvider->init(mDnsTimeout, mDnsTries, mDnsFeatures);
913 }
914}
915
916void
918{
919 mRRCache.setTTL(ttl);
920}
921
922void
924{
925 mRRCache.setSize(size);
926}
927
928/* ====================================================================
929 * The Vovida Software License, Version 1.0
930 *
931 * Copyright (c) 2000-2005 Vovida Networks, Inc. All rights reserved.
932 *
933 * Redistribution and use in source and binary forms, with or without
934 * modification, are permitted provided that the following conditions
935 * are met:
936 *
937 * 1. Redistributions of source code must retain the above copyright
938 * notice, this list of conditions and the following disclaimer.
939 *
940 * 2. Redistributions in binary form must reproduce the above copyright
941 * notice, this list of conditions and the following disclaimer in
942 * the documentation and/or other materials provided with the
943 * distribution.
944 *
945 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
946 * and "Vovida Open Communication Application Library (VOCAL)" must
947 * not be used to endorse or promote products derived from this
948 * software without prior written permission. For written
949 * permission, please contact vocal@vovida.org.
950 *
951 * 4. Products derived from this software may not be called "VOCAL", nor
952 * may "VOCAL" appear in their name, without prior written
953 * permission of Vovida Networks, Inc.
954 *
955 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
956 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
957 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
958 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
959 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
960 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
961 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
962 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
963 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
964 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
965 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
966 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
967 * DAMAGE.
968 *
969 * ====================================================================
970 *
971 * This software consists of voluntary contributions made by Vovida
972 * Networks, Inc. and many individuals on behalf of Vovida Networks,
973 * Inc. For more information on Vovida Networks, Inc., please see
974 * <http://www.vovida.org/>.
975 *
976 */
977
static Data typeToData(int rr)
Definition DnsStub.cxx:450
#define FPEM_Read
Definition FdPoll.hxx:29
#define DebugLog(args_)
Definition Logger.hxx:128
#define StackLog(args_)
Definition Logger.hxx:125
#define InfoLog(args_)
Definition Logger.hxx:131
#define ErrLog(args_)
Definition Logger.hxx:137
#define resip_assert(x)
This file needs to work for both C and C++ code.
Handles cross-platform sockets compatibility.
#define ARES_SUCCESS
Definition ares.h:79
#define ARES_ENOMEM
Definition ares.h:98
#define ARES_ENODATA
Definition ares.h:82
#define ARES_ECONNREFUSED
Definition ares.h:94
#define ARES_EOF
Definition ares.h:96
#define ARES_ETIMEOUT
Definition ares.h:95
#define ARES_EREFUSED
Definition ares.h:87
#define DNS_RR_LEN(r)
Definition ares.h:53
#define ARES_ENOTFOUND
Definition ares.h:85
#define ARES_EBADFAMILY
Definition ares.h:92
#define DNS_HEADER_QDCOUNT(h)
Definition ares.h:48
#define DNS_HEADER_NSCOUNT(h)
Definition ares.h:50
#define ARES_EDESTRUCTION
Definition ares.h:99
#define DNS_HEADER_ANCOUNT(h)
Definition ares.h:49
#define ARES_ENOTIMP
Definition ares.h:86
#define DNS_HEADER_ARCOUNT(h)
Definition ares.h:51
int ares_expand_name(const unsigned char *encoded, const unsigned char *abuf, int alen, char **s, long *enclen)
#define ARES_EBADNAME
Definition ares.h:91
#define ARES_EBADQUERY
Definition ares.h:90
#define ARES_EBADRESP
Definition ares.h:93
#define ARES_ESERVFAIL
Definition ares.h:84
#define ARES_EFORMERR
Definition ares.h:83
#define DNS_RR_TYPE(r)
Definition ares.h:52
#define ARES_EFILE
Definition ares.h:97
#define QFIXEDSZ
#define T_CNAME
#define T_SOA
#define HFIXEDSZ
#define RRFIXEDSZ
virtual void handleProcessNotification()=0
long errorCode() const
Definition AsyncID.hxx:36
The abstract base-class for all exceptions thrown by resip code.
const Data & getMessage() const noexcept
An alternative to std::string, encapsulates an arbitrary buffer of bytes.
Definition Data.hxx:90
const char * c_str() const
Returns a null-terminated string representing.
Definition Data.cxx:1097
@ Take
The Data instance takes complete ownership of the buffer.
Definition Data.hxx:272
virtual void onLogDnsResult(const DNSResult< DnsHostRecord > &)
Definition DnsStub.cxx:47
virtual unsigned int getTimeTillNextProcessMS()
Definition DnsStub.cxx:124
static NameserverList EmptyNameserverList
Definition DnsStub.hxx:119
const std::map< Data, Data > & getEnumDomains() const
Definition DnsStub.cxx:844
void reloadDnsServers()
Definition DnsStub.cxx:898
std::vector< GenericIPAddress > NameserverList
Definition DnsStub.hxx:117
void removeResultTransform()
Definition DnsStub.cxx:403
DnsStub(const NameserverList &additional=EmptyNameserverList, AfterSocketCreationFuncPtr socketFunc=0, AsyncProcessHandler *asyncProcessHandler=0, FdPollGrp *pollGrp=0)
Definition DnsStub.cxx:82
void logDnsCache()
Definition DnsStub.cxx:869
std::vector< DnsResourceRecord * > DnsResourceRecordsByPtr
Definition DnsStub.hxx:116
void setResultTransform(ResultTransform *)
Definition DnsStub.cxx:397
void setEnumDomains(const std::map< Data, Data > &domains)
Definition DnsStub.cxx:837
void clearDnsCache()
Definition DnsStub.cxx:856
void cacheTTL(const Data &key, int rrType, int status, const unsigned char *abuf, int alen)
Definition DnsStub.cxx:242
const std::vector< Data > & getEnumSuffixes() const
Definition DnsStub.cxx:825
void setDnsCacheTTL(int ttl)
Definition DnsStub.cxx:917
void setDnsCacheSize(int size)
Definition DnsStub.cxx:923
virtual void queueCommand(Command *command)
Definition DnsStub.cxx:165
void cache(const Data &key, in_addr addr)
Definition DnsStub.cxx:177
bool checkDnsChange()
Definition DnsStub.cxx:318
virtual void process(FdSet &fdset)
Definition DnsStub.cxx:149
void getDnsCacheDump(std::pair< unsigned long, unsigned long > key, GetDnsCacheDumpHandler *handler)
Definition DnsStub.cxx:882
bool supportedType(int)
Definition DnsStub.cxx:324
virtual void buildFdSet(FdSet &fdset)
Definition DnsStub.cxx:131
void setPollGrp(FdPollGrp *pollGrp)
Definition DnsStub.cxx:409
virtual void handleDnsRaw(ExternalDnsRawResult)
Definition DnsStub.cxx:811
bool changeNameServers(const NameserverList &additional)
Definition DnsStub.cxx:307
void processTimers()
Definition DnsStub.cxx:157
void setEnumSuffixes(const std::vector< Data > &suffixes)
Definition DnsStub.cxx:818
virtual bool checkDnsChange()=0
virtual void lookup(const char *target, unsigned short type, ExternalDnsHandler *handler, void *userData)=0
virtual int init(const std::vector< GenericIPAddress > &additionalNameservers, AfterSocketCreationFuncPtr, int dnsTimeout=0, int dnsTries=0, unsigned int features=0)=0
virtual void freeResult(ExternalDnsRawResult res)=0
virtual bool hostFileLookupLookupOnlyMode()=0
virtual unsigned int getTimeTillNextProcessMS()=0
virtual void buildFdSet(fd_set &read, fd_set &write, int &size)=0
virtual char * errorMessage(long errorCode)=0
virtual void setPollGrp(FdPollGrp *grp)=0
virtual void process(fd_set &read, fd_set &write)=0
virtual void processTimers()=0
virtual void changeNameServers(const std::vector< GenericIPAddress > &additional)=0
virtual FdPollItemHandle addPollItem(Socket sock, FdPollEventMask newMask, FdPollItemIf *item)=0
virtual void delPollItem(FdPollItemHandle handle)=0
Object-oriented wrapper for your platform's file-descriptor set.
Definition Socket.hxx:162
fd_set read
Definition Socket.hxx:256
fd_set write
Definition Socket.hxx:257
virtual void onDnsCacheDumpRetrieved(std::pair< unsigned long, unsigned long > key, const Data &dnsCache)=0
void setSize(int size)
Definition RRCache.hxx:33
void updateCacheFromHostFile(const DnsHostRecord &)
Definition RRCache.cxx:76
void setTTL(int ttl)
Definition RRCache.hxx:32
void cacheTTL(const Data &target, const int rrType, const int status, RROverlay overlay)
Definition RRCache.cxx:164
void updateCache(const Data &target, const int rrType, Itr begin, Itr end)
Definition RRCache.cxx:104
void getCacheDump(Data &dnsCacheDump)
Definition RRCache.cxx:326
void logCache()
Definition RRCache.cxx:318
void clearCache()
Definition RRCache.cxx:243
void process(FdSet &fdset)
cleanup signalled fd
void buildFdSet(FdSet &fdset)
Used to add the 'artificial' fd to the fdset that will be responsible for interrupting a subsequent s...
This file is used to handle compatibility fixes/tweaks so reSIProcate can function on multiple platfo...
#define T_NAPTR
Definition compat.hxx:140
#define T_A
Definition compat.hxx:152
#define T_AAAA
Definition compat.hxx:148
#define T_SRV
Definition compat.hxx:144
dcm! – add UnusedChecking(_enum) below;
void(* AfterSocketCreationFuncPtr)(Socket s, int transportType, const char *file, int line)
Definition Socket.hxx:107