Bugfix
This commit is contained in:
14
src/conf.c
14
src/conf.c
@@ -72,11 +72,13 @@ void config_address_destroy(void)
|
|||||||
int config_address(char *value)
|
int config_address(char *value)
|
||||||
{
|
{
|
||||||
struct dns_address *address = NULL;
|
struct dns_address *address = NULL;
|
||||||
|
struct dns_address *oldaddress;
|
||||||
char ip[MAX_IP_LEN];
|
char ip[MAX_IP_LEN];
|
||||||
char domain_key[DNS_MAX_CONF_CNAME_LEN];
|
char domain_key[DNS_MAX_CONF_CNAME_LEN];
|
||||||
char *begin = NULL;
|
char *begin = NULL;
|
||||||
char *end = NULL;
|
char *end = NULL;
|
||||||
int len = 0;
|
int len = 0;
|
||||||
|
int port;
|
||||||
struct sockaddr_storage addr;
|
struct sockaddr_storage addr;
|
||||||
socklen_t addr_len = sizeof(addr);
|
socklen_t addr_len = sizeof(addr);
|
||||||
char type = '4';
|
char type = '4';
|
||||||
@@ -101,9 +103,12 @@ int config_address(char *value)
|
|||||||
len = end - begin;
|
len = end - begin;
|
||||||
memcpy(address->domain, begin, len);
|
memcpy(address->domain, begin, len);
|
||||||
address->domain[len] = 0;
|
address->domain[len] = 0;
|
||||||
strncpy(ip, end + 1, MAX_IP_LEN);
|
|
||||||
reverse_string(domain_key + 1, address->domain, len);
|
reverse_string(domain_key + 1, address->domain, len);
|
||||||
|
|
||||||
|
if (parse_ip(end + 1, ip, &port) != 0) {
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
if (getaddr_by_host(ip, (struct sockaddr *)&addr, &addr_len) != 0) {
|
if (getaddr_by_host(ip, (struct sockaddr *)&addr, &addr_len) != 0) {
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
@@ -135,7 +140,10 @@ int config_address(char *value)
|
|||||||
|
|
||||||
domain_key[0] = type;
|
domain_key[0] = type;
|
||||||
len++;
|
len++;
|
||||||
art_insert(&dns_conf_address, (unsigned char *)domain_key, len, address);
|
oldaddress = art_insert(&dns_conf_address, (unsigned char *)domain_key, len, address);
|
||||||
|
if (oldaddress) {
|
||||||
|
free(oldaddress);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
errout:
|
errout:
|
||||||
@@ -277,4 +285,4 @@ errout:
|
|||||||
fclose(fp);
|
fclose(fp);
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|||||||
251
src/dns.c
251
src/dns.c
@@ -412,6 +412,95 @@ 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)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
|
||||||
|
int maxlen = 0;
|
||||||
|
int len = 0;
|
||||||
|
struct dns_data_context data_context;
|
||||||
|
int total_len = sizeof(*opt) + opt->length;
|
||||||
|
int ttl = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||||
|
0: | OPTION-CODE |
|
||||||
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||||
|
2: | OPTION-LENGTH |
|
||||||
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||||
|
4: | |
|
||||||
|
/ OPTION-DATA /
|
||||||
|
/ /
|
||||||
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||||
|
*/
|
||||||
|
unsigned char *data = _dns_add_rrs_start(packet, &maxlen);
|
||||||
|
if (data == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (total_len > maxlen) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
data_context.data = data;
|
||||||
|
data_context.ptr = data;
|
||||||
|
data_context.maxsize = maxlen;
|
||||||
|
|
||||||
|
ttl = (opt_code << 16) | opt_len;
|
||||||
|
|
||||||
|
/* add rr head */
|
||||||
|
len = _dns_add_rr_head(&data_context, "", type, DNS_C_IN, ttl, total_len);
|
||||||
|
if (len < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add rr data */
|
||||||
|
memcpy(data_context.ptr, opt, total_len);
|
||||||
|
data_context.ptr += total_len;
|
||||||
|
len = data_context.ptr - data_context.data;
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
|
||||||
|
int qtype = 0;
|
||||||
|
int qclass = 0;
|
||||||
|
int rr_len = 0;
|
||||||
|
int ret = 0;
|
||||||
|
struct dns_data_context data_context;
|
||||||
|
char domain[DNS_MAX_CNAME_LEN];
|
||||||
|
int maxsize = DNS_MAX_CNAME_LEN;
|
||||||
|
int ttl = 0;
|
||||||
|
unsigned char *data = rrs->data;
|
||||||
|
|
||||||
|
data_context.data = data;
|
||||||
|
data_context.ptr = data;
|
||||||
|
data_context.maxsize = rrs->len;
|
||||||
|
|
||||||
|
/* get rr head */
|
||||||
|
ret = _dns_get_rr_head(&data_context, domain, maxsize, &qtype, &qclass, &ttl, &rr_len);
|
||||||
|
if (ret < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (qtype != rrs->type || rr_len > *opt_len) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get rr data */
|
||||||
|
*opt_code = ttl >> 16;
|
||||||
|
*opt_len = ttl & 0xFFFF;
|
||||||
|
memcpy(opt, data_context.ptr, rr_len);
|
||||||
|
data_context.ptr += rr_len;
|
||||||
|
*opt_maxlen = rr_len;
|
||||||
|
|
||||||
|
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;
|
||||||
@@ -546,6 +635,47 @@ int dns_get_SOA(struct dns_rrs *rrs, char *domain, int maxsize, int *ttl, struct
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int dns_add_OPT_ECS(struct dns_packet *packet, dns_rr_type type, struct dns_opt_ecs *ecs)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
|
||||||
|
unsigned char opt_data[DNS_MAX_OPT_LEN];
|
||||||
|
struct dns_opt *opt = (struct dns_opt *)opt_data;
|
||||||
|
int len = 0;
|
||||||
|
|
||||||
|
opt->code = DNS_OPT_T_ECS;
|
||||||
|
opt->length = sizeof(*ecs);
|
||||||
|
memcpy(opt->data, ecs, sizeof(*ecs));
|
||||||
|
|
||||||
|
/* ecs size 4 + bit of address*/
|
||||||
|
len = sizeof(*opt) + 4;
|
||||||
|
len += (ecs->source_prefix / 8);
|
||||||
|
len += (ecs->source_prefix % 8 > 0) ? 1 : 0;
|
||||||
|
|
||||||
|
return dns_add_OPT(packet, type, DNS_OPT_T_ECS, len, opt);
|
||||||
|
}
|
||||||
|
|
||||||
|
int dns_get_OPT_ECS(struct dns_rrs *rrs, unsigned short *opt_code, unsigned short *opt_len, struct dns_opt_ecs *ecs)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
|
||||||
|
unsigned char opt_data[DNS_MAX_OPT_LEN];
|
||||||
|
struct dns_opt *opt = (struct dns_opt *)opt_data;
|
||||||
|
int len = sizeof(opt_data);
|
||||||
|
|
||||||
|
if (dns_get_OPT(rrs, opt_code, opt_len, opt, &len) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opt->code != DNS_OPT_T_ECS) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(ecs, opt->data, opt->length);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Format:
|
* Format:
|
||||||
* |DNS_NAME\0(string)|qtype(short)|qclass(short)|
|
* |DNS_NAME\0(string)|qtype(short)|qclass(short)|
|
||||||
@@ -1074,6 +1204,108 @@ int _dns_encode_SOA(struct dns_context *context, struct dns_rrs *rrs)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int _dns_decode_opt_ecs(struct dns_context *context, struct dns_opt_ecs *ecs)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
|
||||||
|
int len = 0;
|
||||||
|
if (_dns_left_len(context) < 4) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ecs->family = dns_read_short(&context->ptr);
|
||||||
|
ecs->source_prefix = dns_read_char(&context->ptr);
|
||||||
|
ecs->scope_prefix = dns_read_char(&context->ptr);
|
||||||
|
len = (ecs->source_prefix / 8);
|
||||||
|
len += (ecs->source_prefix % 8 > 0) ? 1 : 0;
|
||||||
|
|
||||||
|
if (_dns_left_len(context) < len) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(ecs->addr, context->ptr, len);
|
||||||
|
context->ptr += len;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _dns_encode_OPT(struct dns_context *context, struct dns_rrs *rrs)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _dns_decode_opt(struct dns_context *context, dns_rr_type type, unsigned int ttl, int rr_len)
|
||||||
|
{
|
||||||
|
unsigned short opt_code;
|
||||||
|
unsigned short opt_len;
|
||||||
|
unsigned short ercode = (ttl >> 16) & 0xFFFF;
|
||||||
|
unsigned short ever = (ttl) & 0xFFFF;
|
||||||
|
unsigned char *start = context->ptr;
|
||||||
|
struct dns_packet *packet = context->packet;
|
||||||
|
int ret = 0;
|
||||||
|
/*
|
||||||
|
Field Name Field Type Description
|
||||||
|
------------------------------------------------------
|
||||||
|
NAME domain name empty (root domain)
|
||||||
|
TYPE u_int16_t OPT
|
||||||
|
CLASS u_int16_t sender's UDP payload size
|
||||||
|
TTL u_int32_t extended RCODE and flags
|
||||||
|
RDLEN u_int16_t describes RDATA
|
||||||
|
RDATA octet stream {attribute,value} pairs
|
||||||
|
|
||||||
|
+0 (MSB) +1 (LSB)
|
||||||
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||||
|
0: | OPTION-CODE |
|
||||||
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||||
|
2: | OPTION-LENGTH |
|
||||||
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||||
|
4: | |
|
||||||
|
/ OPTION-DATA /
|
||||||
|
/ /
|
||||||
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||||
|
|
||||||
|
TTL
|
||||||
|
+0 (MSB) +1 (LSB)
|
||||||
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||||
|
0: | EXTENDED-RCODE | VERSION |
|
||||||
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||||
|
2: | Z |
|
||||||
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (ercode != 0) {
|
||||||
|
tlog(TLOG_ERROR, "extend rcode invalid.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ever = ever;
|
||||||
|
|
||||||
|
while (context->ptr - start < rr_len) {
|
||||||
|
opt_code = dns_read_short(&context->ptr);
|
||||||
|
opt_len = dns_read_short(&context->ptr);
|
||||||
|
switch (opt_code) {
|
||||||
|
case DNS_OPT_T_ECS: {
|
||||||
|
struct dns_opt_ecs ecs;
|
||||||
|
ret = _dns_decode_opt_ecs(context, &ecs);
|
||||||
|
if (ret != 0 ) {
|
||||||
|
tlog(TLOG_ERROR, "decode ecs failed.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = dns_add_OPT_ECS(packet, type, &ecs);
|
||||||
|
} break;
|
||||||
|
default:
|
||||||
|
context->ptr += opt_len;
|
||||||
|
tlog(TLOG_DEBUG, "DNS opt type = %d not supported", opt_code);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int _dns_decode_qd(struct dns_context *context)
|
static int _dns_decode_qd(struct dns_context *context)
|
||||||
{
|
{
|
||||||
struct dns_packet *packet = context->packet;
|
struct dns_packet *packet = context->packet;
|
||||||
@@ -1200,6 +1432,19 @@ static int _dns_decode_an(struct dns_context *context, dns_rr_type type)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
case DNS_T_OPT: {
|
||||||
|
unsigned char *opt_start = context->ptr;
|
||||||
|
ret = _dns_decode_opt(context, type, ttl, rr_len);
|
||||||
|
if (ret < 0) {
|
||||||
|
tlog(TLOG_ERROR, "decode opt failed, %s", domain);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context->ptr - opt_start != rr_len) {
|
||||||
|
tlog(TLOG_ERROR, "opt length mitchmatch, %s\n", domain);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
default:
|
default:
|
||||||
context->ptr += rr_len;
|
context->ptr += rr_len;
|
||||||
tlog(TLOG_DEBUG, "DNS type = %d not supported", qtype);
|
tlog(TLOG_DEBUG, "DNS type = %d not supported", qtype);
|
||||||
@@ -1263,6 +1508,12 @@ static int _dns_encode_an(struct dns_context *context, struct dns_rrs *rrs)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case DNS_T_OPT:
|
||||||
|
ret = _dns_encode_OPT(context, rrs);
|
||||||
|
if (ret < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
31
src/dns.h
31
src/dns.h
@@ -9,6 +9,7 @@
|
|||||||
#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
|
||||||
|
#define DNS_MAX_OPT_LEN 256
|
||||||
#define DNS_IN_PACKSIZE (512 * 4)
|
#define DNS_IN_PACKSIZE (512 * 4)
|
||||||
#define DNS_PACKSIZE (512 * 8)
|
#define DNS_PACKSIZE (512 * 8)
|
||||||
|
|
||||||
@@ -44,6 +45,11 @@ typedef enum dns_type {
|
|||||||
DNS_T_ALL = 255
|
DNS_T_ALL = 255
|
||||||
} dns_type_t;
|
} dns_type_t;
|
||||||
|
|
||||||
|
typedef enum dns_opt_code {
|
||||||
|
DNS_OPT_T_ECS = 8,
|
||||||
|
DNS_OPT_T_ALL = 255
|
||||||
|
} dns_opt_code_t;
|
||||||
|
|
||||||
typedef enum dns_opcode {
|
typedef enum dns_opcode {
|
||||||
DNS_OP_QUERY = 0,
|
DNS_OP_QUERY = 0,
|
||||||
DNS_OP_IQUERY = 1,
|
DNS_OP_IQUERY = 1,
|
||||||
@@ -128,7 +134,24 @@ struct dns_soa {
|
|||||||
unsigned int expire;
|
unsigned int expire;
|
||||||
unsigned int minimum;
|
unsigned int minimum;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
;
|
|
||||||
|
#define DNS_OPT_ECS_FAMILY_IPV4 1
|
||||||
|
#define DNS_OPT_ECS_FAMILY_IPV6 2
|
||||||
|
|
||||||
|
/* OPT ECS */
|
||||||
|
struct dns_opt_ecs {
|
||||||
|
unsigned short family;
|
||||||
|
unsigned char source_prefix;
|
||||||
|
unsigned char scope_prefix;
|
||||||
|
unsigned char addr[DNS_RR_AAAA_LEN];
|
||||||
|
};
|
||||||
|
|
||||||
|
/* OPT */
|
||||||
|
struct dns_opt {
|
||||||
|
unsigned short code;
|
||||||
|
unsigned short length;
|
||||||
|
unsigned char data[0];
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
struct dns_rrs *dns_get_rrs_next(struct dns_packet *packet, struct dns_rrs *rrs);
|
struct dns_rrs *dns_get_rrs_next(struct dns_packet *packet, struct dns_rrs *rrs);
|
||||||
struct dns_rrs *dns_get_rrs_start(struct dns_packet *packet, dns_rr_type type, int *count);
|
struct dns_rrs *dns_get_rrs_start(struct dns_packet *packet, dns_rr_type type, int *count);
|
||||||
@@ -156,6 +179,12 @@ 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_OPT(struct dns_packet *packet, dns_rr_type type, unsigned short opt_code, unsigned short opt_len, struct dns_opt *opt);
|
||||||
|
int dns_get_OPT(struct dns_rrs *rrs, unsigned short *opt_code, unsigned short *opt_len, struct dns_opt *opt, int *opt_maxlen);
|
||||||
|
|
||||||
|
int dns_add_OPT_ECS(struct dns_packet *packet, dns_rr_type type, 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);
|
||||||
/*
|
/*
|
||||||
* Packet operation
|
* Packet operation
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -49,6 +49,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#define DNS_MAX_EVENTS 256
|
#define DNS_MAX_EVENTS 256
|
||||||
|
#define DNS_SERVER_TMOUT_TTL (3 * 60)
|
||||||
|
|
||||||
/* dns server data */
|
/* dns server data */
|
||||||
struct dns_server {
|
struct dns_server {
|
||||||
@@ -268,11 +269,25 @@ int _dns_server_request_complete(struct dns_request *request)
|
|||||||
if (request->qtype == DNS_T_A) {
|
if (request->qtype == DNS_T_A) {
|
||||||
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_ipv4) {
|
||||||
|
if (request->has_ping_result == 0 && request->ttl_v4 > DNS_SERVER_TMOUT_TTL) {
|
||||||
|
request->ttl_v4 = DNS_SERVER_TMOUT_TTL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dns_cache_insert(request->domain, request->ttl_v4, DNS_T_A, request->ipv4_addr, DNS_RR_A_LEN);
|
||||||
} else if (request->qtype == DNS_T_AAAA) {
|
} else if (request->qtype == DNS_T_AAAA) {
|
||||||
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_ipv6) {
|
||||||
|
if (request->has_ping_result == 0 && request->ttl_v6 > DNS_SERVER_TMOUT_TTL) {
|
||||||
|
request->ttl_v6 = DNS_SERVER_TMOUT_TTL;
|
||||||
|
}
|
||||||
|
dns_cache_insert(request->domain, request->ttl_v6, DNS_T_AAAA, request->ipv6_addr, DNS_RR_AAAA_LEN);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_dns_reply(request);
|
_dns_reply(request);
|
||||||
@@ -333,7 +348,6 @@ void _dns_server_ping_result(struct ping_host_struct *ping_host, const char *hos
|
|||||||
{
|
{
|
||||||
struct dns_request *request = userptr;
|
struct dns_request *request = userptr;
|
||||||
int may_complete = 0;
|
int may_complete = 0;
|
||||||
int addr_type = 0;
|
|
||||||
|
|
||||||
if (request == NULL) {
|
if (request == NULL) {
|
||||||
return;
|
return;
|
||||||
@@ -355,7 +369,6 @@ void _dns_server_ping_result(struct ping_host_struct *ping_host, const char *hos
|
|||||||
request->ping_ttl_v4 = rtt;
|
request->ping_ttl_v4 = rtt;
|
||||||
request->has_ipv4 = 1;
|
request->has_ipv4 = 1;
|
||||||
memcpy(request->ipv4_addr, &addr_in->sin_addr.s_addr, 4);
|
memcpy(request->ipv4_addr, &addr_in->sin_addr.s_addr, 4);
|
||||||
addr_type = 4;
|
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case AF_INET6: {
|
case AF_INET6: {
|
||||||
@@ -366,14 +379,12 @@ void _dns_server_ping_result(struct ping_host_struct *ping_host, const char *hos
|
|||||||
request->ping_ttl_v4 = rtt;
|
request->ping_ttl_v4 = rtt;
|
||||||
request->has_ipv4 = 1;
|
request->has_ipv4 = 1;
|
||||||
memcpy(request->ipv4_addr, addr_in6->sin6_addr.s6_addr + 12, 4);
|
memcpy(request->ipv4_addr, addr_in6->sin6_addr.s6_addr + 12, 4);
|
||||||
addr_type = 4;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (request->ping_ttl_v6 > rtt) {
|
if (request->ping_ttl_v6 > rtt) {
|
||||||
request->ping_ttl_v6 = rtt;
|
request->ping_ttl_v6 = rtt;
|
||||||
request->has_ipv6 = 1;
|
request->has_ipv6 = 1;
|
||||||
memcpy(request->ipv6_addr, addr_in6->sin6_addr.s6_addr, 16);
|
memcpy(request->ipv6_addr, addr_in6->sin6_addr.s6_addr, 16);
|
||||||
addr_type = 6;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
@@ -396,11 +407,6 @@ void _dns_server_ping_result(struct ping_host_struct *ping_host, const char *hos
|
|||||||
if (may_complete) {
|
if (may_complete) {
|
||||||
_dns_server_request_complete(request);
|
_dns_server_request_complete(request);
|
||||||
_dns_server_request_remove(request);
|
_dns_server_request_remove(request);
|
||||||
if (addr_type == 4) {
|
|
||||||
dns_cache_insert(request->domain, request->ttl_v4, DNS_T_A, request->ipv4_addr, DNS_RR_A_LEN);
|
|
||||||
} else if (addr_type == 6) {
|
|
||||||
dns_cache_insert(request->domain, request->ttl_v6, DNS_T_AAAA, request->ipv6_addr, DNS_RR_AAAA_LEN);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -508,6 +514,10 @@ static int _dns_server_process_answer(struct dns_request *request, char *domain,
|
|||||||
memcpy(request->ipv4_addr, addr, DNS_RR_A_LEN);
|
memcpy(request->ipv4_addr, addr, DNS_RR_A_LEN);
|
||||||
request->ttl_v4 = ttl;
|
request->ttl_v4 = ttl;
|
||||||
request->has_ipv4 = 1;
|
request->has_ipv4 = 1;
|
||||||
|
} else {
|
||||||
|
if (ttl < request->ttl_v4) {
|
||||||
|
request->ttl_v4 = ttl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
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);
|
||||||
@@ -539,6 +549,10 @@ static int _dns_server_process_answer(struct dns_request *request, char *domain,
|
|||||||
memcpy(request->ipv6_addr, addr, DNS_RR_AAAA_LEN);
|
memcpy(request->ipv6_addr, addr, DNS_RR_AAAA_LEN);
|
||||||
request->ttl_v6 = ttl;
|
request->ttl_v6 = ttl;
|
||||||
request->has_ipv6 = 1;
|
request->has_ipv6 = 1;
|
||||||
|
} else {
|
||||||
|
if (ttl < request->ttl_v6) {
|
||||||
|
request->ttl_v6 = ttl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_dns_ip_address_check_add(request, addr, DNS_T_AAAA) != 0) {
|
if (_dns_ip_address_check_add(request, addr, DNS_T_AAAA) != 0) {
|
||||||
@@ -546,7 +560,7 @@ static int _dns_server_process_answer(struct dns_request *request, char *domain,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
sprintf(name, "%.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]);
|
||||||
|
|
||||||
if (_dns_server_ping(request, ip) != 0) {
|
if (_dns_server_ping(request, ip) != 0) {
|
||||||
@@ -702,7 +716,7 @@ static struct dns_address *_dns_server_get_address_by_domain(char *domain, int q
|
|||||||
domain_key[0] = type;
|
domain_key[0] = type;
|
||||||
domain_len++;
|
domain_len++;
|
||||||
|
|
||||||
return art_substring(&dns_conf_address, (unsigned char *)domain_key, domain_len);;
|
return art_substring(&dns_conf_address, (unsigned char *)domain_key, domain_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _dns_server_process_address(struct dns_request *request, struct dns_packet *packet)
|
static int _dns_server_process_address(struct dns_request *request, struct dns_packet *packet)
|
||||||
@@ -745,7 +759,7 @@ errout:
|
|||||||
static int _dns_server_process_cache(struct dns_request *request, struct dns_packet *packet)
|
static int _dns_server_process_cache(struct dns_request *request, struct dns_packet *packet)
|
||||||
{
|
{
|
||||||
struct dns_cache *dns_cache = NULL;
|
struct dns_cache *dns_cache = NULL;
|
||||||
|
|
||||||
dns_cache = dns_cache_get(request->domain, request->qtype);
|
dns_cache = dns_cache_get(request->domain, request->qtype);
|
||||||
if (dns_cache == NULL) {
|
if (dns_cache == NULL) {
|
||||||
goto errout;
|
goto errout;
|
||||||
|
|||||||
@@ -170,9 +170,9 @@ static art_node** find_child(art_node *n, unsigned char c) {
|
|||||||
case NODE4:
|
case NODE4:
|
||||||
p.p1 = (art_node4*)n;
|
p.p1 = (art_node4*)n;
|
||||||
for (i=0 ; i < n->num_children; i++) {
|
for (i=0 ; i < n->num_children; i++) {
|
||||||
/* this cast works around a bug in gcc 5.1 when unrolling loops
|
/* this cast works around a bug in gcc 5.1 when unrolling loops
|
||||||
* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59124
|
* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59124
|
||||||
*/
|
*/
|
||||||
if (((unsigned char*)p.p1->keys)[i] == c)
|
if (((unsigned char*)p.p1->keys)[i] == c)
|
||||||
return &p.p1->children[i];
|
return &p.p1->children[i];
|
||||||
}
|
}
|
||||||
@@ -421,8 +421,8 @@ static void add_child48(art_node48 *n, art_node **ref, unsigned char c, void *ch
|
|||||||
n->n.num_children++;
|
n->n.num_children++;
|
||||||
} else {
|
} else {
|
||||||
art_node256 *new_node = (art_node256*)alloc_node(NODE256);
|
art_node256 *new_node = (art_node256*)alloc_node(NODE256);
|
||||||
int i;
|
int i;
|
||||||
for (i=0;i<256;i++) {
|
for (i=0;i<256;i++) {
|
||||||
if (n->keys[i]) {
|
if (n->keys[i]) {
|
||||||
new_node->children[i] = n->children[n->keys[i] - 1];
|
new_node->children[i] = n->children[n->keys[i] - 1];
|
||||||
}
|
}
|
||||||
@@ -461,8 +461,8 @@ static void add_child16(art_node16 *n, art_node **ref, unsigned char c, void *ch
|
|||||||
#else
|
#else
|
||||||
// Compare the key to all 16 stored keys
|
// Compare the key to all 16 stored keys
|
||||||
unsigned bitfield = 0;
|
unsigned bitfield = 0;
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < 16; ++i) {
|
for (i = 0; i < 16; ++i) {
|
||||||
if (c < n->keys[i])
|
if (c < n->keys[i])
|
||||||
bitfield |= (1 << i);
|
bitfield |= (1 << i);
|
||||||
}
|
}
|
||||||
@@ -489,9 +489,9 @@ static void add_child16(art_node16 *n, art_node **ref, unsigned char c, void *ch
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
art_node48 *new_node = (art_node48*)alloc_node(NODE48);
|
art_node48 *new_node = (art_node48*)alloc_node(NODE48);
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
// Copy the child pointers and populate the key map
|
// Copy the child pointers and populate the key map
|
||||||
memcpy(new_node->children, n->children,
|
memcpy(new_node->children, n->children,
|
||||||
sizeof(void*)*n->n.num_children);
|
sizeof(void*)*n->n.num_children);
|
||||||
for (i=0;i<n->n.num_children;i++) {
|
for (i=0;i<n->n.num_children;i++) {
|
||||||
@@ -688,8 +688,8 @@ static void remove_child256(art_node256 *n, art_node **ref, unsigned char c) {
|
|||||||
copy_header((art_node*)new_node, (art_node*)n);
|
copy_header((art_node*)new_node, (art_node*)n);
|
||||||
|
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
int i;
|
int i;
|
||||||
for (i=0;i<256;i++) {
|
for (i=0;i<256;i++) {
|
||||||
if (n->children[i]) {
|
if (n->children[i]) {
|
||||||
new_node->children[pos] = n->children[i];
|
new_node->children[pos] = n->children[i];
|
||||||
new_node->keys[i] = pos + 1;
|
new_node->keys[i] = pos + 1;
|
||||||
@@ -712,8 +712,8 @@ static void remove_child48(art_node48 *n, art_node **ref, unsigned char c) {
|
|||||||
copy_header((art_node*)new_node, (art_node*)n);
|
copy_header((art_node*)new_node, (art_node*)n);
|
||||||
|
|
||||||
int child = 0;
|
int child = 0;
|
||||||
int i;
|
int i;
|
||||||
for (i=0;i<256;i++) {
|
for (i=0;i<256;i++) {
|
||||||
pos = n->keys[i];
|
pos = n->keys[i];
|
||||||
if (pos) {
|
if (pos) {
|
||||||
new_node->keys[child] = i;
|
new_node->keys[child] = i;
|
||||||
@@ -858,8 +858,8 @@ static int recursive_iter(art_node *n, art_callback cb, void *data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int idx, res;
|
int idx, res;
|
||||||
int i;
|
int i;
|
||||||
switch (n->type) {
|
switch (n->type) {
|
||||||
case NODE4:
|
case NODE4:
|
||||||
for (i=0; i < n->num_children; i++) {
|
for (i=0; i < n->num_children; i++) {
|
||||||
res = recursive_iter(((art_node4*)n)->children[i], cb, data);
|
res = recursive_iter(((art_node4*)n)->children[i], cb, data);
|
||||||
@@ -941,12 +941,6 @@ int art_iter_prefix(art_tree *t, const unsigned char *key, int key_len, art_call
|
|||||||
art_node *n = t->root;
|
art_node *n = t->root;
|
||||||
int prefix_len, depth = 0;
|
int prefix_len, depth = 0;
|
||||||
while (n) {
|
while (n) {
|
||||||
|
|
||||||
if (IS_LEAF(n)) {
|
|
||||||
n = (art_node*)LEAF_RAW(n);
|
|
||||||
art_leaf *l = (art_leaf*)n;
|
|
||||||
printf("LEAF: %s\n", l->key);
|
|
||||||
}
|
|
||||||
// Might be a leaf
|
// Might be a leaf
|
||||||
if (IS_LEAF(n)) {
|
if (IS_LEAF(n)) {
|
||||||
n = (art_node*)LEAF_RAW(n);
|
n = (art_node*)LEAF_RAW(n);
|
||||||
@@ -998,7 +992,7 @@ int art_iter_prefix(art_tree *t, const unsigned char *key, int key_len, art_call
|
|||||||
|
|
||||||
static int str_prefix_matches(const art_leaf *n, const unsigned char *str, int str_len) {
|
static int str_prefix_matches(const art_leaf *n, const unsigned char *str, int str_len) {
|
||||||
// Fail if the key length is too short
|
// Fail if the key length is too short
|
||||||
if (n->key_len > (uint32_t)str_len) return 1;
|
if (n->key_len > (uint32_t)str_len) return 1;
|
||||||
|
|
||||||
// Compare the keys
|
// Compare the keys
|
||||||
return memcmp(str, n->key, n->key_len);
|
return memcmp(str, n->key, n->key_len);
|
||||||
@@ -1008,33 +1002,40 @@ void *art_substring(const art_tree *t, const unsigned char *str, int str_len)
|
|||||||
{
|
{
|
||||||
art_node **child;
|
art_node **child;
|
||||||
art_node *n = t->root;
|
art_node *n = t->root;
|
||||||
art_leaf *found = NULL;
|
art_node *m;
|
||||||
|
art_leaf *found = NULL;
|
||||||
|
int prefix_len, depth = 0;
|
||||||
|
|
||||||
int prefix_len, depth = 0;
|
|
||||||
while (n) {
|
while (n) {
|
||||||
// Might be a leaf
|
// Might be a leaf
|
||||||
if (IS_LEAF(n)) {
|
if (IS_LEAF(n)) {
|
||||||
n = (art_node*)LEAF_RAW(n);
|
n = (art_node*)LEAF_RAW(n);
|
||||||
// Check if the expanded path matches
|
// Check if the expanded path matches
|
||||||
if (!str_prefix_matches((art_leaf*)n, str, str_len)) {
|
if (!str_prefix_matches((art_leaf*)n, str, str_len)) {
|
||||||
found = (art_leaf*)n;
|
found = (art_leaf*)n;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if current is leaf
|
||||||
|
child = find_child(n, 0);
|
||||||
|
m = (child) ? *child : NULL;
|
||||||
|
if (m && IS_LEAF(m)) {
|
||||||
|
m = (art_node*)LEAF_RAW(m);
|
||||||
|
// Check if the expanded path matches
|
||||||
|
if (!str_prefix_matches((art_leaf*)m, str, str_len)) {
|
||||||
|
found = (art_leaf*)m;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Bail if the prefix does not match
|
// Bail if the prefix does not match
|
||||||
if (n->partial_len) {
|
if (n->partial_len) {
|
||||||
prefix_len = check_prefix(n, str, str_len, depth);
|
prefix_len = check_prefix(n, str, str_len, depth);
|
||||||
if (prefix_len != min(MAX_PREFIX_LEN, n->partial_len))
|
if (prefix_len != min(MAX_PREFIX_LEN, n->partial_len))
|
||||||
break;
|
break;
|
||||||
depth = depth + n->partial_len;
|
depth = depth + n->partial_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
art_leaf *l = maximum(n);
|
|
||||||
if (!str_prefix_matches(l, str, str_len)) {
|
|
||||||
found = l;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Recursively search
|
// Recursively search
|
||||||
child = find_child(n, str[depth]);
|
child = find_child(n, str[depth]);
|
||||||
n = (child) ? *child : NULL;
|
n = (child) ? *child : NULL;
|
||||||
@@ -1042,8 +1043,8 @@ void *art_substring(const art_tree *t, const unsigned char *str, int str_len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (found == NULL) {
|
if (found == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return found->value;
|
return found->value;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user