dualstack: cache SOA record for speed.

This commit is contained in:
Nick Peng
2021-01-24 14:16:35 +08:00
parent 51e1e6565f
commit 11cf7b614c
3 changed files with 119 additions and 46 deletions

View File

@@ -142,8 +142,7 @@ void dns_cache_data_free(struct dns_cache_data *data)
free(data);
}
struct dns_cache_data *dns_cache_new_data_addr(uint32_t cache_flag, char *cname, int cname_ttl, unsigned char *addr,
int addr_len)
struct dns_cache_data *dns_cache_new_data(void)
{
struct dns_cache_addr *cache_addr = malloc(sizeof(struct dns_cache_addr));
memset(cache_addr, 0, sizeof(struct dns_cache_addr));
@@ -151,6 +150,50 @@ struct dns_cache_data *dns_cache_new_data_addr(uint32_t cache_flag, char *cname,
return NULL;
}
cache_addr->head.cache_type = CACHE_TYPE_NONE;
cache_addr->head.size = sizeof(struct dns_cache_addr) - sizeof(struct dns_cache_data_head);
return (struct dns_cache_data *)cache_addr;
}
void dns_cache_set_data_soa(struct dns_cache_data *dns_cache, int32_t cache_flag, char *cname, int cname_ttl)
{
if (dns_cache == NULL) {
goto errout;
}
struct dns_cache_addr *cache_addr = (struct dns_cache_addr *)dns_cache;
if (cache_addr == NULL) {
goto errout;
}
memset(cache_addr->addr_data.addr, 0, sizeof(cache_addr->addr_data.addr));
if (cname) {
safe_strncpy(cache_addr->addr_data.cname, cname, DNS_MAX_CNAME_LEN);
cache_addr->addr_data.cname_ttl = cname_ttl;
}
cache_addr->head.cache_flag = cache_flag;
cache_addr->addr_data.soa = 1;
cache_addr->head.cache_type = CACHE_TYPE_ADDR;
cache_addr->head.size = sizeof(struct dns_cache_addr) - sizeof(struct dns_cache_data_head);
errout:
return;
}
void dns_cache_set_data_addr(struct dns_cache_data *dns_cache, uint32_t cache_flag, char *cname, int cname_ttl,
unsigned char *addr, int addr_len)
{
if (dns_cache == NULL) {
goto errout;
}
struct dns_cache_addr *cache_addr = (struct dns_cache_addr *)dns_cache;
if (cache_addr == NULL) {
goto errout;
}
if (addr_len == DNS_RR_A_LEN) {
memcpy(cache_addr->addr_data.addr, addr, DNS_RR_A_LEN);
} else if (addr_len != DNS_RR_AAAA_LEN) {
@@ -167,16 +210,8 @@ struct dns_cache_data *dns_cache_new_data_addr(uint32_t cache_flag, char *cname,
cache_addr->head.cache_flag = cache_flag;
cache_addr->head.cache_type = CACHE_TYPE_ADDR;
cache_addr->head.size = sizeof(struct dns_cache_addr) - sizeof(struct dns_cache_data_head);
return (struct dns_cache_data *)cache_addr;
errout:
if (cache_addr) {
free(cache_addr);
cache_addr = NULL;
}
return NULL;
return;
}
struct dns_cache_data *dns_cache_new_data_packet(uint32_t cache_flag, void *packet, size_t packet_len)
@@ -377,6 +412,18 @@ int dns_cache_get_ttl(struct dns_cache *dns_cache)
return ttl;
}
int dns_cache_is_soa(struct dns_cache *dns_cache) {
if (dns_cache == NULL) {
return 0;
}
struct dns_cache_addr *cache_addr = (struct dns_cache_addr *)dns_cache_get_data(dns_cache);
if (cache_addr->addr_data.soa) {
return 1;
}
return 0;
}
struct dns_cache_data *dns_cache_get_data(struct dns_cache *dns_cache)
{
return dns_cache->cache_data;
@@ -468,7 +515,7 @@ void dns_cache_invalidate(dns_cache_preinvalid_callback callback, int ttl_pre)
}
if (ttl < 0) {
if (dns_cache_head.enable_inactive) {
if (dns_cache_head.enable_inactive && (dns_cache_is_soa(dns_cache) == 0)) {
_dns_cache_move_inactive(dns_cache);
} else {
_dns_cache_remove(dns_cache);

View File

@@ -63,6 +63,7 @@ struct dns_cache_addr {
struct dns_cache_addr_data {
unsigned int cname_ttl;
char cname[DNS_MAX_CNAME_LEN];
char soa;
union {
unsigned char ipv4_addr[DNS_RR_A_LEN];
unsigned char ipv6_addr[DNS_RR_AAAA_LEN];
@@ -116,9 +117,6 @@ uint32_t dns_cache_get_cache_flag(struct dns_cache_data *cache_data);
void dns_cache_data_free(struct dns_cache_data *data);
struct dns_cache_data *dns_cache_new_data_addr(uint32_t cache_flag, char *cname, int cname_ttl, unsigned char *addr,
int addr_len);
struct dns_cache_data *dns_cache_new_data_packet(uint32_t cache_flag, void *packet, size_t packet_len);
int dns_cache_init(int size, int enable_inactive, int inactive_list_expired);
@@ -145,8 +143,17 @@ void dns_cache_invalidate(dns_cache_preinvalid_callback callback, int ttl_pre);
int dns_cache_get_ttl(struct dns_cache *dns_cache);
int dns_cache_is_soa(struct dns_cache *dns_cache);
struct dns_cache_data *dns_cache_new_data(void);
struct dns_cache_data *dns_cache_get_data(struct dns_cache *dns_cache);
void dns_cache_set_data_addr(struct dns_cache_data *dns_cache, uint32_t cache_flag, char *cname, int cname_ttl,
unsigned char *addr, int addr_len);
void dns_cache_set_data_soa(struct dns_cache_data *dns_cache, int32_t cache_flag, char *cname, int cname_ttl);
void dns_cache_destroy(void);
int dns_cache_load(const char *file);

View File

@@ -736,6 +736,10 @@ static int _dns_server_request_update_cache(struct dns_request *request, dns_typ
goto errout;
}
if (request->has_soa) {
ttl = dns_conf_rr_ttl;
}
/* if doing prefetch, update cache only */
if (request->prefetch) {
if (dns_cache_replace(request->domain, ttl, qtype, speed, cache_data) != 0) {
@@ -759,7 +763,7 @@ errout:
static int _dns_server_request_complete_A(struct dns_request *request)
{
char *cname = NULL;
int cname_ttl = 0;
int cname_ttl = dns_conf_rr_ttl;
struct dns_cache_data *cache_data = NULL;
if (request->has_cname) {
@@ -767,27 +771,29 @@ static int _dns_server_request_complete_A(struct dns_request *request)
cname_ttl = request->ttl_cname;
}
if (request->has_ipv4 == 0) {
return 0;
cache_data = dns_cache_new_data();
if (cache_data == NULL) {
goto errout;
}
tlog(TLOG_INFO, "result: %s, rcode: %d, %d.%d.%d.%d\n", request->domain, request->rcode, request->ipv4_addr[0],
request->ipv4_addr[1], request->ipv4_addr[2], request->ipv4_addr[3]);
if (request->has_ipv4 != 0) {
tlog(TLOG_INFO, "result: %s, rcode: %d, %d.%d.%d.%d\n", request->domain, request->rcode, request->ipv4_addr[0],
request->ipv4_addr[1], request->ipv4_addr[2], request->ipv4_addr[3]);
request->has_soa = 0;
if (request->has_ping_result == 0 && request->ttl_v4 > DNS_SERVER_TMOUT_TTL) {
request->ttl_v4 = DNS_SERVER_TMOUT_TTL;
request->has_soa = 0;
if (request->has_ping_result == 0 && request->ttl_v4 > DNS_SERVER_TMOUT_TTL) {
request->ttl_v4 = DNS_SERVER_TMOUT_TTL;
}
dns_cache_set_data_addr(cache_data, request->server_flags, cname, cname_ttl, request->ipv4_addr, DNS_RR_A_LEN);
} else {
dns_cache_set_data_soa(cache_data, request->server_flags, cname, cname_ttl);
}
if (_dns_server_has_bind_flag(request, BIND_FLAG_NO_CACHE) == 0) {
dns_cache_data_free(cache_data);
return 0;
}
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;
}
@@ -807,7 +813,7 @@ static int _dns_server_request_complete_AAAA(struct dns_request *request)
{
int ret = -1;
char *cname = NULL;
int cname_ttl = 0;
int cname_ttl = dns_conf_rr_ttl;
struct dns_cache_data *cache_data = NULL;
if (request->has_cname) {
@@ -815,6 +821,11 @@ static int _dns_server_request_complete_AAAA(struct dns_request *request)
cname_ttl = request->ttl_cname;
}
cache_data = dns_cache_new_data();
if (cache_data == NULL) {
goto errout;
}
if (request->has_ipv6) {
tlog(TLOG_INFO,
"result: %s, rcode: %d, %.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x",
@@ -829,20 +840,22 @@ 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) {
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;
}
cache_data = NULL;
}
dns_cache_set_data_addr(cache_data, request->server_flags, cname, cname_ttl, request->ipv6_addr,
DNS_T_AAAA);
request->has_soa = 0;
} else {
dns_cache_set_data_soa(cache_data, request->server_flags, cname, cname_ttl);
}
if (_dns_server_has_bind_flag(request, BIND_FLAG_NO_CACHE) != 0) {
if (_dns_server_request_update_cache(request, DNS_T_AAAA, cache_data) != 0) {
goto errout;
}
cache_data = NULL;
} else {
dns_cache_data_free(cache_data);
cache_data = NULL;
}
if (request->has_ipv4 && (request->ping_ttl_v4 > 0)) {
@@ -854,12 +867,13 @@ 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) {
cache_data =
dns_cache_new_data_addr(request->server_flags, cname, cname_ttl, request->ipv4_addr, DNS_T_A);
cache_data = dns_cache_new_data();
if (cache_data == NULL) {
goto errout;
}
dns_cache_set_data_addr(cache_data, request->server_flags, cname, cname_ttl, request->ipv4_addr,
DNS_T_A);
if (_dns_server_request_update_cache(request, DNS_T_A, cache_data) != 0) {
goto errout;
}
@@ -2417,7 +2431,7 @@ static int _dns_server_process_cache(struct dns_request *request)
if (dns_cache == NULL) {
if (request->dualstack_selection && request->qtype == DNS_T_AAAA) {
dns_cache_A = dns_cache_lookup(request->domain, DNS_T_A);
if (dns_cache_A) {
if (dns_cache_A && dns_cache_is_soa(dns_cache_A) == 0 && dns_cache_is_soa(dns_cache)) {
tlog(TLOG_DEBUG, "No IPV6 Found, Force IPV4 perfered.");
if (dns_cache_get_ttl(dns_cache_A) == 0) {
uint32_t server_flags = request->server_flags;
@@ -2437,6 +2451,13 @@ static int _dns_server_process_cache(struct dns_request *request)
goto out;
}
if (request->qtype == DNS_T_A) {
if (dns_cache_is_soa(dns_cache)) {
ret = _dns_server_reply_SOA(DNS_RC_NOERROR, request);
goto out;
}
}
if (request->dualstack_selection && request->qtype == DNS_T_AAAA) {
dns_cache_A = dns_cache_lookup(request->domain, DNS_T_A);
if (dns_cache_A && (dns_cache_A->info.speed > 0)) {
@@ -2610,8 +2631,6 @@ static int _dns_server_do_query(struct dns_request *request, const char *domain,
_dns_server_set_dualstack_selection(request);
tlog(TLOG_DEBUG, "dualstack selection %d", request->dualstack_selection);
if (_dns_server_process_special_query(request) == 0) {
goto clean_exit;
}