void DecodeTunnel(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t len, PacketQueue *pq, uint8_t proto) { switch (proto) { case PPP_OVER_GRE: return DecodePPP(tv, dtv, p, pkt, len, pq); case IPPROTO_IP: return DecodeIPV4(tv, dtv, p, pkt, len, pq); case IPPROTO_IPV6: return DecodeIPV6(tv, dtv, p, pkt, len, pq); case VLAN_OVER_GRE: return DecodeVLAN(tv, dtv, p, pkt, len, pq); default: SCLogInfo("FIXME: DecodeTunnel: protocol %" PRIu32 " not supported.", proto); break; } }
/** * \test DecodeVLANTest02 test a good vlan header. * * \retval 1 on success * \retval 0 on failure */ static int DecodeVLANtest03 (void) { uint8_t raw_vlan[] = { 0x00, 0x20, 0x08, 0x00, 0x45, 0x00, 0x00, 0x34, 0x3b, 0x36, 0x40, 0x00, 0x40, 0x06, 0xb7, 0xc9, 0x83, 0x97, 0x20, 0x81, 0x83, 0x97, 0x20, 0x15, 0x04, 0x8a, 0x17, 0x70, 0x4e, 0x14, 0xdf, 0x55, 0x4d, 0x3d, 0x5a, 0x61, 0x80, 0x10, 0x6b, 0x50, 0x3c, 0x4c, 0x00, 0x00, 0x01, 0x01, 0x08, 0x0a, 0x00, 0x04, 0xf0, 0xc8, 0x01, 0x99, 0xa3, 0xf3}; Packet *p = PacketGetFromAlloc(); if (unlikely(p == NULL)) return 0; ThreadVars tv; DecodeThreadVars dtv; memset(&tv, 0, sizeof(ThreadVars)); memset(&dtv, 0, sizeof(DecodeThreadVars)); FlowInitConfig(FLOW_QUIET); DecodeVLAN(&tv, &dtv, p, raw_vlan, sizeof(raw_vlan), NULL); if(p->vlanh == NULL) { goto error; } if(ENGINE_ISSET_EVENT(p,VLAN_HEADER_TOO_SMALL)) { goto error; } if(ENGINE_ISSET_EVENT(p,VLAN_UNKNOWN_TYPE)) { goto error; } PACKET_RECYCLE(p); FlowShutdown(); SCFree(p); return 1; error: PACKET_RECYCLE(p); FlowShutdown(); SCFree(p); return 0; }
/** * \internal * \brief this function is used to decode IEEE802.1q packets * * \param tv pointer to the thread vars * \param dtv pointer code thread vars * \param p pointer to the packet struct * \param pkt pointer to the raw packet * \param len packet len * \param pq pointer to the packet queue * */ void DecodeVLAN(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t len, PacketQueue *pq) { SCPerfCounterIncr(dtv->counter_vlan, tv->sc_perf_pca); if(len < VLAN_HEADER_LEN) { DECODER_SET_EVENT(p,VLAN_HEADER_TOO_SMALL); return; } p->vlanh = (VLANHdr *)pkt; if(p->vlanh == NULL) return; SCLogDebug("p %p pkt %p VLAN protocol %04x VLAN PRI %d VLAN CFI %d VLAN ID %d Len: %" PRId32 "", p, pkt, GET_VLAN_PROTO(p->vlanh), GET_VLAN_PRIORITY(p->vlanh), GET_VLAN_CFI(p->vlanh), GET_VLAN_ID(p->vlanh), len); switch (GET_VLAN_PROTO(p->vlanh)) { case ETHERNET_TYPE_IP: DecodeIPV4(tv, dtv, p, pkt + VLAN_HEADER_LEN, len - VLAN_HEADER_LEN, pq); break; case ETHERNET_TYPE_IPV6: DecodeIPV6(tv, dtv, p, pkt + VLAN_HEADER_LEN, len - VLAN_HEADER_LEN, pq); break; case ETHERNET_TYPE_PPPOE_SESS: DecodePPPOESession(tv, dtv, p, pkt + VLAN_HEADER_LEN, len - VLAN_HEADER_LEN, pq); break; case ETHERNET_TYPE_PPPOE_DISC: DecodePPPOEDiscovery(tv, dtv, p, pkt + VLAN_HEADER_LEN, len - VLAN_HEADER_LEN, pq); break; case ETHERNET_TYPE_VLAN: DecodeVLAN(tv, dtv, p, pkt + VLAN_HEADER_LEN, len - VLAN_HEADER_LEN, pq); break; default: SCLogDebug("unknown VLAN type: %" PRIx32 "",GET_VLAN_PROTO(p->vlanh)); DECODER_SET_EVENT(p,VLAN_UNKNOWN_TYPE); return; } return; }
/** * \test DecodeVLANTest02 test a good vlan header. * * \retval 1 on success * \retval 0 on failure */ static int DecodeVLANtest03 (void) { uint8_t raw_vlan[] = { 0x00, 0x20, 0x08, 0x00, 0x45, 0x00, 0x00, 0x34, 0x3b, 0x36, 0x40, 0x00, 0x40, 0x06, 0xb7, 0xc9, 0x83, 0x97, 0x20, 0x81, 0x83, 0x97, 0x20, 0x15, 0x04, 0x8a, 0x17, 0x70, 0x4e, 0x14, 0xdf, 0x55, 0x4d, 0x3d, 0x5a, 0x61, 0x80, 0x10, 0x6b, 0x50, 0x3c, 0x4c, 0x00, 0x00, 0x01, 0x01, 0x08, 0x0a, 0x00, 0x04, 0xf0, 0xc8, 0x01, 0x99, 0xa3, 0xf3}; Packet *p = SCMalloc(SIZE_OF_PACKET); if (p == NULL) return 0; ThreadVars tv; DecodeThreadVars dtv; memset(&tv, 0, sizeof(ThreadVars)); memset(p, 0, SIZE_OF_PACKET); p->pkt = (uint8_t *)(p + 1); memset(&dtv, 0, sizeof(DecodeThreadVars)); FlowInitConfig(FLOW_QUIET); DecodeVLAN(&tv, &dtv, p, raw_vlan, sizeof(raw_vlan), NULL); FlowShutdown(); if(p->vlanh == NULL) { SCFree(p); return 0; } if(DECODER_ISSET_EVENT(p,VLAN_HEADER_TOO_SMALL)) { SCFree(p); return 0; } if(DECODER_ISSET_EVENT(p,VLAN_UNKNOWN_TYPE)) { SCFree(p); return 0; } SCFree(p); return 1; }
/** * \test DecodeVLANTest01 test if vlan header is too small. * * \retval 1 on success * \retval 0 on failure */ static int DecodeVLANtest01 (void) { uint8_t raw_vlan[] = { 0x00, 0x20, 0x08 }; Packet *p = PacketGetFromAlloc(); if (unlikely(p == NULL)) return 0; ThreadVars tv; DecodeThreadVars dtv; memset(&tv, 0, sizeof(ThreadVars)); memset(&dtv, 0, sizeof(DecodeThreadVars)); DecodeVLAN(&tv, &dtv, p, raw_vlan, sizeof(raw_vlan), NULL); if(ENGINE_ISSET_EVENT(p,VLAN_HEADER_TOO_SMALL)) { SCFree(p); return 1; } SCFree(p); return 0; }
int DecodeTunnel(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t len, PacketQueue *pq, enum DecodeTunnelProto proto) { switch (proto) { case DECODE_TUNNEL_PPP: return DecodePPP(tv, dtv, p, pkt, len, pq); case DECODE_TUNNEL_IPV4: return DecodeIPV4(tv, dtv, p, pkt, len, pq); case DECODE_TUNNEL_IPV6: return DecodeIPV6(tv, dtv, p, pkt, len, pq); case DECODE_TUNNEL_VLAN: return DecodeVLAN(tv, dtv, p, pkt, len, pq); case DECODE_TUNNEL_ETHERNET: return DecodeEthernet(tv, dtv, p, pkt, len, pq); case DECODE_TUNNEL_ERSPAN: return DecodeERSPAN(tv, dtv, p, pkt, len, pq); default: SCLogInfo("FIXME: DecodeTunnel: protocol %" PRIu32 " not supported.", proto); break; } return TM_ECODE_OK; }
/** * \test DecodeVLANTest01 test if vlan header is too small. * * \retval 1 on success * \retval 0 on failure */ static int DecodeVLANtest01 (void) { uint8_t raw_vlan[] = { 0x00, 0x20, 0x08 }; Packet *p = SCMalloc(SIZE_OF_PACKET); if (p == NULL) return 0; ThreadVars tv; DecodeThreadVars dtv; memset(&tv, 0, sizeof(ThreadVars)); memset(p, 0, SIZE_OF_PACKET); p->pkt = (uint8_t *)(p + 1); memset(&dtv, 0, sizeof(DecodeThreadVars)); DecodeVLAN(&tv, &dtv, p, raw_vlan, sizeof(raw_vlan), NULL); if(DECODER_ISSET_EVENT(p,VLAN_HEADER_TOO_SMALL)) { SCFree(p); return 1; } SCFree(p); return 0; }
/** * \internal * \brief this function is used to decode IEEE802.1q packets * * \param tv pointer to the thread vars * \param dtv pointer code thread vars * \param p pointer to the packet struct * \param pkt pointer to the raw packet * \param len packet len * \param pq pointer to the packet queue * */ int DecodeVLAN(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t len, PacketQueue *pq) { uint32_t proto; SCPerfCounterIncr(dtv->counter_vlan, tv->sc_perf_pca); if(len < VLAN_HEADER_LEN) { ENGINE_SET_INVALID_EVENT(p, VLAN_HEADER_TOO_SMALL); return TM_ECODE_FAILED; } if (p->vlan_idx >= 2) { ENGINE_SET_EVENT(p,VLAN_HEADER_TOO_MANY_LAYERS); return TM_ECODE_FAILED; } p->vlanh[p->vlan_idx] = (VLANHdr *)pkt; if(p->vlanh[p->vlan_idx] == NULL) return TM_ECODE_FAILED; proto = GET_VLAN_PROTO(p->vlanh[p->vlan_idx]); SCLogDebug("p %p pkt %p VLAN protocol %04x VLAN PRI %d VLAN CFI %d VLAN ID %d Len: %" PRId32 "", p, pkt, proto, GET_VLAN_PRIORITY(p->vlanh[p->vlan_idx]), GET_VLAN_CFI(p->vlanh[p->vlan_idx]), GET_VLAN_ID(p->vlanh[p->vlan_idx]), len); /* only store the id for flow hashing if it's not disabled. */ if (dtv->vlan_disabled == 0) p->vlan_id[p->vlan_idx] = (uint16_t)GET_VLAN_ID(p->vlanh[p->vlan_idx]); p->vlan_idx++; switch (proto) { case ETHERNET_TYPE_IP: DecodeIPV4(tv, dtv, p, pkt + VLAN_HEADER_LEN, len - VLAN_HEADER_LEN, pq); break; case ETHERNET_TYPE_IPV6: DecodeIPV6(tv, dtv, p, pkt + VLAN_HEADER_LEN, len - VLAN_HEADER_LEN, pq); break; case ETHERNET_TYPE_PPPOE_SESS: DecodePPPOESession(tv, dtv, p, pkt + VLAN_HEADER_LEN, len - VLAN_HEADER_LEN, pq); break; case ETHERNET_TYPE_PPPOE_DISC: DecodePPPOEDiscovery(tv, dtv, p, pkt + VLAN_HEADER_LEN, len - VLAN_HEADER_LEN, pq); break; case ETHERNET_TYPE_VLAN: 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, pq); } break; default: SCLogDebug("unknown VLAN type: %" PRIx32 "", proto); ENGINE_SET_INVALID_EVENT(p, VLAN_UNKNOWN_TYPE); return TM_ECODE_OK; } return TM_ECODE_OK; }
/* * @mbuf: * @pkt: start of l2 header * @len: len of l2 packet */ int DecodeEthernet(mbuf_t *mbuf, uint8_t *pkt, uint16_t len) { EthernetHdr *pethh; LOGDBG(SEC_ETHERNET_DBG_BIT, "==============>enter DecodeEthernet\n"); if (unlikely(len < ETHERNET_HEADER_LEN)) { STAT_L2_HEADER_ERR; DP_Log_Func(mbuf); return DECODE_DROP; } pethh = (EthernetHdr *)(pkt); if((0 == pethh->eth_dst[0] && 0 == pethh->eth_dst[1] && 0 == pethh->eth_dst[2] && 0 == pethh->eth_dst[3] && 0 == pethh->eth_dst[4] && 0 == pethh->eth_dst[5]) || (0 == pethh->eth_src[0] && 0 == pethh->eth_src[1] && 0 == pethh->eth_src[2] && 0 == pethh->eth_src[3] && 0 == pethh->eth_src[4] && 0 == pethh->eth_src[5])) { STAT_L2_HEADER_ERR; DP_Log_Func(mbuf); return DECODE_DROP; } mbuf->ethh = (void *)pethh; LOGDBG(SEC_ETHERNET_DBG_BIT, "dst mac is %x:%x:%x:%x:%x:%x\n", pethh->eth_dst[0],pethh->eth_dst[1], pethh->eth_dst[2],pethh->eth_dst[3], pethh->eth_dst[4],pethh->eth_dst[5]); LOGDBG(SEC_ETHERNET_DBG_BIT, "src mac is %x:%x:%x:%x:%x:%x\n", pethh->eth_src[0],pethh->eth_src[1], pethh->eth_src[2],pethh->eth_src[3], pethh->eth_src[4],pethh->eth_src[5]); LOGDBG(SEC_ETHERNET_DBG_BIT, "eth type is 0x%x\n", pethh->eth_type); memcpy(mbuf->eth_dst, pethh->eth_dst, 6); memcpy(mbuf->eth_src, pethh->eth_src, 6); switch (pethh->eth_type) { case ETHERNET_TYPE_IP: { STAT_L2_RECV_OK; return DecodeIPV4(mbuf, pkt + ETHERNET_HEADER_LEN, len - ETHERNET_HEADER_LEN); } #ifdef ROUTE_PROC_ENABLE case ETHERNET_TYPE_ARP: { if(SEC_OK != oct_pow_se2linux(mbuf)) { STAT_L2_ARP_SE2LINUX_FAIL; return DECODE_DROP; } else { STAT_L2_ARP_SE2LINUX_OK; STAT_L2_RECV_OK; return DECODE_OK; } } #endif case ETHERNET_TYPE_VLAN: case ETHERNET_TYPE_8021QINQ: { STAT_L2_RECV_OK; return DecodeVLAN(mbuf, pkt + ETHERNET_HEADER_LEN, len - ETHERNET_HEADER_LEN); } default: { LOGDBG(SEC_ETHERNET_DBG_BIT, "ether type %04x not supported", pethh->eth_type); STAT_L2_UNSUPPORT; #if 0 output_fw_proc(mbuf); #endif Decode_unsupport_proto_handle(mbuf); return DECODE_OK; } } return DECODE_OK; }
int DecodeEthernet(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint32_t len, PacketQueue *pq) { StatsIncr(tv, dtv->counter_eth); if (unlikely(len < ETHERNET_HEADER_LEN)) { ENGINE_SET_INVALID_EVENT(p, ETHERNET_PKT_TOO_SMALL); 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, pq); break; case ETHERNET_TYPE_IPV6: //printf("DecodeEthernet ip6\n"); DecodeIPV6(tv, dtv, p, pkt + ETHERNET_HEADER_LEN, len - ETHERNET_HEADER_LEN, pq); break; case ETHERNET_TYPE_PPPOE_SESS: //printf("DecodeEthernet PPPOE Session\n"); DecodePPPOESession(tv, dtv, p, pkt + ETHERNET_HEADER_LEN, len - ETHERNET_HEADER_LEN, pq); break; case ETHERNET_TYPE_PPPOE_DISC: //printf("DecodeEthernet PPPOE Discovery\n"); DecodePPPOEDiscovery(tv, dtv, p, pkt + ETHERNET_HEADER_LEN, len - ETHERNET_HEADER_LEN, pq); break; case ETHERNET_TYPE_VLAN: case ETHERNET_TYPE_8021QINQ: DecodeVLAN(tv, dtv, p, pkt + ETHERNET_HEADER_LEN, len - ETHERNET_HEADER_LEN, pq); break; case ETHERNET_TYPE_MPLS_UNICAST: case ETHERNET_TYPE_MPLS_MULTICAST: DecodeMPLS(tv, dtv, p, pkt + ETHERNET_HEADER_LEN, len - ETHERNET_HEADER_LEN, pq); 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, pq); } break; default: SCLogDebug("p %p pkt %p ether type %04x not supported", p, pkt, SCNtohs(p->ethh->eth_type)); } return TM_ECODE_OK; }