update code
This commit is contained in:
200
dns_client.c
200
dns_client.c
@@ -97,9 +97,7 @@ struct dns_query_struct {
|
||||
atomic_t dns_request_sent;
|
||||
void *user_ptr;
|
||||
unsigned long send_tick;
|
||||
atomic_t notified;
|
||||
dns_client_callback callback;
|
||||
struct dns_result result;
|
||||
};
|
||||
|
||||
static struct dns_client client;
|
||||
@@ -270,21 +268,6 @@ int dns_remove_server(char *server_ip, int port, dns_server_type_t server_type)
|
||||
return _dns_client_server_operate(server_ip, port, server_type, 1);
|
||||
}
|
||||
|
||||
int _dns_client_query_complete(struct dns_query_struct *query)
|
||||
{
|
||||
int ret = -1;
|
||||
if (atomic_inc_return(&query->notified) != 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
tlog(TLOG_DEBUG, "call back result : %s", query->domain);
|
||||
if (query->callback) {
|
||||
ret = query->callback(query->domain, &query->result, query->user_ptr);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void _dns_client_query_release(struct dns_query_struct *query)
|
||||
{
|
||||
int refcnt = atomic_dec_return(&query->refcnt);
|
||||
@@ -296,7 +279,10 @@ void _dns_client_query_release(struct dns_query_struct *query)
|
||||
return;
|
||||
}
|
||||
|
||||
_dns_client_query_complete(query);
|
||||
if (query->callback) {
|
||||
query->callback(query->domain, DNS_QUERY_END, NULL, NULL, 0, query->user_ptr);
|
||||
}
|
||||
|
||||
memset(query, 0, sizeof(*query));
|
||||
free(query);
|
||||
}
|
||||
@@ -321,66 +307,6 @@ void _dns_client_query_get(struct dns_query_struct *query)
|
||||
atomic_inc(&query->refcnt);
|
||||
}
|
||||
|
||||
void dns_client_ping_result(struct ping_host_struct *ping_host, const char *host, FAST_PING_RESULT result, struct sockaddr *addr, socklen_t addr_len, int seqno,
|
||||
struct timeval *tv, void *userptr)
|
||||
{
|
||||
struct dns_query_struct *query = userptr;
|
||||
int may_complete = 0;
|
||||
if (query == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (result == PING_RESULT_END) {
|
||||
_dns_client_query_release(query);
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int rtt = tv->tv_sec * 10000 + tv->tv_usec / 100;
|
||||
|
||||
switch (addr->sa_family) {
|
||||
case AF_INET: {
|
||||
struct sockaddr_in *addr_in;
|
||||
addr_in = (struct sockaddr_in *)addr;
|
||||
if (query->result.ttl_v4 > rtt) {
|
||||
query->result.ttl_v4 = rtt;
|
||||
memcpy(query->result.addr_ipv4, &addr_in->sin_addr.s_addr, 4);
|
||||
}
|
||||
} break;
|
||||
case AF_INET6: {
|
||||
struct sockaddr_in6 *addr_in6;
|
||||
addr_in6 = (struct sockaddr_in6 *)addr;
|
||||
if (IN6_IS_ADDR_V4MAPPED(&addr_in6->sin6_addr)) {
|
||||
if (query->result.ttl_v4 > rtt) {
|
||||
query->result.ttl_v4 = rtt;
|
||||
memcpy(query->result.addr_ipv4, addr_in6->sin6_addr.s6_addr + 12, 4);
|
||||
}
|
||||
} else {
|
||||
if (query->result.ttl_v6 > rtt) {
|
||||
query->result.ttl_v6 = rtt;
|
||||
memcpy(query->result.addr_ipv6, addr_in6->sin6_addr.s6_addr, 16);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (result == PING_RESULT_RESPONSE) {
|
||||
tlog(TLOG_DEBUG, "from %15s: seq=%d time=%d\n", host, seqno, rtt);
|
||||
} else {
|
||||
tlog(TLOG_DEBUG, "from %15s: seq=%d timeout\n", host, seqno);
|
||||
}
|
||||
|
||||
if (rtt < 100) {
|
||||
may_complete = 1;
|
||||
} else if (rtt < (get_tick_count() - query->send_tick) * 10) {
|
||||
may_complete = 1;
|
||||
}
|
||||
|
||||
if (may_complete) {
|
||||
_dns_client_query_complete(query);
|
||||
}
|
||||
}
|
||||
|
||||
void _dns_client_period_run()
|
||||
{
|
||||
struct dns_query_struct *query, *tmp;
|
||||
@@ -390,7 +316,6 @@ void _dns_client_period_run()
|
||||
list_for_each_entry_safe(query, tmp, &client.dns_request_list, dns_request_list)
|
||||
{
|
||||
if (now - query->send_tick >= 2000) {
|
||||
_dns_client_query_complete(query);
|
||||
_dns_client_query_remove(query, 1);
|
||||
}
|
||||
}
|
||||
@@ -419,100 +344,20 @@ static struct dns_query_struct *_dns_client_get_request(unsigned short sid, char
|
||||
return query;
|
||||
}
|
||||
|
||||
static int _dns_client_process_answer(char *domain, struct dns_packet *packet)
|
||||
{
|
||||
struct dns_query_struct *query;
|
||||
int ttl;
|
||||
char name[DNS_MAX_CNAME_LEN];
|
||||
char alias[DNS_MAX_CNAME_LEN] = {0};
|
||||
char ip[DNS_MAX_CNAME_LEN] = {0};
|
||||
int rr_count;
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
struct dns_rrs *rrs = NULL;
|
||||
int request_num = 0;
|
||||
|
||||
query = _dns_client_get_request(packet->head.id, domain);
|
||||
if (query == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
request_num = atomic_dec_return(&query->dns_request_sent);
|
||||
if (request_num < 0) {
|
||||
tlog(TLOG_ERROR, "send count is invalid, %d", request_num);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (packet->head.rcode != DNS_RC_NOERROR) {
|
||||
tlog(TLOG_ERROR, "inquery failed, %s, rcode = %d\n", name, packet->head.rcode);
|
||||
if (request_num == 0) {
|
||||
_dns_client_query_remove(query, 0);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (j = 1; j < DNS_RRS_END; j++) {
|
||||
rrs = dns_get_rrs_start(packet, j, &rr_count);
|
||||
for (i = 0; i < rr_count && rrs; i++, rrs = dns_get_rrs_next(packet, rrs)) {
|
||||
switch (rrs->type) {
|
||||
case DNS_T_A: {
|
||||
unsigned char addr[4];
|
||||
dns_get_A(rrs, name, DNS_MAX_CNAME_LEN, &ttl, addr);
|
||||
tlog(TLOG_DEBUG, "%s %d : %d.%d.%d.%d", name, ttl, addr[0], addr[1], addr[2], addr[3]);
|
||||
sprintf(ip, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]);
|
||||
|
||||
if (strncmp(name, domain, DNS_MAX_CNAME_LEN) == 0 || strncmp(alias, name, DNS_MAX_CNAME_LEN) == 0) {
|
||||
_dns_client_query_get(query);
|
||||
if (fast_ping_start(ip, 1, 500, dns_client_ping_result, query) == NULL) {
|
||||
_dns_client_query_release(query);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case DNS_T_AAAA: {
|
||||
unsigned char addr[16];
|
||||
dns_get_AAAA(rrs, name, DNS_MAX_CNAME_LEN, &ttl, addr);
|
||||
sprintf(name, "%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x", 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]);
|
||||
_dns_client_query_get(query);
|
||||
if (fast_ping_start(name, 1, 500, dns_client_ping_result, query) == NULL) {
|
||||
_dns_client_query_release(query);
|
||||
}
|
||||
} break;
|
||||
case DNS_T_NS: {
|
||||
char cname[128];
|
||||
dns_get_CNAME(rrs, name, 128, &ttl, cname, 128);
|
||||
tlog(TLOG_INFO, "NS: %s %d : %s\n", name, ttl, cname);
|
||||
} break;
|
||||
case DNS_T_CNAME: {
|
||||
char cname[128];
|
||||
dns_get_CNAME(rrs, name, 128, &ttl, cname, 128);
|
||||
tlog(TLOG_DEBUG, "%s %d : %s\n", name, ttl, cname);
|
||||
strncpy(alias, cname, DNS_MAX_CNAME_LEN);
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (request_num == 0) {
|
||||
_dns_client_query_remove(query, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _dns_client_recv(unsigned char *inpacket, int inpacket_len, struct sockaddr_storage *from, socklen_t from_len)
|
||||
{
|
||||
int len;
|
||||
int i;
|
||||
int qtype;
|
||||
int qclass;
|
||||
char name[DNS_MAX_CNAME_LEN];
|
||||
char domain[DNS_MAX_CNAME_LEN];
|
||||
int rr_count;
|
||||
struct dns_rrs *rrs = NULL;
|
||||
unsigned char packet_buff[DNS_PACKSIZE];
|
||||
struct dns_packet *packet = (struct dns_packet *)packet_buff;
|
||||
int ret = 0;
|
||||
struct dns_query_struct *query;
|
||||
int request_num = 0;
|
||||
|
||||
packet->head.tc = 0;
|
||||
len = dns_decode(packet, DNS_PACKSIZE, inpacket, inpacket_len);
|
||||
@@ -531,17 +376,30 @@ static int _dns_client_recv(unsigned char *inpacket, int inpacket_len, struct so
|
||||
|
||||
rrs = dns_get_rrs_start(packet, DNS_RRS_QD, &rr_count);
|
||||
for (i = 0; i < rr_count && rrs; i++, rrs = dns_get_rrs_next(packet, rrs)) {
|
||||
dns_get_domain(rrs, name, DNS_MAX_CNAME_LEN, &qtype, &qclass);
|
||||
tlog(TLOG_DEBUG, "domain: %s qtype: %d qclass: %d\n", name, qtype, qclass);
|
||||
dns_get_domain(rrs, domain, DNS_MAX_CNAME_LEN, &qtype, &qclass);
|
||||
tlog(TLOG_DEBUG, "domain: %s qtype: %d qclass: %d\n", domain, qtype, qclass);
|
||||
}
|
||||
|
||||
if (_dns_client_process_answer(name, packet) != 0) {
|
||||
char host[DNS_HOSTNAME_LEN];
|
||||
tlog(TLOG_ERROR, "process answer failed, %s from %s", name, gethost_by_addr(host, (struct sockaddr *)from, from_len));
|
||||
query = _dns_client_get_request(packet->head.id, domain);
|
||||
if (query == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
request_num = atomic_dec_return(&query->dns_request_sent);
|
||||
if (request_num < 0) {
|
||||
tlog(TLOG_ERROR, "send count is invalid, %d", request_num);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
if (query->callback) {
|
||||
ret = query->callback(query->domain, DNS_QUERY_RESULT, packet, inpacket, inpacket_len, query->user_ptr);
|
||||
}
|
||||
|
||||
if (request_num == 0 || ret) {
|
||||
_dns_client_query_remove(query, 0);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _dns_client_process(struct dns_query_struct *dns_query, unsigned long now)
|
||||
@@ -696,13 +554,10 @@ int dns_client_query(char *domain, int qtype, dns_client_callback callback, void
|
||||
INIT_HLIST_NODE(&query->domain_node);
|
||||
INIT_LIST_HEAD(&query->dns_request_list);
|
||||
atomic_set(&query->refcnt, 0);
|
||||
atomic_set(&query->notified, 0);
|
||||
atomic_set(&query->dns_request_sent, 0);
|
||||
strncpy(query->domain, domain, DNS_MAX_CNAME_LEN);
|
||||
query->user_ptr = user_ptr;
|
||||
query->callback = callback;
|
||||
query->result.ttl_v4 = -1;
|
||||
query->result.ttl_v6 = -1;
|
||||
query->qtype = qtype;
|
||||
query->sid = atomic_inc_return(&dns_client_sid);
|
||||
|
||||
@@ -714,6 +569,7 @@ int dns_client_query(char *domain, int qtype, dns_client_callback callback, void
|
||||
hash_add(client.domain_map, &query->domain_node, key);
|
||||
pthread_mutex_unlock(&client.domain_map_lock);
|
||||
|
||||
|
||||
ret = _dns_client_send_query(query, domain);
|
||||
if (ret != 0) {
|
||||
goto errout_del_list;
|
||||
|
||||
10
dns_client.h
10
dns_client.h
@@ -7,7 +7,7 @@ typedef enum {
|
||||
DNS_SERVER_UDP,
|
||||
DNS_SERVER_TCP,
|
||||
DNS_SERVER_HTTP,
|
||||
DNS_SERVER_TYPE_END,
|
||||
DNS_SERVER_TYPE_END,
|
||||
} dns_server_type_t;
|
||||
|
||||
struct dns_result {
|
||||
@@ -18,9 +18,15 @@ struct dns_result {
|
||||
unsigned char addr_ipv6[16];
|
||||
};
|
||||
|
||||
typedef enum dns_result_type {
|
||||
DNS_QUERY_ERR,
|
||||
DNS_QUERY_RESULT = 1,
|
||||
DNS_QUERY_END,
|
||||
} dns_result_type;
|
||||
|
||||
int dns_client_init(void);
|
||||
|
||||
typedef int (*dns_client_callback)(char *domain, struct dns_result *result, void *user_ptr);
|
||||
typedef int (*dns_client_callback)(char *domain, dns_result_type rtype, struct dns_packet *packet, unsigned char *inpacket, int inpacket_len, void *user_ptr);
|
||||
|
||||
int dns_client_query(char *domain, int qtype, dns_client_callback callback, void *user_ptr);
|
||||
|
||||
|
||||
243
dns_server.c
243
dns_server.c
@@ -20,6 +20,7 @@
|
||||
#include "atomic.h"
|
||||
#include "dns.h"
|
||||
#include "dns_client.h"
|
||||
#include "fast_ping.h"
|
||||
#include "hashtable.h"
|
||||
#include "list.h"
|
||||
#include "tlog.h"
|
||||
@@ -60,6 +61,7 @@ struct dns_request {
|
||||
char domain[DNS_MAX_CNAME_LEN];
|
||||
char alias[DNS_MAX_CNAME_LEN];
|
||||
struct dns_head head;
|
||||
unsigned long send_tick;
|
||||
unsigned short qtype;
|
||||
unsigned short id;
|
||||
unsigned short ss_family;
|
||||
@@ -70,8 +72,15 @@ struct dns_request {
|
||||
struct sockaddr addr;
|
||||
};
|
||||
|
||||
int ttl_v4;
|
||||
unsigned char ipv4_addr[DNS_RR_A_LEN];
|
||||
|
||||
int ttl_v6;
|
||||
unsigned char ipv6_addr[DNS_RR_AAAA_LEN];
|
||||
|
||||
atomic_t notified;
|
||||
|
||||
int passthrough;
|
||||
};
|
||||
|
||||
static struct dns_server server;
|
||||
@@ -173,6 +182,22 @@ static int _dns_add_rrs(struct dns_packet *packet, struct dns_request *request)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _dns_reply_inpacket(struct dns_request *request, unsigned char *inpacket, int inpacket_len)
|
||||
{
|
||||
int send_len = 0;
|
||||
unsigned short *id = (unsigned short *)inpacket;
|
||||
|
||||
*id = htons(request->id);
|
||||
|
||||
send_len = sendto(server.fd, inpacket, inpacket_len, 0, &request->addr, request->addr_len);
|
||||
if (send_len != inpacket_len) {
|
||||
tlog(TLOG_ERROR, "send failed.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _dns_reply(struct dns_request *request)
|
||||
{
|
||||
unsigned char inpacket[DNS_IN_PACKSIZE];
|
||||
@@ -181,7 +206,6 @@ static int _dns_reply(struct dns_request *request)
|
||||
struct dns_head head;
|
||||
int ret = 0;
|
||||
int encode_len = 0;
|
||||
int send_len = 0;
|
||||
|
||||
memset(&head, 0, sizeof(head));
|
||||
head.id = request->id;
|
||||
@@ -212,49 +236,202 @@ static int _dns_reply(struct dns_request *request)
|
||||
return -1;
|
||||
}
|
||||
|
||||
send_len = sendto(server.fd, inpacket, encode_len, 0, &request->addr, request->addr_len);
|
||||
if (send_len != encode_len) {
|
||||
tlog(TLOG_ERROR, "send failed.");
|
||||
return _dns_reply_inpacket(request, inpacket, encode_len);
|
||||
}
|
||||
|
||||
int _dns_server_request_complete(struct dns_request *request)
|
||||
{
|
||||
int ret = -1;
|
||||
if (atomic_inc_return(&request->notified) != 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (request->passthrough) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (request->qtype == DNS_T_A) {
|
||||
tlog(TLOG_INFO, "result: %s, %d.%d.%d.%d\n", request->domain, request->ipv4_addr[0], request->ipv4_addr[1], request->ipv4_addr[2],
|
||||
request->ipv4_addr[3]);
|
||||
} else if (request->qtype == DNS_T_AAAA) {
|
||||
tlog(TLOG_INFO, "result :%s, %x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x", 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->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]);
|
||||
}
|
||||
|
||||
_dns_reply(request);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void _dns_server_request_release(struct dns_request *request)
|
||||
{
|
||||
int refcnt = atomic_dec_return(&request->refcnt);
|
||||
if (refcnt) {
|
||||
if (refcnt < 0) {
|
||||
tlog(TLOG_ERROR, "BUG: refcnt is %d", refcnt);
|
||||
abort();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
_dns_server_request_complete(request);
|
||||
memset(request, 0, sizeof(*request));
|
||||
free(request);
|
||||
}
|
||||
|
||||
void _dns_server_request_get(struct dns_request *request)
|
||||
{
|
||||
atomic_inc(&request->refcnt);
|
||||
}
|
||||
|
||||
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, struct timeval *tv, void *userptr)
|
||||
{
|
||||
struct dns_request *request = userptr;
|
||||
int may_complete = 0;
|
||||
if (request == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (result == PING_RESULT_END) {
|
||||
_dns_server_request_release(request);
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int rtt = tv->tv_sec * 10000 + tv->tv_usec / 100;
|
||||
|
||||
switch (addr->sa_family) {
|
||||
case AF_INET: {
|
||||
struct sockaddr_in *addr_in;
|
||||
addr_in = (struct sockaddr_in *)addr;
|
||||
if (request->ttl_v4 > rtt) {
|
||||
request->ttl_v4 = rtt;
|
||||
memcpy(request->ipv4_addr, &addr_in->sin_addr.s_addr, 4);
|
||||
}
|
||||
} break;
|
||||
case AF_INET6: {
|
||||
struct sockaddr_in6 *addr_in6;
|
||||
addr_in6 = (struct sockaddr_in6 *)addr;
|
||||
if (IN6_IS_ADDR_V4MAPPED(&addr_in6->sin6_addr)) {
|
||||
if (request->ttl_v4 > rtt) {
|
||||
request->ttl_v4 = rtt;
|
||||
memcpy(request->ipv4_addr, addr_in6->sin6_addr.s6_addr + 12, 4);
|
||||
}
|
||||
} else {
|
||||
if (request->ttl_v6 > rtt) {
|
||||
request->ttl_v6 = rtt;
|
||||
memcpy(request->ipv6_addr, addr_in6->sin6_addr.s6_addr, 16);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (result == PING_RESULT_RESPONSE) {
|
||||
tlog(TLOG_DEBUG, "from %15s: seq=%d time=%d\n", host, seqno, rtt);
|
||||
} else {
|
||||
tlog(TLOG_DEBUG, "from %15s: seq=%d timeout\n", host, seqno);
|
||||
}
|
||||
|
||||
if (rtt < 100) {
|
||||
may_complete = 1;
|
||||
} else if (rtt < (get_tick_count() - request->send_tick) * 10) {
|
||||
may_complete = 1;
|
||||
}
|
||||
|
||||
if (may_complete) {
|
||||
_dns_server_request_complete(request);
|
||||
}
|
||||
}
|
||||
|
||||
static int _dns_client_process_answer(struct dns_request *request, char *domain, struct dns_packet *packet)
|
||||
{
|
||||
int ttl;
|
||||
char name[DNS_MAX_CNAME_LEN];
|
||||
char alias[DNS_MAX_CNAME_LEN] = {0};
|
||||
char ip[DNS_MAX_CNAME_LEN] = {0};
|
||||
int rr_count;
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
struct dns_rrs *rrs = NULL;
|
||||
|
||||
if (packet->head.rcode != DNS_RC_NOERROR) {
|
||||
tlog(TLOG_ERROR, "inquery failed, %s, rcode = %d\n", name, packet->head.rcode);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (j = 1; j < DNS_RRS_END; j++) {
|
||||
rrs = dns_get_rrs_start(packet, j, &rr_count);
|
||||
for (i = 0; i < rr_count && rrs; i++, rrs = dns_get_rrs_next(packet, rrs)) {
|
||||
switch (rrs->type) {
|
||||
case DNS_T_A: {
|
||||
unsigned char addr[4];
|
||||
dns_get_A(rrs, name, DNS_MAX_CNAME_LEN, &ttl, addr);
|
||||
tlog(TLOG_DEBUG, "%s %d : %d.%d.%d.%d", name, ttl, addr[0], addr[1], addr[2], addr[3]);
|
||||
sprintf(ip, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]);
|
||||
|
||||
if (strncmp(name, domain, DNS_MAX_CNAME_LEN) == 0 || strncmp(alias, name, DNS_MAX_CNAME_LEN) == 0) {
|
||||
_dns_server_request_get(request);
|
||||
if (fast_ping_start(ip, 1, 500, _dns_server_ping_result, request) == NULL) {
|
||||
_dns_server_request_release(request);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case DNS_T_AAAA: {
|
||||
unsigned char addr[16];
|
||||
dns_get_AAAA(rrs, name, DNS_MAX_CNAME_LEN, &ttl, addr);
|
||||
sprintf(name, "%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x", 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]);
|
||||
_dns_server_request_get(request);
|
||||
if (fast_ping_start(name, 1, 500, _dns_server_ping_result, request) == NULL) {
|
||||
_dns_server_request_release(request);
|
||||
}
|
||||
} break;
|
||||
case DNS_T_NS: {
|
||||
char cname[128];
|
||||
dns_get_CNAME(rrs, name, 128, &ttl, cname, 128);
|
||||
tlog(TLOG_INFO, "NS: %s %d : %s\n", name, ttl, cname);
|
||||
} break;
|
||||
case DNS_T_CNAME: {
|
||||
char cname[128];
|
||||
dns_get_CNAME(rrs, name, 128, &ttl, cname, 128);
|
||||
tlog(TLOG_DEBUG, "%s %d : %s\n", name, ttl, cname);
|
||||
strncpy(alias, cname, DNS_MAX_CNAME_LEN);
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dns_server_resolve_callback(char *domain, struct dns_result *result, void *user_ptr)
|
||||
static int dns_server_resolve_callback(char *domain, dns_result_type rtype, struct dns_packet *packet, unsigned char *inpacket, int inpacket_len,
|
||||
void *user_ptr)
|
||||
{
|
||||
struct dns_request *request = user_ptr;
|
||||
|
||||
int refcnt;
|
||||
|
||||
if (user_ptr == NULL) {
|
||||
if (request == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
refcnt = atomic_dec_return(&request->refcnt);
|
||||
if (refcnt) {
|
||||
if (refcnt < 0) {
|
||||
abort();
|
||||
if (rtype == DNS_QUERY_RESULT) {
|
||||
if (request->passthrough) {
|
||||
_dns_reply_inpacket(request, inpacket, inpacket_len);
|
||||
return -1;
|
||||
}
|
||||
_dns_client_process_answer(request, domain, packet);
|
||||
return 0;
|
||||
} else if (rtype == DNS_QUERY_ERR) {
|
||||
tlog(TLOG_ERROR, "request faield, %s", domain);
|
||||
return -1;
|
||||
} else {
|
||||
_dns_server_request_release(request);
|
||||
}
|
||||
|
||||
memcpy(request->ipv4_addr, result->addr_ipv4, 4);
|
||||
strncpy(request->alias, result->alias, DNS_MAX_CNAME_LEN);
|
||||
memcpy(request->ipv6_addr, result->addr_ipv6, 16);
|
||||
|
||||
if (request->qtype == DNS_T_A) {
|
||||
tlog(TLOG_INFO, "result: %s, %d.%d.%d.%d\n", domain, request->ipv4_addr[0], request->ipv4_addr[1], request->ipv4_addr[2], request->ipv4_addr[3]);
|
||||
} else if (request->qtype == DNS_T_AAAA) {
|
||||
tlog(TLOG_INFO, "result :%s, %x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x", 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->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]);
|
||||
}
|
||||
_dns_reply(request);
|
||||
|
||||
memset(request, 0, sizeof(*request));
|
||||
free(request);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -283,6 +460,9 @@ static int _dns_server_recv(unsigned char *inpacket, int inpacket_len, struct so
|
||||
}
|
||||
|
||||
request = malloc(sizeof(*request));
|
||||
memset(request, 0, sizeof(*request));
|
||||
request->ttl_v4 = -1;
|
||||
request->ttl_v6 = -1;
|
||||
if (request == NULL) {
|
||||
printf("malloc failed.\n");
|
||||
goto errout;
|
||||
@@ -319,12 +499,13 @@ static int _dns_server_recv(unsigned char *inpacket, int inpacket_len, struct so
|
||||
break;
|
||||
default:
|
||||
tlog(TLOG_INFO, "unsupport qtype: %d, domain: %s", qtype, request->domain);
|
||||
return ret;
|
||||
request->passthrough = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
tlog(TLOG_INFO, "query server %s from %s, qtype = %d\n", request->domain, gethost_by_addr(name, (struct sockaddr *)from, from_len), qtype);
|
||||
atomic_set(&request->refcnt, 1);
|
||||
_dns_server_request_get(request);
|
||||
request->send_tick = get_tick_count();
|
||||
dns_client_query(request->domain, qtype, dns_server_resolve_callback, request);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -53,6 +53,7 @@ int smartdns_init()
|
||||
}
|
||||
|
||||
tlog_setlogscreen(1);
|
||||
//tlog_setlevel(TLOG_DEBUG);
|
||||
|
||||
ret = fast_ping_init();
|
||||
if (ret != 0) {
|
||||
|
||||
Reference in New Issue
Block a user