00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00059 #ifdef USE_DNS_CACHE
00060
00061 #ifdef DNS_SRV_LB
00062 #include <stdlib.h>
00063 #endif
00064 #include <string.h>
00065
00066 #include "globals.h"
00067 #include "cfg_core.h"
00068 #include "dns_cache.h"
00069 #include "dns_wrappers.h"
00070 #include "compiler_opt.h"
00071 #include "mem/shm_mem.h"
00072 #include "hashes.h"
00073 #include "clist.h"
00074 #include "locking.h"
00075 #include "atomic_ops.h"
00076 #include "ut.h"
00077 #include "timer.h"
00078 #include "timer_ticks.h"
00079 #include "error.h"
00080 #include "rpc.h"
00081 #include "rand/fastrand.h"
00082 #ifdef USE_DNS_CACHE_STATS
00083 #include "pt.h"
00084 #endif
00085
00086
00087
00088 #define DNS_CACHE_DEBUG
00089
00090
00091 #ifndef MAX
00092 #define MAX(a,b) ( ((a)>(b))?(a):(b))
00093 #endif
00094
00095 #define MAX_DNS_RECORDS 255
00096
00097
00098 #define DNS_HASH_SIZE 1024
00099 #define DEFAULT_DNS_TIMER_INTERVAL 120
00100 #define DNS_HE_MAX_ADDR 10
00101 #define MAX_CNAME_CHAIN 10
00102 #define SPACE_FORMAT " "
00103 #define DNS_SRV_ZERO_W_CHANCE 1000
00104
00105
00106 int dns_cache_init=1;
00107 static gen_lock_t* dns_hash_lock=0;
00108 static volatile unsigned int *dns_cache_mem_used=0;
00109 unsigned int dns_timer_interval=DEFAULT_DNS_TIMER_INTERVAL;
00110 int dns_flags=0;
00111
00112
00113 #ifdef USE_DNS_CACHE_STATS
00114 struct t_dns_cache_stats* dns_cache_stats=0;
00115 #endif
00116
00117 #define LOCK_DNS_HASH() lock_get(dns_hash_lock)
00118 #define UNLOCK_DNS_HASH() lock_release(dns_hash_lock)
00119
00120 #define FIX_TTL(t) \
00121 (((t)<cfg_get(core, core_cfg, dns_cache_min_ttl))? \
00122 cfg_get(core, core_cfg, dns_cache_min_ttl): \
00123 (((t)>cfg_get(core, core_cfg, dns_cache_max_ttl))? \
00124 cfg_get(core, core_cfg, dns_cache_max_ttl): \
00125 (t)))
00126
00127
00128 struct dns_hash_head{
00129 struct dns_hash_entry* next;
00130 struct dns_hash_entry* prev;
00131 };
00132
00133 #ifdef DNS_LU_LST
00134 struct dns_lu_lst* dns_last_used_lst=0;
00135 #endif
00136
00137 static struct dns_hash_head* dns_hash=0;
00138
00139
00140 static struct timer_ln* dns_timer_h=0;
00141
00142 #ifdef DNS_WATCHDOG_SUPPORT
00143 static atomic_t *dns_servers_up = NULL;
00144 #endif
00145
00146
00147
00148 static const char* dns_str_errors[]={
00149 "no error",
00150 "no more records",
00151 "unknown error",
00152 "internal error",
00153 "bad SRV entry",
00154 "unresolvable SRV request",
00155 "bad A or AAAA entry",
00156 "unresolvable A or AAAA request",
00157 "invalid ip in A or AAAA record",
00158 "blacklisted ip",
00159 "name too long ",
00160 "ip AF mismatch",
00161 "unresolvable NAPTR request",
00162 "bug - critical error"
00163 };
00164
00165
00166
00167
00168 const char* dns_strerror(int err)
00169 {
00170 err=-err;
00171 if ((err>=0) && (err<sizeof(dns_str_errors)/sizeof(char*)))
00172 return dns_str_errors[err];
00173 return "bug -- bad error number";
00174 }
00175
00176
00177
00178
00179 inline static void dns_destroy_entry(struct dns_hash_entry* e)
00180 {
00181 #ifdef DNS_CACHE_DEBUG
00182 memset(e, 0, e->total_size);
00183 #endif
00184 shm_free(e);
00185 }
00186
00187
00188
00189 inline static void dns_destroy_entry_shm_unsafe(struct dns_hash_entry* e)
00190 {
00191 #ifdef DNS_CACHE_DEBUG
00192 memset(e, 0, e->total_size);
00193 #endif
00194 shm_free_unsafe(e);
00195 }
00196
00197
00198
00199
00200 void dns_hash_put(struct dns_hash_entry* e)
00201 {
00202 if(e && atomic_dec_and_test(&e->refcnt)){
00203
00204 dns_destroy_entry(e);
00205 }
00206 }
00207
00208
00209
00210
00211
00212 void dns_hash_put_shm_unsafe(struct dns_hash_entry* e)
00213 {
00214 if(e && atomic_dec_and_test(&e->refcnt)){
00215
00216 dns_destroy_entry_shm_unsafe(e);
00217 }
00218 }
00219
00220
00221 inline static int dns_cache_clean(unsigned int no, int expired_only);
00222 inline static int dns_cache_free_mem(unsigned int target, int expired_only);
00223
00224 static ticks_t dns_timer(ticks_t ticks, struct timer_ln* tl, void* data)
00225 {
00226 #ifdef DNS_WATCHDOG_SUPPORT
00227
00228 if (atomic_get(dns_servers_up) == 0)
00229 return (ticks_t)(-1);
00230 #endif
00231 if (*dns_cache_mem_used>12*(cfg_get(core, core_cfg, dns_cache_max_mem)/16)){
00232 dns_cache_free_mem(cfg_get(core, core_cfg, dns_cache_max_mem)/2, 1);
00233 }else{
00234 dns_cache_clean(-1, 1);
00235
00236 }
00237 return (ticks_t)(-1);
00238 }
00239
00240
00241
00242 void destroy_dns_cache()
00243 {
00244 if (dns_timer_h){
00245 timer_del(dns_timer_h);
00246 timer_free(dns_timer_h);
00247 dns_timer_h=0;
00248 }
00249 #ifdef DNS_WATCHDOG_SUPPORT
00250 if (dns_servers_up){
00251 shm_free(dns_servers_up);
00252 dns_servers_up=0;
00253 }
00254 #endif
00255 if (dns_hash_lock){
00256 lock_destroy(dns_hash_lock);
00257 lock_dealloc(dns_hash_lock);
00258 dns_hash_lock=0;
00259 }
00260 if (dns_hash){
00261 shm_free(dns_hash);
00262 dns_hash=0;
00263 }
00264 #ifdef DNS_LU_LST
00265 if (dns_last_used_lst){
00266 shm_free(dns_last_used_lst);
00267 dns_last_used_lst=0;
00268 }
00269 #endif
00270 #ifdef USE_DNS_CACHE_STATS
00271 if (dns_cache_stats)
00272 shm_free(dns_cache_stats);
00273 #endif
00274 if (dns_cache_mem_used){
00275 shm_free((void*)dns_cache_mem_used);
00276 dns_cache_mem_used=0;
00277 }
00278 }
00279
00280
00281 void fix_dns_flags(str *gname, str *name)
00282 {
00283
00284
00285
00286
00287
00288 dns_flags = cfg_get(core, core_cfg, dns_cache_flags) & 7;
00289
00290 if (cfg_get(core, core_cfg, dns_try_ipv6)==0){
00291 dns_flags|=DNS_IPV4_ONLY;
00292 }
00293 if (dns_flags & DNS_IPV4_ONLY){
00294 dns_flags&=~(DNS_IPV6_ONLY|DNS_IPV6_FIRST);
00295 }
00296 if (cfg_get(core, core_cfg, dns_srv_lb)){
00297 #ifdef DNS_SRV_LB
00298 dns_flags|=DNS_SRV_RR_LB;
00299 #else
00300 LOG(L_WARN, "WARNING: fix_dns_flags: SRV loadbalaning is set, but"
00301 " support for it is not compiled -- ignoring\n");
00302 #endif
00303 }
00304 if (cfg_get(core, core_cfg, dns_try_naptr)) {
00305 #ifndef USE_NAPTR
00306 LOG(L_WARN, "WARNING: fix_dns_flags: NAPTR support is enabled, but"
00307 " support for it is not compiled -- ignoring\n");
00308 #endif
00309 dns_flags|=DNS_TRY_NAPTR;
00310 }
00311 }
00312
00313
00314
00315
00316 int use_dns_failover_fixup(void *handle, str *gname, str *name, void **val)
00317 {
00318 if ((int)(long)(*val) && !cfg_get(core, handle, use_dns_cache)) {
00319 LOG(L_ERR, "ERROR: use_dns_failover_fixup(): "
00320 "DNS cache is turned off, failover cannot be enabled. "
00321 "(set use_dns_cache to 1)\n");
00322 return -1;
00323 }
00324 return 0;
00325 }
00326
00327
00328
00329
00330 int use_dns_cache_fixup(void *handle, str *gname, str *name, void **val)
00331 {
00332 if ((int)(long)(*val) && !dns_cache_init) {
00333 LOG(L_ERR, "ERROR: use_dns_cache_fixup(): "
00334 "DNS cache is turned off by dns_cache_init=0, "
00335 "it cannot be enabled runtime.\n");
00336 return -1;
00337 }
00338 if (((int)(long)(*val)==0) && cfg_get(core, handle, use_dns_failover)) {
00339 LOG(L_ERR, "ERROR: use_dns_failover_fixup(): "
00340 "DNS failover depends on use_dns_cache, set use_dns_failover "
00341 "to 0 before disabling the DNS cache\n");
00342 return -1;
00343 }
00344 return 0;
00345 }
00346
00347
00348 int dns_cache_max_mem_fixup(void *handle, str *gname, str *name, void **val)
00349 {
00350 unsigned int u;
00351
00352 u = ((unsigned int)(long)(*val))<<10;
00353 (*val) = (void *)(long)u;
00354 return 0;
00355 }
00356
00357 int init_dns_cache()
00358 {
00359 int r;
00360 int ret;
00361
00362 if (dns_cache_init==0) {
00363
00364 default_core_cfg.use_dns_cache=0;
00365 default_core_cfg.use_dns_failover=0;
00366 return 0;
00367 }
00368
00369 ret=0;
00370
00371 if (E_DNS_CRITICAL>=sizeof(dns_str_errors)/sizeof(char*)){
00372 LOG(L_CRIT, "BUG: dns_cache_init: bad dns error table\n");
00373 ret=E_BUG;
00374 goto error;
00375 }
00376 dns_cache_mem_used=shm_malloc(sizeof(*dns_cache_mem_used));
00377 if (dns_cache_mem_used==0){
00378 ret=E_OUT_OF_MEM;
00379 goto error;
00380 }
00381 #ifdef DNS_LU_LST
00382 dns_last_used_lst=shm_malloc(sizeof(*dns_last_used_lst));
00383 if (dns_last_used_lst==0){
00384 ret=E_OUT_OF_MEM;
00385 goto error;
00386 }
00387 clist_init(dns_last_used_lst, next, prev);
00388 #endif
00389 dns_hash=shm_malloc(sizeof(struct dns_hash_head)*DNS_HASH_SIZE);
00390 if (dns_hash==0){
00391 ret=E_OUT_OF_MEM;
00392 goto error;
00393 }
00394 for (r=0; r<DNS_HASH_SIZE; r++)
00395 clist_init(&dns_hash[r], next, prev);
00396
00397 dns_hash_lock=lock_alloc();
00398 if (dns_hash_lock==0){
00399 ret=E_OUT_OF_MEM;
00400 goto error;
00401 }
00402 if (lock_init(dns_hash_lock)==0){
00403 lock_dealloc(dns_hash_lock);
00404 dns_hash_lock=0;
00405 ret=-1;
00406 goto error;
00407 }
00408
00409 #ifdef DNS_WATCHDOG_SUPPORT
00410 dns_servers_up=shm_malloc(sizeof(atomic_t));
00411 if (dns_servers_up==0){
00412 ret=E_OUT_OF_MEM;
00413 goto error;
00414 }
00415 atomic_set(dns_servers_up, 1);
00416 #endif
00417
00418
00419 default_core_cfg.dns_cache_max_mem<<=10;
00420 if (default_core_cfg.use_dns_cache==0)
00421 default_core_cfg.use_dns_failover=0;
00422
00423 fix_dns_flags(NULL, NULL);
00424
00425 dns_timer_h=timer_alloc();
00426 if (dns_timer_h==0){
00427 ret=E_OUT_OF_MEM;
00428 goto error;
00429 }
00430 if (dns_timer_interval){
00431 timer_init(dns_timer_h, dns_timer, 0, 0);
00432 if (timer_add(dns_timer_h, S_TO_TICKS(dns_timer_interval))<0){
00433 LOG(L_CRIT, "BUG: dns_cache_init: failed to add the timer\n");
00434 timer_free(dns_timer_h);
00435 dns_timer_h=0;
00436 goto error;
00437 }
00438 }
00439
00440 return 0;
00441 error:
00442 destroy_dns_cache();
00443 return ret;
00444 }
00445
00446 #ifdef USE_DNS_CACHE_STATS
00447 int init_dns_cache_stats(int iproc_num)
00448 {
00449
00450 if (dns_cache_init==0) return 0;
00451
00452
00453 if (dns_cache_stats)
00454 shm_free(dns_cache_stats);
00455
00456 dns_cache_stats=shm_malloc(sizeof(*dns_cache_stats) * iproc_num);
00457 if (dns_cache_stats==0){
00458 return E_OUT_OF_MEM;
00459 }
00460 memset(dns_cache_stats, 0, sizeof(*dns_cache_stats) * iproc_num);
00461
00462 return 0;
00463 }
00464 #endif
00465
00466
00467
00468
00469
00470 #define dns_hash_no(s, len, type) \
00471 (get_hash1_case_raw((s),(len)) % DNS_HASH_SIZE)
00472
00473
00474
00475 #ifdef DNS_CACHE_DEBUG
00476 #define DEBUG_LU_LST
00477 #ifdef DEBUG_LU_LST
00478
00479 #include <stdlib.h>
00480 #define check_lu_lst(l) ((((l)->next==(l)) || ((l)->prev==(l))) && \
00481 ((l)!=dns_last_used_lst))
00482
00483 #define dbg_lu_lst(txt, l) \
00484 LOG(L_CRIT, "BUG: %s: crt(%p, %p, %p)," \
00485 " prev(%p, %p, %p), next(%p, %p, %p)\n", txt, \
00486 (l), (l)->next, (l)->prev, \
00487 (l)->prev, (l)->prev->next, (l)->prev->prev, \
00488 (l)->next, (l)->next->next, (l)->next->prev \
00489 )
00490
00491 #define debug_lu_lst( txt, l) \
00492 do{ \
00493 if (check_lu_lst((l))){ \
00494 dbg_lu_lst(txt " crt:", (l)); \
00495 abort(); \
00496 } \
00497 if (check_lu_lst((l)->next)){ \
00498 dbg_lu_lst(txt " next:", (l)); \
00499 abort(); \
00500 } \
00501 if (check_lu_lst((l)->prev)){ \
00502 dbg_lu_lst(txt " prev:", (l)); \
00503 abort(); \
00504 } \
00505 }while(0)
00506
00507 #endif
00508 #endif
00509
00510
00511
00512
00513
00514 inline static void _dns_hash_remove(struct dns_hash_entry* e)
00515 {
00516 clist_rm(e, next, prev);
00517 #ifdef DNS_CACHE_DEBUG
00518 e->next=e->prev=0;
00519 #endif
00520 #ifdef DNS_LU_LST
00521 #ifdef DEBUG_LU_LST
00522 debug_lu_lst("_dns_hash_remove: pre rm:", &e->last_used_lst);
00523 #endif
00524 clist_rm(&e->last_used_lst, next, prev);
00525 #ifdef DEBUG_LU_LST
00526 debug_lu_lst("_dns_hash_remove: post rm:", &e->last_used_lst);
00527 #endif
00528 #ifdef DNS_CACHE_DEBUG
00529 e->last_used_lst.next=e->last_used_lst.prev=0;
00530 #endif
00531 #endif
00532 *dns_cache_mem_used-=e->total_size;
00533 dns_hash_put(e);
00534 }
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546 inline static struct dns_hash_entry* _dns_hash_find(str* name, int type,
00547 int* h, int* err)
00548 {
00549 struct dns_hash_entry* e;
00550 struct dns_hash_entry* tmp;
00551 struct dns_hash_entry* ret;
00552 ticks_t now;
00553 int cname_chain;
00554 str cname;
00555 #ifdef DNS_WATCHDOG_SUPPORT
00556 int servers_up;
00557
00558 servers_up = atomic_get(dns_servers_up);
00559 #endif
00560
00561 cname_chain=0;
00562 ret=0;
00563 now=get_ticks_raw();
00564 *err=0;
00565 again:
00566 *h=dns_hash_no(name->s, name->len, type);
00567 #ifdef DNS_CACHE_DEBUG
00568 DBG("dns_hash_find(%.*s(%d), %d), h=%d\n", name->len, name->s,
00569 name->len, type, *h);
00570 #endif
00571 clist_foreach_safe(&dns_hash[*h], e, tmp, next){
00572 if (
00573 #ifdef DNS_WATCHDOG_SUPPORT
00574
00575 servers_up &&
00576 #endif
00577
00578 ((e->ent_flags & DNS_FLAG_PERMANENT) == 0) &&
00579 ((s_ticks_t)(now-e->expire)>=0)
00580 ) {
00581 _dns_hash_remove(e);
00582 }else if ((e->type==type) && (e->name_len==name->len) &&
00583 (strncasecmp(e->name, name->s, e->name_len)==0)){
00584 e->last_used=now;
00585 #ifdef DNS_LU_LST
00586
00587 #ifdef DEBUG_LU_LST
00588 debug_lu_lst("_dns_hash_find: pre rm:", &e->last_used_lst);
00589 #endif
00590 clist_rm(&e->last_used_lst, next, prev);
00591 clist_append(dns_last_used_lst, &e->last_used_lst, next, prev);
00592 #ifdef DEBUG_LU_LST
00593 debug_lu_lst("_dns_hash_find: post append:", &e->last_used_lst);
00594 #endif
00595 #endif
00596 return e;
00597 }else if ((e->type==T_CNAME) &&
00598 !((e->rr_lst==0) || (e->ent_flags & DNS_FLAG_BAD_NAME)) &&
00599 (e->name_len==name->len) &&
00600 (strncasecmp(e->name, name->s, e->name_len)==0)){
00601
00602
00603 e->last_used=now;
00604 #ifdef DNS_LU_LST
00605
00606 #ifdef DEBUG_LU_LST
00607 debug_lu_lst("_dns_hash_find: cname: pre rm:", &e->last_used_lst);
00608 #endif
00609 clist_rm(&e->last_used_lst, next, prev);
00610 clist_append(dns_last_used_lst, &e->last_used_lst, next, prev);
00611 #ifdef DEBUG_LU_LST
00612 debug_lu_lst("_dns_hash_find: cname: post append:",
00613 &e->last_used_lst);
00614 #endif
00615 #endif
00616 ret=e;
00617
00618
00619 if (cname_chain> MAX_CNAME_CHAIN){
00620 LOG(L_ERR, "ERROR: _dns_hash_find: cname chain too long "
00621 "or recursive (\"%.*s\")\n", name->len, name->s);
00622 ret=0;
00623 *err=-1;
00624 break;
00625 }
00626 cname_chain++;
00627 cname.s=((struct cname_rdata*)e->rr_lst->rdata)->name;
00628 cname.len= ((struct cname_rdata*)e->rr_lst->rdata)->name_len;
00629 name=&cname;
00630 goto again;
00631 }
00632 }
00633 return ret;
00634 }
00635
00636
00637
00638
00639
00640
00641
00642
00643 inline static int dns_cache_clean(unsigned int no, int expired_only)
00644 {
00645 struct dns_hash_entry* e;
00646 ticks_t now;
00647 unsigned int n;
00648 unsigned int deleted;
00649 #ifdef DNS_LU_LST
00650 struct dns_lu_lst* l;
00651 struct dns_lu_lst* tmp;
00652 #else
00653 struct dns_hash_entry* t;
00654 unsigned int h;
00655 static unsigned int start=0;
00656 #endif
00657
00658 n=0;
00659 deleted=0;
00660 now=get_ticks_raw();
00661 LOCK_DNS_HASH();
00662 #ifdef DNS_LU_LST
00663 clist_foreach_safe(dns_last_used_lst, l, tmp, next){
00664 e=(struct dns_hash_entry*)(((char*)l)-
00665 (char*)&((struct dns_hash_entry*)(0))->last_used_lst);
00666 if (((e->ent_flags & DNS_FLAG_PERMANENT) == 0)
00667 && (!expired_only || ((s_ticks_t)(now-e->expire)>=0))
00668 ) {
00669 _dns_hash_remove(e);
00670 deleted++;
00671 }
00672 n++;
00673 if (n>=no) break;
00674 }
00675 #else
00676 for(h=start; h!=(start+DNS_HASH_SIZE); h++){
00677 clist_foreach_safe(&dns_hash[h%DNS_HASH_SIZE], e, t, next){
00678 if (((e->ent_flags & DNS_FLAG_PERMANENT) == 0)
00679 && ((s_ticks_t)(now-e->expire)>=0)
00680 ) {
00681 _dns_hash_remove(e);
00682 deleted++;
00683 }
00684 n++;
00685 if (n>=no) goto skip;
00686 }
00687 }
00688
00689 if (!expired_only){
00690 for(h=start; h!=(start+DNS_HASH_SIZE); h++){
00691 clist_foreach_safe(&dns_hash[h%DNS_HASH_SIZE], e, t, next){
00692 if ((e->ent_flags & DNS_FLAG_PERMANENT) == 0) {
00693 _dns_hash_remove(e);
00694 deleted++;
00695 }
00696 n++;
00697 if (n>=no) goto skip;
00698 }
00699 }
00700 }
00701 skip:
00702 start=h;
00703 #endif
00704 UNLOCK_DNS_HASH();
00705 return deleted;
00706 }
00707
00708
00709
00710
00711
00712
00713
00714
00715 inline static int dns_cache_free_mem(unsigned int target, int expired_only)
00716 {
00717 struct dns_hash_entry* e;
00718 ticks_t now;
00719 unsigned int deleted;
00720 #ifdef DNS_LU_LST
00721 struct dns_lu_lst* l;
00722 struct dns_lu_lst* tmp;
00723 #else
00724 struct dns_hash_entry* t;
00725 unsigned int h;
00726 static unsigned int start=0;
00727 #endif
00728
00729 deleted=0;
00730 now=get_ticks_raw();
00731 LOCK_DNS_HASH();
00732 #ifdef DNS_LU_LST
00733 clist_foreach_safe(dns_last_used_lst, l, tmp, next){
00734 if (*dns_cache_mem_used<=target) break;
00735 e=(struct dns_hash_entry*)(((char*)l)-
00736 (char*)&((struct dns_hash_entry*)(0))->last_used_lst);
00737 if (((e->ent_flags & DNS_FLAG_PERMANENT) == 0)
00738 && (!expired_only || ((s_ticks_t)(now-e->expire)>=0))
00739 ) {
00740 _dns_hash_remove(e);
00741 deleted++;
00742 }
00743 }
00744 #else
00745 for(h=start; h!=(start+DNS_HASH_SIZE); h++){
00746 clist_foreach_safe(&dns_hash[h%DNS_HASH_SIZE], e, t, next){
00747 if (*dns_cache_mem_used<=target)
00748 goto skip;
00749 if (((e->ent_flags & DNS_FLAG_PERMANENT) == 0)
00750 && ((s_ticks_t)(now-e->expire)>=0)
00751 ) {
00752 _dns_hash_remove(e);
00753 deleted++;
00754 }
00755 }
00756 }
00757
00758 if (!expired_only){
00759 for(h=start; h!=(start+DNS_HASH_SIZE); h++){
00760 clist_foreach_safe(&dns_hash[h%DNS_HASH_SIZE], e, t, next){
00761 if (*dns_cache_mem_used<=target)
00762 goto skip;
00763 if (((e->ent_flags & DNS_FLAG_PERMANENT) == 0)
00764 && ((s_ticks_t)(now-e->expire)>=0)
00765 ) {
00766 _dns_hash_remove(e);
00767 deleted++;
00768 }
00769 }
00770 }
00771 }
00772 skip:
00773 start=h;
00774 #endif
00775 UNLOCK_DNS_HASH();
00776 return deleted;
00777 }
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788 inline static struct dns_hash_entry* dns_hash_get(str* name, int type, int* h,
00789 int* err)
00790 {
00791 struct dns_hash_entry* e;
00792
00793 LOCK_DNS_HASH();
00794 e=_dns_hash_find(name, type, h, err);
00795 if (e){
00796 atomic_inc(&e->refcnt);
00797 }
00798 UNLOCK_DNS_HASH();
00799 return e;
00800 }
00801
00802
00803
00804
00805
00806
00807 inline static int dns_cache_add(struct dns_hash_entry* e)
00808 {
00809 int h;
00810
00811
00812
00813 if ((*dns_cache_mem_used+e->total_size)>=cfg_get(core, core_cfg, dns_cache_max_mem)){
00814 #ifdef USE_DNS_CACHE_STATS
00815 dns_cache_stats[process_no].dc_lru_cnt++;
00816 #endif
00817 LOG(L_WARN, "WARNING: dns_cache_add: cache full, trying to free...\n");
00818
00819 dns_cache_free_mem(*dns_cache_mem_used/16*14,
00820 !cfg_get(core, core_cfg, dns_cache_del_nonexp));
00821 if ((*dns_cache_mem_used+e->total_size)>=cfg_get(core, core_cfg, dns_cache_max_mem)){
00822 LOG(L_ERR, "ERROR: dns_cache_add: max. cache mem size exceeded\n");
00823 return -1;
00824 }
00825 }
00826 atomic_inc(&e->refcnt);
00827 h=dns_hash_no(e->name, e->name_len, e->type);
00828 #ifdef DNS_CACHE_DEBUG
00829 DBG("dns_cache_add: adding %.*s(%d) %d (flags=%0x) at %d\n",
00830 e->name_len, e->name, e->name_len, e->type, e->ent_flags, h);
00831 #endif
00832 LOCK_DNS_HASH();
00833 *dns_cache_mem_used+=e->total_size;
00834
00835 clist_append(&dns_hash[h], e, next, prev);
00836 #ifdef DNS_LU_LST
00837 clist_append(dns_last_used_lst, &e->last_used_lst, next, prev);
00838 #endif
00839 UNLOCK_DNS_HASH();
00840 return 0;
00841 }
00842
00843
00844
00845
00846
00847 inline static int dns_cache_add_unsafe(struct dns_hash_entry* e)
00848 {
00849 int h;
00850
00851
00852
00853 if ((*dns_cache_mem_used+e->total_size)>=cfg_get(core, core_cfg, dns_cache_max_mem)){
00854 #ifdef USE_DNS_CACHE_STATS
00855 dns_cache_stats[process_no].dc_lru_cnt++;
00856 #endif
00857 LOG(L_WARN, "WARNING: dns_cache_add: cache full, trying to free...\n");
00858
00859 UNLOCK_DNS_HASH();
00860 dns_cache_free_mem(*dns_cache_mem_used/16*14,
00861 !cfg_get(core, core_cfg, dns_cache_del_nonexp));
00862 LOCK_DNS_HASH();
00863 if ((*dns_cache_mem_used+e->total_size)>=cfg_get(core, core_cfg, dns_cache_max_mem)){
00864 LOG(L_ERR, "ERROR: dns_cache_add: max. cache mem size exceeded\n");
00865 return -1;
00866 }
00867 }
00868 atomic_inc(&e->refcnt);
00869 h=dns_hash_no(e->name, e->name_len, e->type);
00870 #ifdef DNS_CACHE_DEBUG
00871 DBG("dns_cache_add: adding %.*s(%d) %d (flags=%0x) at %d\n",
00872 e->name_len, e->name, e->name_len, e->type, e->ent_flags, h);
00873 #endif
00874 *dns_cache_mem_used+=e->total_size;
00875
00876 clist_append(&dns_hash[h], e, next, prev);
00877 #ifdef DNS_LU_LST
00878 clist_append(dns_last_used_lst, &e->last_used_lst, next, prev);
00879 #endif
00880 return 0;
00881 }
00882
00883
00884
00885
00886 inline static struct dns_hash_entry* dns_cache_mk_bad_entry(str* name,
00887 int type,
00888 int ttl,
00889 int flags)
00890 {
00891 struct dns_hash_entry* e;
00892 int size;
00893 ticks_t now;
00894
00895 #ifdef DNS_CACHE_DEBUG
00896 DBG("dns_cache_mk_bad_entry(%.*s, %d, %d, %d)\n", name->len, name->s,
00897 type, ttl, flags);
00898 #endif
00899 size=sizeof(struct dns_hash_entry)+name->len-1+1;
00900 e=shm_malloc(size);
00901 if (e==0){
00902 LOG(L_ERR, "ERROR: dns_cache_mk_bad_entry: out of memory\n");
00903 return 0;
00904 }
00905 memset(e, 0, size);
00906 e->total_size=size;
00907 e->name_len=name->len;
00908 e->type=type;
00909 now=get_ticks_raw();
00910 e->last_used=now;
00911 e->expire=now+S_TO_TICKS(ttl);
00912 memcpy(e->name, name->s, name->len);
00913 e->ent_flags=flags;
00914 return e;
00915 }
00916
00917
00918
00919
00920
00921 inline static struct dns_hash_entry* dns_cache_mk_ip_entry(str* name,
00922 struct ip_addr* ip)
00923 {
00924 struct dns_hash_entry* e;
00925 int size;
00926 ticks_t now;
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939 size=ROUND_POINTER(sizeof(struct dns_hash_entry)+name->len-1+1)+
00940 sizeof(struct dns_rr)+ ip->len;
00941 e=shm_malloc(size);
00942 if (e==0){
00943 LOG(L_ERR, "ERROR: dns_cache_mk_ip_entry: out of memory\n");
00944 return 0;
00945 }
00946 memset(e, 0, size);
00947 e->total_size=size;
00948 e->name_len=name->len;
00949 e->type=(ip->af==AF_INET)?T_A:T_AAAA;
00950 now=get_ticks_raw();
00951 e->last_used=now;
00952 e->expire=now-1;
00953 memcpy(e->name, name->s, name->len);
00954 e->rr_lst=(void*)((char*)e+
00955 ROUND_POINTER(sizeof(struct dns_hash_entry)+name->len-1+1));
00956 e->rr_lst->rdata=(void*)((char*)e->rr_lst+sizeof(struct dns_rr));
00957 e->rr_lst->expire=now-1;
00958
00959 memcpy(e->rr_lst->rdata, ip->u.addr, ip->len);
00960 return e;
00961 }
00962
00963
00964
00965 static struct dns_hash_entry* dns_cache_mk_srv_entry(str* name,
00966 unsigned short priority,
00967 unsigned short weight,
00968 unsigned short port,
00969 str* rr_name,
00970 int ttl)
00971 {
00972 struct dns_hash_entry* e;
00973 int size;
00974 ticks_t now;
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989 size=ROUND_POINTER(sizeof(struct dns_hash_entry)+name->len-1+1) +
00990 ROUND_SHORT(sizeof(struct dns_rr)) +
00991 sizeof(struct srv_rdata)-1 +
00992 rr_name->len+1;
00993
00994 e=shm_malloc(size);
00995 if (e==0){
00996 LOG(L_ERR, "ERROR: dns_cache_srv_ip_entry: out of memory\n");
00997 return 0;
00998 }
00999 memset(e, 0, size);
01000 e->total_size=size;
01001 e->name_len=name->len;
01002 e->type=T_SRV;
01003 now=get_ticks_raw();
01004 e->last_used=now;
01005 e->expire=now+S_TO_TICKS(ttl);
01006 memcpy(e->name, name->s, name->len);
01007 e->rr_lst=(void*)((char*)e+
01008 ROUND_POINTER(sizeof(struct dns_hash_entry)+name->len-1+1));
01009 e->rr_lst->rdata=(void*)((char*)e->rr_lst+ROUND_SHORT(sizeof(struct dns_rr)));
01010 e->rr_lst->expire=e->expire;
01011 ((struct srv_rdata*)e->rr_lst->rdata)->priority = priority;
01012 ((struct srv_rdata*)e->rr_lst->rdata)->weight = weight;
01013 ((struct srv_rdata*)e->rr_lst->rdata)->port = port;
01014 ((struct srv_rdata*)e->rr_lst->rdata)->name_len = rr_name->len;
01015 memcpy(((struct srv_rdata*)e->rr_lst->rdata)->name, rr_name->s, rr_name->len);
01016 return e;
01017 }
01018
01019
01020
01021
01022
01023
01024
01025 inline static struct dns_hash_entry* dns_cache_mk_rd_entry(str* name, int type,
01026 struct rdata** rd_lst)
01027 {
01028 struct dns_hash_entry* e;
01029 struct dns_rr* rr;
01030 struct dns_rr** tail_rr;
01031 struct rdata** p;
01032 struct rdata* tmp_lst;
01033 struct rdata** tail;
01034 struct rdata* l;
01035 int size;
01036 ticks_t now;
01037 unsigned int max_ttl;
01038 unsigned int ttl;
01039 int i;
01040
01041 #define rec_matches(rec, t, n) \
01042 ( ((rec)->name_len==(n)->len) && ((rec)->type==(t)) && \
01043 (strncasecmp((rec)->name, (n)->s, (n)->len)==0))
01044
01045 tmp_lst=0;
01046 tail=&tmp_lst;
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068 size=0;
01069 if (*rd_lst==0)
01070 return 0;
01071
01072
01073 for(p=rd_lst; *p; p=&(*p)->next){
01074 if (((*p)->name_len==name->len) &&
01075 (((*p)->type==type) || ((*p)->type==T_CNAME)) &&
01076 (strncasecmp((*p)->name, name->s, name->len)==0)){
01077 type=(*p)->type;
01078 break;
01079 }
01080 }
01081
01082 switch(type){
01083 case T_A:
01084 for(; *p;){
01085 if (!rec_matches((*p), type, name)){
01086
01087 p=&(*p)->next;
01088 continue;
01089 }
01090 size+=ROUND_POINTER(sizeof(struct dns_rr)+
01091 sizeof(struct a_rdata));
01092
01093 *tail=*p;
01094 tail=&(*p)->next;
01095
01096 *p=(*p)->next;
01097
01098
01099 }
01100 break;
01101 case T_AAAA:
01102 for(; *p;){
01103 if (!rec_matches((*p), type, name)){
01104
01105 p=&(*p)->next;
01106 continue;
01107 }
01108
01109 size+=ROUND_POINTER(sizeof(struct dns_rr)+
01110 sizeof(struct aaaa_rdata));
01111
01112 *tail=*p;
01113 tail=&(*p)->next;
01114
01115 *p=(*p)->next;
01116
01117
01118 }
01119 break;
01120 case T_SRV:
01121 for(; *p;){
01122 if (!rec_matches((*p), type, name)){
01123
01124 p=&(*p)->next;
01125 continue;
01126 }
01127
01128 size+=ROUND_POINTER(ROUND_SHORT(sizeof(struct dns_rr))+
01129 SRV_RDATA_SIZE(*(struct srv_rdata*)(*p)->rdata));
01130
01131 *tail=*p;
01132 tail=&(*p)->next;
01133
01134 *p=(*p)->next;
01135
01136
01137 }
01138 break;
01139 case T_NAPTR:
01140 for(; *p;){
01141 if (!rec_matches((*p), type, name)){
01142
01143 p=&(*p)->next;
01144 continue;
01145 }
01146
01147 size+=ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
01148 NAPTR_RDATA_SIZE(*(struct naptr_rdata*)(*p)->rdata));
01149
01150 *tail=*p;
01151 tail=&(*p)->next;
01152
01153 *p=(*p)->next;
01154
01155
01156 }
01157 break;
01158 case T_CNAME:
01159 for(; *p;){
01160 if (!rec_matches((*p), type, name)){
01161
01162 p=&(*p)->next;
01163 continue;
01164 }
01165
01166 size+=ROUND_POINTER(sizeof(struct dns_rr)+
01167 CNAME_RDATA_SIZE(*(struct cname_rdata*)(*p)->rdata));
01168
01169 *tail=*p;
01170 tail=&(*p)->next;
01171
01172 *p=(*p)->next;
01173
01174
01175 }
01176 break;
01177 case T_TXT:
01178 for(; *p;){
01179 if (!rec_matches((*p), type, name)){
01180
01181 p=&(*p)->next;
01182 continue;
01183 }
01184
01185 size+=ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
01186 TXT_RDATA_SIZE(*(struct txt_rdata*)(*p)->rdata));
01187
01188 *tail=*p;
01189 tail=&(*p)->next;
01190
01191 *p=(*p)->next;
01192
01193
01194 }
01195 break;
01196 case T_EBL:
01197 for(; *p;){
01198 if (!rec_matches((*p), type, name)){
01199
01200 p=&(*p)->next;
01201 continue;
01202 }
01203
01204 size+=ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
01205 EBL_RDATA_SIZE(*(struct ebl_rdata*)(*p)->rdata));
01206
01207 *tail=*p;
01208 tail=&(*p)->next;
01209
01210 *p=(*p)->next;
01211
01212
01213 }
01214 break;
01215 case T_PTR:
01216 for(; *p;){
01217 if (!rec_matches((*p), type, name)){
01218
01219 p=&(*p)->next;
01220 continue;
01221 }
01222
01223 size+=ROUND_POINTER(sizeof(struct dns_rr)+
01224 PTR_RDATA_SIZE(*(struct ptr_rdata*)(*p)->rdata));
01225
01226 *tail=*p;
01227 tail=&(*p)->next;
01228
01229 *p=(*p)->next;
01230
01231
01232 }
01233 break;
01234 default:
01235 LOG(L_CRIT, "BUG: dns_cache_mk_rd_entry: type %d not "
01236 "supported\n", type);
01237
01238
01239 return 0;
01240 }
01241 *tail=0;
01242 if (size==0){
01243 #ifdef DNS_CACHE_DEBUG
01244 DBG("dns_cache_mk_rd_entry: entry %.*s (%d) not found\n",
01245 name->len, name->s, type);
01246 #endif
01247 return 0;
01248 }
01249
01250 size+=ROUND_POINTER(sizeof(struct dns_hash_entry)+name->len-1+1);
01251 e=shm_malloc(size);
01252 if (e==0){
01253 LOG(L_ERR, "ERROR: dns_cache_mk_rd_entry: out of memory\n");
01254 return 0;
01255 }
01256 memset(e, 0, size);
01257 clist_init(e, next, prev);
01258 e->total_size=size;
01259 e->name_len=name->len;
01260 e->type=type;
01261 now=get_ticks_raw();
01262 e->last_used=now;
01263 memcpy(e->name, name->s, name->len);
01264 e->rr_lst=(struct dns_rr*)((char*)e+
01265 ROUND_POINTER(sizeof(struct dns_hash_entry)+name->len-1+1));
01266 tail_rr=&(e->rr_lst);
01267 rr=e->rr_lst;
01268 max_ttl=0;
01269
01270 switch(type){
01271 case T_A:
01272 for(l=tmp_lst; l; l=l->next){
01273 ttl=FIX_TTL(l->ttl);
01274 rr->expire=now+S_TO_TICKS(ttl);
01275 max_ttl=MAX(max_ttl, ttl);
01276 rr->rdata=(void*)((char*)rr+sizeof(struct dns_rr));
01277 memcpy(rr->rdata, l->rdata, sizeof(struct a_rdata));
01278 rr->next=(void*)((char*)rr+ROUND_POINTER(sizeof(struct dns_rr)+
01279 sizeof(struct a_rdata)));
01280 tail_rr=&(rr->next);
01281 rr=rr->next;
01282 }
01283 break;
01284 case T_AAAA:
01285 for(l=tmp_lst; l; l=l->next){
01286 ttl=FIX_TTL(l->ttl);
01287 rr->expire=now+S_TO_TICKS(ttl);
01288 max_ttl=MAX(max_ttl, ttl);
01289 rr->rdata=(void*)((char*)rr+sizeof(struct dns_rr));
01290 memcpy(rr->rdata, l->rdata, sizeof(struct aaaa_rdata));
01291 rr->next=(void*)((char*)rr+ROUND_POINTER(sizeof(struct dns_rr)+
01292 sizeof(struct aaaa_rdata)));
01293 tail_rr=&(rr->next);
01294 rr=rr->next;
01295 }
01296 break;
01297 case T_SRV:
01298 for(l=tmp_lst; l; l=l->next){
01299 ttl=FIX_TTL(l->ttl);
01300 rr->expire=now+S_TO_TICKS(ttl);
01301 max_ttl=MAX(max_ttl, ttl);
01302 rr->rdata=(void*)((char*)rr+
01303 ROUND_SHORT(sizeof(struct dns_rr)));
01304
01305 memcpy(rr->rdata, l->rdata,
01306 SRV_RDATA_SIZE(*(struct srv_rdata*)l->rdata) );
01307 rr->next=(void*)((char*)rr+
01308 ROUND_POINTER( ROUND_SHORT(sizeof(struct dns_rr))+
01309 SRV_RDATA_SIZE(
01310 *(struct srv_rdata*)l->rdata)));
01311 tail_rr=&(rr->next);
01312 rr=rr->next;
01313 }
01314 break;
01315 case T_NAPTR:
01316 for(l=tmp_lst; l; l=l->next){
01317 ttl=FIX_TTL(l->ttl);
01318 rr->expire=now+S_TO_TICKS(ttl);
01319 max_ttl=MAX(max_ttl, ttl);
01320 rr->rdata=(void*)((char*)rr+
01321 ROUND_POINTER(sizeof(struct dns_rr)));
01322
01323 memcpy(rr->rdata, l->rdata,
01324 NAPTR_RDATA_SIZE(*(struct naptr_rdata*)l->rdata) );
01325
01326 ((struct naptr_rdata*)rr->rdata)->flags=
01327 translate_pointer((char*)rr->rdata, (char*)l->rdata,
01328 (((struct naptr_rdata*)l->rdata)->flags));
01329 ((struct naptr_rdata*)rr->rdata)->services=
01330 translate_pointer((char*)rr->rdata, (char*)l->rdata,
01331 (((struct naptr_rdata*)l->rdata)->services));
01332 ((struct naptr_rdata*)rr->rdata)->regexp=
01333 translate_pointer((char*)rr->rdata, (char*)l->rdata,
01334 (((struct naptr_rdata*)l->rdata)->regexp));
01335 ((struct naptr_rdata*)rr->rdata)->repl=
01336 translate_pointer((char*)rr->rdata, (char*)l->rdata,
01337 (((struct naptr_rdata*)l->rdata)->repl));
01338 rr->next=(void*)((char*)rr+
01339 ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
01340 NAPTR_RDATA_SIZE(
01341 *(struct naptr_rdata*)l->rdata)));
01342 tail_rr=&(rr->next);
01343 rr=rr->next;
01344 }
01345 break;
01346 case T_CNAME:
01347 for(l=tmp_lst; l; l=l->next){
01348 ttl=FIX_TTL(l->ttl);
01349 rr->expire=now+S_TO_TICKS(ttl);
01350 max_ttl=MAX(max_ttl, ttl);
01351 rr->rdata=(void*)((char*)rr+sizeof(struct dns_rr));
01352 memcpy(rr->rdata, l->rdata,
01353 CNAME_RDATA_SIZE(*(struct cname_rdata*)l->rdata));
01354 rr->next=(void*)((char*)rr+ROUND_POINTER(sizeof(struct dns_rr)+
01355 CNAME_RDATA_SIZE(*(struct cname_rdata*)l->rdata)));
01356 tail_rr=&(rr->next);
01357 rr=rr->next;
01358 }
01359 break;
01360 case T_TXT:
01361 for(l=tmp_lst; l; l=l->next){
01362 ttl=FIX_TTL(l->ttl);
01363 rr->expire=now+S_TO_TICKS(ttl);
01364 max_ttl=MAX(max_ttl, ttl);
01365 rr->rdata=(void*)((char*)rr+
01366 ROUND_POINTER(sizeof(struct dns_rr)));
01367 memcpy(rr->rdata, l->rdata,
01368 TXT_RDATA_SIZE(*(struct txt_rdata*)l->rdata));
01369
01370 for (i=0; i<((struct txt_rdata*)l->rdata)->cstr_no; i++){
01371 ((struct txt_rdata*)rr->rdata)->txt[i].cstr=
01372 translate_pointer((char*)rr->rdata, (char*)l->rdata,
01373 ((struct txt_rdata*)l->rdata)->txt[i].cstr);
01374 }
01375 rr->next=(void*)((char*)rr+
01376 ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
01377 TXT_RDATA_SIZE(*(struct txt_rdata*)l->rdata)));
01378 tail_rr=&(rr->next);
01379 rr=rr->next;
01380 }
01381 break;
01382 case T_EBL:
01383 for(l=tmp_lst; l; l=l->next){
01384 ttl=FIX_TTL(l->ttl);
01385 rr->expire=now+S_TO_TICKS(ttl);
01386 max_ttl=MAX(max_ttl, ttl);
01387 rr->rdata=(void*)((char*)rr+
01388 ROUND_POINTER(sizeof(struct dns_rr)));
01389 memcpy(rr->rdata, l->rdata,
01390 EBL_RDATA_SIZE(*(struct ebl_rdata*)l->rdata));
01391
01392 ((struct ebl_rdata*)rr->rdata)->separator=
01393 translate_pointer((char*)rr->rdata, (char*)l->rdata,
01394 ((struct ebl_rdata*)l->rdata)->separator);
01395 ((struct ebl_rdata*)rr->rdata)->separator=
01396 translate_pointer((char*)rr->rdata, (char*)l->rdata,
01397 ((struct ebl_rdata*)l->rdata)->separator);
01398 ((struct ebl_rdata*)rr->rdata)->apex=
01399 translate_pointer((char*)rr->rdata, (char*)l->rdata,
01400 ((struct ebl_rdata*)l->rdata)->apex);
01401 rr->next=(void*)((char*)rr+
01402 ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
01403 EBL_RDATA_SIZE(*(struct ebl_rdata*)l->rdata)));
01404 tail_rr=&(rr->next);
01405 rr=rr->next;
01406 }
01407 break;
01408 case T_PTR:
01409 for(l=tmp_lst; l; l=l->next){
01410 ttl=FIX_TTL(l->ttl);
01411 rr->expire=now+S_TO_TICKS(ttl);
01412 max_ttl=MAX(max_ttl, ttl);
01413 rr->rdata=(void*)((char*)rr+sizeof(struct dns_rr));
01414 memcpy(rr->rdata, l->rdata,
01415 PTR_RDATA_SIZE(*(struct ptr_rdata*)l->rdata));
01416 rr->next=(void*)((char*)rr+ROUND_POINTER(sizeof(struct dns_rr)+
01417 PTR_RDATA_SIZE(*(struct ptr_rdata*)l->rdata)));
01418 tail_rr=&(rr->next);
01419 rr=rr->next;
01420 }
01421 break;
01422 default:
01423
01424 LOG(L_CRIT, "BUG: dns_cache_mk_rd_entry: create: type %d not "
01425 "supported\n", type);
01426 ;
01427 }
01428 *tail_rr=0;
01429 e->expire=now+S_TO_TICKS(max_ttl);
01430 free_rdata_list(tmp_lst);
01431 return e;
01432 }
01433
01434
01435
01436
01437
01438 struct tmp_rec{
01439 struct rdata* rd;
01440 struct dns_hash_entry* e;
01441 struct dns_rr* rr;
01442 struct dns_rr** tail_rr;
01443 int max_ttl;
01444 int size;
01445 };
01446
01447
01448
01449
01450
01451 inline static struct dns_hash_entry* dns_cache_mk_rd_entry2(struct rdata* rd)
01452 {
01453 struct rdata* l;
01454 ticks_t now;
01455 struct tmp_rec rec[MAX_DNS_RECORDS];
01456 int rec_idx[MAX_DNS_RECORDS];
01457 int r, i, j;
01458 int no_records;
01459 unsigned int ttl;
01460
01461
01462 no_records=0;
01463 rec[0].e=0;
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484 for(l=rd, i=0; l && (i<MAX_DNS_RECORDS); l=l->next, i++){
01485 for (r=0; r<no_records; r++){
01486 if ((l->type==rec[r].rd->type) &&
01487 (l->name_len==rec[r].rd->name_len)
01488 && (strncasecmp(l->name, rec[r].rd->name, l->name_len)==0)){
01489
01490 goto found;
01491 }
01492 }
01493
01494 if (no_records<MAX_DNS_RECORDS){
01495 rec[r].rd=l;
01496 rec[r].e=0;
01497 rec[r].size=ROUND_POINTER(sizeof(struct dns_hash_entry)+
01498 rec[r].rd->name_len-1+1);
01499 no_records++;
01500 }else{
01501 LOG(L_ERR, "ERROR: dns_cache_mk_rd_entry2: too many records: %d\n",
01502 no_records);
01503
01504 continue;
01505 }
01506 found:
01507 rec_idx[i]=r;
01508 switch(l->type){
01509 case T_A:
01510
01511 rec[r].size+=ROUND_POINTER(sizeof(struct dns_rr)+
01512 sizeof(struct a_rdata));
01513 break;
01514 case T_AAAA:
01515
01516 rec[r].size+=ROUND_POINTER(sizeof(struct dns_rr)+
01517 sizeof(struct aaaa_rdata));
01518 break;
01519 case T_SRV:
01520
01521 rec[r].size+=ROUND_POINTER(ROUND_SHORT(sizeof(struct dns_rr))+
01522 SRV_RDATA_SIZE(*(struct srv_rdata*)l->rdata));
01523 break;
01524 case T_NAPTR:
01525
01526 rec[r].size+=ROUND_POINTER(ROUND_POINTER(
01527 sizeof(struct dns_rr))+
01528 NAPTR_RDATA_SIZE(*(struct naptr_rdata*)l->rdata));
01529 break;
01530 case T_CNAME:
01531
01532 rec[r].size+=ROUND_POINTER(sizeof(struct dns_rr)+
01533 CNAME_RDATA_SIZE(*(struct cname_rdata*)l->rdata));
01534 break;
01535 case T_TXT:
01536
01537 rec[r].size+=ROUND_POINTER(ROUND_POINTER(
01538 sizeof(struct dns_rr))+
01539 TXT_RDATA_SIZE(*(struct txt_rdata*)l->rdata));
01540 break;
01541 case T_EBL:
01542
01543 rec[r].size+=ROUND_POINTER(ROUND_POINTER(
01544 sizeof(struct dns_rr))+
01545 EBL_RDATA_SIZE(*(struct ebl_rdata*)l->rdata));
01546 break;
01547 case T_PTR:
01548
01549 rec[r].size+=ROUND_POINTER(sizeof(struct dns_rr)+
01550 PTR_RDATA_SIZE(*(struct ptr_rdata*)l->rdata));
01551 break;
01552 default:
01553 LOG(L_CRIT, "BUG: dns_cache_mk_rd_entry: type %d not "
01554 "supported\n", l->type);
01555 }
01556 }
01557
01558 now=get_ticks_raw();
01559
01560 for (r=0; r<no_records; r++){
01561 rec[r].e=shm_malloc(rec[r].size);
01562 if (rec[r].e==0){
01563 LOG(L_ERR, "ERROR: dns_cache_mk_rd_entry: out of memory\n");
01564 goto error;
01565 }
01566 memset(rec[r].e, 0, rec[r].size);
01567 rec[r].e->total_size=rec[r].size;
01568 rec[r].e->name_len=rec[r].rd->name_len;
01569 rec[r].e->type=rec[r].rd->type;
01570 rec[r].e->last_used=now;
01571
01572 memcpy(rec[r].e->name, rec[r].rd->name, rec[r].rd->name_len);
01573 rec[r].e->rr_lst=(struct dns_rr*)((char*)rec[r].e+
01574 ROUND_POINTER(sizeof(struct dns_hash_entry)+rec[r].e->name_len
01575 -1+1));
01576 rec[r].tail_rr=&(rec[r].e->rr_lst);
01577 rec[r].rr=rec[r].e->rr_lst;
01578 rec[r].max_ttl=0;
01579
01580 if (r==0){
01581 clist_init(rec[r].e, next, prev);
01582 }else{
01583 clist_append(rec[0].e, rec[r].e, next, prev);
01584 }
01585 }
01586
01587 for(l=rd, i=0; l && (i<MAX_DNS_RECORDS); l=l->next, i++){
01588 r=rec_idx[i];
01589 ttl=FIX_TTL(l->ttl);
01590 switch(l->type){
01591 case T_A:
01592 rec[r].rr->expire=now+S_TO_TICKS(ttl);
01593 rec[r].max_ttl=MAX(rec[r].max_ttl, ttl);
01594 rec[r].rr->rdata=(void*)((char*)rec[r].rr+
01595 sizeof(struct dns_rr));
01596 memcpy(rec[r].rr->rdata, l->rdata, sizeof(struct a_rdata));
01597 rec[r].rr->next=(void*)((char*)rec[r].rr+
01598 ROUND_POINTER(sizeof(struct dns_rr)+
01599 sizeof(struct a_rdata)));
01600 rec[r].tail_rr=&(rec[r].rr->next);
01601 rec[r].rr=rec[r].rr->next;
01602 break;
01603 case T_AAAA:
01604 rec[r].rr->expire=now+S_TO_TICKS(ttl);
01605 rec[r].max_ttl=MAX(rec[r].max_ttl, ttl);
01606 rec[r].rr->rdata=(void*)((char*)rec[r].rr+
01607 sizeof(struct dns_rr));
01608 memcpy(rec[r].rr->rdata, l->rdata, sizeof(struct aaaa_rdata));
01609 rec[r].rr->next=(void*)((char*)rec[r].rr+
01610 ROUND_POINTER(sizeof(struct dns_rr)+
01611 sizeof(struct aaaa_rdata)));
01612 rec[r].tail_rr=&(rec[r].rr->next);
01613 rec[r].rr=rec[r].rr->next;
01614 break;
01615 case T_SRV:
01616 rec[r].rr->expire=now+S_TO_TICKS(ttl);
01617 rec[r].max_ttl=MAX(rec[r].max_ttl, ttl);
01618 rec[r].rr->rdata=(void*)((char*)rec[r].rr+
01619 ROUND_SHORT(sizeof(struct dns_rr)));
01620
01621 memcpy(rec[r].rr->rdata, l->rdata,
01622 SRV_RDATA_SIZE(*(struct srv_rdata*)l->rdata) );
01623 rec[r].rr->next=(void*)((char*)rec[r].rr+
01624 ROUND_POINTER( ROUND_SHORT(sizeof(struct dns_rr))+
01625 SRV_RDATA_SIZE(
01626 *(struct srv_rdata*)l->rdata)));
01627 rec[r].tail_rr=&(rec[r].rr->next);
01628 rec[r].rr=rec[r].rr->next;
01629 break;
01630 case T_NAPTR:
01631 rec[r].rr->expire=now+S_TO_TICKS(ttl);
01632 rec[r].max_ttl=MAX(rec[r].max_ttl, ttl);
01633 rec[r].rr->rdata=(void*)((char*)rec[r].rr+
01634 ROUND_POINTER(sizeof(struct dns_rr)));
01635
01636 memcpy(rec[r].rr->rdata, l->rdata,
01637 NAPTR_RDATA_SIZE(*(struct naptr_rdata*)l->rdata) );
01638
01639 ((struct naptr_rdata*)rec[r].rr->rdata)->flags=
01640 translate_pointer((char*)rec[r].rr->rdata, (char*)l->rdata,
01641 (((struct naptr_rdata*)l->rdata)->flags));
01642 ((struct naptr_rdata*)rec[r].rr->rdata)->services=
01643 translate_pointer((char*)rec[r].rr->rdata, (char*)l->rdata,
01644 (((struct naptr_rdata*)l->rdata)->services));
01645 ((struct naptr_rdata*)rec[r].rr->rdata)->regexp=
01646 translate_pointer((char*)rec[r].rr->rdata, (char*)l->rdata,
01647 (((struct naptr_rdata*)l->rdata)->regexp));
01648 ((struct naptr_rdata*)rec[r].rr->rdata)->repl=
01649 translate_pointer((char*)rec[r].rr->rdata, (char*)l->rdata,
01650 (((struct naptr_rdata*)l->rdata)->repl));
01651 rec[r].rr->next=(void*)((char*)rec[r].rr+
01652 ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
01653 NAPTR_RDATA_SIZE(
01654 *(struct naptr_rdata*)l->rdata)));
01655 rec[r].tail_rr=&(rec[r].rr->next);
01656 rec[r].rr=rec[r].rr->next;
01657 break;
01658 case T_CNAME:
01659 rec[r].rr->expire=now+S_TO_TICKS(ttl);
01660 rec[r].max_ttl=MAX(rec[r].max_ttl, ttl);
01661 rec[r].rr->rdata=(void*)((char*)rec[r].rr
01662 +sizeof(struct dns_rr));
01663 memcpy(rec[r].rr->rdata, l->rdata,
01664 CNAME_RDATA_SIZE(*(struct cname_rdata*)l->rdata));
01665 rec[r].rr->next=(void*)((char*)rec[r].rr+
01666 ROUND_POINTER(sizeof(struct dns_rr)+
01667 CNAME_RDATA_SIZE(*(struct cname_rdata*)l->rdata)));
01668 rec[r].tail_rr=&(rec[r].rr->next);
01669 rec[r].rr=rec[r].rr->next;
01670 break;
01671 case T_TXT:
01672 rec[r].rr->expire=now+S_TO_TICKS(ttl);
01673 rec[r].max_ttl=MAX(rec[r].max_ttl, ttl);
01674 rec[r].rr->rdata=(void*)((char*)rec[r].rr+
01675 ROUND_POINTER(sizeof(struct dns_rr)));
01676 memcpy(rec[r].rr->rdata, l->rdata,
01677 TXT_RDATA_SIZE(*(struct txt_rdata*)l->rdata));
01678
01679 for (j=0; j<((struct txt_rdata*)l->rdata)->cstr_no; j++){
01680 ((struct txt_rdata*)rec[r].rr->rdata)->txt[j].cstr=
01681 translate_pointer((char*)rec[r].rr->rdata,
01682 (char*)l->rdata,
01683 ((struct txt_rdata*)l->rdata)->txt[j].cstr);
01684 }
01685 rec[r].rr->next=(void*)((char*)rec[r].rr+
01686 ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
01687 TXT_RDATA_SIZE(*(struct txt_rdata*)l->rdata)));
01688 rec[r].tail_rr=&(rec[r].rr->next);
01689 rec[r].rr=rec[r].rr->next;
01690 break;
01691 case T_EBL:
01692 rec[r].rr->expire=now+S_TO_TICKS(ttl);
01693 rec[r].max_ttl=MAX(rec[r].max_ttl, ttl);
01694 rec[r].rr->rdata=(void*)((char*)rec[r].rr+
01695 ROUND_POINTER(sizeof(struct dns_rr)));
01696 memcpy(rec[r].rr->rdata, l->rdata,
01697 EBL_RDATA_SIZE(*(struct ebl_rdata*)l->rdata));
01698
01699 ((struct ebl_rdata*)rec[r].rr->rdata)->separator=
01700 translate_pointer((char*)rec[r].rr->rdata,
01701 (char*)l->rdata,
01702 ((struct ebl_rdata*)l->rdata)->separator);
01703 ((struct ebl_rdata*)rec[r].rr->rdata)->apex=
01704 translate_pointer((char*)rec[r].rr->rdata,
01705 (char*)l->rdata,
01706 ((struct ebl_rdata*)l->rdata)->apex);
01707 rec[r].rr->next=(void*)((char*)rec[r].rr+
01708 ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
01709 EBL_RDATA_SIZE(*(struct ebl_rdata*)l->rdata)));
01710 rec[r].tail_rr=&(rec[r].rr->next);
01711 rec[r].rr=rec[r].rr->next;
01712 break;
01713 case T_PTR:
01714 rec[r].rr->expire=now+S_TO_TICKS(ttl);
01715 rec[r].max_ttl=MAX(rec[r].max_ttl, ttl);
01716 rec[r].rr->rdata=(void*)((char*)rec[r].rr
01717 +sizeof(struct dns_rr));
01718 memcpy(rec[r].rr->rdata, l->rdata,
01719 PTR_RDATA_SIZE(*(struct ptr_rdata*)l->rdata));
01720 rec[r].rr->next=(void*)((char*)rec[r].rr+
01721 ROUND_POINTER(sizeof(struct dns_rr)+
01722 PTR_RDATA_SIZE(*(struct ptr_rdata*)l->rdata)));
01723 rec[r].tail_rr=&(rec[r].rr->next);
01724 rec[r].rr=rec[r].rr->next;
01725 break;
01726 default:
01727
01728 ;
01729 }
01730 }
01731 for (r=0; r<no_records; r++){
01732 *rec[r].tail_rr=0;
01733 rec[r].e->expire=now+S_TO_TICKS(rec[r].max_ttl);
01734 }
01735 return rec[0].e;
01736 error:
01737 for (r=0; r<no_records; r++){
01738 dns_destroy_entry(rec[r].e);
01739 }
01740 return 0;
01741 }
01742
01743
01744
01745 inline static struct dns_hash_entry* dns_get_entry(str* name, int type);
01746
01747
01748 #define CACHE_RELEVANT_RECS_ONLY
01749
01750 #ifdef CACHE_RELEVANT_RECS_ONLY
01751
01752
01753
01754
01755
01756
01757
01758
01759
01760
01761
01762
01763 inline static struct dns_hash_entry* dns_get_related(struct dns_hash_entry* e,
01764 int type,
01765 struct rdata** records)
01766 {
01767 struct dns_hash_entry* ret;
01768 struct dns_hash_entry* l;
01769 struct dns_hash_entry* t;
01770 struct dns_hash_entry* lst_end;
01771 struct dns_rr* rr;
01772 static int cname_chain_len=0;
01773 str tmp;
01774
01775 ret=0;
01776 l=e;
01777 #ifdef DNS_CACHE_DEBUG
01778 DBG("dns_get_related(%p (%.*s, %d), %d, *%p) (%d)\n", e,
01779 e->name_len, e->name, e->type, type, *records, cname_chain_len);
01780 #endif
01781 clist_init(l, next, prev);
01782 if (type==e->type){
01783 ret=e;
01784 switch(e->type){
01785 case T_SRV:
01786 for (rr=e->rr_lst; rr && *records; rr=rr->next){
01787 tmp.s=((struct srv_rdata*)rr->rdata)->name;
01788 tmp.len=((struct srv_rdata*)rr->rdata)->name_len;
01789 if (!(dns_flags&DNS_IPV6_ONLY)){
01790 t=dns_cache_mk_rd_entry(&tmp, T_A, records);
01791 if (t){
01792 if ((t->type==T_CNAME) && *records)
01793 dns_get_related(t, T_A, records);
01794 lst_end=t->prev;
01795 clist_append_sublist(l, t, lst_end, next, prev);
01796 }
01797 }
01798 if (!(dns_flags&DNS_IPV4_ONLY)){
01799 t=dns_cache_mk_rd_entry(&tmp, T_AAAA, records);
01800 if (t){
01801 if ((t->type==T_CNAME) && *records)
01802 dns_get_related(t, T_AAAA, records);
01803 lst_end=t->prev;
01804 clist_append_sublist(l, t, lst_end, next, prev);
01805 }
01806 }
01807 }
01808 break;
01809 #ifdef USE_NAPTR
01810 case T_NAPTR:
01811 #ifdef NAPTR_CACHE_ALL_ARS
01812 if (*records)
01813 dns_cache_mk_rd_entry2(*records);
01814 #else
01815 for (rr=e->rr_lst; rr && *records; rr=rr->next){
01816 if (naptr_get_sip_proto((struct naptr_rdata*)rr->rdata)>0){
01817 tmp.s=((struct naptr_rdata*)rr->rdata)->repl;
01818 tmp.len=((struct naptr_rdata*)rr->rdata)->repl_len;
01819 t=dns_cache_mk_rd_entry(&tmp, T_SRV, records);
01820 if (t){
01821 if (*records)
01822 dns_get_related(t, T_SRV, records);
01823 lst_end=t->prev;
01824 clist_append_sublist(l, t, lst_end, next, prev);
01825 }
01826 }
01827 }
01828 #endif
01829 #endif
01830 break;
01831 default:
01832
01833 break;
01834 }
01835 }else if ((e->type==T_CNAME) && (cname_chain_len<MAX_CNAME_CHAIN)){
01836
01837
01838 tmp.s=((struct cname_rdata*)e->rr_lst->rdata)->name;
01839 tmp.len=((struct cname_rdata*)e->rr_lst->rdata)->name_len;
01840 t=dns_cache_mk_rd_entry(&tmp, type, records);
01841 if (t){
01842 if (*records){
01843 cname_chain_len++;
01844 ret=dns_get_related(t, type, records);
01845 cname_chain_len--;
01846 lst_end=t->prev;
01847 clist_append_sublist(l, t, lst_end, next, prev);
01848 }else{
01849
01850
01851
01852 if (t->type==type)
01853 ret=t;
01854 clist_append(l, t, next, prev);
01855 }
01856 }
01857 }
01858 return ret;
01859 }
01860 #endif
01861
01862
01863
01864
01865
01866
01867
01868
01869 inline static struct dns_hash_entry* dns_cache_do_request(str* name, int type)
01870 {
01871 struct rdata* records;
01872 struct dns_hash_entry* e;
01873 struct dns_hash_entry* l;
01874 struct dns_hash_entry* r;
01875 struct dns_hash_entry* t;
01876 struct ip_addr* ip;
01877 str cname_val;
01878 char name_buf[MAX_DNS_NAME];
01879 struct dns_hash_entry* old;
01880 str rec_name;
01881 int add_record, h, err;
01882
01883 e=0;
01884 l=0;
01885 cname_val.s=0;
01886 old = NULL;
01887
01888 #ifdef USE_DNS_CACHE_STATS
01889 if (dns_cache_stats)
01890 dns_cache_stats[process_no].dns_req_cnt++;
01891 #endif
01892
01893 if (type==T_A){
01894 if ((ip=str2ip(name))!=0){
01895 e=dns_cache_mk_ip_entry(name, ip);
01896 if (likely(e))
01897 atomic_set(&e->refcnt, 1);
01898 goto end;
01899 }
01900 }
01901 #ifdef USE_IPV6
01902 else if (type==T_AAAA){
01903 if ((ip=str2ip6(name))!=0){
01904 e=dns_cache_mk_ip_entry(name, ip);
01905 if (likely(e))
01906 atomic_set(&e->refcnt, 1);
01907 goto end;
01908 }
01909 }
01910 #endif
01911 #ifdef DNS_WATCHDOG_SUPPORT
01912 if (atomic_get(dns_servers_up)==0)
01913 goto end;
01914 #endif
01915 if (name->len>=MAX_DNS_NAME){
01916 LOG(L_ERR, "ERROR: dns_cache_do_request: name too long (%d chars)\n",
01917 name->len);
01918 goto end;
01919 }
01920
01921 memcpy(name_buf, name->s, name->len);
01922 name_buf[name->len]=0;
01923 records=get_record(name_buf, type, RES_AR);
01924 if (records){
01925 #ifdef CACHE_RELEVANT_RECS_ONLY
01926 e=dns_cache_mk_rd_entry(name, type, &records);
01927 if (likely(e)){
01928 l=e;
01929 e=dns_get_related(l, type, &records);
01930
01931
01932 if (likely(e)){
01933 atomic_set(&e->refcnt, 1);
01934
01935 }else{
01936
01937
01938
01939
01940 cname_val.s=
01941 ((struct cname_rdata*)l->prev->rr_lst->rdata)->name;
01942 cname_val.len=
01943 ((struct cname_rdata*)l->prev->rr_lst->rdata)->name_len;
01944 DBG("dns_cache_do_request: cname detected: %.*s (%d)\n",
01945 cname_val.len, cname_val.s, cname_val.len);
01946 }
01947
01948 l->prev->next=0;
01949
01950 LOCK_DNS_HASH();
01951 for (r=l; r; r=t){
01952 t=r->next;
01953
01954 add_record = 1;
01955 if (cfg_get(core, core_cfg, dns_cache_rec_pref) > 0) {
01956
01957
01958 rec_name.s = r->name;
01959 rec_name.len = r->name_len;
01960 old = _dns_hash_find(&rec_name, r->type, &h, &err);
01961 if (old) {
01962 if (old->type != r->type) {
01963
01964 old = NULL;
01965
01966 } else if (old->ent_flags & DNS_FLAG_PERMANENT) {
01967
01968 add_record = 0;
01969
01970 } else if ((old->ent_flags & DNS_FLAG_BAD_NAME) == 0) {
01971
01972
01973 add_record =
01974
01975 ((cfg_get(core, core_cfg, dns_cache_rec_pref) == 2)
01976
01977 || ((cfg_get(core, core_cfg, dns_cache_rec_pref) == 3)
01978 && TICKS_LT(old->expire, r->expire)));
01979 }
01980 }
01981 }
01982 if (add_record) {
01983 dns_cache_add_unsafe(r);
01984 if (atomic_get(&r->refcnt)==0){
01985
01986
01987 dns_destroy_entry(r);
01988 }
01989 if (old) {
01990 _dns_hash_remove(old);
01991 old = NULL;
01992 }
01993 } else {
01994 if (old) {
01995 if (r == e) {
01996
01997 e = old;
01998 atomic_inc(&e->refcnt);
01999 }
02000 old = NULL;
02001 }
02002 dns_destroy_entry(r);
02003 }
02004 }
02005 UNLOCK_DNS_HASH();
02006
02007 if (cname_val.s){
02008 DBG("dns_cache_do_request: dns_get_entry(cname: %.*s (%d))\n",
02009 cname_val.len, cname_val.s, cname_val.len);
02010 e=dns_get_entry(&cname_val, type);
02011 }
02012 }
02013 #else
02014 l=dns_cache_mk_rd_entry2(records);
02015 #endif
02016 free_rdata_list(records);
02017 }else if (cfg_get(core, core_cfg, dns_neg_cache_ttl)){
02018 e=dns_cache_mk_bad_entry(name, type,
02019 cfg_get(core, core_cfg, dns_neg_cache_ttl), DNS_FLAG_BAD_NAME);
02020 if (likely(e)) {
02021 atomic_set(&e->refcnt, 1);
02022 dns_cache_add(e);
02023 }
02024 goto end;
02025 }
02026 #ifndef CACHE_RELEVANT_RECS_ONLY
02027 if (l){
02028
02029
02030 l->prev->next=0;
02031
02032 LOCK_DNS_HASH();
02033 for (r=l; r; r=t){
02034 t=r->next;
02035 if (e==0){
02036 if (r->type==T_CNAME){
02037 if ((r->name_len==name->len) && (r->rr_lst) &&
02038 (strncasecmp(r->name, name->s, name->len)==0)){
02039
02040 cname_val.s=
02041 ((struct cname_rdata*)r->rr_lst->rdata)->name;
02042 cname_val.len=
02043 ((struct cname_rdata*)r->rr_lst->rdata)->name_len;
02044 name=&cname_val;
02045 }
02046 }else if ((r->type==type) && (r->name_len==name->len) &&
02047 (strncasecmp(r->name, name->s, name->len)==0)){
02048 e=r;
02049 atomic_set(&e->refcnt, 1);
02050
02051 }
02052 }
02053
02054
02055 add_record = 1;
02056 if (cfg_get(core, core_cfg, dns_cache_rec_pref) > 0) {
02057
02058
02059 rec_name.s = r->name;
02060 rec_name.len = r->name_len;
02061 old = _dns_hash_find(&rec_name, r->type, &h, &err);
02062 if (old) {
02063 if (old->type != r->type) {
02064
02065 old = NULL;
02066
02067 } else if (old->ent_flags & DNS_FLAG_PERMANENT) {
02068
02069 add_record = 0;
02070
02071 } else if ((old->ent_flags & DNS_FLAG_BAD_NAME) == 0) {
02072
02073
02074 add_record =
02075
02076 ((cfg_get(core, core_cfg, dns_cache_rec_pref) == 2)
02077
02078 || ((cfg_get(core, core_cfg, dns_cache_rec_pref) == 3)
02079 && TICKS_LT(old->expire, r->expire)));
02080 }
02081 }
02082 }
02083 if (add_record) {
02084 dns_cache_add_unsafe(r);
02085 if (atomic_get(&r->refcnt)==0){
02086
02087
02088 dns_destroy_entry(r);
02089 }
02090 if (old) {
02091 _dns_hash_remove(old);
02092 old = NULL;
02093 }
02094 } else {
02095 if (old) {
02096 if (r == e) {
02097
02098 e = old;
02099 atomic_inc(&e->refcnt);
02100 }
02101 old = NULL;
02102 }
02103 dns_destroy_entry(r);
02104 }
02105 }
02106 UNLOCK_DNS_HASH();
02107 if ((e==0) && (cname_val.s)){
02108
02109
02110 e=dns_get_entry(&cname_val, type);
02111 }
02112 }
02113 #endif
02114 end:
02115 return e;
02116 }
02117
02118
02119
02120
02121
02122
02123
02124 inline static struct dns_hash_entry* dns_get_entry(str* name, int type)
02125 {
02126 int h;
02127 struct dns_hash_entry* e;
02128 str cname_val;
02129 int err;
02130 static int rec_cnt=0;
02131
02132 e=0;
02133 if (rec_cnt>MAX_CNAME_CHAIN){
02134 LOG(L_WARN, "WARNING: dns_get_entry: CNAME chain too long or"
02135 " recursive CNAMEs (\"%.*s\")\n", name->len, name->s);
02136 goto error;
02137 }
02138 rec_cnt++;
02139 e=dns_hash_get(name, type, &h, &err);
02140 #ifdef USE_DNS_CACHE_STATS
02141 if (e) {
02142 if ((e->ent_flags & DNS_FLAG_BAD_NAME) && dns_cache_stats)
02143
02144 dns_cache_stats[process_no].dc_neg_hits_cnt++;
02145 else if (((e->ent_flags & DNS_FLAG_BAD_NAME) == 0)
02146 && dns_cache_stats
02147 )
02148 dns_cache_stats[process_no].dc_hits_cnt++;
02149
02150 if (dns_cache_stats)
02151 dns_cache_stats[process_no].dns_req_cnt++;
02152 }
02153 #endif
02154
02155 if ((e==0) && ((err) || ((e=dns_cache_do_request(name, type))==0))){
02156 goto error;
02157 }else if ((e->type==T_CNAME) && (type!=T_CNAME)){
02158
02159
02160
02161
02162 cname_val.s= ((struct cname_rdata*)e->rr_lst->rdata)->name;
02163 cname_val.len=((struct cname_rdata*)e->rr_lst->rdata)->name_len;
02164 dns_hash_put(e);
02165 if ((e=dns_cache_do_request(&cname_val, type))==0)
02166 goto error;
02167 }
02168
02169 if ((e->rr_lst==0) || (e->ent_flags & DNS_FLAG_BAD_NAME)){
02170
02171 dns_hash_put(e);
02172 e=0;
02173 }
02174 error:
02175 rec_cnt--;
02176 return e;
02177 }
02178
02179
02180
02181
02182
02183
02184
02185
02186
02187
02188
02189
02190
02191
02192
02193
02194
02195
02196
02197
02198
02199
02200
02201
02202 inline static struct dns_rr* dns_entry_get_rr( struct dns_hash_entry* e,
02203 unsigned char* no, ticks_t now)
02204 {
02205 struct dns_rr* rr;
02206 int n;
02207 #ifdef DNS_WATCHDOG_SUPPORT
02208 int servers_up;
02209
02210 servers_up = atomic_get(dns_servers_up);
02211 #endif
02212
02213 for(rr=e->rr_lst, n=0;rr && (n<*no);rr=rr->next, n++);
02214 for(;rr;rr=rr->next){
02215 if (
02216 #ifdef DNS_WATCHDOG_SUPPORT
02217
02218 servers_up &&
02219 #endif
02220 ((e->ent_flags & DNS_FLAG_PERMANENT) == 0) &&
02221 ((s_ticks_t)(now-rr->expire)>=0)
02222 )
02223 continue;
02224
02225 *no=n;
02226 return rr;
02227 }
02228 *no=n;
02229 return 0;
02230 }
02231
02232
02233 #ifdef DNS_SRV_LB
02234
02235 #define srv_reset_tried(p) (*(p)=0)
02236 #define srv_marked(p, i) (*(p)&(1UL<<(i)))
02237 #define srv_mark_tried(p, i) \
02238 do{ \
02239 (*(p)|=(1UL<<(i))); \
02240 }while(0)
02241
02242 #define srv_next_rr(n, f, i) srv_mark_tried(f, i)
02243
02244
02245 inline static unsigned dns_srv_random(unsigned max)
02246 {
02247 return fastrand_max(max);
02248 }
02249
02250
02251
02252
02253
02254
02255
02256
02257
02258
02259
02260
02261
02262
02263
02264
02265
02266
02267
02268
02269
02270
02271
02272
02273
02274
02275
02276
02277
02278 inline static struct dns_rr* dns_srv_get_nxt_rr(struct dns_hash_entry* e,
02279 srv_flags_t* tried,
02280 unsigned char* no, ticks_t now)
02281 {
02282 #define MAX_SRV_GRP_IDX (sizeof(srv_flags_t)*8)
02283 struct dns_rr* rr;
02284 struct dns_rr* start_grp;
02285 int n;
02286 unsigned sum;
02287 unsigned prio;
02288 unsigned rand_w;
02289 int found;
02290 int saved_idx;
02291 int zero_weight;
02292 int i, idx;
02293 struct r_sums_entry{
02294 unsigned r_sum;
02295 struct dns_rr* rr;
02296 }r_sums[MAX_SRV_GRP_IDX];
02297 #ifdef DNS_WATCHDOG_SUPPORT
02298 int servers_up;
02299
02300 servers_up = atomic_get(dns_servers_up);
02301 #endif
02302
02303 rand_w=0;
02304 for(rr=e->rr_lst, n=0;rr && (n<*no);rr=rr->next, n++);
02305
02306 retry:
02307 if (unlikely(rr==0))
02308 goto no_more_rrs;
02309 start_grp=rr;
02310 prio=((struct srv_rdata*)start_grp->rdata)->priority;
02311 sum=0;
02312 saved_idx=-1;
02313 zero_weight = 0;
02314 found=0;
02315 for (idx=0;rr && (prio==((struct srv_rdata*)rr->rdata)->priority) &&
02316 (idx < MAX_SRV_GRP_IDX); idx++, rr=rr->next){
02317 if ((
02318 #ifdef DNS_WATCHDOG_SUPPORT
02319
02320 servers_up &&
02321 #endif
02322 ((e->ent_flags & DNS_FLAG_PERMANENT) == 0) &&
02323 ((s_ticks_t)(now-rr->expire)>=0) ) ||
02324 (srv_marked(tried, idx)) ) {
02325 r_sums[idx].r_sum=0;
02326 r_sums[idx].rr=0;
02327 continue;
02328 }
02329
02330
02331
02332 if ((saved_idx==-1) || (((struct srv_rdata*)rr->rdata)->weight==0)){
02333 saved_idx=idx;
02334 }
02335 zero_weight += (((struct srv_rdata*)rr->rdata)->weight == 0);
02336 sum+=((struct srv_rdata*)rr->rdata)->weight;
02337 r_sums[idx].r_sum=sum;
02338 r_sums[idx].rr=rr;
02339 found++;
02340 }
02341 if (found==0){
02342
02343 n+=idx;
02344 srv_reset_tried(tried);
02345 goto retry;
02346 }else if ((found==1) || (sum==0) ||
02347 (((rand_w=(dns_srv_random(sum-1)+1))==1) && zero_weight &&
02348 (dns_srv_random(DNS_SRV_ZERO_W_CHANCE)==0))){
02349
02350
02351
02352
02353
02354
02355
02356 i=saved_idx;
02357
02358 goto found;
02359 }
02360
02361
02362
02363 for (i=0; (i<idx) && (r_sums[i].r_sum<rand_w); i++);
02364 found:
02365 #ifdef DNS_CACHE_DEBUG
02366 DBG("dns_srv_get_nxt_rr(%p, %lx, %d, %u): selected %d/%d in grp. %d"
02367 " (rand_w=%d, rr=%p p=%d w=%d rsum=%d)\n",
02368 e, (unsigned long)*tried, *no, now, i, idx, n, rand_w, r_sums[i].rr,
02369 ((struct srv_rdata*)r_sums[i].rr->rdata)->priority,
02370 ((struct srv_rdata*)r_sums[i].rr->rdata)->weight, r_sums[i].r_sum);
02371 #endif
02372
02373 *no=n;
02374 srv_mark_tried(tried, i);
02375 return r_sums[i].rr;
02376 no_more_rrs:
02377 *no=n;
02378 return 0;
02379 }
02380 #endif
02381
02382
02383
02384
02385
02386
02387
02388
02389 inline static struct hostent* dns_entry2he(struct dns_hash_entry* e)
02390 {
02391 static struct hostent he;
02392 static char hostname[256];
02393 static char* p_aliases[1];
02394 static char* p_addr[DNS_HE_MAX_ADDR+1];
02395 static char address[16*DNS_HE_MAX_ADDR];
02396 int af, len;
02397 struct dns_rr* rr;
02398 unsigned char rr_no;
02399 ticks_t now;
02400 int i;
02401
02402 switch(e->type){
02403 case T_A:
02404 af=AF_INET;
02405 len=4;
02406 break;
02407 case T_AAAA:
02408 #ifdef USE_IPV6
02409 af=AF_INET6;
02410 len=16;
02411 break;
02412 #else
02413 LOG(L_ERR, "ERROR: dns_entry2he: IPv6 dns cache entry, but "
02414 "IPv6 support disabled at compile time"
02415 " (recompile with -DUSE_IPV6)\n");
02416 return 0;
02417 #endif
02418 default:
02419 LOG(L_CRIT, "BUG: dns_entry2he: wrong entry type %d for %.*s\n",
02420 e->type, e->name_len, e->name);
02421 return 0;
02422 }
02423
02424
02425 rr_no=0;
02426 now=get_ticks_raw();
02427
02428 if (unlikely((s_ticks_t)(now-e->expire)>=0)) now=e->expire-1;
02429 rr=dns_entry_get_rr(e, &rr_no, now);
02430 for(i=0; rr && (i<DNS_HE_MAX_ADDR); i++,
02431 rr=dns_entry_get_rr(e, &rr_no, now)){
02432 p_addr[i]=&address[i*len];
02433 memcpy(p_addr[i], ((struct a_rdata*)rr->rdata)->ip, len);
02434 }
02435 if (i==0){
02436 DBG("DEBUG: dns_entry2he: no good records found (%d) for %.*s (%d)\n",
02437 rr_no, e->name_len, e->name, e->type);
02438 return 0;
02439 }
02440
02441 p_addr[i]=0;
02442 p_aliases[0]=0;
02443 memcpy(hostname, e->name, e->name_len);
02444 hostname[e->name_len]=0;
02445
02446 he.h_addrtype=af;
02447 he.h_length=len;
02448 he.h_addr_list=p_addr;
02449 he.h_aliases=p_aliases;
02450 he.h_name=hostname;
02451
02452 return &he;
02453 }
02454
02455
02456
02457
02458
02459
02460
02461 inline static struct hostent* dns_a_get_he(str* name)
02462 {
02463 struct dns_hash_entry* e;
02464 struct ip_addr* ip;
02465 struct hostent* he;
02466
02467 e=0;
02468 if ((ip=str2ip(name))!=0){
02469 return ip_addr2he(name, ip);
02470 }
02471 if ((e=dns_get_entry(name, T_A))==0)
02472 return 0;
02473
02474 he=dns_entry2he(e);
02475 dns_hash_put(e);
02476 return he;
02477 }
02478
02479
02480 #ifdef USE_IPV6
02481
02482
02483
02484
02485 inline static struct hostent* dns_aaaa_get_he(str* name)
02486 {
02487 struct dns_hash_entry* e;
02488 struct ip_addr* ip;
02489 struct hostent* he;
02490
02491 e=0;
02492 if ((ip=str2ip6(name))!=0){
02493 return ip_addr2he(name, ip);
02494 }
02495 if ((e=dns_get_entry(name, T_AAAA))==0)
02496 return 0;
02497
02498 he=dns_entry2he(e);
02499 dns_hash_put(e);
02500 return he;
02501 }
02502 #endif
02503
02504
02505
02506
02507 inline static int dns_rr2ip(int type, struct dns_rr* rr, struct ip_addr* ip)
02508 {
02509 switch(type){
02510 case T_A:
02511 ip->af=AF_INET;
02512 ip->len=4;
02513 memcpy(ip->u.addr, ((struct a_rdata*)rr->rdata)->ip, 4);
02514 return 0;
02515 break;
02516 case T_AAAA:
02517 #ifdef USE_IPV6
02518 ip->af=AF_INET6;
02519 ip->len=16;
02520 memcpy(ip->u.addr, ((struct aaaa_rdata*)rr->rdata)->ip6, 16);
02521 return 0;
02522 #else
02523 LOG(L_ERR, "ERROR: dns_rr2ip: IPv6 dns rr, but IPv6 support"
02524 "disabled at compile time (recompile with "
02525 "-DUSE_IPV6)\n" );
02526 #endif
02527 break;
02528 }
02529 return -1;
02530 }
02531
02532
02533
02534
02535
02536
02537
02538
02539
02540
02541
02542 struct hostent* dns_get_he(str* name, int flags)
02543 {
02544 #ifdef USE_IPV6
02545 struct hostent* he;
02546
02547 if ((flags&(DNS_IPV6_FIRST|DNS_IPV6_ONLY))){
02548 he=dns_aaaa_get_he(name);
02549 if (he) return he;
02550 }else{
02551 he=dns_a_get_he(name);
02552 if (he) return he;
02553 }
02554 if (flags&DNS_IPV6_FIRST){
02555 he=dns_a_get_he(name);
02556 }else if (!(flags&(DNS_IPV6_ONLY|DNS_IPV4_ONLY))){
02557 he=dns_aaaa_get_he(name);
02558 }
02559 return he;
02560 #else
02561 return dns_a_get_he(name);
02562 #endif
02563 }
02564
02565
02566
02567
02568
02569
02570 struct hostent* dns_srv_get_he(str* name, unsigned short* port, int flags)
02571 {
02572 struct dns_hash_entry* e;
02573 struct dns_rr* rr;
02574 str rr_name;
02575 struct hostent* he;
02576 ticks_t now;
02577 unsigned char rr_no;
02578
02579 rr=0;
02580 he=0;
02581 now=get_ticks_raw();
02582 if ((e=dns_get_entry(name, T_SRV))==0)
02583 goto error;
02584
02585 rr_no=0;
02586 while( (rr=dns_entry_get_rr(e, &rr_no, now))!=0){
02587
02588 rr_name.s=((struct srv_rdata*)rr->rdata)->name;
02589 rr_name.len=((struct srv_rdata*)rr->rdata)->name_len;
02590 if ((he=dns_get_he(&rr_name, flags))!=0){
02591
02592 *port=((struct srv_rdata*)rr->rdata)->port;
02593 goto end;
02594 }
02595 rr_no++;
02596 }
02597
02598 end:
02599 if (e) dns_hash_put(e);
02600 error:
02601 return he;
02602 }
02603
02604
02605
02606 struct hostent* dns_resolvehost(char* name)
02607 {
02608 str host;
02609 struct hostent* ret;
02610 if ((cfg_get(core, core_cfg, use_dns_cache)==0) || (dns_hash==0)){
02611 ret = _resolvehost(name);
02612 if(unlikely(!ret)){
02613
02614 counter_inc(dns_cnts_h.failed_dns_req);
02615 }
02616 return ret;
02617 }
02618 host.s=name;
02619 host.len=strlen(name);
02620 return dns_get_he(&host, dns_flags);
02621 }
02622
02623
02624
02625
02626 #if 0
02627
02628
02629
02630
02631
02632
02633 struct hostent* dns_sip_resolvehost(str* name, unsigned short* port,
02634 char* proto)
02635 {
02636 struct dns_srv_handle h;
02637 struct ip_addr ip;
02638 int ret;
02639
02640 if ((cfg_get(core, core_cfg, use_dns_cache==0)) || (dns_hash==0)){
02641
02642 return _sip_resolvehost(name, port, proto);
02643 }
02644 dns_srv_handle_init(&h);
02645 ret=dns_sip_resolve(&h, name, &ip, port, proto, dns_flags);
02646 dns_srv_handle_put(&h);
02647 if (ret>=0)
02648 return ip_addr2he(name, &ip);
02649 return 0;
02650 }
02651 #endif
02652
02653
02654
02655
02656
02657
02658
02659
02660
02661
02662 struct hostent* dns_srv_sip_resolvehost(str* name, unsigned short* port,
02663 char* proto)
02664 {
02665 struct hostent* he;
02666 struct ip_addr* ip;
02667 static char tmp[MAX_DNS_NAME];
02668 int len;
02669 str srv_name;
02670 char srv_proto;
02671
02672 if ((cfg_get(core, core_cfg, use_dns_cache)==0) || (dns_hash==0)){
02673
02674 return _sip_resolvehost(name, port, proto);
02675 }
02676 len=0;
02677 if (proto){
02678 if (*proto==0)
02679 *proto=srv_proto=PROTO_UDP;
02680 else
02681 srv_proto=*proto;
02682 }else{
02683 srv_proto=PROTO_UDP;
02684 }
02685
02686 if ((port)&&(*port==0)){
02687 *port=(srv_proto==PROTO_TLS)?SIPS_PORT:SIP_PORT;
02688
02689 if ((name->len+SRV_MAX_PREFIX_LEN+1)>MAX_DNS_NAME){
02690 LOG(L_WARN, "WARNING: dns_sip_resolvehost: domain name too long"
02691 " (%d), unable to perform SRV lookup\n", name->len);
02692 }else{
02693
02694 if ( ((ip=str2ip(name))!=0)
02695 #ifdef USE_IPV6
02696 || ((ip=str2ip6(name))!=0)
02697 #endif
02698 ){
02699
02700 return ip_addr2he(name,ip);
02701 }
02702
02703 switch(srv_proto){
02704 case PROTO_NONE:
02705 if (proto)
02706 *proto=PROTO_UDP;
02707
02708 case PROTO_UDP:
02709 memcpy(tmp, SRV_UDP_PREFIX, SRV_UDP_PREFIX_LEN);
02710 memcpy(tmp+SRV_UDP_PREFIX_LEN, name->s, name->len);
02711 tmp[SRV_UDP_PREFIX_LEN + name->len] = '\0';
02712 len=SRV_UDP_PREFIX_LEN + name->len;
02713 break;
02714 case PROTO_TCP:
02715 memcpy(tmp, SRV_TCP_PREFIX, SRV_TCP_PREFIX_LEN);
02716 memcpy(tmp+SRV_TCP_PREFIX_LEN, name->s, name->len);
02717 tmp[SRV_TCP_PREFIX_LEN + name->len] = '\0';
02718 len=SRV_TCP_PREFIX_LEN + name->len;
02719 break;
02720 case PROTO_TLS:
02721 memcpy(tmp, SRV_TLS_PREFIX, SRV_TLS_PREFIX_LEN);
02722 memcpy(tmp+SRV_TLS_PREFIX_LEN, name->s, name->len);
02723 tmp[SRV_TLS_PREFIX_LEN + name->len] = '\0';
02724 len=SRV_TLS_PREFIX_LEN + name->len;
02725 break;
02726 case PROTO_SCTP:
02727 memcpy(tmp, SRV_SCTP_PREFIX, SRV_SCTP_PREFIX_LEN);
02728 memcpy(tmp+SRV_SCTP_PREFIX_LEN, name->s, name->len);
02729 tmp[SRV_SCTP_PREFIX_LEN + name->len] = '\0';
02730 len=SRV_SCTP_PREFIX_LEN + name->len;
02731 break;
02732 default:
02733 LOG(L_CRIT, "BUG: sip_resolvehost: unknown proto %d\n",
02734 (int)srv_proto);
02735 return 0;
02736 }
02737
02738 srv_name.s=tmp;
02739 srv_name.len=len;
02740 if ((he=dns_srv_get_he(&srv_name, port, dns_flags))!=0)
02741 return he;
02742 }
02743 }
02744
02745 if (name->len >= MAX_DNS_NAME) {
02746 LOG(L_ERR, "dns_sip_resolvehost: domain name too long\n");
02747 return 0;
02748 }
02749 he=dns_get_he(name, dns_flags);
02750 return he;
02751 }
02752
02753
02754
02755 #ifdef USE_NAPTR
02756
02757
02758
02759
02760
02761
02762
02763
02764
02765
02766
02767
02768
02769
02770
02771
02772 struct naptr_rdata* dns_naptr_sip_iterate(struct dns_rr* naptr_head,
02773 naptr_bmp_t* tried,
02774 str* srv_name, char* proto)
02775 {
02776 int i, idx;
02777 struct dns_rr* l;
02778 struct naptr_rdata* naptr;
02779 struct naptr_rdata* naptr_saved;
02780 char saved_proto;
02781 char naptr_proto;
02782
02783 idx=0;
02784 naptr_proto=PROTO_NONE;
02785 naptr_saved=0;
02786 saved_proto=0;
02787 i=0;
02788 for(l=naptr_head; l && (i<MAX_NAPTR_RRS); l=l->next){
02789 naptr=(struct naptr_rdata*) l->rdata;
02790 if (naptr==0){
02791 LOG(L_CRIT, "naptr_iterate: BUG: null rdata\n");
02792 goto end;
02793 }
02794
02795 if ((naptr_proto=naptr_get_sip_proto(naptr))<=0) continue;
02796 if (*tried& (1<<i)){
02797 i++;
02798 continue;
02799 }
02800 #ifdef DNS_CACHE_DEBUG
02801 DBG("naptr_iterate: found a valid sip NAPTR rr %.*s,"
02802 " proto %d\n", naptr->repl_len, naptr->repl,
02803 (int)naptr_proto);
02804 #endif
02805 if ((naptr_proto_supported(naptr_proto))){
02806 if (naptr_choose(&naptr_saved, &saved_proto,
02807 naptr, naptr_proto))
02808 idx=i;
02809 }
02810 i++;
02811 }
02812 if (naptr_saved){
02813
02814 #ifdef DNS_CACHE_DEBUG
02815 DBG("naptr_iterate: choosed NAPTR rr %.*s, proto %d"
02816 " tried: 0x%x\n", naptr_saved->repl_len,
02817 naptr_saved->repl, (int)saved_proto, *tried);
02818 #endif
02819 *tried|=1<<idx;
02820 *proto=saved_proto;
02821 srv_name->s=naptr_saved->repl;
02822 srv_name->len=naptr_saved->repl_len;
02823 return naptr_saved;
02824 }
02825 end:
02826 return 0;
02827 }
02828
02829
02830
02831
02832
02833
02834
02835
02836
02837
02838
02839 struct hostent* dns_naptr_sip_resolvehost(str* name, unsigned short* port,
02840 char* proto)
02841 {
02842 struct hostent* he;
02843 struct ip_addr* tmp_ip;
02844 naptr_bmp_t tried_bmp;
02845 struct dns_hash_entry* e;
02846 char n_proto;
02847 str srv_name;
02848
02849 he=0;
02850 if (dns_hash==0){
02851 LOG(L_WARN, "WARNING: dns_sip_resolvehost: called before dns cache"
02852 " initialization\n");
02853 return _sip_resolvehost(name, port, proto);
02854 }
02855 if (proto && port && (*proto==0) && (*port==0)){
02856 *proto=PROTO_UDP;
02857
02858 if ( ((tmp_ip=str2ip(name))!=0)
02859 #ifdef USE_IPV6
02860 || ((tmp_ip=str2ip6(name))!=0)
02861 #endif
02862 ){
02863
02864 #ifdef USE_IPV6
02865 if (((dns_flags&DNS_IPV4_ONLY) && (tmp_ip->af==AF_INET6))||
02866 ((dns_flags&DNS_IPV6_ONLY) && (tmp_ip->af==AF_INET))){
02867 return 0;
02868 }
02869 #endif
02870 *port=SIP_PORT;
02871 return ip_addr2he(name, tmp_ip);
02872 }
02873
02874 if ((e=dns_get_entry(name, T_NAPTR))==0)
02875 goto naptr_not_found;
02876 naptr_iterate_init(&tried_bmp);
02877 while(dns_naptr_sip_iterate(e->rr_lst, &tried_bmp,
02878 &srv_name, &n_proto)){
02879 if ((he=dns_srv_get_he(&srv_name, port, dns_flags))!=0){
02880 #ifdef DNS_CACHE_DEBUG
02881 DBG("dns_naptr_sip_resolvehost(%.*s, %d, %d) srv, ret=%p\n",
02882 name->len, name->s, (int)*port, (int)*proto, he);
02883 #endif
02884 dns_hash_put(e);
02885 *proto=n_proto;
02886 return he;
02887 }
02888 }
02889
02890 dns_hash_put(e);
02891 }
02892 naptr_not_found:
02893 return dns_srv_sip_resolvehost(name, port, proto);
02894 }
02895 #endif
02896
02897
02898
02899
02900
02901
02902
02903
02904
02905
02906
02907 struct hostent* dns_sip_resolvehost(str* name, unsigned short* port,
02908 char* proto)
02909 {
02910 #ifdef USE_NAPTR
02911 if (dns_flags&DNS_TRY_NAPTR)
02912 return dns_naptr_sip_resolvehost(name, port, proto);
02913 #endif
02914 return dns_srv_sip_resolvehost(name, port, proto);
02915 }
02916
02917
02918
02919
02920
02921
02922
02923
02924
02925
02926
02927
02928
02929
02930
02931
02932
02933
02934
02935
02936
02937
02938
02939
02940
02941
02942
02943
02944
02945
02946
02947
02948
02949
02950
02951
02952 inline static int dns_a_resolve( struct dns_hash_entry** e,
02953 unsigned char* rr_no,
02954 str* name,
02955 struct ip_addr* ip)
02956 {
02957 struct dns_rr* rr;
02958 int ret;
02959 ticks_t now;
02960 struct ip_addr* tmp;
02961
02962 rr=0;
02963 ret=-E_DNS_NO_IP;
02964 if (*e==0){
02965
02966 if ((tmp=str2ip(name))!=0){
02967 *ip=*tmp;
02968 *rr_no=0;
02969 return 0;
02970 }
02971 if ((*e=dns_get_entry(name, T_A))==0)
02972 goto error;
02973
02974 *rr_no=0;
02975 ret=-E_DNS_BAD_IP_ENTRY;
02976 }
02977 now=get_ticks_raw();
02978
02979 if (unlikely((s_ticks_t)(now-(*e)->expire)>=0)) now=(*e)->expire-1;
02980 rr=dns_entry_get_rr(*e, rr_no, now);
02981 if (rr){
02982
02983 dns_rr2ip((*e)->type, rr, ip);
02984 ret=0;
02985 }else{
02986 ret=-E_DNS_EOR;
02987 }
02988 error:
02989 DBG("dns_a_resolve(%.*s, %d) returning %d\n",
02990 name->len, name->s, *rr_no, ret);
02991 return ret;
02992 }
02993
02994
02995 #ifdef USE_IPV6
02996
02997
02998
02999
03000
03001 inline static int dns_aaaa_resolve( struct dns_hash_entry** e,
03002 unsigned char* rr_no,
03003 str* name,
03004 struct ip_addr* ip)
03005 {
03006 struct dns_rr* rr;
03007 int ret;
03008 ticks_t now;
03009 struct ip_addr* tmp;
03010
03011 rr=0;
03012 ret=-E_DNS_NO_IP;
03013 if (*e==0){
03014
03015 if ((tmp=str2ip6(name))!=0){
03016 *ip=*tmp;
03017 *rr_no=0;
03018 return 0;
03019 }
03020 if ((*e=dns_get_entry(name, T_AAAA))==0)
03021 goto error;
03022
03023 *rr_no=0;
03024 ret=-E_DNS_BAD_IP_ENTRY;
03025 }
03026 now=get_ticks_raw();
03027
03028 if (unlikely((s_ticks_t)(now-(*e)->expire)>=0)) now=(*e)->expire-1;
03029 rr=dns_entry_get_rr(*e, rr_no, now);
03030 if (rr){
03031
03032 dns_rr2ip((*e)->type, rr, ip);
03033 ret=0;
03034 }else{
03035 ret=-E_DNS_EOR;
03036 }
03037 error:
03038 return ret;
03039 }
03040 #endif
03041
03042
03043
03044
03045
03046
03047
03048
03049
03050
03051
03052
03053 inline static int dns_ip_resolve( struct dns_hash_entry** e,
03054 unsigned char* rr_no,
03055 str* name,
03056 struct ip_addr* ip,
03057 int flags)
03058 {
03059 int ret;
03060 str host;
03061 struct dns_hash_entry* orig;
03062
03063 ret=-E_DNS_NO_IP;
03064 if (*e==0){
03065 #ifdef USE_IPV6
03066 if ((flags&(DNS_IPV6_FIRST|DNS_IPV6_ONLY))){
03067 ret=dns_aaaa_resolve(e, rr_no, name, ip);
03068 if (ret>=0) return ret;
03069 }else{
03070 ret=dns_a_resolve(e, rr_no, name, ip);
03071 if (ret>=0) return ret;
03072 }
03073 if (flags&DNS_IPV6_FIRST){
03074 ret=dns_a_resolve(e, rr_no, name, ip);
03075 }else if (!(flags&(DNS_IPV6_ONLY|DNS_IPV4_ONLY))){
03076 ret=dns_aaaa_resolve(e, rr_no, name, ip);
03077 }
03078 #else
03079 ret=dns_a_resolve(e, rr_no, name, ip);
03080 #endif
03081 }else if ((*e)->type==T_A){
03082
03083
03084
03085 host.s=(*e)->name;
03086 host.len=(*e)->name_len;
03087 ret=dns_a_resolve(e, rr_no, &host, ip);
03088 #ifdef USE_IPV6
03089 if (ret>=0) return ret;
03090 if (!(flags&(DNS_IPV6_ONLY|DNS_IPV6_FIRST|DNS_IPV4_ONLY))){
03091
03092 orig=*e;
03093 *e=0;
03094 *rr_no=0;
03095 ret=dns_aaaa_resolve(e, rr_no, &host, ip);
03096
03097 dns_hash_put(orig);
03098 }
03099 #endif
03100 }else if ((*e)->type==T_AAAA){
03101
03102
03103 host.s=(*e)->name;
03104 host.len=(*e)->name_len;
03105 #ifdef USE_IPV6
03106
03107 ret=dns_aaaa_resolve(e, rr_no, &host, ip);
03108 if (ret>=0) return ret;
03109 if ((flags&DNS_IPV6_FIRST) && !(flags&DNS_IPV6_ONLY)){
03110
03111 orig=*e;
03112 *e=0;
03113 *rr_no=0;
03114 ret=dns_a_resolve(e, rr_no, &host, ip);
03115
03116 dns_hash_put(orig);
03117 }
03118 #else
03119
03120 orig=*e;
03121 *e=0;
03122 *rr_no=0;
03123 ret=dns_a_resolve(e, rr_no, &host, ip);
03124
03125 dns_hash_put(orig);
03126 #endif
03127 }else{
03128 LOG(L_CRIT, "BUG: dns_ip_resolve: invalid record type %d\n",
03129 (*e)->type);
03130 }
03131 return ret;
03132 }
03133
03134
03135
03136
03137
03138
03139
03140
03141
03142
03143
03144
03145
03146
03147
03148 inline static int dns_srv_resolve_nxt(struct dns_hash_entry** e,
03149 #ifdef DNS_SRV_LB
03150 srv_flags_t* tried,
03151 #endif
03152 unsigned char* rr_no,
03153 str* name, str* host, unsigned short* port)
03154 {
03155 struct dns_rr* rr;
03156 int ret;
03157 ticks_t now;
03158
03159 rr=0;
03160 ret=-E_DNS_NO_SRV;
03161 if (*e==0){
03162 if ((*e=dns_get_entry(name, T_SRV))==0)
03163 goto error;
03164
03165 *rr_no=0;
03166 #ifdef DNS_SRV_LB
03167 if (tried)
03168 srv_reset_tried(tried);
03169 #endif
03170 ret=-E_DNS_BAD_SRV_ENTRY;
03171 }
03172 now=get_ticks_raw();
03173
03174 if (unlikely((s_ticks_t)(now-(*e)->expire)>=0)) now=(*e)->expire-1;
03175 #ifdef DNS_SRV_LB
03176 if (tried){
03177 rr=dns_srv_get_nxt_rr(*e, tried, rr_no, now);
03178 }else
03179 #endif
03180 {
03181 rr=dns_entry_get_rr(*e, rr_no, now);
03182 (*rr_no)++;
03183 }
03184 if (rr){
03185 host->s=((struct srv_rdata*)rr->rdata)->name;
03186 host->len=((struct srv_rdata*)rr->rdata)->name_len;
03187 *port=((struct srv_rdata*)rr->rdata)->port;
03188 ret=0;
03189 }else{
03190 ret=-E_DNS_EOR;
03191 }
03192 error:
03193 return ret;
03194 }
03195
03196
03197
03198
03199
03200
03201
03202
03203
03204 inline static int dns_srv_resolve_ip(struct dns_srv_handle* h,
03205 str* name, struct ip_addr* ip, unsigned short* port,
03206 int flags)
03207 {
03208 int ret;
03209 str host;
03210
03211 host.len=0;
03212 host.s=0;
03213 do{
03214 if (h->a==0){
03215 #ifdef DNS_SRV_LB
03216 if ((ret=dns_srv_resolve_nxt(&h->srv,
03217 (flags & DNS_SRV_RR_LB)?&h->srv_tried_rrs:0,
03218 &h->srv_no,
03219 name, &host, port))<0)
03220 goto error;
03221 #else
03222 if ((ret=dns_srv_resolve_nxt(&h->srv, &h->srv_no,
03223 name, &host, port))<0)
03224 goto error;
03225 #endif
03226 h->port=*port;
03227 }else{
03228 *port=h->port;
03229 }
03230 if ((ret=dns_ip_resolve(&h->a, &h->ip_no, &host, ip, flags))<0){
03231
03232 if (h->a){
03233 dns_hash_put(h->a);
03234 h->a=0;
03235 }
03236 }else if (h->a==0){
03237
03238 }
03239 }while(ret<0);
03240 error:
03241 #ifdef DNS_CACHE_DEBUG
03242 DBG("dns_srv_resolve_ip(\"%.*s\", %d, %d), ret=%d, ip=%s\n",
03243 name->len, name->s, h->srv_no, h->ip_no, ret,
03244 ip?ZSW(ip_addr2a(ip)):"");
03245 #endif
03246 return ret;
03247 }
03248
03249
03250
03251
03252
03253
03254
03255
03256
03257
03258
03259
03260
03261 inline static int dns_srv_sip_resolve(struct dns_srv_handle* h, str* name,
03262 struct ip_addr* ip, unsigned short* port, char* proto,
03263 int flags)
03264 {
03265 static char tmp[MAX_DNS_NAME];
03266 int len;
03267 str srv_name;
03268 struct ip_addr* tmp_ip;
03269 int ret;
03270 struct hostent* he;
03271 char srv_proto;
03272
03273 if (dns_hash==0){
03274 LOG(L_WARN, "WARNING: dns_sip_resolve: called before dns cache"
03275 " initialization\n");
03276 h->srv=h->a=0;
03277 he=_sip_resolvehost(name, port, proto);
03278 if (he){
03279 hostent2ip_addr(ip, he, 0);
03280 return 0;
03281 }
03282 return -E_DNS_NO_SRV;
03283 }
03284 len=0;
03285 if ((h->srv==0) && (h->a==0)){
03286 if (proto){
03287 if (*proto==0)
03288 *proto=srv_proto=PROTO_UDP;
03289 else
03290 srv_proto=*proto;
03291 }else{
03292 srv_proto=PROTO_UDP;
03293 }
03294 h->port=(srv_proto==PROTO_TLS)?SIPS_PORT:SIP_PORT;
03295
03296 h->proto=srv_proto;
03297 if (port){
03298 if (*port==0){
03299
03300
03301 if ((name->len+SRV_MAX_PREFIX_LEN+1)>MAX_DNS_NAME){
03302 LOG(L_WARN, "WARNING: dns_sip_resolvehost: domain name too"
03303 " long (%d), unable to perform SRV lookup\n",
03304 name->len);
03305 }else{
03306
03307 if ( ((tmp_ip=str2ip(name))!=0)
03308 #ifdef USE_IPV6
03309 || ((tmp_ip=str2ip6(name))!=0)
03310 #endif
03311 ){
03312
03313 #ifdef USE_IPV6
03314 if (((flags&DNS_IPV4_ONLY) && (tmp_ip->af==AF_INET6))||
03315 ((flags&DNS_IPV6_ONLY) && (tmp_ip->af==AF_INET))){
03316 return -E_DNS_AF_MISMATCH;
03317 }
03318 #endif
03319 *ip=*tmp_ip;
03320 *port=h->port;
03321
03322 return 0;
03323 }
03324
03325 switch(srv_proto){
03326 case PROTO_NONE:
03327 if (proto)
03328 *proto=PROTO_UDP;
03329
03330 case PROTO_UDP:
03331 memcpy(tmp, SRV_UDP_PREFIX, SRV_UDP_PREFIX_LEN);
03332 memcpy(tmp+SRV_UDP_PREFIX_LEN, name->s, name->len);
03333 tmp[SRV_UDP_PREFIX_LEN + name->len] = '\0';
03334 len=SRV_UDP_PREFIX_LEN + name->len;
03335 break;
03336 case PROTO_TCP:
03337 memcpy(tmp, SRV_TCP_PREFIX, SRV_TCP_PREFIX_LEN);
03338 memcpy(tmp+SRV_TCP_PREFIX_LEN, name->s, name->len);
03339 tmp[SRV_TCP_PREFIX_LEN + name->len] = '\0';
03340 len=SRV_TCP_PREFIX_LEN + name->len;
03341 break;
03342 case PROTO_TLS:
03343 memcpy(tmp, SRV_TLS_PREFIX, SRV_TLS_PREFIX_LEN);
03344 memcpy(tmp+SRV_TLS_PREFIX_LEN, name->s, name->len);
03345 tmp[SRV_TLS_PREFIX_LEN + name->len] = '\0';
03346 len=SRV_TLS_PREFIX_LEN + name->len;
03347 break;
03348 case PROTO_SCTP:
03349 memcpy(tmp, SRV_SCTP_PREFIX, SRV_SCTP_PREFIX_LEN);
03350 memcpy(tmp+SRV_SCTP_PREFIX_LEN, name->s, name->len);
03351 tmp[SRV_SCTP_PREFIX_LEN + name->len] = '\0';
03352 len=SRV_SCTP_PREFIX_LEN + name->len;
03353 break;
03354 default:
03355 LOG(L_CRIT, "BUG: sip_resolvehost: "
03356 "unknown proto %d\n", (int)srv_proto);
03357 return -E_DNS_CRITICAL;
03358 }
03359 srv_name.s=tmp;
03360 srv_name.len=len;
03361 if ((ret=dns_srv_resolve_ip(h, &srv_name, ip,
03362 port, flags))>=0)
03363 {
03364 #ifdef DNS_CACHE_DEBUG
03365 DBG("dns_sip_resolve(%.*s, %d, %d), srv0, ret=%d\n",
03366 name->len, name->s, h->srv_no, h->ip_no, ret);
03367 #endif
03368
03369 return ret;
03370 }
03371 }
03372 }else{
03373 h->port=*port;
03374
03375 }
03376 }
03377 }else if (h->srv){
03378 srv_name.s=h->srv->name;
03379 srv_name.len=h->srv->name_len;
03380
03381 ret=dns_srv_resolve_ip(h, &srv_name, ip, port, flags);
03382 if (proto)
03383 *proto=h->proto;
03384 DBG("dns_sip_resolve(%.*s, %d, %d), srv, ret=%d\n",
03385 name->len, name->s, h->srv_no, h->ip_no, ret);
03386 return ret;
03387 }
03388
03389 if (name->len >= MAX_DNS_NAME) {
03390 LOG(L_ERR, "dns_sip_resolve: domain name too long\n");
03391 return -E_DNS_NAME_TOO_LONG;
03392 }
03393 ret=dns_ip_resolve(&h->a, &h->ip_no, name, ip, flags);
03394 if (port)
03395 *port=h->port;
03396 if (proto)
03397 *proto=h->proto;
03398 #ifdef DNS_CACHE_DEBUG
03399 DBG("dns_sip_resolve(%.*s, %d, %d), ip, ret=%d\n",
03400 name->len, name->s, h->srv_no, h->ip_no, ret);
03401 #endif
03402 return ret;
03403 }
03404
03405
03406
03407 #ifdef USE_NAPTR
03408
03409
03410
03411
03412
03413
03414
03415
03416
03417
03418
03419
03420
03421 inline static int dns_naptr_sip_resolve(struct dns_srv_handle* h, str* name,
03422 struct ip_addr* ip, unsigned short* port, char* proto,
03423 int flags)
03424 {
03425 struct hostent* he;
03426 struct ip_addr* tmp_ip;
03427 naptr_bmp_t tried_bmp;
03428 struct dns_hash_entry* e;
03429 char n_proto;
03430 str srv_name;
03431 int ret;
03432
03433 ret=-E_DNS_NO_NAPTR;
03434 if (dns_hash==0){
03435 LOG(L_WARN, "WARNING: dns_sip_resolve: called before dns cache"
03436 " initialization\n");
03437 h->srv=h->a=0;
03438 he=_sip_resolvehost(name, port, proto);
03439 if (he){
03440 hostent2ip_addr(ip, he, 0);
03441 return 0;
03442 }
03443 return -E_DNS_NO_NAPTR;
03444 }
03445 if (((h->srv==0) && (h->a==0)) &&
03446 proto && port && (*proto==0) && (*port==0)){
03447 *proto=PROTO_UDP;
03448
03449
03450 if ( ((tmp_ip=str2ip(name))!=0)
03451 #ifdef USE_IPV6
03452 || ((tmp_ip=str2ip6(name))!=0)
03453 #endif
03454 ){
03455
03456 #ifdef USE_IPV6
03457 if (((flags&DNS_IPV4_ONLY) && (tmp_ip->af==AF_INET6))||
03458 ((flags&DNS_IPV6_ONLY) && (tmp_ip->af==AF_INET))){
03459 return -E_DNS_AF_MISMATCH;
03460 }
03461 #endif
03462 *ip=*tmp_ip;
03463 h->port=SIP_PORT;
03464 h->proto=*proto;
03465 *port=h->port;
03466 return 0;
03467 }
03468
03469 if ((e=dns_get_entry(name, T_NAPTR))==0)
03470 goto naptr_not_found;
03471 naptr_iterate_init(&tried_bmp);
03472 while(dns_naptr_sip_iterate(e->rr_lst, &tried_bmp,
03473 &srv_name, &n_proto)){
03474 dns_srv_handle_init(h);
03475
03476 if ((ret=dns_srv_resolve_ip(h, &srv_name, ip, port, flags))>=0){
03477 #ifdef DNS_CACHE_DEBUG
03478 DBG("dns_naptr_sip_resolve(%.*s, %d, %d), srv0, ret=%d\n",
03479 name->len, name->s, h->srv_no, h->ip_no, ret);
03480 #endif
03481 dns_hash_put(e);
03482 *proto=n_proto;
03483 h->proto=*proto;
03484 return ret;
03485 }
03486 }
03487
03488 dns_hash_put(e);
03489 dns_srv_handle_init(h);
03490
03491 }
03492 naptr_not_found:
03493 return dns_srv_sip_resolve(h, name, ip, port, proto, flags);
03494 }
03495 #endif
03496
03497
03498
03499
03500
03501
03502
03503
03504
03505
03506
03507
03508
03509
03510
03511
03512 int dns_sip_resolve(struct dns_srv_handle* h, str* name,
03513 struct ip_addr* ip, unsigned short* port, char* proto,
03514 int flags)
03515 {
03516 #ifdef USE_NAPTR
03517 if (flags&DNS_TRY_NAPTR)
03518 return dns_naptr_sip_resolve(h, name, ip, port, proto, flags);
03519 #endif
03520 return dns_srv_sip_resolve(h, name, ip, port, proto, flags);
03521 }
03522
03523
03524
03525
03526 inline static int dns_a_get_ip(str* name, struct ip_addr* ip)
03527 {
03528 struct dns_hash_entry* e;
03529 int ret;
03530 unsigned char rr_no;
03531
03532 e=0;
03533 rr_no=0;
03534 ret=dns_a_resolve(&e, &rr_no, name, ip);
03535 if (e) dns_hash_put(e);
03536 return ret;
03537 }
03538
03539
03540 #ifdef USE_IPV6
03541 inline static int dns_aaaa_get_ip(str* name, struct ip_addr* ip)
03542 {
03543 struct dns_hash_entry* e;
03544 int ret;
03545 unsigned char rr_no;
03546
03547 e=0;
03548 rr_no=0;
03549 ret=dns_aaaa_resolve(&e, &rr_no, name, ip);
03550 if (e) dns_hash_put(e);
03551 return ret;
03552 }
03553 #endif
03554
03555
03556
03557
03558
03559
03560
03561
03562
03563
03564 int dns_get_ip(str* name, struct ip_addr* ip, int flags)
03565 {
03566 int ret;
03567 struct dns_hash_entry* e;
03568 unsigned char rr_no;
03569
03570 e=0;
03571 rr_no=0;
03572 ret=dns_ip_resolve(&e, &rr_no, name, ip, flags);
03573 if (e)
03574 dns_hash_put(e);
03575 return ret;
03576 }
03577
03578
03579
03580
03581 int dns_srv_get_ip(str* name, struct ip_addr* ip, unsigned short* port,
03582 int flags)
03583 {
03584 int ret;
03585 struct dns_srv_handle h;
03586
03587 dns_srv_handle_init(&h);
03588 ret=dns_srv_resolve_ip(&h, name, ip, port, flags);
03589 dns_srv_handle_put(&h);
03590 return ret;
03591 }
03592
03593
03594 #ifdef DNS_WATCHDOG_SUPPORT
03595
03596
03597
03598
03599 void dns_set_server_state(int state)
03600 {
03601 atomic_set(dns_servers_up, state);
03602 }
03603
03604
03605 int dns_get_server_state(void)
03606 {
03607 return atomic_get(dns_servers_up);
03608 }
03609 #endif
03610
03611
03612 void dns_cache_mem_info(rpc_t* rpc, void* ctx)
03613 {
03614 if (!cfg_get(core, core_cfg, use_dns_cache)){
03615 rpc->fault(ctx, 500, "dns cache support disabled (see use_dns_cache)");
03616 return;
03617 }
03618 rpc->add(ctx, "dd", *dns_cache_mem_used, cfg_get(core, core_cfg, dns_cache_max_mem));
03619 }
03620
03621
03622 void dns_cache_debug(rpc_t* rpc, void* ctx)
03623 {
03624 int h;
03625 struct dns_hash_entry* e;
03626 ticks_t now;
03627
03628 if (!cfg_get(core, core_cfg, use_dns_cache)){
03629 rpc->fault(ctx, 500, "dns cache support disabled (see use_dns_cache)");
03630 return;
03631 }
03632 now=get_ticks_raw();
03633 LOCK_DNS_HASH();
03634 for (h=0; h<DNS_HASH_SIZE; h++){
03635 clist_foreach(&dns_hash[h], e, next){
03636 rpc->add(ctx, "sdddddd",
03637 e->name, e->type, e->total_size, e->refcnt.val,
03638 (s_ticks_t)(e->expire-now)<0?-1:
03639 TICKS_TO_S(e->expire-now),
03640 TICKS_TO_S(now-e->last_used),
03641 e->ent_flags);
03642 }
03643 }
03644 UNLOCK_DNS_HASH();
03645 }
03646
03647
03648 #ifdef USE_DNS_CACHE_STATS
03649 static unsigned long stat_sum(int ivar, int breset)
03650 {
03651 unsigned long isum=0;
03652 int i1=0;
03653
03654 for (; i1 < get_max_procs(); i1++)
03655 switch (ivar) {
03656 case 0:
03657 isum+=dns_cache_stats[i1].dns_req_cnt;
03658 if (breset)
03659 dns_cache_stats[i1].dns_req_cnt=0;
03660 break;
03661 case 1:
03662 isum+=dns_cache_stats[i1].dc_hits_cnt;
03663 if (breset)
03664 dns_cache_stats[i1].dc_hits_cnt=0;
03665 break;
03666 case 2:
03667 isum+=dns_cache_stats[i1].dc_neg_hits_cnt;
03668 if (breset)
03669 dns_cache_stats[i1].dc_neg_hits_cnt=0;
03670 break;
03671 case 3:
03672 isum+=dns_cache_stats[i1].dc_lru_cnt;
03673 if (breset)
03674 dns_cache_stats[i1].dc_lru_cnt=0;
03675 break;
03676 }
03677
03678 return isum;
03679 }
03680
03681
03682 void dns_cache_stats_get(rpc_t* rpc, void* c)
03683 {
03684 char *name=NULL;
03685 void *handle;
03686 int found=0,i=0;
03687 int reset=0;
03688 char* dns_cache_stats_names[] = {
03689 "dns_req_cnt",
03690 "dc_hits_cnt",
03691 "dc_neg_hits_cnt",
03692 "dc_lru_cnt",
03693 NULL
03694 };
03695
03696
03697 if (!cfg_get(core, core_cfg, use_dns_cache)) {
03698 rpc->fault(c, 500, "dns cache support disabled");
03699 return;
03700 }
03701 if (rpc->scan(c, "s", &name) < 0)
03702 return;
03703 if (rpc->scan(c, "d", &reset) < 0)
03704 return;
03705 if (!strcasecmp(name, DNS_CACHE_ALL_STATS)) {
03706
03707 rpc->add(c, "{", &handle);
03708 for (i=0; dns_cache_stats_names[i]; i++)
03709 rpc->struct_add(handle, "d",
03710 dns_cache_stats_names[i],
03711 stat_sum(i, reset));
03712
03713 found=1;
03714 } else {
03715 for (i=0; dns_cache_stats_names[i]; i++)
03716 if (!strcasecmp(dns_cache_stats_names[i], name)) {
03717 rpc->add(c, "{", &handle);
03718 rpc->struct_add(handle, "d",
03719 dns_cache_stats_names[i],
03720 stat_sum(i, reset));
03721 found=1;
03722 break;
03723 }
03724 }
03725 if(!found)
03726 rpc->fault(c, 500, "unknown dns cache stat parameter");
03727
03728 return;
03729 }
03730 #endif
03731
03732
03733 void dns_cache_debug_all(rpc_t* rpc, void* ctx)
03734 {
03735 int h;
03736 struct dns_hash_entry* e;
03737 struct dns_rr* rr;
03738 struct ip_addr ip;
03739 int i;
03740 ticks_t now;
03741
03742 if (!cfg_get(core, core_cfg, use_dns_cache)){
03743 rpc->fault(ctx, 500, "dns cache support disabled (see use_dns_cache)");
03744 return;
03745 }
03746 now=get_ticks_raw();
03747 LOCK_DNS_HASH();
03748 for (h=0; h<DNS_HASH_SIZE; h++){
03749 clist_foreach(&dns_hash[h], e, next){
03750 for (i=0, rr=e->rr_lst; rr; i++, rr=rr->next){
03751 rpc->add(ctx, "sddddddd",
03752 e->name, (int)e->type, i, (int)e->total_size,
03753 (int)e->refcnt.val,
03754 (int)(s_ticks_t)(e->expire-now)<0?-1:
03755 TICKS_TO_S(e->expire-now),
03756 (int)TICKS_TO_S(now-e->last_used),
03757 (int)e->ent_flags);
03758 switch(e->type){
03759 case T_A:
03760 case T_AAAA:
03761 if (dns_rr2ip(e->type, rr, &ip)==0){
03762 rpc->add(ctx, "ss", "ip", ip_addr2a(&ip) );
03763 }else{
03764 rpc->add(ctx, "ss", "ip", "<error: bad rr>");
03765 }
03766 break;
03767 case T_SRV:
03768 rpc->add(ctx, "ss", "srv",
03769 ((struct srv_rdata*)(rr->rdata))->name);
03770 break;
03771 case T_NAPTR:
03772 rpc->add(ctx, "ss", "naptr ",
03773 ((struct naptr_rdata*)(rr->rdata))->flags);
03774 break;
03775 case T_CNAME:
03776 rpc->add(ctx, "ss", "cname",
03777 ((struct cname_rdata*)(rr->rdata))->name);
03778 break;
03779 case T_TXT:
03780 rpc->add(ctx, "ss", "txt",
03781 ((struct txt_rdata*)(rr->rdata))->cstr_no?
03782 ((struct txt_rdata*)(rr->rdata))->txt[0].cstr:
03783 "");
03784 break;
03785 case T_EBL:
03786 rpc->add(ctx, "ss", "ebl",
03787 ((struct ebl_rdata*)(rr->rdata))->apex);
03788 break;
03789 case T_PTR:
03790 rpc->add(ctx, "ss", "ptr",
03791 ((struct ptr_rdata*)(rr->rdata))->ptrdname);
03792 break;
03793 default:
03794 rpc->add(ctx, "ss", "unknown", "?");
03795 }
03796 rpc->add(ctx, "d",
03797 (int)(s_ticks_t)(rr->expire-now)<0?-1:
03798 TICKS_TO_S(rr->expire-now));
03799 }
03800 }
03801 }
03802 UNLOCK_DNS_HASH();
03803 }
03804
03805
03806 static char *print_type(unsigned short type)
03807 {
03808 switch (type) {
03809 case T_A:
03810 return "A";
03811 case T_AAAA:
03812 return "AAAA";
03813 case T_SRV:
03814 return "SRV";
03815 case T_NAPTR:
03816 return "NAPTR";
03817 case T_CNAME:
03818 return "CNAME";
03819 case T_TXT:
03820 return "TXT";
03821 case T_EBL:
03822 return "EBL";
03823 case T_PTR:
03824 return "PTR";
03825 default:
03826 return "unknown";
03827 }
03828 }
03829
03830
03835 static int dns_get_type(str* s)
03836 {
03837 char *t;
03838 int len;
03839
03840 t=s->s;
03841 len=s->len;
03842
03843 if ((len>2) && (t[0]=='T' || t[0]=='t') && (t[1]=='_')){
03844 t+=2;
03845 len-=2;
03846 }
03847 switch(len){
03848 case 1:
03849 if (t[0]=='A' || t[0]=='a')
03850 return T_A;
03851 break;
03852 case 4:
03853 if (strncasecmp(t, "AAAA", len)==0)
03854 return T_AAAA;
03855 break;
03856 case 3:
03857 if (strncasecmp(t, "SRV", len)==0)
03858 return T_SRV;
03859 else if (strncasecmp(t, "TXT", len)==0)
03860 return T_TXT;
03861 else if (strncasecmp(t, "EBL", len)==0)
03862 return T_EBL;
03863 else if (strncasecmp(t, "PTR", len)==0)
03864 return T_PTR;
03865 break;
03866 case 5:
03867 if (strncasecmp(t, "NAPTR", len)==0)
03868 return T_NAPTR;
03869 else if (strncasecmp(t, "CNAME", len)==0)
03870 return T_CNAME;
03871 break;
03872 }
03873 return -1;
03874 }
03875
03876
03879 void dns_cache_print_entry(rpc_t* rpc, void* ctx, struct dns_hash_entry* e)
03880 {
03881 int expires;
03882 struct dns_rr* rr;
03883 struct ip_addr ip;
03884 ticks_t now;
03885 str s;
03886 int i;
03887
03888 now=get_ticks_raw();
03889 expires = (s_ticks_t)(e->expire-now)<0?-1: TICKS_TO_S(e->expire-now);
03890
03891 rpc->printf(ctx, "%sname: %s", SPACE_FORMAT, e->name);
03892 rpc->printf(ctx, "%stype: %s", SPACE_FORMAT, print_type(e->type));
03893 rpc->printf(ctx, "%ssize (bytes): %d", SPACE_FORMAT,
03894 e->total_size);
03895 rpc->printf(ctx, "%sreference counter: %d", SPACE_FORMAT,
03896 e->refcnt.val);
03897 if (e->ent_flags & DNS_FLAG_PERMANENT) {
03898 rpc->printf(ctx, "%spermanent: yes", SPACE_FORMAT);
03899 } else {
03900 rpc->printf(ctx, "%spermanent: no", SPACE_FORMAT);
03901 rpc->printf(ctx, "%sexpires in (s): %d", SPACE_FORMAT, expires);
03902 }
03903 rpc->printf(ctx, "%slast used (s): %d", SPACE_FORMAT,
03904 TICKS_TO_S(now-e->last_used));
03905 rpc->printf(ctx, "%snegative entry: %s", SPACE_FORMAT,
03906 (e->ent_flags & DNS_FLAG_BAD_NAME) ? "yes" : "no");
03907
03908 for (rr=e->rr_lst; rr; rr=rr->next) {
03909 switch(e->type) {
03910 case T_A:
03911 case T_AAAA:
03912 if (dns_rr2ip(e->type, rr, &ip)==0){
03913 rpc->printf(ctx, "%srr ip: %s", SPACE_FORMAT,
03914 ip_addr2a(&ip) );
03915 }else{
03916 rpc->printf(ctx, "%srr ip: <error: bad rr>",
03917 SPACE_FORMAT);
03918 }
03919 break;
03920 case T_SRV:
03921 rpc->printf(ctx, "%srr name: %s", SPACE_FORMAT,
03922 ((struct srv_rdata*)(rr->rdata))->name);
03923 rpc->printf(ctx, "%srr port: %d", SPACE_FORMAT,
03924 ((struct srv_rdata*)(rr->rdata))->port);
03925 rpc->printf(ctx, "%srr priority: %d", SPACE_FORMAT,
03926 ((struct srv_rdata*)(rr->rdata))->priority);
03927 rpc->printf(ctx, "%srr weight: %d", SPACE_FORMAT,
03928 ((struct srv_rdata*)(rr->rdata))->weight);
03929 break;
03930 case T_NAPTR:
03931 rpc->printf(ctx, "%srr order: %d", SPACE_FORMAT,
03932 ((struct naptr_rdata*)(rr->rdata))->order);
03933 rpc->printf(ctx, "%srr preference: %d", SPACE_FORMAT,
03934 ((struct naptr_rdata*)(rr->rdata))->pref);
03935 s.s = ((struct naptr_rdata*)(rr->rdata))->flags;
03936 s.len = ((struct naptr_rdata*)(rr->rdata))->flags_len;
03937 rpc->printf(ctx, "%srr flags: %.*s", SPACE_FORMAT,
03938 s.len, s.s);
03939 s.s=((struct naptr_rdata*)(rr->rdata))->services;
03940 s.len=((struct naptr_rdata*)(rr->rdata))->services_len;
03941 rpc->printf(ctx, "%srr service: %.*s", SPACE_FORMAT,
03942 s.len, s.s);
03943 s.s = ((struct naptr_rdata*)(rr->rdata))->regexp;
03944 s.len = ((struct naptr_rdata*)(rr->rdata))->regexp_len;
03945 rpc->printf(ctx, "%srr regexp: %.*s", SPACE_FORMAT,
03946 s.len, s.s);
03947 s.s = ((struct naptr_rdata*)(rr->rdata))->repl;
03948 s.len = ((struct naptr_rdata*)(rr->rdata))->repl_len;
03949 rpc->printf(ctx, "%srr replacement: %.*s",
03950 SPACE_FORMAT, s.len, s.s);
03951 break;
03952 case T_CNAME:
03953 rpc->printf(ctx, "%srr name: %s", SPACE_FORMAT,
03954 ((struct cname_rdata*)(rr->rdata))->name);
03955 break;
03956 case T_TXT:
03957 for (i=0; i<((struct txt_rdata*)(rr->rdata))->cstr_no;
03958 i++){
03959 rpc->printf(ctx, "%stxt[%d]: %s", SPACE_FORMAT, i,
03960 ((struct txt_rdata*)(rr->rdata))->txt[i].cstr);
03961 }
03962 break;
03963 case T_EBL:
03964 rpc->printf(ctx, "%srr position: %d", SPACE_FORMAT,
03965 ((struct ebl_rdata*)(rr->rdata))->position);
03966 rpc->printf(ctx, "%srr separator: %s", SPACE_FORMAT,
03967 ((struct ebl_rdata*)(rr->rdata))->separator);
03968 rpc->printf(ctx, "%srr apex: %s", SPACE_FORMAT,
03969 ((struct ebl_rdata*)(rr->rdata))->apex);
03970 break;
03971 case T_PTR:
03972 rpc->printf(ctx, "%srr name: %s", SPACE_FORMAT,
03973 ((struct ptr_rdata*)(rr->rdata))->ptrdname);
03974 break;
03975 default:
03976 rpc->printf(ctx, "%sresource record: unknown",
03977 SPACE_FORMAT);
03978 }
03979 if ((e->ent_flags & DNS_FLAG_PERMANENT) == 0)
03980 rpc->printf(ctx, "%srr expires in (s): %d", SPACE_FORMAT,
03981 (s_ticks_t)(rr->expire-now)<0?-1 :
03982 TICKS_TO_S(rr->expire-now));
03983 }
03984 }
03985
03986
03987
03988
03989 void dns_cache_view(rpc_t* rpc, void* ctx)
03990 {
03991 int h;
03992 struct dns_hash_entry* e;
03993 ticks_t now;
03994
03995 if (!cfg_get(core, core_cfg, use_dns_cache)){
03996 rpc->fault(ctx, 500, "dns cache support disabled (see use_dns_cache)");
03997 return;
03998 }
03999 now=get_ticks_raw();
04000 LOCK_DNS_HASH();
04001 for (h=0; h<DNS_HASH_SIZE; h++){
04002 clist_foreach(&dns_hash[h], e, next){
04003 if (((e->ent_flags & DNS_FLAG_PERMANENT) == 0)
04004 && TICKS_LT(e->expire, now)
04005 ) {
04006 continue;
04007 }
04008 rpc->printf(ctx, "{\n");
04009 dns_cache_print_entry(rpc, ctx, e);
04010 rpc->printf(ctx, "}");
04011 }
04012 }
04013 UNLOCK_DNS_HASH();
04014 }
04015
04016
04017
04018
04019
04020
04021 void dns_cache_flush(int del_permanent)
04022 {
04023 int h;
04024 struct dns_hash_entry* e;
04025 struct dns_hash_entry* tmp;
04026
04027 DBG("dns_cache_flush(): removing elements from the cache\n");
04028 LOCK_DNS_HASH();
04029 for (h=0; h<DNS_HASH_SIZE; h++){
04030 clist_foreach_safe(&dns_hash[h], e, tmp, next){
04031 if (del_permanent || ((e->ent_flags & DNS_FLAG_PERMANENT) == 0))
04032 _dns_hash_remove(e);
04033 }
04034 }
04035 UNLOCK_DNS_HASH();
04036 }
04037
04038
04039 void dns_cache_delete_all(rpc_t* rpc, void* ctx)
04040 {
04041 if (!cfg_get(core, core_cfg, use_dns_cache)){
04042 rpc->fault(ctx, 500, "dns cache support disabled (see use_dns_cache)");
04043 return;
04044 }
04045 dns_cache_flush(0);
04046 }
04047
04048
04049
04050 void dns_cache_delete_all_force(rpc_t* rpc, void* ctx)
04051 {
04052 if (!cfg_get(core, core_cfg, use_dns_cache)){
04053 rpc->fault(ctx, 500, "dns cache support disabled (see use_dns_cache)");
04054 return;
04055 }
04056 dns_cache_flush(1);
04057 }
04058
04059
04060
04061
04062
04063 static struct dns_hash_entry *dns_cache_clone_entry(struct dns_hash_entry *e,
04064 int rdata_size,
04065 int ttl,
04066 struct dns_rr **_new_rr)
04067 {
04068 struct dns_hash_entry *new;
04069 struct dns_rr *rr, *last_rr, *new_rr;
04070 int size, rounded_size, rr_size;
04071 ticks_t now;
04072 int i;
04073
04074 now=get_ticks_raw();
04075 size = e->total_size;
04076 if (rdata_size) {
04077
04078 rounded_size = ROUND_POINTER(size);
04079
04080 switch (e->type) {
04081 case T_A:
04082 case T_AAAA:
04083 case T_CNAME:
04084 rr_size = sizeof(struct dns_rr);
04085 break;
04086 case T_SRV:
04087 rr_size = ROUND_SHORT(sizeof(struct dns_rr));
04088 break;
04089 case T_NAPTR:
04090 rr_size = ROUND_POINTER(sizeof(struct dns_rr));
04091 break;
04092 case T_TXT:
04093 rr_size = ROUND_POINTER(sizeof(struct dns_rr));
04094 break;
04095 case T_EBL:
04096 rr_size = ROUND_POINTER(sizeof(struct dns_rr));
04097 break;
04098 case T_PTR:
04099 rr_size = sizeof(struct dns_rr);
04100 break;
04101 default:
04102 LOG(L_ERR, "ERROR: dns_cache_clone_entry: type %d not "
04103 "supported\n", e->type);
04104 return NULL;
04105 }
04106 } else {
04107 rounded_size = size;
04108
04109 rr_size = 0;
04110 }
04111
04112 new=shm_malloc(rounded_size+rr_size+rdata_size);
04113 if (!new) {
04114 LOG(L_ERR, "ERROR: dns_cache_clone_entry: out of memory\n");
04115 return NULL;
04116 }
04117 memset(new, 0, rounded_size+rr_size+rdata_size);
04118
04119 memcpy(new, e, size);
04120
04121 new->next = new->prev = NULL;
04122 #ifdef DNS_LU_LST
04123 new->last_used_lst.next = new->last_used_lst.prev = NULL;
04124 #endif
04125 new->rr_lst = (struct dns_rr*)translate_pointer((char*)new, (char*)e,
04126 (char*)new->rr_lst);
04127 atomic_set(&new->refcnt, 0);
04128 new->last_used = now;
04129
04130
04131 last_rr = NULL;
04132 for (rr=new->rr_lst; rr; rr=rr->next) {
04133 rr->rdata = (void*)translate_pointer((char*)new, (char*)e,
04134 (char*)rr->rdata);
04135 if (rr->next)
04136 rr->next = (struct dns_rr*)translate_pointer((char*)new, (char*)e,
04137 (char*)rr->next);
04138 else
04139 last_rr = rr;
04140
04141 switch(e->type){
04142 case T_NAPTR:
04143
04144 ((struct naptr_rdata*)rr->rdata)->flags =
04145 translate_pointer((char*)new, (char*)e,
04146 ((struct naptr_rdata*)rr->rdata)->flags);
04147
04148 ((struct naptr_rdata*)rr->rdata)->services =
04149 translate_pointer((char*)new, (char*)e,
04150 ((struct naptr_rdata*)rr->rdata)->services);
04151
04152 ((struct naptr_rdata*)rr->rdata)->regexp =
04153 translate_pointer((char*)new, (char*)e,
04154 ((struct naptr_rdata*)rr->rdata)->regexp);
04155
04156 ((struct naptr_rdata*)rr->rdata)->repl =
04157 translate_pointer((char*)new, (char*)e,
04158 ((struct naptr_rdata*)rr->rdata)->repl);
04159 break;
04160 case T_TXT:
04161
04162 for (i=0; i<((struct txt_rdata*)rr->rdata)->cstr_no; i++){
04163 ((struct txt_rdata*)rr->rdata)->txt[i].cstr=
04164 translate_pointer((char*) new, (char*) e,
04165 ((struct txt_rdata*)rr->rdata)->txt[i].cstr);
04166 }
04167 break;
04168 case T_EBL:
04169
04170 ((struct ebl_rdata*)rr->rdata)->separator =
04171 translate_pointer((char*)new, (char*)e,
04172 ((struct ebl_rdata*)rr->rdata)->separator);
04173 ((struct ebl_rdata*)rr->rdata)->apex =
04174 translate_pointer((char*)new, (char*)e,
04175 ((struct ebl_rdata*)rr->rdata)->apex);
04176 break;
04177 }
04178 }
04179
04180
04181 if (rdata_size) {
04182
04183 new_rr = (void*)((char*)new + rounded_size);
04184 new_rr->rdata = (void*)((char*)new_rr+rr_size);
04185 new_rr->expire = now + S_TO_TICKS(ttl);
04186
04187 last_rr->next = new_rr;
04188
04189
04190 new->total_size=rounded_size+rr_size+rdata_size;
04191 new->expire = MAX(new->expire, new_rr->expire);
04192
04193
04194 if (_new_rr)
04195 *_new_rr = new_rr;
04196 } else {
04197 if (_new_rr)
04198 *_new_rr = NULL;
04199 }
04200
04201 return new;
04202 }
04203
04204
04205
04206
04207
04208
04209
04210
04211
04212
04213
04214
04215
04216 int dns_cache_add_record(unsigned short type,
04217 str *name,
04218 int ttl,
04219 str *value,
04220 int priority,
04221 int weight,
04222 int port,
04223 int flags)
04224 {
04225 struct dns_hash_entry *old=NULL, *new=NULL;
04226 struct dns_rr *rr;
04227 str rr_name;
04228 struct ip_addr *ip_addr;
04229 ticks_t expire;
04230 int err, h;
04231 int size;
04232 struct dns_rr *new_rr, **rr_p, **rr_iter;
04233 struct srv_rdata *srv_rd;
04234
04235
04236 ip_addr = 0;
04237 size = 0;
04238 rr_name.s = NULL;
04239 rr_name.len = 0;
04240
04241 if (!cfg_get(core, core_cfg, use_dns_cache)){
04242 LOG(L_ERR, "ERROR: dns cache support disabled (see use_dns_cache)\n");
04243 return -1;
04244 }
04245
04246 if ((type != T_A) && (type != T_AAAA) && (type != T_SRV)) {
04247 LOG(L_ERR, "ERROR: rr type %d is not implemented\n",
04248 type);
04249 return -1;
04250 }
04251
04252 if ((flags & DNS_FLAG_BAD_NAME) == 0) {
04253
04254 switch(type) {
04255 case T_A:
04256 ip_addr = str2ip(value);
04257 if (!ip_addr) {
04258 LOG(L_ERR, "ERROR: Malformed ip address: %.*s\n",
04259 value->len, value->s);
04260 return -1;
04261 }
04262 break;
04263 case T_AAAA:
04264 #ifdef USE_IPV6
04265 ip_addr = str2ip6(value);
04266 if (!ip_addr) {
04267 LOG(L_ERR, "ERROR: Malformed ip address: %.*s\n",
04268 value->len, value->s);
04269 return -1;
04270 }
04271 break;
04272 #else
04273 LOG(L_ERR, "ERROR: IPv6 support is disabled\n");
04274 return -1;
04275 #endif
04276 case T_SRV:
04277 rr_name = *value;
04278 break;
04279 }
04280 }
04281
04282
04283 old = dns_hash_get(name, type, &h, &err);
04284 if (old && old->type!=type) {
04285
04286
04287 dns_hash_put(old);
04288 old=NULL;
04289 }
04290
04291 if (old
04292 && (old->ent_flags & DNS_FLAG_PERMANENT)
04293 && ((flags & DNS_FLAG_PERMANENT) == 0)
04294 ) {
04295 LOG(L_ERR, "ERROR: A non-permanent record cannot overwrite "
04296 "a permanent entry\n");
04297 goto error;
04298 }
04299
04300 if (flags & DNS_FLAG_BAD_NAME) {
04301
04302 new = dns_cache_mk_bad_entry(name, type, ttl, flags);
04303 if (!new) {
04304 LOG(L_ERR, "ERROR: Failed to create a negative "
04305 "DNS cache entry\n");
04306 goto error;
04307 }
04308 } else {
04309 if (!old
04310 || (old->ent_flags & DNS_FLAG_BAD_NAME)
04311 || (((old->ent_flags & DNS_FLAG_PERMANENT) == 0)
04312 && (flags & DNS_FLAG_PERMANENT))
04313 ) {
04314
04315
04316
04317
04318
04319 switch(type) {
04320 case T_A:
04321 case T_AAAA:
04322 new = dns_cache_mk_ip_entry(name, ip_addr);
04323 if (!new) {
04324 LOG(L_ERR, "ERROR: Failed to create an A/AAAA record\n");
04325 goto error;
04326 }
04327
04328
04329 expire = get_ticks_raw() + S_TO_TICKS(ttl);
04330 new->expire = expire;
04331 new->rr_lst->expire = expire;
04332 break;
04333 case T_SRV:
04334 new = dns_cache_mk_srv_entry(name, priority, weight, port,
04335 &rr_name, ttl);
04336 if (!new) {
04337 LOG(L_ERR, "ERROR: Failed to create an SRV record\n");
04338 goto error;
04339 }
04340 }
04341 new->ent_flags = flags;
04342 } else {
04343
04344
04345
04346
04347
04348
04349
04350 for (rr=old->rr_lst; rr; rr=rr->next)
04351 if ((((type == T_A) || (type == T_AAAA)) &&
04352 (memcmp(ip_addr->u.addr, ((struct a_rdata*)rr->rdata)->ip,
04353 ip_addr->len)==0))
04354 || ((type == T_SRV) &&
04355 (((struct srv_rdata*)rr->rdata)->name_len == rr_name.len)&&
04356 (memcmp(rr_name.s, ((struct srv_rdata*)rr->rdata)->name,
04357 rr_name.len)==0)))
04358 break;
04359
04360 if (rr) {
04361
04362 new = dns_cache_clone_entry(old, 0, 0, 0);
04363 if (!new) {
04364 LOG(L_ERR, "ERROR: Failed to clone an existing "
04365 "DNS cache entry\n");
04366 goto error;
04367 }
04368
04369 rr = (struct dns_rr*)translate_pointer((char*)new, (char*)old,
04370 (char*)rr);
04371 new_rr = rr;
04372
04373 if (type == T_SRV) {
04374
04375 ((struct srv_rdata*)rr->rdata)->priority = priority;
04376 ((struct srv_rdata*)rr->rdata)->weight = weight;
04377 ((struct srv_rdata*)rr->rdata)->port = port;
04378 }
04379
04380
04381 rr->expire = get_ticks_raw() + S_TO_TICKS(ttl);
04382 new->expire = 0;
04383 for (rr=new->rr_lst; rr; rr=rr->next)
04384 new->expire = MAX(new->expire, rr->expire);
04385 } else {
04386
04387
04388 switch(type) {
04389 case T_A:
04390 size = sizeof(struct a_rdata);
04391 break;
04392 case T_AAAA:
04393 size = sizeof(struct aaaa_rdata);
04394 break;
04395 case T_SRV:
04396 size = sizeof(struct srv_rdata)-1 +
04397 rr_name.len+1;
04398 break;
04399 }
04400 new = dns_cache_clone_entry(old, size, ttl, &rr);
04401 if (!new) {
04402 LOG(L_ERR, "ERROR: Failed to clone an existing "
04403 "DNS cache entry\n");
04404 goto error;
04405 }
04406 new_rr = rr;
04407
04408 switch(type) {
04409 case T_A:
04410 case T_AAAA:
04411 memcpy(rr->rdata, ip_addr->u.addr, ip_addr->len);
04412 break;
04413 case T_SRV:
04414 ((struct srv_rdata*)rr->rdata)->priority = priority;
04415 ((struct srv_rdata*)rr->rdata)->weight = weight;
04416 ((struct srv_rdata*)rr->rdata)->port = port;
04417 ((struct srv_rdata*)rr->rdata)->name_len = rr_name.len;
04418 memcpy(((struct srv_rdata*)rr->rdata)->name, rr_name.s,
04419 rr_name.len);
04420 }
04421
04422
04423 }
04424
04425 if (type == T_SRV) {
04426
04427
04428
04429
04430 rr_p = NULL;
04431 for ( rr_iter = &new->rr_lst;
04432 *rr_iter;
04433 rr_iter = &((*rr_iter)->next)
04434 ) {
04435 if (*rr_iter == new_rr) {
04436 rr_p = rr_iter;
04437 continue;
04438 }
04439 srv_rd = (struct srv_rdata*)(*rr_iter)->rdata;
04440 if ((priority < srv_rd->priority) ||
04441 ((priority == srv_rd->priority) && (weight > srv_rd->weight))
04442 )
04443 break;
04444 }
04445
04446 if (!rr_p)
04447 for ( rr_p = rr_iter;
04448 *rr_p && (*rr_p != new_rr);
04449 rr_p = &((*rr_p)->next)
04450 );
04451 if (!rr_p) {
04452 LOG(L_ERR, "ERROR: Failed to correct the orderd list of SRV resource records\n");
04453 goto error;
04454 }
04455
04456 if (*rr_iter != new_rr->next) {
04457
04458 *rr_p = (*rr_p)->next;
04459
04460 new_rr->next = *rr_iter;
04461 *rr_iter = new_rr;
04462 }
04463 }
04464 }
04465 }
04466
04467 LOCK_DNS_HASH();
04468 if (dns_cache_add_unsafe(new)) {
04469 LOG(L_ERR, "ERROR: Failed to add the entry to the cache\n");
04470 UNLOCK_DNS_HASH();
04471 goto error;
04472 } else {
04473
04474 if (old)
04475 _dns_hash_remove(old);
04476 }
04477 UNLOCK_DNS_HASH();
04478
04479 if (old)
04480 dns_hash_put(old);
04481 return 0;
04482
04483 error:
04484
04485 if (old)
04486 dns_hash_put(old);
04487 if (new)
04488 dns_destroy_entry(new);
04489 return -1;
04490 }
04491
04492
04493
04494 static void dns_cache_delete_record(rpc_t* rpc, void* ctx, unsigned short type)
04495 {
04496 struct dns_hash_entry *e;
04497 str name;
04498 int err, h, found=0, permanent=0;
04499
04500 if (!cfg_get(core, core_cfg, use_dns_cache)){
04501 rpc->fault(ctx, 500, "dns cache support disabled (see use_dns_cache)");
04502 return;
04503 }
04504
04505 if (rpc->scan(ctx, "S", &name) < 1)
04506 return;
04507
04508 LOCK_DNS_HASH();
04509
04510 e=_dns_hash_find(&name, type, &h, &err);
04511 if (e && (e->type==type)) {
04512 if ((e->ent_flags & DNS_FLAG_PERMANENT) == 0)
04513 _dns_hash_remove(e);
04514 else
04515 permanent = 1;
04516 found = 1;
04517 }
04518
04519 UNLOCK_DNS_HASH();
04520
04521 if (permanent)
04522 rpc->fault(ctx, 400, "Permanent entries cannot be deleted");
04523 else if (!found)
04524 rpc->fault(ctx, 400, "Not found");
04525 }
04526
04527
04528
04529
04530
04531
04532
04533 int dns_cache_delete_single_record(unsigned short type,
04534 str *name,
04535 str *value,
04536 int flags)
04537 {
04538 struct dns_hash_entry *old=NULL, *new=NULL;
04539 struct dns_rr *rr, **next_p;
04540 str rr_name;
04541 struct ip_addr *ip_addr;
04542 int err, h;
04543
04544
04545 rr_name.s = NULL;
04546 rr_name.len = 0;
04547 ip_addr = 0;
04548
04549 if (!cfg_get(core, core_cfg, use_dns_cache)){
04550 LOG(L_ERR, "ERROR: dns cache support disabled (see use_dns_cache)\n");
04551 return -1;
04552 }
04553
04554 if ((type != T_A) && (type != T_AAAA) && (type != T_SRV)) {
04555 LOG(L_ERR, "ERROR: rr type %d is not implemented\n",
04556 type);
04557 return -1;
04558 }
04559
04560 if ((flags & DNS_FLAG_BAD_NAME) == 0) {
04561
04562 switch(type) {
04563 case T_A:
04564 ip_addr = str2ip(value);
04565 if (!ip_addr) {
04566 LOG(L_ERR, "ERROR: Malformed ip address: %.*s\n",
04567 value->len, value->s);
04568 return -1;
04569 }
04570 break;
04571 case T_AAAA:
04572 #ifdef USE_IPV6
04573 ip_addr = str2ip6(value);
04574 if (!ip_addr) {
04575 LOG(L_ERR, "ERROR: Malformed ip address: %.*s\n",
04576 value->len, value->s);
04577 return -1;
04578 }
04579 break;
04580 #else
04581 LOG(L_ERR, "ERROR: IPv6 support is disabled\n");
04582 return -1;
04583 #endif
04584 case T_SRV:
04585 rr_name = *value;
04586 break;
04587 }
04588 }
04589
04590
04591 if ((old = dns_hash_get(name, type, &h, &err)) == NULL)
04592 goto not_found;
04593
04594 if ((old->type != type)
04595 || (old->ent_flags != flags)
04596 )
04597 goto not_found;
04598
04599 if (flags & DNS_FLAG_BAD_NAME)
04600 goto delete;
04601
04602
04603 for (rr=old->rr_lst, next_p=&old->rr_lst;
04604 rr;
04605 next_p=&rr->next, rr=rr->next
04606 )
04607 if ((((type == T_A) || (type == T_AAAA)) &&
04608 (memcmp(ip_addr->u.addr, ((struct a_rdata*)rr->rdata)->ip,
04609 ip_addr->len)==0))
04610 || ((type == T_SRV) &&
04611 (((struct srv_rdata*)rr->rdata)->name_len == rr_name.len) &&
04612 (memcmp(rr_name.s, ((struct srv_rdata*)rr->rdata)->name,
04613 rr_name.len)==0)))
04614 break;
04615
04616 if (!rr)
04617 goto not_found;
04618
04619 if ((rr == old->rr_lst) && (rr->next == NULL)) {
04620
04621
04622 goto delete;
04623 } else {
04624
04625
04626
04627
04628
04629 new = dns_cache_clone_entry(old, 0, 0, 0);
04630 if (!new) {
04631 LOG(L_ERR, "ERROR: Failed to clone an existing "
04632 "DNS cache entry\n");
04633 dns_hash_put(old);
04634 return -1;
04635 }
04636
04637 rr = (struct dns_rr*)translate_pointer((char*)new,
04638 (char*)old,
04639 (char*)rr);
04640 next_p = (struct dns_rr**)translate_pointer((char*)new,
04641 (char*)old,
04642 (char*)next_p);
04643
04644
04645 *next_p = rr->next;
04646 }
04647
04648 delete:
04649 LOCK_DNS_HASH();
04650 if (new) {
04651
04652 if (dns_cache_add_unsafe(new)) {
04653 LOG(L_ERR, "ERROR: Failed to add the entry to the cache\n");
04654 UNLOCK_DNS_HASH();
04655 if (old)
04656 dns_hash_put(old);
04657 return -1;
04658 } else {
04659
04660 if (old)
04661 _dns_hash_remove(old);
04662 }
04663 } else if (old) {
04664 _dns_hash_remove(old);
04665 }
04666 UNLOCK_DNS_HASH();
04667
04668 if (old)
04669 dns_hash_put(old);
04670 return 0;
04671
04672 not_found:
04673 LOG(L_ERR, "ERROR: No matching record found\n");
04674 if (old)
04675 dns_hash_put(old);
04676 return -1;
04677 }
04678
04679
04680 void dns_cache_rpc_lookup(rpc_t* rpc, void* ctx)
04681 {
04682 struct dns_hash_entry *e;
04683 str name;
04684 str type;
04685 int t;
04686
04687 if (!cfg_get(core, core_cfg, use_dns_cache)){
04688 rpc->fault(ctx, 500, "dns cache support disabled (see use_dns_cache)");
04689 return;
04690 }
04691
04692 if (rpc->scan(ctx, "SS", &type, &name) < 1)
04693 return;
04694 t=dns_get_type(&type);
04695 if (t<0){
04696 rpc->fault(ctx, 400, "Invalid type");
04697 return;
04698 }
04699 e=dns_get_entry(&name, t);
04700 if (e==0){
04701 rpc->fault(ctx, 400, "Not found");
04702 return;
04703 }
04704 dns_cache_print_entry(rpc, ctx, e);
04705 dns_hash_put(e);
04706 }
04707
04708
04709
04710
04711 void dns_cache_add_a(rpc_t* rpc, void* ctx)
04712 {
04713 str name;
04714 int ttl;
04715 str ip;
04716 int flags;
04717
04718 if (rpc->scan(ctx, "SdSd", &name, &ttl, &ip, &flags) < 4)
04719 return;
04720
04721 if (dns_cache_add_record(T_A,
04722 &name,
04723 ttl,
04724 &ip,
04725 0 ,
04726 0 ,
04727 0 ,
04728 flags)
04729 )
04730 rpc->fault(ctx, 400, "Failed to add the entry to the cache");
04731 }
04732
04733
04734 void dns_cache_add_aaaa(rpc_t* rpc, void* ctx)
04735 {
04736 str name;
04737 int ttl;
04738 str ip;
04739 int flags;
04740
04741 if (rpc->scan(ctx, "SdSd", &name, &ttl, &ip, &flags) < 4)
04742 return;
04743
04744 if (dns_cache_add_record(T_AAAA,
04745 &name,
04746 ttl,
04747 &ip,
04748 0 ,
04749 0 ,
04750 0 ,
04751 flags)
04752 )
04753 rpc->fault(ctx, 400, "Failed to add the entry to the cache");
04754 }
04755
04756 void dns_cache_add_srv(rpc_t* rpc, void* ctx)
04757 {
04758 str name;
04759 int ttl, priority, weight, port;
04760 str rr_name;
04761 int flags;
04762
04763 if (rpc->scan(ctx, "SddddSd", &name, &ttl, &priority, &weight, &port,
04764 &rr_name, &flags) < 7
04765 )
04766 return;
04767
04768 if (dns_cache_add_record(T_SRV,
04769 &name,
04770 ttl,
04771 &rr_name,
04772 priority,
04773 weight,
04774 port,
04775 flags)
04776 )
04777 rpc->fault(ctx, 400, "Failed to add the entry to the cache");
04778 }
04779
04780
04781
04782
04783 void dns_cache_delete_a(rpc_t* rpc, void* ctx)
04784 {
04785 dns_cache_delete_record(rpc, ctx, T_A);
04786 }
04787
04788
04789 void dns_cache_delete_aaaa(rpc_t* rpc, void* ctx)
04790 {
04791 dns_cache_delete_record(rpc, ctx, T_AAAA);
04792 }
04793
04794
04795 void dns_cache_delete_srv(rpc_t* rpc, void* ctx)
04796 {
04797 dns_cache_delete_record(rpc, ctx, T_SRV);
04798 }
04799
04800
04801 void dns_cache_delete_naptr(rpc_t* rpc, void* ctx)
04802 {
04803 dns_cache_delete_record(rpc, ctx, T_NAPTR);
04804 }
04805
04806
04807 void dns_cache_delete_cname(rpc_t* rpc, void* ctx)
04808 {
04809 dns_cache_delete_record(rpc, ctx, T_CNAME);
04810 }
04811
04812
04813 void dns_cache_delete_txt(rpc_t* rpc, void* ctx)
04814 {
04815 dns_cache_delete_record(rpc, ctx, T_TXT);
04816 }
04817
04818 void dns_cache_delete_ebl(rpc_t* rpc, void* ctx)
04819 {
04820 dns_cache_delete_record(rpc, ctx, T_EBL);
04821 }
04822
04823 void dns_cache_delete_ptr(rpc_t* rpc, void* ctx)
04824 {
04825 dns_cache_delete_record(rpc, ctx, T_PTR);
04826 }
04827
04828
04829
04830 #ifdef DNS_WATCHDOG_SUPPORT
04831
04832 void dns_set_server_state_rpc(rpc_t* rpc, void* ctx)
04833 {
04834 int state;
04835
04836 if (!cfg_get(core, core_cfg, use_dns_cache)){
04837 rpc->fault(ctx, 500, "dns cache support disabled (see use_dns_cache)");
04838 return;
04839 }
04840 if (rpc->scan(ctx, "d", &state) < 1)
04841 return;
04842 dns_set_server_state(state);
04843 }
04844
04845
04846 void dns_get_server_state_rpc(rpc_t* rpc, void* ctx)
04847 {
04848 if (!cfg_get(core, core_cfg, use_dns_cache)){
04849 rpc->fault(ctx, 500, "dns cache support disabled (see use_dns_cache)");
04850 return;
04851 }
04852 rpc->add(ctx, "d", dns_get_server_state());
04853 }
04854 #endif
04855
04856 #endif