Code

Fix for regex input of '|', being output causing problems with Nagios' parsing of
[nagiosplug.git] / contrib / check_asterisk.pl
1 #!/usr/bin/perl -w
3 use strict;
4 use IO::Socket;
5 use Getopt::Long;
6 $|=1;
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 = "";
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 
36 sub ok {
37         $s = shift;
38         $s =~ s/[\r\n]//g;
39         print "OK: $s\n";
40         exit(0);
41 }
43 sub warning {
44         $s = shift;
45         $s =~ s/[\r\n]//g;
46         print "WARNING: $s\n";
47         exit(1);
48 }
50 sub error {
51         $s = shift;
52         $s =~ s/[\r\n]//g;
53         print "ERROR: $s\n";
54         exit(2);
55 }
57 sub unknown {
58         $s = shift;
59         $s =~ s/[\r\n]//g;
60         print "UNKNOWN: $s\n";
61         exit(3);
62 }
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 }
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);
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") 
108 ##############################################################################
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         }
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);
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);
148         exit(1) unless ($response =~ m/^Response:\s+(.*)$/i);
149         exit(1) unless ($1 =~ m/Success/i);
151         print $sock "Action: Status\r\n\r\n";
152         print "Action: Status\r\n\r\n" if ($verbose);
154         $response = <$sock>;
155         $message = <$sock>;
156         print $response.$message if ($verbose);
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);
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         }
175 # Log out
176         print $sock "Action: Logoff\r\n\r\n";
178         undef($s);
179         foreach $key (keys %channels) {
180                 $s .= " " . $key . " (" . $channels{$key} . ")";
181         }
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         }
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         }
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         }
216         print $cause;
218         print "\n" if ($verbose);
220         exit($exitcode);
221 } elsif ($runmode == 1) {
222         $port = $iax_port;
224         socket(PING, PF_INET, SOCK_DGRAM, getprotobyname("udp")); 
226         $msg = pack "H24", $iax_src_call . $iax_dst_call . $iax_timestamp .
227                 $iax_outbound_seq . $iax_inbound_seq . $iax_type . $iax_type;
229         $ipaddr = inet_aton($host); 
230         $sendto = sockaddr_in($port,$ipaddr); 
232         send(PING, $msg, 0, $sendto) == length($msg) or die "cannot send to $host : $port : $!\n"; 
234         eval { 
235                 local $SIG{ALRM} = sub { die("alarm time out"); }; 
236                 alarm $iax_timeout; 
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                 } 
246         };
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         }