config: add option -no-cache and -response-mode for domain-rules and add some test cases.

This commit is contained in:
Nick Peng
2023-03-24 21:58:41 +08:00
parent 4f2867b7f4
commit dd23c5fc31
16 changed files with 1004 additions and 66 deletions

View File

@@ -202,6 +202,9 @@ static void *_new_dns_rule(enum domain_rule domain_rule)
case DOMAIN_RULE_CHECKSPEED:
size = sizeof(struct dns_domain_check_orders);
break;
case DOMAIN_RULE_RESPONSE_MODE:
size = sizeof(struct dns_response_mode_rule);
break;
case DOMAIN_RULE_CNAME:
size = sizeof(struct dns_cname_rule);
break;
@@ -2388,6 +2391,38 @@ errout:
return 0;
}
static int _conf_domain_rule_response_mode(char *domain, const char *mode)
{
enum response_mode_type response_mode_type = DNS_RESPONSE_MODE_FIRST_PING_IP;
struct dns_response_mode_rule *response_mode = NULL;
for (int i = 0; dns_conf_response_mode_enum[i].name != NULL; i++) {
if (strcmp(mode, dns_conf_response_mode_enum[i].name) == 0) {
response_mode_type = dns_conf_response_mode_enum[i].id;
break;
}
}
response_mode = _new_dns_rule(DOMAIN_RULE_RESPONSE_MODE);
if (response_mode == NULL) {
goto errout;
}
response_mode->mode = response_mode_type;
if (_config_domain_rule_add(domain, DOMAIN_RULE_RESPONSE_MODE, response_mode) != 0) {
goto errout;
}
_dns_rule_put(&response_mode->head);
return 0;
errout:
if (response_mode) {
_dns_rule_put(&response_mode->head);
}
return 0;
}
static int _conf_domain_set(void *data, int argc, char *argv[])
{
int opt = 0;
@@ -2527,6 +2562,11 @@ static int _conf_domain_rule_delete(const char *domain)
return _config_domain_rule_delete(domain);
}
static int _conf_domain_rule_no_cache(const char *domain)
{
return _config_domain_rule_flag_set(domain, DOMAIN_FLAG_NO_CACHE, 0);
}
static int _conf_domain_rules(void *data, int argc, char *argv[])
{
int opt = 0;
@@ -2539,6 +2579,7 @@ static int _conf_domain_rules(void *data, int argc, char *argv[])
/* clang-format off */
static struct option long_options[] = {
{"speed-check-mode", required_argument, NULL, 'c'},
{"response-mode", required_argument, NULL, 'r'},
{"address", required_argument, NULL, 'a'},
{"ipset", required_argument, NULL, 'p'},
{"nftset", required_argument, NULL, 't'},
@@ -2550,6 +2591,7 @@ static int _conf_domain_rules(void *data, int argc, char *argv[])
{"rr-ttl-max", required_argument, NULL, 253},
{"no-serve-expired", no_argument, NULL, 254},
{"delete", no_argument, NULL, 255},
{"no-cache", no_argument, NULL, 256},
{NULL, no_argument, NULL, 0}
};
/* clang-format on */
@@ -2566,7 +2608,7 @@ static int _conf_domain_rules(void *data, int argc, char *argv[])
/* process extra options */
optind = 1;
while (1) {
opt = getopt_long_only(argc, argv, "c:a:p:t:n:d:A:", long_options, NULL);
opt = getopt_long_only(argc, argv, "c:a:p:t:n:d:A:r:", long_options, NULL);
if (opt == -1) {
break;
}
@@ -2585,6 +2627,19 @@ static int _conf_domain_rules(void *data, int argc, char *argv[])
break;
}
case 'r': {
const char *response_mode = optarg;
if (response_mode == NULL) {
goto errout;
}
if (_conf_domain_rule_response_mode(domain, response_mode) != 0) {
tlog(TLOG_ERROR, "add response-mode rule failed.");
goto errout;
}
break;
}
case 'a': {
const char *address = optarg;
if (address == NULL) {
@@ -2684,6 +2739,14 @@ static int _conf_domain_rules(void *data, int argc, char *argv[])
return 0;
}
case 256: {
if (_conf_domain_rule_no_cache(domain) != 0) {
tlog(TLOG_ERROR, "set no-cache rule failed.");
goto errout;
}
break;
}
default:
break;
}

View File

@@ -74,6 +74,7 @@ enum domain_rule {
DOMAIN_RULE_NFTSET_IP6,
DOMAIN_RULE_NAMESERVER,
DOMAIN_RULE_CHECKSPEED,
DOMAIN_RULE_RESPONSE_MODE,
DOMAIN_RULE_CNAME,
DOMAIN_RULE_TTL,
DOMAIN_RULE_MAX,
@@ -110,6 +111,7 @@ typedef enum {
#define DOMAIN_FLAG_NFTSET_IP6_IGN (1 << 14)
#define DOMAIN_FLAG_NO_SERVE_EXPIRED (1 << 15)
#define DOMAIN_FLAG_CNAME_IGN (1 << 16)
#define DOMAIN_FLAG_NO_CACHE (1 << 17)
#define SERVER_FLAG_EXCLUDE_DEFAULT (1 << 0)
@@ -124,6 +126,12 @@ typedef enum {
#define BIND_FLAG_FORCE_AAAA_SOA (1 << 8)
#define BIND_FLAG_NO_RULE_CNAME (1 << 9)
enum response_mode_type {
DNS_RESPONSE_MODE_FIRST_PING_IP = 0,
DNS_RESPONSE_MODE_FASTEST_IP,
DNS_RESPONSE_MODE_FASTEST_RESPONSE,
};
struct dns_rule {
atomic_t refcnt;
enum domain_rule rule;
@@ -227,6 +235,11 @@ struct dns_domain_check_orders {
struct dns_domain_check_order orders[DOMAIN_CHECK_NUM];
};
struct dns_response_mode_rule {
struct dns_rule head;
enum response_mode_type mode;
};
struct dns_group_table {
DECLARE_HASHTABLE(group, 8);
};
@@ -464,11 +477,6 @@ 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;
enum response_mode_type {
DNS_RESPONSE_MODE_FIRST_PING_IP = 0,
DNS_RESPONSE_MODE_FASTEST_IP,
DNS_RESPONSE_MODE_FASTEST_RESPONSE,
};
extern enum response_mode_type dns_conf_response_mode;
extern int dns_conf_rr_ttl;

View File

@@ -304,10 +304,13 @@ struct dns_request {
struct dns_domain_check_orders *check_order_list;
int check_order;
enum response_mode_type response_mode;
struct dns_request_pending_list *request_pending_list;
int no_select_possible_ip;
int no_cache_cname;
int no_cache;
};
/* dns server data */
@@ -1269,7 +1272,7 @@ static int _dns_cache_cname_packet(struct dns_server_post_context *context)
struct dns_request *request = context->request;
if (request->has_cname == 0 || request->no_cache_cname == 1) {
if (request->has_cname == 0 || request->no_cache_cname == 1 || request->no_cache == 1) {
return 0;
}
@@ -1514,7 +1517,7 @@ static int _dns_cache_reply_packet(struct dns_server_post_context *context)
{
struct dns_request *request = context->request;
int has_soa = request->has_soa;
if (context->do_cache == 0 || _dns_server_has_bind_flag(request, BIND_FLAG_NO_CACHE) == 0) {
if (context->do_cache == 0 || request->no_cache == 1) {
return 0;
}
@@ -2433,6 +2436,7 @@ static struct dns_request *_dns_server_new_request(void)
request->qclass = DNS_C_IN;
request->result_callback = NULL;
request->check_order_list = &dns_conf_check_orders;
request->response_mode = dns_conf_response_mode;
INIT_LIST_HEAD(&request->list);
INIT_LIST_HEAD(&request->pending_list);
INIT_LIST_HEAD(&request->check_list);
@@ -2585,7 +2589,7 @@ out:
}
/* Get first ping result */
if (dns_conf_response_mode == DNS_RESPONSE_MODE_FIRST_PING_IP && last_rtt == -1 && request->ping_time > 0) {
if (request->response_mode == DNS_RESPONSE_MODE_FIRST_PING_IP && last_rtt == -1 && request->ping_time > 0) {
may_complete = 1;
}
@@ -3422,7 +3426,7 @@ static int dns_server_resolve_callback(const char *domain, dns_result_type rtype
return _dns_server_reply_passthrough(&context);
}
if (request->prefetch == 0 && dns_conf_response_mode == DNS_RESPONSE_MODE_FASTEST_RESPONSE &&
if (request->prefetch == 0 && request->response_mode == DNS_RESPONSE_MODE_FASTEST_RESPONSE &&
atomic_read(&request->notified) == 0) {
struct dns_server_post_context context;
int ttl = 0;
@@ -3936,6 +3940,10 @@ static int _dns_server_pre_process_rule_flags(struct dns_request *request)
request->no_serve_expired = 1;
}
if ((flags & DOMAIN_FLAG_NO_CACHE) || (_dns_server_has_bind_flag(request, BIND_FLAG_NO_CACHE) == 0)) {
request->no_cache = 1;
}
if (flags & DOMAIN_FLAG_ADDR_IGN) {
/* ignore this domain */
goto out;
@@ -4432,17 +4440,22 @@ static int _dns_server_qtype_soa(struct dns_request *request)
return -1;
}
static void _dns_server_process_speed_check_rule(struct dns_request *request)
static void _dns_server_process_speed_rule(struct dns_request *request)
{
struct dns_domain_check_orders *check_order = NULL;
struct dns_response_mode_rule *response_mode = NULL;
/* get domain rule flag */
/* get speed check mode */
check_order = _dns_server_get_dns_rule(request, DOMAIN_RULE_CHECKSPEED);
if (check_order == NULL) {
return;
if (check_order != NULL) {
request->check_order_list = check_order;
}
request->check_order_list = check_order;
/* get response mode */
response_mode = _dns_server_get_dns_rule(request, DOMAIN_RULE_RESPONSE_MODE);
if (response_mode != NULL) {
request->response_mode = response_mode->mode;
}
}
static int _dns_server_get_expired_ttl_reply(struct dns_cache *dns_cache)
@@ -5073,7 +5086,7 @@ static int _dns_server_do_query(struct dns_request *request, int skip_notify_eve
}
/* process speed check rule */
_dns_server_process_speed_check_rule(request);
_dns_server_process_speed_rule(request);
/* check and set passthrough */
_dns_server_check_set_passthrough(request);