c8567813e58ddf1ed39e78d9ec8d6d26904cf8f2
[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
2492
2493 #if 0
2494 /* resolves a host name trying  NAPTR,  SRV, A & AAAA lookups, for details
2495  *  see dns_sip_resolve()
2496  *  FIXME: this version will return only the first ip
2497  * returns: hostent struct & *port filled with the port from the SRV record;
2498  *  0 on error
2499  */
2500 struct hostent* dns_sip_resolvehost(str* name, unsigned short* port,
2501                                                                                 char* proto)
2502 {
2503         struct dns_srv_handle h;
2504         struct ip_addr ip;
2505         int ret;
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         dns_srv_handle_init(&h);
2512         ret=dns_sip_resolve(&h, name, &ip, port, proto, dns_flags);
2513         dns_srv_handle_put(&h);
2514         if (ret>=0)
2515                 return ip_addr2he(name, &ip);
2516         return 0;
2517 }
2518 #endif
2519
2520
2521
2522 /* resolves a host name trying SRV lookup if *port==0 or normal A/AAAA lookup
2523  * if *port!=0.
2524  * when performing SRV lookup (*port==0) it will use proto to look for
2525  * tcp or udp hosts, otherwise proto is unused; if proto==0 => no SRV lookup
2526  * returns: hostent struct & *port filled with the port from the SRV record;
2527  *  0 on error
2528  */
2529 struct hostent* dns_srv_sip_resolvehost(str* name, unsigned short* port,
2530                                                                                 char* proto)
2531 {
2532         struct hostent* he;
2533         struct ip_addr* ip;
2534         static char tmp[MAX_DNS_NAME]; /* tmp. buff. for SRV lookups */
2535         str srv_name;
2536         char srv_proto;
2537
2538         if ((cfg_get(core, core_cfg, use_dns_cache)==0) || (dns_hash==0)){
2539                 /* not init or off => use normal, non-cached version */
2540                 return _sip_resolvehost(name, port, proto);
2541         }
2542         if (proto){ /* makes sure we have a protocol set*/
2543                 if (*proto==0)
2544                         *proto=srv_proto=PROTO_UDP; /* default */
2545                 else
2546                         srv_proto=*proto;
2547         }else{
2548                 srv_proto=PROTO_UDP;
2549         }
2550         /* try SRV if no port specified (draft-ietf-sip-srv-06) */
2551         if ((port)&&(*port==0)){
2552                 *port=(srv_proto==PROTO_TLS)?SIPS_PORT:SIP_PORT; /* just in case we
2553                                                                                                                  don't find another */
2554                 if ((name->len+SRV_MAX_PREFIX_LEN+1)>MAX_DNS_NAME){
2555                         LM_WARN("domain name too long (%d), unable to perform SRV lookup\n",
2556                                                 name->len);
2557                 }else{
2558                         /* check if it's an ip address */
2559                         if ( ((ip=str2ip(name))!=0)
2560                                   || ((ip=str2ip6(name))!=0)
2561                                 ){
2562                                 /* we are lucky, this is an ip address */
2563                                 return ip_addr2he(name,ip);
2564                         }
2565
2566                         if(srv_proto==PROTO_WS || srv_proto==PROTO_WSS) {
2567                                 /* no srv records for web sockets */
2568                                 return 0;
2569                         }
2570
2571                         switch(srv_proto){
2572                                 case PROTO_UDP:
2573                                 case PROTO_TCP:
2574                                 case PROTO_TLS:
2575                                 case PROTO_SCTP:
2576                                         create_srv_name(srv_proto, name, tmp);
2577                                         break;
2578                                 default:
2579                                         LM_CRIT("unknown proto %d\n", (int)srv_proto);
2580                                         return 0;
2581                         }
2582
2583                         srv_name.s=tmp;
2584                         srv_name.len=strlen(tmp);
2585                         if ((he=dns_srv_get_he(&srv_name, port, dns_flags))!=0)
2586                                 return he;
2587                 }
2588         }
2589 /*skip_srv:*/
2590         if (name->len >= MAX_DNS_NAME) {
2591                 LM_ERR("domain name too long\n");
2592                 return 0;
2593         }
2594         he=dns_get_he(name, dns_flags);
2595         return he;
2596 }
2597
2598
2599
2600 #ifdef USE_NAPTR
2601 /* iterates over a naptr rr list, returning each time a "good" naptr record
2602  * is found.( srv type, no regex and a supported protocol)
2603  * params:
2604  *         naptr_head - naptr dns_rr list head
2605  *         tried      - bitmap used to keep track of the already tried records
2606  *                      (no more then sizeof(tried)*8 valid records are
2607  *                      ever walked
2608  *         srv_name   - if succesfull, it will be set to the selected record
2609  *                      srv name (naptr repl.)
2610  *         proto      - if succesfull it will be set to the selected record
2611  *                      protocol
2612  * returns  0 if no more records found or a pointer to the selected record
2613  *  and sets  protocol and srv_name
2614  * WARNING: when calling first time make sure you run first
2615  *           naptr_iterate_init(&tried)
2616  */
2617 struct naptr_rdata* dns_naptr_sip_iterate(struct dns_rr* naptr_head,
2618                                                                                         naptr_bmp_t* tried,
2619                                                                                         str* srv_name, char* proto)
2620 {
2621         int i, idx;
2622         struct dns_rr* l;
2623         struct naptr_rdata* naptr;
2624         struct naptr_rdata* naptr_saved;
2625         char saved_proto;
2626         char naptr_proto;
2627
2628         idx=0;
2629         naptr_proto=PROTO_NONE;
2630         naptr_saved=0;
2631         saved_proto=0;
2632         i=0;
2633         for(l=naptr_head; l && (i<MAX_NAPTR_RRS); l=l->next){
2634                 naptr=(struct naptr_rdata*) l->rdata;
2635                 if (naptr==0){
2636                         LM_CRIT("null rdata\n");
2637                         goto end;
2638                 }
2639                 /* check if valid and get proto */
2640                 if ((naptr_proto=naptr_get_sip_proto(naptr))<=0) continue;
2641                 if (*tried& (1<<i)){
2642                         i++;
2643                         continue; /* already tried */
2644                 }
2645                 LM_DBG("found a valid sip NAPTR rr %.*s, proto %d\n",
2646                                 naptr->repl_len, naptr->repl, (int)naptr_proto);
2647                 if (naptr->skip_record) {
2648                         i++;
2649                         continue;
2650                 }
2651                 if ((naptr_proto_supported(naptr_proto))){
2652                         if (naptr_choose(&naptr_saved, &saved_proto,
2653                                                                 naptr, naptr_proto))
2654                                 idx=i;
2655                         }
2656                 i++;
2657         }
2658         if (naptr_saved){
2659                 /* found something */
2660                 LM_DBG("choosed NAPTR rr %.*s, proto %d tried: 0x%x\n",
2661                         naptr_saved->repl_len, naptr_saved->repl, (int)saved_proto, *tried);
2662                 *tried|=1<<idx;
2663                 *proto=saved_proto;
2664                 srv_name->s=naptr_saved->repl;
2665                 srv_name->len=naptr_saved->repl_len;
2666                 return naptr_saved;
2667         }
2668 end:
2669         return 0;
2670 }
2671
2672
2673
2674 /* resolves a host name trying NAPTR lookup if *proto==0 and *port==0, SRV
2675  * lookup if *port==0 or normal A/AAAA lookup
2676  * if *port!=0.
2677  * when performing SRV lookup (*port==0) it will use proto to look for
2678  * tcp or udp hosts; if proto==0 => no SRV lookup
2679  * returns: hostent struct & *port filled with the port from the SRV record;
2680  *  0 on error
2681  */
2682 struct hostent* dns_naptr_sip_resolvehost(str* name, unsigned short* port,
2683                                                                                 char* proto)
2684 {
2685         struct hostent* he;
2686         struct ip_addr* tmp_ip;
2687         naptr_bmp_t tried_bmp;
2688         struct dns_hash_entry* e;
2689         char n_proto;
2690         char origproto;
2691         str srv_name;
2692
2693         if(proto) {
2694                 origproto=*proto;
2695         } else {
2696                 origproto=PROTO_NONE;
2697         }
2698         he=0;
2699         if (dns_hash==0){ /* not init => use normal, non-cached version */
2700                 LM_WARN("called before dns cache initialization\n");
2701                 return _sip_resolvehost(name, port, proto);
2702         }
2703         if (proto && port && (*proto==0) && (*port==0)){
2704                 *proto=PROTO_UDP; /* just in case we don't find another */
2705                 /* check if it's an ip address */
2706                 if ( ((tmp_ip=str2ip(name))!=0)
2707                           || ((tmp_ip=str2ip6(name))!=0)
2708                         ){
2709                         /* we are lucky, this is an ip address */
2710                         if (((dns_flags&DNS_IPV4_ONLY) && (tmp_ip->af==AF_INET6))||
2711                                 ((dns_flags&DNS_IPV6_ONLY) && (tmp_ip->af==AF_INET))){
2712                                 return 0;
2713                         }
2714                         *port=SIP_PORT;
2715                         return ip_addr2he(name, tmp_ip);
2716                 }
2717                 /* do naptr lookup */
2718                 if ((e=dns_get_entry(name, T_NAPTR))==0)
2719                         goto naptr_not_found;
2720                 naptr_iterate_init(&tried_bmp);
2721                 while(dns_naptr_sip_iterate(e->rr_lst, &tried_bmp,
2722                                                                                                 &srv_name, &n_proto)){
2723                         if ((he=dns_srv_get_he(&srv_name, port, dns_flags))!=0){
2724                                 LM_DBG("(%.*s, %d, %d) srv, ret=%p\n",
2725                                                         name->len, name->s, (int)*port, (int)*proto, he);
2726                                 dns_hash_put(e);
2727                                 *proto=n_proto;
2728                                 return he;
2729                         }
2730                 }
2731                 /* no acceptable naptr record found, fallback to srv */
2732                 dns_hash_put(e);
2733         }
2734 naptr_not_found:
2735         if(proto) *proto = origproto;
2736         he = no_naptr_srv_sip_resolvehost(name,port,proto);
2737         /* fallback all the way down to A/AAAA */
2738         if (he==0) {
2739                 he=dns_get_he(name,dns_flags);
2740         }
2741    return he;
2742 }
2743 #endif /* USE_NAPTR */
2744
2745
2746
2747 /* resolves a host name trying NAPTR lookup if *proto==0 and *port==0, SRV
2748  * lookup if *port==0 or normal A/AAAA lookup
2749  * if *port!=0.
2750  * when performing SRV lookup (*port==0) it will use proto to look for
2751  * tcp or udp hosts; if proto==0 => no SRV lookup
2752  * returns: hostent struct & *port filled with the port from the SRV record;
2753  *  0 on error
2754  */
2755 struct hostent* dns_sip_resolvehost(str* name, unsigned short* port,
2756                                                                                 char* proto)
2757 {
2758 #ifdef USE_NAPTR
2759         if (dns_flags&DNS_TRY_NAPTR)
2760                 return dns_naptr_sip_resolvehost(name, port, proto);
2761 #endif
2762         return dns_srv_sip_resolvehost(name, port, proto);
2763 }
2764
2765
2766
2767 /* performs an a lookup, fills the dns_entry pointer and the ip addr.
2768  *  (with the first good ip). if *e ==0 does the a lookup, and changes it
2769  *   to the result, if not it uses the current value and tries to use
2770  *   the rr_no record from it.
2771  * params:  e - must contain the "in-use" dns_hash_entry pointer (from
2772  *               a previous call) or *e==0 (for the first call)
2773  *          name - host name for which we do the lookup (required only
2774  *                  when *e==0)
2775  *          ip   - will be filled with the first good resolved ip started
2776  *                 at *rr_no
2777  *          rr_no - record number to start searching for a good ip from
2778  *                  (e.g. value from previous call + 1), filled on return
2779  *                  with the number of the record corresponding to the
2780  *                  returned ip
2781  * returns 0 on success, <0 on error (see the error codes),
2782  *         fills e, ip and rr_no
2783  *          On end of records (when used to iterate on all the ips) it
2784  *          will return E_DNS_EOR (you should not log an error for this
2785  *          value, is just a signal that the address list end has been reached)
2786  * Note: either e or name must be different from 0 (name.s !=0 also)
2787  * WARNING: dns_hash_put(*e) must be called when you don't need
2788  *          the entry anymore and *e!=0 (failling to do so => mem. leak)
2789  * Example:
2790  *  dns_entry=0;
2791  *  ret=dns_a_get_ip(&dns_entry, name, &ip, &rr_no);  -- get the first rr.
2792  *  ...
2793  *  rr_no++;
2794  *  while((ret>=0) && dns_entry)
2795  *     dns_a_get_ip(&dns_entry, name, &ip, &rr_no); -- get the next rr
2796  *   if (ret!=-E_DNS_EOR) ERROR(....);
2797  *  ...
2798  *  dns_hash_put(dns_entry); -- finished with the entry
2799  */
2800 inline static int dns_a_resolve( struct dns_hash_entry** e,
2801                                                                  unsigned char* rr_no,
2802                                                                  str* name,
2803                                                                  struct ip_addr* ip)
2804 {
2805         struct dns_rr* rr;
2806         int ret;
2807         ticks_t now;
2808         struct ip_addr* tmp;
2809
2810         rr=0;
2811         ret=-E_DNS_NO_IP;
2812         if (*e==0){ /* do lookup */
2813                 /* if ip don't set *e */
2814                 if (str2ip6(name)!=0)
2815                         goto error;
2816                 if ((tmp=str2ip(name))!=0){
2817                         *ip=*tmp;
2818                         *rr_no=0;
2819                         return 0;
2820                 }
2821                 if ((*e=dns_get_entry(name, T_A))==0)
2822                         goto error;
2823                 /* found */
2824                 *rr_no=0;
2825         }
2826         now=get_ticks_raw();
2827         /* if the entry has already expired use the time at the end of lifetime */
2828         if (unlikely((s_ticks_t)(now-(*e)->expire)>=0)) now=(*e)->expire-1;
2829         rr=dns_entry_get_rr(*e, rr_no, now);
2830         if (rr){
2831                 /* everything is ok now, we can try to "convert" the ip */
2832                 dns_rr2ip((*e)->type, rr, ip);
2833                 ret=0;
2834         }else{
2835                 ret=-E_DNS_EOR;
2836         }
2837 error:
2838         LM_DBG("(%.*s, %d) returning %d\n", name->len, name->s, *rr_no, ret);
2839         return ret;
2840 }
2841
2842
2843 /* lookup, fills the dns_entry pointer and the ip addr.
2844  *  (with the first good ip). if *e ==0 does the a lookup, and changes it
2845  *   to the result, if not it uses the current value and tries to use
2846  * Same as dns_a_resolve but for aaaa records (see above).
2847  */
2848 inline static int dns_aaaa_resolve( struct dns_hash_entry** e,
2849                                                                         unsigned char* rr_no,
2850                                                                         str* name,
2851                                                                         struct ip_addr* ip)
2852 {
2853         struct dns_rr* rr;
2854         int ret;
2855         ticks_t now;
2856         struct ip_addr* tmp;
2857
2858         rr=0;
2859         ret=-E_DNS_NO_IP;
2860         if (*e==0){ /* do lookup */
2861                 /* if ip don't set *e */
2862                 if (str2ip(name)!=0)
2863                         goto error;
2864                 if ((tmp=str2ip6(name))!=0){
2865                         *ip=*tmp;
2866                         *rr_no=0;
2867                         return 0;
2868                 }
2869                 if ((*e=dns_get_entry(name, T_AAAA))==0)
2870                         goto error;
2871                 /* found */
2872                 *rr_no=0;
2873         }
2874         now=get_ticks_raw();
2875         /* if the entry has already expired use the time at the end of lifetime */
2876         if (unlikely((s_ticks_t)(now-(*e)->expire)>=0)) now=(*e)->expire-1;
2877         rr=dns_entry_get_rr(*e, rr_no, now);
2878         if (rr){
2879                 /* everything is ok now, we can try to "convert" the ip */
2880                 dns_rr2ip((*e)->type, rr, ip);
2881                 ret=0;
2882         }else{
2883                 ret=-E_DNS_EOR; /* no more records */
2884         }
2885 error:
2886         return ret;
2887 }
2888
2889
2890
2891 /* performs an a or aaaa dns lookup, returns <0 on error (see the
2892  *  dns error codes) and 0 on success
2893  *  flags:  - none set: tries first an a_lookup and if it fails an aaaa_lookup
2894  *          - DNS_IPV6_FIRST: tries first an aaaa_lookup and then an a_lookup
2895  *          - DNS_IPV4_ONLY: tries only an a_lookup
2896  *          - DNS_IPV6_ONLY: tries only an aaaa_lookup
2897  *  see dns_a_resolve() for the rest of the params., examples a.s.o
2898  *  WARNING: don't forget dns_hash_put(*e) when e is not needed anymore
2899  */
2900 inline static int dns_ip_resolve(       struct dns_hash_entry** e,
2901                                                                         unsigned char* rr_no,
2902                                                                         str* name,
2903                                                                         struct ip_addr* ip,
2904                                                                         int flags)
2905 {
2906         int ret, orig_ret;
2907         str host;
2908         struct dns_hash_entry* orig;
2909
2910         ret=-E_DNS_NO_IP;
2911         if (*e==0){ /* first call */
2912                 if ((flags&(DNS_IPV6_FIRST|DNS_IPV6_ONLY))){
2913                         ret=dns_aaaa_resolve(e, rr_no, name, ip);
2914                         if (ret>=0) return ret;
2915                 }else{
2916                         ret=dns_a_resolve(e, rr_no, name, ip);
2917                         if (ret>=0) return ret;
2918                 }
2919                 if (flags&DNS_IPV6_FIRST){
2920                         ret=dns_a_resolve(e, rr_no, name, ip);
2921                 }else if (!(flags&(DNS_IPV6_ONLY|DNS_IPV4_ONLY))){
2922                         ret=dns_aaaa_resolve(e, rr_no, name, ip);
2923                 }
2924         }else if ((*e)->type==T_A){
2925                 /* continue A resolving */
2926                 /* retrieve host name from the hash entry  (ignore name which might
2927                   be null when continuing a srv lookup) */
2928                 host.s=(*e)->name;
2929                 host.len=(*e)->name_len;
2930                 ret=dns_a_resolve(e, rr_no, &host, ip);
2931                 if (ret>=0) return ret;
2932                 if (!(flags&(DNS_IPV6_ONLY|DNS_IPV6_FIRST|DNS_IPV4_ONLY))){
2933                         /* not found, try with AAAA */
2934                         orig_ret=ret;
2935                         orig=*e;
2936                         *e=0;
2937                         *rr_no=0;
2938                         ret=dns_aaaa_resolve(e, rr_no, &host, ip);
2939                         if (ret==-E_DNS_NO_IP && orig_ret==-E_DNS_EOR)
2940                                 ret=orig_ret;
2941                         /* delay original record release until we're finished with host*/
2942                         dns_hash_put(orig);
2943                 }
2944         }else if ((*e)->type==T_AAAA){
2945                 /* retrieve host name from the hash entry  (ignore name which might
2946                   be null when continuing a srv lookup) */
2947                 host.s=(*e)->name;
2948                 host.len=(*e)->name_len;
2949                 /* continue AAAA resolving */
2950                 ret=dns_aaaa_resolve(e, rr_no, &host, ip);
2951                 if (ret>=0) return ret;
2952                 if ((flags&DNS_IPV6_FIRST) && !(flags&DNS_IPV6_ONLY)){
2953                         /* not found, try with A */
2954                         orig_ret=ret;
2955                         orig=*e;
2956                         *e=0;
2957                         *rr_no=0;
2958                         ret=dns_a_resolve(e, rr_no, &host, ip);
2959                         if (ret==-E_DNS_NO_IP && orig_ret==-E_DNS_EOR)
2960                                 ret=orig_ret;
2961                         /* delay original record release until we're finished with host*/
2962                         dns_hash_put(orig);
2963                 }
2964         }else{
2965                 LM_CRIT("invalid record type %d\n", (*e)->type);
2966         }
2967         return ret;
2968 }
2969
2970
2971
2972 /*  gets the first srv record starting at rr_no
2973  *  Next call will return the next record a.s.o.
2974  *  (similar to dns_a_resolve but for srv, sets host, port and automatically
2975  *   switches to the next record in the future)
2976  *
2977  *   if DNS_SRV_LB and tried!=NULL will do random weight based selection
2978  *   for choosing between SRV RRs with the same priority (as described in
2979  *    RFC2782).
2980  *   If tried==NULL or DNS_SRV_LB is not defined => always returns next
2981  *    record in the priority order and for records with the same priority
2982  *     the record with the higher weight (from the remaining ones)
2983  */
2984 inline static int dns_srv_resolve_nxt(struct dns_hash_entry** e,
2985 #ifdef DNS_SRV_LB
2986                                                 srv_flags_t* tried,
2987 #endif
2988                                                 unsigned char* rr_no,
2989                                                 str* name, str* host, unsigned short* port)
2990 {
2991         struct dns_rr* rr;
2992         int ret;
2993         ticks_t now;
2994
2995         rr=0;
2996         ret=-E_DNS_NO_SRV;
2997         if (*e==0){
2998                 if ((*e=dns_get_entry(name, T_SRV))==0)
2999                         goto error;
3000                 /* found it */
3001                 *rr_no=0;
3002 #ifdef DNS_SRV_LB
3003                 if (tried)
3004                         srv_reset_tried(tried);
3005 #endif
3006         }
3007         now=get_ticks_raw();
3008         /* if the entry has already expired use the time at the end of lifetime */
3009         if (unlikely((s_ticks_t)(now-(*e)->expire)>=0)) now=(*e)->expire-1;
3010 #ifdef DNS_SRV_LB
3011         if (tried){
3012                 rr=dns_srv_get_nxt_rr(*e, tried, rr_no, now);
3013         }else
3014 #endif
3015         {
3016                 rr=dns_entry_get_rr(*e, rr_no, now);
3017                 (*rr_no)++; /* try next record next time */
3018         }
3019         if (rr){
3020                 host->s=((struct srv_rdata*)rr->rdata)->name;
3021                 host->len=((struct srv_rdata*)rr->rdata)->name_len;
3022                 *port=((struct srv_rdata*)rr->rdata)->port;
3023                 ret=0;
3024         }else{
3025                 ret=-E_DNS_EOR; /* no more records */
3026         }
3027 error:
3028         return ret;
3029 }
3030
3031
3032
3033 /*  gets the first srv record starting at h->srv_no, resolve it
3034  *   and get the first ip address (starting at h->ip_no)
3035  *  (similar to dns_a_resolve but for srv, sets host, port)
3036  *  WARNING: don't forget to init h prior to calling this function the first
3037  *   time and dns_srv_handle_put(h), even if error is returned
3038  */
3039 inline static int dns_srv_resolve_ip(struct dns_srv_handle* h,
3040                                         str* name, struct ip_addr* ip, unsigned short* port,
3041                                         int flags)
3042 {
3043         int ret;
3044         str host;
3045
3046         host.len=0;
3047         host.s=0;
3048         do{
3049                 if (h->a==0){
3050 #ifdef DNS_SRV_LB
3051                         if ((ret=dns_srv_resolve_nxt(&h->srv,
3052                                                                 (flags & DNS_SRV_RR_LB)?&h->srv_tried_rrs:0,
3053                                                                 &h->srv_no,
3054                                                                 name, &host, port))<0)
3055                                 goto error;
3056 #else
3057                         if ((ret=dns_srv_resolve_nxt(&h->srv, &h->srv_no,
3058                                                                 name, &host, port))<0)
3059                                 goto error;
3060 #endif
3061                         h->port=*port; /* store new port */
3062                 }else{
3063                         *port=h->port; /* return the stored port */
3064                 }
3065                 if ((ret=dns_ip_resolve(&h->a, &h->ip_no, &host, ip, flags))<0){
3066                         /* couldn't find any good ip for this record, try the next one */
3067                         if (h->a){
3068                                 dns_hash_put(h->a);
3069                                 h->a=0;
3070                         }
3071                 }else if (h->a==0){
3072                         /* this was an ip, try the next srv record in the future */
3073                 }
3074         }while(ret<0);
3075 error:
3076         LM_DBG("(\"%.*s\", %d, %d), ret=%d, ip=%s\n",
3077                         name->len, name->s, h->srv_no, h->ip_no, ret,
3078                         ip?ZSW(ip_addr2a(ip)):"");
3079         return ret;
3080 }
3081
3082
3083
3084 /* resolves a host name trying SRV lookup if *port==0 or normal A/AAAA lookup
3085  * if *port!=0.
3086  * when performing SRV lookup (*port==0) it will use proto to look for
3087  * tcp or udp hosts, otherwise proto is unused; if proto==0 => no SRV lookup
3088  * h must be initialized prior to  calling this function and can be used to
3089  * get the subsequent ips
3090  * returns:  <0 on error
3091  *            0 on success and it fills *ip, *port, *h
3092  */
3093 inline static int dns_srv_sip_resolve(struct dns_srv_handle* h,  str* name,
3094                                                 struct ip_addr* ip, unsigned short* port, char* proto,
3095                                                 int flags)
3096 {
3097         struct dns_srv_proto srv_proto_list[PROTO_LAST];
3098         static char tmp[MAX_DNS_NAME]; /* tmp. buff. for SRV lookups */
3099         str srv_name;
3100         struct ip_addr* tmp_ip;
3101         int ret;
3102         struct hostent* he;
3103         size_t i,list_len;
3104         char origproto = 0;
3105
3106         if(proto) origproto = *proto;
3107         if (dns_hash==0){ /* not init => use normal, non-cached version */
3108                 LM_WARN("called before dns cache initialization\n");
3109                 h->srv=h->a=0;
3110                 he=_sip_resolvehost(name, port, proto);
3111                 if (he){
3112                         hostent2ip_addr(ip, he, 0);
3113                         return 0;
3114                 }
3115                 return -E_DNS_NO_SRV;
3116         }
3117         if ((h->srv==0) && (h->a==0)){ /* first call */
3118                 if (proto) {
3119                         if(*proto==0) { /* makes sure we have a protocol set*/
3120                                 *proto=PROTO_UDP; /* default */
3121                         }
3122                         h->port=(*proto==PROTO_TLS)?SIPS_PORT:SIP_PORT; /* just in case we
3123                                                                                                                 don't find another */
3124                         h->proto=*proto; /* store initial protocol */
3125                 } else {
3126                         h->proto=PROTO_UDP; /* default */
3127                 }
3128                 if (port){
3129                         if (*port==0){
3130                                 /* try SRV if initial call & no port specified
3131                                  * (draft-ietf-sip-srv-06) */
3132                                 if ((name->len+SRV_MAX_PREFIX_LEN+1)>MAX_DNS_NAME){
3133                                         LM_WARN("domain name too long (%d), unable to perform SRV lookup\n",
3134                                                                 name->len);
3135                                 }else{
3136                                         /* check if it's an ip address */
3137                                         if ( ((tmp_ip=str2ip(name))!=0)
3138                                                   || ((tmp_ip=str2ip6(name))!=0)
3139                                                 ){
3140                                                 /* we are lucky, this is an ip address */
3141                                                 if (((flags&DNS_IPV4_ONLY) && (tmp_ip->af==AF_INET6))||
3142                                                         ((flags&DNS_IPV6_ONLY) && (tmp_ip->af==AF_INET))){
3143                                                         return -E_DNS_AF_MISMATCH;
3144                                                 }
3145                                                 *ip=*tmp_ip;
3146                                                 *port=h->port;
3147                                                 /* proto already set */
3148                                                 return 0;
3149                                         }
3150
3151                                         /* looping on the ordered list until we found a protocol what has srv record */
3152                                         list_len = create_srv_pref_list(&origproto, srv_proto_list);
3153                                         for (i=0; i<list_len;i++) {
3154                                                 switch (srv_proto_list[i].proto) {
3155                                                         case PROTO_UDP:
3156                                                         case PROTO_TCP:
3157                                                         case PROTO_TLS:
3158                                                         case PROTO_SCTP:
3159                                                                 create_srv_name(srv_proto_list[i].proto, name, tmp);
3160                                                                 break;
3161                                                         default:
3162                                                                 LM_CRIT("unknown proto %d\n", (int)srv_proto_list[i].proto);
3163                                                                 return -E_DNS_CRITICAL;
3164                                                 }
3165                                                 srv_name.s=tmp;
3166                                                 srv_name.len=strlen(tmp);
3167                                                 if ((ret=dns_srv_resolve_ip(h, &srv_name, ip, port, flags))>=0)
3168                                                 {
3169                                                         h->proto = srv_proto_list[i].proto;
3170                                                         if(proto) *proto = h->proto;
3171                                                         LM_DBG("(%.*s, %d, %d), srv0, ret=%d\n",
3172                                                                 name->len, name->s, h->srv_no, h->ip_no, ret);
3173                                                         return ret;
3174                                                 }
3175                                         }
3176                                 }
3177                         }else{ /* if (*port==0) */
3178                                 h->port=*port; /* store initial port */
3179                                 /* proto already set */
3180                         }
3181                 } /* if (port) */
3182         }else if (h->srv){
3183                         srv_name.s=h->srv->name;
3184                         srv_name.len=h->srv->name_len;
3185                         /* continue srv resolving */
3186                         ret=dns_srv_resolve_ip(h, &srv_name, ip, port, flags);
3187                         if (proto)
3188                                 *proto=h->proto;
3189                         LM_DBG("(%.*s, %d, %d), srv, ret=%d\n",
3190                                         name->len, name->s, h->srv_no, h->ip_no, ret);
3191                         return ret;
3192         }
3193         if (name->len >= MAX_DNS_NAME) {
3194                 LM_ERR("domain name too long\n");
3195                 return -E_DNS_NAME_TOO_LONG;
3196         }
3197         ret=dns_ip_resolve(&h->a, &h->ip_no, name, ip, flags);
3198         if (port)
3199                 *port=h->port;
3200         if (proto)
3201                 *proto=h->proto;
3202         LM_DBG("(%.*s, %d, %d), ip, ret=%d\n",
3203                         name->len, name->s, h->srv_no, h->ip_no, ret);
3204         return ret;
3205 }
3206
3207
3208
3209 #ifdef USE_NAPTR
3210
3211
3212 static void mark_skip_current_naptr(struct dns_rr* naptr_head, struct dns_hash_entry* srv)
3213 {
3214         int i;
3215         struct dns_rr* l;
3216         struct naptr_rdata* naptr;
3217
3218         if (!naptr_head || !srv) {
3219                 return;
3220         }
3221
3222         for(l=naptr_head, i=0; l && (i<MAX_NAPTR_RRS); l=l->next, i++) {
3223                 naptr = (struct naptr_rdata *) l->rdata;
3224                 if (naptr == 0)