cache: cache NXDOMAIN records.

This commit is contained in:
Nick Peng
2022-05-28 00:10:24 +08:00
parent b5a5311976
commit 2365a1a2b0

View File

@@ -46,6 +46,7 @@
#define DNS_MAX_EVENTS 256
#define IPV6_READY_CHECK_TIME 180
#define DNS_SERVER_TMOUT_TTL (5 * 60)
#define DNS_SERVER_FAIL_TTL (60)
#define DNS_CONN_BUFF_SIZE 4096
#define DNS_REQUEST_MAX_TIMEOUT 850
#define DNS_PING_TIMEOUT (DNS_REQUEST_MAX_TIMEOUT)
@@ -254,7 +255,8 @@ static tlog_log *dns_audit;
static int is_ipv6_ready;
static int _dns_server_prefetch_request(char *domain, dns_type_t qtype, uint32_t server_flags, struct dns_query_options *options);
static int _dns_server_prefetch_request(char *domain, dns_type_t qtype, uint32_t server_flags,
struct dns_query_options *options);
static int _dns_server_forward_request(unsigned char *inpacket, int inpacket_len)
{
@@ -1005,8 +1007,7 @@ int _dns_cache_cname_packet(struct dns_server_post_context *context)
if (inpacket_len <= 0) {
return -1;
}
cache_packet =
dns_cache_new_data_packet(request->server_flags, inpacket_buff, inpacket_len);
cache_packet = dns_cache_new_data_packet(request->server_flags, inpacket_buff, inpacket_len);
if (cache_packet == NULL) {
return -1;
}
@@ -1042,6 +1043,36 @@ errout:
return -1;
}
static int _dns_cache_error_packet(struct dns_server_post_context *context)
{
struct dns_request *request = context->request;
struct dns_cache_data *cache_packet =
dns_cache_new_data_packet(request->server_flags, context->inpacket, context->inpacket_len);
if (cache_packet == NULL) {
return -1;
}
/* if doing prefetch, update cache only */
if (request->prefetch) {
if (dns_cache_replace(request->domain, DNS_SERVER_FAIL_TTL, context->qtype, -1, cache_packet) != 0) {
goto errout;
}
} else {
/* insert result to cache */
if (dns_cache_insert(request->domain, DNS_SERVER_FAIL_TTL, context->qtype, -1, cache_packet) != 0) {
goto errout;
}
}
return 0;
errout:
if (cache_packet) {
dns_cache_data_free(cache_packet);
}
return -1;
}
static int _dns_cache_reply_packet(struct dns_server_post_context *context)
{
struct dns_request *request = context->request;
@@ -1050,6 +1081,10 @@ static int _dns_cache_reply_packet(struct dns_server_post_context *context)
return 0;
}
if (context->packet->head.rcode == DNS_RC_SERVFAIL || context->packet->head.rcode == DNS_RC_NXDOMAIN) {
return _dns_cache_error_packet(context);
}
if (context->qtype != DNS_T_AAAA && context->qtype != DNS_T_A) {
return 0;
}
@@ -1072,7 +1107,6 @@ static int _dns_cache_reply_packet(struct dns_server_post_context *context)
tlog(TLOG_WARN, "update packet cache failed.");
}
_dns_cache_cname_packet(context);
return 0;
@@ -1174,7 +1208,7 @@ static int _dns_request_post(struct dns_server_post_context *context)
struct dns_request *request = context->request;
int ret = 0;
tlog(TLOG_DEBUG, "reply %s %d %d", request->domain, request->qtype, context->qtype);
tlog(TLOG_DEBUG, "reply %s qtype: %d, rcode: %d", request->domain, request->qtype, context->packet->head.rcode);
if (request->conn == NULL) {
context->do_reply = 0;
@@ -1350,6 +1384,7 @@ static int dns_server_update_reply_packet_id(struct dns_request *request, unsign
}
static void _dns_server_request_release(struct dns_request *request);
static void _dns_server_request_release_complete(struct dns_request *request, int do_complete);
int _dns_server_reply_all_pending_list(struct dns_request *request, struct dns_server_post_context *context)
{
@@ -1380,13 +1415,14 @@ int _dns_server_reply_all_pending_list(struct dns_request *request, struct dns_s
if (atomic_inc_return(&req->notified) != 1) {
return 0;
}
req->rcode = request->rcode;
/* When passthrough, modify the id to be the id of the client request. */
dns_server_update_reply_packet_id(req, context->inpacket, context->inpacket_len);
ret = _dns_reply_inpacket(req, context->inpacket, context->inpacket_len);
}
req->request_pending_list = NULL;
_dns_server_request_release(req);
_dns_server_request_release_complete(req, 0);
}
pthread_mutex_unlock(&pending_list->request_list_lock);
@@ -1400,6 +1436,10 @@ static int _dns_server_request_complete(struct dns_request *request)
int force_A = 0;
int ttl = DNS_SERVER_TMOUT_TTL;
if (request->rcode == DNS_RC_SERVFAIL || request->rcode == DNS_RC_NXDOMAIN) {
ttl = DNS_SERVER_FAIL_TTL;
}
if (request->prefetch == 1) {
return 0;
}
@@ -2312,9 +2352,9 @@ static int _dns_server_process_answer(struct dns_request *request, char *domain,
static int _dns_server_passthrough_rule_check(struct dns_request *request, char *domain, struct dns_packet *packet,
unsigned int result_flag, int *pttl)
{
int ttl;
int ttl = 0;
char name[DNS_MAX_CNAME_LEN] = {0};
int rr_count;
int rr_count = 0;
int i = 0;
int j = 0;
struct dns_rrs *rrs = NULL;
@@ -3724,7 +3764,8 @@ static int _dns_server_do_query(struct dns_request *request)
// Get reference for AAAA query
_dns_server_request_get(request);
request->request_wait++;
if (dns_client_query(request->domain, DNS_T_A, dns_server_resolve_callback, request, group_name, &options) != 0) {
if (dns_client_query(request->domain, DNS_T_A, dns_server_resolve_callback, request, group_name, &options) !=
0) {
request->request_wait--;
_dns_server_request_release(request);
}
@@ -3733,7 +3774,8 @@ static int _dns_server_do_query(struct dns_request *request)
// Get reference for DNS query
request->request_wait++;
_dns_server_request_get(request);
if (dns_client_query(request->domain, request->qtype, dns_server_resolve_callback, request, group_name, &options) != 0) {
if (dns_client_query(request->domain, request->qtype, dns_server_resolve_callback, request, group_name, &options) !=
0) {
request->request_wait--;
_dns_server_request_release(request);
tlog(TLOG_ERROR, "send dns request failed.");
@@ -3748,7 +3790,7 @@ errout:
return ret;
}
static int _dns_server_parser_request(struct dns_request *request, struct dns_packet *packet)
static int _dns_server_parser_request(struct dns_request *request, struct dns_packet *packet)
{
struct dns_rrs *rrs;
int rr_count = 0;
@@ -3780,7 +3822,6 @@ static int _dns_server_parser_request(struct dns_request *request, struct dns_pa
break;
}
/* get request opts */
rr_count = 0;
rrs = dns_get_rrs_start(packet, DNS_RRS_OPT, &rr_count);
@@ -3813,7 +3854,6 @@ static int _dns_server_recv(struct dns_server_conn_head *conn, unsigned char *in
struct dns_packet *packet = (struct dns_packet *)packet_buff;
struct dns_request *request = NULL;
/* decode packet */
tlog(TLOG_DEBUG, "recv query packet from %s, len = %d",
gethost_by_addr(name, sizeof(name), (struct sockaddr *)from), inpacket_len);
@@ -3861,7 +3901,7 @@ errout:
return ret;
}
static int _dns_server_prefetch_setup_options(struct dns_request *request, struct dns_query_options *options)
static int _dns_server_prefetch_setup_options(struct dns_request *request, struct dns_query_options *options)
{
if (options == NULL) {
return 0;
@@ -3875,7 +3915,8 @@ static int _dns_server_prefetch_setup_options(struct dns_request *request, struc
return 0;
}
static int _dns_server_prefetch_request(char *domain, dns_type_t qtype, uint32_t server_flags, struct dns_query_options *options)
static int _dns_server_prefetch_request(char *domain, dns_type_t qtype, uint32_t server_flags,
struct dns_query_options *options)
{
int ret = -1;
struct dns_request *request = NULL;