Nick Peng 7 лет назад
Родитель
Сommit
7e60b9bc72
8 измененных файлов с 207 добавлено и 13 удалено
  1. 7 1
      etc/smartdns/smartdns.conf
  2. 80 7
      src/conf.c
  3. 17 0
      src/conf.h
  4. 62 0
      src/dns_server.c
  5. 0 1
      src/smartdns.c
  6. 6 4
      src/tlog.c
  7. 33 0
      src/util.c
  8. 2 0
      src/util.h

+ 7 - 1
etc/smartdns/smartdns.conf

@@ -4,7 +4,7 @@
 #   IPV4: :53
 #   IPV6  [::]:53
 
-bind :53
+bind [::]:53
 
 # dns cache size
 # cache-size [number]
@@ -42,3 +42,9 @@ server 202.141.162.123:53
 # remote tcp dns server list
 # server-tcp [IP]:[PORT], default port is 53
 # server-tcp 114.114.114.114
+
+# specific address to domain
+# address /domain/ip
+# address /www.example.com/1.2.3.4
+address /cnzz.com/127.0.0.1
+address /adsame.com/127.0.0.1

+ 80 - 7
src/conf.c

@@ -1,5 +1,7 @@
 #include "conf.h"
 #include "tlog.h"
+#include "list.h"
+#include "rbtree.h"
 #include "util.h"
 #include <stdio.h>
 #include <stdlib.h>
@@ -16,6 +18,7 @@ int dns_conf_cachesize = DEFAULT_DNS_CACHE_SIZE;
 struct dns_servers dns_conf_servers[DNS_MAX_SERVERS];
 int dns_conf_server_num;
 int dns_conf_loglevel = TLOG_ERROR;
+LIST_HEAD(dns_conf_address_list);
 
 int config_bind(char *value)
 {
@@ -38,15 +41,15 @@ int config_server(char *value, dns_conf_server_type_t type)
 
 	server = &dns_conf_servers[index];
 	/* parse ip, port from value */
-    if (parse_ip(value, server->server, &port) != 0) {
+	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_DNS_PORT;
-	} 
-	
+		port = DEFAULT_DNS_PORT;
+	}
+
 	server->type = type;
 	server->port = port;
 	dns_conf_server_num++;
@@ -54,6 +57,75 @@ int config_server(char *value, dns_conf_server_type_t type)
 	return 0;
 }
 
+int config_address(char *value)
+{
+	struct dns_address *address;
+	char ip[MAX_IP_LEN];
+	char *begin = NULL;
+	char *end = NULL;
+	int len = 0;
+	struct sockaddr_storage addr;
+	socklen_t addr_len = sizeof(addr);
+
+	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;
+	}
+
+	len = end - begin;
+	memcpy(address->domain, begin, len);
+	address->domain[len] = 0;
+	strncpy(ip, end + 1, MAX_IP_LEN);
+
+	if (getaddr_by_host(ip, (struct sockaddr *)&addr, &addr_len) != 0) {
+		goto errout;
+	}
+
+	switch (addr.ss_family) {
+	case AF_INET: {
+		struct sockaddr_in *addr_in;
+		addr_in = (struct sockaddr_in *)&addr;
+		memcpy(address->ipv4_addr, &addr_in->sin_addr.s_addr, 4);
+		address->addr_type = DNS_T_A;
+	} 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;
+		} else {
+			memcpy(address->ipv6_addr, addr_in6->sin6_addr.s6_addr, 16);
+			address->addr_type = DNS_T_AAAA;
+		}
+	} break;
+	default:
+		goto errout;
+	}
+
+	list_add_tail(&address->list, &dns_conf_address_list);
+
+	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_CONF_TYPE_UDP);
@@ -106,8 +178,9 @@ struct config_item {
 struct config_item config_item[] = {
 	{"bind", config_bind},
 	{"server", config_server_udp},
-    {"server-tcp", config_server_tcp},
-    {"server-http", config_server_http},
+	{"address", config_address},
+	{"server-tcp", config_server_tcp},
+	{"server-http", config_server_http},
 	{"cache-size", config_cache_size},
 	{"loglevel", config_log_level},
 };

+ 17 - 0
src/conf.h

@@ -1,9 +1,14 @@
 #ifndef _DNS_CONF
+#define _DNS_CONF
+
+#include "list.h"
+#include "dns.h"
 
 #define DNS_MAX_SERVERS 32
 #define DNS_MAX_IPLEN 64
 #define DNS_MAX_PATH 1024
 #define DEFAULT_DNS_PORT 53
+#define DNS_MAX_CONF_CNAME_LEN 128
 
 typedef enum dns_conf_server_type {
 	DNS_CONF_TYPE_UDP,
@@ -17,6 +22,17 @@ struct dns_servers {
 	dns_conf_server_type_t type;
 };
 
+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];
+		unsigned char ipv6_addr[DNS_RR_AAAA_LEN];
+		unsigned char addr[0];
+	};
+};
+
 extern char dns_conf_server_ip[DNS_MAX_IPLEN];
 extern int dns_conf_cachesize;
 extern struct dns_servers dns_conf_servers[DNS_MAX_SERVERS];
@@ -25,6 +41,7 @@ extern int dns_conf_verbose;
 extern int dns_conf_loglevel;
 extern char dns_conf_logfile[DNS_MAX_PATH];
 extern int dns_conf_lognum;
+extern struct list_head dns_conf_address_list;
 
 int load_conf(const char *file);
 

+ 62 - 0
src/dns_server.c

@@ -669,6 +669,63 @@ errout:
 	return -1;
 }
 
+static struct dns_address *_dns_server_get_address_by_domain(char *domain)
+{
+	struct dns_address *address;
+	char *match = NULL;
+	int domain_len;
+
+	list_for_each_entry(address, &dns_conf_address_list, list)
+	{
+		domain_len = strnlen(address->domain, DNS_MAX_CNAME_LEN);
+		match = strstr(domain, address->domain);
+		if (match) {
+			if (memcmp(address->domain, match, domain_len + 1) == 0) {
+				return address;
+			}
+		}
+	}
+
+	return NULL;
+}
+
+static int _dns_server_process_address(struct dns_request *request, struct dns_packet *packet)
+{
+	struct dns_address *address = NULL;
+
+	address = _dns_server_get_address_by_domain(request->domain);
+	if (address == NULL) {
+		goto errout;
+	}
+
+	if (request->qtype != address->addr_type) {
+		goto errout;
+	}
+
+	switch (request->qtype) {
+	case DNS_T_A:
+		memcpy(request->ipv4_addr, address->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);
+		request->ttl_v6 = 600;
+		request->has_ipv6 = 1;
+		break;
+	default:
+		goto errout;
+		break;
+	}
+
+	request->rcode = DNS_RC_NOERROR;
+	_dns_reply(request);
+
+	return 0;
+errout:
+	return -1;
+}
+
 static int _dns_server_recv(unsigned char *inpacket, int inpacket_len, struct sockaddr_storage *from, socklen_t from_len)
 {
 	int decode_len;
@@ -746,6 +803,11 @@ static int _dns_server_recv(unsigned char *inpacket, int inpacket_len, struct so
 		break;
 	}
 
+	if (_dns_server_process_address(request, packet) == 0) {
+		free(request);
+		return 0;
+	}
+
 	tlog(TLOG_INFO, "query server %s from %s, qtype = %d\n", request->domain, gethost_by_addr(name, (struct sockaddr *)from, from_len), qtype);
 
 	_dns_server_request_get(request);

+ 0 - 1
src/smartdns.c

@@ -234,7 +234,6 @@ void smartdns_exit(void)
 
 void sig_handle(int sig)
 {
-
 	switch (sig) {
 	case SIGINT:
 		dns_server_stop();

+ 6 - 4
src/tlog.c

@@ -252,8 +252,8 @@ static int _tlog_log_buffer(char *buff, int maxlen, tlog_level level, const char
     struct tlog_info info;
 
     if (tlog_format == NULL) {
-        return -1;
-    }
+		return -1;
+	}
 
     if (level >= TLOG_END) {
         return -1;
@@ -288,8 +288,10 @@ int tlog_vext(tlog_level level, const char *file, int line, const char *func, vo
     int maxlen = 0;
 
     if (tlog.buff == NULL) {
-        return -1;
-    }
+        vprintf(format, ap);
+		printf("\n");
+		return -1;
+	}
 
     if (level < tlog_set_level) {
         return 0;

+ 33 - 0
src/util.c

@@ -47,6 +47,39 @@ errout:
 	return NULL;
 }
 
+int getaddr_by_host(char *host, struct sockaddr *addr, socklen_t *addr_len)
+{
+	struct addrinfo hints;
+	struct addrinfo *result = NULL;
+	int ret = 0;
+
+	memset(&hints, 0, sizeof(hints));
+	hints.ai_family = AF_UNSPEC;
+	hints.ai_socktype = SOCK_STREAM;
+
+	ret = getaddrinfo(host, "53", &hints, &result);
+	if (ret != 0) {
+		goto errout;
+	}
+
+	if (result->ai_addrlen > *addr_len) {
+		result->ai_addrlen = *addr_len;
+	}
+
+	memcpy(addr, result->ai_addr, result->ai_addrlen);
+	*addr_len = result->ai_addrlen;
+
+	freeaddrinfo(result);
+
+	return 0;
+errout:
+	if (result) {
+		freeaddrinfo(result);
+	}
+	return -1;
+
+}
+
 int parse_ip(const char *value, char *ip, int *port)
 {
 	int offset = 0;

+ 2 - 0
src/util.h

@@ -12,6 +12,8 @@ unsigned long get_tick_count(void);
 
 char *gethost_by_addr(char *host, struct sockaddr *addr, socklen_t addr_len);
 
+int getaddr_by_host(char *host, struct sockaddr *addr, socklen_t *addr_len);
+
 int parse_ip(const char *value, char *ip, int *port);
 
 int set_fd_nonblock(int fd, int nonblock);