Optimize configuration, and add blacklist ip features

This commit is contained in:
Nick Peng
2018-12-14 20:50:07 +08:00
parent d6911608fc
commit 62f331c153
25 changed files with 1138 additions and 946 deletions

View File

@@ -1,7 +1,7 @@
BIN=smartdns
OBJS_LIB=lib/rbtree.o lib/art.o lib/bitops.o lib/radix.o
OBJS=smartdns.o fast_ping.o dns_client.o dns_server.o dns.o util.o tlog.o conf.o dns_cache.o $(OBJS_LIB)
OBJS_LIB=lib/rbtree.o lib/art.o lib/bitops.o lib/radix.o lib/conf.o
OBJS=smartdns.o fast_ping.o dns_client.o dns_server.o dns.o util.o tlog.o dns_conf.o dns_cache.o $(OBJS_LIB)
CFLAGS +=-O2 -Wall -Wstrict-prototypes -fno-omit-frame-pointer -Wstrict-aliasing
CFLAGS +=-Iinclude
CFLAGS += -DBASE_FILE_NAME=\"$(notdir $<)\"

View File

@@ -1,738 +0,0 @@
#include "conf.h"
#include "list.h"
#include "rbtree.h"
#include "tlog.h"
#include "util.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define MAX_LINE_LEN 1024
#define MAX_KEY_LEN 64
#define DEFAULT_DNS_CACHE_SIZE 512
char dns_conf_server_ip[DNS_MAX_IPLEN];
char dns_conf_server_tcp_ip[DNS_MAX_IPLEN];
int dns_conf_tcp_idle_time = 120;
int dns_conf_cachesize = DEFAULT_DNS_CACHE_SIZE;
int dns_conf_prefetch = 0;
struct dns_servers dns_conf_servers[DNS_MAX_SERVERS];
struct dns_bogus_nxdomain dns_conf_bogus_nxdomain;
char dns_conf_server_name[DNS_MAX_CONF_CNAME_LEN];
int dns_conf_server_num;
int dns_conf_log_level = TLOG_ERROR;
char dns_conf_log_file[DNS_MAX_PATH];
int dns_conf_log_size = 1024 * 1024;
int dns_conf_log_num = 8;
int dns_conf_audit_enable = 0;
char dns_conf_audit_file[DNS_MAX_PATH];
int dns_conf_audit_size = 1024 * 1024;
int dns_conf_audit_num = 2;
art_tree dns_conf_domain_rule;
radix_tree_t *dns_conf_address_rule;
int dns_conf_rr_ttl;
int dns_conf_rr_ttl_min;
int dns_conf_rr_ttl_max;
int dns_conf_force_AAAA_SOA;
int load_conf_file(const char *file);
int config_bind(char *value)
{
/* server bind address */
strncpy(dns_conf_server_ip, value, DNS_MAX_IPLEN);
return 0;
}
int config_bind_tcp(char *value)
{
/* server bind address */
strncpy(dns_conf_server_tcp_ip, value, DNS_MAX_IPLEN);
return 0;
}
int config_server_name(char *value)
{
strncpy(dns_conf_server_name, value, DNS_MAX_CONF_CNAME_LEN);
return 0;
}
int config_server(char *value, dns_server_type_t type, int default_port)
{
int index = dns_conf_server_num;
struct dns_servers *server;
int port = -1;
if (index >= DNS_MAX_SERVERS) {
tlog(TLOG_ERROR, "exceeds max server number");
return -1;
}
server = &dns_conf_servers[index];
/* parse ip, port from value */
if (parse_ip(value, server->server, &port) != 0) {
return -1;
}
/* if port is not defined, set port to default 53 */
if (port == PORT_NOT_DEFINED) {
port = default_port;
}
server->type = type;
server->port = port;
dns_conf_server_num++;
return 0;
}
int config_domain_iter_cb(void *data, const unsigned char *key, uint32_t key_len, void *value)
{
free(value);
return 0;
}
void config_domain_destroy(void)
{
art_iter(&dns_conf_domain_rule, config_domain_iter_cb, 0);
art_tree_destroy(&dns_conf_domain_rule);
}
void config_address_destroy(radix_node_t *node, void *cbctx)
{
if (node == NULL) {
return;
}
if (node->data == NULL) {
return;
}
free(node->data);
node->data = NULL;
}
int config_address(char *value)
{
struct dns_address *address = NULL;
struct dns_address *oldaddress;
char ip[MAX_IP_LEN];
char domain_key[DNS_MAX_CONF_CNAME_LEN];
char domain[DNS_MAX_CONF_CNAME_LEN];
char *begin = NULL;
char *end = NULL;
int len = 0;
int port;
struct sockaddr_storage addr;
socklen_t addr_len = sizeof(addr);
char type = '4';
begin = strstr(value, "/");
if (begin == NULL) {
goto errout;
}
begin++;
end = strstr(begin, "/");
if (end == NULL) {
goto errout;
}
address = malloc(sizeof(*address));
if (address == NULL) {
goto errout;
}
/* remove prefix . */
while (*begin == '.') {
begin++;
}
memset(address, 0, sizeof(*address));
len = end - begin;
memcpy(domain + 1, begin, len);
/* add dot for subdomain */
domain[0] = '.';
len++;
domain[len] = 0;
reverse_string(domain_key + 1, domain, len);
if (parse_ip(end + 1, ip, &port) != 0) {
goto errout;
}
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;
memcpy(address->ipv4_addr, &addr_in->sin_addr.s_addr, 4);
address->addr_type = DNS_T_A;
type = '4';
} 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(address->ipv4_addr, addr_in6->sin6_addr.s6_addr + 12, 4);
address->addr_type = DNS_T_A;
type = '4';
} else {
memcpy(address->ipv6_addr, addr_in6->sin6_addr.s6_addr, 16);
address->addr_type = DNS_T_AAAA;
type = '6';
}
} break;
default:
goto errout;
}
domain_key[0] = type;
len++;
oldaddress = art_insert(&dns_conf_domain_rule, (unsigned char *)domain_key, len, address);
if (oldaddress) {
free(oldaddress);
}
return 0;
errout:
if (address) {
free(address);
}
tlog(TLOG_ERROR, "add address %s failed", value);
return 0;
}
int config_server_udp(char *value)
{
return config_server(value, DNS_SERVER_UDP, DEFAULT_DNS_PORT);
}
int config_server_tcp(char *value)
{
return config_server(value, DNS_SERVER_TCP, DEFAULT_DNS_PORT);
}
int config_tcp_idle_time(char *value)
{
/* read dns cache size */
int idle_time = atoi(value);
if (idle_time < 0) {
return -1;
}
dns_conf_tcp_idle_time = idle_time;
return 0;
}
int config_server_tls(char *value)
{
return config_server(value, DNS_SERVER_TLS, DEFAULT_DNS_TLS_PORT);
}
int config_cache_size(char *value)
{
/* read dns cache size */
int cache_size = atoi(value);
if (cache_size < 0) {
return -1;
}
dns_conf_cachesize = cache_size;
return 0;
}
int config_cache_prefetch_domain(char *value)
{
/* read dns cache size */
if (strncmp("yes", value, sizeof("yes")) == 0 || strncmp("YES", value, sizeof("YES")) == 0) {
dns_conf_prefetch = 1;
} else if (strncmp("no", value, sizeof("no")) == 0 || strncmp("NO", value, sizeof("NO")) == 0) {
dns_conf_prefetch = 0;
}
return 0;
}
int config_force_AAAA_SOA(char *value)
{
/* read dns cache size */
if (strncmp("yes", value, sizeof("yes")) == 0 || strncmp("YES", value, sizeof("YES")) == 0) {
dns_conf_force_AAAA_SOA = 1;
} else if (strncmp("no", value, sizeof("no")) == 0 || strncmp("NO", value, sizeof("NO")) == 0) {
dns_conf_force_AAAA_SOA = 0;
}
return 0;
}
int config_log_level(char *value)
{
/* read log level and set */
if (strncmp("debug", value, MAX_LINE_LEN) == 0) {
dns_conf_log_level = TLOG_DEBUG;
} else if (strncmp("info", value, MAX_LINE_LEN) == 0) {
dns_conf_log_level = TLOG_INFO;
} else if (strncmp("warn", value, MAX_LINE_LEN) == 0) {
dns_conf_log_level = TLOG_WARN;
} else if (strncmp("error", value, MAX_LINE_LEN) == 0) {
dns_conf_log_level = TLOG_ERROR;
} else {
return -1;
}
return 0;
}
int config_log_file(char *value)
{
/* read dns cache size */
strncpy(dns_conf_log_file, value, DNS_MAX_PATH);
return 0;
}
int config_log_size(char *value)
{
/* read dns cache size */
int base = 1;
if (strstr(value, "k") || strstr(value, "K")) {
base = 1024;
} else if (strstr(value, "m") || strstr(value, "M")) {
base = 1024 * 1024;
} else if (strstr(value, "g") || strstr(value, "G")) {
base = 1024 * 1024 * 1024;
}
int size = atoi(value);
if (size < 0) {
return -1;
}
dns_conf_log_size = size * base;
return 0;
}
int config_log_num(char *value)
{
/* read dns cache size */
int num = atoi(value);
if (num < 0) {
return -1;
}
dns_conf_log_num = num;
return 0;
}
int config_audit_enable(char *value)
{
/* read dns cache size */
if (strncmp("yes", value, sizeof("yes")) == 0 || strncmp("YES", value, sizeof("YES")) == 0) {
dns_conf_audit_enable = 1;
} else if (strncmp("no", value, sizeof("no")) == 0 || strncmp("NO", value, sizeof("NO")) == 0) {
dns_conf_audit_enable = 0;
}
return 0;
}
int config_audit_file(char *value)
{
/* read dns cache size */
strncpy(dns_conf_audit_file, value, DNS_MAX_PATH);
return 0;
}
int config_audit_size(char *value)
{
/* read dns cache size */
int base = 1;
if (strstr(value, "k") || strstr(value, "K")) {
base = 1024;
} else if (strstr(value, "m") || strstr(value, "M")) {
base = 1024 * 1024;
} else if (strstr(value, "g") || strstr(value, "G")) {
base = 1024 * 1024 * 1024;
}
int size = atoi(value);
if (size < 0) {
return -1;
}
dns_conf_audit_size = size * base;
return 0;
}
int config_audit_num(char *value)
{
/* read dns cache size */
int num = atoi(value);
if (num < 0) {
return -1;
}
dns_conf_audit_num = num;
return 0;
}
int config_rr_ttl(char *value)
{
/* read dns cache size */
int ttl = atoi(value);
if (ttl < 0) {
return -1;
}
dns_conf_rr_ttl = ttl;
return 0;
}
int config_rr_ttl_min(char *value)
{
/* read dns cache size */
int ttl = atoi(value);
if (ttl < 0) {
return -1;
}
dns_conf_rr_ttl_min = ttl;
return 0;
}
int config_rr_ttl_max(char *value)
{
/* read dns cache size */
int ttl = atoi(value);
if (ttl < 0) {
return -1;
}
dns_conf_rr_ttl_max = ttl;
return 0;
}
int dns_bogus_nxdomain_exists(unsigned char *ip, dns_type_t addr_type)
{
uint32_t key = 0;
struct dns_bogus_ip_address *ip_addr = NULL;
int addr_len = 0;
if (addr_type == DNS_T_A) {
addr_len = 4;
} else if (addr_type == DNS_T_AAAA) {
addr_len = 16;
} else {
return -1;
}
key = jhash(ip, addr_len, 0);
hash_for_each_possible(dns_conf_bogus_nxdomain.ip_hash, ip_addr, node, key)
{
if (addr_type == DNS_T_A) {
if (memcmp(ip_addr->ipv4_addr, ip, addr_len) == 0) {
return 0;
}
} else if (addr_type == DNS_T_AAAA) {
if (memcmp(ip_addr->ipv6_addr, ip, addr_len) == 0) {
return 0;
}
}
}
return -1;
}
void conf_bogus_nxdomain_destroy(void)
{
struct dns_bogus_ip_address *ip_addr = NULL;
struct hlist_node *tmp = NULL;
int i;
hash_for_each_safe(dns_conf_bogus_nxdomain.ip_hash, i, tmp, ip_addr, node)
{
hlist_del_init(&ip_addr->node);
free(ip_addr);
}
}
radix_node_t *create_addr_node(radix_tree_t *tree, char *addr)
{
radix_node_t *node;
void *p;
prefix_t prefix;
const char *errmsg = NULL;
p = prefix_pton(addr, -1, &prefix, &errmsg);
if (p == NULL) {
return NULL;
}
node = radix_lookup(tree, &prefix);
return node;
}
int config_iplist_action(char *subnet, enum address_action act)
{
radix_node_t *node = NULL;
struct dns_ip_address_rule *ip_rule = NULL;
node = create_addr_node(dns_conf_address_rule, subnet);
if (node == NULL) {
return -1;
}
if (node->data == NULL) {
ip_rule = malloc(sizeof(*ip_rule));
if (ip_rule == NULL) {
return -1;
}
node->data = ip_rule;
memset(ip_rule, 0, sizeof(*ip_rule));
}
ip_rule = node->data;
switch (act) {
case ACTION_BLACKLIST:
ip_rule->blacklist = 1;
break;
case ACTION_BOGUS:
ip_rule->bogus = 1;
break;
}
return 0;
}
int config_blacklist_ip(char *value)
{
return config_iplist_action(value, ACTION_BLACKLIST);
}
int conf_bogus_nxdomain(char *value)
{
//////////////////////////////////////
config_iplist_action(value, ACTION_BOGUS);
//////////////////////////////////////
struct dns_bogus_ip_address *ip_addr = NULL;
char ip[MAX_IP_LEN];
int port;
int ret = -1;
struct sockaddr_storage addr;
socklen_t addr_len = sizeof(addr);
uint32_t key;
ip_addr = malloc(sizeof(*ip_addr));
if (ip_addr == NULL) {
goto errout;
}
memset(ip_addr, 0, sizeof(*ip_addr));
if (parse_ip(value, ip, &port) != 0) {
goto errout;
}
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;
memcpy(ip_addr->ipv4_addr, &addr_in->sin_addr.s_addr, 4);
ip_addr->addr_type = DNS_T_A;
addr_len = 4;
} 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(ip_addr->ipv4_addr, addr_in6->sin6_addr.s6_addr + 12, 4);
ip_addr->addr_type = DNS_T_A;
addr_len = 4;
} else {
memcpy(ip_addr->ipv6_addr, addr_in6->sin6_addr.s6_addr, 16);
addr_len = 16;
}
} break;
default:
goto errout;
}
if (dns_bogus_nxdomain_exists(ip_addr->addr, ip_addr->addr_type) == 0) {
ret = 0;
goto errout;
}
key = jhash(ip_addr->addr, addr_len, 0);
hash_add(dns_conf_bogus_nxdomain.ip_hash, &ip_addr->node, key);
return 0;
errout:
if (ip_addr) {
free(ip_addr);
}
return ret;
}
int config_addtional_file(char *value)
{
char *file_path = value;
if (access(file_path, R_OK) != 0) {
tlog(TLOG_WARN, "conf file %s is not readable.", file_path);
return 0;
}
return load_conf_file(file_path);
}
struct config_item {
const char *item;
int (*item_func)(char *value);
};
struct config_item config_item[] = {
{"server-name", config_server_name},
{"bind", config_bind},
{"bind-tcp", config_bind_tcp},
{"server", config_server_udp},
{"address", config_address},
{"server-tcp", config_server_tcp},
{"tcp-idle-time", config_tcp_idle_time},
{"server-tls", config_server_tls},
{"cache-size", config_cache_size},
{"prefetch-domain", config_cache_prefetch_domain},
{"log-level", config_log_level},
{"log-file", config_log_file},
{"log-size", config_log_size},
{"log-num", config_log_num},
{"audit-enable", config_audit_enable},
{"audit-file", config_audit_file},
{"audit-size", config_audit_size},
{"audit-num", config_audit_num},
{"rr-ttl", config_rr_ttl},
{"rr-ttl-min", config_rr_ttl_min},
{"rr-ttl-max", config_rr_ttl_max},
{"force-AAAA-SOA", config_force_AAAA_SOA},
{"blacklist-ip", config_blacklist_ip},
{"bogus-nxdomain", conf_bogus_nxdomain},
{"conf-file", config_addtional_file},
};
int config_item_num = sizeof(config_item) / sizeof(struct config_item);
int load_conf_init(void)
{
dns_conf_address_rule = New_Radix();
art_tree_init(&dns_conf_domain_rule);
if (dns_conf_address_rule == NULL) {
return -1;
}
hash_init(dns_conf_bogus_nxdomain.ip_hash);
return 0;
}
void load_exit(void)
{
conf_bogus_nxdomain_destroy();
config_domain_destroy();
Destroy_Radix(dns_conf_address_rule, config_address_destroy, NULL);
}
int load_conf_file(const char *file)
{
FILE *fp = NULL;
char line[MAX_LINE_LEN];
char key[MAX_KEY_LEN];
char value[MAX_LINE_LEN];
int filed_num = 0;
int line_num = 0;
int i;
fp = fopen(file, "r");
if (fp == NULL) {
tlog(TLOG_ERROR, "config file %s not exist.", file);
return -1;
}
while (fgets(line, MAX_LINE_LEN, fp)) {
line_num++;
filed_num = sscanf(line, "%63s %1023[^\r\n]s", key, value);
if (filed_num <= 0) {
continue;
}
/* comment, skip */
if (key[0] == '#') {
continue;
}
/* if field format is not key = value, error */
if (filed_num != 2) {
goto errout;
}
for (i = 0; i < config_item_num; i++) {
if (strncmp(config_item[i].item, key, MAX_KEY_LEN) != 0) {
continue;
}
/* call item function */
if (config_item[i].item_func(value) != 0) {
goto errout;
}
break;
}
}
fclose(fp);
return 0;
errout:
printf("invalid config at file %s:%d, %s", file, line_num, line);
tlog(TLOG_ERROR, "invalid config at file %s:%d, %s", file, line_num, line);
if (fp) {
fclose(fp);
}
return -1;
}
int load_conf(const char *file)
{
load_conf_init();
return load_conf_file(file);
}

View File

@@ -33,6 +33,8 @@
#include <netinet/ip.h>
#include <netinet/ip6.h>
#include <netinet/ip_icmp.h>
#include <openssl/err.h>
#include <openssl/ssl.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
@@ -42,8 +44,6 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#define DNS_MAX_HOSTNAME 256
#define DNS_MAX_EVENTS 64
@@ -97,6 +97,7 @@ struct dns_server_info {
SSL *ssl;
SSL_CTX *ssl_ctx;
dns_server_status status;
unsigned int result_flag;
struct dns_server_buff send_buff;
struct dns_server_buff recv_buff;
@@ -155,7 +156,6 @@ struct dns_query_struct {
static struct dns_client client;
static atomic_t dns_client_sid = ATOMIC_INIT(0);
/* get addr info */
static struct addrinfo *_dns_client_getaddr(const char *host, char *port, int type, int protocol)
{
@@ -211,7 +211,7 @@ int _dns_client_server_exist(struct addrinfo *gai, dns_server_type_t server_type
}
/* add dns server information */
int _dns_client_server_add(char *server_ip, struct addrinfo *gai, dns_server_type_t server_type)
int _dns_client_server_add(char *server_ip, struct addrinfo *gai, dns_server_type_t server_type, int result_flag)
{
struct dns_server_info *server_info = NULL;
@@ -229,6 +229,7 @@ int _dns_client_server_add(char *server_ip, struct addrinfo *gai, dns_server_typ
server_info->type = server_type;
server_info->fd = 0;
server_info->status = DNS_SERVER_STATUS_INIT;
server_info->result_flag = result_flag;
if (gai->ai_addrlen > sizeof(server_info->in6)) {
tlog(TLOG_ERROR, "addr len invalid, %d, %zd, %d", gai->ai_addrlen, sizeof(server_info->addr), server_info->ai_family);
@@ -336,7 +337,7 @@ int _dns_client_server_remove(char *server_ip, struct addrinfo *gai, dns_server_
return -1;
}
int _dns_client_server_operate(char *server_ip, int port, dns_server_type_t server_type, int operate)
int _dns_client_server_operate(char *server_ip, int port, dns_server_type_t server_type, int result_flag, int operate)
{
char port_s[8];
int sock_type;
@@ -370,7 +371,7 @@ int _dns_client_server_operate(char *server_ip, int port, dns_server_type_t serv
}
if (operate == 0) {
ret = _dns_client_server_add(server_ip, gai, server_type);
ret = _dns_client_server_add(server_ip, gai, server_type, result_flag);
if (ret != 0) {
goto errout;
}
@@ -389,14 +390,14 @@ errout:
return -1;
}
int dns_add_server(char *server_ip, int port, dns_server_type_t server_type)
int dns_add_server(char *server_ip, int port, dns_server_type_t server_type, int result_flag)
{
return _dns_client_server_operate(server_ip, port, server_type, 0);
return _dns_client_server_operate(server_ip, port, server_type, result_flag, 0);
}
int dns_remove_server(char *server_ip, int port, dns_server_type_t server_type)
{
return _dns_client_server_operate(server_ip, port, server_type, 1);
return _dns_client_server_operate(server_ip, port, server_type, 0, 1);
}
int dns_server_num(void)
@@ -426,7 +427,7 @@ void _dns_client_query_release(struct dns_query_struct *query)
/* notify caller query end */
if (query->callback) {
query->callback(query->domain, DNS_QUERY_END, NULL, NULL, 0, query->user_ptr);
query->callback(query->domain, DNS_QUERY_END, 0, NULL, NULL, 0, query->user_ptr);
}
/* free resource */
@@ -587,7 +588,7 @@ int _dns_replied_check_add(struct dns_query_struct *dns_query, struct sockaddr *
return 0;
}
static int _dns_client_recv(unsigned char *inpacket, int inpacket_len, struct sockaddr *from, socklen_t from_len)
static int _dns_client_recv(struct dns_server_info *server_info, unsigned char *inpacket, int inpacket_len, struct sockaddr *from, socklen_t from_len)
{
int len;
int i;
@@ -609,7 +610,7 @@ static int _dns_client_recv(unsigned char *inpacket, int inpacket_len, struct so
if (len != 0) {
char host_name[DNS_MAX_CNAME_LEN];
tlog(TLOG_ERROR, "decode failed, packet len = %d, tc = %d, id = %d, from = %s\n", inpacket_len, packet->head.tc, packet->head.id,
gethost_by_addr(host_name, from, from_len));
gethost_by_addr(host_name, from, from_len));
return -1;
}
@@ -649,12 +650,11 @@ static int _dns_client_recv(unsigned char *inpacket, int inpacket_len, struct so
/* notify caller dns query result */
if (query->callback) {
ret = query->callback(query->domain, DNS_QUERY_RESULT, packet, inpacket, inpacket_len, query->user_ptr);
}
if (request_num == 0 || ret) {
/* if all server replied, or done, stop query, release resource */
_dns_client_query_remove(query);
ret = query->callback(query->domain, DNS_QUERY_RESULT, server_info->result_flag, packet, inpacket, inpacket_len, query->user_ptr);
if (request_num == 0 || ret) {
/* if all server replied, or done, stop query, release resource */
_dns_client_query_remove(query);
}
}
return ret;
@@ -771,7 +771,7 @@ static int _DNS_client_create_socket_tls(struct dns_server_info *server_info)
}
}
if(SSL_set_fd(ssl, fd) == 0) {
if (SSL_set_fd(ssl, fd) == 0) {
tlog(TLOG_ERROR, "ssl set fd failed.");
goto errout;
}
@@ -844,7 +844,7 @@ static int _dns_client_process_udp(struct dns_server_info *server_info, struct e
tlog(TLOG_DEBUG, "recv udp, from %s", gethost_by_addr(from_host, (struct sockaddr *)&from, from_len));
time(&server_info->last_recv);
if (_dns_client_recv(inpacket, len, (struct sockaddr *)&from, from_len) != 0) {
if (_dns_client_recv(server_info, inpacket, len, (struct sockaddr *)&from, from_len) != 0) {
return -1;
}
@@ -866,7 +866,7 @@ static int _dns_client_process_tcp(struct dns_server_info *server_info, struct e
if (errno == EAGAIN) {
return 0;
}
/* FOR GFW */
if (errno == ECONNRESET) {
goto errout;
@@ -901,9 +901,9 @@ static int _dns_client_process_tcp(struct dns_server_info *server_info, struct e
}
while (1) {
/* tcp result format
* | len (short) | dns query result |
*/
/* tcp result format
* | len (short) | dns query result |
*/
inpacket_data = server_info->recv_buff.data;
len = ntohs(*((unsigned short *)(inpacket_data)));
if (len <= 0 || len >= DNS_IN_PACKSIZE) {
@@ -920,7 +920,7 @@ static int _dns_client_process_tcp(struct dns_server_info *server_info, struct e
tlog(TLOG_DEBUG, "recv tcp from %s, len = %d", gethost_by_addr(from_host, (struct sockaddr *)&server_info->addr, server_info->ai_addrlen), len);
/* process result */
if (_dns_client_recv(inpacket_data, len, &server_info->addr, server_info->ai_addrlen) != 0) {
if (_dns_client_recv(server_info, inpacket_data, len, &server_info->addr, server_info->ai_addrlen) != 0) {
goto errout;
}
len += 2;
@@ -1109,9 +1109,9 @@ static int _dns_client_tls_verify(struct dns_server_info *server_info)
{
X509 *cert = NULL;
char peer_CN[256];
const EVP_MD * digest;
unsigned char md[EVP_MAX_MD_SIZE];
unsigned int n;
const EVP_MD *digest;
unsigned char md[EVP_MAX_MD_SIZE];
unsigned int n;
char cert_fingerprint[256];
int i = 0;
@@ -1194,7 +1194,6 @@ static int _dns_client_process_tls(struct dns_server_info *server_info, struct e
tlog(TLOG_ERROR, "epoll ctl failed.");
goto errout;
}
}
if (event->events & EPOLLIN) {
@@ -1205,7 +1204,7 @@ static int _dns_client_process_tls(struct dns_server_info *server_info, struct e
if (errno == EAGAIN) {
return 0;
}
/* FOR GFW */
if (errno == ECONNRESET) {
goto errout;
@@ -1240,9 +1239,9 @@ static int _dns_client_process_tls(struct dns_server_info *server_info, struct e
}
while (1) {
/* tcp result format
* | len (short) | dns query result |
*/
/* tcp result format
* | len (short) | dns query result |
*/
inpacket_data = server_info->recv_buff.data;
len = ntohs(*((unsigned short *)(inpacket_data)));
if (len <= 0 || len >= DNS_IN_PACKSIZE) {
@@ -1259,7 +1258,7 @@ static int _dns_client_process_tls(struct dns_server_info *server_info, struct e
tlog(TLOG_DEBUG, "recv tcp from %s, len = %d", gethost_by_addr(from_host, (struct sockaddr *)&server_info->addr, server_info->ai_addrlen), len);
/* process result */
if (_dns_client_recv(inpacket_data, len, &server_info->addr, server_info->ai_addrlen) != 0) {
if (_dns_client_recv(server_info, inpacket_data, len, &server_info->addr, server_info->ai_addrlen) != 0) {
goto errout;
}
len += 2;
@@ -1423,7 +1422,7 @@ static int _dns_client_send_tcp(struct dns_server_info *server_info, void *packe
unsigned char *inpacket = inpacket_data;
/* TCP query format
* | len (short) | dns query data |
* | len (short) | dns query data |
*/
*((unsigned short *)(inpacket)) = htons(len);
memcpy(inpacket + 2, packet, len);
@@ -1451,7 +1450,7 @@ static int _dns_client_send_tls(struct dns_server_info *server_info, void *packe
unsigned char *inpacket = inpacket_data;
/* TCP query format
* | len (short) | dns query data |
* | len (short) | dns query data |
*/
*((unsigned short *)(inpacket)) = htons(len);
memcpy(inpacket + 2, packet, len);

View File

@@ -16,10 +16,12 @@ typedef enum dns_result_type {
DNS_QUERY_END,
} dns_result_type;
#define DNSSERVER_FLAG_BLACKLIST_IP (0x1 << 0)
int dns_client_init(void);
/* query result notify function */
typedef int (*dns_client_callback)(char *domain, dns_result_type rtype, struct dns_packet *packet, unsigned char *inpacket, int inpacket_len, void *user_ptr);
typedef int (*dns_client_callback)(char *domain, dns_result_type rtype, unsigned int result_flag, struct dns_packet *packet, unsigned char *inpacket, int inpacket_len, void *user_ptr);
/* query domain */
int dns_client_query(char *domain, int qtype, dns_client_callback callback, void *user_ptr);
@@ -27,7 +29,7 @@ int dns_client_query(char *domain, int qtype, dns_client_callback callback, void
void dns_client_exit(void);
/* add remote dns server */
int dns_add_server(char *server_ip, int port, dns_server_type_t server_type);
int dns_add_server(char *server_ip, int port, dns_server_type_t server_type, int result_flag);
/* remove remote dns server */
int dns_remove_server(char *server_ip, int port, dns_server_type_t server_type);

443
src/dns_conf.c Normal file
View File

@@ -0,0 +1,443 @@
#include "dns_conf.h"
#include "list.h"
#include "rbtree.h"
#include "tlog.h"
#include "util.h"
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define DEFAULT_DNS_CACHE_SIZE 512
char dns_conf_server_ip[DNS_MAX_IPLEN];
char dns_conf_server_tcp_ip[DNS_MAX_IPLEN];
int dns_conf_tcp_idle_time = 120;
int dns_conf_cachesize = DEFAULT_DNS_CACHE_SIZE;
int dns_conf_prefetch = 0;
struct dns_servers dns_conf_servers[DNS_MAX_SERVERS];
char dns_conf_server_name[DNS_MAX_CONF_CNAME_LEN];
int dns_conf_server_num;
int dns_conf_log_level = TLOG_ERROR;
char dns_conf_log_file[DNS_MAX_PATH];
size_t dns_conf_log_size = 1024 * 1024;
int dns_conf_log_num = 8;
int dns_conf_audit_enable = 0;
char dns_conf_audit_file[DNS_MAX_PATH];
size_t dns_conf_audit_size = 1024 * 1024;
int dns_conf_audit_num = 2;
art_tree dns_conf_domain_rule;
radix_tree_t *dns_conf_address_rule;
int dns_conf_rr_ttl;
int dns_conf_rr_ttl_min;
int dns_conf_rr_ttl_max;
int dns_conf_force_AAAA_SOA;
int config_server(int argc, char *argv[], dns_server_type_t type, int default_port)
{
int index = dns_conf_server_num;
struct dns_servers *server;
int port = -1;
char *ip = NULL;
int opt = 0;
int result_flag = 0;
/* clang-format off */
static struct option long_options[] = {
{"blacklist-ip", 0, 0, 'b'},
{0, 0, 0, 0}
};
/* clang-format on */
if (argc <= 1) {
tlog(TLOG_ERROR, "invalid parameter.");
return -1;
}
ip = argv[1];
optind = 1;
while (1) {
opt = getopt_long_only(argc, argv, "", long_options, NULL);
if (opt == -1) {
break;
}
switch (opt) {
case 'b': {
result_flag |= DNSSERVER_FLAG_BLACKLIST_IP;
break;
}
}
}
if (index >= DNS_MAX_SERVERS) {
tlog(TLOG_ERROR, "exceeds max server number");
return -1;
}
server = &dns_conf_servers[index];
/* parse ip, port from ip */
if (parse_ip(ip, server->server, &port) != 0) {
return -1;
}
/* if port is not defined, set port to default 53 */
if (port == PORT_NOT_DEFINED) {
port = default_port;
}
server->type = type;
server->port = port;
server->result_flag = result_flag;
dns_conf_server_num++;
tlog(TLOG_DEBUG, "add server %s, flag: %X", ip, result_flag);
return 0;
}
int config_domain_iter_cb(void *data, const unsigned char *key, uint32_t key_len, void *value)
{
struct dns_domain_rule *domain_rule = value;
int i = 0;
if (domain_rule == NULL) {
return 0;
}
for (i = 0; i < DOMAIN_RULE_MAX; i++) {
free(domain_rule->rules[i]);
}
free(domain_rule);
return 0;
}
void config_domain_destroy(void)
{
art_iter(&dns_conf_domain_rule, config_domain_iter_cb, 0);
art_tree_destroy(&dns_conf_domain_rule);
}
void config_address_destroy(radix_node_t *node, void *cbctx)
{
if (node == NULL) {
return;
}
if (node->data == NULL) {
return;
}
free(node->data);
node->data = NULL;
}
int config_domain_rule_add(char *domain, enum domain_rule type, void *rule)
{
struct dns_domain_rule *domain_rule = NULL;
struct dns_domain_rule *old_domain_rule = NULL;
struct dns_domain_rule *add_domain_rule = NULL;
char domain_key[DNS_MAX_CONF_CNAME_LEN];
int len = 0;
len = strlen(domain);
reverse_string(domain_key, domain, len);
domain_key[len] = '.';
len++;
domain_key[len] = 0;
if (type >= DOMAIN_RULE_MAX) {
goto errout;
}
domain_rule = art_search(&dns_conf_domain_rule, (unsigned char *)domain_key, len);
if (domain_rule == NULL) {
add_domain_rule = malloc(sizeof(*add_domain_rule));
if (add_domain_rule == NULL) {
goto errout;
}
memset(add_domain_rule, 0, sizeof(*add_domain_rule));
domain_rule = add_domain_rule;
}
if (domain_rule->rules[type]) {
free(domain_rule->rules[type]);
domain_rule->rules[type] = NULL;
}
domain_rule->rules[type] = rule;
if (add_domain_rule) {
old_domain_rule = art_insert(&dns_conf_domain_rule, (unsigned char *)domain_key, len, add_domain_rule);
if (old_domain_rule) {
free(old_domain_rule);
}
}
return 0;
errout:
if (add_domain_rule) {
free(add_domain_rule);
}
tlog(TLOG_ERROR, "add doamin %s failed", domain);
return 0;
}
int config_address(void *data, int argc, char *argv[])
{
struct dns_address_IPV4 *address_ipv4 = NULL;
struct dns_address_IPV6 *address_ipv6 = NULL;
void *address = NULL;
char *value = argv[1];
char ip[MAX_IP_LEN];
char domain[DNS_MAX_CONF_CNAME_LEN];
char *begin = NULL;
char *end = NULL;
int len = 0;
int port;
struct sockaddr_storage addr;
socklen_t addr_len = sizeof(addr);
enum domain_rule type = 0;
begin = strstr(value, "/");
if (begin == NULL) {
goto errout;
}
begin++;
end = strstr(begin, "/");
if (end == NULL) {
goto errout;
}
/* remove prefix . */
while (*begin == '.') {
begin++;
}
len = end - begin;
memcpy(domain, begin, len);
domain[len] = 0;
if (parse_ip(end + 1, ip, &port) != 0) {
goto errout;
}
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;
address_ipv4 = malloc(sizeof(*address_ipv4));
if (address_ipv4 == NULL) {
goto errout;
}
addr_in = (struct sockaddr_in *)&addr;
memcpy(address_ipv4->ipv4_addr, &addr_in->sin_addr.s_addr, 4);
type = DOMAIN_RULE_ADDRESS_IPV4;
address = address_ipv4;
} break;
case AF_INET6: {
struct sockaddr_in6 *addr_in6;
addr_in6 = (struct sockaddr_in6 *)&addr;
if (IN6_IS_ADDR_V4MAPPED(&addr_in6->sin6_addr)) {
address_ipv4 = malloc(sizeof(*address_ipv4));
if (address_ipv4 == NULL) {
goto errout;
}
memcpy(address_ipv4->ipv4_addr, addr_in6->sin6_addr.s6_addr + 12, 4);
type = DOMAIN_RULE_ADDRESS_IPV4;
address = address_ipv4;
} else {
address_ipv6 = malloc(sizeof(*address_ipv6));
if (address_ipv6 == NULL) {
goto errout;
}
memcpy(address_ipv6->ipv6_addr, addr_in6->sin6_addr.s6_addr, 16);
type = DOMAIN_RULE_ADDRESS_IPV6;
address = address_ipv6;
}
} break;
default:
goto errout;
}
if (config_domain_rule_add(domain, type, address) != 0) {
goto errout;
}
return 0;
errout:
if (address) {
free(address);
}
tlog(TLOG_ERROR, "add address %s failed", value);
return 0;
}
int config_server_udp(void *data, int argc, char *argv[])
{
return config_server(argc, argv, DNS_SERVER_UDP, DEFAULT_DNS_PORT);
}
int config_server_tcp(void *data, int argc, char *argv[])
{
return config_server(argc, argv, DNS_SERVER_TCP, DEFAULT_DNS_PORT);
}
int config_server_tls(void *data, int argc, char *argv[])
{
return config_server(argc, argv, DNS_SERVER_TLS, DEFAULT_DNS_TLS_PORT);
}
radix_node_t *create_addr_node(radix_tree_t *tree, char *addr)
{
radix_node_t *node;
void *p;
prefix_t prefix;
const char *errmsg = NULL;
p = prefix_pton(addr, -1, &prefix, &errmsg);
if (p == NULL) {
return NULL;
}
node = radix_lookup(tree, &prefix);
return node;
}
int 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(dns_conf_address_rule, subnet);
if (node == NULL) {
return -1;
}
if (node->data == NULL) {
ip_rule = malloc(sizeof(*ip_rule));
if (ip_rule == NULL) {
return -1;
}
node->data = ip_rule;
memset(ip_rule, 0, sizeof(*ip_rule));
}
ip_rule = node->data;
switch (rule) {
case ADDRESS_RULE_BLACKLIST:
ip_rule->blacklist = 1;
break;
case ADDRESS_RULE_BOGUS:
ip_rule->bogus = 1;
break;
}
return 0;
}
int config_blacklist_ip(void *data, int argc, char *argv[])
{
return config_iplist_rule(argv[1], ADDRESS_RULE_BLACKLIST);
}
int conf_bogus_nxdomain(void *data, int argc, char *argv[])
{
return config_iplist_rule(argv[1], ADDRESS_RULE_BOGUS);
}
int config_log_level(void *data, int argc, char *argv[])
{
/* read log level and set */
char *value = argv[1];
if (strncmp("debug", value, MAX_LINE_LEN) == 0) {
dns_conf_log_level = TLOG_DEBUG;
} else if (strncmp("info", value, MAX_LINE_LEN) == 0) {
dns_conf_log_level = TLOG_INFO;
} else if (strncmp("warn", value, MAX_LINE_LEN) == 0) {
dns_conf_log_level = TLOG_WARN;
} else if (strncmp("error", value, MAX_LINE_LEN) == 0) {
dns_conf_log_level = TLOG_ERROR;
} else {
return -1;
}
return 0;
}
struct config_item config_item[] = {
CONF_STRING("server-name", (char *)dns_conf_server_name, DNS_MAX_CONF_CNAME_LEN),
CONF_STRING("bind", dns_conf_server_ip, DNS_MAX_IPLEN),
CONF_STRING("bind-tcp", dns_conf_server_tcp_ip, DNS_MAX_IPLEN),
CONF_CUSTOM("server", config_server_udp, NULL),
CONF_CUSTOM("server-tcp", config_server_tcp, NULL),
CONF_CUSTOM("server-tls", config_server_tls, NULL),
CONF_CUSTOM("address", config_address, NULL),
CONF_INT("tcp-idle-time", &dns_conf_tcp_idle_time, 0, 3600),
CONF_INT("cache-size", &dns_conf_cachesize, 0, CONF_INT_MAX),
CONF_YESNO("prefetch-domain", &dns_conf_prefetch),
CONF_CUSTOM("log-level", config_log_level, NULL),
CONF_STRING("log-file", (char *)dns_conf_log_file, DNS_MAX_PATH),
CONF_SIZE("log-size", &dns_conf_log_size, 0, 1024 * 1024 * 1024),
CONF_INT("log-num", &dns_conf_log_num, 0, 1024),
CONF_YESNO("audit-enable", &dns_conf_audit_enable),
CONF_STRING("audit-file", (char *)&dns_conf_audit_file, DNS_MAX_PATH),
CONF_SIZE("audit-size", &dns_conf_audit_size, 0, 1024 * 1024 * 1024),
CONF_INT("audit-num", &dns_conf_audit_num, 0, 1024),
CONF_INT("rr-ttl", &dns_conf_rr_ttl, 0, CONF_INT_MAX),
CONF_INT("rr-ttl-min", &dns_conf_rr_ttl_min, 0, CONF_INT_MAX),
CONF_INT("rr-ttl-max", &dns_conf_rr_ttl_max, 0, CONF_INT_MAX),
CONF_YESNO("force-AAAA-SOA", &dns_conf_force_AAAA_SOA),
CONF_CUSTOM("blacklist-ip", config_blacklist_ip, NULL),
CONF_CUSTOM("bogus-nxdomain", conf_bogus_nxdomain, NULL),
CONF_CUSTOM("conf-file", config_addtional_file, NULL),
CONF_END(),
};
int config_addtional_file(void *data, int argc, char *argv[])
{
char *file_path = argv[1];
if (access(file_path, R_OK) != 0) {
tlog(TLOG_WARN, "conf file %s is not readable.", file_path);
return 0;
}
return load_conf(file_path, config_item);
}
int _dns_server_load_conf_init(void)
{
dns_conf_address_rule = New_Radix();
art_tree_init(&dns_conf_domain_rule);
if (dns_conf_address_rule == NULL) {
return -1;
}
return 0;
}
void dns_server_load_exit(void)
{
config_domain_destroy();
Destroy_Radix(dns_conf_address_rule, config_address_destroy, NULL);
}
int dns_server_load_conf(const char *file)
{
_dns_server_load_conf_init();
return load_conf(file, config_item);
}

View File

@@ -1,13 +1,14 @@
#ifndef _DNS_CONF
#define _DNS_CONF
#include "list.h"
#include "art.h"
#include "radix.h"
#include "conf.h"
#include "dns.h"
#include "dns_client.h"
#include "hash.h"
#include "hashtable.h"
#include "list.h"
#include "radix.h"
#define DNS_MAX_SERVERS 32
#define DNS_MAX_IPLEN 64
@@ -19,21 +20,31 @@
#define SMARTDNS_LOG_FILE "/var/log/smartdns.log"
#define SMARTDNS_AUDIT_FILE "/var/log/smartdns-audit.log"
enum domain_rule {
DOMAIN_RULE_ADDRESS_IPV4 = 1,
DOMAIN_RULE_ADDRESS_IPV6 = 2,
DOMAIN_RULE_MAX,
};
struct dns_address_IPV4 {
unsigned char ipv4_addr[DNS_RR_A_LEN];
};
struct dns_address_IPV6 {
unsigned char ipv6_addr[DNS_RR_AAAA_LEN];
};
struct dns_domain_rule {
void *rules[DOMAIN_RULE_MAX];
};
struct dns_servers {
char server[DNS_MAX_IPLEN];
unsigned short port;
unsigned int result_flag;
dns_server_type_t type;
};
struct dns_address {
dns_type_t addr_type;
union {
unsigned char ipv4_addr[DNS_RR_A_LEN];
unsigned char ipv6_addr[DNS_RR_AAAA_LEN];
unsigned char addr[0];
};
};
/* ip address lists of domain */
struct dns_bogus_ip_address {
struct hlist_node node;
@@ -45,13 +56,12 @@ struct dns_bogus_ip_address {
};
};
enum address_action {
ACTION_BLACKLIST = 1,
ACTION_BOGUS = 2,
enum address_rule {
ADDRESS_RULE_BLACKLIST = 1,
ADDRESS_RULE_BOGUS = 2,
};
struct dns_ip_address_rule
{
struct dns_ip_address_rule {
unsigned int blacklist : 1;
unsigned int bogus : 1;
};
@@ -68,16 +78,14 @@ extern int dns_conf_prefetch;
extern struct dns_servers dns_conf_servers[DNS_MAX_SERVERS];
extern int dns_conf_server_num;
extern struct dns_bogus_nxdomain dns_conf_bogus_nxdomain;
extern int dns_conf_log_level;
extern char dns_conf_log_file[DNS_MAX_PATH];
extern int dns_conf_log_size;
extern size_t dns_conf_log_size;
extern int dns_conf_log_num;
extern int dns_conf_audit_enable;
extern char dns_conf_audit_file[DNS_MAX_PATH];
extern int dns_conf_audit_size;
extern size_t dns_conf_audit_size;
extern int dns_conf_audit_num;
extern char dns_conf_server_name[DNS_MAX_CONF_CNAME_LEN];
@@ -89,10 +97,10 @@ extern int dns_conf_rr_ttl_min;
extern int dns_conf_rr_ttl_max;
extern int dns_conf_force_AAAA_SOA;
int dns_bogus_nxdomain_exists(unsigned char *ip, dns_type_t addr_type);
void dns_server_load_exit(void);
int load_conf(const char *file);
int dns_server_load_conf(const char *file);
void load_exit(void);
extern int config_addtional_file(void *data, int argc, char *argv[]);
#endif // !_DNS_CONF

View File

@@ -18,7 +18,7 @@
#define _GNU_SOURCE
#include "dns_server.h"
#include "atomic.h"
#include "conf.h"
#include "dns_conf.h"
#include "dns.h"
#include "dns_cache.h"
#include "dns_client.h"
@@ -85,7 +85,6 @@ struct dns_server {
struct list_head client_list;
};
/* ip address lists of domain */
struct dns_ip_address {
struct hlist_node node;
@@ -153,9 +152,11 @@ struct dns_request {
int prefetch;
pthread_mutex_t ip_map_lock;
int ip_map_num;
DECLARE_HASHTABLE(ip_map, 4);
struct dns_domain_rule *domain_rule;
};
static struct dns_server server;
@@ -180,13 +181,12 @@ static void _dns_server_audit_log(struct dns_request *request)
}
if (request->qtype == DNS_T_AAAA) {
snprintf(req_result, sizeof(req_result), "%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x",
request->ipv6_addr[0], request->ipv6_addr[1], request->ipv6_addr[2], request->ipv6_addr[3], request->ipv6_addr[4], request->ipv6_addr[5],
request->ipv6_addr[6], request->ipv6_addr[7], request->ipv6_addr[8], request->ipv6_addr[9], request->ipv6_addr[10], request->ipv6_addr[11],
request->ipv6_addr[12], request->ipv6_addr[13], request->ipv6_addr[14], request->ipv6_addr[15]);
snprintf(req_result, sizeof(req_result), "%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x", request->ipv6_addr[0],
request->ipv6_addr[1], request->ipv6_addr[2], request->ipv6_addr[3], request->ipv6_addr[4], request->ipv6_addr[5], request->ipv6_addr[6],
request->ipv6_addr[7], request->ipv6_addr[8], request->ipv6_addr[9], request->ipv6_addr[10], request->ipv6_addr[11], request->ipv6_addr[12],
request->ipv6_addr[13], request->ipv6_addr[14], request->ipv6_addr[15]);
} else if (request->qtype == DNS_T_A) {
snprintf(req_result, sizeof(req_result), "%d.%d.%d.%d", request->ipv4_addr[0], request->ipv4_addr[1], request->ipv4_addr[2],
request->ipv4_addr[3]);
snprintf(req_result, sizeof(req_result), "%d.%d.%d.%d", request->ipv4_addr[0], request->ipv4_addr[1], request->ipv4_addr[2], request->ipv4_addr[3]);
} else {
return;
}
@@ -324,7 +324,7 @@ static int _dns_server_reply_tcp(struct dns_server_conn *client, void *packet, u
unsigned char *inpacket = inpacket_data;
/* TCP query format
* | len (short) | dns query data |
* | len (short) | dns query data |
*/
*((unsigned short *)(inpacket)) = htons(len);
memcpy(inpacket + 2, packet, len);
@@ -372,8 +372,6 @@ static int _dns_reply_inpacket(struct dns_request *request, unsigned char *inpac
ret = -1;
}
_dns_server_client_release(client);
return ret;
}
@@ -667,23 +665,7 @@ static int _dns_server_get_conf_ttl(int ttl)
return ttl;
}
static int _dns_server_bogus_nxdomain_exists(struct dns_request *request, unsigned char *ip, dns_type_t addr_type)
{
int ret = 0;
ret = dns_bogus_nxdomain_exists(ip, addr_type);
if (ret != 0) {
return -1;
}
if (request->rcode == DNS_RC_SERVFAIL) {
request->rcode = DNS_RC_NXDOMAIN;
}
return 0;
}
static int _dns_server_ip_rule_check(struct dns_request *request, unsigned char *addr, int addr_len, dns_type_t addr_type)
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)
{
prefix_t prefix;
radix_node_t *node = NULL;
@@ -695,7 +677,7 @@ static int _dns_server_ip_rule_check(struct dns_request *request, unsigned char
node = radix_search_best(dns_conf_address_rule, &prefix);
if (node == NULL) {
return - 1;
return -1;
}
if (node->data == NULL) {
@@ -703,11 +685,26 @@ static int _dns_server_ip_rule_check(struct dns_request *request, unsigned char
}
rule = node->data;
if (rule->bogus) {
goto match;
}
if (rule->blacklist) {
if (result_flag & DNSSERVER_FLAG_BLACKLIST_IP) {
goto match;
}
}
return -1;
match:
if (request->rcode == DNS_RC_SERVFAIL) {
request->rcode = DNS_RC_NXDOMAIN;
}
return 0;
}
static int _dns_server_process_answer(struct dns_request *request, char *domain, struct dns_packet *packet)
static int _dns_server_process_answer(struct dns_request *request, char *domain, struct dns_packet *packet, unsigned int result_flag)
{
int ttl;
char name[DNS_MAX_CNAME_LEN] = {0};
@@ -741,18 +738,12 @@ static int _dns_server_process_answer(struct dns_request *request, char *domain,
tlog(TLOG_DEBUG, "domain: %s TTL:%d IP: %d.%d.%d.%d", name, ttl, addr[0], addr[1], addr[2], addr[3]);
if (_dns_server_ip_rule_check(request, addr, 4, DNS_T_A) == 0) {
/* ip rule check */
if (_dns_server_ip_rule_check(request, addr, 4, DNS_T_A, result_flag) == 0) {
_dns_server_request_release(request);
break;
}
/* bogus ip address, skip */
if (_dns_server_bogus_nxdomain_exists(request, addr, DNS_T_A) == 0) {
_dns_server_request_release(request);
tlog(TLOG_DEBUG, "bogus-nxdomain: %s TTL:%d IP: %d.%d.%d.%d", name, ttl, addr[0], addr[1], addr[2], addr[3]);
break;
}
if (strncmp(name, domain, DNS_MAX_CNAME_LEN) != 0 && strncmp(request->cname, name, DNS_MAX_CNAME_LEN) != 0) {
_dns_server_request_release(request);
break;
@@ -799,20 +790,11 @@ static int _dns_server_process_answer(struct dns_request *request, char *domain,
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], addr[11], addr[12], addr[13], addr[14], addr[15]);
if (_dns_server_ip_rule_check(request, addr, 16, DNS_T_A) == 0) {
if (_dns_server_ip_rule_check(request, addr, 16, DNS_T_AAAA, result_flag) == 0) {
_dns_server_request_release(request);
break;
}
/* bogus ip address, skip */
if (_dns_server_bogus_nxdomain_exists(request, addr, DNS_T_AAAA) == 0) {
_dns_server_request_release(request);
tlog(TLOG_DEBUG, "bogus-nxdomain: %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], addr[11], addr[12], addr[13],
addr[14], addr[15]);
break;
}
if (strncmp(name, domain, DNS_MAX_CNAME_LEN) != 0 && strncmp(request->cname, name, DNS_MAX_CNAME_LEN) != 0) {
_dns_server_request_release(request);
break;
@@ -886,10 +868,11 @@ static int dns_server_update_reply_packet_id(struct dns_request *request, unsign
return 0;
}
static int dns_server_resolve_callback(char *domain, dns_result_type rtype, struct dns_packet *packet, unsigned char *inpacket, int inpacket_len,
static int dns_server_resolve_callback(char *domain, dns_result_type rtype, unsigned int result_flag, struct dns_packet *packet, unsigned char *inpacket, int inpacket_len,
void *user_ptr)
{
struct dns_request *request = user_ptr;
struct dns_server_conn *client = request->client;
int ip_num = 0;
if (request == NULL) {
@@ -900,9 +883,10 @@ static int dns_server_resolve_callback(char *domain, dns_result_type rtype, stru
if (request->passthrough) {
dns_server_update_reply_packet_id(request, inpacket, inpacket_len);
_dns_reply_inpacket(request, inpacket, inpacket_len);
return -1;
return 0;
}
_dns_server_process_answer(request, domain, packet);
_dns_server_process_answer(request, domain, packet, result_flag);
return 0;
} else if (rtype == DNS_QUERY_ERR) {
tlog(TLOG_ERROR, "request faield, %s", domain);
@@ -921,6 +905,7 @@ static int dns_server_resolve_callback(char *domain, dns_result_type rtype, stru
_dns_server_request_remove(request);
}
_dns_server_request_release(request);
_dns_server_client_release(client);
}
return 0;
@@ -1023,35 +1008,26 @@ static int _dns_server_reply_SOA(int rcode, struct dns_request *request, struct
static void _dns_server_log_rule(char *domain, unsigned char *rule_key, int rule_key_len)
{
char rule_name[DNS_MAX_CNAME_LEN];
if (rule_key_len <= 0) {
return;
}
reverse_string(rule_name, (char *)rule_key, rule_key_len);
rule_name[rule_key_len - 1] = 0;
rule_name[rule_key_len] = 0;
tlog(TLOG_INFO, "RULE-MATCH, domain: %s, rule: %s", domain, rule_name);
}
static struct dns_address *_dns_server_get_address_by_domain(char *domain, int qtype)
static struct dns_domain_rule *_dns_server_get_domain_rule(char *domain)
{
int domain_len;
char domain_key[DNS_MAX_CNAME_LEN];
char type = '4';
unsigned char matched_key[DNS_MAX_CNAME_LEN];
int matched_key_len = DNS_MAX_CNAME_LEN;
struct dns_address *address = NULL;
switch (qtype) {
case DNS_T_A:
type = '4';
break;
case DNS_T_AAAA:
type = '6';
break;
default:
return NULL;
}
unsigned char matched_key[DNS_MAX_CNAME_LEN];
struct dns_domain_rule *domain_rule = NULL;
domain_len = strlen(domain);
reverse_string(domain_key + 1, domain, domain_len);
domain_key[0] = type;
domain_len++;
reverse_string(domain_key, domain, domain_len);
domain_key[domain_len] = '.';
domain_len++;
domain_key[domain_len] = 0;
@@ -1060,37 +1036,47 @@ static struct dns_address *_dns_server_get_address_by_domain(char *domain, int q
return art_substring(&dns_conf_domain_rule, (unsigned char *)domain_key, domain_len, NULL, NULL);
}
address = art_substring(&dns_conf_domain_rule, (unsigned char *)domain_key, domain_len, matched_key, &matched_key_len);
if (address == NULL) {
domain_rule = art_substring(&dns_conf_domain_rule, (unsigned char *)domain_key, domain_len, matched_key, &matched_key_len);
if (domain_rule == NULL) {
return NULL;
}
if (matched_key_len <= 0) {
return NULL;
}
matched_key_len--;
matched_key[matched_key_len] = 0;
_dns_server_log_rule(domain, matched_key, matched_key_len);
return address;
return domain_rule;
}
static int _dns_server_process_address(struct dns_request *request, struct dns_packet *packet)
{
struct dns_address *address = NULL;
struct dns_address_IPV4 *address_ipv4 = NULL;
struct dns_address_IPV6 *address_ipv6 = NULL;
address = _dns_server_get_address_by_domain(request->domain, request->qtype);
if (address == NULL) {
goto errout;
}
if (request->qtype != address->addr_type) {
if (request->domain_rule == NULL) {
goto errout;
}
switch (request->qtype) {
case DNS_T_A:
memcpy(request->ipv4_addr, address->ipv4_addr, DNS_RR_A_LEN);
if (request->domain_rule->rules[DOMAIN_RULE_ADDRESS_IPV4] == NULL) {
goto errout;
}
address_ipv4 = request->domain_rule->rules[DOMAIN_RULE_ADDRESS_IPV4];
memcpy(request->ipv4_addr, address_ipv4->ipv4_addr, DNS_RR_A_LEN);
request->ttl_v4 = 600;
request->has_ipv4 = 1;
break;
case DNS_T_AAAA:
memcpy(request->ipv6_addr, address->ipv6_addr, DNS_RR_AAAA_LEN);
if (request->domain_rule->rules[DOMAIN_RULE_ADDRESS_IPV6] == NULL) {
goto errout;
}
address_ipv6 = request->domain_rule->rules[DOMAIN_RULE_ADDRESS_IPV6];
memcpy(request->ipv6_addr, address_ipv6->ipv6_addr, DNS_RR_AAAA_LEN);
request->ttl_v6 = 600;
request->has_ipv6 = 1;
break;
@@ -1174,9 +1160,9 @@ static int _dns_server_recv(struct dns_server_conn *client, unsigned char *inpac
goto errout;
}
tlog(TLOG_DEBUG, "request qdcount = %d, ancount = %d, nscount = %d, nrcount = %d, len = %d, id = %d, tc = %d, rd = %d, ra = %d, rcode = %d\n", packet->head.qdcount,
packet->head.ancount, packet->head.nscount, packet->head.nrcount, inpacket_len, packet->head.id, packet->head.tc, packet->head.rd, packet->head.ra,
packet->head.rcode);
tlog(TLOG_DEBUG, "request qdcount = %d, ancount = %d, nscount = %d, nrcount = %d, len = %d, id = %d, tc = %d, rd = %d, ra = %d, rcode = %d\n",
packet->head.qdcount, packet->head.ancount, packet->head.nscount, packet->head.nrcount, inpacket_len, packet->head.id, packet->head.tc,
packet->head.rd, packet->head.ra, packet->head.rcode);
if (packet->head.qr != DNS_QR_QUERY) {
goto errout;
@@ -1187,6 +1173,7 @@ static int _dns_server_recv(struct dns_server_conn *client, unsigned char *inpac
tlog(TLOG_ERROR, "malloc failed.\n");
goto errout;
}
memset(request, 0, sizeof(*request));
pthread_mutex_init(&request->ip_map_lock, 0);
atomic_set(&request->adblock, 0);
@@ -1219,12 +1206,13 @@ static int _dns_server_recv(struct dns_server_conn *client, unsigned char *inpac
request->qtype = qtype;
}
request->domain_rule = _dns_server_get_domain_rule(request->domain);
switch (qtype) {
case DNS_T_PTR:
ret = _dns_server_process_ptr(request, packet);
if (ret == 0) {
free(request);
return ret;
goto clean_exit;
} else {
request->passthrough = 1;
}
@@ -1234,8 +1222,7 @@ static int _dns_server_recv(struct dns_server_conn *client, unsigned char *inpac
case DNS_T_AAAA:
if (dns_conf_force_AAAA_SOA == 1) {
_dns_server_reply_SOA(DNS_RC_NOERROR, request, packet);
free(request);
return 0;
goto clean_exit;
}
break;
default:
@@ -1245,13 +1232,11 @@ static int _dns_server_recv(struct dns_server_conn *client, unsigned char *inpac
}
if (_dns_server_process_address(request, packet) == 0) {
free(request);
return 0;
goto clean_exit;
}
if (_dns_server_process_cache(request, packet) == 0) {
free(request);
return 0;
goto clean_exit;
}
tlog(TLOG_INFO, "query server %s from %s, qtype = %d\n", request->domain, gethost_by_addr(name, (struct sockaddr *)from, from_len), qtype);
@@ -1265,6 +1250,14 @@ static int _dns_server_recv(struct dns_server_conn *client, unsigned char *inpac
request->send_tick = get_tick_count();
dns_client_query(request->domain, qtype, dns_server_resolve_callback, request);
return 0;
clean_exit:
if (request) {
free(request);
}
_dns_server_client_release(client);
return 0;
errout:
if (request) {
@@ -1339,6 +1332,7 @@ static void _dns_server_client_touch(struct dns_server_conn *client)
static int _dns_server_client_close(struct dns_server_conn *client)
{
if (client->fd > 0) {
epoll_ctl(server.epoll_fd, EPOLL_CTL_DEL, client->fd, NULL);
close(client->fd);
client->fd = -1;
}
@@ -1356,7 +1350,7 @@ static int _dns_server_accept(struct dns_server_conn *dnsserver, struct epoll_ev
struct dns_server_conn *client = NULL;
socklen_t addr_len = sizeof(addr);
int fd = -1;
fd = accept4(dnsserver->fd, (struct sockaddr *)&addr, &addr_len, SOCK_NONBLOCK | SOCK_CLOEXEC);
if (fd < 0) {
return -1;
@@ -1408,8 +1402,7 @@ int _dns_server_tcp_recv(struct dns_server_conn *dnsserver)
return 0;
}
len = recv(dnsserver->fd, dnsserver->recvbuff.buf + dnsserver->recvbuff.size,
sizeof(dnsserver->recvbuff.buf) - dnsserver->recvbuff.size, 0);
len = recv(dnsserver->fd, dnsserver->recvbuff.buf + dnsserver->recvbuff.size, sizeof(dnsserver->recvbuff.buf) - dnsserver->recvbuff.size, 0);
if (len < 0) {
if (errno == EAGAIN) {
return 1;
@@ -1439,7 +1432,7 @@ int _dns_server_tcp_process_one_request(struct dns_server_conn *dnsserver)
}
request_len = ntohs(*((unsigned short *)(dnsserver->recvbuff.buf + proceed_len)));
if (request_len >= sizeof(dnsserver->recvbuff.buf)) {
tlog(TLOG_ERROR, "request length is invalid.");
return -1;
@@ -1511,7 +1504,7 @@ int _dns_server_tcp_send(struct dns_server_conn *client)
return 1;
}
return -1;
} else if (len == 0 ) {
} else if (len == 0) {
break;
}
@@ -1539,7 +1532,7 @@ static int _dns_server_process_tcp(struct dns_server_conn *dnsserver, struct epo
if (_dns_server_tcp_process_requests(dnsserver) != 0) {
_dns_server_client_close(dnsserver);
}
}
}
if (event->events & EPOLLOUT) {
if (_dns_server_tcp_send(dnsserver) != 0) {
@@ -1638,7 +1631,6 @@ void _dns_server_tcp_idle_check(void)
}
}
void _dns_server_period_run_second(void)
{
static unsigned int sec = 0;
@@ -1721,6 +1713,7 @@ int dns_server_run(void)
if (num == 0) {
continue;
}
for (i = 0; i < num; i++) {
struct epoll_event *event = &events[i];
struct dns_server_conn *dnsserver = event->data.ptr;
@@ -1771,7 +1764,7 @@ int _dns_server_start_udp(void)
if (server.udp_server.fd <= 0) {
return 0;
}
memset(&event, 0, sizeof(event));
event.events = EPOLLIN;
event.data.ptr = &server.udp_server;
@@ -1790,7 +1783,7 @@ int _dns_server_start_tcp(void)
if (server.tcp_server.fd <= 0) {
return 0;
}
memset(&event, 0, sizeof(event));
event.events = EPOLLIN;
event.data.ptr = &server.tcp_server;
@@ -1816,7 +1809,6 @@ int dns_server_start(void)
return 0;
}
int _dns_create_socket(const char *host_ip, int type)
{
int fd = -1;
@@ -1896,7 +1888,6 @@ int _dns_server_socket(void)
if (fd_tcp < 0) {
goto errout;
}
}
server.udp_server.fd = fd_udp;

116
src/include/conf.h Normal file
View File

@@ -0,0 +1,116 @@
#ifndef _GENERIC_CONF_H
#define _GENERIC_CONF_H
#include <unistd.h>
#define MAX_LINE_LEN 1024
#define MAX_KEY_LEN 64
#define CONF_INT_MAX (~(1 << 31))
#define CONF_INT_MIN (1 << 31)
struct config_item {
const char *item;
int (*item_func)(const char *item, void *data, int argc, char *argv[]);
void *data;
};
struct config_item_custom {
void *custom_data;
int (*custom_func)(void *data, int argc, char *argv[]);
};
struct config_item_int {
int *data;
int min;
int max;
};
struct config_item_string {
char *data;
size_t size;
};
struct config_item_yesno {
int *data;
};
struct config_item_size {
size_t *data;
size_t min;
size_t max;
};
#define CONF_INT(key, value, min_value, max_value) \
{ \
key, conf_int, &(struct config_item_int) \
{ \
.data = value, .min = min_value, .max = max_value \
} \
}
#define CONF_STRING(key, value, len_value) \
{ \
key, conf_string, &(struct config_item_string) \
{ \
.data = value, .size = len_value \
} \
}
#define CONF_YESNO(key, value) \
{ \
key, conf_yesno, &(struct config_item_yesno) \
{ \
.data = value \
} \
}
#define CONF_SIZE(key, value, min_value, max_value) \
{ \
key, conf_size, &(struct config_item_size) \
{ \
.data = value, .min = min_value, .max = max_value \
} \
}
/*
* func: int (*func)(void *data, int argc, char *argv[]);
*/
#define CONF_CUSTOM(key, func, data) \
{ \
key, conf_custom, &(struct config_item_custom) \
{ \
.custom_data = data, .custom_func = func \
} \
}
#define CONF_END() \
{ \
0, 0, 0 \
}
extern int conf_custom(const char *item, void *data, int argc, char *argv[]);
extern int conf_int(const char *item, void *data, int argc, char *argv[]);
extern int conf_string(const char *item, void *data, int argc, char *argv[]);
extern int conf_yesno(const char *item, void *data, int argc, char *argv[]);
extern int conf_size(const char *item, void *data, int argc, char *argv[]);
/*
* Example:
* int num = 0;
*
* struct config_item itmes [] = {
* CONF_INT("CONF_NUM", &num, -1, 10),
* CONF_END();
* }
*
* load_conf(file, items);
*
*/
int load_conf(const char *file, struct config_item items[]);
int load_conf_get_line_count(void);
void load_exit(void);
#endif // !_GENERIC_CONF_H

263
src/lib/conf.c Normal file
View File

@@ -0,0 +1,263 @@
#include "conf.h"
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
__thread int line_no;
int conf_custom(const char *item, void *data, int argc, char *argv[])
{
struct config_item_custom *item_custom = data;
return item_custom->custom_func(item_custom->custom_data, argc, argv);
}
int conf_int(const char *item, void *data, int argc, char *argv[])
{
struct config_item_int *item_int = data;
int value = 0;
if (argc < 2) {
return -1;
}
value = atoi(argv[1]);
if (value < item_int->min) {
value = item_int->min;
} else if (value > item_int->max) {
value = item_int->max;
}
*(item_int->data) = value;
return 0;
}
int conf_string(const char *item, void *data, int argc, char *argv[])
{
struct config_item_string *item_string = data;
if (argc < 2) {
return -1;
}
strncpy(item_string->data, argv[1], item_string->size);
return 0;
}
int conf_yesno(const char *item, void *data, int argc, char *argv[])
{
struct config_item_yesno *item_yesno = data;
int yes = 0;
if (argc < 2) {
return -1;
}
char *value = argv[1];
if (strncmp("yes", value, sizeof("yes")) == 0 || strncmp("YES", value, sizeof("YES")) == 0) {
yes = 1;
} else if (strncmp("no", value, sizeof("no")) == 0 || strncmp("NO", value, sizeof("NO")) == 0) {
yes = 0;
}
*(item_yesno->data) = yes;
return 0;
}
int conf_size(const char *item, void *data, int argc, char *argv[])
{
/* read dns cache size */
int base = 1;
size_t size = 0;
int num = 0;
struct config_item_size *item_size = data;
char *value = argv[1];
if (strstr(value, "k") || strstr(value, "K")) {
base = 1024;
} else if (strstr(value, "m") || strstr(value, "M")) {
base = 1024 * 1024;
} else if (strstr(value, "g") || strstr(value, "G")) {
base = 1024 * 1024 * 1024;
}
num = atoi(value);
if (num < 0) {
return -1;
}
size = num * base;
if (size > item_size->max) {
size = item_size->max;
} else if (size < item_size->min) {
size = item_size->min;
}
*(item_size->data) = size;
return 0;
}
void conf_getopt_reset(void)
{
static struct option long_options[] = {{"-", 0, 0, 0}, {0, 0, 0, 0}};
int argc = 2;
char *argv[3] = {"reset", "", 0};
optind = 1;
opterr = 0;
getopt_long(argc, argv, "", long_options, NULL);
optind = 1;
opterr = 0;
}
int conf_parse_args(char *key, char *value, int *argc, char **argv)
{
char *start = NULL;
char *ptr = value;
int count = 0;
int sep_flag = ' ';
argv[0] = key;
count++;
while (*ptr != '\0') {
if (*ptr == '\\') {
char *tmp = ptr + 1;
while (*tmp != '\0') {
*(tmp - 1) = *tmp;
tmp++;
}
ptr++;
continue;
}
if (*ptr == '"' && start == NULL) {
sep_flag = '"';
start = NULL;
}
if (*ptr != sep_flag && start == NULL) {
start = ptr;
ptr++;
continue;
}
if (*ptr == sep_flag && start == NULL) {
ptr++;
continue;
}
if (*ptr == sep_flag && start) {
argv[count] = start;
*ptr = '\0';
ptr++;
start = ptr;
count++;
sep_flag = ' ';
start = NULL;
continue;
}
ptr++;
}
if (start != ptr && start) {
argv[count] = start;
count++;
}
*argc = count;
argv[count + 1] = 0;
return 0;
}
void load_exit(void)
{
return;
}
int load_conf_get_line_count(void)
{
return line_no;
}
int load_conf_file(const char *file, struct config_item *items)
{
FILE *fp = NULL;
char line[MAX_LINE_LEN];
char key[MAX_KEY_LEN];
char value[MAX_LINE_LEN];
int filed_num = 0;
int i;
int argc;
char *argv[1024];
fp = fopen(file, "r");
if (fp == NULL) {
return -1;
}
line_no = 0;
while (fgets(line, MAX_LINE_LEN, fp)) {
line_no++;
filed_num = sscanf(line, "%63s %1023[^\r\n]s", key, value);
if (filed_num <= 0) {
continue;
}
/* comment, skip */
if (key[0] == '#') {
continue;
}
/* if field format is not key = value, error */
if (filed_num != 2) {
goto errout;
}
for (i = 0;; i++) {
if (items[i].item == NULL) {
break;
}
if (strncmp(items[i].item, key, MAX_KEY_LEN) != 0) {
continue;
}
if (conf_parse_args(key, value, &argc, argv) != 0) {
continue;
}
conf_getopt_reset();
/* call item function */
if (items[i].item_func(items[i].item, items[i].data, argc, argv) != 0) {
conf_getopt_reset();
goto errout;
}
conf_getopt_reset();
break;
}
}
fclose(fp);
return 0;
errout:
if (fp) {
fclose(fp);
}
return -1;
}
int load_conf(const char *file, struct config_item items[])
{
return load_conf_file(file, items);
}

View File

@@ -19,7 +19,7 @@
#define _GNU_SOURCE
#include "art.h"
#include "atomic.h"
#include "conf.h"
#include "dns_conf.h"
#include "dns_client.h"
#include "dns_server.h"
#include "fast_ping.h"
@@ -31,14 +31,14 @@
#include <errno.h>
#include <fcntl.h>
#include <libgen.h>
#include <openssl/err.h>
#include <openssl/ssl.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#define RESOLVE_FILE "/etc/resolv.conf"
#define MAX_LINE_LEN 1024
@@ -55,6 +55,7 @@ void help(void)
" -f run forground.\n"
" -c [conf] config file.\n"
" -p [pid] pid file path\n"
" -S ignore segment fault signal.\n"
" -h show this help message.\n"
"Online help: http://pymumu.github.io/smartdns"
@@ -119,7 +120,7 @@ int smartdns_add_servers(void)
int i = 0;
int ret = 0;
for (i = 0; i < dns_conf_server_num; i++) {
ret = dns_add_server(dns_conf_servers[i].server, dns_conf_servers[i].port, dns_conf_servers[i].type);
ret = dns_add_server(dns_conf_servers[i].server, dns_conf_servers[i].port, dns_conf_servers[i].type, dns_conf_servers[i].result_flag);
if (ret != 0) {
tlog(TLOG_ERROR, "add server failed, %s:%d", dns_conf_servers[i].server, dns_conf_servers[i].port);
return -1;
@@ -206,7 +207,7 @@ int smartdns_init(void)
goto errout;
}
//tlog_setlogscreen(1);
//tlog_setlogscreen(1);
tlog_setlevel(dns_conf_log_level);
if (smartdns_init_ssl() != 0) {
@@ -262,7 +263,7 @@ void smartdns_exit(void)
fast_ping_exit();
smartdns_destroy_ssl();
tlog_exit();
load_exit();
dns_server_load_exit();
}
void sig_handle(int sig)
@@ -287,11 +288,12 @@ int main(int argc, char *argv[])
int opt;
char config_file[MAX_LINE_LEN];
char pid_file[MAX_LINE_LEN];
int signal_ignore = 0;
strncpy(config_file, SMARTDNS_CONF_FILE, MAX_LINE_LEN);
strncpy(pid_file, SMARTDNS_PID_FILE, MAX_LINE_LEN);
while ((opt = getopt(argc, argv, "fhc:p:")) != -1) {
while ((opt = getopt(argc, argv, "fhc:p:S")) != -1) {
switch (opt) {
case 'f':
is_forground = 1;
@@ -302,6 +304,9 @@ int main(int argc, char *argv[])
case 'p':
snprintf(pid_file, sizeof(pid_file), "%s", optarg);
break;
case 'S':
signal_ignore = 1;
break;
case 'h':
help();
return 1;
@@ -315,14 +320,16 @@ int main(int argc, char *argv[])
}
}
signal(SIGABRT, sig_handle);
signal(SIGPIPE, SIG_IGN);
signal(SIGBUS, sig_handle);
signal(SIGSEGV, sig_handle);
signal(SIGILL, sig_handle);
signal(SIGFPE, sig_handle);
if (signal_ignore == 0) {
signal(SIGABRT, sig_handle);
signal(SIGPIPE, SIG_IGN);
signal(SIGBUS, sig_handle);
signal(SIGSEGV, sig_handle);
signal(SIGILL, sig_handle);
signal(SIGFPE, sig_handle);
}
if (load_conf(config_file) != 0) {
if (dns_server_load_conf(config_file) != 0) {
}
if (create_pid_file(pid_file) != 0) {

View File

@@ -155,6 +155,11 @@ int set_fd_nonblock(int fd, int nonblock)
char *reverse_string(char *output, char *input, int len)
{
char *begin = output;
if (len <= 0) {
*output = 0;
return output;
}
len--;
while (len >= 0) {
*output = *(input + len);

View File

@@ -20,4 +20,6 @@ int set_fd_nonblock(int fd, int nonblock);
char *reverse_string(char *output, char *input, int len);
void print_stack(void);
#endif