]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
feature #417: add support for configuration per host timeout value
authorGiuseppe Longo <giuseppelng@gmail.com>
Sat, 12 Oct 2013 10:02:49 +0000 (12:02 +0200)
committerVictor Julien <victor@inliniac.net>
Thu, 28 Nov 2013 09:17:13 +0000 (10:17 +0100)
src/Makefile.am
src/defrag-config.c [new file with mode: 0644]
src/defrag-config.h [new file with mode: 0644]
src/defrag-hash.c
src/defrag.c
src/defrag.h

index 99f524099cbe6a1689d92ae5b66e9e7ddbc266de..f458f8519bd4b8fd033fd329bdb6e106a6c8c8ae 100644 (file)
@@ -54,6 +54,7 @@ decode-tcp.c decode-tcp.h \
 decode-teredo.c decode-teredo.h \
 decode-udp.c decode-udp.h \
 decode-vlan.c decode-vlan.h \
+defrag-config.c defrag-config.h \
 defrag.c defrag.h \
 defrag-hash.c defrag-hash.h \
 defrag-queue.c defrag-queue.h \
diff --git a/src/defrag-config.c b/src/defrag-config.c
new file mode 100644 (file)
index 0000000..4ae272f
--- /dev/null
@@ -0,0 +1,168 @@
+/* Copyright (C) 2007-2013 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 Giuseppe Longo <giuseppelng@gmail.com>
+ *
+ * Example config:
+ * defrag:
+ *    memcap: 32mb
+ *    hash-size: 65536
+ *    trackers: 65535
+ *    max-frags: 65535
+ *    prealloc: yes
+ *
+ *    default-config:
+ *       timeout: 40
+ *
+ *    host-config:
+ *
+ *      - dmz:
+ *          timeout: 30
+ *          address: [192.168.1.0/24, 127.0.0.0/8, 1.1.1.0/24, 2.2.2.0/24, "1.1.1.1", "2.2.2.2", "::1"]
+ *
+ *      - lan:
+ *          timeout: 45
+ *          address:
+ *            - 192.168.0.0/24
+ *            - 192.168.10.0/24
+ *            - 172.16.14.0/24
+ */
+
+#include "suricata-common.h"
+#include "queue.h"
+#include "suricata.h"
+#include "conf.h"
+#include "util-debug.h"
+#include "util-misc.h"
+#include "defrag-config.h"
+
+static SCRadixTree *defrag_tree = NULL;
+
+static int default_timeout = 0;
+
+static void DefragPolicyAddHostInfo(char *host_ip_range, uintmax_t *timeout)
+{
+    uintmax_t *user_data = timeout;
+
+    if (strchr(host_ip_range, ':') != NULL) {
+        SCLogDebug("adding ipv6 host %s", host_ip_range);
+        if (SCRadixAddKeyIPV6String(host_ip_range, defrag_tree, user_data) == NULL) {
+            SCLogWarning(SC_ERR_INVALID_VALUE,
+                        "failed to add ipv6 host %s", host_ip_range);
+        }
+    } else {
+        SCLogDebug("adding ipv4 host %s", host_ip_range);
+        if (SCRadixAddKeyIPV4String(host_ip_range, defrag_tree, user_data) == NULL) {
+            SCLogWarning(SC_ERR_INVALID_VALUE,
+                        "failed to add ipv4 host %s", host_ip_range);
+        }
+    }
+}
+
+static int DefragPolicyGetIPv4HostTimeout(uint8_t *ipv4_addr)
+{
+    SCRadixNode *node = SCRadixFindKeyIPV4BestMatch(ipv4_addr, defrag_tree);
+
+    if (node == NULL)
+        return -1;
+    else
+        return *((int *)node->prefix->user_data_result);
+}
+
+static int DefragPolicyGetIPv6HostTimeout(uint8_t *ipv6_addr)
+{
+    SCRadixNode *node = SCRadixFindKeyIPV6BestMatch(ipv6_addr, defrag_tree);
+    if (node == NULL)
+        return -1;
+    else
+        return *((int *)node->prefix->user_data_result);
+}
+
+int DefragPolicyGetHostTimeout(Packet *p)
+{
+    int timeout = 0;
+
+    if (PKT_IS_IPV4(p))
+        timeout = DefragPolicyGetIPv4HostTimeout((uint8_t *)GET_IPV4_DST_ADDR_PTR(p));
+    else if (PKT_IS_IPV6(p))
+        timeout = DefragPolicyGetIPv6HostTimeout((uint8_t *)GET_IPV6_DST_ADDR(p));
+    else
+        timeout = default_timeout;
+
+    return timeout;
+}
+
+static void DefragParseParameters(ConfNode *n)
+{
+    ConfNode *si;
+    uintmax_t timeout = 0;
+
+    TAILQ_FOREACH(si, &n->head, next) {
+        if (strcasecmp("timeout", si->name) == 0) {
+                SCLogDebug("timeout value  %s", si->val);
+                if (ParseSizeStringU64(si->val, &timeout) < 0) {
+                    SCLogError(SC_ERR_SIZE_PARSE, "Error parsing timeout "
+                               "from conf file");
+                }
+            }
+            if (strcasecmp("address", si->name) == 0) {
+                ConfNode *pval;
+                TAILQ_FOREACH(pval, &si->head, next) {
+                    DefragPolicyAddHostInfo(pval->val, &timeout);
+                }
+            }
+        }
+}
+
+void DefragSetDefaultTimeout(intmax_t timeout)
+{
+    default_timeout = timeout;
+    SCLogDebug("default timeout %d", default_timeout);
+}
+
+void DefragPolicyLoadFromConfig(void)
+{
+    SCEnter();
+
+    defrag_tree = SCRadixCreateRadixTree(NULL, NULL);
+    if (defrag_tree == NULL) {
+        SCLogError(SC_ERR_MEM_ALLOC,
+            "Can't alloc memory for the defrag config tree.");
+        exit(EXIT_FAILURE);
+    }
+
+    ConfNode *server_config = ConfGetNode("defrag.host-config");
+    if (server_config == NULL) {
+        SCLogDebug("failed to read host config");
+        SCReturn;
+    }
+
+    SCLogDebug("configuring host config %p", server_config);
+    ConfNode *sc;
+
+    TAILQ_FOREACH(sc, &server_config->head, next) {
+        ConfNode *p = NULL;
+
+        TAILQ_FOREACH(p, &sc->head, next) {
+            SCLogDebug("parsing configuration for %s", p->name);
+            DefragParseParameters(p);
+        }
+    }
+}
diff --git a/src/defrag-config.h b/src/defrag-config.h
new file mode 100644 (file)
index 0000000..a6c086f
--- /dev/null
@@ -0,0 +1,32 @@
+/* Copyright (C) 2007-2013 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 Giuseppe Longo <giuseppelng@gmail.com>
+ *
+ */
+
+#ifndef DEFRAG_CONFIG_H_
+#define DEFRAG_CONFIG_H_
+
+void DefragSetDefaultTimeout(intmax_t timeout);
+void DefragPolicyLoadFromConfig(void);
+int DefragPolicyGetHostTimeout(Packet *p);
+
+#endif /* DEFRAG_CONFIG_H_ */
index ffb957bb7ff3700335906ad870de8589b776d320..202a16155b356818d38b005a03cc45929c98f6cc 100644 (file)
@@ -19,6 +19,7 @@
 #include "conf.h"
 #include "defrag-hash.h"
 #include "defrag-queue.h"
+#include "defrag-config.h"
 #include "util-random.h"
 #include "util-byte.h"
 #include "util-misc.h"
@@ -89,6 +90,8 @@ static void DefragTrackerInit(DefragTracker *dt, Packet *p) {
     dt->vlan_id[0] = p->vlan_id[0];
     dt->vlan_id[1] = p->vlan_id[1];
     dt->policy = DefragGetOsPolicy(p);
+    dt->host_timeout = DefragPolicyGetHostTimeout(p);
+
     TAILQ_INIT(&dt->frags);
     (void) DefragTrackerIncrUsecnt(dt);
 }
index 496997c0e2e26e57c295b7857c71442f0548e125..9a9603d144f96e7511f85005f2b87b3863dfd0c0 100644 (file)
@@ -53,6 +53,7 @@
 #include "defrag.h"
 #include "defrag-hash.h"
 #include "defrag-queue.h"
+#include "defrag-config.h"
 
 #ifdef UNITTESTS
 #include "util-unittest.h"
@@ -541,7 +542,7 @@ DefragInsertFrag(ThreadVars *tv, DecodeThreadVars *dtv, DefragTracker *tracker,
     }
 
     /* Update timeout. */
-    tracker->timeout = p->ts.tv_sec + defrag_context->timeout;
+    tracker->timeout = p->ts.tv_sec + tracker->host_timeout;
 
     Frag *prev = NULL, *next;
     int overlap = 0;
@@ -879,6 +880,9 @@ DefragInit(void)
         tracker_pool_size = DEFAULT_DEFRAG_HASH_SIZE;
     }
 
+    /* Load the defrag-per-host lookup. */
+    DefragPolicyLoadFromConfig();
+
     /* Allocate the DefragContext. */
     defrag_context = DefragContextNew();
     if (defrag_context == NULL) {
@@ -887,6 +891,7 @@ DefragInit(void)
         exit(EXIT_FAILURE);
     }
 
+    DefragSetDefaultTimeout(defrag_context->timeout);
     DefragInitConfig(FALSE);
 }
 
index f9889bea0699c9c1b0e4014d4ad9a7c45de76b89..cf5abe87241bac7cfa16358aeb0d9d9c31758c2d 100644 (file)
@@ -111,6 +111,7 @@ typedef struct DefragTracker_ {
     Address dst_addr; /**< Destination address for this tracker. */
 
     uint32_t timeout; /**< When this tracker will timeout. */
+    uint32_t host_timeout;  /**< Host timeout, statically assigned from the yaml */
 
     /** use cnt, reference counter */
     SC_ATOMIC_DECLARE(unsigned int, use_cnt);