Module: sip-router Branch: master Commit: 1b30ae44d71332d7e96221ee444a1aede2d3da01 URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=1b30ae44...
Author: Miklos Tirpak miklos@iptel.org Committer: Miklos Tirpak miklos@iptel.org Date: Wed Jun 23 16:34:56 2010 +0200
dns cache: dns_cache_rec_pref config var added
The config variable, dns_cache_rec_pref, can be used to set the DNS cache preference as follows:
0 - do not check duplicates (default) 1 - prefer old records 2 - prefer new records 3 - prefer records with longer lifetime
This variable is checked when a duplicated record is tried to be inserted into the cache. For instance the SRV query answer contains also an A record which is already in the cache. If the config var is not 0, then permanent entries are always preferred.
Note: works only with #define CACHE_RELEVANT_RECS_ONLY at the moment.
---
NEWS | 6 ++++++ cfg_core.c | 7 +++++++ cfg_core.h | 1 + dns_cache.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++---- 4 files changed, 67 insertions(+), 4 deletions(-)
diff --git a/NEWS b/NEWS index 0112243..5d691cb 100644 --- a/NEWS +++ b/NEWS @@ -14,6 +14,7 @@ core: See dst_blacklist_udp_imask a.s.o (dst_blacklist_*_imask). - per message blacklist ignore masks - route() now supports rvalue expressions (e.g. route("test"+$i)) + - support for permanent entries in the DNS cache.
new config variables: - dst_blacklist_udp_imask - global blacklist events ignore mask for udp @@ -27,6 +28,11 @@ new config variables: - dst_blacklist_tcp_imask - like dst_blacklist_udp_imask, but for tcp. - dst_blacklist_tls_imask - like dst_blacklist_tls_imask, but for tcp. - dst_blacklist_sctp_imask -like dst_blacklist_sctp_imask, but for tcp. + - dns_cache_rec_pref - DNS cache record preference: + 0 - do not check duplicates (default) + 1 - prefer old records + 2 - prefer new records + 3 - prefer records with longer lifetime
modules: - blst: functions for ignoring blacklist events per message: diff --git a/cfg_core.c b/cfg_core.c index 101ba9f..d819dee 100644 --- a/cfg_core.c +++ b/cfg_core.c @@ -102,6 +102,7 @@ struct cfg_group_core default_core_cfg = { DEFAULT_DNS_CACHE_MAX_TTL, /*!< maximum ttl */ DEFAULT_DNS_MAX_MEM, /*!< dns_cache_max_mem */ 0, /*!< dns_cache_del_nonexp -- delete only expired entries by default */ + 0, /*!< dns_cache_rec_pref -- 0 by default, do not check the existing entries. */ #endif #ifdef PKG_MALLOC 0, /*!< mem_dump_pkg */ @@ -206,6 +207,12 @@ cfg_def_t core_cfg_def[] = { {"dns_cache_del_nonexp", CFG_VAR_INT, 0, 1, 0, 0, "allow deletion of non-expired records from the cache when " "there is no more space left for new ones"}, + {"dns_cache_rec_pref", CFG_VAR_INT, 0, 3, 0, 0, + "DNS cache record preference: " + " 0 - do not check duplicates" + " 1 - prefer old records" + " 2 - prefer new records" + " 3 - prefer records with longer lifetime"}, #endif #ifdef PKG_MALLOC {"mem_dump_pkg", CFG_VAR_INT, 0, 0, 0, mem_dump_pkg_cb, diff --git a/cfg_core.h b/cfg_core.h index 1e86692..c0d83c8 100644 --- a/cfg_core.h +++ b/cfg_core.h @@ -92,6 +92,7 @@ struct cfg_group_core { unsigned int dns_cache_max_ttl; unsigned int dns_cache_max_mem; int dns_cache_del_nonexp; + int dns_cache_rec_pref; #endif #ifdef PKG_MALLOC int mem_dump_pkg; diff --git a/dns_cache.c b/dns_cache.c index 2ec3d3e..adf2940 100644 --- a/dns_cache.c +++ b/dns_cache.c @@ -1874,10 +1874,14 @@ inline static struct dns_hash_entry* dns_cache_do_request(str* name, int type) struct ip_addr* ip; str cname_val; char name_buf[MAX_DNS_NAME]; + struct dns_hash_entry* old; + str rec_name; + int add_record, h, err;
e=0; l=0; cname_val.s=0; + old = NULL;
#ifdef USE_DNS_CACHE_STATS if (dns_cache_stats) @@ -1944,10 +1948,55 @@ inline static struct dns_hash_entry* dns_cache_do_request(str* name, int type) LOCK_DNS_HASH(); /* optimization */ for (r=l; r; r=t){ t=r->next; - dns_cache_add_unsafe(r); /* refcnt++ inside */ - if (atomic_get(&r->refcnt)==0){ - /* if cache adding failed and nobody else is interested - * destroy this entry */ + /* add the new record to the cache by default */ + add_record = 1; + if (cfg_get(core, core_cfg, dns_cache_rec_pref) > 0) { + /* check whether there is an old record with the + * same type in the cache */ + rec_name.s = r->name; + rec_name.len = r->name_len; + old = _dns_hash_find(&rec_name, r->type, &h, &err); + if (old) { + if (old->type != r->type) { + /* probably CNAME found */ + old = NULL; + + } else if (old->ent_flags & DNS_FLAG_PERMANENT) { + /* never overwrite permanent entries */ + add_record = 0; + + } else if ((old->ent_flags & DNS_FLAG_BAD_NAME) == 0) { + /* Non-negative, non-permanent entry found with + * the same type. */ + add_record = + /* prefer new records */ + ((cfg_get(core, core_cfg, dns_cache_rec_pref) == 2) + /* prefer the record with the longer lifetime */ + || ((cfg_get(core, core_cfg, dns_cache_rec_pref) == 3) + && TICKS_LT(old->expire, r->expire))); + } + } + } + if (add_record) { + dns_cache_add_unsafe(r); /* refcnt++ inside */ + if (atomic_get(&r->refcnt)==0){ + /* if cache adding failed and nobody else is interested + * destroy this entry */ + dns_destroy_entry(r); + } + if (old) { + _dns_hash_remove(old); + old = NULL; + } + } else { + if (old) { + if (r == e) { + /* this entry has to be returned */ + e = old; + atomic_inc(&e->refcnt); + } + old = NULL; + } dns_destroy_entry(r); } }