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