Coverage Report

Created: 2025-07-11 06:47

/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