]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
decode: single network layer entrypoint
authorVictor Julien <victor@inliniac.net>
Wed, 26 Feb 2020 13:06:26 +0000 (14:06 +0100)
committerVictor Julien <victor@inliniac.net>
Fri, 10 Apr 2020 11:53:22 +0000 (13:53 +0200)
This way new layers can be added in a single place.

src/decode-ethernet.c
src/decode-sll.c
src/decode-vlan.c
src/decode.h

index 911538ceb4c1e27b8b9e8d8b1d56f4e98d86ffe9..e46c09cd5f2c00304982928359f143bd5fdd7bfa 100644 (file)
@@ -48,59 +48,14 @@ int DecodeEthernet(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p,
         return TM_ECODE_FAILED;
     }
 
-    if (unlikely(len > ETHERNET_HEADER_LEN + USHRT_MAX)) {
-        return TM_ECODE_FAILED;
-    }
-
     p->ethh = (EthernetHdr *)pkt;
     if (unlikely(p->ethh == NULL))
         return TM_ECODE_FAILED;
 
     SCLogDebug("p %p pkt %p ether type %04x", p, pkt, SCNtohs(p->ethh->eth_type));
 
-    switch (SCNtohs(p->ethh->eth_type)) {
-        case ETHERNET_TYPE_IP:
-            //printf("DecodeEthernet ip4\n");
-            DecodeIPV4(tv, dtv, p, pkt + ETHERNET_HEADER_LEN,
-                       len - ETHERNET_HEADER_LEN);
-            break;
-        case ETHERNET_TYPE_IPV6:
-            //printf("DecodeEthernet ip6\n");
-            DecodeIPV6(tv, dtv, p, pkt + ETHERNET_HEADER_LEN,
-                       len - ETHERNET_HEADER_LEN);
-            break;
-        case ETHERNET_TYPE_PPPOE_SESS:
-            //printf("DecodeEthernet PPPOE Session\n");
-            DecodePPPOESession(tv, dtv, p, pkt + ETHERNET_HEADER_LEN,
-                               len - ETHERNET_HEADER_LEN);
-            break;
-        case ETHERNET_TYPE_PPPOE_DISC:
-            //printf("DecodeEthernet PPPOE Discovery\n");
-            DecodePPPOEDiscovery(tv, dtv, p, pkt + ETHERNET_HEADER_LEN,
-                                 len - ETHERNET_HEADER_LEN);
-            break;
-        case ETHERNET_TYPE_VLAN:
-        case ETHERNET_TYPE_8021QINQ:
-            DecodeVLAN(tv, dtv, p, pkt + ETHERNET_HEADER_LEN,
-                                 len - ETHERNET_HEADER_LEN);
-            break;
-        case ETHERNET_TYPE_MPLS_UNICAST:
-        case ETHERNET_TYPE_MPLS_MULTICAST:
-            DecodeMPLS(tv, dtv, p, pkt + ETHERNET_HEADER_LEN,
-                       len - ETHERNET_HEADER_LEN);
-            break;
-        case ETHERNET_TYPE_DCE:
-            if (unlikely(len < ETHERNET_DCE_HEADER_LEN)) {
-                ENGINE_SET_INVALID_EVENT(p, DCE_PKT_TOO_SMALL);
-            } else {
-                DecodeEthernet(tv, dtv, p, pkt + ETHERNET_DCE_HEADER_LEN,
-                    len - ETHERNET_DCE_HEADER_LEN);
-            }
-            break;
-        default:
-            SCLogDebug("p %p pkt %p ether type %04x not supported", p,
-                       pkt, SCNtohs(p->ethh->eth_type));
-    }
+    DecodeNetworkLayer(tv, dtv, SCNtohs(p->ethh->eth_type), p,
+            pkt + ETHERNET_HEADER_LEN, len - ETHERNET_HEADER_LEN);
 
     return TM_ECODE_OK;
 }
@@ -204,7 +159,7 @@ static int DecodeEthernetTestDceNextTooSmall(void)
 
     DecodeEthernet(&tv, &dtv, p, raw_eth, sizeof(raw_eth));
 
-    FAIL_IF_NOT(ENGINE_ISSET_EVENT(p, ETHERNET_PKT_TOO_SMALL));
+    FAIL_IF_NOT(ENGINE_ISSET_EVENT(p, DCE_PKT_TOO_SMALL));
 
     SCFree(p);
     PASS;
index 6585608aaa5455bd51c7e78d46b1a32297035e3d..9e02b1c8c5af482cd0af4b7c695b4ff7488973e5 100644 (file)
@@ -52,29 +52,8 @@ int DecodeSll(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p,
 
     SCLogDebug("p %p pkt %p sll_protocol %04x", p, pkt, SCNtohs(sllh->sll_protocol));
 
-    switch (SCNtohs(sllh->sll_protocol)) {
-        case ETHERNET_TYPE_IP:
-            if (unlikely(len > SLL_HEADER_LEN + USHRT_MAX)) {
-                return TM_ECODE_FAILED;
-            }
-            DecodeIPV4(tv, dtv, p, pkt + SLL_HEADER_LEN,
-                       len - SLL_HEADER_LEN);
-            break;
-        case ETHERNET_TYPE_IPV6:
-            if (unlikely(len > SLL_HEADER_LEN + USHRT_MAX)) {
-                return TM_ECODE_FAILED;
-            }
-            DecodeIPV6(tv, dtv, p, pkt + SLL_HEADER_LEN,
-                       len - SLL_HEADER_LEN);
-            break;
-        case ETHERNET_TYPE_VLAN:
-            DecodeVLAN(tv, dtv, p, pkt + SLL_HEADER_LEN,
-                                 len - SLL_HEADER_LEN);
-            break;
-        default:
-            SCLogDebug("p %p pkt %p sll type %04x not supported", p,
-                       pkt, SCNtohs(sllh->sll_protocol));
-    }
+    DecodeNetworkLayer(tv, dtv, SCNtohs(sllh->sll_protocol), p,
+            pkt + SLL_HEADER_LEN, len - SLL_HEADER_LEN);
 
     return TM_ECODE_OK;
 }
index c41d870f772559d226f9a1a936e0f8bd82d6ed1d..371e2ad85766e6571b5ab1fb737246cd4edb6efe 100644 (file)
@@ -44,9 +44,6 @@
 #include "util-profiling.h"
 #include "host.h"
 
-static int DecodeIEEE8021ah(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p,
-        const uint8_t *pkt, uint32_t len);
-
 /**
  * \internal
  * \brief this function is used to decode IEEE802.1q packets
@@ -90,56 +87,7 @@ int DecodeVLAN(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p,
 
     p->vlan_id[p->vlan_idx++] = (uint16_t)GET_VLAN_ID(vlan_hdr);
 
-    switch (proto)   {
-        case ETHERNET_TYPE_IP:
-            if (unlikely(len > VLAN_HEADER_LEN + USHRT_MAX)) {
-                return TM_ECODE_FAILED;
-            }
-
-            DecodeIPV4(tv, dtv, p, pkt + VLAN_HEADER_LEN,
-                       len - VLAN_HEADER_LEN);
-            break;
-        case ETHERNET_TYPE_IPV6:
-            if (unlikely(len > VLAN_HEADER_LEN + USHRT_MAX)) {
-                return TM_ECODE_FAILED;
-            }
-            DecodeIPV6(tv, dtv, p, pkt + VLAN_HEADER_LEN,
-                       len - VLAN_HEADER_LEN);
-            break;
-        case ETHERNET_TYPE_PPPOE_SESS:
-            DecodePPPOESession(tv, dtv, p, pkt + VLAN_HEADER_LEN,
-                               len - VLAN_HEADER_LEN);
-            break;
-        case ETHERNET_TYPE_PPPOE_DISC:
-            DecodePPPOEDiscovery(tv, dtv, p, pkt + VLAN_HEADER_LEN,
-                                 len - VLAN_HEADER_LEN);
-            break;
-        case ETHERNET_TYPE_VLAN:
-        case ETHERNET_TYPE_8021AD:
-            if (p->vlan_idx >= 2) {
-                ENGINE_SET_EVENT(p,VLAN_HEADER_TOO_MANY_LAYERS);
-                return TM_ECODE_OK;
-            } else {
-                DecodeVLAN(tv, dtv, p, pkt + VLAN_HEADER_LEN,
-                        len - VLAN_HEADER_LEN);
-            }
-            break;
-        case ETHERNET_TYPE_8021AH:
-            DecodeIEEE8021ah(tv, dtv, p, pkt + VLAN_HEADER_LEN,
-                    len - VLAN_HEADER_LEN);
-            break;
-        case ETHERNET_TYPE_ARP:
-            break;
-        case ETHERNET_TYPE_MPLS_UNICAST:
-        case ETHERNET_TYPE_MPLS_MULTICAST:
-            DecodeMPLS(tv, dtv, p, pkt + VLAN_HEADER_LEN,
-                       len - VLAN_HEADER_LEN);
-            break;
-        default:
-            SCLogDebug("unknown VLAN type: %" PRIx32 "", proto);
-            ENGINE_SET_INVALID_EVENT(p, VLAN_UNKNOWN_TYPE);
-            return TM_ECODE_OK;
-    }
+    DecodeNetworkLayer(tv, dtv, proto, p, pkt + VLAN_HEADER_LEN, len - VLAN_HEADER_LEN);
 
     return TM_ECODE_OK;
 }
@@ -163,7 +111,7 @@ typedef struct IEEE8021ahHdr_ {
 
 #define IEEE8021AH_HEADER_LEN sizeof(IEEE8021ahHdr)
 
-static int DecodeIEEE8021ah(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p,
+int DecodeIEEE8021ah(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p,
         const uint8_t *pkt, uint32_t len)
 {
     StatsIncr(tv, dtv->counter_ieee8021ah);
@@ -174,16 +122,11 @@ static int DecodeIEEE8021ah(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p,
     }
 
     IEEE8021ahHdr *hdr = (IEEE8021ahHdr *)pkt;
-    uint16_t next_proto = SCNtohs(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);
-            break;
-        }
-    }
+    const uint16_t next_proto = SCNtohs(hdr->type);
+
+    DecodeNetworkLayer(tv, dtv, next_proto, p,
+            pkt + IEEE8021AH_HEADER_LEN, len - IEEE8021AH_HEADER_LEN);
+
     return TM_ECODE_OK;
 }
 
index 408944858bc2a6dabf22b31ccbe214fc76596c6f..d703f30ca8f7820422527cb3634ce0659bf0d7f4 100644 (file)
@@ -930,6 +930,7 @@ int DecodeUDP(ThreadVars *, DecodeThreadVars *, Packet *, const uint8_t *, uint1
 int DecodeSCTP(ThreadVars *, DecodeThreadVars *, Packet *, const uint8_t *, uint16_t);
 int DecodeGRE(ThreadVars *, DecodeThreadVars *, Packet *, const uint8_t *, uint32_t);
 int DecodeVLAN(ThreadVars *, DecodeThreadVars *, Packet *, const uint8_t *, uint32_t);
+int DecodeIEEE8021ah(ThreadVars *, DecodeThreadVars *, Packet *, const uint8_t *, uint32_t);
 int DecodeVXLAN(ThreadVars *, DecodeThreadVars *, Packet *, const uint8_t *, uint32_t);
 int DecodeMPLS(ThreadVars *, DecodeThreadVars *, Packet *, const uint8_t *, uint32_t);
 int DecodeERSPAN(ThreadVars *, DecodeThreadVars *, Packet *, const uint8_t *, uint32_t);
@@ -1177,5 +1178,56 @@ static inline void DecodeLinkLayer(ThreadVars *tv, DecodeThreadVars *dtv,
     }
 }
 
-#endif /* __DECODE_H__ */
+static inline void DecodeNetworkLayer(ThreadVars *tv, DecodeThreadVars *dtv,
+        const uint16_t proto, Packet *p, const uint8_t *data, const uint32_t len)
+{
+    switch (proto) {
+        case ETHERNET_TYPE_IP: {
+            uint16_t ip_len = (len < USHRT_MAX) ? (uint16_t)len : (uint16_t)USHRT_MAX;
+            DecodeIPV4(tv, dtv, p, data, ip_len);
+            break;
+        }
+        case ETHERNET_TYPE_IPV6: {
+            uint16_t ip_len = (len < USHRT_MAX) ? (uint16_t)len : (uint16_t)USHRT_MAX;
+            DecodeIPV6(tv, dtv, p, data, ip_len);
+            break;
+        }
+        case ETHERNET_TYPE_PPPOE_SESS:
+            DecodePPPOESession(tv, dtv, p, data, len);
+            break;
+        case ETHERNET_TYPE_PPPOE_DISC:
+            DecodePPPOEDiscovery(tv, dtv, p, data, len);
+            break;
+        case ETHERNET_TYPE_VLAN:
+        case ETHERNET_TYPE_8021AD:
+        case ETHERNET_TYPE_8021QINQ:
+            if (p->vlan_idx >= 2) {
+                ENGINE_SET_EVENT(p,VLAN_HEADER_TOO_MANY_LAYERS);
+            } else {
+                DecodeVLAN(tv, dtv, p, data, len);
+            }
+            break;
+        case ETHERNET_TYPE_8021AH:
+            DecodeIEEE8021ah(tv, dtv, p, data, len);
+            break;
+        case ETHERNET_TYPE_ARP:
+            break;
+        case ETHERNET_TYPE_MPLS_UNICAST:
+        case ETHERNET_TYPE_MPLS_MULTICAST:
+            DecodeMPLS(tv, dtv, p, data, len);
+            break;
+        case ETHERNET_TYPE_DCE:
+            if (unlikely(len < ETHERNET_DCE_HEADER_LEN)) {
+                ENGINE_SET_INVALID_EVENT(p, DCE_PKT_TOO_SMALL);
+            } else {
+                DecodeEthernet(tv, dtv, p, data, len);
+            }
+            break;
+        default:
+            SCLogDebug("unknown ether type: %" PRIx32 "", proto);
+            ENGINE_SET_INVALID_EVENT(p, VLAN_UNKNOWN_TYPE); // TODO
+            break;
+    }
+}
 
+#endif /* __DECODE_H__ */