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.
sayer/1.4-spce2.6
Raphael Coeffic 16 years ago
parent 2eeef30fbb
commit 7e65eccab8

@ -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)

@ -0,0 +1,166 @@
#include "parse_dns.h"
#include <string.h>
#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<dns_msg_count(begin,dns_s_qd); i++){
// query name
if(dns_skip_name(&p,end) < 0) return -1;
// skip query type+class
if((p += 4) > end) return -1;
}
dns_record rr;
for(int s = (int)dns_s_an; s < (int)__dns_max_sections; ++s){
for(int i=0; i<dns_msg_count(begin,(dns_section_type)s); i++){
// expand name
if(dns_expand_name(&p,begin,end,(u_char*)rr.name,NS_MAXDNAME) < 0) return -1;
// at least 8 bytes for type+class+ttl left?
if((p + 8) > 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;
}

@ -0,0 +1,43 @@
#ifndef _parse_dns_h_
#define _parse_dns_h_
#include <arpa/nameser.h>
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

@ -28,6 +28,8 @@
#include "resolver.h"
#include "hash.h"
#include "parse_dns.h"
#include <sys/socket.h>
#include <netdb.h>
#include <string.h>
@ -35,7 +37,7 @@
#include <resolv.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
#include <arpa/nameser_compat.h> // Darwin
//#include <arpa/nameser_compat.h> // Darwin only
#include <list>
@ -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<pair<unsigned int,int> > 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<<i);
while( (p==((srv_entry*)ip_vec[i])->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<pair<unsigned int,int> >::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<pair<unsigned int,int> > 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<<i);
while( (p==((srv_entry*)ip_vec[i])->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<pair<unsigned int,int> >::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<dns_base_entry*>::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();

@ -30,6 +30,7 @@
#include "singleton.h"
#include "hash_table.h"
#include "atomic_types.h"
#include "parse_dns.h"
#include <string>
#include <vector>
@ -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<dns_base_entry*> 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;
};

Loading…
Cancel
Save