2 * resolver related functions
4 * Copyright (C) 2006 iptelorg GmbH
6 * This file is part of Kamailio, a free SIP server.
8 * Kamailio is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version
13 * Kamailio is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 * \brief Kamailio core :: DNS cache handling
34 #include <stdlib.h> /* FIXME: rand() */
40 #include "dns_cache.h"
41 #include "dns_wrappers.h"
42 #include "compiler_opt.h"
43 #include "mem/shm_mem.h"
47 #include "atomic_ops.h"
50 #include "timer_ticks.h"
53 #include "rand/fastrand.h"
54 #ifdef USE_DNS_CACHE_STATS
63 #define MAX(a,b) ( ((a)>(b))?(a):(b))
66 #define MAX_DNS_RECORDS 255 /* maximum dns records number received in a
69 #define DNS_HASH_SIZE 1024 /* must be <= 65535 */
70 #define DEFAULT_DNS_TIMER_INTERVAL 120 /* 2 min. */
71 #define DNS_HE_MAX_ADDR 10 /* maxium addresses returne in a hostent struct */
72 #define MAX_CNAME_CHAIN 10
73 #define SPACE_FORMAT " " /* format of view output */
74 #define DNS_SRV_ZERO_W_CHANCE 1000 /* one in a 1000*weight_sum chance for
75 selecting a 0-weight record */
77 int dns_cache_init=1; /* if 0, the DNS cache is not initialized at startup */
78 static gen_lock_t* dns_hash_lock=0;
79 static volatile unsigned int *dns_cache_mem_used=0; /* current mem. use */
80 unsigned int dns_timer_interval=DEFAULT_DNS_TIMER_INTERVAL; /* in s */
81 int dns_flags=0; /* default flags used for the dns_*resolvehost
82 (compatibility wrappers) */
84 #ifdef USE_DNS_CACHE_STATS
85 struct t_dns_cache_stats* dns_cache_stats=0;
88 #define LOCK_DNS_HASH() lock_get(dns_hash_lock)
89 #define UNLOCK_DNS_HASH() lock_release(dns_hash_lock)
92 (((t)<cfg_get(core, core_cfg, dns_cache_min_ttl))? \
93 cfg_get(core, core_cfg, dns_cache_min_ttl): \
94 (((t)>cfg_get(core, core_cfg, dns_cache_max_ttl))? \
95 cfg_get(core, core_cfg, dns_cache_max_ttl): \
100 struct dns_hash_entry* next;
101 struct dns_hash_entry* prev;
104 struct dns_lu_lst* dns_last_used_lst=0;
106 static struct dns_hash_head* dns_hash=0;
109 static struct timer_ln* dns_timer_h=0;
111 #ifdef DNS_WATCHDOG_SUPPORT
112 static atomic_t *dns_servers_up = NULL;
117 static const char* dns_str_errors[]={
119 "no more records", /* not an error, but and end condition */
123 "unresolvable SRV request",
124 "bad A or AAAA entry",
125 "unresolvable A or AAAA request",
126 "invalid ip in A or AAAA record",
128 "name too long ", /* try again with a shorter name */
129 "ip AF mismatch", /* address family mismatch */
130 "unresolvable NAPTR request",
131 "bug - critical error"
136 /* param: err (negative error number) */
137 const char* dns_strerror(int err)
140 if ((err>=0) && (err<sizeof(dns_str_errors)/sizeof(char*)))
141 return dns_str_errors[err];
142 return "bug -- bad error number";
147 /* "internal" only, don't use unless you really know waht you're doing */
148 inline static void dns_destroy_entry(struct dns_hash_entry* e)
150 memset(e, 0, e->total_size);
151 shm_free(e); /* nice having it in one block isn't it? :-) */
155 /* "internal" only, same as above, asumes shm_lock() held (tm optimization) */
156 inline static void dns_destroy_entry_shm_unsafe(struct dns_hash_entry* e)
158 memset(e, 0, e->total_size);
159 shm_free_unsafe(e); /* nice having it in one block isn't it? :-) */
164 /* dec. the internal refcnt and if 0 deletes the entry */
165 void dns_hash_put(struct dns_hash_entry* e)
167 if(e && atomic_dec_and_test(&e->refcnt)){
168 /* atomic_sub_long(dns_cache_total_used, e->total_size); */
169 dns_destroy_entry(e);
175 /* same as above but uses dns_destroy_unsafe (assumes shm_lock held -- tm
177 void dns_hash_put_shm_unsafe(struct dns_hash_entry* e)
179 if(e && atomic_dec_and_test(&e->refcnt)){
180 /* atomic_sub_long(dns_cache_total_used, e->total_size); */
181 dns_destroy_entry_shm_unsafe(e);
186 inline static int dns_cache_clean(unsigned int no, int expired_only);
187 inline static int dns_cache_free_mem(unsigned int target, int expired_only);
189 static ticks_t dns_timer(ticks_t ticks, struct timer_ln* tl, void* data)
191 #ifdef DNS_WATCHDOG_SUPPORT
192 /* do not clean the hash table if the servers are down */
193 if (atomic_get(dns_servers_up) == 0)
194 return (ticks_t)(-1);
196 if (*dns_cache_mem_used>12*(cfg_get(core, core_cfg, dns_cache_max_mem)/16)){ /* ~ 75% used */
197 dns_cache_free_mem(cfg_get(core, core_cfg, dns_cache_max_mem)/2, 1);
199 dns_cache_clean(-1, 1); /* all the table, only expired entries */
200 /* TODO: better strategy? */
202 return (ticks_t)(-1);
207 void destroy_dns_cache()
210 timer_del(dns_timer_h);
211 timer_free(dns_timer_h);
214 #ifdef DNS_WATCHDOG_SUPPORT
216 shm_free(dns_servers_up);
221 lock_destroy(dns_hash_lock);
222 lock_dealloc(dns_hash_lock);
229 if (dns_last_used_lst){
230 shm_free(dns_last_used_lst);
233 #ifdef USE_DNS_CACHE_STATS
235 shm_free(dns_cache_stats);
237 if (dns_cache_mem_used){
238 shm_free((void*)dns_cache_mem_used);
239 dns_cache_mem_used=0;
243 /* set the value of dns_flags */
244 void fix_dns_flags(str *gname, str *name)
246 /* restore the original value of dns_cache_flags first
247 * (DNS_IPV4_ONLY may have been set only because dns_try_ipv6
248 * was disabled, and the flag must be cleared when
249 * dns_try_ipv6 is enabled) (Miklos)
251 dns_flags = cfg_get(core, core_cfg, dns_cache_flags) & 7;
253 if (cfg_get(core, core_cfg, dns_try_ipv6)==0){
254 dns_flags|=DNS_IPV4_ONLY;
256 if (dns_flags & DNS_IPV4_ONLY){
257 dns_flags&=~(DNS_IPV6_ONLY|DNS_IPV6_FIRST);
259 if (cfg_get(core, core_cfg, dns_srv_lb)){
261 dns_flags|=DNS_SRV_RR_LB;
263 LM_WARN("SRV loadbalaning is set, but"
264 " support for it is not compiled -- ignoring\n");
267 if (cfg_get(core, core_cfg, dns_try_naptr)) {
269 LM_WARN("NAPTR support is enabled, but"
270 " support for it is not compiled -- ignoring\n");
272 dns_flags|=DNS_TRY_NAPTR;
276 /* fixup function for use_dns_failover
277 * verifies that use_dns_cache is set to 1
279 int use_dns_failover_fixup(void *handle, str *gname, str *name, void **val)
281 if ((int)(long)(*val) && !cfg_get(core, handle, use_dns_cache)) {
282 LM_ERR("DNS cache is turned off, failover cannot be enabled. "
283 "(set use_dns_cache to 1)\n");
289 /* fixup function for use_dns_cache
290 * verifies that dns_cache_init is set to 1
292 int use_dns_cache_fixup(void *handle, str *gname, str *name, void **val)
294 if ((int)(long)(*val) && !dns_cache_init) {
295 LM_ERR("DNS cache is turned off by dns_cache_init=0, "
296 "it cannot be enabled runtime.\n");
299 if (((int)(long)(*val)==0) && cfg_get(core, handle, use_dns_failover)) {
300 LM_ERR("DNS failover depends on use_dns_cache, set use_dns_failover "
301 "to 0 before disabling the DNS cache\n");
307 /* KByte to Byte conversion */
308 int dns_cache_max_mem_fixup(void *handle, str *gname, str *name, void **val)
312 u = ((unsigned int)(long)(*val))<<10;
313 (*val) = (void *)(long)u;
322 if (dns_cache_init==0) {
323 /* the DNS cache is turned off */
324 default_core_cfg.use_dns_cache=0;
325 default_core_cfg.use_dns_failover=0;
331 if (E_DNS_CRITICAL>=sizeof(dns_str_errors)/sizeof(char*)){
332 LM_CRIT("bad dns error table\n");
336 dns_cache_mem_used=shm_malloc(sizeof(*dns_cache_mem_used));
337 if (dns_cache_mem_used==0){
342 *dns_cache_mem_used=0;
344 dns_last_used_lst=shm_malloc(sizeof(*dns_last_used_lst));
345 if (dns_last_used_lst==0){
350 clist_init(dns_last_used_lst, next, prev);
352 dns_hash=shm_malloc(sizeof(struct dns_hash_head)*DNS_HASH_SIZE);
358 for (r=0; r<DNS_HASH_SIZE; r++)
359 clist_init(&dns_hash[r], next, prev);
361 dns_hash_lock=lock_alloc();
362 if (dns_hash_lock==0){
366 if (lock_init(dns_hash_lock)==0){
367 lock_dealloc(dns_hash_lock);
373 #ifdef DNS_WATCHDOG_SUPPORT
374 dns_servers_up=shm_malloc(sizeof(atomic_t));
375 if (dns_servers_up==0){
380 atomic_set(dns_servers_up, 1);
384 default_core_cfg.dns_cache_max_mem<<=10; /* Kb */ /* TODO: test with 0 */
385 if (default_core_cfg.use_dns_cache==0)
386 default_core_cfg.use_dns_failover=0; /* cannot work w/o dns_cache support */
388 fix_dns_flags(NULL, NULL);
390 dns_timer_h=timer_alloc();
395 if (dns_timer_interval){
396 timer_init(dns_timer_h, dns_timer, 0, 0); /* "slow" timer */
397 if (timer_add(dns_timer_h, S_TO_TICKS(dns_timer_interval))<0){
398 LM_CRIT("failed to add the timer\n");
399 timer_free(dns_timer_h);
411 #ifdef USE_DNS_CACHE_STATS
412 int init_dns_cache_stats(int iproc_num)
414 /* do not initialize the stats array if the DNS cache will not be used */
415 if (dns_cache_init==0) return 0;
417 /* if it is already initialized */
419 shm_free(dns_cache_stats);
421 dns_cache_stats=shm_malloc(sizeof(*dns_cache_stats) * iproc_num);
422 if (dns_cache_stats==0){
426 memset(dns_cache_stats, 0, sizeof(*dns_cache_stats) * iproc_num);
432 /* hash function, type is not used (obsolete)
433 * params: char* s, int len, int type
434 * returns the hash value
436 #define dns_hash_no(s, len, type) \
437 (get_hash1_case_raw((s),(len)) % DNS_HASH_SIZE)
442 #include <stdlib.h> /* abort() */
443 #define check_lu_lst(l) ((((l)->next==(l)) || ((l)->prev==(l))) && \
444 ((l)!=dns_last_used_lst))
446 #define dbg_lu_lst(txt, l) \
447 LM_CRIT("%s: crt(%p, %p, %p)," \
448 " prev(%p, %p, %p), next(%p, %p, %p)\n", txt, \
449 (l), (l)->next, (l)->prev, \
450 (l)->prev, ((l)->prev)?(l)->prev->next:NULL, \
451 ((l)->prev)?(l)->prev->prev:NULL, \
452 (l)->next, ((l)->next)?(l)->next->next:NULL, \
453 ((l)->next)?(l)->next->prev:NULL \
456 #define debug_lu_lst( txt, l) \
458 if ((l) && check_lu_lst((l))){ \
459 dbg_lu_lst(txt " crt:", (l)); \
462 if (((l)->next) && check_lu_lst((l)->next)){ \
463 dbg_lu_lst(txt " next:", (l)); \
466 if (((l)->prev) && check_lu_lst((l)->prev)){ \
467 dbg_lu_lst(txt " prev:", (l)); \
474 /* must be called with the DNS_LOCK hold
475 * remove and entry from the hash, dec. its refcnt and if not referenced
476 * anymore deletes it */
477 inline static void _dns_hash_remove(struct dns_hash_entry* e)
479 clist_rm(e, next, prev);
481 debug_lu_lst("_dns_hash_remove: pre rm:", &e->last_used_lst);
482 clist_rm(&e->last_used_lst, next, prev);
483 debug_lu_lst("_dns_hash_remove: post rm:", &e->last_used_lst);
484 e->last_used_lst.next=e->last_used_lst.prev=0;
485 *dns_cache_mem_used-=e->total_size;
491 /* non locking version (the dns hash must _be_ locked externally)
492 * returns 0 when not found, or the entry on success (an entry with a
493 * similar name but with a CNAME type will always match).
494 * it doesn't increase the internal refcnt
495 * returns the entry when found, 0 when not found and sets *err to !=0
496 * on error (e.g. recursive cnames)
497 * WARNING: - internal use only
498 * - always check if the returned entry type is CNAME */
499 inline static struct dns_hash_entry* _dns_hash_find(str* name, int type,
502 struct dns_hash_entry* e;
503 struct dns_hash_entry* tmp;
504 struct dns_hash_entry* ret;
508 #ifdef DNS_WATCHDOG_SUPPORT
511 servers_up = atomic_get(dns_servers_up);
519 /* just in case that e.g. the VIA parser get confused */
520 if(unlikely(!name->s || name->len <= 0)) {
521 LM_ERR("invalid name, no cache lookup possible\n");
526 *h=dns_hash_no(name->s, name->len, type);
527 LM_DBG("(%.*s(%d), %d), h=%d\n", name->len, name->s, name->len, type, *h);
528 clist_foreach_safe(&dns_hash[*h], e, tmp, next){
530 #ifdef DNS_WATCHDOG_SUPPORT
531 /* remove expired elements only when the dns servers are up */
534 /* automatically remove expired elements */
535 ((e->ent_flags & DNS_FLAG_PERMANENT) == 0) &&
536 ((s_ticks_t)(now-e->expire)>=0)
539 }else if ((e->type==type) && (e->name_len==name->len) &&
540 (strncasecmp(e->name, name->s, e->name_len)==0)){
542 /* add it at the end */
543 debug_lu_lst("_dns_hash_find: pre rm:", &e->last_used_lst);
544 clist_rm(&e->last_used_lst, next, prev);
545 clist_append(dns_last_used_lst, &e->last_used_lst, next, prev);
546 debug_lu_lst("_dns_hash_find: post append:", &e->last_used_lst);
548 }else if ((e->type==T_CNAME) &&
549 !((e->rr_lst==0) || (e->ent_flags & DNS_FLAG_BAD_NAME)) &&
550 (e->name_len==name->len) &&
551 (strncasecmp(e->name, name->s, e->name_len)==0)){
552 /*if CNAME matches and CNAME is entry is not a neg. cache entry
553 (could be produced by a specific CNAME lookup)*/
555 /* add it at the end */
556 debug_lu_lst("_dns_hash_find: cname: pre rm:", &e->last_used_lst);
557 clist_rm(&e->last_used_lst, next, prev);
558 clist_append(dns_last_used_lst, &e->last_used_lst, next, prev);
559 debug_lu_lst("_dns_hash_find: cname: post append:",
561 ret=e; /* if this is an unfinished cname chain, we try to
562 return the last cname */
563 /* this is a cname => retry using its value */
564 if (cname_chain> MAX_CNAME_CHAIN){
565 LM_ERR("cname chain too long or recursive (\"%.*s\")\n",
572 cname.s=((struct cname_rdata*)e->rr_lst->rdata)->name;
573 cname.len= ((struct cname_rdata*)e->rr_lst->rdata)->name_len;
574 if(cname.s!=NULL && cname.len>0) {
585 /* frees cache entries, if expired_only=0 only expired entries will be
586 * removed, else all of them
587 * it will process maximum no entries (to process all of them use -1)
588 * returns the number of deleted entries
589 * This should be called from a timer process*/
590 inline static int dns_cache_clean(unsigned int no, int expired_only)
592 struct dns_hash_entry* e;
595 unsigned int deleted;
596 struct dns_lu_lst* l;
597 struct dns_lu_lst* tmp;
603 clist_foreach_safe(dns_last_used_lst, l, tmp, next){
604 e=(struct dns_hash_entry*)(((char*)l)-
605 (char*)&((struct dns_hash_entry*)(0))->last_used_lst);
606 if (((e->ent_flags & DNS_FLAG_PERMANENT) == 0)
607 && (!expired_only || ((s_ticks_t)(now-e->expire)>=0))
621 /* frees cache entries, if expired_only=0 only expired entries will be
622 * removed, else all of them
623 * it will stop when the dns cache used memory reaches target (to process all
625 * returns the number of deleted entries */
626 inline static int dns_cache_free_mem(unsigned int target, int expired_only)
628 struct dns_hash_entry* e;
630 unsigned int deleted;
631 struct dns_lu_lst* l;
632 struct dns_lu_lst* tmp;
637 clist_foreach_safe(dns_last_used_lst, l, tmp, next){
638 if (*dns_cache_mem_used<=target) break;
639 e=(struct dns_hash_entry*)(((char*)l)-
640 (char*)&((struct dns_hash_entry*)(0))->last_used_lst);
641 if (((e->ent_flags & DNS_FLAG_PERMANENT) == 0)
642 && (!expired_only || ((s_ticks_t)(now-e->expire)>=0))
654 /* locking version (the dns hash must _not_be locked externally)
655 * returns 0 when not found, the searched entry on success (with CNAMEs
656 * followed) or the last CNAME entry from an unfinished CNAME chain,
657 * if the search matches a CNAME. On error sets *err (e.g. recursive CNAMEs).
658 * it increases the internal refcnt => when finished dns_hash_put() must
659 * be called on the returned entry
660 * WARNING: - the return might be a CNAME even if type!=CNAME, see above */
661 inline static struct dns_hash_entry* dns_hash_get(str* name, int type, int* h,
664 struct dns_hash_entry* e;
667 e=_dns_hash_find(name, type, h, err);
669 atomic_inc(&e->refcnt);
677 /* adds a fully created and init. entry (see dns_cache_mk_entry()) to the hash
679 * returns 0 on success, -1 on error */
680 inline static int dns_cache_add(struct dns_hash_entry* e)
685 /* atomic_add_long(dns_cache_total_used, e->size); */
686 if ((*dns_cache_mem_used+e->total_size)>=cfg_get(core, core_cfg, dns_cache_max_mem)){
687 #ifdef USE_DNS_CACHE_STATS
688 dns_cache_stats[process_no].dc_lru_cnt++;
690 LM_WARN("cache full, trying to free...\n");
691 /* free ~ 12% of the cache */
692 dns_cache_free_mem(*dns_cache_mem_used/16*14,
693 !cfg_get(core, core_cfg, dns_cache_del_nonexp));
694 if ((*dns_cache_mem_used+e->total_size)>=cfg_get(core, core_cfg, dns_cache_max_mem)){
695 LM_ERR("max. cache mem size exceeded\n");
699 atomic_inc(&e->refcnt);
700 h=dns_hash_no(e->name, e->name_len, e->type);
701 LM_DBG("adding %.*s(%d) %d (flags=%0x) at %d\n",
702 e->name_len, e->name, e->name_len, e->type, e->ent_flags, h);
704 *dns_cache_mem_used+=e->total_size; /* no need for atomic ops, written
705 only from within a lock */
706 clist_append(&dns_hash[h], e, next, prev);
707 clist_append(dns_last_used_lst, &e->last_used_lst, next, prev);
714 /* same as above, but it must be called with the dns hash lock held
715 * returns 0 on success, -1 on error */
716 inline static int dns_cache_add_unsafe(struct dns_hash_entry* e)
721 /* atomic_add_long(dns_cache_total_used, e->size); */
722 if ((*dns_cache_mem_used+e->total_size)>=cfg_get(core, core_cfg, dns_cache_max_mem)){
723 #ifdef USE_DNS_CACHE_STATS
724 dns_cache_stats[process_no].dc_lru_cnt++;
726 LM_WARN("cache full, trying to free...\n");
727 /* free ~ 12% of the cache */
729 dns_cache_free_mem(*dns_cache_mem_used/16*14,
730 !cfg_get(core, core_cfg, dns_cache_del_nonexp));
732 if ((*dns_cache_mem_used+e->total_size)>=cfg_get(core, core_cfg, dns_cache_max_mem)){
733 LM_ERR("max. cache mem size exceeded\n");
737 atomic_inc(&e->refcnt);
738 h=dns_hash_no(e->name, e->name_len, e->type);
739 LM_DBG("adding %.*s(%d) %d (flags=%0x) at %d\n",
740 e->name_len, e->name, e->name_len, e->type, e->ent_flags, h);
741 *dns_cache_mem_used+=e->total_size; /* no need for atomic ops, written
742 only from within a lock */
743 clist_append(&dns_hash[h], e, next, prev);
744 clist_append(dns_last_used_lst, &e->last_used_lst, next, prev);
751 /* creates a "negative" entry which will be valid for ttl seconds */
752 inline static struct dns_hash_entry* dns_cache_mk_bad_entry(str* name,
757 struct dns_hash_entry* e;
761 LM_DBG("(%.*s, %d, %d, %d)\n", name->len, name->s, type, ttl, flags);
762 size=sizeof(struct dns_hash_entry)+name->len-1+1;
768 memset(e, 0, size); /* init with 0*/
770 e->name_len=name->len;
774 e->expire=now+S_TO_TICKS(ttl);
775 memcpy(e->name, name->s, name->len);
782 /* create a a/aaaa hash entry from a name and ip address
783 * returns 0 on error */
784 inline static struct dns_hash_entry* dns_cache_mk_ip_entry(str* name,
787 struct dns_hash_entry* e;
791 /* everything is allocated in one block: dns_hash_entry + name +
792 * + dns_rr + rdata; dns_rr must start at an aligned adress,
793 * hence we need to round dns_hash_entry+name size to a sizeof(long)
796 * struct dns_hash_entry
797 * name (name_len+1 bytes)
798 * padding to multiple of sizeof(long)
800 * rdata (no padding needed, since for ip is just an array of chars)
802 size=ROUND_POINTER(sizeof(struct dns_hash_entry)+name->len-1+1)+
803 sizeof(struct dns_rr)+ ip->len;
809 memset(e, 0, size); /* init with 0*/
811 e->name_len=name->len;
812 e->type=(ip->af==AF_INET)?T_A:T_AAAA;
815 e->expire=now-1; /* maximum expire */
816 memcpy(e->name, name->s, name->len); /* memset makes sure is 0-term. */
817 e->rr_lst=(void*)((char*)e+
818 ROUND_POINTER(sizeof(struct dns_hash_entry)+name->len-1+1));
819 e->rr_lst->rdata=(void*)((char*)e->rr_lst+sizeof(struct dns_rr));
820 e->rr_lst->expire=now-1; /* maximum expire */
821 /* no need to align rr_lst->rdata for a or aaaa records */
822 memcpy(e->rr_lst->rdata, ip->u.addr, ip->len);
826 /* creates an srv hash entry from the given parameters
827 * returns 0 on error */
828 static struct dns_hash_entry* dns_cache_mk_srv_entry(str* name,
829 unsigned short priority,
830 unsigned short weight,
835 struct dns_hash_entry* e;
839 /* everything is allocated in one block: dns_hash_entry + name +
840 * + dns_rr + rdata; dns_rr must start at an aligned adress,
841 * hence we need to round dns_hash_entry+name size to a sizeof(long),
842 * and similarly, dns_rr must be rounded to sizeof(short).
845 * struct dns_hash_entry
846 * name (name_len+1 bytes)
847 * padding to multiple of sizeof(long)
849 * padding to multiple of sizeof(short)
852 size=ROUND_POINTER(sizeof(struct dns_hash_entry)+name->len-1+1) +
853 ROUND_SHORT(sizeof(struct dns_rr)) +
854 sizeof(struct srv_rdata)-1 +
862 memset(e, 0, size); /* init with 0*/
864 e->name_len=name->len;
868 e->expire=now+S_TO_TICKS(ttl);
869 memcpy(e->name, name->s, name->len); /* memset makes sure is 0-term. */
870 e->rr_lst=(void*)((char*)e+
871 ROUND_POINTER(sizeof(struct dns_hash_entry)+name->len-1+1));
872 e->rr_lst->rdata=(void*)((char*)e->rr_lst+ROUND_SHORT(sizeof(struct dns_rr)));
873 e->rr_lst->expire=e->expire;
874 ((struct srv_rdata*)e->rr_lst->rdata)->priority = priority;
875 ((struct srv_rdata*)e->rr_lst->rdata)->weight = weight;
876 ((struct srv_rdata*)e->rr_lst->rdata)->port = port;
877 ((struct srv_rdata*)e->rr_lst->rdata)->name_len = rr_name->len;
878 memcpy(((struct srv_rdata*)e->rr_lst->rdata)->name, rr_name->s, rr_name->len);
883 /* create a dns hash entry from a name and a rdata list (pkg_malloc'ed)
884 * (it will use only the type records with the name "name" from the
885 * rdata list with one exception: if a matching CNAME with the same
886 * name is found, the search will stop and this will be the record used)
887 * returns 0 on error and removes the used elements from the rdata list*/
888 inline static struct dns_hash_entry* dns_cache_mk_rd_entry(str* name, int type,
889 struct rdata** rd_lst)
891 struct dns_hash_entry* e;
893 struct dns_rr** tail_rr;
895 struct rdata* tmp_lst;
900 unsigned int max_ttl;
904 #define rec_matches(rec, t, n) /*(struct rdata* record, int type, str* name)*/\
905 ( ((rec)->name_len==(n)->len) && ((rec)->type==(t)) && \
906 (strncasecmp((rec)->name, (n)->s, (n)->len)==0))
912 /* everything is allocated in one block: dns_hash_entry + name +
913 * + dns_rr + rdata_raw+ ....; dns_rr must start at an aligned adress,
914 * hence we need to round dns_hash_entry+name size to a sizeof(long)
915 * multiple. If rdata type requires it, rdata_raw might need to be also
918 * struct dns_hash_entry (e)
919 * name (name_len+1 bytes) (&e->name[0])
920 * padding to multiple of sizeof(char*)
921 * dns_rr1 (e->rr_lst)
922 * possible padding: no padding for a_rdata or aaaa_rdata,
923 * multipe of sizeof(short) for srv_rdata,
924 * multiple of sizeof(long) for naptr_rdata and others
925 * dns_rr1->rdata (e->rr_lst->rdata)
926 * padding to multipe of sizeof long
927 * dns_rr2 (e->rr_lst->next)
934 /* find the first matching rr, if it's a CNAME use CNAME as type,
935 * if not continue with the original type */
936 for(p=rd_lst; *p; p=&(*p)->next){
937 if (((*p)->name_len==name->len) &&
938 (((*p)->type==type) || ((*p)->type==T_CNAME)) &&
939 (strncasecmp((*p)->name, name->s, name->len)==0)){
944 /* continue, we found the type we are looking for */
948 if (!rec_matches((*p), type, name)){
949 /* skip this record */
950 p=&(*p)->next; /* advance */
953 size+=ROUND_POINTER(sizeof(struct dns_rr)+
954 sizeof(struct a_rdata));
955 /* add it to our tmp. lst */
958 /* detach it from the rd list */
960 /* don't advance p, because the crt. elem. has
961 * just been elimintated */
966 if (!rec_matches((*p), type, name)){
967 /* skip this record */
968 p=&(*p)->next; /* advance */
972 size+=ROUND_POINTER(sizeof(struct dns_rr)+
973 sizeof(struct aaaa_rdata));
974 /* add it to our tmp. lst */
977 /* detach it from the rd list */
979 /* don't advance p, because the crt. elem. has
980 * just been elimintated */
985 if (!rec_matches((*p), type, name)){
986 /* skip this record */
987 p=&(*p)->next; /* advance */
990 /* padding to short */
991 size+=ROUND_POINTER(ROUND_SHORT(sizeof(struct dns_rr))+
992 SRV_RDATA_SIZE(*(struct srv_rdata*)(*p)->rdata));
993 /* add it to our tmp. lst */
996 /* detach it from the rd list */
998 /* don't advance p, because the crt. elem. has
999 * just been elimintated */
1004 if (!rec_matches((*p), type, name)){
1005 /* skip this record */
1006 p=&(*p)->next; /* advance */
1009 /* padding to char* */
1010 size+=ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
1011 NAPTR_RDATA_SIZE(*(struct naptr_rdata*)(*p)->rdata));
1012 /* add it to our tmp. lst */
1015 /* detach it from the rd list */
1017 /* don't advance p, because the crt. elem. has
1018 * just been elimintated */
1023 if (!rec_matches((*p), type, name)){
1024 /* skip this record */
1025 p=&(*p)->next; /* advance */
1029 size+=ROUND_POINTER(sizeof(struct dns_rr)+
1030 CNAME_RDATA_SIZE(*(struct cname_rdata*)(*p)->rdata));
1031 /* add it to our tmp. lst */
1034 /* detach it from the rd list */
1036 /* don't advance p, because the crt. elem. has
1037 * just been elimintated */
1042 if (!rec_matches((*p), type, name)){
1043 /* skip this record */
1044 p=&(*p)->next; /* advance */
1047 /* padding to char* (because of txt[]->cstr*/
1048 size+=ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
1049 TXT_RDATA_SIZE(*(struct txt_rdata*)(*p)->rdata));
1050 /* add it to our tmp. lst */
1053 /* detach it from the rd list */
1055 /* don't advance p, because the crt. elem. has
1056 * just been elimintated */
1061 if (!rec_matches((*p), type, name)){
1062 /* skip this record */
1063 p=&(*p)->next; /* advance */
1066 /* padding to char* (because of the char* pointers */
1067 size+=ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
1068 EBL_RDATA_SIZE(*(struct ebl_rdata*)(*p)->rdata));
1069 /* add it to our tmp. lst */
1072 /* detach it from the rd list */
1074 /* don't advance p, because the crt. elem. has
1075 * just been elimintated */
1080 if (!rec_matches((*p), type, name)){
1081 /* skip this record */
1082 p=&(*p)->next; /* advance */
1086 size+=ROUND_POINTER(sizeof(struct dns_rr)+
1087 PTR_RDATA_SIZE(*(struct ptr_rdata*)(*p)->rdata));
1088 /* add it to our tmp. lst */
1091 /* detach it from the rd list */
1093 /* don't advance p, because the crt. elem. has
1094 * just been elimintated */
1098 LM_CRIT("type %d not supported\n", type);
1099 /* we don't know what to do with it, so don't
1100 * add it to the tmp_lst */
1101 return 0; /* error */
1103 *tail=0; /* mark the end of our tmp_lst */
1105 LM_DBG("entry %.*s (%d) not found\n", name->len, name->s, type);
1109 size+=ROUND_POINTER(sizeof(struct dns_hash_entry)+name->len-1+1);
1115 memset(e, 0, size); /* init with 0 */
1116 clist_init(e, next, prev);
1118 e->name_len=name->len;
1120 now=get_ticks_raw();
1122 memcpy(e->name, name->s, name->len); /* memset makes sure is 0-term. */
1123 e->rr_lst=(struct dns_rr*)((char*)e+
1124 ROUND_POINTER(sizeof(struct dns_hash_entry)+name->len-1+1));
1125 tail_rr=&(e->rr_lst);
1128 /* copy the actual data */
1131 for(l=tmp_lst; l; l=l->next){
1132 ttl=FIX_TTL(l->ttl);
1133 rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1134 max_ttl=MAX(max_ttl, ttl);
1135 rr->rdata=(void*)((char*)rr+sizeof(struct dns_rr));
1136 memcpy(rr->rdata, l->rdata, sizeof(struct a_rdata));
1137 rr->next=(void*)((char*)rr+ROUND_POINTER(sizeof(struct dns_rr)+
1138 sizeof(struct a_rdata)));
1139 tail_rr=&(rr->next);
1144 for(l=tmp_lst; l; l=l->next){
1145 ttl=FIX_TTL(l->ttl);
1146 rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1147 max_ttl=MAX(max_ttl, ttl);
1148 rr->rdata=(void*)((char*)rr+sizeof(struct dns_rr));
1149 memcpy(rr->rdata, l->rdata, sizeof(struct aaaa_rdata));
1150 rr->next=(void*)((char*)rr+ROUND_POINTER(sizeof(struct dns_rr)+
1151 sizeof(struct aaaa_rdata)));
1152 tail_rr=&(rr->next);
1157 for(l=tmp_lst; l; l=l->next){
1158 ttl=FIX_TTL(l->ttl);
1159 rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1160 max_ttl=MAX(max_ttl, ttl);
1161 rr->rdata=(void*)((char*)rr+
1162 ROUND_SHORT(sizeof(struct dns_rr)));
1163 /* copy the whole srv_rdata block*/
1164 memcpy(rr->rdata, l->rdata,
1165 SRV_RDATA_SIZE(*(struct srv_rdata*)l->rdata) );
1166 rr->next=(void*)((char*)rr+
1167 ROUND_POINTER( ROUND_SHORT(sizeof(struct dns_rr))+
1169 *(struct srv_rdata*)l->rdata)));
1170 tail_rr=&(rr->next);
1175 for(l=tmp_lst; l; l=l->next){
1176 ttl=FIX_TTL(l->ttl);
1177 rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1178 max_ttl=MAX(max_ttl, ttl);
1179 rr->rdata=(void*)((char*)rr+
1180 ROUND_POINTER(sizeof(struct dns_rr)));
1181 /* copy the whole naptr_rdata block*/
1182 memcpy(rr->rdata, l->rdata,
1183 NAPTR_RDATA_SIZE(*(struct naptr_rdata*)l->rdata) );
1184 /* adjust the string pointer */
1185 ((struct naptr_rdata*)rr->rdata)->flags=
1186 translate_pointer((char*)rr->rdata, (char*)l->rdata,
1187 (((struct naptr_rdata*)l->rdata)->flags));
1188 ((struct naptr_rdata*)rr->rdata)->services=
1189 translate_pointer((char*)rr->rdata, (char*)l->rdata,
1190 (((struct naptr_rdata*)l->rdata)->services));
1191 ((struct naptr_rdata*)rr->rdata)->regexp=
1192 translate_pointer((char*)rr->rdata, (char*)l->rdata,
1193 (((struct naptr_rdata*)l->rdata)->regexp));
1194 ((struct naptr_rdata*)rr->rdata)->repl=
1195 translate_pointer((char*)rr->rdata, (char*)l->rdata,
1196 (((struct naptr_rdata*)l->rdata)->repl));
1197 rr->next=(void*)((char*)rr+
1198 ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
1200 *(struct naptr_rdata*)l->rdata)));
1201 tail_rr=&(rr->next);
1206 for(l=tmp_lst; l; l=l->next){
1207 ttl=FIX_TTL(l->ttl);
1208 rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1209 max_ttl=MAX(max_ttl, ttl);
1210 rr->rdata=(void*)((char*)rr+sizeof(struct dns_rr));
1211 memcpy(rr->rdata, l->rdata,
1212 CNAME_RDATA_SIZE(*(struct cname_rdata*)l->rdata));
1213 rr->next=(void*)((char*)rr+ROUND_POINTER(sizeof(struct dns_rr)+
1214 CNAME_RDATA_SIZE(*(struct cname_rdata*)l->rdata)));
1215 tail_rr=&(rr->next);
1220 for(l=tmp_lst; l; l=l->next){
1221 ttl=FIX_TTL(l->ttl);
1222 rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1223 max_ttl=MAX(max_ttl, ttl);
1224 rr->rdata=(void*)((char*)rr+
1225 ROUND_POINTER(sizeof(struct dns_rr)));
1226 memcpy(rr->rdata, l->rdata,
1227 TXT_RDATA_SIZE(*(struct txt_rdata*)l->rdata));
1228 /* adjust the string pointers */
1229 for (i=0; i<((struct txt_rdata*)l->rdata)->cstr_no; i++){
1230 ((struct txt_rdata*)rr->rdata)->txt[i].cstr=
1231 translate_pointer((char*)rr->rdata, (char*)l->rdata,
1232 ((struct txt_rdata*)l->rdata)->txt[i].cstr);
1234 rr->next=(void*)((char*)rr+
1235 ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
1236 TXT_RDATA_SIZE(*(struct txt_rdata*)l->rdata)));
1237 tail_rr=&(rr->next);
1242 for(l=tmp_lst; l; l=l->next){
1243 ttl=FIX_TTL(l->ttl);
1244 rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1245 max_ttl=MAX(max_ttl, ttl);
1246 rr->rdata=(void*)((char*)rr+
1247 ROUND_POINTER(sizeof(struct dns_rr)));
1248 memcpy(rr->rdata, l->rdata,
1249 EBL_RDATA_SIZE(*(struct ebl_rdata*)l->rdata));
1250 /* adjust the string pointers */
1251 ((struct ebl_rdata*)rr->rdata)->separator=
1252 translate_pointer((char*)rr->rdata, (char*)l->rdata,
1253 ((struct ebl_rdata*)l->rdata)->separator);
1254 ((struct ebl_rdata*)rr->rdata)->separator=
1255 translate_pointer((char*)rr->rdata, (char*)l->rdata,
1256 ((struct ebl_rdata*)l->rdata)->separator);
1257 ((struct ebl_rdata*)rr->rdata)->apex=
1258 translate_pointer((char*)rr->rdata, (char*)l->rdata,
1259 ((struct ebl_rdata*)l->rdata)->apex);
1260 rr->next=(void*)((char*)rr+
1261 ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
1262 EBL_RDATA_SIZE(*(struct ebl_rdata*)l->rdata)));
1263 tail_rr=&(rr->next);
1268 for(l=tmp_lst; l; l=l->next){
1269 ttl=FIX_TTL(l->ttl);
1270 rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1271 max_ttl=MAX(max_ttl, ttl);
1272 rr->rdata=(void*)((char*)rr+sizeof(struct dns_rr));
1273 memcpy(rr->rdata, l->rdata,
1274 PTR_RDATA_SIZE(*(struct ptr_rdata*)l->rdata));
1275 rr->next=(void*)((char*)rr+ROUND_POINTER(sizeof(struct dns_rr)+
1276 PTR_RDATA_SIZE(*(struct ptr_rdata*)l->rdata)));
1277 tail_rr=&(rr->next);
1283 LM_CRIT("type %d not supported\n", type);
1286 *tail_rr=0; /* terminate the list */
1287 e->expire=now+S_TO_TICKS(max_ttl);
1288 free_rdata_list(tmp_lst);
1294 /* structure used only inside dns_cache_mk_rd_entry2 to break
1295 * the list of records into records of the same type */
1298 struct dns_hash_entry* e;
1300 struct dns_rr** tail_rr;
1307 /* create several dns hash entries from a list of rdata structs
1308 * returns 0 on error */
1309 inline static struct dns_hash_entry* dns_cache_mk_rd_entry2(struct rdata* rd)
1313 struct tmp_rec rec[MAX_DNS_RECORDS];
1314 int rec_idx[MAX_DNS_RECORDS];
1316 int no_records; /* number of different records */
1322 /* everything is allocated in one block: dns_hash_entry + name +
1323 * + dns_rr + rdata_raw+ ....; dns_rr must start at an aligned adress,
1324 * hence we need to round dns_hash_entry+name size to a sizeof(long)
1325 * multiple. If rdata type requires it, rdata_raw might need to be also
1328 * struct dns_hash_entry (e)
1329 * name (name_len+1 bytes) (&e->name[0])
1330 * padding to multiple of sizeof(char*)
1331 * dns_rr1 (e->rr_lst)
1332 * possible padding: no padding for a_rdata or aaaa_rdata,
1333 * multipe of sizeof(short) for srv_rdata,
1334 * multiple of sizeof(long) for naptr_rdata and others
1335 * dns_rr1->rdata (e->rr_lst->rdata)
1336 * padding to multipe of sizeof long
1337 * dns_rr2 (e->rr_lst->next)
1342 for(l=rd, i=0; l && (i<MAX_DNS_RECORDS); l=l->next, i++){
1343 for (r=0; r<no_records; r++){
1344 if ((l->type==rec[r].rd->type) &&
1345 (l->name_len==rec[r].rd->name_len)
1346 && (strncasecmp(l->name, rec[r].rd->name, l->name_len)==0)){
1351 /* not found, create new */
1352 if (no_records<MAX_DNS_RECORDS){
1355 rec[r].size=ROUND_POINTER(sizeof(struct dns_hash_entry)+
1356 rec[r].rd->name_len-1+1);
1359 LM_ERR("too many records: %d\n", no_records);
1368 rec[r].size+=ROUND_POINTER(sizeof(struct dns_rr)+
1369 sizeof(struct a_rdata));
1373 rec[r].size+=ROUND_POINTER(sizeof(struct dns_rr)+
1374 sizeof(struct aaaa_rdata));
1377 /* padding to short */
1378 rec[r].size+=ROUND_POINTER(ROUND_SHORT(sizeof(struct dns_rr))+
1379 SRV_RDATA_SIZE(*(struct srv_rdata*)l->rdata));
1382 /* padding to char* */
1383 rec[r].size+=ROUND_POINTER(ROUND_POINTER(
1384 sizeof(struct dns_rr))+
1385 NAPTR_RDATA_SIZE(*(struct naptr_rdata*)l->rdata));
1389 rec[r].size+=ROUND_POINTER(sizeof(struct dns_rr)+
1390 CNAME_RDATA_SIZE(*(struct cname_rdata*)l->rdata));
1393 /* padding to char* (because of txt[]->cstr)*/
1394 rec[r].size+=ROUND_POINTER(ROUND_POINTER(
1395 sizeof(struct dns_rr))+
1396 TXT_RDATA_SIZE(*(struct txt_rdata*)l->rdata));
1399 /* padding to char* (because of char* pointers)*/
1400 rec[r].size+=ROUND_POINTER(ROUND_POINTER(
1401 sizeof(struct dns_rr))+
1402 EBL_RDATA_SIZE(*(struct ebl_rdata*)l->rdata));
1406 rec[r].size+=ROUND_POINTER(sizeof(struct dns_rr)+
1407 PTR_RDATA_SIZE(*(struct ptr_rdata*)l->rdata));
1410 LM_CRIT("type %d not supported\n", l->type);
1414 now=get_ticks_raw();
1415 /* alloc & init the entries */
1416 for (r=0; r<no_records; r++){
1417 rec[r].e=shm_malloc(rec[r].size);
1422 memset(rec[r].e, 0, rec[r].size); /* init with 0*/
1423 rec[r].e->total_size=rec[r].size;
1424 rec[r].e->name_len=rec[r].rd->name_len;
1425 rec[r].e->type=rec[r].rd->type;
1426 rec[r].e->last_used=now;
1427 /* memset makes sure is 0-term. */
1428 memcpy(rec[r].e->name, rec[r].rd->name, rec[r].rd->name_len);
1429 rec[r].e->rr_lst=(struct dns_rr*)((char*)rec[r].e+
1430 ROUND_POINTER(sizeof(struct dns_hash_entry)+rec[r].e->name_len
1432 rec[r].tail_rr=&(rec[r].e->rr_lst);
1433 rec[r].rr=rec[r].e->rr_lst;
1435 /* link them in a list */
1437 clist_init(rec[r].e, next, prev);
1439 clist_append(rec[0].e, rec[r].e, next, prev);
1442 /* copy the actual data */
1443 for(l=rd, i=0; l && (i<MAX_DNS_RECORDS); l=l->next, i++){
1445 ttl=FIX_TTL(l->ttl);
1448 rec[r].rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1449 rec[r].max_ttl=MAX(rec[r].max_ttl, ttl);
1450 rec[r].rr->rdata=(void*)((char*)rec[r].rr+
1451 sizeof(struct dns_rr));
1452 memcpy(rec[r].rr->rdata, l->rdata, sizeof(struct a_rdata));
1453 rec[r].rr->next=(void*)((char*)rec[r].rr+
1454 ROUND_POINTER(sizeof(struct dns_rr)+
1455 sizeof(struct a_rdata)));
1456 rec[r].tail_rr=&(rec[r].rr->next);
1457 rec[r].rr=rec[r].rr->next;
1460 rec[r].rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1461 rec[r].max_ttl=MAX(rec[r].max_ttl, ttl);
1462 rec[r].rr->rdata=(void*)((char*)rec[r].rr+
1463 sizeof(struct dns_rr));
1464 memcpy(rec[r].rr->rdata, l->rdata, sizeof(struct aaaa_rdata));
1465 rec[r].rr->next=(void*)((char*)rec[r].rr+
1466 ROUND_POINTER(sizeof(struct dns_rr)+
1467 sizeof(struct aaaa_rdata)));
1468 rec[r].tail_rr=&(rec[r].rr->next);
1469 rec[r].rr=rec[r].rr->next;
1472 rec[r].rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1473 rec[r].max_ttl=MAX(rec[r].max_ttl, ttl);
1474 rec[r].rr->rdata=(void*)((char*)rec[r].rr+
1475 ROUND_SHORT(sizeof(struct dns_rr)));
1476 /* copy the whole srv_rdata block*/
1477 memcpy(rec[r].rr->rdata, l->rdata,
1478 SRV_RDATA_SIZE(*(struct srv_rdata*)l->rdata) );
1479 rec[r].rr->next=(void*)((char*)rec[r].rr+
1480 ROUND_POINTER( ROUND_SHORT(sizeof(struct dns_rr))+
1482 *(struct srv_rdata*)l->rdata)));
1483 rec[r].tail_rr=&(rec[r].rr->next);
1484 rec[r].rr=rec[r].rr->next;
1487 rec[r].rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1488 rec[r].max_ttl=MAX(rec[r].max_ttl, ttl);
1489 rec[r].rr->rdata=(void*)((char*)rec[r].rr+
1490 ROUND_POINTER(sizeof(struct dns_rr)));
1491 /* copy the whole srv_rdata block*/
1492 memcpy(rec[r].rr->rdata, l->rdata,
1493 NAPTR_RDATA_SIZE(*(struct naptr_rdata*)l->rdata) );
1494 /* adjust the string pointer */
1495 ((struct naptr_rdata*)rec[r].rr->rdata)->flags=
1496 translate_pointer((char*)rec[r].rr->rdata, (char*)l->rdata,
1497 (((struct naptr_rdata*)l->rdata)->flags));
1498 ((struct naptr_rdata*)rec[r].rr->rdata)->services=
1499 translate_pointer((char*)rec[r].rr->rdata, (char*)l->rdata,
1500 (((struct naptr_rdata*)l->rdata)->services));
1501 ((struct naptr_rdata*)rec[r].rr->rdata)->regexp=
1502 translate_pointer((char*)rec[r].rr->rdata, (char*)l->rdata,
1503 (((struct naptr_rdata*)l->rdata)->regexp));
1504 ((struct naptr_rdata*)rec[r].rr->rdata)->repl=
1505 translate_pointer((char*)rec[r].rr->rdata, (char*)l->rdata,
1506 (((struct naptr_rdata*)l->rdata)->repl));
1507 rec[r].rr->next=(void*)((char*)rec[r].rr+
1508 ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
1510 *(struct naptr_rdata*)l->rdata)));
1511 rec[r].tail_rr=&(rec[r].rr->next);
1512 rec[r].rr=rec[r].rr->next;
1515 rec[r].rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1516 rec[r].max_ttl=MAX(rec[r].max_ttl, ttl);
1517 rec[r].rr->rdata=(void*)((char*)rec[r].rr
1518 +sizeof(struct dns_rr));
1519 memcpy(rec[r].rr->rdata, l->rdata,
1520 CNAME_RDATA_SIZE(*(struct cname_rdata*)l->rdata));
1521 rec[r].rr->next=(void*)((char*)rec[r].rr+
1522 ROUND_POINTER(sizeof(struct dns_rr)+
1523 CNAME_RDATA_SIZE(*(struct cname_rdata*)l->rdata)));
1524 rec[r].tail_rr=&(rec[r].rr->next);
1525 rec[r].rr=rec[r].rr->next;
1528 rec[r].rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1529 rec[r].max_ttl=MAX(rec[r].max_ttl, ttl);
1530 rec[r].rr->rdata=(void*)((char*)rec[r].rr+
1531 ROUND_POINTER(sizeof(struct dns_rr)));
1532 memcpy(rec[r].rr->rdata, l->rdata,
1533 TXT_RDATA_SIZE(*(struct txt_rdata*)l->rdata));
1534 /* adjust the string pointers */
1535 for (j=0; j<((struct txt_rdata*)l->rdata)->cstr_no; j++){
1536 ((struct txt_rdata*)rec[r].rr->rdata)->txt[j].cstr=
1537 translate_pointer((char*)rec[r].rr->rdata,
1539 ((struct txt_rdata*)l->rdata)->txt[j].cstr);
1541 rec[r].rr->next=(void*)((char*)rec[r].rr+
1542 ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
1543 TXT_RDATA_SIZE(*(struct txt_rdata*)l->rdata)));
1544 rec[r].tail_rr=&(rec[r].rr->next);
1545 rec[r].rr=rec[r].rr->next;
1548 rec[r].rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1549 rec[r].max_ttl=MAX(rec[r].max_ttl, ttl);
1550 rec[r].rr->rdata=(void*)((char*)rec[r].rr+
1551 ROUND_POINTER(sizeof(struct dns_rr)));
1552 memcpy(rec[r].rr->rdata, l->rdata,
1553 EBL_RDATA_SIZE(*(struct ebl_rdata*)l->rdata));
1554 /* adjust the string pointers */
1555 ((struct ebl_rdata*)rec[r].rr->rdata)->separator=
1556 translate_pointer((char*)rec[r].rr->rdata,
1558 ((struct ebl_rdata*)l->rdata)->separator);
1559 ((struct ebl_rdata*)rec[r].rr->rdata)->apex=
1560 translate_pointer((char*)rec[r].rr->rdata,
1562 ((struct ebl_rdata*)l->rdata)->apex);
1563 rec[r].rr->next=(void*)((char*)rec[r].rr+
1564 ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
1565 EBL_RDATA_SIZE(*(struct ebl_rdata*)l->rdata)));
1566 rec[r].tail_rr=&(rec[r].rr->next);
1567 rec[r].rr=rec[r].rr->next;
1570 rec[r].rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1571 rec[r].max_ttl=MAX(rec[r].max_ttl, ttl);
1572 rec[r].rr->rdata=(void*)((char*)rec[r].rr
1573 +sizeof(struct dns_rr));
1574 memcpy(rec[r].rr->rdata, l->rdata,
1575 PTR_RDATA_SIZE(*(struct ptr_rdata*)l->rdata));
1576 rec[r].rr->next=(void*)((char*)rec[r].rr+
1577 ROUND_POINTER(sizeof(struct dns_rr)+
1578 PTR_RDATA_SIZE(*(struct ptr_rdata*)l->rdata)));
1579 rec[r].tail_rr=&(rec[r].rr->next);
1580 rec[r].rr=rec[r].rr->next;
1587 for (r=0; r<no_records; r++){
1588 *rec[r].tail_rr=0; /* terminate the list */
1589 rec[r].e->expire=now+S_TO_TICKS(rec[r].max_ttl);
1593 for (r=0; r<no_records; r++){
1594 dns_destroy_entry(rec[r].e);
1601 inline static struct dns_hash_entry* dns_get_entry(str* name, int type);
1604 #define CACHE_RELEVANT_RECS_ONLY
1606 #ifdef CACHE_RELEVANT_RECS_ONLY
1607 /* internal only: gets related entries from a rdata list, appends them
1608 * to e (list) and returns:
1609 * - e if e is of the requested type
1610 * - if e is a CNAME, tries to get to the end of the CNAME chain and returns
1611 * the final entry if the types match or 0 if the chain is unfinished
1612 * - 0 on error/not found
1613 * records is modified (the used records are removed from the list and freed)
1615 * WARNING: - records must be pkg_malloc'ed
1616 * Notes: - if the return is 0 and e->type==T_CNAME, the list will contain
1617 * the CNAME chain (the last element being the last CNAME)
1619 inline static struct dns_hash_entry* dns_get_related(struct dns_hash_entry* e,
1621 struct rdata** records)
1623 struct dns_hash_entry* ret;
1624 struct dns_hash_entry* l;
1625 struct dns_hash_entry* t;
1626 struct dns_hash_entry* lst_end;
1628 static int cname_chain_len=0;
1633 LM_DBG("(%p (%.*s, %d), %d, *%p) (%d)\n", e,
1634 e->name_len, e->name, e->type, type, *records, cname_chain_len);
1635 clist_init(l, next, prev);
1640 for (rr=e->rr_lst; rr && *records; rr=rr->next){
1641 tmp.s=((struct srv_rdata*)rr->rdata)->name;
1642 tmp.len=((struct srv_rdata*)rr->rdata)->name_len;
1643 if (!(dns_flags&DNS_IPV6_ONLY)){
1644 t=dns_cache_mk_rd_entry(&tmp, T_A, records);
1646 if ((t->type==T_CNAME) && *records)
1647 dns_get_related(t, T_A, records);
1648 lst_end=t->prev; /* needed for clist_append*/
1649 clist_append_sublist(l, t, lst_end, next, prev);
1652 if (!(dns_flags&DNS_IPV4_ONLY)){
1653 t=dns_cache_mk_rd_entry(&tmp, T_AAAA, records);
1655 if ((t->type==T_CNAME) && *records)
1656 dns_get_related(t, T_AAAA, records);
1657 lst_end=t->prev; /* needed for clist_append*/
1658 clist_append_sublist(l, t, lst_end, next, prev);
1665 #ifdef NAPTR_CACHE_ALL_ARS
1667 dns_cache_mk_rd_entry2(*records);
1669 for (rr=e->rr_lst; rr && *records; rr=rr->next){
1670 if (naptr_get_sip_proto((struct naptr_rdata*)rr->rdata)>0){
1671 tmp.s=((struct naptr_rdata*)rr->rdata)->repl;
1672 tmp.len=((struct naptr_rdata*)rr->rdata)->repl_len;
1673 t=dns_cache_mk_rd_entry(&tmp, T_SRV, records);
1676 dns_get_related(t, T_SRV, records);
1677 lst_end=t->prev; /* needed for clist_append*/
1678 clist_append_sublist(l, t, lst_end, next, prev);
1682 #endif /* NAPTR_CACHE_ALL_ARS */
1683 #endif /* USE_NAPTR */
1689 }else if ((e->type==T_CNAME) && (cname_chain_len<MAX_CNAME_CHAIN)){
1690 /* only one cname is allowed (rfc2181), so we ignore
1691 * the others (we take only the first one) */
1692 tmp.s=((struct cname_rdata*)e->rr_lst->rdata)->name;
1693 tmp.len=((struct cname_rdata*)e->rr_lst->rdata)->name_len;
1694 t=dns_cache_mk_rd_entry(&tmp, type, records);
1698 ret=dns_get_related(t, type, records);
1701 clist_append_sublist(l, t, lst_end, next, prev);
1703 /* if no more recs, but we found the orig. target anyway,
1704 * return it (e.g. recs are only CNAME x & x A 1.2.3.4 or
1708 clist_append(l, t, next, prev);
1718 /* calls the external resolver and populates the cache with the result
1719 * returns: 0 on error, pointer to hash entry on success
1720 * WARNING: make sure you use dns_hash_entry_put() when you're
1721 * finished with the result)
1723 inline static struct dns_hash_entry* dns_cache_do_request(str* name, int type)
1725 struct rdata* records;
1726 struct dns_hash_entry* e;
1727 struct dns_hash_entry* l;
1728 struct dns_hash_entry* r;
1729 struct dns_hash_entry* t;
1732 char name_buf[MAX_DNS_NAME];
1733 struct dns_hash_entry* old;
1735 int add_record, h, err;
1742 #ifdef USE_DNS_CACHE_STATS
1743 if (dns_cache_stats)
1744 dns_cache_stats[process_no].dns_req_cnt++;
1745 #endif /* USE_DNS_CACHE_STATS */
1748 if (str2ip6(name)!=0)
1750 if ((ip=str2ip(name))!=0){
1751 e=dns_cache_mk_ip_entry(name, ip);
1753 atomic_set(&e->refcnt, 1);/* because we ret. a ref. to it*/
1754 goto end; /* we do not cache obvious stuff */
1757 else if (type==T_AAAA){
1758 if (str2ip(name)!=0)
1760 if ((ip=str2ip6(name))!=0){
1761 e=dns_cache_mk_ip_entry(name, ip);
1763 atomic_set(&e->refcnt, 1);/* because we ret. a ref. to it*/
1764 goto end;/* we do not cache obvious stuff */
1767 #ifdef DNS_WATCHDOG_SUPPORT
1768 if (atomic_get(dns_servers_up)==0)
1769 goto end; /* the servers are down, needless to perform the query */
1771 if (name->len>=MAX_DNS_NAME){
1772 LM_ERR("name too long (%d chars)\n", name->len);
1775 /* null terminate the string, needed by get_record */
1776 memcpy(name_buf, name->s, name->len);
1777 name_buf[name->len]=0;
1778 records=get_record(name_buf, type, RES_AR);
1780 #ifdef CACHE_RELEVANT_RECS_ONLY
1781 e=dns_cache_mk_rd_entry(name, type, &records);
1784 e=dns_get_related(l, type, &records);
1785 /* e should contain the searched entry (if found) and l
1786 * all the entries (e and related) */
1788 atomic_set(&e->refcnt, 1); /* 1 because we return a
1791 /* e==0 => l contains a cname list => we use the last
1792 * cname from the chain for a new resolve attempt (l->prev) */
1793 /* only one cname record is allowed (rfc2181), so we ignore
1794 * the others (we take only the first one) */
1796 ((struct cname_rdata*)l->prev->rr_lst->rdata)->name;
1798 ((struct cname_rdata*)l->prev->rr_lst->rdata)->name_len;
1799 LM_DBG("cname detected: %.*s (%d)\n",
1800 cname_val.len, cname_val.s, cname_val.len);
1802 /* add all the records to the hash */
1803 l->prev->next=0; /* we break the double linked list for easier
1805 LOCK_DNS_HASH(); /* optimization */
1808 /* add the new record to the cache by default */
1810 if (cfg_get(core, core_cfg, dns_cache_rec_pref) > 0) {
1811 /* check whether there is an old record with the
1812 * same type in the cache */
1813 rec_name.s = r->name;
1814 rec_name.len = r->name_len;
1815 old = _dns_hash_find(&rec_name, r->type, &h, &err);
1817 if (old->type != r->type) {
1818 /* probably CNAME found */
1821 } else if (old->ent_flags & DNS_FLAG_PERMANENT) {
1822 /* never overwrite permanent entries */
1825 } else if ((old->ent_flags & DNS_FLAG_BAD_NAME) == 0) {
1826 /* Non-negative, non-permanent entry found with
1829 /* prefer new records */
1830 ((cfg_get(core, core_cfg, dns_cache_rec_pref) == 2)
1831 /* prefer the record with the longer lifetime */
1832 || ((cfg_get(core, core_cfg, dns_cache_rec_pref) == 3)
1833 && TICKS_LT(old->expire, r->expire)));
1838 dns_cache_add_unsafe(r); /* refcnt++ inside */
1839 if (atomic_get(&r->refcnt)==0){
1840 /* if cache adding failed and nobody else is interested
1841 * destroy this entry */
1842 dns_destroy_entry(r);
1845 _dns_hash_remove(old);
1851 /* this entry has to be returned */
1853 atomic_inc(&e->refcnt);
1857 dns_destroy_entry(r);
1861 /* if only cnames found => try to resolve the last one */
1863 LM_DBG("dns_get_entry(cname: %.*s (%d))\n",
1864 cname_val.len, cname_val.s, cname_val.len);
1865 e=dns_get_entry(&cname_val, type);
1869 l=dns_cache_mk_rd_entry2(records);
1871 free_rdata_list(records);
1872 }else if (cfg_get(core, core_cfg, dns_neg_cache_ttl)){
1873 e=dns_cache_mk_bad_entry(name, type,
1874 cfg_get(core, core_cfg, dns_neg_cache_ttl), DNS_FLAG_BAD_NAME);
1876 atomic_set(&e->refcnt, 1); /* 1 because we return a ref. to it */
1877 dns_cache_add(e); /* refcnt++ inside*/
1881 #ifndef CACHE_RELEVANT_RECS_ONLY
1883 /* add all the records to the cache, but return only the record
1884 * we are looking for */
1885 l->prev->next=0; /* we break the double linked list for easier
1887 LOCK_DNS_HASH(); /* optimization */
1890 if (e==0){ /* no entry found yet */
1891 if (r->type==T_CNAME){
1892 if ((r->name_len==name->len) && (r->rr_lst) &&
1893 (strncasecmp(r->name, name->s, name->len)==0)){
1894 /* update the name with the name from the cname rec. */
1896 ((struct cname_rdata*)r->rr_lst->rdata)->name;
1898 ((struct cname_rdata*)r->rr_lst->rdata)->name_len;
1901 }else if ((r->type==type) && (r->name_len==name->len) &&
1902 (strncasecmp(r->name, name->s, name->len)==0)){
1904 atomic_set(&e->refcnt, 1); /* 1 because we return a ref.
1909 /* add the new record to the cache by default */
1911 if (cfg_get(core, core_cfg, dns_cache_rec_pref) > 0) {
1912 /* check whether there is an old record with the
1913 * same type in the cache */
1914 rec_name.s = r->name;
1915 rec_name.len = r->name_len;
1916 old = _dns_hash_find(&rec_name, r->type, &h, &err);
1918 if (old->type != r->type) {
1919 /* probably CNAME found */
1922 } else if (old->ent_flags & DNS_FLAG_PERMANENT) {
1923 /* never overwrite permanent entries */
1926 } else if ((old->ent_flags & DNS_FLAG_BAD_NAME) == 0) {
1927 /* Non-negative, non-permanent entry found with
1930 /* prefer new records */
1931 ((cfg_get(core, core_cfg, dns_cache_rec_pref) == 2)
1932 /* prefer the record with the longer lifetime */
1933 || ((cfg_get(core, core_cfg, dns_cache_rec_pref) == 3)
1934 && TICKS_LT(old->expire, r->expire)));
1939 dns_cache_add_unsafe(r); /* refcnt++ inside */
1940 if (atomic_get(&r->refcnt)==0){
1941 /* if cache adding failed and nobody else is interested
1942 * destroy this entry */
1943 dns_destroy_entry(r);
1946 _dns_hash_remove(old);
1952 /* this entry has to be returned */
1954 atomic_inc(&e->refcnt);
1958 dns_destroy_entry(r);
1962 if ((e==0) && (cname_val.s)){ /* not found, but found a cname */
1963 /* only one cname is allowed (rfc2181), so we ignore the
1964 * others (we take only the first one) */
1965 e=dns_get_entry(&cname_val, type);
1975 /* tries to lookup (name, type) in the hash and if not found tries to make
1977 * return: 0 on error, pointer to a dns_hash_entry on success
1978 * WARNING: when not needed anymore dns_hash_put() must be called! */
1979 inline static struct dns_hash_entry* dns_get_entry(str* name, int type)
1982 struct dns_hash_entry* e;
1985 static int rec_cnt=0; /* recursion protection */
1988 if (rec_cnt>MAX_CNAME_CHAIN){
1989 LM_WARN("CNAME chain too long or recursive CNAMEs (\"%.*s\")\n",
1990 name->len, name->s);
1994 e=dns_hash_get(name, type, &h, &err);
1995 #ifdef USE_DNS_CACHE_STATS
1997 if ((e->ent_flags & DNS_FLAG_BAD_NAME) && dns_cache_stats)
1998 /* negative DNS cache hit */
1999 dns_cache_stats[process_no].dc_neg_hits_cnt++;
2000 else if (((e->ent_flags & DNS_FLAG_BAD_NAME) == 0)
2002 ) /* DNS cache hit */
2003 dns_cache_stats[process_no].dc_hits_cnt++;
2005 if (dns_cache_stats)
2006 dns_cache_stats[process_no].dns_req_cnt++;
2008 #endif /* USE_DNS_CACHE_STATS */
2010 if ((e==0) && ((err) || ((e=dns_cache_do_request(name, type))==0))){
2012 }else if ((e->type==T_CNAME) && (type!=T_CNAME)){
2013 /* cname found instead which couldn't be resolved with the cached
2014 * info => try a dns request */
2015 /* only one cname record is allowed (rfc2181), so we ignore
2016 * the others (we take only the first one) */
2017 cname_val.s= ((struct cname_rdata*)e->rr_lst->rdata)->name;
2018 cname_val.len=((struct cname_rdata*)e->rr_lst->rdata)->name_len;
2019 dns_hash_put(e); /* not interested in the cname anymore */
2020 if ((e=dns_cache_do_request(&cname_val, type))==0)
2021 goto error; /* could not resolve cname */
2024 if ((e->rr_lst==0) || (e->ent_flags & DNS_FLAG_BAD_NAME)){
2025 /* negative cache => not resolvable */
2036 /* gets the first non-expired record starting with record no
2037 * from the dns_hash_entry struct e
2038 * params: e - dns_hash_entry struct
2039 * *no - it must contain the start record number (0 initially);
2040 * it will be filled with the returned record number
2041 * now - current time/ticks value
2042 * returns pointer to the rr on success and sets no to the rr number
2043 * 0 on error and fills the error flags
2046 * list all non-expired non-bad-marked ips for name:
2047 * e=dns_get_entry(name, T_A);
2050 * now=get_ticks_raw();
2051 * while(rr=dns_entry_get_rr(e, no, now){
2052 * LM_DBG("address %d\n", *no);
2053 * *no++; ( get the next address next time )
2057 inline static struct dns_rr* dns_entry_get_rr( struct dns_hash_entry* e,
2058 unsigned char* no, ticks_t now)
2062 #ifdef DNS_WATCHDOG_SUPPORT
2065 servers_up = atomic_get(dns_servers_up);
2068 for(rr=e->rr_lst, n=0;rr && (n<*no);rr=rr->next, n++);/* skip *no records*/
2069 for(;rr;rr=rr->next){
2071 #ifdef DNS_WATCHDOG_SUPPORT
2072 /* check the expiration time only when the servers are up */
2075 ((e->ent_flags & DNS_FLAG_PERMANENT) == 0) &&
2076 ((s_ticks_t)(now-rr->expire)>=0) /* expired rr */
2079 /* everything is ok now */
2090 #define srv_reset_tried(p) (*(p)=0)
2091 #define srv_marked(p, i) (*(p)&(1UL<<(i)))
2092 #define srv_mark_tried(p, i) \
2094 (*(p)|=(1UL<<(i))); \
2097 #define srv_next_rr(n, f, i) srv_mark_tried(f, i)
2099 /* returns a random number between 0 and max inclusive (0<=r<=max) */
2100 inline static unsigned dns_srv_random(unsigned max)
2102 return fastrand_max(max);
2105 /* for a SRV record it will return the next entry to be tried according
2106 * to the RFC2782 server selection mechanism
2108 * e is a dns srv hash entry
2109 * no is the start index of the current group (a group is a set of SRV
2110 * rrs with the same priority)
2111 * tried is a bitmap where the tried srv rrs of the same priority are
2113 * now - current time/ticks value
2114 * returns pointer to the rr on success and sets no to the rr number
2115 * 0 on error and fills the error flags
2116 * WARNING: unlike dns_entry_get_rr() this will always return another
2117 * another rr automatically (*no must not be incremented)
2120 * list all non-expired, non-bad-marked, never tried before srv records
2121 * using the rfc2782 algo:
2122 * e=dns_get_entry(name, T_SRV);
2125 * srv_reset_tried(&tried);
2126 * now=get_ticks_raw();
2127 * while(rr=dns_srv_get_nxt_rr(e, &tried, &no, now){
2128 * LM_DBG("address %d\n", *no);
2133 inline static struct dns_rr* dns_srv_get_nxt_rr(struct dns_hash_entry* e,
2135 unsigned char* no, ticks_t now)
2137 #define MAX_SRV_GRP_IDX (sizeof(srv_flags_t)*8)
2139 struct dns_rr* start_grp;
2146 int zero_weight; /* number of records with 0 weight */
2148 struct r_sums_entry{
2151 }r_sums[MAX_SRV_GRP_IDX];
2152 #ifdef DNS_WATCHDOG_SUPPORT
2155 servers_up = atomic_get(dns_servers_up);
2158 memset(r_sums, 0, sizeof(struct r_sums_entry) * MAX_SRV_GRP_IDX);
2160 for(rr=e->rr_lst, n=0;rr && (n<*no);rr=rr->next, n++);/* skip *no records*/
2163 if (unlikely(rr==0))
2166 prio=((struct srv_rdata*)start_grp->rdata)->priority;
2171 for (idx=0;rr && (prio==((struct srv_rdata*)rr->rdata)->priority) &&
2172 (idx < MAX_SRV_GRP_IDX); idx++, rr=rr->next){
2174 #ifdef DNS_WATCHDOG_SUPPORT
2175 /* check the expiration time only when the servers are up */
2178 ((e->ent_flags & DNS_FLAG_PERMANENT) == 0) &&
2179 ((s_ticks_t)(now-rr->expire)>=0) /* expired entry */) ||
2180 (srv_marked(tried, idx)) ) /* already tried */{
2181 r_sums[idx].r_sum=0; /* 0 sum, to skip over it */
2182 r_sums[idx].rr=0; /* debug: mark it as unused */
2185 /* special case, 0 weight records should be "first":
2186 * remember the first rr int the "virtual" list: A 0 weight must
2187 * come first if present, else get the first one */
2188 if ((saved_idx==-1) || (((struct srv_rdata*)rr->rdata)->weight==0)){
2191 zero_weight += (((struct srv_rdata*)rr->rdata)->weight == 0);
2192 sum+=((struct srv_rdata*)rr->rdata)->weight;
2193 r_sums[idx].r_sum=sum;
2198 /* try in the next priority group */
2199 n+=idx; /* next group start idx, last rr */
2200 srv_reset_tried(tried);
2202 }else if ((found==1) || (sum==0) ||
2203 (((rand_w=(dns_srv_random(sum-1)+1))==1) && zero_weight &&
2204 (dns_srv_random(DNS_SRV_ZERO_W_CHANCE)==0))){
2205 /* 1. if only one found, avoid a useless random() call
2206 and select it (saved_idx will point to it).
2207 * 2. if the sum of weights is 0 (all have 0 weight) or
2208 * 3. rand_w==1 and there are records with 0 weight and
2209 * random(probab. of selecting a 0-weight)
2210 * immediately select a 0 weight record.
2211 * (this takes care of the 0-weight at the beginning requirement) */
2212 i=saved_idx; /* saved idx contains either first 0 weight or first
2216 /* if we are here => rand_w is not 0 and we have at least 2 valid options
2217 * => we can safely iterate on the whole r_sums[] whithout any other
2219 for (i=0; (i<idx) && (r_sums[i].r_sum<rand_w); i++);
2221 if(i<MAX_SRV_GRP_IDX) {
2222 LM_DBG("(%p, %lx, %d, %u): selected %d/%d in grp. %d"
2223 " (rand_w=%d, rr=%p rd=%p p=%d w=%d rsum=%d)\n",
2224 e, (unsigned long)*tried, *no, now, i, idx, n, rand_w,
2225 r_sums[i].rr, (r_sums[i].rr) ? r_sums[i].rr->rdata : 0,
2226 (r_sums[i].rr && r_sums[i].rr->rdata)
2227 ? ((struct srv_rdata *)r_sums[i].rr->rdata)->priority
2229 (r_sums[i].rr && r_sums[i].rr->rdata)
2230 ? ((struct srv_rdata *)r_sums[i].rr->rdata)->weight
2233 /* i is the winner */
2234 *no = n; /* grp. start */
2235 if(i < 8 * sizeof(*tried))
2236 srv_mark_tried(tried, i); /* mark it */
2237 return r_sums[i].rr;
2239 LM_WARN("index out of bounds\n");
2247 #endif /* DNS_SRV_LB */
2251 /* gethostbyname compatibility: converts a dns_hash_entry structure
2252 * to a statical internal hostent structure
2253 * returns a pointer to the internal hostent structure on success or
2256 inline static struct hostent* dns_entry2he(struct dns_hash_entry* e)
2258 static struct hostent he;
2259 static char hostname[256];
2260 static char* p_aliases[1];
2261 static char* p_addr[DNS_HE_MAX_ADDR+1];
2262 static char address[16*DNS_HE_MAX_ADDR]; /* max 10 ipv6 addresses */
2265 unsigned char rr_no;
2280 LM_CRIT("wrong entry type %d for %.*s\n",
2281 e->type, e->name_len, e->name);
2287 now=get_ticks_raw();
2288 /* if the entry has already expired use the time at the end of lifetime */
2289 if (unlikely((s_ticks_t)(now-e->expire)>=0)) now=e->expire-1;
2290 rr=dns_entry_get_rr(e, &rr_no, now);
2291 for(i=0; rr && (i<DNS_HE_MAX_ADDR); i++,
2292 rr=dns_entry_get_rr(e, &rr_no, now)){
2293 p_addr[i]=&address[i*len];
2296 ip = ((struct a_rdata*)rr->rdata)->ip;
2299 ip = ((struct aaaa_rdata*)rr->rdata)->ip6;
2302 LM_CRIT("wrong entry type %d for %.*s\n",
2303 e->type, e->name_len, e->name);
2306 memcpy(p_addr[i], ip, len);
2310 LM_DBG("no good records found (%d) for %.*s (%d)\n",
2311 rr_no, e->name_len, e->name, e->type);
2312 return 0; /* no good record found */
2315 p_addr[i]=0; /* mark the end of the addresses */
2316 p_aliases[0]=0; /* no aliases */
2317 memcpy(hostname, e->name, e->name_len);
2318 hostname[e->name_len]=0;
2322 he.h_addr_list=p_addr;
2323 he.h_aliases=p_aliases;
2331 /* gethostbyname compatibility: performs an a_lookup and returns a pointer
2332 * to a statical internal hostent structure
2333 * returns 0 on success, <0 on error (see the error codes)
2335 inline static struct hostent* dns_a_get_he(str* name)
2337 struct dns_hash_entry* e;
2342 if (str2ip6(name)!=0)
2344 if ((ip=str2ip(name))!=0){
2345 return ip_addr2he(name, ip);
2347 if ((e=dns_get_entry(name, T_A))==0)
2356 /* gethostbyname compatibility: performs an aaaa_lookup and returns a pointer
2357 * to a statical internal hostent structure
2358 * returns 0 on success, <0 on error (see the error codes)
2360 inline static struct hostent* dns_aaaa_get_he(str* name)
2362 struct dns_hash_entry* e;
2367 if (str2ip(name)!=0)
2369 if ((ip=str2ip6(name))!=0){
2370 return ip_addr2he(name, ip);
2372 if ((e=dns_get_entry(name, T_AAAA))==0)
2382 /* returns 0 on success, -1 on error (rr type does not contain an ip) */
2383 inline static int dns_rr2ip(int type, struct dns_rr* rr, struct ip_addr* ip)
2389 memcpy(ip->u.addr, ((struct a_rdata*)rr->rdata)->ip, 4);
2395 memcpy(ip->u.addr, ((struct aaaa_rdata*)rr->rdata)->ip6, 16);
2404 /* gethostbyname compatibility:
2405 * performs an a or aaaa dns lookup, returns 0 on error and a pointer to a
2406 * static hostent structure on success
2407 * flags: - none set: tries first an a_lookup and if it fails an aaaa_lookup
2408 * - DNS_IPV6_FIRST: tries first an aaaa_lookup and then an a_lookup
2409 * - DNS_IPV4_ONLY: tries only an a_lookup
2410 * - DNS_IPV6_ONLY: tries only an aaaa_lookup
2412 struct hostent* dns_get_he(str* name, int flags)
2416 if ((flags&(DNS_IPV6_FIRST|DNS_IPV6_ONLY))){
2417 he=dns_aaaa_get_he(name);
2420 he=dns_a_get_he(name);
2423 if (flags&DNS_IPV6_FIRST){
2424 he=dns_a_get_he(name);
2425 }else if (!(flags&(DNS_IPV6_ONLY|DNS_IPV4_ONLY))){
2426 he=dns_aaaa_get_he(name);
2433 /* sip_resolvehost helper: gets the first good hostent/port combination
2434 * returns 0 on error, pointer to static hostent structure on success
2436 struct hostent* dns_srv_get_he(str* name, unsigned short* port, int flags)
2438 struct dns_hash_entry* e;
2443 unsigned char rr_no;
2447 now=get_ticks_raw();
2448 if ((e=dns_get_entry(name, T_SRV))==0)
2450 /* look inside the RRs for a good one (not expired or marked bad) */
2452 while( (rr=dns_entry_get_rr(e, &rr_no, now))!=0){
2453 /* everything is ok now, we can try to resolve the ip */
2454 rr_name.s=((struct srv_rdata*)rr->rdata)->name;
2455 rr_name.len=((struct srv_rdata*)rr->rdata)->name_len;
2456 if ((he=dns_get_he(&rr_name, flags))!=0){
2457 /* success, at least one good ip found */
2458 if(port) *port=((struct srv_rdata*)rr->rdata)->port;
2461 rr_no++; /* try from the next record, the current one was not good */
2463 /* if we reach this point => error, we couldn't find any good rr */
2465 if (e) dns_hash_put(e);
2472 struct hostent* dns_resolvehost(char* name)
2475 struct hostent* ret;
2476 if ((cfg_get(core, core_cfg, use_dns_cache)==0) || (dns_hash==0)){ /* not init yet */
2477 ret = _resolvehost(name);
2479 /* increment dns error counter */
2480 if(counters_initialized())
2481 counter_inc(dns_cnts_h.failed_dns_req);
2486 host.len=strlen(name);
2487 return dns_get_he(&host, dns_flags);
2494 /* resolves a host name trying NAPTR, SRV, A & AAAA lookups, for details
2495 * see dns_sip_resolve()
2496 * FIXME: this version will return only the first ip
2497 * returns: hostent struct & *port filled with the port from the SRV record;
2500 struct hostent* dns_sip_resolvehost(str* name, unsigned short* port,
2503 struct dns_srv_handle h;
2507 if ((cfg_get(core, core_cfg, use_dns_cache==0)) || (dns_hash==0)){
2508 /* not init or off => use normal, non-cached version */
2509 return _sip_resolvehost(name, port, proto);
2511 dns_srv_handle_init(&h);
2512 ret=dns_sip_resolve(&h, name, &ip, port, proto, dns_flags);
2513 dns_srv_handle_put(&h);
2515 return ip_addr2he(name, &ip);
2522 /* resolves a host name trying SRV lookup if *port==0 or normal A/AAAA lookup
2524 * when performing SRV lookup (*port==0) it will use proto to look for
2525 * tcp or udp hosts, otherwise proto is unused; if proto==0 => no SRV lookup
2526 * returns: hostent struct & *port filled with the port from the SRV record;
2529 struct hostent* dns_srv_sip_resolvehost(str* name, unsigned short* port,
2534 static char tmp[MAX_DNS_NAME]; /* tmp. buff. for SRV lookups */
2538 if ((cfg_get(core, core_cfg, use_dns_cache)==0) || (dns_hash==0)){
2539 /* not init or off => use normal, non-cached version */
2540 return _sip_resolvehost(name, port, proto);
2542 if (proto){ /* makes sure we have a protocol set*/
2544 *proto=srv_proto=PROTO_UDP; /* default */
2548 srv_proto=PROTO_UDP;
2550 /* try SRV if no port specified (draft-ietf-sip-srv-06) */
2551 if ((port)&&(*port==0)){
2552 *port=(srv_proto==PROTO_TLS)?SIPS_PORT:SIP_PORT; /* just in case we
2553 don't find another */
2554 if ((name->len+SRV_MAX_PREFIX_LEN+1)>MAX_DNS_NAME){
2555 LM_WARN("domain name too long (%d), unable to perform SRV lookup\n",
2558 /* check if it's an ip address */
2559 if ( ((ip=str2ip(name))!=0)
2560 || ((ip=str2ip6(name))!=0)
2562 /* we are lucky, this is an ip address */
2563 return ip_addr2he(name,ip);
2566 if(srv_proto==PROTO_WS || srv_proto==PROTO_WSS) {
2567 /* no srv records for web sockets */
2576 create_srv_name(srv_proto, name, tmp);
2579 LM_CRIT("unknown proto %d\n", (int)srv_proto);
2584 srv_name.len=strlen(tmp);
2585 if ((he=dns_srv_get_he(&srv_name, port, dns_flags))!=0)
2590 if (name->len >= MAX_DNS_NAME) {
2591 LM_ERR("domain name too long\n");
2594 he=dns_get_he(name, dns_flags);
2601 /* iterates over a naptr rr list, returning each time a "good" naptr record
2602 * is found.( srv type, no regex and a supported protocol)
2604 * naptr_head - naptr dns_rr list head
2605 * tried - bitmap used to keep track of the already tried records
2606 * (no more then sizeof(tried)*8 valid records are
2608 * srv_name - if succesfull, it will be set to the selected record
2609 * srv name (naptr repl.)
2610 * proto - if succesfull it will be set to the selected record
2612 * returns 0 if no more records found or a pointer to the selected record
2613 * and sets protocol and srv_name
2614 * WARNING: when calling first time make sure you run first
2615 * naptr_iterate_init(&tried)
2617 struct naptr_rdata* dns_naptr_sip_iterate(struct dns_rr* naptr_head,
2619 str* srv_name, char* proto)
2623 struct naptr_rdata* naptr;
2624 struct naptr_rdata* naptr_saved;
2629 naptr_proto=PROTO_NONE;
2633 for(l=naptr_head; l && (i<MAX_NAPTR_RRS); l=l->next){
2634 naptr=(struct naptr_rdata*) l->rdata;
2636 LM_CRIT("null rdata\n");
2639 /* check if valid and get proto */
2640 if ((naptr_proto=naptr_get_sip_proto(naptr))<=0) continue;
2641 if (*tried& (1<<i)){
2643 continue; /* already tried */
2645 LM_DBG("found a valid sip NAPTR rr %.*s, proto %d\n",
2646 naptr->repl_len, naptr->repl, (int)naptr_proto);
2647 if (naptr->skip_record) {
2651 if ((naptr_proto_supported(naptr_proto))){
2652 if (naptr_choose(&naptr_saved, &saved_proto,
2653 naptr, naptr_proto))
2659 /* found something */
2660 LM_DBG("choosed NAPTR rr %.*s, proto %d tried: 0x%x\n",
2661 naptr_saved->repl_len, naptr_saved->repl, (int)saved_proto, *tried);
2664 srv_name->s=naptr_saved->repl;
2665 srv_name->len=naptr_saved->repl_len;
2674 /* resolves a host name trying NAPTR lookup if *proto==0 and *port==0, SRV
2675 * lookup if *port==0 or normal A/AAAA lookup
2677 * when performing SRV lookup (*port==0) it will use proto to look for
2678 * tcp or udp hosts; if proto==0 => no SRV lookup
2679 * returns: hostent struct & *port filled with the port from the SRV record;
2682 struct hostent* dns_naptr_sip_resolvehost(str* name, unsigned short* port,
2686 struct ip_addr* tmp_ip;
2687 naptr_bmp_t tried_bmp;
2688 struct dns_hash_entry* e;
2696 origproto=PROTO_NONE;
2699 if (dns_hash==0){ /* not init => use normal, non-cached version */
2700 LM_WARN("called before dns cache initialization\n");
2701 return _sip_resolvehost(name, port, proto);
2703 if (proto && port && (*proto==0) && (*port==0)){
2704 *proto=PROTO_UDP; /* just in case we don't find another */
2705 /* check if it's an ip address */
2706 if ( ((tmp_ip=str2ip(name))!=0)
2707 || ((tmp_ip=str2ip6(name))!=0)
2709 /* we are lucky, this is an ip address */
2710 if (((dns_flags&DNS_IPV4_ONLY) && (tmp_ip->af==AF_INET6))||
2711 ((dns_flags&DNS_IPV6_ONLY) && (tmp_ip->af==AF_INET))){
2715 return ip_addr2he(name, tmp_ip);
2717 /* do naptr lookup */
2718 if ((e=dns_get_entry(name, T_NAPTR))==0)
2719 goto naptr_not_found;
2720 naptr_iterate_init(&tried_bmp);
2721 while(dns_naptr_sip_iterate(e->rr_lst, &tried_bmp,
2722 &srv_name, &n_proto)){
2723 if ((he=dns_srv_get_he(&srv_name, port, dns_flags))!=0){
2724 LM_DBG("(%.*s, %d, %d) srv, ret=%p\n",
2725 name->len, name->s, (int)*port, (int)*proto, he);
2731 /* no acceptable naptr record found, fallback to srv */
2735 if(proto) *proto = origproto;
2736 he = no_naptr_srv_sip_resolvehost(name,port,proto);
2737 /* fallback all the way down to A/AAAA */
2739 he=dns_get_he(name,dns_flags);
2743 #endif /* USE_NAPTR */
2747 /* resolves a host name trying NAPTR lookup if *proto==0 and *port==0, SRV
2748 * lookup if *port==0 or normal A/AAAA lookup
2750 * when performing SRV lookup (*port==0) it will use proto to look for
2751 * tcp or udp hosts; if proto==0 => no SRV lookup
2752 * returns: hostent struct & *port filled with the port from the SRV record;
2755 struct hostent* dns_sip_resolvehost(str* name, unsigned short* port,
2759 if (dns_flags&DNS_TRY_NAPTR)
2760 return dns_naptr_sip_resolvehost(name, port, proto);
2762 return dns_srv_sip_resolvehost(name, port, proto);
2767 /* performs an a lookup, fills the dns_entry pointer and the ip addr.
2768 * (with the first good ip). if *e ==0 does the a lookup, and changes it
2769 * to the result, if not it uses the current value and tries to use
2770 * the rr_no record from it.
2771 * params: e - must contain the "in-use" dns_hash_entry pointer (from
2772 * a previous call) or *e==0 (for the first call)
2773 * name - host name for which we do the lookup (required only
2775 * ip - will be filled with the first good resolved ip started
2777 * rr_no - record number to start searching for a good ip from
2778 * (e.g. value from previous call + 1), filled on return
2779 * with the number of the record corresponding to the
2781 * returns 0 on success, <0 on error (see the error codes),
2782 * fills e, ip and rr_no
2783 * On end of records (when used to iterate on all the ips) it
2784 * will return E_DNS_EOR (you should not log an error for this
2785 * value, is just a signal that the address list end has been reached)
2786 * Note: either e or name must be different from 0 (name.s !=0 also)
2787 * WARNING: dns_hash_put(*e) must be called when you don't need
2788 * the entry anymore and *e!=0 (failling to do so => mem. leak)
2791 * ret=dns_a_get_ip(&dns_entry, name, &ip, &rr_no); -- get the first rr.
2794 * while((ret>=0) && dns_entry)
2795 * dns_a_get_ip(&dns_entry, name, &ip, &rr_no); -- get the next rr
2796 * if (ret!=-E_DNS_EOR) ERROR(....);
2798 * dns_hash_put(dns_entry); -- finished with the entry
2800 inline static int dns_a_resolve( struct dns_hash_entry** e,
2801 unsigned char* rr_no,
2808 struct ip_addr* tmp;
2812 if (*e==0){ /* do lookup */
2813 /* if ip don't set *e */
2814 if (str2ip6(name)!=0)
2816 if ((tmp=str2ip(name))!=0){
2821 if ((*e=dns_get_entry(name, T_A))==0)
2826 now=get_ticks_raw();
2827 /* if the entry has already expired use the time at the end of lifetime */
2828 if (unlikely((s_ticks_t)(now-(*e)->expire)>=0)) now=(*e)->expire-1;
2829 rr=dns_entry_get_rr(*e, rr_no, now);
2831 /* everything is ok now, we can try to "convert" the ip */
2832 dns_rr2ip((*e)->type, rr, ip);
2838 LM_DBG("(%.*s, %d) returning %d\n", name->len, name->s, *rr_no, ret);
2843 /* lookup, fills the dns_entry pointer and the ip addr.
2844 * (with the first good ip). if *e ==0 does the a lookup, and changes it
2845 * to the result, if not it uses the current value and tries to use
2846 * Same as dns_a_resolve but for aaaa records (see above).
2848 inline static int dns_aaaa_resolve( struct dns_hash_entry** e,
2849 unsigned char* rr_no,
2856 struct ip_addr* tmp;
2860 if (*e==0){ /* do lookup */
2861 /* if ip don't set *e */
2862 if (str2ip(name)!=0)
2864 if ((tmp=str2ip6(name))!=0){
2869 if ((*e=dns_get_entry(name, T_AAAA))==0)
2874 now=get_ticks_raw();
2875 /* if the entry has already expired use the time at the end of lifetime */
2876 if (unlikely((s_ticks_t)(now-(*e)->expire)>=0)) now=(*e)->expire-1;
2877 rr=dns_entry_get_rr(*e, rr_no, now);
2879 /* everything is ok now, we can try to "convert" the ip */
2880 dns_rr2ip((*e)->type, rr, ip);
2883 ret=-E_DNS_EOR; /* no more records */
2891 /* performs an a or aaaa dns lookup, returns <0 on error (see the
2892 * dns error codes) and 0 on success
2893 * flags: - none set: tries first an a_lookup and if it fails an aaaa_lookup
2894 * - DNS_IPV6_FIRST: tries first an aaaa_lookup and then an a_lookup
2895 * - DNS_IPV4_ONLY: tries only an a_lookup
2896 * - DNS_IPV6_ONLY: tries only an aaaa_lookup
2897 * see dns_a_resolve() for the rest of the params., examples a.s.o
2898 * WARNING: don't forget dns_hash_put(*e) when e is not needed anymore
2900 inline static int dns_ip_resolve( struct dns_hash_entry** e,
2901 unsigned char* rr_no,
2908 struct dns_hash_entry* orig;
2911 if (*e==0){ /* first call */
2912 if ((flags&(DNS_IPV6_FIRST|DNS_IPV6_ONLY))){
2913 ret=dns_aaaa_resolve(e, rr_no, name, ip);
2914 if (ret>=0) return ret;
2916 ret=dns_a_resolve(e, rr_no, name, ip);
2917 if (ret>=0) return ret;
2919 if (flags&DNS_IPV6_FIRST){
2920 ret=dns_a_resolve(e, rr_no, name, ip);
2921 }else if (!(flags&(DNS_IPV6_ONLY|DNS_IPV4_ONLY))){
2922 ret=dns_aaaa_resolve(e, rr_no, name, ip);
2924 }else if ((*e)->type==T_A){
2925 /* continue A resolving */
2926 /* retrieve host name from the hash entry (ignore name which might
2927 be null when continuing a srv lookup) */
2929 host.len=(*e)->name_len;
2930 ret=dns_a_resolve(e, rr_no, &host, ip);
2931 if (ret>=0) return ret;
2932 if (!(flags&(DNS_IPV6_ONLY|DNS_IPV6_FIRST|DNS_IPV4_ONLY))){
2933 /* not found, try with AAAA */
2938 ret=dns_aaaa_resolve(e, rr_no, &host, ip);
2939 if (ret==-E_DNS_NO_IP && orig_ret==-E_DNS_EOR)
2941 /* delay original record release until we're finished with host*/
2944 }else if ((*e)->type==T_AAAA){
2945 /* retrieve host name from the hash entry (ignore name which might
2946 be null when continuing a srv lookup) */
2948 host.len=(*e)->name_len;
2949 /* continue AAAA resolving */
2950 ret=dns_aaaa_resolve(e, rr_no, &host, ip);
2951 if (ret>=0) return ret;
2952 if ((flags&DNS_IPV6_FIRST) && !(flags&DNS_IPV6_ONLY)){
2953 /* not found, try with A */
2958 ret=dns_a_resolve(e, rr_no, &host, ip);
2959 if (ret==-E_DNS_NO_IP && orig_ret==-E_DNS_EOR)
2961 /* delay original record release until we're finished with host*/
2965 LM_CRIT("invalid record type %d\n", (*e)->type);
2972 /* gets the first srv record starting at rr_no
2973 * Next call will return the next record a.s.o.
2974 * (similar to dns_a_resolve but for srv, sets host, port and automatically
2975 * switches to the next record in the future)
2977 * if DNS_SRV_LB and tried!=NULL will do random weight based selection
2978 * for choosing between SRV RRs with the same priority (as described in
2980 * If tried==NULL or DNS_SRV_LB is not defined => always returns next
2981 * record in the priority order and for records with the same priority
2982 * the record with the higher weight (from the remaining ones)
2984 inline static int dns_srv_resolve_nxt(struct dns_hash_entry** e,
2988 unsigned char* rr_no,
2989 str* name, str* host, unsigned short* port)
2998 if ((*e=dns_get_entry(name, T_SRV))==0)
3004 srv_reset_tried(tried);
3007 now=get_ticks_raw();
3008 /* if the entry has already expired use the time at the end of lifetime */
3009 if (unlikely((s_ticks_t)(now-(*e)->expire)>=0)) now=(*e)->expire-1;
3012 rr=dns_srv_get_nxt_rr(*e, tried, rr_no, now);
3016 rr=dns_entry_get_rr(*e, rr_no, now);
3017 (*rr_no)++; /* try next record next time */
3020 host->s=((struct srv_rdata*)rr->rdata)->name;
3021 host->len=((struct srv_rdata*)rr->rdata)->name_len;
3022 *port=((struct srv_rdata*)rr->rdata)->port;
3025 ret=-E_DNS_EOR; /* no more records */
3033 /* gets the first srv record starting at h->srv_no, resolve it
3034 * and get the first ip address (starting at h->ip_no)
3035 * (similar to dns_a_resolve but for srv, sets host, port)
3036 * WARNING: don't forget to init h prior to calling this function the first
3037 * time and dns_srv_handle_put(h), even if error is returned
3039 inline static int dns_srv_resolve_ip(struct dns_srv_handle* h,
3040 str* name, struct ip_addr* ip, unsigned short* port,
3051 if ((ret=dns_srv_resolve_nxt(&h->srv,
3052 (flags & DNS_SRV_RR_LB)?&h->srv_tried_rrs:0,
3054 name, &host, port))<0)
3057 if ((ret=dns_srv_resolve_nxt(&h->srv, &h->srv_no,
3058 name, &host, port))<0)
3061 h->port=*port; /* store new port */
3063 *port=h->port; /* return the stored port */
3065 if ((ret=dns_ip_resolve(&h->a, &h->ip_no, &host, ip, flags))<0){
3066 /* couldn't find any good ip for this record, try the next one */
3072 /* this was an ip, try the next srv record in the future */
3076 LM_DBG("(\"%.*s\", %d, %d), ret=%d, ip=%s\n",
3077 name->len, name->s, h->srv_no, h->ip_no, ret,
3078 ip?ZSW(ip_addr2a(ip)):"");
3084 /* resolves a host name trying SRV lookup if *port==0 or normal A/AAAA lookup
3086 * when performing SRV lookup (*port==0) it will use proto to look for
3087 * tcp or udp hosts, otherwise proto is unused; if proto==0 => no SRV lookup
3088 * h must be initialized prior to calling this function and can be used to
3089 * get the subsequent ips
3090 * returns: <0 on error
3091 * 0 on success and it fills *ip, *port, *h
3093 inline static int dns_srv_sip_resolve(struct dns_srv_handle* h, str* name,
3094 struct ip_addr* ip, unsigned short* port, char* proto,
3097 struct dns_srv_proto srv_proto_list[PROTO_LAST];
3098 static char tmp[MAX_DNS_NAME]; /* tmp. buff. for SRV lookups */
3100 struct ip_addr* tmp_ip;
3106 if(proto) origproto = *proto;
3107 if (dns_hash==0){ /* not init => use normal, non-cached version */
3108 LM_WARN("called before dns cache initialization\n");
3110 he=_sip_resolvehost(name, port, proto);
3112 hostent2ip_addr(ip, he, 0);
3115 return -E_DNS_NO_SRV;
3117 if ((h->srv==0) && (h->a==0)){ /* first call */
3119 if(*proto==0) { /* makes sure we have a protocol set*/
3120 *proto=PROTO_UDP; /* default */
3122 h->port=(*proto==PROTO_TLS)?SIPS_PORT:SIP_PORT; /* just in case we
3123 don't find another */
3124 h->proto=*proto; /* store initial protocol */
3126 h->proto=PROTO_UDP; /* default */
3130 /* try SRV if initial call & no port specified
3131 * (draft-ietf-sip-srv-06) */
3132 if ((name->len+SRV_MAX_PREFIX_LEN+1)>MAX_DNS_NAME){
3133 LM_WARN("domain name too long (%d), unable to perform SRV lookup\n",
3136 /* check if it's an ip address */
3137 if ( ((tmp_ip=str2ip(name))!=0)
3138 || ((tmp_ip=str2ip6(name))!=0)
3140 /* we are lucky, this is an ip address */
3141 if (((flags&DNS_IPV4_ONLY) && (tmp_ip->af==AF_INET6))||
3142 ((flags&DNS_IPV6_ONLY) && (tmp_ip->af==AF_INET))){
3143 return -E_DNS_AF_MISMATCH;
3147 /* proto already set */
3151 /* looping on the ordered list until we found a protocol what has srv record */
3152 list_len = create_srv_pref_list(&origproto, srv_proto_list);
3153 for (i=0; i<list_len;i++) {
3154 switch (srv_proto_list[i].proto) {
3159 create_srv_name(srv_proto_list[i].proto, name, tmp);
3162 LM_CRIT("unknown proto %d\n", (int)srv_proto_list[i].proto);
3163 return -E_DNS_CRITICAL;
3166 srv_name.len=strlen(tmp);
3167 if ((ret=dns_srv_resolve_ip(h, &srv_name, ip, port, flags))>=0)
3169 h->proto = srv_proto_list[i].proto;
3170 if(proto) *proto = h->proto;
3171 LM_DBG("(%.*s, %d, %d), srv0, ret=%d\n",
3172 name->len, name->s, h->srv_no, h->ip_no, ret);
3177 }else{ /* if (*port==0) */
3178 h->port=*port; /* store initial port */
3179 /* proto already set */
3183 srv_name.s=h->srv->name;
3184 srv_name.len=h->srv->name_len;
3185 /* continue srv resolving */
3186 ret=dns_srv_resolve_ip(h, &srv_name, ip, port, flags);
3189 LM_DBG("(%.*s, %d, %d), srv, ret=%d\n",
3190 name->len, name->s, h->srv_no, h->ip_no, ret);
3193 if (name->len >= MAX_DNS_NAME) {
3194 LM_ERR("domain name too long\n");
3195 return -E_DNS_NAME_TOO_LONG;
3197 ret=dns_ip_resolve(&h->a, &h->ip_no, name, ip, flags);
3202 LM_DBG("(%.*s, %d, %d), ip, ret=%d\n",
3203 name->len, name->s, h->srv_no, h->ip_no, ret);
3212 static void mark_skip_current_naptr(struct dns_rr* naptr_head, struct dns_hash_entry* srv)
3216 struct naptr_rdata* naptr;
3218 if (!naptr_head || !srv) {
3222 for(l=naptr_head, i=0; l && (i<MAX_NAPTR_RRS); l=l->next, i++) {
3223 naptr = (struct naptr_rdata *) l->rdata;