/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 | 1.81k | { |
46 | 1.81k | return m_OptionReader.getTLVRecord((uint8_t)option, getNdpOptionsBasePtr(), getHeaderLen() - getNdpHeaderLen()); |
47 | 1.81k | } |
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 | allocData(sizeof(ndpneighborsolicitationhdr)); |
112 | 0 | m_Protocol = ICMPv6; |
113 | |
|
114 | 0 | ndpneighborsolicitationhdr* pHdr = getNdpHeader(); |
115 | 0 | pHdr->type = static_cast<uint8_t>(ICMPv6MessageType::ICMPv6_NEIGHBOR_SOLICITATION); |
116 | 0 | pHdr->code = code; |
117 | 0 | memcpy(pHdr->targetIP, targetIP.toBytes(), 16); |
118 | 0 | } |
119 | | |
120 | | bool NDPNeighborSolicitationLayer::hasLinkLayerAddress() const |
121 | 1.10k | { |
122 | 1.10k | NdpOption option = this->getNdpOption(NDPNeighborOptionTypes::NDP_OPTION_SOURCE_LINK_LAYER); |
123 | 1.10k | return option.isNull() ? false : true; |
124 | 1.10k | } |
125 | | |
126 | | MacAddress NDPNeighborSolicitationLayer::getLinkLayerAddress() const |
127 | 386 | { |
128 | 386 | NdpOption option = this->getNdpOption(NDPNeighborOptionTypes::NDP_OPTION_SOURCE_LINK_LAYER); |
129 | | |
130 | 386 | if (option.isNull()) |
131 | 0 | { |
132 | 0 | return MacAddress::Zero; |
133 | 0 | } |
134 | | |
135 | 386 | return MacAddress(option.getValue()); |
136 | 386 | } |
137 | | |
138 | | std::string NDPNeighborSolicitationLayer::toString() const |
139 | 1.10k | { |
140 | 1.10k | std::ostringstream typeStream; |
141 | 1.10k | typeStream << "ICMPv6 Layer, Neighbor Solicitation Message, TargetIP: " + getTargetIP().toString(); |
142 | 1.10k | hasLinkLayerAddress() ? typeStream << ", SourceMAC: " + getLinkLayerAddress().toString() |
143 | 1.10k | : typeStream << ", no Option"; |
144 | | |
145 | 1.10k | return typeStream.str(); |
146 | 1.10k | } |
147 | | |
148 | | // -------- Class NDPNeighborAdvertisementLayer ----------------- |
149 | | |
150 | | NDPNeighborAdvertisementLayer::NDPNeighborAdvertisementLayer(uint8_t code, const IPv6Address& targetIP, |
151 | | const MacAddress& targetMac, bool routerFlag, |
152 | | bool unicastFlag, bool overrideFlag) |
153 | 0 | { |
154 | 0 | initLayer(code, targetIP, routerFlag, unicastFlag, overrideFlag); |
155 | 0 | this->addNdpOption(pcpp::NdpOptionBuilder(pcpp::NDPNeighborOptionTypes::NDP_OPTION_TARGET_LINK_LAYER, |
156 | 0 | targetMac.getRawData(), 6)); |
157 | 0 | } |
158 | | |
159 | | NDPNeighborAdvertisementLayer::NDPNeighborAdvertisementLayer(uint8_t code, const IPv6Address& targetIP, |
160 | | bool routerFlag, bool unicastFlag, bool overrideFlag) |
161 | 0 | { |
162 | 0 | initLayer(code, targetIP, routerFlag, unicastFlag, overrideFlag); |
163 | 0 | } |
164 | | |
165 | | void NDPNeighborAdvertisementLayer::initLayer(uint8_t code, const IPv6Address& targetIP, bool routerFlag, |
166 | | bool unicastFlag, bool overrideFlag) |
167 | 0 | { |
168 | 0 | allocData(sizeof(ndpneighboradvertisementhdr)); |
169 | 0 | m_Protocol = ICMPv6; |
170 | |
|
171 | 0 | ndpneighboradvertisementhdr* pHdr = getNdpHeader(); |
172 | 0 | pHdr->type = static_cast<uint8_t>(ICMPv6MessageType::ICMPv6_NEIGHBOR_ADVERTISEMENT); |
173 | 0 | pHdr->code = code; |
174 | 0 | pHdr->router = routerFlag; |
175 | 0 | pHdr->solicited = unicastFlag; |
176 | 0 | pHdr->override = overrideFlag; |
177 | |
|
178 | 0 | memcpy(pHdr->targetIP, targetIP.toBytes(), 16); |
179 | 0 | } |
180 | | |
181 | | bool NDPNeighborAdvertisementLayer::hasTargetMacInfo() const |
182 | 166 | { |
183 | 166 | NdpOption option = this->getNdpOption(NDPNeighborOptionTypes::NDP_OPTION_TARGET_LINK_LAYER); |
184 | 166 | return option.isNull() ? false : true; |
185 | 166 | } |
186 | | |
187 | | MacAddress NDPNeighborAdvertisementLayer::getTargetMac() const |
188 | 154 | { |
189 | 154 | NdpOption option = this->getNdpOption(NDPNeighborOptionTypes::NDP_OPTION_TARGET_LINK_LAYER); |
190 | | |
191 | 154 | if (option.isNull()) |
192 | 0 | { |
193 | 0 | return MacAddress::Zero; |
194 | 0 | } |
195 | | |
196 | 154 | return MacAddress(option.getValue()); |
197 | 154 | } |
198 | | |
199 | | std::string NDPNeighborAdvertisementLayer::toString() const |
200 | 166 | { |
201 | 166 | std::ostringstream typeStream; |
202 | 166 | typeStream << "ICMPv6 Layer, Neighbor Advertisement Message, TargetIP: " << getTargetIP().toString(); |
203 | 166 | hasTargetMacInfo() ? typeStream << ", TargetMAC: " + getTargetMac().toString() : typeStream << ", no Option"; |
204 | | |
205 | 166 | return typeStream.str(); |
206 | 166 | } |
207 | | |
208 | | } // namespace pcpp |