Coverage Report

Created: 2026-07-16 07:15

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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