|
reSIProcate/rutil
9694
|
00001 #if defined(HAVE_CONFIG_H) 00002 #include "config.h" 00003 #endif 00004 00005 #include "AresCompat.hxx" 00006 00007 #ifndef WIN32 00008 #include <sys/types.h> 00009 #include <sys/socket.h> 00010 #include <arpa/inet.h> 00011 #ifndef __CYGWIN__ 00012 # include <netinet/in.h> 00013 # include <arpa/nameser.h> 00014 # include <resolv.h> 00015 #endif 00016 #include <netdb.h> 00017 #include <netinet/in.h> 00018 #else 00019 #include <Winsock2.h> 00020 #include <svcguid.h> 00021 #ifdef USE_IPV6 00022 #include <ws2tcpip.h> 00023 #endif 00024 #endif 00025 00026 #include <set> 00027 #include <vector> 00028 #include <list> 00029 #include <map> 00030 #include <cassert> 00031 #include "rutil/BaseException.hxx" 00032 #include "rutil/Data.hxx" 00033 #include "rutil/Timer.hxx" 00034 #include "rutil/dns/RRFactory.hxx" 00035 #include "rutil/dns/RROverlay.hxx" 00036 #include "rutil/dns/RRFactory.hxx" 00037 #include "rutil/dns/DnsResourceRecord.hxx" 00038 #include "rutil/dns/DnsAAAARecord.hxx" 00039 #include "rutil/dns/DnsHostRecord.hxx" 00040 #include "rutil/dns/DnsNaptrRecord.hxx" 00041 #include "rutil/dns/DnsSrvRecord.hxx" 00042 #include "rutil/dns/DnsCnameRecord.hxx" 00043 #include "rutil/dns/RRCache.hxx" 00044 #include "rutil/WinLeakCheck.hxx" 00045 00046 using namespace resip; 00047 using namespace std; 00048 00049 RRCache::RRCache() 00050 : mHead(), 00051 mLruHead(LruListType::makeList(&mHead)), 00052 mUserDefinedTTL(DEFAULT_USER_DEFINED_TTL), 00053 mSize(DEFAULT_SIZE) 00054 { 00055 mFactoryMap[T_CNAME] = &mCnameRecordFactory; 00056 mFactoryMap[T_NAPTR] = &mNaptrRecordFacotry; 00057 mFactoryMap[T_SRV] = &mSrvRecordFactory; 00058 #ifdef USE_IPV6 00059 mFactoryMap[T_AAAA] = &mAAAARecordFactory; 00060 #endif 00061 mFactoryMap[T_A] = &mHostRecordFactory; 00062 } 00063 00064 RRCache::~RRCache() 00065 { 00066 cleanup(); 00067 } 00068 00069 void 00070 RRCache::updateCacheFromHostFile(const DnsHostRecord &record) 00071 { 00072 //FactoryMap::iterator it = mFactoryMap.find(T_A); 00073 RRList* key = new RRList(record, 3600); 00074 RRSet::iterator lb = mRRSet.lower_bound(key); 00075 if (lb != mRRSet.end() && 00076 !(mRRSet.key_comp()(key, *lb))) 00077 { 00078 (*lb)->update(record, 3600); 00079 touch(*lb); 00080 } 00081 else 00082 { 00083 RRList* val = new RRList(record, 3600); 00084 mRRSet.insert(val); 00085 mLruHead->push_back(val); 00086 purge(); 00087 } 00088 delete key; 00089 } 00090 00091 void 00092 RRCache::updateCache(const Data& target, 00093 const int rrType, 00094 Itr begin, 00095 Itr end) 00096 { 00097 Data domain = (*begin).domain(); 00098 FactoryMap::iterator it = mFactoryMap.find(rrType); 00099 assert(it != mFactoryMap.end()); 00100 RRList* key = new RRList(domain, rrType); 00101 RRSet::iterator lb = mRRSet.lower_bound(key); 00102 if (lb != mRRSet.end() && 00103 !(mRRSet.key_comp()(key, *lb))) 00104 { 00105 (*lb)->update(it->second, begin, end, mUserDefinedTTL); 00106 touch(*lb); 00107 } 00108 else 00109 { 00110 RRList* val = new RRList(it->second, domain, rrType, begin, end, mUserDefinedTTL); 00111 mRRSet.insert(val); 00112 mLruHead->push_back(val); 00113 purge(); 00114 } 00115 delete key; 00116 } 00117 00118 void 00119 RRCache::cacheTTL(const Data& target, 00120 const int rrType, 00121 const int status, 00122 RROverlay overlay) 00123 { 00124 int ttl = getTTL(overlay); 00125 00126 if (ttl < 0) 00127 { 00128 return; 00129 } 00130 00131 if (ttl < mUserDefinedTTL) 00132 { 00133 ttl = mUserDefinedTTL; 00134 } 00135 00136 RRList* val = new RRList(target, rrType, ttl, status); 00137 RRSet::iterator it = mRRSet.find(val); 00138 if (it != mRRSet.end()) 00139 { 00140 (*it)->remove(); 00141 delete *it; 00142 mRRSet.erase(it); 00143 } 00144 mRRSet.insert(val); 00145 mLruHead->push_back(val); 00146 purge(); 00147 } 00148 00149 bool 00150 RRCache::lookup(const Data& target, 00151 const int type, 00152 const int protocol, 00153 Result& records, 00154 int& status) 00155 { 00156 records.empty(); 00157 status = 0; 00158 RRList* key = new RRList(target, type); 00159 RRSet::iterator it = mRRSet.find(key); 00160 delete key; 00161 if (it == mRRSet.end()) 00162 { 00163 return false; 00164 } 00165 else 00166 { 00167 if (Timer::getTimeSecs() >= (*it)->absoluteExpiry()) 00168 { 00169 delete *it; 00170 mRRSet.erase(it); 00171 return false; 00172 } 00173 else 00174 { 00175 records = (*it)->records(protocol); 00176 status = (*it)->status(); 00177 touch(*it); 00178 return true; 00179 } 00180 } 00181 } 00182 00183 void 00184 RRCache::clearCache() 00185 { 00186 cleanup(); 00187 } 00188 00189 void 00190 RRCache::touch(RRList* node) 00191 { 00192 node->remove(); 00193 mLruHead->push_back(node); 00194 } 00195 00196 void 00197 RRCache::cleanup() 00198 { 00199 for (std::set<RRList*, CompareT>::iterator it = mRRSet.begin(); it != mRRSet.end(); it++) 00200 { 00201 (*it)->remove(); 00202 delete *it; 00203 } 00204 mRRSet.clear(); 00205 } 00206 00207 int 00208 RRCache::getTTL(const RROverlay& overlay) 00209 { 00210 // overlay is a soa answer. 00211 if (overlay.type() != T_SOA) return -1; 00212 char* name = 0; 00213 long len = 0; 00214 int status = ares_expand_name(overlay.data(), overlay.msg(), overlay.msgLength(), &name, &len); 00215 assert( status == ARES_SUCCESS ); 00216 const unsigned char* pPos = overlay.data() + len; 00217 free(name); name = 0; 00218 status = ares_expand_name(pPos, overlay.msg(), overlay.msgLength(), &name, &len); 00219 assert( status == ARES_SUCCESS ); 00220 free(name); 00221 pPos += len; 00222 pPos += 16; // skip four 32 bit entities. 00223 return DNS__32BIT(pPos); 00224 } 00225 00226 void 00227 RRCache::purge() 00228 { 00229 if (mRRSet.size() < mSize) return; 00230 RRList* lst = *(mLruHead->begin()); 00231 RRSet::iterator it = mRRSet.find(lst); 00232 assert(it != mRRSet.end()); 00233 lst->remove(); 00234 delete *it; 00235 mRRSet.erase(it); 00236 } 00237 00238 void 00239 RRCache::logCache() 00240 { 00241 for (std::set<RRList*, CompareT>::iterator it = mRRSet.begin(); it != mRRSet.end(); it++) 00242 { 00243 (*it)->log(); 00244 } 00245 } 00246 00247 void 00248 RRCache::getCacheDump(Data& dnsCacheDump) 00249 { 00250 DataStream strm(dnsCacheDump); 00251 for (std::set<RRList*, CompareT>::iterator it = mRRSet.begin(); it != mRRSet.end(); it++) 00252 { 00253 (*it)->encodeRRList(strm); 00254 } 00255 strm.flush(); 00256 } 00257 00258 /* ==================================================================== 00259 * The Vovida Software License, Version 1.0 00260 * 00261 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved. 00262 * Copyright (c) 2010 SIP Spectrum, Inc. All rights reserved. 00263 * 00264 * Redistribution and use in source and binary forms, with or without 00265 * modification, are permitted provided that the following conditions 00266 * are met: 00267 * 00268 * 1. Redistributions of source code must retain the above copyright 00269 * notice, this list of conditions and the following disclaimer. 00270 * 00271 * 2. Redistributions in binary form must reproduce the above copyright 00272 * notice, this list of conditions and the following disclaimer in 00273 * the documentation and/or other materials provided with the 00274 * distribution. 00275 * 00276 * 3. The names "VOCAL", "Vovida Open Communication Application Library", 00277 * and "Vovida Open Communication Application Library (VOCAL)" must 00278 * not be used to endorse or promote products derived from this 00279 * software without prior written permission. For written 00280 * permission, please contact vocal@vovida.org. 00281 * 00282 * 4. Products derived from this software may not be called "VOCAL", nor 00283 * may "VOCAL" appear in their name, without prior written 00284 * permission of Vovida Networks, Inc. 00285 * 00286 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED 00287 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00288 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND 00289 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA 00290 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES 00291 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, 00292 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00293 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00294 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 00295 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00296 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 00297 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 00298 * DAMAGE. 00299 * 00300 * ==================================================================== 00301 * 00302 * This software consists of voluntary contributions made by Vovida 00303 * Networks, Inc. and many individuals on behalf of Vovida Networks, 00304 * Inc. For more information on Vovida Networks, Inc., please see 00305 * <http://www.vovida.org/>. 00306 * 00307 */
1.7.5.1