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); }