cname: fix cname rule loop issue.

This commit is contained in:
Nick Peng
2023-04-17 23:21:41 +08:00
parent 6ca3bfdf36
commit 54d95609bd
3 changed files with 154 additions and 2 deletions

View File

@@ -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;

View File

@@ -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);

View File

@@ -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");
}