Просмотр исходного кода

dns_server: retry when dns packet is truncated.

Nick Peng 1 год назад
Родитель
Сommit
9df7eafd03
4 измененных файлов с 24 добавлено и 18 удалено
  1. 1 1
      src/dns.h
  2. 19 10
      src/dns_client.c
  3. 1 0
      src/dns_client.h
  4. 3 7
      src/dns_server.c

+ 1 - 1
src/dns.h

@@ -27,7 +27,7 @@ extern "C" {
 #define DNS_RR_AAAA_LEN 16
 #define DNS_MAX_CNAME_LEN 256
 #define DNS_MAX_OPT_LEN 256
-#define DNS_IN_PACKSIZE (512 * 8)
+#define DNS_IN_PACKSIZE (512 * 16)
 #define DNS_PACKSIZE (512 * 16)
 #define DNS_DEFAULT_PACKET_SIZE 512
 #define DNS_MAX_ALPN_LEN 32

+ 19 - 10
src/dns_client.c

@@ -280,6 +280,7 @@ static LIST_HEAD(pending_servers);
 static pthread_mutex_t pending_server_mutex = PTHREAD_MUTEX_INITIALIZER;
 static int dns_client_has_bootstrap_dns = 0;
 
+static void _dns_client_retry_dns_query(struct dns_query_struct *query);
 static int _dns_client_send_udp(struct dns_server_info *server_info, void *packet, int len);
 static void _dns_client_clear_wakeup_event(void);
 static void _dns_client_do_wakeup_event(void);
@@ -1856,6 +1857,10 @@ static int _dns_client_recv(struct dns_server_info *server_info, unsigned char *
 			/* remove this result */
 			_dns_replied_check_remove(query, from, from_len);
 			atomic_inc(&query->dns_request_sent);
+			if (ret == DNS_CLIENT_RETRY) {
+				/* retry immdiately */
+				_dns_client_retry_dns_query(query);
+			}
 		}
 	}
 
@@ -4036,6 +4041,19 @@ static int _dns_client_query_parser_options(struct dns_query_struct *query, stru
 	return 0;
 }
 
+static void _dns_client_retry_dns_query(struct dns_query_struct *query)
+{
+	if (atomic_dec_and_test(&query->retry_count) || (query->has_result != 0)) {
+		_dns_client_query_remove(query);
+		if (query->has_result == 0) {
+			tlog(TLOG_DEBUG, "retry query %s, type: %d, id: %d failed", query->domain, query->qtype, query->sid);
+		}
+	} else {
+		tlog(TLOG_DEBUG, "retry query %s, type: %d, id: %d", query->domain, query->qtype, query->sid);
+		_dns_client_send_query(query);
+	}
+}
+
 static int _dns_client_add_hashmap(struct dns_query_struct *query)
 {
 	uint32_t key = 0;
@@ -4439,16 +4457,7 @@ static void _dns_client_period_run(unsigned int msec)
 		if (atomic_read(&query->retry_count) == 1) {
 			_dns_client_check_udp_nat(query);
 		}
-
-		if (atomic_dec_and_test(&query->retry_count) || (query->has_result != 0)) {
-			_dns_client_query_remove(query);
-			if (query->has_result == 0) {
-				tlog(TLOG_DEBUG, "retry query %s, type: %d, id: %d failed", query->domain, query->qtype, query->sid);
-			}
-		} else {
-			tlog(TLOG_DEBUG, "retry query %s, type: %d, id: %d", query->domain, query->qtype, query->sid);
-			_dns_client_send_query(query);
-		}
+		_dns_client_retry_dns_query(query);
 		_dns_client_query_release(query);
 	}
 

+ 1 - 0
src/dns_client.h

@@ -68,6 +68,7 @@ int dns_client_set_ecs(char *ip, int subnet);
 
 struct dns_server_info;
 /* query result notify function */
+#define DNS_CLIENT_RETRY (-2)
 typedef int (*dns_client_callback)(const char *domain, dns_result_type rtype, struct dns_server_info *server_info,
 								   struct dns_packet *packet, unsigned char *inpacket, int inpacket_len,
 								   void *user_ptr);

+ 3 - 7
src/dns_server.c

@@ -3745,14 +3745,10 @@ static int _dns_server_process_answer(struct dns_request *request, const char *d
 		request->rcode = packet->head.rcode;
 	}
 
-	if (has_result == 0 && request->rcode == DNS_RC_NOERROR) {
-		/* When queries A and AAAA from CloudFlare DNS at the same time and there is a retry, 
-		 * CloudFlare DNS may return the sent request packet. I don’t know the reason. 
-		 * Maybe retry should be considered?
-		 */
-		tlog(TLOG_DEBUG, "no result, %s qtype: %d, rcode: %d, id: %d", domain, request->qtype,
+	if (has_result == 0 && request->rcode == DNS_RC_NOERROR && packet->head.tc == 1) {
+		tlog(TLOG_DEBUG, "result is truncated, %s qtype: %d, rcode: %d, id: %d, retry.", domain, request->qtype,
 			 packet->head.rcode, packet->head.id);
-		return 0;
+		return DNS_CLIENT_RETRY;
 	}
 
 	return 0;