code lint and optimize code style

This commit is contained in:
Nick Peng
2019-02-22 23:14:42 +08:00
parent c0c6fde39d
commit 7828f0ec27
28 changed files with 705 additions and 513 deletions

250
src/dns.c
View File

@@ -25,6 +25,7 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#include <arpa/inet.h>
#define QR_MASK 0x8000 #define QR_MASK 0x8000
#define OPCODE_MASK 0x7800 #define OPCODE_MASK 0x7800
@@ -35,10 +36,13 @@
#define RCODE_MASK 0x000F #define RCODE_MASK 0x000F
#define DNS_RR_END (0XFFFF) #define DNS_RR_END (0XFFFF)
#define UNUSED(expr) do { (void)(expr); } while (0) #define UNUSED(expr) \
do { \
(void)(expr); \
} while (0)
/* read short and move pointer */ /* read short and move pointer */
short dns_read_short(unsigned char **buffer) static short _dns_read_short(unsigned char **buffer)
{ {
unsigned short value; unsigned short value;
@@ -48,14 +52,14 @@ short dns_read_short(unsigned char **buffer)
} }
/* write char and move pointer */ /* write char and move pointer */
void dns_write_char(unsigned char **buffer, unsigned char value) static __attribute__((unused)) void _dns_write_char(unsigned char **buffer, unsigned char value)
{ {
**buffer = value; **buffer = value;
*buffer += 1; *buffer += 1;
} }
/* read char and move pointer */ /* read char and move pointer */
unsigned char dns_read_char(unsigned char **buffer) static unsigned char _dns_read_char(unsigned char **buffer)
{ {
unsigned char value = **buffer; unsigned char value = **buffer;
*buffer += 1; *buffer += 1;
@@ -63,7 +67,7 @@ unsigned char dns_read_char(unsigned char **buffer)
} }
/* write short and move pointer */ /* write short and move pointer */
void dns_write_short(unsigned char **buffer, unsigned short value) static void _dns_write_short(unsigned char **buffer, unsigned short value)
{ {
value = htons(value); value = htons(value);
*((unsigned short *)(*buffer)) = value; *((unsigned short *)(*buffer)) = value;
@@ -71,7 +75,7 @@ void dns_write_short(unsigned char **buffer, unsigned short value)
} }
/* write int and move pointer */ /* write int and move pointer */
void dns_write_int(unsigned char **buffer, unsigned int value) static void _dns_write_int(unsigned char **buffer, unsigned int value)
{ {
value = htonl(value); value = htonl(value);
*((unsigned int *)(*buffer)) = value; *((unsigned int *)(*buffer)) = value;
@@ -79,7 +83,7 @@ void dns_write_int(unsigned char **buffer, unsigned int value)
} }
/* read int and move pointer */ /* read int and move pointer */
unsigned int dns_read_int(unsigned char **buffer) static unsigned int _dns_read_int(unsigned char **buffer)
{ {
unsigned int value; unsigned int value;
@@ -138,7 +142,7 @@ struct dns_rrs *dns_get_rrs_next(struct dns_packet *packet, struct dns_rrs *rrs)
} }
/* iterator add rrs begin */ /* iterator add rrs begin */
unsigned char *_dns_add_rrs_start(struct dns_packet *packet, int *maxlen) static unsigned char *_dns_add_rrs_start(struct dns_packet *packet, int *maxlen)
{ {
struct dns_rrs *rrs; struct dns_rrs *rrs;
unsigned char *end = packet->data + packet->len; unsigned char *end = packet->data + packet->len;
@@ -153,7 +157,7 @@ unsigned char *_dns_add_rrs_start(struct dns_packet *packet, int *maxlen)
} }
/* iterator add rrs end */ /* iterator add rrs end */
int dns_rr_add_end(struct dns_packet *packet, int type, dns_type_t rtype, int len) static int _dns_rr_add_end(struct dns_packet *packet, int type, dns_type_t rtype, int len)
{ {
struct dns_rrs *rrs; struct dns_rrs *rrs;
struct dns_rrs *rrs_next; struct dns_rrs *rrs_next;
@@ -221,7 +225,7 @@ static inline int _dns_data_left_len(struct dns_data_context *data_context)
return data_context->maxsize - (data_context->ptr - data_context->data); return data_context->maxsize - (data_context->ptr - data_context->data);
} }
int _dns_add_qr_head(struct dns_data_context *data_context, char *domain, int qtype, int qclass) static int _dns_add_qr_head(struct dns_data_context *data_context, char *domain, int qtype, int qclass)
{ {
/* question head */ /* question head */
/* |domain | /* |domain |
@@ -253,7 +257,7 @@ int _dns_add_qr_head(struct dns_data_context *data_context, char *domain, int qt
return 0; return 0;
} }
int _dns_get_qr_head(struct dns_data_context *data_context, char *domain, int maxsize, int *qtype, int *qclass) static int _dns_get_qr_head(struct dns_data_context *data_context, char *domain, int maxsize, int *qtype, int *qclass)
{ {
int i; int i;
/* question head */ /* question head */
@@ -291,7 +295,7 @@ int _dns_get_qr_head(struct dns_data_context *data_context, char *domain, int ma
return 0; return 0;
} }
int _dns_add_rr_head(struct dns_data_context *data_context, char *domain, int qtype, int qclass, int ttl, int rr_len) static int _dns_add_rr_head(struct dns_data_context *data_context, char *domain, int qtype, int qclass, int ttl, int rr_len)
{ {
int len = 0; int len = 0;
@@ -319,7 +323,7 @@ int _dns_add_rr_head(struct dns_data_context *data_context, char *domain, int qt
return 0; return 0;
} }
int _dns_get_rr_head(struct dns_data_context *data_context, char *domain, int maxsize, int *qtype, int *qclass, int *ttl, int *rr_len) static int _dns_get_rr_head(struct dns_data_context *data_context, char *domain, int maxsize, int *qtype, int *qclass, int *ttl, int *rr_len)
{ {
int len = 0; int len = 0;
@@ -344,7 +348,7 @@ int _dns_get_rr_head(struct dns_data_context *data_context, char *domain, int ma
return len; return len;
} }
int dns_add_RAW(struct dns_packet *packet, dns_rr_type rrtype, dns_type_t rtype, char *domain, int ttl, void *raw, int raw_len) static int _dns_add_RAW(struct dns_packet *packet, dns_rr_type rrtype, dns_type_t rtype, char *domain, int ttl, void *raw, int raw_len)
{ {
int maxlen = 0; int maxlen = 0;
int len = 0; int len = 0;
@@ -380,10 +384,10 @@ int dns_add_RAW(struct dns_packet *packet, dns_rr_type rrtype, dns_type_t rtype,
data_context.ptr += raw_len; data_context.ptr += raw_len;
len = data_context.ptr - data_context.data; len = data_context.ptr - data_context.data;
return dns_rr_add_end(packet, rrtype, rtype, len); return _dns_rr_add_end(packet, rrtype, rtype, len);
} }
int dns_get_RAW(struct dns_rrs *rrs, char *domain, int maxsize, int *ttl, void *raw, int *raw_len) static int _dns_get_RAW(struct dns_rrs *rrs, char *domain, int maxsize, int *ttl, void *raw, int *raw_len)
{ {
int qtype = 0; int qtype = 0;
int qclass = 0; int qclass = 0;
@@ -421,10 +425,10 @@ int dns_get_RAW(struct dns_rrs *rrs, char *domain, int maxsize, int *ttl, void *
return 0; return 0;
} }
int dns_add_OPT(struct dns_packet *packet, dns_rr_type type, unsigned short opt_code, unsigned short opt_len, struct dns_opt *opt) static int __attribute__((unused)) _dns_add_OPT(struct dns_packet *packet, dns_rr_type type, unsigned short opt_code, unsigned short opt_len, struct dns_opt *opt)
{ {
// TODO // TODO
int maxlen = 0; int maxlen = 0;
int len = 0; int len = 0;
struct dns_data_context data_context; struct dns_data_context data_context;
@@ -432,15 +436,15 @@ int dns_add_OPT(struct dns_packet *packet, dns_rr_type type, unsigned short opt_
int ttl = 0; int ttl = 0;
/* /*
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
0: | OPTION-CODE | 0: | OPTION-CODE |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
2: | OPTION-LENGTH | 2: | OPTION-LENGTH |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
4: | | 4: | |
/ OPTION-DATA / / OPTION-DATA /
/ / / /
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
*/ */
unsigned char *data = _dns_add_rrs_start(packet, &maxlen); unsigned char *data = _dns_add_rrs_start(packet, &maxlen);
if (data == NULL) { if (data == NULL) {
@@ -468,10 +472,10 @@ int dns_add_OPT(struct dns_packet *packet, dns_rr_type type, unsigned short opt_
data_context.ptr += total_len; data_context.ptr += total_len;
len = data_context.ptr - data_context.data; len = data_context.ptr - data_context.data;
return dns_rr_add_end(packet, type, DNS_T_OPT, len); return _dns_rr_add_end(packet, type, DNS_T_OPT, len);
} }
int dns_get_OPT(struct dns_rrs *rrs, unsigned short *opt_code, unsigned short *opt_len, struct dns_opt *opt, int *opt_maxlen) static int __attribute__((unused)) _dns_get_OPT(struct dns_rrs *rrs, unsigned short *opt_code, unsigned short *opt_len, struct dns_opt *opt, int *opt_maxlen)
{ {
// TODO // TODO
@@ -509,63 +513,62 @@ int dns_get_OPT(struct dns_rrs *rrs, unsigned short *opt_code, unsigned short *o
return 0; return 0;
} }
int dns_add_CNAME(struct dns_packet *packet, dns_rr_type type, char *domain, int ttl, char *cname) int dns_add_CNAME(struct dns_packet *packet, dns_rr_type type, char *domain, int ttl, char *cname)
{ {
int rr_len = strnlen(cname, DNS_MAX_CNAME_LEN) + 1; int rr_len = strnlen(cname, DNS_MAX_CNAME_LEN) + 1;
return dns_add_RAW(packet, type, DNS_T_CNAME, domain, ttl, cname, rr_len); return _dns_add_RAW(packet, type, DNS_T_CNAME, domain, ttl, cname, rr_len);
} }
int dns_get_CNAME(struct dns_rrs *rrs, char *domain, int maxsize, int *ttl, char *cname, int cname_size) int dns_get_CNAME(struct dns_rrs *rrs, char *domain, int maxsize, int *ttl, char *cname, int cname_size)
{ {
int len = cname_size; int len = cname_size;
return dns_get_RAW(rrs, domain, maxsize, ttl, cname, &len); return _dns_get_RAW(rrs, domain, maxsize, ttl, cname, &len);
} }
int dns_add_A(struct dns_packet *packet, dns_rr_type type, char *domain, int ttl, unsigned char addr[DNS_RR_A_LEN]) int dns_add_A(struct dns_packet *packet, dns_rr_type type, char *domain, int ttl, unsigned char addr[DNS_RR_A_LEN])
{ {
return dns_add_RAW(packet, type, DNS_T_A, domain, ttl, addr, DNS_RR_A_LEN); return _dns_add_RAW(packet, type, DNS_T_A, domain, ttl, addr, DNS_RR_A_LEN);
} }
int dns_get_A(struct dns_rrs *rrs, char *domain, int maxsize, int *ttl, unsigned char addr[DNS_RR_A_LEN]) int dns_get_A(struct dns_rrs *rrs, char *domain, int maxsize, int *ttl, unsigned char addr[DNS_RR_A_LEN])
{ {
int len = DNS_RR_A_LEN; int len = DNS_RR_A_LEN;
return dns_get_RAW(rrs, domain, maxsize, ttl, addr, &len); return _dns_get_RAW(rrs, domain, maxsize, ttl, addr, &len);
} }
int dns_add_PTR(struct dns_packet *packet, dns_rr_type type, char *domain, int ttl, char *cname) int dns_add_PTR(struct dns_packet *packet, dns_rr_type type, char *domain, int ttl, char *cname)
{ {
int rr_len = strnlen(cname, DNS_MAX_CNAME_LEN) + 1; int rr_len = strnlen(cname, DNS_MAX_CNAME_LEN) + 1;
return dns_add_RAW(packet, type, DNS_T_PTR, domain, ttl, cname, rr_len); return _dns_add_RAW(packet, type, DNS_T_PTR, domain, ttl, cname, rr_len);
} }
int dns_get_PTR(struct dns_rrs *rrs, char *domain, int maxsize, int *ttl, char *cname, int cname_size) int dns_get_PTR(struct dns_rrs *rrs, char *domain, int maxsize, int *ttl, char *cname, int cname_size)
{ {
int len = cname_size; int len = cname_size;
return dns_get_RAW(rrs, domain, maxsize, ttl, cname, &len); return _dns_get_RAW(rrs, domain, maxsize, ttl, cname, &len);
} }
int dns_add_NS(struct dns_packet *packet, dns_rr_type type, char *domain, int ttl, char *cname) int dns_add_NS(struct dns_packet *packet, dns_rr_type type, char *domain, int ttl, char *cname)
{ {
int rr_len = strnlen(cname, DNS_MAX_CNAME_LEN) + 1; int rr_len = strnlen(cname, DNS_MAX_CNAME_LEN) + 1;
return dns_add_RAW(packet, type, DNS_T_NS, domain, ttl, cname, rr_len); return _dns_add_RAW(packet, type, DNS_T_NS, domain, ttl, cname, rr_len);
} }
int dns_get_NS(struct dns_rrs *rrs, char *domain, int maxsize, int *ttl, char *cname, int cname_size) int dns_get_NS(struct dns_rrs *rrs, char *domain, int maxsize, int *ttl, char *cname, int cname_size)
{ {
int len = cname_size; int len = cname_size;
return dns_get_RAW(rrs, domain, maxsize, ttl, cname, &len); return _dns_get_RAW(rrs, domain, maxsize, ttl, cname, &len);
} }
int dns_add_AAAA(struct dns_packet *packet, dns_rr_type type, char *domain, int ttl, unsigned char addr[DNS_RR_AAAA_LEN]) int dns_add_AAAA(struct dns_packet *packet, dns_rr_type type, char *domain, int ttl, unsigned char addr[DNS_RR_AAAA_LEN])
{ {
return dns_add_RAW(packet, type, DNS_T_AAAA, domain, ttl, addr, DNS_RR_AAAA_LEN); return _dns_add_RAW(packet, type, DNS_T_AAAA, domain, ttl, addr, DNS_RR_AAAA_LEN);
} }
int dns_get_AAAA(struct dns_rrs *rrs, char *domain, int maxsize, int *ttl, unsigned char addr[DNS_RR_AAAA_LEN]) int dns_get_AAAA(struct dns_rrs *rrs, char *domain, int maxsize, int *ttl, unsigned char addr[DNS_RR_AAAA_LEN])
{ {
int len = DNS_RR_AAAA_LEN; int len = DNS_RR_AAAA_LEN;
return dns_get_RAW(rrs, domain, maxsize, ttl, addr, &len); return _dns_get_RAW(rrs, domain, maxsize, ttl, addr, &len);
} }
int dns_add_SOA(struct dns_packet *packet, dns_rr_type type, char *domain, int ttl, struct dns_soa *soa) int dns_add_SOA(struct dns_packet *packet, dns_rr_type type, char *domain, int ttl, struct dns_soa *soa)
@@ -598,7 +601,7 @@ int dns_add_SOA(struct dns_packet *packet, dns_rr_type type, char *domain, int t
ptr += 4; ptr += 4;
len = ptr - data; len = ptr - data;
return dns_add_RAW(packet, type, DNS_T_SOA, domain, ttl, data, len); return _dns_add_RAW(packet, type, DNS_T_SOA, domain, ttl, data, len);
} }
int dns_get_SOA(struct dns_rrs *rrs, char *domain, int maxsize, int *ttl, struct dns_soa *soa) int dns_get_SOA(struct dns_rrs *rrs, char *domain, int maxsize, int *ttl, struct dns_soa *soa)
@@ -616,7 +619,7 @@ int dns_get_SOA(struct dns_rrs *rrs, char *domain, int maxsize, int *ttl, struct
*| expire | *| expire |
*| minimum | *| minimum |
*/ */
if (dns_get_RAW(rrs, domain, maxsize, ttl, data, &len) != 0) { if (_dns_get_RAW(rrs, domain, maxsize, ttl, data, &len) != 0) {
return -1; return -1;
} }
@@ -674,7 +677,7 @@ int dns_add_OPT_ECS(struct dns_packet *packet, struct dns_opt_ecs *ecs)
len += (ecs->source_prefix / 8); len += (ecs->source_prefix / 8);
len += (ecs->source_prefix % 8 > 0) ? 1 : 0; len += (ecs->source_prefix % 8 > 0) ? 1 : 0;
return dns_add_RAW(packet, DNS_RRS_OPT, DNS_OPT_T_ECS, "", 0, opt_data, len); return _dns_add_RAW(packet, DNS_RRS_OPT, DNS_OPT_T_ECS, "", 0, opt_data, len);
} }
int dns_get_OPT_ECS(struct dns_rrs *rrs, unsigned short *opt_code, unsigned short *opt_len, struct dns_opt_ecs *ecs) int dns_get_OPT_ECS(struct dns_rrs *rrs, unsigned short *opt_code, unsigned short *opt_len, struct dns_opt_ecs *ecs)
@@ -684,7 +687,7 @@ int dns_get_OPT_ECS(struct dns_rrs *rrs, unsigned short *opt_code, unsigned shor
int len = DNS_MAX_OPT_LEN; int len = DNS_MAX_OPT_LEN;
int ttl = 0; int ttl = 0;
if (dns_get_RAW(rrs, 0, 0, &ttl, opt_data, &len) != 0) { if (_dns_get_RAW(rrs, NULL, 0, &ttl, opt_data, &len) != 0) {
return -1; return -1;
} }
@@ -727,7 +730,7 @@ int dns_add_domain(struct dns_packet *packet, char *domain, int qtype, int qclas
len = data_context.ptr - data_context.data; len = data_context.ptr - data_context.data;
return dns_rr_add_end(packet, DNS_RRS_QD, DNS_T_CNAME, len); return _dns_rr_add_end(packet, DNS_RRS_QD, DNS_T_CNAME, len);
} }
int dns_get_domain(struct dns_rrs *rrs, char *domain, int maxsize, int *qtype, int *qclass) int dns_get_domain(struct dns_rrs *rrs, char *domain, int maxsize, int *qtype, int *qclass)
@@ -778,8 +781,8 @@ static int _dns_decode_head(struct dns_context *context)
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
*/ */
head->id = dns_read_short(&context->ptr); head->id = _dns_read_short(&context->ptr);
fields = dns_read_short(&context->ptr); fields = _dns_read_short(&context->ptr);
head->qr = (fields & QR_MASK) >> 15; head->qr = (fields & QR_MASK) >> 15;
head->opcode = (fields & OPCODE_MASK) >> 11; head->opcode = (fields & OPCODE_MASK) >> 11;
head->aa = (fields & AA_MASK) >> 10; head->aa = (fields & AA_MASK) >> 10;
@@ -787,10 +790,10 @@ static int _dns_decode_head(struct dns_context *context)
head->rd = (fields & RD_MASK) >> 8; head->rd = (fields & RD_MASK) >> 8;
head->ra = (fields & RA_MASK) >> 7; head->ra = (fields & RA_MASK) >> 7;
head->rcode = (fields & RCODE_MASK) >> 0; head->rcode = (fields & RCODE_MASK) >> 0;
head->qdcount = dns_read_short(&context->ptr); head->qdcount = _dns_read_short(&context->ptr);
head->ancount = dns_read_short(&context->ptr); head->ancount = _dns_read_short(&context->ptr);
head->nscount = dns_read_short(&context->ptr); head->nscount = _dns_read_short(&context->ptr);
head->nrcount = dns_read_short(&context->ptr); head->nrcount = _dns_read_short(&context->ptr);
return 0; return 0;
} }
@@ -804,7 +807,7 @@ static int _dns_encode_head(struct dns_context *context)
return -1; return -1;
} }
dns_write_short(&context->ptr, head->id); _dns_write_short(&context->ptr, head->id);
int fields = 0; int fields = 0;
fields |= (head->qr << 15) & QR_MASK; fields |= (head->qr << 15) & QR_MASK;
@@ -814,12 +817,12 @@ static int _dns_encode_head(struct dns_context *context)
fields |= (head->rd << 8) & RD_MASK; fields |= (head->rd << 8) & RD_MASK;
fields |= (head->ra << 7) & RA_MASK; fields |= (head->ra << 7) & RA_MASK;
fields |= (head->rcode << 0) & RCODE_MASK; fields |= (head->rcode << 0) & RCODE_MASK;
dns_write_short(&context->ptr, fields); _dns_write_short(&context->ptr, fields);
dns_write_short(&context->ptr, head->qdcount); _dns_write_short(&context->ptr, head->qdcount);
dns_write_short(&context->ptr, head->ancount); _dns_write_short(&context->ptr, head->ancount);
dns_write_short(&context->ptr, head->nscount); _dns_write_short(&context->ptr, head->nscount);
dns_write_short(&context->ptr, head->nrcount); _dns_write_short(&context->ptr, head->nrcount);
return len; return len;
} }
@@ -830,10 +833,10 @@ static int _dns_encode_head_count(struct dns_context *context)
unsigned char *ptr = context->data; unsigned char *ptr = context->data;
ptr += 4; ptr += 4;
dns_write_short(&ptr, head->qdcount); _dns_write_short(&ptr, head->qdcount);
dns_write_short(&ptr, head->ancount); _dns_write_short(&ptr, head->ancount);
dns_write_short(&ptr, head->nscount); _dns_write_short(&ptr, head->nscount);
dns_write_short(&ptr, head->nrcount); _dns_write_short(&ptr, head->nrcount);
return len; return len;
} }
@@ -851,7 +854,7 @@ static int _dns_decode_domain(struct dns_context *context, char *output, int siz
if (ptr > context->data + context->maxsize || ptr < context->data || output_len >= size - 1 || ptr_jump > 4) { if (ptr > context->data + context->maxsize || ptr < context->data || output_len >= size - 1 || ptr_jump > 4) {
return -1; return -1;
} }
len = *ptr; len = *ptr;
if (len == 0) { if (len == 0) {
*output = 0; *output = 0;
@@ -871,7 +874,7 @@ static int _dns_decode_domain(struct dns_context *context, char *output, int siz
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
*/ */
/* read offset */ /* read offset */
len = dns_read_short(&ptr) & 0x3FFF; len = _dns_read_short(&ptr) & 0x3FFF;
if (is_compressed == 0) { if (is_compressed == 0) {
context->ptr = ptr; context->ptr = ptr;
} }
@@ -958,7 +961,7 @@ static int _dns_decode_qr_head(struct dns_context *context, char *domain, int do
{ {
int ret = 0; int ret = 0;
/* /*
0 1 2 3 4 5 6 7 8 9 A B C D E F 0 1 2 3 4 5 6 7 8 9 A B C D E F
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| | | |
/ / / /
@@ -981,8 +984,8 @@ static int _dns_decode_qr_head(struct dns_context *context, char *domain, int do
return -1; return -1;
} }
*qtype = dns_read_short(&context->ptr); *qtype = _dns_read_short(&context->ptr);
*qclass = dns_read_short(&context->ptr); *qclass = _dns_read_short(&context->ptr);
return 0; return 0;
} }
@@ -999,8 +1002,8 @@ static int _dns_encode_qr_head(struct dns_context *context, char *domain, int qt
return -1; return -1;
} }
dns_write_short(&context->ptr, qtype); _dns_write_short(&context->ptr, qtype);
dns_write_short(&context->ptr, qclass); _dns_write_short(&context->ptr, qclass);
return 0; return 0;
} }
@@ -1020,8 +1023,8 @@ static int _dns_decode_rr_head(struct dns_context *context, char *domain, int do
return -1; return -1;
} }
*ttl = dns_read_int(&context->ptr); *ttl = _dns_read_int(&context->ptr);
*rr_len = dns_read_short(&context->ptr); *rr_len = _dns_read_short(&context->ptr);
return 0; return 0;
} }
@@ -1038,8 +1041,8 @@ static int _dns_encode_rr_head(struct dns_context *context, char *domain, int qt
return -1; return -1;
} }
dns_write_int(&context->ptr, ttl); _dns_write_int(&context->ptr, ttl);
dns_write_short(&context->ptr, rr_len); _dns_write_short(&context->ptr, rr_len);
return 0; return 0;
} }
@@ -1054,7 +1057,7 @@ static int _dns_encode_raw(struct dns_context *context, struct dns_rrs *rrs)
int rr_len; int rr_len;
struct dns_data_context data_context; struct dns_data_context data_context;
/* /*
0 1 2 3 4 5 6 7 8 9 A B C D E F 0 1 2 3 4 5 6 7 8 9 A B C D E F
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| | | |
/ / / /
@@ -1111,7 +1114,7 @@ static int _dns_decode_raw(struct dns_context *context, unsigned char *raw, int
return 0; return 0;
} }
int _dns_decode_CNAME(struct dns_context *context, char *cname, int cname_size) static int _dns_decode_CNAME(struct dns_context *context, char *cname, int cname_size)
{ {
int ret = 0; int ret = 0;
ret = _dns_decode_domain(context, cname, cname_size); ret = _dns_decode_domain(context, cname, cname_size);
@@ -1122,7 +1125,7 @@ int _dns_decode_CNAME(struct dns_context *context, char *cname, int cname_size)
return 0; return 0;
} }
int _dns_encode_CNAME(struct dns_context *context, struct dns_rrs *rrs) static int _dns_encode_CNAME(struct dns_context *context, struct dns_rrs *rrs)
{ {
int ret; int ret;
int qtype = 0; int qtype = 0;
@@ -1162,7 +1165,7 @@ int _dns_encode_CNAME(struct dns_context *context, struct dns_rrs *rrs)
return 0; return 0;
} }
int _dns_decode_SOA(struct dns_context *context, struct dns_soa *soa) static int _dns_decode_SOA(struct dns_context *context, struct dns_soa *soa)
{ {
int ret = 0; int ret = 0;
ret = _dns_decode_domain(context, soa->mname, DNS_MAX_CNAME_LEN - 1); ret = _dns_decode_domain(context, soa->mname, DNS_MAX_CNAME_LEN - 1);
@@ -1179,16 +1182,16 @@ int _dns_decode_SOA(struct dns_context *context, struct dns_soa *soa)
return -1; return -1;
} }
soa->serial = dns_read_int(&context->ptr); soa->serial = _dns_read_int(&context->ptr);
soa->refresh = dns_read_int(&context->ptr); soa->refresh = _dns_read_int(&context->ptr);
soa->retry = dns_read_int(&context->ptr); soa->retry = _dns_read_int(&context->ptr);
soa->expire = dns_read_int(&context->ptr); soa->expire = _dns_read_int(&context->ptr);
soa->minimum = dns_read_int(&context->ptr); soa->minimum = _dns_read_int(&context->ptr);
return 0; return 0;
} }
int _dns_encode_SOA(struct dns_context *context, struct dns_rrs *rrs) static int _dns_encode_SOA(struct dns_context *context, struct dns_rrs *rrs)
{ {
int ret; int ret;
int qtype = 0; int qtype = 0;
@@ -1238,33 +1241,32 @@ int _dns_encode_SOA(struct dns_context *context, struct dns_rrs *rrs)
return -1; return -1;
} }
dns_write_int(&context->ptr, *(unsigned int *)data_context.ptr); _dns_write_int(&context->ptr, *(unsigned int *)data_context.ptr);
data_context.ptr += 4; data_context.ptr += 4;
dns_write_int(&context->ptr, *(unsigned int *)data_context.ptr); _dns_write_int(&context->ptr, *(unsigned int *)data_context.ptr);
data_context.ptr += 4; data_context.ptr += 4;
dns_write_int(&context->ptr, *(unsigned int *)data_context.ptr); _dns_write_int(&context->ptr, *(unsigned int *)data_context.ptr);
data_context.ptr += 4; data_context.ptr += 4;
dns_write_int(&context->ptr, *(unsigned int *)data_context.ptr); _dns_write_int(&context->ptr, *(unsigned int *)data_context.ptr);
data_context.ptr += 4; data_context.ptr += 4;
dns_write_int(&context->ptr, *(unsigned int *)data_context.ptr); _dns_write_int(&context->ptr, *(unsigned int *)data_context.ptr);
data_context.ptr += 4; data_context.ptr += 4;
return 0; return 0;
} }
static int _dns_decode_opt_ecs(struct dns_context *context, struct dns_opt_ecs *ecs) static int _dns_decode_opt_ecs(struct dns_context *context, struct dns_opt_ecs *ecs)
{ {
// TODO // TODO
int len = 0; int len = 0;
if (_dns_left_len(context) < 4) { if (_dns_left_len(context) < 4) {
return -1; return -1;
} }
ecs->family = dns_read_short(&context->ptr); ecs->family = _dns_read_short(&context->ptr);
ecs->source_prefix = dns_read_char(&context->ptr); ecs->source_prefix = _dns_read_char(&context->ptr);
ecs->scope_prefix = dns_read_char(&context->ptr); ecs->scope_prefix = _dns_read_char(&context->ptr);
len = (ecs->source_prefix / 8); len = (ecs->source_prefix / 8);
len += (ecs->source_prefix % 8 > 0) ? 1 : 0; len += (ecs->source_prefix % 8 > 0) ? 1 : 0;
@@ -1281,7 +1283,7 @@ static int _dns_decode_opt_ecs(struct dns_context *context, struct dns_opt_ecs *
return 0; return 0;
} }
int _dns_encode_OPT(struct dns_context *context, struct dns_rrs *rrs) static int _dns_encode_OPT(struct dns_context *context, struct dns_rrs *rrs)
{ {
int ret; int ret;
int opt_code = 0; int opt_code = 0;
@@ -1304,15 +1306,15 @@ int _dns_encode_OPT(struct dns_context *context, struct dns_rrs *rrs)
return -1; return -1;
} }
dns_write_short(&context->ptr, opt_code); _dns_write_short(&context->ptr, opt_code);
dns_write_short(&context->ptr, rr_len); _dns_write_short(&context->ptr, rr_len);
memcpy(context->ptr, data_context.ptr, rr_len); memcpy(context->ptr, data_context.ptr, rr_len);
context->ptr += rr_len; context->ptr += rr_len;
return 0; return 0;
} }
int _dns_get_opts_data_len(struct dns_packet *packet, struct dns_rrs *rrs, int count) static int _dns_get_opts_data_len(struct dns_packet *packet, struct dns_rrs *rrs, int count)
{ {
int i = 0; int i = 0;
int len = 0; int len = 0;
@@ -1340,7 +1342,7 @@ int _dns_get_opts_data_len(struct dns_packet *packet, struct dns_rrs *rrs, int c
return len; return len;
} }
int _dns_encode_opts(struct dns_packet *packet, struct dns_context *context, struct dns_rrs *rrs, int count) static int _dns_encode_opts(struct dns_packet *packet, struct dns_context *context, struct dns_rrs *rrs, int count)
{ {
int i = 0; int i = 0;
int len = 0; int len = 0;
@@ -1382,7 +1384,7 @@ static int _dns_decode_opt(struct dns_context *context, dns_rr_type type, unsign
unsigned short opt_code; unsigned short opt_code;
unsigned short opt_len; unsigned short opt_len;
unsigned short ercode = (ttl >> 16) & 0xFFFF; unsigned short ercode = (ttl >> 16) & 0xFFFF;
unsigned short ever = (ttl) & 0xFFFF; unsigned short ever = (ttl)&0xFFFF;
unsigned char *start = context->ptr; unsigned char *start = context->ptr;
struct dns_packet *packet = context->packet; struct dns_packet *packet = context->packet;
int ret = 0; int ret = 0;
@@ -1390,46 +1392,46 @@ static int _dns_decode_opt(struct dns_context *context, dns_rr_type type, unsign
UNUSED(ever); UNUSED(ever);
/* /*
Field Name Field Type Description Field Name Field Type Description
------------------------------------------------------ ------------------------------------------------------
NAME domain name empty (root domain) NAME domain name empty (root domain)
TYPE u_int16_t OPT TYPE u_int16_t OPT
CLASS u_int16_t sender's UDP payload size CLASS u_int16_t sender's UDP payload size
TTL u_int32_t extended RCODE and flags TTL u_int32_t extended RCODE and flags
RDLEN u_int16_t describes RDATA RDLEN u_int16_t describes RDATA
RDATA octet stream {attribute,value} pairs RDATA octet stream {attribute,value} pairs
+0 (MSB) +1 (LSB) +0 (MSB) +1 (LSB)
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
0: | OPTION-CODE | 0: | OPTION-CODE |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
2: | OPTION-LENGTH | 2: | OPTION-LENGTH |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
4: | | 4: | |
/ OPTION-DATA / / OPTION-DATA /
/ / / /
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
TTL TTL
+0 (MSB) +1 (LSB) +0 (MSB) +1 (LSB)
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
0: | EXTENDED-RCODE | VERSION | 0: | EXTENDED-RCODE | VERSION |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
2: | Z | 2: | Z |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
*/ */
if (ercode != 0) { if (ercode != 0) {
tlog(TLOG_ERROR, "extend rcode invalid."); tlog(TLOG_ERROR, "extend rcode invalid.");
return -1; return -1;
} }
while (context->ptr - start < rr_len) { while (context->ptr - start < rr_len) {
if (_dns_left_len(context) < 4) { if (_dns_left_len(context) < 4) {
return -1; return -1;
} }
opt_code = dns_read_short(&context->ptr); opt_code = _dns_read_short(&context->ptr);
opt_len = dns_read_short(&context->ptr); opt_len = _dns_read_short(&context->ptr);
if (_dns_left_len(context) < opt_len) { if (_dns_left_len(context) < opt_len) {
tlog(TLOG_ERROR, "read opt data failed, opt_code = %d, opt_le = %d", opt_code, opt_len); tlog(TLOG_ERROR, "read opt data failed, opt_code = %d, opt_le = %d", opt_code, opt_len);
@@ -1441,13 +1443,13 @@ static int _dns_decode_opt(struct dns_context *context, dns_rr_type type, unsign
case DNS_OPT_T_ECS: { case DNS_OPT_T_ECS: {
struct dns_opt_ecs ecs; struct dns_opt_ecs ecs;
ret = _dns_decode_opt_ecs(context, &ecs); ret = _dns_decode_opt_ecs(context, &ecs);
if (ret != 0 ) { if (ret != 0) {
tlog(TLOG_ERROR, "decode ecs failed."); tlog(TLOG_ERROR, "decode ecs failed.");
return -1; return -1;
} }
ret = dns_add_OPT_ECS(packet, &ecs); ret = dns_add_OPT_ECS(packet, &ecs);
if (ret != 0 ) { if (ret != 0) {
tlog(TLOG_ERROR, "add ecs failed."); tlog(TLOG_ERROR, "add ecs failed.");
return -1; return -1;
} }
@@ -1456,7 +1458,7 @@ static int _dns_decode_opt(struct dns_context *context, dns_rr_type type, unsign
context->ptr += opt_len; context->ptr += opt_len;
tlog(TLOG_DEBUG, "DNS opt type = %d not supported", opt_code); tlog(TLOG_DEBUG, "DNS opt type = %d not supported", opt_code);
break; break;
} }
} }
return 0; return 0;
@@ -1589,7 +1591,7 @@ static int _dns_decode_an(struct dns_context *context, dns_rr_type type)
} }
} break; } break;
case DNS_T_OPT: { case DNS_T_OPT: {
unsigned char *opt_start = context->ptr; unsigned char *opt_start = context->ptr;
ret = _dns_decode_opt(context, type, ttl, rr_len); ret = _dns_decode_opt(context, type, ttl, rr_len);
if (ret < 0) { if (ret < 0) {
tlog(TLOG_ERROR, "decode opt failed, %s", domain); tlog(TLOG_ERROR, "decode opt failed, %s", domain);
@@ -1875,7 +1877,8 @@ int dns_encode(unsigned char *data, int size, struct dns_packet *packet)
return context.ptr - context.data; return context.ptr - context.data;
} }
void dns_debug(void) #if 0
static void dns_debug(void)
{ {
unsigned char data[1024]; unsigned char data[1024];
int len; int len;
@@ -1899,10 +1902,11 @@ void dns_debug(void)
memset(data, 0, sizeof(data)); memset(data, 0, sizeof(data));
len = dns_encode(data, 1024, packet); len = dns_encode(data, 1024, packet);
if (len < 0) { if (len < 0) {
tlog(TLOG_ERROR, "encode failed.\n"); tlog(TLOG_ERROR, "encode failed.");
} }
fd = open("dns-cmp.bin", O_CREAT | O_TRUNC | O_RDWR); fd = open("dns-cmp.bin", O_CREAT | O_TRUNC | O_RDWR);
write(fd, data, len); write(fd, data, len);
close(fd); close(fd);
} }
#endif

View File

@@ -1,11 +1,6 @@
#ifndef _DNS_HEAD_H #ifndef _DNS_HEAD_H
#define _DNS_HEAD_H #define _DNS_HEAD_H
#include <arpa/inet.h>
#include <linux/filter.h>
#include <netdb.h>
#include <stdint.h>
#define DNS_RR_A_LEN 4 #define DNS_RR_A_LEN 4
#define DNS_RR_AAAA_LEN 16 #define DNS_RR_AAAA_LEN 16
#define DNS_MAX_CNAME_LEN 256 #define DNS_MAX_CNAME_LEN 256
@@ -50,9 +45,9 @@ typedef enum dns_type {
DNS_T_ALL = 255 DNS_T_ALL = 255
} dns_type_t; } dns_type_t;
typedef enum dns_opt_code { typedef enum dns_opt_code {
DNS_OPT_T_ECS = 8, DNS_OPT_T_ECS = 8,
DNS_OPT_T_ALL = 255 DNS_OPT_T_ALL = 255
} dns_opt_code_t; } dns_opt_code_t;
typedef enum dns_opcode { typedef enum dns_opcode {
@@ -188,6 +183,9 @@ int dns_get_AAAA(struct dns_rrs *rrs, char *domain, int maxsize, int *ttl, unsig
int dns_add_SOA(struct dns_packet *packet, dns_rr_type type, char *domain, int ttl, struct dns_soa *soa); int dns_add_SOA(struct dns_packet *packet, dns_rr_type type, char *domain, int ttl, struct dns_soa *soa);
int dns_get_SOA(struct dns_rrs *rrs, char *domain, int maxsize, int *ttl, struct dns_soa *soa); int dns_get_SOA(struct dns_rrs *rrs, char *domain, int maxsize, int *ttl, struct dns_soa *soa);
int dns_add_NS(struct dns_packet *packet, dns_rr_type type, char *domain, int ttl, char *cname);
int dns_get_NS(struct dns_rrs *rrs, char *domain, int maxsize, int *ttl, char *cname, int cname_size);
int dns_set_OPT_payload_size(struct dns_packet *packet, int payload_size); int dns_set_OPT_payload_size(struct dns_packet *packet, int payload_size);
int dns_get_OPT_payload_size(struct dns_packet *packet); int dns_get_OPT_payload_size(struct dns_packet *packet);

View File

@@ -10,7 +10,7 @@ struct dns_cache_head {
pthread_mutex_t lock; pthread_mutex_t lock;
}; };
struct dns_cache_head dns_cache_head; static struct dns_cache_head dns_cache_head;
int dns_cache_init(int size) int dns_cache_init(int size)
{ {
@@ -19,22 +19,22 @@ int dns_cache_init(int size)
dns_cache_head.num = 0; dns_cache_head.num = 0;
dns_cache_head.size = size; dns_cache_head.size = size;
pthread_mutex_init(&dns_cache_head.lock, 0); pthread_mutex_init(&dns_cache_head.lock, NULL);
return 0; return 0;
} }
struct dns_cache *_dns_cache_last(void) static __attribute__((unused)) struct dns_cache *_dns_cache_last(void)
{ {
return list_last_entry(&dns_cache_head.cache_list, struct dns_cache, list); return list_last_entry(&dns_cache_head.cache_list, struct dns_cache, list);
} }
struct dns_cache *_dns_cache_first(void) static struct dns_cache *_dns_cache_first(void)
{ {
return list_first_entry_or_null(&dns_cache_head.cache_list, struct dns_cache, list); return list_first_entry_or_null(&dns_cache_head.cache_list, struct dns_cache, list);
} }
void _dns_cache_delete(struct dns_cache *dns_cache) static void _dns_cache_delete(struct dns_cache *dns_cache)
{ {
hash_del(&dns_cache->node); hash_del(&dns_cache->node);
list_del_init(&dns_cache->list); list_del_init(&dns_cache->list);
@@ -59,7 +59,7 @@ void dns_cache_release(struct dns_cache *dns_cache)
_dns_cache_delete(dns_cache); _dns_cache_delete(dns_cache);
} }
void _dns_cache_remove(struct dns_cache *dns_cache) static void _dns_cache_remove(struct dns_cache *dns_cache)
{ {
hash_del(&dns_cache->node); hash_del(&dns_cache->node);
list_del_init(&dns_cache->list); list_del_init(&dns_cache->list);
@@ -74,6 +74,7 @@ int dns_cache_replace(char *domain, char *cname, int cname_ttl, int ttl, dns_typ
return 0; return 0;
} }
/* lookup existing cache */
dns_cache = dns_cache_lookup(domain, qtype); dns_cache = dns_cache_lookup(domain, qtype);
if (dns_cache == NULL) { if (dns_cache == NULL) {
return 0; return 0;
@@ -83,6 +84,7 @@ int dns_cache_replace(char *domain, char *cname, int cname_ttl, int ttl, dns_typ
ttl = DNS_CACHE_TTL_MIN; ttl = DNS_CACHE_TTL_MIN;
} }
/* update cache data */
pthread_mutex_lock(&dns_cache_head.lock); pthread_mutex_lock(&dns_cache_head.lock);
dns_cache->ttl = ttl; dns_cache->ttl = ttl;
dns_cache->qtype = qtype; dns_cache->qtype = qtype;
@@ -128,6 +130,7 @@ int dns_cache_insert(char *domain, char *cname, int cname_ttl, int ttl, dns_type
return 0; return 0;
} }
/* if cache already exists, free */
dns_cache = dns_cache_lookup(domain, qtype); dns_cache = dns_cache_lookup(domain, qtype);
if (dns_cache) { if (dns_cache) {
dns_cache_delete(dns_cache); dns_cache_delete(dns_cache);
@@ -179,6 +182,7 @@ int dns_cache_insert(char *domain, char *cname, int cname_ttl, int ttl, dns_type
INIT_LIST_HEAD(&dns_cache->check_list); INIT_LIST_HEAD(&dns_cache->check_list);
dns_cache_head.num++; dns_cache_head.num++;
/* Release extra cache, remove oldest cache record */
if (dns_cache_head.num > dns_cache_head.size) { if (dns_cache_head.num > dns_cache_head.size) {
struct dns_cache *del_cache; struct dns_cache *del_cache;
del_cache = _dns_cache_first(); del_cache = _dns_cache_first();
@@ -212,6 +216,7 @@ struct dns_cache *dns_cache_lookup(char *domain, dns_type_t qtype)
key = jhash(&qtype, sizeof(qtype), key); key = jhash(&qtype, sizeof(qtype), key);
time(&now); time(&now);
/* find cache */
pthread_mutex_lock(&dns_cache_head.lock); pthread_mutex_lock(&dns_cache_head.lock);
hash_for_each_possible(dns_cache_head.cache_hash, dns_cache, node, key) hash_for_each_possible(dns_cache_head.cache_hash, dns_cache, node, key)
{ {
@@ -228,6 +233,7 @@ struct dns_cache *dns_cache_lookup(char *domain, dns_type_t qtype)
} }
if (dns_cache_ret) { if (dns_cache_ret) {
/* Return NULL if the cache times out */
if (now - dns_cache_ret->insert_time > dns_cache_ret->ttl) { if (now - dns_cache_ret->insert_time > dns_cache_ret->ttl) {
_dns_cache_remove(dns_cache_ret); _dns_cache_remove(dns_cache_ret);
dns_cache_ret = NULL; dns_cache_ret = NULL;
@@ -291,6 +297,7 @@ void dns_cache_invalidate(dns_cache_preinvalid_callback callback, int ttl_pre)
{ {
ttl = dns_cache->insert_time + dns_cache->ttl - now; ttl = dns_cache->insert_time + dns_cache->ttl - now;
if (ttl > 0 && ttl < ttl_pre) { if (ttl > 0 && ttl < ttl_pre) {
/* If the TTL time is in the pre-timeout range, call callback function */
if (callback && dns_cache->del_pending == 0) { if (callback && dns_cache->del_pending == 0) {
list_add_tail(&dns_cache->check_list, &checklist); list_add_tail(&dns_cache->check_list, &checklist);
dns_cache_get(dns_cache); dns_cache_get(dns_cache);
@@ -307,6 +314,7 @@ void dns_cache_invalidate(dns_cache_preinvalid_callback callback, int ttl_pre)
list_for_each_entry_safe(dns_cache, tmp, &checklist, check_list) list_for_each_entry_safe(dns_cache, tmp, &checklist, check_list)
{ {
/* run callback */
if (callback) { if (callback) {
callback(dns_cache); callback(dns_cache);
} }
@@ -326,4 +334,4 @@ void dns_cache_destroy(void)
pthread_mutex_unlock(&dns_cache_head.lock); pthread_mutex_unlock(&dns_cache_head.lock);
pthread_mutex_destroy(&dns_cache_head.lock); pthread_mutex_destroy(&dns_cache_head.lock);
} }

View File

@@ -6,6 +6,7 @@
#include "hash.h" #include "hash.h"
#include "hashtable.h" #include "hashtable.h"
#include "list.h" #include "list.h"
#include <stdlib.h>
#include <time.h> #include <time.h>
#define DNS_CACHE_TTL_MIN 30 #define DNS_CACHE_TTL_MIN 30
@@ -54,4 +55,4 @@ int dns_cache_get_ttl(struct dns_cache *dns_cache);
void dns_cache_destroy(void); void dns_cache_destroy(void);
#endif // !_SMARTDNS_CACHE_H #endif // !_SMARTDNS_CACHE_H

View File

@@ -19,12 +19,12 @@
#include "dns_client.h" #include "dns_client.h"
#include "atomic.h" #include "atomic.h"
#include "dns.h" #include "dns.h"
#include "dns_conf.h"
#include "fast_ping.h" #include "fast_ping.h"
#include "hashtable.h" #include "hashtable.h"
#include "list.h" #include "list.h"
#include "tlog.h" #include "tlog.h"
#include "util.h" #include "util.h"
#include "dns_conf.h"
#include <arpa/inet.h> #include <arpa/inet.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
@@ -59,6 +59,7 @@
#define TCP_FASTOPEN_CONNECT 30 #define TCP_FASTOPEN_CONNECT 30
#endif #endif
/* ECS info */
struct dns_client_ecs { struct dns_client_ecs {
int enable; int enable;
unsigned int family; unsigned int family;
@@ -70,6 +71,7 @@ struct dns_client_ecs {
}; };
}; };
/* TCP/TLS buffer */
struct dns_server_buff { struct dns_server_buff {
unsigned char data[DNS_TCP_BUFFER]; unsigned char data[DNS_TCP_BUFFER];
unsigned short len; unsigned short len;
@@ -123,11 +125,13 @@ struct dns_server_info {
}; };
}; };
/* upstream server group member */
struct dns_server_group_member { struct dns_server_group_member {
struct list_head list; struct list_head list;
struct dns_server_info *server; struct dns_server_info *server;
}; };
/* upstream server groups */
struct dns_server_group { struct dns_server_group {
char group_name[DNS_GROUP_NAME_LEN]; char group_name[DNS_GROUP_NAME_LEN];
struct hlist_node node; struct hlist_node node;
@@ -230,7 +234,7 @@ errout:
} }
/* check whether server exists */ /* check whether server exists */
int _dns_client_server_exist(struct addrinfo *gai, dns_server_type_t server_type) static int _dns_client_server_exist(struct addrinfo *gai, dns_server_type_t server_type)
{ {
struct dns_server_info *server_info, *tmp; struct dns_server_info *server_info, *tmp;
pthread_mutex_lock(&client.server_list_lock); pthread_mutex_lock(&client.server_list_lock);
@@ -256,7 +260,7 @@ int _dns_client_server_exist(struct addrinfo *gai, dns_server_type_t server_type
return -1; return -1;
} }
void _dns_client_server_update_ttl(struct ping_host_struct *ping_host, const char *host, FAST_PING_RESULT result, struct sockaddr *addr, socklen_t addr_len, static void _dns_client_server_update_ttl(struct ping_host_struct *ping_host, const char *host, FAST_PING_RESULT result, struct sockaddr *addr, socklen_t addr_len,
int seqno, int ttl, struct timeval *tv, void *userptr) int seqno, int ttl, struct timeval *tv, void *userptr)
{ {
struct dns_server_info *server_info = userptr; struct dns_server_info *server_info = userptr;
@@ -270,7 +274,7 @@ void _dns_client_server_update_ttl(struct ping_host_struct *ping_host, const cha
} }
/* get server control block by ip and port, type */ /* get server control block by ip and port, type */
struct dns_server_info *_dns_client_get_server(char *server_ip, int port, dns_server_type_t server_type) static struct dns_server_info *_dns_client_get_server(char *server_ip, int port, dns_server_type_t server_type)
{ {
struct dns_server_info *server_info, *tmp; struct dns_server_info *server_info, *tmp;
struct dns_server_info *server_info_return = NULL; struct dns_server_info *server_info_return = NULL;
@@ -335,7 +339,8 @@ errout:
return NULL; return NULL;
} }
struct dns_server_group *_dns_client_get_group(const char *group_name) /* get server group by name */
static struct dns_server_group *_dns_client_get_group(const char *group_name)
{ {
unsigned long key; unsigned long key;
struct dns_server_group *group = NULL; struct dns_server_group *group = NULL;
@@ -358,7 +363,8 @@ struct dns_server_group *_dns_client_get_group(const char *group_name)
return NULL; return NULL;
} }
int _dns_client_add_to_group(char *group_name, struct dns_server_info *server_info) /* add server to group */
static int _dns_client_add_to_group(char *group_name, struct dns_server_info *server_info)
{ {
struct dns_server_group *group = NULL; struct dns_server_group *group = NULL;
struct dns_server_group_member *group_member = NULL; struct dns_server_group_member *group_member = NULL;
@@ -388,6 +394,7 @@ errout:
return -1; return -1;
} }
/* add server to group */
int dns_client_add_to_group(char *group_name, char *server_ip, int port, dns_server_type_t server_type) int dns_client_add_to_group(char *group_name, char *server_ip, int port, dns_server_type_t server_type)
{ {
struct dns_server_info *server_info = NULL; struct dns_server_info *server_info = NULL;
@@ -400,7 +407,8 @@ int dns_client_add_to_group(char *group_name, char *server_ip, int port, dns_ser
return _dns_client_add_to_group(group_name, server_info); return _dns_client_add_to_group(group_name, server_info);
} }
int _dns_client_remove_member(struct dns_server_group_member *group_member) /* free group member */
static int _dns_client_remove_member(struct dns_server_group_member *group_member)
{ {
list_del_init(&group_member->list); list_del_init(&group_member->list);
free(group_member); free(group_member);
@@ -408,7 +416,7 @@ int _dns_client_remove_member(struct dns_server_group_member *group_member)
return 0; return 0;
} }
int _dns_client_remove_from_group(struct dns_server_group *group, struct dns_server_info *server_info) static int _dns_client_remove_from_group(struct dns_server_group *group, struct dns_server_info *server_info)
{ {
struct dns_server_group_member *group_member; struct dns_server_group_member *group_member;
struct dns_server_group_member *tmp; struct dns_server_group_member *tmp;
@@ -425,7 +433,7 @@ int _dns_client_remove_from_group(struct dns_server_group *group, struct dns_ser
return 0; return 0;
} }
int _dns_client_remove_server_from_groups(struct dns_server_info *server_info) static int _dns_client_remove_server_from_groups(struct dns_server_info *server_info)
{ {
struct dns_server_group *group; struct dns_server_group *group;
struct hlist_node *tmp = NULL; struct hlist_node *tmp = NULL;
@@ -488,7 +496,7 @@ errout:
return -1; return -1;
} }
int _dns_client_remove_group(struct dns_server_group *group) static int _dns_client_remove_group(struct dns_server_group *group)
{ {
struct dns_server_group_member *group_member; struct dns_server_group_member *group_member;
struct dns_server_group_member *tmp; struct dns_server_group_member *tmp;
@@ -504,7 +512,7 @@ int _dns_client_remove_group(struct dns_server_group *group)
return 0; return 0;
} }
int dns_remove_group(char *group_name) int dns_client_remove_group(char *group_name)
{ {
unsigned long key; unsigned long key;
struct dns_server_group *group = NULL; struct dns_server_group *group = NULL;
@@ -525,7 +533,7 @@ int dns_remove_group(char *group_name)
return 0; return 0;
} }
void _dns_client_group_remove_all(void) static void _dns_client_group_remove_all(void)
{ {
struct dns_server_group *group; struct dns_server_group *group;
struct hlist_node *tmp = NULL; struct hlist_node *tmp = NULL;
@@ -538,13 +546,14 @@ void _dns_client_group_remove_all(void)
} }
/* add dns server information */ /* add dns server information */
int _dns_client_server_add(char *server_ip, struct addrinfo *gai, dns_server_type_t server_type, unsigned int server_flag, unsigned int result_flag, int ttl, char *spki) static int _dns_client_server_add(char *server_ip, struct addrinfo *gai, dns_server_type_t server_type, unsigned int server_flag, unsigned int result_flag, int ttl,
char *spki)
{ {
struct dns_server_info *server_info = NULL; struct dns_server_info *server_info = NULL;
unsigned char *spki_data = NULL; unsigned char *spki_data = NULL;
int spki_data_len = 0; int spki_data_len = 0;
/* read SPKI */ /* read SPKI value, base64 sha256 value */
if (spki && (strlen(spki) < DNS_MAX_SPKI_LEN)) { if (spki && (strlen(spki) < DNS_MAX_SPKI_LEN)) {
spki_data = malloc(DNS_MAX_SPKI_LEN); spki_data = malloc(DNS_MAX_SPKI_LEN);
if (spki_data) { if (spki_data) {
@@ -558,6 +567,7 @@ int _dns_client_server_add(char *server_ip, struct addrinfo *gai, dns_server_typ
} }
} }
/* if server exist, return */
if (_dns_client_server_exist(gai, server_type) == 0) { if (_dns_client_server_exist(gai, server_type) == 0) {
return 0; return 0;
} }
@@ -584,6 +594,7 @@ int _dns_client_server_add(char *server_ip, struct addrinfo *gai, dns_server_typ
server_info->spki = spki_data; server_info->spki = spki_data;
server_info->spki_len = spki_data_len; server_info->spki_len = spki_data_len;
/* exclude this server from default group */
if ((server_flag & SERVER_FLAG_EXCLUDE_DEFAULT) == 0) { if ((server_flag & SERVER_FLAG_EXCLUDE_DEFAULT) == 0) {
if (_dns_client_add_to_group(DNS_SERVER_GROUP_DEFAULT, server_info) != 0) { if (_dns_client_add_to_group(DNS_SERVER_GROUP_DEFAULT, server_info) != 0) {
tlog(TLOG_ERROR, "add server to default group failed."); tlog(TLOG_ERROR, "add server to default group failed.");
@@ -591,6 +602,7 @@ int _dns_client_server_add(char *server_ip, struct addrinfo *gai, dns_server_typ
} }
} }
/* if server type is TLS, create ssl context */
if (server_type == DNS_SERVER_TLS) { if (server_type == DNS_SERVER_TLS) {
server_info->ssl_ctx = SSL_CTX_new(SSLv23_client_method()); server_info->ssl_ctx = SSL_CTX_new(SSLv23_client_method());
if (server_info->ssl_ctx == NULL) { if (server_info->ssl_ctx == NULL) {
@@ -599,6 +611,7 @@ int _dns_client_server_add(char *server_ip, struct addrinfo *gai, dns_server_typ
} }
} }
/* safe address info */
if (gai->ai_addrlen > sizeof(server_info->in6)) { if (gai->ai_addrlen > sizeof(server_info->in6)) {
tlog(TLOG_ERROR, "addr len invalid, %d, %zd, %d", gai->ai_addrlen, sizeof(server_info->addr), server_info->ai_family); tlog(TLOG_ERROR, "addr len invalid, %d, %zd, %d", gai->ai_addrlen, sizeof(server_info->addr), server_info->ai_family);
goto errout; goto errout;
@@ -652,16 +665,19 @@ static void _dns_client_close_socket(struct dns_server_info *server_info)
} }
if (server_info->ssl) { if (server_info->ssl) {
/* Shutdown ssl */
SSL_shutdown(server_info->ssl); SSL_shutdown(server_info->ssl);
SSL_free(server_info->ssl); SSL_free(server_info->ssl);
server_info->ssl = NULL; server_info->ssl = NULL;
} }
/* remove fd from epoll */
epoll_ctl(client.epoll_fd, EPOLL_CTL_DEL, server_info->fd, NULL); epoll_ctl(client.epoll_fd, EPOLL_CTL_DEL, server_info->fd, NULL);
close(server_info->fd); close(server_info->fd);
server_info->fd = -1; server_info->fd = -1;
server_info->status = DNS_SERVER_STATUS_DISCONNECTED; server_info->status = DNS_SERVER_STATUS_DISCONNECTED;
/* update send recv time */
time(&server_info->last_send); time(&server_info->last_send);
time(&server_info->last_recv); time(&server_info->last_recv);
tlog(TLOG_DEBUG, "server %s closed.", server_info->ip); tlog(TLOG_DEBUG, "server %s closed.", server_info->ip);
@@ -686,11 +702,11 @@ static void _dns_client_server_close(struct dns_server_info *server_info)
if (server_info->ssl_ctx) { if (server_info->ssl_ctx) {
SSL_CTX_free(server_info->ssl_ctx); SSL_CTX_free(server_info->ssl_ctx);
server_info->ssl_ctx = NULL; server_info->ssl_ctx = NULL;
} }
} }
/* remove all servers information */ /* remove all servers information */
void _dns_client_server_remove_all(void) static void _dns_client_server_remove_all(void)
{ {
struct dns_server_info *server_info, *tmp; struct dns_server_info *server_info, *tmp;
pthread_mutex_lock(&client.server_list_lock); pthread_mutex_lock(&client.server_list_lock);
@@ -708,7 +724,7 @@ void _dns_client_server_remove_all(void)
} }
/* remove single server */ /* remove single server */
int _dns_client_server_remove(char *server_ip, struct addrinfo *gai, dns_server_type_t server_type) static int _dns_client_server_remove(char *server_ip, struct addrinfo *gai, dns_server_type_t server_type)
{ {
struct dns_server_info *server_info, *tmp; struct dns_server_info *server_info, *tmp;
@@ -736,7 +752,8 @@ int _dns_client_server_remove(char *server_ip, struct addrinfo *gai, dns_server_
return -1; return -1;
} }
int _dns_client_server_operate(char *server_ip, int port, dns_server_type_t server_type, unsigned int server_flag, unsigned int result_flag, int ttl, char *spki, int operate) static int _dns_client_server_operate(char *server_ip, int port, dns_server_type_t server_type, unsigned int server_flag, unsigned int result_flag, int ttl,
char *spki, int operate)
{ {
char port_s[8]; char port_s[8];
int sock_type; int sock_type;
@@ -770,11 +787,13 @@ int _dns_client_server_operate(char *server_ip, int port, dns_server_type_t serv
} }
if (operate == 0) { if (operate == 0) {
/* add server */
ret = _dns_client_server_add(server_ip, gai, server_type, server_flag, result_flag, ttl, spki); ret = _dns_client_server_add(server_ip, gai, server_type, server_flag, result_flag, ttl, spki);
if (ret != 0) { if (ret != 0) {
goto errout; goto errout;
} }
} else { } else {
/* remove server */
ret = _dns_client_server_remove(server_ip, gai, server_type); ret = _dns_client_server_remove(server_ip, gai, server_type);
if (ret != 0) { if (ret != 0) {
goto errout; goto errout;
@@ -804,7 +823,7 @@ int dns_server_num(void)
return atomic_read(&client.dns_server_num); return atomic_read(&client.dns_server_num);
} }
void _dns_client_query_get(struct dns_query_struct *query) static void _dns_client_query_get(struct dns_query_struct *query)
{ {
if (atomic_inc_return(&query->refcnt) <= 0) { if (atomic_inc_return(&query->refcnt) <= 0) {
tlog(TLOG_ERROR, "BUG: query ref is invalid, domain: %s", query->domain); tlog(TLOG_ERROR, "BUG: query ref is invalid, domain: %s", query->domain);
@@ -812,7 +831,7 @@ void _dns_client_query_get(struct dns_query_struct *query)
} }
} }
void _dns_client_query_release(struct dns_query_struct *query) static void _dns_client_query_release(struct dns_query_struct *query)
{ {
int refcnt = atomic_dec_return(&query->refcnt); int refcnt = atomic_dec_return(&query->refcnt);
int bucket = 0; int bucket = 0;
@@ -847,7 +866,7 @@ void _dns_client_query_release(struct dns_query_struct *query)
free(query); free(query);
} }
void _dns_client_query_remove(struct dns_query_struct *query) static void _dns_client_query_remove(struct dns_query_struct *query)
{ {
/* remove query from period check list, and release reference*/ /* remove query from period check list, and release reference*/
pthread_mutex_lock(&client.domain_map_lock); pthread_mutex_lock(&client.domain_map_lock);
@@ -862,7 +881,7 @@ void _dns_client_query_remove(struct dns_query_struct *query)
_dns_client_query_release(query); _dns_client_query_release(query);
} }
void _dns_client_query_remove_all(void) static void _dns_client_query_remove_all(void)
{ {
struct dns_query_struct *query, *tmp; struct dns_query_struct *query, *tmp;
LIST_HEAD(check_list); LIST_HEAD(check_list);
@@ -883,7 +902,7 @@ void _dns_client_query_remove_all(void)
return; return;
} }
void _dns_client_check_udp_nat(struct dns_query_struct *query) static void _dns_client_check_udp_nat(struct dns_query_struct *query)
{ {
struct dns_server_info *server_info = NULL; struct dns_server_info *server_info = NULL;
struct dns_server_group_member *group_member = NULL; struct dns_server_group_member *group_member = NULL;
@@ -911,7 +930,7 @@ void _dns_client_check_udp_nat(struct dns_query_struct *query)
pthread_mutex_unlock(&client.server_list_lock); pthread_mutex_unlock(&client.server_list_lock);
} }
void _dns_client_check_tcp(void) static void _dns_client_check_tcp(void)
{ {
struct dns_server_info *server_info; struct dns_server_info *server_info;
time_t now; time_t now;
@@ -922,6 +941,7 @@ void _dns_client_check_tcp(void)
list_for_each_entry(server_info, &client.dns_server_list, list) list_for_each_entry(server_info, &client.dns_server_list, list)
{ {
if (server_info->type == DNS_SERVER_UDP) { if (server_info->type == DNS_SERVER_UDP) {
/* no need to check udp server */
continue; continue;
} }
@@ -932,21 +952,22 @@ void _dns_client_check_tcp(void)
} }
} else if (server_info->status == DNS_SERVER_STATUS_CONNECTED) { } else if (server_info->status == DNS_SERVER_STATUS_CONNECTED) {
if (server_info->last_recv + DNS_TCP_IDLE_TIMEOUT < now) { if (server_info->last_recv + DNS_TCP_IDLE_TIMEOUT < now) {
/*disconnect if the server is not responding */
server_info->recv_buff.len = 0; server_info->recv_buff.len = 0;
server_info->send_buff.len = 0; server_info->send_buff.len = 0;
_dns_client_close_socket(server_info); _dns_client_close_socket(server_info);
} }
} }
} }
pthread_mutex_unlock(&client.server_list_lock); pthread_mutex_unlock(&client.server_list_lock);
} }
void _dns_client_period_run_second(void) static void _dns_client_period_run_second(void)
{ {
_dns_client_check_tcp(); _dns_client_check_tcp();
} }
void _dns_client_period_run(void) static void _dns_client_period_run(void)
{ {
struct dns_query_struct *query, *tmp; struct dns_query_struct *query, *tmp;
static unsigned int msec = 0; static unsigned int msec = 0;
@@ -974,10 +995,8 @@ void _dns_client_period_run(void)
_dns_client_check_udp_nat(query); _dns_client_check_udp_nat(query);
_dns_client_query_remove(query); _dns_client_query_remove(query);
_dns_client_query_release(query); _dns_client_query_release(query);
} }
if (msec % 10 == 0) { if (msec % 10 == 0) {
_dns_client_period_run_second(); _dns_client_period_run_second();
} }
@@ -1015,7 +1034,7 @@ static struct dns_query_struct *_dns_client_get_request(unsigned short sid, char
return query_result; return query_result;
} }
int _dns_replied_check_add(struct dns_query_struct *dns_query, struct sockaddr *addr, socklen_t addr_len) static int _dns_replied_check_add(struct dns_query_struct *dns_query, struct sockaddr *addr, socklen_t addr_len)
{ {
uint32_t key = 0; uint32_t key = 0;
struct dns_query_replied *replied_map = NULL; struct dns_query_replied *replied_map = NULL;
@@ -1156,6 +1175,7 @@ static int _dns_client_create_socket_udp(struct dns_server_info *server_info)
setsockopt(server_info->fd, IPPROTO_IP, IP_RECVTTL, &on, sizeof(on)); setsockopt(server_info->fd, IPPROTO_IP, IP_RECVTTL, &on, sizeof(on));
setsockopt(server_info->fd, SOL_IP, IP_TTL, &val, sizeof(val)); setsockopt(server_info->fd, SOL_IP, IP_TTL, &val, sizeof(val));
if (server_info->ai_family == AF_INET6) { if (server_info->ai_family == AF_INET6) {
/* for recving ip ttl value */
setsockopt(server_info->fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on, sizeof(on)); setsockopt(server_info->fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on, sizeof(on));
setsockopt(server_info->fd, IPPROTO_IPV6, IPV6_2292HOPLIMIT, &on, sizeof(on)); setsockopt(server_info->fd, IPPROTO_IPV6, IPV6_2292HOPLIMIT, &on, sizeof(on));
setsockopt(server_info->fd, IPPROTO_IPV6, IPV6_HOPLIMIT, &on, sizeof(on)); setsockopt(server_info->fd, IPPROTO_IPV6, IPV6_HOPLIMIT, &on, sizeof(on));
@@ -1187,6 +1207,7 @@ static int _DNS_client_create_socket_tcp(struct dns_server_info *server_info)
goto errout; goto errout;
} }
/* enable tcp fast open */
if (setsockopt(fd, IPPROTO_TCP, TCP_FASTOPEN_CONNECT, &yes, sizeof(yes)) != 0) { if (setsockopt(fd, IPPROTO_TCP, TCP_FASTOPEN_CONNECT, &yes, sizeof(yes)) != 0) {
tlog(TLOG_DEBUG, "enable TCP fast open failed."); tlog(TLOG_DEBUG, "enable TCP fast open failed.");
} }
@@ -1257,7 +1278,7 @@ static int _DNS_client_create_socket_tls(struct dns_server_info *server_info)
// ? this cause ssl crash ? // ? this cause ssl crash ?
// setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes)); // setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes));
if (connect(fd, (struct sockaddr *)&server_info->addr, server_info->ai_addrlen) != 0) { if (connect(fd, (struct sockaddr *)&server_info->addr, server_info->ai_addrlen) != 0) {
if (errno != EINPROGRESS) { if (errno != EINPROGRESS) {
tlog(TLOG_ERROR, "connect failed."); tlog(TLOG_ERROR, "connect failed.");
@@ -1270,6 +1291,7 @@ static int _DNS_client_create_socket_tls(struct dns_server_info *server_info)
goto errout; goto errout;
} }
/* reuse ssl session */
if (server_info->ssl_session) { if (server_info->ssl_session) {
SSL_set_session(ssl, server_info->ssl_session); SSL_set_session(ssl, server_info->ssl_session);
} }
@@ -1354,6 +1376,7 @@ static int _dns_client_process_udp(struct dns_server_info *server_info, struct e
} }
from_len = msg.msg_namelen; from_len = msg.msg_namelen;
/* Get the TTL of the IP header */
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_TTL) { if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_TTL) {
if (cmsg->cmsg_len >= sizeof(int)) { if (cmsg->cmsg_len >= sizeof(int)) {
@@ -1371,13 +1394,17 @@ static int _dns_client_process_udp(struct dns_server_info *server_info, struct e
tlog(TLOG_DEBUG, "recv udp packet from %s, len: %d, ttl: %d", gethost_by_addr(from_host, sizeof(from_host), (struct sockaddr *)&from), len, ttl); tlog(TLOG_DEBUG, "recv udp packet from %s, len: %d, ttl: %d", gethost_by_addr(from_host, sizeof(from_host), (struct sockaddr *)&from), len, ttl);
if ((ttl != server_info->ttl) && (server_info->ttl > 0) && (server_info->result_flag & DNSSERVER_FLAG_CHECK_TTL)) { if ((ttl != server_info->ttl) && (server_info->ttl > 0) && (server_info->result_flag & DNSSERVER_FLAG_CHECK_TTL)) {
/* If TTL check is enabled but the TTL is inconsistent, it is considered to be a fake dns packet */
if ((ttl < server_info->ttl - server_info->ttl_range) || (ttl > server_info->ttl + server_info->ttl_range)) { if ((ttl < server_info->ttl - server_info->ttl_range) || (ttl > server_info->ttl + server_info->ttl_range)) {
/* tlog(TLOG_DEBUG, "TTL mismatch, from:%d, local %d, discard result", ttl, server_info->ttl); */ /* tlog(TLOG_DEBUG, "TTL mismatch, from:%d, local %d, discard result", ttl, server_info->ttl); */
return 0; return 0;
} }
} }
/* update recv time */
time(&server_info->last_recv); time(&server_info->last_recv);
/* processing dns packet */
if (_dns_client_recv(server_info, inpacket, len, (struct sockaddr *)&from, from_len) != 0) { if (_dns_client_recv(server_info, inpacket, len, (struct sockaddr *)&from, from_len) != 0) {
return -1; return -1;
} }
@@ -1519,7 +1546,8 @@ static int _dns_client_socket_recv(struct dns_server_info *server_info)
} else if (server_info->type == DNS_SERVER_TCP) { } else if (server_info->type == DNS_SERVER_TCP) {
return recv(server_info->fd, server_info->recv_buff.data + server_info->recv_buff.len, DNS_TCP_BUFFER - server_info->recv_buff.len, 0); return recv(server_info->fd, server_info->recv_buff.data + server_info->recv_buff.len, DNS_TCP_BUFFER - server_info->recv_buff.len, 0);
} else if (server_info->type == DNS_SERVER_TLS) { } else if (server_info->type == DNS_SERVER_TLS) {
return _dns_client_socket_ssl_recv(server_info->ssl, server_info->recv_buff.data + server_info->recv_buff.len, DNS_TCP_BUFFER - server_info->recv_buff.len); return _dns_client_socket_ssl_recv(server_info->ssl, server_info->recv_buff.data + server_info->recv_buff.len,
DNS_TCP_BUFFER - server_info->recv_buff.len);
} else { } else {
return -1; return -1;
} }
@@ -1622,7 +1650,7 @@ static int _dns_client_process_tcp(struct dns_server_info *server_info, struct e
} }
pthread_mutex_lock(&client.server_list_lock); pthread_mutex_lock(&client.server_list_lock);
if (server_info->send_buff.len > 0) { if (server_info->send_buff.len > 0) {
/* send data in send_buffer */ /* send existing send_buffer data */
len = _dns_client_socket_send(server_info); len = _dns_client_socket_send(server_info);
if (len < 0) { if (len < 0) {
if (errno == EAGAIN) { if (errno == EAGAIN) {
@@ -1700,7 +1728,7 @@ static int _dns_client_tls_verify(struct dns_server_info *server_info)
/* get spki pin */ /* get spki pin */
key_len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(cert), NULL); key_len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(cert), NULL);
if (key_len <= 0 ) { if (key_len <= 0) {
tlog(TLOG_ERROR, "get x509 public key failed."); tlog(TLOG_ERROR, "get x509 public key failed.");
goto errout; goto errout;
} }
@@ -1714,7 +1742,8 @@ static int _dns_client_tls_verify(struct dns_server_info *server_info)
i2d_X509_PUBKEY(X509_get_X509_PUBKEY(cert), &key_data_tmp); i2d_X509_PUBKEY(X509_get_X509_PUBKEY(cert), &key_data_tmp);
key_sha256 = SSL_SHA256(key_data, key_len, 0); /* Get the SHA256 value of SPKI */
key_sha256 = SSL_SHA256(key_data, key_len, NULL);
if (key_sha256 == NULL) { if (key_sha256 == NULL) {
tlog(TLOG_ERROR, "get sha256 failed."); tlog(TLOG_ERROR, "get sha256 failed.");
goto errout; goto errout;
@@ -1734,6 +1763,7 @@ static int _dns_client_tls_verify(struct dns_server_info *server_info)
tlog(TLOG_DEBUG, "cert SPKI pin(%s): %s", "sha256", cert_fingerprint); tlog(TLOG_DEBUG, "cert SPKI pin(%s): %s", "sha256", cert_fingerprint);
if (server_info->spki) { if (server_info->spki) {
/* check SPKI */
if (memcmp(server_info->spki, key_sha256, server_info->spki_len) != 0) { if (memcmp(server_info->spki, key_sha256, server_info->spki_len) != 0) {
tlog(TLOG_INFO, "server %s cert spki is invalid", server_info->ip); tlog(TLOG_INFO, "server %s cert spki is invalid", server_info->ip);
goto errout; goto errout;
@@ -1765,6 +1795,7 @@ static int _dns_client_process_tls(struct dns_server_info *server_info, struct e
int ssl_ret; int ssl_ret;
if (server_info->status == DNS_SERVER_STATUS_CONNECTING) { if (server_info->status == DNS_SERVER_STATUS_CONNECTING) {
/* do SSL hand shake */
ret = SSL_connect(server_info->ssl); ret = SSL_connect(server_info->ssl);
if (ret == 0) { if (ret == 0) {
goto errout; goto errout;
@@ -1790,11 +1821,12 @@ static int _dns_client_process_tls(struct dns_server_info *server_info, struct e
tlog(TLOG_DEBUG, "tls server %s connected.\n", server_info->ip); tlog(TLOG_DEBUG, "tls server %s connected.\n", server_info->ip);
/* Was the stored session reused? */ /* Was the stored session reused? */
if (SSL_session_reused(server_info->ssl)) { if (SSL_session_reused(server_info->ssl)) {
tlog(TLOG_DEBUG, "reused session"); tlog(TLOG_DEBUG, "reused session");
} else { } else {
tlog(TLOG_DEBUG, "new session"); tlog(TLOG_DEBUG, "new session");
if (server_info->ssl_session) { if (server_info->ssl_session) {
/* free session */
SSL_SESSION_free(server_info->ssl_session); SSL_SESSION_free(server_info->ssl_session);
server_info->ssl_session = NULL; server_info->ssl_session = NULL;
} }
@@ -1804,8 +1836,9 @@ static int _dns_client_process_tls(struct dns_server_info *server_info, struct e
goto errout; goto errout;
} }
/* save ssl session for next request */
server_info->ssl_session = SSL_get1_session(server_info->ssl); server_info->ssl_session = SSL_get1_session(server_info->ssl);
} }
server_info->status = DNS_SERVER_STATUS_CONNECTED; server_info->status = DNS_SERVER_STATUS_CONNECTED;
memset(&fd_event, 0, sizeof(fd_event)); memset(&fd_event, 0, sizeof(fd_event));
@@ -1939,7 +1972,7 @@ static int _dns_client_send_tcp(struct dns_server_info *server_info, void *packe
unsigned char inpacket_data[DNS_IN_PACKSIZE]; unsigned char inpacket_data[DNS_IN_PACKSIZE];
unsigned char *inpacket = inpacket_data; unsigned char *inpacket = inpacket_data;
if (len > sizeof(inpacket_data) -2 ) { if (len > sizeof(inpacket_data) - 2) {
tlog(TLOG_ERROR, "packet size is invalid."); tlog(TLOG_ERROR, "packet size is invalid.");
return -1; return -1;
} }
@@ -1982,7 +2015,7 @@ static int _dns_client_send_tls(struct dns_server_info *server_info, void *packe
unsigned char inpacket_data[DNS_IN_PACKSIZE]; unsigned char inpacket_data[DNS_IN_PACKSIZE];
unsigned char *inpacket = inpacket_data; unsigned char *inpacket = inpacket_data;
if (len > sizeof(inpacket_data) -2 ) { if (len > sizeof(inpacket_data) - 2) {
tlog(TLOG_ERROR, "packet size is invalid."); tlog(TLOG_ERROR, "packet size is invalid.");
return -1; return -1;
} }
@@ -2117,7 +2150,7 @@ static int _dns_client_send_query(struct dns_query_struct *query, char *doamin)
head.ra = 0; head.ra = 0;
head.rcode = 0; head.rcode = 0;
if(dns_packet_init(packet, DNS_PACKSIZE, &head) != 0) { if (dns_packet_init(packet, DNS_PACKSIZE, &head) != 0) {
tlog(TLOG_ERROR, "init packet failed."); tlog(TLOG_ERROR, "init packet failed.");
return -1; return -1;
} }
@@ -2224,7 +2257,7 @@ int dns_client_set_ecs(char *ip, int subnet)
return 0; return 0;
} }
int dns_client_init() int dns_client_init(void)
{ {
pthread_attr_t attr; pthread_attr_t attr;
int epollfd = -1; int epollfd = -1;
@@ -2244,10 +2277,10 @@ int dns_client_init()
goto errout; goto errout;
} }
pthread_mutex_init(&client.server_list_lock, 0); pthread_mutex_init(&client.server_list_lock, NULL);
INIT_LIST_HEAD(&client.dns_server_list); INIT_LIST_HEAD(&client.dns_server_list);
pthread_mutex_init(&client.domain_map_lock, 0); pthread_mutex_init(&client.domain_map_lock, NULL);
hash_init(client.domain_map); hash_init(client.domain_map);
hash_init(client.group); hash_init(client.group);
INIT_LIST_HEAD(&client.dns_request_list); INIT_LIST_HEAD(&client.dns_request_list);
@@ -2286,7 +2319,7 @@ errout:
return -1; return -1;
} }
void dns_client_exit() void dns_client_exit(void)
{ {
if (client.tid > 0) { if (client.tid > 0) {
void *ret = NULL; void *ret = NULL;

View File

@@ -7,40 +7,55 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <syslog.h>
#include <unistd.h> #include <unistd.h>
#include <syslog.h>
#define DEFAULT_DNS_CACHE_SIZE 512 #define DEFAULT_DNS_CACHE_SIZE 512
/* ipset */
struct dns_ipset_table { struct dns_ipset_table {
DECLARE_HASHTABLE(ipset, 8); DECLARE_HASHTABLE(ipset, 8);
}; };
struct dns_ipset_table dns_ipset_table; static struct dns_ipset_table dns_ipset_table;
/* dns groups */
struct dns_group_table dns_group_table; struct dns_group_table dns_group_table;
/* server ip/port */
char dns_conf_server_ip[DNS_MAX_IPLEN]; char dns_conf_server_ip[DNS_MAX_IPLEN];
char dns_conf_server_tcp_ip[DNS_MAX_IPLEN]; char dns_conf_server_tcp_ip[DNS_MAX_IPLEN];
int dns_conf_tcp_idle_time = 120; int dns_conf_tcp_idle_time = 120;
/* cache */
int dns_conf_cachesize = DEFAULT_DNS_CACHE_SIZE; int dns_conf_cachesize = DEFAULT_DNS_CACHE_SIZE;
int dns_conf_prefetch = 0; int dns_conf_prefetch = 0;
/* upstream servers */
struct dns_servers dns_conf_servers[DNS_MAX_SERVERS]; struct dns_servers dns_conf_servers[DNS_MAX_SERVERS];
char dns_conf_server_name[DNS_MAX_CONF_CNAME_LEN]; char dns_conf_server_name[DNS_MAX_CONF_CNAME_LEN];
int dns_conf_server_num; int dns_conf_server_num;
/* logging */
int dns_conf_log_level = TLOG_ERROR; int dns_conf_log_level = TLOG_ERROR;
char dns_conf_log_file[DNS_MAX_PATH]; char dns_conf_log_file[DNS_MAX_PATH];
size_t dns_conf_log_size = 1024 * 1024; size_t dns_conf_log_size = 1024 * 1024;
int dns_conf_log_num = 8; int dns_conf_log_num = 8;
/* auditing */
int dns_conf_audit_enable = 0; int dns_conf_audit_enable = 0;
char dns_conf_audit_file[DNS_MAX_PATH]; char dns_conf_audit_file[DNS_MAX_PATH];
size_t dns_conf_audit_size = 1024 * 1024; size_t dns_conf_audit_size = 1024 * 1024;
int dns_conf_audit_num = 2; int dns_conf_audit_num = 2;
/* address rules */
art_tree dns_conf_domain_rule; art_tree dns_conf_domain_rule;
struct dns_conf_address_rule dns_conf_address_rule; struct dns_conf_address_rule dns_conf_address_rule;
/* dual-stack selection */
int dns_conf_dualstack_ip_selection; int dns_conf_dualstack_ip_selection;
int dns_conf_dualstack_ip_selection_threshold = 30; int dns_conf_dualstack_ip_selection_threshold = 30;
/* TTL */
int dns_conf_rr_ttl; int dns_conf_rr_ttl;
int dns_conf_rr_ttl_min; int dns_conf_rr_ttl_min;
int dns_conf_rr_ttl_max; int dns_conf_rr_ttl_max;
@@ -48,10 +63,12 @@ int dns_conf_force_AAAA_SOA;
int dns_conf_ipset_timeout_enable; int dns_conf_ipset_timeout_enable;
/* ECS */
struct dns_edns_client_subnet dns_conf_ipv4_ecs; struct dns_edns_client_subnet dns_conf_ipv4_ecs;
struct dns_edns_client_subnet dns_conf_ipv6_ecs; struct dns_edns_client_subnet dns_conf_ipv6_ecs;
struct dns_server_groups *dns_conf_get_group(const char *group_name) /* create and get dns server group */
static struct dns_server_groups *_dns_conf_get_group(const char *group_name)
{ {
uint32_t key = 0; uint32_t key = 0;
struct dns_server_groups *group = NULL; struct dns_server_groups *group = NULL;
@@ -82,12 +99,12 @@ errout:
return NULL; return NULL;
} }
int dns_conf_get_group_set(const char *group_name, struct dns_servers *server) static int _dns_conf_get_group_set(const char *group_name, struct dns_servers *server)
{ {
struct dns_server_groups *group = NULL; struct dns_server_groups *group = NULL;
int i = 0; int i = 0;
group = dns_conf_get_group(group_name); group = _dns_conf_get_group(group_name);
if (group == NULL) { if (group == NULL) {
return -1; return -1;
} }
@@ -108,11 +125,11 @@ int dns_conf_get_group_set(const char *group_name, struct dns_servers *server)
return 0; return 0;
} }
const char *dns_conf_get_group_name(const char *group_name) static const char *_dns_conf_get_group_name(const char *group_name)
{ {
struct dns_server_groups *group = NULL; struct dns_server_groups *group = NULL;
group = dns_conf_get_group(group_name); group = _dns_conf_get_group(group_name);
if (group == NULL) { if (group == NULL) {
return NULL; return NULL;
} }
@@ -120,7 +137,7 @@ const char *dns_conf_get_group_name(const char *group_name)
return group->group_name; return group->group_name;
} }
void config_group_table_destroy(void) static void _config_group_table_destroy(void)
{ {
struct dns_server_groups *group = NULL; struct dns_server_groups *group = NULL;
struct hlist_node *tmp = NULL; struct hlist_node *tmp = NULL;
@@ -133,7 +150,7 @@ void config_group_table_destroy(void)
} }
} }
int config_server(int argc, char *argv[], dns_server_type_t type, int default_port) static int _config_server(int argc, char *argv[], dns_server_type_t type, int default_port)
{ {
int index = dns_conf_server_num; int index = dns_conf_server_num;
struct dns_servers *server; struct dns_servers *server;
@@ -147,13 +164,13 @@ int config_server(int argc, char *argv[], dns_server_type_t type, int default_po
int ttl = 0; int ttl = 0;
/* clang-format off */ /* clang-format off */
static struct option long_options[] = { static struct option long_options[] = {
{"blacklist-ip", 0, 0, 'b'}, {"blacklist-ip", no_argument, NULL, 'b'}, /* filtering with blacklist-ip */
{"check-edns", 0, 0, 'e'}, {"check-edns", no_argument, NULL, 'e'}, /* check edns */
{"spki-pin", required_argument, 0, 'p'}, {"spki-pin", required_argument, NULL, 'p'}, /* check SPKI pin */
{"check-ttl", required_argument, 0, 't'}, {"check-ttl", required_argument, NULL, 't'}, /* check ttl */
{"group", required_argument, 0, 'g'}, {"group", required_argument, NULL, 'g'}, /* add to group */
{"exclude-default-group", 0, 0, 'E'}, {"exclude-default-group", no_argument, NULL, 'E'}, /* ecluse this from default group */
{0, 0, 0, 0} {NULL, no_argument, NULL, 0}
}; };
/* clang-format on */ /* clang-format on */
if (argc <= 1) { if (argc <= 1) {
@@ -180,6 +197,7 @@ int config_server(int argc, char *argv[], dns_server_type_t type, int default_po
port = default_port; port = default_port;
} }
/* process extra options */
optind = 1; optind = 1;
while (1) { while (1) {
opt = getopt_long_only(argc, argv, "", long_options, NULL); opt = getopt_long_only(argc, argv, "", long_options, NULL);
@@ -202,6 +220,10 @@ int config_server(int argc, char *argv[], dns_server_type_t type, int default_po
} }
ttl = atoi(optarg); ttl = atoi(optarg);
/* Greater than 0, exact match
Equal to 0, match after check
Less than 0, match in the -N range after inspection
*/
if (ttl < -255 || ttl > 255) { if (ttl < -255 || ttl > 255) {
tlog(TLOG_ERROR, "ttl value is invalid."); tlog(TLOG_ERROR, "ttl value is invalid.");
goto errout; goto errout;
@@ -214,7 +236,7 @@ int config_server(int argc, char *argv[], dns_server_type_t type, int default_po
break; break;
} }
case 'g': { case 'g': {
if (dns_conf_get_group_set(optarg, server) != 0) { if (_dns_conf_get_group_set(optarg, server) != 0) {
tlog(TLOG_ERROR, "add group failed."); tlog(TLOG_ERROR, "add group failed.");
goto errout; goto errout;
} }
@@ -229,6 +251,7 @@ int config_server(int argc, char *argv[], dns_server_type_t type, int default_po
} }
} }
/* add new server */
server->type = type; server->type = type;
server->port = port; server->port = port;
server->result_flag = result_flag; server->result_flag = result_flag;
@@ -247,7 +270,7 @@ errout:
return -1; return -1;
} }
int config_domain_iter_cb(void *data, const unsigned char *key, uint32_t key_len, void *value) static int _config_domain_iter_free(void *data, const unsigned char *key, uint32_t key_len, void *value)
{ {
struct dns_domain_rule *domain_rule = value; struct dns_domain_rule *domain_rule = value;
int i = 0; int i = 0;
@@ -268,13 +291,13 @@ int config_domain_iter_cb(void *data, const unsigned char *key, uint32_t key_len
return 0; return 0;
} }
void config_domain_destroy(void) static void _config_domain_destroy(void)
{ {
art_iter(&dns_conf_domain_rule, config_domain_iter_cb, 0); art_iter(&dns_conf_domain_rule, _config_domain_iter_free, NULL);
art_tree_destroy(&dns_conf_domain_rule); art_tree_destroy(&dns_conf_domain_rule);
} }
void config_address_destroy(radix_node_t *node, void *cbctx) static void _config_address_destroy(radix_node_t *node, void *cbctx)
{ {
if (node == NULL) { if (node == NULL) {
return; return;
@@ -288,7 +311,7 @@ void config_address_destroy(radix_node_t *node, void *cbctx)
node->data = NULL; node->data = NULL;
} }
int config_domain_rule_add(char *domain, enum domain_rule type, void *rule) static int _config_domain_rule_add(char *domain, enum domain_rule type, void *rule)
{ {
struct dns_domain_rule *domain_rule = NULL; struct dns_domain_rule *domain_rule = NULL;
struct dns_domain_rule *old_domain_rule = NULL; struct dns_domain_rule *old_domain_rule = NULL;
@@ -297,6 +320,7 @@ int config_domain_rule_add(char *domain, enum domain_rule type, void *rule)
char domain_key[DNS_MAX_CONF_CNAME_LEN]; char domain_key[DNS_MAX_CONF_CNAME_LEN];
int len = 0; int len = 0;
/* Reverse string, for suffix match */
len = strlen(domain); len = strlen(domain);
reverse_string(domain_key, domain, len); reverse_string(domain_key, domain, len);
domain_key[len] = '.'; domain_key[len] = '.';
@@ -307,6 +331,7 @@ int config_domain_rule_add(char *domain, enum domain_rule type, void *rule)
goto errout; goto errout;
} }
/* Get existing or create domain rule */
domain_rule = art_search(&dns_conf_domain_rule, (unsigned char *)domain_key, len); domain_rule = art_search(&dns_conf_domain_rule, (unsigned char *)domain_key, len);
if (domain_rule == NULL) { if (domain_rule == NULL) {
add_domain_rule = malloc(sizeof(*add_domain_rule)); add_domain_rule = malloc(sizeof(*add_domain_rule));
@@ -317,6 +342,7 @@ int config_domain_rule_add(char *domain, enum domain_rule type, void *rule)
domain_rule = add_domain_rule; domain_rule = add_domain_rule;
} }
/* add new rule to domain */
if (domain_rule->rules[type]) { if (domain_rule->rules[type]) {
free(domain_rule->rules[type]); free(domain_rule->rules[type]);
domain_rule->rules[type] = NULL; domain_rule->rules[type] = NULL;
@@ -324,6 +350,7 @@ int config_domain_rule_add(char *domain, enum domain_rule type, void *rule)
domain_rule->rules[type] = rule; domain_rule->rules[type] = rule;
/* update domain rule */
if (add_domain_rule) { if (add_domain_rule) {
old_domain_rule = art_insert(&dns_conf_domain_rule, (unsigned char *)domain_key, len, add_domain_rule); old_domain_rule = art_insert(&dns_conf_domain_rule, (unsigned char *)domain_key, len, add_domain_rule);
if (old_domain_rule) { if (old_domain_rule) {
@@ -341,7 +368,7 @@ errout:
return -1; return -1;
} }
int config_domain_rule_flag_set(char *domain, unsigned int flag) static int _config_domain_rule_flag_set(char *domain, unsigned int flag)
{ {
struct dns_domain_rule *domain_rule = NULL; struct dns_domain_rule *domain_rule = NULL;
struct dns_domain_rule *old_domain_rule = NULL; struct dns_domain_rule *old_domain_rule = NULL;
@@ -357,6 +384,7 @@ int config_domain_rule_flag_set(char *domain, unsigned int flag)
len++; len++;
domain_key[len] = 0; domain_key[len] = 0;
/* Get existing or create domain rule */
domain_rule = art_search(&dns_conf_domain_rule, (unsigned char *)domain_key, len); domain_rule = art_search(&dns_conf_domain_rule, (unsigned char *)domain_key, len);
if (domain_rule == NULL) { if (domain_rule == NULL) {
add_domain_rule = malloc(sizeof(*add_domain_rule)); add_domain_rule = malloc(sizeof(*add_domain_rule));
@@ -367,6 +395,7 @@ int config_domain_rule_flag_set(char *domain, unsigned int flag)
domain_rule = add_domain_rule; domain_rule = add_domain_rule;
} }
/* add new rule to domain */
if (domain_rule->rules[DOMAIN_RULE_FLAGS] == NULL) { if (domain_rule->rules[DOMAIN_RULE_FLAGS] == NULL) {
rule_flags = malloc(sizeof(*rule_flags)); rule_flags = malloc(sizeof(*rule_flags));
rule_flags->flags = 0; rule_flags->flags = 0;
@@ -376,6 +405,7 @@ int config_domain_rule_flag_set(char *domain, unsigned int flag)
rule_flags = domain_rule->rules[DOMAIN_RULE_FLAGS]; rule_flags = domain_rule->rules[DOMAIN_RULE_FLAGS];
rule_flags->flags |= flag; rule_flags->flags |= flag;
/* update domain rule */
if (add_domain_rule) { if (add_domain_rule) {
old_domain_rule = art_insert(&dns_conf_domain_rule, (unsigned char *)domain_key, len, add_domain_rule); old_domain_rule = art_insert(&dns_conf_domain_rule, (unsigned char *)domain_key, len, add_domain_rule);
if (old_domain_rule) { if (old_domain_rule) {
@@ -393,7 +423,7 @@ errout:
return 0; return 0;
} }
void config_ipset_table_destroy(void) static void _config_ipset_table_destroy(void)
{ {
struct dns_ipset_name *ipset_name = NULL; struct dns_ipset_name *ipset_name = NULL;
struct hlist_node *tmp = NULL; struct hlist_node *tmp = NULL;
@@ -406,7 +436,7 @@ void config_ipset_table_destroy(void)
} }
} }
const char *dns_conf_get_ipset(const char *ipsetname) static const char *_dns_conf_get_ipset(const char *ipsetname)
{ {
uint32_t key = 0; uint32_t key = 0;
struct dns_ipset_name *ipset_name = NULL; struct dns_ipset_name *ipset_name = NULL;
@@ -437,7 +467,7 @@ errout:
return NULL; return NULL;
} }
int config_ipset(void *data, int argc, char *argv[]) static int _config_ipset(void *data, int argc, char *argv[])
{ {
struct dns_ipset_rule *ipset_rule = NULL; struct dns_ipset_rule *ipset_rule = NULL;
char domain[DNS_MAX_CONF_CNAME_LEN]; char domain[DNS_MAX_CONF_CNAME_LEN];
@@ -452,11 +482,13 @@ int config_ipset(void *data, int argc, char *argv[])
goto errout; goto errout;
} }
/* first field */
begin = strstr(value, "/"); begin = strstr(value, "/");
if (begin == NULL) { if (begin == NULL) {
goto errout; goto errout;
} }
/* second field */
begin++; begin++;
end = strstr(begin, "/"); end = strstr(begin, "/");
if (end == NULL) { if (end == NULL) {
@@ -468,6 +500,7 @@ int config_ipset(void *data, int argc, char *argv[])
begin++; begin++;
} }
/* Get domain */
len = end - begin; len = end - begin;
memcpy(domain, begin, len); memcpy(domain, begin, len);
domain[len] = '\0'; domain[len] = '\0';
@@ -477,9 +510,11 @@ int config_ipset(void *data, int argc, char *argv[])
goto errout; goto errout;
} }
/* Process domain option */
if (strncmp(end + 1, "-", sizeof("-")) != 0) { if (strncmp(end + 1, "-", sizeof("-")) != 0) {
/* new ipset domain */
strncpy(ipsetname, end + 1, DNS_MAX_IPSET_NAMELEN); strncpy(ipsetname, end + 1, DNS_MAX_IPSET_NAMELEN);
ipset = dns_conf_get_ipset(ipsetname); ipset = _dns_conf_get_ipset(ipsetname);
if (ipset == NULL) { if (ipset == NULL) {
goto errout; goto errout;
} }
@@ -491,14 +526,15 @@ int config_ipset(void *data, int argc, char *argv[])
ipset_rule->ipsetname = ipset; ipset_rule->ipsetname = ipset;
} else { } else {
if (config_domain_rule_flag_set(domain, DOMAIN_FLAG_IPSET_IGNORE) != 0 ) { /* ignore this domain */
if (_config_domain_rule_flag_set(domain, DOMAIN_FLAG_IPSET_IGNORE) != 0) {
goto errout; goto errout;
} }
return 0; return 0;
} }
if (config_domain_rule_add(domain, DOMAIN_RULE_IPSET, ipset_rule) != 0) { if (_config_domain_rule_add(domain, DOMAIN_RULE_IPSET, ipset_rule) != 0) {
goto errout; goto errout;
} }
@@ -512,7 +548,7 @@ errout:
return 0; return 0;
} }
int config_address(void *data, int argc, char *argv[]) static int _config_address(void *data, int argc, char *argv[])
{ {
struct dns_address_IPV4 *address_ipv4 = NULL; struct dns_address_IPV4 *address_ipv4 = NULL;
struct dns_address_IPV6 *address_ipv6 = NULL; struct dns_address_IPV6 *address_ipv6 = NULL;
@@ -533,11 +569,13 @@ int config_address(void *data, int argc, char *argv[])
goto errout; goto errout;
} }
/* first field */
begin = strstr(value, "/"); begin = strstr(value, "/");
if (begin == NULL) { if (begin == NULL) {
goto errout; goto errout;
} }
/* second field */
begin++; begin++;
end = strstr(begin, "/"); end = strstr(begin, "/");
if (end == NULL) { if (end == NULL) {
@@ -549,6 +587,7 @@ int config_address(void *data, int argc, char *argv[])
begin++; begin++;
} }
/* get domain */
len = end - begin; len = end - begin;
memcpy(domain, begin, len); memcpy(domain, begin, len);
domain[len] = 0; domain[len] = 0;
@@ -564,7 +603,8 @@ int config_address(void *data, int argc, char *argv[])
goto errout; goto errout;
} }
if (config_domain_rule_flag_set(domain, flag) != 0 ) { /* add SOA rule */
if (_config_domain_rule_flag_set(domain, flag) != 0) {
goto errout; goto errout;
} }
@@ -580,12 +620,14 @@ int config_address(void *data, int argc, char *argv[])
goto errout; goto errout;
} }
if (config_domain_rule_flag_set(domain, flag) != 0 ) { /* ignore rule */
if (_config_domain_rule_flag_set(domain, flag) != 0) {
goto errout; goto errout;
} }
return 0; return 0;
} else { } else {
/* set address to domain */
if (parse_ip(end + 1, ip, &port) != 0) { if (parse_ip(end + 1, ip, &port) != 0) {
goto errout; goto errout;
} }
@@ -631,9 +673,10 @@ int config_address(void *data, int argc, char *argv[])
default: default:
goto errout; goto errout;
} }
} }
if (config_domain_rule_add(domain, type, address) != 0) { /* add domain to ART-tree */
if (_config_domain_rule_add(domain, type, address) != 0) {
goto errout; goto errout;
} }
@@ -647,22 +690,22 @@ errout:
return 0; return 0;
} }
int config_server_udp(void *data, int argc, char *argv[]) static int _config_server_udp(void *data, int argc, char *argv[])
{ {
return config_server(argc, argv, DNS_SERVER_UDP, DEFAULT_DNS_PORT); return _config_server(argc, argv, DNS_SERVER_UDP, DEFAULT_DNS_PORT);
} }
int config_server_tcp(void *data, int argc, char *argv[]) static int _config_server_tcp(void *data, int argc, char *argv[])
{ {
return config_server(argc, argv, DNS_SERVER_TCP, DEFAULT_DNS_PORT); return _config_server(argc, argv, DNS_SERVER_TCP, DEFAULT_DNS_PORT);
} }
int config_server_tls(void *data, int argc, char *argv[]) static int _config_server_tls(void *data, int argc, char *argv[])
{ {
return config_server(argc, argv, DNS_SERVER_TLS, DEFAULT_DNS_TLS_PORT); return _config_server(argc, argv, DNS_SERVER_TLS, DEFAULT_DNS_TLS_PORT);
} }
int config_nameserver(void *data, int argc, char *argv[]) static int _config_nameserver(void *data, int argc, char *argv[])
{ {
struct dns_nameserver_rule *nameserver_rule = NULL; struct dns_nameserver_rule *nameserver_rule = NULL;
char domain[DNS_MAX_CONF_CNAME_LEN]; char domain[DNS_MAX_CONF_CNAME_LEN];
@@ -677,11 +720,13 @@ int config_nameserver(void *data, int argc, char *argv[])
goto errout; goto errout;
} }
/* first field */
begin = strstr(value, "/"); begin = strstr(value, "/");
if (begin == NULL) { if (begin == NULL) {
goto errout; goto errout;
} }
/* second field */
begin++; begin++;
end = strstr(begin, "/"); end = strstr(begin, "/");
if (end == NULL) { if (end == NULL) {
@@ -704,7 +749,7 @@ int config_nameserver(void *data, int argc, char *argv[])
if (strncmp(end + 1, "-", sizeof("-")) != 0) { if (strncmp(end + 1, "-", sizeof("-")) != 0) {
strncpy(group_name, end + 1, DNS_GROUP_NAME_LEN); strncpy(group_name, end + 1, DNS_GROUP_NAME_LEN);
group = dns_conf_get_group_name(group_name); group = _dns_conf_get_group_name(group_name);
if (group == NULL) { if (group == NULL) {
goto errout; goto errout;
} }
@@ -716,14 +761,15 @@ int config_nameserver(void *data, int argc, char *argv[])
nameserver_rule->group_name = group; nameserver_rule->group_name = group;
} else { } else {
if (config_domain_rule_flag_set(domain, DOMAIN_FLAG_NAMESERVER_IGNORE) != 0 ) { /* ignore this domain */
if (_config_domain_rule_flag_set(domain, DOMAIN_FLAG_NAMESERVER_IGNORE) != 0) {
goto errout; goto errout;
} }
return 0; return 0;
} }
if (config_domain_rule_add(domain, DOMAIN_RULE_NAMESERVER, nameserver_rule) != 0) { if (_config_domain_rule_add(domain, DOMAIN_RULE_NAMESERVER, nameserver_rule) != 0) {
goto errout; goto errout;
} }
@@ -737,7 +783,7 @@ errout:
return 0; return 0;
} }
radix_node_t *create_addr_node(char *addr) static radix_node_t *_create_addr_node(char *addr)
{ {
radix_node_t *node; radix_node_t *node;
void *p; void *p;
@@ -763,12 +809,12 @@ radix_node_t *create_addr_node(char *addr)
return node; return node;
} }
int config_iplist_rule(char *subnet, enum address_rule rule) static int _config_iplist_rule(char *subnet, enum address_rule rule)
{ {
radix_node_t *node = NULL; radix_node_t *node = NULL;
struct dns_ip_address_rule *ip_rule = NULL; struct dns_ip_address_rule *ip_rule = NULL;
node = create_addr_node(subnet); node = _create_addr_node(subnet);
if (node == NULL) { if (node == NULL) {
return -1; return -1;
} }
@@ -799,34 +845,34 @@ int config_iplist_rule(char *subnet, enum address_rule rule)
return 0; return 0;
} }
int config_blacklist_ip(void *data, int argc, char *argv[]) static int _config_blacklist_ip(void *data, int argc, char *argv[])
{ {
if (argc <= 1) { if (argc <= 1) {
return -1; return -1;
} }
return config_iplist_rule(argv[1], ADDRESS_RULE_BLACKLIST); return _config_iplist_rule(argv[1], ADDRESS_RULE_BLACKLIST);
} }
int conf_bogus_nxdomain(void *data, int argc, char *argv[]) static int _conf_bogus_nxdomain(void *data, int argc, char *argv[])
{ {
if (argc <= 1) { if (argc <= 1) {
return -1; return -1;
} }
return config_iplist_rule(argv[1], ADDRESS_RULE_BOGUS); return _config_iplist_rule(argv[1], ADDRESS_RULE_BOGUS);
} }
int conf_ip_ignore(void *data, int argc, char *argv[]) static int _conf_ip_ignore(void *data, int argc, char *argv[])
{ {
if (argc <= 1) { if (argc <= 1) {
return -1; return -1;
} }
return config_iplist_rule(argv[1], ADDRESS_RULE_IP_IGNORE); return _config_iplist_rule(argv[1], ADDRESS_RULE_IP_IGNORE);
} }
int conf_edns_client_subnet(void *data, int argc, char *argv[]) static int _conf_edns_client_subnet(void *data, int argc, char *argv[])
{ {
char *slash = NULL; char *slash = NULL;
char *value = NULL; char *value = NULL;
@@ -876,7 +922,7 @@ errout:
return -1; return -1;
} }
int config_log_level(void *data, int argc, char *argv[]) static int _config_log_level(void *data, int argc, char *argv[])
{ {
/* read log level and set */ /* read log level and set */
char *value = argv[1]; char *value = argv[1];
@@ -896,23 +942,23 @@ int config_log_level(void *data, int argc, char *argv[])
return 0; return 0;
} }
struct config_item config_item[] = { static struct config_item _config_item[] = {
CONF_STRING("server-name", (char *)dns_conf_server_name, DNS_MAX_CONF_CNAME_LEN), CONF_STRING("server-name", (char *)dns_conf_server_name, DNS_MAX_CONF_CNAME_LEN),
CONF_STRING("bind", dns_conf_server_ip, DNS_MAX_IPLEN), CONF_STRING("bind", dns_conf_server_ip, DNS_MAX_IPLEN),
CONF_STRING("bind-tcp", dns_conf_server_tcp_ip, DNS_MAX_IPLEN), CONF_STRING("bind-tcp", dns_conf_server_tcp_ip, DNS_MAX_IPLEN),
CONF_CUSTOM("server", config_server_udp, NULL), CONF_CUSTOM("server", _config_server_udp, NULL),
CONF_CUSTOM("server-tcp", config_server_tcp, NULL), CONF_CUSTOM("server-tcp", _config_server_tcp, NULL),
CONF_CUSTOM("server-tls", config_server_tls, NULL), CONF_CUSTOM("server-tls", _config_server_tls, NULL),
CONF_CUSTOM("nameserver", config_nameserver, NULL), CONF_CUSTOM("nameserver", _config_nameserver, NULL),
CONF_CUSTOM("address", config_address, NULL), CONF_CUSTOM("address", _config_address, NULL),
CONF_YESNO("ipset-timeout", &dns_conf_ipset_timeout_enable), CONF_YESNO("ipset-timeout", &dns_conf_ipset_timeout_enable),
CONF_CUSTOM("ipset", config_ipset, NULL), CONF_CUSTOM("ipset", _config_ipset, NULL),
CONF_INT("tcp-idle-time", &dns_conf_tcp_idle_time, 0, 3600), CONF_INT("tcp-idle-time", &dns_conf_tcp_idle_time, 0, 3600),
CONF_INT("cache-size", &dns_conf_cachesize, 0, CONF_INT_MAX), CONF_INT("cache-size", &dns_conf_cachesize, 0, CONF_INT_MAX),
CONF_YESNO("prefetch-domain", &dns_conf_prefetch), CONF_YESNO("prefetch-domain", &dns_conf_prefetch),
CONF_YESNO("dualstack-ip-selection", &dns_conf_dualstack_ip_selection), CONF_YESNO("dualstack-ip-selection", &dns_conf_dualstack_ip_selection),
CONF_INT("dualstack-ip-selection-threshold", &dns_conf_dualstack_ip_selection_threshold, 0, 1000), CONF_INT("dualstack-ip-selection-threshold", &dns_conf_dualstack_ip_selection_threshold, 0, 1000),
CONF_CUSTOM("log-level", config_log_level, NULL), CONF_CUSTOM("log-level", _config_log_level, NULL),
CONF_STRING("log-file", (char *)dns_conf_log_file, DNS_MAX_PATH), CONF_STRING("log-file", (char *)dns_conf_log_file, DNS_MAX_PATH),
CONF_SIZE("log-size", &dns_conf_log_size, 0, 1024 * 1024 * 1024), CONF_SIZE("log-size", &dns_conf_log_size, 0, 1024 * 1024 * 1024),
CONF_INT("log-num", &dns_conf_log_num, 0, 1024), CONF_INT("log-num", &dns_conf_log_num, 0, 1024),
@@ -924,15 +970,15 @@ struct config_item config_item[] = {
CONF_INT("rr-ttl-min", &dns_conf_rr_ttl_min, 0, CONF_INT_MAX), CONF_INT("rr-ttl-min", &dns_conf_rr_ttl_min, 0, CONF_INT_MAX),
CONF_INT("rr-ttl-max", &dns_conf_rr_ttl_max, 0, CONF_INT_MAX), CONF_INT("rr-ttl-max", &dns_conf_rr_ttl_max, 0, CONF_INT_MAX),
CONF_YESNO("force-AAAA-SOA", &dns_conf_force_AAAA_SOA), CONF_YESNO("force-AAAA-SOA", &dns_conf_force_AAAA_SOA),
CONF_CUSTOM("blacklist-ip", config_blacklist_ip, NULL), CONF_CUSTOM("blacklist-ip", _config_blacklist_ip, NULL),
CONF_CUSTOM("bogus-nxdomain", conf_bogus_nxdomain, NULL), CONF_CUSTOM("bogus-nxdomain", _conf_bogus_nxdomain, NULL),
CONF_CUSTOM("ignore-ip", conf_ip_ignore, NULL), CONF_CUSTOM("ignore-ip", _conf_ip_ignore, NULL),
CONF_CUSTOM("edns-client-subnet", conf_edns_client_subnet, NULL), CONF_CUSTOM("edns-client-subnet", _conf_edns_client_subnet, NULL),
CONF_CUSTOM("conf-file", config_addtional_file, NULL), CONF_CUSTOM("conf-file", config_addtional_file, NULL),
CONF_END(), CONF_END(),
}; };
int conf_printf(const char *file, int lineno, int ret) static int _conf_printf(const char *file, int lineno, int ret)
{ {
if (ret == CONF_RET_ERR) { if (ret == CONF_RET_ERR) {
tlog(TLOG_ERROR, "process config file '%s' failed at line %d.", file, lineno); tlog(TLOG_ERROR, "process config file '%s' failed at line %d.", file, lineno);
@@ -956,10 +1002,10 @@ int config_addtional_file(void *data, int argc, char *argv[])
return 0; return 0;
} }
return load_conf(file_path, config_item, conf_printf); return load_conf(file_path, _config_item, _conf_printf);
} }
int _dns_server_load_conf_init(void) static int _dns_server_load_conf_init(void)
{ {
dns_conf_address_rule.ipv4 = New_Radix(); dns_conf_address_rule.ipv4 = New_Radix();
dns_conf_address_rule.ipv6 = New_Radix(); dns_conf_address_rule.ipv6 = New_Radix();
@@ -978,19 +1024,19 @@ int _dns_server_load_conf_init(void)
void dns_server_load_exit(void) void dns_server_load_exit(void)
{ {
config_domain_destroy(); _config_domain_destroy();
Destroy_Radix(dns_conf_address_rule.ipv4, config_address_destroy, NULL); Destroy_Radix(dns_conf_address_rule.ipv4, _config_address_destroy, NULL);
Destroy_Radix(dns_conf_address_rule.ipv6, config_address_destroy, NULL); Destroy_Radix(dns_conf_address_rule.ipv6, _config_address_destroy, NULL);
config_ipset_table_destroy(); _config_ipset_table_destroy();
config_group_table_destroy(); _config_group_table_destroy();
} }
int dns_server_load_conf(const char *file) int dns_server_load_conf(const char *file)
{ {
int ret = 0; int ret = 0;
_dns_server_load_conf_init(); _dns_server_load_conf_init();
openlog ("smartdns", LOG_CONS | LOG_NDELAY, LOG_LOCAL1); openlog("smartdns", LOG_CONS | LOG_NDELAY, LOG_LOCAL1);
ret = load_conf(file, config_item, conf_printf); ret = load_conf(file, _config_item, _conf_printf);
closelog(); closelog();
return ret; return ret;
} }

View File

@@ -33,13 +33,13 @@ enum domain_rule {
DOMAIN_RULE_MAX, DOMAIN_RULE_MAX,
}; };
#define DOMAIN_FLAG_ADDR_SOA (1 << 0) #define DOMAIN_FLAG_ADDR_SOA (1 << 0)
#define DOMAIN_FLAG_ADDR_IPV4_SOA (1 << 1) #define DOMAIN_FLAG_ADDR_IPV4_SOA (1 << 1)
#define DOMAIN_FLAG_ADDR_IPV6_SOA (1 << 2) #define DOMAIN_FLAG_ADDR_IPV6_SOA (1 << 2)
#define DOMAIN_FLAG_ADDR_IGN (1 << 3) #define DOMAIN_FLAG_ADDR_IGN (1 << 3)
#define DOMAIN_FLAG_ADDR_IPV4_IGN (1 << 4) #define DOMAIN_FLAG_ADDR_IPV4_IGN (1 << 4)
#define DOMAIN_FLAG_ADDR_IPV6_IGN (1 << 5) #define DOMAIN_FLAG_ADDR_IPV6_IGN (1 << 5)
#define DOMAIN_FLAG_IPSET_IGNORE (1 << 6) #define DOMAIN_FLAG_IPSET_IGNORE (1 << 6)
#define DOMAIN_FLAG_NAMESERVER_IGNORE (1 << 7) #define DOMAIN_FLAG_NAMESERVER_IGNORE (1 << 7)
#define SERVER_FLAG_EXCLUDE_DEFAULT (1 << 0) #define SERVER_FLAG_EXCLUDE_DEFAULT (1 << 0)
@@ -172,4 +172,4 @@ int dns_server_load_conf(const char *file);
extern int config_addtional_file(void *data, int argc, char *argv[]); extern int config_addtional_file(void *data, int argc, char *argv[]);
#endif // !_DNS_CONF #endif // !_DNS_CONF

View File

@@ -15,7 +15,9 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef _GNU_SOURCE
#define _GNU_SOURCE #define _GNU_SOURCE
#endif
#include "dns_server.h" #include "dns_server.h"
#include "atomic.h" #include "atomic.h"
#include "dns.h" #include "dns.h"
@@ -27,26 +29,16 @@
#include "list.h" #include "list.h"
#include "tlog.h" #include "tlog.h"
#include "util.h" #include "util.h"
#include <arpa/inet.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <ifaddrs.h> #include <ifaddrs.h>
#include <linux/filter.h>
#include <netdb.h>
#include <netinet/icmp6.h>
#include <netinet/ip.h>
#include <netinet/ip6.h>
#include <netinet/ip_icmp.h>
#include <pthread.h> #include <pthread.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/epoll.h> #include <sys/epoll.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/stat.h> #include <sys/types.h> /* See NOTES */
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#define DNS_MAX_EVENTS 256 #define DNS_MAX_EVENTS 256
#define DNS_SERVER_TMOUT_TTL (5 * 60) #define DNS_SERVER_TMOUT_TTL (5 * 60)
@@ -230,39 +222,47 @@ static int _dns_add_rrs(struct dns_packet *packet, struct dns_request *request)
int ret = 0; int ret = 0;
char *domain = request->domain; char *domain = request->domain;
if (request->has_ptr) { if (request->has_ptr) {
/* add PTR record */
char hostname[DNS_MAX_CNAME_LEN]; char hostname[DNS_MAX_CNAME_LEN];
if (dns_conf_server_name[0] == 0) { if (dns_conf_server_name[0] == 0) {
/* get local host name */
if (getdomainname(hostname, DNS_MAX_CNAME_LEN) != 0) { if (getdomainname(hostname, DNS_MAX_CNAME_LEN) != 0) {
if (gethostname(hostname, DNS_MAX_CNAME_LEN) != 0) { if (gethostname(hostname, DNS_MAX_CNAME_LEN) != 0) {
return -1; return -1;
} }
} }
/* get host name again */
if (strncmp(hostname, "(none)", DNS_MAX_CNAME_LEN) == 0) { if (strncmp(hostname, "(none)", DNS_MAX_CNAME_LEN) == 0) {
if (gethostname(hostname, DNS_MAX_CNAME_LEN) != 0) { if (gethostname(hostname, DNS_MAX_CNAME_LEN) != 0) {
return -1; return -1;
} }
} }
/* if hostname is (none), return smartdns */
if (strncmp(hostname, "(none)", DNS_MAX_CNAME_LEN) == 0) { if (strncmp(hostname, "(none)", DNS_MAX_CNAME_LEN) == 0) {
strncpy(hostname, "smartdns", DNS_MAX_CNAME_LEN); strncpy(hostname, "smartdns", DNS_MAX_CNAME_LEN);
} }
} else { } else {
/* return configured server name */
strncpy(hostname, dns_conf_server_name, DNS_MAX_CNAME_LEN); strncpy(hostname, dns_conf_server_name, DNS_MAX_CNAME_LEN);
} }
ret = dns_add_PTR(packet, DNS_RRS_AN, request->domain, 30, hostname); ret = dns_add_PTR(packet, DNS_RRS_AN, request->domain, 30, hostname);
} }
/* add CNAME record */
if (request->has_cname) { if (request->has_cname) {
ret |= dns_add_CNAME(packet, DNS_RRS_AN, request->domain, request->ttl_cname, request->cname); ret |= dns_add_CNAME(packet, DNS_RRS_AN, request->domain, request->ttl_cname, request->cname);
domain = request->cname; domain = request->cname;
} }
/* add A record */
if (request->has_ipv4 && request->qtype == DNS_T_A) { if (request->has_ipv4 && request->qtype == DNS_T_A) {
ret |= dns_add_A(packet, DNS_RRS_AN, domain, request->ttl_v4, request->ipv4_addr); ret |= dns_add_A(packet, DNS_RRS_AN, domain, request->ttl_v4, request->ipv4_addr);
} }
/* add AAAA record */
if (request->has_ipv6 && request->qtype == DNS_T_AAAA) { if (request->has_ipv6 && request->qtype == DNS_T_AAAA) {
if (request->has_ipv4) { if (request->has_ipv4) {
ret |= dns_add_A(packet, DNS_RRS_AN, domain, request->ttl_v4, request->ipv4_addr); ret |= dns_add_A(packet, DNS_RRS_AN, domain, request->ttl_v4, request->ipv4_addr);
@@ -270,6 +270,7 @@ static int _dns_add_rrs(struct dns_packet *packet, struct dns_request *request)
ret |= dns_add_AAAA(packet, DNS_RRS_AN, domain, request->ttl_v6, request->ipv6_addr); ret |= dns_add_AAAA(packet, DNS_RRS_AN, domain, request->ttl_v6, request->ipv6_addr);
} }
/* add SOA record */
if (request->has_soa) { if (request->has_soa) {
ret |= dns_add_SOA(packet, DNS_RRS_NS, domain, 0, &request->soa); ret |= dns_add_SOA(packet, DNS_RRS_NS, domain, 0, &request->soa);
} }
@@ -307,7 +308,7 @@ static void _dns_server_client_get(struct dns_server_conn *client)
if (client == NULL) { if (client == NULL) {
return; return;
} }
if (atomic_inc_return(&client->refcnt) <= 0) { if (atomic_inc_return(&client->refcnt) <= 0) {
tlog(TLOG_ERROR, "BUG: client ref is invalid."); tlog(TLOG_ERROR, "BUG: client ref is invalid.");
abort(); abort();
@@ -367,7 +368,7 @@ static int _dns_server_reply_tcp(struct dns_server_conn *client, void *packet, u
static int _dns_server_reply_udp(struct dns_request *request, struct dns_server_conn *client, unsigned char *inpacket, int inpacket_len) static int _dns_server_reply_udp(struct dns_request *request, struct dns_server_conn *client, unsigned char *inpacket, int inpacket_len)
{ {
int send_len = 0; int send_len = 0;
send_len = sendto(client->fd, inpacket, inpacket_len, 0, &request->addr, request->addr_len); send_len = sendto(client->fd, inpacket, inpacket_len, 0, (struct sockaddr *)&request->addr, request->addr_len);
if (send_len != inpacket_len) { if (send_len != inpacket_len) {
tlog(TLOG_ERROR, "send failed."); tlog(TLOG_ERROR, "send failed.");
return -1; return -1;
@@ -424,26 +425,31 @@ static int _dns_reply(struct dns_request *request)
head.tc = 0; head.tc = 0;
head.rcode = request->rcode; head.rcode = request->rcode;
/* init a new DNS packet */
ret = dns_packet_init(packet, DNS_PACKSIZE, &head); ret = dns_packet_init(packet, DNS_PACKSIZE, &head);
if (ret != 0) { if (ret != 0) {
return -1; return -1;
} }
/* add request domain */
ret = dns_add_domain(packet, request->domain, request->qtype, DNS_C_IN); ret = dns_add_domain(packet, request->domain, request->qtype, DNS_C_IN);
if (ret != 0) { if (ret != 0) {
return -1; return -1;
} }
/* add RECORDs */
ret = _dns_add_rrs(packet, request); ret = _dns_add_rrs(packet, request);
if (ret != 0) { if (ret != 0) {
return -1; return -1;
} }
/* encode to binary data */
encode_len = dns_encode(inpacket, DNS_IN_PACKSIZE, packet); encode_len = dns_encode(inpacket, DNS_IN_PACKSIZE, packet);
if (encode_len <= 0) { if (encode_len <= 0) {
return -1; return -1;
} }
/* send request */
return _dns_reply_inpacket(request, inpacket, encode_len); return _dns_reply_inpacket(request, inpacket, encode_len);
} }
@@ -451,6 +457,7 @@ static int _dns_server_reply_SOA(int rcode, struct dns_request *request, struct
{ {
struct dns_soa *soa; struct dns_soa *soa;
/* return SOA record */
request->rcode = rcode; request->rcode = rcode;
request->has_soa = 1; request->has_soa = 1;
request->has_ipv4 = 0; request->has_ipv4 = 0;
@@ -471,6 +478,7 @@ static int _dns_server_reply_SOA(int rcode, struct dns_request *request, struct
return 0; return 0;
} }
/* add ip to specific ipset */
static int _dns_setup_ipset(struct dns_request *request) static int _dns_setup_ipset(struct dns_request *request)
{ {
struct dns_ipset_rule *ipset_rule = NULL; struct dns_ipset_rule *ipset_rule = NULL;
@@ -481,6 +489,7 @@ static int _dns_setup_ipset(struct dns_request *request)
return 0; return 0;
} }
/* check ipset rule */
rule_flags = request->domain_rule->rules[DOMAIN_RULE_FLAGS]; rule_flags = request->domain_rule->rules[DOMAIN_RULE_FLAGS];
if (rule_flags) { if (rule_flags) {
if (rule_flags->flags & DOMAIN_FLAG_IPSET_IGNORE) { if (rule_flags->flags & DOMAIN_FLAG_IPSET_IGNORE) {
@@ -493,10 +502,12 @@ static int _dns_setup_ipset(struct dns_request *request)
return 0; return 0;
} }
/* add IPV4 to ipset */
if (request->has_ipv4 && request->qtype == DNS_T_A) { if (request->has_ipv4 && request->qtype == DNS_T_A) {
ret |= ipset_add(ipset_rule->ipsetname, request->ipv4_addr, DNS_RR_A_LEN, request->ttl_v4 * 2); ret |= ipset_add(ipset_rule->ipsetname, request->ipv4_addr, DNS_RR_A_LEN, request->ttl_v4 * 2);
} }
/* add IPV6 to ipset */
if (request->has_ipv6 && request->qtype == DNS_T_AAAA) { if (request->has_ipv6 && request->qtype == DNS_T_AAAA) {
if (request->has_ipv4) { if (request->has_ipv4) {
ret |= ipset_add(ipset_rule->ipsetname, request->ipv4_addr, DNS_RR_A_LEN, request->ttl_v4 * 2); ret |= ipset_add(ipset_rule->ipsetname, request->ipv4_addr, DNS_RR_A_LEN, request->ttl_v4 * 2);
@@ -509,7 +520,7 @@ static int _dns_setup_ipset(struct dns_request *request)
return ret; return ret;
} }
int _dns_server_request_complete(struct dns_request *request) static int _dns_server_request_complete(struct dns_request *request)
{ {
char *cname = NULL; char *cname = NULL;
int cname_ttl = 0; int cname_ttl = 0;
@@ -518,6 +529,7 @@ int _dns_server_request_complete(struct dns_request *request)
return 0; return 0;
} }
/* if passthrouth, return */
if (request->passthrough) { if (request->passthrough) {
return 0; return 0;
} }
@@ -530,15 +542,17 @@ int _dns_server_request_complete(struct dns_request *request)
if (request->qtype == DNS_T_A) { if (request->qtype == DNS_T_A) {
if (request->has_ipv4) { if (request->has_ipv4) {
tlog(TLOG_INFO, "result: %s, rcode: %d, %d.%d.%d.%d\n", request->domain, request->rcode, request->ipv4_addr[0], request->ipv4_addr[1], 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]); request->ipv4_addr[2], request->ipv4_addr[3]);
if (request->has_ping_result == 0 && request->ttl_v4 > DNS_SERVER_TMOUT_TTL) { if (request->has_ping_result == 0 && request->ttl_v4 > DNS_SERVER_TMOUT_TTL) {
request->ttl_v4 = DNS_SERVER_TMOUT_TTL; request->ttl_v4 = DNS_SERVER_TMOUT_TTL;
} }
/* if doing prefetch, update cache only */
if (request->prefetch) { if (request->prefetch) {
dns_cache_replace(request->domain, cname, cname_ttl, request->ttl_v4, DNS_T_A, request->ipv4_addr, DNS_RR_A_LEN); dns_cache_replace(request->domain, cname, cname_ttl, request->ttl_v4, DNS_T_A, request->ipv4_addr, DNS_RR_A_LEN);
} else { } else {
/* insert result to cache */
dns_cache_insert(request->domain, cname, cname_ttl, 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);
} }
@@ -548,8 +562,9 @@ int _dns_server_request_complete(struct dns_request *request)
} else if (request->qtype == DNS_T_AAAA) { } else if (request->qtype == DNS_T_AAAA) {
if (request->has_ipv4 && request->ping_ttl_v4 > 0) { if (request->has_ipv4 && request->ping_ttl_v4 > 0) {
tlog(TLOG_INFO, "result: %s, rcode: %d, %d.%d.%d.%d\n", request->domain, request->rcode, request->ipv4_addr[0], request->ipv4_addr[1], 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]); request->ipv4_addr[2], request->ipv4_addr[3]);
/* if ipv4 is fasting than ipv6, add ipv4 to cache, and return SOA for AAAA request */
if ((request->ping_ttl_v4 + (dns_conf_dualstack_ip_selection_threshold * 10)) < request->ping_ttl_v6 || request->ping_ttl_v6 < 0) { if ((request->ping_ttl_v4 + (dns_conf_dualstack_ip_selection_threshold * 10)) < request->ping_ttl_v6 || request->ping_ttl_v6 < 0) {
tlog(TLOG_DEBUG, "Force IPV4 perfered."); tlog(TLOG_DEBUG, "Force IPV4 perfered.");
if (request->prefetch) { if (request->prefetch) {
@@ -560,22 +575,23 @@ int _dns_server_request_complete(struct dns_request *request)
return _dns_server_reply_SOA(DNS_RC_NOERROR, request, NULL); return _dns_server_reply_SOA(DNS_RC_NOERROR, request, NULL);
} }
} }
if (request->has_ipv6) { if (request->has_ipv6) {
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, 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], request->ipv6_addr[0], request->ipv6_addr[1], request->ipv6_addr[2], request->ipv6_addr[3], request->ipv6_addr[4], request->ipv6_addr[5],
request->ipv6_addr[6], request->ipv6_addr[7], request->ipv6_addr[8], request->ipv6_addr[9], request->ipv6_addr[10], request->ipv6_addr[11], request->ipv6_addr[6], request->ipv6_addr[7], request->ipv6_addr[8], request->ipv6_addr[9], request->ipv6_addr[10], request->ipv6_addr[11],
request->ipv6_addr[12], request->ipv6_addr[13], request->ipv6_addr[14], request->ipv6_addr[15]); request->ipv6_addr[12], request->ipv6_addr[13], request->ipv6_addr[14], request->ipv6_addr[15]);
if (request->has_ping_result == 0 && request->ttl_v6 > DNS_SERVER_TMOUT_TTL) { if (request->has_ping_result == 0 && request->ttl_v6 > DNS_SERVER_TMOUT_TTL) {
request->ttl_v6 = DNS_SERVER_TMOUT_TTL; request->ttl_v6 = DNS_SERVER_TMOUT_TTL;
} }
/* if doing prefetch, update cache only */
if (request->prefetch) { if (request->prefetch) {
dns_cache_replace(request->domain, cname, cname_ttl, request->ttl_v6, DNS_T_AAAA, request->ipv6_addr, DNS_RR_AAAA_LEN); dns_cache_replace(request->domain, cname, cname_ttl, request->ttl_v6, DNS_T_AAAA, request->ipv6_addr, DNS_RR_AAAA_LEN);
} else { } else {
/* insert result to cache */
dns_cache_insert(request->domain, cname, cname_ttl, 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);
} }
@@ -588,19 +604,21 @@ int _dns_server_request_complete(struct dns_request *request)
tlog(TLOG_INFO, "result: %s, qtype: %d, SOA", request->domain, request->qtype); tlog(TLOG_INFO, "result: %s, qtype: %d, SOA", request->domain, request->qtype);
} }
/* update ipset */
_dns_setup_ipset(request); _dns_setup_ipset(request);
if (request->prefetch) { if (request->prefetch) {
return 0; return 0;
} }
/* return result to client */
_dns_reply(request); _dns_reply(request);
return 0; return 0;
} }
void _dns_server_request_release(struct dns_request *request); static void _dns_server_request_release(struct dns_request *request);
void _dns_server_request_remove(struct dns_request *request) static void _dns_server_request_remove(struct dns_request *request)
{ {
pthread_mutex_lock(&server.request_list_lock); pthread_mutex_lock(&server.request_list_lock);
if (list_empty(&request->list)) { if (list_empty(&request->list)) {
@@ -612,7 +630,7 @@ void _dns_server_request_remove(struct dns_request *request)
_dns_server_request_release(request); _dns_server_request_release(request);
} }
void _dns_server_select_possible_ipaddress(struct dns_request *request) static void _dns_server_select_possible_ipaddress(struct dns_request *request)
{ {
int maxhit = 0; int maxhit = 0;
int bucket = 0; int bucket = 0;
@@ -627,6 +645,8 @@ void _dns_server_select_possible_ipaddress(struct dns_request *request)
return; return;
} }
/* Return the most likely correct IP address */
/* Returns the IP with the most hits, or the last returned record is considered to be the most likely correct. */
hash_for_each_safe(request->ip_map, bucket, tmp, addr_map, node) hash_for_each_safe(request->ip_map, bucket, tmp, addr_map, node)
{ {
if (addr_map->addr_type != request->qtype) { if (addr_map->addr_type != request->qtype) {
@@ -660,22 +680,22 @@ void _dns_server_select_possible_ipaddress(struct dns_request *request)
memcpy(request->ipv4_addr, selected_addr_map->ipv4_addr, DNS_RR_A_LEN); memcpy(request->ipv4_addr, selected_addr_map->ipv4_addr, DNS_RR_A_LEN);
request->ttl_v4 = DNS_SERVER_TMOUT_TTL; request->ttl_v4 = DNS_SERVER_TMOUT_TTL;
tlog(TLOG_DEBUG, "possible result: %s, rcode: %d, %d.%d.%d.%d\n", request->domain, request->rcode, request->ipv4_addr[0], request->ipv4_addr[1], tlog(TLOG_DEBUG, "possible 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]); request->ipv4_addr[2], request->ipv4_addr[3]);
} break; } break;
case DNS_T_AAAA: { case DNS_T_AAAA: {
memcpy(request->ipv6_addr, selected_addr_map->ipv6_addr, DNS_RR_AAAA_LEN); memcpy(request->ipv6_addr, selected_addr_map->ipv6_addr, DNS_RR_AAAA_LEN);
request->ttl_v6 = DNS_SERVER_TMOUT_TTL; request->ttl_v6 = DNS_SERVER_TMOUT_TTL;
tlog(TLOG_DEBUG, "possible result: %s, rcode: %d, %.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x", request->domain, request->rcode, tlog(TLOG_DEBUG, "possible result: %s, rcode: %d, %.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x", request->domain,
request->ipv6_addr[0], request->ipv6_addr[1], request->ipv6_addr[2], request->ipv6_addr[3], request->ipv6_addr[4], request->ipv6_addr[5], 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[6], request->ipv6_addr[7], request->ipv6_addr[8], request->ipv6_addr[9], request->ipv6_addr[10], request->ipv6_addr[11], request->ipv6_addr[5], request->ipv6_addr[6], request->ipv6_addr[7], request->ipv6_addr[8], request->ipv6_addr[9], request->ipv6_addr[10],
request->ipv6_addr[12], request->ipv6_addr[13], request->ipv6_addr[14], request->ipv6_addr[15]); request->ipv6_addr[11], request->ipv6_addr[12], request->ipv6_addr[13], request->ipv6_addr[14], request->ipv6_addr[15]);
} break; } break;
default: default:
break; break;
} }
} }
void _dns_server_request_release(struct dns_request *request) static void _dns_server_request_release(struct dns_request *request)
{ {
struct dns_ip_address *addr_map; struct dns_ip_address *addr_map;
struct hlist_node *tmp; struct hlist_node *tmp;
@@ -709,7 +729,7 @@ void _dns_server_request_release(struct dns_request *request)
free(request); free(request);
} }
void _dns_server_request_get(struct dns_request *request) static void _dns_server_request_get(struct dns_request *request)
{ {
if (atomic_inc_return(&request->refcnt) <= 0) { if (atomic_inc_return(&request->refcnt) <= 0) {
tlog(TLOG_ERROR, "BUG: request ref is invalid, %s", request->domain); tlog(TLOG_ERROR, "BUG: request ref is invalid, %s", request->domain);
@@ -717,8 +737,8 @@ void _dns_server_request_get(struct dns_request *request)
} }
} }
void _dns_server_ping_result(struct ping_host_struct *ping_host, const char *host, FAST_PING_RESULT result, struct sockaddr *addr, socklen_t addr_len, static void _dns_server_ping_result(struct ping_host_struct *ping_host, const char *host, FAST_PING_RESULT result, struct sockaddr *addr, socklen_t addr_len,
int seqno, int ttl, struct timeval *tv, void *userptr) int seqno, int ttl, struct timeval *tv, void *userptr)
{ {
struct dns_request *request = userptr; struct dns_request *request = userptr;
int may_complete = 0; int may_complete = 0;
@@ -781,19 +801,20 @@ void _dns_server_ping_result(struct ping_host_struct *ping_host, const char *hos
tlog(TLOG_DEBUG, "from %s: seq=%d timeout\n", host, seqno); tlog(TLOG_DEBUG, "from %s: seq=%d timeout\n", host, seqno);
} }
/* If the ping delay is less than the threshold, the result is returned */
if (rtt < threshold) { if (rtt < threshold) {
may_complete = 1; may_complete = 1;
} else if (rtt < (get_tick_count() - request->send_tick) * 10) { } else if (rtt < (get_tick_count() - request->send_tick) * 10) {
may_complete = 1; may_complete = 1;
} }
if (may_complete && request->has_ping_result == 1) { if (may_complete && request->has_ping_result == 1) {
_dns_server_request_complete(request); _dns_server_request_complete(request);
_dns_server_request_remove(request); _dns_server_request_remove(request);
} }
} }
int _dns_server_ping(struct dns_request *request, PING_TYPE type, char *ip, int timeout) static int _dns_server_ping(struct dns_request *request, PING_TYPE type, char *ip, int timeout)
{ {
if (fast_ping_start(type, ip, 1, 0, timeout, _dns_server_ping_result, request) == NULL) { if (fast_ping_start(type, ip, 1, 0, timeout, _dns_server_ping_result, request) == NULL) {
return -1; return -1;
@@ -802,7 +823,7 @@ int _dns_server_ping(struct dns_request *request, PING_TYPE type, char *ip, int
return 0; return 0;
} }
int _dns_ip_address_check_add(struct dns_request *request, unsigned char *addr, dns_type_t addr_type) static int _dns_ip_address_check_add(struct dns_request *request, unsigned char *addr, dns_type_t addr_type)
{ {
uint32_t key = 0; uint32_t key = 0;
struct dns_ip_address *addr_map = NULL; struct dns_ip_address *addr_map = NULL;
@@ -816,6 +837,7 @@ int _dns_ip_address_check_add(struct dns_request *request, unsigned char *addr,
return -1; return -1;
} }
/* store the ip address and the number of hits */
key = jhash(addr, addr_len, 0); key = jhash(addr, addr_len, 0);
pthread_mutex_lock(&request->ip_map_lock); pthread_mutex_lock(&request->ip_map_lock);
hash_for_each_possible(request->ip_map, addr_map, node, key) hash_for_each_possible(request->ip_map, addr_map, node, key)
@@ -875,6 +897,7 @@ static int _dns_server_ip_rule_check(struct dns_request *request, unsigned char
radix_node_t *node = NULL; radix_node_t *node = NULL;
struct dns_ip_address_rule *rule = NULL; struct dns_ip_address_rule *rule = NULL;
/* Match IP address rules */
if (prefix_from_blob(addr, addr_len, addr_len * 8, &prefix) == NULL) { if (prefix_from_blob(addr, addr_len, addr_len * 8, &prefix) == NULL) {
return -1; return -1;
} }
@@ -889,7 +912,7 @@ static int _dns_server_ip_rule_check(struct dns_request *request, unsigned char
default: default:
break; break;
} }
if (node == NULL) { if (node == NULL) {
return -1; return -1;
} }
@@ -898,17 +921,20 @@ static int _dns_server_ip_rule_check(struct dns_request *request, unsigned char
return -1; return -1;
} }
/* bogux-nxdomain */
rule = node->data; rule = node->data;
if (rule->bogus) { if (rule->bogus) {
goto match; goto match;
} }
/* blacklist-ip */
if (rule->blacklist) { if (rule->blacklist) {
if (result_flag & DNSSERVER_FLAG_BLACKLIST_IP) { if (result_flag & DNSSERVER_FLAG_BLACKLIST_IP) {
goto match; goto match;
} }
} }
/* ignore-ip */
if (rule->ip_ignore) { if (rule->ip_ignore) {
goto skip; goto skip;
} }
@@ -945,7 +971,6 @@ static int _dns_server_process_answer(struct dns_request *request, char *domain,
return -1; return -1;
} }
ping_timeout = ping_timeout - (now - request->send_tick); ping_timeout = ping_timeout - (now - request->send_tick);
if (ping_timeout > DNS_PING_TIMEOUT) { if (ping_timeout > DNS_PING_TIMEOUT) {
ping_timeout = DNS_PING_TIMEOUT; ping_timeout = DNS_PING_TIMEOUT;
@@ -966,6 +991,7 @@ static int _dns_server_process_answer(struct dns_request *request, char *domain,
} }
} }
_dns_server_request_get(request); _dns_server_request_get(request);
/* get A result */
dns_get_A(rrs, name, DNS_MAX_CNAME_LEN, &ttl, addr); dns_get_A(rrs, name, DNS_MAX_CNAME_LEN, &ttl, addr);
tlog(TLOG_DEBUG, "domain: %s TTL:%d IP: %d.%d.%d.%d", name, ttl, addr[0], addr[1], addr[2], addr[3]); tlog(TLOG_DEBUG, "domain: %s TTL:%d IP: %d.%d.%d.%d", name, ttl, addr[0], addr[1], addr[2], addr[3]);
@@ -973,13 +999,16 @@ static int _dns_server_process_answer(struct dns_request *request, char *domain,
/* ip rule check */ /* ip rule check */
ip_check_result = _dns_server_ip_rule_check(request, addr, 4, DNS_T_A, result_flag); ip_check_result = _dns_server_ip_rule_check(request, addr, 4, DNS_T_A, result_flag);
if (ip_check_result == 0) { if (ip_check_result == 0) {
/* match */
_dns_server_request_release(request); _dns_server_request_release(request);
break; break;
} else if (ip_check_result == -2) { } else if (ip_check_result == -2) {
/* skip */
_dns_server_request_release(request); _dns_server_request_release(request);
continue; continue;
} }
/* if domain is not match */
if (strncmp(name, domain, DNS_MAX_CNAME_LEN) != 0 && strncmp(request->cname, name, DNS_MAX_CNAME_LEN) != 0) { if (strncmp(name, domain, DNS_MAX_CNAME_LEN) != 0 && strncmp(request->cname, name, DNS_MAX_CNAME_LEN) != 0) {
_dns_server_request_release(request); _dns_server_request_release(request);
break; break;
@@ -995,13 +1024,16 @@ static int _dns_server_process_answer(struct dns_request *request, char *domain,
} }
} }
/* Ad blocking result */
if (addr[0] == 0 || addr[0] == 127) { if (addr[0] == 0 || addr[0] == 127) {
/* If half of the servers return the same result, then the domain name result is the IP address. */
if (atomic_inc_return(&request->adblock) <= dns_server_num() / 2) { if (atomic_inc_return(&request->adblock) <= dns_server_num() / 2) {
_dns_server_request_release(request); _dns_server_request_release(request);
break; break;
} }
} }
/* add this ip to reqeust */
if (_dns_ip_address_check_add(request, addr, DNS_T_A) != 0) { if (_dns_ip_address_check_add(request, addr, DNS_T_A) != 0) {
_dns_server_request_release(request); _dns_server_request_release(request);
break; break;
@@ -1010,6 +1042,7 @@ static int _dns_server_process_answer(struct dns_request *request, char *domain,
request->rcode = packet->head.rcode; request->rcode = packet->head.rcode;
sprintf(ip, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]); sprintf(ip, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]);
/* start ping */
if (_dns_server_ping(request, PING_TYPE_ICMP, ip, ping_timeout) != 0) { if (_dns_server_ping(request, PING_TYPE_ICMP, ip, ping_timeout) != 0) {
_dns_server_request_release(request); _dns_server_request_release(request);
} }
@@ -1028,13 +1061,16 @@ static int _dns_server_process_answer(struct dns_request *request, char *domain,
ip_check_result = _dns_server_ip_rule_check(request, addr, 16, DNS_T_AAAA, result_flag); ip_check_result = _dns_server_ip_rule_check(request, addr, 16, DNS_T_AAAA, result_flag);
if (ip_check_result == 0) { if (ip_check_result == 0) {
/* match */
_dns_server_request_release(request); _dns_server_request_release(request);
break; break;
} else if (ip_check_result == -2) { } else if (ip_check_result == -2) {
/* skip */
_dns_server_request_release(request); _dns_server_request_release(request);
continue; continue;
} }
/* if domain is not match */
if (strncmp(name, domain, DNS_MAX_CNAME_LEN) != 0 && strncmp(request->cname, name, DNS_MAX_CNAME_LEN) != 0) { if (strncmp(name, domain, DNS_MAX_CNAME_LEN) != 0 && strncmp(request->cname, name, DNS_MAX_CNAME_LEN) != 0) {
_dns_server_request_release(request); _dns_server_request_release(request);
break; break;
@@ -1050,6 +1086,7 @@ static int _dns_server_process_answer(struct dns_request *request, char *domain,
} }
} }
/* add this ip to reqeust */
if (_dns_ip_address_check_add(request, addr, DNS_T_AAAA) != 0) { if (_dns_ip_address_check_add(request, addr, DNS_T_AAAA) != 0) {
_dns_server_request_release(request); _dns_server_request_release(request);
break; break;
@@ -1060,6 +1097,7 @@ static int _dns_server_process_answer(struct dns_request *request, char *domain,
sprintf(ip, "%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], sprintf(ip, "%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5],
addr[6], addr[7], addr[8], addr[9], addr[10], addr[11], addr[12], addr[13], addr[14], addr[15]); addr[6], addr[7], addr[8], addr[9], addr[10], addr[11], addr[12], addr[13], addr[14], addr[15]);
/* start ping */
if (_dns_server_ping(request, PING_TYPE_ICMP, ip, ping_timeout) != 0) { if (_dns_server_ping(request, PING_TYPE_ICMP, ip, ping_timeout) != 0) {
_dns_server_request_release(request); _dns_server_request_release(request);
} }
@@ -1081,8 +1119,9 @@ static int _dns_server_process_answer(struct dns_request *request, char *domain,
request->has_soa = 1; request->has_soa = 1;
request->rcode = packet->head.rcode; request->rcode = packet->head.rcode;
dns_get_SOA(rrs, name, 128, &ttl, &request->soa); dns_get_SOA(rrs, name, 128, &ttl, &request->soa);
tlog(TLOG_DEBUG, "domain: %s, qtype: %d, SOA: mname: %s, rname: %s, serial: %d, refresh: %d, retry: %d, expire: %d, minimum: %d", domain, request->qtype, tlog(TLOG_DEBUG, "domain: %s, qtype: %d, SOA: mname: %s, rname: %s, serial: %d, refresh: %d, retry: %d, expire: %d, minimum: %d", domain,
request->soa.mname, request->soa.rname, request->soa.serial, request->soa.refresh, request->soa.retry, request->soa.expire, request->soa.minimum); request->qtype, request->soa.mname, request->soa.rname, request->soa.serial, request->soa.refresh, request->soa.retry, request->soa.expire,
request->soa.minimum);
} break; } break;
default: default:
tlog(TLOG_DEBUG, "%s, qtype: %d", name, rrs->type); tlog(TLOG_DEBUG, "%s, qtype: %d", name, rrs->type);
@@ -1116,6 +1155,7 @@ static int _dns_server_reply_passthrouth(struct dns_request *request, struct dns
return 0; return 0;
} }
/* When passthrough, modify the id to be the id of the client request. */
dns_server_update_reply_packet_id(request, inpacket, inpacket_len); dns_server_update_reply_packet_id(request, inpacket, inpacket_len);
ret = _dns_reply_inpacket(request, inpacket, inpacket_len); ret = _dns_reply_inpacket(request, inpacket, inpacket_len);
@@ -1177,6 +1217,7 @@ static int _dns_server_process_ptr(struct dns_request *request, struct dns_packe
return -1; return -1;
} }
/* Get the NIC IP and match it. If the match is successful, return the host name. */
for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
if (ifa->ifa_addr == NULL) { if (ifa->ifa_addr == NULL) {
continue; continue;
@@ -1217,6 +1258,7 @@ static int _dns_server_process_ptr(struct dns_request *request, struct dns_packe
} }
} }
/* Determine if the smartdns service is in effect. */
if (strstr(request->domain, "0.0.0.0.in-addr.arpa") != NULL) { if (strstr(request->domain, "0.0.0.0.in-addr.arpa") != NULL) {
found = 1; found = 1;
} }
@@ -1259,12 +1301,14 @@ static struct dns_domain_rule *_dns_server_get_domain_rule(char *domain)
unsigned char matched_key[DNS_MAX_CNAME_LEN]; unsigned char matched_key[DNS_MAX_CNAME_LEN];
struct dns_domain_rule *domain_rule = NULL; struct dns_domain_rule *domain_rule = NULL;
/* reverse domain string */
domain_len = strlen(domain); domain_len = strlen(domain);
reverse_string(domain_key, domain, domain_len); reverse_string(domain_key, domain, domain_len);
domain_key[domain_len] = '.'; domain_key[domain_len] = '.';
domain_len++; domain_len++;
domain_key[domain_len] = 0; domain_key[domain_len] = 0;
/* find domain rule */
if (likely(dns_conf_log_level > TLOG_INFO)) { if (likely(dns_conf_log_level > TLOG_INFO)) {
return art_substring(&dns_conf_domain_rule, (unsigned char *)domain_key, domain_len, NULL, NULL); return art_substring(&dns_conf_domain_rule, (unsigned char *)domain_key, domain_len, NULL, NULL);
} }
@@ -1293,6 +1337,7 @@ static int _dns_server_pre_process_rule_flags(struct dns_request *request, struc
goto errout; goto errout;
} }
/* get domain rule flag */
rule_flag = request->domain_rule->rules[DOMAIN_RULE_FLAGS]; rule_flag = request->domain_rule->rules[DOMAIN_RULE_FLAGS];
if (rule_flag == NULL) { if (rule_flag == NULL) {
goto errout; goto errout;
@@ -1300,31 +1345,38 @@ static int _dns_server_pre_process_rule_flags(struct dns_request *request, struc
flags = rule_flag->flags; flags = rule_flag->flags;
if (flags & DOMAIN_FLAG_ADDR_IGN) { if (flags & DOMAIN_FLAG_ADDR_IGN) {
/* ignore this domain */
goto errout; goto errout;
} }
if (flags & DOMAIN_FLAG_ADDR_SOA) { if (flags & DOMAIN_FLAG_ADDR_SOA) {
/* return SOA */
_dns_server_reply_SOA(DNS_RC_NOERROR, request, packet); _dns_server_reply_SOA(DNS_RC_NOERROR, request, packet);
return 0; return 0;
} }
/* return specific type of address */
switch (request->qtype) { switch (request->qtype) {
case DNS_T_A: case DNS_T_A:
if (flags & DOMAIN_FLAG_ADDR_IPV4_IGN) { if (flags & DOMAIN_FLAG_ADDR_IPV4_IGN) {
/* ignore this domain for A reqeust */
goto errout; goto errout;
} }
if (flags & DOMAIN_FLAG_ADDR_IPV4_SOA) { if (flags & DOMAIN_FLAG_ADDR_IPV4_SOA) {
/* return SOA for A request */
_dns_server_reply_SOA(DNS_RC_NOERROR, request, packet); _dns_server_reply_SOA(DNS_RC_NOERROR, request, packet);
return 0; return 0;
} }
break; break;
case DNS_T_AAAA: case DNS_T_AAAA:
if (flags & DOMAIN_FLAG_ADDR_IPV6_IGN) { if (flags & DOMAIN_FLAG_ADDR_IPV6_IGN) {
/* ignore this domain for A reqeust */
goto errout; goto errout;
} }
if (flags & DOMAIN_FLAG_ADDR_IPV6_SOA) { if (flags & DOMAIN_FLAG_ADDR_IPV6_SOA) {
/* return SOA for A request */
_dns_server_reply_SOA(DNS_RC_NOERROR, request, packet); _dns_server_reply_SOA(DNS_RC_NOERROR, request, packet);
return 0; return 0;
} }
@@ -1347,6 +1399,7 @@ static int _dns_server_process_address(struct dns_request *request, struct dns_p
goto errout; goto errout;
} }
/* address /domain/ rule */
switch (request->qtype) { switch (request->qtype) {
case DNS_T_A: case DNS_T_A:
if (request->domain_rule->rules[DOMAIN_RULE_ADDRESS_IPV4] == NULL) { if (request->domain_rule->rules[DOMAIN_RULE_ADDRESS_IPV4] == NULL) {
@@ -1392,6 +1445,7 @@ static int _dns_server_process_cache(struct dns_request *request, struct dns_pac
goto errout; goto errout;
} }
/* Cache hits, returning results in the cache */
switch (request->qtype) { switch (request->qtype) {
case DNS_T_A: case DNS_T_A:
memcpy(request->ipv4_addr, dns_cache->ipv4_addr, DNS_RR_A_LEN); memcpy(request->ipv4_addr, dns_cache->ipv4_addr, DNS_RR_A_LEN);
@@ -1444,6 +1498,7 @@ static int _dns_server_recv(struct dns_server_conn *client, unsigned char *inpac
_dns_server_client_get(client); _dns_server_client_get(client);
/* decode packet */
tlog(TLOG_DEBUG, "recv query packet from %s, len = %d", gethost_by_addr(name, sizeof(name), (struct sockaddr *)from), inpacket_len); tlog(TLOG_DEBUG, "recv query packet from %s, len = %d", gethost_by_addr(name, sizeof(name), (struct sockaddr *)from), inpacket_len);
decode_len = dns_decode(packet, DNS_PACKSIZE, inpacket, inpacket_len); decode_len = dns_decode(packet, DNS_PACKSIZE, inpacket, inpacket_len);
if (decode_len < 0) { if (decode_len < 0) {
@@ -1466,7 +1521,7 @@ static int _dns_server_recv(struct dns_server_conn *client, unsigned char *inpac
} }
memset(request, 0, sizeof(*request)); memset(request, 0, sizeof(*request));
pthread_mutex_init(&request->ip_map_lock, 0); pthread_mutex_init(&request->ip_map_lock, NULL);
atomic_set(&request->adblock, 0); atomic_set(&request->adblock, 0);
atomic_set(&request->refcnt, 0); atomic_set(&request->refcnt, 0);
request->ping_ttl_v4 = -1; request->ping_ttl_v4 = -1;
@@ -1476,6 +1531,7 @@ static int _dns_server_recv(struct dns_server_conn *client, unsigned char *inpac
request->client = client; request->client = client;
INIT_LIST_HEAD(&request->list); INIT_LIST_HEAD(&request->list);
/* get client request address type */
if (_dns_recv_addr(request, from, from_len) != 0) { if (_dns_recv_addr(request, from, from_len) != 0) {
goto errout; goto errout;
} }
@@ -1484,6 +1540,7 @@ static int _dns_server_recv(struct dns_server_conn *client, unsigned char *inpac
memcpy(&request->head, &packet->head, sizeof(struct dns_head)); memcpy(&request->head, &packet->head, sizeof(struct dns_head));
hash_init(request->ip_map); hash_init(request->ip_map);
/* get request domain and request qtype */
rrs = dns_get_rrs_start(packet, DNS_RRS_QD, &rr_count); rrs = dns_get_rrs_start(packet, DNS_RRS_QD, &rr_count);
if (rr_count > 1) { if (rr_count > 1) {
goto errout; goto errout;
@@ -1498,45 +1555,54 @@ static int _dns_server_recv(struct dns_server_conn *client, unsigned char *inpac
request->qtype = qtype; request->qtype = qtype;
} }
/* lookup domain rule */
request->domain_rule = _dns_server_get_domain_rule(request->domain); request->domain_rule = _dns_server_get_domain_rule(request->domain);
switch (qtype) { switch (qtype) {
case DNS_T_PTR: case DNS_T_PTR:
/* return PTR record */
ret = _dns_server_process_ptr(request, packet); ret = _dns_server_process_ptr(request, packet);
if (ret == 0) { if (ret == 0) {
goto clean_exit; goto clean_exit;
} else { } else {
/* pass to upstream server */
request->passthrough = 1; request->passthrough = 1;
} }
break; break;
case DNS_T_A: case DNS_T_A:
break; break;
case DNS_T_AAAA: case DNS_T_AAAA:
/* force return SOA */
if (dns_conf_force_AAAA_SOA == 1) { if (dns_conf_force_AAAA_SOA == 1) {
_dns_server_reply_SOA(DNS_RC_NOERROR, request, packet); _dns_server_reply_SOA(DNS_RC_NOERROR, request, packet);
goto clean_exit; goto clean_exit;
} }
break; break;
default: default:
tlog(TLOG_DEBUG, "unsupport qtype: %d, domain: %s", qtype, request->domain); tlog(TLOG_DEBUG, "unsupport qtype: %d, domain: %s", qtype, request->domain);
request->passthrough = 1; request->passthrough = 1;
/* pass request to upstream server */
break; break;
} }
/* process domain flag */
if (_dns_server_pre_process_rule_flags(request, packet) == 0) { if (_dns_server_pre_process_rule_flags(request, packet) == 0) {
goto clean_exit; goto clean_exit;
} }
/* process domain address */
if (_dns_server_process_address(request, packet) == 0) { if (_dns_server_process_address(request, packet) == 0) {
goto clean_exit; goto clean_exit;
} }
/* process cache */
if (_dns_server_process_cache(request, packet) == 0) { if (_dns_server_process_cache(request, packet) == 0) {
goto clean_exit; goto clean_exit;
} }
if (request->domain_rule) { if (request->domain_rule) {
/* Get the nameserver rule */
if (request->domain_rule->rules[DOMAIN_RULE_NAMESERVER]) { if (request->domain_rule->rules[DOMAIN_RULE_NAMESERVER]) {
struct dns_nameserver_rule *nameserver_rule = request->domain_rule->rules[DOMAIN_RULE_NAMESERVER]; struct dns_nameserver_rule *nameserver_rule = request->domain_rule->rules[DOMAIN_RULE_NAMESERVER];
group_name = nameserver_rule->group_name; group_name = nameserver_rule->group_name;
@@ -1553,6 +1619,7 @@ static int _dns_server_recv(struct dns_server_conn *client, unsigned char *inpac
_dns_server_request_get(request); _dns_server_request_get(request);
request->send_tick = get_tick_count(); request->send_tick = get_tick_count();
/* When the dual stack ip preference is enabled, both A and AAAA records are requested. */
if (qtype == DNS_T_AAAA && dns_conf_dualstack_ip_selection) { if (qtype == DNS_T_AAAA && dns_conf_dualstack_ip_selection) {
_dns_server_request_get(request); _dns_server_request_get(request);
request->request_wait++; request->request_wait++;
@@ -1601,7 +1668,7 @@ static int _dns_server_prefetch_request(char *domain, dns_type_t qtype)
goto errout; goto errout;
} }
memset(request, 0, sizeof(*request)); memset(request, 0, sizeof(*request));
pthread_mutex_init(&request->ip_map_lock, 0); pthread_mutex_init(&request->ip_map_lock, NULL);
atomic_set(&request->adblock, 0); atomic_set(&request->adblock, 0);
request->ping_ttl_v4 = -1; request->ping_ttl_v4 = -1;
request->ping_ttl_v6 = -1; request->ping_ttl_v6 = -1;
@@ -1613,6 +1680,7 @@ static int _dns_server_prefetch_request(char *domain, dns_type_t qtype)
hash_init(request->ip_map); hash_init(request->ip_map);
strncpy(request->domain, domain, DNS_MAX_CNAME_LEN); strncpy(request->domain, domain, DNS_MAX_CNAME_LEN);
/* lookup domain rule */
request->domain_rule = _dns_server_get_domain_rule(request->domain); request->domain_rule = _dns_server_get_domain_rule(request->domain);
tlog(TLOG_INFO, "prefetch domain %s, qtype = %d\n", request->domain, qtype); tlog(TLOG_INFO, "prefetch domain %s, qtype = %d\n", request->domain, qtype);
@@ -1627,11 +1695,14 @@ static int _dns_server_prefetch_request(char *domain, dns_type_t qtype)
request->request_wait++; request->request_wait++;
if (request->domain_rule) { if (request->domain_rule) {
/* get nameserver rule */
if (request->domain_rule->rules[DOMAIN_RULE_NAMESERVER]) { if (request->domain_rule->rules[DOMAIN_RULE_NAMESERVER]) {
struct dns_nameserver_rule *nameserver_rule = request->domain_rule->rules[DOMAIN_RULE_NAMESERVER]; struct dns_nameserver_rule *nameserver_rule = request->domain_rule->rules[DOMAIN_RULE_NAMESERVER];
group_name = nameserver_rule->group_name; group_name = nameserver_rule->group_name;
} }
} }
/* send request */
dns_client_query(request->domain, qtype, dns_server_resolve_callback, request, group_name); dns_client_query(request->domain, qtype, dns_server_resolve_callback, request, group_name);
return 0; return 0;
@@ -1724,10 +1795,11 @@ errout:
return -1; return -1;
} }
int _dns_server_tcp_recv(struct dns_server_conn *dnsserver) static int _dns_server_tcp_recv(struct dns_server_conn *dnsserver)
{ {
int len = 0; int len = 0;
/* Receive data */
while (dnsserver->recvbuff.size < sizeof(dnsserver->recvbuff.buf)) { while (dnsserver->recvbuff.size < sizeof(dnsserver->recvbuff.buf)) {
if (dnsserver->recvbuff.size == sizeof(dnsserver->recvbuff.buf)) { if (dnsserver->recvbuff.size == sizeof(dnsserver->recvbuff.buf)) {
return 0; return 0;
@@ -1750,7 +1822,7 @@ int _dns_server_tcp_recv(struct dns_server_conn *dnsserver)
return 0; return 0;
} }
int _dns_server_tcp_process_one_request(struct dns_server_conn *dnsserver) static int _dns_server_tcp_process_one_request(struct dns_server_conn *dnsserver)
{ {
int request_len = 0; int request_len = 0;
int total_len = dnsserver->recvbuff.size; int total_len = dnsserver->recvbuff.size;
@@ -1758,12 +1830,14 @@ int _dns_server_tcp_process_one_request(struct dns_server_conn *dnsserver)
unsigned char *request_data = NULL; unsigned char *request_data = NULL;
int ret = 0; int ret = 0;
/* Handling multiple requests */
for (;;) { for (;;) {
if ((total_len - proceed_len) <= sizeof(unsigned short)) { if ((total_len - proceed_len) <= sizeof(unsigned short)) {
ret = 1; ret = 1;
break; break;
} }
/* Get record length */
request_data = (unsigned char *)(dnsserver->recvbuff.buf + proceed_len); request_data = (unsigned char *)(dnsserver->recvbuff.buf + proceed_len);
request_len = ntohs(*((unsigned short *)(request_data))); request_len = ntohs(*((unsigned short *)(request_data)));
@@ -1779,6 +1853,7 @@ int _dns_server_tcp_process_one_request(struct dns_server_conn *dnsserver)
request_data = (unsigned char *)(dnsserver->recvbuff.buf + proceed_len + sizeof(unsigned short)); request_data = (unsigned char *)(dnsserver->recvbuff.buf + proceed_len + sizeof(unsigned short));
/* process one record */
if (_dns_server_recv(dnsserver, request_data, request_len, &dnsserver->addr, dnsserver->addr_len) != 0) { if (_dns_server_recv(dnsserver, request_data, request_len, &dnsserver->addr, dnsserver->addr_len) != 0) {
tlog(TLOG_ERROR, "process tcp request failed."); tlog(TLOG_ERROR, "process tcp request failed.");
return -1; return -1;
@@ -1796,7 +1871,7 @@ int _dns_server_tcp_process_one_request(struct dns_server_conn *dnsserver)
return ret; return ret;
} }
int _dns_server_tcp_process_requests(struct dns_server_conn *client) static int _dns_server_tcp_process_requests(struct dns_server_conn *client)
{ {
int recv_ret = 0; int recv_ret = 0;
int request_ret = 0; int request_ret = 0;
@@ -1814,14 +1889,17 @@ int _dns_server_tcp_process_requests(struct dns_server_conn *client)
request_ret = _dns_server_tcp_process_one_request(client); request_ret = _dns_server_tcp_process_one_request(client);
if (request_ret < 0) { if (request_ret < 0) {
/* failed */
return -1; return -1;
} }
if (request_ret == 1 && is_eof == 1) { if (request_ret == 1 && is_eof == 1) {
/* failed or remote shutdown */
return -1; return -1;
} }
if (recv_ret == 1 && request_ret == 1) { if (recv_ret == 1 && request_ret == 1) {
/* process complete */
return 0; return 0;
} }
} }
@@ -1829,7 +1907,7 @@ int _dns_server_tcp_process_requests(struct dns_server_conn *client)
return 0; return 0;
} }
int _dns_server_tcp_send(struct dns_server_conn *client) static int _dns_server_tcp_send(struct dns_server_conn *client)
{ {
int len; int len;
while (client->sndbuff.size > 0) { while (client->sndbuff.size > 0) {
@@ -1894,7 +1972,7 @@ static int _dns_server_process(struct dns_server_conn *dnsserver, struct epoll_e
} }
} }
void _dns_server_tcp_ping_check(struct dns_request *request) static void _dns_server_tcp_ping_check(struct dns_request *request)
{ {
struct dns_ip_address *addr_map; struct dns_ip_address *addr_map;
int bucket = 0; int bucket = 0;
@@ -1908,6 +1986,7 @@ void _dns_server_tcp_ping_check(struct dns_request *request)
return; return;
} }
/* start tcping */
pthread_mutex_lock(&request->ip_map_lock); pthread_mutex_lock(&request->ip_map_lock);
hash_for_each(request->ip_map, bucket, addr_map, node) hash_for_each(request->ip_map, bucket, addr_map, node)
{ {
@@ -1939,21 +2018,23 @@ void _dns_server_tcp_ping_check(struct dns_request *request)
request->has_ping_tcp = 1; request->has_ping_tcp = 1;
} }
void _dns_server_prefetch_domain(struct dns_cache *dns_cache) static void _dns_server_prefetch_domain(struct dns_cache *dns_cache)
{ {
/* If there are still hits, continue pre-fetching */
if (dns_cache->hitnum <= 0) { if (dns_cache->hitnum <= 0) {
return; return;
} }
dns_cache->hitnum--; dns_cache->hitnum--;
/* start prefetch domain */
tlog(TLOG_DEBUG, "prefetch by cache %s, qtype %d, ttl %d, hitnum %d", dns_cache->domain, dns_cache->qtype, dns_cache->ttl, dns_cache->hitnum); tlog(TLOG_DEBUG, "prefetch by cache %s, qtype %d, ttl %d, hitnum %d", dns_cache->domain, dns_cache->qtype, dns_cache->ttl, dns_cache->hitnum);
if (_dns_server_prefetch_request(dns_cache->domain, dns_cache->qtype) != 0) { if (_dns_server_prefetch_request(dns_cache->domain, dns_cache->qtype) != 0) {
tlog(TLOG_ERROR, "prefetch domain %s, qtype %d, failed.", dns_cache->domain, dns_cache->qtype); tlog(TLOG_ERROR, "prefetch domain %s, qtype %d, failed.", dns_cache->domain, dns_cache->qtype);
} }
} }
void _dns_server_tcp_idle_check(void) static void _dns_server_tcp_idle_check(void)
{ {
struct dns_server_conn *client, *tmp; struct dns_server_conn *client, *tmp;
time_t now; time_t now;
@@ -1973,13 +2054,14 @@ void _dns_server_tcp_idle_check(void)
} }
} }
void _dns_server_period_run_second(void) static void _dns_server_period_run_second(void)
{ {
static unsigned int sec = 0; static unsigned int sec = 0;
sec++; sec++;
if (sec % 2 == 0) { if (sec % 2 == 0) {
if (dns_conf_prefetch) { if (dns_conf_prefetch) {
/* do pre-fetching */
dns_cache_invalidate(_dns_server_prefetch_domain, 3); dns_cache_invalidate(_dns_server_prefetch_domain, 3);
} else { } else {
dns_cache_invalidate(NULL, 0); dns_cache_invalidate(NULL, 0);
@@ -1989,7 +2071,7 @@ void _dns_server_period_run_second(void)
_dns_server_tcp_idle_check(); _dns_server_tcp_idle_check();
} }
void _dns_server_period_run(void) static void _dns_server_period_run(void)
{ {
struct dns_request *request, *tmp; struct dns_request *request, *tmp;
static unsigned int msec = 0; static unsigned int msec = 0;
@@ -2005,6 +2087,7 @@ void _dns_server_period_run(void)
pthread_mutex_lock(&server.request_list_lock); pthread_mutex_lock(&server.request_list_lock);
list_for_each_entry_safe(request, tmp, &server.request_list, list) list_for_each_entry_safe(request, tmp, &server.request_list, list)
{ {
/* Need to use tcping detection speed */
if (request->send_tick < now - DNS_TCPPING_START && request->has_ping_tcp == 0) { if (request->send_tick < now - DNS_TCPPING_START && request->has_ping_tcp == 0) {
_dns_server_request_get(request); _dns_server_request_get(request);
list_add_tail(&request->check_list, &check_list); list_add_tail(&request->check_list, &check_list);
@@ -2099,7 +2182,7 @@ errout:
return NULL; return NULL;
} }
int _dns_server_start_udp(void) static int _dns_server_start_udp(void)
{ {
struct epoll_event event; struct epoll_event event;
@@ -2118,7 +2201,7 @@ int _dns_server_start_udp(void)
return 0; return 0;
} }
int _dns_server_start_tcp(void) static int _dns_server_start_tcp(void)
{ {
struct epoll_event event; struct epoll_event event;
@@ -2151,7 +2234,7 @@ int dns_server_start(void)
return 0; return 0;
} }
int _dns_create_socket(const char *host_ip, int type) static int _dns_create_socket(const char *host_ip, int type)
{ {
int fd = -1; int fd = -1;
struct addrinfo *gai = NULL; struct addrinfo *gai = NULL;
@@ -2213,7 +2296,7 @@ errout:
return -1; return -1;
} }
int _dns_server_socket(void) static int _dns_server_socket(void)
{ {
int fd_udp = -1; int fd_udp = -1;
int fd_tcp = -1; int fd_tcp = -1;
@@ -2253,7 +2336,7 @@ errout:
return -1; return -1;
} }
void _dns_server_close_socket(void) static void _dns_server_close_socket(void)
{ {
struct dns_server_conn *client, *tmp; struct dns_server_conn *client, *tmp;
@@ -2273,7 +2356,7 @@ void _dns_server_close_socket(void)
} }
} }
int _dns_server_audit_init(void) static int _dns_server_audit_init(void)
{ {
char *audit_file = SMARTDNS_AUDIT_FILE; char *audit_file = SMARTDNS_AUDIT_FILE;
if (dns_conf_audit_enable == 0) { if (dns_conf_audit_enable == 0) {
@@ -2328,7 +2411,7 @@ int dns_server_init(void)
goto errout; goto errout;
} }
pthread_mutex_init(&server.request_list_lock, 0); pthread_mutex_init(&server.request_list_lock, NULL);
INIT_LIST_HEAD(&server.request_list); INIT_LIST_HEAD(&server.request_list);
server.epoll_fd = epollfd; server.epoll_fd = epollfd;
server.run = 1; server.run = 1;

View File

@@ -1,12 +1,21 @@
#ifndef _SMART_DNS_SERVER_H #ifndef _SMART_DNS_SERVER_H
#define _SMART_DNS_SERVER_H #define _SMART_DNS_SERVER_H
#ifdef __cpluscplus
extern "C" {
#endif
int dns_server_init(void); int dns_server_init(void);
int dns_server_run(void); int dns_server_run(void);
int dns_server_start(void);
void dns_server_stop(void); void dns_server_stop(void);
void dns_server_exit(void); void dns_server_exit(void);
#ifdef __cpluscplus
}
#endif
#endif #endif

View File

@@ -45,9 +45,9 @@
#define ICMP_INPACKET_SIZE 1024 #define ICMP_INPACKET_SIZE 1024
#ifndef ICMP_FILTER #ifndef ICMP_FILTER
#define ICMP_FILTER 1 #define ICMP_FILTER 1
struct icmp_filter { struct icmp_filter {
uint32_t data; uint32_t data;
}; };
#endif #endif
@@ -142,7 +142,7 @@ static struct fast_ping_struct ping;
static atomic_t ping_sid = ATOMIC_INIT(0); static atomic_t ping_sid = ATOMIC_INIT(0);
static int bool_print_log = 1; static int bool_print_log = 1;
uint16_t _fast_ping_checksum(uint16_t *header, size_t len) static uint16_t _fast_ping_checksum(uint16_t *header, size_t len)
{ {
uint32_t sum = 0; uint32_t sum = 0;
int i; int i;
@@ -154,7 +154,7 @@ uint16_t _fast_ping_checksum(uint16_t *header, size_t len)
return htons(~((sum >> 16) + (sum & 0xffff))); return htons(~((sum >> 16) + (sum & 0xffff)));
} }
void _fast_ping_install_filter_v6(int sock) static void _fast_ping_install_filter_v6(int sock)
{ {
struct icmp6_filter icmp6_filter; struct icmp6_filter icmp6_filter;
ICMP6_FILTER_SETBLOCKALL(&icmp6_filter); ICMP6_FILTER_SETBLOCKALL(&icmp6_filter);
@@ -186,7 +186,7 @@ void _fast_ping_install_filter_v6(int sock)
} }
} }
void _fast_ping_install_filter_v4(int sock) static void _fast_ping_install_filter_v4(int sock)
{ {
static int once; static int once;
static struct sock_filter insns[] = { static struct sock_filter insns[] = {
@@ -350,8 +350,8 @@ static int _fast_ping_sendping_v6(struct ping_host_struct *ping_host)
icmp6->icmp6_id = ping.ident; icmp6->icmp6_id = ping.ident;
icmp6->icmp6_seq = htons(ping_host->seq); icmp6->icmp6_seq = htons(ping_host->seq);
gettimeofday(&packet->msg.tv, 0); gettimeofday(&packet->msg.tv, NULL);
gettimeofday(&ping_host->last, 0); gettimeofday(&ping_host->last, NULL);
packet->msg.sid = ping_host->sid; packet->msg.sid = ping_host->sid;
packet->msg.cookie = ping_host->cookie; packet->msg.cookie = ping_host->cookie;
packet->msg.seq = ping_host->seq; packet->msg.seq = ping_host->seq;
@@ -397,8 +397,8 @@ static int _fast_ping_sendping_v4(struct ping_host_struct *ping_host)
icmp->icmp_id = ping.ident; icmp->icmp_id = ping.ident;
icmp->icmp_seq = htons(ping_host->seq); icmp->icmp_seq = htons(ping_host->seq);
gettimeofday(&packet->msg.tv, 0); gettimeofday(&packet->msg.tv, NULL);
gettimeofday(&ping_host->last, 0); gettimeofday(&ping_host->last, NULL);
packet->msg.sid = ping_host->sid; packet->msg.sid = ping_host->sid;
packet->msg.seq = ping_host->seq; packet->msg.seq = ping_host->seq;
packet->msg.cookie = ping_host->cookie; packet->msg.cookie = ping_host->cookie;
@@ -449,7 +449,7 @@ static int _fast_ping_sendping_udp(struct ping_host_struct *ping_host)
memset(&dns_head, 0, sizeof(dns_head)); memset(&dns_head, 0, sizeof(dns_head));
dns_head.id = htons(ping_host->sid); dns_head.id = htons(ping_host->sid);
dns_head.flag = flag; dns_head.flag = flag;
gettimeofday(&ping_host->last, 0); gettimeofday(&ping_host->last, NULL);
len = sendto(fd, &dns_head, sizeof(dns_head), 0, (struct sockaddr *)&ping_host->addr, ping_host->addr_len); len = sendto(fd, &dns_head, sizeof(dns_head), 0, (struct sockaddr *)&ping_host->addr, ping_host->addr_len);
if (len < 0 || len != sizeof(dns_head)) { if (len < 0 || len != sizeof(dns_head)) {
int err = errno; int err = errno;
@@ -499,13 +499,13 @@ static int _fast_ping_sendping_tcp(struct ping_host_struct *ping_host)
bool_print_log = 0; bool_print_log = 0;
} }
tlog(TLOG_ERROR, "connect %s, id %d, %s", gethost_by_addr(ping_host_name, sizeof(ping_host_name), (struct sockaddr *)&ping_host->addr), ping_host->sid, tlog(TLOG_ERROR, "connect %s, id %d, %s", gethost_by_addr(ping_host_name, sizeof(ping_host_name), (struct sockaddr *)&ping_host->addr),
strerror(errno)); ping_host->sid, strerror(errno));
goto errout; goto errout;
} }
} }
gettimeofday(&ping_host->last, 0); gettimeofday(&ping_host->last, NULL);
ping_host->fd = fd; ping_host->fd = fd;
memset(&event, 0, sizeof(event)); memset(&event, 0, sizeof(event));
event.events = EPOLLIN | EPOLLOUT | EPOLLERR; event.events = EPOLLIN | EPOLLOUT | EPOLLERR;
@@ -528,7 +528,7 @@ errout:
static int _fast_ping_sendping(struct ping_host_struct *ping_host) static int _fast_ping_sendping(struct ping_host_struct *ping_host)
{ {
int ret = -1; int ret = -1;
gettimeofday(&ping_host->last, 0); gettimeofday(&ping_host->last, NULL);
if (ping_host->type == FAST_PING_ICMP) { if (ping_host->type == FAST_PING_ICMP) {
ret = _fast_ping_sendping_v4(ping_host); ret = _fast_ping_sendping_v4(ping_host);
@@ -741,7 +741,7 @@ errout:
return -1; return -1;
} }
void fast_ping_print_result(struct ping_host_struct *ping_host, const char *host, FAST_PING_RESULT result, struct sockaddr *addr, socklen_t addr_len, int seqno, static void _fast_ping_print_result(struct ping_host_struct *ping_host, const char *host, FAST_PING_RESULT result, struct sockaddr *addr, socklen_t addr_len, int seqno,
int ttl, struct timeval *tv, void *userptr) int ttl, struct timeval *tv, void *userptr)
{ {
if (result == PING_RESULT_RESPONSE) { if (result == PING_RESULT_RESPONSE) {
@@ -882,7 +882,7 @@ struct ping_host_struct *fast_ping_start(PING_TYPE type, const char *host, int c
if (ping_callback) { if (ping_callback) {
ping_host->ping_callback = ping_callback; ping_host->ping_callback = ping_callback;
} else { } else {
ping_host->ping_callback = fast_ping_print_result; ping_host->ping_callback = _fast_ping_print_result;
} }
ping_host->interval = (timeout > interval) ? timeout : interval; ping_host->interval = (timeout > interval) ? timeout : interval;
ping_host->addr_len = gai->ai_addrlen; ping_host->addr_len = gai->ai_addrlen;
@@ -1028,7 +1028,7 @@ static struct fast_ping_packet *_fast_ping_icmp_packet(struct ping_host_struct *
return packet; return packet;
} }
struct fast_ping_packet *_fast_ping_recv_packet(struct ping_host_struct *ping_host, struct msghdr *msg, u_char *inpacket, int len, struct timeval *tvrecv) static struct fast_ping_packet *_fast_ping_recv_packet(struct ping_host_struct *ping_host, struct msghdr *msg, u_char *inpacket, int len, struct timeval *tvrecv)
{ {
struct fast_ping_packet *packet = NULL; struct fast_ping_packet *packet = NULL;
@@ -1325,7 +1325,7 @@ static void _fast_ping_period_run(void)
struct timeval now; struct timeval now;
struct timeval interval; struct timeval interval;
int64_t millisecond; int64_t millisecond;
gettimeofday(&now, 0); gettimeofday(&now, NULL);
LIST_HEAD(action); LIST_HEAD(action);
pthread_mutex_lock(&ping.map_lock); pthread_mutex_lock(&ping.map_lock);
@@ -1422,7 +1422,7 @@ static void *_fast_ping_work(void *arg)
continue; continue;
} }
gettimeofday(&tvnow, 0); gettimeofday(&tvnow, NULL);
for (i = 0; i < num; i++) { for (i = 0; i < num; i++) {
struct epoll_event *event = &events[i]; struct epoll_event *event = &events[i];
struct ping_host_struct *ping_host = (struct ping_host_struct *)event->data.ptr; struct ping_host_struct *ping_host = (struct ping_host_struct *)event->data.ptr;
@@ -1456,8 +1456,8 @@ int fast_ping_init(void)
goto errout; goto errout;
} }
pthread_mutex_init(&ping.map_lock, 0); pthread_mutex_init(&ping.map_lock, NULL);
pthread_mutex_init(&ping.lock, 0); pthread_mutex_init(&ping.lock, NULL);
hash_init(ping.addrmap); hash_init(ping.addrmap);
ping.epoll_fd = epollfd; ping.epoll_fd = epollfd;
ping.ident = (getpid() & 0XFFFF); ping.ident = (getpid() & 0XFFFF);

View File

@@ -237,4 +237,4 @@ int art_iter_prefix(art_tree *t, const unsigned char *prefix, int prefix_len, ar
} }
#endif #endif
#endif #endif

View File

@@ -11,7 +11,7 @@
* Atomic type. * Atomic type.
*/ */
typedef struct { typedef struct {
volatile int counter; int counter;
} atomic_t; } atomic_t;
#define ATOMIC_INIT(i) { (i) } #define ATOMIC_INIT(i) { (i) }
@@ -154,3 +154,4 @@ static inline int atomic_add_negative( int i, atomic_t *v )
} }
#endif #endif

View File

@@ -130,4 +130,4 @@ static inline int bitmap_and(unsigned long *dst, const unsigned long *src1,
return __bitmap_and(dst, src1, src2, nbits); return __bitmap_and(dst, src1, src2, nbits);
} }
#endif /* _PERF_BITOPS_H */ #endif /* _PERF_BITOPS_H */

View File

@@ -197,4 +197,4 @@ static inline uint32_t rol32(uint32_t word, unsigned int shift)
return (word << shift) | (word >> ((-shift) & 31)); return (word << shift) | (word >> ((-shift) & 31));
} }
#endif #endif

View File

@@ -86,7 +86,7 @@ struct config_item_size {
#define CONF_END() \ #define CONF_END() \
{ \ { \
0, 0, 0 \ NULL, NULL, NULL \
} }
extern int conf_custom(const char *item, void *data, int argc, char *argv[]); extern int conf_custom(const char *item, void *data, int argc, char *argv[]);
@@ -118,4 +118,4 @@ int load_conf(const char *file, struct config_item items[], conf_error_handler h
void load_exit(void); void load_exit(void);
#endif // !_GENERIC_CONF_H #endif // !_GENERIC_CONF_H

View File

@@ -74,4 +74,4 @@ extern unsigned long find_first_bit(const unsigned long *addr,
unsigned long find_first_zero_bit(const unsigned long *addr, unsigned long size); unsigned long find_first_zero_bit(const unsigned long *addr, unsigned long size);
#endif #endif
#endif /*_TOOLS_LINUX_ASM_GENERIC_BITOPS_FIND_H_ */ #endif /*_TOOLS_LINUX_ASM_GENERIC_BITOPS_FIND_H_ */

View File

@@ -114,4 +114,4 @@
#define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1) #define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1)
#define round_down(x, y) ((x) & ~__round_mask(x, y)) #define round_down(x, y) ((x) & ~__round_mask(x, y))
#endif /* _TOOLS_LINUX_COMPILER_H */ #endif /* _TOOLS_LINUX_COMPILER_H */

View File

@@ -210,4 +210,4 @@ hash_string(const char *str)
return(v); return(v);
} }
#endif /* _GENERIC_HASH_H */ #endif /* _GENERIC_HASH_H */

View File

@@ -147,4 +147,4 @@ static inline void hash_del(struct hlist_node *node)
hlist_for_each_entry_safe(obj, tmp,\ hlist_for_each_entry_safe(obj, tmp,\
&name[hash_min(key, HASH_BITS(name))], member) &name[hash_min(key, HASH_BITS(name))], member)
#endif #endif

View File

@@ -181,4 +181,4 @@ static inline uint32_t jhash_1word(uint32_t a, uint32_t initval)
return __jhash_nwords(a, 0, 0, initval + JHASH_INITVAL + (1 << 2)); return __jhash_nwords(a, 0, 0, initval + JHASH_INITVAL + (1 << 2));
} }
#endif /* _JHASH_H */ #endif /* _JHASH_H */

View File

@@ -789,4 +789,4 @@ static inline void list_del_range(struct list_head *begin,
#define list_for_each_from(pos, head) \ #define list_for_each_from(pos, head) \
for (; pos != (head); pos = pos->next) for (; pos != (head); pos = pos->next)
#endif /* _GENERIC_LIST_H */ #endif /* _GENERIC_LIST_H */

View File

@@ -159,3 +159,4 @@ const char *prefix_addr_ntop(prefix_t *prefix, char *buf, size_t len);
const char *prefix_ntop(prefix_t *prefix, char *buf, size_t len); const char *prefix_ntop(prefix_t *prefix, char *buf, size_t len);
#endif /* _RADIX_H */ #endif /* _RADIX_H */

View File

@@ -285,3 +285,4 @@ rb_erase_augmented(struct rb_node *node, struct rb_root *root,
} }
#endif /* _GENERIC_RBTREE_H */ #endif /* _GENERIC_RBTREE_H */

View File

@@ -49,7 +49,7 @@
static int verbose_screen; static int verbose_screen;
void help(void) static void _help(void)
{ {
/* clang-format off */ /* clang-format off */
char *help = "" char *help = ""
@@ -69,7 +69,7 @@ void help(void)
printf("%s", help); printf("%s", help);
} }
int smartdns_load_from_resolv(void) static int _smartdns_load_from_resolv(void)
{ {
FILE *fp = NULL; FILE *fp = NULL;
char line[MAX_LINE_LEN]; char line[MAX_LINE_LEN];
@@ -120,7 +120,7 @@ int smartdns_load_from_resolv(void)
return ret; return ret;
} }
int smartdns_add_servers(void) static int _smartdns_add_servers(void)
{ {
int i = 0; int i = 0;
int j = 0; int j = 0;
@@ -129,8 +129,8 @@ int smartdns_add_servers(void)
struct dns_servers *server = NULL; struct dns_servers *server = NULL;
for (i = 0; i < dns_conf_server_num; i++) { for (i = 0; i < dns_conf_server_num; i++) {
ret = dns_client_add_server(dns_conf_servers[i].server, dns_conf_servers[i].port, dns_conf_servers[i].type, dns_conf_servers[i].server_flag, dns_conf_servers[i].result_flag, ret = dns_client_add_server(dns_conf_servers[i].server, dns_conf_servers[i].port, dns_conf_servers[i].type, dns_conf_servers[i].server_flag,
dns_conf_servers[i].ttl, dns_conf_servers[i].spki); dns_conf_servers[i].result_flag, dns_conf_servers[i].ttl, dns_conf_servers[i].spki);
if (ret != 0) { if (ret != 0) {
tlog(TLOG_ERROR, "add server failed, %s:%d", dns_conf_servers[i].server, dns_conf_servers[i].port); tlog(TLOG_ERROR, "add server failed, %s:%d", dns_conf_servers[i].server, dns_conf_servers[i].port);
return -1; return -1;
@@ -158,11 +158,10 @@ int smartdns_add_servers(void)
} }
} }
return 0; return 0;
} }
int smartdns_set_ecs_ip(void) static int _smartdns_set_ecs_ip(void)
{ {
int ret = 0; int ret = 0;
if (dns_conf_ipv4_ecs.enable) { if (dns_conf_ipv4_ecs.enable) {
@@ -176,52 +175,7 @@ int smartdns_set_ecs_ip(void)
return ret; return ret;
} }
int create_pid_file(const char *pid_file) static int _smartdns_init_ssl(void)
{
int fd;
int flags;
char buff[TMP_BUFF_LEN_32];
/* create pid file, and lock this file */
fd = open(pid_file, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
if (fd == -1) {
fprintf(stderr, "create pid file failed, %s\n", strerror(errno));
return -1;
}
flags = fcntl(fd, F_GETFD);
if (flags < 0) {
fprintf(stderr, "Could not get flags for PID file %s\n", pid_file);
goto errout;
}
flags |= FD_CLOEXEC;
if (fcntl(fd, F_SETFD, flags) == -1) {
fprintf(stderr, "Could not set flags for PID file %s\n", pid_file);
goto errout;
}
if (lockf(fd, F_TLOCK, 0) < 0) {
fprintf(stderr, "Server is already running.\n");
goto errout;
}
snprintf(buff, TMP_BUFF_LEN_32, "%d\n", getpid());
if (write(fd, buff, strnlen(buff, TMP_BUFF_LEN_32)) < 0) {
fprintf(stderr, "write pid to file failed, %s.\n", strerror(errno));
goto errout;
}
return 0;
errout:
if (fd > 0) {
close(fd);
}
return -1;
}
int smartdns_init_ssl(void)
{ {
SSL_load_error_strings(); SSL_load_error_strings();
SSL_library_init(); SSL_library_init();
@@ -231,7 +185,7 @@ int smartdns_init_ssl(void)
return 0; return 0;
} }
int smartdns_destroy_ssl(void) static int _smartdns_destroy_ssl(void)
{ {
SSL_CRYPTO_thread_cleanup(); SSL_CRYPTO_thread_cleanup();
ERR_free_strings(); ERR_free_strings();
@@ -240,7 +194,7 @@ int smartdns_destroy_ssl(void)
return 0; return 0;
} }
int smartdns_init(void) static int _smartdns_init(void)
{ {
int ret; int ret;
char *logfile = SMARTDNS_LOG_FILE; char *logfile = SMARTDNS_LOG_FILE;
@@ -260,13 +214,13 @@ int smartdns_init(void)
tlog(TLOG_NOTICE, "smartdns starting...(Copyright (C) Nick Peng <pymumu@gmail.com>, build:%s %s)", __DATE__, __TIME__); tlog(TLOG_NOTICE, "smartdns starting...(Copyright (C) Nick Peng <pymumu@gmail.com>, build:%s %s)", __DATE__, __TIME__);
if (smartdns_init_ssl() != 0) { if (_smartdns_init_ssl() != 0) {
tlog(TLOG_ERROR, "init ssl failed."); tlog(TLOG_ERROR, "init ssl failed.");
goto errout; goto errout;
} }
if (dns_conf_server_num <= 0) { if (dns_conf_server_num <= 0) {
if (smartdns_load_from_resolv() != 0) { if (_smartdns_load_from_resolv() != 0) {
tlog(TLOG_ERROR, "load dns from resolv failed."); tlog(TLOG_ERROR, "load dns from resolv failed.");
goto errout; goto errout;
} }
@@ -289,13 +243,13 @@ int smartdns_init(void)
tlog(TLOG_ERROR, "start dns client failed.\n"); tlog(TLOG_ERROR, "start dns client failed.\n");
goto errout; goto errout;
} }
ret = smartdns_add_servers(); ret = _smartdns_add_servers();
if (ret != 0) { if (ret != 0) {
tlog(TLOG_ERROR, "add servers failed."); tlog(TLOG_ERROR, "add servers failed.");
goto errout; goto errout;
} }
ret = smartdns_set_ecs_ip(); ret = _smartdns_set_ecs_ip();
if (ret != 0) { if (ret != 0) {
tlog(TLOG_WARN, "set ecs ip address failed."); tlog(TLOG_WARN, "set ecs ip address failed.");
} }
@@ -306,57 +260,57 @@ errout:
return -1; return -1;
} }
int smartdns_run(void) static int _smartdns_run(void)
{ {
return dns_server_run(); return dns_server_run();
} }
void smartdns_exit(void) static void _smartdns_exit(void)
{ {
dns_server_exit(); dns_server_exit();
dns_client_exit(); dns_client_exit();
fast_ping_exit(); fast_ping_exit();
smartdns_destroy_ssl(); _smartdns_destroy_ssl();
tlog_exit(); tlog_exit();
dns_server_load_exit(); dns_server_load_exit();
} }
void sig_exit(int signo) static void _sig_exit(int signo)
{ {
dns_server_stop(); dns_server_stop();
} }
void sig_error_exit(int signo, siginfo_t *siginfo, void *ct) static void _sig_error_exit(int signo, siginfo_t *siginfo, void *ct)
{ {
unsigned long PC = 0; unsigned long PC = 0;
ucontext_t *context = ct; ucontext_t *context = ct;
#if defined(__i386__) #if defined(__i386__)
int *pgregs = (int*)(&(context->uc_mcontext.gregs)); int *pgregs = (int *)(&(context->uc_mcontext.gregs));
PC = pgregs[REG_EIP]; PC = pgregs[REG_EIP];
#elif defined(__x86_64__) #elif defined(__x86_64__)
int *pgregs = (int*)(&(context->uc_mcontext.gregs)); int *pgregs = (int *)(&(context->uc_mcontext.gregs));
PC = pgregs[REG_RIP]; PC = pgregs[REG_RIP];
#elif defined(__aarch64__) || defined(__arm__) #elif defined(__aarch64__) || defined(__arm__)
PC = context->uc_mcontext.arm_pc; PC = context->uc_mcontext.arm_pc;
#elif defined(__mips__) #elif defined(__mips__)
PC = context->uc_mcontext.pc; PC = context->uc_mcontext.pc;
#endif #endif
tlog(TLOG_ERROR, "process exit with signal %d, code = %d, errno = %d, pid = %d, self = %d, pc = %#lx, addr = %#lx, build(%s %s)\n", signo, siginfo->si_code, siginfo->si_errno, tlog(TLOG_ERROR, "process exit with signal %d, code = %d, errno = %d, pid = %d, self = %d, pc = %#lx, addr = %#lx, build(%s %s)\n", signo, siginfo->si_code,
siginfo->si_pid, getpid(), PC, (unsigned long)siginfo->si_addr, __DATE__, __TIME__); siginfo->si_errno, siginfo->si_pid, getpid(), PC, (unsigned long)siginfo->si_addr, __DATE__, __TIME__);
sleep(1); sleep(1);
_exit(0); _exit(0);
} }
int sig_list[] = {SIGSEGV, SIGABRT, SIGBUS, SIGILL, SIGFPE}; static int sig_list[] = {SIGSEGV, SIGABRT, SIGBUS, SIGILL, SIGFPE};
int sig_num = sizeof(sig_list) / sizeof(int); static int sig_num = sizeof(sig_list) / sizeof(int);
void reg_signal(void) static void _reg_signal(void)
{ {
struct sigaction act, old; struct sigaction act, old;
int i = 0; int i = 0;
act.sa_sigaction = sig_error_exit; act.sa_sigaction = _sig_error_exit;
sigemptyset(&act.sa_mask); sigemptyset(&act.sa_mask);
act.sa_flags = SA_RESTART | SA_SIGINFO; act.sa_flags = SA_RESTART | SA_SIGINFO;
@@ -395,7 +349,7 @@ int main(int argc, char *argv[])
verbose_screen = 1; verbose_screen = 1;
break; break;
case 'h': case 'h':
help(); _help();
return 1; return 1;
} }
} }
@@ -408,7 +362,7 @@ int main(int argc, char *argv[])
} }
if (signal_ignore == 0) { if (signal_ignore == 0) {
reg_signal(); _reg_signal();
} }
if (dns_server_load_conf(config_file) != 0) { if (dns_server_load_conf(config_file) != 0) {
@@ -420,17 +374,17 @@ int main(int argc, char *argv[])
goto errout; goto errout;
} }
ret = smartdns_init(); ret = _smartdns_init();
if (ret != 0) { if (ret != 0) {
usleep(100000); usleep(100000);
goto errout; goto errout;
} }
signal(SIGINT, sig_exit); signal(SIGINT, _sig_exit);
signal(SIGPIPE, SIG_IGN); signal(SIGPIPE, SIG_IGN);
atexit(smartdns_exit); atexit(_smartdns_exit);
return smartdns_run(); return _smartdns_run();
errout: errout:

View File

@@ -97,10 +97,10 @@ struct tlog_info_inter {
typedef int (*list_callback)(const char *name, struct dirent *entry, void *user); typedef int (*list_callback)(const char *name, struct dirent *entry, void *user);
typedef int (*vprint_callback)(char *buff, int maxlen, void *userptr, const char *format, va_list ap); typedef int (*vprint_callback)(char *buff, int maxlen, void *userptr, const char *format, va_list ap);
struct tlog tlog; static struct tlog tlog;
static int tlog_disable_early_print = 0; static int tlog_disable_early_print = 0;
static tlog_level tlog_set_level = TLOG_INFO; static tlog_level tlog_set_level = TLOG_INFO;
tlog_format_func tlog_format; static tlog_format_func tlog_format;
static unsigned int tlog_localtime_lock = 0; static unsigned int tlog_localtime_lock = 0;
static const char *tlog_level_str[] = { static const char *tlog_level_str[] = {
@@ -332,7 +332,7 @@ static int _tlog_print_buffer(char *buff, int maxlen, void *userptr, const char
return total_len; return total_len;
} }
int _tlog_vprintf(struct tlog_log *log, vprint_callback print_callback, void *userptr, const char *format, va_list ap) static int _tlog_vprintf(struct tlog_log *log, vprint_callback print_callback, void *userptr, const char *format, va_list ap)
{ {
int len; int len;
int maxlen = 0; int maxlen = 0;
@@ -406,7 +406,7 @@ int _tlog_vprintf(struct tlog_log *log, vprint_callback print_callback, void *us
int tlog_vprintf(struct tlog_log *log, const char *format, va_list ap) int tlog_vprintf(struct tlog_log *log, const char *format, va_list ap)
{ {
return _tlog_vprintf(log, _tlog_print_buffer, 0, format, ap); return _tlog_vprintf(log, _tlog_print_buffer, NULL, format, ap);
} }
int tlog_printf(struct tlog_log *log, const char *format, ...) int tlog_printf(struct tlog_log *log, const char *format, ...)
@@ -421,7 +421,7 @@ int tlog_printf(struct tlog_log *log, const char *format, ...)
return len; return len;
} }
int _tlog_early_print(const char *format, va_list ap) static int _tlog_early_print(const char *format, va_list ap)
{ {
char log_buf[TLOG_MAX_LINE_LEN]; char log_buf[TLOG_MAX_LINE_LEN];
int len = 0; int len = 0;
@@ -901,7 +901,7 @@ static int _tlog_write_log(struct tlog_log *log, char *buff, int bufflen)
return len; return len;
} }
int _tlog_has_data(void) static int _tlog_has_data(void)
{ {
struct tlog_log *next = NULL; struct tlog_log *next = NULL;
@@ -919,7 +919,7 @@ int _tlog_has_data(void)
return 0; return 0;
} }
int _tlog_wait_pids(void) static int _tlog_wait_pids(void)
{ {
static time_t last = -1; static time_t last = -1;
time_t now = 0; time_t now = 0;
@@ -931,7 +931,7 @@ int _tlog_wait_pids(void)
while (next) { while (next) {
if (next->zip_pid > 0) { if (next->zip_pid > 0) {
if (now == 0) { if (now == 0) {
now = time(0); now = time(NULL);
} }
if (now != last) { if (now != last) {
@@ -953,7 +953,7 @@ int _tlog_wait_pids(void)
return 0; return 0;
} }
int _tlog_close(struct tlog_log *log, int wait_hang) static int _tlog_close(struct tlog_log *log, int wait_hang)
{ {
struct tlog_log *next = tlog.log; struct tlog_log *next = tlog.log;
@@ -1126,7 +1126,7 @@ void tlog_set_early_printf(int enable)
tlog_disable_early_print = (enable == 0) ? 1 : 0; tlog_disable_early_print = (enable == 0) ? 1 : 0;
} }
void _tlog_log_setlogscreen(struct tlog_log *log, int enable) static void _tlog_log_setlogscreen(struct tlog_log *log, int enable)
{ {
if (log == NULL) { if (log == NULL) {
return; return;
@@ -1260,9 +1260,9 @@ int tlog_init(const char *logfile, int maxlogsize, int maxlogcount, int block, i
tlog.is_wait = 0; tlog.is_wait = 0;
pthread_attr_init(&attr); pthread_attr_init(&attr);
pthread_mutex_init(&tlog.lock, 0); pthread_mutex_init(&tlog.lock, NULL);
pthread_cond_init(&tlog.cond, 0); pthread_cond_init(&tlog.cond, NULL);
pthread_cond_init(&tlog.client_cond, 0); pthread_cond_init(&tlog.client_cond, NULL);
tlog.run = 1; tlog.run = 1;
log = tlog_open(logfile, maxlogsize, maxlogcount, block, buffsize, multiwrite); log = tlog_open(logfile, maxlogsize, maxlogcount, block, buffsize, multiwrite);

View File

@@ -48,7 +48,7 @@ format: Log formats
#ifndef BASE_FILE_NAME #ifndef BASE_FILE_NAME
#define BASE_FILE_NAME __FILE__ #define BASE_FILE_NAME __FILE__
#endif #endif
#define tlog(level, format, ...) tlog_ext(level, BASE_FILE_NAME, __LINE__, __func__, 0, format, ##__VA_ARGS__) #define tlog(level, format, ...) tlog_ext(level, BASE_FILE_NAME, __LINE__, __func__, NULL, format, ##__VA_ARGS__)
extern int tlog_ext(tlog_level level, const char *file, int line, const char *func, void *userptr, const char *format, ...) extern int tlog_ext(tlog_level level, const char *file, int line, const char *func, void *userptr, const char *format, ...)
__attribute__((format(printf, 6, 7))); __attribute__((format(printf, 6, 7)));

View File

@@ -1,16 +1,23 @@
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include "util.h" #include "util.h"
#include "dns_conf.h" #include "dns_conf.h"
#include <arpa/inet.h> #include <arpa/inet.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <linux/netlink.h> #include <linux/netlink.h>
#include <openssl/crypto.h>
#include <openssl/ssl.h>
#include <pthread.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
#include <openssl/crypto.h> #include <sys/types.h>
#include <openssl/ssl.h> #include <sys/stat.h>
#include <pthread.h>
#define TMP_BUFF_LEN_32 32
#define NFNL_SUBSYS_IPSET 6 #define NFNL_SUBSYS_IPSET 6
@@ -248,12 +255,12 @@ static int _ipset_socket_init(void)
return 0; return 0;
} }
static int _ipset_support_timeout(const char *ipsetname) static int _ipset_support_timeout(const char *ipsetname)
{ {
if (dns_conf_ipset_timeout_enable) { if (dns_conf_ipset_timeout_enable) {
return 0; return 0;
} }
return -1; return -1;
} }
@@ -369,82 +376,126 @@ unsigned char *SSL_SHA256(const unsigned char *d, size_t n, unsigned char *md)
int SSL_base64_decode(const char *in, unsigned char *out) int SSL_base64_decode(const char *in, unsigned char *out)
{ {
size_t inlen = strlen(in); size_t inlen = strlen(in);
int outlen; int outlen;
if (inlen == 0) { if (inlen == 0) {
return 0; return 0;
} }
outlen = EVP_DecodeBlock(out, (unsigned char *)in, inlen); outlen = EVP_DecodeBlock(out, (unsigned char *)in, inlen);
if (outlen < 0) { if (outlen < 0) {
goto errout; goto errout;
} }
/* Subtract padding bytes from |outlen| */ /* Subtract padding bytes from |outlen| */
while (in[--inlen] == '=') { while (in[--inlen] == '=') {
--outlen; --outlen;
} }
return outlen; return outlen;
errout: errout:
return -1; return -1;
} }
#define THREAD_STACK_SIZE (16*1024) int create_pid_file(const char *pid_file)
{
int fd;
int flags;
char buff[TMP_BUFF_LEN_32];
/* create pid file, and lock this file */
fd = open(pid_file, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
if (fd == -1) {
fprintf(stderr, "create pid file failed, %s\n", strerror(errno));
return -1;
}
flags = fcntl(fd, F_GETFD);
if (flags < 0) {
fprintf(stderr, "Could not get flags for PID file %s\n", pid_file);
goto errout;
}
flags |= FD_CLOEXEC;
if (fcntl(fd, F_SETFD, flags) == -1) {
fprintf(stderr, "Could not set flags for PID file %s\n", pid_file);
goto errout;
}
if (lockf(fd, F_TLOCK, 0) < 0) {
fprintf(stderr, "Server is already running.\n");
goto errout;
}
snprintf(buff, TMP_BUFF_LEN_32, "%d\n", getpid());
if (write(fd, buff, strnlen(buff, TMP_BUFF_LEN_32)) < 0) {
fprintf(stderr, "write pid to file failed, %s.\n", strerror(errno));
goto errout;
}
return 0;
errout:
if (fd > 0) {
close(fd);
}
return -1;
}
#define THREAD_STACK_SIZE (16 * 1024)
static pthread_mutex_t *lock_cs; static pthread_mutex_t *lock_cs;
static long *lock_count; static long *lock_count;
void pthreads_locking_callback(int mode, int type, const char *file, int line) static __attribute__((unused)) void _pthreads_locking_callback(int mode, int type, const char *file, int line)
{ {
if (mode & CRYPTO_LOCK) { if (mode & CRYPTO_LOCK) {
pthread_mutex_lock(&(lock_cs[type])); pthread_mutex_lock(&(lock_cs[type]));
lock_count[type]++; lock_count[type]++;
} else { } else {
pthread_mutex_unlock(&(lock_cs[type])); pthread_mutex_unlock(&(lock_cs[type]));
} }
} }
unsigned long pthreads_thread_id(void) static __attribute__((unused)) unsigned long _pthreads_thread_id(void)
{ {
unsigned long ret; unsigned long ret;
ret = (unsigned long)pthread_self(); ret = (unsigned long)pthread_self();
return (ret); return (ret);
} }
void SSL_CRYPTO_thread_setup(void) void SSL_CRYPTO_thread_setup(void)
{ {
int i; int i;
lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t)); lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t));
lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(long)); lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(long));
if (!lock_cs || !lock_count) { if (!lock_cs || !lock_count) {
/* Nothing we can do about this...void function! */ /* Nothing we can do about this...void function! */
if (lock_cs) if (lock_cs)
OPENSSL_free(lock_cs); OPENSSL_free(lock_cs);
if (lock_count) if (lock_count)
OPENSSL_free(lock_count); OPENSSL_free(lock_count);
return; return;
} }
for (i = 0; i < CRYPTO_num_locks(); i++) { for (i = 0; i < CRYPTO_num_locks(); i++) {
lock_count[i] = 0; lock_count[i] = 0;
pthread_mutex_init(&(lock_cs[i]), NULL); pthread_mutex_init(&(lock_cs[i]), NULL);
} }
CRYPTO_set_id_callback(pthreads_thread_id); CRYPTO_set_id_callback(_pthreads_thread_id);
CRYPTO_set_locking_callback(pthreads_locking_callback); CRYPTO_set_locking_callback(_pthreads_locking_callback);
} }
void SSL_CRYPTO_thread_cleanup(void) void SSL_CRYPTO_thread_cleanup(void)
{ {
int i; int i;
CRYPTO_set_locking_callback(NULL); CRYPTO_set_locking_callback(NULL);
for (i = 0; i < CRYPTO_num_locks(); i++) { for (i = 0; i < CRYPTO_num_locks(); i++) {
pthread_mutex_destroy(&(lock_cs[i])); pthread_mutex_destroy(&(lock_cs[i]));
} }
OPENSSL_free(lock_cs); OPENSSL_free(lock_cs);
OPENSSL_free(lock_count); OPENSSL_free(lock_count);
} }

View File

@@ -34,4 +34,6 @@ unsigned char *SSL_SHA256(const unsigned char *d, size_t n, unsigned char *md);
int SSL_base64_decode(const char *in, unsigned char *out); int SSL_base64_decode(const char *in, unsigned char *out);
#endif int create_pid_file(const char *pid_file);
#endif