]> git.ipfire.org Git - people/ms/suricata.git/commitdiff
runmode: introduce configuration dereferencing.
authorEric Leblond <eric@regit.org>
Fri, 30 Sep 2011 14:50:50 +0000 (16:50 +0200)
committerEric Leblond <eric@regit.org>
Tue, 4 Oct 2011 21:50:44 +0000 (23:50 +0200)
A devide configuration can be used by multiple threads. It is thus
necessary to wait that all threads stop using the configuration before
freeing it. This patch introduces an atomic counter and a free function
which has to be called by each thread when it will not use anymore
the structure. If the configuration is not used anymore, it is freed
by the free function.

src/runmode-af-packet.c
src/runmode-pcap.c
src/runmode-pfring.c
src/source-af-packet.c
src/source-af-packet.h
src/source-pcap.c
src/source-pcap.h
src/source-pfring.c
src/source-pfring.h

index 031d58846eba38074160de4c14d0e57c9c11cbb0..2a49acff97ad7e0b26c9942e9966e7fea847a8c9 100644 (file)
@@ -78,6 +78,15 @@ void RunModeIdsAFPRegister(void)
     return;
 }
 
+void AFPDerefConfig(void *conf)
+{
+    AFPIfaceConfig *pfp = (AFPIfaceConfig *)conf;
+    /* Pcap config is used only once but cost of this low. */
+    if (SC_ATOMIC_SUB(pfp->ref, 1) == 0) {
+        SCFree(pfp);
+    }
+}
+
 /**
  * \brief extract information from config file
  *
@@ -108,10 +117,13 @@ void *ParseAFPConfig(const char *iface)
     }
     strlcpy(aconf->iface, iface, sizeof(aconf->iface));
     aconf->threads = 1;
+    SC_ATOMIC_INIT(aconf->ref);
+    SC_ATOMIC_ADD(aconf->ref, 1);
     aconf->buffer_size = 0;
     aconf->cluster_id = 1;
     aconf->cluster_type = PACKET_FANOUT_HASH;
     aconf->promisc = 1;
+    aconf->DerefFunc = AFPDerefConfig;
 
     /* Find initial node */
     af_packet_node = ConfGetNode("af-packet");
@@ -138,6 +150,10 @@ void *ParseAFPConfig(const char *iface)
     if (aconf->threads == 0) {
         aconf->threads = 1;
     }
+
+    SC_ATOMIC_RESET(aconf->ref);
+    SC_ATOMIC_ADD(aconf->ref, aconf->threads);
+
     if (ConfGetChildValue(if_root, "cluster-id", &tmpclusterid) != 1) {
         SCLogError(SC_ERR_INVALID_ARGUMENT,"Could not get cluster-id from config");
     } else {
index 51c3d44b33f459bf824e56cb8de9bf61ae2bcf83..4f764acbfd3d127d74704bbfc252c2ed36831d09 100644 (file)
@@ -39,6 +39,7 @@
 #include "util-affinity.h"
 #include "util-device.h"
 #include "util-runmodes.h"
+#include "util-atomic.h"
 
 static const char *default_mode = NULL;
 
@@ -67,6 +68,18 @@ void RunModeIdsPcapRegister(void)
     return;
 }
 
+void PcapDerefConfig(void *conf)
+{
+    PcapIfaceConfig *pfp = (PcapIfaceConfig *)conf;
+    /* Pcap config is used only once but cost of this low. */
+    if (SC_ATOMIC_SUB(pfp->ref, 1) == 0) {
+        if (pfp->bpf_filter) {
+            SCFree(pfp->bpf_filter);
+        }
+        SCFree(pfp);
+    }
+}
+
 
 void *ParsePcapConfig(const char *iface)
 {
@@ -96,6 +109,10 @@ void *ParsePcapConfig(const char *iface)
         aconf->bpf_filter = tmpbpf;
     }
 
+    SC_ATOMIC_INIT(aconf->ref);
+    SC_ATOMIC_ADD(aconf->ref, 1);
+    aconf->DerefFunc = PcapDerefConfig;
+
     /* Find initial node */
     pcap_node = ConfGetNode("pcap");
     if (pcap_node == NULL) {
index 4d02a3cea3fbd40f3be497b97804bbef252c4aeb..8204ccc4d4bf9d5cb72958fbeb19434acda570b7 100644 (file)
@@ -75,6 +75,14 @@ void RunModeIdsPfringRegister(void)
     return;
 }
 
+void PfringDerefConfig(void *conf)
+{
+    PfringIfaceConfig *pfp = (PfringIfaceConfig *)conf;
+    if (SC_ATOMIC_SUB(pfp->ref, 1) == 0) {
+        SCFree(pfp);
+    }
+}
+
 /**
  * \brief extract information from config file
  *
@@ -111,6 +119,9 @@ void *OldParsePfringConfig(const char *iface)
 #ifdef HAVE_PFRING_CLUSTER_TYPE
     pfconf->ctype = (cluster_type)default_ctype;
 #endif
+    pfconf->DerefFunc = PfringDerefConfig;
+    SC_ATOMIC_INIT(pfconf->ref);
+    SC_ATOMIC_ADD(pfconf->ref, 1);
 
     /* Find initial node */
     if (ConfGet("pfring.threads", &threadsstr) != 1) {
@@ -123,6 +134,10 @@ void *OldParsePfringConfig(const char *iface)
     if (pfconf->threads == 0) {
         pfconf->threads = 1;
     }
+
+    SC_ATOMIC_RESET(pfconf->ref);
+    SC_ATOMIC_ADD(pfconf->ref, pfconf->threads);
+
     if (ConfGet("pfring.cluster-id", &tmpclusterid) != 1) {
         SCLogError(SC_ERR_INVALID_ARGUMENT,"Could not get cluster-id from config");
     } else {
@@ -190,6 +205,9 @@ void *ParsePfringConfig(const char *iface)
 #ifdef HAVE_PFRING_CLUSTER_TYPE
     pfconf->ctype = (cluster_type)default_ctype;
 #endif
+    pfconf->DerefFunc = PfringDerefConfig;
+    SC_ATOMIC_INIT(pfconf->ref);
+    SC_ATOMIC_ADD(pfconf->ref, 1);
 
     /* Find initial node */
     pf_ring_node = ConfGetNode("pfring");
@@ -220,6 +238,9 @@ void *ParsePfringConfig(const char *iface)
         pfconf->threads = 1;
     }
 
+    SC_ATOMIC_RESET(pfconf->ref);
+    SC_ATOMIC_ADD(pfconf->ref, pfconf->threads);
+
     /* command line value has precedence */
     if (ConfGet("pfring.cluster-id", &tmpclusterid) == 1) {
         pfconf->cluster_id = (uint16_t)atoi(tmpclusterid);
index b6bae28ada22f5d77d90eca6fa2935782734a707..479cdbf27ad516e2718d208ef85744d3e1ae699f 100644 (file)
@@ -556,8 +556,10 @@ TmEcode ReceiveAFPThreadInit(ThreadVars *tv, void *initdata, void **data) {
     }
 
     AFPThreadVars *ptv = SCMalloc(sizeof(AFPThreadVars));
-    if (ptv == NULL)
+    if (ptv == NULL) {
+        afpconfig->DerefFunc(afpconfig);
         SCReturnInt(TM_ECODE_FAILED);
+    }
     memset(ptv, 0, sizeof(AFPThreadVars));
 
     ptv->tv = tv;
@@ -586,6 +588,7 @@ TmEcode ReceiveAFPThreadInit(ThreadVars *tv, void *initdata, void **data) {
     if (r < 0) {
         SCLogError(SC_ERR_AFP_CREATE, "Couldn't init AF_PACKET socket");
         SCFree(ptv);
+        afpconfig->DerefFunc(afpconfig);
         SCReturnInt(TM_ECODE_FAILED);
     }
 
@@ -599,6 +602,7 @@ TmEcode ReceiveAFPThreadInit(ThreadVars *tv, void *initdata, void **data) {
 #define T_DATA_SIZE 70000
     ptv->data = SCMalloc(T_DATA_SIZE);
     if (ptv->data == NULL) {
+        afpconfig->DerefFunc(afpconfig);
         SCReturnInt(TM_ECODE_FAILED);
     }
     ptv->datalen = T_DATA_SIZE;
@@ -607,8 +611,7 @@ TmEcode ReceiveAFPThreadInit(ThreadVars *tv, void *initdata, void **data) {
 
     *data = (void *)ptv;
 
-    /* we've received a single use structure, we can free it */
-    SCFree(initdata);
+    afpconfig->DerefFunc(afpconfig);
     SCReturnInt(TM_ECODE_OK);
 }
 
index 78420a97c9c83ef5c498c08c138312edd3371105..b43396dd838808174af7fa7cf55eecf65ba1a470 100644 (file)
@@ -51,6 +51,8 @@ typedef struct AFPIfaceConfig_
     int cluster_type;
     /* promisc mode */
     int promisc;
+    SC_ATOMIC_DECLARE(unsigned int, ref);
+    void (*DerefFunc)(void *);
 } AFPIfaceConfig;
 
 void TmModuleReceiveAFPRegister (void);
index 0aba4b58b4006f74d29a609713d38c28b334fdf8..e53ca888540ea0b77efcba42d9e928437409a77c 100644 (file)
@@ -295,8 +295,10 @@ TmEcode ReceivePcapThreadInit(ThreadVars *tv, void *initdata, void **data) {
     }
 
     PcapThreadVars *ptv = SCMalloc(sizeof(PcapThreadVars));
-    if (ptv == NULL)
+    if (ptv == NULL) {
+        pcapconfig->DerefFunc(pcapconfig);
         SCReturnInt(TM_ECODE_FAILED);
+    }
     memset(ptv, 0, sizeof(PcapThreadVars));
 
     ptv->tv = tv;
@@ -308,6 +310,7 @@ TmEcode ReceivePcapThreadInit(ThreadVars *tv, void *initdata, void **data) {
     if (ptv->pcap_handle == NULL) {
         SCLogError(SC_ERR_PCAP_CREATE, "Coudn't create a new pcap handler, error %s", pcap_geterr(ptv->pcap_handle));
         SCFree(ptv);
+        pcapconfig->DerefFunc(pcapconfig);
         SCReturnInt(TM_ECODE_FAILED);
     }
 
@@ -317,6 +320,7 @@ TmEcode ReceivePcapThreadInit(ThreadVars *tv, void *initdata, void **data) {
     if (pcap_set_snaplen_r != 0) {
         SCLogError(SC_ERR_PCAP_SET_SNAPLEN, "Couldn't set snaplen, error: %s", pcap_geterr(ptv->pcap_handle));
         SCFree(ptv);
+        pcapconfig->DerefFunc(pcapconfig);
         SCReturnInt(TM_ECODE_FAILED);
     }
 
@@ -325,6 +329,7 @@ TmEcode ReceivePcapThreadInit(ThreadVars *tv, void *initdata, void **data) {
     if (pcap_set_promisc_r != 0) {
         SCLogError(SC_ERR_PCAP_SET_PROMISC, "Couldn't set promisc mode, error %s", pcap_geterr(ptv->pcap_handle));
         SCFree(ptv);
+        pcapconfig->DerefFunc(pcapconfig);
         SCReturnInt(TM_ECODE_FAILED);
     }
 
@@ -333,6 +338,7 @@ TmEcode ReceivePcapThreadInit(ThreadVars *tv, void *initdata, void **data) {
     if (pcap_set_timeout_r != 0) {
         SCLogError(SC_ERR_PCAP_SET_TIMEOUT, "Problems setting timeout, error %s", pcap_geterr(ptv->pcap_handle));
         SCFree(ptv);
+        pcapconfig->DerefFunc(pcapconfig);
         SCReturnInt(TM_ECODE_FAILED);
     }
 #ifdef HAVE_PCAP_SET_BUFF
@@ -345,6 +351,7 @@ TmEcode ReceivePcapThreadInit(ThreadVars *tv, void *initdata, void **data) {
         if (pcap_set_buffer_size_r != 0) {
             SCLogError(SC_ERR_PCAP_SET_BUFF_SIZE, "Problems setting pcap buffer size, error %s", pcap_geterr(ptv->pcap_handle));
             SCFree(ptv);
+            pcapconfig->DerefFunc(pcapconfig);
             SCReturnInt(TM_ECODE_FAILED);
         }
     }
@@ -356,6 +363,7 @@ TmEcode ReceivePcapThreadInit(ThreadVars *tv, void *initdata, void **data) {
     if (pcap_activate_r != 0) {
         SCLogError(SC_ERR_PCAP_ACTIVATE_HANDLE, "Couldn't activate the pcap handler, error %s", pcap_geterr(ptv->pcap_handle));
         SCFree(ptv);
+        pcapconfig->DerefFunc(pcapconfig);
         SCReturnInt(TM_ECODE_FAILED);
         ptv->pcap_state = PCAP_STATE_DOWN;
     } else {
@@ -365,28 +373,34 @@ TmEcode ReceivePcapThreadInit(ThreadVars *tv, void *initdata, void **data) {
     /* set bpf filter if we have one */
     if (pcapconfig->bpf_filter) {
         ptv->bpf_filter = SCStrdup(pcapconfig->bpf_filter);
+        /* free bpf as we are using a copy */
+        SCFree(pcapconfig->bpf_filter);
         if(pcap_compile(ptv->pcap_handle,&ptv->filter,ptv->bpf_filter,1,0) < 0) {
             SCLogError(SC_ERR_BPF,"bpf compilation error %s",pcap_geterr(ptv->pcap_handle));
             SCFree(ptv);
+            pcapconfig->DerefFunc(pcapconfig);
             return TM_ECODE_FAILED;
         }
 
         if(pcap_setfilter(ptv->pcap_handle,&ptv->filter) < 0) {
             SCLogError(SC_ERR_BPF,"could not set bpf filter %s",pcap_geterr(ptv->pcap_handle));
             SCFree(ptv);
+            pcapconfig->DerefFunc(pcapconfig);
             return TM_ECODE_FAILED;
         }
     }
 
     ptv->datalink = pcap_datalink(ptv->pcap_handle);
 
+    pcapconfig->DerefFunc(pcapconfig);
+
     *data = (void *)ptv;
     SCReturnInt(TM_ECODE_OK);
 }
 #else /* implied LIBPCAP_VERSION_MAJOR == 0 */
 TmEcode ReceivePcapThreadInit(ThreadVars *tv, void *initdata, void **data) {
     SCEnter();
-
+    PcapIfaceConfig *pcapconfig = initdata;
     char *tmpbpfstring;
 
     if (initdata == NULL) {
@@ -395,8 +409,11 @@ TmEcode ReceivePcapThreadInit(ThreadVars *tv, void *initdata, void **data) {
     }
 
     PcapThreadVars *ptv = SCMalloc(sizeof(PcapThreadVars));
-    if (ptv == NULL)
+    if (ptv == NULL) {
+        /* Dereference config */
+        pcapconfig->DerefFunc(pcapconfig);
         SCReturnInt(TM_ECODE_FAILED);
+    }
     memset(ptv, 0, sizeof(PcapThreadVars));
 
     ptv->tv = tv;
@@ -404,6 +421,8 @@ TmEcode ReceivePcapThreadInit(ThreadVars *tv, void *initdata, void **data) {
     SCLogInfo("using interface %s", (char *)initdata);
     if(strlen(initdata)>PCAP_IFACE_NAME_LENGTH) {
         SCFree(ptv);
+        /* Dereference config */
+        pcapconfig->DerefFunc(pcapconfig);
         SCReturnInt(TM_ECODE_FAILED);
     }
     strlcpy(ptv->iface, (char *)initdata, PCAP_IFACE_NAME_LENGTH);
@@ -414,6 +433,8 @@ TmEcode ReceivePcapThreadInit(ThreadVars *tv, void *initdata, void **data) {
     if (ptv->pcap_handle == NULL) {
         SCLogError(SC_ERR_PCAP_OPEN_LIVE, "Problem creating pcap handler for live mode, error %s", errbuf);
         SCFree(ptv);
+        /* Dereference config */
+        pcapconfig->DerefFunc(pcapconfig);
         SCReturnInt(TM_ECODE_FAILED);
     }
 
@@ -425,20 +446,25 @@ TmEcode ReceivePcapThreadInit(ThreadVars *tv, void *initdata, void **data) {
         if(pcap_compile(ptv->pcap_handle,&ptv->filter, ptv->bpf_filter,1,0) < 0) {
             SCLogError(SC_ERR_BPF,"bpf compilation error %s",pcap_geterr(ptv->pcap_handle));
             SCFree(ptv);
+            /* Dereference config */
+            pcapconfig->DerefFunc(pcapconfig);
             return TM_ECODE_FAILED;
         }
 
         if(pcap_setfilter(ptv->pcap_handle,&ptv->filter) < 0) {
             SCLogError(SC_ERR_BPF,"could not set bpf filter %s",pcap_geterr(ptv->pcap_handle));
             SCFree(ptv);
+            /* Dereference config */
+            pcapconfig->DerefFunc(pcapconfig);
             return TM_ECODE_FAILED;
         }
     }
 
-
     ptv->datalink = pcap_datalink(ptv->pcap_handle);
 
     *data = (void *)ptv;
+    /* Dereference config */
+    pcapconfig->DerefFunc(pcapconfig);
     SCReturnInt(TM_ECODE_OK);
 }
 #endif /* LIBPCAP_VERSION_MAJOR */
index 6af5f1716d2d42808f53cab97b5c3c302c9b83f8..c312f02d28e988792b78cbcc3025dd1133c2ce36 100644 (file)
@@ -51,6 +51,8 @@ typedef struct PcapIfaceConfig_
     int buffer_size;
     /* BPF filter */
     char *bpf_filter;
+    SC_ATOMIC_DECLARE(unsigned int, ref);
+    void (*DerefFunc)(void *);
 } PcapIfaceConfig;
 
 
index dfd69b143bd109737d64c2c4d3cd5166dc96bdb0..78a8268fb12434a3d569be95ebf854cf1f6ececb 100644 (file)
@@ -275,9 +275,15 @@ TmEcode ReceivePfringThreadInit(ThreadVars *tv, void *initdata, void **data) {
     char *tmpctype;
     PfringIfaceConfig *pfconf = (PfringIfaceConfig *) initdata;
 
+
+    if (pfconf == NULL)
+        return TM_ECODE_FAILED;
+
     PfringThreadVars *ptv = SCMalloc(sizeof(PfringThreadVars));
-    if (ptv == NULL)
+    if (ptv == NULL) {
+        pfconf->DerefFunc(pfconf);
         return TM_ECODE_FAILED;
+    }
     memset(ptv, 0, sizeof(PfringThreadVars));
 
     ptv->tv = tv;
@@ -289,6 +295,7 @@ TmEcode ReceivePfringThreadInit(ThreadVars *tv, void *initdata, void **data) {
     if (ptv->pd == NULL) {
         SCLogError(SC_ERR_PF_RING_OPEN,"opening %s failed: pfring_open error",
                 ptv->interface);
+        pfconf->DerefFunc(pfconf);
         return TM_ECODE_FAILED;
     } else {
         pfring_set_application_name(ptv->pd, PROG_NAME);
@@ -311,6 +318,7 @@ TmEcode ReceivePfringThreadInit(ThreadVars *tv, void *initdata, void **data) {
         if (rc != 0) {
             SCLogError(SC_ERR_PF_RING_SET_CLUSTER_FAILED, "pfring_set_cluster "
                     "returned %d for cluster-id: %d", rc, ptv->cluster_id);
+            pfconf->DerefFunc(pfconf);
             return TM_ECODE_FAILED;
         }
         SCLogInfo("(%s) Using PF_RING v.%d.%d.%d, interface %s, cluster-id %d",
@@ -329,12 +337,14 @@ TmEcode ReceivePfringThreadInit(ThreadVars *tv, void *initdata, void **data) {
 
     if (rc != 0) {
         SCLogError(SC_ERR_PF_RING_OPEN, "pfring_enable failed returned %d ", rc);
+        pfconf->DerefFunc(pfconf);
         return TM_ECODE_FAILED;
     }
 #endif /* HAVE_PFRING_ENABLE */
 
 
     *data = (void *)ptv;
+    pfconf->DerefFunc(pfconf);
     return TM_ECODE_OK;
 }
 
index cfe3335ef58966068e081f94261575b54e07bf68..f39d8d83348eef03eb153099f723250adc3081cf 100644 (file)
@@ -41,6 +41,8 @@ typedef struct PfringIfaceConfig_
     char iface[PFRING_IFACE_NAME_LENGTH];
     /* number of threads */
     int threads;
+    SC_ATOMIC_DECLARE(unsigned int, ref);
+    void (*DerefFunc)(void *);
 } PfringIfaceConfig;