1#if defined(HAVE_CONFIG_H)
10#include <sys/socket.h>
13# include <netinet/in.h>
14# include <arpa/nameser.h>
18#include <netinet/in.h>
47#define RESIPROCATE_SUBSYSTEM resip::Subsystem::DNS
50 : mResultSink(resultSink),
95 : mInterface(interfaceObj),
104 mHaveChosenTransport(false),
106 mCumulativeWeight(0),
107 mHaveReturnedResults(false)
118DnsResult::transition(Type t)
149 if(mHaveReturnedResults)
153 GreyOrBlacklistCommand* command =
new GreyOrBlacklistCommand(mVip, mInterface.
getMarkManager(),
154 mLastReturnedPath.back(),
167 if(mHaveReturnedResults)
171 GreyOrBlacklistCommand* command =
new GreyOrBlacklistCommand(mVip, mInterface.
getMarkManager(),
172 mLastReturnedPath.back(),
183DnsResult::GreyOrBlacklistCommand::execute()
185 mMarkManager.mark(mResult, mExpiry, mMarkType);
187 DebugLog( <<
"Remove vip " << mPathTop.domain <<
"(" << mPathTop.rrType <<
")");
188 mVip.removeVip(mPathTop.domain, mPathTop.rrType);
197 if (!mResults.empty())
219 mLastResult=mResults.front();
220 mResults.pop_front();
222 if(!mCurrentPath.empty() &&
223 (mCurrentPath.back().rrType==
T_A || mCurrentPath.back().rrType==
T_AAAA))
225 mCurrentPath.pop_back();
232 mCurrentPath.push_back(AorAAAA);
234 StackLog (<<
"Returning next dns entry: " << mLastResult);
235 mLastReturnedPath=mCurrentPath;
236 mHaveReturnedResults=
true;
243 WhitelistCommand* command =
new WhitelistCommand(mVip, mInterface.
getMarkManager(), mLastReturnedPath, mLastResult);
248DnsResult::WhitelistCommand::execute()
250 std::vector<Item>::iterator i;
251 for (i=mPath.begin(); i!=mPath.end(); ++i)
253 DebugLog( <<
"Whitelisting " << i->domain <<
"(" << i->rrType <<
"): " << i->value);
254 mVip.vip(i->domain, i->rrType, i->value);
263 DebugLog (<<
"DnsResult::lookup " << uri);
271DnsResult::lookupInternalWithEnum(
const Uri& uri)
288 mDoingEnum = (int)enums.size();
289 for(std::vector<Data>::iterator it = enums.begin(); it != enums.end(); it++)
291 InfoLog (<<
"Doing ENUM lookup on " << *it);
303DnsResult::lookupInternal(
const Uri& uri)
307 mTarget = (!mSips && uri.
exists(p_maddr)) ? uri.
param(p_maddr) : uri.
host();
309 if (mTarget.
size() >= 2 && mTarget[0] ==
'[' && mTarget[mTarget.
size()-1] ==
']')
316 if (uri.
exists(p_transport))
319 mHaveChosenTransport=
true;
323 mPort = getDefaultPort(mTransport, uri.
port());
327 Tuple tuple(mTarget, mPort, mTransport, mTarget, uri.
netNs());
335 DebugLog (<<
"Found immediate result: " << tuple);
336 mResults.push_back(tuple);
338 if (mHandler) mHandler->
handle(
this);
343 if (mHandler) mHandler->
handle(
this);
347 else if (uri.
port() != 0)
356 if (mTransport ==
UDP)
361 DebugLog(<<
"transport " <<
toData(mTransport) <<
" not supported");
363 if (mHandler) mHandler->
handle(
this);
368 mPort = getDefaultPort(mTransport, uri.
port());
375 StackLog (<<
"Doing SRV lookup of _sips._udp." << mTarget);
381 mHaveChosenTransport=
true;
384 DebugLog(<<
"transport " <<
toData(mTransport) <<
" not supported");
386 if (mHandler) mHandler->
handle(
this);
391 mPort = getDefaultPort(mTransport, uri.
port());
398 StackLog (<<
"Doing SRV lookup of _sips._tcp." << mTarget);
406 DebugLog(<<
"transport " <<
toData(mTransport) <<
" not supported");
408 if (mHandler) mHandler->
handle(
this);
414 mPort = getDefaultPort(mTransport, uri.
port());
424 StackLog (<<
"Doing SRV lookup of _sips._tcp." << mTarget);
429 StackLog (<<
"Doing SRV lookup of _sip._dtls." << mTarget);
434 StackLog (<<
"Doing SRV lookup of _sip._tcp." << mTarget);
442 StackLog (<<
"Doing SRV lookup of _sip._udp." << mTarget);
463 mPort = getDefaultPort(mTransport,uri.
port());
464 tuple=
Tuple(mTarget,mPort,mTransport,mTarget);
470 bool udpSupported =
false;;
475 mPort = getDefaultPort(mTransport,uri.
port());
476 tuple=
Tuple(mTarget,mPort,mTransport,mTarget);
484 bool tcpSupported =
false;
489 mPort = getDefaultPort(mTransport,uri.
port());
492 tuple=
Tuple(mTarget, mPort, mTransport, mTarget, uri.
netNs());
505 mPort = getDefaultPort(mTransport,uri.
port());
506 tuple=
Tuple(mTarget,mPort,mTransport,mTarget);
516 if (udpSupported && mTransport !=
UDP)
519 mPort = getDefaultPort(mTransport, uri.
port());
520 tuple =
Tuple(mTarget, mPort, mTransport, mTarget);
523 else if (tcpSupported && mTransport !=
TCP)
526 mPort = getDefaultPort(mTransport, uri.
port());
527 tuple =
Tuple(mTarget, mPort, mTransport, mTarget, uri.
netNs());
536 mHaveChosenTransport=
true;
537 mResults.push_back(tuple);
539 DebugLog (<<
"Numeric result so return immediately: " << tuple);
546 DebugLog(<<
"Numeric result, but this result is currently blacklisted: " << tuple);
549 if (mHandler) mHandler->
handle(
this);
578 mPort=getDefaultPort(mTransport,uri.
port());
585 if (mHandler) mHandler->
handle(
this);
596void DnsResult::lookupHost(
const Data& target)
602 mPassHostFromAAAAtoA =
target;
616 <<
" because DnsInterface doesn't support transport="<<mTransport);
640 ErrLog( <<
"Should not get this - unknown transport" );
655DnsResult::primeResults()
662 if (!mSRVResults.empty())
664 SRV
next = retrieveSRV();
668 mTransport =
next.transport;
669 StackLog (<<
"No A or AAAA record for " <<
next.target <<
" in additional records");
675 std::map<Data, NAPTR>::iterator it = mTopOrderedNAPTRs.find(
next.key);
676 if(it != mTopOrderedNAPTRs.end())
678 item.domain = (*it).second.key;
680 item.value = (*it).second.replacement;
681 mCurrentPath.push_back(item);
683 item.domain =
next.key;
686 mCurrentPath.push_back(item);
687 lookupHost(
next.target);
692 if (mHandler) mHandler->
handle(
this);
697 else if(!mGreylistedTuples.empty())
699 for(std::vector<Tuple>::iterator i = mGreylistedTuples.begin(); i != mGreylistedTuples.end(); ++i)
701 mResults.push_back(*i);
703 mGreylistedTuples.clear();
708 bool changed = (mType ==
Pending);
710 if (changed && mHandler) mHandler->
handle(
this);
718DnsResult::retrieveSRV()
724 const SRV& srv = *mSRVResults.begin();
725 int priority = srv.priority;
728 if(!mHaveChosenTransport)
735 transport = srv.transport;
742 transport=mTransport;
743 resip_assert(mSRVResults.begin()->transport==transport);
746 if (mCumulativeWeight == 0)
748 for (std::vector<SRV>::iterator i=mSRVResults.begin();
750 && i->priority == priority
751 && i->transport == transport; i++)
754 mCumulativeWeight += i->weight;
759 if(mCumulativeWeight!=0)
773 StackLog (<<
"cumulative weight = " << mCumulativeWeight <<
" selected=" << selected);
775 std::vector<SRV>::iterator i;
776 int cumulativeWeight=0;
777 for (i=mSRVResults.begin(); i!=mSRVResults.end(); ++i)
779 cumulativeWeight+=i->weight;
780 if (cumulativeWeight > selected)
786 if (i == mSRVResults.end())
788 InfoLog (<<
"SRV Results problem selected=" << selected <<
" cum=" << mCumulativeWeight);
792 mCumulativeWeight -=
next.weight;
793 mSRVResults.erase(i);
795 if(!mSRVResults.empty())
797 int nextPriority=mSRVResults.begin()->priority;
802 if(priority!=nextPriority || transport!=nextTransport)
828 else if (order < rhs.
order)
832 else if (order == rhs.
order)
838 else if (pref == rhs.
pref)
876 else if (weight == rhs.
weight)
893 StackLog(<<
"DnsResult::onDnsResult(): A record, for unsupported transport: target=" << mTarget <<
", status=" << result.
status);
896 StackLog (<<
"DnsResult::onDnsResult(): A record, target=" << mTarget <<
", status=" << result.
status);
909 for (vector<DnsHostRecord>::const_iterator it = result.
records.begin(); it != result.
records.end(); ++it)
912 addr.s_addr = (*it).addr().s_addr;
913 Tuple tuple(addr, mPort, mTransport, mTarget);
918 StackLog (<<
"Adding " << tuple <<
" to result set");
919 mResults.push_back(tuple);
922 StackLog(<<
"Adding greylisted tuple " << tuple);
923 mGreylistedTuples.push_back(tuple);
935 StackLog (<<
"Failed async A query: " << result.
msg);
940 bool changed = (mType ==
Pending);
941 if (mResults.empty())
943#ifdef WIN32_SYNCRONOUS_RESOLUTION_ON_ARES_FAILURE
945 WSAQUERYSET QuerySet = { 0 };
946 GUID guidServiceTypeUDP = SVCID_UDP(mPort);
947 GUID guidServiceTypeTCP = SVCID_TCP(mPort);
949 QuerySet.dwSize =
sizeof(WSAQUERYSET);
950 QuerySet.lpServiceClassId = mTransport ==
UDP ? &guidServiceTypeUDP : &guidServiceTypeTCP;
951 QuerySet.dwNameSpace = NS_ALL;
952 QuerySet.lpszServiceInstanceName = (
char *)mTarget.
c_str();
953 if(WSALookupServiceBegin(&QuerySet, LUP_RETURN_ADDR, &hQuery) == 0)
955 DWORD dwQuerySize = 256;
958 LPWSAQUERYSET pQueryResult = (LPWSAQUERYSET)
new char[dwQuerySize];
959 while(iRet == 0 && pQueryResult)
961 iRet = WSALookupServiceNext(hQuery, 0, &dwQuerySize, pQueryResult);
962 if(pQueryResult && iRet == -1 && GetLastError() == WSAEFAULT)
964 delete [] pQueryResult;
965 pQueryResult = (LPWSAQUERYSET)
new char[dwQuerySize];
966 iRet = WSALookupServiceNext(hQuery, 0, &dwQuerySize, pQueryResult);
968 if(pQueryResult && iRet == 0)
970 for(DWORD i = 0; i < pQueryResult->dwNumberOfCsAddrs; i++)
972 SOCKADDR_IN *pSockAddrIn = (SOCKADDR_IN *)pQueryResult->lpcsaBuffer[i].RemoteAddr.lpSockaddr;
973 Tuple tuple(pSockAddrIn->sin_addr, mPort, mTransport, mTarget);
979 StackLog (<<
"Adding (WIN) " << tuple <<
" to result set");
980 mResults.push_back(tuple);
987 delete [] pQueryResult;
988 WSALookupServiceEnd(hQuery);
993 if(mSRVResults.empty())
995 if (mGreylistedTuples.empty())
1002 for(std::vector<Tuple>::iterator i = mGreylistedTuples.begin(); i != mGreylistedTuples.end(); ++i)
1004 mResults.push_back(*i);
1006 mGreylistedTuples.clear();
1017 if(mSRVResults.empty())
1019 if (mGreylistedTuples.empty())
1026 for(std::vector<Tuple>::iterator i = mGreylistedTuples.begin(); i != mGreylistedTuples.end(); ++i)
1028 mResults.push_back(*i);
1030 mGreylistedTuples.clear();
1044 if (changed && mHandler) mHandler->
handle(
this);
1053 StackLog(<<
"DnsResult::onDnsResult(): AAAA record, for unsupported transport: target=" << mTarget <<
", status=" << result.
status);
1056 StackLog(<<
"DnsResult::onDnsResult(): AAAA record, target=" << mTarget <<
", status=" << result.
status);
1070 for (vector<DnsAAAARecord>::const_iterator it = result.
records.begin(); it != result.
records.end(); ++it)
1072 Tuple tuple((*it).v6Address(), mPort, mTransport, mTarget);
1077 StackLog (<<
"Adding " << tuple <<
" to result set");
1078 mResults.push_back(tuple);
1081 StackLog(<<
"Adding greylisted tuple " << tuple);
1082 mGreylistedTuples.push_back(tuple);
1092 StackLog (<<
"Failed async AAAA query: " << result.
msg);
1106 StackLog(<<
"DnsResult::onDnsResult(): SRV record, target=" << mTarget <<
", numRemainingSRV=" << mSRVCount <<
", status = " << result.
status);
1111 if (mType ==
Destroyed && mSRVCount == 0)
1119 for (vector<DnsSrvRecord>::const_iterator it = result.
records.begin(); it != result.
records.end(); ++it)
1122 srv.key = (*it).name();
1123 srv.key.lowercase();
1124 srv.priority = (*it).priority();
1125 srv.weight = (*it).weight();
1126 srv.port = (*it).port();
1127 srv.target = (*it).target();
1129 std::map<Data, NAPTR>::iterator itNaptr = mTopOrderedNAPTRs.find(srv.key);
1130 if(itNaptr != mTopOrderedNAPTRs.end())
1132 srv.naptrpref = itNaptr->second.pref;
1138 if (srv.key.find(
"_sips._udp") !=
Data::npos)
1140 srv.transport =
DTLS;
1142 else if (srv.key.find(
"_sips._tcp") !=
Data::npos)
1144 srv.transport =
TLS;
1148 srv.transport =
UDP;
1150 else if (srv.key.find(
"_dtls") !=
Data::npos)
1152 srv.transport =
DTLS;
1156 srv.transport =
TLS;
1160 srv.transport =
TCP;
1164 StackLog (<<
"Skipping SRV " << srv.key);
1168 if(!mHaveChosenTransport || srv.transport==mTransport)
1174 mSRVResults.push_back(srv);
1186 if (mSRVResults.empty())
1193 mHaveChosenTransport=
true;
1201 mHaveChosenTransport=
true;
1206 mHaveChosenTransport=
true;
1223 mPort = getDefaultPort(mTransport, 0);
1226 StackLog (<<
"No SRV records for " << mTarget <<
". Trying A records");
1229 lookupHost(mTarget);
1238 std::sort(mSRVResults.begin(),mSRVResults.end());
1253 for (vector<DnsNaptrRecord>::const_iterator i = result.
records.begin(); i != result.
records.end(); ++i)
1255 InfoLog(<<
"service=" << i->service()
1256 <<
" order=" << i->order()
1257 <<
" flags=" << i->flags()
1258 <<
" regexp substitution=" << i->regexp().replacement()
1259 <<
" replacement=" << i->replacement());
1264 i->replacement().empty())
1267 if (best.
order() == -1)
1271 else if (i->order() < best.
order())
1275 else if (i->order() == best.
order() &&
1284 Lock l(mEnumDestinationsMutex);
1289 StackLog(<<
"DnsResult::onDnsResult(): ENUM NAPTR record, target=" << mTarget <<
", numRemainingEnum=" << mDoingEnum <<
", status = " << result.
status);
1291 if (best.
order() != -1)
1297 InfoLog(<<
"Rewrote uri " << mInputUri <<
" -> " << rewrite);
1298 mEnumDestinations[order] = rewrite;
1302 ErrLog(<<
"Caught exception: " << e);
1311 DebugLog(<<
"All ENUM DNS queries done, checking for results...");
1312 std::map<int,Uri>::iterator it = mEnumDestinations.begin();
1313 if(it != mEnumDestinations.end())
1315 DebugLog(<<
"Using result for suffix " << (it->first + 1));
1317 lookupInternal(it->second);
1321 DebugLog(<<
"No valid ENUM query result, falling back to request URI");
1322 lookupInternal(mInputUri);
1333 int preferredNAPTROrder=65536;
1334 std::list<NAPTR> supportedNAPTRs;
1335 for (vector<DnsNaptrRecord>::const_iterator it = result.
records.begin(); it != result.
records.end(); ++it)
1338 naptr.key = (*it).name();
1339 naptr.flags = (*it).flags();
1340 naptr.order = (*it).order();
1341 naptr.pref = (*it).preference();
1342 naptr.regex = (*it).regexp();
1343 naptr.replacement = (*it).replacement();
1344 naptr.service = (*it).service();
1346 StackLog (<<
"Received NAPTR record: " << naptr);
1348 if ( !mSips || naptr.service.find(
"SIPS") == 0)
1352 supportedNAPTRs.push_back(naptr);
1353 if(naptr.order < preferredNAPTROrder)
1355 preferredNAPTROrder = naptr.order;
1362 if (supportedNAPTRs.empty())
1364 StackLog (<<
"There are no NAPTR records supported by this client so do an SRV lookup instead");
1372 for (std::list<NAPTR>::const_iterator it = supportedNAPTRs.begin(); it != supportedNAPTRs.end(); ++it)
1374 if(preferredNAPTROrder == (*it).order)
1376 StackLog (<<
"NAPTR record is supported and matches highest priority order. doing SRV query: " << (*it));
1377 mTopOrderedNAPTRs[(*it).replacement] = (*it);
1404 if (mHandler) mHandler->
handle(
this);
1410 StackLog (<<
"Doing SRV lookup of _sips._tcp." << mTarget);
1418 StackLog (<<
"Doing SRV lookup of _sips._tcp." << mTarget);
1424 StackLog (<<
"Doing SRV lookup of _sips._udp." << mTarget);
1430 StackLog (<<
"Doing SRV lookup of _sip._tcp." << mTarget);
1436 StackLog (<<
"Doing SRV lookup of _sip._udp." << mTarget);
1445 StackLog(<<
"DnsResult::onDnsResult(): NAPTR record, inputUri=" << mInputUri <<
", target=" << mTarget <<
", status=" << result.
status);
1456 onNaptrResult(result);
1463void DnsResult::clearCurrPath()
1465 while (!mCurrentPath.empty())
1467 mCurrentPath.pop_back();
1474 strm << result.mTarget <<
" --> " <<
Inserter(result.mResults);
1482 strm <<
"key=" << naptr.
key
1483 <<
" order=" << naptr.
order
1484 <<
" pref=" << naptr.
pref
1485 <<
" flags=" << naptr.
flags
1486 <<
" service=" << naptr.
service
1495 strm <<
"key=" << srv.
key
1499 <<
" port=" << srv.
port
1500 <<
" target=" << srv.
target;
static Data enumService1("e2u+sip")
static Data enumService2("sip+e2u")
#define resip_assert(x)
This file needs to work for both C and C++ code.
#define resip_assert_not_null(x)
An alternative to std::string, encapsulates an arbitrary buffer of bytes.
const char * c_str() const
Returns a null-terminated string representing.
Data substr(size_type first, size_type count=Data::npos) const
Copies a portion of this Data into a new Data.
bool empty() const noexcept
Checks whether the Data is empty.
size_type size() const noexcept
Returns the number of bytes in this Data.
static Data from(const T &x)
Converts from arbitrary other type to Data.
static const size_type npos
Represents an impossible position; returned to indicate failure to find.
virtual void handle(DnsResult *result)=0
virtual void rewriteRequest(const Uri &uri)=0
TupleMarkManager & getMarkManager()
bool isSupportedProtocol(TransportType t)
bool getUdpOnlyOnNumeric() const
bool isSupported(const Data &service)
Data apply(const Data &input) const
const Data & regexp() const
const Data & replacement() const
const RegExp & regexp() const
DnsNaptrRecord::RegExp regex
bool operator<(const NAPTR &rhs) const
bool operator<(const SRV &rhs) const
void lookup(const Uri &uri)
bool greylistLast(uint64_t expiry)
friend class LookupCommand
bool blacklistLast(uint64_t expiry)
DnsResult(DnsInterface &interfaceObj, DnsStub &dns, RRVip &vip, DnsHandler *handler)
const std::map< Data, Data > & getEnumDomains() const
const std::vector< Data > & getEnumSuffixes() const
void lookup(const Data &target, DnsResultSink *sink)
virtual void queueCommand(Command *command)
static bool isIpAddress(const Data &ipAddress)
virtual void onEnumResult(const DNSResult< DnsNaptrRecord > &result, int order)=0
EnumResult(EnumResultSink &resultSink, int order)
void onDnsResult(const DNSResult< DnsHostRecord > &)
BaseException used to indicate parse failures.
static int getRandom()
Returns a postive integer (31 bits) of randomness.
static const int SipWssPort
static const int DefaultSipsPort
static const int SipWsPort
static const int DefaultSipPort
static const char * UNDERSCORE
MarkType getMarkType(const Tuple &tuple)
Represents a network address.
static const Data & toData(TransportType)
Converts the TransportType to a string representation of the transport type, e.g.
static Data inet_ntop(const Tuple &tuple)
Converts the binary socket address to presentation format, via the DnsUtil::inet_ntop() method.
static TransportType toTransport(const Data &)
Converts a string representation of transport type, i.e.
const Data & getTargetDomain() const
Get the domain name this address tuple intends to represent.
Represents the "SIP-URI" and "SIPS-URI" elements in the RFC 3261 grammar.
bool isEnumSearchable() const
Returns true if the uri can be converted into a string that can be used as an enum lookup.
std::vector< Data > getEnumLookups(const std::vector< Data > &suffixes) const
Return a vector of domains to do a NAPTR lookup for enum.
bool exists(const Param< Uri > ¶mType) const
const Data & param(const ExtensionParameter ¶m) const
Const accessor for non-natively-supported parameter types.
This file is used to handle compatibility fixes/tweaks so reSIProcate can function on multiple platfo...
dcm! – add UnusedChecking(_enum) below;
const resip::Data & toData(const TransportType typeEnum)
InserterClass< T > Inserter(const T &t)
Templatized function to construct an instance of InserterClass for a container to be inserted.
bool isEqualNoCase(const Data &left, const Data &right)
std::unique_lock< Mutex > Lock
A convenience class to lock a Lockable (such as a Mutex) on object creation, and unlock on destructio...
unsigned long long uint64_t
TransportType
An enumeration of transport protocols.
EncodeStream & operator<<(EncodeStream &strm, const BaseException &e)