libtins  4.0
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:
112  typedef byte_array serialization_type;
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  delete inner_pdu_;
248  inner_pdu_ = 0;
249  std::swap(inner_pdu_, rhs.inner_pdu_);
250  if (inner_pdu_) {
251  inner_pdu_->parent_pdu(this);
252  }
253  return* this;
254  }
255  #endif
256 
263  virtual ~PDU();
264 
267  virtual uint32_t header_size() const = 0;
268 
273  virtual uint32_t trailer_size() const {
274  return 0;
275  }
276 
281  uint32_t size() const;
282 
287  PDU* inner_pdu() const {
288  return inner_pdu_;
289  }
290 
295  PDU* parent_pdu() const {
296  return parent_pdu_;
297  }
298 
312  PDU* release_inner_pdu();
313 
322  void inner_pdu(PDU* next_pdu);
323 
331  void inner_pdu(const PDU& next_pdu);
332 
342  serialization_type serialize();
343 
352  template<typename T>
353  T* find_pdu(PDUType type = T::pdu_flag) {
354  PDU* pdu = this;
355  while (pdu) {
356  if (pdu->matches_flag(type)) {
357  return static_cast<T*>(pdu);
358  }
359  pdu = pdu->inner_pdu();
360  }
361  return 0;
362  }
363 
369  template<typename T>
370  const T* find_pdu(PDUType type = T::pdu_flag) const {
371  return const_cast<PDU*>(this)->find_pdu<T>(type);
372  }
373 
383  template<typename T>
384  T& rfind_pdu(PDUType type = T::pdu_flag) {
385  T* ptr = find_pdu<T>(type);
386  if (!ptr) {
387  throw pdu_not_found();
388  }
389  return* ptr;
390  }
391 
397  template<typename T>
398  const T& rfind_pdu(PDUType type = T::pdu_flag) const {
399  return const_cast<PDU*>(this)->rfind_pdu<T>(type);
400  }
401 
410  virtual PDU* clone() const = 0;
411 
429  virtual void send(PacketSender& sender, const NetworkInterface& iface);
430 
439  virtual PDU* recv_response(PacketSender& sender, const NetworkInterface& iface);
440 
451  virtual bool matches_response(const uint8_t* ptr, uint32_t total_sz) const;
452 
461  virtual bool matches_flag(PDUType flag) const {
462  return flag == pdu_type();
463  }
464 
470  virtual PDUType pdu_type() const = 0;
471 protected:
475  PDU(const PDU& other);
476 
480  PDU& operator=(const PDU& other);
481 
486  void copy_inner_pdu(const PDU& pdu);
487 
499  virtual void prepare_for_serialize();
500 
507  void serialize(uint8_t* buffer, uint32_t total_sz);
508 
517  virtual void write_serialization(uint8_t* buffer, uint32_t total_sz) = 0;
518 private:
519  void parent_pdu(PDU* parent);
520 
521  PDU* inner_pdu_;
522  PDU* parent_pdu_;
523 };
524 
543 template<typename T>
544 T& operator/= (T& lop, const PDU& rop) {
545  PDU* last = &lop;
546  while (last->inner_pdu()) {
547  last = last->inner_pdu();
548  }
549  last->inner_pdu(rop.clone());
550  return lop;
551 }
552 
558 template<typename T>
559 T operator/ (T lop, const PDU& rop) {
560  lop /= rop;
561  return lop;
562 }
563 
569 template<typename T>
570 T* operator/= (T* lop, const PDU& rop) {
571  *lop /= rop;
572  return lop;
573 }
574 
575 namespace Internals {
576  template<typename T>
577  struct remove_pointer {
578  typedef T type;
579  };
580 
581  template<typename T>
582  struct remove_pointer<T*> {
583  typedef T type;
584  };
585 }
586 
587 template<typename T, typename U>
588 T tins_cast(U* pdu) {
589  typedef typename Internals::remove_pointer<T>::type TrueT;
590  return pdu && (TrueT::pdu_flag == pdu->pdu_type()) ?
591  static_cast<T>(pdu) : 0;
592 }
593 
594 template<typename T, typename U>
595 T& tins_cast(U& pdu) {
596  T* ptr = tins_cast<T*>(&pdu);
597  if (!ptr) {
598  throw bad_tins_cast();
599  }
600  return* ptr;
601 }
602 
603 } // Tins
604 
605 #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:461
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:398
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:370
T * find_pdu(PDUType type=T::pdu_flag)
Finds and returns the first PDU that matches the given flag.
Definition: pdu.h:353
Sends packets through a network interface.
Definition: packet_sender.h:116
virtual uint32_t trailer_size() const
Trailer&#39;s size.
Definition: pdu.h:273
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:295
Definition: pdu.h:577
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
The Tins namespace.
Definition: address_range.h:38
Representing a LLC frame.
Definition: llc.h:47
Type used to store a PDU header&#39;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:544
PDU * inner_pdu() const
Getter for the inner PDU.
Definition: pdu.h:287
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:384
Base class for protocol data units.
Definition: pdu.h:107
PDUType current_pdu_type
Definition: pdu.h:214
endian_type
Definition: pdu.h:117
Exception thrown when a call to tins_cast fails.
Definition: exceptions.h:175