core, lib, modules: restructured source code tree
[sip-router] / 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 #ifdef DNS_LU_LST
351         dns_last_used_lst=shm_malloc(sizeof(*dns_last_used_lst));
352         if (dns_last_used_lst==0){
353                 ret=E_OUT_OF_MEM;
354                 goto error;
355         }
356         clist_init(dns_last_used_lst, next, prev);
357 #endif
358         dns_hash=shm_malloc(sizeof(struct dns_hash_head)*DNS_HASH_SIZE);
359         if (dns_hash==0){
360                 ret=E_OUT_OF_MEM;
361                 goto error;
362         }
363         for (r=0; r<DNS_HASH_SIZE; r++)
364                 clist_init(&dns_hash[r], next, prev);
365
366         dns_hash_lock=lock_alloc();
367         if (dns_hash_lock==0){
368                 ret=E_OUT_OF_MEM;
369                 goto error;
370         }
371         if (lock_init(dns_hash_lock)==0){
372                 lock_dealloc(dns_hash_lock);
373                 dns_hash_lock=0;
374                 ret=-1;
375                 goto error;
376         }
377
378 #ifdef DNS_WATCHDOG_SUPPORT
379         dns_servers_up=shm_malloc(sizeof(atomic_t));
380         if (dns_servers_up==0){
381                 ret=E_OUT_OF_MEM;
382                 goto error;
383         }
384         atomic_set(dns_servers_up, 1);
385 #endif
386
387         /* fix options */
388         default_core_cfg.dns_cache_max_mem<<=10; /* Kb */ /* TODO: test with 0 */
389         if (default_core_cfg.use_dns_cache==0)
390                 default_core_cfg.use_dns_failover=0; /* cannot work w/o dns_cache support */
391         /* fix flags */
392         fix_dns_flags(NULL, NULL);
393
394         dns_timer_h=timer_alloc();
395         if (dns_timer_h==0){
396                 ret=E_OUT_OF_MEM;
397                 goto error;
398         }
399         if (dns_timer_interval){
400                 timer_init(dns_timer_h, dns_timer, 0, 0); /* "slow" timer */
401                 if (timer_add(dns_timer_h, S_TO_TICKS(dns_timer_interval))<0){
402                         LM_CRIT("failed to add the timer\n");
403                         timer_free(dns_timer_h);
404                         dns_timer_h=0;
405                         goto error;
406                 }
407         }
408
409         return 0;
410 error:
411         destroy_dns_cache();
412         return ret;
413 }
414
415 #ifdef USE_DNS_CACHE_STATS
416 int init_dns_cache_stats(int iproc_num)
417 {
418         /* do not initialize the stats array if the DNS cache will not be used */
419         if (dns_cache_init==0) return 0;
420
421         /* if it is already initialized */
422         if (dns_cache_stats)
423                 shm_free(dns_cache_stats);
424
425         dns_cache_stats=shm_malloc(sizeof(*dns_cache_stats) * iproc_num);
426         if (dns_cache_stats==0){
427                 return E_OUT_OF_MEM;
428         }
429         memset(dns_cache_stats, 0, sizeof(*dns_cache_stats) * iproc_num);
430
431         return 0;
432 }
433 #endif
434
435 /* hash function, type is not used (obsolete)
436  * params: char* s, int len, int type
437  * returns the hash value
438  */
439 #define dns_hash_no(s, len, type) \
440         (get_hash1_case_raw((s),(len)) % DNS_HASH_SIZE)
441
442
443
444 #ifdef DNS_CACHE_DEBUG
445 #define DEBUG_LU_LST
446 #ifdef DEBUG_LU_LST
447
448 #include <stdlib.h> /* abort() */
449 #define check_lu_lst(l) ((((l)->next==(l)) || ((l)->prev==(l))) && \
450                                                         ((l)!=dns_last_used_lst))
451
452 #define dbg_lu_lst(txt, l) \
453                 LM_CRIT("%s: crt(%p, %p, %p)," \
454                                         " prev(%p, %p, %p), next(%p, %p, %p)\n", txt, \
455                                         (l), (l)->next, (l)->prev, \
456                                         (l)->prev, (l)->prev->next, (l)->prev->prev, \
457                                         (l)->next, (l)->next->next, (l)->next->prev \
458                                 )
459
460 #define debug_lu_lst( txt, l) \
461         do{ \
462                 if ((l) && check_lu_lst((l))){  \
463                         dbg_lu_lst(txt  " crt:", (l)); \
464                         abort(); \
465                 } \
466                 if (((l)->next) && check_lu_lst((l)->next)){ \
467                         dbg_lu_lst(txt  " next:",  (l)); \
468                         abort(); \
469                 } \
470                 if (((l)->prev) && check_lu_lst((l)->prev)){ \
471                         dbg_lu_lst(txt  " prev:", (l)); \
472                         abort(); \
473                 } \
474         }while(0)
475
476 #endif
477 #endif /* DNS_CACHE_DEBUG */
478
479
480 /* must be called with the DNS_LOCK hold
481  * remove and entry from the hash, dec. its refcnt and if not referenced
482  * anymore deletes it */
483 inline static void _dns_hash_remove(struct dns_hash_entry* e)
484 {
485         clist_rm(e, next, prev);
486 #ifdef DNS_CACHE_DEBUG
487         e->next=e->prev=0;
488 #endif
489 #ifdef DNS_LU_LST
490 #ifdef DEBUG_LU_LST
491         debug_lu_lst("_dns_hash_remove: pre rm:", &e->last_used_lst);
492 #endif
493         clist_rm(&e->last_used_lst, next, prev);
494 #ifdef DEBUG_LU_LST
495         debug_lu_lst("_dns_hash_remove: post rm:", &e->last_used_lst);
496 #endif
497 #ifdef DNS_CACHE_DEBUG
498         e->last_used_lst.next=e->last_used_lst.prev=0;
499 #endif
500 #endif
501         *dns_cache_mem_used-=e->total_size;
502         dns_hash_put(e);
503 }
504
505
506
507 /* non locking  version (the dns hash must _be_ locked externally)
508  * returns 0 when not found, or the entry on success (an entry with a
509  * similar name but with a CNAME type will always match).
510  * it doesn't increase the internal refcnt
511  * returns the entry when found, 0 when not found and sets *err to !=0
512  *  on error (e.g. recursive cnames)
513  * WARNING: - internal use only
514  *          - always check if the returned entry type is CNAME */
515 inline static struct dns_hash_entry* _dns_hash_find(str* name, int type,
516                                                                                                                 int* h, int* err)
517 {
518         struct dns_hash_entry* e;
519         struct dns_hash_entry* tmp;
520         struct dns_hash_entry* ret;
521         ticks_t now;
522         int cname_chain;
523         str cname;
524 #ifdef DNS_WATCHDOG_SUPPORT
525         int servers_up;
526
527         servers_up = atomic_get(dns_servers_up);
528 #endif
529
530         cname_chain=0;
531         ret=0;
532         now=get_ticks_raw();
533         *err=0;
534 again:
535         *h=dns_hash_no(name->s, name->len, type);
536 #ifdef DNS_CACHE_DEBUG
537         LM_DBG("(%.*s(%d), %d), h=%d\n", name->len, name->s, name->len, type, *h);
538 #endif
539         clist_foreach_safe(&dns_hash[*h], e, tmp, next){
540                 if (
541 #ifdef DNS_WATCHDOG_SUPPORT
542                         /* remove expired elements only when the dns servers are up */
543                         servers_up &&
544 #endif
545                         /* automatically remove expired elements */
546                         ((e->ent_flags & DNS_FLAG_PERMANENT) == 0) &&
547                         ((s_ticks_t)(now-e->expire)>=0)
548                 ) {
549                                 _dns_hash_remove(e);
550                 }else if ((e->type==type) && (e->name_len==name->len) &&
551                         (strncasecmp(e->name, name->s, e->name_len)==0)){
552                         e->last_used=now;
553 #ifdef DNS_LU_LST
554                         /* add it at the end */
555 #ifdef DEBUG_LU_LST
556                         debug_lu_lst("_dns_hash_find: pre rm:", &e->last_used_lst);
557 #endif
558                         clist_rm(&e->last_used_lst, next, prev);
559                         clist_append(dns_last_used_lst, &e->last_used_lst, next, prev);
560 #ifdef DEBUG_LU_LST
561                         debug_lu_lst("_dns_hash_find: post append:", &e->last_used_lst);
562 #endif
563 #endif
564                         return e;
565                 }else if ((e->type==T_CNAME) &&
566                                         !((e->rr_lst==0) || (e->ent_flags & DNS_FLAG_BAD_NAME)) &&
567                                         (e->name_len==name->len) &&
568                                         (strncasecmp(e->name, name->s, e->name_len)==0)){
569                         /*if CNAME matches and CNAME is entry is not a neg. cache entry
570                           (could be produced by a specific CNAME lookup)*/
571                         e->last_used=now;
572 #ifdef DNS_LU_LST
573                         /* add it at the end */
574 #ifdef DEBUG_LU_LST
575                         debug_lu_lst("_dns_hash_find: cname: pre rm:", &e->last_used_lst);
576 #endif
577                         clist_rm(&e->last_used_lst, next, prev);
578                         clist_append(dns_last_used_lst, &e->last_used_lst, next, prev);
579 #ifdef DEBUG_LU_LST
580                         debug_lu_lst("_dns_hash_find: cname: post append:",
581                                                         &e->last_used_lst);
582 #endif
583 #endif
584                         ret=e; /* if this is an unfinished cname chain, we try to
585                                           return the last cname */
586                         /* this is a cname => retry using its value */
587                         if (cname_chain> MAX_CNAME_CHAIN){
588                                 LM_ERR("cname chain too long or recursive (\"%.*s\")\n",
589                                                 name->len, name->s);
590                                 ret=0; /* error*/
591                                 *err=-1;
592                                 break;
593                         }
594                         cname_chain++;
595                         cname.s=((struct cname_rdata*)e->rr_lst->rdata)->name;
596                         cname.len= ((struct cname_rdata*)e->rr_lst->rdata)->name_len;
597                         name=&cname;
598                         goto again;
599                 }
600         }
601         return ret;
602 }
603
604
605
606 /* frees cache entries, if expired_only=0 only expired entries will be
607  * removed, else all of them
608  * it will process maximum no entries (to process all of them use -1)
609  * returns the number of deleted entries
610  * This should be called from a timer process*/
611 inline static int dns_cache_clean(unsigned int no, int expired_only)
612 {
613         struct dns_hash_entry* e;
614         ticks_t now;
615         unsigned int n;
616         unsigned int deleted;
617 #ifdef DNS_LU_LST
618         struct dns_lu_lst* l;
619         struct dns_lu_lst* tmp;
620 #else
621         struct dns_hash_entry* t;
622         unsigned int h;
623         static unsigned int start=0;
624 #endif
625
626         n=0;
627         deleted=0;
628         now=get_ticks_raw();
629         LOCK_DNS_HASH();
630 #ifdef DNS_LU_LST
631         clist_foreach_safe(dns_last_used_lst, l, tmp, next){
632                 e=(struct dns_hash_entry*)(((char*)l)-
633                                 (char*)&((struct dns_hash_entry*)(0))->last_used_lst);
634                 if (((e->ent_flags & DNS_FLAG_PERMANENT) == 0)
635                         && (!expired_only || ((s_ticks_t)(now-e->expire)>=0))
636                 ) {
637                                 _dns_hash_remove(e);
638                                 deleted++;
639                 }
640                 n++;
641                 if (n>=no) break;
642         }
643 #else
644         for(h=start; h!=(start+DNS_HASH_SIZE); h++){
645                 clist_foreach_safe(&dns_hash[h%DNS_HASH_SIZE], e, t, next){
646                         if (((e->ent_flags & DNS_FLAG_PERMANENT) == 0)
647                                 && ((s_ticks_t)(now-e->expire)>=0)
648                         ) {
649                                 _dns_hash_remove(e);
650                                 deleted++;
651                         }
652                         n++;
653                         if (n>=no) goto skip;
654                 }
655         }
656         /* not fair, but faster then random() */
657         if (!expired_only){
658                 for(h=start; h!=(start+DNS_HASH_SIZE); h++){
659                         clist_foreach_safe(&dns_hash[h%DNS_HASH_SIZE], e, t, next){
660                                 if ((e->ent_flags & DNS_FLAG_PERMANENT) == 0) {
661                                         _dns_hash_remove(e);
662                                         deleted++;
663                                 }
664                                 n++;
665                                 if (n>=no) goto skip;
666                         }
667                 }
668         }
669 skip:
670         start=h;
671 #endif
672         UNLOCK_DNS_HASH();
673         return deleted;
674 }
675
676
677
678 /* frees cache entries, if expired_only=0 only expired entries will be
679  * removed, else all of them
680  * it will stop when the dns cache used memory reaches target (to process all
681  * of them use 0)
682  * returns the number of deleted entries */
683 inline static int dns_cache_free_mem(unsigned int target, int expired_only)
684 {
685         struct dns_hash_entry* e;
686         ticks_t now;
687         unsigned int deleted;
688 #ifdef DNS_LU_LST
689         struct dns_lu_lst* l;
690         struct dns_lu_lst* tmp;
691 #else
692         struct dns_hash_entry* t;
693         unsigned int h;
694         static unsigned int start=0;
695 #endif
696
697         deleted=0;
698         now=get_ticks_raw();
699         LOCK_DNS_HASH();
700 #ifdef DNS_LU_LST
701         clist_foreach_safe(dns_last_used_lst, l, tmp, next){
702                 if (*dns_cache_mem_used<=target) break;
703                 e=(struct dns_hash_entry*)(((char*)l)-
704                                 (char*)&((struct dns_hash_entry*)(0))->last_used_lst);
705                 if (((e->ent_flags & DNS_FLAG_PERMANENT) == 0)
706                         && (!expired_only || ((s_ticks_t)(now-e->expire)>=0))
707                 ) {
708                                 _dns_hash_remove(e);
709                                 deleted++;
710                 }
711         }
712 #else
713         for(h=start; h!=(start+DNS_HASH_SIZE); h++){
714                 clist_foreach_safe(&dns_hash[h%DNS_HASH_SIZE], e, t, next){
715                         if (*dns_cache_mem_used<=target)
716                                 goto skip;
717                         if (((e->ent_flags & DNS_FLAG_PERMANENT) == 0)
718                                 && ((s_ticks_t)(now-e->expire)>=0)
719                         ) {
720                                 _dns_hash_remove(e);
721                                 deleted++;
722                         }
723                 }
724         }
725         /* not fair, but faster then random() */
726         if (!expired_only){
727                 for(h=start; h!=(start+DNS_HASH_SIZE); h++){
728                         clist_foreach_safe(&dns_hash[h%DNS_HASH_SIZE], e, t, next){
729                                 if (*dns_cache_mem_used<=target)
730                                         goto skip;
731                                 if (((e->ent_flags & DNS_FLAG_PERMANENT) == 0)
732                                         && ((s_ticks_t)(now-e->expire)>=0)
733                                 ) {
734                                         _dns_hash_remove(e);
735                                         deleted++;
736                                 }
737                         }
738                 }
739         }
740 skip:
741         start=h;
742 #endif
743         UNLOCK_DNS_HASH();
744         return deleted;
745 }
746
747
748
749 /* locking  version (the dns hash must _not_be locked externally)
750  * returns 0 when not found, the searched entry on success (with CNAMEs
751  *  followed) or the last CNAME entry from an unfinished CNAME chain,
752  *  if the search matches a CNAME. On error sets *err (e.g. recursive CNAMEs).
753  * it increases the internal refcnt => when finished dns_hash_put() must
754  *  be called on the returned entry
755  *  WARNING: - the return might be a CNAME even if type!=CNAME, see above */
756 inline static struct dns_hash_entry* dns_hash_get(str* name, int type, int* h,
757                                                                                                         int* err)
758 {
759         struct dns_hash_entry* e;
760
761         LOCK_DNS_HASH();
762         e=_dns_hash_find(name, type, h, err);
763         if (e){
764                 atomic_inc(&e->refcnt);
765         }
766         UNLOCK_DNS_HASH();
767         return e;
768 }
769
770
771
772 /* adds a fully created and init. entry (see dns_cache_mk_entry()) to the hash
773  * table
774  * returns 0 on success, -1 on error */
775 inline static int dns_cache_add(struct dns_hash_entry* e)
776 {
777         int h;
778
779         /* check space */
780         /* atomic_add_long(dns_cache_total_used, e->size); */
781         if ((*dns_cache_mem_used+e->total_size)>=cfg_get(core, core_cfg, dns_cache_max_mem)){
782 #ifdef USE_DNS_CACHE_STATS
783                 dns_cache_stats[process_no].dc_lru_cnt++;
784 #endif
785                 LM_WARN("cache full, trying to free...\n");
786                 /* free ~ 12% of the cache */
787                 dns_cache_free_mem(*dns_cache_mem_used/16*14,
788                                         !cfg_get(core, core_cfg, dns_cache_del_nonexp));
789                 if ((*dns_cache_mem_used+e->total_size)>=cfg_get(core, core_cfg, dns_cache_max_mem)){
790                         LM_ERR("max. cache mem size exceeded\n");
791                         return -1;
792                 }
793         }
794         atomic_inc(&e->refcnt);
795         h=dns_hash_no(e->name, e->name_len, e->type);
796 #ifdef DNS_CACHE_DEBUG
797         LM_DBG("adding %.*s(%d) %d (flags=%0x) at %d\n",
798                         e->name_len, e->name, e->name_len, e->type, e->ent_flags, h);
799 #endif
800         LOCK_DNS_HASH();
801                 *dns_cache_mem_used+=e->total_size; /* no need for atomic ops, written
802                                                                                  only from within a lock */
803                 clist_append(&dns_hash[h], e, next, prev);
804 #ifdef DNS_LU_LST
805                 clist_append(dns_last_used_lst, &e->last_used_lst, next, prev);
806 #endif
807         UNLOCK_DNS_HASH();
808         return 0;
809 }
810
811
812
813 /* same as above, but it must be called with the dns hash lock held
814  * returns 0 on success, -1 on error */
815 inline static int dns_cache_add_unsafe(struct dns_hash_entry* e)
816 {
817         int h;
818
819         /* check space */
820         /* atomic_add_long(dns_cache_total_used, e->size); */
821         if ((*dns_cache_mem_used+e->total_size)>=cfg_get(core, core_cfg, dns_cache_max_mem)){
822 #ifdef USE_DNS_CACHE_STATS
823                 dns_cache_stats[process_no].dc_lru_cnt++;
824 #endif
825                 LM_WARN("cache full, trying to free...\n");
826                 /* free ~ 12% of the cache */
827                 UNLOCK_DNS_HASH();
828                 dns_cache_free_mem(*dns_cache_mem_used/16*14,
829                                         !cfg_get(core, core_cfg, dns_cache_del_nonexp));
830                 LOCK_DNS_HASH();
831                 if ((*dns_cache_mem_used+e->total_size)>=cfg_get(core, core_cfg, dns_cache_max_mem)){
832                         LM_ERR("max. cache mem size exceeded\n");
833                         return -1;
834                 }
835         }
836         atomic_inc(&e->refcnt);
837         h=dns_hash_no(e->name, e->name_len, e->type);
838 #ifdef DNS_CACHE_DEBUG
839         LM_DBG("adding %.*s(%d) %d (flags=%0x) at %d\n",
840                         e->name_len, e->name, e->name_len, e->type, e->ent_flags, h);
841 #endif
842         *dns_cache_mem_used+=e->total_size; /* no need for atomic ops, written
843                                                                                  only from within a lock */
844         clist_append(&dns_hash[h], e, next, prev);
845 #ifdef DNS_LU_LST
846         clist_append(dns_last_used_lst, &e->last_used_lst, next, prev);
847 #endif
848         return 0;
849 }
850
851
852
853 /* creates a "negative" entry which will be valid for ttl seconds */
854 inline static struct dns_hash_entry* dns_cache_mk_bad_entry(str* name,
855                                                                                                                         int type,
856                                                                                                                         int ttl,
857                                                                                                                         int flags)
858 {
859         struct dns_hash_entry* e;
860         int size;
861         ticks_t now;
862
863 #ifdef DNS_CACHE_DEBUG
864         LM_DBG("(%.*s, %d, %d, %d)\n", name->len, name->s, type, ttl, flags);
865 #endif
866         size=sizeof(struct dns_hash_entry)+name->len-1+1;
867         e=shm_malloc(size);
868         if (e==0){
869                 LM_ERR("out of memory\n");
870                 return 0;
871         }
872         memset(e, 0, size); /* init with 0*/
873         e->total_size=size;
874         e->name_len=name->len;
875         e->type=type;
876         now=get_ticks_raw();
877         e->last_used=now;
878         e->expire=now+S_TO_TICKS(ttl);
879         memcpy(e->name, name->s, name->len);
880         e->ent_flags=flags;
881         return e;
882 }
883
884
885
886 /* create a a/aaaa hash entry from a name and ip address
887  * returns 0 on error */
888 inline static struct dns_hash_entry* dns_cache_mk_ip_entry(str* name,
889                                                                                                                         struct ip_addr* ip)
890 {
891         struct dns_hash_entry* e;
892         int size;
893         ticks_t now;
894
895         /* everything is allocated in one block: dns_hash_entry + name +
896          * + dns_rr + rdata;  dns_rr must start at an aligned adress,
897          * hence we need to round dns_hash_entry+name size to a sizeof(long)
898          * multiple.
899          * Memory image:
900          * struct dns_hash_entry
901          * name (name_len+1 bytes)
902          * padding to multiple of sizeof(long)
903          * dns_rr
904          * rdata  (no padding needed, since for ip is just an array of chars)
905           */
906         size=ROUND_POINTER(sizeof(struct dns_hash_entry)+name->len-1+1)+
907                         sizeof(struct dns_rr)+ ip->len;
908         e=shm_malloc(size);
909         if (e==0){
910                 LM_ERR("out of memory\n");
911                 return 0;
912         }
913         memset(e, 0, size); /* init with 0*/
914         e->total_size=size;
915         e->name_len=name->len;
916         e->type=(ip->af==AF_INET)?T_A:T_AAAA;
917         now=get_ticks_raw();
918         e->last_used=now;
919         e->expire=now-1; /* maximum expire */
920         memcpy(e->name, name->s, name->len); /* memset makes sure is 0-term. */
921         e->rr_lst=(void*)((char*)e+
922                                 ROUND_POINTER(sizeof(struct dns_hash_entry)+name->len-1+1));
923         e->rr_lst->rdata=(void*)((char*)e->rr_lst+sizeof(struct dns_rr));
924         e->rr_lst->expire=now-1; /* maximum expire */
925         /* no need to align rr_lst->rdata for a or aaaa records */
926         memcpy(e->rr_lst->rdata, ip->u.addr, ip->len);
927         return e;
928 }
929
930 /* creates an srv hash entry from the given parameters
931  * returns 0 on error */
932 static struct dns_hash_entry* dns_cache_mk_srv_entry(str* name,
933                                                         unsigned short priority,
934                                                         unsigned short weight,
935                                                         unsigned short port,
936                                                         str* rr_name,
937                                                         int ttl)
938 {
939         struct dns_hash_entry* e;
940         int size;
941         ticks_t now;
942
943         /* everything is allocated in one block: dns_hash_entry + name +
944          * + dns_rr + rdata;  dns_rr must start at an aligned adress,
945          * hence we need to round dns_hash_entry+name size to a sizeof(long),
946          * and similarly, dns_rr must be rounded to sizeof(short).
947          * multiple.
948          * Memory image:
949          * struct dns_hash_entry
950          * name (name_len+1 bytes)
951          * padding to multiple of sizeof(long)
952          * dns_rr
953          * padding to multiple of sizeof(short)
954          * rdata
955           */
956         size=ROUND_POINTER(sizeof(struct dns_hash_entry)+name->len-1+1) +
957                 ROUND_SHORT(sizeof(struct dns_rr)) +
958                 sizeof(struct srv_rdata)-1 +
959                 rr_name->len+1;
960
961         e=shm_malloc(size);
962         if (e==0){
963                 LM_ERR("out of memory\n");
964                 return 0;
965         }
966         memset(e, 0, size); /* init with 0*/
967         e->total_size=size;
968         e->name_len=name->len;
969         e->type=T_SRV;
970         now=get_ticks_raw();
971         e->last_used=now;
972         e->expire=now+S_TO_TICKS(ttl);
973         memcpy(e->name, name->s, name->len); /* memset makes sure is 0-term. */
974         e->rr_lst=(void*)((char*)e+
975                                 ROUND_POINTER(sizeof(struct dns_hash_entry)+name->len-1+1));
976         e->rr_lst->rdata=(void*)((char*)e->rr_lst+ROUND_SHORT(sizeof(struct dns_rr)));
977         e->rr_lst->expire=e->expire;
978         ((struct srv_rdata*)e->rr_lst->rdata)->priority = priority;
979         ((struct srv_rdata*)e->rr_lst->rdata)->weight = weight;
980         ((struct srv_rdata*)e->rr_lst->rdata)->port = port;
981         ((struct srv_rdata*)e->rr_lst->rdata)->name_len = rr_name->len;
982         memcpy(((struct srv_rdata*)e->rr_lst->rdata)->name, rr_name->s, rr_name->len);
983         return e;
984 }
985
986
987 /* create a dns hash entry from a name and a rdata list (pkg_malloc'ed)
988  * (it will use only the type records with the name "name" from the
989  *  rdata list with one exception: if a matching CNAME with the same
990  *  name is found, the search will stop and this will be the record used)
991  * returns 0 on error and removes the used elements from the rdata list*/
992 inline static struct dns_hash_entry* dns_cache_mk_rd_entry(str* name, int type,
993                                                                                                                 struct rdata** rd_lst)
994 {
995         struct dns_hash_entry* e;
996         struct dns_rr* rr;
997         struct dns_rr** tail_rr;
998         struct rdata** p;
999         struct rdata* tmp_lst;
1000         struct rdata** tail;
1001         struct rdata* l;
1002         int size;
1003         ticks_t now;
1004         unsigned int max_ttl;
1005         unsigned int ttl;
1006         int i;
1007
1008 #define rec_matches(rec, t, n) /*(struct rdata* record, int type, str* name)*/\
1009         (       ((rec)->name_len==(n)->len) && ((rec)->type==(t)) && \
1010                 (strncasecmp((rec)->name, (n)->s, (n)->len)==0))
1011         /* init */
1012         tmp_lst=0;
1013         tail=&tmp_lst;
1014
1015
1016         /* everything is allocated in one block: dns_hash_entry + name +
1017          * + dns_rr + rdata_raw+ ....;  dns_rr must start at an aligned adress,
1018          * hence we need to round dns_hash_entry+name size to a sizeof(long)
1019          * multiple. If rdata type requires it, rdata_raw might need to be also
1020          * aligned.
1021          * Memory image:
1022          * struct dns_hash_entry  (e)
1023          * name (name_len+1 bytes)  (&e->name[0])
1024          * padding to multiple of sizeof(char*)
1025          * dns_rr1 (e->rr_lst)
1026          * possible padding: no padding for a_rdata or aaaa_rdata,
1027          *                   multipe of sizeof(short) for srv_rdata,
1028          *                   multiple of sizeof(long) for naptr_rdata and others
1029          * dns_rr1->rdata  (e->rr_lst->rdata)
1030          * padding to multipe of sizeof long
1031          * dns_rr2 (e->rr_lst->next)
1032          * ....
1033          *
1034          */
1035         size=0;
1036         if (*rd_lst==0)
1037                 return 0;
1038         /* find the first matching rr, if it's a CNAME use CNAME as type,
1039          * if not continue with the original type */
1040         for(p=rd_lst; *p; p=&(*p)->next){
1041                 if (((*p)->name_len==name->len) &&
1042                                 (((*p)->type==type) || ((*p)->type==T_CNAME)) &&
1043                                 (strncasecmp((*p)->name, name->s, name->len)==0)){
1044                         type=(*p)->type;
1045                         break;
1046                 }
1047         }
1048         /* continue, we found the type we are looking for */
1049         switch(type){
1050                 case T_A:
1051                         for(; *p;){
1052                                 if (!rec_matches((*p), type, name)){
1053                                         /* skip this record */
1054                                         p=&(*p)->next; /* advance */
1055                                         continue;
1056                                 }
1057                                 size+=ROUND_POINTER(sizeof(struct dns_rr)+
1058                                                                                 sizeof(struct a_rdata));
1059                                 /* add it to our tmp. lst */
1060                                 *tail=*p;
1061                                 tail=&(*p)->next;
1062                                 /* detach it from the rd list */
1063                                 *p=(*p)->next;
1064                                 /* don't advance p, because the crt. elem. has
1065                                  * just been elimintated */
1066                         }
1067                         break;
1068                 case T_AAAA:
1069                         for(; *p;){
1070                                 if (!rec_matches((*p), type, name)){
1071                                         /* skip this record */
1072                                         p=&(*p)->next; /* advance */
1073                                         continue;
1074                                 }
1075                                 /* no padding */
1076                                 size+=ROUND_POINTER(sizeof(struct dns_rr)+
1077                                                                                         sizeof(struct aaaa_rdata));
1078                                 /* add it to our tmp. lst */
1079                                 *tail=*p;
1080                                 tail=&(*p)->next;
1081                                 /* detach it from the rd list */
1082                                 *p=(*p)->next;
1083                                 /* don't advance p, because the crt. elem. has
1084                                  * just been elimintated */
1085                         }
1086                         break;
1087                 case T_SRV:
1088                         for(; *p;){
1089                                 if (!rec_matches((*p), type, name)){
1090                                         /* skip this record */
1091                                         p=&(*p)->next; /* advance */
1092                                         continue;
1093                                 }
1094                                 /* padding to short */
1095                                 size+=ROUND_POINTER(ROUND_SHORT(sizeof(struct dns_rr))+
1096                                                 SRV_RDATA_SIZE(*(struct srv_rdata*)(*p)->rdata));
1097                                 /* add it to our tmp. lst */
1098                                 *tail=*p;
1099                                 tail=&(*p)->next;
1100                                 /* detach it from the rd list */
1101                                 *p=(*p)->next;
1102                                 /* don't advance p, because the crt. elem. has
1103                                  * just been elimintated */
1104                         }
1105                         break;
1106                 case T_NAPTR:
1107                         for(; *p;){
1108                                 if (!rec_matches((*p), type, name)){
1109                                         /* skip this record */
1110                                         p=&(*p)->next; /* advance */
1111                                         continue;
1112                                 }
1113                                 /* padding to char* */
1114                                 size+=ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
1115                                                 NAPTR_RDATA_SIZE(*(struct naptr_rdata*)(*p)->rdata));
1116                                 /* add it to our tmp. lst */
1117                                 *tail=*p;
1118                                 tail=&(*p)->next;
1119                                 /* detach it from the rd list */
1120                                 *p=(*p)->next;
1121                                 /* don't advance p, because the crt. elem. has
1122                                  * just been elimintated */
1123                         }
1124                         break;
1125                 case T_CNAME:
1126                         for(; *p;){
1127                                 if (!rec_matches((*p), type, name)){
1128                                         /* skip this record */
1129                                         p=&(*p)->next; /* advance */
1130                                         continue;
1131                                 }
1132                                 /* no padding */
1133                                 size+=ROUND_POINTER(sizeof(struct dns_rr)+
1134                                                 CNAME_RDATA_SIZE(*(struct cname_rdata*)(*p)->rdata));
1135                                 /* add it to our tmp. lst */
1136                                 *tail=*p;
1137                                 tail=&(*p)->next;
1138                                 /* detach it from the rd list */
1139                                 *p=(*p)->next;
1140                                 /* don't advance p, because the crt. elem. has
1141                                  * just been elimintated */
1142                         }
1143                         break;
1144                 case T_TXT:
1145                         for(; *p;){
1146                                 if (!rec_matches((*p), type, name)){
1147                                         /* skip this record */
1148                                         p=&(*p)->next; /* advance */
1149                                         continue;
1150                                 }
1151                                 /* padding to char* (because of txt[]->cstr*/
1152                                 size+=ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
1153                                                 TXT_RDATA_SIZE(*(struct txt_rdata*)(*p)->rdata));
1154                                 /* add it to our tmp. lst */
1155                                 *tail=*p;
1156                                 tail=&(*p)->next;
1157                                 /* detach it from the rd list */
1158                                 *p=(*p)->next;
1159                                 /* don't advance p, because the crt. elem. has
1160                                  * just been elimintated */
1161                         }
1162                         break;
1163                 case T_EBL:
1164                         for(; *p;){
1165                                 if (!rec_matches((*p), type, name)){
1166                                         /* skip this record */
1167                                         p=&(*p)->next; /* advance */
1168                                         continue;
1169                                 }
1170                                 /* padding to char* (because of the char* pointers */
1171                                 size+=ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
1172                                                 EBL_RDATA_SIZE(*(struct ebl_rdata*)(*p)->rdata));
1173                                 /* add it to our tmp. lst */
1174                                 *tail=*p;
1175                                 tail=&(*p)->next;
1176                                 /* detach it from the rd list */
1177                                 *p=(*p)->next;
1178                                 /* don't advance p, because the crt. elem. has
1179                                  * just been elimintated */
1180                         }
1181                         break;
1182                 case T_PTR:
1183                         for(; *p;){
1184                                 if (!rec_matches((*p), type, name)){
1185                                         /* skip this record */
1186                                         p=&(*p)->next; /* advance */
1187                                         continue;
1188                                 }
1189                                 /* no padding */
1190                                 size+=ROUND_POINTER(sizeof(struct dns_rr)+
1191                                                 PTR_RDATA_SIZE(*(struct ptr_rdata*)(*p)->rdata));
1192                                 /* add it to our tmp. lst */
1193                                 *tail=*p;
1194                                 tail=&(*p)->next;
1195                                 /* detach it from the rd list */
1196                                 *p=(*p)->next;
1197                                 /* don't advance p, because the crt. elem. has
1198                                  * just been elimintated */
1199                         }
1200                         break;
1201                 default:
1202                         LM_CRIT("type %d not supported\n", type);
1203                         /* we don't know what to do with it, so don't
1204                          * add it to the tmp_lst */
1205                         return 0; /* error */
1206         }
1207         *tail=0; /* mark the end of our tmp_lst */
1208         if (size==0){
1209 #ifdef DNS_CACHE_DEBUG
1210                 LM_DBG("entry %.*s (%d) not found\n", name->len, name->s, type);
1211 #endif
1212                 return 0;
1213         }
1214         /* compute size */
1215         size+=ROUND_POINTER(sizeof(struct dns_hash_entry)+name->len-1+1);
1216         e=shm_malloc(size);
1217         if (e==0){
1218                 LM_ERR("out of memory\n");
1219                 return 0;
1220         }
1221         memset(e, 0, size); /* init with 0 */
1222         clist_init(e, next, prev);
1223         e->total_size=size;
1224         e->name_len=name->len;
1225         e->type=type;
1226         now=get_ticks_raw();
1227         e->last_used=now;
1228         memcpy(e->name, name->s, name->len); /* memset makes sure is 0-term. */
1229         e->rr_lst=(struct dns_rr*)((char*)e+
1230                                 ROUND_POINTER(sizeof(struct dns_hash_entry)+name->len-1+1));
1231         tail_rr=&(e->rr_lst);
1232         rr=e->rr_lst;
1233         max_ttl=0;
1234         /* copy the actual data */
1235         switch(type){
1236                 case T_A:
1237                         for(l=tmp_lst; l; l=l->next){
1238                                 ttl=FIX_TTL(l->ttl);
1239                                 rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1240                                 max_ttl=MAX(max_ttl, ttl);
1241                                 rr->rdata=(void*)((char*)rr+sizeof(struct dns_rr));
1242                                 memcpy(rr->rdata, l->rdata, sizeof(struct a_rdata));
1243                                 rr->next=(void*)((char*)rr+ROUND_POINTER(sizeof(struct dns_rr)+
1244                                                         sizeof(struct a_rdata)));
1245                                 tail_rr=&(rr->next);
1246                                 rr=rr->next;
1247                         }
1248                         break;
1249                 case T_AAAA:
1250                         for(l=tmp_lst; l; l=l->next){
1251                                 ttl=FIX_TTL(l->ttl);
1252                                 rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1253                                 max_ttl=MAX(max_ttl, ttl);
1254                                 rr->rdata=(void*)((char*)rr+sizeof(struct dns_rr));
1255                                 memcpy(rr->rdata, l->rdata, sizeof(struct aaaa_rdata));
1256                                 rr->next=(void*)((char*)rr+ROUND_POINTER(sizeof(struct dns_rr)+
1257                                                         sizeof(struct aaaa_rdata)));
1258                                 tail_rr=&(rr->next);
1259                                 rr=rr->next;
1260                         }
1261                         break;
1262                 case T_SRV:
1263                         for(l=tmp_lst; l; l=l->next){
1264                                 ttl=FIX_TTL(l->ttl);
1265                                 rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1266                                 max_ttl=MAX(max_ttl, ttl);
1267                                 rr->rdata=(void*)((char*)rr+
1268                                                                 ROUND_SHORT(sizeof(struct dns_rr)));
1269                                 /* copy the whole srv_rdata block*/
1270                                 memcpy(rr->rdata, l->rdata,
1271                                                 SRV_RDATA_SIZE(*(struct srv_rdata*)l->rdata) );
1272                                 rr->next=(void*)((char*)rr+
1273                                                         ROUND_POINTER( ROUND_SHORT(sizeof(struct dns_rr))+
1274                                                                                 SRV_RDATA_SIZE(
1275                                                                                         *(struct srv_rdata*)l->rdata)));
1276                                 tail_rr=&(rr->next);
1277                                 rr=rr->next;
1278                         }
1279                         break;
1280                 case T_NAPTR:
1281                         for(l=tmp_lst; l; l=l->next){
1282                                 ttl=FIX_TTL(l->ttl);
1283                                 rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1284                                 max_ttl=MAX(max_ttl, ttl);
1285                                 rr->rdata=(void*)((char*)rr+
1286                                                                 ROUND_POINTER(sizeof(struct dns_rr)));
1287                                 /* copy the whole naptr_rdata block*/
1288                                 memcpy(rr->rdata, l->rdata,
1289                                                 NAPTR_RDATA_SIZE(*(struct naptr_rdata*)l->rdata) );
1290                                 /* adjust the string pointer */
1291                                 ((struct naptr_rdata*)rr->rdata)->flags=
1292                                         translate_pointer((char*)rr->rdata, (char*)l->rdata,
1293                                                         (((struct naptr_rdata*)l->rdata)->flags));
1294                                 ((struct naptr_rdata*)rr->rdata)->services=
1295                                         translate_pointer((char*)rr->rdata, (char*)l->rdata,
1296                                                         (((struct naptr_rdata*)l->rdata)->services));
1297                                 ((struct naptr_rdata*)rr->rdata)->regexp=
1298                                         translate_pointer((char*)rr->rdata, (char*)l->rdata,
1299                                                         (((struct naptr_rdata*)l->rdata)->regexp));
1300                                 ((struct naptr_rdata*)rr->rdata)->repl=
1301                                         translate_pointer((char*)rr->rdata, (char*)l->rdata,
1302                                                         (((struct naptr_rdata*)l->rdata)->repl));
1303                                 rr->next=(void*)((char*)rr+
1304                                                         ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
1305                                                                                 NAPTR_RDATA_SIZE(
1306                                                                                         *(struct naptr_rdata*)l->rdata)));
1307                                 tail_rr=&(rr->next);
1308                                 rr=rr->next;
1309                         }
1310                         break;
1311                 case T_CNAME:
1312                         for(l=tmp_lst; l; l=l->next){
1313                                 ttl=FIX_TTL(l->ttl);
1314                                 rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1315                                 max_ttl=MAX(max_ttl, ttl);
1316                                 rr->rdata=(void*)((char*)rr+sizeof(struct dns_rr));
1317                                 memcpy(rr->rdata, l->rdata,
1318                                                         CNAME_RDATA_SIZE(*(struct cname_rdata*)l->rdata));
1319                                 rr->next=(void*)((char*)rr+ROUND_POINTER(sizeof(struct dns_rr)+
1320                                                         CNAME_RDATA_SIZE(*(struct cname_rdata*)l->rdata)));
1321                                 tail_rr=&(rr->next);
1322                                 rr=rr->next;
1323                         }
1324                         break;
1325                 case T_TXT:
1326                         for(l=tmp_lst; l; l=l->next){
1327                                 ttl=FIX_TTL(l->ttl);
1328                                 rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1329                                 max_ttl=MAX(max_ttl, ttl);
1330                                 rr->rdata=(void*)((char*)rr+
1331                                                         ROUND_POINTER(sizeof(struct dns_rr)));
1332                                 memcpy(rr->rdata, l->rdata,
1333                                                         TXT_RDATA_SIZE(*(struct txt_rdata*)l->rdata));
1334                                 /* adjust the string pointers */
1335                                 for (i=0; i<((struct txt_rdata*)l->rdata)->cstr_no; i++){
1336                                         ((struct txt_rdata*)rr->rdata)->txt[i].cstr=
1337                                                 translate_pointer((char*)rr->rdata, (char*)l->rdata,
1338                                                                 ((struct txt_rdata*)l->rdata)->txt[i].cstr);
1339                                 }
1340                                 rr->next=(void*)((char*)rr+
1341                                                 ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
1342                                                         TXT_RDATA_SIZE(*(struct txt_rdata*)l->rdata)));
1343                                 tail_rr=&(rr->next);
1344                                 rr=rr->next;
1345                         }
1346                         break;
1347                 case T_EBL:
1348                         for(l=tmp_lst; l; l=l->next){
1349                                 ttl=FIX_TTL(l->ttl);
1350                                 rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1351                                 max_ttl=MAX(max_ttl, ttl);
1352                                 rr->rdata=(void*)((char*)rr+
1353                                                         ROUND_POINTER(sizeof(struct dns_rr)));
1354                                 memcpy(rr->rdata, l->rdata,
1355                                                         EBL_RDATA_SIZE(*(struct ebl_rdata*)l->rdata));
1356                                 /* adjust the string pointers */
1357                                 ((struct ebl_rdata*)rr->rdata)->separator=
1358                                         translate_pointer((char*)rr->rdata, (char*)l->rdata,
1359                                                                 ((struct ebl_rdata*)l->rdata)->separator);
1360                                 ((struct ebl_rdata*)rr->rdata)->separator=
1361                                                 translate_pointer((char*)rr->rdata, (char*)l->rdata,
1362                                                                 ((struct ebl_rdata*)l->rdata)->separator);
1363                                 ((struct ebl_rdata*)rr->rdata)->apex=
1364                                                 translate_pointer((char*)rr->rdata, (char*)l->rdata,
1365                                                                 ((struct ebl_rdata*)l->rdata)->apex);
1366                                 rr->next=(void*)((char*)rr+
1367                                                 ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
1368                                                         EBL_RDATA_SIZE(*(struct ebl_rdata*)l->rdata)));
1369                                 tail_rr=&(rr->next);
1370                                 rr=rr->next;
1371                         }
1372                         break;
1373                 case T_PTR:
1374                         for(l=tmp_lst; l; l=l->next){
1375                                 ttl=FIX_TTL(l->ttl);
1376                                 rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1377                                 max_ttl=MAX(max_ttl, ttl);
1378                                 rr->rdata=(void*)((char*)rr+sizeof(struct dns_rr));
1379                                 memcpy(rr->rdata, l->rdata,
1380                                                         PTR_RDATA_SIZE(*(struct ptr_rdata*)l->rdata));
1381                                 rr->next=(void*)((char*)rr+ROUND_POINTER(sizeof(struct dns_rr)+
1382                                                         PTR_RDATA_SIZE(*(struct ptr_rdata*)l->rdata)));
1383                                 tail_rr=&(rr->next);
1384                                 rr=rr->next;
1385                         }
1386                         break;
1387                 default:
1388                         /* do nothing */
1389                         LM_CRIT("type %d not supported\n", type);
1390                                 ;
1391         }
1392         *tail_rr=0; /* terminate the list */
1393         e->expire=now+S_TO_TICKS(max_ttl);
1394         free_rdata_list(tmp_lst);
1395         return e;
1396 }
1397
1398
1399
1400 /* structure used only inside dns_cache_mk_rd_entry2 to break
1401  *  the list of records into records of the same type */
1402 struct tmp_rec{
1403         struct rdata* rd;
1404         struct dns_hash_entry* e;
1405         struct dns_rr* rr;
1406         struct dns_rr** tail_rr;
1407         int max_ttl;
1408         int size;
1409 };
1410
1411
1412
1413 /* create several dns hash entries from a list of rdata structs
1414  * returns 0 on error */
1415 inline static struct dns_hash_entry* dns_cache_mk_rd_entry2(struct rdata* rd)
1416 {
1417         struct rdata* l;
1418         ticks_t now;
1419         struct tmp_rec rec[MAX_DNS_RECORDS];
1420         int rec_idx[MAX_DNS_RECORDS];
1421         int r, i, j;
1422         int no_records; /* number of different records */
1423         unsigned int ttl;
1424
1425
1426         no_records=0;
1427         rec[0].e=0;
1428         /* everything is allocated in one block: dns_hash_entry + name +
1429          * + dns_rr + rdata_raw+ ....;  dns_rr must start at an aligned adress,
1430          * hence we need to round dns_hash_entry+name size to a sizeof(long)
1431          * multiple. If rdata type requires it, rdata_raw might need to be also
1432          * aligned.
1433          * Memory image:
1434          * struct dns_hash_entry  (e)
1435          * name (name_len+1 bytes)  (&e->name[0])
1436          * padding to multiple of sizeof(char*)
1437          * dns_rr1 (e->rr_lst)
1438          * possible padding: no padding for a_rdata or aaaa_rdata,
1439          *                   multipe of sizeof(short) for srv_rdata,
1440          *                   multiple of sizeof(long) for naptr_rdata and others
1441          * dns_rr1->rdata  (e->rr_lst->rdata)
1442          * padding to multipe of sizeof long
1443          * dns_rr2 (e->rr_lst->next)
1444          * ....
1445          *
1446          */
1447         /* compute size */
1448         for(l=rd, i=0; l && (i<MAX_DNS_RECORDS); l=l->next, i++){
1449                 for (r=0; r<no_records; r++){
1450                         if ((l->type==rec[r].rd->type) &&
1451                                         (l->name_len==rec[r].rd->name_len)
1452                                 && (strncasecmp(l->name, rec[r].rd->name, l->name_len)==0)){
1453                                 /* found */
1454                                 goto found;
1455                         }
1456                 }
1457                 /* not found, create new */
1458                 if (no_records<MAX_DNS_RECORDS){
1459                         rec[r].rd=l;
1460                         rec[r].e=0;
1461                         rec[r].size=ROUND_POINTER(sizeof(struct dns_hash_entry)+
1462                                                         rec[r].rd->name_len-1+1);
1463                         no_records++;
1464                 }else{
1465                         LM_ERR("too many records: %d\n", no_records);
1466                         /* skip */
1467                         continue;
1468                 }
1469 found:
1470                 rec_idx[i]=r;
1471                 switch(l->type){
1472                         case T_A:
1473                                 /* no padding */
1474                                 rec[r].size+=ROUND_POINTER(sizeof(struct dns_rr)+
1475                                                                                 sizeof(struct a_rdata));
1476                                 break;
1477                         case T_AAAA:
1478                                 /* no padding */
1479                                 rec[r].size+=ROUND_POINTER(sizeof(struct dns_rr)+
1480                                                                                                 sizeof(struct aaaa_rdata));
1481                                 break;
1482                         case T_SRV:
1483                                 /* padding to short */
1484                                 rec[r].size+=ROUND_POINTER(ROUND_SHORT(sizeof(struct dns_rr))+
1485                                                                 SRV_RDATA_SIZE(*(struct srv_rdata*)l->rdata));
1486                                 break;
1487                         case T_NAPTR:
1488                                         /* padding to char* */
1489                                 rec[r].size+=ROUND_POINTER(ROUND_POINTER(
1490                                                                                                 sizeof(struct dns_rr))+
1491                                                         NAPTR_RDATA_SIZE(*(struct naptr_rdata*)l->rdata));
1492                                 break;
1493                         case T_CNAME:
1494                                         /* no padding */
1495                                 rec[r].size+=ROUND_POINTER(sizeof(struct dns_rr)+
1496                                                         CNAME_RDATA_SIZE(*(struct cname_rdata*)l->rdata));
1497                                 break;
1498                         case T_TXT:
1499                                         /* padding to char* (because of txt[]->cstr)*/
1500                                 rec[r].size+=ROUND_POINTER(ROUND_POINTER(
1501                                                                                                 sizeof(struct dns_rr))+
1502                                                         TXT_RDATA_SIZE(*(struct txt_rdata*)l->rdata));
1503                                 break;
1504                         case T_EBL:
1505                                         /* padding to char* (because of char* pointers)*/
1506                                 rec[r].size+=ROUND_POINTER(ROUND_POINTER(
1507                                                                                                 sizeof(struct dns_rr))+
1508                                                         EBL_RDATA_SIZE(*(struct ebl_rdata*)l->rdata));
1509                                 break;
1510                         case T_PTR:
1511                                         /* no padding */
1512                                 rec[r].size+=ROUND_POINTER(sizeof(struct dns_rr)+
1513                                                         PTR_RDATA_SIZE(*(struct ptr_rdata*)l->rdata));
1514                                 break;
1515                         default:
1516                                 LM_CRIT("type %d not supported\n", l->type);
1517                 }
1518         }
1519
1520         now=get_ticks_raw();
1521         /* alloc & init the entries */
1522         for (r=0; r<no_records; r++){
1523                 rec[r].e=shm_malloc(rec[r].size);
1524                 if (rec[r].e==0){
1525                         LM_ERR("out of memory\n");
1526                         goto error;
1527                 }
1528                 memset(rec[r].e, 0, rec[r].size); /* init with 0*/
1529                 rec[r].e->total_size=rec[r].size;
1530                 rec[r].e->name_len=rec[r].rd->name_len;
1531                 rec[r].e->type=rec[r].rd->type;
1532                 rec[r].e->last_used=now;
1533                 /* memset makes sure is 0-term. */
1534                 memcpy(rec[r].e->name, rec[r].rd->name, rec[r].rd->name_len);
1535                 rec[r].e->rr_lst=(struct dns_rr*)((char*)rec[r].e+
1536                                 ROUND_POINTER(sizeof(struct dns_hash_entry)+rec[r].e->name_len
1537                                                                  -1+1));
1538                 rec[r].tail_rr=&(rec[r].e->rr_lst);
1539                 rec[r].rr=rec[r].e->rr_lst;
1540                 rec[r].max_ttl=0;
1541                 /* link them in a list */
1542                 if (r==0){
1543                         clist_init(rec[r].e, next, prev);
1544                 }else{
1545                         clist_append(rec[0].e, rec[r].e, next, prev);
1546                 }
1547         }
1548         /* copy the actual data */
1549         for(l=rd, i=0; l && (i<MAX_DNS_RECORDS); l=l->next, i++){
1550                 r=rec_idx[i];
1551                 ttl=FIX_TTL(l->ttl);
1552                 switch(l->type){
1553                         case T_A:
1554                                 rec[r].rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1555                                 rec[r].max_ttl=MAX(rec[r].max_ttl, ttl);
1556                                 rec[r].rr->rdata=(void*)((char*)rec[r].rr+
1557                                                                         sizeof(struct dns_rr));
1558                                 memcpy(rec[r].rr->rdata, l->rdata, sizeof(struct a_rdata));
1559                                 rec[r].rr->next=(void*)((char*)rec[r].rr+
1560                                                                         ROUND_POINTER(sizeof(struct dns_rr)+
1561                                                                         sizeof(struct a_rdata)));
1562                                 rec[r].tail_rr=&(rec[r].rr->next);
1563                                 rec[r].rr=rec[r].rr->next;
1564                                 break;
1565                         case T_AAAA:
1566                                 rec[r].rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1567                                 rec[r].max_ttl=MAX(rec[r].max_ttl, ttl);
1568                                 rec[r].rr->rdata=(void*)((char*)rec[r].rr+
1569                                                                         sizeof(struct dns_rr));
1570                                 memcpy(rec[r].rr->rdata, l->rdata, sizeof(struct aaaa_rdata));
1571                                 rec[r].rr->next=(void*)((char*)rec[r].rr+
1572                                                                         ROUND_POINTER(sizeof(struct dns_rr)+
1573                                                                         sizeof(struct aaaa_rdata)));
1574                                 rec[r].tail_rr=&(rec[r].rr->next);
1575                                 rec[r].rr=rec[r].rr->next;
1576                                 break;
1577                         case T_SRV:
1578                                 rec[r].rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1579                                 rec[r].max_ttl=MAX(rec[r].max_ttl, ttl);
1580                                 rec[r].rr->rdata=(void*)((char*)rec[r].rr+
1581                                                                 ROUND_SHORT(sizeof(struct dns_rr)));
1582                                 /* copy the whole srv_rdata block*/
1583                                 memcpy(rec[r].rr->rdata, l->rdata,
1584                                                 SRV_RDATA_SIZE(*(struct srv_rdata*)l->rdata) );
1585                                 rec[r].rr->next=(void*)((char*)rec[r].rr+
1586                                                         ROUND_POINTER( ROUND_SHORT(sizeof(struct dns_rr))+
1587                                                                                 SRV_RDATA_SIZE(
1588                                                                                         *(struct srv_rdata*)l->rdata)));
1589                                 rec[r].tail_rr=&(rec[r].rr->next);
1590                                 rec[r].rr=rec[r].rr->next;
1591                                 break;
1592                         case T_NAPTR:
1593                                 rec[r].rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1594                                 rec[r].max_ttl=MAX(rec[r].max_ttl, ttl);
1595                                 rec[r].rr->rdata=(void*)((char*)rec[r].rr+
1596                                                                 ROUND_POINTER(sizeof(struct dns_rr)));
1597                                 /* copy the whole srv_rdata block*/
1598                                 memcpy(rec[r].rr->rdata, l->rdata,
1599                                                 NAPTR_RDATA_SIZE(*(struct naptr_rdata*)l->rdata) );
1600                                 /* adjust the string pointer */
1601                                 ((struct naptr_rdata*)rec[r].rr->rdata)->flags=
1602                                         translate_pointer((char*)rec[r].rr->rdata, (char*)l->rdata,
1603                                                         (((struct naptr_rdata*)l->rdata)->flags));
1604                                 ((struct naptr_rdata*)rec[r].rr->rdata)->services=
1605                                         translate_pointer((char*)rec[r].rr->rdata, (char*)l->rdata,
1606                                                         (((struct naptr_rdata*)l->rdata)->services));
1607                                 ((struct naptr_rdata*)rec[r].rr->rdata)->regexp=
1608                                         translate_pointer((char*)rec[r].rr->rdata, (char*)l->rdata,
1609                                                         (((struct naptr_rdata*)l->rdata)->regexp));
1610                                 ((struct naptr_rdata*)rec[r].rr->rdata)->repl=
1611                                         translate_pointer((char*)rec[r].rr->rdata, (char*)l->rdata,
1612                                                         (((struct naptr_rdata*)l->rdata)->repl));
1613                                 rec[r].rr->next=(void*)((char*)rec[r].rr+
1614                                                         ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
1615                                                                                 NAPTR_RDATA_SIZE(
1616                                                                                         *(struct naptr_rdata*)l->rdata)));
1617                                 rec[r].tail_rr=&(rec[r].rr->next);
1618                                 rec[r].rr=rec[r].rr->next;
1619                                 break;
1620                         case T_CNAME:
1621                                 rec[r].rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1622                                 rec[r].max_ttl=MAX(rec[r].max_ttl, ttl);
1623                                 rec[r].rr->rdata=(void*)((char*)rec[r].rr
1624                                                                         +sizeof(struct dns_rr));
1625                                 memcpy(rec[r].rr->rdata, l->rdata,
1626                                                         CNAME_RDATA_SIZE(*(struct cname_rdata*)l->rdata));
1627                                 rec[r].rr->next=(void*)((char*)rec[r].rr+
1628                                                         ROUND_POINTER(sizeof(struct dns_rr)+
1629                                                         CNAME_RDATA_SIZE(*(struct cname_rdata*)l->rdata)));
1630                                 rec[r].tail_rr=&(rec[r].rr->next);
1631                                 rec[r].rr=rec[r].rr->next;
1632                                 break;
1633                         case T_TXT:
1634                                 rec[r].rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1635                                 rec[r].max_ttl=MAX(rec[r].max_ttl, ttl);
1636                                 rec[r].rr->rdata=(void*)((char*)rec[r].rr+
1637                                                                         ROUND_POINTER(sizeof(struct dns_rr)));
1638                                 memcpy(rec[r].rr->rdata, l->rdata,
1639                                                         TXT_RDATA_SIZE(*(struct txt_rdata*)l->rdata));
1640                                 /* adjust the string pointers */
1641                                 for (j=0; j<((struct txt_rdata*)l->rdata)->cstr_no; j++){
1642                                         ((struct txt_rdata*)rec[r].rr->rdata)->txt[j].cstr=
1643                                                 translate_pointer((char*)rec[r].rr->rdata,
1644                                                                 (char*)l->rdata,
1645                                                                 ((struct txt_rdata*)l->rdata)->txt[j].cstr);
1646                                 }
1647                                 rec[r].rr->next=(void*)((char*)rec[r].rr+
1648                                                 ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
1649                                                         TXT_RDATA_SIZE(*(struct txt_rdata*)l->rdata)));
1650                                 rec[r].tail_rr=&(rec[r].rr->next);
1651                                 rec[r].rr=rec[r].rr->next;
1652                                 break;
1653                         case T_EBL:
1654                                 rec[r].rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1655                                 rec[r].max_ttl=MAX(rec[r].max_ttl, ttl);
1656                                 rec[r].rr->rdata=(void*)((char*)rec[r].rr+
1657                                                                         ROUND_POINTER(sizeof(struct dns_rr)));
1658                                 memcpy(rec[r].rr->rdata, l->rdata,
1659                                                         EBL_RDATA_SIZE(*(struct ebl_rdata*)l->rdata));
1660                                 /* adjust the string pointers */
1661                                 ((struct ebl_rdata*)rec[r].rr->rdata)->separator=
1662                                         translate_pointer((char*)rec[r].rr->rdata,
1663                                                         (char*)l->rdata,
1664                                                         ((struct ebl_rdata*)l->rdata)->separator);
1665                                 ((struct ebl_rdata*)rec[r].rr->rdata)->apex=
1666                                         translate_pointer((char*)rec[r].rr->rdata,
1667                                                         (char*)l->rdata,
1668                                                         ((struct ebl_rdata*)l->rdata)->apex);
1669                                 rec[r].rr->next=(void*)((char*)rec[r].rr+
1670                                                 ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
1671                                                         EBL_RDATA_SIZE(*(struct ebl_rdata*)l->rdata)));
1672                                 rec[r].tail_rr=&(rec[r].rr->next);
1673                                 rec[r].rr=rec[r].rr->next;
1674                                 break;
1675                         case T_PTR:
1676                                 rec[r].rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1677                                 rec[r].max_ttl=MAX(rec[r].max_ttl, ttl);
1678                                 rec[r].rr->rdata=(void*)((char*)rec[r].rr
1679                                                                         +sizeof(struct dns_rr));
1680                                 memcpy(rec[r].rr->rdata, l->rdata,
1681                                                         PTR_RDATA_SIZE(*(struct ptr_rdata*)l->rdata));
1682                                 rec[r].rr->next=(void*)((char*)rec[r].rr+
1683                                                         ROUND_POINTER(sizeof(struct dns_rr)+
1684                                                         PTR_RDATA_SIZE(*(struct ptr_rdata*)l->rdata)));
1685                                 rec[r].tail_rr=&(rec[r].rr->next);
1686                                 rec[r].rr=rec[r].rr->next;
1687                                 break;
1688                         default:
1689                                 /* do nothing */
1690                                 ;
1691                 }
1692         }
1693         for (r=0; r<no_records; r++){
1694                 *rec[r].tail_rr=0; /* terminate the list */
1695                 rec[r].e->expire=now+S_TO_TICKS(rec[r].max_ttl);
1696         }
1697         return rec[0].e;
1698 error:
1699         for (r=0; r<no_records; r++){
1700                 dns_destroy_entry(rec[r].e);
1701         }
1702         return 0;
1703 }
1704
1705
1706
1707 inline static struct dns_hash_entry* dns_get_entry(str* name, int type);
1708
1709
1710 #define CACHE_RELEVANT_RECS_ONLY
1711
1712 #ifdef CACHE_RELEVANT_RECS_ONLY
1713 /* internal only: gets related entries from a rdata list, appends them
1714  * to e (list) and returns:
1715  *  - e if e is of the requested type
1716  *  -  if e is a CNAME, tries to get to the end of the CNAME chain and returns
1717  *      the final entry if the types match or 0 if the chain is unfinished
1718  *  - 0 on error/not found
1719  * records is modified (the used records are removed from the list and freed)
1720  *
1721  * WARNING: - records must be pkg_malloc'ed
1722  * Notes:   - if the return is 0 and e->type==T_CNAME, the list will contain
1723  *            the CNAME chain (the last element being the last CNAME)
1724  *  */
1725 inline static struct dns_hash_entry* dns_get_related(struct dns_hash_entry* e,
1726                                                                                                                 int type,
1727                                                                                                                 struct rdata** records)
1728 {
1729         struct dns_hash_entry* ret;
1730         struct dns_hash_entry* l;
1731         struct dns_hash_entry* t;
1732         struct dns_hash_entry* lst_end;
1733         struct dns_rr* rr;
1734         static int cname_chain_len=0;
1735         str tmp;
1736
1737         ret=0;
1738         l=e;
1739 #ifdef DNS_CACHE_DEBUG
1740         LM_DBG("(%p (%.*s, %d), %d, *%p) (%d)\n", e,
1741                         e->name_len, e->name, e->type, type, *records, cname_chain_len);
1742 #endif
1743         clist_init(l, next, prev);
1744         if (type==e->type){
1745                 ret=e;
1746                 switch(e->type){
1747                         case T_SRV:
1748                                 for (rr=e->rr_lst; rr && *records; rr=rr->next){
1749                                         tmp.s=((struct srv_rdata*)rr->rdata)->name;
1750                                         tmp.len=((struct srv_rdata*)rr->rdata)->name_len;
1751                                         if (!(dns_flags&DNS_IPV6_ONLY)){
1752                                                 t=dns_cache_mk_rd_entry(&tmp, T_A, records);
1753                                                 if (t){
1754                                                         if ((t->type==T_CNAME) && *records)
1755                                                                 dns_get_related(t, T_A, records);
1756                                                         lst_end=t->prev; /* needed for clist_append*/
1757                                                         clist_append_sublist(l, t, lst_end, next, prev);
1758                                                 }
1759                                         }
1760                                         if (!(dns_flags&DNS_IPV4_ONLY)){
1761                                                 t=dns_cache_mk_rd_entry(&tmp, T_AAAA, records);
1762                                                 if (t){
1763                                                         if ((t->type==T_CNAME) && *records)
1764                                                                 dns_get_related(t, T_AAAA, records);
1765                                                         lst_end=t->prev; /* needed for clist_append*/
1766                                                         clist_append_sublist(l, t, lst_end, next, prev);
1767                                                 }
1768                                         }
1769                                 }
1770                                 break;
1771 #ifdef USE_NAPTR
1772                         case T_NAPTR:
1773 #ifdef NAPTR_CACHE_ALL_ARS
1774                                 if (*records)
1775                                                 dns_cache_mk_rd_entry2(*records);
1776 #else
1777                                 for (rr=e->rr_lst; rr && *records; rr=rr->next){
1778                                         if (naptr_get_sip_proto((struct naptr_rdata*)rr->rdata)>0){
1779                                                 tmp.s=((struct naptr_rdata*)rr->rdata)->repl;
1780                                                 tmp.len=((struct naptr_rdata*)rr->rdata)->repl_len;
1781                                                 t=dns_cache_mk_rd_entry(&tmp, T_SRV, records);
1782                                                 if (t){
1783                                                         if (*records)
1784                                                                 dns_get_related(t, T_SRV, records);
1785                                                         lst_end=t->prev; /* needed for clist_append*/
1786                                                         clist_append_sublist(l, t, lst_end, next, prev);
1787                                                 }
1788                                         }
1789                                 }
1790 #endif /* NAPTR_CACHE_ALL_ARS */
1791 #endif /* USE_NAPTR */
1792                                 break;
1793                         default:
1794                                 /* nothing extra */
1795                                 break;
1796                 }
1797         }else if ((e->type==T_CNAME) && (cname_chain_len<MAX_CNAME_CHAIN)){
1798                 /* only one cname is allowed (rfc2181), so we ignore
1799                  * the others (we take only the first one) */
1800                 tmp.s=((struct cname_rdata*)e->rr_lst->rdata)->name;
1801                 tmp.len=((struct cname_rdata*)e->rr_lst->rdata)->name_len;
1802                 t=dns_cache_mk_rd_entry(&tmp, type, records);
1803                 if (t){
1804                         if (*records){
1805                                 cname_chain_len++;
1806                                 ret=dns_get_related(t, type, records);
1807                                 cname_chain_len--;
1808                                 lst_end=t->prev;
1809                                 clist_append_sublist(l, t, lst_end, next, prev);
1810                         }else{
1811                                 /* if no more recs, but we found the orig. target anyway,
1812                                  *  return it (e.g. recs are only CNAME x & x A 1.2.3.4 or
1813                                  *  CNAME & SRV) */
1814                                 if (t->type==type)
1815                                         ret=t;
1816                                 clist_append(l, t, next, prev);
1817                         }
1818                 }
1819         }
1820         return ret;
1821 }
1822 #endif
1823
1824
1825
1826 /* calls the external resolver and populates the cache with the result
1827  * returns: 0 on error, pointer to hash entry on success
1828  * WARNING: make sure you use dns_hash_entry_put() when you're
1829  *  finished with the result)
1830  * */
1831 inline static struct dns_hash_entry* dns_cache_do_request(str* name, int type)
1832 {
1833         struct rdata* records;
1834         struct dns_hash_entry* e;
1835         struct dns_hash_entry* l;
1836         struct dns_hash_entry* r;
1837         struct dns_hash_entry* t;
1838         struct ip_addr* ip;
1839         str cname_val;
1840         char name_buf[MAX_DNS_NAME];
1841         struct dns_hash_entry* old;
1842         str rec_name;
1843         int add_record, h, err;
1844
1845         e=0;
1846         l=0;
1847         cname_val.s=0;
1848         old = NULL;
1849
1850 #ifdef USE_DNS_CACHE_STATS
1851         if (dns_cache_stats)
1852                 dns_cache_stats[process_no].dns_req_cnt++;
1853 #endif /* USE_DNS_CACHE_STATS */
1854
1855         if (type==T_A){
1856                 if (str2ip6(name)!=0)
1857                         goto end;
1858                 if ((ip=str2ip(name))!=0){
1859                                 e=dns_cache_mk_ip_entry(name, ip);
1860                                 if (likely(e))
1861                                         atomic_set(&e->refcnt, 1);/* because we ret. a ref. to it*/
1862                                 goto end; /* we do not cache obvious stuff */
1863                 }
1864         }
1865         else if (type==T_AAAA){
1866                 if (str2ip(name)!=0)
1867                         goto end;
1868                 if ((ip=str2ip6(name))!=0){
1869                                 e=dns_cache_mk_ip_entry(name, ip);
1870                                 if (likely(e))
1871                                         atomic_set(&e->refcnt, 1);/* because we ret. a ref. to it*/
1872                                 goto end;/* we do not cache obvious stuff */
1873                 }
1874         }
1875 #ifdef DNS_WATCHDOG_SUPPORT
1876         if (atomic_get(dns_servers_up)==0)
1877                 goto end; /* the servers are down, needless to perform the query */
1878 #endif
1879         if (name->len>=MAX_DNS_NAME){
1880                 LM_ERR("name too long (%d chars)\n", name->len);
1881                 goto end;
1882         }
1883         /* null terminate the string, needed by get_record */
1884         memcpy(name_buf, name->s, name->len);
1885         name_buf[name->len]=0;
1886         records=get_record(name_buf, type, RES_AR);
1887         if (records){
1888 #ifdef CACHE_RELEVANT_RECS_ONLY
1889                 e=dns_cache_mk_rd_entry(name, type, &records);
1890                 if (likely(e)){
1891                         l=e;
1892                         e=dns_get_related(l, type, &records);
1893                         /* e should contain the searched entry (if found) and l
1894                          * all the entries (e and related) */
1895                         if (likely(e)){
1896                                 atomic_set(&e->refcnt, 1); /* 1 because we return a
1897                                                                                                 ref. to it */
1898                         }else{
1899                                 /* e==0 => l contains a  cname list => we use the last
1900                                  * cname from the chain for a new resolve attempt (l->prev) */
1901                                 /* only one cname record is allowed (rfc2181), so we ignore
1902                                  * the others (we take only the first one) */
1903                                 cname_val.s=
1904                                         ((struct cname_rdata*)l->prev->rr_lst->rdata)->name;
1905                                 cname_val.len=
1906                                         ((struct cname_rdata*)l->prev->rr_lst->rdata)->name_len;
1907                                 LM_DBG("cname detected: %.*s (%d)\n",
1908                                                 cname_val.len, cname_val.s, cname_val.len);
1909                         }
1910                         /* add all the records to the hash */
1911                         l->prev->next=0; /* we break the double linked list for easier
1912                                                                 searching */
1913                         LOCK_DNS_HASH(); /* optimization */
1914                         for (r=l; r; r=t){
1915                                 t=r->next;
1916                                 /* add the new record to the cache by default */
1917                                 add_record = 1;
1918                                 if (cfg_get(core, core_cfg, dns_cache_rec_pref) > 0) {
1919                                         /* check whether there is an old record with the
1920                                          * same type in the cache */
1921                                         rec_name.s = r->name;
1922                                         rec_name.len = r->name_len;
1923                                         old = _dns_hash_find(&rec_name, r->type, &h, &err);
1924                                         if (old) {
1925                                                 if (old->type != r->type) {
1926                                                         /* probably CNAME found */
1927                                                         old = NULL;
1928
1929                                                 } else if (old->ent_flags & DNS_FLAG_PERMANENT) {
1930                                                         /* never overwrite permanent entries */
1931                                                         add_record = 0;
1932
1933                                                 } else if ((old->ent_flags & DNS_FLAG_BAD_NAME) == 0) {
1934                                                         /* Non-negative, non-permanent entry found with
1935                                                          * the same type. */
1936                                                         add_record =
1937                                                                 /* prefer new records */
1938                                                                 ((cfg_get(core, core_cfg, dns_cache_rec_pref) == 2)
1939                                                                 /* prefer the record with the longer lifetime */
1940                                                                 || ((cfg_get(core, core_cfg, dns_cache_rec_pref) == 3)
1941                                                                         && TICKS_LT(old->expire, r->expire)));
1942                                                 }
1943                                         }
1944                                 }
1945                                 if (add_record) {
1946                                         dns_cache_add_unsafe(r); /* refcnt++ inside */
1947                                         if (atomic_get(&r->refcnt)==0){
1948                                                 /* if cache adding failed and nobody else is interested
1949                                                  * destroy this entry */
1950                                                 dns_destroy_entry(r);
1951                                         }
1952                                         if (old) {
1953                                                 _dns_hash_remove(old);
1954                                                 old = NULL;
1955                                         }
1956                                 } else {
1957                                         if (old) {
1958                                                 if (r == e) {
1959                                                         /* this entry has to be returned */
1960                                                         e = old;
1961                                                         atomic_inc(&e->refcnt);
1962                                                 }
1963                                                 old = NULL;
1964                                         }
1965                                         dns_destroy_entry(r);
1966                                 }
1967                         }
1968                         UNLOCK_DNS_HASH();
1969                         /* if only cnames found => try to resolve the last one */
1970                         if (cname_val.s){
1971                                 LM_DBG("dns_get_entry(cname: %.*s (%d))\n",
1972                                                 cname_val.len, cname_val.s, cname_val.len);
1973                                 e=dns_get_entry(&cname_val, type);
1974                         }
1975                 }
1976 #else
1977                 l=dns_cache_mk_rd_entry2(records);
1978 #endif
1979                 free_rdata_list(records);
1980         }else if (cfg_get(core, core_cfg, dns_neg_cache_ttl)){
1981                 e=dns_cache_mk_bad_entry(name, type, 
1982                                 cfg_get(core, core_cfg, dns_neg_cache_ttl), DNS_FLAG_BAD_NAME);
1983                 if (likely(e)) {
1984                         atomic_set(&e->refcnt, 1); /* 1 because we return a ref. to it */
1985                         dns_cache_add(e); /* refcnt++ inside*/
1986                 }
1987                 goto end;
1988         }
1989 #ifndef CACHE_RELEVANT_RECS_ONLY
1990         if (l){
1991                 /* add all the records to the cache, but return only the record
1992                  * we are looking for */
1993                 l->prev->next=0; /* we break the double linked list for easier
1994                                                         searching */
1995                 LOCK_DNS_HASH(); /* optimization */
1996                 for (r=l; r; r=t){
1997                         t=r->next;
1998                         if (e==0){ /* no entry found yet */
1999                                 if (r->type==T_CNAME){
2000                                         if ((r->name_len==name->len) && (r->rr_lst) &&
2001                                                         (strncasecmp(r->name, name->s, name->len)==0)){
2002                                                 /* update the name with the name from the cname rec. */
2003                                                 cname_val.s=
2004                                                                 ((struct cname_rdata*)r->rr_lst->rdata)->name;
2005                                                 cname_val.len=
2006                                                         ((struct cname_rdata*)r->rr_lst->rdata)->name_len;
2007                                                 name=&cname_val;
2008                                         }
2009                                 }else if ((r->type==type) && (r->name_len==name->len) &&
2010                                                         (strncasecmp(r->name, name->s, name->len)==0)){
2011                                         e=r;
2012                                         atomic_set(&e->refcnt, 1); /* 1 because we return a ref.
2013                                                                                                   to it */
2014                                 }
2015                         }
2016
2017                         /* add the new record to the cache by default */
2018                         add_record = 1;
2019                         if (cfg_get(core, core_cfg, dns_cache_rec_pref) > 0) {
2020                                 /* check whether there is an old record with the
2021                                  * same type in the cache */
2022                                 rec_name.s = r->name;
2023                                 rec_name.len = r->name_len;
2024                                 old = _dns_hash_find(&rec_name, r->type, &h, &err);
2025                                 if (old) {
2026                                         if (old->type != r->type) {
2027                                                 /* probably CNAME found */
2028                                                 old = NULL;
2029
2030                                         } else if (old->ent_flags & DNS_FLAG_PERMANENT) {
2031                                                 /* never overwrite permanent entries */
2032                                                 add_record = 0;
2033
2034                                         } else if ((old->ent_flags & DNS_FLAG_BAD_NAME) == 0) {
2035                                                 /* Non-negative, non-permanent entry found with
2036                                                  * the same type. */
2037                                                 add_record =
2038                                                         /* prefer new records */
2039                                                         ((cfg_get(core, core_cfg, dns_cache_rec_pref) == 2)
2040                                                         /* prefer the record with the longer lifetime */
2041                                                         || ((cfg_get(core, core_cfg, dns_cache_rec_pref) == 3)
2042                                                                 && TICKS_LT(old->expire, r->expire)));
2043                                         }
2044                                 }
2045                         }
2046                         if (add_record) {
2047                                 dns_cache_add_unsafe(r); /* refcnt++ inside */
2048                                 if (atomic_get(&r->refcnt)==0){
2049                                         /* if cache adding failed and nobody else is interested
2050                                          * destroy this entry */
2051                                         dns_destroy_entry(r);
2052                                 }
2053                                 if (old) {
2054                                         _dns_hash_remove(old);
2055                                         old = NULL;
2056                                 }
2057                         } else {
2058                                 if (old) {
2059                                         if (r == e) {
2060                                                 /* this entry has to be returned */
2061                                                 e = old;
2062                                                 atomic_inc(&e->refcnt);
2063                                         }
2064                                         old = NULL;
2065                                 }
2066                                 dns_destroy_entry(r);
2067                         }
2068                 }
2069                 UNLOCK_DNS_HASH();
2070                 if ((e==0) && (cname_val.s)){ /* not found, but found a cname */
2071                         /* only one cname is allowed (rfc2181), so we ignore the
2072                          * others (we take only the first one) */
2073                         e=dns_get_entry(&cname_val, type);
2074                 }
2075         }
2076 #endif
2077 end:
2078         return e;
2079 }
2080
2081
2082
2083 /* tries to lookup (name, type) in the hash and if not found tries to make
2084  *  a dns request
2085  *  return: 0 on error, pointer to a dns_hash_entry on success
2086  *  WARNING: when not needed anymore dns_hash_put() must be called! */
2087 inline static struct dns_hash_entry* dns_get_entry(str* name, int type)
2088 {
2089         int h;
2090         struct dns_hash_entry* e;
2091         str cname_val;
2092         int err;
2093         static int rec_cnt=0; /* recursion protection */
2094
2095         e=0;
2096         if (rec_cnt>MAX_CNAME_CHAIN){
2097                 LM_WARN("CNAME chain too long or recursive CNAMEs (\"%.*s\")\n",
2098                                 name->len, name->s);
2099                 goto error;
2100         }
2101         rec_cnt++;
2102         e=dns_hash_get(name, type, &h, &err);
2103 #ifdef USE_DNS_CACHE_STATS
2104         if (e) {
2105                 if ((e->ent_flags & DNS_FLAG_BAD_NAME) && dns_cache_stats)
2106                         /* negative DNS cache hit */
2107                         dns_cache_stats[process_no].dc_neg_hits_cnt++;
2108                 else if (((e->ent_flags & DNS_FLAG_BAD_NAME) == 0)
2109                                 && dns_cache_stats
2110                 ) /* DNS cache hit */
2111                         dns_cache_stats[process_no].dc_hits_cnt++;
2112
2113                 if (dns_cache_stats)
2114                         dns_cache_stats[process_no].dns_req_cnt++;
2115         }
2116 #endif /* USE_DNS_CACHE_STATS */
2117
2118         if ((e==0) && ((err) || ((e=dns_cache_do_request(name, type))==0))){
2119                 goto error;
2120         }else if ((e->type==T_CNAME) && (type!=T_CNAME)){
2121                 /* cname found instead which couldn't be resolved with the cached
2122                  * info => try a dns request */
2123                 /* only one cname record is allowed (rfc2181), so we ignore
2124                  * the others (we take only the first one) */
2125                 cname_val.s= ((struct cname_rdata*)e->rr_lst->rdata)->name;
2126                 cname_val.len=((struct cname_rdata*)e->rr_lst->rdata)->name_len;
2127                 dns_hash_put(e); /* not interested in the cname anymore */
2128                 if ((e=dns_cache_do_request(&cname_val, type))==0)
2129                         goto error; /* could not resolve cname */
2130         }
2131         /* found */
2132         if ((e->rr_lst==0) || (e->ent_flags & DNS_FLAG_BAD_NAME)){
2133                 /* negative cache => not resolvable */
2134                 dns_hash_put(e);
2135                 e=0;
2136         }
2137 error:
2138         rec_cnt--;
2139         return e;
2140 }
2141
2142
2143
2144 /* gets the first non-expired record starting with record no
2145  * from the dns_hash_entry struct e
2146  * params:       e   - dns_hash_entry struct
2147  *               *no - it must contain the start record number (0 initially);
2148  *                      it will be filled with the returned record number
2149  *               now - current time/ticks value
2150  * returns pointer to the rr on success and sets no to the rr number
2151  *         0 on error and fills the error flags
2152         *
2153  * Example usage:
2154  * list all non-expired non-bad-marked ips for name:
2155  * e=dns_get_entry(name, T_A);
2156  * if (e){
2157  *    *no=0;
2158  *    now=get_ticks_raw();
2159  *    while(rr=dns_entry_get_rr(e, no, now){
2160  *       LM_DBG("address %d\n", *no);
2161  *       *no++;  ( get the next address next time )
2162  *     }
2163  *  }
2164  */
2165 inline static struct dns_rr* dns_entry_get_rr(  struct dns_hash_entry* e,
2166                                                                                          unsigned char* no, ticks_t now)
2167 {
2168         struct dns_rr* rr;
2169         int n;
2170 #ifdef DNS_WATCHDOG_SUPPORT
2171         int servers_up;
2172
2173         servers_up = atomic_get(dns_servers_up);
2174 #endif
2175
2176         for(rr=e->rr_lst, n=0;rr && (n<*no);rr=rr->next, n++);/* skip *no records*/
2177         for(;rr;rr=rr->next){
2178                 if (
2179 #ifdef DNS_WATCHDOG_SUPPORT
2180                         /* check the expiration time only when the servers are up */
2181                         servers_up &&
2182 #endif
2183                         ((e->ent_flags & DNS_FLAG_PERMANENT) == 0) &&
2184                         ((s_ticks_t)(now-rr->expire)>=0) /* expired rr */
2185                 )
2186                         continue;
2187                 /* everything is ok now */
2188                 *no=n;
2189                 return rr;
2190         }
2191         *no=n;
2192         return 0;
2193 }
2194
2195
2196 #ifdef DNS_SRV_LB
2197
2198 #define srv_reset_tried(p)      (*(p)=0)
2199 #define srv_marked(p, i)        (*(p)&(1UL<<(i)))
2200 #define srv_mark_tried(p, i)    \
2201         do{ \
2202                 (*(p)|=(1UL<<(i))); \
2203         }while(0)
2204
2205 #define srv_next_rr(n, f, i) srv_mark_tried(f, i)
2206
2207 /* returns a random number between 0 and max inclusive (0<=r<=max) */
2208 inline static unsigned dns_srv_random(unsigned max)
2209 {
2210         return fastrand_max(max);
2211 }
2212
2213 /* for a SRV record it will return the next entry to be tried according
2214  * to the RFC2782 server selection mechanism
2215  * params:
2216  *    e     is a dns srv hash entry
2217  *    no    is the start index of the current group (a group is a set of SRV
2218  *          rrs with the same priority)
2219  *    tried is a bitmap where the tried srv rrs of the same priority are
2220  *          marked
2221  *    now - current time/ticks value
2222  * returns pointer to the rr on success and sets no to the rr number
2223  *         0 on error and fills the error flags
2224  * WARNING: unlike dns_entry_get_rr() this will always return another
2225  *           another rr automatically (*no must not be incremented)
2226  *
2227  * Example usage:
2228  * list all non-expired, non-bad-marked, never tried before srv records
2229  * using the rfc2782 algo:
2230  * e=dns_get_entry(name, T_SRV);
2231  * if (e){
2232  *    no=0;
2233  *    srv_reset_tried(&tried);
2234  *    now=get_ticks_raw();
2235  *    while(rr=dns_srv_get_nxt_rr(e, &tried, &no, now){
2236  *       LM_DBG("address %d\n", *no);
2237  *     }
2238  *  }
2239  *
2240  */
2241 inline static struct dns_rr* dns_srv_get_nxt_rr(struct dns_hash_entry* e,
2242                                                                                          srv_flags_t* tried,
2243                                                                                          unsigned char* no, ticks_t now)
2244 {
2245 #define MAX_SRV_GRP_IDX         (sizeof(srv_flags_t)*8)
2246         struct dns_rr* rr;
2247         struct dns_rr* start_grp;
2248         int n;
2249         unsigned sum;
2250         unsigned prio;
2251         unsigned rand_w;
2252         int found;
2253         int saved_idx;
2254         int zero_weight; /* number of records with 0 weight */
2255         int i, idx;
2256         struct r_sums_entry{
2257                         unsigned r_sum;
2258                         struct dns_rr* rr;
2259                         }r_sums[MAX_SRV_GRP_IDX];
2260 #ifdef DNS_WATCHDOG_SUPPORT
2261         int servers_up;
2262
2263         servers_up = atomic_get(dns_servers_up);
2264 #endif
2265
2266         memset(r_sums, 0, sizeof(struct r_sums_entry) * MAX_SRV_GRP_IDX);
2267         rand_w=0;
2268         for(rr=e->rr_lst, n=0;rr && (n<*no);rr=rr->next, n++);/* skip *no records*/
2269
2270 retry:
2271         if (unlikely(rr==0))
2272                 goto no_more_rrs;
2273         start_grp=rr;
2274         prio=((struct srv_rdata*)start_grp->rdata)->priority;
2275         sum=0;
2276         saved_idx=-1;
2277         zero_weight = 0;
2278         found=0;
2279         for (idx=0;rr && (prio==((struct srv_rdata*)rr->rdata)->priority) &&
2280                                                 (idx < MAX_SRV_GRP_IDX); idx++, rr=rr->next){
2281                 if ((
2282 #ifdef DNS_WATCHDOG_SUPPORT
2283                         /* check the expiration time only when the servers are up */
2284                         servers_up &&
2285 #endif
2286                         ((e->ent_flags & DNS_FLAG_PERMANENT) == 0) &&
2287                         ((s_ticks_t)(now-rr->expire)>=0) /* expired entry */) ||
2288                                 (srv_marked(tried, idx)) ) /* already tried */{
2289                         r_sums[idx].r_sum=0; /* 0 sum, to skip over it */
2290                         r_sums[idx].rr=0;    /* debug: mark it as unused */
2291                         continue;
2292                 }
2293                 /* special case, 0 weight records should be "first":
2294                  * remember the first rr int the "virtual" list: A 0 weight must
2295                  *  come first if present, else get the first one */
2296                 if ((saved_idx==-1) || (((struct srv_rdata*)rr->rdata)->weight==0)){
2297                         saved_idx=idx;
2298                 }
2299                 zero_weight += (((struct srv_rdata*)rr->rdata)->weight == 0);
2300                 sum+=((struct srv_rdata*)rr->rdata)->weight;
2301                 r_sums[idx].r_sum=sum;
2302                 r_sums[idx].rr=rr;
2303                 found++;
2304         }
2305         if (found==0){
2306                 /* try in the next priority group */
2307                 n+=idx; /* next group start idx, last rr */
2308                 srv_reset_tried(tried);
2309                 goto retry;
2310         }else if ((found==1) || (sum==0) ||
2311                                 (((rand_w=(dns_srv_random(sum-1)+1))==1) && zero_weight &&
2312                                         (dns_srv_random(DNS_SRV_ZERO_W_CHANCE)==0))){
2313                 /* 1. if only one found, avoid a useless random() call
2314                       and select it (saved_idx will point to it).
2315                  * 2. if the sum of weights is 0 (all have 0 weight) or
2316                  * 3. rand_w==1 and there are records with 0 weight and
2317                  *    random(probab. of selecting a 0-weight)
2318                  *     immediately select a 0 weight record.
2319                  *  (this takes care of the 0-weight at the beginning requirement) */
2320                 i=saved_idx; /* saved idx contains either first 0 weight or first
2321                                                 valid record */
2322                 goto found;
2323         }
2324         /* if we are here => rand_w is not 0 and we have at least 2 valid options
2325          * => we can safely iterate on the whole r_sums[] whithout any other
2326          * extra checks */
2327         for (i=0; (i<idx) && (r_sums[i].r_sum<rand_w); i++);
2328 found:
2329 #ifdef DNS_CACHE_DEBUG
2330         LM_DBG("(%p, %lx, %d, %u): selected %d/%d in grp. %d"
2331                         " (rand_w=%d, rr=%p rd=%p p=%d w=%d rsum=%d)\n",
2332                 e, (unsigned long)*tried, *no, now, i, idx, n, rand_w, r_sums[i].rr,
2333                 (r_sums[i].rr)?r_sums[i].rr->rdata:0,
2334                 (r_sums[i].rr&&r_sums[i].rr->rdata)?((struct srv_rdata*)r_sums[i].rr->rdata)->priority:0,
2335                 (r_sums[i].rr&&r_sums[i].rr->rdata)?((struct srv_rdata*)r_sums[i].rr->rdata)->weight:0,
2336                 r_sums[i].r_sum);
2337 #endif
2338         /* i is the winner */
2339         *no=n; /* grp. start */
2340         srv_mark_tried(tried, i); /* mark it */
2341         return r_sums[i].rr;
2342 no_more_rrs:
2343         *no=n;
2344         return 0;
2345 }
2346 #endif /* DNS_SRV_LB */
2347
2348
2349
2350 /* gethostbyname compatibility: converts a dns_hash_entry structure
2351  * to a statical internal hostent structure
2352  * returns a pointer to the internal hostent structure on success or
2353  *          0 on error
2354  */
2355 inline static struct hostent* dns_entry2he(struct dns_hash_entry* e)
2356 {
2357         static struct hostent he;
2358         static char hostname[256];
2359         static char* p_aliases[1];
2360         static char* p_addr[DNS_HE_MAX_ADDR+1];
2361         static char address[16*DNS_HE_MAX_ADDR]; /* max 10 ipv6 addresses */
2362         int af, len;
2363         struct dns_rr* rr;
2364         unsigned char rr_no;
2365         ticks_t now;
2366         int i;
2367
2368         switch(e->type){
2369                 case T_A:
2370                         af=AF_INET;
2371                         len=4;
2372                         break;
2373                 case T_AAAA:
2374                         af=AF_INET6;
2375                         len=16;
2376                         break;
2377                 default:
2378                         LM_CRIT("wrong entry type %d for %.*s\n",
2379                                         e->type, e->name_len, e->name);
2380                         return 0;
2381         }
2382
2383
2384         rr_no=0;
2385         now=get_ticks_raw();
2386         /* if the entry has already expired use the time at the end of lifetime */
2387         if (unlikely((s_ticks_t)(now-e->expire)>=0)) now=e->expire-1;
2388         rr=dns_entry_get_rr(e, &rr_no, now);
2389         for(i=0; rr && (i<DNS_HE_MAX_ADDR); i++,
2390                                                         rr=dns_entry_get_rr(e, &rr_no, now)){
2391                                 p_addr[i]=&address[i*len];
2392                                 memcpy(p_addr[i], ((struct a_rdata*)rr->rdata)->ip, len);
2393         }
2394         if (i==0){
2395                 LM_DBG("no good records found (%d) for %.*s (%d)\n",
2396                                 rr_no, e->name_len, e->name, e->type);
2397                 return 0; /* no good record found */
2398         }
2399
2400         p_addr[i]=0; /* mark the end of the addresses */
2401         p_aliases[0]=0; /* no aliases */
2402         memcpy(hostname, e->name, e->name_len);
2403         hostname[e->name_len]=0;
2404
2405         he.h_addrtype=af;
2406         he.h_length=len;
2407         he.h_addr_list=p_addr;
2408         he.h_aliases=p_aliases;
2409         he.h_name=hostname;
2410
2411         return &he;
2412 }
2413
2414
2415
2416 /* gethostbyname compatibility: performs an a_lookup and returns a pointer
2417  * to a statical internal hostent structure
2418  * returns 0 on success, <0 on error (see the error codes)
2419  */
2420 inline static struct hostent* dns_a_get_he(str* name)
2421 {
2422         struct dns_hash_entry* e;
2423         struct ip_addr* ip;
2424         struct hostent* he;
2425
2426         e=0;
2427         if (str2ip6(name)!=0)
2428                 return 0;
2429         if ((ip=str2ip(name))!=0){
2430                 return ip_addr2he(name, ip);
2431         }
2432         if ((e=dns_get_entry(name, T_A))==0)
2433                 return 0;
2434         /* found */
2435         he=dns_entry2he(e);
2436         dns_hash_put(e);
2437         return he;
2438 }
2439
2440
2441 /* gethostbyname compatibility: performs an aaaa_lookup and returns a pointer
2442  * to a statical internal hostent structure
2443  * returns 0 on success, <0 on error (see the error codes)
2444  */
2445 inline static struct hostent* dns_aaaa_get_he(str* name)
2446 {
2447         struct dns_hash_entry* e;
2448         struct ip_addr* ip;
2449         struct hostent* he;
2450
2451         e=0;
2452         if (str2ip(name)!=0)
2453                 return 0;
2454         if ((ip=str2ip6(name))!=0){
2455                 return ip_addr2he(name, ip);
2456         }
2457         if ((e=dns_get_entry(name, T_AAAA))==0)
2458                         return 0;
2459         /* found */
2460         he=dns_entry2he(e);
2461         dns_hash_put(e);
2462         return he;
2463 }
2464
2465
2466
2467 /* returns 0 on success, -1 on error (rr type does not contain an ip) */
2468 inline static int dns_rr2ip(int type, struct dns_rr* rr, struct ip_addr* ip)
2469 {
2470         switch(type){
2471                 case T_A:
2472                         ip->af=AF_INET;
2473                         ip->len=4;
2474                         memcpy(ip->u.addr, ((struct a_rdata*)rr->rdata)->ip, 4);
2475                         return 0;
2476                         break;
2477                 case T_AAAA:
2478                         ip->af=AF_INET6;
2479                         ip->len=16;
2480                         memcpy(ip->u.addr, ((struct aaaa_rdata*)rr->rdata)->ip6, 16);
2481                         return 0;
2482                         break;
2483         }
2484         return -1;
2485 }
2486
2487
2488
2489 /* gethostbyname compatibility:
2490  * performs an a or aaaa dns lookup, returns 0 on error and a pointer to a
2491  *          static hostent structure on success
2492  *  flags:  - none set: tries first an a_lookup and if it fails an aaaa_lookup
2493  *          - DNS_IPV6_FIRST: tries first an aaaa_lookup and then an a_lookup
2494  *          - DNS_IPV4_ONLY: tries only an a_lookup
2495  *          - DNS_IPV6_ONLY: tries only an aaaa_lookup
2496  */
2497 struct hostent* dns_get_he(str* name, int flags)
2498 {
2499         struct hostent* he;
2500
2501         if ((flags&(DNS_IPV6_FIRST|DNS_IPV6_ONLY))){
2502                 he=dns_aaaa_get_he(name);
2503                 if (he) return he;
2504         }else{
2505                 he=dns_a_get_he(name);
2506                 if (he) return he;
2507         }
2508         if (flags&DNS_IPV6_FIRST){
2509                 he=dns_a_get_he(name);
2510         }else if (!(flags&(DNS_IPV6_ONLY|DNS_IPV4_ONLY))){
2511                 he=dns_aaaa_get_he(name);
2512         }
2513         return he;
2514 }
2515
2516
2517
2518 /* sip_resolvehost helper: gets the first good  hostent/port combination
2519  * returns 0 on error, pointer to static hostent structure on success
2520  *           (and sets port)*/
2521 struct hostent* dns_srv_get_he(str* name, unsigned short* port, int flags)
2522 {
2523         struct dns_hash_entry* e;
2524         struct dns_rr* rr;
2525         str rr_name;
2526         struct hostent* he;
2527         ticks_t now;
2528         unsigned char rr_no;
2529
2530         rr=0;
2531         he=0;
2532         now=get_ticks_raw();
2533         if ((e=dns_get_entry(name, T_SRV))==0)
2534                         goto error;
2535         /* look inside the RRs for a good one (not expired or marked bad)  */
2536         rr_no=0;
2537         while( (rr=dns_entry_get_rr(e, &rr_no, now))!=0){
2538                 /* everything is ok now, we can try to resolve the ip */
2539                 rr_name.s=((struct srv_rdata*)rr->rdata)->name;
2540                 rr_name.len=((struct srv_rdata*)rr->rdata)->name_len;
2541                 if ((he=dns_get_he(&rr_name, flags))!=0){
2542                                 /* success, at least one good ip found */
2543                                 *port=((struct srv_rdata*)rr->rdata)->port;
2544                                 goto end;
2545                 }
2546                 rr_no++; /* try from the next record, the current one was not good */
2547         }
2548         /* if we reach this point => error, we couldn't find any good rr */
2549 end:
2550         if (e) dns_hash_put(e);
2551 error:
2552         return he;
2553 }
2554
2555
2556
2557 struct hostent* dns_resolvehost(char* name)
2558 {
2559         str host;
2560         struct hostent* ret;
2561         if ((cfg_get(core, core_cfg, use_dns_cache)==0) || (dns_hash==0)){ /* not init yet */
2562                 ret =  _resolvehost(name);
2563                 if(unlikely(!ret)){
2564                         /* increment dns error counter */
2565                         if(counters_initialized())
2566                                 counter_inc(dns_cnts_h.failed_dns_req);
2567                 }
2568                 return ret;
2569         }
2570         host.s=name;
2571         host.len=strlen(name);
2572         return dns_get_he(&host, dns_flags);
2573 }
2574
2575
2576
2577
2578 #if 0
2579 /* resolves a host name trying  NAPTR,  SRV, A & AAAA lookups, for details
2580  *  see dns_sip_resolve()
2581  *  FIXME: this version will return only the first ip
2582  * returns: hostent struct & *port filled with the port from the SRV record;
2583  *  0 on error
2584  */
2585 struct hostent* dns_sip_resolvehost(str* name, unsigned short* port,
2586                                                                                 char* proto)
2587 {
2588         struct dns_srv_handle h;
2589         struct ip_addr ip;
2590         int ret;
2591
2592         if ((cfg_get(core, core_cfg, use_dns_cache==0)) || (dns_hash==0)){
2593                 /* not init or off => use normal, non-cached version */
2594                 return _sip_resolvehost(name, port, proto);
2595         }
2596         dns_srv_handle_init(&h);
2597         ret=dns_sip_resolve(&h, name, &ip, port, proto, dns_flags);
2598         dns_srv_handle_put(&h);
2599         if (ret>=0)
2600                 return ip_addr2he(name, &ip);
2601         return 0;
2602 }
2603 #endif
2604
2605
2606
2607 /* resolves a host name trying SRV lookup if *port==0 or normal A/AAAA lookup
2608  * if *port!=0.
2609  * when performing SRV lookup (*port==0) it will use proto to look for
2610  * tcp or udp hosts, otherwise proto is unused; if proto==0 => no SRV lookup
2611  * returns: hostent struct & *port filled with the port from the SRV record;
2612  *  0 on error
2613  */
2614 struct hostent* dns_srv_sip_resolvehost(str* name, unsigned short* port,
2615                                                                                 char* proto)
2616 {
2617         struct hostent* he;
2618         struct ip_addr* ip;
2619         static char tmp[MAX_DNS_NAME]; /* tmp. buff. for SRV lookups */
2620         str srv_name;
2621         char srv_proto;
2622
2623         if ((cfg_get(core, core_cfg, use_dns_cache)==0) || (dns_hash==0)){
2624                 /* not init or off => use normal, non-cached version */
2625                 return _sip_resolvehost(name, port, proto);
2626         }
2627         if (proto){ /* makes sure we have a protocol set*/
2628                 if (*proto==0)
2629                         *proto=srv_proto=PROTO_UDP; /* default */
2630                 else
2631                         srv_proto=*proto;
2632         }else{
2633                 srv_proto=PROTO_UDP;
2634         }
2635         /* try SRV if no port specified (draft-ietf-sip-srv-06) */
2636         if ((port)&&(*port==0)){
2637                 *port=(srv_proto==PROTO_TLS)?SIPS_PORT:SIP_PORT; /* just in case we
2638                                                                                                                  don't find another */
2639                 if ((name->len+SRV_MAX_PREFIX_LEN+1)>MAX_DNS_NAME){
2640                         LM_WARN("domain name too long (%d), unable to perform SRV lookup\n",
2641                                                 name->len);
2642                 }else{
2643                         /* check if it's an ip address */
2644                         if ( ((ip=str2ip(name))!=0)
2645                                   || ((ip=str2ip6(name))!=0)
2646                                 ){
2647                                 /* we are lucky, this is an ip address */
2648                                 return ip_addr2he(name,ip);
2649                         }
2650
2651                         if(srv_proto==PROTO_WS || srv_proto==PROTO_WS) {
2652                                 /* no srv records for web sockets */
2653                                 return 0;
2654                         }
2655
2656                         switch(srv_proto){
2657                                 case PROTO_UDP:
2658                                 case PROTO_TCP:
2659                                 case PROTO_TLS:
2660                                 case PROTO_SCTP:
2661                                         create_srv_name(srv_proto, name, tmp);
2662                                         break;
2663                                 default:
2664                                         LM_CRIT("unknown proto %d\n", (int)srv_proto);
2665                                         return 0;
2666                         }
2667
2668                         srv_name.s=tmp;
2669                         srv_name.len=strlen(tmp);
2670                         if ((he=dns_srv_get_he(&srv_name, port, dns_flags))!=0)
2671                                 return he;
2672                 }
2673         }
2674 /*skip_srv:*/
2675         if (name->len >= MAX_DNS_NAME) {
2676                 LM_ERR("domain name too long\n");
2677                 return 0;
2678         }
2679         he=dns_get_he(name, dns_flags);
2680         return he;
2681 }
2682
2683
2684
2685 #ifdef USE_NAPTR
2686 /* iterates over a naptr rr list, returning each time a "good" naptr record
2687  * is found.( srv type, no regex and a supported protocol)
2688  * params:
2689  *         naptr_head - naptr dns_rr list head
2690  *         tried      - bitmap used to keep track of the already tried records
2691  *                      (no more then sizeof(tried)*8 valid records are
2692  *                      ever walked
2693  *         srv_name   - if succesfull, it will be set to the selected record
2694  *                      srv name (naptr repl.)
2695  *         proto      - if succesfull it will be set to the selected record
2696  *                      protocol
2697  * returns  0 if no more records found or a pointer to the selected record
2698  *  and sets  protocol and srv_name
2699  * WARNING: when calling first time make sure you run first
2700  *           naptr_iterate_init(&tried)
2701  */
2702 struct naptr_rdata* dns_naptr_sip_iterate(struct dns_rr* naptr_head,
2703                                                                                         naptr_bmp_t* tried,
2704                                                                                         str* srv_name, char* proto)
2705 {
2706         int i, idx;
2707         struct dns_rr* l;
2708         struct naptr_rdata* naptr;
2709         struct naptr_rdata* naptr_saved;
2710         char saved_proto;
2711         char naptr_proto;
2712
2713         idx=0;
2714         naptr_proto=PROTO_NONE;
2715         naptr_saved=0;
2716         saved_proto=0;
2717         i=0;
2718         for(l=naptr_head; l && (i<MAX_NAPTR_RRS); l=l->next){
2719                 naptr=(struct naptr_rdata*) l->rdata;
2720                 if (naptr==0){
2721                         LM_CRIT("null rdata\n");
2722                         goto end;
2723                 }
2724                 /* check if valid and get proto */
2725                 if ((naptr_proto=naptr_get_sip_proto(naptr))<=0) continue;
2726                 if (*tried& (1<<i)){
2727                         i++;
2728                         continue; /* already tried */
2729                 }
2730 #ifdef DNS_CACHE_DEBUG
2731                 LM_DBG("found a valid sip NAPTR rr %.*s, proto %d\n",
2732                                 naptr->repl_len, naptr->repl, (int)naptr_proto);
2733 #endif
2734                 if ((naptr_proto_supported(naptr_proto))){
2735                         if (naptr_choose(&naptr_saved, &saved_proto,
2736                                                                 naptr, naptr_proto))
2737                                 idx=i;
2738                         }
2739                 i++;
2740         }
2741         if (naptr_saved){
2742                 /* found something */
2743 #ifdef DNS_CACHE_DEBUG
2744                 LM_DBG("choosed NAPTR rr %.*s, proto %d tried: 0x%x\n",
2745                         naptr_saved->repl_len, naptr_saved->repl, (int)saved_proto, *tried);
2746 #endif
2747                 *tried|=1<<idx;
2748                 *proto=saved_proto;
2749                 srv_name->s=naptr_saved->repl;
2750                 srv_name->len=naptr_saved->repl_len;
2751                 return naptr_saved;
2752         }
2753 end:
2754         return 0;
2755 }
2756
2757
2758
2759 /* resolves a host name trying NAPTR lookup if *proto==0 and *port==0, SRV
2760  * lookup if *port==0 or normal A/AAAA lookup
2761  * if *port!=0.
2762  * when performing SRV lookup (*port==0) it will use proto to look for
2763  * tcp or udp hosts; if proto==0 => no SRV lookup
2764  * returns: hostent struct & *port filled with the port from the SRV record;
2765  *  0 on error
2766  */
2767 struct hostent* dns_naptr_sip_resolvehost(str* name, unsigned short* port,
2768                                                                                 char* proto)
2769 {
2770         struct hostent* he;
2771         struct ip_addr* tmp_ip;
2772         naptr_bmp_t tried_bmp;
2773         struct dns_hash_entry* e;
2774         char n_proto;
2775         char origproto;
2776         str srv_name;
2777
2778         if(proto) {
2779                 origproto=*proto;
2780         } else {
2781                 origproto=PROTO_NONE;
2782         }
2783         he=0;
2784         if (dns_hash==0){ /* not init => use normal, non-cached version */
2785                 LM_WARN("called before dns cache initialization\n");
2786                 return _sip_resolvehost(name, port, proto);
2787         }
2788         if (proto && port && (*proto==0) && (*port==0)){
2789                 *proto=PROTO_UDP; /* just in case we don't find another */
2790                 /* check if it's an ip address */
2791                 if ( ((tmp_ip=str2ip(name))!=0)
2792                           || ((tmp_ip=str2ip6(name))!=0)
2793                         ){
2794                         /* we are lucky, this is an ip address */
2795                         if (((dns_flags&DNS_IPV4_ONLY) && (tmp_ip->af==AF_INET6))||
2796                                 ((dns_flags&DNS_IPV6_ONLY) && (tmp_ip->af==AF_INET))){
2797                                 return 0;
2798                         }
2799                         *port=SIP_PORT;
2800                         return ip_addr2he(name, tmp_ip);
2801                 }
2802                 /* do naptr lookup */
2803                 if ((e=dns_get_entry(name, T_NAPTR))==0)
2804                         goto naptr_not_found;
2805                 naptr_iterate_init(&tried_bmp);
2806                 while(dns_naptr_sip_iterate(e->rr_lst, &tried_bmp,
2807                                                                                                 &srv_name, &n_proto)){
2808                         if ((he=dns_srv_get_he(&srv_name, port, dns_flags))!=0){
2809 #ifdef DNS_CACHE_DEBUG
2810                                 LM_DBG("(%.*s, %d, %d) srv, ret=%p\n",
2811                                                         name->len, name->s, (int)*port, (int)*proto, he);
2812 #endif
2813                                 dns_hash_put(e);
2814                                 *proto=n_proto;
2815                                 return he;
2816                         }
2817                 }
2818                 /* no acceptable naptr record found, fallback to srv */
2819                 dns_hash_put(e);
2820         }
2821 naptr_not_found:
2822         if(proto) *proto = origproto;
2823         he = no_naptr_srv_sip_resolvehost(name,port,proto);
2824         /* fallback all the way down to A/AAAA */
2825         if (he==0) {
2826                 he=dns_get_he(name,dns_flags);
2827         }
2828    return he;
2829 }
2830 #endif /* USE_NAPTR */
2831
2832
2833
2834 /* resolves a host name trying NAPTR lookup if *proto==0 and *port==0, SRV
2835  * lookup if *port==0 or normal A/AAAA lookup
2836  * if *port!=0.
2837  * when performing SRV lookup (*port==0) it will use proto to look for
2838  * tcp or udp hosts; if proto==0 => no SRV lookup
2839  * returns: hostent struct & *port filled with the port from the SRV record;
2840  *  0 on error
2841  */
2842 struct hostent* dns_sip_resolvehost(str* name, unsigned short* port,
2843                                                                                 char* proto)
2844 {
2845 #ifdef USE_NAPTR
2846         if (dns_flags&DNS_TRY_NAPTR)
2847                 return dns_naptr_sip_resolvehost(name, port, proto);
2848 #endif
2849         return dns_srv_sip_resolvehost(name, port, proto);