diff --git a/src/alert-debuglog.c b/src/alert-debuglog.c index 24f37e522e..df3f614f24 100644 --- a/src/alert-debuglog.c +++ b/src/alert-debuglog.c @@ -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); } diff --git a/src/alert-fastlog.c b/src/alert-fastlog.c index 18d82b8e0b..68a9f754e5 100644 --- a/src/alert-fastlog.c +++ b/src/alert-fastlog.c @@ -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); } /** diff --git a/src/alert-unified-alert.c b/src/alert-unified-alert.c index 5112154180..da4b1e0a34 100644 --- a/src/alert-unified-alert.c +++ b/src/alert-unified-alert.c @@ -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 diff --git a/src/alert-unified-log.c b/src/alert-unified-log.c index e9630d875a..402233343e 100644 --- a/src/alert-unified-log.c +++ b/src/alert-unified-log.c @@ -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 @@ -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(ðh, 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,ðh,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(ðh, 0, sizeof(EthernetHdr)); + ethh.eth_type = htons(ETHERNET_TYPE_IP); + + memcpy(buf+buflen,ðh,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 diff --git a/src/alert-unified2-alert.c b/src/alert-unified2-alert.c index 183bc03db8..693a09adce 100644 --- a/src/alert-unified2-alert.c +++ b/src/alert-unified2-alert.c @@ -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; diff --git a/src/output.h b/src/output.h index c40eaa1c84..d516a06311 100644 --- a/src/output.h +++ b/src/output.h @@ -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; diff --git a/src/tm-modules.h b/src/tm-modules.h index 8ac4407f77..2f518a4afd 100644 --- a/src/tm-modules.h +++ b/src/tm-modules.h @@ -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 *);