2
0
Эх сурвалжийг харах

DNS watchdog support implementation: a SER module or an external application can inform the core that the DNS servers
are down. No DNS query is performed in this case, and even expired entries are used from the cache. Use
dns_set_server_state() function from modules or the dns.set_server_state RPC command to set the sate of the DNS
servers.

The feature is desabled by default, enable it with -DDNS_WATCHDOG_SUPPORT (required DNS cache enabled)

Miklos Tirpak 18 жил өмнө
parent
commit
f682fd712c
5 өөрчлөгдсөн 128 нэмэгдсэн , 6 устгасан
  1. 7 0
      Makefile.defs
  2. 14 1
      core_cmd.c
  3. 87 4
      dns_cache.c
  4. 13 0
      dns_cache.h
  5. 7 1
      version.h

+ 7 - 0
Makefile.defs

@@ -60,6 +60,7 @@
 #  2007-05-26  changed darwin module link flags (instead of -bundle_loader ser
 #  2007-05-26  changed darwin module link flags (instead of -bundle_loader ser
 #               -flat_namespace -undefined suppress) (andrei)
 #               -flat_namespace -undefined suppress) (andrei)
 #  2007-07-07  added HAVE_SCHED_SETSCHEDULER for linux (andrei)
 #  2007-07-07  added HAVE_SCHED_SETSCHEDULER for linux (andrei)
+#  2007-07-18  added DNS_WATCHDOG_SUPPORT (Miklos)
 
 
 # check if already included/exported
 # check if already included/exported
 
 
@@ -403,6 +404,11 @@ endif
 #         unsafe)
 #         unsafe)
 # -DUSE_NAPTR
 # -DUSE_NAPTR
 #		 turns on naptr support (but must be also enabled from the config)
 #		 turns on naptr support (but must be also enabled from the config)
+# -DDNS_WATCHDOG_SUPPORT
+#		turns on DNS watchdog support which can be used to inform the
+#		core that the DNS servers are down. No DNS query is performed
+#		when the servers are unreachable, and even expired resource
+#		records are used from the cache. (requires external watchdog)
 
 
 # Sometimes is needes correct non-quoted $OS. HACK: gcc translates known OS to number ('linux'), so there is added underscore
 # Sometimes is needes correct non-quoted $OS. HACK: gcc translates known OS to number ('linux'), so there is added underscore
 
 
@@ -423,6 +429,7 @@ DEFS+= $(extra_defs) \
 	 -DUSE_DNS_FAILOVER \
 	 -DUSE_DNS_FAILOVER \
 	 -DUSE_DST_BLACKLIST \
 	 -DUSE_DST_BLACKLIST \
 	 -DUSE_NAPTR \
 	 -DUSE_NAPTR \
+	 #-DDNS_WATCHDOG_SUPPORT \
 	 #-DLL_MALLOC \
 	 #-DLL_MALLOC \
 	 #-DSF_MALLOC \
 	 #-DSF_MALLOC \
 	 #-DDL_MALLOC \
 	 #-DDL_MALLOC \

+ 14 - 1
core_cmd.c

@@ -57,7 +57,17 @@ static const char* dns_cache_debug_all_doc[] = {
 	"complete dns debug  dump",    /* Documentation string */
 	"complete dns debug  dump",    /* Documentation string */
 	0                              /* Method signature(s) */
 	0                              /* Method signature(s) */
 };
 };
-#endif
+
+#ifdef DNS_WATCHDOG_SUPPORT
+void dns_set_server_state_rpc(rpc_t* rpc, void* ctx);
+
+static const char* dns_set_server_state_doc[] = {
+	"sets the state of the DNS servers " \
+	"(0: all the servers are down, 1: at least one server is up)",    /* Documentation string */
+	0                              /* Method signature(s) */
+};
+#endif /* DNS_WATCHDOG_SUPPORT */
+#endif /* USE_DNS_CACHE */
 #ifdef USE_DST_BLACKLIST
 #ifdef USE_DST_BLACKLIST
 void dst_blst_debug(rpc_t* rpc, void* ctx);
 void dst_blst_debug(rpc_t* rpc, void* ctx);
 void dst_blst_mem_info(rpc_t* rpc, void* ctx);
 void dst_blst_mem_info(rpc_t* rpc, void* ctx);
@@ -469,6 +479,9 @@ rpc_export_t core_rpc_methods[] = {
 	{"dns.mem_info",          dns_cache_mem_info,     dns_cache_mem_info_doc,     0	},
 	{"dns.mem_info",          dns_cache_mem_info,     dns_cache_mem_info_doc,     0	},
 	{"dns.debug",          dns_cache_debug,           dns_cache_debug_doc,        0	},
 	{"dns.debug",          dns_cache_debug,           dns_cache_debug_doc,        0	},
 	{"dns.debug_all",      dns_cache_debug_all,       dns_cache_debug_all_doc,        0	},
 	{"dns.debug_all",      dns_cache_debug_all,       dns_cache_debug_all_doc,        0	},
+#ifdef DNS_WATCHDOG_SUPPORT
+	{"dns.set_server_state",   dns_set_server_state_rpc, dns_set_server_state_doc, 0 },
+#endif
 #endif
 #endif
 #ifdef USE_DST_BLACKLIST
 #ifdef USE_DST_BLACKLIST
 	{"dst_blacklist.mem_info",  dst_blst_mem_info,     dst_blst_mem_info_doc,     0	},
 	{"dst_blacklist.mem_info",  dst_blst_mem_info,     dst_blst_mem_info_doc,     0	},

+ 87 - 4
dns_cache.c

@@ -33,6 +33,8 @@
  *  2007-06-14  dns iterate through A & AAAA records fix (andrei)
  *  2007-06-14  dns iterate through A & AAAA records fix (andrei)
  *  2007-06-15  srv rr weight based load balancing support (andrei)
  *  2007-06-15  srv rr weight based load balancing support (andrei)
  *  2007-06-16  naptr support (andrei)
  *  2007-06-16  naptr support (andrei)
+ *  2008-07-18  DNS watchdog support -- can be used to inform the core
+ *              that the DNS servers are down (Miklos)
  */
  */
 
 
 #ifdef USE_DNS_CACHE
 #ifdef USE_DNS_CACHE
@@ -112,6 +114,10 @@ static struct dns_hash_head* dns_hash=0;
 
 
 static struct timer_ln* dns_timer_h=0;
 static struct timer_ln* dns_timer_h=0;
 
 
+#ifdef DNS_WATCHDOG_SUPPORT
+static atomic_t *dns_servers_up = NULL;
+#endif
+
 
 
 
 
 static const char* dns_str_errors[]={
 static const char* dns_str_errors[]={
@@ -192,6 +198,11 @@ inline static int dns_cache_free_mem(unsigned int target, int expired_only);
 
 
 static ticks_t dns_timer(ticks_t ticks, struct timer_ln* tl, void* data)
 static ticks_t dns_timer(ticks_t ticks, struct timer_ln* tl, void* data)
 {
 {
+#ifdef DNS_WATCHDOG_SUPPORT
+	/* do not clean the hash table if the servers are down */
+	if (atomic_get(dns_servers_up) == 0)
+		return (ticks_t)(-1);
+#endif
 	if (*dns_cache_mem_used>12*(dns_cache_max_mem/16)){ /* ~ 75% used */
 	if (*dns_cache_mem_used>12*(dns_cache_max_mem/16)){ /* ~ 75% used */
 		dns_cache_free_mem(dns_cache_max_mem/2, 1); 
 		dns_cache_free_mem(dns_cache_max_mem/2, 1); 
 	}else{
 	}else{
@@ -210,6 +221,12 @@ void destroy_dns_cache()
 		timer_free(dns_timer_h);
 		timer_free(dns_timer_h);
 		dns_timer_h=0;
 		dns_timer_h=0;
 	}
 	}
+#ifdef DNS_WATCHDOG_SUPPORT
+	if (dns_servers_up){
+		shm_free(dns_servers_up);
+		dns_servers_up=0;
+	}
+#endif
 	if (dns_hash_lock){
 	if (dns_hash_lock){
 		lock_destroy(dns_hash_lock);
 		lock_destroy(dns_hash_lock);
 		lock_dealloc(dns_hash_lock);
 		lock_dealloc(dns_hash_lock);
@@ -277,6 +294,15 @@ int init_dns_cache()
 		ret=-1;
 		ret=-1;
 		goto error;
 		goto error;
 	}
 	}
+
+#ifdef DNS_WATCHDOG_SUPPORT
+	dns_servers_up=shm_malloc(sizeof(atomic_t));
+	if (dns_servers_up==0){
+		ret=E_OUT_OF_MEM;
+		goto error;
+	}
+	atomic_set(dns_servers_up, 1);
+#endif
 	
 	
 	/* fix options */
 	/* fix options */
 	dns_cache_max_mem<<=10; /* Kb */ /* TODO: test with 0 */
 	dns_cache_max_mem<<=10; /* Kb */ /* TODO: test with 0 */
@@ -413,6 +439,11 @@ inline static struct dns_hash_entry* _dns_hash_find(str* name, int type,
 	ticks_t now;
 	ticks_t now;
 	int cname_chain;
 	int cname_chain;
 	str cname;
 	str cname;
+#ifdef DNS_WATCHDOG_SUPPORT
+	int servers_up;
+
+	servers_up = atomic_get(dns_servers_up);
+#endif
 	
 	
 	cname_chain=0;
 	cname_chain=0;
 	ret=0;
 	ret=0;
@@ -425,8 +456,14 @@ again:
 												name->len, type, *h);
 												name->len, type, *h);
 #endif
 #endif
 	clist_foreach_safe(&dns_hash[*h], e, tmp, next){
 	clist_foreach_safe(&dns_hash[*h], e, tmp, next){
-		/* automatically remove expired elements */
-		if ((s_ticks_t)(now-e->expire)>=0){
+		if (
+#ifdef DNS_WATCHDOG_SUPPORT
+			/* remove expired elements only when the dns servers are up */
+			servers_up &&
+#endif
+			/* automatically remove expired elements */
+			((s_ticks_t)(now-e->expire)>=0)
+		) {
 				_dns_hash_remove(e);
 				_dns_hash_remove(e);
 		}else if ((e->type==type) && (e->name_len==name->len) &&
 		}else if ((e->type==type) && (e->name_len==name->len) &&
 			(strncasecmp(e->name, name->s, e->name_len)==0)){
 			(strncasecmp(e->name, name->s, e->name_len)==0)){
@@ -1476,6 +1513,10 @@ inline static struct dns_hash_entry* dns_cache_do_request(str* name, int type)
 				goto end;/* we do not cache obvious stuff */
 				goto end;/* we do not cache obvious stuff */
 		}
 		}
 	}
 	}
+#ifdef DNS_WATCHDOG_SUPPORT
+	if (atomic_get(dns_servers_up)==0)
+		goto end; /* the servers are down, needless to perform the query */
+#endif
 	if (name->len>=MAX_DNS_NAME){
 	if (name->len>=MAX_DNS_NAME){
 		LOG(L_ERR, "ERROR: dns_cache_do_request: name too long (%d chars)\n",
 		LOG(L_ERR, "ERROR: dns_cache_do_request: name too long (%d chars)\n",
 					name->len);
 					name->len);
@@ -1660,11 +1701,22 @@ inline static struct dns_rr* dns_entry_get_rr(	struct dns_hash_entry* e,
 	struct dns_rr* rr;
 	struct dns_rr* rr;
 	int n;
 	int n;
 	int flags;
 	int flags;
+#ifdef DNS_WATCHDOG_SUPPORT
+	int servers_up;
+
+	servers_up = atomic_get(dns_servers_up);
+#endif
 	
 	
 	flags=0;
 	flags=0;
 	for(rr=e->rr_lst, n=0;rr && (n<*no);rr=rr->next, n++);/* skip *no records*/
 	for(rr=e->rr_lst, n=0;rr && (n<*no);rr=rr->next, n++);/* skip *no records*/
 	for(;rr;rr=rr->next){
 	for(;rr;rr=rr->next){
-		if ((s_ticks_t)(now-e->expire)>=0) /* expired entry */
+		if (
+#ifdef DNS_WATCHDOG_SUPPORT
+			/* check the expiration time only when the servers are up */
+			servers_up &&
+#endif
+			((s_ticks_t)(now-rr->expire)>=0) /* expired rr */
+		)
 			continue;
 			continue;
 		if (rr->err_flags){ /* bad rr */
 		if (rr->err_flags){ /* bad rr */
 			continue;
 			continue;
@@ -1741,6 +1793,11 @@ inline static struct dns_rr* dns_srv_get_nxt_rr(struct dns_hash_entry* e,
 			unsigned r_sum;
 			unsigned r_sum;
 			struct dns_rr* rr;
 			struct dns_rr* rr;
 			}r_sums[MAX_SRV_GRP_IDX];
 			}r_sums[MAX_SRV_GRP_IDX];
+#ifdef DNS_WATCHDOG_SUPPORT
+	int servers_up;
+
+	servers_up = atomic_get(dns_servers_up);
+#endif
 	
 	
 	rand_w=0;
 	rand_w=0;
 	for(rr=e->rr_lst, n=0;rr && (n<*no);rr=rr->next, n++);/* skip *no records*/
 	for(rr=e->rr_lst, n=0;rr && (n<*no);rr=rr->next, n++);/* skip *no records*/
@@ -1755,7 +1812,12 @@ retry:
 	found=0;
 	found=0;
 	for (idx=0;rr && (prio==((struct srv_rdata*)rr->rdata)->priority) &&
 	for (idx=0;rr && (prio==((struct srv_rdata*)rr->rdata)->priority) &&
 						(idx < MAX_SRV_GRP_IDX); idx++, rr=rr->next){
 						(idx < MAX_SRV_GRP_IDX); idx++, rr=rr->next){
-		if ( ((s_ticks_t)(now-rr->expire)>=0) /* expired entry */ ||
+		if ((
+#ifdef DNS_WATCHDOG_SUPPORT
+			/* check the expiration time only when the servers are up */
+			servers_up &&
+#endif
+			((s_ticks_t)(now-rr->expire)>=0) /* expired entry */) ||
 				(rr->err_flags) /* bad rr */ ||
 				(rr->err_flags) /* bad rr */ ||
 				(srv_marked(tried, idx)) ) /* already tried */{
 				(srv_marked(tried, idx)) ) /* already tried */{
 			r_sums[idx].r_sum=0; /* 0 sum, to skip over it */
 			r_sums[idx].r_sum=0; /* 0 sum, to skip over it */
@@ -2939,6 +3001,16 @@ int dns_srv_get_ip(str* name, struct ip_addr* ip, unsigned short* port,
 }
 }
 
 
 
 
+#ifdef DNS_WATCHDOG_SUPPORT
+/* sets the state of the DNS servers:
+ * 1: at least one server is up
+ * 0: all the servers are down
+ */
+void dns_set_server_state(int state)
+{
+	atomic_set(dns_servers_up, state);
+}
+#endif /* DNS_WATCHDOG_SUPPORT */
 
 
 /* rpc functions */
 /* rpc functions */
 void dns_cache_mem_info(rpc_t* rpc, void* ctx)
 void dns_cache_mem_info(rpc_t* rpc, void* ctx)
@@ -3026,5 +3098,16 @@ void dns_cache_debug_all(rpc_t* rpc, void* ctx)
 	UNLOCK_DNS_HASH();
 	UNLOCK_DNS_HASH();
 }
 }
 
 
+#ifdef DNS_WATCHDOG_SUPPORT
+/* sets the DNS server states */
+void dns_set_server_state_rpc(rpc_t* rpc, void* ctx)
+{
+	int	state;
+
+	if (rpc->scan(ctx, "d", &state) < 1)
+		return;
+	dns_set_server_state(state);
+}
+#endif /* DNS_WATCHDOG_SUPPORT */
 
 
 #endif
 #endif

+ 13 - 0
dns_cache.h

@@ -48,6 +48,10 @@
 #error "DNS FAILOVER requires DNS CACHE support (define USE_DNS_CACHE)"
 #error "DNS FAILOVER requires DNS CACHE support (define USE_DNS_CACHE)"
 #endif
 #endif
 
 
+#if defined(DNS_WATCHDOG_SUPPORT) && !defined(USE_DNS_CACHE)
+#error "DNS WATCHDOG requires DNS CACHE support (define USE_DNS_CACHE)"
+#endif
+
 /* uncomment the define below for SRV weight based load balancing */
 /* uncomment the define below for SRV weight based load balancing */
 #define DNS_SRV_LB
 #define DNS_SRV_LB
 
 
@@ -308,4 +312,13 @@ inline static int dns_sip_resolve2su(struct dns_srv_handle* h,
 		init_su(su, &ip, port);
 		init_su(su, &ip, port);
 	return ret;
 	return ret;
 }
 }
+
+#ifdef DNS_WATCHDOG_SUPPORT
+/* sets the state of the DNS servers:
+ * 1: at least one server is up
+ * 0: all the servers are down
+ */
+void dns_set_server_state(int state);
+#endif /* DNS_WATCHDOG_SUPPORT */
+
 #endif
 #endif

+ 7 - 1
version.h

@@ -260,6 +260,12 @@
 #define USE_DNS_FAILOVER_STR ""
 #define USE_DNS_FAILOVER_STR ""
 #endif
 #endif
 
 
+#ifdef DNS_WATCHDOG_SUPPORT
+#define DNS_WATCHDOG_SUPPORT_STR ", DNS_WATCHDOG_SUPPORT"
+#else
+#define DNS_WATCHDOG_SUPPORT_STR ""
+#endif
+
 #ifdef USE_NAPTR
 #ifdef USE_NAPTR
 #define USE_NAPTR_STR ", USE_NAPTR"
 #define USE_NAPTR_STR ", USE_NAPTR"
 #else
 #else
@@ -297,7 +303,7 @@
 	USE_FUTEX_STR \
 	USE_FUTEX_STR \
 	FAST_LOCK_STR NOSMP_STR USE_PTHREAD_MUTEX_STR USE_POSIX_SEM_STR \
 	FAST_LOCK_STR NOSMP_STR USE_PTHREAD_MUTEX_STR USE_POSIX_SEM_STR \
 	USE_SYSV_SEM_STR USE_COMP_STR USE_DNS_CACHE_STR USE_DNS_FAILOVER_STR \
 	USE_SYSV_SEM_STR USE_COMP_STR USE_DNS_CACHE_STR USE_DNS_FAILOVER_STR \
-	USE_NAPTR_STR USE_DST_BLACKLIST_STR
+	DNS_WATCHDOG_SUPPORT_STR USE_NAPTR_STR USE_DST_BLACKLIST_STR
 
 
 
 
 #endif
 #endif