New upstream version 2.3
This commit is contained in:
parent
c845af032a
commit
5c6ba24b61
129 changed files with 14313 additions and 2999 deletions
|
@ -55,8 +55,10 @@ EXTRA_PROGRAMS = pst3$(EXEEXT)
|
|||
subdir = plugins-root
|
||||
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/m4/np_mysqlclient.m4 \
|
||||
$(top_srcdir)/gl/m4/00gnulib.m4 $(top_srcdir)/gl/m4/alloca.m4 \
|
||||
am__aclocal_m4_deps = $(top_srcdir)/m4/libcurl.m4 \
|
||||
$(top_srcdir)/m4/np_mysqlclient.m4 \
|
||||
$(top_srcdir)/m4/uriparser.m4 $(top_srcdir)/gl/m4/00gnulib.m4 \
|
||||
$(top_srcdir)/gl/m4/alloca.m4 \
|
||||
$(top_srcdir)/gl/m4/arpa_inet_h.m4 \
|
||||
$(top_srcdir)/gl/m4/base64.m4 $(top_srcdir)/gl/m4/btowc.m4 \
|
||||
$(top_srcdir)/gl/m4/codeset.m4 \
|
||||
|
@ -913,6 +915,11 @@ LD = @LD@
|
|||
LDAPINCLUDE = @LDAPINCLUDE@
|
||||
LDAPLIBS = @LDAPLIBS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LIBCURL = @LIBCURL@
|
||||
LIBCURLCFLAGS = @LIBCURLCFLAGS@
|
||||
LIBCURLINCLUDE = @LIBCURLINCLUDE@
|
||||
LIBCURLLIBS = @LIBCURLLIBS@
|
||||
LIBCURL_CPPFLAGS = @LIBCURL_CPPFLAGS@
|
||||
LIBGNU_LIBDEPS = @LIBGNU_LIBDEPS@
|
||||
LIBGNU_LTLIBDEPS = @LIBGNU_LTLIBDEPS@
|
||||
LIBICONV = @LIBICONV@
|
||||
|
@ -1038,6 +1045,7 @@ PERL = @PERL@
|
|||
PERLMODS_DIR = @PERLMODS_DIR@
|
||||
PGINCLUDE = @PGINCLUDE@
|
||||
PGLIBS = @PGLIBS@
|
||||
PKGCONFIG = @PKGCONFIG@
|
||||
PKG_ARCH = @PKG_ARCH@
|
||||
PLUGIN_TEST = @PLUGIN_TEST@
|
||||
POSUB = @POSUB@
|
||||
|
@ -1255,6 +1263,11 @@ TIME_H_DEFINES_STRUCT_TIMESPEC = @TIME_H_DEFINES_STRUCT_TIMESPEC@
|
|||
UNDEFINE_STRTOK_R = @UNDEFINE_STRTOK_R@
|
||||
UNISTD_H_HAVE_WINSOCK2_H = @UNISTD_H_HAVE_WINSOCK2_H@
|
||||
UNISTD_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS = @UNISTD_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS@
|
||||
URIPARSER = @URIPARSER@
|
||||
URIPARSERCFLAGS = @URIPARSERCFLAGS@
|
||||
URIPARSERINCLUDE = @URIPARSERINCLUDE@
|
||||
URIPARSERLIBS = @URIPARSERLIBS@
|
||||
URIPARSER_CPPFLAGS = @URIPARSER_CPPFLAGS@
|
||||
USE_NLS = @USE_NLS@
|
||||
VERSION = @VERSION@
|
||||
WARRANTY = @WARRANTY@
|
||||
|
@ -1265,6 +1278,7 @@ WTSAPI32LIBS = @WTSAPI32LIBS@
|
|||
XGETTEXT = @XGETTEXT@
|
||||
XGETTEXT_015 = @XGETTEXT_015@
|
||||
XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
|
||||
_libcurl_config = @_libcurl_config@
|
||||
abs_builddir = @abs_builddir@
|
||||
abs_srcdir = @abs_srcdir@
|
||||
abs_top_builddir = @abs_top_builddir@
|
||||
|
|
|
@ -323,7 +323,8 @@ int get_hardware_address(int sock,char *interface_name){
|
|||
#elif defined(__bsd__)
|
||||
/* King 2004 see ACKNOWLEDGEMENTS */
|
||||
|
||||
int mib[6], len;
|
||||
size_t len;
|
||||
int mib[6];
|
||||
char *buf;
|
||||
unsigned char *ptr;
|
||||
struct if_msghdr *ifm;
|
||||
|
@ -693,7 +694,7 @@ int receive_dhcp_packet(void *buffer, int buffer_size, int sock, int timeout, st
|
|||
else{
|
||||
bzero(&source_address,sizeof(source_address));
|
||||
address_size=sizeof(source_address);
|
||||
recv_result=recvfrom(sock,(char *)buffer,buffer_size,MSG_PEEK,(struct sockaddr *)&source_address,&address_size);
|
||||
recv_result=recvfrom(sock,(char *)buffer,buffer_size,0,(struct sockaddr *)&source_address,&address_size);
|
||||
if(verbose)
|
||||
printf("recv_result: %d\n",recv_result);
|
||||
|
||||
|
|
|
@ -67,7 +67,9 @@ const char *email = "devel@monitoring-plugins.org";
|
|||
#include <netinet/in_systm.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip6.h>
|
||||
#include <netinet/ip_icmp.h>
|
||||
#include <netinet/icmp6.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <signal.h>
|
||||
#include <float.h>
|
||||
|
@ -113,8 +115,8 @@ typedef struct rta_host {
|
|||
unsigned short id; /* id in **table, and icmp pkts */
|
||||
char *name; /* arg used for adding this host */
|
||||
char *msg; /* icmp error message, if any */
|
||||
struct sockaddr_in saddr_in; /* the address of this host */
|
||||
struct in_addr error_addr; /* stores address of error replies */
|
||||
struct sockaddr_storage saddr_in; /* the address of this host */
|
||||
struct sockaddr_storage error_addr; /* stores address of error replies */
|
||||
unsigned long long time_waited; /* total time waited, in usecs */
|
||||
unsigned int icmp_sent, icmp_recv, icmp_lost; /* counters */
|
||||
unsigned char icmp_type, icmp_code; /* type and code from errors */
|
||||
|
@ -140,6 +142,18 @@ typedef struct icmp_ping_data {
|
|||
unsigned short ping_id;
|
||||
} icmp_ping_data;
|
||||
|
||||
typedef union ip_hdr {
|
||||
struct ip ip;
|
||||
struct ip6_hdr ip6;
|
||||
} ip_hdr;
|
||||
|
||||
typedef union icmp_packet {
|
||||
void *buf;
|
||||
struct icmp *icp;
|
||||
struct icmp6_hdr *icp6;
|
||||
u_short *cksum_in;
|
||||
} icmp_packet;
|
||||
|
||||
/* the different modes of this program are as follows:
|
||||
* MODE_RTA: send all packets no matter what (mimic check_icmp and check_ping)
|
||||
* MODE_HOSTCHECK: Return immediately upon any sign of life
|
||||
|
@ -190,8 +204,9 @@ static int get_threshold(char *str, threshold *th);
|
|||
static void run_checks(void);
|
||||
static void set_source_ip(char *);
|
||||
static int add_target(char *);
|
||||
static int add_target_ip(char *, struct in_addr *);
|
||||
static int handle_random_icmp(unsigned char *, struct sockaddr_in *);
|
||||
static int add_target_ip(char *, struct sockaddr_storage *);
|
||||
static int handle_random_icmp(unsigned char *, struct sockaddr_storage *);
|
||||
static void parse_address(struct sockaddr_storage *, char *, int);
|
||||
static unsigned short icmp_checksum(unsigned short *, int);
|
||||
static void finish(int);
|
||||
static void crash(const char *, ...);
|
||||
|
@ -300,7 +315,7 @@ get_icmp_error_msg(unsigned char icmp_type, unsigned char icmp_code)
|
|||
}
|
||||
|
||||
static int
|
||||
handle_random_icmp(unsigned char *packet, struct sockaddr_in *addr)
|
||||
handle_random_icmp(unsigned char *packet, struct sockaddr_storage *addr)
|
||||
{
|
||||
struct icmp p, sent_icmp;
|
||||
struct rta_host *host = NULL;
|
||||
|
@ -342,9 +357,11 @@ handle_random_icmp(unsigned char *packet, struct sockaddr_in *addr)
|
|||
/* it is indeed a response for us */
|
||||
host = table[ntohs(sent_icmp.icmp_seq)/packets];
|
||||
if(debug) {
|
||||
char address[INET6_ADDRSTRLEN];
|
||||
parse_address(addr, address, sizeof(address));
|
||||
printf("Received \"%s\" from %s for ICMP ECHO sent to %s.\n",
|
||||
get_icmp_error_msg(p.icmp_type, p.icmp_code),
|
||||
inet_ntoa(addr->sin_addr), host->name);
|
||||
get_icmp_error_msg(p.icmp_type, p.icmp_code),
|
||||
address, host->name);
|
||||
}
|
||||
|
||||
icmp_lost++;
|
||||
|
@ -364,11 +381,23 @@ handle_random_icmp(unsigned char *packet, struct sockaddr_in *addr)
|
|||
}
|
||||
host->icmp_type = p.icmp_type;
|
||||
host->icmp_code = p.icmp_code;
|
||||
host->error_addr.s_addr = addr->sin_addr.s_addr;
|
||||
host->error_addr = *addr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void parse_address(struct sockaddr_storage *addr, char *address, int size)
|
||||
{
|
||||
switch (address_family) {
|
||||
case AF_INET:
|
||||
inet_ntop(address_family, &((struct sockaddr_in *)addr)->sin_addr, address, size);
|
||||
break;
|
||||
case AF_INET6:
|
||||
inet_ntop(address_family, &((struct sockaddr_in6 *)addr)->sin6_addr, address, size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
|
@ -381,6 +410,7 @@ main(int argc, char **argv)
|
|||
#ifdef SO_TIMESTAMP
|
||||
int on = 1;
|
||||
#endif
|
||||
char * opts_str = "vhVw:c:n:p:t:H:s:i:b:I:l:m:64";
|
||||
|
||||
setlocale (LC_ALL, "");
|
||||
bindtextdomain (PACKAGE, LOCALEDIR);
|
||||
|
@ -390,33 +420,8 @@ main(int argc, char **argv)
|
|||
* that before pointer magic (esp. on network data) */
|
||||
icmp_sockerrno = udp_sockerrno = tcp_sockerrno = sockets = 0;
|
||||
|
||||
if((icmp_sock = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP)) != -1)
|
||||
sockets |= HAVE_ICMP;
|
||||
else icmp_sockerrno = errno;
|
||||
|
||||
/* if((udp_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) != -1) */
|
||||
/* sockets |= HAVE_UDP; */
|
||||
/* else udp_sockerrno = errno; */
|
||||
|
||||
/* if((tcp_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) != -1) */
|
||||
/* sockets |= HAVE_TCP; */
|
||||
/* else tcp_sockerrno = errno; */
|
||||
|
||||
/* now drop privileges (no effect if not setsuid or geteuid() == 0) */
|
||||
setuid(getuid());
|
||||
|
||||
#ifdef SO_TIMESTAMP
|
||||
if(setsockopt(icmp_sock, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on)))
|
||||
if(debug) printf("Warning: no SO_TIMESTAMP support\n");
|
||||
#endif // SO_TIMESTAMP
|
||||
|
||||
/* POSIXLY_CORRECT might break things, so unset it (the portable way) */
|
||||
environ = NULL;
|
||||
|
||||
/* use the pid to mark packets as ours */
|
||||
/* Some systems have 32-bit pid_t so mask off only 16 bits */
|
||||
pid = getpid() & 0xffff;
|
||||
/* printf("pid = %u\n", pid); */
|
||||
address_family = -1;
|
||||
int icmp_proto = IPPROTO_ICMP;
|
||||
|
||||
/* get calling name the old-fashioned way for portability instead
|
||||
* of relying on the glibc-ism __progname */
|
||||
|
@ -456,20 +461,35 @@ main(int argc, char **argv)
|
|||
packets = 5;
|
||||
}
|
||||
|
||||
/* Parse extra opts if any */
|
||||
argv=np_extra_opts(&argc, argv, progname);
|
||||
|
||||
/* support "--help" and "--version" */
|
||||
if(argc == 2) {
|
||||
if(!strcmp(argv[1], "--help"))
|
||||
strcpy(argv[1], "-h");
|
||||
if(!strcmp(argv[1], "--version"))
|
||||
strcpy(argv[1], "-V");
|
||||
/* Parse protocol arguments first */
|
||||
for(i = 1; i < argc; i++) {
|
||||
while((arg = getopt(argc, argv, opts_str)) != EOF) {
|
||||
unsigned short size;
|
||||
switch(arg) {
|
||||
case '4':
|
||||
if (address_family != -1)
|
||||
crash("Multiple protocol versions not supported");
|
||||
address_family = AF_INET;
|
||||
break;
|
||||
case '6':
|
||||
#ifdef USE_IPV6
|
||||
if (address_family != -1)
|
||||
crash("Multiple protocol versions not supported");
|
||||
address_family = AF_INET6;
|
||||
#else
|
||||
usage (_("IPv6 support not available\n"));
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset argument scanning */
|
||||
optind = 1;
|
||||
|
||||
/* parse the arguments */
|
||||
for(i = 1; i < argc; i++) {
|
||||
while((arg = getopt(argc, argv, "vhVw:c:n:p:t:H:s:i:b:I:l:m:")) != EOF) {
|
||||
while((arg = getopt(argc, argv, opts_str)) != EOF) {
|
||||
unsigned short size;
|
||||
switch(arg) {
|
||||
case 'v':
|
||||
|
@ -530,10 +550,30 @@ main(int argc, char **argv)
|
|||
case 'h': /* help */
|
||||
print_help ();
|
||||
exit (STATE_UNKNOWN);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* POSIXLY_CORRECT might break things, so unset it (the portable way) */
|
||||
environ = NULL;
|
||||
|
||||
/* use the pid to mark packets as ours */
|
||||
/* Some systems have 32-bit pid_t so mask off only 16 bits */
|
||||
pid = getpid() & 0xffff;
|
||||
/* printf("pid = %u\n", pid); */
|
||||
|
||||
/* Parse extra opts if any */
|
||||
argv=np_extra_opts(&argc, argv, progname);
|
||||
|
||||
/* support "--help" and "--version" */
|
||||
if(argc == 2) {
|
||||
if(!strcmp(argv[1], "--help"))
|
||||
strcpy(argv[1], "-h");
|
||||
if(!strcmp(argv[1], "--version"))
|
||||
strcpy(argv[1], "-V");
|
||||
}
|
||||
|
||||
argv = &argv[optind];
|
||||
while(*argv) {
|
||||
add_target(*argv);
|
||||
|
@ -545,6 +585,30 @@ main(int argc, char **argv)
|
|||
exit(3);
|
||||
}
|
||||
|
||||
// add_target might change address_family
|
||||
switch ( address_family ){
|
||||
case AF_INET: icmp_proto = IPPROTO_ICMP;
|
||||
break;
|
||||
case AF_INET6: icmp_proto = IPPROTO_ICMPV6;
|
||||
break;
|
||||
default: crash("Address family not supported");
|
||||
}
|
||||
if((icmp_sock = socket(address_family, SOCK_RAW, icmp_proto)) != -1)
|
||||
sockets |= HAVE_ICMP;
|
||||
else icmp_sockerrno = errno;
|
||||
|
||||
|
||||
#ifdef SO_TIMESTAMP
|
||||
if(setsockopt(icmp_sock, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on)))
|
||||
if(debug) printf("Warning: no SO_TIMESTAMP support\n");
|
||||
#endif // SO_TIMESTAMP
|
||||
|
||||
/* now drop privileges (no effect if not setsuid or geteuid() == 0) */
|
||||
if (setuid(getuid()) == -1) {
|
||||
printf("ERROR: Failed to drop privileges\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(!sockets) {
|
||||
if(icmp_sock == -1) {
|
||||
errno = icmp_sockerrno;
|
||||
|
@ -608,7 +672,7 @@ main(int argc, char **argv)
|
|||
if(max_completion_time > (u_int)timeout * 1000000) {
|
||||
printf("max_completion_time: %llu timeout: %u\n",
|
||||
max_completion_time, timeout);
|
||||
printf("Timout must be at lest %llu\n",
|
||||
printf("Timeout must be at least %llu\n",
|
||||
max_completion_time / 1000000 + 1);
|
||||
}
|
||||
}
|
||||
|
@ -633,7 +697,7 @@ main(int argc, char **argv)
|
|||
}
|
||||
|
||||
host = list;
|
||||
table = malloc(sizeof(struct rta_host **) * targets);
|
||||
table = (struct rta_host**)malloc(sizeof(struct rta_host **) * targets);
|
||||
i = 0;
|
||||
while(host) {
|
||||
host->id = i*packets;
|
||||
|
@ -697,9 +761,15 @@ run_checks()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/* response structure:
|
||||
* IPv4:
|
||||
* ip header : 20 bytes
|
||||
* icmp header : 28 bytes
|
||||
* IPv6:
|
||||
* ip header : 40 bytes
|
||||
* icmp header : 28 bytes
|
||||
* both:
|
||||
* icmp echo reply : the rest
|
||||
*/
|
||||
static int
|
||||
|
@ -707,16 +777,27 @@ wait_for_reply(int sock, u_int t)
|
|||
{
|
||||
int n, hlen;
|
||||
static unsigned char buf[4096];
|
||||
struct sockaddr_in resp_addr;
|
||||
struct ip *ip;
|
||||
struct icmp icp;
|
||||
struct sockaddr_storage resp_addr;
|
||||
union ip_hdr *ip;
|
||||
union icmp_packet packet;
|
||||
struct rta_host *host;
|
||||
struct icmp_ping_data data;
|
||||
struct timeval wait_start, now;
|
||||
u_int tdiff, i, per_pkt_wait;
|
||||
|
||||
if (!(packet.buf = malloc(icmp_pkt_size))) {
|
||||
crash("send_icmp_ping(): failed to malloc %d bytes for send buffer",
|
||||
icmp_pkt_size);
|
||||
return -1; /* might be reached if we're in debug mode */
|
||||
}
|
||||
|
||||
memset(packet.buf, 0, icmp_pkt_size);
|
||||
|
||||
/* if we can't listen or don't have anything to listen to, just return */
|
||||
if(!t || !icmp_pkts_en_route) return 0;
|
||||
if(!t || !icmp_pkts_en_route) {
|
||||
free(packet.buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
gettimeofday(&wait_start, &tz);
|
||||
|
||||
|
@ -735,7 +816,7 @@ wait_for_reply(int sock, u_int t)
|
|||
|
||||
/* reap responses until we hit a timeout */
|
||||
n = recvfrom_wto(sock, buf, sizeof(buf),
|
||||
(struct sockaddr *)&resp_addr, &t, &now);
|
||||
(struct sockaddr *)&resp_addr, &t, &now);
|
||||
if(!n) {
|
||||
if(debug > 1) {
|
||||
printf("recvfrom_wto() timed out during a %u usecs wait\n",
|
||||
|
@ -745,12 +826,23 @@ wait_for_reply(int sock, u_int t)
|
|||
}
|
||||
if(n < 0) {
|
||||
if(debug) printf("recvfrom_wto() returned errors\n");
|
||||
free(packet.buf);
|
||||
return n;
|
||||
}
|
||||
|
||||
ip = (struct ip *)buf;
|
||||
if(debug > 1) printf("received %u bytes from %s\n",
|
||||
ntohs(ip->ip_len), inet_ntoa(resp_addr.sin_addr));
|
||||
// FIXME: with ipv6 we don't have an ip header here
|
||||
if (address_family != AF_INET6) {
|
||||
ip = (union ip_hdr *)buf;
|
||||
|
||||
if(debug > 1) {
|
||||
char address[INET6_ADDRSTRLEN];
|
||||
parse_address(&resp_addr, address, sizeof(address));
|
||||
printf("received %u bytes from %s\n",
|
||||
address_family == AF_INET6 ? ntohs(ip->ip6.ip6_plen)
|
||||
: ntohs(ip->ip.ip_len),
|
||||
address);
|
||||
}
|
||||
}
|
||||
|
||||
/* obsolete. alpha on tru64 provides the necessary defines, but isn't broken */
|
||||
/* #if defined( __alpha__ ) && __STDC__ && !defined( __GLIBC__ ) */
|
||||
|
@ -759,12 +851,14 @@ wait_for_reply(int sock, u_int t)
|
|||
* off the bottom 4 bits */
|
||||
/* hlen = (ip->ip_vhl & 0x0f) << 2; */
|
||||
/* #else */
|
||||
hlen = ip->ip_hl << 2;
|
||||
hlen = (address_family == AF_INET6) ? 0 : ip->ip.ip_hl << 2;
|
||||
/* #endif */
|
||||
|
||||
if(n < (hlen + ICMP_MINLEN)) {
|
||||
char address[INET6_ADDRSTRLEN];
|
||||
parse_address(&resp_addr, address, sizeof(address));
|
||||
crash("received packet too short for ICMP (%d bytes, expected %d) from %s\n",
|
||||
n, hlen + icmp_pkt_size, inet_ntoa(resp_addr.sin_addr));
|
||||
n, hlen + icmp_pkt_size, address);
|
||||
}
|
||||
/* else if(debug) { */
|
||||
/* printf("ip header size: %u, packet size: %u (expected %u, %u)\n", */
|
||||
|
@ -773,23 +867,39 @@ wait_for_reply(int sock, u_int t)
|
|||
/* } */
|
||||
|
||||
/* check the response */
|
||||
memcpy(&icp, buf + hlen, sizeof(icp));
|
||||
|
||||
if(ntohs(icp.icmp_id) != pid || icp.icmp_type != ICMP_ECHOREPLY ||
|
||||
ntohs(icp.icmp_seq) >= targets*packets) {
|
||||
memcpy(packet.buf, buf + hlen, icmp_pkt_size);
|
||||
/* address_family == AF_INET6 ? sizeof(struct icmp6_hdr)
|
||||
: sizeof(struct icmp));*/
|
||||
|
||||
if( (address_family == PF_INET &&
|
||||
(ntohs(packet.icp->icmp_id) != pid || packet.icp->icmp_type != ICMP_ECHOREPLY
|
||||
|| ntohs(packet.icp->icmp_seq) >= targets * packets))
|
||||
|| (address_family == PF_INET6 &&
|
||||
(ntohs(packet.icp6->icmp6_id) != pid || packet.icp6->icmp6_type != ICMP6_ECHO_REPLY
|
||||
|| ntohs(packet.icp6->icmp6_seq) >= targets * packets))) {
|
||||
if(debug > 2) printf("not a proper ICMP_ECHOREPLY\n");
|
||||
handle_random_icmp(buf + hlen, &resp_addr);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* this is indeed a valid response */
|
||||
memcpy(&data, icp.icmp_data, sizeof(data));
|
||||
if (debug > 2)
|
||||
printf("ICMP echo-reply of len %lu, id %u, seq %u, cksum 0x%X\n",
|
||||
(unsigned long)sizeof(data), ntohs(icp.icmp_id),
|
||||
ntohs(icp.icmp_seq), icp.icmp_cksum);
|
||||
if (address_family == PF_INET) {
|
||||
memcpy(&data, packet.icp->icmp_data, sizeof(data));
|
||||
if (debug > 2)
|
||||
printf("ICMP echo-reply of len %lu, id %u, seq %u, cksum 0x%X\n",
|
||||
(unsigned long)sizeof(data), ntohs(packet.icp->icmp_id),
|
||||
ntohs(packet.icp->icmp_seq), packet.icp->icmp_cksum);
|
||||
host = table[ntohs(packet.icp->icmp_seq)/packets];
|
||||
} else {
|
||||
memcpy(&data, &packet.icp6->icmp6_dataun.icmp6_un_data8[4], sizeof(data));
|
||||
if (debug > 2)
|
||||
printf("ICMP echo-reply of len %lu, id %u, seq %u, cksum 0x%X\n",
|
||||
(unsigned long)sizeof(data), ntohs(packet.icp6->icmp6_id),
|
||||
ntohs(packet.icp6->icmp6_seq), packet.icp6->icmp6_cksum);
|
||||
host = table[ntohs(packet.icp6->icmp6_seq)/packets];
|
||||
}
|
||||
|
||||
host = table[ntohs(icp.icmp_seq)/packets];
|
||||
tdiff = get_timevaldiff(&data.stime, &now);
|
||||
|
||||
host->time_waited += tdiff;
|
||||
|
@ -801,22 +911,25 @@ wait_for_reply(int sock, u_int t)
|
|||
host->rtmin = tdiff;
|
||||
|
||||
if(debug) {
|
||||
char address[INET6_ADDRSTRLEN];
|
||||
parse_address(&resp_addr, address, sizeof(address));
|
||||
printf("%0.3f ms rtt from %s, outgoing ttl: %u, incoming ttl: %u, max: %0.3f, min: %0.3f\n",
|
||||
(float)tdiff / 1000, inet_ntoa(resp_addr.sin_addr),
|
||||
ttl, ip->ip_ttl, (float)host->rtmax / 1000, (float)host->rtmin / 1000);
|
||||
(float)tdiff / 1000, address,
|
||||
ttl, ip->ip.ip_ttl, (float)host->rtmax / 1000, (float)host->rtmin / 1000);
|
||||
}
|
||||
|
||||
/* if we're in hostcheck mode, exit with limited printouts */
|
||||
if(mode == MODE_HOSTCHECK) {
|
||||
printf("OK - %s responds to ICMP. Packet %u, rta %0.3fms|"
|
||||
"pkt=%u;;0;%u rta=%0.3f;%0.3f;%0.3f;;\n",
|
||||
host->name, icmp_recv, (float)tdiff / 1000,
|
||||
icmp_recv, packets, (float)tdiff / 1000,
|
||||
(float)warn.rta / 1000, (float)crit.rta / 1000);
|
||||
"pkt=%u;;0;%u rta=%0.3f;%0.3f;%0.3f;;\n",
|
||||
host->name, icmp_recv, (float)tdiff / 1000,
|
||||
icmp_recv, packets, (float)tdiff / 1000,
|
||||
(float)warn.rta / 1000, (float)crit.rta / 1000);
|
||||
exit(STATE_OK);
|
||||
}
|
||||
}
|
||||
|
||||
free(packet.buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -824,62 +937,81 @@ wait_for_reply(int sock, u_int t)
|
|||
static int
|
||||
send_icmp_ping(int sock, struct rta_host *host)
|
||||
{
|
||||
static union {
|
||||
void *buf; /* re-use so we prevent leaks */
|
||||
struct icmp *icp;
|
||||
u_short *cksum_in;
|
||||
} packet = { NULL };
|
||||
long int len;
|
||||
struct icmp_ping_data data;
|
||||
struct msghdr hdr;
|
||||
struct iovec iov;
|
||||
struct timeval tv;
|
||||
struct sockaddr *addr;
|
||||
void *buf = NULL;
|
||||
|
||||
if(sock == -1) {
|
||||
errno = 0;
|
||||
crash("Attempt to send on bogus socket");
|
||||
return -1;
|
||||
}
|
||||
addr = (struct sockaddr *)&host->saddr_in;
|
||||
|
||||
if(!packet.buf) {
|
||||
if (!(packet.buf = malloc(icmp_pkt_size))) {
|
||||
if(!buf) {
|
||||
if (!(buf = malloc(icmp_pkt_size))) {
|
||||
crash("send_icmp_ping(): failed to malloc %d bytes for send buffer",
|
||||
icmp_pkt_size);
|
||||
return -1; /* might be reached if we're in debug mode */
|
||||
}
|
||||
}
|
||||
memset(packet.buf, 0, icmp_pkt_size);
|
||||
memset(buf, 0, icmp_pkt_size);
|
||||
|
||||
if((gettimeofday(&tv, &tz)) == -1) return -1;
|
||||
if((gettimeofday(&tv, &tz)) == -1) {
|
||||
free(buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
data.ping_id = 10; /* host->icmp.icmp_sent; */
|
||||
memcpy(&data.stime, &tv, sizeof(tv));
|
||||
memcpy(&packet.icp->icmp_data, &data, sizeof(data));
|
||||
packet.icp->icmp_type = ICMP_ECHO;
|
||||
packet.icp->icmp_code = 0;
|
||||
packet.icp->icmp_cksum = 0;
|
||||
packet.icp->icmp_id = htons(pid);
|
||||
packet.icp->icmp_seq = htons(host->id++);
|
||||
packet.icp->icmp_cksum = icmp_checksum(packet.cksum_in, icmp_pkt_size);
|
||||
|
||||
if (debug > 2)
|
||||
printf("Sending ICMP echo-request of len %lu, id %u, seq %u, cksum 0x%X to host %s\n",
|
||||
(unsigned long)sizeof(data), ntohs(packet.icp->icmp_id),
|
||||
ntohs(packet.icp->icmp_seq), packet.icp->icmp_cksum,
|
||||
host->name);
|
||||
if (address_family == AF_INET) {
|
||||
struct icmp *icp = (struct icmp*)buf;
|
||||
|
||||
memcpy(&icp->icmp_data, &data, sizeof(data));
|
||||
|
||||
icp->icmp_type = ICMP_ECHO;
|
||||
icp->icmp_code = 0;
|
||||
icp->icmp_cksum = 0;
|
||||
icp->icmp_id = htons(pid);
|
||||
icp->icmp_seq = htons(host->id++);
|
||||
icp->icmp_cksum = icmp_checksum((unsigned short*)buf, icmp_pkt_size);
|
||||
|
||||
if (debug > 2)
|
||||
printf("Sending ICMP echo-request of len %lu, id %u, seq %u, cksum 0x%X to host %s\n",
|
||||
(unsigned long)sizeof(data), ntohs(icp->icmp_id), ntohs(icp->icmp_seq), icp->icmp_cksum, host->name);
|
||||
}
|
||||
else {
|
||||
struct icmp6_hdr *icp6 = (struct icmp6_hdr*)buf;
|
||||
memcpy(&icp6->icmp6_dataun.icmp6_un_data8[4], &data, sizeof(data));
|
||||
icp6->icmp6_type = ICMP6_ECHO_REQUEST;
|
||||
icp6->icmp6_code = 0;
|
||||
icp6->icmp6_cksum = 0;
|
||||
icp6->icmp6_id = htons(pid);
|
||||
icp6->icmp6_seq = htons(host->id++);
|
||||
// let checksum be calculated automatically
|
||||
|
||||
if (debug > 2) {
|
||||
printf("Sending ICMP echo-request of len %lu, id %u, seq %u, cksum 0x%X to host %s\n",
|
||||
(unsigned long)sizeof(data), ntohs(icp6->icmp6_id),
|
||||
ntohs(icp6->icmp6_seq), icp6->icmp6_cksum, host->name);
|
||||
}
|
||||
}
|
||||
|
||||
memset(&iov, 0, sizeof(iov));
|
||||
iov.iov_base = packet.buf;
|
||||
iov.iov_base = buf;
|
||||
iov.iov_len = icmp_pkt_size;
|
||||
|
||||
memset(&hdr, 0, sizeof(hdr));
|
||||
hdr.msg_name = addr;
|
||||
hdr.msg_namelen = sizeof(struct sockaddr);
|
||||
hdr.msg_name = (struct sockaddr *)&host->saddr_in;
|
||||
hdr.msg_namelen = sizeof(struct sockaddr_storage);
|
||||
hdr.msg_iov = &iov;
|
||||
hdr.msg_iovlen = 1;
|
||||
|
||||
errno = 0;
|
||||
|
||||
/* MSG_CONFIRM is a linux thing and only available on linux kernels >= 2.3.15, see send(2) */
|
||||
#ifdef MSG_CONFIRM
|
||||
len = sendmsg(sock, &hdr, MSG_CONFIRM);
|
||||
|
@ -887,9 +1019,15 @@ send_icmp_ping(int sock, struct rta_host *host)
|
|||
len = sendmsg(sock, &hdr, 0);
|
||||
#endif
|
||||
|
||||
free(buf);
|
||||
|
||||
if(len < 0 || (unsigned int)len != icmp_pkt_size) {
|
||||
if(debug) printf("Failed to send ping to %s\n",
|
||||
inet_ntoa(host->saddr_in.sin_addr));
|
||||
if(debug) {
|
||||
char address[INET6_ADDRSTRLEN];
|
||||
parse_address((struct sockaddr_storage *)&host->saddr_in, address, sizeof(address));
|
||||
printf("Failed to send ping to %s: %s\n", address, strerror(errno));
|
||||
}
|
||||
errno = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -934,7 +1072,7 @@ recvfrom_wto(int sock, void *buf, unsigned int len, struct sockaddr *saddr,
|
|||
|
||||
if(!n) return 0; /* timeout */
|
||||
|
||||
slen = sizeof(struct sockaddr);
|
||||
slen = sizeof(struct sockaddr_storage);
|
||||
|
||||
memset(&iov, 0, sizeof(iov));
|
||||
iov.iov_base = buf;
|
||||
|
@ -958,6 +1096,7 @@ recvfrom_wto(int sock, void *buf, unsigned int len, struct sockaddr *saddr,
|
|||
break ;
|
||||
}
|
||||
}
|
||||
|
||||
if (!chdr)
|
||||
#endif // SO_TIMESTAMP
|
||||
gettimeofday(tv, &tz);
|
||||
|
@ -991,6 +1130,7 @@ finish(int sig)
|
|||
|
||||
/* iterate thrice to calculate values, give output, and print perfparse */
|
||||
host = list;
|
||||
|
||||
while(host) {
|
||||
if(!host->icmp_recv) {
|
||||
/* rta 0 is ofcourse not entirely correct, but will still show up
|
||||
|
@ -1039,10 +1179,12 @@ finish(int sig)
|
|||
if(!host->icmp_recv) {
|
||||
status = STATE_CRITICAL;
|
||||
if(host->flags & FLAG_LOST_CAUSE) {
|
||||
char address[INET6_ADDRSTRLEN];
|
||||
parse_address(&host->error_addr, address, sizeof(address));
|
||||
printf("%s: %s @ %s. rta nan, lost %d%%",
|
||||
host->name,
|
||||
get_icmp_error_msg(host->icmp_type, host->icmp_code),
|
||||
inet_ntoa(host->error_addr),
|
||||
address,
|
||||
100);
|
||||
}
|
||||
else { /* not marked as lost cause, so we have no flags for it */
|
||||
|
@ -1104,7 +1246,6 @@ get_timevaldiff(struct timeval *early, struct timeval *later)
|
|||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = (later->tv_sec - early->tv_sec) * 1000000;
|
||||
ret += later->tv_usec - early->tv_usec;
|
||||
|
||||
|
@ -1112,18 +1253,35 @@ get_timevaldiff(struct timeval *early, struct timeval *later)
|
|||
}
|
||||
|
||||
static int
|
||||
add_target_ip(char *arg, struct in_addr *in)
|
||||
add_target_ip(char *arg, struct sockaddr_storage *in)
|
||||
{
|
||||
struct rta_host *host;
|
||||
struct sockaddr_in *sin, *host_sin;
|
||||
struct sockaddr_in6 *sin6, *host_sin6;
|
||||
|
||||
/* disregard obviously stupid addresses */
|
||||
if(in->s_addr == INADDR_NONE || in->s_addr == INADDR_ANY)
|
||||
if (address_family == AF_INET)
|
||||
sin = (struct sockaddr_in *)in;
|
||||
else
|
||||
sin6 = (struct sockaddr_in6 *)in;
|
||||
|
||||
|
||||
|
||||
/* disregard obviously stupid addresses
|
||||
* (I didn't find an ipv6 equivalent to INADDR_NONE) */
|
||||
if (((address_family == AF_INET && (sin->sin_addr.s_addr == INADDR_NONE
|
||||
|| sin->sin_addr.s_addr == INADDR_ANY)))
|
||||
|| (address_family == AF_INET6 && (sin6->sin6_addr.s6_addr == in6addr_any.s6_addr))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* no point in adding two identical IP's, so don't. ;) */
|
||||
host = list;
|
||||
while(host) {
|
||||
if(host->saddr_in.sin_addr.s_addr == in->s_addr) {
|
||||
host_sin = (struct sockaddr_in *)&host->saddr_in;
|
||||
host_sin6 = (struct sockaddr_in6 *)&host->saddr_in;
|
||||
|
||||
if( (address_family == AF_INET && host_sin->sin_addr.s_addr == sin->sin_addr.s_addr)
|
||||
|| (address_family == AF_INET6 && host_sin6->sin6_addr.s6_addr == sin6->sin6_addr.s6_addr)) {
|
||||
if(debug) printf("Identical IP already exists. Not adding %s\n", arg);
|
||||
return -1;
|
||||
}
|
||||
|
@ -1131,19 +1289,29 @@ add_target_ip(char *arg, struct in_addr *in)
|
|||
}
|
||||
|
||||
/* add the fresh ip */
|
||||
host = malloc(sizeof(struct rta_host));
|
||||
host = (struct rta_host*)malloc(sizeof(struct rta_host));
|
||||
if(!host) {
|
||||
char straddr[INET6_ADDRSTRLEN];
|
||||
parse_address((struct sockaddr_storage*)&in, straddr, sizeof(straddr));
|
||||
crash("add_target_ip(%s, %s): malloc(%d) failed",
|
||||
arg, inet_ntoa(*in), sizeof(struct rta_host));
|
||||
arg, straddr, sizeof(struct rta_host));
|
||||
}
|
||||
memset(host, 0, sizeof(struct rta_host));
|
||||
|
||||
/* set the values. use calling name for output */
|
||||
host->name = strdup(arg);
|
||||
|
||||
/* fill out the sockaddr_in struct */
|
||||
host->saddr_in.sin_family = AF_INET;
|
||||
host->saddr_in.sin_addr.s_addr = in->s_addr;
|
||||
/* fill out the sockaddr_storage struct */
|
||||
if(address_family == AF_INET) {
|
||||
host_sin = (struct sockaddr_in *)&host->saddr_in;
|
||||
host_sin->sin_family = AF_INET;
|
||||
host_sin->sin_addr.s_addr = sin->sin_addr.s_addr;
|
||||
}
|
||||
else {
|
||||
host_sin6 = (struct sockaddr_in6 *)&host->saddr_in;
|
||||
host_sin6->sin6_family = AF_INET6;
|
||||
memcpy(host_sin6->sin6_addr.s6_addr, sin6->sin6_addr.s6_addr, sizeof host_sin6->sin6_addr.s6_addr);
|
||||
}
|
||||
|
||||
host->rtmin = DBL_MAX;
|
||||
|
||||
|
@ -1160,31 +1328,67 @@ add_target_ip(char *arg, struct in_addr *in)
|
|||
static int
|
||||
add_target(char *arg)
|
||||
{
|
||||
int i;
|
||||
struct hostent *he;
|
||||
struct in_addr *in, ip;
|
||||
int error, result;
|
||||
struct sockaddr_storage ip;
|
||||
struct addrinfo hints, *res, *p;
|
||||
struct sockaddr_in *sin;
|
||||
struct sockaddr_in6 *sin6;
|
||||
|
||||
switch (address_family) {
|
||||
case -1:
|
||||
/* -4 and -6 are not specified on cmdline */
|
||||
address_family = AF_INET;
|
||||
sin = (struct sockaddr_in *)&ip;
|
||||
result = inet_pton(address_family, arg, &sin->sin_addr);
|
||||
#ifdef USE_IPV6
|
||||
if( result != 1 ){
|
||||
address_family = AF_INET6;
|
||||
sin6 = (struct sockaddr_in6 *)&ip;
|
||||
result = inet_pton(address_family, arg, &sin6->sin6_addr);
|
||||
}
|
||||
#endif
|
||||
/* If we don't find any valid addresses, we still don't know the address_family */
|
||||
if ( result != 1) {
|
||||
address_family = -1;
|
||||
}
|
||||
break;
|
||||
case AF_INET:
|
||||
sin = (struct sockaddr_in *)&ip;
|
||||
result = inet_pton(address_family, arg, &sin->sin_addr);
|
||||
break;
|
||||
case AF_INET6:
|
||||
sin6 = (struct sockaddr_in6 *)&ip;
|
||||
result = inet_pton(address_family, arg, &sin6->sin6_addr);
|
||||
break;
|
||||
default: crash("Address family not supported");
|
||||
}
|
||||
|
||||
/* don't resolve if we don't have to */
|
||||
if((ip.s_addr = inet_addr(arg)) != INADDR_NONE) {
|
||||
if(result == 1) {
|
||||
/* don't add all ip's if we were given a specific one */
|
||||
return add_target_ip(arg, &ip);
|
||||
/* he = gethostbyaddr((char *)in, sizeof(struct in_addr), AF_INET); */
|
||||
/* if(!he) return add_target_ip(arg, in); */
|
||||
}
|
||||
else {
|
||||
errno = 0;
|
||||
he = gethostbyname(arg);
|
||||
if(!he) {
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
if (address_family == -1) {
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
} else {
|
||||
hints.ai_family = address_family == AF_INET ? PF_INET : PF_INET6;
|
||||
}
|
||||
hints.ai_socktype = SOCK_RAW;
|
||||
if((error = getaddrinfo(arg, NULL, &hints, &res)) != 0) {
|
||||
errno = 0;
|
||||
crash("Failed to resolve %s", arg);
|
||||
crash("Failed to resolve %s: %s", arg, gai_strerror(error));
|
||||
return -1;
|
||||
}
|
||||
address_family = res->ai_family;
|
||||
}
|
||||
|
||||
/* possibly add all the IP's as targets */
|
||||
for(i = 0; he->h_addr_list[i]; i++) {
|
||||
in = (struct in_addr *)he->h_addr_list[i];
|
||||
add_target_ip(arg, in);
|
||||
for(p = res; p != NULL; p = p->ai_next) {
|
||||
memcpy(&ip, p->ai_addr, p->ai_addrlen);
|
||||
add_target_ip(arg, &ip);
|
||||
|
||||
/* this is silly, but it works */
|
||||
if(mode == MODE_HOSTCHECK || mode == MODE_ALL) {
|
||||
|
@ -1193,6 +1397,7 @@ add_target(char *arg)
|
|||
}
|
||||
break;
|
||||
}
|
||||
freeaddrinfo(res);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1203,7 +1408,7 @@ set_source_ip(char *arg)
|
|||
struct sockaddr_in src;
|
||||
|
||||
memset(&src, 0, sizeof(src));
|
||||
src.sin_family = AF_INET;
|
||||
src.sin_family = address_family;
|
||||
if((src.sin_addr.s_addr = inet_addr(arg)) == INADDR_NONE)
|
||||
src.sin_addr.s_addr = get_ip_address(arg);
|
||||
if(bind(icmp_sock, (struct sockaddr *)&src, sizeof(src)) == -1)
|
||||
|
@ -1311,12 +1516,12 @@ get_threshold(char *str, threshold *th)
|
|||
unsigned short
|
||||
icmp_checksum(unsigned short *p, int n)
|
||||
{
|
||||
register unsigned short cksum;
|
||||
register long sum = 0;
|
||||
unsigned short cksum;
|
||||
long sum = 0;
|
||||
|
||||
while(n > 1) {
|
||||
while(n > 2) {
|
||||
sum += *p++;
|
||||
n -= 2;
|
||||
n -= sizeof(unsigned short);
|
||||
}
|
||||
|
||||
/* mop up the occasional odd byte */
|
||||
|
@ -1347,6 +1552,8 @@ print_help(void)
|
|||
|
||||
printf (" %s\n", "-H");
|
||||
printf (" %s\n", _("specify a target"));
|
||||
printf (" %s\n", "[-4|-6]");
|
||||
printf (" %s\n", _("Use IPv4 (default) or IPv6 to communicate with the targets"));
|
||||
printf (" %s\n", "-w");
|
||||
printf (" %s", _("warning threshold (currently "));
|
||||
printf ("%0.3fms,%u%%)\n", (float)warn.rta / 1000, warn.pl);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue