2
0
Эх сурвалжийг харах

conf: make all config in rule group.

Nick Peng 1 жил өмнө
parent
commit
d02fec5c0e
6 өөрчлөгдсөн 295 нэмэгдсэн , 149 устгасан
  1. 3 2
      src/dns_cache.c
  2. 154 65
      src/dns_conf.c
  3. 16 17
      src/dns_conf.h
  4. 59 50
      src/dns_server.c
  5. 36 15
      src/include/conf.h
  6. 27 0
      src/lib/conf.c

+ 3 - 2
src/dns_cache.c

@@ -569,9 +569,10 @@ static int _dns_cache_read_to_cache(struct dns_cache_record *cache_record, struc
 		info->replace_time = now;
 	}
 
-	expired_time = dns_conf_serve_expired_prefetch_time;
+	struct dns_conf_group *rule_group = dns_server_get_rule_group(info->dns_group_name);
+	expired_time = rule_group->dns_serve_expired_prefetch_time;
 	if (expired_time == 0) {
-		expired_time = dns_conf_serve_expired_ttl / 2;
+		expired_time = rule_group->dns_serve_expired_ttl / 2;
 		if (expired_time == 0 || expired_time > EXPIRED_DOMAIN_PREFETCH_TIME) {
 			expired_time = EXPIRED_DOMAIN_PREFETCH_TIME;
 		}

+ 154 - 65
src/dns_conf.c

@@ -76,7 +76,6 @@ char dns_conf_bind_ca_key_file[DNS_MAX_PATH];
 char dns_conf_bind_ca_key_pass[DNS_MAX_PATH];
 char dns_conf_need_cert = 0;
 
-int dns_conf_max_reply_ip_num = DNS_MAX_REPLY_IP_NUM;
 int dns_conf_max_query_limit = DNS_MAX_QUERY_LIMIT;
 
 static struct config_enum_list dns_conf_response_mode_enum[] = {
@@ -85,15 +84,10 @@ static struct config_enum_list dns_conf_response_mode_enum[] = {
 	{"fastest-response", DNS_RESPONSE_MODE_FASTEST_RESPONSE},
 	{NULL, 0}};
 
-enum response_mode_type dns_conf_response_mode;
+enum response_mode_type dns_conf_default_response_mode = DNS_RESPONSE_MODE_FIRST_PING_IP;
 
 /* cache */
 ssize_t dns_conf_cachesize = -1;
-int dns_conf_prefetch = 0;
-int dns_conf_serve_expired = 1;
-int dns_conf_serve_expired_ttl = 24 * 3600 * 3; /* 3 days */
-int dns_conf_serve_expired_prefetch_time;
-int dns_conf_serve_expired_reply_ttl = 3;
 
 /* upstream servers */
 struct dns_servers dns_conf_servers[DNS_MAX_SERVERS];
@@ -155,19 +149,8 @@ static LIST_HEAD(dns_conf_group_info_list);
 struct dns_conf_rule dns_conf_rule;
 struct dns_conf_client_rule dns_conf_client_rule;
 
-/* dual-stack selection */
-int dns_conf_dualstack_ip_allow_force_AAAA;
-int dns_conf_dualstack_ip_selection_threshold = 10;
-
 static int dns_conf_expand_ptr_from_address = 0;
-
-/* TTL */
-int dns_conf_rr_ttl;
-int dns_conf_rr_ttl_reply_max;
-int dns_conf_rr_ttl_min = 600;
-int dns_conf_rr_ttl_max;
 int dns_conf_local_ttl;
-int dns_conf_force_no_cname;
 int dns_conf_nftset_debug_enable;
 int dns_conf_mdns_lookup;
 int dns_conf_acl_enable;
@@ -205,6 +188,97 @@ static int _config_nftset_setvalue(struct dns_nftset_names *nftsets, const char
 static int _config_client_rule_flag_set(const char *ip_cidr, unsigned int flag, unsigned int is_clear);
 static int _config_client_rule_group_add(const char *client, const char *group_name);
 
+static __attribute__((unused)) int _dns_conf_group_int(int value, int *data)
+{
+	struct dns_conf_group *conf_group = _config_current_rule_group();
+	if (conf_group == NULL) {
+		return -1;
+	}
+
+	void *ptr = (char *)conf_group + (size_t)data;
+	*(int *)ptr = value;
+
+	return 0;
+}
+
+static __attribute__((unused)) int _dns_conf_group_int_base(int value, int *data)
+{
+	struct dns_conf_group *conf_group = _config_current_rule_group();
+	if (conf_group == NULL) {
+		return -1;
+	}
+
+	void *ptr = (char *)conf_group + (size_t)data;
+	*(int *)ptr = value;
+
+	return 0;
+}
+
+static __attribute__((unused)) int _dns_conf_group_string(const char *value, char *data)
+{
+	struct dns_conf_group *conf_group = _config_current_rule_group();
+	if (conf_group == NULL) {
+		return -1;
+	}
+
+	char *ptr = (char *)conf_group + (size_t)data;
+	safe_strncpy(ptr, value, DNS_MAX_PATH);
+
+	return 0;
+}
+
+static __attribute__((unused)) int _dns_conf_group_yesno(int value, int *data)
+{
+	struct dns_conf_group *conf_group = _config_current_rule_group();
+	if (conf_group == NULL) {
+		return -1;
+	}
+
+	void *ptr = (char *)conf_group + (size_t)data;
+	*(int *)ptr = value;
+
+	return 0;
+}
+
+static __attribute__((unused)) int _dns_conf_group_size(size_t value, size_t *data)
+{
+	struct dns_conf_group *conf_group = _config_current_rule_group();
+	if (conf_group == NULL) {
+		return -1;
+	}
+
+	void *ptr = (char *)conf_group + (size_t)data;
+	*(size_t *)ptr = value;
+
+	return 0;
+}
+
+static __attribute__((unused)) int _dns_conf_group_ssize(ssize_t value, ssize_t *data)
+{
+	struct dns_conf_group *conf_group = _config_current_rule_group();
+	if (conf_group == NULL) {
+		return -1;
+	}
+
+	void *ptr = (char *)conf_group + (size_t)data;
+	*(ssize_t *)ptr = value;
+
+	return 0;
+}
+
+static __attribute__((unused)) int _dns_conf_group_enum(int value, int *data)
+{
+	struct dns_conf_group *conf_group = _config_current_rule_group();
+	if (conf_group == NULL) {
+		return -1;
+	}
+
+	void *ptr = (char *)conf_group + (size_t)data;
+	*(int *)ptr = value;
+
+	return 0;
+}
+
 static void *_new_dns_rule_ext(enum domain_rule domain_rule, int ext_size)
 {
 	struct dns_rule *rule;
@@ -521,6 +595,12 @@ static int _config_rule_group_setup_value(struct dns_conf_group_info *group_info
 	memset(soa_table, 0, soa_talbe_size);
 	memcpy(&group_rule->check_orders, &dns_conf_default_check_orders, sizeof(group_rule->check_orders));
 	group_rule->dualstack_ip_selection = 1;
+	group_rule->dns_dualstack_ip_selection_threshold = 10;
+	group_rule->dns_rr_ttl_min = 600;
+	group_rule->dns_serve_expired_ttl = 24 * 3600 * 3;
+	group_rule->dns_serve_expired_reply_ttl = 3;
+	group_rule->dns_max_reply_ip_num = DNS_MAX_REPLY_IP_NUM;
+	group_rule->dns_response_mode = dns_conf_default_response_mode;
 
 	return 0;
 }
@@ -2516,14 +2596,6 @@ static int _config_speed_check_mode(void *data, int argc, char *argv[])
 	return _config_speed_check_mode_parser(&_config_current_rule_group()->check_orders, mode);
 }
 
-static int _config_dualstack_ip_selection(void *data, int argc, char *argv[])
-{
-	struct config_item_yesno item;
-
-	item.data = &_config_current_rule_group()->dualstack_ip_selection;
-	return conf_yesno(NULL, &item, argc, argv);
-}
-
 static int _config_dns64(void *data, int argc, char *argv[])
 {
 	prefix_t prefix;
@@ -3538,14 +3610,6 @@ errout:
 	return -1;
 }
 
-static int _config_force_AAAA_soa(void *data, int argc, char *argv[])
-{
-	struct config_item_yesno item;
-
-	item.data = &_config_current_rule_group()->force_AAAA_SOA;
-	return conf_yesno(NULL, &item, argc, argv);
-}
-
 static int _conf_qtype_soa(uint8_t *soa_table, int argc, char *argv[])
 {
 	int i = 0;
@@ -5536,14 +5600,20 @@ static struct config_item _config_item[] = {
 	CONF_CUSTOM("cache-file", _config_option_parser_filepath, (char *)&dns_conf_cache_file),
 	CONF_YESNO("cache-persist", &dns_conf_cache_persist),
 	CONF_INT("cache-checkpoint-time", &dns_conf_cache_checkpoint_time, 0, 3600 * 24 * 7),
-	CONF_YESNO("prefetch-domain", &dns_conf_prefetch),
-	CONF_YESNO("serve-expired", &dns_conf_serve_expired),
-	CONF_INT("serve-expired-ttl", &dns_conf_serve_expired_ttl, 0, CONF_INT_MAX),
-	CONF_INT("serve-expired-reply-ttl", &dns_conf_serve_expired_reply_ttl, 0, CONF_INT_MAX),
-	CONF_INT("serve-expired-prefetch-time", &dns_conf_serve_expired_prefetch_time, 0, CONF_INT_MAX),
-	CONF_CUSTOM("dualstack-ip-selection", _config_dualstack_ip_selection, NULL),
-	CONF_YESNO("dualstack-ip-allow-force-AAAA", &dns_conf_dualstack_ip_allow_force_AAAA),
-	CONF_INT("dualstack-ip-selection-threshold", &dns_conf_dualstack_ip_selection_threshold, 0, 1000),
+	CONF_YESNO_FUNC("prefetch-domain", _dns_conf_group_yesno, (void *)offsetof(struct dns_conf_group, dns_prefetch)),
+	CONF_YESNO_FUNC("serve-expired", _dns_conf_group_yesno, (void *)offsetof(struct dns_conf_group, dns_serve_expired)),
+	CONF_INT_FUNC("serve-expired-ttl", _dns_conf_group_int,
+				  (void *)offsetof(struct dns_conf_group, dns_serve_expired_ttl), 0, CONF_INT_MAX),
+	CONF_INT_FUNC("serve-expired-reply-ttl", _dns_conf_group_int,
+				  (void *)offsetof(struct dns_conf_group, dns_serve_expired_reply_ttl), 0, CONF_INT_MAX),
+	CONF_INT_FUNC("serve-expired-prefetch-time", _dns_conf_group_int,
+				  (void *)offsetof(struct dns_conf_group, dns_serve_expired_prefetch_time), 0, CONF_INT_MAX),
+	CONF_YESNO_FUNC("dualstack-ip-selection", _dns_conf_group_yesno,
+					(void *)offsetof(struct dns_conf_group, dualstack_ip_selection)),
+	CONF_YESNO_FUNC("dualstack-ip-allow-force-AAAA", _dns_conf_group_yesno,
+					(void *)offsetof(struct dns_conf_group, dns_dualstack_ip_allow_force_AAAA)),
+	CONF_INT_FUNC("dualstack-ip-selection-threshold", _dns_conf_group_int,
+				  (void *)offsetof(struct dns_conf_group, dns_dualstack_ip_selection_threshold), 0, 1000),
 	CONF_CUSTOM("dns64", _config_dns64, NULL),
 	CONF_CUSTOM("log-level", _config_log_level, NULL),
 	CONF_CUSTOM("log-file", _config_option_parser_filepath, (char *)dns_conf_log_file),
@@ -5561,16 +5631,23 @@ static struct config_item _config_item[] = {
 	CONF_YESNO("audit-console", &dns_conf_audit_console),
 	CONF_YESNO("audit-syslog", &dns_conf_audit_syslog),
 	CONF_YESNO("acl-enable", &dns_conf_acl_enable),
-	CONF_INT("rr-ttl", &dns_conf_rr_ttl, 0, CONF_INT_MAX),
-	CONF_INT("rr-ttl-min", &dns_conf_rr_ttl_min, 0, CONF_INT_MAX),
-	CONF_INT("rr-ttl-max", &dns_conf_rr_ttl_max, 0, CONF_INT_MAX),
-	CONF_INT("rr-ttl-reply-max", &dns_conf_rr_ttl_reply_max, 0, CONF_INT_MAX),
-	CONF_INT("local-ttl", &dns_conf_local_ttl, 0, CONF_INT_MAX),
-	CONF_INT("max-reply-ip-num", &dns_conf_max_reply_ip_num, 1, CONF_INT_MAX),
+	CONF_INT_FUNC("rr-ttl", _dns_conf_group_int, (void *)offsetof(struct dns_conf_group, dns_rr_ttl), 0, CONF_INT_MAX),
+	CONF_INT_FUNC("rr-ttl-min", _dns_conf_group_int, (void *)offsetof(struct dns_conf_group, dns_rr_ttl_min), 0,
+				  CONF_INT_MAX),
+	CONF_INT_FUNC("rr-ttl-max", _dns_conf_group_int, (void *)offsetof(struct dns_conf_group, dns_rr_ttl_max), 0,
+				  CONF_INT_MAX),
+	CONF_INT_FUNC("rr-ttl-reply-max", _dns_conf_group_int,
+				  (void *)offsetof(struct dns_conf_group, dns_rr_ttl_reply_max), 0, CONF_INT_MAX),
+	CONF_INT_FUNC("local-ttl", _dns_conf_group_int, (void *)offsetof(struct dns_conf_group, dns_local_ttl), 0,
+				  CONF_INT_MAX),
+	CONF_INT_FUNC("max-reply-ip-num", _dns_conf_group_int,
+				  (void *)offsetof(struct dns_conf_group, dns_max_reply_ip_num), 1, CONF_INT_MAX),
 	CONF_INT("max-query-limit", &dns_conf_max_query_limit, 0, CONF_INT_MAX),
-	CONF_ENUM("response-mode", &dns_conf_response_mode, &dns_conf_response_mode_enum),
-	CONF_CUSTOM("force-AAAA-SOA", _config_force_AAAA_soa, NULL),
-	CONF_YESNO("force-no-CNAME", &dns_conf_force_no_cname),
+	CONF_ENUM_FUNC("response-mode", _dns_conf_group_enum, (void *)offsetof(struct dns_conf_group, dns_response_mode),
+				   &dns_conf_response_mode_enum),
+	CONF_YESNO_FUNC("force-AAAA-SOA", _dns_conf_group_yesno, (void *)offsetof(struct dns_conf_group, force_AAAA_SOA)),
+	CONF_YESNO_FUNC("force-no-CNAME", _dns_conf_group_yesno,
+					(void *)offsetof(struct dns_conf_group, dns_force_no_cname)),
 	CONF_CUSTOM("force-qtype-SOA", _config_qtype_soa, NULL),
 	CONF_CUSTOM("blacklist-ip", _config_blacklist_ip, NULL),
 	CONF_CUSTOM("whitelist-ip", _conf_whitelist_ip, NULL),
@@ -5980,6 +6057,30 @@ static void _dns_conf_auto_set_cache_size(void)
 	}
 }
 
+static void _dns_conf_group_post(void)
+{
+	struct dns_conf_group *group;
+	struct hlist_node *tmp = NULL;
+	unsigned long i = 0;
+
+	hash_for_each_safe(dns_conf_rule.group, i, tmp, group, node)
+	{
+		if (dns_conf_cachesize == 0 && group->dns_response_mode == DNS_RESPONSE_MODE_FASTEST_RESPONSE) {
+			group->dns_response_mode = DNS_RESPONSE_MODE_FASTEST_IP;
+			tlog(TLOG_WARN, "force set response of group %s to %s as cache size is 0", group->group_name,
+				 dns_conf_response_mode_enum[group->dns_response_mode].name);
+		}
+
+		if ((group->dns_rr_ttl_min > group->dns_rr_ttl_max) && group->dns_rr_ttl_max > 0) {
+			group->dns_rr_ttl_min = group->dns_rr_ttl_max;
+		}
+
+		if ((group->dns_rr_ttl_max < group->dns_rr_ttl_min) && group->dns_rr_ttl_max > 0) {
+			group->dns_rr_ttl_max = group->dns_rr_ttl_min;
+		}
+	}
+}
+
 static int _dns_conf_load_post(void)
 {
 	_config_setup_smartdns_domain();
@@ -5989,24 +6090,12 @@ static int _dns_conf_load_post(void)
 
 	_dns_conf_setup_mdns();
 
-	if (dns_conf_cachesize == 0 && dns_conf_response_mode == DNS_RESPONSE_MODE_FASTEST_RESPONSE) {
-		dns_conf_response_mode = DNS_RESPONSE_MODE_FASTEST_IP;
-		tlog(TLOG_WARN, "force set response to %s as cache size is 0",
-			 dns_conf_response_mode_enum[dns_conf_response_mode].name);
-	}
-
-	if ((dns_conf_rr_ttl_min > dns_conf_rr_ttl_max) && dns_conf_rr_ttl_max > 0) {
-		dns_conf_rr_ttl_min = dns_conf_rr_ttl_max;
-	}
-
-	if ((dns_conf_rr_ttl_max < dns_conf_rr_ttl_min) && dns_conf_rr_ttl_max > 0) {
-		dns_conf_rr_ttl_max = dns_conf_rr_ttl_min;
-	}
-
 	if (dns_resolv_file[0] == '\0') {
 		safe_strncpy(dns_resolv_file, DNS_RESOLV_FILE, sizeof(dns_resolv_file));
 	}
 
+	_dns_conf_group_post();
+
 	_config_domain_set_name_table_destroy();
 
 	_config_ip_set_name_table_destroy();

+ 16 - 17
src/dns_conf.h

@@ -432,6 +432,21 @@ struct dns_conf_group {
 	struct dns_edns_client_subnet ipv6_ecs;
 	int force_AAAA_SOA;
 	int dualstack_ip_selection;
+	int dns_dualstack_ip_allow_force_AAAA;
+	int dns_dualstack_ip_selection_threshold;
+	int dns_rr_ttl;
+	int dns_rr_ttl_reply_max;
+	int dns_rr_ttl_min;
+	int dns_rr_ttl_max;
+	int dns_local_ttl;
+	int dns_force_no_cname;
+	int dns_prefetch;
+	int dns_serve_expired;
+	int dns_serve_expired_ttl;
+	int dns_serve_expired_prefetch_time;
+	int dns_serve_expired_reply_ttl;
+	int dns_max_reply_ip_num;
+	enum response_mode_type dns_response_mode;
 	char copy_data_section_end[0];
 	const char *group_name;
 };
@@ -607,11 +622,6 @@ extern char dns_conf_need_cert;
 
 extern int dns_conf_tcp_idle_time;
 extern ssize_t dns_conf_cachesize;
-extern int dns_conf_prefetch;
-extern int dns_conf_serve_expired;
-extern int dns_conf_serve_expired_ttl;
-extern int dns_conf_serve_expired_prefetch_time;
-extern int dns_conf_serve_expired_reply_ttl;
 extern struct dns_servers dns_conf_servers[DNS_MAX_SERVERS];
 extern int dns_conf_server_num;
 
@@ -655,24 +665,13 @@ extern char dns_conf_server_name[DNS_MAX_SERVER_NAME_LEN];
 extern struct dns_conf_domain_rule dns_conf_domain_rule;
 extern struct dns_conf_client_rule dns_conf_client_rule;
 
-extern int dns_conf_dualstack_ip_allow_force_AAAA;
-extern int dns_conf_dualstack_ip_selection_threshold;
-
-extern int dns_conf_max_reply_ip_num;
 extern int dns_conf_max_query_limit;
-extern enum response_mode_type dns_conf_response_mode;
-
-extern int dns_conf_rr_ttl;
-extern int dns_conf_rr_ttl_reply_max;
-extern int dns_conf_rr_ttl_min;
-extern int dns_conf_rr_ttl_max;
+extern enum response_mode_type dns_conf_default_response_mode;
 extern int dns_conf_nftset_debug_enable;
 extern int dns_conf_local_ttl;
 extern int dns_conf_mdns_lookup;
 extern int dns_conf_acl_enable;
 
-extern int dns_conf_force_no_cname;
-
 extern char dns_conf_user[DNS_CONF_USERNAME_LEN];
 
 extern char dns_conf_sni_proxy_ip[DNS_MAX_IPLEN];

+ 59 - 50
src/dns_server.c

@@ -461,9 +461,9 @@ static void *_dns_server_get_bind_ipset_nftset_rule(struct dns_request *request,
 
 static int _dns_server_get_conf_ttl(struct dns_request *request, int ttl)
 {
-	int rr_ttl = dns_conf_rr_ttl;
-	int rr_ttl_min = dns_conf_rr_ttl_min;
-	int rr_ttl_max = dns_conf_rr_ttl_max;
+	int rr_ttl = request->conf->dns_rr_ttl;
+	int rr_ttl_min = request->conf->dns_rr_ttl_min;
+	int rr_ttl_max = request->conf->dns_rr_ttl_max;
 
 	if (request->is_mdns_lookup) {
 		rr_ttl_min = DNS_SERVER_ADDR_TTL;
@@ -478,14 +478,15 @@ static int _dns_server_get_conf_ttl(struct dns_request *request, int ttl)
 		/* make domain rule ttl high priority */
 		if (ttl_rule->ttl_min > 0) {
 			rr_ttl_min = ttl_rule->ttl_min;
-			if (dns_conf_rr_ttl_max <= rr_ttl_min && dns_conf_rr_ttl_max > 0) {
+			if (request->conf->dns_rr_ttl_max <= rr_ttl_min && request->conf->dns_rr_ttl_max > 0) {
 				rr_ttl_max = rr_ttl_min;
 			}
 		}
 
 		if (ttl_rule->ttl_max > 0) {
 			rr_ttl_max = ttl_rule->ttl_max;
-			if (dns_conf_rr_ttl_min >= rr_ttl_max && dns_conf_rr_ttl_min > 0 && ttl_rule->ttl_min <= 0) {
+			if (request->conf->dns_rr_ttl_min >= rr_ttl_max && request->conf->dns_rr_ttl_min > 0 &&
+				ttl_rule->ttl_min <= 0) {
 				rr_ttl_min = rr_ttl_max;
 			}
 		}
@@ -515,7 +516,7 @@ static int _dns_server_get_reply_ttl(struct dns_request *request, int ttl)
 
 	if ((request->passthrough == 0 || request->passthrough == 2) && dns_conf_cachesize > 0 &&
 		request->check_order_list->orders[0].type != DOMAIN_CHECK_NONE) {
-		reply_ttl = dns_conf_serve_expired_reply_ttl;
+		reply_ttl = request->conf->dns_serve_expired_reply_ttl;
 		if (reply_ttl < 2) {
 			reply_ttl = 2;
 		}
@@ -939,7 +940,7 @@ static int _dns_rrs_add_all_best_ip(struct dns_server_post_context *context)
 	int ignore_speed = 0;
 	int maxhit = 0;
 
-	if (context->select_all_best_ip == 0 || context->ip_num >= dns_conf_max_reply_ip_num) {
+	if (context->select_all_best_ip == 0 || context->ip_num >= request->conf->dns_max_reply_ip_num) {
 		return 0;
 	}
 
@@ -963,7 +964,7 @@ static int _dns_rrs_add_all_best_ip(struct dns_server_post_context *context)
 		pthread_mutex_lock(&request->ip_map_lock);
 		hash_for_each_safe(request->ip_map, bucket, tmp, addr_map, node)
 		{
-			if (context->ip_num >= dns_conf_max_reply_ip_num) {
+			if (context->ip_num >= request->conf->dns_max_reply_ip_num) {
 				break;
 			}
 
@@ -1438,9 +1439,9 @@ static int _dns_reply_inpacket(struct dns_request *request, unsigned char *inpac
 	return ret;
 }
 
-static inline int _dns_server_expired_cache_ttl(struct dns_cache *cache)
+static inline int _dns_server_expired_cache_ttl(struct dns_cache *cache, int serve_expired_ttl)
 {
-	return cache->info.insert_time + cache->info.ttl + dns_conf_serve_expired_ttl - time(NULL);
+	return cache->info.insert_time + cache->info.ttl + serve_expired_ttl - time(NULL);
 }
 
 static int _dns_cache_is_specify_packet(int qtype)
@@ -1463,7 +1464,7 @@ static int _dns_server_get_cache_timeout(struct dns_request *request, struct dns
 {
 	int timeout = 0;
 	int prefetch_time = 0;
-	int is_serve_expired = dns_conf_serve_expired;
+	int is_serve_expired = request->conf->dns_serve_expired;
 
 	if (request->rcode != DNS_RC_NOERROR) {
 		return ttl + 1;
@@ -1473,7 +1474,7 @@ static int _dns_server_get_cache_timeout(struct dns_request *request, struct dns
 		return ttl + 1;
 	}
 
-	if (dns_conf_prefetch) {
+	if (request->conf->dns_prefetch) {
 		prefetch_time = 1;
 	}
 
@@ -1491,9 +1492,9 @@ static int _dns_server_get_cache_timeout(struct dns_request *request, struct dns
 
 	if (prefetch_time == 1) {
 		if (is_serve_expired) {
-			timeout = dns_conf_serve_expired_prefetch_time;
+			timeout = request->conf->dns_serve_expired_prefetch_time;
 			if (timeout == 0) {
-				timeout = dns_conf_serve_expired_ttl / 2;
+				timeout = request->conf->dns_serve_expired_ttl / 2;
 				if (timeout == 0 || timeout > EXPIRED_DOMAIN_PREFETCH_TIME) {
 					timeout = EXPIRED_DOMAIN_PREFETCH_TIME;
 				}
@@ -1504,7 +1505,8 @@ static int _dns_server_get_cache_timeout(struct dns_request *request, struct dns
 			} else if (cache_key != NULL) {
 				struct dns_cache *old_cache = dns_cache_lookup(cache_key);
 				if (old_cache) {
-					time_t next_ttl = _dns_server_expired_cache_ttl(old_cache) - old_cache->info.ttl + ttl;
+					time_t next_ttl = _dns_server_expired_cache_ttl(old_cache, request->conf->dns_serve_expired_ttl) -
+									  old_cache->info.ttl + ttl;
 					if (next_ttl < timeout) {
 						timeout = next_ttl;
 					}
@@ -1517,7 +1519,7 @@ static int _dns_server_get_cache_timeout(struct dns_request *request, struct dns
 	} else {
 		timeout = ttl;
 		if (is_serve_expired) {
-			timeout += dns_conf_serve_expired_ttl;
+			timeout += request->conf->dns_serve_expired_ttl;
 		}
 
 		timeout += 3;
@@ -2132,17 +2134,17 @@ static int _dns_request_update_id_ttl(struct dns_server_post_context *context)
 	int ttl = context->reply_ttl;
 	struct dns_request *request = context->request;
 
-	if (dns_conf_rr_ttl_reply_max > 0) {
-		if (request->ip_ttl > dns_conf_rr_ttl_reply_max && ttl == 0) {
+	if (request->conf->dns_rr_ttl_reply_max > 0) {
+		if (request->ip_ttl > request->conf->dns_rr_ttl_reply_max && ttl == 0) {
 			ttl = request->ip_ttl;
 		}
 
-		if (ttl > dns_conf_rr_ttl_reply_max) {
-			ttl = dns_conf_rr_ttl_reply_max;
+		if (ttl > request->conf->dns_rr_ttl_reply_max) {
+			ttl = request->conf->dns_rr_ttl_reply_max;
 		}
 
 		if (ttl == 0) {
-			ttl = dns_conf_rr_ttl_reply_max;
+			ttl = request->conf->dns_rr_ttl_reply_max;
 		}
 	}
 
@@ -2343,7 +2345,7 @@ static void _dns_server_check_complete_dualstack(struct dns_request *request, st
 		return;
 	}
 
-	if (dualstack_request->qtype == DNS_T_A && dns_conf_dualstack_ip_allow_force_AAAA == 0) {
+	if (dualstack_request->qtype == DNS_T_A && request->conf->dns_dualstack_ip_allow_force_AAAA == 0) {
 		return;
 	}
 
@@ -2355,7 +2357,7 @@ static void _dns_server_check_complete_dualstack(struct dns_request *request, st
 		return;
 	}
 
-	if (request->ping_time <= (dns_conf_dualstack_ip_selection_threshold * 10)) {
+	if (request->ping_time <= (request->conf->dns_dualstack_ip_selection_threshold * 10)) {
 		return;
 	}
 
@@ -2390,13 +2392,13 @@ static int _dns_server_force_dualstack(struct dns_request *request)
 	}
 
 	if (request->ping_time > 0) {
-		if (request->dualstack_selection_ping_time + (dns_conf_dualstack_ip_selection_threshold * 10) >
+		if (request->dualstack_selection_ping_time + (request->conf->dns_dualstack_ip_selection_threshold * 10) >
 			request->ping_time) {
 			return -1;
 		}
 	}
 
-	if (request->qtype == DNS_T_A && dns_conf_dualstack_ip_allow_force_AAAA == 0) {
+	if (request->qtype == DNS_T_A && request->conf->dns_dualstack_ip_allow_force_AAAA == 0) {
 		return -1;
 	}
 
@@ -2537,7 +2539,7 @@ static int _dns_ip_address_check_add(struct dns_request *request, char *cname, u
 	addr_map->recv_tick = get_tick_count();
 	addr_map->ping_time = ping_time;
 	memcpy(addr_map->ip_addr, addr, addr_len);
-	if (dns_conf_force_no_cname == 0) {
+	if (request->conf->dns_force_no_cname == 0) {
 		safe_strncpy(addr_map->cname, cname, DNS_MAX_CNAME_LEN);
 	}
 
@@ -2630,14 +2632,14 @@ static void _dns_server_select_possible_ipaddress(struct dns_request *request)
 	switch (request->qtype) {
 	case DNS_T_A: {
 		memcpy(request->ip_addr, selected_addr_map->ip_addr, DNS_RR_A_LEN);
-		request->ip_ttl = dns_conf_rr_ttl_min > 0 ? dns_conf_rr_ttl_min : DNS_SERVER_TMOUT_TTL;
+		request->ip_ttl = request->conf->dns_rr_ttl_min > 0 ? request->conf->dns_rr_ttl_min : DNS_SERVER_TMOUT_TTL;
 		tlog(TLOG_DEBUG, "possible result: %s, rcode: %d,  hitnum: %d, %d.%d.%d.%d", request->domain, request->rcode,
 			 selected_addr_map->hitnum, request->ip_addr[0], request->ip_addr[1], request->ip_addr[2],
 			 request->ip_addr[3]);
 	} break;
 	case DNS_T_AAAA: {
 		memcpy(request->ip_addr, selected_addr_map->ip_addr, DNS_RR_AAAA_LEN);
-		request->ip_ttl = dns_conf_rr_ttl_min > 0 ? dns_conf_rr_ttl_min : DNS_SERVER_TMOUT_TTL;
+		request->ip_ttl = request->conf->dns_rr_ttl_min > 0 ? request->conf->dns_rr_ttl_min : DNS_SERVER_TMOUT_TTL;
 		tlog(TLOG_DEBUG,
 			 "possible result: %s, rcode: %d,  hitnum: %d, "
 			 "%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x",
@@ -2849,8 +2851,9 @@ static struct dns_request *_dns_server_new_request(void)
 	request->conn = NULL;
 	request->qclass = DNS_C_IN;
 	request->result_callback = NULL;
+	request->conf = dns_server_get_default_rule_group();
 	request->check_order_list = &dns_conf_default_check_orders;
-	request->response_mode = dns_conf_response_mode;
+	request->response_mode = dns_conf_default_response_mode;
 	INIT_LIST_HEAD(&request->list);
 	INIT_LIST_HEAD(&request->pending_list);
 	INIT_LIST_HEAD(&request->check_list);
@@ -3514,7 +3517,7 @@ static int _dns_server_process_answer_A(struct dns_rrs *rrs, struct dns_request
 			request->has_ip = 1;
 			memcpy(request->ip_addr, paddr, DNS_RR_A_LEN);
 			request->ip_ttl = _dns_server_get_conf_ttl(request, ttl);
-			if (cname[0] != 0 && request->has_cname == 0 && dns_conf_force_no_cname == 0) {
+			if (cname[0] != 0 && request->has_cname == 0 && request->conf->dns_force_no_cname == 0) {
 				request->has_cname = 1;
 				safe_strncpy(request->cname, cname, DNS_MAX_CNAME_LEN);
 			}
@@ -3600,7 +3603,7 @@ static int _dns_server_process_answer_AAAA(struct dns_rrs *rrs, struct dns_reque
 			request->has_ip = 1;
 			memcpy(request->ip_addr, paddr, DNS_RR_AAAA_LEN);
 			request->ip_ttl = _dns_server_get_conf_ttl(request, ttl);
-			if (cname[0] != 0 && request->has_cname == 0 && dns_conf_force_no_cname == 0) {
+			if (cname[0] != 0 && request->has_cname == 0 && request->conf->dns_force_no_cname == 0) {
 				request->has_cname = 1;
 				safe_strncpy(request->cname, cname, DNS_MAX_CNAME_LEN);
 			}
@@ -3983,7 +3986,7 @@ static int _dns_server_get_answer(struct dns_server_post_context *context)
 			case DNS_T_CNAME: {
 				char cname[DNS_MAX_CNAME_LEN];
 				char name[DNS_MAX_CNAME_LEN] = {0};
-				if (dns_conf_force_no_cname) {
+				if (request->conf->dns_force_no_cname) {
 					continue;
 				}
 
@@ -4687,12 +4690,12 @@ static int _dns_server_get_local_ttl(struct dns_request *request)
 		return dns_conf_local_ttl;
 	}
 
-	if (dns_conf_rr_ttl > 0) {
-		return dns_conf_rr_ttl;
+	if (request->conf->dns_rr_ttl > 0) {
+		return request->conf->dns_rr_ttl;
 	}
 
-	if (dns_conf_rr_ttl_min > 0) {
-		return dns_conf_rr_ttl_min;
+	if (request->conf->dns_rr_ttl_min > 0) {
+		return request->conf->dns_rr_ttl_min;
 	}
 
 	return DNS_SERVER_ADDR_TTL;
@@ -5304,7 +5307,7 @@ static DNS_CHILD_POST_RESULT _dns_server_process_cname_callback(struct dns_reque
 																struct dns_request *child_request, int is_first_resp)
 {
 	_dns_server_request_copy(request, child_request);
-	if (child_request->rcode == DNS_RC_NOERROR && dns_conf_force_no_cname == 0 && child_request->has_soa == 0) {
+	if (child_request->rcode == DNS_RC_NOERROR && request->conf->dns_force_no_cname == 0 && child_request->has_soa == 0) {
 		safe_strncpy(request->cname, child_request->domain, sizeof(request->cname));
 		request->has_cname = 1;
 		request->ttl_cname = _dns_server_get_conf_ttl(request, child_request->ip_ttl);
@@ -5610,17 +5613,19 @@ static void _dns_server_process_speed_rule(struct dns_request *request)
 	response_mode = _dns_server_get_dns_rule(request, DOMAIN_RULE_RESPONSE_MODE);
 	if (response_mode != NULL) {
 		request->response_mode = response_mode->mode;
+	} else {
+		request->response_mode = request->conf->dns_response_mode;
 	}
 }
 
-static int _dns_server_get_expired_ttl_reply(struct dns_cache *dns_cache)
+static int _dns_server_get_expired_ttl_reply(struct dns_request *request, struct dns_cache *dns_cache)
 {
 	int ttl = dns_cache_get_ttl(dns_cache);
 	if (ttl > 0) {
 		return ttl;
 	}
 
-	return dns_conf_serve_expired_reply_ttl;
+	return request->conf->dns_serve_expired_reply_ttl;
 }
 
 static int _dns_server_process_cache_packet(struct dns_request *request, struct dns_cache *dns_cache)
@@ -5664,7 +5669,7 @@ static int _dns_server_process_cache_packet(struct dns_request *request, struct
 	context.do_ipset = do_ipset;
 	context.do_audit = 1;
 	context.do_reply = 1;
-	context.reply_ttl = _dns_server_get_expired_ttl_reply(dns_cache);
+	context.reply_ttl = _dns_server_get_expired_ttl_reply(request, dns_cache);
 	ret = _dns_server_reply_passthrough(&context);
 out:
 	if (cache_packet) {
@@ -5714,7 +5719,7 @@ static int _dns_server_process_cache(struct dns_request *request)
 		goto out;
 	}
 
-	if (request->qtype == DNS_T_A && dns_conf_dualstack_ip_allow_force_AAAA == 0) {
+	if (request->qtype == DNS_T_A && request->conf->dns_dualstack_ip_allow_force_AAAA == 0) {
 		goto reply_cache;
 	}
 
@@ -5740,13 +5745,13 @@ static int _dns_server_process_cache(struct dns_request *request)
 		}
 
 		if (dualstack_dns_cache && (dualstack_dns_cache->info.speed > 0)) {
-			if ((dualstack_dns_cache->info.speed + (dns_conf_dualstack_ip_selection_threshold * 10)) <
+			if ((dualstack_dns_cache->info.speed + (request->conf->dns_dualstack_ip_selection_threshold * 10)) <
 					dns_cache->info.speed ||
 				dns_cache->info.speed < 0) {
 				tlog(TLOG_DEBUG, "cache result: %s, qtype: %d, force %s preferred, id: %d, time1: %d, time2: %d",
 					 request->domain, request->qtype, request->qtype == DNS_T_AAAA ? "IPv4" : "IPv6", request->id,
 					 dns_cache->info.speed, dualstack_dns_cache->info.speed);
-				request->ip_ttl = _dns_server_get_expired_ttl_reply(dualstack_dns_cache);
+				request->ip_ttl = _dns_server_get_expired_ttl_reply(request, dualstack_dns_cache);
 				ret = _dns_server_reply_SOA(DNS_RC_NOERROR, request);
 				goto out_update_cache;
 			}
@@ -7578,7 +7583,8 @@ static int _dns_server_second_ping_check(struct dns_request *request)
 	return ret;
 }
 
-static dns_cache_tmout_action_t _dns_server_prefetch_domain(struct dns_cache *dns_cache)
+static dns_cache_tmout_action_t _dns_server_prefetch_domain(struct dns_conf_group *conf_group,
+															struct dns_cache *dns_cache)
 {
 	/* If there are still hits, continue pre-fetching */
 	struct dns_server_query_option server_query_option;
@@ -7602,9 +7608,10 @@ static dns_cache_tmout_action_t _dns_server_prefetch_domain(struct dns_cache *dn
 	return DNS_CACHE_TMOUT_ACTION_OK;
 }
 
-static dns_cache_tmout_action_t _dns_server_prefetch_expired_domain(struct dns_cache *dns_cache)
+static dns_cache_tmout_action_t _dns_server_prefetch_expired_domain(struct dns_conf_group *conf_group,
+																	struct dns_cache *dns_cache)
 {
-	time_t ttl = _dns_server_expired_cache_ttl(dns_cache);
+	time_t ttl = _dns_server_expired_cache_ttl(dns_cache, conf_group->dns_serve_expired_ttl);
 	if (ttl <= 1) {
 		return DNS_CACHE_TMOUT_ACTION_DEL;
 	}
@@ -7637,11 +7644,13 @@ static dns_cache_tmout_action_t _dns_server_cache_expired(struct dns_cache *dns_
 		return DNS_CACHE_TMOUT_ACTION_DEL;
 	}
 
-	if (dns_conf_prefetch == 1) {
-		if (dns_conf_serve_expired == 1) {
-			return _dns_server_prefetch_expired_domain(dns_cache);
+	struct dns_conf_group *conf_group = dns_server_get_rule_group(dns_cache->info.dns_group_name);
+
+	if (conf_group->dns_prefetch == 1) {
+		if (conf_group->dns_serve_expired == 1) {
+			return _dns_server_prefetch_expired_domain(conf_group, dns_cache);
 		} else {
-			return _dns_server_prefetch_domain(dns_cache);
+			return _dns_server_prefetch_domain(conf_group, dns_cache);
 		}
 	}
 

+ 36 - 15
src/include/conf.h

@@ -47,6 +47,7 @@ struct config_item_int {
 	int *data;
 	int min;
 	int max;
+	int (*func)(int value, int *data);
 };
 
 struct config_item_int_base {
@@ -54,27 +55,32 @@ struct config_item_int_base {
 	int min;
 	int max;
 	int base;
+	int (*func)(int value, int *data);
 };
 
 struct config_item_string {
 	char *data;
 	size_t size;
+	int (*func)(const char *value, char *data);
 };
 
 struct config_item_yesno {
 	int *data;
+	int (*func)(int value, int *data);
 };
 
 struct config_item_size {
 	size_t *data;
 	size_t min;
 	size_t max;
+	int (*func)(size_t value, size_t *data);
 };
 
 struct config_item_ssize {
 	ssize_t *data;
 	ssize_t min;
 	ssize_t max;
+	int (*func)(ssize_t value, ssize_t *data);
 };
 
 struct config_enum_list {
@@ -85,59 +91,74 @@ struct config_enum_list {
 struct config_enum {
 	int *data;
 	struct config_enum_list *list;
+	int (*func)(int value, int *data);
 };
 
-#define CONF_INT(key, value, min_value, max_value)                                                                     \
+#define CONF_INT_FUNC(key, func_value, value, min_value, max_value)                                                    \
 	{                                                                                                                  \
 		key, conf_int, &(struct config_item_int)                                                                       \
 		{                                                                                                              \
-			.data = value, .min = min_value, .max = max_value                                                          \
+			.data = value, .func = func_value, .min = min_value, .max = max_value,                                     \
 		}                                                                                                              \
 	}
-#define CONF_INT_BASE(key, value, min_value, max_value, base_value)                                                    \
+#define CONF_INT_BASE_FUNC(key, func_value, value, min_value, max_value, base_value)                                   \
 	{                                                                                                                  \
 		key, conf_int_base, &(struct config_item_int_base)                                                             \
 		{                                                                                                              \
-			.data = value, .min = min_value, .max = max_value, .base = base_value                                      \
+			.data = value, .func = func_value, .min = min_value, .max = max_value, .base = base_value                  \
 		}                                                                                                              \
 	}
-#define CONF_STRING(key, value, len_value)                                                                             \
+#define CONF_STRING_FUNC(key, func_value, value, len_value)                                                            \
 	{                                                                                                                  \
 		key, conf_string, &(struct config_item_string)                                                                 \
 		{                                                                                                              \
-			.data = value, .size = len_value                                                                           \
+			.data = value, .func = func_value, .size = len_value                                                       \
 		}                                                                                                              \
 	}
-#define CONF_YESNO(key, value)                                                                                         \
+#define CONF_YESNO_FUNC(key, func_value, value)                                                                        \
 	{                                                                                                                  \
 		key, conf_yesno, &(struct config_item_yesno)                                                                   \
 		{                                                                                                              \
-			.data = value                                                                                              \
+			.data = value, .func = func_value                                                                          \
 		}                                                                                                              \
 	}
-#define CONF_SIZE(key, value, min_value, max_value)                                                                    \
+#define CONF_SIZE_FUNC(key, func_value, value, min_value, max_value)                                                   \
 	{                                                                                                                  \
 		key, conf_size, &(struct config_item_size)                                                                     \
 		{                                                                                                              \
-			.data = value, .min = min_value, .max = max_value                                                          \
+			.data = value, .func = func_value, .min = min_value, .max = max_value                                      \
 		}                                                                                                              \
 	}
-#define CONF_SSIZE(key, value, min_value, max_value)                                                                   \
+#define CONF_SSIZE_FUNC(key, func_value, value, min_value, max_value)                                                  \
 	{                                                                                                                  \
 		key, conf_ssize, &(struct config_item_ssize)                                                                   \
 		{                                                                                                              \
-			.data = value, .min = min_value, .max = max_value                                                          \
+			.data = value, .func = func_value, .min = min_value, .max = max_value                                      \
 		}                                                                                                              \
 	}
-
-#define CONF_ENUM(key, value, enum)                                                                                    \
+#define CONF_ENUM_FUNC(key, func_value, value, enum)                                                                   \
 	{                                                                                                                  \
 		key, conf_enum, &(struct config_enum)                                                                          \
 		{                                                                                                              \
-			.data = (int *)value, .list = (struct config_enum_list *)enum                                              \
+			.data = (int *)value, .func = func_value, .list = (struct config_enum_list *)enum                          \
 		}                                                                                                              \
 	}
 
+#define CONF_INT(key, value, min_value, max_value) CONF_INT_FUNC(key, NULL, value, min_value, max_value)
+
+#define CONF_INT_BASE(key, value, min_value, max_value, base_value)                                                    \
+	CONF_INT_BASE_FUNC(key, NULL, value, min_value, max_value, base_value)
+
+#define CONF_STRING(key, value, len_value) CONF_STRING_FUNC(key, NULL, value, len_value)
+
+#define CONF_YESNO(key, value) CONF_YESNO_FUNC(key, NULL, value)
+
+#define CONF_SIZE(key, value, min_value, max_value) CONF_SIZE_FUNC(key, NULL, value, min_value, max_value)
+
+#define CONF_SSIZE(key, value, min_value, max_value) CONF_SSIZE_FUNC(key, NULL, value, min_value, max_value)
+
+#define CONF_ENUM(key, value, enum) CONF_ENUM_FUNC(key, NULL, value, enum)
+
 /*
  * func: int (*func)(void *data, int argc, char *argv[]);
  */

+ 27 - 0
src/lib/conf.c

@@ -99,6 +99,10 @@ int conf_int(const char *item, void *data, int argc, char *argv[])
 		value = item_int->max;
 	}
 
+	if (item_int->func) {
+		return item_int->func(value, item_int->data);
+	}
+
 	*(item_int->data) = value;
 
 	return 0;
@@ -120,6 +124,10 @@ int conf_int_base(const char *item, void *data, int argc, char *argv[])
 		value = item_int->max;
 	}
 
+	if (item_int->func) {
+		return item_int->func(value, item_int->data);
+	}
+
 	*(item_int->data) = value;
 
 	return 0;
@@ -133,6 +141,10 @@ int conf_string(const char *item, void *data, int argc, char *argv[])
 		return -1;
 	}
 
+	if (item_string->func) {
+		return item_string->func(argv[1], item_string->data);
+	}
+
 	strncpy(item_string->data, argv[1], item_string->size);
 
 	return 0;
@@ -158,6 +170,10 @@ int conf_yesno(const char *item, void *data, int argc, char *argv[])
 		yes = 0;
 	}
 
+	if (item_yesno->func) {
+		return item_yesno->func(yes, item_yesno->data);
+	}
+
 	*(item_yesno->data) = yes;
 
 	return 0;
@@ -191,6 +207,10 @@ int conf_size(const char *item, void *data, int argc, char *argv[])
 		size = item_size->min;
 	}
 
+	if (item_size->func) {
+		return item_size->func(size, item_size->data);
+	}
+
 	*(item_size->data) = size;
 
 	return 0;
@@ -224,6 +244,10 @@ int conf_ssize(const char *item, void *data, int argc, char *argv[])
 		size = item_size->min;
 	}
 
+	if (item_size->func) {
+		return item_size->func(size, item_size->data);
+	}
+
 	*(item_size->data) = size;
 
 	return 0;
@@ -241,6 +265,9 @@ int conf_enum(const char *item, void *data, int argc, char *argv[])
 
 	for (i = 0; item_enum->list[i].name != NULL; i++) {
 		if (strcmp(enum_name, item_enum->list[i].name) == 0) {
+			if (item_enum->func) {
+				return item_enum->func(item_enum->list[i].id, item_enum->data);
+			}
 			*(item_enum->data) = item_enum->list[i].id;
 			return 0;
 		}