| 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 | #include <types.hpp>
|
|---|
| 24 | #include <string>
|
|---|
| 25 | #include <unicode_char.hpp>
|
|---|
| 26 | #include <boost/asio/buffer.hpp>
|
|---|
| 27 | #include <swap_bytes.hpp>
|
|---|
| 28 | #include <strEx.h>
|
|---|
| 29 | #include <utils.h>
|
|---|
| 30 |
|
|---|
| 31 | using namespace nscp::helpers;
|
|---|
| 32 |
|
|---|
| 33 | namespace nrpe {
|
|---|
| 34 |
|
|---|
| 35 |
|
|---|
| 36 |
|
|---|
| 37 | class data {
|
|---|
| 38 | public:
|
|---|
| 39 | static const short unknownPacket = 0;
|
|---|
| 40 | static const short queryPacket = 1;
|
|---|
| 41 | static const short responsePacket = 2;
|
|---|
| 42 | static const short version2 = 2;
|
|---|
| 43 |
|
|---|
| 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 |
|
|---|
| 52 | };
|
|---|
| 53 |
|
|---|
| 54 | class length {
|
|---|
| 55 | typedef unsigned int size_type;
|
|---|
| 56 | static size_type payload_length_;
|
|---|
| 57 | public:
|
|---|
| 58 | static void set_payload_length(size_type length) {
|
|---|
| 59 | payload_length_ = length;
|
|---|
| 60 | }
|
|---|
| 61 | static size_type get_packet_length() {
|
|---|
| 62 | return get_packet_length(payload_length_);
|
|---|
| 63 | }
|
|---|
| 64 | static size_type get_packet_length(size_type payload_length) {
|
|---|
| 65 | return sizeof(nrpe::data::packet)+payload_length*sizeof(char);
|
|---|
| 66 | }
|
|---|
| 67 | static size_type get_payload_length() {
|
|---|
| 68 | return payload_length_;
|
|---|
| 69 | }
|
|---|
| 70 | static size_type get_payload_length(size_type packet_length) {
|
|---|
| 71 | return (packet_length-sizeof(nrpe::data::packet))/sizeof(char);
|
|---|
| 72 | }
|
|---|
| 73 | };
|
|---|
| 74 |
|
|---|
| 75 | class nrpe_exception : public std::exception {
|
|---|
| 76 | std::string error_;
|
|---|
| 77 | public:
|
|---|
| 78 | nrpe_exception(std::wstring error) : error_(utf8::cvt<std::string>(error)) {}
|
|---|
| 79 | nrpe_exception(std::string error) : error_(utf8::cvt<std::string>(error)) {}
|
|---|
| 80 | ~nrpe_exception() throw() {}
|
|---|
| 81 | const char* what() const throw() {
|
|---|
| 82 | return error_.c_str();
|
|---|
| 83 | }
|
|---|
| 84 | const std::wstring wwhat() const throw() {
|
|---|
| 85 | return utf8::to_unicode(error_);
|
|---|
| 86 | }
|
|---|
| 87 | };
|
|---|
| 88 | class nrpe_packet_exception : public nrpe_exception {
|
|---|
| 89 | public:
|
|---|
| 90 | nrpe_packet_exception(std::wstring error) : nrpe_exception(error) {}
|
|---|
| 91 | };
|
|---|
| 92 |
|
|---|
| 93 | class packet /*: public boost::noncopyable*/ {
|
|---|
| 94 | public:
|
|---|
| 95 |
|
|---|
| 96 |
|
|---|
| 97 | private:
|
|---|
| 98 | char *tmpBuffer;
|
|---|
| 99 | unsigned int payload_length_;
|
|---|
| 100 | short type_;
|
|---|
| 101 | short version_;
|
|---|
| 102 | int result_;
|
|---|
| 103 | std::wstring payload_;
|
|---|
| 104 | unsigned int crc32_;
|
|---|
| 105 | unsigned int calculatedCRC32_;
|
|---|
| 106 | public:
|
|---|
| 107 | packet(unsigned int payload_length) : tmpBuffer(NULL), payload_length_(payload_length) {};
|
|---|
| 108 | packet(std::vector<char> buffer, unsigned int payload_length) : tmpBuffer(NULL), payload_length_(payload_length) {
|
|---|
| 109 | char *tmp = new char[buffer.size()+1];
|
|---|
| 110 | copy( buffer.begin(), buffer.end(), tmp);
|
|---|
| 111 | try {
|
|---|
| 112 | readFrom(tmp, buffer.size());
|
|---|
| 113 | } catch (nrpe::nrpe_packet_exception &e) {
|
|---|
| 114 | delete [] tmp;
|
|---|
| 115 | throw e;
|
|---|
| 116 | }
|
|---|
| 117 | delete [] tmp;
|
|---|
| 118 | };
|
|---|
| 119 | packet(const char *buffer, unsigned int buffer_length) : tmpBuffer(NULL), payload_length_(length::get_payload_length(buffer_length)) {
|
|---|
| 120 | readFrom(buffer, buffer_length);
|
|---|
| 121 | };
|
|---|
| 122 | packet(short type, short version, int result, std::wstring payLoad, unsigned int payload_length)
|
|---|
| 123 | : tmpBuffer(NULL)
|
|---|
| 124 | , payload_length_(payload_length)
|
|---|
| 125 | , type_(type)
|
|---|
| 126 | , version_(version)
|
|---|
| 127 | , result_(result)
|
|---|
| 128 | , payload_(payLoad)
|
|---|
| 129 | , crc32_(0)
|
|---|
| 130 | , calculatedCRC32_(0)
|
|---|
| 131 | {
|
|---|
| 132 | }
|
|---|
| 133 | packet()
|
|---|
| 134 | : tmpBuffer(NULL)
|
|---|
| 135 | , payload_length_(nrpe::length::get_payload_length())
|
|---|
| 136 | , type_(nrpe::data::unknownPacket)
|
|---|
| 137 | , version_(nrpe::data::version2)
|
|---|
| 138 | , result_(0)
|
|---|
| 139 | , crc32_(0)
|
|---|
| 140 | , calculatedCRC32_(0)
|
|---|
| 141 | {
|
|---|
| 142 | }
|
|---|
| 143 | packet(const packet &other) : tmpBuffer(NULL) {
|
|---|
| 144 | payload_ = other.payload_;
|
|---|
| 145 | type_ = other.type_;
|
|---|
| 146 | version_ = other.version_;
|
|---|
| 147 | result_ = other.result_;
|
|---|
| 148 | crc32_ = other.crc32_;
|
|---|
| 149 | calculatedCRC32_ = other.calculatedCRC32_;
|
|---|
| 150 | payload_length_ = other.payload_length_;
|
|---|
| 151 | }
|
|---|
| 152 | packet& operator=(packet const& other) {
|
|---|
| 153 | tmpBuffer=NULL;
|
|---|
| 154 | payload_ = other.payload_;
|
|---|
| 155 | type_ = other.type_;
|
|---|
| 156 | version_ = other.version_;
|
|---|
| 157 | result_ = other.result_;
|
|---|
| 158 | crc32_ = other.crc32_;
|
|---|
| 159 | calculatedCRC32_ = other.calculatedCRC32_;
|
|---|
| 160 | payload_length_ = other.payload_length_;
|
|---|
| 161 | return *this;
|
|---|
| 162 | }
|
|---|
| 163 |
|
|---|
| 164 | static packet unknown_response(std::wstring message) {
|
|---|
| 165 | return packet(nrpe::data::responsePacket, nrpe::data::version2, 3, message, 0);
|
|---|
| 166 | }
|
|---|
| 167 |
|
|---|
| 168 | ~packet() {
|
|---|
| 169 | delete [] tmpBuffer;
|
|---|
| 170 | }
|
|---|
| 171 | static packet make_request(std::wstring payload, unsigned int buffer_length) {
|
|---|
| 172 | return packet(nrpe::data::queryPacket, nrpe::data::version2, -1, payload, buffer_length);
|
|---|
| 173 | }
|
|---|
| 174 |
|
|---|
| 175 | const char* create_buffer() {
|
|---|
| 176 | delete [] tmpBuffer;
|
|---|
| 177 | unsigned int packet_length = nrpe::length::get_packet_length(payload_length_);
|
|---|
| 178 | tmpBuffer = new char[packet_length+1];
|
|---|
| 179 | memset(tmpBuffer, 0, packet_length+1);
|
|---|
| 180 | //TODO readd this ZeroMemory(tmpBuffer, getBufferLength()+1);
|
|---|
| 181 | nrpe::data::packet *p = reinterpret_cast<nrpe::data::packet*>(tmpBuffer);
|
|---|
| 182 | p->result_code = swap_bytes::hton<int16_t>(result_);
|
|---|
| 183 | p->packet_type = swap_bytes::hton<int16_t>(type_);
|
|---|
| 184 | p->packet_version = swap_bytes::hton<int16_t>(version_);
|
|---|
| 185 | if (payload_.length() >= payload_length_-1)
|
|---|
| 186 | throw nrpe::nrpe_packet_exception(_T("To much data cant create return packet (truncate datat)"));
|
|---|
| 187 | //ZeroMemory(p->buffer, payload_length_-1);
|
|---|
| 188 | strncpy(p->buffer, ::to_string(payload_).c_str(), payload_.length());
|
|---|
| 189 | p->buffer[payload_.length()] = 0;
|
|---|
| 190 | p->crc32_value = 0;
|
|---|
| 191 | crc32_ = p->crc32_value = swap_bytes::hton<u_int32_t>(calculate_crc32(tmpBuffer, packet_length));
|
|---|
| 192 | // std::wcout << _T("About to send: ") << to_string() << std::endl;
|
|---|
| 193 | // std::wcout << _T("About to send: ")
|
|---|
| 194 | // << _T("<<<") << to_wstring(strEx::format_buffer(tmpBuffer, packet_length))
|
|---|
| 195 | // << _T(">>>, ") << strEx::ihextos((int16_t)tmpBuffer[2])
|
|---|
| 196 | // << _T(", ") << strEx::ihextos((u_int32_t)tmpBuffer[4])
|
|---|
| 197 | // << _T(", ") << strEx::ihextos((int16_t)tmpBuffer[8])
|
|---|
| 198 | // << _T(", crc: ") << strEx::ihextos(p->crc32_value)
|
|---|
| 199 | // << std::endl;
|
|---|
| 200 | return tmpBuffer;
|
|---|
| 201 | }
|
|---|
| 202 |
|
|---|
| 203 | std::vector<char> get_buffer() {
|
|---|
| 204 | const char *c = create_buffer();
|
|---|
| 205 | std::vector<char> buf(c, c+get_packet_length());
|
|---|
| 206 | return buf;
|
|---|
| 207 | }
|
|---|
| 208 |
|
|---|
| 209 | void readFrom(const char *buffer, std::size_t length) {
|
|---|
| 210 | // std::wcout << _T("Just read: ")
|
|---|
| 211 | // << _T("") << strEx::ihextos(buffer[0])
|
|---|
| 212 | // << _T(", ") << strEx::ihextos(buffer[1])
|
|---|
| 213 | // << _T(", ") << strEx::ihextos(buffer[2])
|
|---|
| 214 | // << _T(", ") << strEx::ihextos(buffer[3])
|
|---|
| 215 | // << _T(", ") << strEx::ihextos(buffer[4])
|
|---|
| 216 | // << std::endl;
|
|---|
| 217 | if (buffer == NULL)
|
|---|
| 218 | throw nrpe::nrpe_packet_exception(_T("No buffer."));
|
|---|
| 219 | if (length != get_packet_length())
|
|---|
| 220 | throw nrpe::nrpe_packet_exception(_T("Invalid packet length: ") + strEx::itos(length) + _T(" != ") + strEx::itos(get_packet_length()) + _T(" configured payload is: ") + to_wstring(get_payload_length()));
|
|---|
| 221 | const nrpe::data::packet *p = reinterpret_cast<const nrpe::data::packet*>(buffer);
|
|---|
| 222 | type_ = swap_bytes::ntoh<int16_t>(p->packet_type);
|
|---|
| 223 | if ((type_ != nrpe::data::queryPacket)&&(type_ != nrpe::data::responsePacket))
|
|---|
| 224 | throw nrpe::nrpe_packet_exception(_T("Invalid packet type: ") + strEx::itos(type_));
|
|---|
| 225 | version_ = swap_bytes::ntoh<int16_t>(p->packet_version);
|
|---|
| 226 | if (version_ != nrpe::data::version2)
|
|---|
| 227 | throw nrpe::nrpe_packet_exception(_T("Invalid packet version.") + strEx::itos(version_));
|
|---|
| 228 | crc32_ = swap_bytes::ntoh<u_int32_t>(p->crc32_value);
|
|---|
| 229 | // Verify CRC32
|
|---|
| 230 | // @todo Fix this, currently we need a const buffer so we cannot change the CRC to 0.
|
|---|
| 231 | char * tb = new char[length+1];
|
|---|
| 232 | memcpy(tb, buffer, length);
|
|---|
| 233 | nrpe::data::packet *p2 = reinterpret_cast<nrpe::data::packet*>(tb);
|
|---|
| 234 | p2->crc32_value = 0;
|
|---|
| 235 | calculatedCRC32_ = calculate_crc32(tb, get_packet_length());
|
|---|
| 236 | delete [] tb;
|
|---|
| 237 | // std::wcout << _T("Just read: ") << to_string() << std::endl;
|
|---|
| 238 | if (crc32_ != calculatedCRC32_)
|
|---|
| 239 | throw nrpe::nrpe_packet_exception(_T("Invalid checksum in NRPE packet: ") + strEx::ihextos(crc32_) + _T("!=") + strEx::ihextos(calculatedCRC32_));
|
|---|
| 240 | // Verify CRC32 end
|
|---|
| 241 | result_ = swap_bytes::ntoh<int16_t>(p->result_code);
|
|---|
| 242 | payload_ = strEx::string_to_wstring(std::string(p->buffer));
|
|---|
| 243 | }
|
|---|
| 244 |
|
|---|
| 245 | unsigned short getVersion() const { return version_; }
|
|---|
| 246 | unsigned short getType() const { return type_; }
|
|---|
| 247 | unsigned short getResult() const { return result_; }
|
|---|
| 248 | std::wstring getPayload() const { return payload_; }
|
|---|
| 249 | bool verifyCRC() { return calculatedCRC32_ == crc32_; }
|
|---|
| 250 | unsigned int get_packet_length() const { return nrpe::length::get_packet_length(payload_length_); }
|
|---|
| 251 | unsigned int get_payload_length() const { return payload_length_; }
|
|---|
| 252 |
|
|---|
| 253 | boost::asio::const_buffer to_buffers() {
|
|---|
| 254 | return boost::asio::buffer(create_buffer(), get_packet_length());
|
|---|
| 255 | }
|
|---|
| 256 | std::wstring to_string() {
|
|---|
| 257 | std::wstringstream ss;
|
|---|
| 258 | ss << _T("type: ") << type_;
|
|---|
| 259 | ss << _T(", version: ") << version_;
|
|---|
| 260 | ss << _T(", result: ") << result_;
|
|---|
| 261 | ss << _T(", crc32: ") << crc32_;
|
|---|
| 262 | ss << _T(", payload: ") << payload_;
|
|---|
| 263 | return ss.str();
|
|---|
| 264 | }
|
|---|
| 265 | static nrpe::packet create_response(int ret, std::wstring string, int buffer_length) {
|
|---|
| 266 | return packet(nrpe::data::responsePacket, nrpe::data::version2, ret, string, buffer_length);
|
|---|
| 267 | }
|
|---|
| 268 | };
|
|---|
| 269 | }
|
|---|
| 270 |
|
|---|