From 2848aa0ac70c6ede0226cd32582d9c9ed8c83612 Mon Sep 17 00:00:00 2001 From: Nick Peng Date: Thu, 11 Aug 2022 00:57:09 +0800 Subject: [PATCH] server_group: fix server group not working issue. --- src/dns_cache.c | 42 ++++++++++++---- src/dns_cache.h | 23 ++++++--- src/dns_client.c | 4 -- src/dns_server.c | 103 ++++++++++++++++++++++++++------------- src/dns_server.h | 12 ++++- src/include/stringutil.h | 9 ++++ 6 files changed, 139 insertions(+), 54 deletions(-) diff --git a/src/dns_cache.c b/src/dns_cache.c index 1f9722f..8871983 100644 --- a/src/dns_cache.c +++ b/src/dns_cache.c @@ -128,9 +128,14 @@ enum CACHE_TYPE dns_cache_data_type(struct dns_cache_data *cache_data) return cache_data->head.cache_type; } -uint32_t dns_cache_get_cache_flag(struct dns_cache_data *cache_data) +uint32_t dns_cache_get_query_flag(struct dns_cache_data *cache_data) { - return cache_data->head.cache_flag; + return cache_data->head.query_flag; +} + +const char *dns_cache_get_dns_group_name(struct dns_cache_data *cache_data) +{ + return cache_data->head.dns_group_name; } void dns_cache_data_free(struct dns_cache_data *data) @@ -156,7 +161,8 @@ struct dns_cache_data *dns_cache_new_data(void) return (struct dns_cache_data *)cache_addr; } -void dns_cache_set_data_soa(struct dns_cache_data *dns_cache, int32_t cache_flag, char *cname, int cname_ttl) +void dns_cache_set_data_soa(struct dns_cache_data *dns_cache, struct dns_cache_query_option *query_option, char *cname, + int cname_ttl) { if (dns_cache == NULL) { goto errout; @@ -179,7 +185,13 @@ void dns_cache_set_data_soa(struct dns_cache_data *dns_cache, int32_t cache_flag cache_addr->addr_data.cname_ttl = cname_ttl; } - cache_addr->head.cache_flag = cache_flag; + if (query_option) { + cache_addr->head.query_flag = query_option->query_flag; + if (query_option->dns_group_name) { + safe_strncpy(cache_addr->head.dns_group_name, query_option->dns_group_name, DNS_CACHE_GROUP_NAME_LEN); + } + } + cache_addr->addr_data.soa = 1; cache_addr->head.cache_type = CACHE_TYPE_ADDR; cache_addr->head.size = sizeof(struct dns_cache_addr) - sizeof(struct dns_cache_data_head); @@ -187,8 +199,8 @@ errout: return; } -void dns_cache_set_data_addr(struct dns_cache_data *dns_cache, uint32_t cache_flag, char *cname, int cname_ttl, - unsigned char *addr, int addr_len) +void dns_cache_set_data_addr(struct dns_cache_data *dns_cache, struct dns_cache_query_option *query_option, char *cname, + int cname_ttl, unsigned char *addr, int addr_len) { if (dns_cache == NULL) { goto errout; @@ -212,14 +224,21 @@ void dns_cache_set_data_addr(struct dns_cache_data *dns_cache, uint32_t cache_fl cache_addr->addr_data.cname_ttl = cname_ttl; } - cache_addr->head.cache_flag = cache_flag; + if (query_option) { + cache_addr->head.query_flag = query_option->query_flag; + if (query_option->dns_group_name) { + safe_strncpy(cache_addr->head.dns_group_name, query_option->dns_group_name, DNS_CACHE_GROUP_NAME_LEN); + } + } + cache_addr->head.cache_type = CACHE_TYPE_ADDR; cache_addr->head.size = sizeof(struct dns_cache_addr) - sizeof(struct dns_cache_data_head); errout: return; } -struct dns_cache_data *dns_cache_new_data_packet(uint32_t cache_flag, void *packet, size_t packet_len) +struct dns_cache_data *dns_cache_new_data_packet(struct dns_cache_query_option *query_option, void *packet, + size_t packet_len) { struct dns_cache_packet *cache_packet = NULL; size_t data_size = 0; @@ -236,7 +255,12 @@ struct dns_cache_data *dns_cache_new_data_packet(uint32_t cache_flag, void *pack memcpy(cache_packet->data, packet, packet_len); memset(&cache_packet->head, 0, sizeof(cache_packet->head)); - cache_packet->head.cache_flag = cache_flag; + if (query_option) { + cache_packet->head.query_flag = query_option->query_flag; + if (query_option->dns_group_name) { + strncpy(cache_packet->head.dns_group_name, query_option->dns_group_name, DNS_CACHE_GROUP_NAME_LEN - 1); + } + } cache_packet->head.cache_type = CACHE_TYPE_PACKET; cache_packet->head.size = packet_len; diff --git a/src/dns_cache.h b/src/dns_cache.h index 76f21bd..72cf26a 100644 --- a/src/dns_cache.h +++ b/src/dns_cache.h @@ -33,6 +33,7 @@ extern "C" { #define DNS_CACHE_TTL_MIN 1 #define DNS_CACHE_VERSION_LEN 32 +#define DNS_CACHE_GROUP_NAME_LEN 32 #define MAGIC_NUMBER 0x6548634163536e44 #define MAGIC_CACHE_DATA 0x44615461 @@ -47,9 +48,15 @@ enum CACHE_RECORD_TYPE { CACHE_RECORD_TYPE_INACTIVE, }; +struct dns_cache_query_option { + uint32_t query_flag; + const char *dns_group_name; +}; + struct dns_cache_data_head { - uint32_t cache_flag; enum CACHE_TYPE cache_type; + uint32_t query_flag; + char dns_group_name[DNS_CACHE_GROUP_NAME_LEN]; int is_soa; ssize_t size; }; @@ -115,11 +122,14 @@ struct dns_cache_file { enum CACHE_TYPE dns_cache_data_type(struct dns_cache_data *cache_data); -uint32_t dns_cache_get_cache_flag(struct dns_cache_data *cache_data); +uint32_t dns_cache_get_query_flag(struct dns_cache_data *cache_data); + +const char *dns_cache_get_dns_group_name(struct dns_cache_data *cache_data); void dns_cache_data_free(struct dns_cache_data *data); -struct dns_cache_data *dns_cache_new_data_packet(uint32_t cache_flag, void *packet, size_t packet_len); +struct dns_cache_data *dns_cache_new_data_packet(struct dns_cache_query_option *query_option, void *packet, + size_t packet_len); int dns_cache_init(int size, int enable_inactive, int inactive_list_expired); @@ -156,10 +166,11 @@ struct dns_cache_data *dns_cache_new_data(void); struct dns_cache_data *dns_cache_get_data(struct dns_cache *dns_cache); -void dns_cache_set_data_addr(struct dns_cache_data *dns_cache, uint32_t cache_flag, char *cname, int cname_ttl, - unsigned char *addr, int addr_len); +void dns_cache_set_data_addr(struct dns_cache_data *dns_cache, struct dns_cache_query_option *query_option, char *cname, + int cname_ttl, unsigned char *addr, int addr_len); -void dns_cache_set_data_soa(struct dns_cache_data *dns_cache, int32_t cache_flag, char *cname, int cname_ttl); +void dns_cache_set_data_soa(struct dns_cache_data *dns_cache, struct dns_cache_query_option *query_option, char *cname, + int cname_ttl); void dns_cache_destroy(void); diff --git a/src/dns_client.c b/src/dns_client.c index 321675f..0eef2be 100644 --- a/src/dns_client.c +++ b/src/dns_client.c @@ -1416,10 +1416,6 @@ static void _dns_client_query_remove(struct dns_query_struct *query) { /* remove query from period check list, and release reference*/ pthread_mutex_lock(&client.domain_map_lock); - if (list_empty(&query->dns_request_list)) { - pthread_mutex_unlock(&client.domain_map_lock); - return; - } list_del_init(&query->dns_request_list); hash_del(&query->domain_node); pthread_mutex_unlock(&client.domain_map_lock); diff --git a/src/dns_server.c b/src/dns_server.c index 7270856..7e936e0 100644 --- a/src/dns_server.c +++ b/src/dns_server.c @@ -163,6 +163,7 @@ struct dns_request { struct dns_server_conn_head *conn; uint32_t server_flags; + char dns_group_name[DNS_GROUP_NAME_LEN]; /* dns request list */ struct list_head list; @@ -261,8 +262,8 @@ static tlog_log *dns_audit; static int is_ipv6_ready; -static int _dns_server_prefetch_request(char *domain, dns_type_t qtype, int expired_domain, uint32_t server_flags, - struct dns_query_options *options); +static int _dns_server_prefetch_request(char *domain, dns_type_t qtype, int expired_domain, + struct dns_server_query_option *server_query_option); static int _dns_server_get_answer(struct dns_server_post_context *context); static void _dns_server_request_get(struct dns_request *request); static void _dns_server_request_release(struct dns_request *request); @@ -940,6 +941,8 @@ static int _dns_server_request_update_cache(struct dns_request *request, dns_typ speed = request->ping_time; if (has_soa) { + struct dns_cache_query_option cache_option; + if (request->dualstack_selection && request->has_ip && request->qtype == DNS_T_AAAA) { ttl = _dns_server_get_conf_ttl(request->ip_ttl); } else { @@ -948,7 +951,10 @@ static int _dns_server_request_update_cache(struct dns_request *request, dns_typ ttl = DNS_SERVER_TMOUT_TTL; } } - dns_cache_set_data_soa(cache_data, request->server_flags, request->cname, request->ttl_cname); + + cache_option.query_flag = request->server_flags; + cache_option.dns_group_name = 0; + dns_cache_set_data_soa(cache_data, &cache_option, request->cname, request->ttl_cname); } tlog(TLOG_DEBUG, "cache %s qtype: %d ttl: %d\n", request->domain, qtype, ttl); @@ -983,6 +989,7 @@ static int _dns_cache_cname_packet(struct dns_server_post_context *context) { struct dns_packet *packet = context->packet; struct dns_packet *cname_packet = NULL; + struct dns_cache_query_option cache_option; int ret = 0; int i = 0; int j = 0; @@ -1080,7 +1087,10 @@ static 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_option.query_flag = request->server_flags; + cache_option.dns_group_name = request->dns_group_name; + cache_packet = dns_cache_new_data_packet(&cache_option, inpacket_buff, inpacket_len); if (cache_packet == NULL) { return -1; } @@ -1123,9 +1133,13 @@ errout: static int _dns_cache_packet(struct dns_server_post_context *context) { + struct dns_cache_query_option cache_option; struct dns_request *request = context->request; + + cache_option.query_flag = request->server_flags; + cache_option.dns_group_name = request->dns_group_name; struct dns_cache_data *cache_packet = - dns_cache_new_data_packet(request->server_flags, context->inpacket, context->inpacket_len); + dns_cache_new_data_packet(&cache_option, context->inpacket, context->inpacket_len); if (cache_packet == NULL) { return -1; } @@ -1249,8 +1263,11 @@ static int _dns_cache_reply_packet(struct dns_server_post_context *context) return _dns_cache_specify_packet(context); } + struct dns_cache_query_option cache_option; + cache_option.query_flag = request->server_flags; + cache_option.dns_group_name = request->dns_group_name; struct dns_cache_data *cache_packet = - dns_cache_new_data_packet(request->server_flags, context->inpacket, context->inpacket_len); + dns_cache_new_data_packet(&cache_option, context->inpacket, context->inpacket_len); if (cache_packet == NULL) { return -1; } @@ -1788,10 +1805,6 @@ static void _dns_server_complete_with_multi_ipaddress(struct dns_request *reques struct dns_server_post_context context; int do_reply = 0; - if (request->passthrough) { - return; - } - if (atomic_read(&request->ip_map_num) > 0) { request->has_soa = 0; } @@ -3647,18 +3660,21 @@ reply_cache: out_update_cache: if (dns_cache_get_ttl(dns_cache) == 0) { - uint32_t server_flags = request->server_flags; - struct dns_query_options options; + struct dns_server_query_option dns_query_options; + dns_query_options.server_flags = request->server_flags; + dns_query_options.dns_group_name = request->dns_group_name; if (request->conn == NULL) { - server_flags = dns_cache_get_cache_flag(dns_cache->cache_data); + dns_query_options.server_flags = dns_cache_get_query_flag(dns_cache->cache_data); + dns_query_options.dns_group_name = dns_cache_get_dns_group_name(dns_cache->cache_data); } - options.enable_flag = 0; + dns_query_options.ecs_enable_flag = 0; if (request->has_ecs) { - options.enable_flag |= DNS_QUEY_OPTION_ECS_DNS; - memcpy(&options.ecs_dns, &request->ecs, sizeof(options.ecs_dns)); + dns_query_options.ecs_enable_flag |= DNS_QUEY_OPTION_ECS_DNS; + memcpy(&dns_query_options.ecs_dns, &request->ecs, sizeof(dns_query_options.ecs_dns)); } - _dns_server_prefetch_request(request->domain, request->qtype, 0, server_flags, &options); + + _dns_server_prefetch_request(request->domain, request->qtype, 0, &dns_query_options); } else { dns_cache_update(dns_cache); } @@ -3969,6 +3985,7 @@ static int _dns_server_query_dualstack(struct dns_request *request) } request_dualstack->server_flags = request->server_flags; + safe_strncpy(request_dualstack->dns_group_name, request->dns_group_name, sizeof(request->dns_group_name)); safe_strncpy(request_dualstack->domain, request->domain, sizeof(request->domain)); request_dualstack->qtype = qtype; request_dualstack->dualstack_selection_query = 1; @@ -4013,9 +4030,14 @@ static int _dns_server_do_query(struct dns_request *request) /* lookup domain rule */ _dns_server_get_domain_rule(request); - group_name = _dns_server_get_request_groupname(request); - if (group_name == NULL) { - group_name = dns_group; + + group_name = request->dns_group_name; + if (request->dns_group_name[0] == '\0') { + group_name = _dns_server_get_request_groupname(request); + if (group_name == NULL) { + group_name = dns_group; + } + safe_strncpy(request->dns_group_name, group_name, DNS_GROUP_NAME_LEN); } if (_dns_server_process_host(request) == 0) { @@ -4206,22 +4228,28 @@ errout: return ret; } -static int _dns_server_prefetch_setup_options(struct dns_request *request, struct dns_query_options *options) +static int _dns_server_setup_server_query_options(struct dns_request *request, + struct dns_server_query_option *server_query_option) { - if (options == NULL) { + if (server_query_option == NULL) { return 0; } - if (options->enable_flag & DNS_QUEY_OPTION_ECS_DNS) { + request->server_flags = server_query_option->server_flags; + if (server_query_option->dns_group_name) { + safe_strncpy(request->dns_group_name, server_query_option->dns_group_name, DNS_GROUP_NAME_LEN); + } + + if (server_query_option->ecs_enable_flag & DNS_QUEY_OPTION_ECS_DNS) { request->has_ecs = 1; - memcpy(&request->ecs, &options->ecs_dns, sizeof(request->ecs)); + memcpy(&request->ecs, &server_query_option->ecs_dns, sizeof(request->ecs)); } return 0; } -static int _dns_server_prefetch_request(char *domain, dns_type_t qtype, int expired_domain, uint32_t server_flags, - struct dns_query_options *options) +static int _dns_server_prefetch_request(char *domain, dns_type_t qtype, int expired_domain, + struct dns_server_query_option *server_query_option) { int ret = -1; struct dns_request *request = NULL; @@ -4234,8 +4262,7 @@ static int _dns_server_prefetch_request(char *domain, dns_type_t qtype, int expi safe_strncpy(request->domain, domain, sizeof(request->domain)); request->qtype = qtype; - request->server_flags = server_flags; - _dns_server_prefetch_setup_options(request, options); + _dns_server_setup_server_query_options(request, server_query_option); _dns_server_request_set_enable_prefetch(request, expired_domain); ret = _dns_server_do_query(request); if (ret != 0) { @@ -4253,7 +4280,8 @@ errout: return ret; } -int dns_server_query(const char *domain, int qtype, uint32_t server_flags, dns_result_callback callback, void *user_ptr) +int dns_server_query(const char *domain, int qtype, struct dns_server_query_option *server_query_option, + dns_result_callback callback, void *user_ptr) { int ret = -1; struct dns_request *request = NULL; @@ -4264,9 +4292,9 @@ int dns_server_query(const char *domain, int qtype, uint32_t server_flags, dns_r goto errout; } - request->server_flags = server_flags; safe_strncpy(request->domain, domain, sizeof(request->domain)); request->qtype = qtype; + _dns_server_setup_server_query_options(request, server_query_option); _dns_server_request_set_callback(request, callback, user_ptr); ret = _dns_server_do_query(request); if (ret != 0) { @@ -4662,6 +4690,7 @@ static int _dns_server_second_ping_check(struct dns_request *request) static void _dns_server_prefetch_domain(struct dns_cache *dns_cache) { /* If there are still hits, continue pre-fetching */ + struct dns_server_query_option server_query_option; int hitnum = dns_cache_hitnum_dec_get(dns_cache); if (hitnum <= 0) { return; @@ -4670,8 +4699,10 @@ static void _dns_server_prefetch_domain(struct dns_cache *dns_cache) /* start prefetch domain */ tlog(TLOG_DEBUG, "prefetch by cache %s, qtype %d, ttl %d, hitnum %d", dns_cache->info.domain, dns_cache->info.qtype, dns_cache->info.ttl, hitnum); - if (_dns_server_prefetch_request(dns_cache->info.domain, dns_cache->info.qtype, 0, - dns_cache_get_cache_flag(dns_cache->cache_data), NULL) != 0) { + server_query_option.dns_group_name = dns_cache_get_dns_group_name(dns_cache->cache_data); + server_query_option.server_flags = dns_cache_get_query_flag(dns_cache->cache_data); + server_query_option.ecs_enable_flag = 0; + if (_dns_server_prefetch_request(dns_cache->info.domain, dns_cache->info.qtype, 0, &server_query_option) != 0) { tlog(TLOG_ERROR, "prefetch domain %s, qtype %d, failed.", dns_cache->info.domain, dns_cache->info.qtype); } } @@ -4682,8 +4713,12 @@ static void _dns_server_prefetch_expired_domain(struct dns_cache *dns_cache) tlog(TLOG_DEBUG, "expired domain, prefetch by cache %s, qtype %d, ttl %d", dns_cache->info.domain, dns_cache->info.qtype, dns_cache->info.ttl); - if (_dns_server_prefetch_request(dns_cache->info.domain, dns_cache->info.qtype, 1, - dns_cache_get_cache_flag(dns_cache->cache_data), NULL) != 0) { + struct dns_server_query_option server_query_option; + server_query_option.dns_group_name = dns_cache_get_dns_group_name(dns_cache->cache_data); + server_query_option.server_flags = dns_cache_get_query_flag(dns_cache->cache_data); + server_query_option.ecs_enable_flag = 0; + + if (_dns_server_prefetch_request(dns_cache->info.domain, dns_cache->info.qtype, 1, &server_query_option) != 0) { tlog(TLOG_ERROR, "prefetch domain %s, qtype %d, failed.", dns_cache->info.domain, dns_cache->info.qtype); } } diff --git a/src/dns_server.h b/src/dns_server.h index 5bf9492..c76ada3 100644 --- a/src/dns_server.h +++ b/src/dns_server.h @@ -21,11 +21,20 @@ #include "dns.h" #include +#include "dns_client.h" #ifdef __cpluscplus extern "C" { #endif +struct dns_server_query_option { + uint32_t server_flags; + const char *dns_group_name; + unsigned long ecs_enable_flag; + struct dns_opt_ecs ecs_dns; + struct dns_query_ecs_ip ecs_ip; +}; + int dns_server_init(void); int dns_server_run(void); @@ -41,7 +50,8 @@ typedef int (*dns_result_callback)(const char *domain, dns_rtcode_t rtcode, dns_ unsigned int ping_time, void *user_ptr); /* query domain */ -int dns_server_query(const char *domain, int qtype, uint32_t server_flags, dns_result_callback callback, void *user_ptr); +int dns_server_query(const char *domain, int qtype, struct dns_server_query_option *server_query_option, + dns_result_callback callback, void *user_ptr); #ifdef __cpluscplus } diff --git a/src/include/stringutil.h b/src/include/stringutil.h index 626a58c..f91a59c 100644 --- a/src/include/stringutil.h +++ b/src/include/stringutil.h @@ -24,6 +24,15 @@ static inline char *safe_strncpy(char *dest, const char *src, size_t n) { + if (src == NULL) { + dest[0] = '\0'; + return dest; + } + + if (n <= 0) { + return NULL; + } + #if __GNUC__ > 7 #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wstringop-truncation"