diff options
-rw-r--r-- | .travis.yml | 14 | ||||
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | THANKS.in | 1 | ||||
-rw-r--r-- | lib/utils_base.c | 19 | ||||
-rw-r--r-- | lib/utils_base.h | 5 | ||||
-rw-r--r-- | lib/utils_cmd.c | 42 | ||||
-rw-r--r-- | lib/utils_cmd.h | 13 | ||||
-rw-r--r-- | plugins-root/check_icmp.c | 465 | ||||
-rw-r--r-- | plugins/check_dbi.c | 1 | ||||
-rw-r--r-- | plugins/check_dns.c | 36 | ||||
-rw-r--r-- | plugins/check_hpjd.c | 12 | ||||
-rw-r--r-- | plugins/check_http.c | 2 | ||||
-rw-r--r-- | plugins/check_pgsql.c | 1 | ||||
-rw-r--r-- | plugins/check_smtp.c | 1 | ||||
-rw-r--r-- | plugins/common.h | 14 | ||||
-rw-r--r-- | plugins/popen.c | 29 | ||||
-rw-r--r-- | plugins/runcmd.c | 13 | ||||
-rw-r--r-- | plugins/t/NPTest.cache.travis | 2 | ||||
-rw-r--r-- | plugins/tests/certs/server-cert.pem | 41 | ||||
-rw-r--r-- | plugins/tests/certs/server-key.pem | 43 | ||||
-rwxr-xr-x | plugins/tests/check_http.t | 16 | ||||
-rwxr-xr-x | plugins/tests/check_snmp.t | 110 | ||||
-rw-r--r-- | plugins/utils.c | 31 | ||||
-rw-r--r-- | plugins/utils.h | 9 |
24 files changed, 572 insertions, 350 deletions
diff --git a/.travis.yml b/.travis.yml index 712f2475..946345c4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ sudo: required -dist: trusty +dist: xenial language: c env: @@ -39,7 +39,6 @@ before_install: - "sudo killall -9 ntpd ||:" # Trusty has no swap, lets create some - sudo fallocate -l 20M /swapfile; sudo chmod 600 /swapfile; sudo mkswap /swapfile; sudo swapon /swapfile - - sudo add-apt-repository -y ppa:waja/trusty-backports - sudo apt-get update -qq - sudo apt-get purge -qq gawk @@ -52,7 +51,7 @@ install: - sudo apt-get install -qq --no-install-recommends autoconf automake - sudo apt-get install -qq --no-install-recommends faketime - sudo apt-get install -qq --no-install-recommends libmonitoring-plugin-perl - - sudo apt-get install -qq --no-install-recommends squid3 + - sudo apt-get install -qq --no-install-recommends squid # Trusty related dependencies (not yet provided) - test "$(dpkg -l | grep -E "mysql-(client|server)-[0-9].[0-9]" | grep -c ^ii)" -gt 0 || sudo apt-get install -qq --no-install-recommends mariadb-client mariadb-server # enable ssl apache @@ -60,8 +59,9 @@ install: - sudo a2ensite default-ssl - sudo make-ssl-cert generate-default-snakeoil --force-overwrite - sudo service apache2 reload - - sudo cp tools/squid.conf /etc/squid3/squid.conf - - sudo service squid3 reload + - sudo cp tools/squid.conf /etc/squid/squid.conf + - sudo service squid reload + - sudo service mysql restart before_script: # ensure we have a test database in place for tests @@ -73,8 +73,8 @@ before_script: - make - export NPTEST_ACCEPTDEFAULT=1 - export NPTEST_CACHE="$(pwd)/plugins/t/NPTest.cache.travis" - - ssh-keygen -t dsa -N "" -f ~/.ssh/id_dsa - - cat ~/.ssh/id_dsa.pub >> ~/.ssh/authorized_keys + - ssh-keygen -t rsa -N "" -f ~/.ssh/id_rsa + - cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys - ssh-keyscan localhost >> ~/.ssh/known_hosts - touch ~/.ssh/config - sudo rm -f /usr/share/mibs/ietf/SNMPv2-PDU /usr/share/mibs/ietf/IPSEC-SPD-MIB /usr/share/mibs/ietf/IPATM-IPMC-MIB /usr/share/mibs/iana/IANA-IPPM-METRICS-REGISTRY-MIB @@ -5,6 +5,8 @@ This file documents the major additions and syntax changes between releases. check_dns: allow 'expected address' (-a) to be specified in CIDR notation (IPv4 only). check_dns: allow for IPv6 RDNS + check_dns: allow unsorted addresses + check_dns: allow forcing complete match of all addresses check_apt: add --only-critical switch check_apt: add -l/--list option to print packages @@ -356,3 +356,4 @@ Sven Geggus Thomas Kurschel Yannick Charton Nicolai Søborg +Rolf Eike Beer diff --git a/lib/utils_base.c b/lib/utils_base.c index 19a531f5..fd7058da 100644 --- a/lib/utils_base.c +++ b/lib/utils_base.c @@ -37,6 +37,9 @@ monitoring_plugin *this_monitoring_plugin=NULL; +unsigned int timeout_state = STATE_CRITICAL; +unsigned int timeout_interval = DEFAULT_SOCKET_TIMEOUT; + int _np_state_read_file(FILE *); void np_init( char *plugin_name, int argc, char **argv ) { @@ -359,6 +362,22 @@ char *np_extract_value(const char *varlist, const char *name, char sep) { return value; } +const char * +state_text (int result) +{ + switch (result) { + case STATE_OK: + return "OK"; + case STATE_WARNING: + return "WARNING"; + case STATE_CRITICAL: + return "CRITICAL"; + case STATE_DEPENDENT: + return "DEPENDENT"; + default: + return "UNKNOWN"; + } +} /* * Read a string representing a state (ok, warning... or numeric: 0, 1) and diff --git a/lib/utils_base.h b/lib/utils_base.h index 42ae0c09..d7e7dffa 100644 --- a/lib/utils_base.h +++ b/lib/utils_base.h @@ -61,6 +61,10 @@ void print_thresholds(const char *, thresholds *); int check_range(double, range *); int get_status(double, thresholds *); +/* Handle timeouts */ +extern unsigned int timeout_state; +extern unsigned int timeout_interval; + /* All possible characters in a threshold range */ #define NP_THRESHOLDS_CHARS "-0123456789.:@~" @@ -107,5 +111,6 @@ void np_state_write_string(time_t, char *); void np_init(char *, int argc, char **argv); void np_set_args(int argc, char **argv); void np_cleanup(); +const char *state_text (int); #endif /* _UTILS_BASE_ */ diff --git a/lib/utils_cmd.c b/lib/utils_cmd.c index 7eb9a3a0..795840d3 100644 --- a/lib/utils_cmd.c +++ b/lib/utils_cmd.c @@ -40,6 +40,7 @@ /** includes **/ #include "common.h" +#include "utils.h" #include "utils_cmd.h" #include "utils_base.h" #include <fcntl.h> @@ -65,31 +66,6 @@ extern char **environ; # define SIG_ERR ((Sigfunc *)-1) #endif -/* This variable must be global, since there's no way the caller - * can forcibly slay a dead or ungainly running program otherwise. - * Multithreading apps and plugins can initialize it (via CMD_INIT) - * in an async safe manner PRIOR to calling cmd_run() or cmd_run_array() - * for the first time. - * - * The check for initialized values is atomic and can - * occur in any number of threads simultaneously. */ -static pid_t *_cmd_pids = NULL; - -/* Try sysconf(_SC_OPEN_MAX) first, as it can be higher than OPEN_MAX. - * If that fails and the macro isn't defined, we fall back to an educated - * guess. There's no guarantee that our guess is adequate and the program - * will die with SIGSEGV if it isn't and the upper boundary is breached. */ -#define DEFAULT_MAXFD 256 /* fallback value if no max open files value is set */ -#define MAXFD_LIMIT 8192 /* upper limit of open files */ -#ifdef _SC_OPEN_MAX -static long maxfd = 0; -#elif defined(OPEN_MAX) -# define maxfd OPEN_MAX -#else /* sysconf macro unavailable, so guess (may be wildly inaccurate) */ -# define maxfd DEFAULT_MAXFD -#endif - - /** prototypes **/ static int _cmd_open (char *const *, int *, int *) __attribute__ ((__nonnull__ (1, 2, 3))); @@ -406,3 +382,19 @@ cmd_file_read ( char *filename, output *out, int flags) return 0; } + +void +timeout_alarm_handler (int signo) +{ + size_t i; + if (signo == SIGALRM) { + printf (_("%s - Plugin timed out after %d seconds\n"), + state_text(timeout_state), timeout_interval); + + if(_cmd_pids) for(i = 0; i < maxfd; i++) { + if(_cmd_pids[i] != 0) kill(_cmd_pids[i], SIGKILL); + } + + exit (timeout_state); + } +} diff --git a/lib/utils_cmd.h b/lib/utils_cmd.h index ebaf15be..6f3aeb81 100644 --- a/lib/utils_cmd.h +++ b/lib/utils_cmd.h @@ -32,4 +32,17 @@ void cmd_init (void); #define CMD_NO_ARRAYS 0x01 /* don't populate arrays at all */ #define CMD_NO_ASSOC 0x02 /* output.line won't point to buf */ +/* This variable must be global, since there's no way the caller + * can forcibly slay a dead or ungainly running program otherwise. + * Multithreading apps and plugins can initialize it (via CMD_INIT) + * in an async safe manner PRIOR to calling cmd_run() or cmd_run_array() + * for the first time. + * + * The check for initialized values is atomic and can + * occur in any number of threads simultaneously. */ +static pid_t *_cmd_pids = NULL; + +RETSIGTYPE timeout_alarm_handler (int); + + #endif /* _UTILS_CMD_ */ diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c index 4098874c..e45fdf60 100644 --- a/plugins-root/check_icmp.c +++ b/plugins-root/check_icmp.c @@ -67,7 +67,9 @@ const char *email = "devel@monitoring-plugins.org"; #include <netinet/in_systm.h> #include <netinet/in.h> #include <netinet/ip.h> +#include <netinet/ip6.h> #include <netinet/ip_icmp.h> +#include <netinet/icmp6.h> #include <arpa/inet.h> #include <signal.h> #include <float.h> @@ -113,8 +115,8 @@ typedef struct rta_host { unsigned short id; /* id in **table, and icmp pkts */ char *name; /* arg used for adding this host */ char *msg; /* icmp error message, if any */ - struct sockaddr_in saddr_in; /* the address of this host */ - struct in_addr error_addr; /* stores address of error replies */ + struct sockaddr_storage saddr_in; /* the address of this host */ + struct sockaddr_storage error_addr; /* stores address of error replies */ unsigned long long time_waited; /* total time waited, in usecs */ unsigned int icmp_sent, icmp_recv, icmp_lost; /* counters */ unsigned char icmp_type, icmp_code; /* type and code from errors */ @@ -140,6 +142,18 @@ typedef struct icmp_ping_data { unsigned short ping_id; } icmp_ping_data; +typedef union ip_hdr { + struct ip ip; + struct ip6_hdr ip6; +} ip_hdr; + +typedef union icmp_packet { + void *buf; + struct icmp *icp; + struct icmp6_hdr *icp6; + u_short *cksum_in; +} icmp_packet; + /* the different modes of this program are as follows: * MODE_RTA: send all packets no matter what (mimic check_icmp and check_ping) * MODE_HOSTCHECK: Return immediately upon any sign of life @@ -190,8 +204,9 @@ static int get_threshold(char *str, threshold *th); static void run_checks(void); static void set_source_ip(char *); static int add_target(char *); -static int add_target_ip(char *, struct in_addr *); -static int handle_random_icmp(unsigned char *, struct sockaddr_in *); +static int add_target_ip(char *, struct sockaddr_storage *); +static int handle_random_icmp(unsigned char *, struct sockaddr_storage *); +static void parse_address(struct sockaddr_storage *, char *, int); static unsigned short icmp_checksum(unsigned short *, int); static void finish(int); static void crash(const char *, ...); @@ -300,7 +315,7 @@ get_icmp_error_msg(unsigned char icmp_type, unsigned char icmp_code) } static int -handle_random_icmp(unsigned char *packet, struct sockaddr_in *addr) +handle_random_icmp(unsigned char *packet, struct sockaddr_storage *addr) { struct icmp p, sent_icmp; struct rta_host *host = NULL; @@ -342,9 +357,11 @@ handle_random_icmp(unsigned char *packet, struct sockaddr_in *addr) /* it is indeed a response for us */ host = table[ntohs(sent_icmp.icmp_seq)/packets]; if(debug) { + char address[INET6_ADDRSTRLEN]; + parse_address(addr, address, sizeof(address)); printf("Received \"%s\" from %s for ICMP ECHO sent to %s.\n", - get_icmp_error_msg(p.icmp_type, p.icmp_code), - inet_ntoa(addr->sin_addr), host->name); + get_icmp_error_msg(p.icmp_type, p.icmp_code), + address, host->name); } icmp_lost++; @@ -364,11 +381,23 @@ handle_random_icmp(unsigned char *packet, struct sockaddr_in *addr) } host->icmp_type = p.icmp_type; host->icmp_code = p.icmp_code; - host->error_addr.s_addr = addr->sin_addr.s_addr; + host->error_addr = *addr; return 0; } +void parse_address(struct sockaddr_storage *addr, char *address, int size) +{ + switch (address_family) { + case AF_INET: + inet_ntop(address_family, &((struct sockaddr_in *)addr)->sin_addr, address, size); + break; + case AF_INET6: + inet_ntop(address_family, &((struct sockaddr_in6 *)addr)->sin6_addr, address, size); + break; + } +} + int main(int argc, char **argv) { @@ -381,6 +410,7 @@ main(int argc, char **argv) #ifdef SO_TIMESTAMP int on = 1; #endif + char * opts_str = "vhVw:c:n:p:t:H:s:i:b:I:l:m:64"; setlocale (LC_ALL, ""); bindtextdomain (PACKAGE, LOCALEDIR); @@ -390,33 +420,8 @@ main(int argc, char **argv) * that before pointer magic (esp. on network data) */ icmp_sockerrno = udp_sockerrno = tcp_sockerrno = sockets = 0; - if((icmp_sock = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP)) != -1) - sockets |= HAVE_ICMP; - else icmp_sockerrno = errno; - - /* if((udp_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) != -1) */ - /* sockets |= HAVE_UDP; */ - /* else udp_sockerrno = errno; */ - - /* if((tcp_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) != -1) */ - /* sockets |= HAVE_TCP; */ - /* else tcp_sockerrno = errno; */ - - /* now drop privileges (no effect if not setsuid or geteuid() == 0) */ - setuid(getuid()); - -#ifdef SO_TIMESTAMP - if(setsockopt(icmp_sock, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on))) - if(debug) printf("Warning: no SO_TIMESTAMP support\n"); -#endif // SO_TIMESTAMP - - /* POSIXLY_CORRECT might break things, so unset it (the portable way) */ - environ = NULL; - - /* use the pid to mark packets as ours */ - /* Some systems have 32-bit pid_t so mask off only 16 bits */ - pid = getpid() & 0xffff; - /* printf("pid = %u\n", pid); */ + address_family = -1; + int icmp_proto = IPPROTO_ICMP; /* get calling name the old-fashioned way for portability instead * of relying on the glibc-ism __progname */ @@ -456,20 +461,35 @@ main(int argc, char **argv) packets = 5; } - /* Parse extra opts if any */ - argv=np_extra_opts(&argc, argv, progname); - - /* support "--help" and "--version" */ - if(argc == 2) { - if(!strcmp(argv[1], "--help")) - strcpy(argv[1], "-h"); - if(!strcmp(argv[1], "--version")) - strcpy(argv[1], "-V"); + /* Parse protocol arguments first */ + for(i = 1; i < argc; i++) { + while((arg = getopt(argc, argv, opts_str)) != EOF) { + unsigned short size; + switch(arg) { + case '4': + if (address_family != -1) + crash("Multiple protocol versions not supported"); + address_family = AF_INET; + break; + case '6': +#ifdef USE_IPV6 + if (address_family != -1) + crash("Multiple protocol versions not supported"); + address_family = AF_INET6; +#else + usage (_("IPv6 support not available\n")); +#endif + break; + } + } } + /* Reset argument scanning */ + optind = 1; + /* parse the arguments */ for(i = 1; i < argc; i++) { - while((arg = getopt(argc, argv, "vhVw:c:n:p:t:H:s:i:b:I:l:m:")) != EOF) { + while((arg = getopt(argc, argv, opts_str)) != EOF) { unsigned short size; switch(arg) { case 'v': @@ -530,10 +550,30 @@ main(int argc, char **argv) case 'h': /* help */ print_help (); exit (STATE_UNKNOWN); + break; } } } + /* POSIXLY_CORRECT might break things, so unset it (the portable way) */ + environ = NULL; + + /* use the pid to mark packets as ours */ + /* Some systems have 32-bit pid_t so mask off only 16 bits */ + pid = getpid() & 0xffff; + /* printf("pid = %u\n", pid); */ + + /* Parse extra opts if any */ + argv=np_extra_opts(&argc, argv, progname); + + /* support "--help" and "--version" */ + if(argc == 2) { + if(!strcmp(argv[1], "--help")) + strcpy(argv[1], "-h"); + if(!strcmp(argv[1], "--version")) + strcpy(argv[1], "-V"); + } + argv = &argv[optind]; while(*argv) { add_target(*argv); @@ -545,6 +585,30 @@ main(int argc, char **argv) exit(3); } + // add_target might change address_family + switch ( address_family ){ + case AF_INET: icmp_proto = IPPROTO_ICMP; + break; + case AF_INET6: icmp_proto = IPPROTO_ICMPV6; + break; + default: crash("Address family not supported"); + } + if((icmp_sock = socket(address_family, SOCK_RAW, icmp_proto)) != -1) + sockets |= HAVE_ICMP; + else icmp_sockerrno = errno; + + +#ifdef SO_TIMESTAMP + if(setsockopt(icmp_sock, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on))) + if(debug) printf("Warning: no SO_TIMESTAMP support\n"); +#endif // SO_TIMESTAMP + + /* now drop privileges (no effect if not setsuid or geteuid() == 0) */ + if (setuid(getuid()) == -1) { + printf("ERROR: Failed to drop privileges\n"); + return 1; + } + if(!sockets) { if(icmp_sock == -1) { errno = icmp_sockerrno; @@ -633,7 +697,7 @@ main(int argc, char **argv) } host = list; - table = malloc(sizeof(struct rta_host **) * targets); + table = (struct rta_host**)malloc(sizeof(struct rta_host **) * targets); i = 0; while(host) { host->id = i*packets; @@ -697,9 +761,15 @@ run_checks() } } + /* response structure: + * IPv4: * ip header : 20 bytes * icmp header : 28 bytes + * IPv6: + * ip header : 40 bytes + * icmp header : 28 bytes + * both: * icmp echo reply : the rest */ static int @@ -707,16 +777,27 @@ wait_for_reply(int sock, u_int t) { int n, hlen; static unsigned char buf[4096]; - struct sockaddr_in resp_addr; - struct ip *ip; - struct icmp icp; + struct sockaddr_storage resp_addr; + union ip_hdr *ip; + union icmp_packet packet; struct rta_host *host; struct icmp_ping_data data; struct timeval wait_start, now; u_int tdiff, i, per_pkt_wait; + if (!(packet.buf = malloc(icmp_pkt_size))) { + crash("send_icmp_ping(): failed to malloc %d bytes for send buffer", + icmp_pkt_size); + return -1; /* might be reached if we're in debug mode */ + } + + memset(packet.buf, 0, icmp_pkt_size); + /* if we can't listen or don't have anything to listen to, just return */ - if(!t || !icmp_pkts_en_route) return 0; + if(!t || !icmp_pkts_en_route) { + free(packet.buf); + return 0; + } gettimeofday(&wait_start, &tz); @@ -735,7 +816,7 @@ wait_for_reply(int sock, u_int t) /* reap responses until we hit a timeout */ n = recvfrom_wto(sock, buf, sizeof(buf), - (struct sockaddr *)&resp_addr, &t, &now); + (struct sockaddr *)&resp_addr, &t, &now); if(!n) { if(debug > 1) { printf("recvfrom_wto() timed out during a %u usecs wait\n", @@ -745,12 +826,23 @@ wait_for_reply(int sock, u_int t) } if(n < 0) { if(debug) printf("recvfrom_wto() returned errors\n"); + free(packet.buf); return n; } - ip = (struct ip *)buf; - if(debug > 1) printf("received %u bytes from %s\n", - ntohs(ip->ip_len), inet_ntoa(resp_addr.sin_addr)); + // FIXME: with ipv6 we don't have an ip header here + if (address_family != AF_INET6) { + ip = (union ip_hdr *)buf; + + if(debug > 1) { + char address[INET6_ADDRSTRLEN]; + parse_address(&resp_addr, address, sizeof(address)); + printf("received %u bytes from %s\n", + address_family == AF_INET6 ? ntohs(ip->ip6.ip6_plen) + : ntohs(ip->ip.ip_len), + address); + } + } /* obsolete. alpha on tru64 provides the necessary defines, but isn't broken */ /* #if defined( __alpha__ ) && __STDC__ && !defined( __GLIBC__ ) */ @@ -759,12 +851,14 @@ wait_for_reply(int sock, u_int t) * off the bottom 4 bits */ /* hlen = (ip->ip_vhl & 0x0f) << 2; */ /* #else */ - hlen = ip->ip_hl << 2; + hlen = (address_family == AF_INET6) ? 0 : ip->ip.ip_hl << 2; /* #endif */ if(n < (hlen + ICMP_MINLEN)) { + char address[INET6_ADDRSTRLEN]; + parse_address(&resp_addr, address, sizeof(address)); crash("received packet too short for ICMP (%d bytes, expected %d) from %s\n", - n, hlen + icmp_pkt_size, inet_ntoa(resp_addr.sin_addr)); + n, hlen + icmp_pkt_size, address); } /* else if(debug) { */ /* printf("ip header size: %u, packet size: %u (expected %u, %u)\n", */ @@ -773,23 +867,39 @@ wait_for_reply(int sock, u_int t) /* } */ /* check the response */ - memcpy(&icp, buf + hlen, sizeof(icp)); - if(ntohs(icp.icmp_id) != pid || icp.icmp_type != ICMP_ECHOREPLY || - ntohs(icp.icmp_seq) >= targets*packets) { + memcpy(packet.buf, buf + hlen, icmp_pkt_size); +/* address_family == AF_INET6 ? sizeof(struct icmp6_hdr) + : sizeof(struct icmp));*/ + + if( (address_family == PF_INET && + (ntohs(packet.icp->icmp_id) != pid || packet.icp->icmp_type != ICMP_ECHOREPLY + || ntohs(packet.icp->icmp_seq) >= targets * packets)) + || (address_family == PF_INET6 && + (ntohs(packet.icp6->icmp6_id) != pid || packet.icp6->icmp6_type != ICMP6_ECHO_REPLY + || ntohs(packet.icp6->icmp6_seq) >= targets * packets))) { if(debug > 2) printf("not a proper ICMP_ECHOREPLY\n"); handle_random_icmp(buf + hlen, &resp_addr); continue; } /* this is indeed a valid response */ - memcpy(&data, icp.icmp_data, sizeof(data)); - if (debug > 2) - printf("ICMP echo-reply of len %lu, id %u, seq %u, cksum 0x%X\n", - (unsigned long)sizeof(data), ntohs(icp.icmp_id), - ntohs(icp.icmp_seq), icp.icmp_cksum); + if (address_family == PF_INET) { + memcpy(&data, packet.icp->icmp_data, sizeof(data)); + if (debug > 2) + printf("ICMP echo-reply of len %lu, id %u, seq %u, cksum 0x%X\n", + (unsigned long)sizeof(data), ntohs(packet.icp->icmp_id), + ntohs(packet.icp->icmp_seq), packet.icp->icmp_cksum); + host = table[ntohs(packet.icp->icmp_seq)/packets]; + } else { + memcpy(&data, &packet.icp6->icmp6_dataun.icmp6_un_data8[4], sizeof(data)); + if (debug > 2) + printf("ICMP echo-reply of len %lu, id %u, seq %u, cksum 0x%X\n", + (unsigned long)sizeof(data), ntohs(packet.icp6->icmp6_id), + ntohs(packet.icp6->icmp6_seq), packet.icp6->icmp6_cksum); + host = table[ntohs(packet.icp6->icmp6_seq)/packets]; + } - host = table[ntohs(icp.icmp_seq)/packets]; tdiff = get_timevaldiff(&data.stime, &now); host->time_waited += tdiff; @@ -801,22 +911,25 @@ wait_for_reply(int sock, u_int t) host->rtmin = tdiff; if(debug) { + char address[INET6_ADDRSTRLEN]; + parse_address(&resp_addr, address, sizeof(address)); printf("%0.3f ms rtt from %s, outgoing ttl: %u, incoming ttl: %u, max: %0.3f, min: %0.3f\n", - (float)tdiff / 1000, inet_ntoa(resp_addr.sin_addr), - ttl, ip->ip_ttl, (float)host->rtmax / 1000, (float)host->rtmin / 1000); + (float)tdiff / 1000, address, + ttl, ip->ip.ip_ttl, (float)host->rtmax / 1000, (float)host->rtmin / 1000); } /* if we're in hostcheck mode, exit with limited printouts */ if(mode == MODE_HOSTCHECK) { printf("OK - %s responds to ICMP. Packet %u, rta %0.3fms|" - "pkt=%u;;0;%u rta=%0.3f;%0.3f;%0.3f;;\n", - host->name, icmp_recv, (float)tdiff / 1000, - icmp_recv, packets, (float)tdiff / 1000, - (float)warn.rta / 1000, (float)crit.rta / 1000); + "pkt=%u;;0;%u rta=%0.3f;%0.3f;%0.3f;;\n", + host->name, icmp_recv, (float)tdiff / 1000, + icmp_recv, packets, (float)tdiff / 1000, + (float)warn.rta / 1000, (float)crit.rta / 1000); exit(STATE_OK); } } + free(packet.buf); return 0; } @@ -824,62 +937,81 @@ wait_for_reply(int sock, u_int t) static int send_icmp_ping(int sock, struct rta_host *host) { - static union { - void *buf; /* re-use so we prevent leaks */ - struct icmp *icp; - u_short *cksum_in; - } packet = { NULL }; long int len; struct icmp_ping_data data; struct msghdr hdr; struct iovec iov; struct timeval tv; - struct sockaddr *addr; + void *buf = NULL; if(sock == -1) { errno = 0; crash("Attempt to send on bogus socket"); return -1; } - addr = (struct sockaddr *)&host->saddr_in; - if(!packet.buf) { - if (!(packet.buf = malloc(icmp_pkt_size))) { + if(!buf) { + if (!(buf = malloc(icmp_pkt_size))) { crash("send_icmp_ping(): failed to malloc %d bytes for send buffer", icmp_pkt_size); return -1; /* might be reached if we're in debug mode */ } } - memset(packet.buf, 0, icmp_pkt_size); + memset(buf, 0, icmp_pkt_size); - if((gettimeofday(&tv, &tz)) == -1) return -1; + if((gettimeofday(&tv, &tz)) == -1) { + free(buf); + return -1; + } data.ping_id = 10; /* host->icmp.icmp_sent; */ memcpy(&data.stime, &tv, sizeof(tv)); - memcpy(&packet.icp->icmp_data, &data, sizeof(data)); - packet.icp->icmp_type = ICMP_ECHO; - packet.icp->icmp_code = 0; - packet.icp->icmp_cksum = 0; - packet.icp->icmp_id = htons(pid); - packet.icp->icmp_seq = htons(host->id++); - packet.icp->icmp_cksum = icmp_checksum(packet.cksum_in, icmp_pkt_size); - - if (debug > 2) - printf("Sending ICMP echo-request of len %lu, id %u, seq %u, cksum 0x%X to host %s\n", - (unsigned long)sizeof(data), ntohs(packet.icp->icmp_id), - ntohs(packet.icp->icmp_seq), packet.icp->icmp_cksum, - host->name); + + if (address_family == AF_INET) { + struct icmp *icp = (struct icmp*)buf; + + memcpy(&icp->icmp_data, &data, sizeof(data)); + + icp->icmp_type = ICMP_ECHO; + icp->icmp_code = 0; + icp->icmp_cksum = 0; + icp->icmp_id = htons(pid); + icp->icmp_seq = htons(host->id++); + icp->icmp_cksum = icmp_checksum((unsigned short*)buf, icmp_pkt_size); + + if (debug > 2) + printf("Sending ICMP echo-request of len %lu, id %u, seq %u, cksum 0x%X to host %s\n", + (unsigned long)sizeof(data), ntohs(icp->icmp_id), ntohs(icp->icmp_seq), icp->icmp_cksum, host->name); + } + else { + struct icmp6_hdr *icp6 = (struct icmp6_hdr*)buf; + memcpy(&icp6->icmp6_dataun.icmp6_un_data8[4], &data, sizeof(data)); + icp6->icmp6_type = ICMP6_ECHO_REQUEST; + icp6->icmp6_code = 0; + icp6->icmp6_cksum = 0; + icp6->icmp6_id = htons(pid); + icp6->icmp6_seq = htons(host->id++); + // let checksum be calculated automatically + + if (debug > 2) { + printf("Sending ICMP echo-request of len %lu, id %u, seq %u, cksum 0x%X to host %s\n", + (unsigned long)sizeof(data), ntohs(icp6->icmp6_id), + ntohs(icp6->icmp6_seq), icp6->icmp6_cksum, host->name); + } + } memset(&iov, 0, sizeof(iov)); - iov.iov_base = packet.buf; + iov.iov_base = buf; iov.iov_len = icmp_pkt_size; memset(&hdr, 0, sizeof(hdr)); - hdr.msg_name = addr; - hdr.msg_namelen = sizeof(struct sockaddr); + hdr.msg_name = (struct sockaddr *)&host->saddr_in; + hdr.msg_namelen = sizeof(struct sockaddr_storage); hdr.msg_iov = &iov; hdr.msg_iovlen = 1; + errno = 0; + /* MSG_CONFIRM is a linux thing and only available on linux kernels >= 2.3.15, see send(2) */ #ifdef MSG_CONFIRM len = sendmsg(sock, &hdr, MSG_CONFIRM); @@ -887,9 +1019,15 @@ send_icmp_ping(int sock, struct rta_host *host) len = sendmsg(sock, &hdr, 0); #endif + free(buf); + if(len < 0 || (unsigned int)len != icmp_pkt_size) { - if(debug) printf("Failed to send ping to %s\n", - inet_ntoa(host->saddr_in.sin_addr)); + if(debug) { + char address[INET6_ADDRSTRLEN]; + parse_address((struct sockaddr_storage *)&host->saddr_in, address, sizeof(address)); + printf("Failed to send ping to %s: %s\n", address, strerror(errno)); + } + errno = 0; return -1; } @@ -934,7 +1072,7 @@ recvfrom_wto(int sock, void *buf, unsigned int len, struct sockaddr *saddr, if(!n) return 0; /* timeout */ - slen = sizeof(struct sockaddr); + slen = sizeof(struct sockaddr_storage); memset(&iov, 0, sizeof(iov)); iov.iov_base = buf; @@ -958,6 +1096,7 @@ recvfrom_wto(int sock, void *buf, unsigned int len, struct sockaddr *saddr, break ; } } + if (!chdr) #endif // SO_TIMESTAMP gettimeofday(tv, &tz); @@ -991,6 +1130,7 @@ finish(int sig) /* iterate thrice to calculate values, give output, and print perfparse */ host = list; + while(host) { if(!host->icmp_recv) { /* rta 0 is ofcourse not entirely correct, but will still show up @@ -1039,10 +1179,12 @@ finish(int sig) if(!host->icmp_recv) { status = STATE_CRITICAL; if(host->flags & FLAG_LOST_CAUSE) { + char address[INET6_ADDRSTRLEN]; + parse_address(&host->error_addr, address, sizeof(address)); printf("%s: %s @ %s. rta nan, lost %d%%", host->name, get_icmp_error_msg(host->icmp_type, host->icmp_code), - inet_ntoa(host->error_addr), + address, 100); } else { /* not marked as lost cause, so we have no flags for it */ @@ -1104,7 +1246,6 @@ get_timevaldiff(struct timeval *early, struct timeval *later) { return 0; } - ret = (later->tv_sec - early->tv_sec) * 1000000; ret += later->tv_usec - early->tv_usec; @@ -1112,18 +1253,35 @@ get_timevaldiff(struct timeval *early, struct timeval *later) } static int -add_target_ip(char *arg, struct in_addr *in) +add_target_ip(char *arg, struct sockaddr_storage *in) { struct rta_host *host; + struct sockaddr_in *sin, *host_sin; + struct sockaddr_in6 *sin6, *host_sin6; + + if (address_family == AF_INET) + sin = (struct sockaddr_in *)in; + else + sin6 = (struct sockaddr_in6 *)in; - /* disregard obviously stupid addresses */ - if(in->s_addr == INADDR_NONE || in->s_addr == INADDR_ANY) + + + /* disregard obviously stupid addresses + * (I didn't find an ipv6 equivalent to INADDR_NONE) */ + if (((address_family == AF_INET && (sin->sin_addr.s_addr == INADDR_NONE + || sin->sin_addr.s_addr == INADDR_ANY))) + || (address_family == AF_INET6 && (sin6->sin6_addr.s6_addr == in6addr_any.s6_addr))) { return -1; + } /* no point in adding two identical IP's, so don't. ;) */ host = list; while(host) { - if(host->saddr_in.sin_addr.s_addr == in->s_addr) { + host_sin = (struct sockaddr_in *)&host->saddr_in; + host_sin6 = (struct sockaddr_in6 *)&host->saddr_in; + + if( (address_family == AF_INET && host_sin->sin_addr.s_addr == sin->sin_addr.s_addr) + || (address_family == AF_INET6 && host_sin6->sin6_addr.s6_addr == sin6->sin6_addr.s6_addr)) { if(debug) printf("Identical IP already exists. Not adding %s\n", arg); return -1; } @@ -1131,19 +1289,29 @@ add_target_ip(char *arg, struct in_addr *in) } /* add the fresh ip */ - host = malloc(sizeof(struct rta_host)); + host = (struct rta_host*)malloc(sizeof(struct rta_host)); if(!host) { + char straddr[INET6_ADDRSTRLEN]; + parse_address((struct sockaddr_storage*)&in, straddr, sizeof(straddr)); crash("add_target_ip(%s, %s): malloc(%d) failed", - arg, inet_ntoa(*in), sizeof(struct rta_host)); + arg, straddr, sizeof(struct rta_host)); } memset(host, 0, sizeof(struct rta_host)); /* set the values. use calling name for output */ host->name = strdup(arg); - /* fill out the sockaddr_in struct */ - host->saddr_in.sin_family = AF_INET; - host->saddr_in.sin_addr.s_addr = in->s_addr; + /* fill out the sockaddr_storage struct */ + if(address_family == AF_INET) { + host_sin = (struct sockaddr_in *)&host->saddr_in; + host_sin->sin_family = AF_INET; + host_sin->sin_addr.s_addr = sin->sin_addr.s_addr; + } + else { + host_sin6 = (struct sockaddr_in6 *)&host->saddr_in; + host_sin6->sin6_family = AF_INET6; + memcpy(host_sin6->sin6_addr.s6_addr, sin6->sin6_addr.s6_addr, sizeof host_sin6->sin6_addr.s6_addr); + } host->rtmin = DBL_MAX; @@ -1160,31 +1328,67 @@ add_target_ip(char *arg, struct in_addr *in) static int add_target(char *arg) { - int i; - struct hostent *he; - struct in_addr *in, ip; + int error, result; + struct sockaddr_storage ip; + struct addrinfo hints, *res, *p; + struct sockaddr_in *sin; + struct sockaddr_in6 *sin6; + + switch (address_family) { + case -1: + /* -4 and -6 are not specified on cmdline */ + address_family = AF_INET; + sin = (struct sockaddr_in *)&ip; + result = inet_pton(address_family, arg, &sin->sin_addr); +#ifdef USE_IPV6 + if( result != 1 ){ + address_family = AF_INET6; + sin6 = (struct sockaddr_in6 *)&ip; + result = inet_pton(address_family, arg, &sin6->sin6_addr); + } +#endif + /* If we don't find any valid addresses, we still don't know the address_family */ + if ( result != 1) { + address_family = -1; + } + break; + case AF_INET: + sin = (struct sockaddr_in *)&ip; + result = inet_pton(address_family, arg, &sin->sin_addr); + break; + case AF_INET6: + sin6 = (struct sockaddr_in6 *)&ip; + result = inet_pton(address_family, arg, &sin6->sin6_addr); + break; + default: crash("Address family not supported"); + } /* don't resolve if we don't have to */ - if((ip.s_addr = inet_addr(arg)) != INADDR_NONE) { + if(result == 1) { /* don't add all ip's if we were given a specific one */ return add_target_ip(arg, &ip); - /* he = gethostbyaddr((char *)in, sizeof(struct in_addr), AF_INET); */ - /* if(!he) return add_target_ip(arg, in); */ } else { errno = 0; - he = gethostbyname(arg); - if(!he) { + memset(&hints, 0, sizeof(hints)); + if (address_family == -1) { + hints.ai_family = AF_UNSPEC; + } else { + hints.ai_family = address_family == AF_INET ? PF_INET : PF_INET6; + } + hints.ai_socktype = SOCK_RAW; + if((error = getaddrinfo(arg, NULL, &hints, &res)) != 0) { errno = 0; - crash("Failed to resolve %s", arg); + crash("Failed to resolve %s: %s", arg, gai_strerror(error)); return -1; } + address_family = res->ai_family; } /* possibly add all the IP's as targets */ - for(i = 0; he->h_addr_list[i]; i++) { - in = (struct in_addr *)he->h_addr_list[i]; - add_target_ip(arg, in); + for(p = res; p != NULL; p = p->ai_next) { + memcpy(&ip, p->ai_addr, p->ai_addrlen); + add_target_ip(arg, &ip); /* this is silly, but it works */ if(mode == MODE_HOSTCHECK || mode == MODE_ALL) { @@ -1193,6 +1397,7 @@ add_target(char *arg) } break; } + freeaddrinfo(res); return 0; } @@ -1203,7 +1408,7 @@ set_source_ip(char *arg) struct sockaddr_in src; memset(&src, 0, sizeof(src)); - src.sin_family = AF_INET; + src.sin_family = address_family; if((src.sin_addr.s_addr = inet_addr(arg)) == INADDR_NONE) src.sin_addr.s_addr = get_ip_address(arg); if(bind(icmp_sock, (struct sockaddr *)&src, sizeof(src)) == -1) @@ -1311,12 +1516,12 @@ get_threshold(char *str, threshold *th) unsigned short icmp_checksum(unsigned short *p, int n) { - register unsigned short cksum; - register long sum = 0; + unsigned short cksum; + long sum = 0; - while(n > 1) { + while(n > 2) { sum += *p++; - n -= 2; + n -= sizeof(unsigned short); } /* mop up the occasional odd byte */ @@ -1347,6 +1552,8 @@ print_help(void) printf (" %s\n", "-H"); printf (" %s\n", _("specify a target")); + printf (" %s\n", "[-4|-6]"); + printf (" %s\n", _("Use IPv4 (default) or IPv6 to communicate with the targets")); printf (" %s\n", "-w"); printf (" %s", _("warning threshold (currently ")); printf ("%0.3fms,%u%%)\n", (float)warn.rta / 1000, warn.pl); diff --git a/plugins/check_dbi.c b/plugins/check_dbi.c index 826eb8d9..ced13d05 100644 --- a/plugins/check_dbi.c +++ b/plugins/check_dbi.c @@ -35,6 +35,7 @@ const char *email = "devel@monitoring-plugins.org"; #include "common.h" #include "utils.h" +#include "utils_cmd.h" #include "netutils.h" diff --git a/plugins/check_dns.c b/plugins/check_dns.c index f2061636..d4d0b885 100644 --- a/plugins/check_dns.c +++ b/plugins/check_dns.c @@ -56,6 +56,7 @@ char **expected_address = NULL; int expected_address_cnt = 0; int expect_authority = FALSE; +int all_match = FALSE; thresholds *time_thresholds = NULL; static int @@ -168,8 +169,8 @@ main (int argc, char **argv) temp_buffer++; /* Strip leading spaces */ - for (; *temp_buffer != '\0' && *temp_buffer == ' '; temp_buffer++) - /* NOOP */; + while (*temp_buffer == ' ') + temp_buffer++; strip(temp_buffer); if (temp_buffer==NULL || strlen(temp_buffer)==0) { @@ -228,16 +229,27 @@ main (int argc, char **argv) if (result == STATE_OK && expected_address_cnt > 0) { result = STATE_CRITICAL; temp_buffer = ""; + unsigned long expect_match = (1 << expected_address_cnt) - 1; + unsigned long addr_match = (1 << n_addresses) - 1; for (i=0; i<expected_address_cnt; i++) { + int j; /* check if we get a match on 'raw' ip or cidr */ - if ( strcmp(address, expected_address[i]) == 0 - || ip_match_cidr(address, expected_address[i]) ) - result = STATE_OK; + for (j=0; j<n_addresses; j++) { + if ( strcmp(addresses[j], expected_address[i]) == 0 + || ip_match_cidr(addresses[j], expected_address[i]) ) { + result = STATE_OK; + addr_match &= ~(1 << j); + expect_match &= ~(1 << i); + } + } /* prepare an error string */ xasprintf(&temp_buffer, "%s%s; ", temp_buffer, expected_address[i]); } + /* check if expected_address must cover all in addresses and none may be missing */ + if (all_match && (expect_match != 0 || addr_match != 0)) + result = STATE_CRITICAL; if (result == STATE_CRITICAL) { /* Strip off last semicolon... */ temp_buffer[strlen(temp_buffer)-2] = '\0'; @@ -401,6 +413,7 @@ process_arguments (int argc, char **argv) {"reverse-server", required_argument, 0, 'r'}, {"expected-address", required_argument, 0, 'a'}, {"expect-authority", no_argument, 0, 'A'}, + {"all", no_argument, 0, 'L'}, {"warning", required_argument, 0, 'w'}, {"critical", required_argument, 0, 'c'}, {0, 0, 0, 0} @@ -414,7 +427,7 @@ process_arguments (int argc, char **argv) strcpy (argv[c], "-t"); while (1) { - c = getopt_long (argc, argv, "hVvAt:H:s:r:a:w:c:", long_opts, &opt_index); + c = getopt_long (argc, argv, "hVvALt:H:s:r:a:w:c:", long_opts, &opt_index); if (c == -1 || c == EOF) break; @@ -462,6 +475,9 @@ process_arguments (int argc, char **argv) case 'A': /* expect authority */ expect_authority = TRUE; break; + case 'L': /* all must match */ + all_match = TRUE; + break; case 'w': warning = optarg; break; @@ -530,14 +546,16 @@ print_help (void) printf (" -a, --expected-address=IP-ADDRESS|CIDR|HOST\n"); printf (" %s\n", _("Optional IP-ADDRESS/CIDR you expect the DNS server to return. HOST must end")); printf (" %s\n", _("with a dot (.). This option can be repeated multiple times (Returns OK if any")); - printf (" %s\n", _("value match). If multiple addresses are returned at once, you have to match")); - printf (" %s\n", _("the whole string of addresses separated with commas (sorted alphabetically).")); + printf (" %s\n", _("value matches).")); printf (" -A, --expect-authority\n"); printf (" %s\n", _("Optionally expect the DNS server to be authoritative for the lookup")); printf (" -w, --warning=seconds\n"); printf (" %s\n", _("Return warning if elapsed time exceeds value. Default off")); printf (" -c, --critical=seconds\n"); printf (" %s\n", _("Return critical if elapsed time exceeds value. Default off")); + printf (" -L, --all\n"); + printf (" %s\n", _("Return critical if the list of expected addresses does not match all addresses")); + printf (" %s\n", _("returned. Default off")); printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); @@ -549,5 +567,5 @@ void print_usage (void) { printf ("%s\n", _("Usage:")); - printf ("%s -H host [-s server] [-a expected-address] [-A] [-t timeout] [-w warn] [-c crit]\n", progname); + printf ("%s -H host [-s server] [-a expected-address] [-A] [-t timeout] [-w warn] [-c crit] [-L]\n", progname); } diff --git a/plugins/check_hpjd.c b/plugins/check_hpjd.c index f159f5a2..65465567 100644 --- a/plugins/check_hpjd.c +++ b/plugins/check_hpjd.c @@ -67,6 +67,7 @@ void print_usage (void); char *community = NULL; char *address = NULL; char *port = NULL; +int check_paper_out = 1; int main (int argc, char **argv) @@ -240,7 +241,8 @@ main (int argc, char **argv) strcpy (errmsg, _("Paper Jam")); } else if (paper_out) { - result = STATE_WARNING; + if (check_paper_out) + result = STATE_WARNING; strcpy (errmsg, _("Out of Paper")); } else if (line_status == OFFLINE) { @@ -325,7 +327,7 @@ process_arguments (int argc, char **argv) while (1) { - c = getopt_long (argc, argv, "+hVH:C:p:", longopts, &option); + c = getopt_long (argc, argv, "+hVH:C:p:D", longopts, &option); if (c == -1 || c == EOF || c == 1) break; @@ -347,6 +349,8 @@ process_arguments (int argc, char **argv) usage2 (_("Port must be a positive short integer"), optarg); else port = atoi(optarg); + case 'D': /* disable paper out check*/ + check_paper_out = 0; break; case 'V': /* version */ print_revision (progname, NP_VERSION); @@ -420,6 +424,8 @@ print_help (void) printf (" %s", _("Specify the port to check ")); printf (_("(default=%s)"), DEFAULT_PORT); printf ("\n"); + printf (" %s\n", "-D"); + printf (" %s", _("Disable paper check ")); printf (UT_SUPPORT); } @@ -430,5 +436,5 @@ void print_usage (void) { printf ("%s\n", _("Usage:")); - printf ("%s -H host [-C community] [-p port]\n", progname); + printf ("%s -H host [-C community] [-p port] [-D]\n", progname); } diff --git a/plugins/check_http.c b/plugins/check_http.c index 856e1e90..de59a068 100644 --- a/plugins/check_http.c +++ b/plugins/check_http.c @@ -1155,6 +1155,8 @@ check_http (void) xasprintf (&msg, _("Invalid HTTP response received from host on port %d: %s\n"), server_port, status_line); + if (show_body) + xasprintf (&msg, _("%s\n%s"), msg, page); die (STATE_CRITICAL, "HTTP CRITICAL - %s", msg); } diff --git a/plugins/check_pgsql.c b/plugins/check_pgsql.c index 5cd47093..11ce6916 100644 --- a/plugins/check_pgsql.c +++ b/plugins/check_pgsql.c @@ -34,6 +34,7 @@ const char *email = "devel@monitoring-plugins.org"; #include "common.h" #include "utils.h" +#include "utils_cmd.h" #include "netutils.h" #include <libpq-fe.h> diff --git a/plugins/check_smtp.c b/plugins/check_smtp.c index 0fcf4c68..d37c57c8 100644 --- a/plugins/check_smtp.c +++ b/plugins/check_smtp.c @@ -293,6 +293,7 @@ main (int argc, char **argv) printf("%s", buffer); } + n = 0; while (n < ncommands) { xasprintf (&cmd_str, "%s%s", commands[n], "\r\n"); my_send(cmd_str, strlen(cmd_str)); diff --git a/plugins/common.h b/plugins/common.h index 6bf4fca4..0f08e2f6 100644 --- a/plugins/common.h +++ b/plugins/common.h @@ -225,4 +225,18 @@ enum { # define __attribute__(x) /* do nothing */ #endif +/* Try sysconf(_SC_OPEN_MAX) first, as it can be higher than OPEN_MAX. + * If that fails and the macro isn't defined, we fall back to an educated + * guess. There's no guarantee that our guess is adequate and the program + * will die with SIGSEGV if it isn't and the upper boundary is breached. */ +#define DEFAULT_MAXFD 256 /* fallback value if no max open files value is set */ +#define MAXFD_LIMIT 8192 /* upper limit of open files */ +#ifdef _SC_OPEN_MAX +static long maxfd = 0; +#elif defined(OPEN_MAX) +# define maxfd OPEN_MAX +#else /* sysconf macro unavailable, so guess (may be wildly inaccurate) */ +# define maxfd DEFAULT_MAXFD +#endif + #endif /* _COMMON_H_ */ diff --git a/plugins/popen.c b/plugins/popen.c index 592263fd..116d168d 100644 --- a/plugins/popen.c +++ b/plugins/popen.c @@ -78,7 +78,6 @@ RETSIGTYPE popen_timeout_alarm_handler (int); #define min(a,b) ((a) < (b) ? (a) : (b)) #define max(a,b) ((a) > (b) ? (a) : (b)) -int open_max (void); /* {Prog openmax} */ static void err_sys (const char *, ...) __attribute__((noreturn,format(printf, 1, 2))); char *rtrim (char *, const char *); @@ -86,7 +85,6 @@ char *pname = NULL; /* caller can set this from argv[0] */ /*int *childerr = NULL;*//* ptr to array allocated at run-time */ /*extern pid_t *childpid = NULL; *//* ptr to array allocated at run-time */ -static int maxfd; /* from our open_max(), {Prog openmax} */ #ifdef REDHAT_SPOPEN_ERROR static volatile int childtermd = 0; @@ -187,13 +185,11 @@ spopen (const char *cmdstring) argv[i] = NULL; if (childpid == NULL) { /* first time through */ - maxfd = open_max (); /* allocate zeroed out array for child pids */ if ((childpid = calloc ((size_t)maxfd, sizeof (pid_t))) == NULL) return (NULL); } if (child_stderr_array == NULL) { /* first time through */ - maxfd = open_max (); /* allocate zeroed out array for child pids */ if ((child_stderr_array = calloc ((size_t)maxfd, sizeof (int))) == NULL) return (NULL); } @@ -273,15 +269,6 @@ spclose (FILE * fp) return (1); } -#ifdef OPEN_MAX -static int openmax = OPEN_MAX; -#else -static int openmax = 0; -#endif - -#define OPEN_MAX_GUESS 256 /* if OPEN_MAX is indeterminate */ - /* no guarantee this is adequate */ - #ifdef REDHAT_SPOPEN_ERROR RETSIGTYPE popen_sigchld_handler (int signo) @@ -311,22 +298,6 @@ popen_timeout_alarm_handler (int signo) } -int -open_max (void) -{ - if (openmax == 0) { /* first time through */ - errno = 0; - if ((openmax = sysconf (_SC_OPEN_MAX)) < 0) { - if (errno == 0) - openmax = OPEN_MAX_GUESS; /* it's indeterminate */ - else - err_sys (_("sysconf error for _SC_OPEN_MAX")); - } - } - return (openmax); -} - - /* Fatal error related to a system call. * Print a message and die. */ diff --git a/plugins/runcmd.c b/plugins/runcmd.c index 1a7c904f..c3828678 100644 --- a/plugins/runcmd.c +++ b/plugins/runcmd.c @@ -67,19 +67,6 @@ * occur in any number of threads simultaneously. */ static pid_t *np_pids = NULL; -/* Try sysconf(_SC_OPEN_MAX) first, as it can be higher than OPEN_MAX. - * If that fails and the macro isn't defined, we fall back to an educated - * guess. There's no guarantee that our guess is adequate and the program - * will die with SIGSEGV if it isn't and the upper boundary is breached. */ -#ifdef _SC_OPEN_MAX -static long maxfd = 0; -#elif defined(OPEN_MAX) -# define maxfd OPEN_MAX -#else /* sysconf macro unavailable, so guess (may be wildly inaccurate) */ -# define maxfd 256 -#endif - - /** prototypes **/ static int np_runcmd_open(const char *, int *, int *) __attribute__((__nonnull__(1, 2, 3))); diff --git a/plugins/t/NPTest.cache.travis b/plugins/t/NPTest.cache.travis index 6ee45053..9b9f8059 100644 --- a/plugins/t/NPTest.cache.travis +++ b/plugins/t/NPTest.cache.travis @@ -50,5 +50,5 @@ 'NP_SNMP_USER' => '', 'NP_SSH_CONFIGFILE' => '~/.ssh/config', 'NP_SSH_HOST' => 'localhost', - 'NP_SSH_IDENTITY' => '~/.ssh/id_dsa' + 'NP_SSH_IDENTITY' => '~/.ssh/id_rsa' } diff --git a/plugins/tests/certs/server-cert.pem b/plugins/tests/certs/server-cert.pem index 549e4f7e..b84b91d2 100644 --- a/plugins/tests/certs/server-cert.pem +++ b/plugins/tests/certs/server-cert.pem @@ -1,21 +1,24 @@ -----BEGIN CERTIFICATE----- -MIIDYzCCAsygAwIBAgIJAL8LkpNwzYdxMA0GCSqGSIb3DQEBBAUAMH8xCzAJBgNV -BAYTAlVLMRMwEQYDVQQIEwpEZXJieXNoaXJlMQ8wDQYDVQQHEwZCZWxwZXIxFzAV -BgNVBAoTDk5hZ2lvcyBQbHVnaW5zMREwDwYDVQQDEwhUb24gVm9vbjEeMBwGCSqG -SIb3DQEJARYPdG9udm9vbkBtYWMuY29tMB4XDTA5MDMwNTIxNDEyOFoXDTE5MDMw -MzIxNDEyOFowfzELMAkGA1UEBhMCVUsxEzARBgNVBAgTCkRlcmJ5c2hpcmUxDzAN -BgNVBAcTBkJlbHBlcjEXMBUGA1UEChMOTmFnaW9zIFBsdWdpbnMxETAPBgNVBAMT -CFRvbiBWb29uMR4wHAYJKoZIhvcNAQkBFg90b252b29uQG1hYy5jb20wgZ8wDQYJ -KoZIhvcNAQEBBQADgY0AMIGJAoGBAKcWMBtNtfY8vZXk0SN6/EYTVN/LOvaOSegy -oVdLoGwuwjagk+XmCzvCqHZRp8lnCLay7AO8AQI7TSN02ihCcSrgGA9OT+HciIJ1 -l5/kEYUAuA1PR6YKK/T713zUAlMzy2tsugx5+xSsSEwsXkmne52jJiG/wuE5CLT0 -9pF8HQqHAgMBAAGjgeYwgeMwHQYDVR0OBBYEFGioSPQ/rdE19+zaeY2YvHTXlUDI -MIGzBgNVHSMEgaswgaiAFGioSPQ/rdE19+zaeY2YvHTXlUDIoYGEpIGBMH8xCzAJ -BgNVBAYTAlVLMRMwEQYDVQQIEwpEZXJieXNoaXJlMQ8wDQYDVQQHEwZCZWxwZXIx -FzAVBgNVBAoTDk5hZ2lvcyBQbHVnaW5zMREwDwYDVQQDEwhUb24gVm9vbjEeMBwG -CSqGSIb3DQEJARYPdG9udm9vbkBtYWMuY29tggkAvwuSk3DNh3EwDAYDVR0TBAUw -AwEB/zANBgkqhkiG9w0BAQQFAAOBgQCdqasaIO6JiV5ONFG6Tr1++85UfEdZKMUX -N2NHiNNUunolIZEYR+dW99ezKmHlDiQ/tMgoLVYpl2Ubho2pAkLGQR+W0ZASgWQ1 -NjfV27Rv0y6lYQMTA0lVAU93L1x9reo3FMedmL5+H+lIEpLCxEPtAJNISrJOneZB -W5jDadwkoQ== +MIIEBjCCAu6gAwIBAgIJANbQ5QQrKhUGMA0GCSqGSIb3DQEBCwUAMIGXMQswCQYD +VQQGEwJERTEQMA4GA1UECAwHQmF2YXJpYTEPMA0GA1UEBwwGTXVuaWNoMRswGQYD +VQQKDBJNb25pdG9yaW5nIFBsdWdpbnMxGzAZBgNVBAMMEk1vbml0b3JpbmcgUGx1 +Z2luczErMCkGCSqGSIb3DQEJARYcZGV2ZWxAbW9uaXRvcmluZy1wbHVnaW5zLm9y +ZzAeFw0xOTAyMTkxNTMxNDRaFw0yOTAyMTYxNTMxNDRaMIGXMQswCQYDVQQGEwJE +RTEQMA4GA1UECAwHQmF2YXJpYTEPMA0GA1UEBwwGTXVuaWNoMRswGQYDVQQKDBJN +b25pdG9yaW5nIFBsdWdpbnMxGzAZBgNVBAMMEk1vbml0b3JpbmcgUGx1Z2luczEr +MCkGCSqGSIb3DQEJARYcZGV2ZWxAbW9uaXRvcmluZy1wbHVnaW5zLm9yZzCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKgV2yp8pQvJuN+aJGdAe6Hd0tja +uteCPcNIcM92WLOF69TLTSYon1XDon4tHTh4Z5d4lD8bfsGzFVBmDSgWidhAUf+v +EqEXwbp293ej/Frc0pXCvmrz6kI1tWrLtQhL/VdbxFYxhV7JjKb+PY3SxGFpSLPe +PQ/5SwVndv7rZIwcjseL22K5Uy2TIrkgzzm2pRs/IvoxRybYr/+LGoHyrtJC6AO8 +ylp8A/etL0gwtUvRnrnZeTQ2pA1uZ5QN3anTL8JP/ZRZYNegIkaawqMtTKbhM6pi +u3/4a3Uppvt0y7vmGfQlYejxCpICnMrvHMpw8L58zv/98AbCGjDU3UwCt6MCAwEA +AaNTMFEwHQYDVR0OBBYEFG/UH6nGYPlVcM75UXzXBF5GZyrcMB8GA1UdIwQYMBaA +FG/UH6nGYPlVcM75UXzXBF5GZyrcMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcN +AQELBQADggEBAGwitJPOnlIKLndNf+iCLMIs0dxsl8kAaejFcjoT0n4ja7Y6Zrqz +VSIidzz9vQWvy24xKJpAOdj/iLRHCUOG+Pf5fA6+/FiuqXr6gE2/lm0eC58BNONr +E5OzjQ/VoQ8RX4hDntgu6FYbaVa/vhwn16igt9qmdNGGZXf2/+DM3JADwyaA4EK8 +vm7KdofX9zkxXecHPNvf3jiVLPiDDt6tkGpHPEsyP/yc+RUdltUeZvHfliV0cCuC +jJX+Fm9ysjSpHIFFr+jUMuMHibWoOD8iy3eYxfCDoWsH488pCbj8MNuAq6vd6DBk +bOZxDz43vjWuYMkwXJTxJQh7Pne6kK0vE1g= -----END CERTIFICATE----- diff --git a/plugins/tests/certs/server-key.pem b/plugins/tests/certs/server-key.pem index eacaeaa3..11947555 100644 --- a/plugins/tests/certs/server-key.pem +++ b/plugins/tests/certs/server-key.pem @@ -1,15 +1,28 @@ ------BEGIN RSA PRIVATE KEY----- -MIICWwIBAAKBgQCnFjAbTbX2PL2V5NEjevxGE1Tfyzr2jknoMqFXS6BsLsI2oJPl -5gs7wqh2UafJZwi2suwDvAECO00jdNooQnEq4BgPTk/h3IiCdZef5BGFALgNT0em -Civ0+9d81AJTM8trbLoMefsUrEhMLF5Jp3udoyYhv8LhOQi09PaRfB0KhwIDAQAB -AoGAfpxclcP8N3vteXErXURrd7pcXT0GECDgNjhvc9PV20RPXM+vYs1AA+fMeeQE -TaRqwO6x016aMRO4rz5ztYArecTBznkds1k59pkN/Ne/nsueU4tvGK8MNyS2o986 -Voohqkaq4Lcy1bcHJb9su1ELjegEr1R76Mz452Hsy+uTbAECQQDcg/tZWKVeh5CQ -dOEB3YWHwfn0NDgfPm/X2i2kAZ7n7URaUy/ffdlfsrr1mBtHCfedLoOxmmlNfEpM -hXAAurSHAkEAwfk7fEb0iN0Sj9gTozO7c6Ky10KwePZyjVzqSQIiJq3NX8BEaIeb -51TXxE5VxaLjjMLRkA0hWTYXClgERFZ6AQJAN7ChPqwzf08PRFwwIw911JY5cOHr -NoDHMCUql5vNLNdwBruxgGjBB/kUXEfgw60RusFvgt/zLh1wiii844JDawJAGQBF -sYP3urg7zzx7c3qUe5gJ0wLuefjR1PSX4ecbfb7DDMdcSdjIuG1QDiZGmd2f1KG7 -nwSCOtxk5dloW2KGAQJAQh/iBn0QhfKLFAP5eZBVk8E8XlZuw+S2DLy5SnBlIiYJ -GB5I2OClgtudXMv1labFrcST8O9eFrtsrhU1iUGUOw== ------END RSA PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCoFdsqfKULybjf +miRnQHuh3dLY2rrXgj3DSHDPdlizhevUy00mKJ9Vw6J+LR04eGeXeJQ/G37BsxVQ +Zg0oFonYQFH/rxKhF8G6dvd3o/xa3NKVwr5q8+pCNbVqy7UIS/1XW8RWMYVeyYym +/j2N0sRhaUiz3j0P+UsFZ3b+62SMHI7Hi9tiuVMtkyK5IM85tqUbPyL6MUcm2K// +ixqB8q7SQugDvMpafAP3rS9IMLVL0Z652Xk0NqQNbmeUDd2p0y/CT/2UWWDXoCJG +msKjLUym4TOqYrt/+Gt1Kab7dMu75hn0JWHo8QqSApzK7xzKcPC+fM7//fAGwhow +1N1MArejAgMBAAECggEANuvdTwanTzC8jaNqHaq+OuemS2E9B8nwsGxtH/zFgvNR +WZiMPtmrJnTkFWJcV+VPw/iMSAqN4nDHmBugVOb4Z4asxGTKK4T9shXJSnh0rqPU +00ZsvbmxY6z0+E5TesCJqQ+9GYTY1V357V7JchvaOxIRxWPqg9urHbru8OCtW/I5 +Fh5HPUZlgCvlMpjlhyjydIf/oXyVA3RNsXlwe8+2cKuGIrjEzm2j9o3VF0sctTX0 +ItP8A9qDmDQN7GIWX0MW6gncojpS1omC2wcFsdjj/xfPyiDal1X4aq/2YqG8351c +YlM/+6Va0u9WWE/i64gASTAVqpMV4Yg8y0gGycuA0QKBgQDbgI2QeLd3FvMcURiU +l3w9qJgw/Jp3jaNC/9LkVGGz4f4lKKB67lPZvI4noMK8GqO/LcXgqP/RY1oJojoA +/6JKVvzYGASZ7VgMoG9bk1AneP1PGdibuTUEwimGlcObxnDFIC/yjwPFu3jIdqdS +zZi1RZzyqAogN5y3SBEypSmn9wKBgQDECKsqqlcizmCl8v5aVk875AzGN+DOHZqx +bkmztlnLO/2e2Fmk3G5Vvnui0FYisf8Eq19tUTQCF6lSfJlGQeFAT119wkFZhLu+ +FfLGqoEMH0ijJg/8PpdpFRK3I94YcISoTNN6yxMvE6xdDGfKCt5a+IX5bwQi9Zdc +B242gEc6tQKBgA6tM8n7KFlAIZU9HuWgk2AUC8kKutFPmSD7tgAqXDYI4FNfugs+ +MEEYyHCB4UNujJBV4Ss6YZCAkh6eyD4U2aca1eElCfm40vBVMdzvpqZdAqLtWXxg +D9l3mgszrFaYGCY2Fr6jLV9lP5g3xsxUjudf9jSLY9HvpfzjRrMaNATVAoGBALTl +/vYfPMucwKlC5B7++J0e4/7iv6vUu9SyHocdZh1anb9AjPDKjXLIlZT4RhQ8R0XK +0wOw5JpttU2uN08TKkbLNk3/vYhbKVjPLjrQSseh8sjDLgsqw1QwIxYnniLVakVY +p+rvjSNrNyqicQCMKQavwgocvSd5lJRTMwxOMezlAoGBAKWj71BX+0CK00/2S6lC +TcNcuUPG0d8y1czZ4q6tUlG4htwq1FMOpaghATXjkdsOGTLS+H1aA0Kt7Ai9zDhc +/bzOJEJ+jvBXV4Gcs7jl1r/HTKv0tT9ZSI5Vzkida0rfqxDGzcMVlLuCdH0cb8Iu +N0wdmCAqlQwHR13+F1zrAD7V +-----END PRIVATE KEY----- diff --git a/plugins/tests/check_http.t b/plugins/tests/check_http.t index d6d31de1..006f1339 100755 --- a/plugins/tests/check_http.t +++ b/plugins/tests/check_http.t @@ -4,13 +4,13 @@ # # To create the https server certificate: # openssl req -new -x509 -keyout server-key.pem -out server-cert.pem -days 3650 -nodes -# Country Name (2 letter code) [AU]:UK -# State or Province Name (full name) [Some-State]:Derbyshire -# Locality Name (eg, city) []:Belper +# Country Name (2 letter code) [AU]:DE +# State or Province Name (full name) [Some-State]:Bavaria +# Locality Name (eg, city) []:Munich # Organization Name (eg, company) [Internet Widgits Pty Ltd]:Monitoring Plugins # Organizational Unit Name (eg, section) []: -# Common Name (eg, YOUR name) []:Ton Voon -# Email Address []:tonvoon@mac.com +# Common Name (e.g. server FQDN or YOUR name) []:Monitoring Plugins +# Email Address []:devel@monitoring-plugins.org use strict; use Test::More; @@ -194,16 +194,16 @@ SKIP: { $result = NPTest->testCmd( "$command -p $port_https -S -C 14" ); is( $result->return_code, 0, "$command -p $port_https -S -C 14" ); - is( $result->output, 'OK - Certificate \'Ton Voon\' will expire on Sun Mar 3 21:41:28 2019 +0000.', "output ok" ); + is( $result->output, "OK - Certificate 'Monitoring Plugins' will expire on Fri Feb 16 15:31:44 2029 +0000.", "output ok" ); $result = NPTest->testCmd( "$command -p $port_https -S -C 14000" ); is( $result->return_code, 1, "$command -p $port_https -S -C 14000" ); - like( $result->output, '/WARNING - Certificate \'Ton Voon\' expires in \d+ day\(s\) \(Sun Mar 3 21:41:28 2019 \+0000\)./', "output ok" ); + like( $result->output, '/WARNING - Certificate \'Monitoring Plugins\' expires in \d+ day\(s\) \(Fri Feb 16 15:31:44 2029 \+0000\)./', "output ok" ); # Expired cert tests $result = NPTest->testCmd( "$command -p $port_https -S -C 13960,14000" ); is( $result->return_code, 2, "$command -p $port_https -S -C 13960,14000" ); - like( $result->output, '/CRITICAL - Certificate \'Ton Voon\' expires in \d+ day\(s\) \(Sun Mar 3 21:41:28 2019 \+0000\)./', "output ok" ); + like( $result->output, '/CRITICAL - Certificate \'Monitoring Plugins\' expires in \d+ day\(s\) \(Fri Feb 16 15:31:44 2029 \+0000\)./', "output ok" ); $result = NPTest->testCmd( "$command -p $port_https_expired -S -C 7" ); is( $result->return_code, 2, "$command -p $port_https_expired -S -C 7" ); diff --git a/plugins/tests/check_snmp.t b/plugins/tests/check_snmp.t index 73a68b20..85d6bf55 100755 --- a/plugins/tests/check_snmp.t +++ b/plugins/tests/check_snmp.t @@ -7,6 +7,7 @@ use strict; use Test::More; use NPTest; use FindBin qw($Bin); +use POSIX qw/strftime/; my $tests = 67; # Check that all dependent modules are available @@ -37,6 +38,7 @@ if ($@) { my $port_snmp = 16100 + int(rand(100)); +my $faketime = -x '/usr/bin/faketime' ? 1 : 0; # Start up server my @pids; @@ -118,77 +120,81 @@ like($res->output, '/'.quotemeta('SNMP OK - And now have fun with with this: \"C "And now have fun with with this: \"C:\\\\\" because we\'re not done yet!"').'/m', "Attempt to confuse parser No.3"); -system("rm -f ".$ENV{'MP_STATE_PATH'}."/check_snmp/*"); -$res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.10 --rate -w 600" ); -is($res->return_code, 0, "Returns OK"); -is($res->output, "No previous data to calculate rate - assume okay"); +system("rm -f ".$ENV{'MP_STATE_PATH'}."/*/check_snmp/*"); -# Need to sleep, otherwise duration=0 -sleep 1; +# run rate checks with faketime. rate checks depend on the exact amount of time spend between the +# plugin runs which may fail on busy machines. +# using faketime removes this race condition and also saves all the sleeps in between. +SKIP: { + skip "No faketime binary found", 28 if !$faketime; -$res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.10 --rate -w 600" ); -is($res->return_code, 1, "WARNING - due to going above rate calculation" ); -is($res->output, "SNMP RATE WARNING - *666* | iso.3.6.1.4.1.8072.3.2.67.10=666;600 "); + my $ts = time(); + $res = NPTest->testCmd("LC_TIME=C TZ=UTC faketime -f '".strftime("%Y-%m-%d %H:%M:%S", localtime($ts))."' ./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.10 --rate -w 600" ); + is($res->return_code, 0, "Returns OK"); + is($res->output, "No previous data to calculate rate - assume okay"); -$res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.10 --rate -w 600" ); -is($res->return_code, 3, "UNKNOWN - basically the divide by zero error" ); -is($res->output, "Time duration between plugin calls is invalid"); + # test rate 1 second later + $res = NPTest->testCmd("LC_TIME=C TZ=UTC faketime -f '".strftime("%Y-%m-%d %H:%M:%S", localtime($ts+1))."' ./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.10 --rate -w 600" ); + is($res->return_code, 1, "WARNING - due to going above rate calculation" ); + is($res->output, "SNMP RATE WARNING - *666* | iso.3.6.1.4.1.8072.3.2.67.10=666;600 "); + # test rate with same time + $res = NPTest->testCmd("LC_TIME=C TZ=UTC faketime -f '".strftime("%Y-%m-%d %H:%M:%S", localtime($ts+1))."' ./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.10 --rate -w 600" ); + is($res->return_code, 3, "UNKNOWN - basically the divide by zero error" ); + is($res->output, "Time duration between plugin calls is invalid"); -$res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.10 --rate -l inoctets" ); -is($res->return_code, 0, "OK for first call" ); -is($res->output, "No previous data to calculate rate - assume okay" ); -# Need to sleep, otherwise duration=0 -sleep 1; + $res = NPTest->testCmd("LC_TIME=C TZ=UTC faketime -f '".strftime("%Y-%m-%d %H:%M:%S", localtime($ts))."' ./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.10 --rate -l inoctets" ); + is($res->return_code, 0, "OK for first call" ); + is($res->output, "No previous data to calculate rate - assume okay" ); -$res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.10 --rate -l inoctets" ); -is($res->return_code, 0, "OK as no thresholds" ); -is($res->output, "SNMP RATE OK - inoctets 666 | inoctets=666 ", "Check label"); + # test rate 1 second later + $res = NPTest->testCmd("LC_TIME=C TZ=UTC faketime -f '".strftime("%Y-%m-%d %H:%M:%S", localtime($ts+1))."' ./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.10 --rate -l inoctets" ); + is($res->return_code, 0, "OK as no thresholds" ); + is($res->output, "SNMP RATE OK - inoctets 666 | inoctets=666 ", "Check label"); -sleep 2; + # test rate 3 seconds later + $res = NPTest->testCmd("LC_TIME=C TZ=UTC faketime -f '".strftime("%Y-%m-%d %H:%M:%S", localtime($ts+3))."' ./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.10 --rate -l inoctets" ); + is($res->return_code, 0, "OK as no thresholds" ); + is($res->output, "SNMP RATE OK - inoctets 333 | inoctets=333 ", "Check rate decreases due to longer interval"); -$res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.10 --rate -l inoctets" ); -is($res->return_code, 0, "OK as no thresholds" ); -is($res->output, "SNMP RATE OK - inoctets 333 | inoctets=333 ", "Check rate decreases due to longer interval"); + # label performance data check + $res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.10 -l test" ); + is($res->return_code, 0, "OK as no thresholds" ); + is($res->output, "SNMP OK - test 67996 | test=67996c ", "Check label"); -# label performance data check -$res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.10 -l test" ); -is($res->return_code, 0, "OK as no thresholds" ); -is($res->output, "SNMP OK - test 67996 | test=67996c ", "Check label"); + $res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.10 -l \"test'test\"" ); + is($res->return_code, 0, "OK as no thresholds" ); + is($res->output, "SNMP OK - test'test 68662 | \"test'test\"=68662c ", "Check label"); -$res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.10 -l \"test'test\"" ); -is($res->return_code, 0, "OK as no thresholds" ); -is($res->output, "SNMP OK - test'test 68662 | \"test'test\"=68662c ", "Check label"); + $res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.10 -l 'test\"test'" ); + is($res->return_code, 0, "OK as no thresholds" ); + is($res->output, "SNMP OK - test\"test 69328 | 'test\"test'=69328c ", "Check label"); -$res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.10 -l 'test\"test'" ); -is($res->return_code, 0, "OK as no thresholds" ); -is($res->output, "SNMP OK - test\"test 69328 | 'test\"test'=69328c ", "Check label"); + $res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.10 -l test -O" ); + is($res->return_code, 0, "OK as no thresholds" ); + is($res->output, "SNMP OK - test 69994 | iso.3.6.1.4.1.8072.3.2.67.10=69994c ", "Check label"); -$res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.10 -l test -O" ); -is($res->return_code, 0, "OK as no thresholds" ); -is($res->output, "SNMP OK - test 69994 | iso.3.6.1.4.1.8072.3.2.67.10=69994c ", "Check label"); + $res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.10" ); + is($res->return_code, 0, "OK as no thresholds" ); + is($res->output, "SNMP OK - 70660 | iso.3.6.1.4.1.8072.3.2.67.10=70660c ", "Check label"); -$res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.10" ); -is($res->return_code, 0, "OK as no thresholds" ); -is($res->output, "SNMP OK - 70660 | iso.3.6.1.4.1.8072.3.2.67.10=70660c ", "Check label"); + $res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.10 -l 'test test'" ); + is($res->return_code, 0, "OK as no thresholds" ); + is($res->output, "SNMP OK - test test 71326 | 'test test'=71326c ", "Check label"); -$res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.10 -l 'test test'" ); -is($res->return_code, 0, "OK as no thresholds" ); -is($res->output, "SNMP OK - test test 71326 | 'test test'=71326c ", "Check label"); + $res = NPTest->testCmd("LC_TIME=C TZ=UTC faketime -f '".strftime("%Y-%m-%d %H:%M:%S", localtime($ts))."' ./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.10 --rate -l inoctets_per_minute --rate-multiplier=60" ); + is($res->return_code, 0, "OK for first call" ); + is($res->output, "No previous data to calculate rate - assume okay" ); -$res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.10 --rate -l inoctets_per_minute --rate-multiplier=60" ); -is($res->return_code, 0, "OK for first call" ); -is($res->output, "No previous data to calculate rate - assume okay" ); - -# Need to sleep, otherwise duration=0 -sleep 1; + # test 1 second later + $res = NPTest->testCmd("LC_TIME=C TZ=UTC faketime -f '".strftime("%Y-%m-%d %H:%M:%S", localtime($ts+1))."' ./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.10 --rate -l inoctets_per_minute --rate-multiplier=60" ); + is($res->return_code, 0, "OK as no thresholds" ); + is($res->output, "SNMP RATE OK - inoctets_per_minute 39960 | inoctets_per_minute=39960 ", "Checking multiplier"); +}; -$res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.10 --rate -l inoctets_per_minute --rate-multiplier=60" ); -is($res->return_code, 0, "OK as no thresholds" ); -is($res->output, "SNMP RATE OK - inoctets_per_minute 39960 | inoctets_per_minute=39960 ", "Checking multiplier"); $res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.11 -s '\"stringtests\"'" ); diff --git a/plugins/utils.c b/plugins/utils.c index 231af92b..ee620133 100644 --- a/plugins/utils.c +++ b/plugins/utils.c @@ -36,9 +36,6 @@ extern const char *progname; #define STRLEN 64 #define TXTBLK 128 -unsigned int timeout_state = STATE_CRITICAL; -unsigned int timeout_interval = DEFAULT_SOCKET_TIMEOUT; - time_t start_time, end_time; /* ************************************************************************** @@ -148,33 +145,6 @@ print_revision (const char *command_name, const char *revision) command_name, revision, PACKAGE, VERSION); } -const char * -state_text (int result) -{ - switch (result) { - case STATE_OK: - return "OK"; - case STATE_WARNING: - return "WARNING"; - case STATE_CRITICAL: - return "CRITICAL"; - case STATE_DEPENDENT: - return "DEPENDENT"; - default: - return "UNKNOWN"; - } -} - -void -timeout_alarm_handler (int signo) -{ - if (signo == SIGALRM) { - printf (_("%s - Plugin timed out after %d seconds\n"), - state_text(timeout_state), timeout_interval); - exit (timeout_state); - } -} - int is_numeric (char *number) { @@ -708,4 +678,3 @@ char *sperfdata_int (const char *label, return data; } - diff --git a/plugins/utils.h b/plugins/utils.h index a436e1ca..6aa316fe 100644 --- a/plugins/utils.h +++ b/plugins/utils.h @@ -29,13 +29,6 @@ suite of plugins. */ void support (void); void print_revision (const char *, const char *); -/* Handle timeouts */ - -extern unsigned int timeout_state; -extern unsigned int timeout_interval; - -RETSIGTYPE timeout_alarm_handler (int); - extern time_t start_time, end_time; /* Test input types */ @@ -89,8 +82,6 @@ void usage4(const char *) __attribute__((noreturn)); void usage5(void) __attribute__((noreturn)); void usage_va(const char *fmt, ...) __attribute__((noreturn)); -const char *state_text (int); - #define max(a,b) (((a)>(b))?(a):(b)) #define min(a,b) (((a)<(b))?(a):(b)) |