summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorroot <dirty.ren@gmail.com>2017-08-18 19:13:30 (GMT)
committerroot <dirty.ren@gmail.com>2017-08-18 19:13:30 (GMT)
commitab7d056ee36c064ae0a75fb0029cb8cf20df5b66 (patch)
tree7c581f05d95cfb30533942e535a40fabeedda10f
parentb3d39e605ef7ce7da056721c4e2e140966be3530 (diff)
downloadmonitoring-plugins-ab7d056ee36c064ae0a75fb0029cb8cf20df5b66.tar.gz
Add support to Jitter, MOS and Score
-rw-r--r--lib/utils_base.c13
-rw-r--r--plugins-root/check_icmp.c429
2 files changed, 396 insertions, 46 deletions
diff --git a/lib/utils_base.c b/lib/utils_base.c
index 3822bcf..8a03d09 100644
--- a/lib/utils_base.c
+++ b/lib/utils_base.c
@@ -300,6 +300,19 @@ char *np_escaped_string (const char *string) {
300 300
301int np_check_if_root(void) { return (geteuid() == 0); } 301int np_check_if_root(void) { return (geteuid() == 0); }
302 302
303int np_warn_if_not_root(void) {
304 int status = np_check_if_root();
305 if(!status) {
306 printf(_("Warning: "));
307 printf(_("This plugin must be either run as root or setuid root.\n"));
308 printf(_("To run as root, you can use a tool like sudo.\n"));
309 printf(_("To set the setuid permissions, use the command:\n"));
310 /* XXX could we use something like progname? */
311 printf("\tchmod u+s yourpluginfile\n");
312 }
313 return status;
314}
315
303/* 316/*
304 * Extract the value from key/value pairs, or return NULL. The value returned 317 * Extract the value from key/value pairs, or return NULL. The value returned
305 * can be free()ed. 318 * can be free()ed.
diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c
index 4098874..d68c4e0 100644
--- a/plugins-root/check_icmp.c
+++ b/plugins-root/check_icmp.c
@@ -42,6 +42,10 @@ char *progname;
42const char *copyright = "2005-2008"; 42const char *copyright = "2005-2008";
43const char *email = "devel@monitoring-plugins.org"; 43const char *email = "devel@monitoring-plugins.org";
44 44
45#ifdef __sun
46#define _XPG4_2
47#endif
48
45/** Monitoring Plugins basic includes */ 49/** Monitoring Plugins basic includes */
46#include "common.h" 50#include "common.h"
47#include "netutils.h" 51#include "netutils.h"
@@ -120,18 +124,35 @@ typedef struct rta_host {
120 unsigned char icmp_type, icmp_code; /* type and code from errors */ 124 unsigned char icmp_type, icmp_code; /* type and code from errors */
121 unsigned short flags; /* control/status flags */ 125 unsigned short flags; /* control/status flags */
122 double rta; /* measured RTA */ 126 double rta; /* measured RTA */
127 int rta_status;
123 double rtmax; /* max rtt */ 128 double rtmax; /* max rtt */
124 double rtmin; /* min rtt */ 129 double rtmin; /* min rtt */
130 double jitter; /* measured jitter */
131 int jitter_status;
132 double jitter_max; /* jitter rtt */
133 double jitter_min; /* jitter rtt */
134 double EffectiveLatency;
135 double mos; /* Mean opnion score */
136 int mos_status;
137 double score; /* score */
138 int score_status;
139 u_int last_tdiff;
140 u_int last_icmp_seq; /* Last ICMP_SEQ to check out of order pkts */
125 unsigned char pl; /* measured packet loss */ 141 unsigned char pl; /* measured packet loss */
142 int pl_status;
126 struct rta_host *next; /* linked list */ 143 struct rta_host *next; /* linked list */
144 int order_status;
127} rta_host; 145} rta_host;
128 146
129#define FLAG_LOST_CAUSE 0x01 /* decidedly dead target. */ 147#define FLAG_LOST_CAUSE 0x01 /* decidedly dead target. */
130 148
131/* threshold structure. all values are maximum allowed, exclusive */ 149/* threshold structure. all values are maximum allowed, exclusive */
132typedef struct threshold { 150typedef struct threshold {
133 unsigned char pl; /* max allowed packet loss in percent */ 151 unsigned char pl; /* max allowed packet loss in percent */
134 unsigned int rta; /* roundtrip time average, microseconds */ 152 unsigned int rta; /* roundtrip time average, microseconds */
153 double jitter; /* jitter time average, microseconds */
154 double mos; /* MOS */
155 double score; /* Score */
135} threshold; 156} threshold;
136 157
137/* the data structure */ 158/* the data structure */
@@ -187,6 +208,7 @@ static int wait_for_reply(int, u_int);
187static int recvfrom_wto(int, void *, unsigned int, struct sockaddr *, u_int *, struct timeval*); 208static int recvfrom_wto(int, void *, unsigned int, struct sockaddr *, u_int *, struct timeval*);
188static int send_icmp_ping(int, struct rta_host *); 209static int send_icmp_ping(int, struct rta_host *);
189static int get_threshold(char *str, threshold *th); 210static int get_threshold(char *str, threshold *th);
211static int get_threshold2(char *str, threshold *, threshold *, int type);
190static void run_checks(void); 212static void run_checks(void);
191static void set_source_ip(char *); 213static void set_source_ip(char *);
192static int add_target(char *); 214static int add_target(char *);
@@ -223,6 +245,12 @@ static unsigned int warn_down = 1, crit_down = 1; /* host down threshold values
223static int min_hosts_alive = -1; 245static int min_hosts_alive = -1;
224float pkt_backoff_factor = 1.5; 246float pkt_backoff_factor = 1.5;
225float target_backoff_factor = 1.5; 247float target_backoff_factor = 1.5;
248int rta_mode=0;
249int pl_mode=0;
250int jitter_mode=0;
251int score_mode=0;
252int mos_mode=0;
253int order_mode=0;
226 254
227/** code start **/ 255/** code start **/
228static void 256static void
@@ -378,6 +406,9 @@ main(int argc, char **argv)
378 int icmp_sockerrno, udp_sockerrno, tcp_sockerrno; 406 int icmp_sockerrno, udp_sockerrno, tcp_sockerrno;
379 int result; 407 int result;
380 struct rta_host *host; 408 struct rta_host *host;
409#ifdef HAVE_SIGACTION
410 struct sigaction sig_action;
411#endif
381#ifdef SO_TIMESTAMP 412#ifdef SO_TIMESTAMP
382 int on = 1; 413 int on = 1;
383#endif 414#endif
@@ -386,6 +417,9 @@ main(int argc, char **argv)
386 bindtextdomain (PACKAGE, LOCALEDIR); 417 bindtextdomain (PACKAGE, LOCALEDIR);
387 textdomain (PACKAGE); 418 textdomain (PACKAGE);
388 419
420 /* print a helpful error message if geteuid != 0 */
421 np_warn_if_not_root();
422
389 /* we only need to be setsuid when we get the sockets, so do 423 /* we only need to be setsuid when we get the sockets, so do
390 * that before pointer magic (esp. on network data) */ 424 * that before pointer magic (esp. on network data) */
391 icmp_sockerrno = udp_sockerrno = tcp_sockerrno = sockets = 0; 425 icmp_sockerrno = udp_sockerrno = tcp_sockerrno = sockets = 0;
@@ -430,10 +464,19 @@ main(int argc, char **argv)
430 table = NULL; 464 table = NULL;
431 465
432 mode = MODE_RTA; 466 mode = MODE_RTA;
467 /* Default critical thresholds */
433 crit.rta = 500000; 468 crit.rta = 500000;
434 crit.pl = 80; 469 crit.pl = 80;
470 crit.jitter = 50;
471 crit.mos= 3;
472 crit.score=70;
473 /* Default warning thresholds */
435 warn.rta = 200000; 474 warn.rta = 200000;
436 warn.pl = 40; 475 warn.pl = 40;
476 warn.jitter = 40;
477 warn.mos= 3.5;
478 warn.score=80;
479
437 protocols = HAVE_ICMP | HAVE_UDP | HAVE_TCP; 480 protocols = HAVE_ICMP | HAVE_UDP | HAVE_TCP;
438 pkt_interval = 80000; /* 80 msec packet interval by default */ 481 pkt_interval = 80000; /* 80 msec packet interval by default */
439 packets = 5; 482 packets = 5;
@@ -469,14 +512,14 @@ main(int argc, char **argv)
469 512
470 /* parse the arguments */ 513 /* parse the arguments */
471 for(i = 1; i < argc; i++) { 514 for(i = 1; i < argc; i++) {
472 while((arg = getopt(argc, argv, "vhVw:c:n:p:t:H:s:i:b:I:l:m:")) != EOF) { 515 while((arg = getopt(argc, argv, "vhVw:c:n:p:t:H:s:i:b:I:l:m:P:R:J:S:M:O")) != EOF) {
473 unsigned short size; 516 long size;
474 switch(arg) { 517 switch(arg) {
475 case 'v': 518 case 'v':
476 debug++; 519 debug++;
477 break; 520 break;
478 case 'b': 521 case 'b':
479 size = (unsigned short)strtol(optarg,NULL,0); 522 size = strtol(optarg,NULL,0);
480 if (size >= (sizeof(struct icmp) + sizeof(struct icmp_ping_data)) && 523 if (size >= (sizeof(struct icmp) + sizeof(struct icmp_ping_data)) &&
481 size < MAX_PING_DATA) { 524 size < MAX_PING_DATA) {
482 icmp_data_size = size; 525 icmp_data_size = size;
@@ -526,11 +569,34 @@ main(int argc, char **argv)
526 break; 569 break;
527 case 'V': /* version */ 570 case 'V': /* version */
528 print_revision (progname, NP_VERSION); 571 print_revision (progname, NP_VERSION);
529 exit (STATE_UNKNOWN); 572 exit (STATE_OK);
530 case 'h': /* help */ 573 case 'h': /* help */
531 print_help (); 574 print_help ();
532 exit (STATE_UNKNOWN); 575 exit (STATE_OK);
533 } 576 case 'R': /* RTA mode */
577 get_threshold2(optarg, &warn, &crit,1);
578 rta_mode=1;
579 break;
580 case 'P': /* packet loss mode */
581 get_threshold2(optarg, &warn, &crit,2);
582 pl_mode=1;
583 break;
584 case 'J': /* packet loss mode */
585 get_threshold2(optarg, &warn, &crit,3);
586 jitter_mode=1;
587 break;
588 case 'M': /* MOS mode */
589 get_threshold2(optarg, &warn, &crit,4);
590 mos_mode=1;
591 break;
592 case 'S': /* score mode */
593 get_threshold2(optarg, &warn, &crit,5);
594 score_mode=1;
595 break;
596 case 'O': /* out of order mode */
597 order_mode=1;
598 break;
599 }
534 } 600 }
535 } 601 }
536 602
@@ -579,11 +645,25 @@ main(int argc, char **argv)
579 if(warn.pl > crit.pl) warn.pl = crit.pl; 645 if(warn.pl > crit.pl) warn.pl = crit.pl;
580 if(warn.rta > crit.rta) warn.rta = crit.rta; 646 if(warn.rta > crit.rta) warn.rta = crit.rta;
581 if(warn_down > crit_down) crit_down = warn_down; 647 if(warn_down > crit_down) crit_down = warn_down;
582 648 if(warn.jitter > crit.jitter) crit.jitter = warn.jitter;
649 if(warn.mos < crit.mos) warn.mos = crit.mos;
650 if(warn.score < crit.score) warn.score = crit.score;
651
652#ifdef HAVE_SIGACTION
653 sig_action.sa_sigaction = NULL;
654 sig_action.sa_handler = finish;
655 sigfillset(&sig_action.sa_mask);
656 sig_action.sa_flags = SA_NODEFER|SA_RESTART;
657 sigaction(SIGINT, &sig_action, NULL);
658 sigaction(SIGHUP, &sig_action, NULL);
659 sigaction(SIGTERM, &sig_action, NULL);
660 sigaction(SIGALRM, &sig_action, NULL);
661#else /* HAVE_SIGACTION */
583 signal(SIGINT, finish); 662 signal(SIGINT, finish);
584 signal(SIGHUP, finish); 663 signal(SIGHUP, finish);
585 signal(SIGTERM, finish); 664 signal(SIGTERM, finish);
586 signal(SIGALRM, finish); 665 signal(SIGALRM, finish);
666#endif /* HAVE_SIGACTION */
587 if(debug) printf("Setting alarm timeout to %u seconds\n", timeout); 667 if(debug) printf("Setting alarm timeout to %u seconds\n", timeout);
588 alarm(timeout); 668 alarm(timeout);
589 669
@@ -608,7 +688,7 @@ main(int argc, char **argv)
608 if(max_completion_time > (u_int)timeout * 1000000) { 688 if(max_completion_time > (u_int)timeout * 1000000) {
609 printf("max_completion_time: %llu timeout: %u\n", 689 printf("max_completion_time: %llu timeout: %u\n",
610 max_completion_time, timeout); 690 max_completion_time, timeout);
611 printf("Timeout must be at least %llu\n", 691 printf("Timout must be at lest %llu\n",
612 max_completion_time / 1000000 + 1); 692 max_completion_time / 1000000 + 1);
613 } 693 }
614 } 694 }
@@ -633,7 +713,7 @@ main(int argc, char **argv)
633 } 713 }
634 714
635 host = list; 715 host = list;
636 table = malloc(sizeof(struct rta_host **) * targets); 716 table = malloc(sizeof(struct rta_host *) * targets);
637 i = 0; 717 i = 0;
638 while(host) { 718 while(host) {
639 host->id = i*packets; 719 host->id = i*packets;
@@ -671,9 +751,9 @@ run_checks()
671 751
672 /* we're still in the game, so send next packet */ 752 /* we're still in the game, so send next packet */
673 (void)send_icmp_ping(icmp_sock, table[t]); 753 (void)send_icmp_ping(icmp_sock, table[t]);
674 result = wait_for_reply(icmp_sock, target_interval); 754 (void)wait_for_reply(icmp_sock, target_interval);
675 } 755 }
676 result = wait_for_reply(icmp_sock, pkt_interval * targets); 756 (void)wait_for_reply(icmp_sock, pkt_interval * targets);
677 } 757 }
678 758
679 if(icmp_pkts_en_route && targets_alive) { 759 if(icmp_pkts_en_route && targets_alive) {
@@ -693,7 +773,7 @@ run_checks()
693 * haven't yet */ 773 * haven't yet */
694 if(debug) printf("Waiting for %u micro-seconds (%0.3f msecs)\n", 774 if(debug) printf("Waiting for %u micro-seconds (%0.3f msecs)\n",
695 final_wait, (float)final_wait / 1000); 775 final_wait, (float)final_wait / 1000);
696 result = wait_for_reply(icmp_sock, final_wait); 776 (void)wait_for_reply(icmp_sock, final_wait);
697 } 777 }
698} 778}
699 779
@@ -714,6 +794,7 @@ wait_for_reply(int sock, u_int t)
714 struct icmp_ping_data data; 794 struct icmp_ping_data data;
715 struct timeval wait_start, now; 795 struct timeval wait_start, now;
716 u_int tdiff, i, per_pkt_wait; 796 u_int tdiff, i, per_pkt_wait;
797 double jitter_tmp;
717 798
718 /* if we can't listen or don't have anything to listen to, just return */ 799 /* if we can't listen or don't have anything to listen to, just return */
719 if(!t || !icmp_pkts_en_route) return 0; 800 if(!t || !icmp_pkts_en_route) return 0;
@@ -792,12 +873,43 @@ wait_for_reply(int sock, u_int t)
792 host = table[ntohs(icp.icmp_seq)/packets]; 873 host = table[ntohs(icp.icmp_seq)/packets];
793 tdiff = get_timevaldiff(&data.stime, &now); 874 tdiff = get_timevaldiff(&data.stime, &now);
794 875
876 if (host->last_tdiff>0) {
877 /* Calculate jitter */
878 if (host->last_tdiff > tdiff) {
879 jitter_tmp = host->last_tdiff - tdiff;
880 }
881 else {
882 jitter_tmp = tdiff - host->last_tdiff;
883 }
884 if (host->jitter==0) {
885 host->jitter=jitter_tmp;
886 host->jitter_max=jitter_tmp;
887 host->jitter_min=jitter_tmp;
888 }
889 else {
890 host->jitter+=jitter_tmp;
891 if (jitter_tmp < host->jitter_min)
892 host->jitter_min=jitter_tmp;
893 if (jitter_tmp > host->jitter_max)
894 host->jitter_max=jitter_tmp;
895 }
896
897 /* Check if packets in order */
898 if (host->last_icmp_seq >= icp.icmp_seq)
899 host->order_status=STATE_CRITICAL;
900 }
901 host->last_tdiff=tdiff;
902
903 host->last_icmp_seq=icp.icmp_seq;
904
905 //printf("%d tdiff %d host->jitter %u host->last_tdiff %u\n", icp.icmp_seq, tdiff, host->jitter, host->last_tdiff);
906
795 host->time_waited += tdiff; 907 host->time_waited += tdiff;
796 host->icmp_recv++; 908 host->icmp_recv++;
797 icmp_recv++; 909 icmp_recv++;
798 if (tdiff > host->rtmax) 910 if (tdiff > (int)host->rtmax)
799 host->rtmax = tdiff; 911 host->rtmax = tdiff;
800 if (tdiff < host->rtmin) 912 if (tdiff < (int)host->rtmin)
801 host->rtmin = tdiff; 913 host->rtmin = tdiff;
802 914
803 if(debug) { 915 if(debug) {
@@ -945,8 +1057,10 @@ recvfrom_wto(int sock, void *buf, unsigned int len, struct sockaddr *saddr,
945 hdr.msg_namelen = slen; 1057 hdr.msg_namelen = slen;
946 hdr.msg_iov = &iov; 1058 hdr.msg_iov = &iov;
947 hdr.msg_iovlen = 1; 1059 hdr.msg_iovlen = 1;
1060#ifdef HAVE_MSGHDR_MSG_CONTROL
948 hdr.msg_control = ans_data; 1061 hdr.msg_control = ans_data;
949 hdr.msg_controllen = sizeof(ans_data); 1062 hdr.msg_controllen = sizeof(ans_data);
1063#endif
950 1064
951 ret = recvmsg(sock, &hdr, 0); 1065 ret = recvmsg(sock, &hdr, 0);
952#ifdef SO_TIMESTAMP 1066#ifdef SO_TIMESTAMP
@@ -975,6 +1089,8 @@ finish(int sig)
975 {"OK", "WARNING", "CRITICAL", "UNKNOWN", "DEPENDENT"}; 1089 {"OK", "WARNING", "CRITICAL", "UNKNOWN", "DEPENDENT"};
976 int hosts_ok = 0; 1090 int hosts_ok = 0;
977 int hosts_warn = 0; 1091 int hosts_warn = 0;
1092 double R;
1093 int shown=0;
978 1094
979 alarm(0); 1095 alarm(0);
980 if(debug > 1) printf("finish(%d) called\n", sig); 1096 if(debug > 1) printf("finish(%d) called\n", sig);
@@ -990,6 +1106,7 @@ finish(int sig)
990 } 1106 }
991 1107
992 /* iterate thrice to calculate values, give output, and print perfparse */ 1108 /* iterate thrice to calculate values, give output, and print perfparse */
1109 status=STATE_OK;
993 host = list; 1110 host = list;
994 while(host) { 1111 while(host) {
995 if(!host->icmp_recv) { 1112 if(!host->icmp_recv) {
@@ -1005,19 +1122,104 @@ finish(int sig)
1005 pl = ((host->icmp_sent - host->icmp_recv) * 100) / host->icmp_sent; 1122 pl = ((host->icmp_sent - host->icmp_recv) * 100) / host->icmp_sent;
1006 rta = (double)host->time_waited / host->icmp_recv; 1123 rta = (double)host->time_waited / host->icmp_recv;
1007 } 1124 }
1125 if (host->icmp_recv>1) {
1126 host->jitter=(host->jitter / (host->icmp_recv - 1)/1000);
1127 host->EffectiveLatency = (rta/1000) + host->jitter * 2 + 10;
1128 if (host->EffectiveLatency < 160)
1129 R = 93.2 - (host->EffectiveLatency / 40);
1130 else
1131 R = 93.2 - ((host->EffectiveLatency - 120) / 10);
1132 R = R - (pl * 2.5);
1133 if (R<0) R=0;
1134 host->score = R;
1135 host->mos= 1 + ((0.035) * R) + ((.000007) * R * (R-60) * (100-R));
1136 }
1137 else {
1138 host->jitter=0;
1139 host->jitter_min=0;
1140 host->jitter_max=0;
1141 host->mos=0;
1142 }
1008 host->pl = pl; 1143 host->pl = pl;
1009 host->rta = rta; 1144 host->rta = rta;
1010 if(pl >= crit.pl || rta >= crit.rta) { 1145
1011 status = STATE_CRITICAL; 1146 /* if no new mode selected, use old schema */
1147 if (!rta_mode && !pl_mode && !jitter_mode && !score_mode && !mos_mode && !order_mode) {
1148 rta_mode=1;
1149 pl_mode=1;
1012 } 1150 }
1013 else if(!status && (pl >= warn.pl || rta >= warn.rta)) { 1151
1014 status = STATE_WARNING; 1152 /* Check which mode is on and do the warn / Crit stuff */
1015 hosts_warn++; 1153 if (rta_mode) {
1154 if(rta >= crit.rta) {
1155 status = STATE_CRITICAL;
1156 host->rta_status=STATE_CRITICAL;
1157 }
1158 else if(status!=STATE_CRITICAL && (rta >= warn.rta)) {
1159 status = STATE_WARNING;
1160 hosts_warn++;
1161 host->rta_status=STATE_WARNING;
1162 }
1163 else {
1164 hosts_ok++;
1165 }
1016 } 1166 }
1017 else { 1167 if (pl_mode) {
1018 hosts_ok++; 1168 if(pl >= crit.pl) {
1169 status = STATE_CRITICAL;
1170 host->pl_status=STATE_CRITICAL;
1171 }
1172 else if(status!=STATE_CRITICAL && (pl >= warn.pl)) {
1173 status = STATE_WARNING;
1174 hosts_warn++;
1175 host->pl_status=STATE_WARNING;
1176 }
1177 else {
1178 hosts_ok++;
1179 }
1180 }
1181 if (jitter_mode) {
1182 if(host->jitter >= crit.jitter) {
1183 status = STATE_CRITICAL;
1184 host->jitter_status=STATE_CRITICAL;
1185 }
1186 else if(status!=STATE_CRITICAL && (host->jitter >= warn.jitter)) {
1187 status = STATE_WARNING;
1188 hosts_warn++;
1189 host->jitter_status=STATE_WARNING;
1190 }
1191 else {
1192 hosts_ok++;
1193 }
1194 }
1195 if (mos_mode) {
1196 if(host->mos <= crit.mos) {
1197 status = STATE_CRITICAL;
1198 host->mos_status=STATE_CRITICAL;
1199 }
1200 else if(status!=STATE_CRITICAL && (host->mos <= warn.mos)) {
1201 status = STATE_WARNING;
1202 hosts_warn++;
1203 host->mos_status=STATE_WARNING;
1204 }
1205 else {
1206 hosts_ok++;
1207 }
1208 }
1209 if (score_mode) {
1210 if(host->score <= crit.score) {
1211 status = STATE_CRITICAL;
1212 host->score_status=STATE_CRITICAL;
1213 }
1214 else if(status!=STATE_CRITICAL && (host->score <= warn.score)) {
1215 status = STATE_WARNING;
1216 score_mode++;
1217 host->score_status=STATE_WARNING;
1218 }
1219 else {
1220 hosts_ok++;
1221 }
1019 } 1222 }
1020
1021 host = host->next; 1223 host = host->next;
1022 } 1224 }
1023 /* this is inevitable */ 1225 /* this is inevitable */
@@ -1027,9 +1229,10 @@ finish(int sig)
1027 else if((hosts_ok + hosts_warn) >= min_hosts_alive) status = STATE_WARNING; 1229 else if((hosts_ok + hosts_warn) >= min_hosts_alive) status = STATE_WARNING;
1028 } 1230 }
1029 printf("%s - ", status_string[status]); 1231 printf("%s - ", status_string[status]);
1030 1232
1031 host = list; 1233 host = list;
1032 while(host) { 1234 while(host) {
1235
1033 if(debug) puts(""); 1236 if(debug) puts("");
1034 if(i) { 1237 if(i) {
1035 if(i < targets) printf(" :: "); 1238 if(i < targets) printf(" :: ");
@@ -1038,6 +1241,8 @@ finish(int sig)
1038 i++; 1241 i++;
1039 if(!host->icmp_recv) { 1242 if(!host->icmp_recv) {
1040 status = STATE_CRITICAL; 1243 status = STATE_CRITICAL;
1244 host->rtmin=0;
1245 host->jitter_min=0;
1041 if(host->flags & FLAG_LOST_CAUSE) { 1246 if(host->flags & FLAG_LOST_CAUSE) {
1042 printf("%s: %s @ %s. rta nan, lost %d%%", 1247 printf("%s: %s @ %s. rta nan, lost %d%%",
1043 host->name, 1248 host->name,
@@ -1050,26 +1255,92 @@ finish(int sig)
1050 } 1255 }
1051 } 1256 }
1052 else { /* !icmp_recv */ 1257 else { /* !icmp_recv */
1053 printf("%s: rta %0.3fms, lost %u%%", 1258 printf("%s: ", host->name);
1054 host->name, host->rta / 1000, host->pl); 1259 /* rta text output */
1260 if (rta_mode) {
1261 shown=1;
1262 if (status == STATE_OK)
1263 printf("%s rta %0.3fms",(shown==1)?",":"", host->rta / 1000);
1264 else if (status==STATE_WARNING && host->rta_status==status)
1265 printf("%s rta %0.3fms > %0.3fms",(shown==1)?",":"", (float)host->rta / 1000, (float)warn.rta/1000);
1266 else if (status==STATE_CRITICAL && host->rta_status==status)
1267 printf("%s rta %0.3fms > %0.3fms",(shown==1)?",":"", (float)host->rta / 1000, (float)crit.rta/1000);
1268 }
1269 /* pl text output */
1270 if (pl_mode) {
1271 shown=1;
1272 if (status == STATE_OK)
1273 printf("%s lost %u%%",(shown==1)?",":"", host->pl);
1274 else if (status==STATE_WARNING && host->pl_status==status)
1275 printf("%s lost %u%% > %u%%",(shown==1)?",":"", host->pl, warn.pl);
1276 else if (status==STATE_CRITICAL && host->pl_status==status)
1277 printf("%s lost %u%% > %u%%",(shown==1)?",":"", host->pl, crit.pl);
1278 }
1279 /* jitter text output */
1280 if (jitter_mode) {
1281 shown=1;
1282 if (status == STATE_OK)
1283 printf("%s jitter %0.3fms",(shown==1)?",":"", (float)host->jitter);
1284 else if (status==STATE_WARNING && host->jitter_status==status)
1285 printf("%s jitter %0.3fms > %0.3fms",(shown==1)?",":"", (float)host->jitter, warn.jitter);
1286 else if (status==STATE_CRITICAL && host->jitter_status==status)
1287 printf("%s jitter %0.3fms > %0.3fms",(shown==1)?",":"", (float)host->jitter, crit.jitter);
1288 }
1289 /* mos text output */
1290 if (mos_mode) {
1291 shown=1;
1292 if (status == STATE_OK)
1293 printf("%s MOS %0.1f",(shown==1)?",":"", (float)host->mos);
1294 else if (status==STATE_WARNING && host->mos_status==status)
1295 printf("%s MOS %0.1f < %0.1f",(shown==1)?",":"", (float)host->mos, (float)warn.mos);
1296 else if (status==STATE_CRITICAL && host->mos_status==status)
1297 printf("%s MOS %0.1f < %0.1f",(shown==1)?",":"", (float)host->mos, (float)crit.mos);
1298 }
1299 /* score text output */
1300 if (score_mode) {
1301 shown=1;
1302 if (status == STATE_OK)
1303 printf("%s Score %u",(shown==1)?",":"", (int)host->score);
1304 else if (status==STATE_WARNING && host->score_status==status )
1305 printf("%s Score %u < %u",(shown==1)?",":"", (int)host->score, (int)warn.score);
1306 else if (status==STATE_CRITICAL && host->score_status==status )
1307 printf("%s Score %u < %u",(shown==1)?",":"", (int)host->score, (int)crit.score);
1308 }
1309 /* order statis text output */
1310 if (order_mode) {
1311 shown=1;
1312 if (status == STATE_OK)
1313 printf("%s Packets in order",(shown==1)?",":"");
1314 else if (status==STATE_CRITICAL && host->order_status==status)
1315 printf("%s Packets out of order",(shown==1)?",":"");
1316 }
1055 } 1317 }
1056
1057 host = host->next; 1318 host = host->next;
1058 } 1319 }
1059 1320
1060 /* iterate once more for pretty perfparse output */ 1321 /* iterate once more for pretty perfparse output */
1061 printf("|"); 1322 if (!(!rta_mode && !pl_mode && !jitter_mode && !score_mode && !mos_mode && order_mode)) {
1323 printf("|");
1324 }
1062 i = 0; 1325 i = 0;
1063 host = list; 1326 host = list;
1064 while(host) { 1327 while(host) {
1065 if(debug) puts(""); 1328 if(debug) puts("");
1066 printf("%srta=%0.3fms;%0.3f;%0.3f;0; %spl=%u%%;%u;%u;; %srtmax=%0.3fms;;;; %srtmin=%0.3fms;;;; ", 1329 if (rta_mode && host->pl<100) {
1067 (targets > 1) ? host->name : "", 1330 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);
1068 host->rta / 1000, (float)warn.rta / 1000, (float)crit.rta / 1000, 1331 }
1069 (targets > 1) ? host->name : "", host->pl, warn.pl, crit.pl, 1332 if (pl_mode) {
1070 (targets > 1) ? host->name : "", (float)host->rtmax / 1000, 1333 printf("%spl=%u%%;%u;%u;0;100 ", (targets > 1) ? host->name : "", host->pl, warn.pl, crit.pl);
1071 (targets > 1) ? host->name : "", (host->rtmin < DBL_MAX) ? (float)host->rtmin / 1000 : (float)0); 1334 }
1072 1335 if (jitter_mode && host->pl<100) {
1336 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);
1337 }
1338 if (mos_mode && host->pl<100) {
1339 printf("%smos=%0.1f;%0.1f;%0.1f;0;5 ", (targets > 1) ? host->name : "", (float)host->mos, (float)warn.mos, (float)crit.mos);
1340 }
1341 if (score_mode && host->pl<100) {
1342 printf("%sscore=%u;%u;%u;0;100 ", (targets > 1) ? host->name : "", (int)host->score, (int)warn.score, (int)crit.score);
1343 }
1073 host = host->next; 1344 host = host->next;
1074 } 1345 }
1075 1346
@@ -1144,8 +1415,20 @@ add_target_ip(char *arg, struct in_addr *in)
1144 /* fill out the sockaddr_in struct */ 1415 /* fill out the sockaddr_in struct */
1145 host->saddr_in.sin_family = AF_INET; 1416 host->saddr_in.sin_family = AF_INET;
1146 host->saddr_in.sin_addr.s_addr = in->s_addr; 1417 host->saddr_in.sin_addr.s_addr = in->s_addr;
1147
1148 host->rtmin = DBL_MAX; 1418 host->rtmin = DBL_MAX;
1419 host->rtmax = 0;
1420 host->jitter=0;
1421 host->jitter_max=0;
1422 host->jitter_min=DBL_MAX;
1423 host->last_tdiff=0;
1424 host->order_status=STATE_OK;
1425 host->last_icmp_seq=0;
1426 host->rta_status=0;
1427 host->pl_status=0;
1428 host->jitter_status=0;
1429 host->mos_status=0;
1430 host->score_status=0;
1431 host->pl_status=0;
1149 1432
1150 if(!list) list = cursor = host; 1433 if(!list) list = cursor = host;
1151 else cursor->next = host; 1434 else cursor->next = host;
@@ -1250,7 +1533,7 @@ get_timevar(const char *str)
1250 1533
1251 /* unit might be given as ms|m (millisec), 1534 /* unit might be given as ms|m (millisec),
1252 * us|u (microsec) or just plain s, for seconds */ 1535 * us|u (microsec) or just plain s, for seconds */
1253 u = p = '\0'; 1536 p = '\0';
1254 u = str[len - 1]; 1537 u = str[len - 1];
1255 if(len >= 2 && !isdigit((int)str[len - 2])) p = str[len - 2]; 1538 if(len >= 2 && !isdigit((int)str[len - 2])) p = str[len - 2];
1256 if(p && u == 's') u = p; 1539 if(p && u == 's') u = p;
@@ -1262,7 +1545,7 @@ get_timevar(const char *str)
1262 else if(u == 's') factor = 1000000; /* seconds */ 1545 else if(u == 's') factor = 1000000; /* seconds */
1263 if(debug > 2) printf("factor is %u\n", factor); 1546 if(debug > 2) printf("factor is %u\n", factor);
1264 1547
1265 i = strtoul(str, &ptr, 0); 1548 i = strtoul(str, &ptr, 0);
1266 if(!ptr || *ptr != '.' || strlen(ptr) < 2 || factor == 1) 1549 if(!ptr || *ptr != '.' || strlen(ptr) < 2 || factor == 1)
1267 return i * factor; 1550 return i * factor;
1268 1551
@@ -1308,6 +1591,46 @@ get_threshold(char *str, threshold *th)
1308 return 0; 1591 return 0;
1309} 1592}
1310 1593
1594/* not too good at checking errors, but it'll do (main() should barfe on -1) */
1595static int
1596get_threshold2(char *str, threshold *warn, threshold *crit, int type)
1597{
1598 char *p = NULL, i = 0;
1599
1600 if(!str || !strlen(str) || !warn || !crit) return -1;
1601 /* pointer magic slims code by 10 lines. i is bof-stop on stupid libc's */
1602 p = &str[strlen(str) - 1];
1603 while(p != &str[0]) {
1604 if( (*p == 'm') || (*p == '%') ) *p = '\0';
1605 else if(*p == ',' && i) {
1606 *p = '\0'; /* reset it so get_timevar(str) works nicely later */
1607 if (type==1)
1608 crit->rta = atof(p+1)*1000;
1609 else if (type==2)
1610 crit->pl = (unsigned char)strtoul(p+1, NULL, 0);
1611 else if (type==3)
1612 crit->jitter = atof(p+1);
1613 else if (type==4)
1614 crit->mos = atof(p+1);
1615 else if (type==5)
1616 crit->score = atof(p+1);
1617 }
1618 i = 1;
1619 p--;
1620 }
1621 if (type==1)
1622 warn->rta = atof(p)*1000;
1623 else if (type==2)
1624 warn->pl = (unsigned char)strtoul(p, NULL, 0);
1625 if (type==3)
1626 warn->jitter = atof(p);
1627 else if (type==4)
1628 warn->mos = atof(p);
1629 else if (type==5)
1630 warn->score = atof(p);
1631 return 0;
1632}
1633
1311unsigned short 1634unsigned short
1312icmp_checksum(unsigned short *p, int n) 1635icmp_checksum(unsigned short *p, int n)
1313{ 1636{
@@ -1332,10 +1655,9 @@ icmp_checksum(unsigned short *p, int n)
1332void 1655void
1333print_help(void) 1656print_help(void)
1334{ 1657{
1335
1336 /*print_revision (progname);*/ /* FIXME: Why? */ 1658 /*print_revision (progname);*/ /* FIXME: Why? */
1337
1338 printf ("Copyright (c) 2005 Andreas Ericsson <ae@op5.se>\n"); 1659 printf ("Copyright (c) 2005 Andreas Ericsson <ae@op5.se>\n");
1660
1339 printf (COPYRIGHT, copyright, email); 1661 printf (COPYRIGHT, copyright, email);
1340 1662
1341 printf ("\n\n"); 1663 printf ("\n\n");
@@ -1344,20 +1666,35 @@ print_help(void)
1344 1666
1345 printf (UT_HELP_VRSN); 1667 printf (UT_HELP_VRSN);
1346 printf (UT_EXTRA_OPTS); 1668 printf (UT_EXTRA_OPTS);
1347 1669 printf (" %s\n", "-w");
1348 printf (" %s\n", "-H");
1349 printf (" %s\n", _("specify a target"));
1350 printf (" %s\n", "-w");
1351 printf (" %s", _("warning threshold (currently ")); 1670 printf (" %s", _("warning threshold (currently "));
1352 printf ("%0.3fms,%u%%)\n", (float)warn.rta / 1000, warn.pl); 1671 printf ("%0.3fms,%u%%)\n", (float)warn.rta / 1000, warn.pl);
1353 printf (" %s\n", "-c"); 1672 printf (" %s\n", "-c");
1354 printf (" %s", _("critical threshold (currently ")); 1673 printf (" %s", _("critical threshold (currently "));
1355 printf ("%0.3fms,%u%%)\n", (float)crit.rta / 1000, crit.pl); 1674 printf ("%0.3fms,%u%%)\n", (float)crit.rta / 1000, crit.pl);
1675
1676 printf (" %s\n", "-R");
1677 printf (" %s\n", _("RTA, round trip average, mode warning,critical, ex. 100ms,200ms unit in ms"));
1678 printf (" %s\n", "-P");
1679 printf (" %s\n", _("packet loss mode, ex. 40%,50% , unit in %"));
1680 printf (" %s\n", "-J");
1681 printf (" %s\n", _("jitter mode warning,critical, ex. 40.000ms,50.000ms , unit in ms "));
1682 printf (" %s\n", "-M");
1683 printf (" %s\n", _("MOS mode, between 0 and 4.4 warning,critical, ex. 3.5,3.0"));
1684 printf (" %s\n", "-S");
1685 printf (" %s\n", _("score mode, max value 100 warning,critical, ex. 80,70 "));
1686 printf (" %s\n", "-O");
1687 printf (" %s\n", _("detect out of order ICMP packts "));
1688 printf (" %s\n", "-H");
1689 printf (" %s\n", _("specify a target"));
1356 printf (" %s\n", "-s"); 1690 printf (" %s\n", "-s");
1357 printf (" %s\n", _("specify a source IP address or device name")); 1691 printf (" %s\n", _("specify a source IP address or device name"));
1358 printf (" %s\n", "-n"); 1692 printf (" %s\n", "-n");
1359 printf (" %s", _("number of packets to send (currently ")); 1693 printf (" %s", _("number of packets to send (currently "));
1360 printf ("%u)\n",packets); 1694 printf ("%u)\n",packets);
1695 printf (" %s\n", "-p");
1696 printf (" %s", _("number of packets to send (currently "));
1697 printf ("%u)\n",packets);
1361 printf (" %s\n", "-i"); 1698 printf (" %s\n", "-i");
1362 printf (" %s", _("max packet interval (currently ")); 1699 printf (" %s", _("max packet interval (currently "));
1363 printf ("%0.3fms)\n",(float)pkt_interval / 1000); 1700 printf ("%0.3fms)\n",(float)pkt_interval / 1000);
@@ -1378,9 +1715,9 @@ print_help(void)
1378 printf (" %s %u + %d)\n", _("Packet size will be data bytes + icmp header (currently"),icmp_data_size, ICMP_MINLEN); 1715 printf (" %s %u + %d)\n", _("Packet size will be data bytes + icmp header (currently"),icmp_data_size, ICMP_MINLEN);
1379 printf (" %s\n", "-v"); 1716 printf (" %s\n", "-v");
1380 printf (" %s\n", _("verbose")); 1717 printf (" %s\n", _("verbose"));
1381
1382 printf ("\n"); 1718 printf ("\n");
1383 printf ("%s\n", _("Notes:")); 1719 printf ("%s\n", _("Notes:"));
1720 printf ("%s\n", _("If not mode R,P,J,M,S or O is informed, default icmp behavior, RTA and packet loss"));
1384 printf (" %s\n", _("The -H switch is optional. Naming a host (or several) to check is not.")); 1721 printf (" %s\n", _("The -H switch is optional. Naming a host (or several) to check is not."));
1385 printf ("\n"); 1722 printf ("\n");
1386 printf (" %s\n", _("Threshold format for -w and -c is 200.25,60% for 200.25 msec RTA and 60%")); 1723 printf (" %s\n", _("Threshold format for -w and -c is 200.25,60% for 200.25 msec RTA and 60%"));