Add address rule
This commit is contained in:
@@ -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
|
||||
87
src/conf.c
87
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
src/conf.h
17
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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -234,7 +234,6 @@ void smartdns_exit(void)
|
||||
|
||||
void sig_handle(int sig)
|
||||
{
|
||||
|
||||
switch (sig) {
|
||||
case SIGINT:
|
||||
dns_server_stop();
|
||||
|
||||
10
src/tlog.c
10
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
src/util.c
33
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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user