| 1 | /**************************************************************************
|
|---|
| 2 | * Copyright (C) 2004-2007 by Michael Medin <michael@medin.name> *
|
|---|
| 3 | * *
|
|---|
| 4 | * This code is part of NSClient++ - http://trac.nakednuns.org/nscp *
|
|---|
| 5 | * *
|
|---|
| 6 | * This program is free software; you can redistribute it and/or modify *
|
|---|
| 7 | * it under the terms of the GNU General Public License as published by *
|
|---|
| 8 | * the Free Software Foundation; either version 2 of the License, or *
|
|---|
| 9 | * (at your option) any later version. *
|
|---|
| 10 | * *
|
|---|
| 11 | * This program is distributed in the hope that it will be useful, *
|
|---|
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|---|
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|---|
| 14 | * GNU General Public License for more details. *
|
|---|
| 15 | * *
|
|---|
| 16 | * You should have received a copy of the GNU General Public License *
|
|---|
| 17 | * along with this program; if not, write to the *
|
|---|
| 18 | * Free Software Foundation, Inc., *
|
|---|
| 19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
|---|
| 20 | ***************************************************************************/
|
|---|
| 21 | #pragma once
|
|---|
| 22 |
|
|---|
| 23 |
|
|---|
| 24 | typedef short int16_t;
|
|---|
| 25 | typedef unsigned long u_int32_t;
|
|---|
| 26 |
|
|---|
| 27 | class NRPEPacket {
|
|---|
| 28 | public:
|
|---|
| 29 | static const short unknownPacket = 0;
|
|---|
| 30 | static const short queryPacket = 1;
|
|---|
| 31 | static const short responsePacket = 2;
|
|---|
| 32 | static const short version2 = 2;
|
|---|
| 33 |
|
|---|
| 34 | class NRPEPacketException {
|
|---|
| 35 | std::wstring error_;
|
|---|
| 36 | public:
|
|---|
| 37 | NRPEPacketException(std::wstring error) : error_(error) {}
|
|---|
| 38 | std::wstring getMessage() {
|
|---|
| 39 | return error_;
|
|---|
| 40 | }
|
|---|
| 41 | };
|
|---|
| 42 |
|
|---|
| 43 | private:
|
|---|
| 44 | typedef struct packet {
|
|---|
| 45 | int16_t packet_version;
|
|---|
| 46 | int16_t packet_type;
|
|---|
| 47 | u_int32_t crc32_value;
|
|---|
| 48 | int16_t result_code;
|
|---|
| 49 | char buffer[];
|
|---|
| 50 | } packet;
|
|---|
| 51 | std::wstring payload_;
|
|---|
| 52 | short type_;
|
|---|
| 53 | short version_;
|
|---|
| 54 | NSCAPI::nagiosReturn result_;
|
|---|
| 55 | unsigned int crc32_;
|
|---|
| 56 | unsigned int calculatedCRC32_;
|
|---|
| 57 | char *tmpBuffer;
|
|---|
| 58 | unsigned int buffer_length_;
|
|---|
| 59 | public:
|
|---|
| 60 | NRPEPacket(unsigned int buffer_length) : tmpBuffer(NULL), buffer_length_(buffer_length) {};
|
|---|
| 61 | NRPEPacket(const char *buffer, unsigned int length, unsigned int buffer_length) : tmpBuffer(NULL), buffer_length_(buffer_length) {
|
|---|
| 62 | readFrom(buffer, length);
|
|---|
| 63 | };
|
|---|
| 64 | NRPEPacket(short type, short version, NSCAPI::nagiosReturn result, std::wstring payLoad, unsigned int buffer_length)
|
|---|
| 65 | : tmpBuffer(NULL)
|
|---|
| 66 | ,type_(type)
|
|---|
| 67 | ,version_(version)
|
|---|
| 68 | ,result_(result)
|
|---|
| 69 | ,payload_(payLoad)
|
|---|
| 70 | ,buffer_length_(buffer_length)
|
|---|
| 71 | {
|
|---|
| 72 | }
|
|---|
| 73 | NRPEPacket()
|
|---|
| 74 | : tmpBuffer(NULL)
|
|---|
| 75 | ,type_(unknownPacket)
|
|---|
| 76 | ,version_(version2)
|
|---|
| 77 | ,result_(0)
|
|---|
| 78 | ,buffer_length_(0)
|
|---|
| 79 | {
|
|---|
| 80 | }
|
|---|
| 81 | NRPEPacket(NRPEPacket &other) : tmpBuffer(NULL) {
|
|---|
| 82 | payload_ = other.payload_;
|
|---|
| 83 | type_ = other.type_;
|
|---|
| 84 | version_ = other.version_;
|
|---|
| 85 | result_ = other.result_;
|
|---|
| 86 | crc32_ = other.crc32_;
|
|---|
| 87 | calculatedCRC32_ = other.calculatedCRC32_;
|
|---|
| 88 | buffer_length_ = other.buffer_length_;
|
|---|
| 89 | }
|
|---|
| 90 | ~NRPEPacket() {
|
|---|
| 91 | delete [] tmpBuffer;
|
|---|
| 92 | }
|
|---|
| 93 | static NRPEPacket make_request(std::wstring payload, unsigned int buffer_length) {
|
|---|
| 94 | return NRPEPacket(queryPacket, version2, -1, payload, buffer_length);
|
|---|
| 95 | }
|
|---|
| 96 |
|
|---|
| 97 | const char* getBuffer() {
|
|---|
| 98 | delete [] tmpBuffer;
|
|---|
| 99 | tmpBuffer = new char[getBufferLength()+1];
|
|---|
| 100 | ZeroMemory(tmpBuffer, getBufferLength()+1);
|
|---|
| 101 | packet *p = reinterpret_cast<packet*>(tmpBuffer);
|
|---|
| 102 | p->result_code = htons(NSCHelper::nagios2int(result_));
|
|---|
| 103 | p->packet_type = htons(type_);
|
|---|
| 104 | p->packet_version = htons(version_);
|
|---|
| 105 | if (payload_.length() >= buffer_length_-1)
|
|---|
| 106 | throw NRPEPacketException(_T("To much data cant create return packet (truncate datat)"));
|
|---|
| 107 | //ZeroMemory(p->buffer, buffer_length_-1);
|
|---|
| 108 | strncpy_s(p->buffer, buffer_length_-1, strEx::wstring_to_string(payload_).c_str(), payload_.length());
|
|---|
| 109 | p->buffer[payload_.length()] = 0;
|
|---|
| 110 | p->crc32_value = 0;
|
|---|
| 111 | p->crc32_value = htonl(calculate_crc32(tmpBuffer, getBufferLength()));
|
|---|
| 112 | return tmpBuffer;
|
|---|
| 113 | }
|
|---|
| 114 |
|
|---|
| 115 | void readFrom(const char *buffer, unsigned int length) {
|
|---|
| 116 | if (buffer == NULL)
|
|---|
| 117 | throw NRPEPacketException(_T("No buffer."));
|
|---|
| 118 | if (length != getBufferLength())
|
|---|
| 119 | throw NRPEPacketException(_T("Invalid length: ") + strEx::itos(length) + _T(" != ") + strEx::itos(getBufferLength()));
|
|---|
| 120 | const packet *p = reinterpret_cast<const packet*>(buffer);
|
|---|
| 121 | type_ = ntohs(p->packet_type);
|
|---|
| 122 | if ((type_ != queryPacket)&&(type_ != responsePacket))
|
|---|
| 123 | throw NRPEPacketException(_T("Invalid packet type."));
|
|---|
| 124 | version_ = ntohs(p->packet_version);
|
|---|
| 125 | if (version_ != version2)
|
|---|
| 126 | throw NRPEPacketException(_T("Invalid packet version."));
|
|---|
| 127 | crc32_ = ntohl(p->crc32_value);
|
|---|
| 128 | // Verify CRC32
|
|---|
| 129 | // @todo Fix this, currently we need a const buffer so we cannot change the CRC to 0.
|
|---|
| 130 | char * tb = new char[getBufferLength()+1];
|
|---|
| 131 | memcpy(tb, buffer, getBufferLength());
|
|---|
| 132 | packet *p2 = reinterpret_cast<packet*>(tb);
|
|---|
| 133 | p2->crc32_value = 0;
|
|---|
| 134 | calculatedCRC32_ = calculate_crc32(tb, getBufferLength());
|
|---|
| 135 | delete [] tb;
|
|---|
| 136 | if (crc32_ != calculatedCRC32_)
|
|---|
| 137 | throw NRPEPacketException(_T("Invalid checksum in NRPE packet!"));
|
|---|
| 138 | // Verify CRC32 end
|
|---|
| 139 | result_ = NSCHelper::int2nagios(ntohs(p->result_code));
|
|---|
| 140 | payload_ = strEx::string_to_wstring(std::string(p->buffer));
|
|---|
| 141 | }
|
|---|
| 142 |
|
|---|
| 143 | unsigned short getVersion() const { return version_; }
|
|---|
| 144 | unsigned short getType() const { return type_; }
|
|---|
| 145 | unsigned short getResult() const { return result_; }
|
|---|
| 146 | std::wstring getPayload() const { return payload_; }
|
|---|
| 147 | bool verifyCRC() { return calculatedCRC32_ == crc32_; }
|
|---|
| 148 | unsigned int getBufferLength() const { return getBufferLength(buffer_length_); }
|
|---|
| 149 | static unsigned int getBufferLength(unsigned int buffer_length) { return sizeof(packet)+buffer_length*sizeof(char); }
|
|---|
| 150 | unsigned int getInternalBufferLength() const { return buffer_length_; }
|
|---|
| 151 |
|
|---|
| 152 |
|
|---|
| 153 | std::wstring toString() {
|
|---|
| 154 | std::wstringstream ss;
|
|---|
| 155 | ss << _T("type: ") << type_;
|
|---|
| 156 | ss << _T(", version: ") << version_;
|
|---|
| 157 | ss << _T(", result: ") << result_;
|
|---|
| 158 | ss << _T(", payload: ") << payload_;
|
|---|
| 159 | return ss.str();
|
|---|
| 160 | }
|
|---|
| 161 |
|
|---|
| 162 | };
|
|---|
| 163 |
|
|---|
| 164 |
|
|---|
| 165 |
|
|---|
| 166 |
|
|---|