diff options
Diffstat (limited to 'library/Icinga/Protocol/Nrpe')
-rw-r--r-- | library/Icinga/Protocol/Nrpe/Connection.php | 111 | ||||
-rw-r--r-- | library/Icinga/Protocol/Nrpe/Packet.php | 69 |
2 files changed, 180 insertions, 0 deletions
diff --git a/library/Icinga/Protocol/Nrpe/Connection.php b/library/Icinga/Protocol/Nrpe/Connection.php new file mode 100644 index 0000000..491a965 --- /dev/null +++ b/library/Icinga/Protocol/Nrpe/Connection.php @@ -0,0 +1,111 @@ +<?php +/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Protocol\Nrpe; + +use Icinga\Exception\IcingaException; + +class Connection +{ + protected $host; + protected $port; + protected $connection; + protected $use_ssl = false; + protected $lastReturnCode = null; + + public function __construct($host, $port = 5666) + { + $this->host = $host; + $this->port = $port; + } + + public function useSsl($use_ssl = true) + { + $this->use_ssl = $use_ssl; + return $this; + } + + public function sendCommand($command, $args = null) + { + if (! empty($args)) { + $command .= '!' . implode('!', $args); + } + + $packet = Packet::createQuery($command); + return $this->send($packet); + } + + public function getLastReturnCode() + { + return $this->lastReturnCode; + } + + public function send(Packet $packet) + { + $conn = $this->connection(); + $bytes = $packet->getBinary(); + fputs($conn, $bytes, strlen($bytes)); + // TODO: Check result checksum! + $result = fread($conn, 8192); + if ($result === false) { + throw new IcingaException('CHECK_NRPE: Error receiving data from daemon.'); + } elseif (strlen($result) === 0) { + throw new IcingaException( + 'CHECK_NRPE: Received 0 bytes from daemon. Check the remote server logs for error messages' + ); + } + // TODO: CHECK_NRPE: Receive underflow - only %d bytes received (%d expected) + $code = unpack('n', substr($result, 8, 2)); + $this->lastReturnCode = $code[1]; + $this->disconnect(); + return rtrim(substr($result, 10, -2)); + } + + protected function connect() + { + $ctx = stream_context_create(); + if ($this->use_ssl) { + // TODO: fail if not ok: + $res = stream_context_set_option($ctx, 'ssl', 'ciphers', 'ADH'); + $uri = sprintf('ssl://%s:%d', $this->host, $this->port); + } else { + $uri = sprintf('tcp://%s:%d', $this->host, $this->port); + } + $this->connection = @stream_socket_client( + $uri, + $errno, + $errstr, + 10, + STREAM_CLIENT_CONNECT, + $ctx + ); + if (! $this->connection) { + throw new IcingaException( + 'NRPE Connection failed: %s', + $errstr + ); + } + } + + protected function connection() + { + if ($this->connection === null) { + $this->connect(); + } + return $this->connection; + } + + protected function disconnect() + { + if (is_resource($this->connection)) { + fclose($this->connection); + $this->connection = null; + } + return $this; + } + + public function __destruct() + { + $this->disconnect(); + } +} diff --git a/library/Icinga/Protocol/Nrpe/Packet.php b/library/Icinga/Protocol/Nrpe/Packet.php new file mode 100644 index 0000000..54c8526 --- /dev/null +++ b/library/Icinga/Protocol/Nrpe/Packet.php @@ -0,0 +1,69 @@ +<?php +/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Protocol\Nrpe; + +class Packet +{ + const QUERY = 0x01; + const RESPONSE = 0x02; + + protected $version = 0x02; + protected $type; + protected $body; + protected static $randomBytes; + + public function __construct($type, $body) + { + $this->type = $type; + $this->body = $body; + $this->regenerateRandomBytes(); + } + + // TODO: renew "from time to time" to allow long-running daemons + protected function regenerateRandomBytes() + { + self::$randomBytes = ''; + for ($i = 0; $i < 4096; $i++) { + self::$randomBytes .= pack('N', mt_rand()); + } + } + + public static function createQuery($body) + { + $packet = new Packet(self::QUERY, $body); + return $packet; + } + + protected function getFillString($length) + { + $max = strlen(self::$randomBytes) - $length; + return substr(self::$randomBytes, rand(0, $max), $length); + } + + // TODO: WTF is SR? And 2324? + public function getBinary() + { + $version = pack('n', $this->version); + $type = pack('n', $this->type); + $dummycrc = "\x00\x00\x00\x00"; + $result = "\x00\x00"; + $result = pack('n', 2324); + $body = $this->body + . "\x00" + . $this->getFillString(1023 - strlen($this->body)) + . 'SR'; + + $crc = pack( + 'N', + crc32($version . $type . $dummycrc . $result . $body) + ); + $bytes = $version . $type . $crc . $result . $body; + return $bytes; + } + + public function __toString() + { + return $this->body; + } +} |