Add address rule

This commit is contained in:
Nick Peng
2018-06-25 00:03:24 +08:00
parent aaca2494e4
commit 7e60b9bc72
8 changed files with 207 additions and 13 deletions

View File

@@ -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

View File

@@ -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},
};

View File

@@ -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);

View File

@@ -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);

View File

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

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);