diff options
Diffstat (limited to 'contrib/check_asterisk.pl')
| -rw-r--r-- | contrib/check_asterisk.pl | 259 |
1 files changed, 259 insertions, 0 deletions
diff --git a/contrib/check_asterisk.pl b/contrib/check_asterisk.pl new file mode 100644 index 00000000..179d3671 --- /dev/null +++ b/contrib/check_asterisk.pl | |||
| @@ -0,0 +1,259 @@ | |||
| 1 | #!/usr/bin/perl -w | ||
| 2 | |||
| 3 | use strict; | ||
| 4 | use IO::Socket; | ||
| 5 | use Getopt::Long; | ||
| 6 | $|=1; | ||
| 7 | |||
| 8 | my ( | ||
| 9 | $host, $username, $password, $verbose, $help, $command, $mode, | ||
| 10 | $ipaddr, $respaddr, $sendto, $msg, $recvfrom, | ||
| 11 | $version, $response, $message, $line, | ||
| 12 | $sock, $port, $reply, | ||
| 13 | $warning, $critical, | ||
| 14 | %warnval, %critval, | ||
| 15 | %channels, | ||
| 16 | $runmode, | ||
| 17 | $key, | ||
| 18 | $s, | ||
| 19 | ); | ||
| 20 | my $stop = 0; | ||
| 21 | my $mgr_port = 5038; | ||
| 22 | my $iax_port = 4569; | ||
| 23 | my $exitcode = 0; | ||
| 24 | my $cause = ""; | ||
| 25 | |||
| 26 | my $iax_answer = 0; | ||
| 27 | my $iax_maxlen = 1024; | ||
| 28 | my $iax_timeout = 5; | ||
| 29 | my $iax_src_call = "8000"; #8000 most siginificant bit is IAX packet type full ... required for a poke etc... | ||
| 30 | my $iax_dst_call = "0000"; | ||
| 31 | my $iax_timestamp = "00000000"; | ||
| 32 | my $iax_outbound_seq = "00"; | ||
| 33 | my $iax_inbound_seq = "00"; | ||
| 34 | my $iax_type = "06"; #IAX_Control | ||
| 35 | |||
| 36 | sub ok { | ||
| 37 | $s = shift; | ||
| 38 | $s =~ s/[\r\n]//g; | ||
| 39 | print "OK: $s\n"; | ||
| 40 | exit(0); | ||
| 41 | } | ||
| 42 | |||
| 43 | sub warning { | ||
| 44 | $s = shift; | ||
| 45 | $s =~ s/[\r\n]//g; | ||
| 46 | print "WARNING: $s\n"; | ||
| 47 | exit(1); | ||
| 48 | } | ||
| 49 | |||
| 50 | sub error { | ||
| 51 | $s = shift; | ||
| 52 | $s =~ s/[\r\n]//g; | ||
| 53 | print "ERROR: $s\n"; | ||
| 54 | exit(2); | ||
| 55 | } | ||
| 56 | |||
| 57 | sub unknown { | ||
| 58 | $s = shift; | ||
| 59 | $s =~ s/[\r\n]//g; | ||
| 60 | print "UNKNOWN: $s\n"; | ||
| 61 | exit(3); | ||
| 62 | } | ||
| 63 | |||
| 64 | sub syntax { | ||
| 65 | $s = shift; | ||
| 66 | unless ($s =~ m/Help:/) { | ||
| 67 | $s = "Error: (".$s.")" or $s = 'Unknown'; | ||
| 68 | } | ||
| 69 | print "$s\n" unless ($help); | ||
| 70 | print "Syntax: $0 -m mgr -h <host> -u <username> -p <password> [-cwv]\n"; | ||
| 71 | print "Syntax: $0 -m iax -h <host> [-v]\n"; | ||
| 72 | print "* --host -h Host\n"; | ||
| 73 | print "* --mode -m Mode - eithr 'mgr' or 'iax'\n"; | ||
| 74 | print " --username -u Username\n"; | ||
| 75 | print " --password -p Password\n"; | ||
| 76 | print " --port -P n Port (if not using $mgr_port for manager or $iax_port for IAX)\n"; | ||
| 77 | print " --warning xxx=n Return warning if > n channels of type xxx.\n"; | ||
| 78 | print " --critical xxx=n Return critical if > n channels of type xxx.\n"; | ||
| 79 | print " --verbose -v Verbose\n"; | ||
| 80 | print " --help -h This help\n"; | ||
| 81 | exit(3); | ||
| 82 | } | ||
| 83 | |||
| 84 | Getopt::Long::Configure('bundling'); | ||
| 85 | GetOptions | ||
| 86 | ("p=s" => \$password, "password=s" => \$password, | ||
| 87 | "u=s" => \$username, "username=s" => \$username, | ||
| 88 | "h=s" => \$host, "host=s" => \$host, | ||
| 89 | "P=i" => \$port, "port=i" => \$port, | ||
| 90 | "H" => \$help, "help" => \$help, | ||
| 91 | "v" => \$verbose, "verbose" => \$verbose, | ||
| 92 | "m=s" => \$mode, "mode=s" => \$mode, | ||
| 93 | "critical=s" => \$critical, "warning=s" => \$warning); | ||
| 94 | |||
| 95 | syntax("Help:") if ($help); | ||
| 96 | syntax("Missing host") unless (defined($host)); | ||
| 97 | syntax("Missing mode") unless (defined($mode)); | ||
| 98 | if ($mode =~ /^iax$/i) { | ||
| 99 | print "Running in IAX mode\n" if ($verbose); | ||
| 100 | $runmode = 1; | ||
| 101 | } elsif ($mode =~ /^mgr$/i) { | ||
| 102 | print "Running in Manager mode\n" if ($verbose); | ||
| 103 | $runmode = 2; | ||
| 104 | } else { | ||
| 105 | syntax("Unknown mode $mode") | ||
| 106 | } | ||
| 107 | |||
| 108 | ############################################################################## | ||
| 109 | |||
| 110 | if ($runmode == 2) { | ||
| 111 | $port = $mgr_port; | ||
| 112 | syntax("Missing username") unless (defined($username)); | ||
| 113 | syntax("Missing password") unless (defined($password)); | ||
| 114 | if (defined($warning)) { | ||
| 115 | foreach $s (split(/,/, $warning)) { | ||
| 116 | syntax("Warning value given, $s, is invalid") | ||
| 117 | unless ($s =~ /^(\w+)=(\d+)$/); | ||
| 118 | $warnval{$1} = $2; | ||
| 119 | print "Clear to give WARNING after $2 connections on $1\n" if ($verbose); | ||
| 120 | } | ||
| 121 | } | ||
| 122 | if (defined($critical)) { | ||
| 123 | foreach $s (split(/,/, $critical)) { | ||
| 124 | syntax("Critical value given, $s, is invalid") | ||
| 125 | unless ($s =~ /^(\w+)=(\d+)$/); | ||
| 126 | $critval{$1} = $2; | ||
| 127 | print "Clear to give CRITICAL after $2 connections on $1\n" if ($verbose); | ||
| 128 | } | ||
| 129 | } | ||
| 130 | |||
| 131 | print "Connecting to $host:$port\n" if ($verbose); | ||
| 132 | unless ($sock = IO::Socket::INET->new(PeerAddr => $host, PeerPort => $port, Proto => 'tcp')) { | ||
| 133 | print("Could not connect to asterisk server ".$host.":".$port."\n"); | ||
| 134 | exit(2); | ||
| 135 | } | ||
| 136 | print "Connected to $host:$port\n" if ($verbose); | ||
| 137 | $version = <$sock>; | ||
| 138 | print $version if ($verbose); | ||
| 139 | |||
| 140 | print $sock "Action: Login\r\nUsername: $username\r\nSecret: $password\r\nEvents: off\r\n\r\n"; | ||
| 141 | print "Action: Login\r\nUsername: $username\r\nSecret: $password\r\n\r\n" if ($verbose); | ||
| 142 | $response = <$sock>; | ||
| 143 | $message = <$sock>; | ||
| 144 | $s = <$sock>; | ||
| 145 | print $response.$message if ($verbose); | ||
| 146 | print $s if ($verbose); | ||
| 147 | |||
| 148 | exit(1) unless ($response =~ m/^Response:\s+(.*)$/i); | ||
| 149 | exit(1) unless ($1 =~ m/Success/i); | ||
| 150 | |||
| 151 | print $sock "Action: Status\r\n\r\n"; | ||
| 152 | print "Action: Status\r\n\r\n" if ($verbose); | ||
| 153 | |||
| 154 | $response = <$sock>; | ||
| 155 | $message = <$sock>; | ||
| 156 | print $response.$message if ($verbose); | ||
| 157 | |||
| 158 | &unknown("Unknown answer $response (wanted Response: something)") unless ($response =~ m/^Response:\s+(.*)$/i); | ||
| 159 | &unknown("$response didn't say Success") unless ($1 =~ m/Success/i); | ||
| 160 | &unknown("Unknown answer $response (wanted Message: something)") unless ($message =~ m/^Message:\s+(.*)$/i); | ||
| 161 | &unknown("didn't understand message $message") unless ($1 =~ m/Channel status will follow/i); | ||
| 162 | |||
| 163 | $stop=0; | ||
| 164 | while (($stop == 0) && ($line = <$sock>)) { | ||
| 165 | print "$line" if ($verbose); | ||
| 166 | if ($line =~ m/Channel:\s+(\w+)\//) { | ||
| 167 | $channels{$1}++; | ||
| 168 | print "Found $1 channel\n" if ($verbose); | ||
| 169 | } | ||
| 170 | if ($line =~ m/Event:\s*StatusComplete/i) { | ||
| 171 | $stop++; | ||
| 172 | } | ||
| 173 | } | ||
| 174 | |||
| 175 | # Log out | ||
| 176 | print $sock "Action: Logoff\r\n\r\n"; | ||
| 177 | |||
| 178 | undef($s); | ||
| 179 | foreach $key (keys %channels) { | ||
| 180 | $s .= " " . $key . " (" . $channels{$key} . ")"; | ||
| 181 | } | ||
| 182 | |||
| 183 | foreach $key (keys %critval) { | ||
| 184 | print "key = $key\n" if ($verbose); | ||
| 185 | if (defined($channels{$key}) && ($channels{$key} > $critval{$key})) { | ||
| 186 | $exitcode = 2; | ||
| 187 | $cause .= $channels{$key} . " $key channels detected. "; | ||
| 188 | } | ||
| 189 | } | ||
| 190 | |||
| 191 | if ($exitcode < 2) { | ||
| 192 | foreach $key (keys %warnval) { | ||
| 193 | print "key = $key\n" if ($verbose); | ||
| 194 | if (defined($channels{$key}) && ($channels{$key} > $warnval{$key})) { | ||
| 195 | $exitcode = 1; | ||
| 196 | $cause .= $channels{$key} . " $key channels detected. "; | ||
| 197 | } | ||
| 198 | } | ||
| 199 | } | ||
| 200 | |||
| 201 | if ($exitcode == 0) { | ||
| 202 | print "OK "; | ||
| 203 | } elsif ($exitcode == 1) { | ||
| 204 | print "WARNING "; | ||
| 205 | } elsif ($exitcode == 2) { | ||
| 206 | print "CRITICAL "; | ||
| 207 | } elsif ($exitcode > 2) { | ||
| 208 | print "UNKNOWN "; | ||
| 209 | } | ||
| 210 | if (defined($s)) { | ||
| 211 | $cause .= " Channels:$s"; | ||
| 212 | } else { | ||
| 213 | $cause .= " (idle)"; | ||
| 214 | } | ||
| 215 | |||
| 216 | print $cause; | ||
| 217 | |||
| 218 | print "\n" if ($verbose); | ||
| 219 | |||
| 220 | exit($exitcode); | ||
| 221 | } elsif ($runmode == 1) { | ||
| 222 | $port = $iax_port; | ||
| 223 | |||
| 224 | socket(PING, PF_INET, SOCK_DGRAM, getprotobyname("udp")); | ||
| 225 | |||
| 226 | $msg = pack "H24", $iax_src_call . $iax_dst_call . $iax_timestamp . | ||
| 227 | $iax_outbound_seq . $iax_inbound_seq . $iax_type . $iax_type; | ||
| 228 | |||
| 229 | $ipaddr = inet_aton($host); | ||
| 230 | $sendto = sockaddr_in($port,$ipaddr); | ||
| 231 | |||
| 232 | send(PING, $msg, 0, $sendto) == length($msg) or die "cannot send to $host : $port : $!\n"; | ||
| 233 | |||
| 234 | eval { | ||
| 235 | local $SIG{ALRM} = sub { die("alarm time out"); }; | ||
| 236 | alarm $iax_timeout; | ||
| 237 | |||
| 238 | while (1) { | ||
| 239 | $recvfrom = recv(PING, $msg, $iax_maxlen, 0) or die "recv: $!"; | ||
| 240 | ($port, $ipaddr) = sockaddr_in($recvfrom); | ||
| 241 | $respaddr = inet_ntoa($ipaddr); | ||
| 242 | $iax_answer++; | ||
| 243 | # print "Response from $respaddr : $port\n"; | ||
| 244 | } | ||
| 245 | |||
| 246 | }; | ||
| 247 | |||
| 248 | if ($iax_answer) { | ||
| 249 | if ($iax_answer == 1) { | ||
| 250 | $reply = "reply"; | ||
| 251 | } else { | ||
| 252 | $reply = "replies"; | ||
| 253 | } | ||
| 254 | &ok("Got $iax_answer $reply"); | ||
| 255 | } else { | ||
| 256 | &error("Got no reply"); | ||
| 257 | } | ||
| 258 | } | ||
| 259 | |||
