feature: add expand ptr from address feature
This commit is contained in:
@@ -236,6 +236,9 @@ log-level info
|
|||||||
# nameserver /www.example.com/office, Set the domain name to use the appropriate server group.
|
# nameserver /www.example.com/office, Set the domain name to use the appropriate server group.
|
||||||
# nameserver /www.example.com/-, ignore this domain
|
# nameserver /www.example.com/-, ignore this domain
|
||||||
|
|
||||||
|
# expand ptr record from address record
|
||||||
|
# expand-ptr-from-address yes
|
||||||
|
|
||||||
# specific address to domain
|
# specific address to domain
|
||||||
# address /domain/[ip|-|-4|-6|#|#4|#6]
|
# address /domain/[ip|-|-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
|
||||||
|
|||||||
@@ -140,6 +140,8 @@ int dns_conf_dualstack_ip_selection = 1;
|
|||||||
int dns_conf_dualstack_ip_allow_force_AAAA;
|
int dns_conf_dualstack_ip_allow_force_AAAA;
|
||||||
int dns_conf_dualstack_ip_selection_threshold = 10;
|
int dns_conf_dualstack_ip_selection_threshold = 10;
|
||||||
|
|
||||||
|
int dns_conf_expand_ptr_from_address = 0;
|
||||||
|
|
||||||
/* TTL */
|
/* TTL */
|
||||||
int dns_conf_rr_ttl;
|
int dns_conf_rr_ttl;
|
||||||
int dns_conf_rr_ttl_reply_max;
|
int dns_conf_rr_ttl_reply_max;
|
||||||
@@ -167,6 +169,7 @@ struct dns_edns_client_subnet dns_conf_ipv6_ecs;
|
|||||||
char dns_conf_sni_proxy_ip[DNS_MAX_IPLEN];
|
char dns_conf_sni_proxy_ip[DNS_MAX_IPLEN];
|
||||||
|
|
||||||
static int _conf_domain_rule_nameserver(char *domain, const char *group_name);
|
static int _conf_domain_rule_nameserver(char *domain, const char *group_name);
|
||||||
|
static int _conf_ptr_add(const char *hostname, const char *ip, int is_dynamic);
|
||||||
|
|
||||||
static void *_new_dns_rule(enum domain_rule domain_rule)
|
static void *_new_dns_rule(enum domain_rule domain_rule)
|
||||||
{
|
{
|
||||||
@@ -1575,6 +1578,11 @@ static int _conf_domain_rule_address(char *domain, const char *domain_address)
|
|||||||
default:
|
default:
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* add PTR */
|
||||||
|
if (dns_conf_expand_ptr_from_address == 1 && _conf_ptr_add(domain, ip, 0) != 0) {
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add domain to ART-tree */
|
/* add domain to ART-tree */
|
||||||
@@ -2790,6 +2798,7 @@ static struct dns_ptr *_dns_conf_get_ptr(const char *ptr_domain)
|
|||||||
|
|
||||||
safe_strncpy(ptr->ptr_domain, ptr_domain, DNS_MAX_PTR_LEN);
|
safe_strncpy(ptr->ptr_domain, ptr_domain, DNS_MAX_PTR_LEN);
|
||||||
hash_add(dns_ptr_table.ptr, &ptr->node, key);
|
hash_add(dns_ptr_table.ptr, &ptr->node, key);
|
||||||
|
ptr->is_soa = 1;
|
||||||
|
|
||||||
return ptr;
|
return ptr;
|
||||||
errout:
|
errout:
|
||||||
@@ -2800,7 +2809,7 @@ errout:
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _conf_ptr_add(const char *hostname, const char *ip)
|
static int _conf_ptr_add(const char *hostname, const char *ip, int is_dynamic)
|
||||||
{
|
{
|
||||||
struct dns_ptr *ptr = NULL;
|
struct dns_ptr *ptr = NULL;
|
||||||
struct sockaddr_storage addr;
|
struct sockaddr_storage addr;
|
||||||
@@ -2852,6 +2861,13 @@ static int _conf_ptr_add(const char *hostname, const char *ip)
|
|||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_dynamic == 1 && ptr->is_soa == 0 && ptr->is_dynamic == 0) {
|
||||||
|
/* already set fix PTR, skip */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr->is_dynamic = is_dynamic;
|
||||||
|
ptr->is_soa = 0;
|
||||||
safe_strncpy(ptr->hostname, hostname, DNS_MAX_CNAME_LEN);
|
safe_strncpy(ptr->hostname, hostname, DNS_MAX_CNAME_LEN);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -2860,7 +2876,7 @@ errout:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _config_ptr_table_destroy(void)
|
static void _config_ptr_table_destroy(int only_dynamic)
|
||||||
{
|
{
|
||||||
struct dns_ptr *ptr = NULL;
|
struct dns_ptr *ptr = NULL;
|
||||||
struct hlist_node *tmp = NULL;
|
struct hlist_node *tmp = NULL;
|
||||||
@@ -2868,6 +2884,10 @@ static void _config_ptr_table_destroy(void)
|
|||||||
|
|
||||||
hash_for_each_safe(dns_ptr_table.ptr, i, tmp, ptr, node)
|
hash_for_each_safe(dns_ptr_table.ptr, i, tmp, ptr, node)
|
||||||
{
|
{
|
||||||
|
if (only_dynamic != 0 && ptr->is_dynamic == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
hlist_del_init(&ptr->node);
|
hlist_del_init(&ptr->node);
|
||||||
free(ptr);
|
free(ptr);
|
||||||
}
|
}
|
||||||
@@ -2912,7 +2932,7 @@ errout:
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _conf_host_add(const char *hostname, const char *ip, dns_hosts_type host_type)
|
static int _conf_host_add(const char *hostname, const char *ip, dns_hosts_type host_type, int is_dynamic)
|
||||||
{
|
{
|
||||||
struct dns_hosts *host = NULL;
|
struct dns_hosts *host = NULL;
|
||||||
struct dns_hosts *host_other __attribute__((unused));
|
struct dns_hosts *host_other __attribute__((unused));
|
||||||
@@ -2952,9 +2972,14 @@ static int _conf_host_add(const char *hostname, const char *ip, dns_hosts_type h
|
|||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_dynamic == 1 && host->is_soa == 0 && host->is_dynamic == 0) {
|
||||||
|
/* already set fixed PTR, skip */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* add this to return SOA when addr is not exist */
|
/* add this to return SOA when addr is not exist */
|
||||||
host_other = _dns_conf_get_hosts(hostname, dns_type_other);
|
host_other = _dns_conf_get_hosts(hostname, dns_type_other);
|
||||||
|
host->is_dynamic = is_dynamic;
|
||||||
host->host_type = host_type;
|
host->host_type = host_type;
|
||||||
|
|
||||||
switch (addr.ss_family) {
|
switch (addr.ss_family) {
|
||||||
@@ -3013,12 +3038,12 @@ static int _conf_dhcp_lease_dnsmasq_add(const char *file)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = _conf_host_add(hostname, ip, DNS_HOST_TYPE_DNSMASQ);
|
ret = _conf_host_add(hostname, ip, DNS_HOST_TYPE_DNSMASQ, 1);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
tlog(TLOG_WARN, "add host %s/%s at %d failed", hostname, ip, line_no);
|
tlog(TLOG_WARN, "add host %s/%s at %d failed", hostname, ip, line_no);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = _conf_ptr_add(hostname, ip);
|
ret = _conf_ptr_add(hostname, ip, 1);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
tlog(TLOG_WARN, "add ptr %s/%s at %d failed.", hostname, ip, line_no);
|
tlog(TLOG_WARN, "add ptr %s/%s at %d failed.", hostname, ip, line_no);
|
||||||
}
|
}
|
||||||
@@ -3055,7 +3080,7 @@ static int _conf_hosts_file(void *data, int argc, char *argv[])
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _config_host_table_destroy(void)
|
static void _config_host_table_destroy(int only_dynamic)
|
||||||
{
|
{
|
||||||
struct dns_hosts *host = NULL;
|
struct dns_hosts *host = NULL;
|
||||||
struct hlist_node *tmp = NULL;
|
struct hlist_node *tmp = NULL;
|
||||||
@@ -3063,6 +3088,10 @@ static void _config_host_table_destroy(void)
|
|||||||
|
|
||||||
hash_for_each_safe(dns_hosts_table.hosts, i, tmp, host, node)
|
hash_for_each_safe(dns_hosts_table.hosts, i, tmp, host, node)
|
||||||
{
|
{
|
||||||
|
if (only_dynamic != 0 && host->is_dynamic == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
hlist_del_init(&host->node);
|
hlist_del_init(&host->node);
|
||||||
free(host);
|
free(host);
|
||||||
}
|
}
|
||||||
@@ -3093,8 +3122,8 @@ int dns_server_check_update_hosts(void)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
_config_ptr_table_destroy();
|
_config_ptr_table_destroy(1);
|
||||||
_config_host_table_destroy();
|
_config_host_table_destroy(1);
|
||||||
|
|
||||||
if (_conf_dhcp_lease_dnsmasq_add(dns_conf_dnsmasq_lease_file) != 0) {
|
if (_conf_dhcp_lease_dnsmasq_add(dns_conf_dnsmasq_lease_file) != 0) {
|
||||||
return -1;
|
return -1;
|
||||||
@@ -3187,6 +3216,7 @@ static struct config_item _config_item[] = {
|
|||||||
CONF_CUSTOM("server-tls", _config_server_tls, NULL),
|
CONF_CUSTOM("server-tls", _config_server_tls, NULL),
|
||||||
CONF_CUSTOM("server-https", _config_server_https, NULL),
|
CONF_CUSTOM("server-https", _config_server_https, NULL),
|
||||||
CONF_CUSTOM("nameserver", _config_nameserver, NULL),
|
CONF_CUSTOM("nameserver", _config_nameserver, NULL),
|
||||||
|
CONF_YESNO("expand-ptr-from-address", &dns_conf_expand_ptr_from_address),
|
||||||
CONF_CUSTOM("address", _config_address, NULL),
|
CONF_CUSTOM("address", _config_address, NULL),
|
||||||
CONF_CUSTOM("cname", _config_cname, NULL),
|
CONF_CUSTOM("cname", _config_cname, NULL),
|
||||||
CONF_CUSTOM("proxy-server", _config_proxy_server, NULL),
|
CONF_CUSTOM("proxy-server", _config_proxy_server, NULL),
|
||||||
@@ -3336,8 +3366,8 @@ void dns_server_load_exit(void)
|
|||||||
_config_ipset_table_destroy();
|
_config_ipset_table_destroy();
|
||||||
_config_nftset_table_destroy();
|
_config_nftset_table_destroy();
|
||||||
_config_group_table_destroy();
|
_config_group_table_destroy();
|
||||||
_config_ptr_table_destroy();
|
_config_ptr_table_destroy(0);
|
||||||
_config_host_table_destroy();
|
_config_host_table_destroy(0);
|
||||||
_config_qtype_soa_table_destroy();
|
_config_qtype_soa_table_destroy();
|
||||||
_config_proxy_table_destroy();
|
_config_proxy_table_destroy();
|
||||||
|
|
||||||
|
|||||||
@@ -249,6 +249,8 @@ struct dns_ptr {
|
|||||||
struct hlist_node node;
|
struct hlist_node node;
|
||||||
char ptr_domain[DNS_MAX_PTR_LEN];
|
char ptr_domain[DNS_MAX_PTR_LEN];
|
||||||
char hostname[DNS_MAX_CNAME_LEN];
|
char hostname[DNS_MAX_CNAME_LEN];
|
||||||
|
char is_dynamic;
|
||||||
|
char is_soa;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dns_ptr_table {
|
struct dns_ptr_table {
|
||||||
@@ -266,7 +268,8 @@ struct dns_hosts {
|
|||||||
char domain[DNS_MAX_CNAME_LEN];
|
char domain[DNS_MAX_CNAME_LEN];
|
||||||
dns_hosts_type host_type;
|
dns_hosts_type host_type;
|
||||||
int dns_type;
|
int dns_type;
|
||||||
int is_soa;
|
char is_soa;
|
||||||
|
char is_dynamic;
|
||||||
union {
|
union {
|
||||||
unsigned char ipv4_addr[DNS_RR_A_LEN];
|
unsigned char ipv4_addr[DNS_RR_A_LEN];
|
||||||
unsigned char ipv6_addr[DNS_RR_AAAA_LEN];
|
unsigned char ipv6_addr[DNS_RR_AAAA_LEN];
|
||||||
|
|||||||
@@ -161,3 +161,50 @@ 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, ptr)
|
||||||
|
{
|
||||||
|
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
|
||||||
|
expand-ptr-from-address yes
|
||||||
|
address /a.com/10.11.12.13
|
||||||
|
address /a.com/64:ff9b::1010:1010
|
||||||
|
cache-persist no)""");
|
||||||
|
smartdns::Client client;
|
||||||
|
ASSERT_TRUE(client.Query("13.12.11.10.in-addr.arpa PTR", 60053));
|
||||||
|
std::cout << client.GetResult() << std::endl;
|
||||||
|
ASSERT_EQ(client.GetAnswerNum(), 1);
|
||||||
|
EXPECT_EQ(client.GetStatus(), "NOERROR");
|
||||||
|
EXPECT_EQ(client.GetAnswer()[0].GetName(), "13.12.11.10.in-addr.arpa");
|
||||||
|
EXPECT_EQ(client.GetAnswer()[0].GetTTL(), 600);
|
||||||
|
EXPECT_EQ(client.GetAnswer()[0].GetType(), "PTR");
|
||||||
|
EXPECT_EQ(client.GetAnswer()[0].GetData(), "a.com.");
|
||||||
|
|
||||||
|
ASSERT_TRUE(client.Query("0.1.0.1.0.1.0.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.b.9.f.f.4.6.0.0.ip6.arpa PTR", 60053));
|
||||||
|
std::cout << client.GetResult() << std::endl;
|
||||||
|
ASSERT_EQ(client.GetAnswerNum(), 1);
|
||||||
|
EXPECT_EQ(client.GetStatus(), "NOERROR");
|
||||||
|
EXPECT_EQ(client.GetAnswer()[0].GetName(),
|
||||||
|
"0.1.0.1.0.1.0.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.b.9.f.f.4.6.0.0.ip6.arpa");
|
||||||
|
EXPECT_EQ(client.GetAnswer()[0].GetTTL(), 600);
|
||||||
|
EXPECT_EQ(client.GetAnswer()[0].GetType(), "PTR");
|
||||||
|
EXPECT_EQ(client.GetAnswer()[0].GetData(), "a.com.");
|
||||||
|
}
|
||||||
@@ -49,7 +49,18 @@ DNSRecord::~DNSRecord() {}
|
|||||||
|
|
||||||
bool DNSRecord::Parser(const std::string &line)
|
bool DNSRecord::Parser(const std::string &line)
|
||||||
{
|
{
|
||||||
std::vector<std::string> fields = StringSplit(line, '\t');
|
std::vector<std::string> fields_first = StringSplit(line, '\t');
|
||||||
|
std::vector<std::string> fields;
|
||||||
|
|
||||||
|
for (const auto &f : fields_first) {
|
||||||
|
std::vector<std::string> fields_second = StringSplit(f, ' ');
|
||||||
|
for (const auto &s : fields_second) {
|
||||||
|
if (s.length() > 0) {
|
||||||
|
fields.push_back(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (fields.size() < 3) {
|
if (fields.size() < 3) {
|
||||||
std::cerr << "Invalid DNS record: " << line << ", size: " << fields.size() << std::endl;
|
std::cerr << "Invalid DNS record: " << line << ", size: " << fields.size() << std::endl;
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
Reference in New Issue
Block a user