summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>2023-10-12 23:37:38 (GMT)
committerGitHub <noreply@github.com>2023-10-12 23:37:38 (GMT)
commit56ba2368d93a4fad4a6d874a2c9bfade1f2b37b0 (patch)
tree14aadfb8054c96873694b40c8aed73227e3b48fd
parent4d8f1dab571ff86af3c3cc8695683d40ef0b5a56 (diff)
parentf5074ac7f01ba95469748531b503c56b31e55cc3 (diff)
downloadmonitoring-plugins-56ba2368d93a4fad4a6d874a2c9bfade1f2b37b0.tar.gz
Merge pull request #1928 from datamuc/merge-jitter
check_icmp: Add support to Jitter, MOS and Score
-rw-r--r--.github/workflows/test.yml2
-rw-r--r--.gitignore2
-rw-r--r--plugins-root/check_icmp.c684
-rw-r--r--plugins-root/t/check_icmp.t58
-rw-r--r--po/de.po22
-rw-r--r--po/fr.po22
-rw-r--r--po/monitoring-plugins.pot22
7 files changed, 699 insertions, 113 deletions
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 0f845de..ea0b38b 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -21,7 +21,7 @@ jobs:
21 uses: codespell-project/actions-codespell@v2 21 uses: codespell-project/actions-codespell@v2
22 with: 22 with:
23 skip: "./.git,./.gitignore,./ABOUT-NLS,*.po,./gl,./po,./tools/squid.conf,./build-aux/ltmain.sh" 23 skip: "./.git,./.gitignore,./ABOUT-NLS,*.po,./gl,./po,./tools/squid.conf,./build-aux/ltmain.sh"
24 ignore_words_list: allright,gord,didi,hda,nd,alis,clen,scrit,ser,fot,te,parm,isnt,consol,oneliners,esponse 24 ignore_words_list: allright,gord,didi,hda,nd,alis,clen,scrit,ser,fot,te,parm,isnt,consol,oneliners,esponse,slac
25 check_filenames: true 25 check_filenames: true
26 check_hidden: true 26 check_hidden: true
27# super-linter: 27# super-linter:
diff --git a/.gitignore b/.gitignore
index 02ca61e..6f903d6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -94,7 +94,7 @@ NP-VERSION-FILE
94/gl/limits.h 94/gl/limits.h
95/gl/malloc/dynarray-skeleton.gl.h 95/gl/malloc/dynarray-skeleton.gl.h
96/gl/malloc/dynarray.gl.h 96/gl/malloc/dynarray.gl.h
97/gl/stdckdint. 97/gl/stdckdint.h
98 98
99# /lib/ 99# /lib/
100/lib/.deps 100/lib/.deps
diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c
index 1d47e9f..303241d 100644
--- a/plugins-root/check_icmp.c
+++ b/plugins-root/check_icmp.c
@@ -43,7 +43,7 @@ const char *copyright = "2005-2008";
43const char *email = "devel@monitoring-plugins.org"; 43const char *email = "devel@monitoring-plugins.org";
44 44
45/** Monitoring Plugins basic includes */ 45/** Monitoring Plugins basic includes */
46#include "common.h" 46#include "../plugins/common.h"
47#include "netutils.h" 47#include "netutils.h"
48#include "utils.h" 48#include "utils.h"
49 49
@@ -109,18 +109,35 @@ typedef struct rta_host {
109 unsigned char icmp_type, icmp_code; /* type and code from errors */ 109 unsigned char icmp_type, icmp_code; /* type and code from errors */
110 unsigned short flags; /* control/status flags */ 110 unsigned short flags; /* control/status flags */
111 double rta; /* measured RTA */ 111 double rta; /* measured RTA */
112 int rta_status; // check result for RTA checks
112 double rtmax; /* max rtt */ 113 double rtmax; /* max rtt */
113 double rtmin; /* min rtt */ 114 double rtmin; /* min rtt */
115 double jitter; /* measured jitter */
116 int jitter_status; // check result for Jitter checks
117 double jitter_max; /* jitter rtt maximum */
118 double jitter_min; /* jitter rtt minimum */
119 double EffectiveLatency;
120 double mos; /* Mean opnion score */
121 int mos_status; // check result for MOS checks
122 double score; /* score */
123 int score_status; // check result for score checks
124 u_int last_tdiff;
125 u_int last_icmp_seq; /* Last ICMP_SEQ to check out of order pkts */
114 unsigned char pl; /* measured packet loss */ 126 unsigned char pl; /* measured packet loss */
127 int pl_status; // check result for packet loss checks
115 struct rta_host *next; /* linked list */ 128 struct rta_host *next; /* linked list */
129 int order_status; // check result for packet order checks
116} rta_host; 130} rta_host;
117 131
118#define FLAG_LOST_CAUSE 0x01 /* decidedly dead target. */ 132#define FLAG_LOST_CAUSE 0x01 /* decidedly dead target. */
119 133
120/* threshold structure. all values are maximum allowed, exclusive */ 134/* threshold structure. all values are maximum allowed, exclusive */
121typedef struct threshold { 135typedef struct threshold {
122 unsigned char pl; /* max allowed packet loss in percent */ 136 unsigned char pl; /* max allowed packet loss in percent */
123 unsigned int rta; /* roundtrip time average, microseconds */ 137 unsigned int rta; /* roundtrip time average, microseconds */
138 double jitter; /* jitter time average, microseconds */
139 double mos; /* MOS */
140 double score; /* Score */
124} threshold; 141} threshold;
125 142
126/* the data structure */ 143/* the data structure */
@@ -159,6 +176,16 @@ typedef union icmp_packet {
159#define MODE_ALL 2 176#define MODE_ALL 2
160#define MODE_ICMP 3 177#define MODE_ICMP 3
161 178
179enum enum_threshold_mode {
180 const_rta_mode,
181 const_packet_loss_mode,
182 const_jitter_mode,
183 const_mos_mode,
184 const_score_mode
185};
186
187typedef enum enum_threshold_mode threshold_mode;
188
162/* the different ping types we can do 189/* the different ping types we can do
163 * TODO: investigate ARP ping as well */ 190 * TODO: investigate ARP ping as well */
164#define HAVE_ICMP 1 191#define HAVE_ICMP 1
@@ -188,6 +215,8 @@ static int wait_for_reply(int, u_int);
188static int recvfrom_wto(int, void *, unsigned int, struct sockaddr *, u_int *, struct timeval*); 215static int recvfrom_wto(int, void *, unsigned int, struct sockaddr *, u_int *, struct timeval*);
189static int send_icmp_ping(int, struct rta_host *); 216static int send_icmp_ping(int, struct rta_host *);
190static int get_threshold(char *str, threshold *th); 217static int get_threshold(char *str, threshold *th);
218static bool get_threshold2(char *str, size_t length, threshold *, threshold *, threshold_mode mode);
219static bool parse_threshold2_helper(char *s, size_t length, threshold *thr, threshold_mode mode);
191static void run_checks(void); 220static void run_checks(void);
192static void set_source_ip(char *); 221static void set_source_ip(char *);
193static int add_target(char *); 222static int add_target(char *);
@@ -199,13 +228,28 @@ static void finish(int);
199static void crash(const char *, ...); 228static void crash(const char *, ...);
200 229
201/** external **/ 230/** external **/
202extern int optind, opterr, optopt; 231extern int optind;
203extern char *optarg; 232extern char *optarg;
204extern char **environ; 233extern char **environ;
205 234
206/** global variables **/ 235/** global variables **/
207static struct rta_host **table, *cursor, *list; 236static struct rta_host **table, *cursor, *list;
208static threshold crit = {80, 500000}, warn = {40, 200000}; 237
238static threshold crit = {
239 .pl = 80,
240 .rta = 500000,
241 .jitter = 0.0,
242 .mos = 0.0,
243 .score = 0.0
244};
245static threshold warn = {
246 .pl = 40,
247 .rta = 200000,
248 .jitter = 0.0,
249 .mos = 0.0,
250 .score = 0.0
251};
252
209static int mode, protocols, sockets, debug = 0, timeout = 10; 253static int mode, protocols, sockets, debug = 0, timeout = 10;
210static unsigned short icmp_data_size = DEFAULT_PING_DATA_SIZE; 254static unsigned short icmp_data_size = DEFAULT_PING_DATA_SIZE;
211static unsigned short icmp_pkt_size = DEFAULT_PING_DATA_SIZE + ICMP_MINLEN; 255static unsigned short icmp_pkt_size = DEFAULT_PING_DATA_SIZE + ICMP_MINLEN;
@@ -224,6 +268,12 @@ static unsigned int warn_down = 1, crit_down = 1; /* host down threshold values
224static int min_hosts_alive = -1; 268static int min_hosts_alive = -1;
225float pkt_backoff_factor = 1.5; 269float pkt_backoff_factor = 1.5;
226float target_backoff_factor = 1.5; 270float target_backoff_factor = 1.5;
271bool rta_mode=false;
272bool pl_mode=false;
273bool jitter_mode=false;
274bool score_mode=false;
275bool mos_mode=false;
276bool order_mode=false;
227 277
228/** code start **/ 278/** code start **/
229static void 279static void
@@ -393,12 +443,14 @@ main(int argc, char **argv)
393 int icmp_sockerrno, udp_sockerrno, tcp_sockerrno; 443 int icmp_sockerrno, udp_sockerrno, tcp_sockerrno;
394 int result; 444 int result;
395 struct rta_host *host; 445 struct rta_host *host;
446#ifdef HAVE_SIGACTION
447 struct sigaction sig_action;
448#endif
396#ifdef SO_TIMESTAMP 449#ifdef SO_TIMESTAMP
397 int on = 1; 450 int on = 1;
398#endif 451#endif
399 char *source_ip = NULL; 452 char *source_ip = NULL;
400 char * opts_str = "vhVw:c:n:p:t:H:s:i:b:I:l:m:64"; 453 char * opts_str = "vhVw:c:n:p:t:H:s:i:b:I:l:m:P:R:J:S:M:O64";
401
402 setlocale (LC_ALL, ""); 454 setlocale (LC_ALL, "");
403 bindtextdomain (PACKAGE, LOCALEDIR); 455 bindtextdomain (PACKAGE, LOCALEDIR);
404 textdomain (PACKAGE); 456 textdomain (PACKAGE);
@@ -407,7 +459,7 @@ main(int argc, char **argv)
407 * that before pointer magic (esp. on network data) */ 459 * that before pointer magic (esp. on network data) */
408 icmp_sockerrno = udp_sockerrno = tcp_sockerrno = sockets = 0; 460 icmp_sockerrno = udp_sockerrno = tcp_sockerrno = sockets = 0;
409 461
410 address_family = -1; 462 address_family = -1;
411 int icmp_proto = IPPROTO_ICMP; 463 int icmp_proto = IPPROTO_ICMP;
412 464
413 /* get calling name the old-fashioned way for portability instead 465 /* get calling name the old-fashioned way for portability instead
@@ -422,10 +474,19 @@ main(int argc, char **argv)
422 table = NULL; 474 table = NULL;
423 475
424 mode = MODE_RTA; 476 mode = MODE_RTA;
477 /* Default critical thresholds */
425 crit.rta = 500000; 478 crit.rta = 500000;
426 crit.pl = 80; 479 crit.pl = 80;
480 crit.jitter = 50;
481 crit.mos= 3;
482 crit.score=70;
483 /* Default warning thresholds */
427 warn.rta = 200000; 484 warn.rta = 200000;
428 warn.pl = 40; 485 warn.pl = 40;
486 warn.jitter = 40;
487 warn.mos= 3.5;
488 warn.score=80;
489
429 protocols = HAVE_ICMP | HAVE_UDP | HAVE_TCP; 490 protocols = HAVE_ICMP | HAVE_UDP | HAVE_TCP;
430 pkt_interval = 80000; /* 80 msec packet interval by default */ 491 pkt_interval = 80000; /* 80 msec packet interval by default */
431 packets = 5; 492 packets = 5;
@@ -481,7 +542,8 @@ main(int argc, char **argv)
481 /* Reset argument scanning */ 542 /* Reset argument scanning */
482 optind = 1; 543 optind = 1;
483 544
484 unsigned short size; 545 unsigned long size;
546 bool err;
485 /* parse the arguments */ 547 /* parse the arguments */
486 for(i = 1; i < argc; i++) { 548 for(i = 1; i < argc; i++) {
487 while((arg = getopt(argc, argv, opts_str)) != EOF) { 549 while((arg = getopt(argc, argv, opts_str)) != EOF) {
@@ -490,7 +552,7 @@ main(int argc, char **argv)
490 debug++; 552 debug++;
491 break; 553 break;
492 case 'b': 554 case 'b':
493 size = (unsigned short)strtol(optarg,NULL,0); 555 size = strtol(optarg,NULL,0);
494 if (size >= (sizeof(struct icmp) + sizeof(struct icmp_ping_data)) && 556 if (size >= (sizeof(struct icmp) + sizeof(struct icmp_ping_data)) &&
495 size < MAX_PING_DATA) { 557 size < MAX_PING_DATA) {
496 icmp_data_size = size; 558 icmp_data_size = size;
@@ -545,6 +607,49 @@ main(int argc, char **argv)
545 print_help (); 607 print_help ();
546 exit (STATE_UNKNOWN); 608 exit (STATE_UNKNOWN);
547 break; 609 break;
610 case 'R': /* RTA mode */
611 err = get_threshold2(optarg, strlen(optarg), &warn, &crit, const_rta_mode);
612 if (!err) {
613 crash("Failed to parse RTA threshold");
614 }
615
616 rta_mode=true;
617 break;
618 case 'P': /* packet loss mode */
619 err = get_threshold2(optarg, strlen(optarg), &warn, &crit, const_packet_loss_mode);
620 if (!err) {
621 crash("Failed to parse packet loss threshold");
622 }
623
624 pl_mode=true;
625 break;
626 case 'J': /* jitter mode */
627 err = get_threshold2(optarg, strlen(optarg), &warn, &crit, const_jitter_mode);
628 if (!err) {
629 crash("Failed to parse jitter threshold");
630 }
631
632 jitter_mode=true;
633 break;
634 case 'M': /* MOS mode */
635 err = get_threshold2(optarg, strlen(optarg), &warn, &crit, const_mos_mode);
636 if (!err) {
637 crash("Failed to parse MOS threshold");
638 }
639
640 mos_mode=true;
641 break;
642 case 'S': /* score mode */
643 err = get_threshold2(optarg, strlen(optarg), &warn, &crit, const_score_mode);
644 if (!err) {
645 crash("Failed to parse score threshold");
646 }
647
648 score_mode=true;
649 break;
650 case 'O': /* out of order mode */
651 order_mode=true;
652 break;
548 } 653 }
549 } 654 }
550 } 655 }
@@ -565,10 +670,10 @@ main(int argc, char **argv)
565 add_target(*argv); 670 add_target(*argv);
566 argv++; 671 argv++;
567 } 672 }
673
568 if(!targets) { 674 if(!targets) {
569 errno = 0; 675 errno = 0;
570 crash("No hosts to check"); 676 crash("No hosts to check");
571 exit(3);
572 } 677 }
573 678
574 // add_target might change address_family 679 // add_target might change address_family
@@ -631,11 +736,25 @@ main(int argc, char **argv)
631 if(warn.pl > crit.pl) warn.pl = crit.pl; 736 if(warn.pl > crit.pl) warn.pl = crit.pl;
632 if(warn.rta > crit.rta) warn.rta = crit.rta; 737 if(warn.rta > crit.rta) warn.rta = crit.rta;
633 if(warn_down > crit_down) crit_down = warn_down; 738 if(warn_down > crit_down) crit_down = warn_down;
634 739 if(warn.jitter > crit.jitter) crit.jitter = warn.jitter;
740 if(warn.mos < crit.mos) warn.mos = crit.mos;
741 if(warn.score < crit.score) warn.score = crit.score;
742
743#ifdef HAVE_SIGACTION
744 sig_action.sa_sigaction = NULL;
745 sig_action.sa_handler = finish;
746 sigfillset(&sig_action.sa_mask);
747 sig_action.sa_flags = SA_NODEFER|SA_RESTART;
748 sigaction(SIGINT, &sig_action, NULL);
749 sigaction(SIGHUP, &sig_action, NULL);
750 sigaction(SIGTERM, &sig_action, NULL);
751 sigaction(SIGALRM, &sig_action, NULL);
752#else /* HAVE_SIGACTION */
635 signal(SIGINT, finish); 753 signal(SIGINT, finish);
636 signal(SIGHUP, finish); 754 signal(SIGHUP, finish);
637 signal(SIGTERM, finish); 755 signal(SIGTERM, finish);
638 signal(SIGALRM, finish); 756 signal(SIGALRM, finish);
757#endif /* HAVE_SIGACTION */
639 if(debug) printf("Setting alarm timeout to %u seconds\n", timeout); 758 if(debug) printf("Setting alarm timeout to %u seconds\n", timeout);
640 alarm(timeout); 759 alarm(timeout);
641 760
@@ -685,7 +804,11 @@ main(int argc, char **argv)
685 } 804 }
686 805
687 host = list; 806 host = list;
688 table = (struct rta_host**)malloc(sizeof(struct rta_host **) * targets); 807 table = malloc(sizeof(struct rta_host *) * targets);
808 if(!table) {
809 crash("main(): malloc failed for host table");
810 }
811
689 i = 0; 812 i = 0;
690 while(host) { 813 while(host) {
691 host->id = i*packets; 814 host->id = i*packets;
@@ -772,6 +895,7 @@ wait_for_reply(int sock, u_int t)
772 struct icmp_ping_data data; 895 struct icmp_ping_data data;
773 struct timeval wait_start, now; 896 struct timeval wait_start, now;
774 u_int tdiff, i, per_pkt_wait; 897 u_int tdiff, i, per_pkt_wait;
898 double jitter_tmp;
775 899
776 if (!(packet.buf = malloc(icmp_pkt_size))) { 900 if (!(packet.buf = malloc(icmp_pkt_size))) {
777 crash("send_icmp_ping(): failed to malloc %d bytes for send buffer", 901 crash("send_icmp_ping(): failed to malloc %d bytes for send buffer",
@@ -890,12 +1014,44 @@ wait_for_reply(int sock, u_int t)
890 1014
891 tdiff = get_timevaldiff(&data.stime, &now); 1015 tdiff = get_timevaldiff(&data.stime, &now);
892 1016
1017 if (host->last_tdiff>0) {
1018 /* Calculate jitter */
1019 if (host->last_tdiff > tdiff) {
1020 jitter_tmp = host->last_tdiff - tdiff;
1021 } else {
1022 jitter_tmp = tdiff - host->last_tdiff;
1023 }
1024
1025 if (host->jitter==0) {
1026 host->jitter=jitter_tmp;
1027 host->jitter_max=jitter_tmp;
1028 host->jitter_min=jitter_tmp;
1029 } else {
1030 host->jitter+=jitter_tmp;
1031
1032 if (jitter_tmp < host->jitter_min) {
1033 host->jitter_min=jitter_tmp;
1034 }
1035
1036 if (jitter_tmp > host->jitter_max) {
1037 host->jitter_max=jitter_tmp;
1038 }
1039 }
1040
1041 /* Check if packets in order */
1042 if (host->last_icmp_seq >= packet.icp->icmp_seq)
1043 host->order_status=STATE_CRITICAL;
1044 }
1045 host->last_tdiff=tdiff;
1046
1047 host->last_icmp_seq=packet.icp->icmp_seq;
1048
893 host->time_waited += tdiff; 1049 host->time_waited += tdiff;
894 host->icmp_recv++; 1050 host->icmp_recv++;
895 icmp_recv++; 1051 icmp_recv++;
896 if (tdiff > host->rtmax) 1052 if (tdiff > (unsigned int)host->rtmax)
897 host->rtmax = tdiff; 1053 host->rtmax = tdiff;
898 if (tdiff < host->rtmin) 1054 if (tdiff < (unsigned int)host->rtmin)
899 host->rtmin = tdiff; 1055 host->rtmin = tdiff;
900 1056
901 if(debug) { 1057 if(debug) {
@@ -1056,7 +1212,9 @@ recvfrom_wto(int sock, void *buf, unsigned int len, struct sockaddr *saddr,
1056 int n, ret; 1212 int n, ret;
1057 struct timeval to, then, now; 1213 struct timeval to, then, now;
1058 fd_set rd, wr; 1214 fd_set rd, wr;
1215#ifdef HAVE_MSGHDR_MSG_CONTROL
1059 char ans_data[4096]; 1216 char ans_data[4096];
1217#endif // HAVE_MSGHDR_MSG_CONTROL
1060 struct msghdr hdr; 1218 struct msghdr hdr;
1061 struct iovec iov; 1219 struct iovec iov;
1062#ifdef SO_TIMESTAMP 1220#ifdef SO_TIMESTAMP
@@ -1094,8 +1252,10 @@ recvfrom_wto(int sock, void *buf, unsigned int len, struct sockaddr *saddr,
1094 hdr.msg_namelen = slen; 1252 hdr.msg_namelen = slen;
1095 hdr.msg_iov = &iov; 1253 hdr.msg_iov = &iov;
1096 hdr.msg_iovlen = 1; 1254 hdr.msg_iovlen = 1;
1255#ifdef HAVE_MSGHDR_MSG_CONTROL
1097 hdr.msg_control = ans_data; 1256 hdr.msg_control = ans_data;
1098 hdr.msg_controllen = sizeof(ans_data); 1257 hdr.msg_controllen = sizeof(ans_data);
1258#endif
1099 1259
1100 ret = recvmsg(sock, &hdr, 0); 1260 ret = recvmsg(sock, &hdr, 0);
1101#ifdef SO_TIMESTAMP 1261#ifdef SO_TIMESTAMP
@@ -1125,6 +1285,8 @@ finish(int sig)
1125 {"OK", "WARNING", "CRITICAL", "UNKNOWN", "DEPENDENT"}; 1285 {"OK", "WARNING", "CRITICAL", "UNKNOWN", "DEPENDENT"};
1126 int hosts_ok = 0; 1286 int hosts_ok = 0;
1127 int hosts_warn = 0; 1287 int hosts_warn = 0;
1288 int this_status;
1289 double R;
1128 1290
1129 alarm(0); 1291 alarm(0);
1130 if(debug > 1) printf("finish(%d) called\n", sig); 1292 if(debug > 1) printf("finish(%d) called\n", sig);
@@ -1140,9 +1302,12 @@ finish(int sig)
1140 } 1302 }
1141 1303
1142 /* iterate thrice to calculate values, give output, and print perfparse */ 1304 /* iterate thrice to calculate values, give output, and print perfparse */
1305 status=STATE_OK;
1143 host = list; 1306 host = list;
1144 1307
1145 while(host) { 1308 while(host) {
1309 this_status = STATE_OK;
1310
1146 if(!host->icmp_recv) { 1311 if(!host->icmp_recv) {
1147 /* rta 0 is ofcourse not entirely correct, but will still show up 1312 /* rta 0 is ofcourse not entirely correct, but will still show up
1148 * conspicuously as missing entries in perfparse and cacti */ 1313 * conspicuously as missing entries in perfparse and cacti */
@@ -1151,26 +1316,138 @@ finish(int sig)
1151 status = STATE_CRITICAL; 1316 status = STATE_CRITICAL;
1152 /* up the down counter if not already counted */ 1317 /* up the down counter if not already counted */
1153 if(!(host->flags & FLAG_LOST_CAUSE) && targets_alive) targets_down++; 1318 if(!(host->flags & FLAG_LOST_CAUSE) && targets_alive) targets_down++;
1154 } 1319 } else {
1155 else {
1156 pl = ((host->icmp_sent - host->icmp_recv) * 100) / host->icmp_sent; 1320 pl = ((host->icmp_sent - host->icmp_recv) * 100) / host->icmp_sent;
1157 rta = (double)host->time_waited / host->icmp_recv; 1321 rta = (double)host->time_waited / host->icmp_recv;
1158 } 1322 }
1323
1324 if (host->icmp_recv>1) {
1325 /*
1326 * This algorithm is probably pretty much blindly copied from
1327 * locations like this one: https://www.slac.stanford.edu/comp/net/wan-mon/tutorial.html#mos
1328 * It calculates a MOS value (range of 1 to 5, where 1 is bad and 5 really good).
1329 * According to some quick research MOS originates from the Audio/Video transport network area.
1330 * Whether it can and should be computed from ICMP data, I can not say.
1331 *
1332 * Anyway the basic idea is to map a value "R" with a range of 0-100 to the MOS value
1333 *
1334 * MOS stands likely for Mean Opinion Score ( https://en.wikipedia.org/wiki/Mean_Opinion_Score )
1335 *
1336 * More links:
1337 * - https://confluence.slac.stanford.edu/display/IEPM/MOS
1338 */
1339 host->jitter=(host->jitter / (host->icmp_recv - 1)/1000);
1340
1341 /*
1342 * Take the average round trip latency (in milliseconds), add
1343 * round trip jitter, but double the impact to latency
1344 * then add 10 for protocol latencies (in milliseconds).
1345 */
1346 host->EffectiveLatency = (rta/1000) + host->jitter * 2 + 10;
1347
1348 if (host->EffectiveLatency < 160) {
1349 R = 93.2 - (host->EffectiveLatency / 40);
1350 } else {
1351 R = 93.2 - ((host->EffectiveLatency - 120) / 10);
1352 }
1353
1354 // Now, let us deduct 2.5 R values per percentage of packet loss (i.e. a
1355 // loss of 5% will be entered as 5).
1356 R = R - (pl * 2.5);
1357
1358 if (R < 0) {
1359 R = 0;
1360 }
1361
1362 host->score = R;
1363 host->mos= 1 + ((0.035) * R) + ((.000007) * R * (R-60) * (100-R));
1364 } else {
1365 host->jitter=0;
1366 host->jitter_min=0;
1367 host->jitter_max=0;
1368 host->mos=0;
1369 }
1370
1159 host->pl = pl; 1371 host->pl = pl;
1160 host->rta = rta; 1372 host->rta = rta;
1161 if(pl >= crit.pl || rta >= crit.rta) { 1373
1162 status = STATE_CRITICAL; 1374 /* if no new mode selected, use old schema */
1375 if (!rta_mode && !pl_mode && !jitter_mode && !score_mode && !mos_mode && !order_mode) {
1376 rta_mode = true;
1377 pl_mode = true;
1163 } 1378 }
1164 else if(!status && (pl >= warn.pl || rta >= warn.rta)) { 1379
1165 status = STATE_WARNING; 1380 /* Check which mode is on and do the warn / Crit stuff */
1166 hosts_warn++; 1381 if (rta_mode) {
1382 if(rta >= crit.rta) {
1383 this_status = STATE_CRITICAL;
1384 status = STATE_CRITICAL;
1385 host->rta_status=STATE_CRITICAL;
1386 } else if(status!=STATE_CRITICAL && (rta >= warn.rta)) {
1387 this_status = (this_status <= STATE_WARNING ? STATE_WARNING : this_status);
1388 status = STATE_WARNING;
1389 host->rta_status=STATE_WARNING;
1390 }
1391 }
1392
1393 if (pl_mode) {
1394 if(pl >= crit.pl) {
1395 this_status = STATE_CRITICAL;
1396 status = STATE_CRITICAL;
1397 host->pl_status=STATE_CRITICAL;
1398 } else if(status!=STATE_CRITICAL && (pl >= warn.pl)) {
1399 this_status = (this_status <= STATE_WARNING ? STATE_WARNING : this_status);
1400 status = STATE_WARNING;
1401 host->pl_status=STATE_WARNING;
1402 }
1403 }
1404
1405 if (jitter_mode) {
1406 if(host->jitter >= crit.jitter) {
1407 this_status = STATE_CRITICAL;
1408 status = STATE_CRITICAL;
1409 host->jitter_status=STATE_CRITICAL;
1410 } else if(status!=STATE_CRITICAL && (host->jitter >= warn.jitter)) {
1411 this_status = (this_status <= STATE_WARNING ? STATE_WARNING : this_status);
1412 status = STATE_WARNING;
1413 host->jitter_status=STATE_WARNING;
1414 }
1415 }
1416
1417 if (mos_mode) {
1418 if(host->mos <= crit.mos) {
1419 this_status = STATE_CRITICAL;
1420 status = STATE_CRITICAL;
1421 host->mos_status=STATE_CRITICAL;
1422 } else if(status!=STATE_CRITICAL && (host->mos <= warn.mos)) {
1423 this_status = (this_status <= STATE_WARNING ? STATE_WARNING : this_status);
1424 status = STATE_WARNING;
1425 host->mos_status=STATE_WARNING;
1426 }
1427 }
1428
1429 if (score_mode) {
1430 if(host->score <= crit.score) {
1431 this_status = STATE_CRITICAL;
1432 status = STATE_CRITICAL;
1433 host->score_status=STATE_CRITICAL;
1434 } else if(status!=STATE_CRITICAL && (host->score <= warn.score)) {
1435 this_status = (this_status <= STATE_WARNING ? STATE_WARNING : this_status);
1436 status = STATE_WARNING;
1437 host->score_status=STATE_WARNING;
1438 }
1167 } 1439 }
1168 else { 1440
1441 if (this_status == STATE_WARNING) {
1442 hosts_warn++;
1443 } else if (this_status == STATE_OK) {
1169 hosts_ok++; 1444 hosts_ok++;
1170 } 1445 }
1171 1446
1172 host = host->next; 1447 host = host->next;
1173 } 1448 }
1449
1450
1174 /* this is inevitable */ 1451 /* this is inevitable */
1175 if(!targets_alive) status = STATE_CRITICAL; 1452 if(!targets_alive) status = STATE_CRITICAL;
1176 if(min_hosts_alive > -1) { 1453 if(min_hosts_alive > -1) {
@@ -1181,6 +1458,7 @@ finish(int sig)
1181 1458
1182 host = list; 1459 host = list;
1183 while(host) { 1460 while(host) {
1461
1184 if(debug) puts(""); 1462 if(debug) puts("");
1185 if(i) { 1463 if(i) {
1186 if(i < targets) printf(" :: "); 1464 if(i < targets) printf(" :: ");
@@ -1189,6 +1467,8 @@ finish(int sig)
1189 i++; 1467 i++;
1190 if(!host->icmp_recv) { 1468 if(!host->icmp_recv) {
1191 status = STATE_CRITICAL; 1469 status = STATE_CRITICAL;
1470 host->rtmin=0;
1471 host->jitter_min=0;
1192 if(host->flags & FLAG_LOST_CAUSE) { 1472 if(host->flags & FLAG_LOST_CAUSE) {
1193 char address[INET6_ADDRSTRLEN]; 1473 char address[INET6_ADDRSTRLEN];
1194 parse_address(&host->error_addr, address, sizeof(address)); 1474 parse_address(&host->error_addr, address, sizeof(address));
@@ -1197,31 +1477,117 @@ finish(int sig)
1197 get_icmp_error_msg(host->icmp_type, host->icmp_code), 1477 get_icmp_error_msg(host->icmp_type, host->icmp_code),
1198 address, 1478 address,
1199 100); 1479 100);
1200 } 1480 } else { /* not marked as lost cause, so we have no flags for it */
1201 else { /* not marked as lost cause, so we have no flags for it */
1202 printf("%s: rta nan, lost 100%%", host->name); 1481 printf("%s: rta nan, lost 100%%", host->name);
1203 } 1482 }
1483 } else { /* !icmp_recv */
1484 printf("%s", host->name);
1485 /* rta text output */
1486 if (rta_mode) {
1487 if (status == STATE_OK)
1488 printf(" rta %0.3fms", host->rta / 1000);
1489 else if (status==STATE_WARNING && host->rta_status==status)
1490 printf(" rta %0.3fms > %0.3fms", (float)host->rta / 1000, (float)warn.rta/1000);
1491 else if (status==STATE_CRITICAL && host->rta_status==status)
1492 printf(" rta %0.3fms > %0.3fms", (float)host->rta / 1000, (float)crit.rta/1000);
1493 }
1494 /* pl text output */
1495 if (pl_mode) {
1496 if (status == STATE_OK)
1497 printf(" lost %u%%", host->pl);
1498 else if (status==STATE_WARNING && host->pl_status==status)
1499 printf(" lost %u%% > %u%%", host->pl, warn.pl);
1500 else if (status==STATE_CRITICAL && host->pl_status==status)
1501 printf(" lost %u%% > %u%%", host->pl, crit.pl);
1502 }
1503 /* jitter text output */
1504 if (jitter_mode) {
1505 if (status == STATE_OK)
1506 printf(" jitter %0.3fms", (float)host->jitter);
1507 else if (status==STATE_WARNING && host->jitter_status==status)
1508 printf(" jitter %0.3fms > %0.3fms", (float)host->jitter, warn.jitter);
1509 else if (status==STATE_CRITICAL && host->jitter_status==status)
1510 printf(" jitter %0.3fms > %0.3fms", (float)host->jitter, crit.jitter);
1511 }
1512 /* mos text output */
1513 if (mos_mode) {
1514 if (status == STATE_OK)
1515 printf(" MOS %0.1f", (float)host->mos);
1516 else if (status==STATE_WARNING && host->mos_status==status)
1517 printf(" MOS %0.1f < %0.1f", (float)host->mos, (float)warn.mos);
1518 else if (status==STATE_CRITICAL && host->mos_status==status)
1519 printf(" MOS %0.1f < %0.1f", (float)host->mos, (float)crit.mos);
1520 }
1521 /* score text output */
1522 if (score_mode) {
1523 if (status == STATE_OK)
1524 printf(" Score %u", (int)host->score);
1525 else if (status==STATE_WARNING && host->score_status==status )
1526 printf(" Score %u < %u", (int)host->score, (int)warn.score);
1527 else if (status==STATE_CRITICAL && host->score_status==status )
1528 printf(" Score %u < %u", (int)host->score, (int)crit.score);
1529 }
1530 /* order statis text output */
1531 if (order_mode) {
1532 if (status == STATE_OK)
1533 printf(" Packets in order");
1534 else if (status==STATE_CRITICAL && host->order_status==status)
1535 printf(" Packets out of order");
1536 }
1204 } 1537 }
1205 else { /* !icmp_recv */
1206 printf("%s: rta %0.3fms, lost %u%%",
1207 host->name, host->rta / 1000, host->pl);
1208 }
1209
1210 host = host->next; 1538 host = host->next;
1211 } 1539 }
1212 1540
1213 /* iterate once more for pretty perfparse output */ 1541 /* iterate once more for pretty perfparse output */
1214 printf("|"); 1542 if (!(!rta_mode && !pl_mode && !jitter_mode && !score_mode && !mos_mode && order_mode)) {
1543 printf("|");
1544 }
1215 i = 0; 1545 i = 0;
1216 host = list; 1546 host = list;
1217 while(host) { 1547 while(host) {
1218 if(debug) puts(""); 1548 if(debug) puts("");
1219 printf("%srta=%0.3fms;%0.3f;%0.3f;0; %spl=%u%%;%u;%u;; %srtmax=%0.3fms;;;; %srtmin=%0.3fms;;;; ", 1549
1550 if (rta_mode && host->pl<100) {
1551 printf("%srta=%0.3fms;%0.3f;%0.3f;0; %srtmax=%0.3fms;;;; %srtmin=%0.3fms;;;; ",
1220 (targets > 1) ? host->name : "", 1552 (targets > 1) ? host->name : "",
1221 host->rta / 1000, (float)warn.rta / 1000, (float)crit.rta / 1000, 1553 host->rta / 1000, (float)warn.rta / 1000, (float)crit.rta / 1000,
1222 (targets > 1) ? host->name : "", host->pl, warn.pl, crit.pl,
1223 (targets > 1) ? host->name : "", (float)host->rtmax / 1000, 1554 (targets > 1) ? host->name : "", (float)host->rtmax / 1000,
1224 (targets > 1) ? host->name : "", (host->rtmin < INFINITY) ? (float)host->rtmin / 1000 : (float)0); 1555 (targets > 1) ? host->name : "", (host->rtmin < INFINITY) ? (float)host->rtmin / 1000 : (float)0);
1556 }
1557
1558 if (pl_mode) {
1559 printf("%spl=%u%%;%u;%u;0;100 ", (targets > 1) ? host->name : "", host->pl, warn.pl, crit.pl);
1560 }
1561
1562 if (jitter_mode && host->pl<100) {
1563 printf("%sjitter_avg=%0.3fms;%0.3f;%0.3f;0; %sjitter_max=%0.3fms;;;; %sjitter_min=%0.3fms;;;; ",
1564 (targets > 1) ? host->name : "",
1565 (float)host->jitter,
1566 (float)warn.jitter,
1567 (float)crit.jitter,
1568 (targets > 1) ? host->name : "",
1569 (float)host->jitter_max / 1000, (targets > 1) ? host->name : "",
1570 (float)host->jitter_min / 1000
1571 );
1572 }
1573
1574 if (mos_mode && host->pl<100) {
1575 printf("%smos=%0.1f;%0.1f;%0.1f;0;5 ",
1576 (targets > 1) ? host->name : "",
1577 (float)host->mos,
1578 (float)warn.mos,
1579 (float)crit.mos
1580 );
1581 }
1582
1583 if (score_mode && host->pl<100) {
1584 printf("%sscore=%u;%u;%u;0;100 ",
1585 (targets > 1) ? host->name : "",
1586 (int)host->score,
1587 (int)warn.score,
1588 (int)crit.score
1589 );
1590 }
1225 1591
1226 host = host->next; 1592 host = host->next;
1227 } 1593 }
@@ -1312,6 +1678,7 @@ add_target_ip(char *arg, struct sockaddr_storage *in)
1312 /* set the values. use calling name for output */ 1678 /* set the values. use calling name for output */
1313 host->name = strdup(arg); 1679 host->name = strdup(arg);
1314 1680
1681
1315 /* fill out the sockaddr_storage struct */ 1682 /* fill out the sockaddr_storage struct */
1316 if(address_family == AF_INET) { 1683 if(address_family == AF_INET) {
1317 host_sin = (struct sockaddr_in *)&host->saddr_in; 1684 host_sin = (struct sockaddr_in *)&host->saddr_in;
@@ -1324,7 +1691,22 @@ add_target_ip(char *arg, struct sockaddr_storage *in)
1324 memcpy(host_sin6->sin6_addr.s6_addr, sin6->sin6_addr.s6_addr, sizeof host_sin6->sin6_addr.s6_addr); 1691 memcpy(host_sin6->sin6_addr.s6_addr, sin6->sin6_addr.s6_addr, sizeof host_sin6->sin6_addr.s6_addr);
1325 } 1692 }
1326 1693
1694 /* fill out the sockaddr_in struct */
1327 host->rtmin = INFINITY; 1695 host->rtmin = INFINITY;
1696 host->rtmax = 0;
1697 host->jitter=0;
1698 host->jitter_max=0;
1699 host->jitter_min=INFINITY;
1700 host->last_tdiff=0;
1701 host->order_status=STATE_OK;
1702 host->last_icmp_seq=0;
1703 host->rta_status=0;
1704 host->pl_status=0;
1705 host->jitter_status=0;
1706 host->mos_status=0;
1707 host->score_status=0;
1708 host->pl_status=0;
1709
1328 1710
1329 if(!list) list = cursor = host; 1711 if(!list) list = cursor = host;
1330 else cursor->next = host; 1712 else cursor->next = host;
@@ -1408,7 +1790,7 @@ add_target(char *arg)
1408 } 1790 }
1409 break; 1791 break;
1410 } 1792 }
1411 freeaddrinfo(res); 1793 freeaddrinfo(res);
1412 1794
1413 return 0; 1795 return 0;
1414} 1796}
@@ -1472,7 +1854,7 @@ get_timevar(const char *str)
1472 1854
1473 /* unit might be given as ms|m (millisec), 1855 /* unit might be given as ms|m (millisec),
1474 * us|u (microsec) or just plain s, for seconds */ 1856 * us|u (microsec) or just plain s, for seconds */
1475 u = p = '\0'; 1857 p = '\0';
1476 u = str[len - 1]; 1858 u = str[len - 1];
1477 if(len >= 2 && !isdigit((int)str[len - 2])) p = str[len - 2]; 1859 if(len >= 2 && !isdigit((int)str[len - 2])) p = str[len - 2];
1478 if(p && u == 's') u = p; 1860 if(p && u == 's') u = p;
@@ -1530,6 +1912,81 @@ get_threshold(char *str, threshold *th)
1530 return 0; 1912 return 0;
1531} 1913}
1532 1914
1915/*
1916 * This functions receives a pointer to a string which should contain a threshold for the
1917 * rta, packet_loss, jitter, mos or score mode in the form number,number[m|%]* assigns the
1918 * parsed number to the corresponding threshold variable.
1919 * @param[in,out] str String containing the given threshold values
1920 * @param[in] length strlen(str)
1921 * @param[out] warn Pointer to the warn threshold struct to which the values should be assigned
1922 * @param[out] crit Pointer to the crit threshold struct to which the values should be assigned
1923 * @param[in] mode Determines whether this a threshold for rta, packet_loss, jitter, mos or score (exclusively)
1924 */
1925static bool get_threshold2(char *str, size_t length, threshold *warn, threshold *crit, threshold_mode mode) {
1926 if (!str || !length || !warn || !crit) return false;
1927
1928
1929 // p points to the last char in str
1930 char *p = &str[length - 1];
1931
1932 // first_iteration is bof-stop on stupid libc's
1933 bool first_iteration = true;
1934
1935 while(p != &str[0]) {
1936 if( (*p == 'm') || (*p == '%') ) {
1937 *p = '\0';
1938 } else if(*p == ',' && !first_iteration) {
1939 *p = '\0'; /* reset it so get_timevar(str) works nicely later */
1940
1941 char *start_of_value = p + 1;
1942
1943 if (!parse_threshold2_helper(start_of_value, strlen(start_of_value), crit, mode)){
1944 return false;
1945 }
1946
1947 }
1948 first_iteration = false;
1949 p--;
1950 }
1951
1952 return parse_threshold2_helper(p, strlen(p), warn, mode);
1953}
1954
1955static bool parse_threshold2_helper(char *s, size_t length, threshold *thr, threshold_mode mode) {
1956 char *resultChecker = {0};
1957
1958 switch (mode) {
1959 case const_rta_mode:
1960 thr->rta = strtod(s, &resultChecker) * 1000;
1961 break;
1962 case const_packet_loss_mode:
1963 thr->pl = (unsigned char)strtoul(s, &resultChecker, 0);
1964 break;
1965 case const_jitter_mode:
1966 thr->jitter = strtod(s, &resultChecker);
1967
1968 break;
1969 case const_mos_mode:
1970 thr->mos = strtod(s, &resultChecker);
1971 break;
1972 case const_score_mode:
1973 thr->score = strtod(s, &resultChecker);
1974 break;
1975 }
1976
1977 if (resultChecker == s) {
1978 // Failed to parse
1979 return false;
1980 }
1981
1982 if (resultChecker != (s + length)) {
1983 // Trailing symbols
1984 return false;
1985 }
1986
1987 return true;
1988}
1989
1533unsigned short 1990unsigned short
1534icmp_checksum(uint16_t *p, size_t n) 1991icmp_checksum(uint16_t *p, size_t n)
1535{ 1992{
@@ -1555,74 +2012,91 @@ icmp_checksum(uint16_t *p, size_t n)
1555void 2012void
1556print_help(void) 2013print_help(void)
1557{ 2014{
1558 2015 /*print_revision (progname);*/ /* FIXME: Why? */
1559 /*print_revision (progname);*/ /* FIXME: Why? */ 2016 printf ("Copyright (c) 2005 Andreas Ericsson <ae@op5.se>\n");
1560 2017
1561 printf ("Copyright (c) 2005 Andreas Ericsson <ae@op5.se>\n"); 2018 printf (COPYRIGHT, copyright, email);
1562 printf (COPYRIGHT, copyright, email); 2019
1563 2020 printf ("\n\n");
1564 printf ("\n\n"); 2021
1565 2022 print_usage ();
1566 print_usage (); 2023
1567 2024 printf (UT_HELP_VRSN);
1568 printf (UT_HELP_VRSN); 2025 printf (UT_EXTRA_OPTS);
1569 printf (UT_EXTRA_OPTS); 2026
1570 2027 printf (" %s\n", "-H");
1571 printf (" %s\n", "-H"); 2028 printf (" %s\n", _("specify a target"));
1572 printf (" %s\n", _("specify a target")); 2029 printf (" %s\n", "[-4|-6]");
1573 printf (" %s\n", "[-4|-6]"); 2030 printf (" %s\n", _("Use IPv4 (default) or IPv6 to communicate with the targets"));
1574 printf (" %s\n", _("Use IPv4 (default) or IPv6 to communicate with the targets")); 2031 printf (" %s\n", "-w");
1575 printf (" %s\n", "-w"); 2032 printf (" %s", _("warning threshold (currently "));
1576 printf (" %s", _("warning threshold (currently ")); 2033 printf ("%0.3fms,%u%%)\n", (float)warn.rta / 1000, warn.pl);
1577 printf ("%0.3fms,%u%%)\n", (float)warn.rta / 1000, warn.pl); 2034 printf (" %s\n", "-c");
1578 printf (" %s\n", "-c"); 2035 printf (" %s", _("critical threshold (currently "));
1579 printf (" %s", _("critical threshold (currently ")); 2036 printf ("%0.3fms,%u%%)\n", (float)crit.rta / 1000, crit.pl);
1580 printf ("%0.3fms,%u%%)\n", (float)crit.rta / 1000, crit.pl); 2037
1581 printf (" %s\n", "-s"); 2038 printf (" %s\n", "-R");
1582 printf (" %s\n", _("specify a source IP address or device name")); 2039 printf (" %s\n", _("RTA, round trip average, mode warning,critical, ex. 100ms,200ms unit in ms"));
1583 printf (" %s\n", "-n"); 2040 printf (" %s\n", "-P");
1584 printf (" %s", _("number of packets to send (currently ")); 2041 printf (" %s\n", _("packet loss mode, ex. 40%,50% , unit in %"));
1585 printf ("%u)\n",packets); 2042 printf (" %s\n", "-J");
1586 printf (" %s\n", "-i"); 2043 printf (" %s\n", _("jitter mode warning,critical, ex. 40.000ms,50.000ms , unit in ms "));
1587 printf (" %s", _("max packet interval (currently ")); 2044 printf (" %s\n", "-M");
1588 printf ("%0.3fms)\n",(float)pkt_interval / 1000); 2045 printf (" %s\n", _("MOS mode, between 0 and 4.4 warning,critical, ex. 3.5,3.0"));
1589 printf (" %s\n", "-I"); 2046 printf (" %s\n", "-S");
1590 printf (" %s", _("max target interval (currently ")); 2047 printf (" %s\n", _("score mode, max value 100 warning,critical, ex. 80,70 "));
1591 printf ("%0.3fms)\n", (float)target_interval / 1000); 2048 printf (" %s\n", "-O");
1592 printf (" %s\n", "-m"); 2049 printf (" %s\n", _("detect out of order ICMP packts "));
1593 printf (" %s",_("number of alive hosts required for success")); 2050 printf (" %s\n", "-H");
1594 printf ("\n"); 2051 printf (" %s\n", _("specify a target"));
1595 printf (" %s\n", "-l"); 2052 printf (" %s\n", "-s");
1596 printf (" %s", _("TTL on outgoing packets (currently ")); 2053 printf (" %s\n", _("specify a source IP address or device name"));
1597 printf ("%u)\n", ttl); 2054 printf (" %s\n", "-n");
1598 printf (" %s\n", "-t"); 2055 printf (" %s", _("number of packets to send (currently "));
1599 printf (" %s",_("timeout value (seconds, currently ")); 2056 printf ("%u)\n",packets);
1600 printf ("%u)\n", timeout); 2057 printf (" %s\n", "-p");
1601 printf (" %s\n", "-b"); 2058 printf (" %s", _("number of packets to send (currently "));
1602 printf (" %s\n", _("Number of icmp data bytes to send")); 2059 printf ("%u)\n",packets);
1603 printf (" %s %u + %d)\n", _("Packet size will be data bytes + icmp header (currently"),icmp_data_size, ICMP_MINLEN); 2060 printf (" %s\n", "-i");
1604 printf (" %s\n", "-v"); 2061 printf (" %s", _("max packet interval (currently "));
1605 printf (" %s\n", _("verbose")); 2062 printf ("%0.3fms)\n",(float)pkt_interval / 1000);
1606 2063 printf (" %s\n", "-I");
1607 printf ("\n"); 2064 printf (" %s", _("max target interval (currently "));
1608 printf ("%s\n", _("Notes:")); 2065 printf ("%0.3fms)\n", (float)target_interval / 1000);
1609 printf (" %s\n", _("The -H switch is optional. Naming a host (or several) to check is not.")); 2066 printf (" %s\n", "-m");
1610 printf ("\n"); 2067 printf (" %s",_("number of alive hosts required for success"));
1611 printf (" %s\n", _("Threshold format for -w and -c is 200.25,60% for 200.25 msec RTA and 60%")); 2068 printf ("\n");
1612 printf (" %s\n", _("packet loss. The default values should work well for most users.")); 2069 printf (" %s\n", "-l");
1613 printf (" %s\n", _("You can specify different RTA factors using the standardized abbreviations")); 2070 printf (" %s", _("TTL on outgoing packets (currently "));
1614 printf (" %s\n", _("us (microseconds), ms (milliseconds, default) or just plain s for seconds.")); 2071 printf ("%u)\n", ttl);
1615/* -d not yet implemented */ 2072 printf (" %s\n", "-t");
1616/* printf ("%s\n", _("Threshold format for -d is warn,crit. 12,14 means WARNING if >= 12 hops")); 2073 printf (" %s",_("timeout value (seconds, currently "));
1617 printf ("%s\n", _("are spent and CRITICAL if >= 14 hops are spent.")); 2074 printf ("%u)\n", timeout);
1618 printf ("%s\n\n", _("NOTE: Some systems decrease TTL when forming ICMP_ECHOREPLY, others do not."));*/ 2075 printf (" %s\n", "-b");
1619 printf ("\n"); 2076 printf (" %s\n", _("Number of icmp data bytes to send"));
1620 printf (" %s\n", _("The -v switch can be specified several times for increased verbosity.")); 2077 printf (" %s %u + %d)\n", _("Packet size will be data bytes + icmp header (currently"),icmp_data_size, ICMP_MINLEN);
1621/* printf ("%s\n", _("Long options are currently unsupported.")); 2078 printf (" %s\n", "-v");
1622 printf ("%s\n", _("Options marked with * require an argument")); 2079 printf (" %s\n", _("verbose"));
1623*/ 2080 printf ("\n");
1624 2081 printf ("%s\n", _("Notes:"));
1625 printf (UT_SUPPORT); 2082 printf (" %s\n", _("If none of R,P,J,M,S or O is specified, default behavior is -R -P"));
2083 printf (" %s\n", _("The -H switch is optional. Naming a host (or several) to check is not."));
2084 printf ("\n");
2085 printf (" %s\n", _("Threshold format for -w and -c is 200.25,60% for 200.25 msec RTA and 60%"));
2086 printf (" %s\n", _("packet loss. The default values should work well for most users."));
2087 printf (" %s\n", _("You can specify different RTA factors using the standardized abbreviations"));
2088 printf (" %s\n", _("us (microseconds), ms (milliseconds, default) or just plain s for seconds."));
2089 /* -d not yet implemented */
2090 /* printf ("%s\n", _("Threshold format for -d is warn,crit. 12,14 means WARNING if >= 12 hops"));
2091 printf ("%s\n", _("are spent and CRITICAL if >= 14 hops are spent."));
2092 printf ("%s\n\n", _("NOTE: Some systems decrease TTL when forming ICMP_ECHOREPLY, others do not."));*/
2093 printf ("\n");
2094 printf (" %s\n", _("The -v switch can be specified several times for increased verbosity."));
2095 /* printf ("%s\n", _("Long options are currently unsupported."));
2096 printf ("%s\n", _("Options marked with * require an argument"));
2097 */
2098
2099 printf (UT_SUPPORT);
1626} 2100}
1627 2101
1628 2102
@@ -1630,6 +2104,6 @@ print_help(void)
1630void 2104void
1631print_usage (void) 2105print_usage (void)
1632{ 2106{
1633 printf ("%s\n", _("Usage:")); 2107 printf ("%s\n", _("Usage:"));
1634 printf(" %s [options] [-H] host1 host2 hostN\n", progname); 2108 printf(" %s [options] [-H] host1 host2 hostN\n", progname);
1635} 2109}
diff --git a/plugins-root/t/check_icmp.t b/plugins-root/t/check_icmp.t
index 96addd3..4f9db86 100644
--- a/plugins-root/t/check_icmp.t
+++ b/plugins-root/t/check_icmp.t
@@ -12,14 +12,14 @@ my $allow_sudo = getTestParameter( "NP_ALLOW_SUDO",
12 "no" ); 12 "no" );
13 13
14if ($allow_sudo eq "yes" or $> == 0) { 14if ($allow_sudo eq "yes" or $> == 0) {
15 plan tests => 20; 15 plan tests => 39;
16} else { 16} else {
17 plan skip_all => "Need sudo to test check_icmp"; 17 plan skip_all => "Need sudo to test check_icmp";
18} 18}
19my $sudo = $> == 0 ? '' : 'sudo'; 19my $sudo = $> == 0 ? '' : 'sudo';
20 20
21my $successOutput = '/OK - .*?: rta (?:[\d\.]+ms)|(?:nan), lost \d+%/'; 21my $successOutput = '/OK - .*? rta (?:[\d\.]+ms)|(?:nan), lost \d+%/';
22my $failureOutput = '/(WARNING|CRITICAL) - .*?: rta [\d\.]+ms, lost \d%/'; 22my $failureOutput = '/(WARNING|CRITICAL) - .*? rta (?:[\d\.]+ms > [\d\.]+ms|nan)/';
23 23
24my $host_responsive = getTestParameter( "NP_HOST_RESPONSIVE", 24my $host_responsive = getTestParameter( "NP_HOST_RESPONSIVE",
25 "The hostname of system responsive to network requests", 25 "The hostname of system responsive to network requests",
@@ -54,7 +54,7 @@ is( $res->return_code, 2, "Syntax ok, with forced critical" );
54like( $res->output, $failureOutput, "Output OK" ); 54like( $res->output, $failureOutput, "Output OK" );
55 55
56$res = NPTest->testCmd( 56$res = NPTest->testCmd(
57 "$sudo ./check_icmp -H $host_nonresponsive -w 10000ms,100% -c 10000ms,100%" 57 "$sudo ./check_icmp -H $host_nonresponsive -w 10000ms,100% -c 10000ms,100% -t 2"
58 ); 58 );
59is( $res->return_code, 2, "Timeout - host nonresponsive" ); 59is( $res->return_code, 2, "Timeout - host nonresponsive" );
60like( $res->output, '/100%/', "Error contains '100%' string (for 100% packet loss)" ); 60like( $res->output, '/100%/', "Error contains '100%' string (for 100% packet loss)" );
@@ -66,13 +66,13 @@ is( $res->return_code, 3, "No hostname" );
66like( $res->output, '/No hosts to check/', "Output with appropriate error message"); 66like( $res->output, '/No hosts to check/', "Output with appropriate error message");
67 67
68$res = NPTest->testCmd( 68$res = NPTest->testCmd(
69 "$sudo ./check_icmp -H $host_nonresponsive -w 10000ms,100% -c 10000ms,100% -n 1 -m 0" 69 "$sudo ./check_icmp -H $host_nonresponsive -w 10000ms,100% -c 10000ms,100% -n 1 -m 0 -t 2"
70 ); 70 );
71is( $res->return_code, 0, "One host nonresponsive - zero required" ); 71is( $res->return_code, 0, "One host nonresponsive - zero required" );
72like( $res->output, $successOutput, "Output OK" ); 72like( $res->output, $successOutput, "Output OK" );
73 73
74$res = NPTest->testCmd( 74$res = NPTest->testCmd(
75 "$sudo ./check_icmp -H $host_responsive -H $host_nonresponsive -w 10000ms,100% -c 10000ms,100% -n 1 -m 1" 75 "$sudo ./check_icmp -H $host_responsive -H $host_nonresponsive -w 10000ms,100% -c 10000ms,100% -n 1 -m 1 -t 2"
76 ); 76 );
77is( $res->return_code, 0, "One of two host nonresponsive - one required" ); 77is( $res->return_code, 0, "One of two host nonresponsive - one required" );
78like( $res->output, $successOutput, "Output OK" ); 78like( $res->output, $successOutput, "Output OK" );
@@ -94,3 +94,49 @@ $res = NPTest->testCmd(
94 ); 94 );
95is( $res->return_code, 0, "Try max packet size" ); 95is( $res->return_code, 0, "Try max packet size" );
96like( $res->output, $successOutput, "Output OK - Didn't overflow" ); 96like( $res->output, $successOutput, "Output OK - Didn't overflow" );
97
98$res = NPTest->testCmd(
99 "$sudo ./check_icmp -H $host_responsive -R 100,100 -n 1 -t 2"
100 );
101is( $res->return_code, 0, "rta works" );
102like( $res->output, $successOutput, "Output OK" );
103$res = NPTest->testCmd(
104 "$sudo ./check_icmp -H $host_responsive -P 80,90 -n 1 -t 2"
105 );
106is( $res->return_code, 0, "pl works" );
107like( $res->output, '/lost 0%/', "Output OK" );
108
109$res = NPTest->testCmd(
110 "$sudo ./check_icmp -H $host_responsive -J 80,90 -t 2"
111 );
112is( $res->return_code, 0, "jitter works" );
113like( $res->output, '/jitter \d/', "Output OK" );
114
115$res = NPTest->testCmd(
116 "$sudo ./check_icmp -H $host_responsive -M 4,3 -t 2"
117 );
118is( $res->return_code, 0, "mos works" );
119like( $res->output, '/MOS \d/', "Output OK" );
120
121$res = NPTest->testCmd(
122 "$sudo ./check_icmp -H $host_responsive -S 80,70 -t 2"
123 );
124is( $res->return_code, 0, "score works" );
125like( $res->output, '/Score \d/', "Output OK" );
126
127$res = NPTest->testCmd(
128 "$sudo ./check_icmp -H $host_responsive -O -t 2"
129 );
130is( $res->return_code, 0, "order works" );
131like( $res->output, '/Packets in order/', "Output OK" );
132
133$res = NPTest->testCmd(
134 "$sudo ./check_icmp -H $host_responsive -O -S 80,70 -M 4,3 -J 80,90 -P 80,90 -R 100,100 -t 2"
135 );
136is( $res->return_code, 0, "order works" );
137like( $res->output, '/Packets in order/', "Output OK" );
138like( $res->output, '/Score \d/', "Output OK" );
139like( $res->output, '/MOS \d/', "Output OK" );
140like( $res->output, '/jitter \d/', "Output OK" );
141like( $res->output, '/lost 0%/', "Output OK" );
142like( $res->output, $successOutput, "Output OK" );
diff --git a/po/de.po b/po/de.po
index c25a2b4..6d79f9d 100644
--- a/po/de.po
+++ b/po/de.po
@@ -5070,6 +5070,25 @@ msgstr "Warning threshold Integer sein"
5070msgid "critical threshold (currently " 5070msgid "critical threshold (currently "
5071msgstr "Critical threshold muss ein Integer sein" 5071msgstr "Critical threshold muss ein Integer sein"
5072 5072
5073msgid ""
5074"RTA, round trip average, mode warning,critical, ex. 100ms,200ms unit in ms"
5075msgstr ""
5076
5077msgid "packet loss mode, ex. 40%,50% , unit in %"
5078msgstr ""
5079
5080msgid "jitter mode warning,critical, ex. 40.000ms,50.000ms , unit in ms "
5081msgstr ""
5082
5083msgid "MOS mode, between 0 and 4.4 warning,critical, ex. 3.5,3.0"
5084msgstr ""
5085
5086msgid "score mode, max value 100 warning,critical, ex. 80,70 "
5087msgstr ""
5088
5089msgid "detect out of order ICMP packts "
5090msgstr ""
5091
5073#, fuzzy 5092#, fuzzy
5074msgid "specify a source IP address or device name" 5093msgid "specify a source IP address or device name"
5075msgstr "Hostname oder Serveradresse muss angegeben werden" 5094msgstr "Hostname oder Serveradresse muss angegeben werden"
@@ -5101,6 +5120,9 @@ msgstr ""
5101msgid "verbose" 5120msgid "verbose"
5102msgstr "" 5121msgstr ""
5103 5122
5123msgid "If none of R,P,J,M,S or O is specified, default behavior is -R -P"
5124msgstr ""
5125
5104msgid "The -H switch is optional. Naming a host (or several) to check is not." 5126msgid "The -H switch is optional. Naming a host (or several) to check is not."
5105msgstr "" 5127msgstr ""
5106 5128
diff --git a/po/fr.po b/po/fr.po
index 321a230..c59042d 100644
--- a/po/fr.po
+++ b/po/fr.po
@@ -5290,6 +5290,25 @@ msgstr "Valeurs pour le seuil d'avertissement (actuellement "
5290msgid "critical threshold (currently " 5290msgid "critical threshold (currently "
5291msgstr "Valeurs pour le seuil critique (actuellement " 5291msgstr "Valeurs pour le seuil critique (actuellement "
5292 5292
5293msgid ""
5294"RTA, round trip average, mode warning,critical, ex. 100ms,200ms unit in ms"
5295msgstr ""
5296
5297msgid "packet loss mode, ex. 40%,50% , unit in %"
5298msgstr ""
5299
5300msgid "jitter mode warning,critical, ex. 40.000ms,50.000ms , unit in ms "
5301msgstr ""
5302
5303msgid "MOS mode, between 0 and 4.4 warning,critical, ex. 3.5,3.0"
5304msgstr ""
5305
5306msgid "score mode, max value 100 warning,critical, ex. 80,70 "
5307msgstr ""
5308
5309msgid "detect out of order ICMP packts "
5310msgstr ""
5311
5293msgid "specify a source IP address or device name" 5312msgid "specify a source IP address or device name"
5294msgstr "spécifiez une adresse ou un nom d'hôte" 5313msgstr "spécifiez une adresse ou un nom d'hôte"
5295 5314
@@ -5320,6 +5339,9 @@ msgstr ""
5320msgid "verbose" 5339msgid "verbose"
5321msgstr "" 5340msgstr ""
5322 5341
5342msgid "If none of R,P,J,M,S or O is specified, default behavior is -R -P"
5343msgstr ""
5344
5323msgid "The -H switch is optional. Naming a host (or several) to check is not." 5345msgid "The -H switch is optional. Naming a host (or several) to check is not."
5324msgstr "" 5346msgstr ""
5325 5347
diff --git a/po/monitoring-plugins.pot b/po/monitoring-plugins.pot
index 54d79fe..90424b7 100644
--- a/po/monitoring-plugins.pot
+++ b/po/monitoring-plugins.pot
@@ -4895,6 +4895,25 @@ msgstr ""
4895msgid "critical threshold (currently " 4895msgid "critical threshold (currently "
4896msgstr "" 4896msgstr ""
4897 4897
4898msgid ""
4899"RTA, round trip average, mode warning,critical, ex. 100ms,200ms unit in ms"
4900msgstr ""
4901
4902msgid "packet loss mode, ex. 40%,50% , unit in %"
4903msgstr ""
4904
4905msgid "jitter mode warning,critical, ex. 40.000ms,50.000ms , unit in ms "
4906msgstr ""
4907
4908msgid "MOS mode, between 0 and 4.4 warning,critical, ex. 3.5,3.0"
4909msgstr ""
4910
4911msgid "score mode, max value 100 warning,critical, ex. 80,70 "
4912msgstr ""
4913
4914msgid "detect out of order ICMP packts "
4915msgstr ""
4916
4898msgid "specify a source IP address or device name" 4917msgid "specify a source IP address or device name"
4899msgstr "" 4918msgstr ""
4900 4919
@@ -4925,6 +4944,9 @@ msgstr ""
4925msgid "verbose" 4944msgid "verbose"
4926msgstr "" 4945msgstr ""
4927 4946
4947msgid "If none of R,P,J,M,S or O is specified, default behavior is -R -P"
4948msgstr ""
4949
4928msgid "The -H switch is optional. Naming a host (or several) to check is not." 4950msgid "The -H switch is optional. Naming a host (or several) to check is not."
4929msgstr "" 4951msgstr ""
4930 4952