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