feature: auto detect ipv6 features.

This commit is contained in:
Nick Peng
2022-05-17 20:35:36 +08:00
parent ee40591aed
commit 03478debe8
4 changed files with 101 additions and 13 deletions

View File

@@ -420,7 +420,7 @@ static int _dns_client_server_exist(const char *server_ip, int port, dns_server_
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)
struct timeval *tv, int error, void *userptr)
{
struct dns_server_info *server_info = userptr;
if (result != PING_RESULT_RESPONSE || server_info == NULL) {

View File

@@ -44,6 +44,7 @@
#include <sys/types.h>
#define DNS_MAX_EVENTS 256
#define IPV6_READY_CHECK_TIME 180
#define DNS_SERVER_TMOUT_TTL (5 * 60)
#define DNS_CONN_BUFF_SIZE 4096
#define DNS_REQUEST_MAX_TIMEOUT 850
@@ -248,6 +249,8 @@ static struct dns_server server;
static tlog_log *dns_audit;
static int is_ipv6_ready;
static int _dns_server_prefetch_request(char *domain, dns_type_t qtype, uint32_t server_flags);
static int _dns_server_forward_request(unsigned char *inpacket, int inpacket_len)
@@ -1675,7 +1678,7 @@ errout:
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 error, void *userptr)
{
struct dns_request *request = userptr;
int may_complete = 0;
@@ -1692,6 +1695,18 @@ static void _dns_server_ping_result(struct ping_host_struct *ping_host, const ch
return;
} else if (result == PING_RESULT_TIMEOUT) {
return;
} else if (result == PING_RESULT_ERROR) {
if (addr->sa_family != AF_INET6) {
return;
}
if (is_ipv6_ready) {
if (error == EADDRNOTAVAIL || errno == EACCES) {
is_ipv6_ready = 0;
tlog(TLOG_ERROR, "IPV6 is not ready, disable all ipv6 feature, recheck after %ds", IPV6_READY_CHECK_TIME);
}
}
return;
}
unsigned int rtt = tv->tv_sec * 10000 + tv->tv_usec / 100;
@@ -3011,6 +3026,60 @@ out:
return ret;
}
void _dns_server_check_ipv6_ready(void)
{
static int do_get_conf = 0;
static int is_icmp_check_set;
static int is_tcp_check_set;
int i = 0;
if (do_get_conf == 0) {
for (i = 0; i < DOMAIN_CHECK_NUM; i++) {
if (dns_conf_check_order.order[i] == DOMAIN_CHECK_ICMP) {
is_icmp_check_set = 1;
}
if (dns_conf_check_order.order[i] == DOMAIN_CHECK_TCP) {
is_tcp_check_set = 1;
}
}
if (is_icmp_check_set == 0) {
tlog(TLOG_INFO, "ICMP ping is disabled, no ipv6 icmp check feature");
}
do_get_conf = 1;
}
if (is_icmp_check_set) {
struct ping_host_struct *check_ping = fast_ping_start(PING_TYPE_ICMP, "2001::", 1, 0, 100, 0, 0);
if (check_ping) {
fast_ping_stop(check_ping);
is_ipv6_ready = 1;
return;
}
if (errno == EADDRNOTAVAIL) {
is_ipv6_ready = 0;
return;
}
}
if (is_tcp_check_set) {
struct ping_host_struct *check_ping = fast_ping_start(PING_TYPE_TCP, "2001::", 1, 0, 100, 0, 0);
if (check_ping) {
fast_ping_stop(check_ping);
is_ipv6_ready = 1;
return;
}
if (errno == EADDRNOTAVAIL) {
is_ipv6_ready = 0;
return;
}
}
}
static void _dns_server_request_set_client(struct dns_request *request, struct dns_server_conn_head *conn)
{
request->conn = conn;
@@ -3116,6 +3185,10 @@ static void _dns_server_check_set_passthrough(struct dns_request *request)
request->passthrough = 1;
}
if (is_ipv6_ready == 0 && request->qtype == DNS_T_AAAA) {
request->passthrough = 1;
}
if (request->passthrough == 1) {
request->dualstack_selection = 0;
}
@@ -3791,6 +3864,10 @@ static void _dns_server_period_run_second(void)
}
_dns_server_tcp_idle_check();
if (sec % IPV6_READY_CHECK_TIME == 0 && is_ipv6_ready == 0) {
_dns_server_check_ipv6_ready();
}
}
static void _dns_server_period_run(void)
@@ -4240,6 +4317,9 @@ int dns_server_init(void)
goto errout;
}
_dns_server_check_ipv6_ready();
tlog(TLOG_INFO, "%s", (is_ipv6_ready) ? "IPV6 is ready, enable IPV6 features" : "IPV6 is not ready, disable IPV6 features");
return 0;
errout:
server.run = 0;

View File

@@ -97,6 +97,7 @@ struct ping_host_struct {
FAST_PING_TYPE type;
void *userptr;
int error;
fast_ping_result ping_callback;
char host[PING_MAX_HOSTLEN];
@@ -386,7 +387,7 @@ static void _fast_ping_host_put(struct ping_host_struct *ping_host)
tv.tv_usec = 0;
ping_host->ping_callback(ping_host, ping_host->host, PING_RESULT_END, &ping_host->addr, ping_host->addr_len,
ping_host->seq, ping_host->ttl, &tv, ping_host->userptr);
ping_host->seq, ping_host->ttl, &tv, ping_host->error, ping_host->userptr);
}
tlog(TLOG_DEBUG, "ping end, id %d", ping_host->sid);
@@ -414,7 +415,7 @@ static void _fast_ping_host_remove(struct ping_host_struct *ping_host)
tv.tv_usec = 0;
ping_host->ping_callback(ping_host, ping_host->host, PING_RESULT_END, &ping_host->addr, ping_host->addr_len,
ping_host->seq, ping_host->ttl, &tv, ping_host->userptr);
ping_host->seq, ping_host->ttl, &tv, ping_host->error, ping_host->userptr);
}
_fast_ping_host_put(ping_host);
@@ -445,7 +446,7 @@ static int _fast_ping_sendping_v6(struct ping_host_struct *ping_host)
(struct sockaddr *)&ping_host->addr, ping_host->addr_len);
if (len < 0 || len != sizeof(struct fast_ping_packet)) {
int err = errno;
if (errno == ENETUNREACH || errno == EINVAL) {
if (errno == ENETUNREACH || errno == EINVAL || errno == EADDRNOTAVAIL) {
goto errout;
}
@@ -644,6 +645,7 @@ static int _fast_ping_sendping(struct ping_host_struct *ping_host)
ping_host->send = 1;
if (ret != 0) {
ping_host->error = errno;
return ret;
}
@@ -848,13 +850,15 @@ errout:
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 error, void *userptr)
{
if (result == PING_RESULT_RESPONSE) {
double rtt = tv->tv_sec * 1000.0 + tv->tv_usec / 1000.0;
tlog(TLOG_INFO, "from %15s: seq=%d ttl=%d time=%.3f\n", host, seqno, ttl, rtt);
} else if (result == PING_RESULT_TIMEOUT) {
tlog(TLOG_INFO, "from %15s: seq=%d timeout\n", host, seqno);
} else if (result == PING_RESULT_ERROR) {
tlog(TLOG_DEBUG, "from %15s: error is %s\n", host, strerror(error));
} else if (result == PING_RESULT_END) {
fast_ping_stop(ping_host);
}
@@ -1041,7 +1045,6 @@ struct ping_host_struct *fast_ping_start(PING_TYPE type, const char *host, int c
ret = _fast_ping_get_addr_by_type(type, ip_str, port, &gai, &ping_type);
if (ret != 0) {
tlog(TLOG_ERROR, "get addr by type failed, host: %s", host);
goto errout;
}
@@ -1097,6 +1100,9 @@ struct ping_host_struct *fast_ping_start(PING_TYPE type, const char *host, int c
_fast_ping_host_put(ping_host);
return ping_host;
errout_remove:
ping_host->ping_callback(ping_host, ping_host->host, PING_RESULT_ERROR, &ping_host->addr,
ping_host->addr_len, ping_host->seq, ping_host->ttl, 0,
ping_host->error, ping_host->userptr);
fast_ping_stop(ping_host);
_fast_ping_host_put(ping_host);
ping_host = NULL;
@@ -1315,7 +1321,7 @@ static int _fast_ping_process_icmp(struct ping_host_struct *ping_host, struct ti
if (recv_ping_host->ping_callback) {
recv_ping_host->ping_callback(recv_ping_host, recv_ping_host->host, PING_RESULT_RESPONSE, &recv_ping_host->addr,
recv_ping_host->addr_len, recv_ping_host->seq, recv_ping_host->ttl, &tvresult,
recv_ping_host->userptr);
ping_host->error, recv_ping_host->userptr);
}
recv_ping_host->send = 0;
@@ -1349,7 +1355,8 @@ static int _fast_ping_process_tcp(struct ping_host_struct *ping_host, struct epo
tv_sub(&tvresult, tvsend);
if (ping_host->ping_callback) {
ping_host->ping_callback(ping_host, ping_host->host, PING_RESULT_RESPONSE, &ping_host->addr,
ping_host->addr_len, ping_host->seq, ping_host->ttl, &tvresult, ping_host->userptr);
ping_host->addr_len, ping_host->seq, ping_host->ttl, &tvresult, ping_host->error,
ping_host->userptr);
}
ping_host->send = 0;
@@ -1445,7 +1452,7 @@ static int _fast_ping_process_udp(struct ping_host_struct *ping_host, struct tim
if (recv_ping_host->ping_callback) {
recv_ping_host->ping_callback(recv_ping_host, recv_ping_host->host, PING_RESULT_RESPONSE, &recv_ping_host->addr,
recv_ping_host->addr_len, recv_ping_host->seq, recv_ping_host->ttl, &tvresult,
recv_ping_host->userptr);
ping_host->error, recv_ping_host->userptr);
}
recv_ping_host->send = 0;
@@ -1554,7 +1561,7 @@ static void _fast_ping_period_run(void)
if (millisecond >= ping_host->timeout && ping_host->send == 1) {
ping_host->ping_callback(ping_host, ping_host->host, PING_RESULT_TIMEOUT, &ping_host->addr,
ping_host->addr_len, ping_host->seq, ping_host->ttl, &interval,
ping_host->userptr);
ping_host->error, ping_host->userptr);
ping_host->send = 0;
}

View File

@@ -34,13 +34,14 @@ typedef enum {
typedef enum {
PING_RESULT_RESPONSE = 1,
PING_RESULT_TIMEOUT = 2,
PING_RESULT_END = 3,
PING_RESULT_ERROR = 3,
PING_RESULT_END = 4,
} FAST_PING_RESULT;
struct ping_host_struct;
typedef void (*fast_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 error, void *userptr);
/* start ping */
struct ping_host_struct *fast_ping_start(PING_TYPE type, const char *host, int count, int interval, int timeout,