Browse Source

Add configuration for log, ttl, server-name
cache cname.

Nick Peng 7 years ago
parent
commit
b33affdbd5
8 changed files with 243 additions and 40 deletions
  1. 21 2
      etc/smartdns/smartdns.conf
  2. 114 9
      src/conf.c
  3. 12 6
      src/conf.h
  4. 7 1
      src/dns_cache.c
  5. 4 2
      src/dns_cache.h
  6. 50 13
      src/dns_server.c
  7. 19 3
      src/smartdns.c
  8. 16 4
      src/tlog.c

+ 21 - 2
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

+ 114 - 9
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);
 

+ 12 - 6
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);

+ 7 - 1
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);

+ 4 - 2
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);
 

+ 50 - 13
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);

+ 19 - 3
src/smartdns.c

@@ -30,6 +30,7 @@
 #include "util.h"
 #include <errno.h>
 #include <fcntl.h>
+#include <libgen.h>
 #include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -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];
+
+	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(SMARTDNS_LOG_PATH, SMARTDNS_LOG_FILE, 1024 * 512, 8, 1, 0, 0);
+	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) {

+ 16 - 4
src/tlog.c

@@ -1,5 +1,5 @@
 /*
- * ttinylog 
+ * tinylog 
  * Copyright (C) 2018 Ruilin Peng (Nick) <[email protected]> 
  * https://github.com/pymumu/tinylog
  */
@@ -20,6 +20,14 @@
 #include <sys/wait.h>
 #include <unistd.h>
 
+#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;