Browse Source

Add support DNS-PING

Nick Peng 7 years ago
parent
commit
4c81b46f76
4 changed files with 320 additions and 36 deletions
  1. 2 2
      src/dns_client.c
  2. 6 6
      src/dns_server.c
  3. 307 21
      src/fast_ping.c
  4. 5 7
      src/fast_ping.h

+ 2 - 2
src/dns_client.c

@@ -274,7 +274,7 @@ int _dns_client_server_add(char *server_ip, struct addrinfo *gai, dns_server_typ
 
 	/* start ping task */
 	if (ttl == 0 && (result_flag & DNSSERVER_FLAG_CHECK_TTL)) {
-		server_info->ping_host = fast_ping_start(server_ip, 0, 60000, 1000, _dns_client_server_update_ttl, server_info);
+		server_info->ping_host = fast_ping_start(PING_TYPE_DNS, server_ip, 0, 60000, 1000, _dns_client_server_update_ttl, server_info);
 		if (server_info->ping_host == NULL) {
 			tlog(TLOG_ERROR, "start ping failed.");
 			goto errout;
@@ -916,7 +916,7 @@ static int _dns_client_process_udp(struct dns_server_info *server_info, struct e
 
 	tlog(TLOG_DEBUG, "recv udp, from %s, ttl: %d", gethost_by_addr(from_host, (struct sockaddr *)&from, from_len), ttl);
 
-	if ((ttl != server_info->ttl) && (server_info->result_flag & DNSSERVER_FLAG_CHECK_TTL)) {
+	if ((ttl != server_info->ttl) && (server_info->ttl > 0) && (server_info->result_flag & DNSSERVER_FLAG_CHECK_TTL)) {
 		tlog(TLOG_DEBUG, "TTL mismatch, from:%d, local %d, discard result", ttl, server_info->ttl);
 		return 0;
 	}

+ 6 - 6
src/dns_server.c

@@ -729,9 +729,9 @@ void _dns_server_ping_result(struct ping_host_struct *ping_host, const char *hos
 	}
 }
 
-int _dns_server_ping(struct dns_request *request, char *ip, int timeout)
+int _dns_server_ping(struct dns_request *request, PING_TYPE type, char *ip, int timeout)
 {
-	if (fast_ping_start(ip, 1, 0, timeout, _dns_server_ping_result, request) == NULL) {
+	if (fast_ping_start(type, ip, 1, 0, timeout, _dns_server_ping_result, request) == NULL) {
 		return -1;
 	}
 
@@ -913,7 +913,7 @@ static int _dns_server_process_answer(struct dns_request *request, char *domain,
 				request->rcode = packet->head.rcode;
 				sprintf(ip, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]);
 
-				if (_dns_server_ping(request, ip, DNS_PING_TIMEOUT) != 0) {
+				if (_dns_server_ping(request, PING_TYPE_ICMP, ip, DNS_PING_TIMEOUT) != 0) {
 					_dns_server_request_release(request);
 				}
 			} break;
@@ -959,7 +959,7 @@ static int _dns_server_process_answer(struct dns_request *request, char *domain,
 				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]);
 
-				if (_dns_server_ping(request, ip, DNS_PING_TIMEOUT) != 0) {
+				if (_dns_server_ping(request, PING_TYPE_ICMP, ip, DNS_PING_TIMEOUT) != 0) {
 					_dns_server_request_release(request);
 				}
 			} break;
@@ -1710,7 +1710,7 @@ void _dns_server_tcp_ping_check(struct dns_request *request)
 		case DNS_T_A: {
 			_dns_server_request_get(request);
 			sprintf(ip, "%d.%d.%d.%d:80", addr_map->ipv4_addr[0], addr_map->ipv4_addr[1], addr_map->ipv4_addr[2], addr_map->ipv4_addr[3]);
-			if (_dns_server_ping(request, ip, DNS_PING_TCP_TIMEOUT) != 0) {
+			if (_dns_server_ping(request, PING_TYPE_TCP, ip, DNS_PING_TCP_TIMEOUT) != 0) {
 				_dns_server_request_release(request);
 			}
 		} break;
@@ -1721,7 +1721,7 @@ void _dns_server_tcp_ping_check(struct dns_request *request)
 					addr_map->ipv6_addr[7], addr_map->ipv6_addr[8], addr_map->ipv6_addr[9], addr_map->ipv6_addr[10], addr_map->ipv6_addr[11],
 					addr_map->ipv6_addr[12], addr_map->ipv6_addr[13], addr_map->ipv6_addr[14], addr_map->ipv6_addr[15]);
 
-			if (_dns_server_ping(request, ip, DNS_PING_TCP_TIMEOUT) != 0) {
+			if (_dns_server_ping(request, PING_TYPE_TCP, ip, DNS_PING_TCP_TIMEOUT) != 0) {
 				_dns_server_request_release(request);
 			}
 		} break;

+ 307 - 21
src/fast_ping.c

@@ -44,6 +44,24 @@
 #define ICMP_PACKET_SIZE (1024 * 64)
 #define ICMP_INPACKET_SIZE 1024
 
+struct ping_dns_head {
+	unsigned short id;
+	unsigned short flag;
+	unsigned short qdcount;
+	unsigned short ancount;
+	unsigned short aucount;
+	unsigned short adcount;
+} __attribute__((packed));
+
+typedef enum FAST_PING_TYPE { 
+	FAST_PING_ICMP = 1, 
+	FAST_PING_ICMP6 = 2, 
+	FAST_PING_TCP, 
+	FAST_PING_UDP, 
+	FAST_PING_UDP6,
+	FAST_PING_END,
+}  FAST_PING_TYPE;
+
 struct fast_ping_packet_msg {
 	struct timeval tv;
 	unsigned int sid;
@@ -104,6 +122,10 @@ struct fast_ping_struct {
 	struct ping_host_struct icmp_host;
 	int fd_icmp6;
 	struct ping_host_struct icmp6_host;
+	int fd_udp;
+	struct ping_host_struct udp_host;
+	int fd_udp6;
+	struct ping_host_struct udp6_host;
 
 	pthread_mutex_t map_lock;
 	DECLARE_HASHTABLE(addrmap, 6);
@@ -269,7 +291,8 @@ static void _fast_ping_host_put(struct ping_host_struct *ping_host)
 		tv.tv_sec = 0;
 		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->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);
 	}
 
 	tlog(TLOG_DEBUG, "ping %p end", ping_host);
@@ -296,7 +319,8 @@ static void _fast_ping_host_remove(struct ping_host_struct *ping_host)
 		tv.tv_sec = 0;
 		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->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);
 	}
 
 	_fast_ping_host_put(ping_host);
@@ -386,6 +410,42 @@ errout:
 	return -1;
 }
 
+static int _fast_ping_sendping_udp(struct ping_host_struct *ping_host)
+{
+	struct ping_dns_head dns_head;
+	int len;
+	int flag = 0;
+
+	flag |= (0 << 15) & 0x8000;
+	flag |= (2 << 11) & 0x7800;
+	flag |= (0 << 10) & 0x0400;
+	flag |= (0 << 9) & 0x0200;
+	flag |= (0 << 8) & 0x0100;
+	flag |= (0 << 7) & 0x0080;
+	flag |= (0 << 0) & 0x000F;
+
+	ping_host->seq++;
+	memset(&dns_head, 0, sizeof(dns_head));
+	dns_head.id = htons(ping_host->sid);
+	dns_head.flag = flag;
+	len = sendto(ping.fd_udp, &dns_head, sizeof(dns_head), 0, (struct sockaddr *)&ping_host->addr, ping_host->addr_len);
+	if (len < 0 || len != sizeof(dns_head)) {
+		int err = errno;
+		if (errno == ENETUNREACH || errno == EINVAL) {
+			goto errout;
+		}
+		char ping_host_name[PING_MAX_HOSTLEN];
+		tlog(TLOG_ERROR, "sendto %s, id %d, %s", gethost_by_addr(ping_host_name, (struct sockaddr *)&ping_host->addr, ping_host->addr_len), ping_host->sid,
+			 strerror(err));
+		goto errout;
+	}
+
+	return 0;
+
+errout:
+	return -1;
+}
+
 static int _fast_ping_sendping_tcp(struct ping_host_struct *ping_host)
 {
 	struct epoll_event event;
@@ -452,6 +512,8 @@ static int _fast_ping_sendping(struct ping_host_struct *ping_host)
 		ret = _fast_ping_sendping_v6(ping_host);
 	} else if (ping_host->type == FAST_PING_TCP) {
 		ret = _fast_ping_sendping_tcp(ping_host);
+	} else if (ping_host->type == FAST_PING_UDP) {
+		ret = _fast_ping_sendping_udp(ping_host);
 	}
 
 	ping_host->send = 1;
@@ -471,7 +533,7 @@ static int _fast_ping_create_icmp_sock(FAST_PING_TYPE type)
 	struct epoll_event event;
 	int buffsize = 64 * 1024;
 	socklen_t optlen = sizeof(buffsize);
-	const int val=255;
+	const int val = 255;
 	const int on = 1;
 
 	switch (type) {
@@ -559,6 +621,95 @@ errout:
 	return -1;
 }
 
+static int _fast_ping_create_udp_sock(FAST_PING_TYPE type)
+{
+	int fd = -1;
+	struct ping_host_struct *udp_host = NULL;
+	struct epoll_event event;
+	const int val = 255;
+	const int on = 1;
+
+	switch (type) {
+	case FAST_PING_UDP:
+		fd = socket(AF_INET, SOCK_DGRAM, 0);
+		if (fd < 0) {
+			tlog(TLOG_ERROR, "create udp socket failed, %s\n", strerror(errno));
+			goto errout;
+		}
+		
+		udp_host = &ping.udp_host;
+		break;
+	case FAST_PING_UDP6:
+		fd = socket(AF_INET6, SOCK_DGRAM, 0);
+		if (fd < 0) {
+			tlog(TLOG_ERROR, "create udp socket failed, %s\n", strerror(errno));
+			goto errout;
+		}
+		
+		udp_host = &ping.udp6_host;
+		break;
+	default:
+		return -1;
+	}
+
+	setsockopt(fd, SOL_IP, IP_TTL, &val, sizeof(val));
+	setsockopt(fd, IPPROTO_IP, IP_RECVTTL, &on, sizeof(on));
+
+	memset(&event, 0, sizeof(event));
+	event.events = EPOLLIN;
+	event.data.ptr = udp_host;
+	if (epoll_ctl(ping.epoll_fd, EPOLL_CTL_ADD, fd, &event) != 0) {
+		goto errout;
+	}
+
+	udp_host->fd = fd;
+	udp_host->type = FAST_PING_UDP;
+	return fd;
+
+errout:
+	close(fd);
+	return -1;
+}
+
+static int _fast_ping_create_udp(FAST_PING_TYPE type) 
+{
+	int fd = 0;
+	int *set_fd = NULL;
+
+	pthread_mutex_lock(&ping.lock);
+	switch (type) {
+	case FAST_PING_UDP:
+		set_fd = &ping.fd_udp;
+		break;
+	case FAST_PING_UDP6:
+		set_fd = &ping.fd_udp6;
+		break;
+	default:
+		goto errout;
+		break;
+	}
+
+	if (*set_fd > 0) {
+		goto out;
+	}
+
+	fd = _fast_ping_create_udp_sock(type);
+	if (fd < 0) {
+		goto errout;
+	}
+
+	*set_fd = fd;
+out:
+	pthread_mutex_unlock(&ping.lock);
+	return *set_fd;
+errout:
+	if (fd > 0) {
+		close(fd);
+	}
+	pthread_mutex_unlock(&ping.lock);
+	return -1;
+}
+
 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)
 {
@@ -572,7 +723,7 @@ void fast_ping_print_result(struct ping_host_struct *ping_host, const char *host
 	}
 }
 
-struct ping_host_struct *fast_ping_start(const char *host, int count, int interval, int timeout, fast_ping_result ping_callback, void *userptr)
+struct ping_host_struct *fast_ping_start(PING_TYPE type, const char *host, int count, int interval, int timeout, fast_ping_result ping_callback, void *userptr)
 {
 	struct ping_host_struct *ping_host = NULL;
 	struct addrinfo *gai = NULL;
@@ -583,7 +734,7 @@ struct ping_host_struct *fast_ping_start(const char *host, int count, int interv
 	char port_str[MAX_IP_LEN];
 	char *service = NULL;
 	int port = -1;
-	FAST_PING_TYPE type;
+	FAST_PING_TYPE ping_type;
 	int socktype = 0;
 	unsigned int seed;
 
@@ -591,19 +742,58 @@ struct ping_host_struct *fast_ping_start(const char *host, int count, int interv
 		goto errout;
 	}
 
-	if (port > 0) {
+	switch (type) {
+	case PING_TYPE_ICMP: {
+		socktype = SOCK_RAW;
+		domain = _fast_ping_getdomain(ip_str);
+		if (domain < 0) {
+			return NULL;
+		}
+
+		switch (domain) {
+		case AF_INET:
+			icmp_proto = IPPROTO_ICMP;
+			ping_type = FAST_PING_ICMP;
+			break;
+		case AF_INET6:
+			icmp_proto = IPPROTO_ICMPV6;
+			ping_type = FAST_PING_ICMP6;
+			break;
+		default:
+			return NULL;
+			break;
+		}
+
+		if (_fast_ping_create_icmp(ping_type) < 0) {
+			goto errout;
+		}
+
+		gai = _fast_ping_getaddr(ip_str, service, socktype, icmp_proto);
+		if (gai == NULL) {
+			goto errout;
+		}
+	} break;
+	case PING_TYPE_TCP: {
+		if (port <= 0) {
+			port = 80;
+		}
+
 		icmp_proto = 0;
 		socktype = SOCK_STREAM;
 		snprintf(port_str, MAX_IP_LEN, "%d", port);
 		service = port_str;
-		type = FAST_PING_TCP;
+		ping_type = FAST_PING_TCP;
 
 		gai = _fast_ping_getaddr(ip_str, service, socktype, icmp_proto);
 		if (gai == NULL) {
 			goto errout;
 		}
-	} else {
-		socktype = SOCK_RAW;
+	} break;
+	case PING_TYPE_DNS: {
+		if (port <= 0) {
+			port = 53;
+		}
+
 		domain = _fast_ping_getdomain(ip_str);
 		if (domain < 0) {
 			return NULL;
@@ -611,19 +801,23 @@ struct ping_host_struct *fast_ping_start(const char *host, int count, int interv
 
 		switch (domain) {
 		case AF_INET:
-			icmp_proto = IPPROTO_ICMP;
-			type = FAST_PING_ICMP;
+			ping_type = FAST_PING_UDP;
 			break;
 		case AF_INET6:
-			icmp_proto = IPPROTO_ICMPV6;
-			type = FAST_PING_ICMP6;
+			ping_type = FAST_PING_UDP6;
 			break;
 		default:
 			return NULL;
 			break;
 		}
 
-		if (_fast_ping_create_icmp(type) < 0) {
+		icmp_proto = 0;
+		socktype = SOCK_DGRAM;
+		snprintf(port_str, MAX_IP_LEN, "%d", port);
+		service = port_str;
+		ping_type = FAST_PING_UDP;
+
+		if (_fast_ping_create_udp(ping_type) < 0) {
 			goto errout;
 		}
 
@@ -631,6 +825,10 @@ struct ping_host_struct *fast_ping_start(const char *host, int count, int interv
 		if (gai == NULL) {
 			goto errout;
 		}
+	} break;
+	default:
+		goto errout;
+		break;
 	}
 
 	ping_host = malloc(sizeof(*ping_host));
@@ -643,7 +841,7 @@ struct ping_host_struct *fast_ping_start(const char *host, int count, int interv
 	ping_host->fd = -1;
 	ping_host->timeout = timeout;
 	ping_host->count = count;
-	ping_host->type = type;
+	ping_host->type = ping_type;
 	ping_host->userptr = userptr;
 	atomic_set(&ping_host->ref, 0);
 	atomic_set(&ping_host->notified, 0);
@@ -705,7 +903,7 @@ int fast_ping_stop(struct ping_host_struct *ping_host)
 	if (ping_host == NULL) {
 		return 0;
 	}
-	
+
 	atomic_inc_return(&ping_host->notified);
 	_fast_ping_host_remove(ping_host);
 	_fast_ping_host_put(ping_host);
@@ -732,7 +930,7 @@ static struct fast_ping_packet *_fast_ping_icmp6_packet(struct ping_host_struct
 	for (c = CMSG_FIRSTHDR(msg); c; c = CMSG_NXTHDR(msg, c)) {
 		if (c->cmsg_level != IPPROTO_IPV6)
 			continue;
-		switch(c->cmsg_type) {
+		switch (c->cmsg_type) {
 		case IPV6_HOPLIMIT:
 #ifdef IPV6_2292HOPLIMIT
 		case IPV6_2292HOPLIMIT:
@@ -927,8 +1125,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->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->send = 0;
@@ -943,6 +1141,91 @@ errout:
 	return -1;
 }
 
+static int _fast_ping_process_udp(struct ping_host_struct *ping_host, struct timeval *now)
+{
+	int len;
+	u_char inpacket[ICMP_INPACKET_SIZE];
+	struct sockaddr_storage from;
+	struct ping_host_struct *recv_ping_host;
+	struct ping_dns_head *dns_head = NULL;
+	socklen_t from_len = sizeof(from);
+	uint32_t addrkey;
+	struct timeval tvresult = *now;
+	struct timeval *tvsend = NULL;
+	unsigned int sid;
+	struct msghdr msg;
+	struct iovec iov;
+	char ans_data[4096];
+	struct cmsghdr *cmsg;
+	int ttl = 0;
+
+	memset(&msg, 0, sizeof(msg));
+	iov.iov_base = (char *)inpacket;
+	iov.iov_len = sizeof(inpacket);
+	msg.msg_name = &from;
+	msg.msg_namelen = sizeof(from);
+	msg.msg_iov = &iov;
+	msg.msg_iovlen = 1;
+	msg.msg_control = ans_data;
+	msg.msg_controllen = sizeof(ans_data);
+
+	len = recvmsg(ping_host->fd, &msg, MSG_DONTWAIT);
+	if (len < 0) {
+		tlog(TLOG_ERROR, "recvfrom failed, %s\n", strerror(errno));
+		goto errout;
+	}
+
+	for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
+		if (cmsg->cmsg_level == SOL_IP
+			&& cmsg->cmsg_type == IP_TTL
+		) {
+			uint8_t * ttlPtr = (uint8_t *)CMSG_DATA(cmsg);
+			ttl = *ttlPtr;
+			break;
+		}
+	}
+
+	from_len = msg.msg_namelen;
+	dns_head = (struct ping_dns_head *)inpacket;
+	if (len < sizeof(*dns_head)) {
+		goto errout;
+	}
+	addrkey = jhash(&from, from_len, 0);
+	sid = ntohs(dns_head->id);
+	addrkey = jhash(&sid, sizeof(sid), addrkey);
+	pthread_mutex_lock(&ping.map_lock);
+	hash_for_each_possible(ping.addrmap, recv_ping_host, addr_node, addrkey)
+	{
+		if (recv_ping_host->addr_len == from_len && memcmp(&recv_ping_host->addr, &from, from_len) == 0 && recv_ping_host->sid == sid) {
+			break;
+		}
+	}
+
+	pthread_mutex_unlock(&ping.map_lock);
+
+	if (recv_ping_host == NULL) {
+		return -1;
+	}
+
+	recv_ping_host->ttl = ttl;
+	tvsend = &recv_ping_host->last;
+	tv_sub(&tvresult, tvsend);
+	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);
+	}
+
+	recv_ping_host->send = 0;
+
+	if (recv_ping_host->count == 1) {
+		_fast_ping_host_remove(recv_ping_host);
+	}
+
+	return 0;
+errout:
+	return -1;
+}
+
 static int _fast_ping_process(struct ping_host_struct *ping_host, struct epoll_event *event, struct timeval *now)
 {
 	int ret = -1;
@@ -955,6 +1238,9 @@ static int _fast_ping_process(struct ping_host_struct *ping_host, struct epoll_e
 	case FAST_PING_TCP:
 		ret = _fast_ping_process_tcp(ping_host, event, now);
 		break;
+	case FAST_PING_UDP:
+		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();
@@ -1029,8 +1315,8 @@ static void _fast_ping_period_run(void)
 		tv_sub(&interval, &ping_host->last);
 		millisecond = interval.tv_sec * 1000 + interval.tv_usec / 1000;
 		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->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->send = 0;
 		}
 

+ 5 - 7
src/fast_ping.h

@@ -8,12 +8,10 @@ extern "C" {
 #endif
 
 typedef enum {
-	FAST_PING_ICMP = 1,
-	FAST_PING_ICMP6 = 2,
-	FAST_PING_TCP,
-	FAST_PING_UDP,
-	FAST_PING_END
-} FAST_PING_TYPE;
+	PING_TYPE_ICMP = 1,
+	PING_TYPE_TCP = 2,
+	PING_TYPE_DNS = 3,
+} PING_TYPE;
 
 typedef enum {
 	PING_RESULT_RESPONSE = 1,
@@ -25,7 +23,7 @@ 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);
 
 /* start ping */
-struct ping_host_struct *fast_ping_start(const char *host, int count, int interval, int timeout, fast_ping_result ping_callback, void *userptr);
+struct ping_host_struct *fast_ping_start(PING_TYPE type, const char *host, int count, int interval, int timeout, fast_ping_result ping_callback, void *userptr);
 
 /* stop ping */
 int fast_ping_stop(struct ping_host_struct *ping_host);