Răsfoiți Sursa

fix: resolve fast_ping races and proxy crash

Nick Peng 1 zi în urmă
părinte
comite
dcc981633b

+ 16 - 4
src/dns_client/proxy.c

@@ -30,12 +30,22 @@
 int _dns_proxy_handshake(struct dns_server_info *server_info, struct epoll_event *event, unsigned long now)
 {
 	struct epoll_event fd_event;
-	proxy_handshake_state ret = proxy_conn_handshake(server_info->proxy);
-	int fd = server_info->fd;
+	proxy_handshake_state ret;
+	int fd;
 	int retval = -1;
 	int epoll_op = EPOLL_CTL_MOD;
 
+	pthread_mutex_lock(&server_info->lock);
+	if (server_info->proxy == NULL) {
+		pthread_mutex_unlock(&server_info->lock);
+		return -1;
+	}
+
+	ret = proxy_conn_handshake(server_info->proxy);
+	fd = server_info->fd;
+
 	if (ret == PROXY_HANDSHAKE_OK) {
+		pthread_mutex_unlock(&server_info->lock);
 		return 0;
 	}
 
@@ -92,13 +102,15 @@ int _dns_proxy_handshake(struct dns_server_info *server_info, struct epoll_event
 		goto errout;
 	}
 
+	pthread_mutex_unlock(&server_info->lock);
 	return retval;
 
 errout:
-	pthread_mutex_lock(&server_info->lock);
 	server_info->recv_buff.len = 0;
 	server_info->send_buff.len = 0;
-	_dns_client_close_socket(server_info);
+	if (server_info->proxy) {
+		_dns_client_close_socket(server_info);
+	}
 	pthread_mutex_unlock(&server_info->lock);
 	return -1;
 }

+ 4 - 0
src/dns_server/speed_check.c

@@ -232,6 +232,10 @@ int _dns_server_check_speed(struct dns_request *request, char *ip)
 		break;
 	}
 
+	if (ping_timeout < 200) {
+		ping_timeout = 200;
+	}
+
 	port = request->check_order_list->orders[order].tcp_port;
 	type = request->check_order_list->orders[order].type;
 	switch (type) {

+ 7 - 3
src/fast_ping/fast_ping.c

@@ -235,6 +235,10 @@ struct ping_host_struct *fast_ping_start(PING_TYPE type, const char *host, int c
 		goto errout;
 	}
 
+	if (timeout <= 0) {
+		timeout = 100;
+	}
+
 	ret = _fast_ping_get_addr_by_type(type, ip_str, port, &gai, &ping_type);
 	if (ret != 0) {
 		goto errout;
@@ -375,8 +379,8 @@ static int _fast_ping_process(struct ping_host_struct *ping_host, struct epoll_e
 		ret = _fast_ping_process_udp(ping_host, now);
 		break;
 	default:
-		tlog(TLOG_ERROR, "BUG: type error : %p, %d, %s, %d", ping_host, ping_host->sid, ping_host->host, ping_host->fd);
-		abort();
+
+		BUG("type error : %p, %d, %s, %d", ping_host, ping_host->sid, ping_host->host, ping_host->fd);
 		break;
 	}
 
@@ -512,7 +516,7 @@ static void *_fast_ping_work(void *arg)
 		for (i = 0; i < num; i++) {
 			struct epoll_event *event = &events[i];
 			/* read event */
-			if (event->data.fd == ping.event_fd) {
+			if (event->data.ptr == NULL) {
 				uint64_t value;
 				int unused __attribute__((unused));
 				unused = read(ping.event_fd, &value, sizeof(uint64_t));

+ 2 - 2
src/fast_ping/ping_fake.c

@@ -35,8 +35,8 @@ void _fast_ping_fake_put(struct fast_ping_fake_ip *fake)
 	int ref_cnt = atomic_dec_and_test(&fake->ref);
 	if (!ref_cnt) {
 		if (ref_cnt < 0) {
-			tlog(TLOG_ERROR, "invalid refcount of fake ping %s", fake->host);
-			abort();
+
+			BUG("invalid refcount of fake ping %s", fake->host);
 		}
 		return;
 	}

+ 5 - 4
src/fast_ping/ping_host.c

@@ -20,6 +20,7 @@
 #include "ping_host.h"
 #include "notify_event.h"
 #include "ping_fake.h"
+#include "smartdns/util.h"
 
 #include <errno.h>
 #include <pthread.h>
@@ -29,8 +30,8 @@
 void _fast_ping_host_get(struct ping_host_struct *ping_host)
 {
 	if (atomic_inc_return(&ping_host->ref) <= 0) {
-		tlog(TLOG_ERROR, "BUG: ping host ref is invalid, host: %s", ping_host->host);
-		abort();
+
+		BUG("ping host ref is invalid, host: %s", ping_host->host);
 	}
 }
 
@@ -60,8 +61,8 @@ void _fast_ping_host_put(struct ping_host_struct *ping_host)
 	int ref_cnt = atomic_dec_and_test(&ping_host->ref);
 	if (!ref_cnt) {
 		if (ref_cnt < 0) {
-			tlog(TLOG_ERROR, "invalid refcount of ping_host %s", ping_host->host);
-			abort();
+
+			BUG("invalid refcount of ping_host %s", ping_host->host);
 		}
 		return;
 	}

+ 31 - 19
src/fast_ping/ping_icmp.c

@@ -479,34 +479,46 @@ errout:
 int _fast_ping_sockaddr_ip_cmp(struct sockaddr *first_addr, socklen_t first_addr_len, struct sockaddr *second_addr,
 							   socklen_t second_addr_len)
 {
-	if (first_addr_len != second_addr_len) {
+	void *ip1, *ip2;
+	int len1, len2;
+
+	if (first_addr->sa_family == AF_INET) {
+		ip1 = &((struct sockaddr_in *)first_addr)->sin_addr.s_addr;
+		len1 = IPV4_ADDR_LEN;
+	} else if (first_addr->sa_family == AF_INET6) {
+		struct in6_addr *in6 = &((struct sockaddr_in6 *)first_addr)->sin6_addr;
+		if (IN6_IS_ADDR_V4MAPPED(in6)) {
+			ip1 = in6->s6_addr + 12;
+			len1 = IPV4_ADDR_LEN;
+		} else {
+			ip1 = in6->s6_addr;
+			len1 = IPV6_ADDR_LEN;
+		}
+	} else {
 		return -1;
 	}
 
-	if (first_addr->sa_family != second_addr->sa_family) {
+	if (second_addr->sa_family == AF_INET) {
+		ip2 = &((struct sockaddr_in *)second_addr)->sin_addr.s_addr;
+		len2 = IPV4_ADDR_LEN;
+	} else if (second_addr->sa_family == AF_INET6) {
+		struct in6_addr *in6 = &((struct sockaddr_in6 *)second_addr)->sin6_addr;
+		if (IN6_IS_ADDR_V4MAPPED(in6)) {
+			ip2 = in6->s6_addr + 12;
+			len2 = IPV4_ADDR_LEN;
+		} else {
+			ip2 = in6->s6_addr;
+			len2 = IPV6_ADDR_LEN;
+		}
+	} else {
 		return -1;
 	}
 
-	switch (first_addr->sa_family) {
-	case AF_INET: {
-		struct sockaddr_in *first_addr_in = (struct sockaddr_in *)first_addr;
-		struct sockaddr_in *second_addr_in = (struct sockaddr_in *)second_addr;
-		if (memcmp(&first_addr_in->sin_addr.s_addr, &second_addr_in->sin_addr.s_addr, IPV4_ADDR_LEN) != 0) {
-			return -1;
-		}
-	} break;
-	case AF_INET6: {
-		struct sockaddr_in6 *first_addr_in6 = (struct sockaddr_in6 *)first_addr;
-		struct sockaddr_in6 *second_addr_in6 = (struct sockaddr_in6 *)second_addr;
-		if (memcmp(&first_addr_in6->sin6_addr.s6_addr, &second_addr_in6->sin6_addr.s6_addr, IPV4_ADDR_LEN) != 0) {
-			return -1;
-		}
-	} break;
-	default:
+	if (len1 != len2) {
 		return -1;
 	}
 
-	return 0;
+	return memcmp(ip1, ip2, len1);
 }
 
 uint16_t _fast_ping_checksum(uint16_t *header, size_t len)

+ 4 - 4
src/fast_ping/ping_tcp_syn.c

@@ -682,7 +682,7 @@ int _fast_ping_process_tcp_syn(struct ping_host_struct *ping_host, struct timeva
 		}
 
 		/* Check if SYN-ACK or RST */
-		if (!((tcp->syn && tcp->ack) || tcp->rst)) {
+		if (!((tcp->syn && tcp->ack) || (tcp->rst && tcp->ack))) {
 			continue;
 		}
 
@@ -869,6 +869,9 @@ static int _fast_ping_create_tcp_syn_sock(int is_ipv6)
 		tcp_syn_host = &ping.tcp_syn6_host;
 	}
 
+	tcp_syn_host->fd = fd;
+	tcp_syn_host->type = FAST_PING_TCP_SYN;
+
 	/* Add to epoll */
 	memset(&event, 0, sizeof(event));
 	event.events = EPOLLIN;
@@ -878,9 +881,6 @@ static int _fast_ping_create_tcp_syn_sock(int is_ipv6)
 		goto errout;
 	}
 
-	tcp_syn_host->fd = fd;
-	tcp_syn_host->type = FAST_PING_TCP_SYN;
-
 	return fd;
 
 errout:

+ 1 - 1
src/fast_ping/wakeup_event.c

@@ -43,7 +43,7 @@ int _fast_ping_init_wakeup_event(void)
 	struct epoll_event event;
 	memset(&event, 0, sizeof(event));
 	event.events = EPOLLIN | EPOLLERR;
-	event.data.fd = fdevent;
+	event.data.ptr = NULL;
 	if (epoll_ctl(ping.epoll_fd, EPOLL_CTL_ADD, fdevent, &event) != 0) {
 		tlog(TLOG_ERROR, "set eventfd failed, %s\n", strerror(errno));
 		goto errout;

+ 12 - 9
src/lib/art.c

@@ -30,6 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <stdio.h>
 #include <assert.h>
 #include "smartdns/lib/art.h"
+#include "smartdns/util.h"
 
 // #ifdef __i386__
 //     #include <emmintrin.h>
@@ -76,10 +77,10 @@ static art_node* alloc_node(uint8_t type) {
             mem = (art_node*)calloc(1, sizeof(art_node256));
             break;
         default:
-            abort();
+            BUG("alloc_node: invalid type");
     }
     if (mem == NULL) {
-		abort();
+		BUG("alloc_node: calloc failed");
 	}
 	n = mem;
 	n->type = type;
@@ -156,7 +157,7 @@ static void destroy_node(art_node *n) {
             break;
 
         default:
-            abort();
+            BUG("destroy_node: invalid type");
     }
 
     // Free ourself on the way up
@@ -273,7 +274,7 @@ static art_node** find_child(art_node *n, unsigned char c) {
             break;
 
         default:
-            abort();
+            BUG("find_child: invalid type");
     }
     return NULL;
 }
@@ -373,7 +374,8 @@ static art_leaf* minimum(const art_node *n) {
             while (!((const art_node256*)n)->children[idx]) idx++;
             return minimum(((const art_node256*)n)->children[idx]);
         default:
-            abort();
+            BUG("minimum: invalid type");
+            return NULL;
     }
 }
 
@@ -401,7 +403,8 @@ static art_leaf* maximum(const art_node *n) {
             while (!((const art_node256*)n)->children[idx]) idx--;
             return maximum(((const art_node256*)n)->children[idx]);
         default:
-            abort();
+            BUG("maximum: invalid type");
+            return NULL;
     }
 }
 
@@ -623,7 +626,7 @@ static void add_child(art_node *n, art_node **ref, unsigned char c, void *child)
         case NODE256:
             return add_child256((art_node256*)n, ref, c, child);
         default:
-            abort();
+            BUG("add_child: invalid type");
     }
 }
 
@@ -877,7 +880,7 @@ static void remove_child(art_node *n, art_node **ref, unsigned char c, art_node
         case NODE256:
             return remove_child256((art_node256*)n, ref, c);
         default:
-            abort();
+            BUG("remove_child: invalid type");
     }
 }
 
@@ -994,7 +997,7 @@ static int recursive_iter(art_node *n, art_callback cb, void *data) {
             break;
 
         default:
-            abort();
+            BUG("recursive_iter: invalid type");
     }
     return 0;
 }