libtins  4.6
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  RTP,
185  UNKNOWN = 999,
186  USER_DEFINED_PDU = 1000
187  };
188 
193  static const endian_type endianness = BE;
194 
198  struct metadata {
202  metadata();
203 
208  metadata(uint32_t header_size, PDUType current_type, PDUType next_type);
209 
213  uint32_t header_size;
214 
219 
224  };
225 
229  PDU();
230 
231  #if TINS_IS_CXX11
237  PDU(PDU &&rhs) TINS_NOEXCEPT
238  : inner_pdu_(0), parent_pdu_(0) {
239  std::swap(inner_pdu_, rhs.inner_pdu_);
240  if (inner_pdu_) {
241  inner_pdu_->parent_pdu(this);
242  }
243  }
244 
250  PDU& operator=(PDU &&rhs) TINS_NOEXCEPT {
251  delete inner_pdu_;
252  inner_pdu_ = 0;
253  std::swap(inner_pdu_, rhs.inner_pdu_);
254  if (inner_pdu_) {
255  inner_pdu_->parent_pdu(this);
256  }
257  return* this;
258  }
259  #endif
260 
267  virtual ~PDU();
268 
271  virtual uint32_t header_size() const = 0;
272 
277  virtual uint32_t trailer_size() const {
278  return 0;
279  }
280 
285  uint32_t size() const;
286 
291  virtual uint32_t advertised_size() const;
292 
297  PDU* inner_pdu() const {
298  return inner_pdu_;
299  }
300 
305  PDU* parent_pdu() const {
306  return parent_pdu_;
307  }
308 
322  PDU* release_inner_pdu();
323 
332  void inner_pdu(PDU* next_pdu);
333 
341  void inner_pdu(const PDU& next_pdu);
342 
352  serialization_type serialize();
353 
362  template<typename T>
363  T* find_pdu(PDUType type = T::pdu_flag) {
364  PDU* pdu = this;
365  while (pdu) {
366  if (pdu->matches_flag(type)) {
367  return static_cast<T*>(pdu);
368  }
369  pdu = pdu->inner_pdu();
370  }
371  return 0;
372  }
373 
379  template<typename T>
380  const T* find_pdu(PDUType type = T::pdu_flag) const {
381  return const_cast<PDU*>(this)->find_pdu<T>(type);
382  }
383 
393  template<typename T>
394  T& rfind_pdu(PDUType type = T::pdu_flag) {
395  T* ptr = find_pdu<T>(type);
396  if (!ptr) {
397  throw pdu_not_found();
398  }
399  return* ptr;
400  }
401 
407  template<typename T>
408  const T& rfind_pdu(PDUType type = T::pdu_flag) const {
409  return const_cast<PDU*>(this)->rfind_pdu<T>(type);
410  }
411 
420  virtual PDU* clone() const = 0;
421 
439  virtual void send(PacketSender& sender, const NetworkInterface& iface);
440 
449  virtual PDU* recv_response(PacketSender& sender, const NetworkInterface& iface);
450 
461  virtual bool matches_response(const uint8_t* ptr, uint32_t total_sz) const;
462 
471  virtual bool matches_flag(PDUType flag) const {
472  return flag == pdu_type();
473  }
474 
480  virtual PDUType pdu_type() const = 0;
481 protected:
485  PDU(const PDU& other);
486 
490  PDU& operator=(const PDU& other);
491 
496  void copy_inner_pdu(const PDU& pdu);
497 
509  virtual void prepare_for_serialize();
510 
517  void serialize(uint8_t* buffer, uint32_t total_sz);
518 
527  virtual void write_serialization(uint8_t* buffer, uint32_t total_sz) = 0;
528 private:
529  void parent_pdu(PDU* parent);
530 
531  PDU* inner_pdu_;
532  PDU* parent_pdu_;
533 };
534 
553 template<typename T>
554 T& operator/= (T& lop, const PDU& rop) {
555  PDU* last = &lop;
556  while (last->inner_pdu()) {
557  last = last->inner_pdu();
558  }
559  last->inner_pdu(rop.clone());
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 
579 template<typename T>
580 T* operator/= (T* lop, const PDU& rop) {
581  *lop /= rop;
582  return lop;
583 }
584 
585 namespace Internals {
586  template<typename T>
587  struct remove_pointer {
588  typedef T type;
589  };
590 
591  template<typename T>
592  struct remove_pointer<T*> {
593  typedef T type;
594  };
595 }
596 
597 template<typename T, typename U>
598 T tins_cast(U* pdu) {
599  typedef typename Internals::remove_pointer<T>::type TrueT;
600  return pdu && (TrueT::pdu_flag == pdu->pdu_type()) ?
601  static_cast<T>(pdu) : 0;
602 }
603 
604 template<typename T, typename U>
605 T& tins_cast(U& pdu) {
606  T* ptr = tins_cast<T*>(&pdu);
607  if (!ptr) {
608  throw bad_tins_cast();
609  }
610  return* ptr;
611 }
612 
613 } // Tins
614 
615 #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:408
PDU * parent_pdu() const
Definition: pdu.h:305
PDU(PDU &&rhs) TINS_NOEXCEPT
Move constructor.
Definition: pdu.h:237
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:380
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:250
PDUType
Enum which identifies each type of PDU.
Definition: pdu.h:127
virtual uint32_t trailer_size() const
Trailer's size.
Definition: pdu.h:277
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:363
T & rfind_pdu(PDUType type=T::pdu_flag)
Finds and returns the first PDU that matches the given flag.
Definition: pdu.h:394
PDU * inner_pdu() const
Getter for the inner PDU.
Definition: pdu.h:297
virtual bool matches_flag(PDUType flag) const
Check whether this PDU matches the specified flag.
Definition: pdu.h:471
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 RTP PDU.
Definition: rtp.h:19
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:554
Definition: pdu.h:587
Type used to store a PDU header's data.
Definition: pdu.h:198
PDUType current_pdu_type
Definition: pdu.h:218
uint32_t header_size
Definition: pdu.h:213
PDUType next_pdu_type
Definition: pdu.h:223