|
|
@@ -137,6 +137,8 @@ struct dns_request {
|
|
|
atomic_t refcnt;
|
|
|
|
|
|
struct dns_server_conn_head *conn;
|
|
|
+ uint32_t server_flags;
|
|
|
+
|
|
|
/* dns request list */
|
|
|
struct list_head list;
|
|
|
|
|
|
@@ -206,7 +208,7 @@ static struct dns_server server;
|
|
|
|
|
|
static tlog_log *dns_audit;
|
|
|
|
|
|
-static int _dns_server_prefetch_request(char *domain, dns_type_t qtype);
|
|
|
+static int _dns_server_prefetch_request(char *domain, dns_type_t qtype, uint32_t server_flags);
|
|
|
|
|
|
static int _dns_server_forward_request(unsigned char *inpacket, int inpacket_len)
|
|
|
{
|
|
|
@@ -216,17 +218,27 @@ static int _dns_server_forward_request(unsigned char *inpacket, int inpacket_len
|
|
|
|
|
|
static int _dns_server_has_bind_flag(struct dns_request *request, uint32_t flag)
|
|
|
{
|
|
|
- if (request->conn == NULL) {
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
- if (request->conn->server_flags & flag) {
|
|
|
+ if (request->server_flags & flag) {
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
+static int _dns_server_get_conf_ttl(int ttl)
|
|
|
+{
|
|
|
+ if (dns_conf_rr_ttl > 0) {
|
|
|
+ return dns_conf_rr_ttl;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (dns_conf_rr_ttl_max > 0 && ttl > dns_conf_rr_ttl_max) {
|
|
|
+ ttl = dns_conf_rr_ttl_max;
|
|
|
+ } else if (dns_conf_rr_ttl_min > 0 && ttl < dns_conf_rr_ttl_min) {
|
|
|
+ ttl = dns_conf_rr_ttl_min;
|
|
|
+ }
|
|
|
+ return ttl;
|
|
|
+}
|
|
|
+
|
|
|
static int _dns_server_epoll_ctl(struct dns_server_conn_head *head, int op, uint32_t events)
|
|
|
{
|
|
|
struct epoll_event event;
|
|
|
@@ -692,10 +704,47 @@ static int _dns_setup_ipset(struct dns_request *request)
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+static int _dns_server_request_update_cache(struct dns_request *request, dns_type_t qtype,
|
|
|
+ struct dns_cache_data *cache_data)
|
|
|
+{
|
|
|
+ int ttl;
|
|
|
+ int speed = 0;
|
|
|
+
|
|
|
+ if (qtype == DNS_T_A) {
|
|
|
+ ttl = _dns_server_get_conf_ttl(request->ttl_v4);
|
|
|
+ speed = request->ping_ttl_v4;
|
|
|
+ } else if (qtype == DNS_T_AAAA) {
|
|
|
+ ttl = _dns_server_get_conf_ttl(request->ttl_v6);
|
|
|
+ speed = request->ping_ttl_v6;
|
|
|
+ } else {
|
|
|
+ goto errout;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* if doing prefetch, update cache only */
|
|
|
+ if (request->prefetch) {
|
|
|
+ if (dns_cache_replace(request->domain, ttl, qtype, speed, cache_data) != 0) {
|
|
|
+ goto errout;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ /* insert result to cache */
|
|
|
+ if (dns_cache_insert(request->domain, ttl, qtype, speed, cache_data) != 0) {
|
|
|
+ goto errout;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+errout:
|
|
|
+ if (cache_data) {
|
|
|
+ dns_cache_data_free(cache_data);
|
|
|
+ }
|
|
|
+ return -1;
|
|
|
+}
|
|
|
+
|
|
|
static int _dns_server_request_complete_A(struct dns_request *request)
|
|
|
{
|
|
|
char *cname = NULL;
|
|
|
int cname_ttl = 0;
|
|
|
+ struct dns_cache_data *cache_data = NULL;
|
|
|
|
|
|
if (request->has_cname) {
|
|
|
cname = request->cname;
|
|
|
@@ -718,23 +767,32 @@ static int _dns_server_request_complete_A(struct dns_request *request)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
- /* if doing prefetch, update cache only */
|
|
|
- if (request->prefetch) {
|
|
|
- dns_cache_replace(request->domain, cname, cname_ttl, request->ttl_v4, DNS_T_A, request->ipv4_addr, DNS_RR_A_LEN,
|
|
|
- request->ping_ttl_v4);
|
|
|
- } else {
|
|
|
- /* insert result to cache */
|
|
|
- dns_cache_insert(request->domain, cname, cname_ttl, request->ttl_v4, DNS_T_A, request->ipv4_addr, DNS_RR_A_LEN,
|
|
|
- request->ping_ttl_v4);
|
|
|
+ cache_data = dns_cache_new_data_addr(request->server_flags, cname, cname_ttl, request->ipv4_addr, DNS_RR_A_LEN);
|
|
|
+ if (cache_data == NULL) {
|
|
|
+ goto errout;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (_dns_server_request_update_cache(request, DNS_T_A, cache_data) != 0) {
|
|
|
+ goto errout;
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
|
+
|
|
|
+errout:
|
|
|
+ if (cache_data) {
|
|
|
+ dns_cache_data_free(cache_data);
|
|
|
+ cache_data = NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ return -1;
|
|
|
}
|
|
|
|
|
|
static int _dns_server_request_complete_AAAA(struct dns_request *request)
|
|
|
{
|
|
|
+ int ret = -1;
|
|
|
char *cname = NULL;
|
|
|
int cname_ttl = 0;
|
|
|
+ struct dns_cache_data *cache_data = NULL;
|
|
|
|
|
|
if (request->has_cname) {
|
|
|
cname = request->cname;
|
|
|
@@ -756,13 +814,14 @@ static int _dns_server_request_complete_AAAA(struct dns_request *request)
|
|
|
|
|
|
/* if doing prefetch, update cache only */
|
|
|
if (_dns_server_has_bind_flag(request, BIND_FLAG_NO_CACHE) != 0) {
|
|
|
- if (request->prefetch) {
|
|
|
- dns_cache_replace(request->domain, cname, cname_ttl, request->ttl_v6, DNS_T_AAAA, request->ipv6_addr,
|
|
|
- DNS_RR_AAAA_LEN, request->ping_ttl_v6);
|
|
|
- } else {
|
|
|
- /* insert result to cache */
|
|
|
- dns_cache_insert(request->domain, cname, cname_ttl, request->ttl_v6, DNS_T_AAAA, request->ipv6_addr,
|
|
|
- DNS_RR_AAAA_LEN, request->ping_ttl_v6);
|
|
|
+ cache_data =
|
|
|
+ dns_cache_new_data_addr(request->server_flags, cname, cname_ttl, request->ipv6_addr, DNS_T_AAAA);
|
|
|
+ if (cache_data == NULL) {
|
|
|
+ goto errout;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (_dns_server_request_update_cache(request, DNS_T_AAAA, cache_data) != 0) {
|
|
|
+ goto errout;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -778,21 +837,25 @@ static int _dns_server_request_complete_AAAA(struct dns_request *request)
|
|
|
request->ping_ttl_v6 < 0) {
|
|
|
tlog(TLOG_DEBUG, "Force IPV4 perfered.");
|
|
|
if (_dns_server_has_bind_flag(request, BIND_FLAG_NO_CACHE) != 0) {
|
|
|
- if (request->prefetch) {
|
|
|
- dns_cache_replace(request->domain, cname, cname_ttl, request->ttl_v4, DNS_T_A, request->ipv4_addr,
|
|
|
- DNS_RR_A_LEN, request->ping_ttl_v4);
|
|
|
- } else {
|
|
|
- dns_cache_insert(request->domain, cname, cname_ttl, request->ttl_v4, DNS_T_A, request->ipv4_addr,
|
|
|
- DNS_RR_A_LEN, request->ping_ttl_v4);
|
|
|
+ cache_data =
|
|
|
+ dns_cache_new_data_addr(request->server_flags, cname, cname_ttl, request->ipv4_addr, DNS_T_A);
|
|
|
+ if (cache_data == NULL) {
|
|
|
+ goto errout;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (_dns_server_request_update_cache(request, DNS_T_A, cache_data) != 0) {
|
|
|
+ goto errout;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (request->dualstack_selection) {
|
|
|
if (_dns_server_reply_SOA(DNS_RC_NOERROR, request) != 0) {
|
|
|
- return -1;
|
|
|
+ ret = -1;
|
|
|
+ goto errout;
|
|
|
}
|
|
|
|
|
|
- return 1;
|
|
|
+ ret = 1;
|
|
|
+ goto errout;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -800,6 +863,14 @@ static int _dns_server_request_complete_AAAA(struct dns_request *request)
|
|
|
request->has_ipv4 = 0;
|
|
|
|
|
|
return 0;
|
|
|
+
|
|
|
+errout:
|
|
|
+ if (cache_data == NULL) {
|
|
|
+ dns_cache_data_free(cache_data);
|
|
|
+ cache_data = NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
static int _dns_server_request_complete(struct dns_request *request)
|
|
|
@@ -1196,20 +1267,6 @@ static int _dns_ip_address_check_add(struct dns_request *request, unsigned char
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static int _dns_server_get_conf_ttl(int ttl)
|
|
|
-{
|
|
|
- if (dns_conf_rr_ttl > 0) {
|
|
|
- return dns_conf_rr_ttl;
|
|
|
- }
|
|
|
-
|
|
|
- if (dns_conf_rr_ttl_max > 0 && ttl > dns_conf_rr_ttl_max) {
|
|
|
- ttl = dns_conf_rr_ttl_max;
|
|
|
- } else if (dns_conf_rr_ttl_min > 0 && ttl < dns_conf_rr_ttl_min) {
|
|
|
- ttl = dns_conf_rr_ttl_min;
|
|
|
- }
|
|
|
- return ttl;
|
|
|
-}
|
|
|
-
|
|
|
static int _dns_server_ip_rule_check(struct dns_request *request, unsigned char *addr, int addr_len,
|
|
|
dns_type_t addr_type, int result_flag)
|
|
|
{
|
|
|
@@ -1709,8 +1766,7 @@ static int _dns_server_get_answer(struct dns_request *request, struct dns_packet
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static int _dns_server_reply_passthrouth(struct dns_request *request, struct dns_packet *packet,
|
|
|
- unsigned char *inpacket, int inpacket_len)
|
|
|
+static int _dns_server_setup_ipset_packet(struct dns_request *request, struct dns_packet *packet)
|
|
|
{
|
|
|
int ttl;
|
|
|
char name[DNS_MAX_CNAME_LEN] = {0};
|
|
|
@@ -1720,44 +1776,21 @@ static int _dns_server_reply_passthrouth(struct dns_request *request, struct dns
|
|
|
struct dns_rrs *rrs = NULL;
|
|
|
struct dns_ipset_rule *ipset_rule = NULL;
|
|
|
struct dns_rule_flags *rule_flags = NULL;
|
|
|
- int ret = 0;
|
|
|
-
|
|
|
- if (atomic_inc_return(&request->notified) != 1) {
|
|
|
- return 0;
|
|
|
- }
|
|
|
-
|
|
|
- if (request->result_callback) {
|
|
|
- _dns_server_get_answer(request, packet);
|
|
|
- _dns_result_callback(request);
|
|
|
- }
|
|
|
-
|
|
|
- if (request->conn == NULL) {
|
|
|
- return 0;
|
|
|
- }
|
|
|
-
|
|
|
- /* When passthrough, modify the id to be the id of the client request. */
|
|
|
- dns_server_update_reply_packet_id(request, inpacket, inpacket_len);
|
|
|
- ret = _dns_reply_inpacket(request, inpacket, inpacket_len);
|
|
|
-
|
|
|
- if (packet->head.rcode != DNS_RC_NOERROR && packet->head.rcode != DNS_RC_NXDOMAIN) {
|
|
|
- return ret;
|
|
|
- }
|
|
|
|
|
|
if (_dns_server_has_bind_flag(request, BIND_FLAG_NO_RULE_IPSET) == 0) {
|
|
|
- return ret;
|
|
|
+ return -1;
|
|
|
}
|
|
|
-
|
|
|
/* check ipset rule */
|
|
|
rule_flags = request->domain_rule.rules[DOMAIN_RULE_FLAGS];
|
|
|
if (rule_flags) {
|
|
|
if (rule_flags->flags & DOMAIN_FLAG_IPSET_IGNORE) {
|
|
|
- return ret;
|
|
|
+ return -1;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
ipset_rule = request->domain_rule.rules[DOMAIN_RULE_IPSET];
|
|
|
if (ipset_rule == NULL) {
|
|
|
- return ret;
|
|
|
+ return -1;
|
|
|
}
|
|
|
|
|
|
for (j = 1; j < DNS_RRS_END; j++) {
|
|
|
@@ -1778,8 +1811,8 @@ static int _dns_server_reply_passthrouth(struct dns_request *request, struct dns
|
|
|
/* add IPV4 to ipset */
|
|
|
ipset_add(ipset_rule->ipsetname, addr, DNS_RR_A_LEN, request->ttl_v4 * 2);
|
|
|
|
|
|
- tlog(TLOG_DEBUG, "IPSET-MATCH-PASSTHROUTH: domain: %s, ipset: %s, IP: %d.%d.%d.%d",
|
|
|
- request->domain, ipset_rule->ipsetname, addr[0], addr[1], addr[2], addr[3]);
|
|
|
+ tlog(TLOG_DEBUG, "IPSET-MATCH-PASSTHROUTH: domain: %s, ipset: %s, IP: %d.%d.%d.%d", request->domain,
|
|
|
+ ipset_rule->ipsetname, addr[0], addr[1], addr[2], addr[3]);
|
|
|
} break;
|
|
|
case DNS_T_AAAA: {
|
|
|
unsigned char addr[16];
|
|
|
@@ -1797,9 +1830,11 @@ static int _dns_server_reply_passthrouth(struct dns_request *request, struct dns
|
|
|
ipset_add(ipset_rule->ipsetname, addr, DNS_RR_AAAA_LEN, request->ttl_v6 * 2);
|
|
|
}
|
|
|
|
|
|
- tlog(TLOG_DEBUG, "IPSET-MATCH-PASSTHROUTH: domain: %s, ipset: %s, IP: %.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x",
|
|
|
- request->domain, ipset_rule->ipsetname, addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], addr[8],
|
|
|
- addr[9], addr[10], addr[11], addr[12], addr[13], addr[14], addr[15]);
|
|
|
+ tlog(TLOG_DEBUG,
|
|
|
+ "IPSET-MATCH-PASSTHROUTH: domain: %s, ipset: %s, IP: "
|
|
|
+ "%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x",
|
|
|
+ request->domain, ipset_rule->ipsetname, addr[0], addr[1], addr[2], addr[3], addr[4], addr[5],
|
|
|
+ addr[6], addr[7], addr[8], addr[9], addr[10], addr[11], addr[12], addr[13], addr[14], addr[15]);
|
|
|
} break;
|
|
|
default:
|
|
|
break;
|
|
|
@@ -1807,7 +1842,48 @@ static int _dns_server_reply_passthrouth(struct dns_request *request, struct dns
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- return ret;
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int _dns_server_reply_passthrouth(struct dns_request *request, struct dns_packet *packet,
|
|
|
+ unsigned char *inpacket, int inpacket_len)
|
|
|
+{
|
|
|
+ int ret = 0;
|
|
|
+
|
|
|
+ if (atomic_inc_return(&request->notified) != 1) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ _dns_server_get_answer(request, packet);
|
|
|
+ if (request->result_callback) {
|
|
|
+ _dns_result_callback(request);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (request->conn == NULL) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* When passthrough, modify the id to be the id of the client request. */
|
|
|
+ dns_server_update_reply_packet_id(request, inpacket, inpacket_len);
|
|
|
+ ret = _dns_reply_inpacket(request, inpacket, inpacket_len);
|
|
|
+
|
|
|
+ if (packet->head.rcode != DNS_RC_NOERROR && packet->head.rcode != DNS_RC_NXDOMAIN) {
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (_dns_server_has_bind_flag(request, BIND_FLAG_NO_CACHE) != 0 &&
|
|
|
+ (request->qtype == DNS_T_AAAA || request->qtype == DNS_T_A)) {
|
|
|
+ struct dns_cache_data *cache_packet = dns_cache_new_data_packet(request->server_flags, inpacket, inpacket_len);
|
|
|
+ if (cache_packet == NULL) {
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (_dns_server_request_update_cache(request, request->qtype, cache_packet) != 0) {
|
|
|
+ tlog(TLOG_WARN, "update packet cache failed.");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return _dns_server_setup_ipset_packet(request, packet);
|
|
|
}
|
|
|
|
|
|
static int dns_server_resolve_callback(char *domain, dns_result_type rtype, unsigned int result_flag,
|
|
|
@@ -1949,7 +2025,6 @@ static void _dns_server_log_rule(const char *domain, enum domain_rule rule_type,
|
|
|
int rule_key_len)
|
|
|
{
|
|
|
char rule_name[DNS_MAX_CNAME_LEN];
|
|
|
-
|
|
|
if (rule_key_len <= 0) {
|
|
|
return;
|
|
|
}
|
|
|
@@ -2184,6 +2259,118 @@ static void _dns_server_process_speed_check_rule(struct dns_request *request)
|
|
|
request->check_order_list = check_order;
|
|
|
}
|
|
|
|
|
|
+static int _dns_server_process_cache_addr(struct dns_request *request, struct dns_cache *dns_cache)
|
|
|
+{
|
|
|
+ struct dns_cache_addr *cache_addr = (struct dns_cache_addr *)dns_cache_get_data(dns_cache);
|
|
|
+
|
|
|
+ if (cache_addr->head.cache_type != CACHE_TYPE_ADDR) {
|
|
|
+ goto errout;
|
|
|
+ }
|
|
|
+ /* Cache hits, returning results in the cache */
|
|
|
+ switch (request->qtype) {
|
|
|
+ case DNS_T_A:
|
|
|
+ memcpy(request->ipv4_addr, cache_addr->addr_data.ipv4_addr, DNS_RR_A_LEN);
|
|
|
+ request->ttl_v4 = dns_cache_get_ttl(dns_cache);
|
|
|
+ request->has_ipv4 = 1;
|
|
|
+ break;
|
|
|
+ case DNS_T_AAAA:
|
|
|
+ memcpy(request->ipv6_addr, cache_addr->addr_data.ipv6_addr, DNS_RR_AAAA_LEN);
|
|
|
+ request->ttl_v6 = dns_cache_get_ttl(dns_cache);
|
|
|
+ request->has_ipv6 = 1;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ goto errout;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (cache_addr->addr_data.cname[0] != 0) {
|
|
|
+ safe_strncpy(request->cname, cache_addr->addr_data.cname, DNS_MAX_CNAME_LEN);
|
|
|
+ request->has_cname = 1;
|
|
|
+ request->ttl_cname = cache_addr->addr_data.cname_ttl;
|
|
|
+ }
|
|
|
+
|
|
|
+ request->rcode = DNS_RC_NOERROR;
|
|
|
+
|
|
|
+ _dns_result_callback(request);
|
|
|
+
|
|
|
+ if (request->prefetch == 0) {
|
|
|
+ _dns_reply(request);
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+errout:
|
|
|
+ return -1;
|
|
|
+}
|
|
|
+
|
|
|
+static int _dns_server_process_cache_packet(struct dns_request *request, struct dns_cache *dns_cache)
|
|
|
+{
|
|
|
+ struct dns_cache_packet *cache_packet = (struct dns_cache_packet *)dns_cache_get_data(dns_cache);
|
|
|
+
|
|
|
+ if (cache_packet->head.cache_type != CACHE_TYPE_PACKET) {
|
|
|
+ goto errout;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (dns_cache->qtype != request->qtype) {
|
|
|
+ goto errout;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (atomic_inc_return(&request->notified) != 1) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (request->result_callback) {
|
|
|
+ unsigned char packet_buff[DNS_PACKSIZE];
|
|
|
+ struct dns_packet *packet = (struct dns_packet *)packet_buff;
|
|
|
+
|
|
|
+ if (dns_decode(packet, DNS_PACKSIZE, cache_packet->data, cache_packet->head.size) != 0) {
|
|
|
+ goto errout;
|
|
|
+ }
|
|
|
+
|
|
|
+ _dns_server_get_answer(request, packet);
|
|
|
+ _dns_result_callback(request);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (request->conn == NULL) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* When passthrough, modify the id to be the id of the client request. */
|
|
|
+ dns_server_update_reply_packet_id(request, cache_packet->data, cache_packet->head.size);
|
|
|
+ return _dns_reply_inpacket(request, cache_packet->data, cache_packet->head.size);
|
|
|
+errout:
|
|
|
+ return -1;
|
|
|
+}
|
|
|
+
|
|
|
+static int _dns_server_process_cache_data(struct dns_request *request, struct dns_cache *dns_cache)
|
|
|
+{
|
|
|
+ enum CACHE_TYPE cache_type = CACHE_TYPE_NONE;
|
|
|
+ int ret = -1;
|
|
|
+
|
|
|
+ cache_type = dns_cache_data_type(dns_cache->cache_data);
|
|
|
+ switch (cache_type) {
|
|
|
+ case CACHE_TYPE_ADDR:
|
|
|
+ ret = _dns_server_process_cache_addr(request, dns_cache);
|
|
|
+ if (ret != 0) {
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case CACHE_TYPE_PACKET:
|
|
|
+ ret = _dns_server_process_cache_packet(request, dns_cache);
|
|
|
+ if (ret != 0) {
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ goto out;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+out:
|
|
|
+ return -1;
|
|
|
+}
|
|
|
+
|
|
|
static int _dns_server_process_cache(struct dns_request *request)
|
|
|
{
|
|
|
struct dns_cache *dns_cache = NULL;
|
|
|
@@ -2201,7 +2388,11 @@ static int _dns_server_process_cache(struct dns_request *request)
|
|
|
if (dns_cache_A) {
|
|
|
tlog(TLOG_DEBUG, "No IPV6 Found, Force IPV4 perfered.");
|
|
|
if (dns_cache_get_ttl(dns_cache_A) == 0) {
|
|
|
- _dns_server_prefetch_request(request->domain, request->qtype);
|
|
|
+ uint32_t server_flags = request->server_flags;
|
|
|
+ if (request->conn == NULL) {
|
|
|
+ server_flags = dns_cache_get_cache_flag(dns_cache_A->cache_data);
|
|
|
+ }
|
|
|
+ _dns_server_prefetch_request(request->domain, request->qtype, server_flags);
|
|
|
}
|
|
|
ret = _dns_server_reply_SOA(DNS_RC_NOERROR, request);
|
|
|
goto out;
|
|
|
@@ -2226,42 +2417,18 @@ static int _dns_server_process_cache(struct dns_request *request)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- /* Cache hits, returning results in the cache */
|
|
|
- switch (request->qtype) {
|
|
|
- case DNS_T_A:
|
|
|
- memcpy(request->ipv4_addr, dns_cache->ipv4_addr, DNS_RR_A_LEN);
|
|
|
- request->ttl_v4 = dns_cache_get_ttl(dns_cache);
|
|
|
- request->has_ipv4 = 1;
|
|
|
- break;
|
|
|
- case DNS_T_AAAA:
|
|
|
- memcpy(request->ipv6_addr, dns_cache->ipv6_addr, DNS_RR_AAAA_LEN);
|
|
|
- request->ttl_v6 = dns_cache_get_ttl(dns_cache);
|
|
|
- request->has_ipv6 = 1;
|
|
|
- break;
|
|
|
- default:
|
|
|
+ ret = _dns_server_process_cache_data(request, dns_cache);
|
|
|
+ if (ret != 0) {
|
|
|
goto out;
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- if (dns_cache->cname[0] != 0) {
|
|
|
- safe_strncpy(request->cname, dns_cache->cname, DNS_MAX_CNAME_LEN);
|
|
|
- request->has_cname = 1;
|
|
|
- request->ttl_cname = dns_cache->cname_ttl;
|
|
|
- }
|
|
|
-
|
|
|
- request->rcode = DNS_RC_NOERROR;
|
|
|
-
|
|
|
- _dns_result_callback(request);
|
|
|
-
|
|
|
- if (request->prefetch == 0) {
|
|
|
- _dns_reply(request);
|
|
|
}
|
|
|
|
|
|
- ret = 0;
|
|
|
-
|
|
|
out_update_cache:
|
|
|
if (dns_cache_get_ttl(dns_cache) == 0) {
|
|
|
- _dns_server_prefetch_request(request->domain, request->qtype);
|
|
|
+ uint32_t server_flags = request->server_flags;
|
|
|
+ if (request->conn == NULL) {
|
|
|
+ server_flags = dns_cache_get_cache_flag(dns_cache_A->cache_data);
|
|
|
+ }
|
|
|
+ _dns_server_prefetch_request(request->domain, request->qtype, server_flags);
|
|
|
} else {
|
|
|
dns_cache_update(dns_cache);
|
|
|
}
|
|
|
@@ -2282,6 +2449,7 @@ out:
|
|
|
static void _dns_server_request_set_client(struct dns_request *request, struct dns_server_conn_head *conn)
|
|
|
{
|
|
|
request->conn = conn;
|
|
|
+ request->server_flags = conn->server_flags;
|
|
|
_dns_server_conn_get(conn);
|
|
|
}
|
|
|
|
|
|
@@ -2551,7 +2719,7 @@ errout:
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-static int _dns_server_prefetch_request(char *domain, dns_type_t qtype)
|
|
|
+static int _dns_server_prefetch_request(char *domain, dns_type_t qtype, uint32_t server_flags)
|
|
|
{
|
|
|
int ret = -1;
|
|
|
struct dns_request *request = NULL;
|
|
|
@@ -2562,6 +2730,7 @@ static int _dns_server_prefetch_request(char *domain, dns_type_t qtype)
|
|
|
goto errout;
|
|
|
}
|
|
|
|
|
|
+ request->server_flags = server_flags;
|
|
|
_dns_server_request_set_enable_prefetch(request);
|
|
|
ret = _dns_server_do_query(request, domain, qtype);
|
|
|
if (ret != 0) {
|
|
|
@@ -2579,7 +2748,7 @@ errout:
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-int dns_server_query(char *domain, int qtype, dns_result_callback callback, void *user_ptr)
|
|
|
+int dns_server_query(char *domain, int qtype, uint32_t server_flags, dns_result_callback callback, void *user_ptr)
|
|
|
{
|
|
|
int ret = -1;
|
|
|
struct dns_request *request = NULL;
|
|
|
@@ -2590,6 +2759,7 @@ int dns_server_query(char *domain, int qtype, dns_result_callback callback, void
|
|
|
goto errout;
|
|
|
}
|
|
|
|
|
|
+ request->server_flags = server_flags;
|
|
|
_dns_server_request_set_callback(request, callback, user_ptr);
|
|
|
ret = _dns_server_do_query(request, domain, qtype);
|
|
|
if (ret != 0) {
|
|
|
@@ -2986,7 +3156,8 @@ static void _dns_server_prefetch_domain(struct dns_cache *dns_cache)
|
|
|
/* start prefetch domain */
|
|
|
tlog(TLOG_DEBUG, "prefetch by cache %s, qtype %d, ttl %d, hitnum %d", dns_cache->domain, dns_cache->qtype,
|
|
|
dns_cache->ttl, hitnum);
|
|
|
- if (_dns_server_prefetch_request(dns_cache->domain, dns_cache->qtype) != 0) {
|
|
|
+ if (_dns_server_prefetch_request(dns_cache->domain, dns_cache->qtype,
|
|
|
+ dns_cache_get_cache_flag(dns_cache->cache_data)) != 0) {
|
|
|
tlog(TLOG_ERROR, "prefetch domain %s, qtype %d, failed.", dns_cache->domain, dns_cache->qtype);
|
|
|
}
|
|
|
}
|