|
|
|
|
@ -1,4 +1,4 @@
|
|
|
|
|
/* Copyright (C) 2007-2021 Open Information Security Foundation
|
|
|
|
|
/* Copyright (C) 2007-2026 Open Information Security Foundation
|
|
|
|
|
*
|
|
|
|
|
* You can copy, redistribute or modify this Program under the terms of
|
|
|
|
|
* the GNU General Public License version 2 as published by the Free
|
|
|
|
|
@ -165,6 +165,136 @@ static int DecodeEthernetTestDceNextTooSmall(void)
|
|
|
|
|
PASS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief decode a frame with an unhandled ethertype and check the
|
|
|
|
|
* ethertype DecodeGetUnknownEthertype() reports for it
|
|
|
|
|
*/
|
|
|
|
|
static int DecodeEthernetUnknownEthertypeCheck(
|
|
|
|
|
int datalink, const uint8_t *raw, uint32_t len, uint16_t expected)
|
|
|
|
|
{
|
|
|
|
|
Packet *p = PacketGetFromAlloc();
|
|
|
|
|
FAIL_IF_NULL(p);
|
|
|
|
|
ThreadVars tv;
|
|
|
|
|
DecodeThreadVars dtv;
|
|
|
|
|
|
|
|
|
|
memset(&dtv, 0, sizeof(DecodeThreadVars));
|
|
|
|
|
memset(&tv, 0, sizeof(ThreadVars));
|
|
|
|
|
|
|
|
|
|
FAIL_IF(PacketCopyData(p, raw, len) != 0);
|
|
|
|
|
p->datalink = datalink;
|
|
|
|
|
DecodeLinkLayer(&tv, &dtv, datalink, p, GET_PKT_DATA(p), GET_PKT_LEN(p));
|
|
|
|
|
|
|
|
|
|
FAIL_IF_NOT(ENGINE_ISSET_EVENT(p, ETHERNET_UNKNOWN_ETHERTYPE));
|
|
|
|
|
uint16_t ethertype = 0;
|
|
|
|
|
FAIL_IF_NOT(DecodeGetUnknownEthertype(p, ðertype));
|
|
|
|
|
FAIL_IF(ethertype != expected);
|
|
|
|
|
|
|
|
|
|
PacketFree(p);
|
|
|
|
|
PASS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** \test untagged frame: the unknown ethertype is the ethernet type */
|
|
|
|
|
static int DecodeEthernetTestUnknownEthertype(void)
|
|
|
|
|
{
|
|
|
|
|
/* MACs, RARP ethertype, RARP payload */
|
|
|
|
|
const uint8_t raw[] = { 0x00, 0x10, 0x94, 0x55, 0x00, 0x01, 0x00, 0x10, 0x94, 0x56, 0x00, 0x01,
|
|
|
|
|
0x80, 0x35, 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x03 };
|
|
|
|
|
return DecodeEthernetUnknownEthertypeCheck(LINKTYPE_ETHERNET, raw, sizeof(raw), 0x8035);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** \test QinQ frame: the unknown ethertype follows the inner VLAN tag */
|
|
|
|
|
static int DecodeEthernetTestUnknownEthertypeQinQ(void)
|
|
|
|
|
{
|
|
|
|
|
/* MACs, 802.1ad, outer tag (VID 100, next 802.1Q), inner tag (VID 200,
|
|
|
|
|
* next RARP), RARP payload */
|
|
|
|
|
const uint8_t raw[] = { 0x00, 0x10, 0x94, 0x55, 0x00, 0x01, 0x00, 0x10, 0x94, 0x56, 0x00, 0x01,
|
|
|
|
|
0x88, 0xa8, 0x00, 0x64, 0x81, 0x00, 0x00, 0xc8, 0x80, 0x35, 0x00, 0x01, 0x08, 0x00, 0x06,
|
|
|
|
|
0x04, 0x00, 0x03 };
|
|
|
|
|
return DecodeEthernetUnknownEthertypeCheck(LINKTYPE_ETHERNET, raw, sizeof(raw), 0x8035);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** \test 802.1ah frame: the unknown ethertype follows the customer MACs */
|
|
|
|
|
static int DecodeEthernetTestUnknownEthertype8021ah(void)
|
|
|
|
|
{
|
|
|
|
|
/* MACs, 802.1ah, flags, customer MACs, RARP ethertype, RARP payload */
|
|
|
|
|
const uint8_t raw[] = { 0x00, 0x10, 0x94, 0x55, 0x00, 0x01, 0x00, 0x10, 0x94, 0x56, 0x00, 0x01,
|
|
|
|
|
0x88, 0xe7, 0x00, 0x00, 0x00, 0x01, 0x00, 0x10, 0x94, 0x57, 0x00, 0x01, 0x00, 0x10, 0x94,
|
|
|
|
|
0x58, 0x00, 0x01, 0x80, 0x35, 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x03 };
|
|
|
|
|
return DecodeEthernetUnknownEthertypeCheck(LINKTYPE_ETHERNET, raw, sizeof(raw), 0x8035);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** \test SLL frame without an ethernet header: the unknown ethertype
|
|
|
|
|
* follows a VLAN tag after the SLL protocol field */
|
|
|
|
|
static int DecodeEthernetTestUnknownEthertypeSll(void)
|
|
|
|
|
{
|
|
|
|
|
/* SLL packet type, ARPHRD type, address length, address, protocol 802.1Q,
|
|
|
|
|
* tag (VID 100, next RARP), RARP payload */
|
|
|
|
|
const uint8_t raw[] = { 0x00, 0x00, 0x00, 0x01, 0x00, 0x06, 0x00, 0x10, 0x94, 0x55, 0x00, 0x01,
|
|
|
|
|
0x00, 0x00, 0x81, 0x00, 0x00, 0x64, 0x80, 0x35, 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00,
|
|
|
|
|
0x03 };
|
|
|
|
|
return DecodeEthernetUnknownEthertypeCheck(LINKTYPE_LINUX_SLL, raw, sizeof(raw), 0x8035);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** \test SLL2 frame: the SLL2 protocol is the first field of its header,
|
|
|
|
|
* so the VLAN tag starts after the whole header, not after that field */
|
|
|
|
|
static int DecodeEthernetTestUnknownEthertypeSll2(void)
|
|
|
|
|
{
|
|
|
|
|
/* protocol 802.1Q, reserved, ifindex, ARPHRD type, packet type, address
|
|
|
|
|
* length, address, tag (VID 100, next RARP), RARP payload */
|
|
|
|
|
const uint8_t raw[] = { 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x06,
|
|
|
|
|
0x00, 0x10, 0x94, 0x55, 0x00, 0x01, 0x00, 0x00, 0x00, 0x64, 0x80, 0x35, 0x00, 0x01, 0x08,
|
|
|
|
|
0x00, 0x06, 0x04, 0x00, 0x03 };
|
|
|
|
|
return DecodeEthernetUnknownEthertypeCheck(LINKTYPE_LINUX_SLL2, raw, sizeof(raw), 0x8035);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** \test Cisco HDLC frame: the unknown ethertype is the HDLC protocol */
|
|
|
|
|
static int DecodeEthernetTestUnknownEthertypeCHDLC(void)
|
|
|
|
|
{
|
|
|
|
|
/* address, control, RARP protocol, RARP payload */
|
|
|
|
|
const uint8_t raw[] = { 0x0f, 0x00, 0x80, 0x35, 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00,
|
|
|
|
|
0x03 };
|
|
|
|
|
return DecodeEthernetUnknownEthertypeCheck(LINKTYPE_CISCO_HDLC, raw, sizeof(raw), 0x8035);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** \test DCE frame: the unknown ethertype is in the inner ethernet header,
|
|
|
|
|
* not the outer DCE ethertype */
|
|
|
|
|
static int DecodeEthernetTestUnknownEthertypeDce(void)
|
|
|
|
|
{
|
|
|
|
|
/* MACs, DCE, 2 DCE bytes, inner MACs, RARP ethertype, RARP payload */
|
|
|
|
|
const uint8_t raw[] = { 0x00, 0x10, 0x94, 0x55, 0x00, 0x01, 0x00, 0x10, 0x94, 0x56, 0x00, 0x01,
|
|
|
|
|
0x89, 0x03, 0x00, 0x00, 0x00, 0x10, 0x94, 0x55, 0x00, 0x01, 0x00, 0x10, 0x94, 0x56, 0x00,
|
|
|
|
|
0x01, 0x80, 0x35, 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x03 };
|
|
|
|
|
return DecodeEthernetUnknownEthertypeCheck(LINKTYPE_ETHERNET, raw, sizeof(raw), 0x8035);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** \test frame cut off inside a VLAN tag: no unknown ethertype event, and
|
|
|
|
|
* the lookup stops at the end of the packet instead of reading past it */
|
|
|
|
|
static int DecodeEthernetTestUnknownEthertypeTruncated(void)
|
|
|
|
|
{
|
|
|
|
|
/* macs, 802.1Q, first half of the tag */
|
|
|
|
|
const uint8_t raw[] = { 0x00, 0x10, 0x94, 0x55, 0x00, 0x01, 0x00, 0x10, 0x94, 0x56, 0x00, 0x01,
|
|
|
|
|
0x81, 0x00, 0x00, 0x64 };
|
|
|
|
|
Packet *p = PacketGetFromAlloc();
|
|
|
|
|
FAIL_IF_NULL(p);
|
|
|
|
|
ThreadVars tv;
|
|
|
|
|
DecodeThreadVars dtv;
|
|
|
|
|
|
|
|
|
|
memset(&dtv, 0, sizeof(DecodeThreadVars));
|
|
|
|
|
memset(&tv, 0, sizeof(ThreadVars));
|
|
|
|
|
|
|
|
|
|
FAIL_IF(PacketCopyData(p, raw, sizeof(raw)) != 0);
|
|
|
|
|
p->datalink = LINKTYPE_ETHERNET;
|
|
|
|
|
DecodeEthernet(&tv, &dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p));
|
|
|
|
|
|
|
|
|
|
FAIL_IF_NOT(ENGINE_ISSET_EVENT(p, VLAN_HEADER_TOO_SMALL));
|
|
|
|
|
FAIL_IF(ENGINE_ISSET_EVENT(p, ETHERNET_UNKNOWN_ETHERTYPE));
|
|
|
|
|
uint16_t ethertype = 0;
|
|
|
|
|
FAIL_IF(DecodeGetUnknownEthertype(p, ðertype));
|
|
|
|
|
|
|
|
|
|
PacketFree(p);
|
|
|
|
|
PASS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif /* UNITTESTS */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -180,6 +310,19 @@ void DecodeEthernetRegisterTests(void)
|
|
|
|
|
DecodeEthernetTestDceNextTooSmall);
|
|
|
|
|
UtRegisterTest("DecodeEthernetTestDceTooSmall",
|
|
|
|
|
DecodeEthernetTestDceTooSmall);
|
|
|
|
|
UtRegisterTest("DecodeEthernetTestUnknownEthertype", DecodeEthernetTestUnknownEthertype);
|
|
|
|
|
UtRegisterTest(
|
|
|
|
|
"DecodeEthernetTestUnknownEthertypeQinQ", DecodeEthernetTestUnknownEthertypeQinQ);
|
|
|
|
|
UtRegisterTest(
|
|
|
|
|
"DecodeEthernetTestUnknownEthertype8021ah", DecodeEthernetTestUnknownEthertype8021ah);
|
|
|
|
|
UtRegisterTest("DecodeEthernetTestUnknownEthertypeSll", DecodeEthernetTestUnknownEthertypeSll);
|
|
|
|
|
UtRegisterTest(
|
|
|
|
|
"DecodeEthernetTestUnknownEthertypeSll2", DecodeEthernetTestUnknownEthertypeSll2);
|
|
|
|
|
UtRegisterTest(
|
|
|
|
|
"DecodeEthernetTestUnknownEthertypeCHDLC", DecodeEthernetTestUnknownEthertypeCHDLC);
|
|
|
|
|
UtRegisterTest("DecodeEthernetTestUnknownEthertypeDce", DecodeEthernetTestUnknownEthertypeDce);
|
|
|
|
|
UtRegisterTest("DecodeEthernetTestUnknownEthertypeTruncated",
|
|
|
|
|
DecodeEthernetTestUnknownEthertypeTruncated);
|
|
|
|
|
#endif /* UNITTESTS */
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
|