Explorar o código

feature: auto detect ipv6 features.

Nick Peng %!s(int64=3) %!d(string=hai) anos
pai
achega
03478debe8
Modificáronse 4 ficheiros con 101 adicións e 13 borrados
  1. 1 1
      src/dns_client.c
  2. 81 1
      src/dns_server.c
  3. 16 9
      src/fast_ping.c
  4. 3 2
      src/fast_ping.h

+ 1 - 1
src/dns_client.c

@@ -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) {

+ 81 - 1
src/dns_server.c

@@ -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;

+ 16 - 9
src/fast_ping.c

@@ -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;
 		}
 

+ 3 - 2
src/fast_ping.h

@@ -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,