浏览代码

force-qtype-SOA: support qtype range.

Nick Peng 2 年之前
父节点
当前提交
ad43c796cf
共有 3 个文件被更改,包括 46 次插入44 次删除
  1. 33 21
      src/dns_conf.c
  2. 3 9
      src/dns_conf.h
  3. 10 14
      src/dns_server.c

+ 33 - 21
src/dns_conf.c

@@ -43,7 +43,7 @@ struct dns_nftset_table {
 };
 static struct dns_nftset_table dns_nftset_table;
 
-struct dns_qtype_soa_table dns_qtype_soa_table;
+uint8_t *dns_qtype_soa_table;
 
 struct dns_domain_set_name_table dns_domain_set_name_table;
 
@@ -2382,8 +2382,8 @@ static int _config_iplist_rule(char *subnet, enum address_rule rule)
 
 static int _config_qtype_soa(void *data, int argc, char *argv[])
 {
-	struct dns_qtype_soa_list *soa_list = NULL;
 	int i = 0;
+	int j = 0;
 
 	if (argc <= 1) {
 		return -1;
@@ -2393,19 +2393,31 @@ static int _config_qtype_soa(void *data, int argc, char *argv[])
 		char sub_arg[1024];
 		safe_strncpy(sub_arg, argv[i], sizeof(sub_arg));
 		for (char *tok = strtok(sub_arg, ","); tok; tok = strtok(NULL, ",")) {
-			soa_list = malloc(sizeof(*soa_list));
-			if (soa_list == NULL) {
-				tlog(TLOG_ERROR, "cannot malloc memory");
-				return -1;
+			char *dash = strstr(tok, "-");
+			if (dash != NULL) {
+				*dash = '\0';
+			}
+
+			long start = atol(tok);
+			long end = start;
+
+			if (start > MAX_QTYPE_NUM || start < 0) {
+				tlog(TLOG_ERROR, "invalid qtype %ld", start);
+				continue;
 			}
 
-			memset(soa_list, 0, sizeof(*soa_list));
-			soa_list->qtypeid = atol(tok);
-			if (soa_list->qtypeid == DNS_T_AAAA) {
-				dns_conf_force_AAAA_SOA = 1;
+			if (dash != NULL && *(dash + 1) != '\0') {
+				end = atol(dash + 1);
+				if (end > MAX_QTYPE_NUM) {
+					end = MAX_QTYPE_NUM;
+				}
+			}
+
+			for (j = start; j <= end; j++) {
+				int offset = j / 8;
+				int bit = j % 8;
+				dns_qtype_soa_table[offset] |= (1 << bit);
 			}
-			uint32_t key = hash_32_generic(soa_list->qtypeid, 32);
-			hash_add(dns_qtype_soa_table.qtype, &soa_list->node, key);
 		}
 	}
 
@@ -2414,14 +2426,9 @@ static int _config_qtype_soa(void *data, int argc, char *argv[])
 
 static void _config_qtype_soa_table_destroy(void)
 {
-	struct dns_qtype_soa_list *soa_list = NULL;
-	struct hlist_node *tmp = NULL;
-	unsigned long i = 0;
-
-	hash_for_each_safe(dns_qtype_soa_table.qtype, i, tmp, soa_list, node)
-	{
-		hlist_del_init(&soa_list->node);
-		free(soa_list);
+	if (dns_qtype_soa_table) {
+		free(dns_qtype_soa_table);
+		dns_qtype_soa_table = NULL;
 	}
 }
 
@@ -3530,7 +3537,12 @@ static int _dns_server_load_conf_init(void)
 
 	hash_init(dns_ipset_table.ipset);
 	hash_init(dns_nftset_table.nftset);
-	hash_init(dns_qtype_soa_table.qtype);
+	dns_qtype_soa_table = malloc(MAX_QTYPE_NUM / 8 + 1);
+	if (dns_qtype_soa_table == NULL) {
+		tlog(TLOG_WARN, "malloc qtype soa table failed.");
+		return -1;
+	}
+	memset(dns_qtype_soa_table, 0, MAX_QTYPE_NUM / 8 + 1);
 	hash_init(dns_group_table.group);
 	hash_init(dns_hosts_table.hosts);
 	hash_init(dns_ptr_table.ptr);

+ 3 - 9
src/dns_conf.h

@@ -57,6 +57,8 @@ extern "C" {
 #define DEFAULT_DNS_TLS_PORT 853
 #define DEFAULT_DNS_HTTPS_PORT 443
 #define DNS_MAX_CONF_CNAME_LEN 256
+#define MAX_QTYPE_NUM 65535
+
 #define SMARTDNS_CONF_FILE "/etc/smartdns/smartdns.conf"
 #define SMARTDNS_LOG_FILE "/var/log/smartdns/smartdns.log"
 #define SMARTDNS_AUDIT_FILE "/var/log/smartdns/smartdns-audit.log"
@@ -381,15 +383,7 @@ struct dns_bind_ip {
 	struct nftset_ipset_rules nftset_ipset_rule;
 };
 
-struct dns_qtype_soa_list {
-	struct hlist_node node;
-	uint32_t qtypeid;
-};
-
-struct dns_qtype_soa_table {
-	DECLARE_HASHTABLE(qtype, 8);
-};
-extern struct dns_qtype_soa_table dns_qtype_soa_table;
+extern uint8_t *dns_qtype_soa_table;
 
 struct dns_domain_set_rule {
 	struct list_head list;

+ 10 - 14
src/dns_server.c

@@ -285,7 +285,7 @@ struct dns_request {
 	int request_wait;
 	int prefetch;
 	int prefetch_expired_domain;
-	
+
 	int dualstack_selection;
 	int dualstack_selection_force_soa;
 	int dualstack_selection_query;
@@ -4574,25 +4574,21 @@ errout:
 
 static int _dns_server_qtype_soa(struct dns_request *request)
 {
-	struct dns_qtype_soa_list *soa_list = NULL;
-
-	if (request->skip_qtype_soa) {
+	if (request->skip_qtype_soa || dns_qtype_soa_table == NULL) {
 		return -1;
 	}
 
-	uint32_t key = hash_32_generic(request->qtype, 32);
-	hash_for_each_possible(dns_qtype_soa_table.qtype, soa_list, node, key)
-	{
-		if (request->qtype != soa_list->qtypeid) {
-			continue;
+	if (request->qtype >= 0 && request->qtype <= MAX_QTYPE_NUM) {
+		int offset = request->qtype / 8;
+		int bit = request->qtype % 8;
+		if ((dns_qtype_soa_table[offset] & (1 << bit)) == 0) {
+			return -1;
 		}
-
-		_dns_server_reply_SOA(DNS_RC_NOERROR, request);
-		tlog(TLOG_DEBUG, "force qtype %d soa", request->qtype);
-		return 0;
 	}
 
-	return -1;
+	_dns_server_reply_SOA(DNS_RC_NOERROR, request);
+	tlog(TLOG_DEBUG, "force qtype %d soa", request->qtype);
+	return 0;
 }
 
 static void _dns_server_process_speed_rule(struct dns_request *request)