address: support multiple ip addresses
This commit is contained in:
@@ -247,8 +247,9 @@ log-level info
|
|||||||
# expand-ptr-from-address yes
|
# expand-ptr-from-address yes
|
||||||
|
|
||||||
# specific address to domain
|
# specific address to domain
|
||||||
# address /domain/[ip|-|-4|-6|#|#4|#6]
|
# address /domain/[ip1,ip2|-|-4|-6|#|#4|#6]
|
||||||
# address /www.example.com/1.2.3.4, return ip 1.2.3.4 to client
|
# address /www.example.com/1.2.3.4, return ip 1.2.3.4 to client
|
||||||
|
# address /www.example.com/1.2.3.4,5.6.7.8, return multiple ip addresses
|
||||||
# address /www.example.com/-, ignore address, query from upstream, suffix 4, for ipv4, 6 for ipv6, none for all
|
# address /www.example.com/-, ignore address, query from upstream, suffix 4, for ipv4, 6 for ipv6, none for all
|
||||||
# address /www.example.com/#, return SOA to client, suffix 4, for ipv4, 6 for ipv6, none for all
|
# address /www.example.com/#, return SOA to client, suffix 4, for ipv4, 6 for ipv6, none for all
|
||||||
|
|
||||||
|
|||||||
166
src/dns_conf.c
166
src/dns_conf.c
@@ -30,7 +30,7 @@
|
|||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#define DNS_MAX_REPLY_IP_NUM 8
|
#define TMP_BUFF_LEN 1024
|
||||||
|
|
||||||
/* ipset */
|
/* ipset */
|
||||||
struct dns_ipset_table {
|
struct dns_ipset_table {
|
||||||
@@ -173,7 +173,7 @@ static int _conf_ptr_add(const char *hostname, const char *ip, int is_dynamic);
|
|||||||
static int _conf_client_subnet(char *subnet, struct dns_edns_client_subnet *ipv4_ecs,
|
static int _conf_client_subnet(char *subnet, struct dns_edns_client_subnet *ipv4_ecs,
|
||||||
struct dns_edns_client_subnet *ipv6_ecs);
|
struct dns_edns_client_subnet *ipv6_ecs);
|
||||||
|
|
||||||
static void *_new_dns_rule(enum domain_rule domain_rule)
|
static void *_new_dns_rule_ext(enum domain_rule domain_rule, int ext_size)
|
||||||
{
|
{
|
||||||
struct dns_rule *rule;
|
struct dns_rule *rule;
|
||||||
int size = 0;
|
int size = 0;
|
||||||
@@ -220,6 +220,7 @@ static void *_new_dns_rule(enum domain_rule domain_rule)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size += ext_size;
|
||||||
rule = malloc(size);
|
rule = malloc(size);
|
||||||
if (!rule) {
|
if (!rule) {
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -230,6 +231,11 @@ static void *_new_dns_rule(enum domain_rule domain_rule)
|
|||||||
return rule;
|
return rule;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void *_new_dns_rule(enum domain_rule domain_rule)
|
||||||
|
{
|
||||||
|
return _new_dns_rule_ext(domain_rule, 0);
|
||||||
|
}
|
||||||
|
|
||||||
static void _dns_rule_get(struct dns_rule *rule)
|
static void _dns_rule_get(struct dns_rule *rule)
|
||||||
{
|
{
|
||||||
atomic_inc(&rule->refcnt);
|
atomic_inc(&rule->refcnt);
|
||||||
@@ -1498,50 +1504,75 @@ static int _conf_domain_rule_address(char *domain, const char *domain_address)
|
|||||||
struct dns_rule_address_IPV4 *address_ipv4 = NULL;
|
struct dns_rule_address_IPV4 *address_ipv4 = NULL;
|
||||||
struct dns_rule_address_IPV6 *address_ipv6 = NULL;
|
struct dns_rule_address_IPV6 *address_ipv6 = NULL;
|
||||||
struct dns_rule *address = NULL;
|
struct dns_rule *address = NULL;
|
||||||
|
|
||||||
char ip[MAX_IP_LEN];
|
char ip[MAX_IP_LEN];
|
||||||
int port = 0;
|
int port = 0;
|
||||||
struct sockaddr_storage addr;
|
struct sockaddr_storage addr;
|
||||||
socklen_t addr_len = sizeof(addr);
|
socklen_t addr_len = sizeof(addr);
|
||||||
enum domain_rule type = 0;
|
|
||||||
unsigned int flag = 0;
|
unsigned int flag = 0;
|
||||||
|
char *ptr = NULL;
|
||||||
|
char *field = NULL;
|
||||||
|
char tmpbuff[TMP_BUFF_LEN] = {0};
|
||||||
|
|
||||||
if (*(domain_address) == '#') {
|
char ipv6_addr[DNS_MAX_REPLY_IP_NUM][DNS_RR_AAAA_LEN];
|
||||||
if (strncmp(domain_address, "#4", sizeof("#4")) == 0) {
|
int ipv6_num = 0;
|
||||||
flag = DOMAIN_FLAG_ADDR_IPV4_SOA;
|
char ipv4_addr[DNS_MAX_REPLY_IP_NUM][DNS_RR_A_LEN];
|
||||||
} else if (strncmp(domain_address, "#6", sizeof("#6")) == 0) {
|
int ipv4_num = 0;
|
||||||
flag = DOMAIN_FLAG_ADDR_IPV6_SOA;
|
|
||||||
} else if (strncmp(domain_address, "#", sizeof("#")) == 0) {
|
safe_strncpy(tmpbuff, domain_address, sizeof(tmpbuff));
|
||||||
flag = DOMAIN_FLAG_ADDR_SOA;
|
|
||||||
} else {
|
ptr = tmpbuff;
|
||||||
goto errout;
|
|
||||||
|
do {
|
||||||
|
field = ptr;
|
||||||
|
ptr = strstr(ptr, ",");
|
||||||
|
|
||||||
|
if (field == NULL) {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add SOA rule */
|
if (ptr) {
|
||||||
if (_config_domain_rule_flag_set(domain, flag, 0) != 0) {
|
*ptr = 0;
|
||||||
goto errout;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
if (*(field) == '#') {
|
||||||
} else if (*(domain_address) == '-') {
|
if (strncmp(field, "#4", sizeof("#4")) == 0) {
|
||||||
if (strncmp(domain_address, "-4", sizeof("-4")) == 0) {
|
flag = DOMAIN_FLAG_ADDR_IPV4_SOA;
|
||||||
flag = DOMAIN_FLAG_ADDR_IPV4_IGN;
|
} else if (strncmp(field, "#6", sizeof("#6")) == 0) {
|
||||||
} else if (strncmp(domain_address, "-6", sizeof("-6")) == 0) {
|
flag = DOMAIN_FLAG_ADDR_IPV6_SOA;
|
||||||
flag = DOMAIN_FLAG_ADDR_IPV6_IGN;
|
} else if (strncmp(field, "#", sizeof("#")) == 0) {
|
||||||
} else if (strncmp(domain_address, "-", sizeof("-")) == 0) {
|
flag = DOMAIN_FLAG_ADDR_SOA;
|
||||||
flag = DOMAIN_FLAG_ADDR_IGN;
|
} else {
|
||||||
} else {
|
goto errout;
|
||||||
goto errout;
|
}
|
||||||
|
|
||||||
|
/* add SOA rule */
|
||||||
|
if (_config_domain_rule_flag_set(domain, flag, 0) != 0) {
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
} else if (*(field) == '-') {
|
||||||
|
if (strncmp(field, "-4", sizeof("-4")) == 0) {
|
||||||
|
flag = DOMAIN_FLAG_ADDR_IPV4_IGN;
|
||||||
|
} else if (strncmp(field, "-6", sizeof("-6")) == 0) {
|
||||||
|
flag = DOMAIN_FLAG_ADDR_IPV6_IGN;
|
||||||
|
} else if (strncmp(field, "-", sizeof("-")) == 0) {
|
||||||
|
flag = DOMAIN_FLAG_ADDR_IGN;
|
||||||
|
} else {
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ignore rule */
|
||||||
|
if (_config_domain_rule_flag_set(domain, flag, 0) != 0) {
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ignore rule */
|
|
||||||
if (_config_domain_rule_flag_set(domain, flag, 0) != 0) {
|
|
||||||
goto errout;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
/* set address to domain */
|
/* set address to domain */
|
||||||
if (parse_ip(domain_address, ip, &port) != 0) {
|
if (parse_ip(field, ip, &port) != 0) {
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1552,53 +1583,74 @@ static int _conf_domain_rule_address(char *domain, const char *domain_address)
|
|||||||
switch (addr.ss_family) {
|
switch (addr.ss_family) {
|
||||||
case AF_INET: {
|
case AF_INET: {
|
||||||
struct sockaddr_in *addr_in = NULL;
|
struct sockaddr_in *addr_in = NULL;
|
||||||
address_ipv4 = _new_dns_rule(DOMAIN_RULE_ADDRESS_IPV4);
|
|
||||||
if (address_ipv4 == NULL) {
|
|
||||||
goto errout;
|
|
||||||
}
|
|
||||||
|
|
||||||
addr_in = (struct sockaddr_in *)&addr;
|
addr_in = (struct sockaddr_in *)&addr;
|
||||||
memcpy(address_ipv4->ipv4_addr, &addr_in->sin_addr.s_addr, 4);
|
memcpy(ipv4_addr[ipv4_num], &addr_in->sin_addr.s_addr, DNS_RR_A_LEN);
|
||||||
type = DOMAIN_RULE_ADDRESS_IPV4;
|
ipv4_num++;
|
||||||
address = (struct dns_rule *)address_ipv4;
|
|
||||||
} break;
|
} break;
|
||||||
case AF_INET6: {
|
case AF_INET6: {
|
||||||
struct sockaddr_in6 *addr_in6 = NULL;
|
struct sockaddr_in6 *addr_in6 = NULL;
|
||||||
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)) {
|
||||||
address_ipv4 = _new_dns_rule(DOMAIN_RULE_ADDRESS_IPV4);
|
memcpy(ipv4_addr[ipv4_num], addr_in6->sin6_addr.s6_addr + 12, DNS_RR_A_LEN);
|
||||||
if (address_ipv4 == NULL) {
|
ipv4_num++;
|
||||||
goto errout;
|
|
||||||
}
|
|
||||||
memcpy(address_ipv4->ipv4_addr, addr_in6->sin6_addr.s6_addr + 12, 4);
|
|
||||||
type = DOMAIN_RULE_ADDRESS_IPV4;
|
|
||||||
address = (struct dns_rule *)address_ipv4;
|
|
||||||
} else {
|
} else {
|
||||||
address_ipv6 = _new_dns_rule(DOMAIN_RULE_ADDRESS_IPV6);
|
address_ipv6 = _new_dns_rule(DOMAIN_RULE_ADDRESS_IPV6);
|
||||||
if (address_ipv6 == NULL) {
|
if (address_ipv6 == NULL) {
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
memcpy(address_ipv6->ipv6_addr, addr_in6->sin6_addr.s6_addr, 16);
|
memcpy(ipv6_addr[ipv6_num], addr_in6->sin6_addr.s6_addr, DNS_RR_AAAA_LEN);
|
||||||
type = DOMAIN_RULE_ADDRESS_IPV6;
|
ipv6_num++;
|
||||||
address = (struct dns_rule *)address_ipv6;
|
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
default:
|
default:
|
||||||
goto errout;
|
ip[0] = '\0';
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add PTR */
|
/* add PTR */
|
||||||
if (dns_conf_expand_ptr_from_address == 1 && _conf_ptr_add(domain, ip, 0) != 0) {
|
if (dns_conf_expand_ptr_from_address == 1 && ip[0] != '\0' && _conf_ptr_add(domain, ip, 0) != 0) {
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ptr) {
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
} while (ptr);
|
||||||
|
|
||||||
|
if (ipv4_num > 0) {
|
||||||
|
address_ipv4 = _new_dns_rule_ext(DOMAIN_RULE_ADDRESS_IPV4, ipv4_num * DNS_RR_A_LEN);
|
||||||
|
if (address_ipv4 == NULL) {
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(address_ipv4->ipv4_addr, ipv4_addr[0], ipv4_num * DNS_RR_A_LEN);
|
||||||
|
address_ipv4->addr_num = ipv4_num;
|
||||||
|
address = (struct dns_rule *)address_ipv4;
|
||||||
|
|
||||||
|
if (_config_domain_rule_add(domain, DOMAIN_RULE_ADDRESS_IPV4, address) != 0) {
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
_dns_rule_put(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add domain to ART-tree */
|
if (ipv6_num > 0) {
|
||||||
if (_config_domain_rule_add(domain, type, address) != 0) {
|
address_ipv6 = _new_dns_rule_ext(DOMAIN_RULE_ADDRESS_IPV6, ipv6_num * DNS_RR_AAAA_LEN);
|
||||||
goto errout;
|
if (address_ipv6 == NULL) {
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(address_ipv6->ipv6_addr, ipv6_addr[0], ipv6_num * DNS_RR_AAAA_LEN);
|
||||||
|
address_ipv6->addr_num = ipv6_num;
|
||||||
|
address = (struct dns_rule *)address_ipv6;
|
||||||
|
|
||||||
|
if (_config_domain_rule_add(domain, DOMAIN_RULE_ADDRESS_IPV6, address) != 0) {
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
_dns_rule_put(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
_dns_rule_put(address);
|
|
||||||
return 0;
|
return 0;
|
||||||
errout:
|
errout:
|
||||||
if (address) {
|
if (address) {
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ extern "C" {
|
|||||||
#define DEFAULT_DNS_HTTPS_PORT 443
|
#define DEFAULT_DNS_HTTPS_PORT 443
|
||||||
#define DNS_MAX_CONF_CNAME_LEN 256
|
#define DNS_MAX_CONF_CNAME_LEN 256
|
||||||
#define MAX_QTYPE_NUM 65535
|
#define MAX_QTYPE_NUM 65535
|
||||||
|
#define DNS_MAX_REPLY_IP_NUM 8
|
||||||
|
|
||||||
#define SMARTDNS_CONF_FILE "/etc/smartdns/smartdns.conf"
|
#define SMARTDNS_CONF_FILE "/etc/smartdns/smartdns.conf"
|
||||||
#define SMARTDNS_LOG_FILE "/var/log/smartdns/smartdns.log"
|
#define SMARTDNS_LOG_FILE "/var/log/smartdns/smartdns.log"
|
||||||
@@ -150,12 +151,14 @@ struct dns_rule_flags {
|
|||||||
|
|
||||||
struct dns_rule_address_IPV4 {
|
struct dns_rule_address_IPV4 {
|
||||||
struct dns_rule head;
|
struct dns_rule head;
|
||||||
unsigned char ipv4_addr[DNS_RR_A_LEN];
|
char addr_num;
|
||||||
|
unsigned char ipv4_addr[][DNS_RR_A_LEN];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dns_rule_address_IPV6 {
|
struct dns_rule_address_IPV6 {
|
||||||
struct dns_rule head;
|
struct dns_rule head;
|
||||||
unsigned char ipv6_addr[DNS_RR_AAAA_LEN];
|
char addr_num;
|
||||||
|
unsigned char ipv6_addr[][DNS_RR_AAAA_LEN];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dns_ipset_name {
|
struct dns_ipset_name {
|
||||||
|
|||||||
@@ -4110,10 +4110,35 @@ static int _dns_server_get_local_ttl(struct dns_request *request)
|
|||||||
return DNS_SERVER_ADDR_TTL;
|
return DNS_SERVER_ADDR_TTL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int _dns_server_address_generate_order(int orders[], int order_num, int max_order_count)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
int j = 0;
|
||||||
|
int k = 0;
|
||||||
|
for (i = 0; i < order_num && i < max_order_count; i++) {
|
||||||
|
orders[i] = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < order_num && max_order_count; i++) {
|
||||||
|
k = rand() % order_num;
|
||||||
|
j = rand() % order_num;
|
||||||
|
if (j == k) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int temp = orders[j];
|
||||||
|
orders[j] = orders[k];
|
||||||
|
orders[k] = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int _dns_server_process_address(struct dns_request *request)
|
static int _dns_server_process_address(struct dns_request *request)
|
||||||
{
|
{
|
||||||
struct dns_rule_address_IPV4 *address_ipv4 = NULL;
|
struct dns_rule_address_IPV4 *address_ipv4 = NULL;
|
||||||
struct dns_rule_address_IPV6 *address_ipv6 = NULL;
|
struct dns_rule_address_IPV6 *address_ipv6 = NULL;
|
||||||
|
int orders[DNS_MAX_REPLY_IP_NUM];
|
||||||
|
|
||||||
if (_dns_server_has_bind_flag(request, BIND_FLAG_NO_RULE_ADDR) == 0) {
|
if (_dns_server_has_bind_flag(request, BIND_FLAG_NO_RULE_ADDR) == 0) {
|
||||||
goto errout;
|
goto errout;
|
||||||
@@ -4126,14 +4151,39 @@ static int _dns_server_process_address(struct dns_request *request)
|
|||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
address_ipv4 = _dns_server_get_dns_rule(request, DOMAIN_RULE_ADDRESS_IPV4);
|
address_ipv4 = _dns_server_get_dns_rule(request, DOMAIN_RULE_ADDRESS_IPV4);
|
||||||
memcpy(request->ip_addr, address_ipv4->ipv4_addr, DNS_RR_A_LEN);
|
if (address_ipv4 == NULL) {
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
_dns_server_address_generate_order(orders, address_ipv4->addr_num, DNS_MAX_REPLY_IP_NUM);
|
||||||
|
|
||||||
|
memcpy(request->ip_addr, address_ipv4->ipv4_addr[orders[0]], DNS_RR_A_LEN);
|
||||||
|
for (int i = 1; i < address_ipv4->addr_num; i++) {
|
||||||
|
int index = orders[i];
|
||||||
|
if (index >= address_ipv4->addr_num) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
_dns_ip_address_check_add(request, request->cname, address_ipv4->ipv4_addr[index], DNS_T_A, 1, NULL);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case DNS_T_AAAA:
|
case DNS_T_AAAA:
|
||||||
if (request->domain_rule.rules[DOMAIN_RULE_ADDRESS_IPV6] == NULL) {
|
if (request->domain_rule.rules[DOMAIN_RULE_ADDRESS_IPV6] == NULL) {
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
address_ipv6 = _dns_server_get_dns_rule(request, DOMAIN_RULE_ADDRESS_IPV6);
|
address_ipv6 = _dns_server_get_dns_rule(request, DOMAIN_RULE_ADDRESS_IPV6);
|
||||||
memcpy(request->ip_addr, address_ipv6->ipv6_addr, DNS_RR_AAAA_LEN);
|
if (address_ipv6 == NULL) {
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
_dns_server_address_generate_order(orders, address_ipv6->addr_num, DNS_MAX_REPLY_IP_NUM);
|
||||||
|
|
||||||
|
memcpy(request->ip_addr, address_ipv6->ipv6_addr[orders[0]], DNS_RR_AAAA_LEN);
|
||||||
|
for (int i = 1; i < address_ipv6->addr_num; i++) {
|
||||||
|
int index = orders[i];
|
||||||
|
if (index >= address_ipv6->addr_num) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
_dns_ip_address_check_add(request, request->cname, address_ipv6->ipv6_addr[index], DNS_T_AAAA, 1, NULL);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
goto errout;
|
goto errout;
|
||||||
@@ -4149,6 +4199,7 @@ static int _dns_server_process_address(struct dns_request *request)
|
|||||||
context.do_reply = 1;
|
context.do_reply = 1;
|
||||||
context.do_audit = 1;
|
context.do_audit = 1;
|
||||||
context.do_ipset = 1;
|
context.do_ipset = 1;
|
||||||
|
context.select_all_best_ip = 1;
|
||||||
_dns_request_post(&context);
|
_dns_request_post(&context);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -161,3 +161,94 @@ cache-persist no)""");
|
|||||||
EXPECT_EQ(client.GetAnswer()[0].GetType(), "AAAA");
|
EXPECT_EQ(client.GetAnswer()[0].GetType(), "AAAA");
|
||||||
EXPECT_EQ(client.GetAnswer()[0].GetData(), "64:ff9b::1010:1010");
|
EXPECT_EQ(client.GetAnswer()[0].GetData(), "64:ff9b::1010:1010");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(Address, multiaddress)
|
||||||
|
{
|
||||||
|
smartdns::MockServer server_upstream;
|
||||||
|
smartdns::Server server;
|
||||||
|
|
||||||
|
server_upstream.Start("udp://0.0.0.0:61053", [&](struct smartdns::ServerRequestContext *request) {
|
||||||
|
if (request->qtype == DNS_T_A) {
|
||||||
|
smartdns::MockServer::AddIP(request, request->domain.c_str(), "1.2.3.4", 700);
|
||||||
|
return smartdns::SERVER_REQUEST_OK;
|
||||||
|
} else if (request->qtype == DNS_T_AAAA) {
|
||||||
|
smartdns::MockServer::AddIP(request, request->domain.c_str(), "64:ff9b::102:304", 700);
|
||||||
|
return smartdns::SERVER_REQUEST_OK;
|
||||||
|
}
|
||||||
|
return smartdns::SERVER_REQUEST_SOA;
|
||||||
|
});
|
||||||
|
|
||||||
|
server.Start(R"""(bind [::]:60053
|
||||||
|
server 127.0.0.1:61053
|
||||||
|
log-num 0
|
||||||
|
log-console yes
|
||||||
|
log-level debug
|
||||||
|
speed-check-mode none
|
||||||
|
address /a.com/10.10.10.10,11.11.11.11,22.22.22.22
|
||||||
|
address /a.com/64:ff9b::1010:1010,64:ff9b::1111:1111,64:ff9b::2222:2222
|
||||||
|
cache-persist no)""");
|
||||||
|
smartdns::Client client;
|
||||||
|
ASSERT_TRUE(client.Query("a.com A", 60053));
|
||||||
|
std::cout << client.GetResult() << std::endl;
|
||||||
|
std::map<std::string, smartdns::DNSRecord *> result;
|
||||||
|
|
||||||
|
ASSERT_EQ(client.GetAnswerNum(), 3);
|
||||||
|
EXPECT_EQ(client.GetStatus(), "NOERROR");
|
||||||
|
auto answers = client.GetAnswer();
|
||||||
|
for (int i = 0; i < client.GetAnswerNum(); i++) {
|
||||||
|
result[client.GetAnswer()[i].GetData()] = &answers[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT_NE(result.find("10.10.10.10"), result.end());
|
||||||
|
auto check_result = result["10.10.10.10"];
|
||||||
|
EXPECT_EQ(check_result->GetName(), "a.com");
|
||||||
|
EXPECT_EQ(check_result->GetTTL(), 600);
|
||||||
|
EXPECT_EQ(check_result->GetType(), "A");
|
||||||
|
EXPECT_EQ(check_result->GetData(), "10.10.10.10");
|
||||||
|
|
||||||
|
ASSERT_NE(result.find("11.11.11.11"), result.end());
|
||||||
|
check_result = result["11.11.11.11"];
|
||||||
|
EXPECT_EQ(check_result->GetName(), "a.com");
|
||||||
|
EXPECT_EQ(check_result->GetTTL(), 600);
|
||||||
|
EXPECT_EQ(check_result->GetType(), "A");
|
||||||
|
EXPECT_EQ(check_result->GetData(), "11.11.11.11");
|
||||||
|
|
||||||
|
ASSERT_NE(result.find("22.22.22.22"), result.end());
|
||||||
|
check_result = result["22.22.22.22"];
|
||||||
|
EXPECT_EQ(check_result->GetName(), "a.com");
|
||||||
|
EXPECT_EQ(check_result->GetTTL(), 600);
|
||||||
|
EXPECT_EQ(check_result->GetType(), "A");
|
||||||
|
EXPECT_EQ(check_result->GetData(), "22.22.22.22");
|
||||||
|
|
||||||
|
result.clear();
|
||||||
|
|
||||||
|
ASSERT_TRUE(client.Query("a.com AAAA", 60053));
|
||||||
|
std::cout << client.GetResult() << std::endl;
|
||||||
|
ASSERT_EQ(client.GetAnswerNum(), 3);
|
||||||
|
EXPECT_EQ(client.GetStatus(), "NOERROR");
|
||||||
|
answers = client.GetAnswer();
|
||||||
|
for (int i = 0; i < client.GetAnswerNum(); i++) {
|
||||||
|
result[client.GetAnswer()[i].GetData()] = &answers[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT_NE(result.find("64:ff9b::1010:1010"), result.end());
|
||||||
|
check_result = result["64:ff9b::1010:1010"];
|
||||||
|
EXPECT_EQ(check_result->GetName(), "a.com");
|
||||||
|
EXPECT_EQ(check_result->GetTTL(), 600);
|
||||||
|
EXPECT_EQ(check_result->GetType(), "AAAA");
|
||||||
|
EXPECT_EQ(check_result->GetData(), "64:ff9b::1010:1010");
|
||||||
|
|
||||||
|
ASSERT_NE(result.find("64:ff9b::1111:1111"), result.end());
|
||||||
|
check_result = result["64:ff9b::1111:1111"];
|
||||||
|
EXPECT_EQ(check_result->GetName(), "a.com");
|
||||||
|
EXPECT_EQ(check_result->GetTTL(), 600);
|
||||||
|
EXPECT_EQ(check_result->GetType(), "AAAA");
|
||||||
|
EXPECT_EQ(check_result->GetData(), "64:ff9b::1111:1111");
|
||||||
|
|
||||||
|
ASSERT_NE(result.find("64:ff9b::2222:2222"), result.end());
|
||||||
|
check_result = result["64:ff9b::2222:2222"];
|
||||||
|
EXPECT_EQ(check_result->GetName(), "a.com");
|
||||||
|
EXPECT_EQ(check_result->GetTTL(), 600);
|
||||||
|
EXPECT_EQ(check_result->GetType(), "AAAA");
|
||||||
|
EXPECT_EQ(check_result->GetData(), "64:ff9b::2222:2222");
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user