Coverage Report

Created: 2026-03-07 06:49

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
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