/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 | const size_t headerLen = sizeof(mpls_header); |
17 | 0 | m_DataLen = headerLen; |
18 | 0 | m_Data = new uint8_t[headerLen]; |
19 | 0 | memset(m_Data, 0, headerLen); |
20 | 0 | m_Protocol = MPLS; |
21 | |
|
22 | 0 | setMplsLabel(mplsLabel); |
23 | 0 | setTTL(ttl); |
24 | 0 | setExperimentalUseValue(experimentalUseValue); |
25 | 0 | setBottomOfStack(bottomOfStack); |
26 | 0 | } |
27 | | |
28 | | bool MplsLayer::isBottomOfStack() const |
29 | 4.87k | { |
30 | 4.87k | return (getMplsHeader()->misc & 0x01); |
31 | 4.87k | } |
32 | | |
33 | | void MplsLayer::setBottomOfStack(bool val) |
34 | 439 | { |
35 | 439 | if (!val) |
36 | 308 | getMplsHeader()->misc &= 0xFE; |
37 | 131 | else |
38 | 131 | getMplsHeader()->misc |= 0x1; |
39 | 439 | } |
40 | | |
41 | | uint8_t MplsLayer::getExperimentalUseValue() const |
42 | 878 | { |
43 | 878 | return ((getMplsHeader()->misc & 0x0E) >> 1); |
44 | 878 | } |
45 | | |
46 | | bool MplsLayer::setExperimentalUseValue(uint8_t val) |
47 | 0 | { |
48 | | // exp value is only 3 bits |
49 | 0 | if (val > 7) |
50 | 0 | { |
51 | 0 | PCPP_LOG_ERROR("Set ExperimentalUse value got an illegal value: " << (int)val |
52 | 0 | << ". 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 | 878 | { |
71 | 878 | return (htobe16(getMplsHeader()->hiLabel) << 4) | ((getMplsHeader()->misc & 0xF0) >> 4); |
72 | 878 | } |
73 | | |
74 | | bool MplsLayer::setMplsLabel(uint32_t label) |
75 | 0 | { |
76 | 0 | if (label > 0xFFFFF) |
77 | 0 | { |
78 | 0 | PCPP_LOG_ERROR( |
79 | 0 | "MPLS label mustn't exceed 20 bits which is the value 0xffff. Got a parameter with the value 0x" |
80 | 0 | << std::hex << label); |
81 | 0 | return false; |
82 | 0 | } |
83 | | |
84 | 0 | mpls_header* hdr = getMplsHeader(); |
85 | | |
86 | | // clear the 4 label bits in misc field |
87 | 0 | hdr->misc &= 0x0F; |
88 | | |
89 | | // take the last nibble of the label value and move this nibble to its place in misc |
90 | 0 | uint8_t miscVal = (label & 0x0F) << 4; |
91 | | |
92 | | // update misc field |
93 | 0 | hdr->misc |= miscVal; |
94 | | |
95 | | // get rid of the nibble that went to misc |
96 | 0 | label = label >> 4; |
97 | | |
98 | | // set the high 2 bytes of the label |
99 | 0 | hdr->hiLabel = (uint16_t)htobe16(label); |
100 | |
|
101 | 0 | return true; |
102 | 0 | } |
103 | | |
104 | | void MplsLayer::parseNextLayer() |
105 | 3.99k | { |
106 | 3.99k | size_t headerLen = getHeaderLen(); |
107 | 3.99k | if (m_DataLen < headerLen + 1) |
108 | 0 | return; |
109 | | |
110 | 3.99k | uint8_t* payload = m_Data + sizeof(mpls_header); |
111 | 3.99k | size_t payloadLen = m_DataLen - sizeof(mpls_header); |
112 | | |
113 | 3.99k | if (!isBottomOfStack()) |
114 | 2.87k | { |
115 | 2.87k | constructNextLayer<MplsLayer>(payload, payloadLen); |
116 | 2.87k | return; |
117 | 2.87k | } |
118 | | |
119 | 1.11k | uint8_t nextNibble = (*((uint8_t*)(m_Data + headerLen)) & 0xF0) >> 4; |
120 | 1.11k | switch (nextNibble) |
121 | 1.11k | { |
122 | 15 | case 4: |
123 | 15 | tryConstructNextLayerWithFallback<IPv4Layer, PayloadLayer>(payload, payloadLen); |
124 | 15 | break; |
125 | 750 | case 6: |
126 | 750 | tryConstructNextLayerWithFallback<IPv6Layer, PayloadLayer>(payload, payloadLen); |
127 | 750 | break; |
128 | 351 | default: |
129 | 351 | constructNextLayer<PayloadLayer>(payload, payloadLen); |
130 | 1.11k | } |
131 | 1.11k | } |
132 | | |
133 | | void MplsLayer::computeCalculateFields() |
134 | 439 | { |
135 | 439 | Layer* nextLayer = getNextLayer(); |
136 | 439 | if (nextLayer != nullptr) |
137 | 439 | { |
138 | 439 | setBottomOfStack((nextLayer->getProtocol() != MPLS)); |
139 | 439 | } |
140 | 439 | } |
141 | | |
142 | | std::string MplsLayer::toString() const |
143 | 878 | { |
144 | 878 | std::ostringstream labelStream; |
145 | 878 | labelStream << getMplsLabel(); |
146 | 878 | std::ostringstream expStream; |
147 | 878 | expStream << (int)getExperimentalUseValue(); |
148 | 878 | std::ostringstream ttlStream; |
149 | 878 | ttlStream << (int)getTTL(); |
150 | 878 | std::string bottomOfStack = isBottomOfStack() ? "true" : "false"; |
151 | | |
152 | 878 | return "MPLS Layer, Label: " + labelStream.str() + ", Exp: " + expStream.str() + ", TTL: " + ttlStream.str() + |
153 | 878 | ", Bottom of stack: " + bottomOfStack; |
154 | 878 | } |
155 | | |
156 | | } // namespace pcpp |