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