4 * resolver related functions
6 * Copyright (C) 2006 iptelorg GmbH
8 * This file is part of ser, a free SIP server.
10 * ser is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version
15 * For a license to use the ser software under conditions
16 * other than those described here, or to purchase support for this
17 * software, please contact iptel.org by e-mail at the following addresses:
20 * ser is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31 * 2006-07-13 created by andrei
32 * 2006-10-06 port fix (andrei)
33 * 2007-06-14 dns iterate through A & AAAA records fix (andrei)
34 * 2007-06-15 srv rr weight based load balancing support (andrei)
35 * 2007-06-16 naptr support (andrei)
36 * 2008-07-18 DNS watchdog support -- can be used to inform the core
37 * that the DNS servers are down (Miklos)
38 * 2008-07-25 various rpc commands to manipulate the content
39 * of the cache (Miklos)
40 * 2007-07-30 DNS cache measurements added (Gergo)
41 * 2007-08-17 dns_cache_del_nonexp config option is introduced (Miklos)
42 * 2008-02-04 DNS cache options are adapted for the configuration
44 * 2008-02-11 dns_cache_init cfg parameter is introduced (Miklos)
45 * 2008-10-17 fixed srv continue with 0 hostname (when falling back to
47 * 2009-03-30 TXT record support, more rpcs (andrei)
48 * 2009-03-30 EBL record support (andrei)
49 * 2009-04-01 PTR record support (andrei)
53 * \brief SIP-router core ::
62 #include <stdlib.h> /* FIXME: rand() */
68 #include "dns_cache.h"
69 #include "dns_wrappers.h"
70 #include "compiler_opt.h"
71 #include "mem/shm_mem.h"
75 #include "atomic_ops.h"
78 #include "timer_ticks.h"
81 #include "rand/fastrand.h"
82 #ifdef USE_DNS_CACHE_STATS
88 #define DNS_CACHE_DEBUG /* extra sanity checks and debugging */
92 #define MAX(a,b) ( ((a)>(b))?(a):(b))
95 #define MAX_DNS_RECORDS 255 /* maximum dns records number received in a
98 #define DNS_HASH_SIZE 1024 /* must be <= 65535 */
99 #define DEFAULT_DNS_TIMER_INTERVAL 120 /* 2 min. */
100 #define DNS_HE_MAX_ADDR 10 /* maxium addresses returne in a hostent struct */
101 #define MAX_CNAME_CHAIN 10
102 #define SPACE_FORMAT " " /* format of view output */
104 int dns_cache_init=1; /* if 0, the DNS cache is not initialized at startup */
105 static gen_lock_t* dns_hash_lock=0;
106 static volatile unsigned int *dns_cache_mem_used=0; /* current mem. use */
107 unsigned int dns_timer_interval=DEFAULT_DNS_TIMER_INTERVAL; /* in s */
108 int dns_flags=0; /* default flags used for the dns_*resolvehost
109 (compatibility wrappers) */
111 #ifdef USE_DNS_CACHE_STATS
112 struct t_dns_cache_stats* dns_cache_stats=0;
115 #define LOCK_DNS_HASH() lock_get(dns_hash_lock)
116 #define UNLOCK_DNS_HASH() lock_release(dns_hash_lock)
119 (((t)<cfg_get(core, core_cfg, dns_cache_min_ttl))? \
120 cfg_get(core, core_cfg, dns_cache_min_ttl): \
121 (((t)>cfg_get(core, core_cfg, dns_cache_max_ttl))? \
122 cfg_get(core, core_cfg, dns_cache_max_ttl): \
126 struct dns_hash_head{
127 struct dns_hash_entry* next;
128 struct dns_hash_entry* prev;
132 struct dns_lu_lst* dns_last_used_lst=0;
135 static struct dns_hash_head* dns_hash=0;
138 static struct timer_ln* dns_timer_h=0;
140 #ifdef DNS_WATCHDOG_SUPPORT
141 static atomic_t *dns_servers_up = NULL;
146 static const char* dns_str_errors[]={
148 "no more records", /* not an error, but and end condition */
152 "unresolvable SRV request",
153 "bad A or AAAA entry",
154 "unresolvable A or AAAA request",
155 "invalid ip in A or AAAA record",
157 "name too long ", /* try again with a shorter name */
158 "ip AF mismatch", /* address family mismatch */
159 "unresolvable NAPTR request",
160 "bug - critical error"
165 /* param: err (negative error number) */
166 const char* dns_strerror(int err)
169 if ((err>=0) && (err<sizeof(dns_str_errors)/sizeof(char*)))
170 return dns_str_errors[err];
171 return "bug -- bad error number";
176 /* "internal" only, don't use unless you really know waht you're doing */
177 inline static void dns_destroy_entry(struct dns_hash_entry* e)
179 #ifdef DNS_CACHE_DEBUG
180 memset(e, 0, e->total_size);
182 shm_free(e); /* nice having it in one block isn't it? :-) */
186 /* "internal" only, same as above, asumes shm_lock() held (tm optimization) */
187 inline static void dns_destroy_entry_shm_unsafe(struct dns_hash_entry* e)
189 #ifdef DNS_CACHE_DEBUG
190 memset(e, 0, e->total_size);
192 shm_free_unsafe(e); /* nice having it in one block isn't it? :-) */
197 /* dec. the internal refcnt and if 0 deletes the entry */
198 void dns_hash_put(struct dns_hash_entry* e)
200 if(e && atomic_dec_and_test(&e->refcnt)){
201 /* atomic_sub_long(dns_cache_total_used, e->total_size); */
202 dns_destroy_entry(e);
208 /* same as above but uses dns_destroy_unsafe (assumes shm_lock held -- tm
210 void dns_hash_put_shm_unsafe(struct dns_hash_entry* e)
212 if(e && atomic_dec_and_test(&e->refcnt)){
213 /* atomic_sub_long(dns_cache_total_used, e->total_size); */
214 dns_destroy_entry_shm_unsafe(e);
219 inline static int dns_cache_clean(unsigned int no, int expired_only);
220 inline static int dns_cache_free_mem(unsigned int target, int expired_only);
222 static ticks_t dns_timer(ticks_t ticks, struct timer_ln* tl, void* data)
224 #ifdef DNS_WATCHDOG_SUPPORT
225 /* do not clean the hash table if the servers are down */
226 if (atomic_get(dns_servers_up) == 0)
227 return (ticks_t)(-1);
229 if (*dns_cache_mem_used>12*(cfg_get(core, core_cfg, dns_cache_max_mem)/16)){ /* ~ 75% used */
230 dns_cache_free_mem(cfg_get(core, core_cfg, dns_cache_max_mem)/2, 1);
232 dns_cache_clean(-1, 1); /* all the table, only expired entries */
233 /* TODO: better strategy? */
235 return (ticks_t)(-1);
240 void destroy_dns_cache()
243 timer_del(dns_timer_h);
244 timer_free(dns_timer_h);
247 #ifdef DNS_WATCHDOG_SUPPORT
249 shm_free(dns_servers_up);
254 lock_destroy(dns_hash_lock);
255 lock_dealloc(dns_hash_lock);
263 if (dns_last_used_lst){
264 shm_free(dns_last_used_lst);
268 #ifdef USE_DNS_CACHE_STATS
270 shm_free(dns_cache_stats);
272 if (dns_cache_mem_used){
273 shm_free((void*)dns_cache_mem_used);
274 dns_cache_mem_used=0;
278 /* set the value of dns_flags */
279 void fix_dns_flags(str *gname, str *name)
281 /* restore the original value of dns_cache_flags first
282 * (DNS_IPV4_ONLY may have been set only because dns_try_ipv6
283 * was disabled, and the flag must be cleared when
284 * dns_try_ipv6 is enabled) (Miklos)
286 dns_flags = cfg_get(core, core_cfg, dns_cache_flags) & 7;
288 if (cfg_get(core, core_cfg, dns_try_ipv6)==0){
289 dns_flags|=DNS_IPV4_ONLY;
291 if (dns_flags & DNS_IPV4_ONLY){
292 dns_flags&=~(DNS_IPV6_ONLY|DNS_IPV6_FIRST);
294 if (cfg_get(core, core_cfg, dns_srv_lb)){
296 dns_flags|=DNS_SRV_RR_LB;
298 LOG(L_WARN, "WARNING: fix_dns_flags: SRV loadbalaning is set, but"
299 " support for it is not compiled -- ignoring\n");
302 if (cfg_get(core, core_cfg, dns_try_naptr)) {
304 LOG(L_WARN, "WARNING: fix_dns_flags: NAPTR support is enabled, but"
305 " support for it is not compiled -- ignoring\n");
307 dns_flags|=DNS_TRY_NAPTR;
311 /* fixup function for use_dns_failover
312 * verifies that use_dns_cache is set to 1
314 int use_dns_failover_fixup(void *handle, str *gname, str *name, void **val)
316 if ((int)(long)(*val) && !cfg_get(core, handle, use_dns_cache)) {
317 LOG(L_ERR, "ERROR: use_dns_failover_fixup(): "
318 "DNS cache is turned off, failover cannot be enabled. "
319 "(set use_dns_cache to 1)\n");
325 /* fixup function for use_dns_cache
326 * verifies that dns_cache_init is set to 1
328 int use_dns_cache_fixup(void *handle, str *gname, str *name, void **val)
330 if ((int)(long)(*val) && !dns_cache_init) {
331 LOG(L_ERR, "ERROR: use_dns_cache_fixup(): "
332 "DNS cache is turned off by dns_cache_init=0, "
333 "it cannot be enabled runtime.\n");
336 if (((int)(long)(*val)==0) && cfg_get(core, handle, use_dns_failover)) {
337 LOG(L_ERR, "ERROR: use_dns_failover_fixup(): "
338 "DNS failover depends on use_dns_cache, set use_dns_failover "
339 "to 0 before disabling the DNS cache\n");
345 /* KByte to Byte conversion */
346 int dns_cache_max_mem_fixup(void *handle, str *gname, str *name, void **val)
350 u = ((unsigned int)(long)(*val))<<10;
351 (*val) = (void *)(long)u;
360 if (dns_cache_init==0) {
361 /* the DNS cache is turned off */
362 default_core_cfg.use_dns_cache=0;
363 default_core_cfg.use_dns_failover=0;
369 if (E_DNS_CRITICAL>=sizeof(dns_str_errors)/sizeof(char*)){
370 LOG(L_CRIT, "BUG: dns_cache_init: bad dns error table\n");
374 dns_cache_mem_used=shm_malloc(sizeof(*dns_cache_mem_used));
375 if (dns_cache_mem_used==0){
380 dns_last_used_lst=shm_malloc(sizeof(*dns_last_used_lst));
381 if (dns_last_used_lst==0){
385 clist_init(dns_last_used_lst, next, prev);
387 dns_hash=shm_malloc(sizeof(struct dns_hash_head)*DNS_HASH_SIZE);
392 for (r=0; r<DNS_HASH_SIZE; r++)
393 clist_init(&dns_hash[r], next, prev);
395 dns_hash_lock=lock_alloc();
396 if (dns_hash_lock==0){
400 if (lock_init(dns_hash_lock)==0){
401 lock_dealloc(dns_hash_lock);
407 #ifdef DNS_WATCHDOG_SUPPORT
408 dns_servers_up=shm_malloc(sizeof(atomic_t));
409 if (dns_servers_up==0){
413 atomic_set(dns_servers_up, 1);
417 default_core_cfg.dns_cache_max_mem<<=10; /* Kb */ /* TODO: test with 0 */
418 if (default_core_cfg.use_dns_cache==0)
419 default_core_cfg.use_dns_failover=0; /* cannot work w/o dns_cache support */
421 fix_dns_flags(NULL, NULL);
423 dns_timer_h=timer_alloc();
428 if (dns_timer_interval){
429 timer_init(dns_timer_h, dns_timer, 0, 0); /* "slow" timer */
430 if (timer_add(dns_timer_h, S_TO_TICKS(dns_timer_interval))<0){
431 LOG(L_CRIT, "BUG: dns_cache_init: failed to add the timer\n");
432 timer_free(dns_timer_h);
444 #ifdef USE_DNS_CACHE_STATS
445 int init_dns_cache_stats(int iproc_num)
447 /* do not initialize the stats array if the DNS cache will not be used */
448 if (dns_cache_init==0) return 0;
450 /* if it is already initialized */
452 shm_free(dns_cache_stats);
454 dns_cache_stats=shm_malloc(sizeof(*dns_cache_stats) * iproc_num);
455 if (dns_cache_stats==0){
458 memset(dns_cache_stats, 0, sizeof(*dns_cache_stats) * iproc_num);
464 /* hash function, type is not used (obsolete)
465 * params: char* s, int len, int type
466 * returns the hash value
468 #define dns_hash_no(s, len, type) \
469 (get_hash1_case_raw((s),(len)) % DNS_HASH_SIZE)
473 #ifdef DNS_CACHE_DEBUG
477 #include <stdlib.h> /* abort() */
478 #define check_lu_lst(l) ((((l)->next==(l)) || ((l)->prev==(l))) && \
479 ((l)!=dns_last_used_lst))
481 #define dbg_lu_lst(txt, l) \
482 LOG(L_CRIT, "BUG: %s: crt(%p, %p, %p)," \
483 " prev(%p, %p, %p), next(%p, %p, %p)\n", txt, \
484 (l), (l)->next, (l)->prev, \
485 (l)->prev, (l)->prev->next, (l)->prev->prev, \
486 (l)->next, (l)->next->next, (l)->next->prev \
489 #define debug_lu_lst( txt, l) \
491 if (check_lu_lst((l))){ \
492 dbg_lu_lst(txt " crt:", (l)); \
495 if (check_lu_lst((l)->next)){ \
496 dbg_lu_lst(txt " next:", (l)); \
499 if (check_lu_lst((l)->prev)){ \
500 dbg_lu_lst(txt " prev:", (l)); \
506 #endif /* DNS_CACHE_DEBUG */
509 /* must be called with the DNS_LOCK hold
510 * remove and entry from the hash, dec. its refcnt and if not referenced
511 * anymore deletes it */
512 inline static void _dns_hash_remove(struct dns_hash_entry* e)
514 clist_rm(e, next, prev);
515 #ifdef DNS_CACHE_DEBUG
520 debug_lu_lst("_dns_hash_remove: pre rm:", &e->last_used_lst);
522 clist_rm(&e->last_used_lst, next, prev);
524 debug_lu_lst("_dns_hash_remove: post rm:", &e->last_used_lst);
526 #ifdef DNS_CACHE_DEBUG
527 e->last_used_lst.next=e->last_used_lst.prev=0;
530 *dns_cache_mem_used-=e->total_size;
536 /* non locking version (the dns hash must _be_ locked externally)
537 * returns 0 when not found, or the entry on success (an entry with a
538 * similar name but with a CNAME type will always match).
539 * it doesn't increase the internal refcnt
540 * returns the entry when found, 0 when not found and sets *err to !=0
541 * on error (e.g. recursive cnames)
542 * WARNING: - internal use only
543 * - always check if the returned entry type is CNAME */
544 inline static struct dns_hash_entry* _dns_hash_find(str* name, int type,
547 struct dns_hash_entry* e;
548 struct dns_hash_entry* tmp;
549 struct dns_hash_entry* ret;
553 #ifdef DNS_WATCHDOG_SUPPORT
556 servers_up = atomic_get(dns_servers_up);
564 *h=dns_hash_no(name->s, name->len, type);
565 #ifdef DNS_CACHE_DEBUG
566 DBG("dns_hash_find(%.*s(%d), %d), h=%d\n", name->len, name->s,
567 name->len, type, *h);
569 clist_foreach_safe(&dns_hash[*h], e, tmp, next){
571 #ifdef DNS_WATCHDOG_SUPPORT
572 /* remove expired elements only when the dns servers are up */
575 /* automatically remove expired elements */
576 ((e->ent_flags & DNS_FLAG_PERMANENT) == 0) &&
577 ((s_ticks_t)(now-e->expire)>=0)
580 }else if ((e->type==type) && (e->name_len==name->len) &&
581 (strncasecmp(e->name, name->s, e->name_len)==0)){
584 /* add it at the end */
586 debug_lu_lst("_dns_hash_find: pre rm:", &e->last_used_lst);
588 clist_rm(&e->last_used_lst, next, prev);
589 clist_append(dns_last_used_lst, &e->last_used_lst, next, prev);
591 debug_lu_lst("_dns_hash_find: post append:", &e->last_used_lst);
595 }else if ((e->type==T_CNAME) &&
596 !((e->rr_lst==0) || (e->ent_flags & DNS_FLAG_BAD_NAME)) &&
597 (e->name_len==name->len) &&
598 (strncasecmp(e->name, name->s, e->name_len)==0)){
599 /*if CNAME matches and CNAME is entry is not a neg. cache entry
600 (could be produced by a specific CNAME lookup)*/
603 /* add it at the end */
605 debug_lu_lst("_dns_hash_find: cname: pre rm:", &e->last_used_lst);
607 clist_rm(&e->last_used_lst, next, prev);
608 clist_append(dns_last_used_lst, &e->last_used_lst, next, prev);
610 debug_lu_lst("_dns_hash_find: cname: post append:",
614 ret=e; /* if this is an unfinished cname chain, we try to
615 return the last cname */
616 /* this is a cname => retry using its value */
617 if (cname_chain> MAX_CNAME_CHAIN){
618 LOG(L_ERR, "ERROR: _dns_hash_find: cname chain too long "
619 "or recursive (\"%.*s\")\n", name->len, name->s);
625 cname.s=((struct cname_rdata*)e->rr_lst->rdata)->name;
626 cname.len= ((struct cname_rdata*)e->rr_lst->rdata)->name_len;
636 /* frees cache entries, if expired_only=0 only expired entries will be
637 * removed, else all of them
638 * it will process maximum no entries (to process all of them use -1)
639 * returns the number of deleted entries
640 * This should be called from a timer process*/
641 inline static int dns_cache_clean(unsigned int no, int expired_only)
643 struct dns_hash_entry* e;
646 unsigned int deleted;
648 struct dns_lu_lst* l;
649 struct dns_lu_lst* tmp;
651 struct dns_hash_entry* t;
653 static unsigned int start=0;
661 clist_foreach_safe(dns_last_used_lst, l, tmp, next){
662 e=(struct dns_hash_entry*)(((char*)l)-
663 (char*)&((struct dns_hash_entry*)(0))->last_used_lst);
664 if (((e->ent_flags & DNS_FLAG_PERMANENT) == 0)
665 && (!expired_only || ((s_ticks_t)(now-e->expire)>=0))
674 for(h=start; h!=(start+DNS_HASH_SIZE); h++){
675 clist_foreach_safe(&dns_hash[h%DNS_HASH_SIZE], e, t, next){
676 if (((e->ent_flags & DNS_FLAG_PERMANENT) == 0)
677 && ((s_ticks_t)(now-e->expire)>=0)
683 if (n>=no) goto skip;
686 /* not fair, but faster then random() */
688 for(h=start; h!=(start+DNS_HASH_SIZE); h++){
689 clist_foreach_safe(&dns_hash[h%DNS_HASH_SIZE], e, t, next){
690 if ((e->ent_flags & DNS_FLAG_PERMANENT) == 0) {
695 if (n>=no) goto skip;
708 /* frees cache entries, if expired_only=0 only expired entries will be
709 * removed, else all of them
710 * it will stop when the dns cache used memory reaches target (to process all
712 * returns the number of deleted entries */
713 inline static int dns_cache_free_mem(unsigned int target, int expired_only)
715 struct dns_hash_entry* e;
717 unsigned int deleted;
719 struct dns_lu_lst* l;
720 struct dns_lu_lst* tmp;
722 struct dns_hash_entry* t;
724 static unsigned int start=0;
731 clist_foreach_safe(dns_last_used_lst, l, tmp, next){
732 if (*dns_cache_mem_used<=target) break;
733 e=(struct dns_hash_entry*)(((char*)l)-
734 (char*)&((struct dns_hash_entry*)(0))->last_used_lst);
735 if (((e->ent_flags & DNS_FLAG_PERMANENT) == 0)
736 && (!expired_only || ((s_ticks_t)(now-e->expire)>=0))
743 for(h=start; h!=(start+DNS_HASH_SIZE); h++){
744 clist_foreach_safe(&dns_hash[h%DNS_HASH_SIZE], e, t, next){
745 if (*dns_cache_mem_used<=target)
747 if (((e->ent_flags & DNS_FLAG_PERMANENT) == 0)
748 && ((s_ticks_t)(now-e->expire)>=0)
755 /* not fair, but faster then random() */
757 for(h=start; h!=(start+DNS_HASH_SIZE); h++){
758 clist_foreach_safe(&dns_hash[h%DNS_HASH_SIZE], e, t, next){
759 if (*dns_cache_mem_used<=target)
761 if (((e->ent_flags & DNS_FLAG_PERMANENT) == 0)
762 && ((s_ticks_t)(now-e->expire)>=0)
779 /* locking version (the dns hash must _not_be locked externally)
780 * returns 0 when not found, the searched entry on success (with CNAMEs
781 * followed) or the last CNAME entry from an unfinished CNAME chain,
782 * if the search matches a CNAME. On error sets *err (e.g. recursive CNAMEs).
783 * it increases the internal refcnt => when finished dns_hash_put() must
784 * be called on the returned entry
785 * WARNING: - the return might be a CNAME even if type!=CNAME, see above */
786 inline static struct dns_hash_entry* dns_hash_get(str* name, int type, int* h,
789 struct dns_hash_entry* e;
792 e=_dns_hash_find(name, type, h, err);
794 atomic_inc(&e->refcnt);
802 /* adds a fully created and init. entry (see dns_cache_mk_entry()) to the hash
804 * returns 0 on success, -1 on error */
805 inline static int dns_cache_add(struct dns_hash_entry* e)
810 /* atomic_add_long(dns_cache_total_used, e->size); */
811 if ((*dns_cache_mem_used+e->total_size)>=cfg_get(core, core_cfg, dns_cache_max_mem)){
812 #ifdef USE_DNS_CACHE_STATS
813 dns_cache_stats[process_no].dc_lru_cnt++;
815 LOG(L_WARN, "WARNING: dns_cache_add: cache full, trying to free...\n");
816 /* free ~ 12% of the cache */
817 dns_cache_free_mem(*dns_cache_mem_used/16*14,
818 !cfg_get(core, core_cfg, dns_cache_del_nonexp));
819 if ((*dns_cache_mem_used+e->total_size)>=cfg_get(core, core_cfg, dns_cache_max_mem)){
820 LOG(L_ERR, "ERROR: dns_cache_add: max. cache mem size exceeded\n");
824 atomic_inc(&e->refcnt);
825 h=dns_hash_no(e->name, e->name_len, e->type);
826 #ifdef DNS_CACHE_DEBUG
827 DBG("dns_cache_add: adding %.*s(%d) %d (flags=%0x) at %d\n",
828 e->name_len, e->name, e->name_len, e->type, e->ent_flags, h);
831 *dns_cache_mem_used+=e->total_size; /* no need for atomic ops, written
832 only from within a lock */
833 clist_append(&dns_hash[h], e, next, prev);
835 clist_append(dns_last_used_lst, &e->last_used_lst, next, prev);
843 /* same as above, but it must be called with the dns hash lock held
844 * returns 0 on success, -1 on error */
845 inline static int dns_cache_add_unsafe(struct dns_hash_entry* e)
850 /* atomic_add_long(dns_cache_total_used, e->size); */
851 if ((*dns_cache_mem_used+e->total_size)>=cfg_get(core, core_cfg, dns_cache_max_mem)){
852 #ifdef USE_DNS_CACHE_STATS
853 dns_cache_stats[process_no].dc_lru_cnt++;
855 LOG(L_WARN, "WARNING: dns_cache_add: cache full, trying to free...\n");
856 /* free ~ 12% of the cache */
858 dns_cache_free_mem(*dns_cache_mem_used/16*14,
859 !cfg_get(core, core_cfg, dns_cache_del_nonexp));
861 if ((*dns_cache_mem_used+e->total_size)>=cfg_get(core, core_cfg, dns_cache_max_mem)){
862 LOG(L_ERR, "ERROR: dns_cache_add: max. cache mem size exceeded\n");
866 atomic_inc(&e->refcnt);
867 h=dns_hash_no(e->name, e->name_len, e->type);
868 #ifdef DNS_CACHE_DEBUG
869 DBG("dns_cache_add: adding %.*s(%d) %d (flags=%0x) at %d\n",
870 e->name_len, e->name, e->name_len, e->type, e->ent_flags, h);
872 *dns_cache_mem_used+=e->total_size; /* no need for atomic ops, written
873 only from within a lock */
874 clist_append(&dns_hash[h], e, next, prev);
876 clist_append(dns_last_used_lst, &e->last_used_lst, next, prev);
883 /* creates a "negative" entry which will be valid for ttl seconds */
884 inline static struct dns_hash_entry* dns_cache_mk_bad_entry(str* name,
889 struct dns_hash_entry* e;
893 #ifdef DNS_CACHE_DEBUG
894 DBG("dns_cache_mk_bad_entry(%.*s, %d, %d, %d)\n", name->len, name->s,
897 size=sizeof(struct dns_hash_entry)+name->len-1+1;
900 LOG(L_ERR, "ERROR: dns_cache_mk_bad_entry: out of memory\n");
903 memset(e, 0, size); /* init with 0*/
905 e->name_len=name->len;
909 e->expire=now+S_TO_TICKS(ttl);
910 memcpy(e->name, name->s, name->len);
917 /* create a a/aaaa hash entry from a name and ip address
918 * returns 0 on error */
919 inline static struct dns_hash_entry* dns_cache_mk_ip_entry(str* name,
922 struct dns_hash_entry* e;
926 /* everything is allocated in one block: dns_hash_entry + name +
927 * + dns_rr + rdata; dns_rr must start at an aligned adress,
928 * hence we need to round dns_hash_entry+name size to a sizeof(long)
931 * struct dns_hash_entry
932 * name (name_len+1 bytes)
933 * padding to multiple of sizeof(long)
935 * rdata (no padding needed, since for ip is just an array of chars)
937 size=ROUND_POINTER(sizeof(struct dns_hash_entry)+name->len-1+1)+
938 sizeof(struct dns_rr)+ ip->len;
941 LOG(L_ERR, "ERROR: dns_cache_mk_ip_entry: out of memory\n");
944 memset(e, 0, size); /* init with 0*/
946 e->name_len=name->len;
947 e->type=(ip->af==AF_INET)?T_A:T_AAAA;
950 e->expire=now-1; /* maximum expire */
951 memcpy(e->name, name->s, name->len); /* memset makes sure is 0-term. */
952 e->rr_lst=(void*)((char*)e+
953 ROUND_POINTER(sizeof(struct dns_hash_entry)+name->len-1+1));
954 e->rr_lst->rdata=(void*)((char*)e->rr_lst+sizeof(struct dns_rr));
955 e->rr_lst->expire=now-1; /* maximum expire */
956 /* no need to align rr_lst->rdata for a or aaaa records */
957 memcpy(e->rr_lst->rdata, ip->u.addr, ip->len);
961 /* creates an srv hash entry from the given parameters
962 * returns 0 on error */
963 static struct dns_hash_entry* dns_cache_mk_srv_entry(str* name,
964 unsigned short priority,
965 unsigned short weight,
970 struct dns_hash_entry* e;
974 /* everything is allocated in one block: dns_hash_entry + name +
975 * + dns_rr + rdata; dns_rr must start at an aligned adress,
976 * hence we need to round dns_hash_entry+name size to a sizeof(long),
977 * and similarly, dns_rr must be rounded to sizeof(short).
980 * struct dns_hash_entry
981 * name (name_len+1 bytes)
982 * padding to multiple of sizeof(long)
984 * padding to multiple of sizeof(short)
987 size=ROUND_POINTER(sizeof(struct dns_hash_entry)+name->len-1+1) +
988 ROUND_SHORT(sizeof(struct dns_rr)) +
989 sizeof(struct srv_rdata)-1 +
994 LOG(L_ERR, "ERROR: dns_cache_srv_ip_entry: out of memory\n");
997 memset(e, 0, size); /* init with 0*/
999 e->name_len=name->len;
1001 now=get_ticks_raw();
1003 e->expire=now+S_TO_TICKS(ttl);
1004 memcpy(e->name, name->s, name->len); /* memset makes sure is 0-term. */
1005 e->rr_lst=(void*)((char*)e+
1006 ROUND_POINTER(sizeof(struct dns_hash_entry)+name->len-1+1));
1007 e->rr_lst->rdata=(void*)((char*)e->rr_lst+ROUND_SHORT(sizeof(struct dns_rr)));
1008 e->rr_lst->expire=e->expire;
1009 ((struct srv_rdata*)e->rr_lst->rdata)->priority = priority;
1010 ((struct srv_rdata*)e->rr_lst->rdata)->weight = weight;
1011 ((struct srv_rdata*)e->rr_lst->rdata)->port = port;
1012 ((struct srv_rdata*)e->rr_lst->rdata)->name_len = rr_name->len;
1013 memcpy(((struct srv_rdata*)e->rr_lst->rdata)->name, rr_name->s, rr_name->len);
1018 /* create a dns hash entry from a name and a rdata list (pkg_malloc'ed)
1019 * (it will use only the type records with the name "name" from the
1020 * rdata list with one exception: if a matching CNAME with the same
1021 * name is found, the search will stop and this will be the record used)
1022 * returns 0 on error and removes the used elements from the rdata list*/
1023 inline static struct dns_hash_entry* dns_cache_mk_rd_entry(str* name, int type,
1024 struct rdata** rd_lst)
1026 struct dns_hash_entry* e;
1028 struct dns_rr** tail_rr;
1030 struct rdata* tmp_lst;
1031 struct rdata** tail;
1035 unsigned int max_ttl;
1039 #define rec_matches(rec, t, n) /*(struct rdata* record, int type, str* name)*/\
1040 ( ((rec)->name_len==(n)->len) && ((rec)->type==(t)) && \
1041 (strncasecmp((rec)->name, (n)->s, (n)->len)==0))
1047 /* everything is allocated in one block: dns_hash_entry + name +
1048 * + dns_rr + rdata_raw+ ....; dns_rr must start at an aligned adress,
1049 * hence we need to round dns_hash_entry+name size to a sizeof(long)
1050 * multiple. If rdata type requires it, rdata_raw might need to be also
1053 * struct dns_hash_entry (e)
1054 * name (name_len+1 bytes) (&e->name[0])
1055 * padding to multiple of sizeof(char*)
1056 * dns_rr1 (e->rr_lst)
1057 * possible padding: no padding for a_rdata or aaaa_rdata,
1058 * multipe of sizeof(short) for srv_rdata,
1059 * multiple of sizeof(long) for naptr_rdata and others
1060 * dns_rr1->rdata (e->rr_lst->rdata)
1061 * padding to multipe of sizeof long
1062 * dns_rr2 (e->rr_lst->next)
1069 /* find the first matching rr, if it's a CNAME use CNAME as type,
1070 * if not continue with the original type */
1071 for(p=rd_lst; *p; p=&(*p)->next){
1072 if (((*p)->name_len==name->len) &&
1073 (((*p)->type==type) || ((*p)->type==T_CNAME)) &&
1074 (strncasecmp((*p)->name, name->s, name->len)==0)){
1079 /* continue, we found the type we are looking for */
1083 if (!rec_matches((*p), type, name)){
1084 /* skip this record */
1085 p=&(*p)->next; /* advance */
1088 size+=ROUND_POINTER(sizeof(struct dns_rr)+
1089 sizeof(struct a_rdata));
1090 /* add it to our tmp. lst */
1093 /* detach it from the rd list */
1095 /* don't advance p, because the crt. elem. has
1096 * just been elimintated */
1101 if (!rec_matches((*p), type, name)){
1102 /* skip this record */
1103 p=&(*p)->next; /* advance */
1107 size+=ROUND_POINTER(sizeof(struct dns_rr)+
1108 sizeof(struct aaaa_rdata));
1109 /* add it to our tmp. lst */
1112 /* detach it from the rd list */
1114 /* don't advance p, because the crt. elem. has
1115 * just been elimintated */
1120 if (!rec_matches((*p), type, name)){
1121 /* skip this record */
1122 p=&(*p)->next; /* advance */
1125 /* padding to short */
1126 size+=ROUND_POINTER(ROUND_SHORT(sizeof(struct dns_rr))+
1127 SRV_RDATA_SIZE(*(struct srv_rdata*)(*p)->rdata));
1128 /* add it to our tmp. lst */
1131 /* detach it from the rd list */
1133 /* don't advance p, because the crt. elem. has
1134 * just been elimintated */
1139 if (!rec_matches((*p), type, name)){
1140 /* skip this record */
1141 p=&(*p)->next; /* advance */
1144 /* padding to char* */
1145 size+=ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
1146 NAPTR_RDATA_SIZE(*(struct naptr_rdata*)(*p)->rdata));
1147 /* add it to our tmp. lst */
1150 /* detach it from the rd list */
1152 /* don't advance p, because the crt. elem. has
1153 * just been elimintated */
1158 if (!rec_matches((*p), type, name)){
1159 /* skip this record */
1160 p=&(*p)->next; /* advance */
1164 size+=ROUND_POINTER(sizeof(struct dns_rr)+
1165 CNAME_RDATA_SIZE(*(struct cname_rdata*)(*p)->rdata));
1166 /* add it to our tmp. lst */
1169 /* detach it from the rd list */
1171 /* don't advance p, because the crt. elem. has
1172 * just been elimintated */
1177 if (!rec_matches((*p), type, name)){
1178 /* skip this record */
1179 p=&(*p)->next; /* advance */
1182 /* padding to char* (because of txt[]->cstr*/
1183 size+=ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
1184 TXT_RDATA_SIZE(*(struct txt_rdata*)(*p)->rdata));
1185 /* add it to our tmp. lst */
1188 /* detach it from the rd list */
1190 /* don't advance p, because the crt. elem. has
1191 * just been elimintated */
1196 if (!rec_matches((*p), type, name)){
1197 /* skip this record */
1198 p=&(*p)->next; /* advance */
1201 /* padding to char* (because of the char* pointers */
1202 size+=ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
1203 EBL_RDATA_SIZE(*(struct ebl_rdata*)(*p)->rdata));
1204 /* add it to our tmp. lst */
1207 /* detach it from the rd list */
1209 /* don't advance p, because the crt. elem. has
1210 * just been elimintated */
1215 if (!rec_matches((*p), type, name)){
1216 /* skip this record */
1217 p=&(*p)->next; /* advance */
1221 size+=ROUND_POINTER(sizeof(struct dns_rr)+
1222 PTR_RDATA_SIZE(*(struct ptr_rdata*)(*p)->rdata));
1223 /* add it to our tmp. lst */
1226 /* detach it from the rd list */
1228 /* don't advance p, because the crt. elem. has
1229 * just been elimintated */
1233 LOG(L_CRIT, "BUG: dns_cache_mk_rd_entry: type %d not "
1234 "supported\n", type);
1235 /* we don't know what to do with it, so don't
1236 * add it to the tmp_lst */
1237 return 0; /* error */
1239 *tail=0; /* mark the end of our tmp_lst */
1241 #ifdef DNS_CACHE_DEBUG
1242 DBG("dns_cache_mk_rd_entry: entry %.*s (%d) not found\n",
1243 name->len, name->s, type);
1248 size+=ROUND_POINTER(sizeof(struct dns_hash_entry)+name->len-1+1);
1251 LOG(L_ERR, "ERROR: dns_cache_mk_rd_entry: out of memory\n");
1254 memset(e, 0, size); /* init with 0 */
1255 clist_init(e, next, prev);
1257 e->name_len=name->len;
1259 now=get_ticks_raw();
1261 memcpy(e->name, name->s, name->len); /* memset makes sure is 0-term. */
1262 e->rr_lst=(struct dns_rr*)((char*)e+
1263 ROUND_POINTER(sizeof(struct dns_hash_entry)+name->len-1+1));
1264 tail_rr=&(e->rr_lst);
1267 /* copy the actual data */
1270 for(l=tmp_lst; l; l=l->next){
1271 ttl=FIX_TTL(l->ttl);
1272 rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1273 max_ttl=MAX(max_ttl, ttl);
1274 rr->rdata=(void*)((char*)rr+sizeof(struct dns_rr));
1275 memcpy(rr->rdata, l->rdata, sizeof(struct a_rdata));
1276 rr->next=(void*)((char*)rr+ROUND_POINTER(sizeof(struct dns_rr)+
1277 sizeof(struct a_rdata)));
1278 tail_rr=&(rr->next);
1283 for(l=tmp_lst; l; l=l->next){
1284 ttl=FIX_TTL(l->ttl);
1285 rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1286 max_ttl=MAX(max_ttl, ttl);
1287 rr->rdata=(void*)((char*)rr+sizeof(struct dns_rr));
1288 memcpy(rr->rdata, l->rdata, sizeof(struct aaaa_rdata));
1289 rr->next=(void*)((char*)rr+ROUND_POINTER(sizeof(struct dns_rr)+
1290 sizeof(struct aaaa_rdata)));
1291 tail_rr=&(rr->next);
1296 for(l=tmp_lst; l; l=l->next){
1297 ttl=FIX_TTL(l->ttl);
1298 rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1299 max_ttl=MAX(max_ttl, ttl);
1300 rr->rdata=(void*)((char*)rr+
1301 ROUND_SHORT(sizeof(struct dns_rr)));
1302 /* copy the whole srv_rdata block*/
1303 memcpy(rr->rdata, l->rdata,
1304 SRV_RDATA_SIZE(*(struct srv_rdata*)l->rdata) );
1305 rr->next=(void*)((char*)rr+
1306 ROUND_POINTER( ROUND_SHORT(sizeof(struct dns_rr))+
1308 *(struct srv_rdata*)l->rdata)));
1309 tail_rr=&(rr->next);
1314 for(l=tmp_lst; l; l=l->next){
1315 ttl=FIX_TTL(l->ttl);
1316 rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1317 max_ttl=MAX(max_ttl, ttl);
1318 rr->rdata=(void*)((char*)rr+
1319 ROUND_POINTER(sizeof(struct dns_rr)));
1320 /* copy the whole naptr_rdata block*/
1321 memcpy(rr->rdata, l->rdata,
1322 NAPTR_RDATA_SIZE(*(struct naptr_rdata*)l->rdata) );
1323 /* adjust the string pointer */
1324 ((struct naptr_rdata*)rr->rdata)->flags=
1325 translate_pointer((char*)rr->rdata, (char*)l->rdata,
1326 (((struct naptr_rdata*)l->rdata)->flags));
1327 ((struct naptr_rdata*)rr->rdata)->services=
1328 translate_pointer((char*)rr->rdata, (char*)l->rdata,
1329 (((struct naptr_rdata*)l->rdata)->services));
1330 ((struct naptr_rdata*)rr->rdata)->regexp=
1331 translate_pointer((char*)rr->rdata, (char*)l->rdata,
1332 (((struct naptr_rdata*)l->rdata)->regexp));
1333 ((struct naptr_rdata*)rr->rdata)->repl=
1334 translate_pointer((char*)rr->rdata, (char*)l->rdata,
1335 (((struct naptr_rdata*)l->rdata)->repl));
1336 rr->next=(void*)((char*)rr+
1337 ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
1339 *(struct naptr_rdata*)l->rdata)));
1340 tail_rr=&(rr->next);
1345 for(l=tmp_lst; l; l=l->next){
1346 ttl=FIX_TTL(l->ttl);
1347 rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1348 max_ttl=MAX(max_ttl, ttl);
1349 rr->rdata=(void*)((char*)rr+sizeof(struct dns_rr));
1350 memcpy(rr->rdata, l->rdata,
1351 CNAME_RDATA_SIZE(*(struct cname_rdata*)l->rdata));
1352 rr->next=(void*)((char*)rr+ROUND_POINTER(sizeof(struct dns_rr)+
1353 CNAME_RDATA_SIZE(*(struct cname_rdata*)l->rdata)));
1354 tail_rr=&(rr->next);
1359 for(l=tmp_lst; l; l=l->next){
1360 ttl=FIX_TTL(l->ttl);
1361 rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1362 max_ttl=MAX(max_ttl, ttl);
1363 rr->rdata=(void*)((char*)rr+
1364 ROUND_POINTER(sizeof(struct dns_rr)));
1365 memcpy(rr->rdata, l->rdata,
1366 TXT_RDATA_SIZE(*(struct txt_rdata*)l->rdata));
1367 /* adjust the string pointers */
1368 for (i=0; i<((struct txt_rdata*)l->rdata)->cstr_no; i++){
1369 ((struct txt_rdata*)rr->rdata)->txt[i].cstr=
1370 translate_pointer((char*)rr->rdata, (char*)l->rdata,
1371 ((struct txt_rdata*)l->rdata)->txt[i].cstr);
1373 rr->next=(void*)((char*)rr+
1374 ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
1375 TXT_RDATA_SIZE(*(struct txt_rdata*)l->rdata)));
1376 tail_rr=&(rr->next);
1381 for(l=tmp_lst; l; l=l->next){
1382 ttl=FIX_TTL(l->ttl);
1383 rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1384 max_ttl=MAX(max_ttl, ttl);
1385 rr->rdata=(void*)((char*)rr+
1386 ROUND_POINTER(sizeof(struct dns_rr)));
1387 memcpy(rr->rdata, l->rdata,
1388 EBL_RDATA_SIZE(*(struct ebl_rdata*)l->rdata));
1389 /* adjust the string pointers */
1390 ((struct ebl_rdata*)rr->rdata)->separator=
1391 translate_pointer((char*)rr->rdata, (char*)l->rdata,
1392 ((struct ebl_rdata*)l->rdata)->separator);
1393 ((struct ebl_rdata*)rr->rdata)->separator=
1394 translate_pointer((char*)rr->rdata, (char*)l->rdata,
1395 ((struct ebl_rdata*)l->rdata)->separator);
1396 ((struct ebl_rdata*)rr->rdata)->apex=
1397 translate_pointer((char*)rr->rdata, (char*)l->rdata,
1398 ((struct ebl_rdata*)l->rdata)->apex);
1399 rr->next=(void*)((char*)rr+
1400 ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
1401 EBL_RDATA_SIZE(*(struct ebl_rdata*)l->rdata)));
1402 tail_rr=&(rr->next);
1407 for(l=tmp_lst; l; l=l->next){
1408 ttl=FIX_TTL(l->ttl);
1409 rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1410 max_ttl=MAX(max_ttl, ttl);
1411 rr->rdata=(void*)((char*)rr+sizeof(struct dns_rr));
1412 memcpy(rr->rdata, l->rdata,
1413 PTR_RDATA_SIZE(*(struct ptr_rdata*)l->rdata));
1414 rr->next=(void*)((char*)rr+ROUND_POINTER(sizeof(struct dns_rr)+
1415 PTR_RDATA_SIZE(*(struct ptr_rdata*)l->rdata)));
1416 tail_rr=&(rr->next);
1422 LOG(L_CRIT, "BUG: dns_cache_mk_rd_entry: create: type %d not "
1423 "supported\n", type);
1426 *tail_rr=0; /* terminate the list */
1427 e->expire=now+S_TO_TICKS(max_ttl);
1428 free_rdata_list(tmp_lst);
1434 /* structure used only inside dns_cache_mk_rd_entry2 to break
1435 * the list of records into records of the same type */
1438 struct dns_hash_entry* e;
1440 struct dns_rr** tail_rr;
1447 /* create several dns hash entries from a list of rdata structs
1448 * returns 0 on error */
1449 inline static struct dns_hash_entry* dns_cache_mk_rd_entry2(struct rdata* rd)
1453 struct tmp_rec rec[MAX_DNS_RECORDS];
1454 int rec_idx[MAX_DNS_RECORDS];
1456 int no_records; /* number of different records */
1462 /* everything is allocated in one block: dns_hash_entry + name +
1463 * + dns_rr + rdata_raw+ ....; dns_rr must start at an aligned adress,
1464 * hence we need to round dns_hash_entry+name size to a sizeof(long)
1465 * multiple. If rdata type requires it, rdata_raw might need to be also
1468 * struct dns_hash_entry (e)
1469 * name (name_len+1 bytes) (&e->name[0])
1470 * padding to multiple of sizeof(char*)
1471 * dns_rr1 (e->rr_lst)
1472 * possible padding: no padding for a_rdata or aaaa_rdata,
1473 * multipe of sizeof(short) for srv_rdata,
1474 * multiple of sizeof(long) for naptr_rdata and others
1475 * dns_rr1->rdata (e->rr_lst->rdata)
1476 * padding to multipe of sizeof long
1477 * dns_rr2 (e->rr_lst->next)
1482 for(l=rd, i=0; l && (i<MAX_DNS_RECORDS); l=l->next, i++){
1483 for (r=0; r<no_records; r++){
1484 if ((l->type==rec[r].rd->type) &&
1485 (l->name_len==rec[r].rd->name_len)
1486 && (strncasecmp(l->name, rec[r].rd->name, l->name_len)==0)){
1491 /* not found, create new */
1492 if (no_records<MAX_DNS_RECORDS){
1495 rec[r].size=ROUND_POINTER(sizeof(struct dns_hash_entry)+
1496 rec[r].rd->name_len-1+1);
1499 LOG(L_ERR, "ERROR: dns_cache_mk_rd_entry2: too many records: %d\n",
1509 rec[r].size+=ROUND_POINTER(sizeof(struct dns_rr)+
1510 sizeof(struct a_rdata));
1514 rec[r].size+=ROUND_POINTER(sizeof(struct dns_rr)+
1515 sizeof(struct aaaa_rdata));
1518 /* padding to short */
1519 rec[r].size+=ROUND_POINTER(ROUND_SHORT(sizeof(struct dns_rr))+
1520 SRV_RDATA_SIZE(*(struct srv_rdata*)l->rdata));
1523 /* padding to char* */
1524 rec[r].size+=ROUND_POINTER(ROUND_POINTER(
1525 sizeof(struct dns_rr))+
1526 NAPTR_RDATA_SIZE(*(struct naptr_rdata*)l->rdata));
1530 rec[r].size+=ROUND_POINTER(sizeof(struct dns_rr)+
1531 CNAME_RDATA_SIZE(*(struct cname_rdata*)l->rdata));
1534 /* padding to char* (because of txt[]->cstr)*/
1535 rec[r].size+=ROUND_POINTER(ROUND_POINTER(
1536 sizeof(struct dns_rr))+
1537 TXT_RDATA_SIZE(*(struct txt_rdata*)l->rdata));
1540 /* padding to char* (because of char* pointers)*/
1541 rec[r].size+=ROUND_POINTER(ROUND_POINTER(
1542 sizeof(struct dns_rr))+
1543 EBL_RDATA_SIZE(*(struct ebl_rdata*)l->rdata));
1547 rec[r].size+=ROUND_POINTER(sizeof(struct dns_rr)+
1548 PTR_RDATA_SIZE(*(struct ptr_rdata*)l->rdata));
1551 LOG(L_CRIT, "BUG: dns_cache_mk_rd_entry: type %d not "
1552 "supported\n", l->type);
1556 now=get_ticks_raw();
1557 /* alloc & init the entries */
1558 for (r=0; r<no_records; r++){
1559 rec[r].e=shm_malloc(rec[r].size);
1561 LOG(L_ERR, "ERROR: dns_cache_mk_rd_entry: out of memory\n");
1564 memset(rec[r].e, 0, rec[r].size); /* init with 0*/
1565 rec[r].e->total_size=rec[r].size;
1566 rec[r].e->name_len=rec[r].rd->name_len;
1567 rec[r].e->type=rec[r].rd->type;
1568 rec[r].e->last_used=now;
1569 /* memset makes sure is 0-term. */
1570 memcpy(rec[r].e->name, rec[r].rd->name, rec[r].rd->name_len);
1571 rec[r].e->rr_lst=(struct dns_rr*)((char*)rec[r].e+
1572 ROUND_POINTER(sizeof(struct dns_hash_entry)+rec[r].e->name_len
1574 rec[r].tail_rr=&(rec[r].e->rr_lst);
1575 rec[r].rr=rec[r].e->rr_lst;
1577 /* link them in a list */
1579 clist_init(rec[r].e, next, prev);
1581 clist_append(rec[0].e, rec[r].e, next, prev);
1584 /* copy the actual data */
1585 for(l=rd, i=0; l && (i<MAX_DNS_RECORDS); l=l->next, i++){
1587 ttl=FIX_TTL(l->ttl);
1590 rec[r].rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1591 rec[r].max_ttl=MAX(rec[r].max_ttl, ttl);
1592 rec[r].rr->rdata=(void*)((char*)rec[r].rr+
1593 sizeof(struct dns_rr));
1594 memcpy(rec[r].rr->rdata, l->rdata, sizeof(struct a_rdata));
1595 rec[r].rr->next=(void*)((char*)rec[r].rr+
1596 ROUND_POINTER(sizeof(struct dns_rr)+
1597 sizeof(struct a_rdata)));
1598 rec[r].tail_rr=&(rec[r].rr->next);
1599 rec[r].rr=rec[r].rr->next;
1602 rec[r].rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1603 rec[r].max_ttl=MAX(rec[r].max_ttl, ttl);
1604 rec[r].rr->rdata=(void*)((char*)rec[r].rr+
1605 sizeof(struct dns_rr));
1606 memcpy(rec[r].rr->rdata, l->rdata, sizeof(struct aaaa_rdata));
1607 rec[r].rr->next=(void*)((char*)rec[r].rr+
1608 ROUND_POINTER(sizeof(struct dns_rr)+
1609 sizeof(struct aaaa_rdata)));
1610 rec[r].tail_rr=&(rec[r].rr->next);
1611 rec[r].rr=rec[r].rr->next;
1614 rec[r].rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1615 rec[r].max_ttl=MAX(rec[r].max_ttl, ttl);
1616 rec[r].rr->rdata=(void*)((char*)rec[r].rr+
1617 ROUND_SHORT(sizeof(struct dns_rr)));
1618 /* copy the whole srv_rdata block*/
1619 memcpy(rec[r].rr->rdata, l->rdata,
1620 SRV_RDATA_SIZE(*(struct srv_rdata*)l->rdata) );
1621 rec[r].rr->next=(void*)((char*)rec[r].rr+
1622 ROUND_POINTER( ROUND_SHORT(sizeof(struct dns_rr))+
1624 *(struct srv_rdata*)l->rdata)));
1625 rec[r].tail_rr=&(rec[r].rr->next);
1626 rec[r].rr=rec[r].rr->next;
1629 rec[r].rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1630 rec[r].max_ttl=MAX(rec[r].max_ttl, ttl);
1631 rec[r].rr->rdata=(void*)((char*)rec[r].rr+
1632 ROUND_POINTER(sizeof(struct dns_rr)));
1633 /* copy the whole srv_rdata block*/
1634 memcpy(rec[r].rr->rdata, l->rdata,
1635 NAPTR_RDATA_SIZE(*(struct naptr_rdata*)l->rdata) );
1636 /* adjust the string pointer */
1637 ((struct naptr_rdata*)rec[r].rr->rdata)->flags=
1638 translate_pointer((char*)rec[r].rr->rdata, (char*)l->rdata,
1639 (((struct naptr_rdata*)l->rdata)->flags));
1640 ((struct naptr_rdata*)rec[r].rr->rdata)->services=
1641 translate_pointer((char*)rec[r].rr->rdata, (char*)l->rdata,
1642 (((struct naptr_rdata*)l->rdata)->services));
1643 ((struct naptr_rdata*)rec[r].rr->rdata)->regexp=
1644 translate_pointer((char*)rec[r].rr->rdata, (char*)l->rdata,
1645 (((struct naptr_rdata*)l->rdata)->regexp));
1646 ((struct naptr_rdata*)rec[r].rr->rdata)->repl=
1647 translate_pointer((char*)rec[r].rr->rdata, (char*)l->rdata,
1648 (((struct naptr_rdata*)l->rdata)->repl));
1649 rec[r].rr->next=(void*)((char*)rec[r].rr+
1650 ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
1652 *(struct naptr_rdata*)l->rdata)));
1653 rec[r].tail_rr=&(rec[r].rr->next);
1654 rec[r].rr=rec[r].rr->next;
1657 rec[r].rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1658 rec[r].max_ttl=MAX(rec[r].max_ttl, ttl);
1659 rec[r].rr->rdata=(void*)((char*)rec[r].rr
1660 +sizeof(struct dns_rr));
1661 memcpy(rec[r].rr->rdata, l->rdata,
1662 CNAME_RDATA_SIZE(*(struct cname_rdata*)l->rdata));
1663 rec[r].rr->next=(void*)((char*)rec[r].rr+
1664 ROUND_POINTER(sizeof(struct dns_rr)+
1665 CNAME_RDATA_SIZE(*(struct cname_rdata*)l->rdata)));
1666 rec[r].tail_rr=&(rec[r].rr->next);
1667 rec[r].rr=rec[r].rr->next;
1670 rec[r].rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1671 rec[r].max_ttl=MAX(rec[r].max_ttl, ttl);
1672 rec[r].rr->rdata=(void*)((char*)rec[r].rr+
1673 ROUND_POINTER(sizeof(struct dns_rr)));
1674 memcpy(rec[r].rr->rdata, l->rdata,
1675 TXT_RDATA_SIZE(*(struct txt_rdata*)l->rdata));
1676 /* adjust the string pointers */
1677 for (j=0; j<((struct txt_rdata*)l->rdata)->cstr_no; j++){
1678 ((struct txt_rdata*)rec[r].rr->rdata)->txt[j].cstr=
1679 translate_pointer((char*)rec[r].rr->rdata,
1681 ((struct txt_rdata*)l->rdata)->txt[j].cstr);
1683 rec[r].rr->next=(void*)((char*)rec[r].rr+
1684 ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
1685 TXT_RDATA_SIZE(*(struct txt_rdata*)l->rdata)));
1686 rec[r].tail_rr=&(rec[r].rr->next);
1687 rec[r].rr=rec[r].rr->next;
1690 rec[r].rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1691 rec[r].max_ttl=MAX(rec[r].max_ttl, ttl);
1692 rec[r].rr->rdata=(void*)((char*)rec[r].rr+
1693 ROUND_POINTER(sizeof(struct dns_rr)));
1694 memcpy(rec[r].rr->rdata, l->rdata,
1695 EBL_RDATA_SIZE(*(struct ebl_rdata*)l->rdata));
1696 /* adjust the string pointers */
1697 ((struct ebl_rdata*)rec[r].rr->rdata)->separator=
1698 translate_pointer((char*)rec[r].rr->rdata,
1700 ((struct ebl_rdata*)l->rdata)->separator);
1701 ((struct ebl_rdata*)rec[r].rr->rdata)->apex=
1702 translate_pointer((char*)rec[r].rr->rdata,
1704 ((struct ebl_rdata*)l->rdata)->apex);
1705 rec[r].rr->next=(void*)((char*)rec[r].rr+
1706 ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
1707 EBL_RDATA_SIZE(*(struct ebl_rdata*)l->rdata)));
1708 rec[r].tail_rr=&(rec[r].rr->next);
1709 rec[r].rr=rec[r].rr->next;
1712 rec[r].rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1713 rec[r].max_ttl=MAX(rec[r].max_ttl, ttl);
1714 rec[r].rr->rdata=(void*)((char*)rec[r].rr
1715 +sizeof(struct dns_rr));
1716 memcpy(rec[r].rr->rdata, l->rdata,
1717 PTR_RDATA_SIZE(*(struct ptr_rdata*)l->rdata));
1718 rec[r].rr->next=(void*)((char*)rec[r].rr+
1719 ROUND_POINTER(sizeof(struct dns_rr)+
1720 PTR_RDATA_SIZE(*(struct ptr_rdata*)l->rdata)));
1721 rec[r].tail_rr=&(rec[r].rr->next);
1722 rec[r].rr=rec[r].rr->next;
1729 for (r=0; r<no_records; r++){
1730 *rec[r].tail_rr=0; /* terminate the list */
1731 rec[r].e->expire=now+S_TO_TICKS(rec[r].max_ttl);
1735 for (r=0; r<no_records; r++){
1736 dns_destroy_entry(rec[r].e);
1743 inline static struct dns_hash_entry* dns_get_entry(str* name, int type);
1746 #define CACHE_RELEVANT_RECS_ONLY
1748 #ifdef CACHE_RELEVANT_RECS_ONLY
1749 /* internal only: gets related entries from a rdata list, appends them
1750 * to e (list) and returns:
1751 * - e if e is of the requested type
1752 * - if e is a CNAME, tries to get to the end of the CNAME chain and returns
1753 * the final entry if the types match or 0 if the chain is unfinished
1754 * - 0 on error/not found
1755 * records is modified (the used records are removed from the list and freed)
1757 * WARNING: - records must be pkg_malloc'ed
1758 * Notes: - if the return is 0 and e->type==T_CNAME, the list will contain
1759 * the CNAME chain (the last element being the last CNAME)
1761 inline static struct dns_hash_entry* dns_get_related(struct dns_hash_entry* e,
1763 struct rdata** records)
1765 struct dns_hash_entry* ret;
1766 struct dns_hash_entry* l;
1767 struct dns_hash_entry* t;
1768 struct dns_hash_entry* lst_end;
1770 static int cname_chain_len=0;
1775 #ifdef DNS_CACHE_DEBUG
1776 DBG("dns_get_related(%p (%.*s, %d), %d, *%p) (%d)\n", e,
1777 e->name_len, e->name, e->type, type, *records, cname_chain_len);
1779 clist_init(l, next, prev);
1784 for (rr=e->rr_lst; rr && *records; rr=rr->next){
1785 tmp.s=((struct srv_rdata*)rr->rdata)->name;
1786 tmp.len=((struct srv_rdata*)rr->rdata)->name_len;
1787 if (!(dns_flags&DNS_IPV6_ONLY)){
1788 t=dns_cache_mk_rd_entry(&tmp, T_A, records);
1790 if ((t->type==T_CNAME) && *records)
1791 dns_get_related(t, T_A, records);
1792 lst_end=t->prev; /* needed for clist_append*/
1793 clist_append_sublist(l, t, lst_end, next, prev);
1796 if (!(dns_flags&DNS_IPV4_ONLY)){
1797 t=dns_cache_mk_rd_entry(&tmp, T_AAAA, records);
1799 if ((t->type==T_CNAME) && *records)
1800 dns_get_related(t, T_AAAA, records);
1801 lst_end=t->prev; /* needed for clist_append*/
1802 clist_append_sublist(l, t, lst_end, next, prev);
1809 #ifdef NAPTR_CACHE_ALL_ARS
1811 dns_cache_mk_rd_entry2(*records);
1813 for (rr=e->rr_lst; rr && *records; rr=rr->next){
1814 if (naptr_get_sip_proto((struct naptr_rdata*)rr->rdata)>0){
1815 tmp.s=((struct naptr_rdata*)rr->rdata)->repl;
1816 tmp.len=((struct naptr_rdata*)rr->rdata)->repl_len;
1817 t=dns_cache_mk_rd_entry(&tmp, T_SRV, records);
1820 dns_get_related(t, T_SRV, records);
1821 lst_end=t->prev; /* needed for clist_append*/
1822 clist_append_sublist(l, t, lst_end, next, prev);
1826 #endif /* NAPTR_CACHE_ALL_ARS */
1827 #endif /* USE_NAPTR */
1833 }else if ((e->type==T_CNAME) && (cname_chain_len<MAX_CNAME_CHAIN)){
1834 /* only one cname is allowed (rfc2181), so we ignore
1835 * the others (we take only the first one) */
1836 tmp.s=((struct cname_rdata*)e->rr_lst->rdata)->name;
1837 tmp.len=((struct cname_rdata*)e->rr_lst->rdata)->name_len;
1838 t=dns_cache_mk_rd_entry(&tmp, type, records);
1842 ret=dns_get_related(t, type, records);
1845 clist_append_sublist(l, t, lst_end, next, prev);
1847 /* if no more recs, but we found the orig. target anyway,
1848 * return it (e.g. recs are only CNAME x & x A 1.2.3.4 or
1852 clist_append(l, t, next, prev);
1862 /* calls the external resolver and populates the cache with the result
1863 * returns: 0 on error, pointer to hash entry on success
1864 * WARNING: make sure you use dns_hash_entry_put() when you're
1865 * finished with the result)
1867 inline static struct dns_hash_entry* dns_cache_do_request(str* name, int type)
1869 struct rdata* records;
1870 struct dns_hash_entry* e;
1871 struct dns_hash_entry* l;
1872 struct dns_hash_entry* r;
1873 struct dns_hash_entry* t;
1876 char name_buf[MAX_DNS_NAME];
1877 struct dns_hash_entry* old;
1879 int add_record, h, err;
1886 #ifdef USE_DNS_CACHE_STATS
1887 if (dns_cache_stats)
1888 dns_cache_stats[process_no].dns_req_cnt++;
1889 #endif /* USE_DNS_CACHE_STATS */
1892 if ((ip=str2ip(name))!=0){
1893 e=dns_cache_mk_ip_entry(name, ip);
1895 atomic_set(&e->refcnt, 1);/* because we ret. a ref. to it*/
1896 goto end; /* we do not cache obvious stuff */
1900 else if (type==T_AAAA){
1901 if ((ip=str2ip6(name))!=0){
1902 e=dns_cache_mk_ip_entry(name, ip);
1904 atomic_set(&e->refcnt, 1);/* because we ret. a ref. to it*/
1905 goto end;/* we do not cache obvious stuff */
1908 #endif /* USE_IPV6 */
1909 #ifdef DNS_WATCHDOG_SUPPORT
1910 if (atomic_get(dns_servers_up)==0)
1911 goto end; /* the servers are down, needless to perform the query */
1913 if (name->len>=MAX_DNS_NAME){
1914 LOG(L_ERR, "ERROR: dns_cache_do_request: name too long (%d chars)\n",
1918 /* null terminate the string, needed by get_record */
1919 memcpy(name_buf, name->s, name->len);
1920 name_buf[name->len]=0;
1921 records=get_record(name_buf, type, RES_AR);
1923 #ifdef CACHE_RELEVANT_RECS_ONLY
1924 e=dns_cache_mk_rd_entry(name, type, &records);
1927 e=dns_get_related(l, type, &records);
1928 /* e should contain the searched entry (if found) and l
1929 * all the entries (e and related) */
1931 atomic_set(&e->refcnt, 1); /* 1 because we return a
1934 /* e==0 => l contains a cname list => we use the last
1935 * cname from the chain for a new resolve attempt (l->prev) */
1936 /* only one cname record is allowed (rfc2181), so we ignore
1937 * the others (we take only the first one) */
1939 ((struct cname_rdata*)l->prev->rr_lst->rdata)->name;
1941 ((struct cname_rdata*)l->prev->rr_lst->rdata)->name_len;
1942 DBG("dns_cache_do_request: cname detected: %.*s (%d)\n",
1943 cname_val.len, cname_val.s, cname_val.len);
1945 /* add all the records to the hash */
1946 l->prev->next=0; /* we break the double linked list for easier
1948 LOCK_DNS_HASH(); /* optimization */
1951 /* add the new record to the cache by default */
1953 if (cfg_get(core, core_cfg, dns_cache_rec_pref) > 0) {
1954 /* check whether there is an old record with the
1955 * same type in the cache */
1956 rec_name.s = r->name;
1957 rec_name.len = r->name_len;
1958 old = _dns_hash_find(&rec_name, r->type, &h, &err);
1960 if (old->type != r->type) {
1961 /* probably CNAME found */
1964 } else if (old->ent_flags & DNS_FLAG_PERMANENT) {
1965 /* never overwrite permanent entries */
1968 } else if ((old->ent_flags & DNS_FLAG_BAD_NAME) == 0) {
1969 /* Non-negative, non-permanent entry found with
1972 /* prefer new records */
1973 ((cfg_get(core, core_cfg, dns_cache_rec_pref) == 2)
1974 /* prefer the record with the longer lifetime */
1975 || ((cfg_get(core, core_cfg, dns_cache_rec_pref) == 3)
1976 && TICKS_LT(old->expire, r->expire)));
1981 dns_cache_add_unsafe(r); /* refcnt++ inside */
1982 if (atomic_get(&r->refcnt)==0){
1983 /* if cache adding failed and nobody else is interested
1984 * destroy this entry */
1985 dns_destroy_entry(r);
1988 _dns_hash_remove(old);
1994 /* this entry has to be returned */
1996 atomic_inc(&e->refcnt);
2000 dns_destroy_entry(r);
2004 /* if only cnames found => try to resolve the last one */
2006 DBG("dns_cache_do_request: dns_get_entry(cname: %.*s (%d))\n",
2007 cname_val.len, cname_val.s, cname_val.len);
2008 e=dns_get_entry(&cname_val, type);
2012 l=dns_cache_mk_rd_entry2(records);
2014 free_rdata_list(records);
2015 }else if (cfg_get(core, core_cfg, dns_neg_cache_ttl)){
2016 e=dns_cache_mk_bad_entry(name, type,
2017 cfg_get(core, core_cfg, dns_neg_cache_ttl), DNS_FLAG_BAD_NAME);
2019 atomic_set(&e->refcnt, 1); /* 1 because we return a ref. to it */
2020 dns_cache_add(e); /* refcnt++ inside*/
2024 #ifndef CACHE_RELEVANT_RECS_ONLY
2026 /* add all the records to the cache, but return only the record
2027 * we are looking for */
2028 l->prev->next=0; /* we break the double linked list for easier
2030 LOCK_DNS_HASH(); /* optimization */
2033 if (e==0){ /* no entry found yet */
2034 if (r->type==T_CNAME){
2035 if ((r->name_len==name->len) && (r->rr_lst) &&
2036 (strncasecmp(r->name, name->s, name->len)==0)){
2037 /* update the name with the name from the cname rec. */
2039 ((struct cname_rdata*)r->rr_lst->rdata)->name;
2041 ((struct cname_rdata*)r->rr_lst->rdata)->name_len;
2044 }else if ((r->type==type) && (r->name_len==name->len) &&
2045 (strncasecmp(r->name, name->s, name->len)==0)){
2047 atomic_set(&e->refcnt, 1); /* 1 because we return a ref.
2052 /* add the new record to the cache by default */
2054 if (cfg_get(core, core_cfg, dns_cache_rec_pref) > 0) {
2055 /* check whether there is an old record with the
2056 * same type in the cache */
2057 rec_name.s = r->name;
2058 rec_name.len = r->name_len;
2059 old = _dns_hash_find(&rec_name, r->type, &h, &err);
2061 if (old->type != r->type) {
2062 /* probably CNAME found */
2065 } else if (old->ent_flags & DNS_FLAG_PERMANENT) {
2066 /* never overwrite permanent entries */
2069 } else if ((old->ent_flags & DNS_FLAG_BAD_NAME) == 0) {
2070 /* Non-negative, non-permanent entry found with
2073 /* prefer new records */
2074 ((cfg_get(core, core_cfg, dns_cache_rec_pref) == 2)
2075 /* prefer the record with the longer lifetime */
2076 || ((cfg_get(core, core_cfg, dns_cache_rec_pref) == 3)
2077 && TICKS_LT(old->expire, r->expire)));
2082 dns_cache_add_unsafe(r); /* refcnt++ inside */
2083 if (atomic_get(&r->refcnt)==0){
2084 /* if cache adding failed and nobody else is interested
2085 * destroy this entry */
2086 dns_destroy_entry(r);
2089 _dns_hash_remove(old);
2095 /* this entry has to be returned */
2097 atomic_inc(&e->refcnt);
2101 dns_destroy_entry(r);
2105 if ((e==0) && (cname_val.s)){ /* not found, but found a cname */
2106 /* only one cname is allowed (rfc2181), so we ignore the
2107 * others (we take only the first one) */
2108 e=dns_get_entry(&cname_val, type);
2118 /* tries to lookup (name, type) in the hash and if not found tries to make
2120 * return: 0 on error, pointer to a dns_hash_entry on success
2121 * WARNING: when not needed anymore dns_hash_put() must be called! */
2122 inline static struct dns_hash_entry* dns_get_entry(str* name, int type)
2125 struct dns_hash_entry* e;
2128 static int rec_cnt=0; /* recursion protection */
2131 if (rec_cnt>MAX_CNAME_CHAIN){
2132 LOG(L_WARN, "WARNING: dns_get_entry: CNAME chain too long or"
2133 " recursive CNAMEs (\"%.*s\")\n", name->len, name->s);
2137 e=dns_hash_get(name, type, &h, &err);
2138 #ifdef USE_DNS_CACHE_STATS
2140 if ((e->ent_flags & DNS_FLAG_BAD_NAME) && dns_cache_stats)
2141 /* negative DNS cache hit */
2142 dns_cache_stats[process_no].dc_neg_hits_cnt++;
2143 else if (((e->ent_flags & DNS_FLAG_BAD_NAME) == 0)
2145 ) /* DNS cache hit */
2146 dns_cache_stats[process_no].dc_hits_cnt++;
2148 if (dns_cache_stats)
2149 dns_cache_stats[process_no].dns_req_cnt++;
2151 #endif /* USE_DNS_CACHE_STATS */
2153 if ((e==0) && ((err) || ((e=dns_cache_do_request(name, type))==0))){
2155 }else if ((e->type==T_CNAME) && (type!=T_CNAME)){
2156 /* cname found instead which couldn't be resolved with the cached
2157 * info => try a dns request */
2158 /* only one cname record is allowed (rfc2181), so we ignore
2159 * the others (we take only the first one) */
2160 cname_val.s= ((struct cname_rdata*)e->rr_lst->rdata)->name;
2161 cname_val.len=((struct cname_rdata*)e->rr_lst->rdata)->name_len;
2162 dns_hash_put(e); /* not interested in the cname anymore */
2163 if ((e=dns_cache_do_request(&cname_val, type))==0)
2164 goto error; /* could not resolve cname */
2167 if ((e->rr_lst==0) || (e->ent_flags & DNS_FLAG_BAD_NAME)){
2168 /* negative cache => not resolvable */
2179 /* gets the first non-expired record starting with record no
2180 * from the dns_hash_entry struct e
2181 * params: e - dns_hash_entry struct
2182 * *no - it must contain the start record number (0 initially);
2183 * it will be filled with the returned record number
2184 * now - current time/ticks value
2185 * returns pointer to the rr on success and sets no to the rr number
2186 * 0 on error and fills the error flags
2189 * list all non-expired non-bad-marked ips for name:
2190 * e=dns_get_entry(name, T_A);
2193 * now=get_ticks_raw();
2194 * while(rr=dns_entry_get_rr(e, no, now){
2195 * DBG("address %d\n", *no);
2196 * *no++; ( get the next address next time )
2200 inline static struct dns_rr* dns_entry_get_rr( struct dns_hash_entry* e,
2201 unsigned char* no, ticks_t now)
2206 #ifdef DNS_WATCHDOG_SUPPORT
2209 servers_up = atomic_get(dns_servers_up);
2213 for(rr=e->rr_lst, n=0;rr && (n<*no);rr=rr->next, n++);/* skip *no records*/
2214 for(;rr;rr=rr->next){
2216 #ifdef DNS_WATCHDOG_SUPPORT
2217 /* check the expiration time only when the servers are up */
2220 ((e->ent_flags & DNS_FLAG_PERMANENT) == 0) &&
2221 ((s_ticks_t)(now-rr->expire)>=0) /* expired rr */
2224 /* everything is ok now */
2235 #define srv_reset_tried(p) (*(p)=0)
2236 #define srv_marked(p, i) (*(p)&(1UL<<(i)))
2237 #define srv_mark_tried(p, i) \
2239 (*(p)|=(1UL<<(i))); \
2242 #define srv_next_rr(n, f, i) srv_mark_tried(f, i)
2244 /* returns a random number between 0 and max inclusive (0<=r<=max) */
2245 inline static unsigned dns_srv_random(unsigned max)
2247 return fastrand_max(max);
2250 /* for a SRV record it will return the next entry to be tried according
2251 * to the RFC2782 server selection mechanism
2253 * e is a dns srv hash entry
2254 * no is the start index of the current group (a group is a set of SRV
2255 * rrs with the same priority)
2256 * tried is a bitmap where the tried srv rrs of the same priority are
2258 * now - current time/ticks value
2259 * returns pointer to the rr on success and sets no to the rr number
2260 * 0 on error and fills the error flags
2261 * WARNING: unlike dns_entry_get_rr() this will always return another
2262 * another rr automatically (*no must not be incremented)
2265 * list all non-expired, non-bad-marked, never tried before srv records
2266 * using the rfc2782 algo:
2267 * e=dns_get_entry(name, T_SRV);
2270 * srv_reset_tried(&tried);
2271 * now=get_ticks_raw();
2272 * while(rr=dns_srv_get_nxt_rr(e, &tried, &no, now){
2273 * DBG("address %d\n", *no);
2278 inline static struct dns_rr* dns_srv_get_nxt_rr(struct dns_hash_entry* e,
2280 unsigned char* no, ticks_t now)
2282 #define MAX_SRV_GRP_IDX (sizeof(srv_flags_t)*8)
2284 struct dns_rr* start_grp;
2292 struct r_sums_entry{
2295 }r_sums[MAX_SRV_GRP_IDX];
2296 #ifdef DNS_WATCHDOG_SUPPORT
2299 servers_up = atomic_get(dns_servers_up);
2303 for(rr=e->rr_lst, n=0;rr && (n<*no);rr=rr->next, n++);/* skip *no records*/
2306 if (unlikely(rr==0))
2309 prio=((struct srv_rdata*)start_grp->rdata)->priority;
2313 for (idx=0;rr && (prio==((struct srv_rdata*)rr->rdata)->priority) &&
2314 (idx < MAX_SRV_GRP_IDX); idx++, rr=rr->next){
2316 #ifdef DNS_WATCHDOG_SUPPORT
2317 /* check the expiration time only when the servers are up */
2320 ((e->ent_flags & DNS_FLAG_PERMANENT) == 0) &&
2321 ((s_ticks_t)(now-rr->expire)>=0) /* expired entry */) ||
2322 (srv_marked(tried, idx)) ) /* already tried */{
2323 r_sums[idx].r_sum=0; /* 0 sum, to skip over it */
2324 r_sums[idx].rr=0; /* debug: mark it as unused */
2327 /* special case, 0 weight records should be "first":
2328 * remember the first rr int the "virtual" list: A 0 weight must
2329 * come first if present, else get the first one */
2330 if ((saved_idx==-1) || (((struct srv_rdata*)rr->rdata)->weight==0)){
2333 sum+=((struct srv_rdata*)rr->rdata)->weight;
2334 r_sums[idx].r_sum=sum;
2339 /* try in the next priority group */
2340 n+=idx; /* next group start idx, last rr */
2341 srv_reset_tried(tried);
2343 }else if ((found==1) || ((rand_w=dns_srv_random(sum))==0)){
2344 /* 1. if only one found, avoid a useless random() call or
2345 * 2. if rand_w==0, immediately select a 0 weight record if present,
2346 * or else the first record found
2347 * (this takes care of the 0-weight at the beginning requirement) */
2348 i=saved_idx; /* saved idx contains either first 0 weight or first
2352 /* if we are here => rand_w is not 0 and we have at least 2 valid options
2353 * => we can safely iterate on the whole r_sums[] whithout any other
2355 for (i=0; (i<idx) && (r_sums[i].r_sum<rand_w); i++);
2357 #ifdef DNS_CACHE_DEBUG
2358 DBG("dns_srv_get_nxt_rr(%p, %lx, %d, %u): selected %d/%d in grp. %d"
2359 " (rand_w=%d, rr=%p p=%d w=%d rsum=%d)\n",
2360 e, (unsigned long)*tried, *no, now, i, idx, n, rand_w, r_sums[i].rr,
2361 ((struct srv_rdata*)r_sums[i].rr->rdata)->priority,
2362 ((struct srv_rdata*)r_sums[i].rr->rdata)->weight, r_sums[i].r_sum);
2364 /* i is the winner */
2365 *no=n; /* grp. start */
2366 srv_mark_tried(tried, i); /* mark it */
2367 return r_sums[i].rr;
2372 #endif /* DNS_SRV_LB */
2376 /* gethostbyname compatibility: converts a dns_hash_entry structure
2377 * to a statical internal hostent structure
2378 * returns a pointer to the internal hostent structure on success or
2381 inline static struct hostent* dns_entry2he(struct dns_hash_entry* e)
2383 static struct hostent he;
2384 static char hostname[256];
2385 static char* p_aliases[1];
2386 static char* p_addr[DNS_HE_MAX_ADDR+1];
2387 static char address[16*DNS_HE_MAX_ADDR]; /* max 10 ipv6 addresses */
2390 unsigned char rr_no;
2404 #else /* USE_IPV6 */
2405 LOG(L_ERR, "ERROR: dns_entry2he: IPv6 dns cache entry, but "
2406 "IPv6 support disabled at compile time"
2407 " (recompile with -DUSE_IPV6)\n");
2409 #endif /* USE_IPV6 */
2411 LOG(L_CRIT, "BUG: dns_entry2he: wrong entry type %d for %.*s\n",
2412 e->type, e->name_len, e->name);
2418 now=get_ticks_raw();
2419 /* if the entry has already expired use the time at the end of lifetime */
2420 if (unlikely((s_ticks_t)(now-e->expire)>=0)) now=e->expire-1;
2421 rr=dns_entry_get_rr(e, &rr_no, now);
2422 for(i=0; rr && (i<DNS_HE_MAX_ADDR); i++,
2423 rr=dns_entry_get_rr(e, &rr_no, now)){
2424 p_addr[i]=&address[i*len];
2425 memcpy(p_addr[i], ((struct a_rdata*)rr->rdata)->ip, len);
2428 DBG("DEBUG: dns_entry2he: no good records found (%d) for %.*s (%d)\n",
2429 rr_no, e->name_len, e->name, e->type);
2430 return 0; /* no good record found */
2433 p_addr[i]=0; /* mark the end of the addresses */
2434 p_aliases[0]=0; /* no aliases */
2435 memcpy(hostname, e->name, e->name_len);
2436 hostname[e->name_len]=0;
2440 he.h_addr_list=p_addr;
2441 he.h_aliases=p_aliases;
2449 /* gethostbyname compatibility: performs an a_lookup and returns a pointer
2450 * to a statical internal hostent structure
2451 * returns 0 on success, <0 on error (see the error codes)
2453 inline static struct hostent* dns_a_get_he(str* name)
2455 struct dns_hash_entry* e;
2460 if ((ip=str2ip(name))!=0){
2461 return ip_addr2he(name, ip);
2463 if ((e=dns_get_entry(name, T_A))==0)
2473 /* gethostbyname compatibility: performs an aaaa_lookup and returns a pointer
2474 * to a statical internal hostent structure
2475 * returns 0 on success, <0 on error (see the error codes)
2477 inline static struct hostent* dns_aaaa_get_he(str* name)
2479 struct dns_hash_entry* e;
2484 if ((ip=str2ip6(name))!=0){
2485 return ip_addr2he(name, ip);
2487 if ((e=dns_get_entry(name, T_AAAA))==0)
2498 /* returns 0 on success, -1 on error (rr type does not contain an ip) */
2499 inline static int dns_rr2ip(int type, struct dns_rr* rr, struct ip_addr* ip)
2505 memcpy(ip->u.addr, ((struct a_rdata*)rr->rdata)->ip, 4);
2512 memcpy(ip->u.addr, ((struct aaaa_rdata*)rr->rdata)->ip6, 16);
2514 #else /* USE_IPV6 */
2515 LOG(L_ERR, "ERROR: dns_rr2ip: IPv6 dns rr, but IPv6 support"
2516 "disabled at compile time (recompile with "
2518 #endif /*USE_IPV6 */
2526 /* gethostbyname compatibility:
2527 * performs an a or aaaa dns lookup, returns 0 on error and a pointer to a
2528 * static hostent structure on success
2529 * flags: - none set: tries first an a_lookup and if it fails an aaaa_lookup
2530 * - DNS_IPV6_FIRST: tries first an aaaa_lookup and then an a_lookup
2531 * - DNS_IPV4_ONLY: tries only an a_lookup
2532 * - DNS_IPV6_ONLY: tries only an aaaa_lookup
2534 struct hostent* dns_get_he(str* name, int flags)
2539 if ((flags&(DNS_IPV6_FIRST|DNS_IPV6_ONLY))){
2540 he=dns_aaaa_get_he(name);
2543 he=dns_a_get_he(name);
2546 if (flags&DNS_IPV6_FIRST){
2547 he=dns_a_get_he(name);
2548 }else if (!(flags&(DNS_IPV6_ONLY|DNS_IPV4_ONLY))){
2549 he=dns_aaaa_get_he(name);
2552 #else /* USE_IPV6 */
2553 return dns_a_get_he(name);
2554 #endif /* USE_IPV6 */
2559 /* sip_resolvehost helper: gets the first good hostent/port combination
2560 * returns 0 on error, pointer to static hostent structure on success
2562 struct hostent* dns_srv_get_he(str* name, unsigned short* port, int flags)
2564 struct dns_hash_entry* e;
2569 unsigned char rr_no;
2573 now=get_ticks_raw();
2574 if ((e=dns_get_entry(name, T_SRV))==0)
2576 /* look inside the RRs for a good one (not expired or marked bad) */
2578 while( (rr=dns_entry_get_rr(e, &rr_no, now))!=0){
2579 /* everything is ok now, we can try to resolve the ip */
2580 rr_name.s=((struct srv_rdata*)rr->rdata)->name;
2581 rr_name.len=((struct srv_rdata*)rr->rdata)->name_len;
2582 if ((he=dns_get_he(&rr_name, flags))!=0){
2583 /* success, at least one good ip found */
2584 *port=((struct srv_rdata*)rr->rdata)->port;
2587 rr_no++; /* try from the next record, the current one was not good */
2589 /* if we reach this point => error, we couldn't find any good rr */
2591 if (e) dns_hash_put(e);
2598 struct hostent* dns_resolvehost(char* name)
2601 struct hostent* ret;
2602 if ((cfg_get(core, core_cfg, use_dns_cache)==0) || (dns_hash==0)){ /* not init yet */
2603 ret = _resolvehost(name);
2605 /* increment dns error counter */
2606 counter_inc(dns_cnts_h.failed_dns_req);
2611 host.len=strlen(name);
2612 return dns_get_he(&host, dns_flags);
2619 /* resolves a host name trying NAPTR, SRV, A & AAAA lookups, for details
2620 * see dns_sip_resolve()
2621 * FIXME: this version will return only the first ip
2622 * returns: hostent struct & *port filled with the port from the SRV record;
2625 struct hostent* dns_sip_resolvehost(str* name, unsigned short* port,
2628 struct dns_srv_handle h;
2632 if ((cfg_get(core, core_cfg, use_dns_cache==0)) || (dns_hash==0)){
2633 /* not init or off => use normal, non-cached version */
2634 return _sip_resolvehost(name, port, proto);
2636 dns_srv_handle_init(&h);
2637 ret=dns_sip_resolve(&h, name, &ip, port, proto, dns_flags);
2638 dns_srv_handle_put(&h);
2640 return ip_addr2he(name, &ip);
2647 /* resolves a host name trying SRV lookup if *port==0 or normal A/AAAA lookup
2649 * when performing SRV lookup (*port==0) it will use proto to look for
2650 * tcp or udp hosts, otherwise proto is unused; if proto==0 => no SRV lookup
2651 * returns: hostent struct & *port filled with the port from the SRV record;
2654 struct hostent* dns_srv_sip_resolvehost(str* name, unsigned short* port,
2659 static char tmp[MAX_DNS_NAME]; /* tmp. buff. for SRV lookups */
2664 if ((cfg_get(core, core_cfg, use_dns_cache)==0) || (dns_hash==0)){
2665 /* not init or off => use normal, non-cached version */
2666 return _sip_resolvehost(name, port, proto);
2669 if (proto){ /* makes sure we have a protocol set*/
2671 *proto=srv_proto=PROTO_UDP; /* default */
2675 srv_proto=PROTO_UDP;
2677 /* try SRV if no port specified (draft-ietf-sip-srv-06) */
2678 if ((port)&&(*port==0)){
2679 *port=(srv_proto==PROTO_TLS)?SIPS_PORT:SIP_PORT; /* just in case we
2680 don't find another */
2681 if ((name->len+SRV_MAX_PREFIX_LEN+1)>MAX_DNS_NAME){
2682 LOG(L_WARN, "WARNING: dns_sip_resolvehost: domain name too long"
2683 " (%d), unable to perform SRV lookup\n", name->len);
2685 /* check if it's an ip address */
2686 if ( ((ip=str2ip(name))!=0)
2688 || ((ip=str2ip6(name))!=0)
2691 /* we are lucky, this is an ip address */
2692 return ip_addr2he(name,ip);
2696 case PROTO_NONE: /* no proto specified, use udp */
2701 memcpy(tmp, SRV_UDP_PREFIX, SRV_UDP_PREFIX_LEN);
2702 memcpy(tmp+SRV_UDP_PREFIX_LEN, name->s, name->len);
2703 tmp[SRV_UDP_PREFIX_LEN + name->len] = '\0';
2704 len=SRV_UDP_PREFIX_LEN + name->len;
2707 memcpy(tmp, SRV_TCP_PREFIX, SRV_TCP_PREFIX_LEN);
2708 memcpy(tmp+SRV_TCP_PREFIX_LEN, name->s, name->len);
2709 tmp[SRV_TCP_PREFIX_LEN + name->len] = '\0';
2710 len=SRV_TCP_PREFIX_LEN + name->len;
2713 memcpy(tmp, SRV_TLS_PREFIX, SRV_TLS_PREFIX_LEN);
2714 memcpy(tmp+SRV_TLS_PREFIX_LEN, name->s, name->len);
2715 tmp[SRV_TLS_PREFIX_LEN + name->len] = '\0';
2716 len=SRV_TLS_PREFIX_LEN + name->len;
2719 memcpy(tmp, SRV_SCTP_PREFIX, SRV_SCTP_PREFIX_LEN);
2720 memcpy(tmp+SRV_SCTP_PREFIX_LEN, name->s, name->len);
2721 tmp[SRV_SCTP_PREFIX_LEN + name->len] = '\0';
2722 len=SRV_SCTP_PREFIX_LEN + name->len;
2725 LOG(L_CRIT, "BUG: sip_resolvehost: unknown proto %d\n",
2732 if ((he=dns_srv_get_he(&srv_name, port, dns_flags))!=0)
2737 if (name->len >= MAX_DNS_NAME) {
2738 LOG(L_ERR, "dns_sip_resolvehost: domain name too long\n");
2741 he=dns_get_he(name, dns_flags);
2748 /* iterates over a naptr rr list, returning each time a "good" naptr record
2749 * is found.( srv type, no regex and a supported protocol)
2751 * naptr_head - naptr dns_rr list head
2752 * tried - bitmap used to keep track of the already tried records
2753 * (no more then sizeof(tried)*8 valid records are
2755 * srv_name - if succesfull, it will be set to the selected record
2756 * srv name (naptr repl.)
2757 * proto - if succesfull it will be set to the selected record
2759 * returns 0 if no more records found or a pointer to the selected record
2760 * and sets protocol and srv_name
2761 * WARNING: when calling first time make sure you run first
2762 * naptr_iterate_init(&tried)
2764 struct naptr_rdata* dns_naptr_sip_iterate(struct dns_rr* naptr_head,
2766 str* srv_name, char* proto)
2770 struct naptr_rdata* naptr;
2771 struct naptr_rdata* naptr_saved;
2776 naptr_proto=PROTO_NONE;
2780 for(l=naptr_head; l && (i<MAX_NAPTR_RRS); l=l->next){
2781 naptr=(struct naptr_rdata*) l->rdata;
2783 LOG(L_CRIT, "naptr_iterate: BUG: null rdata\n");
2786 /* check if valid and get proto */
2787 if ((naptr_proto=naptr_get_sip_proto(naptr))<=0) continue;
2788 if (*tried& (1<<i)){
2790 continue; /* already tried */
2792 #ifdef DNS_CACHE_DEBUG
2793 DBG("naptr_iterate: found a valid sip NAPTR rr %.*s,"
2794 " proto %d\n", naptr->repl_len, naptr->repl,
2797 if ((naptr_proto_supported(naptr_proto))){
2798 if (naptr_choose(&naptr_saved, &saved_proto,
2799 naptr, naptr_proto))
2805 /* found something */
2806 #ifdef DNS_CACHE_DEBUG
2807 DBG("naptr_iterate: choosed NAPTR rr %.*s, proto %d"
2808 " tried: 0x%x\n", naptr_saved->repl_len,
2809 naptr_saved->repl, (int)saved_proto, *tried);
2813 srv_name->s=naptr_saved->repl;
2814 srv_name->len=naptr_saved->repl_len;
2823 /* resolves a host name trying NAPTR lookup if *proto==0 and *port==0, SRV
2824 * lookup if *port==0 or normal A/AAAA lookup
2826 * when performing SRV lookup (*port==0) it will use proto to look for
2827 * tcp or udp hosts; if proto==0 => no SRV lookup
2828 * returns: hostent struct & *port filled with the port from the SRV record;
2831 struct hostent* dns_naptr_sip_resolvehost(str* name, unsigned short* port,
2835 struct ip_addr* tmp_ip;
2836 naptr_bmp_t tried_bmp;
2837 struct dns_hash_entry* e;
2842 if (dns_hash==0){ /* not init => use normal, non-cached version */
2843 LOG(L_WARN, "WARNING: dns_sip_resolvehost: called before dns cache"
2844 " initialization\n");
2845 return _sip_resolvehost(name, port, proto);
2847 if (proto && port && (*proto==0) && (*port==0)){
2848 *proto=PROTO_UDP; /* just in case we don't find another */
2849 /* check if it's an ip address */
2850 if ( ((tmp_ip=str2ip(name))!=0)
2852 || ((tmp_ip=str2ip6(name))!=0)
2855 /* we are lucky, this is an ip address */
2857 if (((dns_flags&DNS_IPV4_ONLY) && (tmp_ip->af==AF_INET6))||
2858 ((dns_flags&DNS_IPV6_ONLY) && (tmp_ip->af==AF_INET))){
2863 return ip_addr2he(name, tmp_ip);
2865 /* do naptr lookup */
2866 if ((e=dns_get_entry(name, T_NAPTR))==0)
2867 goto naptr_not_found;
2868 naptr_iterate_init(&tried_bmp);
2869 while(dns_naptr_sip_iterate(e->rr_lst, &tried_bmp,
2870 &srv_name, &n_proto)){
2871 if ((he=dns_srv_get_he(&srv_name, port, dns_flags))!=0){
2872 #ifdef DNS_CACHE_DEBUG
2873 DBG("dns_naptr_sip_resolvehost(%.*s, %d, %d) srv, ret=%p\n",
2874 name->len, name->s, (int)*port, (int)*proto, he);
2881 /* no acceptable naptr record found, fallback to srv */
2885 return dns_srv_sip_resolvehost(name, port, proto);
2887 #endif /* USE_NAPTR */
2891 /* resolves a host name trying NAPTR lookup if *proto==0 and *port==0, SRV
2892 * lookup if *port==0 or normal A/AAAA lookup
2894 * when performing SRV lookup (*port==0) it will use proto to look for
2895 * tcp or udp hosts; if proto==0 => no SRV lookup
2896 * returns: hostent struct & *port filled with the port from the SRV record;
2899 struct hostent* dns_sip_resolvehost(str* name, unsigned short* port,
2903 if (dns_flags&DNS_TRY_NAPTR)
2904 return dns_naptr_sip_resolvehost(name, port, proto);
2906 return dns_srv_sip_resolvehost(name, port, proto);
2911 /* performs an a lookup, fills the dns_entry pointer and the ip addr.
2912 * (with the first good ip). if *e ==0 does the a lookup, and changes it
2913 * to the result, if not it uses the current value and tries to use
2914 * the rr_no record from it.
2915 * params: e - must contain the "in-use" dns_hash_entry pointer (from
2916 * a previous call) or *e==0 (for the first call)
2917 * name - host name for which we do the lookup (required only
2919 * ip - will be filled with the first good resolved ip started
2921 * rr_no - record number to start searching for a good ip from
2922 * (e.g. value from previous call + 1), filled on return
2923 * with the number of the record corresponding to the
2925 * returns 0 on success, <0 on error (see the error codes),
2926 * fills e, ip and rr_no
2927 * On end of records (when used to iterate on all the ips) it
2928 * will return E_DNS_EOR (you should not log an error for this
2929 * value, is just a signal that the address list end has been reached)
2930 * Note: either e or name must be different from 0 (name.s !=0 also)
2931 * WARNING: dns_hash_put(*e) must be called when you don't need
2932 * the entry anymore and *e!=0 (failling to do so => mem. leak)
2935 * ret=dns_a_get_ip(&dns_entry, name, &ip, &rr_no); -- get the first rr.
2938 * while((ret>=0) && dns_entry)
2939 * dns_a_get_ip(&dns_entry, name, &ip, &rr_no); -- get the next rr
2940 * if (ret!=-E_DNS_EOR) ERROR(....);
2942 * dns_hash_put(dns_entry); -- finished with the entry
2944 inline static int dns_a_resolve( struct dns_hash_entry** e,
2945 unsigned char* rr_no,
2952 struct ip_addr* tmp;
2956 if (*e==0){ /* do lookup */
2957 /* if ip don't set *e */
2958 if ((tmp=str2ip(name))!=0){
2963 if ((*e=dns_get_entry(name, T_A))==0)
2967 ret=-E_DNS_BAD_IP_ENTRY;
2969 now=get_ticks_raw();
2970 /* if the entry has already expired use the time at the end of lifetime */
2971 if (unlikely((s_ticks_t)(now-(*e)->expire)>=0)) now=(*e)->expire-1;
2972 rr=dns_entry_get_rr(*e, rr_no, now);
2974 /* everything is ok now, we can try to "convert" the ip */
2975 dns_rr2ip((*e)->type, rr, ip);
2981 DBG("dns_a_resovle(%.*s, %d) returning %d\n",
2982 name->len, name->s, *rr_no, ret);
2988 /* lookup, fills the dns_entry pointer and the ip addr.
2989 * (with the first good ip). if *e ==0 does the a lookup, and changes it
2990 * to the result, if not it uses the current value and tries to use
2991 * Same as dns_a_resolve but for aaaa records (see above).
2993 inline static int dns_aaaa_resolve( struct dns_hash_entry** e,
2994 unsigned char* rr_no,
3001 struct ip_addr* tmp;
3005 if (*e==0){ /* do lookup */
3006 /* if ip don't set *e */
3007 if ((tmp=str2ip6(name))!=0){
3012 if ((*e=dns_get_entry(name, T_AAAA))==0)
3016 ret=-E_DNS_BAD_IP_ENTRY;
3018 now=get_ticks_raw();
3019 /* if the entry has already expired use the time at the end of lifetime */
3020 if (unlikely((s_ticks_t)(now-(*e)->expire)>=0)) now=(*e)->expire-1;
3021 rr=dns_entry_get_rr(*e, rr_no, now);
3023 /* everything is ok now, we can try to "convert" the ip */
3024 dns_rr2ip((*e)->type, rr, ip);
3027 ret=-E_DNS_EOR; /* no more records */
3032 #endif /* USE_IPV6 */
3036 /* performs an a or aaaa dns lookup, returns <0 on error (see the
3037 * dns error codes) and 0 on success
3038 * flags: - none set: tries first an a_lookup and if it fails an aaaa_lookup
3039 * - DNS_IPV6_FIRST: tries first an aaaa_lookup and then an a_lookup
3040 * - DNS_IPV4_ONLY: tries only an a_lookup
3041 * - DNS_IPV6_ONLY: tries only an aaaa_lookup
3042 * see dns_a_resolve() for the rest of the params., examples a.s.o
3043 * WARNING: don't forget dns_hash_put(*e) when e is not needed anymore
3045 inline static int dns_ip_resolve( struct dns_hash_entry** e,
3046 unsigned char* rr_no,
3053 struct dns_hash_entry* orig;
3056 if (*e==0){ /* first call */
3058 if ((flags&(DNS_IPV6_FIRST|DNS_IPV6_ONLY))){
3059 ret=dns_aaaa_resolve(e, rr_no, name, ip);
3060 if (ret>=0) return ret;
3062 ret=dns_a_resolve(e, rr_no, name, ip);
3063 if (ret>=0) return ret;
3065 if (flags&DNS_IPV6_FIRST){
3066 ret=dns_a_resolve(e, rr_no, name, ip);
3067 }else if (!(flags&(DNS_IPV6_ONLY|DNS_IPV4_ONLY))){
3068 ret=dns_aaaa_resolve(e, rr_no, name, ip);
3070 #else /* USE_IPV6 */
3071 ret=dns_a_resolve(e, rr_no, name, ip);
3072 #endif /* USE_IPV6 */
3073 }else if ((*e)->type==T_A){
3074 /* continue A resolving */
3075 /* retrieve host name from the hash entry (ignore name which might
3076 be null when continuing a srv lookup) */
3078 host.len=(*e)->name_len;
3079 ret=dns_a_resolve(e, rr_no, &host, ip);
3081 if (ret>=0) return ret;
3082 if (!(flags&(DNS_IPV6_ONLY|DNS_IPV6_FIRST|DNS_IPV4_ONLY))){
3083 /* not found, try with AAAA */
3087 ret=dns_aaaa_resolve(e, rr_no, &host, ip);
3088 /* delay original record release until we're finished with host*/
3091 #endif /* USE_IPV6 */
3092 }else if ((*e)->type==T_AAAA){
3093 /* retrieve host name from the hash entry (ignore name which might
3094 be null when continuing a srv lookup) */
3096 host.len=(*e)->name_len;
3098 /* continue AAAA resolving */
3099 ret=dns_aaaa_resolve(e, rr_no, &host, ip);
3100 if (ret>=0) return ret;
3101 if ((flags&DNS_IPV6_FIRST) && !(flags&DNS_IPV6_ONLY)){
3102 /* not found, try with A */
3106 ret=dns_a_resolve(e, rr_no, &host, ip);
3107 /* delay original record release until we're finished with host*/
3110 #else /* USE_IPV6 */
3111 /* ipv6 disabled, try with A */
3115 ret=dns_a_resolve(e, rr_no, &host, ip);
3116 /* delay original record release until we're finished with host*/
3118 #endif /* USE_IPV6 */
3120 LOG(L_CRIT, "BUG: dns_ip_resolve: invalid record type %d\n",
3128 /* gets the first srv record starting at rr_no
3129 * Next call will return the next record a.s.o.
3130 * (similar to dns_a_resolve but for srv, sets host, port and automatically
3131 * switches to the next record in the future)
3133 * if DNS_SRV_LB and tried!=NULL will do random weight based selection
3134 * for choosing between SRV RRs with the same priority (as described in
3136 * If tried==NULL or DNS_SRV_LB is not defined => always returns next
3137 * record in the priority order and for records with the same priority
3138 * the record with the higher weight (from the remaining ones)
3140 inline static int dns_srv_resolve_nxt(struct dns_hash_entry** e,
3144 unsigned char* rr_no,
3145 str* name, str* host, unsigned short* port)
3154 if ((*e=dns_get_entry(name, T_SRV))==0)
3160 srv_reset_tried(tried);
3162 ret=-E_DNS_BAD_SRV_ENTRY;
3164 now=get_ticks_raw();
3165 /* if the entry has already expired use the time at the end of lifetime */
3166 if (unlikely((s_ticks_t)(now-(*e)->expire)>=0)) now=(*e)->expire-1;
3169 rr=dns_srv_get_nxt_rr(*e, tried, rr_no, now);
3173 rr=dns_entry_get_rr(*e, rr_no, now);
3174 (*rr_no)++; /* try next record next time */
3177 host->s=((struct srv_rdata*)rr->rdata)->name;
3178 host->len=((struct srv_rdata*)rr->rdata)->name_len;
3179 *port=((struct srv_rdata*)rr->rdata)->port;
3182 ret=-E_DNS_EOR; /* no more records */
3190 /* gets the first srv record starting at h->srv_no, resolve it
3191 * and get the first ip address (starting at h->ip_no)
3192 * (similar to dns_a_resolve but for srv, sets host, port)
3193 * WARNING: don't forget to init h prior to calling this function the first
3194 * time and dns_srv_handle_put(h), even if error is returned
3196 inline static int dns_srv_resolve_ip(struct dns_srv_handle* h,
3197 str* name, struct ip_addr* ip, unsigned short* port,
3208 if ((ret=dns_srv_resolve_nxt(&h->srv,
3209 (flags & DNS_SRV_RR_LB)?&h->srv_tried_rrs:0,
3211 name, &host, port))<0)
3214 if ((ret=dns_srv_resolve_nxt(&h->srv, &h->srv_no,
3215 name, &host, port))<0)
3218 h->port=*port; /* store new port */
3220 *port=h->port; /* return the stored port */
3222 if ((ret=dns_ip_resolve(&h->a, &h->ip_no, &host, ip, flags))<0){
3223 /* couldn't find any good ip for this record, try the next one */
3229 /* this was an ip, try the next srv record in the future */
3233 #ifdef DNS_CACHE_DEBUG
3234 DBG("dns_srv_resolve_ip(\"%.*s\", %d, %d), ret=%d, ip=%s\n",
3235 name->len, name->s, h->srv_no, h->ip_no, ret,
3236 ip?ZSW(ip_addr2a(ip)):"");
3243 /* resolves a host name trying SRV lookup if *port==0 or normal A/AAAA lookup
3245 * when performing SRV lookup (*port==0) it will use proto to look for
3246 * tcp or udp hosts, otherwise proto is unused; if proto==0 => no SRV lookup
3247 * h must be initialized prior to calling this function and can be used to
3248 * get the subsequent ips
3249 * returns: <0 on error
3250 * 0 on success and it fills *ip, *port, dns_sip_resolve_h
3251 * WARNING: when finished, dns_sip_resolve_put(h) must be called!
3253 inline static int dns_srv_sip_resolve(struct dns_srv_handle* h, str* name,
3254 struct ip_addr* ip, unsigned short* port, char* proto,
3257 static char tmp[MAX_DNS_NAME]; /* tmp. buff. for SRV lookups */
3260 struct ip_addr* tmp_ip;
3265 if (dns_hash==0){ /* not init => use normal, non-cached version */
3266 LOG(L_WARN, "WARNING: dns_sip_resolve: called before dns cache"
3267 " initialization\n");
3269 he=_sip_resolvehost(name, port, proto);
3271 hostent2ip_addr(ip, he, 0);
3274 return -E_DNS_NO_SRV;
3277 if ((h->srv==0) && (h->a==0)){ /* first call */
3278 if (proto){ /* makes sure we have a protocol set*/
3280 *proto=srv_proto=PROTO_UDP; /* default */
3284 srv_proto=PROTO_UDP;
3286 h->port=(srv_proto==PROTO_TLS)?SIPS_PORT:SIP_PORT; /* just in case we
3287 don't find another */
3288 h->proto=srv_proto; /* store initial protocol */
3291 /* try SRV if initial call & no port specified
3292 * (draft-ietf-sip-srv-06) */
3293 if ((name->len+SRV_MAX_PREFIX_LEN+1)>MAX_DNS_NAME){
3294 LOG(L_WARN, "WARNING: dns_sip_resolvehost: domain name too"
3295 " long (%d), unable to perform SRV lookup\n",
3298 /* check if it's an ip address */
3299 if ( ((tmp_ip=str2ip(name))!=0)
3301 || ((tmp_ip=str2ip6(name))!=0)
3304 /* we are lucky, this is an ip address */
3306 if (((flags&DNS_IPV4_ONLY) && (tmp_ip->af==AF_INET6))||
3307 ((flags&DNS_IPV6_ONLY) && (tmp_ip->af==AF_INET))){
3308 return -E_DNS_AF_MISMATCH;
3313 /* proto already set */
3318 case PROTO_NONE: /* no proto specified, use udp */
3323 memcpy(tmp, SRV_UDP_PREFIX, SRV_UDP_PREFIX_LEN);
3324 memcpy(tmp+SRV_UDP_PREFIX_LEN, name->s, name->len);
3325 tmp[SRV_UDP_PREFIX_LEN + name->len] = '\0';
3326 len=SRV_UDP_PREFIX_LEN + name->len;