Coverage Report

Created: 2026-10-17 07:07

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/PcapPlusPlus/Packet++/src/PPPoELayer.cpp
Line
Count
Source
1
0
#define LOG_MODULE PacketLogModulePPPoELayer
2
3
#include "PPPoELayer.h"
4
#include "IPv4Layer.h"
5
#include "IPv6Layer.h"
6
#include "PayloadLayer.h"
7
#include "Logger.h"
8
#include <unordered_map>
9
#include <sstream>
10
#include "EndianPortable.h"
11
12
namespace pcpp
13
{
14
15
  /// PPPoELayer
16
  /// ~~~~~~~~~~
17
18
  PPPoELayer::PPPoELayer(uint8_t version, uint8_t type, PPPoELayer::PPPoECode code, uint16_t sessionId,
19
                         size_t additionalBytesToAllocate)
20
0
  {
21
0
    const size_t dataLen = sizeof(pppoe_header) + additionalBytesToAllocate;
22
0
    allocData(dataLen);
23
24
0
    pppoe_header* pppoeHdr = getPPPoEHeader();
25
0
    pppoeHdr->version = (version & 0xf);
26
0
    pppoeHdr->type = (type & 0x0f);
27
0
    pppoeHdr->code = code;
28
0
    pppoeHdr->sessionId = htobe16(sessionId);
29
0
    pppoeHdr->payloadLength = 0;
30
0
  }
31
32
  void PPPoELayer::computeCalculateFields()
33
0
  {
34
0
    pppoe_header* pppoeHdr = getPPPoEHeader();
35
0
    pppoeHdr->payloadLength = htobe16(m_DataLen - sizeof(pppoe_header));
36
0
  }
37
38
  const FieldDescriptor PPPoELayer::SerializedFields::Code{ Layer::SerializedFields::MaxID + 1, "code" };
39
  const FieldDescriptor PPPoELayer::SerializedFields::Version{ Layer::SerializedFields::MaxID + 2, "version" };
40
  const FieldDescriptor PPPoELayer::SerializedFields::Type{ Layer::SerializedFields::MaxID + 3, "type" };
41
  const FieldDescriptor PPPoELayer::SerializedFields::SessionID{ Layer::SerializedFields::MaxID + 4, "sessionID" };
42
43
  void PPPoELayer::serializeLayer(ObjectScope& serializer) const
44
0
  {
45
0
    auto* header = getPPPoEHeader();
46
0
    serializer.writeField(SerializedFields::Code, header->code);
47
0
    serializer.writeField(SerializedFields::Version, header->version);
48
0
    serializer.writeField(SerializedFields::Type, header->type);
49
0
    serializer.writeField(SerializedFields::SessionID, be16toh(header->sessionId));
50
0
  }
51
52
  /// PPPoESessionLayer
53
  /// ~~~~~~~~~~~~~~~~~
54
55
  void PPPoESessionLayer::parseNextLayer()
56
0
  {
57
0
    size_t headerLen = getHeaderLen();
58
0
    if (m_DataLen <= headerLen)
59
0
      return;
60
61
0
    uint8_t* payload = m_Data + headerLen;
62
0
    size_t payloadLen = m_DataLen - headerLen;
63
64
0
    switch (getPPPNextProtocol())
65
0
    {
66
0
    case PCPP_PPP_IP:
67
0
      tryConstructNextLayerWithFallback<IPv4Layer, PayloadLayer>(payload, payloadLen);
68
0
      break;
69
0
    case PCPP_PPP_IPV6:
70
0
      tryConstructNextLayerWithFallback<IPv6Layer, PayloadLayer>(payload, payloadLen);
71
0
      break;
72
0
    default:
73
0
      constructNextLayer<PayloadLayer>(payload, payloadLen);
74
0
      break;
75
0
    }
76
0
  }
77
78
  uint16_t PPPoESessionLayer::getPPPNextProtocol() const
79
0
  {
80
0
    if (m_DataLen < getHeaderLen())
81
0
    {
82
0
      PCPP_LOG_ERROR("ERROR: size of layer is smaller then PPPoE session header");
83
0
      return 0;
84
0
    }
85
86
0
    uint16_t pppNextProto = *reinterpret_cast<uint16_t*>(m_Data + sizeof(pppoe_header));
87
0
    return be16toh(pppNextProto);
88
0
  }
89
90
  void PPPoESessionLayer::setPPPNextProtocol(uint16_t nextProtocol)
91
0
  {
92
0
    if (m_DataLen < getHeaderLen())
93
0
    {
94
0
      PCPP_LOG_ERROR("ERROR: size of layer is smaller then PPPoE session header");
95
0
      return;
96
0
    }
97
98
0
    uint16_t* pppProto = reinterpret_cast<uint16_t*>(m_Data + sizeof(pppoe_header));
99
0
    *pppProto = htobe16(nextProtocol);
100
0
  }
101
102
  std::unordered_map<uint16_t, std::string> createPPPNextProtoToStringMap()
103
2
  {
104
2
    std::unordered_map<uint16_t, std::string> tempMap;
105
2
    tempMap[PCPP_PPP_PADDING] = "Padding Protocol";
106
2
    tempMap[PCPP_PPP_ROHC_SCID] = "ROHC small-CID";
107
2
    tempMap[PCPP_PPP_ROHC_LCID] = "ROHC large-CID";
108
2
    tempMap[PCPP_PPP_IP] = "Internet Protocol version 4";
109
2
    tempMap[PCPP_PPP_OSI] = "OSI Network Layer";
110
2
    tempMap[PCPP_PPP_XNSIDP] = "Xerox NS IDP";
111
2
    tempMap[PCPP_PPP_DEC4] = "DECnet Phase IV";
112
2
    tempMap[PCPP_PPP_AT] = "Appletalk";
113
2
    tempMap[PCPP_PPP_IPX] = "Novell IPX";
114
2
    tempMap[PCPP_PPP_VJC_COMP] = "Van Jacobson Compressed TCP/IP";
115
2
    tempMap[PCPP_PPP_VJC_UNCOMP] = "Van Jacobson Uncompressed TCP/IP";
116
2
    tempMap[PCPP_PPP_BCP] = "Bridging PDU";
117
2
    tempMap[PCPP_PPP_ST] = "Stream Protocol (ST-II)";
118
2
    tempMap[PCPP_PPP_VINES] = "Banyan Vines";
119
2
    tempMap[PCPP_PPP_AT_EDDP] = "AppleTalk EDDP";
120
2
    tempMap[PCPP_PPP_AT_SB] = "AppleTalk SmartBuffered";
121
2
    tempMap[PCPP_PPP_MP] = "Multi-Link";
122
2
    tempMap[PCPP_PPP_NB] = "NETBIOS Framing";
123
2
    tempMap[PCPP_PPP_CISCO] = "Cisco Systems";
124
2
    tempMap[PCPP_PPP_ASCOM] = "Ascom Timeplex";
125
2
    tempMap[PCPP_PPP_LBLB] = "Fujitsu Link Backup and Load Balancing (LBLB)";
126
2
    tempMap[PCPP_PPP_RL] = "DCA Remote Lan";
127
2
    tempMap[PCPP_PPP_SDTP] = "Serial Data Transport Protocol (PPP-SDTP)";
128
2
    tempMap[PCPP_PPP_LLC] = "SNA over 802.2";
129
2
    tempMap[PCPP_PPP_SNA] = "SNA";
130
2
    tempMap[PCPP_PPP_IPV6HC] = "IPv6 Header Compression ";
131
2
    tempMap[PCPP_PPP_KNX] = "KNX Bridging Data";
132
2
    tempMap[PCPP_PPP_ENCRYPT] = "Encryption";
133
2
    tempMap[PCPP_PPP_ILE] = "Individual Link Encryption";
134
2
    tempMap[PCPP_PPP_IPV6] = "Internet Protocol version 6";
135
2
    tempMap[PCPP_PPP_MUX] = "PPP Muxing";
136
2
    tempMap[PCPP_PPP_VSNP] = "Vendor-Specific Network Protocol (VSNP)";
137
2
    tempMap[PCPP_PPP_TNP] = "TRILL Network Protocol (TNP)";
138
2
    tempMap[PCPP_PPP_RTP_FH] = "RTP IPHC Full Header";
139
2
    tempMap[PCPP_PPP_RTP_CTCP] = "RTP IPHC Compressed TCP";
140
2
    tempMap[PCPP_PPP_RTP_CNTCP] = "RTP IPHC Compressed Non TCP";
141
2
    tempMap[PCPP_PPP_RTP_CUDP8] = "RTP IPHC Compressed UDP 8";
142
2
    tempMap[PCPP_PPP_RTP_CRTP8] = "RTP IPHC Compressed RTP 8";
143
2
    tempMap[PCPP_PPP_STAMPEDE] = "Stampede Bridging";
144
2
    tempMap[PCPP_PPP_MPPLUS] = "MP+ Protocol";
145
2
    tempMap[PCPP_PPP_NTCITS_IPI] = "NTCITS IPI";
146
2
    tempMap[PCPP_PPP_ML_SLCOMP] = "Single link compression in multilink";
147
2
    tempMap[PCPP_PPP_COMP] = "Compressed datagram";
148
2
    tempMap[PCPP_PPP_STP_HELLO] = "802.1d Hello Packets";
149
2
    tempMap[PCPP_PPP_IBM_SR] = "IBM Source Routing BPDU";
150
2
    tempMap[PCPP_PPP_DEC_LB] = "DEC LANBridge100 Spanning Tree";
151
2
    tempMap[PCPP_PPP_CDP] = "Cisco Discovery Protocol";
152
2
    tempMap[PCPP_PPP_NETCS] = "Netcs Twin Routing";
153
2
    tempMap[PCPP_PPP_STP] = "STP - Scheduled Transfer Protocol";
154
2
    tempMap[PCPP_PPP_EDP] = "EDP - Extreme Discovery Protocol";
155
2
    tempMap[PCPP_PPP_OSCP] = "Optical Supervisory Channel Protocol (OSCP)";
156
2
    tempMap[PCPP_PPP_OSCP2] = "Optical Supervisory Channel Protocol (OSCP)";
157
2
    tempMap[PCPP_PPP_LUXCOM] = "Luxcom";
158
2
    tempMap[PCPP_PPP_SIGMA] = "Sigma Network Systems";
159
2
    tempMap[PCPP_PPP_ACSP] = "Apple Client Server Protocol";
160
2
    tempMap[PCPP_PPP_MPLS_UNI] = "MPLS Unicast";
161
2
    tempMap[PCPP_PPP_MPLS_MULTI] = "MPLS Multicast";
162
2
    tempMap[PCPP_PPP_P12844] = "IEEE p1284.4 standard - data packets";
163
2
    tempMap[PCPP_PPP_TETRA] = "ETSI TETRA Network Protocol Type 1";
164
2
    tempMap[PCPP_PPP_MFTP] = "Multichannel Flow Treatment Protocol";
165
2
    tempMap[PCPP_PPP_RTP_CTCPND] = "RTP IPHC Compressed TCP No Delta";
166
2
    tempMap[PCPP_PPP_RTP_CS] = "RTP IPHC Context State";
167
2
    tempMap[PCPP_PPP_RTP_CUDP16] = "RTP IPHC Compressed UDP 16";
168
2
    tempMap[PCPP_PPP_RTP_CRDP16] = "RTP IPHC Compressed RTP 16";
169
2
    tempMap[PCPP_PPP_CCCP] = "Cray Communications Control Protocol";
170
2
    tempMap[PCPP_PPP_CDPD_MNRP] = "CDPD Mobile Network Registration Protocol";
171
2
    tempMap[PCPP_PPP_EXPANDAP] = "Expand accelerator protocol";
172
2
    tempMap[PCPP_PPP_ODSICP] = "ODSICP NCP";
173
2
    tempMap[PCPP_PPP_DOCSIS] = "DOCSIS DLL";
174
2
    tempMap[PCPP_PPP_CETACEANNDP] = "Cetacean Network Detection Protocol";
175
2
    tempMap[PCPP_PPP_LZS] = "Stacker LZS";
176
2
    tempMap[PCPP_PPP_REFTEK] = "RefTek Protocol";
177
2
    tempMap[PCPP_PPP_FC] = "Fibre Channel";
178
2
    tempMap[PCPP_PPP_EMIT] = "EMIT Protocols";
179
2
    tempMap[PCPP_PPP_VSP] = "Vendor-Specific Protocol (VSP)";
180
2
    tempMap[PCPP_PPP_TLSP] = "TRILL Link State Protocol (TLSP)";
181
2
    tempMap[PCPP_PPP_IPCP] = "Internet Protocol Control Protocol";
182
2
    tempMap[PCPP_PPP_OSINLCP] = "OSI Network Layer Control Protocol";
183
2
    tempMap[PCPP_PPP_XNSIDPCP] = "Xerox NS IDP Control Protocol";
184
2
    tempMap[PCPP_PPP_DECNETCP] = "DECnet Phase IV Control Protocol";
185
2
    tempMap[PCPP_PPP_ATCP] = "AppleTalk Control Protocol";
186
2
    tempMap[PCPP_PPP_IPXCP] = "Novell IPX Control Protocol";
187
2
    tempMap[PCPP_PPP_BRIDGENCP] = "Bridging NCP";
188
2
    tempMap[PCPP_PPP_SPCP] = "Stream Protocol Control Protocol";
189
2
    tempMap[PCPP_PPP_BVCP] = "Banyan Vines Control Protocol";
190
2
    tempMap[PCPP_PPP_MLCP] = "Multi-Link Control Protocol";
191
2
    tempMap[PCPP_PPP_NBCP] = "NETBIOS Framing Control Protocol";
192
2
    tempMap[PCPP_PPP_CISCOCP] = "Cisco Systems Control Protocol";
193
2
    tempMap[PCPP_PPP_ASCOMCP] = "Ascom Timeplex";
194
2
    tempMap[PCPP_PPP_LBLBCP] = "Fujitsu LBLB Control Protocol";
195
2
    tempMap[PCPP_PPP_RLNCP] = "DCA Remote Lan Network Control Protocol (RLNCP)";
196
2
    tempMap[PCPP_PPP_SDCP] = "Serial Data Control Protocol (PPP-SDCP)";
197
2
    tempMap[PCPP_PPP_LLCCP] = "SNA over 802.2 Control Protocol";
198
2
    tempMap[PCPP_PPP_SNACP] = "SNA Control Protocol";
199
2
    tempMap[PCPP_PPP_IP6HCCP] = "IP6 Header Compression Control Protocol";
200
2
    tempMap[PCPP_PPP_KNXCP] = "KNX Bridging Control Protocol";
201
2
    tempMap[PCPP_PPP_ECP] = "Encryption Control Protocol";
202
2
    tempMap[PCPP_PPP_ILECP] = "Individual Link Encryption Control Protocol";
203
2
    tempMap[PCPP_PPP_IPV6CP] = "IPv6 Control Protocol";
204
2
    tempMap[PCPP_PPP_MUXCP] = "PPP Muxing Control Protocol";
205
2
    tempMap[PCPP_PPP_VSNCP] = "Vendor-Specific Network Control Protocol (VSNCP)";
206
2
    tempMap[PCPP_PPP_TNCP] = "TRILL Network Control Protocol";
207
2
    tempMap[PCPP_PPP_STAMPEDECP] = "Stampede Bridging Control Protocol";
208
2
    tempMap[PCPP_PPP_MPPCP] = "MP+ Control Protocol";
209
2
    tempMap[PCPP_PPP_IPICP] = "NTCITS IPI Control Protocol";
210
2
    tempMap[PCPP_PPP_SLCC] = "Single link compression in multilink control";
211
2
    tempMap[PCPP_PPP_CCP] = "Compression Control Protocol";
212
2
    tempMap[PCPP_PPP_CDPCP] = "Cisco Discovery Protocol Control Protocol";
213
2
    tempMap[PCPP_PPP_NETCSCP] = "Netcs Twin Routing";
214
2
    tempMap[PCPP_PPP_STPCP] = "STP - Control Protocol";
215
2
    tempMap[PCPP_PPP_EDPCP] = "EDPCP - Extreme Discovery Protocol Control Protocol";
216
2
    tempMap[PCPP_PPP_ACSPC] = "Apple Client Server Protocol Control";
217
2
    tempMap[PCPP_PPP_MPLSCP] = "MPLS Control Protocol";
218
2
    tempMap[PCPP_PPP_P12844CP] = "IEEE p1284.4 standard - Protocol Control";
219
2
    tempMap[PCPP_PPP_TETRACP] = "ETSI TETRA TNP1 Control Protocol";
220
2
    tempMap[PCPP_PPP_MFTPCP] = "Multichannel Flow Treatment Protocol";
221
2
    tempMap[PCPP_PPP_LCP] = "Link Control Protocol";
222
2
    tempMap[PCPP_PPP_PAP] = "Password Authentication Protocol";
223
2
    tempMap[PCPP_PPP_LQR] = "Link Quality Report";
224
2
    tempMap[PCPP_PPP_SPAP] = "Shiva Password Authentication Protocol";
225
2
    tempMap[PCPP_PPP_CBCP] = "Callback Control Protocol (CBCP)";
226
2
    tempMap[PCPP_PPP_BACP] = "BACP Bandwidth Allocation Control Protocol";
227
2
    tempMap[PCPP_PPP_BAP] = "BAP Bandwidth Allocation Protocol";
228
2
    tempMap[PCPP_PPP_VSAP] = "Vendor-Specific Authentication Protocol (VSAP)";
229
2
    tempMap[PCPP_PPP_CONTCP] = "Container Control Protocol";
230
2
    tempMap[PCPP_PPP_CHAP] = "Challenge Handshake Authentication Protocol";
231
2
    tempMap[PCPP_PPP_RSAAP] = "RSA Authentication Protocol";
232
2
    tempMap[PCPP_PPP_EAP] = "Extensible Authentication Protocol";
233
2
    tempMap[PCPP_PPP_SIEP] = "Mitsubishi Security Information Exchange Protocol (SIEP)";
234
2
    tempMap[PCPP_PPP_SBAP] = "Stampede Bridging Authorization Protocol";
235
2
    tempMap[PCPP_PPP_PRPAP] = "Proprietary Authentication Protocol";
236
2
    tempMap[PCPP_PPP_PRPAP2] = "Proprietary Authentication Protocol";
237
2
    tempMap[PCPP_PPP_PRPNIAP] = "Proprietary Node ID Authentication Protocol";
238
2
    return tempMap;
239
2
  }
240
241
  const std::unordered_map<uint16_t, std::string> PPPNextProtoToString = createPPPNextProtoToStringMap();
242
243
  std::string PPPoESessionLayer::toString() const
244
0
  {
245
0
    auto findResult = PPPNextProtoToString.find(getPPPNextProtocol());
246
0
    std::string nextProtocol;
247
0
    if (findResult != PPPNextProtoToString.end())
248
0
      nextProtocol = findResult->second;
249
0
    else
250
0
    {
251
0
      std::ostringstream stream;
252
0
      stream << "Unknown (0x" << std::hex << getPPPNextProtocol() << ")";
253
0
      nextProtocol = stream.str();
254
0
    }
255
256
0
    return "PPP-over-Ethernet Session (followed by '" + nextProtocol + "')";
257
0
  }
258
259
  /// PPPoEDiscoveryLayer
260
  /// ~~~~~~~~~~~~~~~~~~~
261
262
  PPPoEDiscoveryLayer::PPPoETagTypes PPPoEDiscoveryLayer::PPPoETag::getType() const
263
0
  {
264
0
    if (m_Data == nullptr)
265
0
      return PPPoEDiscoveryLayer::PPPoETagTypes::PPPOE_TAG_EOL;
266
267
0
    return static_cast<PPPoEDiscoveryLayer::PPPoETagTypes>(be16toh(m_Data->recordType));
268
0
  }
269
270
  size_t PPPoEDiscoveryLayer::PPPoETag::getTotalSize() const
271
0
  {
272
0
    if (m_Data == nullptr)
273
0
      return 0;
274
275
0
    return 2 * sizeof(uint16_t) + be16toh(m_Data->recordLen);
276
0
  }
277
278
  size_t PPPoEDiscoveryLayer::PPPoETag::getDataSize() const
279
0
  {
280
0
    if (m_Data == nullptr)
281
0
      return 0;
282
283
0
    return be16toh(m_Data->recordLen);
284
0
  }
285
286
  PPPoEDiscoveryLayer::PPPoETag PPPoEDiscoveryLayer::PPPoETagBuilder::build() const
287
0
  {
288
0
    size_t tagSize = 2 * sizeof(uint16_t) + m_RecValueLen;
289
0
    uint8_t* recordBuffer = new uint8_t[tagSize];
290
0
    uint16_t tagTypeVal = htobe16(static_cast<uint16_t>(m_RecType));
291
0
    uint16_t tagLength = htobe16(static_cast<uint16_t>(m_RecValueLen));
292
0
    memcpy(recordBuffer, &tagTypeVal, sizeof(uint16_t));
293
0
    memcpy(recordBuffer + sizeof(uint16_t), &tagLength, sizeof(uint16_t));
294
0
    if (tagLength > 0 && m_RecValue != nullptr)
295
0
      memcpy(recordBuffer + 2 * sizeof(uint16_t), m_RecValue, m_RecValueLen);
296
297
0
    return PPPoEDiscoveryLayer::PPPoETag(recordBuffer);
298
0
  }
299
300
  PPPoEDiscoveryLayer::PPPoETag PPPoEDiscoveryLayer::getTag(PPPoEDiscoveryLayer::PPPoETagTypes tagType) const
301
0
  {
302
0
    return m_TagReader.getTLVRecord(static_cast<uint32_t>(tagType), getTagBasePtr(),
303
0
                                    m_DataLen - sizeof(pppoe_header));
304
0
  }
305
306
  PPPoEDiscoveryLayer::PPPoETag PPPoEDiscoveryLayer::getFirstTag() const
307
0
  {
308
0
    return m_TagReader.getFirstTLVRecord(getTagBasePtr(), m_DataLen - sizeof(pppoe_header));
309
0
  }
310
311
  PPPoEDiscoveryLayer::PPPoETag PPPoEDiscoveryLayer::getNextTag(const PPPoEDiscoveryLayer::PPPoETag& tag) const
312
0
  {
313
0
    return m_TagReader.getNextTLVRecord(const_cast<PPPoEDiscoveryLayer::PPPoETag&>(tag), getTagBasePtr(),
314
0
                                        m_DataLen - sizeof(pppoe_header));
315
0
  }
316
317
  int PPPoEDiscoveryLayer::getTagCount() const
318
0
  {
319
0
    return m_TagReader.getTLVRecordCount(getTagBasePtr(), m_DataLen - sizeof(pppoe_header));
320
0
  }
321
322
  PPPoEDiscoveryLayer::PPPoETag PPPoEDiscoveryLayer::addTagAt(const PPPoETagBuilder& tagBuilder, int offset)
323
0
  {
324
0
    PPPoETag newTag = tagBuilder.build();
325
0
    if (newTag.isNull())
326
0
    {
327
0
      PCPP_LOG_ERROR("Cannot build new tag of type " << (int)newTag.getType());
328
0
      return newTag;
329
0
    }
330
331
0
    size_t sizeToExtend = newTag.getTotalSize();
332
333
0
    if (!extendLayer(offset, sizeToExtend))
334
0
    {
335
0
      PCPP_LOG_ERROR("Could not extend PPPoEDiscoveryLayer in [" << sizeToExtend << "] bytes");
336
0
      newTag.purgeRecordData();
337
0
      return PPPoETag(nullptr);
338
0
    }
339
340
0
    memcpy(m_Data + offset, newTag.getRecordBasePtr(), newTag.getTotalSize());
341
342
0
    uint8_t* newTagPtr = m_Data + offset;
343
344
0
    m_TagReader.changeTLVRecordCount(1);
345
346
0
    newTag.purgeRecordData();
347
348
0
    getPPPoEHeader()->payloadLength += htobe16(sizeToExtend);
349
350
0
    return PPPoETag(newTagPtr);
351
0
  }
352
353
  PPPoEDiscoveryLayer::PPPoETag PPPoEDiscoveryLayer::addTagAfter(const PPPoETagBuilder& tagBuilder,
354
                                                                 PPPoETagTypes prevTagType)
355
0
  {
356
0
    int offset = 0;
357
358
0
    PPPoETag prevTag = getTag(prevTagType);
359
360
0
    if (prevTag.isNull())
361
0
    {
362
0
      offset = getHeaderLen();
363
0
    }
364
0
    else
365
0
    {
366
0
      offset = prevTag.getRecordBasePtr() + prevTag.getTotalSize() - m_Data;
367
0
    }
368
369
0
    return addTagAt(tagBuilder, offset);
370
0
  }
371
372
  PPPoEDiscoveryLayer::PPPoETag PPPoEDiscoveryLayer::addTag(const PPPoETagBuilder& tagBuilder)
373
0
  {
374
0
    return addTagAt(tagBuilder, getHeaderLen());
375
0
  }
376
377
  size_t PPPoEDiscoveryLayer::getHeaderLen() const
378
0
  {
379
0
    size_t payloadLen = sizeof(pppoe_header) + be16toh(getPPPoEHeader()->payloadLength);
380
0
    if (payloadLen > m_DataLen)
381
0
      return m_DataLen;
382
383
0
    return payloadLen;
384
0
  }
385
386
  bool PPPoEDiscoveryLayer::removeTag(PPPoEDiscoveryLayer::PPPoETagTypes tagType)
387
0
  {
388
0
    PPPoEDiscoveryLayer::PPPoETag tagToRemove = getTag(tagType);
389
0
    if (tagToRemove.isNull())
390
0
    {
391
0
      PCPP_LOG_ERROR("Couldn't find tag");
392
0
      return false;
393
0
    }
394
395
0
    int offset = tagToRemove.getRecordBasePtr() - m_Data;
396
397
0
    uint16_t tagTotalSize = tagToRemove.getTotalSize();
398
399
0
    if (!shortenLayer(offset, tagTotalSize))
400
0
    {
401
0
      return false;
402
0
    }
403
404
0
    m_TagReader.changeTLVRecordCount(-1);
405
406
0
    getPPPoEHeader()->payloadLength -= htobe16(tagTotalSize);
407
0
    return true;
408
0
  }
409
410
  bool PPPoEDiscoveryLayer::removeAllTags()
411
0
  {
412
0
    size_t tagCount = getTagCount();
413
0
    int offset = sizeof(pppoe_header);
414
0
    if (!shortenLayer(offset, m_DataLen - offset))
415
0
    {
416
0
      return false;
417
0
    }
418
0
    m_TagReader.changeTLVRecordCount(0 - tagCount);
419
0
    getPPPoEHeader()->payloadLength = 0;
420
0
    return true;
421
0
  }
422
423
  std::string PPPoEDiscoveryLayer::codeToString(PPPoECode code) const
424
0
  {
425
0
    switch (code)
426
0
    {
427
0
    case PPPoELayer::PPPOE_CODE_SESSION:
428
0
      return std::string("PPPoE Session");
429
0
    case PPPoELayer::PPPOE_CODE_PADO:
430
0
      return std::string("PADO");
431
0
    case PPPoELayer::PPPOE_CODE_PADI:
432
0
      return std::string("PADI");
433
0
    case PPPoELayer::PPPOE_CODE_PADG:
434
0
      return std::string("PADG");
435
0
    case PPPoELayer::PPPOE_CODE_PADC:
436
0
      return std::string("PADC");
437
0
    case PPPoELayer::PPPOE_CODE_PADQ:
438
0
      return std::string("PADQ");
439
0
    case PPPoELayer::PPPOE_CODE_PADR:
440
0
      return std::string("PADR");
441
0
    case PPPoELayer::PPPOE_CODE_PADS:
442
0
      return std::string("PADS");
443
0
    case PPPoELayer::PPPOE_CODE_PADT:
444
0
      return std::string("PADT");
445
0
    case PPPoELayer::PPPOE_CODE_PADM:
446
0
      return std::string("PADM");
447
0
    case PPPoELayer::PPPOE_CODE_PADN:
448
0
      return std::string("PADN");
449
0
    default:
450
0
      return std::string("Unknown PPPoE code");
451
0
    }
452
0
  }
453
454
  static constexpr const char* tagTypeToString(PPPoEDiscoveryLayer::PPPoETagTypes tagType)
455
0
  {
456
0
    switch (tagType)
457
0
    {
458
0
    case PPPoEDiscoveryLayer::PPPOE_TAG_EOL:
459
0
      return "PPPOE_TAG_EOL";
460
0
    case PPPoEDiscoveryLayer::PPPOE_TAG_SVC_NAME:
461
0
      return "PPPOE_TAG_SVC_NAME";
462
0
    case PPPoEDiscoveryLayer::PPPOE_TAG_AC_NAME:
463
0
      return "PPPOE_TAG_AC_NAME";
464
0
    case PPPoEDiscoveryLayer::PPPOE_TAG_HOST_UNIQ:
465
0
      return "PPPOE_TAG_HOST_UNIQ";
466
0
    case PPPoEDiscoveryLayer::PPPOE_TAG_AC_COOKIE:
467
0
      return "PPPOE_TAG_AC_COOKIE";
468
0
    case PPPoEDiscoveryLayer::PPPOE_TAG_VENDOR:
469
0
      return "PPPOE_TAG_VENDOR";
470
0
    case PPPoEDiscoveryLayer::PPPOE_TAG_CREDITS:
471
0
      return "PPPOE_TAG_CREDITS";
472
0
    case PPPoEDiscoveryLayer::PPPOE_TAG_METRICS:
473
0
      return "PPPOE_TAG_METRICS";
474
0
    case PPPoEDiscoveryLayer::PPPOE_TAG_SEQ_NUM:
475
0
      return "PPPOE_TAG_SEQ_NUM";
476
0
    case PPPoEDiscoveryLayer::PPPOE_TAG_CRED_SCALE:
477
0
      return "PPPOE_TAG_CRED_SCALE";
478
0
    case PPPoEDiscoveryLayer::PPPOE_TAG_RELAY_ID:
479
0
      return "PPPOE_TAG_RELAY_ID";
480
0
    case PPPoEDiscoveryLayer::PPPOE_TAG_HURL:
481
0
      return "PPPOE_TAG_HURL";
482
0
    case PPPoEDiscoveryLayer::PPPOE_TAG_MOTM:
483
0
      return "PPPOE_TAG_MOTM";
484
0
    case PPPoEDiscoveryLayer::PPPOE_TAG_MAX_PAYLD:
485
0
      return "PPPOE_TAG_MAX_PAYLD";
486
0
    case PPPoEDiscoveryLayer::PPPOE_TAG_IP_RT_ADD:
487
0
      return "PPPOE_TAG_IP_RT_ADD";
488
0
    case PPPoEDiscoveryLayer::PPPOE_TAG_SVC_ERR:
489
0
      return "PPPOE_TAG_SVC_ERR";
490
0
    case PPPoEDiscoveryLayer::PPPOE_TAG_AC_ERR:
491
0
      return "PPPOE_TAG_AC_ERR";
492
0
    case PPPoEDiscoveryLayer::PPPOE_TAG_GENERIC_ERR:
493
0
      return "PPPOE_TAG_GENERIC_ERR";
494
0
    default:
495
0
      return "Unknown";
496
0
    }
497
0
  }
498
499
  const FieldDescriptor PPPoEDiscoveryLayer::SerializedFields::Tags{ PPPoELayer::SerializedFields::MaxID + 1,
500
                                                                   "tags" };
501
  const FieldDescriptor PPPoEDiscoveryLayer::SerializedFields::Tag{ 0, "tag" };
502
503
  void PPPoEDiscoveryLayer::serializeLayer(ObjectScope& serializer) const
504
0
  {
505
0
    PPPoELayer::serializeLayer(serializer);
506
0
    {
507
0
      auto tags = serializer.writeArray(SerializedFields::Tags);
508
0
      for (auto tag = getFirstTag(); tag.isNotNull(); tag = getNextTag(tag))
509
0
      {
510
0
        tags.writeField(SerializedFields::Tag, tagTypeToString(tag.getType()));
511
0
      }
512
0
    }
513
0
  }
514
515
}  // namespace pcpp