Unified output fixes: alert count per module (not per thread), fix timestamps on pcap mode, write *all* the alerts of a packet, write the log header once also on unified alert

remotes/origin/master-1.0.x
Pablo Rincon 16 years ago committed by Victor Julien
parent b02bb6b6b4
commit cef12d30b5

@ -55,7 +55,6 @@ void TmModuleAlertDebugLogRegister (void) {
typedef struct AlertDebugLogThread_ {
LogFileCtx *file_ctx;
/** LogFileCtx has the pointer to the file and a mutex to allow multithreading */
uint32_t alerts;
} AlertDebugLogThread;
static void CreateTimeString (const struct timeval *ts, char *str, size_t size) {
@ -138,7 +137,7 @@ TmEcode AlertDebugLogIPv4(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq
/* pkt vars */
/* flowvars */
aft->alerts += p->alerts.cnt;
aft->file_ctx->alerts += p->alerts.cnt;
fprintf(aft->file_ctx->fp, "PACKET LEN: %" PRIu32 "\n", p->pktlen);
fprintf(aft->file_ctx->fp, "PACKET:\n");
@ -159,7 +158,7 @@ TmEcode AlertDebugLogIPv6(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq
if (p->alerts.cnt == 0)
return TM_ECODE_OK;
aft->alerts += p->alerts.cnt;
aft->file_ctx->alerts += p->alerts.cnt;
CreateTimeString(&p->ts, timebuf, sizeof(timebuf));
@ -232,7 +231,7 @@ void AlertDebugLogExitPrintStats(ThreadVars *tv, void *data) {
return;
}
SCLogInfo("(%s) Alerts %" PRIu32 "", tv->name, aft->alerts);
SCLogInfo("(%s) Alerts %" PRIu64 "", tv->name, aft->file_ctx->alerts);
}

@ -78,7 +78,6 @@ void TmModuleAlertFastLogIPv6Register (void) {
typedef struct AlertFastLogThread_ {
/** LogFileCtx has the pointer to the file and a mutex to allow multithreading */
LogFileCtx* file_ctx;
uint32_t alerts;
} AlertFastLogThread;
static void CreateTimeString (const struct timeval *ts, char *str, size_t size) {
@ -101,14 +100,15 @@ TmEcode AlertFastLogIPv4(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq)
if (p->alerts.cnt == 0)
return TM_ECODE_OK;
aft->alerts += p->alerts.cnt;
CreateTimeString(&p->ts, timebuf, sizeof(timebuf));
SCMutexLock(&aft->file_ctx->fp_mutex);
aft->file_ctx->alerts += p->alerts.cnt;
for (i = 0; i < p->alerts.cnt; i++) {
PacketAlert *pa = &p->alerts.alerts[i];
char srcip[16], dstip[16];
inet_ntop(AF_INET, (const void *)GET_IPV4_SRC_ADDR_PTR(p), srcip, sizeof(srcip));
@ -116,8 +116,8 @@ TmEcode AlertFastLogIPv4(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq)
fprintf(aft->file_ctx->fp, "%s [**] [%" PRIu32 ":%" PRIu32 ":%" PRIu32 "] %s [**] [Classification: %s] [Priority: %" PRIu32 "] {%" PRIu32 "} %s:%" PRIu32 " -> %s:%" PRIu32 "\n",
timebuf, pa->gid, pa->sid, pa->rev, pa->msg, pa->class_msg, pa->prio, IPV4_GET_IPPROTO(p), srcip, p->sp, dstip, p->dp);
fflush(aft->file_ctx->fp);
}
fflush(aft->file_ctx->fp);
SCMutexUnlock(&aft->file_ctx->fp_mutex);
return TM_ECODE_OK;
@ -132,12 +132,12 @@ TmEcode AlertFastLogIPv6(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq)
if (p->alerts.cnt == 0)
return TM_ECODE_OK;
aft->alerts += p->alerts.cnt;
CreateTimeString(&p->ts, timebuf, sizeof(timebuf));
SCMutexLock(&aft->file_ctx->fp_mutex);
aft->file_ctx->alerts += p->alerts.cnt;
for (i = 0; i < p->alerts.cnt; i++) {
PacketAlert *pa = &p->alerts.alerts[i];
char srcip[46], dstip[46];
@ -204,7 +204,7 @@ void AlertFastLogExitPrintStats(ThreadVars *tv, void *data) {
return;
}
SCLogInfo("(%s) Alerts %" PRIu32 "", tv->name, aft->alerts);
SCLogInfo("(%s) Alerts %" PRIu64 "", tv->name, aft->file_ctx->alerts);
}
/**

@ -10,7 +10,13 @@
* - inspect gettimeofday for threadsafely
* - implement configuration
*
* Notes: barnyard-0.2.0 read "struct timeval" instead of
* struct timeval32 like snort, this means that on 64 bit arch, the log entries
* wont have the same length. To be sure to add compatibility for barnyard
* and other parsers, theres a macro available for 64 bit barnyard compatibility
* But if you want real snort compatibility, don't use that macro
*/
#define BARNYARD_64_COMPAT 1
#include "suricata-common.h"
#include "debug.h"
@ -53,8 +59,6 @@ void TmModuleAlertUnifiedAlertRegister (void) {
typedef struct AlertUnifiedAlertThread_ {
/** LogFileCtx has the pointer to the file and a mutex to allow multithreading */
LogFileCtx* file_ctx;
uint32_t size_limit;
uint32_t size_current;
} AlertUnifiedAlertThread;
#define ALERTUNIFIEDALERT_ALERTMAGIC 0xDEAD4137 /* taken from Snort */
@ -74,25 +78,35 @@ typedef struct AlertUnifiedAlertPacketHeader_ {
uint32_t sig_sid;
uint32_t sig_rev;
uint32_t sig_class;
uint32_t sig_prio;
uint32_t pad1; /* Snort's event_id */
uint32_t pad2; /* Snort's event_reference */
#ifdef BARNYARD_64_COMPAT
uint64_t tv_sec1; /* from Snort's struct pcap_timeval in Event */
uint64_t tv_usec1; /* from Snort's struct pcap_timeval in Event */
uint64_t tv_sec2; /* from Snort's struct pcap_timeval */
uint64_t tv_usec2; /* from Snort's struct pcap_timeval */
#else
uint32_t tv_sec1; /* from Snort's struct pcap_timeval in Event */
uint32_t tv_usec1; /* from Snort's struct pcap_timeval in Event */
uint32_t tv_sec2; /* from Snort's struct pcap_timeval */
uint32_t tv_usec2; /* from Snort's struct pcap_timeval */
#endif
uint32_t src_ip;
uint32_t dst_ip;
uint16_t sp;
uint16_t dp;
uint32_t protocol;
uint32_t flags;
} AlertUnifiedAlertPacketHeader;
int AlertUnifiedAlertWriteFileHeader(ThreadVars *t, AlertUnifiedAlertThread *aun) {
int AlertUnifiedAlertWriteFileHeader(LogFileCtx *file_ctx) {
int ret;
if (file_ctx->flags & LOGFILE_HEADER_WRITTEN)
return 0;
/** write the fileheader to the file so the reader can recognize it */
AlertUnifiedAlertFileHeader hdr;
@ -101,15 +115,17 @@ int AlertUnifiedAlertWriteFileHeader(ThreadVars *t, AlertUnifiedAlertThread *aun
hdr.ver_minor = ALERTUNIFIEDALERT_VERMINOR;
hdr.timezone = 0; /* XXX */
ret = fwrite(&hdr, sizeof(hdr), 1, aun->file_ctx->fp);
ret = fwrite(&hdr, sizeof(AlertUnifiedAlertFileHeader), 1, file_ctx->fp);
if (ret != 1) {
SCLogError(SC_ERR_FWRITE, "Error: fwrite failed: ret = %" PRId32 ", %s",
ret, strerror(errno));
return -1;
}
fflush(aun->file_ctx->fp);
fflush(file_ctx->fp);
aun->size_current = sizeof(hdr);
file_ctx->size_current = sizeof(hdr);
file_ctx->flags |= LOGFILE_HEADER_WRITTEN;
return 0;
}
@ -117,7 +133,8 @@ int AlertUnifiedAlertCloseFile(ThreadVars *t, AlertUnifiedAlertThread *aun) {
if (aun->file_ctx->fp != NULL) {
fclose(aun->file_ctx->fp);
}
aun->size_current = 0;
aun->file_ctx->size_current = 0;
aun->file_ctx->flags = 0;
return 0;
}
@ -133,7 +150,7 @@ int AlertUnifiedAlertRotateFile(ThreadVars *t, AlertUnifiedAlertThread *aun) {
"Error: AlertUnifiedLogOpenFileCtx, open new log file failed");
return -1;
}
if (AlertUnifiedAlertWriteFileHeader(t, aun) < 0) {
if (AlertUnifiedAlertWriteFileHeader(aun->file_ctx) < 0) {
SCLogError(SC_ERR_UNIFIED_ALERT_GENERIC, "Error: "
"AlertUnifiedLogAppendFile, write unified header failed");
return -1;
@ -146,6 +163,7 @@ TmEcode AlertUnifiedAlert (ThreadVars *tv, Packet *p, void *data, PacketQueue *p
{
AlertUnifiedAlertThread *aun = (AlertUnifiedAlertThread *)data;
AlertUnifiedAlertPacketHeader hdr;
int ret;
uint8_t ethh_offset = 0;
@ -159,27 +177,7 @@ TmEcode AlertUnifiedAlert (ThreadVars *tv, Packet *p, void *data, PacketQueue *p
ethh_offset = sizeof(EthernetHdr);
}
/** check and enforce the filesize limit, thread safe */
SCMutexLock(&aun->file_ctx->fp_mutex);
if ((aun->size_current + sizeof(hdr)) > aun->size_limit) {
if (AlertUnifiedAlertRotateFile(tv,aun) < 0)
{
SCMutexUnlock(&aun->file_ctx->fp_mutex);
return TM_ECODE_FAILED;
}
}
SCMutexUnlock(&aun->file_ctx->fp_mutex);
/* XXX which one to add to this alert? Lets see how Snort solves this.
* For now just take last alert. */
PacketAlert *pa = &p->alerts.alerts[p->alerts.cnt-1];
/* fill the hdr structure */
hdr.sig_gen = pa->gid;
hdr.sig_sid = pa->sid;
hdr.sig_rev = pa->rev;
hdr.sig_class = pa->class;
hdr.sig_prio = pa->prio;
/* fill the hdr structure with the data of the packet */
hdr.pad1 = 0;
hdr.pad2 = 0;
hdr.tv_sec1 = hdr.tv_sec2 = p->ts.tv_sec;
@ -191,17 +189,43 @@ TmEcode AlertUnifiedAlert (ThreadVars *tv, Packet *p, void *data, PacketQueue *p
hdr.protocol = IPV4_GET_RAW_IPPROTO(p->ip4h);
hdr.flags = 0;
/* write and flush so it's written immediately */
ret = fwrite(&hdr, sizeof(hdr), 1, aun->file_ctx->fp);
if (ret != 1) {
SCLogError(SC_ERR_FWRITE, "Error: fwrite failed: %s", strerror(errno));
return TM_ECODE_FAILED;
uint16_t i = 0;
for (; i < p->alerts.cnt; i++) {
PacketAlert *pa = &p->alerts.alerts[i];
/* fill the rest of the hdr structure with the data of the alert */
hdr.sig_gen = pa->gid;
hdr.sig_sid = pa->sid;
hdr.sig_rev = pa->rev;
hdr.sig_class = pa->class;
hdr.sig_prio = pa->prio;
SCMutexLock(&aun->file_ctx->fp_mutex);
/** check and enforce the filesize limit, thread safe */
if ((aun->file_ctx->size_current + sizeof(hdr)) > aun->file_ctx->size_limit) {
if (AlertUnifiedAlertRotateFile(tv,aun) < 0) {
SCMutexUnlock(&aun->file_ctx->fp_mutex);
aun->file_ctx->alerts += i;
return TM_ECODE_FAILED;
}
}
/* Then the unified header */
ret = fwrite(&hdr, sizeof(AlertUnifiedAlertPacketHeader), 1, aun->file_ctx->fp);
if (ret != 1) {
SCLogError(SC_ERR_FWRITE, "Error: fwrite failed: %s", strerror(errno));
SCMutexUnlock(&aun->file_ctx->fp_mutex);
aun->file_ctx->alerts += i;
return TM_ECODE_FAILED;
}
/* force writing to disk so barnyard will not read half
* written records and choke. */
fflush(aun->file_ctx->fp);
SCMutexUnlock(&aun->file_ctx->fp_mutex);
aun->file_ctx->size_current += sizeof(hdr);
}
/* force writing to disk so barnyard will not read half
* written records and choke. */
fflush(aun->file_ctx->fp);
aun->file_ctx->alerts += p->alerts.cnt;
aun->size_current += sizeof(hdr);
return TM_ECODE_OK;
}
@ -213,27 +237,13 @@ TmEcode AlertUnifiedAlertThreadInit(ThreadVars *t, void *initdata, void **data)
}
memset(aun, 0, sizeof(AlertUnifiedAlertThread));
if(initdata == NULL)
{
if (initdata == NULL) {
SCLogDebug("Error getting context for UnifiedAlert. \"initdata\" argument NULL");
free(aun);
return TM_ECODE_FAILED;
}
/** Use the Ouptut Context (file pointer and mutex) */
aun->file_ctx = (LogFileCtx*) initdata;
aun->size_limit = 30;
/** Write Unified header */
int ret = AlertUnifiedAlertWriteFileHeader(t, aun);
if (ret != 0) {
SCLogError(SC_ERR_UNIFIED_ALERT_GENERIC,
"Error: AlertUnifiedLogWriteFileHeader failed");
free(aun);
return TM_ECODE_FAILED;
}
/* XXX make configurable */
aun->size_limit = 10 * 1024 * 1024;
*data = (void *)aun;
return TM_ECODE_OK;
@ -246,6 +256,11 @@ TmEcode AlertUnifiedAlertThreadDeinit(ThreadVars *t, void *data)
goto error;
}
if (!(aun->file_ctx->flags & LOGFILE_ALERTS_PRINTED)) {
SCLogInfo("Alert unified 1 alert module wrote %"PRIu64" alerts", aun->file_ctx->alerts);
/* Do not print it for each thread */
aun->file_ctx->flags |= LOGFILE_ALERTS_PRINTED;
}
/* clear memory */
memset(aun, 0, sizeof(AlertUnifiedAlertThread));
free(aun);
@ -279,6 +294,8 @@ LogFileCtx *AlertUnifiedAlertInitCtx(ConfNode *conf)
file_ctx->prefix = strdup(filename);
ret = AlertUnifiedAlertOpenFileCtx(file_ctx, filename);
/* XXX make configurable */
file_ctx->size_limit = UNIFIED_FILESIZE_LIMIT;
if (ret < 0)
return NULL;
@ -303,7 +320,12 @@ int AlertUnifiedAlertOpenFileCtx(LogFileCtx *file_ctx, const char *prefix)
/* get the time so we can have a filename with seconds since epoch */
struct timeval ts;
memset (&ts, 0, sizeof(struct timeval));
TimeGet(&ts);
extern int run_mode;
if (run_mode == MODE_UNITTEST)
TimeGet(&ts);
else
gettimeofday(&ts, NULL);
/* create the filename to use */
char *log_dir;
@ -319,8 +341,17 @@ int AlertUnifiedAlertOpenFileCtx(LogFileCtx *file_ctx, const char *prefix)
strerror(errno));
ret = -1;
}
file_ctx->flags = 0;
/** Write Unified header */
ret = AlertUnifiedAlertWriteFileHeader(file_ctx);
if (ret != 0) {
SCLogError(SC_ERR_UNIFIED_ALERT_GENERIC,
"Error: AlertUnifiedLogWriteFileHeader failed");
return TM_ECODE_FAILED;
}
return ret;
return TM_ECODE_OK;
}
#ifdef UNITTESTS

@ -10,7 +10,13 @@
* - inspect gettimeofday for threadsafely
* - implement configuration
*
* Notes: barnyard-0.2.0 read "struct timeval" instead of
* struct timeval32 like snort, this means that on 64 bit arch, the log entries
* wont have the same length. To be sure to add compatibility for barnyard
* and other parsers, theres a macro available for 64 bit barnyard compatibility
* But if you want real snort compatibility, don't use that macro
*/
#define BARNYARD_64_COMPAT 1
#include <string.h>
@ -80,8 +86,19 @@ typedef struct AlertUnifiedLogPacketHeader_ {
uint32_t sig_prio;
uint32_t pad1; /* Snort's event_id */
uint32_t pad2; /* Snort's event_reference */
uint32_t tv_sec1; /* from Snort's struct pcap_timeval */
uint32_t tv_usec1; /* from Snort's struct pcap_timeval */
#ifdef BARNYARD_64_COMPAT
uint64_t tv_sec1; /* from Snort's struct pcap_timeval in Event */
uint64_t tv_usec1; /* from Snort's struct pcap_timeval in Event */
/* 32 bit unsigned flags */
uint32_t pktflags;
/* Snort's 'SnortPktHeader' structure */
uint64_t tv_sec2; /* from Snort's struct pcap_timeval */
uint64_t tv_usec2; /* from Snort's struct pcap_timeval */
#else
uint32_t tv_sec1; /* from Snort's struct pcap_timeval in Event */
uint32_t tv_usec1; /* from Snort's struct pcap_timeval in Event */
/* 32 bit unsigned flags */
uint32_t pktflags;
@ -89,12 +106,17 @@ typedef struct AlertUnifiedLogPacketHeader_ {
/* Snort's 'SnortPktHeader' structure */
uint32_t tv_sec2; /* from Snort's struct pcap_timeval */
uint32_t tv_usec2; /* from Snort's struct pcap_timeval */
#endif
uint32_t caplen;
uint32_t pktlen;
} AlertUnifiedLogPacketHeader;
int AlertUnifiedLogWriteFileHeader(LogFileCtx *file_ctx) {
int ret;
if (file_ctx->flags & LOGFILE_HEADER_WRITTEN)
return 0;
/* write the fileheader to the file so the reader can recognize it */
AlertUnifiedLogFileHeader hdr;
@ -121,6 +143,7 @@ int AlertUnifiedLogCloseFile(ThreadVars *t, AlertUnifiedLogThread *aun) {
fclose(aun->file_ctx->fp);
}
aun->file_ctx->size_current = 0;
aun->file_ctx->flags = 0;
return 0;
}
@ -157,29 +180,7 @@ TmEcode AlertUnifiedLog (ThreadVars *tv, Packet *p, void *data, PacketQueue *pq)
ethh_offset = sizeof(EthernetHdr);
}
/* check and enforce the filesize limit */
/** Wait for the mutex. We dont want all the threads rotating the file
* at the same time :) */
SCMutexLock(&aun->file_ctx->fp_mutex);
if ((aun->file_ctx->size_current + sizeof(hdr) + p->pktlen + ethh_offset) > aun->file_ctx->size_limit) {
if (AlertUnifiedLogRotateFile(tv,aun) < 0)
{
SCMutexUnlock(&aun->file_ctx->fp_mutex);
return TM_ECODE_FAILED;
}
}
SCMutexUnlock(&aun->file_ctx->fp_mutex);
/* XXX which one to add to this alert? Lets see how Snort solves this.
* For now just take last alert. */
PacketAlert *pa = &p->alerts.alerts[p->alerts.cnt-1];
/* fill the hdr structure */
hdr.sig_gen = pa->gid;
hdr.sig_sid = pa->sid;
hdr.sig_rev = pa->rev;
hdr.sig_class = pa->class;
hdr.sig_prio = pa->prio;
/* fill the hdr structure with the data of the packet */
hdr.pad1 = 0;
hdr.pad2 = 0;
hdr.tv_sec1 = hdr.tv_sec2 = p->ts.tv_sec;
@ -187,32 +188,59 @@ TmEcode AlertUnifiedLog (ThreadVars *tv, Packet *p, void *data, PacketQueue *pq)
hdr.pktflags = 0; /* XXX */
hdr.pktlen = hdr.caplen = p->pktlen + ethh_offset;
memcpy(buf,&hdr,sizeof(hdr));
buflen = sizeof(hdr);
if (p->ethh == NULL) {
EthernetHdr ethh;
memset(&ethh, 0, sizeof(EthernetHdr));
ethh.eth_type = htons(ETHERNET_TYPE_IP);
uint16_t i = 0;
for (; i < p->alerts.cnt; i++) {
PacketAlert *pa = &p->alerts.alerts[i];
memcpy(buf+buflen,&ethh,sizeof(ethh));
buflen += sizeof(ethh);
}
/* fill the hdr structure with the data of the alert */
hdr.sig_gen = pa->gid;
hdr.sig_sid = pa->sid;
hdr.sig_rev = pa->rev;
hdr.sig_class = pa->class;
hdr.sig_prio = pa->prio;
memcpy(buf+buflen,&p->pkt,p->pktlen);
buflen += p->pktlen;
memcpy(buf,&hdr,sizeof(hdr));
buflen = sizeof(hdr);
/** write and flush so it's written immediately, no need to lock her, no need to lock heree */
ret = fwrite(buf, buflen, 1, aun->file_ctx->fp);
if (ret != 1) {
printf("Error: fwrite failed: %s\n", strerror(errno));
return TM_ECODE_FAILED;
if (p->ethh == NULL) {
EthernetHdr ethh;
memset(&ethh, 0, sizeof(EthernetHdr));
ethh.eth_type = htons(ETHERNET_TYPE_IP);
memcpy(buf+buflen,&ethh,sizeof(ethh));
buflen += sizeof(ethh);
}
memcpy(buf+buflen,&p->pkt,p->pktlen);
buflen += p->pktlen;
/** Wait for the mutex. We dont want all the threads rotating the file
* at the same time :) */
SCMutexLock(&aun->file_ctx->fp_mutex);
if ((aun->file_ctx->size_current + sizeof(hdr) + p->pktlen + ethh_offset) > aun->file_ctx->size_limit) {
if (AlertUnifiedLogRotateFile(tv,aun) < 0) {
SCMutexUnlock(&aun->file_ctx->fp_mutex);
aun->file_ctx->alerts += i;
return TM_ECODE_FAILED;
}
}
ret = fwrite(buf, buflen, 1, aun->file_ctx->fp);
if (ret != 1) {
printf("Error: fwrite failed: %s\n", strerror(errno));
aun->file_ctx->alerts += i;
SCMutexUnlock(&aun->file_ctx->fp_mutex);
return TM_ECODE_FAILED;
}
/* force writing to disk so barnyard will not read half
* written records and choke. */
fflush(aun->file_ctx->fp);
SCMutexUnlock(&aun->file_ctx->fp_mutex);
aun->file_ctx->size_current += buflen;
}
/* force writing to disk so barnyard will not read half
* written records and choke. */
fflush(aun->file_ctx->fp);
aun->file_ctx->alerts += p->alerts.cnt;
aun->file_ctx->size_current += buflen;
return TM_ECODE_OK;
}
@ -223,8 +251,8 @@ TmEcode AlertUnifiedLogThreadInit(ThreadVars *t, void *initdata, void **data)
return TM_ECODE_FAILED;
}
memset(aun, 0, sizeof(AlertUnifiedLogThread));
if(initdata == NULL)
{
if (initdata == NULL) {
SCLogDebug("Error getting context for UnifiedLog. \"initdata\" argument NULL");
free(aun);
return TM_ECODE_FAILED;
@ -243,6 +271,12 @@ TmEcode AlertUnifiedLogThreadDeinit(ThreadVars *t, void *data)
goto error;
}
if (!(aun->file_ctx->flags & LOGFILE_ALERTS_PRINTED)) {
SCLogInfo("Alert unified 1 log module wrote %"PRIu64" alerts", aun->file_ctx->alerts);
/* Do not print it for each thread */
aun->file_ctx->flags |= LOGFILE_ALERTS_PRINTED;
}
/* clear memory */
memset(aun, 0, sizeof(AlertUnifiedLogThread));
free(aun);
@ -260,11 +294,10 @@ error:
* */
LogFileCtx *AlertUnifiedLogInitCtx(ConfNode *conf)
{
int ret=0;
int ret = 0;
LogFileCtx* file_ctx=LogFileNewCtx();
if(file_ctx == NULL)
{
if (file_ctx == NULL) {
printf("AlertUnifiedLogInitCtx: Couldn't create new file_ctx\n");
return NULL;
}
@ -277,11 +310,11 @@ LogFileCtx *AlertUnifiedLogInitCtx(ConfNode *conf)
filename = DEFAULT_LOG_FILENAME;
file_ctx->prefix = strdup(filename);
file_ctx->size_limit = 1 * 1024 * 1024; /* XXX Make configurable. */
file_ctx->size_limit = UNIFIED_FILESIZE_LIMIT; /* XXX Make configurable. */
ret=AlertUnifiedLogOpenFileCtx(file_ctx, filename);
ret = AlertUnifiedLogOpenFileCtx(file_ctx, filename);
if(ret < 0)
if (ret < 0)
return NULL;
return file_ctx;
@ -304,7 +337,12 @@ int AlertUnifiedLogOpenFileCtx(LogFileCtx *file_ctx, const char *prefix)
/* get the time so we can have a filename with seconds since epoch */
struct timeval ts;
memset (&ts, 0, sizeof(struct timeval));
TimeGet(&ts);
extern int run_mode;
if (run_mode == MODE_UNITTEST)
TimeGet(&ts);
else
gettimeofday(&ts, NULL);
/* create the filename to use */
char *log_dir;
@ -321,8 +359,14 @@ int AlertUnifiedLogOpenFileCtx(LogFileCtx *file_ctx, const char *prefix)
ret = -1;
}
/* Write out the header. */
return AlertUnifiedLogWriteFileHeader(file_ctx);
/** Write Unified header */
ret = AlertUnifiedLogWriteFileHeader(file_ctx);
if (ret != 0) {
printf("Error: AlertUnifiedLogWriteFileHeader failed.\n");
return TM_ECODE_FAILED;
}
return TM_ECODE_OK;
}
#ifdef UNITTESTS

@ -48,8 +48,6 @@ int Unified2AlertOpenFileCtx(LogFileCtx *, const char *);
*/
typedef struct Unified2AlertThread_ {
LogFileCtx *file_ctx; /** LogFileCtx pointer */
uint32_t size_limit; /**< file size limit */
uint32_t size_current; /**< file current size */
} Unified2AlertThread;
/**
@ -147,7 +145,7 @@ int Unified2AlertCloseFile(ThreadVars *t, Unified2AlertThread *aun) {
if (aun->file_ctx->fp != NULL) {
fclose(aun->file_ctx->fp);
}
aun->size_current = 0;
aun->file_ctx->size_current = 0;
return 0;
}
@ -196,6 +194,7 @@ TmEcode Unified2Alert (ThreadVars *t, Packet *p, void *data, PacketQueue *pq)
/**
* \brief Function to fill unified2 packet format into the file.
* No need to lock here, since it's already locked
*
* \param t Thread Variable containing input/output queue, cpu affinity etc.
* \param p Packet struct used to decide for ipv4 or ipv6
@ -203,7 +202,6 @@ TmEcode Unified2Alert (ThreadVars *t, Packet *p, void *data, PacketQueue *pq)
* \retval 0 on succces
* \retval -1 on failure
*/
int Unified2PacketTypeAlert (ThreadVars *t, Packet *p, void *data)
{
Unified2AlertThread *aun = (Unified2AlertThread *)data;
@ -227,16 +225,6 @@ int Unified2PacketTypeAlert (ThreadVars *t, Packet *p, void *data)
memcpy(write_buffer,&hdr,sizeof(Unified2AlertFileHeader));
SCMutexLock(&aun->file_ctx->fp_mutex);
if ((aun->size_current + (sizeof(hdr) + sizeof(phdr))) > aun->size_limit) {
if (Unified2AlertRotateFile(t,aun) < 0)
{
SCMutexUnlock(&aun->file_ctx->fp_mutex);
return -1;
}
}
SCMutexUnlock(&aun->file_ctx->fp_mutex);
phdr.sensor_id = 0;
phdr.linktype = htonl(p->datalink);
phdr.event_id = 0;
@ -252,9 +240,7 @@ int Unified2PacketTypeAlert (ThreadVars *t, Packet *p, void *data)
SCLogError(SC_ERR_FWRITE, "Error: fwrite failed: %s", strerror(errno));
return -1;
}
fflush(aun->file_ctx->fp);
aun->size_current += len;
aun->file_ctx->size_current += len;
return 0;
}
@ -301,30 +287,10 @@ int Unified2IPv6TypeAlert (ThreadVars *t, Packet *p, void *data, PacketQueue *pq
ethh_offset = sizeof(EthernetHdr);
}
/* check and enforce the filesize limit */
SCMutexLock(&aun->file_ctx->fp_mutex);
if ((aun->size_current +(sizeof(hdr) + sizeof(phdr))) > aun->size_limit) {
if (Unified2AlertRotateFile(t,aun) < 0)
{
SCMutexUnlock(&aun->file_ctx->fp_mutex);
return -1;
}
}
SCMutexUnlock(&aun->file_ctx->fp_mutex);
/* XXX which one to add to this alert? Lets see how Snort solves this.
* For now just take last alert. */
pa = &p->alerts.alerts[p->alerts.cnt-1];
/* fill the phdr structure */
/* fill the phdr structure with the data of the packet */
phdr.sensor_id = 0;
phdr.event_id = 0;
phdr.generator_id = htonl(pa->gid);
phdr.signature_id = htonl(pa->sid);
phdr.signature_revision = htonl(pa->rev);
phdr.classification_id = htonl(pa->class);
phdr.priority_id = htonl(pa->prio);
phdr.event_second = htonl(p->ts.tv_sec);
phdr.event_microsecond = htonl(p->ts.tv_usec);
phdr.src_ip = *(struct in6_addr*)GET_IPV6_SRC_ADDR(p);
@ -337,10 +303,22 @@ int Unified2IPv6TypeAlert (ThreadVars *t, Packet *p, void *data, PacketQueue *pq
phdr.packet_action = 0;
switch(phdr.protocol) {
case IPPROTO_ICMPV6:
if(p->icmpv6h) {
phdr.sp = htons(p->icmpv6h->type);
phdr.dp = htons(p->icmpv6h->code);
} else {
phdr.sp = 0;
phdr.dp = 0;
}
break;
case IPPROTO_ICMP:
if(p->icmpv4h) {
phdr.sp = htons(p->icmpv4h->type);
phdr.dp = htons(p->icmpv4h->code);
} else {
phdr.sp = 0;
phdr.dp = 0;
}
break;
case IPPROTO_UDP:
@ -355,18 +333,47 @@ int Unified2IPv6TypeAlert (ThreadVars *t, Packet *p, void *data, PacketQueue *pq
break;
}
memcpy(write_buffer+sizeof(Unified2AlertFileHeader),&phdr,sizeof(AlertIPv6Unified2));
uint16_t i = 0;
for (; i < p->alerts.cnt; i++) {
pa = &p->alerts.alerts[i];
ret = fwrite(write_buffer,len, 1, aun->file_ctx->fp);
if (ret != 1) {
SCLogError(SC_ERR_FWRITE, "Error: fwrite failed: %s", strerror(errno));
return -1;
}
/* fill the header structure with the data of the alert */
phdr.generator_id = htonl(pa->gid);
phdr.signature_id = htonl(pa->sid);
phdr.signature_revision = htonl(pa->rev);
phdr.classification_id = htonl(pa->class);
phdr.priority_id = htonl(pa->prio);
memcpy(write_buffer+sizeof(Unified2AlertFileHeader),&phdr,sizeof(AlertIPv6Unified2));
SCMutexLock(&aun->file_ctx->fp_mutex);
if ((aun->file_ctx->size_current +(sizeof(hdr) + sizeof(phdr))) > aun->file_ctx->size_limit) {
if (Unified2AlertRotateFile(t,aun) < 0) {
SCMutexUnlock(&aun->file_ctx->fp_mutex);
aun->file_ctx->alerts += i;
return -1;
}
}
ret = fwrite(write_buffer,len, 1, aun->file_ctx->fp);
if (ret != 1) {
SCLogError(SC_ERR_FWRITE, "Error: fwrite failed: %s", strerror(errno));
SCMutexUnlock(&aun->file_ctx->fp_mutex);
aun->file_ctx->alerts += i;
return -1;
}
fflush(aun->file_ctx->fp);
fflush(aun->file_ctx->fp);
aun->size_current += len;
aun->file_ctx->size_current += len;
Unified2PacketTypeAlert(t, p, data);
Unified2PacketTypeAlert(t, p, data);
SCMutexUnlock(&aun->file_ctx->fp_mutex);
}
aun->file_ctx->alerts += p->alerts.cnt;
return 0;
}
@ -405,43 +412,24 @@ int Unified2IPv4TypeAlert (ThreadVars *tv, Packet *p, void *data, PacketQueue *p
hdr.length = htonl(sizeof(AlertIPv4Unified2));
memcpy(write_buffer,&hdr,sizeof(Unified2AlertFileHeader));
/* if we have no ethernet header (e.g. when using nfq), we have to create
* one ourselves. */
if (p->ethh == NULL) {
ethh_offset = sizeof(EthernetHdr);
}
/* check and enforce the filesize limit */
SCMutexLock(&aun->file_ctx->fp_mutex);
if ((aun->size_current +(sizeof(hdr) + sizeof(phdr))) > aun->size_limit) {
if (Unified2AlertRotateFile(tv,aun) < 0)
{
SCMutexUnlock(&aun->file_ctx->fp_mutex);
return -1;
}
}
SCMutexUnlock(&aun->file_ctx->fp_mutex);
/* XXX which one to add to this alert? Lets see how Snort solves this.
* For now just take last alert. */
pa = &p->alerts.alerts[p->alerts.cnt-1];
/* fill the hdr structure */
/* fill the hdr structure with the packet data */
phdr.sensor_id = 0;
phdr.event_id = 0;
phdr.generator_id = htonl(pa->gid);
phdr.signature_id = htonl(pa->sid);
phdr.signature_revision = htonl(pa->rev);
phdr.classification_id = htonl(pa->class);
phdr.priority_id = htonl(pa->prio);
phdr.event_second = htonl(p->ts.tv_sec);
phdr.event_microsecond = htonl(p->ts.tv_usec);
phdr.src_ip = p->ip4h->ip_src.s_addr;
phdr.dst_ip = p->ip4h->ip_dst.s_addr;
phdr.protocol = IPV4_GET_RAW_IPPROTO(p->ip4h);
if(p->action & ACTION_DROP)
phdr.packet_action = UNIFIED2_BLOCKED_FLAG;
else
@ -466,18 +454,49 @@ int Unified2IPv4TypeAlert (ThreadVars *tv, Packet *p, void *data, PacketQueue *p
break;
}
memcpy(write_buffer+sizeof(Unified2AlertFileHeader),&phdr,sizeof(AlertIPv4Unified2));
uint16_t i = 0;
for (; i < p->alerts.cnt; i++) {
pa = &p->alerts.alerts[i];
/* fill the hdr structure with the alert data */
phdr.generator_id = htonl(pa->gid);
phdr.signature_id = htonl(pa->sid);
phdr.signature_revision = htonl(pa->rev);
phdr.classification_id = htonl(pa->class);
phdr.priority_id = htonl(pa->prio);
memcpy(write_buffer+sizeof(Unified2AlertFileHeader),&phdr,sizeof(AlertIPv4Unified2));
/* check and enforce the filesize limit */
SCMutexLock(&aun->file_ctx->fp_mutex);
if ((aun->file_ctx->size_current +(sizeof(hdr) + sizeof(phdr))) > aun->file_ctx->size_limit) {
if (Unified2AlertRotateFile(tv,aun) < 0) {
SCMutexUnlock(&aun->file_ctx->fp_mutex);
aun->file_ctx->alerts += i;
return -1;
}
}
ret = fwrite(write_buffer,len, 1, aun->file_ctx->fp);
if (ret != 1) {
SCLogError(SC_ERR_FWRITE, "Error: fwrite failed: %s", strerror(errno));
return -1;
}
ret = fwrite(write_buffer,len, 1, aun->file_ctx->fp);
if (ret != 1) {
SCLogError(SC_ERR_FWRITE, "Error: fwrite failed: %s", strerror(errno));
SCMutexUnlock(&aun->file_ctx->fp_mutex);
aun->file_ctx->alerts += i;
return -1;
}
fflush(aun->file_ctx->fp);
aun->file_ctx->size_current += len;
fflush(aun->file_ctx->fp);
aun->size_current += len;
/* Write the alert (it doesn't lock inside, since we
* already locked here for rotation check)
*/
Unified2PacketTypeAlert(tv, p, data);
SCMutexUnlock(&aun->file_ctx->fp_mutex);
}
aun->file_ctx->alerts += p->alerts.cnt;
Unified2PacketTypeAlert(tv, p, data);
return 0;
}
@ -508,9 +527,6 @@ TmEcode Unified2AlertThreadInit(ThreadVars *t, void *initdata, void **data)
/** Use the Ouptut Context (file pointer and mutex) */
aun->file_ctx = (LogFileCtx*) initdata;
/* XXX make configurable */
aun->size_limit = 10 * 1024 * 1024;
*data = (void *)aun;
return TM_ECODE_OK;
}
@ -531,6 +547,12 @@ TmEcode Unified2AlertThreadDeinit(ThreadVars *t, void *data)
goto error;
}
if (!(aun->file_ctx->flags & LOGFILE_ALERTS_PRINTED)) {
SCLogInfo("Alert unified 2 module wrote %"PRIu64" alerts", aun->file_ctx->alerts);
/* Do not print it for each thread */
aun->file_ctx->flags |= LOGFILE_ALERTS_PRINTED;
}
/* clear memory */
memset(aun, 0, sizeof(Unified2AlertThread));
free(aun);
@ -549,8 +571,7 @@ LogFileCtx *Unified2AlertInitCtx(ConfNode *conf)
int ret=0;
LogFileCtx* file_ctx=LogFileNewCtx();
if(file_ctx == NULL)
{
if (file_ctx == NULL) {
SCLogError(SC_ERR_UNIFIED2_ALERT_GENERIC, "Unified2AlertInitCtx: "
"Couldn't create new file_ctx");
return NULL;
@ -564,9 +585,12 @@ LogFileCtx *Unified2AlertInitCtx(ConfNode *conf)
filename = DEFAULT_LOG_FILENAME;
file_ctx->prefix = strdup(filename);
ret=Unified2AlertOpenFileCtx(file_ctx, filename);
ret = Unified2AlertOpenFileCtx(file_ctx, filename);
if(ret < 0)
/* XXX make configurable */
file_ctx->size_limit = UNIFIED_FILESIZE_LIMIT;
if (ret < 0)
return NULL;
return file_ctx;
@ -589,7 +613,12 @@ int Unified2AlertOpenFileCtx(LogFileCtx *file_ctx, const char *prefix)
/** get the time so we can have a filename with seconds since epoch */
struct timeval ts;
memset(&ts, 0x00, sizeof(struct timeval));
TimeGet(&ts);
extern int run_mode;
if (run_mode == MODE_UNITTEST)
TimeGet(&ts);
else
gettimeofday(&ts, NULL);
/* create the filename to use */
char *log_dir;

@ -8,6 +8,9 @@
#ifndef __OUTPUT_H__
#define __OUTPUT_H__
#include "suricata.h"
#define UNIFIED_FILESIZE_LIMIT 10*1024*1024
typedef struct OutputModule_ {
char *name;
char *conf_name;

@ -69,12 +69,21 @@ typedef struct LogFileCtx_ {
* the date onto the end of files. */
char *prefix;
/**< Current file size and size limits for the file - for rotating
* outputs. */
uint32_t size_limit;
uint32_t size_current;
/** Generic size_limit and size_current
* They must be common to the threads accesing the same file */
uint32_t size_limit; /**< file size limit */
uint32_t size_current; /**< file current size */
/* Alerts on the module (not on the file) */
uint64_t alerts;
/* flag to avoid multiple threads printing the same stats */
uint8_t flags;
} LogFileCtx;
/* flags for LogFileCtx */
#define LOGFILE_HEADER_WRITTEN 0x01
#define LOGFILE_ALERTS_PRINTED 0x02
LogFileCtx *LogFileNewCtx();
int LogFileFreeCtx(LogFileCtx *);

Loading…
Cancel
Save