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