|
@@ -19,6 +19,8 @@
|
|
|
#include "fast_ping.h"
|
|
#include "fast_ping.h"
|
|
|
#include "atomic.h"
|
|
#include "atomic.h"
|
|
|
#include "hashtable.h"
|
|
#include "hashtable.h"
|
|
|
|
|
+#include "tlog.h"
|
|
|
|
|
+#include "util.h"
|
|
|
#include <arpa/inet.h>
|
|
#include <arpa/inet.h>
|
|
|
#include <errno.h>
|
|
#include <errno.h>
|
|
|
#include <linux/filter.h>
|
|
#include <linux/filter.h>
|
|
@@ -43,6 +45,8 @@
|
|
|
|
|
|
|
|
struct fast_ping_packet_msg {
|
|
struct fast_ping_packet_msg {
|
|
|
struct timeval tv;
|
|
struct timeval tv;
|
|
|
|
|
+ unsigned int sid;
|
|
|
|
|
+ unsigned int seq;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
struct fast_ping_packet {
|
|
struct fast_ping_packet {
|
|
@@ -57,7 +61,7 @@ struct ping_host_struct {
|
|
|
atomic_t ref;
|
|
atomic_t ref;
|
|
|
struct hlist_node host_node;
|
|
struct hlist_node host_node;
|
|
|
struct hlist_node addr_node;
|
|
struct hlist_node addr_node;
|
|
|
- int type;
|
|
|
|
|
|
|
+ FAST_PING_TYPE type;
|
|
|
|
|
|
|
|
void *userptr;
|
|
void *userptr;
|
|
|
fast_ping_result ping_callback;
|
|
fast_ping_result ping_callback;
|
|
@@ -70,7 +74,12 @@ struct ping_host_struct {
|
|
|
int timeout;
|
|
int timeout;
|
|
|
int count;
|
|
int count;
|
|
|
int send;
|
|
int send;
|
|
|
- struct sockaddr addr;
|
|
|
|
|
|
|
+ unsigned int sid;
|
|
|
|
|
+ union {
|
|
|
|
|
+ struct sockaddr addr;
|
|
|
|
|
+ struct sockaddr_in6 in6;
|
|
|
|
|
+ struct sockaddr_in in;
|
|
|
|
|
+ };
|
|
|
socklen_t addr_len;
|
|
socklen_t addr_len;
|
|
|
struct fast_ping_packet packet;
|
|
struct fast_ping_packet packet;
|
|
|
};
|
|
};
|
|
@@ -93,6 +102,7 @@ struct fast_ping_struct {
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
static struct fast_ping_struct ping;
|
|
static struct fast_ping_struct ping;
|
|
|
|
|
+static atomic_t ping_sid = ATOMIC_INIT(0);
|
|
|
|
|
|
|
|
uint16_t _fast_ping_checksum(uint16_t *header, size_t len)
|
|
uint16_t _fast_ping_checksum(uint16_t *header, size_t len)
|
|
|
{
|
|
{
|
|
@@ -270,6 +280,8 @@ static int _fast_ping_sendping_v6(struct ping_host_struct *ping_host)
|
|
|
icmp6->icmp6_seq = htons(ping_host->seq);
|
|
icmp6->icmp6_seq = htons(ping_host->seq);
|
|
|
|
|
|
|
|
gettimeofday(&packet->msg.tv, 0);
|
|
gettimeofday(&packet->msg.tv, 0);
|
|
|
|
|
+ packet->msg.sid = ping_host->sid;
|
|
|
|
|
+ packet->msg.seq = ping_host->seq;
|
|
|
icmp6->icmp6_cksum = _fast_ping_checksum((void *)packet, sizeof(struct fast_ping_packet));
|
|
icmp6->icmp6_cksum = _fast_ping_checksum((void *)packet, sizeof(struct fast_ping_packet));
|
|
|
|
|
|
|
|
len = sendto(ping_host->fd, &ping_host->packet, sizeof(struct fast_ping_packet), 0, (struct sockaddr *)&ping_host->addr, ping_host->addr_len);
|
|
len = sendto(ping_host->fd, &ping_host->packet, sizeof(struct fast_ping_packet), 0, (struct sockaddr *)&ping_host->addr, ping_host->addr_len);
|
|
@@ -299,6 +311,8 @@ static int _fast_ping_sendping_v4(struct ping_host_struct *ping_host)
|
|
|
icmp->icmp_seq = htons(ping_host->seq);
|
|
icmp->icmp_seq = htons(ping_host->seq);
|
|
|
|
|
|
|
|
gettimeofday(&packet->msg.tv, 0);
|
|
gettimeofday(&packet->msg.tv, 0);
|
|
|
|
|
+ packet->msg.sid = ping_host->sid;
|
|
|
|
|
+ packet->msg.seq = ping_host->seq;
|
|
|
icmp->icmp_cksum = _fast_ping_checksum((void *)packet, sizeof(struct fast_ping_packet));
|
|
icmp->icmp_cksum = _fast_ping_checksum((void *)packet, sizeof(struct fast_ping_packet));
|
|
|
|
|
|
|
|
len = sendto(ping_host->fd, packet, sizeof(struct fast_ping_packet), 0, (struct sockaddr *)&ping_host->addr, ping_host->addr_len);
|
|
len = sendto(ping_host->fd, packet, sizeof(struct fast_ping_packet), 0, (struct sockaddr *)&ping_host->addr, ping_host->addr_len);
|
|
@@ -317,9 +331,9 @@ static int _fast_ping_sendping(struct ping_host_struct *ping_host)
|
|
|
{
|
|
{
|
|
|
int ret = -1;
|
|
int ret = -1;
|
|
|
|
|
|
|
|
- if (ping_host->type == AF_INET) {
|
|
|
|
|
|
|
+ if (ping_host->type == FAST_PING_ICMP) {
|
|
|
ret = _fast_ping_sendping_v4(ping_host);
|
|
ret = _fast_ping_sendping_v4(ping_host);
|
|
|
- } else if (ping_host->type == AF_INET6) {
|
|
|
|
|
|
|
+ } else if (ping_host->type == FAST_PING_ICMP6) {
|
|
|
ret = _fast_ping_sendping_v6(ping_host);
|
|
ret = _fast_ping_sendping_v6(ping_host);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -333,15 +347,15 @@ static int _fast_ping_sendping(struct ping_host_struct *ping_host)
|
|
|
return 0;
|
|
return 0;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-static int _fast_ping_create_sock(int protocol)
|
|
|
|
|
|
|
+static int _fast_ping_create_sock(FAST_PING_TYPE type)
|
|
|
{
|
|
{
|
|
|
int fd = -1;
|
|
int fd = -1;
|
|
|
struct ping_host_struct *icmp_host = NULL;
|
|
struct ping_host_struct *icmp_host = NULL;
|
|
|
struct epoll_event event;
|
|
struct epoll_event event;
|
|
|
|
|
|
|
|
- switch (protocol) {
|
|
|
|
|
- case IPPROTO_ICMP:
|
|
|
|
|
- fd = socket(AF_INET, SOCK_RAW, protocol);
|
|
|
|
|
|
|
+ switch (type) {
|
|
|
|
|
+ case FAST_PING_ICMP:
|
|
|
|
|
+ fd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
|
|
|
if (fd < 0) {
|
|
if (fd < 0) {
|
|
|
fprintf(stderr, "create icmp socket failed.\n");
|
|
fprintf(stderr, "create icmp socket failed.\n");
|
|
|
goto errout;
|
|
goto errout;
|
|
@@ -349,8 +363,8 @@ static int _fast_ping_create_sock(int protocol)
|
|
|
_fast_ping_install_filter_v4(fd);
|
|
_fast_ping_install_filter_v4(fd);
|
|
|
icmp_host = &ping.icmp_host;
|
|
icmp_host = &ping.icmp_host;
|
|
|
break;
|
|
break;
|
|
|
- case IPPROTO_ICMPV6:
|
|
|
|
|
- fd = socket(AF_INET6, SOCK_RAW, protocol);
|
|
|
|
|
|
|
+ case FAST_PING_ICMP6:
|
|
|
|
|
+ fd = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
|
|
|
if (fd < 0) {
|
|
if (fd < 0) {
|
|
|
fprintf(stderr, "create icmp socket failed.\n");
|
|
fprintf(stderr, "create icmp socket failed.\n");
|
|
|
goto errout;
|
|
goto errout;
|
|
@@ -358,6 +372,8 @@ static int _fast_ping_create_sock(int protocol)
|
|
|
_fast_ping_install_filter_v6(fd);
|
|
_fast_ping_install_filter_v6(fd);
|
|
|
icmp_host = &ping.icmp6_host;
|
|
icmp_host = &ping.icmp6_host;
|
|
|
break;
|
|
break;
|
|
|
|
|
+ default:
|
|
|
|
|
+ return -1;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
event.events = EPOLLIN;
|
|
event.events = EPOLLIN;
|
|
@@ -367,7 +383,7 @@ static int _fast_ping_create_sock(int protocol)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
icmp_host->fd = fd;
|
|
icmp_host->fd = fd;
|
|
|
- icmp_host->type = AF_PACKET;
|
|
|
|
|
|
|
+ icmp_host->type = type;
|
|
|
return fd;
|
|
return fd;
|
|
|
|
|
|
|
|
errout:
|
|
errout:
|
|
@@ -375,17 +391,17 @@ errout:
|
|
|
return -1;
|
|
return -1;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-static int _fast_ping_create_icmp(int protocol)
|
|
|
|
|
|
|
+static int _fast_ping_create_icmp(FAST_PING_TYPE type)
|
|
|
{
|
|
{
|
|
|
int fd = 0;
|
|
int fd = 0;
|
|
|
int *set_fd = NULL;
|
|
int *set_fd = NULL;
|
|
|
|
|
|
|
|
pthread_mutex_lock(&ping.lock);
|
|
pthread_mutex_lock(&ping.lock);
|
|
|
- switch (protocol) {
|
|
|
|
|
- case IPPROTO_ICMP:
|
|
|
|
|
|
|
+ switch (type) {
|
|
|
|
|
+ case FAST_PING_ICMP:
|
|
|
set_fd = &ping.fd_icmp;
|
|
set_fd = &ping.fd_icmp;
|
|
|
break;
|
|
break;
|
|
|
- case IPPROTO_ICMPV6:
|
|
|
|
|
|
|
+ case FAST_PING_ICMP6:
|
|
|
set_fd = &ping.fd_icmp6;
|
|
set_fd = &ping.fd_icmp6;
|
|
|
break;
|
|
break;
|
|
|
default:
|
|
default:
|
|
@@ -397,7 +413,7 @@ static int _fast_ping_create_icmp(int protocol)
|
|
|
goto out;
|
|
goto out;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- fd = _fast_ping_create_sock(protocol);
|
|
|
|
|
|
|
+ fd = _fast_ping_create_sock(type);
|
|
|
if (fd < 0) {
|
|
if (fd < 0) {
|
|
|
goto errout;
|
|
goto errout;
|
|
|
}
|
|
}
|
|
@@ -414,7 +430,8 @@ errout:
|
|
|
return -1;
|
|
return -1;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-void fast_ping_print_result(const char *host, FAST_PING_RESULT result, struct sockaddr *addr, socklen_t addr_len, int seqno, struct timeval *tv, void *userptr)
|
|
|
|
|
|
|
+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,
|
|
|
|
|
+ struct timeval *tv, void *userptr)
|
|
|
{
|
|
{
|
|
|
if (result == PING_RESULT_RESPONSE) {
|
|
if (result == PING_RESULT_RESPONSE) {
|
|
|
double rtt = tv->tv_sec * 1000.0 + tv->tv_usec / 1000.0;
|
|
double rtt = tv->tv_sec * 1000.0 + tv->tv_usec / 1000.0;
|
|
@@ -424,7 +441,7 @@ void fast_ping_print_result(const char *host, FAST_PING_RESULT result, struct so
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-int fast_ping_start(const char *host, int count, int timeout, fast_ping_result ping_callback, void *userptr)
|
|
|
|
|
|
|
+struct ping_host_struct *fast_ping_start(const char *host, int count, int timeout, fast_ping_result ping_callback, void *userptr)
|
|
|
{
|
|
{
|
|
|
struct ping_host_struct *ping_host = NULL;
|
|
struct ping_host_struct *ping_host = NULL;
|
|
|
struct addrinfo *gai = NULL;
|
|
struct addrinfo *gai = NULL;
|
|
@@ -433,25 +450,28 @@ int fast_ping_start(const char *host, int count, int timeout, fast_ping_result p
|
|
|
uint32_t hostkey;
|
|
uint32_t hostkey;
|
|
|
uint32_t addrkey;
|
|
uint32_t addrkey;
|
|
|
int fd = -1;
|
|
int fd = -1;
|
|
|
|
|
+ FAST_PING_TYPE type;
|
|
|
|
|
|
|
|
domain = _fast_ping_getdomain(host);
|
|
domain = _fast_ping_getdomain(host);
|
|
|
if (domain < 0) {
|
|
if (domain < 0) {
|
|
|
- return -1;
|
|
|
|
|
|
|
+ return NULL;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
switch (domain) {
|
|
switch (domain) {
|
|
|
case AF_INET:
|
|
case AF_INET:
|
|
|
icmp_proto = IPPROTO_ICMP;
|
|
icmp_proto = IPPROTO_ICMP;
|
|
|
|
|
+ type = FAST_PING_ICMP;
|
|
|
break;
|
|
break;
|
|
|
case AF_INET6:
|
|
case AF_INET6:
|
|
|
icmp_proto = IPPROTO_ICMPV6;
|
|
icmp_proto = IPPROTO_ICMPV6;
|
|
|
|
|
+ type = FAST_PING_ICMP6;
|
|
|
break;
|
|
break;
|
|
|
default:
|
|
default:
|
|
|
- return -1;
|
|
|
|
|
|
|
+ return NULL;
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- fd = _fast_ping_create_icmp(icmp_proto);
|
|
|
|
|
|
|
+ fd = _fast_ping_create_icmp(type);
|
|
|
if (fd < 0) {
|
|
if (fd < 0) {
|
|
|
goto errout;
|
|
goto errout;
|
|
|
}
|
|
}
|
|
@@ -469,24 +489,28 @@ int fast_ping_start(const char *host, int count, int timeout, fast_ping_result p
|
|
|
int interval = 1000;
|
|
int interval = 1000;
|
|
|
memset(ping_host, 0, sizeof(*ping_host));
|
|
memset(ping_host, 0, sizeof(*ping_host));
|
|
|
strncpy(ping_host->host, host, PING_MAX_HOSTLEN);
|
|
strncpy(ping_host->host, host, PING_MAX_HOSTLEN);
|
|
|
- ping_host->type = domain;
|
|
|
|
|
ping_host->fd = fd;
|
|
ping_host->fd = fd;
|
|
|
ping_host->timeout = timeout;
|
|
ping_host->timeout = timeout;
|
|
|
ping_host->count = count;
|
|
ping_host->count = count;
|
|
|
|
|
+ ping_host->type = type;
|
|
|
ping_host->userptr = userptr;
|
|
ping_host->userptr = userptr;
|
|
|
|
|
+ atomic_set(&ping_host->ref, 0);
|
|
|
|
|
+ ping_host->sid = atomic_inc_return(&ping_sid);
|
|
|
if (ping_callback) {
|
|
if (ping_callback) {
|
|
|
ping_host->ping_callback = ping_callback;
|
|
ping_host->ping_callback = ping_callback;
|
|
|
} else {
|
|
} else {
|
|
|
ping_host->ping_callback = fast_ping_print_result;
|
|
ping_host->ping_callback = fast_ping_print_result;
|
|
|
}
|
|
}
|
|
|
ping_host->interval = (timeout > interval) ? timeout : interval;
|
|
ping_host->interval = (timeout > interval) ? timeout : interval;
|
|
|
- memcpy(&ping_host->addr, gai->ai_addr, gai->ai_addrlen);
|
|
|
|
|
ping_host->addr_len = gai->ai_addrlen;
|
|
ping_host->addr_len = gai->ai_addrlen;
|
|
|
-
|
|
|
|
|
- atomic_set(&ping_host->ref, 0);
|
|
|
|
|
|
|
+ if (gai->ai_addrlen > sizeof(struct sockaddr_in6)) {
|
|
|
|
|
+ goto errout;
|
|
|
|
|
+ }
|
|
|
|
|
+ memcpy(&ping_host->addr, gai->ai_addr, gai->ai_addrlen);
|
|
|
|
|
|
|
|
hostkey = hash_string(ping_host->host);
|
|
hostkey = hash_string(ping_host->host);
|
|
|
addrkey = jhash(&ping_host->addr, ping_host->addr_len, 0);
|
|
addrkey = jhash(&ping_host->addr, ping_host->addr_len, 0);
|
|
|
|
|
+ addrkey = jhash(&ping_host->sid, sizeof(ping_host->sid), addrkey);
|
|
|
pthread_mutex_lock(&ping.map_lock);
|
|
pthread_mutex_lock(&ping.map_lock);
|
|
|
_fast_ping_host_get(ping_host);
|
|
_fast_ping_host_get(ping_host);
|
|
|
hash_add(ping.hostmap, &ping_host->host_node, hostkey);
|
|
hash_add(ping.hostmap, &ping_host->host_node, hostkey);
|
|
@@ -496,7 +520,7 @@ int fast_ping_start(const char *host, int count, int timeout, fast_ping_result p
|
|
|
freeaddrinfo(gai);
|
|
freeaddrinfo(gai);
|
|
|
|
|
|
|
|
_fast_ping_sendping(ping_host);
|
|
_fast_ping_sendping(ping_host);
|
|
|
- return 0;
|
|
|
|
|
|
|
+ return ping_host;
|
|
|
errout:
|
|
errout:
|
|
|
if (fd > 0) {
|
|
if (fd > 0) {
|
|
|
close(fd);
|
|
close(fd);
|
|
@@ -510,26 +534,11 @@ errout:
|
|
|
free(ping_host);
|
|
free(ping_host);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- return -1;
|
|
|
|
|
|
|
+ return NULL;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-int fast_ping_stop(const char *host)
|
|
|
|
|
|
|
+int fast_ping_stop(struct ping_host_struct *ping_host)
|
|
|
{
|
|
{
|
|
|
- struct ping_host_struct *ping_host;
|
|
|
|
|
- uint32_t key;
|
|
|
|
|
- key = hash_string(host);
|
|
|
|
|
- pthread_mutex_lock(&ping.map_lock);
|
|
|
|
|
- hash_for_each_possible(ping.hostmap, ping_host, host_node, key)
|
|
|
|
|
- {
|
|
|
|
|
- if (strncmp(host, ping_host->host, PING_MAX_HOSTLEN) == 0) {
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- if (ping_host == NULL) {
|
|
|
|
|
- pthread_mutex_unlock(&ping.map_lock);
|
|
|
|
|
- return -1;
|
|
|
|
|
- }
|
|
|
|
|
- pthread_mutex_unlock(&ping.map_lock);
|
|
|
|
|
_fast_ping_host_put(ping_host);
|
|
_fast_ping_host_put(ping_host);
|
|
|
return 0;
|
|
return 0;
|
|
|
}
|
|
}
|
|
@@ -543,46 +552,38 @@ static void tv_sub(struct timeval *out, struct timeval *in)
|
|
|
out->tv_sec -= in->tv_sec;
|
|
out->tv_sec -= in->tv_sec;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-static int _fast_ping_icmp6_packet(struct ping_host_struct *ping_host, u_char *packet_data, int data_len, struct timeval *tvrecv)
|
|
|
|
|
|
|
+static struct fast_ping_packet *_fast_ping_icmp6_packet(struct ping_host_struct *ping_host, u_char *packet_data, int data_len)
|
|
|
{
|
|
{
|
|
|
int icmp_len;
|
|
int icmp_len;
|
|
|
struct fast_ping_packet *packet = (struct fast_ping_packet *)packet_data;
|
|
struct fast_ping_packet *packet = (struct fast_ping_packet *)packet_data;
|
|
|
struct icmp6_hdr *icmp6 = &packet->icmp6;
|
|
struct icmp6_hdr *icmp6 = &packet->icmp6;
|
|
|
- struct timeval tvresult = *tvrecv;
|
|
|
|
|
|
|
|
|
|
if (icmp6->icmp6_type != ICMP6_ECHO_REPLY) {
|
|
if (icmp6->icmp6_type != ICMP6_ECHO_REPLY) {
|
|
|
- return -1;
|
|
|
|
|
|
|
+ return NULL;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
icmp_len = data_len;
|
|
icmp_len = data_len;
|
|
|
if (icmp_len < 16) {
|
|
if (icmp_len < 16) {
|
|
|
- return -1;
|
|
|
|
|
|
|
+ return NULL;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (icmp6->icmp6_id != ping.ident) {
|
|
if (icmp6->icmp6_id != ping.ident) {
|
|
|
- return -1;
|
|
|
|
|
|
|
+ return NULL;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- struct timeval *tvsend = &packet->msg.tv;
|
|
|
|
|
- tv_sub(&tvresult, tvsend);
|
|
|
|
|
-
|
|
|
|
|
- if (ping_host->ping_callback) {
|
|
|
|
|
- ping_host->ping_callback(ping_host->host, PING_RESULT_RESPONSE, &ping_host->addr, ping_host->addr_len, ping_host->seq, &tvresult, ping_host->userptr);
|
|
|
|
|
- }
|
|
|
|
|
- return 0;
|
|
|
|
|
|
|
+ return packet;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-static int _fast_ping_icmp_packet(struct ping_host_struct *ping_host, u_char *packet_data, int data_len, struct timeval *tvrecv)
|
|
|
|
|
|
|
+static struct fast_ping_packet *_fast_ping_icmp_packet(struct ping_host_struct *ping_host, u_char *packet_data, int data_len)
|
|
|
{
|
|
{
|
|
|
struct ip *ip = (struct ip *)packet_data;
|
|
struct ip *ip = (struct ip *)packet_data;
|
|
|
struct fast_ping_packet *packet;
|
|
struct fast_ping_packet *packet;
|
|
|
struct icmp *icmp;
|
|
struct icmp *icmp;
|
|
|
- struct timeval tvresult = *tvrecv;
|
|
|
|
|
int hlen;
|
|
int hlen;
|
|
|
int icmp_len;
|
|
int icmp_len;
|
|
|
|
|
|
|
|
if (ip->ip_p != IPPROTO_ICMP) {
|
|
if (ip->ip_p != IPPROTO_ICMP) {
|
|
|
- return -1;
|
|
|
|
|
|
|
+ return NULL;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
hlen = ip->ip_hl << 2;
|
|
hlen = ip->ip_hl << 2;
|
|
@@ -591,84 +592,56 @@ static int _fast_ping_icmp_packet(struct ping_host_struct *ping_host, u_char *pa
|
|
|
icmp_len = data_len - hlen;
|
|
icmp_len = data_len - hlen;
|
|
|
|
|
|
|
|
if (icmp_len < 16) {
|
|
if (icmp_len < 16) {
|
|
|
- return -1;
|
|
|
|
|
|
|
+ return NULL;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (icmp->icmp_type != ICMP_ECHOREPLY) {
|
|
if (icmp->icmp_type != ICMP_ECHOREPLY) {
|
|
|
- return -1;
|
|
|
|
|
|
|
+ return NULL;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (icmp->icmp_id != ping.ident) {
|
|
if (icmp->icmp_id != ping.ident) {
|
|
|
- return -1;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- struct timeval *tvsend = &packet->msg.tv;
|
|
|
|
|
- tv_sub(&tvresult, tvsend);
|
|
|
|
|
- if (ping_host->ping_callback) {
|
|
|
|
|
- ping_host->ping_callback(ping_host->host, PING_RESULT_RESPONSE, &ping_host->addr, ping_host->addr_len, ping_host->seq, &tvresult, ping_host->userptr);
|
|
|
|
|
|
|
+ return NULL;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- return 0;
|
|
|
|
|
|
|
+ return packet;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-static int _fast_ping_recvping(struct ping_host_struct *ping_host, u_char *inpacket, int len, struct timeval *tvrecv)
|
|
|
|
|
|
|
+struct fast_ping_packet *_fast_ping_recv_packet(struct ping_host_struct *ping_host, u_char *inpacket, int len, struct timeval *tvrecv)
|
|
|
{
|
|
{
|
|
|
|
|
+ struct fast_ping_packet *packet = NULL;
|
|
|
|
|
|
|
|
- if (ping_host->type == AF_INET6) {
|
|
|
|
|
- if (_fast_ping_icmp6_packet(ping_host, inpacket, len, tvrecv)) {
|
|
|
|
|
|
|
+ if (ping_host->type == FAST_PING_ICMP6) {
|
|
|
|
|
+ packet = _fast_ping_icmp6_packet(ping_host, inpacket, len);
|
|
|
|
|
+ if (packet == NULL) {
|
|
|
goto errout;
|
|
goto errout;
|
|
|
}
|
|
}
|
|
|
- } else if (ping_host->type == AF_INET) {
|
|
|
|
|
- if (_fast_ping_icmp_packet(ping_host, inpacket, len, tvrecv)) {
|
|
|
|
|
|
|
+ } else if (ping_host->type == FAST_PING_ICMP) {
|
|
|
|
|
+ packet = _fast_ping_icmp_packet(ping_host, inpacket, len);
|
|
|
|
|
+ if (packet == NULL) {
|
|
|
goto errout;
|
|
goto errout;
|
|
|
}
|
|
}
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return 0;
|
|
|
|
|
-errout:
|
|
|
|
|
- return -1;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-#if 0
|
|
|
|
|
-static int _fast_ping_gethost_by_addr(char *host, struct sockaddr *addr, socklen_t addr_len)
|
|
|
|
|
-{
|
|
|
|
|
- struct sockaddr_storage *addr_store = (struct sockaddr_storage *)addr;
|
|
|
|
|
- host[0] = 0;
|
|
|
|
|
- switch (addr_store->ss_family) {
|
|
|
|
|
- case AF_INET: {
|
|
|
|
|
- struct sockaddr_in *addr_in;
|
|
|
|
|
- addr_in = (struct sockaddr_in *)addr;
|
|
|
|
|
- inet_ntop(AF_INET, &addr_in->sin_addr, host, addr_len);
|
|
|
|
|
- } break;
|
|
|
|
|
- case AF_INET6: {
|
|
|
|
|
- struct sockaddr_in6 *addr_in6;
|
|
|
|
|
- addr_in6 = (struct sockaddr_in6 *)addr;
|
|
|
|
|
- if (IN6_IS_ADDR_V4MAPPED(&addr_in6->sin6_addr)) {
|
|
|
|
|
- struct sockaddr_in addr_in4;
|
|
|
|
|
- memset(&addr_in4, 0, sizeof(addr_in4));
|
|
|
|
|
- memcpy(&addr_in4.sin_addr.s_addr, addr_in6->sin6_addr.s6_addr + 12, sizeof(addr_in4.sin_addr.s_addr));
|
|
|
|
|
- } else {
|
|
|
|
|
- inet_ntop(AF_INET6, &addr_in6->sin6_addr, host, addr_len);
|
|
|
|
|
- }
|
|
|
|
|
- } break;
|
|
|
|
|
- default:
|
|
|
|
|
|
|
+ } else {
|
|
|
goto errout;
|
|
goto errout;
|
|
|
- break;
|
|
|
|
|
}
|
|
}
|
|
|
- return 0;
|
|
|
|
|
|
|
+
|
|
|
|
|
+ return packet;
|
|
|
errout:
|
|
errout:
|
|
|
- return -1;
|
|
|
|
|
|
|
+ return NULL;
|
|
|
}
|
|
}
|
|
|
-#endif
|
|
|
|
|
|
|
|
|
|
-static int _fast_ping_process(struct ping_host_struct *ping_host, struct timeval *now)
|
|
|
|
|
|
|
+static int _fast_ping_process_icmp(struct ping_host_struct *ping_host, struct timeval *now)
|
|
|
{
|
|
{
|
|
|
int len;
|
|
int len;
|
|
|
u_char inpacket[ICMP_INPACKET_SIZE];
|
|
u_char inpacket[ICMP_INPACKET_SIZE];
|
|
|
struct sockaddr_storage from;
|
|
struct sockaddr_storage from;
|
|
|
struct ping_host_struct *recv_ping_host;
|
|
struct ping_host_struct *recv_ping_host;
|
|
|
|
|
+ struct fast_ping_packet *packet = NULL;
|
|
|
socklen_t from_len = sizeof(from);
|
|
socklen_t from_len = sizeof(from);
|
|
|
uint32_t addrkey;
|
|
uint32_t addrkey;
|
|
|
|
|
+ struct timeval tvresult = *now;
|
|
|
|
|
+ struct timeval *tvsend = NULL;
|
|
|
|
|
+ unsigned int sid;
|
|
|
|
|
+ unsigned int seq;
|
|
|
|
|
|
|
|
len = recvfrom(ping_host->fd, inpacket, sizeof(inpacket), 0, (struct sockaddr *)&from, (socklen_t *)&from_len);
|
|
len = recvfrom(ping_host->fd, inpacket, sizeof(inpacket), 0, (struct sockaddr *)&from, (socklen_t *)&from_len);
|
|
|
if (len < 0) {
|
|
if (len < 0) {
|
|
@@ -676,11 +649,21 @@ static int _fast_ping_process(struct ping_host_struct *ping_host, struct timeval
|
|
|
goto errout;
|
|
goto errout;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ packet = _fast_ping_recv_packet(ping_host, inpacket, len, now);
|
|
|
|
|
+ if (packet == NULL) {
|
|
|
|
|
+ tlog(TLOG_ERROR, "recv ping packet failed.");
|
|
|
|
|
+ goto errout;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
addrkey = jhash(&from, from_len, 0);
|
|
addrkey = jhash(&from, from_len, 0);
|
|
|
|
|
+ tvsend = &packet->msg.tv;
|
|
|
|
|
+ sid = packet->msg.sid;
|
|
|
|
|
+ seq = packet->msg.seq;
|
|
|
|
|
+ addrkey = jhash(&sid, sizeof(sid), addrkey);
|
|
|
pthread_mutex_lock(&ping.map_lock);
|
|
pthread_mutex_lock(&ping.map_lock);
|
|
|
hash_for_each_possible(ping.addrmap, recv_ping_host, addr_node, addrkey)
|
|
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) {
|
|
|
|
|
|
|
+ if (recv_ping_host->addr_len == from_len && memcmp(&recv_ping_host->addr, &from, from_len) == 0 && recv_ping_host->sid == sid) {
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -690,13 +673,19 @@ static int _fast_ping_process(struct ping_host_struct *ping_host, struct timeval
|
|
|
return -1;
|
|
return -1;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- recv_ping_host->send = 0;
|
|
|
|
|
-
|
|
|
|
|
- _fast_ping_recvping(recv_ping_host, inpacket, len, now);
|
|
|
|
|
|
|
+ if (recv_ping_host->seq != seq) {
|
|
|
|
|
+ tlog(TLOG_ERROR, "seq num mismatch, expect %u, real %u", recv_ping_host->seq, seq);
|
|
|
|
|
+ return -1;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- if (recv_ping_host->count >= 0) {
|
|
|
|
|
- recv_ping_host->count--;
|
|
|
|
|
|
|
+ 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, &tvresult, recv_ping_host->userptr);
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ recv_ping_host->send = 0;
|
|
|
|
|
+
|
|
|
if (recv_ping_host->count == 0) {
|
|
if (recv_ping_host->count == 0) {
|
|
|
_fast_ping_host_put(recv_ping_host);
|
|
_fast_ping_host_put(recv_ping_host);
|
|
|
}
|
|
}
|
|
@@ -705,6 +694,22 @@ errout:
|
|
|
return -1;
|
|
return -1;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+static int _fast_ping_process(struct ping_host_struct *ping_host, struct timeval *now)
|
|
|
|
|
+{
|
|
|
|
|
+ int ret = -1;
|
|
|
|
|
+
|
|
|
|
|
+ switch (ping_host->type) {
|
|
|
|
|
+ case FAST_PING_ICMP6:
|
|
|
|
|
+ case FAST_PING_ICMP:
|
|
|
|
|
+ ret = _fast_ping_process_icmp(ping_host, now);
|
|
|
|
|
+ break;
|
|
|
|
|
+ default:
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return ret;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
static void _fast_ping_period_run()
|
|
static void _fast_ping_period_run()
|
|
|
{
|
|
{
|
|
|
struct ping_host_struct *ping_host;
|
|
struct ping_host_struct *ping_host;
|
|
@@ -722,7 +727,8 @@ static void _fast_ping_period_run()
|
|
|
tv_sub(&interval, &ping_host->last);
|
|
tv_sub(&interval, &ping_host->last);
|
|
|
millisecond = interval.tv_sec * 1000 + interval.tv_usec / 1000;
|
|
millisecond = interval.tv_sec * 1000 + interval.tv_usec / 1000;
|
|
|
if (millisecond > ping_host->timeout && ping_host->send == 1) {
|
|
if (millisecond > ping_host->timeout && ping_host->send == 1) {
|
|
|
- ping_host->ping_callback(ping_host->host, PING_RESULT_TIMEOUT, &ping_host->addr, ping_host->addr_len, ping_host->seq, &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, &interval,
|
|
|
|
|
+ ping_host->userptr);
|
|
|
ping_host->send = 0;
|
|
ping_host->send = 0;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -806,19 +812,18 @@ int fast_ping_init()
|
|
|
goto errout;
|
|
goto errout;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- ping.run = 1;
|
|
|
|
|
- ret = pthread_create(&ping.tid, &attr, _fast_ping_work, NULL);
|
|
|
|
|
- if (ret != 0) {
|
|
|
|
|
- fprintf(stderr, "create ping work thread failed, %s\n", strerror(errno));
|
|
|
|
|
- goto errout;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
pthread_mutex_init(&ping.map_lock, 0);
|
|
pthread_mutex_init(&ping.map_lock, 0);
|
|
|
pthread_mutex_init(&ping.lock, 0);
|
|
pthread_mutex_init(&ping.lock, 0);
|
|
|
hash_init(ping.hostmap);
|
|
hash_init(ping.hostmap);
|
|
|
hash_init(ping.addrmap);
|
|
hash_init(ping.addrmap);
|
|
|
ping.epoll_fd = epollfd;
|
|
ping.epoll_fd = epollfd;
|
|
|
ping.ident = getpid();
|
|
ping.ident = getpid();
|
|
|
|
|
+ ping.run = 1;
|
|
|
|
|
+ ret = pthread_create(&ping.tid, &attr, _fast_ping_work, NULL);
|
|
|
|
|
+ if (ret != 0) {
|
|
|
|
|
+ fprintf(stderr, "create ping work thread failed, %s\n", strerror(errno));
|
|
|
|
|
+ goto errout;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
|
errout:
|
|
errout:
|