libtins  4.5
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;
45 class NetworkInterface;
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  DOT1AD,
174  DOT1Q,
175  PPPOE,
176  STP,
177  PPI,
178  IPSEC_AH,
179  IPSEC_ESP,
180  PKTAP,
181  MPLS,
182  DOT11_CONTROL_TA,
183  VXLAN,
184  UNKNOWN = 999,
185  USER_DEFINED_PDU = 1000
186  };
187 
192  static const endian_type endianness = BE;
193 
197  struct metadata {
201  metadata();
202 
207  metadata(uint32_t header_size, PDUType current_type, PDUType next_type);
208 
212  uint32_t header_size;
213 
218 
223  };
224 
228  PDU();
229 
230  #if TINS_IS_CXX11
236  PDU(PDU &&rhs) TINS_NOEXCEPT
237  : inner_pdu_(0), parent_pdu_(0) {
238  std::swap(inner_pdu_, rhs.inner_pdu_);
239  if (inner_pdu_) {
240  inner_pdu_->parent_pdu(this);
241  }
242  }
243 
249  PDU& operator=(PDU &&rhs) TINS_NOEXCEPT {
250  delete inner_pdu_;
251  inner_pdu_ = 0;
252  std::swap(inner_pdu_, rhs.inner_pdu_);
253  if (inner_pdu_) {
254  inner_pdu_->parent_pdu(this);
255  }
256  return* this;
257  }
258  #endif
259 
266  virtual ~PDU();
267 
270  virtual uint32_t header_size() const = 0;
271 
276  virtual uint32_t trailer_size() const {
277  return 0;
278  }
279 
284  uint32_t size() const;
285 
290  virtual uint32_t advertised_size() const;
291 
296  PDU* inner_pdu() const {
297  return inner_pdu_;
298  }
299 
304  PDU* parent_pdu() const {
305  return parent_pdu_;
306  }
307 
321  PDU* release_inner_pdu();
322 
331  void inner_pdu(PDU* next_pdu);
332 
340  void inner_pdu(const PDU& next_pdu);
341 
351  serialization_type serialize();
352 
361  template<typename T>
362  T* find_pdu(PDUType type = T::pdu_flag) {
363  PDU* pdu = this;
364  while (pdu) {
365  if (pdu->matches_flag(type)) {
366  return static_cast<T*>(pdu);
367  }
368  pdu = pdu->inner_pdu();
369  }
370  return 0;
371  }
372 
378  template<typename T>
379  const T* find_pdu(PDUType type = T::pdu_flag) const {
380  return const_cast<PDU*>(this)->find_pdu<T>(type);
381  }
382 
392  template<typename T>
393  T& rfind_pdu(PDUType type = T::pdu_flag) {
394  T* ptr = find_pdu<T>(type);
395  if (!ptr) {
396  throw pdu_not_found();
397  }
398  return* ptr;
399  }
400 
406  template<typename T>
407  const T& rfind_pdu(PDUType type = T::pdu_flag) const {
408  return const_cast<PDU*>(this)->rfind_pdu<T>(type);
409  }
410 
419  virtual PDU* clone() const = 0;
420 
438  virtual void send(PacketSender& sender, const NetworkInterface& iface);
439 
448  virtual PDU* recv_response(PacketSender& sender, const NetworkInterface& iface);
449 
460  virtual bool matches_response(const uint8_t* ptr, uint32_t total_sz) const;
461 
470  virtual bool matches_flag(PDUType flag) const {
471  return flag == pdu_type();
472  }
473 
479  virtual PDUType pdu_type() const = 0;
480 protected:
484  PDU(const PDU& other);
485 
489  PDU& operator=(const PDU& other);
490 
495  void copy_inner_pdu(const PDU& pdu);
496 
508  virtual void prepare_for_serialize();
509 
516  void serialize(uint8_t* buffer, uint32_t total_sz);
517 
526  virtual void write_serialization(uint8_t* buffer, uint32_t total_sz) = 0;
527 private:
528  void parent_pdu(PDU* parent);
529 
530  PDU* inner_pdu_;
531  PDU* parent_pdu_;
532 };
533 
552 template<typename T>
553 T& operator/= (T& lop, const PDU& rop) {
554  PDU* last = &lop;
555  while (last->inner_pdu()) {
556  last = last->inner_pdu();
557  }
558  last->inner_pdu(rop.clone());
559  return lop;
560 }
561 
567 template<typename T>
568 T operator/ (T lop, const PDU& rop) {
569  lop /= rop;
570  return lop;
571 }
572 
578 template<typename T>
579 T* operator/= (T* lop, const PDU& rop) {
580  *lop /= rop;
581  return lop;
582 }
583 
584 namespace Internals {
585  template<typename T>
586  struct remove_pointer {
587  typedef T type;
588  };
589 
590  template<typename T>
591  struct remove_pointer<T*> {
592  typedef T type;
593  };
594 }
595 
596 template<typename T, typename U>
597 T tins_cast(U* pdu) {
598  typedef typename Internals::remove_pointer<T>::type TrueT;
599  return pdu && (TrueT::pdu_flag == pdu->pdu_type()) ?
600  static_cast<T>(pdu) : 0;
601 }
602 
603 template<typename T, typename U>
604 T& tins_cast(U& pdu) {
605  T* ptr = tins_cast<T*>(&pdu);
606  if (!ptr) {
607  throw bad_tins_cast();
608  }
609  return* ptr;
610 }
611 
612 } // Tins
613 
614 #endif // TINS_PDU_H
Represents an ARP PDU.
Definition: arp.h:50
Represents the DHCP PDU.
Definition: dhcp.h:67
Represents a DHCPv6 PDU.
Definition: dhcpv6.h:52
Represents a DNS PDU.
Definition: dns.h:85
Class representing an IEEE 802.3 PDU.
Definition: dot3.h:46
Represents the EAP encapsulation over LAN.
Definition: eapol.h:56
Class that represents an ICMP PDU.
Definition: icmp.h:65
Represents an ICMPv6 PDU.
Definition: icmpv6.h:58
Class that represents an IP PDU.
Definition: ip.h:63
Definition: ipv6.h:54
Representing a LLC frame.
Definition: llc.h:47
Represents an MPLS PDU.
Definition: mpls.h:46
Abstraction of a network interface.
Definition: network_interface.h:47
Base class for protocol data units.
Definition: pdu.h:107
endian_type
Definition: pdu.h:117
const T & rfind_pdu(PDUType type=T::pdu_flag) const
Finds and returns the first PDU that matches the given flag.
Definition: pdu.h:407
PDU * parent_pdu() const
Definition: pdu.h:304
PDU(PDU &&rhs) TINS_NOEXCEPT
Move constructor.
Definition: pdu.h:236
virtual uint32_t header_size() const =0
The header's size.
const T * find_pdu(PDUType type=T::pdu_flag) const
Finds and returns the first PDU that matches the given flag.
Definition: pdu.h:379
byte_array serialization_type
Definition: pdu.h:112
virtual void write_serialization(uint8_t *buffer, uint32_t total_sz)=0
Serializes this TCP PDU.
PDU & operator=(PDU &&rhs) TINS_NOEXCEPT
Move assignment operator.
Definition: pdu.h:249
PDUType
Enum which identifies each type of PDU.
Definition: pdu.h:127
virtual uint32_t trailer_size() const
Trailer's size.
Definition: pdu.h:276
virtual PDU * clone() const =0
Clones this packet.
virtual PDUType pdu_type() const =0
Getter for the PDU's type.
T * find_pdu(PDUType type=T::pdu_flag)
Finds and returns the first PDU that matches the given flag.
Definition: pdu.h:362
T & rfind_pdu(PDUType type=T::pdu_flag)
Finds and returns the first PDU that matches the given flag.
Definition: pdu.h:393
PDU * inner_pdu() const
Getter for the inner PDU.
Definition: pdu.h:296
virtual bool matches_flag(PDUType flag) const
Check whether this PDU matches the specified flag.
Definition: pdu.h:470
Sends packets through a network interface.
Definition: packet_sender.h:118
Class that represents the RC4 EAPOL PDU.
Definition: eapol.h:198
Class that represents the RSN EAPOL PDU.
Definition: eapol.h:397
Represents a Linux cooked-mode capture (SLL) PDU.
Definition: sll.h:45
Represents a SNAP frame.
Definition: snap.h:48
Represents a Spanning Tree Protocol PDU.
Definition: stp.h:44
Represents a TCP PDU.
Definition: tcp.h:76
Represents an UDP PDU.
Definition: udp.h:63
Represents a VXLAN PDU.
Definition: vxlan.h:17
Exception thrown when a PDU is not found when using PDU::rfind_pdu.
Definition: exceptions.h:98
The Tins namespace.
Definition: address_range.h:38
std::vector< uint8_t > byte_array
Definition: pdu.h:45
AddressRange< HWAddress< n > > operator/(const HWAddress< n > &addr, int mask)
Constructs an AddressRange from a base address and a mask.
Definition: address_range.h:308
T & operator/=(T &lop, const PDU &rop)
Concatenation operator.
Definition: pdu.h:553
Definition: pdu.h:586
Type used to store a PDU header's data.
Definition: pdu.h:197
PDUType current_pdu_type
Definition: pdu.h:217
uint32_t header_size
Definition: pdu.h:212
PDUType next_pdu_type
Definition: pdu.h:222