/src/PcapPlusPlus/Packet++/src/EthLayer.cpp
Line | Count | Source |
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 | allocData(headerLen); |
20 | |
|
21 | 0 | ether_header* ethHdr = getEthHeader(); |
22 | 0 | destMac.copyTo(ethHdr->dstMac); |
23 | 0 | sourceMac.copyTo(ethHdr->srcMac); |
24 | 0 | ethHdr->etherType = htobe16(etherType); |
25 | 0 | m_Protocol = Ethernet; |
26 | 0 | } |
27 | | |
28 | | void EthLayer::parseNextLayer() |
29 | 878k | { |
30 | 878k | if (m_DataLen <= sizeof(ether_header)) |
31 | 256 | return; |
32 | | |
33 | 878k | ether_header* hdr = getEthHeader(); |
34 | 878k | uint8_t* payload = m_Data + sizeof(ether_header); |
35 | 878k | size_t payloadLen = m_DataLen - sizeof(ether_header); |
36 | | |
37 | 878k | switch (be16toh(hdr->etherType)) |
38 | 878k | { |
39 | 667k | case PCPP_ETHERTYPE_IP: |
40 | 667k | tryConstructNextLayerWithFallback<IPv4Layer, PayloadLayer>(payload, payloadLen); |
41 | 667k | break; |
42 | 144k | case PCPP_ETHERTYPE_IPV6: |
43 | 144k | tryConstructNextLayerWithFallback<IPv6Layer, PayloadLayer>(payload, payloadLen); |
44 | 144k | break; |
45 | 11.1k | case PCPP_ETHERTYPE_ARP: |
46 | 11.1k | tryConstructNextLayerWithFallback<ArpLayer, PayloadLayer>(payload, payloadLen); |
47 | 11.1k | break; |
48 | 29.1k | case PCPP_ETHERTYPE_VLAN: |
49 | 39.3k | case PCPP_ETHERTYPE_IEEE_802_1AD: |
50 | 39.3k | tryConstructNextLayerWithFallback<VlanLayer, PayloadLayer>(payload, payloadLen); |
51 | 39.3k | break; |
52 | 3.56k | case PCPP_ETHERTYPE_PPPOES: |
53 | 3.56k | tryConstructNextLayerWithFallback<PPPoESessionLayer, PayloadLayer>(payload, payloadLen); |
54 | 3.56k | break; |
55 | 3.10k | case PCPP_ETHERTYPE_PPPOED: |
56 | 3.10k | tryConstructNextLayerWithFallback<PPPoEDiscoveryLayer, PayloadLayer>(payload, payloadLen); |
57 | 3.10k | break; |
58 | 5.56k | case PCPP_ETHERTYPE_MPLS: |
59 | 5.56k | tryConstructNextLayerWithFallback<MplsLayer, PayloadLayer>(payload, payloadLen); |
60 | 5.56k | break; |
61 | 342 | case PCPP_ETHERTYPE_WAKE_ON_LAN: |
62 | 342 | tryConstructNextLayerWithFallback<WakeOnLanLayer, PayloadLayer>(payload, payloadLen); |
63 | 342 | break; |
64 | 878k | } |
65 | | |
66 | | // If no next layer was constructed, assume it's a payload layer |
67 | 878k | if (!hasNextLayer()) |
68 | 2.90k | constructNextLayer<PayloadLayer>(payload, payloadLen); |
69 | 878k | } |
70 | | |
71 | | void EthLayer::computeCalculateFields() |
72 | 168k | { |
73 | 168k | if (m_NextLayer == nullptr) |
74 | 128 | return; |
75 | | |
76 | 168k | switch (m_NextLayer->getProtocol()) |
77 | 168k | { |
78 | 127k | case IPv4: |
79 | 127k | getEthHeader()->etherType = htobe16(PCPP_ETHERTYPE_IP); |
80 | 127k | break; |
81 | 29.0k | case IPv6: |
82 | 29.0k | getEthHeader()->etherType = htobe16(PCPP_ETHERTYPE_IPV6); |
83 | 29.0k | break; |
84 | 3.01k | case ARP: |
85 | 3.01k | getEthHeader()->etherType = htobe16(PCPP_ETHERTYPE_ARP); |
86 | 3.01k | break; |
87 | 5.41k | case VLAN: |
88 | 5.41k | getEthHeader()->etherType = htobe16(PCPP_ETHERTYPE_VLAN); |
89 | 5.41k | break; |
90 | 3.39k | default: |
91 | 3.39k | return; |
92 | 168k | } |
93 | 168k | } |
94 | | |
95 | | std::string EthLayer::toString() const |
96 | 336k | { |
97 | 336k | return "Ethernet II Layer, Src: " + getSourceMac().toString() + ", Dst: " + getDestMac().toString(); |
98 | 336k | } |
99 | | |
100 | | bool EthLayer::isDataValid(const uint8_t* data, size_t dataLen) |
101 | 888k | { |
102 | 888k | if (dataLen >= sizeof(ether_header)) |
103 | 888k | { |
104 | | // Ethertypes: These are 16-bit identifiers appearing as the initial |
105 | | // two octets after the MAC destination and source (or after a |
106 | | // tag) which, when considered as an unsigned integer, are equal |
107 | | // to or larger than 0x0600. |
108 | | // |
109 | | // From: https://tools.ietf.org/html/rfc5342#section-2.3.2.1 |
110 | | // More: IEEE Std 802.3 Clause 3.2.6 |
111 | 888k | return be16toh(*reinterpret_cast<const uint16_t*>(data + 12)) >= static_cast<uint16_t>(0x0600); |
112 | 888k | } |
113 | 73 | else |
114 | 73 | { |
115 | 73 | return false; |
116 | 73 | } |
117 | 888k | } |
118 | | |
119 | | const FieldDescriptor EthLayer::SerializedFields::SrcMacAddress{ Layer::SerializedFields::MaxID + 1, |
120 | | "srcMacAddress" }; |
121 | | const FieldDescriptor EthLayer::SerializedFields::DstMacAddress{ Layer::SerializedFields::MaxID + 2, |
122 | | "dstMacAddress" }; |
123 | | const FieldDescriptor EthLayer::SerializedFields::EtherType{ Layer::SerializedFields::MaxID + 3, "etherType" }; |
124 | | |
125 | | void EthLayer::serializeLayer(ObjectScope& serializer) const |
126 | 0 | { |
127 | 0 | auto* header = getEthHeader(); |
128 | 0 | serializer.writeField(SerializedFields::SrcMacAddress, getSourceMac().toString()); |
129 | 0 | serializer.writeField(SerializedFields::DstMacAddress, getDestMac().toString()); |
130 | | serializer.writeField(SerializedFields::EtherType, be16toh(header->etherType)); |
131 | 0 | } |
132 | | } // namespace pcpp |