Skip to content

Commit 484251c

Browse files
committed
dns_server: fix DNS64 issue and add group config support for DNS64
1 parent 2234976 commit 484251c

File tree

5 files changed

+128
-27
lines changed

5 files changed

+128
-27
lines changed

etc/smartdns/smartdns.conf

+1-1
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ log-level info
203203

204204
# certificate path
205205
# ca-path [path]
206-
# ca-path /etc/ss/certs
206+
# ca-path /etc/ssl/certs
207207

208208
# remote udp dns server list
209209
# server [IP]:[PORT]|URL [-blacklist-ip] [-whitelist-ip] [-check-edns] [-group [group] ...] [-exclude-default-group]

src/dns_conf.c

+8-5
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,6 @@ static time_t dns_conf_dnsmasq_lease_file_time;
6161
struct dns_hosts_table dns_hosts_table;
6262
int dns_hosts_record_num;
6363

64-
/* DNS64 */
65-
struct dns_dns64 dns_conf_dns_dns64;
66-
6764
/* SRV-HOST */
6865
struct dns_srv_record_table dns_conf_srv_record_table;
6966

@@ -2833,6 +2830,11 @@ static int _config_dns64(void *data, int argc, char *argv[])
28332830

28342831
subnet = argv[1];
28352832

2833+
if (strncmp(subnet, "-", 2U) == 0) {
2834+
memset(&_config_current_rule_group()->dns_dns64, 0, sizeof(struct dns_dns64));
2835+
return 0;
2836+
}
2837+
28362838
p = prefix_pton(subnet, -1, &prefix, &errmsg);
28372839
if (p == NULL) {
28382840
goto errout;
@@ -2848,8 +2850,9 @@ static int _config_dns64(void *data, int argc, char *argv[])
28482850
goto errout;
28492851
}
28502852

2851-
memcpy(&dns_conf_dns_dns64.prefix, &prefix.add.sin6.s6_addr, sizeof(dns_conf_dns_dns64.prefix));
2852-
dns_conf_dns_dns64.prefix_len = prefix.bitlen;
2853+
struct dns_dns64 *dns64 = &(_config_current_rule_group()->dns_dns64);
2854+
memcpy(&dns64->prefix, &prefix.add.sin6.s6_addr, sizeof(dns64->prefix));
2855+
dns64->prefix_len = prefix.bitlen;
28532856

28542857
return 0;
28552858

src/dns_conf.h

+11-7
Original file line numberDiff line numberDiff line change
@@ -448,17 +448,27 @@ struct dns_conf_ipset_nftset {
448448
struct dns_nftset_names nftset_no_speed;
449449
};
450450

451+
struct dns_dns64 {
452+
unsigned char prefix[DNS_RR_AAAA_LEN];
453+
uint32_t prefix_len;
454+
};
455+
451456
struct dns_conf_group {
452457
struct hlist_node node;
453458
struct dns_conf_domain_rule domain_rule;
454459
struct dns_conf_address_rule address_rule;
455460
uint8_t *soa_table;
461+
/* === AUTO COPY FIELD BEGIN === */
456462
char copy_data_section_begin[0];
457463
struct dns_conf_ipset_nftset ipset_nftset;
458464
struct dns_domain_check_orders check_orders;
459465
/* ECS */
460466
struct dns_edns_client_subnet ipv4_ecs;
461467
struct dns_edns_client_subnet ipv6_ecs;
468+
469+
/* DNS64 */
470+
struct dns_dns64 dns_dns64;
471+
462472
int force_AAAA_SOA;
463473
int dualstack_ip_selection;
464474
int dns_dualstack_ip_allow_force_AAAA;
@@ -477,6 +487,7 @@ struct dns_conf_group {
477487
int dns_max_reply_ip_num;
478488
enum response_mode_type dns_response_mode;
479489
char copy_data_section_end[0];
490+
/* === AUTO COPY FIELD END === */
480491
const char *group_name;
481492
};
482493

@@ -616,11 +627,6 @@ struct dns_set_rule_flags_callback_args {
616627
int is_clear_flag;
617628
};
618629

619-
struct dns_dns64 {
620-
unsigned char prefix[DNS_RR_AAAA_LEN];
621-
uint32_t prefix_len;
622-
};
623-
624630
struct dns_srv_record {
625631
struct list_head list;
626632
char host[DNS_MAX_CNAME_LEN];
@@ -640,8 +646,6 @@ struct dns_srv_record_table {
640646
};
641647
extern struct dns_srv_record_table dns_conf_srv_record_table;
642648

643-
extern struct dns_dns64 dns_conf_dns_dns64;
644-
645649
extern struct dns_bind_ip dns_conf_bind_ip[DNS_MAX_BIND_IP];
646650
extern int dns_conf_bind_ip_num;
647651

src/dns_server.c

+26-14
Original file line numberDiff line numberDiff line change
@@ -625,7 +625,7 @@ static int _dns_server_is_dns64_request(struct dns_request *request)
625625
return 0;
626626
}
627627

628-
if (dns_conf_dns_dns64.prefix_len <= 0) {
628+
if (request->conf->dns_dns64.prefix_len <= 0) {
629629
return 0;
630630
}
631631

@@ -4138,6 +4138,9 @@ static int _dns_server_process_answer(struct dns_request *request, const char *d
41384138
case DNS_T_SOA: {
41394139
/* if DNS64 enabled, skip check SOA. */
41404140
if (_dns_server_is_dns64_request(request)) {
4141+
if (request->has_ip) {
4142+
_dns_server_request_complete(request);
4143+
}
41414144
break;
41424145
}
41434146

@@ -4513,7 +4516,7 @@ static void _dns_server_query_end(struct dns_request *request)
45134516
if (request->dualstack_selection_query == 1) {
45144517
if ((conf->ipset_nftset.ipset_no_speed.ipv4_enable || conf->ipset_nftset.nftset_no_speed.ip_enable ||
45154518
conf->ipset_nftset.ipset_no_speed.ipv6_enable || conf->ipset_nftset.nftset_no_speed.ip6_enable) &&
4516-
dns_conf_dns_dns64.prefix_len == 0) {
4519+
request->conf->dns_dns64.prefix_len == 0) {
45174520
/* if speed check fail enabled, we need reply quickly, otherwise wait for ping result.*/
45184521
_dns_server_request_complete(request);
45194522
}
@@ -5961,7 +5964,7 @@ _dns_server_process_dns64_callback(struct dns_request *request, struct dns_reque
59615964
int addr_len = 0;
59625965

59635966
if (request->has_ip == 1) {
5964-
if (memcmp(request->ip_addr, dns_conf_dns_dns64.prefix, 12) != 0) {
5967+
if (memcmp(request->ip_addr, request->conf->dns_dns64.prefix, 12) != 0) {
59655968
return DNS_CHILD_POST_SKIP;
59665969
}
59675970
}
@@ -5976,11 +5979,12 @@ _dns_server_process_dns64_callback(struct dns_request *request, struct dns_reque
59765979
request->ttl_cname = child_request->ttl_cname;
59775980
}
59785981

5979-
if (child_request->has_ip == 0) {
5982+
if (child_request->has_ip == 0 && request->has_ip == 0) {
5983+
request->rcode = child_request->rcode;
59805984
if (child_request->has_soa) {
59815985
memcpy(&request->soa, &child_request->soa, sizeof(struct dns_soa));
59825986
request->has_soa = 1;
5983-
return DNS_CHILD_POST_SUCCESS;
5987+
return DNS_CHILD_POST_SKIP;
59845988
}
59855989

59865990
if (request->has_soa == 0) {
@@ -5990,13 +5994,15 @@ _dns_server_process_dns64_callback(struct dns_request *request, struct dns_reque
59905994
return DNS_CHILD_POST_FAIL;
59915995
}
59925996

5993-
memcpy(request->ip_addr, dns_conf_dns_dns64.prefix, 16);
5994-
memcpy(request->ip_addr + 12, child_request->ip_addr, 4);
5995-
request->ip_ttl = child_request->ip_ttl;
5996-
request->has_ip = 1;
5997-
request->has_soa = 0;
5997+
if (request->has_ip == 0 && child_request->has_ip == 1) {
5998+
request->rcode = child_request->rcode;
5999+
memcpy(request->ip_addr, request->conf->dns_dns64.prefix, 12);
6000+
memcpy(request->ip_addr + 12, child_request->ip_addr, 4);
6001+
request->ip_ttl = child_request->ip_ttl;
6002+
request->has_ip = 1;
6003+
request->has_soa = 0;
6004+
}
59986005

5999-
request->rcode = child_request->rcode;
60006006
pthread_mutex_lock(&request->ip_map_lock);
60016007
hash_for_each_safe(request->ip_map, bucket, tmp, addr_map, node)
60026008
{
@@ -6026,7 +6032,7 @@ _dns_server_process_dns64_callback(struct dns_request *request, struct dns_reque
60266032

60276033
new_addr_map->addr_type = DNS_T_AAAA;
60286034
addr_len = DNS_RR_AAAA_LEN;
6029-
memcpy(new_addr_map->ip_addr, dns_conf_dns_dns64.prefix, 16);
6035+
memcpy(new_addr_map->ip_addr, request->conf->dns_dns64.prefix, 16);
60306036
memcpy(new_addr_map->ip_addr + 12, addr_map->ip_addr, 4);
60316037

60326038
new_addr_map->ping_time = addr_map->ping_time;
@@ -6042,7 +6048,7 @@ _dns_server_process_dns64_callback(struct dns_request *request, struct dns_reque
60426048
return DNS_CHILD_POST_NO_RESPONSE;
60436049
}
60446050

6045-
return DNS_CHILD_POST_SUCCESS;
6051+
return DNS_CHILD_POST_SKIP;
60466052
}
60476053

60486054
static int _dns_server_process_dns64(struct dns_request *request)
@@ -6060,6 +6066,8 @@ static int _dns_server_process_dns64(struct dns_request *request)
60606066
return -1;
60616067
}
60626068

6069+
request->dualstack_selection = 0;
6070+
child_request->prefetch_flags |= PREFETCH_FLAGS_NO_DUALSTACK;
60636071
request->request_wait++;
60646072
int ret = _dns_server_do_query(child_request, 0);
60656073
if (ret != 0) {
@@ -6069,7 +6077,7 @@ static int _dns_server_process_dns64(struct dns_request *request)
60696077
}
60706078

60716079
_dns_server_request_release_complete(child_request, 0);
6072-
return 1;
6080+
return 0;
60736081

60746082
errout:
60756083

@@ -6288,6 +6296,10 @@ static int _dns_server_process_cache(struct dns_request *request)
62886296
goto reply_cache;
62896297
}
62906298

6299+
if (_dns_server_is_dns64_request(request) == 1) {
6300+
goto reply_cache;
6301+
}
6302+
62916303
cache_key.qtype = dualstack_qtype;
62926304
dualstack_dns_cache = dns_cache_lookup(&cache_key);
62936305
if (dualstack_dns_cache == NULL && request->cname[0] != '\0') {

test/cases/test-dns64.cc

+82
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,85 @@ dualstack-ip-selection no
5959
EXPECT_EQ(client.GetAnswer()[0].GetType(), "AAAA");
6060
EXPECT_EQ(client.GetAnswer()[0].GetData(), "64:ff9b::102:304");
6161
}
62+
63+
TEST_F(DNS64, with_dualstack)
64+
{
65+
smartdns::MockServer server_upstream;
66+
smartdns::Server server;
67+
68+
server_upstream.Start("udp://0.0.0.0:61053", [&](struct smartdns::ServerRequestContext *request) {
69+
if (request->qtype == DNS_T_A) {
70+
smartdns::MockServer::AddIP(request, request->domain.c_str(), "1.2.3.4");
71+
return smartdns::SERVER_REQUEST_OK;
72+
}
73+
return smartdns::SERVER_REQUEST_SOA;
74+
});
75+
76+
server.MockPing(PING_TYPE_ICMP, "1.2.3.4", 60, 200);
77+
78+
server.Start(R"""(bind [::]:60053
79+
server 127.0.0.1:61053
80+
dns64 64:ff9b::/96
81+
)""");
82+
smartdns::Client client;
83+
ASSERT_TRUE(client.Query("a.com AAAA", 60053));
84+
std::cout << client.GetResult() << std::endl;
85+
ASSERT_EQ(client.GetAnswerNum(), 1);
86+
EXPECT_EQ(client.GetStatus(), "NOERROR");
87+
EXPECT_EQ(client.GetAnswer()[0].GetName(), "a.com");
88+
EXPECT_EQ(client.GetAnswer()[0].GetTTL(), 3);
89+
EXPECT_EQ(client.GetAnswer()[0].GetType(), "AAAA");
90+
EXPECT_EQ(client.GetAnswer()[0].GetData(), "64:ff9b::102:304");
91+
EXPECT_LT(client.GetQueryTime(), 100);
92+
93+
usleep(500000);
94+
ASSERT_TRUE(client.Query("a.com AAAA", 60053));
95+
std::cout << client.GetResult() << std::endl;
96+
ASSERT_EQ(client.GetAnswerNum(), 1);
97+
EXPECT_EQ(client.GetStatus(), "NOERROR");
98+
EXPECT_EQ(client.GetAnswer()[0].GetName(), "a.com");
99+
EXPECT_GT(client.GetAnswer()[0].GetTTL(), 500);
100+
EXPECT_EQ(client.GetAnswer()[0].GetType(), "AAAA");
101+
EXPECT_EQ(client.GetAnswer()[0].GetData(), "64:ff9b::102:304");
102+
EXPECT_LT(client.GetQueryTime(), 100);
103+
}
104+
105+
106+
TEST_F(DNS64, with_AAAA_result)
107+
{
108+
smartdns::MockServer server_upstream;
109+
smartdns::Server server;
110+
111+
server_upstream.Start("udp://0.0.0.0:61053", [&](struct smartdns::ServerRequestContext *request) {
112+
if (request->qtype == DNS_T_A) {
113+
smartdns::MockServer::AddIP(request, request->domain.c_str(), "1.2.3.4");
114+
return smartdns::SERVER_REQUEST_OK;
115+
}
116+
117+
if (request->qtype == DNS_T_AAAA) {
118+
smartdns::MockServer::AddIP(request, request->domain.c_str(), "2001:db8::1");
119+
smartdns::MockServer::AddIP(request, request->domain.c_str(), "2001:db8::2");
120+
return smartdns::SERVER_REQUEST_OK;
121+
}
122+
return smartdns::SERVER_REQUEST_SOA;
123+
});
124+
125+
server.MockPing(PING_TYPE_ICMP, "1.2.3.4", 60, 300);
126+
server.MockPing(PING_TYPE_ICMP, "2001:db8::1", 60, 90);
127+
server.MockPing(PING_TYPE_ICMP, "2001:db8::2", 60, 100);
128+
129+
server.Start(R"""(bind [::]:60053
130+
server 127.0.0.1:61053
131+
dns64 64:ff9b::/96
132+
)""");
133+
smartdns::Client client;
134+
ASSERT_TRUE(client.Query("a.com AAAA", 60053));
135+
std::cout << client.GetResult() << std::endl;
136+
ASSERT_EQ(client.GetAnswerNum(), 1);
137+
EXPECT_EQ(client.GetStatus(), "NOERROR");
138+
EXPECT_LT(client.GetQueryTime(), 1200);
139+
EXPECT_EQ(client.GetAnswer()[0].GetName(), "a.com");
140+
EXPECT_EQ(client.GetAnswer()[0].GetTTL(), 3);
141+
EXPECT_EQ(client.GetAnswer()[0].GetData(), "2001:db8::1");
142+
}
143+

0 commit comments

Comments
 (0)