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