Skip to content

Commit

Permalink
dns_conf: ip-alias support ip-set input
Browse files Browse the repository at this point in the history
  • Loading branch information
pymumu committed Nov 2, 2023
1 parent aca8cf9 commit 3d7db2d
Show file tree
Hide file tree
Showing 4 changed files with 147 additions and 38 deletions.
1 change: 1 addition & 0 deletions etc/smartdns/smartdns.conf
Original file line number Diff line number Diff line change
Expand Up @@ -348,3 +348,4 @@ log-level info
# ip-set -name ip-list -file /etc/smartdns/ip-list.conf
# bogus-nxdomain ip-set:ip-list
# ip-alias ip-set:ip-list 1.2.3.4
# ip-alias ip-set:ip-list ip-set:ip-map-list
3 changes: 3 additions & 0 deletions package/openwrt/files/etc/init.d/smartdns
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,7 @@ load_domain_rules()

config_get forwarding_domain_set_file "$section" "forwarding_domain_set_file" ""
[ ! -z "$forwarding_domain_set_file" ] && {
[ ! -e "$forwarding_domain_set_file" ] && touch $forwarding_domain_set_file
conf_append "domain-set" "-name ${domain_set_name}-forwarding-file -file '$forwarding_domain_set_file'"
conf_append "domain-rules" "/domain-set:${domain_set_name}-forwarding-file/ $domain_set_args"
}
Expand All @@ -307,6 +308,7 @@ load_domain_rules()

config_get block_domain_set_file "$section" "block_domain_set_file"
[ ! -z "$block_domain_set_file" ] && {
[ ! -e "$block_domain_set_file" ] && touch $block_domain_set_file
conf_append "domain-set" "-name ${domain_set_name}-block-file -file '$block_domain_set_file'"
conf_append "domain-rules" "/domain-set:${domain_set_name}-block-file/ --address #"
}
Expand Down Expand Up @@ -355,6 +357,7 @@ load_domain_rule_list()
[ ! -z "$addition_flag" ] && domain_set_args="$domain_set_args $addition_flag"
[ -z "$domain_set_args" ] && return

[ ! -e "$domain_list_file" ] && touch $domain_list_file
conf_append "domain-set" "-name domain-rule-list-${domain_set_name} -file '$domain_list_file'"
conf_append "domain-rules" "/domain-set:domain-rule-list-${domain_set_name}/ $domain_set_args"
}
Expand Down
112 changes: 74 additions & 38 deletions src/dns_conf.c
Original file line number Diff line number Diff line change
Expand Up @@ -794,8 +794,8 @@ static int _config_set_rule_each_from_list(const char *file, set_rule_add_func c

fp = fopen(file, "r");
if (fp == NULL) {
tlog(TLOG_WARN, "open file %s error, %s", file, strerror(errno));
return 0;
tlog(TLOG_ERROR, "open file %s error, %s", file, strerror(errno));
return -1;
}

line_no = 0;
Expand Down Expand Up @@ -845,7 +845,9 @@ static int _config_domain_rule_set_each(const char *domain_set, set_rule_add_fun
{
switch (set_name_item->type) {
case DNS_DOMAIN_SET_LIST:
_config_set_rule_each_from_list(set_name_item->file, callback, priv);
if (_config_set_rule_each_from_list(set_name_item->file, callback, priv) != 0) {
return -1;
}
break;
case DNS_DOMAIN_SET_GEOSITE:
break;
Expand Down Expand Up @@ -2858,7 +2860,9 @@ static int _config_ip_rule_set_each(const char *ip_set, set_rule_add_func callba
{
switch (set_name_item->type) {
case DNS_IP_SET_LIST:
_config_set_rule_each_from_list(set_name_item->file, callback, priv);
if (_config_set_rule_each_from_list(set_name_item->file, callback, priv) != 0) {
return -1;
}
break;
default:
tlog(TLOG_WARN, "ip set %s type %d not support.", set_name_list->name, set_name_item->type);
Expand Down Expand Up @@ -3020,10 +3024,58 @@ static int _config_ip_rule_add(const char *ip_cidr, enum ip_rule type, void *rul
return -1;
}

static int _config_ip_rule_alias_add_ip(const char *ip, struct ip_rule_alias *ip_alias)
{
struct sockaddr_storage addr;
socklen_t addr_len = sizeof(addr);
unsigned char *paddr = NULL;
int ret = 0;

ret = getaddr_by_host(ip, (struct sockaddr *)&addr, &addr_len);
if (ret != 0) {
tlog(TLOG_ERROR, "ip is invalid: %s", ip);
goto errout;
}

switch (addr.ss_family) {
case AF_INET: {
struct sockaddr_in *addr_in = NULL;
addr_in = (struct sockaddr_in *)&addr;
paddr = (unsigned char *)&(addr_in->sin_addr.s_addr);
_dns_iplist_ip_address_add(&ip_alias->ip_alias, paddr, DNS_RR_A_LEN);
} break;
case AF_INET6: {
struct sockaddr_in6 *addr_in6 = NULL;
addr_in6 = (struct sockaddr_in6 *)&addr;
if (IN6_IS_ADDR_V4MAPPED(&addr_in6->sin6_addr)) {
paddr = addr_in6->sin6_addr.s6_addr + 12;
_dns_iplist_ip_address_add(&ip_alias->ip_alias, paddr, DNS_RR_A_LEN);
} else {
paddr = addr_in6->sin6_addr.s6_addr;
_dns_iplist_ip_address_add(&ip_alias->ip_alias, paddr, DNS_RR_AAAA_LEN);
}
} break;
default:
goto errout;
break;
}

return 0;

errout:
return -1;
}

static int _config_ip_alias_add_ip_callback(const char *ip_cidr, void *priv)
{
return _config_ip_rule_alias_add_ip(ip_cidr, (struct ip_rule_alias *)priv);
}

static int _config_ip_alias(const char *ip_cidr, const char *ips)
{
struct ip_rule_alias *ip_alias = NULL;
char *target_ips = NULL;
int ret = 0;

if (ip_cidr == NULL || ips == NULL) {
goto errout;
Expand All @@ -3034,43 +3086,21 @@ static int _config_ip_alias(const char *ip_cidr, const char *ips)
goto errout;
}

target_ips = strdup(ips);
if (target_ips == NULL) {
goto errout;
}

for (char *tok = strtok(target_ips, ","); tok != NULL; tok = strtok(NULL, ",")) {
struct sockaddr_storage addr;
socklen_t addr_len = sizeof(addr);
unsigned char *paddr = NULL;
int ret = 0;

ret = getaddr_by_host(tok, (struct sockaddr *)&addr, &addr_len);
if (ret != 0) {
if (strncmp(ips, "ip-set:", sizeof("ip-set:") - 1) == 0) {
if (_config_ip_rule_set_each(ips + sizeof("ip-set:") - 1, _config_ip_alias_add_ip_callback, ip_alias) != 0) {
goto errout;
}
} else {
target_ips = strdup(ips);
if (target_ips == NULL) {
goto errout;
}

switch (addr.ss_family) {
case AF_INET: {
struct sockaddr_in *addr_in = NULL;
addr_in = (struct sockaddr_in *)&addr;
paddr = (unsigned char *)&(addr_in->sin_addr.s_addr);
_dns_iplist_ip_address_add(&ip_alias->ip_alias, paddr, DNS_RR_A_LEN);
} break;
case AF_INET6: {
struct sockaddr_in6 *addr_in6 = NULL;
addr_in6 = (struct sockaddr_in6 *)&addr;
if (IN6_IS_ADDR_V4MAPPED(&addr_in6->sin6_addr)) {
paddr = addr_in6->sin6_addr.s6_addr + 12;
_dns_iplist_ip_address_add(&ip_alias->ip_alias, paddr, DNS_RR_A_LEN);
} else {
paddr = addr_in6->sin6_addr.s6_addr;
_dns_iplist_ip_address_add(&ip_alias->ip_alias, paddr, DNS_RR_AAAA_LEN);
for (char *tok = strtok(target_ips, ","); tok != NULL; tok = strtok(NULL, ",")) {
ret = _config_ip_rule_alias_add_ip(tok, ip_alias);
if (ret != 0) {
goto errout;
}
} break;
default:
goto errout;
break;
}
}

Expand All @@ -3079,7 +3109,9 @@ static int _config_ip_alias(const char *ip_cidr, const char *ips)
}

_dns_ip_rule_put(&ip_alias->head);
free(target_ips);
if (target_ips) {
free(target_ips);
}

return 0;
errout:
Expand Down Expand Up @@ -3302,6 +3334,10 @@ static int _conf_ip_set(void *data, int argc, char *argv[])
if (ip_set) {
free(ip_set);
}

if (ip_set_name_list != NULL) {
free(ip_set_name_list);
}
return -1;
}

Expand Down
69 changes: 69 additions & 0 deletions test/cases/test-ip-rule.cc
Original file line number Diff line number Diff line change
Expand Up @@ -210,3 +210,72 @@ cache-persist no)""");
EXPECT_EQ(client.GetAnswer()[0].GetName(), "a.com");
EXPECT_EQ(client.GetAnswer()[0].GetData(), "7.8.9.10");
}

TEST_F(IPRule, ip_alias_ip_set)
{
smartdns::MockServer server_upstream;
smartdns::MockServer server_upstream2;
smartdns::Server server;
std::string file = "/tmp/smartdns_test_ip_set.list" + smartdns::GenerateRandomString(5);
std::string file_ip = "/tmp/smartdns_test_ip_set_ip.list" + smartdns::GenerateRandomString(5);
std::ofstream ofs(file);
std::ofstream ofs_ip(file_ip);
ASSERT_TRUE(ofs.is_open());
ASSERT_TRUE(ofs_ip.is_open());
Defer
{
ofs.close();
unlink(file.c_str());
ofs_ip.close();
unlink(file_ip.c_str());
};

server_upstream.Start("udp://0.0.0.0:61053", [](struct smartdns::ServerRequestContext *request) {
if (request->qtype != DNS_T_A) {
return smartdns::SERVER_REQUEST_SOA;
}

smartdns::MockServer::AddIP(request, request->domain.c_str(), "1.2.3.4", 611);
smartdns::MockServer::AddIP(request, request->domain.c_str(), "4.5.6.7", 611);
smartdns::MockServer::AddIP(request, request->domain.c_str(), "7.8.9.10", 611);
return smartdns::SERVER_REQUEST_OK;
});

server.MockPing(PING_TYPE_ICMP, "1.2.3.4", 60, 10);
server.MockPing(PING_TYPE_ICMP, "4.5.6.7", 60, 90);
server.MockPing(PING_TYPE_ICMP, "7.8.9.10", 60, 40);

std::string ipset_list = R"""(
1.2.3.0/24
4.5.6.0/24
7.8.9.0/24
)""";
ofs.write(ipset_list.c_str(), ipset_list.length());
ofs.flush();

std::string ipset_list_ip = R"""(
1.1.1.1
)""";
ofs_ip.write(ipset_list_ip.c_str(), ipset_list_ip.length());
ofs_ip.flush();

server.Start(R"""(bind [::]:60053
server udp://127.0.0.1:61053 -blacklist-ip
ip-set -name ip-list -file )""" +
file + R"""(
ip-set -name ip-list-ip -file )""" +
file_ip + R"""(
ip-alias ip-set:ip-list ip-set:ip-list-ip
log-num 0
speed-check-mode none
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(), 1);
EXPECT_EQ(client.GetStatus(), "NOERROR");
EXPECT_EQ(client.GetAnswer()[0].GetName(), "a.com");
EXPECT_EQ(client.GetAnswer()[0].GetData(), "1.1.1.1");
}

0 comments on commit 3d7db2d

Please sign in to comment.