Feature: add domain-set option, simplify domain name rule settings
This commit is contained in:
26
ReadMe.md
26
ReadMe.md
@@ -529,6 +529,7 @@ rtt min/avg/max/mdev = 5.954/6.133/6.313/0.195 ms
|
|||||||
| ipset | 域名 ipset | 无 | ipset /domain/[ipset\|-\|#[4\|6]:[ipset\|-][,#[4\|6]:[ipset\|-]]],-表示忽略 | ipset /www.example.com/#4:dns4,#6:- |
|
| ipset | 域名 ipset | 无 | ipset /domain/[ipset\|-\|#[4\|6]:[ipset\|-][,#[4\|6]:[ipset\|-]]],-表示忽略 | ipset /www.example.com/#4:dns4,#6:- |
|
||||||
| ipset-timeout | 设置 ipset 超时功能启用 | 自动 | [yes] | ipset-timeout yes |
|
| ipset-timeout | 设置 ipset 超时功能启用 | 自动 | [yes] | ipset-timeout yes |
|
||||||
| domain-rules | 设置域名规则 | 无 | domain-rules /domain/ [-rules...]<br>[-c\|-speed-check-mode]:测速模式,参考 speed-check-mode 配置<br>[-a\|-address]:参考 address 配置<br>[-n\|-nameserver]:参考 nameserver 配置<br>[-p\|-ipset]:参考ipset配置<br>[-d\|-dualstack-ip-selection]:参考 dualstack-ip-selection | domain-rules /www.example.com/ -speed-check-mode none |
|
| domain-rules | 设置域名规则 | 无 | domain-rules /domain/ [-rules...]<br>[-c\|-speed-check-mode]:测速模式,参考 speed-check-mode 配置<br>[-a\|-address]:参考 address 配置<br>[-n\|-nameserver]:参考 nameserver 配置<br>[-p\|-ipset]:参考ipset配置<br>[-d\|-dualstack-ip-selection]:参考 dualstack-ip-selection | domain-rules /www.example.com/ -speed-check-mode none |
|
||||||
|
| domain-set | 设置域名集合 | 无 | domain-set [options...]<br>[-n\|-name]:域名集合名称 <br>[-t\|-type]:域名集合类型,当前仅支持list,格式为域名列表,一行一个域名。<br>[-f\|-file]:域名集合文件路径。<br> 选项需要配合address, nameserver, ipset等需要指定域名的地方使用,使用方式为 /domain-set:[name]/| domain-set -name set -type list -file /path/to/list <br> address /domain-set:set/1.2.4.8 |
|
||||||
| bogus-nxdomain | 假冒 IP 地址过滤 | 无 | [ip/subnet],可重复 | bogus-nxdomain 1.2.3.4/16 |
|
| bogus-nxdomain | 假冒 IP 地址过滤 | 无 | [ip/subnet],可重复 | bogus-nxdomain 1.2.3.4/16 |
|
||||||
| ignore-ip | 忽略 IP 地址 | 无 | [ip/subnet],可重复 | ignore-ip 1.2.3.4/16 |
|
| ignore-ip | 忽略 IP 地址 | 无 | [ip/subnet],可重复 | ignore-ip 1.2.3.4/16 |
|
||||||
| whitelist-ip | 白名单 IP 地址 | 无 | [ip/subnet],可重复 | whitelist-ip 1.2.3.4/16 |
|
| whitelist-ip | 白名单 IP 地址 | 无 | [ip/subnet],可重复 | whitelist-ip 1.2.3.4/16 |
|
||||||
@@ -697,6 +698,31 @@ rtt min/avg/max/mdev = 5.954/6.133/6.313/0.195 ms
|
|||||||
|
|
||||||
* Windows系统默认使用mDNS解析地址,如需要在windows下用使用smartdns解析,则需要在主机名后面增加`.`,表示使用DNS解析。如`ping smartdns.`
|
* Windows系统默认使用mDNS解析地址,如需要在windows下用使用smartdns解析,则需要在主机名后面增加`.`,表示使用DNS解析。如`ping smartdns.`
|
||||||
|
|
||||||
|
13. 域名集合如何使用?
|
||||||
|
为方便按集合配置域名,对于有/domain/的配置,可以指定域名集合,方便维护。具体方法为:
|
||||||
|
|
||||||
|
* 使用`domain-set`配置集合文件,如
|
||||||
|
|
||||||
|
```sh
|
||||||
|
domain-set -name ad -file /etc/smartdns/ad-list.conf
|
||||||
|
```
|
||||||
|
|
||||||
|
ad-list.conf的格式为一个域名一行,如
|
||||||
|
|
||||||
|
```
|
||||||
|
ad.com
|
||||||
|
site.com
|
||||||
|
```
|
||||||
|
|
||||||
|
* 在有/domain/配置的选项使用域名集合,只需要将`/domain/`配置为`/domain-set:[集合名称]/`即可,如:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
address /domain-set:ad/#
|
||||||
|
domain-rules /domain-set:ad/ -a #
|
||||||
|
nameserver /domain-set:ad/server
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
## 编译
|
## 编译
|
||||||
|
|
||||||
SmartDNS 提供了编译软件包的脚本(`package/build-pkg.sh`),支持编译 LuCI、Debian、OpenWrt 和 Optware 安装包。
|
SmartDNS 提供了编译软件包的脚本(`package/build-pkg.sh`),支持编译 LuCI、Debian、OpenWrt 和 Optware 安装包。
|
||||||
|
|||||||
28
ReadMe_en.md
28
ReadMe_en.md
@@ -487,6 +487,7 @@ Note: Merlin firmware is derived from ASUS firmware and can theoretically be use
|
|||||||
|ipset|Domain IPSet|None|ipset /domain/[ipset\|-\|#[4\|6]:[ipset\|-][,#[4\|6]:[ipset\|-]]], `-` for ignore|ipset /www.example.com/#4:dns4,#6:-
|
|ipset|Domain IPSet|None|ipset /domain/[ipset\|-\|#[4\|6]:[ipset\|-][,#[4\|6]:[ipset\|-]]], `-` for ignore|ipset /www.example.com/#4:dns4,#6:-
|
||||||
|ipset-timeout|ipset timeout enable|auto|[yes]|ipset-timeout yes
|
|ipset-timeout|ipset timeout enable|auto|[yes]|ipset-timeout yes
|
||||||
|domain-rules|set domain rules|None|domain-rules /domain/ [-rules...]<br>`[-c\|-speed-check-mode]`: set speed check mode,same as parameter `speed-check-mode`<br>`[-a\|-address]`: same as parameter `address` <br>`[-n\|-nameserver]`: same as parameter `nameserver`<br>`[-p\|-ipset]`: same as parameter `ipset`<br>`[-d\|-dualstack-ip-selection]`: same as parameter `dualstack-ip-selection`|domain-rules /www.example.com/ -speed-check-mode none
|
|domain-rules|set domain rules|None|domain-rules /domain/ [-rules...]<br>`[-c\|-speed-check-mode]`: set speed check mode,same as parameter `speed-check-mode`<br>`[-a\|-address]`: same as parameter `address` <br>`[-n\|-nameserver]`: same as parameter `nameserver`<br>`[-p\|-ipset]`: same as parameter `ipset`<br>`[-d\|-dualstack-ip-selection]`: same as parameter `dualstack-ip-selection`|domain-rules /www.example.com/ -speed-check-mode none
|
||||||
|
| domain-set | collection of domains|None| domain-set [options...]<br>[-n\|-name]:name of set <br>[-t\|-type] [list]: set type, only support list, one domain per line <br>[-f\|-file]:file path of domain set<br> used with address, nameserver, ipset, example: /domain-set:[name]/ | domain-set -name set -type list -file /path/to/list <br> address /domain-set:set/1.2.4.8 |
|
||||||
|bogus-nxdomain|bogus IP address|None|[IP/subnet], Repeatable| bogus-nxdomain 1.2.3.4/16
|
|bogus-nxdomain|bogus IP address|None|[IP/subnet], Repeatable| bogus-nxdomain 1.2.3.4/16
|
||||||
|ignore-ip|ignore ip address|None|[ip/subnet], Repeatable| ignore-ip 1.2.3.4/16
|
|ignore-ip|ignore ip address|None|[ip/subnet], Repeatable| ignore-ip 1.2.3.4/16
|
||||||
|whitelist-ip|ip whitelist|None|[ip/subnet], Repeatable,When the filtering server responds IPs in the IP whitelist, only result in whitelist will be accepted| whitelist-ip 1.2.3.4/16
|
|whitelist-ip|ip whitelist|None|[ip/subnet], Repeatable,When the filtering server responds IPs in the IP whitelist, only result in whitelist will be accepted| whitelist-ip 1.2.3.4/16
|
||||||
@@ -632,12 +633,37 @@ Note: Merlin firmware is derived from ASUS firmware and can theoretically be use
|
|||||||
|
|
||||||
```sh
|
```sh
|
||||||
dnsmasq-lease-file /var/lib/misc/dnsmasq.leases
|
dnsmasq-lease-file /var/lib/misc/dnsmasq.leases
|
||||||
````\
|
```
|
||||||
|
|
||||||
After the configuration is complete, you can directly use the host name to connect to the local machine. But need to pay attention:
|
After the configuration is complete, you can directly use the host name to connect to the local machine. But need to pay attention:
|
||||||
|
|
||||||
* Windows system uses mDNS to resolve addresses by default. If you need to use smartdns to resolve addresses under Windows, you need to add `.` after the host name, indicating that DNS resolution is used. Such as `ping smartdns.`
|
* Windows system uses mDNS to resolve addresses by default. If you need to use smartdns to resolve addresses under Windows, you need to add `.` after the host name, indicating that DNS resolution is used. Such as `ping smartdns.`
|
||||||
|
|
||||||
|
1. How to use the domain set?
|
||||||
|
To facilitate configuring domain names by set, for configurations with /domain/, you can specify a domain name set for easy maintenance. The specific method is:
|
||||||
|
|
||||||
|
* Use `domain-set` configuration domain set file:
|
||||||
|
|
||||||
|
````sh
|
||||||
|
domain-set -name ad -file /etc/smartdns/ad-list.conf
|
||||||
|
````
|
||||||
|
|
||||||
|
The format of ad-list.conf is one domain per line:
|
||||||
|
|
||||||
|
````
|
||||||
|
ad.com
|
||||||
|
site.com
|
||||||
|
````
|
||||||
|
|
||||||
|
* To use the domain set, you only need to configure `/domain/` to `/domain-set:[collection name]/`, such as:
|
||||||
|
|
||||||
|
````sh
|
||||||
|
address /domain-set:ad/#
|
||||||
|
domain-rules /domain-set:ad/ -a #
|
||||||
|
nameserver /domain-set:ad/server
|
||||||
|
...
|
||||||
|
````
|
||||||
|
|
||||||
## Compile
|
## Compile
|
||||||
|
|
||||||
smartdns contains scripts for compiling packages, supports compiling luci, debian, openwrt, opare installation packages, and can execute `package/build-pkg.sh` compilation.
|
smartdns contains scripts for compiling packages, supports compiling luci, debian, openwrt, opare installation packages, and can execute `package/build-pkg.sh` compilation.
|
||||||
|
|||||||
@@ -219,3 +219,17 @@ log-level info
|
|||||||
# [-n] -nameserver [group|-]: same as nameserver option
|
# [-n] -nameserver [group|-]: same as nameserver option
|
||||||
# [-p] -ipset [ipset|-]: same as ipset option
|
# [-p] -ipset [ipset|-]: same as ipset option
|
||||||
# [-d] -dualstack-ip-selection [yes|no]: same as dualstack-ip-selection option
|
# [-d] -dualstack-ip-selection [yes|no]: same as dualstack-ip-selection option
|
||||||
|
|
||||||
|
# collection of domains
|
||||||
|
# the domain-set can be used with /domain/ for address, nameserver, ipset, etc.
|
||||||
|
# domain-set -name [set-name] -type list -file [/path/to/file]
|
||||||
|
# [-n] -name [set name]: domain set name
|
||||||
|
# [-t] -type [list]: domain set type, list only now
|
||||||
|
# [-f] -file [path/to/set]: file path of domain set
|
||||||
|
#
|
||||||
|
# example:
|
||||||
|
# domain-set -name domain-list -type list -file /etc/smartdns/domain-list.conf
|
||||||
|
# address /domain-set:domain-list/1.2.3.4
|
||||||
|
# nameserver /domain-set:domain-list/server-group
|
||||||
|
# ipset /domain-set:domain-list/ipset
|
||||||
|
# domain-rules /domain-set:domain-list/ -speed-check-mode ping
|
||||||
|
|||||||
421
src/dns_conf.c
421
src/dns_conf.c
@@ -42,6 +42,9 @@ static struct dns_ipset_table dns_ipset_table;
|
|||||||
|
|
||||||
struct dns_qtype_soa_table dns_qtype_soa_table;
|
struct dns_qtype_soa_table dns_qtype_soa_table;
|
||||||
|
|
||||||
|
struct dns_domain_set_rule_table dns_domain_set_rule_table;
|
||||||
|
struct dns_domain_set_name_table dns_domain_set_name_table;
|
||||||
|
|
||||||
/* dns groups */
|
/* dns groups */
|
||||||
struct dns_group_table dns_group_table;
|
struct dns_group_table dns_group_table;
|
||||||
|
|
||||||
@@ -142,6 +145,62 @@ 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 void *_new_dns_rule(enum domain_rule domain_rule)
|
||||||
|
{
|
||||||
|
struct dns_rule *rule;
|
||||||
|
int size = 0;
|
||||||
|
|
||||||
|
if (domain_rule >= DOMAIN_RULE_MAX) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (domain_rule) {
|
||||||
|
case DOMAIN_RULE_FLAGS:
|
||||||
|
size = sizeof(struct dns_rule_flags);
|
||||||
|
break;
|
||||||
|
case DOMAIN_RULE_ADDRESS_IPV4:
|
||||||
|
size = sizeof(struct dns_rule_address_IPV4);
|
||||||
|
break;
|
||||||
|
case DOMAIN_RULE_ADDRESS_IPV6:
|
||||||
|
size = sizeof(struct dns_rule_address_IPV6);
|
||||||
|
break;
|
||||||
|
case DOMAIN_RULE_IPSET:
|
||||||
|
case DOMAIN_RULE_IPSET_IPV4:
|
||||||
|
case DOMAIN_RULE_IPSET_IPV6:
|
||||||
|
size = sizeof(struct dns_ipset_rule);
|
||||||
|
break;
|
||||||
|
case DOMAIN_RULE_NAMESERVER:
|
||||||
|
size = sizeof(struct dns_nameserver_rule);
|
||||||
|
break;
|
||||||
|
case DOMAIN_RULE_CHECKSPEED:
|
||||||
|
size = sizeof(struct dns_domain_check_orders);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
rule = malloc(size);
|
||||||
|
if (!rule) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
memset(rule, 0, size);
|
||||||
|
rule->rule = domain_rule;
|
||||||
|
atomic_set(&rule->refcnt, 1);
|
||||||
|
return rule;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _dns_rule_get(struct dns_rule *rule)
|
||||||
|
{
|
||||||
|
atomic_inc(&rule->refcnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _dns_rule_put(struct dns_rule *rule)
|
||||||
|
{
|
||||||
|
if (atomic_dec_and_test(&rule->refcnt)) {
|
||||||
|
free(rule);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int _get_domain(char *value, char *domain, int max_dmain_size, char **ptr_after_domain)
|
static int _get_domain(char *value, char *domain, int max_dmain_size, char **ptr_after_domain)
|
||||||
{
|
{
|
||||||
char *begin = NULL;
|
char *begin = NULL;
|
||||||
@@ -431,7 +490,8 @@ static int _config_domain_iter_free(void *data, const unsigned char *key, uint32
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(domain_rule->rules[i]);
|
_dns_rule_put(domain_rule->rules[i]);
|
||||||
|
domain_rule->rules[i] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(domain_rule);
|
free(domain_rule);
|
||||||
@@ -458,6 +518,69 @@ static void _config_address_destroy(radix_node_t *node, void *cbctx)
|
|||||||
node->data = NULL;
|
node->data = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int _config_domain_set_rule_add_ext(char *set_name, enum domain_rule type, void *rule, unsigned int flags, int is_clear_flag)
|
||||||
|
{
|
||||||
|
struct dns_domain_set_rule *set_rule = NULL;
|
||||||
|
struct dns_domain_set_rule_list *set_rule_list = NULL;
|
||||||
|
uint32_t key = 0;
|
||||||
|
|
||||||
|
if (set_name == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
set_rule = malloc(sizeof(struct dns_domain_set_rule));
|
||||||
|
if (set_rule == NULL) {
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
memset(set_rule, 0, sizeof(struct dns_domain_set_rule));
|
||||||
|
|
||||||
|
set_rule->type = type;
|
||||||
|
set_rule->rule = rule;
|
||||||
|
set_rule->flags = flags;
|
||||||
|
set_rule->is_clear_flag = is_clear_flag;
|
||||||
|
|
||||||
|
if (rule) {
|
||||||
|
_dns_rule_get(rule);
|
||||||
|
}
|
||||||
|
|
||||||
|
key = hash_string(set_name);
|
||||||
|
hash_for_each_possible(dns_domain_set_rule_table.rule_list, set_rule_list, node, key)
|
||||||
|
{
|
||||||
|
if (strncmp(set_rule_list->domain_set, set_name, DNS_MAX_CNAME_LEN) == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (set_rule_list == NULL) {
|
||||||
|
set_rule_list = malloc(sizeof(struct dns_domain_set_rule_list));
|
||||||
|
if (set_rule_list == NULL) {
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
memset(set_rule_list, 0, sizeof(struct dns_domain_set_rule_list));
|
||||||
|
INIT_LIST_HEAD(&set_rule_list->domain_ruls_list);
|
||||||
|
safe_strncpy(set_rule_list->domain_set, set_name, DNS_MAX_CNAME_LEN);
|
||||||
|
hash_add(dns_domain_set_rule_table.rule_list, &set_rule_list->node, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
list_add_tail(&set_rule->list, &set_rule_list->domain_ruls_list);
|
||||||
|
return 0;
|
||||||
|
errout:
|
||||||
|
if (set_rule) {
|
||||||
|
free(set_rule);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _config_domian_set_rule_flags(char *set_name, unsigned int flags, int is_clear_flag)
|
||||||
|
{
|
||||||
|
return _config_domain_set_rule_add_ext(set_name, DOMAIN_RULE_FLAGS, NULL, flags, is_clear_flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _config_domain_set_rule_add(char *set_name, enum domain_rule type, void *rule)
|
||||||
|
{
|
||||||
|
return _config_domain_set_rule_add_ext(set_name, type, rule, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
static int _config_domain_rule_add(char *domain, enum domain_rule type, void *rule)
|
static int _config_domain_rule_add(char *domain, enum domain_rule type, void *rule)
|
||||||
{
|
{
|
||||||
struct dns_domain_rule *domain_rule = NULL;
|
struct dns_domain_rule *domain_rule = NULL;
|
||||||
@@ -473,6 +596,11 @@ static int _config_domain_rule_add(char *domain, enum domain_rule type, void *ru
|
|||||||
tlog(TLOG_ERROR, "domain name %s too long", domain);
|
tlog(TLOG_ERROR, "domain name %s too long", domain);
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (strncmp(domain, "domain-set:", sizeof("domain-set:") - 1) == 0) {
|
||||||
|
return _config_domain_set_rule_add(domain + sizeof("domain-set:") - 1, type, rule);
|
||||||
|
}
|
||||||
|
|
||||||
reverse_string(domain_key, domain, len, 1);
|
reverse_string(domain_key, domain, len, 1);
|
||||||
domain_key[len] = '.';
|
domain_key[len] = '.';
|
||||||
len++;
|
len++;
|
||||||
@@ -495,11 +623,12 @@ static int _config_domain_rule_add(char *domain, enum domain_rule type, void *ru
|
|||||||
|
|
||||||
/* add new rule to domain */
|
/* add new rule to domain */
|
||||||
if (domain_rule->rules[type]) {
|
if (domain_rule->rules[type]) {
|
||||||
free(domain_rule->rules[type]);
|
_dns_rule_put(domain_rule->rules[type]);
|
||||||
domain_rule->rules[type] = NULL;
|
domain_rule->rules[type] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
domain_rule->rules[type] = rule;
|
domain_rule->rules[type] = rule;
|
||||||
|
_dns_rule_get(rule);
|
||||||
|
|
||||||
/* update domain rule */
|
/* update domain rule */
|
||||||
if (add_domain_rule) {
|
if (add_domain_rule) {
|
||||||
@@ -529,6 +658,10 @@ static int _config_domain_rule_flag_set(char *domain, unsigned int flag, unsigne
|
|||||||
char domain_key[DNS_MAX_CONF_CNAME_LEN];
|
char domain_key[DNS_MAX_CONF_CNAME_LEN];
|
||||||
int len = 0;
|
int len = 0;
|
||||||
|
|
||||||
|
if (strncmp(domain, "domain-set:", sizeof("domain-set:") - 1) == 0) {
|
||||||
|
return _config_domian_set_rule_flags(domain + sizeof("domain-set:") - 1, flag, is_clear);
|
||||||
|
}
|
||||||
|
|
||||||
len = strlen(domain);
|
len = strlen(domain);
|
||||||
if (len >= (int)sizeof(domain_key)) {
|
if (len >= (int)sizeof(domain_key)) {
|
||||||
tlog(TLOG_ERROR, "domain %s too long", domain);
|
tlog(TLOG_ERROR, "domain %s too long", domain);
|
||||||
@@ -552,13 +685,12 @@ static int _config_domain_rule_flag_set(char *domain, unsigned int flag, unsigne
|
|||||||
|
|
||||||
/* add new rule to domain */
|
/* add new rule to domain */
|
||||||
if (domain_rule->rules[DOMAIN_RULE_FLAGS] == NULL) {
|
if (domain_rule->rules[DOMAIN_RULE_FLAGS] == NULL) {
|
||||||
rule_flags = malloc(sizeof(*rule_flags));
|
rule_flags = _new_dns_rule(DOMAIN_RULE_FLAGS);
|
||||||
memset(rule_flags, 0, sizeof(*rule_flags));
|
|
||||||
rule_flags->flags = 0;
|
rule_flags->flags = 0;
|
||||||
domain_rule->rules[DOMAIN_RULE_FLAGS] = rule_flags;
|
domain_rule->rules[DOMAIN_RULE_FLAGS] = (struct dns_rule *)rule_flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
rule_flags = domain_rule->rules[DOMAIN_RULE_FLAGS];
|
rule_flags = (struct dns_rule_flags *)domain_rule->rules[DOMAIN_RULE_FLAGS];
|
||||||
if (is_clear == false) {
|
if (is_clear == false) {
|
||||||
rule_flags->flags |= flag;
|
rule_flags->flags |= flag;
|
||||||
} else {
|
} else {
|
||||||
@@ -670,7 +802,7 @@ static int _conf_domain_rule_ipset(char *domain, const char *ipsetname)
|
|||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
ipset_rule = malloc(sizeof(*ipset_rule));
|
ipset_rule = _new_dns_rule(type);
|
||||||
if (ipset_rule == NULL) {
|
if (ipset_rule == NULL) {
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
@@ -680,6 +812,7 @@ static int _conf_domain_rule_ipset(char *domain, const char *ipsetname)
|
|||||||
if (_config_domain_rule_add(domain, type, ipset_rule) != 0) {
|
if (_config_domain_rule_add(domain, type, ipset_rule) != 0) {
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
_dns_rule_put(&ipset_rule->head);
|
||||||
}
|
}
|
||||||
|
|
||||||
goto clear;
|
goto clear;
|
||||||
@@ -688,7 +821,7 @@ errout:
|
|||||||
tlog(TLOG_ERROR, "add ipset %s failed", ipsetname);
|
tlog(TLOG_ERROR, "add ipset %s failed", ipsetname);
|
||||||
|
|
||||||
if (ipset_rule) {
|
if (ipset_rule) {
|
||||||
free(ipset_rule);
|
_dns_rule_put(&ipset_rule->head);
|
||||||
}
|
}
|
||||||
|
|
||||||
clear:
|
clear:
|
||||||
@@ -720,9 +853,9 @@ errout:
|
|||||||
|
|
||||||
static int _conf_domain_rule_address(char *domain, const char *domain_address)
|
static int _conf_domain_rule_address(char *domain, const char *domain_address)
|
||||||
{
|
{
|
||||||
struct dns_address_IPV4 *address_ipv4 = NULL;
|
struct dns_rule_address_IPV4 *address_ipv4 = NULL;
|
||||||
struct dns_address_IPV6 *address_ipv6 = NULL;
|
struct dns_rule_address_IPV6 *address_ipv6 = NULL;
|
||||||
void *address = NULL;
|
struct dns_rule *address = NULL;
|
||||||
char ip[MAX_IP_LEN];
|
char ip[MAX_IP_LEN];
|
||||||
int port = 0;
|
int port = 0;
|
||||||
struct sockaddr_storage addr;
|
struct sockaddr_storage addr;
|
||||||
@@ -777,7 +910,7 @@ static int _conf_domain_rule_address(char *domain, const char *domain_address)
|
|||||||
switch (addr.ss_family) {
|
switch (addr.ss_family) {
|
||||||
case AF_INET: {
|
case AF_INET: {
|
||||||
struct sockaddr_in *addr_in = NULL;
|
struct sockaddr_in *addr_in = NULL;
|
||||||
address_ipv4 = malloc(sizeof(*address_ipv4));
|
address_ipv4 = _new_dns_rule(DOMAIN_RULE_ADDRESS_IPV4);
|
||||||
if (address_ipv4 == NULL) {
|
if (address_ipv4 == NULL) {
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
@@ -785,27 +918,27 @@ static int _conf_domain_rule_address(char *domain, const char *domain_address)
|
|||||||
addr_in = (struct sockaddr_in *)&addr;
|
addr_in = (struct sockaddr_in *)&addr;
|
||||||
memcpy(address_ipv4->ipv4_addr, &addr_in->sin_addr.s_addr, 4);
|
memcpy(address_ipv4->ipv4_addr, &addr_in->sin_addr.s_addr, 4);
|
||||||
type = DOMAIN_RULE_ADDRESS_IPV4;
|
type = DOMAIN_RULE_ADDRESS_IPV4;
|
||||||
address = address_ipv4;
|
address = (struct dns_rule *)address_ipv4;
|
||||||
} break;
|
} break;
|
||||||
case AF_INET6: {
|
case AF_INET6: {
|
||||||
struct sockaddr_in6 *addr_in6 = NULL;
|
struct sockaddr_in6 *addr_in6 = NULL;
|
||||||
addr_in6 = (struct sockaddr_in6 *)&addr;
|
addr_in6 = (struct sockaddr_in6 *)&addr;
|
||||||
if (IN6_IS_ADDR_V4MAPPED(&addr_in6->sin6_addr)) {
|
if (IN6_IS_ADDR_V4MAPPED(&addr_in6->sin6_addr)) {
|
||||||
address_ipv4 = malloc(sizeof(*address_ipv4));
|
address_ipv4 = _new_dns_rule(DOMAIN_RULE_ADDRESS_IPV4);
|
||||||
if (address_ipv4 == NULL) {
|
if (address_ipv4 == NULL) {
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
memcpy(address_ipv4->ipv4_addr, addr_in6->sin6_addr.s6_addr + 12, 4);
|
memcpy(address_ipv4->ipv4_addr, addr_in6->sin6_addr.s6_addr + 12, 4);
|
||||||
type = DOMAIN_RULE_ADDRESS_IPV4;
|
type = DOMAIN_RULE_ADDRESS_IPV4;
|
||||||
address = address_ipv4;
|
address = (struct dns_rule *)address_ipv4;
|
||||||
} else {
|
} else {
|
||||||
address_ipv6 = malloc(sizeof(*address_ipv6));
|
address_ipv6 = _new_dns_rule(DOMAIN_RULE_ADDRESS_IPV6);
|
||||||
if (address_ipv6 == NULL) {
|
if (address_ipv6 == NULL) {
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
memcpy(address_ipv6->ipv6_addr, addr_in6->sin6_addr.s6_addr, 16);
|
memcpy(address_ipv6->ipv6_addr, addr_in6->sin6_addr.s6_addr, 16);
|
||||||
type = DOMAIN_RULE_ADDRESS_IPV6;
|
type = DOMAIN_RULE_ADDRESS_IPV6;
|
||||||
address = address_ipv6;
|
address = (struct dns_rule *)address_ipv6;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
default:
|
default:
|
||||||
@@ -818,10 +951,11 @@ static int _conf_domain_rule_address(char *domain, const char *domain_address)
|
|||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_dns_rule_put(address);
|
||||||
return 0;
|
return 0;
|
||||||
errout:
|
errout:
|
||||||
if (address) {
|
if (address) {
|
||||||
free(address);
|
_dns_rule_put(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
tlog(TLOG_ERROR, "add address %s, %s failed", domain, domain_address);
|
tlog(TLOG_ERROR, "add address %s, %s failed", domain, domain_address);
|
||||||
@@ -857,7 +991,6 @@ static int _config_speed_check_mode_parser(struct dns_domain_check_orders *check
|
|||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
safe_strncpy(tmpbuff, mode, DNS_MAX_OPT_LEN);
|
safe_strncpy(tmpbuff, mode, DNS_MAX_OPT_LEN);
|
||||||
memset(check_orders, 0, sizeof(*check_orders));
|
|
||||||
|
|
||||||
ptr = tmpbuff;
|
ptr = tmpbuff;
|
||||||
do {
|
do {
|
||||||
@@ -1088,7 +1221,7 @@ static int _conf_domain_rule_nameserver(char *domain, const char *group_name)
|
|||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
nameserver_rule = malloc(sizeof(*nameserver_rule));
|
nameserver_rule = _new_dns_rule(DOMAIN_RULE_NAMESERVER);
|
||||||
if (nameserver_rule == NULL) {
|
if (nameserver_rule == NULL) {
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
@@ -1107,10 +1240,12 @@ static int _conf_domain_rule_nameserver(char *domain, const char *group_name)
|
|||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_dns_rule_put(&nameserver_rule->head);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
errout:
|
errout:
|
||||||
if (nameserver_rule) {
|
if (nameserver_rule) {
|
||||||
free(nameserver_rule);
|
_dns_rule_put(&nameserver_rule->head);
|
||||||
}
|
}
|
||||||
|
|
||||||
tlog(TLOG_ERROR, "add nameserver %s, %s failed", domain, group_name);
|
tlog(TLOG_ERROR, "add nameserver %s, %s failed", domain, group_name);
|
||||||
@@ -1265,6 +1400,50 @@ static void _config_qtype_soa_table_destroy(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _config_domain_set_name_table_destroy(void)
|
||||||
|
{
|
||||||
|
struct dns_domain_set_name_list *set_name_list = NULL;
|
||||||
|
struct hlist_node *tmp = NULL;
|
||||||
|
struct dns_domain_set_name *set_name = NULL;
|
||||||
|
struct dns_domain_set_name *tmp1 = NULL;
|
||||||
|
unsigned long i = 0;
|
||||||
|
|
||||||
|
hash_for_each_safe(dns_domain_set_name_table.names, i, tmp, set_name_list, node)
|
||||||
|
{
|
||||||
|
hlist_del_init(&set_name_list->node);
|
||||||
|
list_for_each_entry_safe(set_name, tmp1, &set_name_list->set_name_list, list)
|
||||||
|
{
|
||||||
|
list_del(&set_name->list);
|
||||||
|
free(set_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(set_name_list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _config_domain_set_rule_table_destroy(void)
|
||||||
|
{
|
||||||
|
struct dns_domain_set_rule_list *set_rule_list = NULL;
|
||||||
|
struct hlist_node *tmp = NULL;
|
||||||
|
struct dns_domain_set_rule *set_rule = NULL;
|
||||||
|
struct dns_domain_set_rule *tmp1 = NULL;
|
||||||
|
unsigned long i = 0;
|
||||||
|
|
||||||
|
hash_for_each_safe(dns_domain_set_rule_table.rule_list, i, tmp, set_rule_list, node)
|
||||||
|
{
|
||||||
|
hlist_del_init(&set_rule_list->node);
|
||||||
|
list_for_each_entry_safe(set_rule, tmp1, &set_rule_list->domain_ruls_list, list)
|
||||||
|
{
|
||||||
|
list_del(&set_rule->list);
|
||||||
|
if (set_rule->rule) {
|
||||||
|
_dns_rule_put(set_rule->rule);
|
||||||
|
}
|
||||||
|
free(set_rule);
|
||||||
|
}
|
||||||
|
free(set_rule_list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int _config_blacklist_ip(void *data, int argc, char *argv[])
|
static int _config_blacklist_ip(void *data, int argc, char *argv[])
|
||||||
{
|
{
|
||||||
if (argc <= 1) {
|
if (argc <= 1) {
|
||||||
@@ -1355,11 +1534,10 @@ static int _conf_domain_rule_speed_check(char *domain, const char *mode)
|
|||||||
{
|
{
|
||||||
struct dns_domain_check_orders *check_orders = NULL;
|
struct dns_domain_check_orders *check_orders = NULL;
|
||||||
|
|
||||||
check_orders = malloc(sizeof(*check_orders) * DOMAIN_CHECK_NUM);
|
check_orders = _new_dns_rule(DOMAIN_RULE_CHECKSPEED);
|
||||||
if (check_orders == NULL) {
|
if (check_orders == NULL) {
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
memset(check_orders, 0, sizeof(*check_orders));
|
|
||||||
|
|
||||||
if (_config_speed_check_mode_parser(check_orders, mode) != 0) {
|
if (_config_speed_check_mode_parser(check_orders, mode) != 0) {
|
||||||
goto errout;
|
goto errout;
|
||||||
@@ -1369,14 +1547,111 @@ static int _conf_domain_rule_speed_check(char *domain, const char *mode)
|
|||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_dns_rule_put(&check_orders->head);
|
||||||
return 0;
|
return 0;
|
||||||
errout:
|
errout:
|
||||||
if (check_orders) {
|
if (check_orders) {
|
||||||
free(check_orders);
|
_dns_rule_put(&check_orders->head);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int _conf_domain_set(void *data, int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int opt = 0;
|
||||||
|
uint32_t key = 0;
|
||||||
|
struct dns_domain_set_name *domain_set = NULL;
|
||||||
|
struct dns_domain_set_name_list *domain_set_name_list = NULL;
|
||||||
|
char set_name[DNS_MAX_CNAME_LEN] = {0};
|
||||||
|
|
||||||
|
/* clang-format off */
|
||||||
|
static struct option long_options[] = {
|
||||||
|
{"name", required_argument, NULL, 'n'},
|
||||||
|
{"type", required_argument, NULL, 't'},
|
||||||
|
{"file", required_argument, NULL, 'f'},
|
||||||
|
{NULL, 0, NULL, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (argc <= 1) {
|
||||||
|
tlog(TLOG_ERROR, "invalid parameter.");
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
domain_set = malloc(sizeof(*domain_set));
|
||||||
|
if (domain_set == NULL) {
|
||||||
|
tlog(TLOG_ERROR, "cannot malloc memory.");
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
memset(domain_set, 0, sizeof(*domain_set));
|
||||||
|
INIT_LIST_HEAD(&domain_set->list);
|
||||||
|
|
||||||
|
optind = 1;
|
||||||
|
while (1) {
|
||||||
|
opt = getopt_long_only(argc, argv, "n:t:f:", long_options, NULL);
|
||||||
|
if (opt == -1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (opt) {
|
||||||
|
case 'n':
|
||||||
|
safe_strncpy(set_name, optarg, DNS_MAX_CNAME_LEN);
|
||||||
|
break;
|
||||||
|
case 't': {
|
||||||
|
const char *type = optarg;
|
||||||
|
if (strncmp(type, "list", 5) == 0) {
|
||||||
|
domain_set->type = DNS_DOMAIN_SET_LIST;
|
||||||
|
} else if (strncmp(type, "geosite", 7) == 0) {
|
||||||
|
domain_set->type = DNS_DOMAIN_SET_GEOSITE;
|
||||||
|
} else {
|
||||||
|
tlog(TLOG_ERROR, "invalid domain set type.");
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'f':
|
||||||
|
conf_get_conf_fullpath(optarg, domain_set->file, DNS_MAX_PATH);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* clang-format on */
|
||||||
|
|
||||||
|
if (set_name[0] == 0 || domain_set->file[0] == 0) {
|
||||||
|
tlog(TLOG_ERROR, "invalid parameter.");
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
key = hash_string(set_name);
|
||||||
|
hash_for_each_possible(dns_domain_set_name_table.names, domain_set_name_list, node, key)
|
||||||
|
{
|
||||||
|
if (strcmp(domain_set_name_list->name, set_name) == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (domain_set_name_list == NULL) {
|
||||||
|
domain_set_name_list = malloc(sizeof(*domain_set_name_list));
|
||||||
|
if (domain_set_name_list == NULL) {
|
||||||
|
tlog(TLOG_ERROR, "cannot malloc memory.");
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
memset(domain_set_name_list, 0, sizeof(*domain_set_name_list));
|
||||||
|
INIT_LIST_HEAD(&domain_set_name_list->set_name_list);
|
||||||
|
safe_strncpy(domain_set_name_list->name, set_name, DNS_MAX_CNAME_LEN);
|
||||||
|
hash_add(dns_domain_set_name_table.names, &domain_set_name_list->node, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
list_add_tail(&domain_set->list, &domain_set_name_list->set_name_list);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
errout:
|
||||||
|
if (domain_set) {
|
||||||
|
free(domain_set);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
static int _conf_domain_rules(void *data, int argc, char *argv[])
|
static int _conf_domain_rules(void *data, int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int opt = 0;
|
int opt = 0;
|
||||||
@@ -1922,6 +2197,7 @@ static struct config_item _config_item[] = {
|
|||||||
CONF_CUSTOM("ignore-ip", _conf_ip_ignore, NULL),
|
CONF_CUSTOM("ignore-ip", _conf_ip_ignore, NULL),
|
||||||
CONF_CUSTOM("edns-client-subnet", _conf_edns_client_subnet, NULL),
|
CONF_CUSTOM("edns-client-subnet", _conf_edns_client_subnet, NULL),
|
||||||
CONF_CUSTOM("domain-rules", _conf_domain_rules, NULL),
|
CONF_CUSTOM("domain-rules", _conf_domain_rules, NULL),
|
||||||
|
CONF_CUSTOM("domain-set", _conf_domain_set, NULL),
|
||||||
CONF_CUSTOM("dnsmasq-lease-file", _conf_dhcp_lease_dnsmasq_file, NULL),
|
CONF_CUSTOM("dnsmasq-lease-file", _conf_dhcp_lease_dnsmasq_file, NULL),
|
||||||
CONF_CUSTOM("hosts-file", _conf_hosts_file, NULL),
|
CONF_CUSTOM("hosts-file", _conf_hosts_file, NULL),
|
||||||
CONF_STRING("ca-file", (char *)&dns_conf_ca_file, DNS_MAX_PATH),
|
CONF_STRING("ca-file", (char *)&dns_conf_ca_file, DNS_MAX_PATH),
|
||||||
@@ -1987,6 +2263,96 @@ int config_addtional_file(void *data, int argc, char *argv[])
|
|||||||
return load_conf(file_path, _config_item, _conf_printf);
|
return load_conf(file_path, _config_item, _conf_printf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int _update_domain_set_from_list(const char *file, struct dns_domain_set_rule_list *set_rule_list)
|
||||||
|
{
|
||||||
|
FILE *fp = NULL;
|
||||||
|
char line[MAX_LINE_LEN];
|
||||||
|
char domain[DNS_MAX_CNAME_LEN];
|
||||||
|
int ret = 0;
|
||||||
|
int line_no = 0;
|
||||||
|
int filed_num = 0;
|
||||||
|
struct dns_domain_set_rule *set_rule = NULL;
|
||||||
|
|
||||||
|
fp = fopen(file, "r");
|
||||||
|
if (fp == NULL) {
|
||||||
|
tlog(TLOG_WARN, "open file %s error, %s", file, strerror(errno));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
line_no = 0;
|
||||||
|
while (fgets(line, MAX_LINE_LEN, fp)) {
|
||||||
|
line_no++;
|
||||||
|
filed_num = sscanf(line, "%256s", domain);
|
||||||
|
if (filed_num <= 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (domain[0] == '#' || domain[0] == '\n') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
list_for_each_entry(set_rule, &set_rule_list->domain_ruls_list, list)
|
||||||
|
{
|
||||||
|
if (set_rule->type == DOMAIN_RULE_FLAGS) {
|
||||||
|
ret = _config_domain_rule_flag_set(domain, set_rule->flags, set_rule->is_clear_flag);
|
||||||
|
} else {
|
||||||
|
ret = _config_domain_rule_add(domain, set_rule->type, set_rule->rule);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret != 0) {
|
||||||
|
tlog(TLOG_WARN, "process file %s failed at line %d.", file, line_no);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _update_domain_set(void)
|
||||||
|
{
|
||||||
|
struct dns_domain_set_rule_list *set_rule_list = NULL;
|
||||||
|
|
||||||
|
struct dns_domain_set_name_list *set_name_list = NULL;
|
||||||
|
struct dns_domain_set_name *set_name_item = NULL;
|
||||||
|
|
||||||
|
unsigned long i = 0;
|
||||||
|
uint32_t key = 0;
|
||||||
|
|
||||||
|
hash_for_each(dns_domain_set_rule_table.rule_list, i, set_rule_list, node)
|
||||||
|
{
|
||||||
|
key = hash_string(set_rule_list->domain_set);
|
||||||
|
hash_for_each_possible(dns_domain_set_name_table.names, set_name_list, node, key)
|
||||||
|
{
|
||||||
|
if (strcmp(set_name_list->name, set_rule_list->domain_set) == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (set_name_list == NULL) {
|
||||||
|
tlog(TLOG_WARN, "domain set %s not found.", set_rule_list->domain_set);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
list_for_each_entry(set_name_item, &set_name_list->set_name_list, list)
|
||||||
|
{
|
||||||
|
switch (set_name_item->type) {
|
||||||
|
case DNS_DOMAIN_SET_LIST:
|
||||||
|
_update_domain_set_from_list(set_name_item->file, set_rule_list);
|
||||||
|
break;
|
||||||
|
case DNS_DOMAIN_SET_GEOSITE:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
tlog(TLOG_WARN, "domain set %s type %d not support.", set_name_list->name, set_name_item->type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int _dns_server_load_conf_init(void)
|
static int _dns_server_load_conf_init(void)
|
||||||
{
|
{
|
||||||
dns_conf_address_rule.ipv4 = New_Radix();
|
dns_conf_address_rule.ipv4 = New_Radix();
|
||||||
@@ -2003,6 +2369,8 @@ static int _dns_server_load_conf_init(void)
|
|||||||
hash_init(dns_group_table.group);
|
hash_init(dns_group_table.group);
|
||||||
hash_init(dns_hosts_table.hosts);
|
hash_init(dns_hosts_table.hosts);
|
||||||
hash_init(dns_ptr_table.ptr);
|
hash_init(dns_ptr_table.ptr);
|
||||||
|
hash_init(dns_domain_set_rule_table.rule_list);
|
||||||
|
hash_init(dns_domain_set_name_table.names);
|
||||||
|
|
||||||
_config_setup_smartdns_domain();
|
_config_setup_smartdns_domain();
|
||||||
|
|
||||||
@@ -2096,7 +2464,6 @@ static int _dns_conf_load_post(void)
|
|||||||
dns_conf_response_mode_enum[dns_conf_response_mode].name);
|
dns_conf_response_mode_enum[dns_conf_response_mode].name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if ((dns_conf_rr_ttl_min > dns_conf_rr_ttl_max) && dns_conf_rr_ttl_max > 0) {
|
if ((dns_conf_rr_ttl_min > dns_conf_rr_ttl_max) && dns_conf_rr_ttl_max > 0) {
|
||||||
dns_conf_rr_ttl_min = dns_conf_rr_ttl_max;
|
dns_conf_rr_ttl_min = dns_conf_rr_ttl_max;
|
||||||
}
|
}
|
||||||
@@ -2113,6 +2480,10 @@ static int _dns_conf_load_post(void)
|
|||||||
safe_strncpy(dns_resolv_file, DNS_RESOLV_FILE, sizeof(dns_resolv_file));
|
safe_strncpy(dns_resolv_file, DNS_RESOLV_FILE, sizeof(dns_resolv_file));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_update_domain_set();
|
||||||
|
_config_domain_set_name_table_destroy();
|
||||||
|
_config_domain_set_rule_table_destroy();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
#define _DNS_CONF
|
#define _DNS_CONF
|
||||||
|
|
||||||
#include "art.h"
|
#include "art.h"
|
||||||
|
#include "atomic.h"
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
#include "dns.h"
|
#include "dns.h"
|
||||||
#include "dns_client.h"
|
#include "dns_client.h"
|
||||||
@@ -102,16 +103,25 @@ typedef enum {
|
|||||||
#define BIND_FLAG_NO_DUALSTACK_SELECTION (1 << 7)
|
#define BIND_FLAG_NO_DUALSTACK_SELECTION (1 << 7)
|
||||||
#define BIND_FLAG_FORCE_AAAA_SOA (1 << 8)
|
#define BIND_FLAG_FORCE_AAAA_SOA (1 << 8)
|
||||||
|
|
||||||
|
struct dns_rule {
|
||||||
|
atomic_t refcnt;
|
||||||
|
enum domain_rule rule;
|
||||||
|
char rule_data[];
|
||||||
|
};
|
||||||
|
|
||||||
struct dns_rule_flags {
|
struct dns_rule_flags {
|
||||||
|
struct dns_rule head;
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
unsigned int is_flag_set;
|
unsigned int is_flag_set;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dns_address_IPV4 {
|
struct dns_rule_address_IPV4 {
|
||||||
|
struct dns_rule head;
|
||||||
unsigned char ipv4_addr[DNS_RR_A_LEN];
|
unsigned char ipv4_addr[DNS_RR_A_LEN];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dns_address_IPV6 {
|
struct dns_rule_address_IPV6 {
|
||||||
|
struct dns_rule head;
|
||||||
unsigned char ipv6_addr[DNS_RR_AAAA_LEN];
|
unsigned char ipv6_addr[DNS_RR_AAAA_LEN];
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -121,14 +131,17 @@ struct dns_ipset_name {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct dns_ipset_rule {
|
struct dns_ipset_rule {
|
||||||
|
struct dns_rule head;
|
||||||
const char *ipsetname;
|
const char *ipsetname;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dns_domain_rule {
|
struct dns_domain_rule {
|
||||||
void *rules[DOMAIN_RULE_MAX];
|
struct dns_rule head;
|
||||||
|
struct dns_rule *rules[DOMAIN_RULE_MAX];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dns_nameserver_rule {
|
struct dns_nameserver_rule {
|
||||||
|
struct dns_rule head;
|
||||||
const char *group_name;
|
const char *group_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -145,6 +158,7 @@ struct dns_domain_check_order {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct dns_domain_check_orders {
|
struct dns_domain_check_orders {
|
||||||
|
struct dns_rule head;
|
||||||
struct dns_domain_check_order orders[DOMAIN_CHECK_NUM];
|
struct dns_domain_check_order orders[DOMAIN_CHECK_NUM];
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -255,6 +269,46 @@ struct dns_qtype_soa_table {
|
|||||||
};
|
};
|
||||||
extern struct dns_qtype_soa_table dns_qtype_soa_table;
|
extern struct dns_qtype_soa_table dns_qtype_soa_table;
|
||||||
|
|
||||||
|
struct dns_domain_set_rule {
|
||||||
|
struct list_head list;
|
||||||
|
enum domain_rule type;
|
||||||
|
void *rule;
|
||||||
|
unsigned int flags;
|
||||||
|
unsigned int is_clear_flag;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct dns_domain_set_rule_list {
|
||||||
|
struct hlist_node node;
|
||||||
|
char domain_set[DNS_MAX_CNAME_LEN];
|
||||||
|
struct list_head domain_ruls_list;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct dns_domain_set_rule_table {
|
||||||
|
DECLARE_HASHTABLE(rule_list, 4);
|
||||||
|
};
|
||||||
|
extern struct dns_domain_set_rule_table dns_domain_set_rule_table;
|
||||||
|
|
||||||
|
enum dns_domain_set_type {
|
||||||
|
DNS_DOMAIN_SET_LIST = 0,
|
||||||
|
DNS_DOMAIN_SET_GEOSITE = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct dns_domain_set_name {
|
||||||
|
struct list_head list;
|
||||||
|
enum dns_domain_set_type type;
|
||||||
|
char file[DNS_MAX_PATH];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct dns_domain_set_name_list {
|
||||||
|
struct hlist_node node;
|
||||||
|
char name[DNS_MAX_CNAME_LEN];
|
||||||
|
struct list_head set_name_list;
|
||||||
|
};
|
||||||
|
struct dns_domain_set_name_table {
|
||||||
|
DECLARE_HASHTABLE(names, 4);
|
||||||
|
};
|
||||||
|
extern struct dns_domain_set_name_table dns_domain_set_name_table;
|
||||||
|
|
||||||
extern struct dns_bind_ip dns_conf_bind_ip[DNS_MAX_BIND_IP];
|
extern struct dns_bind_ip dns_conf_bind_ip[DNS_MAX_BIND_IP];
|
||||||
extern int dns_conf_bind_ip_num;
|
extern int dns_conf_bind_ip_num;
|
||||||
|
|
||||||
|
|||||||
@@ -316,6 +316,15 @@ static int _dns_server_epoll_ctl(struct dns_server_conn_head *head, int op, uint
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void *_dns_server_get_dns_rule(struct dns_request *request, enum domain_rule rule)
|
||||||
|
{
|
||||||
|
if (rule >= DOMAIN_RULE_MAX || request == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return request->domain_rule.rules[rule];
|
||||||
|
}
|
||||||
|
|
||||||
static void _dns_server_set_dualstack_selection(struct dns_request *request)
|
static void _dns_server_set_dualstack_selection(struct dns_request *request)
|
||||||
{
|
{
|
||||||
struct dns_rule_flags *rule_flag = NULL;
|
struct dns_rule_flags *rule_flag = NULL;
|
||||||
@@ -325,7 +334,7 @@ static void _dns_server_set_dualstack_selection(struct dns_request *request)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
rule_flag = request->domain_rule.rules[DOMAIN_RULE_FLAGS];
|
rule_flag = _dns_server_get_dns_rule(request, DOMAIN_RULE_FLAGS);
|
||||||
if (rule_flag) {
|
if (rule_flag) {
|
||||||
if (rule_flag->flags & DOMAIN_FLAG_DUALSTACK_SELECT) {
|
if (rule_flag->flags & DOMAIN_FLAG_DUALSTACK_SELECT) {
|
||||||
request->dualstack_selection = 1;
|
request->dualstack_selection = 1;
|
||||||
@@ -361,7 +370,7 @@ static int _dns_server_is_return_soa(struct dns_request *request)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rule_flag = request->domain_rule.rules[DOMAIN_RULE_FLAGS];
|
rule_flag = _dns_server_get_dns_rule(request, DOMAIN_RULE_FLAGS);
|
||||||
if (rule_flag) {
|
if (rule_flag) {
|
||||||
flags = rule_flag->flags;
|
flags = rule_flag->flags;
|
||||||
if (flags & DOMAIN_FLAG_ADDR_SOA) {
|
if (flags & DOMAIN_FLAG_ADDR_SOA) {
|
||||||
@@ -733,11 +742,11 @@ static int _dns_add_rrs(struct dns_server_post_context *context)
|
|||||||
}
|
}
|
||||||
/* add SOA record */
|
/* add SOA record */
|
||||||
if (has_soa) {
|
if (has_soa) {
|
||||||
ret |= dns_add_SOA(context->packet, DNS_RRS_NS, domain, 0, &request->soa);
|
ret |= dns_add_SOA(context->packet, DNS_RRS_NS, domain, request->ip_ttl, &request->soa);
|
||||||
tlog(TLOG_DEBUG, "result: %s, qtype: %d, return SOA", request->domain, context->qtype);
|
tlog(TLOG_DEBUG, "result: %s, qtype: %d, return SOA", request->domain, context->qtype);
|
||||||
} else if (context->do_force_soa == 1) {
|
} else if (context->do_force_soa == 1) {
|
||||||
_dns_server_setup_soa(request);
|
_dns_server_setup_soa(request);
|
||||||
ret |= dns_add_SOA(context->packet, DNS_RRS_NS, domain, 0, &request->soa);
|
ret |= dns_add_SOA(context->packet, DNS_RRS_NS, domain, request->ip_ttl, &request->soa);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request->has_ecs) {
|
if (request->has_ecs) {
|
||||||
@@ -1317,15 +1326,15 @@ static int _dns_server_setup_ipset_packet(struct dns_server_post_context *contex
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* check ipset rule */
|
/* check ipset rule */
|
||||||
rule_flags = request->domain_rule.rules[DOMAIN_RULE_FLAGS];
|
rule_flags = _dns_server_get_dns_rule(request, DOMAIN_RULE_FLAGS);
|
||||||
if (!rule_flags || (rule_flags->flags & DOMAIN_FLAG_IPSET_IGN) == 0) {
|
if (!rule_flags || (rule_flags->flags & DOMAIN_FLAG_IPSET_IGN) == 0) {
|
||||||
ipset_rule = request->domain_rule.rules[DOMAIN_RULE_IPSET];
|
ipset_rule = _dns_server_get_dns_rule(request, DOMAIN_RULE_IPSET);
|
||||||
}
|
}
|
||||||
if (!rule_flags || (rule_flags->flags & DOMAIN_FLAG_IPSET_IPV4_IGN) == 0) {
|
if (!rule_flags || (rule_flags->flags & DOMAIN_FLAG_IPSET_IPV4_IGN) == 0) {
|
||||||
ipset_rule_v4 = request->domain_rule.rules[DOMAIN_RULE_IPSET_IPV4];
|
ipset_rule_v4 = _dns_server_get_dns_rule(request, DOMAIN_RULE_IPSET_IPV4);
|
||||||
}
|
}
|
||||||
if (!rule_flags || (rule_flags->flags & DOMAIN_FLAG_IPSET_IPV6_IGN) == 0) {
|
if (!rule_flags || (rule_flags->flags & DOMAIN_FLAG_IPSET_IPV6_IGN) == 0) {
|
||||||
ipset_rule_v6 = request->domain_rule.rules[DOMAIN_RULE_IPSET_IPV6];
|
ipset_rule_v6 = _dns_server_get_dns_rule(request, DOMAIN_RULE_IPSET_IPV6);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(ipset_rule || ipset_rule_v4 || ipset_rule_v6)) {
|
if (!(ipset_rule || ipset_rule_v4 || ipset_rule_v6)) {
|
||||||
@@ -2501,6 +2510,7 @@ static int _dns_server_process_answer(struct dns_request *request, const char *d
|
|||||||
request->soa.refresh, request->soa.retry, request->soa.expire, request->soa.minimum);
|
request->soa.refresh, request->soa.retry, request->soa.expire, request->soa.minimum);
|
||||||
int soa_num = atomic_inc_return(&request->soa_num);
|
int soa_num = atomic_inc_return(&request->soa_num);
|
||||||
if ((soa_num >= (dns_server_num() / 3) + 1 || soa_num > 4) && atomic_read(&request->ip_map_num) <= 0) {
|
if ((soa_num >= (dns_server_num() / 3) + 1 || soa_num > 4) && atomic_read(&request->ip_map_num) <= 0) {
|
||||||
|
request->ip_ttl = ttl;
|
||||||
_dns_server_request_complete(request);
|
_dns_server_request_complete(request);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
@@ -3340,7 +3350,7 @@ static int _dns_server_pre_process_rule_flags(struct dns_request *request)
|
|||||||
unsigned int flags = 0;
|
unsigned int flags = 0;
|
||||||
|
|
||||||
/* get domain rule flag */
|
/* get domain rule flag */
|
||||||
rule_flag = request->domain_rule.rules[DOMAIN_RULE_FLAGS];
|
rule_flag = _dns_server_get_dns_rule(request, DOMAIN_RULE_FLAGS);
|
||||||
if (rule_flag == NULL) {
|
if (rule_flag == NULL) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -3394,14 +3404,15 @@ out:
|
|||||||
|
|
||||||
soa:
|
soa:
|
||||||
/* return SOA */
|
/* return SOA */
|
||||||
|
request->ip_ttl = 30;
|
||||||
_dns_server_reply_SOA(DNS_RC_NOERROR, request);
|
_dns_server_reply_SOA(DNS_RC_NOERROR, request);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _dns_server_process_address(struct dns_request *request)
|
static int _dns_server_process_address(struct dns_request *request)
|
||||||
{
|
{
|
||||||
struct dns_address_IPV4 *address_ipv4 = NULL;
|
struct dns_rule_address_IPV4 *address_ipv4 = NULL;
|
||||||
struct dns_address_IPV6 *address_ipv6 = NULL;
|
struct dns_rule_address_IPV6 *address_ipv6 = NULL;
|
||||||
|
|
||||||
if (_dns_server_has_bind_flag(request, BIND_FLAG_NO_RULE_ADDR) == 0) {
|
if (_dns_server_has_bind_flag(request, BIND_FLAG_NO_RULE_ADDR) == 0) {
|
||||||
goto errout;
|
goto errout;
|
||||||
@@ -3413,14 +3424,14 @@ static int _dns_server_process_address(struct dns_request *request)
|
|||||||
if (request->domain_rule.rules[DOMAIN_RULE_ADDRESS_IPV4] == NULL) {
|
if (request->domain_rule.rules[DOMAIN_RULE_ADDRESS_IPV4] == NULL) {
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
address_ipv4 = request->domain_rule.rules[DOMAIN_RULE_ADDRESS_IPV4];
|
address_ipv4 = _dns_server_get_dns_rule(request, DOMAIN_RULE_ADDRESS_IPV4);
|
||||||
memcpy(request->ip_addr, address_ipv4->ipv4_addr, DNS_RR_A_LEN);
|
memcpy(request->ip_addr, address_ipv4->ipv4_addr, DNS_RR_A_LEN);
|
||||||
break;
|
break;
|
||||||
case DNS_T_AAAA:
|
case DNS_T_AAAA:
|
||||||
if (request->domain_rule.rules[DOMAIN_RULE_ADDRESS_IPV6] == NULL) {
|
if (request->domain_rule.rules[DOMAIN_RULE_ADDRESS_IPV6] == NULL) {
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
address_ipv6 = request->domain_rule.rules[DOMAIN_RULE_ADDRESS_IPV6];
|
address_ipv6 = _dns_server_get_dns_rule(request, DOMAIN_RULE_ADDRESS_IPV6);
|
||||||
memcpy(request->ip_addr, address_ipv6->ipv6_addr, DNS_RR_AAAA_LEN);
|
memcpy(request->ip_addr, address_ipv6->ipv6_addr, DNS_RR_AAAA_LEN);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -3468,7 +3479,7 @@ static void _dns_server_process_speed_check_rule(struct dns_request *request)
|
|||||||
struct dns_domain_check_orders *check_order = NULL;
|
struct dns_domain_check_orders *check_order = NULL;
|
||||||
|
|
||||||
/* get domain rule flag */
|
/* get domain rule flag */
|
||||||
check_order = request->domain_rule.rules[DOMAIN_RULE_CHECKSPEED];
|
check_order = _dns_server_get_dns_rule(request, DOMAIN_RULE_CHECKSPEED);
|
||||||
if (check_order == NULL) {
|
if (check_order == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -3812,7 +3823,7 @@ static int _dns_server_process_smartdns_domain(struct dns_request *request)
|
|||||||
unsigned int flags = 0;
|
unsigned int flags = 0;
|
||||||
|
|
||||||
/* get domain rule flag */
|
/* get domain rule flag */
|
||||||
rule_flag = request->domain_rule.rules[DOMAIN_RULE_FLAGS];
|
rule_flag = _dns_server_get_dns_rule(request, DOMAIN_RULE_FLAGS);
|
||||||
if (rule_flag == NULL) {
|
if (rule_flag == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -3870,7 +3881,7 @@ static const char *_dns_server_get_request_groupname(struct dns_request *request
|
|||||||
|
|
||||||
/* Get the nameserver rule */
|
/* Get the nameserver rule */
|
||||||
if (request->domain_rule.rules[DOMAIN_RULE_NAMESERVER]) {
|
if (request->domain_rule.rules[DOMAIN_RULE_NAMESERVER]) {
|
||||||
struct dns_nameserver_rule *nameserver_rule = request->domain_rule.rules[DOMAIN_RULE_NAMESERVER];
|
struct dns_nameserver_rule *nameserver_rule = _dns_server_get_dns_rule(request, DOMAIN_RULE_NAMESERVER);
|
||||||
return nameserver_rule->group_name;
|
return nameserver_rule->group_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4052,7 +4063,6 @@ static int _dns_server_do_query(struct dns_request *request)
|
|||||||
safe_strncpy(request->dns_group_name, group_name, DNS_GROUP_NAME_LEN);
|
safe_strncpy(request->dns_group_name, group_name, DNS_GROUP_NAME_LEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
_dns_server_set_dualstack_selection(request);
|
_dns_server_set_dualstack_selection(request);
|
||||||
|
|
||||||
if (_dns_server_process_special_query(request) == 0) {
|
if (_dns_server_process_special_query(request) == 0) {
|
||||||
|
|||||||
@@ -495,7 +495,7 @@ static int _smartdns_create_logdir(void)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
chown(logdir, uid, gid);
|
unused = chown(logdir, uid, gid);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user