cname: fix cname rule loop issue.
This commit is contained in:
@@ -2297,7 +2297,7 @@ static int _dns_client_process_udp(struct dns_server_info *server_info, struct e
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (errno == ECONNREFUSED) {
|
if (errno == ECONNREFUSED || errno == ENETUNREACH || errno == EHOSTUNREACH) {
|
||||||
tlog(TLOG_DEBUG, "recvfrom %s failed, %s\n", server_info->ip, strerror(errno));
|
tlog(TLOG_DEBUG, "recvfrom %s failed, %s\n", server_info->ip, strerror(errno));
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
@@ -3568,7 +3568,7 @@ static int _dns_client_send_packet(struct dns_query_struct *query, void *packet,
|
|||||||
time(&now);
|
time(&now);
|
||||||
if (now - lastlog > 120) {
|
if (now - lastlog > 120) {
|
||||||
lastlog = now;
|
lastlog = now;
|
||||||
tlog(TLOG_WARN, "Send query %s to upstream server failed, total server number %d", query->domain,
|
tlog(TLOG_WARN, "send query %s to upstream server failed, total server number %d", query->domain,
|
||||||
total_server);
|
total_server);
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
@@ -311,6 +311,8 @@ struct dns_request {
|
|||||||
int no_select_possible_ip;
|
int no_select_possible_ip;
|
||||||
int no_cache_cname;
|
int no_cache_cname;
|
||||||
int no_cache;
|
int no_cache;
|
||||||
|
|
||||||
|
int has_cname_loop;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* dns server data */
|
/* dns server data */
|
||||||
@@ -4228,6 +4230,10 @@ static int _dns_server_process_cname_pre(struct dns_request *request)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (request->has_cname_loop == 1) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* get domain rule flag */
|
/* get domain rule flag */
|
||||||
rule_flag = _dns_server_get_dns_rule(request, DOMAIN_RULE_FLAGS);
|
rule_flag = _dns_server_get_dns_rule(request, DOMAIN_RULE_FLAGS);
|
||||||
if (rule_flag != NULL) {
|
if (rule_flag != NULL) {
|
||||||
@@ -4267,6 +4273,10 @@ static int _dns_server_process_cname(struct dns_request *request)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (request->has_cname_loop == 1) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* get domain rule flag */
|
/* get domain rule flag */
|
||||||
rule_flag = _dns_server_get_dns_rule(request, DOMAIN_RULE_FLAGS);
|
rule_flag = _dns_server_get_dns_rule(request, DOMAIN_RULE_FLAGS);
|
||||||
if (rule_flag != NULL) {
|
if (rule_flag != NULL) {
|
||||||
@@ -4289,6 +4299,33 @@ static int _dns_server_process_cname(struct dns_request *request)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* check cname rule loop */
|
||||||
|
struct dns_request *check_request = child_request->parent_request;
|
||||||
|
struct dns_cname_rule *child_cname = _dns_server_get_dns_rule(child_request, DOMAIN_RULE_CNAME);
|
||||||
|
|
||||||
|
/* sub domain rule*/
|
||||||
|
if (child_cname != NULL && strncmp(child_request->domain, child_cname->cname, DNS_MAX_CNAME_LEN) == 0) {
|
||||||
|
child_request->domain_rule.rules[DOMAIN_RULE_CNAME] = NULL;
|
||||||
|
child_request->has_cname_loop = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* loop rule */
|
||||||
|
while (check_request != NULL && child_cname != NULL) {
|
||||||
|
struct dns_cname_rule *check_cname = _dns_server_get_dns_rule(check_request, DOMAIN_RULE_CNAME);
|
||||||
|
if (check_cname == NULL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strstr(child_request->domain, check_request->domain) != NULL &&
|
||||||
|
check_request != child_request->parent_request) {
|
||||||
|
child_request->domain_rule.rules[DOMAIN_RULE_CNAME] = NULL;
|
||||||
|
child_request->has_cname_loop = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
check_request = check_request->parent_request;
|
||||||
|
}
|
||||||
|
|
||||||
child_group_name = _dns_server_get_request_groupname(child_request);
|
child_group_name = _dns_server_get_request_groupname(child_request);
|
||||||
if (child_group_name) {
|
if (child_group_name) {
|
||||||
/* reset dns group and setup child request domain group again when do query.*/
|
/* reset dns group and setup child request domain group again when do query.*/
|
||||||
@@ -5029,6 +5066,7 @@ static int _dns_server_query_dualstack(struct dns_request *request)
|
|||||||
safe_strncpy(request_dualstack->domain, request->domain, sizeof(request->domain));
|
safe_strncpy(request_dualstack->domain, request->domain, sizeof(request->domain));
|
||||||
request_dualstack->qtype = qtype;
|
request_dualstack->qtype = qtype;
|
||||||
request_dualstack->dualstack_selection_query = 1;
|
request_dualstack->dualstack_selection_query = 1;
|
||||||
|
request_dualstack->has_cname_loop = request->has_cname_loop;
|
||||||
request_dualstack->prefetch = request->prefetch;
|
request_dualstack->prefetch = request->prefetch;
|
||||||
request_dualstack->prefetch_expired_domain = request->prefetch_expired_domain;
|
request_dualstack->prefetch_expired_domain = request->prefetch_expired_domain;
|
||||||
_dns_server_request_get(request);
|
_dns_server_request_get(request);
|
||||||
|
|||||||
@@ -63,3 +63,117 @@ cache-persist no)""");
|
|||||||
EXPECT_EQ(client.GetAnswer()[0].GetData(), "b.com.");
|
EXPECT_EQ(client.GetAnswer()[0].GetData(), "b.com.");
|
||||||
EXPECT_EQ(client.GetAnswer()[1].GetData(), "1.2.3.4");
|
EXPECT_EQ(client.GetAnswer()[1].GetData(), "1.2.3.4");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(Cname, subdomain1)
|
||||||
|
{
|
||||||
|
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) {
|
||||||
|
return smartdns::SERVER_REQUEST_SOA;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request->domain == "s.a.com") {
|
||||||
|
smartdns::MockServer::AddIP(request, request->domain.c_str(), "4.5.6.7", 700);
|
||||||
|
return smartdns::SERVER_REQUEST_OK;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
smartdns::MockServer::AddIP(request, request->domain.c_str(), "1.2.3.4", 611);
|
||||||
|
return smartdns::SERVER_REQUEST_OK;
|
||||||
|
});
|
||||||
|
|
||||||
|
server.Start(R"""(bind [::]:60053
|
||||||
|
cname /a.com/s.a.com
|
||||||
|
server 127.0.0.1:61053
|
||||||
|
log-num 0
|
||||||
|
log-console yes
|
||||||
|
log-level debug
|
||||||
|
cache-persist no)""");
|
||||||
|
smartdns::Client client;
|
||||||
|
ASSERT_TRUE(client.Query("a.com", 60053));
|
||||||
|
std::cout << client.GetResult() << std::endl;
|
||||||
|
ASSERT_EQ(client.GetAnswerNum(), 2);
|
||||||
|
EXPECT_EQ(client.GetStatus(), "NOERROR");
|
||||||
|
EXPECT_EQ(client.GetAnswer()[0].GetName(), "a.com");
|
||||||
|
EXPECT_EQ(client.GetAnswer()[0].GetData(), "s.a.com.");
|
||||||
|
EXPECT_EQ(client.GetAnswer()[1].GetData(), "4.5.6.7");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(Cname, subdomain2)
|
||||||
|
{
|
||||||
|
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) {
|
||||||
|
return smartdns::SERVER_REQUEST_SOA;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request->domain == "a.s.a.com") {
|
||||||
|
smartdns::MockServer::AddIP(request, request->domain.c_str(), "4.5.6.7", 700);
|
||||||
|
return smartdns::SERVER_REQUEST_OK;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
smartdns::MockServer::AddIP(request, request->domain.c_str(), "1.2.3.4", 611);
|
||||||
|
return smartdns::SERVER_REQUEST_OK;
|
||||||
|
});
|
||||||
|
|
||||||
|
server.Start(R"""(bind [::]:60053
|
||||||
|
cname /a.com/s.a.com
|
||||||
|
cname /s.a.com/a.s.a.com
|
||||||
|
server 127.0.0.1:61053
|
||||||
|
log-num 0
|
||||||
|
log-console yes
|
||||||
|
log-level debug
|
||||||
|
cache-persist no)""");
|
||||||
|
smartdns::Client client;
|
||||||
|
ASSERT_TRUE(client.Query("a.com", 60053));
|
||||||
|
std::cout << client.GetResult() << std::endl;
|
||||||
|
ASSERT_EQ(client.GetAnswerNum(), 2);
|
||||||
|
EXPECT_EQ(client.GetStatus(), "NOERROR");
|
||||||
|
EXPECT_EQ(client.GetAnswer()[0].GetName(), "a.com");
|
||||||
|
EXPECT_EQ(client.GetAnswer()[0].GetData(), "s.a.com.");
|
||||||
|
EXPECT_EQ(client.GetAnswer()[1].GetData(), "4.5.6.7");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST_F(Cname, loop)
|
||||||
|
{
|
||||||
|
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) {
|
||||||
|
return smartdns::SERVER_REQUEST_SOA;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request->domain == "s.a.com") {
|
||||||
|
smartdns::MockServer::AddIP(request, request->domain.c_str(), "4.5.6.7", 700);
|
||||||
|
return smartdns::SERVER_REQUEST_OK;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
smartdns::MockServer::AddIP(request, request->domain.c_str(), "1.2.3.4", 611);
|
||||||
|
return smartdns::SERVER_REQUEST_OK;
|
||||||
|
});
|
||||||
|
|
||||||
|
server.Start(R"""(bind [::]:60053
|
||||||
|
cname /a.com/c.a.com
|
||||||
|
cname /c.a.com/s.a.com
|
||||||
|
server 127.0.0.1:61053
|
||||||
|
log-num 0
|
||||||
|
log-console yes
|
||||||
|
log-level debug
|
||||||
|
cache-persist no)""");
|
||||||
|
smartdns::Client client;
|
||||||
|
ASSERT_TRUE(client.Query("a.com", 60053));
|
||||||
|
std::cout << client.GetResult() << std::endl;
|
||||||
|
ASSERT_EQ(client.GetAnswerNum(), 2);
|
||||||
|
EXPECT_EQ(client.GetStatus(), "NOERROR");
|
||||||
|
EXPECT_EQ(client.GetAnswer()[0].GetName(), "a.com");
|
||||||
|
EXPECT_EQ(client.GetAnswer()[0].GetData(), "c.a.com.");
|
||||||
|
EXPECT_EQ(client.GetAnswer()[1].GetData(), "4.5.6.7");
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user