File Coverage

blib/lib/Nagios/NRPE/Client.pm
Criterion Covered Total %
statement 26 100 26.0
branch 0 22 0.0
condition 0 18 0.0
subroutine 9 12 75.0
pod 3 3 100.0
total 38 155 24.5


line stmt bran cond sub pod time code
1             #!/usr/bin/perl
2              
3             =pod
4              
5             =head1 NAME
6              
7             Nagios::NRPE::Client - A Nagios NRPE client
8              
9             =head1 SYNOPSIS
10              
11             use Nagios::NRPE::Client;
12              
13             my $client = Nagios::NRPE::Client->new( host => "localhost", check => 'check_cpu');
14             my $response = $client->run();
15             if(defined $response->{error}) {
16             print "ERROR: Couldn't run check " . $client->{check} . " because of: " . $response->{reason} . "\n";
17             } else {
18             print $response->{buffer}."\n";
19             }
20              
21             =head1 DESCRIPTION
22              
23             This Perl Module implements Version 2 and 3 of the NRPE-Protocol. With this module you can execute
24             checks on a remote server.
25              
26             =head1 COPYRIGHT AND LICENSE
27              
28             This software is copyright (c) 2017 by the authors (see AUTHORS file).
29              
30             This is free software; you can redistribute it and/or modify it under
31             the same terms as the Perl 5 programming language system itself.
32              
33             =cut
34              
35             package Nagios::NRPE::Client;
36              
37             our $VERSION = '1.0.2';
38              
39 1     1   6471 use 5.010_000;
  1         7  
40              
41 1     1   10 use strict;
  1         3  
  1         42  
42 1     1   9 use warnings;
  1         3  
  1         40  
43              
44 1     1   1257 use Data::Dumper;
  1         25219  
  1         100  
45 1     1   12 use Carp;
  1         3  
  1         82  
46 1     1   716 use IO::Socket;
  1         32470  
  1         5  
47 1     1   6271 use IO::Socket::INET6;
  1         20748  
  1         12  
48 1         550 use Nagios::NRPE::Packet qw(NRPE_PACKET_VERSION_3
49             NRPE_PACKET_VERSION_2
50             NRPE_PACKET_QUERY
51             MAX_PACKETBUFFER_LENGTH
52             STATE_UNKNOWN
53             STATE_CRITICAL
54             STATE_WARNING
55 1     1   15035 STATE_OK);
  1         4  
56              
57             =pod
58              
59             =head1 SUBROUTINES
60              
61             =over 2
62              
63             =item new()
64              
65             Constructor for the Nagios::NRPE::Client Object
66              
67             example
68              
69             my $client = Nagios::NRPE::Client->new( host => "localhost", check => 'check_cpu');
70              
71             Takes a hash of options:
72              
73             * host =>
74              
75             The hostname or IP on which the NRPE-Server is running
76              
77             * port =>
78              
79             The port number at which the NRPE-Server is listening
80              
81             * timeout =>
82              
83             Timeout for TCP/IP communication
84              
85             * arglist => ["arg","uments"]
86              
87             List of arguments attached to the check
88              
89             * check => "check_command"
90              
91             Command defined in the nrpe.cfg on the NRPE-Server
92              
93             * ssl => 0,1
94              
95             Use or don't use SSL
96              
97             =back
98              
99             =cut
100              
101             sub new {
102 0     0 1   my ( $class, %hash ) = @_;
103 0           my $self = {};
104 0   0       $self->{arglist} = delete $hash{arglist} || [];
105 0   0       $self->{bindaddr} = delete $hash{bindaddr} || 0;
106 0   0       $self->{check} = delete $hash{check} || "";
107 0   0       $self->{host} = delete $hash{host} || "localhost";
108 0   0       $self->{ipv4} = delete $hash{ipv4} || 0;
109 0   0       $self->{ipv6} = delete $hash{ipv6} || 0;
110 0   0       $self->{port} = delete $hash{port} || 5666;
111 0   0       $self->{ssl} = delete $hash{ssl} || 0;
112 0   0       $self->{timeout} = delete $hash{timeout} || 30;
113 0           bless $self, $class;
114             }
115              
116             =pod
117              
118             =over 2
119              
120             =item create_socket()
121              
122             Helper function that can create either an INET socket or a SSL socket
123              
124             =back
125              
126             =cut
127              
128             sub create_socket {
129 0     0 1   my ($self) = @_;
130 0           my $reason;
131             my $socket;
132              
133             my %socket_opts = (
134              
135             # where to connect
136             PeerHost => $self->{host},
137             PeerPort => $self->{port},
138             Timeout => $self->{timeout}
139 0           );
140 0 0         if ( $self->{bindaddr} ) {
141 0           $socket_opts{LocalAddr} = $self->{bindaddr};
142             }
143 0 0         if ( $self->{ipv4} ) {
144 0           $socket_opts{Domain} = AF_INET;
145             }
146 0 0         if ( $self->{ipv6} ) {
147 0           $socket_opts{Domain} = AF_INET6;
148             }
149 0 0         if ( $self->{ssl} ) {
150 0           eval {
151             # required for new IO::Socket::SSL versions
152 1     1   1216 use IO::Socket::SSL;
  1         158709  
  1         34  
153 0           };
154              
155 0           $socket_opts{SSL_cipher_list} = 'ADH';
156 0           $socket_opts{SSL_verify_mode} = SSL_VERIFY_NONE;
157 0           $socket_opts{SSL_version} = 'TLSv1';
158              
159 0           $socket = IO::Socket::SSL->new(%socket_opts);
160 0 0         if ($SSL_ERROR) {
161 0           $reason = "$!,$SSL_ERROR";
162             }
163              
164             }
165             else {
166 0           $socket_opts{Proto} = 'tcp';
167 0           $socket_opts{Type} = SOCK_STREAM;
168 0           $socket = IO::Socket::INET6->new(%socket_opts);
169 0           $reason = $@;
170             }
171              
172 0 0         if ( !$socket ) {
173 0           my %return;
174 0           $return{'error'} = 1;
175 0           $return{'reason'} = $reason;
176 0           return ( \%return );
177             }
178              
179 0           return $socket;
180              
181             }
182              
183             =pod
184              
185             =over 2
186              
187             =item run()
188              
189             Runs the communication to the server and returns a hash of the form:
190              
191             my $response = $client->run();
192              
193             The output should be a hashref of this form for NRPE V3:
194              
195             {
196             version => NRPE_VERSION,
197             type => RESPONSE_TYPE,
198             crc32 => CRC32_CHECKSUM,
199             code => RESPONSE_CODE,
200             alignment => PACKET_ALIGNMENT,
201             buffer_length => OUTPUT_LENGTH,
202             buffer => CHECK_OUTPUT
203             }
204            
205             and this for for NRPE V2:
206              
207             {
208             version => NRPE_VERSION,
209             type => RESPONSE_TYPE,
210             crc32 => CRC32_CHECKSUM,
211             code => RESPONSE_CODE,
212             buffer => CHECK_OUTPUT
213             }
214              
215             =back
216              
217             =cut
218              
219             sub run {
220 0     0 1   my ($self) = @_;
221 0           my $check;
222 0 0         if ( scalar @{ $self->{arglist} } == 0 ) {
  0            
223 0           $check = $self->{check};
224             }
225             else {
226 0           $check = join '!', $self->{check}, @{ $self->{arglist} };
  0            
227             }
228              
229 0           my $socket = $self->create_socket();
230 0 0         if ( ref $socket eq "REF" ) {
231 0           return ($socket);
232             }
233 0           my $packet = Nagios::NRPE::Packet->new();
234 0           my $response;
235 0           my $assembled = $packet->assemble(
236             type => NRPE_PACKET_QUERY,
237             check => $check,
238             version => NRPE_PACKET_VERSION_3
239             );
240              
241 0           print $socket $assembled;
242 0           while (<$socket>) {
243 0           $response .= $_;
244             }
245 0           close($socket);
246              
247 0 0         if ( !$response ) {
248 0           $socket = $self->create_socket();
249 0 0         if ( ref $socket eq "REF" ) {
250 0           return ($socket);
251             }
252 0           $packet = Nagios::NRPE::Packet->new();
253 0           $response = undef;
254 0           $assembled = $packet->assemble(
255             type => NRPE_PACKET_QUERY,
256             check => $check,
257             version => NRPE_PACKET_VERSION_2
258             );
259              
260 0           print $socket $assembled;
261 0           while (<$socket>) {
262 0           $response .= $_;
263             }
264 0           close($socket);
265              
266 0 0         if ( !$response ) {
267 0           my %return;
268 0           $return{'error'} = 1;
269 0           $return{'reason'} = "No output from remote host";
270 0           return ( \%return );
271             }
272             }
273 0           return $packet->deassemble($response);
274             }
275              
276             =pod
277              
278             =head1 COPYRIGHT AND LICENSE
279              
280             This software is copyright (c) 2017 by the authors (see AUTHORS file).
281              
282             This is free software; you can redistribute it and/or modify it under
283             the same terms as the Perl 5 programming language system itself.
284              
285             =cut
286              
287             1;