/src/PcapPlusPlus/Packet++/header/ArpLayer.h
Line | Count | Source (jump to first uncovered line) |
1 | | #pragma once |
2 | | |
3 | | #include "Layer.h" |
4 | | #include "IpAddress.h" |
5 | | #include "MacAddress.h" |
6 | | #include "DeprecationUtils.h" |
7 | | |
8 | | /// @file |
9 | | |
10 | | /// @namespace pcpp |
11 | | /// @brief The main namespace for the PcapPlusPlus lib |
12 | | namespace pcpp |
13 | | { |
14 | | /// @struct arphdr |
15 | | /// Represents an ARP protocol header |
16 | | #pragma pack(push, 1) |
17 | | struct arphdr |
18 | | { |
19 | | /// Hardware type (HTYPE) |
20 | | uint16_t hardwareType; |
21 | | /// Protocol type (PTYPE). The permitted PTYPE values share a numbering space with those for EtherType |
22 | | uint16_t protocolType; |
23 | | /// Hardware address length (HLEN). For IPv4, this has the value 0x0800 |
24 | | uint8_t hardwareSize; |
25 | | /// Protocol length (PLEN). Length (in octets) of addresses used in the upper layer protocol. (The upper layer |
26 | | /// protocol specified in PTYPE.) IPv4 address size is 4 |
27 | | uint8_t protocolSize; |
28 | | /// Specifies the operation that the sender is performing: 1 (::ARP_REQUEST) for request, 2 (::ARP_REPLY) for |
29 | | /// reply |
30 | | uint16_t opcode; |
31 | | /// Sender hardware address (SHA) |
32 | | uint8_t senderMacAddr[6]; |
33 | | /// Sender protocol address (SPA) |
34 | | uint32_t senderIpAddr; |
35 | | /// Target hardware address (THA) |
36 | | uint8_t targetMacAddr[6]; |
37 | | /// Target protocol address (TPA) |
38 | | uint32_t targetIpAddr; |
39 | | }; |
40 | | #pragma pack(pop) |
41 | | static_assert(sizeof(arphdr) == 28, "arphdr size is not 28 bytes"); |
42 | | |
43 | | /// An enum for ARP message type |
44 | | enum ArpOpcode |
45 | | { |
46 | | ARP_REQUEST = 0x0001, ///< ARP request |
47 | | ARP_REPLY = 0x0002 ///< ARP reply (response) |
48 | | }; |
49 | | |
50 | | /// @brief An enum representing the ARP message type |
51 | | enum class ArpMessageType |
52 | | { |
53 | | Unknown, ///< Unknown ARP message type |
54 | | Request, ///< ARP request |
55 | | Reply, ///< ARP reply |
56 | | GratuitousRequest, ///< Gratuitous ARP request |
57 | | GratuitousReply, ///< Gratuitous ARP reply |
58 | | }; |
59 | | |
60 | | /// @brief A struct representing the build data for an ARP request |
61 | | /// |
62 | | /// An ARP request is a message sent by a machine to request the MAC address of another machine on the network. |
63 | | struct ArpRequest |
64 | | { |
65 | | MacAddress senderMacAddr; |
66 | | IPv4Address senderIpAddr; |
67 | | IPv4Address targetIpAddr; |
68 | | |
69 | | /// @brief Construct a new Arp Request object |
70 | | /// @param senderMacAddress The MAC address of the machine sending the query. |
71 | | /// @param senderIPAddress The IP address of the machine sending the query. |
72 | | /// @param targetIPAddress The IP address of the target machine being queried. |
73 | | ArpRequest(MacAddress const& senderMacAddress, IPv4Address const& senderIPAddress, |
74 | | IPv4Address const& targetIPAddress) |
75 | 0 | : senderMacAddr(senderMacAddress), senderIpAddr(senderIPAddress), targetIpAddr(targetIPAddress) {}; |
76 | | }; |
77 | | |
78 | | /// @brief A struct representing the build data for an ARP reply |
79 | | /// |
80 | | /// An ARP reply is a message sent by a machine in response to an ARP request. It contains the MAC address of the |
81 | | /// answering machine, and is sent to the IP/MAC address of the machine that sent the original ARP request. |
82 | | struct ArpReply |
83 | | { |
84 | | MacAddress senderMacAddr; |
85 | | IPv4Address senderIpAddr; |
86 | | MacAddress targetMacAddr; |
87 | | IPv4Address targetIpAddr; |
88 | | |
89 | | /// @brief Construct a new Arp Reply object |
90 | | /// @param senderMacAddress The MAC address of the machine sending the reply. |
91 | | /// @param senderIPAddress The IP address of the machine sending the reply. |
92 | | /// @param targetMacAddress The MAC address of the target machine being replied to. |
93 | | /// @param targetIPAddress The IP address of the target machine being replied to. |
94 | | /// @remarks The target machine is considered the machine that sent the original ARP request. |
95 | | ArpReply(MacAddress const& senderMacAddress, IPv4Address const& senderIPAddress, |
96 | | MacAddress const& targetMacAddress, IPv4Address const& targetIPAddress) |
97 | | : senderMacAddr(senderMacAddress), senderIpAddr(senderIPAddress), targetMacAddr(targetMacAddress), |
98 | 0 | targetIpAddr(targetIPAddress) {}; |
99 | | }; |
100 | | |
101 | | /// @brief A struct representing the build data for a gratuitous ARP request |
102 | | /// |
103 | | /// A gratuitous ARP request is an ARP request that is sent by a machine to announce its presence on the network. |
104 | | /// It is an ARP request that has both the sender and target IP addresses set to the IP address of the machine |
105 | | /// and the target MAC address set to the broadcast address. Normally such a request will not receive a reply. |
106 | | /// |
107 | | /// These requests can be used to update ARP caches on other machines on the network, or to help in detecting IP |
108 | | /// address conflicts. |
109 | | struct GratuitousArpRequest |
110 | | { |
111 | | MacAddress senderMacAddr; |
112 | | IPv4Address senderIpAddr; |
113 | | |
114 | | /// @brief Construct a new Gratuitous Arp Request object |
115 | | /// @param senderMacAddress The MAC address of the machine sending the gratuitous ARP request. |
116 | | /// @param senderIPAddress The IP address of the machine sending the gratuitous ARP request. |
117 | | /// @remarks The target MAC address is set to the broadcast address and the target IP address is set to the |
118 | | /// sender's. |
119 | | GratuitousArpRequest(MacAddress const& senderMacAddress, IPv4Address const& senderIPAddress) |
120 | 0 | : senderMacAddr(senderMacAddress), senderIpAddr(senderIPAddress) {}; |
121 | | }; |
122 | | |
123 | | /// @brief A struct representing the build data a gratuitous ARP reply |
124 | | /// |
125 | | /// A gratuitous ARP reply is an ARP reply that is sent by a machine to announce its presence on the network. |
126 | | /// It is gratuitous in the sense that it is not in response to an ARP request, but sent unsolicited to the network. |
127 | | struct GratuitousArpReply |
128 | | { |
129 | | MacAddress senderMacAddr; |
130 | | IPv4Address senderIpAddr; |
131 | | |
132 | | /// @brief Construct a new Gratuitous Arp Reply object |
133 | | /// @param senderMacAddress The MAC address of the machine sending the gratuitous ARP reply. |
134 | | /// @param senderIPAddress The IP address of the machine sending the gratuitous ARP reply. |
135 | | /// @remarks The target MAC address is set to the broadcast address and the target IP address is set to the |
136 | | /// sender's. |
137 | | GratuitousArpReply(MacAddress const& senderMacAddress, IPv4Address const& senderIPAddress) |
138 | 0 | : senderMacAddr(senderMacAddress), senderIpAddr(senderIPAddress) {}; |
139 | | }; |
140 | | |
141 | | /// @class ArpLayer |
142 | | /// Represents an ARP protocol layer. Currently only IPv4 ARP messages are supported |
143 | | class ArpLayer : public Layer |
144 | | { |
145 | | public: |
146 | | /// A constructor that creates the layer from an existing packet raw data |
147 | | /// @param[in] data A pointer to the raw data (will be casted to @ref arphdr) |
148 | | /// @param[in] dataLen Size of the data in bytes |
149 | | /// @param[in] prevLayer A pointer to the previous layer |
150 | | /// @param[in] packet A pointer to the Packet instance where layer will be stored in |
151 | | ArpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) |
152 | | : Layer(data, dataLen, prevLayer, packet, ARP) |
153 | 0 | { |
154 | 0 | m_DataLen = sizeof(arphdr); |
155 | 0 | } |
156 | | |
157 | | /// @brief A constructor that creates an ARP header |
158 | | /// @param[in] opCode ARP message type (ARP request or ARP reply) |
159 | | /// @param[in] senderMacAddr The sender MAC address (will be put in arphdr#senderMacAddr) |
160 | | /// @param[in] senderIpAddr The sender IP address (will be put in arphdr#senderIpAddr) |
161 | | /// @param[in] targetMacAddr The target MAC address (will be put in arphdr#targetMacAddr) |
162 | | /// @param[in] targetIpAddr The target IP address (will be put in arphdr#targetIpAddr) |
163 | | /// @remarks No validation is done on the input parameters. The caller must ensure that the input creates a |
164 | | /// valid header. |
165 | | ArpLayer(ArpOpcode opCode, const MacAddress& senderMacAddr, const IPv4Address& senderIpAddr, |
166 | | const MacAddress& targetMacAddr, const IPv4Address& targetIpAddr); |
167 | | |
168 | | /// A constructor that allocates a new ARP header |
169 | | /// @param[in] opCode ARP message type (ARP request or ARP reply) |
170 | | /// @param[in] senderMacAddr The sender MAC address (will be put in arphdr#senderMacAddr) |
171 | | /// @param[in] targetMacAddr The target MAC address (will be put in arphdr#targetMacAddr) |
172 | | /// @param[in] senderIpAddr The sender IP address (will be put in arphdr#senderIpAddr) |
173 | | /// @param[in] targetIpAddr The target IP address (will be put in arphdr#targetIpAddr) |
174 | | /// @deprecated This constructor has been deprecated. Please use one of the other overloads. |
175 | | /// @remarks This constructor zeroes the target MAC address for ARP requests to keep backward compatibility. |
176 | | PCPP_DEPRECATED("This constructor has been deprecated. Please use one of the other overloads.") |
177 | | ArpLayer(ArpOpcode opCode, const MacAddress& senderMacAddr, const MacAddress& targetMacAddr, |
178 | | const IPv4Address& senderIpAddr, const IPv4Address& targetIpAddr); |
179 | | |
180 | | /// @brief A constructor that creates an ARP request header. |
181 | | /// @param arpRequest The ARP request data |
182 | | explicit ArpLayer(ArpRequest const& arpRequest); |
183 | | |
184 | | /// @brief A constructor that creates an ARP reply header. |
185 | | /// @param arpReply The ARP reply data |
186 | | explicit ArpLayer(ArpReply const& arpReply); |
187 | | |
188 | | /// @brief A constructor that creates a gratuitous ARP request header. |
189 | | /// @param gratuitousArpRequest The gratuitous ARP request data |
190 | | explicit ArpLayer(GratuitousArpRequest const& gratuitousArpRequest); |
191 | | |
192 | | /// @brief A constructor that creates a gratuitous ARP reply header. |
193 | | /// @param gratuitousArpReply The gratuitous ARP reply data |
194 | | explicit ArpLayer(GratuitousArpReply const& gratuitousArpReply); |
195 | | |
196 | | ~ArpLayer() override = default; |
197 | | |
198 | | /// Get a pointer to the ARP header. Notice this points directly to the data, so every change will change the |
199 | | /// actual packet data |
200 | | /// @return A pointer to the @ref arphdr |
201 | | inline arphdr* getArpHeader() const |
202 | 0 | { |
203 | 0 | return reinterpret_cast<arphdr*>(m_Data); |
204 | 0 | } |
205 | | |
206 | | /// Get the ARP opcode |
207 | | /// @return The ARP opcode |
208 | | /// @remarks The opcode may not be one of the values in @ref ArpOpcode |
209 | | ArpOpcode getOpcode() const; |
210 | | |
211 | | /// Get the sender hardware address (SHA) in the form of MacAddress |
212 | | /// @return A MacAddress containing the sender hardware address (SHA) |
213 | | inline MacAddress getSenderMacAddress() const |
214 | 0 | { |
215 | 0 | return MacAddress(getArpHeader()->senderMacAddr); |
216 | 0 | } |
217 | | |
218 | | /// Get the target hardware address (THA) in the form of MacAddress |
219 | | /// @return A MacAddress containing the target hardware address (THA) |
220 | | inline MacAddress getTargetMacAddress() const |
221 | 0 | { |
222 | 0 | return MacAddress(getArpHeader()->targetMacAddr); |
223 | 0 | } |
224 | | |
225 | | /// Get the sender protocol address (SPA) in the form of IPv4Address |
226 | | /// @return An IPv4Address containing the sender protocol address (SPA) |
227 | | inline IPv4Address getSenderIpAddr() const |
228 | 0 | { |
229 | 0 | return getArpHeader()->senderIpAddr; |
230 | 0 | } |
231 | | |
232 | | /// Get the target protocol address (TPA) in the form of IPv4Address |
233 | | /// @return An IPv4Address containing the target protocol address (TPA) |
234 | | inline IPv4Address getTargetIpAddr() const |
235 | 0 | { |
236 | 0 | return getArpHeader()->targetIpAddr; |
237 | 0 | } |
238 | | |
239 | | // implement abstract methods |
240 | | |
241 | | /// Does nothing for this layer (ArpLayer is always last) |
242 | | void parseNextLayer() override |
243 | 0 | {} |
244 | | |
245 | | /// @return The size of @ref arphdr |
246 | | size_t getHeaderLen() const override |
247 | 0 | { |
248 | 0 | return sizeof(arphdr); |
249 | 0 | } |
250 | | |
251 | | /// Calculate the following fields: |
252 | | /// - @ref arphdr#hardwareType = Ethernet (1) |
253 | | /// - @ref arphdr#hardwareSize = 6 |
254 | | /// - @ref arphdr#protocolType = ETHERTYPE_IP (assume IPv4 over ARP) |
255 | | /// - @ref arphdr#protocolSize = 4 (assume IPv4 over ARP) |
256 | | void computeCalculateFields() override; |
257 | | |
258 | | /// @brief Attempts to determine the ARP message type based on the header signature. |
259 | | /// @return An @ref ArpMessageType representing the ARP message type. |
260 | | ArpMessageType getMessageType() const; |
261 | | |
262 | | /// Is this packet an ARP request? |
263 | | bool isRequest() const; |
264 | | |
265 | | /// Is this packet an ARP reply? |
266 | | bool isReply() const; |
267 | | |
268 | | std::string toString() const override; |
269 | | |
270 | | OsiModelLayer getOsiModelLayer() const override |
271 | 0 | { |
272 | 0 | return OsiModelNetworkLayer; |
273 | 0 | } |
274 | | |
275 | | /// A static method that validates the input data |
276 | | /// @param[in] data The pointer to the beginning of a byte stream of an ARP layer |
277 | | /// @param[in] dataLen The length of the byte stream |
278 | | /// @return True if the data is valid and can represent an ARP layer |
279 | | static bool isDataValid(const uint8_t* data, size_t dataLen) |
280 | 0 | { |
281 | 0 | return canReinterpretAs<arphdr>(data, dataLen); |
282 | 0 | } |
283 | | }; |
284 | | |
285 | | } // namespace pcpp |