From: Victor Julien Date: Thu, 13 Feb 2020 20:43:30 +0000 (+0100) Subject: decode/hdlc: initial support X-Git-Tag: suricata-6.0.0-beta1~536 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=328a94206eeabdd306cf129d896e7af0ba53a275;p=thirdparty%2Fsuricata.git decode/hdlc: initial support --- diff --git a/rules/decoder-events.rules b/rules/decoder-events.rules index 6518a17500..d5e001f9c7 100644 --- a/rules/decoder-events.rules +++ b/rules/decoder-events.rules @@ -143,5 +143,8 @@ 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 2200114 +# Cisco HDLC +alert pkthdr any any -> any any (msg:"SURICATA CHDLC packet too small"; decode-event:chdlc.pkt_too_small; classtype:protocol-command-decode; sid:2200115; rev:1;) + +# next sid is 2200116 diff --git a/src/Makefile.am b/src/Makefile.am index c47012c346..0e9acce524 100755 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -63,6 +63,7 @@ datasets-string.c datasets-string.h \ datasets-sha256.c datasets-sha256.h \ datasets-md5.c datasets-md5.h \ decode.c decode.h \ +decode-chdlc.c decode-chdlc.h \ decode-erspan.c decode-erspan.h \ decode-ethernet.c decode-ethernet.h \ decode-events.c decode-events.h \ diff --git a/src/decode-chdlc.c b/src/decode-chdlc.c new file mode 100644 index 0000000000..6ecb6b44ba --- /dev/null +++ b/src/decode-chdlc.c @@ -0,0 +1,111 @@ +/* Copyright (C) 2020 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 + * + * Decode Cisco HDLC + */ + +#include "suricata-common.h" +#include "decode.h" +#include "decode-chdlc.h" +#include "decode-events.h" + +#include "util-unittest.h" +#include "util-debug.h" + +int DecodeCHDLC(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, + const uint8_t *pkt, uint32_t len) +{ + StatsIncr(tv, dtv->counter_chdlc); + + if (unlikely(len < CHDLC_HEADER_LEN)) { + ENGINE_SET_INVALID_EVENT(p, CHDLC_PKT_TOO_SMALL); + return TM_ECODE_FAILED; + } + + if (unlikely(len > CHDLC_HEADER_LEN + USHRT_MAX)) { + return TM_ECODE_FAILED; + } + + CHDLCHdr *hdr = (CHDLCHdr *)pkt; + if (unlikely(hdr == NULL)) + return TM_ECODE_FAILED; + + SCLogDebug("p %p pkt %p ether type %04x", p, pkt, SCNtohs(hdr->protocol)); + + DecodeNetworkLayer(tv, dtv, SCNtohs(hdr->protocol), p, + pkt + CHDLC_HEADER_LEN, len - CHDLC_HEADER_LEN); + + return TM_ECODE_OK; +} + +#ifdef UNITTESTS +static int DecodeCHDLCTest01 (void) +{ + uint8_t raw[] = { 0x0f,0x00,0x08,0x00, // HDLC + 0x45,0x00,0x00,0x30,0x15,0x5a,0x40,0x00,0x80,0x06, + 0x6c,0xd0,0xc0,0xa8,0x02,0x07,0x41,0x37,0x74,0xb7, + 0x13,0x4a,0x00,0x50,0x9c,0x34,0x09,0x6c,0x00,0x00, + 0x00,0x00,0x70,0x02,0x40,0x00,0x11,0x47,0x00,0x00, + 0x02,0x04,0x05,0xb4,0x01,0x01,0x04,0x02 }; + + Packet *p = SCMalloc(SIZE_OF_PACKET); + if (unlikely(p == NULL)) + return 0; + ThreadVars tv; + DecodeThreadVars dtv; + + memset(&dtv, 0, sizeof(DecodeThreadVars)); + memset(&tv, 0, sizeof(ThreadVars)); + memset(p, 0, SIZE_OF_PACKET); + + DecodeCHDLC(&tv, &dtv, p, raw, sizeof(raw)); + + FAIL_IF_NOT(PKT_IS_IPV4(p)); + FAIL_IF_NOT(PKT_IS_TCP(p)); + FAIL_IF_NOT(p->dp == 80); + + SCFree(p); + PASS; +} +#endif /* UNITTESTS */ + + +/** + * \brief Registers Ethernet unit tests + * \todo More Ethernet tests + */ +void DecodeCHDLCRegisterTests(void) +{ +#ifdef UNITTESTS + UtRegisterTest("DecodeCHDLCTest01", DecodeCHDLCTest01); +#endif /* UNITTESTS */ +} +/** + * @} + */ diff --git a/src/decode-chdlc.h b/src/decode-chdlc.h new file mode 100644 index 0000000000..47e0d7c1a3 --- /dev/null +++ b/src/decode-chdlc.h @@ -0,0 +1,37 @@ +/* Copyright (C) 2020 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_CHDLC_H__ +#define __DECODE_CHDLC_H__ + +#define CHDLC_HEADER_LEN 4 + +typedef struct CHDLCHdr_ { + uint8_t address; + uint8_t control; + uint16_t protocol; +} CHDLCHdr; + +void DecodeCHDLCRegisterTests(void); + +#endif /* __DECODE_CHDLC_H__ */ diff --git a/src/decode-events.c b/src/decode-events.c index 7bb48deef8..62412d6204 100644 --- a/src/decode-events.c +++ b/src/decode-events.c @@ -184,6 +184,9 @@ const struct DecodeEvents_ DEvents[] = { /* Cisco Fabric Path/DCE events. */ { "decoder.dce.pkt_too_small", DCE_PKT_TOO_SMALL, }, + /* Cisco HDLC events. */ + { "decoder.chdlc.pkt_too_small", CHDLC_PKT_TOO_SMALL, }, + /* STREAM EVENTS */ { "stream.3whs_ack_in_wrong_dir", STREAM_3WHS_ACK_IN_WRONG_DIR, }, { "stream.3whs_async_wrong_seq", STREAM_3WHS_ASYNC_WRONG_SEQ, }, diff --git a/src/decode-events.h b/src/decode-events.h index b9cceb6793..f0f55276b9 100644 --- a/src/decode-events.h +++ b/src/decode-events.h @@ -191,8 +191,11 @@ enum { /* Cisco Fabric Path/DCE events. */ DCE_PKT_TOO_SMALL, + /* Cisco HDLC events. */ + CHDLC_PKT_TOO_SMALL, + /* END OF DECODE EVENTS ON SINGLE PACKET */ - DECODE_EVENT_PACKET_MAX = DCE_PKT_TOO_SMALL, + DECODE_EVENT_PACKET_MAX = CHDLC_PKT_TOO_SMALL, /* STREAM EVENTS */ STREAM_3WHS_ACK_IN_WRONG_DIR, diff --git a/src/decode.c b/src/decode.c index f406bb42f7..323679d3a9 100644 --- a/src/decode.c +++ b/src/decode.c @@ -483,6 +483,7 @@ void DecodeRegisterPerfCounters(DecodeThreadVars *dtv, ThreadVars *tv) dtv->counter_ipv4 = StatsRegisterCounter("decoder.ipv4", tv); dtv->counter_ipv6 = StatsRegisterCounter("decoder.ipv6", tv); dtv->counter_eth = StatsRegisterCounter("decoder.ethernet", tv); + dtv->counter_chdlc = StatsRegisterCounter("decoder.chdlc", tv); dtv->counter_raw = StatsRegisterCounter("decoder.raw", tv); dtv->counter_null = StatsRegisterCounter("decoder.null", tv); dtv->counter_sll = StatsRegisterCounter("decoder.sll", tv); diff --git a/src/decode.h b/src/decode.h index d703f30ca8..2b5c41cc3b 100644 --- a/src/decode.h +++ b/src/decode.h @@ -74,6 +74,7 @@ enum PktSrcEnum { #include "decode-erspan.h" #include "decode-ethernet.h" +#include "decode-chdlc.h" #include "decode-gre.h" #include "decode-ppp.h" #include "decode-pppoe.h" @@ -633,6 +634,7 @@ typedef struct DecodeThreadVars_ uint16_t counter_invalid; uint16_t counter_eth; + uint16_t counter_chdlc; uint16_t counter_ipv4; uint16_t counter_ipv6; uint16_t counter_tcp; @@ -935,6 +937,7 @@ int DecodeVXLAN(ThreadVars *, DecodeThreadVars *, Packet *, const uint8_t *, uin int DecodeMPLS(ThreadVars *, DecodeThreadVars *, Packet *, const uint8_t *, uint32_t); int DecodeERSPAN(ThreadVars *, DecodeThreadVars *, Packet *, const uint8_t *, uint32_t); int DecodeERSPANTypeI(ThreadVars *, DecodeThreadVars *, Packet *, const uint8_t *, uint32_t); +int DecodeCHDLC(ThreadVars *, DecodeThreadVars *, Packet *, const uint8_t *, uint32_t); int DecodeTEMPLATE(ThreadVars *, DecodeThreadVars *, Packet *, const uint8_t *, uint32_t); #ifdef UNITTESTS @@ -1039,6 +1042,10 @@ void DecodeUnregisterCounters(void); #define DLT_EN10MB 1 #endif +#ifndef DLT_C_HDLC +#define DLT_C_HDLC 104 +#endif + /* taken from pcap's bpf.h */ #ifndef DLT_RAW #ifdef __OpenBSD__ @@ -1064,6 +1071,7 @@ void DecodeUnregisterCounters(void); #define LINKTYPE_RAW2 101 #define LINKTYPE_IPV4 228 #define LINKTYPE_GRE_OVER_IP 778 +#define LINKTYPE_CISCO_HDLC DLT_C_HDLC #define PPP_OVER_GRE 11 #define VLAN_OVER_GRE 13 @@ -1171,6 +1179,9 @@ static inline void DecodeLinkLayer(ThreadVars *tv, DecodeThreadVars *dtv, case LINKTYPE_NULL: DecodeNull(tv, dtv, p, data, len); break; + case LINKTYPE_CISCO_HDLC: + DecodeCHDLC(tv, dtv, p, data, len); + break; default: SCLogError(SC_ERR_DATALINK_UNIMPLEMENTED, "datalink type " "%"PRId32" not yet supported", datalink); diff --git a/src/runmode-unittests.c b/src/runmode-unittests.c index 792e6f5c8d..7632dbfec2 100644 --- a/src/runmode-unittests.c +++ b/src/runmode-unittests.c @@ -146,6 +146,7 @@ static void RegisterUnittests(void) IPPairBitRegisterTests(); StatsRegisterTests(); DecodeEthernetRegisterTests(); + DecodeCHDLCRegisterTests(); DecodePPPRegisterTests(); DecodeVLANRegisterTests(); DecodeVXLANRegisterTests(); diff --git a/src/source-pcap-file-helper.c b/src/source-pcap-file-helper.c index cbf4650b1d..558af5c541 100644 --- a/src/source-pcap-file-helper.c +++ b/src/source-pcap-file-helper.c @@ -253,6 +253,9 @@ TmEcode ValidateLinkType(int datalink, DecoderFunc *DecoderFn) case LINKTYPE_NULL: *DecoderFn = DecodeNull; break; + case LINKTYPE_CISCO_HDLC: + *DecoderFn = DecodeCHDLC; + break; default: SCLogError(SC_ERR_UNIMPLEMENTED,