source: nscp/include/nrpe/packet.hpp @ 724a835

0.4.10.4.2
Last change on this file since 724a835 was 724a835, checked in by Michael Medin <michael@…>, 11 months ago
  • Tracked down a few memory leaks when connections time-out.
  • Added test cases for connection timeouts in lua NRPE test suite
  • Improved the LUA module a bit
  • Property mode set to 100644
File size: 10.3 KB
Line 
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
31using namespace nscp::helpers;
32
33namespace 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
Note: See TracBrowser for help on using the repository browser.