Skip to content

Instantly share code, notes, and snippets.

@PBXForums
Created July 31, 2023 21:25
Show Gist options
  • Save PBXForums/a6adfe7b3bd132aa2532df76a0f0a2c3 to your computer and use it in GitHub Desktop.
Save PBXForums/a6adfe7b3bd132aa2532df76a0f0a2c3 to your computer and use it in GitHub Desktop.
#!/usr/bin/perl
## Script written by Noah Guttman and Copyright (C) 2014 Noah Guttman. This script is released and distributed under the terms of the GNU General Public License
#Libraries to use
use warnings;
use strict;
use Getopt::Std;
use Time::HiRes qw(gettimeofday usleep);
use IO::Socket;
use threads;
use threads::shared;
use String::Random;
use vars qw($opt_h $opt_H $opt_P $opt_t $opt_r $opt_d $opt_R $opt_M $opt_s $opt_I $opt_c);
$opt_R ='';
my $baseport;
my @output;
my @line;
my $val;
my $received_packet :shared;
$received_packet ="";
my $testerrortotal=0;
my $response_timeout=0;
my $elapsed=1000;
my $debug_output="";
my $exitcode=3;
my $icmp_responsed :shared;
$icmp_responsed = 0;
my $timeout=1000000;
my $retries=4;
my $errors=0;
my $maxfailures =3;
my $localIP;
my $localPort;
my $timer =0;
my $ReturnMin=10000000;
my $ReturnMax=0;
my $ReturnTotal=0;
my $testoktotal=0;
my $ReturnAvg=0;
my $sock;
my $recvthread;
my $optionPacket='';
my $randomstring = new String::Random;
##init();
# Get the options
#if ($#ARGV le 0) {
# $opt_h=1;
#} else {
# getopts('hdsH:P:t:r:R:M:I:c:');
#}
## Display Help
if ($opt_h){
print "::SIP Options Check Instructions::\n\n";
print " -h, Display this help information\n";
print " -H, Hostname or IP to check\n";
print " -P, Port to check\n";
print " The default is 5060\n";
print " -s, Accept any SIP message as valid response\n";
print " -I, Attempt to bind to the IP when sending the Options packet\n";
print " If this IP is not present on the server the test will fail with an error \n";
print " -M, Custom message to report on failure\n";
print " -R, Restart command to use (for use with event handlers)\n";
print " -t, Timeout (ms) for each communication attempt.\n";
print " The default is 1000\n";
print " -r, Number of OPTIONS packets to send.\n";
print " The default is 4\n";
print " -c, Number of bad responses to trigger a critical\n";
print " The default is 3\n";
print " -d, Turn on debug mode - prints out packet(s) recived.\n";
print "Script written by Noah Guttman and Copyright (C) 2014 Noah Guttman.\n";
print "This script is released and distributed under the terms of the GNU\n";
print "General Public License. >>>> http://www.gnu.org/licenses/\n";
print "";
print "This program is free software: you can redistribute it and/or modify\n";
print "it under the terms of the GNU General Public License as published by\n";
print "the Free Software Foundation.\n\n";
print "This program is distributed in the hope that it will be useful,\n";
print "but WITHOUT ANY WARRANTY; without even the implied warranty of\n";
print "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n";
print "GNU General Public License for more details.\n";
print ">>>> http://www.gnu.org/licenses/\n";
exit 0;
}
##Set custom output if any set
if ($opt_P){
$baseport=$opt_P;
}else{
$baseport=5060;
$opt_P=5060;
}
if ($opt_t){
$timeout=$opt_t*1000;
}
if ($opt_r){
$retries=$opt_r;
}
if ($opt_c){
$maxfailures = $opt_c;
}
$sock = IO::Socket::INET->new(
PeerAddr=> "www.google.com",
PeerPort=> 80,
Proto => "tcp");
$opt_H = $sock->sockhost;
#$opt_H='localhost';
#Check that the thread is responding
for (my $i=0; $i < $retries; $i++){
if ($opt_I){
$sock = IO::Socket::INET->new(
Proto => 'udp',
PeerPort => $baseport,
PeerAddr => $opt_H,
LocalAddr => $opt_I,
) or die "Could not create socket: $!\n";
}else{
$sock = IO::Socket::INET->new(
Proto => 'udp',
PeerPort => $baseport,
PeerAddr => $opt_H,
) or die "Could not create socket: $!\n";
}
$recvthread = threads->new( \&recive_rtpproxy_request);
usleep(10000);
$localIP = $sock->sockhost;
$localPort = $sock->sockport;
$optionPacket = "OPTIONS sip:test\@$opt_H:$opt_P SIP/2.0\r\nVia: SIP/2.0/UDP $localIP:$localPort;branch=z9hG4bK." .$randomstring->randpattern("cCncnCCcnCncnCcncC") .";rport\r\nFrom: <sip:nagios\@$opt_H:$opt_P>;tag=" .$randomstring->randpattern("cCncnCc") ."\r\nTo: <sip:test\@$opt_H:$opt_P>\r\nCall-ID: " .$randomstring->randpattern("cCncnCCcnCncnCcncC") ."\@$localIP\r\nCSeq: 1 OPTIONS\r\nAccept: application/sdp\r\nMax-Forwards: 70\r\nUser-Agent: DCVoIP Monitoring\r\nContent-Length: 0\r\n\r\n";
#$optionPacket = "OPTIONS sip:test\@$opt_H:$opt_P SIP/2.0\r\nVia: SIP/2.0/UDP $localIP:$localPort;branch=z9hG4bK." .$randomstring->randpattern("cCncnCCcnCncnCcncC") .";rport\r\n";
if ($opt_d){
$debug_output = $debug_output."\n------------------------------\nOPTIONS PACKET:$optionPacket\n------------------------------\n";
}
my $starttime = gettimeofday;
$sock->send("$optionPacket") or die "Send error: $!\n";
#reset timer
$timer =0;
while (($timer <= $timeout ) && ($received_packet !~ /SIP\/2.0 \d\d\d/i)){
usleep(1000);
$timer = $timer + 1000;
}
#reset timer
$timer =0;
$elapsed = (gettimeofday - $starttime)*1000;
#reject bad time data
if ($elapsed < 0){
$elapsed='';
}
if ($opt_d){
$debug_output = $debug_output."\n------------------------------\nRESPONSE PACKET:$received_packet\n------------------------------\n";
}
if ($received_packet =~ /SIP\/2.0 200/i){
$recvthread->join();
if ($ReturnMin > $elapsed){
$ReturnMin = $elapsed;
}
if ($ReturnMax <$elapsed){
$ReturnMax = $elapsed;
}
$ReturnTotal = $ReturnTotal + $elapsed;
$testoktotal++;
$ReturnAvg = ($ReturnTotal / $testoktotal);
if ($opt_d){
$debug_output = $debug_output."Stats so far : ReturnMin=$ReturnMin"."ms;; ReturnAvg=$ReturnAvg"."ms;; ReturnMax=$ReturnMax"."ms;;ICMP=$icmp_responsed;; Errors=$errors;; Timeouts=$response_timeout;;\n";
}
}elsif (($received_packet =~ /SIP\/2.0/i) && ($opt_s)){
$recvthread->join();
if ($ReturnMin > $elapsed){
$ReturnMin = $elapsed;
}
if ($ReturnMax <$elapsed){
$ReturnMax = $elapsed;
}
$ReturnTotal = $ReturnTotal + $elapsed;
$testoktotal++;
$ReturnAvg = ($ReturnTotal / $testoktotal);
if ($opt_d){
$debug_output = $debug_output."Stats so far : ReturnMin=$ReturnMin"."ms;; ReturnAvg=$ReturnAvg"."ms;; ReturnMax=$ReturnMax"."ms;;ICMP=$icmp_responsed;; Errors=$errors;; Timeouts=$response_timeout;;\n";
}
}elsif ($icmp_responsed >$testerrortotal){
$recvthread->join();
$testerrortotal++
}elsif ($received_packet =~ /./){
$errors++;
$recvthread->join();
$testerrortotal++
}else{
$recvthread->detach;
$response_timeout++;
$testerrortotal++;
}
$sock->close;
$received_packet='';
usleep (5000);
}
if ($testerrortotal == 0){
print ("<<<check_sip_options>>>\nOK: $ReturnAvg SIP Component has responded in an average of $ReturnAvg ms. $opt_R $opt_H $opt_P");
$exitcode = 0;
if ($opt_d){
print ("$debug_output");
}
print ("|ReturnMin=$ReturnMin"."ms;; ReturnAvg=$ReturnAvg"."ms;; ReturnMax=$ReturnMax"."ms;; ICMP=$icmp_responsed;; Errors=$errors;; Timeouts=$response_timeout;;\n");
exit ($exitcode);
}elsif ($testerrortotal < $maxfailures){
print ("<<<check_sip_options>>>\n$opt_R $opt_H $opt_P Warning: SIP Component has responded with $testerrortotal errors and in an average of $ReturnAvg ms.");
$exitcode = 1;
if ($opt_M){
print ("$opt_M");
}
if ($opt_d){
print ("$debug_output");
}
print ("|ReturnMin=$ReturnMin"."ms;; ReturnAvg=$ReturnAvg"."ms;; ReturnMax=$ReturnMax"."ms;; ICMP=$icmp_responsed;; Errors=$errors;; Timeouts=$response_timeout;;\n");
exit ($exitcode);
}
#Catch all for all other cases
print ("<<<check_sip_options>>>\n$opt_R $opt_H $opt_P CRITICAL: SIP Component has not responded correctly after $testerrortotal attempts.");
$exitcode = 2;
if ($opt_M){
print ("$opt_M");
}
if ($opt_d){
print ("$debug_output");
}
print ("|ICMP=$icmp_responsed;; Errors=$errors;; Timeouts=$response_timeout;;\n");
exit ($exitcode);
sub recive_rtpproxy_request{
$sock->recv($received_packet,128) or $icmp_responsed++;
$sock->close;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment