diff --git a/Packet++/header/EthDot3Layer.h b/Packet++/header/EthDot3Layer.h index c725cd86f4..8b63434436 100644 --- a/Packet++/header/EthDot3Layer.h +++ b/Packet++/header/EthDot3Layer.h @@ -118,6 +118,30 @@ namespace pcpp /// @param[in] dataLen The length of the byte stream /// @return True if the data is valid and can represent an IEEE 802.3 Eth packet static bool isDataValid(const uint8_t* data, size_t dataLen); + + /// @struct SerializedFields + /// Fields written by EthDot3Layer's serializeLayer(), in addition to + /// Layer::SerializedFields. + struct SerializedFields : Layer::SerializedFields + { + /// @return All field descriptors for EthDot3Layer + static std::vector all() + { + auto result = Layer::SerializedFields::all(); + std::initializer_list extra{ SrcMacAddress, DstMacAddress }; + std::copy(extra.begin(), extra.end(), std::back_inserter(result)); + return result; + } + + /// @brief Source MAC address, as a string + static const FieldDescriptor SrcMacAddress; + + /// @brief Destination MAC address, as a string + static const FieldDescriptor DstMacAddress; + }; + + protected: + void serializeLayer(ObjectScope& serializer) const override; }; } // namespace pcpp diff --git a/Packet++/header/LLCLayer.h b/Packet++/header/LLCLayer.h index ddaf7a99ad..f422fd0f19 100644 --- a/Packet++/header/LLCLayer.h +++ b/Packet++/header/LLCLayer.h @@ -79,6 +79,33 @@ namespace pcpp /// @param[in] dataLen The length of the byte stream /// @return True if the data is valid and can represent an LLC packet static bool isDataValid(const uint8_t* data, size_t dataLen); + + /// @struct SerializedFields + /// Fields written by LLCLayer's serializeLayer(), in addition to + /// Layer::SerializedFields. + struct SerializedFields : Layer::SerializedFields + { + /// @return All field descriptors for LLCLayer + static std::vector all() + { + auto result = Layer::SerializedFields::all(); + std::initializer_list extra{ DSAP, SSAP, Control }; + std::copy(extra.begin(), extra.end(), std::back_inserter(result)); + return result; + } + + /// @brief Destination Service Access Point + static const FieldDescriptor DSAP; + + /// @brief Source Service Access Point + static const FieldDescriptor SSAP; + + /// @brief First byte of the LLC control field + static const FieldDescriptor Control; + }; + + protected: + void serializeLayer(ObjectScope& serializer) const override; }; } // namespace pcpp diff --git a/Packet++/header/MplsLayer.h b/Packet++/header/MplsLayer.h index 12ea1cd817..baba5c4dd8 100644 --- a/Packet++/header/MplsLayer.h +++ b/Packet++/header/MplsLayer.h @@ -115,6 +115,36 @@ namespace pcpp { return canReinterpretAs(data, dataLen); } + + /// @struct SerializedFields + /// Fields written by MplsLayer's serializeLayer(), in addition to + /// Layer::SerializedFields. + struct SerializedFields : Layer::SerializedFields + { + /// @return All field descriptors for MplsLayer + static std::vector all() + { + auto result = Layer::SerializedFields::all(); + std::initializer_list extra{ Label, TTL, IsBottomOfStack, ExperimentalUseValue }; + std::copy(extra.begin(), extra.end(), std::back_inserter(result)); + return result; + } + + /// @brief MPLS label + static const FieldDescriptor Label; + + /// @brief Time to live + static const FieldDescriptor TTL; + + /// @brief True if this is the last label in the stack (S bit) + static const FieldDescriptor IsBottomOfStack; + + /// @brief Experimental use / traffic class bits + static const FieldDescriptor ExperimentalUseValue; + }; + + protected: + void serializeLayer(ObjectScope& serializer) const override; }; } // namespace pcpp diff --git a/Packet++/header/NullLoopbackLayer.h b/Packet++/header/NullLoopbackLayer.h index 6c0e2ec261..a88b3b9e6c 100644 --- a/Packet++/header/NullLoopbackLayer.h +++ b/Packet++/header/NullLoopbackLayer.h @@ -87,5 +87,26 @@ namespace pcpp { return data != nullptr && dataLen >= sizeof(uint32_t); } + + /// @struct SerializedFields + /// Fields written by NullLoopbackLayer's serializeLayer(), in addition to + /// Layer::SerializedFields. + struct SerializedFields : Layer::SerializedFields + { + /// @return All field descriptors for NullLoopbackLayer + static std::vector all() + { + auto result = Layer::SerializedFields::all(); + std::initializer_list extra{ Family }; + std::copy(extra.begin(), extra.end(), std::back_inserter(result)); + return result; + } + + /// @brief Protocol family (AF_* value) of the payload + static const FieldDescriptor Family; + }; + + protected: + void serializeLayer(ObjectScope& serializer) const override; }; } // namespace pcpp diff --git a/Packet++/header/Sll2Layer.h b/Packet++/header/Sll2Layer.h index 83a55253c2..5cb67be784 100644 --- a/Packet++/header/Sll2Layer.h +++ b/Packet++/header/Sll2Layer.h @@ -147,6 +147,39 @@ namespace pcpp { return OsiModelDataLinkLayer; } - }; + /// @struct SerializedFields + /// Fields written by Sll2Layer's serializeLayer(), in addition to + /// Layer::SerializedFields. + struct SerializedFields : Layer::SerializedFields + { + /// @return All field descriptors for Sll2Layer + static std::vector all() + { + auto result = Layer::SerializedFields::all(); + std::initializer_list extra{ ProtocolType, InterfaceIndex, ArpHeaderType, PacketType, + LinkLayerAddress }; + std::copy(extra.begin(), extra.end(), std::back_inserter(result)); + return result; + } + + /// @brief EtherType of the encapsulated protocol, in host byte order + static const FieldDescriptor ProtocolType; + + /// @brief Index of the capture interface + static const FieldDescriptor InterfaceIndex; + + /// @brief ARPHRD_* link-layer address type (e.g. 1 for Ethernet) + static const FieldDescriptor ArpHeaderType; + + /// @brief Packet type + static const FieldDescriptor PacketType; + + /// @brief Link-layer address of the sender + static const FieldDescriptor LinkLayerAddress; + }; + + protected: + void serializeLayer(ObjectScope& serializer) const override; + }; } // namespace pcpp diff --git a/Packet++/header/SllLayer.h b/Packet++/header/SllLayer.h index a97b83e983..a1742468cc 100644 --- a/Packet++/header/SllLayer.h +++ b/Packet++/header/SllLayer.h @@ -88,6 +88,37 @@ namespace pcpp { return OsiModelDataLinkLayer; } + + /// @struct SerializedFields + /// Fields written by SllLayer's serializeLayer(), in addition to + /// Layer::SerializedFields. + struct SerializedFields : Layer::SerializedFields + { + /// @return All field descriptors for SllLayer + static std::vector all() + { + auto result = Layer::SerializedFields::all(); + std::initializer_list extra{ PacketType, ArpHeaderType, ProtocolType, + LinkLayerAddress }; + std::copy(extra.begin(), extra.end(), std::back_inserter(result)); + return result; + } + + /// @brief Packet type + static const FieldDescriptor PacketType; + + /// @brief ARPHRD_* link-layer address type (e.g. 1 for Ethernet) + static const FieldDescriptor ArpHeaderType; + + /// @brief EtherType of the encapsulated protocol, in host byte order + static const FieldDescriptor ProtocolType; + + /// @brief Link-layer address of the sender + static const FieldDescriptor LinkLayerAddress; + }; + + protected: + void serializeLayer(ObjectScope& serializer) const override; }; } // namespace pcpp diff --git a/Packet++/header/TpktLayer.h b/Packet++/header/TpktLayer.h index 073942ca54..74c33c4566 100644 --- a/Packet++/header/TpktLayer.h +++ b/Packet++/header/TpktLayer.h @@ -100,6 +100,27 @@ namespace pcpp return OsiModelTransportLayer; } + /// @struct SerializedFields + /// Fields written by TpktLayer's serializeLayer(), in addition to + /// Layer::SerializedFields. + struct SerializedFields : Layer::SerializedFields + { + /// @return All field descriptors for TpktLayer + static std::vector all() + { + auto result = Layer::SerializedFields::all(); + std::initializer_list extra{ Version }; + std::copy(extra.begin(), extra.end(), std::back_inserter(result)); + return result; + } + + /// @brief TPKT version + static const FieldDescriptor Version; + }; + + protected: + void serializeLayer(ObjectScope& serializer) const override; + private: /// Get a pointer to the TPKT header. Data can be retrieved through the /// other methods of this layer. Notice the return value points directly to the data, so every change will diff --git a/Packet++/header/VlanLayer.h b/Packet++/header/VlanLayer.h index 238d36bd1d..f90137de49 100644 --- a/Packet++/header/VlanLayer.h +++ b/Packet++/header/VlanLayer.h @@ -120,5 +120,35 @@ namespace pcpp { return canReinterpretAs(data, dataLen); } + + /// @struct SerializedFields + /// Fields written by VlanLayer's serializeLayer(), in addition to + /// Layer::SerializedFields. + struct SerializedFields : Layer::SerializedFields + { + /// @return All field descriptors for VlanLayer + static std::vector all() + { + auto result = Layer::SerializedFields::all(); + std::initializer_list extra{ VlanID, CFI, Priority, EtherType }; + std::copy(extra.begin(), extra.end(), std::back_inserter(result)); + return result; + } + + /// @brief VLAN identifier (12 bits) + static const FieldDescriptor VlanID; + + /// @brief Canonical Format Indicator / Drop Eligible Indicator bit + static const FieldDescriptor CFI; + + /// @brief Priority Code Point + static const FieldDescriptor Priority; + + /// @brief EtherType, in host byte order (e.g. 2048 for IPv4) + static const FieldDescriptor EtherType; + }; + + protected: + void serializeLayer(ObjectScope& serializer) const override; }; } // namespace pcpp diff --git a/Packet++/header/VxlanLayer.h b/Packet++/header/VxlanLayer.h index e872c4ee00..3df5056a26 100644 --- a/Packet++/header/VxlanLayer.h +++ b/Packet++/header/VxlanLayer.h @@ -142,5 +142,32 @@ namespace pcpp { return OsiModelDataLinkLayer; } + + /// @struct SerializedFields + /// Fields written by VxlanLayer's serializeLayer(), in addition to + /// Layer::SerializedFields. + struct SerializedFields : Layer::SerializedFields + { + /// @return All field descriptors for VxlanLayer + static std::vector all() + { + auto result = Layer::SerializedFields::all(); + std::initializer_list extra{ ValidVNI, GroupPolicyID, VNI }; + std::copy(extra.begin(), extra.end(), std::back_inserter(result)); + return result; + } + + /// @brief True if the "valid VNI" flag (I bit) is set + static const FieldDescriptor ValidVNI; + + /// @brief Group Policy ID (VXLAN-GBP extension) + static const FieldDescriptor GroupPolicyID; + + /// @brief VXLAN Network Identifier (24 bits) + static const FieldDescriptor VNI; + }; + + protected: + void serializeLayer(ObjectScope& serializer) const override; }; } // namespace pcpp diff --git a/Packet++/header/WakeOnLanLayer.h b/Packet++/header/WakeOnLanLayer.h index 3e98acc46a..ff33d4e89a 100644 --- a/Packet++/header/WakeOnLanLayer.h +++ b/Packet++/header/WakeOnLanLayer.h @@ -137,5 +137,29 @@ namespace pcpp /// @return Returns the protocol info as readable string std::string toString() const override; + + /// @struct SerializedFields + /// Fields written by WakeOnLanLayer's serializeLayer(), in addition to + /// Layer::SerializedFields. + struct SerializedFields : Layer::SerializedFields + { + /// @return All field descriptors for WakeOnLanLayer + static std::vector all() + { + auto result = Layer::SerializedFields::all(); + std::initializer_list extra{ TargetAddress, Password }; + std::copy(extra.begin(), extra.end(), std::back_inserter(result)); + return result; + } + + /// @brief Target MAC address that the magic packet wakes, as a string + static const FieldDescriptor TargetAddress; + + /// @brief Optional SecureOn password, if present + static const FieldDescriptor Password; + }; + + protected: + void serializeLayer(ObjectScope& serializer) const override; }; } // namespace pcpp diff --git a/Packet++/src/EthDot3Layer.cpp b/Packet++/src/EthDot3Layer.cpp index 498ca4e588..24e0f9a3d7 100644 --- a/Packet++/src/EthDot3Layer.cpp +++ b/Packet++/src/EthDot3Layer.cpp @@ -52,4 +52,15 @@ namespace pcpp return false; } } + + const FieldDescriptor EthDot3Layer::SerializedFields::SrcMacAddress{ Layer::SerializedFields::MaxID + 1, + "srcMacAddress" }; + const FieldDescriptor EthDot3Layer::SerializedFields::DstMacAddress{ Layer::SerializedFields::MaxID + 2, + "dstMacAddress" }; + + void EthDot3Layer::serializeLayer(ObjectScope& serializer) const + { + serializer.writeField(SerializedFields::SrcMacAddress, getSourceMac().toString()); + serializer.writeField(SerializedFields::DstMacAddress, getDestMac().toString()); + } } // namespace pcpp diff --git a/Packet++/src/LLCLayer.cpp b/Packet++/src/LLCLayer.cpp index d7c0df9df7..1ccb8f076a 100644 --- a/Packet++/src/LLCLayer.cpp +++ b/Packet++/src/LLCLayer.cpp @@ -51,4 +51,15 @@ namespace pcpp return dataLen >= sizeof(llc_header) && !(data[0] == 0xFF && data[1] == 0xFF); } + const FieldDescriptor LLCLayer::SerializedFields::DSAP{ Layer::SerializedFields::MaxID + 1, "dsap" }; + const FieldDescriptor LLCLayer::SerializedFields::SSAP{ Layer::SerializedFields::MaxID + 2, "ssap" }; + const FieldDescriptor LLCLayer::SerializedFields::Control{ Layer::SerializedFields::MaxID + 3, "control" }; + + void LLCLayer::serializeLayer(ObjectScope& serializer) const + { + auto* header = getLlcHeader(); + serializer.writeField(SerializedFields::DSAP, header->dsap); + serializer.writeField(SerializedFields::SSAP, header->ssap); + serializer.writeField(SerializedFields::Control, header->control); + } } // namespace pcpp diff --git a/Packet++/src/MplsLayer.cpp b/Packet++/src/MplsLayer.cpp index 2c009e209e..f28e7f5f62 100644 --- a/Packet++/src/MplsLayer.cpp +++ b/Packet++/src/MplsLayer.cpp @@ -150,4 +150,19 @@ namespace pcpp ", Bottom of stack: " + bottomOfStack; } + const FieldDescriptor MplsLayer::SerializedFields::Label{ Layer::SerializedFields::MaxID + 1, "label" }; + const FieldDescriptor MplsLayer::SerializedFields::TTL{ Layer::SerializedFields::MaxID + 2, "ttl" }; + const FieldDescriptor MplsLayer::SerializedFields::IsBottomOfStack{ Layer::SerializedFields::MaxID + 3, + "isBottomOfStack" }; + + const FieldDescriptor MplsLayer::SerializedFields::ExperimentalUseValue{ Layer::SerializedFields::MaxID + 4, + "experimentalUseValue" }; + + void MplsLayer::serializeLayer(ObjectScope& serializer) const + { + serializer.writeField(SerializedFields::Label, getMplsLabel()); + serializer.writeField(SerializedFields::TTL, getTTL()); + serializer.writeField(SerializedFields::IsBottomOfStack, isBottomOfStack()); + serializer.writeField(SerializedFields::ExperimentalUseValue, getExperimentalUseValue()); + } } // namespace pcpp diff --git a/Packet++/src/NullLoopbackLayer.cpp b/Packet++/src/NullLoopbackLayer.cpp index 5139df25b1..a6bcde787c 100644 --- a/Packet++/src/NullLoopbackLayer.cpp +++ b/Packet++/src/NullLoopbackLayer.cpp @@ -103,4 +103,11 @@ namespace pcpp return "Null/Loopback"; } + const FieldDescriptor NullLoopbackLayer::SerializedFields::Family{ Layer::SerializedFields::MaxID + 1, "family" }; + + void NullLoopbackLayer::serializeLayer(ObjectScope& serializer) const + { + serializer.writeField(SerializedFields::Family, getFamily()); + } + } // namespace pcpp diff --git a/Packet++/src/Sll2Layer.cpp b/Packet++/src/Sll2Layer.cpp index 2f1e2ad6dc..131a96fb81 100644 --- a/Packet++/src/Sll2Layer.cpp +++ b/Packet++/src/Sll2Layer.cpp @@ -11,6 +11,7 @@ #include "MplsLayer.h" #include "LLCLayer.h" #include "EndianPortable.h" +#include "GeneralUtils.h" namespace pcpp { @@ -208,4 +209,25 @@ namespace pcpp return getSll2Header()->link_layer_addr; } + const FieldDescriptor Sll2Layer::SerializedFields::ProtocolType{ Layer::SerializedFields::MaxID + 1, + "protocolType" }; + const FieldDescriptor Sll2Layer::SerializedFields::InterfaceIndex{ Layer::SerializedFields::MaxID + 2, + "interfaceIndex" }; + const FieldDescriptor Sll2Layer::SerializedFields::ArpHeaderType{ Layer::SerializedFields::MaxID + 3, + "arpHeaderType" }; + const FieldDescriptor Sll2Layer::SerializedFields::PacketType{ Layer::SerializedFields::MaxID + 4, "packetType" }; + const FieldDescriptor Sll2Layer::SerializedFields::LinkLayerAddress{ Layer::SerializedFields::MaxID + 5, + "linkLayerAddress" }; + + void Sll2Layer::serializeLayer(ObjectScope& serializer) const + { + auto* header = getSll2Header(); + serializer.writeField(SerializedFields::ProtocolType, be16toh(header->protocol_type)); + serializer.writeField(SerializedFields::InterfaceIndex, be32toh(header->interface_index)); + serializer.writeField(SerializedFields::ArpHeaderType, be16toh(header->ARPHRD_type)); + serializer.writeField(SerializedFields::PacketType, be16toh(header->packet_type)); + auto linkLayerAddrLen = (std::min)(be16toh(header->link_layer_addr_len), static_cast(8)); + serializer.writeField(SerializedFields::LinkLayerAddress, + byteArrayToHexString(header->link_layer_addr, linkLayerAddrLen)); + } } // namespace pcpp diff --git a/Packet++/src/SllLayer.cpp b/Packet++/src/SllLayer.cpp index 782c45a029..1e06c51a5c 100644 --- a/Packet++/src/SllLayer.cpp +++ b/Packet++/src/SllLayer.cpp @@ -10,6 +10,7 @@ #include "PPPoELayer.h" #include "MplsLayer.h" #include "EndianPortable.h" +#include "GeneralUtils.h" namespace pcpp { @@ -131,4 +132,23 @@ namespace pcpp return "Linux cooked header"; } + const FieldDescriptor SllLayer::SerializedFields::PacketType{ Layer::SerializedFields::MaxID + 1, "packetType" }; + const FieldDescriptor SllLayer::SerializedFields::ArpHeaderType{ Layer::SerializedFields::MaxID + 2, + "arpHeaderType" }; + const FieldDescriptor SllLayer::SerializedFields::ProtocolType{ Layer::SerializedFields::MaxID + 3, + "protocolType" }; + const FieldDescriptor SllLayer::SerializedFields::LinkLayerAddress{ Layer::SerializedFields::MaxID + 4, + "linkLayerAddress" }; + + void SllLayer::serializeLayer(ObjectScope& serializer) const + { + auto* header = getSllHeader(); + serializer.writeField(SerializedFields::PacketType, be16toh(header->packet_type)); + serializer.writeField(SerializedFields::ArpHeaderType, be16toh(header->ARPHRD_type)); + serializer.writeField(SerializedFields::ProtocolType, be16toh(header->protocol_type)); + auto linkLayerAddrLen = (std::min)(be16toh(header->link_layer_addr_len), static_cast(8)); + serializer.writeField(SerializedFields::LinkLayerAddress, + byteArrayToHexString(header->link_layer_addr, linkLayerAddrLen)); + } + } // namespace pcpp diff --git a/Packet++/src/TpktLayer.cpp b/Packet++/src/TpktLayer.cpp index 8a9e20fdf8..cc792e2c4a 100644 --- a/Packet++/src/TpktLayer.cpp +++ b/Packet++/src/TpktLayer.cpp @@ -65,4 +65,10 @@ namespace pcpp tryConstructNextLayerWithFallback(payload, payloadLen); } + const FieldDescriptor TpktLayer::SerializedFields::Version{ Layer::SerializedFields::MaxID + 1, "version" }; + + void TpktLayer::serializeLayer(ObjectScope& serializer) const + { + serializer.writeField(SerializedFields::Version, getTpktHeader()->version); + } } // namespace pcpp diff --git a/Packet++/src/VlanLayer.cpp b/Packet++/src/VlanLayer.cpp index 81457ac3ba..5e5707f02b 100644 --- a/Packet++/src/VlanLayer.cpp +++ b/Packet++/src/VlanLayer.cpp @@ -155,4 +155,17 @@ namespace pcpp ", CFI: " + cfiStream.str(); } + const FieldDescriptor VlanLayer::SerializedFields::VlanID{ Layer::SerializedFields::MaxID + 1, "vlanID" }; + const FieldDescriptor VlanLayer::SerializedFields::CFI{ Layer::SerializedFields::MaxID + 2, "cfi" }; + const FieldDescriptor VlanLayer::SerializedFields::Priority{ Layer::SerializedFields::MaxID + 3, "priority" }; + + const FieldDescriptor VlanLayer::SerializedFields::EtherType{ Layer::SerializedFields::MaxID + 4, "etherType" }; + + void VlanLayer::serializeLayer(ObjectScope& serializer) const + { + serializer.writeField(SerializedFields::VlanID, getVlanID()); + serializer.writeField(SerializedFields::CFI, getCFI()); + serializer.writeField(SerializedFields::Priority, getPriority()); + serializer.writeField(SerializedFields::EtherType, be16toh(getVlanHeader()->etherType)); + } } // namespace pcpp diff --git a/Packet++/src/VxlanLayer.cpp b/Packet++/src/VxlanLayer.cpp index b217de6ccc..b7c154387c 100644 --- a/Packet++/src/VxlanLayer.cpp +++ b/Packet++/src/VxlanLayer.cpp @@ -57,4 +57,16 @@ namespace pcpp tryConstructNextLayerWithFallback(payload, payloadLen); } + const FieldDescriptor VxlanLayer::SerializedFields::ValidVNI{ Layer::SerializedFields::MaxID + 1, "validVNI" }; + const FieldDescriptor VxlanLayer::SerializedFields::GroupPolicyID{ Layer::SerializedFields::MaxID + 2, + "groupPolicyID" }; + const FieldDescriptor VxlanLayer::SerializedFields::VNI{ Layer::SerializedFields::MaxID + 3, "vni" }; + + void VxlanLayer::serializeLayer(ObjectScope& serializer) const + { + auto* header = getVxlanHeader(); + serializer.writeField(SerializedFields::ValidVNI, header->vniPresentFlag ? true : false); + serializer.writeField(SerializedFields::GroupPolicyID, be16toh(header->groupPolicyID)); + serializer.writeField(SerializedFields::VNI, getVNI()); + } } // namespace pcpp diff --git a/Packet++/src/WakeOnLanLayer.cpp b/Packet++/src/WakeOnLanLayer.cpp index 5b58ee00a9..0710c5e10b 100644 --- a/Packet++/src/WakeOnLanLayer.cpp +++ b/Packet++/src/WakeOnLanLayer.cpp @@ -131,4 +131,13 @@ namespace pcpp return "Wake On LAN Layer, target address: " + getTargetAddr().toString(); } + const FieldDescriptor WakeOnLanLayer::SerializedFields::TargetAddress{ Layer::SerializedFields::MaxID + 1, + "targetAddress" }; + const FieldDescriptor WakeOnLanLayer::SerializedFields::Password{ Layer::SerializedFields::MaxID + 2, "password" }; + + void WakeOnLanLayer::serializeLayer(ObjectScope& serializer) const + { + serializer.writeField(SerializedFields::TargetAddress, getTargetAddr().toString()); + serializer.writeField(SerializedFields::Password, getPassword()); + } } // namespace pcpp diff --git a/Tests/Packet++Test/Tests/EthAndArpTests.cpp b/Tests/Packet++Test/Tests/EthAndArpTests.cpp index 1dc968a72c..0e9698386d 100644 --- a/Tests/Packet++Test/Tests/EthAndArpTests.cpp +++ b/Tests/Packet++Test/Tests/EthAndArpTests.cpp @@ -274,6 +274,15 @@ PTF_TEST_CASE(EthDot3LayerParsingTest) PTF_ASSERT_NOT_NULL(ethDot3Layer->getNextLayer()); PTF_ASSERT_EQUAL(ethDot3Layer->getNextLayer()->getProtocol(), pcpp::LLC, enum); + + { + std::ostringstream oss; + pcpp::JsonSerializer serializer(oss); + ethDot3Layer->serialize(serializer); + PTF_ASSERT_EQUAL( + oss.str(), + R"({"protocolName":"EthernetDot3","protocolId":33,"length":14,"srcMacAddress":"00:13:f7:11:5e:db","dstMacAddress":"01:80:c2:00:00:00"})"); + } } // EthDot3LayerParsingTest PTF_TEST_CASE(EthDot3LayerCreateEditTest) diff --git a/Tests/Packet++Test/Tests/LLCTests.cpp b/Tests/Packet++Test/Tests/LLCTests.cpp index 73671e9bee..94822c5619 100644 --- a/Tests/Packet++Test/Tests/LLCTests.cpp +++ b/Tests/Packet++Test/Tests/LLCTests.cpp @@ -29,6 +29,14 @@ PTF_TEST_CASE(LLCParsingTests) PTF_ASSERT_EQUAL(llcLayer1->toString(), "Logical Link Control"); + { + std::ostringstream oss; + pcpp::JsonSerializer serializer(oss); + llcLayer1->serialize(serializer); + PTF_ASSERT_EQUAL(oss.str(), + R"({"protocolName":"LLC","protocolId":44,"length":3,"dsap":66,"ssap":66,"control":3})"); + } + auto rawPacket2 = createPacketFromHexResource("PacketExamples/llc_vlan.dat"); pcpp::Packet llcPacket2(rawPacket2.get()); pcpp::LLCLayer* llcLayer2 = llcPacket2.getLayerOfType(); diff --git a/Tests/Packet++Test/Tests/Sll2Tests.cpp b/Tests/Packet++Test/Tests/Sll2Tests.cpp index bd475c06dd..8000433275 100644 --- a/Tests/Packet++Test/Tests/Sll2Tests.cpp +++ b/Tests/Packet++Test/Tests/Sll2Tests.cpp @@ -40,6 +40,14 @@ PTF_TEST_CASE(Sll2PacketParsingTest) pcpp::MacAddress macAddrRef("d2:cf:c2:50:15:ea"); PTF_ASSERT_EQUAL(macAddrRef, macAddrFromPacket); PTF_ASSERT_EQUAL(macAddrRef, sll2Layer->getLinkLayerAsMacAddress()); + { + std::ostringstream oss; + pcpp::JsonSerializer serializer(oss); + sll2Layer->serialize(serializer); + PTF_ASSERT_EQUAL( + oss.str(), + R"({"protocolName":"SLL2","protocolId":52,"length":20,"protocolType":2048,"interfaceIndex":20,"arpHeaderType":1,"packetType":1024,"linkLayerAddress":"d2cfc25015ea0000"})"); + } } // Sll2PacketParsingTest PTF_TEST_CASE(Sll2ParseLLCTest) diff --git a/Tests/Packet++Test/Tests/SllNullLoopbackTests.cpp b/Tests/Packet++Test/Tests/SllNullLoopbackTests.cpp index c89f6b78e9..d01cb64e70 100644 --- a/Tests/Packet++Test/Tests/SllNullLoopbackTests.cpp +++ b/Tests/Packet++Test/Tests/SllNullLoopbackTests.cpp @@ -40,6 +40,14 @@ PTF_TEST_CASE(SllPacketParsingTest) pcpp::MacAddress macAddrRef("00:12:44:1e:74:00"); PTF_ASSERT_EQUAL(macAddrRef, macAddrFromPacket); PTF_ASSERT_EQUAL(sllLayer->getSllHeader()->protocol_type, htobe16(PCPP_ETHERTYPE_IPV6)); + { + std::ostringstream oss; + pcpp::JsonSerializer serializer(oss); + sllLayer->serialize(serializer); + PTF_ASSERT_EQUAL( + oss.str(), + R"({"protocolName":"SLL","protocolId":19,"length":16,"packetType":0,"arpHeaderType":1,"protocolType":34525,"linkLayerAddress":"0012441e7400"})"); + } } // SllPacketParsingTest PTF_TEST_CASE(SllPacketCreationTest) @@ -111,6 +119,12 @@ PTF_TEST_CASE(NullLoopbackTest) PTF_ASSERT_NOT_NULL(nextLayer); PTF_ASSERT_EQUAL(nextLayer->getProtocol(), pcpp::IPv6, enum); PTF_ASSERT_EQUAL(nullLoopbackLayer->getFamily(), PCPP_BSD_AF_INET6_DARWIN); + { + std::ostringstream oss; + pcpp::JsonSerializer serializer(oss); + nullLoopbackLayer->serialize(serializer); + PTF_ASSERT_EQUAL(oss.str(), R"({"protocolName":"NULL_LOOPBACK","protocolId":21,"length":4,"family":30})"); + } PTF_ASSERT_TRUE(nullPacket2.isPacketOfType(pcpp::NULL_LOOPBACK)); nullLoopbackLayer = nullPacket2.getLayerOfType(); diff --git a/Tests/Packet++Test/Tests/TpktTests.cpp b/Tests/Packet++Test/Tests/TpktTests.cpp index 57101d9d10..5af7e8681c 100644 --- a/Tests/Packet++Test/Tests/TpktTests.cpp +++ b/Tests/Packet++Test/Tests/TpktTests.cpp @@ -26,6 +26,13 @@ PTF_TEST_CASE(TpktLayerTest) PTF_ASSERT_EQUAL(tpktLayer->toString(), "TPKT Layer, version: 3, length: 607"); + { + std::ostringstream oss; + pcpp::JsonSerializer serializer(oss); + tpktLayer->serialize(serializer); + PTF_ASSERT_EQUAL(oss.str(), R"({"protocolName":"TPKT","protocolId":48,"length":4,"version":3})"); + } + pcpp::TpktLayer tpktLayerTest((uint8_t)8, (uint16_t)605); PTF_ASSERT_EQUAL(tpktLayerTest.getVersion(), 8); PTF_ASSERT_EQUAL(tpktLayerTest.getLength(), 605); diff --git a/Tests/Packet++Test/Tests/VlanMplsTests.cpp b/Tests/Packet++Test/Tests/VlanMplsTests.cpp index 2fbe359d21..b8706a4521 100644 --- a/Tests/Packet++Test/Tests/VlanMplsTests.cpp +++ b/Tests/Packet++Test/Tests/VlanMplsTests.cpp @@ -49,6 +49,14 @@ PTF_TEST_CASE(VlanParseAndCreation) PTF_ASSERT_EQUAL(secondVlanLayerPtr->getVlanID(), 200); PTF_ASSERT_EQUAL(secondVlanLayerPtr->getCFI(), 0); PTF_ASSERT_EQUAL(secondVlanLayerPtr->getPriority(), 2); + { + std::ostringstream oss; + pcpp::JsonSerializer serializer(oss); + secondVlanLayerPtr->serialize(serializer); + PTF_ASSERT_EQUAL( + oss.str(), + R"({"protocolName":"VLAN","protocolId":9,"length":4,"vlanID":200,"cfi":0,"priority":2,"etherType":2054})"); + } pcpp::MacAddress macSrc("ca:03:0d:b4:00:1c"); pcpp::MacAddress macDest("ff:ff:ff:ff:ff:ff"); @@ -111,6 +119,14 @@ PTF_TEST_CASE(MplsLayerTest) PTF_ASSERT_TRUE(mplsLayer->isBottomOfStack()); PTF_ASSERT_EQUAL(mplsLayer->getExperimentalUseValue(), 0); PTF_ASSERT_EQUAL(mplsLayer->getMplsLabel(), 16000); + { + std::ostringstream oss; + pcpp::JsonSerializer serializer(oss); + mplsLayer->serialize(serializer); + PTF_ASSERT_EQUAL( + oss.str(), + R"({"protocolName":"MPLS","protocolId":14,"length":4,"label":16000,"ttl":126,"isBottomOfStack":true,"experimentalUseValue":0})"); + } PTF_ASSERT_NOT_NULL(mplsLayer->getNextLayer()); PTF_ASSERT_EQUAL(mplsLayer->getNextLayer()->getProtocol(), pcpp::IPv4, enum); @@ -225,6 +241,15 @@ PTF_TEST_CASE(VxlanParsingAndCreationTest) PTF_ASSERT_NOT_NULL(vxlanLayer->getNextLayer()); PTF_ASSERT_EQUAL(vxlanLayer->getNextLayer()->getProtocol(), pcpp::Ethernet, enum); + { + std::ostringstream oss; + pcpp::JsonSerializer serializer(oss); + vxlanLayer->serialize(serializer); + PTF_ASSERT_EQUAL( + oss.str(), + R"({"protocolName":"VXLAN","protocolId":26,"length":8,"validVNI":true,"groupPolicyID":100,"vni":3000001})"); + } + // edit vxlan fields vxlanLayer->getVxlanHeader()->gbpFlag = 0; vxlanLayer->getVxlanHeader()->dontLearnFlag = 0; diff --git a/Tests/Packet++Test/Tests/WakeOnLanTests.cpp b/Tests/Packet++Test/Tests/WakeOnLanTests.cpp index 4b8e5796db..987b1fd01b 100644 --- a/Tests/Packet++Test/Tests/WakeOnLanTests.cpp +++ b/Tests/Packet++Test/Tests/WakeOnLanTests.cpp @@ -25,6 +25,15 @@ PTF_TEST_CASE(WakeOnLanParsingTests) PTF_ASSERT_EQUAL(wolLayer1->getPassword(), "192.168.1.1"); PTF_ASSERT_EQUAL(wolLayer1->toString(), "Wake On LAN Layer, target address: 00:0d:56:dc:9e:35"); + { + std::ostringstream oss; + pcpp::JsonSerializer serializer(oss); + wolLayer1->serialize(serializer); + PTF_ASSERT_EQUAL( + oss.str(), + R"({"protocolName":"WakeOnLan","protocolId":46,"length":106,"targetAddress":"00:0d:56:dc:9e:35","password":"192.168.1.1"})"); + } + auto rawPacket2 = createPacketFromHexResource("PacketExamples/WoL_udp.dat"); pcpp::Packet wolPacket2(rawPacket2.get());