diff --git a/rules/decoder-events.rules b/rules/decoder-events.rules index bb6b00533f..ffa017c249 100644 --- a/rules/decoder-events.rules +++ b/rules/decoder-events.rules @@ -97,6 +97,7 @@ alert pkthdr any any -> any any (msg:"SURICATA VLAN header too small "; decode-e alert pkthdr any any -> any any (msg:"SURICATA VLAN unknown type"; decode-event:vlan.unknown_type; classtype:protocol-command-decode; sid:2200067; rev:2;) # more than 2 vlan layers in the packet alert pkthdr any any -> any any (msg:"SURICATA VLAN too many layers"; decode-event:vlan.too_many_layers; classtype:protocol-command-decode; sid:2200091; rev:2;) +alert pkthdr any any -> any any (msg:"SURICATA IEEE802.1AH header too small"; decode-event:ieee8021ah.header_too_small; classtype:protocol-command-decode; sid:2200112; rev:1;) alert pkthdr any any -> any any (msg:"SURICATA IP raw invalid IP version "; decode-event:ipraw.invalid_ip_version; classtype:protocol-command-decode; sid:2200068; rev:2;) alert pkthdr any any -> any any (msg:"SURICATA FRAG IPv4 Packet size too large"; decode-event:ipv4.frag_pkt_too_large; classtype:protocol-command-decode; sid:2200069; rev:3;) @@ -141,5 +142,5 @@ alert pkthdr any any -> any any (msg:"SURICATA ERSPAN too many vlan layers"; dec # Cisco Fabric Path/DCE alert pkthdr any any -> any any (msg:"SURICATA DCE packet too small"; decode-event:dce.pkt_too_small; classtype:protocol-command-decode; sid:2200110; rev:2;) -# next sid is 2200112 +# next sid is 2200113 diff --git a/src/decode-ethernet.h b/src/decode-ethernet.h index 7008ebc08d..b61c5d7d0e 100644 --- a/src/decode-ethernet.h +++ b/src/decode-ethernet.h @@ -41,6 +41,7 @@ #define ETHERNET_TYPE_PPPOE_DISC 0x8863 /* discovery stage */ #define ETHERNET_TYPE_PPPOE_SESS 0x8864 /* session stage */ #define ETHERNET_TYPE_8021AD 0x88a8 +#define ETHERNET_TYPE_8021AH 0x88e7 #define ETHERNET_TYPE_8021Q 0x8100 #define ETHERNET_TYPE_LOOP 0x9000 #define ETHERNET_TYPE_8021QINQ 0x9100 diff --git a/src/decode-events.c b/src/decode-events.c index e6b330a76c..9d08284f5f 100644 --- a/src/decode-events.c +++ b/src/decode-events.c @@ -140,6 +140,7 @@ const struct DecodeEvents_ DEvents[] = { { "decoder.vlan.header_too_small",VLAN_HEADER_TOO_SMALL, }, { "decoder.vlan.unknown_type",VLAN_UNKNOWN_TYPE, }, { "decoder.vlan.too_many_layers", VLAN_HEADER_TOO_MANY_LAYERS, }, + { "decoder.ieee8021ah.header_too_small", IEEE8021AH_HEADER_TOO_SMALL, }, /* RAW EVENTS */ { "decoder.ipraw.invalid_ip_version",IPRAW_INVALID_IPV, }, diff --git a/src/decode-events.h b/src/decode-events.h index 9330b2bd2e..c899c901f0 100644 --- a/src/decode-events.h +++ b/src/decode-events.h @@ -145,6 +145,8 @@ enum { VLAN_UNKNOWN_TYPE, /**< vlan unknown type */ VLAN_HEADER_TOO_MANY_LAYERS, + IEEE8021AH_HEADER_TOO_SMALL, + /* RAW EVENTS */ IPRAW_INVALID_IPV, /**< invalid ip version in ip raw */ diff --git a/src/decode-vlan.c b/src/decode-vlan.c index dc07a68519..70096a416e 100644 --- a/src/decode-vlan.c +++ b/src/decode-vlan.c @@ -44,6 +44,9 @@ #include "util-profiling.h" #include "host.h" +static int DecodeIEEE8021ah(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, + uint8_t *pkt, uint16_t len, PacketQueue *pq); + /** * \internal * \brief this function is used to decode IEEE802.1q packets @@ -117,6 +120,10 @@ int DecodeVLAN(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, u len - VLAN_HEADER_LEN, pq); } break; + case ETHERNET_TYPE_8021AH: + DecodeIEEE8021ah(tv, dtv, p, pkt + VLAN_HEADER_LEN, + len - VLAN_HEADER_LEN, pq); + break; default: SCLogDebug("unknown VLAN type: %" PRIx32 "", proto); ENGINE_SET_INVALID_EVENT(p, VLAN_UNKNOWN_TYPE); @@ -139,6 +146,38 @@ uint16_t DecodeVLANGetId(const Packet *p, uint8_t layer) return 0; } +typedef struct IEEE8021ahHdr_ { + uint32_t flags; + uint8_t c_destination[6]; + uint8_t c_source[6]; + uint16_t type; /**< next protocol */ +} __attribute__((__packed__)) IEEE8021ahHdr; + +#define IEEE8021AH_HEADER_LEN sizeof(IEEE8021ahHdr) + +static int DecodeIEEE8021ah(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t len, PacketQueue *pq) +{ + StatsIncr(tv, dtv->counter_ieee8021ah); + + if (len < IEEE8021AH_HEADER_LEN) { + ENGINE_SET_INVALID_EVENT(p, IEEE8021AH_HEADER_TOO_SMALL); + return TM_ECODE_FAILED; + } + + IEEE8021ahHdr *hdr = (IEEE8021ahHdr *)pkt; + uint16_t next_proto = ntohs(hdr->type); + + switch (next_proto) { + case ETHERNET_TYPE_VLAN: + case ETHERNET_TYPE_8021QINQ: { + DecodeVLAN(tv, dtv, p, pkt + IEEE8021AH_HEADER_LEN, + len - IEEE8021AH_HEADER_LEN, pq); + break; + } + } + return TM_ECODE_OK; +} + #ifdef UNITTESTS /** \todo Must GRE+VLAN and Multi-Vlan packets to * create more tests diff --git a/src/decode.c b/src/decode.c index 85d0ca9915..30dd8cee3a 100644 --- a/src/decode.c +++ b/src/decode.c @@ -422,6 +422,7 @@ void DecodeRegisterPerfCounters(DecodeThreadVars *dtv, ThreadVars *tv) dtv->counter_gre = StatsRegisterCounter("decoder.gre", tv); dtv->counter_vlan = StatsRegisterCounter("decoder.vlan", tv); dtv->counter_vlan_qinq = StatsRegisterCounter("decoder.vlan_qinq", tv); + dtv->counter_ieee8021ah = StatsRegisterCounter("decoder.ieee8021ah", tv); dtv->counter_teredo = StatsRegisterCounter("decoder.teredo", tv); dtv->counter_ipv4inipv6 = StatsRegisterCounter("decoder.ipv4_in_ipv6", tv); dtv->counter_ipv6inipv6 = StatsRegisterCounter("decoder.ipv6_in_ipv6", tv); diff --git a/src/decode.h b/src/decode.h index 4c0eeee7d5..16c54a28b0 100644 --- a/src/decode.h +++ b/src/decode.h @@ -655,6 +655,7 @@ typedef struct DecodeThreadVars_ uint16_t counter_gre; uint16_t counter_vlan; uint16_t counter_vlan_qinq; + uint16_t counter_ieee8021ah; uint16_t counter_pppoe; uint16_t counter_teredo; uint16_t counter_mpls;