1 /*
2 * resolver related functions
3 *
4 * Copyright (C) 2006 iptelorg GmbH
5 *
6 * This file is part of Kamailio, a free SIP server.
7 *
8 * Kamailio is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version
12 *
13 * Kamailio is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23 /*!
24 * \file
25 * \brief Kamailio core :: DNS cache handling
26 * \ingroup core
27 * Module: \ref core
28 */
29
30
31 #ifdef USE_DNS_CACHE
32
33 #ifdef DNS_SRV_LB
34 #include <stdlib.h> /* FIXME: rand() */
35 #endif
36 #include <string.h>
37
38 #include "globals.h"
39 #include "cfg_core.h"
40 #include "dns_cache.h"
41 #include "dns_wrappers.h"
42 #include "compiler_opt.h"
43 #include "mem/shm_mem.h"
44 #include "hashes.h"
45 #include "clist.h"
46 #include "locking.h"
47 #include "atomic_ops.h"
48 #include "ut.h"
49 #include "timer.h"
50 #include "timer_ticks.h"
51 #include "error.h"
52 #include "rpc.h"
53 #include "rand/fastrand.h"
54 #ifdef USE_DNS_CACHE_STATS
55 #include "pt.h"
56 #endif
57
58
59
60
61
62 #ifndef MAX
63 #define MAX(a,b) ( ((a)>(b))?(a):(b))
64 #endif
65
66 #define MAX_DNS_RECORDS 255 /* maximum dns records number received in a
67 dns answer*/
68
69 #define DNS_HASH_SIZE 1024 /* must be <= 65535 */
70 #define DEFAULT_DNS_TIMER_INTERVAL 120 /* 2 min. */
71 #define DNS_HE_MAX_ADDR 10 /* maxium addresses returne in a hostent struct */
72 #define MAX_CNAME_CHAIN 10
73 #define SPACE_FORMAT " " /* format of view output */
74 #define DNS_SRV_ZERO_W_CHANCE 1000 /* one in a 1000*weight_sum chance for
75 selecting a 0-weight record */
76
77 int dns_cache_init=1; /* if 0, the DNS cache is not initialized at startup */
78 static gen_lock_t* dns_hash_lock=0;
79 static volatile unsigned int *dns_cache_mem_used=0; /* current mem. use */
80 unsigned int dns_timer_interval=DEFAULT_DNS_TIMER_INTERVAL; /* in s */
81 int dns_flags=0; /* default flags used for the dns_*resolvehost
82 (compatibility wrappers) */
83
84 #ifdef USE_DNS_CACHE_STATS
85 struct t_dns_cache_stats* dns_cache_stats=0;
86 #endif
87
88 #define LOCK_DNS_HASH() lock_get(dns_hash_lock)
89 #define UNLOCK_DNS_HASH() lock_release(dns_hash_lock)
90
91 #define FIX_TTL(t) \
92 (((t)<cfg_get(core, core_cfg, dns_cache_min_ttl))? \
93 cfg_get(core, core_cfg, dns_cache_min_ttl): \
94 (((t)>cfg_get(core, core_cfg, dns_cache_max_ttl))? \
95 cfg_get(core, core_cfg, dns_cache_max_ttl): \
96 (t)))
97
98
99 struct dns_hash_head{
100 struct dns_hash_entry* next;
101 struct dns_hash_entry* prev;
102 };
103
104 struct dns_lu_lst* dns_last_used_lst=0;
105
106 static struct dns_hash_head* dns_hash=0;
107
108
109 static struct timer_ln* dns_timer_h=0;
110
111 #ifdef DNS_WATCHDOG_SUPPORT
112 static atomic_t *dns_servers_up = NULL;
113 #endif
114
115
116
117 static const char* dns_str_errors[]={
118 "no error",
119 "no more records", /* not an error, but and end condition */
120 "unknown error",
121 "internal error",
122 "bad SRV entry",
123 "unresolvable SRV request",
124 "bad A or AAAA entry",
125 "unresolvable A or AAAA request",
126 "invalid ip in A or AAAA record",
127 "blacklisted ip",
128 "name too long ", /* try again with a shorter name */
129 "ip AF mismatch", /* address family mismatch */
130 "unresolvable NAPTR request",
131 "bug - critical error"
132 };
133
134
135
136 /* param: err (negative error number) */
dns_strerror(int err)137 const char* dns_strerror(int err)
138 {
139 err=-err;
140 if ((err>=0) && (err<sizeof(dns_str_errors)/sizeof(char*)))
141 return dns_str_errors[err];
142 return "bug -- bad error number";
143 }
144
145
146
147 /* "internal" only, don't use unless you really know waht you're doing */
dns_destroy_entry(struct dns_hash_entry * e)148 inline static void dns_destroy_entry(struct dns_hash_entry* e)
149 {
150 memset(e, 0, e->total_size);
151 shm_free(e); /* nice having it in one block isn't it? :-) */
152 }
153
154
155 /* "internal" only, same as above, asumes shm_lock() held (tm optimization) */
dns_destroy_entry_shm_unsafe(struct dns_hash_entry * e)156 inline static void dns_destroy_entry_shm_unsafe(struct dns_hash_entry* e)
157 {
158 memset(e, 0, e->total_size);
159 shm_free_unsafe(e); /* nice having it in one block isn't it? :-) */
160 }
161
162
163
164 /* dec. the internal refcnt and if 0 deletes the entry */
dns_hash_put(struct dns_hash_entry * e)165 void dns_hash_put(struct dns_hash_entry* e)
166 {
167 if(e && atomic_dec_and_test(&e->refcnt)){
168 /* atomic_sub_long(dns_cache_total_used, e->total_size); */
169 dns_destroy_entry(e);
170 }
171 }
172
173
174
175 /* same as above but uses dns_destroy_unsafe (assumes shm_lock held -- tm
176 * optimization) */
dns_hash_put_shm_unsafe(struct dns_hash_entry * e)177 void dns_hash_put_shm_unsafe(struct dns_hash_entry* e)
178 {
179 if(e && atomic_dec_and_test(&e->refcnt)){
180 /* atomic_sub_long(dns_cache_total_used, e->total_size); */
181 dns_destroy_entry_shm_unsafe(e);
182 }
183 }
184
185
186 inline static int dns_cache_clean(unsigned int no, int expired_only);
187 inline static int dns_cache_free_mem(unsigned int target, int expired_only);
188
dns_timer(ticks_t ticks,struct timer_ln * tl,void * data)189 static ticks_t dns_timer(ticks_t ticks, struct timer_ln* tl, void* data)
190 {
191 #ifdef DNS_WATCHDOG_SUPPORT
192 /* do not clean the hash table if the servers are down */
193 if (atomic_get(dns_servers_up) == 0)
194 return (ticks_t)(-1);
195 #endif
196 if (*dns_cache_mem_used>12*(cfg_get(core, core_cfg, dns_cache_max_mem)/16)){ /* ~ 75% used */
197 dns_cache_free_mem(cfg_get(core, core_cfg, dns_cache_max_mem)/2, 1);
198 }else{
199 dns_cache_clean(-1, 1); /* all the table, only expired entries */
200 /* TODO: better strategy? */
201 }
202 return (ticks_t)(-1);
203 }
204
205
206
destroy_dns_cache()207 void destroy_dns_cache()
208 {
209 if (dns_timer_h){
210 timer_del(dns_timer_h);
211 timer_free(dns_timer_h);
212 dns_timer_h=0;
213 }
214 #ifdef DNS_WATCHDOG_SUPPORT
215 if (dns_servers_up){
216 shm_free(dns_servers_up);
217 dns_servers_up=0;
218 }
219 #endif
220 if (dns_hash_lock){
221 lock_destroy(dns_hash_lock);
222 lock_dealloc(dns_hash_lock);
223 dns_hash_lock=0;
224 }
225 if (dns_hash){
226 shm_free(dns_hash);
227 dns_hash=0;
228 }
229 if (dns_last_used_lst){
230 shm_free(dns_last_used_lst);
231 dns_last_used_lst=0;
232 }
233 #ifdef USE_DNS_CACHE_STATS
234 if (dns_cache_stats)
235 shm_free(dns_cache_stats);
236 #endif
237 if (dns_cache_mem_used){
238 shm_free((void*)dns_cache_mem_used);
239 dns_cache_mem_used=0;
240 }
241 }
242
243 /* set the value of dns_flags */
fix_dns_flags(str * gname,str * name)244 void fix_dns_flags(str *gname, str *name)
245 {
246 /* restore the original value of dns_cache_flags first
247 * (DNS_IPV4_ONLY may have been set only because dns_try_ipv6
248 * was disabled, and the flag must be cleared when
249 * dns_try_ipv6 is enabled) (Miklos)
250 */
251 dns_flags = cfg_get(core, core_cfg, dns_cache_flags) & 7;
252
253 if (cfg_get(core, core_cfg, dns_try_ipv6)==0){
254 dns_flags|=DNS_IPV4_ONLY;
255 }
256 if (dns_flags & DNS_IPV4_ONLY){
257 dns_flags&=~(DNS_IPV6_ONLY|DNS_IPV6_FIRST);
258 }
259 if (cfg_get(core, core_cfg, dns_srv_lb)){
260 #ifdef DNS_SRV_LB
261 dns_flags|=DNS_SRV_RR_LB;
262 #else
263 LM_WARN("SRV loadbalaning is set, but"
264 " support for it is not compiled -- ignoring\n");
265 #endif
266 }
267 if (cfg_get(core, core_cfg, dns_try_naptr)) {
268 #ifndef USE_NAPTR
269 LM_WARN("NAPTR support is enabled, but"
270 " support for it is not compiled -- ignoring\n");
271 #endif
272 dns_flags|=DNS_TRY_NAPTR;
273 }
274 }
275
276 /* fixup function for use_dns_failover
277 * verifies that use_dns_cache is set to 1
278 */
use_dns_failover_fixup(void * handle,str * gname,str * name,void ** val)279 int use_dns_failover_fixup(void *handle, str *gname, str *name, void **val)
280 {
281 if ((int)(long)(*val) && !cfg_get(core, handle, use_dns_cache)) {
282 LM_ERR("DNS cache is turned off, failover cannot be enabled. "
283 "(set use_dns_cache to 1)\n");
284 return -1;
285 }
286 return 0;
287 }
288
289 /* fixup function for use_dns_cache
290 * verifies that dns_cache_init is set to 1
291 */
use_dns_cache_fixup(void * handle,str * gname,str * name,void ** val)292 int use_dns_cache_fixup(void *handle, str *gname, str *name, void **val)
293 {
294 if ((int)(long)(*val) && !dns_cache_init) {
295 LM_ERR("DNS cache is turned off by dns_cache_init=0, "
296 "it cannot be enabled runtime.\n");
297 return -1;
298 }
299 if (((int)(long)(*val)==0) && cfg_get(core, handle, use_dns_failover)) {
300 LM_ERR("DNS failover depends on use_dns_cache, set use_dns_failover "
301 "to 0 before disabling the DNS cache\n");
302 return -1;
303 }
304 return 0;
305 }
306
307 /* KByte to Byte conversion */
dns_cache_max_mem_fixup(void * handle,str * gname,str * name,void ** val)308 int dns_cache_max_mem_fixup(void *handle, str *gname, str *name, void **val)
309 {
310 unsigned int u;
311
312 u = ((unsigned int)(long)(*val))<<10;
313 (*val) = (void *)(long)u;
314 return 0;
315 }
316
init_dns_cache()317 int init_dns_cache()
318 {
319 int r;
320 int ret;
321
322 if (dns_cache_init==0) {
323 /* the DNS cache is turned off */
324 default_core_cfg.use_dns_cache=0;
325 default_core_cfg.use_dns_failover=0;
326 return 0;
327 }
328
329 ret=0;
330 /* sanity check */
331 if (E_DNS_CRITICAL>=sizeof(dns_str_errors)/sizeof(char*)){
332 LM_CRIT("bad dns error table\n");
333 ret=E_BUG;
334 goto error;
335 }
336 dns_cache_mem_used=shm_malloc(sizeof(*dns_cache_mem_used));
337 if (dns_cache_mem_used==0){
338 SHM_MEM_ERROR;
339 ret=E_OUT_OF_MEM;
340 goto error;
341 }
342 *dns_cache_mem_used=0;
343
344 dns_last_used_lst=shm_malloc(sizeof(*dns_last_used_lst));
345 if (dns_last_used_lst==0){
346 SHM_MEM_ERROR;
347 ret=E_OUT_OF_MEM;
348 goto error;
349 }
350 clist_init(dns_last_used_lst, next, prev);
351
352 dns_hash=shm_malloc(sizeof(struct dns_hash_head)*DNS_HASH_SIZE);
353 if (dns_hash==0){
354 SHM_MEM_ERROR;
355 ret=E_OUT_OF_MEM;
356 goto error;
357 }
358 for (r=0; r<DNS_HASH_SIZE; r++)
359 clist_init(&dns_hash[r], next, prev);
360
361 dns_hash_lock=lock_alloc();
362 if (dns_hash_lock==0){
363 ret=E_OUT_OF_MEM;
364 goto error;
365 }
366 if (lock_init(dns_hash_lock)==0){
367 lock_dealloc(dns_hash_lock);
368 dns_hash_lock=0;
369 ret=-1;
370 goto error;
371 }
372
373 #ifdef DNS_WATCHDOG_SUPPORT
374 dns_servers_up=shm_malloc(sizeof(atomic_t));
375 if (dns_servers_up==0){
376 SHM_MEM_ERROR;
377 ret=E_OUT_OF_MEM;
378 goto error;
379 }
380 atomic_set(dns_servers_up, 1);
381 #endif
382
383 /* fix options */
384 default_core_cfg.dns_cache_max_mem<<=10; /* Kb */ /* TODO: test with 0 */
385 if (default_core_cfg.use_dns_cache==0)
386 default_core_cfg.use_dns_failover=0; /* cannot work w/o dns_cache support */
387 /* fix flags */
388 fix_dns_flags(NULL, NULL);
389
390 dns_timer_h=timer_alloc();
391 if (dns_timer_h==0){
392 ret=E_OUT_OF_MEM;
393 goto error;
394 }
395 if (dns_timer_interval){
396 timer_init(dns_timer_h, dns_timer, 0, 0); /* "slow" timer */
397 if (timer_add(dns_timer_h, S_TO_TICKS(dns_timer_interval))<0){
398 LM_CRIT("failed to add the timer\n");
399 timer_free(dns_timer_h);
400 dns_timer_h=0;
401 goto error;
402 }
403 }
404
405 return 0;
406 error:
407 destroy_dns_cache();
408 return ret;
409 }
410
411 #ifdef USE_DNS_CACHE_STATS
init_dns_cache_stats(int iproc_num)412 int init_dns_cache_stats(int iproc_num)
413 {
414 /* do not initialize the stats array if the DNS cache will not be used */
415 if (dns_cache_init==0) return 0;
416
417 /* if it is already initialized */
418 if (dns_cache_stats)
419 shm_free(dns_cache_stats);
420
421 dns_cache_stats=shm_malloc(sizeof(*dns_cache_stats) * iproc_num);
422 if (dns_cache_stats==0){
423 SHM_MEM_ERROR;
424 return E_OUT_OF_MEM;
425 }
426 memset(dns_cache_stats, 0, sizeof(*dns_cache_stats) * iproc_num);
427
428 return 0;
429 }
430 #endif
431
432 /* hash function, type is not used (obsolete)
433 * params: char* s, int len, int type
434 * returns the hash value
435 */
436 #define dns_hash_no(s, len, type) \
437 (get_hash1_case_raw((s),(len)) % DNS_HASH_SIZE)
438
439
440
441
442 #include <stdlib.h> /* abort() */
443 #define check_lu_lst(l) ((((l)->next==(l)) || ((l)->prev==(l))) && \
444 ((l)!=dns_last_used_lst))
445
446 #define dbg_lu_lst(txt, l) \
447 LM_CRIT("%s: crt(%p, %p, %p)," \
448 " prev(%p, %p, %p), next(%p, %p, %p)\n", txt, \
449 (l), (l)->next, (l)->prev, \
450 (l)->prev, ((l)->prev)?(l)->prev->next:NULL, \
451 ((l)->prev)?(l)->prev->prev:NULL, \
452 (l)->next, ((l)->next)?(l)->next->next:NULL, \
453 ((l)->next)?(l)->next->prev:NULL \
454 )
455
456 #define debug_lu_lst( txt, l) \
457 do{ \
458 if ((l) && check_lu_lst((l))){ \
459 dbg_lu_lst(txt " crt:", (l)); \
460 abort(); \
461 } \
462 if (((l)->next) && check_lu_lst((l)->next)){ \
463 dbg_lu_lst(txt " next:", (l)); \
464 abort(); \
465 } \
466 if (((l)->prev) && check_lu_lst((l)->prev)){ \
467 dbg_lu_lst(txt " prev:", (l)); \
468 abort(); \
469 } \
470 }while(0)
471
472
473
474 /* must be called with the DNS_LOCK hold
475 * remove and entry from the hash, dec. its refcnt and if not referenced
476 * anymore deletes it */
_dns_hash_remove(struct dns_hash_entry * e)477 inline static void _dns_hash_remove(struct dns_hash_entry* e)
478 {
479 clist_rm(e, next, prev);
480 e->next=e->prev=0;
481 debug_lu_lst("_dns_hash_remove: pre rm:", &e->last_used_lst);
482 clist_rm(&e->last_used_lst, next, prev);
483 debug_lu_lst("_dns_hash_remove: post rm:", &e->last_used_lst);
484 e->last_used_lst.next=e->last_used_lst.prev=0;
485 *dns_cache_mem_used-=e->total_size;
486 dns_hash_put(e);
487 }
488
489
490
491 /* non locking version (the dns hash must _be_ locked externally)
492 * returns 0 when not found, or the entry on success (an entry with a
493 * similar name but with a CNAME type will always match).
494 * it doesn't increase the internal refcnt
495 * returns the entry when found, 0 when not found and sets *err to !=0
496 * on error (e.g. recursive cnames)
497 * WARNING: - internal use only
498 * - always check if the returned entry type is CNAME */
_dns_hash_find(str * name,int type,int * h,int * err)499 inline static struct dns_hash_entry* _dns_hash_find(str* name, int type,
500 int* h, int* err)
501 {
502 struct dns_hash_entry* e;
503 struct dns_hash_entry* tmp;
504 struct dns_hash_entry* ret;
505 ticks_t now;
506 int cname_chain;
507 str cname;
508 #ifdef DNS_WATCHDOG_SUPPORT
509 int servers_up;
510
511 servers_up = atomic_get(dns_servers_up);
512 #endif
513
514 cname_chain=0;
515 ret=0;
516 now=get_ticks_raw();
517 *err=0;
518
519 /* just in case that e.g. the VIA parser get confused */
520 if(unlikely(!name->s || name->len <= 0)) {
521 LM_ERR("invalid name, no cache lookup possible\n");
522 *err=-1;
523 return 0;
524 }
525 again:
526 *h=dns_hash_no(name->s, name->len, type);
527 LM_DBG("(%.*s(%d), %d), h=%d\n", name->len, name->s, name->len, type, *h);
528 clist_foreach_safe(&dns_hash[*h], e, tmp, next){
529 if (
530 #ifdef DNS_WATCHDOG_SUPPORT
531 /* remove expired elements only when the dns servers are up */
532 servers_up &&
533 #endif
534 /* automatically remove expired elements */
535 ((e->ent_flags & DNS_FLAG_PERMANENT) == 0) &&
536 ((s_ticks_t)(now-e->expire)>=0)
537 ) {
538 _dns_hash_remove(e);
539 }else if ((e->type==type) && (e->name_len==name->len) &&
540 (strncasecmp(e->name, name->s, e->name_len)==0)){
541 e->last_used=now;
542 /* add it at the end */
543 debug_lu_lst("_dns_hash_find: pre rm:", &e->last_used_lst);
544 clist_rm(&e->last_used_lst, next, prev);
545 clist_append(dns_last_used_lst, &e->last_used_lst, next, prev);
546 debug_lu_lst("_dns_hash_find: post append:", &e->last_used_lst);
547 return e;
548 }else if ((e->type==T_CNAME) &&
549 !((e->rr_lst==0) || (e->ent_flags & DNS_FLAG_BAD_NAME)) &&
550 (e->name_len==name->len) &&
551 (strncasecmp(e->name, name->s, e->name_len)==0)){
552 /*if CNAME matches and CNAME is entry is not a neg. cache entry
553 (could be produced by a specific CNAME lookup)*/
554 e->last_used=now;
555 /* add it at the end */
556 debug_lu_lst("_dns_hash_find: cname: pre rm:", &e->last_used_lst);
557 clist_rm(&e->last_used_lst, next, prev);
558 clist_append(dns_last_used_lst, &e->last_used_lst, next, prev);
559 debug_lu_lst("_dns_hash_find: cname: post append:",
560 &e->last_used_lst);
561 ret=e; /* if this is an unfinished cname chain, we try to
562 return the last cname */
563 /* this is a cname => retry using its value */
564 if (cname_chain> MAX_CNAME_CHAIN){
565 LM_ERR("cname chain too long or recursive (\"%.*s\")\n",
566 name->len, name->s);
567 ret=0; /* error*/
568 *err=-1;
569 break;
570 }
571 cname_chain++;
572 cname.s=((struct cname_rdata*)e->rr_lst->rdata)->name;
573 cname.len= ((struct cname_rdata*)e->rr_lst->rdata)->name_len;
574 if(cname.s!=NULL && cname.len>0) {
575 name=&cname;
576 goto again;
577 }
578 }
579 }
580 return ret;
581 }
582
583
584
585 /* frees cache entries, if expired_only=0 only expired entries will be
586 * removed, else all of them
587 * it will process maximum no entries (to process all of them use -1)
588 * returns the number of deleted entries
589 * This should be called from a timer process*/
dns_cache_clean(unsigned int no,int expired_only)590 inline static int dns_cache_clean(unsigned int no, int expired_only)
591 {
592 struct dns_hash_entry* e;
593 ticks_t now;
594 unsigned int n;
595 unsigned int deleted;
596 struct dns_lu_lst* l;
597 struct dns_lu_lst* tmp;
598
599 n=0;
600 deleted=0;
601 now=get_ticks_raw();
602 LOCK_DNS_HASH();
603 clist_foreach_safe(dns_last_used_lst, l, tmp, next){
604 e=(struct dns_hash_entry*)(((char*)l)-
605 (char*)&((struct dns_hash_entry*)(0))->last_used_lst);
606 if (((e->ent_flags & DNS_FLAG_PERMANENT) == 0)
607 && (!expired_only || ((s_ticks_t)(now-e->expire)>=0))
608 ) {
609 _dns_hash_remove(e);
610 deleted++;
611 }
612 n++;
613 if (n>=no) break;
614 }
615 UNLOCK_DNS_HASH();
616 return deleted;
617 }
618
619
620
621 /* frees cache entries, if expired_only=0 only expired entries will be
622 * removed, else all of them
623 * it will stop when the dns cache used memory reaches target (to process all
624 * of them use 0)
625 * returns the number of deleted entries */
dns_cache_free_mem(unsigned int target,int expired_only)626 inline static int dns_cache_free_mem(unsigned int target, int expired_only)
627 {
628 struct dns_hash_entry* e;
629 ticks_t now;
630 unsigned int deleted;
631 struct dns_lu_lst* l;
632 struct dns_lu_lst* tmp;
633
634 deleted=0;
635 now=get_ticks_raw();
636 LOCK_DNS_HASH();
637 clist_foreach_safe(dns_last_used_lst, l, tmp, next){
638 if (*dns_cache_mem_used<=target) break;
639 e=(struct dns_hash_entry*)(((char*)l)-
640 (char*)&((struct dns_hash_entry*)(0))->last_used_lst);
641 if (((e->ent_flags & DNS_FLAG_PERMANENT) == 0)
642 && (!expired_only || ((s_ticks_t)(now-e->expire)>=0))
643 ) {
644 _dns_hash_remove(e);
645 deleted++;
646 }
647 }
648 UNLOCK_DNS_HASH();
649 return deleted;
650 }
651
652
653
654 /* locking version (the dns hash must _not_be locked externally)
655 * returns 0 when not found, the searched entry on success (with CNAMEs
656 * followed) or the last CNAME entry from an unfinished CNAME chain,
657 * if the search matches a CNAME. On error sets *err (e.g. recursive CNAMEs).
658 * it increases the internal refcnt => when finished dns_hash_put() must
659 * be called on the returned entry
660 * WARNING: - the return might be a CNAME even if type!=CNAME, see above */
dns_hash_get(str * name,int type,int * h,int * err)661 inline static struct dns_hash_entry* dns_hash_get(str* name, int type, int* h,
662 int* err)
663 {
664 struct dns_hash_entry* e;
665
666 LOCK_DNS_HASH();
667 e=_dns_hash_find(name, type, h, err);
668 if (e){
669 atomic_inc(&e->refcnt);
670 }
671 UNLOCK_DNS_HASH();
672 return e;
673 }
674
675
676
677 /* adds a fully created and init. entry (see dns_cache_mk_entry()) to the hash
678 * table
679 * returns 0 on success, -1 on error */
dns_cache_add(struct dns_hash_entry * e)680 inline static int dns_cache_add(struct dns_hash_entry* e)
681 {
682 int h;
683
684 /* check space */
685 /* atomic_add_long(dns_cache_total_used, e->size); */
686 if ((*dns_cache_mem_used+e->total_size)>=cfg_get(core, core_cfg, dns_cache_max_mem)){
687 #ifdef USE_DNS_CACHE_STATS
688 dns_cache_stats[process_no].dc_lru_cnt++;
689 #endif
690 LM_WARN("cache full, trying to free...\n");
691 /* free ~ 12% of the cache */
692 dns_cache_free_mem(*dns_cache_mem_used/16*14,
693 !cfg_get(core, core_cfg, dns_cache_del_nonexp));
694 if ((*dns_cache_mem_used+e->total_size)>=cfg_get(core, core_cfg, dns_cache_max_mem)){
695 LM_ERR("max. cache mem size exceeded\n");
696 return -1;
697 }
698 }
699 atomic_inc(&e->refcnt);
700 h=dns_hash_no(e->name, e->name_len, e->type);
701 LM_DBG("adding %.*s(%d) %d (flags=%0x) at %d\n",
702 e->name_len, e->name, e->name_len, e->type, e->ent_flags, h);
703 LOCK_DNS_HASH();
704 *dns_cache_mem_used+=e->total_size; /* no need for atomic ops, written
705 only from within a lock */
706 clist_append(&dns_hash[h], e, next, prev);
707 clist_append(dns_last_used_lst, &e->last_used_lst, next, prev);
708 UNLOCK_DNS_HASH();
709 return 0;
710 }
711
712
713
714 /* same as above, but it must be called with the dns hash lock held
715 * returns 0 on success, -1 on error */
dns_cache_add_unsafe(struct dns_hash_entry * e)716 inline static int dns_cache_add_unsafe(struct dns_hash_entry* e)
717 {
718 int h;
719
720 /* check space */
721 /* atomic_add_long(dns_cache_total_used, e->size); */
722 if ((*dns_cache_mem_used+e->total_size)>=cfg_get(core, core_cfg, dns_cache_max_mem)){
723 #ifdef USE_DNS_CACHE_STATS
724 dns_cache_stats[process_no].dc_lru_cnt++;
725 #endif
726 LM_WARN("cache full, trying to free...\n");
727 /* free ~ 12% of the cache */
728 UNLOCK_DNS_HASH();
729 dns_cache_free_mem(*dns_cache_mem_used/16*14,
730 !cfg_get(core, core_cfg, dns_cache_del_nonexp));
731 LOCK_DNS_HASH();
732 if ((*dns_cache_mem_used+e->total_size)>=cfg_get(core, core_cfg, dns_cache_max_mem)){
733 LM_ERR("max. cache mem size exceeded\n");
734 return -1;
735 }
736 }
737 atomic_inc(&e->refcnt);
738 h=dns_hash_no(e->name, e->name_len, e->type);
739 LM_DBG("adding %.*s(%d) %d (flags=%0x) at %d\n",
740 e->name_len, e->name, e->name_len, e->type, e->ent_flags, h);
741 *dns_cache_mem_used+=e->total_size; /* no need for atomic ops, written
742 only from within a lock */
743 clist_append(&dns_hash[h], e, next, prev);
744 clist_append(dns_last_used_lst, &e->last_used_lst, next, prev);
745
746 return 0;
747 }
748
749
750
751 /* creates a "negative" entry which will be valid for ttl seconds */
dns_cache_mk_bad_entry(str * name,int type,int ttl,int flags)752 inline static struct dns_hash_entry* dns_cache_mk_bad_entry(str* name,
753 int type,
754 int ttl,
755 int flags)
756 {
757 struct dns_hash_entry* e;
758 int size;
759 ticks_t now;
760
761 LM_DBG("(%.*s, %d, %d, %d)\n", name->len, name->s, type, ttl, flags);
762 size=sizeof(struct dns_hash_entry)+name->len-1+1;
763 e=shm_malloc(size);
764 if (e==0){
765 SHM_MEM_ERROR;
766 return 0;
767 }
768 memset(e, 0, size); /* init with 0*/
769 e->total_size=size;
770 e->name_len=name->len;
771 e->type=type;
772 now=get_ticks_raw();
773 e->last_used=now;
774 e->expire=now+S_TO_TICKS(ttl);
775 memcpy(e->name, name->s, name->len);
776 e->ent_flags=flags;
777 return e;
778 }
779
780
781
782 /* create a a/aaaa hash entry from a name and ip address
783 * returns 0 on error */
dns_cache_mk_ip_entry(str * name,struct ip_addr * ip)784 inline static struct dns_hash_entry* dns_cache_mk_ip_entry(str* name,
785 struct ip_addr* ip)
786 {
787 struct dns_hash_entry* e;
788 int size;
789 ticks_t now;
790
791 /* everything is allocated in one block: dns_hash_entry + name +
792 * + dns_rr + rdata; dns_rr must start at an aligned adress,
793 * hence we need to round dns_hash_entry+name size to a sizeof(long)
794 * multiple.
795 * Memory image:
796 * struct dns_hash_entry
797 * name (name_len+1 bytes)
798 * padding to multiple of sizeof(long)
799 * dns_rr
800 * rdata (no padding needed, since for ip is just an array of chars)
801 */
802 size=ROUND_POINTER(sizeof(struct dns_hash_entry)+name->len-1+1)+
803 sizeof(struct dns_rr)+ ip->len;
804 e=shm_malloc(size);
805 if (e==0){
806 SHM_MEM_ERROR;
807 return 0;
808 }
809 memset(e, 0, size); /* init with 0*/
810 e->total_size=size;
811 e->name_len=name->len;
812 e->type=(ip->af==AF_INET)?T_A:T_AAAA;
813 now=get_ticks_raw();
814 e->last_used=now;
815 e->expire=now-1; /* maximum expire */
816 memcpy(e->name, name->s, name->len); /* memset makes sure is 0-term. */
817 e->rr_lst=(void*)((char*)e+
818 ROUND_POINTER(sizeof(struct dns_hash_entry)+name->len-1+1));
819 e->rr_lst->rdata=(void*)((char*)e->rr_lst+sizeof(struct dns_rr));
820 e->rr_lst->expire=now-1; /* maximum expire */
821 /* no need to align rr_lst->rdata for a or aaaa records */
822 memcpy(e->rr_lst->rdata, ip->u.addr, ip->len);
823 return e;
824 }
825
826 /* creates an srv hash entry from the given parameters
827 * returns 0 on error */
dns_cache_mk_srv_entry(str * name,unsigned short priority,unsigned short weight,unsigned short port,str * rr_name,int ttl)828 static struct dns_hash_entry* dns_cache_mk_srv_entry(str* name,
829 unsigned short priority,
830 unsigned short weight,
831 unsigned short port,
832 str* rr_name,
833 int ttl)
834 {
835 struct dns_hash_entry* e;
836 int size;
837 ticks_t now;
838
839 /* everything is allocated in one block: dns_hash_entry + name +
840 * + dns_rr + rdata; dns_rr must start at an aligned adress,
841 * hence we need to round dns_hash_entry+name size to a sizeof(long),
842 * and similarly, dns_rr must be rounded to sizeof(short).
843 * multiple.
844 * Memory image:
845 * struct dns_hash_entry
846 * name (name_len+1 bytes)
847 * padding to multiple of sizeof(long)
848 * dns_rr
849 * padding to multiple of sizeof(short)
850 * rdata
851 */
852 size=ROUND_POINTER(sizeof(struct dns_hash_entry)+name->len-1+1) +
853 ROUND_SHORT(sizeof(struct dns_rr)) +
854 sizeof(struct srv_rdata)-1 +
855 rr_name->len+1;
856
857 e=shm_malloc(size);
858 if (e==0){
859 SHM_MEM_ERROR;
860 return 0;
861 }
862 memset(e, 0, size); /* init with 0*/
863 e->total_size=size;
864 e->name_len=name->len;
865 e->type=T_SRV;
866 now=get_ticks_raw();
867 e->last_used=now;
868 e->expire=now+S_TO_TICKS(ttl);
869 memcpy(e->name, name->s, name->len); /* memset makes sure is 0-term. */
870 e->rr_lst=(void*)((char*)e+
871 ROUND_POINTER(sizeof(struct dns_hash_entry)+name->len-1+1));
872 e->rr_lst->rdata=(void*)((char*)e->rr_lst+ROUND_SHORT(sizeof(struct dns_rr)));
873 e->rr_lst->expire=e->expire;
874 ((struct srv_rdata*)e->rr_lst->rdata)->priority = priority;
875 ((struct srv_rdata*)e->rr_lst->rdata)->weight = weight;
876 ((struct srv_rdata*)e->rr_lst->rdata)->port = port;
877 ((struct srv_rdata*)e->rr_lst->rdata)->name_len = rr_name->len;
878 memcpy(((struct srv_rdata*)e->rr_lst->rdata)->name, rr_name->s, rr_name->len);
879 return e;
880 }
881
882
883 /* create a dns hash entry from a name and a rdata list (pkg_malloc'ed)
884 * (it will use only the type records with the name "name" from the
885 * rdata list with one exception: if a matching CNAME with the same
886 * name is found, the search will stop and this will be the record used)
887 * returns 0 on error and removes the used elements from the rdata list*/
dns_cache_mk_rd_entry(str * name,int type,struct rdata ** rd_lst)888 inline static struct dns_hash_entry* dns_cache_mk_rd_entry(str* name, int type,
889 struct rdata** rd_lst)
890 {
891 struct dns_hash_entry* e;
892 struct dns_rr* rr;
893 struct dns_rr** tail_rr;
894 struct rdata** p;
895 struct rdata* tmp_lst;
896 struct rdata** tail;
897 struct rdata* l;
898 int size;
899 ticks_t now;
900 unsigned int max_ttl;
901 unsigned int ttl;
902 int i;
903
904 #define rec_matches(rec, t, n) /*(struct rdata* record, int type, str* name)*/\
905 ( ((rec)->name_len==(n)->len) && ((rec)->type==(t)) && \
906 (strncasecmp((rec)->name, (n)->s, (n)->len)==0))
907 /* init */
908 tmp_lst=0;
909 tail=&tmp_lst;
910
911
912 /* everything is allocated in one block: dns_hash_entry + name +
913 * + dns_rr + rdata_raw+ ....; dns_rr must start at an aligned adress,
914 * hence we need to round dns_hash_entry+name size to a sizeof(long)
915 * multiple. If rdata type requires it, rdata_raw might need to be also
916 * aligned.
917 * Memory image:
918 * struct dns_hash_entry (e)
919 * name (name_len+1 bytes) (&e->name[0])
920 * padding to multiple of sizeof(char*)
921 * dns_rr1 (e->rr_lst)
922 * possible padding: no padding for a_rdata or aaaa_rdata,
923 * multipe of sizeof(short) for srv_rdata,
924 * multiple of sizeof(long) for naptr_rdata and others
925 * dns_rr1->rdata (e->rr_lst->rdata)
926 * padding to multipe of sizeof long
927 * dns_rr2 (e->rr_lst->next)
928 * ....
929 *
930 */
931 size=0;
932 if (*rd_lst==0)
933 return 0;
934 /* find the first matching rr, if it's a CNAME use CNAME as type,
935 * if not continue with the original type */
936 for(p=rd_lst; *p; p=&(*p)->next){
937 if (((*p)->name_len==name->len) &&
938 (((*p)->type==type) || ((*p)->type==T_CNAME)) &&
939 (strncasecmp((*p)->name, name->s, name->len)==0)){
940 type=(*p)->type;
941 break;
942 }
943 }
944 /* continue, we found the type we are looking for */
945 switch(type){
946 case T_A:
947 for(; *p;){
948 if (!rec_matches((*p), type, name)){
949 /* skip this record */
950 p=&(*p)->next; /* advance */
951 continue;
952 }
953 size+=ROUND_POINTER(sizeof(struct dns_rr)+
954 sizeof(struct a_rdata));
955 /* add it to our tmp. lst */
956 *tail=*p;
957 tail=&(*p)->next;
958 /* detach it from the rd list */
959 *p=(*p)->next;
960 /* don't advance p, because the crt. elem. has
961 * just been elimintated */
962 }
963 break;
964 case T_AAAA:
965 for(; *p;){
966 if (!rec_matches((*p), type, name)){
967 /* skip this record */
968 p=&(*p)->next; /* advance */
969 continue;
970 }
971 /* no padding */
972 size+=ROUND_POINTER(sizeof(struct dns_rr)+
973 sizeof(struct aaaa_rdata));
974 /* add it to our tmp. lst */
975 *tail=*p;
976 tail=&(*p)->next;
977 /* detach it from the rd list */
978 *p=(*p)->next;
979 /* don't advance p, because the crt. elem. has
980 * just been elimintated */
981 }
982 break;
983 case T_SRV:
984 for(; *p;){
985 if (!rec_matches((*p), type, name)){
986 /* skip this record */
987 p=&(*p)->next; /* advance */
988 continue;
989 }
990 /* padding to short */
991 size+=ROUND_POINTER(ROUND_SHORT(sizeof(struct dns_rr))+
992 SRV_RDATA_SIZE(*(struct srv_rdata*)(*p)->rdata));
993 /* add it to our tmp. lst */
994 *tail=*p;
995 tail=&(*p)->next;
996 /* detach it from the rd list */
997 *p=(*p)->next;
998 /* don't advance p, because the crt. elem. has
999 * just been elimintated */
1000 }
1001 break;
1002 case T_NAPTR:
1003 for(; *p;){
1004 if (!rec_matches((*p), type, name)){
1005 /* skip this record */
1006 p=&(*p)->next; /* advance */
1007 continue;
1008 }
1009 /* padding to char* */
1010 size+=ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
1011 NAPTR_RDATA_SIZE(*(struct naptr_rdata*)(*p)->rdata));
1012 /* add it to our tmp. lst */
1013 *tail=*p;
1014 tail=&(*p)->next;
1015 /* detach it from the rd list */
1016 *p=(*p)->next;
1017 /* don't advance p, because the crt. elem. has
1018 * just been elimintated */
1019 }
1020 break;
1021 case T_CNAME:
1022 for(; *p;){
1023 if (!rec_matches((*p), type, name)){
1024 /* skip this record */
1025 p=&(*p)->next; /* advance */
1026 continue;
1027 }
1028 /* no padding */
1029 size+=ROUND_POINTER(sizeof(struct dns_rr)+
1030 CNAME_RDATA_SIZE(*(struct cname_rdata*)(*p)->rdata));
1031 /* add it to our tmp. lst */
1032 *tail=*p;
1033 tail=&(*p)->next;
1034 /* detach it from the rd list */
1035 *p=(*p)->next;
1036 /* don't advance p, because the crt. elem. has
1037 * just been elimintated */
1038 }
1039 break;
1040 case T_TXT:
1041 for(; *p;){
1042 if (!rec_matches((*p), type, name)){
1043 /* skip this record */
1044 p=&(*p)->next; /* advance */
1045 continue;
1046 }
1047 /* padding to char* (because of txt[]->cstr*/
1048 size+=ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
1049 TXT_RDATA_SIZE(*(struct txt_rdata*)(*p)->rdata));
1050 /* add it to our tmp. lst */
1051 *tail=*p;
1052 tail=&(*p)->next;
1053 /* detach it from the rd list */
1054 *p=(*p)->next;
1055 /* don't advance p, because the crt. elem. has
1056 * just been elimintated */
1057 }
1058 break;
1059 case T_EBL:
1060 for(; *p;){
1061 if (!rec_matches((*p), type, name)){
1062 /* skip this record */
1063 p=&(*p)->next; /* advance */
1064 continue;
1065 }
1066 /* padding to char* (because of the char* pointers */
1067 size+=ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
1068 EBL_RDATA_SIZE(*(struct ebl_rdata*)(*p)->rdata));
1069 /* add it to our tmp. lst */
1070 *tail=*p;
1071 tail=&(*p)->next;
1072 /* detach it from the rd list */
1073 *p=(*p)->next;
1074 /* don't advance p, because the crt. elem. has
1075 * just been elimintated */
1076 }
1077 break;
1078 case T_PTR:
1079 for(; *p;){
1080 if (!rec_matches((*p), type, name)){
1081 /* skip this record */
1082 p=&(*p)->next; /* advance */
1083 continue;
1084 }
1085 /* no padding */
1086 size+=ROUND_POINTER(sizeof(struct dns_rr)+
1087 PTR_RDATA_SIZE(*(struct ptr_rdata*)(*p)->rdata));
1088 /* add it to our tmp. lst */
1089 *tail=*p;
1090 tail=&(*p)->next;
1091 /* detach it from the rd list */
1092 *p=(*p)->next;
1093 /* don't advance p, because the crt. elem. has
1094 * just been elimintated */
1095 }
1096 break;
1097 default:
1098 LM_CRIT("type %d not supported\n", type);
1099 /* we don't know what to do with it, so don't
1100 * add it to the tmp_lst */
1101 return 0; /* error */
1102 }
1103 *tail=0; /* mark the end of our tmp_lst */
1104 if (size==0){
1105 LM_DBG("entry %.*s (%d) not found\n", name->len, name->s, type);
1106 return 0;
1107 }
1108 /* compute size */
1109 size+=ROUND_POINTER(sizeof(struct dns_hash_entry)+name->len-1+1);
1110 e=shm_malloc(size);
1111 if (e==0){
1112 SHM_MEM_ERROR;
1113 return 0;
1114 }
1115 memset(e, 0, size); /* init with 0 */
1116 clist_init(e, next, prev);
1117 e->total_size=size;
1118 e->name_len=name->len;
1119 e->type=type;
1120 now=get_ticks_raw();
1121 e->last_used=now;
1122 memcpy(e->name, name->s, name->len); /* memset makes sure is 0-term. */
1123 e->rr_lst=(struct dns_rr*)((char*)e+
1124 ROUND_POINTER(sizeof(struct dns_hash_entry)+name->len-1+1));
1125 tail_rr=&(e->rr_lst);
1126 rr=e->rr_lst;
1127 max_ttl=0;
1128 /* copy the actual data */
1129 switch(type){
1130 case T_A:
1131 for(l=tmp_lst; l; l=l->next){
1132 ttl=FIX_TTL(l->ttl);
1133 rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1134 max_ttl=MAX(max_ttl, ttl);
1135 rr->rdata=(void*)((char*)rr+sizeof(struct dns_rr));
1136 memcpy(rr->rdata, l->rdata, sizeof(struct a_rdata));
1137 rr->next=(void*)((char*)rr+ROUND_POINTER(sizeof(struct dns_rr)+
1138 sizeof(struct a_rdata)));
1139 tail_rr=&(rr->next);
1140 rr=rr->next;
1141 }
1142 break;
1143 case T_AAAA:
1144 for(l=tmp_lst; l; l=l->next){
1145 ttl=FIX_TTL(l->ttl);
1146 rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1147 max_ttl=MAX(max_ttl, ttl);
1148 rr->rdata=(void*)((char*)rr+sizeof(struct dns_rr));
1149 memcpy(rr->rdata, l->rdata, sizeof(struct aaaa_rdata));
1150 rr->next=(void*)((char*)rr+ROUND_POINTER(sizeof(struct dns_rr)+
1151 sizeof(struct aaaa_rdata)));
1152 tail_rr=&(rr->next);
1153 rr=rr->next;
1154 }
1155 break;
1156 case T_SRV:
1157 for(l=tmp_lst; l; l=l->next){
1158 ttl=FIX_TTL(l->ttl);
1159 rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1160 max_ttl=MAX(max_ttl, ttl);
1161 rr->rdata=(void*)((char*)rr+
1162 ROUND_SHORT(sizeof(struct dns_rr)));
1163 /* copy the whole srv_rdata block*/
1164 memcpy(rr->rdata, l->rdata,
1165 SRV_RDATA_SIZE(*(struct srv_rdata*)l->rdata) );
1166 rr->next=(void*)((char*)rr+
1167 ROUND_POINTER( ROUND_SHORT(sizeof(struct dns_rr))+
1168 SRV_RDATA_SIZE(
1169 *(struct srv_rdata*)l->rdata)));
1170 tail_rr=&(rr->next);
1171 rr=rr->next;
1172 }
1173 break;
1174 case T_NAPTR:
1175 for(l=tmp_lst; l; l=l->next){
1176 ttl=FIX_TTL(l->ttl);
1177 rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1178 max_ttl=MAX(max_ttl, ttl);
1179 rr->rdata=(void*)((char*)rr+
1180 ROUND_POINTER(sizeof(struct dns_rr)));
1181 /* copy the whole naptr_rdata block*/
1182 memcpy(rr->rdata, l->rdata,
1183 NAPTR_RDATA_SIZE(*(struct naptr_rdata*)l->rdata) );
1184 /* adjust the string pointer */
1185 ((struct naptr_rdata*)rr->rdata)->flags=
1186 translate_pointer((char*)rr->rdata, (char*)l->rdata,
1187 (((struct naptr_rdata*)l->rdata)->flags));
1188 ((struct naptr_rdata*)rr->rdata)->services=
1189 translate_pointer((char*)rr->rdata, (char*)l->rdata,
1190 (((struct naptr_rdata*)l->rdata)->services));
1191 ((struct naptr_rdata*)rr->rdata)->regexp=
1192 translate_pointer((char*)rr->rdata, (char*)l->rdata,
1193 (((struct naptr_rdata*)l->rdata)->regexp));
1194 ((struct naptr_rdata*)rr->rdata)->repl=
1195 translate_pointer((char*)rr->rdata, (char*)l->rdata,
1196 (((struct naptr_rdata*)l->rdata)->repl));
1197 rr->next=(void*)((char*)rr+
1198 ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
1199 NAPTR_RDATA_SIZE(
1200 *(struct naptr_rdata*)l->rdata)));
1201 tail_rr=&(rr->next);
1202 rr=rr->next;
1203 }
1204 break;
1205 case T_CNAME:
1206 for(l=tmp_lst; l; l=l->next){
1207 ttl=FIX_TTL(l->ttl);
1208 rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1209 max_ttl=MAX(max_ttl, ttl);
1210 rr->rdata=(void*)((char*)rr+sizeof(struct dns_rr));
1211 memcpy(rr->rdata, l->rdata,
1212 CNAME_RDATA_SIZE(*(struct cname_rdata*)l->rdata));
1213 rr->next=(void*)((char*)rr+ROUND_POINTER(sizeof(struct dns_rr)+
1214 CNAME_RDATA_SIZE(*(struct cname_rdata*)l->rdata)));
1215 tail_rr=&(rr->next);
1216 rr=rr->next;
1217 }
1218 break;
1219 case T_TXT:
1220 for(l=tmp_lst; l; l=l->next){
1221 ttl=FIX_TTL(l->ttl);
1222 rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1223 max_ttl=MAX(max_ttl, ttl);
1224 rr->rdata=(void*)((char*)rr+
1225 ROUND_POINTER(sizeof(struct dns_rr)));
1226 memcpy(rr->rdata, l->rdata,
1227 TXT_RDATA_SIZE(*(struct txt_rdata*)l->rdata));
1228 /* adjust the string pointers */
1229 for (i=0; i<((struct txt_rdata*)l->rdata)->cstr_no; i++){
1230 ((struct txt_rdata*)rr->rdata)->txt[i].cstr=
1231 translate_pointer((char*)rr->rdata, (char*)l->rdata,
1232 ((struct txt_rdata*)l->rdata)->txt[i].cstr);
1233 }
1234 rr->next=(void*)((char*)rr+
1235 ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
1236 TXT_RDATA_SIZE(*(struct txt_rdata*)l->rdata)));
1237 tail_rr=&(rr->next);
1238 rr=rr->next;
1239 }
1240 break;
1241 case T_EBL:
1242 for(l=tmp_lst; l; l=l->next){
1243 ttl=FIX_TTL(l->ttl);
1244 rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1245 max_ttl=MAX(max_ttl, ttl);
1246 rr->rdata=(void*)((char*)rr+
1247 ROUND_POINTER(sizeof(struct dns_rr)));
1248 memcpy(rr->rdata, l->rdata,
1249 EBL_RDATA_SIZE(*(struct ebl_rdata*)l->rdata));
1250 /* adjust the string pointers */
1251 ((struct ebl_rdata*)rr->rdata)->separator=
1252 translate_pointer((char*)rr->rdata, (char*)l->rdata,
1253 ((struct ebl_rdata*)l->rdata)->separator);
1254 ((struct ebl_rdata*)rr->rdata)->separator=
1255 translate_pointer((char*)rr->rdata, (char*)l->rdata,
1256 ((struct ebl_rdata*)l->rdata)->separator);
1257 ((struct ebl_rdata*)rr->rdata)->apex=
1258 translate_pointer((char*)rr->rdata, (char*)l->rdata,
1259 ((struct ebl_rdata*)l->rdata)->apex);
1260 rr->next=(void*)((char*)rr+
1261 ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
1262 EBL_RDATA_SIZE(*(struct ebl_rdata*)l->rdata)));
1263 tail_rr=&(rr->next);
1264 rr=rr->next;
1265 }
1266 break;
1267 case T_PTR:
1268 for(l=tmp_lst; l; l=l->next){
1269 ttl=FIX_TTL(l->ttl);
1270 rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1271 max_ttl=MAX(max_ttl, ttl);
1272 rr->rdata=(void*)((char*)rr+sizeof(struct dns_rr));
1273 memcpy(rr->rdata, l->rdata,
1274 PTR_RDATA_SIZE(*(struct ptr_rdata*)l->rdata));
1275 rr->next=(void*)((char*)rr+ROUND_POINTER(sizeof(struct dns_rr)+
1276 PTR_RDATA_SIZE(*(struct ptr_rdata*)l->rdata)));
1277 tail_rr=&(rr->next);
1278 rr=rr->next;
1279 }
1280 break;
1281 default:
1282 /* do nothing */
1283 LM_CRIT("type %d not supported\n", type);
1284 ;
1285 }
1286 *tail_rr=0; /* terminate the list */
1287 e->expire=now+S_TO_TICKS(max_ttl);
1288 free_rdata_list(tmp_lst);
1289 return e;
1290 }
1291
1292
1293
1294 /* structure used only inside dns_cache_mk_rd_entry2 to break
1295 * the list of records into records of the same type */
1296 struct tmp_rec{
1297 struct rdata* rd;
1298 struct dns_hash_entry* e;
1299 struct dns_rr* rr;
1300 struct dns_rr** tail_rr;
1301 int max_ttl;
1302 int size;
1303 };
1304
1305
1306
1307 /* create several dns hash entries from a list of rdata structs
1308 * returns 0 on error */
dns_cache_mk_rd_entry2(struct rdata * rd)1309 inline static struct dns_hash_entry* dns_cache_mk_rd_entry2(struct rdata* rd)
1310 {
1311 struct rdata* l;
1312 ticks_t now;
1313 struct tmp_rec rec[MAX_DNS_RECORDS];
1314 int rec_idx[MAX_DNS_RECORDS];
1315 int r, i, j;
1316 int no_records; /* number of different records */
1317 unsigned int ttl;
1318
1319
1320 no_records=0;
1321 rec[0].e=0;
1322 /* everything is allocated in one block: dns_hash_entry + name +
1323 * + dns_rr + rdata_raw+ ....; dns_rr must start at an aligned adress,
1324 * hence we need to round dns_hash_entry+name size to a sizeof(long)
1325 * multiple. If rdata type requires it, rdata_raw might need to be also
1326 * aligned.
1327 * Memory image:
1328 * struct dns_hash_entry (e)
1329 * name (name_len+1 bytes) (&e->name[0])
1330 * padding to multiple of sizeof(char*)
1331 * dns_rr1 (e->rr_lst)
1332 * possible padding: no padding for a_rdata or aaaa_rdata,
1333 * multipe of sizeof(short) for srv_rdata,
1334 * multiple of sizeof(long) for naptr_rdata and others
1335 * dns_rr1->rdata (e->rr_lst->rdata)
1336 * padding to multipe of sizeof long
1337 * dns_rr2 (e->rr_lst->next)
1338 * ....
1339 *
1340 */
1341 /* compute size */
1342 for(l=rd, i=0; l && (i<MAX_DNS_RECORDS); l=l->next, i++){
1343 for (r=0; r<no_records; r++){
1344 if ((l->type==rec[r].rd->type) &&
1345 (l->name_len==rec[r].rd->name_len)
1346 && (strncasecmp(l->name, rec[r].rd->name, l->name_len)==0)){
1347 /* found */
1348 goto found;
1349 }
1350 }
1351 /* not found, create new */
1352 if (no_records<MAX_DNS_RECORDS){
1353 rec[r].rd=l;
1354 rec[r].e=0;
1355 rec[r].size=ROUND_POINTER(sizeof(struct dns_hash_entry)+
1356 rec[r].rd->name_len-1+1);
1357 no_records++;
1358 }else{
1359 LM_ERR("too many records: %d\n", no_records);
1360 /* skip */
1361 continue;
1362 }
1363 found:
1364 rec_idx[i]=r;
1365 switch(l->type){
1366 case T_A:
1367 /* no padding */
1368 rec[r].size+=ROUND_POINTER(sizeof(struct dns_rr)+
1369 sizeof(struct a_rdata));
1370 break;
1371 case T_AAAA:
1372 /* no padding */
1373 rec[r].size+=ROUND_POINTER(sizeof(struct dns_rr)+
1374 sizeof(struct aaaa_rdata));
1375 break;
1376 case T_SRV:
1377 /* padding to short */
1378 rec[r].size+=ROUND_POINTER(ROUND_SHORT(sizeof(struct dns_rr))+
1379 SRV_RDATA_SIZE(*(struct srv_rdata*)l->rdata));
1380 break;
1381 case T_NAPTR:
1382 /* padding to char* */
1383 rec[r].size+=ROUND_POINTER(ROUND_POINTER(
1384 sizeof(struct dns_rr))+
1385 NAPTR_RDATA_SIZE(*(struct naptr_rdata*)l->rdata));
1386 break;
1387 case T_CNAME:
1388 /* no padding */
1389 rec[r].size+=ROUND_POINTER(sizeof(struct dns_rr)+
1390 CNAME_RDATA_SIZE(*(struct cname_rdata*)l->rdata));
1391 break;
1392 case T_TXT:
1393 /* padding to char* (because of txt[]->cstr)*/
1394 rec[r].size+=ROUND_POINTER(ROUND_POINTER(
1395 sizeof(struct dns_rr))+
1396 TXT_RDATA_SIZE(*(struct txt_rdata*)l->rdata));
1397 break;
1398 case T_EBL:
1399 /* padding to char* (because of char* pointers)*/
1400 rec[r].size+=ROUND_POINTER(ROUND_POINTER(
1401 sizeof(struct dns_rr))+
1402 EBL_RDATA_SIZE(*(struct ebl_rdata*)l->rdata));
1403 break;
1404 case T_PTR:
1405 /* no padding */
1406 rec[r].size+=ROUND_POINTER(sizeof(struct dns_rr)+
1407 PTR_RDATA_SIZE(*(struct ptr_rdata*)l->rdata));
1408 break;
1409 default:
1410 LM_CRIT("type %d not supported\n", l->type);
1411 }
1412 }
1413
1414 now=get_ticks_raw();
1415 /* alloc & init the entries */
1416 for (r=0; r<no_records; r++){
1417 rec[r].e=shm_malloc(rec[r].size);
1418 if (rec[r].e==0){
1419 SHM_MEM_ERROR;
1420 goto error;
1421 }
1422 memset(rec[r].e, 0, rec[r].size); /* init with 0*/
1423 rec[r].e->total_size=rec[r].size;
1424 rec[r].e->name_len=rec[r].rd->name_len;
1425 rec[r].e->type=rec[r].rd->type;
1426 rec[r].e->last_used=now;
1427 /* memset makes sure is 0-term. */
1428 memcpy(rec[r].e->name, rec[r].rd->name, rec[r].rd->name_len);
1429 rec[r].e->rr_lst=(struct dns_rr*)((char*)rec[r].e+
1430 ROUND_POINTER(sizeof(struct dns_hash_entry)+rec[r].e->name_len
1431 -1+1));
1432 rec[r].tail_rr=&(rec[r].e->rr_lst);
1433 rec[r].rr=rec[r].e->rr_lst;
1434 rec[r].max_ttl=0;
1435 /* link them in a list */
1436 if (r==0){
1437 clist_init(rec[r].e, next, prev);
1438 }else{
1439 clist_append(rec[0].e, rec[r].e, next, prev);
1440 }
1441 }
1442 /* copy the actual data */
1443 for(l=rd, i=0; l && (i<MAX_DNS_RECORDS); l=l->next, i++){
1444 r=rec_idx[i];
1445 ttl=FIX_TTL(l->ttl);
1446 switch(l->type){
1447 case T_A:
1448 rec[r].rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1449 rec[r].max_ttl=MAX(rec[r].max_ttl, ttl);
1450 rec[r].rr->rdata=(void*)((char*)rec[r].rr+
1451 sizeof(struct dns_rr));
1452 memcpy(rec[r].rr->rdata, l->rdata, sizeof(struct a_rdata));
1453 rec[r].rr->next=(void*)((char*)rec[r].rr+
1454 ROUND_POINTER(sizeof(struct dns_rr)+
1455 sizeof(struct a_rdata)));
1456 rec[r].tail_rr=&(rec[r].rr->next);
1457 rec[r].rr=rec[r].rr->next;
1458 break;
1459 case T_AAAA:
1460 rec[r].rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1461 rec[r].max_ttl=MAX(rec[r].max_ttl, ttl);
1462 rec[r].rr->rdata=(void*)((char*)rec[r].rr+
1463 sizeof(struct dns_rr));
1464 memcpy(rec[r].rr->rdata, l->rdata, sizeof(struct aaaa_rdata));
1465 rec[r].rr->next=(void*)((char*)rec[r].rr+
1466 ROUND_POINTER(sizeof(struct dns_rr)+
1467 sizeof(struct aaaa_rdata)));
1468 rec[r].tail_rr=&(rec[r].rr->next);
1469 rec[r].rr=rec[r].rr->next;
1470 break;
1471 case T_SRV:
1472 rec[r].rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1473 rec[r].max_ttl=MAX(rec[r].max_ttl, ttl);
1474 rec[r].rr->rdata=(void*)((char*)rec[r].rr+
1475 ROUND_SHORT(sizeof(struct dns_rr)));
1476 /* copy the whole srv_rdata block*/
1477 memcpy(rec[r].rr->rdata, l->rdata,
1478 SRV_RDATA_SIZE(*(struct srv_rdata*)l->rdata) );
1479 rec[r].rr->next=(void*)((char*)rec[r].rr+
1480 ROUND_POINTER( ROUND_SHORT(sizeof(struct dns_rr))+
1481 SRV_RDATA_SIZE(
1482 *(struct srv_rdata*)l->rdata)));
1483 rec[r].tail_rr=&(rec[r].rr->next);
1484 rec[r].rr=rec[r].rr->next;
1485 break;
1486 case T_NAPTR:
1487 rec[r].rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1488 rec[r].max_ttl=MAX(rec[r].max_ttl, ttl);
1489 rec[r].rr->rdata=(void*)((char*)rec[r].rr+
1490 ROUND_POINTER(sizeof(struct dns_rr)));
1491 /* copy the whole srv_rdata block*/
1492 memcpy(rec[r].rr->rdata, l->rdata,
1493 NAPTR_RDATA_SIZE(*(struct naptr_rdata*)l->rdata) );
1494 /* adjust the string pointer */
1495 ((struct naptr_rdata*)rec[r].rr->rdata)->flags=
1496 translate_pointer((char*)rec[r].rr->rdata, (char*)l->rdata,
1497 (((struct naptr_rdata*)l->rdata)->flags));
1498 ((struct naptr_rdata*)rec[r].rr->rdata)->services=
1499 translate_pointer((char*)rec[r].rr->rdata, (char*)l->rdata,
1500 (((struct naptr_rdata*)l->rdata)->services));
1501 ((struct naptr_rdata*)rec[r].rr->rdata)->regexp=
1502 translate_pointer((char*)rec[r].rr->rdata, (char*)l->rdata,
1503 (((struct naptr_rdata*)l->rdata)->regexp));
1504 ((struct naptr_rdata*)rec[r].rr->rdata)->repl=
1505 translate_pointer((char*)rec[r].rr->rdata, (char*)l->rdata,
1506 (((struct naptr_rdata*)l->rdata)->repl));
1507 rec[r].rr->next=(void*)((char*)rec[r].rr+
1508 ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
1509 NAPTR_RDATA_SIZE(
1510 *(struct naptr_rdata*)l->rdata)));
1511 rec[r].tail_rr=&(rec[r].rr->next);
1512 rec[r].rr=rec[r].rr->next;
1513 break;
1514 case T_CNAME:
1515 rec[r].rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1516 rec[r].max_ttl=MAX(rec[r].max_ttl, ttl);
1517 rec[r].rr->rdata=(void*)((char*)rec[r].rr
1518 +sizeof(struct dns_rr));
1519 memcpy(rec[r].rr->rdata, l->rdata,
1520 CNAME_RDATA_SIZE(*(struct cname_rdata*)l->rdata));
1521 rec[r].rr->next=(void*)((char*)rec[r].rr+
1522 ROUND_POINTER(sizeof(struct dns_rr)+
1523 CNAME_RDATA_SIZE(*(struct cname_rdata*)l->rdata)));
1524 rec[r].tail_rr=&(rec[r].rr->next);
1525 rec[r].rr=rec[r].rr->next;
1526 break;
1527 case T_TXT:
1528 rec[r].rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1529 rec[r].max_ttl=MAX(rec[r].max_ttl, ttl);
1530 rec[r].rr->rdata=(void*)((char*)rec[r].rr+
1531 ROUND_POINTER(sizeof(struct dns_rr)));
1532 memcpy(rec[r].rr->rdata, l->rdata,
1533 TXT_RDATA_SIZE(*(struct txt_rdata*)l->rdata));
1534 /* adjust the string pointers */
1535 for (j=0; j<((struct txt_rdata*)l->rdata)->cstr_no; j++){
1536 ((struct txt_rdata*)rec[r].rr->rdata)->txt[j].cstr=
1537 translate_pointer((char*)rec[r].rr->rdata,
1538 (char*)l->rdata,
1539 ((struct txt_rdata*)l->rdata)->txt[j].cstr);
1540 }
1541 rec[r].rr->next=(void*)((char*)rec[r].rr+
1542 ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
1543 TXT_RDATA_SIZE(*(struct txt_rdata*)l->rdata)));
1544 rec[r].tail_rr=&(rec[r].rr->next);
1545 rec[r].rr=rec[r].rr->next;
1546 break;
1547 case T_EBL:
1548 rec[r].rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1549 rec[r].max_ttl=MAX(rec[r].max_ttl, ttl);
1550 rec[r].rr->rdata=(void*)((char*)rec[r].rr+
1551 ROUND_POINTER(sizeof(struct dns_rr)));
1552 memcpy(rec[r].rr->rdata, l->rdata,
1553 EBL_RDATA_SIZE(*(struct ebl_rdata*)l->rdata));
1554 /* adjust the string pointers */
1555 ((struct ebl_rdata*)rec[r].rr->rdata)->separator=
1556 translate_pointer((char*)rec[r].rr->rdata,
1557 (char*)l->rdata,
1558 ((struct ebl_rdata*)l->rdata)->separator);
1559 ((struct ebl_rdata*)rec[r].rr->rdata)->apex=
1560 translate_pointer((char*)rec[r].rr->rdata,
1561 (char*)l->rdata,
1562 ((struct ebl_rdata*)l->rdata)->apex);
1563 rec[r].rr->next=(void*)((char*)rec[r].rr+
1564 ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
1565 EBL_RDATA_SIZE(*(struct ebl_rdata*)l->rdata)));
1566 rec[r].tail_rr=&(rec[r].rr->next);
1567 rec[r].rr=rec[r].rr->next;
1568 break;
1569 case T_PTR:
1570 rec[r].rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1571 rec[r].max_ttl=MAX(rec[r].max_ttl, ttl);
1572 rec[r].rr->rdata=(void*)((char*)rec[r].rr
1573 +sizeof(struct dns_rr));
1574 memcpy(rec[r].rr->rdata, l->rdata,
1575 PTR_RDATA_SIZE(*(struct ptr_rdata*)l->rdata));
1576 rec[r].rr->next=(void*)((char*)rec[r].rr+
1577 ROUND_POINTER(sizeof(struct dns_rr)+
1578 PTR_RDATA_SIZE(*(struct ptr_rdata*)l->rdata)));
1579 rec[r].tail_rr=&(rec[r].rr->next);
1580 rec[r].rr=rec[r].rr->next;
1581 break;
1582 default:
1583 /* do nothing */
1584 ;
1585 }
1586 }
1587 for (r=0; r<no_records; r++){
1588 *rec[r].tail_rr=0; /* terminate the list */
1589 rec[r].e->expire=now+S_TO_TICKS(rec[r].max_ttl);
1590 }
1591 return rec[0].e;
1592 error:
1593 for (r=0; r<no_records; r++){
1594 dns_destroy_entry(rec[r].e);
1595 }
1596 return 0;
1597 }
1598
1599
1600
1601 inline static struct dns_hash_entry* dns_get_entry(str* name, int type);
1602
1603
1604 #define CACHE_RELEVANT_RECS_ONLY
1605
1606 #ifdef CACHE_RELEVANT_RECS_ONLY
1607 /* internal only: gets related entries from a rdata list, appends them
1608 * to e (list) and returns:
1609 * - e if e is of the requested type
1610 * - if e is a CNAME, tries to get to the end of the CNAME chain and returns
1611 * the final entry if the types match or 0 if the chain is unfinished
1612 * - 0 on error/not found
1613 * records is modified (the used records are removed from the list and freed)
1614 *
1615 * WARNING: - records must be pkg_malloc'ed
1616 * Notes: - if the return is 0 and e->type==T_CNAME, the list will contain
1617 * the CNAME chain (the last element being the last CNAME)
1618 * */
dns_get_related(struct dns_hash_entry * e,int type,struct rdata ** records)1619 inline static struct dns_hash_entry* dns_get_related(struct dns_hash_entry* e,
1620 int type,
1621 struct rdata** records)
1622 {
1623 struct dns_hash_entry* ret;
1624 struct dns_hash_entry* l;
1625 struct dns_hash_entry* t;
1626 struct dns_hash_entry* lst_end;
1627 struct dns_rr* rr;
1628 static int cname_chain_len=0;
1629 str tmp;
1630
1631 ret=0;
1632 l=e;
1633 LM_DBG("(%p (%.*s, %d), %d, *%p) (%d)\n", e,
1634 e->name_len, e->name, e->type, type, *records, cname_chain_len);
1635 clist_init(l, next, prev);
1636 if (type==e->type){
1637 ret=e;
1638 switch(e->type){
1639 case T_SRV:
1640 for (rr=e->rr_lst; rr && *records; rr=rr->next){
1641 tmp.s=((struct srv_rdata*)rr->rdata)->name;
1642 tmp.len=((struct srv_rdata*)rr->rdata)->name_len;
1643 if (!(dns_flags&DNS_IPV6_ONLY)){
1644 t=dns_cache_mk_rd_entry(&tmp, T_A, records);
1645 if (t){
1646 if ((t->type==T_CNAME) && *records)
1647 dns_get_related(t, T_A, records);
1648 lst_end=t->prev; /* needed for clist_append*/
1649 clist_append_sublist(l, t, lst_end, next, prev);
1650 }
1651 }
1652 if (!(dns_flags&DNS_IPV4_ONLY)){
1653 t=dns_cache_mk_rd_entry(&tmp, T_AAAA, records);
1654 if (t){
1655 if ((t->type==T_CNAME) && *records)
1656 dns_get_related(t, T_AAAA, records);
1657 lst_end=t->prev; /* needed for clist_append*/
1658 clist_append_sublist(l, t, lst_end, next, prev);
1659 }
1660 }
1661 }
1662 break;
1663 #ifdef USE_NAPTR
1664 case T_NAPTR:
1665 #ifdef NAPTR_CACHE_ALL_ARS
1666 if (*records)
1667 dns_cache_mk_rd_entry2(*records);
1668 #else
1669 for (rr=e->rr_lst; rr && *records; rr=rr->next){
1670 if (naptr_get_sip_proto((struct naptr_rdata*)rr->rdata)>0){
1671 tmp.s=((struct naptr_rdata*)rr->rdata)->repl;
1672 tmp.len=((struct naptr_rdata*)rr->rdata)->repl_len;
1673 t=dns_cache_mk_rd_entry(&tmp, T_SRV, records);
1674 if (t){
1675 if (*records)
1676 dns_get_related(t, T_SRV, records);
1677 lst_end=t->prev; /* needed for clist_append*/
1678 clist_append_sublist(l, t, lst_end, next, prev);
1679 }
1680 }
1681 }
1682 #endif /* NAPTR_CACHE_ALL_ARS */
1683 #endif /* USE_NAPTR */
1684 break;
1685 default:
1686 /* nothing extra */
1687 break;
1688 }
1689 }else if ((e->type==T_CNAME) && (cname_chain_len<MAX_CNAME_CHAIN)){
1690 /* only one cname is allowed (rfc2181), so we ignore
1691 * the others (we take only the first one) */
1692 tmp.s=((struct cname_rdata*)e->rr_lst->rdata)->name;
1693 tmp.len=((struct cname_rdata*)e->rr_lst->rdata)->name_len;
1694 t=dns_cache_mk_rd_entry(&tmp, type, records);
1695 if (t){
1696 if (*records){
1697 cname_chain_len++;
1698 ret=dns_get_related(t, type, records);
1699 cname_chain_len--;
1700 lst_end=t->prev;
1701 clist_append_sublist(l, t, lst_end, next, prev);
1702 }else{
1703 /* if no more recs, but we found the orig. target anyway,
1704 * return it (e.g. recs are only CNAME x & x A 1.2.3.4 or
1705 * CNAME & SRV) */
1706 if (t->type==type)
1707 ret=t;
1708 clist_append(l, t, next, prev);
1709 }
1710 }
1711 }
1712 return ret;
1713 }
1714 #endif
1715
1716
1717
1718 /* calls the external resolver and populates the cache with the result
1719 * returns: 0 on error, pointer to hash entry on success
1720 * WARNING: make sure you use dns_hash_entry_put() when you're
1721 * finished with the result)
1722 * */
dns_cache_do_request(str * name,int type)1723 inline static struct dns_hash_entry* dns_cache_do_request(str* name, int type)
1724 {
1725 struct rdata* records;
1726 struct dns_hash_entry* e;
1727 struct dns_hash_entry* l;
1728 struct dns_hash_entry* r;
1729 struct dns_hash_entry* t;
1730 struct ip_addr* ip;
1731 str cname_val;
1732 char name_buf[MAX_DNS_NAME];
1733 struct dns_hash_entry* old;
1734 str rec_name;
1735 int add_record, h, err;
1736
1737 e=0;
1738 l=0;
1739 cname_val.s=0;
1740 old = NULL;
1741
1742 #ifdef USE_DNS_CACHE_STATS
1743 if (dns_cache_stats)
1744 dns_cache_stats[process_no].dns_req_cnt++;
1745 #endif /* USE_DNS_CACHE_STATS */
1746
1747 if (type==T_A){
1748 if (str2ip6(name)!=0)
1749 goto end;
1750 if ((ip=str2ip(name))!=0){
1751 e=dns_cache_mk_ip_entry(name, ip);
1752 if (likely(e))
1753 atomic_set(&e->refcnt, 1);/* because we ret. a ref. to it*/
1754 goto end; /* we do not cache obvious stuff */
1755 }
1756 }
1757 else if (type==T_AAAA){
1758 if (str2ip(name)!=0)
1759 goto end;
1760 if ((ip=str2ip6(name))!=0){
1761 e=dns_cache_mk_ip_entry(name, ip);
1762 if (likely(e))
1763 atomic_set(&e->refcnt, 1);/* because we ret. a ref. to it*/
1764 goto end;/* we do not cache obvious stuff */
1765 }
1766 }
1767 #ifdef DNS_WATCHDOG_SUPPORT
1768 if (atomic_get(dns_servers_up)==0)
1769 goto end; /* the servers are down, needless to perform the query */
1770 #endif
1771 if (name->len>=MAX_DNS_NAME){
1772 LM_ERR("name too long (%d chars)\n", name->len);
1773 goto end;
1774 }
1775 /* null terminate the string, needed by get_record */
1776 memcpy(name_buf, name->s, name->len);
1777 name_buf[name->len]=0;
1778 records=get_record(name_buf, type, RES_AR);
1779 if (records){
1780 #ifdef CACHE_RELEVANT_RECS_ONLY
1781 e=dns_cache_mk_rd_entry(name, type, &records);
1782 if (likely(e)){
1783 l=e;
1784 e=dns_get_related(l, type, &records);
1785 /* e should contain the searched entry (if found) and l
1786 * all the entries (e and related) */
1787 if (likely(e)){
1788 atomic_set(&e->refcnt, 1); /* 1 because we return a
1789 ref. to it */
1790 }else{
1791 /* e==0 => l contains a cname list => we use the last
1792 * cname from the chain for a new resolve attempt (l->prev) */
1793 /* only one cname record is allowed (rfc2181), so we ignore
1794 * the others (we take only the first one) */
1795 cname_val.s=
1796 ((struct cname_rdata*)l->prev->rr_lst->rdata)->name;
1797 cname_val.len=
1798 ((struct cname_rdata*)l->prev->rr_lst->rdata)->name_len;
1799 LM_DBG("cname detected: %.*s (%d)\n",
1800 cname_val.len, cname_val.s, cname_val.len);
1801 }
1802 /* add all the records to the hash */
1803 l->prev->next=0; /* we break the double linked list for easier
1804 searching */
1805 LOCK_DNS_HASH(); /* optimization */
1806 for (r=l; r; r=t){
1807 t=r->next;
1808 /* add the new record to the cache by default */
1809 add_record = 1;
1810 if (cfg_get(core, core_cfg, dns_cache_rec_pref) > 0) {
1811 /* check whether there is an old record with the
1812 * same type in the cache */
1813 rec_name.s = r->name;
1814 rec_name.len = r->name_len;
1815 old = _dns_hash_find(&rec_name, r->type, &h, &err);
1816 if (old) {
1817 if (old->type != r->type) {
1818 /* probably CNAME found */
1819 old = NULL;
1820
1821 } else if (old->ent_flags & DNS_FLAG_PERMANENT) {
1822 /* never overwrite permanent entries */
1823 add_record = 0;
1824
1825 } else if ((old->ent_flags & DNS_FLAG_BAD_NAME) == 0) {
1826 /* Non-negative, non-permanent entry found with
1827 * the same type. */
1828 add_record =
1829 /* prefer new records */
1830 ((cfg_get(core, core_cfg, dns_cache_rec_pref) == 2)
1831 /* prefer the record with the longer lifetime */
1832 || ((cfg_get(core, core_cfg, dns_cache_rec_pref) == 3)
1833 && TICKS_LT(old->expire, r->expire)));
1834 }
1835 }
1836 }
1837 if (add_record) {
1838 dns_cache_add_unsafe(r); /* refcnt++ inside */
1839 if (atomic_get(&r->refcnt)==0){
1840 /* if cache adding failed and nobody else is interested
1841 * destroy this entry */
1842 dns_destroy_entry(r);
1843 }
1844 if (old) {
1845 _dns_hash_remove(old);
1846 old = NULL;
1847 }
1848 } else {
1849 if (old) {
1850 if (r == e) {
1851 /* this entry has to be returned */
1852 e = old;
1853 atomic_inc(&e->refcnt);
1854 }
1855 old = NULL;
1856 }
1857 dns_destroy_entry(r);
1858 }
1859 }
1860 UNLOCK_DNS_HASH();
1861 /* if only cnames found => try to resolve the last one */
1862 if (cname_val.s){
1863 LM_DBG("dns_get_entry(cname: %.*s (%d))\n",
1864 cname_val.len, cname_val.s, cname_val.len);
1865 e=dns_get_entry(&cname_val, type);
1866 }
1867 }
1868 #else
1869 l=dns_cache_mk_rd_entry2(records);
1870 #endif
1871 free_rdata_list(records);
1872 }else if (cfg_get(core, core_cfg, dns_neg_cache_ttl)){
1873 e=dns_cache_mk_bad_entry(name, type,
1874 cfg_get(core, core_cfg, dns_neg_cache_ttl), DNS_FLAG_BAD_NAME);
1875 if (likely(e)) {
1876 atomic_set(&e->refcnt, 1); /* 1 because we return a ref. to it */
1877 dns_cache_add(e); /* refcnt++ inside*/
1878 }
1879 goto end;
1880 }
1881 #ifndef CACHE_RELEVANT_RECS_ONLY
1882 if (l){
1883 /* add all the records to the cache, but return only the record
1884 * we are looking for */
1885 l->prev->next=0; /* we break the double linked list for easier
1886 searching */
1887 LOCK_DNS_HASH(); /* optimization */
1888 for (r=l; r; r=t){
1889 t=r->next;
1890 if (e==0){ /* no entry found yet */
1891 if (r->type==T_CNAME){
1892 if ((r->name_len==name->len) && (r->rr_lst) &&
1893 (strncasecmp(r->name, name->s, name->len)==0)){
1894 /* update the name with the name from the cname rec. */
1895 cname_val.s=
1896 ((struct cname_rdata*)r->rr_lst->rdata)->name;
1897 cname_val.len=
1898 ((struct cname_rdata*)r->rr_lst->rdata)->name_len;
1899 name=&cname_val;
1900 }
1901 }else if ((r->type==type) && (r->name_len==name->len) &&
1902 (strncasecmp(r->name, name->s, name->len)==0)){
1903 e=r;
1904 atomic_set(&e->refcnt, 1); /* 1 because we return a ref.
1905 to it */
1906 }
1907 }
1908
1909 /* add the new record to the cache by default */
1910 add_record = 1;
1911 if (cfg_get(core, core_cfg, dns_cache_rec_pref) > 0) {
1912 /* check whether there is an old record with the
1913 * same type in the cache */
1914 rec_name.s = r->name;
1915 rec_name.len = r->name_len;
1916 old = _dns_hash_find(&rec_name, r->type, &h, &err);
1917 if (old) {
1918 if (old->type != r->type) {
1919 /* probably CNAME found */
1920 old = NULL;
1921
1922 } else if (old->ent_flags & DNS_FLAG_PERMANENT) {
1923 /* never overwrite permanent entries */
1924 add_record = 0;
1925
1926 } else if ((old->ent_flags & DNS_FLAG_BAD_NAME) == 0) {
1927 /* Non-negative, non-permanent entry found with
1928 * the same type. */
1929 add_record =
1930 /* prefer new records */
1931 ((cfg_get(core, core_cfg, dns_cache_rec_pref) == 2)
1932 /* prefer the record with the longer lifetime */
1933 || ((cfg_get(core, core_cfg, dns_cache_rec_pref) == 3)
1934 && TICKS_LT(old->expire, r->expire)));
1935 }
1936 }
1937 }
1938 if (add_record) {
1939 dns_cache_add_unsafe(r); /* refcnt++ inside */
1940 if (atomic_get(&r->refcnt)==0){
1941 /* if cache adding failed and nobody else is interested
1942 * destroy this entry */
1943 dns_destroy_entry(r);
1944 }
1945 if (old) {
1946 _dns_hash_remove(old);
1947 old = NULL;
1948 }
1949 } else {
1950 if (old) {
1951 if (r == e) {
1952 /* this entry has to be returned */
1953 e = old;
1954 atomic_inc(&e->refcnt);
1955 }
1956 old = NULL;
1957 }
1958 dns_destroy_entry(r);
1959 }
1960 }
1961 UNLOCK_DNS_HASH();
1962 if ((e==0) && (cname_val.s)){ /* not found, but found a cname */
1963 /* only one cname is allowed (rfc2181), so we ignore the
1964 * others (we take only the first one) */
1965 e=dns_get_entry(&cname_val, type);
1966 }
1967 }
1968 #endif
1969 end:
1970 return e;
1971 }
1972
1973
1974
1975 /* tries to lookup (name, type) in the hash and if not found tries to make
1976 * a dns request
1977 * return: 0 on error, pointer to a dns_hash_entry on success
1978 * WARNING: when not needed anymore dns_hash_put() must be called! */
dns_get_entry(str * name,int type)1979 inline static struct dns_hash_entry* dns_get_entry(str* name, int type)
1980 {
1981 int h;
1982 struct dns_hash_entry* e;
1983 str cname_val;
1984 int err;
1985 static int rec_cnt=0; /* recursion protection */
1986
1987 e=0;
1988 if (rec_cnt>MAX_CNAME_CHAIN){
1989 LM_WARN("CNAME chain too long or recursive CNAMEs (\"%.*s\")\n",
1990 name->len, name->s);
1991 goto error;
1992 }
1993 rec_cnt++;
1994 e=dns_hash_get(name, type, &h, &err);
1995 #ifdef USE_DNS_CACHE_STATS
1996 if (e) {
1997 if ((e->ent_flags & DNS_FLAG_BAD_NAME) && dns_cache_stats)
1998 /* negative DNS cache hit */
1999 dns_cache_stats[process_no].dc_neg_hits_cnt++;
2000 else if (((e->ent_flags & DNS_FLAG_BAD_NAME) == 0)
2001 && dns_cache_stats
2002 ) /* DNS cache hit */
2003 dns_cache_stats[process_no].dc_hits_cnt++;
2004
2005 if (dns_cache_stats)
2006 dns_cache_stats[process_no].dns_req_cnt++;
2007 }
2008 #endif /* USE_DNS_CACHE_STATS */
2009
2010 if ((e==0) && ((err) || ((e=dns_cache_do_request(name, type))==0))){
2011 goto error;
2012 }else if ((e->type==T_CNAME) && (type!=T_CNAME)){
2013 /* cname found instead which couldn't be resolved with the cached
2014 * info => try a dns request */
2015 /* only one cname record is allowed (rfc2181), so we ignore
2016 * the others (we take only the first one) */
2017 cname_val.s= ((struct cname_rdata*)e->rr_lst->rdata)->name;
2018 cname_val.len=((struct cname_rdata*)e->rr_lst->rdata)->name_len;
2019 dns_hash_put(e); /* not interested in the cname anymore */
2020 if ((e=dns_cache_do_request(&cname_val, type))==0)
2021 goto error; /* could not resolve cname */
2022 }
2023 /* found */
2024 if ((e->rr_lst==0) || (e->ent_flags & DNS_FLAG_BAD_NAME)){
2025 /* negative cache => not resolvable */
2026 dns_hash_put(e);
2027 e=0;
2028 }
2029 error:
2030 rec_cnt--;
2031 return e;
2032 }
2033
2034
2035
2036 /* gets the first non-expired record starting with record no
2037 * from the dns_hash_entry struct e
2038 * params: e - dns_hash_entry struct
2039 * *no - it must contain the start record number (0 initially);
2040 * it will be filled with the returned record number
2041 * now - current time/ticks value
2042 * returns pointer to the rr on success and sets no to the rr number
2043 * 0 on error and fills the error flags
2044 *
2045 * Example usage:
2046 * list all non-expired non-bad-marked ips for name:
2047 * e=dns_get_entry(name, T_A);
2048 * if (e){
2049 * *no=0;
2050 * now=get_ticks_raw();
2051 * while(rr=dns_entry_get_rr(e, no, now){
2052 * LM_DBG("address %d\n", *no);
2053 * *no++; ( get the next address next time )
2054 * }
2055 * }
2056 */
dns_entry_get_rr(struct dns_hash_entry * e,unsigned char * no,ticks_t now)2057 inline static struct dns_rr* dns_entry_get_rr( struct dns_hash_entry* e,
2058 unsigned char* no, ticks_t now)
2059 {
2060 struct dns_rr* rr;
2061 int n;
2062 #ifdef DNS_WATCHDOG_SUPPORT
2063 int servers_up;
2064
2065 servers_up = atomic_get(dns_servers_up);
2066 #endif
2067
2068 for(rr=e->rr_lst, n=0;rr && (n<*no);rr=rr->next, n++);/* skip *no records*/
2069 for(;rr;rr=rr->next){
2070 if (
2071 #ifdef DNS_WATCHDOG_SUPPORT
2072 /* check the expiration time only when the servers are up */
2073 servers_up &&
2074 #endif
2075 ((e->ent_flags & DNS_FLAG_PERMANENT) == 0) &&
2076 ((s_ticks_t)(now-rr->expire)>=0) /* expired rr */
2077 )
2078 continue;
2079 /* everything is ok now */
2080 *no=n;
2081 return rr;
2082 }
2083 *no=n;
2084 return 0;
2085 }
2086
2087
2088 #ifdef DNS_SRV_LB
2089
2090 #define srv_reset_tried(p) (*(p)=0)
2091 #define srv_marked(p, i) (*(p)&(1UL<<(i)))
2092 #define srv_mark_tried(p, i) \
2093 do{ \
2094 (*(p)|=(1UL<<(i))); \
2095 }while(0)
2096
2097 #define srv_next_rr(n, f, i) srv_mark_tried(f, i)
2098
2099 /* returns a random number between 0 and max inclusive (0<=r<=max) */
dns_srv_random(unsigned max)2100 inline static unsigned dns_srv_random(unsigned max)
2101 {
2102 return fastrand_max(max);
2103 }
2104
2105 /* for a SRV record it will return the next entry to be tried according
2106 * to the RFC2782 server selection mechanism
2107 * params:
2108 * e is a dns srv hash entry
2109 * no is the start index of the current group (a group is a set of SRV
2110 * rrs with the same priority)
2111 * tried is a bitmap where the tried srv rrs of the same priority are
2112 * marked
2113 * now - current time/ticks value
2114 * returns pointer to the rr on success and sets no to the rr number
2115 * 0 on error and fills the error flags
2116 * WARNING: unlike dns_entry_get_rr() this will always return another
2117 * another rr automatically (*no must not be incremented)
2118 *
2119 * Example usage:
2120 * list all non-expired, non-bad-marked, never tried before srv records
2121 * using the rfc2782 algo:
2122 * e=dns_get_entry(name, T_SRV);
2123 * if (e){
2124 * no=0;
2125 * srv_reset_tried(&tried);
2126 * now=get_ticks_raw();
2127 * while(rr=dns_srv_get_nxt_rr(e, &tried, &no, now){
2128 * LM_DBG("address %d\n", *no);
2129 * }
2130 * }
2131 *
2132 */
dns_srv_get_nxt_rr(struct dns_hash_entry * e,srv_flags_t * tried,unsigned char * no,ticks_t now)2133 inline static struct dns_rr* dns_srv_get_nxt_rr(struct dns_hash_entry* e,
2134 srv_flags_t* tried,
2135 unsigned char* no, ticks_t now)
2136 {
2137 #define MAX_SRV_GRP_IDX (sizeof(srv_flags_t)*8)
2138 struct dns_rr* rr;
2139 struct dns_rr* start_grp;
2140 int n;
2141 unsigned sum;
2142 unsigned prio;
2143 unsigned rand_w;
2144 int found;
2145 int saved_idx;
2146 int zero_weight; /* number of records with 0 weight */
2147 int i, idx;
2148 struct r_sums_entry{
2149 unsigned r_sum;
2150 struct dns_rr* rr;
2151 }r_sums[MAX_SRV_GRP_IDX];
2152 #ifdef DNS_WATCHDOG_SUPPORT
2153 int servers_up;
2154
2155 servers_up = atomic_get(dns_servers_up);
2156 #endif
2157
2158 memset(r_sums, 0, sizeof(struct r_sums_entry) * MAX_SRV_GRP_IDX);
2159 rand_w=0;
2160 for(rr=e->rr_lst, n=0;rr && (n<*no);rr=rr->next, n++);/* skip *no records*/
2161
2162 retry:
2163 if (unlikely(rr==0))
2164 goto no_more_rrs;
2165 start_grp=rr;
2166 prio=((struct srv_rdata*)start_grp->rdata)->priority;
2167 sum=0;
2168 saved_idx=-1;
2169 zero_weight = 0;
2170 found=0;
2171 for (idx=0;rr && (prio==((struct srv_rdata*)rr->rdata)->priority) &&
2172 (idx < MAX_SRV_GRP_IDX); idx++, rr=rr->next){
2173 if ((
2174 #ifdef DNS_WATCHDOG_SUPPORT
2175 /* check the expiration time only when the servers are up */
2176 servers_up &&
2177 #endif
2178 ((e->ent_flags & DNS_FLAG_PERMANENT) == 0) &&
2179 ((s_ticks_t)(now-rr->expire)>=0) /* expired entry */) ||
2180 (srv_marked(tried, idx)) ) /* already tried */{
2181 r_sums[idx].r_sum=0; /* 0 sum, to skip over it */
2182 r_sums[idx].rr=0; /* debug: mark it as unused */
2183 continue;
2184 }
2185 /* special case, 0 weight records should be "first":
2186 * remember the first rr int the "virtual" list: A 0 weight must
2187 * come first if present, else get the first one */
2188 if ((saved_idx==-1) || (((struct srv_rdata*)rr->rdata)->weight==0)){
2189 saved_idx=idx;
2190 }
2191 zero_weight += (((struct srv_rdata*)rr->rdata)->weight == 0);
2192 sum+=((struct srv_rdata*)rr->rdata)->weight;
2193 r_sums[idx].r_sum=sum;
2194 r_sums[idx].rr=rr;
2195 found++;
2196 }
2197 if (found==0){
2198 /* try in the next priority group */
2199 n+=idx; /* next group start idx, last rr */
2200 srv_reset_tried(tried);
2201 goto retry;
2202 }else if ((found==1) || (sum==0) ||
2203 (((rand_w=(dns_srv_random(sum-1)+1))==1) && zero_weight &&
2204 (dns_srv_random(DNS_SRV_ZERO_W_CHANCE)==0))){
2205 /* 1. if only one found, avoid a useless random() call
2206 and select it (saved_idx will point to it).
2207 * 2. if the sum of weights is 0 (all have 0 weight) or
2208 * 3. rand_w==1 and there are records with 0 weight and
2209 * random(probab. of selecting a 0-weight)
2210 * immediately select a 0 weight record.
2211 * (this takes care of the 0-weight at the beginning requirement) */
2212 i=saved_idx; /* saved idx contains either first 0 weight or first
2213 valid record */
2214 goto found;
2215 }
2216 /* if we are here => rand_w is not 0 and we have at least 2 valid options
2217 * => we can safely iterate on the whole r_sums[] whithout any other
2218 * extra checks */
2219 for (i=0; (i<idx) && (r_sums[i].r_sum<rand_w); i++);
2220 found:
2221 if(i<MAX_SRV_GRP_IDX) {
2222 LM_DBG("(%p, %lx, %d, %u): selected %d/%d in grp. %d"
2223 " (rand_w=%d, rr=%p rd=%p p=%d w=%d rsum=%d)\n",
2224 e, (unsigned long)*tried, *no, now, i, idx, n, rand_w,
2225 r_sums[i].rr, (r_sums[i].rr) ? r_sums[i].rr->rdata : 0,
2226 (r_sums[i].rr && r_sums[i].rr->rdata)
2227 ? ((struct srv_rdata *)r_sums[i].rr->rdata)->priority
2228 : 0,
2229 (r_sums[i].rr && r_sums[i].rr->rdata)
2230 ? ((struct srv_rdata *)r_sums[i].rr->rdata)->weight
2231 : 0,
2232 r_sums[i].r_sum);
2233 /* i is the winner */
2234 *no = n; /* grp. start */
2235 if(i < 8 * sizeof(*tried))
2236 srv_mark_tried(tried, i); /* mark it */
2237 return r_sums[i].rr;
2238 } else {
2239 LM_WARN("index out of bounds\n");
2240 *no=n;
2241 return 0;
2242 }
2243 no_more_rrs:
2244 *no=n;
2245 return 0;
2246 }
2247 #endif /* DNS_SRV_LB */
2248
2249
2250
2251 /* gethostbyname compatibility: converts a dns_hash_entry structure
2252 * to a statical internal hostent structure
2253 * returns a pointer to the internal hostent structure on success or
2254 * 0 on error
2255 */
dns_entry2he(struct dns_hash_entry * e)2256 inline static struct hostent* dns_entry2he(struct dns_hash_entry* e)
2257 {
2258 static struct hostent he;
2259 static char hostname[256];
2260 static char* p_aliases[1];
2261 static char* p_addr[DNS_HE_MAX_ADDR+1];
2262 static char address[16*DNS_HE_MAX_ADDR]; /* max 10 ipv6 addresses */
2263 int af, len;
2264 struct dns_rr* rr;
2265 unsigned char rr_no;
2266 unsigned char *ip;
2267 ticks_t now;
2268 int i;
2269
2270 switch(e->type){
2271 case T_A:
2272 af=AF_INET;
2273 len=4;
2274 break;
2275 case T_AAAA:
2276 af=AF_INET6;
2277 len=16;
2278 break;
2279 default:
2280 LM_CRIT("wrong entry type %d for %.*s\n",
2281 e->type, e->name_len, e->name);
2282 return 0;
2283 }
2284
2285
2286 rr_no=0;
2287 now=get_ticks_raw();
2288 /* if the entry has already expired use the time at the end of lifetime */
2289 if (unlikely((s_ticks_t)(now-e->expire)>=0)) now=e->expire-1;
2290 rr=dns_entry_get_rr(e, &rr_no, now);
2291 for(i=0; rr && (i<DNS_HE_MAX_ADDR); i++,
2292 rr=dns_entry_get_rr(e, &rr_no, now)){
2293 p_addr[i]=&address[i*len];
2294 switch(e->type){
2295 case T_A:
2296 ip = ((struct a_rdata*)rr->rdata)->ip;
2297 break;
2298 case T_AAAA:
2299 ip = ((struct aaaa_rdata*)rr->rdata)->ip6;
2300 break;
2301 default:
2302 LM_CRIT("wrong entry type %d for %.*s\n",
2303 e->type, e->name_len, e->name);
2304 return 0;
2305 }
2306 memcpy(p_addr[i], ip, len);
2307 rr_no++;
2308 }
2309 if (i==0){
2310 LM_DBG("no good records found (%d) for %.*s (%d)\n",
2311 rr_no, e->name_len, e->name, e->type);
2312 return 0; /* no good record found */
2313 }
2314
2315 p_addr[i]=0; /* mark the end of the addresses */
2316 p_aliases[0]=0; /* no aliases */
2317 memcpy(hostname, e->name, e->name_len);
2318 hostname[e->name_len]=0;
2319
2320 he.h_addrtype=af;
2321 he.h_length=len;
2322 he.h_addr_list=p_addr;
2323 he.h_aliases=p_aliases;
2324 he.h_name=hostname;
2325
2326 return &he;
2327 }
2328
2329
2330
2331 /* gethostbyname compatibility: performs an a_lookup and returns a pointer
2332 * to a statical internal hostent structure
2333 * returns 0 on success, <0 on error (see the error codes)
2334 */
dns_a_get_he(str * name)2335 inline static struct hostent* dns_a_get_he(str* name)
2336 {
2337 struct dns_hash_entry* e;
2338 struct ip_addr* ip;
2339 struct hostent* he;
2340
2341 e=0;
2342 if (str2ip6(name)!=0)
2343 return 0;
2344 if ((ip=str2ip(name))!=0){
2345 return ip_addr2he(name, ip);
2346 }
2347 if ((e=dns_get_entry(name, T_A))==0)
2348 return 0;
2349 /* found */
2350 he=dns_entry2he(e);
2351 dns_hash_put(e);
2352 return he;
2353 }
2354
2355
2356 /* gethostbyname compatibility: performs an aaaa_lookup and returns a pointer
2357 * to a statical internal hostent structure
2358 * returns 0 on success, <0 on error (see the error codes)
2359 */
dns_aaaa_get_he(str * name)2360 inline static struct hostent* dns_aaaa_get_he(str* name)
2361 {
2362 struct dns_hash_entry* e;
2363 struct ip_addr* ip;
2364 struct hostent* he;
2365
2366 e=0;
2367 if (str2ip(name)!=0)
2368 return 0;
2369 if ((ip=str2ip6(name))!=0){
2370 return ip_addr2he(name, ip);
2371 }
2372 if ((e=dns_get_entry(name, T_AAAA))==0)
2373 return 0;
2374 /* found */
2375 he=dns_entry2he(e);
2376 dns_hash_put(e);
2377 return he;
2378 }
2379
2380
2381
2382 /* returns 0 on success, -1 on error (rr type does not contain an ip) */
dns_rr2ip(int type,struct dns_rr * rr,struct ip_addr * ip)2383 inline static int dns_rr2ip(int type, struct dns_rr* rr, struct ip_addr* ip)
2384 {
2385 switch(type){
2386 case T_A:
2387 ip->af=AF_INET;
2388 ip->len=4;
2389 memcpy(ip->u.addr, ((struct a_rdata*)rr->rdata)->ip, 4);
2390 return 0;
2391 break;
2392 case T_AAAA:
2393 ip->af=AF_INET6;
2394 ip->len=16;
2395 memcpy(ip->u.addr, ((struct aaaa_rdata*)rr->rdata)->ip6, 16);
2396 return 0;
2397 break;
2398 }
2399 return -1;
2400 }
2401
2402
2403
2404 /* gethostbyname compatibility:
2405 * performs an a or aaaa dns lookup, returns 0 on error and a pointer to a
2406 * static hostent structure on success
2407 * flags: - none set: tries first an a_lookup and if it fails an aaaa_lookup
2408 * - DNS_IPV6_FIRST: tries first an aaaa_lookup and then an a_lookup
2409 * - DNS_IPV4_ONLY: tries only an a_lookup
2410 * - DNS_IPV6_ONLY: tries only an aaaa_lookup
2411 */
dns_get_he(str * name,int flags)2412 struct hostent* dns_get_he(str* name, int flags)
2413 {
2414 struct hostent* he;
2415
2416 if ((flags&(DNS_IPV6_FIRST|DNS_IPV6_ONLY))){
2417 he=dns_aaaa_get_he(name);
2418 if (he) return he;
2419 }else{
2420 he=dns_a_get_he(name);
2421 if (he) return he;
2422 }
2423 if (flags&DNS_IPV6_FIRST){
2424 he=dns_a_get_he(name);
2425 }else if (!(flags&(DNS_IPV6_ONLY|DNS_IPV4_ONLY))){
2426 he=dns_aaaa_get_he(name);
2427 }
2428 return he;
2429 }
2430
2431
2432
2433 /* sip_resolvehost helper: gets the first good hostent/port combination
2434 * returns 0 on error, pointer to static hostent structure on success
2435 * (and sets port)*/
dns_srv_get_he(str * name,unsigned short * port,int flags)2436 struct hostent* dns_srv_get_he(str* name, unsigned short* port, int flags)
2437 {
2438 struct dns_hash_entry* e;
2439 struct dns_rr* rr;
2440 str rr_name;
2441 struct hostent* he;
2442 ticks_t now;
2443 unsigned char rr_no;
2444
2445 rr=0;
2446 he=0;
2447 now=get_ticks_raw();
2448 if ((e=dns_get_entry(name, T_SRV))==0)
2449 goto error;
2450 /* look inside the RRs for a good one (not expired or marked bad) */
2451 rr_no=0;
2452 while( (rr=dns_entry_get_rr(e, &rr_no, now))!=0){
2453 /* everything is ok now, we can try to resolve the ip */
2454 rr_name.s=((struct srv_rdata*)rr->rdata)->name;
2455 rr_name.len=((struct srv_rdata*)rr->rdata)->name_len;
2456 if ((he=dns_get_he(&rr_name, flags))!=0){
2457 /* success, at least one good ip found */
2458 if(port) *port=((struct srv_rdata*)rr->rdata)->port;
2459 goto end;
2460 }
2461 rr_no++; /* try from the next record, the current one was not good */
2462 }
2463 /* if we reach this point => error, we couldn't find any good rr */
2464 end:
2465 if (e) dns_hash_put(e);
2466 error:
2467 return he;
2468 }
2469
2470
2471
dns_resolvehost(char * name)2472 struct hostent* dns_resolvehost(char* name)
2473 {
2474 str host;
2475 struct hostent* ret;
2476 if ((cfg_get(core, core_cfg, use_dns_cache)==0) || (dns_hash==0)){ /* not init yet */
2477 ret = _resolvehost(name);
2478 if(unlikely(!ret)){
2479 /* increment dns error counter */
2480 if(counters_initialized())
2481 counter_inc(dns_cnts_h.failed_dns_req);
2482 }
2483 return ret;
2484 }
2485 host.s=name;
2486 host.len=strlen(name);
2487 return dns_get_he(&host, dns_flags);
2488 }
2489
2490
2491 /* resolves a host name trying SRV lookup if *port==0 or normal A/AAAA lookup
2492 * if *port!=0.
2493 * when performing SRV lookup (*port==0) it will use proto to look for
2494 * tcp or udp hosts, otherwise proto is unused; if proto==0 => no SRV lookup
2495 * returns: hostent struct & *port filled with the port from the SRV record;
2496 * 0 on error
2497 */
dns_srv_sip_resolvehost(str * name,unsigned short * port,char * proto)2498 struct hostent* dns_srv_sip_resolvehost(str* name, unsigned short* port,
2499 char* proto)
2500 {
2501 struct hostent* he;
2502 struct ip_addr* ip;
2503 static char tmp[MAX_DNS_NAME]; /* tmp. buff. for SRV lookups */
2504 str srv_name;
2505 char srv_proto;
2506
2507 if ((cfg_get(core, core_cfg, use_dns_cache)==0) || (dns_hash==0)){
2508 /* not init or off => use normal, non-cached version */
2509 return _sip_resolvehost(name, port, proto);
2510 }
2511 if (proto){ /* makes sure we have a protocol set*/
2512 if (*proto==0)
2513 *proto=srv_proto=PROTO_UDP; /* default */
2514 else
2515 srv_proto=*proto;
2516 }else{
2517 srv_proto=PROTO_UDP;
2518 }
2519 /* try SRV if no port specified (draft-ietf-sip-srv-06) */
2520 if ((port)&&(*port==0)){
2521 *port=(srv_proto==PROTO_TLS)?SIPS_PORT:SIP_PORT; /* just in case we
2522 don't find another */
2523 if ((name->len+SRV_MAX_PREFIX_LEN+1)>MAX_DNS_NAME){
2524 LM_WARN("domain name too long (%d), unable to perform SRV lookup\n",
2525 name->len);
2526 }else{
2527 /* check if it's an ip address */
2528 if ( ((ip=str2ip(name))!=0)
2529 || ((ip=str2ip6(name))!=0)
2530 ){
2531 /* we are lucky, this is an ip address */
2532 return ip_addr2he(name,ip);
2533 }
2534
2535 if(srv_proto==PROTO_WS || srv_proto==PROTO_WSS) {
2536 /* no srv records for web sockets */
2537 return 0;
2538 }
2539
2540 switch(srv_proto){
2541 case PROTO_UDP:
2542 case PROTO_TCP:
2543 case PROTO_TLS:
2544 case PROTO_SCTP:
2545 create_srv_name(srv_proto, name, tmp);
2546 break;
2547 default:
2548 LM_CRIT("unknown proto %d\n", (int)srv_proto);
2549 return 0;
2550 }
2551
2552 srv_name.s=tmp;
2553 srv_name.len=strlen(tmp);
2554 if ((he=dns_srv_get_he(&srv_name, port, dns_flags))!=0)
2555 return he;
2556 }
2557 }
2558 /*skip_srv:*/
2559 if (name->len >= MAX_DNS_NAME) {
2560 LM_ERR("domain name too long\n");
2561 return 0;
2562 }
2563 he=dns_get_he(name, dns_flags);
2564 return he;
2565 }
2566
2567
2568
2569 #ifdef USE_NAPTR
2570 /* iterates over a naptr rr list, returning each time a "good" naptr record
2571 * is found.( srv type, no regex and a supported protocol)
2572 * params:
2573 * naptr_head - naptr dns_rr list head
2574 * tried - bitmap used to keep track of the already tried records
2575 * (no more then sizeof(tried)*8 valid records are
2576 * ever walked
2577 * srv_name - if succesfull, it will be set to the selected record
2578 * srv name (naptr repl.)
2579 * proto - if succesfull it will be set to the selected record
2580 * protocol
2581 * returns 0 if no more records found or a pointer to the selected record
2582 * and sets protocol and srv_name
2583 * WARNING: when calling first time make sure you run first
2584 * naptr_iterate_init(&tried)
2585 */
dns_naptr_sip_iterate(struct dns_rr * naptr_head,naptr_bmp_t * tried,str * srv_name,char * proto)2586 struct naptr_rdata* dns_naptr_sip_iterate(struct dns_rr* naptr_head,
2587 naptr_bmp_t* tried,
2588 str* srv_name, char* proto)
2589 {
2590 int i, idx;
2591 struct dns_rr* l;
2592 struct naptr_rdata* naptr;
2593 struct naptr_rdata* naptr_saved;
2594 char saved_proto;
2595 char naptr_proto;
2596
2597 idx=0;
2598 naptr_proto=PROTO_NONE;
2599 naptr_saved=0;
2600 saved_proto=0;
2601 i=0;
2602 for(l=naptr_head; l && (i<MAX_NAPTR_RRS); l=l->next){
2603 naptr=(struct naptr_rdata*) l->rdata;
2604 if (naptr==0){
2605 LM_CRIT("null rdata\n");
2606 goto end;
2607 }
2608 /* check if valid and get proto */
2609 if ((naptr_proto=naptr_get_sip_proto(naptr))<=0) continue;
2610 if (*tried& (1<<i)){
2611 i++;
2612 continue; /* already tried */
2613 }
2614 LM_DBG("found a valid sip NAPTR rr %.*s, proto %d\n",
2615 naptr->repl_len, naptr->repl, (int)naptr_proto);
2616 if (naptr->skip_record) {
2617 i++;
2618 continue;
2619 }
2620 if ((naptr_proto_supported(naptr_proto))){
2621 if (naptr_choose(&naptr_saved, &saved_proto,
2622 naptr, naptr_proto))
2623 idx=i;
2624 }
2625 i++;
2626 }
2627 if (naptr_saved){
2628 /* found something */
2629 LM_DBG("choosed NAPTR rr %.*s, proto %d tried: 0x%x\n",
2630 naptr_saved->repl_len, naptr_saved->repl, (int)saved_proto, *tried);
2631 *tried|=1<<idx;
2632 *proto=saved_proto;
2633 srv_name->s=naptr_saved->repl;
2634 srv_name->len=naptr_saved->repl_len;
2635 return naptr_saved;
2636 }
2637 end:
2638 return 0;
2639 }
2640
2641
2642
2643 /* resolves a host name trying NAPTR lookup if *proto==0 and *port==0, SRV
2644 * lookup if *port==0 or normal A/AAAA lookup
2645 * if *port!=0.
2646 * when performing SRV lookup (*port==0) it will use proto to look for
2647 * tcp or udp hosts; if proto==0 => no SRV lookup
2648 * returns: hostent struct & *port filled with the port from the SRV record;
2649 * 0 on error
2650 */
dns_naptr_sip_resolvehost(str * name,unsigned short * port,char * proto)2651 struct hostent* dns_naptr_sip_resolvehost(str* name, unsigned short* port,
2652 char* proto)
2653 {
2654 struct hostent* he;
2655 struct ip_addr* tmp_ip;
2656 naptr_bmp_t tried_bmp;
2657 struct dns_hash_entry* e;
2658 char n_proto;
2659 char origproto;
2660 str srv_name;
2661
2662 if(proto) {
2663 origproto=*proto;
2664 } else {
2665 origproto=PROTO_NONE;
2666 }
2667 he=0;
2668 if (dns_hash==0){ /* not init => use normal, non-cached version */
2669 LM_WARN("called before dns cache initialization\n");
2670 return _sip_resolvehost(name, port, proto);
2671 }
2672 if (proto && port && (*proto==0) && (*port==0)){
2673 *proto=PROTO_UDP; /* just in case we don't find another */
2674 /* check if it's an ip address */
2675 if ( ((tmp_ip=str2ip(name))!=0)
2676 || ((tmp_ip=str2ip6(name))!=0)
2677 ){
2678 /* we are lucky, this is an ip address */
2679 if (((dns_flags&DNS_IPV4_ONLY) && (tmp_ip->af==AF_INET6))||
2680 ((dns_flags&DNS_IPV6_ONLY) && (tmp_ip->af==AF_INET))){
2681 return 0;
2682 }
2683 *port=SIP_PORT;
2684 return ip_addr2he(name, tmp_ip);
2685 }
2686 /* do naptr lookup */
2687 if ((e=dns_get_entry(name, T_NAPTR))==0)
2688 goto naptr_not_found;
2689 naptr_iterate_init(&tried_bmp);
2690 while(dns_naptr_sip_iterate(e->rr_lst, &tried_bmp,
2691 &srv_name, &n_proto)){
2692 if ((he=dns_srv_get_he(&srv_name, port, dns_flags))!=0){
2693 LM_DBG("(%.*s, %d, %d) srv, ret=%p\n",
2694 name->len, name->s, (int)*port, (int)*proto, he);
2695 dns_hash_put(e);
2696 *proto=n_proto;
2697 return he;
2698 }
2699 }
2700 /* no acceptable naptr record found, fallback to srv */
2701 dns_hash_put(e);
2702 }
2703 naptr_not_found:
2704 if(proto) *proto = origproto;
2705 he = no_naptr_srv_sip_resolvehost(name,port,proto);
2706 /* fallback all the way down to A/AAAA */
2707 if (he==0) {
2708 he=dns_get_he(name,dns_flags);
2709 }
2710 return he;
2711 }
2712 #endif /* USE_NAPTR */
2713
2714
2715
2716 /* resolves a host name trying NAPTR lookup if *proto==0 and *port==0, SRV
2717 * lookup if *port==0 or normal A/AAAA lookup
2718 * if *port!=0.
2719 * when performing SRV lookup (*port==0) it will use proto to look for
2720 * tcp or udp hosts; if proto==0 => no SRV lookup
2721 * returns: hostent struct & *port filled with the port from the SRV record;
2722 * 0 on error
2723 */
dns_sip_resolvehost(str * name,unsigned short * port,char * proto)2724 struct hostent* dns_sip_resolvehost(str* name, unsigned short* port,
2725 char* proto)
2726 {
2727 #ifdef USE_NAPTR
2728 if (dns_flags&DNS_TRY_NAPTR)
2729 return dns_naptr_sip_resolvehost(name, port, proto);
2730 #endif
2731 return dns_srv_sip_resolvehost(name, port, proto);
2732 }
2733
2734
2735
2736 /* performs an a lookup, fills the dns_entry pointer and the ip addr.
2737 * (with the first good ip). if *e ==0 does the a lookup, and changes it
2738 * to the result, if not it uses the current value and tries to use
2739 * the rr_no record from it.
2740 * params: e - must contain the "in-use" dns_hash_entry pointer (from
2741 * a previous call) or *e==0 (for the first call)
2742 * name - host name for which we do the lookup (required only
2743 * when *e==0)
2744 * ip - will be filled with the first good resolved ip started
2745 * at *rr_no
2746 * rr_no - record number to start searching for a good ip from
2747 * (e.g. value from previous call + 1), filled on return
2748 * with the number of the record corresponding to the
2749 * returned ip
2750 * returns 0 on success, <0 on error (see the error codes),
2751 * fills e, ip and rr_no
2752 * On end of records (when used to iterate on all the ips) it
2753 * will return E_DNS_EOR (you should not log an error for this
2754 * value, is just a signal that the address list end has been reached)
2755 * Note: either e or name must be different from 0 (name.s !=0 also)
2756 * WARNING: dns_hash_put(*e) must be called when you don't need
2757 * the entry anymore and *e!=0 (failling to do so => mem. leak)
2758 * Example:
2759 * dns_entry=0;
2760 * ret=dns_a_get_ip(&dns_entry, name, &ip, &rr_no); -- get the first rr.
2761 * ...
2762 * rr_no++;
2763 * while((ret>=0) && dns_entry)
2764 * dns_a_get_ip(&dns_entry, name, &ip, &rr_no); -- get the next rr
2765 * if (ret!=-E_DNS_EOR) ERROR(....);
2766 * ...
2767 * dns_hash_put(dns_entry); -- finished with the entry
2768 */
dns_a_resolve(struct dns_hash_entry ** e,unsigned char * rr_no,str * name,struct ip_addr * ip)2769 inline static int dns_a_resolve( struct dns_hash_entry** e,
2770 unsigned char* rr_no,
2771 str* name,
2772 struct ip_addr* ip)
2773 {
2774 struct dns_rr* rr;
2775 int ret;
2776 ticks_t now;
2777 struct ip_addr* tmp;
2778
2779 rr=0;
2780 ret=-E_DNS_NO_IP;
2781 if (*e==0){ /* do lookup */
2782 /* if ip don't set *e */
2783 if (str2ip6(name)!=0)
2784 goto error;
2785 if ((tmp=str2ip(name))!=0){
2786 *ip=*tmp;
2787 *rr_no=0;
2788 return 0;
2789 }
2790 if ((*e=dns_get_entry(name, T_A))==0)
2791 goto error;
2792 /* found */
2793 *rr_no=0;
2794 }
2795 now=get_ticks_raw();
2796 /* if the entry has already expired use the time at the end of lifetime */
2797 if (unlikely((s_ticks_t)(now-(*e)->expire)>=0)) now=(*e)->expire-1;
2798 rr=dns_entry_get_rr(*e, rr_no, now);
2799 if (rr){
2800 /* everything is ok now, we can try to "convert" the ip */
2801 dns_rr2ip((*e)->type, rr, ip);
2802 ret=0;
2803 }else{
2804 ret=-E_DNS_EOR;
2805 }
2806 error:
2807 LM_DBG("(%.*s, %d) returning %d\n", name->len, name->s, *rr_no, ret);
2808 return ret;
2809 }
2810
2811
2812 /* lookup, fills the dns_entry pointer and the ip addr.
2813 * (with the first good ip). if *e ==0 does the a lookup, and changes it
2814 * to the result, if not it uses the current value and tries to use
2815 * Same as dns_a_resolve but for aaaa records (see above).
2816 */
dns_aaaa_resolve(struct dns_hash_entry ** e,unsigned char * rr_no,str * name,struct ip_addr * ip)2817 inline static int dns_aaaa_resolve( struct dns_hash_entry** e,
2818 unsigned char* rr_no,
2819 str* name,
2820 struct ip_addr* ip)
2821 {
2822 struct dns_rr* rr;
2823 int ret;
2824 ticks_t now;
2825 struct ip_addr* tmp;
2826
2827 rr=0;
2828 ret=-E_DNS_NO_IP;
2829 if (*e==0){ /* do lookup */
2830 /* if ip don't set *e */
2831 if (str2ip(name)!=0)
2832 goto error;
2833 if ((tmp=str2ip6(name))!=0){
2834 *ip=*tmp;
2835 *rr_no=0;
2836 return 0;
2837 }
2838 if ((*e=dns_get_entry(name, T_AAAA))==0)
2839 goto error;
2840 /* found */
2841 *rr_no=0;
2842 }
2843 now=get_ticks_raw();
2844 /* if the entry has already expired use the time at the end of lifetime */
2845 if (unlikely((s_ticks_t)(now-(*e)->expire)>=0)) now=(*e)->expire-1;
2846 rr=dns_entry_get_rr(*e, rr_no, now);
2847 if (rr){
2848 /* everything is ok now, we can try to "convert" the ip */
2849 dns_rr2ip((*e)->type, rr, ip);
2850 ret=0;
2851 }else{
2852 ret=-E_DNS_EOR; /* no more records */
2853 }
2854 error:
2855 return ret;
2856 }
2857
2858
2859
2860 /* performs an a or aaaa dns lookup, returns <0 on error (see the
2861 * dns error codes) and 0 on success
2862 * flags: - none set: tries first an a_lookup and if it fails an aaaa_lookup
2863 * - DNS_IPV6_FIRST: tries first an aaaa_lookup and then an a_lookup
2864 * - DNS_IPV4_ONLY: tries only an a_lookup
2865 * - DNS_IPV6_ONLY: tries only an aaaa_lookup
2866 * see dns_a_resolve() for the rest of the params., examples a.s.o
2867 * WARNING: don't forget dns_hash_put(*e) when e is not needed anymore
2868 */
dns_ip_resolve(struct dns_hash_entry ** e,unsigned char * rr_no,str * name,struct ip_addr * ip,int flags)2869 inline static int dns_ip_resolve( struct dns_hash_entry** e,
2870 unsigned char* rr_no,
2871 str* name,
2872 struct ip_addr* ip,
2873 int flags)
2874 {
2875 int ret, orig_ret;
2876 str host;
2877 struct dns_hash_entry* orig;
2878
2879 ret=-E_DNS_NO_IP;
2880 if (*e==0){ /* first call */
2881 if ((flags&(DNS_IPV6_FIRST|DNS_IPV6_ONLY))){
2882 ret=dns_aaaa_resolve(e, rr_no, name, ip);
2883 if (ret>=0) return ret;
2884 }else{
2885 ret=dns_a_resolve(e, rr_no, name, ip);
2886 if (ret>=0) return ret;
2887 }
2888 if (flags&DNS_IPV6_FIRST){
2889 ret=dns_a_resolve(e, rr_no, name, ip);
2890 }else if (!(flags&(DNS_IPV6_ONLY|DNS_IPV4_ONLY))){
2891 ret=dns_aaaa_resolve(e, rr_no, name, ip);
2892 }
2893 }else if ((*e)->type==T_A){
2894 /* continue A resolving */
2895 /* retrieve host name from the hash entry (ignore name which might
2896 be null when continuing a srv lookup) */
2897 host.s=(*e)->name;
2898 host.len=(*e)->name_len;
2899 ret=dns_a_resolve(e, rr_no, &host, ip);
2900 if (ret>=0) return ret;
2901 if (!(flags&(DNS_IPV6_ONLY|DNS_IPV6_FIRST|DNS_IPV4_ONLY))){
2902 /* not found, try with AAAA */
2903 orig_ret=ret;
2904 orig=*e;
2905 *e=0;
2906 *rr_no=0;
2907 ret=dns_aaaa_resolve(e, rr_no, &host, ip);
2908 if (ret==-E_DNS_NO_IP && orig_ret==-E_DNS_EOR)
2909 ret=orig_ret;
2910 /* delay original record release until we're finished with host*/
2911 dns_hash_put(orig);
2912 }
2913 }else if ((*e)->type==T_AAAA){
2914 /* retrieve host name from the hash entry (ignore name which might
2915 be null when continuing a srv lookup) */
2916 host.s=(*e)->name;
2917 host.len=(*e)->name_len;
2918 /* continue AAAA resolving */
2919 ret=dns_aaaa_resolve(e, rr_no, &host, ip);
2920 if (ret>=0) return ret;
2921 if ((flags&DNS_IPV6_FIRST) && !(flags&DNS_IPV6_ONLY)){
2922 /* not found, try with A */
2923 orig_ret=ret;
2924 orig=*e;
2925 *e=0;
2926 *rr_no=0;
2927 ret=dns_a_resolve(e, rr_no, &host, ip);
2928 if (ret==-E_DNS_NO_IP && orig_ret==-E_DNS_EOR)
2929 ret=orig_ret;
2930 /* delay original record release until we're finished with host*/
2931 dns_hash_put(orig);
2932 }
2933 }else{
2934 LM_CRIT("invalid record type %d\n", (*e)->type);
2935 }
2936 return ret;
2937 }
2938
2939
2940
2941 /* gets the first srv record starting at rr_no
2942 * Next call will return the next record a.s.o.
2943 * (similar to dns_a_resolve but for srv, sets host, port and automatically
2944 * switches to the next record in the future)
2945 *
2946 * if DNS_SRV_LB and tried!=NULL will do random weight based selection
2947 * for choosing between SRV RRs with the same priority (as described in
2948 * RFC2782).
2949 * If tried==NULL or DNS_SRV_LB is not defined => always returns next
2950 * record in the priority order and for records with the same priority
2951 * the record with the higher weight (from the remaining ones)
2952 */
dns_srv_resolve_nxt(struct dns_hash_entry ** e,srv_flags_t * tried,unsigned char * rr_no,str * name,str * host,unsigned short * port)2953 inline static int dns_srv_resolve_nxt(struct dns_hash_entry** e,
2954 #ifdef DNS_SRV_LB
2955 srv_flags_t* tried,
2956 #endif
2957 unsigned char* rr_no,
2958 str* name, str* host, unsigned short* port)
2959 {
2960 struct dns_rr* rr;
2961 int ret;
2962 ticks_t now;
2963
2964 rr=0;
2965 ret=-E_DNS_NO_SRV;
2966 if (*e==0){
2967 if ((*e=dns_get_entry(name, T_SRV))==0)
2968 goto error;
2969 /* found it */
2970 *rr_no=0;
2971 #ifdef DNS_SRV_LB
2972 if (tried)
2973 srv_reset_tried(tried);
2974 #endif
2975 }
2976 now=get_ticks_raw();
2977 /* if the entry has already expired use the time at the end of lifetime */
2978 if (unlikely((s_ticks_t)(now-(*e)->expire)>=0)) now=(*e)->expire-1;
2979 #ifdef DNS_SRV_LB
2980 if (tried){
2981 rr=dns_srv_get_nxt_rr(*e, tried, rr_no, now);
2982 }else
2983 #endif
2984 {
2985 rr=dns_entry_get_rr(*e, rr_no, now);
2986 (*rr_no)++; /* try next record next time */
2987 }
2988 if (rr){
2989 host->s=((struct srv_rdata*)rr->rdata)->name;
2990 host->len=((struct srv_rdata*)rr->rdata)->name_len;
2991 *port=((struct srv_rdata*)rr->rdata)->port;
2992 ret=0;
2993 }else{
2994 ret=-E_DNS_EOR; /* no more records */
2995 }
2996 error:
2997 return ret;
2998 }
2999
3000
3001
3002 /* gets the first srv record starting at h->srv_no, resolve it
3003 * and get the first ip address (starting at h->ip_no)
3004 * (similar to dns_a_resolve but for srv, sets host, port)
3005 * WARNING: don't forget to init h prior to calling this function the first
3006 * time and dns_srv_handle_put(h), even if error is returned
3007 */
dns_srv_resolve_ip(struct dns_srv_handle * h,str * name,struct ip_addr * ip,unsigned short * port,int flags)3008 inline static int dns_srv_resolve_ip(struct dns_srv_handle* h,
3009 str* name, struct ip_addr* ip, unsigned short* port,
3010 int flags)
3011 {
3012 int ret;
3013 str host;
3014 unsigned short vport;
3015
3016 host.len=0;
3017 host.s=0;
3018 if(port) vport =*port;
3019 else vport = 0;
3020
3021 do{
3022 if (h->a==0){
3023 #ifdef DNS_SRV_LB
3024 if ((ret=dns_srv_resolve_nxt(&h->srv,
3025 (flags & DNS_SRV_RR_LB)?&h->srv_tried_rrs:0,
3026 &h->srv_no,
3027 name, &host, &vport))<0)
3028 goto error;
3029 #else
3030 if ((ret=dns_srv_resolve_nxt(&h->srv, &h->srv_no,
3031 name, &host, &vport))<0)
3032 goto error;
3033 #endif
3034 h->port=vport; /* store new port */
3035 if(port) *port=vport;
3036 }else{
3037 if(port) *port=h->port; /* return the stored port */
3038 }
3039 if ((ret=dns_ip_resolve(&h->a, &h->ip_no, &host, ip, flags))<0){
3040 /* couldn't find any good ip for this record, try the next one */
3041 if (h->a){
3042 dns_hash_put(h->a);
3043 h->a=0;
3044 }
3045 }else if (h->a==0){
3046 /* this was an ip, try the next srv record in the future */
3047 }
3048 }while(ret<0);
3049 error:
3050 LM_DBG("(\"%.*s\", %d, %d), ret=%d, ip=%s\n",
3051 name->len, name->s, h->srv_no, h->ip_no, ret,
3052 ip?ZSW(ip_addr2a(ip)):"");
3053 return ret;
3054 }
3055
3056
3057
3058 /* resolves a host name trying SRV lookup if *port==0 or normal A/AAAA lookup
3059 * if *port!=0.
3060 * when performing SRV lookup (*port==0) it will use proto to look for
3061 * tcp or udp hosts, otherwise proto is unused; if proto==0 => no SRV lookup
3062 * h must be initialized prior to calling this function and can be used to
3063 * get the subsequent ips
3064 * returns: <0 on error
3065 * 0 on success and it fills *ip, *port, *h
3066 */
dns_srv_sip_resolve(struct dns_srv_handle * h,str * name,struct ip_addr * ip,unsigned short * port,char * proto,int flags)3067 inline static int dns_srv_sip_resolve(struct dns_srv_handle* h, str* name,
3068 struct ip_addr* ip, unsigned short* port, char* proto,
3069 int flags)
3070 {
3071 struct dns_srv_proto srv_proto_list[PROTO_LAST];
3072 static char tmp[MAX_DNS_NAME]; /* tmp. buff. for SRV lookups */
3073 str srv_name;
3074 struct ip_addr* tmp_ip;
3075 int ret;
3076 struct hostent* he;
3077 size_t i,list_len;
3078 char origproto = 0;
3079
3080 if(proto) origproto = *proto;
3081 if (dns_hash==0){ /* not init => use normal, non-cached version */
3082 LM_WARN("called before dns cache initialization\n");
3083 h->srv=h->a=0;
3084 he=_sip_resolvehost(name, port, proto);
3085 if (he){
3086 hostent2ip_addr(ip, he, 0);
3087 return 0;
3088 }
3089 return -E_DNS_NO_SRV;
3090 }
3091 if ((h->srv==0) && (h->a==0)){ /* first call */
3092 if (proto) {
3093 if(*proto==0) { /* makes sure we have a protocol set*/
3094 *proto=PROTO_UDP; /* default */
3095 }
3096 h->port=(*proto==PROTO_TLS)?SIPS_PORT:SIP_PORT; /* just in case we
3097 don't find another */
3098 h->proto=*proto; /* store initial protocol */
3099 } else {
3100 h->proto=PROTO_UDP; /* default */
3101 }
3102 if (port){
3103 if (*port==0){
3104 /* try SRV if initial call & no port specified
3105 * (draft-ietf-sip-srv-06) */
3106 if ((name->len+SRV_MAX_PREFIX_LEN+1)>MAX_DNS_NAME){
3107 LM_WARN("domain name too long (%d), unable to perform SRV lookup\n",
3108 name->len);
3109 }else{
3110 /* check if it's an ip address */
3111 if ( ((tmp_ip=str2ip(name))!=0)
3112 || ((tmp_ip=str2ip6(name))!=0)
3113 ){
3114 /* we are lucky, this is an ip address */
3115 if (((flags&DNS_IPV4_ONLY) && (tmp_ip->af==AF_INET6))||
3116 ((flags&DNS_IPV6_ONLY) && (tmp_ip->af==AF_INET))){
3117 return -E_DNS_AF_MISMATCH;
3118 }
3119 *ip=*tmp_ip;
3120 *port=h->port;
3121 /* proto already set */
3122 return 0;
3123 }
3124
3125 /* looping on the ordered list until we found a protocol what has srv record */
3126 list_len = create_srv_pref_list(&origproto, srv_proto_list);
3127 for (i=0; i<list_len;i++) {
3128 switch (srv_proto_list[i].proto) {
3129 case PROTO_UDP:
3130 case PROTO_TCP:
3131 case PROTO_TLS:
3132 case PROTO_SCTP:
3133 create_srv_name(srv_proto_list[i].proto, name, tmp);
3134 break;
3135 default:
3136 LM_CRIT("unknown proto %d\n", (int)srv_proto_list[i].proto);
3137 return -E_DNS_CRITICAL;
3138 }
3139 srv_name.s=tmp;
3140 srv_name.len=strlen(tmp);
3141 if ((ret=dns_srv_resolve_ip(h, &srv_name, ip, port, flags))>=0)
3142 {
3143 h->proto = srv_proto_list[i].proto;
3144 if(proto) *proto = h->proto;
3145 LM_DBG("(%.*s, %d, %d), srv0, ret=%d\n",
3146 name->len, name->s, h->srv_no, h->ip_no, ret);
3147 return ret;
3148 }
3149 }
3150 }
3151 }else{ /* if (*port==0) */
3152 h->port=*port; /* store initial port */
3153 /* proto already set */
3154 }
3155 } /* if (port) */
3156 }else if (h->srv){
3157 srv_name.s=h->srv->name;
3158 srv_name.len=h->srv->name_len;
3159 /* continue srv resolving */
3160 ret=dns_srv_resolve_ip(h, &srv_name, ip, port, flags);
3161 if (proto)
3162 *proto=h->proto;
3163 LM_DBG("(%.*s, %d, %d), srv, ret=%d\n",
3164 name->len, name->s, h->srv_no, h->ip_no, ret);
3165 return ret;
3166 }
3167 if (name->len >= MAX_DNS_NAME) {
3168 LM_ERR("domain name too long\n");
3169 return -E_DNS_NAME_TOO_LONG;
3170 }
3171 ret=dns_ip_resolve(&h->a, &h->ip_no, name, ip, flags);
3172 if (port)
3173 *port=h->port;
3174 if (proto)
3175 *proto=h->proto;
3176 LM_DBG("(%.*s, %d, %d), ip, ret=%d\n",
3177 name->len, name->s, h->srv_no, h->ip_no, ret);
3178 return ret;
3179 }
3180
3181
3182
3183 #ifdef USE_NAPTR
3184
3185
mark_skip_current_naptr(struct dns_rr * naptr_head,struct dns_hash_entry * srv)3186 static void mark_skip_current_naptr(struct dns_rr* naptr_head, struct dns_hash_entry* srv)
3187 {
3188 int i;
3189 struct dns_rr* l;
3190 struct naptr_rdata* naptr;
3191
3192 if (!naptr_head || !srv) {
3193 return;
3194 }
3195
3196 for(l=naptr_head, i=0; l && (i<MAX_NAPTR_RRS); l=l->next, i++) {
3197 naptr = (struct naptr_rdata *) l->rdata;
3198 if (naptr == 0) {
3199 break;
3200 }
3201 if (naptr->skip_record) {
3202 continue;
3203 }
3204 if (srv->name_len == naptr->repl_len && !memcmp(srv->name, naptr->repl, srv->name_len)) {
3205 naptr->skip_record = 1;
3206 LM_NOTICE("Mark to skip %.*s NAPTR record due to all IPs are unreachable\n", naptr->repl_len, naptr->repl);
3207 break;
3208 }
3209 }
3210 }
3211
3212
have_more_active_naptr(struct dns_rr * naptr_head)3213 inline static int have_more_active_naptr(struct dns_rr* naptr_head)
3214 {
3215 int i, res = 0;
3216 struct dns_rr* l;
3217 struct naptr_rdata* naptr;
3218 char naptr_proto;
3219
3220 if (!naptr_head) {
3221 return res;
3222 }
3223
3224 for(l=naptr_head, i=0; l && (i<MAX_NAPTR_RRS); l=l->next, i++) {
3225 naptr = (struct naptr_rdata *) l->rdata;
3226 if (naptr == 0) {
3227 break;
3228 }
3229 if (naptr->skip_record) {
3230 continue;
3231 } else if ((naptr_proto = naptr_get_sip_proto(naptr)) <= 0) {
3232 continue;
3233 } else if ((naptr_proto_supported(naptr_proto))) {
3234 res = 1;
3235 break;
3236 }
3237 }
3238 return res;
3239 }
3240
3241 /* resolves a host name trying:
3242 * - NAPTR lookup if the address is not an ip and proto!=0, port!=0
3243 * *port==0 and *proto=0 and if flags allow NAPTR lookups
3244 * -SRV lookup if port!=0 and *port==0
3245 * - normal A/AAAA lookup if *port!=0, or port==0
3246 * when performing SRV lookup (*port==0) it will use proto to look for
3247 * tcp or udp hosts, otherwise proto is unused; if proto==0 => no SRV lookup
3248 * h must be initialized prior to calling this function and can be used to
3249 * get the subsequent ips
3250 * returns: <0 on error
3251 * 0 on success and it fills *ip, *port, dns_sip_resolve_h
3252 * WARNING: when finished, dns_sip_resolve_put(h) must be called!
3253 */
dns_naptr_sip_resolve(struct dns_srv_handle * h,str * name,struct ip_addr * ip,unsigned short * port,char * proto,int flags)3254 inline static int dns_naptr_sip_resolve(struct dns_srv_handle* h, str* name,
3255 struct ip_addr* ip, unsigned short* port, char* proto,
3256 int flags)
3257 {
3258 struct hostent* he;
3259 struct ip_addr* tmp_ip;
3260 naptr_bmp_t tried_bmp;
3261 struct dns_hash_entry* e;
3262 char n_proto, origproto;
3263 str srv_name;
3264 int ret;
3265 int res;
3266 int try_lookup_naptr = 0;
3267
3268 ret=-E_DNS_NO_NAPTR;
3269 if(proto) origproto=*proto;
3270 else origproto = PROTO_NONE;
3271 if (dns_hash==0){ /* not init => use normal, non-cached version */
3272 LM_WARN("called before dns cache initialization\n");
3273 h->srv=h->a=0;
3274 he=_sip_resolvehost(name, port, proto);
3275 if (he){
3276 hostent2ip_addr(ip, he, 0);
3277 return 0;
3278 }
3279 return -E_DNS_NO_NAPTR;
3280 }
3281 if (((h->srv==0) && (h->a==0)) && /* first call */
3282 proto && port && (*proto==0) && (*port==0)){
3283 *proto=PROTO_UDP; /* just in case we don't find another */
3284
3285 /* check if it's an ip address */
3286 if ( ((tmp_ip=str2ip(name))!=0)
3287 || ((tmp_ip=str2ip6(name))!=0)
3288 ){
3289 /* we are lucky, this is an ip address */
3290 if (((flags&DNS_IPV4_ONLY) && (tmp_ip->af==AF_INET6))||
3291 ((flags&DNS_IPV6_ONLY) && (tmp_ip->af==AF_INET))){
3292 return -E_DNS_AF_MISMATCH;
3293 }
3294 *ip=*tmp_ip;
3295 h->port=SIP_PORT;
3296 h->proto=*proto;
3297 *port=h->port;
3298 return 0;
3299 }
3300 try_lookup_naptr = 1;
3301 }
3302 /* check if it's an ip address, dns_srv_sip_resolve will return the right failure */
3303 if (str2ip(name) || str2ip6(name))
3304 goto naptr_not_found;
3305 /* do naptr lookup */
3306 if ((e=dns_get_entry(name, T_NAPTR))==0)
3307 goto naptr_not_found;
3308
3309 if (!try_lookup_naptr) {
3310 if(proto) *proto=origproto;
3311 res = dns_srv_sip_resolve(h, name, ip, port, proto, flags);
3312 if (res) {
3313 mark_skip_current_naptr(e->rr_lst, h->srv);
3314 if (have_more_active_naptr(e->rr_lst)) {
3315 // No more avaliable IP for current NAPTR record, let's try next one
3316 try_lookup_naptr = 1;
3317 }
3318 } else {
3319 return res;
3320 }
3321 }
3322
3323 if (try_lookup_naptr) {
3324 naptr_iterate_init(&tried_bmp);
3325 while(dns_naptr_sip_iterate(e->rr_lst, &tried_bmp,
3326 &srv_name, &n_proto)){
3327 dns_srv_handle_init(h); /* make sure h does not contain garbage
3328 from previous dns_srv_sip_resolve calls */
3329 if ((ret=dns_srv_resolve_ip(h, &srv_name, ip, port, flags))>=0){
3330 LM_DBG("(%.*s, %d, %d), srv0, ret=%d\n",
3331 name->len, name->s, h->srv_no, h->ip_no, ret);
3332 dns_hash_put(e);
3333 if(proto) *proto=n_proto;
3334 h->proto=n_proto;
3335 return ret;
3336 }
3337 }
3338 /* no acceptable naptr record found, fallback to srv */
3339 dns_hash_put(e);
3340 dns_srv_handle_init(h); /* make sure h does not contain garbage
3341 from previous dns_srv_sip_resolve calls */
3342 }
3343 naptr_not_found:
3344 if(proto) *proto=origproto;
3345 return dns_srv_sip_resolve(h, name, ip, port, proto, flags);
3346 }
3347 #endif /* USE_NAPTR */
3348
3349
3350
3351 /* resolves a host name trying:
3352 * - NAPTR lookup if the address is not an ip and proto!=0, port!=0
3353 * *port==0 and *proto=0 and if flags allow NAPTR lookups
3354 * -SRV lookup if port!=0 and *port==0
3355 * - normal A/AAAA lookup if *port!=0, or port==0
3356 * when performing SRV lookup (*port==0) it will use proto to look for
3357 * tcp or udp hosts, otherwise proto is unused; if proto==0 => no SRV lookup
3358 * h must be initialized prior to calling this function and can be used to
3359 * get the subsequent ips
3360 * returns: <0 on error
3361 * 0 on success and it fills *ip, *port, dns_sip_resolve_h
3362 */
dns_sip_resolve(struct dns_srv_handle * h,str * name,struct ip_addr * ip,unsigned short * port,char * proto,int flags)3363 int dns_sip_resolve(struct dns_srv_handle* h, str* name,
3364 struct ip_addr* ip, unsigned short* port, char* proto,
3365 int flags)
3366 {
3367 #ifdef USE_NAPTR
3368 if (flags&DNS_TRY_NAPTR)
3369 return dns_naptr_sip_resolve(h, name, ip, port, proto, flags);
3370 #endif
3371 return dns_srv_sip_resolve(h, name, ip, port, proto, flags);
3372 }
3373
3374 /* performs an a lookup and fills ip with the first good ip address
3375 * returns 0 on success, <0 on error (see the error codes)
3376 */
dns_a_get_ip(str * name,struct ip_addr * ip)3377 inline static int dns_a_get_ip(str* name, struct ip_addr* ip)
3378 {
3379 struct dns_hash_entry* e;
3380 int ret;
3381 unsigned char rr_no;
3382
3383 e=0;
3384 rr_no=0;
3385 ret=dns_a_resolve(&e, &rr_no, name, ip);
3386 if (e) dns_hash_put(e);
3387 return ret;
3388 }
3389
3390
dns_aaaa_get_ip(str * name,struct ip_addr * ip)3391 inline static int dns_aaaa_get_ip(str* name, struct ip_addr* ip)
3392 {
3393 struct dns_hash_entry* e;
3394 int ret;
3395 unsigned char rr_no;
3396
3397 e=0;
3398 rr_no=0;
3399 ret=dns_aaaa_resolve(&e, &rr_no, name, ip);
3400 if (e) dns_hash_put(e);
3401 return ret;
3402 }
3403
3404
3405
3406 /* performs an a or aaaa dns lookup, returns <0 on error (see the
3407 * dns error codes) and 0 on success
3408 * flags: - none set: tries first an a_lookup and if it fails an aaaa_lookup
3409 * - DNS_IPV6_FIRST: tries first an aaaa_lookup and then an a_lookup
3410 * - DNS_IPV4_ONLY: tries only an a_lookup
3411 * - DNS_IPV6_ONLY: tries only an aaaa_lookup
3412 */
dns_get_ip(str * name,struct ip_addr * ip,int flags)3413 int dns_get_ip(str* name, struct ip_addr* ip, int flags)
3414 {
3415 int ret;
3416 struct dns_hash_entry* e;
3417 unsigned char rr_no;
3418
3419 e=0;
3420 rr_no=0;
3421 ret=dns_ip_resolve(&e, &rr_no, name, ip, flags);
3422 if (e)
3423 dns_hash_put(e);
3424 return ret;
3425 }
3426
3427
3428
3429 /* fast "inline" version, gets the first good ip:port */
dns_srv_get_ip(str * name,struct ip_addr * ip,unsigned short * port,int flags)3430 int dns_srv_get_ip(str* name, struct ip_addr* ip, unsigned short* port,
3431 int flags)
3432 {
3433 int ret;
3434 struct dns_srv_handle h;
3435
3436 dns_srv_handle_init(&h);
3437 ret=dns_srv_resolve_ip(&h, name, ip, port, flags);
3438 dns_srv_handle_put(&h);
3439 return ret;
3440 }
3441
3442
3443 #ifdef DNS_WATCHDOG_SUPPORT
3444 /* sets the state of the DNS servers:
3445 * 1: at least one server is up
3446 * 0: all the servers are down
3447 */
dns_set_server_state(int state)3448 void dns_set_server_state(int state)
3449 {
3450 atomic_set(dns_servers_up, state);
3451 }
3452
3453 /* returns the state of the DNS servers */
dns_get_server_state(void)3454 int dns_get_server_state(void)
3455 {
3456 return atomic_get(dns_servers_up);
3457 }
3458 #endif /* DNS_WATCHDOG_SUPPORT */
3459
3460 /* rpc functions */
dns_cache_mem_info(rpc_t * rpc,void * ctx)3461 void dns_cache_mem_info(rpc_t* rpc, void* ctx)
3462 {
3463 if (!cfg_get(core, core_cfg, use_dns_cache)){
3464 rpc->fault(ctx, 500, "dns cache support disabled (see use_dns_cache)");
3465 return;
3466 }
3467 rpc->add(ctx, "dd", *dns_cache_mem_used, cfg_get(core, core_cfg, dns_cache_max_mem));
3468 }
3469
3470
dns_cache_debug(rpc_t * rpc,void * ctx)3471 void dns_cache_debug(rpc_t* rpc, void* ctx)
3472 {
3473 int h;
3474 struct dns_hash_entry* e;
3475 ticks_t now;
3476
3477 if (!cfg_get(core, core_cfg, use_dns_cache)){
3478 rpc->fault(ctx, 500, "dns cache support disabled (see use_dns_cache)");
3479 return;
3480 }
3481 now=get_ticks_raw();
3482 LOCK_DNS_HASH();
3483 for (h=0; h<DNS_HASH_SIZE; h++){
3484 clist_foreach(&dns_hash[h], e, next){
3485 rpc->add(ctx, "sdddddd",
3486 e->name, e->type, e->total_size, e->refcnt.val,
3487 (s_ticks_t)(e->expire-now)<0?-1:
3488 TICKS_TO_S(e->expire-now),
3489 TICKS_TO_S(now-e->last_used),
3490 e->ent_flags);
3491 }
3492 }
3493 UNLOCK_DNS_HASH();
3494 }
3495
3496
3497 #ifdef USE_DNS_CACHE_STATS
stat_sum(int ivar,int breset)3498 static unsigned long stat_sum(int ivar, int breset)
3499 {
3500 unsigned long isum=0;
3501 int i1=0;
3502
3503 for (; i1 < get_max_procs(); i1++)
3504 switch (ivar) {
3505 case 0:
3506 isum+=dns_cache_stats[i1].dns_req_cnt;
3507 if (breset)
3508 dns_cache_stats[i1].dns_req_cnt=0;
3509 break;
3510 case 1:
3511 isum+=dns_cache_stats[i1].dc_hits_cnt;
3512 if (breset)
3513 dns_cache_stats[i1].dc_hits_cnt=0;
3514 break;
3515 case 2:
3516 isum+=dns_cache_stats[i1].dc_neg_hits_cnt;
3517 if (breset)
3518 dns_cache_stats[i1].dc_neg_hits_cnt=0;
3519 break;
3520 case 3:
3521 isum+=dns_cache_stats[i1].dc_lru_cnt;
3522 if (breset)
3523 dns_cache_stats[i1].dc_lru_cnt=0;
3524 break;
3525 }
3526
3527 return isum;
3528 }
3529
3530
dns_cache_stats_get(rpc_t * rpc,void * c)3531 void dns_cache_stats_get(rpc_t* rpc, void* c)
3532 {
3533 char *name=NULL;
3534 void *handle;
3535 int found=0,i=0;
3536 int reset=0;
3537 char* dns_cache_stats_names[] = {
3538 "dns_req_cnt",
3539 "dc_hits_cnt",
3540 "dc_neg_hits_cnt",
3541 "dc_lru_cnt",
3542 NULL
3543 };
3544
3545
3546 if (!cfg_get(core, core_cfg, use_dns_cache)) {
3547 rpc->fault(c, 500, "dns cache support disabled");
3548 return;
3549 }
3550 if (rpc->scan(c, "s", &name) < 0)
3551 return;
3552 if (rpc->scan(c, "d", &reset) < 0)
3553 return;
3554 if (!strcasecmp(name, DNS_CACHE_ALL_STATS)) {
3555 /* dump all the dns cache stat values */
3556 rpc->add(c, "{", &handle);
3557 for (i=0; dns_cache_stats_names[i]; i++)
3558 rpc->struct_add(handle, "d",
3559 dns_cache_stats_names[i],
3560 stat_sum(i, reset));
3561
3562 found=1;
3563 } else {
3564 for (i=0; dns_cache_stats_names[i]; i++)
3565 if (!strcasecmp(dns_cache_stats_names[i], name)) {
3566 rpc->add(c, "{", &handle);
3567 rpc->struct_add(handle, "d",
3568 dns_cache_stats_names[i],
3569 stat_sum(i, reset));
3570 found=1;
3571 break;
3572 }
3573 }
3574 if(!found)
3575 rpc->fault(c, 500, "unknown dns cache stat parameter");
3576
3577 return;
3578 }
3579 #endif /* USE_DNS_CACHE_STATS */
3580
3581 /* rpc functions */
dns_cache_debug_all(rpc_t * rpc,void * ctx)3582 void dns_cache_debug_all(rpc_t* rpc, void* ctx)
3583 {
3584 int h;
3585 struct dns_hash_entry* e;
3586 struct dns_rr* rr;
3587 struct ip_addr ip;
3588 int i;
3589 ticks_t now;
3590
3591 if (!cfg_get(core, core_cfg, use_dns_cache)){
3592 rpc->fault(ctx, 500, "dns cache support disabled (see use_dns_cache)");
3593 return;
3594 }
3595 now=get_ticks_raw();
3596 LOCK_DNS_HASH();
3597 for (h=0; h<DNS_HASH_SIZE; h++){
3598 clist_foreach(&dns_hash[h], e, next){
3599 for (i=0, rr=e->rr_lst; rr; i++, rr=rr->next){
3600 rpc->add(ctx, "sddddddd",
3601 e->name, (int)e->type, i, (int)e->total_size,
3602 (int)e->refcnt.val,
3603 (int)(s_ticks_t)(e->expire-now)<0?-1:
3604 TICKS_TO_S(e->expire-now),
3605 (int)TICKS_TO_S(now-e->last_used),
3606 (int)e->ent_flags);
3607 switch(e->type){
3608 case T_A:
3609 case T_AAAA:
3610 if (dns_rr2ip(e->type, rr, &ip)==0){
3611 rpc->add(ctx, "ss", "ip", ip_addr2a(&ip) );
3612 }else{
3613 rpc->add(ctx, "ss", "ip", "<error: bad rr>");
3614 }
3615 break;
3616 case T_SRV:
3617 rpc->add(ctx, "ss", "srv",
3618 ((struct srv_rdata*)(rr->rdata))->name);
3619 break;
3620 case T_NAPTR:
3621 rpc->add(ctx, "ss", "naptr ",
3622 ((struct naptr_rdata*)(rr->rdata))->flags);
3623 break;
3624 case T_CNAME:
3625 rpc->add(ctx, "ss", "cname",
3626 ((struct cname_rdata*)(rr->rdata))->name);
3627 break;
3628 case T_TXT:
3629 rpc->add(ctx, "ss", "txt",
3630 ((struct txt_rdata*)(rr->rdata))->cstr_no?
3631 ((struct txt_rdata*)(rr->rdata))->txt[0].cstr:
3632 "");
3633 break;
3634 case T_EBL:
3635 rpc->add(ctx, "ss", "ebl",
3636 ((struct ebl_rdata*)(rr->rdata))->apex);
3637 break;
3638 case T_PTR:
3639 rpc->add(ctx, "ss", "ptr",
3640 ((struct ptr_rdata*)(rr->rdata))->ptrdname);
3641 break;
3642 default:
3643 rpc->add(ctx, "ss", "unknown", "?");
3644 }
3645 rpc->add(ctx, "d",
3646 (int)(s_ticks_t)(rr->expire-now)<0?-1:
3647 TICKS_TO_S(rr->expire-now));
3648 }
3649 }
3650 }
3651 UNLOCK_DNS_HASH();
3652 }
3653
3654
print_type(unsigned short type)3655 static char *print_type(unsigned short type)
3656 {
3657 switch (type) {
3658 case T_A:
3659 return "A";
3660 case T_AAAA:
3661 return "AAAA";
3662 case T_SRV:
3663 return "SRV";
3664 case T_NAPTR:
3665 return "NAPTR";
3666 case T_CNAME:
3667 return "CNAME";
3668 case T_TXT:
3669 return "TXT";
3670 case T_EBL:
3671 return "EBL";
3672 case T_PTR:
3673 return "PTR";
3674 default:
3675 return "unknown";
3676 }
3677 }
3678
3679
3680 /** convert string type to dns integer T_*.
3681 * used for rpc type translation.
3682 * @return T_* on success, -1 on error.
3683 */
dns_get_type(str * s)3684 static int dns_get_type(str* s)
3685 {
3686 char *t;
3687 int len;
3688
3689 t=s->s;
3690 len=s->len;
3691 /* skip over a T_ or t_ prefix */
3692 if ((len>2) && (t[0]=='T' || t[0]=='t') && (t[1]=='_')){
3693 t+=2;
3694 len-=2;
3695 }
3696 switch(len){
3697 case 1:
3698 if (t[0]=='A' || t[0]=='a')
3699 return T_A;
3700 break;
3701 case 4:
3702 if (strncasecmp(t, "AAAA", len)==0)
3703 return T_AAAA;
3704 break;
3705 case 3:
3706 if (strncasecmp(t, "SRV", len)==0)
3707 return T_SRV;
3708 else if (strncasecmp(t, "TXT", len)==0)
3709 return T_TXT;
3710 else if (strncasecmp(t, "EBL", len)==0)
3711 return T_EBL;
3712 else if (strncasecmp(t, "PTR", len)==0)
3713 return T_PTR;
3714 break;
3715 case 5:
3716 if (strncasecmp(t, "NAPTR", len)==0)
3717 return T_NAPTR;
3718 else if (strncasecmp(t, "CNAME", len)==0)
3719 return T_CNAME;
3720 break;
3721 }
3722 return -1;
3723 }
3724
3725
3726 /** rpc-prints a dns cache entry.
3727 */
dns_cache_print_entry(rpc_t * rpc,void * ctx,struct dns_hash_entry * e)3728 int dns_cache_print_entry(rpc_t* rpc, void* ctx, struct dns_hash_entry* e)
3729 {
3730 int expires;
3731 struct dns_rr* rr;
3732 struct ip_addr ip;
3733 ticks_t now;
3734 str s;
3735 int i;
3736 int n;
3737 void *th;
3738 void *rh;
3739 void *sh;
3740 void *ih;
3741 void *ah;
3742
3743 /* add entry node */
3744 if(rpc->add(ctx, "{", &th) < 0) {
3745 rpc->fault(ctx, 500, "Internal error root reply");
3746 return -1;
3747 }
3748
3749 now=get_ticks_raw();
3750 expires = (s_ticks_t)(e->expire-now)<0?-1: TICKS_TO_S(e->expire-now);
3751 if(rpc->struct_add(th, "ssddsdds",
3752 "name", e->name,
3753 "type", print_type(e->type),
3754 "size_bytes", e->total_size,
3755 "reference_counter", e->refcnt.val,
3756 "permanent", (e->ent_flags & DNS_FLAG_PERMANENT) ? "yes" : "no",
3757 "expires", (e->ent_flags & DNS_FLAG_PERMANENT)?0:expires, /* seconds */
3758 "last_used", TICKS_TO_S(now-e->last_used), /* seconds */
3759 "negative_entry", (e->ent_flags & DNS_FLAG_BAD_NAME) ? "yes" : "no")
3760 <0) {
3761 rpc->fault(ctx, 500, "Internal error building structure");
3762 return -1;
3763 }
3764 n = 0;
3765 for (rr=e->rr_lst; rr; rr=rr->next) {
3766 if(n==0) {
3767 if(rpc->struct_add(th, "[", "records", &rh)<0) {
3768 rpc->fault(ctx, 500, "Internal error building records");
3769 return -1;
3770 }
3771 }
3772 if(rpc->array_add(rh, "{", &sh) < 0) {
3773 rpc->fault(ctx, 500, "Internal error adding record");
3774 return -1;
3775 }
3776 if(rpc->struct_add(sh, "d", "rr_idx", n)<0) {
3777 rpc->fault(ctx, 500, "Internal error adding rr_idx");
3778 return -1;
3779 }
3780 n++;
3781 switch(e->type) {
3782 case T_A:
3783 case T_AAAA:
3784 if (dns_rr2ip(e->type, rr, &ip)==0){
3785 if(rpc->struct_add(sh, "s", "rr_ip", ip_addr2a(&ip))<0) {
3786 rpc->fault(ctx, 500, "Internal error adding rr_ip");
3787 return -1;
3788 }
3789 }else{
3790 if(rpc->struct_add(sh, "s", "rr_ip", "error-bad-rr")<0) {
3791 rpc->fault(ctx, 500, "Internal error adding rr_ip");
3792 return -1;
3793 }
3794 }
3795 break;
3796 case T_SRV:
3797 if(rpc->struct_add(sh, "sddd",
3798 "rr_name", ((struct srv_rdata*)(rr->rdata))->name,
3799 "rr_port", ((struct srv_rdata*)(rr->rdata))->port,
3800 "rr_priority", ((struct srv_rdata*)(rr->rdata))->priority,
3801 "rr_weight", ((struct srv_rdata*)(rr->rdata))->weight)<0) {
3802 rpc->fault(ctx, 500, "Internal error adding rr srv fields");
3803 return -1;
3804 }
3805 break;
3806 case T_NAPTR:
3807 if(rpc->struct_add(sh, "dd",
3808 "rr_order", ((struct naptr_rdata*)(rr->rdata))->order,
3809 "rr_preference", ((struct naptr_rdata*)(rr->rdata))->pref)
3810 <0) {
3811 rpc->fault(ctx, 500, "Internal error adding naptr order");
3812 return -1;
3813 }
3814 s.s = ((struct naptr_rdata*)(rr->rdata))->flags;
3815 s.len = ((struct naptr_rdata*)(rr->rdata))->flags_len;
3816 if(rpc->struct_add(sh, "S", "rr_flags", &s)<0) {
3817 rpc->fault(ctx, 500, "Internal error adding naptre rr_flags");
3818 return -1;
3819 }
3820 s.s=((struct naptr_rdata*)(rr->rdata))->services;
3821 s.len=((struct naptr_rdata*)(rr->rdata))->services_len;
3822 if(rpc->struct_add(sh, "S", "rr_service", &s)<0) {
3823 rpc->fault(ctx, 500, "Internal error adding naptre rr_service");
3824 return -1;
3825 }
3826 s.s = ((struct naptr_rdata*)(rr->rdata))->regexp;
3827 s.len = ((struct naptr_rdata*)(rr->rdata))->regexp_len;
3828 if(rpc->struct_add(sh, "S", "rr_regexp", &s)<0) {
3829 rpc->fault(ctx, 500, "Internal error adding naptre rr_regexp");
3830 return -1;
3831 }
3832 s.s = ((struct naptr_rdata*)(rr->rdata))->repl;
3833 s.len = ((struct naptr_rdata*)(rr->rdata))->repl_len;
3834 if(rpc->struct_add(sh, "S", "rr_regexp", &s)<0) {
3835 rpc->fault(ctx, 500, "Internal error adding naptre rr_replacement");
3836 return -1;
3837 }
3838 break;
3839 case T_CNAME:
3840 if(rpc->struct_add(sh, "s", "rr_name",
3841 ((struct cname_rdata*)(rr->rdata))->name)<0) {
3842 rpc->fault(ctx, 500, "Internal error adding cname rr_name");
3843 return -1;
3844 }
3845 break;
3846 case T_TXT:
3847 if(rpc->struct_add(sh, "[", "txt", &ih)<0) {
3848 rpc->fault(ctx, 500, "Internal error txt record");
3849 return -1;
3850 }
3851 for (i=0; i<((struct txt_rdata*)(rr->rdata))->cstr_no;
3852 i++){
3853 if(rpc->array_add(ih, "{", &ah) < 0) {
3854 rpc->fault(ctx, 500, "Internal error adding txt record");
3855 return -1;
3856 }
3857 if(rpc->struct_add(ah, "ds", "idx", i,
3858 "rr_txt",
3859 ((struct txt_rdata*)(rr->rdata))->txt[i].cstr)<0) {
3860 rpc->fault(ctx, 500, "Internal error adding rr_txt");
3861 return -1;
3862 }
3863 }
3864 break;
3865 case T_EBL:
3866 if(rpc->struct_add(sh, "dss",
3867 "rr_position", ((struct ebl_rdata*)(rr->rdata))->position,
3868 "rr_separator", ((struct ebl_rdata*)(rr->rdata))->separator,
3869 "rr_apex", ((struct ebl_rdata*)(rr->rdata))->apex)<0) {
3870 rpc->fault(ctx, 500, "Internal error adding ebl fields");
3871 return -1;
3872 }
3873 break;
3874 case T_PTR:
3875 if(rpc->struct_add(sh, "s", "rr_name",
3876 ((struct ptr_rdata*)(rr->rdata))->ptrdname)<0) {
3877 rpc->fault(ctx, 500, "Internal error adding ptr rr_name");
3878 return -1;
3879 }
3880 break;
3881 default:
3882 if(rpc->struct_add(sh, "s", "rr_type", "unknown" )<0) {
3883 rpc->fault(ctx, 500, "Internal error adding rr unknown");
3884 return -1;
3885 }
3886 }
3887 if ((e->ent_flags & DNS_FLAG_PERMANENT) == 0) {
3888 if(rpc->struct_add(sh, "sd", "rr_permanent", "no",
3889 "rr_expires",
3890 (s_ticks_t)(rr->expire-now)<0?-1 :
3891 TICKS_TO_S(rr->expire-now))<0) {
3892 rpc->fault(ctx, 500, "Internal error adding rr_expires");
3893 return -1;
3894 }
3895 } else {
3896 if(rpc->struct_add(sh, "sd", "rr_permanent", "yes",
3897 "rr_expires", 0)<0) {
3898 rpc->fault(ctx, 500, "Internal error adding rr_expires");
3899 return -1;
3900 }
3901 }
3902 }
3903 return 0;
3904 }
3905
3906
3907
3908 /* dumps the content of the cache in a human-readable format */
dns_cache_view(rpc_t * rpc,void * ctx)3909 void dns_cache_view(rpc_t* rpc, void* ctx)
3910 {
3911 int h;
3912 struct dns_hash_entry* e;
3913 ticks_t now;
3914
3915 if (!cfg_get(core, core_cfg, use_dns_cache)){
3916 rpc->fault(ctx, 500, "dns cache support disabled (see use_dns_cache)");
3917 return;
3918 }
3919 now=get_ticks_raw();
3920 LOCK_DNS_HASH();
3921 for (h=0; h<DNS_HASH_SIZE; h++){
3922 clist_foreach(&dns_hash[h], e, next){
3923 if (((e->ent_flags & DNS_FLAG_PERMANENT) == 0)
3924 && TICKS_LT(e->expire, now)
3925 ) {
3926 continue;
3927 }
3928 if(dns_cache_print_entry(rpc, ctx, e)<0) {
3929 LM_DBG("failed to print dns entry\n");
3930 return;
3931 }
3932 }
3933 }
3934 UNLOCK_DNS_HASH();
3935 }
3936
3937
3938 /* Delete all the entries from the cache.
3939 * If del_permanent is 0, then only the
3940 * non-permanent entries are deleted.
3941 */
dns_cache_flush(int del_permanent)3942 void dns_cache_flush(int del_permanent)
3943 {
3944 int h;
3945 struct dns_hash_entry* e;
3946 struct dns_hash_entry* tmp;
3947
3948 LM_DBG("removing elements from the cache\n");
3949 LOCK_DNS_HASH();
3950 for (h=0; h<DNS_HASH_SIZE; h++){
3951 clist_foreach_safe(&dns_hash[h], e, tmp, next){
3952 if (del_permanent || ((e->ent_flags & DNS_FLAG_PERMANENT) == 0))
3953 _dns_hash_remove(e);
3954 }
3955 }
3956 UNLOCK_DNS_HASH();
3957 }
3958
3959 /* deletes all the non-permanent entries from the cache */
dns_cache_delete_all(rpc_t * rpc,void * ctx)3960 void dns_cache_delete_all(rpc_t* rpc, void* ctx)
3961 {
3962 void *th;
3963
3964 if (!cfg_get(core, core_cfg, use_dns_cache)){
3965 rpc->fault(ctx, 500, "dns cache support disabled (see use_dns_cache)");
3966 return;
3967 }
3968 dns_cache_flush(0);
3969
3970 if(rpc->add(ctx, "{", &th) < 0) {
3971 rpc->fault(ctx, 500, "Internal error - root structure");
3972 return;
3973 }
3974 if(rpc->struct_add(th, "s", "status", "ok") < 0) {
3975 rpc->fault(ctx, 500, "Internal error - status");
3976 return;
3977 }
3978 }
3979
3980 /* deletes all the entries from the cache,
3981 * even the permanent ones */
dns_cache_delete_all_force(rpc_t * rpc,void * ctx)3982 void dns_cache_delete_all_force(rpc_t* rpc, void* ctx)
3983 {
3984 void *th;
3985
3986 if (!cfg_get(core, core_cfg, use_dns_cache)){
3987 rpc->fault(ctx, 500, "dns cache support disabled (see use_dns_cache)");
3988 return;
3989 }
3990 dns_cache_flush(1);
3991
3992 if(rpc->add(ctx, "{", &th) < 0) {
3993 rpc->fault(ctx, 500, "Internal error - root structure");
3994 return;
3995 }
3996 if(rpc->struct_add(th, "s", "status", "ok") < 0) {
3997 rpc->fault(ctx, 500, "Internal error - status");
3998 return;
3999 }
4000 }
4001
4002 /* clones an entry and extends its memory area to hold a new rr.
4003 * if rdata_size>0 the new dns_rr struct is initialized, but the rdata is
4004 * only filled with 0.
4005 */
dns_cache_clone_entry(struct dns_hash_entry * e,int rdata_size,int ttl,struct dns_rr ** _new_rr)4006 static struct dns_hash_entry *dns_cache_clone_entry(struct dns_hash_entry *e,
4007 int rdata_size,
4008 int ttl,
4009 struct dns_rr **_new_rr)
4010 {
4011 struct dns_hash_entry *new;
4012 struct dns_rr *rr, *last_rr, *new_rr;
4013 int size, rounded_size, rr_size;
4014 ticks_t now;
4015 int i;
4016
4017 now=get_ticks_raw();
4018 size = e->total_size;
4019 if (rdata_size) {
4020 /* we have to extend the entry */
4021 rounded_size = ROUND_POINTER(size); /* size may not have been
4022 rounded previously */
4023 switch (e->type) {
4024 case T_A:
4025 case T_AAAA:
4026 case T_CNAME:
4027 rr_size = sizeof(struct dns_rr);
4028 break;
4029 case T_SRV:
4030 rr_size = ROUND_SHORT(sizeof(struct dns_rr));
4031 break;
4032 case T_NAPTR:
4033 rr_size = ROUND_POINTER(sizeof(struct dns_rr));
4034 break;
4035 case T_TXT:
4036 rr_size = ROUND_POINTER(sizeof(struct dns_rr));
4037 break;
4038 case T_EBL:
4039 rr_size = ROUND_POINTER(sizeof(struct dns_rr));
4040 break;
4041 case T_PTR:
4042 rr_size = sizeof(struct dns_rr);
4043 break;
4044 default:
4045 LM_ERR("type %d not supported\n", e->type);
4046 return NULL;
4047 }
4048 } else {
4049 rounded_size = size; /* no need to round the size, we just clone
4050 the entry without extending it */
4051 rr_size = 0;
4052 }
4053
4054 new=shm_malloc(rounded_size+rr_size+rdata_size);
4055 if (!new) {
4056 SHM_MEM_ERROR;
4057 return NULL;
4058 }
4059 memset(new, 0, rounded_size+rr_size+rdata_size);
4060 /* clone the entry */
4061 memcpy(new, e, size);
4062 /* fix the values and pointers */
4063 new->next = new->prev = NULL;
4064 new->last_used_lst.next = new->last_used_lst.prev = NULL;
4065 new->rr_lst = (struct dns_rr*)translate_pointer((char*)new, (char*)e,
4066 (char*)new->rr_lst);
4067 atomic_set(&new->refcnt, 0);
4068 new->last_used = now;
4069 /* expire and total_size are fixed later if needed */
4070 /* fix the pointers inside the rr structures */
4071 last_rr = NULL;
4072 for (rr=new->rr_lst; rr; rr=rr->next) {
4073 rr->rdata = (void*)translate_pointer((char*)new, (char*)e,
4074 (char*)rr->rdata);
4075 if (rr->next)
4076 rr->next = (struct dns_rr*)translate_pointer((char*)new, (char*)e,
4077 (char*)rr->next);
4078 else
4079 last_rr = rr;
4080
4081 switch(e->type){
4082 case T_NAPTR:
4083 if(rr->rdata==NULL) {
4084 LM_WARN("null rdata filed for type: %u\n", e->type);
4085 break;
4086 }
4087 /* there are pointers inside the NAPTR rdata stucture */
4088 ((struct naptr_rdata*)rr->rdata)->flags =
4089 translate_pointer((char*)new, (char*)e,
4090 ((struct naptr_rdata*)rr->rdata)->flags);
4091
4092 ((struct naptr_rdata*)rr->rdata)->services =
4093 translate_pointer((char*)new, (char*)e,
4094 ((struct naptr_rdata*)rr->rdata)->services);
4095
4096 ((struct naptr_rdata*)rr->rdata)->regexp =
4097 translate_pointer((char*)new, (char*)e,
4098 ((struct naptr_rdata*)rr->rdata)->regexp);
4099
4100 ((struct naptr_rdata*)rr->rdata)->repl =
4101 translate_pointer((char*)new, (char*)e,
4102 ((struct naptr_rdata*)rr->rdata)->repl);
4103 break;
4104 case T_TXT:
4105 if(rr->rdata==NULL) {
4106 LM_WARN("null rdata filed for type: %u\n", e->type);
4107 break;
4108 }
4109 /* there are pointers inside the TXT structure */
4110 for (i=0; i<((struct txt_rdata*)rr->rdata)->cstr_no; i++){
4111 ((struct txt_rdata*)rr->rdata)->txt[i].cstr=
4112 translate_pointer((char*) new, (char*) e,
4113 ((struct txt_rdata*)rr->rdata)->txt[i].cstr);
4114 }
4115 break;
4116 case T_EBL:
4117 if(rr->rdata==NULL) {
4118 LM_WARN("null rdata filed for type: %u\n", e->type);
4119 break;
4120 }
4121 /* there are pointers inside the EBL structure */
4122 ((struct ebl_rdata*)rr->rdata)->separator =
4123 translate_pointer((char*)new, (char*)e,
4124 ((struct ebl_rdata*)rr->rdata)->separator);
4125 ((struct ebl_rdata*)rr->rdata)->apex =
4126 translate_pointer((char*)new, (char*)e,
4127 ((struct ebl_rdata*)rr->rdata)->apex);
4128 break;
4129 }
4130 }
4131
4132
4133 if (rdata_size) {
4134 /* set the pointer to the new rr structure */
4135 new_rr = (void*)((char*)new + rounded_size);
4136 new_rr->rdata = (void*)((char*)new_rr+rr_size);
4137 new_rr->expire = now + S_TO_TICKS(ttl);
4138 /* link the rr to the previous one */
4139 if(last_rr) {
4140 last_rr->next = new_rr;
4141 }
4142
4143 /* fix the total_size and expires values */
4144 new->total_size=rounded_size+rr_size+rdata_size;
4145 new->expire = MAX(new->expire, new_rr->expire);
4146
4147
4148 if (_new_rr)
4149 *_new_rr = new_rr;
4150 } else {
4151 if (_new_rr)
4152 *_new_rr = NULL;
4153 }
4154
4155 return new;
4156 }
4157
4158
4159 /* Adds a new record to the cache.
4160 * If there is an existing record with the same name and value
4161 * (ip address in case of A/AAAA record, name in case of SRV record)
4162 * only the remaining fields are updated.
4163 *
4164 * Note that permanent records cannot be overwritten unless
4165 * the new record is also permanent. A permanent record
4166 * completely replaces a non-permanent one.
4167 *
4168 * Currently only A, AAAA, and SRV records are supported.
4169 */
dns_cache_add_record(unsigned short type,str * name,int ttl,str * value,int priority,int weight,int port,int flags)4170 int dns_cache_add_record(unsigned short type,
4171 str *name,
4172 int ttl,
4173 str *value,
4174 int priority,
4175 int weight,
4176 int port,
4177 int flags)
4178 {
4179 struct dns_hash_entry *old=NULL, *new=NULL;
4180 struct dns_rr *rr;
4181 str rr_name;
4182 struct ip_addr *ip_addr;
4183 ticks_t expire;
4184 int err, h;
4185 int size;
4186 struct dns_rr *new_rr, **rr_p, **rr_iter;
4187 struct srv_rdata *srv_rd;
4188
4189 /* eliminate gcc warnings */
4190 ip_addr = 0;
4191 size = 0;
4192 rr_name.s = NULL;
4193 rr_name.len = 0;
4194
4195 if (!cfg_get(core, core_cfg, use_dns_cache)){
4196 LM_ERR("dns cache support disabled (see use_dns_cache)\n");
4197 return -1;
4198 }
4199
4200 if ((type != T_A) && (type != T_AAAA) && (type != T_SRV)) {
4201 LM_ERR("rr type %d is not implemented\n", type);
4202 return -1;
4203 }
4204
4205 if ((flags & DNS_FLAG_BAD_NAME) == 0) {
4206 /* fix-up the values */
4207 switch(type) {
4208 case T_A:
4209 ip_addr = str2ip(value);
4210 if (!ip_addr) {
4211 LM_ERR("Malformed ip address: %.*s\n",
4212 value->len, value->s);
4213 return -1;
4214 }
4215 break;
4216 case T_AAAA:
4217 ip_addr = str2ip6(value);
4218 if (!ip_addr) {
4219 LM_ERR("Malformed ip address: %.*s\n",
4220 value->len, value->s);
4221 return -1;
4222 }
4223 break;
4224 case T_SRV:
4225 rr_name = *value;
4226 break;
4227 }
4228 }
4229
4230 /* check whether there is a matching entry in the cache */
4231 old = dns_hash_get(name, type, &h, &err);
4232 if (old && old->type!=type) {
4233 /* probably we found a CNAME instead of the specified type,
4234 it is not needed */
4235 dns_hash_put(old);
4236 old=NULL;
4237 }
4238
4239 if (old
4240 && (old->ent_flags & DNS_FLAG_PERMANENT)
4241 && ((flags & DNS_FLAG_PERMANENT) == 0)
4242 ) {
4243 LM_ERR("A non-permanent record cannot overwrite "
4244 "a permanent entry\n");
4245 goto error;
4246 }
4247 /* prepare the entry */
4248 if (flags & DNS_FLAG_BAD_NAME) {
4249 /* negative entry */
4250 new = dns_cache_mk_bad_entry(name, type, ttl, flags);
4251 if (!new) {
4252 LM_ERR("Failed to create a negative "
4253 "DNS cache entry\n");
4254 goto error;
4255 }
4256 } else {
4257 if (!old
4258 || (old->ent_flags & DNS_FLAG_BAD_NAME)
4259 || (((old->ent_flags & DNS_FLAG_PERMANENT) == 0)
4260 && (flags & DNS_FLAG_PERMANENT))
4261 ) {
4262 /* There was no matching entry in the hash table,
4263 * the entry is a negative record with inefficient space,
4264 * or a permanent entry overwrites a non-permanent one.
4265 * Let us create a new one.
4266 */
4267 switch(type) {
4268 case T_A:
4269 case T_AAAA:
4270 new = dns_cache_mk_ip_entry(name, ip_addr);
4271 if (!new) {
4272 LM_ERR("Failed to create an A/AAAA record\n");
4273 goto error;
4274 }
4275 /* fix the expiration time, dns_cache_mk_ip_entry() sets it
4276 * to now-1 */
4277 expire = get_ticks_raw() + S_TO_TICKS(ttl);
4278 new->expire = expire;
4279 new->rr_lst->expire = expire;
4280 break;
4281 case T_SRV:
4282 new = dns_cache_mk_srv_entry(name, priority, weight, port,
4283 &rr_name, ttl);
4284 if (!new) {
4285 LM_ERR("Failed to create an SRV record\n");
4286 goto error;
4287 }
4288 }
4289 new->ent_flags = flags;
4290 } else {
4291 /* we must modify the entry, so better to clone it, modify the new
4292 * one, and replace the old with the new entry in the hash table,
4293 * because the entry might be in use (even if the dns hash is
4294 * locked). The old entry will be removed from the hash and
4295 * automatically destroyed when its refcnt will be 0*/
4296
4297 /* check whether there is an rr with the same value */
4298 for (rr=old->rr_lst; rr; rr=rr->next)
4299 if ((((type == T_A) || (type == T_AAAA)) &&
4300 (memcmp(ip_addr->u.addr, ((struct a_rdata*)rr->rdata)->ip,
4301 ip_addr->len)==0))
4302 || ((type == T_SRV) &&
4303 (((struct srv_rdata*)rr->rdata)->name_len == rr_name.len)&&
4304 (memcmp(rr_name.s, ((struct srv_rdata*)rr->rdata)->name,
4305 rr_name.len)==0)))
4306 break;
4307
4308 if (rr) {
4309 /* the rr was found in the list */
4310 new = dns_cache_clone_entry(old, 0, 0, 0);
4311 if (!new) {
4312 LM_ERR("Failed to clone an existing "
4313 "DNS cache entry\n");
4314 goto error;
4315 }
4316 /* let the rr point to the new structure */
4317 rr = (struct dns_rr*)translate_pointer((char*)new, (char*)old,
4318 (char*)rr);
4319 new_rr = rr;
4320
4321 if (type == T_SRV) {
4322 /* fix the priority, weight, and port */
4323 ((struct srv_rdata*)rr->rdata)->priority = priority;
4324 ((struct srv_rdata*)rr->rdata)->weight = weight;
4325 ((struct srv_rdata*)rr->rdata)->port = port;
4326 }
4327
4328 /* fix the expire value */
4329 rr->expire = get_ticks_raw() + S_TO_TICKS(ttl);
4330 new->expire = 0;
4331 for (rr=new->rr_lst; rr; rr=rr->next)
4332 new->expire = MAX(new->expire, rr->expire);
4333 } else {
4334 /* there was no matching rr, extend the structure with a new
4335 * one */
4336 switch(type) {
4337 case T_A:
4338 size = sizeof(struct a_rdata);
4339 break;
4340 case T_AAAA:
4341 size = sizeof(struct aaaa_rdata);
4342 break;
4343 case T_SRV:
4344 size = sizeof(struct srv_rdata)-1 +
4345 rr_name.len+1;
4346 break;
4347 }
4348 new = dns_cache_clone_entry(old, size, ttl, &rr);
4349 if (!new) {
4350 LM_ERR("Failed to clone an existing "
4351 "DNS cache entry\n");
4352 goto error;
4353 }
4354 new_rr = rr;
4355
4356 switch(type) {
4357 case T_A:
4358 case T_AAAA:
4359 memcpy(rr->rdata, ip_addr->u.addr, ip_addr->len);
4360 break;
4361 case T_SRV:
4362 ((struct srv_rdata*)rr->rdata)->priority = priority;
4363 ((struct srv_rdata*)rr->rdata)->weight = weight;
4364 ((struct srv_rdata*)rr->rdata)->port = port;
4365 ((struct srv_rdata*)rr->rdata)->name_len = rr_name.len;
4366 memcpy(((struct srv_rdata*)rr->rdata)->name, rr_name.s,
4367 rr_name.len);
4368 }
4369 /* maximum expire value has been already fixed by
4370 * dns_cache_clone_entry() */
4371 }
4372
4373 if (type == T_SRV) {
4374 /* SRV records must be ordered by their priority and weight.
4375 * With modifying an exising rr, or adding new rr to the DNS entry,
4376 * the ordered list might got broken which needs to be fixed.
4377 */
4378 rr_p = NULL;
4379 for ( rr_iter = &new->rr_lst;
4380 *rr_iter;
4381 rr_iter = &((*rr_iter)->next)
4382 ) {
4383 if (*rr_iter == new_rr) {
4384 rr_p = rr_iter;
4385 continue;
4386 }
4387 srv_rd = (struct srv_rdata*)(*rr_iter)->rdata;
4388 if ((priority < srv_rd->priority) ||
4389 ((priority == srv_rd->priority) && (weight > srv_rd->weight))
4390 )
4391 break; /* insert here */
4392 }
4393
4394 if (!rr_p) {
4395 for ( rr_p = rr_iter;
4396 *rr_p && (*rr_p != new_rr);
4397 rr_p = &((*rr_p)->next)
4398 );
4399 }
4400 if (!rr_p) {
4401 LM_ERR("Failed to correct the ordered list of SRV resource records\n");
4402 goto error;
4403 }
4404
4405 if (*rr_iter != new_rr->next) {
4406 /* unlink rr from the list */
4407 *rr_p = (*rr_p)?(*rr_p)->next:NULL;
4408 /* link it before *rr_iter */
4409 new_rr->next = *rr_iter;
4410 *rr_iter = new_rr;
4411 }
4412 }
4413 }
4414 }
4415
4416 LOCK_DNS_HASH();
4417 if (dns_cache_add_unsafe(new)) {
4418 LM_ERR("Failed to add the entry to the cache\n");
4419 UNLOCK_DNS_HASH();
4420 goto error;
4421 } else {
4422 /* remove the old entry from the list */
4423 if (old)
4424 _dns_hash_remove(old);
4425 }
4426 UNLOCK_DNS_HASH();
4427
4428 if (old)
4429 dns_hash_put(old);
4430 return 0;
4431
4432 error:
4433 /* leave the old entry in the list, and free the new one */
4434 if (old)
4435 dns_hash_put(old);
4436 if (new)
4437 dns_destroy_entry(new);
4438 return -1;
4439 }
4440
4441
4442 /* deletes a record from the cache */
dns_cache_delete_record(rpc_t * rpc,void * ctx,unsigned short type)4443 static void dns_cache_delete_record(rpc_t* rpc, void* ctx, unsigned short type)
4444 {
4445 struct dns_hash_entry *e;
4446 str name;
4447 int err, h, found=0, permanent=0;
4448
4449 if (!cfg_get(core, core_cfg, use_dns_cache)){
4450 rpc->fault(ctx, 500, "dns cache support disabled (see use_dns_cache)");
4451 return;
4452 }
4453
4454 if (rpc->scan(ctx, "S", &name) < 1)
4455 return;
4456
4457 LOCK_DNS_HASH();
4458
4459 e=_dns_hash_find(&name, type, &h, &err);
4460 if (e && (e->type==type)) {
4461 if ((e->ent_flags & DNS_FLAG_PERMANENT) == 0)
4462 _dns_hash_remove(e);
4463 else
4464 permanent = 1;
4465 found = 1;
4466 }
4467
4468 UNLOCK_DNS_HASH();
4469
4470 if (permanent)
4471 rpc->fault(ctx, 400, "Permanent entries cannot be deleted");
4472 else if (!found)
4473 rpc->fault(ctx, 400, "Not found");
4474 }
4475
4476 /* Delete a single record from the cache,
4477 * i.e. the record with the same name and value
4478 * (ip address in case of A/AAAA record, name in case of SRV record).
4479 *
4480 * Currently only A, AAAA, and SRV records are supported.
4481 */
dns_cache_delete_single_record(unsigned short type,str * name,str * value,int flags)4482 int dns_cache_delete_single_record(unsigned short type,
4483 str *name,
4484 str *value,
4485 int flags)
4486 {
4487 struct dns_hash_entry *old=NULL, *new=NULL;
4488 struct dns_rr *rr, **next_p;
4489 str rr_name;
4490 struct ip_addr *ip_addr;
4491 int err, h;
4492
4493 /* eliminate gcc warnings */
4494 rr_name.s = NULL;
4495 rr_name.len = 0;
4496 ip_addr = 0;
4497
4498 if (!cfg_get(core, core_cfg, use_dns_cache)){
4499 LM_ERR("dns cache support disabled (see use_dns_cache)\n");
4500 return -1;
4501 }
4502
4503 if ((type != T_A) && (type != T_AAAA) && (type != T_SRV)) {
4504 LM_ERR("rr type %d is not implemented\n", type);
4505 return -1;
4506 }
4507
4508 if ((flags & DNS_FLAG_BAD_NAME) == 0) {
4509 /* fix-up the values */
4510 switch(type) {
4511 case T_A:
4512 ip_addr = str2ip(value);
4513 if (!ip_addr) {
4514 LM_ERR("Malformed ip address: %.*s\n",
4515 value->len, value->s);
4516 return -1;
4517 }
4518 break;
4519 case T_AAAA:
4520 ip_addr = str2ip6(value);
4521 if (!ip_addr) {
4522 LM_ERR("Malformed ip address: %.*s\n",
4523 value->len, value->s);
4524 return -1;
4525 }
4526 break;
4527 case T_SRV:
4528 rr_name = *value;
4529 break;
4530 }
4531 }
4532
4533 /* check whether there is a matching entry in the cache */
4534 if ((old = dns_hash_get(name, type, &h, &err)) == NULL)
4535 goto not_found;
4536
4537 if ((old->type != type) /* may be CNAME */
4538 || (old->ent_flags != flags)
4539 )
4540 goto not_found;
4541
4542 if (flags & DNS_FLAG_BAD_NAME) /* negative record, there is no value */
4543 goto delete;
4544
4545 /* check whether there is an rr with the same value */
4546 for (rr=old->rr_lst, next_p=&old->rr_lst;
4547 rr;
4548 next_p=&rr->next, rr=rr->next
4549 )
4550 if ((((type == T_A) || (type == T_AAAA)) &&
4551 (memcmp(ip_addr->u.addr, ((struct a_rdata*)rr->rdata)->ip,
4552 ip_addr->len)==0))
4553 || ((type == T_SRV) &&
4554 (((struct srv_rdata*)rr->rdata)->name_len == rr_name.len) &&
4555 (memcmp(rr_name.s, ((struct srv_rdata*)rr->rdata)->name,
4556 rr_name.len)==0)))
4557 break;
4558
4559 if (!rr)
4560 goto not_found;
4561
4562 if ((rr == old->rr_lst) && (rr->next == NULL)) {
4563 /* There is a single rr value, hence the whole
4564 * hash entry can be deleted */
4565 goto delete;
4566 } else {
4567 /* we must modify the entry, so better to clone it, modify the new
4568 * one, and replace the old with the new entry in the hash table,
4569 * because the entry might be in use (even if the dns hash is
4570 * locked). The old entry will be removed from the hash and
4571 * automatically destroyed when its refcnt will be 0*/
4572 new = dns_cache_clone_entry(old, 0, 0, 0);
4573 if (!new) {
4574 LM_ERR("Failed to clone an existing DNS cache entry\n");
4575 dns_hash_put(old);
4576 return -1;
4577 }
4578 /* let rr and next_p point to the new structure */
4579 rr = (struct dns_rr*)translate_pointer((char*)new,
4580 (char*)old,
4581 (char*)rr);
4582 next_p = (struct dns_rr**)translate_pointer((char*)new,
4583 (char*)old,
4584 (char*)next_p);
4585 /* unlink rr from the list. The memory will be freed
4586 * when the whole record is freed */
4587 *next_p = rr->next;
4588 }
4589
4590 delete:
4591 LOCK_DNS_HASH();
4592 if (new) {
4593 /* delete the old entry only if the new one can be added */
4594 if (dns_cache_add_unsafe(new)) {
4595 LM_ERR("Failed to add the entry to the cache\n");
4596 UNLOCK_DNS_HASH();
4597 if (old)
4598 dns_hash_put(old);
4599 return -1;
4600 } else {
4601 /* remove the old entry from the list */
4602 if (old)
4603 _dns_hash_remove(old);
4604 }
4605 } else if (old) {
4606 _dns_hash_remove(old);
4607 }
4608 UNLOCK_DNS_HASH();
4609
4610 if (old)
4611 dns_hash_put(old);
4612 return 0;
4613
4614 not_found:
4615 LM_ERR("No matching record found\n");
4616 if (old)
4617 dns_hash_put(old);
4618 return -1;
4619 }
4620
4621 /* performs a dns lookup over rpc */
dns_cache_rpc_lookup(rpc_t * rpc,void * ctx)4622 void dns_cache_rpc_lookup(rpc_t* rpc, void* ctx)
4623 {
4624 struct dns_hash_entry *e;
4625 str name;
4626 str type;
4627 int t;
4628
4629 if (!cfg_get(core, core_cfg, use_dns_cache)){
4630 rpc->fault(ctx, 500, "dns cache support disabled (see use_dns_cache)");
4631 return;
4632 }
4633
4634 if (rpc->scan(ctx, "SS", &type, &name) < 1)
4635 return;
4636 t=dns_get_type(&type);
4637 if (t<0){
4638 rpc->fault(ctx, 400, "Invalid type");
4639 return;
4640 }
4641 e=dns_get_entry(&name, t);
4642 if (e==0){
4643 rpc->fault(ctx, 400, "Not found");
4644 return;
4645 }
4646 if(dns_cache_print_entry(rpc, ctx, e)<0) {
4647 LM_DBG("failed to print the dns entry\n");
4648 }
4649 dns_hash_put(e);
4650 }
4651
4652
4653
4654 /* wrapper functions for adding and deleting records */
dns_cache_add_a(rpc_t * rpc,void * ctx)4655 void dns_cache_add_a(rpc_t* rpc, void* ctx)
4656 {
4657 str name;
4658 int ttl;
4659 str ip;
4660 int flags;
4661
4662 if (rpc->scan(ctx, "SdSd", &name, &ttl, &ip, &flags) < 4)
4663 return;
4664
4665 if (dns_cache_add_record(T_A,
4666 &name,
4667 ttl,
4668 &ip,
4669 0 /* priority */,
4670 0 /* weight */,
4671 0 /* port */,
4672 flags)
4673 )
4674 rpc->fault(ctx, 400, "Failed to add the entry to the cache");
4675 }
4676
4677
dns_cache_add_aaaa(rpc_t * rpc,void * ctx)4678 void dns_cache_add_aaaa(rpc_t* rpc, void* ctx)
4679 {
4680 str name;
4681 int ttl;
4682 str ip;
4683 int flags;
4684
4685 if (rpc->scan(ctx, "SdSd", &name, &ttl, &ip, &flags) < 4)
4686 return;
4687
4688 if (dns_cache_add_record(T_AAAA,
4689 &name,
4690 ttl,
4691 &ip,
4692 0 /* priority */,
4693 0 /* weight */,
4694 0 /* port */,
4695 flags)
4696 )
4697 rpc->fault(ctx, 400, "Failed to add the entry to the cache");
4698 }
4699
dns_cache_add_srv(rpc_t * rpc,void * ctx)4700 void dns_cache_add_srv(rpc_t* rpc, void* ctx)
4701 {
4702 str name;
4703 int ttl, priority, weight, port;
4704 str rr_name;
4705 int flags;
4706
4707 if (rpc->scan(ctx, "SddddSd", &name, &ttl, &priority, &weight, &port,
4708 &rr_name, &flags) < 7
4709 )
4710 return;
4711
4712 if (dns_cache_add_record(T_SRV,
4713 &name,
4714 ttl,
4715 &rr_name,
4716 priority,
4717 weight,
4718 port,
4719 flags)
4720 )
4721 rpc->fault(ctx, 400, "Failed to add the entry to the cache");
4722 }
4723
4724
4725
4726
dns_cache_delete_a(rpc_t * rpc,void * ctx)4727 void dns_cache_delete_a(rpc_t* rpc, void* ctx)
4728 {
4729 dns_cache_delete_record(rpc, ctx, T_A);
4730 }
4731
4732
dns_cache_delete_aaaa(rpc_t * rpc,void * ctx)4733 void dns_cache_delete_aaaa(rpc_t* rpc, void* ctx)
4734 {
4735 dns_cache_delete_record(rpc, ctx, T_AAAA);
4736 }
4737
4738
dns_cache_delete_srv(rpc_t * rpc,void * ctx)4739 void dns_cache_delete_srv(rpc_t* rpc, void* ctx)
4740 {
4741 dns_cache_delete_record(rpc, ctx, T_SRV);
4742 }
4743
4744
dns_cache_delete_naptr(rpc_t * rpc,void * ctx)4745 void dns_cache_delete_naptr(rpc_t* rpc, void* ctx)
4746 {
4747 dns_cache_delete_record(rpc, ctx, T_NAPTR);
4748 }
4749
4750
dns_cache_delete_cname(rpc_t * rpc,void * ctx)4751 void dns_cache_delete_cname(rpc_t* rpc, void* ctx)
4752 {
4753 dns_cache_delete_record(rpc, ctx, T_CNAME);
4754 }
4755
4756
dns_cache_delete_txt(rpc_t * rpc,void * ctx)4757 void dns_cache_delete_txt(rpc_t* rpc, void* ctx)
4758 {
4759 dns_cache_delete_record(rpc, ctx, T_TXT);
4760 }
4761
dns_cache_delete_ebl(rpc_t * rpc,void * ctx)4762 void dns_cache_delete_ebl(rpc_t* rpc, void* ctx)
4763 {
4764 dns_cache_delete_record(rpc, ctx, T_EBL);
4765 }
4766
dns_cache_delete_ptr(rpc_t * rpc,void * ctx)4767 void dns_cache_delete_ptr(rpc_t* rpc, void* ctx)
4768 {
4769 dns_cache_delete_record(rpc, ctx, T_PTR);
4770 }
4771
4772
4773
4774 #ifdef DNS_WATCHDOG_SUPPORT
4775 /* sets the DNS server states */
dns_set_server_state_rpc(rpc_t * rpc,void * ctx)4776 void dns_set_server_state_rpc(rpc_t* rpc, void* ctx)
4777 {
4778 int state;
4779
4780 if (!cfg_get(core, core_cfg, use_dns_cache)){
4781 rpc->fault(ctx, 500, "dns cache support disabled (see use_dns_cache)");
4782 return;
4783 }
4784 if (rpc->scan(ctx, "d", &state) < 1)
4785 return;
4786 dns_set_server_state(state);
4787 }
4788
4789 /* prints the DNS server state */
dns_get_server_state_rpc(rpc_t * rpc,void * ctx)4790 void dns_get_server_state_rpc(rpc_t* rpc, void* ctx)
4791 {
4792 if (!cfg_get(core, core_cfg, use_dns_cache)){
4793 rpc->fault(ctx, 500, "dns cache support disabled (see use_dns_cache)");
4794 return;
4795 }
4796 rpc->add(ctx, "d", dns_get_server_state());
4797 }
4798 #endif /* DNS_WATCHDOG_SUPPORT */
4799
4800 #endif
4801