decode: single network layer entrypoint

This way new layers can be added in a single place.
pull/4802/head
Victor Julien 5 years ago
parent 88bccfb80e
commit 136d351e40

@ -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;

@ -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;
}

@ -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;
}

@ -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__ */

Loading…
Cancel
Save