#define IPV6_EXTHDRS ip6eh.ip6_exthdrs
#define IPV6_EH_CNT ip6eh.ip6_exthdrs_cnt
+/**
+ * \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, pkt, plen, pq, IPPROTO_IP);
+ PacketEnqueue(pq,tp);
+ return;
+ }
+ }
+ } else {
+ ENGINE_SET_EVENT(p, IPV4_IN_IPV6_WRONG_IP_VER);
+ }
+ return;
+}
+
static void
DecodeIPV6ExtHdrs(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t len, PacketQueue *pq)
{
plen -= hdrextlen;
break;
}
+ case IPPROTO_IPIP:
+ IPV6_SET_L4PROTO(p,nh);
+ DecodeIPv4inIPv6(tv, dtv, p, pkt, plen, pq);
+ SCReturn;
case IPPROTO_NONE:
IPV6_SET_L4PROTO(p,nh);
SCReturn;
case IPPROTO_SCTP:
IPV6_SET_L4PROTO (p, IPPROTO_SCTP);
return DecodeSCTP(tv, dtv, p, pkt + IPV6_HEADER_LEN, IPV6_GET_PLEN(p), pq);
+ case IPPROTO_IPIP:
+ IPV6_SET_L4PROTO(p, IPPROTO_IPIP);
+ return DecodeIPv4inIPv6(tv, dtv, p, pkt + IPV6_HEADER_LEN, IPV6_GET_PLEN(p), pq);
case IPPROTO_FRAGMENT:
case IPPROTO_HOPOPTS:
case IPPROTO_ROUTING:
case IPPROTO_ESP:
DecodeIPV6ExtHdrs(tv, dtv, p, pkt + IPV6_HEADER_LEN, IPV6_GET_PLEN(p), pq);
break;
+
default:
p->proto = IPV6_GET_NH(p);
break;
{ "ipv4.frag_overlap", IPV4_FRAG_OVERLAP, },
{ "ipv6.frag_too_large", IPV6_FRAG_PKT_TOO_LARGE, },
{ "ipv6.frag_overlap", IPV6_FRAG_OVERLAP, },
+ { "ipv6.ipv4_in_ipv6_too_small", IPV4_IN_IPV6_PKT_TOO_SMALL, },
+ { "ipv6.ipv4_in_ipv6_wrong_version", IPV4_IN_IPV6_WRONG_IP_VER, },
{ "stream.3whs_ack_in_wrong_dir", STREAM_3WHS_ACK_IN_WRONG_DIR, },
{ "stream.3whs_async_wrong_seq", STREAM_3WHS_ASYNC_WRONG_SEQ, },
{ "stream.3whs_right_seq_wrong_ack_evasion", STREAM_3WHS_RIGHT_SEQ_WRONG_ACK_EVASION, },