diff --git a/include/tins/constants.h b/include/tins/constants.h index a20cd0a..169ca92 100644 --- a/include/tins/constants.h +++ b/include/tins/constants.h @@ -75,20 +75,22 @@ struct IP { struct Ethernet { enum e { UNKNOWN = 0, - SPRITE = 0x0500, // Sprite - IP = 0x0800, // IP - ARP = 0x0806, // Address resolution - MPLS = 0x8847, // MPLS - REVARP = 0x8035, // Reverse ARP - AT = 0x809B, // AppleTalk protocol - AARP = 0x80F3, // AppleTalk ARP - VLAN = 0x8100, // IEEE 802.1Q VLAN tagging - IPX = 0x8137, // IPX - IPV6 = 0x86dd, // IP protocol version 6 - PPPOED = 0x8863, // PPPoE Discovery - PPPOES = 0x8864, // PPPoE Session - EAPOL = 0x888e, // EAPOL - LOOPBACK = 0x9000 // used to test interfaces + SPRITE = 0x0500, // Sprite + IP = 0x0800, // IP + ARP = 0x0806, // Address resolution + MPLS = 0x8847, // MPLS + REVARP = 0x8035, // Reverse ARP + AT = 0x809B, // AppleTalk protocol + AARP = 0x80F3, // AppleTalk ARP + VLAN = 0x8100, // IEEE 802.1Q VLAN tagging + QINQ = 0x88a8, // IEEE 802.1ad VLAN tagging + OLD_QINQ = 0x9100, // IEEE 802.1ad VLAN tagging (old, deprecated, value) + IPX = 0x8137, // IPX + IPV6 = 0x86dd, // IP protocol version 6 + PPPOED = 0x8863, // PPPoE Discovery + PPPOES = 0x8864, // PPPoE Session + EAPOL = 0x888e, // EAPOL + LOOPBACK = 0x9000 // used to test interfaces }; }; diff --git a/src/dot1q.cpp b/src/dot1q.cpp index f243bab..585a666 100644 --- a/src/dot1q.cpp +++ b/src/dot1q.cpp @@ -101,10 +101,15 @@ uint32_t Dot1Q::trailer_size() const { void Dot1Q::write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU *) { OutputMemoryStream stream(buffer, total_sz); if (inner_pdu()) { - // Set the appropriate payload type flag - Constants::Ethernet::e flag = Internals::pdu_flag_to_ether_type( - inner_pdu()->pdu_type() - ); + Constants::Ethernet::e flag; + PDUType type = inner_pdu()->pdu_type(); + if (type == PDU::DOT1Q) { + flag = Constants::Ethernet::QINQ; + } + else { + // Set the appropriate payload type flag + flag = Internals::pdu_flag_to_ether_type(type); + } payload_type(static_cast(flag)); } stream.write(header_); diff --git a/src/internals.cpp b/src/internals.cpp index bc5704f..6571d9f 100644 --- a/src/internals.cpp +++ b/src/internals.cpp @@ -106,6 +106,8 @@ Tins::PDU* pdu_from_flag(Constants::Ethernet::e flag, case Tins::Constants::Ethernet::EAPOL: return EAPOL::from_bytes(buffer, size); case Tins::Constants::Ethernet::VLAN: + case Tins::Constants::Ethernet::QINQ: + case Tins::Constants::Ethernet::OLD_QINQ: return new Dot1Q(buffer, size); case Tins::Constants::Ethernet::MPLS: return new MPLS(buffer, size); diff --git a/tests/src/dot1q.cpp b/tests/src/dot1q.cpp index 2b496c7..e6ac20c 100644 --- a/tests/src/dot1q.cpp +++ b/tests/src/dot1q.cpp @@ -4,6 +4,9 @@ #include #include "dot1q.h" #include "arp.h" +#include "ip.h" +#include "tcp.h" +#include "rawpdu.h" #include "ethernetII.h" using namespace std; @@ -21,7 +24,6 @@ const uint8_t Dot1QTest::expected_packet[] = { 123, 8, 6, 0, 1, 8, 0, 6, 4, 0, 2, 0, 25, 6, 234, 184, 193, 192, 168, 123, 1, 255, 255, 255, 255, 255, 255, 192, 168, 123, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }; TEST_F(Dot1QTest, DefaultConstructor) { @@ -79,3 +81,15 @@ TEST_F(Dot1QTest, Id) { dot1.id(3543); EXPECT_EQ(3543, dot1.id()); } + +TEST_F(Dot1QTest, QinQ) { + EthernetII pkt = EthernetII() / Dot1Q(10) / Dot1Q(42) / IP("192.168.1.2") / + TCP(23, 45) / RawPDU("asdasdasd"); + PDU::serialization_type buffer = pkt.serialize(); + EthernetII pkt2(&buffer[0], buffer.size()); + const Dot1Q& q1 = pkt2.rfind_pdu(); + ASSERT_TRUE(q1.inner_pdu() != NULL); + const Dot1Q& q2 = q1.inner_pdu()->rfind_pdu(); + EXPECT_EQ(10, q1.id()); + EXPECT_EQ(42, q2.id()); +}