feature: add ip-alias option.
This commit is contained in:
149
src/dns_conf.c
149
src/dns_conf.c
@@ -252,6 +252,38 @@ static void _dns_rule_put(struct dns_rule *rule)
|
||||
}
|
||||
}
|
||||
|
||||
static struct dns_iplist_ip_addresses *_new_dns_iplist_ip_addresses(void)
|
||||
{
|
||||
struct dns_iplist_ip_addresses *iplist;
|
||||
|
||||
iplist = malloc(sizeof(struct dns_iplist_ip_addresses));
|
||||
if (!iplist) {
|
||||
return NULL;
|
||||
}
|
||||
memset(iplist, 0, sizeof(struct dns_iplist_ip_addresses));
|
||||
atomic_set(&iplist->refcnt, 1);
|
||||
return iplist;
|
||||
}
|
||||
|
||||
static void _dns_iplist_ip_addresses_put(struct dns_iplist_ip_addresses *iplist)
|
||||
{
|
||||
if (atomic_dec_and_test(&iplist->refcnt)) {
|
||||
free(iplist);
|
||||
}
|
||||
}
|
||||
|
||||
static void _dns_iplist_ip_address_add(struct dns_iplist_ip_addresses *iplist, unsigned char addr[], int addr_len)
|
||||
{
|
||||
iplist->ipaddr = realloc(iplist->ipaddr, (iplist->ipaddr_num + 1) * sizeof(struct dns_iplist_ip_address));
|
||||
if (iplist->ipaddr == NULL) {
|
||||
return;
|
||||
}
|
||||
memset(&iplist->ipaddr[iplist->ipaddr_num], 0, sizeof(struct dns_iplist_ip_address));
|
||||
iplist->ipaddr[iplist->ipaddr_num].addr_len = addr_len;
|
||||
memcpy(iplist->ipaddr[iplist->ipaddr_num].addr, addr, addr_len);
|
||||
iplist->ipaddr_num++;
|
||||
}
|
||||
|
||||
static int _get_domain(char *value, char *domain, int max_domain_size, char **ptr_after_domain)
|
||||
{
|
||||
char *begin = NULL;
|
||||
@@ -768,6 +800,7 @@ static void _config_domain_destroy(void)
|
||||
|
||||
static void _config_address_destroy(radix_node_t *node, void *cbctx)
|
||||
{
|
||||
struct dns_ip_address_rule *address_rule = NULL;
|
||||
if (node == NULL) {
|
||||
return;
|
||||
}
|
||||
@@ -776,6 +809,12 @@ static void _config_address_destroy(radix_node_t *node, void *cbctx)
|
||||
return;
|
||||
}
|
||||
|
||||
address_rule = node->data;
|
||||
if (address_rule->ip_alias) {
|
||||
_dns_iplist_ip_addresses_put(address_rule->ip_alias);
|
||||
address_rule->ip_alias = NULL;
|
||||
}
|
||||
|
||||
free(node->data);
|
||||
node->data = NULL;
|
||||
}
|
||||
@@ -2461,20 +2500,20 @@ static radix_node_t *_create_addr_node(char *addr)
|
||||
return node;
|
||||
}
|
||||
|
||||
static int _config_iplist_rule(char *subnet, enum address_rule rule)
|
||||
static struct dns_ip_address_rule *_config_iplist_rule(char *subnet, enum address_rule rule)
|
||||
{
|
||||
radix_node_t *node = NULL;
|
||||
struct dns_ip_address_rule *ip_rule = NULL;
|
||||
|
||||
node = _create_addr_node(subnet);
|
||||
if (node == NULL) {
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (node->data == NULL) {
|
||||
ip_rule = malloc(sizeof(*ip_rule));
|
||||
if (ip_rule == NULL) {
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
node->data = ip_rule;
|
||||
@@ -2496,11 +2535,15 @@ static int _config_iplist_rule(char *subnet, enum address_rule rule)
|
||||
case ADDRESS_RULE_IP_IGNORE:
|
||||
ip_rule->ip_ignore = 1;
|
||||
break;
|
||||
case ADDRESS_RULE_IP_ALIAS: {
|
||||
ip_rule->ip_alias = _new_dns_iplist_ip_addresses();
|
||||
ip_rule->ip_alias_enable = 1;
|
||||
} break;
|
||||
default:
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return ip_rule;
|
||||
}
|
||||
|
||||
static int _config_qtype_soa(void *data, int argc, char *argv[])
|
||||
@@ -2582,7 +2625,11 @@ static int _config_blacklist_ip(void *data, int argc, char *argv[])
|
||||
return -1;
|
||||
}
|
||||
|
||||
return _config_iplist_rule(argv[1], ADDRESS_RULE_BLACKLIST);
|
||||
if (_config_iplist_rule(argv[1], ADDRESS_RULE_BLACKLIST) == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _conf_bogus_nxdomain(void *data, int argc, char *argv[])
|
||||
@@ -2591,7 +2638,11 @@ static int _conf_bogus_nxdomain(void *data, int argc, char *argv[])
|
||||
return -1;
|
||||
}
|
||||
|
||||
return _config_iplist_rule(argv[1], ADDRESS_RULE_BOGUS);
|
||||
if (_config_iplist_rule(argv[1], ADDRESS_RULE_BOGUS) == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _conf_ip_ignore(void *data, int argc, char *argv[])
|
||||
@@ -2600,7 +2651,11 @@ static int _conf_ip_ignore(void *data, int argc, char *argv[])
|
||||
return -1;
|
||||
}
|
||||
|
||||
return _config_iplist_rule(argv[1], ADDRESS_RULE_IP_IGNORE);
|
||||
if (_config_iplist_rule(argv[1], ADDRESS_RULE_IP_IGNORE) == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _conf_whitelist_ip(void *data, int argc, char *argv[])
|
||||
@@ -2609,7 +2664,82 @@ static int _conf_whitelist_ip(void *data, int argc, char *argv[])
|
||||
return -1;
|
||||
}
|
||||
|
||||
return _config_iplist_rule(argv[1], ADDRESS_RULE_WHITELIST);
|
||||
if (_config_iplist_rule(argv[1], ADDRESS_RULE_WHITELIST) == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _conf_ip_alias(void *data, int argc, char *argv[])
|
||||
{
|
||||
struct dns_ip_address_rule *ip_rule = NULL;
|
||||
struct dns_iplist_ip_addresses *ip_alias = NULL;
|
||||
char *target_ips = NULL;
|
||||
|
||||
if (argc <= 2) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ip_rule = _config_iplist_rule(argv[1], ADDRESS_RULE_IP_ALIAS);
|
||||
if (ip_rule == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ip_alias = ip_rule->ip_alias;
|
||||
if (ip_alias == NULL) {
|
||||
tlog(TLOG_ERROR, "cannot malloc memory");
|
||||
goto errout;
|
||||
}
|
||||
|
||||
target_ips = strdup(argv[2]);
|
||||
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;
|
||||
unsigned char *paddr = NULL;
|
||||
int ret = 0;
|
||||
|
||||
ret = getaddr_by_host(tok, (struct sockaddr *)&addr, &addr_len);
|
||||
if (ret != 0) {
|
||||
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, 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, paddr, DNS_RR_A_LEN);
|
||||
} else {
|
||||
paddr = addr_in6->sin6_addr.s6_addr;
|
||||
_dns_iplist_ip_address_add(ip_alias, paddr, DNS_RR_AAAA_LEN);
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
goto errout;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free(target_ips);
|
||||
return 0;
|
||||
errout:
|
||||
if (target_ips) {
|
||||
free(target_ips);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int _conf_client_subnet(char *subnet, struct dns_edns_client_subnet *ipv4_ecs,
|
||||
@@ -3591,6 +3721,7 @@ static struct config_item _config_item[] = {
|
||||
CONF_CUSTOM("force-qtype-SOA", _config_qtype_soa, NULL),
|
||||
CONF_CUSTOM("blacklist-ip", _config_blacklist_ip, NULL),
|
||||
CONF_CUSTOM("whitelist-ip", _conf_whitelist_ip, NULL),
|
||||
CONF_CUSTOM("ip-alias", _conf_ip_alias, NULL),
|
||||
CONF_CUSTOM("bogus-nxdomain", _conf_bogus_nxdomain, NULL),
|
||||
CONF_CUSTOM("ignore-ip", _conf_ip_ignore, NULL),
|
||||
CONF_CUSTOM("edns-client-subnet", _conf_edns_client_subnet, NULL),
|
||||
|
||||
@@ -355,6 +355,22 @@ enum address_rule {
|
||||
ADDRESS_RULE_WHITELIST = 2,
|
||||
ADDRESS_RULE_BOGUS = 3,
|
||||
ADDRESS_RULE_IP_IGNORE = 4,
|
||||
ADDRESS_RULE_IP_ALIAS = 5,
|
||||
};
|
||||
|
||||
struct dns_iplist_ip_address {
|
||||
int addr_len;
|
||||
union {
|
||||
unsigned char ipv4_addr[DNS_RR_A_LEN];
|
||||
unsigned char ipv6_addr[DNS_RR_AAAA_LEN];
|
||||
unsigned char addr[0];
|
||||
};
|
||||
};
|
||||
|
||||
struct dns_iplist_ip_addresses {
|
||||
atomic_t refcnt;
|
||||
int ipaddr_num;
|
||||
struct dns_iplist_ip_address *ipaddr;
|
||||
};
|
||||
|
||||
struct dns_ip_address_rule {
|
||||
@@ -362,6 +378,8 @@ struct dns_ip_address_rule {
|
||||
unsigned int whitelist : 1;
|
||||
unsigned int bogus : 1;
|
||||
unsigned int ip_ignore : 1;
|
||||
unsigned int ip_alias_enable : 1;
|
||||
struct dns_iplist_ip_addresses *ip_alias;
|
||||
};
|
||||
|
||||
struct dns_conf_address_rule {
|
||||
|
||||
241
src/dns_server.c
241
src/dns_server.c
@@ -2732,8 +2732,8 @@ static int _dns_server_check_speed(struct dns_request *request, char *ip)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int _dns_server_ip_rule_check(struct dns_request *request, unsigned char *addr, int addr_len,
|
||||
dns_type_t addr_type, int result_flag)
|
||||
static struct dns_ip_address_rule *_dns_server_ip_rule_get(struct dns_request *request, unsigned char *addr,
|
||||
int addr_len, dns_type_t addr_type)
|
||||
{
|
||||
prefix_t prefix;
|
||||
radix_node_t *node = NULL;
|
||||
@@ -2741,7 +2741,7 @@ static int _dns_server_ip_rule_check(struct dns_request *request, unsigned char
|
||||
|
||||
/* Match IP address rules */
|
||||
if (prefix_from_blob(addr, addr_len, addr_len * 8, &prefix) == NULL) {
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (prefix.family) {
|
||||
@@ -2756,15 +2756,24 @@ static int _dns_server_ip_rule_check(struct dns_request *request, unsigned char
|
||||
}
|
||||
|
||||
if (node == NULL) {
|
||||
goto rule_not_found;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (node->data == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rule = node->data;
|
||||
|
||||
return rule;
|
||||
}
|
||||
|
||||
static int _dns_server_ip_rule_check(struct dns_request *request, struct dns_ip_address_rule *rule, int result_flag)
|
||||
{
|
||||
if (rule == NULL) {
|
||||
goto rule_not_found;
|
||||
}
|
||||
|
||||
/* bogus-nxdomain */
|
||||
rule = node->data;
|
||||
if (rule->bogus) {
|
||||
request->rcode = DNS_RC_NXDOMAIN;
|
||||
request->has_soa = 1;
|
||||
@@ -2785,6 +2794,10 @@ static int _dns_server_ip_rule_check(struct dns_request *request, unsigned char
|
||||
goto skip;
|
||||
}
|
||||
|
||||
if (rule->ip_alias_enable) {
|
||||
goto match;
|
||||
}
|
||||
|
||||
rule_not_found:
|
||||
if (result_flag & DNSSERVER_FLAG_WHITELIST_IP) {
|
||||
if (rule == NULL) {
|
||||
@@ -2807,6 +2820,60 @@ match:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _dns_server_process_ip_alias(struct dns_request *request, struct dns_iplist_ip_addresses *alias,
|
||||
unsigned char **paddrs, int *paddr_num, int max_paddr_num, int addr_len)
|
||||
{
|
||||
int addr_num = 0;
|
||||
|
||||
if (alias == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (request == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (alias->ipaddr_num <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < alias->ipaddr_num && i < max_paddr_num; i++) {
|
||||
if (alias->ipaddr[i].addr_len != addr_len) {
|
||||
continue;
|
||||
}
|
||||
paddrs[i] = alias->ipaddr[i].addr;
|
||||
addr_num++;
|
||||
}
|
||||
|
||||
*paddr_num = addr_num;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _dns_server_process_ip_rule(struct dns_request *request, unsigned char *addr, int addr_len,
|
||||
dns_type_t addr_type, int result_flag, struct dns_iplist_ip_addresses **alias)
|
||||
{
|
||||
struct dns_ip_address_rule *rule = NULL;
|
||||
int ret = 0;
|
||||
|
||||
rule = _dns_server_ip_rule_get(request, addr, addr_len, addr_type);
|
||||
ret = _dns_server_ip_rule_check(request, rule, result_flag);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (rule->ip_alias_enable && alias != NULL) {
|
||||
*alias = rule->ip_alias;
|
||||
if (alias == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* need process ip alias */
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _dns_server_is_adblock_ipv6(const unsigned char addr[16])
|
||||
{
|
||||
int i = 0;
|
||||
@@ -2830,8 +2897,11 @@ static int _dns_server_process_answer_A(struct dns_rrs *rrs, struct dns_request
|
||||
int ttl = 0;
|
||||
int ip_check_result = 0;
|
||||
unsigned char addr[4];
|
||||
unsigned char *paddrs[MAX_IP_NUM];
|
||||
int paddr_num = 0;
|
||||
char name[DNS_MAX_CNAME_LEN] = {0};
|
||||
char ip[DNS_MAX_CNAME_LEN] = {0};
|
||||
struct dns_iplist_ip_addresses *alias = NULL;
|
||||
|
||||
if (request->qtype != DNS_T_A) {
|
||||
/* ignore non-matched query type */
|
||||
@@ -2839,65 +2909,71 @@ static int _dns_server_process_answer_A(struct dns_rrs *rrs, struct dns_request
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
_dns_server_request_get(request);
|
||||
|
||||
/* get A result */
|
||||
dns_get_A(rrs, name, DNS_MAX_CNAME_LEN, &ttl, addr);
|
||||
paddrs[paddr_num] = addr;
|
||||
paddr_num = 1;
|
||||
|
||||
tlog(TLOG_DEBUG, "domain: %s TTL: %d IP: %d.%d.%d.%d", name, ttl, addr[0], addr[1], addr[2], addr[3]);
|
||||
|
||||
/* if domain is not match */
|
||||
if (strncmp(name, domain, DNS_MAX_CNAME_LEN) != 0 && strncmp(cname, name, DNS_MAX_CNAME_LEN) != 0) {
|
||||
_dns_server_request_release(request);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* ip rule check */
|
||||
ip_check_result = _dns_server_ip_rule_check(request, addr, 4, DNS_T_A, result_flag);
|
||||
ip_check_result = _dns_server_process_ip_rule(request, addr, 4, DNS_T_A, result_flag, &alias);
|
||||
if (ip_check_result == 0) {
|
||||
/* match */
|
||||
_dns_server_request_release(request);
|
||||
return -1;
|
||||
} else if (ip_check_result == -2 || ip_check_result == -3) {
|
||||
/* skip, nxdomain */
|
||||
_dns_server_request_release(request);
|
||||
return ip_check_result;
|
||||
}
|
||||
|
||||
if (atomic_read(&request->ip_map_num) == 0) {
|
||||
request->has_ip = 1;
|
||||
memcpy(request->ip_addr, addr, DNS_RR_A_LEN);
|
||||
request->ip_ttl = _dns_server_get_conf_ttl(request, ttl);
|
||||
if (cname[0] != 0 && request->has_cname == 0 && dns_conf_force_no_cname == 0) {
|
||||
request->has_cname = 1;
|
||||
safe_strncpy(request->cname, cname, DNS_MAX_CNAME_LEN);
|
||||
}
|
||||
} else {
|
||||
if (ttl < request->ip_ttl) {
|
||||
request->ip_ttl = _dns_server_get_conf_ttl(request, ttl);
|
||||
}
|
||||
int ret = _dns_server_process_ip_alias(request, alias, paddrs, &paddr_num, MAX_IP_NUM, DNS_RR_A_LEN);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Ad blocking result */
|
||||
if (addr[0] == 0 || addr[0] == 127) {
|
||||
/* If half of the servers return the same result, then ignore this address */
|
||||
if (atomic_inc_return(&request->adblock) <= (dns_server_alive_num() / 2 + dns_server_alive_num() % 2)) {
|
||||
request->rcode = DNS_RC_NOERROR;
|
||||
_dns_server_request_release(request);
|
||||
for (int i = 0; i < paddr_num; i++) {
|
||||
unsigned char *paddr = paddrs[i];
|
||||
if (atomic_read(&request->ip_map_num) == 0) {
|
||||
request->has_ip = 1;
|
||||
memcpy(request->ip_addr, paddr, DNS_RR_A_LEN);
|
||||
request->ip_ttl = _dns_server_get_conf_ttl(request, ttl);
|
||||
if (cname[0] != 0 && request->has_cname == 0 && dns_conf_force_no_cname == 0) {
|
||||
request->has_cname = 1;
|
||||
safe_strncpy(request->cname, cname, DNS_MAX_CNAME_LEN);
|
||||
}
|
||||
} else {
|
||||
if (ttl < request->ip_ttl) {
|
||||
request->ip_ttl = _dns_server_get_conf_ttl(request, ttl);
|
||||
}
|
||||
}
|
||||
|
||||
/* Ad blocking result */
|
||||
if (paddr[0] == 0 || paddr[0] == 127) {
|
||||
/* If half of the servers return the same result, then ignore this address */
|
||||
if (atomic_inc_return(&request->adblock) <= (dns_server_alive_num() / 2 + dns_server_alive_num() % 2)) {
|
||||
request->rcode = DNS_RC_NOERROR;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* add this ip to request */
|
||||
if (_dns_ip_address_check_add(request, cname, paddr, DNS_T_A, 0, NULL) != 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* add this ip to request */
|
||||
if (_dns_ip_address_check_add(request, cname, addr, DNS_T_A, 0, NULL) != 0) {
|
||||
_dns_server_request_release(request);
|
||||
return -1;
|
||||
}
|
||||
sprintf(ip, "%d.%d.%d.%d", paddr[0], paddr[1], paddr[2], paddr[3]);
|
||||
|
||||
sprintf(ip, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]);
|
||||
|
||||
/* start ping */
|
||||
if (_dns_server_check_speed(request, ip) != 0) {
|
||||
_dns_server_request_release(request);
|
||||
/* start ping */
|
||||
_dns_server_request_get(request);
|
||||
if (_dns_server_check_speed(request, ip) != 0) {
|
||||
_dns_server_request_release(request);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -2907,17 +2983,22 @@ static int _dns_server_process_answer_AAAA(struct dns_rrs *rrs, struct dns_reque
|
||||
char *cname, unsigned int result_flag)
|
||||
{
|
||||
unsigned char addr[16];
|
||||
unsigned char *paddrs[MAX_IP_NUM];
|
||||
int paddr_num = 0;
|
||||
char name[DNS_MAX_CNAME_LEN] = {0};
|
||||
char ip[DNS_MAX_CNAME_LEN] = {0};
|
||||
int ttl = 0;
|
||||
int ip_check_result = 0;
|
||||
struct dns_iplist_ip_addresses *alias = NULL;
|
||||
|
||||
if (request->qtype != DNS_T_AAAA) {
|
||||
/* ignore non-matched query type */
|
||||
return -1;
|
||||
}
|
||||
_dns_server_request_get(request);
|
||||
|
||||
dns_get_AAAA(rrs, name, DNS_MAX_CNAME_LEN, &ttl, addr);
|
||||
paddrs[paddr_num] = addr;
|
||||
paddr_num = 1;
|
||||
|
||||
tlog(TLOG_DEBUG, "domain: %s TTL: %d IP: %.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x",
|
||||
name, ttl, addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], addr[8], addr[9], addr[10],
|
||||
@@ -2925,58 +3006,62 @@ static int _dns_server_process_answer_AAAA(struct dns_rrs *rrs, struct dns_reque
|
||||
|
||||
/* if domain is not match */
|
||||
if (strncmp(name, domain, DNS_MAX_CNAME_LEN) != 0 && strncmp(cname, name, DNS_MAX_CNAME_LEN) != 0) {
|
||||
_dns_server_request_release(request);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ip_check_result = _dns_server_ip_rule_check(request, addr, 16, DNS_T_AAAA, result_flag);
|
||||
ip_check_result = _dns_server_process_ip_rule(request, addr, 16, DNS_T_AAAA, result_flag, &alias);
|
||||
if (ip_check_result == 0) {
|
||||
/* match */
|
||||
_dns_server_request_release(request);
|
||||
return -1;
|
||||
} else if (ip_check_result == -2 || ip_check_result == -3) {
|
||||
/* skip, nxdomain */
|
||||
_dns_server_request_release(request);
|
||||
return ip_check_result;
|
||||
}
|
||||
|
||||
if (atomic_read(&request->ip_map_num) == 0) {
|
||||
request->has_ip = 1;
|
||||
memcpy(request->ip_addr, addr, DNS_RR_AAAA_LEN);
|
||||
request->ip_ttl = _dns_server_get_conf_ttl(request, ttl);
|
||||
if (cname[0] != 0 && request->has_cname == 0 && dns_conf_force_no_cname == 0) {
|
||||
request->has_cname = 1;
|
||||
safe_strncpy(request->cname, cname, DNS_MAX_CNAME_LEN);
|
||||
}
|
||||
} else {
|
||||
if (ttl < request->ip_ttl) {
|
||||
request->ip_ttl = _dns_server_get_conf_ttl(request, ttl);
|
||||
}
|
||||
int ret = _dns_server_process_ip_alias(request, alias, paddrs, &paddr_num, MAX_IP_NUM, DNS_RR_AAAA_LEN);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Ad blocking result */
|
||||
if (_dns_server_is_adblock_ipv6(addr) == 0) {
|
||||
/* If half of the servers return the same result, then ignore this address */
|
||||
if (atomic_inc_return(&request->adblock) <= (dns_server_alive_num() / 2 + dns_server_alive_num() % 2)) {
|
||||
request->rcode = DNS_RC_NOERROR;
|
||||
_dns_server_request_release(request);
|
||||
for (int i = 0; i < paddr_num; i++) {
|
||||
unsigned char *paddr = paddrs[i];
|
||||
if (atomic_read(&request->ip_map_num) == 0) {
|
||||
request->has_ip = 1;
|
||||
memcpy(request->ip_addr, paddr, DNS_RR_AAAA_LEN);
|
||||
request->ip_ttl = _dns_server_get_conf_ttl(request, ttl);
|
||||
if (cname[0] != 0 && request->has_cname == 0 && dns_conf_force_no_cname == 0) {
|
||||
request->has_cname = 1;
|
||||
safe_strncpy(request->cname, cname, DNS_MAX_CNAME_LEN);
|
||||
}
|
||||
} else {
|
||||
if (ttl < request->ip_ttl) {
|
||||
request->ip_ttl = _dns_server_get_conf_ttl(request, ttl);
|
||||
}
|
||||
}
|
||||
|
||||
/* Ad blocking result */
|
||||
if (_dns_server_is_adblock_ipv6(paddr) == 0) {
|
||||
/* If half of the servers return the same result, then ignore this address */
|
||||
if (atomic_inc_return(&request->adblock) <= (dns_server_alive_num() / 2 + dns_server_alive_num() % 2)) {
|
||||
request->rcode = DNS_RC_NOERROR;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* add this ip to request */
|
||||
if (_dns_ip_address_check_add(request, cname, paddr, DNS_T_AAAA, 0, NULL) != 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* add this ip to request */
|
||||
if (_dns_ip_address_check_add(request, cname, addr, DNS_T_AAAA, 0, NULL) != 0) {
|
||||
_dns_server_request_release(request);
|
||||
return -1;
|
||||
}
|
||||
sprintf(ip, "[%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x]", paddr[0], paddr[1],
|
||||
paddr[2], paddr[3], paddr[4], paddr[5], paddr[6], paddr[7], paddr[8], paddr[9], paddr[10], paddr[11],
|
||||
paddr[12], paddr[13], paddr[14], paddr[15]);
|
||||
|
||||
sprintf(ip, "[%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x]", addr[0], addr[1], addr[2],
|
||||
addr[3], addr[4], addr[5], addr[6], addr[7], addr[8], addr[9], addr[10], addr[11], addr[12], addr[13],
|
||||
addr[14], addr[15]);
|
||||
|
||||
/* start ping */
|
||||
if (_dns_server_check_speed(request, ip) != 0) {
|
||||
_dns_server_request_release(request);
|
||||
/* start ping */
|
||||
_dns_server_request_get(request);
|
||||
if (_dns_server_check_speed(request, ip) != 0) {
|
||||
_dns_server_request_release(request);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -3140,7 +3225,7 @@ static int _dns_server_passthrough_rule_check(struct dns_request *request, const
|
||||
addr[3]);
|
||||
|
||||
/* ip rule check */
|
||||
ip_check_result = _dns_server_ip_rule_check(request, addr, 4, DNS_T_A, result_flag);
|
||||
ip_check_result = _dns_server_process_ip_rule(request, addr, 4, DNS_T_A, result_flag, NULL);
|
||||
if (ip_check_result == 0 || ip_check_result == -2 || ip_check_result == -3) {
|
||||
/* match, skip, nxdomain */
|
||||
_dns_server_request_release(request);
|
||||
@@ -3180,7 +3265,7 @@ static int _dns_server_passthrough_rule_check(struct dns_request *request, const
|
||||
name, ttl_tmp, addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], addr[8],
|
||||
addr[9], addr[10], addr[11], addr[12], addr[13], addr[14], addr[15]);
|
||||
|
||||
ip_check_result = _dns_server_ip_rule_check(request, addr, 16, DNS_T_AAAA, result_flag);
|
||||
ip_check_result = _dns_server_process_ip_rule(request, addr, 16, DNS_T_AAAA, result_flag, NULL);
|
||||
if (ip_check_result == 0 || ip_check_result == -2 || ip_check_result == -3) {
|
||||
/* match, skip, nxdomain */
|
||||
_dns_server_request_release(request);
|
||||
|
||||
@@ -743,11 +743,15 @@ static void smartdns_test_notify_func(int fd_notify, uint64_t retval)
|
||||
}
|
||||
}
|
||||
|
||||
#define smartdns_close_allfds() close_all_fd(fd_notify);
|
||||
int smartdns_main(int argc, char *argv[], int fd_notify)
|
||||
#define smartdns_close_allfds() \
|
||||
if (no_close_allfds == 0) { \
|
||||
close_all_fd(fd_notify); \
|
||||
}
|
||||
|
||||
int smartdns_main(int argc, char *argv[], int fd_notify, int no_close_allfds)
|
||||
#else
|
||||
#define smartdns_test_notify(retval)
|
||||
#define smartdns_close_allfds() close_all_fd(-1);
|
||||
#define smartdns_close_allfds() close_all_fd(-1)
|
||||
int main(int argc, char *argv[])
|
||||
#endif
|
||||
{
|
||||
|
||||
@@ -29,7 +29,7 @@ typedef void (*smartdns_post_func)(void *arg);
|
||||
|
||||
int smartdns_reg_post_func(smartdns_post_func func, void *arg);
|
||||
|
||||
int smartdns_main(int argc, char *argv[], int fd_notify);
|
||||
int smartdns_main(int argc, char *argv[], int fd_notify, int no_close_allfds);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
49
src/util.c
49
src/util.c
@@ -156,6 +156,55 @@ errout:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int generate_random_addr(unsigned char *addr, int addr_len, int mask)
|
||||
{
|
||||
if (mask / 8 > addr_len) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int offset = mask / 8;
|
||||
int bit = 0;
|
||||
|
||||
for (int i = offset; i < addr_len; i++) {
|
||||
bit = 0xFF;
|
||||
if (i == offset) {
|
||||
bit = ~(0xFF << (8 - mask % 8)) & 0xFF;
|
||||
}
|
||||
addr[i] = jhash(&addr[i], 1, 0) & bit;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int generate_addr_map(unsigned char *addr_from, unsigned char *addr_to, unsigned char *addr_out, int addr_len, int mask)
|
||||
{
|
||||
if ((mask / 8) >= addr_len) {
|
||||
if (mask % 8 != 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int offset = mask / 8;
|
||||
int bit = mask % 8;
|
||||
for (int i = 0; i < offset; i++) {
|
||||
addr_out[i] = addr_to[i];
|
||||
}
|
||||
|
||||
if (bit != 0) {
|
||||
int mask1 = 0xFF >> bit;
|
||||
int mask2 = (0xFF << (8 - bit)) & 0xFF;
|
||||
addr_out[offset] = addr_from[offset] & mask1;
|
||||
addr_out[offset] |= addr_to[offset] & mask2;
|
||||
offset = offset + 1;
|
||||
}
|
||||
|
||||
for (int i = offset; i < addr_len; i++) {
|
||||
addr_out[i] = addr_from[i];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int getaddr_by_host(const char *host, struct sockaddr *addr, socklen_t *addr_len)
|
||||
{
|
||||
struct addrinfo hints;
|
||||
|
||||
@@ -59,6 +59,11 @@ char *dir_name(char *path);
|
||||
|
||||
char *get_host_by_addr(char *host, int maxsize, struct sockaddr *addr);
|
||||
|
||||
int generate_random_addr(unsigned char *addr, int addr_len, int mask);
|
||||
|
||||
int generate_addr_map(unsigned char *addr_from, unsigned char *addr_to, unsigned char *addr_out, int addr_len,
|
||||
int mask);
|
||||
|
||||
int getaddr_by_host(const char *host, struct sockaddr *addr, socklen_t *addr_len);
|
||||
|
||||
int getsocket_inet(int fd, struct sockaddr *addr, socklen_t *addr_len);
|
||||
|
||||
Reference in New Issue
Block a user