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