libtins  4.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Pages
pdu.h
1 /*
2  * Copyright (c) 2017, 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_PDU_H
31 #define TINS_PDU_H
32 
33 
34 #include <stdint.h>
35 #include <vector>
36 #include <tins/macros.h>
37 #include <tins/cxxstd.h>
38 #include <tins/exceptions.h>
39 
42 namespace Tins {
43 
44 class PacketSender;
46 
50 typedef std::vector<uint8_t> byte_array;
51 
107 class TINS_API PDU {
108 public:
113 
117  enum endian_type {
118  BE,
119  LE
120  };
121 
127  enum PDUType {
128  RAW,
129  ETHERNET_II,
130  IEEE802_3,
131  DOT3 = IEEE802_3,
132  RADIOTAP,
133  DOT11,
134  DOT11_ACK,
135  DOT11_ASSOC_REQ,
136  DOT11_ASSOC_RESP,
137  DOT11_AUTH,
138  DOT11_BEACON,
139  DOT11_BLOCK_ACK,
140  DOT11_BLOCK_ACK_REQ,
141  DOT11_CF_END,
142  DOT11_DATA,
143  DOT11_CONTROL,
144  DOT11_DEAUTH,
145  DOT11_DIASSOC,
146  DOT11_END_CF_ACK,
147  DOT11_MANAGEMENT,
148  DOT11_PROBE_REQ,
149  DOT11_PROBE_RESP,
150  DOT11_PS_POLL,
151  DOT11_REASSOC_REQ,
152  DOT11_REASSOC_RESP,
153  DOT11_RTS,
154  DOT11_QOS_DATA,
155  LLC,
156  SNAP,
157  IP,
158  ARP,
159  TCP,
160  UDP,
161  ICMP,
162  BOOTP,
163  DHCP,
164  EAPOL,
165  RC4EAPOL,
166  RSNEAPOL,
167  DNS,
168  LOOPBACK,
169  IPv6,
170  ICMPv6,
171  SLL,
172  DHCPv6,
173  DOT1Q,
174  PPPOE,
175  STP,
176  PPI,
177  IPSEC_AH,
178  IPSEC_ESP,
179  PKTAP,
180  MPLS,
181  UNKNOWN = 999,
182  USER_DEFINED_PDU = 1000
183  };
184 
189  static const endian_type endianness = BE;
190 
194  struct metadata {
198  metadata();
199 
204  metadata(uint32_t header_size, PDUType current_type, PDUType next_type);
205 
209  uint32_t header_size;
210 
215 
220  };
221 
225  PDU();
226 
227  #if TINS_IS_CXX11
228 
233  PDU(PDU &&rhs) TINS_NOEXCEPT
234  : inner_pdu_(0), parent_pdu_(0) {
235  std::swap(inner_pdu_, rhs.inner_pdu_);
236  if (inner_pdu_) {
237  inner_pdu_->parent_pdu(this);
238  }
239  }
240 
246  PDU& operator=(PDU &&rhs) TINS_NOEXCEPT {
247  std::swap(inner_pdu_, rhs.inner_pdu_);
248  rhs.inner_pdu_ = 0;
249  if (inner_pdu_) {
250  inner_pdu_->parent_pdu(this);
251  }
252  return* this;
253  }
254  #endif
255 
262  virtual ~PDU();
263 
266  virtual uint32_t header_size() const = 0;
267 
272  virtual uint32_t trailer_size() const {
273  return 0;
274  }
275 
280  uint32_t size() const;
281 
286  PDU* inner_pdu() const {
287  return inner_pdu_;
288  }
289 
294  PDU* parent_pdu() const {
295  return parent_pdu_;
296  }
297 
311  PDU* release_inner_pdu();
312 
321  void inner_pdu(PDU* next_pdu);
322 
330  void inner_pdu(const PDU& next_pdu);
331 
341  serialization_type serialize();
342 
351  template<typename T>
352  T* find_pdu(PDUType type = T::pdu_flag) {
353  PDU* pdu = this;
354  while (pdu) {
355  if (pdu->matches_flag(type)) {
356  return static_cast<T*>(pdu);
357  }
358  pdu = pdu->inner_pdu();
359  }
360  return 0;
361  }
362 
368  template<typename T>
369  const T* find_pdu(PDUType type = T::pdu_flag) const {
370  return const_cast<PDU*>(this)->find_pdu<T>(type);
371  }
372 
382  template<typename T>
383  T& rfind_pdu(PDUType type = T::pdu_flag) {
384  T* ptr = find_pdu<T>(type);
385  if (!ptr) {
386  throw pdu_not_found();
387  }
388  return* ptr;
389  }
390 
396  template<typename T>
397  const T& rfind_pdu(PDUType type = T::pdu_flag) const {
398  return const_cast<PDU*>(this)->rfind_pdu<T>(type);
399  }
400 
409  virtual PDU* clone() const = 0;
410 
428  virtual void send(PacketSender& sender, const NetworkInterface& iface);
429 
438  virtual PDU* recv_response(PacketSender& sender, const NetworkInterface& iface);
439 
450  virtual bool matches_response(const uint8_t* ptr, uint32_t total_sz) const;
451 
460  virtual bool matches_flag(PDUType flag) const {
461  return flag == pdu_type();
462  }
463 
469  virtual PDUType pdu_type() const = 0;
470 protected:
474  PDU(const PDU& other);
475 
479  PDU& operator=(const PDU& other);
480 
485  void copy_inner_pdu(const PDU& pdu);
486 
498  virtual void prepare_for_serialize();
499 
506  void serialize(uint8_t* buffer, uint32_t total_sz);
507 
516  virtual void write_serialization(uint8_t* buffer, uint32_t total_sz) = 0;
517 private:
518  void parent_pdu(PDU* parent);
519 
520  PDU* inner_pdu_;
521  PDU* parent_pdu_;
522 };
523 
542 template<typename T>
543 T& operator/= (T& lop, const PDU& rop) {
544  PDU* last = &lop;
545  while (last->inner_pdu()) {
546  last = last->inner_pdu();
547  }
548  last->inner_pdu(rop.clone());
549  return lop;
550 }
551 
557 template<typename T>
558 T operator/ (T lop, const PDU& rop) {
559  lop /= rop;
560  return lop;
561 }
562 
568 template<typename T>
569 T* operator/= (T* lop, const PDU& rop) {
570  *lop /= rop;
571  return lop;
572 }
573 
574 namespace Internals {
575  template<typename T>
576  struct remove_pointer {
577  typedef T type;
578  };
579 
580  template<typename T>
581  struct remove_pointer<T*> {
582  typedef T type;
583  };
584 }
585 
586 template<typename T, typename U>
587 T tins_cast(U* pdu) {
588  typedef typename Internals::remove_pointer<T>::type TrueT;
589  return pdu && (TrueT::pdu_flag == pdu->pdu_type()) ?
590  static_cast<T>(pdu) : 0;
591 }
592 
593 template<typename T, typename U>
594 T& tins_cast(U& pdu) {
595  T* ptr = tins_cast<T*>(&pdu);
596  if (!ptr) {
597  throw bad_tins_cast();
598  }
599  return* ptr;
600 }
601 
602 } // Tins
603 
604 #endif // TINS_PDU_H
PDUType next_pdu_type
Definition: pdu.h:219
virtual bool matches_flag(PDUType flag) const
Check whether this PDU matches the specified flag.
Definition: pdu.h:460
uint32_t header_size
Definition: pdu.h:209
Class that represents an ICMP PDU.
Definition: icmp.h:65
Represents a TCP PDU.
Definition: tcp.h:76
Exception thrown when a PDU is not found when using PDU::rfind_pdu.
Definition: exceptions.h:80
const T & rfind_pdu(PDUType type=T::pdu_flag) const
Finds and returns the first PDU that matches the given flag.
Definition: pdu.h:397
Class that represents an IP PDU.
Definition: ip.h:63
Represents a Linux cooked-mode capture (SLL) PDU.
Definition: sll.h:45
std::vector< uint8_t > byte_array
Definition: pdu.h:45
Represents an MPLS PDU.
Definition: mpls.h:46
Represents a DNS PDU.
Definition: dns.h:85
PDUType
Enum which identifies each type of PDU.
Definition: pdu.h:127
const T * find_pdu(PDUType type=T::pdu_flag) const
Finds and returns the first PDU that matches the given flag.
Definition: pdu.h:369
T * find_pdu(PDUType type=T::pdu_flag)
Finds and returns the first PDU that matches the given flag.
Definition: pdu.h:352
Sends packets through a network interface.
Definition: packet_sender.h:116
virtual uint32_t trailer_size() const
Trailer's size.
Definition: pdu.h:272
PDU & operator=(PDU &&rhs) TINS_NOEXCEPT
Move assignment operator.
Definition: pdu.h:246
Represents an ARP PDU.
Definition: arp.h:50
Represents an ICMPv6 PDU.
Definition: icmpv6.h:57
AddressRange< HWAddress< n > > operator/(const HWAddress< n > &addr, int mask)
Constructs an AddressRange from a base address and a mask.
Definition: address_range.h:304
PDU * parent_pdu() const
Definition: pdu.h:294
Definition: pdu.h:576
Represents a DHCPv6 PDU.
Definition: dhcpv6.h:52
Definition: ipv6.h:54
Represents a Spanning Tree Protocol PDU.
Definition: stp.h:44
Represents an UDP PDU.
Definition: udp.h:63
Class representing an IEEE 802.3 PDU.
Definition: dot3.h:46
Representing a LLC frame.
Definition: llc.h:47
Type used to store a PDU header's data.
Definition: pdu.h:194
Class that represents the RC4 EAPOL PDU.
Definition: eapol.h:198
Class that represents the RSN EAPOL PDU.
Definition: eapol.h:397
Abstraction of a network interface.
Definition: network_interface.h:47
T & operator/=(T &lop, const PDU &rop)
Concatenation operator.
Definition: pdu.h:543
PDU * inner_pdu() const
Getter for the inner PDU.
Definition: pdu.h:286
Represents the DHCP PDU.
Definition: dhcp.h:67
Represents the EAP encapsulation over LAN.
Definition: eapol.h:56
Represents a SNAP frame.
Definition: snap.h:48
virtual PDU * clone() const =0
Clones this packet.
PDU(PDU &&rhs) TINS_NOEXCEPT
Move constructor.
Definition: pdu.h:233
byte_array serialization_type
Definition: pdu.h:112
T & rfind_pdu(PDUType type=T::pdu_flag)
Finds and returns the first PDU that matches the given flag.
Definition: pdu.h:383
Base class for protocol data units.
Definition: pdu.h:107
PDUType current_pdu_type
Definition: pdu.h:214
endian_type
Definition: pdu.h:117