diff options
-rw-r--r-- | plugins-root/check_icmp.c | 408 |
1 files changed, 377 insertions, 31 deletions
diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c index 1d47e9f..72ad1d7 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" |
@@ -109,18 +113,35 @@ typedef struct rta_host { | |||
109 | unsigned char icmp_type, icmp_code; /* type and code from errors */ | 113 | unsigned char icmp_type, icmp_code; /* type and code from errors */ |
110 | unsigned short flags; /* control/status flags */ | 114 | unsigned short flags; /* control/status flags */ |
111 | double rta; /* measured RTA */ | 115 | double rta; /* measured RTA */ |
116 | int rta_status; | ||
112 | double rtmax; /* max rtt */ | 117 | double rtmax; /* max rtt */ |
113 | double rtmin; /* min rtt */ | 118 | double rtmin; /* min rtt */ |
119 | double jitter; /* measured jitter */ | ||
120 | int jitter_status; | ||
121 | double jitter_max; /* jitter rtt */ | ||
122 | double jitter_min; /* jitter rtt */ | ||
123 | double EffectiveLatency; | ||
124 | double mos; /* Mean opnion score */ | ||
125 | int mos_status; | ||
126 | double score; /* score */ | ||
127 | int score_status; | ||
128 | u_int last_tdiff; | ||
129 | u_int last_icmp_seq; /* Last ICMP_SEQ to check out of order pkts */ | ||
114 | unsigned char pl; /* measured packet loss */ | 130 | unsigned char pl; /* measured packet loss */ |
131 | int pl_status; | ||
115 | struct rta_host *next; /* linked list */ | 132 | struct rta_host *next; /* linked list */ |
133 | int order_status; | ||
116 | } rta_host; | 134 | } rta_host; |
117 | 135 | ||
118 | #define FLAG_LOST_CAUSE 0x01 /* decidedly dead target. */ | 136 | #define FLAG_LOST_CAUSE 0x01 /* decidedly dead target. */ |
119 | 137 | ||
120 | /* threshold structure. all values are maximum allowed, exclusive */ | 138 | /* threshold structure. all values are maximum allowed, exclusive */ |
121 | typedef struct threshold { | 139 | typedef struct threshold { |
122 | unsigned char pl; /* max allowed packet loss in percent */ | 140 | unsigned char pl; /* max allowed packet loss in percent */ |
123 | unsigned int rta; /* roundtrip time average, microseconds */ | 141 | unsigned int rta; /* roundtrip time average, microseconds */ |
142 | double jitter; /* jitter time average, microseconds */ | ||
143 | double mos; /* MOS */ | ||
144 | double score; /* Score */ | ||
124 | } threshold; | 145 | } threshold; |
125 | 146 | ||
126 | /* the data structure */ | 147 | /* the data structure */ |
@@ -188,6 +209,7 @@ static int wait_for_reply(int, u_int); | |||
188 | static int recvfrom_wto(int, void *, unsigned int, struct sockaddr *, u_int *, struct timeval*); | 209 | static int recvfrom_wto(int, void *, unsigned int, struct sockaddr *, u_int *, struct timeval*); |
189 | static int send_icmp_ping(int, struct rta_host *); | 210 | static int send_icmp_ping(int, struct rta_host *); |
190 | static int get_threshold(char *str, threshold *th); | 211 | static int get_threshold(char *str, threshold *th); |
212 | static int get_threshold2(char *str, threshold *, threshold *, int type); | ||
191 | static void run_checks(void); | 213 | static void run_checks(void); |
192 | static void set_source_ip(char *); | 214 | static void set_source_ip(char *); |
193 | static int add_target(char *); | 215 | static int add_target(char *); |
@@ -224,6 +246,12 @@ static unsigned int warn_down = 1, crit_down = 1; /* host down threshold values | |||
224 | static int min_hosts_alive = -1; | 246 | static int min_hosts_alive = -1; |
225 | float pkt_backoff_factor = 1.5; | 247 | float pkt_backoff_factor = 1.5; |
226 | float target_backoff_factor = 1.5; | 248 | float target_backoff_factor = 1.5; |
249 | int rta_mode=0; | ||
250 | int pl_mode=0; | ||
251 | int jitter_mode=0; | ||
252 | int score_mode=0; | ||
253 | int mos_mode=0; | ||
254 | int order_mode=0; | ||
227 | 255 | ||
228 | /** code start **/ | 256 | /** code start **/ |
229 | static void | 257 | static void |
@@ -393,12 +421,14 @@ main(int argc, char **argv) | |||
393 | int icmp_sockerrno, udp_sockerrno, tcp_sockerrno; | 421 | int icmp_sockerrno, udp_sockerrno, tcp_sockerrno; |
394 | int result; | 422 | int result; |
395 | struct rta_host *host; | 423 | struct rta_host *host; |
424 | #ifdef HAVE_SIGACTION | ||
425 | struct sigaction sig_action; | ||
426 | #endif | ||
396 | #ifdef SO_TIMESTAMP | 427 | #ifdef SO_TIMESTAMP |
397 | int on = 1; | 428 | int on = 1; |
398 | #endif | 429 | #endif |
399 | char *source_ip = NULL; | 430 | char *source_ip = NULL; |
400 | char * opts_str = "vhVw:c:n:p:t:H:s:i:b:I:l:m:64"; | 431 | 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, ""); | 432 | setlocale (LC_ALL, ""); |
403 | bindtextdomain (PACKAGE, LOCALEDIR); | 433 | bindtextdomain (PACKAGE, LOCALEDIR); |
404 | textdomain (PACKAGE); | 434 | textdomain (PACKAGE); |
@@ -422,10 +452,19 @@ main(int argc, char **argv) | |||
422 | table = NULL; | 452 | table = NULL; |
423 | 453 | ||
424 | mode = MODE_RTA; | 454 | mode = MODE_RTA; |
455 | /* Default critical thresholds */ | ||
425 | crit.rta = 500000; | 456 | crit.rta = 500000; |
426 | crit.pl = 80; | 457 | crit.pl = 80; |
458 | crit.jitter = 50; | ||
459 | crit.mos= 3; | ||
460 | crit.score=70; | ||
461 | /* Default warning thresholds */ | ||
427 | warn.rta = 200000; | 462 | warn.rta = 200000; |
428 | warn.pl = 40; | 463 | warn.pl = 40; |
464 | warn.jitter = 40; | ||
465 | warn.mos= 3.5; | ||
466 | warn.score=80; | ||
467 | |||
429 | protocols = HAVE_ICMP | HAVE_UDP | HAVE_TCP; | 468 | protocols = HAVE_ICMP | HAVE_UDP | HAVE_TCP; |
430 | pkt_interval = 80000; /* 80 msec packet interval by default */ | 469 | pkt_interval = 80000; /* 80 msec packet interval by default */ |
431 | packets = 5; | 470 | packets = 5; |
@@ -481,16 +520,17 @@ main(int argc, char **argv) | |||
481 | /* Reset argument scanning */ | 520 | /* Reset argument scanning */ |
482 | optind = 1; | 521 | optind = 1; |
483 | 522 | ||
484 | unsigned short size; | 523 | unsigned long size; |
485 | /* parse the arguments */ | 524 | /* parse the arguments */ |
486 | for(i = 1; i < argc; i++) { | 525 | for(i = 1; i < argc; i++) { |
487 | while((arg = getopt(argc, argv, opts_str)) != EOF) { | 526 | while((arg = getopt(argc, argv, opts_str)) != EOF) { |
527 | while((arg = getopt(argc, argv, "vhVw:c:n:p:t:H:s:i:b:I:l:m:P:R:J:S:M:O")) != EOF) { | ||
488 | switch(arg) { | 528 | switch(arg) { |
489 | case 'v': | 529 | case 'v': |
490 | debug++; | 530 | debug++; |
491 | break; | 531 | break; |
492 | case 'b': | 532 | case 'b': |
493 | size = (unsigned short)strtol(optarg,NULL,0); | 533 | size = strtol(optarg,NULL,0); |
494 | if (size >= (sizeof(struct icmp) + sizeof(struct icmp_ping_data)) && | 534 | if (size >= (sizeof(struct icmp) + sizeof(struct icmp_ping_data)) && |
495 | size < MAX_PING_DATA) { | 535 | size < MAX_PING_DATA) { |
496 | icmp_data_size = size; | 536 | icmp_data_size = size; |
@@ -540,11 +580,34 @@ main(int argc, char **argv) | |||
540 | break; | 580 | break; |
541 | case 'V': /* version */ | 581 | case 'V': /* version */ |
542 | print_revision (progname, NP_VERSION); | 582 | print_revision (progname, NP_VERSION); |
543 | exit (STATE_UNKNOWN); | 583 | exit (STATE_OK); |
544 | case 'h': /* help */ | 584 | case 'h': /* help */ |
545 | print_help (); | 585 | print_help (); |
546 | exit (STATE_UNKNOWN); | 586 | exit (STATE_UNKNOWN); |
547 | break; | 587 | break; |
588 | case 'R': /* RTA mode */ | ||
589 | get_threshold2(optarg, &warn, &crit,1); | ||
590 | rta_mode=1; | ||
591 | break; | ||
592 | case 'P': /* packet loss mode */ | ||
593 | get_threshold2(optarg, &warn, &crit,2); | ||
594 | pl_mode=1; | ||
595 | break; | ||
596 | case 'J': /* packet loss mode */ | ||
597 | get_threshold2(optarg, &warn, &crit,3); | ||
598 | jitter_mode=1; | ||
599 | break; | ||
600 | case 'M': /* MOS mode */ | ||
601 | get_threshold2(optarg, &warn, &crit,4); | ||
602 | mos_mode=1; | ||
603 | break; | ||
604 | case 'S': /* score mode */ | ||
605 | get_threshold2(optarg, &warn, &crit,5); | ||
606 | score_mode=1; | ||
607 | break; | ||
608 | case 'O': /* out of order mode */ | ||
609 | order_mode=1; | ||
610 | break; | ||
548 | } | 611 | } |
549 | } | 612 | } |
550 | } | 613 | } |
@@ -631,11 +694,25 @@ main(int argc, char **argv) | |||
631 | if(warn.pl > crit.pl) warn.pl = crit.pl; | 694 | if(warn.pl > crit.pl) warn.pl = crit.pl; |
632 | if(warn.rta > crit.rta) warn.rta = crit.rta; | 695 | if(warn.rta > crit.rta) warn.rta = crit.rta; |
633 | if(warn_down > crit_down) crit_down = warn_down; | 696 | if(warn_down > crit_down) crit_down = warn_down; |
634 | 697 | if(warn.jitter > crit.jitter) crit.jitter = warn.jitter; | |
698 | if(warn.mos < crit.mos) warn.mos = crit.mos; | ||
699 | if(warn.score < crit.score) warn.score = crit.score; | ||
700 | |||
701 | #ifdef HAVE_SIGACTION | ||
702 | sig_action.sa_sigaction = NULL; | ||
703 | sig_action.sa_handler = finish; | ||
704 | sigfillset(&sig_action.sa_mask); | ||
705 | sig_action.sa_flags = SA_NODEFER|SA_RESTART; | ||
706 | sigaction(SIGINT, &sig_action, NULL); | ||
707 | sigaction(SIGHUP, &sig_action, NULL); | ||
708 | sigaction(SIGTERM, &sig_action, NULL); | ||
709 | sigaction(SIGALRM, &sig_action, NULL); | ||
710 | #else /* HAVE_SIGACTION */ | ||
635 | signal(SIGINT, finish); | 711 | signal(SIGINT, finish); |
636 | signal(SIGHUP, finish); | 712 | signal(SIGHUP, finish); |
637 | signal(SIGTERM, finish); | 713 | signal(SIGTERM, finish); |
638 | signal(SIGALRM, finish); | 714 | signal(SIGALRM, finish); |
715 | #endif /* HAVE_SIGACTION */ | ||
639 | if(debug) printf("Setting alarm timeout to %u seconds\n", timeout); | 716 | if(debug) printf("Setting alarm timeout to %u seconds\n", timeout); |
640 | alarm(timeout); | 717 | alarm(timeout); |
641 | 718 | ||
@@ -660,7 +737,7 @@ main(int argc, char **argv) | |||
660 | if(max_completion_time > (u_int)timeout * 1000000) { | 737 | if(max_completion_time > (u_int)timeout * 1000000) { |
661 | printf("max_completion_time: %llu timeout: %u\n", | 738 | printf("max_completion_time: %llu timeout: %u\n", |
662 | max_completion_time, timeout); | 739 | max_completion_time, timeout); |
663 | printf("Timeout must be at least %llu\n", | 740 | printf("Timout must be at lest %llu\n", |
664 | max_completion_time / 1000000 + 1); | 741 | max_completion_time / 1000000 + 1); |
665 | } | 742 | } |
666 | } | 743 | } |
@@ -685,7 +762,11 @@ main(int argc, char **argv) | |||
685 | } | 762 | } |
686 | 763 | ||
687 | host = list; | 764 | host = list; |
765 | //<<<<<<< HEAD FIXME | ||
688 | table = (struct rta_host**)malloc(sizeof(struct rta_host **) * targets); | 766 | table = (struct rta_host**)malloc(sizeof(struct rta_host **) * targets); |
767 | //======= | ||
768 | // table = malloc(sizeof(struct rta_host *) * targets); | ||
769 | //>>>>>>> jitter-orig | ||
689 | i = 0; | 770 | i = 0; |
690 | while(host) { | 771 | while(host) { |
691 | host->id = i*packets; | 772 | host->id = i*packets; |
@@ -772,6 +853,7 @@ wait_for_reply(int sock, u_int t) | |||
772 | struct icmp_ping_data data; | 853 | struct icmp_ping_data data; |
773 | struct timeval wait_start, now; | 854 | struct timeval wait_start, now; |
774 | u_int tdiff, i, per_pkt_wait; | 855 | u_int tdiff, i, per_pkt_wait; |
856 | double jitter_tmp; | ||
775 | 857 | ||
776 | if (!(packet.buf = malloc(icmp_pkt_size))) { | 858 | if (!(packet.buf = malloc(icmp_pkt_size))) { |
777 | crash("send_icmp_ping(): failed to malloc %d bytes for send buffer", | 859 | crash("send_icmp_ping(): failed to malloc %d bytes for send buffer", |
@@ -890,12 +972,43 @@ wait_for_reply(int sock, u_int t) | |||
890 | 972 | ||
891 | tdiff = get_timevaldiff(&data.stime, &now); | 973 | tdiff = get_timevaldiff(&data.stime, &now); |
892 | 974 | ||
975 | if (host->last_tdiff>0) { | ||
976 | /* Calculate jitter */ | ||
977 | if (host->last_tdiff > tdiff) { | ||
978 | jitter_tmp = host->last_tdiff - tdiff; | ||
979 | } | ||
980 | else { | ||
981 | jitter_tmp = tdiff - host->last_tdiff; | ||
982 | } | ||
983 | if (host->jitter==0) { | ||
984 | host->jitter=jitter_tmp; | ||
985 | host->jitter_max=jitter_tmp; | ||
986 | host->jitter_min=jitter_tmp; | ||
987 | } | ||
988 | else { | ||
989 | host->jitter+=jitter_tmp; | ||
990 | if (jitter_tmp < host->jitter_min) | ||
991 | host->jitter_min=jitter_tmp; | ||
992 | if (jitter_tmp > host->jitter_max) | ||
993 | host->jitter_max=jitter_tmp; | ||
994 | } | ||
995 | |||
996 | /* Check if packets in order */ | ||
997 | if (host->last_icmp_seq >= icp.icmp_seq) | ||
998 | host->order_status=STATE_CRITICAL; | ||
999 | } | ||
1000 | host->last_tdiff=tdiff; | ||
1001 | |||
1002 | host->last_icmp_seq=icp.icmp_seq; | ||
1003 | |||
1004 | //printf("%d tdiff %d host->jitter %u host->last_tdiff %u\n", icp.icmp_seq, tdiff, host->jitter, host->last_tdiff); | ||
1005 | |||
893 | host->time_waited += tdiff; | 1006 | host->time_waited += tdiff; |
894 | host->icmp_recv++; | 1007 | host->icmp_recv++; |
895 | icmp_recv++; | 1008 | icmp_recv++; |
896 | if (tdiff > host->rtmax) | 1009 | if (tdiff > (int)host->rtmax) |
897 | host->rtmax = tdiff; | 1010 | host->rtmax = tdiff; |
898 | if (tdiff < host->rtmin) | 1011 | if (tdiff < (int)host->rtmin) |
899 | host->rtmin = tdiff; | 1012 | host->rtmin = tdiff; |
900 | 1013 | ||
901 | if(debug) { | 1014 | if(debug) { |
@@ -1094,8 +1207,10 @@ recvfrom_wto(int sock, void *buf, unsigned int len, struct sockaddr *saddr, | |||
1094 | hdr.msg_namelen = slen; | 1207 | hdr.msg_namelen = slen; |
1095 | hdr.msg_iov = &iov; | 1208 | hdr.msg_iov = &iov; |
1096 | hdr.msg_iovlen = 1; | 1209 | hdr.msg_iovlen = 1; |
1210 | #ifdef HAVE_MSGHDR_MSG_CONTROL | ||
1097 | hdr.msg_control = ans_data; | 1211 | hdr.msg_control = ans_data; |
1098 | hdr.msg_controllen = sizeof(ans_data); | 1212 | hdr.msg_controllen = sizeof(ans_data); |
1213 | #endif | ||
1099 | 1214 | ||
1100 | ret = recvmsg(sock, &hdr, 0); | 1215 | ret = recvmsg(sock, &hdr, 0); |
1101 | #ifdef SO_TIMESTAMP | 1216 | #ifdef SO_TIMESTAMP |
@@ -1125,6 +1240,7 @@ finish(int sig) | |||
1125 | {"OK", "WARNING", "CRITICAL", "UNKNOWN", "DEPENDENT"}; | 1240 | {"OK", "WARNING", "CRITICAL", "UNKNOWN", "DEPENDENT"}; |
1126 | int hosts_ok = 0; | 1241 | int hosts_ok = 0; |
1127 | int hosts_warn = 0; | 1242 | int hosts_warn = 0; |
1243 | double R; | ||
1128 | 1244 | ||
1129 | alarm(0); | 1245 | alarm(0); |
1130 | if(debug > 1) printf("finish(%d) called\n", sig); | 1246 | if(debug > 1) printf("finish(%d) called\n", sig); |
@@ -1140,6 +1256,7 @@ finish(int sig) | |||
1140 | } | 1256 | } |
1141 | 1257 | ||
1142 | /* iterate thrice to calculate values, give output, and print perfparse */ | 1258 | /* iterate thrice to calculate values, give output, and print perfparse */ |
1259 | status=STATE_OK; | ||
1143 | host = list; | 1260 | host = list; |
1144 | 1261 | ||
1145 | while(host) { | 1262 | while(host) { |
@@ -1156,19 +1273,104 @@ finish(int sig) | |||
1156 | pl = ((host->icmp_sent - host->icmp_recv) * 100) / host->icmp_sent; | 1273 | pl = ((host->icmp_sent - host->icmp_recv) * 100) / host->icmp_sent; |
1157 | rta = (double)host->time_waited / host->icmp_recv; | 1274 | rta = (double)host->time_waited / host->icmp_recv; |
1158 | } | 1275 | } |
1276 | if (host->icmp_recv>1) { | ||
1277 | host->jitter=(host->jitter / (host->icmp_recv - 1)/1000); | ||
1278 | host->EffectiveLatency = (rta/1000) + host->jitter * 2 + 10; | ||
1279 | if (host->EffectiveLatency < 160) | ||
1280 | R = 93.2 - (host->EffectiveLatency / 40); | ||
1281 | else | ||
1282 | R = 93.2 - ((host->EffectiveLatency - 120) / 10); | ||
1283 | R = R - (pl * 2.5); | ||
1284 | if (R<0) R=0; | ||
1285 | host->score = R; | ||
1286 | host->mos= 1 + ((0.035) * R) + ((.000007) * R * (R-60) * (100-R)); | ||
1287 | } | ||
1288 | else { | ||
1289 | host->jitter=0; | ||
1290 | host->jitter_min=0; | ||
1291 | host->jitter_max=0; | ||
1292 | host->mos=0; | ||
1293 | } | ||
1159 | host->pl = pl; | 1294 | host->pl = pl; |
1160 | host->rta = rta; | 1295 | host->rta = rta; |
1161 | if(pl >= crit.pl || rta >= crit.rta) { | 1296 | |
1162 | status = STATE_CRITICAL; | 1297 | /* if no new mode selected, use old schema */ |
1298 | if (!rta_mode && !pl_mode && !jitter_mode && !score_mode && !mos_mode && !order_mode) { | ||
1299 | rta_mode=1; | ||
1300 | pl_mode=1; | ||
1163 | } | 1301 | } |
1164 | else if(!status && (pl >= warn.pl || rta >= warn.rta)) { | 1302 | |
1165 | status = STATE_WARNING; | 1303 | /* Check which mode is on and do the warn / Crit stuff */ |
1166 | hosts_warn++; | 1304 | if (rta_mode) { |
1305 | if(rta >= crit.rta) { | ||
1306 | status = STATE_CRITICAL; | ||
1307 | host->rta_status=STATE_CRITICAL; | ||
1308 | } | ||
1309 | else if(status!=STATE_CRITICAL && (rta >= warn.rta)) { | ||
1310 | status = STATE_WARNING; | ||
1311 | hosts_warn++; | ||
1312 | host->rta_status=STATE_WARNING; | ||
1313 | } | ||
1314 | else { | ||
1315 | hosts_ok++; | ||
1316 | } | ||
1167 | } | 1317 | } |
1168 | else { | 1318 | if (pl_mode) { |
1169 | hosts_ok++; | 1319 | if(pl >= crit.pl) { |
1320 | status = STATE_CRITICAL; | ||
1321 | host->pl_status=STATE_CRITICAL; | ||
1322 | } | ||
1323 | else if(status!=STATE_CRITICAL && (pl >= warn.pl)) { | ||
1324 | status = STATE_WARNING; | ||
1325 | hosts_warn++; | ||
1326 | host->pl_status=STATE_WARNING; | ||
1327 | } | ||
1328 | else { | ||
1329 | hosts_ok++; | ||
1330 | } | ||
1331 | } | ||
1332 | if (jitter_mode) { | ||
1333 | if(host->jitter >= crit.jitter) { | ||
1334 | status = STATE_CRITICAL; | ||
1335 | host->jitter_status=STATE_CRITICAL; | ||
1336 | } | ||
1337 | else if(status!=STATE_CRITICAL && (host->jitter >= warn.jitter)) { | ||
1338 | status = STATE_WARNING; | ||
1339 | hosts_warn++; | ||
1340 | host->jitter_status=STATE_WARNING; | ||
1341 | } | ||
1342 | else { | ||
1343 | hosts_ok++; | ||
1344 | } | ||
1345 | } | ||
1346 | if (mos_mode) { | ||
1347 | if(host->mos <= crit.mos) { | ||
1348 | status = STATE_CRITICAL; | ||
1349 | host->mos_status=STATE_CRITICAL; | ||
1350 | } | ||
1351 | else if(status!=STATE_CRITICAL && (host->mos <= warn.mos)) { | ||
1352 | status = STATE_WARNING; | ||
1353 | hosts_warn++; | ||
1354 | host->mos_status=STATE_WARNING; | ||
1355 | } | ||
1356 | else { | ||
1357 | hosts_ok++; | ||
1358 | } | ||
1359 | } | ||
1360 | if (score_mode) { | ||
1361 | if(host->score <= crit.score) { | ||
1362 | status = STATE_CRITICAL; | ||
1363 | host->score_status=STATE_CRITICAL; | ||
1364 | } | ||
1365 | else if(status!=STATE_CRITICAL && (host->score <= warn.score)) { | ||
1366 | status = STATE_WARNING; | ||
1367 | score_mode++; | ||
1368 | host->score_status=STATE_WARNING; | ||
1369 | } | ||
1370 | else { | ||
1371 | hosts_ok++; | ||
1372 | } | ||
1170 | } | 1373 | } |
1171 | |||
1172 | host = host->next; | 1374 | host = host->next; |
1173 | } | 1375 | } |
1174 | /* this is inevitable */ | 1376 | /* this is inevitable */ |
@@ -1178,9 +1380,10 @@ finish(int sig) | |||
1178 | else if((hosts_ok + hosts_warn) >= min_hosts_alive) status = STATE_WARNING; | 1380 | else if((hosts_ok + hosts_warn) >= min_hosts_alive) status = STATE_WARNING; |
1179 | } | 1381 | } |
1180 | printf("%s - ", status_string[status]); | 1382 | printf("%s - ", status_string[status]); |
1181 | 1383 | ||
1182 | host = list; | 1384 | host = list; |
1183 | while(host) { | 1385 | while(host) { |
1386 | |||
1184 | if(debug) puts(""); | 1387 | if(debug) puts(""); |
1185 | if(i) { | 1388 | if(i) { |
1186 | if(i < targets) printf(" :: "); | 1389 | if(i < targets) printf(" :: "); |
@@ -1189,6 +1392,8 @@ finish(int sig) | |||
1189 | i++; | 1392 | i++; |
1190 | if(!host->icmp_recv) { | 1393 | if(!host->icmp_recv) { |
1191 | status = STATE_CRITICAL; | 1394 | status = STATE_CRITICAL; |
1395 | host->rtmin=0; | ||
1396 | host->jitter_min=0; | ||
1192 | if(host->flags & FLAG_LOST_CAUSE) { | 1397 | if(host->flags & FLAG_LOST_CAUSE) { |
1193 | char address[INET6_ADDRSTRLEN]; | 1398 | char address[INET6_ADDRSTRLEN]; |
1194 | parse_address(&host->error_addr, address, sizeof(address)); | 1399 | parse_address(&host->error_addr, address, sizeof(address)); |
@@ -1203,26 +1408,92 @@ finish(int sig) | |||
1203 | } | 1408 | } |
1204 | } | 1409 | } |
1205 | else { /* !icmp_recv */ | 1410 | else { /* !icmp_recv */ |
1206 | printf("%s: rta %0.3fms, lost %u%%", | 1411 | printf("%s ", host->name); |
1207 | host->name, host->rta / 1000, host->pl); | 1412 | /* rta text output */ |
1413 | if (rta_mode) { | ||
1414 | if (status == STATE_OK) | ||
1415 | printf("rta %0.3fms", host->rta / 1000); | ||
1416 | else if (status==STATE_WARNING && host->rta_status==status) | ||
1417 | printf("rta %0.3fms > %0.3fms", (float)host->rta / 1000, (float)warn.rta/1000); | ||
1418 | else if (status==STATE_CRITICAL && host->rta_status==status) | ||
1419 | printf("rta %0.3fms > %0.3fms", (float)host->rta / 1000, (float)crit.rta/1000); | ||
1420 | } | ||
1421 | /* pl text output */ | ||
1422 | if (pl_mode) { | ||
1423 | if (status == STATE_OK) | ||
1424 | printf("lost %u%%", host->pl); | ||
1425 | else if (status==STATE_WARNING && host->pl_status==status) | ||
1426 | printf("lost %u%% > %u%%", host->pl, warn.pl); | ||
1427 | else if (status==STATE_CRITICAL && host->pl_status==status) | ||
1428 | printf("lost %u%% > %u%%", host->pl, crit.pl); | ||
1429 | } | ||
1430 | /* jitter text output */ | ||
1431 | if (jitter_mode) { | ||
1432 | if (status == STATE_OK) | ||
1433 | printf("jitter %0.3fms", (float)host->jitter); | ||
1434 | else if (status==STATE_WARNING && host->jitter_status==status) | ||
1435 | printf("jitter %0.3fms > %0.3fms", (float)host->jitter, warn.jitter); | ||
1436 | else if (status==STATE_CRITICAL && host->jitter_status==status) | ||
1437 | printf("jitter %0.3fms > %0.3fms", (float)host->jitter, crit.jitter); | ||
1438 | } | ||
1439 | /* mos text output */ | ||
1440 | if (mos_mode) { | ||
1441 | if (status == STATE_OK) | ||
1442 | printf("MOS %0.1f", (float)host->mos); | ||
1443 | else if (status==STATE_WARNING && host->mos_status==status) | ||
1444 | printf("MOS %0.1f < %0.1f", (float)host->mos, (float)warn.mos); | ||
1445 | else if (status==STATE_CRITICAL && host->mos_status==status) | ||
1446 | printf("MOS %0.1f < %0.1f", (float)host->mos, (float)crit.mos); | ||
1447 | } | ||
1448 | /* score text output */ | ||
1449 | if (score_mode) { | ||
1450 | if (status == STATE_OK) | ||
1451 | printf("Score %u", (int)host->score); | ||
1452 | else if (status==STATE_WARNING && host->score_status==status ) | ||
1453 | printf("Score %u < %u", (int)host->score, (int)warn.score); | ||
1454 | else if (status==STATE_CRITICAL && host->score_status==status ) | ||
1455 | printf("Score %u < %u", (int)host->score, (int)crit.score); | ||
1456 | } | ||
1457 | /* order statis text output */ | ||
1458 | if (order_mode) { | ||
1459 | if (status == STATE_OK) | ||
1460 | printf("Packets in order"); | ||
1461 | else if (status==STATE_CRITICAL && host->order_status==status) | ||
1462 | printf("Packets out of order"); | ||
1463 | } | ||
1208 | } | 1464 | } |
1209 | |||
1210 | host = host->next; | 1465 | host = host->next; |
1211 | } | 1466 | } |
1212 | 1467 | ||
1213 | /* iterate once more for pretty perfparse output */ | 1468 | /* iterate once more for pretty perfparse output */ |
1214 | printf("|"); | 1469 | if (!(!rta_mode && !pl_mode && !jitter_mode && !score_mode && !mos_mode && order_mode)) { |
1470 | printf("|"); | ||
1471 | } | ||
1215 | i = 0; | 1472 | i = 0; |
1216 | host = list; | 1473 | host = list; |
1217 | while(host) { | 1474 | while(host) { |
1218 | if(debug) puts(""); | 1475 | if(debug) puts(""); |
1219 | printf("%srta=%0.3fms;%0.3f;%0.3f;0; %spl=%u%%;%u;%u;; %srtmax=%0.3fms;;;; %srtmin=%0.3fms;;;; ", | 1476 | if (rta_mode && host->pl<100) { |
1477 | // FIXME printf("%srta=%0.3fms;%0.3f;%0.3f;0; %srtmax=%0.3fms;;;; %srtmin=%0.3fms;;;; ",(targets > 1) ? host->name : "", (float)host->rta / 1000, (float)warn.rta / 1000, (float)crit.rta / 1000, (targets > 1) ? host->name : "", (float)host->rtmax / 1000, (targets > 1) ? host->name : "", (float)host->rtmin / 1000); | ||
1478 | printf("%srta=%0.3fms;%0.3f;%0.3f;0; %spl=%u%%;%u;%u;; %srtmax=%0.3fms;;;; %srtmin=%0.3fms;;;; ", | ||
1220 | (targets > 1) ? host->name : "", | 1479 | (targets > 1) ? host->name : "", |
1221 | host->rta / 1000, (float)warn.rta / 1000, (float)crit.rta / 1000, | 1480 | host->rta / 1000, (float)warn.rta / 1000, (float)crit.rta / 1000, |
1222 | (targets > 1) ? host->name : "", host->pl, warn.pl, crit.pl, | 1481 | (targets > 1) ? host->name : "", host->pl, warn.pl, crit.pl, |
1223 | (targets > 1) ? host->name : "", (float)host->rtmax / 1000, | 1482 | (targets > 1) ? host->name : "", (float)host->rtmax / 1000, |
1224 | (targets > 1) ? host->name : "", (host->rtmin < INFINITY) ? (float)host->rtmin / 1000 : (float)0); | 1483 | (targets > 1) ? host->name : "", (host->rtmin < INFINITY) ? (float)host->rtmin / 1000 : (float)0); |
1225 | 1484 | } | |
1485 | if (pl_mode) { | ||
1486 | printf("%spl=%u%%;%u;%u;0;100 ", (targets > 1) ? host->name : "", host->pl, warn.pl, crit.pl); | ||
1487 | } | ||
1488 | if (jitter_mode && host->pl<100) { | ||
1489 | 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); | ||
1490 | } | ||
1491 | if (mos_mode && host->pl<100) { | ||
1492 | printf("%smos=%0.1f;%0.1f;%0.1f;0;5 ", (targets > 1) ? host->name : "", (float)host->mos, (float)warn.mos, (float)crit.mos); | ||
1493 | } | ||
1494 | if (score_mode && host->pl<100) { | ||
1495 | printf("%sscore=%u;%u;%u;0;100 ", (targets > 1) ? host->name : "", (int)host->score, (int)warn.score, (int)crit.score); | ||
1496 | } | ||
1226 | host = host->next; | 1497 | host = host->next; |
1227 | } | 1498 | } |
1228 | 1499 | ||
@@ -1312,6 +1583,7 @@ add_target_ip(char *arg, struct sockaddr_storage *in) | |||
1312 | /* set the values. use calling name for output */ | 1583 | /* set the values. use calling name for output */ |
1313 | host->name = strdup(arg); | 1584 | host->name = strdup(arg); |
1314 | 1585 | ||
1586 | |||
1315 | /* fill out the sockaddr_storage struct */ | 1587 | /* fill out the sockaddr_storage struct */ |
1316 | if(address_family == AF_INET) { | 1588 | if(address_family == AF_INET) { |
1317 | host_sin = (struct sockaddr_in *)&host->saddr_in; | 1589 | host_sin = (struct sockaddr_in *)&host->saddr_in; |
@@ -1324,7 +1596,24 @@ 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); | 1596 | memcpy(host_sin6->sin6_addr.s6_addr, sin6->sin6_addr.s6_addr, sizeof host_sin6->sin6_addr.s6_addr); |
1325 | } | 1597 | } |
1326 | 1598 | ||
1599 | /* fill out the sockaddr_in struct */ | ||
1600 | host->saddr_in.sin_family = AF_INET; | ||
1601 | host->saddr_in.sin_addr.s_addr = in->s_addr; | ||
1327 | host->rtmin = INFINITY; | 1602 | host->rtmin = INFINITY; |
1603 | host->rtmax = 0; | ||
1604 | host->jitter=0; | ||
1605 | host->jitter_max=0; | ||
1606 | host->jitter_min=INFINITY; | ||
1607 | host->last_tdiff=0; | ||
1608 | host->order_status=STATE_OK; | ||
1609 | host->last_icmp_seq=0; | ||
1610 | host->rta_status=0; | ||
1611 | host->pl_status=0; | ||
1612 | host->jitter_status=0; | ||
1613 | host->mos_status=0; | ||
1614 | host->score_status=0; | ||
1615 | host->pl_status=0; | ||
1616 | |||
1328 | 1617 | ||
1329 | if(!list) list = cursor = host; | 1618 | if(!list) list = cursor = host; |
1330 | else cursor->next = host; | 1619 | else cursor->next = host; |
@@ -1472,7 +1761,7 @@ get_timevar(const char *str) | |||
1472 | 1761 | ||
1473 | /* unit might be given as ms|m (millisec), | 1762 | /* unit might be given as ms|m (millisec), |
1474 | * us|u (microsec) or just plain s, for seconds */ | 1763 | * us|u (microsec) or just plain s, for seconds */ |
1475 | u = p = '\0'; | 1764 | p = '\0'; |
1476 | u = str[len - 1]; | 1765 | u = str[len - 1]; |
1477 | if(len >= 2 && !isdigit((int)str[len - 2])) p = str[len - 2]; | 1766 | if(len >= 2 && !isdigit((int)str[len - 2])) p = str[len - 2]; |
1478 | if(p && u == 's') u = p; | 1767 | if(p && u == 's') u = p; |
@@ -1484,7 +1773,7 @@ get_timevar(const char *str) | |||
1484 | else if(u == 's') factor = 1000000; /* seconds */ | 1773 | else if(u == 's') factor = 1000000; /* seconds */ |
1485 | if(debug > 2) printf("factor is %u\n", factor); | 1774 | if(debug > 2) printf("factor is %u\n", factor); |
1486 | 1775 | ||
1487 | i = strtoul(str, &ptr, 0); | 1776 | i = strtoul(str, &ptr, 0); |
1488 | if(!ptr || *ptr != '.' || strlen(ptr) < 2 || factor == 1) | 1777 | if(!ptr || *ptr != '.' || strlen(ptr) < 2 || factor == 1) |
1489 | return i * factor; | 1778 | return i * factor; |
1490 | 1779 | ||
@@ -1530,6 +1819,46 @@ get_threshold(char *str, threshold *th) | |||
1530 | return 0; | 1819 | return 0; |
1531 | } | 1820 | } |
1532 | 1821 | ||
1822 | /* not too good at checking errors, but it'll do (main() should barfe on -1) */ | ||
1823 | static int | ||
1824 | get_threshold2(char *str, threshold *warn, threshold *crit, int type) | ||
1825 | { | ||
1826 | char *p = NULL, i = 0; | ||
1827 | |||
1828 | if(!str || !strlen(str) || !warn || !crit) return -1; | ||
1829 | /* pointer magic slims code by 10 lines. i is bof-stop on stupid libc's */ | ||
1830 | p = &str[strlen(str) - 1]; | ||
1831 | while(p != &str[0]) { | ||
1832 | if( (*p == 'm') || (*p == '%') ) *p = '\0'; | ||
1833 | else if(*p == ',' && i) { | ||
1834 | *p = '\0'; /* reset it so get_timevar(str) works nicely later */ | ||
1835 | if (type==1) | ||
1836 | crit->rta = atof(p+1)*1000; | ||
1837 | else if (type==2) | ||
1838 | crit->pl = (unsigned char)strtoul(p+1, NULL, 0); | ||
1839 | else if (type==3) | ||
1840 | crit->jitter = atof(p+1); | ||
1841 | else if (type==4) | ||
1842 | crit->mos = atof(p+1); | ||
1843 | else if (type==5) | ||
1844 | crit->score = atof(p+1); | ||
1845 | } | ||
1846 | i = 1; | ||
1847 | p--; | ||
1848 | } | ||
1849 | if (type==1) | ||
1850 | warn->rta = atof(p)*1000; | ||
1851 | else if (type==2) | ||
1852 | warn->pl = (unsigned char)strtoul(p, NULL, 0); | ||
1853 | if (type==3) | ||
1854 | warn->jitter = atof(p); | ||
1855 | else if (type==4) | ||
1856 | warn->mos = atof(p); | ||
1857 | else if (type==5) | ||
1858 | warn->score = atof(p); | ||
1859 | return 0; | ||
1860 | } | ||
1861 | |||
1533 | unsigned short | 1862 | unsigned short |
1534 | icmp_checksum(uint16_t *p, size_t n) | 1863 | icmp_checksum(uint16_t *p, size_t n) |
1535 | { | 1864 | { |
@@ -1555,10 +1884,9 @@ icmp_checksum(uint16_t *p, size_t n) | |||
1555 | void | 1884 | void |
1556 | print_help(void) | 1885 | print_help(void) |
1557 | { | 1886 | { |
1558 | |||
1559 | /*print_revision (progname);*/ /* FIXME: Why? */ | 1887 | /*print_revision (progname);*/ /* FIXME: Why? */ |
1560 | |||
1561 | printf ("Copyright (c) 2005 Andreas Ericsson <ae@op5.se>\n"); | 1888 | printf ("Copyright (c) 2005 Andreas Ericsson <ae@op5.se>\n"); |
1889 | |||
1562 | printf (COPYRIGHT, copyright, email); | 1890 | printf (COPYRIGHT, copyright, email); |
1563 | 1891 | ||
1564 | printf ("\n\n"); | 1892 | printf ("\n\n"); |
@@ -1578,11 +1906,29 @@ print_help(void) | |||
1578 | printf (" %s\n", "-c"); | 1906 | printf (" %s\n", "-c"); |
1579 | printf (" %s", _("critical threshold (currently ")); | 1907 | printf (" %s", _("critical threshold (currently ")); |
1580 | printf ("%0.3fms,%u%%)\n", (float)crit.rta / 1000, crit.pl); | 1908 | printf ("%0.3fms,%u%%)\n", (float)crit.rta / 1000, crit.pl); |
1909 | |||
1910 | printf (" %s\n", "-R"); | ||
1911 | printf (" %s\n", _("RTA, round trip average, mode warning,critical, ex. 100ms,200ms unit in ms")); | ||
1912 | printf (" %s\n", "-P"); | ||
1913 | printf (" %s\n", _("packet loss mode, ex. 40%,50% , unit in %")); | ||
1914 | printf (" %s\n", "-J"); | ||
1915 | printf (" %s\n", _("jitter mode warning,critical, ex. 40.000ms,50.000ms , unit in ms ")); | ||
1916 | printf (" %s\n", "-M"); | ||
1917 | printf (" %s\n", _("MOS mode, between 0 and 4.4 warning,critical, ex. 3.5,3.0")); | ||
1918 | printf (" %s\n", "-S"); | ||
1919 | printf (" %s\n", _("score mode, max value 100 warning,critical, ex. 80,70 ")); | ||
1920 | printf (" %s\n", "-O"); | ||
1921 | printf (" %s\n", _("detect out of order ICMP packts ")); | ||
1922 | printf (" %s\n", "-H"); | ||
1923 | printf (" %s\n", _("specify a target")); | ||
1581 | printf (" %s\n", "-s"); | 1924 | printf (" %s\n", "-s"); |
1582 | printf (" %s\n", _("specify a source IP address or device name")); | 1925 | printf (" %s\n", _("specify a source IP address or device name")); |
1583 | printf (" %s\n", "-n"); | 1926 | printf (" %s\n", "-n"); |
1584 | printf (" %s", _("number of packets to send (currently ")); | 1927 | printf (" %s", _("number of packets to send (currently ")); |
1585 | printf ("%u)\n",packets); | 1928 | printf ("%u)\n",packets); |
1929 | printf (" %s\n", "-p"); | ||
1930 | printf (" %s", _("number of packets to send (currently ")); | ||
1931 | printf ("%u)\n",packets); | ||
1586 | printf (" %s\n", "-i"); | 1932 | printf (" %s\n", "-i"); |
1587 | printf (" %s", _("max packet interval (currently ")); | 1933 | printf (" %s", _("max packet interval (currently ")); |
1588 | printf ("%0.3fms)\n",(float)pkt_interval / 1000); | 1934 | printf ("%0.3fms)\n",(float)pkt_interval / 1000); |
@@ -1603,9 +1949,9 @@ print_help(void) | |||
1603 | printf (" %s %u + %d)\n", _("Packet size will be data bytes + icmp header (currently"),icmp_data_size, ICMP_MINLEN); | 1949 | printf (" %s %u + %d)\n", _("Packet size will be data bytes + icmp header (currently"),icmp_data_size, ICMP_MINLEN); |
1604 | printf (" %s\n", "-v"); | 1950 | printf (" %s\n", "-v"); |
1605 | printf (" %s\n", _("verbose")); | 1951 | printf (" %s\n", _("verbose")); |
1606 | |||
1607 | printf ("\n"); | 1952 | printf ("\n"); |
1608 | printf ("%s\n", _("Notes:")); | 1953 | printf ("%s\n", _("Notes:")); |
1954 | printf ("%s\n", _("If not mode R,P,J,M,S or O is informed, default icmp behavior, RTA and packet loss")); | ||
1609 | printf (" %s\n", _("The -H switch is optional. Naming a host (or several) to check is not.")); | 1955 | printf (" %s\n", _("The -H switch is optional. Naming a host (or several) to check is not.")); |
1610 | printf ("\n"); | 1956 | printf ("\n"); |
1611 | printf (" %s\n", _("Threshold format for -w and -c is 200.25,60% for 200.25 msec RTA and 60%")); | 1957 | printf (" %s\n", _("Threshold format for -w and -c is 200.25,60% for 200.25 msec RTA and 60%")); |