domain-rules: new feature, support set speed-check-mode
This commit is contained in:
@@ -568,6 +568,7 @@ https://github.com/pymumu/smartdns/releases
|
|||||||
|nameserver|指定域名使用server组解析|无|nameserver /domain/[group\|-], `group`为组名,`-`表示忽略此规则,配套server中的`-group`参数使用| nameserver /www.example.com/office
|
|nameserver|指定域名使用server组解析|无|nameserver /domain/[group\|-], `group`为组名,`-`表示忽略此规则,配套server中的`-group`参数使用| nameserver /www.example.com/office
|
||||||
|ipset|域名IPSET|None|ipset /domain/[ipset\|-], `-`表示忽略|ipset /www.example.com/pass
|
|ipset|域名IPSET|None|ipset /domain/[ipset\|-], `-`表示忽略|ipset /www.example.com/pass
|
||||||
|ipset-timeout|设置IPSET超时功能启用|auto|[yes]|ipset-timeout yes
|
|ipset-timeout|设置IPSET超时功能启用|auto|[yes]|ipset-timeout yes
|
||||||
|
|domain-rules|设置域名规则|无|domain-rules /domain/ [-rules...]<br>`[-speed-check-mode]`: 测速模式,参考`speed-check-mode`配置<br>`[-address]`: 参考`address`配置<br>`[-nameserver]`: 参考`nameserver`配置<br>`[-ipset]`:参考`ipset`配置|domain-rules /www.example.com/ -speed-check-mode none
|
||||||
|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
|
||||||
|
|||||||
@@ -563,6 +563,7 @@ Note: Merlin firmware is derived from ASUS firmware and can theoretically be use
|
|||||||
|nameserver|To query domain with specific server group|None|nameserver /domain/[group\|-], `group` is the group name, `-` means ignore this rule, use the `-group` parameter in the related server|nameserver /www.example.com/office
|
|nameserver|To query domain with specific server group|None|nameserver /domain/[group\|-], `group` is the group name, `-` means ignore this rule, use the `-group` parameter in the related server|nameserver /www.example.com/office
|
||||||
|ipset|Domain IPSet|None|ipset /domain/[ipset\|-], `-` for ignore|ipset /www.example.com/pass
|
|ipset|Domain IPSet|None|ipset /domain/[ipset\|-], `-` for ignore|ipset /www.example.com/pass
|
||||||
|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>`[-speed-check-mode]`: set speed check mode,same as parameter `speed-check-mode`<br>`[-address]`: same as parameter `address` <br>`[-nameserver]`: same as parameter `nameserver`<br>`[-ipset]`: same as parameter `ipset`|domain-rules /www.example.com/ -speed-check-mode none
|
||||||
|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
|
||||||
|
|||||||
@@ -156,3 +156,12 @@ log-level info
|
|||||||
# ipset /domain/[ipset|-]
|
# ipset /domain/[ipset|-]
|
||||||
# ipset /www.example.com/block, set ipset with ipset name of block
|
# ipset /www.example.com/block, set ipset with ipset name of block
|
||||||
# ipset /www.example.com/-, ignore this domain
|
# ipset /www.example.com/-, ignore this domain
|
||||||
|
|
||||||
|
# set domain rules
|
||||||
|
# domain-rules /domain/ [-speed-check-mode [...]]
|
||||||
|
# rules:
|
||||||
|
# -speed-check-mode [mode]: speed check mode
|
||||||
|
# speed-check-mode [ping|tcp:port|none|,]
|
||||||
|
# -address [address|-]: same as address option
|
||||||
|
# -nameserver [group|-]: same as nameserver option
|
||||||
|
# -ipset [ipset|-]: same as ipset option
|
||||||
423
src/dns_conf.c
423
src/dns_conf.c
@@ -58,6 +58,7 @@ struct dns_domain_check_order dns_conf_check_order = {
|
|||||||
.order = {DOMAIN_CHECK_ICMP, DOMAIN_CHECK_TCP},
|
.order = {DOMAIN_CHECK_ICMP, DOMAIN_CHECK_TCP},
|
||||||
.tcp_port = 80,
|
.tcp_port = 80,
|
||||||
};
|
};
|
||||||
|
int dns_has_cap_ping = 0;
|
||||||
|
|
||||||
/* logging */
|
/* logging */
|
||||||
int dns_conf_log_level = TLOG_ERROR;
|
int dns_conf_log_level = TLOG_ERROR;
|
||||||
@@ -94,6 +95,49 @@ 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 int _get_domain(char *value, char *domain, int max_dmain_size, char **ptr_after_domain)
|
||||||
|
{
|
||||||
|
char *begin = NULL;
|
||||||
|
char *end = NULL;
|
||||||
|
int len = 0;
|
||||||
|
|
||||||
|
/* first field */
|
||||||
|
begin = strstr(value, "/");
|
||||||
|
if (begin == NULL) {
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* second field */
|
||||||
|
begin++;
|
||||||
|
end = strstr(begin, "/");
|
||||||
|
if (end == NULL) {
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* remove prefix . */
|
||||||
|
while (*begin == '.') {
|
||||||
|
begin++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get domain */
|
||||||
|
len = end - begin;
|
||||||
|
if (len >= max_dmain_size) {
|
||||||
|
tlog(TLOG_ERROR, "domain name %s too long", value);
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(domain, begin, len);
|
||||||
|
domain[len] = '\0';
|
||||||
|
|
||||||
|
if (ptr_after_domain) {
|
||||||
|
*ptr_after_domain = end + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
errout:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* create and get dns server group */
|
/* create and get dns server group */
|
||||||
static struct dns_server_groups *_dns_conf_get_group(const char *group_name)
|
static struct dns_server_groups *_dns_conf_get_group(const char *group_name)
|
||||||
{
|
{
|
||||||
@@ -523,58 +567,14 @@ errout:
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _config_ipset(void *data, int argc, char *argv[])
|
static int _conf_domain_rule_ipset(char *domain, const char *ipsetname)
|
||||||
{
|
{
|
||||||
struct dns_ipset_rule *ipset_rule = NULL;
|
struct dns_ipset_rule *ipset_rule = NULL;
|
||||||
char domain[DNS_MAX_CONF_CNAME_LEN];
|
|
||||||
char ipsetname[DNS_MAX_IPSET_NAMELEN];
|
|
||||||
const char *ipset = NULL;
|
const char *ipset = NULL;
|
||||||
char *begin = NULL;
|
|
||||||
char *end = NULL;
|
|
||||||
int len = 0;
|
|
||||||
char *value = argv[1];
|
|
||||||
|
|
||||||
if (argc <= 1) {
|
|
||||||
goto errout;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* first field */
|
|
||||||
begin = strstr(value, "/");
|
|
||||||
if (begin == NULL) {
|
|
||||||
goto errout;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* second field */
|
|
||||||
begin++;
|
|
||||||
end = strstr(begin, "/");
|
|
||||||
if (end == NULL) {
|
|
||||||
goto errout;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* remove prefix . */
|
|
||||||
while (*begin == '.') {
|
|
||||||
begin++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get domain */
|
|
||||||
len = end - begin;
|
|
||||||
if (len >= sizeof(domain)) {
|
|
||||||
tlog(TLOG_ERROR, "domain name %s too long", value);
|
|
||||||
goto errout;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(domain, begin, len);
|
|
||||||
domain[len] = '\0';
|
|
||||||
|
|
||||||
len = strlen(end + 1);
|
|
||||||
if (len <= 0) {
|
|
||||||
goto errout;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Process domain option */
|
/* Process domain option */
|
||||||
if (strncmp(end + 1, "-", sizeof("-")) != 0) {
|
if (strncmp(ipsetname, "-", sizeof("-")) != 0) {
|
||||||
/* new ipset domain */
|
/* new ipset domain */
|
||||||
safe_strncpy(ipsetname, end + 1, DNS_MAX_IPSET_NAMELEN);
|
|
||||||
ipset = _dns_conf_get_ipset(ipsetname);
|
ipset = _dns_conf_get_ipset(ipsetname);
|
||||||
if (ipset == NULL) {
|
if (ipset == NULL) {
|
||||||
goto errout;
|
goto errout;
|
||||||
@@ -605,66 +605,47 @@ errout:
|
|||||||
free(ipset_rule);
|
free(ipset_rule);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tlog(TLOG_ERROR, "add ipset %s failed", ipsetname);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _config_ipset(void *data, int argc, char *argv[])
|
||||||
|
{
|
||||||
|
char domain[DNS_MAX_CONF_CNAME_LEN];
|
||||||
|
char *value = argv[1];
|
||||||
|
|
||||||
|
if (argc <= 1) {
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_get_domain(value, domain, DNS_MAX_CONF_CNAME_LEN, &value) != 0) {
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _conf_domain_rule_ipset(domain, value);
|
||||||
|
errout:
|
||||||
tlog(TLOG_ERROR, "add ipset %s failed", value);
|
tlog(TLOG_ERROR, "add ipset %s failed", value);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _config_address(void *data, int argc, char *argv[])
|
static int _conf_domain_rule_address(char *domain, const char *domain_address)
|
||||||
{
|
{
|
||||||
struct dns_address_IPV4 *address_ipv4 = NULL;
|
struct dns_address_IPV4 *address_ipv4 = NULL;
|
||||||
struct dns_address_IPV6 *address_ipv6 = NULL;
|
struct dns_address_IPV6 *address_ipv6 = NULL;
|
||||||
void *address = NULL;
|
void *address = NULL;
|
||||||
char *value = argv[1];
|
|
||||||
char ip[MAX_IP_LEN];
|
char ip[MAX_IP_LEN];
|
||||||
char domain[DNS_MAX_CONF_CNAME_LEN];
|
|
||||||
char *begin = NULL;
|
|
||||||
char *end = NULL;
|
|
||||||
int len = 0;
|
|
||||||
int port;
|
int port;
|
||||||
struct sockaddr_storage addr;
|
struct sockaddr_storage addr;
|
||||||
socklen_t addr_len = sizeof(addr);
|
socklen_t addr_len = sizeof(addr);
|
||||||
enum domain_rule type = 0;
|
enum domain_rule type = 0;
|
||||||
unsigned int flag = 0;
|
unsigned int flag = 0;
|
||||||
|
|
||||||
if (argc <= 1) {
|
if (*(domain_address) == '#') {
|
||||||
goto errout;
|
if (strncmp(domain_address, "#4", sizeof("#4")) == 0) {
|
||||||
}
|
|
||||||
|
|
||||||
/* first field */
|
|
||||||
begin = strstr(value, "/");
|
|
||||||
if (begin == NULL) {
|
|
||||||
goto errout;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* second field */
|
|
||||||
begin++;
|
|
||||||
end = strstr(begin, "/");
|
|
||||||
if (end == NULL) {
|
|
||||||
goto errout;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* remove prefix . */
|
|
||||||
while (*begin == '.') {
|
|
||||||
begin++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get domain */
|
|
||||||
len = end - begin;
|
|
||||||
|
|
||||||
if (len >= sizeof(domain)) {
|
|
||||||
tlog(TLOG_ERROR, "domain name %s too long", value);
|
|
||||||
goto errout;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(domain, begin, len);
|
|
||||||
domain[len] = 0;
|
|
||||||
|
|
||||||
if (*(end + 1) == '#') {
|
|
||||||
if (strncmp(end + 1, "#4", sizeof("#4")) == 0) {
|
|
||||||
flag = DOMAIN_FLAG_ADDR_IPV4_SOA;
|
flag = DOMAIN_FLAG_ADDR_IPV4_SOA;
|
||||||
} else if (strncmp(end + 1, "#6", sizeof("#6")) == 0) {
|
} else if (strncmp(domain_address, "#6", sizeof("#6")) == 0) {
|
||||||
flag = DOMAIN_FLAG_ADDR_IPV6_SOA;
|
flag = DOMAIN_FLAG_ADDR_IPV6_SOA;
|
||||||
} else if (strncmp(end + 1, "#", sizeof("#")) == 0) {
|
} else if (strncmp(domain_address, "#", sizeof("#")) == 0) {
|
||||||
flag = DOMAIN_FLAG_ADDR_SOA;
|
flag = DOMAIN_FLAG_ADDR_SOA;
|
||||||
} else {
|
} else {
|
||||||
goto errout;
|
goto errout;
|
||||||
@@ -676,12 +657,12 @@ static int _config_address(void *data, int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
} else if (*(end + 1) == '-') {
|
} else if (*(domain_address) == '-') {
|
||||||
if (strncmp(end + 1, "-4", sizeof("-4")) == 0) {
|
if (strncmp(domain_address, "-4", sizeof("-4")) == 0) {
|
||||||
flag = DOMAIN_FLAG_ADDR_IPV4_IGN;
|
flag = DOMAIN_FLAG_ADDR_IPV4_IGN;
|
||||||
} else if (strncmp(end + 1, "-6", sizeof("-6")) == 0) {
|
} else if (strncmp(domain_address, "-6", sizeof("-6")) == 0) {
|
||||||
flag = DOMAIN_FLAG_ADDR_IPV6_IGN;
|
flag = DOMAIN_FLAG_ADDR_IPV6_IGN;
|
||||||
} else if (strncmp(end + 1, "-", sizeof("-")) == 0) {
|
} else if (strncmp(domain_address, "-", sizeof("-")) == 0) {
|
||||||
flag = DOMAIN_FLAG_ADDR_IGN;
|
flag = DOMAIN_FLAG_ADDR_IGN;
|
||||||
} else {
|
} else {
|
||||||
goto errout;
|
goto errout;
|
||||||
@@ -695,7 +676,7 @@ static int _config_address(void *data, int argc, char *argv[])
|
|||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
/* set address to domain */
|
/* set address to domain */
|
||||||
if (parse_ip(end + 1, ip, &port) != 0) {
|
if (parse_ip(domain_address, ip, &port) != 0) {
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -753,28 +734,45 @@ errout:
|
|||||||
free(address);
|
free(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tlog(TLOG_ERROR, "add address %s, %s failed", domain, domain_address);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _config_address(void *data, int argc, char *argv[])
|
||||||
|
{
|
||||||
|
char *value = argv[1];
|
||||||
|
char domain[DNS_MAX_CONF_CNAME_LEN];
|
||||||
|
|
||||||
|
if (argc <= 1) {
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_get_domain(value, domain, DNS_MAX_CONF_CNAME_LEN, &value) != 0) {
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _conf_domain_rule_address(domain, value);
|
||||||
|
errout:
|
||||||
tlog(TLOG_ERROR, "add address %s failed", value);
|
tlog(TLOG_ERROR, "add address %s failed", value);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _config_speed_check_mode(void *data, int argc, char *argv[])
|
static int _config_speed_check_mode_parser(struct dns_domain_check_order *check_order, const char *mode)
|
||||||
{
|
{
|
||||||
char mode[DNS_MAX_OPT_LEN];
|
char tmpbuff[DNS_MAX_OPT_LEN];
|
||||||
char *field;
|
char *field;
|
||||||
char *ptr;
|
char *ptr;
|
||||||
int order = 0;
|
int order = 0;
|
||||||
int port = 80;
|
int port = 80;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
if (argc <= 1) {
|
safe_strncpy(tmpbuff, mode, DNS_MAX_OPT_LEN);
|
||||||
return -1;
|
memset(check_order, 0, sizeof(*check_order));
|
||||||
}
|
|
||||||
|
|
||||||
safe_strncpy(mode, argv[1], sizeof(mode));
|
ptr = tmpbuff;
|
||||||
ptr = mode;
|
|
||||||
do {
|
do {
|
||||||
field = ptr;
|
field = ptr;
|
||||||
ptr = strstr(mode, ",");
|
ptr = strstr(ptr, ",");
|
||||||
if (field == NULL || order >= DOMAIN_CHECK_NUM) {
|
if (field == NULL || order >= DOMAIN_CHECK_NUM) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -784,7 +782,13 @@ static int _config_speed_check_mode(void *data, int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (strncmp(field, "ping", sizeof("ping")) == 0) {
|
if (strncmp(field, "ping", sizeof("ping")) == 0) {
|
||||||
dns_conf_check_order.order[order] = DOMAIN_CHECK_ICMP;
|
if (dns_has_cap_ping == 0) {
|
||||||
|
if (ptr) {
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
check_order->order[order] = DOMAIN_CHECK_ICMP;
|
||||||
} else if (strstr(field, "tcp") == field) {
|
} else if (strstr(field, "tcp") == field) {
|
||||||
char *port_str = strstr(field, ":");
|
char *port_str = strstr(field, ":");
|
||||||
if (port_str) {
|
if (port_str) {
|
||||||
@@ -794,12 +798,12 @@ static int _config_speed_check_mode(void *data, int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dns_conf_check_order.order[order] = DOMAIN_CHECK_TCP;
|
check_order->order[order] = DOMAIN_CHECK_TCP;
|
||||||
dns_conf_check_order.tcp_port = port;
|
check_order->tcp_port = port;
|
||||||
} else if (strncmp(field, "none", sizeof("none")) == 0) {
|
} else if (strncmp(field, "none", sizeof("none")) == 0) {
|
||||||
dns_conf_check_order.order[order] = DOMAIN_CHECK_NONE;
|
check_order->order[order] = DOMAIN_CHECK_NONE;
|
||||||
for (i = order + 1; i < DOMAIN_CHECK_NUM; i++) {
|
for (i = order + 1; i < DOMAIN_CHECK_NUM; i++) {
|
||||||
dns_conf_check_order.order[i] = DOMAIN_CHECK_NONE;
|
check_order->order[i] = DOMAIN_CHECK_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -809,11 +813,23 @@ static int _config_speed_check_mode(void *data, int argc, char *argv[])
|
|||||||
ptr++;
|
ptr++;
|
||||||
}
|
}
|
||||||
|
|
||||||
} while (1);
|
} while (ptr);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int _config_speed_check_mode(void *data, int argc, char *argv[])
|
||||||
|
{
|
||||||
|
char mode[DNS_MAX_OPT_LEN];
|
||||||
|
|
||||||
|
if (argc <= 1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
safe_strncpy(mode, argv[1], sizeof(mode));
|
||||||
|
return _config_speed_check_mode_parser(&dns_conf_check_order, mode);
|
||||||
|
}
|
||||||
|
|
||||||
static int _config_bind_ip(int argc, char *argv[], DNS_BIND_TYPE type)
|
static int _config_bind_ip(int argc, char *argv[], DNS_BIND_TYPE type)
|
||||||
{
|
{
|
||||||
int index = dns_conf_bind_ip_num;
|
int index = dns_conf_bind_ip_num;
|
||||||
@@ -950,56 +966,12 @@ static int _config_server_https(void *data, int argc, char *argv[])
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _config_nameserver(void *data, int argc, char *argv[])
|
static int _conf_domain_rule_nameserver(char *domain, const char *group_name)
|
||||||
{
|
{
|
||||||
struct dns_nameserver_rule *nameserver_rule = NULL;
|
struct dns_nameserver_rule *nameserver_rule = NULL;
|
||||||
char domain[DNS_MAX_CONF_CNAME_LEN];
|
|
||||||
char group_name[DNS_GROUP_NAME_LEN];
|
|
||||||
const char *group = NULL;
|
const char *group = NULL;
|
||||||
char *begin = NULL;
|
|
||||||
char *end = NULL;
|
|
||||||
int len = 0;
|
|
||||||
char *value = argv[1];
|
|
||||||
|
|
||||||
if (argc <= 1) {
|
if (strncmp(group_name, "-", sizeof("-")) != 0) {
|
||||||
goto errout;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* first field */
|
|
||||||
begin = strstr(value, "/");
|
|
||||||
if (begin == NULL) {
|
|
||||||
goto errout;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* second field */
|
|
||||||
begin++;
|
|
||||||
end = strstr(begin, "/");
|
|
||||||
if (end == NULL) {
|
|
||||||
goto errout;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* remove prefix . */
|
|
||||||
while (*begin == '.') {
|
|
||||||
begin++;
|
|
||||||
}
|
|
||||||
|
|
||||||
len = end - begin;
|
|
||||||
|
|
||||||
if (len >= sizeof(domain)) {
|
|
||||||
tlog(TLOG_ERROR, "domain name %s too long", value);
|
|
||||||
goto errout;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(domain, begin, len);
|
|
||||||
domain[len] = '\0';
|
|
||||||
|
|
||||||
len = strlen(end + 1);
|
|
||||||
if (len <= 0) {
|
|
||||||
goto errout;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strncmp(end + 1, "-", sizeof("-")) != 0) {
|
|
||||||
safe_strncpy(group_name, end + 1, DNS_GROUP_NAME_LEN);
|
|
||||||
group = _dns_conf_get_group_name(group_name);
|
group = _dns_conf_get_group_name(group_name);
|
||||||
if (group == NULL) {
|
if (group == NULL) {
|
||||||
goto errout;
|
goto errout;
|
||||||
@@ -1030,6 +1002,25 @@ errout:
|
|||||||
free(nameserver_rule);
|
free(nameserver_rule);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tlog(TLOG_ERROR, "add nameserver %s, %s failed", domain, group_name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _config_nameserver(void *data, int argc, char *argv[])
|
||||||
|
{
|
||||||
|
char domain[DNS_MAX_CONF_CNAME_LEN];
|
||||||
|
char *value = argv[1];
|
||||||
|
|
||||||
|
if (argc <= 1) {
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_get_domain(value, domain, DNS_MAX_CONF_CNAME_LEN, &value) != 0) {
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _conf_domain_rule_nameserver(domain, value);
|
||||||
|
errout:
|
||||||
tlog(TLOG_ERROR, "add nameserver %s failed", value);
|
tlog(TLOG_ERROR, "add nameserver %s failed", value);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1188,6 +1179,127 @@ errout:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int _conf_domain_rule_speed_check(char *domain, const char *mode)
|
||||||
|
{
|
||||||
|
struct dns_domain_check_order *check_order;
|
||||||
|
|
||||||
|
check_order = malloc(sizeof(*check_order));
|
||||||
|
if (check_order == NULL) {
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_config_speed_check_mode_parser(check_order, mode) != 0) {
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_config_domain_rule_add(domain, DOMAIN_RULE_CHECKSPEED, check_order) != 0) {
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
errout:
|
||||||
|
if (check_order) {
|
||||||
|
free(check_order);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _conf_domain_rules(void *data, int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int opt = 0;
|
||||||
|
char domain[DNS_MAX_CONF_CNAME_LEN];
|
||||||
|
char *value = argv[1];
|
||||||
|
|
||||||
|
/* clang-format off */
|
||||||
|
static struct option long_options[] = {
|
||||||
|
{"speed-check-mode", required_argument, NULL, 'c'},
|
||||||
|
{"address", required_argument, NULL, 'a'},
|
||||||
|
{"ipset", required_argument, NULL, 'p'},
|
||||||
|
{"nameserver", required_argument, NULL, 'n'},
|
||||||
|
{NULL, no_argument, NULL, 0}
|
||||||
|
};
|
||||||
|
/* clang-format on */
|
||||||
|
|
||||||
|
if (argc <= 1) {
|
||||||
|
tlog(TLOG_ERROR, "invalid parameter.");
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_get_domain(value, domain, DNS_MAX_CONF_CNAME_LEN, &value) != 0) {
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* process extra options */
|
||||||
|
optind = 1;
|
||||||
|
while (1) {
|
||||||
|
opt = getopt_long_only(argc, argv, "", long_options, NULL);
|
||||||
|
if (opt == -1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (opt) {
|
||||||
|
case 'c': {
|
||||||
|
const char *check_mode = optarg;
|
||||||
|
if (check_mode == NULL) {
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_conf_domain_rule_speed_check(domain, check_mode) != 0) {
|
||||||
|
tlog(TLOG_ERROR, "add check-speed-rule rule failed.");
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'a': {
|
||||||
|
const char *address = optarg;
|
||||||
|
if (address == NULL) {
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_conf_domain_rule_address(domain, address) != 0) {
|
||||||
|
tlog(TLOG_ERROR, "add address rule failed.");
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'p': {
|
||||||
|
const char *ipsetname = optarg;
|
||||||
|
if (ipsetname == NULL) {
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_conf_domain_rule_ipset(domain, ipsetname) != 0) {
|
||||||
|
tlog(TLOG_ERROR, "add ipset rule failed.");
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'n': {
|
||||||
|
const char *nameserver_group = optarg;
|
||||||
|
if (nameserver_group == NULL) {
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_conf_domain_rule_nameserver(domain, nameserver_group) != 0) {
|
||||||
|
tlog(TLOG_ERROR, "add nameserver rule failed.");
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
errout:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
static int _config_log_level(void *data, int argc, char *argv[])
|
static int _config_log_level(void *data, int argc, char *argv[])
|
||||||
{
|
{
|
||||||
/* read log level and set */
|
/* read log level and set */
|
||||||
@@ -1248,6 +1360,7 @@ static struct config_item _config_item[] = {
|
|||||||
CONF_CUSTOM("bogus-nxdomain", _conf_bogus_nxdomain, NULL),
|
CONF_CUSTOM("bogus-nxdomain", _conf_bogus_nxdomain, NULL),
|
||||||
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("conf-file", config_addtional_file, NULL),
|
CONF_CUSTOM("conf-file", config_addtional_file, NULL),
|
||||||
CONF_END(),
|
CONF_END(),
|
||||||
};
|
};
|
||||||
@@ -1323,6 +1436,8 @@ static int _dns_conf_speed_check_mode_verify(void)
|
|||||||
int i, j;
|
int i, j;
|
||||||
int has_cap = has_network_raw_cap();
|
int has_cap = has_network_raw_cap();
|
||||||
int print_log = 0;
|
int print_log = 0;
|
||||||
|
|
||||||
|
dns_has_cap_ping = has_cap;
|
||||||
if (has_cap == 1) {
|
if (has_cap == 1) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ enum domain_rule {
|
|||||||
DOMAIN_RULE_ADDRESS_IPV6,
|
DOMAIN_RULE_ADDRESS_IPV6,
|
||||||
DOMAIN_RULE_IPSET,
|
DOMAIN_RULE_IPSET,
|
||||||
DOMAIN_RULE_NAMESERVER,
|
DOMAIN_RULE_NAMESERVER,
|
||||||
|
DOMAIN_RULE_CHECKSPEED,
|
||||||
DOMAIN_RULE_MAX,
|
DOMAIN_RULE_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1935,6 +1935,19 @@ errout:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _dns_server_prolcess_speed_check_rule(struct dns_request *request)
|
||||||
|
{
|
||||||
|
struct dns_domain_check_order *check_order = NULL;
|
||||||
|
|
||||||
|
/* get domain rule flag */
|
||||||
|
check_order = request->domain_rule.rules[DOMAIN_RULE_CHECKSPEED];
|
||||||
|
if (check_order == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
request->check_order_list = check_order;
|
||||||
|
}
|
||||||
|
|
||||||
static int _dns_server_process_cache(struct dns_request *request)
|
static int _dns_server_process_cache(struct dns_request *request)
|
||||||
{
|
{
|
||||||
struct dns_cache *dns_cache = NULL;
|
struct dns_cache *dns_cache = NULL;
|
||||||
@@ -2109,6 +2122,17 @@ static const char *_dns_server_get_request_groupname(struct dns_request *request
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _dns_server_check_set_passthrough(struct dns_request *request)
|
||||||
|
{
|
||||||
|
if (request->check_order_list->order[0] == DOMAIN_CHECK_NONE) {
|
||||||
|
request->passthrough = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_dns_server_has_bind_flag(request, BIND_FLAG_NO_SPEED_CHECK) == 0) {
|
||||||
|
request->passthrough = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int _dns_server_do_query(struct dns_request *request, const char *domain, int qtype)
|
static int _dns_server_do_query(struct dns_request *request, const char *domain, int qtype)
|
||||||
{
|
{
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
@@ -2143,6 +2167,12 @@ static int _dns_server_do_query(struct dns_request *request, const char *domain,
|
|||||||
goto clean_exit;
|
goto clean_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* process speed check rule */
|
||||||
|
_dns_server_prolcess_speed_check_rule(request);
|
||||||
|
|
||||||
|
/* check and set passthrough */
|
||||||
|
_dns_server_check_set_passthrough(request);
|
||||||
|
|
||||||
/* process cache */
|
/* process cache */
|
||||||
if (request->prefetch == 0) {
|
if (request->prefetch == 0) {
|
||||||
if (_dns_server_process_cache(request) == 0) {
|
if (_dns_server_process_cache(request) == 0) {
|
||||||
@@ -2186,17 +2216,6 @@ errout:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _dns_server_check_set_passthrough(struct dns_request *request, struct dns_server_conn_head *conn)
|
|
||||||
{
|
|
||||||
if (request->check_order_list->order[0] == DOMAIN_CHECK_NONE) {
|
|
||||||
request->passthrough = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_dns_server_has_bind_flag(request, BIND_FLAG_NO_SPEED_CHECK) == 0) {
|
|
||||||
request->passthrough = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _dns_server_recv(struct dns_server_conn_head *conn, unsigned char *inpacket, int inpacket_len, struct sockaddr_storage *local, socklen_t local_len,
|
static int _dns_server_recv(struct dns_server_conn_head *conn, unsigned char *inpacket, int inpacket_len, struct sockaddr_storage *local, socklen_t local_len,
|
||||||
struct sockaddr_storage *from, socklen_t from_len)
|
struct sockaddr_storage *from, socklen_t from_len)
|
||||||
{
|
{
|
||||||
@@ -2254,7 +2273,6 @@ static int _dns_server_recv(struct dns_server_conn_head *conn, unsigned char *in
|
|||||||
|
|
||||||
memcpy(&request->localaddr, local, local_len);
|
memcpy(&request->localaddr, local, local_len);
|
||||||
_dns_server_request_set_client(request, conn);
|
_dns_server_request_set_client(request, conn);
|
||||||
_dns_server_check_set_passthrough(request, conn);
|
|
||||||
_dns_server_request_set_client_addr(request, from, from_len);
|
_dns_server_request_set_client_addr(request, from, from_len);
|
||||||
_dns_server_request_set_id(request, packet->head.id);
|
_dns_server_request_set_id(request, packet->head.id);
|
||||||
_dns_server_set_dualstack_selection(request);
|
_dns_server_set_dualstack_selection(request);
|
||||||
|
|||||||
Reference in New Issue
Block a user