From b33affdbd54f61233917651aa2c37bbe192d3bbc Mon Sep 17 00:00:00 2001 From: Nick Peng Date: Sat, 7 Jul 2018 01:03:32 +0800 Subject: [PATCH] Add configuration for log, ttl, server-name cache cname. --- etc/smartdns/smartdns.conf | 23 ++++++- src/conf.c | 123 ++++++++++++++++++++++++++++++++++--- src/conf.h | 18 ++++-- src/dns_cache.c | 8 ++- src/dns_cache.h | 6 +- src/dns_server.c | 63 +++++++++++++++---- src/smartdns.c | 22 ++++++- src/tlog.c | 20 ++++-- 8 files changed, 243 insertions(+), 40 deletions(-) diff --git a/etc/smartdns/smartdns.conf b/etc/smartdns/smartdns.conf index 8f117fd..443056a 100644 --- a/etc/smartdns/smartdns.conf +++ b/etc/smartdns/smartdns.conf @@ -1,3 +1,9 @@ +# dns server name, defaut is host name +# server-name, +# example: +# server-name smartdns +# + # dns server bind ip and port, default dns server port is 53. # bind [IP]:port, # example: @@ -11,9 +17,22 @@ bind [::]:53 # 0: for no cache cache-size 512 +# ttl for all resource record +# rr-ttl: ttl for all record +# rr-ttl-min: minimum ttl for resource record +# rr-ttl-max: maximum ttl for resource record +# example: +# rr-ttl 300 +# rr-ttl-min 60 +# rr-ttl-max 86400 + # set log level -# loglevel [level], level=error, warn, info, debug -loglevel error +# log-level [level], level=error, warn, info, debug +# log-size k,m,g +log-level error +# log-file /var/log/smartdns.log +# log-size 128k +# log-num 2 # remote udp dns server list # server [IP]:[PORT], default port is 53 diff --git a/src/conf.c b/src/conf.c index eb2ed0b..b9cea2f 100644 --- a/src/conf.c +++ b/src/conf.c @@ -16,9 +16,17 @@ char dns_conf_server_ip[DNS_MAX_IPLEN]; int dns_conf_cachesize = DEFAULT_DNS_CACHE_SIZE; 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_loglevel = TLOG_ERROR; +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; + art_tree dns_conf_address; +int dns_conf_rr_ttl; +int dns_conf_rr_ttl_min; +int dns_conf_rr_ttl_max; int config_bind(char *value) { @@ -28,6 +36,12 @@ int config_bind(char *value) return 0; } +int config_server_name(char *value) +{ + strncpy(dns_conf_server_name, value, DNS_MAX_CNAME_LEN); + return 0; +} + int config_server(char *value, dns_conf_server_type_t type) { int index = dns_conf_server_num; @@ -75,6 +89,7 @@ int config_address(char *value) 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; @@ -101,9 +116,9 @@ int config_address(char *value) memset(address, 0, sizeof(*address)); len = end - begin; - memcpy(address->domain, begin, len); - address->domain[len] = 0; - reverse_string(domain_key + 1, address->domain, len); + memcpy(domain, begin, len); + domain[len] = 0; + reverse_string(domain_key + 1, domain, len); if (parse_ip(end + 1, ip, &port) != 0) { goto errout; @@ -187,18 +202,102 @@ int config_log_level(char *value) { /* read log level and set */ if (strncmp("debug", value, MAX_LINE_LEN) == 0) { - dns_conf_loglevel = TLOG_DEBUG; + dns_conf_log_level = TLOG_DEBUG; } else if (strncmp("info", value, MAX_LINE_LEN) == 0) { - dns_conf_loglevel = TLOG_INFO; + dns_conf_log_level = TLOG_INFO; } else if (strncmp("warn", value, MAX_LINE_LEN) == 0) { - dns_conf_loglevel = TLOG_WARN; + dns_conf_log_level = TLOG_WARN; } else if (strncmp("error", value, MAX_LINE_LEN) == 0) { - dns_conf_loglevel = TLOG_ERROR; + dns_conf_log_level = TLOG_ERROR; } 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_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; +} + + struct config_item { const char *item; int (*item_func)(char *value); @@ -211,7 +310,13 @@ struct config_item config_item[] = { {"server-tcp", config_server_tcp}, {"server-http", config_server_http}, {"cache-size", config_cache_size}, - {"loglevel", config_log_level}, + {"log-level", config_log_level}, + {"log-file", config_log_file}, + {"log-size", config_log_size}, + {"log-num", config_log_num}, + {"rr-ttl", config_rr_ttl}, + {"rr-ttl-min", config_rr_ttl_min}, + {"rr-ttl-max", config_rr_ttl_max}, }; int config_item_num = sizeof(config_item) / sizeof(struct config_item); diff --git a/src/conf.h b/src/conf.h index 0bf4b4e..42656db 100644 --- a/src/conf.h +++ b/src/conf.h @@ -24,8 +24,6 @@ struct dns_servers { }; struct dns_address { - struct list_head list; - char domain[DNS_MAX_CONF_CNAME_LEN]; dns_type_t addr_type; union { unsigned char ipv4_addr[DNS_RR_A_LEN]; @@ -38,12 +36,20 @@ extern char dns_conf_server_ip[DNS_MAX_IPLEN]; extern int dns_conf_cachesize; extern struct dns_servers dns_conf_servers[DNS_MAX_SERVERS]; extern int dns_conf_server_num; -extern int dns_conf_verbose; -extern int dns_conf_loglevel; -extern char dns_conf_logfile[DNS_MAX_PATH]; -extern int dns_conf_lognum; + +extern int dns_conf_log_level; +extern char dns_conf_log_file[DNS_MAX_PATH]; +extern int dns_conf_log_size; +extern int dns_conf_log_num; + +extern char dns_conf_server_name[DNS_MAX_CONF_CNAME_LEN]; extern art_tree dns_conf_address; +extern int dns_conf_rr_ttl; +extern int dns_conf_rr_ttl_min; +extern int dns_conf_rr_ttl_max; + + int load_conf(const char *file); void load_exit(void); diff --git a/src/dns_cache.c b/src/dns_cache.c index cf21bce..d78ecc6 100644 --- a/src/dns_cache.c +++ b/src/dns_cache.c @@ -50,7 +50,7 @@ void dns_cache_release(struct dns_cache *dns_cache) _dns_cache_delete(dns_cache); } -int dns_cache_insert(char *domain, int ttl, dns_type_t qtype, unsigned char *addr, int addr_len) +int dns_cache_insert(char *domain, char *cname, int cname_ttl, int ttl, dns_type_t qtype, unsigned char *addr, int addr_len) { unsigned int key = 0; struct dns_cache *dns_cache = NULL; @@ -73,6 +73,7 @@ int dns_cache_insert(char *domain, int ttl, dns_type_t qtype, unsigned char *add key = hash_string(domain); key = jhash(&qtype, sizeof(qtype), key); strncpy(dns_cache->domain, domain, DNS_MAX_CNAME_LEN); + dns_cache->cname[0] = 0; dns_cache->qtype = qtype; dns_cache->ttl = ttl; atomic_set(&dns_cache->ref, 1); @@ -91,6 +92,11 @@ int dns_cache_insert(char *domain, int ttl, dns_type_t qtype, unsigned char *add goto errout; } + if (cname) { + strncpy(dns_cache->cname, cname, DNS_MAX_CNAME_LEN); + dns_cache->cname_ttl = cname_ttl; + } + pthread_mutex_lock(&dns_cache_head.lock); hash_add(dns_cache_head.cache_hash, &dns_cache->node, key); list_add_tail(&dns_cache->list, &dns_cache_head.cache_list); diff --git a/src/dns_cache.h b/src/dns_cache.h index c9ceb64..58365ef 100644 --- a/src/dns_cache.h +++ b/src/dns_cache.h @@ -12,7 +12,9 @@ struct dns_cache { struct list_head list; atomic_t ref; char domain[DNS_MAX_CNAME_LEN]; - unsigned ttl; + char cname[DNS_MAX_CNAME_LEN]; + unsigned int cname_ttl; + unsigned int ttl; time_t insert_time; dns_type_t qtype; union { @@ -24,7 +26,7 @@ struct dns_cache { int dns_cache_init(int size); -int dns_cache_insert(char *domain, int ttl, dns_type_t qtype, unsigned char *addr, int addr_len); +int dns_cache_insert(char *domain, char *cname, int cname_ttl, int ttl, dns_type_t qtype, unsigned char *addr, int addr_len); struct dns_cache *dns_cache_get(char *domain, dns_type_t qtype); diff --git a/src/dns_server.c b/src/dns_server.c index 49b29b2..c4a3a19 100644 --- a/src/dns_server.c +++ b/src/dns_server.c @@ -159,16 +159,24 @@ static int _dns_add_rrs(struct dns_packet *packet, struct dns_request *request) char *domain = request->domain; if (request->has_ptr) { char hostname[DNS_MAX_CNAME_LEN]; - if (getdomainname(hostname, DNS_MAX_CNAME_LEN) != 0) { - if (gethostname(hostname, DNS_MAX_CNAME_LEN) != 0) { - return -1; + if (dns_conf_server_name[0] == 0) { + if (getdomainname(hostname, DNS_MAX_CNAME_LEN) != 0) { + if (gethostname(hostname, DNS_MAX_CNAME_LEN) != 0) { + return -1; + } } - } - if (strncmp(hostname, "(none)", DNS_MAX_CNAME_LEN) == 0) { - if (gethostname(hostname, DNS_MAX_CNAME_LEN) != 0) { - return -1; + if (strncmp(hostname, "(none)", DNS_MAX_CNAME_LEN) == 0) { + if (gethostname(hostname, DNS_MAX_CNAME_LEN) != 0) { + return -1; + } } + + if (strncmp(hostname, "(none)", DNS_MAX_CNAME_LEN) == 0) { + strncpy(hostname, "smartdns", DNS_MAX_CNAME_LEN); + } + } else { + strncpy(hostname, dns_conf_server_name, DNS_MAX_CNAME_LEN); } ret = dns_add_PTR(packet, DNS_RRS_AN, request->domain, 30, hostname); @@ -258,6 +266,9 @@ static int _dns_reply(struct dns_request *request) int _dns_server_request_complete(struct dns_request *request) { int ret = -1; + char *cname = NULL; + int cname_ttl = 0; + if (atomic_inc_return(&request->notified) != 1) { return 0; } @@ -266,6 +277,11 @@ int _dns_server_request_complete(struct dns_request *request) return 0; } + if (request->has_cname) { + cname = request->cname; + cname_ttl = request->ttl_cname; + } + if (request->qtype == DNS_T_A) { tlog(TLOG_INFO, "result: %s, rcode: %d, %d.%d.%d.%d\n", request->domain, request->rcode, request->ipv4_addr[0], request->ipv4_addr[1], request->ipv4_addr[2], request->ipv4_addr[3]); @@ -275,7 +291,8 @@ int _dns_server_request_complete(struct dns_request *request) request->ttl_v4 = DNS_SERVER_TMOUT_TTL; } } - dns_cache_insert(request->domain, request->ttl_v4, DNS_T_A, request->ipv4_addr, DNS_RR_A_LEN); + + dns_cache_insert(request->domain, cname, cname_ttl, request->ttl_v4, DNS_T_A, request->ipv4_addr, DNS_RR_A_LEN); } else if (request->qtype == DNS_T_AAAA) { tlog(TLOG_INFO, "result :%s, rcode: %d, %.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x", request->domain, request->rcode, request->ipv6_addr[0], request->ipv6_addr[1], request->ipv6_addr[2], request->ipv6_addr[3], request->ipv6_addr[4], request->ipv6_addr[5], @@ -286,7 +303,7 @@ int _dns_server_request_complete(struct dns_request *request) if (request->has_ping_result == 0 && request->ttl_v6 > DNS_SERVER_TMOUT_TTL) { request->ttl_v6 = DNS_SERVER_TMOUT_TTL; } - dns_cache_insert(request->domain, request->ttl_v6, DNS_T_AAAA, request->ipv6_addr, DNS_RR_AAAA_LEN); + dns_cache_insert(request->domain, cname, cname_ttl, request->ttl_v6, DNS_T_AAAA, request->ipv6_addr, DNS_RR_AAAA_LEN); } } @@ -464,6 +481,20 @@ int _dns_ip_address_check_add(struct dns_request *request, unsigned char *addr, return 0; } +static int _dns_server_get_conf_ttl(int ttl) +{ + if (dns_conf_rr_ttl > 0) { + return dns_conf_rr_ttl; + } + + if (dns_conf_rr_ttl_max > 0 && ttl > dns_conf_rr_ttl_max) { + ttl = dns_conf_rr_ttl_max; + } else if (dns_conf_rr_ttl_min > 0 && ttl < dns_conf_rr_ttl_min) { + ttl = dns_conf_rr_ttl_min; + } + return ttl; +} + static int _dns_server_process_answer(struct dns_request *request, char *domain, struct dns_packet *packet) { int ttl; @@ -512,11 +543,11 @@ static int _dns_server_process_answer(struct dns_request *request, char *domain, if (request->has_ipv4 == 0) { memcpy(request->ipv4_addr, addr, DNS_RR_A_LEN); - request->ttl_v4 = ttl; + request->ttl_v4 = _dns_server_get_conf_ttl(ttl); request->has_ipv4 = 1; } else { if (ttl < request->ttl_v4) { - request->ttl_v4 = ttl; + request->ttl_v4 = _dns_server_get_conf_ttl(ttl); } } if (_dns_ip_address_check_add(request, addr, DNS_T_A) != 0) { @@ -547,11 +578,11 @@ static int _dns_server_process_answer(struct dns_request *request, char *domain, if (request->has_ipv6 == 0) { memcpy(request->ipv6_addr, addr, DNS_RR_AAAA_LEN); - request->ttl_v6 = ttl; + request->ttl_v6 = _dns_server_get_conf_ttl(ttl); request->has_ipv6 = 1; } else { if (ttl < request->ttl_v6) { - request->ttl_v6 = ttl; + request->ttl_v6 = _dns_server_get_conf_ttl(ttl); } } @@ -785,6 +816,12 @@ static int _dns_server_process_cache(struct dns_request *request, struct dns_pac break; } + if (dns_cache->cname[0] != 0) { + strncpy(request->cname, dns_cache->cname, DNS_MAX_CNAME_LEN); + request->has_cname = 1; + request->ttl_cname = dns_cache->cname_ttl; + } + request->rcode = DNS_RC_NOERROR; _dns_reply(request); dns_cache_update(dns_cache); diff --git a/src/smartdns.c b/src/smartdns.c index af849ec..abb570e 100644 --- a/src/smartdns.c +++ b/src/smartdns.c @@ -30,6 +30,7 @@ #include "util.h" #include #include +#include #include #include #include @@ -56,6 +57,8 @@ void help(void) " -c [conf] config file.\n" " -p [pid] pid file path\n" " -h show this help message.\n" + + "Online help: http://smartdns.github.io" "\n"; /* clang-format on */ printf(help); @@ -175,15 +178,28 @@ errout: int smartdns_init(void) { int ret; + char logdir[DNS_MAX_PATH]; + char logname[DNS_MAX_PATH]; - ret = tlog_init(SMARTDNS_LOG_PATH, SMARTDNS_LOG_FILE, 1024 * 512, 8, 1, 0, 0); + if (dns_conf_log_file[0] != 0) { + strncpy(logdir, dns_conf_log_file, DNS_MAX_PATH); + strncpy(logname, dns_conf_log_file, DNS_MAX_PATH); + + dirname(logdir); + basename(logname); + } else { + strncpy(logdir, SMARTDNS_LOG_PATH, DNS_MAX_PATH); + strncpy(logname, SMARTDNS_LOG_FILE, DNS_MAX_PATH); + } + + ret = tlog_init(logdir, logname, dns_conf_log_size, dns_conf_log_num, 1, 0, 0); if (ret != 0) { tlog(TLOG_ERROR, "start tlog failed.\n"); goto errout; } - tlog_setlogscreen(1); - tlog_setlevel(dns_conf_loglevel); + /* tlog_setlogscreen(1); */ + tlog_setlevel(dns_conf_log_level); if (dns_conf_server_num <= 0) { if (smartdns_load_from_resolv() != 0) { diff --git a/src/tlog.c b/src/tlog.c index 04feca7..a9d8427 100644 --- a/src/tlog.c +++ b/src/tlog.c @@ -1,5 +1,5 @@ /* - * ttinylog + * tinylog * Copyright (C) 2018 Ruilin Peng (Nick) * https://github.com/pymumu/tinylog */ @@ -20,6 +20,14 @@ #include #include +#ifndef likely +# define likely(x) __builtin_expect(!!(x), 1) +#endif + +#ifndef unlikely +# define unlikely(x) __builtin_expect(!!(x), 0) +#endif + #define TLOG_BUFF_SIZE (1024 * 128) #define TLOG_MAX_LINE_LEN (1024) #define TLOG_TMP_LEN 128 @@ -292,8 +300,12 @@ int tlog_vext(tlog_level level, const char *file, int line, const char *func, vo if (level < tlog_set_level) { return 0; } - - if (tlog.buff == NULL) { + + if (unlikely(tlog.logsize <= 0)) { + return 0; + } + + if (unlikely(tlog.buff == NULL)) { vprintf(format, ap); printf("\n"); return -1; @@ -875,7 +887,7 @@ int tlog_init(const char *logdir, const char *logname, int maxlogsize, int maxlo tlog.block = (block != 0) ? 1 : 0; tlog.waiters = 0; tlog.dropped = 0; - tlog.logsize = (maxlogsize > 0) ? maxlogsize : TLOG_LOG_SIZE; + tlog.logsize = (maxlogsize >= 0) ? maxlogsize : TLOG_LOG_SIZE; tlog.logcount = (maxlogcount > 0) ? maxlogcount : TLOG_LOG_COUNT; tlog.fd = -1; tlog.filesize = 0;