Skip to content

Commit

Permalink
decode: single network layer entrypoint
Browse files Browse the repository at this point in the history
This way new layers can be added in a single place.
  • Loading branch information
victorjulien committed Apr 10, 2020
1 parent 88bccfb commit 136d351
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 136 deletions.
51 changes: 3 additions & 48 deletions src/decode-ethernet.c
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
Expand Down
25 changes: 2 additions & 23 deletions src/decode-sll.c
Expand Up @@ -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;
}
Expand Down
71 changes: 7 additions & 64 deletions src/decode-vlan.c
Expand Up @@ -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
Expand Down Expand Up @@ -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;
}
Expand All @@ -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);
Expand All @@ -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;
}

Expand Down
54 changes: 53 additions & 1 deletion src/decode.h
Expand Up @@ -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);
Expand Down Expand Up @@ -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__ */

0 comments on commit 136d351

Please sign in to comment.