#!/usr/bin/perl -w

# Version:      01
# Date:         Nov 3, 2021
# Author:       ivan.stetka@live.com
# Summary:      This is a Nagios NCPA plugin for checking the number of one type of socket state with the netstat command
#            
# On host side copy plugin to directory '/usr/local/ncpa/plugins/'
#
# Nagios example:
# ./check_ncpa.py -H '<host IP>' -t '<your token>' -M 'plugins/check_socketState_count.pl' -a "-S 'CLOSE_WAIT' -w 100 -c 200"
#

use strict;
use Getopt::Long qw(:config no_ignore_case bundling);

my %STATES = (
    OK          => 0,
    WARNING     => 1,
    CRITICAL    => 2,
    UNKNOWN     => 3
);

my $state = undef;
my $crit = undef;
my $warn = undef;
my $help = 0;
my $stateCount = 0;
my @a_state = ('BOUND', 'CLOSED', 'CLOSE_WAIT', 'CLOSING', 'ESTABLISHED', 'FIN_WAIT1', 'FIN_WAIT2', 'IDLE', 'LAST_ACK', 'LISTEN', 'SYN_RECEIVED', 'SYN_SENT', 'TIME_WAIT', 'UNKNOWN');

GetOptions(
    'S|state:s'     => \$state,
    'w|warning:n'   => \$warn,
    'c|critical:n'  => \$crit,
    'h|help'        => \$help
);

if ($help) {
    help();
    exit($STATES{OK});
}

if (!defined $warn || !defined $crit || !defined $state) {
    print "UNKNOWN: Missing some required parameter (warning, critical or state').\n";
    help();
    exit($STATES{UNKNOWN});
}

if ($crit <= 0 || $warn <= 0) {
    print "UNKNOWN: Incorrect warning: '$warn' or critical: '$crit' threshold.\n";
    help();
    exit($STATES{UNKNOWN});
}

if ($warn > $crit) {
    print "The warning threshold '$warn' cannot be greater than critical threshold '$crit'.\n";
    help();
    exit($STATES{UNKNOWN});
}

unless ( grep { $_ eq $state} @a_state ) {
    print "UNKNOWN: Incorrect tape of socket state: $state.\n";
    help();
    exit($STATES{UNKNOWN});
}

open BC1, "netstat -an | grep $state | wc -l |";
$stateCount = <BC1>;
close BC1;
$stateCount =~ s/\n//;

if ($stateCount !~ /^\d+$/ ) {
    print "CRITICAL: netstat command error (Count): $stateCount\n";
    exit($STATES{CRITICAL});
}

my $text = "the number of socket state '$state' is $stateCount.\n|'$state'=$stateCount;$warn;$crit;\n";

if ($stateCount >= $crit ){
    print "CRITICAL: $text";
    exit($STATES{CRITICAL});
} elsif ($stateCount >= $warn ){
    print "WARNING: $text";
    exit($STATES{WARNING});
} else {
    print "OK: $text";
    exit($STATES{OK});
}

# # # SUBROUTINES # # #

#   Help subroutine
sub help {
    print <<HELP;

H E L P:

This is a nagios NCPA plugin for checking the number of one type of socket state with the netstat command,

-S, --state             # type of socket state [BOUND,CLOSED,CLOSE_WAIT,CLOSING,ESTABLISHED,FIN_WAIT1,FIN_WAIT2,IDLE,LAST_ACK,LISTEN,SYN_RECEIVED,SYN_SENT,TIME_WAIT,UNKNOWN]
                        # example state: CLOSE_WAIT
-w, --critical          # warning threshold of maximum state count
-c, --critical          # critical threshold of maximum state count
-h, --help              # print this help

HELP
}
