diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c index 1d47e9fc..72ad1d7d 100644 --- a/plugins-root/check_icmp.c +++ b/plugins-root/check_icmp.c @@ -42,6 +42,10 @@ char *progname; const char *copyright = "2005-2008"; const char *email = "devel@monitoring-plugins.org"; +#ifdef __sun +#define _XPG4_2 +#endif + /** Monitoring Plugins basic includes */ #include "common.h" #include "netutils.h" @@ -109,18 +113,35 @@ 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 */ + int rta_status; double rtmax; /* max rtt */ double rtmin; /* min rtt */ + double jitter; /* measured jitter */ + int jitter_status; + double jitter_max; /* jitter rtt */ + double jitter_min; /* jitter rtt */ + double EffectiveLatency; + double mos; /* Mean opnion score */ + int mos_status; + double score; /* score */ + int score_status; + u_int last_tdiff; + u_int last_icmp_seq; /* Last ICMP_SEQ to check out of order pkts */ unsigned char pl; /* measured packet loss */ + int pl_status; struct rta_host *next; /* linked list */ + int order_status; } rta_host; #define FLAG_LOST_CAUSE 0x01 /* decidedly dead target. */ /* threshold structure. all values are maximum allowed, exclusive */ typedef struct threshold { - unsigned char pl; /* max allowed packet loss in percent */ - unsigned int rta; /* roundtrip time average, microseconds */ + unsigned char pl; /* max allowed packet loss in percent */ + unsigned int rta; /* roundtrip time average, microseconds */ + double jitter; /* jitter time average, microseconds */ + double mos; /* MOS */ + double score; /* Score */ } threshold; /* the data structure */ @@ -188,6 +209,7 @@ static int wait_for_reply(int, u_int); static int recvfrom_wto(int, void *, unsigned int, struct sockaddr *, u_int *, struct timeval*); static int send_icmp_ping(int, struct rta_host *); static int get_threshold(char *str, threshold *th); +static int get_threshold2(char *str, threshold *, threshold *, int type); static void run_checks(void); static void set_source_ip(char *); static int add_target(char *); @@ -224,6 +246,12 @@ static unsigned int warn_down = 1, crit_down = 1; /* host down threshold values static int min_hosts_alive = -1; float pkt_backoff_factor = 1.5; float target_backoff_factor = 1.5; +int rta_mode=0; +int pl_mode=0; +int jitter_mode=0; +int score_mode=0; +int mos_mode=0; +int order_mode=0; /** code start **/ static void @@ -393,12 +421,14 @@ main(int argc, char **argv) int icmp_sockerrno, udp_sockerrno, tcp_sockerrno; int result; struct rta_host *host; +#ifdef HAVE_SIGACTION + struct sigaction sig_action; +#endif #ifdef SO_TIMESTAMP int on = 1; #endif char *source_ip = NULL; - char * opts_str = "vhVw:c:n:p:t:H:s:i:b:I:l:m:64"; - + char * opts_str = "vhVw:c:n:p:t:H:s:i:b:I:l:m:P:R:J:S:M:O64"; setlocale (LC_ALL, ""); bindtextdomain (PACKAGE, LOCALEDIR); textdomain (PACKAGE); @@ -422,10 +452,19 @@ main(int argc, char **argv) table = NULL; mode = MODE_RTA; + /* Default critical thresholds */ crit.rta = 500000; crit.pl = 80; + crit.jitter = 50; + crit.mos= 3; + crit.score=70; + /* Default warning thresholds */ warn.rta = 200000; warn.pl = 40; + warn.jitter = 40; + warn.mos= 3.5; + warn.score=80; + protocols = HAVE_ICMP | HAVE_UDP | HAVE_TCP; pkt_interval = 80000; /* 80 msec packet interval by default */ packets = 5; @@ -481,16 +520,17 @@ main(int argc, char **argv) /* Reset argument scanning */ optind = 1; - unsigned short size; + unsigned long size; /* parse the arguments */ for(i = 1; i < argc; i++) { while((arg = getopt(argc, argv, opts_str)) != EOF) { + while((arg = getopt(argc, argv, "vhVw:c:n:p:t:H:s:i:b:I:l:m:P:R:J:S:M:O")) != EOF) { switch(arg) { case 'v': debug++; break; case 'b': - size = (unsigned short)strtol(optarg,NULL,0); + size = strtol(optarg,NULL,0); if (size >= (sizeof(struct icmp) + sizeof(struct icmp_ping_data)) && size < MAX_PING_DATA) { icmp_data_size = size; @@ -540,11 +580,34 @@ main(int argc, char **argv) break; case 'V': /* version */ print_revision (progname, NP_VERSION); - exit (STATE_UNKNOWN); + exit (STATE_OK); case 'h': /* help */ print_help (); exit (STATE_UNKNOWN); break; + case 'R': /* RTA mode */ + get_threshold2(optarg, &warn, &crit,1); + rta_mode=1; + break; + case 'P': /* packet loss mode */ + get_threshold2(optarg, &warn, &crit,2); + pl_mode=1; + break; + case 'J': /* packet loss mode */ + get_threshold2(optarg, &warn, &crit,3); + jitter_mode=1; + break; + case 'M': /* MOS mode */ + get_threshold2(optarg, &warn, &crit,4); + mos_mode=1; + break; + case 'S': /* score mode */ + get_threshold2(optarg, &warn, &crit,5); + score_mode=1; + break; + case 'O': /* out of order mode */ + order_mode=1; + break; } } } @@ -631,11 +694,25 @@ main(int argc, char **argv) if(warn.pl > crit.pl) warn.pl = crit.pl; if(warn.rta > crit.rta) warn.rta = crit.rta; if(warn_down > crit_down) crit_down = warn_down; + if(warn.jitter > crit.jitter) crit.jitter = warn.jitter; + if(warn.mos < crit.mos) warn.mos = crit.mos; + if(warn.score < crit.score) warn.score = crit.score; +#ifdef HAVE_SIGACTION + sig_action.sa_sigaction = NULL; + sig_action.sa_handler = finish; + sigfillset(&sig_action.sa_mask); + sig_action.sa_flags = SA_NODEFER|SA_RESTART; + sigaction(SIGINT, &sig_action, NULL); + sigaction(SIGHUP, &sig_action, NULL); + sigaction(SIGTERM, &sig_action, NULL); + sigaction(SIGALRM, &sig_action, NULL); +#else /* HAVE_SIGACTION */ signal(SIGINT, finish); signal(SIGHUP, finish); signal(SIGTERM, finish); signal(SIGALRM, finish); +#endif /* HAVE_SIGACTION */ if(debug) printf("Setting alarm timeout to %u seconds\n", timeout); alarm(timeout); @@ -660,7 +737,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("Timeout must be at least %llu\n", + printf("Timout must be at lest %llu\n", max_completion_time / 1000000 + 1); } } @@ -685,7 +762,11 @@ main(int argc, char **argv) } host = list; +//<<<<<<< HEAD FIXME table = (struct rta_host**)malloc(sizeof(struct rta_host **) * targets); +//======= +// table = malloc(sizeof(struct rta_host *) * targets); +//>>>>>>> jitter-orig i = 0; while(host) { host->id = i*packets; @@ -772,6 +853,7 @@ wait_for_reply(int sock, u_int t) struct icmp_ping_data data; struct timeval wait_start, now; u_int tdiff, i, per_pkt_wait; + double jitter_tmp; if (!(packet.buf = malloc(icmp_pkt_size))) { crash("send_icmp_ping(): failed to malloc %d bytes for send buffer", @@ -890,12 +972,43 @@ wait_for_reply(int sock, u_int t) tdiff = get_timevaldiff(&data.stime, &now); + if (host->last_tdiff>0) { + /* Calculate jitter */ + if (host->last_tdiff > tdiff) { + jitter_tmp = host->last_tdiff - tdiff; + } + else { + jitter_tmp = tdiff - host->last_tdiff; + } + if (host->jitter==0) { + host->jitter=jitter_tmp; + host->jitter_max=jitter_tmp; + host->jitter_min=jitter_tmp; + } + else { + host->jitter+=jitter_tmp; + if (jitter_tmp < host->jitter_min) + host->jitter_min=jitter_tmp; + if (jitter_tmp > host->jitter_max) + host->jitter_max=jitter_tmp; + } + + /* Check if packets in order */ + if (host->last_icmp_seq >= icp.icmp_seq) + host->order_status=STATE_CRITICAL; + } + host->last_tdiff=tdiff; + + host->last_icmp_seq=icp.icmp_seq; + + //printf("%d tdiff %d host->jitter %u host->last_tdiff %u\n", icp.icmp_seq, tdiff, host->jitter, host->last_tdiff); + host->time_waited += tdiff; host->icmp_recv++; icmp_recv++; - if (tdiff > host->rtmax) + if (tdiff > (int)host->rtmax) host->rtmax = tdiff; - if (tdiff < host->rtmin) + if (tdiff < (int)host->rtmin) host->rtmin = tdiff; if(debug) { @@ -1094,8 +1207,10 @@ recvfrom_wto(int sock, void *buf, unsigned int len, struct sockaddr *saddr, hdr.msg_namelen = slen; hdr.msg_iov = &iov; hdr.msg_iovlen = 1; +#ifdef HAVE_MSGHDR_MSG_CONTROL hdr.msg_control = ans_data; hdr.msg_controllen = sizeof(ans_data); +#endif ret = recvmsg(sock, &hdr, 0); #ifdef SO_TIMESTAMP @@ -1125,6 +1240,7 @@ finish(int sig) {"OK", "WARNING", "CRITICAL", "UNKNOWN", "DEPENDENT"}; int hosts_ok = 0; int hosts_warn = 0; + double R; alarm(0); if(debug > 1) printf("finish(%d) called\n", sig); @@ -1140,6 +1256,7 @@ finish(int sig) } /* iterate thrice to calculate values, give output, and print perfparse */ + status=STATE_OK; host = list; while(host) { @@ -1156,19 +1273,104 @@ finish(int sig) pl = ((host->icmp_sent - host->icmp_recv) * 100) / host->icmp_sent; rta = (double)host->time_waited / host->icmp_recv; } - host->pl = pl; - host->rta = rta; - if(pl >= crit.pl || rta >= crit.rta) { - status = STATE_CRITICAL; - } - else if(!status && (pl >= warn.pl || rta >= warn.rta)) { - status = STATE_WARNING; - hosts_warn++; + if (host->icmp_recv>1) { + host->jitter=(host->jitter / (host->icmp_recv - 1)/1000); + host->EffectiveLatency = (rta/1000) + host->jitter * 2 + 10; + if (host->EffectiveLatency < 160) + R = 93.2 - (host->EffectiveLatency / 40); + else + R = 93.2 - ((host->EffectiveLatency - 120) / 10); + R = R - (pl * 2.5); + if (R<0) R=0; + host->score = R; + host->mos= 1 + ((0.035) * R) + ((.000007) * R * (R-60) * (100-R)); } else { - hosts_ok++; + host->jitter=0; + host->jitter_min=0; + host->jitter_max=0; + host->mos=0; + } + host->pl = pl; + host->rta = rta; + + /* if no new mode selected, use old schema */ + if (!rta_mode && !pl_mode && !jitter_mode && !score_mode && !mos_mode && !order_mode) { + rta_mode=1; + pl_mode=1; } + /* Check which mode is on and do the warn / Crit stuff */ + if (rta_mode) { + if(rta >= crit.rta) { + status = STATE_CRITICAL; + host->rta_status=STATE_CRITICAL; + } + else if(status!=STATE_CRITICAL && (rta >= warn.rta)) { + status = STATE_WARNING; + hosts_warn++; + host->rta_status=STATE_WARNING; + } + else { + hosts_ok++; + } + } + if (pl_mode) { + if(pl >= crit.pl) { + status = STATE_CRITICAL; + host->pl_status=STATE_CRITICAL; + } + else if(status!=STATE_CRITICAL && (pl >= warn.pl)) { + status = STATE_WARNING; + hosts_warn++; + host->pl_status=STATE_WARNING; + } + else { + hosts_ok++; + } + } + if (jitter_mode) { + if(host->jitter >= crit.jitter) { + status = STATE_CRITICAL; + host->jitter_status=STATE_CRITICAL; + } + else if(status!=STATE_CRITICAL && (host->jitter >= warn.jitter)) { + status = STATE_WARNING; + hosts_warn++; + host->jitter_status=STATE_WARNING; + } + else { + hosts_ok++; + } + } + if (mos_mode) { + if(host->mos <= crit.mos) { + status = STATE_CRITICAL; + host->mos_status=STATE_CRITICAL; + } + else if(status!=STATE_CRITICAL && (host->mos <= warn.mos)) { + status = STATE_WARNING; + hosts_warn++; + host->mos_status=STATE_WARNING; + } + else { + hosts_ok++; + } + } + if (score_mode) { + if(host->score <= crit.score) { + status = STATE_CRITICAL; + host->score_status=STATE_CRITICAL; + } + else if(status!=STATE_CRITICAL && (host->score <= warn.score)) { + status = STATE_WARNING; + score_mode++; + host->score_status=STATE_WARNING; + } + else { + hosts_ok++; + } + } host = host->next; } /* this is inevitable */ @@ -1178,9 +1380,10 @@ finish(int sig) else if((hosts_ok + hosts_warn) >= min_hosts_alive) status = STATE_WARNING; } printf("%s - ", status_string[status]); - + host = list; while(host) { + if(debug) puts(""); if(i) { if(i < targets) printf(" :: "); @@ -1189,6 +1392,8 @@ finish(int sig) i++; if(!host->icmp_recv) { status = STATE_CRITICAL; + host->rtmin=0; + host->jitter_min=0; if(host->flags & FLAG_LOST_CAUSE) { char address[INET6_ADDRSTRLEN]; parse_address(&host->error_addr, address, sizeof(address)); @@ -1203,26 +1408,92 @@ finish(int sig) } } else { /* !icmp_recv */ - printf("%s: rta %0.3fms, lost %u%%", - host->name, host->rta / 1000, host->pl); + printf("%s ", host->name); + /* rta text output */ + if (rta_mode) { + if (status == STATE_OK) + printf("rta %0.3fms", host->rta / 1000); + else if (status==STATE_WARNING && host->rta_status==status) + printf("rta %0.3fms > %0.3fms", (float)host->rta / 1000, (float)warn.rta/1000); + else if (status==STATE_CRITICAL && host->rta_status==status) + printf("rta %0.3fms > %0.3fms", (float)host->rta / 1000, (float)crit.rta/1000); + } + /* pl text output */ + if (pl_mode) { + if (status == STATE_OK) + printf("lost %u%%", host->pl); + else if (status==STATE_WARNING && host->pl_status==status) + printf("lost %u%% > %u%%", host->pl, warn.pl); + else if (status==STATE_CRITICAL && host->pl_status==status) + printf("lost %u%% > %u%%", host->pl, crit.pl); + } + /* jitter text output */ + if (jitter_mode) { + if (status == STATE_OK) + printf("jitter %0.3fms", (float)host->jitter); + else if (status==STATE_WARNING && host->jitter_status==status) + printf("jitter %0.3fms > %0.3fms", (float)host->jitter, warn.jitter); + else if (status==STATE_CRITICAL && host->jitter_status==status) + printf("jitter %0.3fms > %0.3fms", (float)host->jitter, crit.jitter); + } + /* mos text output */ + if (mos_mode) { + if (status == STATE_OK) + printf("MOS %0.1f", (float)host->mos); + else if (status==STATE_WARNING && host->mos_status==status) + printf("MOS %0.1f < %0.1f", (float)host->mos, (float)warn.mos); + else if (status==STATE_CRITICAL && host->mos_status==status) + printf("MOS %0.1f < %0.1f", (float)host->mos, (float)crit.mos); + } + /* score text output */ + if (score_mode) { + if (status == STATE_OK) + printf("Score %u", (int)host->score); + else if (status==STATE_WARNING && host->score_status==status ) + printf("Score %u < %u", (int)host->score, (int)warn.score); + else if (status==STATE_CRITICAL && host->score_status==status ) + printf("Score %u < %u", (int)host->score, (int)crit.score); + } + /* order statis text output */ + if (order_mode) { + if (status == STATE_OK) + printf("Packets in order"); + else if (status==STATE_CRITICAL && host->order_status==status) + printf("Packets out of order"); + } } - host = host->next; } /* iterate once more for pretty perfparse output */ - printf("|"); + if (!(!rta_mode && !pl_mode && !jitter_mode && !score_mode && !mos_mode && order_mode)) { + printf("|"); + } i = 0; host = list; while(host) { if(debug) puts(""); - printf("%srta=%0.3fms;%0.3f;%0.3f;0; %spl=%u%%;%u;%u;; %srtmax=%0.3fms;;;; %srtmin=%0.3fms;;;; ", + if (rta_mode && host->pl<100) { + // FIXME printf("%srta=%0.3fms;%0.3f;%0.3f;0; %srtmax=%0.3fms;;;; %srtmin=%0.3fms;;;; ",(targets > 1) ? host->name : "", (float)host->rta / 1000, (float)warn.rta / 1000, (float)crit.rta / 1000, (targets > 1) ? host->name : "", (float)host->rtmax / 1000, (targets > 1) ? host->name : "", (float)host->rtmin / 1000); + 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 : "", (float)host->rtmax / 1000, (targets > 1) ? host->name : "", (host->rtmin < INFINITY) ? (float)host->rtmin / 1000 : (float)0); - + } + if (pl_mode) { + printf("%spl=%u%%;%u;%u;0;100 ", (targets > 1) ? host->name : "", host->pl, warn.pl, crit.pl); + } + if (jitter_mode && host->pl<100) { + printf("%sjitter_avg=%0.3fms;%0.3f;%0.3f;0; %sjitter_max=%0.3fms;;;; %sjitter_min=%0.3fms;;;; ", (targets > 1) ? host->name : "", (float)host->jitter, (float)warn.jitter, (float)crit.jitter, (targets > 1) ? host->name : "", (float)host->jitter_max / 1000, (targets > 1) ? host->name : "",(float)host->jitter_min / 1000); + } + if (mos_mode && host->pl<100) { + printf("%smos=%0.1f;%0.1f;%0.1f;0;5 ", (targets > 1) ? host->name : "", (float)host->mos, (float)warn.mos, (float)crit.mos); + } + if (score_mode && host->pl<100) { + printf("%sscore=%u;%u;%u;0;100 ", (targets > 1) ? host->name : "", (int)host->score, (int)warn.score, (int)crit.score); + } host = host->next; } @@ -1312,6 +1583,7 @@ add_target_ip(char *arg, struct sockaddr_storage *in) /* set the values. use calling name for output */ host->name = strdup(arg); + /* fill out the sockaddr_storage struct */ if(address_family == AF_INET) { host_sin = (struct sockaddr_in *)&host->saddr_in; @@ -1324,7 +1596,24 @@ add_target_ip(char *arg, struct sockaddr_storage *in) memcpy(host_sin6->sin6_addr.s6_addr, sin6->sin6_addr.s6_addr, sizeof host_sin6->sin6_addr.s6_addr); } + /* fill out the sockaddr_in struct */ + host->saddr_in.sin_family = AF_INET; + host->saddr_in.sin_addr.s_addr = in->s_addr; host->rtmin = INFINITY; + host->rtmax = 0; + host->jitter=0; + host->jitter_max=0; + host->jitter_min=INFINITY; + host->last_tdiff=0; + host->order_status=STATE_OK; + host->last_icmp_seq=0; + host->rta_status=0; + host->pl_status=0; + host->jitter_status=0; + host->mos_status=0; + host->score_status=0; + host->pl_status=0; + if(!list) list = cursor = host; else cursor->next = host; @@ -1472,7 +1761,7 @@ get_timevar(const char *str) /* unit might be given as ms|m (millisec), * us|u (microsec) or just plain s, for seconds */ - u = p = '\0'; + p = '\0'; u = str[len - 1]; if(len >= 2 && !isdigit((int)str[len - 2])) p = str[len - 2]; if(p && u == 's') u = p; @@ -1484,7 +1773,7 @@ get_timevar(const char *str) else if(u == 's') factor = 1000000; /* seconds */ if(debug > 2) printf("factor is %u\n", factor); - i = strtoul(str, &ptr, 0); + i = strtoul(str, &ptr, 0); if(!ptr || *ptr != '.' || strlen(ptr) < 2 || factor == 1) return i * factor; @@ -1530,6 +1819,46 @@ get_threshold(char *str, threshold *th) return 0; } +/* not too good at checking errors, but it'll do (main() should barfe on -1) */ +static int +get_threshold2(char *str, threshold *warn, threshold *crit, int type) +{ + char *p = NULL, i = 0; + + if(!str || !strlen(str) || !warn || !crit) return -1; + /* pointer magic slims code by 10 lines. i is bof-stop on stupid libc's */ + p = &str[strlen(str) - 1]; + while(p != &str[0]) { + if( (*p == 'm') || (*p == '%') ) *p = '\0'; + else if(*p == ',' && i) { + *p = '\0'; /* reset it so get_timevar(str) works nicely later */ + if (type==1) + crit->rta = atof(p+1)*1000; + else if (type==2) + crit->pl = (unsigned char)strtoul(p+1, NULL, 0); + else if (type==3) + crit->jitter = atof(p+1); + else if (type==4) + crit->mos = atof(p+1); + else if (type==5) + crit->score = atof(p+1); + } + i = 1; + p--; + } + if (type==1) + warn->rta = atof(p)*1000; + else if (type==2) + warn->pl = (unsigned char)strtoul(p, NULL, 0); + if (type==3) + warn->jitter = atof(p); + else if (type==4) + warn->mos = atof(p); + else if (type==5) + warn->score = atof(p); + return 0; +} + unsigned short icmp_checksum(uint16_t *p, size_t n) { @@ -1555,10 +1884,9 @@ icmp_checksum(uint16_t *p, size_t n) void print_help(void) { - /*print_revision (progname);*/ /* FIXME: Why? */ - printf ("Copyright (c) 2005 Andreas Ericsson \n"); + printf (COPYRIGHT, copyright, email); printf ("\n\n"); @@ -1578,11 +1906,29 @@ print_help(void) printf (" %s\n", "-c"); printf (" %s", _("critical threshold (currently ")); printf ("%0.3fms,%u%%)\n", (float)crit.rta / 1000, crit.pl); + + printf (" %s\n", "-R"); + printf (" %s\n", _("RTA, round trip average, mode warning,critical, ex. 100ms,200ms unit in ms")); + printf (" %s\n", "-P"); + printf (" %s\n", _("packet loss mode, ex. 40%,50% , unit in %")); + printf (" %s\n", "-J"); + printf (" %s\n", _("jitter mode warning,critical, ex. 40.000ms,50.000ms , unit in ms ")); + printf (" %s\n", "-M"); + printf (" %s\n", _("MOS mode, between 0 and 4.4 warning,critical, ex. 3.5,3.0")); + printf (" %s\n", "-S"); + printf (" %s\n", _("score mode, max value 100 warning,critical, ex. 80,70 ")); + printf (" %s\n", "-O"); + printf (" %s\n", _("detect out of order ICMP packts ")); + printf (" %s\n", "-H"); + printf (" %s\n", _("specify a target")); printf (" %s\n", "-s"); printf (" %s\n", _("specify a source IP address or device name")); printf (" %s\n", "-n"); printf (" %s", _("number of packets to send (currently ")); printf ("%u)\n",packets); + printf (" %s\n", "-p"); + printf (" %s", _("number of packets to send (currently ")); + printf ("%u)\n",packets); printf (" %s\n", "-i"); printf (" %s", _("max packet interval (currently ")); printf ("%0.3fms)\n",(float)pkt_interval / 1000); @@ -1603,9 +1949,9 @@ print_help(void) 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")); - printf ("\n"); printf ("%s\n", _("Notes:")); + printf ("%s\n", _("If not mode R,P,J,M,S or O is informed, default icmp behavior, RTA and packet loss")); printf (" %s\n", _("The -H switch is optional. Naming a host (or several) to check is not.")); printf ("\n"); printf (" %s\n", _("Threshold format for -w and -c is 200.25,60% for 200.25 msec RTA and 60%"));