/[resiprocate]/main/sip/resiprocate/DnsResult.cxx
ViewVC logotype

Contents of /main/sip/resiprocate/DnsResult.cxx

Parent Directory Parent Directory | Revision Log Revision Log


Revision 4740 - (show annotations) (download)
Tue May 24 21:30:57 2005 UTC (14 years, 6 months ago) by daniel
File size: 30475 byte(s)
AresDns.hxx/cxx: Redefined lookup and ares callback methonds.
DnsInterface.hxx/cxx: Added dns caching support and  methods to (un)register blacklist listener.
DnsResult.hxx/cxx: Modified to use dns caching, blacklisting, and vip; removed dead code.
Makefile: Added dns cache related files.
Security.hxx/cxx: correctly handle default paths in the constructor
SipStack.hxx/cxx: Added blacklist listener registration and unregistration.
StatelessHandler.cxx: Got it to compile with USE_IPV6 defined.
TlsConnection.cxx: Make logging less verbose.
TransactionController.hxx/cxx: Added blacklist listener registration and unregistration.
TransactionState.cxx: Added whitelisting(vip) rules.
TransportSelector.hxx/cxx: Added blacklist listener registration and unregistration; refactor and clarify for IPv6
WinSecurity.hxx/cxx: since certificates are preloaded, don't query the filesystem cert store.
dum/ClientAuthManager.cxx: changed DebugLog to InfoLog in handle method.
dum/DialogUsageManager.cxx: changed DebugLog to InfoLog in internalProcess method.
dum/test/BasicCall.cxx: added keep-alive test case.
dum/test/basicRegister.cxx: updated commandline options and simplified for TLS/IPv6.
dum/test/testIdentity.cxx: added test for identity over TLS/IPv6.
external/ExternalDns.hxx: redefined ExternalDnsHandler and lookup methods in ExternalDns class.
os/Tuple.cxx: fix constructor to copy complete IPv6 address.
os/WinCompat.hxx/cxx: add support to determine local IPv6 address; now only used on Windows platform.
os/compat.hxx: added define for T_A.
1 #if defined(HAVE_CONFIG_H)
2 #include "resiprocate/config.hxx"
3 #endif
4
5 #include <algorithm>
6 #include <stack>
7
8 #ifndef WIN32
9 #include <sys/types.h>
10 #include <sys/socket.h>
11 #include <arpa/inet.h>
12 #ifndef __CYGWIN__
13 # include <netinet/in.h>
14 # include <arpa/nameser.h>
15 # include <resolv.h>
16 #endif
17 #include <netdb.h>
18 #include <netinet/in.h>
19 #else
20 #include <Winsock2.h>
21 #include <svcguid.h>
22 #ifdef USE_IPV6
23 #include <ws2tcpip.h>
24 #endif
25 #endif
26
27 #if defined(USE_ARES)
28 extern "C"
29 {
30 #include "ares.h"
31 #include "ares_dns.h"
32 }
33 #endif
34
35 #include "resiprocate/os/DnsUtil.hxx"
36 #include "resiprocate/os/Inserter.hxx"
37 #include "resiprocate/os/Logger.hxx"
38 #include "resiprocate/os/Random.hxx"
39 #include "resiprocate/os/Tuple.hxx"
40 #include "resiprocate/os/compat.hxx"
41
42 #include "resiprocate/DnsHandler.hxx"
43 #include "resiprocate/DnsInterface.hxx"
44 #include "resiprocate/dns/QueryTypes.hxx"
45 #include "resiprocate/dns/DnsStub.hxx"
46 #include "resiprocate/DnsResult.hxx"
47 #include "resiprocate/Uri.hxx"
48 #include "resiprocate/os/WinLeakCheck.hxx"
49
50 #if !defined(USE_ARES)
51 #warning "ARES is required"
52 #endif
53
54 using namespace resip;
55 using namespace std;
56
57 #define RESIPROCATE_SUBSYSTEM resip::Subsystem::DNS
58
59 DnsResult::DnsResult(DnsInterface& interfaceObj, DnsStub& dns, RRVip& vip, DnsHandler* handler)
60 : mInterface(interfaceObj),
61 mDns(dns),
62 mVip(vip),
63 mHandler(handler),
64 mSRVCount(0),
65 mSips(false),
66 mTransport(UNKNOWN_TRANSPORT),
67 mPort(-1),
68 mType(Pending),
69 mBlacklistLastReturnedResult(false)
70 {
71 }
72
73 DnsResult::~DnsResult()
74 {
75 //DebugLog (<< "DnsResult::~DnsResult() " << *this);
76 assert(mType != Pending);
77 }
78
79 void
80 DnsResult::transition(Type t)
81 {
82 if ((t == Finished || t == Destroyed || t == Available) &&
83 (mType == Pending))
84 {
85 mInterface.mActiveQueryCount--;
86 assert(mInterface.mActiveQueryCount >= 0);
87 }
88 mType = t;
89 }
90
91 void
92 DnsResult::destroy()
93 {
94 assert(this);
95 //DebugLog (<< "DnsResult::destroy() " << *this);
96
97 if (mType == Pending)
98 {
99 transition(Destroyed);
100 }
101 else
102 {
103 delete this;
104 }
105 }
106
107 DnsResult::Type
108 DnsResult::available()
109 {
110 assert(mType != Destroyed);
111 if (mType == Available)
112 {
113 if (!mResults.empty())
114 {
115 return Available;
116 }
117 else
118 {
119 if (mBlacklistLastReturnedResult)
120 {
121 blacklistLastReturnedResult();
122 mBlacklistLastReturnedResult = false;
123 }
124 primeResults();
125 return available(); // recurse
126 }
127 }
128 else
129 {
130 return mType;
131 }
132 }
133
134 Tuple
135 DnsResult::next()
136 {
137 assert(available() == Available);
138 Tuple next = mResults.front();
139 mResults.pop_front();
140 StackLog (<< "Returning next dns entry: " << next);
141
142 if (mBlacklistLastReturnedResult)
143 {
144 blacklistLastReturnedResult();
145 }
146 else if (!mCurrResultPath.empty())
147 {
148 mBlacklistLastReturnedResult = true;
149 }
150 mLastReturnedResult = next;
151
152 assert(mCurrSuccessPath.size()<=3);
153 Item top;
154 if (!mCurrSuccessPath.empty())
155 {
156 top = mCurrSuccessPath.top();
157 if (top.rrType == T_A || top.rrType == T_AAAA)
158 {
159 mCurrSuccessPath.pop();
160 }
161 }
162 top.domain = next.getTargetDomain();
163 top.rrType = next.isV4()? T_A : T_AAAA;
164 top.value = DnsUtil::inet_ntop(next);
165 mCurrSuccessPath.push(top);
166 return next;
167 }
168
169 void DnsResult::success()
170 {
171 while (!mCurrSuccessPath.empty())
172 {
173 Item top = mCurrSuccessPath.top();
174 mVip.vip(top.domain, top.rrType, top.value);
175 InfoLog( << "Whitelisting " << top.domain << "(" << top.rrType << "): " << top.value);
176 mCurrSuccessPath.pop();
177 }
178 }
179
180 void
181 DnsResult::lookup(const Uri& uri)
182 {
183 DebugLog (<< "DnsResult::lookup " << uri);
184 //int type = this->mType;
185
186 //assert(uri.scheme() == Symbols::Sips || uri.scheme() == Symbols::Sip);
187 mSips = (uri.scheme() == Symbols::Sips);
188 mTarget = (!mSips && uri.exists(p_maddr)) ? uri.param(p_maddr) : uri.host();
189 mSrvKey = Symbols::UNDERSCORE + uri.scheme().substr(0, uri.scheme().size()) + Symbols::DOT;
190 bool isNumeric = DnsUtil::isIpAddress(mTarget);
191
192 if (uri.exists(p_transport))
193 {
194 mTransport = Tuple::toTransport(uri.param(p_transport));
195
196 if (isNumeric) // IP address specified
197 {
198 mPort = getDefaultPort(mTransport, uri.port());
199 Tuple tuple(mTarget, mPort, mTransport, mTarget);
200 DebugLog (<< "Found immediate result: " << tuple);
201 mResults.push_back(tuple);
202 transition(Available);
203 mHandler->handle(this);
204 }
205 else if (uri.port() != 0)
206 {
207 mPort = uri.port();
208 lookupHost(mTarget); // for current target and port
209 }
210 else
211 {
212 if (mSips)
213 {
214 if (mTransport == UDP)
215 {
216 mTransport = DTLS;
217 if (!mInterface.isSupportedProtocol(mTransport))
218 {
219 transition(Finished);
220 mHandler->handle(this);
221 return;
222 }
223 mSRVCount++;
224 mDns.lookup<RR_SRV>("_sips._udp." + mTarget, Protocol::Sip, this);
225 }
226 else
227 {
228 mTransport = TLS;
229 if (!mInterface.isSupportedProtocol(mTransport))
230 {
231 transition(Finished);
232 mHandler->handle(this);
233 return;
234 }
235 mSRVCount++;
236 mDns.lookup<RR_SRV>("_sips._tcp." + mTarget, Protocol::Sip, this);
237 }
238 }
239 else
240 {
241 if (!mInterface.isSupportedProtocol(mTransport))
242 {
243 transition(Finished);
244 mHandler->handle(this);
245 return;
246 }
247
248 switch(mTransport)
249 {
250 case TLS: //deprecated, mean TLS over TCP
251 mSRVCount++;
252 mDns.lookup<RR_SRV>("_sip._tls." + mTarget, Protocol::Sip, this);
253 break;
254 case DTLS: //deprecated, mean TLS over TCP
255 mSRVCount++;
256 mDns.lookup<RR_SRV>("_sip._dtls." + mTarget, Protocol::Sip, this);
257 break;
258 case TCP:
259 mSRVCount++;
260 mDns.lookup<RR_SRV>("_sip._tcp." + mTarget, Protocol::Sip, this);
261 break;
262 case SCTP:
263 case DCCP:
264 case UDP:
265 default: //fall through to UDP for unimplemented & unknown
266 mSRVCount++;
267 mDns.lookup<RR_SRV>("_sip._udp." + mTarget, Protocol::Sip, this);
268 }
269 }
270 }
271 }
272 else
273 {
274 if (isNumeric || uri.port() != 0)
275 {
276 if (mSips || mTransport == TLS)
277 {
278 mTransport = TLS;
279 }
280 else
281 {
282 mTransport = UDP;
283 }
284
285 if (isNumeric) // IP address specified
286 {
287 mPort = getDefaultPort(mTransport, uri.port());
288 Tuple tuple(mTarget, mPort, mTransport, mTarget);
289 mResults.push_back(tuple);
290 transition(Available);
291 DebugLog (<< "Numeric result so return immediately: " << tuple);
292 mHandler->handle(this);
293 }
294 else // port specified so we know the transport
295 {
296 mPort = uri.port();
297 if (mInterface.isSupported(mTransport, V6) || mInterface.isSupported(mTransport, V4))
298 {
299 lookupHost(mTarget);
300 }
301 else
302 {
303 assert(0);
304 mHandler->handle(this);
305 }
306 }
307 }
308 else // do NAPTR
309 {
310 mDns.lookup<RR_NAPTR>(mTarget, Protocol::Sip, this); // for current target
311 }
312 }
313 }
314
315 void DnsResult::lookupHost(const Data& target)
316 {
317 if (mInterface.isSupported(mTransport, V6))
318 {
319 #ifdef USE_IPV6
320 DebugLog(<< "Doing host (AAAA) lookup: " << target);
321 mPassHostFromAAAAtoA = target;
322 mDns.lookup<RR_AAAA>(target, Protocol::Sip, this);
323 #else
324 assert(0);
325 mDns.lookup<RR_A>(target, Protocol::Sip, this);
326 #endif
327 }
328 else if (mInterface.isSupported(mTransport, V4))
329 {
330 mDns.lookup<RR_A>(target, Protocol::Sip, this);
331 }
332 else
333 {
334 assert(0);
335 }
336 }
337
338 int
339 DnsResult::getDefaultPort(TransportType transport, int port)
340 {
341 if (port == 0)
342 {
343 switch (transport)
344 {
345 case UDP:
346 return Symbols::DefaultSipPort;
347 case TCP:
348 return mSips ? Symbols::DefaultSipsPort : Symbols::DefaultSipPort;
349 case TLS:
350 return Symbols::DefaultSipsPort;
351 default:
352 InfoLog( << "Should not get this - unkown transport" );
353 return Symbols::DefaultSipPort; // !cj! todo - remove
354 assert(0);
355 }
356 }
357 else
358 {
359 return port;
360 }
361
362 assert(0);
363 return 0;
364 }
365
366 void
367 DnsResult::primeResults()
368 {
369 StackLog(<< "Priming " << Inserter(mSRVResults));
370 //assert(mType != Pending);
371 //assert(mType != Finished);
372 assert(mResults.empty());
373
374 if (!mSRVResults.empty())
375 {
376 SRV next = retrieveSRV();
377 StackLog (<< "Primed with SRV=" << next);
378 transition(Pending);
379 mPort = next.port;
380 mTransport = next.transport;
381 StackLog (<< "No A or AAAA record for " << next.target << " in additional records");
382 if (mInterface.isSupported(mTransport, V6) || mInterface.isSupported(mTransport, V4))
383 {
384 assert(mCurrResultPath.size()<=2);
385 Item top;
386 if (!mCurrResultPath.empty())
387 {
388 top = mCurrResultPath.top();
389 if (top.rrType == T_SRV)
390 {
391 vector<Data> records;
392 records.push_back(top.value);
393 mDns.blacklist(top.domain, top.rrType, Protocol::Sip, records);
394 mCurrResultPath.pop();
395 }
396 else
397 {
398 assert(top.rrType==T_NAPTR);
399 }
400 }
401
402 while (!mCurrSuccessPath.empty())
403 {
404 top = mCurrSuccessPath.top();
405 if (top.rrType != T_NAPTR)
406 {
407 mCurrSuccessPath.pop();
408 }
409 else
410 {
411 break;
412 }
413 }
414 top.domain = next.key;
415 top.rrType = T_SRV;
416 top.value = next.target + ":" + Data(next.port);
417 mCurrResultPath.push(top);
418 mCurrSuccessPath.push(top);
419 lookupHost(next.target);
420 }
421 else
422 {
423 assert(0);
424 mHandler->handle(this);
425 }
426 // don't call primeResults since we need to wait for the response to
427 // AAAA/A query first
428 }
429 else
430 {
431 bool changed = (mType == Pending);
432 transition(Finished);
433 if (!mCurrResultPath.empty())
434 {
435 assert(mCurrResultPath.size()<=2);
436 while (!mCurrResultPath.empty())
437 {
438 Item top = mCurrResultPath.top();
439 vector<Data> records;
440 records.push_back(top.value);
441 mDns.blacklist(top.domain, top.rrType, Protocol::Sip, records);
442 mCurrResultPath.pop();
443 }
444 }
445 if (changed) mHandler->handle(this);
446 }
447
448 // Either we are finished or there are results primed
449 assert(mType == Finished ||
450 mType == Pending ||
451 (mType == Available && !mResults.empty())
452 );
453 }
454
455 // implement the selection algorithm from rfc2782 (SRV records)
456 DnsResult::SRV
457 DnsResult::retrieveSRV()
458 {
459 // !ah! if mTransport is known -- should we ignore those that don't match?!
460 assert(!mSRVResults.empty());
461
462 const SRV& srv = *mSRVResults.begin();
463 if (srv.cumulativeWeight == 0)
464 {
465 int priority = srv.priority;
466
467 mCumulativeWeight=0;
468 //!dcm! -- this should be fixed properly; TCP req. lines were being sent
469 //out on UDP
470 TransportType transport = mSRVResults.begin()->transport;
471 for (std::vector<SRV>::iterator i=mSRVResults.begin();
472 i!=mSRVResults.end()
473 && i->priority == priority
474 && i->transport == transport; i++)
475 {
476 mCumulativeWeight += i->weight;
477 i->cumulativeWeight = mCumulativeWeight;
478 }
479 }
480
481 int selected = Random::getRandom() % (mCumulativeWeight+1);
482
483 StackLog (<< "cumulative weight = " << mCumulativeWeight << " selected=" << selected);
484
485 std::vector<SRV>::iterator i;
486 for (i=mSRVResults.begin(); i!=mSRVResults.end(); i++)
487 {
488 if (i->cumulativeWeight >= selected)
489 {
490 break;
491 }
492 }
493
494 if (i == mSRVResults.end())
495 {
496 InfoLog (<< "SRV Results problem selected=" << selected << " cum=" << mCumulativeWeight);
497 }
498 assert(i != mSRVResults.end());
499 SRV next = *i;
500 mCumulativeWeight -= next.cumulativeWeight;
501 mSRVResults.erase(i);
502
503 StackLog (<< "SRV: " << Inserter(mSRVResults));
504
505 return next;
506 }
507
508 // adapted from the adig.c example in ares
509 const unsigned char*
510 DnsResult::skipDNSQuestion(const unsigned char *aptr,
511 const unsigned char *abuf,
512 int alen)
513 {
514 char *name=0;
515 int status=0;
516 int len=0;
517
518 // Parse the question name.
519 status = ares_expand_name(aptr, abuf, alen, &name, &len);
520 if (status != ARES_SUCCESS)
521 {
522 StackLog (<< "Failed parse of RR");
523 return NULL;
524 }
525 aptr += len;
526
527 // Make sure there's enough data after the name for the fixed part
528 // of the question.
529 if (aptr + QFIXEDSZ > abuf + alen)
530 {
531 free(name);
532 StackLog (<< "Failed parse of RR");
533 return NULL;
534 }
535
536 // Parse the question type and class.
537 //int type = DNS_QUESTION_TYPE(aptr);
538 //int dnsclass = DNS_QUESTION_CLASS(aptr);
539 aptr += QFIXEDSZ;
540
541 free(name);
542 return aptr;
543 }
544
545 DnsResult::NAPTR::NAPTR() : order(0), pref(0)
546 {
547 }
548
549 bool
550 DnsResult::NAPTR::operator<(const DnsResult::NAPTR& rhs) const
551 {
552 if (key.empty()) // default value
553 {
554 return false;
555 }
556 else if (rhs.key.empty()) // default value
557 {
558 return true;
559 }
560 else if (order < rhs.order)
561 {
562 return true;
563 }
564 else if (order == rhs.order)
565 {
566 if (pref < rhs.pref)
567 {
568 return true;
569 }
570 else if (pref == rhs.pref)
571 {
572 return replacement < rhs.replacement;
573 }
574 }
575 return false;
576 }
577
578 DnsResult::SRV::SRV() : priority(0), weight(0), cumulativeWeight(0), port(0)
579 {
580 }
581
582 bool
583 DnsResult::SRV::operator<(const DnsResult::SRV& rhs) const
584 {
585 if (transport < rhs.transport)
586 {
587 return true;
588 }
589 else if (transport == rhs.transport)
590 {
591 if (target < rhs.target)
592 {
593 return true;
594 }
595 else if (target == rhs.target)
596 {
597 if (priority < rhs.priority)
598 {
599 return true;
600 }
601 else if (priority == rhs.priority)
602 {
603 if (weight < rhs.weight)
604 {
605 return true;
606 }
607 }
608 }
609 }
610 return false;
611 }
612
613 void DnsResult::onDnsResult(const DNSResult<DnsHostRecord>& result)
614 {
615 if (!mInterface.isSupported(mTransport, V4) && !mInterface.isSupported(mTransport, V6))
616 {
617 return;
618 }
619 StackLog (<< "Received dns result for: " << mTarget);
620 StackLog (<< "DnsResult::onDnsResult() " << result.status);
621
622 // This function assumes that the A query that caused this callback
623 // is the _only_ outstanding DNS query that might result in a
624 // callback into this function
625 if ( mType == Destroyed )
626 {
627 destroy();
628 return;
629 }
630
631 if (result.status == 0)
632 {
633 for (vector<DnsHostRecord>::const_iterator it = result.records.begin(); it != result.records.end(); ++it)
634 {
635 in_addr addr;
636 addr.s_addr = (*it).addr().s_addr;
637 //Tuple tuple(addr, mPort, mTransport, mTarget);
638 Tuple tuple(addr, mPort, mTransport, it->name());
639 StackLog (<< "Adding " << tuple << " to result set");
640 mResults.push_back(tuple);
641 }
642 }
643 else
644 {
645 StackLog (<< "Failed async A query: " << result.msg);
646 }
647
648 if (mSRVCount == 0)
649 {
650 bool changed = (mType == Pending);
651 if (mResults.empty())
652 {
653 #ifdef WIN32_SYNCRONOUS_RESOLUTION_ON_ARES_FAILURE
654 // Try Windows Name Resolution (not asyncronous)
655 WSAQUERYSET QuerySet = { 0 };
656 GUID guidServiceTypeUDP = SVCID_UDP(mPort);
657 GUID guidServiceTypeTCP = SVCID_TCP(mPort);
658 HANDLE hQuery;
659 QuerySet.dwSize = sizeof(WSAQUERYSET);
660 QuerySet.lpServiceClassId = mTransport == UDP ? &guidServiceTypeUDP : &guidServiceTypeTCP;
661 QuerySet.dwNameSpace = NS_ALL;
662 QuerySet.lpszServiceInstanceName = (char *)mTarget.c_str();
663 if(WSALookupServiceBegin(&QuerySet, LUP_RETURN_ADDR, &hQuery) == 0)
664 {
665 DWORD dwQuerySize = 256; // Starting size
666 int iRet = 0;
667 bool fDone = false;
668 LPWSAQUERYSET pQueryResult = (LPWSAQUERYSET) new char[dwQuerySize];
669 while(iRet == 0 && pQueryResult)
670 {
671 iRet = WSALookupServiceNext(hQuery, 0, &dwQuerySize, pQueryResult);
672 if(pQueryResult && iRet == -1 && GetLastError() == WSAEFAULT)
673 {
674 delete [] pQueryResult;
675 pQueryResult = (LPWSAQUERYSET) new char[dwQuerySize]; // Re-allocate new size
676 iRet = WSALookupServiceNext(hQuery, 0, &dwQuerySize, pQueryResult);
677 }
678 if(pQueryResult && iRet == 0)
679 {
680 for(DWORD i = 0; i < pQueryResult->dwNumberOfCsAddrs; i++)
681 {
682 SOCKADDR_IN *pSockAddrIn = (SOCKADDR_IN *)pQueryResult->lpcsaBuffer[i].RemoteAddr.lpSockaddr;
683 Tuple tuple(pSockAddrIn->sin_addr, mPort, mTransport, mTarget);
684 StackLog (<< "Adding (WIN) " << tuple << " to result set");
685 mResults.push_back(tuple);
686 mType = Available;
687 }
688 }
689 }
690 delete [] pQueryResult;
691 WSALookupServiceEnd(hQuery);
692 }
693 if(mResults.empty())
694 {
695 mType = Finished;
696 }
697 #else
698 mType = Finished;
699 #endif
700 clearCurrPath();
701 }
702 else
703 {
704 if (mSRVResults.empty())
705 {
706 transition(Available);
707 }
708 else
709 {
710 mType = Available;
711 }
712 addToPath(mResults);
713 }
714 if (changed) mHandler->handle(this);
715 }
716 }
717
718 #ifdef USE_IPV6
719 void DnsResult::onDnsResult(const DNSResult<DnsAAAARecord>& result)
720 {
721 StackLog (<< "Received AAAA result for: " << mTarget);
722 if (!mInterface.isSupported(mTransport, V6))
723 {
724 return;
725 }
726 StackLog (<< "DnsResult::onDnsResult() " << result.status);
727 assert(mInterface.isSupported(mTransport, V6));
728
729 // This function assumes that the AAAA query that caused this callback
730 // is the _only_ outstanding DNS query that might result in a
731 // callback into this function
732 if ( mType == Destroyed )
733 {
734 destroy();
735 return;
736 }
737
738 if (result.status == 0)
739 {
740 for (vector<DnsAAAARecord>::const_iterator it = result.records.begin(); it != result.records.end(); ++it)
741 {
742 Tuple tuple((*it).v6Address(), mPort, mTransport, mTarget);
743 StackLog (<< "Adding " << tuple << " to result set");
744 mResults.push_back(tuple);
745 }
746 }
747 else
748 {
749 StackLog (<< "Failed async AAAA query: " << result.msg);
750 }
751 // funnel through to host processing
752 mDns.lookup<RR_A>(mPassHostFromAAAAtoA, Protocol::Sip, this);
753
754 }
755 #endif
756
757 void DnsResult::onDnsResult(const DNSResult<DnsSrvRecord>& result)
758 {
759 StackLog (<< "Received SRV result for: " << mTarget);
760 assert(mSRVCount>=0);
761 mSRVCount--;
762 StackLog (<< "DnsResult::onDnsResult() " << mSRVCount << " status=" << result.status);
763
764 // There could be multiple SRV queries outstanding, but there will be no
765 // other DNS queries outstanding that might cause a callback into this
766 // object.
767 if (mType == Destroyed && mSRVCount == 0)
768 {
769 destroy();
770 return;
771 }
772
773 if (result.status == 0)
774 {
775 for (vector<DnsSrvRecord>::const_iterator it = result.records.begin(); it != result.records.end(); ++it)
776 {
777 SRV srv;
778 srv.key = (*it).name();
779 srv.priority = (*it).priority();
780 srv.weight = (*it).weight();
781 srv.port = (*it).port();
782 srv.target = (*it).target();
783 if (srv.key.find("_sips._udp") != Data::npos)
784 {
785 srv.transport = DTLS;
786 }
787 else if (srv.key.find("_sips._tcp") != Data::npos)
788 {
789 srv.transport = TLS;
790 }
791 else if (srv.key.find("_udp") != Data::npos)
792 {
793 srv.transport = UDP;
794 }
795 else if (srv.key.find("_dtls") != Data::npos)
796 {
797 srv.transport = DTLS;
798 }
799 else if (srv.key.find("_tls") != Data::npos)
800 {
801 srv.transport = TLS;
802 }
803 else if (srv.key.find("_tcp") != Data::npos)
804 {
805 srv.transport = TCP;
806 }
807 else
808 {
809 StackLog (<< "Skipping SRV " << srv.key);
810 continue;
811 }
812 mSRVResults.push_back(srv);
813 }
814 }
815 else
816 {
817 StackLog (<< "SRV lookup failed: " << result.status);
818 }
819
820 // no outstanding queries
821 if (mSRVCount == 0)
822 {
823 if (mSRVResults.empty())
824 {
825 if (mTransport == UNKNOWN_TRANSPORT)
826 {
827 if (mSips)
828 {
829 mTransport = TLS;
830 mPort = Symbols::DefaultSipsPort;
831 }
832 else
833 {
834 mTransport = UDP;
835 mPort = Symbols::DefaultSipPort;
836 }
837 }
838 else
839 {
840 mPort = getDefaultPort(mTransport, 0);
841 }
842
843 StackLog (<< "No SRV records for " << mTarget << ". Trying A records");
844 if (mInterface.isSupported(mTransport, V6) || mInterface.isSupported(mTransport, V4))
845 {
846 lookupHost(mTarget);
847 }
848 else
849 {
850 primeResults();
851 }
852 }
853 else
854 {
855 std::sort(mSRVResults.begin(),mSRVResults.end()); // !jf! uggh
856 primeResults();
857 }
858 }
859 }
860
861 void DnsResult::onDnsResult(const DNSResult<DnsNaptrRecord>& result)
862 {
863 StackLog (<< "Received NAPTR result for: " << mTarget);
864 StackLog (<< "DnsResult::onDnsResult() " << result.status);
865
866 // This function assumes that the NAPTR query that caused this
867 // callback is the ONLY outstanding query that might cause
868 // a callback into this object
869 if (mType == Destroyed)
870 {
871
872 destroy();
873 return;
874 }
875
876 bool bFail = false;
877 if (result.status == 0)
878 {
879 for (vector<DnsNaptrRecord>::const_iterator it = result.records.begin(); it != result.records.end(); ++it)
880 {
881 NAPTR naptr;
882 naptr.key = (*it).name();
883 naptr.flags = (*it).flags();
884 naptr.order = (*it).order();
885 naptr.pref = (*it).preference();
886 naptr.regex = (*it).regexp();
887 naptr.replacement = (*it).replacement();
888 naptr.service = (*it).service();
889
890 StackLog (<< "Adding NAPTR record: " << naptr);
891 if ( mSips && naptr.service.find("SIPS") == 0)
892 {
893 if (mInterface.isSupported(naptr.service) && naptr < mPreferredNAPTR)
894 {
895 mPreferredNAPTR = naptr;
896 StackLog (<< "Picked preferred: " << mPreferredNAPTR);
897 }
898 }
899 else if (mInterface.isSupported(naptr.service) && naptr < mPreferredNAPTR)
900 {
901 mPreferredNAPTR = naptr;
902 StackLog (<< "Picked preferred: " << mPreferredNAPTR);
903 }
904 }
905
906 // This means that dns / NAPTR is misconfigured for this client
907 if (mPreferredNAPTR.key.empty())
908 {
909 StackLog (<< "No NAPTR records that are supported by this client");
910 transition(Finished);
911 mHandler->handle(this);
912 return;
913 }
914
915 if (result.records.size() == 0) // didn't find any NAPTR records
916 {
917 StackLog (<< "There are no NAPTR records so do an SRV lookup instead");
918 bFail = true;
919 }
920 else
921 {
922 transition(Pending);
923 Item item;
924 item.domain = mPreferredNAPTR.key;
925 item.rrType = T_NAPTR;
926 item.value = mPreferredNAPTR.replacement;
927 clearCurrPath();
928 mCurrResultPath.push(item);
929 mCurrSuccessPath.push(item);
930 mSRVCount++;
931 mDns.lookup<RR_SRV>(mPreferredNAPTR.replacement, Protocol::Sip, this);
932 }
933 }
934 else
935 {
936 if (result.status > 6)
937 {
938 DebugLog (<< "NAPTR lookup failed: " << result.msg);
939 }
940 else
941 {
942 StackLog (<< "NAPTR lookup failed: " << result.msg);
943 }
944 bFail = true;
945 }
946
947 if (bFail)
948 {
949 if (mSips)
950 {
951 if (!mInterface.isSupportedProtocol(TLS))
952 {
953 transition(Finished);
954 mHandler->handle(this);
955 return;
956 }
957
958 mSRVCount++;
959 mDns.lookup<RR_SRV>("_sips._tcp." + mTarget, Protocol::Sip, this);
960 }
961 else
962 {
963 if (mInterface.isSupportedProtocol(TLS))
964 {
965 mDns.lookup<RR_SRV>("_sips._tcp." + mTarget, Protocol::Sip, this);
966 ++mSRVCount;
967 }
968 if (mInterface.isSupportedProtocol(TCP))
969 {
970 mDns.lookup<RR_SRV>("_sip._tcp." + mTarget, Protocol::Sip, this);
971 ++mSRVCount;
972 }
973 if (mInterface.isSupportedProtocol(UDP))
974 {
975 mDns.lookup<RR_SRV>("_sip._udp." + mTarget, Protocol::Sip, this);
976 ++mSRVCount;
977 }
978 }
979 StackLog (<< "Doing SRV queries " << mSRVCount << " for " << mTarget);
980 }
981 }
982
983 void DnsResult::onDnsResult(const DNSResult<DnsCnameRecord>& result)
984 {
985 }
986
987 void DnsResult::clearCurrPath()
988 {
989 while (!mCurrResultPath.empty())
990 {
991 mCurrResultPath.pop();
992 }
993
994 while (!mCurrSuccessPath.empty())
995 {
996 mCurrSuccessPath.pop();
997 }
998 }
999
1000 void DnsResult::blacklistLastReturnedResult()
1001 {
1002 assert(!mCurrResultPath.empty());
1003 Item top = mCurrResultPath.top();
1004 assert(top.rrType==T_A || top.rrType==T_AAAA);
1005 assert(top.domain==mLastReturnedResult.getTargetDomain());
1006 assert(top.value==DnsUtil::inet_ntop(mLastReturnedResult));
1007 vector<Data> records;
1008 records.push_back(top.value);
1009 mDns.blacklist(top.domain, top.rrType, Protocol::Sip, records);
1010 mVip.removeVip(top.domain, top.rrType);
1011 mCurrResultPath.pop();
1012 }
1013
1014 void DnsResult::addToPath(const std::deque<Tuple>& results)
1015 {
1016 assert(mCurrResultPath.size()<=2);
1017 for (std::deque<Tuple>::const_reverse_iterator it = results.rbegin(); it != results.rend(); ++it)
1018 {
1019 Item item;
1020 item.domain = (*it).getTargetDomain();
1021 item.rrType = (*it).isV4()? T_A : T_AAAA;
1022 item.value = DnsUtil::inet_ntop((*it));
1023 mCurrResultPath.push(item);
1024 }
1025 }
1026
1027 std::ostream&
1028 resip::operator<<(std::ostream& strm, const resip::DnsResult& result)
1029 {
1030 strm << result.mTarget << " --> " << Inserter(result.mResults);
1031 return strm;
1032 }
1033
1034
1035 std::ostream&
1036 resip::operator<<(std::ostream& strm, const resip::DnsResult::NAPTR& naptr)
1037 {
1038 strm << "key=" << naptr.key
1039 << " order=" << naptr.order
1040 << " pref=" << naptr.pref
1041 << " flags=" << naptr.flags
1042 << " service=" << naptr.service
1043 << " regex=" << naptr.regex
1044 << " replacement=" << naptr.replacement;
1045 return strm;
1046 }
1047
1048 std::ostream&
1049 resip::operator<<(std::ostream& strm, const resip::DnsResult::SRV& srv)
1050 {
1051 strm << "key=" << srv.key
1052 << " t=" << Tuple::toData(srv.transport)
1053 << " p=" << srv.priority
1054 << " w=" << srv.weight
1055 << " c=" << srv.cumulativeWeight
1056 << " port=" << srv.port
1057 << " target=" << srv.target;
1058 return strm;
1059 }
1060
1061
1062 // Copyright (c) 2003, Jason Fischl
1063 /* ====================================================================
1064 * The Vovida Software License, Version 1.0
1065 *
1066 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
1067 *
1068 * Redistribution and use in source and binary forms, with or without
1069 * modification, are permitted provided that the following conditions
1070 * are met:
1071 *
1072 * 1. Redistributions of source code must retain the above copyright
1073 * notice, this list of conditions and the following disclaimer.
1074 *
1075 * 2. Redistributions in binary form must reproduce the above copyright
1076 * notice, this list of conditions and the following disclaimer in
1077 * the documentation and/or other materials provided with the
1078 * distribution.
1079 *
1080 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
1081 * and "Vovida Open Communication Application Library (VOCAL)" must
1082 * not be used to endorse or promote products derived from this
1083 * software without prior written permission. For written
1084 * permission, please contact vocal@vovida.org.
1085 *
1086 * 4. Products derived from this software may not be called "VOCAL", nor
1087 * may "VOCAL" appear in their name, without prior written
1088 * permission of Vovida Networks, Inc.
1089 *
1090 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
1091 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1092 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
1093 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
1094 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
1095 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
1096 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
1097 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
1098 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
1099 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1100 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
1101 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
1102 * DAMAGE.
1103 *
1104 * ====================================================================
1105 *
1106 * This software consists of voluntary contributions made by Vovida
1107 * Networks, Inc. and many individuals on behalf of Vovida Networks,
1108 * Inc. For more information on Vovida Networks, Inc., please see
1109 * <http://www.vovida.org/>.
1110 *
1111 */

Properties

Name Value
svn:eol-style LF

webmaster AT resiprocate DOT org
ViewVC Help
Powered by ViewVC 1.1.27