/src/PcapPlusPlus/Packet++/header/EthLayer.h
Line | Count | Source |
1 | | #pragma once |
2 | | |
3 | | #include "Layer.h" |
4 | | #include "MacAddress.h" |
5 | | #include <algorithm> |
6 | | #include <iterator> |
7 | | |
8 | | /// @file |
9 | | |
10 | | /// @namespace pcpp |
11 | | /// @brief The main namespace for the PcapPlusPlus lib |
12 | | namespace pcpp |
13 | | { |
14 | | |
15 | | /// @struct ether_header |
16 | | /// Represents an Ethernet II header |
17 | | #pragma pack(push, 1) |
18 | | struct ether_header |
19 | | { |
20 | | /// Destination MAC |
21 | | uint8_t dstMac[6]; |
22 | | /// Source MAC |
23 | | uint8_t srcMac[6]; |
24 | | /// EtherType |
25 | | uint16_t etherType; |
26 | | }; |
27 | | #pragma pack(pop) |
28 | | static_assert(sizeof(ether_header) == 14, "ether_header size is not 14 bytes"); |
29 | | |
30 | | // Ethernet protocol ID's |
31 | | |
32 | | /// IP |
33 | 1.43M | #define PCPP_ETHERTYPE_IP 0x0800 |
34 | | /// Address resolution |
35 | 22.7k | #define PCPP_ETHERTYPE_ARP 0x0806 |
36 | | /// Transparent Ethernet Bridging |
37 | 0 | #define PCPP_ETHERTYPE_ETHBRIDGE 0x6558 |
38 | | /// Reverse ARP |
39 | | #define PCPP_ETHERTYPE_REVARP 0x8035 |
40 | | /// AppleTalk protocol |
41 | | #define PCPP_ETHERTYPE_AT 0x809B |
42 | | /// AppleTalk ARP |
43 | | #define PCPP_ETHERTYPE_AARP 0x80F3 |
44 | | /// IEEE 802.1Q VLAN tagging |
45 | 300k | #define PCPP_ETHERTYPE_VLAN 0x8100 |
46 | | /// IPX |
47 | | #define PCPP_ETHERTYPE_IPX 0x8137 |
48 | | /// IP protocol version 6 |
49 | 288k | #define PCPP_ETHERTYPE_IPV6 0x86dd |
50 | | /// used to test interfaces |
51 | | #define PCPP_ETHERTYPE_LOOPBACK 0x9000 |
52 | | /// PPPoE discovery |
53 | 6.38k | #define PCPP_ETHERTYPE_PPPOED 0x8863 |
54 | | /// PPPoE session |
55 | 77.7k | #define PCPP_ETHERTYPE_PPPOES 0x8864 |
56 | | /// MPLS |
57 | 9.29k | #define PCPP_ETHERTYPE_MPLS 0x8847 |
58 | | /// Point-to-point protocol (PPP) |
59 | 89.9k | #define PCPP_ETHERTYPE_PPP 0x880B |
60 | | /// RDMA over Converged Ethernet (RoCEv1) |
61 | | #define PCPP_ETHERTYPE_ROCEV1 0x8915 |
62 | | /// IEEE 802.1ad Provider Bridge, Q-in-Q |
63 | 307k | #define PCPP_ETHERTYPE_IEEE_802_1AD 0x88A8 |
64 | | /// Wake on LAN |
65 | 342 | #define PCPP_ETHERTYPE_WAKE_ON_LAN 0x0842 |
66 | | |
67 | | /// @class EthLayer |
68 | | /// Represents an Ethernet II protocol layer |
69 | | class EthLayer : public Layer |
70 | | { |
71 | | public: |
72 | | /// A constructor that creates the layer from an existing packet raw data |
73 | | /// @param[in] data A pointer to the raw data (will be casted to ether_header) |
74 | | /// @param[in] dataLen Size of the data in bytes |
75 | | /// @param[in] packet A pointer to the Packet instance where layer will be stored in |
76 | 1.68M | EthLayer(uint8_t* data, size_t dataLen, Packet* packet) : Layer(data, dataLen, nullptr, packet, Ethernet) |
77 | 1.68M | {} |
78 | | |
79 | | /// A constructor that creates the layer from an existing packet raw data |
80 | | /// @param[in] data A pointer to the raw data (will be casted to ether_header) |
81 | | /// @param[in] dataLen Size of the data in bytes |
82 | | /// @param[in] prevLayer A pointer to the previous layer |
83 | | /// @param[in] packet A pointer to the Packet instance where layer will be stored in |
84 | | EthLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) |
85 | 6.64k | : Layer(data, dataLen, prevLayer, packet, Ethernet) |
86 | 6.64k | {} |
87 | | |
88 | | /// A constructor that creates a new Ethernet header and allocates the data |
89 | | /// @param[in] sourceMac The source MAC address |
90 | | /// @param[in] destMac The destination MAC address |
91 | | /// @param[in] etherType The EtherType to be used. It's an optional parameter, a value of 0 will be set if not |
92 | | /// provided |
93 | | EthLayer(const MacAddress& sourceMac, const MacAddress& destMac, uint16_t etherType = 0); |
94 | | |
95 | | ~EthLayer() override = default; |
96 | | |
97 | | /// Get a pointer to the Ethernet header. Notice this points directly to the data, so every change will change |
98 | | /// the actual packet data |
99 | | /// @return A pointer to the ether_header |
100 | | inline ether_header* getEthHeader() const |
101 | 3.23M | { |
102 | 3.23M | return reinterpret_cast<ether_header*>(m_Data); |
103 | 3.23M | } |
104 | | |
105 | | /// Get the source MAC address |
106 | | /// @return The source MAC address |
107 | | inline MacAddress getSourceMac() const |
108 | 623k | { |
109 | 623k | return MacAddress(getEthHeader()->srcMac); |
110 | 623k | } |
111 | | |
112 | | /// Set source MAC address |
113 | | /// @param sourceMac Source MAC to set |
114 | | inline void setSourceMac(const MacAddress& sourceMac) |
115 | 0 | { |
116 | 0 | sourceMac.copyTo(getEthHeader()->srcMac); |
117 | 0 | } |
118 | | |
119 | | /// Get the destination MAC address |
120 | | /// @return The destination MAC address |
121 | | inline MacAddress getDestMac() const |
122 | 623k | { |
123 | 623k | return MacAddress(getEthHeader()->dstMac); |
124 | 623k | } |
125 | | |
126 | | /// Set destination MAC address |
127 | | /// @param destMac Destination MAC to set |
128 | | inline void setDestMac(const MacAddress& destMac) |
129 | 0 | { |
130 | 0 | destMac.copyTo(getEthHeader()->dstMac); |
131 | 0 | } |
132 | | |
133 | | // implement abstract methods |
134 | | |
135 | | /// Currently identifies the following next layers: IPv4Layer, IPv6Layer, ArpLayer, VlanLayer, |
136 | | /// PPPoESessionLayer, PPPoEDiscoveryLayer, MplsLayer. Otherwise sets PayloadLayer |
137 | | void parseNextLayer() override; |
138 | | |
139 | | /// @return Size of ether_header |
140 | | size_t getHeaderLen() const override |
141 | 495k | { |
142 | 495k | return sizeof(ether_header); |
143 | 495k | } |
144 | | |
145 | | /// Calculate ether_header#etherType for known protocols: IPv4, IPv6, ARP, VLAN |
146 | | void computeCalculateFields() override; |
147 | | |
148 | | std::string toString() const override; |
149 | | |
150 | | OsiModelLayer getOsiModelLayer() const override |
151 | 311k | { |
152 | 311k | return OsiModelDataLinkLayer; |
153 | 311k | } |
154 | | |
155 | | /// A static method that validates the input data |
156 | | /// @param[in] data The pointer to the beginning of a byte stream of an Ethernet II packet |
157 | | /// @param[in] dataLen The length of the byte stream |
158 | | /// @return True if the data is valid and can represent an Ethernet II packet |
159 | | static bool isDataValid(const uint8_t* data, size_t dataLen); |
160 | | |
161 | | /// @struct SerializedFields |
162 | | /// Fields written by EthLayer's serializeLayer(), in addition to |
163 | | /// Layer::SerializedFields. |
164 | | struct SerializedFields : Layer::SerializedFields |
165 | | { |
166 | | /// @return All field descriptors for EthLayer |
167 | | static std::vector<FieldDescriptor> all() |
168 | 0 | { |
169 | 0 | auto result = Layer::SerializedFields::all(); |
170 | 0 | std::initializer_list<FieldDescriptor> extra{ SrcMacAddress, DstMacAddress, EtherType }; |
171 | 0 | std::copy(extra.begin(), extra.end(), std::back_inserter(result)); |
172 | 0 | return result; |
173 | 0 | } |
174 | | |
175 | | /// @brief Source MAC address, as a string |
176 | | static const FieldDescriptor SrcMacAddress; |
177 | | |
178 | | /// @brief Destination MAC address, as a string |
179 | | static const FieldDescriptor DstMacAddress; |
180 | | |
181 | | /// @brief EtherType, in host byte order (e.g. 2048 for IPv4) |
182 | | static const FieldDescriptor EtherType; |
183 | | }; |
184 | | |
185 | | protected: |
186 | | void serializeLayer(ObjectScope& serializer) const override; |
187 | | }; |
188 | | |
189 | | } // namespace pcpp |