Browse code

core, lib, modules: restructured source code tree

- new folder src/ to hold the source code for main project applications
- main.c is in src/
- all core files are subfolder are in src/core/
- modules are in src/modules/
- libs are in src/lib/
- application Makefiles are in src/
- application binary is built in src/ (src/kamailio)

Daniel-Constantin Mierla authored on 07/12/2016 11:03:51
Showing 1 changed files
1 1
deleted file mode 100644
... ...
@@ -1,4731 +0,0 @@
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
-#define DNS_CACHE_DEBUG /* extra sanity checks and debugging */
61
-
62
-
63
-#ifndef MAX
64
-	#define MAX(a,b) ( ((a)>(b))?(a):(b))
65
-#endif
66
-
67
-#define MAX_DNS_RECORDS 255  /* maximum dns records number  received in a
68
-							   dns answer*/
69
-
70
-#define DNS_HASH_SIZE	1024 /* must be <= 65535 */
71
-#define DEFAULT_DNS_TIMER_INTERVAL 120  /* 2 min. */
72
-#define DNS_HE_MAX_ADDR 10  /* maxium addresses returne in a hostent struct */
73
-#define MAX_CNAME_CHAIN  10
74
-#define SPACE_FORMAT "    " /* format of view output */
75
-#define DNS_SRV_ZERO_W_CHANCE	1000 /* one in a 1000*weight_sum chance for
76
-										selecting a 0-weight record */
77
-
78
-int dns_cache_init=1;	/* if 0, the DNS cache is not initialized at startup */
79
-static gen_lock_t* dns_hash_lock=0;
80
-static volatile unsigned int *dns_cache_mem_used=0; /* current mem. use */
81
-unsigned int dns_timer_interval=DEFAULT_DNS_TIMER_INTERVAL; /* in s */
82
-int dns_flags=0; /* default flags used for the  dns_*resolvehost
83
-                    (compatibility wrappers) */
84
-
85
-#ifdef USE_DNS_CACHE_STATS
86
-struct t_dns_cache_stats* dns_cache_stats=0;
87
-#endif
88
-
89
-#define LOCK_DNS_HASH()		lock_get(dns_hash_lock)
90
-#define UNLOCK_DNS_HASH()	lock_release(dns_hash_lock)
91
-
92
-#define FIX_TTL(t) \
93
-	(((t)<cfg_get(core, core_cfg, dns_cache_min_ttl))? \
94
-		cfg_get(core, core_cfg, dns_cache_min_ttl): \
95
-		(((t)>cfg_get(core, core_cfg, dns_cache_max_ttl))? \
96
-			cfg_get(core, core_cfg, dns_cache_max_ttl): \
97
-			(t)))
98
-
99
-
100
-struct dns_hash_head{
101
-	struct dns_hash_entry* next;
102
-	struct dns_hash_entry* prev;
103
-};
104
-
105
-#ifdef DNS_LU_LST
106
-struct dns_lu_lst* dns_last_used_lst=0;
107
-#endif
108
-
109
-static struct dns_hash_head* dns_hash=0;
110
-
111
-
112
-static struct timer_ln* dns_timer_h=0;
113
-
114
-#ifdef DNS_WATCHDOG_SUPPORT
115
-static atomic_t *dns_servers_up = NULL;
116
-#endif
117
-
118
-
119
-
120
-static const char* dns_str_errors[]={
121
-	"no error",
122
-	"no more records", /* not an error, but and end condition */
123
-	"unknown error",
124
-	"internal error",
125
-	"bad SRV entry",
126
-	"unresolvable SRV request",
127
-	"bad A or AAAA entry",
128
-	"unresolvable A or AAAA request",
129
-	"invalid ip in A or AAAA record",
130
-	"blacklisted ip",
131
-	"name too long ", /* try again with a shorter name */
132
-	"ip AF mismatch", /* address family mismatch */
133
-	"unresolvable NAPTR request",
134
-	"bug - critical error"
135
-};
136
-
137
-
138
-
139
-/* param: err (negative error number) */
140
-const char* dns_strerror(int err)
141
-{
142
-	err=-err;
143
-	if ((err>=0) && (err<sizeof(dns_str_errors)/sizeof(char*)))
144
-		return dns_str_errors[err];
145
-	return "bug -- bad error number";
146
-}
147
-
148
-
149
-
150
-/* "internal" only, don't use unless you really know waht you're doing */
151
-inline static void dns_destroy_entry(struct dns_hash_entry* e)
152
-{
153
-#ifdef DNS_CACHE_DEBUG
154
-	memset(e, 0, e->total_size);
155
-#endif
156
-	shm_free(e); /* nice having it in one block isn't it? :-) */
157
-}
158
-
159
-
160
-/* "internal" only, same as above, asumes shm_lock() held (tm optimization) */
161
-inline static void dns_destroy_entry_shm_unsafe(struct dns_hash_entry* e)
162
-{
163
-#ifdef DNS_CACHE_DEBUG
164
-	memset(e, 0, e->total_size);
165
-#endif
166
-	shm_free_unsafe(e); /* nice having it in one block isn't it? :-) */
167
-}
168
-
169
-
170
-
171
-/* dec. the internal refcnt and if 0 deletes the entry */
172
-void dns_hash_put(struct dns_hash_entry* e)
173
-{
174
-	if(e && atomic_dec_and_test(&e->refcnt)){
175
-		/* atomic_sub_long(dns_cache_total_used, e->total_size); */
176
-		dns_destroy_entry(e);
177
-	}
178
-}
179
-
180
-
181
-
182
-/* same as above but uses dns_destroy_unsafe (assumes shm_lock held -- tm
183
- *  optimization) */
184
-void dns_hash_put_shm_unsafe(struct dns_hash_entry* e)
185
-{
186
-	if(e && atomic_dec_and_test(&e->refcnt)){
187
-		/* atomic_sub_long(dns_cache_total_used, e->total_size); */
188
-		dns_destroy_entry_shm_unsafe(e);
189
-	}
190
-}
191
-
192
-
193
-inline static int dns_cache_clean(unsigned int no, int expired_only);
194
-inline static int dns_cache_free_mem(unsigned int target, int expired_only);
195
-
196
-static ticks_t dns_timer(ticks_t ticks, struct timer_ln* tl, void* data)
197
-{
198
-#ifdef DNS_WATCHDOG_SUPPORT
199
-	/* do not clean the hash table if the servers are down */
200
-	if (atomic_get(dns_servers_up) == 0)
201
-		return (ticks_t)(-1);
202
-#endif
203
-	if (*dns_cache_mem_used>12*(cfg_get(core, core_cfg, dns_cache_max_mem)/16)){ /* ~ 75% used */
204
-		dns_cache_free_mem(cfg_get(core, core_cfg, dns_cache_max_mem)/2, 1);
205
-	}else{
206
-		dns_cache_clean(-1, 1); /* all the table, only expired entries */
207
-		/* TODO: better strategy? */
208
-	}
209
-	return (ticks_t)(-1);
210
-}
211
-
212
-
213
-
214
-void destroy_dns_cache()
215
-{
216
-	if (dns_timer_h){
217
-		timer_del(dns_timer_h);
218
-		timer_free(dns_timer_h);
219
-		dns_timer_h=0;
220
-	}
221
-#ifdef DNS_WATCHDOG_SUPPORT
222
-	if (dns_servers_up){
223
-		shm_free(dns_servers_up);
224
-		dns_servers_up=0;
225
-	}
226
-#endif
227
-	if (dns_hash_lock){
228
-		lock_destroy(dns_hash_lock);
229
-		lock_dealloc(dns_hash_lock);
230
-		dns_hash_lock=0;
231
-	}
232
-	if (dns_hash){
233
-		shm_free(dns_hash);
234
-		dns_hash=0;
235
-	}
236
-#ifdef DNS_LU_LST
237
-	if (dns_last_used_lst){
238
-		shm_free(dns_last_used_lst);
239
-		dns_last_used_lst=0;
240
-	}
241
-#endif
242
-#ifdef USE_DNS_CACHE_STATS
243
-	if (dns_cache_stats)
244
-		shm_free(dns_cache_stats);
245
-#endif
246
-	if (dns_cache_mem_used){
247
-		shm_free((void*)dns_cache_mem_used);
248
-		dns_cache_mem_used=0;
249
-	}
250
-}
251
-
252
-/* set the value of dns_flags */
253
-void fix_dns_flags(str *gname, str *name)
254
-{
255
-	/* restore the original value of dns_cache_flags first
256
-	 * (DNS_IPV4_ONLY may have been set only because dns_try_ipv6
257
-	 * was disabled, and the flag must be cleared when
258
-	 * dns_try_ipv6 is enabled) (Miklos)
259
-	 */
260
-	dns_flags = cfg_get(core, core_cfg, dns_cache_flags) & 7;
261
-
262
-	if (cfg_get(core, core_cfg, dns_try_ipv6)==0){
263
-		dns_flags|=DNS_IPV4_ONLY;
264
-	}
265
-	if (dns_flags & DNS_IPV4_ONLY){
266
-		dns_flags&=~(DNS_IPV6_ONLY|DNS_IPV6_FIRST);
267
-	}
268
-	if (cfg_get(core, core_cfg, dns_srv_lb)){
269
-#ifdef DNS_SRV_LB
270
-		dns_flags|=DNS_SRV_RR_LB;
271
-#else
272
-		LM_WARN("SRV loadbalaning is set, but"
273
-					" support for it is not compiled -- ignoring\n");
274
-#endif
275
-	}
276
-	if (cfg_get(core, core_cfg, dns_try_naptr)) {
277
-#ifndef USE_NAPTR
278
-	LM_WARN("NAPTR support is enabled, but"
279
-				" support for it is not compiled -- ignoring\n");
280
-#endif
281
-		dns_flags|=DNS_TRY_NAPTR;
282
-	}
283
-}
284
-
285
-/* fixup function for use_dns_failover
286
- * verifies that use_dns_cache is set to 1
287
- */
288
-int use_dns_failover_fixup(void *handle, str *gname, str *name, void **val)
289
-{
290
-	if ((int)(long)(*val) && !cfg_get(core, handle, use_dns_cache)) {
291
-		LM_ERR("DNS cache is turned off, failover cannot be enabled. "
292
-			"(set use_dns_cache to 1)\n");
293
-		return -1;
294
-	}
295
-	return 0;
296
-}
297
-
298
-/* fixup function for use_dns_cache
299
- * verifies that dns_cache_init is set to 1
300
- */
301
-int use_dns_cache_fixup(void *handle, str *gname, str *name, void **val)
302
-{
303
-	if ((int)(long)(*val) && !dns_cache_init) {
304
-		LM_ERR("DNS cache is turned off by dns_cache_init=0, "
305
-			"it cannot be enabled runtime.\n");
306
-		return -1;
307
-	}
308
-	if (((int)(long)(*val)==0) && cfg_get(core, handle, use_dns_failover)) {
309
-		LM_ERR("DNS failover depends on use_dns_cache, set use_dns_failover "
310
-			"to 0 before disabling the DNS cache\n");
311
-		return -1;
312
-	}
313
-	return 0;
314
-}
315
-
316
-/* KByte to Byte conversion */
317
-int dns_cache_max_mem_fixup(void *handle, str *gname, str *name, void **val)
318
-{
319
-	unsigned int    u;
320
-
321
-	u = ((unsigned int)(long)(*val))<<10;
322
-	(*val) = (void *)(long)u;
323
-	return 0;
324
-}
325
-
326
-int init_dns_cache()
327
-{
328
-	int r;
329
-	int ret;
330
-
331
-	if (dns_cache_init==0) {
332
-		/* the DNS cache is turned off */
333
-		default_core_cfg.use_dns_cache=0;
334
-		default_core_cfg.use_dns_failover=0;
335
-		return 0;
336
-	}
337
-
338
-	ret=0;
339
-	/* sanity check */
340
-	if (E_DNS_CRITICAL>=sizeof(dns_str_errors)/sizeof(char*)){
341
-		LM_CRIT("bad dns error table\n");
342
-		ret=E_BUG;
343
-		goto error;
344
-	}
345
-	dns_cache_mem_used=shm_malloc(sizeof(*dns_cache_mem_used));
346
-	if (dns_cache_mem_used==0){
347
-		ret=E_OUT_OF_MEM;
348
-		goto error;
349
-	}
350
-#ifdef DNS_LU_LST
351
-	dns_last_used_lst=shm_malloc(sizeof(*dns_last_used_lst));
352
-	if (dns_last_used_lst==0){
353
-		ret=E_OUT_OF_MEM;
354
-		goto error;
355
-	}
356
-	clist_init(dns_last_used_lst, next, prev);
357
-#endif
358
-	dns_hash=shm_malloc(sizeof(struct dns_hash_head)*DNS_HASH_SIZE);
359
-	if (dns_hash==0){
360
-		ret=E_OUT_OF_MEM;
361
-		goto error;
362
-	}
363
-	for (r=0; r<DNS_HASH_SIZE; r++)
364
-		clist_init(&dns_hash[r], next, prev);
365
-
366
-	dns_hash_lock=lock_alloc();
367
-	if (dns_hash_lock==0){
368
-		ret=E_OUT_OF_MEM;
369
-		goto error;
370
-	}
371
-	if (lock_init(dns_hash_lock)==0){
372
-		lock_dealloc(dns_hash_lock);
373
-		dns_hash_lock=0;
374
-		ret=-1;
375
-		goto error;
376
-	}
377
-
378
-#ifdef DNS_WATCHDOG_SUPPORT
379
-	dns_servers_up=shm_malloc(sizeof(atomic_t));
380
-	if (dns_servers_up==0){
381
-		ret=E_OUT_OF_MEM;
382
-		goto error;
383
-	}
384
-	atomic_set(dns_servers_up, 1);
385
-#endif
386
-
387
-	/* fix options */
388
-	default_core_cfg.dns_cache_max_mem<<=10; /* Kb */ /* TODO: test with 0 */
389
-	if (default_core_cfg.use_dns_cache==0)
390
-		default_core_cfg.use_dns_failover=0; /* cannot work w/o dns_cache support */
391
-	/* fix flags */
392
-	fix_dns_flags(NULL, NULL);
393
-
394
-	dns_timer_h=timer_alloc();
395
-	if (dns_timer_h==0){
396
-		ret=E_OUT_OF_MEM;
397
-		goto error;
398
-	}
399
-	if (dns_timer_interval){
400
-		timer_init(dns_timer_h, dns_timer, 0, 0); /* "slow" timer */
401
-		if (timer_add(dns_timer_h, S_TO_TICKS(dns_timer_interval))<0){
402
-			LM_CRIT("failed to add the timer\n");
403
-			timer_free(dns_timer_h);
404
-			dns_timer_h=0;
405
-			goto error;
406
-		}
407
-	}
408
-
409
-	return 0;
410
-error:
411
-	destroy_dns_cache();
412
-	return ret;
413
-}
414
-
415
-#ifdef USE_DNS_CACHE_STATS
416
-int init_dns_cache_stats(int iproc_num)
417
-{
418
-	/* do not initialize the stats array if the DNS cache will not be used */
419
-	if (dns_cache_init==0) return 0;
420
-
421
-	/* if it is already initialized */
422
-	if (dns_cache_stats)
423
-		shm_free(dns_cache_stats);
424
-
425
-	dns_cache_stats=shm_malloc(sizeof(*dns_cache_stats) * iproc_num);
426
-	if (dns_cache_stats==0){
427
-		return E_OUT_OF_MEM;
428
-	}
429
-	memset(dns_cache_stats, 0, sizeof(*dns_cache_stats) * iproc_num);
430
-
431
-	return 0;
432
-}
433
-#endif
434
-
435
-/* hash function, type is not used (obsolete)
436
- * params: char* s, int len, int type
437
- * returns the hash value
438
- */
439
-#define dns_hash_no(s, len, type) \
440
-	(get_hash1_case_raw((s),(len)) % DNS_HASH_SIZE)
441
-
442
-
443
-
444
-#ifdef DNS_CACHE_DEBUG
445
-#define DEBUG_LU_LST
446
-#ifdef DEBUG_LU_LST
447
-
448
-#include <stdlib.h> /* abort() */
449
-#define check_lu_lst(l) ((((l)->next==(l)) || ((l)->prev==(l))) && \
450
-							((l)!=dns_last_used_lst))
451
-
452
-#define dbg_lu_lst(txt, l) \
453
-		LM_CRIT("%s: crt(%p, %p, %p)," \
454
-					" prev(%p, %p, %p), next(%p, %p, %p)\n", txt, \
455
-					(l), (l)->next, (l)->prev, \
456
-					(l)->prev, (l)->prev->next, (l)->prev->prev, \
457
-					(l)->next, (l)->next->next, (l)->next->prev \
458
-				)
459
-
460
-#define debug_lu_lst( txt, l) \
461
-	do{ \
462
-		if ((l) && check_lu_lst((l))){  \
463
-			dbg_lu_lst(txt  " crt:", (l)); \
464
-			abort(); \
465
-		} \
466
-		if (((l)->next) && check_lu_lst((l)->next)){ \
467
-			dbg_lu_lst(txt  " next:",  (l)); \
468
-			abort(); \
469
-		} \
470
-		if (((l)->prev) && check_lu_lst((l)->prev)){ \
471
-			dbg_lu_lst(txt  " prev:", (l)); \
472
-			abort(); \
473
-		} \
474
-	}while(0)
475
-
476
-#endif
477
-#endif /* DNS_CACHE_DEBUG */
478
-
479
-
480
-/* must be called with the DNS_LOCK hold
481
- * remove and entry from the hash, dec. its refcnt and if not referenced
482
- * anymore deletes it */
483
-inline static void _dns_hash_remove(struct dns_hash_entry* e)
484
-{
485
-	clist_rm(e, next, prev);
486
-#ifdef DNS_CACHE_DEBUG
487
-	e->next=e->prev=0;
488
-#endif
489
-#ifdef DNS_LU_LST
490
-#ifdef DEBUG_LU_LST
491
-	debug_lu_lst("_dns_hash_remove: pre rm:", &e->last_used_lst);
492
-#endif
493
-	clist_rm(&e->last_used_lst, next, prev);
494
-#ifdef DEBUG_LU_LST
495
-	debug_lu_lst("_dns_hash_remove: post rm:", &e->last_used_lst);
496
-#endif
497
-#ifdef DNS_CACHE_DEBUG
498
-	e->last_used_lst.next=e->last_used_lst.prev=0;
499
-#endif
500
-#endif
501
-	*dns_cache_mem_used-=e->total_size;
502
-	dns_hash_put(e);
503
-}
504
-
505
-
506
-
507
-/* non locking  version (the dns hash must _be_ locked externally)
508
- * returns 0 when not found, or the entry on success (an entry with a
509
- * similar name but with a CNAME type will always match).
510
- * it doesn't increase the internal refcnt
511
- * returns the entry when found, 0 when not found and sets *err to !=0
512
- *  on error (e.g. recursive cnames)
513
- * WARNING: - internal use only
514
- *          - always check if the returned entry type is CNAME */
515
-inline static struct dns_hash_entry* _dns_hash_find(str* name, int type,
516
-														int* h, int* err)
517
-{
518
-	struct dns_hash_entry* e;
519
-	struct dns_hash_entry* tmp;
520
-	struct dns_hash_entry* ret;
521
-	ticks_t now;
522
-	int cname_chain;
523
-	str cname;
524
-#ifdef DNS_WATCHDOG_SUPPORT
525
-	int servers_up;
526
-
527
-	servers_up = atomic_get(dns_servers_up);
528
-#endif
529
-
530
-	cname_chain=0;
531
-	ret=0;
532
-	now=get_ticks_raw();
533
-	*err=0;
534
-again:
535
-	*h=dns_hash_no(name->s, name->len, type);
536
-#ifdef DNS_CACHE_DEBUG
537
-	LM_DBG("(%.*s(%d), %d), h=%d\n", name->len, name->s, name->len, type, *h);
538
-#endif
539
-	clist_foreach_safe(&dns_hash[*h], e, tmp, next){
540
-		if (
541
-#ifdef DNS_WATCHDOG_SUPPORT
542
-			/* remove expired elements only when the dns servers are up */
543
-			servers_up &&
544
-#endif
545
-			/* automatically remove expired elements */
546
-			((e->ent_flags & DNS_FLAG_PERMANENT) == 0) &&
547
-			((s_ticks_t)(now-e->expire)>=0)
548
-		) {
549
-				_dns_hash_remove(e);
550
-		}else if ((e->type==type) && (e->name_len==name->len) &&
551
-			(strncasecmp(e->name, name->s, e->name_len)==0)){
552
-			e->last_used=now;
553
-#ifdef DNS_LU_LST
554
-			/* add it at the end */
555
-#ifdef DEBUG_LU_LST
556
-			debug_lu_lst("_dns_hash_find: pre rm:", &e->last_used_lst);
557
-#endif
558
-			clist_rm(&e->last_used_lst, next, prev);
559
-			clist_append(dns_last_used_lst, &e->last_used_lst, next, prev);
560
-#ifdef DEBUG_LU_LST
561
-			debug_lu_lst("_dns_hash_find: post append:", &e->last_used_lst);
562
-#endif
563
-#endif
564
-			return e;
565
-		}else if ((e->type==T_CNAME) &&
566
-					!((e->rr_lst==0) || (e->ent_flags & DNS_FLAG_BAD_NAME)) &&
567
-					(e->name_len==name->len) &&
568
-					(strncasecmp(e->name, name->s, e->name_len)==0)){
569
-			/*if CNAME matches and CNAME is entry is not a neg. cache entry
570
-			  (could be produced by a specific CNAME lookup)*/
571
-			e->last_used=now;
572
-#ifdef DNS_LU_LST
573
-			/* add it at the end */
574
-#ifdef DEBUG_LU_LST
575
-			debug_lu_lst("_dns_hash_find: cname: pre rm:", &e->last_used_lst);
576
-#endif
577
-			clist_rm(&e->last_used_lst, next, prev);
578
-			clist_append(dns_last_used_lst, &e->last_used_lst, next, prev);
579
-#ifdef DEBUG_LU_LST
580
-			debug_lu_lst("_dns_hash_find: cname: post append:",
581
-							&e->last_used_lst);
582
-#endif
583
-#endif
584
-			ret=e; /* if this is an unfinished cname chain, we try to
585
-					  return the last cname */
586
-			/* this is a cname => retry using its value */
587
-			if (cname_chain> MAX_CNAME_CHAIN){
588
-				LM_ERR("cname chain too long or recursive (\"%.*s\")\n",
589
-						name->len, name->s);
590
-				ret=0; /* error*/
591
-				*err=-1;
592
-				break;
593
-			}
594
-			cname_chain++;
595
-			cname.s=((struct cname_rdata*)e->rr_lst->rdata)->name;
596
-			cname.len= ((struct cname_rdata*)e->rr_lst->rdata)->name_len;
597
-			name=&cname;
598
-			goto again;
599
-		}
600
-	}
601
-	return ret;
602
-}
603
-
604
-
605
-
606
-/* frees cache entries, if expired_only=0 only expired entries will be
607
- * removed, else all of them
608
- * it will process maximum no entries (to process all of them use -1)
609
- * returns the number of deleted entries
610
- * This should be called from a timer process*/
611
-inline static int dns_cache_clean(unsigned int no, int expired_only)
612
-{
613
-	struct dns_hash_entry* e;
614
-	ticks_t now;
615
-	unsigned int n;
616
-	unsigned int deleted;
617
-#ifdef DNS_LU_LST
618
-	struct dns_lu_lst* l;
619
-	struct dns_lu_lst* tmp;
620
-#else
621
-	struct dns_hash_entry* t;
622
-	unsigned int h;
623
-	static unsigned int start=0;
624
-#endif
625
-
626
-	n=0;
627
-	deleted=0;
628
-	now=get_ticks_raw();
629
-	LOCK_DNS_HASH();
630
-#ifdef DNS_LU_LST
631
-	clist_foreach_safe(dns_last_used_lst, l, tmp, next){
632
-		e=(struct dns_hash_entry*)(((char*)l)-
633
-				(char*)&((struct dns_hash_entry*)(0))->last_used_lst);
634
-		if (((e->ent_flags & DNS_FLAG_PERMANENT) == 0)
635
-			&& (!expired_only || ((s_ticks_t)(now-e->expire)>=0))
636
-		) {
637
-				_dns_hash_remove(e);
638
-				deleted++;
639
-		}
640
-		n++;
641
-		if (n>=no) break;
642
-	}
643
-#else
644
-	for(h=start; h!=(start+DNS_HASH_SIZE); h++){
645
-		clist_foreach_safe(&dns_hash[h%DNS_HASH_SIZE], e, t, next){
646
-			if (((e->ent_flags & DNS_FLAG_PERMANENT) == 0)
647
-				&& ((s_ticks_t)(now-e->expire)>=0)
648
-			) {
649
-				_dns_hash_remove(e);
650
-				deleted++;
651
-			}
652
-			n++;
653
-			if (n>=no) goto skip;
654
-		}
655
-	}
656
-	/* not fair, but faster then random() */
657
-	if (!expired_only){
658
-		for(h=start; h!=(start+DNS_HASH_SIZE); h++){
659
-			clist_foreach_safe(&dns_hash[h%DNS_HASH_SIZE], e, t, next){
660
-				if ((e->ent_flags & DNS_FLAG_PERMANENT) == 0) {
661
-					_dns_hash_remove(e);
662
-					deleted++;
663
-				}
664
-				n++;
665
-				if (n>=no) goto skip;
666
-			}
667
-		}
668
-	}
669
-skip:
670
-	start=h;
671
-#endif
672
-	UNLOCK_DNS_HASH();
673
-	return deleted;
674
-}
675
-
676
-
677
-
678
-/* frees cache entries, if expired_only=0 only expired entries will be
679
- * removed, else all of them
680
- * it will stop when the dns cache used memory reaches target (to process all
681
- * of them use 0)
682
- * returns the number of deleted entries */
683
-inline static int dns_cache_free_mem(unsigned int target, int expired_only)
684
-{
685
-	struct dns_hash_entry* e;
686
-	ticks_t now;
687
-	unsigned int deleted;
688
-#ifdef DNS_LU_LST
689
-	struct dns_lu_lst* l;
690
-	struct dns_lu_lst* tmp;
691
-#else
692
-	struct dns_hash_entry* t;
693
-	unsigned int h;
694
-	static unsigned int start=0;
695
-#endif
696
-
697
-	deleted=0;
698
-	now=get_ticks_raw();
699
-	LOCK_DNS_HASH();
700
-#ifdef DNS_LU_LST
701
-	clist_foreach_safe(dns_last_used_lst, l, tmp, next){
702
-		if (*dns_cache_mem_used<=target) break;
703
-		e=(struct dns_hash_entry*)(((char*)l)-
704
-				(char*)&((struct dns_hash_entry*)(0))->last_used_lst);
705
-		if (((e->ent_flags & DNS_FLAG_PERMANENT) == 0)
706
-			&& (!expired_only || ((s_ticks_t)(now-e->expire)>=0))
707
-		) {
708
-				_dns_hash_remove(e);
709
-				deleted++;
710
-		}
711
-	}
712
-#else
713
-	for(h=start; h!=(start+DNS_HASH_SIZE); h++){
714
-		clist_foreach_safe(&dns_hash[h%DNS_HASH_SIZE], e, t, next){
715
-			if (*dns_cache_mem_used<=target)
716
-				goto skip;
717
-			if (((e->ent_flags & DNS_FLAG_PERMANENT) == 0)
718
-				&& ((s_ticks_t)(now-e->expire)>=0)
719
-			) {
720
-				_dns_hash_remove(e);
721
-				deleted++;
722
-			}
723
-		}
724
-	}
725
-	/* not fair, but faster then random() */
726
-	if (!expired_only){
727
-		for(h=start; h!=(start+DNS_HASH_SIZE); h++){
728
-			clist_foreach_safe(&dns_hash[h%DNS_HASH_SIZE], e, t, next){
729
-				if (*dns_cache_mem_used<=target)
730
-					goto skip;
731
-				if (((e->ent_flags & DNS_FLAG_PERMANENT) == 0)
732
-					&& ((s_ticks_t)(now-e->expire)>=0)
733
-				) {
734
-					_dns_hash_remove(e);
735
-					deleted++;
736
-				}
737
-			}
738
-		}
739
-	}
740
-skip:
741
-	start=h;
742
-#endif
743
-	UNLOCK_DNS_HASH();
744
-	return deleted;
745
-}
746
-
747
-
748
-
749
-/* locking  version (the dns hash must _not_be locked externally)
750
- * returns 0 when not found, the searched entry on success (with CNAMEs
751
- *  followed) or the last CNAME entry from an unfinished CNAME chain,
752
- *  if the search matches a CNAME. On error sets *err (e.g. recursive CNAMEs).
753
- * it increases the internal refcnt => when finished dns_hash_put() must
754
- *  be called on the returned entry
755
- *  WARNING: - the return might be a CNAME even if type!=CNAME, see above */
756
-inline static struct dns_hash_entry* dns_hash_get(str* name, int type, int* h,
757
-													int* err)
758
-{
759
-	struct dns_hash_entry* e;
760
-
761
-	LOCK_DNS_HASH();
762
-	e=_dns_hash_find(name, type, h, err);
763
-	if (e){
764
-		atomic_inc(&e->refcnt);
765
-	}
766
-	UNLOCK_DNS_HASH();
767
-	return e;
768
-}
769
-
770
-
771
-
772
-/* adds a fully created and init. entry (see dns_cache_mk_entry()) to the hash
773
- * table
774
- * returns 0 on success, -1 on error */
775
-inline static int dns_cache_add(struct dns_hash_entry* e)
776
-{
777
-	int h;
778
-
779
-	/* check space */
780
-	/* atomic_add_long(dns_cache_total_used, e->size); */
781
-	if ((*dns_cache_mem_used+e->total_size)>=cfg_get(core, core_cfg, dns_cache_max_mem)){
782
-#ifdef USE_DNS_CACHE_STATS
783
-		dns_cache_stats[process_no].dc_lru_cnt++;
784
-#endif
785
-		LM_WARN("cache full, trying to free...\n");
786
-		/* free ~ 12% of the cache */
787
-		dns_cache_free_mem(*dns_cache_mem_used/16*14,
788
-					!cfg_get(core, core_cfg, dns_cache_del_nonexp));
789
-		if ((*dns_cache_mem_used+e->total_size)>=cfg_get(core, core_cfg, dns_cache_max_mem)){
790
-			LM_ERR("max. cache mem size exceeded\n");
791
-			return -1;
792
-		}
793
-	}
794
-	atomic_inc(&e->refcnt);
795
-	h=dns_hash_no(e->name, e->name_len, e->type);
796
-#ifdef DNS_CACHE_DEBUG
797
-	LM_DBG("adding %.*s(%d) %d (flags=%0x) at %d\n",
798
-			e->name_len, e->name, e->name_len, e->type, e->ent_flags, h);
799
-#endif
800
-	LOCK_DNS_HASH();
801
-		*dns_cache_mem_used+=e->total_size; /* no need for atomic ops, written
802
-										 only from within a lock */
803
-		clist_append(&dns_hash[h], e, next, prev);
804
-#ifdef DNS_LU_LST
805
-		clist_append(dns_last_used_lst, &e->last_used_lst, next, prev);
806
-#endif
807
-	UNLOCK_DNS_HASH();
808
-	return 0;
809
-}
810
-
811
-
812
-
813
-/* same as above, but it must be called with the dns hash lock held
814
- * returns 0 on success, -1 on error */
815
-inline static int dns_cache_add_unsafe(struct dns_hash_entry* e)
816
-{
817
-	int h;
818
-
819
-	/* check space */
820
-	/* atomic_add_long(dns_cache_total_used, e->size); */
821
-	if ((*dns_cache_mem_used+e->total_size)>=cfg_get(core, core_cfg, dns_cache_max_mem)){
822
-#ifdef USE_DNS_CACHE_STATS
823
-		dns_cache_stats[process_no].dc_lru_cnt++;
824
-#endif
825
-		LM_WARN("cache full, trying to free...\n");
826
-		/* free ~ 12% of the cache */
827
-		UNLOCK_DNS_HASH();
828
-		dns_cache_free_mem(*dns_cache_mem_used/16*14,
829
-					!cfg_get(core, core_cfg, dns_cache_del_nonexp));
830
-		LOCK_DNS_HASH();
831
-		if ((*dns_cache_mem_used+e->total_size)>=cfg_get(core, core_cfg, dns_cache_max_mem)){
832
-			LM_ERR("max. cache mem size exceeded\n");
833
-			return -1;
834
-		}
835
-	}
836
-	atomic_inc(&e->refcnt);
837
-	h=dns_hash_no(e->name, e->name_len, e->type);
838
-#ifdef DNS_CACHE_DEBUG
839
-	LM_DBG("adding %.*s(%d) %d (flags=%0x) at %d\n",
840
-			e->name_len, e->name, e->name_len, e->type, e->ent_flags, h);
841
-#endif
842
-	*dns_cache_mem_used+=e->total_size; /* no need for atomic ops, written
843
-										 only from within a lock */
844
-	clist_append(&dns_hash[h], e, next, prev);
845
-#ifdef DNS_LU_LST
846
-	clist_append(dns_last_used_lst, &e->last_used_lst, next, prev);
847
-#endif
848
-	return 0;
849
-}
850
-
851
-
852
-
853
-/* creates a "negative" entry which will be valid for ttl seconds */
854
-inline static struct dns_hash_entry* dns_cache_mk_bad_entry(str* name,
855
-															int type,
856
-															int ttl,
857
-															int flags)
858
-{
859
-	struct dns_hash_entry* e;
860
-	int size;
861
-	ticks_t now;
862
-
863
-#ifdef DNS_CACHE_DEBUG
864
-	LM_DBG("(%.*s, %d, %d, %d)\n", name->len, name->s, type, ttl, flags);
865
-#endif
866
-	size=sizeof(struct dns_hash_entry)+name->len-1+1;
867
-	e=shm_malloc(size);
868
-	if (e==0){
869
-		LM_ERR("out of memory\n");
870
-		return 0;
871
-	}
872
-	memset(e, 0, size); /* init with 0*/
873
-	e->total_size=size;
874
-	e->name_len=name->len;
875
-	e->type=type;
876
-	now=get_ticks_raw();
877
-	e->last_used=now;
878
-	e->expire=now+S_TO_TICKS(ttl);
879
-	memcpy(e->name, name->s, name->len);
880
-	e->ent_flags=flags;
881
-	return e;
882
-}
883
-
884
-
885
-
886
-/* create a a/aaaa hash entry from a name and ip address
887
- * returns 0 on error */
888
-inline static struct dns_hash_entry* dns_cache_mk_ip_entry(str* name,
889
-															struct ip_addr* ip)
890
-{
891
-	struct dns_hash_entry* e;
892
-	int size;
893
-	ticks_t now;
894
-
895
-	/* everything is allocated in one block: dns_hash_entry + name +
896
-	 * + dns_rr + rdata;  dns_rr must start at an aligned adress,
897
-	 * hence we need to round dns_hash_entry+name size to a sizeof(long)
898
-	 * multiple.
899
-	 * Memory image:
900
-	 * struct dns_hash_entry
901
-	 * name (name_len+1 bytes)
902
-	 * padding to multiple of sizeof(long)
903
-	 * dns_rr
904
-	 * rdata  (no padding needed, since for ip is just an array of chars)
905