From: Eric Leblond Date: Mon, 16 Jul 2012 14:11:40 +0000 (+0200) Subject: Add support for IPv4-in-IPv6 X-Git-Tag: suricata-1.4beta1~92 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F23%2Fhead;p=thirdparty%2Fsuricata.git Add support for IPv4-in-IPv6 This patch adds support for IPv4-in-IPv6 and should fix #462. --- diff --git a/rules/decoder-events.rules b/rules/decoder-events.rules index 13f2ac3344..1299e41a30 100644 --- a/rules/decoder-events.rules +++ b/rules/decoder-events.rules @@ -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 diff --git a/src/decode-events.h b/src/decode-events.h index 179e4fd7a5..32aeee95ce 100644 --- a/src/decode-events.h +++ b/src/decode-events.h @@ -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, }; diff --git a/src/decode-ipv6.c b/src/decode-ipv6.c index 15701e1ad2..826dba5e23 100644 --- a/src/decode-ipv6.c +++ b/src/decode-ipv6.c @@ -45,6 +45,32 @@ #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; diff --git a/src/detect-engine-event.h b/src/detect-engine-event.h index 5ab28194c1..9d719b84bd 100644 --- a/src/detect-engine-event.h +++ b/src/detect-engine-event.h @@ -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, },