From def0270de78fd4af15dfa72aab68cb65b335b2d7 Mon Sep 17 00:00:00 2001 From: Eric Leblond Date: Wed, 8 Aug 2012 16:21:27 +0200 Subject: [PATCH] decode: decode IPv6-in-IPv6 This patch adds decoding of IPv6-in-IPv6. It also adds some events for invalid packets. This patch should fix #514. --- rules/decoder-events.rules | 5 ++++- src/decode-events.h | 3 +++ src/decode-ipv6.c | 28 ++++++++++++++++++++++++++++ src/detect-engine-event.h | 2 ++ 4 files changed, 37 insertions(+), 1 deletion(-) diff --git a/rules/decoder-events.rules b/rules/decoder-events.rules index 1299e41a30..6ced87942f 100644 --- a/rules/decoder-events.rules +++ b/rules/decoder-events.rules @@ -89,6 +89,9 @@ alert icmp any any -> any any (msg:"SURICATA ICMPv6 invalid checksum"; icmpv6-cs # 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;) +# IPv6 in IPv6 rules +alert pkthdr any any -> any any (msg:"SURICATA IPv6-in-IPv6 packet too short"; decode-event:ipv6.ipv6_in_ipv6_too_small; sid:2200084; rev:1;) +alert pkthdr any any -> any any (msg:"SURICATA IPv6-in-IPv6 invalid protocol"; decode-event:ipv6.ipv6_in_ipv6_wrong_version; sid:2200085; rev:1;) -# next sid is 2200084 +# next sid is 2200086 diff --git a/src/decode-events.h b/src/decode-events.h index 0c7983d501..89f8422444 100644 --- a/src/decode-events.h +++ b/src/decode-events.h @@ -200,6 +200,9 @@ enum { /* IPv4 in IPv6 events */ IPV4_IN_IPV6_PKT_TOO_SMALL, IPV4_IN_IPV6_WRONG_IP_VER, + /* IPv6 in IPv6 events */ + IPV6_IN_IPV6_PKT_TOO_SMALL, + IPV6_IN_IPV6_WRONG_IP_VER, /* should always be last! */ DECODE_EVENT_MAX, diff --git a/src/decode-ipv6.c b/src/decode-ipv6.c index 826dba5e23..be003afc11 100644 --- a/src/decode-ipv6.c +++ b/src/decode-ipv6.c @@ -71,6 +71,32 @@ static void DecodeIPv4inIPv6(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, u 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; +} + static void DecodeIPV6ExtHdrs(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t len, PacketQueue *pq) { @@ -515,6 +541,8 @@ void DecodeIPV6(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, 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_IPV6: + return DecodeIP6inIP6(tv, dtv, p, pkt + IPV6_HEADER_LEN, IPV6_GET_PLEN(p), pq); case IPPROTO_FRAGMENT: case IPPROTO_HOPOPTS: case IPPROTO_ROUTING: diff --git a/src/detect-engine-event.h b/src/detect-engine-event.h index 9d719b84bd..f8034f96f0 100644 --- a/src/detect-engine-event.h +++ b/src/detect-engine-event.h @@ -118,6 +118,8 @@ struct DetectEngineEvents_ { { "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, }, + { "ipv6.ipv6_in_ipv6_too_small", IPV6_IN_IPV6_PKT_TOO_SMALL, }, + { "ipv6.ipv6_in_ipv6_wrong_version", IPV6_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, },