|
reSIProcate/stack
9694
|
00001 #if defined(HAVE_CONFIG_H) 00002 #include "config.h" 00003 #endif 00004 00005 #include <algorithm> 00006 #include <stack> 00007 00008 #ifndef WIN32 00009 #include <sys/types.h> 00010 #include <sys/socket.h> 00011 #include <arpa/inet.h> 00012 #ifndef __CYGWIN__ 00013 # include <netinet/in.h> 00014 # include <arpa/nameser.h> 00015 # include <resolv.h> 00016 #endif 00017 #include <netdb.h> 00018 #include <netinet/in.h> 00019 #else 00020 #include <Winsock2.h> 00021 #include <svcguid.h> 00022 #ifdef USE_IPV6 00023 #include <ws2tcpip.h> 00024 #endif 00025 #endif 00026 00027 #include "rutil/DnsUtil.hxx" 00028 #include "rutil/Inserter.hxx" 00029 #include "rutil/Logger.hxx" 00030 #include "rutil/ParseBuffer.hxx" 00031 #include "rutil/Random.hxx" 00032 #include "rutil/compat.hxx" 00033 #include "rutil/Timer.hxx" 00034 #include "rutil/dns/DnsHandler.hxx" 00035 #include "rutil/dns/QueryTypes.hxx" 00036 #include "rutil/dns/DnsStub.hxx" 00037 #include "rutil/dns/DnsNaptrRecord.hxx" 00038 #include "resip/stack/DnsResult.hxx" 00039 #include "resip/stack/DnsInterface.hxx" 00040 #include "resip/stack/TupleMarkManager.hxx" 00041 #include "resip/stack/Tuple.hxx" 00042 #include "resip/stack/Uri.hxx" 00043 #include "rutil/WinLeakCheck.hxx" // not compatible with placement new used below 00044 00045 using namespace resip; 00046 using namespace std; 00047 00048 #define RESIPROCATE_SUBSYSTEM resip::Subsystem::DNS 00049 00050 DnsResult::DnsResult(DnsInterface& interfaceObj, DnsStub& dns, RRVip& vip, DnsHandler* handler) 00051 : mInterface(interfaceObj), 00052 mDns(dns), 00053 mVip(vip), 00054 mHandler(handler), 00055 mSRVCount(0), 00056 mDoingEnum(false), 00057 mSips(false), 00058 mTransport(UNKNOWN_TRANSPORT), 00059 mPort(-1), 00060 mHaveChosenTransport(false), 00061 mType(Pending), 00062 mCumulativeWeight(0), 00063 mHaveReturnedResults(false) 00064 { 00065 } 00066 00067 DnsResult::~DnsResult() 00068 { 00069 //DebugLog (<< "DnsResult::~DnsResult() " << *this); 00070 assert(mType != Pending); 00071 } 00072 00073 void 00074 DnsResult::transition(Type t) 00075 { 00076 if((t == Pending || t== Available) && 00077 (mType== Finished || mType == Destroyed) ) 00078 { 00079 assert(0); 00080 } 00081 00082 mType = t; 00083 } 00084 00085 void 00086 DnsResult::destroy() 00087 { 00088 assert(this); 00089 //DebugLog (<< "DnsResult::destroy() " << *this); 00090 00091 if (mType == Pending) 00092 { 00093 transition(Destroyed); 00094 } 00095 else 00096 { 00097 transition(Finished); 00098 delete this; 00099 } 00100 } 00101 00102 bool 00103 DnsResult::blacklistLast(UInt64 expiry) 00104 { 00105 if(mHaveReturnedResults) 00106 { 00107 assert(!mLastReturnedPath.empty()); 00108 assert(mLastReturnedPath.size()<=3); 00109 Item top = mLastReturnedPath.back(); 00110 00111 mInterface.getMarkManager().mark(mLastResult,expiry,TupleMarkManager::BLACK); 00112 00113 DebugLog( << "Remove vip " << top.domain << "(" << top.rrType << ")"); 00114 mVip.removeVip(top.domain, top.rrType); 00115 return true; 00116 } 00117 00118 return false; 00119 } 00120 00121 bool 00122 DnsResult::greylistLast(UInt64 expiry) 00123 { 00124 if(mHaveReturnedResults) 00125 { 00126 assert(!mLastReturnedPath.empty()); 00127 assert(mLastReturnedPath.size()<=3); 00128 Item top = mLastReturnedPath.back(); 00129 00130 mInterface.getMarkManager().mark(mLastResult,expiry,TupleMarkManager::GREY); 00131 00132 DebugLog( << "Remove vip " << top.domain << "(" << top.rrType << ")"); 00133 mVip.removeVip(top.domain, top.rrType); 00134 return true; 00135 } 00136 00137 return false; 00138 } 00139 00140 DnsResult::Type 00141 DnsResult::available() 00142 { 00143 assert(mType != Destroyed); 00144 if (mType == Available) 00145 { 00146 if (!mResults.empty()) 00147 { 00148 return Available; 00149 } 00150 else 00151 { 00152 primeResults(); 00153 return available(); // recurse 00154 } 00155 } 00156 else 00157 { 00158 return mType; 00159 } 00160 } 00161 00162 Tuple 00163 DnsResult::next() 00164 { 00165 assert(available()==Available); 00166 assert(mCurrentPath.size()<=3); 00167 00168 mLastResult=mResults.front(); 00169 mResults.pop_front(); 00170 00171 if(!mCurrentPath.empty() && 00172 (mCurrentPath.back().rrType==T_A || mCurrentPath.back().rrType==T_AAAA)) 00173 { 00174 mCurrentPath.pop_back(); 00175 } 00176 00177 Item AorAAAA; 00178 AorAAAA.domain = mLastResult.getTargetDomain(); 00179 AorAAAA.rrType = mLastResult.isV4() ? T_A : T_AAAA; 00180 AorAAAA.value = Tuple::inet_ntop(mLastResult); 00181 mCurrentPath.push_back(AorAAAA); 00182 00183 StackLog (<< "Returning next dns entry: " << mLastResult); 00184 mLastReturnedPath=mCurrentPath; 00185 mHaveReturnedResults=true; 00186 return mLastResult; 00187 } 00188 00189 void 00190 DnsResult::whitelistLast() 00191 { 00192 std::vector<Item>::iterator i; 00193 for (i=mLastReturnedPath.begin(); i!=mLastReturnedPath.end(); ++i) 00194 { 00195 DebugLog( << "Whitelisting " << i->domain << "(" << i->rrType << "): " << i->value); 00196 mVip.vip(i->domain, i->rrType, i->value); 00197 } 00198 } 00199 00200 void 00201 DnsResult::lookup(const Uri& uri, const std::vector<Data> &enumSuffixes) 00202 { 00203 DebugLog (<< "DnsResult::lookup " << uri); 00204 //int type = this->mType; 00205 if (!enumSuffixes.empty() && uri.isEnumSearchable()) 00206 { 00207 mInputUri = uri; 00208 mDoingEnum = true; 00209 std::vector<Data> enums = uri.getEnumLookups(enumSuffixes); 00210 assert(enums.size() <= 1); 00211 if (!enums.empty()) 00212 { 00213 InfoLog (<< "Doing ENUM lookup on " << *enums.begin()); 00214 mDns.lookup<RR_NAPTR>(*enums.begin(), Protocol::Enum, this); 00215 return; 00216 } 00217 } 00218 00219 mDoingEnum = false; 00220 lookupInternal(uri); 00221 } 00222 00223 void 00224 DnsResult::lookupInternal(const Uri& uri) 00225 { 00226 //assert(uri.scheme() == Symbols::Sips || uri.scheme() == Symbols::Sip); 00227 mSips = (uri.scheme() == Symbols::Sips); 00228 mTarget = (!mSips && uri.exists(p_maddr)) ? uri.param(p_maddr) : uri.host(); 00229 mSrvKey = Symbols::UNDERSCORE + uri.scheme().substr(0, uri.scheme().size()) + Symbols::DOT; 00230 bool isNumeric = DnsUtil::isIpAddress(mTarget); 00231 00232 if (uri.exists(p_transport)) 00233 { 00234 mTransport = Tuple::toTransport(uri.param(p_transport)); 00235 mHaveChosenTransport=true; 00236 00237 if (isNumeric) // IP address specified 00238 { 00239 mPort = getDefaultPort(mTransport, uri.port()); 00240 Tuple tuple(mTarget, mPort, mTransport, mTarget); 00241 00242 // ?bwc? If this is greylisted, what can we do? This is the only result 00243 if(!(mInterface.getMarkManager().getMarkType(tuple)==TupleMarkManager::BLACK)) 00244 { 00245 DebugLog (<< "Found immediate result: " << tuple); 00246 mResults.push_back(tuple); 00247 transition(Available); 00248 if (mHandler) mHandler->handle(this); 00249 } 00250 else 00251 { 00252 transition(Available); 00253 if (mHandler) mHandler->handle(this); 00254 } 00255 00256 } 00257 else if (uri.port() != 0) 00258 { 00259 mPort = uri.port(); 00260 lookupHost(mTarget); // for current target and port 00261 } 00262 else 00263 { 00264 if (mSips) 00265 { 00266 if (mTransport == UDP) 00267 { 00268 mTransport = DTLS; 00269 if (!mInterface.isSupportedProtocol(mTransport)) 00270 { 00271 transition(Finished); 00272 if (mHandler) mHandler->handle(this); 00273 return; 00274 } 00275 if(!mDns.supportedType(T_SRV)) 00276 { 00277 mPort = getDefaultPort(mTransport, uri.port()); 00278 lookupHost(mTarget); // for current target and port 00279 } 00280 else 00281 { 00282 mSRVCount++; 00283 mDns.lookup<RR_SRV>("_sips._udp." + mTarget, Protocol::Sip, this); 00284 StackLog (<< "Doing SRV lookup of _sips._udp." << mTarget); 00285 } 00286 } 00287 else 00288 { 00289 mTransport = TLS; 00290 mHaveChosenTransport=true; 00291 if (!mInterface.isSupportedProtocol(mTransport)) 00292 { 00293 transition(Finished); 00294 if (mHandler) mHandler->handle(this); 00295 return; 00296 } 00297 if(!mDns.supportedType(T_SRV)) 00298 { 00299 mPort = getDefaultPort(mTransport, uri.port()); 00300 lookupHost(mTarget); // for current target and port 00301 } 00302 else 00303 { 00304 mSRVCount++; 00305 mDns.lookup<RR_SRV>("_sips._tcp." + mTarget, Protocol::Sip, this); 00306 StackLog (<< "Doing SRV lookup of _sips._tcp." << mTarget); 00307 } 00308 } 00309 } 00310 else 00311 { 00312 if (!mInterface.isSupportedProtocol(mTransport)) 00313 { 00314 transition(Finished); 00315 if (mHandler) mHandler->handle(this); 00316 return; 00317 } 00318 00319 if(!mDns.supportedType(T_SRV)) 00320 { 00321 mPort = getDefaultPort(mTransport, uri.port()); 00322 lookupHost(mTarget); // for current target and port 00323 return; 00324 } 00325 00326 switch(mTransport) 00327 { 00328 case TLS: //deprecated, mean TLS over TCP 00329 mSRVCount++; 00330 mDns.lookup<RR_SRV>("_sips._tcp." + mTarget, Protocol::Sip, this); 00331 StackLog (<< "Doing SRV lookup of _sips._tcp." << mTarget); 00332 break; 00333 case DTLS: //deprecated, mean TLS over TCP 00334 mSRVCount++; 00335 mDns.lookup<RR_SRV>("_sip._dtls." + mTarget, Protocol::Sip, this); 00336 StackLog (<< "Doing SRV lookup of _sip._dtls." << mTarget); 00337 break; 00338 case TCP: 00339 mSRVCount++; 00340 mDns.lookup<RR_SRV>("_sip._tcp." + mTarget, Protocol::Sip, this); 00341 StackLog (<< "Doing SRV lookup of _sip._tcp." << mTarget); 00342 break; 00343 case SCTP: 00344 case DCCP: 00345 case UDP: 00346 default: //fall through to UDP for unimplemented & unknown 00347 mSRVCount++; 00348 mDns.lookup<RR_SRV>("_sip._udp." + mTarget, Protocol::Sip, this); 00349 StackLog (<< "Doing SRV lookup of _sip._udp." << mTarget); 00350 } 00351 } 00352 } 00353 } 00354 else // transport parameter is not specified 00355 { 00356 // if hostname is numeric, a port is specified, or NAPTR queries are not support by the DNS layer - skip NAPTR lookup 00357 if (isNumeric || uri.port() != 0 || !mDns.supportedType(T_NAPTR)) 00358 { 00359 TupleMarkManager::MarkType mark=TupleMarkManager::BLACK; 00360 Tuple tuple; 00361 00362 if(isNumeric) 00363 { 00364 if(mSips) 00365 { 00366 if((mInterface.isSupported(TLS, V4) || 00367 mInterface.isSupported(TLS, V6))) 00368 { 00369 mTransport=TLS; 00370 mPort = getDefaultPort(mTransport,uri.port()); 00371 tuple=Tuple(mTarget,mPort,mTransport,mTarget); 00372 mark=mInterface.getMarkManager().getMarkType(tuple); 00373 } 00374 } 00375 else 00376 { 00377 if(mark!=TupleMarkManager::OK && (mInterface.isSupported(UDP, V4) || 00378 mInterface.isSupported(UDP, V6))) 00379 { 00380 mTransport=UDP; 00381 mPort = getDefaultPort(mTransport,uri.port()); 00382 tuple=Tuple(mTarget,mPort,mTransport,mTarget); 00383 mark=mInterface.getMarkManager().getMarkType(tuple); 00384 } 00385 00386 if(mark!=TupleMarkManager::OK && (mInterface.isSupported(TCP, V4) || 00387 mInterface.isSupported(TCP, V6))) 00388 { 00389 mTransport=TCP; 00390 mPort = getDefaultPort(mTransport,uri.port()); 00391 tuple=Tuple(mTarget,mPort,mTransport,mTarget); 00392 mark=mInterface.getMarkManager().getMarkType(tuple); 00393 } 00394 00395 if(mark!=TupleMarkManager::OK && (mInterface.isSupported(TLS, V4) || 00396 mInterface.isSupported(TLS, V6))) 00397 { 00398 mTransport=TLS; 00399 mPort = getDefaultPort(mTransport,uri.port()); 00400 tuple=Tuple(mTarget,mPort,mTransport,mTarget); 00401 mark=mInterface.getMarkManager().getMarkType(tuple); 00402 } 00403 } 00404 00405 if(mark==TupleMarkManager::OK || mark==TupleMarkManager::GREY) 00406 { 00407 mHaveChosenTransport=true; 00408 mResults.push_back(tuple); 00409 transition(Available); 00410 DebugLog (<< "Numeric result so return immediately: " << tuple); 00411 } 00412 else 00413 { 00414 // .bwc. Numeric result is blacklisted. Oh well. 00415 assert(mResults.empty()); 00416 transition(Available); 00417 DebugLog(<< "Numeric result, but this result is currently blacklisted: " << tuple); 00418 } 00419 00420 if (mHandler) mHandler->handle(this); 00421 00422 } 00423 else // host is not numeric, so we need to make a query 00424 { 00425 mTransport=UNKNOWN_TRANSPORT; 00426 00427 if(mSips) 00428 { 00429 if(mInterface.isSupported(TLS, V4) || mInterface.isSupported(TLS, V6)) 00430 { 00431 mTransport=TLS; 00432 } 00433 } 00434 else if(mInterface.isSupported(UDP, V4) || mInterface.isSupported(UDP, V6)) 00435 { 00436 mTransport=UDP; 00437 } 00438 else if(mInterface.isSupported(TCP, V4) || mInterface.isSupported(TCP, V6)) 00439 { 00440 mTransport=TCP; 00441 } 00442 else if(mInterface.isSupported(TLS, V4) || mInterface.isSupported(TLS, V6)) 00443 { 00444 mTransport=TLS; 00445 } 00446 00447 if(mTransport!=UNKNOWN_TRANSPORT) 00448 { 00449 mPort=getDefaultPort(mTransport,uri.port()); 00450 lookupHost(mTarget); 00451 } 00452 else 00453 { 00454 // !bwc! Debatable. 00455 assert(0); 00456 if (mHandler) mHandler->handle(this); 00457 } 00458 } 00459 } 00460 else // do NAPTR 00461 { 00462 mDns.lookup<RR_NAPTR>(mTarget, Protocol::Sip, this); // for current target 00463 } 00464 } 00465 } 00466 00467 void DnsResult::lookupHost(const Data& target) 00468 { 00469 if (mInterface.isSupported(mTransport, V6)) 00470 { 00471 #ifdef USE_IPV6 00472 DebugLog(<< "Doing host (AAAA) lookup: " << target); 00473 mPassHostFromAAAAtoA = target; 00474 mDns.lookup<RR_AAAA>(target, Protocol::Sip, this); 00475 #else 00476 assert(0); 00477 mDns.lookup<RR_A>(target, Protocol::Sip, this); 00478 #endif 00479 } 00480 else if (mInterface.isSupported(mTransport, V4)) 00481 { 00482 mDns.lookup<RR_A>(target, Protocol::Sip, this); 00483 } 00484 else 00485 { 00486 CritLog(<<"Cannot lookup target="<<target 00487 <<" because DnsInterface doesn't support transport="<<mTransport); 00488 assert(0); 00489 } 00490 } 00491 00492 int 00493 DnsResult::getDefaultPort(TransportType transport, int port) 00494 { 00495 if (port == 0) 00496 { 00497 switch (transport) 00498 { 00499 case UDP: 00500 return Symbols::DefaultSipPort; 00501 case TCP: 00502 return mSips ? Symbols::DefaultSipsPort : Symbols::DefaultSipPort; 00503 case TLS: 00504 case DTLS: 00505 return Symbols::DefaultSipsPort; 00506 default: 00507 ErrLog( << "Should not get this - unknown transport" ); 00508 return Symbols::DefaultSipPort; // !cj! todo - remove 00509 assert(0); 00510 } 00511 } 00512 else 00513 { 00514 return port; 00515 } 00516 00517 assert(0); 00518 return 0; 00519 } 00520 00521 void 00522 DnsResult::primeResults() 00523 { 00524 StackLog(<< "Priming " << Inserter(mSRVResults)); 00525 //assert(mType != Pending); 00526 //assert(mType != Finished); 00527 assert(mResults.empty()); 00528 00529 if (!mSRVResults.empty()) 00530 { 00531 SRV next = retrieveSRV(); 00532 StackLog (<< "Primed with SRV=" << next); 00533 transition(Pending); 00534 mPort = next.port; 00535 mTransport = next.transport; 00536 StackLog (<< "No A or AAAA record for " << next.target << " in additional records"); 00537 if (mInterface.isSupported(mTransport, V6) || mInterface.isSupported(mTransport, V4)) 00538 { 00539 Item item; 00540 clearCurrPath(); 00541 // Check if SRV came from a NAPTR look up 00542 std::map<Data, NAPTR>::iterator it = mTopOrderedNAPTRs.find(next.key); 00543 if(it != mTopOrderedNAPTRs.end()) 00544 { 00545 item.domain = (*it).second.key; 00546 item.rrType = T_NAPTR; 00547 item.value = (*it).second.replacement; 00548 mCurrentPath.push_back(item); 00549 } 00550 item.domain = next.key; 00551 item.rrType = T_SRV; 00552 item.value = next.target + ":" + Data(next.port); 00553 mCurrentPath.push_back(item); 00554 lookupHost(next.target); 00555 } 00556 else 00557 { 00558 assert(0); 00559 if (mHandler) mHandler->handle(this); 00560 } 00561 // don't call primeResults since we need to wait for the response to 00562 // AAAA/A query first 00563 } 00564 else if(!mGreylistedTuples.empty()) 00565 { 00566 for(std::vector<Tuple>::iterator i = mGreylistedTuples.begin(); i != mGreylistedTuples.end(); ++i) 00567 { 00568 mResults.push_back(*i); 00569 } 00570 mGreylistedTuples.clear(); 00571 transition(Available); 00572 } 00573 else 00574 { 00575 bool changed = (mType == Pending); 00576 transition(Finished); 00577 if (changed && mHandler) mHandler->handle(this); 00578 } 00579 00580 // Either we are finished or there are results primed 00581 } 00582 00583 // implement the selection algorithm from rfc2782 (SRV records) 00584 DnsResult::SRV 00585 DnsResult::retrieveSRV() 00586 { 00587 // !ah! if mTransport is known -- should we ignore those that don't match?! 00588 assert(!mSRVResults.empty()); 00589 assert(mSRVCount==0); 00590 00591 const SRV& srv = *mSRVResults.begin(); 00592 int priority = srv.priority; 00593 TransportType transport=UNKNOWN_TRANSPORT; 00594 00595 if(!mHaveChosenTransport) 00596 { 00597 // .bwc. We have not chosen a transport yet; this happens when we fail 00598 // to find a NAPTR record, and the transport is not specified in the uri. 00599 // In this contingency, we manufacture best-guess SRV queries for each 00600 // transport we support, and try one transport at a time. This 00601 // means we might try more than one transport for the uri in question. 00602 transport = srv.transport; 00603 } 00604 else 00605 { 00606 // .bwc. We chose our transport before we started looking up SRVs. 00607 // All SRVs must match. 00608 00609 transport=mTransport; 00610 assert(mSRVResults.begin()->transport==transport); 00611 } 00612 00613 if (mCumulativeWeight == 0) 00614 { 00615 for (std::vector<SRV>::iterator i=mSRVResults.begin(); 00616 i!=mSRVResults.end() 00617 && i->priority == priority 00618 && i->transport == transport; i++) 00619 { 00620 assert(i->weight>=0); 00621 mCumulativeWeight += i->weight; 00622 } 00623 } 00624 00625 int selected =0; 00626 if(mCumulativeWeight!=0) 00627 { 00628 selected = Random::getRandom() % (mCumulativeWeight); 00629 } 00630 else 00631 { 00632 // .bwc. All of the remaining SRVs (at this priority/type) have a weight 00633 // of 0. The best we can do here is pick arbitrarily. In this case, we 00634 // will end up picking the first. 00635 // (selected will be less than the weight of the first SRV, causing the 00636 // loop below to break on the first iteration) 00637 selected=-1; 00638 } 00639 00640 StackLog (<< "cumulative weight = " << mCumulativeWeight << " selected=" << selected); 00641 00642 std::vector<SRV>::iterator i; 00643 int cumulativeWeight=0; 00644 for (i=mSRVResults.begin(); i!=mSRVResults.end(); ++i) 00645 { 00646 cumulativeWeight+=i->weight; 00647 if (cumulativeWeight > selected) 00648 { 00649 break; 00650 } 00651 } 00652 00653 if (i == mSRVResults.end()) 00654 { 00655 InfoLog (<< "SRV Results problem selected=" << selected << " cum=" << mCumulativeWeight); 00656 } 00657 assert(i != mSRVResults.end()); 00658 SRV next = *i; 00659 mCumulativeWeight -= next.weight; 00660 mSRVResults.erase(i); 00661 00662 if(!mSRVResults.empty()) 00663 { 00664 int nextPriority=mSRVResults.begin()->priority; 00665 TransportType nextTransport=mSRVResults.begin()->transport; 00666 00667 // .bwc. If we have finished traversing a priority value/transport type, 00668 // we reset the cumulative weight to 0, to prompt its recalculation. 00669 if(priority!=nextPriority || transport!=nextTransport) 00670 { 00671 mCumulativeWeight=0; 00672 } 00673 } 00674 00675 StackLog (<< "SRV: " << Inserter(mSRVResults)); 00676 00677 return next; 00678 } 00679 00680 DnsResult::NAPTR::NAPTR() : order(0), pref(0) 00681 { 00682 } 00683 00684 bool 00685 DnsResult::NAPTR::operator<(const DnsResult::NAPTR& rhs) const 00686 { 00687 if (key.empty()) // default value 00688 { 00689 return false; 00690 } 00691 else if (rhs.key.empty()) // default value 00692 { 00693 return true; 00694 } 00695 else if (order < rhs.order) 00696 { 00697 return true; 00698 } 00699 else if (order == rhs.order) 00700 { 00701 if (pref < rhs.pref) 00702 { 00703 return true; 00704 } 00705 else if (pref == rhs.pref) 00706 { 00707 return replacement < rhs.replacement; 00708 } 00709 } 00710 return false; 00711 } 00712 00713 DnsResult::SRV::SRV() : priority(0), weight(0), port(0) 00714 { 00715 // .kw. member "transport" is not initialized. good default? 00716 } 00717 00718 bool 00719 DnsResult::SRV::operator<(const DnsResult::SRV& rhs) const 00720 { 00721 if (naptrpref < rhs.naptrpref) 00722 { 00723 return true; 00724 } 00725 else if(naptrpref == rhs.naptrpref) 00726 { 00727 if (transport < rhs.transport) 00728 { 00729 return true; 00730 } 00731 else if (transport == rhs.transport) 00732 { 00733 if (priority < rhs.priority) 00734 { 00735 return true; 00736 } 00737 else if (priority == rhs.priority) 00738 { 00739 if (weight < rhs.weight) 00740 { 00741 return true; 00742 } 00743 else if (weight == rhs.weight) 00744 { 00745 if (target < rhs.target) 00746 { 00747 return true; 00748 } 00749 } 00750 } 00751 } 00752 } 00753 return false; 00754 } 00755 00756 void DnsResult::onDnsResult(const DNSResult<DnsHostRecord>& result) 00757 { 00758 if (!mInterface.isSupported(mTransport, V4) && !mInterface.isSupported(mTransport, V6)) 00759 { 00760 return; 00761 } 00762 StackLog (<< "Received dns result for: " << mTarget); 00763 StackLog (<< "DnsResult::onDnsResult() " << result.status); 00764 00765 // This function assumes that the A query that caused this callback 00766 // is the _only_ outstanding DNS query that might result in a 00767 // callback into this function 00768 if ( mType == Destroyed ) 00769 { 00770 destroy(); 00771 return; 00772 } 00773 00774 if (result.status == 0) 00775 { 00776 for (vector<DnsHostRecord>::const_iterator it = result.records.begin(); it != result.records.end(); ++it) 00777 { 00778 in_addr addr; 00779 addr.s_addr = (*it).addr().s_addr; 00780 Tuple tuple(addr, mPort, mTransport, mTarget); 00781 00782 switch(mInterface.getMarkManager().getMarkType(tuple)) 00783 { 00784 case TupleMarkManager::OK: 00785 StackLog (<< "Adding " << tuple << " to result set"); 00786 mResults.push_back(tuple); 00787 break; 00788 case TupleMarkManager::GREY: 00789 StackLog(<< "Adding greylisted tuple " << tuple); 00790 mGreylistedTuples.push_back(tuple); 00791 break; 00792 case TupleMarkManager::BLACK: 00793 default: 00794 ;// .bwc. Do nothing. 00795 } 00796 00797 } 00798 00799 } 00800 else 00801 { 00802 StackLog (<< "Failed async A query: " << result.msg); 00803 } 00804 00805 if (mSRVCount == 0) 00806 { 00807 bool changed = (mType == Pending); 00808 if (mResults.empty()) 00809 { 00810 #ifdef WIN32_SYNCRONOUS_RESOLUTION_ON_ARES_FAILURE 00811 // Try Windows Name Resolution (not asyncronous) 00812 WSAQUERYSET QuerySet = { 0 }; 00813 GUID guidServiceTypeUDP = SVCID_UDP(mPort); 00814 GUID guidServiceTypeTCP = SVCID_TCP(mPort); 00815 HANDLE hQuery; 00816 QuerySet.dwSize = sizeof(WSAQUERYSET); 00817 QuerySet.lpServiceClassId = mTransport == UDP ? &guidServiceTypeUDP : &guidServiceTypeTCP; 00818 QuerySet.dwNameSpace = NS_ALL; 00819 QuerySet.lpszServiceInstanceName = (char *)mTarget.c_str(); 00820 if(WSALookupServiceBegin(&QuerySet, LUP_RETURN_ADDR, &hQuery) == 0) 00821 { 00822 DWORD dwQuerySize = 256; // Starting size 00823 int iRet = 0; 00824 bool fDone = false; 00825 LPWSAQUERYSET pQueryResult = (LPWSAQUERYSET) new char[dwQuerySize]; 00826 while(iRet == 0 && pQueryResult) 00827 { 00828 iRet = WSALookupServiceNext(hQuery, 0, &dwQuerySize, pQueryResult); 00829 if(pQueryResult && iRet == -1 && GetLastError() == WSAEFAULT) 00830 { 00831 delete [] pQueryResult; 00832 pQueryResult = (LPWSAQUERYSET) new char[dwQuerySize]; // Re-allocate new size 00833 iRet = WSALookupServiceNext(hQuery, 0, &dwQuerySize, pQueryResult); 00834 } 00835 if(pQueryResult && iRet == 0) 00836 { 00837 for(DWORD i = 0; i < pQueryResult->dwNumberOfCsAddrs; i++) 00838 { 00839 SOCKADDR_IN *pSockAddrIn = (SOCKADDR_IN *)pQueryResult->lpcsaBuffer[i].RemoteAddr.lpSockaddr; 00840 Tuple tuple(pSockAddrIn->sin_addr, mPort, mTransport, mTarget); 00841 00842 if(mInterface.getMarkManager().getMarkType(tuple)!=TupleMarkManager::BLACK) 00843 { 00844 // .bwc. This is the only result we have, so it doesn't 00845 // matter if it is greylisted. 00846 StackLog (<< "Adding (WIN) " << tuple << " to result set"); 00847 mResults.push_back(tuple); 00848 transition(Available); 00849 } 00850 00851 } 00852 } 00853 } 00854 delete [] pQueryResult; 00855 WSALookupServiceEnd(hQuery); 00856 } 00857 00858 if(mResults.empty()) 00859 { 00860 if(mSRVResults.empty()) 00861 { 00862 if (mGreylistedTuples.empty()) 00863 { 00864 transition(Finished); 00865 clearCurrPath(); 00866 } 00867 else 00868 { 00869 for(std::vector<Tuple>::iterator i = mGreylistedTuples.begin(); i != mGreylistedTuples.end(); ++i) 00870 { 00871 mResults.push_back(*i); 00872 } 00873 mGreylistedTuples.clear(); 00874 transition(Available); 00875 } 00876 } 00877 else 00878 { 00879 transition(Available); 00880 } 00881 } 00882 #else 00883 // .bwc. If this A query failed, don't give up if there are more SRVs! 00884 if(mSRVResults.empty()) 00885 { 00886 if (mGreylistedTuples.empty()) 00887 { 00888 transition(Finished); 00889 clearCurrPath(); 00890 } 00891 else 00892 { 00893 for(std::vector<Tuple>::iterator i = mGreylistedTuples.begin(); i != mGreylistedTuples.end(); ++i) 00894 { 00895 mResults.push_back(*i); 00896 } 00897 mGreylistedTuples.clear(); 00898 transition(Available); 00899 } 00900 } 00901 else 00902 { 00903 transition(Available); 00904 } 00905 #endif 00906 } 00907 else 00908 { 00909 transition(Available); 00910 } 00911 if (changed && mHandler) mHandler->handle(this); 00912 } 00913 } 00914 00915 void DnsResult::onDnsResult(const DNSResult<DnsAAAARecord>& result) 00916 { 00917 #ifdef USE_IPV6 00918 StackLog (<< "Received AAAA result for: " << mTarget); 00919 if (!mInterface.isSupported(mTransport, V6)) 00920 { 00921 return; 00922 } 00923 StackLog (<< "DnsResult::onDnsResult() " << result.status); 00924 assert(mInterface.isSupported(mTransport, V6)); 00925 00926 // This function assumes that the AAAA query that caused this callback 00927 // is the _only_ outstanding DNS query that might result in a 00928 // callback into this function 00929 if ( mType == Destroyed ) 00930 { 00931 destroy(); 00932 return; 00933 } 00934 00935 if (result.status == 0) 00936 { 00937 for (vector<DnsAAAARecord>::const_iterator it = result.records.begin(); it != result.records.end(); ++it) 00938 { 00939 Tuple tuple((*it).v6Address(), mPort, mTransport, mTarget); 00940 00941 switch(mInterface.getMarkManager().getMarkType(tuple)) 00942 { 00943 case TupleMarkManager::OK: 00944 StackLog (<< "Adding " << tuple << " to result set"); 00945 mResults.push_back(tuple); 00946 break; 00947 case TupleMarkManager::GREY: 00948 StackLog(<< "Adding greylisted tuple " << tuple); 00949 mGreylistedTuples.push_back(tuple); 00950 break; 00951 case TupleMarkManager::BLACK: 00952 default: 00953 ;// .bwc. Do nothing. 00954 } 00955 00956 } 00957 00958 } 00959 else 00960 { 00961 StackLog (<< "Failed async AAAA query: " << result.msg); 00962 } 00963 // funnel through to host processing 00964 mDns.lookup<RR_A>(mPassHostFromAAAAtoA, Protocol::Sip, this); 00965 #else 00966 assert(0); 00967 #endif 00968 } 00969 00970 void DnsResult::onDnsResult(const DNSResult<DnsSrvRecord>& result) 00971 { 00972 StackLog (<< "Received SRV result for: " << mTarget); 00973 assert(mSRVCount>=0); 00974 mSRVCount--; 00975 StackLog (<< "DnsResult::onDnsResult() " << mSRVCount << " status=" << result.status); 00976 00977 // There could be multiple SRV queries outstanding, but there will be no 00978 // other DNS queries outstanding that might cause a callback into this 00979 // object. 00980 if (mType == Destroyed && mSRVCount == 0) 00981 { 00982 destroy(); 00983 return; 00984 } 00985 00986 if (result.status == 0) 00987 { 00988 for (vector<DnsSrvRecord>::const_iterator it = result.records.begin(); it != result.records.end(); ++it) 00989 { 00990 SRV srv; 00991 srv.key = (*it).name(); 00992 srv.priority = (*it).priority(); 00993 srv.weight = (*it).weight(); 00994 srv.port = (*it).port(); 00995 srv.target = (*it).target(); 00996 // fillin srv.naptrpref - if found in NAPTR map, then SRV query was driven from a NAPTR lookup 00997 std::map<Data, NAPTR>::iterator itNaptr = mTopOrderedNAPTRs.find(srv.key); 00998 if(itNaptr != mTopOrderedNAPTRs.end()) 00999 { 01000 srv.naptrpref = itNaptr->second.pref; 01001 } 01002 else 01003 { 01004 srv.naptrpref = 0; 01005 } 01006 if (srv.key.find("_sips._udp") != Data::npos) 01007 { 01008 srv.transport = DTLS; 01009 } 01010 else if (srv.key.find("_sips._tcp") != Data::npos) 01011 { 01012 srv.transport = TLS; 01013 } 01014 else if (srv.key.find("_udp") != Data::npos) 01015 { 01016 srv.transport = UDP; 01017 } 01018 else if (srv.key.find("_dtls") != Data::npos) 01019 { 01020 srv.transport = DTLS; 01021 } 01022 else if (srv.key.find("_tls") != Data::npos) 01023 { 01024 srv.transport = TLS; 01025 } 01026 else if (srv.key.find("_tcp") != Data::npos) 01027 { 01028 srv.transport = TCP; 01029 } 01030 else 01031 { 01032 StackLog (<< "Skipping SRV " << srv.key); 01033 continue; 01034 } 01035 01036 if(!mHaveChosenTransport || srv.transport==mTransport) 01037 { 01038 // .bwc. If we have not committed to a given transport, or we have 01039 // committed to a given transport which this SRV matches, we will 01040 // add this SRV. We do not add SRVs that do not match a transport 01041 // we have committed to. 01042 mSRVResults.push_back(srv); 01043 } 01044 } 01045 } 01046 else 01047 { 01048 StackLog (<< "SRV lookup failed: " << result.domain << " " << result.status); 01049 } 01050 01051 // no outstanding queries 01052 if (mSRVCount == 0) 01053 { 01054 if (mSRVResults.empty()) 01055 { 01056 if (mTransport == UNKNOWN_TRANSPORT) 01057 { 01058 if (mSips) 01059 { 01060 mTransport = TLS; 01061 mHaveChosenTransport=true; 01062 mPort = Symbols::DefaultSipsPort; 01063 } 01064 else 01065 { 01066 if (mInterface.isSupported(UDP, V4)) 01067 { 01068 mTransport = UDP; 01069 mHaveChosenTransport=true; 01070 } 01071 else if (mInterface.isSupported(TCP, V4)) 01072 { 01073 mTransport = TCP; 01074 mHaveChosenTransport=true; 01075 } 01076 /* Yes, there is the possibility that at this point mTransport 01077 is still UNKNOWN_TRANSPORT, but this is likely to fail just as 01078 well as defaulting to UDP when there isn't an interface that 01079 supports UDP. 01080 It doesn't support failover to TCP when there is a UDP failure, 01081 but neither does the original code. 01082 This fixes the case where there is no UDP transport, but 01083 there was no explicit ;transport=tcp on the uri. 01084 (mjf) 01085 */ 01086 mPort = Symbols::DefaultSipPort; 01087 } 01088 } 01089 else 01090 { 01091 mPort = getDefaultPort(mTransport, 0); 01092 } 01093 01094 StackLog (<< "No SRV records for " << mTarget << ". Trying A records"); 01095 if (mInterface.isSupported(mTransport, V6) || mInterface.isSupported(mTransport, V4)) 01096 { 01097 lookupHost(mTarget); 01098 } 01099 else 01100 { 01101 primeResults(); 01102 } 01103 } 01104 else 01105 { 01106 std::sort(mSRVResults.begin(),mSRVResults.end()); // !jf! uggh 01107 primeResults(); 01108 } 01109 } 01110 } 01111 01112 static Data enumService1("e2u+sip"); 01113 static Data enumService2("sip+e2u"); 01114 void 01115 DnsResult::onEnumResult(const DNSResult<DnsNaptrRecord>& result) 01116 { 01117 mDoingEnum = false; 01118 01119 if (result.status == 0) 01120 { 01121 DnsNaptrRecord best; 01122 best.order() = -1; 01123 01124 for (vector<DnsNaptrRecord>::const_iterator i = result.records.begin(); i != result.records.end(); ++i) 01125 { 01126 InfoLog (<< "service=" << i->service() 01127 << " order=" << i->order() 01128 << " flags=" << i->flags() 01129 << " regexp substitution=" << i->regexp().replacement() 01130 << " replacement=" << i->replacement()); 01131 01132 if ( (isEqualNoCase(i->service(), enumService1) || 01133 isEqualNoCase(i->service(), enumService2) ) && // only E2U records 01134 //i->flags().find("u") != Data::npos && // must be terminal record 01135 i->replacement().empty() ) 01136 01137 { 01138 if (best.order() == -1) 01139 { 01140 best = *i; 01141 } 01142 else if (i->order() < best.order()) 01143 { 01144 best = *i; 01145 } 01146 else if (i->order() == best.order() && 01147 i->preference() < best.preference()) 01148 { 01149 best = *i; 01150 } 01151 } 01152 } 01153 01154 if (best.order() != -1) 01155 { 01156 InfoLog (<< "Found an enum result: " << best.regexp().replacement()); 01157 try 01158 { 01159 Uri rewrite(best.regexp().apply(Data::from(mInputUri))); 01160 InfoLog (<< "Rewrote uri " << mInputUri << " -> " << rewrite); 01161 mHandler->rewriteRequest(rewrite); 01162 lookupInternal(rewrite); 01163 } 01164 catch (ParseException& e ) 01165 { 01166 ErrLog(<<"Caught exception: "<< e); 01167 lookupInternal(mInputUri); 01168 } 01169 } 01170 else 01171 { 01172 lookupInternal(mInputUri); 01173 } 01174 } 01175 else 01176 { 01177 lookupInternal(mInputUri); 01178 } 01179 } 01180 01181 void 01182 DnsResult::onNaptrResult(const DNSResult<DnsNaptrRecord>& result) 01183 { 01184 bool bFail = false; 01185 if (result.status == 0) 01186 { 01187 int preferredNAPTROrder=65536; // order is unsigned short - so max is 65535, initialize to one higher 01188 std::list<NAPTR> supportedNAPTRs; 01189 for (vector<DnsNaptrRecord>::const_iterator it = result.records.begin(); it != result.records.end(); ++it) 01190 { 01191 NAPTR naptr; 01192 naptr.key = (*it).name(); 01193 naptr.flags = (*it).flags(); 01194 naptr.order = (*it).order(); 01195 naptr.pref = (*it).preference(); 01196 naptr.regex = (*it).regexp(); 01197 naptr.replacement = (*it).replacement(); 01198 naptr.service = (*it).service(); 01199 01200 StackLog (<< "Received NAPTR record: " << naptr); 01201 01202 if ( !mSips || naptr.service.find("SIPS") == 0) 01203 { 01204 if (mInterface.isSupported(naptr.service)) 01205 { 01206 supportedNAPTRs.push_back(naptr); 01207 if(naptr.order < preferredNAPTROrder) 01208 { 01209 preferredNAPTROrder = naptr.order; 01210 } 01211 } 01212 } 01213 } 01214 01215 // This means that dns / NAPTR is misconfigured for this client 01216 if (supportedNAPTRs.empty()) 01217 { 01218 StackLog (<< "There are no NAPTR records supported by this client so do an SRV lookup instead"); 01219 bFail = true; 01220 } 01221 else 01222 { 01223 // Go through NAPTR's and issue SRV queries for each supported record, that has equal 01224 // ordering to the most preferred order discovered above 01225 transition(Pending); 01226 for (std::list<NAPTR>::const_iterator it = supportedNAPTRs.begin(); it != supportedNAPTRs.end(); ++it) 01227 { 01228 if(preferredNAPTROrder == (*it).order) 01229 { 01230 StackLog (<< "NAPTR record is supported and matches highes priority order. doing SRV query: " << (*it)); 01231 mTopOrderedNAPTRs[(*it).replacement] = (*it); 01232 mSRVCount++; 01233 mDns.lookup<RR_SRV>((*it).replacement, Protocol::Sip, this); 01234 } 01235 } 01236 } 01237 } 01238 else 01239 { 01240 if (result.status > 6) 01241 { 01242 DebugLog (<< "NAPTR lookup failed: " << result.domain << " " << result.msg); 01243 } 01244 else 01245 { 01246 StackLog (<< "NAPTR lookup failed: " << result.domain << " " << result.msg); 01247 } 01248 bFail = true; 01249 } 01250 01251 if (bFail) 01252 { 01253 if (mSips) 01254 { 01255 if (!mInterface.isSupportedProtocol(TLS)) 01256 { 01257 transition(Finished); 01258 if (mHandler) mHandler->handle(this); 01259 return; 01260 } 01261 01262 mSRVCount++; 01263 mDns.lookup<RR_SRV>("_sips._tcp." + mTarget, Protocol::Sip, this); 01264 StackLog (<< "Doing SRV lookup of _sips._tcp." << mTarget); 01265 } 01266 else 01267 { 01268 if (mInterface.isSupportedProtocol(TLS)) 01269 { 01270 mDns.lookup<RR_SRV>("_sips._tcp." + mTarget, Protocol::Sip, this); 01271 ++mSRVCount; 01272 StackLog (<< "Doing SRV lookup of _sips._tcp." << mTarget); 01273 } 01274 if (mInterface.isSupportedProtocol(DTLS)) 01275 { 01276 mDns.lookup<RR_SRV>("_sips._udp." + mTarget, Protocol::Sip, this); 01277 ++mSRVCount; 01278 StackLog (<< "Doing SRV lookup of _sips._udp." << mTarget); 01279 } 01280 if (mInterface.isSupportedProtocol(TCP)) 01281 { 01282 mDns.lookup<RR_SRV>("_sip._tcp." + mTarget, Protocol::Sip, this); 01283 ++mSRVCount; 01284 StackLog (<< "Doing SRV lookup of _sip._tcp." << mTarget); 01285 } 01286 if (mInterface.isSupportedProtocol(UDP)) 01287 { 01288 mDns.lookup<RR_SRV>("_sip._udp." + mTarget, Protocol::Sip, this); 01289 ++mSRVCount; 01290 StackLog (<< "Doing SRV lookup of _sip._udp." << mTarget); 01291 } 01292 } 01293 } 01294 } 01295 01296 void 01297 DnsResult::onDnsResult(const DNSResult<DnsNaptrRecord>& result) 01298 { 01299 StackLog (<< "Received NAPTR result for: " << mInputUri << " target=" << mTarget); 01300 StackLog (<< "DnsResult::onDnsResult() " << result.status); 01301 01302 // This function assumes that the NAPTR query that caused this 01303 // callback is the ONLY outstanding query that might cause 01304 // a callback into this object 01305 if (mType == Destroyed) 01306 { 01307 destroy(); 01308 return; 01309 } 01310 01311 if (mDoingEnum) 01312 { 01313 onEnumResult(result); 01314 } 01315 else 01316 { 01317 onNaptrResult(result); 01318 } 01319 01320 } 01321 01322 void DnsResult::onDnsResult(const DNSResult<DnsCnameRecord>& result) 01323 { 01324 } 01325 01326 void DnsResult::clearCurrPath() 01327 { 01328 while (!mCurrentPath.empty()) 01329 { 01330 mCurrentPath.pop_back(); 01331 } 01332 } 01333 01334 EncodeStream& 01335 resip::operator<<(EncodeStream& strm, const resip::DnsResult& result) 01336 { 01337 strm << result.mTarget << " --> " << Inserter(result.mResults); 01338 return strm; 01339 } 01340 01341 01342 EncodeStream& 01343 resip::operator<<(EncodeStream& strm, const resip::DnsResult::NAPTR& naptr) 01344 { 01345 strm << "key=" << naptr.key 01346 << " order=" << naptr.order 01347 << " pref=" << naptr.pref 01348 << " flags=" << naptr.flags 01349 << " service=" << naptr.service 01350 << " regex=" << naptr.regex.regexp() << " -> " << naptr.regex.replacement() 01351 << " replacement=" << naptr.replacement; 01352 return strm; 01353 } 01354 01355 EncodeStream& 01356 resip::operator<<(EncodeStream& strm, const resip::DnsResult::SRV& srv) 01357 { 01358 strm << "key=" << srv.key 01359 << " t=" << Tuple::toData(srv.transport) 01360 << " p=" << srv.priority 01361 << " w=" << srv.weight 01362 << " port=" << srv.port 01363 << " target=" << srv.target; 01364 return strm; 01365 } 01366 01367 // Copyright (c) 2003, Jason Fischl 01368 /* ==================================================================== 01369 * The Vovida Software License, Version 1.0 01370 * 01371 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved. 01372 * 01373 * Redistribution and use in source and binary forms, with or without 01374 * modification, are permitted provided that the following conditions 01375 * are met: 01376 * 01377 * 1. Redistributions of source code must retain the above copyright 01378 * notice, this list of conditions and the following disclaimer. 01379 * 01380 * 2. Redistributions in binary form must reproduce the above copyright 01381 * notice, this list of conditions and the following disclaimer in 01382 * the documentation and/or other materials provided with the 01383 * distribution. 01384 * 01385 * 3. The names "VOCAL", "Vovida Open Communication Application Library", 01386 * and "Vovida Open Communication Application Library (VOCAL)" must 01387 * not be used to endorse or promote products derived from this 01388 * software without prior written permission. For written 01389 * permission, please contact vocal@vovida.org. 01390 * 01391 * 4. Products derived from this software may not be called "VOCAL", nor 01392 * may "VOCAL" appear in their name, without prior written 01393 * permission of Vovida Networks, Inc. 01394 * 01395 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED 01396 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 01397 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND 01398 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA 01399 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES 01400 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, 01401 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 01402 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 01403 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 01404 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 01405 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 01406 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 01407 * DAMAGE. 01408 * 01409 * ==================================================================== 01410 * 01411 * This software consists of voluntary contributions made by Vovida 01412 * Networks, Inc. and many individuals on behalf of Vovida Networks, 01413 * Inc. For more information on Vovida Networks, Inc., please see 01414 * <http://www.vovida.org/>. 01415 * 01416 */
1.7.5.1