From: Victor Julien Date: Wed, 26 Feb 2020 13:06:26 +0000 (+0100) Subject: decode: single network layer entrypoint X-Git-Tag: suricata-6.0.0-beta1~537 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=136d351e403b0ca53c7a7d9544f1affab31cee42;p=thirdparty%2Fsuricata.git decode: single network layer entrypoint This way new layers can be added in a single place. --- diff --git a/src/decode-ethernet.c b/src/decode-ethernet.c index 911538ceb4..e46c09cd5f 100644 --- a/src/decode-ethernet.c +++ b/src/decode-ethernet.c @@ -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; diff --git a/src/decode-sll.c b/src/decode-sll.c index 6585608aaa..9e02b1c8c5 100644 --- a/src/decode-sll.c +++ b/src/decode-sll.c @@ -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; } diff --git a/src/decode-vlan.c b/src/decode-vlan.c index c41d870f77..371e2ad857 100644 --- a/src/decode-vlan.c +++ b/src/decode-vlan.c @@ -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; } diff --git a/src/decode.h b/src/decode.h index 408944858b..d703f30ca8 100644 --- a/src/decode.h +++ b/src/decode.h @@ -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__ */