libtins  4.4
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  UNKNOWN = 999,
184  USER_DEFINED_PDU = 1000
185  };
186 
191  static const endian_type endianness = BE;
192 
196  struct metadata {
200  metadata();
201 
206  metadata(uint32_t header_size, PDUType current_type, PDUType next_type);
207 
211  uint32_t header_size;
212 
217 
222  };
223 
227  PDU();
228 
229  #if TINS_IS_CXX11
235  PDU(PDU &&rhs) TINS_NOEXCEPT
236  : inner_pdu_(0), parent_pdu_(0) {
237  std::swap(inner_pdu_, rhs.inner_pdu_);
238  if (inner_pdu_) {
239  inner_pdu_->parent_pdu(this);
240  }
241  }
242 
248  PDU& operator=(PDU &&rhs) TINS_NOEXCEPT {
249  delete inner_pdu_;
250  inner_pdu_ = 0;
251  std::swap(inner_pdu_, rhs.inner_pdu_);
252  if (inner_pdu_) {
253  inner_pdu_->parent_pdu(this);
254  }
255  return* this;
256  }
257  #endif
258 
265  virtual ~PDU();
266 
269  virtual uint32_t header_size() const = 0;
270 
275  virtual uint32_t trailer_size() const {
276  return 0;
277  }
278 
283  uint32_t size() const;
284 
289  virtual uint32_t advertised_size() const;
290 
295  PDU* inner_pdu() const {
296  return inner_pdu_;
297  }
298 
303  PDU* parent_pdu() const {
304  return parent_pdu_;
305  }
306 
320  PDU* release_inner_pdu();
321 
330  void inner_pdu(PDU* next_pdu);
331 
339  void inner_pdu(const PDU& next_pdu);
340 
350  serialization_type serialize();
351 
360  template<typename T>
361  T* find_pdu(PDUType type = T::pdu_flag) {
362  PDU* pdu = this;
363  while (pdu) {
364  if (pdu->matches_flag(type)) {
365  return static_cast<T*>(pdu);
366  }
367  pdu = pdu->inner_pdu();
368  }
369  return 0;
370  }
371 
377  template<typename T>
378  const T* find_pdu(PDUType type = T::pdu_flag) const {
379  return const_cast<PDU*>(this)->find_pdu<T>(type);
380  }
381 
391  template<typename T>
392  T& rfind_pdu(PDUType type = T::pdu_flag) {
393  T* ptr = find_pdu<T>(type);
394  if (!ptr) {
395  throw pdu_not_found();
396  }
397  return* ptr;
398  }
399 
405  template<typename T>
406  const T& rfind_pdu(PDUType type = T::pdu_flag) const {
407  return const_cast<PDU*>(this)->rfind_pdu<T>(type);
408  }
409 
418  virtual PDU* clone() const = 0;
419 
437  virtual void send(PacketSender& sender, const NetworkInterface& iface);
438 
447  virtual PDU* recv_response(PacketSender& sender, const NetworkInterface& iface);
448 
459  virtual bool matches_response(const uint8_t* ptr, uint32_t total_sz) const;
460 
469  virtual bool matches_flag(PDUType flag) const {
470  return flag == pdu_type();
471  }
472 
478  virtual PDUType pdu_type() const = 0;
479 protected:
483  PDU(const PDU& other);
484 
488  PDU& operator=(const PDU& other);
489 
494  void copy_inner_pdu(const PDU& pdu);
495 
507  virtual void prepare_for_serialize();
508 
515  void serialize(uint8_t* buffer, uint32_t total_sz);
516 
525  virtual void write_serialization(uint8_t* buffer, uint32_t total_sz) = 0;
526 private:
527  void parent_pdu(PDU* parent);
528 
529  PDU* inner_pdu_;
530  PDU* parent_pdu_;
531 };
532 
551 template<typename T>
552 T& operator/= (T& lop, const PDU& rop) {
553  PDU* last = &lop;
554  while (last->inner_pdu()) {
555  last = last->inner_pdu();
556  }
557  last->inner_pdu(rop.clone());
558  return lop;
559 }
560 
566 template<typename T>
567 T operator/ (T lop, const PDU& rop) {
568  lop /= rop;
569  return lop;
570 }
571 
577 template<typename T>
578 T* operator/= (T* lop, const PDU& rop) {
579  *lop /= rop;
580  return lop;
581 }
582 
583 namespace Internals {
584  template<typename T>
585  struct remove_pointer {
586  typedef T type;
587  };
588 
589  template<typename T>
590  struct remove_pointer<T*> {
591  typedef T type;
592  };
593 }
594 
595 template<typename T, typename U>
596 T tins_cast(U* pdu) {
597  typedef typename Internals::remove_pointer<T>::type TrueT;
598  return pdu && (TrueT::pdu_flag == pdu->pdu_type()) ?
599  static_cast<T>(pdu) : 0;
600 }
601 
602 template<typename T, typename U>
603 T& tins_cast(U& pdu) {
604  T* ptr = tins_cast<T*>(&pdu);
605  if (!ptr) {
606  throw bad_tins_cast();
607  }
608  return* ptr;
609 }
610 
611 } // Tins
612 
613 #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:57
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:406
PDU * parent_pdu() const
Definition: pdu.h:303
PDU(PDU &&rhs) TINS_NOEXCEPT
Move constructor.
Definition: pdu.h:235
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:378
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:248
PDUType
Enum which identifies each type of PDU.
Definition: pdu.h:127
virtual uint32_t trailer_size() const
Trailer's size.
Definition: pdu.h:275
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:361
T & rfind_pdu(PDUType type=T::pdu_flag)
Finds and returns the first PDU that matches the given flag.
Definition: pdu.h:392
PDU * inner_pdu() const
Getter for the inner PDU.
Definition: pdu.h:295
virtual bool matches_flag(PDUType flag) const
Check whether this PDU matches the specified flag.
Definition: pdu.h:469
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
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:304
T & operator/=(T &lop, const PDU &rop)
Concatenation operator.
Definition: pdu.h:552
Definition: pdu.h:585
Type used to store a PDU header's data.
Definition: pdu.h:196
PDUType current_pdu_type
Definition: pdu.h:216
uint32_t header_size
Definition: pdu.h:211
PDUType next_pdu_type
Definition: pdu.h:221