summaryrefslogtreecommitdiffstats
path: root/plugins-root/check_icmp.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins-root/check_icmp.c')
-rw-r--r--plugins-root/check_icmp.c83
1 files changed, 49 insertions, 34 deletions
diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c
index 01ae174..f8f1535 100644
--- a/plugins-root/check_icmp.c
+++ b/plugins-root/check_icmp.c
@@ -50,19 +50,11 @@ const char *email = "devel@monitoring-plugins.org";
50#if HAVE_SYS_SOCKIO_H 50#if HAVE_SYS_SOCKIO_H
51#include <sys/sockio.h> 51#include <sys/sockio.h>
52#endif 52#endif
53#include <sys/ioctl.h> 53
54#include <sys/time.h> 54#include <sys/time.h>
55#include <sys/types.h>
56#include <stdio.h>
57#include <stdlib.h>
58#include <stdarg.h>
59#include <unistd.h>
60#include <stddef.h>
61#include <errno.h> 55#include <errno.h>
62#include <string.h> 56#include <signal.h>
63#include <ctype.h> 57#include <ctype.h>
64#include <netdb.h>
65#include <sys/socket.h>
66#include <net/if.h> 58#include <net/if.h>
67#include <netinet/in_systm.h> 59#include <netinet/in_systm.h>
68#include <netinet/in.h> 60#include <netinet/in.h>
@@ -71,8 +63,6 @@ const char *email = "devel@monitoring-plugins.org";
71#include <netinet/ip_icmp.h> 63#include <netinet/ip_icmp.h>
72#include <netinet/icmp6.h> 64#include <netinet/icmp6.h>
73#include <arpa/inet.h> 65#include <arpa/inet.h>
74#include <signal.h>
75#include <float.h>
76 66
77 67
78/** sometimes undefined system macros (quite a few, actually) **/ 68/** sometimes undefined system macros (quite a few, actually) **/
@@ -207,7 +197,7 @@ static int add_target(char *);
207static int add_target_ip(char *, struct sockaddr_storage *); 197static int add_target_ip(char *, struct sockaddr_storage *);
208static int handle_random_icmp(unsigned char *, struct sockaddr_storage *); 198static int handle_random_icmp(unsigned char *, struct sockaddr_storage *);
209static void parse_address(struct sockaddr_storage *, char *, int); 199static void parse_address(struct sockaddr_storage *, char *, int);
210static unsigned short icmp_checksum(unsigned short *, int); 200static unsigned short icmp_checksum(uint16_t *, size_t);
211static void finish(int); 201static void finish(int);
212static void crash(const char *, ...); 202static void crash(const char *, ...);
213 203
@@ -223,7 +213,7 @@ static int mode, protocols, sockets, debug = 0, timeout = 10;
223static unsigned short icmp_data_size = DEFAULT_PING_DATA_SIZE; 213static unsigned short icmp_data_size = DEFAULT_PING_DATA_SIZE;
224static unsigned short icmp_pkt_size = DEFAULT_PING_DATA_SIZE + ICMP_MINLEN; 214static unsigned short icmp_pkt_size = DEFAULT_PING_DATA_SIZE + ICMP_MINLEN;
225 215
226static unsigned int icmp_sent = 0, icmp_recv = 0, icmp_lost = 0; 216static unsigned int icmp_sent = 0, icmp_recv = 0, icmp_lost = 0, ttl = 0;
227#define icmp_pkts_en_route (icmp_sent - (icmp_recv + icmp_lost)) 217#define icmp_pkts_en_route (icmp_sent - (icmp_recv + icmp_lost))
228static unsigned short targets_down = 0, targets = 0, packets = 0; 218static unsigned short targets_down = 0, targets = 0, packets = 0;
229#define targets_alive (targets - targets_down) 219#define targets_alive (targets - targets_down)
@@ -233,7 +223,6 @@ static pid_t pid;
233static struct timezone tz; 223static struct timezone tz;
234static struct timeval prog_start; 224static struct timeval prog_start;
235static unsigned long long max_completion_time = 0; 225static unsigned long long max_completion_time = 0;
236static unsigned char ttl = 0; /* outgoing ttl */
237static unsigned int warn_down = 1, crit_down = 1; /* host down threshold values */ 226static unsigned int warn_down = 1, crit_down = 1; /* host down threshold values */
238static int min_hosts_alive = -1; 227static int min_hosts_alive = -1;
239float pkt_backoff_factor = 1.5; 228float pkt_backoff_factor = 1.5;
@@ -410,6 +399,7 @@ main(int argc, char **argv)
410#ifdef SO_TIMESTAMP 399#ifdef SO_TIMESTAMP
411 int on = 1; 400 int on = 1;
412#endif 401#endif
402 char *source_ip = NULL;
413 char * opts_str = "vhVw:c:n:p:t:H:s:i:b:I:l:m:64"; 403 char * opts_str = "vhVw:c:n:p:t:H:s:i:b:I:l:m:64";
414 404
415 setlocale (LC_ALL, ""); 405 setlocale (LC_ALL, "");
@@ -464,7 +454,6 @@ main(int argc, char **argv)
464 /* Parse protocol arguments first */ 454 /* Parse protocol arguments first */
465 for(i = 1; i < argc; i++) { 455 for(i = 1; i < argc; i++) {
466 while((arg = getopt(argc, argv, opts_str)) != EOF) { 456 while((arg = getopt(argc, argv, opts_str)) != EOF) {
467 unsigned short size;
468 switch(arg) { 457 switch(arg) {
469 case '4': 458 case '4':
470 if (address_family != -1) 459 if (address_family != -1)
@@ -487,10 +476,10 @@ main(int argc, char **argv)
487 /* Reset argument scanning */ 476 /* Reset argument scanning */
488 optind = 1; 477 optind = 1;
489 478
479 unsigned short size;
490 /* parse the arguments */ 480 /* parse the arguments */
491 for(i = 1; i < argc; i++) { 481 for(i = 1; i < argc; i++) {
492 while((arg = getopt(argc, argv, opts_str)) != EOF) { 482 while((arg = getopt(argc, argv, opts_str)) != EOF) {
493 unsigned short size;
494 switch(arg) { 483 switch(arg) {
495 case 'v': 484 case 'v':
496 debug++; 485 debug++;
@@ -530,7 +519,7 @@ main(int argc, char **argv)
530 add_target(optarg); 519 add_target(optarg);
531 break; 520 break;
532 case 'l': 521 case 'l':
533 ttl = (unsigned char)strtoul(optarg, NULL, 0); 522 ttl = (int)strtoul(optarg, NULL, 0);
534 break; 523 break;
535 case 'm': 524 case 'm':
536 min_hosts_alive = (int)strtoul(optarg, NULL, 0); 525 min_hosts_alive = (int)strtoul(optarg, NULL, 0);
@@ -542,7 +531,7 @@ main(int argc, char **argv)
542 } 531 }
543 break; 532 break;
544 case 's': /* specify source IP address */ 533 case 's': /* specify source IP address */
545 set_source_ip(optarg); 534 source_ip = optarg;
546 break; 535 break;
547 case 'V': /* version */ 536 case 'V': /* version */
548 print_revision (progname, NP_VERSION); 537 print_revision (progname, NP_VERSION);
@@ -597,6 +586,8 @@ main(int argc, char **argv)
597 sockets |= HAVE_ICMP; 586 sockets |= HAVE_ICMP;
598 else icmp_sockerrno = errno; 587 else icmp_sockerrno = errno;
599 588
589 if( source_ip )
590 set_source_ip(source_ip);
600 591
601#ifdef SO_TIMESTAMP 592#ifdef SO_TIMESTAMP
602 if(setsockopt(icmp_sock, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on))) 593 if(setsockopt(icmp_sock, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on)))
@@ -717,7 +708,7 @@ main(int argc, char **argv)
717static void 708static void
718run_checks() 709run_checks()
719{ 710{
720 u_int i, t, result; 711 u_int i, t;
721 u_int final_wait, time_passed; 712 u_int final_wait, time_passed;
722 713
723 /* this loop might actually violate the pkt_interval or target_interval 714 /* this loop might actually violate the pkt_interval or target_interval
@@ -735,9 +726,9 @@ run_checks()
735 726
736 /* we're still in the game, so send next packet */ 727 /* we're still in the game, so send next packet */
737 (void)send_icmp_ping(icmp_sock, table[t]); 728 (void)send_icmp_ping(icmp_sock, table[t]);
738 result = wait_for_reply(icmp_sock, target_interval); 729 wait_for_reply(icmp_sock, target_interval);
739 } 730 }
740 result = wait_for_reply(icmp_sock, pkt_interval * targets); 731 wait_for_reply(icmp_sock, pkt_interval * targets);
741 } 732 }
742 733
743 if(icmp_pkts_en_route && targets_alive) { 734 if(icmp_pkts_en_route && targets_alive) {
@@ -757,7 +748,7 @@ run_checks()
757 * haven't yet */ 748 * haven't yet */
758 if(debug) printf("Waiting for %u micro-seconds (%0.3f msecs)\n", 749 if(debug) printf("Waiting for %u micro-seconds (%0.3f msecs)\n",
759 final_wait, (float)final_wait / 1000); 750 final_wait, (float)final_wait / 1000);
760 result = wait_for_reply(icmp_sock, final_wait); 751 wait_for_reply(icmp_sock, final_wait);
761 } 752 }
762} 753}
763 754
@@ -776,7 +767,7 @@ static int
776wait_for_reply(int sock, u_int t) 767wait_for_reply(int sock, u_int t)
777{ 768{
778 int n, hlen; 769 int n, hlen;
779 static unsigned char buf[4096]; 770 static unsigned char buf[65536];
780 struct sockaddr_storage resp_addr; 771 struct sockaddr_storage resp_addr;
781 union ip_hdr *ip; 772 union ip_hdr *ip;
782 union icmp_packet packet; 773 union icmp_packet packet;
@@ -913,9 +904,27 @@ wait_for_reply(int sock, u_int t)
913 if(debug) { 904 if(debug) {
914 char address[INET6_ADDRSTRLEN]; 905 char address[INET6_ADDRSTRLEN];
915 parse_address(&resp_addr, address, sizeof(address)); 906 parse_address(&resp_addr, address, sizeof(address));
916 printf("%0.3f ms rtt from %s, outgoing ttl: %u, incoming ttl: %u, max: %0.3f, min: %0.3f\n", 907
917 (float)tdiff / 1000, address, 908 switch(address_family) {
918 ttl, ip->ip.ip_ttl, (float)host->rtmax / 1000, (float)host->rtmin / 1000); 909 case AF_INET: {
910 printf("%0.3f ms rtt from %s, outgoing ttl: %u, incoming ttl: %u, max: %0.3f, min: %0.3f\n",
911 (float)tdiff / 1000,
912 address,
913 ttl,
914 ip->ip.ip_ttl,
915 (float)host->rtmax / 1000,
916 (float)host->rtmin / 1000);
917 break;
918 };
919 case AF_INET6: {
920 printf("%0.3f ms rtt from %s, outgoing ttl: %u, max: %0.3f, min: %0.3f\n",
921 (float)tdiff / 1000,
922 address,
923 ttl,
924 (float)host->rtmax / 1000,
925 (float)host->rtmin / 1000);
926 };
927 }
919 } 928 }
920 929
921 /* if we're in hostcheck mode, exit with limited printouts */ 930 /* if we're in hostcheck mode, exit with limited printouts */
@@ -938,6 +947,7 @@ static int
938send_icmp_ping(int sock, struct rta_host *host) 947send_icmp_ping(int sock, struct rta_host *host)
939{ 948{
940 long int len; 949 long int len;
950 size_t addrlen;
941 struct icmp_ping_data data; 951 struct icmp_ping_data data;
942 struct msghdr hdr; 952 struct msghdr hdr;
943 struct iovec iov; 953 struct iovec iov;
@@ -969,6 +979,7 @@ send_icmp_ping(int sock, struct rta_host *host)
969 979
970 if (address_family == AF_INET) { 980 if (address_family == AF_INET) {
971 struct icmp *icp = (struct icmp*)buf; 981 struct icmp *icp = (struct icmp*)buf;
982 addrlen = sizeof(struct sockaddr_in);
972 983
973 memcpy(&icp->icmp_data, &data, sizeof(data)); 984 memcpy(&icp->icmp_data, &data, sizeof(data));
974 985
@@ -977,7 +988,7 @@ send_icmp_ping(int sock, struct rta_host *host)
977 icp->icmp_cksum = 0; 988 icp->icmp_cksum = 0;
978 icp->icmp_id = htons(pid); 989 icp->icmp_id = htons(pid);
979 icp->icmp_seq = htons(host->id++); 990 icp->icmp_seq = htons(host->id++);
980 icp->icmp_cksum = icmp_checksum((unsigned short*)buf, icmp_pkt_size); 991 icp->icmp_cksum = icmp_checksum((uint16_t*)buf, (size_t)icmp_pkt_size);
981 992
982 if (debug > 2) 993 if (debug > 2)
983 printf("Sending ICMP echo-request of len %lu, id %u, seq %u, cksum 0x%X to host %s\n", 994 printf("Sending ICMP echo-request of len %lu, id %u, seq %u, cksum 0x%X to host %s\n",
@@ -985,7 +996,10 @@ send_icmp_ping(int sock, struct rta_host *host)
985 } 996 }
986 else { 997 else {
987 struct icmp6_hdr *icp6 = (struct icmp6_hdr*)buf; 998 struct icmp6_hdr *icp6 = (struct icmp6_hdr*)buf;
999 addrlen = sizeof(struct sockaddr_in6);
1000
988 memcpy(&icp6->icmp6_dataun.icmp6_un_data8[4], &data, sizeof(data)); 1001 memcpy(&icp6->icmp6_dataun.icmp6_un_data8[4], &data, sizeof(data));
1002
989 icp6->icmp6_type = ICMP6_ECHO_REQUEST; 1003 icp6->icmp6_type = ICMP6_ECHO_REQUEST;
990 icp6->icmp6_code = 0; 1004 icp6->icmp6_code = 0;
991 icp6->icmp6_cksum = 0; 1005 icp6->icmp6_cksum = 0;
@@ -1006,7 +1020,7 @@ send_icmp_ping(int sock, struct rta_host *host)
1006 1020
1007 memset(&hdr, 0, sizeof(hdr)); 1021 memset(&hdr, 0, sizeof(hdr));
1008 hdr.msg_name = (struct sockaddr *)&host->saddr_in; 1022 hdr.msg_name = (struct sockaddr *)&host->saddr_in;
1009 hdr.msg_namelen = sizeof(struct sockaddr_storage); 1023 hdr.msg_namelen = addrlen;
1010 hdr.msg_iov = &iov; 1024 hdr.msg_iov = &iov;
1011 hdr.msg_iovlen = 1; 1025 hdr.msg_iovlen = 1;
1012 1026
@@ -1514,18 +1528,19 @@ get_threshold(char *str, threshold *th)
1514} 1528}
1515 1529
1516unsigned short 1530unsigned short
1517icmp_checksum(unsigned short *p, int n) 1531icmp_checksum(uint16_t *p, size_t n)
1518{ 1532{
1519 unsigned short cksum; 1533 unsigned short cksum;
1520 long sum = 0; 1534 long sum = 0;
1521 1535
1522 while(n > 2) { 1536 /* sizeof(uint16_t) == 2 */
1523 sum += *p++; 1537 while(n >= 2) {
1524 n -= sizeof(unsigned short); 1538 sum += *(p++);
1539 n -= 2;
1525 } 1540 }
1526 1541
1527 /* mop up the occasional odd byte */ 1542 /* mop up the occasional odd byte */
1528 if(n == 1) sum += (unsigned char)*p; 1543 if(n == 1) sum += *((uint8_t *)p -1);
1529 1544
1530 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ 1545 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
1531 sum += (sum >> 16); /* add carry */ 1546 sum += (sum >> 16); /* add carry */