From 0b6423f9c99d9edf8c96fefd0f6c453859395aa1 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Mon, 30 Sep 2013 00:03:24 +0200 Subject: Import Nagios Plugins site Import the Nagios Plugins web site, Cronjobs, infrastructure scripts, and configuration files. --- web/attachments/121773-check_icmp-bundled.diff | 742 +++++++++++++++++++++++++ 1 file changed, 742 insertions(+) create mode 100644 web/attachments/121773-check_icmp-bundled.diff (limited to 'web/attachments/121773-check_icmp-bundled.diff') diff --git a/web/attachments/121773-check_icmp-bundled.diff b/web/attachments/121773-check_icmp-bundled.diff new file mode 100644 index 0000000..4bb56b4 --- /dev/null +++ b/web/attachments/121773-check_icmp-bundled.diff @@ -0,0 +1,742 @@ +diff -urN ../plugins/plugins/check_icmp.c ./plugins/check_icmp.c +--- ../plugins/plugins/check_icmp.c 2005-02-01 15:31:11.000000000 +0100 ++++ ./plugins/check_icmp.c 2005-02-18 15:57:08.000000000 +0100 +@@ -1,5 +1,5 @@ + /* +- * $Id: check_icmp.c,v 1.5 2005/02/01 07:33:13 stanleyhopcroft Exp $ ++ * $Id: check_icmp.c,v 1.12 2005/01/29 23:23:23 exon Exp $ + * + * Author: Andreas Ericsson + * +@@ -14,6 +14,15 @@ + * redundant routes. The only remainders of fping is currently a few + * function names. + * ++ * Kudos to; ++ * Joe Rhett ++ * Wickus Botha ++ * Aaron Carr ++ * Harper Mann ++ * Phil Costelloe ++ * Carsten Schmitz ++ * for lending me system resources, testing and feedback ++ * + */ + + #include +@@ -84,7 +93,7 @@ + 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 */ +- unsigned long long time_waited; /* total time waited, in usecs */ ++ unsigned long int 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 */ + unsigned short flags; /* control/status flags */ +@@ -137,18 +146,19 @@ + #define IP_HDR_SIZE 20 + #define MAX_PING_DATA (MAX_IP_PKT_SIZE - IP_HDR_SIZE - ICMP_MINLEN) + #define DEFAULT_PING_DATA_SIZE (MIN_PING_DATA_SIZE + 44) ++#define DEFAULT_TTL 64 + +-/* various target states */ +-#define TSTATE_INACTIVE 0x01 /* don't ping this host anymore */ +-#define TSTATE_WAITING 0x02 /* unanswered packets on the wire */ +-#define TSTATE_ALIVE 0x04 /* target is alive (has answered something) */ +-#define TSTATE_UNREACH 0x08 ++#define MIN_PKT_INTERVAL 25000 /* min pkt_interval, microsecs */ ++#define NOFORCE_WAIT 0 ++#define FORCE_WAIT 1 + + /** prototypes **/ +-static void usage(unsigned char, char *); ++static void usage(unsigned char, char *, ...); + static u_int get_timevar(const char *); + static u_int get_timevaldiff(struct timeval *, struct timeval *); +-static int wait_for_reply(int, u_int); ++static int reap_replies(int, u_int, int); ++void u_sleep(u_int u_sec); ++static u_int wait_for_reply(int, u_int); + static int recvfrom_wto(int, char *, unsigned int, struct sockaddr *, u_int *); + static int send_icmp_ping(int, struct rta_host *); + static int get_threshold(char *str, threshold *th); +@@ -162,6 +172,7 @@ + + /** external **/ + extern int optind, opterr, optopt; ++/* extern int h_errno; */ + extern char *optarg; + extern char **environ; + +@@ -173,15 +184,15 @@ + static unsigned short icmp_pkt_size, icmp_data_size = DEFAULT_PING_DATA_SIZE; + static unsigned int icmp_sent = 0, icmp_recv = 0, icmp_lost = 0; + #define icmp_pkts_en_route (icmp_sent - (icmp_recv + icmp_lost)) +-static unsigned short targets_down = 0, targets = 0, packets = 0; ++static unsigned int targets_down = 0, targets = 0, packets = 0; + #define targets_alive (targets - targets_down) + static unsigned int retry_interval, pkt_interval, target_interval; + static int icmp_sock, tcp_sock, udp_sock, status = STATE_OK; + static pid_t pid; + static struct timezone tz; + static struct timeval prog_start; +-static unsigned long long max_completion_time = 0; +-static unsigned char ttl = 0; /* outgoing ttl */ ++static unsigned long int max_completion_time = 0; ++static unsigned char ttl = 64; /* outgoing ttl */ + static unsigned int warn_down = 1, crit_down = 1; /* host down threshold values */ + float pkt_backoff_factor = 1.5; + float target_backoff_factor = 1.5; +@@ -210,7 +221,8 @@ + { + char *msg = "unreachable"; + +- if(debug > 1) printf("get_icmp_error_msg(%u, %u)\n", icmp_type, icmp_code); ++ if(debug > 3) printf("get_icmp_error_msg(%u, %u) called\n", ++ icmp_type, icmp_code); + switch(icmp_type) { + case ICMP_UNREACH: + switch(icmp_code) { +@@ -269,7 +281,7 @@ + unsigned char *ptr; + + if(p->icmp_type == ICMP_ECHO && p->icmp_id == pid) { +- /* echo request from us to us (pinging localhost) */ ++ if(debug > 2) printf("echo request from us to us (pinging localhost)\n"); + return 0; + } + +@@ -286,9 +298,13 @@ + * TIMXCEED actually sends a proper icmp response we will have passed + * too many hops to have a hope of reaching it later, in which case it + * indicates overconfidence in the network, poor routing or both. */ ++ if(debug > 2) printf("random ICMP response type: %u, code: %u\n", ++ p->icmp_type, p->icmp_code); + if(p->icmp_type != ICMP_UNREACH && p->icmp_type != ICMP_TIMXCEED && + p->icmp_type != ICMP_SOURCEQUENCH && p->icmp_type != ICMP_PARAMPROB) + { ++ if(debug > 1) printf("Unsafe to handle unknown type %u, returning\n", ++ p->icmp_type); + return 0; + } + +@@ -298,7 +314,7 @@ + if(sent_icmp->icmp_type != ICMP_ECHO || sent_icmp->icmp_id != pid || + sent_icmp->icmp_seq >= targets) + { +- if(debug) printf("Packet is no response to a packet we sent\n"); ++ if(debug) printf("not a response to a packet we sent, or target failed to duplicate request\n"); + return 0; + } + +@@ -394,12 +410,12 @@ + } + else if(!strcmp(progname, "check_host")) { + mode = MODE_HOSTCHECK; +- pkt_interval = 1000000; ++ pkt_interval = 200000; + packets = 5; + crit.rta = warn.rta = 1000000; + crit.pl = warn.pl = 100; + } +- else if(!strcmp(progname, "check_rta_multi")) { ++ else if(!strcmp(progname, "check_icmp_multi")) { + mode = MODE_ALL; + target_interval = 0; + pkt_interval = 50000; +@@ -408,6 +424,8 @@ + + /* parse the arguments */ + for(i = 1; i < argc; i++) { ++ /* the leading '-' of the optstring makes non-argument options ++ * return with arg 1, meaning it's */ + while((arg = getopt(argc, argv, "vhVw:c:n:p:t:H:i:b:I:l:")) != EOF) { + switch(arg) { + case 'v': +@@ -436,7 +454,8 @@ + timeout = strtoul(optarg, NULL, 0); + if(!timeout) timeout = 10; + break; +- case 'H': ++ case 'H': case 1: /* 1 is default for non-option arguments */ ++ /* printf("arg: %ld, optarg: %s\n", arg, optarg); */ + add_target(optarg); + break; + case 'l': +@@ -460,11 +479,10 @@ + add_target(*argv); + argv++; + } +- if(!targets) { +- errno = 0; +- crash("No hosts to check"); +- exit(3); +- } ++ if(!targets) usage('h', "No hosts to check"); ++ ++ if(getuid() && pkt_interval < MIN_PKT_INTERVAL) ++ pkt_interval = MIN_PKT_INTERVAL; + + if(!sockets) { + if(icmp_sock == -1) { +@@ -486,10 +504,12 @@ + if(!ttl) ttl = 64; + + if(icmp_sock) { ++ errno = 0; + result = setsockopt(icmp_sock, SOL_IP, IP_TTL, &ttl, sizeof(ttl)); + if(debug) { +- if(result == -1) printf("setsockopt failed\n"); +- else printf("ttl set to %u\n", ttl); ++ printf("setsockopt(icmp_sock, SOL_IP, IP_TTL, %u) = %d (%s)\n", ++ ttl, result, strerror(errno)); ++ if(result != -1) printf("outgoing ttl set to %u\n", ttl); + } + } + +@@ -505,7 +525,7 @@ + signal(SIGHUP, finish); + signal(SIGTERM, finish); + signal(SIGALRM, finish); +- if(debug) printf("Setting alarm timeout to %u seconds\n", timeout); ++ if(debug > 1) printf("Setting alarm timeout to %u seconds\n", timeout); + alarm(timeout); + + /* make sure we don't wait any longer than necessary */ +@@ -514,10 +534,9 @@ + ((targets * packets * pkt_interval) + (targets * target_interval)) + + (targets * packets * crit.rta) + crit.rta; + +- if(debug) { ++ if(debug > 1) { + printf("packets: %u, targets: %u\n" +- "target_interval: %0.3f, pkt_interval %0.3f\n" +- "crit.rta: %0.3f\n" ++ "target_interval: %0.3f, pkt_interval %0.3f, crit.rta: %0.3f\n" + "max_completion_time: %0.3f\n", + packets, targets, + (float)target_interval / 1000, (float)pkt_interval / 1000, +@@ -527,9 +546,9 @@ + + if(debug) { + if(max_completion_time > (u_int)timeout * 1000000) { +- printf("max_completion_time: %llu timeout: %u\n", ++ printf("max_completion_time: %lu timeout: %u\n", + max_completion_time, timeout); +- printf("Timout must be at lest %llu\n", ++ printf("Timout must be at lest %lu\n", + max_completion_time / 1000000 + 1); + } + } +@@ -579,24 +598,27 @@ + u_int i, t, result; + u_int final_wait, time_passed; + +- /* this loop might actually violate the pkt_interval or target_interval +- * settings, but only if there aren't any packets on the wire which +- * indicates that the target can handle an increased packet rate */ +- for(i = 0; i < packets; i++) { +- for(t = 0; t < targets; t++) { ++ /* send the packets */ ++ for(t = 0; t < targets; t++) { ++ for(i = 0; i < packets; i++) { ++ + /* don't send useless packets */ +- if(!targets_alive) finish(0); + if(table[t]->flags & FLAG_LOST_CAUSE) { + if(debug) printf("%s is a lost cause. not sending any more\n", + table[t]->name); + continue; + } +- ++ + /* we're still in the game, so send next packet */ + (void)send_icmp_ping(icmp_sock, table[t]); +- result = wait_for_reply(icmp_sock, target_interval); ++ ++ /* pause for a while so we don't flood the network */ ++ result = reap_replies(icmp_sock, pkt_interval, FORCE_WAIT); + } +- result = wait_for_reply(icmp_sock, pkt_interval * targets); ++ ++ /* wait for all incoming packets from all hosts */ ++ if(target_interval > pkt_interval) ++ result = reap_replies(icmp_sock, target_interval - pkt_interval, FORCE_WAIT); + } + + if(icmp_pkts_en_route && targets_alive) { +@@ -604,7 +626,7 @@ + final_wait = max_completion_time - time_passed; + + if(debug) { +- printf("time_passed: %u final_wait: %u max_completion_time: %llu\n", ++ printf("time_passed: %u final_wait: %u max_completion_time: %lu\n", + time_passed, final_wait, max_completion_time); + } + if(time_passed > max_completion_time) { +@@ -616,8 +638,61 @@ + * haven't yet */ + if(debug) printf("Waiting for %u micro-seconds (%0.3f msecs)\n", + final_wait, (float)final_wait / 1000); +- result = wait_for_reply(icmp_sock, final_wait); ++ result = reap_replies(icmp_sock, final_wait, NOFORCE_WAIT); ++ } ++} ++ ++/* ++ * select() is posix, so we expect it to be around ++ */ ++void ++u_sleep(u_int u_sec) ++{ ++ int nfound; ++ struct timeval to; ++ fd_set readset, writeset; ++ ++ if(debug > 3) printf("sleeping for %u microseconds\n", u_sec); ++ if(!u_sec) return; ++ ++ to.tv_sec = u_sec / 1000000; ++ to.tv_usec = u_sec % 1000000; ++ FD_ZERO(&writeset); ++ FD_ZERO(&readset); ++ nfound = select(0, &readset, &writeset, NULL, &to); ++ if(nfound < 0) ++ crash("select() in u_sleep"); ++ ++ return; ++} /* u_sleep() */ ++ ++static int ++reap_replies(int sock, u_int t, int wait_forced) ++{ ++ /* wrap up if all targets are declared dead */ ++ if(debug > 3) printf("reap_replies(%d, %u, %d) called\n", sock, t, wait_forced); ++ ++ if(!targets_alive || ++ get_timevaldiff(&prog_start, NULL) >= max_completion_time) ++ { ++ finish(0); ++ } ++ ++ /* listen til timeout while there are packets en route (rhymes!) ;) */ ++ while(t && icmp_pkts_en_route) { ++ t = wait_for_reply(sock, t); ++ ++ /* the dead won't sing to us */ ++ if(!targets_alive) finish(0); + } ++ ++ if(icmp_recv == (targets_alive * (int)packets)) finish(0); ++ ++ if(!t || !wait_forced) return 0; ++ ++ u_sleep(t); ++ ++ return 0; + } + + /* response structure: +@@ -625,126 +700,98 @@ + * icmp header : 28 bytes + * icmp echo reply : the rest + */ +-static int ++static u_int + wait_for_reply(int sock, u_int t) + { + int n, hlen; + static char buf[4096]; + struct sockaddr_in resp_addr; + struct ip *ip; +- struct icmp *icp, *sent_icmp; ++ struct icmp *icp; + struct rta_host *host; + struct icmp_ping_data *data; + struct timeval wait_start, now; +- u_int tdiff, i, per_pkt_wait; +- +- /* if we can't listen or don't have anything to listen to, just return */ +- if(!t || !icmp_pkts_en_route) return 0; ++ u_int tdiff, timo = t; + + gettimeofday(&wait_start, &tz); + +- i = t; +- per_pkt_wait = t / icmp_pkts_en_route; +- while(icmp_pkts_en_route && get_timevaldiff(&wait_start, NULL) < i) { +- t = per_pkt_wait; +- +- /* wrap up if all targets are declared dead */ +- if(!targets_alive || +- get_timevaldiff(&prog_start, NULL) >= max_completion_time || +- (mode == MODE_HOSTCHECK && targets_down)) +- { +- finish(0); +- } ++ n = recvfrom_wto(sock, buf, sizeof(buf), (struct sockaddr *)&resp_addr, &timo); ++ if(!n) { /* timeout */ ++ if(debug > 2) printf("recvfrom_wto() timed out during a %u usecs wait\n", t); ++ return 0; /* no time left, so return just that */ ++ } + +- /* reap responses until we hit a timeout */ +- n = recvfrom_wto(sock, buf, sizeof(buf), +- (struct sockaddr *)&resp_addr, &t); +- if(!n) { +- if(debug > 1) { +- printf("recvfrom_wto() timed out during a %u usecs wait\n", +- per_pkt_wait); +- } +- continue; /* timeout for this one, so keep trying */ +- } +- if(n < 0) { +- if(debug) printf("recvfrom_wto() returned errors\n"); +- return n; +- } ++ gettimeofday(&now, &tz); ++ tdiff = get_timevaldiff(&wait_start, &now); ++ /* make sure we can return time left */ ++ if(t > tdiff) t -= tdiff; ++ else t = 0; + +- ip = (struct ip *)buf; +- if(debug > 1) printf("received %u bytes from %s\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)); + +-/* obsolete. alpha on tru64 provides the necessary defines, but isn't broken */ ++/* obsolete, or at least not globally applicable */ + /* #if defined( __alpha__ ) && __STDC__ && !defined( __GLIBC__ ) */ + /* alpha headers are decidedly broken. Using an ansi compiler, + * they provide ip_vhl instead of ip_hl and ip_v, so we mask + * off the bottom 4 bits */ + /* hlen = (ip->ip_vhl & 0x0f) << 2; */ + /* #else */ +- hlen = ip->ip_hl << 2; ++ hlen = ip->ip_hl << 2; + /* #endif */ + +- if(n < (hlen + ICMP_MINLEN)) { +- 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)); +- } +- /* else if(debug) { */ +- /* printf("ip header size: %u, packet size: %u (expected %u, %u)\n", */ +- /* hlen, ntohs(ip->ip_len) - hlen, */ +- /* sizeof(struct ip), icmp_pkt_size); */ +- /* } */ +- +- /* check the response */ +- icp = (struct icmp *)(buf + hlen); +- sent_icmp = (struct icmp *)(buf + hlen + ICMP_MINLEN); +- /* printf("buf: %p, icp: %p, distance: %u (expected %u)\n", */ +- /* buf, icp, */ +- /* (u_int)icp - (u_int)buf, hlen); */ +- /* printf("buf: %p, sent_icmp: %p, distance: %u (expected %u)\n", */ +- /* buf, sent_icmp, */ +- /* (u_int)sent_icmp - (u_int)buf, hlen + ICMP_MINLEN); */ +- +- if(icp->icmp_id != pid) { +- handle_random_icmp(icp, &resp_addr); +- continue; +- } +- +- if(icp->icmp_type != ICMP_ECHOREPLY || icp->icmp_seq >= targets) { +- if(debug > 2) printf("not a proper ICMP_ECHOREPLY\n"); +- handle_random_icmp(icp, &resp_addr); +- continue; +- } +- +- /* this is indeed a valid response */ +- data = (struct icmp_ping_data *)(icp->icmp_data); +- +- host = table[icp->icmp_seq]; +- gettimeofday(&now, &tz); +- tdiff = get_timevaldiff(&data->stime, &now); ++ if(n < (hlen + ICMP_MINLEN)) { ++ 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)); ++ } ++ else if(debug > 2) { ++ printf("ip header size: %u, packet size: %u (expected %u, %u)\n", ++ hlen, ntohs(ip->ip_len) - hlen, ++ sizeof(struct ip), (u_int)icmp_pkt_size); ++ } + +- host->time_waited += tdiff; +- host->icmp_recv++; +- icmp_recv++; ++ /* check the response */ ++ icp = (struct icmp *)(buf + hlen); + ++ if(icp->icmp_id != pid || icp->icmp_type != ICMP_ECHOREPLY || icp->icmp_seq >= targets) { + if(debug) { +- printf("%0.3f ms rtt from %s, outgoing ttl: %u, incoming ttl: %u\n", +- (float)tdiff / 1000, inet_ntoa(resp_addr.sin_addr), +- ttl, ip->ip_ttl); +- } ++ printf("inbound packet is:\n"); ++ if(icp->icmp_id != pid) printf("\tnot marked by me\n"); ++ if(icp->icmp_type != ICMP_ECHOREPLY) printf("\tnot an echo reply\n"); ++ if(icp->icmp_seq >= targets) printf("\ttagged with a too high seq number\n"); ++ } ++ handle_random_icmp(icp, &resp_addr); ++ return t; ++ } ++ if(debug > 2) puts("inbound packet is a valid ICMP_ECHOREPLY to a packet we sent"); ++ ++ /* this is indeed a valid response */ ++ data = (struct icmp_ping_data *)(icp->icmp_data); ++ host = table[icp->icmp_seq]; ++ tdiff = get_timevaldiff(&data->stime, &now); ++ ++ host->time_waited += tdiff; ++ host->icmp_recv++; ++ icmp_recv++; + +- /* 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); +- exit(STATE_OK); +- } ++ if(debug) { ++ printf("%0.3f ms rtt from %s, outgoing ttl: %u, incoming ttl: %u\n", ++ (float)tdiff / 1000, inet_ntoa(resp_addr.sin_addr), ++ ttl, ip->ip_ttl); ++ } ++ ++ /* 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); ++ exit(STATE_OK); + } + +- return 0; ++ return t; + } + + /* the ping functions */ +@@ -776,8 +823,6 @@ + } + memset(buf, 0, icmp_pkt_size + sizeof(struct ip)); + +- if((gettimeofday(&tv, &tz)) == -1) return -1; +- + icp = (struct icmp *)buf; + icp->icmp_type = ICMP_ECHO; + icp->icmp_code = 0; +@@ -785,7 +830,9 @@ + icp->icmp_id = pid; + icp->icmp_seq = host->id; + data = (struct icmp_ping_data *)icp->icmp_data; +- data->ping_id = 10; /* host->icmp.icmp_sent; */ ++ data->ping_id = host->icmp_sent; ++ ++ if((gettimeofday(&tv, &tz)) == -1) return -1; + memcpy(&data->stime, &tv, sizeof(struct timeval)); + icp->icmp_cksum = icmp_checksum((u_short *)icp, icmp_pkt_size); + +@@ -798,6 +845,7 @@ + return -1; + } + ++ /* increment the counters */ + icmp_sent++; + host->icmp_sent++; + +@@ -809,7 +857,7 @@ + u_int *timo) + { + u_int slen; +- int n; ++ int n, result; + struct timeval to, then, now; + fd_set rd, wr; + +@@ -835,7 +883,10 @@ + + slen = sizeof(struct sockaddr); + +- return recvfrom(sock, buf, len, 0, saddr, &slen); ++ result = recvfrom(sock, buf, len, 0, saddr, &slen); ++ if(result < 0) crash("recvfrom in recvfrom_wto"); ++ ++ return result; + } + + static void +@@ -849,7 +900,7 @@ + {"OK", "WARNING", "CRITICAL", "UNKNOWN", "DEPENDENT"}; + + alarm(0); +- if(debug > 1) printf("finish(%d) called\n", sig); ++ if(debug > 2) printf("finish(%d) called\n", sig); + + if(icmp_sock != -1) close(icmp_sock); + if(udp_sock != -1) close(udp_sock); +@@ -1016,23 +1067,20 @@ + struct hostent *he; + struct in_addr *in, ip; + +- /* don't resolve if we don't have to */ +- if((ip.s_addr = inet_addr(arg)) != INADDR_NONE) { +- /* 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; ++ /* don't resolve if we don't have to, don't add all ip's if we were ++ * given a specific one, even if we're in hostcheck mode */ ++ if(inet_aton(arg, &ip)) return add_target_ip(arg, &ip); ++ ++ /* not an IP, so resolve */ ++ errno = 0; ++ he = gethostbyname(arg); ++ if(!he && h_errno == TRY_AGAIN) { ++ u_sleep(500000); + he = gethostbyname(arg); +- if(!he) { +- errno = 0; +- crash("Failed to resolve %s", arg); +- return -1; +- } + } + ++ if(!he) usage(0, "Failed to resolve %s: %s", arg, hstrerror(h_errno)); ++ + /* 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]; +@@ -1040,7 +1088,7 @@ + + /* this is silly, but it works */ + if(mode == MODE_HOSTCHECK || mode == MODE_ALL) { +- printf("mode: %d\n", mode); ++ if(debug) printf("mode: %d\n", mode); + continue; + } + break; +@@ -1048,6 +1096,7 @@ + + return 0; + } ++ + /* + * u = micro + * m = milli +@@ -1073,12 +1122,12 @@ + if(len >= 2 && !isdigit((int)str[len - 2])) p = str[len - 2]; + if(p && u == 's') u = p; + else if(!p) p = u; +- if(debug > 2) printf("evaluating %s, u: %c, p: %c\n", str, u, p); ++ if(debug > 3) printf("evaluating %s, u: %c, p: %c\n", str, u, p); + + if(u == 'u') factor = 1; /* microseconds */ + else if(u == 'm') factor = 1000; /* milliseconds */ + else if(u == 's') factor = 1000000; /* seconds */ +- if(debug > 2) printf("factor is %u\n", factor); ++ if(debug > 3) printf("factor is %u\n", factor); + + i = strtoul(str, &ptr, 0); + if(!ptr || *ptr != '.' || strlen(ptr) < 2 || factor == 1) +@@ -1149,51 +1198,58 @@ + + /* make core plugin developers happy (silly, really) */ + static void +-usage(unsigned char arg, char *msg) ++usage(unsigned char arg, char *fmt, ...) + { +- if(msg) printf("%s: %s\n", progname, msg); ++ if(fmt) { ++ va_list ap; ++ ++ printf("%s: ", progname); ++ ++ va_start(ap, fmt); ++ vprintf(fmt, ap); ++ va_end(ap); ++ puts("\n"); ++ } + + if(arg == 'V') { +- printf("$Id: check_icmp.c,v 1.5 2005/02/01 07:33:13 stanleyhopcroft Exp $\n"); ++ printf("$Id: check_icmp.c,v 1.12 2005/01/29 23:23:23 exon Exp $\n"); + exit(STATE_UNKNOWN); + } + + printf("Usage: %s [options] [-H] host1 host2 hostn\n\n", progname); + +- if(arg != 'h') exit(3); ++ if(arg != 'h') { ++ printf("%s -h for details\n", progname); ++ exit(3); ++ } + + printf("Where options are any combination of:\n" +- " * -H | --host specify a target\n" +- " * -w | --warn warning threshold (currently %0.3fms,%u%%)\n" +- " * -c | --crit critical threshold (currently %0.3fms,%u%%)\n" +- " * -n | --packets number of packets to send (currently %u)\n" +- " * -i | --interval max packet interval (currently %0.3fms)\n" +- " * -I | --hostint max target interval (currently %0.3fms)\n" +- " * -l | --ttl TTL on outgoing packets (currently %u)\n" +- " * -t | --timeout timeout value (seconds, currently %u)\n" +- " * -b | --bytes icmp packet size (currenly ignored)\n" +- " -v | --verbose verbosity++\n" +- " -h | --help this cruft\n", ++ " * -H | --host specify a target\n" ++ " * -w | --warn warning threshold (currently %0.3fms,%u%%)\n" ++ " * -c | --crit critical threshold (currently %0.3fms,%u%%)\n" ++ " * -n | --packets number of packets to send (currently %u)\n" ++ " * -i | --interval max packet interval (currently %0.3fms)\n" ++ " * -I | --hostint max target interval (currently %0.3fms)\n", + (float)warn.rta / 1000, warn.pl, (float)crit.rta / 1000, crit.pl, + packets, +- (float)pkt_interval / 1000, (float)target_interval / 1000, ++ (float)pkt_interval / 1000, (float)target_interval / 1000); ++ ++ printf(" * -l | --ttl outgoing TTL (currently %u, not supported on all platforms)\n" ++ " * -t | --timeout timeout value (seconds, currently %u)\n" ++ " * -b | --bytes icmp packet size (currenly ignored)\n" ++ " -v | --verbose verbosity++ (4 is sort of max)\n" ++ " -h | --help this cruft\n", + ttl, timeout); + +- puts("\nThe -H switch is optional. Naming a host (or several) to check is not.\n\n" +- "Threshold format for -w and -c is 200.25,60% for 200.25 msec RTA and 60%\n" +- "packet loss. The default values should work well for most users.\n" ++ puts("\nThreshold format for -w and -c is 200.25,60% for 200.25 msec RTA and 60%\n" ++ "packet loss. All threshold values match inclusively.\n" + "You can specify different RTA factors using the standardized abbreviations\n" +- "us (microseconds), ms (milliseconds, default) or just plain s for seconds.\n\n" +- "Threshold format for -d is warn,crit. 12,14 means WARNING if >= 12 hops\n" +- "are spent and CRITICAL if >= 14 hops are spent.\n" +- "NOTE: Some systems decrease TTL when forming ICMP_ECHOREPLY, others do not.\n\n" +- "The -v switch can be specified several times for increased verbosity.\n\n" +- "Long options are currently unsupported.\n\n" +- "Options marked with * require an argument\n"); +- +- puts("The latest version of this plugin can be found at http://oss.op5.se/nagios\n" +- "or https://devel.op5.se/oss until the day it is included in the official\n" +- "plugin distribution.\n"); ++ "us (microseconds), ms (milliseconds, default) or just plain s for seconds.\n"); ++ puts("Long options are currently unsupported.\n"); ++ puts("Options marked with * require an argument\n"); ++ puts("If this program is invoked as check_host (with a symlink, preferrably), it will exit with status\n" ++ "OK upon the first properly received ICMP_ECHOREPLY, making it ideal\n" ++ "for hostchecks (less network load and much, much faster on OK)\n"); + + exit(3); + } -- cgit v1.2.3-74-g34f1