d93330018715295741257365240dddbe6be29c82
[kamailio] / src / core / dns_cache.c
1 /*
2  * resolver related functions
3  *
4  * Copyright (C) 2006 iptelorg GmbH
5  *
6  * This file is part of Kamailio, a free SIP server.
7  *
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
12  *
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.
17  *
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
21  */
22
23 /*!
24  * \file
25  * \brief Kamailio core :: DNS cache handling
26  * \ingroup core
27  * Module: \ref core
28  */
29
30
31 #ifdef USE_DNS_CACHE
32
33 #ifdef DNS_SRV_LB
34 #include <stdlib.h> /* FIXME: rand() */
35 #endif
36 #include <string.h>
37
38 #include "globals.h"
39 #include "cfg_core.h"
40 #include "dns_cache.h"
41 #include "dns_wrappers.h"
42 #include "compiler_opt.h"
43 #include "mem/shm_mem.h"
44 #include "hashes.h"
45 #include "clist.h"
46 #include "locking.h"
47 #include "atomic_ops.h"
48 #include "ut.h"
49 #include "timer.h"
50 #include "timer_ticks.h"
51 #include "error.h"
52 #include "rpc.h"
53 #include "rand/fastrand.h"
54 #ifdef USE_DNS_CACHE_STATS
55 #include "pt.h"
56 #endif
57
58
59
60 #define DNS_CACHE_DEBUG /* extra sanity checks and debugging */
61
62
63 #ifndef MAX
64         #define MAX(a,b) ( ((a)>(b))?(a):(b))
65 #endif
66
67 #define MAX_DNS_RECORDS 255  /* maximum dns records number  received in a
68                                                            dns answer*/
69
70 #define DNS_HASH_SIZE   1024 /* must be <= 65535 */
71 #define DEFAULT_DNS_TIMER_INTERVAL 120  /* 2 min. */
72 #define DNS_HE_MAX_ADDR 10  /* maxium addresses returne in a hostent struct */
73 #define MAX_CNAME_CHAIN  10
74 #define SPACE_FORMAT "    " /* format of view output */
75 #define DNS_SRV_ZERO_W_CHANCE   1000 /* one in a 1000*weight_sum chance for
76                                                                                 selecting a 0-weight record */
77
78 int dns_cache_init=1;   /* if 0, the DNS cache is not initialized at startup */
79 static gen_lock_t* dns_hash_lock=0;
80 static volatile unsigned int *dns_cache_mem_used=0; /* current mem. use */
81 unsigned int dns_timer_interval=DEFAULT_DNS_TIMER_INTERVAL; /* in s */
82 int dns_flags=0; /* default flags used for the  dns_*resolvehost
83                     (compatibility wrappers) */
84
85 #ifdef USE_DNS_CACHE_STATS
86 struct t_dns_cache_stats* dns_cache_stats=0;
87 #endif
88
89 #define LOCK_DNS_HASH()         lock_get(dns_hash_lock)
90 #define UNLOCK_DNS_HASH()       lock_release(dns_hash_lock)
91
92 #define FIX_TTL(t) \
93         (((t)<cfg_get(core, core_cfg, dns_cache_min_ttl))? \
94                 cfg_get(core, core_cfg, dns_cache_min_ttl): \
95                 (((t)>cfg_get(core, core_cfg, dns_cache_max_ttl))? \
96                         cfg_get(core, core_cfg, dns_cache_max_ttl): \
97                         (t)))
98
99
100 struct dns_hash_head{
101         struct dns_hash_entry* next;
102         struct dns_hash_entry* prev;
103 };
104
105 #ifdef DNS_LU_LST
106 struct dns_lu_lst* dns_last_used_lst=0;
107 #endif
108
109 static struct dns_hash_head* dns_hash=0;
110
111
112 static struct timer_ln* dns_timer_h=0;
113
114 #ifdef DNS_WATCHDOG_SUPPORT
115 static atomic_t *dns_servers_up = NULL;
116 #endif
117
118
119
120 static const char* dns_str_errors[]={
121         "no error",
122         "no more records", /* not an error, but and end condition */
123         "unknown error",
124         "internal error",
125         "bad SRV entry",
126         "unresolvable SRV request",
127         "bad A or AAAA entry",
128         "unresolvable A or AAAA request",
129         "invalid ip in A or AAAA record",
130         "blacklisted ip",
131         "name too long ", /* try again with a shorter name */
132         "ip AF mismatch", /* address family mismatch */
133         "unresolvable NAPTR request",
134         "bug - critical error"
135 };
136
137
138
139 /* param: err (negative error number) */
140 const char* dns_strerror(int err)
141 {
142         err=-err;
143         if ((err>=0) && (err<sizeof(dns_str_errors)/sizeof(char*)))
144                 return dns_str_errors[err];
145         return "bug -- bad error number";
146 }
147
148
149
150 /* "internal" only, don't use unless you really know waht you're doing */
151 inline static void dns_destroy_entry(struct dns_hash_entry* e)
152 {
153 #ifdef DNS_CACHE_DEBUG
154         memset(e, 0, e->total_size);
155 #endif
156         shm_free(e); /* nice having it in one block isn't it? :-) */
157 }
158
159
160 /* "internal" only, same as above, asumes shm_lock() held (tm optimization) */
161 inline static void dns_destroy_entry_shm_unsafe(struct dns_hash_entry* e)
162 {
163 #ifdef DNS_CACHE_DEBUG
164         memset(e, 0, e->total_size);
165 #endif
166         shm_free_unsafe(e); /* nice having it in one block isn't it? :-) */
167 }
168
169
170
171 /* dec. the internal refcnt and if 0 deletes the entry */
172 void dns_hash_put(struct dns_hash_entry* e)
173 {
174         if(e && atomic_dec_and_test(&e->refcnt)){
175                 /* atomic_sub_long(dns_cache_total_used, e->total_size); */
176                 dns_destroy_entry(e);
177         }
178 }
179
180
181
182 /* same as above but uses dns_destroy_unsafe (assumes shm_lock held -- tm
183  *  optimization) */
184 void dns_hash_put_shm_unsafe(struct dns_hash_entry* e)
185 {
186         if(e && atomic_dec_and_test(&e->refcnt)){
187                 /* atomic_sub_long(dns_cache_total_used, e->total_size); */
188                 dns_destroy_entry_shm_unsafe(e);
189         }
190 }
191
192
193 inline static int dns_cache_clean(unsigned int no, int expired_only);
194 inline static int dns_cache_free_mem(unsigned int target, int expired_only);
195
196 static ticks_t dns_timer(ticks_t ticks, struct timer_ln* tl, void* data)
197 {
198 #ifdef DNS_WATCHDOG_SUPPORT
199         /* do not clean the hash table if the servers are down */
200         if (atomic_get(dns_servers_up) == 0)
201                 return (ticks_t)(-1);
202 #endif
203         if (*dns_cache_mem_used>12*(cfg_get(core, core_cfg, dns_cache_max_mem)/16)){ /* ~ 75% used */
204                 dns_cache_free_mem(cfg_get(core, core_cfg, dns_cache_max_mem)/2, 1);
205         }else{
206                 dns_cache_clean(-1, 1); /* all the table, only expired entries */
207                 /* TODO: better strategy? */
208         }
209         return (ticks_t)(-1);
210 }
211
212
213
214 void destroy_dns_cache()
215 {
216         if (dns_timer_h){
217                 timer_del(dns_timer_h);
218                 timer_free(dns_timer_h);
219                 dns_timer_h=0;
220         }
221 #ifdef DNS_WATCHDOG_SUPPORT
222         if (dns_servers_up){
223                 shm_free(dns_servers_up);
224                 dns_servers_up=0;
225         }
226 #endif
227         if (dns_hash_lock){
228                 lock_destroy(dns_hash_lock);
229                 lock_dealloc(dns_hash_lock);
230                 dns_hash_lock=0;
231         }
232         if (dns_hash){
233                 shm_free(dns_hash);
234                 dns_hash=0;
235         }
236 #ifdef DNS_LU_LST
237         if (dns_last_used_lst){
238                 shm_free(dns_last_used_lst);
239                 dns_last_used_lst=0;
240         }
241 #endif
242 #ifdef USE_DNS_CACHE_STATS
243         if (dns_cache_stats)
244                 shm_free(dns_cache_stats);
245 #endif
246         if (dns_cache_mem_used){
247                 shm_free((void*)dns_cache_mem_used);
248                 dns_cache_mem_used=0;
249         }
250 }
251
252 /* set the value of dns_flags */
253 void fix_dns_flags(str *gname, str *name)
254 {
255         /* restore the original value of dns_cache_flags first
256          * (DNS_IPV4_ONLY may have been set only because dns_try_ipv6
257          * was disabled, and the flag must be cleared when
258          * dns_try_ipv6 is enabled) (Miklos)
259          */
260         dns_flags = cfg_get(core, core_cfg, dns_cache_flags) & 7;
261
262         if (cfg_get(core, core_cfg, dns_try_ipv6)==0){
263                 dns_flags|=DNS_IPV4_ONLY;
264         }
265         if (dns_flags & DNS_IPV4_ONLY){
266                 dns_flags&=~(DNS_IPV6_ONLY|DNS_IPV6_FIRST);
267         }
268         if (cfg_get(core, core_cfg, dns_srv_lb)){
269 #ifdef DNS_SRV_LB
270                 dns_flags|=DNS_SRV_RR_LB;
271 #else
272                 LM_WARN("SRV loadbalaning is set, but"
273                                         " support for it is not compiled -- ignoring\n");
274 #endif
275         }
276         if (cfg_get(core, core_cfg, dns_try_naptr)) {
277 #ifndef USE_NAPTR
278         LM_WARN("NAPTR support is enabled, but"
279                                 " support for it is not compiled -- ignoring\n");
280 #endif
281                 dns_flags|=DNS_TRY_NAPTR;
282         }
283 }
284
285 /* fixup function for use_dns_failover
286  * verifies that use_dns_cache is set to 1
287  */
288 int use_dns_failover_fixup(void *handle, str *gname, str *name, void **val)
289 {
290         if ((int)(long)(*val) && !cfg_get(core, handle, use_dns_cache)) {
291                 LM_ERR("DNS cache is turned off, failover cannot be enabled. "
292                         "(set use_dns_cache to 1)\n");
293                 return -1;
294         }
295         return 0;
296 }
297
298 /* fixup function for use_dns_cache
299  * verifies that dns_cache_init is set to 1
300  */
301 int use_dns_cache_fixup(void *handle, str *gname, str *name, void **val)
302 {
303         if ((int)(long)(*val) && !dns_cache_init) {
304                 LM_ERR("DNS cache is turned off by dns_cache_init=0, "
305                         "it cannot be enabled runtime.\n");
306                 return -1;
307         }
308         if (((int)(long)(*val)==0) && cfg_get(core, handle, use_dns_failover)) {
309                 LM_ERR("DNS failover depends on use_dns_cache, set use_dns_failover "
310                         "to 0 before disabling the DNS cache\n");
311                 return -1;
312         }
313         return 0;
314 }
315
316 /* KByte to Byte conversion */
317 int dns_cache_max_mem_fixup(void *handle, str *gname, str *name, void **val)
318 {
319         unsigned int    u;
320
321         u = ((unsigned int)(long)(*val))<<10;
322         (*val) = (void *)(long)u;
323         return 0;
324 }
325
326 int init_dns_cache()
327 {
328         int r;
329         int ret;
330
331         if (dns_cache_init==0) {
332                 /* the DNS cache is turned off */
333                 default_core_cfg.use_dns_cache=0;
334                 default_core_cfg.use_dns_failover=0;
335                 return 0;
336         }
337
338         ret=0;
339         /* sanity check */
340         if (E_DNS_CRITICAL>=sizeof(dns_str_errors)/sizeof(char*)){
341                 LM_CRIT("bad dns error table\n");
342                 ret=E_BUG;
343                 goto error;
344         }
345         dns_cache_mem_used=shm_malloc(sizeof(*dns_cache_mem_used));
346         if (dns_cache_mem_used==0){
347                 ret=E_OUT_OF_MEM;
348                 goto error;
349         }
350
351         *dns_cache_mem_used=0;
352
353 #ifdef DNS_LU_LST
354         dns_last_used_lst=shm_malloc(sizeof(*dns_last_used_lst));
355         if (dns_last_used_lst==0){
356                 ret=E_OUT_OF_MEM;
357                 goto error;
358         }
359         clist_init(dns_last_used_lst, next, prev);
360 #endif
361         dns_hash=shm_malloc(sizeof(struct dns_hash_head)*DNS_HASH_SIZE);
362         if (dns_hash==0){
363                 ret=E_OUT_OF_MEM;
364                 goto error;
365         }
366         for (r=0; r<DNS_HASH_SIZE; r++)
367                 clist_init(&dns_hash[r], next, prev);
368
369         dns_hash_lock=lock_alloc();
370         if (dns_hash_lock==0){
371                 ret=E_OUT_OF_MEM;
372                 goto error;
373         }
374         if (lock_init(dns_hash_lock)==0){
375                 lock_dealloc(dns_hash_lock);
376                 dns_hash_lock=0;
377                 ret=-1;
378                 goto error;
379         }
380
381 #ifdef DNS_WATCHDOG_SUPPORT
382         dns_servers_up=shm_malloc(sizeof(atomic_t));
383         if (dns_servers_up==0){
384                 ret=E_OUT_OF_MEM;
385                 goto error;
386         }
387         atomic_set(dns_servers_up, 1);
388 #endif
389
390         /* fix options */
391         default_core_cfg.dns_cache_max_mem<<=10; /* Kb */ /* TODO: test with 0 */
392         if (default_core_cfg.use_dns_cache==0)
393                 default_core_cfg.use_dns_failover=0; /* cannot work w/o dns_cache support */
394         /* fix flags */
395         fix_dns_flags(NULL, NULL);
396
397         dns_timer_h=timer_alloc();
398         if (dns_timer_h==0){
399                 ret=E_OUT_OF_MEM;
400                 goto error;
401         }
402         if (dns_timer_interval){
403                 timer_init(dns_timer_h, dns_timer, 0, 0); /* "slow" timer */
404                 if (timer_add(dns_timer_h, S_TO_TICKS(dns_timer_interval))<0){
405                         LM_CRIT("failed to add the timer\n");
406                         timer_free(dns_timer_h);
407                         dns_timer_h=0;
408                         goto error;
409                 }
410         }
411
412         return 0;
413 error:
414         destroy_dns_cache();
415         return ret;
416 }
417
418 #ifdef USE_DNS_CACHE_STATS
419 int init_dns_cache_stats(int iproc_num)
420 {
421         /* do not initialize the stats array if the DNS cache will not be used */
422         if (dns_cache_init==0) return 0;
423
424         /* if it is already initialized */
425         if (dns_cache_stats)
426                 shm_free(dns_cache_stats);
427
428         dns_cache_stats=shm_malloc(sizeof(*dns_cache_stats) * iproc_num);
429         if (dns_cache_stats==0){
430                 return E_OUT_OF_MEM;
431         }
432         memset(dns_cache_stats, 0, sizeof(*dns_cache_stats) * iproc_num);
433
434         return 0;
435 }
436 #endif
437
438 /* hash function, type is not used (obsolete)
439  * params: char* s, int len, int type
440  * returns the hash value
441  */
442 #define dns_hash_no(s, len, type) \
443         (get_hash1_case_raw((s),(len)) % DNS_HASH_SIZE)
444
445
446
447 #ifdef DNS_CACHE_DEBUG
448 #define DEBUG_LU_LST
449 #ifdef DEBUG_LU_LST
450
451 #include <stdlib.h> /* abort() */
452 #define check_lu_lst(l) ((((l)->next==(l)) || ((l)->prev==(l))) && \
453                                                         ((l)!=dns_last_used_lst))
454
455 #define dbg_lu_lst(txt, l) \
456                 LM_CRIT("%s: crt(%p, %p, %p)," \
457                                         " prev(%p, %p, %p), next(%p, %p, %p)\n", txt, \
458                                         (l), (l)->next, (l)->prev, \
459                                         (l)->prev, ((l)->prev)?(l)->prev->next:NULL, \
460                                         ((l)->prev)?(l)->prev->prev:NULL, \
461                                         (l)->next, ((l)->next)?(l)->next->next:NULL, \
462                                         ((l)->next)?(l)->next->prev:NULL \
463                                 )
464
465 #define debug_lu_lst( txt, l) \
466         do{ \
467                 if ((l) && check_lu_lst((l))){  \
468                         dbg_lu_lst(txt  " crt:", (l)); \
469                         abort(); \
470                 } \
471                 if (((l)->next) && check_lu_lst((l)->next)){ \
472                         dbg_lu_lst(txt  " next:",  (l)); \
473                         abort(); \
474                 } \
475                 if (((l)->prev) && check_lu_lst((l)->prev)){ \
476                         dbg_lu_lst(txt  " prev:", (l)); \
477                         abort(); \
478                 } \
479         }while(0)
480
481 #endif
482 #endif /* DNS_CACHE_DEBUG */
483
484
485 /* must be called with the DNS_LOCK hold
486  * remove and entry from the hash, dec. its refcnt and if not referenced
487  * anymore deletes it */
488 inline static void _dns_hash_remove(struct dns_hash_entry* e)
489 {
490         clist_rm(e, next, prev);
491 #ifdef DNS_CACHE_DEBUG
492         e->next=e->prev=0;
493 #endif
494 #ifdef DNS_LU_LST
495 #ifdef DEBUG_LU_LST
496         debug_lu_lst("_dns_hash_remove: pre rm:", &e->last_used_lst);
497 #endif
498         clist_rm(&e->last_used_lst, next, prev);
499 #ifdef DEBUG_LU_LST
500         debug_lu_lst("_dns_hash_remove: post rm:", &e->last_used_lst);
501 #endif
502 #ifdef DNS_CACHE_DEBUG
503         e->last_used_lst.next=e->last_used_lst.prev=0;
504 #endif
505 #endif
506         *dns_cache_mem_used-=e->total_size;
507         dns_hash_put(e);
508 }
509
510
511
512 /* non locking  version (the dns hash must _be_ locked externally)
513  * returns 0 when not found, or the entry on success (an entry with a
514  * similar name but with a CNAME type will always match).
515  * it doesn't increase the internal refcnt
516  * returns the entry when found, 0 when not found and sets *err to !=0
517  *  on error (e.g. recursive cnames)
518  * WARNING: - internal use only
519  *          - always check if the returned entry type is CNAME */
520 inline static struct dns_hash_entry* _dns_hash_find(str* name, int type,
521                                                                                                                 int* h, int* err)
522 {
523         struct dns_hash_entry* e;
524         struct dns_hash_entry* tmp;
525         struct dns_hash_entry* ret;
526         ticks_t now;
527         int cname_chain;
528         str cname;
529 #ifdef DNS_WATCHDOG_SUPPORT
530         int servers_up;
531
532         servers_up = atomic_get(dns_servers_up);
533 #endif
534
535         cname_chain=0;
536         ret=0;
537         now=get_ticks_raw();
538         *err=0;
539 again:
540         *h=dns_hash_no(name->s, name->len, type);
541 #ifdef DNS_CACHE_DEBUG
542         LM_DBG("(%.*s(%d), %d), h=%d\n", name->len, name->s, name->len, type, *h);
543 #endif
544         clist_foreach_safe(&dns_hash[*h], e, tmp, next){
545                 if (
546 #ifdef DNS_WATCHDOG_SUPPORT
547                         /* remove expired elements only when the dns servers are up */
548                         servers_up &&
549 #endif
550                         /* automatically remove expired elements */
551                         ((e->ent_flags & DNS_FLAG_PERMANENT) == 0) &&
552                         ((s_ticks_t)(now-e->expire)>=0)
553                 ) {
554                                 _dns_hash_remove(e);
555                 }else if ((e->type==type) && (e->name_len==name->len) &&
556                         (strncasecmp(e->name, name->s, e->name_len)==0)){
557                         e->last_used=now;
558 #ifdef DNS_LU_LST
559                         /* add it at the end */
560 #ifdef DEBUG_LU_LST
561                         debug_lu_lst("_dns_hash_find: pre rm:", &e->last_used_lst);
562 #endif
563                         clist_rm(&e->last_used_lst, next, prev);
564                         clist_append(dns_last_used_lst, &e->last_used_lst, next, prev);
565 #ifdef DEBUG_LU_LST
566                         debug_lu_lst("_dns_hash_find: post append:", &e->last_used_lst);
567 #endif
568 #endif
569                         return e;
570                 }else if ((e->type==T_CNAME) &&
571                                         !((e->rr_lst==0) || (e->ent_flags & DNS_FLAG_BAD_NAME)) &&
572                                         (e->name_len==name->len) &&
573                                         (strncasecmp(e->name, name->s, e->name_len)==0)){
574                         /*if CNAME matches and CNAME is entry is not a neg. cache entry
575                           (could be produced by a specific CNAME lookup)*/
576                         e->last_used=now;
577 #ifdef DNS_LU_LST
578                         /* add it at the end */
579 #ifdef DEBUG_LU_LST
580                         debug_lu_lst("_dns_hash_find: cname: pre rm:", &e->last_used_lst);
581 #endif
582                         clist_rm(&e->last_used_lst, next, prev);
583                         clist_append(dns_last_used_lst, &e->last_used_lst, next, prev);
584 #ifdef DEBUG_LU_LST
585                         debug_lu_lst("_dns_hash_find: cname: post append:",
586                                                         &e->last_used_lst);
587 #endif
588 #endif
589                         ret=e; /* if this is an unfinished cname chain, we try to
590                                           return the last cname */
591                         /* this is a cname => retry using its value */
592                         if (cname_chain> MAX_CNAME_CHAIN){
593                                 LM_ERR("cname chain too long or recursive (\"%.*s\")\n",
594                                                 name->len, name->s);
595                                 ret=0; /* error*/
596                                 *err=-1;
597                                 break;
598                         }
599                         cname_chain++;
600                         cname.s=((struct cname_rdata*)e->rr_lst->rdata)->name;
601                         cname.len= ((struct cname_rdata*)e->rr_lst->rdata)->name_len;
602                         if(cname.s!=NULL && cname.len>0) {
603                                 name=&cname;
604                                 goto again;
605                         }
606                 }
607         }
608         return ret;
609 }
610
611
612
613 /* frees cache entries, if expired_only=0 only expired entries will be
614  * removed, else all of them
615  * it will process maximum no entries (to process all of them use -1)
616  * returns the number of deleted entries
617  * This should be called from a timer process*/
618 inline static int dns_cache_clean(unsigned int no, int expired_only)
619 {
620         struct dns_hash_entry* e;
621         ticks_t now;
622         unsigned int n;
623         unsigned int deleted;
624 #ifdef DNS_LU_LST
625         struct dns_lu_lst* l;
626         struct dns_lu_lst* tmp;
627 #else
628         struct dns_hash_entry* t;
629         unsigned int h;
630         static unsigned int start=0;
631 #endif
632
633         n=0;
634         deleted=0;
635         now=get_ticks_raw();
636         LOCK_DNS_HASH();
637 #ifdef DNS_LU_LST
638         clist_foreach_safe(dns_last_used_lst, l, tmp, next){
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))
643                 ) {
644                                 _dns_hash_remove(e);
645                                 deleted++;
646                 }
647                 n++;
648                 if (n>=no) break;
649         }
650 #else
651         for(h=start; h!=(start+DNS_HASH_SIZE); h++){
652                 clist_foreach_safe(&dns_hash[h%DNS_HASH_SIZE], e, t, next){
653                         if (((e->ent_flags & DNS_FLAG_PERMANENT) == 0)
654                                 && ((s_ticks_t)(now-e->expire)>=0)
655                         ) {
656                                 _dns_hash_remove(e);
657                                 deleted++;
658                         }
659                         n++;
660                         if (n>=no) goto skip;
661                 }
662         }
663         /* not fair, but faster then random() */
664         if (!expired_only){
665                 for(h=start; h!=(start+DNS_HASH_SIZE); h++){
666                         clist_foreach_safe(&dns_hash[h%DNS_HASH_SIZE], e, t, next){
667                                 if ((e->ent_flags & DNS_FLAG_PERMANENT) == 0) {
668                                         _dns_hash_remove(e);
669                                         deleted++;
670                                 }
671                                 n++;
672                                 if (n>=no) goto skip;
673                         }
674                 }
675         }
676 skip:
677         start=h;
678 #endif
679         UNLOCK_DNS_HASH();
680         return deleted;
681 }
682
683
684
685 /* frees cache entries, if expired_only=0 only expired entries will be
686  * removed, else all of them
687  * it will stop when the dns cache used memory reaches target (to process all
688  * of them use 0)
689  * returns the number of deleted entries */
690 inline static int dns_cache_free_mem(unsigned int target, int expired_only)
691 {
692         struct dns_hash_entry* e;
693         ticks_t now;
694         unsigned int deleted;
695 #ifdef DNS_LU_LST
696         struct dns_lu_lst* l;
697         struct dns_lu_lst* tmp;
698 #else
699         struct dns_hash_entry* t;
700         unsigned int h;
701         static unsigned int start=0;
702 #endif
703
704         deleted=0;
705         now=get_ticks_raw();
706         LOCK_DNS_HASH();
707 #ifdef DNS_LU_LST
708         clist_foreach_safe(dns_last_used_lst, l, tmp, next){
709                 if (*dns_cache_mem_used<=target) break;
710                 e=(struct dns_hash_entry*)(((char*)l)-
711                                 (char*)&((struct dns_hash_entry*)(0))->last_used_lst);
712                 if (((e->ent_flags & DNS_FLAG_PERMANENT) == 0)
713                         && (!expired_only || ((s_ticks_t)(now-e->expire)>=0))
714                 ) {
715                                 _dns_hash_remove(e);
716                                 deleted++;
717                 }
718         }
719 #else
720         for(h=start; h!=(start+DNS_HASH_SIZE); h++){
721                 clist_foreach_safe(&dns_hash[h%DNS_HASH_SIZE], e, t, next){
722                         if (*dns_cache_mem_used<=target)
723                                 goto skip;
724                         if (((e->ent_flags & DNS_FLAG_PERMANENT) == 0)
725                                 && ((s_ticks_t)(now-e->expire)>=0)
726                         ) {
727                                 _dns_hash_remove(e);
728                                 deleted++;
729                         }
730                 }
731         }
732         /* not fair, but faster then random() */
733         if (!expired_only){
734                 for(h=start; h!=(start+DNS_HASH_SIZE); h++){
735                         clist_foreach_safe(&dns_hash[h%DNS_HASH_SIZE], e, t, next){
736                                 if (*dns_cache_mem_used<=target)
737                                         goto skip;
738                                 if (((e->ent_flags & DNS_FLAG_PERMANENT) == 0)
739                                         && ((s_ticks_t)(now-e->expire)>=0)
740                                 ) {
741                                         _dns_hash_remove(e);
742                                         deleted++;
743                                 }
744                         }
745                 }
746         }
747 skip:
748         start=h;
749 #endif
750         UNLOCK_DNS_HASH();
751         return deleted;
752 }
753
754
755
756 /* locking  version (the dns hash must _not_be locked externally)
757  * returns 0 when not found, the searched entry on success (with CNAMEs
758  *  followed) or the last CNAME entry from an unfinished CNAME chain,
759  *  if the search matches a CNAME. On error sets *err (e.g. recursive CNAMEs).
760  * it increases the internal refcnt => when finished dns_hash_put() must
761  *  be called on the returned entry
762  *  WARNING: - the return might be a CNAME even if type!=CNAME, see above */
763 inline static struct dns_hash_entry* dns_hash_get(str* name, int type, int* h,
764                                                                                                         int* err)
765 {
766         struct dns_hash_entry* e;
767
768         LOCK_DNS_HASH();
769         e=_dns_hash_find(name, type, h, err);
770         if (e){
771                 atomic_inc(&e->refcnt);
772         }
773         UNLOCK_DNS_HASH();
774         return e;
775 }
776
777
778
779 /* adds a fully created and init. entry (see dns_cache_mk_entry()) to the hash
780  * table
781  * returns 0 on success, -1 on error */
782 inline static int dns_cache_add(struct dns_hash_entry* e)
783 {
784         int h;
785
786         /* check space */
787         /* atomic_add_long(dns_cache_total_used, e->size); */
788         if ((*dns_cache_mem_used+e->total_size)>=cfg_get(core, core_cfg, dns_cache_max_mem)){
789 #ifdef USE_DNS_CACHE_STATS
790                 dns_cache_stats[process_no].dc_lru_cnt++;
791 #endif
792                 LM_WARN("cache full, trying to free...\n");
793                 /* free ~ 12% of the cache */
794                 dns_cache_free_mem(*dns_cache_mem_used/16*14,
795                                         !cfg_get(core, core_cfg, dns_cache_del_nonexp));
796                 if ((*dns_cache_mem_used+e->total_size)>=cfg_get(core, core_cfg, dns_cache_max_mem)){
797                         LM_ERR("max. cache mem size exceeded\n");
798                         return -1;
799                 }
800         }
801         atomic_inc(&e->refcnt);
802         h=dns_hash_no(e->name, e->name_len, e->type);
803 #ifdef DNS_CACHE_DEBUG
804         LM_DBG("adding %.*s(%d) %d (flags=%0x) at %d\n",
805                         e->name_len, e->name, e->name_len, e->type, e->ent_flags, h);
806 #endif
807         LOCK_DNS_HASH();
808                 *dns_cache_mem_used+=e->total_size; /* no need for atomic ops, written
809                                                                                  only from within a lock */
810                 clist_append(&dns_hash[h], e, next, prev);
811 #ifdef DNS_LU_LST
812                 clist_append(dns_last_used_lst, &e->last_used_lst, next, prev);
813 #endif
814         UNLOCK_DNS_HASH();
815         return 0;
816 }
817
818
819
820 /* same as above, but it must be called with the dns hash lock held
821  * returns 0 on success, -1 on error */
822 inline static int dns_cache_add_unsafe(struct dns_hash_entry* e)
823 {
824         int h;
825
826         /* check space */
827         /* atomic_add_long(dns_cache_total_used, e->size); */
828         if ((*dns_cache_mem_used+e->total_size)>=cfg_get(core, core_cfg, dns_cache_max_mem)){
829 #ifdef USE_DNS_CACHE_STATS
830                 dns_cache_stats[process_no].dc_lru_cnt++;
831 #endif
832                 LM_WARN("cache full, trying to free...\n");
833                 /* free ~ 12% of the cache */
834                 UNLOCK_DNS_HASH();
835                 dns_cache_free_mem(*dns_cache_mem_used/16*14,
836                                         !cfg_get(core, core_cfg, dns_cache_del_nonexp));
837                 LOCK_DNS_HASH();
838                 if ((*dns_cache_mem_used+e->total_size)>=cfg_get(core, core_cfg, dns_cache_max_mem)){
839                         LM_ERR("max. cache mem size exceeded\n");
840                         return -1;
841                 }
842         }
843         atomic_inc(&e->refcnt);
844         h=dns_hash_no(e->name, e->name_len, e->type);
845 #ifdef DNS_CACHE_DEBUG
846         LM_DBG("adding %.*s(%d) %d (flags=%0x) at %d\n",
847                         e->name_len, e->name, e->name_len, e->type, e->ent_flags, h);
848 #endif
849         *dns_cache_mem_used+=e->total_size; /* no need for atomic ops, written
850                                                                                  only from within a lock */
851         clist_append(&dns_hash[h], e, next, prev);
852 #ifdef DNS_LU_LST
853         clist_append(dns_last_used_lst, &e->last_used_lst, next, prev);
854 #endif
855         return 0;
856 }
857
858
859
860 /* creates a "negative" entry which will be valid for ttl seconds */
861 inline static struct dns_hash_entry* dns_cache_mk_bad_entry(str* name,
862                                                                                                                         int type,
863                                                                                                                         int ttl,
864                                                                                                                         int flags)
865 {
866         struct dns_hash_entry* e;
867         int size;
868         ticks_t now;
869
870 #ifdef DNS_CACHE_DEBUG
871         LM_DBG("(%.*s, %d, %d, %d)\n", name->len, name->s, type, ttl, flags);
872 #endif
873         size=sizeof(struct dns_hash_entry)+name->len-1+1;
874         e=shm_malloc(size);
875         if (e==0){
876                 LM_ERR("out of memory\n");
877                 return 0;
878         }
879         memset(e, 0, size); /* init with 0*/
880         e->total_size=size;
881         e->name_len=name->len;
882         e->type=type;
883         now=get_ticks_raw();
884         e->last_used=now;
885         e->expire=now+S_TO_TICKS(ttl);
886         memcpy(e->name, name->s, name->len);
887         e->ent_flags=flags;
888         return e;
889 }
890
891
892
893 /* create a a/aaaa hash entry from a name and ip address
894  * returns 0 on error */
895 inline static struct dns_hash_entry* dns_cache_mk_ip_entry(str* name,
896                                                                                                                         struct ip_addr* ip)
897 {
898         struct dns_hash_entry* e;
899         int size;
900         ticks_t now;
901
902         /* everything is allocated in one block: dns_hash_entry + name +
903          * + dns_rr + rdata;  dns_rr must start at an aligned adress,
904          * hence we need to round dns_hash_entry+name size to a sizeof(long)
905          * multiple.
906          * Memory image:
907          * struct dns_hash_entry
908          * name (name_len+1 bytes)
909          * padding to multiple of sizeof(long)
910          * dns_rr
911          * rdata  (no padding needed, since for ip is just an array of chars)
912           */
913         size=ROUND_POINTER(sizeof(struct dns_hash_entry)+name->len-1+1)+
914                         sizeof(struct dns_rr)+ ip->len;
915         e=shm_malloc(size);
916         if (e==0){
917                 LM_ERR("out of memory\n");
918                 return 0;
919         }
920         memset(e, 0, size); /* init with 0*/
921         e->total_size=size;
922         e->name_len=name->len;
923         e->type=(ip->af==AF_INET)?T_A:T_AAAA;
924         now=get_ticks_raw();
925         e->last_used=now;
926         e->expire=now-1; /* maximum expire */
927         memcpy(e->name, name->s, name->len); /* memset makes sure is 0-term. */
928         e->rr_lst=(void*)((char*)e+
929                                 ROUND_POINTER(sizeof(struct dns_hash_entry)+name->len-1+1));
930         e->rr_lst->rdata=(void*)((char*)e->rr_lst+sizeof(struct dns_rr));
931         e->rr_lst->expire=now-1; /* maximum expire */
932         /* no need to align rr_lst->rdata for a or aaaa records */
933         memcpy(e->rr_lst->rdata, ip->u.addr, ip->len);
934         return e;
935 }
936
937 /* creates an srv hash entry from the given parameters
938  * returns 0 on error */
939 static struct dns_hash_entry* dns_cache_mk_srv_entry(str* name,
940                                                         unsigned short priority,
941                                                         unsigned short weight,
942                                                         unsigned short port,
943                                                         str* rr_name,
944                                                         int ttl)
945 {
946         struct dns_hash_entry* e;
947         int size;
948         ticks_t now;
949
950         /* everything is allocated in one block: dns_hash_entry + name +
951          * + dns_rr + rdata;  dns_rr must start at an aligned adress,
952          * hence we need to round dns_hash_entry+name size to a sizeof(long),
953          * and similarly, dns_rr must be rounded to sizeof(short).
954          * multiple.
955          * Memory image:
956          * struct dns_hash_entry
957          * name (name_len+1 bytes)
958          * padding to multiple of sizeof(long)
959          * dns_rr
960          * padding to multiple of sizeof(short)
961          * rdata
962           */
963         size=ROUND_POINTER(sizeof(struct dns_hash_entry)+name->len-1+1) +
964                 ROUND_SHORT(sizeof(struct dns_rr)) +
965                 sizeof(struct srv_rdata)-1 +
966                 rr_name->len+1;
967
968         e=shm_malloc(size);
969         if (e==0){
970                 LM_ERR("out of memory\n");
971                 return 0;
972         }
973         memset(e, 0, size); /* init with 0*/
974         e->total_size=size;
975         e->name_len=name->len;
976         e->type=T_SRV;
977         now=get_ticks_raw();
978         e->last_used=now;
979         e->expire=now+S_TO_TICKS(ttl);
980         memcpy(e->name, name->s, name->len); /* memset makes sure is 0-term. */
981         e->rr_lst=(void*)((char*)e+
982                                 ROUND_POINTER(sizeof(struct dns_hash_entry)+name->len-1+1));
983         e->rr_lst->rdata=(void*)((char*)e->rr_lst+ROUND_SHORT(sizeof(struct dns_rr)));
984         e->rr_lst->expire=e->expire;
985         ((struct srv_rdata*)e->rr_lst->rdata)->priority = priority;
986         ((struct srv_rdata*)e->rr_lst->rdata)->weight = weight;
987         ((struct srv_rdata*)e->rr_lst->rdata)->port = port;
988         ((struct srv_rdata*)e->rr_lst->rdata)->name_len = rr_name->len;
989         memcpy(((struct srv_rdata*)e->rr_lst->rdata)->name, rr_name->s, rr_name->len);
990         return e;
991 }
992
993
994 /* create a dns hash entry from a name and a rdata list (pkg_malloc'ed)
995  * (it will use only the type records with the name "name" from the
996  *  rdata list with one exception: if a matching CNAME with the same
997  *  name is found, the search will stop and this will be the record used)
998  * returns 0 on error and removes the used elements from the rdata list*/
999 inline static struct dns_hash_entry* dns_cache_mk_rd_entry(str* name, int type,
1000                                                                                                                 struct rdata** rd_lst)
1001 {
1002         struct dns_hash_entry* e;
1003         struct dns_rr* rr;
1004         struct dns_rr** tail_rr;
1005         struct rdata** p;
1006         struct rdata* tmp_lst;
1007         struct rdata** tail;
1008         struct rdata* l;
1009         int size;
1010         ticks_t now;
1011         unsigned int max_ttl;
1012         unsigned int ttl;
1013         int i;
1014
1015 #define rec_matches(rec, t, n) /*(struct rdata* record, int type, str* name)*/\
1016         (       ((rec)->name_len==(n)->len) && ((rec)->type==(t)) && \
1017                 (strncasecmp((rec)->name, (n)->s, (n)->len)==0))
1018         /* init */
1019         tmp_lst=0;
1020         tail=&tmp_lst;
1021
1022
1023         /* everything is allocated in one block: dns_hash_entry + name +
1024          * + dns_rr + rdata_raw+ ....;  dns_rr must start at an aligned adress,
1025          * hence we need to round dns_hash_entry+name size to a sizeof(long)
1026          * multiple. If rdata type requires it, rdata_raw might need to be also
1027          * aligned.
1028          * Memory image:
1029          * struct dns_hash_entry  (e)
1030          * name (name_len+1 bytes)  (&e->name[0])
1031          * padding to multiple of sizeof(char*)
1032          * dns_rr1 (e->rr_lst)
1033          * possible padding: no padding for a_rdata or aaaa_rdata,
1034          *                   multipe of sizeof(short) for srv_rdata,
1035          *                   multiple of sizeof(long) for naptr_rdata and others
1036          * dns_rr1->rdata  (e->rr_lst->rdata)
1037          * padding to multipe of sizeof long
1038          * dns_rr2 (e->rr_lst->next)
1039          * ....
1040          *
1041          */
1042         size=0;
1043         if (*rd_lst==0)
1044                 return 0;
1045         /* find the first matching rr, if it's a CNAME use CNAME as type,
1046          * if not continue with the original type */
1047         for(p=rd_lst; *p; p=&(*p)->next){
1048                 if (((*p)->name_len==name->len) &&
1049                                 (((*p)->type==type) || ((*p)->type==T_CNAME)) &&
1050                                 (strncasecmp((*p)->name, name->s, name->len)==0)){
1051                         type=(*p)->type;
1052                         break;
1053                 }
1054         }
1055         /* continue, we found the type we are looking for */
1056         switch(type){
1057                 case T_A:
1058                         for(; *p;){
1059                                 if (!rec_matches((*p), type, name)){
1060                                         /* skip this record */
1061                                         p=&(*p)->next; /* advance */
1062                                         continue;
1063                                 }
1064                                 size+=ROUND_POINTER(sizeof(struct dns_rr)+
1065                                                                                 sizeof(struct a_rdata));
1066                                 /* add it to our tmp. lst */
1067                                 *tail=*p;
1068                                 tail=&(*p)->next;
1069                                 /* detach it from the rd list */
1070                                 *p=(*p)->next;
1071                                 /* don't advance p, because the crt. elem. has
1072                                  * just been elimintated */
1073                         }
1074                         break;
1075                 case T_AAAA:
1076                         for(; *p;){
1077                                 if (!rec_matches((*p), type, name)){
1078                                         /* skip this record */
1079                                         p=&(*p)->next; /* advance */
1080                                         continue;
1081                                 }
1082                                 /* no padding */
1083                                 size+=ROUND_POINTER(sizeof(struct dns_rr)+
1084                                                                                         sizeof(struct aaaa_rdata));
1085                                 /* add it to our tmp. lst */
1086                                 *tail=*p;
1087                                 tail=&(*p)->next;
1088                                 /* detach it from the rd list */
1089                                 *p=(*p)->next;
1090                                 /* don't advance p, because the crt. elem. has
1091                                  * just been elimintated */
1092                         }
1093                         break;
1094                 case T_SRV:
1095                         for(; *p;){
1096                                 if (!rec_matches((*p), type, name)){
1097                                         /* skip this record */
1098                                         p=&(*p)->next; /* advance */
1099                                         continue;
1100                                 }
1101                                 /* padding to short */
1102                                 size+=ROUND_POINTER(ROUND_SHORT(sizeof(struct dns_rr))+
1103                                                 SRV_RDATA_SIZE(*(struct srv_rdata*)(*p)->rdata));
1104                                 /* add it to our tmp. lst */
1105                                 *tail=*p;
1106                                 tail=&(*p)->next;
1107                                 /* detach it from the rd list */
1108                                 *p=(*p)->next;
1109                                 /* don't advance p, because the crt. elem. has
1110                                  * just been elimintated */
1111                         }
1112                         break;
1113                 case T_NAPTR:
1114                         for(; *p;){
1115                                 if (!rec_matches((*p), type, name)){
1116                                         /* skip this record */
1117                                         p=&(*p)->next; /* advance */
1118                                         continue;
1119                                 }
1120                                 /* padding to char* */
1121                                 size+=ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
1122                                                 NAPTR_RDATA_SIZE(*(struct naptr_rdata*)(*p)->rdata));
1123                                 /* add it to our tmp. lst */
1124                                 *tail=*p;
1125                                 tail=&(*p)->next;
1126                                 /* detach it from the rd list */
1127                                 *p=(*p)->next;
1128                                 /* don't advance p, because the crt. elem. has
1129                                  * just been elimintated */
1130                         }
1131                         break;
1132                 case T_CNAME:
1133                         for(; *p;){
1134                                 if (!rec_matches((*p), type, name)){
1135                                         /* skip this record */
1136                                         p=&(*p)->next; /* advance */
1137                                         continue;
1138                                 }
1139                                 /* no padding */
1140                                 size+=ROUND_POINTER(sizeof(struct dns_rr)+
1141                                                 CNAME_RDATA_SIZE(*(struct cname_rdata*)(*p)->rdata));
1142                                 /* add it to our tmp. lst */
1143                                 *tail=*p;
1144                                 tail=&(*p)->next;
1145                                 /* detach it from the rd list */
1146                                 *p=(*p)->next;
1147                                 /* don't advance p, because the crt. elem. has
1148                                  * just been elimintated */
1149                         }
1150                         break;
1151                 case T_TXT:
1152                         for(; *p;){
1153                                 if (!rec_matches((*p), type, name)){
1154                                         /* skip this record */
1155                                         p=&(*p)->next; /* advance */
1156                                         continue;
1157                                 }
1158                                 /* padding to char* (because of txt[]->cstr*/
1159                                 size+=ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
1160                                                 TXT_RDATA_SIZE(*(struct txt_rdata*)(*p)->rdata));
1161                                 /* add it to our tmp. lst */
1162                                 *tail=*p;
1163                                 tail=&(*p)->next;
1164                                 /* detach it from the rd list */
1165                                 *p=(*p)->next;
1166                                 /* don't advance p, because the crt. elem. has
1167                                  * just been elimintated */
1168                         }
1169                         break;
1170                 case T_EBL:
1171                         for(; *p;){
1172                                 if (!rec_matches((*p), type, name)){
1173                                         /* skip this record */
1174                                         p=&(*p)->next; /* advance */
1175                                         continue;
1176                                 }
1177                                 /* padding to char* (because of the char* pointers */
1178                                 size+=ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
1179                                                 EBL_RDATA_SIZE(*(struct ebl_rdata*)(*p)->rdata));
1180                                 /* add it to our tmp. lst */
1181                                 *tail=*p;
1182                                 tail=&(*p)->next;
1183                                 /* detach it from the rd list */
1184                                 *p=(*p)->next;
1185                                 /* don't advance p, because the crt. elem. has
1186                                  * just been elimintated */
1187                         }
1188                         break;
1189                 case T_PTR:
1190                         for(; *p;){
1191                                 if (!rec_matches((*p), type, name)){
1192                                         /* skip this record */
1193                                         p=&(*p)->next; /* advance */
1194                                         continue;
1195                                 }
1196                                 /* no padding */
1197                                 size+=ROUND_POINTER(sizeof(struct dns_rr)+
1198                                                 PTR_RDATA_SIZE(*(struct ptr_rdata*)(*p)->rdata));
1199                                 /* add it to our tmp. lst */
1200                                 *tail=*p;
1201                                 tail=&(*p)->next;
1202                                 /* detach it from the rd list */
1203                                 *p=(*p)->next;
1204                                 /* don't advance p, because the crt. elem. has
1205                                  * just been elimintated */
1206                         }
1207                         break;
1208                 default:
1209                         LM_CRIT("type %d not supported\n", type);
1210                         /* we don't know what to do with it, so don't
1211                          * add it to the tmp_lst */
1212                         return 0; /* error */
1213         }
1214         *tail=0; /* mark the end of our tmp_lst */
1215         if (size==0){
1216 #ifdef DNS_CACHE_DEBUG
1217                 LM_DBG("entry %.*s (%d) not found\n", name->len, name->s, type);
1218 #endif
1219                 return 0;
1220         }
1221         /* compute size */
1222         size+=ROUND_POINTER(sizeof(struct dns_hash_entry)+name->len-1+1);
1223         e=shm_malloc(size);
1224         if (e==0){
1225                 LM_ERR("out of memory\n");
1226                 return 0;
1227         }
1228         memset(e, 0, size); /* init with 0 */
1229         clist_init(e, next, prev);
1230         e->total_size=size;
1231         e->name_len=name->len;
1232         e->type=type;
1233         now=get_ticks_raw();
1234         e->last_used=now;
1235         memcpy(e->name, name->s, name->len); /* memset makes sure is 0-term. */
1236         e->rr_lst=(struct dns_rr*)((char*)e+
1237                                 ROUND_POINTER(sizeof(struct dns_hash_entry)+name->len-1+1));
1238         tail_rr=&(e->rr_lst);
1239         rr=e->rr_lst;
1240         max_ttl=0;
1241         /* copy the actual data */
1242         switch(type){
1243                 case T_A:
1244                         for(l=tmp_lst; l; l=l->next){
1245                                 ttl=FIX_TTL(l->ttl);
1246                                 rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1247                                 max_ttl=MAX(max_ttl, ttl);
1248                                 rr->rdata=(void*)((char*)rr+sizeof(struct dns_rr));
1249                                 memcpy(rr->rdata, l->rdata, sizeof(struct a_rdata));
1250                                 rr->next=(void*)((char*)rr+ROUND_POINTER(sizeof(struct dns_rr)+
1251                                                         sizeof(struct a_rdata)));
1252                                 tail_rr=&(rr->next);
1253                                 rr=rr->next;
1254                         }
1255                         break;
1256                 case T_AAAA:
1257                         for(l=tmp_lst; l; l=l->next){
1258                                 ttl=FIX_TTL(l->ttl);
1259                                 rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1260                                 max_ttl=MAX(max_ttl, ttl);
1261                                 rr->rdata=(void*)((char*)rr+sizeof(struct dns_rr));
1262                                 memcpy(rr->rdata, l->rdata, sizeof(struct aaaa_rdata));
1263                                 rr->next=(void*)((char*)rr+ROUND_POINTER(sizeof(struct dns_rr)+
1264                                                         sizeof(struct aaaa_rdata)));
1265                                 tail_rr=&(rr->next);
1266                                 rr=rr->next;
1267                         }
1268                         break;
1269                 case T_SRV:
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+
1275                                                                 ROUND_SHORT(sizeof(struct dns_rr)));
1276                                 /* copy the whole srv_rdata block*/
1277                                 memcpy(rr->rdata, l->rdata,
1278                                                 SRV_RDATA_SIZE(*(struct srv_rdata*)l->rdata) );
1279                                 rr->next=(void*)((char*)rr+
1280                                                         ROUND_POINTER( ROUND_SHORT(sizeof(struct dns_rr))+
1281                                                                                 SRV_RDATA_SIZE(
1282                                                                                         *(struct srv_rdata*)l->rdata)));
1283                                 tail_rr=&(rr->next);
1284                                 rr=rr->next;
1285                         }
1286                         break;
1287                 case T_NAPTR:
1288                         for(l=tmp_lst; l; l=l->next){
1289                                 ttl=FIX_TTL(l->ttl);
1290                                 rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1291                                 max_ttl=MAX(max_ttl, ttl);
1292                                 rr->rdata=(void*)((char*)rr+
1293                                                                 ROUND_POINTER(sizeof(struct dns_rr)));
1294                                 /* copy the whole naptr_rdata block*/
1295                                 memcpy(rr->rdata, l->rdata,
1296                                                 NAPTR_RDATA_SIZE(*(struct naptr_rdata*)l->rdata) );
1297                                 /* adjust the string pointer */
1298                                 ((struct naptr_rdata*)rr->rdata)->flags=
1299                                         translate_pointer((char*)rr->rdata, (char*)l->rdata,
1300                                                         (((struct naptr_rdata*)l->rdata)->flags));
1301                                 ((struct naptr_rdata*)rr->rdata)->services=
1302                                         translate_pointer((char*)rr->rdata, (char*)l->rdata,
1303                                                         (((struct naptr_rdata*)l->rdata)->services));
1304                                 ((struct naptr_rdata*)rr->rdata)->regexp=
1305                                         translate_pointer((char*)rr->rdata, (char*)l->rdata,
1306                                                         (((struct naptr_rdata*)l->rdata)->regexp));
1307                                 ((struct naptr_rdata*)rr->rdata)->repl=
1308                                         translate_pointer((char*)rr->rdata, (char*)l->rdata,
1309                                                         (((struct naptr_rdata*)l->rdata)->repl));
1310                                 rr->next=(void*)((char*)rr+
1311                                                         ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
1312                                                                                 NAPTR_RDATA_SIZE(
1313                                                                                         *(struct naptr_rdata*)l->rdata)));
1314                                 tail_rr=&(rr->next);
1315                                 rr=rr->next;
1316                         }
1317                         break;
1318                 case T_CNAME:
1319                         for(l=tmp_lst; l; l=l->next){
1320                                 ttl=FIX_TTL(l->ttl);
1321                                 rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1322                                 max_ttl=MAX(max_ttl, ttl);
1323                                 rr->rdata=(void*)((char*)rr+sizeof(struct dns_rr));
1324                                 memcpy(rr->rdata, l->rdata,
1325                                                         CNAME_RDATA_SIZE(*(struct cname_rdata*)l->rdata));
1326                                 rr->next=(void*)((char*)rr+ROUND_POINTER(sizeof(struct dns_rr)+
1327                                                         CNAME_RDATA_SIZE(*(struct cname_rdata*)l->rdata)));
1328                                 tail_rr=&(rr->next);
1329                                 rr=rr->next;
1330                         }
1331                         break;
1332                 case T_TXT:
1333                         for(l=tmp_lst; l; l=l->next){
1334                                 ttl=FIX_TTL(l->ttl);
1335                                 rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1336                                 max_ttl=MAX(max_ttl, ttl);
1337                                 rr->rdata=(void*)((char*)rr+
1338                                                         ROUND_POINTER(sizeof(struct dns_rr)));
1339                                 memcpy(rr->rdata, l->rdata,
1340                                                         TXT_RDATA_SIZE(*(struct txt_rdata*)l->rdata));
1341                                 /* adjust the string pointers */
1342                                 for (i=0; i<((struct txt_rdata*)l->rdata)->cstr_no; i++){
1343                                         ((struct txt_rdata*)rr->rdata)->txt[i].cstr=
1344                                                 translate_pointer((char*)rr->rdata, (char*)l->rdata,
1345                                                                 ((struct txt_rdata*)l->rdata)->txt[i].cstr);
1346                                 }
1347                                 rr->next=(void*)((char*)rr+
1348                                                 ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
1349                                                         TXT_RDATA_SIZE(*(struct txt_rdata*)l->rdata)));
1350                                 tail_rr=&(rr->next);
1351                                 rr=rr->next;
1352                         }
1353                         break;
1354                 case T_EBL:
1355                         for(l=tmp_lst; l; l=l->next){
1356                                 ttl=FIX_TTL(l->ttl);
1357                                 rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1358                                 max_ttl=MAX(max_ttl, ttl);
1359                                 rr->rdata=(void*)((char*)rr+
1360                                                         ROUND_POINTER(sizeof(struct dns_rr)));
1361                                 memcpy(rr->rdata, l->rdata,
1362                                                         EBL_RDATA_SIZE(*(struct ebl_rdata*)l->rdata));
1363                                 /* adjust the string pointers */
1364                                 ((struct ebl_rdata*)rr->rdata)->separator=
1365                                         translate_pointer((char*)rr->rdata, (char*)l->rdata,
1366                                                                 ((struct ebl_rdata*)l->rdata)->separator);
1367                                 ((struct ebl_rdata*)rr->rdata)->separator=
1368                                                 translate_pointer((char*)rr->rdata, (char*)l->rdata,
1369                                                                 ((struct ebl_rdata*)l->rdata)->separator);
1370                                 ((struct ebl_rdata*)rr->rdata)->apex=
1371                                                 translate_pointer((char*)rr->rdata, (char*)l->rdata,
1372                                                                 ((struct ebl_rdata*)l->rdata)->apex);
1373                                 rr->next=(void*)((char*)rr+
1374                                                 ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
1375                                                         EBL_RDATA_SIZE(*(struct ebl_rdata*)l->rdata)));
1376                                 tail_rr=&(rr->next);
1377                                 rr=rr->next;
1378                         }
1379                         break;
1380                 case T_PTR:
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+sizeof(struct dns_rr));
1386                                 memcpy(rr->rdata, l->rdata,
1387                                                         PTR_RDATA_SIZE(*(struct ptr_rdata*)l->rdata));
1388                                 rr->next=(void*)((char*)rr+ROUND_POINTER(sizeof(struct dns_rr)+
1389                                                         PTR_RDATA_SIZE(*(struct ptr_rdata*)l->rdata)));
1390                                 tail_rr=&(rr->next);
1391                                 rr=rr->next;
1392                         }
1393                         break;
1394                 default:
1395                         /* do nothing */
1396                         LM_CRIT("type %d not supported\n", type);
1397                                 ;
1398         }
1399         *tail_rr=0; /* terminate the list */
1400         e->expire=now+S_TO_TICKS(max_ttl);
1401         free_rdata_list(tmp_lst);
1402         return e;
1403 }
1404
1405
1406
1407 /* structure used only inside dns_cache_mk_rd_entry2 to break
1408  *  the list of records into records of the same type */
1409 struct tmp_rec{
1410         struct rdata* rd;
1411         struct dns_hash_entry* e;
1412         struct dns_rr* rr;
1413         struct dns_rr** tail_rr;
1414         int max_ttl;
1415         int size;
1416 };
1417
1418
1419
1420 /* create several dns hash entries from a list of rdata structs
1421  * returns 0 on error */
1422 inline static struct dns_hash_entry* dns_cache_mk_rd_entry2(struct rdata* rd)
1423 {
1424         struct rdata* l;
1425         ticks_t now;
1426         struct tmp_rec rec[MAX_DNS_RECORDS];
1427         int rec_idx[MAX_DNS_RECORDS];
1428         int r, i, j;
1429         int no_records; /* number of different records */
1430         unsigned int ttl;
1431
1432
1433         no_records=0;
1434         rec[0].e=0;
1435         /* everything is allocated in one block: dns_hash_entry + name +
1436          * + dns_rr + rdata_raw+ ....;  dns_rr must start at an aligned adress,
1437          * hence we need to round dns_hash_entry+name size to a sizeof(long)
1438          * multiple. If rdata type requires it, rdata_raw might need to be also
1439          * aligned.
1440          * Memory image:
1441          * struct dns_hash_entry  (e)
1442          * name (name_len+1 bytes)  (&e->name[0])
1443          * padding to multiple of sizeof(char*)
1444          * dns_rr1 (e->rr_lst)
1445          * possible padding: no padding for a_rdata or aaaa_rdata,
1446          *                   multipe of sizeof(short) for srv_rdata,
1447          *                   multiple of sizeof(long) for naptr_rdata and others
1448          * dns_rr1->rdata  (e->rr_lst->rdata)
1449          * padding to multipe of sizeof long
1450          * dns_rr2 (e->rr_lst->next)
1451          * ....
1452          *
1453          */
1454         /* compute size */
1455         for(l=rd, i=0; l && (i<MAX_DNS_RECORDS); l=l->next, i++){
1456                 for (r=0; r<no_records; r++){
1457                         if ((l->type==rec[r].rd->type) &&
1458                                         (l->name_len==rec[r].rd->name_len)
1459                                 && (strncasecmp(l->name, rec[r].rd->name, l->name_len)==0)){
1460                                 /* found */
1461                                 goto found;
1462                         }
1463                 }
1464                 /* not found, create new */
1465                 if (no_records<MAX_DNS_RECORDS){
1466                         rec[r].rd=l;
1467                         rec[r].e=0;
1468                         rec[r].size=ROUND_POINTER(sizeof(struct dns_hash_entry)+
1469                                                         rec[r].rd->name_len-1+1);
1470                         no_records++;
1471                 }else{
1472                         LM_ERR("too many records: %d\n", no_records);
1473                         /* skip */
1474                         continue;
1475                 }
1476 found:
1477                 rec_idx[i]=r;
1478                 switch(l->type){
1479                         case T_A:
1480                                 /* no padding */
1481                                 rec[r].size+=ROUND_POINTER(sizeof(struct dns_rr)+
1482                                                                                 sizeof(struct a_rdata));
1483                                 break;
1484                         case T_AAAA:
1485                                 /* no padding */
1486                                 rec[r].size+=ROUND_POINTER(sizeof(struct dns_rr)+
1487                                                                                                 sizeof(struct aaaa_rdata));
1488                                 break;
1489                         case T_SRV:
1490                                 /* padding to short */
1491                                 rec[r].size+=ROUND_POINTER(ROUND_SHORT(sizeof(struct dns_rr))+
1492                                                                 SRV_RDATA_SIZE(*(struct srv_rdata*)l->rdata));
1493                                 break;
1494                         case T_NAPTR:
1495                                         /* padding to char* */
1496                                 rec[r].size+=ROUND_POINTER(ROUND_POINTER(
1497                                                                                                 sizeof(struct dns_rr))+
1498                                                         NAPTR_RDATA_SIZE(*(struct naptr_rdata*)l->rdata));
1499                                 break;
1500                         case T_CNAME:
1501                                         /* no padding */
1502                                 rec[r].size+=ROUND_POINTER(sizeof(struct dns_rr)+
1503                                                         CNAME_RDATA_SIZE(*(struct cname_rdata*)l->rdata));
1504                                 break;
1505                         case T_TXT:
1506                                         /* padding to char* (because of txt[]->cstr)*/
1507                                 rec[r].size+=ROUND_POINTER(ROUND_POINTER(
1508                                                                                                 sizeof(struct dns_rr))+
1509                                                         TXT_RDATA_SIZE(*(struct txt_rdata*)l->rdata));
1510                                 break;
1511                         case T_EBL:
1512                                         /* padding to char* (because of char* pointers)*/
1513                                 rec[r].size+=ROUND_POINTER(ROUND_POINTER(
1514                                                                                                 sizeof(struct dns_rr))+
1515                                                         EBL_RDATA_SIZE(*(struct ebl_rdata*)l->rdata));
1516                                 break;
1517                         case T_PTR:
1518                                         /* no padding */
1519                                 rec[r].size+=ROUND_POINTER(sizeof(struct dns_rr)+
1520                                                         PTR_RDATA_SIZE(*(struct ptr_rdata*)l->rdata));
1521                                 break;
1522                         default:
1523                                 LM_CRIT("type %d not supported\n", l->type);
1524                 }
1525         }
1526
1527         now=get_ticks_raw();
1528         /* alloc & init the entries */
1529         for (r=0; r<no_records; r++){
1530                 rec[r].e=shm_malloc(rec[r].size);
1531                 if (rec[r].e==0){
1532                         LM_ERR("out of memory\n");
1533                         goto error;
1534                 }
1535                 memset(rec[r].e, 0, rec[r].size); /* init with 0*/
1536                 rec[r].e->total_size=rec[r].size;
1537                 rec[r].e->name_len=rec[r].rd->name_len;
1538                 rec[r].e->type=rec[r].rd->type;
1539                 rec[r].e->last_used=now;
1540                 /* memset makes sure is 0-term. */
1541                 memcpy(rec[r].e->name, rec[r].rd->name, rec[r].rd->name_len);
1542                 rec[r].e->rr_lst=(struct dns_rr*)((char*)rec[r].e+
1543                                 ROUND_POINTER(sizeof(struct dns_hash_entry)+rec[r].e->name_len
1544                                                                  -1+1));
1545                 rec[r].tail_rr=&(rec[r].e->rr_lst);
1546                 rec[r].rr=rec[r].e->rr_lst;
1547                 rec[r].max_ttl=0;
1548                 /* link them in a list */
1549                 if (r==0){
1550                         clist_init(rec[r].e, next, prev);
1551                 }else{
1552                         clist_append(rec[0].e, rec[r].e, next, prev);
1553                 }
1554         }
1555         /* copy the actual data */
1556         for(l=rd, i=0; l && (i<MAX_DNS_RECORDS); l=l->next, i++){
1557                 r=rec_idx[i];
1558                 ttl=FIX_TTL(l->ttl);
1559                 switch(l->type){
1560                         case T_A:
1561                                 rec[r].rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1562                                 rec[r].max_ttl=MAX(rec[r].max_ttl, ttl);
1563                                 rec[r].rr->rdata=(void*)((char*)rec[r].rr+
1564                                                                         sizeof(struct dns_rr));
1565                                 memcpy(rec[r].rr->rdata, l->rdata, sizeof(struct a_rdata));
1566                                 rec[r].rr->next=(void*)((char*)rec[r].rr+
1567                                                                         ROUND_POINTER(sizeof(struct dns_rr)+
1568                                                                         sizeof(struct a_rdata)));
1569                                 rec[r].tail_rr=&(rec[r].rr->next);
1570                                 rec[r].rr=rec[r].rr->next;
1571                                 break;
1572                         case T_AAAA:
1573                                 rec[r].rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1574                                 rec[r].max_ttl=MAX(rec[r].max_ttl, ttl);
1575                                 rec[r].rr->rdata=(void*)((char*)rec[r].rr+
1576                                                                         sizeof(struct dns_rr));
1577                                 memcpy(rec[r].rr->rdata, l->rdata, sizeof(struct aaaa_rdata));
1578                                 rec[r].rr->next=(void*)((char*)rec[r].rr+
1579                                                                         ROUND_POINTER(sizeof(struct dns_rr)+
1580                                                                         sizeof(struct aaaa_rdata)));
1581                                 rec[r].tail_rr=&(rec[r].rr->next);
1582                                 rec[r].rr=rec[r].rr->next;
1583                                 break;
1584                         case T_SRV:
1585                                 rec[r].rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1586                                 rec[r].max_ttl=MAX(rec[r].max_ttl, ttl);
1587                                 rec[r].rr->rdata=(void*)((char*)rec[r].rr+
1588                                                                 ROUND_SHORT(sizeof(struct dns_rr)));
1589                                 /* copy the whole srv_rdata block*/
1590                                 memcpy(rec[r].rr->rdata, l->rdata,
1591                                                 SRV_RDATA_SIZE(*(struct srv_rdata*)l->rdata) );
1592                                 rec[r].rr->next=(void*)((char*)rec[r].rr+
1593                                                         ROUND_POINTER( ROUND_SHORT(sizeof(struct dns_rr))+
1594                                                                                 SRV_RDATA_SIZE(
1595                                                                                         *(struct srv_rdata*)l->rdata)));
1596                                 rec[r].tail_rr=&(rec[r].rr->next);
1597                                 rec[r].rr=rec[r].rr->next;
1598                                 break;
1599                         case T_NAPTR:
1600                                 rec[r].rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1601                                 rec[r].max_ttl=MAX(rec[r].max_ttl, ttl);
1602                                 rec[r].rr->rdata=(void*)((char*)rec[r].rr+
1603                                                                 ROUND_POINTER(sizeof(struct dns_rr)));
1604                                 /* copy the whole srv_rdata block*/
1605                                 memcpy(rec[r].rr->rdata, l->rdata,
1606                                                 NAPTR_RDATA_SIZE(*(struct naptr_rdata*)l->rdata) );
1607                                 /* adjust the string pointer */
1608                                 ((struct naptr_rdata*)rec[r].rr->rdata)->flags=
1609                                         translate_pointer((char*)rec[r].rr->rdata, (char*)l->rdata,
1610                                                         (((struct naptr_rdata*)l->rdata)->flags));
1611                                 ((struct naptr_rdata*)rec[r].rr->rdata)->services=
1612                                         translate_pointer((char*)rec[r].rr->rdata, (char*)l->rdata,
1613                                                         (((struct naptr_rdata*)l->rdata)->services));
1614                                 ((struct naptr_rdata*)rec[r].rr->rdata)->regexp=
1615                                         translate_pointer((char*)rec[r].rr->rdata, (char*)l->rdata,
1616                                                         (((struct naptr_rdata*)l->rdata)->regexp));
1617                                 ((struct naptr_rdata*)rec[r].rr->rdata)->repl=
1618                                         translate_pointer((char*)rec[r].rr->rdata, (char*)l->rdata,
1619                                                         (((struct naptr_rdata*)l->rdata)->repl));
1620                                 rec[r].rr->next=(void*)((char*)rec[r].rr+
1621                                                         ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
1622                                                                                 NAPTR_RDATA_SIZE(
1623                                                                                         *(struct naptr_rdata*)l->rdata)));
1624                                 rec[r].tail_rr=&(rec[r].rr->next);
1625                                 rec[r].rr=rec[r].rr->next;
1626                                 break;
1627                         case T_CNAME:
1628                                 rec[r].rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1629                                 rec[r].max_ttl=MAX(rec[r].max_ttl, ttl);
1630                                 rec[r].rr->rdata=(void*)((char*)rec[r].rr
1631                                                                         +sizeof(struct dns_rr));
1632                                 memcpy(rec[r].rr->rdata, l->rdata,
1633                                                         CNAME_RDATA_SIZE(*(struct cname_rdata*)l->rdata));
1634                                 rec[r].rr->next=(void*)((char*)rec[r].rr+
1635                                                         ROUND_POINTER(sizeof(struct dns_rr)+
1636                                                         CNAME_RDATA_SIZE(*(struct cname_rdata*)l->rdata)));
1637                                 rec[r].tail_rr=&(rec[r].rr->next);
1638                                 rec[r].rr=rec[r].rr->next;
1639                                 break;
1640                         case T_TXT:
1641                                 rec[r].rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1642                                 rec[r].max_ttl=MAX(rec[r].max_ttl, ttl);
1643                                 rec[r].rr->rdata=(void*)((char*)rec[r].rr+
1644                                                                         ROUND_POINTER(sizeof(struct dns_rr)));
1645                                 memcpy(rec[r].rr->rdata, l->rdata,
1646                                                         TXT_RDATA_SIZE(*(struct txt_rdata*)l->rdata));
1647                                 /* adjust the string pointers */
1648                                 for (j=0; j<((struct txt_rdata*)l->rdata)->cstr_no; j++){
1649                                         ((struct txt_rdata*)rec[r].rr->rdata)->txt[j].cstr=
1650                                                 translate_pointer((char*)rec[r].rr->rdata,
1651                                                                 (char*)l->rdata,
1652                                                                 ((struct txt_rdata*)l->rdata)->txt[j].cstr);
1653                                 }
1654                                 rec[r].rr->next=(void*)((char*)rec[r].rr+
1655                                                 ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
1656                                                         TXT_RDATA_SIZE(*(struct txt_rdata*)l->rdata)));
1657                                 rec[r].tail_rr=&(rec[r].rr->next);
1658                                 rec[r].rr=rec[r].rr->next;
1659                                 break;
1660                         case T_EBL:
1661                                 rec[r].rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1662                                 rec[r].max_ttl=MAX(rec[r].max_ttl, ttl);
1663                                 rec[r].rr->rdata=(void*)((char*)rec[r].rr+
1664                                                                         ROUND_POINTER(sizeof(struct dns_rr)));
1665                                 memcpy(rec[r].rr->rdata, l->rdata,
1666                                                         EBL_RDATA_SIZE(*(struct ebl_rdata*)l->rdata));
1667                                 /* adjust the string pointers */
1668                                 ((struct ebl_rdata*)rec[r].rr->rdata)->separator=
1669                                         translate_pointer((char*)rec[r].rr->rdata,
1670                                                         (char*)l->rdata,
1671                                                         ((struct ebl_rdata*)l->rdata)->separator);
1672                                 ((struct ebl_rdata*)rec[r].rr->rdata)->apex=
1673                                         translate_pointer((char*)rec[r].rr->rdata,
1674                                                         (char*)l->rdata,
1675                                                         ((struct ebl_rdata*)l->rdata)->apex);
1676                                 rec[r].rr->next=(void*)((char*)rec[r].rr+
1677                                                 ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
1678                                                         EBL_RDATA_SIZE(*(struct ebl_rdata*)l->rdata)));
1679                                 rec[r].tail_rr=&(rec[r].rr->next);
1680                                 rec[r].rr=rec[r].rr->next;
1681                                 break;
1682                         case T_PTR:
1683                                 rec[r].rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1684                                 rec[r].max_ttl=MAX(rec[r].max_ttl, ttl);
1685                                 rec[r].rr->rdata=(void*)((char*)rec[r].rr
1686                                                                         +sizeof(struct dns_rr));
1687                                 memcpy(rec[r].rr->rdata, l->rdata,
1688                                                         PTR_RDATA_SIZE(*(struct ptr_rdata*)l->rdata));
1689                                 rec[r].rr->next=(void*)((char*)rec[r].rr+
1690                                                         ROUND_POINTER(sizeof(struct dns_rr)+
1691                                                         PTR_RDATA_SIZE(*(struct ptr_rdata*)l->rdata)));
1692                                 rec[r].tail_rr=&(rec[r].rr->next);
1693                                 rec[r].rr=rec[r].rr->next;
1694                                 break;
1695                         default:
1696                                 /* do nothing */
1697                                 ;
1698                 }
1699         }
1700         for (r=0; r<no_records; r++){
1701                 *rec[r].tail_rr=0; /* terminate the list */
1702                 rec[r].e->expire=now+S_TO_TICKS(rec[r].max_ttl);
1703         }
1704         return rec[0].e;
1705 error:
1706         for (r=0; r<no_records; r++){
1707                 dns_destroy_entry(rec[r].e);
1708         }
1709         return 0;
1710 }
1711
1712
1713
1714 inline static struct dns_hash_entry* dns_get_entry(str* name, int type);
1715
1716
1717 #define CACHE_RELEVANT_RECS_ONLY
1718
1719 #ifdef CACHE_RELEVANT_RECS_ONLY
1720 /* internal only: gets related entries from a rdata list, appends them
1721  * to e (list) and returns:
1722  *  - e if e is of the requested type
1723  *  -  if e is a CNAME, tries to get to the end of the CNAME chain and returns
1724  *      the final entry if the types match or 0 if the chain is unfinished
1725  *  - 0 on error/not found
1726  * records is modified (the used records are removed from the list and freed)
1727  *
1728  * WARNING: - records must be pkg_malloc'ed
1729  * Notes:   - if the return is 0 and e->type==T_CNAME, the list will contain
1730  *            the CNAME chain (the last element being the last CNAME)
1731  *  */
1732 inline static struct dns_hash_entry* dns_get_related(struct dns_hash_entry* e,
1733                                                                                                                 int type,
1734                                                                                                                 struct rdata** records)
1735 {
1736         struct dns_hash_entry* ret;
1737         struct dns_hash_entry* l;
1738         struct dns_hash_entry* t;
1739         struct dns_hash_entry* lst_end;
1740         struct dns_rr* rr;
1741         static int cname_chain_len=0;
1742         str tmp;
1743
1744         ret=0;
1745         l=e;
1746 #ifdef DNS_CACHE_DEBUG
1747         LM_DBG("(%p (%.*s, %d), %d, *%p) (%d)\n", e,
1748                         e->name_len, e->name, e->type, type, *records, cname_chain_len);
1749 #endif
1750         clist_init(l, next, prev);
1751         if (type==e->type){
1752                 ret=e;
1753                 switch(e->type){
1754                         case T_SRV:
1755                                 for (rr=e->rr_lst; rr && *records; rr=rr->next){
1756                                         tmp.s=((struct srv_rdata*)rr->rdata)->name;
1757                                         tmp.len=((struct srv_rdata*)rr->rdata)->name_len;
1758                                         if (!(dns_flags&DNS_IPV6_ONLY)){
1759                                                 t=dns_cache_mk_rd_entry(&tmp, T_A, records);
1760                                                 if (t){
1761                                                         if ((t->type==T_CNAME) && *records)
1762                                                                 dns_get_related(t, T_A, records);
1763                                                         lst_end=t->prev; /* needed for clist_append*/
1764                                                         clist_append_sublist(l, t, lst_end, next, prev);
1765                                                 }
1766                                         }
1767                                         if (!(dns_flags&DNS_IPV4_ONLY)){
1768                                                 t=dns_cache_mk_rd_entry(&tmp, T_AAAA, records);
1769                                                 if (t){
1770                                                         if ((t->type==T_CNAME) && *records)
1771                                                                 dns_get_related(t, T_AAAA, records);
1772                                                         lst_end=t->prev; /* needed for clist_append*/
1773                                                         clist_append_sublist(l, t, lst_end, next, prev);
1774                                                 }
1775                                         }
1776                                 }
1777                                 break;
1778 #ifdef USE_NAPTR
1779                         case T_NAPTR:
1780 #ifdef NAPTR_CACHE_ALL_ARS
1781                                 if (*records)
1782                                                 dns_cache_mk_rd_entry2(*records);
1783 #else
1784                                 for (rr=e->rr_lst; rr && *records; rr=rr->next){
1785                                         if (naptr_get_sip_proto((struct naptr_rdata*)rr->rdata)>0){
1786                                                 tmp.s=((struct naptr_rdata*)rr->rdata)->repl;
1787                                                 tmp.len=((struct naptr_rdata*)rr->rdata)->repl_len;
1788                                                 t=dns_cache_mk_rd_entry(&tmp, T_SRV, records);
1789                                                 if (t){
1790                                                         if (*records)
1791                                                                 dns_get_related(t, T_SRV, records);
1792                                                         lst_end=t->prev; /* needed for clist_append*/
1793                                                         clist_append_sublist(l, t, lst_end, next, prev);
1794                                                 }
1795                                         }
1796                                 }
1797 #endif /* NAPTR_CACHE_ALL_ARS */
1798 #endif /* USE_NAPTR */
1799                                 break;
1800                         default:
1801                                 /* nothing extra */
1802                                 break;
1803                 }
1804         }else if ((e->type==T_CNAME) && (cname_chain_len<MAX_CNAME_CHAIN)){
1805                 /* only one cname is allowed (rfc2181), so we ignore
1806                  * the others (we take only the first one) */
1807                 tmp.s=((struct cname_rdata*)e->rr_lst->rdata)->name;
1808                 tmp.len=((struct cname_rdata*)e->rr_lst->rdata)->name_len;
1809                 t=dns_cache_mk_rd_entry(&tmp, type, records);
1810                 if (t){
1811                         if (*records){
1812                                 cname_chain_len++;
1813                                 ret=dns_get_related(t, type, records);
1814                                 cname_chain_len--;
1815                                 lst_end=t->prev;
1816                                 clist_append_sublist(l, t, lst_end, next, prev);
1817                         }else{
1818                                 /* if no more recs, but we found the orig. target anyway,
1819                                  *  return it (e.g. recs are only CNAME x & x A 1.2.3.4 or
1820                                  *  CNAME & SRV) */
1821                                 if (t->type==type)
1822                                         ret=t;
1823                                 clist_append(l, t, next, prev);
1824                         }
1825                 }
1826         }
1827         return ret;
1828 }
1829 #endif
1830
1831
1832
1833 /* calls the external resolver and populates the cache with the result
1834  * returns: 0 on error, pointer to hash entry on success
1835  * WARNING: make sure you use dns_hash_entry_put() when you're
1836  *  finished with the result)
1837  * */
1838 inline static struct dns_hash_entry* dns_cache_do_request(str* name, int type)
1839 {
1840         struct rdata* records;
1841         struct dns_hash_entry* e;
1842         struct dns_hash_entry* l;
1843         struct dns_hash_entry* r;
1844         struct dns_hash_entry* t;
1845         struct ip_addr* ip;
1846         str cname_val;
1847         char name_buf[MAX_DNS_NAME];
1848         struct dns_hash_entry* old;
1849         str rec_name;
1850         int add_record, h, err;
1851
1852         e=0;
1853         l=0;
1854         cname_val.s=0;
1855         old = NULL;
1856
1857 #ifdef USE_DNS_CACHE_STATS
1858         if (dns_cache_stats)
1859                 dns_cache_stats[process_no].dns_req_cnt++;
1860 #endif /* USE_DNS_CACHE_STATS */
1861
1862         if (type==T_A){
1863                 if (str2ip6(name)!=0)
1864                         goto end;
1865                 if ((ip=str2ip(name))!=0){
1866                                 e=dns_cache_mk_ip_entry(name, ip);
1867                                 if (likely(e))
1868                                         atomic_set(&e->refcnt, 1);/* because we ret. a ref. to it*/
1869                                 goto end; /* we do not cache obvious stuff */
1870                 }
1871         }
1872         else if (type==T_AAAA){
1873                 if (str2ip(name)!=0)
1874                         goto end;
1875                 if ((ip=str2ip6(name))!=0){
1876                                 e=dns_cache_mk_ip_entry(name, ip);
1877                                 if (likely(e))
1878                                         atomic_set(&e->refcnt, 1);/* because we ret. a ref. to it*/
1879                                 goto end;/* we do not cache obvious stuff */
1880                 }
1881         }
1882 #ifdef DNS_WATCHDOG_SUPPORT
1883         if (atomic_get(dns_servers_up)==0)
1884                 goto end; /* the servers are down, needless to perform the query */
1885 #endif
1886         if (name->len>=MAX_DNS_NAME){
1887                 LM_ERR("name too long (%d chars)\n", name->len);
1888                 goto end;
1889         }
1890         /* null terminate the string, needed by get_record */
1891         memcpy(name_buf, name->s, name->len);
1892         name_buf[name->len]=0;
1893         records=get_record(name_buf, type, RES_AR);
1894         if (records){
1895 #ifdef CACHE_RELEVANT_RECS_ONLY
1896                 e=dns_cache_mk_rd_entry(name, type, &records);
1897                 if (likely(e)){
1898                         l=e;
1899                         e=dns_get_related(l, type, &records);
1900                         /* e should contain the searched entry (if found) and l
1901                          * all the entries (e and related) */
1902                         if (likely(e)){
1903                                 atomic_set(&e->refcnt, 1); /* 1 because we return a
1904                                                                                                 ref. to it */
1905                         }else{
1906                                 /* e==0 => l contains a  cname list => we use the last
1907                                  * cname from the chain for a new resolve attempt (l->prev) */
1908                                 /* only one cname record is allowed (rfc2181), so we ignore
1909                                  * the others (we take only the first one) */
1910                                 cname_val.s=
1911                                         ((struct cname_rdata*)l->prev->rr_lst->rdata)->name;
1912                                 cname_val.len=
1913                                         ((struct cname_rdata*)l->prev->rr_lst->rdata)->name_len;
1914                                 LM_DBG("cname detected: %.*s (%d)\n",
1915                                                 cname_val.len, cname_val.s, cname_val.len);
1916                         }
1917                         /* add all the records to the hash */
1918                         l->prev->next=0; /* we break the double linked list for easier
1919                                                                 searching */
1920                         LOCK_DNS_HASH(); /* optimization */
1921                         for (r=l; r; r=t){
1922                                 t=r->next;
1923                                 /* add the new record to the cache by default */
1924                                 add_record = 1;
1925                                 if (cfg_get(core, core_cfg, dns_cache_rec_pref) > 0) {
1926                                         /* check whether there is an old record with the
1927                                          * same type in the cache */
1928                                         rec_name.s = r->name;
1929                                         rec_name.len = r->name_len;
1930                                         old = _dns_hash_find(&rec_name, r->type, &h, &err);
1931                                         if (old) {
1932                                                 if (old->type != r->type) {
1933                                                         /* probably CNAME found */
1934                                                         old = NULL;
1935
1936                                                 } else if (old->ent_flags & DNS_FLAG_PERMANENT) {
1937                                                         /* never overwrite permanent entries */
1938                                                         add_record = 0;
1939
1940                                                 } else if ((old->ent_flags & DNS_FLAG_BAD_NAME) == 0) {
1941                                                         /* Non-negative, non-permanent entry found with
1942                                                          * the same type. */
1943                                                         add_record =
1944                                                                 /* prefer new records */
1945                                                                 ((cfg_get(core, core_cfg, dns_cache_rec_pref) == 2)
1946                                                                 /* prefer the record with the longer lifetime */
1947                                                                 || ((cfg_get(core, core_cfg, dns_cache_rec_pref) == 3)
1948                                                                         && TICKS_LT(old->expire, r->expire)));
1949                                                 }
1950                                         }
1951                                 }
1952                                 if (add_record) {
1953                                         dns_cache_add_unsafe(r); /* refcnt++ inside */
1954                                         if (atomic_get(&r->refcnt)==0){
1955                                                 /* if cache adding failed and nobody else is interested
1956                                                  * destroy this entry */
1957                                                 dns_destroy_entry(r);
1958                                         }
1959                                         if (old) {
1960                                                 _dns_hash_remove(old);
1961                                                 old = NULL;
1962                                         }
1963                                 } else {
1964                                         if (old) {
1965                                                 if (r == e) {
1966                                                         /* this entry has to be returned */
1967                                                         e = old;
1968                                                         atomic_inc(&e->refcnt);
1969                                                 }
1970                                                 old = NULL;
1971                                         }
1972                                         dns_destroy_entry(r);
1973                                 }
1974                         }
1975                         UNLOCK_DNS_HASH();
1976                         /* if only cnames found => try to resolve the last one */
1977                         if (cname_val.s){
1978                                 LM_DBG("dns_get_entry(cname: %.*s (%d))\n",
1979                                                 cname_val.len, cname_val.s, cname_val.len);
1980                                 e=dns_get_entry(&cname_val, type);
1981                         }
1982                 }
1983 #else
1984                 l=dns_cache_mk_rd_entry2(records);
1985 #endif
1986                 free_rdata_list(records);
1987         }else if (cfg_get(core, core_cfg, dns_neg_cache_ttl)){
1988                 e=dns_cache_mk_bad_entry(name, type, 
1989                                 cfg_get(core, core_cfg, dns_neg_cache_ttl), DNS_FLAG_BAD_NAME);
1990                 if (likely(e)) {
1991                         atomic_set(&e->refcnt, 1); /* 1 because we return a ref. to it */
1992                         dns_cache_add(e); /* refcnt++ inside*/
1993                 }
1994                 goto end;
1995         }
1996 #ifndef CACHE_RELEVANT_RECS_ONLY
1997         if (l){
1998                 /* add all the records to the cache, but return only the record
1999                  * we are looking for */
2000                 l->prev->next=0; /* we break the double linked list for easier
2001                                                         searching */
2002                 LOCK_DNS_HASH(); /* optimization */
2003                 for (r=l; r; r=t){
2004                         t=r->next;
2005                         if (e==0){ /* no entry found yet */
2006                                 if (r->type==T_CNAME){
2007                                         if ((r->name_len==name->len) && (r->rr_lst) &&
2008                                                         (strncasecmp(r->name, name->s, name->len)==0)){
2009                                                 /* update the name with the name from the cname rec. */
2010                                                 cname_val.s=
2011                                                                 ((struct cname_rdata*)r->rr_lst->rdata)->name;
2012                                                 cname_val.len=
2013                                                         ((struct cname_rdata*)r->rr_lst->rdata)->name_len;
2014                                                 name=&cname_val;
2015                                         }
2016                                 }else if ((r->type==type) && (r->name_len==name->len) &&
2017                                                         (strncasecmp(r->name, name->s, name->len)==0)){
2018                                         e=r;
2019                                         atomic_set(&e->refcnt, 1); /* 1 because we return a ref.
2020                                                                                                   to it */
2021                                 }
2022                         }
2023
2024                         /* add the new record to the cache by default */
2025                         add_record = 1;
2026                         if (cfg_get(core, core_cfg, dns_cache_rec_pref) > 0) {
2027                                 /* check whether there is an old record with the
2028                                  * same type in the cache */
2029                                 rec_name.s = r->name;
2030                                 rec_name.len = r->name_len;
2031                                 old = _dns_hash_find(&rec_name, r->type, &h, &err);
2032                                 if (old) {
2033                                         if (old->type != r->type) {
2034                                                 /* probably CNAME found */
2035                                                 old = NULL;
2036
2037                                         } else if (old->ent_flags & DNS_FLAG_PERMANENT) {
2038                                                 /* never overwrite permanent entries */
2039                                                 add_record = 0;
2040
2041                                         } else if ((old->ent_flags & DNS_FLAG_BAD_NAME) == 0) {
2042                                                 /* Non-negative, non-permanent entry found with
2043                                                  * the same type. */
2044                                                 add_record =
2045                                                         /* prefer new records */
2046                                                         ((cfg_get(core, core_cfg, dns_cache_rec_pref) == 2)
2047                                                         /* prefer the record with the longer lifetime */
2048                                                         || ((cfg_get(core, core_cfg, dns_cache_rec_pref) == 3)
2049                                                                 && TICKS_LT(old->expire, r->expire)));
2050                                         }
2051                                 }
2052                         }
2053                         if (add_record) {
2054                                 dns_cache_add_unsafe(r); /* refcnt++ inside */
2055                                 if (atomic_get(&r->refcnt)==0){
2056                                         /* if cache adding failed and nobody else is interested
2057                                          * destroy this entry */
2058                                         dns_destroy_entry(r);
2059                                 }
2060                                 if (old) {
2061                                         _dns_hash_remove(old);
2062                                         old = NULL;
2063                                 }
2064                         } else {
2065                                 if (old) {
2066                                         if (r == e) {
2067                                                 /* this entry has to be returned */
2068                                                 e = old;
2069                                                 atomic_inc(&e->refcnt);
2070                                         }
2071                                         old = NULL;
2072                                 }
2073                                 dns_destroy_entry(r);
2074                         }
2075                 }
2076                 UNLOCK_DNS_HASH();
2077                 if ((e==0) && (cname_val.s)){ /* not found, but found a cname */
2078                         /* only one cname is allowed (rfc2181), so we ignore the
2079                          * others (we take only the first one) */
2080                         e=dns_get_entry(&cname_val, type);
2081                 }
2082         }
2083 #endif
2084 end:
2085         return e;
2086 }
2087
2088
2089
2090 /* tries to lookup (name, type) in the hash and if not found tries to make
2091  *  a dns request
2092  *  return: 0 on error, pointer to a dns_hash_entry on success
2093  *  WARNING: when not needed anymore dns_hash_put() must be called! */
2094 inline static struct dns_hash_entry* dns_get_entry(str* name, int type)
2095 {
2096         int h;
2097         struct dns_hash_entry* e;
2098         str cname_val;
2099         int err;
2100         static int rec_cnt=0; /* recursion protection */
2101
2102         e=0;
2103         if (rec_cnt>MAX_CNAME_CHAIN){
2104                 LM_WARN("CNAME chain too long or recursive CNAMEs (\"%.*s\")\n",
2105                                 name->len, name->s);
2106                 goto error;
2107         }
2108         rec_cnt++;
2109         e=dns_hash_get(name, type, &h, &err);
2110 #ifdef USE_DNS_CACHE_STATS
2111         if (e) {
2112                 if ((e->ent_flags & DNS_FLAG_BAD_NAME) && dns_cache_stats)
2113                         /* negative DNS cache hit */
2114                         dns_cache_stats[process_no].dc_neg_hits_cnt++;
2115                 else if (((e->ent_flags & DNS_FLAG_BAD_NAME) == 0)
2116                                 && dns_cache_stats
2117                 ) /* DNS cache hit */
2118                         dns_cache_stats[process_no].dc_hits_cnt++;
2119
2120                 if (dns_cache_stats)
2121                         dns_cache_stats[process_no].dns_req_cnt++;
2122         }
2123 #endif /* USE_DNS_CACHE_STATS */
2124
2125         if ((e==0) && ((err) || ((e=dns_cache_do_request(name, type))==0))){
2126                 goto error;
2127         }else if ((e->type==T_CNAME) && (type!=T_CNAME)){
2128                 /* cname found instead which couldn't be resolved with the cached
2129                  * info => try a dns request */
2130                 /* only one cname record is allowed (rfc2181), so we ignore
2131                  * the others (we take only the first one) */
2132                 cname_val.s= ((struct cname_rdata*)e->rr_lst->rdata)->name;
2133                 cname_val.len=((struct cname_rdata*)e->rr_lst->rdata)->name_len;
2134                 dns_hash_put(e); /* not interested in the cname anymore */
2135                 if ((e=dns_cache_do_request(&cname_val, type))==0)
2136                         goto error; /* could not resolve cname */
2137         }
2138         /* found */
2139         if ((e->rr_lst==0) || (e->ent_flags & DNS_FLAG_BAD_NAME)){
2140                 /* negative cache => not resolvable */
2141                 dns_hash_put(e);
2142                 e=0;
2143         }
2144 error:
2145         rec_cnt--;
2146         return e;
2147 }
2148
2149
2150
2151 /* gets the first non-expired record starting with record no
2152  * from the dns_hash_entry struct e
2153  * params:       e   - dns_hash_entry struct
2154  *               *no - it must contain the start record number (0 initially);
2155  *                      it will be filled with the returned record number
2156  *               now - current time/ticks value
2157  * returns pointer to the rr on success and sets no to the rr number
2158  *         0 on error and fills the error flags
2159         *
2160  * Example usage:
2161  * list all non-expired non-bad-marked ips for name:
2162  * e=dns_get_entry(name, T_A);
2163  * if (e){
2164  *    *no=0;
2165  *    now=get_ticks_raw();
2166  *    while(rr=dns_entry_get_rr(e, no, now){
2167  *       LM_DBG("address %d\n", *no);
2168  *       *no++;  ( get the next address next time )
2169  *     }
2170  *  }
2171  */
2172 inline static struct dns_rr* dns_entry_get_rr(  struct dns_hash_entry* e,
2173                                                                                          unsigned char* no, ticks_t now)
2174 {
2175         struct dns_rr* rr;
2176         int n;
2177 #ifdef DNS_WATCHDOG_SUPPORT
2178         int servers_up;
2179
2180         servers_up = atomic_get(dns_servers_up);
2181 #endif
2182
2183         for(rr=e->rr_lst, n=0;rr && (n<*no);rr=rr->next, n++);/* skip *no records*/
2184         for(;rr;rr=rr->next){
2185                 if (
2186 #ifdef DNS_WATCHDOG_SUPPORT
2187                         /* check the expiration time only when the servers are up */
2188                         servers_up &&
2189 #endif
2190                         ((e->ent_flags & DNS_FLAG_PERMANENT) == 0) &&
2191                         ((s_ticks_t)(now-rr->expire)>=0) /* expired rr */
2192                 )
2193                         continue;
2194                 /* everything is ok now */
2195                 *no=n;
2196                 return rr;
2197         }
2198         *no=n;
2199         return 0;
2200 }
2201
2202
2203 #ifdef DNS_SRV_LB
2204
2205 #define srv_reset_tried(p)      (*(p)=0)
2206 #define srv_marked(p, i)        (*(p)&(1UL<<(i)))
2207 #define srv_mark_tried(p, i)    \
2208         do{ \
2209                 (*(p)|=(1UL<<(i))); \
2210         }while(0)
2211
2212 #define srv_next_rr(n, f, i) srv_mark_tried(f, i)
2213
2214 /* returns a random number between 0 and max inclusive (0<=r<=max) */
2215 inline static unsigned dns_srv_random(unsigned max)
2216 {
2217         return fastrand_max(max);
2218 }
2219
2220 /* for a SRV record it will return the next entry to be tried according
2221  * to the RFC2782 server selection mechanism
2222  * params:
2223  *    e     is a dns srv hash entry
2224  *    no    is the start index of the current group (a group is a set of SRV
2225  *          rrs with the same priority)
2226  *    tried is a bitmap where the tried srv rrs of the same priority are
2227  *          marked
2228  *    now - current time/ticks value
2229  * returns pointer to the rr on success and sets no to the rr number
2230  *         0 on error and fills the error flags
2231  * WARNING: unlike dns_entry_get_rr() this will always return another
2232  *           another rr automatically (*no must not be incremented)
2233  *
2234  * Example usage:
2235  * list all non-expired, non-bad-marked, never tried before srv records
2236  * using the rfc2782 algo:
2237  * e=dns_get_entry(name, T_SRV);
2238  * if (e){
2239  *    no=0;
2240  *    srv_reset_tried(&tried);
2241  *    now=get_ticks_raw();
2242  *    while(rr=dns_srv_get_nxt_rr(e, &tried, &no, now){
2243  *       LM_DBG("address %d\n", *no);
2244  *     }
2245  *  }
2246  *
2247  */
2248 inline static struct dns_rr* dns_srv_get_nxt_rr(struct dns_hash_entry* e,
2249                                                                                          srv_flags_t* tried,
2250                                                                                          unsigned char* no, ticks_t now)
2251 {
2252 #define MAX_SRV_GRP_IDX         (sizeof(srv_flags_t)*8)
2253         struct dns_rr* rr;
2254         struct dns_rr* start_grp;
2255         int n;
2256         unsigned sum;
2257         unsigned prio;
2258         unsigned rand_w;
2259         int found;
2260         int saved_idx;
2261         int zero_weight; /* number of records with 0 weight */
2262         int i, idx;
2263         struct r_sums_entry{
2264                         unsigned r_sum;
2265                         struct dns_rr* rr;
2266                         }r_sums[MAX_SRV_GRP_IDX];
2267 #ifdef DNS_WATCHDOG_SUPPORT
2268         int servers_up;
2269
2270         servers_up = atomic_get(dns_servers_up);
2271 #endif
2272
2273         memset(r_sums, 0, sizeof(struct r_sums_entry) * MAX_SRV_GRP_IDX);
2274         rand_w=0;
2275         for(rr=e->rr_lst, n=0;rr && (n<*no);rr=rr->next, n++);/* skip *no records*/
2276
2277 retry:
2278         if (unlikely(rr==0))
2279                 goto no_more_rrs;
2280         start_grp=rr;
2281         prio=((struct srv_rdata*)start_grp->rdata)->priority;
2282         sum=0;
2283         saved_idx=-1;
2284         zero_weight = 0;
2285         found=0;
2286         for (idx=0;rr && (prio==((struct srv_rdata*)rr->rdata)->priority) &&
2287                                                 (idx < MAX_SRV_GRP_IDX); idx++, rr=rr->next){
2288                 if ((
2289 #ifdef DNS_WATCHDOG_SUPPORT
2290                         /* check the expiration time only when the servers are up */
2291                         servers_up &&
2292 #endif
2293                         ((e->ent_flags & DNS_FLAG_PERMANENT) == 0) &&
2294                         ((s_ticks_t)(now-rr->expire)>=0) /* expired entry */) ||
2295                                 (srv_marked(tried, idx)) ) /* already tried */{
2296                         r_sums[idx].r_sum=0; /* 0 sum, to skip over it */
2297                         r_sums[idx].rr=0;    /* debug: mark it as unused */
2298                         continue;
2299                 }
2300                 /* special case, 0 weight records should be "first":
2301                  * remember the first rr int the "virtual" list: A 0 weight must
2302                  *  come first if present, else get the first one */
2303                 if ((saved_idx==-1) || (((struct srv_rdata*)rr->rdata)->weight==0)){
2304                         saved_idx=idx;
2305                 }
2306                 zero_weight += (((struct srv_rdata*)rr->rdata)->weight == 0);
2307                 sum+=((struct srv_rdata*)rr->rdata)->weight;
2308                 r_sums[idx].r_sum=sum;
2309                 r_sums[idx].rr=rr;
2310                 found++;
2311         }
2312         if (found==0){
2313                 /* try in the next priority group */
2314                 n+=idx; /* next group start idx, last rr */
2315                 srv_reset_tried(tried);
2316                 goto retry;
2317         }else if ((found==1) || (sum==0) ||
2318                                 (((rand_w=(dns_srv_random(sum-1)+1))==1) && zero_weight &&
2319                                         (dns_srv_random(DNS_SRV_ZERO_W_CHANCE)==0))){
2320                 /* 1. if only one found, avoid a useless random() call
2321                       and select it (saved_idx will point to it).
2322                  * 2. if the sum of weights is 0 (all have 0 weight) or
2323                  * 3. rand_w==1 and there are records with 0 weight and
2324                  *    random(probab. of selecting a 0-weight)
2325                  *     immediately select a 0 weight record.
2326                  *  (this takes care of the 0-weight at the beginning requirement) */
2327                 i=saved_idx; /* saved idx contains either first 0 weight or first
2328                                                 valid record */
2329                 goto found;
2330         }
2331         /* if we are here => rand_w is not 0 and we have at least 2 valid options
2332          * => we can safely iterate on the whole r_sums[] whithout any other
2333          * extra checks */
2334         for (i=0; (i<idx) && (r_sums[i].r_sum<rand_w); i++);
2335 found:
2336 #ifdef DNS_CACHE_DEBUG
2337         LM_DBG("(%p, %lx, %d, %u): selected %d/%d in grp. %d"
2338                         " (rand_w=%d, rr=%p rd=%p p=%d w=%d rsum=%d)\n",
2339                 e, (unsigned long)*tried, *no, now, i, idx, n, rand_w, r_sums[i].rr,
2340                 (r_sums[i].rr)?r_sums[i].rr->rdata:0,
2341                 (r_sums[i].rr&&r_sums[i].rr->rdata)?((struct srv_rdata*)r_sums[i].rr->rdata)->priority:0,
2342                 (r_sums[i].rr&&r_sums[i].rr->rdata)?((struct srv_rdata*)r_sums[i].rr->rdata)->weight:0,
2343                 r_sums[i].r_sum);
2344 #endif
2345         /* i is the winner */
2346         *no=n; /* grp. start */
2347         srv_mark_tried(tried, i); /* mark it */
2348         return r_sums[i].rr;
2349 no_more_rrs:
2350         *no=n;
2351         return 0;
2352 }
2353 #endif /* DNS_SRV_LB */
2354
2355
2356
2357 /* gethostbyname compatibility: converts a dns_hash_entry structure
2358  * to a statical internal hostent structure
2359  * returns a pointer to the internal hostent structure on success or
2360  *          0 on error
2361  */
2362 inline static struct hostent* dns_entry2he(struct dns_hash_entry* e)
2363 {
2364         static struct hostent he;
2365         static char hostname[256];
2366         static char* p_aliases[1];
2367         static char* p_addr[DNS_HE_MAX_ADDR+1];
2368         static char address[16*DNS_HE_MAX_ADDR]; /* max 10 ipv6 addresses */
2369         int af, len;
2370         struct dns_rr* rr;
2371         unsigned char rr_no;
2372         unsigned char *ip;
2373         ticks_t now;
2374         int i;
2375
2376         switch(e->type){
2377                 case T_A:
2378                         af=AF_INET;
2379                         len=4;
2380                         break;
2381                 case T_AAAA:
2382                         af=AF_INET6;
2383                         len=16;
2384                         break;
2385                 default:
2386                         LM_CRIT("wrong entry type %d for %.*s\n",
2387                                         e->type, e->name_len, e->name);
2388                         return 0;
2389         }
2390
2391
2392         rr_no=0;
2393         now=get_ticks_raw();
2394         /* if the entry has already expired use the time at the end of lifetime */
2395         if (unlikely((s_ticks_t)(now-e->expire)>=0)) now=e->expire-1;
2396         rr=dns_entry_get_rr(e, &rr_no, now);
2397         for(i=0; rr && (i<DNS_HE_MAX_ADDR); i++,
2398                                                         rr=dns_entry_get_rr(e, &rr_no, now)){
2399                                 p_addr[i]=&address[i*len];
2400                                 switch(e->type){
2401                                         case T_A:
2402                                                 ip = ((struct a_rdata*)rr->rdata)->ip;
2403                                                 break;
2404                                         case T_AAAA:
2405                                                 ip = ((struct aaaa_rdata*)rr->rdata)->ip6;
2406                                                 break;
2407                                         default:
2408                                                 LM_CRIT("wrong entry type %d for %.*s\n",
2409                                                         e->type, e->name_len, e->name);
2410                                                 return 0;
2411                                 }
2412                                 memcpy(p_addr[i], ip, len);
2413         }
2414         if (i==0){
2415                 LM_DBG("no good records found (%d) for %.*s (%d)\n",
2416                                 rr_no, e->name_len, e->name, e->type);
2417                 return 0; /* no good record found */
2418         }
2419
2420         p_addr[i]=0; /* mark the end of the addresses */
2421         p_aliases[0]=0; /* no aliases */
2422         memcpy(hostname, e->name, e->name_len);
2423         hostname[e->name_len]=0;
2424
2425         he.h_addrtype=af;
2426         he.h_length=len;
2427         he.h_addr_list=p_addr;
2428         he.h_aliases=p_aliases;
2429         he.h_name=hostname;
2430
2431         return &he;
2432 }
2433
2434
2435
2436 /* gethostbyname compatibility: performs an a_lookup and returns a pointer
2437  * to a statical internal hostent structure
2438  * returns 0 on success, <0 on error (see the error codes)
2439  */
2440 inline static struct hostent* dns_a_get_he(str* name)
2441 {
2442         struct dns_hash_entry* e;
2443         struct ip_addr* ip;
2444         struct hostent* he;
2445
2446         e=0;
2447         if (str2ip6(name)!=0)
2448                 return 0;
2449         if ((ip=str2ip(name))!=0){
2450                 return ip_addr2he(name, ip);
2451         }
2452         if ((e=dns_get_entry(name, T_A))==0)
2453                 return 0;
2454         /* found */
2455         he=dns_entry2he(e);
2456         dns_hash_put(e);
2457         return he;
2458 }
2459
2460
2461 /* gethostbyname compatibility: performs an aaaa_lookup and returns a pointer
2462  * to a statical internal hostent structure
2463  * returns 0 on success, <0 on error (see the error codes)
2464  */
2465 inline static struct hostent* dns_aaaa_get_he(str* name)
2466 {
2467         struct dns_hash_entry* e;
2468         struct ip_addr* ip;
2469         struct hostent* he;
2470
2471         e=0;
2472         if (str2ip(name)!=0)
2473                 return 0;
2474         if ((ip=str2ip6(name))!=0){
2475                 return ip_addr2he(name, ip);
2476         }
2477         if ((e=dns_get_entry(name, T_AAAA))==0)
2478                         return 0;
2479         /* found */
2480         he=dns_entry2he(e);
2481         dns_hash_put(e);
2482         return he;
2483 }
2484
2485
2486
2487 /* returns 0 on success, -1 on error (rr type does not contain an ip) */
2488 inline static int dns_rr2ip(int type, struct dns_rr* rr, struct ip_addr* ip)
2489 {
2490         switch(type){
2491                 case T_A:
2492                         ip->af=AF_INET;
2493                         ip->len=4;
2494                         memcpy(ip->u.addr, ((struct a_rdata*)rr->rdata)->ip, 4);
2495                         return 0;
2496                         break;
2497                 case T_AAAA:
2498                         ip->af=AF_INET6;
2499                         ip->len=16;
2500                         memcpy(ip->u.addr, ((struct aaaa_rdata*)rr->rdata)->ip6, 16);
2501                         return 0;
2502                         break;
2503         }
2504         return -1;
2505 }
2506
2507
2508
2509 /* gethostbyname compatibility:
2510  * performs an a or aaaa dns lookup, returns 0 on error and a pointer to a
2511  *          static hostent structure on success
2512  *  flags:  - none set: tries first an a_lookup and if it fails an aaaa_lookup
2513  *          - DNS_IPV6_FIRST: tries first an aaaa_lookup and then an a_lookup
2514  *          - DNS_IPV4_ONLY: tries only an a_lookup
2515  *          - DNS_IPV6_ONLY: tries only an aaaa_lookup
2516  */
2517 struct hostent* dns_get_he(str* name, int flags)
2518 {
2519         struct hostent* he;
2520
2521         if ((flags&(DNS_IPV6_FIRST|DNS_IPV6_ONLY))){
2522                 he=dns_aaaa_get_he(name);
2523                 if (he) return he;
2524         }else{
2525                 he=dns_a_get_he(name);
2526                 if (he) return he;
2527         }
2528         if (flags&DNS_IPV6_FIRST){
2529                 he=dns_a_get_he(name);
2530         }else if (!(flags&(DNS_IPV6_ONLY|DNS_IPV4_ONLY))){
2531                 he=dns_aaaa_get_he(name);
2532         }
2533         return he;
2534 }
2535
2536
2537
2538 /* sip_resolvehost helper: gets the first good  hostent/port combination
2539  * returns 0 on error, pointer to static hostent structure on success
2540  *           (and sets port)*/
2541 struct hostent* dns_srv_get_he(str* name, unsigned short* port, int flags)
2542 {
2543         struct dns_hash_entry* e;
2544         struct dns_rr* rr;
2545         str rr_name;
2546         struct hostent* he;
2547         ticks_t now;
2548         unsigned char rr_no;
2549
2550         rr=0;
2551         he=0;
2552         now=get_ticks_raw();
2553         if ((e=dns_get_entry(name, T_SRV))==0)
2554                         goto error;
2555         /* look inside the RRs for a good one (not expired or marked bad)  */
2556         rr_no=0;
2557         while( (rr=dns_entry_get_rr(e, &rr_no, now))!=0){
2558                 /* everything is ok now, we can try to resolve the ip */
2559                 rr_name.s=((struct srv_rdata*)rr->rdata)->name;
2560                 rr_name.len=((struct srv_rdata*)rr->rdata)->name_len;
2561                 if ((he=dns_get_he(&rr_name, flags))!=0){
2562                                 /* success, at least one good ip found */
2563                                 if(port) *port=((struct srv_rdata*)rr->rdata)->port;
2564                                 goto end;
2565                 }
2566                 rr_no++; /* try from the next record, the current one was not good */
2567         }
2568         /* if we reach this point => error, we couldn't find any good rr */
2569 end:
2570         if (e) dns_hash_put(e);
2571 error:
2572         return he;
2573 }
2574
2575
2576
2577 struct hostent* dns_resolvehost(char* name)
2578 {
2579         str host;
2580         struct hostent* ret;
2581         if ((cfg_get(core, core_cfg, use_dns_cache)==0) || (dns_hash==0)){ /* not init yet */
2582                 ret =  _resolvehost(name);
2583                 if(unlikely(!ret)){
2584                         /* increment dns error counter */
2585                         if(counters_initialized())
2586                                 counter_inc(dns_cnts_h.failed_dns_req);
2587                 }
2588                 return ret;
2589         }
2590         host.s=name;
2591         host.len=strlen(name);
2592         return dns_get_he(&host, dns_flags);
2593 }
2594
2595
2596
2597
2598 #if 0
2599 /* resolves a host name trying  NAPTR,  SRV, A & AAAA lookups, for details
2600  *  see dns_sip_resolve()
2601  *  FIXME: this version will return only the first ip
2602  * returns: hostent struct & *port filled with the port from the SRV record;
2603  *  0 on error
2604  */
2605 struct hostent* dns_sip_resolvehost(str* name, unsigned short* port,
2606                                                                                 char* proto)
2607 {
2608         struct dns_srv_handle h;
2609         struct ip_addr ip;
2610         int ret;
2611
2612         if ((cfg_get(core, core_cfg, use_dns_cache==0)) || (dns_hash==0)){
2613                 /* not init or off => use normal, non-cached version */
2614                 return _sip_resolvehost(name, port, proto);
2615         }
2616         dns_srv_handle_init(&h);
2617         ret=dns_sip_resolve(&h, name, &ip, port, proto, dns_flags);
2618         dns_srv_handle_put(&h);
2619         if (ret>=0)
2620                 return ip_addr2he(name, &ip);
2621         return 0;
2622 }
2623 #endif
2624
2625
2626
2627 /* resolves a host name trying SRV lookup if *port==0 or normal A/AAAA lookup
2628  * if *port!=0.
2629  * when performing SRV lookup (*port==0) it will use proto to look for
2630  * tcp or udp hosts, otherwise proto is unused; if proto==0 => no SRV lookup
2631  * returns: hostent struct & *port filled with the port from the SRV record;
2632  *  0 on error
2633  */
2634 struct hostent* dns_srv_sip_resolvehost(str* name, unsigned short* port,
2635                                                                                 char* proto)
2636 {
2637         struct hostent* he;
2638         struct ip_addr* ip;
2639         static char tmp[MAX_DNS_NAME]; /* tmp. buff. for SRV lookups */
2640         str srv_name;
2641         char srv_proto;
2642
2643         if ((cfg_get(core, core_cfg, use_dns_cache)==0) || (dns_hash==0)){
2644                 /* not init or off => use normal, non-cached version */
2645                 return _sip_resolvehost(name, port, proto);
2646         }
2647         if (proto){ /* makes sure we have a protocol set*/
2648                 if (*proto==0)
2649                         *proto=srv_proto=PROTO_UDP; /* default */
2650                 else
2651                         srv_proto=*proto;
2652         }else{
2653                 srv_proto=PROTO_UDP;
2654         }
2655         /* try SRV if no port specified (draft-ietf-sip-srv-06) */
2656         if ((port)&&(*port==0)){
2657                 *port=(srv_proto==PROTO_TLS)?SIPS_PORT:SIP_PORT; /* just in case we
2658                                                                                                                  don't find another */
2659                 if ((name->len+SRV_MAX_PREFIX_LEN+1)>MAX_DNS_NAME){
2660                         LM_WARN("domain name too long (%d), unable to perform SRV lookup\n",
2661                                                 name->len);
2662                 }else{
2663                         /* check if it's an ip address */
2664                         if ( ((ip=str2ip(name))!=0)
2665                                   || ((ip=str2ip6(name))!=0)
2666                                 ){
2667                                 /* we are lucky, this is an ip address */
2668                                 return ip_addr2he(name,ip);
2669                         }
2670
2671                         if(srv_proto==PROTO_WS || srv_proto==PROTO_WSS) {
2672                                 /* no srv records for web sockets */
2673                                 return 0;
2674                         }
2675
2676                         switch(srv_proto){
2677                                 case PROTO_UDP:
2678                                 case PROTO_TCP:
2679                                 case PROTO_TLS:
2680                                 case PROTO_SCTP:
2681                                         create_srv_name(srv_proto, name, tmp);
2682                                         break;
2683                                 default:
2684                                         LM_CRIT("unknown proto %d\n", (int)srv_proto);
2685                                         return 0;
2686                         }
2687
2688                         srv_name.s=tmp;
2689                         srv_name.len=strlen(tmp);
2690                         if ((he=dns_srv_get_he(&srv_name, port, dns_flags))!=0)
2691                                 return he;
2692                 }
2693         }
2694 /*skip_srv:*/
2695         if (name->len >= MAX_DNS_NAME) {
2696                 LM_ERR("domain name too long\n");
2697                 return 0;
2698         }
2699         he=dns_get_he(name, dns_flags);
2700         return he;
2701 }
2702
2703
2704
2705 #ifdef USE_NAPTR
2706 /* iterates over a naptr rr list, returning each time a "good" naptr record
2707  * is found.( srv type, no regex and a supported protocol)
2708  * params:
2709  *         naptr_head - naptr dns_rr list head
2710  *         tried      - bitmap used to keep track of the already tried records
2711  *                      (no more then sizeof(tried)*8 valid records are
2712  *                      ever walked
2713  *         srv_name   - if succesfull, it will be set to the selected record
2714  *                      srv name (naptr repl.)
2715  *         proto      - if succesfull it will be set to the selected record
2716  *                      protocol
2717  * returns  0 if no more records found or a pointer to the selected record
2718  *  and sets  protocol and srv_name
2719  * WARNING: when calling first time make sure you run first
2720  *           naptr_iterate_init(&tried)
2721  */
2722 struct naptr_rdata* dns_naptr_sip_iterate(struct dns_rr* naptr_head,
2723                                                                                         naptr_bmp_t* tried,
2724                                                                                         str* srv_name, char* proto)
2725 {
2726         int i, idx;
2727         struct dns_rr* l;
2728         struct naptr_rdata* naptr;
2729         struct naptr_rdata* naptr_saved;
2730         char saved_proto;
2731         char naptr_proto;
2732
2733         idx=0;
2734         naptr_proto=PROTO_NONE;
2735         naptr_saved=0;
2736         saved_proto=0;
2737         i=0;
2738         for(l=naptr_head; l && (i<MAX_NAPTR_RRS); l=l->next){
2739                 naptr=(struct naptr_rdata*) l->rdata;
2740                 if (naptr==0){
2741                         LM_CRIT("null rdata\n");
2742                         goto end;
2743                 }
2744                 /* check if valid and get proto */
2745                 if ((naptr_proto=naptr_get_sip_proto(naptr))<=0) continue;
2746                 if (*tried& (1<<i)){
2747                         i++;
2748                         continue; /* already tried */
2749                 }
2750 #ifdef DNS_CACHE_DEBUG
2751                 LM_DBG("found a valid sip NAPTR rr %.*s, proto %d\n",
2752                                 naptr->repl_len, naptr->repl, (int)naptr_proto);
2753 #endif
2754                 if ((naptr_proto_supported(naptr_proto))){
2755                         if (naptr_choose(&naptr_saved, &saved_proto,
2756                                                                 naptr, naptr_proto))
2757                                 idx=i;
2758                         }
2759                 i++;
2760         }
2761         if (naptr_saved){
2762                 /* found something */
2763 #ifdef DNS_CACHE_DEBUG
2764                 LM_DBG("choosed NAPTR rr %.*s, proto %d tried: 0x%x\n",
2765                         naptr_saved->repl_len, naptr_saved->repl, (int)saved_proto, *tried);
2766 #endif
2767                 *tried|=1<<idx;
2768                 *proto=saved_proto;
2769                 srv_name->s=naptr_saved->repl;
2770                 srv_name->len=naptr_saved->repl_len;
2771                 return naptr_saved;
2772         }
2773 end:
2774         return 0;
2775 }
2776
2777
2778
2779 /* resolves a host name trying NAPTR lookup if *proto==0 and *port==0, SRV
2780  * lookup if *port==0 or normal A/AAAA lookup
2781  * if *port!=0.
2782  * when performing SRV lookup (*port==0) it will use proto to look for
2783  * tcp or udp hosts; if proto==0 => no SRV lookup
2784  * returns: hostent struct & *port filled with the port from the SRV record;
2785  *  0 on error
2786  */
2787 struct hostent* dns_naptr_sip_resolvehost(str* name, unsigned short* port,
2788                                                                                 char* proto)
2789 {
2790         struct hostent* he;
2791         struct ip_addr* tmp_ip;
2792         naptr_bmp_t tried_bmp;
2793         struct dns_hash_entry* e;
2794         char n_proto;
2795         char origproto;
2796         str srv_name;
2797
2798         if(proto) {
2799                 origproto=*proto;
2800         } else {
2801                 origproto=PROTO_NONE;
2802         }
2803         he=0;
2804         if (dns_hash==0){ /* not init => use normal, non-cached version */
2805                 LM_WARN("called before dns cache initialization\n");
2806                 return _sip_resolvehost(name, port, proto);
2807         }
2808         if (proto && port && (*proto==0) && (*port==0)){
2809                 *proto=PROTO_UDP; /* just in case we don't find another */
2810                 /* check if it's an ip address */
2811                 if ( ((tmp_ip=str2ip(name))!=0)
2812                           || ((tmp_ip=str2ip6(name))!=0)
2813                         ){
2814                         /* we are lucky, this is an ip address */
2815                         if (((dns_flags&DNS_IPV4_ONLY) && (tmp_ip->af==AF_INET6))||
2816                                 ((dns_flags&DNS_IPV6_ONLY) && (tmp_ip->af==AF_INET))){
2817                                 return 0;
2818                         }
2819                         *port=SIP_PORT;
2820                         return ip_addr2he(name, tmp_ip);
2821                 }
2822                 /* do naptr lookup */
2823                 if ((e=dns_get_entry(name, T_NAPTR))==0)
2824                         goto naptr_not_found;
2825                 naptr_iterate_init(&tried_bmp);
2826                 while(dns_naptr_sip_iterate(e->rr_lst, &tried_bmp,
2827                                                                                                 &srv_name, &n_proto)){
2828                         if ((he=dns_srv_get_he(&srv_name, port, dns_flags))!=0){
2829 #ifdef DNS_CACHE_DEBUG
2830                                 LM_DBG("(%.*s, %d, %d) srv, ret=%p\n",
2831                                                         name->len, name->s, (int)*port, (int)*proto, he);
2832 #endif
2833                                 dns_hash_put(e);
2834                                 *proto=n_proto;
2835                                 return he;
2836                         }
2837                 }
2838                 /* no acceptable naptr record found, fallback to srv */
2839                 dns_hash_put(e);
2840         }
2841 naptr_not_found:
2842         if(proto) *proto = origproto;
2843         he = no_naptr_srv_sip_resolvehost(name,port,proto);
2844         /* fallback all the way down to A/AAAA */
2845         if (he==0) {
2846                 he=dns_get_he(name,dns_flags);
2847         }
2848    return he;
2849 }
2850 #endif /* USE_NAPTR */
2851
2852
2853
2854 /* resolves a host name trying NAPTR lookup if *proto==0 and *port==0, SRV
2855  * lookup if *port==0 or normal A/AAAA lookup
2856  * if *port!=0.
2857  * when performing SRV lookup (*port==0) it will use proto to look for
2858  * tcp or udp hosts; if proto==0 => no SRV lookup
2859  * returns: hostent struct & *port filled with the port from the SRV record;
2860  *  0 on error
2861  */
2862 struct hostent* dns_sip_resolvehost(str* name, unsigned short* port,
2863                                                                                 char* proto)
2864 {
2865 #ifdef USE_NAPTR
2866         if (dns_flags&DNS_TRY_NAPTR)
2867                 return dns_naptr_sip_resolvehost(name, port, proto);
2868 #endif
2869         return dns_srv_sip_resolvehost(name, port, proto);
2870 }
2871
2872
2873
2874 /* performs an a lookup, fills the dns_entry pointer and the ip addr.
2875  *  (with the first good ip). if *e ==0 does the a lookup, and changes it
2876  *   to the result, if not it uses the current value and tries to use
2877  *   the rr_no record from it.
2878  * params:  e - must contain the "in-use" dns_hash_entry pointer (from
2879  *               a previous call) or *e==0 (for the first call)
2880  *          name - host name for which we do the lookup (required only
2881  *                  when *e==0)
2882  *          ip   - will be filled with the first good resolved ip started
2883  *                 at *rr_no
2884  *          rr_no - record number to start searching for a good ip from
2885  *                  (e.g. value from previous call + 1), filled on return
2886  *                  with the number of the record corresponding to the
2887  *                  returned ip
2888  * returns 0 on success, <0 on error (see the error codes),
2889  *         fills e, ip and rr_no
2890  *          On end of records (when used to iterate on all the ips) it
2891  *          will return E_DNS_EOR (you should not log an error for this
2892  *          value, is just a signal that the address list end has been reached)
2893  * Note: either e or name must be different from 0 (name.s !=0 also)
2894  * WARNING: dns_hash_put(*e) must be called when you don't need
2895  *          the entry anymore and *e!=0 (failling to do so => mem. leak)
2896  * Example:
2897  *  dns_entry=0;
2898  *  ret=dns_a_get_ip(&dns_entry, name, &ip, &rr_no);  -- get the first rr.
2899  *  ...
2900  *  rr_no++;
2901  *  while((ret>=0) && dns_entry)
2902  *     dns_a_get_ip(&dns_entry, name, &ip, &rr_no); -- get the next rr
2903  *   if (ret!=-E_DNS_EOR) ERROR(....);
2904  *  ...
2905  *  dns_hash_put(dns_entry); -- finished with the entry
2906  */
2907 inline static int dns_a_resolve( struct dns_hash_entry** e,
2908                                                                  unsigned char* rr_no,
2909                                                                  str* name,
2910                                                                  struct ip_addr* ip)
2911 {
2912         struct dns_rr* rr;
2913         int ret;
2914         ticks_t now;
2915         struct ip_addr* tmp;
2916
2917         rr=0;
2918         ret=-E_DNS_NO_IP;
2919         if (*e==0){ /* do lookup */
2920                 /* if ip don't set *e */
2921                 if (str2ip6(name)!=0)
2922                         goto error;
2923                 if ((tmp=str2ip(name))!=0){
2924                         *ip=*tmp;
2925                         *rr_no=0;
2926                         return 0;
2927                 }
2928                 if ((*e=dns_get_entry(name, T_A))==0)
2929                         goto error;
2930                 /* found */
2931                 *rr_no=0;
2932                 ret=-E_DNS_BAD_IP_ENTRY;
2933         }
2934         now=get_ticks_raw();
2935         /* if the entry has already expired use the time at the end of lifetime */
2936         if (unlikely((s_ticks_t)(now-(*e)->expire)>=0)) now=(*e)->expire-1;
2937         rr=dns_entry_get_rr(*e, rr_no, now);
2938         if (rr){
2939                 /* everything is ok now, we can try to "convert" the ip */
2940                 dns_rr2ip((*e)->type, rr, ip);
2941                 ret=0;
2942         }else{
2943                 ret=-E_DNS_EOR;
2944         }
2945 error:
2946         LM_DBG("(%.*s, %d) returning %d\n", name->len, name->s, *rr_no, ret);
2947         return ret;
2948 }
2949
2950
2951 /* lookup, fills the dns_entry pointer and the ip addr.
2952  *  (with the first good ip). if *e ==0 does the a lookup, and changes it
2953  *   to the result, if not it uses the current value and tries to use
2954  * Same as dns_a_resolve but for aaaa records (see above).
2955  */
2956 inline static int dns_aaaa_resolve( struct dns_hash_entry** e,
2957                                                                         unsigned char* rr_no,
2958                                                                         str* name,
2959                                                                         struct ip_addr* ip)
2960 {
2961         struct dns_rr* rr;
2962         int ret;
2963         ticks_t now;
2964         struct ip_addr* tmp;
2965
2966         rr=0;
2967         ret=-E_DNS_NO_IP;
2968         if (*e==0){ /* do lookup */
2969                 /* if ip don't set *e */
2970                 if (str2ip(name)!=0)
2971                         goto error;
2972                 if ((tmp=str2ip6(name))!=0){
2973                         *ip=*tmp;
2974                         *rr_no=0;
2975                         return 0;
2976                 }
2977                 if ((*e=dns_get_entry(name, T_AAAA))==0)
2978                         goto error;
2979                 /* found */
2980                 *rr_no=0;
2981                 ret=-E_DNS_BAD_IP_ENTRY;
2982         }
2983         now=get_ticks_raw();
2984         /* if the entry has already expired use the time at the end of lifetime */
2985         if (unlikely((s_ticks_t)(now-(*e)->expire)>=0)) now=(*e)->expire-1;
2986         rr=dns_entry_get_rr(*e, rr_no, now);
2987         if (rr){
2988                 /* everything is ok now, we can try to "convert" the ip */
2989                 dns_rr2ip((*e)->type, rr, ip);
2990                 ret=0;
2991         }else{
2992                 ret=-E_DNS_EOR; /* no more records */
2993         }
2994 error:
2995         return ret;
2996 }
2997
2998
2999
3000 /* performs an a or aaaa dns lookup, returns <0 on error (see the
3001  *  dns error codes) and 0 on success
3002  *  flags:  - none set: tries first an a_lookup and if it fails an aaaa_lookup
3003  *          - DNS_IPV6_FIRST: tries first an aaaa_lookup and then an a_lookup
3004  *          - DNS_IPV4_ONLY: tries only an a_lookup
3005  *          - DNS_IPV6_ONLY: tries only an aaaa_lookup
3006  *  see dns_a_resolve() for the rest of the params., examples a.s.o
3007  *  WARNING: don't forget dns_hash_put(*e) when e is not needed anymore
3008  */
3009 inline static int dns_ip_resolve(       struct dns_hash_entry** e,
3010                                                                         unsigned char* rr_no,
3011                                                                         str* name,
3012                                                                         struct ip_addr* ip,
3013                                                                         int flags)
3014 {
3015         int ret, orig_ret;
3016         str host;
3017         struct dns_hash_entry* orig;
3018
3019         ret=-E_DNS_NO_IP;
3020         if (*e==0){ /* first call */
3021                 if ((flags&(DNS_IPV6_FIRST|DNS_IPV6_ONLY))){
3022                         ret=dns_aaaa_resolve(e, rr_no, name, ip);
3023                         if (ret>=0) return ret;
3024                 }else{
3025                         ret=dns_a_resolve(e, rr_no, name, ip);
3026                         if (ret>=0) return ret;
3027                 }
3028                 if (flags&DNS_IPV6_FIRST){
3029                         ret=dns_a_resolve(e, rr_no, name, ip);
3030                 }else if (!(flags&(DNS_IPV6_ONLY|DNS_IPV4_ONLY))){
3031                         ret=dns_aaaa_resolve(e, rr_no, name, ip);
3032                 }
3033         }else if ((*e)->type==T_A){
3034                 /* continue A resolving */
3035                 /* retrieve host name from the hash entry  (ignore name which might
3036                   be null when continuing a srv lookup) */
3037                 host.s=(*e)->name;
3038                 host.len=(*e)->name_len;
3039                 ret=dns_a_resolve(e, rr_no, &host, ip);
3040                 if (ret>=0) return ret;
3041                 if (!(flags&(DNS_IPV6_ONLY|DNS_IPV6_FIRST|DNS_IPV4_ONLY))){
3042                         /* not found, try with AAAA */
3043                         orig_ret=ret;
3044                         orig=*e;
3045                         *e=0;
3046                         *rr_no=0;
3047                         ret=dns_aaaa_resolve(e, rr_no, &host, ip);
3048                         if (ret==-E_DNS_NO_IP && orig_ret==-E_DNS_EOR)
3049                                 ret=orig_ret;
3050                         /* delay original record release until we're finished with host*/
3051                         dns_hash_put(orig);
3052                 }
3053         }else if ((*e)->type==T_AAAA){
3054                 /* retrieve host name from the hash entry  (ignore name which might
3055                   be null when continuing a srv lookup) */
3056                 host.s=(*e)->name;
3057                 host.len=(*e)->name_len;
3058                 /* continue AAAA resolving */
3059                 ret=dns_aaaa_resolve(e, rr_no, &host, ip);
3060                 if (ret>=0) return ret;
3061                 if ((flags&DNS_IPV6_FIRST) && !(flags&DNS_IPV6_ONLY)){
3062                         /* not found, try with A */
3063                         orig_ret=ret;
3064                         orig=*e;
3065                         *e=0;
3066                         *rr_no=0;
3067                         ret=dns_a_resolve(e, rr_no, &host, ip);
3068                         if (ret==-E_DNS_NO_IP && orig_ret==-E_DNS_EOR)
3069                                 ret=orig_ret;
3070                         /* delay original record release until we're finished with host*/
3071                         dns_hash_put(orig);
3072                 }
3073         }else{
3074                 LM_CRIT("invalid record type %d\n", (*e)->type);
3075         }
3076         return ret;
3077 }
3078
3079
3080
3081 /*  gets the first srv record starting at rr_no
3082  *  Next call will return the next record a.s.o.
3083  *  (similar to dns_a_resolve but for srv, sets host, port and automatically
3084  *   switches to the next record in the future)
3085  *
3086  *   if DNS_SRV_LB and tried!=NULL will do random weight based selection
3087  *   for choosing between SRV RRs with the same priority (as described in
3088  *    RFC2782).
3089  *   If tried==NULL or DNS_SRV_LB is not defined => always returns next
3090  *    record in the priority order and for records with the same priority
3091  *     the record with the higher weight (from the remaining ones)
3092  */
3093 inline static int dns_srv_resolve_nxt(struct dns_hash_entry** e,
3094 #ifdef DNS_SRV_LB
3095                                                 srv_flags_t* tried,
3096 #endif
3097                                                 unsigned char* rr_no,
3098                                                 str* name, str* host, unsigned short* port)
3099 {
3100         struct dns_rr* rr;
3101         int ret;
3102         ticks_t now;
3103
3104         rr=0;
3105         ret=-E_DNS_NO_SRV;
3106         if (*e==0){
3107                 if ((*e=dns_get_entry(name, T_SRV))==0)
3108                         goto error;
3109                 /* found it */
3110                 *rr_no=0;
3111 #ifdef DNS_SRV_LB
3112                 if (tried)
3113                         srv_reset_tried(tried);
3114 #endif
3115                 ret=-E_DNS_BAD_SRV_ENTRY;
3116         }
3117         now=get_ticks_raw();
3118         /* if the entry has already expired use the time at the end of lifetime */
3119         if (unlikely((s_ticks_t)(now-(*e)->expire)>=0)) now=(*e)->expire-1;
3120 #ifdef DNS_SRV_LB
3121         if (tried){
3122                 rr=dns_srv_get_nxt_rr(*e, tried, rr_no, now);
3123         }else
3124 #endif
3125         {
3126                 rr=dns_entry_get_rr(*e, rr_no, now);
3127                 (*rr_no)++; /* try next record next time */
3128         }
3129         if (rr){
3130                 host->s=((struct srv_rdata*)rr->rdata)->name;
3131                 host->len=((struct srv_rdata*)rr->rdata)->name_len;
3132                 *port=((struct srv_rdata*)rr->rdata)->port;
3133                 ret=0;
3134         }else{
3135                 ret=-E_DNS_EOR; /* no more records */
3136         }
3137 error:
3138         return ret;
3139 }
3140
3141
3142
3143 /*  gets the first srv record starting at h->srv_no, resolve it
3144  *   and get the first ip address (starting at h->ip_no)
3145  *  (similar to dns_a_resolve but for srv, sets host, port)
3146  *  WARNING: don't forget to init h prior to calling this function the first
3147  *   time and dns_srv_handle_put(h), even if error is returned
3148  */
3149 inline static int dns_srv_resolve_ip(struct dns_srv_handle* h,
3150                                         str* name, struct ip_addr* ip, unsigned short* port,
3151                                         int flags)
3152 {
3153         int ret;
3154         str host;
3155
3156         host.len=0;
3157         host.s=0;
3158         do{
3159                 if (h->a==0){
3160 #ifdef DNS_SRV_LB
3161                         if ((ret=dns_srv_resolve_nxt(&h->srv,
3162                                                                 (flags & DNS_SRV_RR_LB)?&h->srv_tried_rrs:0,
3163                                                                 &h->srv_no,
3164                                                                 name, &host, port))<0)
3165                                 goto error;
3166 #else
3167                         if ((ret=dns_srv_resolve_nxt(&h->srv, &h->srv_no,
3168                                                                 name, &host, port))<0)
3169                                 goto error;
3170 #endif
3171                         h->port=*port; /* store new port */
3172                 }else{
3173                         *port=h->port; /* return the stored port */
3174                 }
3175                 if ((ret=dns_ip_resolve(&h->a, &h->ip_no, &host, ip, flags))<0){
3176                         /* couldn't find any good ip for this record, try the next one */
3177                         if (h->a){
3178                                 dns_hash_put(h->a);
3179                                 h->a=0;
3180                         }
3181                 }else if (h->a==0){
3182                         /* this was an ip, try the next srv record in the future */
3183                 }
3184         }while(ret<0);
3185 error:
3186 #ifdef DNS_CACHE_DEBUG
3187         LM_DBG("(\"%.*s\", %d, %d), ret=%d, ip=%s\n",
3188                         name->len, name->s, h->srv_no, h->ip_no, ret,
3189                         ip?ZSW(ip_addr2a(ip)):"");
3190 #endif
3191         return ret;
3192 }
3193
3194
3195
3196 /* resolves a host name trying SRV lookup if *port==0 or normal A/AAAA lookup
3197  * if *port!=0.
3198  * when performing SRV lookup (*port==0) it will use proto to look for
3199  * tcp or udp hosts, otherwise proto is unused; if proto==0 => no SRV lookup
3200  * h must be initialized prior to  calling this function and can be used to
3201  * get the subsequent ips
3202  * returns:  <0 on error
3203  *            0 on success and it fills *ip, *port, *h
3204  */
3205 inline static int dns_srv_sip_resolve(struct dns_srv_handle* h,  str* name,
3206                                                 struct ip_addr* ip, unsigned short* port, char* proto,
3207                                                 int flags)
3208 {
3209         struct dns_srv_proto srv_proto_list[PROTO_LAST];
3210         static char tmp[MAX_DNS_NAME]; /* tmp. buff. for SRV lookups */
3211         str srv_name;
3212         struct ip_addr* tmp_ip;
3213         int ret;
3214         struct hostent* he;
3215         size_t i,list_len;
3216         char origproto = 0;
3217
3218         if(proto) origproto = *proto;
3219         if (dns_hash==0){ /* not init => use normal, non-cached version */
3220                 LM_WARN("called before dns cache initialization\n");
3221                 h->srv=h->a=0;
3222                 he=_sip_resolvehost(name, port, proto);
3223                 if (he){
3224                         hostent2ip_addr(ip, he, 0);
3225                         return 0;
3226                 }
3227                 return -E_DNS_NO_SRV;
3228         }
3229         if ((h->srv==0) && (h->a==0)){ /* first call */
3230                 if (proto) {
3231                         if(*proto==0) { /* makes sure we have a protocol set*/
3232                                 *proto=PROTO_UDP; /* default */
3233                         }
3234                         h->port=(*proto==PROTO_TLS)?SIPS_PORT:SIP_PORT; /* just in case we
3235                                                                                                                 don't find another */
3236                         h->proto=*proto; /* store initial protocol */
3237                 } else {
3238                         h->proto=PROTO_UDP; /* default */
3239                 }
3240                 if (port){
3241                         if (*port==0){
3242                                 /* try SRV if initial call & no port specified
3243                                  * (draft-ietf-sip-srv-06) */
3244                                 if ((name->len+SRV_MAX_PREFIX_LEN+1)>MAX_DNS_NAME){
3245                                         LM_WARN("domain name too long (%d), unable to perform SRV lookup\n",
3246                                                                 name->len);
3247                                 }else{
3248                                         /* check if it's an ip address */
3249                                         if ( ((tmp_ip=str2ip(name))!=0)
3250                                                   || ((tmp_ip=str2ip6(name))!=0)
3251                                                 ){
3252                                                 /* we are lucky, this is an ip address */
3253                                                 if (((flags&DNS_IPV4_ONLY) && (tmp_ip->af==AF_INET6))||
3254                                                         ((flags&DNS_IPV6_ONLY) && (tmp_ip->af==AF_INET))){
3255                                                         return -E_DNS_AF_MISMATCH;
3256                                                 }
3257                                                 *ip=*tmp_ip;
3258                                                 *port=h->port;
3259                                                 /* proto already set */
3260                                                 return 0;
3261                                         }
3262
3263                                         /* looping on the ordered list until we found a protocol what has srv record */
3264