source: nscp/include/nrpe/nrpepacket.hpp @ 9b3f53c

0.4.00.4.10.4.2
Last change on this file since 9b3f53c was 9b3f53c, checked in by Michael Medin <michael@…>, 4 years ago

First version of a working NRPE Listener (does not (yet) handle commands but sockets are there and such)

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