Module: sip-router Branch: sr_3.0 Commit: d495d4cd2c3bdc4323f1850fe1c6ed48f342f317 URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=d495d4cd...
Author: Miklos Tirpak miklos@iptel.org Committer: Andrei Pelinescu-Onciul andrei@iptel.org Date: Wed Aug 18 15:32:36 2010 +0200
dns cache: fix manually inserted SRV record order
The manually inserted SRV records thought the RPC interface were not ordered by their priority and weight which resulted in wrong SRV look-ups, i.e. not the highest priority record was chosen first. (cherry picked from commit 78beed37b8975e11851553c41c17578481772dad)
---
dns_cache.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 44 insertions(+), 0 deletions(-)
diff --git a/dns_cache.c b/dns_cache.c index e382373..47c7ba4 100644 --- a/dns_cache.c +++ b/dns_cache.c @@ -4072,6 +4072,8 @@ static void dns_cache_add_record(rpc_t* rpc, void* ctx, unsigned short type) ticks_t expire; int err, h; int size; + struct dns_rr *new_rr, **rr_p, **rr_iter; + struct srv_rdata *srv_rd;
/* eliminate gcc warnings */ ip_addr = 0; @@ -4206,6 +4208,7 @@ static void dns_cache_add_record(rpc_t* rpc, void* ctx, unsigned short type) /* let the rr point to the new structure */ rr = (struct dns_rr*)translate_pointer((char*)new, (char*)old, (char*)rr); + new_rr = rr;
if (type == T_SRV) { /* fix the priority, weight, and port */ @@ -4240,6 +4243,7 @@ static void dns_cache_add_record(rpc_t* rpc, void* ctx, unsigned short type) " the cache"); goto error; } + new_rr = rr;
switch(type) { case T_A: @@ -4257,6 +4261,46 @@ static void dns_cache_add_record(rpc_t* rpc, void* ctx, unsigned short type) /* maximum expire value has been already fixed by * dns_cache_clone_entry() */ } + + if (type == T_SRV) { + /* SRV records must be ordered by their priority and weight. + * With modifying an exising rr, or adding new rr to the DNS entry, + * the ordered list might got broken which needs to be fixed. + */ + rr_p = NULL; + for ( rr_iter = &new->rr_lst; + *rr_iter; + rr_iter = &((*rr_iter)->next) + ) { + if (*rr_iter == new_rr) { + rr_p = rr_iter; + continue; + } + srv_rd = (struct srv_rdata*)(*rr_iter)->rdata; + if ((priority < srv_rd->priority) || + ((priority == srv_rd->priority) && (weight > srv_rd->weight)) + ) + break; /* insert here */ + } + + if (!rr_p) + for ( rr_p = rr_iter; + *rr_p && (*rr_p != new_rr); + rr_p = &((*rr_p)->next) + ); + if (!rr_p) { + LOG(L_ERR, "ERROR: Failed to correct the orderd list of SRV resource records\n"); + goto error; + } + + if (*rr_iter != new_rr->next) { + /* unlink rr from the list */ + *rr_p = (*rr_p)->next; + /* link it before *rr_iter */ + new_rr->next = *rr_iter; + *rr_iter = new_rr; + } + } } }