ecs: support pass client ecs to upstream
This commit is contained in:
@@ -887,11 +887,12 @@ int dns_add_OPT_ECS(struct dns_packet *packet, struct dns_opt_ecs *ecs)
|
|||||||
int dns_get_OPT_ECS(struct dns_rrs *rrs, unsigned short *opt_code, unsigned short *opt_len, struct dns_opt_ecs *ecs)
|
int dns_get_OPT_ECS(struct dns_rrs *rrs, unsigned short *opt_code, unsigned short *opt_len, struct dns_opt_ecs *ecs)
|
||||||
{
|
{
|
||||||
unsigned char opt_data[DNS_MAX_OPT_LEN];
|
unsigned char opt_data[DNS_MAX_OPT_LEN];
|
||||||
|
char domain[DNS_MAX_CNAME_LEN] = {0};
|
||||||
struct dns_opt *opt = (struct dns_opt *)opt_data;
|
struct dns_opt *opt = (struct dns_opt *)opt_data;
|
||||||
int len = DNS_MAX_OPT_LEN;
|
int len = DNS_MAX_OPT_LEN;
|
||||||
int ttl = 0;
|
int ttl = 0;
|
||||||
|
|
||||||
if (_dns_get_RAW(rrs, NULL, 0, &ttl, opt_data, &len) != 0) {
|
if (_dns_get_RAW(rrs, domain, DNS_MAX_CNAME_LEN, &ttl, opt_data, &len) != 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
169
src/dns_client.c
169
src/dns_client.c
@@ -66,13 +66,7 @@
|
|||||||
/* ECS info */
|
/* ECS info */
|
||||||
struct dns_client_ecs {
|
struct dns_client_ecs {
|
||||||
int enable;
|
int enable;
|
||||||
unsigned int family;
|
struct dns_opt_ecs ecs;
|
||||||
unsigned int bitlen;
|
|
||||||
union {
|
|
||||||
unsigned char ipv4_addr[DNS_RR_A_LEN];
|
|
||||||
unsigned char ipv6_addr[DNS_RR_AAAA_LEN];
|
|
||||||
unsigned char addr[0];
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* TCP/TLS buffer */
|
/* TCP/TLS buffer */
|
||||||
@@ -244,6 +238,9 @@ struct dns_query_struct {
|
|||||||
/* has result */
|
/* has result */
|
||||||
int has_result;
|
int has_result;
|
||||||
|
|
||||||
|
/* ECS */
|
||||||
|
struct dns_client_ecs ecs;
|
||||||
|
|
||||||
/* replied hash table */
|
/* replied hash table */
|
||||||
DECLARE_HASHTABLE(replied_map, 4);
|
DECLARE_HASHTABLE(replied_map, 4);
|
||||||
};
|
};
|
||||||
@@ -2873,42 +2870,13 @@ static int _dns_client_send_packet(struct dns_query_struct *query, void *packet,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _dns_client_dns_add_ecs(struct dns_packet *packet, int qtype)
|
static int _dns_client_dns_add_ecs(struct dns_query_struct *query, struct dns_packet *packet)
|
||||||
{
|
{
|
||||||
int add_ipv4_ecs = 0;
|
if (query->ecs.enable == 0) {
|
||||||
int add_ipv6_ecs = 0;
|
return 0;
|
||||||
|
|
||||||
if (qtype == DNS_T_A && client.ecs_ipv4.enable) {
|
|
||||||
add_ipv4_ecs = 1;
|
|
||||||
} else if (qtype == DNS_T_AAAA && client.ecs_ipv6.enable) {
|
|
||||||
add_ipv6_ecs = 1;
|
|
||||||
} else {
|
|
||||||
if (client.ecs_ipv4.enable) {
|
|
||||||
add_ipv4_ecs = 1;
|
|
||||||
} else if (client.ecs_ipv6.enable) {
|
|
||||||
add_ipv4_ecs = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (add_ipv4_ecs) {
|
return dns_add_OPT_ECS(packet, &query->ecs.ecs);
|
||||||
struct dns_opt_ecs ecs;
|
|
||||||
ecs.family = DNS_ADDR_FAMILY_IP;
|
|
||||||
ecs.source_prefix = client.ecs_ipv4.bitlen;
|
|
||||||
ecs.scope_prefix = 0;
|
|
||||||
memcpy(ecs.addr, client.ecs_ipv4.ipv4_addr, DNS_RR_A_LEN);
|
|
||||||
return dns_add_OPT_ECS(packet, &ecs);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (add_ipv6_ecs) {
|
|
||||||
struct dns_opt_ecs ecs;
|
|
||||||
ecs.family = DNS_ADDR_FAMILY_IPV6;
|
|
||||||
ecs.source_prefix = client.ecs_ipv6.bitlen;
|
|
||||||
ecs.scope_prefix = 0;
|
|
||||||
memcpy(ecs.addr, client.ecs_ipv6.ipv6_addr, DNS_RR_AAAA_LEN);
|
|
||||||
return dns_add_OPT_ECS(packet, &ecs);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _dns_client_send_query(struct dns_query_struct *query, char *doamin)
|
static int _dns_client_send_query(struct dns_query_struct *query, char *doamin)
|
||||||
@@ -2942,7 +2910,7 @@ static int _dns_client_send_query(struct dns_query_struct *query, char *doamin)
|
|||||||
|
|
||||||
dns_set_OPT_payload_size(packet, DNS_IN_PACKSIZE);
|
dns_set_OPT_payload_size(packet, DNS_IN_PACKSIZE);
|
||||||
/* dns_add_OPT_TCP_KEEYALIVE(packet, 600); */
|
/* dns_add_OPT_TCP_KEEYALIVE(packet, 600); */
|
||||||
if (_dns_client_dns_add_ecs(packet, query->qtype) != 0) {
|
if (_dns_client_dns_add_ecs(query, packet) != 0) {
|
||||||
tlog(TLOG_ERROR, "add ecs failed.");
|
tlog(TLOG_ERROR, "add ecs failed.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -2964,7 +2932,102 @@ static int _dns_client_send_query(struct dns_query_struct *query, char *doamin)
|
|||||||
return _dns_client_send_packet(query, inpacket, encode_len);
|
return _dns_client_send_packet(query, inpacket, encode_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
int dns_client_query(char *domain, int qtype, dns_client_callback callback, void *user_ptr, const char *group_name)
|
int _dns_client_query_setup_default_ecs(struct dns_query_struct *query)
|
||||||
|
{
|
||||||
|
int add_ipv4_ecs = 0;
|
||||||
|
int add_ipv6_ecs = 0;
|
||||||
|
|
||||||
|
if (query->qtype == DNS_T_A && client.ecs_ipv4.enable) {
|
||||||
|
add_ipv4_ecs = 1;
|
||||||
|
} else if (query->qtype == DNS_T_AAAA && client.ecs_ipv6.enable) {
|
||||||
|
add_ipv6_ecs = 1;
|
||||||
|
} else {
|
||||||
|
if (client.ecs_ipv4.enable) {
|
||||||
|
add_ipv4_ecs = 1;
|
||||||
|
} else if (client.ecs_ipv6.enable) {
|
||||||
|
add_ipv4_ecs = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (add_ipv4_ecs) {
|
||||||
|
memcpy(&query->ecs, &client.ecs_ipv4, sizeof(query->ecs));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (add_ipv6_ecs) {
|
||||||
|
memcpy(&query->ecs, &client.ecs_ipv6, sizeof(query->ecs));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _dns_client_query_parser_options(struct dns_query_struct *query, struct dns_query_options *options)
|
||||||
|
{
|
||||||
|
if (options == NULL) {
|
||||||
|
_dns_client_query_setup_default_ecs(query);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options->enable_flag & DNS_QUEY_OPTION_ECS_IP) {
|
||||||
|
struct sockaddr_storage addr;
|
||||||
|
socklen_t addr_len = sizeof(addr);
|
||||||
|
struct dns_opt_ecs *ecs;
|
||||||
|
|
||||||
|
ecs = &query->ecs.ecs;
|
||||||
|
getaddr_by_host(options->ecs_ip.ip, (struct sockaddr *)&addr, &addr_len);
|
||||||
|
|
||||||
|
query->ecs.enable = 1;
|
||||||
|
ecs->source_prefix = options->ecs_ip.subnet;
|
||||||
|
ecs->scope_prefix = 0;
|
||||||
|
|
||||||
|
switch (addr.ss_family) {
|
||||||
|
case AF_INET: {
|
||||||
|
struct sockaddr_in *addr_in;
|
||||||
|
addr_in = (struct sockaddr_in *)&addr;
|
||||||
|
ecs->family = DNS_OPT_ECS_FAMILY_IPV4;
|
||||||
|
memcpy(&ecs->addr, &addr_in->sin_addr.s_addr, 4);
|
||||||
|
} break;
|
||||||
|
case AF_INET6: {
|
||||||
|
struct sockaddr_in6 *addr_in6;
|
||||||
|
addr_in6 = (struct sockaddr_in6 *)&addr;
|
||||||
|
if (IN6_IS_ADDR_V4MAPPED(&addr_in6->sin6_addr)) {
|
||||||
|
memcpy(&ecs->addr, addr_in6->sin6_addr.s6_addr + 12, 4);
|
||||||
|
ecs->family = DNS_OPT_ECS_FAMILY_IPV4;
|
||||||
|
} else {
|
||||||
|
memcpy(&ecs->addr, addr_in6->sin6_addr.s6_addr, 16);
|
||||||
|
ecs->family = DNS_OPT_ECS_FAMILY_IPV6;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
default:
|
||||||
|
tlog(TLOG_WARN, "ECS set failure.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options->enable_flag & DNS_QUEY_OPTION_ECS_DNS) {
|
||||||
|
struct dns_opt_ecs *ecs = &options->ecs_dns;
|
||||||
|
if (ecs->family != DNS_OPT_ECS_FAMILY_IPV6 && ecs->family != DNS_OPT_ECS_FAMILY_IPV4) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ecs->family == DNS_OPT_ECS_FAMILY_IPV4 && ecs->source_prefix > 32) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ecs->family == DNS_OPT_ECS_FAMILY_IPV6 && ecs->source_prefix > 128) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(&query->ecs.ecs, ecs, sizeof(query->ecs.ecs));
|
||||||
|
query->ecs.enable = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dns_client_query(char *domain, int qtype, dns_client_callback callback, void *user_ptr, const char *group_name,
|
||||||
|
struct dns_query_options *options)
|
||||||
{
|
{
|
||||||
struct dns_query_struct *query = NULL;
|
struct dns_query_struct *query = NULL;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
@@ -2999,6 +3062,11 @@ int dns_client_query(char *domain, int qtype, dns_client_callback callback, void
|
|||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_dns_client_query_parser_options(query, options) != 0) {
|
||||||
|
tlog(TLOG_ERROR, "parser options for %s failed.", domain);
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
_dns_client_query_get(query);
|
_dns_client_query_get(query);
|
||||||
/* add query to hashtable */
|
/* add query to hashtable */
|
||||||
key = hash_string(domain);
|
key = hash_string(domain);
|
||||||
@@ -3299,20 +3367,25 @@ int dns_client_set_ecs(char *ip, int subnet)
|
|||||||
case AF_INET: {
|
case AF_INET: {
|
||||||
struct sockaddr_in *addr_in;
|
struct sockaddr_in *addr_in;
|
||||||
addr_in = (struct sockaddr_in *)&addr;
|
addr_in = (struct sockaddr_in *)&addr;
|
||||||
memcpy(&client.ecs_ipv4.ipv4_addr, &addr_in->sin_addr.s_addr, 4);
|
memcpy(&client.ecs_ipv4.ecs.addr, &addr_in->sin_addr.s_addr, 4);
|
||||||
client.ecs_ipv4.bitlen = subnet;
|
client.ecs_ipv4.ecs.source_prefix = subnet;
|
||||||
|
client.ecs_ipv4.ecs.scope_prefix = 0;
|
||||||
|
client.ecs_ipv4.ecs.family = DNS_OPT_ECS_FAMILY_IPV4;
|
||||||
client.ecs_ipv4.enable = 1;
|
client.ecs_ipv4.enable = 1;
|
||||||
} break;
|
} break;
|
||||||
case AF_INET6: {
|
case AF_INET6: {
|
||||||
struct sockaddr_in6 *addr_in6;
|
struct sockaddr_in6 *addr_in6;
|
||||||
addr_in6 = (struct sockaddr_in6 *)&addr;
|
addr_in6 = (struct sockaddr_in6 *)&addr;
|
||||||
if (IN6_IS_ADDR_V4MAPPED(&addr_in6->sin6_addr)) {
|
if (IN6_IS_ADDR_V4MAPPED(&addr_in6->sin6_addr)) {
|
||||||
memcpy(&client.ecs_ipv4.ipv4_addr, addr_in6->sin6_addr.s6_addr + 12, 4);
|
client.ecs_ipv4.ecs.source_prefix = subnet;
|
||||||
client.ecs_ipv4.bitlen = subnet;
|
client.ecs_ipv4.ecs.scope_prefix = 0;
|
||||||
|
client.ecs_ipv4.ecs.family = DNS_OPT_ECS_FAMILY_IPV4;
|
||||||
client.ecs_ipv4.enable = 1;
|
client.ecs_ipv4.enable = 1;
|
||||||
} else {
|
} else {
|
||||||
memcpy(&client.ecs_ipv6.ipv6_addr, addr_in6->sin6_addr.s6_addr, 16);
|
memcpy(&client.ecs_ipv6.ecs.addr, addr_in6->sin6_addr.s6_addr, 16);
|
||||||
client.ecs_ipv6.bitlen = subnet;
|
client.ecs_ipv6.ecs.source_prefix = subnet;
|
||||||
|
client.ecs_ipv6.ecs.scope_prefix = 0;
|
||||||
|
client.ecs_ipv6.ecs.family = DNS_ADDR_FAMILY_IPV6;
|
||||||
client.ecs_ipv6.enable = 1;
|
client.ecs_ipv6.enable = 1;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|||||||
@@ -47,6 +47,9 @@ typedef enum dns_result_type {
|
|||||||
#define DNSSERVER_FLAG_CHECK_EDNS (0x1 << 2)
|
#define DNSSERVER_FLAG_CHECK_EDNS (0x1 << 2)
|
||||||
#define DNSSERVER_FLAG_CHECK_TTL (0x1 << 3)
|
#define DNSSERVER_FLAG_CHECK_TTL (0x1 << 3)
|
||||||
|
|
||||||
|
#define DNS_QUEY_OPTION_ECS_DNS (1 << 0)
|
||||||
|
#define DNS_QUEY_OPTION_ECS_IP (1 << 1)
|
||||||
|
|
||||||
int dns_client_init(void);
|
int dns_client_init(void);
|
||||||
|
|
||||||
int dns_client_set_ecs(char *ip, int subnet);
|
int dns_client_set_ecs(char *ip, int subnet);
|
||||||
@@ -56,8 +59,20 @@ typedef int (*dns_client_callback)(char *domain, dns_result_type rtype, unsigned
|
|||||||
struct dns_packet *packet, unsigned char *inpacket, int inpacket_len,
|
struct dns_packet *packet, unsigned char *inpacket, int inpacket_len,
|
||||||
void *user_ptr);
|
void *user_ptr);
|
||||||
|
|
||||||
|
struct dns_query_ecs_ip {
|
||||||
|
char ip[DNS_MAX_CNAME_LEN];
|
||||||
|
int subnet;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct dns_query_options {
|
||||||
|
unsigned long long enable_flag;
|
||||||
|
struct dns_opt_ecs ecs_dns;
|
||||||
|
struct dns_query_ecs_ip ecs_ip;
|
||||||
|
};
|
||||||
|
|
||||||
/* query domain */
|
/* query domain */
|
||||||
int dns_client_query(char *domain, int qtype, dns_client_callback callback, void *user_ptr, const char *group_name);
|
int dns_client_query(char *domain, int qtype, dns_client_callback callback, void *user_ptr, const char *group_name,
|
||||||
|
struct dns_query_options *options);
|
||||||
|
|
||||||
void dns_client_exit(void);
|
void dns_client_exit(void);
|
||||||
|
|
||||||
|
|||||||
165
src/dns_server.c
165
src/dns_server.c
@@ -184,6 +184,8 @@ struct dns_request {
|
|||||||
struct sockaddr addr;
|
struct sockaddr addr;
|
||||||
};
|
};
|
||||||
struct sockaddr_storage localaddr;
|
struct sockaddr_storage localaddr;
|
||||||
|
int has_ecs;
|
||||||
|
struct dns_opt_ecs ecs;
|
||||||
|
|
||||||
dns_result_callback result_callback;
|
dns_result_callback result_callback;
|
||||||
void *user_ptr;
|
void *user_ptr;
|
||||||
@@ -252,7 +254,7 @@ static tlog_log *dns_audit;
|
|||||||
|
|
||||||
static int is_ipv6_ready;
|
static int is_ipv6_ready;
|
||||||
|
|
||||||
static int _dns_server_prefetch_request(char *domain, dns_type_t qtype, uint32_t server_flags);
|
static int _dns_server_prefetch_request(char *domain, dns_type_t qtype, uint32_t server_flags, struct dns_query_options *options);
|
||||||
|
|
||||||
static int _dns_server_forward_request(unsigned char *inpacket, int inpacket_len)
|
static int _dns_server_forward_request(unsigned char *inpacket, int inpacket_len)
|
||||||
{
|
{
|
||||||
@@ -685,6 +687,10 @@ static int _dns_add_rrs(struct dns_server_post_context *context)
|
|||||||
_dns_server_setup_soa(request);
|
_dns_server_setup_soa(request);
|
||||||
ret |= dns_add_SOA(context->packet, DNS_RRS_NS, domain, 0, &request->soa);
|
ret |= dns_add_SOA(context->packet, DNS_RRS_NS, domain, 0, &request->soa);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (request->has_ecs) {
|
||||||
|
ret |= dns_add_OPT_ECS(context->packet, &request->ecs);
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3346,10 +3352,17 @@ static int _dns_server_process_cache(struct dns_request *request)
|
|||||||
out_update_cache:
|
out_update_cache:
|
||||||
if (dns_cache_get_ttl(dns_cache) == 0) {
|
if (dns_cache_get_ttl(dns_cache) == 0) {
|
||||||
uint32_t server_flags = request->server_flags;
|
uint32_t server_flags = request->server_flags;
|
||||||
|
struct dns_query_options options;
|
||||||
if (request->conn == NULL) {
|
if (request->conn == NULL) {
|
||||||
server_flags = dns_cache_get_cache_flag(dns_cache->cache_data);
|
server_flags = dns_cache_get_cache_flag(dns_cache->cache_data);
|
||||||
}
|
}
|
||||||
_dns_server_prefetch_request(request->domain, request->qtype, server_flags);
|
|
||||||
|
options.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_server_prefetch_request(request->domain, request->qtype, server_flags, &options);
|
||||||
} else {
|
} else {
|
||||||
dns_cache_update(dns_cache);
|
dns_cache_update(dns_cache);
|
||||||
}
|
}
|
||||||
@@ -3623,19 +3636,29 @@ errout:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _dns_server_do_query(struct dns_request *request, const char *domain, int qtype)
|
static int _dns_server_setup_query_option(struct dns_request *request, struct dns_query_options *options)
|
||||||
|
{
|
||||||
|
options->enable_flag = 0;
|
||||||
|
|
||||||
|
if (request->has_ecs) {
|
||||||
|
memcpy(&options->ecs_dns, &request->ecs, sizeof(options->ecs_dns));
|
||||||
|
options->enable_flag |= DNS_QUEY_OPTION_ECS_DNS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _dns_server_do_query(struct dns_request *request)
|
||||||
{
|
{
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
const char *group_name = NULL;
|
const char *group_name = NULL;
|
||||||
const char *dns_group = NULL;
|
const char *dns_group = NULL;
|
||||||
|
struct dns_query_options options;
|
||||||
|
|
||||||
if (request->conn) {
|
if (request->conn) {
|
||||||
dns_group = request->conn->dns_group;
|
dns_group = request->conn->dns_group;
|
||||||
}
|
}
|
||||||
|
|
||||||
safe_strncpy(request->domain, domain, sizeof(request->domain));
|
|
||||||
request->qtype = qtype;
|
|
||||||
|
|
||||||
/* lookup domain rule */
|
/* lookup domain rule */
|
||||||
_dns_server_get_domain_rule(request);
|
_dns_server_get_domain_rule(request);
|
||||||
group_name = _dns_server_get_request_groupname(request);
|
group_name = _dns_server_get_request_groupname(request);
|
||||||
@@ -3686,6 +3709,9 @@ static int _dns_server_do_query(struct dns_request *request, const char *domain,
|
|||||||
goto clean_exit;
|
goto clean_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// setup options
|
||||||
|
_dns_server_setup_query_option(request, &options);
|
||||||
|
|
||||||
// Get reference for server thread
|
// Get reference for server thread
|
||||||
_dns_server_request_get(request);
|
_dns_server_request_get(request);
|
||||||
pthread_mutex_lock(&server.request_list_lock);
|
pthread_mutex_lock(&server.request_list_lock);
|
||||||
@@ -3694,11 +3720,11 @@ static int _dns_server_do_query(struct dns_request *request, const char *domain,
|
|||||||
request->send_tick = get_tick_count();
|
request->send_tick = get_tick_count();
|
||||||
|
|
||||||
/* When the dual stack ip preference is enabled, both A and AAAA records are requested. */
|
/* When the dual stack ip preference is enabled, both A and AAAA records are requested. */
|
||||||
if (qtype == DNS_T_AAAA && request->dualstack_selection) {
|
if (request->qtype == DNS_T_AAAA && request->dualstack_selection) {
|
||||||
// Get reference for AAAA query
|
// Get reference for AAAA query
|
||||||
_dns_server_request_get(request);
|
_dns_server_request_get(request);
|
||||||
request->request_wait++;
|
request->request_wait++;
|
||||||
if (dns_client_query(request->domain, DNS_T_A, dns_server_resolve_callback, request, group_name) != 0) {
|
if (dns_client_query(request->domain, DNS_T_A, dns_server_resolve_callback, request, group_name, &options) != 0) {
|
||||||
request->request_wait--;
|
request->request_wait--;
|
||||||
_dns_server_request_release(request);
|
_dns_server_request_release(request);
|
||||||
}
|
}
|
||||||
@@ -3707,7 +3733,7 @@ static int _dns_server_do_query(struct dns_request *request, const char *domain,
|
|||||||
// Get reference for DNS query
|
// Get reference for DNS query
|
||||||
request->request_wait++;
|
request->request_wait++;
|
||||||
_dns_server_request_get(request);
|
_dns_server_request_get(request);
|
||||||
if (dns_client_query(request->domain, qtype, dns_server_resolve_callback, request, group_name) != 0) {
|
if (dns_client_query(request->domain, request->qtype, dns_server_resolve_callback, request, group_name, &options) != 0) {
|
||||||
request->request_wait--;
|
request->request_wait--;
|
||||||
_dns_server_request_release(request);
|
_dns_server_request_release(request);
|
||||||
tlog(TLOG_ERROR, "send dns request failed.");
|
tlog(TLOG_ERROR, "send dns request failed.");
|
||||||
@@ -3722,6 +3748,60 @@ errout:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int _dns_server_parser_request(struct dns_request *request, struct dns_packet *packet)
|
||||||
|
{
|
||||||
|
struct dns_rrs *rrs;
|
||||||
|
int rr_count = 0;
|
||||||
|
int i = 0;
|
||||||
|
int ret = 0;
|
||||||
|
int qclass;
|
||||||
|
int qtype = DNS_T_ALL;
|
||||||
|
char domain[DNS_MAX_CNAME_LEN];
|
||||||
|
|
||||||
|
if (packet->head.qr != DNS_QR_QUERY) {
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get request domain and request qtype */
|
||||||
|
rrs = dns_get_rrs_start(packet, DNS_RRS_QD, &rr_count);
|
||||||
|
if (rr_count > 1 || rr_count <= 0) {
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < rr_count && rrs; i++, rrs = dns_get_rrs_next(packet, rrs)) {
|
||||||
|
ret = dns_get_domain(rrs, domain, sizeof(domain), &qtype, &qclass);
|
||||||
|
if (ret != 0) {
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only support one question.
|
||||||
|
safe_strncpy(request->domain, domain, sizeof(request->domain));
|
||||||
|
request->qtype = qtype;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* get request opts */
|
||||||
|
rr_count = 0;
|
||||||
|
rrs = dns_get_rrs_start(packet, DNS_RRS_OPT, &rr_count);
|
||||||
|
if (rr_count <= 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < rr_count && rrs; i++, rrs = dns_get_rrs_next(packet, rrs)) {
|
||||||
|
ret = dns_get_OPT_ECS(rrs, NULL, NULL, &request->ecs);
|
||||||
|
if (ret != 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
request->has_ecs = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
errout:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
static int _dns_server_recv(struct dns_server_conn_head *conn, unsigned char *inpacket, int inpacket_len,
|
static int _dns_server_recv(struct dns_server_conn_head *conn, unsigned char *inpacket, int inpacket_len,
|
||||||
struct sockaddr_storage *local, socklen_t local_len, struct sockaddr_storage *from,
|
struct sockaddr_storage *local, socklen_t local_len, struct sockaddr_storage *from,
|
||||||
socklen_t from_len)
|
socklen_t from_len)
|
||||||
@@ -3730,14 +3810,9 @@ static int _dns_server_recv(struct dns_server_conn_head *conn, unsigned char *in
|
|||||||
int ret = -1;
|
int ret = -1;
|
||||||
unsigned char packet_buff[DNS_PACKSIZE];
|
unsigned char packet_buff[DNS_PACKSIZE];
|
||||||
char name[DNS_MAX_CNAME_LEN];
|
char name[DNS_MAX_CNAME_LEN];
|
||||||
char domain[DNS_MAX_CNAME_LEN];
|
|
||||||
struct dns_packet *packet = (struct dns_packet *)packet_buff;
|
struct dns_packet *packet = (struct dns_packet *)packet_buff;
|
||||||
struct dns_request *request = NULL;
|
struct dns_request *request = NULL;
|
||||||
struct dns_rrs *rrs;
|
|
||||||
int rr_count = 0;
|
|
||||||
int i = 0;
|
|
||||||
int qclass;
|
|
||||||
int qtype = DNS_T_ALL;
|
|
||||||
|
|
||||||
/* decode packet */
|
/* decode packet */
|
||||||
tlog(TLOG_DEBUG, "recv query packet from %s, len = %d",
|
tlog(TLOG_DEBUG, "recv query packet from %s, len = %d",
|
||||||
@@ -3754,40 +3829,25 @@ static int _dns_server_recv(struct dns_server_conn_head *conn, unsigned char *in
|
|||||||
packet->head.qdcount, packet->head.ancount, packet->head.nscount, packet->head.nrcount, inpacket_len,
|
packet->head.qdcount, packet->head.ancount, packet->head.nscount, packet->head.nrcount, inpacket_len,
|
||||||
packet->head.id, packet->head.tc, packet->head.rd, packet->head.ra, packet->head.rcode);
|
packet->head.id, packet->head.tc, packet->head.rd, packet->head.ra, packet->head.rcode);
|
||||||
|
|
||||||
if (packet->head.qr != DNS_QR_QUERY) {
|
|
||||||
goto errout;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get request domain and request qtype */
|
|
||||||
rrs = dns_get_rrs_start(packet, DNS_RRS_QD, &rr_count);
|
|
||||||
if (rr_count > 1) {
|
|
||||||
goto errout;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < rr_count && rrs; i++, rrs = dns_get_rrs_next(packet, rrs)) {
|
|
||||||
ret = dns_get_domain(rrs, domain, sizeof(domain), &qtype, &qclass);
|
|
||||||
if (ret != 0) {
|
|
||||||
goto errout;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only support one question.
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
tlog(TLOG_INFO, "query server %s from %s, qtype = %d\n", domain, name, qtype);
|
|
||||||
|
|
||||||
request = _dns_server_new_request();
|
request = _dns_server_new_request();
|
||||||
if (request == NULL) {
|
if (request == NULL) {
|
||||||
tlog(TLOG_ERROR, "malloc failed.\n");
|
tlog(TLOG_ERROR, "malloc failed.\n");
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_dns_server_parser_request(request, packet) != 0) {
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
tlog(TLOG_INFO, "query server %s from %s, qtype = %d\n", request->domain, name, request->qtype);
|
||||||
|
|
||||||
memcpy(&request->localaddr, local, local_len);
|
memcpy(&request->localaddr, local, local_len);
|
||||||
_dns_server_request_set_client(request, conn);
|
_dns_server_request_set_client(request, conn);
|
||||||
_dns_server_request_set_client_addr(request, from, from_len);
|
_dns_server_request_set_client_addr(request, from, from_len);
|
||||||
_dns_server_request_set_id(request, packet->head.id);
|
_dns_server_request_set_id(request, packet->head.id);
|
||||||
ret = _dns_server_do_query(request, domain, qtype);
|
ret = _dns_server_do_query(request);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
tlog(TLOG_ERROR, "do query %s failed.\n", domain);
|
tlog(TLOG_ERROR, "do query %s failed.\n", request->domain);
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
_dns_server_request_release_complete(request, 0);
|
_dns_server_request_release_complete(request, 0);
|
||||||
@@ -3801,7 +3861,21 @@ errout:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _dns_server_prefetch_request(char *domain, dns_type_t qtype, uint32_t server_flags)
|
static int _dns_server_prefetch_setup_options(struct dns_request *request, struct dns_query_options *options)
|
||||||
|
{
|
||||||
|
if (options == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options->enable_flag & DNS_QUEY_OPTION_ECS_DNS) {
|
||||||
|
request->has_ecs = 1;
|
||||||
|
memcpy(&request->ecs, &options->ecs_dns, sizeof(request->ecs));
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _dns_server_prefetch_request(char *domain, dns_type_t qtype, uint32_t server_flags, struct dns_query_options *options)
|
||||||
{
|
{
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
struct dns_request *request = NULL;
|
struct dns_request *request = NULL;
|
||||||
@@ -3812,11 +3886,14 @@ static int _dns_server_prefetch_request(char *domain, dns_type_t qtype, uint32_t
|
|||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
safe_strncpy(request->domain, domain, sizeof(request->domain));
|
||||||
|
request->qtype = qtype;
|
||||||
request->server_flags = server_flags;
|
request->server_flags = server_flags;
|
||||||
|
_dns_server_prefetch_setup_options(request, options);
|
||||||
_dns_server_request_set_enable_prefetch(request);
|
_dns_server_request_set_enable_prefetch(request);
|
||||||
ret = _dns_server_do_query(request, domain, qtype);
|
ret = _dns_server_do_query(request);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
tlog(TLOG_ERROR, "do query %s failed.\n", domain);
|
tlog(TLOG_ERROR, "do query %s failed.\n", request->domain);
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3842,8 +3919,10 @@ int dns_server_query(char *domain, int qtype, uint32_t server_flags, dns_result_
|
|||||||
}
|
}
|
||||||
|
|
||||||
request->server_flags = server_flags;
|
request->server_flags = server_flags;
|
||||||
|
safe_strncpy(request->domain, domain, sizeof(request->domain));
|
||||||
|
request->qtype = qtype;
|
||||||
_dns_server_request_set_callback(request, callback, user_ptr);
|
_dns_server_request_set_callback(request, callback, user_ptr);
|
||||||
ret = _dns_server_do_query(request, domain, qtype);
|
ret = _dns_server_do_query(request);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
tlog(TLOG_ERROR, "do query %s failed.\n", domain);
|
tlog(TLOG_ERROR, "do query %s failed.\n", domain);
|
||||||
goto errout;
|
goto errout;
|
||||||
@@ -4239,7 +4318,7 @@ static void _dns_server_prefetch_domain(struct dns_cache *dns_cache)
|
|||||||
tlog(TLOG_DEBUG, "prefetch by cache %s, qtype %d, ttl %d, hitnum %d", dns_cache->info.domain, dns_cache->info.qtype,
|
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);
|
dns_cache->info.ttl, hitnum);
|
||||||
if (_dns_server_prefetch_request(dns_cache->info.domain, dns_cache->info.qtype,
|
if (_dns_server_prefetch_request(dns_cache->info.domain, dns_cache->info.qtype,
|
||||||
dns_cache_get_cache_flag(dns_cache->cache_data)) != 0) {
|
dns_cache_get_cache_flag(dns_cache->cache_data), NULL) != 0) {
|
||||||
tlog(TLOG_ERROR, "prefetch domain %s, qtype %d, failed.", dns_cache->info.domain, dns_cache->info.qtype);
|
tlog(TLOG_ERROR, "prefetch domain %s, qtype %d, failed.", dns_cache->info.domain, dns_cache->info.qtype);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user