/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 | | #include <string.h> |
14 | | |
15 | | namespace pcpp |
16 | | { |
17 | | |
18 | | |
19 | | EthLayer::EthLayer(const MacAddress& sourceMac, const MacAddress& destMac, uint16_t etherType) : Layer() |
20 | 0 | { |
21 | 0 | const size_t headerLen = sizeof(ether_header); |
22 | 0 | m_DataLen = headerLen; |
23 | 0 | m_Data = new uint8_t[headerLen]; |
24 | 0 | memset(m_Data, 0, headerLen); |
25 | |
|
26 | 0 | ether_header* ethHdr = (ether_header*)m_Data; |
27 | 0 | destMac.copyTo(ethHdr->dstMac); |
28 | 0 | sourceMac.copyTo(ethHdr->srcMac); |
29 | 0 | ethHdr->etherType = htobe16(etherType); |
30 | 0 | m_Protocol = Ethernet; |
31 | 0 | } |
32 | | |
33 | | void EthLayer::parseNextLayer() |
34 | 16.0k | { |
35 | 16.0k | if (m_DataLen <= sizeof(ether_header)) |
36 | 237 | return; |
37 | | |
38 | 15.7k | ether_header* hdr = getEthHeader(); |
39 | 15.7k | uint8_t* payload = m_Data + sizeof(ether_header); |
40 | 15.7k | size_t payloadLen = m_DataLen - sizeof(ether_header); |
41 | | |
42 | 15.7k | switch (be16toh(hdr->etherType)) |
43 | 15.7k | { |
44 | 2.72k | case PCPP_ETHERTYPE_IP: |
45 | 2.72k | m_NextLayer = IPv4Layer::isDataValid(payload, payloadLen) |
46 | 2.72k | ? static_cast<Layer*>(new IPv4Layer(payload, payloadLen, this, m_Packet)) |
47 | 2.72k | : static_cast<Layer*>(new PayloadLayer(payload, payloadLen, this, m_Packet)); |
48 | 2.72k | break; |
49 | 552 | case PCPP_ETHERTYPE_IPV6: |
50 | 552 | m_NextLayer = IPv6Layer::isDataValid(payload, payloadLen) |
51 | 552 | ? static_cast<Layer*>(new IPv6Layer(payload, payloadLen, this, m_Packet)) |
52 | 552 | : static_cast<Layer*>(new PayloadLayer(payload, payloadLen, this, m_Packet)); |
53 | 552 | break; |
54 | 493 | case PCPP_ETHERTYPE_ARP: |
55 | 493 | m_NextLayer = new ArpLayer(payload, payloadLen, this, m_Packet); |
56 | 493 | break; |
57 | 4.87k | case PCPP_ETHERTYPE_VLAN: |
58 | 5.97k | case PCPP_ETHERTYPE_IEEE_802_1AD: |
59 | 5.97k | m_NextLayer = new VlanLayer(payload, payloadLen, this, m_Packet); |
60 | 5.97k | break; |
61 | 1.74k | case PCPP_ETHERTYPE_PPPOES: |
62 | 1.74k | m_NextLayer = PPPoESessionLayer::isDataValid(payload, payloadLen) |
63 | 1.74k | ? static_cast<Layer*>(new PPPoESessionLayer(payload, payloadLen, this, m_Packet)) |
64 | 1.74k | : static_cast<Layer*>(new PayloadLayer(payload, payloadLen, this, m_Packet)); |
65 | 1.74k | break; |
66 | 517 | case PCPP_ETHERTYPE_PPPOED: |
67 | 517 | m_NextLayer = PPPoEDiscoveryLayer::isDataValid(payload, payloadLen) |
68 | 517 | ? static_cast<Layer*>(new PPPoEDiscoveryLayer(payload, payloadLen, this, m_Packet)) |
69 | 517 | : static_cast<Layer*>(new PayloadLayer(payload, payloadLen, this, m_Packet)); |
70 | 517 | break; |
71 | 1.13k | case PCPP_ETHERTYPE_MPLS: |
72 | 1.13k | m_NextLayer = new MplsLayer(payload, payloadLen, this, m_Packet); |
73 | 1.13k | break; |
74 | 724 | case PCPP_ETHERTYPE_WAKE_ON_LAN: |
75 | 724 | m_NextLayer = WakeOnLanLayer::isDataValid(payload, payloadLen) |
76 | 724 | ? static_cast<Layer*>(new WakeOnLanLayer(payload, payloadLen, this, m_Packet)) |
77 | 724 | : static_cast<Layer*>(new PayloadLayer(payload, payloadLen, this, m_Packet)); |
78 | 724 | break; |
79 | 1.90k | default: |
80 | 1.90k | m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); |
81 | 15.7k | } |
82 | 15.7k | } |
83 | | |
84 | | void EthLayer::computeCalculateFields() |
85 | 0 | { |
86 | 0 | if (m_NextLayer == NULL) |
87 | 0 | return; |
88 | | |
89 | 0 | switch (m_NextLayer->getProtocol()) |
90 | 0 | { |
91 | 0 | case IPv4: |
92 | 0 | getEthHeader()->etherType = htobe16(PCPP_ETHERTYPE_IP); |
93 | 0 | break; |
94 | 0 | case IPv6: |
95 | 0 | getEthHeader()->etherType = htobe16(PCPP_ETHERTYPE_IPV6); |
96 | 0 | break; |
97 | 0 | case ARP: |
98 | 0 | getEthHeader()->etherType = htobe16(PCPP_ETHERTYPE_ARP); |
99 | 0 | break; |
100 | 0 | case VLAN: |
101 | 0 | getEthHeader()->etherType = htobe16(PCPP_ETHERTYPE_VLAN); |
102 | 0 | break; |
103 | 0 | default: |
104 | 0 | return; |
105 | 0 | } |
106 | 0 | } |
107 | | |
108 | | std::string EthLayer::toString() const |
109 | 0 | { |
110 | 0 | return "Ethernet II Layer, Src: " + getSourceMac().toString() + ", Dst: " + getDestMac().toString(); |
111 | 0 | } |
112 | | |
113 | | bool EthLayer::isDataValid(const uint8_t* data, size_t dataLen) |
114 | 23.1k | { |
115 | 23.1k | if (dataLen >= sizeof(ether_header)) |
116 | 21.3k | { |
117 | | /** |
118 | | * Ethertypes: These are 16-bit identifiers appearing as the initial |
119 | | * two octets after the MAC destination and source (or after a |
120 | | * tag) which, when considered as an unsigned integer, are equal |
121 | | * to or larger than 0x0600. |
122 | | * |
123 | | * From: https://tools.ietf.org/html/rfc5342#section-2.3.2.1 |
124 | | * More: IEEE Std 802.3 Clause 3.2.6 |
125 | | */ |
126 | 21.3k | return be16toh(*(uint16_t*)(data + 12)) >= (uint16_t)0x0600; |
127 | 21.3k | } |
128 | 1.78k | else |
129 | 1.78k | { |
130 | 1.78k | return false; |
131 | 1.78k | } |
132 | 23.1k | } |
133 | | |
134 | | } // namespace pcpp |