Merge branch 'master' into fix/shellcheck

This commit is contained in:
RincewindsHat 2021-12-02 16:42:05 +01:00 committed by GitHub
commit 911e44045d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
115 changed files with 15534 additions and 1547 deletions

View file

@ -1,60 +1,54 @@
{
'MYSQL_LOGIN_DETAILS' => '-u root -d test',
'NP_ALLOW_SUDO' => 'yes',
'NP_DNS_SERVER' => '8.8.8.8',
'NP_GOOD_NTP_SERVICE' => '',
'NP_HOSTNAME_INVALID' => 'nosuchhost',
'NP_HOSTNAME_VALID' => 'monitoring-plugins.org',
'NP_HOSTNAME_VALID_IP' => '130.133.8.40',
'NP_HOSTNAME_VALID_CIDR' => '130.133.8.41/30',
'NP_HOSTNAME_INVALID_CIDR' => '130.133.8.39/30',
'NP_HOSTNAME_VALID_REVERSE' => 'orwell.monitoring-plugins.org.',
'NP_HOST_DHCP_RESPONSIVE' => '',
'NP_HOST_NONRESPONSIVE' => '10.0.0.1',
'NP_HOST_RESPONSIVE' => 'localhost',
'NP_HOST_SMB' => '',
'NP_HOST_SNMP' => 'localhost',
'NP_HOST_TCP_FTP' => '',
'NP_HOST_TCP_HPJD' => '',
'NP_HOST_HPJD_PORT_INVALID' => '161',
'NP_HOST_HPJD_PORT_VALID' => '',
'NP_HOST_TCP_HTTP' => 'localhost',
'NP_HOSTNAME_INVALID_CIDR' => '130.133.8.39/30',
'NP_HOSTNAME_INVALID' => 'nosuchhost',
'NP_HOSTNAME_VALID_CIDR' => '130.133.8.41/30',
'NP_HOSTNAME_VALID_IP' => '130.133.8.40',
'NP_HOSTNAME_VALID' => 'monitoring-plugins.org',
'NP_HOSTNAME_VALID_REVERSE' => 'orwell.monitoring-plugins.org.',
'NP_HOST_NONRESPONSIVE' => '192.168.1.2',
'NP_HOST_RESPONSIVE' => 'localhost',
'NP_HOST_SMB' => '',
'NP_HOST_SNMP' => '',
'NP_HOST_TCP_FTP' => '',
'NP_HOST_TCP_HPJD' => '',
'NP_HOST_TCP_HTTP2' => 'test.monitoring-plugins.org',
'NP_HOST_TCP_HTTP' => 'localhost',
'NP_HOST_TCP_IMAP' => 'imap.web.de',
'NP_HOST_TCP_JABBER' => 'jabber.org',
'NP_HOST_TCP_LDAP' => 'localhost',
'NP_HOST_TCP_POP' => 'pop.web.de',
'NP_HOST_TCP_PROXY' => 'localhost',
'NP_HOST_TCP_SMTP' => 'localhost',
'NP_HOST_TCP_SMTP_NOTLS' => '',
'NP_HOST_TCP_SMTP_TLS' => '',
'NP_HOST_TLS_CERT' => 'localhost',
'NP_HOST_TLS_HTTP' => 'localhost',
'NP_HOST_UDP_TIME' => 'none',
'NP_INTERNET_ACCESS' => 'yes',
'NP_LDAP_BASE_DN' => 'cn=admin,dc=nodomain',
'NP_MOUNTPOINT2_VALID' => '/media/ramdisk',
'NP_LDAP_BASE_DN' => 'dc=nodomain',
'NP_MOUNTPOINT2_VALID' => '/media/ramdisk1',
'NP_MOUNTPOINT_VALID' => '/',
'NP_MYSQL_LOGIN_DETAILS' => '-u root -d test',
'NP_MYSQL_SERVER' => 'localhost',
'NP_HOST_UDP_TIME' => 'localhost',
'NP_MYSQL_SOCKET' => '/var/run/mysqld/mysqld.sock',
'NP_MYSQL_WITH_SLAVE' => '',
'NP_MYSQL_WITH_SLAVE_LOGIN' => '',
'NP_NO_NTP_SERVICE' => 'localhost',
'NP_PORT_TCP_PROXY' => '3128',
'NP_SMB_SHARE' => '',
'NP_SMB_SHARE_DENY' => '',
'NP_SMB_SHARE_SPC' => '',
'NP_SMB_VALID_USER' => '',
'NP_SMB_VALID_USER_PASS' => '',
'NP_SNMP_COMMUNITY' => 'public',
'NP_SNMP_COMMUNITY' => '',
'NP_SNMP_USER' => '',
'NP_SSH_CONFIGFILE' => '~/.ssh/config',
'NP_SSH_HOST' => 'localhost',
'NP_SSH_IDENTITY' => '~/.ssh/id_dsa',
'NP_HOST_TCP_JABBER' => 'jabber.org',
'host_nonresponsive' => '10.0.0.1',
'host_responsive' => 'localhost',
'host_snmp' => '',
'host_tcp_ftp' => '',
'host_tcp_http' => 'localhost',
'host_tcp_imap' => 'imap.nierlein.de',
'host_tcp_smtp' => 'localhost',
'hostname_invalid' => 'nosuchhost',
'snmp_community' => '',
'user_snmp' => '',
'host_udp_time' => 'none',
'NP_SSH_IDENTITY' => '~/.ssh/id_rsa'
}

101
.github/prepare_debian.sh vendored Executable file
View file

@ -0,0 +1,101 @@
#!/bin/bash
set -x
set -e
export DEBIAN_FRONTEND=noninteractive
apt-get update
apt-get -y install software-properties-common
if [ $(lsb_release -is) = "Debian" ]; then
apt-add-repository non-free
apt-get update
fi
apt-get -y install perl autotools-dev libdbi-dev libldap2-dev libpq-dev libradcli-dev libnet-snmp-perl procps
apt-get -y install libdbi0-dev libdbd-sqlite3 libssl-dev dnsutils snmp-mibs-downloader libsnmp-perl snmpd
apt-get -y install fping snmp netcat-openbsd smbclient vsftpd apache2 ssl-cert postfix libhttp-daemon-ssl-perl
apt-get -y install libdbd-sybase-perl libnet-dns-perl
apt-get -y install slapd ldap-utils
apt-get -y install gcc make autoconf automake gettext
apt-get -y install faketime
apt-get -y install libmonitoring-plugin-perl
apt-get -y install libcurl4-openssl-dev
apt-get -y install liburiparser-dev
apt-get -y install squid
apt-get -y install openssh-server
apt-get -y install mariadb-server mariadb-client libmariadb-dev
apt-get -y install cron iputils-ping
apt-get -y install iproute2
# remove ipv6 interface from hosts
if [ $(ip addr show | grep "inet6 ::1" | wc -l) -eq "0" ]; then
sed '/^::1/d' /etc/hosts > /tmp/hosts
cp -f /tmp/hosts /etc/hosts
fi
ip addr show
cat /etc/hosts
# apache
a2enmod ssl
a2ensite default-ssl
# replace snakeoil certs with openssl generated ones as the make-ssl-cert ones
# seems to cause problems with our plugins
rm /etc/ssl/certs/ssl-cert-snakeoil.pem
rm /etc/ssl/private/ssl-cert-snakeoil.key
openssl req -nodes -newkey rsa:2048 -x509 -sha256 -days 365 -nodes -keyout /etc/ssl/private/ssl-cert-snakeoil.key -out /etc/ssl/certs/ssl-cert-snakeoil.pem -subj "/C=GB/ST=London/L=London/O=Global Security/OU=IT Department/CN=$(hostname)"
service apache2 restart
# squid
cp tools/squid.conf /etc/squid/squid.conf
service squid start
# mariadb
service mariadb start
mysql -e "create database IF NOT EXISTS test;" -uroot
# ldap
sed -e 's/cn=admin,dc=nodomain/'$(/usr/sbin/slapcat|grep ^dn:|awk '{print $2}')'/' -i .github/NPTest.cache
service slapd start
# sshd
ssh-keygen -t rsa -N "" -f ~/.ssh/id_rsa
cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
service ssh start
sleep 1
ssh-keyscan localhost >> ~/.ssh/known_hosts
touch ~/.ssh/config
# start one login session, required for check_users
ssh -tt localhost </dev/null >/dev/null 2>/dev/null &
disown %1
# snmpd
for DIR in /usr/share/snmp/mibs /usr/share/mibs; do
rm -f $DIR/ietf/SNMPv2-PDU \
$DIR/ietf/IPSEC-SPD-MIB \
$DIR/ietf/IPATM-IPMC-MIB \
$DIR/iana/IANA-IPPM-METRICS-REGISTRY-MIB
done
mkdir -p /var/lib/snmp/mib_indexes
sed -e 's/^agentaddress.*/agentaddress 127.0.0.1/' -i /etc/snmp/snmpd.conf
service snmpd start
# start cron, will be used by check_nagios
cron
# start postfix
service postfix start
# start ftpd
service vsftpd start
# hostname
sed "/NP_HOST_TLS_CERT/s/.*/'NP_HOST_TLS_CERT' => '$(hostname)',/" -i /src/.github/NPTest.cache
# create some test files to lower inodes
for i in $(seq 10); do
touch /media/ramdisk2/test.$1
done

71
.github/workflows/codeql-analysis.yml vendored Normal file
View file

@ -0,0 +1,71 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ master ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ master ]
schedule:
- cron: '15 18 * * 0'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'cpp' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
# Learn more:
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
steps:
- name: Checkout repository
uses: actions/checkout@v2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
- name: Install packages
run: |
sudo apt-get install -y --no-install-recommends m4 gettext automake autoconf make build-essential
sudo apt-get install -y --no-install-recommends perl autotools-dev libdbi-dev libldap2-dev libpq-dev \
libmysqlclient-dev libradcli-dev libkrb5-dev libdbi0-dev \
libdbd-sqlite3 libssl-dev libcurl4-openssl-dev liburiparser-dev
- name: Configure build
run: |
./tools/setup
./configure --enable-libtap
- name: Build
run: |
make
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1

47
.github/workflows/test.yml vendored Normal file
View file

@ -0,0 +1,47 @@
name: Test
on:
push:
branches:
- '*'
pull_request:
jobs:
# macos:
# ...
linux:
runs-on: ubuntu-latest
name: Running tests on ${{ matrix.distro }}
strategy:
fail-fast: false
matrix:
distro:
- 'debian:testing'
#...
include:
- distro: 'debian:testing'
prepare: .github/prepare_debian.sh
#...
steps:
- name: Git clone repository
uses: actions/checkout@v2
#- name: Setup tmate session, see https://github.com/marketplace/actions/debugging-with-tmate
# uses: mxschmitt/action-tmate@v3
- name: Run the tests on ${{ matrix.distro }}
run: |
docker volume create --driver local --opt type=tmpfs --opt device=tmpfs --opt o=size=100m,uid=1000 tmp-vol
docker run \
-e NPTEST_ACCEPTDEFAULT=1 \
-e NPTEST_CACHE="/src/.github/NPTest.cache" \
-w /src -v ${PWD}:/src \
--tmpfs /media/ramdisk1 \
-v /var/run/utmp:/var/run/utmp \
--mount source=tmp-vol,destination=/src,target=/media/ramdisk2 \
${{ matrix.distro }} \
/bin/sh -c '${{ matrix.prepare }} && \
tools/setup && \
./configure --enable-libtap --with-ipv6=no && \
make && \
make test'
docker container prune -f
docker volume prune -f

8
.gitignore vendored
View file

@ -142,6 +142,7 @@ NP-VERSION-FILE
/plugins/check_by_ssh
/plugins/check_clamd
/plugins/check_cluster
/plugins/check_curl
/plugins/check_dbi
/plugins/check_dig
/plugins/check_disk
@ -202,6 +203,12 @@ NP-VERSION-FILE
/plugins/stamp-h*
/plugins/urlize
# /plugins/picohttpparser
/plugins/picohttpparser/Makefile
/plugins/picohttpparser/Makefile.in
/plugins/picohttpparser/.deps
/plugins/picohttpparser/libpicohttpparser.a
# /plugins/t/
/plugins/t/*.tmp
@ -241,6 +248,7 @@ NP-VERSION-FILE
/plugins-scripts/check_sensors
/plugins-scripts/check_wave
/plugins-scripts/check_file_age
/plugins-scripts/check_uptime
# /po/
/po/Makefile

View file

@ -1,88 +0,0 @@
sudo: required
dist: trusty
language: c
env:
global:
# This is the encrypted COVERITY_SCAN_TOKEN, created via the "travis
# encrypt" command using the project repository's public key.
- secure: "ggJ9c/VfKcwtrwz/My+ne4My7D8g3qi3vz5Hh+yLiri0+oIXCy313ZD6ssIEY/5beQZEOnuHhBgBJd/Y3clSQNc2M9fRNc+wxOkIO992lgnY0MZJN3y9MLfpqUbTClhU9Fst0qXQqGpI6UI8yz1tj7yKi7DPrycJLRrjMpyTfyo="
matrix:
include:
- compiler: "gcc"
os: linux
env:
- PLATFORM=linux BITS=64 HOST=x86_64
addons:
coverity_scan:
project:
name: "monitoring-plugins/monitoring-plugins"
description: "Monitoring Plugins"
notification_email: team@monitoring-plugins.org
build_command_prepend: tools/setup && ./configure
build_command: make
branch_pattern: coverity.*
- compiler: "clang"
os: linux
env:
- PLATFORM=linux BITS=64 HOST=x86_64
before_install:
# Trusty related fixed
# multiverse is no on trusty activated (https://github.com/travis-ci/travis-ci/issues/4979)
- sudo add-apt-repository "deb http://archive.ubuntu.com/ubuntu/ trusty multiverse" && sudo add-apt-repository "deb http://archive.ubuntu.com/ubuntu/ trusty-updates multiverse"
# /etc/hosts has IPv6 hosts (https://github.com/travis-ci/travis-ci/issues/4978)
- sudo [ $(ip addr show | grep "inet6 ::1" | wc -l) -lt "1" ] && sudo sed -i '/^::1/d' /etc/hosts
# Trusty has running ntpd on localhost, but we don't like that for our tests
- 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
# http://docs.travis-ci.com/user/trusty-ci-environment/ indicates, no MySQL on Trusty (yet)
# # ensure we have a test database in place for tests
# - mysql -e "create database IF NOT EXISTS test;" -uroot
install:
- sudo apt-get install -qq --no-install-recommends perl autotools-dev libdbi-dev libldap2-dev libpq-dev libmysqlclient-dev libradcli-dev libkrb5-dev libnet-snmp-perl procps
- sudo apt-get install -qq --no-install-recommends libdbi0-dev libdbd-sqlite3 libssl-dev dnsutils snmp-mibs-downloader libsnmp-perl snmpd
- sudo apt-get install -qq --no-install-recommends fping snmp netcat smbclient fping pure-ftpd apache2 postfix libhttp-daemon-ssl-perl
- sudo apt-get install -qq --no-install-recommends libdbd-sybase-perl libnet-dns-perl
- sudo apt-get install -qq --no-install-recommends slapd ldap-utils
- sudo apt-get install -qq --no-install-recommends autoconf automake
- sudo apt-get install -qq --no-install-recommends faketime
# 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
before_script:
# ensure we have a test database in place for tests
- mysql -e "create database IF NOT EXISTS test;" -uroot
# Detect LDAP configuration (seems volatile on trusty env)
- sed -e 's/cn=admin,dc=nodomain/'$(sudo /usr/sbin/slapcat|grep ^dn:|grep cn=|awk '{print $2}')'/' -i plugins/t/NPTest.cache.travis
- tools/setup
- ./configure --enable-libtap
- make
- 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-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
- sudo mkdir -p /var/lib/snmp/mib_indexes
- sudo mkdir /media/ramdisk && sudo chmod 777 /media/ramdisk && sudo mount -t tmpfs -o size=20% none /media/ramdisk
script:
- if [ "$COVERITY_SCAN_BRANCH" != 1 ]; then make test; fi
notifications:
irc:
channels:
- "chat.freenode.net#Monitoring-Plugins"
on_success: change
on_failure: always
skip_join: true
email:
# - team@monitoring-plugins.org

View file

@ -20,7 +20,7 @@ Using the DLPI support on SysV systems to get the host MAC address in check_dhcp
Stenberg, Daniel
Copyright (c) 1996 - 2004, Daniel Stenberg, <daniel@haxx.se>
http://curl.haxx.se/
Use of duplication of macros in m4/np_curl.m4
Use of duplication of macros in m4/np_curl.m4 (slighly adapted for m4/uriparser.m4 too)
Coreutils team
Copyright (C) 91, 1995-2004 Free Software Foundation, Inc.
@ -31,3 +31,9 @@ Gnulib team
Copyright (C) 2001, 2003, 2004, 2006 Free Software Foundation, Inc
http://www.gnu.org/software/gnulib/
Use of lib files that originally were used from coreutils
Copyright (c) 2009-2014 Kazuho Oku, Tokuhiro Matsuno, Daisuke Murase,
Shigeo Mitsunari
picohttpparser
https://github.com/h2o/picohttpparser
Use of the library for HTTP header parsing in check_curl.

View file

@ -34,6 +34,7 @@ test test-debug:
if test "$(PERLMODS_DIR)" != ""; then cd perlmods && $(MAKE) $@; fi
cd plugins && $(MAKE) $@
cd plugins-scripts && $(MAKE) $@
cd plugins-root && $(MAKE) $@
# Solaris pkgmk
BUILDDIR = build-solaris

47
NEWS
View file

@ -1,12 +1,57 @@
This file documents the major additions and syntax changes between releases.
2.3 [...]
2.4 [...]
ENHANCEMENTS
FIXES
2.3 10th December 2020
ENHANCEMENTS
check_dns: allow 'expected address' (-a) to be specified in CIDR notation
(IPv4 only).
check_dns: allow for IPv6 RDNS
check_dns: Accept CIDR
check_dns: allow unsorted addresses
check_dns: allow forcing complete match of all addresses
check_dns: option to expect NXDOMAIN
check_apt: add --only-critical switch
check_apt: add -l/--list option to print packages
check_file_age: add range checking
check_file_age: enable to test for maximum file size
check_apt: adding packages-warning option
check_load: Adding top consuming processes option
check_http: Adding Proxy-Authorization and extra headers
check_snmp: make calcualtion of timeout value in help output more clear
check_uptime: new plugin for checking uptime to see how long the system is running
check_curl: check_http replacement based on libcurl
check_http: Allow user to specify HTTP method after proxy CONNECT
check_http: Add new flag --show-body/-B to print body
check_cluster: Added data argument validation
check_icmp: Add IPv6 support
check_icmp: Automatically detect IP protocol
check_icmp: emit error if multiple protocol version
check_disk: add support to display inodes usage in perfdata
check_hpjd: Added -D option to disable warning on 'out of paper'
check_http: support the --show-body/-B flag when --expect is used
check_mysql: allow mariadbclient to be used
check_tcp: add --sni
check_dns: detect unreachable dns service in nslookup output
FIXES
Fix regression where check_dhcp was rereading response in a tight loop
check_dns: fix error detection on sles nslookup
check_disk_smb: fix timeout issue
check_swap: repaired "-n" behaviour
check_icmp: Correctly set address_family on lookup
check_icmp: Do not overwrite -4,-6 on lookup
check_smtp: initializes n before it is used
check_dns: fix typo in parameter description
check_by_ssh: fix child process leak on timeouts
check_mysql: Allow sockets to be specified to -H
check_procs: improve command examples for 'at least' processes
check_swap: repaired "-n" behaviour
check_disk: include -P switch in help
check_mailq: restore accidentially removed options
2.2 29th November 2016
ENHANCEMENTS

View file

@ -6,7 +6,7 @@
SRC_ROOT=`dirname $0`
NPVF=NP-VERSION-FILE
DEF_VER=2.2.git
DEF_VER=2.3git
LF='
'

242
NPTest.pm
View file

@ -53,8 +53,8 @@ developer to interactively request test parameter information from the
user. The user can accept the developer's default value or reply "none"
which will then be returned as "" for the test to skip if appropriate.
If a parameter needs to be entered and the test is run without a tty
attached (such as a cronjob), the parameter will be assigned as if it
If a parameter needs to be entered and the test is run without a tty
attached (such as a cronjob), the parameter will be assigned as if it
was "none". Tests can check for the parameter and skip if not set.
Responses are stored in an external, file-based cache so subsequent test
@ -62,17 +62,6 @@ runs will use these values. The user is able to change the values by
amending the values in the file /var/tmp/NPTest.cache, or by setting
the appropriate environment variable before running the test.
The option exists to store parameters in a scoped means, allowing a
test harness to a localise a parameter should the need arise. This
allows a parameter of the same name to exist in a test harness
specific scope, while not affecting the globally scoped parameter. The
scoping identifier is the name of the test harness sans the trailing
".t". All cache searches first look to a scoped parameter before
looking for the parameter at global scope. Thus for a test harness
called "check_disk.t" requesting the parameter "mountpoint_valid", the
cache is first searched for "check_disk"/"mountpoint_valid", if this
fails, then a search is conducted for "mountpoint_valid".
To facilitate quick testing setup, it is possible to accept all the
developer provided defaults by setting the environment variable
"NPTEST_ACCEPTDEFAULT" to "1" (or any other perl truth value). Note
@ -249,26 +238,26 @@ sub checkCmd
{
if ( scalar( grep { $_ == $exitStatus } @{$desiredExitStatus} ) )
{
$desiredExitStatus = $exitStatus;
$desiredExitStatus = $exitStatus;
}
else
{
$desiredExitStatus = -1;
$desiredExitStatus = -1;
}
}
elsif ( ref $desiredExitStatus eq "HASH" )
{
if ( exists( ${$desiredExitStatus}{$exitStatus} ) )
{
if ( defined( ${$desiredExitStatus}{$exitStatus} ) )
{
$testOutput = ${$desiredExitStatus}{$exitStatus};
}
$desiredExitStatus = $exitStatus;
if ( defined( ${$desiredExitStatus}{$exitStatus} ) )
{
$testOutput = ${$desiredExitStatus}{$exitStatus};
}
$desiredExitStatus = $exitStatus;
}
else
{
$desiredExitStatus = -1;
$desiredExitStatus = -1;
}
}
@ -327,78 +316,51 @@ sub skipMsg
return $testStatus;
}
sub getTestParameter
{
my( $param, $envvar, $default, $brief, $scoped );
my $new_style;
if (scalar @_ <= 3) {
($param, $brief, $default) = @_;
$envvar = $param;
$new_style = 1;
} else {
( $param, $envvar, $default, $brief, $scoped ) = @_;
$new_style = 0;
sub getTestParameter {
my($param, $description, $default) = @_;
if($param !~ m/^NP_[A-Z0-9_]+$/mx) {
die("parameter should be all uppercase and start with NP_ (requested from ".(caller(0))[1].")");
}
# Apply default values for optional arguments
$scoped = ( defined( $scoped ) && $scoped );
return $ENV{$param} if $ENV{$param};
my $testharness = basename( (caller(0))[1], ".t" ); # used for scoping
if ( defined( $envvar ) && exists( $ENV{$envvar} ) && $ENV{$envvar} )
{
return $ENV{$envvar};
}
my $cachedValue = SearchCache( $param, $testharness );
if ( defined( $cachedValue ) )
{
# This save required to convert to new style because the key required is
# changing to the environment variable
if ($new_style == 0) {
SetCacheParameter( $envvar, undef, $cachedValue );
}
my $cachedValue = SearchCache($param);
if(defined $cachedValue) {
return $cachedValue;
}
my $defaultValid = ( defined( $default ) && $default );
my $autoAcceptDefault = ( exists( $ENV{'NPTEST_ACCEPTDEFAULT'} ) && $ENV{'NPTEST_ACCEPTDEFAULT'} );
if ( $autoAcceptDefault && $defaultValid )
{
return $default;
if($ENV{'NPTEST_ACCEPTDEFAULT'}) {
return $default if $default;
return "";
}
# Set "none" if no terminal attached (eg, tinderbox build servers when new variables set)
return "" unless (-t STDIN);
my $userResponse = "";
while ( $userResponse eq "" )
{
while($userResponse eq "") {
print STDERR "\n";
print STDERR "Test Harness : $testharness\n";
print STDERR "Test Parameter : $param\n";
print STDERR "Environment Variable : $envvar\n" if ($param ne $envvar);
print STDERR "Brief Description : $brief\n";
print STDERR "Enter value (or 'none') ", ($defaultValid ? "[${default}]" : "[]"), " => ";
print STDERR "Test File : ".(caller(0))[1]."\n";
print STDERR "Test Parameter : $param\n";
print STDERR "Description : $description\n";
print STDERR "Enter value (or 'none') ", ($default ? "[${default}]" : "[]"), " => ";
$userResponse = <STDIN>;
$userResponse = "" if ! defined( $userResponse ); # Handle EOF
chomp( $userResponse );
if ( $defaultValid && $userResponse eq "" )
{
chomp($userResponse);
if($default && $userResponse eq "") {
$userResponse = $default;
}
}
print STDERR "\n";
if ($userResponse =~ /^(na|none)$/) {
$userResponse = "";
if($userResponse =~ /^(na|none)$/) {
$userResponse = "";
}
# define all user responses at global scope
SetCacheParameter( $param, ( $scoped ? $testharness : undef ), $userResponse );
# store user responses
SetCacheParameter($param, $userResponse);
return $userResponse;
}
@ -407,37 +369,20 @@ sub getTestParameter
# Internal Cache Management Functions
#
sub SearchCache
{
my( $param, $scope ) = @_;
sub SearchCache {
my($param) = @_;
LoadCache();
if ( exists( $CACHE{$scope} ) && exists( $CACHE{$scope}{$param} ) )
{
return $CACHE{$scope}{$param};
}
if ( exists( $CACHE{$param} ) )
{
if(exists $CACHE{$param}) {
return $CACHE{$param};
}
return undef; # Need this to say "nothing found"
return undef; # Need this to say "nothing found"
}
sub SetCacheParameter
{
my( $param, $scope, $value ) = @_;
if ( defined( $scope ) )
{
$CACHE{$scope}{$param} = $value;
}
else
{
$CACHE{$param} = $value;
}
sub SetCacheParameter {
my($param, $value) = @_;
$CACHE{$param} = $value;
SaveCache();
}
@ -475,6 +420,11 @@ sub SaveCache
delete $CACHE{'_cache_loaded_'};
my $oldFileContents = delete $CACHE{'_original_cache'};
# clean up old style params
for my $key (keys %CACHE) {
delete $CACHE{$key} if $key !~ m/^NP_[A-Z0-9_]+$/mx;
}
my($dataDumper) = new Data::Dumper([\%CACHE]);
$dataDumper->Terse(1);
$dataDumper->Sortkeys(1);
@ -486,7 +436,7 @@ sub SaveCache
if($oldFileContents ne $data) {
my($fileHandle) = new IO::File;
if (!$fileHandle->open( "> ${CACHEFILENAME}")) {
print STDERR "NPTest::LoadCache() : Problem saving ${CACHEFILENAME} : $!\n";
print STDERR "NPTest::SaveCache() : Problem saving ${CACHEFILENAME} : $!\n";
return;
}
print $fileHandle $data;
@ -542,10 +492,10 @@ sub DetermineTestHarnessDirectory
push ( @dirs, "./tests");
}
if ( @dirs > 0 )
{
return @dirs;
}
if ( @dirs > 0 )
{
return @dirs;
}
# To be honest I don't understand which case satisfies the
# original code in test.pl : when $tstdir == `pwd` w.r.t.
@ -611,73 +561,73 @@ sub TestsFrom
# All the new object oriented stuff below
sub new {
my $type = shift;
my $self = {};
return bless $self, $type;
sub new {
my $type = shift;
my $self = {};
return bless $self, $type;
}
# Accessors
sub return_code {
my $self = shift;
if (@_) {
return $self->{return_code} = shift;
} else {
return $self->{return_code};
}
my $self = shift;
if (@_) {
return $self->{return_code} = shift;
} else {
return $self->{return_code};
}
}
sub output {
my $self = shift;
if (@_) {
return $self->{output} = shift;
} else {
return $self->{output};
}
my $self = shift;
if (@_) {
return $self->{output} = shift;
} else {
return $self->{output};
}
}
sub perf_output {
my $self = shift;
$_ = $self->{output};
/\|(.*)$/;
return $1 || "";
my $self = shift;
$_ = $self->{output};
/\|(.*)$/;
return $1 || "";
}
sub only_output {
my $self = shift;
$_ = $self->{output};
/(.*?)\|/;
return $1 || "";
my $self = shift;
$_ = $self->{output};
/(.*?)\|/;
return $1 || "";
}
sub testCmd {
my $class = shift;
my $command = shift or die "No command passed to testCmd";
my $timeout = shift || 120;
my $object = $class->new;
my $class = shift;
my $command = shift or die "No command passed to testCmd";
my $timeout = shift || 120;
my $object = $class->new;
local $SIG{'ALRM'} = sub { die("timeout in command: $command"); };
alarm($timeout); # no test should take longer than 120 seconds
local $SIG{'ALRM'} = sub { die("timeout in command: $command"); };
alarm($timeout); # no test should take longer than 120 seconds
my $output = `$command`;
$object->return_code($? >> 8);
$_ = $? & 127;
if ($_) {
die "Got signal $_ for command $command";
}
chomp $output;
$object->output($output);
my $output = `$command`;
$object->return_code($? >> 8);
$_ = $? & 127;
if ($_) {
die "Got signal $_ for command $command";
}
chomp $output;
$object->output($output);
alarm(0);
alarm(0);
my ($pkg, $file, $line) = caller(0);
print "Testing: $command", $/;
if ($ENV{'NPTEST_DEBUG'}) {
print "testCmd: Called from line $line in $file", $/;
print "Output: ", $object->output, $/;
print "Return code: ", $object->return_code, $/;
}
my ($pkg, $file, $line) = caller(0);
print "Testing: $command", $/;
if ($ENV{'NPTEST_DEBUG'}) {
print "testCmd: Called from line $line in $file", $/;
print "Output: ", $object->output, $/;
print "Return code: ", $object->return_code, $/;
}
return $object;
return $object;
}
# do we have ipv6

4
README
View file

@ -10,7 +10,7 @@ Monitoring Plugins
* For information on detailed changes that have been made or plugins
that have been added, read the `ChangeLog` file.
* Some plugins require that you have additional programs and/or
* Some plugins require that you have additional programs or
libraries installed on your system before they can be used. Plugins that
are dependent on other programs/libraries that are missing are usually not
compiled. Read the `REQUIREMENTS` file for more information.
@ -19,7 +19,7 @@ Monitoring Plugins
the basic guidelines for development will provide detailed help when
invoked with the `-h` or `--help` options.
You can check for the latest plugins at:
You can check the latest plugins at:
* <https://www.monitoring-plugins.org/>

View file

@ -11,6 +11,22 @@ check_ldaps, check_http --ssl, check_tcp --ssl, check_smtp --starttls
- Requires openssl or gnutls libraries for SSL connections
http://www.openssl.org, http://www.gnu.org/software/gnutls
check_curl:
- Requires libcurl 7.15.2 or later
http://www.haxx.se
- --ssl/-S and -C requires OpenSSL for certificate checks, otherwise
libcurl must be quite new to support CURLINFO_CERTINFO with
GnuTLS and NSS libraries:
- 7.42.0 or newer for GnuTLS
- 7.34.0 or newer for NSS
GnuTLS is known to create problems on some distributions with
self-signed certificate chains
http://www.openssl.org, http://www.gnu.org/software/gnutls,
http://www.mozilla.org/projects/security/pki/nss/,
other SSL implementations are currently not supported
- uriparser 0.7.5 or later
https://uriparser.github.io/
check_fping:
- Requires the fping utility distributed with SATAN. Either
download and install SATAN or grab the fping program from

View file

@ -356,3 +356,28 @@ Sven Geggus
Thomas Kurschel
Yannick Charton
Nicolai Søborg
Rolf Eike Beer
Bernd Arnold
Andreas Baumann
Tobias Wolf
Lars Michelsen
Vincent Danjean
Kostyantyn Hushchyn
Christian Tacke
Alexander A. Klimov
Vadim Zhukov
Bernard Spil
Christian Schmidt
Guido Falsi
Harald Koch
Iustin Pop
Jacob Hansen
Jean-François Rameau
Karol Babioch
Lucas Bussey
Marc Sánchez
Markus Frosch
Michael Kraus
Patrick Rauscher
Prathamesh Bhanuse
Valentin Vidic

View file

@ -1,6 +1,6 @@
dnl Process this file with autoconf to produce a configure script.
AC_PREREQ(2.59)
AC_INIT(monitoring-plugins,2.2)
AC_INIT(monitoring-plugins,2.3git)
AC_CONFIG_SRCDIR(NPTest.pm)
AC_CONFIG_FILES([gl/Makefile])
AC_CONFIG_AUX_DIR(build-aux)
@ -385,6 +385,42 @@ if test "$ac_cv_header_wtsapi32_h" = "yes"; then
AC_SUBST(WTSAPI32LIBS)
fi
_can_enable_check_curl=no
dnl Check for cURL library
LIBCURL_CHECK_CONFIG(yes, 7.15.2, [
_can_enable_check_curl=yes
LIBCURLINCLUDE="$LIBCURL_CPPFLAGS"
LIBCURLLIBS="$LIBCURL"
LIBCURLCFLAGS="$LIBCURL_CPPFLAGS"
AC_SUBST(LIBCURLINCLUDE)
AC_SUBST(LIBCURLLIBS)
AC_SUBST(LIBCURLCFLAGS)
], [
_can_enable_check_curl=no
AC_MSG_WARN([Skipping curl plugin])
AC_MSG_WARN([install libcurl libs to compile this plugin (see REQUIREMENTS).])
])
dnl Check for uriparser library
URIPARSER_CHECK(yes, 0.7.5, [
URIPARSERINCLUDE="$URIPARSER_CPPFLAGS"
URIPARSERLIBS="$URIPARSER"
URIPARSERCFLAGS="$URIPARSER_CPPFLAGS"
AC_SUBST(URIPARSERINCLUDE)
AC_SUBST(URIPARSERLIBS)
AC_SUBST(URIPARSERCFLAGS)
], [
_can_enable_check_curl=no
AC_MSG_WARN([Skipping curl plugin])
AC_MSG_WARN([install the uriparser library to compile this plugin (see REQUIREMENTS).])
])
dnl prerequisites met, enable the plugin
if test x$_can_enable_check_curl = xyes; then
EXTRAS="$EXTRAS check_curl\$(EXEEXT)"
fi
AC_CONFIG_FILES([plugins/picohttpparser/Makefile])
dnl Fallback to who(1) if the system doesn't provide an utmpx(5) interface
if test "$ac_cv_header_utmpx_h" = "no" -a "$ac_cv_header_wtsapi32_h" = "no"
then
@ -747,6 +783,16 @@ dnl ac_cv_ps_format=["%*s %d %d %d %d %*d %*d %d %d%*[ 0123456789abcdef]%[OSRZT
dnl ac_cv_ps_cols=8
dnl AC_MSG_RESULT([$ac_cv_ps_command])
dnl This one is the exact same test as the next one but includes etime
elif ps axwo 'stat comm vsz rss user uid pid ppid etime args' 2>/dev/null | \
egrep -i ["^ *STAT +[UCOMAND]+ +VSZ +RSS +USER +UID +PID +PPID +ELAPSED +COMMAND"] > /dev/null
then
ac_cv_ps_varlist="[procstat,&procuid,&procpid,&procppid,&procvsz,&procrss,&procpcpu,procetime,procprog,&pos]"
ac_cv_ps_command="$PATH_TO_PS axwo 'stat uid pid ppid vsz rss pcpu etime comm args'"
ac_cv_ps_format="%s %d %d %d %d %d %f %s %s %n"
ac_cv_ps_cols=10
AC_MSG_RESULT([$ac_cv_ps_command])
dnl Some gnu/linux systems (debian for one) don't like -axwo and need axwo.
dnl so test for this first...
elif ps axwo 'stat comm vsz rss user uid pid ppid args' 2>/dev/null | \
@ -1016,6 +1062,10 @@ if test -n "$ac_cv_ps_varlist" ; then
AC_DEFINE(PS_USES_PROCETIME,"yes",
[Whether the ps utility uses the "procetime" field])
fi
if echo "$ac_cv_ps_varlist" | grep "procpcpu" >/dev/null; then
AC_DEFINE(PS_USES_PROCPCPU,"yes",
[Whether the ps utility uses the "procpcpu" field])
fi
fi
AC_PATH_PROG(PATH_TO_PING,ping)
@ -1060,6 +1110,14 @@ then
ac_cv_ping_packets_first=yes
AC_MSG_RESULT([$with_ping_command])
elif $PATH_TO_PING -4 -n -U -w 10 -c 1 127.0.0.1 2>/dev/null | \
egrep -i "^round-trip|^rtt" >/dev/null
then
# check if -4 is supported - issue #1550
with_ping_command="$PATH_TO_PING -4 -n -U -w %d -c %d %s"
ac_cv_ping_packets_first=yes
ac_cv_ping_has_timeout=yes
AC_MSG_RESULT([$with_ping_command])
elif $PATH_TO_PING -n -U -w 10 -c 1 127.0.0.1 2>/dev/null | \
egrep -i "^round-trip|^rtt" >/dev/null
then
@ -1882,4 +1940,5 @@ ACX_FEATURE([enable],[perl-modules])
ACX_FEATURE([with],[cgiurl])
ACX_FEATURE([with],[trusted-path])
ACX_FEATURE([enable],[libtap])
ACX_FEATURE([with],[libcurl])
ACX_FEATURE([with],[uriparser])

View file

@ -11,14 +11,14 @@ Before you start
- Check Travis CI status.
- Update local Git repository to the current `master` tip. For a
maintenance release (e.g., version 2.2.2), update to the current
`maint-2.2` tip, instead.
maintenance release (e.g., version 2.3.2), update to the current
`maint-2.3` tip, instead.
Prepare and commit files
------------------------
- Update `configure.ac` and `NP-VERSION-GEN` with new version.
- Update `NEWS` from `git log --reverse v2.2.1..` output, and specify
- Update `NEWS` from `git log --reverse v2.3.1..` output, and specify
the release version/date.
- Update `AUTHORS` if there are new team members.
- Update `THANKS.in` using `tools/update-thanks`.
@ -29,27 +29,27 @@ Prepare and commit files
Create annotated tag
--------------------
git tag -a -m 'Monitoring Plugins 2.3' v2.3
git tag -a -m 'Monitoring Plugins 2.4' v2.4
Push the code and tag to GitHub
-------------------------------
git push monitoring-plugins master
git push monitoring-plugins v2.3
git push monitoring-plugins v2.4
Create new maintenance branch
-----------------------------
_Only necessary when creating a feature release._
git checkout -b maint-2.3 v2.3
git push -u monitoring-plugins maint-2.3
git checkout -b maint-2.4 v2.4
git push -u monitoring-plugins maint-2.4
Checkout new version
--------------------
rm -rf /tmp/plugins
git archive --prefix=tmp/plugins/ v2.3 | (cd /; tar -xf -)
git archive --prefix=tmp/plugins/ v2.4 | (cd /; tar -xf -)
Build the tarball
-----------------
@ -62,26 +62,26 @@ Build the tarball
Upload tarball to web site
--------------------------
scp monitoring-plugins-2.3.tar.gz \
scp monitoring-plugins-2.4.tar.gz \
plugins@orwell.monitoring-plugins.org:web/download/
Generate SHA1 checksum file on web site
---------------------------------------
ssh plugins@orwell.monitoring-plugins.org \
'(cd web/download; $HOME/bin/create-checksum monitoring-plugins-2.3.tar.gz)'
'(cd web/download; $HOME/bin/create-checksum monitoring-plugins-2.4.tar.gz)'
Announce new release
--------------------
- In the site.git repository:
- Create `web/input/news/release-2-3.md`.
- Create `web/input/news/release-2-4.md`.
- Update the `plugins_release` version in `web/macros.py`.
- Commit and push the result:
git add web/input/news/release-2-3.md
git commit web/input/news/release-2-3.md web/macros.py
git add web/input/news/release-2-4.md
git commit web/input/news/release-2-4.md web/macros.py
git push origin master
- Post an announcement on (at least) the following mailing lists:
@ -93,6 +93,6 @@ Announce new release
If you want to mention the number of contributors in the announcement:
git shortlog -s v2.2.1..v2.3 | wc -l
git shortlog -s v2.3.1..v2.4 | wc -l
<!-- vim:set filetype=markdown textwidth=72: -->

View file

@ -143,6 +143,7 @@ get_fs_usage (char const *file, char const *disk, struct fs_usage *fsp)
fsp->fsu_bavail_top_bit_set = EXTRACT_TOP_BIT (vfsd.f_bavail) != 0;
fsp->fsu_files = PROPAGATE_ALL_ONES (vfsd.f_files);
fsp->fsu_ffree = PROPAGATE_ALL_ONES (vfsd.f_ffree);
fsp->fsu_favail = PROPAGATE_ALL_ONES (vfsd.f_favail);
return 0;
}
@ -174,6 +175,7 @@ get_fs_usage (char const *file, char const *disk, struct fs_usage *fsp)
fsp->fsu_bavail_top_bit_set = EXTRACT_TOP_BIT (fsd.fd_req.bfreen) != 0;
fsp->fsu_files = PROPAGATE_ALL_ONES (fsd.fd_req.gtot);
fsp->fsu_ffree = PROPAGATE_ALL_ONES (fsd.fd_req.gfree);
fsp->fsu_favail = PROPAGATE_ALL_ONES (fsd.fd_req.gfree);
#elif defined STAT_READ_FILSYS /* SVR2 */
# ifndef SUPERBOFF
@ -209,6 +211,7 @@ get_fs_usage (char const *file, char const *disk, struct fs_usage *fsp)
? UINTMAX_MAX
: (fsd.s_isize - 2) * INOPB * (fsd.s_type == Fs2b ? 2 : 1));
fsp->fsu_ffree = PROPAGATE_ALL_ONES (fsd.s_tinode);
fsp->fsu_favail = PROPAGATE_ALL_ONES (fsd.s_tinode);
#elif defined STAT_STATFS3_OSF1 /* OSF/1 */
@ -296,6 +299,7 @@ get_fs_usage (char const *file, char const *disk, struct fs_usage *fsp)
fsp->fsu_bavail_top_bit_set = EXTRACT_TOP_BIT (fsd.f_bavail) != 0;
fsp->fsu_files = PROPAGATE_ALL_ONES (fsd.f_files);
fsp->fsu_ffree = PROPAGATE_ALL_ONES (fsd.f_ffree);
fsp->fsu_favail = PROPAGATE_ALL_ONES (fsd.f_ffree);
#endif
@ -323,6 +327,7 @@ statfs (char *file, struct statfs *fsb)
fsb->f_bavail = fsd.du_tfree;
fsb->f_files = (fsd.du_isize - 2) * fsd.du_inopb;
fsb->f_ffree = fsd.du_tinode;
fsb->f_favail = fsd.du_tinode;
fsb->f_fsid.val[0] = fsd.du_site;
fsb->f_fsid.val[1] = fsd.du_pckno;
return 0;

View file

@ -32,7 +32,8 @@ struct fs_usage
uintmax_t fsu_bavail; /* Free blocks available to non-superuser. */
bool fsu_bavail_top_bit_set; /* 1 if fsu_bavail represents a value < 0. */
uintmax_t fsu_files; /* Total file nodes. */
uintmax_t fsu_ffree; /* Free file nodes. */
uintmax_t fsu_ffree; /* Free file nodes to superuser. */
uintmax_t fsu_favail; /* Free file nodes to non-superuser. */
};
int get_fs_usage (char const *file, char const *disk, struct fs_usage *fsp);

View file

@ -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 ) {
@ -87,10 +90,13 @@ void _get_monitoring_plugin( monitoring_plugin **pointer ){
void
die (int result, const char *fmt, ...)
{
va_list ap;
va_start (ap, fmt);
vprintf (fmt, ap);
va_end (ap);
if(fmt!=NULL) {
va_list ap;
va_start (ap, fmt);
vprintf (fmt, ap);
va_end (ap);
}
if(this_monitoring_plugin!=NULL) {
np_cleanup();
}
@ -122,6 +128,7 @@ range
temp_range->end = 0;
temp_range->end_infinity = TRUE;
temp_range->alert_on = OUTSIDE;
temp_range->text = strdup(str);
if (str[0] == '@') {
temp_range->alert_on = INSIDE;
@ -356,6 +363,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
@ -684,4 +707,3 @@ void np_state_write_string(time_t data_time, char *data_string) {
np_free(temp_file);
}

View file

@ -23,6 +23,7 @@ typedef struct range_struct {
double end;
int end_infinity;
int alert_on; /* OUTSIDE (default) or INSIDE */
char* text; /* original unparsed text input */
} range;
typedef struct thresholds_struct {
@ -61,6 +62,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 +112,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_ */

View file

@ -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);
}
}

View file

@ -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_ */

View file

@ -69,6 +69,8 @@ np_add_parameter(struct parameter_list **list, const char *name)
new_path->dtotal_units = 0;
new_path->inodes_total = 0;
new_path->inodes_free = 0;
new_path->inodes_free_to_root = 0;
new_path->inodes_used = 0;
new_path->dused_inodes_percent = 0;
new_path->dfree_inodes_percent = 0;

View file

@ -24,9 +24,10 @@ struct parameter_list
char *group;
struct mount_entry *best_match;
struct parameter_list *name_next;
uintmax_t total, available, available_to_root, used, inodes_free, inodes_total;
uintmax_t total, available, available_to_root, used,
inodes_free, inodes_free_to_root, inodes_used, inodes_total;
double dfree_pct, dused_pct;
double dused_units, dfree_units, dtotal_units;
uint64_t dused_units, dfree_units, dtotal_units;
double dused_inodes_percent, dfree_inodes_percent;
};

272
m4/libcurl.m4 Normal file
View file

@ -0,0 +1,272 @@
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
# / __| | | | |_) | |
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
# Copyright (C) 2006, David Shaw <dshaw@jabberwocky.com>
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at https://curl.haxx.se/docs/copyright.html.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is
# furnished to do so, under the terms of the COPYING file.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
###########################################################################
# LIBCURL_CHECK_CONFIG ([DEFAULT-ACTION], [MINIMUM-VERSION],
# [ACTION-IF-YES], [ACTION-IF-NO])
# ----------------------------------------------------------
# David Shaw <dshaw@jabberwocky.com> May-09-2006
#
# Checks for libcurl. DEFAULT-ACTION is the string yes or no to
# specify whether to default to --with-libcurl or --without-libcurl.
# If not supplied, DEFAULT-ACTION is yes. MINIMUM-VERSION is the
# minimum version of libcurl to accept. Pass the version as a regular
# version number like 7.10.1. If not supplied, any version is
# accepted. ACTION-IF-YES is a list of shell commands to run if
# libcurl was successfully found and passed the various tests.
# ACTION-IF-NO is a list of shell commands that are run otherwise.
# Note that using --without-libcurl does run ACTION-IF-NO.
#
# This macro #defines HAVE_LIBCURL if a working libcurl setup is
# found, and sets @LIBCURL@ and @LIBCURL_CPPFLAGS@ to the necessary
# values. Other useful defines are LIBCURL_FEATURE_xxx where xxx are
# the various features supported by libcurl, and LIBCURL_PROTOCOL_yyy
# where yyy are the various protocols supported by libcurl. Both xxx
# and yyy are capitalized. See the list of AH_TEMPLATEs at the top of
# the macro for the complete list of possible defines. Shell
# variables $libcurl_feature_xxx and $libcurl_protocol_yyy are also
# defined to 'yes' for those features and protocols that were found.
# Note that xxx and yyy keep the same capitalization as in the
# curl-config list (e.g. it's "HTTP" and not "http").
#
# Users may override the detected values by doing something like:
# LIBCURL="-lcurl" LIBCURL_CPPFLAGS="-I/usr/myinclude" ./configure
#
# For the sake of sanity, this macro assumes that any libcurl that is
# found is after version 7.7.2, the first version that included the
# curl-config script. Note that it is very important for people
# packaging binary versions of libcurl to include this script!
# Without curl-config, we can only guess what protocols are available,
# or use curl_version_info to figure it out at runtime.
AC_DEFUN([LIBCURL_CHECK_CONFIG],
[
AH_TEMPLATE([LIBCURL_FEATURE_SSL],[Defined if libcurl supports SSL])
AH_TEMPLATE([LIBCURL_FEATURE_KRB4],[Defined if libcurl supports KRB4])
AH_TEMPLATE([LIBCURL_FEATURE_IPV6],[Defined if libcurl supports IPv6])
AH_TEMPLATE([LIBCURL_FEATURE_LIBZ],[Defined if libcurl supports libz])
AH_TEMPLATE([LIBCURL_FEATURE_ASYNCHDNS],[Defined if libcurl supports AsynchDNS])
AH_TEMPLATE([LIBCURL_FEATURE_IDN],[Defined if libcurl supports IDN])
AH_TEMPLATE([LIBCURL_FEATURE_SSPI],[Defined if libcurl supports SSPI])
AH_TEMPLATE([LIBCURL_FEATURE_NTLM],[Defined if libcurl supports NTLM])
AH_TEMPLATE([LIBCURL_PROTOCOL_HTTP],[Defined if libcurl supports HTTP])
AH_TEMPLATE([LIBCURL_PROTOCOL_HTTPS],[Defined if libcurl supports HTTPS])
AH_TEMPLATE([LIBCURL_PROTOCOL_FTP],[Defined if libcurl supports FTP])
AH_TEMPLATE([LIBCURL_PROTOCOL_FTPS],[Defined if libcurl supports FTPS])
AH_TEMPLATE([LIBCURL_PROTOCOL_FILE],[Defined if libcurl supports FILE])
AH_TEMPLATE([LIBCURL_PROTOCOL_TELNET],[Defined if libcurl supports TELNET])
AH_TEMPLATE([LIBCURL_PROTOCOL_LDAP],[Defined if libcurl supports LDAP])
AH_TEMPLATE([LIBCURL_PROTOCOL_DICT],[Defined if libcurl supports DICT])
AH_TEMPLATE([LIBCURL_PROTOCOL_TFTP],[Defined if libcurl supports TFTP])
AH_TEMPLATE([LIBCURL_PROTOCOL_RTSP],[Defined if libcurl supports RTSP])
AH_TEMPLATE([LIBCURL_PROTOCOL_POP3],[Defined if libcurl supports POP3])
AH_TEMPLATE([LIBCURL_PROTOCOL_IMAP],[Defined if libcurl supports IMAP])
AH_TEMPLATE([LIBCURL_PROTOCOL_SMTP],[Defined if libcurl supports SMTP])
AC_ARG_WITH(libcurl,
AS_HELP_STRING([--with-libcurl=PREFIX],[look for the curl library in PREFIX/lib and headers in PREFIX/include]),
[_libcurl_with=$withval],[_libcurl_with=ifelse([$1],,[yes],[$1])])
if test "$_libcurl_with" != "no" ; then
AC_PROG_AWK
_libcurl_version_parse="eval $AWK '{split(\$NF,A,\".\"); X=256*256*A[[1]]+256*A[[2]]+A[[3]]; print X;}'"
_libcurl_try_link=yes
if test -d "$_libcurl_with" ; then
LIBCURL_CPPFLAGS="-I$withval/include"
_libcurl_ldflags="-L$withval/lib"
AC_PATH_PROG([_libcurl_config],[curl-config],[],
["$withval/bin"])
else
AC_PATH_PROG([_libcurl_config],[curl-config],[],[$PATH])
fi
if test x$_libcurl_config != "x" ; then
AC_CACHE_CHECK([for the version of libcurl],
[libcurl_cv_lib_curl_version],
[libcurl_cv_lib_curl_version=`$_libcurl_config --version | $AWK '{print $[]2}'`])
_libcurl_version=`echo $libcurl_cv_lib_curl_version | $_libcurl_version_parse`
_libcurl_wanted=`echo ifelse([$2],,[0],[$2]) | $_libcurl_version_parse`
if test $_libcurl_wanted -gt 0 ; then
AC_CACHE_CHECK([for libcurl >= version $2],
[libcurl_cv_lib_version_ok],
[
if test $_libcurl_version -ge $_libcurl_wanted ; then
libcurl_cv_lib_version_ok=yes
else
libcurl_cv_lib_version_ok=no
fi
])
fi
if test $_libcurl_wanted -eq 0 || test x$libcurl_cv_lib_version_ok = xyes ; then
if test x"$LIBCURL_CPPFLAGS" = "x" ; then
LIBCURL_CPPFLAGS=`$_libcurl_config --cflags`
fi
if test x"$LIBCURL" = "x" ; then
LIBCURL=`$_libcurl_config --libs`
# This is so silly, but Apple actually has a bug in their
# curl-config script. Fixed in Tiger, but there are still
# lots of Panther installs around.
case "${host}" in
powerpc-apple-darwin7*)
LIBCURL=`echo $LIBCURL | sed -e 's|-arch i386||g'`
;;
esac
fi
# All curl-config scripts support --feature
_libcurl_features=`$_libcurl_config --feature`
# Is it modern enough to have --protocols? (7.12.4)
if test $_libcurl_version -ge 461828 ; then
_libcurl_protocols=`$_libcurl_config --protocols`
fi
else
_libcurl_try_link=no
fi
unset _libcurl_wanted
fi
if test $_libcurl_try_link = yes ; then
# we didn't find curl-config, so let's see if the user-supplied
# link line (or failing that, "-lcurl") is enough.
LIBCURL=${LIBCURL-"$_libcurl_ldflags -lcurl"}
AC_CACHE_CHECK([whether libcurl is usable],
[libcurl_cv_lib_curl_usable],
[
_libcurl_save_cppflags=$CPPFLAGS
CPPFLAGS="$LIBCURL_CPPFLAGS $CPPFLAGS"
_libcurl_save_libs=$LIBS
LIBS="$LIBCURL $LIBS"
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <curl/curl.h>]],[[
/* Try and use a few common options to force a failure if we are
missing symbols or can't link. */
int x;
curl_easy_setopt(NULL,CURLOPT_URL,NULL);
x=CURL_ERROR_SIZE;
x=CURLOPT_WRITEFUNCTION;
x=CURLOPT_WRITEDATA;
x=CURLOPT_ERRORBUFFER;
x=CURLOPT_STDERR;
x=CURLOPT_VERBOSE;
if (x) {;}
]])],libcurl_cv_lib_curl_usable=yes,libcurl_cv_lib_curl_usable=no)
CPPFLAGS=$_libcurl_save_cppflags
LIBS=$_libcurl_save_libs
unset _libcurl_save_cppflags
unset _libcurl_save_libs
])
if test $libcurl_cv_lib_curl_usable = yes ; then
# Does curl_free() exist in this version of libcurl?
# If not, fake it with free()
_libcurl_save_cppflags=$CPPFLAGS
CPPFLAGS="$CPPFLAGS $LIBCURL_CPPFLAGS"
_libcurl_save_libs=$LIBS
LIBS="$LIBS $LIBCURL"
AC_CHECK_FUNC(curl_free,,
AC_DEFINE(curl_free,free,
[Define curl_free() as free() if our version of curl lacks curl_free.]))
CPPFLAGS=$_libcurl_save_cppflags
LIBS=$_libcurl_save_libs
unset _libcurl_save_cppflags
unset _libcurl_save_libs
AC_DEFINE(HAVE_LIBCURL,1,
[Define to 1 if you have a functional curl library.])
AC_SUBST(LIBCURL_CPPFLAGS)
AC_SUBST(LIBCURL)
for _libcurl_feature in $_libcurl_features ; do
AC_DEFINE_UNQUOTED(AS_TR_CPP(libcurl_feature_$_libcurl_feature),[1])
eval AS_TR_SH(libcurl_feature_$_libcurl_feature)=yes
done
if test "x$_libcurl_protocols" = "x" ; then
# We don't have --protocols, so just assume that all
# protocols are available
_libcurl_protocols="HTTP FTP FILE TELNET LDAP DICT TFTP"
if test x$libcurl_feature_SSL = xyes ; then
_libcurl_protocols="$_libcurl_protocols HTTPS"
# FTPS wasn't standards-compliant until version
# 7.11.0 (0x070b00 == 461568)
if test $_libcurl_version -ge 461568; then
_libcurl_protocols="$_libcurl_protocols FTPS"
fi
fi
# RTSP, IMAP, POP3 and SMTP were added in
# 7.20.0 (0x071400 == 463872)
if test $_libcurl_version -ge 463872; then
_libcurl_protocols="$_libcurl_protocols RTSP IMAP POP3 SMTP"
fi
fi
for _libcurl_protocol in $_libcurl_protocols ; do
AC_DEFINE_UNQUOTED(AS_TR_CPP(libcurl_protocol_$_libcurl_protocol),[1])
eval AS_TR_SH(libcurl_protocol_$_libcurl_protocol)=yes
done
else
unset LIBCURL
unset LIBCURL_CPPFLAGS
fi
fi
unset _libcurl_try_link
unset _libcurl_version_parse
unset _libcurl_config
unset _libcurl_feature
unset _libcurl_features
unset _libcurl_protocol
unset _libcurl_protocols
unset _libcurl_version
unset _libcurl_ldflags
fi
if test x$_libcurl_with = xno || test x$libcurl_cv_lib_curl_usable != xyes ; then
# This is the IF-NO path
ifelse([$4],,:,[$4])
else
# This is the IF-YES path
ifelse([$3],,:,[$3])
fi
unset _libcurl_with
])dnl

View file

@ -53,18 +53,34 @@ AC_DEFUN([np_mysqlclient],
_savedcppflags="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS $np_mysql_include"
dnl Putting $np_mysql_libs as other libraries ensures that all mysql dependencies are linked in
dnl Although -lmysqlclient is duplicated, it is not a problem
AC_CHECK_LIB([mysqlclient], [mysql_init], [
with_mysql=$np_mysql_config
AC_DEFINE(HAVE_MYSQLCLIENT, 1, [Defined if mysqlclient is found and can compile])
], [with_mysql=no], [$np_mysql_libs])
np_check_lib_mysqlclient
CPPFLAGS=$_savedcppflags
fi
fi
])
dnl Test mysql_init using mysqlclient
AC_DEFUN([np_check_lib_mysqlclient],
[
dnl Putting $np_mysql_libs as other libraries ensures that all mysql dependencies are linked in
dnl Although -lmysqlclient is duplicated, it is not a problem
AC_CHECK_LIB([mysqlclient], [mysql_init], [
with_mysql=$np_mysql_config
AC_DEFINE(HAVE_MYSQLCLIENT, 1, [Defined if mysqlclient is found and can compile])
], [np_check_lib_mariadbclient], [$np_mysql_libs])
])
dnl Test mysql_init using mariadbclient
AC_DEFUN([np_check_lib_mariadbclient],
[
AC_CHECK_LIB([mariadbclient], [mysql_init], [
with_mysql=$np_mysql_config
AC_DEFINE(HAVE_MYSQLCLIENT, 1, [Defined if mariadbclient is found and can compile])
], [with_mysql=no], [$np_mysql_libs])
])
dnl Will take $1, find last occurrance of -LDIR and add DIR to LD_RUN_PATH
AC_DEFUN([np_add_to_runpath],
[

140
m4/uriparser.m4 Normal file
View file

@ -0,0 +1,140 @@
# (this check is rougly based on and inspired libcurl.m4)
# URIPARSER_CHECK ([DEFAULT-ACTION], [MINIMUM-VERSION],
# [ACTION-IF-YES], [ACTION-IF-NO])
# Checks for uriparser library. DEFAULT-ACTION is the string yes or no to
# specify whether to default to --with-uriparser or --without-liburiparser.
# If not supplied, DEFAULT-ACTION is yes. MINIMUM-VERSION is the
# minimum version of uriparser to accept. Pass the version as a regular
# version number like 0.8.5. If not supplied, any version is
# accepted. ACTION-IF-YES is a list of shell commands to run if
# uriparser was successfully found and passed the various tests.
# ACTION-IF-NO is a list of shell commands that are run otherwise.
# Note that using --without-uriparser does run ACTION-IF-NO.
#
# This macro #defines HAVE_URIPARSER if a working uriparser setup is
# found, and sets @URIPARSER@ and @URIPARSER_CPPFLAGS@ to the necessary
# values.
#
# Users may override the detected values by doing something like:
# URIPARSER="-luriparser" URIPARSER_CPPFLAGS="-I/usr/myinclude" ./configure
#
AC_DEFUN([URIPARSER_CHECK],
[
AC_ARG_WITH(uriparser,
AS_HELP_STRING([--with-uriparser=PREFIX],[look for the uriparser library in PREFIX/lib and headers in PREFIX/include]),
[_uriparser_with=$withval],[_uriparser_with=ifelse([$1],,[yes],[$1])])
if test "$_uriparser_with" != "no" ; then
_uriparser_try_link=yes
AC_CHECK_PROG(PKGCONFIG,pkg-config,pkg-config,no)
if test "x$URIPARSER" != "x" || test "x$URIPARSER_CPPFLAGS" != "x"; then
:
elif test -d "$_uriparser_with" ; then
URIPARSER_CPPFLAGS="-I$withval/include"
_uriparser_ldflags="-L$withval/lib"
elif test x$PKGCONFIG != xno; then
AC_CACHE_CHECK([for the version of uriparser],
[uriparser_cv_uriparser_version],
[uriparser_cv_uriparser_version=`$PKGCONFIG liburiparser --modversion`])
AC_PROG_AWK
_uriparser_version_parse="eval $AWK '{split(\$NF,A,\".\"); X=256*256*A[[1]]+256*A[[2]]+A[[3]]; print X;}'"
_uriparser_version=`echo $uriparser_cv_uriparser_version | $_uriparser_version_parse`
_uriparser_wanted=`echo ifelse([$2],,[0],[$2]) | $_uriparser_version_parse`
if test $_uriparser_wanted -gt 0 ; then
AC_CACHE_CHECK([for uriparser >= version $2],
[uriparser_cv_lib_version_ok],
[
if test $_uriparser_version -ge $_uriparser_wanted ; then
uriparser_cv_lib_version_ok=yes
else
uriparser_cv_lib_version_ok=no
fi
])
fi
if test $_uriparser_wanted -eq 0 || test x$uriparser_cv_lib_version_ok = xyes ; then
if test x"$URIPARSER_CPPFLAGS" = "x" ; then
URIPARSER_CPPFLAGS=`$PKGCONFIG liburiparser --cflags`
fi
if test x"$URIPARSER" = "x" ; then
URIPARSER=`$PKGCONFIG liburiparser --libs`
fi
else
_uriparser_try_link=no
fi
unset _uriparser_wanted
else
dnl no pkg-config, ok, do our best and set some defaults
URIPARSER_CPPFLAGS="-I/usr/include"
URIPARSER="-luriparser -L/usr/lib -L/usr/lib64 -L/usr/lib/x86_64-linux-gnu -L/usr/lib/i686-linux-gnu"
fi
if test $_uriparser_try_link = yes ; then
# let's see if the user-supplied
# link line (or failing that, "-luriparser") is enough.
URIPARSER=${URIPARSER-"$_uriparser_ldflags -luriparser"}
AC_CACHE_CHECK([whether uriparser is usable],
[uriparser_cv_lib_uriparser_usable],
[
_liburiparser_save_cppflags=$CPPFLAGS
CPPFLAGS="$URIPARSER_CPPFLAGS $CPPFLAGS"
_liburiparser_save_libs=$LIBS
LIBS="$URIPARSER $LIBS"
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <uriparser/Uri.h>]],[[
/* Try and use a few common options to force a failure if we are
missing symbols or cannot link. */
UriParserStateA state;
UriUriA uri;
state.uri = &uri;
char *location = "http://test.dom/dir/file.ext";
int x = uriParseUriA (&state, location);
if (x == URI_SUCCESS) {;}
]])],uriparser_cv_lib_uriparser_usable=yes,uriparser_cv_lib_uriparser_usable=no)
CPPFLAGS=$_liburiparser_save_cppflags
LIBS=$_liburiparser_save_libs
unset _liburiparser_save_cppflags
unset _liburiparser_save_libs
])
if test $uriparser_cv_lib_uriparser_usable = yes ; then
AC_DEFINE(HAVE_URIPARSER,1,
[Define to 1 if you have a functional uriparser library.])
AC_SUBST(URIPARSER_CPPFLAGS)
AC_SUBST(URIPARSER)
else
unset URIPARSER
unset URIPARSER_CPPFLAGS
fi
fi
unset _uriparser_try_link
unset _uriparser_version_parse
unset _uriparser_version
unset _uriparser_ldflags
fi
if test x$_uriparser_with = xno || test x$uriparser_cv_lib_uriparser_usable != xyes ; then
# This is the IF-NO path
ifelse([$4],,:,[$4])
else
# This is the IF-YES path
ifelse([$3],,:,[$3])
fi
unset _uriparser_with
])dnl

View file

@ -37,6 +37,9 @@ TESTS = @PLUGIN_TEST@
test:
perl -I $(top_builddir) -I $(top_srcdir) ../test.pl
test-debug:
NPTEST_DEBUG=1 HARNESS_VERBOSE=1 perl -I $(top_builddir) -I $(top_srcdir) ../test.pl
setuid_root_mode = ug=rx,u+s
# /* Author Coreutils team - see ACKNOWLEDGEMENTS */

View file

@ -323,7 +323,8 @@ int get_hardware_address(int sock,char *interface_name){
#elif defined(__bsd__)
/* King 2004 see ACKNOWLEDGEMENTS */
int mib[6], len;
size_t len;
int mib[6];
char *buf;
unsigned char *ptr;
struct if_msghdr *ifm;

View file

@ -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':
@ -482,7 +502,7 @@ main(int argc, char **argv)
icmp_data_size = size;
icmp_pkt_size = size + ICMP_MINLEN;
} else
usage_va("ICMP data length must be between: %d and %d",
usage_va("ICMP data length must be between: %lu and %lu",
sizeof(struct icmp) + sizeof(struct icmp_ping_data),
MAX_PING_DATA - 1);
break;
@ -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;
@ -608,7 +672,7 @@ main(int argc, char **argv)
if(max_completion_time > (u_int)timeout * 1000000) {
printf("max_completion_time: %llu timeout: %u\n",
max_completion_time, timeout);
printf("Timout must be at lest %llu\n",
printf("Timeout must be at least %llu\n",
max_completion_time / 1000000 + 1);
}
}
@ -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,10 +1130,11 @@ 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
* conspicuosly as missing entries in perfparse and cacti */
* conspicuously as missing entries in perfparse and cacti */
pl = 100;
rta = 0;
status = STATE_CRITICAL;
@ -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;
/* disregard obviously stupid addresses */
if(in->s_addr == INADDR_NONE || in->s_addr == INADDR_ANY)
if (address_family == AF_INET)
sin = (struct sockaddr_in *)in;
else
sin6 = (struct sockaddr_in6 *)in;
/* 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) {
crash("add_target_ip(%s, %s): malloc(%d) failed",
arg, inet_ntoa(*in), sizeof(struct rta_host));
char straddr[INET6_ADDRSTRLEN];
parse_address((struct sockaddr_storage*)&in, straddr, sizeof(straddr));
crash("add_target_ip(%s, %s): malloc(%lu) failed",
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);

View file

@ -19,7 +19,7 @@ if ($allow_sudo eq "yes" or $> == 0) {
my $sudo = $> == 0 ? '' : 'sudo';
my $successOutput = '/OK: Received \d+ DHCPOFFER\(s\), \d+ of 1 requested servers responded, max lease time = \d+ sec\./';
my $failureOutput = '/CRITICAL: No DHCPOFFERs were received/';
my $failureOutput = '/CRITICAL: (No DHCPOFFERs were received|Received \d+ DHCPOFFER\(s\), 0 of 1 requested servers responded, max lease time = \d+ sec\.)/';
my $invalidOutput = '/Invalid hostname/';
my $host_responsive = getTestParameter( "NP_HOST_DHCP_RESPONSIVE",
@ -36,7 +36,12 @@ my $hostname_invalid = getTestParameter( "NP_HOSTNAME_INVALID",
# try to determince interface
my $interface = '';
if(`ifconfig -a 2>/dev/null` =~ m/^(e\w*\d+)/mx and $1 ne 'eth0') {
# find interface used for default route
if (-x '/usr/sbin/ip' and `/usr/sbin/ip route get 1.1.1.1 2>/dev/null` =~ m/\sdev\s(\S+)/) {
$interface = "-i $1";
}
elsif (`ifconfig -a 2>/dev/null` =~ m/^(e\w*\d+)/mx and $1 ne 'eth0') {
$interface = ' -i '.$1;
}

View file

@ -16,11 +16,13 @@ VPATH=$(top_srcdir) $(top_srcdir)/plugins-scripts $(top_srcdir)/plugins-scripts/
libexec_SCRIPTS = check_breeze check_disk_smb check_flexlm check_ircd \
check_log check_oracle check_rpc check_sensors check_wave \
check_ifstatus check_ifoperstatus check_mailq check_file_age \
check_uptime \
utils.sh utils.pm
EXTRA_DIST=check_breeze.pl check_disk_smb.pl check_flexlm.pl check_ircd.pl \
check_log.sh check_oracle.sh check_rpc.pl check_sensors.sh \
check_ifstatus.pl check_ifoperstatus.pl check_wave.pl check_mailq.pl check_file_age.pl \
check_uptime.pl \
utils.sh.in utils.pm.in t
EDIT = sed \

View file

@ -19,7 +19,7 @@
#
require 5.004;
use POSIX;
use POSIX qw(setsid);
use strict;
use Getopt::Long;
use vars qw($opt_P $opt_V $opt_h $opt_H $opt_s $opt_W $opt_u $opt_p $opt_w $opt_c $opt_a $verbose);
@ -28,6 +28,9 @@ use FindBin;
use lib "$FindBin::Bin";
use utils qw($TIMEOUT %ERRORS &print_revision &support &usage);
# make us session leader which makes all childs exit if we do
setsid;
sub print_help ();
sub print_usage ();
@ -175,6 +178,8 @@ my @lines = undef;
# Just in case of problems, let's not hang the monitoring system
$SIG{'ALRM'} = sub {
print "No Answer from Client\n";
$SIG{'INT'} = 'IGNORE';
kill(-2, $$);
exit $ERRORS{"UNKNOWN"};
};
alarm($TIMEOUT);

View file

@ -43,8 +43,6 @@ $ENV{'ENV'}='';
$opt_w = 240;
$opt_c = 600;
$opt_W = 0;
$opt_C = 0;
$opt_f = "";
Getopt::Long::Configure('bundling');
@ -53,10 +51,10 @@ GetOptions(
"h" => \$opt_h, "help" => \$opt_h,
"i" => \$opt_i, "ignore-missing" => \$opt_i,
"f=s" => \$opt_f, "file" => \$opt_f,
"w=f" => \$opt_w, "warning-age=f" => \$opt_w,
"W=f" => \$opt_W, "warning-size=f" => \$opt_W,
"c=f" => \$opt_c, "critical-age=f" => \$opt_c,
"C=f" => \$opt_C, "critical-size=f" => \$opt_C);
"w=s" => \$opt_w, "warning-age=s" => \$opt_w,
"W=s" => \$opt_W, "warning-size=s" => \$opt_W,
"c=s" => \$opt_c, "critical-age=s" => \$opt_c,
"C=s" => \$opt_C, "critical-size=s" => \$opt_C);
if ($opt_V) {
print_revision($PROGNAME, '@NP_VERSION@');
@ -91,18 +89,47 @@ unless (-e $opt_f) {
$st = File::stat::stat($opt_f);
$age = time - $st->mtime;
$size = $st->size;
$perfdata = "age=${age}s;${opt_w};${opt_c} size=${size}B;${opt_W};${opt_C};0";
$result = 'OK';
if (($opt_c and $age > $opt_c) or ($opt_C and $size < $opt_C)) {
$result = 'CRITICAL';
if ($opt_c !~ m/^\d+$/ or ($opt_C and $opt_C !~ m/^\d+$/)
or $opt_w !~ m/^\d+$/ or ($opt_W and $opt_W !~ m/^\d+$/)) {
# range has been specified so use M::P::R to process
require Monitoring::Plugin::Range;
# use permissive range defaults for size when none specified
$opt_W = "0:" unless ($opt_W);
$opt_C = "0:" unless ($opt_C);
if (Monitoring::Plugin::Range->parse_range_string($opt_c)
->check_range($age) == 1) { # 1 means it raises an alert because it's OUTSIDE the range
$result = 'CRITICAL';
}
elsif (Monitoring::Plugin::Range->parse_range_string($opt_C)
->check_range($size) == 1) {
$result = 'CRITICAL';
}
elsif (Monitoring::Plugin::Range->parse_range_string($opt_w)
->check_range($age) == 1) {
$result = 'WARNING';
}
elsif (Monitoring::Plugin::Range->parse_range_string($opt_W)
->check_range($size) == 1) {
$result = 'WARNING';
}
}
elsif (($opt_w and $age > $opt_w) or ($opt_W and $size < $opt_W)) {
$result = 'WARNING';
else {
# use permissive defaults for size when none specified
$opt_W = 0 unless ($opt_W);
$opt_C = 0 unless ($opt_C);
if ($age > $opt_c or $size < $opt_C) {
$result = 'CRITICAL';
}
elsif ($age > $opt_w or $size < $opt_W) {
$result = 'WARNING';
}
}
$perfdata = "age=${age}s;${opt_w};${opt_c} size=${size}B;${opt_W};${opt_C};0";
print "FILE_AGE $result: $opt_f is $age seconds old and $size bytes | $perfdata\n";
exit $ERRORS{$result};
@ -120,7 +147,15 @@ sub print_help () {
print "\n";
print " -i | --ignore-missing : return OK if the file does not exist\n";
print " <secs> File must be no more than this many seconds old (default: warn 240 secs, crit 600)\n";
print " <size> File must be at least this many bytes long (default: crit 0 bytes)\n";
print " <size> File must be at least this many bytes long (default: file size is ignored (0 bytes))\n\n";
print " Both <secs> and <size> can specify a range using the standard plugin syntax\n";
print " If any of the warning and critical arguments are in range syntax (not just bare numbers)\n";
print " then all warning and critical arguments will be interpreted as ranges.\n";
print " To use range processing the perl module Monitoring::Plugin must be installed\n";
print " For range syntax see https://www.monitoring-plugins.org/doc/guidelines.html#THRESHOLDFORMAT\n";
print " It is strongly recommended when using range syntax that all four of -w, -W, -c and -C are specified\n";
print " otherwise it is unlikely that the size test will be doing what is desired\n";
print "\n";
support();
}

View file

@ -124,10 +124,10 @@ if (!defined($session)) {
## map ifdescr to ifindex - should look at being able to cache this value
if (defined $ifdescr || defined $iftype) {
# escape "/" in ifdescr - very common in the Cisco world
if (defined $iftype) {
$status=fetch_ifindex($snmpIfType, $iftype);
} else {
# escape "/" in ifdescr - very common in the Cisco world
$ifdescr =~ s/\//\\\//g;
$status=fetch_ifindex($snmpIfDescr, $ifdescr); # if using on device with large number of interfaces
# recommend use of SNMP v2 (get-bulk)

View file

@ -69,7 +69,9 @@ $ENV{'ENV'}='';
# -----------------------------------------------------------------[ Global ]--
$PROGNAME = "check_ircd";
my $NICK="ircd$$";
# nickname shouldn't be longer than 9 chars, this might happen with large PIDs
# To prevent this, we cut of the part over 10000
my $NICK="ircd" . $$ % 10000;
my $USER_INFO="monitor localhost localhost : ";
# -------------------------------------------------------------[ connection ]--

View file

@ -1,8 +1,7 @@
#!/bin/sh
#
# Log file pattern detector plugin for monitoring
# Written by Ethan Galstad (nagios@nagios.org)
# Last Modified: 07-31-1999
# Written originally by Ethan Galstad (nagios@nagios.org)
#
# Usage: ./check_log <log_file> <old_log_file> <pattern>
#
@ -70,6 +69,11 @@ print_usage() {
echo "Usage: $PROGNAME -F logfile -O oldlog -q query"
echo "Usage: $PROGNAME --help"
echo "Usage: $PROGNAME --version"
echo ""
echo "Other parameters:"
echo " -a|--all : Print all matching lines"
echo " -p|--perl-regex : Use perl style regular expressions in the query"
echo " -e|--extended-regex : Use extended style regular expressions in the query (not necessary for GNU grep)"
}
print_help() {
@ -116,34 +120,58 @@ while test -n "$1"; do
;;
--filename)
logfile=$2
shift
shift 2
;;
-F)
logfile=$2
shift
shift 2
;;
--oldlog)
oldlog=$2
shift
shift 2
;;
-O)
oldlog=$2
shift
shift 2
;;
--query)
query=$2
shift
shift 2
;;
-q)
query=$2
shift
shift 2
;;
-x)
exitstatus=$2
shift
shift 2
;;
--exitstatus)
exitstatus=$2
shift 2
;;
--extended-regex)
ERE=1
shift
;;
-e)
ERE=1
shift
;;
--perl-regex)
PRE=1
shift
;;
-p)
PRE=1
shift
;;
--all)
ALL=1
shift
;;
-a)
ALL=1
shift
;;
*)
@ -152,9 +180,24 @@ while test -n "$1"; do
exit "$STATE_UNKNOWN"
;;
esac
shift
done
# Parameter sanity check
if [ $ERE ] && [ $PRE ] ; then
echo "Can not use extended and perl regex at the same time"
exit "$STATE_UNKNOWN"
fi
GREP="grep"
if [ $ERE ]; then
GREP="grep -E"
fi
if [ $PRE ]; then
GREP="grep -P"
fi
# If the source log file doesn't exist, exit
if [ ! -e "$logfile" ]; then
@ -180,9 +223,10 @@ fi
# The temporary file that the script should use while
# processing the log file.
if [ -x /bin/mktemp ]; then
tempdiff=$(/bin/mktemp /tmp/check_log.XXXXXXXXXX)
tempdiff=$(/bin/mktemp /tmp/check_log.XXXXXXXXXX)
else
tempdiff=$(/bin/date '+%H%M%S')
tempdiff=$(/bin/date '+%H%M%S')
tempdiff="/tmp/check_log.${tempdiff}"
touch "$tempdiff"
chmod 600 "$tempdiff"
@ -190,11 +234,21 @@ fi
diff "$logfile" "$oldlog" | grep -v "^>" > "$tempdiff"
# Count the number of matching log entries we have
count=$(grep -c "$query" "$tempdiff")
# Get the last matching entry in the diff file
lastentry=$(grep "$query" "$tempdiff" | tail -1)
if [ $ALL ]; then
# Get the last matching entry in the diff file
entry=$($GREP "$query" "$tempdiff")
# Count the number of matching log entries we have
count=$(echo "$entry" | wc -l)
else
# Count the number of matching log entries we have
count=$($GREP -c "$query" "$tempdiff")
# Get the last matching entry in the diff file
entry=$($GREP "$query" "$tempdiff" | tail -1)
fi
rm -f "$tempdiff"
cat "$logfile" > "$oldlog"
@ -203,7 +257,7 @@ if [ "$count" = "0" ]; then # no matches, exit with no error
echo "Log check ok - 0 pattern matches found"
exitstatus=$STATE_OK
else # Print total matche count and the last entry we found
echo "($count) $lastentry"
echo "($count) $entry"
exitstatus=$STATE_CRITICAL
fi

View file

@ -28,9 +28,9 @@
use POSIX;
use strict;
use Getopt::Long;
use vars qw($opt_V $opt_h $opt_v $verbose $PROGNAME $opt_w $opt_c $opt_t $opt_s
$opt_M $mailq $status $state $msg $msg_q $msg_p $opt_W $opt_C $mailq @lines
%srcdomains %dstdomains);
use vars qw($opt_V $opt_h $opt_v $verbose $PROGNAME $opt_w $opt_c $opt_t $opt_s $opt_d
$opt_M $mailq $status $state $msg $msg_q $msg_p $opt_W $opt_C $mailq $mailq_args
@lines %srcdomains %dstdomains);
use FindBin;
use lib "$FindBin::Bin";
use utils qw(%ERRORS &print_revision &support &usage );
@ -48,6 +48,8 @@ $PROGNAME = "check_mailq";
$mailq = 'sendmail'; # default
$msg_q = 0 ;
$msg_p = 0 ;
# If appended, must start with a space
$mailq_args = '' ;
$state = $ERRORS{'UNKNOWN'};
Getopt::Long::Configure('bundling');
@ -68,6 +70,10 @@ if ($opt_s) {
$sudo = "";
}
if ($opt_d) {
$mailq_args = $mailq_args . ' -C ' . $opt_d;
}
$SIG{'ALRM'} = sub {
print ("ERROR: timed out waiting for $utils::PATH_TO_MAILQ \n");
exit $ERRORS{"WARNING"};
@ -309,8 +315,8 @@ elsif ( $mailq eq "postfix" ) {
## open mailq
if ( defined $utils::PATH_TO_MAILQ && -x $utils::PATH_TO_MAILQ ) {
if (! open (MAILQ, "$sudo $utils::PATH_TO_MAILQ | " ) ) {
print "ERROR: could not open $utils::PATH_TO_MAILQ \n";
if (! open (MAILQ, "$sudo $utils::PATH_TO_MAILQ$mailq_args | " ) ) {
print "ERROR: could not open $utils::PATH_TO_MAILQ$mailq_args \n";
exit $ERRORS{'UNKNOWN'};
}
}elsif( defined $utils::PATH_TO_MAILQ){
@ -330,7 +336,7 @@ elsif ( $mailq eq "postfix" ) {
close MAILQ;
if ( $? ) {
print "CRITICAL: Error code ".($?>>8)." returned from $utils::PATH_TO_MAILQ",$/;
print "CRITICAL: Error code ".($?>>8)." returned from $utils::PATH_TO_MAILQ$mailq_args",$/;
exit $ERRORS{CRITICAL};
}
@ -343,7 +349,7 @@ elsif ( $mailq eq "postfix" ) {
}elsif ($lines[0]=~/Mail queue is empty/) {
$msg_q = 0;
}else{
print "Couldn't match $utils::PATH_TO_MAILQ output\n";
print "Couldn't match $utils::PATH_TO_MAILQ$mailq_args output\n";
exit $ERRORS{'UNKNOWN'};
}
@ -533,7 +539,7 @@ elsif ( $mailq eq "nullmailer" ) {
while (<MAILQ>) {
#2006-06-22 16:00:00 282 bytes
if (/^[1-9][0-9]*-[01][0-9]-[0-3][0-9]\s[0-2][0-9]\:[0-2][0-9]\:[0-2][0-9]\s{2}[0-9]+\sbytes$/) {
if (/^[1-9][0-9]*-[01][0-9]-[0-3][0-9]\s[0-2][0-9]\:[0-5][0-9]\:[0-5][0-9]\s+[0-9]+\sbytes/) {
$msg_q++ ;
}
}
@ -568,7 +574,10 @@ sub process_arguments(){
"w=i" => \$opt_w, "warning=i" => \$opt_w, # warning if above this number
"c=i" => \$opt_c, "critical=i" => \$opt_c, # critical if above this number
"t=i" => \$opt_t, "timeout=i" => \$opt_t,
"s" => \$opt_s, "sudo" => \$opt_s
"s" => \$opt_s, "sudo" => \$opt_s,
"d:s" => \$opt_d, "configdir:s" => \$opt_d,
"W=i" => \$opt_W, # warning if above this number
"C=i" => \$opt_C, # critical if above this number
);
if ($opt_V) {
@ -649,7 +658,7 @@ sub process_arguments(){
}
sub print_usage () {
print "Usage: $PROGNAME -w <warn> -c <crit> [-W <warn>] [-C <crit>] [-M <MTA>] [-t <timeout>] [-s] [-v]\n";
print "Usage: $PROGNAME -w <warn> -c <crit> [-W <warn>] [-C <crit>] [-M <MTA>] [-t <timeout>] [-s] [-d <CONFIGDIR>] [-v]\n";
}
sub print_help () {
@ -662,11 +671,12 @@ sub print_help () {
print " Feedback/patches to support non-sendmail mailqueue welcome\n\n";
print "-w (--warning) = Min. number of messages in queue to generate warning\n";
print "-c (--critical) = Min. number of messages in queue to generate critical alert ( w < c )\n";
print "-W (--Warning) = Min. number of messages for same domain in queue to generate warning\n";
print "-C (--Critical) = Min. number of messages for same domain in queue to generate critical alert ( W < C )\n";
print "-W = Min. number of messages for same domain in queue to generate warning\n";
print "-C = Min. number of messages for same domain in queue to generate critical alert ( W < C )\n";
print "-t (--timeout) = Plugin timeout in seconds (default = $utils::TIMEOUT)\n";
print "-M (--mailserver) = [ sendmail | qmail | postfix | exim | nullmailer ] (default = autodetect)\n";
print "-s (--sudo) = Use sudo to call the mailq command\n";
print "-d (--configdir) = Config file or directory\n";
print "-h (--help)\n";
print "-V (--version)\n";
print "-v (--verbose) = debugging output\n";

315
plugins-scripts/check_uptime.pl Executable file
View file

@ -0,0 +1,315 @@
#!@PERL@ -w
# check_uptime - check uptime to see how long the system is running.
#
# License Information:
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
# USA
#
############################################################################
use POSIX;
use strict;
use Getopt::Long;
use vars qw($opt_V $opt_h $opt_v $verbose $PROGNAME $opt_w $opt_c
$opt_f $opt_s
$lower_warn_threshold $upper_warn_threshold
$lower_crit_threshold $upper_crit_threshold
$status $state $msg);
use FindBin;
use lib "$FindBin::Bin";
use utils qw(%ERRORS &print_revision &support &usage );
sub print_help ();
sub print_usage ();
sub process_arguments ();
$ENV{'PATH'}='@TRUSTED_PATH@';
$ENV{'BASH_ENV'}='';
$ENV{'ENV'}='';
$PROGNAME = "check_uptime";
$state = $ERRORS{'UNKNOWN'};
my $uptime_file = "/proc/uptime";
# Process arguments
Getopt::Long::Configure('bundling');
$status = process_arguments();
if ($status){
print "ERROR: processing arguments\n";
exit $ERRORS{"UNKNOWN"};
}
# Get uptime info from file
if ( ! -r $uptime_file ) {
print "ERROR: file '$uptime_file' is not readable\n";
exit $ERRORS{"UNKNOWN"};
}
if ( ! open FILE, "<", $uptime_file ) {
print "ERROR: cannot read from file '$uptime_file'\n";
exit $ERRORS{"UNKNOWN"};
}
chomp( my $file_content = <FILE> );
close FILE;
print "$uptime_file: $file_content\n" if $verbose;
# Get first digit value (without fraction)
my ( $uptime_seconds ) = $file_content =~ /^([\d]+)/;
# Bail out if value is not numeric
if ( $uptime_seconds !~ /^\d+$/ ) {
print "ERROR: no numeric value: $uptime_seconds\n";
exit $ERRORS{"UNKNOWN"};
}
# Do calculations for a "pretty" format (2 weeks, 5 days, ...)
my ( $secs, $mins, $hours, $days, $weeks );
$secs = $uptime_seconds;
$mins = $hours = $days = $weeks = 0;
if ( $secs > 100 ) {
$mins = int( $secs / 60 );
$secs -= $mins * 60;
}
if ( $mins > 100 ) {
$hours = int( $mins / 60 );
$mins -= $hours * 60;
}
if ( $hours > 48 ) {
$days = int( $hours / 24 );
$hours -= $days * 24;
}
if ( $days > 14 ) {
$weeks = int( $days / 7 );
$days -= $weeks * 7;
}
my $pretty_uptime = "";
$pretty_uptime .= sprintf( "%d week%s, ", $weeks, $weeks == 1 ? "" : "s" ) if $weeks;
$pretty_uptime .= sprintf( "%d day%s, ", $days, $days == 1 ? "" : "s" ) if $days;
$pretty_uptime .= sprintf( "%d hour%s, ", $hours, $hours == 1 ? "" : "s" ) if $hours;
$pretty_uptime .= sprintf( "%d minute%s, ", $mins, $mins == 1 ? "" : "s" ) if $mins;
# Replace last occurence of comma with "and"
$pretty_uptime =~ s/, $/ and /;
# Always print the seconds (though it may be 0 seconds)
$pretty_uptime .= sprintf( "%d second%s", $secs, $secs == 1 ? "" : "s" );
# Default to catch errors in program
my $state_str = "UNKNOWN";
# Check values
my $out_of_bounds_text = "";
if ( $uptime_seconds > $upper_crit_threshold ) {
$state_str = "CRITICAL";
$out_of_bounds_text = "upper crit";
} elsif ( $uptime_seconds < $lower_crit_threshold ) {
$state_str = "CRITICAL";
$out_of_bounds_text = "lower crit";
} elsif ( $uptime_seconds > $upper_warn_threshold ) {
$state_str = "WARNING";
$out_of_bounds_text = "upper warn";
} elsif ( $uptime_seconds < $lower_warn_threshold ) {
$state_str = "WARNING";
$out_of_bounds_text = "lower warn";
} else {
$state_str = "OK";
}
$msg = "$state_str: ";
$msg .= "uptime is $uptime_seconds seconds. ";
$msg .= "Exceeds $out_of_bounds_text threshold. " if $out_of_bounds_text;
$msg .= "Running for $pretty_uptime. " if $opt_f;
if ( $opt_s ) {
my $up_since = strftime( "%Y-%m-%d %H:%M:%S", localtime( time - $uptime_seconds ) );
$msg .= "Running since $up_since. ";
}
$state = $ERRORS{$state_str};
# Perfdata support
print "$msg|uptime=${uptime_seconds}s;$upper_warn_threshold;$upper_crit_threshold;0\n";
exit $state;
#####################################
#### subs
sub process_arguments(){
GetOptions
("V" => \$opt_V, "version" => \$opt_V,
"v" => \$opt_v, "verbose" => \$opt_v,
"h" => \$opt_h, "help" => \$opt_h,
"w=s" => \$opt_w, "warning=s" => \$opt_w, # warning if above this number
"c=s" => \$opt_c, "critical=s" => \$opt_c, # critical if above this number
"f" => \$opt_f, "for" => \$opt_f, # show "running for ..."
"s" => \$opt_s, "since" => \$opt_s, # show "running since ..."
);
if ($opt_V) {
print_revision($PROGNAME,'@NP_VERSION@');
exit $ERRORS{'UNKNOWN'};
}
if ($opt_h) {
print_help();
exit $ERRORS{'UNKNOWN'};
}
if (defined $opt_v) {
$verbose = $opt_v;
}
unless ( defined $opt_w && defined $opt_c ) {
print_usage();
exit $ERRORS{'UNKNOWN'};
}
# Check if a range was supplied ("lowvalue:highvalue") for warning and critical
# Otherwise, set 0 as the lower threshold and the parameter value as upper threshold
# (the uptime should always be positive, so there should be no issue)
if ( $opt_w =~ /^(.+):(.+)$/ ) {
$lower_warn_threshold = $1;
$upper_warn_threshold = $2;
} else {
$lower_warn_threshold = 0;
$upper_warn_threshold = $opt_w;
}
if ( $opt_c =~ /^(.+):(.+)$/ ) {
$lower_crit_threshold = $1;
$upper_crit_threshold = $2;
} else {
$lower_crit_threshold = 0;
$upper_crit_threshold = $opt_c;
}
# Set as seconds (calculate if suffix present)
$lower_warn_threshold = calc_as_seconds( $lower_warn_threshold );
$lower_crit_threshold = calc_as_seconds( $lower_crit_threshold );
$upper_warn_threshold = calc_as_seconds( $upper_warn_threshold );
$upper_crit_threshold = calc_as_seconds( $upper_crit_threshold );
# Check for numeric value of warning parameter
if ( $lower_warn_threshold !~ /^\d+$/ ) {
print "Lower warning (-w) is not numeric\n";
exit $ERRORS{'UNKNOWN'};
}
if ( $upper_warn_threshold !~ /^\d+$/ ) {
print "Upper warning (-w) is not numeric\n";
exit $ERRORS{'UNKNOWN'};
}
# Check for numeric value of critical parameter
if ( $lower_crit_threshold !~ /^\d+$/ ) {
print "Lower critical (-c) is not numeric\n";
exit $ERRORS{'UNKNOWN'};
}
if ( $upper_crit_threshold !~ /^\d+$/ ) {
print "Upper critical (-c) is not numeric\n";
exit $ERRORS{'UNKNOWN'};
}
# Check boundaries
if ( $upper_warn_threshold >= $upper_crit_threshold ) {
print "Upper Warning (-w) cannot be greater than Critical (-c)!\n";
exit $ERRORS{'UNKNOWN'};
}
# No "<=" since both values are zero if no range (only upper threshold values) is given
if ( $lower_warn_threshold < $lower_crit_threshold ) {
print "Lower Warning (-w) cannot be less than Critical (-c)!\n";
exit $ERRORS{'UNKNOWN'};
}
return $ERRORS{'OK'};
}
sub print_usage () {
print "Usage: $PROGNAME -w <warn> -c <crit> [-v]\n";
}
sub print_help () {
print_revision($PROGNAME,'@NP_VERSION@');
print "Copyright (c) 2002 Subhendu Ghosh/Carlos Canau/Benjamin Schmid\n";
print "Copyright (c) 2018 Bernd Arnold\n";
print "\n";
print_usage();
print "\n";
print " Checks the uptime of the system using $uptime_file\n";
print "\n";
print "-w (--warning) = Min. number of uptime to generate warning\n";
print "-c (--critical) = Min. number of uptime to generate critical alert ( w < c )\n";
print "-f (--for) = Show uptime in a pretty format (Running for x weeks, x days, ...)\n";
print "-s (--since) = Show last boot in yyyy-mm-dd HH:MM:SS format (output from 'uptime -s')\n";
print "-h (--help)\n";
print "-V (--version)\n";
print "-v (--verbose) = debugging output\n";
print "\n\n";
print "Note: -w and -c are required arguments.\n";
print " You can suffix both values with s for seconds (default), m (minutes), h (hours), d (days) or w (weeks).\n";
print "\n";
print "Range support: You may specify a range for both warning and critical thresholds.\n";
print " This works without additional Perl modules.\n";
print "Example: ./check_uptime -w 10m:4w -c 1m:8w\n";
print " Results in a critical state when uptime is below 60 seconds or higher than 8 weeks,\n";
print " and in a warning state when uptime is below 10 minutes or above 4 weeks.\n";
print "\n\n";
support();
}
sub calc_as_seconds () {
my $parameter = shift;
# Check if suffix is present
# Calculate parameter to seconds (to get an integer value finally)
# If no suffix is present, just return the value
# Possible suffixes:
# s = seconds
# m = minutes
# h = hours
# d = days
# w = weeks
my %factor = ( "s" => 1,
"m" => 60,
"h" => 60 * 60,
"d" => 60 * 60 * 24,
"w" => 60 * 60 * 24 * 7,
);
if ( $parameter =~ /^(\d+)([a-z])$/ ) {
my $value = $1;
my $suffix = $2;
print "detected: value=$value, suffix=$suffix\n" if $verbose;
if ( ! defined $factor{$suffix} ) {
print "Error: wrong suffix ($suffix) for value '$parameter'";
exit $ERRORS{'UNKNOWN'};
}
$parameter = $value * $factor{$suffix};
}
return $parameter;
}

View file

@ -5,14 +5,14 @@
#
use strict;
use Test::More tests => 17;
use Test::More tests => 27;
use NPTest;
my $successOutput = '/^FILE_AGE OK: /';
my $warningOutput = '/^FILE_AGE WARNING: /';
my $criticalOutput = '/^FILE_AGE CRITICAL: /';
my $unknownOutput = '/^FILE_AGE UNKNOWN: /';
my $performanceOutput = '/ \| age=[0-9]+s;[0-9]+;[0-9]+ size=[0-9]+B;[0-9]+;[0-9]+;0$/';
my $performanceOutput = '/ \| age=[0-9]+s;[0-9:]+;[0-9:]+ size=[0-9]+B;[0-9:]+;[0-9:]+;0$/';
my $result;
my $temp_file = "/tmp/check_file_age.tmp";
@ -20,64 +20,75 @@ my $temp_link = "/tmp/check_file_age.link.tmp";
unlink $temp_file, $temp_link;
$result = NPTest->testCmd(
"./check_file_age"
);
$result = NPTest->testCmd("./check_file_age");
cmp_ok( $result->return_code, '==', 3, "Missing parameters" );
like ( $result->output, $unknownOutput, "Output for unknown correct" );
$result = NPTest->testCmd(
"./check_file_age -f $temp_file"
);
$result = NPTest->testCmd("./check_file_age -f $temp_file");
cmp_ok( $result->return_code, '==', 2, "File not exists" );
like ( $result->output, $criticalOutput, "Output for file missing correct" );
write_chars(100);
$result = NPTest->testCmd(
"./check_file_age -f $temp_file"
);
$result = NPTest->testCmd("./check_file_age -f $temp_file");
cmp_ok( $result->return_code, '==', 0, "File is new enough" );
like ( $result->output, $successOutput, "Output for success correct" );
sleep 2;
$result = NPTest->testCmd(
"./check_file_age -f $temp_file -w 1"
);
$result = NPTest->testCmd("./check_file_age -f $temp_file -w 1");
cmp_ok( $result->return_code, '==', 1, "Warning for file over 1 second old" );
like ( $result->output, $warningOutput, "Output for warning correct" );
$result = NPTest->testCmd(
"./check_file_age -f $temp_file -c 1"
);
$result = NPTest->testCmd("./check_file_age -f $temp_file -c 1");
cmp_ok( $result->return_code, '==', 2, "Critical for file over 1 second old" );
like ( $result->output, $criticalOutput, "Output for critical correct" );
$result = NPTest->testCmd(
"./check_file_age -f $temp_file -c 1000 -W 100"
);
$result = NPTest->testCmd("./check_file_age -f $temp_file -c 1000 -W 100");
cmp_ok( $result->return_code, '==', 0, "Checking file size" );
$result = NPTest->testCmd(
"./check_file_age -f $temp_file -c 1000 -W 100"
);
$result = NPTest->testCmd("./check_file_age -f $temp_file -c 1000 -W 100");
like( $result->output, $performanceOutput, "Checking for performance Output" );
$result = NPTest->testCmd(
"./check_file_age -f /non/existent --ignore-missing"
);
$result = NPTest->testCmd("./check_file_age -f $temp_file -c 1000 -W 100");
like( $result->output, $performanceOutput, "Checking for performance Output from range" );
$result = NPTest->testCmd("./check_file_age -f /non/existent --ignore-missing");
cmp_ok( $result->return_code, '==', 0, "Honours --ignore-missing" );
$result = NPTest->testCmd(
"./check_file_age -f $temp_file -c 1000 -W 101"
);
$result = NPTest->testCmd("./check_file_age -f $temp_file -c 1000 -W 101");
cmp_ok( $result->return_code, '==', 1, "One byte too short" );
$result = NPTest->testCmd(
"./check_file_age -f $temp_file -c 1000 -C 101"
);
$result = NPTest->testCmd("./check_file_age -f $temp_file -c 1000 -C 101");
cmp_ok( $result->return_code, '==', 2, "One byte too short - critical" );
SKIP: {
eval 'use Monitoring::Plugin::Range';
skip "Monitoring::Plugin::Range module require", 9 if $@;
$result = NPTest->testCmd("./check_file_age -f $temp_file -w 0:1");
cmp_ok( $result->return_code, '==', 1, "Warning for file over 1 second old by range" );
like ( $result->output, $warningOutput, "Output for warning by range correct" );
$result = NPTest->testCmd("./check_file_age -f $temp_file -c 0:1");
cmp_ok( $result->return_code, '==', 2, "Critical for file over 1 second old by range" );
like ( $result->output, $criticalOutput, "Output for critical by range correct" );
$result = NPTest->testCmd("./check_file_age -f $temp_file -c 0:1000 -W 0:100");
cmp_ok( $result->return_code, '==', 0, "Checking file size by range" );
$result = NPTest->testCmd("./check_file_age -f $temp_file -c 1000 -W 101:");
cmp_ok( $result->return_code, '==', 1, "One byte too short by range" );
$result = NPTest->testCmd("./check_file_age -f $temp_file -c 1000 -W 0:99");
cmp_ok( $result->return_code, '==', 1, "One byte too long by range" );
$result = NPTest->testCmd("./check_file_age -f $temp_file -c 1000 -C 101:");
cmp_ok( $result->return_code, '==', 2, "One byte too short by range - critical" );
$result = NPTest->testCmd("./check_file_age -f $temp_file -c 1000 -C 0:99");
cmp_ok( $result->return_code, '==', 2, "One byte too long by range - critical" );
};
symlink $temp_file, $temp_link or die "Cannot create symlink";
$result = NPTest->testCmd("./check_file_age -f $temp_link -c 10");
cmp_ok( $result->return_code, '==', 0, "Works for symlinks" );

View file

@ -0,0 +1,129 @@
#!/usr/bin/perl -w -I ..
#
# check_uptime tests
#
#
use strict;
use Test::More tests => 40;
use NPTest;
my $result;
$result = NPTest->testCmd(
"./check_uptime"
);
cmp_ok( $result->return_code, '==', 3, "Missing parameters" );
like ( $result->output, '/^Usage: check_uptime -w/', "Output for missing parameters correct" );
$result = NPTest->testCmd(
"./check_uptime --help"
);
cmp_ok( $result->return_code, '==', 3, "Help output requested" );
like ( $result->output, '/ABSOLUTELY NO WARRANTY/', "Output for help correct" );
$result = NPTest->testCmd(
"./check_uptime -w 5 -c 2"
);
cmp_ok( $result->return_code, '==', 3, "Warning greater than critical" );
like ( $result->output, '/^Upper Warning .*cannot be greater than Critical/', "Output for warning greater than critical correct" );
$result = NPTest->testCmd(
"./check_uptime -c 1000 -W 100 2>&1"
);
like ( $result->output, '/^Unknown option: W/', "Output with wrong parameter is correct" );
$result = NPTest->testCmd(
"./check_uptime -f -w 1 -c 2"
);
cmp_ok( $result->return_code, '==', 2, "Uptime higher than 2 seconds" );
like ( $result->output, '/Running for \d+/', "Output for the f parameter correct" );
$result = NPTest->testCmd(
"./check_uptime -s -w 1 -c 2"
);
cmp_ok( $result->return_code, '==', 2, "Uptime higher than 2 seconds" );
like ( $result->output, '/Running since \d+/', "Output for the s parameter correct" );
$result = NPTest->testCmd(
"./check_uptime -w 1 -c 2"
);
cmp_ok( $result->return_code, '==', 2, "Uptime higher than 2 seconds" );
like ( $result->output, '/^CRITICAL: uptime is \d+ seconds/', "Output for uptime higher than 2 seconds correct" );
$result = NPTest->testCmd(
"./check_uptime -w 1 -c 9999w"
);
cmp_ok( $result->return_code, '==', 1, "Uptime lower than 9999 weeks" );
like ( $result->output, '/^WARNING: uptime is \d+ seconds/', "Output for uptime lower than 9999 weeks correct" );
$result = NPTest->testCmd(
"./check_uptime -w 9998w -c 9999w"
);
cmp_ok( $result->return_code, '==', 0, "Uptime lower than 9998 weeks" );
like ( $result->output, '/^OK: uptime is \d+ seconds/', "Output for uptime lower than 9998 weeks correct" );
like ( $result->output, '/\|uptime=[0-9]+s;6046790400;6047395200;/', "Checking for performance output" );
$result = NPTest->testCmd(
"./check_uptime -w 111222d -c 222333d"
);
cmp_ok( $result->return_code, '==', 0, "Uptime lower than 111222 days" );
like ( $result->output, '/^OK: uptime is \d+ seconds/', "Output for uptime lower than 111222 days correct" );
like ( $result->output, '/\|uptime=[0-9]+s;9609580800;19209571200;/', "Checking for performance output" );
# Same as before, hopefully uptime is higher than 2 seconds so no warning
$result = NPTest->testCmd(
"./check_uptime -w 2:111222d -c 1:222333d"
);
cmp_ok( $result->return_code, '==', 0, "Uptime lower than 111222 days, and higher 2 seconds" );
like ( $result->output, '/^OK: uptime is \d+ seconds/', "Output for uptime lower than 111222 days, and higher 2 seconds correct" );
like ( $result->output, '/\|uptime=[0-9]+s;9609580800;19209571200;/', "Checking for performance output" );
# Same as before, now the low warning should trigger
$result = NPTest->testCmd(
"./check_uptime -w 111221d:111222d -c 1:222333d"
);
cmp_ok( $result->return_code, '==', 1, "Uptime lower than 111221 days raises warning" );
like ( $result->output, '/^WARNING: uptime is \d+ seconds/', "Output for uptime lower than 111221 days correct" );
like ( $result->output, '/Exceeds lower warn threshold/', "Exceeds text correct" );
like ( $result->output, '/\|uptime=[0-9]+s;9609580800;19209571200;/', "Checking for performance output" );
# Same as before, now the low critical should trigger
$result = NPTest->testCmd(
"./check_uptime -w 111221d:111222d -c 111220d:222333d"
);
cmp_ok( $result->return_code, '==', 2, "Uptime lower than 111220 days raises critical" );
like ( $result->output, '/^CRITICAL: uptime is \d+ seconds/', "Output for uptime lower than 111220 days correct" );
like ( $result->output, '/Exceeds lower crit threshold/', "Exceeds text correct" );
like ( $result->output, '/\|uptime=[0-9]+s;9609580800;19209571200;/', "Checking for performance output" );
#
# Range values using ":" without two parts ("a:b") is invalid
# Strings without two parts are always considered as upper threshold
#
$result = NPTest->testCmd(
"./check_uptime -w 2: -c 1:4"
);
cmp_ok( $result->return_code, '==', 3, "Wrong parameter format raises unknown" );
like ( $result->output, '/^Upper warning .* is not numeric/', "Output for wrong parameter format correct" );
$result = NPTest->testCmd(
"./check_uptime -w 2:3 -c 1:"
);
cmp_ok( $result->return_code, '==', 3, "Wrong parameter format raises unknown" );
like ( $result->output, '/^Upper critical .* is not numeric/', "Output for wrong parameter format correct" );
$result = NPTest->testCmd(
"./check_uptime -w :3 -c 1:4"
);
cmp_ok( $result->return_code, '==', 3, "Wrong parameter format raises unknown" );
like ( $result->output, '/^Upper warning .* is not numeric/', "Output for wrong parameter format correct" );
$result = NPTest->testCmd(
"./check_uptime -w 2:3 -c :4"
);
cmp_ok( $result->return_code, '==', 3, "Wrong parameter format raises unknown" );
like ( $result->output, '/^Upper critical .* is not numeric/', "Output for wrong parameter format correct" );

View file

@ -10,6 +10,7 @@ use strict;
use Test::More;
use NPTest;
use lib ".";
use lib "..";
use utils;

View file

@ -38,7 +38,9 @@ check_tcp_programs = check_ftp check_imap check_nntp check_pop \
EXTRA_PROGRAMS = check_mysql check_radius check_pgsql check_snmp check_hpjd \
check_swap check_fping check_ldap check_game check_dig \
check_nagios check_by_ssh check_dns check_nt check_ide_smart \
check_procs check_mysql_query check_apt check_dbi
check_procs check_mysql_query check_apt check_dbi check_curl
SUBDIRS = picohttpparser
EXTRA_DIST = t tests
@ -69,6 +71,9 @@ test-debug:
check_apt_LDADD = $(BASEOBJS)
check_cluster_LDADD = $(BASEOBJS)
check_curl_CFLAGS = $(AM_CFLAGS) $(LIBCURLCFLAGS) $(URIPARSERCFLAGS) $(LIBCURLINCLUDE) $(URIPARSERINCLUDE) -Ipicohttpparser
check_curl_CPPFLAGS = $(AM_CPPFLAGS) $(LIBCURLCFLAGS) $(URIPARSERCFLAGS) $(LIBCURLINCLUDE) $(URIPARSERINCLUDE) -Ipicohttpparser
check_curl_LDADD = $(NETLIBS) $(LIBCURLLIBS) $(SSLOBJS) $(URIPARSERLIBS) picohttpparser/libpicohttpparser.a
check_dbi_LDADD = $(NETLIBS) $(DBILIBS)
check_dig_LDADD = $(NETLIBS)
check_disk_LDADD = $(BASEOBJS)
@ -89,7 +94,7 @@ check_mysql_query_CFLAGS = $(AM_CFLAGS) $(MYSQLCFLAGS)
check_mysql_query_CPPFLAGS = $(AM_CPPFLAGS) $(MYSQLINCLUDE)
check_mysql_query_LDADD = $(NETLIBS) $(MYSQLLIBS)
check_nagios_LDADD = $(BASEOBJS)
check_nt_LDADD = $(NETLIBS)
check_nt_LDADD = $(NETLIBS)
check_ntp_LDADD = $(NETLIBS) $(MATHLIBS)
check_ntp_peer_LDADD = $(NETLIBS) $(MATHLIBS)
check_nwstat_LDADD = $(NETLIBS)

View file

@ -66,12 +66,17 @@ char* construct_cmdline(upgrade_type u, const char *opts);
/* run an apt-get update */
int run_update(void);
/* run an apt-get upgrade */
int run_upgrade(int *pkgcount, int *secpkgcount);
int run_upgrade(int *pkgcount, int *secpkgcount, char ***pkglist, char ***secpkglist);
/* add another clause to a regexp */
char* add_to_regexp(char *expr, const char *next);
/* extract package name from Inst line */
char* pkg_name(char *line);
/* string comparison function for qsort */
int cmpstringp(const void *p1, const void *p2);
/* configuration variables */
static int verbose = 0; /* -v */
static int list = 0; /* list packages available for upgrade */
static int do_update = 0; /* whether to call apt-get update */
static int only_critical = 0; /* whether to warn about non-critical updates */
static upgrade_type upgrade = UPGRADE; /* which type of upgrade to do */
@ -81,13 +86,16 @@ static char *do_include = NULL; /* regexp to only include certain packages */
static char *do_exclude = NULL; /* regexp to only exclude certain packages */
static char *do_critical = NULL; /* regexp specifying critical packages */
static char *input_filename = NULL; /* input filename for testing */
/* number of packages available for upgrade to return WARNING status */
static int packages_warning = 1;
/* other global variables */
static int stderr_warning = 0; /* if a cmd issued output on stderr */
static int exec_warning = 0; /* if a cmd exited non-zero */
int main (int argc, char **argv) {
int result=STATE_UNKNOWN, packages_available=0, sec_count=0;
int result=STATE_UNKNOWN, packages_available=0, sec_count=0, i=0;
char **packages_list=NULL, **secpackages_list=NULL;
/* Parse extra opts if any */
argv=np_extra_opts(&argc, argv, progname);
@ -107,11 +115,11 @@ int main (int argc, char **argv) {
if(do_update) result = run_update();
/* apt-get upgrade */
result = max_state(result, run_upgrade(&packages_available, &sec_count));
result = max_state(result, run_upgrade(&packages_available, &sec_count, &packages_list, &secpackages_list));
if(sec_count > 0){
result = max_state(result, STATE_CRITICAL);
} else if(packages_available > 0 && only_critical == 0){
} else if(packages_available >= packages_warning && only_critical == 0){
result = max_state(result, STATE_WARNING);
} else if(result > STATE_UNKNOWN){
result = STATE_UNKNOWN;
@ -130,6 +138,18 @@ int main (int argc, char **argv) {
sec_count
);
if(list) {
qsort(secpackages_list, sec_count, sizeof(char*), cmpstringp);
qsort(packages_list, packages_available-sec_count, sizeof(char*), cmpstringp);
for(i = 0; i < sec_count; i++)
printf("%s (security)\n", secpackages_list[i]);
if (only_critical == 0) {
for(i = 0; i < packages_available - sec_count; i++)
printf("%s\n", packages_list[i]);
}
}
return result;
}
@ -146,16 +166,18 @@ int process_arguments (int argc, char **argv) {
{"upgrade", optional_argument, 0, 'U'},
{"no-upgrade", no_argument, 0, 'n'},
{"dist-upgrade", optional_argument, 0, 'd'},
{"list", no_argument, 0, 'l'},
{"include", required_argument, 0, 'i'},
{"exclude", required_argument, 0, 'e'},
{"critical", required_argument, 0, 'c'},
{"only-critical", no_argument, 0, 'o'},
{"input-file", required_argument, 0, INPUT_FILE_OPT},
{"packages-warning", required_argument, 0, 'w'},
{0, 0, 0, 0}
};
while(1) {
c = getopt_long(argc, argv, "hVvt:u::U::d::ni:e:c:o", longopts, NULL);
c = getopt_long(argc, argv, "hVvt:u::U::d::nli:e:c:ow:", longopts, NULL);
if(c == -1 || c == EOF || c == 1) break;
@ -196,6 +218,9 @@ int process_arguments (int argc, char **argv) {
if(update_opts==NULL) die(STATE_UNKNOWN, "strdup failed");
}
break;
case 'l':
list=1;
break;
case 'i':
do_include=add_to_regexp(do_include, optarg);
break;
@ -211,6 +236,9 @@ int process_arguments (int argc, char **argv) {
case INPUT_FILE_OPT:
input_filename = optarg;
break;
case 'w':
packages_warning = atoi(optarg);
break;
default:
/* print short usage statement if args not parsable */
usage5();
@ -222,7 +250,7 @@ int process_arguments (int argc, char **argv) {
/* run an apt-get upgrade */
int run_upgrade(int *pkgcount, int *secpkgcount){
int run_upgrade(int *pkgcount, int *secpkgcount, char ***pkglist, char ***secpkglist){
int i=0, result=STATE_UNKNOWN, regres=0, pc=0, spc=0;
struct output chld_out, chld_err;
regex_t ireg, ereg, sreg;
@ -278,6 +306,11 @@ int run_upgrade(int *pkgcount, int *secpkgcount){
cmdline);
}
*pkglist=malloc(sizeof(char *) * chld_out.lines);
if(!pkglist) die(STATE_UNKNOWN, "malloc failed!\n");
*secpkglist=malloc(sizeof(char *) * chld_out.lines);
if(!secpkglist) die(STATE_UNKNOWN, "malloc failed!\n");
/* parse the output, which should only consist of lines like
*
* Inst package ....
@ -302,6 +335,9 @@ int run_upgrade(int *pkgcount, int *secpkgcount){
if(regexec(&sreg, chld_out.line[i], 0, NULL, 0)==0){
spc++;
if(verbose) printf("*");
(*secpkglist)[spc-1] = pkg_name(chld_out.line[i]);
} else {
(*pkglist)[pc-spc-1] = pkg_name(chld_out.line[i]);
}
if(verbose){
printf("*%s\n", chld_out.line[i]);
@ -368,6 +404,31 @@ int run_update(void){
return result;
}
char* pkg_name(char *line){
char *start=NULL, *space=NULL, *pkg=NULL;
int len=0;
start = line + strlen(PKGINST_PREFIX);
len = strlen(start);
space = index(start, ' ');
if(space!=NULL){
len = space - start;
}
pkg=malloc(sizeof(char)*(len+1));
if(!pkg) die(STATE_UNKNOWN, "malloc failed!\n");
strncpy(pkg, start, len);
pkg[len]='\0';
return pkg;
}
int cmpstringp(const void *p1, const void *p2){
return strcmp(* (char * const *) p1, * (char * const *) p2);
}
char* add_to_regexp(char *expr, const char *next){
char *re=NULL;
@ -450,8 +511,11 @@ print_help (void)
printf (" %s\n", "-d, --dist-upgrade=OPTS");
printf (" %s\n", _("Perform a dist-upgrade instead of normal upgrade. Like with -U OPTS"));
printf (" %s\n", _("can be provided to override the default options."));
printf (" %s\n", " -n, --no-upgrade");
printf (" %s\n", "-n, --no-upgrade");
printf (" %s\n", _("Do not run the upgrade. Probably not useful (without -u at least)."));
printf (" %s\n", "-l, --list");
printf (" %s\n", _("List packages available for upgrade. Packages are printed sorted by"));
printf (" %s\n", _("name with security packages listed first."));
printf (" %s\n", "-i, --include=REGEXP");
printf (" %s\n", _("Include only packages matching REGEXP. Can be specified multiple times"));
printf (" %s\n", _("the values will be combined together. Any packages matching this list"));
@ -472,7 +536,10 @@ print_help (void)
printf (" %s\n", "-o, --only-critical");
printf (" %s\n", _("Only warn about upgrades matching the critical list. The total number"));
printf (" %s\n", _("of upgrades will be printed, but any non-critical upgrades will not cause"));
printf (" %s\n\n", _("the plugin to return WARNING status."));
printf (" %s\n", _("the plugin to return WARNING status."));
printf (" %s\n", "-w, --packages-warning");
printf (" %s\n", _("Minumum number of packages available for upgrade to return WARNING status."));
printf (" %s\n\n", _("Default is 1 package."));
printf ("%s\n\n", _("The following options require root privileges and should be used with care:"));
printf (" %s\n", "-u, --update=OPTS");
@ -490,5 +557,5 @@ void
print_usage(void)
{
printf ("%s\n", _("Usage:"));
printf ("%s [[-d|-u|-U]opts] [-n] [-t timeout]\n", progname);
printf ("%s [[-d|-u|-U]opts] [-n] [-l] [-t timeout] [-w packages-warning]\n", progname);
}

View file

@ -230,7 +230,6 @@ process_arguments (int argc, char **argv)
timeout_interval = atoi (optarg);
break;
case 'H': /* host */
host_or_die(optarg);
hostname = optarg;
break;
case 'p': /* port number */
@ -329,7 +328,6 @@ process_arguments (int argc, char **argv)
if (c <= argc) {
die (STATE_UNKNOWN, _("%s: You must provide a host name\n"), progname);
}
host_or_die(argv[c]);
hostname = argv[c++];
}

View file

@ -143,6 +143,7 @@ int main(int argc, char **argv){
int process_arguments(int argc, char **argv){
int c;
char *ptr;
int option=0;
static struct option longopts[]={
{"data", required_argument,0,'d'},
@ -188,6 +189,15 @@ int process_arguments(int argc, char **argv){
case 'd': /* data values */
data_vals=(char *)strdup(optarg);
/* validate data */
for (ptr=data_vals;ptr!=NULL;ptr+=2){
if (ptr[0]<'0' || ptr[0]>'3')
return ERROR;
if (ptr[1]=='\0')
break;
if (ptr[1]!=',')
return ERROR;
}
break;
case 'l': /* text label */

2467
plugins/check_curl.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -35,6 +35,7 @@ const char *email = "devel@monitoring-plugins.org";
#include "common.h"
#include "utils.h"
#include "utils_cmd.h"
#include "netutils.h"

View file

@ -331,7 +331,7 @@ print_help (void)
printf ("Copyright (c) 2000 Karl DeBisschop <kdebisschop@users.sourceforge.net>\n");
printf (COPYRIGHT, copyright, email);
printf (_("This plugin test the DNS service on the specified host using dig"));
printf (_("This plugin tests the DNS service on the specified host using dig"));
printf ("\n\n");

View file

@ -1,29 +1,29 @@
/*****************************************************************************
*
*
* Monitoring check_disk plugin
*
*
* License: GPL
* Copyright (c) 1999-2008 Monitoring Plugins Development Team
*
*
* Description:
*
*
* This file contains the check_disk plugin
*
*
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*
*
*
*****************************************************************************/
const char *progname = "check_disk";
@ -46,7 +46,7 @@ const char *email = "devel@monitoring-plugins.org";
#include <stdarg.h>
#include "fsusage.h"
#include "mountlist.h"
#include "intprops.h" /* necessary for TYPE_MAXIMUM */
#include "intprops.h" /* necessary for TYPE_MAXIMUM */
#if HAVE_LIMITS_H
# include <limits.h>
#endif
@ -141,6 +141,7 @@ int erronly = FALSE;
int display_mntp = FALSE;
int exact_match = FALSE;
int freespace_ignore_reserved = FALSE;
int display_inodes_perfdata = FALSE;
char *warn_freespace_units = NULL;
char *crit_freespace_units = NULL;
char *warn_freespace_percent = NULL;
@ -167,11 +168,10 @@ main (int argc, char **argv)
char *output;
char *details;
char *perf;
char *perf_ilabel;
char *preamble;
char *flag_header;
double inode_space_pct;
double warning_high_tide;
double critical_high_tide;
int temp_result;
struct mount_entry *me;
@ -186,6 +186,7 @@ main (int argc, char **argv)
output = strdup ("");
details = strdup ("");
perf = strdup ("");
perf_ilabel = strdup ("");
stat_buf = malloc(sizeof *stat_buf);
setlocale (LC_ALL, "");
@ -242,17 +243,17 @@ main (int argc, char **argv)
#ifdef __CYGWIN__
if (strncmp(path->name, "/cygdrive/", 10) != 0 || strlen(path->name) > 11)
continue;
continue;
snprintf(mountdir, sizeof(mountdir), "%s:\\", me->me_mountdir + 10);
if (GetDriveType(mountdir) != DRIVE_FIXED)
me->me_remote = 1;
me->me_remote = 1;
#endif
/* Filters */
/* Remove filesystems already seen */
if (np_seen_name(seen, me->me_mountdir)) {
continue;
}
}
np_add_name(&seen, me->me_mountdir);
if (path->group == NULL) {
@ -285,8 +286,17 @@ main (int argc, char **argv)
get_stats (path, &fsp);
if (verbose >= 3) {
printf ("For %s, used_pct=%g free_pct=%g used_units=%g free_units=%g total_units=%g used_inodes_pct=%g free_inodes_pct=%g fsp.fsu_blocksize=%llu mult=%llu\n",
me->me_mountdir, path->dused_pct, path->dfree_pct, path->dused_units, path->dfree_units, path->dtotal_units, path->dused_inodes_percent, path->dfree_inodes_percent, fsp.fsu_blocksize, mult);
printf ("For %s, used_pct=%g free_pct=%g used_units=%llu free_units=%llu total_units=%llu used_inodes_pct=%g free_inodes_pct=%g fsp.fsu_blocksize=%llu mult=%llu\n",
me->me_mountdir,
path->dused_pct,
path->dfree_pct,
path->dused_units,
path->dfree_units,
path->dtotal_units,
path->dused_inodes_percent,
path->dfree_inodes_percent,
fsp.fsu_blocksize,
mult);
}
/* Threshold comparisons */
@ -323,54 +333,79 @@ main (int argc, char **argv)
*/
/* *_high_tide must be reinitialized at each run */
warning_high_tide = UINT_MAX;
critical_high_tide = UINT_MAX;
uint64_t warning_high_tide = UINT64_MAX;
if (path->freespace_units->warning != NULL) {
warning_high_tide = path->dtotal_units - path->freespace_units->warning->end;
warning_high_tide = (path->dtotal_units - path->freespace_units->warning->end) * mult;
}
if (path->freespace_percent->warning != NULL) {
warning_high_tide = abs( min( (double) warning_high_tide, (double) (1.0 - path->freespace_percent->warning->end/100)*path->dtotal_units ));
}
if (path->freespace_units->critical != NULL) {
critical_high_tide = path->dtotal_units - path->freespace_units->critical->end;
}
if (path->freespace_percent->critical != NULL) {
critical_high_tide = abs( min( (double) critical_high_tide, (double) (1.0 - path->freespace_percent->critical->end/100)*path->dtotal_units ));
warning_high_tide = min( warning_high_tide, (uint64_t)((1.0 - path->freespace_percent->warning->end/100) * (path->dtotal_units * mult)) );
}
/* Nb: *_high_tide are unset when == UINT_MAX */
uint64_t critical_high_tide = UINT64_MAX;
if (path->freespace_units->critical != NULL) {
critical_high_tide = (path->dtotal_units - path->freespace_units->critical->end) * mult;
}
if (path->freespace_percent->critical != NULL) {
critical_high_tide = min( critical_high_tide, (uint64_t)((1.0 - path->freespace_percent->critical->end/100) * (path->dtotal_units * mult)) );
}
/* Nb: *_high_tide are unset when == UINT64_MAX */
xasprintf (&perf, "%s %s", perf,
perfdata ((!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir,
path->dused_units, units,
(warning_high_tide != UINT_MAX ? TRUE : FALSE), warning_high_tide,
(critical_high_tide != UINT_MAX ? TRUE : FALSE), critical_high_tide,
TRUE, 0,
TRUE, path->dtotal_units));
perfdata_uint64 (
(!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir,
path->dused_units * mult, "B",
(warning_high_tide == UINT64_MAX ? FALSE : TRUE), warning_high_tide,
(critical_high_tide == UINT64_MAX ? FALSE : TRUE), critical_high_tide,
TRUE, 0,
TRUE, path->dtotal_units * mult));
if (display_inodes_perfdata) {
/* *_high_tide must be reinitialized at each run */
warning_high_tide = UINT64_MAX;
critical_high_tide = UINT64_MAX;
if (path->freeinodes_percent->warning != NULL) {
warning_high_tide = llabs( min( (double) warning_high_tide, (double) (1.0 - path->freeinodes_percent->warning->end/100)*path->inodes_total ));
}
if (path->freeinodes_percent->critical != NULL) {
critical_high_tide = llabs( min( (double) critical_high_tide, (double) (1.0 - path->freeinodes_percent->critical->end/100)*path->inodes_total ));
}
xasprintf (&perf_ilabel, "%s (inodes)", (!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir);
/* Nb: *_high_tide are unset when == UINT64_MAX */
xasprintf (&perf, "%s %s", perf,
perfdata_uint64 (perf_ilabel,
path->inodes_used, "",
(warning_high_tide != UINT64_MAX ? TRUE : FALSE), warning_high_tide,
(critical_high_tide != UINT64_MAX ? TRUE : FALSE), critical_high_tide,
TRUE, 0,
TRUE, path->inodes_total));
}
if (disk_result==STATE_OK && erronly && !verbose)
continue;
if(disk_result && verbose >= 1) {
xasprintf(&flag_header, " %s [", state_text (disk_result));
} else {
xasprintf(&flag_header, "");
}
xasprintf (&output, "%s%s %s %.0f %s (%.0f%%",
output, flag_header,
(!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir,
path->dfree_units,
units,
path->dfree_pct);
if (path->dused_inodes_percent < 0) {
xasprintf(&output, "%s inode=-)%s;", output, (disk_result ? "]" : ""));
} else {
xasprintf(&output, "%s inode=%.0f%%)%s;", output, path->dfree_inodes_percent, ((disk_result && verbose >= 1) ? "]" : ""));
}
if(disk_result && verbose >= 1) {
xasprintf(&flag_header, " %s [", state_text (disk_result));
} else {
xasprintf(&flag_header, "");
}
xasprintf (&output, "%s%s %s %llu%s (%.0f%%",
output, flag_header,
(!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir,
path->dfree_units,
units,
path->dfree_pct);
if (path->dused_inodes_percent < 0) {
xasprintf(&output, "%s inode=-)%s;", output, (disk_result ? "]" : ""));
} else {
xasprintf(&output, "%s inode=%.0f%%)%s;", output, path->dfree_inodes_percent, ((disk_result && verbose >= 1) ? "]" : ""));
}
free(flag_header);
/* TODO: Need to do a similar debug line
xasprintf (&details, _("%s\n\
%.0f of %.0f %s (%.0f%% inode=%.0f%%) free on %s (type %s mounted on %s) warn:%lu crit:%lu warn%%:%.0f%% crit%%:%.0f%%"),
xasprintf (&details, _("%s\n\%.0f of %.0f %s (%.0f%% inode=%.0f%%) free on %s (type %s mounted on %s) warn:%lu crit:%lu warn%%:%.0f%% crit%%:%.0f%%"),
details, dfree_units, dtotal_units, units, dfree_pct, inode_space_pct,
me->me_devname, me->me_type, me->me_mountdir,
(unsigned long)w_df, (unsigned long)c_df, w_dfp, c_dfp);
@ -455,6 +490,7 @@ process_arguments (int argc, char **argv)
{"ignore-eregi-partition", required_argument, 0, 'I'},
{"local", no_argument, 0, 'l'},
{"stat-remote-fs", no_argument, 0, 'L'},
{"iperfdata", no_argument, 0, 'P'},
{"mountpoint", no_argument, 0, 'M'},
{"errors-only", no_argument, 0, 'e'},
{"exact-match", no_argument, 0, 'E'},
@ -477,7 +513,7 @@ process_arguments (int argc, char **argv)
strcpy (argv[c], "-t");
while (1) {
c = getopt_long (argc, argv, "+?VqhvefCt:c:w:K:W:u:p:x:X:N:mklLg:R:r:i:I:MEA", longopts, &option);
c = getopt_long (argc, argv, "+?VqhvefCt:c:w:K:W:u:p:x:X:N:mklLPg:R:r:i:I:MEA", longopts, &option);
if (c == -1 || c == EOF)
break;
@ -530,14 +566,14 @@ process_arguments (int argc, char **argv)
}
break;
case 'W': /* warning inode threshold */
case 'W': /* warning inode threshold */
if (*optarg == '@') {
warn_freeinodes_percent = optarg;
} else {
xasprintf(&warn_freeinodes_percent, "@%s", optarg);
}
break;
case 'K': /* critical inode threshold */
case 'K': /* critical inode threshold */
if (*optarg == '@') {
crit_freeinodes_percent = optarg;
} else {
@ -547,21 +583,24 @@ process_arguments (int argc, char **argv)
case 'u':
if (units)
free(units);
if (! strcmp (optarg, "bytes")) {
if (! strcasecmp (optarg, "bytes")) {
mult = (uintmax_t)1;
units = strdup ("B");
} else if (! strcmp (optarg, "kB")) {
} else if ( (! strcmp (optarg, "kB")) || (!strcmp(optarg, "KiB")) ) {
mult = (uintmax_t)1024;
units = strdup ("kB");
} else if (! strcmp (optarg, "MB")) {
units = strdup ("kiB");
} else if ( (! strcmp (optarg, "MB")) || (!strcmp(optarg, "MiB")) ) {
mult = (uintmax_t)1024 * 1024;
units = strdup ("MB");
} else if (! strcmp (optarg, "GB")) {
units = strdup ("MiB");
} else if ( (! strcmp (optarg, "GB")) || (!strcmp(optarg, "GiB")) ) {
mult = (uintmax_t)1024 * 1024 * 1024;
units = strdup ("GB");
} else if (! strcmp (optarg, "TB")) {
units = strdup ("GiB");
} else if ( (! strcmp (optarg, "TB")) || (!strcmp(optarg, "TiB")) ) {
mult = (uintmax_t)1024 * 1024 * 1024 * 1024;
units = strdup ("TB");
units = strdup ("TiB");
} else if ( (! strcmp (optarg, "PB")) || (!strcmp(optarg, "PiB")) ) {
mult = (uintmax_t)1024 * 1024 * 1024 * 1024 * 1024;
units = strdup ("PiB");
} else {
die (STATE_UNKNOWN, _("unit type %s not known\n"), optarg);
}
@ -572,19 +611,23 @@ process_arguments (int argc, char **argv)
mult = 1024;
if (units)
free(units);
units = strdup ("kB");
units = strdup ("kiB");
break;
case 'm': /* display mountpoint */
mult = 1024 * 1024;
if (units)
free(units);
units = strdup ("MB");
units = strdup ("MiB");
break;
case 'L':
stat_remote_fs = 1;
/* fallthrough */
case 'l':
show_local_fs = 1;
break;
case 'P':
display_inodes_perfdata = 1;
break;
case 'p': /* select path */
if (! (warn_freespace_units || crit_freespace_units || warn_freespace_percent ||
crit_freespace_percent || warn_usedspace_units || crit_usedspace_units ||
@ -781,7 +824,7 @@ process_arguments (int argc, char **argv)
}
if (units == NULL) {
units = strdup ("MB");
units = strdup ("MiB");
mult = (uintmax_t)1024 * 1024;
}
@ -904,6 +947,8 @@ print_help (void)
printf (" %s\n", _("Display only devices/mountpoints with errors"));
printf (" %s\n", "-f, --freespace-ignore-reserved");
printf (" %s\n", _("Don't account root-reserved blocks into freespace in perfdata"));
printf (" %s\n", "-P, --iperfdata");
printf (" %s\n", _("Display inode usage in perfdata"));
printf (" %s\n", "-g, --group=NAME");
printf (" %s\n", _("Group paths. Thresholds apply to (free-)space of all partitions together"));
printf (" %s\n", "-k, --kilobytes");
@ -993,50 +1038,59 @@ get_stats (struct parameter_list *p, struct fs_usage *fsp) {
if (p_list->group && ! (strcmp(p_list->group, p->group))) {
stat_path(p_list);
get_fs_usage (p_list->best_match->me_mountdir, p_list->best_match->me_devname, &tmpfsp);
get_path_stats(p_list, &tmpfsp);
get_path_stats(p_list, &tmpfsp);
if (verbose >= 3)
printf("Group %s: adding %llu blocks sized %llu, (%s) used_units=%g free_units=%g total_units=%g fsu_blocksize=%llu mult=%llu\n",
p_list->group, tmpfsp.fsu_bavail, tmpfsp.fsu_blocksize, p_list->best_match->me_mountdir, p_list->dused_units, p_list->dfree_units,
p_list->dtotal_units, mult);
printf("Group %s: adding %llu blocks sized %llu, (%s) used_units=%lu free_units=%llu total_units=%llu mult=%llu\n",
p_list->group,
tmpfsp.fsu_blocks,
tmpfsp.fsu_blocksize,
p_list->best_match->me_mountdir,
p_list->dused_units,
p_list->dfree_units,
p_list->dtotal_units,
mult);
/* prevent counting the first FS of a group twice since its parameter_list entry
/* prevent counting the first FS of a group twice since its parameter_list entry
* is used to carry the information of all file systems of the entire group */
if (! first) {
p->total += p_list->total;
p->available += p_list->available;
p->available_to_root += p_list->available_to_root;
p->used += p_list->used;
p->dused_units += p_list->dused_units;
p->dfree_units += p_list->dfree_units;
p->dtotal_units += p_list->dtotal_units;
p->inodes_total += p_list->inodes_total;
p->inodes_free += p_list->inodes_free;
p->inodes_free_to_root += p_list->inodes_free_to_root;
p->inodes_used += p_list->inodes_used;
}
first = 0;
}
if (verbose >= 3)
printf("Group %s now has: used_units=%g free_units=%g total_units=%g fsu_blocksize=%llu mult=%llu\n",
p->group, tmpfsp.fsu_bavail, tmpfsp.fsu_blocksize, p->best_match->me_mountdir, p->dused_units,
p->dfree_units, p->dtotal_units, mult);
if (verbose >= 3)
printf("Group %s now has: used_units=%llu free_units=%llu total_units=%llu fsu_blocksize=%llu mult=%llu\n",
p->group,
p->dused_units,
p->dfree_units,
p->dtotal_units,
tmpfsp.fsu_blocksize,
mult);
}
/* modify devname and mountdir for output */
p->best_match->me_mountdir = p->best_match->me_devname = p->group;
}
/* finally calculate percentages for either plain FS or summed up group */
p->dused_pct = calculate_percent( p->used, p->used + p->available ); /* used + available can never be > uintmax */
p->dused_pct = calculate_percent( p->used, p->used + p->available ); /* used + available can never be > uintmax */
p->dfree_pct = 100 - p->dused_pct;
p->dused_inodes_percent = calculate_percent(p->inodes_total - p->inodes_free, p->inodes_total);
p->dfree_inodes_percent = 100 - p->dused_inodes_percent;
}
void
get_path_stats (struct parameter_list *p, struct fs_usage *fsp) {
/* 2007-12-08 - Workaround for Gnulib reporting insanely high available
* space on BSD (the actual value should be negative but fsp->fsu_bavail
* is unsigned) */
p->available = fsp->fsu_bavail > fsp->fsu_bfree ? 0 : fsp->fsu_bavail;
p->available = fsp->fsu_bavail;
p->available_to_root = fsp->fsu_bfree;
p->used = fsp->fsu_blocks - fsp->fsu_bfree;
if (freespace_ignore_reserved) {
@ -1046,11 +1100,22 @@ get_path_stats (struct parameter_list *p, struct fs_usage *fsp) {
/* default behaviour : take all the blocks into account */
p->total = fsp->fsu_blocks;
}
p->dused_units = p->used*fsp->fsu_blocksize/mult;
p->dfree_units = p->available*fsp->fsu_blocksize/mult;
p->dtotal_units = p->total*fsp->fsu_blocksize/mult;
p->inodes_total = fsp->fsu_files; /* Total file nodes. */
p->inodes_free = fsp->fsu_ffree; /* Free file nodes. */
/* Free file nodes. Not sure the workaround is required, but in case...*/
p->inodes_free = fsp->fsu_favail > fsp->fsu_ffree ? 0 : fsp->fsu_favail;
p->inodes_free_to_root = fsp->fsu_ffree; /* Free file nodes for root. */
p->inodes_used = fsp->fsu_files - fsp->fsu_ffree;
if (freespace_ignore_reserved) {
/* option activated : we substract the root-reserved inodes from the total */
/* not all OS report fsp->fsu_favail, only the ones with statvfs syscall */
/* for others, fsp->fsu_ffree == fsp->fsu_favail */
p->inodes_total = fsp->fsu_files - p->inodes_free_to_root + p->inodes_free;
} else {
/* default behaviour : take all the inodes into account */
p->inodes_total = fsp->fsu_files;
}
np_add_name(&seen, p->best_match->me_mountdir);
}

View file

@ -41,7 +41,7 @@ const char *email = "devel@monitoring-plugins.org";
int process_arguments (int, char **);
int validate_arguments (void);
int error_scan (char *);
int error_scan (char *, int *);
int ip_match_cidr(const char *, const char *);
unsigned long ip2long(const char *);
void print_help (void);
@ -54,8 +54,10 @@ char ptr_server[ADDRESS_LENGTH] = "";
int verbose = FALSE;
char **expected_address = NULL;
int expected_address_cnt = 0;
int expect_nxdomain = FALSE;
int expect_authority = FALSE;
int all_match = FALSE;
thresholds *time_thresholds = NULL;
static int
@ -86,6 +88,7 @@ main (int argc, char **argv)
int parse_address = FALSE; /* This flag scans for Address: but only after Name: */
output chld_out, chld_err;
size_t i;
int is_nxdomain = FALSE;
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
@ -168,8 +171,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) {
@ -185,7 +188,7 @@ main (int argc, char **argv)
}
result = error_scan (chld_out.line[i]);
result = error_scan (chld_out.line[i], &is_nxdomain);
if (result != STATE_OK) {
msg = strchr (chld_out.line[i], ':');
if(msg) msg++;
@ -198,13 +201,20 @@ main (int argc, char **argv)
if (verbose)
puts(chld_err.line[i]);
if (error_scan (chld_err.line[i]) != STATE_OK) {
result = max_state (result, error_scan (chld_err.line[i]));
if (error_scan (chld_err.line[i], &is_nxdomain) != STATE_OK) {
result = max_state (result, error_scan (chld_err.line[i], &is_nxdomain));
msg = strchr(input_buffer, ':');
if(msg) msg++;
if(msg)
msg++;
else
msg = input_buffer;
}
}
if (is_nxdomain && !expect_nxdomain) {
die (STATE_CRITICAL, _("Domain '%s' was not found by the server\n"), query_address);
}
if (addresses) {
int i,slen;
char *adrp;
@ -228,16 +238,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';
@ -245,6 +266,16 @@ main (int argc, char **argv)
}
}
if (expect_nxdomain) {
if (!is_nxdomain) {
result = STATE_CRITICAL;
xasprintf(&msg, _("Domain '%s' was found by the server: '%s'\n"), query_address, address);
} else {
if (address != NULL) free(address);
address = "NXDOMAIN";
}
}
/* check if authoritative */
if (result == STATE_OK && expect_authority && non_authoritative) {
result = STATE_CRITICAL;
@ -324,9 +355,15 @@ ip2long(const char* src) {
}
int
error_scan (char *input_buffer)
error_scan (char *input_buffer, int *is_nxdomain)
{
const int nxdomain = strstr (input_buffer, "Non-existent") ||
strstr (input_buffer, "** server can't find") ||
strstr (input_buffer, "** Can't find") ||
strstr (input_buffer, "NXDOMAIN");
if (nxdomain) *is_nxdomain = TRUE;
/* the DNS lookup timed out */
if (strstr (input_buffer, _("Note: nslookup is deprecated and may be removed from future releases.")) ||
strstr (input_buffer, _("Consider using the `dig' or `host' programs instead. Run nslookup with")) ||
@ -336,6 +373,8 @@ error_scan (char *input_buffer)
/* DNS server is not running... */
else if (strstr (input_buffer, "No response from server"))
die (STATE_CRITICAL, _("No response from DNS %s\n"), dns_server);
else if (strstr (input_buffer, "no servers could be reached"))
die (STATE_CRITICAL, _("No response from DNS %s\n"), dns_server);
/* Host name is valid, but server doesn't have records... */
else if (strstr (input_buffer, "No records"))
@ -343,7 +382,7 @@ error_scan (char *input_buffer)
/* Connection was refused */
else if (strstr (input_buffer, "Connection refused") ||
strstr (input_buffer, "Couldn't find server") ||
strstr (input_buffer, "Couldn't find server") ||
strstr (input_buffer, "Refused") ||
(strstr (input_buffer, "** server can't find") &&
strstr (input_buffer, ": REFUSED")))
@ -357,12 +396,6 @@ error_scan (char *input_buffer)
else if (strstr (input_buffer, "No information"))
die (STATE_CRITICAL, _("No information returned by DNS server at %s\n"), dns_server);
/* Host or domain name does not exist */
else if (strstr (input_buffer, "Non-existent") ||
strstr (input_buffer, "** server can't find") ||
strstr (input_buffer,"NXDOMAIN"))
die (STATE_CRITICAL, _("Domain %s was not found by the server\n"), query_address);
/* Network is unreachable */
else if (strstr (input_buffer, "Network is unreachable"))
die (STATE_CRITICAL, _("Network is unreachable\n"));
@ -399,7 +432,9 @@ process_arguments (int argc, char **argv)
{"server", required_argument, 0, 's'},
{"reverse-server", required_argument, 0, 'r'},
{"expected-address", required_argument, 0, 'a'},
{"expect-nxdomain", no_argument, 0, 'n'},
{"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}
@ -413,7 +448,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, "hVvALnt:H:s:r:a:w:c:", long_opts, &opt_index);
if (c == -1 || c == EOF)
break;
@ -454,13 +489,33 @@ process_arguments (int argc, char **argv)
case 'a': /* expected address */
if (strlen (optarg) >= ADDRESS_LENGTH)
die (STATE_UNKNOWN, _("Input buffer overflow\n"));
expected_address = (char **)realloc(expected_address, (expected_address_cnt+1) * sizeof(char**));
expected_address[expected_address_cnt] = strdup(optarg);
expected_address_cnt++;
if (strchr(optarg, ',') != NULL) {
char *comma = strchr(optarg, ',');
while (comma != NULL) {
expected_address = (char **)realloc(expected_address, (expected_address_cnt+1) * sizeof(char**));
expected_address[expected_address_cnt] = strndup(optarg, comma - optarg);
expected_address_cnt++;
optarg = comma + 1;
comma = strchr(optarg, ',');
}
expected_address = (char **)realloc(expected_address, (expected_address_cnt+1) * sizeof(char**));
expected_address[expected_address_cnt] = strdup(optarg);
expected_address_cnt++;
} else {
expected_address = (char **)realloc(expected_address, (expected_address_cnt+1) * sizeof(char**));
expected_address[expected_address_cnt] = strdup(optarg);
expected_address_cnt++;
}
break;
case 'n': /* expect NXDOMAIN */
expect_nxdomain = TRUE;
break;
case 'A': /* expect authority */
expect_authority = TRUE;
break;
case 'L': /* all must match */
all_match = TRUE;
break;
case 'w':
warning = optarg;
break;
@ -496,8 +551,15 @@ process_arguments (int argc, char **argv)
int
validate_arguments ()
{
if (query_address[0] == 0)
if (query_address[0] == 0) {
printf ("missing --host argument\n");
return ERROR;
}
if (expected_address_cnt > 0 && expect_nxdomain) {
printf ("--expected-address and --expect-nxdomain cannot be combined\n");
return ERROR;
}
return OK;
}
@ -529,14 +591,19 @@ 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 (" -n, --expect-nxdomain\n");
printf (" %s\n", _("Expect the DNS server to return NXDOMAIN (i.e. the domain was not found)"));
printf (" %s\n", _("Cannot be used together with -a"));
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);
@ -548,5 +615,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] [-n] [-A] [-t timeout] [-w warn] [-c crit] [-L]\n", progname);
}

View file

@ -184,7 +184,7 @@ textscan (char *buf)
int status = STATE_UNKNOWN;
if (strstr (buf, "not found")) {
die (STATE_CRITICAL, _("FPING UNKNOW - %s not found\n"), server_name);
die (STATE_CRITICAL, _("FPING UNKNOWN - %s not found\n"), server_name);
}
else if (strstr (buf, "is unreachable") || strstr (buf, "Unreachable")) {

View file

@ -66,7 +66,8 @@ void print_usage (void);
char *community = NULL;
char *address = NULL;
char *port = NULL;
unsigned int port = 0;
int check_paper_out = 1;
int
main (int argc, char **argv)
@ -120,8 +121,12 @@ main (int argc, char **argv)
HPJD_GD_DOOR_OPEN, HPJD_GD_PAPER_OUTPUT, HPJD_GD_STATUS_DISPLAY);
/* get the command to run */
sprintf (command_line, "%s -OQa -m : -v 1 -c %s %s:%hd %s", PATH_TO_SNMPGET, community,
address, port, query_string);
sprintf (command_line, "%s -OQa -m : -v 1 -c %s %s:%u %s",
PATH_TO_SNMPGET,
community,
address,
port,
query_string);
/* run the command */
child_process = spopen (command_line);
@ -240,7 +245,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 +331,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 +353,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);
@ -376,11 +384,8 @@ process_arguments (int argc, char **argv)
community = strdup (DEFAULT_COMMUNITY);
}
if (port == NULL) {
if (argv[c] != NULL )
port = argv[c];
else
port = atoi (DEFAULT_PORT);
if (port == 0) {
port = atoi(DEFAULT_PORT);
}
return validate_arguments ();
@ -420,6 +425,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 +437,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);
}

View file

@ -72,7 +72,7 @@ int maximum_age = -1;
enum {
REGS = 2,
MAX_RE_SIZE = 256
MAX_RE_SIZE = 1024
};
#include "regex.h"
regex_t preg;
@ -120,12 +120,14 @@ int use_ssl = FALSE;
int use_sni = FALSE;
int verbose = FALSE;
int show_extended_perfdata = FALSE;
int show_body = FALSE;
int sd;
int min_page_len = 0;
int max_page_len = 0;
int redir_depth = 0;
int max_depth = 15;
char *http_method;
char *http_method_proxy;
char *http_post_data;
char *http_content_type;
char buffer[MAX_INPUT_BUFFER];
@ -239,6 +241,7 @@ process_arguments (int argc, char **argv)
{"use-ipv4", no_argument, 0, '4'},
{"use-ipv6", no_argument, 0, '6'},
{"extended-perfdata", no_argument, 0, 'E'},
{"show-body", no_argument, 0, 'B'},
{0, 0, 0, 0}
};
@ -259,7 +262,7 @@ process_arguments (int argc, char **argv)
}
while (1) {
c = getopt_long (argc, argv, "Vvh46t:c:w:A:k:H:P:j:T:I:a:b:d:e:p:s:R:r:u:f:C:J:K:nlLS::m:M:NE", longopts, &option);
c = getopt_long (argc, argv, "Vvh46t:c:w:A:k:H:P:j:T:I:a:b:d:e:p:s:R:r:u:f:C:J:K:nlLS::m:M:NEB", longopts, &option);
if (c == -1 || c == EOF)
break;
@ -446,6 +449,12 @@ process_arguments (int argc, char **argv)
if (http_method)
free(http_method);
http_method = strdup (optarg);
char *tmp;
if ((tmp = strstr(http_method, ":")) > 0) {
tmp[0] = '\0';
http_method = http_method;
http_method_proxy = ++tmp;
}
break;
case 'd': /* string or substring */
strncpy (header_expect, optarg, MAX_INPUT_BUFFER - 1);
@ -540,6 +549,9 @@ process_arguments (int argc, char **argv)
case 'E': /* show extended perfdata */
show_extended_perfdata = TRUE;
break;
case 'B': /* print body content after status line */
show_body = TRUE;
break;
}
}
@ -566,6 +578,9 @@ process_arguments (int argc, char **argv)
if (http_method == NULL)
http_method = strdup ("GET");
if (http_method_proxy == NULL)
http_method_proxy = strdup ("GET");
if (client_cert && !client_privkey)
usage4 (_("If you use a client certificate you must also specify a private key file"));
@ -916,6 +931,21 @@ check_http (void)
if (verbose) printf ("Entering CONNECT tunnel mode with proxy %s:%d to dst %s:%d\n", server_address, server_port, host_name, HTTPS_PORT);
asprintf (&buf, "%s %s:%d HTTP/1.1\r\n%s\r\n", http_method, host_name, HTTPS_PORT, user_agent);
if (strlen(proxy_auth)) {
base64_encode_alloc (proxy_auth, strlen (proxy_auth), &auth);
xasprintf (&buf, "%sProxy-Authorization: Basic %s\r\n", buf, auth);
}
/* optionally send any other header tag */
if (http_opt_headers_count) {
for (i = 0; i < http_opt_headers_count ; i++) {
if (force_host_header != http_opt_headers[i]) {
xasprintf (&buf, "%s%s\r\n", buf, http_opt_headers[i]);
}
}
/* This cannot be free'd here because a redirection will then try to access this and segfault */
/* Covered in a testcase in tests/check_http.t */
/* free(http_opt_headers); */
}
asprintf (&buf, "%sProxy-Connection: keep-alive\r\n", buf);
asprintf (&buf, "%sHost: %s\r\n", buf, host_name);
/* we finished our request, send empty line with CRLF */
@ -950,7 +980,7 @@ check_http (void)
if ( server_address != NULL && strcmp(http_method, "CONNECT") == 0
&& host_name != NULL && use_ssl == TRUE)
asprintf (&buf, "%s %s %s\r\n%s\r\n", "GET", server_url, host_name ? "HTTP/1.1" : "HTTP/1.0", user_agent);
asprintf (&buf, "%s %s %s\r\n%s\r\n", http_method_proxy, server_url, host_name ? "HTTP/1.1" : "HTTP/1.0", user_agent);
else
asprintf (&buf, "%s %s %s\r\n%s\r\n", http_method, server_url, host_name ? "HTTP/1.1" : "HTTP/1.0", user_agent);
@ -1140,6 +1170,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);
}
@ -1290,6 +1322,9 @@ check_http (void)
perfd_time (elapsed_time),
perfd_size (page_len));
if (show_body)
xasprintf (&msg, _("%s\n%s"), msg, page);
result = max_state_alt(get_status(elapsed_time, thlds), result);
die (result, "HTTP %s: %s\n", state_text(result), msg);
@ -1418,8 +1453,8 @@ redir (char *pos, char *status_line)
!strncmp(server_address, addr, MAX_IPV4_HOSTLENGTH) &&
(host_name && !strncmp(host_name, addr, MAX_IPV4_HOSTLENGTH)) &&
!strcmp(server_url, url))
die (STATE_WARNING,
_("HTTP WARNING - redirection creates an infinite loop - %s://%s:%d%s%s\n"),
die (STATE_CRITICAL,
_("HTTP CRITICAL - redirection creates an infinite loop - %s://%s:%d%s%s\n"),
type, addr, i, url, (display_html ? "</A>" : ""));
strcpy (server_type, type);
@ -1532,6 +1567,10 @@ print_help (void)
print_usage ();
#ifdef HAVE_SSL
printf (_("In the first form, make an HTTP request."));
printf (_("In the second form, connect to the server and check the TLS certificate."));
#endif
printf (_("NOTE: One or both of -H and -I must be specified"));
printf ("\n");
@ -1581,7 +1620,7 @@ print_help (void)
printf (" %s\n", _("URL to GET or POST (default: /)"));
printf (" %s\n", "-P, --post=STRING");
printf (" %s\n", _("URL encoded http POST data"));
printf (" %s\n", "-j, --method=STRING (for example: HEAD, OPTIONS, TRACE, PUT, DELETE, CONNECT)");
printf (" %s\n", "-j, --method=STRING (for example: HEAD, OPTIONS, TRACE, PUT, DELETE, CONNECT, CONNECT:POST)");
printf (" %s\n", _("Set HTTP method."));
printf (" %s\n", "-N, --no-body");
printf (" %s\n", _("Don't wait for document body: stop reading after headers."));
@ -1611,6 +1650,8 @@ print_help (void)
printf (" %s\n", _("Any other tags to be sent in http header. Use multiple times for additional headers"));
printf (" %s\n", "-E, --extended-perfdata");
printf (" %s\n", _("Print additional performance data"));
printf (" %s\n", "-B, --show-body");
printf (" %s\n", _("Print body content below status line"));
printf (" %s\n", "-L, --link");
printf (" %s\n", _("Wrap output in HTML link (obsoleted by urlize)"));
printf (" %s\n", "-f, --onredirect=<ok|warning|critical|follow|sticky|stickyport>");
@ -1629,7 +1670,7 @@ print_help (void)
printf ("%s\n", _("Notes:"));
printf (" %s\n", _("This plugin will attempt to open an HTTP connection with the host."));
printf (" %s\n", _("Successful connects return STATE_OK, refusals and timeouts return STATE_CRITICAL"));
printf (" %s\n", _("other errors return STATE_UNKNOWN. Successful connects, but incorrect reponse"));
printf (" %s\n", _("other errors return STATE_UNKNOWN. Successful connects, but incorrect response"));
printf (" %s\n", _("messages from the host result in STATE_WARNING return values. If you are"));
printf (" %s\n", _("checking a virtual server that uses 'host headers' you must supply the FQDN"));
printf (" %s\n", _("(fully qualified domain name) as the [host_name] argument."));
@ -1668,7 +1709,8 @@ print_help (void)
printf (" %s\n", _("all these options are needed: -I <proxy> -p <proxy-port> -u <check-url> -S(sl) -j CONNECT -H <webserver>"));
printf (" %s\n", _("a STATE_OK will be returned. When the server returns its content but exceeds"));
printf (" %s\n", _("the 5-second threshold, a STATE_WARNING will be returned. When an error occurs,"));
printf (" %s\n", _("a STATE_CRITICAL will be returned."));
printf (" %s\n", _("a STATE_CRITICAL will be returned. By adding a colon to the method you can set the method used"));
printf (" %s\n", _("inside the proxied connection: -j CONNECT:POST"));
#endif
@ -1688,6 +1730,8 @@ print_usage (void)
printf (" [-b proxy_auth] [-f <ok|warning|critcal|follow|sticky|stickyport>]\n");
printf (" [-e <expect>] [-d string] [-s string] [-l] [-r <regex> | -R <case-insensitive regex>]\n");
printf (" [-P string] [-m <min_pg_size>:<max_pg_size>] [-4|-6] [-N] [-M <age>]\n");
printf (" [-A string] [-k string] [-S <version>] [--sni] [-C <warn_age>[,<crit_age>]]\n");
printf (" [-A string] [-k string] [-S <version>] [--sni]\n");
printf (" [-T <content-type>] [-j method]\n");
printf (" %s -H <vhost> | -I <IP-address> -C <warn_age>[,<crit_age>]\n",progname);
printf (" [-p <port>] [-t <timeout>] [-4|-6] [--sni]\n");
}

View file

@ -283,7 +283,7 @@ get_offline_text (int status)
return offline_status_text[i].text;
}
}
return "UNKNOW";
return "UNKNOWN";
}

View file

@ -237,7 +237,7 @@ main (int argc, char *argv[])
if(entries_thresholds != NULL) {
if (verbose) {
printf ("entries found: %d\n", num_entries);
print_thresholds("entry threasholds", entries_thresholds);
print_thresholds("entry thresholds", entries_thresholds);
}
status_entries = get_status(num_entries, entries_thresholds);
if (status_entries == STATE_CRITICAL) {
@ -432,6 +432,9 @@ validate_arguments ()
set_thresholds(&entries_thresholds,
warn_entries, crit_entries);
}
if (ld_passwd==NULL)
ld_passwd = getenv("LDAP_PASSWORD");
return OK;
}
@ -465,7 +468,7 @@ print_help (void)
printf (" %s\n", "-D [--bind]");
printf (" %s\n", _("ldap bind DN (if required)"));
printf (" %s\n", "-P [--pass]");
printf (" %s\n", _("ldap password (if required)"));
printf (" %s\n", _("ldap password (if required, or set the password through environment variable 'LDAP_PASSWORD')"));
printf (" %s\n", "-T [--starttls]");
printf (" %s\n", _("use starttls mechanism introduced in protocol version 3"));
printf (" %s\n", "-S [--ssl]");

View file

@ -33,6 +33,7 @@ const char *copyright = "1999-2007";
const char *email = "devel@monitoring-plugins.org";
#include "common.h"
#include "runcmd.h"
#include "utils.h"
#include "popen.h"
@ -52,6 +53,9 @@ static int process_arguments (int argc, char **argv);
static int validate_arguments (void);
void print_help (void);
void print_usage (void);
static int print_top_consuming_processes();
static int n_procs_to_show = 0;
/* strictly for pretty-print usage in loops */
static const int nums[3] = { 1, 5, 15 };
@ -205,11 +209,14 @@ main (int argc, char **argv)
else if(la[i] > wload[i]) result = STATE_WARNING;
}
printf("%s - %s|", state_text(result), status_line);
printf("LOAD %s - %s|", state_text(result), status_line);
for(i = 0; i < 3; i++)
printf("load%d=%.3f;%.3f;%.3f;0; ", nums[i], la[i], wload[i], cload[i]);
putchar('\n');
if (n_procs_to_show > 0) {
print_top_consuming_processes();
}
return result;
}
@ -227,6 +234,7 @@ process_arguments (int argc, char **argv)
{"percpu", no_argument, 0, 'r'},
{"version", no_argument, 0, 'V'},
{"help", no_argument, 0, 'h'},
{"procs-to-show", required_argument, 0, 'n'},
{0, 0, 0, 0}
};
@ -234,7 +242,7 @@ process_arguments (int argc, char **argv)
return ERROR;
while (1) {
c = getopt_long (argc, argv, "Vhrc:w:", longopts, &option);
c = getopt_long (argc, argv, "Vhrc:w:n:", longopts, &option);
if (c == -1 || c == EOF)
break;
@ -255,6 +263,9 @@ process_arguments (int argc, char **argv)
case 'h': /* help */
print_help ();
exit (STATE_UNKNOWN);
case 'n':
n_procs_to_show = atoi(optarg);
break;
case '?': /* help */
usage5 ();
}
@ -324,6 +335,9 @@ print_help (void)
printf (" %s\n", _("the load average format is the same used by \"uptime\" and \"w\""));
printf (" %s\n", "-r, --percpu");
printf (" %s\n", _("Divide the load averages by the number of CPUs (when possible)"));
printf (" %s\n", "-n, --procs-to-show=NUMBER_OF_PROCS");
printf (" %s\n", _("Number of processes to show when printing the top consuming processes."));
printf (" %s\n", _("NUMBER_OF_PROCS=0 disables this feature. Default value is 0"));
printf (UT_SUPPORT);
}
@ -332,5 +346,48 @@ void
print_usage (void)
{
printf ("%s\n", _("Usage:"));
printf ("%s [-r] -w WLOAD1,WLOAD5,WLOAD15 -c CLOAD1,CLOAD5,CLOAD15\n", progname);
printf ("%s [-r] -w WLOAD1,WLOAD5,WLOAD15 -c CLOAD1,CLOAD5,CLOAD15 [-n NUMBER_OF_PROCS]\n", progname);
}
#ifdef PS_USES_PROCPCPU
int cmpstringp(const void *p1, const void *p2) {
int procuid = 0;
int procpid = 0;
int procppid = 0;
int procvsz = 0;
int procrss = 0;
float procpcpu = 0;
char procstat[8];
#ifdef PS_USES_PROCETIME
char procetime[MAX_INPUT_BUFFER];
#endif /* PS_USES_PROCETIME */
char procprog[MAX_INPUT_BUFFER];
int pos;
sscanf (* (char * const *) p1, PS_FORMAT, PS_VARLIST);
float procpcpu1 = procpcpu;
sscanf (* (char * const *) p2, PS_FORMAT, PS_VARLIST);
return procpcpu1 < procpcpu;
}
#endif /* PS_USES_PROCPCPU */
static int print_top_consuming_processes() {
int i = 0;
struct output chld_out, chld_err;
if(np_runcmd(PS_COMMAND, &chld_out, &chld_err, 0) != 0){
fprintf(stderr, _("'%s' exited with non-zero status.\n"), PS_COMMAND);
return STATE_UNKNOWN;
}
if (chld_out.lines < 2) {
fprintf(stderr, _("some error occurred getting procs list.\n"));
return STATE_UNKNOWN;
}
#ifdef PS_USES_PROCPCPU
qsort(chld_out.line + 1, chld_out.lines - 1, sizeof(char*), cmpstringp);
#endif /* PS_USES_PROCPCPU */
int lines_to_show = chld_out.lines < (n_procs_to_show + 1)
? chld_out.lines : n_procs_to_show + 1;
for (i = 0; i < lines_to_show; i += 1) {
printf("%s\n", chld_out.line[i]);
}
return OK;
}

View file

@ -379,6 +379,9 @@ process_arguments (int argc, char **argv)
if (is_host (optarg)) {
db_host = optarg;
}
else if (*optarg == '/') {
db_socket = optarg;
}
else {
usage2 (_("Invalid hostname/address"), optarg);
}

View file

@ -136,18 +136,18 @@ main (int argc, char **argv)
die (STATE_CRITICAL, "QUERY %s: Fetch row error - %s\n", _("CRITICAL"), error);
}
/* free the result */
mysql_free_result (res);
/* close the connection */
mysql_close (&mysql);
if (! is_numeric(row[0])) {
die (STATE_CRITICAL, "QUERY %s: %s - '%s'\n", _("CRITICAL"), _("Is not a numeric"), row[0]);
}
value = strtod(row[0], NULL);
/* free the result */
mysql_free_result (res);
/* close the connection */
mysql_close (&mysql);
if (verbose >= 3)
printf("mysql result: %f\n", value);

View file

@ -548,7 +548,7 @@ double jitter_request(const char *host, int *status){
DBG(print_ntp_control_message(&req));
/* Attempt to read the largest size packet possible */
req.count=htons(MAX_CM_SIZE);
DBG(printf("recieving READSTAT response"))
DBG(printf("receiving READSTAT response"))
read(conn, &req, SIZEOF_NTPCM(req));
DBG(print_ntp_control_message(&req));
/* Each peer identifier is 4 bytes in the data section, which
@ -608,7 +608,7 @@ double jitter_request(const char *host, int *status){
DBG(print_ntp_control_message(&req));
req.count = htons(MAX_CM_SIZE);
DBG(printf("recieving READVAR response...\n"));
DBG(printf("receiving READVAR response...\n"));
read(conn, &req, SIZEOF_NTPCM(req));
DBG(print_ntp_control_message(&req));

View file

@ -245,7 +245,7 @@ int ntp_request(const char *host, double *offset, int *offset_result, double *ji
do {
/* Attempt to read the largest size packet possible */
req.count=htons(MAX_CM_SIZE);
DBG(printf("recieving READSTAT response"))
DBG(printf("receiving READSTAT response"))
if(read(conn, &req, SIZEOF_NTPCM(req)) == -1)
die(STATE_CRITICAL, "NTP CRITICAL: No response from NTP server\n");
DBG(print_ntp_control_message(&req));

View file

@ -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>
@ -346,7 +347,7 @@ process_arguments (int argc, char **argv)
if (!is_pg_dbname (optarg)) /* checks length and valid chars */
usage2 (_("Database name is not valid"), optarg);
else /* we know length, and know optarg is terminated, so us strcpy */
strcpy (dbName, optarg);
snprintf(dbName, NAMEDATALEN, "%s", optarg);
break;
case 'l': /* login name */
if (!is_pg_logname (optarg))
@ -565,7 +566,7 @@ print_help (void)
printf (" %s\n", _("Typically, the monitoring user (unless the --logname option is used) should be"));
printf (" %s\n", _("able to connect to the database without a password. The plugin can also send"));
printf (" %s\n", _("a password, but no effort is made to obsure or encrypt the password."));
printf (" %s\n", _("a password, but no effort is made to obscure or encrypt the password."));
printf (UT_SUPPORT);
}

View file

@ -37,6 +37,8 @@ const char *email = "devel@monitoring-plugins.org";
#include "popen.h"
#include "utils.h"
#include <signal.h>
#define WARN_DUPLICATES "DUPLICATES FOUND! "
#define UNKNOWN_TRIP_TIME -1.0 /* -1 seconds */
@ -163,10 +165,14 @@ main (int argc, char **argv)
printf ("</A>");
/* Print performance data */
printf("|%s", fperfdata ("rta", (double) rta, "ms",
wrta>0?TRUE:FALSE, wrta,
crta>0?TRUE:FALSE, crta,
TRUE, 0, FALSE, 0));
if (pl != 100) {
printf("|%s", fperfdata ("rta", (double) rta, "ms",
wrta>0?TRUE:FALSE, wrta,
crta>0?TRUE:FALSE, crta,
TRUE, 0, FALSE, 0));
} else {
printf("| rta=U;%f;%f;;", wrta, crta);
}
printf(" %s\n", perfdata ("pl", (long) pl, "%",
wpl>0?TRUE:FALSE, wpl,
cpl>0?TRUE:FALSE, cpl,

View file

@ -1,34 +1,34 @@
/*****************************************************************************
*
*
* Monitoring check_procs plugin
*
*
* License: GPL
* Copyright (c) 2000-2008 Monitoring Plugins Development Team
*
*
* Description:
*
*
* This file contains the check_procs plugin
*
*
* Checks all processes and generates WARNING or CRITICAL states if the
* specified metric is outside the required threshold ranges. The metric
* defaults to number of processes. Search filters can be applied to limit
* the processes to check.
*
*
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*
*
*
*****************************************************************************/
const char *progname = "check_procs";
@ -50,7 +50,7 @@ const char *email = "devel@monitoring-plugins.org";
int process_arguments (int, char **);
int validate_arguments (void);
int convert_to_seconds (char *);
int convert_to_seconds (char *);
void print_help (void);
void print_usage (void);
@ -230,9 +230,9 @@ main (int argc, char **argv)
procseconds = convert_to_seconds(procetime);
if (verbose >= 3)
printf ("proc#=%d uid=%d vsz=%d rss=%d pid=%d ppid=%d pcpu=%.2f stat=%s etime=%s prog=%s args=%s\n",
printf ("proc#=%d uid=%d vsz=%d rss=%d pid=%d ppid=%d pcpu=%.2f stat=%s etime=%s prog=%s args=%s\n",
procs, procuid, procvsz, procrss,
procpid, procppid, procpcpu, procstat,
procpid, procppid, procpcpu, procstat,
procetime, procprog, procargs);
/* Ignore self */
@ -265,7 +265,7 @@ main (int argc, char **argv)
}
}
if ((options & STAT) && (strstr (statopts, procstat)))
if ((options & STAT) && (strstr (procstat, statopts)))
resultsum |= STAT;
if ((options & ARGS) && procargs && (strstr (procargs, args) != NULL))
resultsum |= ARGS;
@ -292,9 +292,9 @@ main (int argc, char **argv)
procs++;
if (verbose >= 2) {
printf ("Matched: uid=%d vsz=%d rss=%d pid=%d ppid=%d pcpu=%.2f stat=%s etime=%s prog=%s args=%s\n",
printf ("Matched: uid=%d vsz=%d rss=%d pid=%d ppid=%d pcpu=%.2f stat=%s etime=%s prog=%s args=%s\n",
procuid, procvsz, procrss,
procpid, procppid, procpcpu, procstat,
procpid, procppid, procpcpu, procstat,
procetime, procprog, procargs);
}
@ -320,7 +320,7 @@ main (int argc, char **argv)
result = max_state (result, i);
}
}
}
}
/* This should not happen */
else if (verbose) {
printf(_("Not parseable: %s"), input_buffer);
@ -332,7 +332,7 @@ main (int argc, char **argv)
return STATE_UNKNOWN;
}
if ( result == STATE_UNKNOWN )
if ( result == STATE_UNKNOWN )
result = STATE_OK;
/* Needed if procs found, but none match filter */
@ -352,9 +352,9 @@ main (int argc, char **argv)
if (metric != METRIC_PROCS) {
printf (_("%d crit, %d warn out of "), crit, warn);
}
}
}
printf (ngettext ("%d process", "%d processes", (unsigned long) procs), procs);
if (strcmp(fmt,"") != 0) {
printf (_(" with %s"), fmt);
}
@ -440,7 +440,7 @@ process_arguments (int argc, char **argv)
break;
case 'c': /* critical threshold */
critical_range = optarg;
break;
break;
case 'w': /* warning threshold */
warning_range = optarg;
break;
@ -542,11 +542,11 @@ process_arguments (int argc, char **argv)
if ( strcmp(optarg, "PROCS") == 0) {
metric = METRIC_PROCS;
break;
}
}
else if ( strcmp(optarg, "VSZ") == 0) {
metric = METRIC_VSZ;
break;
}
}
else if ( strcmp(optarg, "RSS") == 0 ) {
metric = METRIC_RSS;
break;
@ -559,7 +559,7 @@ process_arguments (int argc, char **argv)
metric = METRIC_ELAPSED;
break;
}
usage4 (_("Metric must be one of PROCS, VSZ, RSS, CPU, ELAPSED!"));
case 'k': /* linux kernel thread filter */
kthread_filter = 1;
@ -642,7 +642,7 @@ convert_to_seconds(char *etime) {
seconds = 0;
for (ptr = etime; *ptr != '\0'; ptr++) {
if (*ptr == '-') {
hyphcnt++;
continue;
@ -764,6 +764,11 @@ be the total number of running processes\n\n"));
printf (" %s\n", "check_procs -w 2:2 -c 2:1024 -C portsentry");
printf (" %s\n", _("Warning if not two processes with command name portsentry."));
printf (" %s\n\n", _("Critical if < 2 or > 1024 processes"));
printf (" %s\n", "check_procs -c 1: -C sshd");
printf (" %s\n", _("Critical if not at least 1 process with command sshd"));
printf (" %s\n", "check_procs -w 1024 -c 1: -C sshd");
printf (" %s\n", _("Warning if > 1024 processes with command name sshd."));
printf (" %s\n\n", _("Critical if < 1 processes with command name sshd."));
printf (" %s\n", "check_procs -w 10 -a '/usr/local/bin/perl' -u root");
printf (" %s\n", _("Warning alert if > 10 processes with command arguments containing"));
printf (" %s\n\n", _("'/usr/local/bin/perl' and owned by root"));

View file

@ -360,7 +360,7 @@ print_help (void)
printf (" %s\n", "-u, --username=STRING");
printf (" %s\n", _("The user to authenticate"));
printf (" %s\n", "-p, --password=STRING");
printf (" %s\n", _("Password for autentication (SECURITY RISK)"));
printf (" %s\n", _("Password for authentication (SECURITY RISK)"));
printf (" %s\n", "-n, --nas-id=STRING");
printf (" %s\n", _("NAS identifier"));
printf (" %s\n", "-N, --nas-ip-address=STRING");

View file

@ -438,7 +438,7 @@ print_help (void)
printf ("%s\n", _("This plugin will attempt to open an RTSP connection with the host."));
printf ("%s\n", _("Successul connects return STATE_OK, refusals and timeouts return"));
printf ("%s\n", _("STATE_CRITICAL, other errors return STATE_UNKNOWN. Successful connects,"));
printf ("%s\n", _("but incorrect reponse messages from the host result in STATE_WARNING return"));
printf ("%s\n", _("but incorrect response messages from the host result in STATE_WARNING return"));
printf ("%s\n", _("values."));
printf (UT_SUPPORT);

View file

@ -55,6 +55,7 @@ enum {
#define SMTP_EXPECT "220"
#define SMTP_HELO "HELO "
#define SMTP_EHLO "EHLO "
#define SMTP_LHLO "LHLO "
#define SMTP_QUIT "QUIT\r\n"
#define SMTP_STARTTLS "STARTTLS\r\n"
#define SMTP_AUTH_LOGIN "AUTH LOGIN\r\n"
@ -102,6 +103,7 @@ int check_critical_time = FALSE;
int verbose = 0;
int use_ssl = FALSE;
short use_ehlo = FALSE;
short use_lhlo = FALSE;
short ssl_established = 0;
char *localhostname = NULL;
int sd;
@ -152,7 +154,9 @@ main (int argc, char **argv)
return STATE_CRITICAL;
}
}
if(use_ehlo)
if(use_lhlo)
xasprintf (&helocmd, "%s%s%s", SMTP_LHLO, localhostname, "\r\n");
else if(use_ehlo)
xasprintf (&helocmd, "%s%s%s", SMTP_EHLO, localhostname, "\r\n");
else
xasprintf (&helocmd, "%s%s%s", SMTP_HELO, localhostname, "\r\n");
@ -197,7 +201,7 @@ main (int argc, char **argv)
if (recvlines(buffer, MAX_INPUT_BUFFER) <= 0) {
printf (_("recv() failed\n"));
return STATE_WARNING;
} else if(use_ehlo){
} else if(use_ehlo || use_lhlo){
if(strstr(buffer, "250 STARTTLS") != NULL ||
strstr(buffer, "250-STARTTLS") != NULL){
supports_tls=TRUE;
@ -293,6 +297,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));
@ -469,6 +474,7 @@ process_arguments (int argc, char **argv)
{"use-ipv4", no_argument, 0, '4'},
{"use-ipv6", no_argument, 0, '6'},
{"help", no_argument, 0, 'h'},
{"lmtp", no_argument, 0, 'L'},
{"starttls",no_argument,0,'S'},
{"certificate",required_argument,0,'D'},
{"ignore-quit-failure",no_argument,0,'q'},
@ -488,7 +494,7 @@ process_arguments (int argc, char **argv)
}
while (1) {
c = getopt_long (argc, argv, "+hVv46t:p:f:e:c:w:H:C:R:SD:F:A:U:P:q",
c = getopt_long (argc, argv, "+hVv46Lt:p:f:e:c:w:H:C:R:SD:F:A:U:P:q",
longopts, &option);
if (c == -1 || c == EOF)
@ -615,6 +621,9 @@ process_arguments (int argc, char **argv)
use_ssl = TRUE;
use_ehlo = TRUE;
break;
case 'L':
use_lhlo = TRUE;
break;
case '4':
address_family = AF_INET;
break;
@ -823,6 +832,8 @@ print_help (void)
printf (" %s\n", _("SMTP AUTH username"));
printf (" %s\n", "-P, --authpass=STRING");
printf (" %s\n", _("SMTP AUTH password"));
printf (" %s\n", "-L, --lmtp");
printf (" %s\n", _("Send LHLO instead of HELO/EHLO"));
printf (" %s\n", "-q, --ignore-quit-failure");
printf (" %s\n", _("Ignore failure when sending QUIT command to server"));
@ -835,7 +846,7 @@ print_help (void)
printf("\n");
printf ("%s\n", _("Successul connects return STATE_OK, refusals and timeouts return"));
printf ("%s\n", _("STATE_CRITICAL, other errors return STATE_UNKNOWN. Successful"));
printf ("%s\n", _("connects, but incorrect reponse messages from the host result in"));
printf ("%s\n", _("connects, but incorrect response messages from the host result in"));
printf ("%s\n", _("STATE_WARNING return values."));
printf (UT_SUPPORT);
@ -849,6 +860,6 @@ print_usage (void)
printf ("%s\n", _("Usage:"));
printf ("%s -H host [-p port] [-4|-6] [-e expect] [-C command] [-R response] [-f from addr]\n", progname);
printf ("[-A authtype -U authuser -P authpass] [-w warn] [-c crit] [-t timeout] [-q]\n");
printf ("[-F fqdn] [-S] [-D warn days cert expire[,crit days cert expire]] [-v] \n");
printf ("[-F fqdn] [-S] [-L] [-D warn days cert expire[,crit days cert expire]] [-v] \n");
}

View file

@ -468,6 +468,9 @@ main (int argc, char **argv)
/* Process this block for numeric comparisons */
/* Make some special values,like Timeticks numeric only if a threshold is defined */
if (thlds[i]->warning || thlds[i]->critical || calculate_rate) {
if (verbose > 2) {
print_thresholds(" thresholds", thlds[i]);
}
ptr = strpbrk (show, "-0123456789");
if (ptr == NULL)
die (STATE_UNKNOWN,_("No valid data returned (%s)\n"), show);
@ -576,20 +579,23 @@ main (int argc, char **argv)
len = sizeof(perfstr)-strlen(perfstr)-1;
strncat(perfstr, show, len>ptr-show ? ptr-show : len);
if (type)
strncat(perfstr, type, sizeof(perfstr)-strlen(perfstr)-1);
if (warning_thresholds) {
strncat(perfstr, ";", sizeof(perfstr)-strlen(perfstr)-1);
strncat(perfstr, warning_thresholds, sizeof(perfstr)-strlen(perfstr)-1);
if(thlds[i]->warning && thlds[i]->warning->text)
strncat(perfstr, thlds[i]->warning->text, sizeof(perfstr)-strlen(perfstr)-1);
}
if (critical_thresholds) {
if (!warning_thresholds)
strncat(perfstr, ";", sizeof(perfstr)-strlen(perfstr)-1);
strncat(perfstr, ";", sizeof(perfstr)-strlen(perfstr)-1);
strncat(perfstr, critical_thresholds, sizeof(perfstr)-strlen(perfstr)-1);
if(thlds[i]->critical && thlds[i]->critical->text)
strncat(perfstr, thlds[i]->critical->text, sizeof(perfstr)-strlen(perfstr)-1);
}
if (type)
strncat(perfstr, type, sizeof(perfstr)-strlen(perfstr)-1);
strncat(perfstr, " ", sizeof(perfstr)-strlen(perfstr)-1);
}
}
@ -1160,7 +1166,7 @@ print_help (void)
printf ("(%s \"%s\")\n", _("default is") ,DEFAULT_COMMUNITY);
printf (" %s\n", "-U, --secname=USERNAME");
printf (" %s\n", _("SNMPv3 username"));
printf (" %s\n", "-A, --authpassword=PASSWORD");
printf (" %s\n", "-A, --authpasswd=PASSWORD");
printf (" %s\n", _("SNMPv3 authentication password"));
printf (" %s\n", "-X, --privpasswd=PASSWORD");
printf (" %s\n", _("SNMPv3 privacy password"));
@ -1207,8 +1213,9 @@ print_help (void)
printf (" %s\n", _("Separates output on multiple OID requests"));
printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
printf (" %s\n", _("NOTE the final timeout value is calculated using this formula: timeout_interval * retries + 5"));
printf (" %s\n", "-e, --retries=INTEGER");
printf (" %s\n", _("Number of retries to be used in the requests"));
printf (" %s%i\n", _("Number of retries to be used in the requests, default: "), DEFAULT_RETRIES);
printf (" %s\n", "-O, --perf-oids");
printf (" %s\n", _("Label performance data with OIDs instead of --label's"));

View file

@ -34,6 +34,9 @@ const char *email = "devel@monitoring-plugins.org";
#include "common.h"
#include "popen.h"
#include "utils.h"
#include <string.h>
#include <math.h>
#include <libintl.h>
#ifdef HAVE_DECL_SWAPCTL
# ifdef HAVE_SYS_PARAM_H
@ -51,16 +54,19 @@ const char *email = "devel@monitoring-plugins.org";
# define SWAP_CONVERSION 1
#endif
int check_swap (int usp, float free_swap_mb);
typedef struct {
int is_percentage;
uint64_t value;
} threshold_t;
int check_swap (float free_swap_mb, float total_swap_mb);
int process_arguments (int argc, char **argv);
int validate_arguments (void);
void print_usage (void);
void print_help (void);
int warn_percent = 0;
int crit_percent = 0;
float warn_size_bytes = 0;
float crit_size_bytes = 0;
threshold_t warn;
threshold_t crit;
int verbose;
int allswaps;
int no_swap_state = STATE_CRITICAL;
@ -68,9 +74,10 @@ int no_swap_state = STATE_CRITICAL;
int
main (int argc, char **argv)
{
int percent_used, percent;
float total_swap_mb = 0, used_swap_mb = 0, free_swap_mb = 0;
float dsktotal_mb = 0, dskused_mb = 0, dskfree_mb = 0, tmp_mb = 0;
unsigned int percent_used, percent;
uint64_t total_swap_mb = 0, used_swap_mb = 0, free_swap_mb = 0;
uint64_t dsktotal_mb = 0, dskused_mb = 0, dskfree_mb = 0;
uint64_t tmp_KB = 0;
int result = STATE_UNKNOWN;
char input_buffer[MAX_INPUT_BUFFER];
#ifdef HAVE_PROC_MEMINFO
@ -116,10 +123,15 @@ main (int argc, char **argv)
}
fp = fopen (PROC_MEMINFO, "r");
while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, fp)) {
if (sscanf (input_buffer, "%*[S]%*[w]%*[a]%*[p]%*[:] %f %f %f", &dsktotal_mb, &dskused_mb, &dskfree_mb) == 3) {
dsktotal_mb = dsktotal_mb / 1048576; /* Apply conversion */
dskused_mb = dskused_mb / 1048576;
dskfree_mb = dskfree_mb / 1048576;
/*
* The following sscanf call looks for a line looking like: "Swap: 123 123 123"
* On which kind of system this format exists, I can not say, but I wanted to
* document this for people who are not adapt with sscanf anymore, like me
*/
if (sscanf (input_buffer, "%*[S]%*[w]%*[a]%*[p]%*[:] %lu %lu %lu", &dsktotal_mb, &dskused_mb, &dskfree_mb) == 3) {
dsktotal_mb = dsktotal_mb / (1024 * 1024); /* Apply conversion */
dskused_mb = dskused_mb / (1024 * 1024);
dskfree_mb = dskfree_mb / (1024 * 1024);
total_swap_mb += dsktotal_mb;
used_swap_mb += dskused_mb;
free_swap_mb += dskfree_mb;
@ -128,21 +140,25 @@ main (int argc, char **argv)
percent=100.0;
else
percent = 100 * (((double) dskused_mb) / ((double) dsktotal_mb));
result = max_state (result, check_swap (percent, dskfree_mb));
result = max_state (result, check_swap (dskfree_mb, dsktotal_mb));
if (verbose)
xasprintf (&status, "%s [%.0f (%d%%)]", status, dskfree_mb, 100 - percent);
xasprintf (&status, "%s [%lu (%d%%)]", status, dskfree_mb, 100 - percent);
}
}
else if (sscanf (input_buffer, "%*[S]%*[w]%*[a]%*[p]%[TotalFre]%*[:] %f %*[k]%*[B]", str, &tmp_mb)) {
/*
* The following sscanf call looks for lines looking like: "SwapTotal: 123" and "SwapFree: 123"
* This format exists at least on Debian Linux with a 5.* kernel
*/
else if (sscanf (input_buffer, "%*[S]%*[w]%*[a]%*[p]%[TotalFre]%*[:] %lu %*[k]%*[B]", str, &tmp_KB)) {
if (verbose >= 3) {
printf("Got %s with %f\n", str, tmp_mb);
printf("Got %s with %lu\n", str, tmp_KB);
}
/* I think this part is always in Kb, so convert to mb */
if (strcmp ("Total", str) == 0) {
dsktotal_mb = tmp_mb / 1024;
dsktotal_mb = tmp_KB / 1024;
}
else if (strcmp ("Free", str) == 0) {
dskfree_mb = tmp_mb / 1024;
dskfree_mb = tmp_KB / 1024;
}
}
}
@ -227,7 +243,7 @@ main (int argc, char **argv)
free_swap_mb += dskfree_mb;
if (allswaps) {
percent = 100 * (((double) dskused_mb) / ((double) dsktotal_mb));
result = max_state (result, check_swap (percent, dskfree_mb));
result = max_state (result, check_swap (dskfree_mb, dsktotal_mb));
if (verbose)
xasprintf (&status, "%s [%.0f (%d%%)]", status, dskfree_mb, 100 - percent);
}
@ -289,7 +305,7 @@ main (int argc, char **argv)
if(allswaps && dsktotal_mb > 0){
percent = 100 * (((double) dskused_mb) / ((double) dsktotal_mb));
result = max_state (result, check_swap (percent, dskfree_mb));
result = max_state (result, check_swap (dskfree_mb, dsktotal_mb));
if (verbose) {
xasprintf (&status, "%s [%.0f (%d%%)]", status, dskfree_mb, 100 - percent);
}
@ -328,7 +344,7 @@ main (int argc, char **argv)
if(allswaps && dsktotal_mb > 0){
percent = 100 * (((double) dskused_mb) / ((double) dsktotal_mb));
result = max_state (result, check_swap (percent, dskfree_mb));
result = max_state (result, check_swap(dskfree_mb, dsktotal_mb));
if (verbose) {
xasprintf (&status, "%s [%.0f (%d%%)]", status, dskfree_mb, 100 - percent);
}
@ -355,14 +371,19 @@ main (int argc, char **argv)
status = "- Swap is either disabled, not present, or of zero size. ";
}
result = max_state (result, check_swap (percent_used, free_swap_mb));
printf (_("SWAP %s - %d%% free (%d MB out of %d MB) %s|"),
result = max_state (result, check_swap(free_swap_mb, total_swap_mb));
printf (_("SWAP %s - %d%% free (%dMB out of %dMB) %s|"),
state_text (result),
(100 - percent_used), (int) free_swap_mb, (int) total_swap_mb, status);
puts (perfdata ("swap", (long) free_swap_mb, "MB",
TRUE, (long) max (warn_size_bytes/(1024 * 1024), warn_percent/100.0*total_swap_mb),
TRUE, (long) max (crit_size_bytes/(1024 * 1024), crit_percent/100.0*total_swap_mb),
uint64_t warn_print = warn.value;
if (warn.is_percentage) warn_print = warn.value * (total_swap_mb *1024 *1024/100);
uint64_t crit_print = crit.value;
if (crit.is_percentage) crit_print = crit.value * (total_swap_mb *1024 *1024/100);
puts (perfdata_uint64 ("swap", free_swap_mb *1024 *1024, "B",
TRUE, warn_print,
TRUE, crit_print,
TRUE, 0,
TRUE, (long) total_swap_mb));
@ -370,26 +391,37 @@ main (int argc, char **argv)
}
int
check_swap (int usp, float free_swap_mb)
check_swap(float free_swap_mb, float total_swap_mb)
{
if (!free_swap_mb) return no_swap_state;
if (!total_swap_mb) return no_swap_state;
int result = STATE_UNKNOWN;
float free_swap = free_swap_mb * (1024 * 1024); /* Convert back to bytes as warn and crit specified in bytes */
if (usp >= 0 && crit_percent != 0 && usp >= (100.0 - crit_percent))
result = STATE_CRITICAL;
else if (crit_size_bytes > 0 && free_swap <= crit_size_bytes)
result = STATE_CRITICAL;
else if (usp >= 0 && warn_percent != 0 && usp >= (100.0 - warn_percent))
result = STATE_WARNING;
else if (warn_size_bytes > 0 && free_swap <= warn_size_bytes)
result = STATE_WARNING;
else if (usp >= 0.0)
result = STATE_OK;
return result;
uint64_t free_swap = free_swap_mb * (1024 * 1024); /* Convert back to bytes as warn and crit specified in bytes */
if (!crit.is_percentage && crit.value >= free_swap) return STATE_CRITICAL;
if (!warn.is_percentage && warn.value >= free_swap) return STATE_WARNING;
uint64_t usage_percentage = ((total_swap_mb - free_swap_mb) / total_swap_mb) * 100;
if (crit.is_percentage &&
usage_percentage >= 0 &&
crit.value != 0 &&
usage_percentage >= (100 - crit.value))
{
return STATE_CRITICAL;
}
if (warn.is_percentage &&
usage_percentage >= 0 &&
warn.value != 0 &&
usage_percentage >= (100 - warn.value))
{
return STATE_WARNING;
}
return STATE_OK;
}
@ -422,42 +454,68 @@ process_arguments (int argc, char **argv)
break;
switch (c) {
case 'w': /* warning size threshold */
if (is_intnonneg (optarg)) {
warn_size_bytes = (float) atoi (optarg);
break;
}
else if (strstr (optarg, ",") &&
strstr (optarg, "%") &&
sscanf (optarg, "%f,%d%%", &warn_size_bytes, &warn_percent) == 2) {
warn_size_bytes = floorf(warn_size_bytes);
break;
}
else if (strstr (optarg, "%") &&
sscanf (optarg, "%d%%", &warn_percent) == 1) {
break;
}
else {
usage4 (_("Warning threshold must be integer or percentage!"));
}
case 'c': /* critical size threshold */
if (is_intnonneg (optarg)) {
crit_size_bytes = (float) atoi (optarg);
break;
}
else if (strstr (optarg, ",") &&
strstr (optarg, "%") &&
sscanf (optarg, "%f,%d%%", &crit_size_bytes, &crit_percent) == 2) {
crit_size_bytes = floorf(crit_size_bytes);
break;
}
else if (strstr (optarg, "%") &&
sscanf (optarg, "%d%%", &crit_percent) == 1) {
break;
}
else {
usage4 (_("Critical threshold must be integer or percentage!"));
case 'w': /* warning size threshold */
{
/*
* We expect either a positive integer value without a unit, which means
* the unit is Bytes or a positive integer value and a percentage sign (%),
* which means the value must be with 0 and 100 and is relative to the total swap
*/
size_t length;
length = strlen(optarg);
if (optarg[length - 1] == '%') {
/* It's percentage */
warn.is_percentage = 1;
optarg[length - 1] = '\0';
if (is_uint64(optarg, &warn.value)) {
if (warn.value > 100) {
usage4 (_("Warning threshold percentage must be <= 100!"));
} else {
break;
}
}
} else {
/* It's Bytes */
warn.is_percentage = 0;
if (is_uint64(optarg, &warn.value)) {
break;
} else {
usage4 (_("Warning threshold be positive integer or percentage!"));
}
}
}
case 'c': /* critical size threshold */
{
/*
* We expect either a positive integer value without a unit, which means
* the unit is Bytes or a positive integer value and a percentage sign (%),
* which means the value must be with 0 and 100 and is relative to the total swap
*/
size_t length;
length = strlen(optarg);
if (optarg[length - 1] == '%') {
/* It's percentage */
crit.is_percentage = 1;
optarg[length - 1] = '\0';
if (is_uint64(optarg, &crit.value)) {
if (crit.value> 100) {
usage4 (_("Critical threshold percentage must be <= 100!"));
} else {
break;
}
}
} else {
/* It's Bytes */
crit.is_percentage = 0;
if (is_uint64(optarg, &crit.value)) {
break;
} else {
usage4 (_("Critical threshold be positive integer or percentage!"));
}
}
}
case 'a': /* all swap */
allswaps = TRUE;
break;
@ -482,23 +540,6 @@ process_arguments (int argc, char **argv)
c = optind;
if (c == argc)
return validate_arguments ();
if (warn_percent == 0 && is_intnonneg (argv[c]))
warn_percent = atoi (argv[c++]);
if (c == argc)
return validate_arguments ();
if (crit_percent == 0 && is_intnonneg (argv[c]))
crit_percent = atoi (argv[c++]);
if (c == argc)
return validate_arguments ();
if (warn_size_bytes == 0 && is_intnonneg (argv[c]))
warn_size_bytes = (float) atoi (argv[c++]);
if (c == argc)
return validate_arguments ();
if (crit_size_bytes == 0 && is_intnonneg (argv[c]))
crit_size_bytes = (float) atoi (argv[c++]);
return validate_arguments ();
}
@ -508,17 +549,15 @@ process_arguments (int argc, char **argv)
int
validate_arguments (void)
{
if (warn_percent == 0 && crit_percent == 0 && warn_size_bytes == 0
&& crit_size_bytes == 0) {
if (warn.value == 0 && crit.value == 0) {
return ERROR;
}
else if (warn_percent < crit_percent) {
usage4
(_("Warning percentage should be more than critical percentage"));
}
else if (warn_size_bytes < crit_size_bytes) {
usage4
(_("Warning free space should be more than critical free space"));
else if ((warn.is_percentage == crit.is_percentage) && (warn.value < crit.value)) {
/* This is NOT triggered if warn and crit are different units, e.g warn is percentage
* and crit is absolut. We cannot determine the condition at this point since we
* dont know the value of total swap yet
*/
usage4(_("Warning should be more than critical"));
}
return OK;
}
@ -534,7 +573,7 @@ print_help (void)
printf ("%s\n", _("Check swap space on local machine."));
printf ("\n\n");
printf ("\n\n");
print_usage ();
@ -542,33 +581,32 @@ print_help (void)
printf (UT_EXTRA_OPTS);
printf (" %s\n", "-w, --warning=INTEGER");
printf (" %s\n", _("Exit with WARNING status if less than INTEGER bytes of swap space are free"));
printf (" %s\n", "-w, --warning=PERCENT%%");
printf (" %s\n", _("Exit with WARNING status if less than PERCENT of swap space is free"));
printf (" %s\n", "-c, --critical=INTEGER");
printf (" %s\n", _("Exit with CRITICAL status if less than INTEGER bytes of swap space are free"));
printf (" %s\n", "-c, --critical=PERCENT%%");
printf (" %s\n", _("Exit with CRITICAL status if less than PERCENT of swap space is free"));
printf (" %s\n", "-a, --allswaps");
printf (" %s\n", _("Conduct comparisons for all swap partitions, one by one"));
printf (" %s\n", "-n, --no-swap=<ok|warning|critical|unknown>");
printf (" %s %s\n", _("Resulting state when there is no swap regardless of thresholds. Default:"), state_text(no_swap_state));
printf (" %s\n", _("Exit with WARNING status if less than INTEGER bytes of swap space are free"));
printf (" %s\n", "-w, --warning=PERCENT%");
printf (" %s\n", _("Exit with WARNING status if less than PERCENT of swap space is free"));
printf (" %s\n", "-c, --critical=INTEGER");
printf (" %s\n", _("Exit with CRITICAL status if less than INTEGER bytes of swap space are free"));
printf (" %s\n", "-c, --critical=PERCENT%");
printf (" %s\n", _("Exit with CRITICAL status if less than PERCENT of swap space is free"));
printf (" %s\n", "-a, --allswaps");
printf (" %s\n", _("Conduct comparisons for all swap partitions, one by one"));
printf (" %s\n", "-n, --no-swap=<ok|warning|critical|unknown>");
printf (" %s %s\n", _("Resulting state when there is no swap regardless of thresholds. Default:"), state_text(no_swap_state));
printf (UT_VERBOSE);
printf ("\n");
printf ("%s\n", _("Notes:"));
printf (" %s\n", _("Both INTEGER and PERCENT thresholds can be specified, they are all checked."));
printf (" %s\n", _("On AIX, if -a is specified, uses lsps -a, otherwise uses lsps -s."));
printf ("%s\n", _("Notes:"));
printf (" %s\n", _("Both INTEGER and PERCENT thresholds can be specified, they are all checked."));
printf (" %s\n", _("On AIX, if -a is specified, uses lsps -a, otherwise uses lsps -s."));
printf (UT_SUPPORT);
}
void
print_usage (void)
{
printf ("%s\n", _("Usage:"));
printf (" %s [-av] -w <percent_free>%% -c <percent_free>%%\n",progname);
printf (" -w <bytes_free> -c <bytes_free> [-n <state>]\n");
printf (" %s [-av] -w <percent_free>%% -c <percent_free>%%\n",progname);
printf (" -w <bytes_free> -c <bytes_free> [-n <state>]\n");
}

View file

@ -86,6 +86,11 @@ static char buffer[MAXBUF];
static int expect_mismatch_state = STATE_WARNING;
static int match_flags = NP_MATCH_EXACT;
#ifdef HAVE_SSL
static char *sni = NULL;
static int sni_specified = FALSE;
#endif
#define FLAG_SSL 0x01
#define FLAG_VERBOSE 0x02
#define FLAG_TIME_WARN 0x04
@ -241,7 +246,7 @@ main (int argc, char **argv)
#ifdef HAVE_SSL
if (flags & FLAG_SSL){
result = np_net_ssl_init(sd);
result = np_net_ssl_init_with_hostname(sd, (sni_specified ? sni : NULL));
if (result == STATE_OK && check_cert == TRUE) {
result = np_net_ssl_check_cert(days_till_exp_warn, days_till_exp_crit);
}
@ -401,6 +406,10 @@ process_arguments (int argc, char **argv)
int escape = 0;
char *temp;
enum {
SNI_OPTION = CHAR_MAX + 1
};
int option = 0;
static struct option longopts[] = {
{"hostname", required_argument, 0, 'H'},
@ -427,6 +436,7 @@ process_arguments (int argc, char **argv)
{"version", no_argument, 0, 'V'},
{"help", no_argument, 0, 'h'},
{"ssl", no_argument, 0, 'S'},
{"sni", required_argument, 0, SNI_OPTION},
{"certificate", required_argument, 0, 'D'},
{0, 0, 0, 0}
};
@ -602,6 +612,15 @@ process_arguments (int argc, char **argv)
flags |= FLAG_SSL;
#else
die (STATE_UNKNOWN, _("Invalid option - SSL is not available"));
#endif
break;
case SNI_OPTION:
#ifdef HAVE_SSL
flags |= FLAG_SSL;
sni_specified = TRUE;
sni = optarg;
#else
die (STATE_UNKNOWN, _("Invalid option - SSL is not available"));
#endif
break;
case 'A':
@ -671,6 +690,8 @@ print_help (void)
printf (" %s\n", _("1st is #days for warning, 2nd is critical (if not specified - 0)."));
printf (" %s\n", "-S, --ssl");
printf (" %s\n", _("Use SSL for the connection."));
printf (" %s\n", "--sni=STRING");
printf (" %s\n", _("SSL server_name"));
#endif
printf (UT_WARN_CRIT);

View file

@ -402,7 +402,10 @@ get_ups_variable (const char *varname, char *buf, size_t buflen)
/* create the command string to send to the UPS daemon */
/* Add LOGOUT to avoid read failure logs */
sprintf (send_buffer, "GET VAR %s %s\nLOGOUT\n", ups_name, varname);
if (snprintf (send_buffer, sizeof(send_buffer), "GET VAR %s %s\nLOGOUT\n", ups_name, varname) >= sizeof(send_buffer)) {
printf("%s\n", _("UPS name to long for buffer"));
return ERROR;
}
/* send the command to the daemon and get a response back */
if (process_tcp_request

View file

@ -174,6 +174,11 @@
*
*/
/* MariaDB 10.2 client does not set MYSQL_PORT */
#ifndef MYSQL_PORT
# define MYSQL_PORT 3306
#endif
enum {
OK = 0,
ERROR = -1
@ -220,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_ */

View file

@ -86,11 +86,9 @@ main (int argc, char **argv)
result = cmd_run_array (command_line, &chld_out, &chld_err, 0);
}
if (chld_err.lines > 0) {
printf ("Error output from command:\n");
for (i = 0; i < chld_err.lines; i++) {
printf ("%s\n", chld_err.line[i]);
fprintf (stderr, "%s\n", chld_err.line[i]);
}
exit (STATE_WARNING);
}
/* Return UNKNOWN or worse if no output is returned */

View file

@ -0,0 +1,3 @@
noinst_LIBRARIES = libpicohttpparser.a
libpicohttpparser_a_SOURCES = picohttpparser.c picohttpparser.h

View file

@ -0,0 +1,645 @@
/*
* Copyright (c) 2009-2014 Kazuho Oku, Tokuhiro Matsuno, Daisuke Murase,
* Shigeo Mitsunari
*
* The software is licensed under either the MIT License (below) or the Perl
* license.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include <assert.h>
#include <stddef.h>
#include <string.h>
#ifdef __SSE4_2__
#ifdef _MSC_VER
#include <nmmintrin.h>
#else
#include <x86intrin.h>
#endif
#endif
#include "picohttpparser.h"
#if __GNUC__ >= 3
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
#else
#define likely(x) (x)
#define unlikely(x) (x)
#endif
#ifdef _MSC_VER
#define ALIGNED(n) _declspec(align(n))
#else
#define ALIGNED(n) __attribute__((aligned(n)))
#endif
#define IS_PRINTABLE_ASCII(c) ((unsigned char)(c)-040u < 0137u)
#define CHECK_EOF() \
if (buf == buf_end) { \
*ret = -2; \
return NULL; \
}
#define EXPECT_CHAR_NO_CHECK(ch) \
if (*buf++ != ch) { \
*ret = -1; \
return NULL; \
}
#define EXPECT_CHAR(ch) \
CHECK_EOF(); \
EXPECT_CHAR_NO_CHECK(ch);
#define ADVANCE_TOKEN(tok, toklen) \
do { \
const char *tok_start = buf; \
static const char ALIGNED(16) ranges2[16] = "\000\040\177\177"; \
int found2; \
buf = findchar_fast(buf, buf_end, ranges2, 4, &found2); \
if (!found2) { \
CHECK_EOF(); \
} \
while (1) { \
if (*buf == ' ') { \
break; \
} else if (unlikely(!IS_PRINTABLE_ASCII(*buf))) { \
if ((unsigned char)*buf < '\040' || *buf == '\177') { \
*ret = -1; \
return NULL; \
} \
} \
++buf; \
CHECK_EOF(); \
} \
tok = tok_start; \
toklen = buf - tok_start; \
} while (0)
static const char *token_char_map = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
"\0\1\0\1\1\1\1\1\0\0\1\1\0\1\1\0\1\1\1\1\1\1\1\1\1\1\0\0\0\0\0\0"
"\0\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\0\0\0\1\1"
"\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\0\1\0\1\0"
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
static const char *findchar_fast(const char *buf, const char *buf_end, const char *ranges, size_t ranges_size, int *found)
{
*found = 0;
#if __SSE4_2__
if (likely(buf_end - buf >= 16)) {
__m128i ranges16 = _mm_loadu_si128((const __m128i *)ranges);
size_t left = (buf_end - buf) & ~15;
do {
__m128i b16 = _mm_loadu_si128((const __m128i *)buf);
int r = _mm_cmpestri(ranges16, ranges_size, b16, 16, _SIDD_LEAST_SIGNIFICANT | _SIDD_CMP_RANGES | _SIDD_UBYTE_OPS);
if (unlikely(r != 16)) {
buf += r;
*found = 1;
break;
}
buf += 16;
left -= 16;
} while (likely(left != 0));
}
#else
/* suppress unused parameter warning */
(void)buf_end;
(void)ranges;
(void)ranges_size;
#endif
return buf;
}
static const char *get_token_to_eol(const char *buf, const char *buf_end, const char **token, size_t *token_len, int *ret)
{
const char *token_start = buf;
#ifdef __SSE4_2__
static const char ALIGNED(16) ranges1[16] = "\0\010" /* allow HT */
"\012\037" /* allow SP and up to but not including DEL */
"\177\177"; /* allow chars w. MSB set */
int found;
buf = findchar_fast(buf, buf_end, ranges1, 6, &found);
if (found)
goto FOUND_CTL;
#else
/* find non-printable char within the next 8 bytes, this is the hottest code; manually inlined */
while (likely(buf_end - buf >= 8)) {
#define DOIT() \
do { \
if (unlikely(!IS_PRINTABLE_ASCII(*buf))) \
goto NonPrintable; \
++buf; \
} while (0)
DOIT();
DOIT();
DOIT();
DOIT();
DOIT();
DOIT();
DOIT();
DOIT();
#undef DOIT
continue;
NonPrintable:
if ((likely((unsigned char)*buf < '\040') && likely(*buf != '\011')) || unlikely(*buf == '\177')) {
goto FOUND_CTL;
}
++buf;
}
#endif
for (;; ++buf) {
CHECK_EOF();
if (unlikely(!IS_PRINTABLE_ASCII(*buf))) {
if ((likely((unsigned char)*buf < '\040') && likely(*buf != '\011')) || unlikely(*buf == '\177')) {
goto FOUND_CTL;
}
}
}
FOUND_CTL:
if (likely(*buf == '\015')) {
++buf;
EXPECT_CHAR('\012');
*token_len = buf - 2 - token_start;
} else if (*buf == '\012') {
*token_len = buf - token_start;
++buf;
} else {
*ret = -1;
return NULL;
}
*token = token_start;
return buf;
}
static const char *is_complete(const char *buf, const char *buf_end, size_t last_len, int *ret)
{
int ret_cnt = 0;
buf = last_len < 3 ? buf : buf + last_len - 3;
while (1) {
CHECK_EOF();
if (*buf == '\015') {
++buf;
CHECK_EOF();
EXPECT_CHAR('\012');
++ret_cnt;
} else if (*buf == '\012') {
++buf;
++ret_cnt;
} else {
++buf;
ret_cnt = 0;
}
if (ret_cnt == 2) {
return buf;
}
}
*ret = -2;
return NULL;
}
#define PARSE_INT(valp_, mul_) \
if (*buf < '0' || '9' < *buf) { \
buf++; \
*ret = -1; \
return NULL; \
} \
*(valp_) = (mul_) * (*buf++ - '0');
#define PARSE_INT_3(valp_) \
do { \
int res_ = 0; \
PARSE_INT(&res_, 100) \
*valp_ = res_; \
PARSE_INT(&res_, 10) \
*valp_ += res_; \
PARSE_INT(&res_, 1) \
*valp_ += res_; \
} while (0)
/* returned pointer is always within [buf, buf_end), or null */
static const char *parse_http_version(const char *buf, const char *buf_end, int *minor_version, int *ret)
{
/* we want at least [HTTP/1.<two chars>] to try to parse */
if (buf_end - buf < 9) {
*ret = -2;
return NULL;
}
EXPECT_CHAR_NO_CHECK('H');
EXPECT_CHAR_NO_CHECK('T');
EXPECT_CHAR_NO_CHECK('T');
EXPECT_CHAR_NO_CHECK('P');
EXPECT_CHAR_NO_CHECK('/');
EXPECT_CHAR_NO_CHECK('1');
EXPECT_CHAR_NO_CHECK('.');
PARSE_INT(minor_version, 1);
return buf;
}
static const char *parse_headers(const char *buf, const char *buf_end, struct phr_header *headers, size_t *num_headers,
size_t max_headers, int *ret)
{
for (;; ++*num_headers) {
CHECK_EOF();
if (*buf == '\015') {
++buf;
EXPECT_CHAR('\012');
break;
} else if (*buf == '\012') {
++buf;
break;
}
if (*num_headers == max_headers) {
*ret = -1;
return NULL;
}
if (!(*num_headers != 0 && (*buf == ' ' || *buf == '\t'))) {
/* parsing name, but do not discard SP before colon, see
* http://www.mozilla.org/security/announce/2006/mfsa2006-33.html */
headers[*num_headers].name = buf;
static const char ALIGNED(16) ranges1[] = "\x00 " /* control chars and up to SP */
"\"\"" /* 0x22 */
"()" /* 0x28,0x29 */
",," /* 0x2c */
"//" /* 0x2f */
":@" /* 0x3a-0x40 */
"[]" /* 0x5b-0x5d */
"{\377"; /* 0x7b-0xff */
int found;
buf = findchar_fast(buf, buf_end, ranges1, sizeof(ranges1) - 1, &found);
if (!found) {
CHECK_EOF();
}
while (1) {
if (*buf == ':') {
break;
} else if (!token_char_map[(unsigned char)*buf]) {
*ret = -1;
return NULL;
}
++buf;
CHECK_EOF();
}
if ((headers[*num_headers].name_len = buf - headers[*num_headers].name) == 0) {
*ret = -1;
return NULL;
}
++buf;
for (;; ++buf) {
CHECK_EOF();
if (!(*buf == ' ' || *buf == '\t')) {
break;
}
}
} else {
headers[*num_headers].name = NULL;
headers[*num_headers].name_len = 0;
}
const char *value;
size_t value_len;
if ((buf = get_token_to_eol(buf, buf_end, &value, &value_len, ret)) == NULL) {
return NULL;
}
/* remove trailing SPs and HTABs */
const char *value_end = value + value_len;
for (; value_end != value; --value_end) {
const char c = *(value_end - 1);
if (!(c == ' ' || c == '\t')) {
break;
}
}
headers[*num_headers].value = value;
headers[*num_headers].value_len = value_end - value;
}
return buf;
}
static const char *parse_request(const char *buf, const char *buf_end, const char **method, size_t *method_len, const char **path,
size_t *path_len, int *minor_version, struct phr_header *headers, size_t *num_headers,
size_t max_headers, int *ret)
{
/* skip first empty line (some clients add CRLF after POST content) */
CHECK_EOF();
if (*buf == '\015') {
++buf;
EXPECT_CHAR('\012');
} else if (*buf == '\012') {
++buf;
}
/* parse request line */
ADVANCE_TOKEN(*method, *method_len);
do {
++buf;
} while (*buf == ' ');
ADVANCE_TOKEN(*path, *path_len);
do {
++buf;
} while (*buf == ' ');
if (*method_len == 0 || *path_len == 0) {
*ret = -1;
return NULL;
}
if ((buf = parse_http_version(buf, buf_end, minor_version, ret)) == NULL) {
return NULL;
}
if (*buf == '\015') {
++buf;
EXPECT_CHAR('\012');
} else if (*buf == '\012') {
++buf;
} else {
*ret = -1;
return NULL;
}
return parse_headers(buf, buf_end, headers, num_headers, max_headers, ret);
}
int phr_parse_request(const char *buf_start, size_t len, const char **method, size_t *method_len, const char **path,
size_t *path_len, int *minor_version, struct phr_header *headers, size_t *num_headers, size_t last_len)
{
const char *buf = buf_start, *buf_end = buf_start + len;
size_t max_headers = *num_headers;
int r;
*method = NULL;
*method_len = 0;
*path = NULL;
*path_len = 0;
*minor_version = -1;
*num_headers = 0;
/* if last_len != 0, check if the request is complete (a fast countermeasure
againt slowloris */
if (last_len != 0 && is_complete(buf, buf_end, last_len, &r) == NULL) {
return r;
}
if ((buf = parse_request(buf, buf_end, method, method_len, path, path_len, minor_version, headers, num_headers, max_headers,
&r)) == NULL) {
return r;
}
return (int)(buf - buf_start);
}
static const char *parse_response(const char *buf, const char *buf_end, int *minor_version, int *status, const char **msg,
size_t *msg_len, struct phr_header *headers, size_t *num_headers, size_t max_headers, int *ret)
{
/* parse "HTTP/1.x" */
if ((buf = parse_http_version(buf, buf_end, minor_version, ret)) == NULL) {
return NULL;
}
/* skip space */
if (*buf != ' ') {
*ret = -1;
return NULL;
}
do {
++buf;
} while (*buf == ' ');
/* parse status code, we want at least [:digit:][:digit:][:digit:]<other char> to try to parse */
if (buf_end - buf < 4) {
*ret = -2;
return NULL;
}
PARSE_INT_3(status);
/* get message includig preceding space */
if ((buf = get_token_to_eol(buf, buf_end, msg, msg_len, ret)) == NULL) {
return NULL;
}
if (*msg_len == 0) {
/* ok */
} else if (**msg == ' ') {
/* remove preceding space */
do {
++*msg;
--*msg_len;
} while (**msg == ' ');
} else {
/* garbage found after status code */
*ret = -1;
return NULL;
}
return parse_headers(buf, buf_end, headers, num_headers, max_headers, ret);
}
int phr_parse_response(const char *buf_start, size_t len, int *minor_version, int *status, const char **msg, size_t *msg_len,
struct phr_header *headers, size_t *num_headers, size_t last_len)
{
const char *buf = buf_start, *buf_end = buf + len;
size_t max_headers = *num_headers;
int r;
*minor_version = -1;
*status = 0;
*msg = NULL;
*msg_len = 0;
*num_headers = 0;
/* if last_len != 0, check if the response is complete (a fast countermeasure
against slowloris */
if (last_len != 0 && is_complete(buf, buf_end, last_len, &r) == NULL) {
return r;
}
if ((buf = parse_response(buf, buf_end, minor_version, status, msg, msg_len, headers, num_headers, max_headers, &r)) == NULL) {
return r;
}
return (int)(buf - buf_start);
}
int phr_parse_headers(const char *buf_start, size_t len, struct phr_header *headers, size_t *num_headers, size_t last_len)
{
const char *buf = buf_start, *buf_end = buf + len;
size_t max_headers = *num_headers;
int r;
*num_headers = 0;
/* if last_len != 0, check if the response is complete (a fast countermeasure
against slowloris */
if (last_len != 0 && is_complete(buf, buf_end, last_len, &r) == NULL) {
return r;
}
if ((buf = parse_headers(buf, buf_end, headers, num_headers, max_headers, &r)) == NULL) {
return r;
}
return (int)(buf - buf_start);
}
enum {
CHUNKED_IN_CHUNK_SIZE,
CHUNKED_IN_CHUNK_EXT,
CHUNKED_IN_CHUNK_DATA,
CHUNKED_IN_CHUNK_CRLF,
CHUNKED_IN_TRAILERS_LINE_HEAD,
CHUNKED_IN_TRAILERS_LINE_MIDDLE
};
static int decode_hex(int ch)
{
if ('0' <= ch && ch <= '9') {
return ch - '0';
} else if ('A' <= ch && ch <= 'F') {
return ch - 'A' + 0xa;
} else if ('a' <= ch && ch <= 'f') {
return ch - 'a' + 0xa;
} else {
return -1;
}
}
ssize_t phr_decode_chunked(struct phr_chunked_decoder *decoder, char *buf, size_t *_bufsz)
{
size_t dst = 0, src = 0, bufsz = *_bufsz;
ssize_t ret = -2; /* incomplete */
while (1) {
switch (decoder->_state) {
case CHUNKED_IN_CHUNK_SIZE:
for (;; ++src) {
int v;
if (src == bufsz)
goto Exit;
if ((v = decode_hex(buf[src])) == -1) {
if (decoder->_hex_count == 0) {
ret = -1;
goto Exit;
}
break;
}
if (decoder->_hex_count == sizeof(size_t) * 2) {
ret = -1;
goto Exit;
}
decoder->bytes_left_in_chunk = decoder->bytes_left_in_chunk * 16 + v;
++decoder->_hex_count;
}
decoder->_hex_count = 0;
decoder->_state = CHUNKED_IN_CHUNK_EXT;
/* fallthru */
case CHUNKED_IN_CHUNK_EXT:
/* RFC 7230 A.2 "Line folding in chunk extensions is disallowed" */
for (;; ++src) {
if (src == bufsz)
goto Exit;
if (buf[src] == '\012')
break;
}
++src;
if (decoder->bytes_left_in_chunk == 0) {
if (decoder->consume_trailer) {
decoder->_state = CHUNKED_IN_TRAILERS_LINE_HEAD;
break;
} else {
goto Complete;
}
}
decoder->_state = CHUNKED_IN_CHUNK_DATA;
/* fallthru */
case CHUNKED_IN_CHUNK_DATA: {
size_t avail = bufsz - src;
if (avail < decoder->bytes_left_in_chunk) {
if (dst != src)
memmove(buf + dst, buf + src, avail);
src += avail;
dst += avail;
decoder->bytes_left_in_chunk -= avail;
goto Exit;
}
if (dst != src)
memmove(buf + dst, buf + src, decoder->bytes_left_in_chunk);
src += decoder->bytes_left_in_chunk;
dst += decoder->bytes_left_in_chunk;
decoder->bytes_left_in_chunk = 0;
decoder->_state = CHUNKED_IN_CHUNK_CRLF;
}
/* fallthru */
case CHUNKED_IN_CHUNK_CRLF:
for (;; ++src) {
if (src == bufsz)
goto Exit;
if (buf[src] != '\015')
break;
}
if (buf[src] != '\012') {
ret = -1;
goto Exit;
}
++src;
decoder->_state = CHUNKED_IN_CHUNK_SIZE;
break;
case CHUNKED_IN_TRAILERS_LINE_HEAD:
for (;; ++src) {
if (src == bufsz)
goto Exit;
if (buf[src] != '\015')
break;
}
if (buf[src++] == '\012')
goto Complete;
decoder->_state = CHUNKED_IN_TRAILERS_LINE_MIDDLE;
/* fallthru */
case CHUNKED_IN_TRAILERS_LINE_MIDDLE:
for (;; ++src) {
if (src == bufsz)
goto Exit;
if (buf[src] == '\012')
break;
}
++src;
decoder->_state = CHUNKED_IN_TRAILERS_LINE_HEAD;
break;
default:
assert(!"decoder is corrupt");
}
}
Complete:
ret = bufsz - src;
Exit:
if (dst != src)
memmove(buf + dst, buf + src, bufsz - src);
*_bufsz = dst;
return ret;
}
int phr_decode_chunked_is_in_data(struct phr_chunked_decoder *decoder)
{
return decoder->_state == CHUNKED_IN_CHUNK_DATA;
}
#undef CHECK_EOF
#undef EXPECT_CHAR
#undef ADVANCE_TOKEN

View file

@ -0,0 +1,87 @@
/*
* Copyright (c) 2009-2014 Kazuho Oku, Tokuhiro Matsuno, Daisuke Murase,
* Shigeo Mitsunari
*
* The software is licensed under either the MIT License (below) or the Perl
* license.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#ifndef picohttpparser_h
#define picohttpparser_h
#include <sys/types.h>
#ifdef _MSC_VER
#define ssize_t intptr_t
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* contains name and value of a header (name == NULL if is a continuing line
* of a multiline header */
struct phr_header {
const char *name;
size_t name_len;
const char *value;
size_t value_len;
};
/* returns number of bytes consumed if successful, -2 if request is partial,
* -1 if failed */
int phr_parse_request(const char *buf, size_t len, const char **method, size_t *method_len, const char **path, size_t *path_len,
int *minor_version, struct phr_header *headers, size_t *num_headers, size_t last_len);
/* ditto */
int phr_parse_response(const char *_buf, size_t len, int *minor_version, int *status, const char **msg, size_t *msg_len,
struct phr_header *headers, size_t *num_headers, size_t last_len);
/* ditto */
int phr_parse_headers(const char *buf, size_t len, struct phr_header *headers, size_t *num_headers, size_t last_len);
/* should be zero-filled before start */
struct phr_chunked_decoder {
size_t bytes_left_in_chunk; /* number of bytes left in current chunk */
char consume_trailer; /* if trailing headers should be consumed */
char _hex_count;
char _state;
};
/* the function rewrites the buffer given as (buf, bufsz) removing the chunked-
* encoding headers. When the function returns without an error, bufsz is
* updated to the length of the decoded data available. Applications should
* repeatedly call the function while it returns -2 (incomplete) every time
* supplying newly arrived data. If the end of the chunked-encoded data is
* found, the function returns a non-negative number indicating the number of
* octets left undecoded at the tail of the supplied buffer. Returns -1 on
* error.
*/
ssize_t phr_decode_chunked(struct phr_chunked_decoder *decoder, char *buf, size_t *bufsz);
/* returns if the chunked decoder is in middle of chunked data */
int phr_decode_chunked_is_in_data(struct phr_chunked_decoder *decoder);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -39,9 +39,9 @@
*****************************************************************************/
#include "common.h"
#include "utils.h"
/* extern so plugin has pid to kill exec'd process on timeouts */
extern int timeout_interval;
extern pid_t *childpid;
extern int *child_stderr_array;
extern FILE *child_process;
@ -76,18 +76,9 @@ RETSIGTYPE popen_timeout_alarm_handler (int);
#define SIG_ERR ((Sigfunc *)-1)
#endif
#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 *);
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;
#endif
@ -186,14 +177,15 @@ spopen (const char *cmdstring)
}
argv[i] = NULL;
if(maxfd == 0)
maxfd = open_max();
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 +265,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)
@ -309,63 +292,3 @@ popen_timeout_alarm_handler (int signo)
exit (STATE_CRITICAL);
}
}
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. */
#define MAXLINE 2048
static void
err_sys (const char *fmt, ...)
{
int errnoflag = 1;
int errno_save;
char buf[MAXLINE];
va_list ap;
va_start (ap, fmt);
/* err_doit (1, fmt, ap); */
errno_save = errno; /* value caller might want printed */
vsprintf (buf, fmt, ap);
if (errnoflag)
sprintf (buf + strlen (buf), ": %s", strerror (errno_save));
strcat (buf, "\n");
fflush (stdout); /* in case stdout and stderr are the same */
fputs (buf, stderr);
fflush (NULL); /* flushes all stdio output streams */
va_end (ap);
exit (1);
}
char *
rtrim (char *str, const char *tok)
{
int i = 0;
int j = sizeof (str);
while (str != NULL && i < j) {
if (*(str + i) == *tok) {
sprintf (str + i, "%s", "\0");
return str;
}
i++;
}
return str;
}

View file

@ -7,7 +7,6 @@ FILE *spopen (const char *);
int spclose (FILE *);
RETSIGTYPE popen_timeout_alarm_handler (int);
extern unsigned int timeout_interval;
pid_t *childpid=NULL;
int *child_stderr_array=NULL;
FILE *child_process=NULL;

View file

@ -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)));
@ -99,14 +86,8 @@ extern void die (int, const char *, ...)
* through this api and thus achieve async-safeness throughout the api */
void np_runcmd_init(void)
{
#ifndef maxfd
if(!maxfd && (maxfd = sysconf(_SC_OPEN_MAX)) < 0) {
/* possibly log or emit a warning here, since there's no
* guarantee that our guess at maxfd will be adequate */
maxfd = 256;
}
#endif
if(maxfd == 0)
maxfd = open_max();
if(!np_pids) np_pids = calloc(maxfd, sizeof(pid_t));
}

View file

@ -1,29 +1,29 @@
/*****************************************************************************
*
*
* Monitoring Plugins SSL utilities
*
*
* License: GPL
* Copyright (c) 2005-2010 Monitoring Plugins Development Team
*
*
* Description:
*
*
* This file contains common functions for plugins that require SSL.
*
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*
*
*
*****************************************************************************/
#define MAX_CN_LENGTH 256
@ -193,12 +193,22 @@ int np_net_ssl_read(void *buf, int num) {
int np_net_ssl_check_cert(int days_till_exp_warn, int days_till_exp_crit){
# ifdef USE_OPENSSL
X509 *certificate=NULL;
X509 *certificate = NULL;
certificate=SSL_get_peer_certificate(s);
return(np_net_ssl_check_certificate(certificate, days_till_exp_warn, days_till_exp_crit));
# else /* ifndef USE_OPENSSL */
printf("%s\n", _("WARNING - Plugin does not support checking certificates."));
return STATE_WARNING;
# endif /* USE_OPENSSL */
}
int np_net_ssl_check_certificate(X509 *certificate, int days_till_exp_warn, int days_till_exp_crit){
# ifdef USE_OPENSSL
X509_NAME *subj=NULL;
char timestamp[50] = "";
char cn[MAX_CN_LENGTH]= "";
char *tz;
int cnlen =-1;
int status=STATE_UNKNOWN;
@ -210,7 +220,6 @@ int np_net_ssl_check_cert(int days_till_exp_warn, int days_till_exp_crit){
int time_remaining;
time_t tm_t;
certificate=SSL_get_peer_certificate(s);
if (!certificate) {
printf("%s\n",_("CRITICAL - Cannot retrieve server certificate."));
return STATE_CRITICAL;

View file

@ -9,17 +9,9 @@ use Test::More;
use NPTest;
# Required parameters
my $ssh_service = getTestParameter( "NP_SSH_HOST",
"A host providing SSH service",
"localhost");
my $ssh_key = getTestParameter( "NP_SSH_IDENTITY",
"A key allowing access to NP_SSH_HOST",
"~/.ssh/id_dsa");
my $ssh_conf = getTestParameter( "NP_SSH_CONFIGFILE",
"A config file with ssh settings",
"~/.ssh/config");
my $ssh_service = getTestParameter("NP_SSH_HOST", "A host providing SSH service", "localhost");
my $ssh_key = getTestParameter("NP_SSH_IDENTITY", "A key allowing access to NP_SSH_HOST", "~/.ssh/id_dsa");
my $ssh_conf = getTestParameter( "NP_SSH_CONFIGFILE", "A config file with ssh settings", "~/.ssh/config");
plan skip_all => "SSH_HOST and SSH_IDENTITY must be defined" unless ($ssh_service && $ssh_key);

201
plugins/t/check_curl.t Normal file
View file

@ -0,0 +1,201 @@
#! /usr/bin/perl -w -I ..
#
# HyperText Transfer Protocol (HTTP) Test via check_http
#
#
use strict;
use Test::More;
use POSIX qw/mktime strftime/;
use NPTest;
plan tests => 58;
my $successOutput = '/OK.*HTTP.*second/';
my $res;
my $plugin = 'check_http';
$plugin = 'check_curl' if $0 =~ m/check_curl/mx;
my $host_tcp_http = getTestParameter("NP_HOST_TCP_HTTP", "A host providing the HTTP Service (a web server)", "localhost");
my $host_tls_http = getTestParameter("NP_HOST_TLS_HTTP", "A host providing the HTTPS Service (a tls web server)", "localhost");
my $host_tls_cert = getTestParameter("NP_HOST_TLS_CERT", "the common name of the certificate.", "localhost");
my $host_nonresponsive = getTestParameter("NP_HOST_NONRESPONSIVE", "The hostname of system not responsive to network requests", "10.0.0.1");
my $hostname_invalid = getTestParameter("NP_HOSTNAME_INVALID", "An invalid (not known to DNS) hostname", "nosuchhost");
my $internet_access = getTestParameter("NP_INTERNET_ACCESS", "Is this system directly connected to the internet?", "yes");
my $host_tcp_http2 = getTestParameter("NP_HOST_TCP_HTTP2", "A host providing an index page containing the string 'monitoring'", "test.monitoring-plugins.org");
my $host_tcp_proxy = getTestParameter("NP_HOST_TCP_PROXY", "A host providing a HTTP proxy with CONNECT support", "localhost");
my $port_tcp_proxy = getTestParameter("NP_PORT_TCP_PROXY", "Port of the proxy with HTTP and CONNECT support", "3128");
my $faketime = -x '/usr/bin/faketime' ? 1 : 0;
$res = NPTest->testCmd(
"./$plugin $host_tcp_http -wt 300 -ct 600"
);
cmp_ok( $res->return_code, '==', 0, "Webserver $host_tcp_http responded" );
like( $res->output, $successOutput, "Output OK" );
$res = NPTest->testCmd(
"./$plugin $host_tcp_http -wt 300 -ct 600 -v -v -v -k 'bob:there' -k 'carl:frown'"
);
like( $res->output, '/bob:there\r\ncarl:frown\r\n/', "Got headers with multiple -k options" );
$res = NPTest->testCmd(
"./$plugin $host_nonresponsive -wt 1 -ct 2 -t 3"
);
cmp_ok( $res->return_code, '==', 2, "Webserver $host_nonresponsive not responding" );
# was CRITICAL only, but both check_curl and check_http print HTTP CRITICAL (puzzle?!)
like( $res->output, "/HTTP CRITICAL - Invalid HTTP response received from host on port 80: cURL returned 28 - Connection timed out after/", "Output OK");
$res = NPTest->testCmd(
"./$plugin $hostname_invalid -wt 1 -ct 2"
);
cmp_ok( $res->return_code, '==', 2, "Webserver $hostname_invalid not valid" );
# The first part of the message comes from the OS catalogue, so cannot check this.
# On Debian, it is Name or service not known, on Darwin, it is No address associated with nodename
# Is also possible to get a socket timeout if DNS is not responding fast enough
# cURL gives us consistent strings from it's own 'lib/strerror.c'
like( $res->output, "/cURL returned 6 - Could not resolve host:/", "Output OK");
# host header checks
$res = NPTest->testCmd("./$plugin -v -H $host_tcp_http");
like( $res->output, '/^Host: '.$host_tcp_http.'\s*$/ms', "Host Header OK" );
like( $res->output, '/CURLOPT_URL: http:\/\/'.$host_tcp_http.':80\//ms', "Url OK" );
$res = NPTest->testCmd("./$plugin -v -H $host_tcp_http -p 80");
like( $res->output, '/^Host: '.$host_tcp_http.'\s*$/ms', "Host Header OK" );
like( $res->output, '/CURLOPT_URL: http:\/\/'.$host_tcp_http.':80\//ms', "Url OK" );
$res = NPTest->testCmd("./$plugin -v -H $host_tcp_http:8080 -p 80");
like( $res->output, '/^Host: '.$host_tcp_http.':8080\s*$/ms', "Host Header OK" );
like( $res->output, '/CURLOPT_URL: http:\/\/'.$host_tcp_http.':80\//ms', "Url OK" );
$res = NPTest->testCmd("./$plugin -v -H $host_tcp_http:8080 -p 80");
like( $res->output, '/^Host: '.$host_tcp_http.':8080\s*$/ms', "Host Header OK" );
like( $res->output, '/CURLOPT_URL: http:\/\/'.$host_tcp_http.':80\//ms', "Url OK" );
$res = NPTest->testCmd("./$plugin -v -H $host_tcp_http:8080 -p 80 -k 'Host: testhost:8001'");
like( $res->output, '/^Host: testhost:8001\s*$/ms', "Host Header OK" );
like( $res->output, '/CURLOPT_URL: http:\/\/'.$host_tcp_http.':80\//ms', "Url OK" );
$res = NPTest->testCmd("./$plugin -v -I $host_tcp_http -p 80 -k 'Host: testhost:8001'");
like( $res->output, '/^Host: testhost:8001\s*$/ms', "Host Header OK" );
like( $res->output, '/CURLOPT_URL: http:\/\/'.$host_tcp_http.':80\//ms', "Url OK" );
SKIP: {
skip "No internet access", 4 if $internet_access eq "no";
$res = NPTest->testCmd("./$plugin -v -H $host_tls_http -S");
like( $res->output, '/^Host: '.$host_tls_http.'\s*$/ms', "Host Header OK" );
$res = NPTest->testCmd("./$plugin -v -H $host_tls_http:8080 -S -p 443");
like( $res->output, '/^Host: '.$host_tls_http.':8080\s*$/ms', "Host Header OK" );
$res = NPTest->testCmd("./$plugin -v -H $host_tls_http:443 -S -p 443");
like( $res->output, '/^Host: '.$host_tls_http.'\s*$/ms', "Host Header OK" );
$res = NPTest->testCmd("./$plugin -v -H $host_tls_http -D -S -p 443");
like( $res->output, '/(^Host: '.$host_tls_http.'\s*$)|(cURL returned 60)/ms', "Host Header OK" );
};
SKIP: {
skip "No host serving monitoring in index file", 7 unless $host_tcp_http2;
$res = NPTest->testCmd( "./$plugin -H $host_tcp_http2 -r 'monitoring'" );
cmp_ok( $res->return_code, "==", 0, "Got a reference to 'monitoring'");
$res = NPTest->testCmd( "./$plugin -H $host_tcp_http2 -r 'mONiTORing'" );
cmp_ok( $res->return_code, "==", 2, "Not got 'mONiTORing'");
like ( $res->output, "/pattern not found/", "Error message says 'pattern not found'");
$res = NPTest->testCmd( "./$plugin -H $host_tcp_http2 -R 'mONiTORing'" );
cmp_ok( $res->return_code, "==", 0, "But case insensitive doesn't mind 'mONiTORing'");
$res = NPTest->testCmd( "./$plugin -H $host_tcp_http2 -r 'monitoring' --invert-regex" );
cmp_ok( $res->return_code, "==", 2, "Invert results work when found");
like ( $res->output, "/pattern found/", "Error message says 'pattern found'");
$res = NPTest->testCmd( "./$plugin -H $host_tcp_http2 -r 'mONiTORing' --invert-regex" );
cmp_ok( $res->return_code, "==", 0, "And also when not found");
}
SKIP: {
skip "No internet access", 28 if $internet_access eq "no";
$res = NPTest->testCmd(
"./$plugin --ssl $host_tls_http"
);
cmp_ok( $res->return_code, '==', 0, "Can read https for $host_tls_http" );
$res = NPTest->testCmd( "./$plugin -C 1 --ssl $host_tls_http" );
cmp_ok( $res->return_code, '==', 0, "Checking certificate for $host_tls_http");
like ( $res->output, "/Certificate '$host_tls_cert' will expire on/", "Output OK" );
my $saved_cert_output = $res->output;
$res = NPTest->testCmd( "./$plugin -C 8000,1 --ssl $host_tls_http" );
cmp_ok( $res->return_code, '==', 1, "Checking certificate for $host_tls_http");
like ( $res->output, qr/WARNING - Certificate '$host_tls_cert' expires in \d+ day/, "Output Warning" );
$res = NPTest->testCmd( "./$plugin $host_tls_http -C 1" );
is( $res->return_code, 0, "Old syntax for cert checking okay" );
is( $res->output, $saved_cert_output, "Same output as new syntax" );
$res = NPTest->testCmd( "./$plugin -H $host_tls_http -C 1" );
is( $res->return_code, 0, "Updated syntax for cert checking okay" );
is( $res->output, $saved_cert_output, "Same output as new syntax" );
$res = NPTest->testCmd( "./$plugin -C 1 $host_tls_http" );
cmp_ok( $res->output, 'eq', $saved_cert_output, "--ssl option automatically added");
$res = NPTest->testCmd( "./$plugin $host_tls_http -C 1" );
cmp_ok( $res->output, 'eq', $saved_cert_output, "Old syntax for cert checking still works");
# run some certificate checks with faketime
SKIP: {
skip "No faketime binary found", 12 if !$faketime;
$res = NPTest->testCmd("LC_TIME=C TZ=UTC ./$plugin -C 1 $host_tls_http");
like($res->output, qr/OK - Certificate '$host_tls_cert' will expire on/, "Catch cert output");
is( $res->return_code, 0, "Catch cert output exit code" );
my($mon,$day,$hour,$min,$sec,$year) = ($res->output =~ /(\w+)\s+(\d+)\s+(\d+):(\d+):(\d+)\s+(\d+)/);
if(!defined $year) {
die("parsing date failed from: ".$res->output);
}
my $months = {'Jan' => 0, 'Feb' => 1, 'Mar' => 2, 'Apr' => 3, 'May' => 4, 'Jun' => 5, 'Jul' => 6, 'Aug' => 7, 'Sep' => 8, 'Oct' => 9, 'Nov' => 10, 'Dec' => 11};
my $ts = mktime($sec, $min, $hour, $day, $months->{$mon}, $year-1900);
my $time = strftime("%Y-%m-%d %H:%M:%S", localtime($ts));
$res = NPTest->testCmd("LC_TIME=C TZ=UTC faketime -f '".strftime("%Y-%m-%d %H:%M:%S", localtime($ts))."' ./$plugin -C 1 $host_tls_http");
like($res->output, qr/CRITICAL - Certificate '$host_tls_cert' just expired/, "Output on expire date");
is( $res->return_code, 2, "Output on expire date" );
$res = NPTest->testCmd("LC_TIME=C TZ=UTC faketime -f '".strftime("%Y-%m-%d %H:%M:%S", localtime($ts-1))."' ./$plugin -C 1 $host_tls_http");
like($res->output, qr/CRITICAL - Certificate '$host_tls_cert' expires in 0 minutes/, "cert expires in 1 second output");
is( $res->return_code, 2, "cert expires in 1 second exit code" );
$res = NPTest->testCmd("LC_TIME=C TZ=UTC faketime -f '".strftime("%Y-%m-%d %H:%M:%S", localtime($ts-120))."' ./$plugin -C 1 $host_tls_http");
like($res->output, qr/CRITICAL - Certificate '$host_tls_cert' expires in 2 minutes/, "cert expires in 2 minutes output");
is( $res->return_code, 2, "cert expires in 2 minutes exit code" );
$res = NPTest->testCmd("LC_TIME=C TZ=UTC faketime -f '".strftime("%Y-%m-%d %H:%M:%S", localtime($ts-7200))."' ./$plugin -C 1 $host_tls_http");
like($res->output, qr/CRITICAL - Certificate '$host_tls_cert' expires in 2 hours/, "cert expires in 2 hours output");
is( $res->return_code, 2, "cert expires in 2 hours exit code" );
$res = NPTest->testCmd("LC_TIME=C TZ=UTC faketime -f '".strftime("%Y-%m-%d %H:%M:%S", localtime($ts+1))."' ./$plugin -C 1 $host_tls_http");
like($res->output, qr/CRITICAL - Certificate '$host_tls_cert' expired on/, "Certificate expired output");
is( $res->return_code, 2, "Certificate expired exit code" );
};
$res = NPTest->testCmd( "./$plugin --ssl $host_tls_http -E" );
like ( $res->output, '/time_connect=[\d\.]+/', 'Extended Performance Data Output OK' );
like ( $res->output, '/time_ssl=[\d\.]+/', 'Extended Performance Data SSL Output OK' );
$res = NPTest->testCmd(
"./$plugin --ssl -H www.e-paycobalt.com"
);
cmp_ok( $res->return_code, "==", 0, "Can read https for www.e-paycobalt.com (uses AES certificate)" );
$res = NPTest->testCmd( "./$plugin -H www.mozilla.com -u /firefox -f curl" );
is( $res->return_code, 0, "Redirection based on location is okay");
$res = NPTest->testCmd( "./$plugin -H www.mozilla.com --extended-perfdata" );
like ( $res->output, '/time_connect=[\d\.]+/', 'Extended Performance Data Output OK' );
}

View file

@ -88,8 +88,9 @@ $result = NPTest->testCmd(
);
$_ = $result->perf_output;
my ($warn_absth_data, $crit_absth_data, $total_absth_data) = (m/=.[^;]*;(\d+);(\d+);\d+;(\d+)/);
is ($warn_absth_data, $total_absth_data - 20, "Wrong warning in perf data using absolute thresholds");
is ($crit_absth_data, $total_absth_data - 10, "Wrong critical in perf data using absolute thresholds");
# default unit is MiB, but perfdata is always bytes
is ($warn_absth_data, $total_absth_data - (20 * (2 ** 20)), "Wrong warning in perf data using absolute thresholds");
is ($crit_absth_data, $total_absth_data - (10 * (2 ** 20)), "Wrong critical in perf data using absolute thresholds");
# Then check percent thresholds.
$result = NPTest->testCmd(
@ -119,7 +120,7 @@ like ( $result->only_output, qr/$more_free/, "Have disk name in text");
$result = NPTest->testCmd( "./check_disk -w 1 -c 1 -p $more_free -p $less_free" );
cmp_ok( $result->return_code, '==', 0, "At least 1 MB available on $more_free and $less_free");
$_ = $result->output;
my ($free_mb_on_mp1, $free_mb_on_mp2) = (m/(\d+) MB .* (\d+) MB /g);
my ($free_mb_on_mp1, $free_mb_on_mp2) = (m/(\d+)MiB .* (\d+)MiB /g);
my $free_mb_on_all = $free_mb_on_mp1 + $free_mb_on_mp2;
@ -248,11 +249,11 @@ $result = NPTest->testCmd( "./check_disk -w 100% -c 100% ".${mountpoint_valid} )
cmp_ok( $result->return_code, "==", 2, "100% empty" );
like( $result->output, $failureOutput, "Right output" );
$result = NPTest->testCmd( "./check_disk -w 100000 -c 100000 $mountpoint_valid" );
cmp_ok( $result->return_code, '==', 2, "Check for 100GB free" );
$result = NPTest->testCmd( "./check_disk -w 100000000 -c 100000000 $mountpoint_valid" );
cmp_ok( $result->return_code, '==', 2, "Check for 100TB free" );
$result = NPTest->testCmd( "./check_disk -w 100 -c 100 -u GB ".${mountpoint_valid} ); # 100 GB empty
cmp_ok( $result->return_code, "==", 2, "100 GB empty" );
$result = NPTest->testCmd( "./check_disk -w 100 -c 100 -u TB ".${mountpoint_valid} ); # 100 TB empty
cmp_ok( $result->return_code, "==", 2, "100 TB empty" );
# Checking old syntax of check_disk warn crit [fs], with warn/crit at USED% thresholds

View file

@ -10,7 +10,7 @@ use NPTest;
plan skip_all => "check_dns not compiled" unless (-x "check_dns");
plan tests => 19;
plan tests => 23;
my $successOutput = '/DNS OK: [\.0-9]+ seconds? response time/';
@ -105,3 +105,11 @@ cmp_ok( $res->return_code, '==', 0, "Got expected address");
$res = NPTest->testCmd("./check_dns -H $hostname_valid -a $hostname_invalid_cidr -t 5");
cmp_ok( $res->return_code, '==', 2, "Got wrong address");
like ( $res->output, "/^DNS CRITICAL.*expected '$hostname_invalid_cidr' but got '$hostname_valid_ip'".'$/', "Output OK");
$res = NPTest->testCmd("./check_dns -H $hostname_valid -n");
cmp_ok( $res->return_code, '==', 2, "Found $hostname_valid");
like ( $res->output, "/^DNS CRITICAL.*Domain '$hostname_valid' was found by the server:/", "Output OK");
$res = NPTest->testCmd("./check_dns -H $hostname_invalid -n");
cmp_ok( $res->return_code, '==', 0, "Did not find $hostname_invalid");
like ( $res->output, $successOutput, "Output OK" );

View file

@ -5,40 +5,30 @@
#
use strict;
use Test;
use Test::More;
use NPTest;
use vars qw($tests);
my $host_responsive = getTestParameter("NP_HOST_RESPONSIVE", "The hostname of system responsive to network requests", "localhost");
my $host_nonresponsive = getTestParameter("NP_HOST_NONRESPONSIVE", "The hostname of system not responsive to network requests", "10.0.0.1");
my $hostname_invalid = getTestParameter("NP_HOSTNAME_INVALID", "An invalid (not known to DNS) hostname", "nosuchhost");
BEGIN {$tests = 4; plan tests => $tests}
my $successOutput = '/^FPING OK - /';
my $failureOutput = '/^FPING CRITICAL - /';
my $host_responsive = getTestParameter( "host_responsive", "NP_HOST_RESPONSIVE", "localhost",
"The hostname of system responsive to network requests" );
my $host_nonresponsive = getTestParameter( "host_nonresponsive", "NP_HOST_NONRESPONSIVE", "10.0.0.1",
"The hostname of system not responsive to network requests" );
my $hostname_invalid = getTestParameter( "hostname_invalid", "NP_HOSTNAME_INVALID", "nosuchhost",
"An invalid (not known to DNS) hostname" );
my $t;
my $res;
my $fping = qx(which fping 2> /dev/null);
chomp($fping);
if( ! -x "./check_fping") {
$t += skipMissingCmd( "./check_fping", $tests );
plan skip_all => "check_fping not found, skipping tests";
}
elsif ( $> != 0 && (!$fping || ! -u $fping)) {
$t += skipMsg( "./check_fping", $tests );
elsif ( !$fping || !-x $fping ) {
plan skip_all => "fping not found or cannot be executed, skipping tests";
} else {
$t += checkCmd( "./check_fping $host_responsive", 0, $successOutput );
$t += checkCmd( "./check_fping $host_nonresponsive", [ 1, 2 ] );
$t += checkCmd( "./check_fping $hostname_invalid", [ 1, 2 ] );
}
plan tests => 3;
$res = NPTest->testCmd( "./check_fping $host_responsive" );
cmp_ok( $res->return_code, '==', 0, "Responsive host returns OK");
exit(0) if defined($Test::Harness::VERSION);
exit($tests - $t);
$res = NPTest->testCmd( "./check_fping $host_nonresponsive" );
cmp_ok( $res->return_code, '==', 2, "Non-Responsive host returns Critical");
$res = NPTest->testCmd( "./check_fping $hostname_invalid" );
cmp_ok( $res->return_code, '==', 3, "Invalid host returns Unknown");
}

View file

@ -11,14 +11,9 @@ use NPTest;
use vars qw($tests);
BEGIN {$tests = 4; plan tests => $tests}
my $host_tcp_ftp = getTestParameter( "host_tcp_ftp", "NP_HOST_TCP_FTP", "localhost",
"A host providing the FTP Service (an FTP server)");
my $host_nonresponsive = getTestParameter( "host_nonresponsive", "NP_HOST_NONRESPONSIVE", "10.0.0.1",
"The hostname of system not responsive to network requests" );
my $hostname_invalid = getTestParameter( "hostname_invalid", "NP_HOSTNAME_INVALID", "nosuchhost",
"An invalid (not known to DNS) hostname" );
my $host_tcp_ftp = getTestParameter("NP_HOST_TCP_FTP", "A host providing the FTP Service (an FTP server)", "localhost");
my $host_nonresponsive = getTestParameter("NP_HOST_NONRESPONSIVE", "The hostname of system not responsive to network requests", "10.0.0.1");
my $hostname_invalid = getTestParameter("NP_HOSTNAME_INVALID", "An invalid (not known to DNS) hostname", "nosuchhost");
my $successOutput = '/FTP OK -\s+[0-9]?\.?[0-9]+ second response time/';

View file

@ -9,54 +9,46 @@ use Test::More;
use POSIX qw/mktime strftime/;
use NPTest;
plan tests => 49;
plan tests => 50;
my $successOutput = '/OK.*HTTP.*second/';
my $res;
my $plugin = 'check_http';
$plugin = 'check_curl' if $0 =~ m/check_curl/mx;
my $host_tcp_http = getTestParameter( "NP_HOST_TCP_HTTP",
"A host providing the HTTP Service (a web server)",
"localhost" );
my $host_nonresponsive = getTestParameter( "NP_HOST_NONRESPONSIVE",
"The hostname of system not responsive to network requests",
"10.0.0.1" );
my $hostname_invalid = getTestParameter( "NP_HOSTNAME_INVALID",
"An invalid (not known to DNS) hostname",
"nosuchhost");
my $internet_access = getTestParameter( "NP_INTERNET_ACCESS",
"Is this system directly connected to the internet?",
"yes");
my $host_tcp_http2 = getTestParameter( "NP_HOST_TCP_HTTP2",
"A host providing an index page containing the string 'monitoring'",
"test.monitoring-plugins.org" );
my $host_tcp_http = getTestParameter("NP_HOST_TCP_HTTP", "A host providing the HTTP Service (a web server)", "localhost");
my $host_tls_http = getTestParameter("NP_HOST_TLS_HTTP", "A host providing the HTTPS Service (a tls web server)", "localhost");
my $host_tls_cert = getTestParameter("NP_HOST_TLS_CERT", "the common name of the certificate.", "localhost");
my $host_nonresponsive = getTestParameter("NP_HOST_NONRESPONSIVE", "The hostname of system not responsive to network requests", "10.0.0.1");
my $hostname_invalid = getTestParameter("NP_HOSTNAME_INVALID", "An invalid (not known to DNS) hostname", "nosuchhost");
my $internet_access = getTestParameter("NP_INTERNET_ACCESS", "Is this system directly connected to the internet?", "yes");
my $host_tcp_http2 = getTestParameter("NP_HOST_TCP_HTTP2", "A host providing an index page containing the string 'monitoring'", "test.monitoring-plugins.org");
my $host_tcp_proxy = getTestParameter("NP_HOST_TCP_PROXY", "A host providing a HTTP proxy with CONNECT support", "localhost");
my $port_tcp_proxy = getTestParameter("NP_PORT_TCP_PROXY", "Port of the proxy with HTTP and CONNECT support", "3128");
my $faketime = -x '/usr/bin/faketime' ? 1 : 0;
$res = NPTest->testCmd(
"./check_http $host_tcp_http -wt 300 -ct 600"
"./$plugin $host_tcp_http -wt 300 -ct 600"
);
cmp_ok( $res->return_code, '==', 0, "Webserver $host_tcp_http responded" );
like( $res->output, $successOutput, "Output OK" );
$res = NPTest->testCmd(
"./check_http $host_tcp_http -wt 300 -ct 600 -v -v -v -k 'bob:there' -k 'carl:frown'"
"./$plugin $host_tcp_http -wt 300 -ct 600 -v -v -v -k 'bob:there' -k 'carl:frown'"
);
like( $res->output, '/bob:there\r\ncarl:frown\r\n/', "Got headers with multiple -k options" );
$res = NPTest->testCmd(
"./check_http $host_nonresponsive -wt 1 -ct 2 -t 3"
"./$plugin $host_nonresponsive -wt 1 -ct 2 -t 3"
);
cmp_ok( $res->return_code, '==', 2, "Webserver $host_nonresponsive not responding" );
cmp_ok( $res->output, 'eq', "CRITICAL - Socket timeout after 3 seconds", "Output OK");
$res = NPTest->testCmd(
"./check_http $hostname_invalid -wt 1 -ct 2"
"./$plugin $hostname_invalid -wt 1 -ct 2"
);
cmp_ok( $res->return_code, '==', 2, "Webserver $hostname_invalid not valid" );
# The first part of the message comes from the OS catalogue, so cannot check this.
@ -65,87 +57,87 @@ cmp_ok( $res->return_code, '==', 2, "Webserver $hostname_invalid not valid" );
like( $res->output, "/Unable to open TCP socket|Socket timeout after/", "Output OK");
# host header checks
$res = NPTest->testCmd("./check_http -v -H $host_tcp_http");
$res = NPTest->testCmd("./$plugin -v -H $host_tcp_http");
like( $res->output, '/^Host: '.$host_tcp_http.'\s*$/ms', "Host Header OK" );
$res = NPTest->testCmd("./check_http -v -H $host_tcp_http -p 80");
$res = NPTest->testCmd("./$plugin -v -H $host_tcp_http -p 80");
like( $res->output, '/^Host: '.$host_tcp_http.'\s*$/ms', "Host Header OK" );
$res = NPTest->testCmd("./check_http -v -H $host_tcp_http:8080 -p 80");
$res = NPTest->testCmd("./$plugin -v -H $host_tcp_http:8080 -p 80");
like( $res->output, '/^Host: '.$host_tcp_http.':8080\s*$/ms', "Host Header OK" );
$res = NPTest->testCmd("./check_http -v -H $host_tcp_http:8080 -p 80");
$res = NPTest->testCmd("./$plugin -v -H $host_tcp_http:8080 -p 80");
like( $res->output, '/^Host: '.$host_tcp_http.':8080\s*$/ms', "Host Header OK" );
SKIP: {
skip "No internet access", 3 if $internet_access eq "no";
$res = NPTest->testCmd("./check_http -v -H www.verisign.com -S");
like( $res->output, '/^Host: www.verisign.com\s*$/ms', "Host Header OK" );
$res = NPTest->testCmd("./$plugin -v -H $host_tls_http -S");
like( $res->output, '/^Host: '.$host_tls_http.'\s*$/ms', "Host Header OK" );
$res = NPTest->testCmd("./check_http -v -H www.verisign.com:8080 -S -p 443");
like( $res->output, '/^Host: www.verisign.com:8080\s*$/ms', "Host Header OK" );
$res = NPTest->testCmd("./$plugin -v -H $host_tls_http:8080 -S -p 443");
like( $res->output, '/^Host: '.$host_tls_http.':8080\s*$/ms', "Host Header OK" );
$res = NPTest->testCmd("./check_http -v -H www.verisign.com:443 -S -p 443");
like( $res->output, '/^Host: www.verisign.com\s*$/ms', "Host Header OK" );
$res = NPTest->testCmd("./$plugin -v -H $host_tls_http:443 -S -p 443");
like( $res->output, '/^Host: '.$host_tls_http.'\s*$/ms', "Host Header OK" );
};
SKIP: {
skip "No host serving monitoring in index file", 7 unless $host_tcp_http2;
$res = NPTest->testCmd( "./check_http -H $host_tcp_http2 -r 'monitoring'" );
$res = NPTest->testCmd( "./$plugin -H $host_tcp_http2 -r 'monitoring'" );
cmp_ok( $res->return_code, "==", 0, "Got a reference to 'monitoring'");
$res = NPTest->testCmd( "./check_http -H $host_tcp_http2 -r 'mONiTORing'" );
$res = NPTest->testCmd( "./$plugin -H $host_tcp_http2 -r 'mONiTORing'" );
cmp_ok( $res->return_code, "==", 2, "Not got 'mONiTORing'");
like ( $res->output, "/pattern not found/", "Error message says 'pattern not found'");
$res = NPTest->testCmd( "./check_http -H $host_tcp_http2 -R 'mONiTORing'" );
$res = NPTest->testCmd( "./$plugin -H $host_tcp_http2 -R 'mONiTORing'" );
cmp_ok( $res->return_code, "==", 0, "But case insensitive doesn't mind 'mONiTORing'");
$res = NPTest->testCmd( "./check_http -H $host_tcp_http2 -r 'monitoring' --invert-regex" );
$res = NPTest->testCmd( "./$plugin -H $host_tcp_http2 -r 'monitoring' --invert-regex" );
cmp_ok( $res->return_code, "==", 2, "Invert results work when found");
like ( $res->output, "/pattern found/", "Error message says 'pattern found'");
$res = NPTest->testCmd( "./check_http -H $host_tcp_http2 -r 'mONiTORing' --invert-regex" );
$res = NPTest->testCmd( "./$plugin -H $host_tcp_http2 -r 'mONiTORing' --invert-regex" );
cmp_ok( $res->return_code, "==", 0, "And also when not found");
}
SKIP: {
skip "No internet access", 16 if $internet_access eq "no";
skip "No internet access", 23 if $internet_access eq "no";
$res = NPTest->testCmd(
"./check_http --ssl www.verisign.com"
"./$plugin --ssl $host_tls_http"
);
cmp_ok( $res->return_code, '==', 0, "Can read https for www.verisign.com" );
cmp_ok( $res->return_code, '==', 0, "Can read https for $host_tls_http" );
$res = NPTest->testCmd( "./check_http -C 1 --ssl www.verisign.com" );
cmp_ok( $res->return_code, '==', 0, "Checking certificate for www.verisign.com");
like ( $res->output, "/Certificate 'www.verisign.com' will expire on/", "Output OK" );
$res = NPTest->testCmd( "./$plugin -C 1 --ssl $host_tls_http" );
cmp_ok( $res->return_code, '==', 0, "Checking certificate for $host_tls_http");
like ( $res->output, "/Certificate '$host_tls_cert' will expire on/", "Output OK" );
my $saved_cert_output = $res->output;
$res = NPTest->testCmd( "./check_http -C 8000,1 --ssl www.verisign.com" );
cmp_ok( $res->return_code, '==', 1, "Checking certificate for www.verisign.com");
like ( $res->output, qr/WARNING - Certificate 'www.verisign.com' expires in \d+ day/, "Output Warning" );
$res = NPTest->testCmd( "./$plugin -C 8000,1 --ssl $host_tls_http" );
cmp_ok( $res->return_code, '==', 1, "Checking certificate for $host_tls_http");
like ( $res->output, qr/WARNING - Certificate '$host_tls_cert' expires in \d+ day/, "Output Warning" );
$res = NPTest->testCmd( "./check_http www.verisign.com -C 1" );
$res = NPTest->testCmd( "./$plugin $host_tls_http -C 1" );
is( $res->return_code, 0, "Old syntax for cert checking okay" );
is( $res->output, $saved_cert_output, "Same output as new syntax" );
$res = NPTest->testCmd( "./check_http -H www.verisign.com -C 1" );
$res = NPTest->testCmd( "./$plugin -H $host_tls_http -C 1" );
is( $res->return_code, 0, "Updated syntax for cert checking okay" );
is( $res->output, $saved_cert_output, "Same output as new syntax" );
$res = NPTest->testCmd( "./check_http -C 1 www.verisign.com" );
$res = NPTest->testCmd( "./$plugin -C 1 $host_tls_http" );
cmp_ok( $res->output, 'eq', $saved_cert_output, "--ssl option automatically added");
$res = NPTest->testCmd( "./check_http www.verisign.com -C 1" );
$res = NPTest->testCmd( "./$plugin $host_tls_http -C 1" );
cmp_ok( $res->output, 'eq', $saved_cert_output, "Old syntax for cert checking still works");
# run some certificate checks with faketime
SKIP: {
skip "No faketime binary found", 12 if !$faketime;
$res = NPTest->testCmd("LC_TIME=C TZ=UTC ./check_http -C 1 www.verisign.com");
like($res->output, qr/OK - Certificate 'www.verisign.com' will expire on/, "Catch cert output");
skip "No faketime binary found", 7 if !$faketime;
$res = NPTest->testCmd("LC_TIME=C TZ=UTC ./$plugin -C 1 $host_tls_http");
like($res->output, qr/OK - Certificate '$host_tls_cert' will expire on/, "Catch cert output");
is( $res->return_code, 0, "Catch cert output exit code" );
my($mon,$day,$hour,$min,$sec,$year) = ($res->output =~ /(\w+)\s+(\d+)\s+(\d+):(\d+):(\d+)\s+(\d+)/);
if(!defined $year) {
@ -154,40 +146,51 @@ SKIP: {
my $months = {'Jan' => 0, 'Feb' => 1, 'Mar' => 2, 'Apr' => 3, 'May' => 4, 'Jun' => 5, 'Jul' => 6, 'Aug' => 7, 'Sep' => 8, 'Oct' => 9, 'Nov' => 10, 'Dec' => 11};
my $ts = mktime($sec, $min, $hour, $day, $months->{$mon}, $year-1900);
my $time = strftime("%Y-%m-%d %H:%M:%S", localtime($ts));
$res = NPTest->testCmd("LC_TIME=C TZ=UTC faketime -f '".strftime("%Y-%m-%d %H:%M:%S", localtime($ts))."' ./check_http -C 1 www.verisign.com");
like($res->output, qr/CRITICAL - Certificate 'www.verisign.com' just expired/, "Output on expire date");
is( $res->return_code, 2, "Output on expire date" );
$res = NPTest->testCmd("LC_TIME=C TZ=UTC faketime -f '".strftime("%Y-%m-%d %H:%M:%S", localtime($ts))."' ./$plugin -C 1 $host_tls_http");
like($res->output, qr/CRITICAL - Certificate '$host_tls_cert' just expired/, "Output on expire date");
$res = NPTest->testCmd("LC_TIME=C TZ=UTC faketime -f '".strftime("%Y-%m-%d %H:%M:%S", localtime($ts-1))."' ./check_http -C 1 www.verisign.com");
like($res->output, qr/CRITICAL - Certificate 'www.verisign.com' expires in 0 minutes/, "cert expires in 1 second output");
is( $res->return_code, 2, "cert expires in 1 second exit code" );
$res = NPTest->testCmd("LC_TIME=C TZ=UTC faketime -f '".strftime("%Y-%m-%d %H:%M:%S", localtime($ts-1))."' ./$plugin -C 1 $host_tls_http");
like($res->output, qr/CRITICAL - Certificate '$host_tls_cert' expires in 0 minutes/, "cert expires in 1 second output");
$res = NPTest->testCmd("LC_TIME=C TZ=UTC faketime -f '".strftime("%Y-%m-%d %H:%M:%S", localtime($ts-120))."' ./check_http -C 1 www.verisign.com");
like($res->output, qr/CRITICAL - Certificate 'www.verisign.com' expires in 2 minutes/, "cert expires in 2 minutes output");
is( $res->return_code, 2, "cert expires in 2 minutes exit code" );
$res = NPTest->testCmd("LC_TIME=C TZ=UTC faketime -f '".strftime("%Y-%m-%d %H:%M:%S", localtime($ts-120))."' ./$plugin -C 1 $host_tls_http");
like($res->output, qr/CRITICAL - Certificate '$host_tls_cert' expires in 2 minutes/, "cert expires in 2 minutes output");
$res = NPTest->testCmd("LC_TIME=C TZ=UTC faketime -f '".strftime("%Y-%m-%d %H:%M:%S", localtime($ts-7200))."' ./check_http -C 1 www.verisign.com");
like($res->output, qr/CRITICAL - Certificate 'www.verisign.com' expires in 2 hours/, "cert expires in 2 hours output");
is( $res->return_code, 2, "cert expires in 2 hours exit code" );
$res = NPTest->testCmd("LC_TIME=C TZ=UTC faketime -f '".strftime("%Y-%m-%d %H:%M:%S", localtime($ts-7200))."' ./$plugin -C 1 $host_tls_http");
like($res->output, qr/CRITICAL - Certificate '$host_tls_cert' expires in 2 hours/, "cert expires in 2 hours output");
$res = NPTest->testCmd("LC_TIME=C TZ=UTC faketime -f '".strftime("%Y-%m-%d %H:%M:%S", localtime($ts+1))."' ./check_http -C 1 www.verisign.com");
like($res->output, qr/CRITICAL - Certificate 'www.verisign.com' expired on/, "Certificate expired output");
is( $res->return_code, 2, "Certificate expired exit code" );
$res = NPTest->testCmd("LC_TIME=C TZ=UTC faketime -f '".strftime("%Y-%m-%d %H:%M:%S", localtime($ts+1))."' ./$plugin -C 1 $host_tls_http");
like($res->output, qr/CRITICAL - Certificate '$host_tls_cert' expired on/, "Certificate expired output");
};
$res = NPTest->testCmd( "./check_http --ssl www.verisign.com -E" );
$res = NPTest->testCmd( "./$plugin --ssl $host_tls_http -E" );
like ( $res->output, '/time_connect=[\d\.]+/', 'Extended Performance Data Output OK' );
like ( $res->output, '/time_ssl=[\d\.]+/', 'Extended Performance Data SSL Output OK' );
$res = NPTest->testCmd(
"./check_http --ssl -H www.e-paycobalt.com"
"./$plugin --ssl -H www.e-paycobalt.com"
);
cmp_ok( $res->return_code, "==", 0, "Can read https for www.e-paycobalt.com (uses AES certificate)" );
$res = NPTest->testCmd( "./check_http -H www.mozilla.com -u /firefox -f follow" );
$res = NPTest->testCmd( "./$plugin -H www.mozilla.com -u /firefox -f follow" );
is( $res->return_code, 0, "Redirection based on location is okay");
$res = NPTest->testCmd( "./check_http -H www.mozilla.com --extended-perfdata" );
$res = NPTest->testCmd( "./$plugin -H www.mozilla.com --extended-perfdata" );
like ( $res->output, '/time_connect=[\d\.]+/', 'Extended Performance Data Output OK' );
}
SKIP: {
skip "No internet access or proxy configured", 6 if $internet_access eq "no" or ! $host_tcp_proxy;
$res = NPTest->testCmd( "./$plugin -I $host_tcp_proxy -p $port_tcp_proxy -u http://$host_tcp_http -e 200,301,302");
is( $res->return_code, 0, "Proxy HTTP works");
like($res->output, qr/OK: Status line output matched/, "Proxy HTTP Output is sufficent");
$res = NPTest->testCmd( "./$plugin -I $host_tcp_proxy -p $port_tcp_proxy -H $host_tls_http -S -j CONNECT");
is( $res->return_code, 0, "Proxy HTTP CONNECT works");
like($res->output, qr/HTTP OK:/, "Proxy HTTP CONNECT output sufficent");
$res = NPTest->testCmd( "./$plugin -I $host_tcp_proxy -p $port_tcp_proxy -H $host_tls_http -S -j CONNECT:HEAD");
is( $res->return_code, 0, "Proxy HTTP CONNECT works with override method");
like($res->output, qr/HTTP OK:/, "Proxy HTTP CONNECT output sufficent");
}

View file

@ -8,17 +8,10 @@ use strict;
use Test::More tests => 7;
use NPTest;
my $host_tcp_smtp = getTestParameter( "host_tcp_smtp", "NP_HOST_TCP_SMTP", "mailhost",
"A host providing an STMP Service (a mail server)");
my $host_tcp_imap = getTestParameter( "host_tcp_imap", "NP_HOST_TCP_IMAP", $host_tcp_smtp,
"A host providing an IMAP Service (a mail server)");
my $host_nonresponsive = getTestParameter( "host_nonresponsive", "NP_HOST_NONRESPONSIVE", "10.0.0.1",
"The hostname of system not responsive to network requests" );
my $hostname_invalid = getTestParameter( "hostname_invalid", "NP_HOSTNAME_INVALID", "nosuchhost",
"An invalid (not known to DNS) hostname" );
my $host_tcp_smtp = getTestParameter("NP_HOST_TCP_SMTP", "A host providing an STMP Service (a mail server)", "mailhost");
my $host_tcp_imap = getTestParameter("NP_HOST_TCP_IMAP", "A host providing an IMAP Service (a mail server)", $host_tcp_smtp);
my $host_nonresponsive = getTestParameter("NP_HOST_NONRESPONSIVE", "The hostname of system not responsive to network requests", "10.0.0.1");
my $hostname_invalid = getTestParameter("NP_HOSTNAME_INVALID", "An invalid (not known to DNS) hostname", "nosuchhost");
my $t;

View file

@ -10,23 +10,9 @@ use NPTest;
plan tests => 10;
my $host_tcp_jabber = getTestParameter(
"NP_HOST_TCP_JABBER",
"A host providing the Jabber Service",
"jabber.org"
);
my $host_nonresponsive = getTestParameter(
"NP_HOST_NONRESPONSIVE",
"The hostname of system not responsive to network requests",
"10.0.0.1",
);
my $hostname_invalid = getTestParameter(
"NP_HOSTNAME_INVALID",
"An invalid (not known to DNS) hostname",
"nosuchhost",
);
my $host_tcp_jabber = getTestParameter("NP_HOST_TCP_JABBER", "A host providing the Jabber Service", "jabber.de");
my $host_nonresponsive = getTestParameter("NP_HOST_NONRESPONSIVE", "The hostname of system not responsive to network requests", "10.0.0.1");
my $hostname_invalid = getTestParameter("NP_HOSTNAME_INVALID", "An invalid (not known to DNS) hostname", "nosuchhost");
my $jabberOK = '/JABBER OK\s-\s\d+\.\d+\ssecond response time on '.$host_tcp_jabber.' port 5222/';

View file

@ -9,19 +9,10 @@ use warnings;
use Test::More;
use NPTest;
my $host_tcp_ldap = getTestParameter("NP_HOST_TCP_LDAP",
"A host providing the LDAP Service",
"localhost" );
my $ldap_base_dn = getTestParameter("NP_LDAP_BASE_DN",
"A base dn for the LDAP Service",
"cn=admin" );
my $host_nonresponsive = getTestParameter("host_nonresponsive", "NP_HOST_NONRESPONSIVE", "10.0.0.1",
"The hostname of system not responsive to network requests" );
my $hostname_invalid = getTestParameter("hostname_invalid", "NP_HOSTNAME_INVALID", "nosuchhost",
"An invalid (not known to DNS) hostname" );
my $host_tcp_ldap = getTestParameter("NP_HOST_TCP_LDAP", "A host providing the LDAP Service", "localhost");
my $ldap_base_dn = getTestParameter("NP_LDAP_BASE_DN", "A base dn for the LDAP Service", "cn=admin");
my $host_nonresponsive = getTestParameter("NP_HOST_NONRESPONSIVE", "The hostname of system not responsive to network requests", "10.0.0.1");
my $hostname_invalid = getTestParameter("NP_HOSTNAME_INVALID", "An invalid (not known to DNS) hostname", "nosuchhost");
my($result, $cmd);
my $command = './check_ldap';

View file

@ -11,8 +11,8 @@ use NPTest;
my $res;
my $loadValue = "[0-9]+\.?[0-9]+";
my $successOutput = "/^OK - load average: $loadValue, $loadValue, $loadValue/";
my $failureOutput = "/^CRITICAL - load average: $loadValue, $loadValue, $loadValue/";
my $successOutput = "/^LOAD OK - load average: $loadValue, $loadValue, $loadValue/";
my $failureOutput = "/^LOAD CRITICAL - load average: $loadValue, $loadValue, $loadValue/";
plan tests => 11;

View file

@ -21,30 +21,11 @@ plan skip_all => "check_mysql not compiled" unless (-x "check_mysql");
plan tests => 15;
my $bad_login_output = '/Access denied for user /';
my $mysqlserver = getTestParameter(
"NP_MYSQL_SERVER",
"A MySQL Server hostname or IP with no slaves setup"
);
my $mysqlsocket = getTestParameter(
"NP_MYSQL_SOCKET",
"Full path to a MySQL Server socket with no slaves setup"
);
my $mysql_login_details = getTestParameter(
"MYSQL_LOGIN_DETAILS",
"Command line parameters to specify login access (requires " .
"REPLICATION CLIENT privleges)",
"-u test -ptest",
);
my $with_slave = getTestParameter(
"NP_MYSQL_WITH_SLAVE",
"MySQL server with slaves setup"
);
my $with_slave_login = getTestParameter(
"NP_MYSQL_WITH_SLAVE_LOGIN",
"Login details for server with slave (requires REPLICATION CLIENT " .
"privleges)",
$mysql_login_details || "-u test -ptest"
);
my $mysqlserver = getTestParameter("NP_MYSQL_SERVER", "A MySQL Server hostname or IP with no slaves setup");
my $mysqlsocket = getTestParameter("NP_MYSQL_SOCKET", "Full path to a MySQL Server socket with no slaves setup");
my $mysql_login_details = getTestParameter("NP_MYSQL_LOGIN_DETAILS", "Command line parameters to specify login access (requires REPLICATION CLIENT privleges)", "-u test -ptest");
my $with_slave = getTestParameter("NP_MYSQL_WITH_SLAVE", "MySQL server with slaves setup");
my $with_slave_login = getTestParameter("NP_MYSQL_WITH_SLAVE_LOGIN", "Login details for server with slave (requires REPLICATION CLIENT privleges)", $mysql_login_details || "-u test -ptest");
my $result;

View file

@ -17,15 +17,8 @@ use vars qw($tests);
plan skip_all => "check_mysql_query not compiled" unless (-x "check_mysql_query");
my $mysqlserver = getTestParameter(
"NP_MYSQL_SERVER",
"A MySQL Server with no slaves setup"
);
my $mysql_login_details = getTestParameter(
"MYSQL_LOGIN_DETAILS",
"Command line parameters to specify login access",
"-u user -ppw -d db",
);
my $mysqlserver = getTestParameter("NP_MYSQL_SERVER", "A MySQL Server with no slaves setup");
my $mysql_login_details = getTestParameter("NP_MYSQL_LOGIN_DETAILS", "Command line parameters to specify login access", "-u user -ppw -d db");
my $result;
if (! $mysqlserver) {

View file

@ -15,18 +15,12 @@ BEGIN {
my $res;
my $host_snmp = getTestParameter( "host_snmp", "NP_HOST_SNMP", "localhost",
"A host providing an SNMP Service");
my $host_snmp = getTestParameter("NP_HOST_SNMP", "A host providing an SNMP Service", "localhost");
my $snmp_community = getTestParameter("NP_SNMP_COMMUNITY", "The SNMP Community string for SNMP Testing (assumes snmp v1)", "public");
my $host_nonresponsive = getTestParameter("NP_HOST_NONRESPONSIVE", "The hostname of system not responsive to network requests", "10.0.0.1");
my $hostname_invalid = getTestParameter("NP_HOSTNAME_INVALID", "An invalid (not known to DNS) hostname", "nosuchhost");
my $user_snmp = getTestParameter("NP_SNMP_USER", "An SNMP user", "auth_md5");
my $snmp_community = getTestParameter( "snmp_community", "NP_SNMP_COMMUNITY", "public",
"The SNMP Community string for SNMP Testing (assumes snmp v1)" );
my $host_nonresponsive = getTestParameter( "host_nonresponsive", "NP_HOST_NONRESPONSIVE", "10.0.0.1",
"The hostname of system not responsive to network requests" );
my $hostname_invalid = getTestParameter( "hostname_invalid", "NP_HOSTNAME_INVALID", "nosuchhost",
"An invalid (not known to DNS) hostname" );
my $user_snmp = getTestParameter( "user_snmp", "NP_SNMP_USER", "auth_md5", "An SNMP user");
$res = NPTest->testCmd( "./check_snmp -t 1" );
is( $res->return_code, 3, "No host name" );
@ -154,9 +148,9 @@ SKIP: {
cmp_ok( $res->return_code, '==', 0, "Timetick used as a string");
like($res->output, '/^SNMP OK - Timeticks:\s\(\d+\)\s+(?:\d+ days?,\s+)?\d+:\d+:\d+\.\d+\s.*$/', "Timetick used as a string, result printed rather than parsed");
$res = NPTest->testCmd( "./check_snmp -H $host_snmp -C $snmp_community -o HOST-RESOURCES-MIB::hrSWRunParameters.1");
cmp_ok( $res->return_code, '==', 0, "Timetick used as a string");
is( $res->output, 'SNMP OK - "" | ', "snmp response without datatype" );
$res = NPTest->testCmd( "./check_snmp -H $host_snmp -C $snmp_community -o HOST-RESOURCES-MIB::hrSWRunName.1");
cmp_ok( $res->return_code, '==', 0, "snmp response without datatype");
like( $res->output, '/^SNMP OK - "(systemd|init)" \| $/', "snmp response without datatype" );
}
SKIP: {

View file

@ -9,17 +9,9 @@ use Test::More;
use NPTest;
# Required parameters
my $ssh_host = getTestParameter("NP_SSH_HOST",
"A host providing SSH service",
"localhost");
my $host_nonresponsive = getTestParameter("NP_HOST_NONRESPONSIVE",
"The hostname of system not responsive to network requests",
"10.0.0.1" );
my $hostname_invalid = getTestParameter("NP_HOSTNAME_INVALID",
"An invalid (not known to DNS) hostname",
"nosuchhost" );
my $ssh_host = getTestParameter("NP_SSH_HOST", "A host providing SSH service", "localhost");
my $host_nonresponsive = getTestParameter("NP_HOST_NONRESPONSIVE", "The hostname of system not responsive to network requests", "10.0.0.1" );
my $hostname_invalid = getTestParameter("NP_HOSTNAME_INVALID", "An invalid (not known to DNS) hostname", "nosuchhost" );
plan skip_all => "SSH_HOST must be defined" unless $ssh_host;

View file

@ -8,9 +8,9 @@ use strict;
use Test::More tests => 8;
use NPTest;
my $successOutput = '/^SWAP OK - [0-9]+\% free \([0-9]+ MB out of [0-9]+ MB\)/';
my $failureOutput = '/^SWAP CRITICAL - [0-9]+\% free \([0-9]+ MB out of [0-9]+ MB\)/';
my $warnOutput = '/^SWAP WARNING - [0-9]+\% free \([0-9]+ MB out of [0-9]+ MB\)/';
my $successOutput = '/^SWAP OK - [0-9]+\% free \([0-9]+MB out of [0-9]+MB\)/';
my $failureOutput = '/^SWAP CRITICAL - [0-9]+\% free \([0-9]+MB out of [0-9]+MB\)/';
my $warnOutput = '/^SWAP WARNING - [0-9]+\% free \([0-9]+MB out of [0-9]+MB\)/';
my $result;

View file

@ -15,18 +15,11 @@ BEGIN {
}
my $host_tcp_http = getTestParameter( "host_tcp_http", "NP_HOST_TCP_HTTP", "localhost",
"A host providing the HTTP Service (a web server)" );
my $host_nonresponsive = getTestParameter( "host_nonresponsive", "NP_HOST_NONRESPONSIVE", "10.0.0.1",
"The hostname of system not responsive to network requests" );
my $hostname_invalid = getTestParameter( "hostname_invalid", "NP_HOSTNAME_INVALID", "nosuchhost",
"An invalid (not known to DNS) hostname" );
my $internet_access = getTestParameter( "NP_INTERNET_ACCESS",
"Is this system directly connected to the internet?",
"yes");
my $host_tcp_http = getTestParameter("NP_HOST_TCP_HTTP", "A host providing the HTTP Service (a web server)", "localhost");
my $host_tls_http = getTestParameter("NP_HOST_TLS_HTTP", "A host providing the HTTPS Service (a tls web server)", "localhost");
my $host_nonresponsive = getTestParameter("NP_HOST_NONRESPONSIVE", "The hostname of system not responsive to network requests", "10.0.0.1");
my $hostname_invalid = getTestParameter("NP_HOSTNAME_INVALID", "An invalid (not known to DNS) hostname", "nosuchhost");
my $internet_access = getTestParameter("NP_INTERNET_ACCESS", "Is this system directly connected to the internet?", "yes");
my $successOutput = '/^TCP OK\s-\s+[0-9]?\.?[0-9]+ second response time on port [0-9]+/';
@ -42,10 +35,10 @@ $t += checkCmd( "./check_tcp $host_tcp_http -p 81 -wt 0 -ct 0 -to 1", 2
$t += checkCmd( "./check_tcp $host_nonresponsive -p 80 -wt 0 -ct 0 -to 1", 2 );
$t += checkCmd( "./check_tcp $hostname_invalid -p 80 -wt 0 -ct 0 -to 1", 2 );
if($internet_access ne "no") {
$t += checkCmd( "./check_tcp -S -D 1 -H www.verisign.com -p 443", 0 );
$t += checkCmd( "./check_tcp -S -D 9000,1 -H www.verisign.com -p 443", 1 );
$t += checkCmd( "./check_tcp -S -D 9000 -H www.verisign.com -p 443", 1 );
$t += checkCmd( "./check_tcp -S -D 9000,8999 -H www.verisign.com -p 443", 2 );
$t += checkCmd( "./check_tcp -S -D 1 -H $host_tls_http -p 443", 0 );
$t += checkCmd( "./check_tcp -S -D 9000,1 -H $host_tls_http -p 443", 1 );
$t += checkCmd( "./check_tcp -S -D 9000 -H $host_tls_http -p 443", 1 );
$t += checkCmd( "./check_tcp -S -D 9000,8999 -H $host_tls_http -p 443", 2 );
}
# Need the \r\n to make it more standards compliant with web servers. Need the various quotes

View file

@ -11,14 +11,9 @@ use NPTest;
use vars qw($tests);
BEGIN {$tests = 8; plan tests => $tests}
my $host_udp_time = getTestParameter( "host_udp_time", "NP_HOST_UDP_TIME", "localhost",
"A host providing the UDP Time Service" );
my $host_nonresponsive = getTestParameter( "host_nonresponsive", "NP_HOST_NONRESPONSIVE", "10.0.0.1",
"The hostname of system not responsive to network requests" );
my $hostname_invalid = getTestParameter( "hostname_invalid", "NP_HOSTNAME_INVALID", "nosuchhost",
"An invalid (not known to DNS) hostname" );
my $host_udp_time = getTestParameter("NP_HOST_UDP_TIME", "A host providing the UDP Time Service", "localhost");
my $host_nonresponsive = getTestParameter("NP_HOST_NONRESPONSIVE", "The hostname of system not responsive to network requests", "10.0.0.1");
my $hostname_invalid = getTestParameter("NP_HOSTNAME_INVALID", "An invalid (not known to DNS) hostname", "nosuchhost");
my $successOutput = '/^TIME OK - [0-9]+ second time difference/';

View file

@ -34,12 +34,12 @@ my $nc;
if(system("which nc.traditional >/dev/null 2>&1") == 0) {
$nc = 'nc.traditional -w 3 -l -u -p 3333';
}
elsif(system("which netcat >/dev/null 2>&1") == 0) {
$nc = 'netcat -w 3 -l -u -p 3333';
}
elsif(system("which nc >/dev/null 2>&1") == 0) {
$nc = 'nc -w 3 -l -u -4 localhost 3333';
}
elsif(system("which netcat >/dev/null 2>&1") == 0) {
$nc = 'netcat -w 3 -l -u -p 3333';
}
SKIP: {
skip "solaris netcat does not listen to udp", 6 if $^O eq 'solaris';

View file

@ -1,21 +1,24 @@
-----BEGIN CERTIFICATE-----
MIIDYzCCAsygAwIBAgIJAJISzcX71f5pMA0GCSqGSIb3DQEBBAUAMH8xCzAJBgNV
BAYTAlVLMRMwEQYDVQQIEwpEZXJieXNoaXJlMQ8wDQYDVQQHEwZCZWxwZXIxFzAV
BgNVBAoTDk5hZ2lvcyBQbHVnaW5zMREwDwYDVQQDEwhUb24gVm9vbjEeMBwGCSqG
SIb3DQEJARYPdG9udm9vbkBtYWMuY29tMB4XDTA5MDMwNjAwMTMxNVoXDTA5MDMw
NTAwMTMxNlowfzELMAkGA1UEBhMCVUsxEzARBgNVBAgTCkRlcmJ5c2hpcmUxDzAN
BgNVBAcTBkJlbHBlcjEXMBUGA1UEChMOTmFnaW9zIFBsdWdpbnMxETAPBgNVBAMT
CFRvbiBWb29uMR4wHAYJKoZIhvcNAQkBFg90b252b29uQG1hYy5jb20wgZ8wDQYJ
KoZIhvcNAQEBBQADgY0AMIGJAoGBAOQHP4JnzACi4q6quXAiK+gTSffG6yyjEV+K
iyutRgBF2MdF03X5ls0wENw/5fnMTrHynl4XoGoV/rD4CR2hGT0m7dv7Vu0MRLlP
J1SCiFeMuQS30zzLMJr0A7IW869qRlKQmzxs1JT6XDbSoNQuF154zoxwNsKlMjoX
tJSHN2YpAgMBAAGjgeYwgeMwHQYDVR0OBBYEFHWjM9OQldrDLMcAfPnUVfGxlzOp
MIGzBgNVHSMEgaswgaiAFHWjM9OQldrDLMcAfPnUVfGxlzOpoYGEpIGBMH8xCzAJ
BgNVBAYTAlVLMRMwEQYDVQQIEwpEZXJieXNoaXJlMQ8wDQYDVQQHEwZCZWxwZXIx
FzAVBgNVBAoTDk5hZ2lvcyBQbHVnaW5zMREwDwYDVQQDEwhUb24gVm9vbjEeMBwG
CSqGSIb3DQEJARYPdG9udm9vbkBtYWMuY29tggkAkhLNxfvV/mkwDAYDVR0TBAUw
AwEB/zANBgkqhkiG9w0BAQQFAAOBgQDHjoXoGwBamCiNplTt93jH/TO08RATdZP5
45hlxv2+PKCjjTiFa2mjAvopFiqmYsr40XYEmpeYMiaOzOW5rBjtqBAT/JJWyfda
SCmj3swqyKus63rv/iuokIhZzBdhbB+eOJJrmwT2SEc5KdRaipH0QAGF1nZAAGzo
6xW7hkzYog==
MIIEETCCAvmgAwIBAgIUFDsP6WnV/uqeQMpD/DYSqouE13kwDQYJKoZIhvcNAQEL
BQAwgZcxCzAJBgNVBAYTAkRFMRAwDgYDVQQIDAdCYXZhcmlhMQ8wDQYDVQQHDAZN
dW5pY2gxGzAZBgNVBAoMEk1vbml0b3JpbmcgUGx1Z2luczEbMBkGA1UEAwwSTW9u
aXRvcmluZyBQbHVnaW5zMSswKQYJKoZIhvcNAQkBFhxkZXZlbEBtb25pdG9yaW5n
LXBsdWdpbnMub3JnMB4XDTA4MDEwMTExMDAyNloXDTA4MDEwMjExMDAyNlowgZcx
CzAJBgNVBAYTAkRFMRAwDgYDVQQIDAdCYXZhcmlhMQ8wDQYDVQQHDAZNdW5pY2gx
GzAZBgNVBAoMEk1vbml0b3JpbmcgUGx1Z2luczEbMBkGA1UEAwwSTW9uaXRvcmlu
ZyBQbHVnaW5zMSswKQYJKoZIhvcNAQkBFhxkZXZlbEBtb25pdG9yaW5nLXBsdWdp
bnMub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyeHKwKFjJWUX
YHKsisypUf9dHlIPQAISyGP1BX6UL26ZLvE6kKbx3LFQ9W2POGoQWlzFiB1soGeV
WDd0U0JtWdCKmOXWdcXpupQlTSUtRCMDQkfqLN8GR5TBTd73rezp5mz08nMfLwu0
p5VQ191Ui8JHFgrAOalAn8Uw5De8vj4VmTXmU5NJ2UFoC0ddU/Th/lwRCayHc1cn
MVq2F7c/uhMUUQYNBmJy0pxoHawp+j9NKl/xIYsjgQNgahQyNuswuGHjaEwhPu+7
G03XsW4ehu+H1898M/MkSln6LQAU1syoJ8ypPM8tV+zgx4uwj7udnZ2hceN95uW7
0PWg5DQyUwIDAQABo1MwUTAdBgNVHQ4EFgQUt9ps3KJ1XiMuy/ijFBjMzf6jgwkw
HwYDVR0jBBgwFoAUt9ps3KJ1XiMuy/ijFBjMzf6jgwkwDwYDVR0TAQH/BAUwAwEB
/zANBgkqhkiG9w0BAQsFAAOCAQEAVPBZwMHbrnHFbmhbcPuvYd5cxk0uSVNAUzsl
2biCq5P+ZHo10VHGygXtdV4utqk/IrAt2u5qSxycWPStCtAgTd3Q8ncfjOkaHM4z
2bxTkhLyQeU8NWPuDBqDszo2GOaFTv+lm36LEKiAfqB1tjQVePSkycdrWIhkamBV
EgMe6uHLdU7QQk1ajQfrBdakN1beqki/dKieA6gm+XF/QS4SSYINmsHB/2X5cT9U
b/KMB8xurCnuJQuk1P4VsSkJCOSeHjWZgK9pKNdsIJZr4wDVfhjQgU0XT6xakSf7
eCaHtO0VKsbLZoiTmpxidjsdYiXyeKYIQNtUpTjyJ5V/cZsq9w==
-----END CERTIFICATE-----

Some files were not shown because too many files have changed in this diff Show more