/src/PcapPlusPlus/Packet++/header/Layer.h
Line | Count | Source (jump to first uncovered line) |
1 | | #pragma once |
2 | | |
3 | | #include <stdint.h> |
4 | | #include <stdio.h> |
5 | | #include "ProtocolType.h" |
6 | | #include <string> |
7 | | |
8 | | /// @file |
9 | | |
10 | | /** |
11 | | * \namespace pcpp |
12 | | * \brief The main namespace for the PcapPlusPlus lib |
13 | | */ |
14 | | namespace pcpp |
15 | | { |
16 | | |
17 | | /** |
18 | | * @class IDataContainer |
19 | | * An interface (virtual abstract class) that indicates an object that holds a pointer to a buffer data. The Layer class is an example |
20 | | * of such object, hence it inherits this interface |
21 | | */ |
22 | | class IDataContainer |
23 | | { |
24 | | public: |
25 | | /** |
26 | | * Get a pointer to the data |
27 | | * @param[in] offset Get a pointer in a certain offset. Default is 0 - get a pointer to start of data |
28 | | * @return A pointer to the data |
29 | | */ |
30 | | virtual uint8_t* getDataPtr(size_t offset = 0) const = 0; |
31 | | |
32 | 4.50M | virtual ~IDataContainer() {} |
33 | | }; |
34 | | |
35 | | class Packet; |
36 | | |
37 | | /** |
38 | | * @class Layer |
39 | | * Layer is the base class for all protocol layers. Each protocol supported in PcapPlusPlus has a class that inherits Layer. |
40 | | * The protocol layer class expose all properties and methods relevant for viewing and editing protocol fields. |
41 | | * For example: a pointer to a structured header (e.g tcphdr, iphdr, etc.), protocol header size, payload size, compute |
42 | | * fields that can be automatically computed, print protocol data to string, etc. |
43 | | * Each protocol instance is obviously part of a protocol stack (which construct a packet). This protocol stack is represented |
44 | | * in PcapPlusPlus in a linked list, and each layer is an element in this list. That's why each layer has properties to the next and previous |
45 | | * layer in the protocol stack |
46 | | * The Layer class, as a base class, is abstract and the user can't create an instance of it (it has a private constructor) |
47 | | * Each layer holds a pointer to the relevant place in the packet. The layer sees all the data from this pointer forward until the |
48 | | * end of the packet. Here is an example packet showing this concept: |
49 | | * |
50 | | @verbatim |
51 | | ==================================================== |
52 | | |Eth |IPv4 |TCP |Packet | |
53 | | |Header |Header |Header |Payload | |
54 | | ==================================================== |
55 | | |
56 | | |--------------------------------------------------| |
57 | | EthLayer data |
58 | | |---------------------------------------| |
59 | | IPv4Layer data |
60 | | |---------------------------| |
61 | | TcpLayer data |
62 | | |----------------| |
63 | | PayloadLayer data |
64 | | @endverbatim |
65 | | * |
66 | | */ |
67 | | class Layer : public IDataContainer |
68 | | { |
69 | | friend class Packet; |
70 | | public: |
71 | | /** |
72 | | * A destructor for this class. Frees the data if it was allocated by the layer constructor (see isAllocatedToPacket() for more info) |
73 | | */ |
74 | | virtual ~Layer(); |
75 | | |
76 | | /** |
77 | | * @return A pointer to the next layer in the protocol stack or NULL if the layer is the last one |
78 | | */ |
79 | 82.6M | Layer* getNextLayer() const { return m_NextLayer; } |
80 | | |
81 | | /** |
82 | | * @return A pointer to the previous layer in the protocol stack or NULL if the layer is the first one |
83 | | */ |
84 | 2.32M | Layer* getPrevLayer() const { return m_PrevLayer; } |
85 | | |
86 | | /** |
87 | | * @return The protocol enum |
88 | | */ |
89 | 61.9M | ProtocolType getProtocol() const { return m_Protocol; } |
90 | | |
91 | | /** |
92 | | * Check if the layer's protocol matches a protocol family |
93 | | * @param protocolTypeFamily The protocol family to check |
94 | | * @return True if the layer's protocol matches the protocol family, false otherwise |
95 | | */ |
96 | | bool isMemberOfProtocolFamily(ProtocolTypeFamily protocolTypeFamily) const; |
97 | | |
98 | | /** |
99 | | * @return A pointer to the layer raw data. In most cases it'll be a pointer to the first byte of the header |
100 | | */ |
101 | 285k | uint8_t* getData() const { return m_Data; } |
102 | | |
103 | | /** |
104 | | * @return The length in bytes of the data from the first byte of the header until the end of the packet |
105 | | */ |
106 | 2.08M | size_t getDataLen() const { return m_DataLen; } |
107 | | |
108 | | /** |
109 | | * @return A pointer for the layer payload, meaning the first byte after the header |
110 | | */ |
111 | 0 | uint8_t* getLayerPayload() const { return m_Data + getHeaderLen(); } |
112 | | |
113 | | /** |
114 | | * @return The size in bytes of the payload |
115 | | */ |
116 | 51.0k | size_t getLayerPayloadSize() const { return m_DataLen - getHeaderLen(); } |
117 | | |
118 | | /** |
119 | | * Raw data in layers can come from one of sources: |
120 | | * 1. from an existing packet - this is the case when parsing packets received from files or the network. In this case the data was |
121 | | * already allocated by someone else, and layer only holds the pointer to the relevant place inside this data |
122 | | * 2. when creating packets, data is allocated when layer is created. In this case the layer is responsible for freeing it as well |
123 | | * |
124 | | * @return Returns true if the data was allocated by an external source (a packet) or false if it was allocated by the layer itself |
125 | | */ |
126 | 4.50M | bool isAllocatedToPacket() const { return m_Packet != NULL; } |
127 | | |
128 | | /** |
129 | | * Copy the raw data of this layer to another array |
130 | | * @param[out] toArr The destination byte array |
131 | | */ |
132 | | void copyData(uint8_t* toArr) const; |
133 | | |
134 | | // implement abstract methods |
135 | | |
136 | 117k | uint8_t* getDataPtr(size_t offset = 0) const { return (uint8_t*)(m_Data + offset); } |
137 | | |
138 | | |
139 | | // abstract methods |
140 | | |
141 | | /** |
142 | | * Each layer is responsible for parsing the next layer |
143 | | */ |
144 | | virtual void parseNextLayer() = 0; |
145 | | |
146 | | /** |
147 | | * @return The header length in bytes |
148 | | */ |
149 | | virtual size_t getHeaderLen() const = 0; |
150 | | |
151 | | /** |
152 | | * Each layer can compute field values automatically using this method. This is an abstract method |
153 | | */ |
154 | | virtual void computeCalculateFields() = 0; |
155 | | |
156 | | /** |
157 | | * @return A string representation of the layer most important data (should look like the layer description in Wireshark) |
158 | | */ |
159 | | virtual std::string toString() const = 0; |
160 | | |
161 | | /** |
162 | | * @return The OSI Model layer this protocol belongs to |
163 | | */ |
164 | | virtual OsiModelLayer getOsiModelLayer() const = 0; |
165 | | |
166 | | protected: |
167 | | uint8_t* m_Data; |
168 | | size_t m_DataLen; |
169 | | Packet* m_Packet; |
170 | | ProtocolType m_Protocol; |
171 | | Layer* m_NextLayer; |
172 | | Layer* m_PrevLayer; |
173 | | bool m_IsAllocatedInPacket; |
174 | | |
175 | 0 | Layer() : m_Data(NULL), m_DataLen(0), m_Packet(NULL), m_Protocol(UnknownProtocol), m_NextLayer(NULL), m_PrevLayer(NULL), m_IsAllocatedInPacket(false) { } |
176 | | |
177 | | Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : |
178 | | m_Data(data), m_DataLen(dataLen), |
179 | | m_Packet(packet), m_Protocol(UnknownProtocol), |
180 | 4.34M | m_NextLayer(NULL), m_PrevLayer(prevLayer), m_IsAllocatedInPacket(false) {} |
181 | | |
182 | | // Copy c'tor |
183 | | Layer(const Layer& other); |
184 | | Layer& operator=(const Layer& other); |
185 | | |
186 | 23.7k | void setNextLayer(Layer* nextLayer) { m_NextLayer = nextLayer; } |
187 | 0 | void setPrevLayer(Layer* prevLayer) { m_PrevLayer = prevLayer; } |
188 | | |
189 | | virtual bool extendLayer(int offsetInLayer, size_t numOfBytesToExtend); |
190 | | virtual bool shortenLayer(int offsetInLayer, size_t numOfBytesToShorten); |
191 | | }; |
192 | | |
193 | | } // namespace pcpp |
194 | | |
195 | | inline std::ostream& operator<<(std::ostream& os, const pcpp::Layer &layer) |
196 | 0 | { |
197 | 0 | os << layer.toString(); |
198 | 0 | return os; |
199 | 0 | } |