Coverage Report

Created: 2023-01-17 06:15

/src/PcapPlusPlus/Packet++/src/MplsLayer.cpp
Line
Count
Source (jump to first uncovered line)
1
#define LOG_MODULE PacketLogModuleMplsLayer
2
3
#include "MplsLayer.h"
4
#include "IPv4Layer.h"
5
#include "IPv6Layer.h"
6
#include "PayloadLayer.h"
7
#include "Logger.h"
8
#include <string.h>
9
#include <sstream>
10
#include "EndianPortable.h"
11
12
namespace pcpp
13
{
14
15
MplsLayer::MplsLayer(uint32_t mplsLabel, uint8_t ttl, uint8_t experimentalUseValue, bool bottomOfStack)
16
0
{
17
0
  const size_t headerLen = sizeof(mpls_header);
18
0
  m_DataLen = headerLen;
19
0
  m_Data = new uint8_t[headerLen];
20
0
  memset(m_Data, 0, headerLen);
21
0
  m_Protocol = MPLS;
22
23
0
  setMplsLabel(mplsLabel);
24
0
  setTTL(ttl);
25
0
  setExperimentalUseValue(experimentalUseValue);
26
0
  setBottomOfStack(bottomOfStack);
27
0
}
28
29
bool MplsLayer::isBottomOfStack() const
30
5.42k
{
31
5.42k
  return (getMplsHeader()->misc & 0x01);
32
5.42k
}
33
34
void MplsLayer::setBottomOfStack(bool val)
35
0
{
36
0
  if (!val)
37
0
    getMplsHeader()->misc &= 0xFE;
38
0
  else
39
0
    getMplsHeader()->misc |= 0x1;
40
0
}
41
42
uint8_t MplsLayer::getExperimentalUseValue() const
43
0
{
44
0
  return ((getMplsHeader()->misc & 0x0E) >> 1);
45
0
}
46
47
bool MplsLayer::setExperimentalUseValue(uint8_t val)
48
0
{
49
  // exp value is only 3 bits
50
0
  if (val > 7)
51
0
  {
52
0
    PCPP_LOG_ERROR("Set ExperimentalUse value got an illegal value: " << (int)val << ". Value must be lower than 8");
53
0
    return false;
54
0
  }
55
56
0
  mpls_header* hdr = getMplsHeader();
57
58
  // clear the 3 exp bits
59
0
  hdr->misc &= 0xF1;
60
61
  // move the 3 bits to their place
62
0
  val = val << 1;
63
64
0
  hdr->misc |= val;
65
66
0
  return true;
67
0
}
68
69
uint32_t MplsLayer::getMplsLabel() const
70
0
{
71
0
  return (htobe16(getMplsHeader()->hiLabel) << 4) | ((getMplsHeader()->misc & 0xF0) >> 4);
72
0
}
73
74
bool MplsLayer::setMplsLabel(uint32_t label)
75
0
{
76
0
  if (label > 0xFFFFF)
77
0
  {
78
0
    PCPP_LOG_ERROR("MPLS label mustn't exceed 20 bits which is the value 0xffff. Got a parameter with the value 0x" << std::hex << label);
79
0
    return false;
80
0
  }
81
82
0
  mpls_header* hdr = getMplsHeader();
83
84
  // clear the 4 label bits in misc field
85
0
  hdr->misc &= 0x0F;
86
87
  // take the last nibble of the label value and move this nibble to its place in misc
88
0
  uint8_t miscVal = (label & 0x0F) << 4;
89
90
  // update misc field
91
0
  hdr->misc |= miscVal;
92
93
  // get rid of the nibble that went to misc
94
0
  label = label >> 4;
95
96
  // set the high 2 bytes of the label
97
0
  hdr->hiLabel = (uint16_t)htobe16(label);
98
99
0
  return true;
100
0
}
101
102
103
void MplsLayer::parseNextLayer()
104
5.57k
{
105
5.57k
  size_t headerLen = getHeaderLen();
106
5.57k
  if (m_DataLen < headerLen + 1)
107
150
    return;
108
109
5.42k
  uint8_t* payload = m_Data + sizeof(mpls_header);
110
5.42k
  size_t payloadLen = m_DataLen - sizeof(mpls_header);
111
112
5.42k
  if (!isBottomOfStack())
113
1.93k
  {
114
1.93k
    m_NextLayer = new MplsLayer(payload, payloadLen, this, m_Packet);
115
1.93k
    return;
116
1.93k
  }
117
118
3.48k
  uint8_t nextNibble = (*((uint8_t*)(m_Data + headerLen)) & 0xF0) >> 4;
119
3.48k
  switch (nextNibble)
120
3.48k
  {
121
2.86k
    case 4:
122
2.86k
      m_NextLayer = IPv4Layer::isDataValid(payload, payloadLen)
123
2.86k
        ? static_cast<Layer*>(new IPv4Layer(payload, payloadLen, this, m_Packet))
124
2.86k
        : static_cast<Layer*>(new PayloadLayer(payload, payloadLen, this, m_Packet));
125
2.86k
      break;
126
182
    case 6:
127
182
      m_NextLayer = IPv6Layer::isDataValid(payload, payloadLen)
128
182
        ? static_cast<Layer*>(new IPv6Layer(payload, payloadLen, this, m_Packet))
129
182
        : static_cast<Layer*>(new PayloadLayer(payload, payloadLen, this, m_Packet));
130
182
      break;
131
438
    default:
132
438
      m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet);
133
3.48k
  }
134
3.48k
}
135
136
void MplsLayer::computeCalculateFields()
137
0
{
138
0
  Layer* nextLayer = getNextLayer();
139
0
  if (nextLayer != NULL)
140
0
  {
141
0
    setBottomOfStack((nextLayer->getProtocol() != MPLS));
142
0
  }
143
0
}
144
145
std::string MplsLayer::toString() const
146
0
{
147
0
  std::ostringstream labelStream;
148
0
  labelStream << getMplsLabel();
149
0
  std::ostringstream expStream;
150
0
  expStream << (int)getExperimentalUseValue();
151
0
  std::ostringstream ttlStream;
152
0
  ttlStream << (int)getTTL();
153
0
  std::string bottomOfStack = isBottomOfStack() ? "true" : "false";
154
155
0
  return "MPLS Layer, Label: " + labelStream.str() + ", Exp: " + expStream.str() + ", TTL: " + ttlStream.str() +
156
0
      ", Bottom of stack: " + bottomOfStack;
157
0
}
158
159
} // namespace pcpp