libtins  3.4
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Pages
internals.h
1 /*
2  * Copyright (c) 2016, Matias Fontanini
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * * Redistributions in binary form must reproduce the above
12  * copyright notice, this list of conditions and the following disclaimer
13  * in the documentation and/or other materials provided with the
14  * distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  *
28  */
29 
30 #ifndef TINS_INTERNALS_H
31 #define TINS_INTERNALS_H
32 
33 #if TINS_IS_CXX11
34 #include <type_traits>
35 #endif
36 
37 #include <sstream>
38 #include <string>
39 #include <stdint.h>
40 #include "constants.h"
41 #include "pdu.h"
42 #include "hw_address.h"
43 
47 namespace Tins {
48 namespace Memory {
49 
50 class InputMemoryStream;
51 } // Memory
52 class IPv4Address;
53 class IPv6Address;
54 class ICMPExtensionsStructure;
55 
56 namespace Internals {
57 
58 template<size_t n>
59 class byte_array {
60 public:
61  typedef uint8_t* iterator;
62  typedef const uint8_t* const_iterator;
63 
64  byte_array() {
65  std::fill(begin(), end(), 0);
66  }
67 
68  template<typename InputIterator>
69  byte_array(InputIterator start, InputIterator last) {
70  std::copy(start, last, data);
71  }
72 
73  template<typename InputIterator>
74  byte_array(InputIterator start) {
75  std::copy(start, n, data);
76  }
77 
78  uint8_t& operator[](size_t i) {
79  return data[i];
80  }
81 
82  uint8_t operator[](size_t i) const{
83  return data[i];
84  }
85 
86  iterator begin() {
87  return data;
88  }
89 
90  iterator end() {
91  return data + n;
92  }
93 
94  const_iterator begin() const {
95  return data;
96  }
97 
98  const_iterator end() const {
99  return data + n;
100  }
101 
102  size_t size() const {
103  return n;
104  }
105 private:
106  uint8_t data[n];
107 };
108 
109 void skip_line(std::istream& input);
110 bool from_hex(const std::string& str, uint32_t& result);
111 bool from_hex(const std::string& str, std::string& result);
112 
113 template<bool, typename T = void>
114 struct enable_if {
115  typedef T type;
116 };
117 
118 template<typename T>
119 struct enable_if<false, T> {
120 
121 };
122 
123 PDU* pdu_from_flag(Constants::Ethernet::e flag, const uint8_t* buffer,
124  uint32_t size, bool rawpdu_on_no_match = true);
125 PDU* pdu_from_flag(Constants::IP::e flag, const uint8_t* buffer,
126  uint32_t size, bool rawpdu_on_no_match = true);
127 PDU* pdu_from_dlt_flag(int flag, const uint8_t* buffer,
128  uint32_t size, bool rawpdu_on_no_match = true);
129 PDU* pdu_from_flag(PDU::PDUType type, const uint8_t* buffer, uint32_t size);
130 
131 Constants::Ethernet::e pdu_flag_to_ether_type(PDU::PDUType flag);
132 PDU::PDUType ether_type_to_pdu_flag(Constants::Ethernet::e flag);
133 Constants::IP::e pdu_flag_to_ip_type(PDU::PDUType flag);
134 PDU::PDUType ip_type_to_pdu_flag(Constants::IP::e flag);
135 
136 uint32_t get_padded_icmp_inner_pdu_size(const PDU* inner_pdu, uint32_t pad_alignment);
137 void try_parse_icmp_extensions(Memory::InputMemoryStream& stream,
138  uint32_t payload_length, ICMPExtensionsStructure& extensions);
139 
140 template<typename T>
141 bool increment_buffer(T& addr) {
142  typename T::iterator it = addr.end() - 1;
143  while (it >= addr.begin() && *it == 0xff) {
144  *it = 0;
145  --it;
146  }
147  // reached end
148  if (it < addr.begin()) {
149  return true;
150  }
151  (*it)++;
152  return false;
153 }
154 
155 template<typename T>
156 bool decrement_buffer(T& addr) {
157  typename T::iterator it = addr.end() - 1;
158  while (it >= addr.begin() && *it == 0) {
159  *it = 0xff;
160  --it;
161  }
162  // reached end
163  if (it < addr.begin()) {
164  return true;
165  }
166  (*it)--;
167  return false;
168 }
169 
170 bool increment(IPv4Address& addr);
171 bool increment(IPv6Address& addr);
172 bool decrement(IPv4Address& addr);
173 bool decrement(IPv6Address& addr);
174 template<size_t n>
175 bool increment(HWAddress<n>& addr) {
176  return increment_buffer(addr);
177 }
178 template<size_t n>
179 bool decrement(HWAddress<n>& addr) {
180  return decrement_buffer(addr);
181 }
182 
183 // Compares sequence numbers as defined by RFC 1982.
184 int seq_compare(uint32_t seq1, uint32_t seq2);
185 
186 IPv4Address last_address_from_mask(IPv4Address addr, IPv4Address mask);
187 IPv6Address last_address_from_mask(IPv6Address addr, const IPv6Address& mask);
188 template<size_t n>
189 HWAddress<n> last_address_from_mask(HWAddress<n> addr, const HWAddress<n>& mask) {
190  typename HWAddress<n>::iterator addr_iter = addr.begin();
191  for (typename HWAddress<n>::const_iterator it = mask.begin(); it != mask.end(); ++it, ++addr_iter) {
192  *addr_iter = *addr_iter | ~*it;
193  }
194  return addr;
195 }
196 
197 inline bool is_dot3(const uint8_t* ptr, size_t sz) {
198  return (sz >= 13 && ptr[12] < 8);
199 }
200 
201 template<typename T>
202 struct is_unsigned_integral {
203  static const bool value = false;
204 };
205 
206 template<>
207 struct is_unsigned_integral<uint8_t> {
208  static const bool value = true;
209 };
210 
211 template<>
212 struct is_unsigned_integral<uint16_t> {
213  static const bool value = true;
214 };
215 
216 template<>
217 struct is_unsigned_integral<uint32_t> {
218  static const bool value = true;
219 };
220 
221 template<>
222 struct is_unsigned_integral<uint64_t> {
223  static const bool value = true;
224 };
225 
226 #if TINS_IS_CXX11 && !defined(_MSC_VER)
227 
228 // Template metaprogramming trait to determine if a functor can accept another parameter as an argument
229 template <typename T, typename P, typename=void>
230 struct accepts_type : std::false_type { };
231 
232 template <typename T, typename P>
233 struct accepts_type<T, P,
234  typename std::enable_if<
235  std::is_same< decltype( std::declval<T>()(std::declval<P>()) ), bool>::value
236  >::type
237 > : std::true_type { };
238 
239 // use enable_if to invoke the Packet&& version of the sniff_loop handler if possible - otherwise fail to old behavior
240 template <typename Functor, typename Packet>
241 bool invoke_loop_cb(Functor& f, Packet& p, typename std::enable_if<accepts_type<Functor, Packet>::value, bool>::type* = 0) {
242  return f(std::move(p));
243 }
244 
245 template <typename Functor, typename Packet>
246 bool invoke_loop_cb(Functor& f, Packet& p, typename std::enable_if<!accepts_type<Functor, Packet>::value && accepts_type<Functor, Packet&>::value, bool>::type* = 0) {
247  return f(p);
248 }
249 
250 template <typename Functor, typename Packet>
251 bool invoke_loop_cb(Functor& f, Packet& p, typename std::enable_if<!accepts_type<Functor, Packet>::value && !accepts_type<Functor, Packet&>::value, bool>::type* = 0) {
252  return f(*p.pdu());
253 }
254 #endif
255 
256 } // namespace Internals
257 } // namespace Tins
262 #endif
std::vector< uint8_t > byte_array
Definition: pdu.h:46
PDUType
Enum which identifies each type of PDU.
Definition: pdu.h:128