X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=plugins-root%2Fcheck_icmp.c;h=1dde4478936afc8df47549d1da12da28b2eb40ca;hb=c2d9c59dc9dd4ee1627627569ab4b0d45c60f103;hp=5fb9c364a56c08892927db3370f026126cb06ac0;hpb=c64070fd3f924b02a517117bba2dfe702d020a9b;p=nagiosplug.git diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c index 5fb9c36..1dde447 100644 --- a/plugins-root/check_icmp.c +++ b/plugins-root/check_icmp.c @@ -6,8 +6,6 @@ * Copyright (c) 2005-2008 Nagios Plugins Development Team * Original Author : Andreas Ericsson * -* Last Modified: $Date$ -* * Description: * * This file contains the check_icmp plugin @@ -35,14 +33,12 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . * -* $Id$ * *****************************************************************************/ /* progname may change */ /* char *progname = "check_icmp"; */ char *progname; -const char *revision = "$Revision$"; const char *copyright = "2005-2008"; const char *email = "nagiosplug-devel@lists.sourceforge.net"; @@ -74,6 +70,7 @@ const char *email = "nagiosplug-devel@lists.sourceforge.net"; #include #include #include +#include /** sometimes undefined system macros (quite a few, actually) **/ @@ -106,6 +103,9 @@ const char *email = "nagiosplug-devel@lists.sourceforge.net"; # define ICMP_UNREACH_PRECEDENCE_CUTOFF 15 #endif +#ifndef DBL_MAX +# define DBL_MAX 9.9999999999e999 +#endif typedef unsigned short range_t; /* type for get_range() -- unimplemented */ @@ -120,6 +120,8 @@ typedef struct rta_host { unsigned char icmp_type, icmp_code; /* type and code from errors */ unsigned short flags; /* control/status flags */ double rta; /* measured RTA */ + double rtmax; /* max rtt */ + double rtmin; /* min rtt */ unsigned char pl; /* measured packet loss */ struct rta_host *next; /* linked list */ } rta_host; @@ -182,14 +184,14 @@ static u_int get_timevar(const char *); static u_int get_timevaldiff(struct timeval *, struct timeval *); static in_addr_t get_ip_address(const char *); static int wait_for_reply(int, u_int); -static int recvfrom_wto(int, char *, unsigned int, struct sockaddr *, u_int *); +static int recvfrom_wto(int, void *, unsigned int, struct sockaddr *, u_int *); static int send_icmp_ping(int, struct rta_host *); 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(char *, struct sockaddr_in *); +static int handle_random_icmp(unsigned char *, struct sockaddr_in *); static unsigned short icmp_checksum(unsigned short *, int); static void finish(int); static void crash(const char *, ...); @@ -298,7 +300,7 @@ get_icmp_error_msg(unsigned char icmp_type, unsigned char icmp_code) } static int -handle_random_icmp(char *packet, struct sockaddr_in *addr) +handle_random_icmp(unsigned char *packet, struct sockaddr_in *addr) { struct icmp p, sent_icmp; struct rta_host *host = NULL; @@ -331,14 +333,14 @@ handle_random_icmp(char *packet, struct sockaddr_in *addr) * to RFC 792). If it isn't, just ignore it */ memcpy(&sent_icmp, packet + 28, sizeof(sent_icmp)); if(sent_icmp.icmp_type != ICMP_ECHO || sent_icmp.icmp_id != pid || - sent_icmp.icmp_seq >= targets) + sent_icmp.icmp_seq >= targets*packets) { if(debug) printf("Packet is no response to a packet we sent\n"); return 0; } /* it is indeed a response for us */ - host = table[sent_icmp.icmp_seq]; + host = table[sent_icmp.icmp_seq/packets]; if(debug) { printf("Received \"%s\" from %s for ICMP ECHO sent to %s.\n", get_icmp_error_msg(p.icmp_type, p.icmp_code), @@ -463,13 +465,13 @@ main(int argc, char **argv) case 'b': size = strtol(optarg,NULL,0); if (size >= (sizeof(struct icmp) + sizeof(struct icmp_ping_data)) && - size <= MAX_PING_DATA + ICMP_MINLEN) { - icmp_pkt_size = size; - icmp_data_size = icmp_pkt_size - ICMP_MINLEN; + size < MAX_PING_DATA) { + icmp_data_size = size; + icmp_pkt_size = size + ICMP_MINLEN; } else - usage_va("ICMP packet size must be between: %d and %d", + usage_va("ICMP data length must be between: %d and %d", sizeof(struct icmp) + sizeof(struct icmp_ping_data), - MAX_PING_DATA + ICMP_MINLEN); + MAX_PING_DATA - 1); break; case 'i': @@ -511,7 +513,7 @@ main(int argc, char **argv) set_source_ip(optarg); break; case 'V': /* version */ - /*print_revision (progname, revision);*/ /* FIXME: Why? */ + print_revision (progname, NP_VERSION); exit (STATE_OK); case 'h': /* help */ print_help (); @@ -622,7 +624,7 @@ main(int argc, char **argv) table = malloc(sizeof(struct rta_host **) * (argc - 1)); i = 0; while(host) { - host->id = i; + host->id = i*packets; table[i] = host; host = host->next; i++; @@ -692,7 +694,7 @@ static int wait_for_reply(int sock, u_int t) { int n, hlen; - static char buf[4096]; + static unsigned char buf[4096]; struct sockaddr_in resp_addr; struct ip *ip; struct icmp icp; @@ -761,12 +763,7 @@ wait_for_reply(int sock, u_int t) /* check the response */ memcpy(&icp, buf + hlen, sizeof(icp)); - if(icp.icmp_id != pid) { - handle_random_icmp(buf + hlen, &resp_addr); - continue; - } - - if(icp.icmp_type != ICMP_ECHOREPLY || icp.icmp_seq >= targets) { + if(icp.icmp_id != pid || icp.icmp_type != ICMP_ECHOREPLY || icp.icmp_seq >= targets*packets) { if(debug > 2) printf("not a proper ICMP_ECHOREPLY\n"); handle_random_icmp(buf + hlen, &resp_addr); continue; @@ -774,19 +771,26 @@ wait_for_reply(int sock, u_int t) /* this is indeed a valid response */ memcpy(&data, icp.icmp_data, sizeof(data)); + if (debug > 2) + printf("ICMP echo-reply of len %u, id %u, seq %u, cksum 0x%X\n", + sizeof(data), icp.icmp_id, icp.icmp_seq, icp.icmp_cksum); - host = table[icp.icmp_seq]; + host = table[icp.icmp_seq/packets]; gettimeofday(&now, &tz); tdiff = get_timevaldiff(&data.stime, &now); host->time_waited += tdiff; host->icmp_recv++; icmp_recv++; + if (tdiff > host->rtmax) + host->rtmax = tdiff; + if (tdiff < host->rtmin) + host->rtmin = tdiff; if(debug) { - printf("%0.3f ms rtt from %s, outgoing ttl: %u, incoming ttl: %u\n", + 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); + ttl, ip->ip_ttl, (float)host->rtmax / 1000, (float)host->rtmin / 1000); } /* if we're in hostcheck mode, exit with limited printouts */ @@ -808,7 +812,7 @@ static int send_icmp_ping(int sock, struct rta_host *host) { static union { - char *buf; /* re-use so we prevent leaks */ + void *buf; /* re-use so we prevent leaks */ struct icmp *icp; u_short *cksum_in; } packet = { NULL }; @@ -842,9 +846,13 @@ send_icmp_ping(int sock, struct rta_host *host) packet.icp->icmp_code = 0; packet.icp->icmp_cksum = 0; packet.icp->icmp_id = pid; - packet.icp->icmp_seq = host->id; + packet.icp->icmp_seq = host->id++; packet.icp->icmp_cksum = icmp_checksum(packet.cksum_in, icmp_pkt_size); + if (debug > 2) + printf("Sending ICMP echo-request of len %u, id %u, seq %u, cksum 0x%X to host %s\n", + sizeof(data), packet.icp->icmp_id, packet.icp->icmp_seq, packet.icp->icmp_cksum, host->name); + len = sendto(sock, packet.buf, icmp_pkt_size, 0, (struct sockaddr *)addr, sizeof(struct sockaddr)); @@ -861,7 +869,7 @@ send_icmp_ping(int sock, struct rta_host *host) } static int -recvfrom_wto(int sock, char *buf, unsigned int len, struct sockaddr *saddr, +recvfrom_wto(int sock, void *buf, unsigned int len, struct sockaddr *saddr, u_int *timo) { u_int slen; @@ -993,11 +1001,12 @@ finish(int sig) host = list; while(host) { if(debug) puts(""); - printf("%srta=%0.3fms;%0.3f;%0.3f;0; %spl=%u%%;%u;%u;; ", + printf("%srta=%0.3fms;%0.3f;%0.3f;0; %spl=%u%%;%u;%u;; %srtmax=%0.3fms;;;; %srtmin=%0.3fms;;;; ", (targets > 1) ? host->name : "", host->rta / 1000, (float)warn.rta / 1000, (float)crit.rta / 1000, - (targets > 1) ? host->name : "", - host->pl, warn.pl, crit.pl); + (targets > 1) ? host->name : "", host->pl, warn.pl, crit.pl, + (targets > 1) ? host->name : "", (float)host->rtmax / 1000, + (targets > 1) ? host->name : "", (host->rtmin < DBL_MAX) ? (float)host->rtmin / 1000 : (float)0); host = host->next; } @@ -1028,7 +1037,7 @@ get_timevaldiff(struct timeval *early, struct timeval *later) if(!early) early = &prog_start; /* if early > later we return 0 so as to indicate a timeout */ - if(early->tv_sec > early->tv_sec || + if(early->tv_sec > later->tv_sec || (early->tv_sec == later->tv_sec && early->tv_usec > later->tv_usec)) { return 0; @@ -1074,6 +1083,8 @@ add_target_ip(char *arg, struct in_addr *in) host->saddr_in.sin_family = AF_INET; host->saddr_in.sin_addr.s_addr = in->s_addr; + host->rtmin = DBL_MAX; + if(!list) list = cursor = host; else cursor->next = host; @@ -1260,7 +1271,7 @@ void print_help(void) { - /*print_revision (progname, revision);*/ /* FIXME: Why? */ + /*print_revision (progname);*/ /* FIXME: Why? */ printf ("Copyright (c) 2005 Andreas Ericsson \n"); printf (COPYRIGHT, copyright, email); @@ -1276,10 +1287,10 @@ print_help(void) printf (" %s\n", _("specify a target")); printf (" %s\n", "-w"); printf (" %s", _("warning threshold (currently ")); - printf ("%0.3fms,%u%%)\n", (float)warn.rta / 1000 , warn.pl / 1000); + printf ("%0.3fms,%u%%)\n", (float)warn.rta / 1000, warn.pl); printf (" %s\n", "-c"); printf (" %s", _("critical threshold (currently ")); - printf ("%0.3fms,%u%%)\n", (float)crit.rta, crit.pl); + printf ("%0.3fms,%u%%)\n", (float)crit.rta / 1000, crit.pl); printf (" %s\n", "-s"); printf (" %s\n", _("specify a source IP address or device name")); printf (" %s\n", "-n"); @@ -1296,13 +1307,13 @@ print_help(void) printf ("\n"); printf (" %s\n", "-l"); printf (" %s", _("TTL on outgoing packets (currently ")); - printf ("%u)", ttl); + printf ("%u)\n", ttl); printf (" %s\n", "-t"); printf (" %s",_("timeout value (seconds, currently ")); printf ("%u)\n", timeout); printf (" %s\n", "-b"); - printf (" %s", _("icmp packet size (bytes, currently ")); - printf ("%u)\n", icmp_pkt_size); + printf (" %s\n", _("Number of icmp data bytes to send")); + printf (" %s %u + %d)\n", _("Packet size will be data bytes + icmp header (currently"),icmp_data_size, ICMP_MINLEN); printf (" %s\n", "-v"); printf (" %s\n", _("verbose"));