Feature: support local host name & ptr resolve.

This commit is contained in:
Nick Peng
2022-05-21 00:09:18 +08:00
parent dbfe9063e4
commit dae263444f
7 changed files with 584 additions and 39 deletions

View File

@@ -587,6 +587,7 @@ rtt min/avg/max/mdev = 5.954/6.133/6.313/0.195 ms
| force-AAAA-SOA | 强制 AAAA 地址返回 SOA | no | [yes\|no] | force-AAAA-SOA yes |
| force-qtype-SOA | 强制指定 qtype 返回 SOA | qtype id | [<qtypeid> \| ...] | force-qtype-SOA 65 28
| prefetch-domain | 域名预先获取功能 | no | [yes\|no] | prefetch-domain yes |
| dnsmasq-lease-file | 支持读取dnsmasq dhcp文件解析本地主机名功能 | 无 | dnsmasq dhcp lease文件路径 | dnsmasq-lease-file /var/lib/misc/dnsmasq.leases |
| serve-expired | 过期缓存服务功能 | yes | [yes\|no],开启此功能后,如果有请求时尝试回应 TTL 为 0 的过期记录,并发查询记录,以避免查询等待 |
| serve-expired-ttl | 过期缓存服务最长超时时间 | 0 | 秒0 表示停用超时,大于 0 表示指定的超时的秒数 | serve-expired-ttl 0 |
| serve-expired-reply-ttl | 回应的过期缓存 TTL | 5 | 秒0 表示停用超时,大于 0 表示指定的超时的秒数 | serve-expired-reply-ttl 30 |

View File

@@ -531,6 +531,7 @@ Note: Merlin firmware is derived from ASUS firmware and can theoretically be use
|force-AAAA-SOA|force AAAA query return SOA|no|[yes\|no]|force-AAAA-SOA yes
|force-qtype-SOA|force specific qtype return SOA|qtype id|[qtypeid | ...]|force-qtype-SOA 65 28
|prefetch-domain|domain prefetch feature|no|[yes\|no]|prefetch-domain yes
|dnsmasq-lease-file|Support reading dnsmasq dhcp file to resolve local hostname|None|dnsmasq dhcp lease file| dnsmasq-lease-file /var/lib/misc/dnsmasq.leases
|serve-expired|Cache serve expired feature|yes|[yes\|no], Attempts to serve old responses from cache with a TTL of 0 in the response without waiting for the actual resolution to finish.|serve-expired yes
|serve-expired-ttl|Cache serve expired limite TTL|0|second0disable> 0 seconds after expiration|serve-expired-ttl 0
|serve-expired-reply-ttl|TTL value to use when replying with expired data|5|second0disable> 0 seconds after expiration|serve-expired-reply-ttl 30

View File

@@ -28,6 +28,7 @@
#include <string.h>
#include <syslog.h>
#include <unistd.h>
#include <errno.h>
#define DEFAULT_DNS_CACHE_SIZE 512
@@ -42,6 +43,14 @@ struct dns_qtype_soa_table dns_qtype_soa_table;
/* dns groups */
struct dns_group_table dns_group_table;
struct dns_ptr_table dns_ptr_table;
char dns_conf_dnsmasq_lease_file[DNS_MAX_PATH];
time_t dns_conf_dnsmasq_lease_file_time;
struct dns_hosts_table dns_hosts_table;
int dns_hosts_record_num;
/* server ip/port */
struct dns_bind_ip dns_conf_bind_ip[DNS_MAX_BIND_IP];
int dns_conf_bind_ip_num = 0;
@@ -1429,6 +1438,342 @@ errout:
return -1;
}
static struct dns_ptr *_dns_conf_get_ptr(const char *ptr_domain)
{
uint32_t key = 0;
struct dns_ptr *ptr = NULL;
key = hash_string(ptr_domain);
hash_for_each_possible(dns_ptr_table.ptr, ptr, node, key)
{
if (strncmp(ptr->ptr_domain, ptr_domain, DNS_MAX_CNAME_LEN) != 0) {
continue;
}
return ptr;
}
ptr = malloc(sizeof(*ptr));
if (ptr == NULL) {
goto errout;
}
safe_strncpy(ptr->ptr_domain, ptr_domain, DNS_MAX_PTR_LEN);
hash_add(dns_ptr_table.ptr, &ptr->node, key);
return ptr;
errout:
if (ptr) {
free(ptr);
}
return NULL;
}
static int _conf_ptr_add(const char *hostname, const char *ip)
{
struct dns_ptr *ptr = NULL;
struct sockaddr_storage addr;
unsigned char *paddr;
socklen_t addr_len = sizeof(addr);
char ptr_domain[DNS_MAX_PTR_LEN];
if (getaddr_by_host(ip, (struct sockaddr *)&addr, &addr_len) != 0) {
goto errout;
}
switch (addr.ss_family) {
case AF_INET: {
struct sockaddr_in *addr_in;
addr_in = (struct sockaddr_in *)&addr;
paddr = (unsigned char *)&(addr_in->sin_addr.s_addr);
snprintf(ptr_domain, sizeof(ptr_domain), "%d.%d.%d.%d.in-addr.arpa",
paddr[3], paddr[2], paddr[1], paddr[0]);
} break;
case AF_INET6: {
struct sockaddr_in6 *addr_in6;
addr_in6 = (struct sockaddr_in6 *)&addr;
if (IN6_IS_ADDR_V4MAPPED(&addr_in6->sin6_addr)) {
paddr = addr_in6->sin6_addr.s6_addr + 12;
snprintf(ptr_domain, sizeof(ptr_domain), "%d.%d.%d.%d.in-addr.arpa",
paddr[3], paddr[2], paddr[1], paddr[0]);
} else {
paddr = addr_in6->sin6_addr.s6_addr;
snprintf(
ptr_domain, sizeof(ptr_domain),
"%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x."
"%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x."
"%x.ip6.arpa",
paddr[15] & 0xF, (paddr[15] >> 4) & 0xF, paddr[14] & 0xF,
(paddr[14] >> 4) & 0xF, paddr[13] & 0xF, (paddr[13] >> 4) & 0xF,
paddr[12] & 0xF, (paddr[12] >> 4) & 0xF, paddr[11] & 0xF,
(paddr[11] >> 4) & 0xF, paddr[10] & 0xF, (paddr[10] >> 4) & 0xF,
paddr[9] & 0xF, (paddr[9] >> 4) & 0xF, paddr[8] & 0xF,
(paddr[8] >> 4) & 0xF, paddr[7] & 0xF, (paddr[7] >> 4) & 0xF,
paddr[6] & 0xF, (paddr[6] >> 4) & 0xF, paddr[5] & 0xF,
(paddr[5] >> 4) & 0xF, paddr[4] & 0xF, (paddr[4] >> 4) & 0xF,
paddr[3] & 0xF, (paddr[3] >> 4) & 0xF, paddr[2] & 0xF,
(paddr[2] >> 4) & 0xF, paddr[1] & 0xF, (paddr[1] >> 4) & 0xF,
paddr[0] & 0xF, (paddr[0] >> 4) & 0xF);
}
} break;
default:
goto errout;
break;
}
ptr = _dns_conf_get_ptr(ptr_domain);
if (ptr == NULL) {
goto errout;
}
safe_strncpy(ptr->hostname, hostname, DNS_MAX_CNAME_LEN);
return 0;
errout:
return -1;
}
static void _config_ptr_table_destroy(void)
{
struct dns_ptr *ptr = NULL;
struct hlist_node *tmp = NULL;
int i;
hash_for_each_safe(dns_ptr_table.ptr, i, tmp, ptr, node)
{
hlist_del_init(&ptr->node);
free(ptr);
}
}
static struct dns_hosts *_dns_conf_get_hosts(const char *hostname, int dns_type)
{
uint32_t key = 0;
struct dns_hosts *host = NULL;
char hostname_lower[DNS_MAX_CNAME_LEN];
key = hash_string(to_lower_case(hostname_lower, hostname, DNS_MAX_CNAME_LEN));
key = jhash(&dns_type, sizeof(dns_type), key);
hash_for_each_possible(dns_hosts_table.hosts, host, node, key)
{
if (host->dns_type != dns_type) {
continue;
}
if (strncmp(host->domain, hostname_lower, DNS_MAX_CNAME_LEN) != 0) {
continue;
}
return host;
}
host = malloc(sizeof(*host));
if (host == NULL) {
goto errout;
}
safe_strncpy(host->domain, hostname_lower, DNS_MAX_CNAME_LEN);
host->dns_type = dns_type;
host->is_soa = 1;
hash_add(dns_hosts_table.hosts, &host->node, key);
return host;
errout:
if (host) {
free(host);
}
return NULL;
}
static int _conf_host_add(const char *hostname, const char *ip, dns_hosts_type host_type)
{
struct dns_hosts *host = NULL;
struct dns_hosts *host_other __attribute__((unused));;
struct sockaddr_storage addr;
socklen_t addr_len = sizeof(addr);
int dns_type = 0;
int dns_type_other = 0;
if (getaddr_by_host(ip, (struct sockaddr *)&addr, &addr_len) != 0) {
goto errout;
}
switch (addr.ss_family) {
case AF_INET:
dns_type = DNS_T_A;
dns_type_other = DNS_T_AAAA;
break;
case AF_INET6: {
struct sockaddr_in6 *addr_in6;
addr_in6 = (struct sockaddr_in6 *)&addr;
if (IN6_IS_ADDR_V4MAPPED(&addr_in6->sin6_addr)) {
dns_type = DNS_T_A;
dns_type_other = DNS_T_AAAA;
} else {
dns_type = DNS_T_AAAA;
dns_type_other = DNS_T_A;
}
} break;
default:
goto errout;
break;
}
host = _dns_conf_get_hosts(hostname, dns_type);
if (host == NULL) {
goto errout;
}
/* add this to return SOA when addr is not exist */
host_other = _dns_conf_get_hosts(hostname, dns_type_other);
host->host_type = host_type;
switch (addr.ss_family) {
case AF_INET: {
struct sockaddr_in *addr_in;
addr_in = (struct sockaddr_in *)&addr;
memcpy(host->ipv4_addr, &addr_in->sin_addr.s_addr, 4);
host->is_soa = 0;
} break;
case AF_INET6: {
struct sockaddr_in6 *addr_in6;
addr_in6 = (struct sockaddr_in6 *)&addr;
if (IN6_IS_ADDR_V4MAPPED(&addr_in6->sin6_addr)) {
memcpy(host->ipv4_addr, addr_in6->sin6_addr.s6_addr + 12, 4);
} else {
memcpy(host->ipv6_addr, addr_in6->sin6_addr.s6_addr, 16);
}
host->is_soa = 0;
} break;
default:
goto errout;
}
dns_hosts_record_num++;
return 0;
errout:
return -1;
}
static int _conf_dhcp_lease_dnsmasq_add(const char *file)
{
FILE *fp = NULL;
char line[MAX_LINE_LEN];
char ip[DNS_MAX_IPLEN];
char hostname[DNS_MAX_CNAME_LEN];
int ret = 0;
int line_no = 0;
int filed_num;
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, "%*s %*s %64s %256s %*s", ip, hostname);
if (filed_num <= 0) {
continue;
}
if (strncmp(hostname, "*", DNS_MAX_CNAME_LEN) == 0) {
continue;
}
ret = _conf_host_add(hostname, ip, DNS_HOST_TYPE_DNSMASQ);
if (ret != 0) {
tlog(TLOG_WARN, "add host %s/%s at %d failed", hostname, ip, line_no);
}
ret = _conf_ptr_add(hostname, ip);
if (ret != 0) {
tlog(TLOG_WARN, "add ptr %s/%s at %d failed.", hostname, ip, line_no);
}
}
fclose(fp);
return 0;
}
static int _conf_dhcp_lease_dnsmasq_file(void *data, int argc, char *argv[])
{
struct stat statbuf;
if (argc < 1) {
return -1;
}
safe_strncpy(dns_conf_dnsmasq_lease_file, argv[1], DNS_MAX_PATH);
if (_conf_dhcp_lease_dnsmasq_add(argv[1]) != 0) {
return -1;
}
if (stat(dns_conf_dnsmasq_lease_file, &statbuf) != 0) {
return 0;
}
dns_conf_dnsmasq_lease_file_time = statbuf.st_mtime;
return 0;
}
static int _conf_hosts_file(void *data, int argc, char *argv[])
{
return 0;
}
static void _config_host_table_destroy(void)
{
struct dns_hosts *host = NULL;
struct hlist_node *tmp = NULL;
int i;
hash_for_each_safe(dns_hosts_table.hosts, i, tmp, host, node)
{
hlist_del_init(&host->node);
free(host);
}
dns_hosts_record_num = 0;
}
int dns_server_check_update_hosts(void)
{
struct stat statbuf;
time_t now;
if (stat(dns_conf_dnsmasq_lease_file, &statbuf) != 0) {
return -1;
}
if (dns_conf_dnsmasq_lease_file_time == statbuf.st_mtime) {
return -1;
}
time(&now);
if (now - statbuf.st_mtime < 30) {
return -1;
}
_config_ptr_table_destroy();
_config_host_table_destroy();
if (_conf_dhcp_lease_dnsmasq_add(dns_conf_dnsmasq_lease_file) != 0) {
return -1;
}
dns_conf_dnsmasq_lease_file_time = statbuf.st_mtime;
return 0;
}
static int _config_log_level(void *data, int argc, char *argv[])
{
/* read log level and set */
@@ -1497,6 +1842,8 @@ static struct config_item _config_item[] = {
CONF_CUSTOM("ignore-ip", _conf_ip_ignore, NULL),
CONF_CUSTOM("edns-client-subnet", _conf_edns_client_subnet, NULL),
CONF_CUSTOM("domain-rules", _conf_domain_rules, NULL),
CONF_CUSTOM("dnsmasq-lease-file", _conf_dhcp_lease_dnsmasq_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-path", (char *)&dns_conf_ca_path, DNS_MAX_PATH),
CONF_CUSTOM("conf-file", config_addtional_file, NULL),
@@ -1520,10 +1867,15 @@ static int _conf_printf(const char *file, int lineno, int ret)
int config_addtional_file(void *data, int argc, char *argv[])
{
char *conf_file = argv[1];
char *conf_file;
char file_path[DNS_MAX_PATH];
char file_path_dir[DNS_MAX_PATH];
if (argc < 1) {
return -1;
}
conf_file = argv[1];
if (conf_file[0] != '/') {
safe_strncpy(file_path_dir, conf_get_conf_file(), DNS_MAX_PATH);
dirname(file_path_dir);
@@ -1563,6 +1915,8 @@ static int _dns_server_load_conf_init(void)
hash_init(dns_ipset_table.ipset);
hash_init(dns_qtype_soa_table.qtype);
hash_init(dns_group_table.group);
hash_init(dns_hosts_table.hosts);
hash_init(dns_ptr_table.ptr);
return 0;
}
@@ -1574,6 +1928,8 @@ void dns_server_load_exit(void)
Destroy_Radix(dns_conf_address_rule.ipv6, _config_address_destroy, NULL);
_config_ipset_table_destroy();
_config_group_table_destroy();
_config_ptr_table_destroy();
_config_host_table_destroy();
_config_qtype_soa_table_destroy();
}

View File

@@ -35,6 +35,7 @@ extern "C" {
#define DNS_MAX_BIND_IP 16
#define DNS_MAX_SERVERS 64
#define DNS_MAX_SERVER_NAME_LEN 128
#define DNS_MAX_PTR_LEN 128
#define DNS_MAX_IPSET_NAMELEN 32
#define DNS_GROUP_NAME_LEN 32
#define DNS_NAX_GROUP_NUMBER 16
@@ -145,6 +146,40 @@ struct dns_group_table {
};
extern struct dns_group_table dns_group_table;
struct dns_ptr {
struct hlist_node node;
char ptr_domain[DNS_MAX_PTR_LEN];
char hostname[DNS_MAX_CNAME_LEN];
};
struct dns_ptr_table {
DECLARE_HASHTABLE(ptr, 16);
};
extern struct dns_ptr_table dns_ptr_table;
typedef enum dns_hosts_type {
DNS_HOST_TYPE_HOST = 0,
DNS_HOST_TYPE_DNSMASQ = 1,
} dns_hosts_type;
struct dns_hosts {
struct hlist_node node;
char domain[DNS_MAX_CNAME_LEN];
dns_hosts_type host_type;
int dns_type;
int is_soa;
union {
unsigned char ipv4_addr[DNS_RR_A_LEN];
unsigned char ipv6_addr[DNS_RR_AAAA_LEN];
};
};
struct dns_hosts_table {
DECLARE_HASHTABLE(hosts, 16);
};
extern struct dns_hosts_table dns_hosts_table;
extern int dns_hosts_record_num;
struct dns_servers {
char server[DNS_MAX_IPLEN];
unsigned short port;
@@ -270,6 +305,8 @@ void dns_server_load_exit(void);
int dns_server_load_conf(const char *file);
int dns_server_check_update_hosts(void);
extern int config_addtional_file(void *data, int argc, char *argv[]);
#ifdef __cpluscplus
}

View File

@@ -192,6 +192,7 @@ struct dns_request {
int has_ping_result;
int has_ping_tcp;
int has_ptr;
char ptr_hostname[DNS_MAX_CNAME_LEN];
int has_cname;
char cname[DNS_MAX_CNAME_LEN];
@@ -639,32 +640,7 @@ static int _dns_add_rrs(struct dns_server_post_context *context)
char *domain = request->domain;
if (request->has_ptr) {
/* add PTR record */
char hostname[DNS_MAX_CNAME_LEN];
if (dns_conf_server_name[0] == 0) {
/* get local host name */
if (getdomainname(hostname, DNS_MAX_CNAME_LEN) != 0) {
if (gethostname(hostname, DNS_MAX_CNAME_LEN) != 0) {
return -1;
}
}
/* get host name again */
if (strncmp(hostname, "(none)", DNS_MAX_CNAME_LEN) == 0) {
if (gethostname(hostname, DNS_MAX_CNAME_LEN) != 0) {
return -1;
}
}
/* if hostname is (none), return smartdns */
if (strncmp(hostname, "(none)", DNS_MAX_CNAME_LEN) == 0) {
safe_strncpy(hostname, "smartdns", DNS_MAX_CNAME_LEN);
}
} else {
/* return configured server name */
safe_strncpy(hostname, dns_conf_server_name, DNS_MAX_CNAME_LEN);
}
ret = dns_add_PTR(context->packet, DNS_RRS_AN, request->domain, 30, hostname);
ret = dns_add_PTR(context->packet, DNS_RRS_AN, request->domain, 30, request->ptr_hostname);
}
/* add CNAME record */
@@ -2478,7 +2454,35 @@ static int dns_server_resolve_callback(char *domain, dns_result_type rtype, unsi
return 0;
}
static int _dns_server_process_ptr(struct dns_request *request)
static int _dns_server_process_ptrs(struct dns_request *request)
{
uint32_t key = 0;
struct dns_ptr *ptr = NULL;
struct dns_ptr *ptr_tmp = NULL;
key = hash_string(request->domain);
hash_for_each_possible(dns_ptr_table.ptr, ptr_tmp, node, key)
{
if (strncmp(ptr_tmp->ptr_domain, request->domain, DNS_MAX_CNAME_LEN) != 0) {
continue;
}
ptr = ptr_tmp;
break;
}
if (ptr == NULL) {
goto errout;
}
request->has_ptr = 1;
safe_strncpy(request->ptr_hostname, ptr->hostname, DNS_MAX_CNAME_LEN);
return 0;
errout:
return -1;
}
static int _dns_server_process_local_ptr(struct dns_request *request)
{
struct ifaddrs *ifaddr = NULL;
struct ifaddrs *ifa = NULL;
@@ -2530,19 +2534,21 @@ static int _dns_server_process_ptr(struct dns_request *request)
break;
}
if (strstr(request->domain, reverse_addr) != NULL) {
if (strncmp(request->domain, reverse_addr, DNS_MAX_CNAME_LEN) == 0) {
found = 1;
break;
}
}
/* Determine if the smartdns service is in effect. */
if (strstr(request->domain, "0.0.0.0.in-addr.arpa") != NULL) {
if (strncmp(request->domain, "0.0.0.0.in-addr.arpa", DNS_MAX_CNAME_LEN) ==
0) {
found = 1;
}
/* Determine if the smartdns service is in effect. */
if (found == 0 && strncmp(request->domain, "smartdns", sizeof("smartdns")) == 0) {
if (found == 0 &&
strncmp(request->domain, "smartdns", sizeof("smartdns")) == 0) {
found = 1;
}
@@ -2550,13 +2556,33 @@ static int _dns_server_process_ptr(struct dns_request *request)
goto errout;
}
request->rcode = DNS_RC_NOERROR;
char hostname[DNS_MAX_CNAME_LEN];
if (dns_conf_server_name[0] == 0) {
/* get local host name */
if (getdomainname(hostname, DNS_MAX_CNAME_LEN) != 0) {
if (gethostname(hostname, DNS_MAX_CNAME_LEN) != 0) {
return -1;
}
}
/* get host name again */
if (strncmp(hostname, "(none)", DNS_MAX_CNAME_LEN) == 0) {
if (gethostname(hostname, DNS_MAX_CNAME_LEN) != 0) {
return -1;
}
}
/* if hostname is (none), return smartdns */
if (strncmp(hostname, "(none)", DNS_MAX_CNAME_LEN) == 0) {
safe_strncpy(hostname, "smartdns", DNS_MAX_CNAME_LEN);
}
} else {
/* return configured server name */
safe_strncpy(hostname, dns_conf_server_name, DNS_MAX_CNAME_LEN);
}
request->has_ptr = 1;
struct dns_server_post_context context;
_dns_server_post_context_init(&context, request);
context.do_reply = 1;
context.do_audit = 0;
_dns_request_post(&context);
safe_strncpy(request->ptr_hostname, hostname, DNS_MAX_CNAME_LEN);
freeifaddrs(ifaddr);
return 0;
@@ -2567,6 +2593,28 @@ errout:
return -1;
}
static int _dns_server_process_ptr(struct dns_request *request)
{
if (_dns_server_process_ptrs(request) == 0) {
goto reply_exit;
}
if (_dns_server_process_local_ptr(request) == 0) {
goto reply_exit;
}
return -1;
reply_exit:
request->rcode = DNS_RC_NOERROR;
struct dns_server_post_context context;
_dns_server_post_context_init(&context, request);
context.do_reply = 1;
context.do_audit = 0;
_dns_request_post(&context);
return 0;
}
static void _dns_server_log_rule(const char *domain, enum domain_rule rule_type, unsigned char *rule_key,
int rule_key_len)
{
@@ -3199,6 +3247,71 @@ static void _dns_server_check_set_passthrough(struct dns_request *request)
}
}
static int _dns_server_process_host(struct dns_request *request)
{
uint32_t key = 0;
struct dns_hosts *host = NULL;
struct dns_hosts *host_tmp = NULL;
int dns_type = request->qtype;
char hostname_lower[DNS_MAX_CNAME_LEN];
if (dns_hosts_record_num <= 0) {
return -1;
}
key = hash_string(to_lower_case(hostname_lower, request->domain, DNS_MAX_CNAME_LEN));
key = jhash(&dns_type, sizeof(dns_type), key);
hash_for_each_possible(dns_hosts_table.hosts, host_tmp, node, key)
{
if (host_tmp->dns_type != dns_type) {
continue;
}
if (strncmp(host_tmp->domain, hostname_lower, DNS_MAX_CNAME_LEN) != 0) {
continue;
}
host = host_tmp;
break;
}
if (host == NULL) {
return -1;
}
if (host->is_soa) {
request->has_soa = 1;
return _dns_server_reply_SOA(DNS_RC_NOERROR, request);
}
switch (request->qtype) {
case DNS_T_A:
memcpy(request->ipv4_addr, host->ipv4_addr, DNS_RR_A_LEN);
request->ttl_v4 = 600;
request->has_ipv4 = 1;
break;
case DNS_T_AAAA:
memcpy(request->ipv6_addr, host->ipv6_addr, DNS_RR_AAAA_LEN);
request->ttl_v6 = 600;
request->has_ipv6 = 1;
break;
default:
goto errout;
break;
}
request->rcode = DNS_RC_NOERROR;
struct dns_server_post_context context;
_dns_server_post_context_init(&context, request);
context.do_reply = 1;
context.do_audit = 1;
_dns_request_post(&context);
return 0;
errout:
return -1;
}
static int _dns_server_do_query(struct dns_request *request, const char *domain, int qtype)
{
int ret = -1;
@@ -3219,6 +3332,10 @@ static int _dns_server_do_query(struct dns_request *request, const char *domain,
group_name = dns_group;
}
if (_dns_server_process_host(request) == 0) {
goto clean_exit;
}
_dns_server_set_dualstack_selection(request);
if (_dns_server_process_special_query(request) == 0) {
@@ -3873,6 +3990,12 @@ static void _dns_server_period_run_second(void)
if (sec % IPV6_READY_CHECK_TIME == 0 && is_ipv6_ready == 0) {
_dns_server_check_ipv6_ready();
}
if (sec % 60 == 0) {
if (dns_server_check_update_hosts() == 0) {
tlog(TLOG_INFO, "Update host file data");
}
}
}
static void _dns_server_period_run(void)

View File

@@ -133,7 +133,7 @@ errout:
return NULL;
}
int getaddr_by_host(char *host, struct sockaddr *addr, socklen_t *addr_len)
int getaddr_by_host(const char *host, struct sockaddr *addr, socklen_t *addr_len)
{
struct addrinfo hints;
struct addrinfo *result = NULL;
@@ -473,6 +473,31 @@ char *reverse_string(char *output, const char *input, int len, int to_lower_case
return begin;
}
char *to_lower_case(char *output, const char *input, int len)
{
char *begin = output;
int i = 0;
if (len <= 0) {
*output = 0;
return output;
}
len--;
while (i < len && *(input + i) != '\0') {
*output = *(input + i);
if (*output >= 'A' && *output <= 'Z') {
/* To lower case */
*output = *output + 32;
}
output++;
i++;
}
*output = 0;
return begin;
}
static inline void _ipset_add_attr(struct nlmsghdr *netlink_head, uint16_t type, size_t len, const void *data)
{
struct ipset_netlink_attr *attr = (void *)netlink_head + NETLINK_ALIGN(netlink_head->nlmsg_len);

View File

@@ -49,7 +49,7 @@ unsigned long get_tick_count(void);
char *gethost_by_addr(char *host, int maxsize, struct sockaddr *addr);
int getaddr_by_host(char *host, struct sockaddr *addr, socklen_t *addr_len);
int getaddr_by_host(const char *host, struct sockaddr *addr, socklen_t *addr_len);
int getsocknet_inet(int fd, struct sockaddr *addr, socklen_t *addr_len);
@@ -65,6 +65,8 @@ int set_fd_nonblock(int fd, int nonblock);
char *reverse_string(char *output, const char *input, int len, int to_lower_case);
char *to_lower_case(char *output, const char *input, int len);
void print_stack(void);
int ipset_add(const char *ipsetname, const unsigned char addr[], int addr_len, unsigned long timeout);