From: Victor Julien Date: Wed, 20 May 2015 21:01:22 +0000 (+0200) Subject: decode: add ERSPANv1 decoder X-Git-Tag: suricata-3.0RC1~331 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=928957f0a39a8ead06935b2b37e6f593659a1f09;p=thirdparty%2Fsuricata.git decode: add ERSPANv1 decoder Only allow v1 to be parsed as thats what is tested. Take vlan_id from the ERSPAN layer. --- diff --git a/rules/decoder-events.rules b/rules/decoder-events.rules index dc74a8160b..314c0f9268 100644 --- a/rules/decoder-events.rules +++ b/rules/decoder-events.rules @@ -128,5 +128,11 @@ alert pkthdr any any -> any any (msg:"SURICATA NULL pkt too small"; decode-event # packet has type not supported by Suricata's decoders alert pkthdr any any -> any any (msg:"SURICATA NULL unsupported type"; decode-event:ltnull.unsupported_type; sid: 2200104; rev:1;) -# next sid is 2200105 +# ERSPAN +alert pkthdr any any -> any any (msg:"SURICATA ERSPAN pkt too small"; decode-event:erspan.header_too_small; sid: 2200105; rev:1;) +# packet has type not supported by Suricata's decoders +alert pkthdr any any -> any any (msg:"SURICATA ERSPAN unsupported version"; decode-event:erspan.unsupported_version; sid: 2200106; rev:1;) +alert pkthdr any any -> any any (msg:"SURICATA ERSPAN too many vlan layers"; decode-event:erspan.too_many_vlan_layers; sid: 2200107; rev:1;) + +# next sid is 2200108 diff --git a/src/Makefile.am b/src/Makefile.am index d682b62cc4..8193384277 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -41,6 +41,7 @@ conf-yaml-loader.c conf-yaml-loader.h \ counters.c counters.h \ data-queue.c data-queue.h \ decode.c decode.h \ +decode-erspan.c decode-erspan.h \ decode-ethernet.c decode-ethernet.h \ decode-events.c decode-events.h \ decode-gre.c decode-gre.h \ diff --git a/src/decode-erspan.c b/src/decode-erspan.c new file mode 100644 index 0000000000..9325f6b81f --- /dev/null +++ b/src/decode-erspan.c @@ -0,0 +1,78 @@ +/* Copyright (C) 2015 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 + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/** + * \ingroup decode + * + * @{ + */ + + +/** + * \file + * + * \author Victor Julien + * + * Decodes ERSPAN + */ + +#include "suricata-common.h" +#include "suricata.h" +#include "decode.h" +#include "decode-events.h" +#include "decode-erspan.h" + +#include "util-unittest.h" +#include "util-debug.h" + +/** + * \brief Function to decode ERSPAN packets + */ + +int DecodeERSPAN(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t len, PacketQueue *pq) +{ + if (len < sizeof(ErspanHdr)) { + ENGINE_SET_EVENT(p,ERSPAN_HEADER_TOO_SMALL); + return TM_ECODE_FAILED; + } + + const ErspanHdr *ehdr = (const ErspanHdr *)pkt; + uint16_t version = ntohs(ehdr->ver_vlan) >> 12; + uint16_t vlan_id = ntohs(ehdr->ver_vlan) & 0x0fff; + + SCLogDebug("ERSPAN: version %u vlan %u", version, vlan_id); + + /* only v1 is tested at this time */ + if (version != 1) { + ENGINE_SET_EVENT(p,ERSPAN_UNSUPPORTED_VERSION); + return TM_ECODE_FAILED; + } + + if (vlan_id > 0) { + if (p->vlan_idx >= 2) { + ENGINE_SET_EVENT(p,ERSPAN_TOO_MANY_VLAN_LAYERS); + return TM_ECODE_FAILED; + } + p->vlan_id[p->vlan_idx++] = vlan_id; + } + + return DecodeEthernet(tv, dtv, p, pkt + sizeof(ErspanHdr), len - sizeof(ErspanHdr), pq); +} + +/** + * @} + */ diff --git a/src/decode-erspan.h b/src/decode-erspan.h new file mode 100644 index 0000000000..2f81d1e4a3 --- /dev/null +++ b/src/decode-erspan.h @@ -0,0 +1,37 @@ +/* Copyright (C) 2007-2010 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 + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/** + * \file + * + * \author Victor Julien + * + */ + +#ifndef __DECODE_ERSPAN_H__ +#define __DECODE_ERSPAN_H__ + +#include "decode.h" +#include "threadvars.h" + +typedef struct ErspanHdr_ { + uint16_t ver_vlan; + uint16_t flags_spanid; + uint32_t padding; +} __attribute__((__packed__)) ErspanHdr; + +#endif /* __DECODE_ERSPAN_H__ */ diff --git a/src/decode-ethernet.h b/src/decode-ethernet.h index 2a6f86e936..f8ede8803f 100644 --- a/src/decode-ethernet.h +++ b/src/decode-ethernet.h @@ -40,6 +40,7 @@ #define ETHERNET_TYPE_8021Q 0x8100 #define ETHERNET_TYPE_LOOP 0x9000 #define ETHERNET_TYPE_8021QINQ 0x9100 +#define ETHERNET_TYPE_ERSPAN 0x88BE typedef struct EthernetHdr_ { uint8_t eth_dst[6]; diff --git a/src/decode-events.h b/src/decode-events.h index 7ad23d9f72..c16d0d92d6 100644 --- a/src/decode-events.h +++ b/src/decode-events.h @@ -240,6 +240,11 @@ enum { MPLS_BAD_LABEL_RESERVED, MPLS_UNKNOWN_PAYLOAD_TYPE, + /* ERSPAN events */ + ERSPAN_HEADER_TOO_SMALL, + ERSPAN_UNSUPPORTED_VERSION, + ERSPAN_TOO_MANY_VLAN_LAYERS, + /* should always be last! */ DECODE_EVENT_MAX, }; diff --git a/src/decode-gre.c b/src/decode-gre.c index f827cabe88..6ad9e39758 100644 --- a/src/decode-gre.c +++ b/src/decode-gre.c @@ -249,6 +249,19 @@ int DecodeGRE(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, ui break; } + case ETHERNET_TYPE_ERSPAN: + { + if (pq != NULL) { + Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len, + len - header_len, DECODE_TUNNEL_ERSPAN, pq); + if (tp != NULL) { + PKT_SET_SRC(tp, PKT_SRC_DECODER_GRE); + PacketEnqueue(pq,tp); + } + } + break; + } + default: return TM_ECODE_OK; } diff --git a/src/decode.c b/src/decode.c index ca96ee0adf..49896d8efc 100644 --- a/src/decode.c +++ b/src/decode.c @@ -80,6 +80,8 @@ int DecodeTunnel(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, return DecodeVLAN(tv, dtv, p, pkt, len, pq); case DECODE_TUNNEL_ETHERNET: return DecodeEthernet(tv, dtv, p, pkt, len, pq); + case DECODE_TUNNEL_ERSPAN: + return DecodeERSPAN(tv, dtv, p, pkt, len, pq); default: SCLogInfo("FIXME: DecodeTunnel: protocol %" PRIu32 " not supported.", proto); break; diff --git a/src/decode.h b/src/decode.h index 830b3b360a..1c02a3ede9 100644 --- a/src/decode.h +++ b/src/decode.h @@ -65,6 +65,7 @@ enum PktSrcEnum { #include "action-globals.h" +#include "decode-erspan.h" #include "decode-ethernet.h" #include "decode-gre.h" #include "decode-ppp.h" @@ -831,6 +832,7 @@ typedef struct DecodeThreadVars_ enum DecodeTunnelProto { DECODE_TUNNEL_ETHERNET, + DECODE_TUNNEL_ERSPAN, DECODE_TUNNEL_VLAN, DECODE_TUNNEL_IPV4, DECODE_TUNNEL_IPV6, @@ -875,6 +877,7 @@ int DecodeSCTP(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint16_t, int DecodeGRE(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint16_t, PacketQueue *); int DecodeVLAN(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint16_t, PacketQueue *); int DecodeMPLS(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint16_t, PacketQueue *); +int DecodeERSPAN(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint16_t, PacketQueue *); void AddressDebugPrint(Address *); diff --git a/src/detect-engine-event.h b/src/detect-engine-event.h index 5d51d6834d..9d6424fbdb 100644 --- a/src/detect-engine-event.h +++ b/src/detect-engine-event.h @@ -243,6 +243,11 @@ struct DetectEngineEvents_ { { "mpls.bad_label_reserved", MPLS_BAD_LABEL_RESERVED, }, { "mpls.unknown_payload_type", MPLS_UNKNOWN_PAYLOAD_TYPE, }, + /* ERSPAN events */ + { "erspan.header_too_small", ERSPAN_HEADER_TOO_SMALL, }, + { "erspan.unsupported_version", ERSPAN_UNSUPPORTED_VERSION, }, + { "erspan.too_many_vlan_layers", ERSPAN_TOO_MANY_VLAN_LAYERS, }, + { NULL, 0 }, }; #endif /* DETECT_EVENTS */