diff options
Diffstat (limited to 'plugins-root/check_icmp.c')
-rw-r--r-- | plugins-root/check_icmp.c | 429 |
1 files changed, 383 insertions, 46 deletions
diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c index 4098874c..d68c4e0d 100644 --- a/plugins-root/check_icmp.c +++ b/plugins-root/check_icmp.c | |||
@@ -42,6 +42,10 @@ char *progname; | |||
42 | const char *copyright = "2005-2008"; | 42 | const char *copyright = "2005-2008"; |
43 | const char *email = "devel@monitoring-plugins.org"; | 43 | const 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 */ |
132 | typedef struct threshold { | 150 | typedef 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); | |||
187 | static int recvfrom_wto(int, void *, unsigned int, struct sockaddr *, u_int *, struct timeval*); | 208 | static int recvfrom_wto(int, void *, unsigned int, struct sockaddr *, u_int *, struct timeval*); |
188 | static int send_icmp_ping(int, struct rta_host *); | 209 | static int send_icmp_ping(int, struct rta_host *); |
189 | static int get_threshold(char *str, threshold *th); | 210 | static int get_threshold(char *str, threshold *th); |
211 | static int get_threshold2(char *str, threshold *, threshold *, int type); | ||
190 | static void run_checks(void); | 212 | static void run_checks(void); |
191 | static void set_source_ip(char *); | 213 | static void set_source_ip(char *); |
192 | static int add_target(char *); | 214 | static int add_target(char *); |
@@ -223,6 +245,12 @@ static unsigned int warn_down = 1, crit_down = 1; /* host down threshold values | |||
223 | static int min_hosts_alive = -1; | 245 | static int min_hosts_alive = -1; |
224 | float pkt_backoff_factor = 1.5; | 246 | float pkt_backoff_factor = 1.5; |
225 | float target_backoff_factor = 1.5; | 247 | float target_backoff_factor = 1.5; |
248 | int rta_mode=0; | ||
249 | int pl_mode=0; | ||
250 | int jitter_mode=0; | ||
251 | int score_mode=0; | ||
252 | int mos_mode=0; | ||
253 | int order_mode=0; | ||
226 | 254 | ||
227 | /** code start **/ | 255 | /** code start **/ |
228 | static void | 256 | static 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) */ | ||
1595 | static int | ||
1596 | get_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 | |||
1311 | unsigned short | 1634 | unsigned short |
1312 | icmp_checksum(unsigned short *p, int n) | 1635 | icmp_checksum(unsigned short *p, int n) |
1313 | { | 1636 | { |
@@ -1332,10 +1655,9 @@ icmp_checksum(unsigned short *p, int n) | |||
1332 | void | 1655 | void |
1333 | print_help(void) | 1656 | print_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%")); |