From 7e65eccab8c635edfd95588dac9dd3b5d09a4369 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Sun, 5 Sep 2010 18:01:34 +0200 Subject: [PATCH] added onw functions for parsing DNS reply as it seems, several functions declared in arpa/nameser.h are not present in libresolv.so on Linux. those functions are considered to be internal to libresolv. --- core/Makefile | 4 +- core/sip/parse_dns.cpp | 166 +++++++++++++ core/sip/parse_dns.h | 43 ++++ core/sip/resolver.cpp | 533 +++++++++++++++++++---------------------- core/sip/resolver.h | 8 +- 5 files changed, 472 insertions(+), 282 deletions(-) create mode 100644 core/sip/parse_dns.cpp create mode 100644 core/sip/parse_dns.h diff --git a/core/Makefile b/core/Makefile index ec05a9dc..c8cf51bb 100644 --- a/core/Makefile +++ b/core/Makefile @@ -50,9 +50,11 @@ deps: $(DEPS) COREPATH=. include ../Makefile.defs -LDFLAGS += -lresolv + CPPFLAGS += -I$(COREPATH) +EXTRA_LDFLAGS += -lresolv + # implicit rules %.o : %.cpp %.d ../Makefile.defs $(CXX) -c -o $@ $< $(CPPFLAGS) $(CXXFLAGS) diff --git a/core/sip/parse_dns.cpp b/core/sip/parse_dns.cpp new file mode 100644 index 00000000..5f67b277 --- /dev/null +++ b/core/sip/parse_dns.cpp @@ -0,0 +1,166 @@ +#include "parse_dns.h" +#include + +#include "log.h" + +#define SECTION_COUNTS_OFF 4 +#define HEADER_OFFSET 12 + +unsigned short dns_msg_count(u_char* begin, dns_section_type sect); +int dns_skip_name(u_char** p, u_char* end); +int dns_expand_name(u_char** ptr, u_char* begin, u_char* end, + u_char* buf, unsigned int len); + +inline unsigned short dns_get_16(u_char* p) +{ + unsigned short res = *(p++); + res <<= 8; + res |= *p; + + return res; +} + +inline unsigned int dns_get_32(u_char* p) +{ + unsigned int res = dns_get_16(p); + res <<= 16; + res |= dns_get_16(p+2); + + return res; +} + +int dns_msg_parse(u_char* msg, int len, dns_parse_fct fct, void* data) +{ + u_char* begin = msg; + u_char* p = begin + HEADER_OFFSET; + u_char* end = msg + len; + + if(p >= end) return -1; + + // skip query section + for(int i=0; i end) return -1; + } + + dns_record rr; + for(int s = (int)dns_s_an; s < (int)__dns_max_sections; ++s){ + for(int i=0; i end) return -1; + + rr.type = dns_get_16(p); + p += 2; + + rr.rr_class = dns_get_16(p); + p += 2; + + rr.ttl = dns_get_32(p); + p+= 4; + + // fetch rdata len + if(p+2 > end) return -1; + rr.rdata_len = *(p++) << 8; + rr.rdata_len |= *(p++); + rr.rdata = p; + + // skip rdata + if((p += rr.rdata_len) > end) return -1; + + // call provided function + if(fct && (*fct)(&rr,(dns_section_type)s,begin,end,data)) return -1; + } + } + + return 0; +} + +unsigned short dns_msg_count(u_char* begin, dns_section_type sect) +{ + u_char* p = begin + SECTION_COUNTS_OFF + 2*sect; + + return ((u_short)*p)<<8 | ((u_short)*(p+1)); +} + +int dns_skip_name(u_char** p, u_char* end) +{ + while(*p < end) { + + if(!**p) { // zero label + if(++(*p) < end) return 0; + return -1; + } + else if(**p & 0xC0){ // ptr + if((*p += 2) < end) return 0; + return -1; + } + else { // label + *p += **p+1; + } + } + + return -1; +} + +int dns_expand_name(u_char** ptr, u_char* begin, u_char* end, + u_char* start_buf, unsigned int len) +{ + u_char* buf = start_buf; + u_char* p = *ptr; + bool is_ptr=false; + + while(p < end) { + + if(!*p) { // reached the end of a label + if(len){ + *buf = '\0'; // zero-term + if(!is_ptr){ *ptr = p+1; } + return (buf-start_buf); + } + return -1; + } + + if( (*p & 0xC0) == 0xC0 ){ // ptr + + unsigned short l_off = (((unsigned short)*p & 0x3F) << 8); + if(++p >= end) return -1; + l_off |= *p; + if(++p >= end) return -1; + + if(begin + l_off + 1 >= end) return -1; + + if(!is_ptr){ + *ptr = p; + is_ptr = true; + } + p = begin + l_off; + continue; + } + + if( (*p & 0x3F) != *p ){ // NOT a label + return -1; + } + + if(p + *p + 1 >= end) return -1; + if(len <= *p) return -1; + + memcpy(buf,p+1,*p); + len -= *p; + buf += *p; + p += *p + 1; + + if(*p){ + if(!(--len)) return -1; + *(buf++) = '.'; + } + } + + return -1; +} + diff --git a/core/sip/parse_dns.h b/core/sip/parse_dns.h new file mode 100644 index 00000000..667be7ad --- /dev/null +++ b/core/sip/parse_dns.h @@ -0,0 +1,43 @@ +#ifndef _parse_dns_h_ +#define _parse_dns_h_ + +#include + +enum dns_section_type { + + dns_s_qd=0, // question section + dns_s_an, // answer section + dns_s_ns, // authority section + dns_s_ar, // additional section + __dns_max_sections +}; + +enum dns_rr_type { + + dns_r_a = 1, + dns_r_ns = 2, + dns_r_cname = 5, + dns_r_aaaa = 28, + dns_r_srv = 33 +}; + +struct dns_record +{ + char name[NS_MAXDNAME]; + unsigned short type; + unsigned short rr_class; + unsigned int ttl; + + unsigned short rdata_len; + unsigned char* rdata; +}; + +class dns_entry; + +typedef int (*dns_parse_fct)(dns_record* rr, dns_section_type t, u_char* begin, u_char* end, void* data); + +int dns_msg_parse(u_char* msg, int len, dns_parse_fct fct, void* data); +int dns_expand_name(u_char** ptr, u_char* begin, u_char* end, + u_char* buf, unsigned int len); + +#endif diff --git a/core/sip/resolver.cpp b/core/sip/resolver.cpp index 1b4d13f0..f081c231 100644 --- a/core/sip/resolver.cpp +++ b/core/sip/resolver.cpp @@ -28,6 +28,8 @@ #include "resolver.h" #include "hash.h" +#include "parse_dns.h" + #include #include #include @@ -35,7 +37,7 @@ #include #include #include -#include // Darwin +//#include // Darwin only #include @@ -50,7 +52,6 @@ using std::list; // (the limit is the # bits in dns_handle::srv_used) #define MAX_SRV_RR (sizeof(unsigned int)*8) - struct ip_entry : public dns_base_entry { @@ -78,30 +79,43 @@ public: : dns_entry() {} - int next_ip(dns_handle* h, sockaddr_storage* sa); -}; + void init(){}; -int dns_ip_entry::next_ip(dns_handle* h, sockaddr_storage* sa) -{ - if(h->ip_e != this){ - if(h->ip_e) dec_ref(h->ip_e); - h->ip_e = this; - h->ip_n = 0; - } + dns_base_entry* get_rr(dns_record* rr, u_char* begin, u_char* end); + + int next_ip(dns_handle* h, sockaddr_storage* sa) + { + if(h->ip_e != this){ + if(h->ip_e) dec_ref(h->ip_e); + h->ip_e = this; + h->ip_n = 0; + } - int& index = h->ip_n; - if(index >= (int)ip_vec.size()) return -1; + int& index = h->ip_n; + if(index >= (int)ip_vec.size()) return -1; - //copy address - ((ip_entry*)ip_vec[index++])->to_sa(sa); + //copy address + ((ip_entry*)ip_vec[index++])->to_sa(sa); - // reached the end? - if(index >= (int)ip_vec.size()) { - index = -1; - } + // reached the end? + if(index >= (int)ip_vec.size()) { + index = -1; + } - return 0; -} + return 0; + } +}; + +static bool srv_less(const dns_base_entry* le, const dns_base_entry* re) +{ + const srv_entry* l_srv = (const srv_entry*)le; + const srv_entry* r_srv = (const srv_entry*)re; + + if(l_srv->p != r_srv->p) + return l_srv->p < r_srv->p; + else + return l_srv->w < r_srv->w; +}; class dns_srv_entry : public dns_entry @@ -111,106 +125,104 @@ public: : dns_entry() {} - int next_ip(dns_handle* h, sockaddr_storage* sa); -}; - -int dns_srv_entry::next_ip(dns_handle* h, sockaddr_storage* sa) -{ - int& index = h->srv_n; - if(index >= (int)ip_vec.size()) return -1; - - if(h->srv_e != this){ - if(h->srv_e) dec_ref(h->srv_e); - h->srv_e = this; - h->srv_n = 0; - h->srv_used = 0; - } - else if(h->ip_n != -1){ - ((sockaddr_in*)sa)->sin_port = h->port; - return h->ip_e->next_ip(h,sa); + void init(){ + stable_sort(ip_vec.begin(),ip_vec.end(),srv_less); } - // reset IP record - if(h->ip_e){ - dec_ref(h->ip_e); - h->ip_e = NULL; - h->ip_n = 0; - } - - list > srv_lst; - int i = index; + dns_base_entry* get_rr(dns_record* rr, u_char* begin, u_char* end); - // fetch current priority - unsigned short p = ((srv_entry*)ip_vec[i])->p; - unsigned int w_sum = 0; - - // and fetch records with same priority - // which have not been chosen yet - int srv_lst_size=0; - unsigned int used_mask=(1<p) ){ + int next_ip(dns_handle* h, sockaddr_storage* sa) + { + int& index = h->srv_n; + if(index >= (int)ip_vec.size()) return -1; - DBG("used_mask & h->srv_used: %i & %i",used_mask,h->srv_used); - if(!(used_mask & h->srv_used)){ - w_sum += ((srv_entry*)ip_vec[i])->w; - srv_lst.push_back(std::make_pair(w_sum,i)); - srv_lst_size++; + if(h->srv_e != this){ + if(h->srv_e) dec_ref(h->srv_e); + h->srv_e = this; + h->srv_n = 0; + h->srv_used = 0; } - - if((++i >= (int)ip_vec.size()) || - (i >= (int)MAX_SRV_RR)){ - break; + else if(h->ip_n != -1){ + ((sockaddr_in*)sa)->sin_port = h->port; + return h->ip_e->next_ip(h,sa); } - - DBG("(p==((srv_entry*)ip_vec[i])->p): %i, %i",p,((srv_entry*)ip_vec[i])->p); - used_mask = used_mask << 1; - } - - srv_entry* e=NULL; - DBG("srv_lst_size: %i",srv_lst_size); - if((srv_lst_size > 1) && w_sum){ - // multiple records: apply weigthed load balancing - // - remember the entries which have already been used - unsigned int r = random() % (w_sum+1); - - DBG("random SRV lottery: %u / %u",r,w_sum); - list >::iterator srv_lst_it = srv_lst.begin(); - while(srv_lst_it != srv_lst.end()){ - if(srv_lst_it->first >= r){ - DBG("h->srv_used: %i (before)",h->srv_used); - h->srv_used |= (1<<(srv_lst_it->second)); - DBG("h->srv_used: %i (after)",h->srv_used); - e = (srv_entry*)ip_vec[srv_lst_it->second]; + + // reset IP record + if(h->ip_e){ + dec_ref(h->ip_e); + h->ip_e = NULL; + h->ip_n = 0; + } + + list > srv_lst; + int i = index; + + // fetch current priority + unsigned short p = ((srv_entry*)ip_vec[i])->p; + unsigned int w_sum = 0; + + // and fetch records with same priority + // which have not been chosen yet + int srv_lst_size=0; + unsigned int used_mask=(1<p) ){ + + if(!(used_mask & h->srv_used)){ + w_sum += ((srv_entry*)ip_vec[i])->w; + srv_lst.push_back(std::make_pair(w_sum,i)); + srv_lst_size++; + } + + if((++i >= (int)ip_vec.size()) || + (i >= (int)MAX_SRV_RR)){ break; } - ++srv_lst_it; - } - - // should never trigger - assert(e); - } - else { - // single record or all weights == 0 - e = (srv_entry*)ip_vec[srv_lst.begin()->second]; - - if( (i<(int)ip_vec.size()) && (i<(int)MAX_SRV_RR)){ - index = i; + + used_mask = used_mask << 1; } - else if(!w_sum){ - index++; + + srv_entry* e=NULL; + if((srv_lst_size > 1) && w_sum){ + // multiple records: apply weigthed load balancing + // - remember the entries which have already been used + unsigned int r = random() % (w_sum+1); + + list >::iterator srv_lst_it = srv_lst.begin(); + while(srv_lst_it != srv_lst.end()){ + if(srv_lst_it->first >= r){ + h->srv_used |= (1<<(srv_lst_it->second)); + e = (srv_entry*)ip_vec[srv_lst_it->second]; + break; + } + ++srv_lst_it; + } + + // will only happen if the algorithm + // is broken + if(!e) + return -1; } else { - index = -1; + // single record or all weights == 0 + e = (srv_entry*)ip_vec[srv_lst.begin()->second]; + + if( (i<(int)ip_vec.size()) && (i<(int)MAX_SRV_RR)){ + index = i; + } + else if(!w_sum){ + index++; + } + else { + index = -1; + } } - DBG("index = %i",index); + + //TODO: find a solution for IPv6 + h->port = htons(e->port); + ((sockaddr_in*)sa)->sin_port = h->port; + return resolver::instance()->resolve_name(e->target.c_str(),h,sa,IPv4); } - - //TODO: find a solution for IPv6 - h->port = htons(e->port); - ((sockaddr_in*)sa)->sin_port = h->port; - return resolver::instance()->resolve_name(e->target.c_str(),h,sa,IPv4); -} - +}; dns_entry::dns_entry() : dns_base_entry() @@ -219,7 +231,6 @@ dns_entry::dns_entry() dns_entry::~dns_entry() { - DBG("~dns_entry()"); for(vector::iterator it = ip_vec.begin(); it != ip_vec.end(); ++it) { @@ -227,6 +238,31 @@ dns_entry::~dns_entry() } } +dns_entry* dns_entry::make_entry(ns_type t) +{ + switch(t){ + case ns_t_srv: + return new dns_srv_entry(); + case ns_t_a: + //case ns_t_aaaa: + return new dns_ip_entry(); + default: + return NULL; + } +} + +void dns_entry::add_rr(dns_record* rr, u_char* begin, u_char* end, long now) +{ + dns_base_entry* e = get_rr(rr,begin,end); + if(!e) return; + + e->expire = rr->ttl + now; + if(expire < e->expire) + expire = e->expire; + + ip_vec.push_back(e); +} + dns_bucket::dns_bucket(unsigned long id) : dns_bucket_base(id) { @@ -294,17 +330,6 @@ dns_entry* dns_bucket::find(const string& name) return e; } -_resolver::_resolver() - : cache(DNS_CACHE_SIZE) -{ - start(); -} - -_resolver::~_resolver() -{ - -} - static void dns_error(int error, const char* domain) { switch(error){ @@ -330,47 +355,11 @@ void ip_entry::to_sa(sockaddr_storage* sa) memcpy(&(sa_in->sin_addr),&addr,sizeof(in_addr)); } -static int collect_rr(ns_msg* handle, ns_sect section, ns_type type, - dns_entry* dns_e, long now, - dns_base_entry* (rr_to_entry)(ns_msg*,ns_rr*)) +dns_base_entry* dns_ip_entry::get_rr(dns_record* rr, u_char* begin, u_char* end) { - /* - * Look at all the resource records in this section. - */ - - assert(handle); - assert(dns_e); - - ns_rr rr; - - for(int rrnum = 0; rrnum < ns_msg_count(*handle, section); rrnum++) { - /* - * Expand the resource record number rrnum into rr. - */ - if (ns_parserr(handle, section, rrnum, &rr)) { - ERROR("ns_parserr: %s\n", strerror(errno)); - continue; - } - - /* - * If the record type is correct, save the data into - * the proper entry. - */ - if(ns_rr_type(rr) == type) { - dns_base_entry* new_entry = (*rr_to_entry)(handle,&rr); - if(!new_entry){ continue; } - new_entry->expire = now + ns_rr_ttl(rr); - dns_e->ip_vec.push_back(new_entry); - if(dns_e->expire < new_entry->expire) - dns_e->expire = new_entry->expire; - } - } - - return 0; -} + if(rr->type != dns_r_a) + return NULL; -static dns_base_entry* rr_to_a_entry(ns_msg*, ns_rr* rr) -{ DBG("A:\tTTL=%i\t%s\t%i.%i.%i.%i\n", ns_rr_ttl(*rr), ns_rr_name(*rr), @@ -382,40 +371,36 @@ static dns_base_entry* rr_to_a_entry(ns_msg*, ns_rr* rr) ip_entry* new_ip = new ip_entry(); new_ip->type = IPv4; memcpy(&(new_ip->addr), ns_rr_rdata(*rr), sizeof(in_addr)); - + return new_ip; } -static int collect_a_rr(ns_msg* handle, ns_sect section, dns_entry* dns_e, long now) +dns_base_entry* dns_srv_entry::get_rr(dns_record* rr, u_char* begin, u_char* end) { - return collect_rr(handle,section,ns_t_a,dns_e,now,rr_to_a_entry); -} + if(rr->type != dns_r_srv) + return NULL; -static dns_base_entry* rr_to_srv_entry(ns_msg* handle, ns_rr* rr) -{ - char name_buf[MAXDNAME]; + u_char name_buf[NS_MAXDNAME]; const u_char * rdata = ns_rr_rdata(*rr); /* Expand the target's name */ - if (ns_name_uncompress( - ns_msg_base(*handle),/* Start of the packet */ - ns_msg_end(*handle), /* End of the packet */ - rdata+6, /* Position in the packet*/ - name_buf, /* Result */ - MAXDNAME) /* Size of result buffer */ - < 0) { /* Negative: error */ + u_char* p = (u_char*)rdata+6; + if (dns_expand_name(&p,begin,end, + name_buf, /* Result */ + NS_MAXDNAME) /* Size of result buffer */ + < 0) { /* Negative: error */ - ERROR("ns_name_uncompress failed\n"); - return NULL; + ERROR("dns_expand_name failed\n"); + return NULL; } DBG("SRV:\tTTL=%i\t%s\tP=<%i> W=<%i> P=<%i> T=<%s>\n", - ns_rr_ttl(*rr), - ns_rr_name(*rr), - ns_get16(rdata), - ns_get16(rdata+2), - ns_get16(rdata+4), - name_buf); + ns_rr_ttl(*rr), + ns_rr_name(*rr), + ns_get16(rdata), + ns_get16(rdata+2), + ns_get16(rdata+4), + name_buf); srv_entry* srv_r = new srv_entry(); srv_r->p = ns_get16(rdata); @@ -426,90 +411,117 @@ static dns_base_entry* rr_to_srv_entry(ns_msg* handle, ns_rr* rr) return srv_r; } -static bool srv_less(const dns_base_entry* le, const dns_base_entry* re) +struct dns_entry_h { - const srv_entry* l_srv = (const srv_entry*)le; - const srv_entry* r_srv = (const srv_entry*)re; + dns_entry* e; + long now; +}; - if(l_srv->p != r_srv->p) - return l_srv->p < r_srv->p; +int rr_to_dns_entry(dns_record* rr, dns_section_type t, u_char* begin, u_char* end, void* data) +{ + dns_entry* dns_e = ((dns_entry_h*)data)->e; + long now = ((dns_entry_h*)data)->now; + + if(t == dns_s_an) + dns_e->add_rr(rr,begin,end,now); + + // TODO: parse the additional section as well. + // there might be some A/AAAA records related to + // the SRV targets. + + return 0; +} + +dns_handle::dns_handle() + : srv_e(0), srv_n(0), ip_e(0), ip_n(0) +{} + +dns_handle::~dns_handle() +{ + if(ip_e) + dec_ref(ip_e); + + if(srv_e) + dec_ref(srv_e); +} + +bool dns_handle::valid() +{ + return (ip_e); +} + +bool dns_handle::eoip() +{ + if(srv_e) + return (srv_n == -1) && (ip_n == -1); else - return l_srv->w < r_srv->w; -}; + return (ip_n == -1); +} -static int collect_srv_rr(ns_msg* handle, ns_sect section, dns_entry* dns_e, long now) +int dns_handle::next_ip(sockaddr_storage* sa) { - int ret = collect_rr(handle,section,ns_t_srv,dns_e,now,rr_to_srv_entry); - if(!ret){ - stable_sort(dns_e->ip_vec.begin(),dns_e->ip_vec.end(),srv_less); - } + if(!valid() || eoip()) return -1; - return ret; + if(srv_e) + return srv_e->next_ip(this,sa); + else + return ip_e->next_ip(this,sa); } -int _resolver::query_dns(const char* name, dns_entry** e, long now) +_resolver::_resolver() + : cache(DNS_CACHE_SIZE) +{ + start(); +} + +_resolver::~_resolver() { - typedef union { - HEADER hdr; /* defined in resolv.h */ - u_char buf[NS_PACKETSZ]; /* defined in arpa/nameser.h */ - } dns_response; /* response buffers */ +} + +int _resolver::query_dns(const char* name, dns_entry** e, long now) +{ + u_char dns_res[NS_PACKETSZ]; + if(!name) return -1; - dns_response dns_res; ns_type t = (name[0] == '_') ? ns_t_srv : ns_t_a; - //TODO: add AAAA record support - int dns_res_len = res_search(name,ns_c_in,t, - (u_char *)&dns_res.buf,sizeof(dns_response)); + //TODO: add AAAA record support + int dns_res_len = res_search(name,ns_c_in,t,dns_res,NS_PACKETSZ); if(dns_res_len < 0){ dns_error(h_errno,name); return -1; } - + + *e = dns_entry::make_entry(t); + /* * Initialize a handle to this response. The handle will * be used later to extract information from the response. */ - ns_msg handle; - if (ns_initparse(dns_res.buf, dns_res_len, &handle) < 0) { - ERROR("ns_initparse: %s\n", strerror(errno)); + dns_entry_h dns_h = { *e, now }; + if (dns_msg_parse(dns_res, dns_res_len, rr_to_dns_entry, &dns_h) < 0) { + DBG("Could not parse DNS reply"); return -1; } - if(!ns_msg_count(handle,ns_s_an)) { - // nothing in the answer section + *e = dns_h.e; + if(!*e) { + DBG("no dns_entry created"); return -1; } - - int ret; - switch(t){ - case ns_t_srv: - *e = new dns_srv_entry(); - ret = collect_srv_rr(&handle,ns_s_an,*e,now); - break; - case ns_t_a: - *e = new dns_ip_entry(); - ret = collect_a_rr(&handle,ns_s_an,*e,now); - break; - default: - ret = -1; - break; - } - - // TODO: parse the additional section as well. - // there might be some A/AAAA records related to - // the SRV targets. - - if((ret < 0) || (*e)->ip_vec.empty()){ - delete *e; - *e = NULL; - return -1; + if((*e)->ip_vec.empty()){ + delete *e; + *e = NULL; + return -1; } + (*e)->init(); inc_ref(*e); + return 0; } @@ -552,13 +564,14 @@ int _resolver::resolve_name(const char* name, return -1; } - // if ttl != 0 - if(e->expire != tv_now.tv_sec){ - // cache the new record - b->insert(name,e); - } - if(e) { + + // if ttl != 0 + if(e->expire != tv_now.tv_sec){ + // cache the new record + b->insert(name,e); + } + // now we should have a valid IP return e->next_ip(h,sa); } @@ -574,7 +587,6 @@ int _resolver::str2ip(const char* name, if(types & IPv4){ int ret = inet_pton(AF_INET,name,&((sockaddr_in*)sa)->sin_addr); if(ret==1) { - DBG("inet_pton() succeeded"); ((sockaddr_in*)sa)->sin_family = AF_INET; return 1; } @@ -587,7 +599,6 @@ int _resolver::str2ip(const char* name, if(types & IPv6){ int ret = inet_pton(AF_INET6,name,&((sockaddr_in6*)sa)->sin6_addr); if(ret==1) { - DBG("inet_pton() succeeded"); ((sockaddr_in6*)sa)->sin6_family = AF_INET6; return 1; } @@ -600,43 +611,6 @@ int _resolver::str2ip(const char* name, return 0; } -dns_handle::dns_handle() - : srv_e(0), srv_n(0), ip_e(0), ip_n(0) -{} - -dns_handle::~dns_handle() -{ - DBG("~dns_handle()"); - if(ip_e) - dec_ref(ip_e); - - if(srv_e) - dec_ref(srv_e); -} - -bool dns_handle::valid() -{ - return (ip_e); -} - -bool dns_handle::eoip() -{ - if(srv_e) - return (srv_n == -1) && (ip_n == -1); - else - return (ip_n == -1); -} - -int dns_handle::next_ip(sockaddr_storage* sa) -{ - if(!valid() || eoip()) return -1; - - if(srv_e) - return srv_e->next_ip(this,sa); - else - return ip_e->next_ip(this,sa); -} - void _resolver::run() { for(;;) { @@ -660,14 +634,13 @@ void _resolver::run() dns_bucket::value_map::iterator tmp_it = it; bool end_of_bucket = (++it == bucket->elmts.end()); - DBG("########### expiring record %p #############",dns_e); bucket->elmts.erase(tmp_it); dec_ref(dns_e); if(end_of_bucket) break; } else { - DBG("######### record %p expires in %li seconds ##########",dns_e,it->second->expire-tv_now.tv_sec); + //DBG("######### record %p expires in %li seconds ##########",dns_e,it->second->expire-tv_now.tv_sec); } } bucket->unlock(); diff --git a/core/sip/resolver.h b/core/sip/resolver.h index 4e9c535b..cf69a3a5 100644 --- a/core/sip/resolver.h +++ b/core/sip/resolver.h @@ -30,6 +30,7 @@ #include "singleton.h" #include "hash_table.h" #include "atomic_types.h" +#include "parse_dns.h" #include #include @@ -70,12 +71,17 @@ class dns_entry : public atomic_ref_cnt, public dns_base_entry { + virtual dns_base_entry* get_rr(dns_record* rr, u_char* begin, u_char* end)=0; + public: vector ip_vec; + static dns_entry* make_entry(ns_type t); + dns_entry(); virtual ~dns_entry(); - + virtual void init()=0; + virtual void add_rr(dns_record* rr, u_char* begin, u_char* end, long now); virtual int next_ip(dns_handle* h, sockaddr_storage* sa)=0; };