diff --git a/Makefile b/Makefile index d7b9d53..681c7ef 100755 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ BIN=smartdns -OBJS=smartdns.o fast_ping.o lib/bitops.o dns_client.o dns_server.o dns.o util.o tlog.o +OBJS=smartdns.o fast_ping.o lib/bitops.o dns_client.o dns_server.o dns.o util.o tlog.o conf.o CFLAGS=-g -O0 -Wall CFLAGS +=-Iinclude CFLAGS += -DBASE_FILE_NAME=\"$(notdir $<)\" diff --git a/conf.c b/conf.c new file mode 100644 index 0000000..d7e8b3f --- /dev/null +++ b/conf.c @@ -0,0 +1,191 @@ +#include "conf.h" +#include "tlog.h" +#include +#include +#include +#include + +#define MAX_LINE_LEN 1024 +#define MAX_KEY_LEN 64 + +#define DEFAULT_DNS_PORT 53 +#define DEFAULT_DNS_CACHE_SIZE 512 + +int dns_conf_port = DEFAULT_DNS_PORT; +int dns_conf_cachesize = DEFAULT_DNS_CACHE_SIZE; +struct dns_servers dns_conf_servers[DNS_MAX_SERVERS]; +int dns_conf_server_num; + +int config_port(char *value) +{ + int port = atoi(value); + if (port <= 0 || port >= 65535) { + return -1; + } + + dns_conf_port = port; + + return 0; +} + +int config_parse_ip(char *value, char *ip, unsigned short *port) +{ + int offset = 0; + char *colon = NULL; + + if (strstr(value, "[")) { + /* ipv6 with port */ + char *bracket_end = strstr(value, "]"); + if (bracket_end == NULL) { + return -1; + } + + offset = bracket_end - value - 1; + memcpy(ip, value + 1, offset); + ip[offset] = 0; + + colon = bracket_end + 1; + + } else if (strstr(value, "::")) { + /* ipv6 without port */ + strncpy(ip, value, DNS_MAX_IPLEN); + colon = NULL; + } else { + /* ipv4 */ + colon = strstr(value, ":"); + if (colon == NULL) { + /* without port */ + strncpy(ip, value, DNS_MAX_IPLEN); + } else { + /* with port */ + offset = colon - value; + colon++; + memcpy(ip, value, offset); + } + } + + if (colon) { + /* get port num */ + *port = atoi(colon); + } else { + *port = DEFAULT_DNS_PORT; + } + + return 0; +} + +int config_server(char *value, dns_conf_server_type_t type) +{ + int index = dns_conf_server_num; + struct dns_servers *server; + if (index >= DNS_MAX_SERVERS) { + tlog(TLOG_ERROR, "exceeds max server number"); + return -1; + } + + server = &dns_conf_servers[index]; + if (config_parse_ip(value, server->server, &server->port) != 0) { + return -1; + } + + server->type = type; + dns_conf_server_num++; + + return 0; +} + +int config_server_udp(char *value) +{ + return config_server(value, DNS_CONF_TYPE_UDP); +} + +int config_server_tcp(char *value) +{ + return config_server(value, DNS_CONF_TYPE_TCP); +} + +int config_server_http(char *value) +{ + return config_server(value, DNS_CONF_TYPE_HTTP); +} + +int config_cache_size(char *value) +{ + int cache_size = atoi(value); + if (cache_size < 0) { + return -1; + } + + dns_conf_cachesize = cache_size; + + return 0; +} + +struct config_item { + const char *item; + int (*item_func)(char *value); +}; + +struct config_item config_item[] = { + {"port", config_port}, + {"server", config_server_udp}, + {"server-tcp", config_server_tcp}, + {"server-http", config_server_http}, + {"cache-size", config_cache_size}, +}; +int config_item_num = sizeof(config_item) / sizeof(struct config_item); + +int load_conf(const char *file) +{ + FILE *fp = NULL; + char line[MAX_LINE_LEN]; + char key[MAX_KEY_LEN]; + char value[MAX_LINE_LEN]; + int filed_num = 0; + int line_num = 0; + int i; + + fp = fopen(file, "r"); + if (fp == NULL) { + tlog(TLOG_ERROR, "config file %s not exist.", file); + return -1; + } + + while (fgets(line, MAX_LINE_LEN, fp)) { + line_num++; + filed_num = sscanf(line, "%63s %1023[^\r\n]s", key, value); + if (filed_num <= 0) { + continue; + } + + if (key[0] == '#') { + continue; + } + + if (filed_num != 2) { + goto errout; + } + + for (i = 0; i < config_item_num; i++) { + if (strncmp(config_item[i].item, key, MAX_KEY_LEN) != 0) { + continue; + } + + if (config_item[i].item_func(value) != 0) { + goto errout; + } + + break; + } + } + + fclose(fp); + + return 0; +errout: + printf("invalid config at line %d: %s", line_num, line); + if (fp) { + fclose(fp); + } + return -1; +} \ No newline at end of file diff --git a/conf.h b/conf.h new file mode 100644 index 0000000..f1e2b18 --- /dev/null +++ b/conf.h @@ -0,0 +1,25 @@ +#ifndef _DNS_CONF + +#define DNS_MAX_SERVERS 32 +#define DNS_MAX_IPLEN 64 + +typedef enum dns_conf_server_type { + DNS_CONF_TYPE_UDP, + DNS_CONF_TYPE_TCP, + DNS_CONF_TYPE_HTTP, +} dns_conf_server_type_t; + +struct dns_servers { + char server[DNS_MAX_IPLEN]; + unsigned short port; + dns_conf_server_type_t type; +}; + +extern int dns_conf_port; +extern int dns_conf_cachesize; +extern struct dns_servers dns_conf_servers[DNS_MAX_SERVERS]; +extern int dns_conf_server_num; + +int load_conf(const char *file); + +#endif // !_DNS_CONF \ No newline at end of file diff --git a/dns_client.c b/dns_client.c index a7dbc5b..12730ea 100644 --- a/dns_client.c +++ b/dns_client.c @@ -169,7 +169,8 @@ int _dns_client_server_add(char *server_ip, struct addrinfo *gai, dns_server_typ server_info->ss_family = gai->ai_family; server_info->addr_len = gai->ai_addrlen; server_info->type = server_type; - if (gai->ai_addrlen > sizeof(server_info->addr)) { + if (gai->ai_addrlen > sizeof(server_info->in6)) { + tlog(TLOG_ERROR, "addr len invalid, %d, %d, %d", gai->ai_addrlen, sizeof(server_info->addr), server_info->ss_family); goto errout; } memcpy(&server_info->addr, gai->ai_addr, gai->ai_addrlen); @@ -235,6 +236,7 @@ int _dns_client_server_operate(char *server_ip, int port, dns_server_type_t serv snprintf(port_s, 8, "%d", port); gai = _dns_client_getaddr(server_ip, port_s, sock_type, 0); if (gai == NULL) { + tlog(TLOG_ERROR, "get address failed, %s:%d", server_ip, port); goto errout; } diff --git a/dns_server.c b/dns_server.c index 4cddb82..aacfeae 100644 --- a/dns_server.c +++ b/dns_server.c @@ -25,6 +25,7 @@ #include "list.h" #include "tlog.h" #include "util.h" +#include "conf.h" #include #include #include @@ -784,8 +785,10 @@ int dns_server_socket(void) { int fd = -1; struct addrinfo *gai = NULL; + char port_str[8]; - gai = _dns_server_getaddr(NULL, "53", SOCK_DGRAM, 0); + snprintf(port_str, sizeof(port_str), "%d", dns_conf_port); + gai = _dns_server_getaddr(NULL, port_str, SOCK_DGRAM, 0); if (gai == NULL) { tlog(TLOG_ERROR, "get address failed.\n"); goto errout; diff --git a/smartdns.c b/smartdns.c index c980a57..7c174ba 100755 --- a/smartdns.c +++ b/smartdns.c @@ -22,6 +22,7 @@ #include "hashtable.h" #include "list.h" #include "tlog.h" +#include "conf.h" #include "atomic.h" #include #include @@ -42,13 +43,33 @@ void print_result(struct ping_host_struct *ping_host, const char *host, FAST_PIN #endif } +int smartdns_add_servers(void) +{ + int i = 0; + int ret = 0; + for (i = 0; i < dns_conf_server_num; i++) { + ret = dns_add_server(dns_conf_servers[i].server, dns_conf_servers[i].port, dns_conf_servers[i].type); + if (ret != 0) { + tlog(TLOG_ERROR, "add server failed, %s:%d", dns_conf_servers[i].server, dns_conf_servers[i].port); + return -1; + } + } + + return 0; +} + int smartdns_init() { int ret; + if (load_conf("smartdns.conf") != 0) { + fprintf(stderr, "load config failed."); + goto errout; + } + ret = tlog_init(".", "smartdns.log", 1024 * 1024, 8, 1, 0, 0); if (ret != 0) { - fprintf(stderr, "start tlog failed.\n"); + tlog(TLOG_ERROR, "start tlog failed.\n"); goto errout; } @@ -57,22 +78,29 @@ int smartdns_init() ret = fast_ping_init(); if (ret != 0) { - fprintf(stderr, "start ping failed.\n"); + tlog(TLOG_ERROR, "start ping failed.\n"); goto errout; } ret = dns_server_init(); if (ret != 0) { - fprintf(stderr, "start dns server failed.\n"); + tlog(TLOG_ERROR, "start dns server failed.\n"); goto errout; } ret = dns_client_init(); if (ret != 0) { - fprintf(stderr, "start dns client failed.\n"); + tlog(TLOG_ERROR, "start dns client failed.\n"); goto errout; } + ret = smartdns_add_servers(); + if (ret != 0) { + tlog(TLOG_ERROR, "add servers failed."); + goto errout; + } + + /* dns_add_server("192.168.1.1", 53, DNS_SERVER_UDP); dns_add_server("114.114.114.114", 53, DNS_SERVER_UDP); dns_add_server("123.207.137.88", 53, DNS_SERVER_UDP); @@ -82,7 +110,7 @@ int smartdns_init() dns_add_server("77.88.8.8", 53, DNS_SERVER_UDP); dns_add_server("202.141.162.123", 53, DNS_SERVER_UDP); dns_add_server("101.132.183.99", 53, DNS_SERVER_UDP); - + */ // int i = 0; // for(i = 0; i < 10; i++) // { @@ -249,18 +277,17 @@ int rbtree_test() void sig_handle(int sig) { tlog(TLOG_ERROR, "process exit.\n"); - sleep(1); _exit(0); } + int main(int argc, char *argv[]) { int ret; - atexit(smartdns_exit); + atexit(smartdns_exit); signal(SIGABRT, sig_handle); ret = smartdns_init(); if (ret != 0) { - fprintf(stderr, "init smartdns failed.\n"); goto errout; } diff --git a/smartdns.conf b/smartdns.conf new file mode 100644 index 0000000..9bcbf7b --- /dev/null +++ b/smartdns.conf @@ -0,0 +1,13 @@ + +# port +port 53 + +cache-size 1024 + +server 114.114.114.114 +server 123.207.137.88 +server 202.141.178.13:5353 +server 208.67.222.222:5353 +server 77.88.8.8:53 +server 202.141.162.123:53 +server 101.132.183.99:53