/src/PcapPlusPlus/Packet++/src/EthLayer.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | #define LOG_MODULE PacketLogModuleEthLayer |
2 | | |
3 | | #include "EthLayer.h" |
4 | | #include "IPv4Layer.h" |
5 | | #include "IPv6Layer.h" |
6 | | #include "PayloadLayer.h" |
7 | | #include "ArpLayer.h" |
8 | | #include "VlanLayer.h" |
9 | | #include "PPPoELayer.h" |
10 | | #include "MplsLayer.h" |
11 | | #include "WakeOnLanLayer.h" |
12 | | #include "EndianPortable.h" |
13 | | |
14 | | namespace pcpp |
15 | | { |
16 | 0 | EthLayer::EthLayer(const MacAddress& sourceMac, const MacAddress& destMac, uint16_t etherType) : Layer() |
17 | 0 | { |
18 | 0 | const size_t headerLen = sizeof(ether_header); |
19 | 0 | m_DataLen = headerLen; |
20 | 0 | m_Data = new uint8_t[headerLen]; |
21 | 0 | memset(m_Data, 0, headerLen); |
22 | |
|
23 | 0 | ether_header* ethHdr = getEthHeader(); |
24 | 0 | destMac.copyTo(ethHdr->dstMac); |
25 | 0 | sourceMac.copyTo(ethHdr->srcMac); |
26 | 0 | ethHdr->etherType = htobe16(etherType); |
27 | 0 | m_Protocol = Ethernet; |
28 | 0 | } |
29 | | |
30 | | void EthLayer::parseNextLayer() |
31 | 288k | { |
32 | 288k | if (m_DataLen <= sizeof(ether_header)) |
33 | 430 | return; |
34 | | |
35 | 287k | ether_header* hdr = getEthHeader(); |
36 | 287k | uint8_t* payload = m_Data + sizeof(ether_header); |
37 | 287k | size_t payloadLen = m_DataLen - sizeof(ether_header); |
38 | | |
39 | 287k | switch (be16toh(hdr->etherType)) |
40 | 287k | { |
41 | 218k | case PCPP_ETHERTYPE_IP: |
42 | 218k | tryConstructNextLayerWithFallback<IPv4Layer, PayloadLayer>(payload, payloadLen, m_Packet); |
43 | 218k | break; |
44 | 23.6k | case PCPP_ETHERTYPE_IPV6: |
45 | 23.6k | tryConstructNextLayerWithFallback<IPv6Layer, PayloadLayer>(payload, payloadLen, m_Packet); |
46 | 23.6k | break; |
47 | 365 | case PCPP_ETHERTYPE_ARP: |
48 | 365 | tryConstructNextLayerWithFallback<ArpLayer, PayloadLayer>(payload, payloadLen, m_Packet); |
49 | 365 | break; |
50 | 44.3k | case PCPP_ETHERTYPE_VLAN: |
51 | 44.3k | case PCPP_ETHERTYPE_IEEE_802_1AD: |
52 | 44.3k | tryConstructNextLayerWithFallback<VlanLayer, PayloadLayer>(payload, payloadLen, m_Packet); |
53 | 44.3k | break; |
54 | 0 | case PCPP_ETHERTYPE_PPPOES: |
55 | 0 | tryConstructNextLayerWithFallback<PPPoESessionLayer, PayloadLayer>(payload, payloadLen, m_Packet); |
56 | 0 | break; |
57 | 0 | case PCPP_ETHERTYPE_PPPOED: |
58 | 0 | tryConstructNextLayerWithFallback<PPPoEDiscoveryLayer, PayloadLayer>(payload, payloadLen, m_Packet); |
59 | 0 | break; |
60 | 0 | case PCPP_ETHERTYPE_MPLS: |
61 | 0 | tryConstructNextLayerWithFallback<MplsLayer, PayloadLayer>(payload, payloadLen, m_Packet); |
62 | 0 | break; |
63 | 0 | case PCPP_ETHERTYPE_WAKE_ON_LAN: |
64 | 0 | tryConstructNextLayerWithFallback<WakeOnLanLayer, PayloadLayer>(payload, payloadLen, m_Packet); |
65 | 0 | break; |
66 | 287k | } |
67 | | |
68 | | // If no next layer was constructed, assume it's a payload layer |
69 | 287k | if (!hasNextLayer()) |
70 | 1.12k | constructNextLayer<PayloadLayer>(payload, payloadLen, m_Packet); |
71 | 287k | } |
72 | | |
73 | | void EthLayer::computeCalculateFields() |
74 | 54.7k | { |
75 | 54.7k | if (m_NextLayer == nullptr) |
76 | 215 | return; |
77 | | |
78 | 54.5k | switch (m_NextLayer->getProtocol()) |
79 | 54.5k | { |
80 | 43.5k | case IPv4: |
81 | 43.5k | getEthHeader()->etherType = htobe16(PCPP_ETHERTYPE_IP); |
82 | 43.5k | break; |
83 | 4.79k | case IPv6: |
84 | 4.79k | getEthHeader()->etherType = htobe16(PCPP_ETHERTYPE_IPV6); |
85 | 4.79k | break; |
86 | 110 | case ARP: |
87 | 110 | getEthHeader()->etherType = htobe16(PCPP_ETHERTYPE_ARP); |
88 | 110 | break; |
89 | 5.35k | case VLAN: |
90 | 5.35k | getEthHeader()->etherType = htobe16(PCPP_ETHERTYPE_VLAN); |
91 | 5.35k | break; |
92 | 723 | default: |
93 | 723 | return; |
94 | 54.5k | } |
95 | 54.5k | } |
96 | | |
97 | | std::string EthLayer::toString() const |
98 | 109k | { |
99 | 109k | return "Ethernet II Layer, Src: " + getSourceMac().toString() + ", Dst: " + getDestMac().toString(); |
100 | 109k | } |
101 | | |
102 | | bool EthLayer::isDataValid(const uint8_t* data, size_t dataLen) |
103 | 288k | { |
104 | 288k | if (dataLen >= sizeof(ether_header)) |
105 | 288k | { |
106 | | // Ethertypes: These are 16-bit identifiers appearing as the initial |
107 | | // two octets after the MAC destination and source (or after a |
108 | | // tag) which, when considered as an unsigned integer, are equal |
109 | | // to or larger than 0x0600. |
110 | | // |
111 | | // From: https://tools.ietf.org/html/rfc5342#section-2.3.2.1 |
112 | | // More: IEEE Std 802.3 Clause 3.2.6 |
113 | 288k | return be16toh(*reinterpret_cast<const uint16_t*>(data + 12)) >= static_cast<uint16_t>(0x0600); |
114 | 288k | } |
115 | 2 | else |
116 | 2 | { |
117 | 2 | return false; |
118 | 2 | } |
119 | 288k | } |
120 | | } // namespace pcpp |