remove the footer saying that vim is the best editor -- anyone knows anyway
[pingcheck] / src / icmp / icmpdata.cpp
1 /*
2  The software in this package is distributed under the GNU General
3  Public License version 2 (with a special exception described below).
4
5  A copy of GNU General Public License (GPL) is included in this distribution,
6  in the file COPYING.GPL.
7
8  As a special exception, if other files instantiate templates or use macros
9  or inline functions from this file, or you compile this file and link it
10  with other works to produce a work based on this file, this file
11  does not by itself cause the resulting work to be covered
12  by the GNU General Public License.
13
14  However the source code for this file must still be made available
15  in accordance with section (3) of the GNU General Public License.
16
17  This exception does not invalidate any other reasons why a work based
18  on this file might be covered by the GNU General Public License.
19
20  Christian Herdtweck, Intra2net AG 2015
21  Based on an example in Boost Documentation (by Christopher M. Kohlhoff)
22  and adaptation by Guilherme M. Ferreira
23  */
24
25 #include "icmpdata.h"
26
27 #include <sstream>
28 #include <iostream>
29
30 #include <logfunc.hpp>
31
32 #include "boost_assert_handler.h"
33 #include "ip/ipv4header.h"
34 #include "ip/ipv6header.h"
35
36 using I2n::Logger::GlobalLogger;
37 using boost::asio::ip::address;
38
39 IcmpData::IcmpData()
40     : size( 0 )
41     , raw_data( 0 )
42 {}
43
44 IcmpData::IcmpData(const std::size_t size_arg)
45     : size( size_arg )
46     , raw_data( size_arg )
47 {}
48
49 bool IcmpData::match_echo_reply(const uint16_t identifier,
50                               const uint16_t sequence_number) const
51 {  return false;  }
52
53 bool IcmpData::match_destination_unreachable(const uint16_t identifier,
54                                   const uint16_t sequence_number,
55                                   const address &destination_address) const
56 {  return false;  }
57
58 bool IcmpData::match_time_exceeded(const uint16_t identifier,
59                                    const uint16_t sequence_number,
60                                    const address &destination_address) const
61 {  return false;  }
62
63 std::size_t IcmpData::get_size() const
64 {  return size;  }
65
66 int IcmpData::get_ip_version() const
67 {
68     int offset = 4;   // the 4 uninteresting bytes we need to skip
69     uint8_t version_with_ihl = static_cast<uint8_t>(IcmpData::raw_data[offset]);
70     int version = static_cast<int>( (version_with_ihl & 0xF0) >> 4 );
71     return version;
72 }
73
74 IpHeaderPtr IcmpData::get_ip_header() const
75 {
76     // make stream from relevant part of payload
77     std::stringbuf buffer;
78     std::ostream buf_filler( &buffer );
79     raw_data.write( buf_filler );
80     std::istream stream( &buffer );
81
82     // skip 4 byte
83     stream.seekg(4, stream.beg);
84
85     // interpret as IP header
86     int ip_version = get_ip_version();
87     IpHeaderPtr result;
88     if (ip_version == 4)
89     {
90         Ipv4Header *result_val = new Ipv4Header();
91         stream >> *result_val;
92         result.reset( result_val );
93     }
94     else if (ip_version == 6)
95     {
96         Ipv6Header *result_val = new Ipv6Header();
97         stream >> *result_val;
98         result.reset( result_val );
99     }
100     else
101     {   // throw runtime error through boost_assert_handler
102         GlobalLogger.error() << "Invalid IP version: " << ip_version
103                              << " ! Maybe data is no IP packet?";
104         BOOST_ASSERT( !"Invalid IP version or not IP packet!" );
105     }
106
107     return result;
108 }
109
110 uint32_t IcmpData::calc_checksum_part() const
111 {  return raw_data.calc_checksum_part();  }
112
113
114 void IcmpData::print( const size_t &bytes_received,
115                       const boost::posix_time::ptime &time_packet_sent,
116                       const std::string &remote_address,
117                       const uint32_t ttl) const
118 {}
119
120 std::istream& IcmpData::read(std::istream &is)  // read raw data
121 {
122     return raw_data.read(is);
123 }
124
125 std::ostream& IcmpData::write(std::ostream &os) const
126 {
127     return raw_data.write(os);
128 }
129
130 std::string IcmpData::to_string() const
131 {
132     std::stringstream buf;
133     buf << "[IcmpData of length " << size << "]";
134     return buf.str();
135 }
136
137 std::istream& operator>>(
138         std::istream &is,
139         IcmpData &data
140 )
141 {  return data.read( is );  }
142
143 std::ostream& operator<<(
144         std::ostream &os,
145         const IcmpData &data
146 )
147 {  return data.write( os );  }
148