From a76cd9aa5f5fd50cb21eb768faef2b24234fc29c Mon Sep 17 00:00:00 2001
From: Eric Leblond <eric@regit.org>
Date: Fri, 13 Jul 2012 15:46:02 +0200
Subject: [PATCH 2/2] sig: add l3_proto keyword

This patch adds a l3_proto keyword to the signature language. It
can be used to specify if the signature has to match on IPv4, IPv6
or both. For example, one can write:
  alert http any any -> any 22 (msg: "HTTP v6"; l3_proto:ip6; sid:14;)

This should close #494.
---
 src/Makefile.am      |    1 +
 src/detect-l3proto.c |  122 ++++++++++++++++++++++++++++++++++++++++++++++++++
 src/detect-l3proto.h |   34 ++++++++++++++
 src/detect.c         |    2 +
 src/detect.h         |    2 +
 5 files changed, 161 insertions(+)
 create mode 100644 src/detect-l3proto.c
 create mode 100644 src/detect-l3proto.h

diff --git a/src/Makefile.am b/src/Makefile.am
index 5f5e345..03c300e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -111,6 +111,7 @@ detect-rawbytes.c detect-rawbytes.h \
 detect-bytetest.c detect-bytetest.h \
 detect-bytejump.c detect-bytejump.h \
 detect-sameip.c detect-sameip.h \
+detect-l3proto.c detect-l3proto.h \
 detect-ipproto.c detect-ipproto.h \
 detect-within.c detect-within.h \
 detect-distance.c detect-distance.h \
diff --git a/src/detect-l3proto.c b/src/detect-l3proto.c
new file mode 100644
index 0000000..c149e98
--- /dev/null
+++ b/src/detect-l3proto.c
@@ -0,0 +1,122 @@
+/* Copyright (C) 2012 Open Information Security Foundation
+ *
+ * You can copy, redistribute or modify this Program under the terms of
+ * the GNU General Public License version 2 as published by the Free
+ * Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * \file
+ *
+ * \author Eric Leblond <eric@regit.org>
+ *
+ *
+ * Implements the l3_proto keyword
+ */
+
+#include "suricata-common.h"
+#include "debug.h"
+#include "decode.h"
+#include "detect.h"
+
+#include "detect-ipproto.h"
+
+#include "detect-parse.h"
+#include "detect-engine.h"
+#include "detect-engine-mpm.h"
+
+#include "detect-engine-siggroup.h"
+#include "detect-engine-address.h"
+
+#include "util-byte.h"
+#include "util-unittest.h"
+#include "util-unittest-helper.h"
+
+#include "util-debug.h"
+
+static int DetectL3ProtoSetup(DetectEngineCtx *, Signature *, char *);
+
+void DetectL3ProtoRegister(void)
+{
+    sigmatch_table[DETECT_L3PROTO].name = "l3_proto";
+    sigmatch_table[DETECT_L3PROTO].Match = NULL;
+    sigmatch_table[DETECT_L3PROTO].Setup = DetectL3ProtoSetup;
+    sigmatch_table[DETECT_L3PROTO].Free  = NULL;
+    sigmatch_table[DETECT_L3PROTO].RegisterTests = NULL;
+
+    return;
+}
+/**
+ * \internal
+ * \brief Setup l3_proto keyword.
+ *
+ * \param de_ctx Detection engine context
+ * \param s Signature
+ * \param optstr Options string
+ *
+ * \return Non-zero on error
+ */
+static int DetectL3ProtoSetup(DetectEngineCtx *de_ctx, Signature *s, char *optstr)
+{
+    char *str = optstr;
+    char dubbed = 0;
+
+    /* strip "'s */
+    if (optstr[0] == '\"' && optstr[strlen(optstr) - 1] == '\"') {
+        str = SCStrdup(optstr + 1);
+        if (str == NULL)
+            goto error;
+        str[strlen(optstr) - 2] = '\0';
+        dubbed = 1;
+    }
+
+    /* reset possible any value */
+    if (s->proto.flags & DETECT_PROTO_ANY) {
+        s->proto.flags &= ~DETECT_PROTO_ANY;
+    }
+
+    /* authorized value, ip, any, ip4, ipv4, ip6, ipv6 */
+    if (strcasecmp(str,"ipv4") == 0 ||
+            strcasecmp(str,"ip4") == 0 ) {
+        if (s->proto.flags & DETECT_PROTO_IPV6) {
+            SCLogError(SC_ERR_INVALID_SIGNATURE, "Conflicting l3 proto specified");
+            goto error;
+        }
+        s->proto.flags |= DETECT_PROTO_IPV4;
+        SCLogDebug("IPv4 protocol detected");
+    } else if (strcasecmp(str,"ipv6") == 0 ||
+            strcasecmp(str,"ip6") == 0 ) {
+        if (s->proto.flags & DETECT_PROTO_IPV6) {
+            SCLogError(SC_ERR_INVALID_SIGNATURE, "Conflicting l3 proto specified");
+            goto error;
+        }
+        s->proto.flags |= DETECT_PROTO_IPV6;
+        SCLogDebug("IPv6 protocol detected");
+    } else if ((strcasecmp(str,"ip") == 0) ||
+            strcasecmp(str,"any") == 0 ) {
+        /* Proto "ip" is treated as an "any" */
+        s->proto.flags |= DETECT_PROTO_ANY;
+        SCLogDebug("IP protocol detected");
+    } else {
+        SCLogError(SC_ERR_INVALID_SIGNATURE, "Invalid l3 proto: \"%s\"", str);
+        goto error;
+    }
+
+    if (dubbed)
+        SCFree(str);
+    return 0;
+error:
+    if (dubbed)
+        SCFree(str);
+    return -1;
+}
diff --git a/src/detect-l3proto.h b/src/detect-l3proto.h
new file mode 100644
index 0000000..9d60df8
--- /dev/null
+++ b/src/detect-l3proto.h
@@ -0,0 +1,34 @@
+/* Copyright (C) 2012 Open Information Security Foundation
+ *
+ * You can copy, redistribute or modify this Program under the terms of
+ * the GNU General Public License version 2 as published by the Free
+ * Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * \file
+ *
+ * \author Eric Leblond <eric@regit.org>
+ *
+ */
+
+#ifndef __DETECT_L3PROTO_H__
+#define __DETECT_L3PROTO_H__
+
+/**
+ * \brief Registration function for ip_proto keyword.
+ */
+void DetectL3ProtoRegister (void);
+
+#endif /* __DETECT_L3PROTO_H__ */
+
diff --git a/src/detect.c b/src/detect.c
index ed7884e..e6f4063 100644
--- a/src/detect.c
+++ b/src/detect.c
@@ -72,6 +72,7 @@
 #include "detect-bytetest.h"
 #include "detect-bytejump.h"
 #include "detect-sameip.h"
+#include "detect-l3proto.h"
 #include "detect-ipproto.h"
 #include "detect-within.h"
 #include "detect-distance.h"
@@ -4665,6 +4666,7 @@ void SigTableSetup(void) {
     DetectBytetestRegister();
     DetectBytejumpRegister();
     DetectSameipRegister();
+    DetectL3ProtoRegister();
     DetectIPProtoRegister();
     DetectWithinRegister();
     DetectDistanceRegister();
diff --git a/src/detect.h b/src/detect.h
index 2b0041a..dd56de7 100644
--- a/src/detect.h
+++ b/src/detect.h
@@ -1031,6 +1031,8 @@ enum {
     DETECT_FILEMAGIC,
     DETECT_FILEMD5,
 
+    DETECT_L3PROTO,
+
     /* make sure this stays last */
     DETECT_TBLSIZE,
 };
-- 
1.7.10.4

