/src/PcapPlusPlus/Packet++/src/ArpLayer.cpp
Line | Count | Source |
1 | | #define LOG_MODULE PacketLogModuleArpLayer |
2 | | |
3 | | #include "ArpLayer.h" |
4 | | #include "EthLayer.h" |
5 | | #include "EndianPortable.h" |
6 | | |
7 | | namespace pcpp |
8 | | { |
9 | | ArpLayer::ArpLayer(ArpOpcode opCode, const MacAddress& senderMacAddr, const IPv4Address& senderIpAddr, |
10 | | const MacAddress& targetMacAddr, const IPv4Address& targetIpAddr) |
11 | 0 | { |
12 | 0 | constexpr size_t headerLen = sizeof(arphdr); |
13 | 0 | allocData(headerLen); |
14 | 0 | m_Protocol = ARP; |
15 | |
|
16 | 0 | arphdr* arpHeader = getArpHeader(); |
17 | 0 | arpHeader->opcode = htobe16(static_cast<uint16_t>(opCode)); |
18 | 0 | senderMacAddr.copyTo(arpHeader->senderMacAddr); |
19 | 0 | targetMacAddr.copyTo(arpHeader->targetMacAddr); |
20 | 0 | arpHeader->senderIpAddr = senderIpAddr.toInt(); |
21 | 0 | arpHeader->targetIpAddr = targetIpAddr.toInt(); |
22 | 0 | } |
23 | | |
24 | | // This constructor zeroes the target MAC address for ARP requests to keep backward compatibility. |
25 | | ArpLayer::ArpLayer(ArpOpcode opCode, const MacAddress& senderMacAddr, const MacAddress& targetMacAddr, |
26 | | const IPv4Address& senderIpAddr, const IPv4Address& targetIpAddr) |
27 | 0 | : ArpLayer(opCode, senderMacAddr, senderIpAddr, opCode == ARP_REQUEST ? MacAddress::Zero : targetMacAddr, |
28 | 0 | targetIpAddr) |
29 | 0 | {} |
30 | | |
31 | | ArpLayer::ArpLayer(ArpRequest const& arpRequest) |
32 | 0 | : ArpLayer(ARP_REQUEST, arpRequest.senderMacAddr, arpRequest.senderIpAddr, MacAddress::Zero, |
33 | 0 | arpRequest.targetIpAddr) |
34 | 0 | {} |
35 | | |
36 | | ArpLayer::ArpLayer(ArpReply const& arpReply) |
37 | 0 | : ArpLayer(ARP_REPLY, arpReply.senderMacAddr, arpReply.senderIpAddr, arpReply.targetMacAddr, |
38 | 0 | arpReply.targetIpAddr) |
39 | 0 | {} |
40 | | |
41 | | ArpLayer::ArpLayer(GratuitousArpRequest const& gratuitousArpRequest) |
42 | 0 | : ArpLayer(ARP_REQUEST, gratuitousArpRequest.senderMacAddr, gratuitousArpRequest.senderIpAddr, |
43 | 0 | MacAddress::Broadcast, gratuitousArpRequest.senderIpAddr) |
44 | 0 | {} |
45 | | |
46 | | ArpLayer::ArpLayer(GratuitousArpReply const& gratuitousArpReply) |
47 | 0 | : ArpLayer(ARP_REPLY, gratuitousArpReply.senderMacAddr, gratuitousArpReply.senderIpAddr, MacAddress::Broadcast, |
48 | 0 | gratuitousArpReply.senderIpAddr) |
49 | 0 | {} |
50 | | |
51 | | ArpOpcode ArpLayer::getOpcode() const |
52 | 0 | { |
53 | 0 | return static_cast<ArpOpcode>(be16toh(getArpHeader()->opcode)); |
54 | 0 | } |
55 | | |
56 | | void ArpLayer::computeCalculateFields() |
57 | 0 | { |
58 | 0 | arphdr* arpHeader = getArpHeader(); |
59 | 0 | arpHeader->hardwareType = htobe16(1); // Ethernet |
60 | 0 | arpHeader->hardwareSize = 6; |
61 | 0 | arpHeader->protocolType = htobe16(PCPP_ETHERTYPE_IP); // assume IPv4 over ARP |
62 | 0 | arpHeader->protocolSize = 4; // assume IPv4 over ARP |
63 | 0 | } |
64 | | |
65 | | ArpMessageType ArpLayer::getMessageType() const |
66 | 0 | { |
67 | 0 | switch (getOpcode()) |
68 | 0 | { |
69 | 0 | case ArpOpcode::ARP_REQUEST: |
70 | 0 | { |
71 | 0 | if (getTargetMacAddress() == MacAddress::Broadcast && getSenderIpAddr() == getTargetIpAddr()) |
72 | 0 | { |
73 | 0 | return ArpMessageType::GratuitousRequest; |
74 | 0 | } |
75 | 0 | return ArpMessageType::Request; |
76 | 0 | } |
77 | 0 | case ArpOpcode::ARP_REPLY: |
78 | 0 | { |
79 | 0 | if (getTargetMacAddress() == MacAddress::Broadcast && getSenderIpAddr() == getTargetIpAddr()) |
80 | 0 | { |
81 | 0 | return ArpMessageType::GratuitousReply; |
82 | 0 | } |
83 | 0 | return ArpMessageType::Reply; |
84 | 0 | } |
85 | 0 | default: |
86 | 0 | return ArpMessageType::Unknown; |
87 | 0 | } |
88 | 0 | } |
89 | | |
90 | | bool ArpLayer::isRequest() const |
91 | 0 | { |
92 | 0 | return getOpcode() == pcpp::ArpOpcode::ARP_REQUEST; |
93 | 0 | } |
94 | | |
95 | | bool ArpLayer::isReply() const |
96 | 0 | { |
97 | 0 | return getOpcode() == pcpp::ArpOpcode::ARP_REPLY; |
98 | 0 | } |
99 | | |
100 | | std::string ArpLayer::toString() const |
101 | 0 | { |
102 | 0 | switch (getOpcode()) |
103 | 0 | { |
104 | 0 | case ArpOpcode::ARP_REQUEST: |
105 | 0 | return "ARP Layer, ARP request, who has " + getTargetIpAddr().toString() + " ? Tell " + |
106 | 0 | getSenderIpAddr().toString(); |
107 | 0 | case ArpOpcode::ARP_REPLY: |
108 | 0 | return "ARP Layer, ARP reply, " + getSenderIpAddr().toString() + " is at " + |
109 | 0 | getSenderMacAddress().toString(); |
110 | 0 | default: |
111 | 0 | return "ARP Layer, unknown opcode (" + std::to_string(getOpcode()) + ")"; |
112 | 0 | } |
113 | 0 | } |
114 | | |
115 | | const FieldDescriptor ArpLayer::SerializedFields::OpCode{ Layer::SerializedFields::MaxID + 1, "opCode" }; |
116 | | const FieldDescriptor ArpLayer::SerializedFields::SenderMacAddress{ Layer::SerializedFields::MaxID + 2, |
117 | | "senderMacAddress" }; |
118 | | const FieldDescriptor ArpLayer::SerializedFields::TargetMacAddress{ Layer::SerializedFields::MaxID + 3, |
119 | | "targetMacAddress" }; |
120 | | const FieldDescriptor ArpLayer::SerializedFields::SenderIpAddress{ Layer::SerializedFields::MaxID + 4, |
121 | | "senderIpAddress" }; |
122 | | const FieldDescriptor ArpLayer::SerializedFields::TargetIpAddress{ Layer::SerializedFields::MaxID + 5, |
123 | | "targetIpAddress" }; |
124 | | const FieldDescriptor ArpLayer::SerializedFields::MessageType{ Layer::SerializedFields::MaxID + 6, "messageType" }; |
125 | | const FieldDescriptor ArpLayer::SerializedFields::HardwareType{ Layer::SerializedFields::MaxID + 7, |
126 | | "hardwareType" }; |
127 | | const FieldDescriptor ArpLayer::SerializedFields::HardwareSize{ Layer::SerializedFields::MaxID + 8, |
128 | | "hardwareSize" }; |
129 | | const FieldDescriptor ArpLayer::SerializedFields::ProtocolType{ Layer::SerializedFields::MaxID + 9, |
130 | | "protocolType" }; |
131 | | const FieldDescriptor ArpLayer::SerializedFields::ProtocolSize{ Layer::SerializedFields::MaxID + 10, |
132 | | "protocolSize" }; |
133 | | |
134 | | static constexpr const char* getOpCodeAsString(ArpOpcode opCode) |
135 | 0 | { |
136 | 0 | switch (opCode) |
137 | 0 | { |
138 | 0 | case ARP_REQUEST: |
139 | 0 | return "Request"; |
140 | 0 | case ARP_REPLY: |
141 | 0 | return "Reply"; |
142 | 0 | default: |
143 | 0 | return "Unknown"; |
144 | 0 | } |
145 | 0 | } |
146 | | |
147 | | static constexpr const char* getMessageTypeAsString(ArpMessageType messageType) |
148 | 0 | { |
149 | 0 | switch (messageType) |
150 | 0 | { |
151 | 0 | case ArpMessageType::Request: |
152 | 0 | return "Request"; |
153 | 0 | case ArpMessageType::Reply: |
154 | 0 | return "Reply"; |
155 | 0 | case ArpMessageType::GratuitousRequest: |
156 | 0 | return "GratuitousRequest"; |
157 | 0 | case ArpMessageType::GratuitousReply: |
158 | 0 | return "GratuitousReply"; |
159 | 0 | default: |
160 | 0 | return "Unknown"; |
161 | 0 | } |
162 | 0 | } |
163 | | |
164 | | void ArpLayer::serializeLayer(ObjectScope& serializer) const |
165 | 0 | { |
166 | 0 | auto* opCode = getOpCodeAsString(getOpcode()); |
167 | 0 | auto* messageType = getMessageTypeAsString(getMessageType()); |
168 | |
|
169 | 0 | serializer.writeField(SerializedFields::OpCode, opCode); |
170 | 0 | serializer.writeField(SerializedFields::SenderMacAddress, getSenderMacAddress().toString()); |
171 | 0 | serializer.writeField(SerializedFields::TargetMacAddress, getTargetMacAddress().toString()); |
172 | 0 | serializer.writeField(SerializedFields::SenderIpAddress, getSenderIpAddr().toString()); |
173 | 0 | serializer.writeField(SerializedFields::TargetIpAddress, getTargetIpAddr().toString()); |
174 | 0 | serializer.writeField(SerializedFields::MessageType, messageType); |
175 | 0 | auto* header = getArpHeader(); |
176 | 0 | serializer.writeField(SerializedFields::HardwareType, be16toh(header->hardwareType)); |
177 | 0 | serializer.writeField(SerializedFields::HardwareSize, header->hardwareSize); |
178 | | serializer.writeField(SerializedFields::ProtocolType, be16toh(header->protocolType)); |
179 | 0 | serializer.writeField(SerializedFields::ProtocolSize, header->protocolSize); |
180 | 0 | } |
181 | | } // namespace pcpp |