Feature #478 » u2-test-patchv2.diff
src/alert-unified2-alert.c | ||
---|---|---|
*
|
||
* \author Breno Silva <breno.silva@gmail.com>
|
||
* \author Eric Leblond <eric@regit.org>
|
||
* \author Ignacio Sanchez <sanchezmartin.ji@gmail.com>
|
||
*
|
||
* Logs alerts in a format compatible to Snort's unified2 format, so it should
|
||
* be readable by Barnyard2.
|
||
* Experimental support for XFF extradata records.
|
||
*/
|
||
#include "suricata-common.h"
|
||
... | ... | |
#include "threadvars.h"
|
||
#include "tm-threads.h"
|
||
#include "util-unittest.h"
|
||
#include "alert-unified2-alert.h"
|
||
#include "decode-ipv4.h"
|
||
... | ... | |
#include "util-byte.h"
|
||
#include "util-misc.h"
|
||
#include "app-layer-htp.h"
|
||
#include "app-layer.h"
|
||
#include "output.h"
|
||
#include "alert-unified2-alert.h"
|
||
#include "util-privs.h"
|
||
... | ... | |
} Unified2AlertFileHeader;
|
||
/**
|
||
* Unified2 Extra Data Header
|
||
*
|
||
*/
|
||
typedef struct _Unified2ExtraDataHdr{
|
||
uint32_t event_type;
|
||
uint32_t event_length;
|
||
} Unified2ExtraDataHdr;
|
||
/**
|
||
* Unified2 Extra Data (currently used only for XFF)
|
||
*
|
||
*/
|
||
typedef struct _Unified2ExtraData{
|
||
uint32_t sensor_id;
|
||
uint32_t event_id;
|
||
uint32_t event_second;
|
||
uint32_t type; /* EventInfo */
|
||
uint32_t data_type; /*EventDataType */
|
||
uint32_t blob_length; /* Length of the data + sizeof(blob_length) + sizeof(data_type)*/
|
||
} Unified2ExtraData;
|
||
/**
|
||
* Unified2 Ipv4 struct
|
||
*
|
||
* Used for storing ipv4 type values.
|
||
... | ... | |
uint8_t packet_data[4]; /**< packet data */
|
||
} Unified2Packet;
|
||
#define ALERT_UNIFIED2ALERT_XFF 1
|
||
#define ALERT_UNIFIED2ALERT_XFF_OVERWRITE 2
|
||
#define ALERT_UNIFIED2ALERT_XFF_DEFAULT "X-Forwarded-For"
|
||
#define ALERT_UNIFIED2ALERT_XFF_MINLEN 7
|
||
typedef struct Unified2AlertFileCtx_ {
|
||
LogFileCtx *file_ctx;
|
||
uint32_t flags; /** Store mode */
|
||
char *xff_header; /** XFF Header name in case XFF mode is enabled */
|
||
} Unified2AlertFileCtx;
|
||
/**
|
||
* Unified2 thread vars
|
||
*
|
||
* Used for storing file options.
|
||
*/
|
||
typedef struct Unified2AlertThread_ {
|
||
LogFileCtx *file_ctx; /**< LogFileCtx pointer */
|
||
Unified2AlertFileCtx *unified2alert_ctx; /**< LogFileCtx pointer */
|
||
uint8_t *data; /**< Per function and thread data */
|
||
/** Pointer to the Unified2AlertFileHeader contained in
|
||
* the pointer data. */
|
||
... | ... | |
*/
|
||
int Unified2AlertCloseFile(ThreadVars *t, Unified2AlertThread *aun) {
|
||
if (aun->file_ctx->fp != NULL) {
|
||
fclose(aun->file_ctx->fp);
|
||
if (aun->unified2alert_ctx->file_ctx->fp != NULL) {
|
||
fclose(aun->unified2alert_ctx->file_ctx->fp);
|
||
}
|
||
aun->file_ctx->size_current = 0;
|
||
aun->unified2alert_ctx->file_ctx->size_current = 0;
|
||
return 0;
|
||
}
|
||
... | ... | |
"Error: Unified2AlertCloseFile failed");
|
||
return -1;
|
||
}
|
||
if (Unified2AlertOpenFileCtx(aun->file_ctx,aun->file_ctx->prefix) < 0) {
|
||
if (Unified2AlertOpenFileCtx(aun->unified2alert_ctx->file_ctx,aun->unified2alert_ctx->
|
||
file_ctx->prefix) < 0) {
|
||
SCLogError(SC_ERR_UNIFIED2_ALERT_GENERIC,
|
||
"Error: Unified2AlertOpenFileCtx, open new log file failed");
|
||
return -1;
|
||
... | ... | |
{
|
||
int ret;
|
||
ret = fwrite(aun->data, aun->length, 1, aun->file_ctx->fp);
|
||
ret = fwrite(aun->data, aun->length, 1, aun->unified2alert_ctx->file_ctx->fp);
|
||
if (ret != 1) {
|
||
SCLogError(SC_ERR_FWRITE, "Error: fwrite failed: %s", strerror(errno));
|
||
return -1;
|
||
}
|
||
aun->file_ctx->size_current += aun->length;
|
||
aun->unified2alert_ctx->file_ctx->size_current += aun->length;
|
||
return 1;
|
||
}
|
||
/**
|
||
* \brief Function to return XFF IP if any...
|
||
* \retval 1 if the IP has been foudn and returned in dstbuf
|
||
* \retval 0 if the IP has not being found or error
|
||
*/
|
||
int GetXFFIP ( Packet *p, Unified2AlertThread *aun, char *dstbuf ){
|
||
char xffip[128];
|
||
if (aun->unified2alert_ctx->flags & ALERT_UNIFIED2ALERT_XFF) {
|
||
HtpState *htp_state = NULL;
|
||
htp_tx_t *tx = NULL;
|
||
htp_header_t *h_xff = NULL;
|
||
char *p_xff = NULL;
|
||
size_t idx = 0;
|
||
size_t hsize = 0;
|
||
if (p->flow && AppLayerGetProtoFromPacket(p) == ALPROTO_HTTP) {
|
||
htp_state = (HtpState *) AppLayerGetProtoStateFromPacket(p);
|
||
if ( htp_state && htp_state->connp && htp_state->connp->conn) {
|
||
hsize = list_size(htp_state->connp->conn->transactions);
|
||
for (idx = 0; idx < hsize; idx++) {
|
||
tx = list_get(htp_state->connp->conn->transactions, idx);
|
||
if (tx != NULL && tx->request_headers != NULL) {
|
||
h_xff = table_getc(tx->request_headers, aun->unified2alert_ctx->xff_header);
|
||
if (h_xff != NULL && bstr_len(h_xff->value) > ALERT_UNIFIED2ALERT_XFF_MINLEN - 1
|
||
&& bstr_len(h_xff->value) < 120) {
|
||
strlcpy(xffip, bstr_ptr(h_xff->value), bstr_len(h_xff->value) + 1);
|
||
/* Check for chained ips separated by ", ", we will get the last one */
|
||
p_xff = strrchr(xffip, ' ');
|
||
if (p_xff == NULL) {
|
||
p_xff = xffip;
|
||
} else {
|
||
p_xff++;
|
||
}
|
||
/* Sanity check on extracted IP */
|
||
if (strlen(p_xff) > ALERT_UNIFIED2ALERT_XFF_MINLEN - 1 &&
|
||
strlen(p_xff) < 43 ) {
|
||
strlcpy(dstbuf, p_xff, 42);
|
||
return 1; // OK
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return 0; // Not found
|
||
}
|
||
/**
|
||
* \brief Unified2 main entry function
|
||
*
|
||
* \retval TM_ECODE_OK all is good
|
||
... | ... | |
Unified2AlertThread *aun = (Unified2AlertThread *)data;
|
||
Unified2AlertFileHeader *hdr = (Unified2AlertFileHeader*)(aun->data);
|
||
Unified2Packet *phdr = (Unified2Packet *)(hdr + 1);
|
||
/* Prepare the pointers to extradata structures should they are required */
|
||
/* If they are required we will shift the *hdr and the *phdr */
|
||
Unified2AlertFileHeader *eu2hdr = (Unified2AlertFileHeader*)(aun->data);
|
||
Unified2ExtraDataHdr *ehdr = (Unified2ExtraDataHdr *)(eu2hdr + 1);
|
||
Unified2ExtraData *dhdr = (Unified2ExtraData *) (ehdr + 1);
|
||
uint32_t *edxff = (uint32_t *) (dhdr + 1);
|
||
|
||
aun->length = 0;
|
||
aun->offset = 0;
|
||
|
||
char ipbuf[128];
|
||
// If XFF in non overwrite mode...
|
||
if ((aun->unified2alert_ctx->flags & ALERT_UNIFIED2ALERT_XFF) &&
|
||
(aun->unified2alert_ctx->flags & ALERT_UNIFIED2ALERT_XFF_OVERWRITE) == 0 ) {
|
||
if ( GetXFFIP (p, aun, ipbuf) == 1 ) {
|
||
in_addr_t xffip;
|
||
if ( inet_pton(AF_INET, ipbuf, &(xffip) ) == 1 ) {
|
||
memset(dhdr, 0, sizeof(Unified2ExtraData));
|
||
eu2hdr->type = htonl (110);
|
||
eu2hdr->length = htonl(sizeof (Unified2ExtraDataHdr)
|
||
+ sizeof (Unified2ExtraData) + 4);
|
||
ehdr->event_type = htonl(4); // Extra hdr
|
||
ehdr->event_length = htonl(sizeof (Unified2ExtraDataHdr)
|
||
+ sizeof (Unified2ExtraData) + 4);
|
||
dhdr->sensor_id = 0;
|
||
dhdr->event_id = aun->event_id;
|
||
dhdr->event_second = htonl(p->ts.tv_sec);
|
||
dhdr->data_type = htonl(1);
|
||
dhdr->type = htonl(1);
|
||
dhdr->blob_length = htonl(12);
|
||
aun->length += sizeof(Unified2AlertFileHeader) + sizeof (Unified2ExtraDataHdr)
|
||
+ sizeof (Unified2ExtraData) + 4;
|
||
aun->offset += sizeof(Unified2AlertFileHeader) + sizeof (Unified2ExtraDataHdr)
|
||
+ sizeof (Unified2ExtraData) + 4;
|
||
*edxff=xffip;
|
||
//memcpy(aun->data + (aun->offset - 4), &xffip_net, 4);
|
||
/* Shift the *hdr and *phdr pointers */
|
||
hdr = (Unified2AlertFileHeader*)(edxff + 1);
|
||
phdr = (Unified2Packet *)(hdr + 1);
|
||
}
|
||
}
|
||
}
|
||
|
||
int ethh_offset = 0;
|
||
EthernetHdr ethhdr = { {0,0,0,0,0,0}, {0,0,0,0,0,0}, htons(ETHERNET_TYPE_IPV6) };
|
||
uint32_t hdr_length = 0;
|
||
... | ... | |
datalink = DLT_RAW;
|
||
}
|
||
aun->length = sizeof(Unified2AlertFileHeader) + UNIFIED2_PACKET_SIZE;
|
||
aun->offset = sizeof(Unified2AlertFileHeader) + UNIFIED2_PACKET_SIZE;
|
||
aun->length += sizeof(Unified2AlertFileHeader) + UNIFIED2_PACKET_SIZE;
|
||
aun->offset += sizeof(Unified2AlertFileHeader) + UNIFIED2_PACKET_SIZE;
|
||
/* Include Packet header */
|
||
if (PKT_IS_IPV4(p)) {
|
||
... | ... | |
SCLogError(SC_ERR_INVALID_VALUE, "len is too big for thread data");
|
||
goto error;
|
||
}
|
||
// If XFF in overwrite mode...
|
||
if (aun->unified2alert_ctx->flags & ALERT_UNIFIED2ALERT_XFF_OVERWRITE) {
|
||
if ( GetXFFIP (p, aun, ipbuf) == 1 ) {
|
||
in_addr_t xffip;
|
||
if ( inet_pton(AF_INET, ipbuf, &(xffip) ) == 1 ) {
|
||
fakehdr.ip4h.s_ip_src.s_addr = xffip;
|
||
}
|
||
}
|
||
}
|
||
memcpy(aun->data + aun->offset, &fakehdr, hdr_length);
|
||
aun->iphdr = (void *)(aun->data + aun->offset);
|
||
aun->offset += hdr_length;
|
||
} else if (PKT_IS_IPV6(p)) {
|
||
|
||
} else if (PKT_IS_IPV6(p)) {
|
||
FakeIPv6Hdr fakehdr;
|
||
hdr_length = sizeof(FakeIPv6Hdr);
|
||
... | ... | |
SCLogError(SC_ERR_INVALID_VALUE, "len is too big for thread data");
|
||
goto error;
|
||
}
|
||
if (aun->unified2alert_ctx->flags & ALERT_UNIFIED2ALERT_XFF_OVERWRITE) {
|
||
if ( GetXFFIP (p, aun, ipbuf) == 1 ) {
|
||
uint32_t xffip6[4];
|
||
if ( inet_pton(AF_INET6, ipbuf, xffip6 ) == 1 ) {
|
||
memcpy(fakehdr.ip6h.s_ip6_src, xffip6, 16);
|
||
}
|
||
}
|
||
}
|
||
|
||
memcpy(aun->data + aun->offset, &fakehdr, hdr_length);
|
||
aun->iphdr = (void *)(aun->data + aun->offset);
|
||
aun->offset += hdr_length;
|
||
... | ... | |
gphdr.event_second = htonl(p->ts.tv_sec);
|
||
gphdr.event_microsecond = htonl(p->ts.tv_usec);
|
||
gphdr.src_ip = *(struct in6_addr*)GET_IPV6_SRC_ADDR(p);
|
||
gphdr.dst_ip = *(struct in6_addr*)GET_IPV6_DST_ADDR(p);
|
||
gphdr.dst_ip = *(struct in6_addr*)GET_IPV6_DST_ADDR(p);
|
||
gphdr.protocol = p->proto;
|
||
if(p->action & ACTION_DROP)
|
||
... | ... | |
phdr->classification_id = htonl(pa->s->class);
|
||
phdr->priority_id = htonl(pa->s->prio);
|
||
SCMutexLock(&aun->file_ctx->fp_mutex);
|
||
if ((aun->file_ctx->size_current + length) > aun->file_ctx->size_limit) {
|
||
SCMutexLock(&aun->unified2alert_ctx->file_ctx->fp_mutex);
|
||
if ((aun->unified2alert_ctx->file_ctx->size_current + length)
|
||
> aun->unified2alert_ctx->file_ctx->size_limit) {
|
||
if (Unified2AlertRotateFile(t,aun) < 0) {
|
||
aun->file_ctx->alerts += i;
|
||
SCMutexUnlock(&aun->file_ctx->fp_mutex);
|
||
aun->unified2alert_ctx->file_ctx->alerts += i;
|
||
SCMutexUnlock(&aun->unified2alert_ctx->file_ctx->fp_mutex);
|
||
return -1;
|
||
}
|
||
}
|
||
if (Unified2Write(aun) != 1) {
|
||
aun->file_ctx->alerts += i;
|
||
SCMutexUnlock(&aun->file_ctx->fp_mutex);
|
||
aun->unified2alert_ctx->file_ctx->alerts += i;
|
||
SCMutexUnlock(&aun->unified2alert_ctx->file_ctx->fp_mutex);
|
||
return -1;
|
||
}
|
||
... | ... | |
pa->flags & (PACKET_ALERT_FLAG_STATE_MATCH|PACKET_ALERT_FLAG_STREAM_MATCH) ? 1 : 0);
|
||
if (ret != 1) {
|
||
SCLogError(SC_ERR_FWRITE, "Error: fwrite failed: %s", strerror(errno));
|
||
aun->file_ctx->alerts += i;
|
||
SCMutexUnlock(&aun->file_ctx->fp_mutex);
|
||
aun->unified2alert_ctx->file_ctx->alerts += i;
|
||
SCMutexUnlock(&aun->unified2alert_ctx->file_ctx->fp_mutex);
|
||
return -1;
|
||
}
|
||
fflush(aun->file_ctx->fp);
|
||
aun->file_ctx->alerts++;
|
||
SCMutexUnlock(&aun->file_ctx->fp_mutex);
|
||
fflush(aun->unified2alert_ctx->file_ctx->fp);
|
||
aun->unified2alert_ctx->file_ctx->alerts++;
|
||
SCMutexUnlock(&aun->unified2alert_ctx->file_ctx->fp_mutex);
|
||
}
|
||
return 0;
|
||
... | ... | |
gphdr.event_microsecond = htonl(p->ts.tv_usec);
|
||
gphdr.src_ip = p->ip4h->s_ip_src.s_addr;
|
||
gphdr.dst_ip = p->ip4h->s_ip_dst.s_addr;
|
||
// If XFF in overwrite mode...
|
||
if (aun->unified2alert_ctx->flags & ALERT_UNIFIED2ALERT_XFF_OVERWRITE) {
|
||
char ipbuf[128];
|
||
if ( GetXFFIP (p, aun, ipbuf) == 1 ) {
|
||
in_addr_t xffip;
|
||
if ( inet_pton(AF_INET, ipbuf, &(xffip) ) == 1 ) {
|
||
if (p->flowflags & FLOW_PKT_TOCLIENT) {
|
||
gphdr.dst_ip = xffip;
|
||
} else {
|
||
gphdr.src_ip = xffip;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
gphdr.protocol = IPV4_GET_RAW_IPPROTO(p->ip4h);
|
||
if(p->action & ACTION_DROP)
|
||
... | ... | |
phdr->priority_id = htonl(pa->s->prio);
|
||
/* check and enforce the filesize limit */
|
||
SCMutexLock(&aun->file_ctx->fp_mutex);
|
||
SCMutexLock(&aun->unified2alert_ctx->file_ctx->fp_mutex);
|
||
if ((aun->file_ctx->size_current + length) > aun->file_ctx->size_limit) {
|
||
if ((aun->unified2alert_ctx->file_ctx->size_current + length)
|
||
> aun->unified2alert_ctx->file_ctx->size_limit) {
|
||
if (Unified2AlertRotateFile(tv,aun) < 0) {
|
||
aun->file_ctx->alerts += i;
|
||
SCMutexUnlock(&aun->file_ctx->fp_mutex);
|
||
aun->unified2alert_ctx->file_ctx->alerts += i;
|
||
SCMutexUnlock(&aun->unified2alert_ctx->file_ctx->fp_mutex);
|
||
return -1;
|
||
}
|
||
}
|
||
if (Unified2Write(aun) != 1) {
|
||
aun->file_ctx->alerts += i;
|
||
SCMutexUnlock(&aun->file_ctx->fp_mutex);
|
||
aun->unified2alert_ctx->file_ctx->alerts += i;
|
||
SCMutexUnlock(&aun->unified2alert_ctx->file_ctx->fp_mutex);
|
||
return -1;
|
||
}
|
||
... | ... | |
ret = Unified2PacketTypeAlert(aun, p, event_id,
|
||
pa->flags & (PACKET_ALERT_FLAG_STATE_MATCH|PACKET_ALERT_FLAG_STREAM_MATCH) ? 1 : 0);
|
||
if (ret != 1) {
|
||
aun->file_ctx->alerts += i;
|
||
SCMutexUnlock(&aun->file_ctx->fp_mutex);
|
||
aun->unified2alert_ctx->file_ctx->alerts += i;
|
||
SCMutexUnlock(&aun->unified2alert_ctx->file_ctx->fp_mutex);
|
||
return -1;
|
||
}
|
||
fflush(aun->file_ctx->fp);
|
||
aun->file_ctx->alerts++;
|
||
SCMutexUnlock(&aun->file_ctx->fp_mutex);
|
||
fflush(aun->unified2alert_ctx->file_ctx->fp);
|
||
aun->unified2alert_ctx->file_ctx->alerts++;
|
||
SCMutexUnlock(&aun->unified2alert_ctx->file_ctx->fp_mutex);
|
||
}
|
||
return 0;
|
||
... | ... | |
return TM_ECODE_FAILED;
|
||
}
|
||
/** Use the Ouptut Context (file pointer and mutex) */
|
||
aun->file_ctx = ((OutputCtx *)initdata)->data;
|
||
aun->unified2alert_ctx = ((OutputCtx *)initdata)->data;
|
||
aun->data = SCMalloc(sizeof(Unified2AlertFileHeader) + sizeof(Unified2Packet) + IPV4_MAXPACKET_LEN);
|
||
aun->data = SCMalloc(sizeof(Unified2AlertFileHeader) + sizeof(Unified2Packet) +
|
||
IPV4_MAXPACKET_LEN + sizeof(Unified2ExtraDataHdr) + sizeof (Unified2ExtraData));
|
||
if (aun->data == NULL) {
|
||
SCFree(aun);
|
||
return TM_ECODE_FAILED;
|
||
}
|
||
aun->datalen = sizeof(Unified2AlertFileHeader) + sizeof(Unified2Packet) + IPV4_MAXPACKET_LEN;
|
||
aun->datalen = sizeof(Unified2AlertFileHeader) + sizeof(Unified2Packet) +
|
||
IPV4_MAXPACKET_LEN + sizeof(Unified2ExtraDataHdr) + sizeof (Unified2ExtraData);
|
||
*data = (void *)aun;
|
||
... | ... | |
goto error;
|
||
}
|
||
if (!(aun->file_ctx->flags & LOGFILE_ALERTS_PRINTED)) {
|
||
if (!(aun->unified2alert_ctx->file_ctx->flags & LOGFILE_ALERTS_PRINTED)) {
|
||
SCLogInfo("Alert unified2 module wrote %"PRIu64" alerts",
|
||
aun->file_ctx->alerts);
|
||
aun->unified2alert_ctx->file_ctx->alerts);
|
||
/* Do not print it for each thread */
|
||
aun->file_ctx->flags |= LOGFILE_ALERTS_PRINTED;
|
||
aun->unified2alert_ctx->file_ctx->flags |= LOGFILE_ALERTS_PRINTED;
|
||
}
|
||
... | ... | |
{
|
||
int ret = 0;
|
||
LogFileCtx* file_ctx = NULL;
|
||
OutputCtx* output_ctx = NULL;
|
||
|
||
file_ctx = LogFileNewCtx();
|
||
if (file_ctx == NULL) {
|
||
SCLogError(SC_ERR_UNIFIED2_ALERT_GENERIC, "Couldn't create new file_ctx");
|
||
... | ... | |
if (ret < 0)
|
||
goto error;
|
||
OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx));
|
||
output_ctx = SCCalloc(1, sizeof(OutputCtx));
|
||
if (output_ctx == NULL)
|
||
goto error;
|
||
output_ctx->data = file_ctx;
|
||
|
||
Unified2AlertFileCtx *unified2alert_ctx = SCMalloc(sizeof(Unified2AlertFileCtx));
|
||
if (unified2alert_ctx == NULL) {
|
||
goto error;
|
||
}
|
||
memset(unified2alert_ctx, 0x00, sizeof(Unified2AlertFileCtx));
|
||
unified2alert_ctx->file_ctx = file_ctx;
|
||
|
||
output_ctx->data = unified2alert_ctx;
|
||
output_ctx->DeInit = Unified2AlertDeInitCtx;
|
||
|
||
const char *xff = ConfNodeLookupChildValue(conf, "xff");
|
||
const char *xff_header = ConfNodeLookupChildValue(conf, "xffheadername");
|
||
const char *xff_overwrite = ConfNodeLookupChildValue(conf, "xffoverwrite");
|
||
|
||
if (xff != NULL && ConfValIsTrue(xff)) {
|
||
unified2alert_ctx->flags |= ALERT_UNIFIED2ALERT_XFF;
|
||
if (xff_header != NULL) {
|
||
unified2alert_ctx->xff_header = (char *) xff_header;
|
||
} else {
|
||
unified2alert_ctx->xff_header = ALERT_UNIFIED2ALERT_XFF_DEFAULT;
|
||
}
|
||
if (xff_overwrite != NULL && ConfValIsTrue(xff_overwrite)) {
|
||
unified2alert_ctx->flags |= ALERT_UNIFIED2ALERT_XFF_OVERWRITE;
|
||
}
|
||
}
|
||
SCLogInfo("Unified2-alert initialized: filename %s, limit %"PRIu64" MB",
|
||
filename, file_ctx->size_limit / (1024*1024));
|
||
... | ... | |
return output_ctx;
|
||
error:
|
||
if (output_ctx != NULL) {
|
||
SCFree(output_ctx);
|
||
}
|
||
|
||
if (file_ctx != NULL) {
|
||
LogFileFreeCtx(file_ctx);
|
||
}
|
||
... | ... | |
static void Unified2AlertDeInitCtx(OutputCtx *output_ctx)
|
||
{
|
||
if (output_ctx != NULL) {
|
||
LogFileCtx *logfile_ctx = (LogFileCtx *)output_ctx->data;
|
||
if (logfile_ctx != NULL) {
|
||
LogFileFreeCtx(logfile_ctx);
|
||
Unified2AlertFileCtx *unified2alert_ctx = (Unified2AlertFileCtx *) output_ctx->data;
|
||
if (unified2alert_ctx != NULL) {
|
||
LogFileCtx *logfile_ctx = unified2alert_ctx->file_ctx;
|
||
if (logfile_ctx != NULL) {
|
||
LogFileFreeCtx(logfile_ctx);
|
||
}
|
||
SCFree(unified2alert_ctx);
|
||
}
|
||
SCFree(output_ctx);
|
||
}
|
- « Previous
- 1
- …
- 5
- 6
- 7
- Next »