1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#ifndef PACKETPP_ARP_LAYER
#define PACKETPP_ARP_LAYER
#include "Layer.h"
#include "IpAddress.h"
#include "MacAddress.h"
/// @file
/**
* \namespace pcpp
* \brief The main namespace for the PcapPlusPlus lib
*/
namespace pcpp
{
/**
* @struct arphdr
* Represents an ARP protocol header
*/
#pragma pack(push, 1)
struct arphdr
{
/** Hardware type (HTYPE) */
uint16_t hardwareType;
/** Protocol type (PTYPE). The permitted PTYPE values share a numbering space with those for EtherType */
uint16_t protocolType;
/** Hardware address length (HLEN). For IPv4, this has the value 0x0800 */
uint8_t hardwareSize;
/** Protocol length (PLEN). Length (in octets) of addresses used in the upper layer protocol. (The upper layer protocol specified in PTYPE.) IPv4 address size is 4 */
uint8_t protocolSize;
/** Specifies the operation that the sender is performing: 1 (::ARP_REQUEST) for request, 2 (::ARP_REPLY) for reply */
uint16_t opcode;
/** Sender hardware address (SHA) */
uint8_t senderMacAddr[6];
/** Sender protocol address (SPA) */
uint32_t senderIpAddr;
/** Target hardware address (THA) */
uint8_t targetMacAddr[6];
/** Target protocol address (TPA) */
uint32_t targetIpAddr;
};
#pragma pack(pop)
/**
* An enum for ARP message type
*/
enum ArpOpcode
{
ARP_REQUEST = 0x0001, ///< ARP request
ARP_REPLY = 0x0002 ///< ARP reply (response)
};
/**
* @class ArpLayer
* Represents an ARP protocol layer. Currently only IPv4 ARP messages are supported
*/
class ArpLayer : public Layer
{
public:
/**
* A constructor that creates the layer from an existing packet raw data
* @param[in] data A pointer to the raw data (will be casted to @ref arphdr)
* @param[in] dataLen Size of the data in bytes
* @param[in] prevLayer A pointer to the previous layer
* @param[in] packet A pointer to the Packet instance where layer will be stored in
*/
ArpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet) { m_Protocol = ARP; m_DataLen = sizeof(arphdr); }
/**
* A constructor that allocates a new ARP header
* @param[in] opCode ARP message type (ARP request or ARP reply)
* @param[in] senderMacAddr The sender MAC address (will be put in arphdr#senderMacAddr)
* @param[in] targetMacAddr The target MAC address (will be put in arphdr#targetMacAddr)
* @param[in] senderIpAddr The sender IP address (will be put in arphdr#senderIpAddr)
* @param[in] targetIpAddr The target IP address (will be put in arphdr#targetIpAddr)
*/
ArpLayer(ArpOpcode opCode, const MacAddress& senderMacAddr, const MacAddress& targetMacAddr, const IPv4Address& senderIpAddr, const IPv4Address& targetIpAddr);
~ArpLayer() {}
/**
* Get a pointer to the ARP header. Notice this points directly to the data, so every change will change the actual packet data
* @return A pointer to the @ref arphdr
*/
inline arphdr* getArpHeader() const { return (arphdr*)m_Data; }
/**
* Get the sender hardware address (SHA) in the form of MacAddress
* @return A MacAddress containing the sender hardware address (SHA)
*/
inline MacAddress getSenderMacAddress() const { return MacAddress(getArpHeader()->senderMacAddr); }
/**
* Get the target hardware address (THA) in the form of MacAddress
* @return A MacAddress containing the target hardware address (THA)
*/
inline MacAddress getTargetMacAddress() const { return MacAddress(getArpHeader()->targetMacAddr); }
/**
* Get the sender protocol address (SPA) in the form of IPv4Address
* @return An IPv4Address containing the sender protocol address (SPA)
*/
inline IPv4Address getSenderIpAddr() const { return getArpHeader()->senderIpAddr; }
/**
* Get the target protocol address (TPA) in the form of IPv4Address
* @return An IPv4Address containing the target protocol address (TPA)
*/
inline IPv4Address getTargetIpAddr() const { return getArpHeader()->targetIpAddr; }
// implement abstract methods
/**
* Does nothing for this layer (ArpLayer is always last)
*/
void parseNextLayer() {}
/**
* @return The size of @ref arphdr
*/
size_t getHeaderLen() const { return sizeof(arphdr); }
/**
* Calculate the following fields:
* - @ref arphdr#hardwareType = Ethernet (1)
* - @ref arphdr#hardwareSize = 6
* - @ref arphdr#protocolType = ETHERTYPE_IP (assume IPv4 over ARP)
* - @ref arphdr#protocolSize = 4 (assume IPv4 over ARP)
* - if it's an ARP request: @ref arphdr#targetMacAddr = MacAddress("00:00:00:00:00:00")
*/
void computeCalculateFields();
/**
* Is this packet an ARP request?
*/
bool isRequest() const;
/**
* Is this packet an ARP reply?
*/
bool isReply() const;
std::string toString() const;
OsiModelLayer getOsiModelLayer() const { return OsiModelNetworkLayer; }
};
} // namespace pcpp
#endif /* PACKETPP_ARP_LAYER */