This way new layers can be added in a single place.
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;
}
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;
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;
}
#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
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;
}
#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);
}
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;
}
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);
}
}
-#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__ */