static int DecodeIPV6Packet (ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t len) { if (unlikely(len < IPV6_HEADER_LEN)) { return -1; } if (unlikely(IP_GET_RAW_VER(pkt) != 6)) { SCLogDebug("wrong ip version %" PRIu8 "",IP_GET_RAW_VER(pkt)); ENGINE_SET_INVALID_EVENT(p, IPV6_WRONG_IP_VER); return -1; } p->ip6h = (IPV6Hdr *)pkt; if (unlikely(len < (IPV6_HEADER_LEN + IPV6_GET_PLEN(p)))) { ENGINE_SET_INVALID_EVENT(p, IPV6_TRUNC_PKT); return -1; } SET_IPV6_SRC_ADDR(p,&p->src); SET_IPV6_DST_ADDR(p,&p->dst); return 0; }
int DecodeRaw(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint32_t len, PacketQueue *pq) { StatsIncr(tv, dtv->counter_raw); /* If it is ipv4 or ipv6 it should at least be the size of ipv4 */ if (unlikely(len < IPV4_HEADER_LEN)) { ENGINE_SET_INVALID_EVENT(p, IPV4_PKT_TOO_SMALL); return TM_ECODE_FAILED; } if (IP_GET_RAW_VER(pkt) == 4) { if (unlikely(GET_PKT_LEN(p) > USHRT_MAX)) { return TM_ECODE_FAILED; } SCLogDebug("IPV4 Packet"); DecodeIPV4(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq); } else if (IP_GET_RAW_VER(pkt) == 6) { if (unlikely(GET_PKT_LEN(p) > USHRT_MAX)) { return TM_ECODE_FAILED; } SCLogDebug("IPV6 Packet"); DecodeIPV6(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq); } else { SCLogDebug("Unknown ip version %" PRIu8 "", IP_GET_RAW_VER(pkt)); ENGINE_SET_EVENT(p,IPRAW_INVALID_IPV); } return TM_ECODE_OK; }
void DecodeRaw(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t len, PacketQueue *pq) { SCPerfCounterIncr(dtv->counter_raw, tv->sc_perf_pca); /* If it is ipv4 or ipv6 it should at least be the size of ipv4 */ if (len < IPV4_HEADER_LEN) { ENGINE_SET_EVENT(p,IPV4_PKT_TOO_SMALL); return; } if (IP_GET_RAW_VER(pkt) == 4) { SCLogDebug("IPV4 Packet"); DecodeIPV4(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq); } else if (IP_GET_RAW_VER(pkt) == 6) { SCLogDebug("IPV6 Packet"); DecodeIPV6(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq); } else { SCLogDebug("Unknown ip version %" PRIu8 "", IP_GET_RAW_VER(pkt)); ENGINE_SET_EVENT(p,IPRAW_INVALID_IPV); } return; }
/** * \brief Function to decode IPv4 in IPv6 packets * */ static void DecodeIP6inIP6(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t plen, PacketQueue *pq) { if (unlikely(plen < IPV6_HEADER_LEN)) { ENGINE_SET_EVENT(p, IPV6_IN_IPV6_PKT_TOO_SMALL); return; } if (IP_GET_RAW_VER(pkt) == 6) { if (pq != NULL) { Packet *tp = PacketPseudoPktSetup(p, pkt, plen, IPPROTO_IPV6); if (tp != NULL) { DecodeTunnel(tv, dtv, tp, pkt, plen, pq, IPPROTO_IPV6); PacketEnqueue(pq,tp); return; } } } else { ENGINE_SET_EVENT(p, IPV6_IN_IPV6_WRONG_IP_VER); } return; }
/** * \brief Function to decode IPv6 in IPv6 packets * */ static int DecodeIP6inIP6(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t plen, PacketQueue *pq) { if (unlikely(plen < IPV6_HEADER_LEN)) { ENGINE_SET_INVALID_EVENT(p, IPV6_IN_IPV6_PKT_TOO_SMALL); return TM_ECODE_FAILED; } if (IP_GET_RAW_VER(pkt) == 6) { if (unlikely(pq != NULL)) { Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt, plen, DECODE_TUNNEL_IPV6, pq); if (tp != NULL) { PKT_SET_SRC(tp, PKT_SRC_DECODER_IPV6); PacketEnqueue(pq,tp); StatsIncr(tv, dtv->counter_ipv6inipv6); } } } else { ENGINE_SET_EVENT(p, IPV6_IN_IPV6_WRONG_IP_VER); } return TM_ECODE_OK; }
/** * \brief Function to decode IPv4 in IPv6 packets * */ static void DecodeIPv4inIPv6(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t plen, PacketQueue *pq) { if (unlikely(plen < IPV4_HEADER_LEN)) { ENGINE_SET_INVALID_EVENT(p, IPV4_IN_IPV6_PKT_TOO_SMALL); return; } if (IP_GET_RAW_VER(pkt) == 4) { if (pq != NULL) { Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt, plen, DECODE_TUNNEL_IPV4, pq); if (tp != NULL) { PKT_SET_SRC(tp, PKT_SRC_DECODER_IPV6); /* add the tp to the packet queue. */ PacketEnqueue(pq,tp); StatsIncr(tv, dtv->counter_ipv4inipv6); return; } } } else { ENGINE_SET_EVENT(p, IPV4_IN_IPV6_WRONG_IP_VER); } return; }
/** * \brief Function to decode IPv4 in IPv6 packets * */ static void DecodeIPv4inIPv6(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t plen, PacketQueue *pq) { if (unlikely(plen < IPV4_HEADER_LEN)) { ENGINE_SET_EVENT(p, IPV4_IN_IPV6_PKT_TOO_SMALL); return; } if (IP_GET_RAW_VER(pkt) == 4) { if (pq != NULL) { Packet *tp = PacketPseudoPktSetup(p, pkt, plen, IPPROTO_IP); if (tp != NULL) { DecodeTunnel(tv, dtv, tp, GET_PKT_DATA(tp), GET_PKT_LEN(tp), pq, IPPROTO_IP); PacketEnqueue(pq,tp); SCPerfCounterIncr(dtv->counter_ipv4inipv6, tv->sc_perf_pca); return; } } } else { ENGINE_SET_EVENT(p, IPV4_IN_IPV6_WRONG_IP_VER); } return; }
/** * \brief Function to decode Teredo packets * * \retval 0 if packet is not a Teredo packet, 1 if it is */ int DecodeTeredo(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t len, PacketQueue *pq) { uint8_t *start = pkt; /* Is this packet to short to contain an IPv6 packet ? */ if (len < IPV6_HEADER_LEN) return 0; /* Teredo encapsulate IPv6 in UDP and can add some custom message * part before the IPv6 packet. In our case, we just want to get * over an ORIGIN indication. So we just make one offset if needed. */ if (start[0] == 0x0) { switch (start[1]) { /* origin indication: compatible with tunnel */ case 0x0: /* offset is coherent with len and presence of an IPv6 header */ if (len >= TEREDO_ORIG_INDICATION_LENGTH + IPV6_HEADER_LEN) start += TEREDO_ORIG_INDICATION_LENGTH; else return 0; break; /* authentication: negotiation not real tunnel */ case 0x1: return 0; /* this case is not possible in Teredo: not that protocol */ default: return 0; } } /* There is no specific field that we can check to prove that the packet * is a Teredo packet. We've zapped here all the possible Teredo header * and we should have an IPv6 packet at the start pointer. * We then can only do two checks before sending the encapsulated packets * to decoding: * - The packet has a protocol version which is IPv6. * - The IPv6 length of the packet matches what remains in buffer. */ if (IP_GET_RAW_VER(start) == 6) { IPV6Hdr *thdr = (IPV6Hdr *)start; if (len == IPV6_HEADER_LEN + IPV6_GET_RAW_PLEN(thdr) + (start - pkt)) { if (pq != NULL) { int blen = len - (start - pkt); /* spawn off tunnel packet */ Packet *tp = PacketPseudoPktSetup(p, start, blen, IPPROTO_IPV6); if (tp != NULL) { PKT_SET_SRC(tp, PKT_SRC_DECODER_TEREDO); /* send that to the Tunnel decoder */ DecodeTunnel(tv, dtv, tp, GET_PKT_DATA(tp), GET_PKT_LEN(tp), pq, IPPROTO_IPV6); /* add the tp to the packet queue. */ PacketEnqueue(pq,tp); SCPerfCounterIncr(dtv->counter_teredo, tv->sc_perf_pca); return 1; } } } return 0; } return 0; }