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