summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDanijel Tasov <m@rbfh.de>2023-09-23 14:33:52 (GMT)
committerDanijel Tasov <m@rbfh.de>2023-09-23 14:33:52 (GMT)
commit4b242f0678b69565205bc992bd69ee8e42c5e163 (patch)
tree7298faf5a80abb391bd875563c6207dcb65c39d1
parent719e27ddc2f0b48bcd7fe5584b23e3ce83ddf291 (diff)
parent8272d73e579739cccbfce61f7401cd5f8b9fd0e0 (diff)
downloadmonitoring-plugins-4b242f0678b69565205bc992bd69ee8e42c5e163.tar.gz
Merge branch 'jitter-orig' into merge-jitter
-rw-r--r--plugins-root/check_icmp.c408
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;
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"
@@ -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 */
121typedef struct threshold { 139typedef 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);
188static int recvfrom_wto(int, void *, unsigned int, struct sockaddr *, u_int *, struct timeval*); 209static int recvfrom_wto(int, void *, unsigned int, struct sockaddr *, u_int *, struct timeval*);
189static int send_icmp_ping(int, struct rta_host *); 210static int send_icmp_ping(int, struct rta_host *);
190static int get_threshold(char *str, threshold *th); 211static int get_threshold(char *str, threshold *th);
212static int get_threshold2(char *str, threshold *, threshold *, int type);
191static void run_checks(void); 213static void run_checks(void);
192static void set_source_ip(char *); 214static void set_source_ip(char *);
193static int add_target(char *); 215static int add_target(char *);
@@ -224,6 +246,12 @@ static unsigned int warn_down = 1, crit_down = 1; /* host down threshold values
224static int min_hosts_alive = -1; 246static int min_hosts_alive = -1;
225float pkt_backoff_factor = 1.5; 247float pkt_backoff_factor = 1.5;
226float target_backoff_factor = 1.5; 248float target_backoff_factor = 1.5;
249int rta_mode=0;
250int pl_mode=0;
251int jitter_mode=0;
252int score_mode=0;
253int mos_mode=0;
254int order_mode=0;
227 255
228/** code start **/ 256/** code start **/
229static void 257static 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) */
1823static int
1824get_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
1533unsigned short 1862unsigned short
1534icmp_checksum(uint16_t *p, size_t n) 1863icmp_checksum(uint16_t *p, size_t n)
1535{ 1864{
@@ -1555,10 +1884,9 @@ icmp_checksum(uint16_t *p, size_t n)
1555void 1884void
1556print_help(void) 1885print_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%"));