]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
Add support for IPv4-in-IPv6 23/head
authorEric Leblond <eric@regit.org>
Mon, 16 Jul 2012 14:11:40 +0000 (16:11 +0200)
committerEric Leblond <eric@regit.org>
Wed, 22 Aug 2012 08:38:22 +0000 (10:38 +0200)
This patch adds support for IPv4-in-IPv6 and should fix #462.

rules/decoder-events.rules
src/decode-events.h
src/decode-ipv6.c
src/detect-engine-event.h

index 13f2ac3344c02611e7ab5c3eb70fe127bf01b054..1299e41a30523ac260fee3907b85aee3c7c6f2d6 100644 (file)
@@ -86,5 +86,9 @@ alert tcp any any -> any any (msg:"SURICATA TCPv6 invalid checksum"; tcpv6-csum:
 alert udp any any -> any any (msg:"SURICATA UDPv6 invalid checksum"; udpv6-csum:invalid; sid:2200078; rev:1;)
 alert icmp any any -> any any (msg:"SURICATA ICMPv6 invalid checksum"; icmpv6-csum:invalid; sid:2200079; rev:1;)
 
-# next sid is 2200082
+# IPv4 in IPv6 rules
+alert pkthdr any any -> any any (msg:"SURICATA IPv4-in-IPv6 packet too short"; decode-event:ipv6.ipv4_in_ipv6_too_small; sid:2200082; rev:1;)
+alert pkthdr any any -> any any (msg:"SURICATA IPv4-in-IPv6 invalid protocol"; decode-event:ipv6.ipv4_in_ipv6_wrong_version; sid:2200083; rev:1;)
+
+# next sid is 2200084
 
index 179e4fd7a59decae145cd48912749a68c062602a..32aeee95ce5318d5ef989b4bec4f90043e793d0c 100644 (file)
@@ -192,6 +192,10 @@ enum {
     IPV6_FRAG_PKT_TOO_LARGE,
     IPV6_FRAG_OVERLAP,
 
+    /* IPv4 in IPv6 events */
+    IPV4_IN_IPV6_PKT_TOO_SMALL,
+    IPV4_IN_IPV6_WRONG_IP_VER,
+
     /* should always be last! */
     DECODE_EVENT_MAX,
 };
index 15701e1ad28f15d219f6a281702d30c2217e9937..826dba5e230c5e79d0dc4b9b32c1e9eca4bb9b28 100644 (file)
 #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)
 {
@@ -403,6 +429,10 @@ DecodeIPV6ExtHdrs(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt
                 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;
@@ -482,6 +512,9 @@ void DecodeIPV6(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt,
         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:
@@ -491,6 +524,7 @@ void DecodeIPV6(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt,
         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;
index 5ab28194c186ff6f55e7829db80c46c82c633c0a..9d719b84bda8f9fdad2d436da5d434c121fcd4c9 100644 (file)
@@ -116,6 +116,8 @@ struct DetectEngineEvents_ {
     { "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, },