Index: /branches/rel_apv_10_7/usr/click/lib/libdns_agent/Makefile
===================================================================
--- /branches/rel_apv_10_7/usr/click/lib/libdns_agent/Makefile	(revision 39379)
+++ /branches/rel_apv_10_7/usr/click/lib/libdns_agent/Makefile	(working copy)
@@ -34,7 +34,7 @@
 	  -L${.OBJDIR}/../libhttp_utils -lhttp_utils \
 	  -L${.OBJDIR}/../libfastlog -lfastlog \
 	  -L${.OBJDIR}/../libenglog -lenglog \
-	  -lcrypt -lanl -lm -lz
+	  -lcrypt -lanl -lcares -lm -lz
 
 .if defined(USTACK)
 .include <bsd.lib.mk>
Index: /branches/rel_apv_10_7/usr/click/lib/libdns_agent/dns_daemon.c
===================================================================
--- /branches/rel_apv_10_7/usr/click/lib/libdns_agent/dns_daemon.c	(revision 39379)
+++ /branches/rel_apv_10_7/usr/click/lib/libdns_agent/dns_daemon.c	(working copy)
@@ -25,9 +25,11 @@
 #include "amp_ulog.h"
 #include <fastlog.h>
 #include <click/app/proxy/proxy_lib_hash.h>
+#include <ares.h>
 
 #define NAMESERVER_UPDATE_INTERVAL 30 /* second */
 #define DNS_AGENT_SLEEP_TIME    1000  /* microsecond */
+#define DNS_THREAD_HOST_LEN 255
 
 static char ns_table[NAMESERVER_MAX_NUM][INET6_ADDRSTRLEN];
 static int ns_mod_time;
@@ -46,19 +48,23 @@
 extern int atcp_event_outrq_enqueue(int thread_id, void *buf, uint16_t app_id);
 
 struct dns_req_ctx {
-	int busy_fl;
+	int busy_fl; // Indicates if a DNS request is active (1 = processing, 0 = ready/enqueued)
 	webagent_dns_data_t *webagent_ctx;
-	struct gaicb *req[1];
-	struct gaicb req_item;
+	ares_channel_t *channel;
+	char host[DNS_THREAD_HOST_LEN]; // Hostname to be resolved by the thread
+	uint32_t ttl;
+	volatile int done; // Indicates whether IP and TTL have been retrieved; must be set last by the writer thread
+	struct sockaddr ai_addr;  // large enough for IPv4 or IPv6
+	socklen_t addr_len;               // store size
 };
 
 #define DNS_REQ_LIST_LEN 20
 #define DEFAULT_WEBAGENT_DNS_TTL 1
 
-static __thread struct dns_req_ctx dns_req_wait_list[DNS_REQ_LIST_LEN];
-__thread int outstanding_dns_req_cnt = 0;
+static struct dns_req_ctx dns_req_wait_list[DNS_REQ_LIST_LEN];
+int outstanding_dns_req_cnt = 0;
 
-static time_t 
+static time_t
 get_nsfile_last_mtime(void)
 {
 	struct stat stat_buf;
@@ -415,12 +421,70 @@
 	return;
 }
 
-static int
-domain_resolve_asynch(webagent_dns_data_t *dns_data_p)
+/* c-ares ares_getaddrinfo() callback function */
+static void
+addrinfo_cb(void *arg, int status, int timeouts, struct ares_addrinfo *result)
+{
+	struct dns_req_ctx *ctx = (struct dns_req_ctx *)arg;
+
+	// fastlog_syslog(LOG_DEBUG,"%s: Result: %d(%s), timeouts: %d", __FUNCTION__, status, ares_strerror(status), timeouts);
+	fastlog_syslog(LOG_DEBUG,"%s: rv: %d, t: %d", __FUNCTION__, status, timeouts);
+
+	if (status != ARES_SUCCESS || !result) {
+		fastlog_syslog(LOG_DEBUG, "DNS query failed: %s\n", ares_strerror(status));
+        ctx->done = -1;
+        return;
+    }
+
+	struct ares_addrinfo_node *node = result->nodes;
+    if (node && node->ai_addr) {
+        ctx->ttl = node->ai_ttl;
+		char ip_str[INET6_ADDRSTRLEN] = {0};
+
+        if (node->ai_family == AF_INET) {
+            ctx->addr_len = sizeof(struct sockaddr_in);
+            memcpy(&(ctx->ai_addr), node->ai_addr, ctx->addr_len);
+			inet_ntop(AF_INET, &(((struct sockaddr_in *)node->ai_addr)->sin_addr), ip_str, sizeof(ip_str));
+        } else if (node->ai_family == AF_INET6) {
+            ctx->addr_len = sizeof(struct sockaddr_in6);
+            memcpy(&(ctx->ai_addr), node->ai_addr, ctx->addr_len);
+			inet_ntop(AF_INET6, &(((struct sockaddr_in6 *)node->ai_addr)->sin6_addr), ip_str, sizeof(ip_str));
+        }
+    }
+	ares_freeaddrinfo(result);
+	ctx->done = 1;
+}
+
+void dns_req_query(void *arg)
+{
+    struct dns_req_ctx *ctx = (struct dns_req_ctx *)arg;
+    ctx->channel = NULL;
+    struct ares_addrinfo_hints hints;
+    struct ares_options options;
+    int optmask = ARES_OPT_EVENT_THREAD | ARES_OPT_TIMEOUTMS | ARES_OPT_TRIES | ARES_OPT_SERVER_FAILOVER;
+
+    memset(&options, 0, sizeof(options));
+    options.evsys = ARES_EVSYS_DEFAULT;
+    options.timeout = 250;
+    options.tries = 1;
+
+    if (ares_init_options(&ctx->channel, &options, optmask) != ARES_SUCCESS) {
+        fastlog_syslog(LOG_DEBUG, "c-ares initialization issue");
+		ctx->ttl = 0;
+		ctx->done = -2;
+    } else {
+		memset(&hints, 0, sizeof(hints));
+		hints.ai_family = AF_UNSPEC;
+		hints.ai_flags = ARES_AI_CANONNAME;
+
+		ares_getaddrinfo(ctx->channel, ctx->host, NULL, &hints, addrinfo_cb, ctx);
+	}
+}
+
+static int domain_resolve_asynch(webagent_dns_data_t *dns_data_p) // here
 {
 	int free_idx = 0;
 	int ret;
-
 	/* find first free slot and Queue nreqs_base..nreqs requests. */
 	while (free_idx < DNS_REQ_LIST_LEN) {
 		if (dns_req_wait_list[free_idx].busy_fl == 0) {
@@ -428,28 +492,18 @@
 		}
 		free_idx++;
 	}
-	if (free_idx > DNS_REQ_LIST_LEN) {
+	if (free_idx >= DNS_REQ_LIST_LEN) {
 		/* Note: this should not happen because in the thread func we do not read if list is full */
 		fastlog_syslog(LOG_DEBUG, "%s: run out of free requests %d", __FUNCTION__, outstanding_dns_req_cnt);
 		ulog_error_no_conn(AMP_ULOG_WEBAGENT, "run out of free requests");
 		return -1;
 	}
-	dns_req_wait_list[free_idx].req_item.ar_name = dns_data_p->host;
-	dns_req_wait_list[free_idx].req_item.ar_service = NULL;
-	dns_req_wait_list[free_idx].req_item.ar_request = NULL; //hints will be default
-	dns_req_wait_list[free_idx].req_item.ar_result = NULL;
-	dns_req_wait_list[free_idx].req[0] = &(dns_req_wait_list[free_idx].req_item);
-
-	ret = getaddrinfo_a(GAI_NOWAIT, dns_req_wait_list[free_idx].req, 1, NULL);
-	if (ret) {
-		fastlog_syslog(LOG_DEBUG, "%s: getaddrinfo_a failed %d", __FUNCTION__, ret);
-		ulog_error_no_conn(AMP_ULOG_WEBAGENT, "getaddrinfo_a failed %d", ret);
-		return -2;
-	}
-	/* dns req successfully sent */
+
+	snprintf(dns_req_wait_list[free_idx].host, sizeof(dns_req_wait_list[free_idx].host), "%s", dns_data_p->host);
+	dns_req_query(&dns_req_wait_list[free_idx]);
+
 	dns_req_wait_list[free_idx].webagent_ctx = dns_data_p;
 	dns_req_wait_list[free_idx].busy_fl = 1;
-
 	outstanding_dns_req_cnt++;
 	//fastlog_syslog(LOG_DEBUG, "%s: sent req for %s(idx %d), out reqs %d",
 	//	       __FUNCTION__, host, free_idx, outstanding_dns_req_cnt);
@@ -459,46 +513,52 @@
 static void
 cleanup_poll_item(struct dns_req_ctx *poll_item)
 {
-	poll_item->webagent_ctx = NULL;
-	poll_item->busy_fl = 0;
+	WEBAGENT_DNS_FREE(poll_item->webagent_ctx);
+	poll_item->ttl = 0;
+	poll_item->addr_len = 0;
 	outstanding_dns_req_cnt--;
+	ares_destroy(poll_item->channel);
+	memset(&(poll_item->ai_addr), 0, sizeof(poll_item->ai_addr));
+	poll_item->done = 0;
+	poll_item->busy_fl = 0;
 }
 
 static int
 domain_resolve_poll()
 {
 	int ret;
-	struct addrinfo *res;
-	struct gaicb *req_p;
+	struct sockaddr *res;
 	webagent_dns_data_t *webagent_ctx;
 	int poll_freed_cnt = 0;
 
-	for (int i = 0; i < DNS_REQ_LIST_LEN; i++) {
-		if (dns_req_wait_list[i].busy_fl == 0) {
+	for (int i = 0; i < DNS_REQ_LIST_LEN; ++i) {
+		if (dns_req_wait_list[i].busy_fl == 0 || dns_req_wait_list[i].done == 0) {
 			continue;
 		}
-		req_p = dns_req_wait_list[i].req[0];
-		ret = gai_error(req_p);
 
-		if (ret == EAI_INPROGRESS) {
-			continue;
-		}
 		webagent_ctx = dns_req_wait_list[i].webagent_ctx;
-
-		if (ret == 0) {
+		if (dns_req_wait_list[i].done == 1) {
 			/* ready */
-			res = req_p->ar_result;
-			if (res->ai_addr->sa_family == AF_INET) {
-				struct sockaddr_in *my_addr = (struct sockaddr_in *)res->ai_addr;
+			res = &(dns_req_wait_list[i].ai_addr);
+			if (res->sa_family == AF_INET) {
+				struct sockaddr_in *my_addr = (struct sockaddr_in *)res;
 				fastlog_syslog(LOG_DEBUG, "%s: [%d], outstanding req %d, thread id %d: host %s -> ip %s",
 							__FUNCTION__, i, outstanding_dns_req_cnt, webagent_ctx->thread_id,
 							webagent_ctx->host, inet_ntoa(my_addr->sin_addr));
 				webagent_ctx->iptable.ip4_dns_record_table[0].ip = my_addr->sin_addr.s_addr;
-				webagent_ctx->iptable.ip4_dns_record_table[0].ttl = DEFAULT_WEBAGENT_DNS_TTL;
+				if (dns_req_wait_list[i].ttl != 0){		/* check if ttl is valid */
+					webagent_ctx->iptable.ip4_dns_record_table[0].ttl = dns_req_wait_list[i].ttl;
+				}else{
+					webagent_ctx->iptable.ip4_dns_record_table[0].ttl = DEFAULT_WEBAGENT_DNS_TTL;
+				}
 			} else {
-				struct sockaddr_in6 *my_addr = (struct sockaddr_in6 *)res->ai_addr;
+				struct sockaddr_in6 *my_addr = (struct sockaddr_in6 *)res;
 				webagent_ctx->iptable.ip6_dns_record_table[0].ip = my_addr->sin6_addr;
-				webagent_ctx->iptable.ip6_dns_record_table[0].ttl = DEFAULT_WEBAGENT_DNS_TTL;
+				if (dns_req_wait_list[i].ttl != 0){
+					webagent_ctx->iptable.ip6_dns_record_table[0].ttl = dns_req_wait_list[i].ttl;
+				}else{
+					webagent_ctx->iptable.ip6_dns_record_table[0].ttl = DEFAULT_WEBAGENT_DNS_TTL;
+				}
 			}
 			webagent_ctx->ip_num = 1;
 		} else {
@@ -515,7 +575,6 @@
 				       __FUNCTION__, webagent_ctx->thread_id);
 			ulog_error_no_conn(AMP_ULOG_WEBAGENT, "failed to insert webagent dns data to outrq [%hu]",
 					   webagent_ctx->thread_id);
-			WEBAGENT_DNS_FREE(webagent_ctx);
 		}
 		cleanup_poll_item(&dns_req_wait_list[i]);
 		poll_freed_cnt++;
@@ -605,6 +664,7 @@
 	}
 
 	load_nameserver();
+	ares_library_init(ARES_LIB_INIT_ALL);
 	last_ticks = click_softticks100;
 
 	INIT_INDENT_LEVEL;
@@ -614,12 +674,6 @@
 			last_ticks = click_softticks100;
 		}
 
-		if (atcp_event_inrq_empty(ATCP_DNS_RQ) && outstanding_dns_req_cnt == 0) {
-			/* nothing incoming or outstanding */
-			usleep(DNS_AGENT_SLEEP_TIME);
-			continue;
-		}
-
 		if (outstanding_dns_req_cnt) {
 			if (domain_resolve_poll() == 0) {
 				/* nothing freed up from the poll */
@@ -642,6 +696,7 @@
 			}
 		}
 	}
+	ares_library_cleanup();
 }
 
 #ifdef FUNC_TRACE
Index: /branches/rel_apv_10_7/usr/click/lib/libuinet-atcp/bin/atcp/Makefile
===================================================================
--- /branches/rel_apv_10_7/usr/click/lib/libuinet-atcp/bin/atcp/Makefile	(revision 39379)
+++ /branches/rel_apv_10_7/usr/click/lib/libuinet-atcp/bin/atcp/Makefile	(working copy)
@@ -11,7 +11,7 @@
 CXXFLAGS= -std=c++11 -I${TOPDIR}/../libbreakpad/build/src
 LIBBREAKPAD_CLIENT=${TOPDIR}/../libbreakpad/build/src/client/linux/libbreakpad_client.a
 ifneq ($(ARM64), yes)
-LDADD= -L${UINET_DESTDIR}/lib/ -lanl -lm -lpcap \
+LDADD= -L${UINET_DESTDIR}/lib/ -lanl -lcares -lm -lpcap \
 	-L${RTE_SDK}/${RTE_TARGET}/lib -ldpdk \
 	-Wl,--start-group \
 	-L${TOPDIR}/../libenv -lenv \
