Changeset 9b3f53c in nscp for include/nrpe/nrpepacket.hpp


Ignore:
Timestamp:
12/06/09 22:23:10 (4 years ago)
Author:
Michael Medin <michael@…>
Branches:
master, 0.4.0, 0.4.1, 0.4.2
Children:
79e734f
Parents:
dcd90b2
Message:

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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • include/nrpe/nrpepacket.hpp

    r1e0bbec r9b3f53c  
    2222 
    2323#include <types.hpp> 
    24  
    25  
    26 class NRPEPacket { 
    27 public: 
    28   static const short unknownPacket = 0; 
    29   static const short queryPacket = 1; 
    30   static const short responsePacket = 2; 
    31   static const short version2 = 2; 
    32  
    33   class NRPEPacketException { 
     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 { 
    34111    std::wstring error_; 
    35112  public: 
    36     NRPEPacketException(std::wstring error) : error_(error) {} 
     113    nrpe_packet_exception(std::wstring error) : error_(error) {} 
    37114    std::wstring getMessage() { 
    38115      return error_; 
     
    40117  }; 
    41118 
    42 private: 
    43   typedef struct packet { 
    44     int16_t   packet_version; 
    45     int16_t   packet_type; 
    46     u_int32_t crc32_value; 
    47     int16_t   result_code; 
    48     char      buffer[]; 
    49   } packet; 
    50   std::wstring payload_; 
    51   short type_; 
    52   short version_; 
    53   NSCAPI::nagiosReturn result_; 
    54   unsigned int crc32_; 
    55   unsigned int calculatedCRC32_; 
    56   char *tmpBuffer; 
    57   unsigned int buffer_length_; 
    58 public: 
    59   NRPEPacket(unsigned int buffer_length) : tmpBuffer(NULL), buffer_length_(buffer_length) {}; 
    60   NRPEPacket(const char *buffer, unsigned int length, unsigned int buffer_length) : tmpBuffer(NULL), buffer_length_(buffer_length) { 
    61     readFrom(buffer, length); 
    62   }; 
    63   NRPEPacket(short type, short version, NSCAPI::nagiosReturn result, std::wstring payLoad, unsigned int buffer_length)  
    64     : tmpBuffer(NULL)  
    65     ,type_(type) 
    66     ,version_(version) 
    67     ,result_(result) 
    68     ,payload_(payLoad) 
    69     ,buffer_length_(buffer_length) 
    70   { 
    71   } 
    72   NRPEPacket()  
    73     : tmpBuffer(NULL)  
    74     ,type_(unknownPacket) 
    75     ,version_(version2) 
    76     ,result_(0) 
    77     ,buffer_length_(0) 
    78   { 
    79   } 
    80   NRPEPacket(const NRPEPacket &other) : tmpBuffer(NULL) { 
    81     payload_ = other.payload_; 
    82     type_ = other.type_; 
    83     version_ = other.version_; 
    84     result_ = other.result_; 
    85     crc32_ = other.crc32_; 
    86     calculatedCRC32_ = other.calculatedCRC32_; 
    87     buffer_length_ = other.buffer_length_; 
    88   } 
    89   NRPEPacket& operator=(NRPEPacket const& other) { 
    90     tmpBuffer=NULL; 
    91     payload_ = other.payload_; 
    92     type_ = other.type_; 
    93     version_ = other.version_; 
    94     result_ = other.result_; 
    95     crc32_ = other.crc32_; 
    96     calculatedCRC32_ = other.calculatedCRC32_; 
    97     buffer_length_ = other.buffer_length_; 
    98     return *this; 
    99   } 
    100  
    101   ~NRPEPacket() { 
    102     delete [] tmpBuffer; 
    103   } 
    104   static NRPEPacket make_request(std::wstring payload, unsigned int buffer_length) { 
    105     return NRPEPacket(queryPacket, version2, -1, payload, buffer_length); 
    106   } 
    107  
    108   const char* getBuffer() { 
    109     delete [] tmpBuffer; 
    110     tmpBuffer = new char[getBufferLength()+1]; 
    111     //TODO readd this ZeroMemory(tmpBuffer, getBufferLength()+1); 
    112     packet *p = reinterpret_cast<packet*>(tmpBuffer); 
    113     p->result_code = htons(NSCHelper::nagios2int(result_)); 
    114     p->packet_type = htons(type_); 
    115     p->packet_version = htons(version_); 
    116     if (payload_.length() >= buffer_length_-1) 
    117       throw NRPEPacketException(_T("To much data cant create return packet (truncate datat)")); 
    118     //ZeroMemory(p->buffer, buffer_length_-1); 
    119     strncpy(p->buffer, to_string(payload_).c_str(), payload_.length()); 
    120     p->buffer[payload_.length()] = 0; 
    121     p->crc32_value = 0; 
    122     p->crc32_value = htonl(calculate_crc32(tmpBuffer, getBufferLength())); 
    123     return tmpBuffer; 
    124   } 
    125  
    126   void readFrom(const char *buffer, unsigned int length) { 
    127     if (buffer == NULL) 
    128       throw NRPEPacketException(_T("No buffer.")); 
    129     if (length != getBufferLength()) 
    130       throw NRPEPacketException(_T("Invalid length: ") + strEx::itos(length) + _T(" != ") + strEx::itos(getBufferLength())); 
    131     const packet *p = reinterpret_cast<const packet*>(buffer); 
    132     type_ = ntohs(p->packet_type); 
    133     if ((type_ != queryPacket)&&(type_ != responsePacket)) 
    134       throw NRPEPacketException(_T("Invalid packet type.")); 
    135     version_ = ntohs(p->packet_version); 
    136     if (version_ != version2) 
    137       throw NRPEPacketException(_T("Invalid packet version.")); 
    138     crc32_ = ntohl(p->crc32_value); 
    139     // Verify CRC32 
    140     // @todo Fix this, currently we need a const buffer so we cannot change the CRC to 0. 
    141     char * tb = new char[getBufferLength()+1]; 
    142     memcpy(tb, buffer, getBufferLength()); 
    143     packet *p2 = reinterpret_cast<packet*>(tb); 
    144     p2->crc32_value = 0; 
    145     calculatedCRC32_ = calculate_crc32(tb, getBufferLength()); 
    146     delete [] tb; 
    147     if (crc32_ != calculatedCRC32_)  
    148       throw NRPEPacketException(_T("Invalid checksum in NRPE packet!")); 
    149     // Verify CRC32 end 
    150     result_ = NSCHelper::int2nagios(ntohs(p->result_code)); 
    151     payload_ = strEx::string_to_wstring(std::string(p->buffer)); 
    152   } 
    153  
    154   unsigned short getVersion() const { return version_; } 
    155   unsigned short getType() const { return type_; } 
    156   unsigned short getResult() const { return result_; } 
    157   std::wstring getPayload() const { return payload_; } 
    158   bool verifyCRC() { return calculatedCRC32_ == crc32_; } 
    159   unsigned int getBufferLength() const { return getBufferLength(buffer_length_); } 
    160   static unsigned int getBufferLength(unsigned int buffer_length) { return sizeof(packet)+buffer_length*sizeof(char); } 
    161   unsigned int getInternalBufferLength() const { return buffer_length_; } 
    162  
    163  
    164   std::wstring toString() { 
    165     std::wstringstream ss; 
    166     ss << _T("type: ") << type_; 
    167     ss << _T(", version: ") << version_; 
    168     ss << _T(", result: ") << result_; 
    169     ss << _T(", payload: ") << payload_; 
    170     return ss.str(); 
    171   } 
    172  
    173 }; 
    174  
    175  
    176  
    177  
     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 TracChangeset for help on using the changeset viewer.