/src/PcapPlusPlus/Packet++/src/NdpLayer.cpp
Line | Count | Source |
1 | 0 | #define LOG_MODULE PacketLogModuleNdpLayer |
2 | | |
3 | | #include "NdpLayer.h" |
4 | | #include "Logger.h" |
5 | | |
6 | | namespace pcpp |
7 | | { |
8 | | |
9 | | // -------- Class NdpOptionBuilder ----------------- |
10 | | |
11 | | NdpOption NdpOptionBuilder::build() const |
12 | 0 | { |
13 | 0 | size_t optionSize = m_RecValueLen + 2 * sizeof(uint8_t); |
14 | 0 | size_t padding = (8 - (optionSize % 8)) % 8; // Padding bytes for a option with 8 byte boundary |
15 | 0 | size_t optionSizeWithPadding = optionSize + padding; |
16 | |
|
17 | 0 | uint8_t* recordBuffer = new uint8_t[optionSizeWithPadding]; |
18 | 0 | memset(recordBuffer, 0, optionSizeWithPadding); |
19 | 0 | recordBuffer[0] = static_cast<uint8_t>(m_RecType); |
20 | | // length value is stored in units of 8 octets |
21 | 0 | recordBuffer[1] = static_cast<uint8_t>(optionSizeWithPadding / 8); |
22 | 0 | memcpy(recordBuffer + 2, m_RecValue, m_RecValueLen); |
23 | |
|
24 | 0 | return NdpOption(recordBuffer); |
25 | 0 | } |
26 | | |
27 | | // -------- Class NDPLayerBase ----------------- |
28 | | |
29 | | size_t NDPLayerBase::getNdpOptionCount() const |
30 | 0 | { |
31 | 0 | return m_OptionReader.getTLVRecordCount(getNdpOptionsBasePtr(), getHeaderLen() - getNdpHeaderLen()); |
32 | 0 | } |
33 | | |
34 | | NdpOption NDPLayerBase::getFirstNdpOption() const |
35 | 0 | { |
36 | 0 | return m_OptionReader.getFirstTLVRecord(getNdpOptionsBasePtr(), getHeaderLen() - getNdpHeaderLen()); |
37 | 0 | } |
38 | | |
39 | | NdpOption NDPLayerBase::getNextNdpOption(NdpOption& option) const |
40 | 0 | { |
41 | 0 | return m_OptionReader.getNextTLVRecord(option, getNdpOptionsBasePtr(), getHeaderLen() - getNdpHeaderLen()); |
42 | 0 | } |
43 | | |
44 | | NdpOption NDPLayerBase::getNdpOption(NDPNeighborOptionTypes option) const |
45 | 2.60k | { |
46 | 2.60k | return m_OptionReader.getTLVRecord((uint8_t)option, getNdpOptionsBasePtr(), getHeaderLen() - getNdpHeaderLen()); |
47 | 2.60k | } |
48 | | |
49 | | NdpOption NDPLayerBase::addNdpOption(const NdpOptionBuilder& optionBuilder) |
50 | 0 | { |
51 | 0 | return addNdpOptionAt(optionBuilder, getHeaderLen()); |
52 | 0 | } |
53 | | |
54 | | NdpOption NDPLayerBase::addNdpOptionAt(const NdpOptionBuilder& optionBuilder, int offset) |
55 | 0 | { |
56 | 0 | NdpOption newOption = optionBuilder.build(); |
57 | |
|
58 | 0 | if (newOption.isNull()) |
59 | 0 | { |
60 | 0 | PCPP_LOG_ERROR("Cannot build new option of type " << (int)newOption.getType()); |
61 | 0 | return newOption; |
62 | 0 | } |
63 | | |
64 | 0 | size_t sizeToExtend = newOption.getTotalSize(); |
65 | |
|
66 | 0 | if (!extendLayer(offset, sizeToExtend)) |
67 | 0 | { |
68 | 0 | PCPP_LOG_ERROR("Could not extend NdpLayer in [" << sizeToExtend << "] bytes"); |
69 | 0 | newOption.purgeRecordData(); |
70 | 0 | return NdpOption(nullptr); |
71 | 0 | } |
72 | | |
73 | 0 | memcpy(m_Data + offset, newOption.getRecordBasePtr(), newOption.getTotalSize()); |
74 | |
|
75 | 0 | newOption.purgeRecordData(); |
76 | |
|
77 | 0 | m_OptionReader.changeTLVRecordCount(1); |
78 | |
|
79 | 0 | uint8_t* newOptPtr = m_Data + offset; |
80 | |
|
81 | 0 | return NdpOption(newOptPtr); |
82 | 0 | } |
83 | | |
84 | | bool NDPLayerBase::removeAllNdpOptions() |
85 | 0 | { |
86 | 0 | int offset = getNdpHeaderLen(); |
87 | 0 | if (!shortenLayer(offset, getHeaderLen() - offset)) |
88 | 0 | return false; |
89 | | |
90 | 0 | m_OptionReader.changeTLVRecordCount(0 - getNdpOptionCount()); |
91 | 0 | return true; |
92 | 0 | } |
93 | | |
94 | | // -------- Class NDPNeighborSolicitationLayer ----------------- |
95 | | |
96 | | NDPNeighborSolicitationLayer::NDPNeighborSolicitationLayer(uint8_t code, const IPv6Address& targetIP) |
97 | 0 | { |
98 | 0 | initLayer(code, targetIP); |
99 | 0 | } |
100 | | |
101 | | NDPNeighborSolicitationLayer::NDPNeighborSolicitationLayer(uint8_t code, const IPv6Address& targetIP, |
102 | | const MacAddress& srcMac) |
103 | 0 | { |
104 | 0 | initLayer(code, targetIP); |
105 | 0 | this->addNdpOption( |
106 | 0 | pcpp::NdpOptionBuilder(pcpp::NDPNeighborOptionTypes::NDP_OPTION_SOURCE_LINK_LAYER, srcMac.getRawData(), 6)); |
107 | 0 | } |
108 | | |
109 | | void NDPNeighborSolicitationLayer::initLayer(uint8_t code, const IPv6Address& targetIP) |
110 | 0 | { |
111 | 0 | m_DataLen = sizeof(ndpneighborsolicitationhdr); |
112 | 0 | m_Data = new uint8_t[m_DataLen]; |
113 | 0 | memset(m_Data, 0, m_DataLen); |
114 | 0 | m_Protocol = ICMPv6; |
115 | |
|
116 | 0 | ndpneighborsolicitationhdr* pHdr = getNdpHeader(); |
117 | 0 | pHdr->type = static_cast<uint8_t>(ICMPv6MessageType::ICMPv6_NEIGHBOR_SOLICITATION); |
118 | 0 | pHdr->code = code; |
119 | 0 | memcpy(pHdr->targetIP, targetIP.toBytes(), 16); |
120 | 0 | } |
121 | | |
122 | | bool NDPNeighborSolicitationLayer::hasLinkLayerAddress() const |
123 | 1.73k | { |
124 | 1.73k | NdpOption option = this->getNdpOption(NDPNeighborOptionTypes::NDP_OPTION_SOURCE_LINK_LAYER); |
125 | 1.73k | return option.isNull() ? false : true; |
126 | 1.73k | } |
127 | | |
128 | | MacAddress NDPNeighborSolicitationLayer::getLinkLayerAddress() const |
129 | 444 | { |
130 | 444 | NdpOption option = this->getNdpOption(NDPNeighborOptionTypes::NDP_OPTION_SOURCE_LINK_LAYER); |
131 | | |
132 | 444 | if (option.isNull()) |
133 | 0 | { |
134 | 0 | return MacAddress::Zero; |
135 | 0 | } |
136 | | |
137 | 444 | return MacAddress(option.getValue()); |
138 | 444 | } |
139 | | |
140 | | std::string NDPNeighborSolicitationLayer::toString() const |
141 | 1.73k | { |
142 | 1.73k | std::ostringstream typeStream; |
143 | 1.73k | typeStream << "ICMPv6 Layer, Neighbor Solicitation Message, TargetIP: " + getTargetIP().toString(); |
144 | 1.73k | hasLinkLayerAddress() ? typeStream << ", SourceMAC: " + getLinkLayerAddress().toString() |
145 | 1.73k | : typeStream << ", no Option"; |
146 | | |
147 | 1.73k | return typeStream.str(); |
148 | 1.73k | } |
149 | | |
150 | | // -------- Class NDPNeighborAdvertisementLayer ----------------- |
151 | | |
152 | | NDPNeighborAdvertisementLayer::NDPNeighborAdvertisementLayer(uint8_t code, const IPv6Address& targetIP, |
153 | | const MacAddress& targetMac, bool routerFlag, |
154 | | bool unicastFlag, bool overrideFlag) |
155 | 0 | { |
156 | 0 | initLayer(code, targetIP, routerFlag, unicastFlag, overrideFlag); |
157 | 0 | this->addNdpOption(pcpp::NdpOptionBuilder(pcpp::NDPNeighborOptionTypes::NDP_OPTION_TARGET_LINK_LAYER, |
158 | 0 | targetMac.getRawData(), 6)); |
159 | 0 | } |
160 | | |
161 | | NDPNeighborAdvertisementLayer::NDPNeighborAdvertisementLayer(uint8_t code, const IPv6Address& targetIP, |
162 | | bool routerFlag, bool unicastFlag, bool overrideFlag) |
163 | 0 | { |
164 | 0 | initLayer(code, targetIP, routerFlag, unicastFlag, overrideFlag); |
165 | 0 | } |
166 | | |
167 | | void NDPNeighborAdvertisementLayer::initLayer(uint8_t code, const IPv6Address& targetIP, bool routerFlag, |
168 | | bool unicastFlag, bool overrideFlag) |
169 | 0 | { |
170 | 0 | m_DataLen = sizeof(ndpneighboradvertisementhdr); |
171 | 0 | m_Data = new uint8_t[m_DataLen]; |
172 | 0 | memset(m_Data, 0, m_DataLen); |
173 | 0 | m_Protocol = ICMPv6; |
174 | |
|
175 | 0 | ndpneighboradvertisementhdr* pHdr = getNdpHeader(); |
176 | 0 | pHdr->type = static_cast<uint8_t>(ICMPv6MessageType::ICMPv6_NEIGHBOR_ADVERTISEMENT); |
177 | 0 | pHdr->code = code; |
178 | 0 | pHdr->router = routerFlag; |
179 | 0 | pHdr->solicited = unicastFlag; |
180 | 0 | pHdr->override = overrideFlag; |
181 | |
|
182 | 0 | memcpy(pHdr->targetIP, targetIP.toBytes(), 16); |
183 | 0 | } |
184 | | |
185 | | bool NDPNeighborAdvertisementLayer::hasTargetMacInfo() const |
186 | 250 | { |
187 | 250 | NdpOption option = this->getNdpOption(NDPNeighborOptionTypes::NDP_OPTION_TARGET_LINK_LAYER); |
188 | 250 | return option.isNull() ? false : true; |
189 | 250 | } |
190 | | |
191 | | MacAddress NDPNeighborAdvertisementLayer::getTargetMac() const |
192 | 176 | { |
193 | 176 | NdpOption option = this->getNdpOption(NDPNeighborOptionTypes::NDP_OPTION_TARGET_LINK_LAYER); |
194 | | |
195 | 176 | if (option.isNull()) |
196 | 0 | { |
197 | 0 | return MacAddress::Zero; |
198 | 0 | } |
199 | | |
200 | 176 | return MacAddress(option.getValue()); |
201 | 176 | } |
202 | | |
203 | | std::string NDPNeighborAdvertisementLayer::toString() const |
204 | 250 | { |
205 | 250 | std::ostringstream typeStream; |
206 | 250 | typeStream << "ICMPv6 Layer, Neighbor Advertisement Message, TargetIP: " << getTargetIP().toString(); |
207 | 250 | hasTargetMacInfo() ? typeStream << ", TargetMAC: " + getTargetMac().toString() : typeStream << ", no Option"; |
208 | | |
209 | 250 | return typeStream.str(); |
210 | 250 | } |
211 | | |
212 | | } // namespace pcpp |