Add ECS and bugfix
This commit is contained in:
@@ -44,6 +44,11 @@ cache-size 512
|
||||
# dualstack-preference [yes|no]
|
||||
# dualstack-preference yes
|
||||
|
||||
# edns client subnet
|
||||
# edns-client-subnet-ipv4 [ip/subnet]
|
||||
# edns-client-subnet-ipv6 [ip/subnet]
|
||||
# edns-client-subnet-ipv4 192.168.1.1/24
|
||||
|
||||
# ttl for all resource record
|
||||
# rr-ttl: ttl for all record
|
||||
# rr-ttl-min: minimum ttl for resource record
|
||||
|
||||
@@ -656,7 +656,7 @@ int dns_get_OPT_payload_size(struct dns_packet *packet)
|
||||
return packet->payloadsize;
|
||||
}
|
||||
|
||||
int dns_add_OPT_ECS(struct dns_packet *packet, dns_rr_type type, struct dns_opt_ecs *ecs)
|
||||
int dns_add_OPT_ECS(struct dns_packet *packet, struct dns_opt_ecs *ecs)
|
||||
{
|
||||
unsigned char opt_data[DNS_MAX_OPT_LEN];
|
||||
struct dns_opt *opt = (struct dns_opt *)opt_data;
|
||||
@@ -1425,7 +1425,7 @@ static int _dns_decode_opt(struct dns_context *context, dns_rr_type type, unsign
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = dns_add_OPT_ECS(packet, type, &ecs);
|
||||
ret = dns_add_OPT_ECS(packet, &ecs);
|
||||
} break;
|
||||
default:
|
||||
context->ptr += opt_len;
|
||||
|
||||
@@ -10,10 +10,13 @@
|
||||
#define DNS_RR_AAAA_LEN 16
|
||||
#define DNS_MAX_CNAME_LEN 256
|
||||
#define DNS_MAX_OPT_LEN 256
|
||||
#define DNS_IN_PACKSIZE (512 * 4)
|
||||
#define DNS_IN_PACKSIZE (512 * 2)
|
||||
#define DNS_PACKSIZE (512 * 8)
|
||||
#define DNS_DEFAULT_PACKET_SIZE 512
|
||||
|
||||
#define DNS_ADDR_FAMILY_IP 1
|
||||
#define DNS_ADDR_FAMILY_IPV6 2
|
||||
|
||||
typedef enum dns_qr {
|
||||
DNS_QR_QUERY = 0,
|
||||
DNS_QR_ANSWER = 1,
|
||||
@@ -188,7 +191,7 @@ int dns_get_SOA(struct dns_rrs *rrs, char *domain, int maxsize, int *ttl, struct
|
||||
int dns_set_OPT_payload_size(struct dns_packet *packet, int payload_size);
|
||||
int dns_get_OPT_payload_size(struct dns_packet *packet);
|
||||
|
||||
int dns_add_OPT_ECS(struct dns_packet *packet, dns_rr_type type, struct dns_opt_ecs *ecs);
|
||||
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);
|
||||
/*
|
||||
* Packet operation
|
||||
|
||||
@@ -50,6 +50,17 @@
|
||||
#define DNS_HOSTNAME_LEN 128
|
||||
#define DNS_TCP_BUFFER (16 * 1024)
|
||||
|
||||
struct dns_client_ecs {
|
||||
int enable;
|
||||
unsigned int family;
|
||||
unsigned int bitlen;
|
||||
union {
|
||||
unsigned char ipv4_addr[DNS_RR_A_LEN];
|
||||
unsigned char ipv6_addr[DNS_RR_AAAA_LEN];
|
||||
unsigned char addr[0];
|
||||
};
|
||||
};
|
||||
|
||||
/* dns client */
|
||||
struct dns_client {
|
||||
pthread_t tid;
|
||||
@@ -65,6 +76,10 @@ struct dns_client {
|
||||
struct list_head dns_request_list;
|
||||
atomic_t dns_server_num;
|
||||
|
||||
/* ECS */
|
||||
struct dns_client_ecs ecs_ipv4;
|
||||
struct dns_client_ecs ecs_ipv6;
|
||||
|
||||
/* query doman hash table, key: sid + domain */
|
||||
pthread_mutex_t domain_map_lock;
|
||||
DECLARE_HASHTABLE(domain_map, 6);
|
||||
@@ -1548,6 +1563,26 @@ static int _dns_client_send_packet(struct dns_query_struct *query, void *packet,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _dns_client_dns_add_ecs(struct dns_packet *packet, int qtype)
|
||||
{
|
||||
if (qtype == DNS_T_A && client.ecs_ipv4.enable) {
|
||||
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);
|
||||
} else if (qtype == DNS_T_AAAA && client.ecs_ipv6.enable) {
|
||||
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)
|
||||
{
|
||||
unsigned char packet_buff[DNS_PACKSIZE];
|
||||
@@ -1571,7 +1606,13 @@ static int _dns_client_send_query(struct dns_query_struct *query, char *doamin)
|
||||
/* add question */
|
||||
dns_add_domain(packet, doamin, query->qtype, DNS_C_IN);
|
||||
|
||||
dns_set_OPT_payload_size(packet, 1024);
|
||||
dns_set_OPT_payload_size(packet, DNS_IN_PACKSIZE);
|
||||
|
||||
if (_dns_client_dns_add_ecs(packet, query->qtype) != 0) {
|
||||
tlog(TLOG_ERROR, "add ecs failed.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* encode packet */
|
||||
encode_len = dns_encode(inpacket, DNS_IN_PACKSIZE, packet);
|
||||
if (encode_len <= 0) {
|
||||
@@ -1642,6 +1683,12 @@ errout:
|
||||
return -1;
|
||||
}
|
||||
|
||||
int dns_client_set_ecs(char *ip, int subnet)
|
||||
{
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dns_client_init()
|
||||
{
|
||||
pthread_attr_t attr;
|
||||
|
||||
@@ -21,6 +21,8 @@ typedef enum dns_result_type {
|
||||
|
||||
int dns_client_init(void);
|
||||
|
||||
int dns_client_set_ecs(char *ip, int subnet);
|
||||
|
||||
/* query result notify function */
|
||||
typedef int (*dns_client_callback)(char *domain, dns_result_type rtype, unsigned int result_flag, struct dns_packet *packet, unsigned char *inpacket, int inpacket_len, void *user_ptr);
|
||||
|
||||
|
||||
@@ -44,6 +44,9 @@ int dns_conf_rr_ttl_min;
|
||||
int dns_conf_rr_ttl_max;
|
||||
int dns_conf_force_AAAA_SOA;
|
||||
|
||||
struct dns_edns_client_subnet dns_conf_ipv4_ecs;
|
||||
struct dns_edns_client_subnet dns_conf_ipv6_ecs;
|
||||
|
||||
int config_server(int argc, char *argv[], dns_server_type_t type, int default_port)
|
||||
{
|
||||
int index = dns_conf_server_num;
|
||||
@@ -477,14 +480,61 @@ int config_iplist_rule(char *subnet, enum address_rule rule)
|
||||
|
||||
int config_blacklist_ip(void *data, int argc, char *argv[])
|
||||
{
|
||||
if (argc <= 1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return config_iplist_rule(argv[1], ADDRESS_RULE_BLACKLIST);
|
||||
}
|
||||
|
||||
int conf_bogus_nxdomain(void *data, int argc, char *argv[])
|
||||
{
|
||||
if (argc <= 1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return config_iplist_rule(argv[1], ADDRESS_RULE_BOGUS);
|
||||
}
|
||||
|
||||
int conf_edns_client_subnet(void *data, int argc, char *argv[])
|
||||
{
|
||||
char *slash = NULL;
|
||||
char *value = NULL;
|
||||
int subnet = 0;
|
||||
struct dns_edns_client_subnet *ecs = data;
|
||||
struct sockaddr_storage addr;
|
||||
socklen_t addr_len = sizeof(addr);
|
||||
|
||||
if (argc <= 1 || data == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
value = argv[1];
|
||||
|
||||
slash = strstr(value, "/");
|
||||
if (slash) {
|
||||
*slash = 0;
|
||||
slash++;
|
||||
subnet = atoi(slash);
|
||||
if (subnet < 0 || subnet > 128) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (getaddr_by_host(value, (struct sockaddr *)&addr, &addr_len) != 0) {
|
||||
goto errout;
|
||||
}
|
||||
|
||||
strncpy(ecs->ip, value, DNS_MAX_IPLEN);
|
||||
ecs->subnet = subnet;
|
||||
ecs->enable = 1;
|
||||
|
||||
return 0;
|
||||
|
||||
errout:
|
||||
return -1;
|
||||
}
|
||||
|
||||
int config_log_level(void *data, int argc, char *argv[])
|
||||
{
|
||||
/* read log level and set */
|
||||
@@ -533,6 +583,8 @@ struct config_item config_item[] = {
|
||||
CONF_YESNO("force-AAAA-SOA", &dns_conf_force_AAAA_SOA),
|
||||
CONF_CUSTOM("blacklist-ip", config_blacklist_ip, NULL),
|
||||
CONF_CUSTOM("bogus-nxdomain", conf_bogus_nxdomain, NULL),
|
||||
CONF_CUSTOM("edns-client-subnet-ipv4", conf_edns_client_subnet, &dns_conf_ipv6_ecs),
|
||||
CONF_CUSTOM("edns-client-subnet-ipv6", conf_edns_client_subnet, &dns_conf_ipv6_ecs),
|
||||
CONF_CUSTOM("conf-file", config_addtional_file, NULL),
|
||||
CONF_END(),
|
||||
};
|
||||
|
||||
@@ -77,6 +77,12 @@ struct dns_ip_address_rule {
|
||||
unsigned int bogus : 1;
|
||||
};
|
||||
|
||||
struct dns_edns_client_subnet {
|
||||
int enable;
|
||||
char ip[DNS_MAX_IPLEN];
|
||||
int subnet;
|
||||
};
|
||||
|
||||
extern char dns_conf_server_ip[DNS_MAX_IPLEN];
|
||||
extern char dns_conf_server_tcp_ip[DNS_MAX_IPLEN];
|
||||
extern int dns_conf_tcp_idle_time;
|
||||
@@ -107,6 +113,9 @@ extern int dns_conf_rr_ttl_min;
|
||||
extern int dns_conf_rr_ttl_max;
|
||||
extern int dns_conf_force_AAAA_SOA;
|
||||
|
||||
extern struct dns_edns_client_subnet dns_conf_ipv4_ecs;
|
||||
extern struct dns_edns_client_subnet dns_conf_ipv6_ecs;
|
||||
|
||||
void dns_server_load_exit(void);
|
||||
|
||||
int dns_server_load_conf(const char *file);
|
||||
|
||||
@@ -567,7 +567,8 @@ void _dns_server_request_release(struct dns_request *request)
|
||||
int refcnt = atomic_dec_return(&request->refcnt);
|
||||
if (refcnt) {
|
||||
if (refcnt < 0) {
|
||||
tlog(TLOG_ERROR, "BUG: refcnt is %d, domain %s", refcnt, request->domain);
|
||||
tlog(TLOG_ERROR, "BUG: refcnt is %d, domain %s, qtype =%d", refcnt, request->domain,
|
||||
request->qtype);
|
||||
abort();
|
||||
}
|
||||
return;
|
||||
@@ -707,10 +708,10 @@ int _dns_ip_address_check_add(struct dns_request *request, unsigned char *addr,
|
||||
}
|
||||
}
|
||||
request->ip_map_num++;
|
||||
pthread_mutex_unlock(&request->ip_map_lock);
|
||||
|
||||
addr_map = malloc(sizeof(*addr_map));
|
||||
if (addr_map == NULL) {
|
||||
pthread_mutex_unlock(&request->ip_map_lock);
|
||||
tlog(TLOG_ERROR, "malloc failed");
|
||||
return -1;
|
||||
}
|
||||
@@ -718,6 +719,7 @@ int _dns_ip_address_check_add(struct dns_request *request, unsigned char *addr,
|
||||
addr_map->addr_type = addr_type;
|
||||
memcpy(addr_map->addr, addr, addr_len);
|
||||
hash_add(request->ip_map, &addr_map->node, key);
|
||||
pthread_mutex_unlock(&request->ip_map_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1302,12 +1304,12 @@ static int _dns_server_recv(struct dns_server_conn *client, unsigned char *inpac
|
||||
_dns_server_request_get(request);
|
||||
request->send_tick = get_tick_count();
|
||||
|
||||
dns_client_query(request->domain, qtype, dns_server_resolve_callback, request);
|
||||
request->request_wait++;
|
||||
dns_client_query(request->domain, qtype, dns_server_resolve_callback, request);
|
||||
if (qtype == DNS_T_AAAA && dns_conf_dualstack_preference) {
|
||||
_dns_server_request_get(request);
|
||||
dns_client_query(request->domain, DNS_T_A, dns_server_resolve_callback, request);
|
||||
request->request_wait++;
|
||||
dns_client_query(request->domain, DNS_T_A, dns_server_resolve_callback, request);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1361,6 +1363,7 @@ static int _dns_server_prefetch_request(char *domain, dns_type_t qtype)
|
||||
|
||||
_dns_server_request_get(request);
|
||||
request->send_tick = get_tick_count();
|
||||
request->request_wait++;
|
||||
dns_client_query(request->domain, qtype, dns_server_resolve_callback, request);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -134,6 +134,20 @@ int smartdns_add_servers(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int smartdns_set_ecs_ip(void)
|
||||
{
|
||||
int ret = 0;
|
||||
if (dns_conf_ipv4_ecs.enable) {
|
||||
ret |= dns_client_set_ecs(dns_conf_ipv4_ecs.ip, dns_conf_ipv4_ecs.subnet);
|
||||
}
|
||||
|
||||
if (dns_conf_ipv6_ecs.enable) {
|
||||
ret |= dns_client_set_ecs(dns_conf_ipv6_ecs.ip, dns_conf_ipv6_ecs.subnet);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int create_pid_file(const char *pid_file)
|
||||
{
|
||||
int fd;
|
||||
@@ -251,6 +265,11 @@ int smartdns_init(void)
|
||||
goto errout;
|
||||
}
|
||||
|
||||
ret = smartdns_set_ecs_ip();
|
||||
if (ret != 0 ) {
|
||||
tlog(TLOG_WARN, "set ecs ip address failed.");
|
||||
}
|
||||
|
||||
return 0;
|
||||
errout:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user