summaryrefslogtreecommitdiffstats
path: root/plugins-root
diff options
context:
space:
mode:
Diffstat (limited to 'plugins-root')
-rw-r--r--plugins-root/check_icmp.c406
-rw-r--r--plugins-root/t/check_icmp.t58
2 files changed, 432 insertions, 32 deletions
diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c
index 1d47e9fc..0401788c 100644
--- a/plugins-root/check_icmp.c
+++ b/plugins-root/check_icmp.c
@@ -109,18 +109,35 @@ typedef struct rta_host {
109 unsigned char icmp_type, icmp_code; /* type and code from errors */ 109 unsigned char icmp_type, icmp_code; /* type and code from errors */
110 unsigned short flags; /* control/status flags */ 110 unsigned short flags; /* control/status flags */
111 double rta; /* measured RTA */ 111 double rta; /* measured RTA */
112 int rta_status;
112 double rtmax; /* max rtt */ 113 double rtmax; /* max rtt */
113 double rtmin; /* min rtt */ 114 double rtmin; /* min rtt */
115 double jitter; /* measured jitter */
116 int jitter_status;
117 double jitter_max; /* jitter rtt */
118 double jitter_min; /* jitter rtt */
119 double EffectiveLatency;
120 double mos; /* Mean opnion score */
121 int mos_status;
122 double score; /* score */
123 int score_status;
124 u_int last_tdiff;
125 u_int last_icmp_seq; /* Last ICMP_SEQ to check out of order pkts */
114 unsigned char pl; /* measured packet loss */ 126 unsigned char pl; /* measured packet loss */
127 int pl_status;
115 struct rta_host *next; /* linked list */ 128 struct rta_host *next; /* linked list */
129 int order_status;
116} rta_host; 130} rta_host;
117 131
118#define FLAG_LOST_CAUSE 0x01 /* decidedly dead target. */ 132#define FLAG_LOST_CAUSE 0x01 /* decidedly dead target. */
119 133
120/* threshold structure. all values are maximum allowed, exclusive */ 134/* threshold structure. all values are maximum allowed, exclusive */
121typedef struct threshold { 135typedef struct threshold {
122 unsigned char pl; /* max allowed packet loss in percent */ 136 unsigned char pl; /* max allowed packet loss in percent */
123 unsigned int rta; /* roundtrip time average, microseconds */ 137 unsigned int rta; /* roundtrip time average, microseconds */
138 double jitter; /* jitter time average, microseconds */
139 double mos; /* MOS */
140 double score; /* Score */
124} threshold; 141} threshold;
125 142
126/* the data structure */ 143/* the data structure */
@@ -188,6 +205,7 @@ static int wait_for_reply(int, u_int);
188static int recvfrom_wto(int, void *, unsigned int, struct sockaddr *, u_int *, struct timeval*); 205static int recvfrom_wto(int, void *, unsigned int, struct sockaddr *, u_int *, struct timeval*);
189static int send_icmp_ping(int, struct rta_host *); 206static int send_icmp_ping(int, struct rta_host *);
190static int get_threshold(char *str, threshold *th); 207static int get_threshold(char *str, threshold *th);
208static int get_threshold2(char *str, threshold *, threshold *, int type);
191static void run_checks(void); 209static void run_checks(void);
192static void set_source_ip(char *); 210static void set_source_ip(char *);
193static int add_target(char *); 211static int add_target(char *);
@@ -224,6 +242,12 @@ static unsigned int warn_down = 1, crit_down = 1; /* host down threshold values
224static int min_hosts_alive = -1; 242static int min_hosts_alive = -1;
225float pkt_backoff_factor = 1.5; 243float pkt_backoff_factor = 1.5;
226float target_backoff_factor = 1.5; 244float target_backoff_factor = 1.5;
245int rta_mode=0;
246int pl_mode=0;
247int jitter_mode=0;
248int score_mode=0;
249int mos_mode=0;
250int order_mode=0;
227 251
228/** code start **/ 252/** code start **/
229static void 253static void
@@ -393,12 +417,14 @@ main(int argc, char **argv)
393 int icmp_sockerrno, udp_sockerrno, tcp_sockerrno; 417 int icmp_sockerrno, udp_sockerrno, tcp_sockerrno;
394 int result; 418 int result;
395 struct rta_host *host; 419 struct rta_host *host;
420#ifdef HAVE_SIGACTION
421 struct sigaction sig_action;
422#endif
396#ifdef SO_TIMESTAMP 423#ifdef SO_TIMESTAMP
397 int on = 1; 424 int on = 1;
398#endif 425#endif
399 char *source_ip = NULL; 426 char *source_ip = NULL;
400 char * opts_str = "vhVw:c:n:p:t:H:s:i:b:I:l:m:64"; 427 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, ""); 428 setlocale (LC_ALL, "");
403 bindtextdomain (PACKAGE, LOCALEDIR); 429 bindtextdomain (PACKAGE, LOCALEDIR);
404 textdomain (PACKAGE); 430 textdomain (PACKAGE);
@@ -422,10 +448,19 @@ main(int argc, char **argv)
422 table = NULL; 448 table = NULL;
423 449
424 mode = MODE_RTA; 450 mode = MODE_RTA;
451 /* Default critical thresholds */
425 crit.rta = 500000; 452 crit.rta = 500000;
426 crit.pl = 80; 453 crit.pl = 80;
454 crit.jitter = 50;
455 crit.mos= 3;
456 crit.score=70;
457 /* Default warning thresholds */
427 warn.rta = 200000; 458 warn.rta = 200000;
428 warn.pl = 40; 459 warn.pl = 40;
460 warn.jitter = 40;
461 warn.mos= 3.5;
462 warn.score=80;
463
429 protocols = HAVE_ICMP | HAVE_UDP | HAVE_TCP; 464 protocols = HAVE_ICMP | HAVE_UDP | HAVE_TCP;
430 pkt_interval = 80000; /* 80 msec packet interval by default */ 465 pkt_interval = 80000; /* 80 msec packet interval by default */
431 packets = 5; 466 packets = 5;
@@ -481,7 +516,7 @@ main(int argc, char **argv)
481 /* Reset argument scanning */ 516 /* Reset argument scanning */
482 optind = 1; 517 optind = 1;
483 518
484 unsigned short size; 519 unsigned long size;
485 /* parse the arguments */ 520 /* parse the arguments */
486 for(i = 1; i < argc; i++) { 521 for(i = 1; i < argc; i++) {
487 while((arg = getopt(argc, argv, opts_str)) != EOF) { 522 while((arg = getopt(argc, argv, opts_str)) != EOF) {
@@ -490,7 +525,7 @@ main(int argc, char **argv)
490 debug++; 525 debug++;
491 break; 526 break;
492 case 'b': 527 case 'b':
493 size = (unsigned short)strtol(optarg,NULL,0); 528 size = strtol(optarg,NULL,0);
494 if (size >= (sizeof(struct icmp) + sizeof(struct icmp_ping_data)) && 529 if (size >= (sizeof(struct icmp) + sizeof(struct icmp_ping_data)) &&
495 size < MAX_PING_DATA) { 530 size < MAX_PING_DATA) {
496 icmp_data_size = size; 531 icmp_data_size = size;
@@ -545,6 +580,29 @@ main(int argc, char **argv)
545 print_help (); 580 print_help ();
546 exit (STATE_UNKNOWN); 581 exit (STATE_UNKNOWN);
547 break; 582 break;
583 case 'R': /* RTA mode */
584 get_threshold2(optarg, &warn, &crit,1);
585 rta_mode=1;
586 break;
587 case 'P': /* packet loss mode */
588 get_threshold2(optarg, &warn, &crit,2);
589 pl_mode=1;
590 break;
591 case 'J': /* jitter mode */
592 get_threshold2(optarg, &warn, &crit,3);
593 jitter_mode=1;
594 break;
595 case 'M': /* MOS mode */
596 get_threshold2(optarg, &warn, &crit,4);
597 mos_mode=1;
598 break;
599 case 'S': /* score mode */
600 get_threshold2(optarg, &warn, &crit,5);
601 score_mode=1;
602 break;
603 case 'O': /* out of order mode */
604 order_mode=1;
605 break;
548 } 606 }
549 } 607 }
550 } 608 }
@@ -631,11 +689,25 @@ main(int argc, char **argv)
631 if(warn.pl > crit.pl) warn.pl = crit.pl; 689 if(warn.pl > crit.pl) warn.pl = crit.pl;
632 if(warn.rta > crit.rta) warn.rta = crit.rta; 690 if(warn.rta > crit.rta) warn.rta = crit.rta;
633 if(warn_down > crit_down) crit_down = warn_down; 691 if(warn_down > crit_down) crit_down = warn_down;
634 692 if(warn.jitter > crit.jitter) crit.jitter = warn.jitter;
693 if(warn.mos < crit.mos) warn.mos = crit.mos;
694 if(warn.score < crit.score) warn.score = crit.score;
695
696#ifdef HAVE_SIGACTION
697 sig_action.sa_sigaction = NULL;
698 sig_action.sa_handler = finish;
699 sigfillset(&sig_action.sa_mask);
700 sig_action.sa_flags = SA_NODEFER|SA_RESTART;
701 sigaction(SIGINT, &sig_action, NULL);
702 sigaction(SIGHUP, &sig_action, NULL);
703 sigaction(SIGTERM, &sig_action, NULL);
704 sigaction(SIGALRM, &sig_action, NULL);
705#else /* HAVE_SIGACTION */
635 signal(SIGINT, finish); 706 signal(SIGINT, finish);
636 signal(SIGHUP, finish); 707 signal(SIGHUP, finish);
637 signal(SIGTERM, finish); 708 signal(SIGTERM, finish);
638 signal(SIGALRM, finish); 709 signal(SIGALRM, finish);
710#endif /* HAVE_SIGACTION */
639 if(debug) printf("Setting alarm timeout to %u seconds\n", timeout); 711 if(debug) printf("Setting alarm timeout to %u seconds\n", timeout);
640 alarm(timeout); 712 alarm(timeout);
641 713
@@ -685,7 +757,7 @@ main(int argc, char **argv)
685 } 757 }
686 758
687 host = list; 759 host = list;
688 table = (struct rta_host**)malloc(sizeof(struct rta_host **) * targets); 760 table = malloc(sizeof(struct rta_host *) * targets);
689 i = 0; 761 i = 0;
690 while(host) { 762 while(host) {
691 host->id = i*packets; 763 host->id = i*packets;
@@ -772,6 +844,7 @@ wait_for_reply(int sock, u_int t)
772 struct icmp_ping_data data; 844 struct icmp_ping_data data;
773 struct timeval wait_start, now; 845 struct timeval wait_start, now;
774 u_int tdiff, i, per_pkt_wait; 846 u_int tdiff, i, per_pkt_wait;
847 double jitter_tmp;
775 848
776 if (!(packet.buf = malloc(icmp_pkt_size))) { 849 if (!(packet.buf = malloc(icmp_pkt_size))) {
777 crash("send_icmp_ping(): failed to malloc %d bytes for send buffer", 850 crash("send_icmp_ping(): failed to malloc %d bytes for send buffer",
@@ -890,12 +963,43 @@ wait_for_reply(int sock, u_int t)
890 963
891 tdiff = get_timevaldiff(&data.stime, &now); 964 tdiff = get_timevaldiff(&data.stime, &now);
892 965
966 if (host->last_tdiff>0) {
967 /* Calculate jitter */
968 if (host->last_tdiff > tdiff) {
969 jitter_tmp = host->last_tdiff - tdiff;
970 }
971 else {
972 jitter_tmp = tdiff - host->last_tdiff;
973 }
974 if (host->jitter==0) {
975 host->jitter=jitter_tmp;
976 host->jitter_max=jitter_tmp;
977 host->jitter_min=jitter_tmp;
978 }
979 else {
980 host->jitter+=jitter_tmp;
981 if (jitter_tmp < host->jitter_min)
982 host->jitter_min=jitter_tmp;
983 if (jitter_tmp > host->jitter_max)
984 host->jitter_max=jitter_tmp;
985 }
986
987 /* Check if packets in order */
988 if (host->last_icmp_seq >= packet.icp->icmp_seq)
989 host->order_status=STATE_CRITICAL;
990 }
991 host->last_tdiff=tdiff;
992
993 host->last_icmp_seq=packet.icp->icmp_seq;
994
995 //printf("%d tdiff %d host->jitter %u host->last_tdiff %u\n", icp.icmp_seq, tdiff, host->jitter, host->last_tdiff);
996
893 host->time_waited += tdiff; 997 host->time_waited += tdiff;
894 host->icmp_recv++; 998 host->icmp_recv++;
895 icmp_recv++; 999 icmp_recv++;
896 if (tdiff > host->rtmax) 1000 if (tdiff > (int)host->rtmax)
897 host->rtmax = tdiff; 1001 host->rtmax = tdiff;
898 if (tdiff < host->rtmin) 1002 if (tdiff < (int)host->rtmin)
899 host->rtmin = tdiff; 1003 host->rtmin = tdiff;
900 1004
901 if(debug) { 1005 if(debug) {
@@ -1094,8 +1198,10 @@ recvfrom_wto(int sock, void *buf, unsigned int len, struct sockaddr *saddr,
1094 hdr.msg_namelen = slen; 1198 hdr.msg_namelen = slen;
1095 hdr.msg_iov = &iov; 1199 hdr.msg_iov = &iov;
1096 hdr.msg_iovlen = 1; 1200 hdr.msg_iovlen = 1;
1201#ifdef HAVE_MSGHDR_MSG_CONTROL
1097 hdr.msg_control = ans_data; 1202 hdr.msg_control = ans_data;
1098 hdr.msg_controllen = sizeof(ans_data); 1203 hdr.msg_controllen = sizeof(ans_data);
1204#endif
1099 1205
1100 ret = recvmsg(sock, &hdr, 0); 1206 ret = recvmsg(sock, &hdr, 0);
1101#ifdef SO_TIMESTAMP 1207#ifdef SO_TIMESTAMP
@@ -1125,6 +1231,8 @@ finish(int sig)
1125 {"OK", "WARNING", "CRITICAL", "UNKNOWN", "DEPENDENT"}; 1231 {"OK", "WARNING", "CRITICAL", "UNKNOWN", "DEPENDENT"};
1126 int hosts_ok = 0; 1232 int hosts_ok = 0;
1127 int hosts_warn = 0; 1233 int hosts_warn = 0;
1234 int this_status;
1235 double R;
1128 1236
1129 alarm(0); 1237 alarm(0);
1130 if(debug > 1) printf("finish(%d) called\n", sig); 1238 if(debug > 1) printf("finish(%d) called\n", sig);
@@ -1140,9 +1248,11 @@ finish(int sig)
1140 } 1248 }
1141 1249
1142 /* iterate thrice to calculate values, give output, and print perfparse */ 1250 /* iterate thrice to calculate values, give output, and print perfparse */
1251 status=STATE_OK;
1143 host = list; 1252 host = list;
1144 1253
1145 while(host) { 1254 while(host) {
1255 this_status = STATE_OK;
1146 if(!host->icmp_recv) { 1256 if(!host->icmp_recv) {
1147 /* rta 0 is ofcourse not entirely correct, but will still show up 1257 /* rta 0 is ofcourse not entirely correct, but will still show up
1148 * conspicuously as missing entries in perfparse and cacti */ 1258 * conspicuously as missing entries in perfparse and cacti */
@@ -1156,21 +1266,107 @@ finish(int sig)
1156 pl = ((host->icmp_sent - host->icmp_recv) * 100) / host->icmp_sent; 1266 pl = ((host->icmp_sent - host->icmp_recv) * 100) / host->icmp_sent;
1157 rta = (double)host->time_waited / host->icmp_recv; 1267 rta = (double)host->time_waited / host->icmp_recv;
1158 } 1268 }
1269 if (host->icmp_recv>1) {
1270 host->jitter=(host->jitter / (host->icmp_recv - 1)/1000);
1271 host->EffectiveLatency = (rta/1000) + host->jitter * 2 + 10;
1272 if (host->EffectiveLatency < 160)
1273 R = 93.2 - (host->EffectiveLatency / 40);
1274 else
1275 R = 93.2 - ((host->EffectiveLatency - 120) / 10);
1276 R = R - (pl * 2.5);
1277 if (R<0) R=0;
1278 host->score = R;
1279 host->mos= 1 + ((0.035) * R) + ((.000007) * R * (R-60) * (100-R));
1280 }
1281 else {
1282 host->jitter=0;
1283 host->jitter_min=0;
1284 host->jitter_max=0;
1285 host->mos=0;
1286 }
1159 host->pl = pl; 1287 host->pl = pl;
1160 host->rta = rta; 1288 host->rta = rta;
1161 if(pl >= crit.pl || rta >= crit.rta) { 1289
1162 status = STATE_CRITICAL; 1290 /* if no new mode selected, use old schema */
1291 if (!rta_mode && !pl_mode && !jitter_mode && !score_mode && !mos_mode && !order_mode) {
1292 rta_mode=1;
1293 pl_mode=1;
1294 }
1295
1296#define THIS_STATUS_WARNING this_status = (this_status <= STATE_WARNING ? STATE_WARNING : this_status)
1297 /* Check which mode is on and do the warn / Crit stuff */
1298 if (rta_mode) {
1299 if(rta >= crit.rta) {
1300 this_status = STATE_CRITICAL;
1301 status = STATE_CRITICAL;
1302 host->rta_status=STATE_CRITICAL;
1303 }
1304 else if(status!=STATE_CRITICAL && (rta >= warn.rta)) {
1305 THIS_STATUS_WARNING;
1306 status = STATE_WARNING;
1307 host->rta_status=STATE_WARNING;
1308 }
1309 }
1310 if (pl_mode) {
1311 if(pl >= crit.pl) {
1312 this_status = STATE_CRITICAL;
1313 status = STATE_CRITICAL;
1314 host->pl_status=STATE_CRITICAL;
1315 }
1316 else if(status!=STATE_CRITICAL && (pl >= warn.pl)) {
1317 THIS_STATUS_WARNING;
1318 status = STATE_WARNING;
1319 host->pl_status=STATE_WARNING;
1320 }
1321 }
1322 if (jitter_mode) {
1323 if(host->jitter >= crit.jitter) {
1324 this_status = STATE_CRITICAL;
1325 status = STATE_CRITICAL;
1326 host->jitter_status=STATE_CRITICAL;
1327 }
1328 else if(status!=STATE_CRITICAL && (host->jitter >= warn.jitter)) {
1329 THIS_STATUS_WARNING;
1330 status = STATE_WARNING;
1331 host->jitter_status=STATE_WARNING;
1332 }
1333 }
1334 if (mos_mode) {
1335 if(host->mos <= crit.mos) {
1336 this_status = STATE_CRITICAL;
1337 status = STATE_CRITICAL;
1338 host->mos_status=STATE_CRITICAL;
1339 }
1340 else if(status!=STATE_CRITICAL && (host->mos <= warn.mos)) {
1341 THIS_STATUS_WARNING;
1342 status = STATE_WARNING;
1343 host->mos_status=STATE_WARNING;
1344 }
1163 } 1345 }
1164 else if(!status && (pl >= warn.pl || rta >= warn.rta)) { 1346 if (score_mode) {
1165 status = STATE_WARNING; 1347 if(host->score <= crit.score) {
1348 this_status = STATE_CRITICAL;
1349 status = STATE_CRITICAL;
1350 host->score_status=STATE_CRITICAL;
1351 }
1352 else if(status!=STATE_CRITICAL && (host->score <= warn.score)) {
1353 THIS_STATUS_WARNING;
1354 status = STATE_WARNING;
1355 host->score_status=STATE_WARNING;
1356 }
1357 }
1358
1359 if (this_status == STATE_WARNING) {
1166 hosts_warn++; 1360 hosts_warn++;
1167 } 1361 }
1168 else { 1362 else if (this_status == STATE_OK) {
1169 hosts_ok++; 1363 hosts_ok++;
1170 } 1364 }
1171 1365
1172 host = host->next; 1366 host = host->next;
1173 } 1367 }
1368
1369
1174 /* this is inevitable */ 1370 /* this is inevitable */
1175 if(!targets_alive) status = STATE_CRITICAL; 1371 if(!targets_alive) status = STATE_CRITICAL;
1176 if(min_hosts_alive > -1) { 1372 if(min_hosts_alive > -1) {
@@ -1181,6 +1377,7 @@ finish(int sig)
1181 1377
1182 host = list; 1378 host = list;
1183 while(host) { 1379 while(host) {
1380
1184 if(debug) puts(""); 1381 if(debug) puts("");
1185 if(i) { 1382 if(i) {
1186 if(i < targets) printf(" :: "); 1383 if(i < targets) printf(" :: ");
@@ -1189,6 +1386,8 @@ finish(int sig)
1189 i++; 1386 i++;
1190 if(!host->icmp_recv) { 1387 if(!host->icmp_recv) {
1191 status = STATE_CRITICAL; 1388 status = STATE_CRITICAL;
1389 host->rtmin=0;
1390 host->jitter_min=0;
1192 if(host->flags & FLAG_LOST_CAUSE) { 1391 if(host->flags & FLAG_LOST_CAUSE) {
1193 char address[INET6_ADDRSTRLEN]; 1392 char address[INET6_ADDRSTRLEN];
1194 parse_address(&host->error_addr, address, sizeof(address)); 1393 parse_address(&host->error_addr, address, sizeof(address));
@@ -1203,26 +1402,108 @@ finish(int sig)
1203 } 1402 }
1204 } 1403 }
1205 else { /* !icmp_recv */ 1404 else { /* !icmp_recv */
1206 printf("%s: rta %0.3fms, lost %u%%", 1405 printf("%s", host->name);
1207 host->name, host->rta / 1000, host->pl); 1406 /* rta text output */
1407 if (rta_mode) {
1408 if (status == STATE_OK)
1409 printf(" rta %0.3fms", host->rta / 1000);
1410 else if (status==STATE_WARNING && host->rta_status==status)
1411 printf(" rta %0.3fms > %0.3fms", (float)host->rta / 1000, (float)warn.rta/1000);
1412 else if (status==STATE_CRITICAL && host->rta_status==status)
1413 printf(" rta %0.3fms > %0.3fms", (float)host->rta / 1000, (float)crit.rta/1000);
1414 }
1415 /* pl text output */
1416 if (pl_mode) {
1417 if (status == STATE_OK)
1418 printf(" lost %u%%", host->pl);
1419 else if (status==STATE_WARNING && host->pl_status==status)
1420 printf(" lost %u%% > %u%%", host->pl, warn.pl);
1421 else if (status==STATE_CRITICAL && host->pl_status==status)
1422 printf(" lost %u%% > %u%%", host->pl, crit.pl);
1423 }
1424 /* jitter text output */
1425 if (jitter_mode) {
1426 if (status == STATE_OK)
1427 printf(" jitter %0.3fms", (float)host->jitter);
1428 else if (status==STATE_WARNING && host->jitter_status==status)
1429 printf(" jitter %0.3fms > %0.3fms", (float)host->jitter, warn.jitter);
1430 else if (status==STATE_CRITICAL && host->jitter_status==status)
1431 printf(" jitter %0.3fms > %0.3fms", (float)host->jitter, crit.jitter);
1432 }
1433 /* mos text output */
1434 if (mos_mode) {
1435 if (status == STATE_OK)
1436 printf(" MOS %0.1f", (float)host->mos);
1437 else if (status==STATE_WARNING && host->mos_status==status)
1438 printf(" MOS %0.1f < %0.1f", (float)host->mos, (float)warn.mos);
1439 else if (status==STATE_CRITICAL && host->mos_status==status)
1440 printf(" MOS %0.1f < %0.1f", (float)host->mos, (float)crit.mos);
1441 }
1442 /* score text output */
1443 if (score_mode) {
1444 if (status == STATE_OK)
1445 printf(" Score %u", (int)host->score);
1446 else if (status==STATE_WARNING && host->score_status==status )
1447 printf(" Score %u < %u", (int)host->score, (int)warn.score);
1448 else if (status==STATE_CRITICAL && host->score_status==status )
1449 printf(" Score %u < %u", (int)host->score, (int)crit.score);
1450 }
1451 /* order statis text output */
1452 if (order_mode) {
1453 if (status == STATE_OK)
1454 printf(" Packets in order");
1455 else if (status==STATE_CRITICAL && host->order_status==status)
1456 printf(" Packets out of order");
1457 }
1208 } 1458 }
1209
1210 host = host->next; 1459 host = host->next;
1211 } 1460 }
1212 1461
1213 /* iterate once more for pretty perfparse output */ 1462 /* iterate once more for pretty perfparse output */
1214 printf("|"); 1463 if (!(!rta_mode && !pl_mode && !jitter_mode && !score_mode && !mos_mode && order_mode)) {
1464 printf("|");
1465 }
1215 i = 0; 1466 i = 0;
1216 host = list; 1467 host = list;
1217 while(host) { 1468 while(host) {
1218 if(debug) puts(""); 1469 if(debug) puts("");
1219 printf("%srta=%0.3fms;%0.3f;%0.3f;0; %spl=%u%%;%u;%u;; %srtmax=%0.3fms;;;; %srtmin=%0.3fms;;;; ", 1470 if (rta_mode && host->pl<100) {
1471 printf("%srta=%0.3fms;%0.3f;%0.3f;0; %srtmax=%0.3fms;;;; %srtmin=%0.3fms;;;; ",
1220 (targets > 1) ? host->name : "", 1472 (targets > 1) ? host->name : "",
1221 host->rta / 1000, (float)warn.rta / 1000, (float)crit.rta / 1000, 1473 host->rta / 1000, (float)warn.rta / 1000, (float)crit.rta / 1000,
1222 (targets > 1) ? host->name : "", host->pl, warn.pl, crit.pl,
1223 (targets > 1) ? host->name : "", (float)host->rtmax / 1000, 1474 (targets > 1) ? host->name : "", (float)host->rtmax / 1000,
1224 (targets > 1) ? host->name : "", (host->rtmin < INFINITY) ? (float)host->rtmin / 1000 : (float)0); 1475 (targets > 1) ? host->name : "", (host->rtmin < INFINITY) ? (float)host->rtmin / 1000 : (float)0);
1225 1476 }
1477 if (pl_mode) {
1478 printf("%spl=%u%%;%u;%u;0;100 ", (targets > 1) ? host->name : "", host->pl, warn.pl, crit.pl);
1479 }
1480 if (jitter_mode && host->pl<100) {
1481 printf("%sjitter_avg=%0.3fms;%0.3f;%0.3f;0; %sjitter_max=%0.3fms;;;; %sjitter_min=%0.3fms;;;; ",
1482 (targets > 1) ? host->name : "",
1483 (float)host->jitter,
1484 (float)warn.jitter,
1485 (float)crit.jitter,
1486 (targets > 1) ? host->name : "",
1487 (float)host->jitter_max / 1000, (targets > 1) ? host->name : "",
1488 (float)host->jitter_min / 1000
1489 );
1490 }
1491 if (mos_mode && host->pl<100) {
1492 printf("%smos=%0.1f;%0.1f;%0.1f;0;5 ",
1493 (targets > 1) ? host->name : "",
1494 (float)host->mos,
1495 (float)warn.mos,
1496 (float)crit.mos
1497 );
1498 }
1499 if (score_mode && host->pl<100) {
1500 printf("%sscore=%u;%u;%u;0;100 ",
1501 (targets > 1) ? host->name : "",
1502 (int)host->score,
1503 (int)warn.score,
1504 (int)crit.score
1505 );
1506 }
1226 host = host->next; 1507 host = host->next;
1227 } 1508 }
1228 1509
@@ -1312,6 +1593,7 @@ add_target_ip(char *arg, struct sockaddr_storage *in)
1312 /* set the values. use calling name for output */ 1593 /* set the values. use calling name for output */
1313 host->name = strdup(arg); 1594 host->name = strdup(arg);
1314 1595
1596
1315 /* fill out the sockaddr_storage struct */ 1597 /* fill out the sockaddr_storage struct */
1316 if(address_family == AF_INET) { 1598 if(address_family == AF_INET) {
1317 host_sin = (struct sockaddr_in *)&host->saddr_in; 1599 host_sin = (struct sockaddr_in *)&host->saddr_in;
@@ -1324,7 +1606,22 @@ add_target_ip(char *arg, struct sockaddr_storage *in)
1324 memcpy(host_sin6->sin6_addr.s6_addr, sin6->sin6_addr.s6_addr, sizeof host_sin6->sin6_addr.s6_addr); 1606 memcpy(host_sin6->sin6_addr.s6_addr, sin6->sin6_addr.s6_addr, sizeof host_sin6->sin6_addr.s6_addr);
1325 } 1607 }
1326 1608
1609 /* fill out the sockaddr_in struct */
1327 host->rtmin = INFINITY; 1610 host->rtmin = INFINITY;
1611 host->rtmax = 0;
1612 host->jitter=0;
1613 host->jitter_max=0;
1614 host->jitter_min=INFINITY;
1615 host->last_tdiff=0;
1616 host->order_status=STATE_OK;
1617 host->last_icmp_seq=0;
1618 host->rta_status=0;
1619 host->pl_status=0;
1620 host->jitter_status=0;
1621 host->mos_status=0;
1622 host->score_status=0;
1623 host->pl_status=0;
1624
1328 1625
1329 if(!list) list = cursor = host; 1626 if(!list) list = cursor = host;
1330 else cursor->next = host; 1627 else cursor->next = host;
@@ -1472,7 +1769,7 @@ get_timevar(const char *str)
1472 1769
1473 /* unit might be given as ms|m (millisec), 1770 /* unit might be given as ms|m (millisec),
1474 * us|u (microsec) or just plain s, for seconds */ 1771 * us|u (microsec) or just plain s, for seconds */
1475 u = p = '\0'; 1772 p = '\0';
1476 u = str[len - 1]; 1773 u = str[len - 1];
1477 if(len >= 2 && !isdigit((int)str[len - 2])) p = str[len - 2]; 1774 if(len >= 2 && !isdigit((int)str[len - 2])) p = str[len - 2];
1478 if(p && u == 's') u = p; 1775 if(p && u == 's') u = p;
@@ -1530,6 +1827,46 @@ get_threshold(char *str, threshold *th)
1530 return 0; 1827 return 0;
1531} 1828}
1532 1829
1830/* not too good at checking errors, but it'll do (main() should barfe on -1) */
1831static int
1832get_threshold2(char *str, threshold *warn, threshold *crit, int type)
1833{
1834 char *p = NULL, i = 0;
1835
1836 if(!str || !strlen(str) || !warn || !crit) return -1;
1837 /* pointer magic slims code by 10 lines. i is bof-stop on stupid libc's */
1838 p = &str[strlen(str) - 1];
1839 while(p != &str[0]) {
1840 if( (*p == 'm') || (*p == '%') ) *p = '\0';
1841 else if(*p == ',' && i) {
1842 *p = '\0'; /* reset it so get_timevar(str) works nicely later */
1843 if (type==1)
1844 crit->rta = atof(p+1)*1000;
1845 else if (type==2)
1846 crit->pl = (unsigned char)strtoul(p+1, NULL, 0);
1847 else if (type==3)
1848 crit->jitter = atof(p+1);
1849 else if (type==4)
1850 crit->mos = atof(p+1);
1851 else if (type==5)
1852 crit->score = atof(p+1);
1853 }
1854 i = 1;
1855 p--;
1856 }
1857 if (type==1)
1858 warn->rta = atof(p)*1000;
1859 else if (type==2)
1860 warn->pl = (unsigned char)strtoul(p, NULL, 0);
1861 if (type==3)
1862 warn->jitter = atof(p);
1863 else if (type==4)
1864 warn->mos = atof(p);
1865 else if (type==5)
1866 warn->score = atof(p);
1867 return 0;
1868}
1869
1533unsigned short 1870unsigned short
1534icmp_checksum(uint16_t *p, size_t n) 1871icmp_checksum(uint16_t *p, size_t n)
1535{ 1872{
@@ -1555,10 +1892,9 @@ icmp_checksum(uint16_t *p, size_t n)
1555void 1892void
1556print_help(void) 1893print_help(void)
1557{ 1894{
1558
1559 /*print_revision (progname);*/ /* FIXME: Why? */ 1895 /*print_revision (progname);*/ /* FIXME: Why? */
1560
1561 printf ("Copyright (c) 2005 Andreas Ericsson <ae@op5.se>\n"); 1896 printf ("Copyright (c) 2005 Andreas Ericsson <ae@op5.se>\n");
1897
1562 printf (COPYRIGHT, copyright, email); 1898 printf (COPYRIGHT, copyright, email);
1563 1899
1564 printf ("\n\n"); 1900 printf ("\n\n");
@@ -1578,11 +1914,29 @@ print_help(void)
1578 printf (" %s\n", "-c"); 1914 printf (" %s\n", "-c");
1579 printf (" %s", _("critical threshold (currently ")); 1915 printf (" %s", _("critical threshold (currently "));
1580 printf ("%0.3fms,%u%%)\n", (float)crit.rta / 1000, crit.pl); 1916 printf ("%0.3fms,%u%%)\n", (float)crit.rta / 1000, crit.pl);
1917
1918 printf (" %s\n", "-R");
1919 printf (" %s\n", _("RTA, round trip average, mode warning,critical, ex. 100ms,200ms unit in ms"));
1920 printf (" %s\n", "-P");
1921 printf (" %s\n", _("packet loss mode, ex. 40%,50% , unit in %"));
1922 printf (" %s\n", "-J");
1923 printf (" %s\n", _("jitter mode warning,critical, ex. 40.000ms,50.000ms , unit in ms "));
1924 printf (" %s\n", "-M");
1925 printf (" %s\n", _("MOS mode, between 0 and 4.4 warning,critical, ex. 3.5,3.0"));
1926 printf (" %s\n", "-S");
1927 printf (" %s\n", _("score mode, max value 100 warning,critical, ex. 80,70 "));
1928 printf (" %s\n", "-O");
1929 printf (" %s\n", _("detect out of order ICMP packts "));
1930 printf (" %s\n", "-H");
1931 printf (" %s\n", _("specify a target"));
1581 printf (" %s\n", "-s"); 1932 printf (" %s\n", "-s");
1582 printf (" %s\n", _("specify a source IP address or device name")); 1933 printf (" %s\n", _("specify a source IP address or device name"));
1583 printf (" %s\n", "-n"); 1934 printf (" %s\n", "-n");
1584 printf (" %s", _("number of packets to send (currently ")); 1935 printf (" %s", _("number of packets to send (currently "));
1585 printf ("%u)\n",packets); 1936 printf ("%u)\n",packets);
1937 printf (" %s\n", "-p");
1938 printf (" %s", _("number of packets to send (currently "));
1939 printf ("%u)\n",packets);
1586 printf (" %s\n", "-i"); 1940 printf (" %s\n", "-i");
1587 printf (" %s", _("max packet interval (currently ")); 1941 printf (" %s", _("max packet interval (currently "));
1588 printf ("%0.3fms)\n",(float)pkt_interval / 1000); 1942 printf ("%0.3fms)\n",(float)pkt_interval / 1000);
@@ -1603,9 +1957,9 @@ print_help(void)
1603 printf (" %s %u + %d)\n", _("Packet size will be data bytes + icmp header (currently"),icmp_data_size, ICMP_MINLEN); 1957 printf (" %s %u + %d)\n", _("Packet size will be data bytes + icmp header (currently"),icmp_data_size, ICMP_MINLEN);
1604 printf (" %s\n", "-v"); 1958 printf (" %s\n", "-v");
1605 printf (" %s\n", _("verbose")); 1959 printf (" %s\n", _("verbose"));
1606
1607 printf ("\n"); 1960 printf ("\n");
1608 printf ("%s\n", _("Notes:")); 1961 printf ("%s\n", _("Notes:"));
1962 printf (" %s\n", _("If none of R,P,J,M,S or O is specified, default behavior is -R -P"));
1609 printf (" %s\n", _("The -H switch is optional. Naming a host (or several) to check is not.")); 1963 printf (" %s\n", _("The -H switch is optional. Naming a host (or several) to check is not."));
1610 printf ("\n"); 1964 printf ("\n");
1611 printf (" %s\n", _("Threshold format for -w and -c is 200.25,60% for 200.25 msec RTA and 60%")); 1965 printf (" %s\n", _("Threshold format for -w and -c is 200.25,60% for 200.25 msec RTA and 60%"));
diff --git a/plugins-root/t/check_icmp.t b/plugins-root/t/check_icmp.t
index 96addd3b..4f9db868 100644
--- a/plugins-root/t/check_icmp.t
+++ b/plugins-root/t/check_icmp.t
@@ -12,14 +12,14 @@ my $allow_sudo = getTestParameter( "NP_ALLOW_SUDO",
12 "no" ); 12 "no" );
13 13
14if ($allow_sudo eq "yes" or $> == 0) { 14if ($allow_sudo eq "yes" or $> == 0) {
15 plan tests => 20; 15 plan tests => 39;
16} else { 16} else {
17 plan skip_all => "Need sudo to test check_icmp"; 17 plan skip_all => "Need sudo to test check_icmp";
18} 18}
19my $sudo = $> == 0 ? '' : 'sudo'; 19my $sudo = $> == 0 ? '' : 'sudo';
20 20
21my $successOutput = '/OK - .*?: rta (?:[\d\.]+ms)|(?:nan), lost \d+%/'; 21my $successOutput = '/OK - .*? rta (?:[\d\.]+ms)|(?:nan), lost \d+%/';
22my $failureOutput = '/(WARNING|CRITICAL) - .*?: rta [\d\.]+ms, lost \d%/'; 22my $failureOutput = '/(WARNING|CRITICAL) - .*? rta (?:[\d\.]+ms > [\d\.]+ms|nan)/';
23 23
24my $host_responsive = getTestParameter( "NP_HOST_RESPONSIVE", 24my $host_responsive = getTestParameter( "NP_HOST_RESPONSIVE",
25 "The hostname of system responsive to network requests", 25 "The hostname of system responsive to network requests",
@@ -54,7 +54,7 @@ is( $res->return_code, 2, "Syntax ok, with forced critical" );
54like( $res->output, $failureOutput, "Output OK" ); 54like( $res->output, $failureOutput, "Output OK" );
55 55
56$res = NPTest->testCmd( 56$res = NPTest->testCmd(
57 "$sudo ./check_icmp -H $host_nonresponsive -w 10000ms,100% -c 10000ms,100%" 57 "$sudo ./check_icmp -H $host_nonresponsive -w 10000ms,100% -c 10000ms,100% -t 2"
58 ); 58 );
59is( $res->return_code, 2, "Timeout - host nonresponsive" ); 59is( $res->return_code, 2, "Timeout - host nonresponsive" );
60like( $res->output, '/100%/', "Error contains '100%' string (for 100% packet loss)" ); 60like( $res->output, '/100%/', "Error contains '100%' string (for 100% packet loss)" );
@@ -66,13 +66,13 @@ is( $res->return_code, 3, "No hostname" );
66like( $res->output, '/No hosts to check/', "Output with appropriate error message"); 66like( $res->output, '/No hosts to check/', "Output with appropriate error message");
67 67
68$res = NPTest->testCmd( 68$res = NPTest->testCmd(
69 "$sudo ./check_icmp -H $host_nonresponsive -w 10000ms,100% -c 10000ms,100% -n 1 -m 0" 69 "$sudo ./check_icmp -H $host_nonresponsive -w 10000ms,100% -c 10000ms,100% -n 1 -m 0 -t 2"
70 ); 70 );
71is( $res->return_code, 0, "One host nonresponsive - zero required" ); 71is( $res->return_code, 0, "One host nonresponsive - zero required" );
72like( $res->output, $successOutput, "Output OK" ); 72like( $res->output, $successOutput, "Output OK" );
73 73
74$res = NPTest->testCmd( 74$res = NPTest->testCmd(
75 "$sudo ./check_icmp -H $host_responsive -H $host_nonresponsive -w 10000ms,100% -c 10000ms,100% -n 1 -m 1" 75 "$sudo ./check_icmp -H $host_responsive -H $host_nonresponsive -w 10000ms,100% -c 10000ms,100% -n 1 -m 1 -t 2"
76 ); 76 );
77is( $res->return_code, 0, "One of two host nonresponsive - one required" ); 77is( $res->return_code, 0, "One of two host nonresponsive - one required" );
78like( $res->output, $successOutput, "Output OK" ); 78like( $res->output, $successOutput, "Output OK" );
@@ -94,3 +94,49 @@ $res = NPTest->testCmd(
94 ); 94 );
95is( $res->return_code, 0, "Try max packet size" ); 95is( $res->return_code, 0, "Try max packet size" );
96like( $res->output, $successOutput, "Output OK - Didn't overflow" ); 96like( $res->output, $successOutput, "Output OK - Didn't overflow" );
97
98$res = NPTest->testCmd(
99 "$sudo ./check_icmp -H $host_responsive -R 100,100 -n 1 -t 2"
100 );
101is( $res->return_code, 0, "rta works" );
102like( $res->output, $successOutput, "Output OK" );
103$res = NPTest->testCmd(
104 "$sudo ./check_icmp -H $host_responsive -P 80,90 -n 1 -t 2"
105 );
106is( $res->return_code, 0, "pl works" );
107like( $res->output, '/lost 0%/', "Output OK" );
108
109$res = NPTest->testCmd(
110 "$sudo ./check_icmp -H $host_responsive -J 80,90 -t 2"
111 );
112is( $res->return_code, 0, "jitter works" );
113like( $res->output, '/jitter \d/', "Output OK" );
114
115$res = NPTest->testCmd(
116 "$sudo ./check_icmp -H $host_responsive -M 4,3 -t 2"
117 );
118is( $res->return_code, 0, "mos works" );
119like( $res->output, '/MOS \d/', "Output OK" );
120
121$res = NPTest->testCmd(
122 "$sudo ./check_icmp -H $host_responsive -S 80,70 -t 2"
123 );
124is( $res->return_code, 0, "score works" );
125like( $res->output, '/Score \d/', "Output OK" );
126
127$res = NPTest->testCmd(
128 "$sudo ./check_icmp -H $host_responsive -O -t 2"
129 );
130is( $res->return_code, 0, "order works" );
131like( $res->output, '/Packets in order/', "Output OK" );
132
133$res = NPTest->testCmd(
134 "$sudo ./check_icmp -H $host_responsive -O -S 80,70 -M 4,3 -J 80,90 -P 80,90 -R 100,100 -t 2"
135 );
136is( $res->return_code, 0, "order works" );
137like( $res->output, '/Packets in order/', "Output OK" );
138like( $res->output, '/Score \d/', "Output OK" );
139like( $res->output, '/MOS \d/', "Output OK" );
140like( $res->output, '/jitter \d/', "Output OK" );
141like( $res->output, '/lost 0%/', "Output OK" );
142like( $res->output, $successOutput, "Output OK" );