diff --git a/src/runmode-af-packet.c b/src/runmode-af-packet.c index 031d58846e..2a49acff97 100644 --- a/src/runmode-af-packet.c +++ b/src/runmode-af-packet.c @@ -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 { diff --git a/src/runmode-pcap.c b/src/runmode-pcap.c index 51c3d44b33..4f764acbfd 100644 --- a/src/runmode-pcap.c +++ b/src/runmode-pcap.c @@ -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) { diff --git a/src/runmode-pfring.c b/src/runmode-pfring.c index 4d02a3cea3..8204ccc4d4 100644 --- a/src/runmode-pfring.c +++ b/src/runmode-pfring.c @@ -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); diff --git a/src/source-af-packet.c b/src/source-af-packet.c index b6bae28ada..479cdbf27a 100644 --- a/src/source-af-packet.c +++ b/src/source-af-packet.c @@ -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); } diff --git a/src/source-af-packet.h b/src/source-af-packet.h index 78420a97c9..b43396dd83 100644 --- a/src/source-af-packet.h +++ b/src/source-af-packet.h @@ -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); diff --git a/src/source-pcap.c b/src/source-pcap.c index 0aba4b58b4..e53ca88854 100644 --- a/src/source-pcap.c +++ b/src/source-pcap.c @@ -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 */ diff --git a/src/source-pcap.h b/src/source-pcap.h index 6af5f1716d..c312f02d28 100644 --- a/src/source-pcap.h +++ b/src/source-pcap.h @@ -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; diff --git a/src/source-pfring.c b/src/source-pfring.c index dfd69b143b..78a8268fb1 100644 --- a/src/source-pfring.c +++ b/src/source-pfring.c @@ -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; } diff --git a/src/source-pfring.h b/src/source-pfring.h index cfe3335ef5..f39d8d8334 100644 --- a/src/source-pfring.h +++ b/src/source-pfring.h @@ -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;