]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
decode/hdlc: initial support
authorVictor Julien <victor@inliniac.net>
Thu, 13 Feb 2020 20:43:30 +0000 (21:43 +0100)
committerVictor Julien <victor@inliniac.net>
Fri, 10 Apr 2020 11:53:22 +0000 (13:53 +0200)
rules/decoder-events.rules
src/Makefile.am
src/decode-chdlc.c [new file with mode: 0644]
src/decode-chdlc.h [new file with mode: 0644]
src/decode-events.c
src/decode-events.h
src/decode.c
src/decode.h
src/runmode-unittests.c
src/source-pcap-file-helper.c

index 6518a17500de3e8305282babdd607d613474daf4..d5e001f9c71299c66e2343e45f3e5c2fe73b04e7 100644 (file)
@@ -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
 
index c47012c346c0c4a5da0f8232b84330fd9ab1bc07..0e9acce524b2048d98ffbd595233c80831d041de 100755 (executable)
@@ -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 (file)
index 0000000..6ecb6b4
--- /dev/null
@@ -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 <victor@inliniac.net>
+ *
+ * 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 (file)
index 0000000..47e0d7c
--- /dev/null
@@ -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 <victor@inliniac.net>
+ */
+
+#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__ */
index 7bb48deef848400fff5d2959130abf47cdd35c5c..62412d620438e3ba0e21f8dffafb8cf794cf96ea 100644 (file)
@@ -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, },
index b9cceb679395ea4f2291d4807781cf1de59c871b..f0f55276b9d02dcb3a848a8cb7c50d47dde42ad7 100644 (file)
@@ -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,
index f406bb42f70eb4a5d77bf8057e20539ffd453b53..323679d3a9a5414452e57f4e4af12acaa96849fd 100644 (file)
@@ -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);
index d703f30ca8f7820422527cb3634ce0659bf0d7f4..2b5c41cc3b4a40d3ed676afffcdc8a95c23d96a3 100644 (file)
@@ -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);
index 792e6f5c8d470145426da856711e74416a770dcd..7632dbfec2752caed80647345b2aa9ef37d780e4 100644 (file)
@@ -146,6 +146,7 @@ static void RegisterUnittests(void)
     IPPairBitRegisterTests();
     StatsRegisterTests();
     DecodeEthernetRegisterTests();
+    DecodeCHDLCRegisterTests();
     DecodePPPRegisterTests();
     DecodeVLANRegisterTests();
     DecodeVXLANRegisterTests();
index cbf4650b1dbadd84564a636beda1cb3225553df7..558af5c54172ed5b73df510619e7ac8afdaa9eb6 100644 (file)
@@ -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,