libtins 4.4
Loading...
Searching...
No Matches
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
42namespace Tins {
43
44class PacketSender;
45class NetworkInterface;
46
50typedef std::vector<uint8_t> byte_array;
51
107class TINS_API PDU {
108public:
113
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;
479protected:
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;
526private:
527 void parent_pdu(PDU* parent);
528
529 PDU* inner_pdu_;
530 PDU* parent_pdu_;
531};
532
551template<typename T>
552T& 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
566template<typename T>
567T operator/ (T lop, const PDU& rop) {
568 lop /= rop;
569 return lop;
570}
571
577template<typename T>
578T* operator/= (T* lop, const PDU& rop) {
579 *lop /= rop;
580 return lop;
581}
582
583namespace Internals {
584 template<typename T>
586 typedef T type;
587 };
588
589 template<typename T>
590 struct remove_pointer<T*> {
591 typedef T type;
592 };
593}
594
595template<typename T, typename U>
596T 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
602template<typename T, typename U>
603T& 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
PDU(PDU &&rhs) TINS_NOEXCEPT
Move constructor.
Definition: pdu.h:235
virtual uint32_t header_size() const =0
The header's size.
virtual PDU * clone() const =0
Clones this packet.
byte_array serialization_type
Definition: pdu.h:112
virtual void write_serialization(uint8_t *buffer, uint32_t total_sz)=0
Serializes this TCP PDU.
PDUType
Enum which identifies each type of PDU.
Definition: pdu.h:127
PDU * parent_pdu() const
Definition: pdu.h:303
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
virtual uint32_t trailer_size() const
Trailer's size.
Definition: pdu.h:275
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
virtual PDUType pdu_type() const =0
Getter for the PDU's type.
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 * 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
PDU & operator=(PDU &&rhs) TINS_NOEXCEPT
Move assignment operator.
Definition: pdu.h:248
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:50
T & operator/=(T &lop, const PDU &rop)
Concatenation operator.
Definition: pdu.h:552
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
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