alert-unified2: logging of stream segments.

This patch adds the logging of stream segments. Among other
modifications, it uses a wrapper to fwrite to permit to update
file statistics in an automated manner. Some memcpy have also
been avoided by using pointer to the data.
remotes/origin/master-1.1.x
Eric Leblond 14 years ago committed by Victor Julien
parent 2fa837bcec
commit 79c329f81b

@ -63,17 +63,6 @@
/**< Minimum log file limit in MB. */
#define MIN_LIMIT 1
/**
* Unified2 thread vars
*
* Used for storing file options.
*/
typedef struct Unified2AlertThread_ {
LogFileCtx *file_ctx; /** LogFileCtx pointer */
uint8_t *data; /** Per function and thread data */
int datalen; /** Length of per function and thread data */
} Unified2AlertThread;
/**
* Unified2 file header struct
*
@ -146,15 +135,39 @@ typedef struct AlertUnified2Packet_ {
uint8_t packet_data[4]; /**< packet data */
} Unified2Packet;
/**
* Unified2 thread vars
*
* Used for storing file options.
*/
typedef struct Unified2AlertThread_ {
LogFileCtx *file_ctx; /**< LogFileCtx pointer */
uint8_t *data; /**< Per function and thread data */
/** Pointer to the Unified2AlertFileHeader contained in
* the pointer data. */
Unified2AlertFileHeader *hdr;
/** Pointer to the Unified2Packet contained in
* the pointer data. */
Unified2Packet *phdr;
/** Pointer to the IPv4 or IPv6 header contained in
* the pointer data. */
void *iphdr;
int datalen; /**< Length of per function and thread data */
int offset; /**< Offset used to now where to fill data */
int length; /**< Length of data for current alert */
} Unified2AlertThread;
#define UNIFIED2_PACKET_SIZE (sizeof(Unified2Packet) - 4)
SC_ATOMIC_DECLARE(unsigned int, unified2_event_id); /**< Atomic counter, to link relative event */
/** prototypes */
TmEcode Unified2Alert (ThreadVars *, Packet *, void *, PacketQueue *, PacketQueue *);
TmEcode Unified2AlertThreadInit(ThreadVars *, void *, void **);
TmEcode Unified2AlertThreadDeinit(ThreadVars *, void *);
int Unified2IPv4TypeAlert(ThreadVars *, Packet *, void *, PacketQueue *);
int Unified2IPv6TypeAlert(ThreadVars *, Packet *, void *, PacketQueue *);
int Unified2PacketTypeAlert(Unified2AlertThread *, Packet *, void *);
int Unified2PacketTypeAlert(Unified2AlertThread *, Packet *, void *, uint32_t);
void Unified2RegisterTests();
int Unified2AlertOpenFileCtx(LogFileCtx *, const char *);
static void Unified2AlertDeInitCtx(OutputCtx *);
@ -211,6 +224,28 @@ int Unified2AlertRotateFile(ThreadVars *t, Unified2AlertThread *aun) {
return 0;
}
/**
* \brief Wrapper for fwrite
*
* This function is basically a wrapper for fwrite which take
* in charge a size counter.
*
* \return 1 in case of success
*/
static int Unified2Write(Unified2AlertThread *aun)
{
int ret;
ret = fwrite(aun->data, aun->length, 1, aun->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;
return 1;
}
/**
* \brief Unified2 main entry function
*
@ -237,6 +272,65 @@ TmEcode Unified2Alert (ThreadVars *t, Packet *p, void *data, PacketQueue *pq, Pa
return TM_ECODE_OK;
}
typedef struct _FakeIPv4Hdr {
IPV4Hdr ip4h;
TCPHdr tcph;
} FakeIPv4Hdr;
static int Unified2ForgeFakeIPv4Header(FakeIPv4Hdr *fakehdr, Packet *p, int pkt_len, char invert)
{
fakehdr->ip4h.ip_verhl = p->ip4h->ip_verhl;
fakehdr->ip4h.ip_proto = p->ip4h->ip_proto;
if (! invert) {
fakehdr->ip4h.ip_src.s_addr = p->ip4h->ip_src.s_addr;
fakehdr->ip4h.ip_dst.s_addr = p->ip4h->ip_dst.s_addr;
} else {
fakehdr->ip4h.ip_dst.s_addr = p->ip4h->ip_src.s_addr;
fakehdr->ip4h.ip_src.s_addr = p->ip4h->ip_dst.s_addr;
}
fakehdr->ip4h.ip_len = htons((uint16_t)pkt_len);
if (! invert) {
fakehdr->tcph.th_sport = p->tcph->th_sport;
fakehdr->tcph.th_dport = p->tcph->th_dport;
} else {
fakehdr->tcph.th_dport = p->tcph->th_sport;
fakehdr->tcph.th_sport = p->tcph->th_dport;
}
fakehdr->tcph.th_offx2 = 0x50; /* just the TCP header, no options */
return 1;
}
typedef struct _FakeIPv6Hdr {
IPV6Hdr ip6h;
TCPHdr tcph;
} FakeIPv6Hdr;
static int Unified2ForgeFakeIPv6Header(FakeIPv6Hdr *fakehdr, Packet *p, int pkt_len, char invert)
{
fakehdr->ip6h.s_ip6_vfc = p->ip6h->s_ip6_vfc;
fakehdr->ip6h.s_ip6_nxt = IPPROTO_TCP;
fakehdr->ip6h.s_ip6_plen = htons(sizeof(TCPHdr));
if (!invert) {
memcpy(fakehdr->ip6h.ip6_src, p->ip6h->ip6_src, 32);
} else {
memcpy(fakehdr->ip6h.ip6_src, p->ip6h->ip6_dst, 16);
memcpy(fakehdr->ip6h.ip6_dst, p->ip6h->ip6_src, 16);
}
if (! invert) {
fakehdr->tcph.th_sport = p->tcph->th_sport;
fakehdr->tcph.th_dport = p->tcph->th_dport;
} else {
fakehdr->tcph.th_dport = p->tcph->th_sport;
fakehdr->tcph.th_sport = p->tcph->th_dport;
}
fakehdr->tcph.th_offx2 = 0x50; /* just the TCP header, no options */
return 1;
}
/**
* \brief Log the stream chunk that we alerted on. We construct a
* fake ipv4 and tcp header to make sure the packet length
@ -256,7 +350,9 @@ TmEcode Unified2Alert (ThreadVars *t, Packet *p, void *data, PacketQueue *pq, Pa
* into the buffer now.
* \todo We could even have union of the headers with the write buffers
*/
static int Unified2StreamTypeAlertIPv4 (Unified2AlertThread *aun, Packet *p, void *stream)
static int Unified2StreamTypeAlertIPv4 (Unified2AlertThread *aun,
Packet *p, void *stream,
uint32_t event_id)
{
struct {
IPV4Hdr ip4h;
@ -265,11 +361,12 @@ static int Unified2StreamTypeAlertIPv4 (Unified2AlertThread *aun, Packet *p, voi
Unified2Packet phdr;
Unified2AlertFileHeader hdr;
int ret;
int len = (sizeof(Unified2AlertFileHeader) + UNIFIED2_PACKET_SIZE);
uint32_t pkt_len;
aun->length += (sizeof(Unified2AlertFileHeader) + UNIFIED2_PACKET_SIZE);
memset(&fakehdr, 0x00, sizeof(fakehdr));
memset(aun->data,0x00,aun->datalen);
memset(aun->data + aun->offset, 0x00, aun->datalen - aun->offset);
memset(&hdr, 0, sizeof(Unified2AlertFileHeader));
memset(&phdr, 0, sizeof(Unified2Packet));
@ -292,11 +389,11 @@ static int Unified2StreamTypeAlertIPv4 (Unified2AlertThread *aun, Packet *p, voi
fakehdr.tcph.th_dport = p->tcph->th_dport;
fakehdr.tcph.th_offx2 = 0x50; /* just the TCP header, no options */
len += (int)pkt_len;
aun->length += (int)pkt_len;
if (len > aun->datalen) {
if (aun->length > aun->datalen) {
SCLogError(SC_ERR_INVALID_VALUE, "len is too big for thread data: %d vs %d",
len, aun->datalen);
aun->length, aun->datalen);
return -1;
}
@ -305,28 +402,26 @@ static int Unified2StreamTypeAlertIPv4 (Unified2AlertThread *aun, Packet *p, voi
phdr.sensor_id = 0;
phdr.linktype = htonl(DLT_RAW);
phdr.event_id = 0;
phdr.event_id = event_id;
phdr.event_second = phdr.packet_second = htonl(p->ts.tv_sec);
phdr.packet_microsecond = htonl(p->ts.tv_usec);
phdr.packet_length = htonl(pkt_len);
memcpy(aun->data, &hdr, sizeof(Unified2AlertFileHeader));
memcpy(aun->data + aun->offset, &hdr, sizeof(Unified2AlertFileHeader));
memcpy(aun->data + sizeof(Unified2AlertFileHeader),
memcpy(aun->data + aun->offset + sizeof(Unified2AlertFileHeader),
&phdr, UNIFIED2_PACKET_SIZE);
memcpy(aun->data + sizeof(Unified2AlertFileHeader) + UNIFIED2_PACKET_SIZE,
memcpy(aun->data + aun->offset + sizeof(Unified2AlertFileHeader) + UNIFIED2_PACKET_SIZE,
&fakehdr, sizeof(fakehdr));
memcpy(aun->data + sizeof(Unified2AlertFileHeader) + UNIFIED2_PACKET_SIZE + sizeof(fakehdr),
memcpy(aun->data + aun->offset + sizeof(Unified2AlertFileHeader) + UNIFIED2_PACKET_SIZE + sizeof(fakehdr),
stream_msg->data.data, stream_msg->data.data_len);
ret = fwrite(aun->data, len, 1, aun->file_ctx->fp);
ret = Unified2Write(aun);
if (ret != 1) {
SCLogError(SC_ERR_FWRITE, "Error: fwrite failed: %s", strerror(errno));
return -1;
}
aun->file_ctx->size_current += len;
return 0;
return 1;
}
/**
@ -351,7 +446,9 @@ static int Unified2StreamTypeAlertIPv4 (Unified2AlertThread *aun, Packet *p, voi
* into the buffer now.
* \todo We could even have union of the headers with the write buffers
*/
static int Unified2StreamTypeAlertIPv6 (Unified2AlertThread *aun, Packet *p, void *stream)
static int Unified2StreamTypeAlertIPv6 (Unified2AlertThread *aun,
Packet *p, void *stream,
uint32_t event_id)
{
struct fakehdr_ {
EthernetHdr ethh;
@ -362,10 +459,11 @@ static int Unified2StreamTypeAlertIPv6 (Unified2AlertThread *aun, Packet *p, voi
Unified2Packet phdr;
Unified2AlertFileHeader hdr;
int ret;
int len = (sizeof(Unified2AlertFileHeader) + UNIFIED2_PACKET_SIZE);
aun->length += (sizeof(Unified2AlertFileHeader) + UNIFIED2_PACKET_SIZE);
memset(&fakehdr, 0x00, sizeof(fakehdr));
memset(aun->data,0x00,aun->datalen);
memset(aun->data + aun->offset, 0x00, aun->datalen - aun->offset);
memset(&hdr, 0, sizeof(Unified2AlertFileHeader));
memset(&phdr, 0, sizeof(Unified2Packet));
@ -383,11 +481,11 @@ static int Unified2StreamTypeAlertIPv6 (Unified2AlertThread *aun, Packet *p, voi
fakehdr.tcph.th_dport = p->tcph->th_dport;
fakehdr.tcph.th_offx2 = 0x50; /* just the TCP header, no options */
len += (sizeof(fakehdr) + stream_msg->data.data_len);
aun->length += (sizeof(fakehdr) + stream_msg->data.data_len);
if (len > aun->datalen) {
if (aun->length > aun->datalen) {
SCLogError(SC_ERR_INVALID_VALUE, "len is too big for thread data: %d vs %d",
len, aun->datalen);
aun->length, aun->datalen);
return -1;
}
@ -396,30 +494,88 @@ static int Unified2StreamTypeAlertIPv6 (Unified2AlertThread *aun, Packet *p, voi
phdr.sensor_id = 0;
phdr.linktype = htonl(DLT_EN10MB);
phdr.event_id = 0;
phdr.event_id = event_id;
phdr.event_second = phdr.packet_second = htonl(p->ts.tv_sec);
phdr.packet_microsecond = htonl(p->ts.tv_usec);
phdr.packet_length = htonl(sizeof(fakehdr) + stream_msg->data.data_len);
memcpy(aun->data, &hdr, sizeof(Unified2AlertFileHeader));
memcpy(aun->data + aun->offset, &hdr, sizeof(Unified2AlertFileHeader));
memcpy(aun->data + sizeof(Unified2AlertFileHeader),
memcpy(aun->data + aun->offset + sizeof(Unified2AlertFileHeader),
&phdr, UNIFIED2_PACKET_SIZE);
memcpy(aun->data + sizeof(Unified2AlertFileHeader) + UNIFIED2_PACKET_SIZE,
memcpy(aun->data + aun->offset + sizeof(Unified2AlertFileHeader) + UNIFIED2_PACKET_SIZE,
&fakehdr, sizeof(fakehdr));
memcpy(aun->data + sizeof(Unified2AlertFileHeader) + UNIFIED2_PACKET_SIZE + sizeof(fakehdr),
memcpy(aun->data + aun->offset + sizeof(Unified2AlertFileHeader) + UNIFIED2_PACKET_SIZE + sizeof(fakehdr),
stream_msg->data.data, stream_msg->data.data_len);
ret = fwrite(aun->data, len, 1, aun->file_ctx->fp);
ret = Unified2Write(aun);
if (ret != 1) {
SCLogError(SC_ERR_FWRITE, "Error: fwrite failed: %s", strerror(errno));
return -1;
}
aun->file_ctx->size_current += len;
return 0;
return 1;
}
/**
* \brief Write a faked Packet in unified2 file for each stream segment.
*/
static int Unified2PrintStreamSegmentCallback(Packet *p, void *data, uint8_t *buf, uint32_t buflen)
{
int ret = 1;
Unified2AlertThread *aun = (Unified2AlertThread *)data;
int ethh_offset = 14;
uint32_t hdr_length = 0;
uint32_t orig_length = aun->length;
if (PKT_IS_IPV6(p)) {
hdr_length = sizeof(FakeIPv6Hdr);
((FakeIPv6Hdr *)aun->iphdr)->ip6h.s_ip6_plen =
htons((uint16_t) (hdr_length + buflen));
} else {
FakeIPv4Hdr *fakehdr = (FakeIPv4Hdr *)aun->iphdr;
hdr_length = sizeof(FakeIPv4Hdr);
fakehdr->ip4h.ip_len = htons((uint16_t) (hdr_length + buflen));
}
aun->hdr->length = htonl(UNIFIED2_PACKET_SIZE +
buflen + ethh_offset + hdr_length);
aun->phdr->packet_length = htonl(buflen + ethh_offset + hdr_length);
aun->length += buflen;
if (aun->length > aun->datalen) {
SCLogError(SC_ERR_INVALID_VALUE, "len is too big for thread"
" data: %d vs %d",
aun->length, aun->datalen);
aun->length = orig_length;
return -1;
}
memcpy(aun->data + aun->offset, buf, buflen);
/* rebuild checksum */
if (PKT_IS_IPV6(p)) {
FakeIPv6Hdr *fakehdr = (FakeIPv6Hdr *)aun->iphdr;
fakehdr->tcph.th_sum = TCPV6CalculateChecksum(
(uint16_t *)&(fakehdr->ip6h.ip6_src),
(uint16_t *)&fakehdr->tcph, buflen + sizeof(TCPHdr));
} else {
FakeIPv4Hdr *fakehdr = (FakeIPv4Hdr *)aun->iphdr;
fakehdr->tcph.th_sum = TCPCalculateChecksum(
(uint16_t *)&(fakehdr->ip4h.ip_src),
(uint16_t *)&fakehdr->tcph, buflen + sizeof(TCPHdr));
fakehdr->ip4h.ip_csum = IPV4CalculateChecksum(
(uint16_t *)&fakehdr->ip4h,
IPV4_GET_RAW_HLEN(&fakehdr->ip4h));
}
ret = Unified2Write(aun);
aun->length = orig_length;
if (ret != 1) {
return ret;
}
return ret;
}
/**
* \brief Function to fill unified2 packet format into the file. If the alert
* was generated based on a stream chunk we call the stream function
@ -437,70 +593,119 @@ static int Unified2StreamTypeAlertIPv6 (Unified2AlertThread *aun, Packet *p, voi
* \retval 0 on succces
* \retval -1 on failure
*/
int Unified2PacketTypeAlert (Unified2AlertThread *aun, Packet *p, void *stream)
int Unified2PacketTypeAlert (Unified2AlertThread *aun, Packet *p, void *stream, uint32_t event_id)
{
if (PKT_IS_TCP(p) && stream != NULL) {
if (PKT_IS_IPV4(p)) {
return Unified2StreamTypeAlertIPv4(aun, p, stream);
return Unified2StreamTypeAlertIPv4(aun, p, stream, event_id);
} else if (PKT_IS_IPV6(p)) {
return Unified2StreamTypeAlertIPv6(aun, p, stream);
return Unified2StreamTypeAlertIPv6(aun, p, stream, event_id);
}
}
Unified2Packet phdr;
Unified2AlertFileHeader hdr;
Unified2AlertFileHeader *hdr = (Unified2AlertFileHeader*)(aun->data + aun->offset);
Unified2Packet *phdr = (Unified2Packet *)(hdr + 1);
int ret;
int len = (sizeof(Unified2AlertFileHeader) + UNIFIED2_PACKET_SIZE);
int len = aun->offset + (sizeof(Unified2AlertFileHeader) + UNIFIED2_PACKET_SIZE);
int ethh_offset = 0;
int datalink = p->datalink;
EthernetHdr ethhdr = { {0,0,0,0,0,0}, {0,0,0,0,0,0}, htons(ETHERNET_TYPE_IPV6) };
if (PKT_IS_IPV6(p) && p->ethh == NULL) {
ethh_offset = 14;
datalink = DLT_EN10MB;
}
len += (GET_PKT_LEN(p) + ethh_offset);
if (len > aun->datalen) {
SCLogError(SC_ERR_INVALID_VALUE, "len is too big for thread data: %d vs %d",
len, aun->datalen);
return -1;
/* Fake this */
ethh_offset = 14;
datalink = DLT_EN10MB;
if (PKT_IS_IPV6(p)) {
ethhdr.eth_type = htons(ETHERNET_TYPE_IPV6);
} else {
ethhdr.eth_type = htons(ETHERNET_TYPE_IP);
}
memset(aun->data,0,aun->datalen);
memset(&hdr, 0, sizeof(Unified2AlertFileHeader));
memset(&phdr, 0, sizeof(Unified2Packet));
memset(hdr, 0, sizeof(Unified2AlertFileHeader));
memset(phdr, 0, sizeof(Unified2Packet));
hdr.type = htonl(UNIFIED2_PACKET_TYPE);
hdr.length = htonl(UNIFIED2_PACKET_SIZE + GET_PKT_LEN(p) + ethh_offset);
hdr->type = htonl(UNIFIED2_PACKET_TYPE);
aun->hdr = hdr;
phdr.sensor_id = 0;
phdr.linktype = htonl(datalink);
phdr.event_id = 0;
phdr.event_second = phdr.packet_second = htonl(p->ts.tv_sec);
phdr.packet_microsecond = htonl(p->ts.tv_usec);
phdr.packet_length = htonl(GET_PKT_LEN(p) + ethh_offset);
memcpy(aun->data, &hdr, sizeof(Unified2AlertFileHeader));
phdr->sensor_id = 0;
phdr->linktype = htonl(datalink);
phdr->event_id = event_id;
phdr->event_second = phdr->packet_second = htonl(p->ts.tv_sec);
phdr->packet_microsecond = htonl(p->ts.tv_usec);
aun->phdr = phdr;
memcpy(aun->data + sizeof(Unified2AlertFileHeader),
&phdr, UNIFIED2_PACKET_SIZE);
if (ethh_offset > 0) {
memcpy(aun->data + sizeof(Unified2AlertFileHeader) + UNIFIED2_PACKET_SIZE,
memcpy(aun->data + aun->offset + sizeof(Unified2AlertFileHeader) + UNIFIED2_PACKET_SIZE,
&ethhdr, 14);
len += ethh_offset;
}
if (p->payload_len) {
len += GET_PKT_LEN(p);
if (len > aun->datalen) {
SCLogError(SC_ERR_INVALID_VALUE, "len is too big for thread data: %d vs %d",
len, aun->datalen - aun->offset);
return -1;
}
hdr->length = htonl(UNIFIED2_PACKET_SIZE + GET_PKT_LEN(p) + ethh_offset);
phdr->packet_length = htonl(GET_PKT_LEN(p) + ethh_offset);
memcpy(aun->data + aun->offset + sizeof(Unified2AlertFileHeader) + UNIFIED2_PACKET_SIZE + ethh_offset,
GET_PKT_DATA(p), GET_PKT_LEN(p));
ret = Unified2Write(aun);
} else {
uint8_t flag;
if ((! PKT_IS_TCP(p)) || p->flow == NULL ||
p->flow->protoctx == NULL) {
return 1;
}
/* IDS mode reverse the data */
/** \todo improve the order selection policy */
if (p->flowflags & FLOW_PKT_TOSERVER) {
flag = FLOW_PKT_TOCLIENT;
} else {
flag = FLOW_PKT_TOSERVER;
}
aun->length = len;
if (aun->length > aun->datalen) {
SCLogError(SC_ERR_INVALID_VALUE, "len is too big for thread data: %d vs %d",
aun->length, aun->datalen);
return -1;
}
aun->offset += sizeof(Unified2AlertFileHeader) + UNIFIED2_PACKET_SIZE + ethh_offset;
/* Include Packet header */
if (PKT_IS_IPV4(p)) {
FakeIPv4Hdr fakehdr;
uint32_t hdr_length = sizeof(FakeIPv4Hdr);
memset(&fakehdr, 0, hdr_length);
Unified2ForgeFakeIPv4Header(&fakehdr, p, hdr_length, 0);
memcpy(aun->data + aun->offset, &fakehdr, hdr_length);
aun->iphdr = (void *)(aun->data + aun->offset);
aun->offset += hdr_length;
aun->length += hdr_length;
} else {
FakeIPv6Hdr fakehdr;
uint32_t hdr_length = sizeof(FakeIPv6Hdr);
memset(&fakehdr, 0, hdr_length);
Unified2ForgeFakeIPv6Header(&fakehdr, p, hdr_length, 1);
aun->length += hdr_length;
if (aun->length > aun->datalen) {
SCLogError(SC_ERR_INVALID_VALUE, "len is too big for thread data: %d vs %d",
aun->length, aun->datalen);
return -1;
}
memcpy(aun->data + aun->offset, &fakehdr, hdr_length);
aun->iphdr = (void *)(aun->data + aun->offset);
aun->offset += hdr_length;
}
ret = StreamSegmentForEach(p, flag, Unified2PrintStreamSegmentCallback, (void *)aun);
}
memcpy(aun->data + sizeof(Unified2AlertFileHeader) + UNIFIED2_PACKET_SIZE + ethh_offset,
GET_PKT_DATA(p), GET_PKT_LEN(p));
ret = fwrite(aun->data,len, 1, aun->file_ctx->fp);
if (ret != 1) {
SCLogError(SC_ERR_FWRITE, "Error: fwrite failed: %s", strerror(errno));
SCLogInfo("Failed to write alert");
return -1;
}
aun->file_ctx->size_current += len;
return 0;
return 1;
}
/**
@ -517,69 +722,65 @@ int Unified2PacketTypeAlert (Unified2AlertThread *aun, Packet *p, void *stream)
int Unified2IPv6TypeAlert (ThreadVars *t, Packet *p, void *data, PacketQueue *pq)
{
Unified2AlertThread *aun = (Unified2AlertThread *)data;
AlertIPv6Unified2 phdr;
Unified2AlertFileHeader hdr;
Unified2AlertFileHeader *hdr = (Unified2AlertFileHeader *)aun->data;
AlertIPv6Unified2 *phdr = (AlertIPv6Unified2 *)(hdr + 1);
PacketAlert *pa;
int ret, len;
char head_buf[sizeof(Unified2AlertFileHeader) + sizeof(AlertIPv6Unified2)];
int ret;
if (p->alerts.cnt == 0)
return 0;
len = (sizeof(Unified2AlertFileHeader) + sizeof(AlertIPv6Unified2));
aun->length = (sizeof(Unified2AlertFileHeader) + sizeof(AlertIPv6Unified2));
aun->offset = aun->length;
memset(&hdr, 0, sizeof(Unified2AlertFileHeader));
memset(&phdr, 0, sizeof(AlertIPv6Unified2));
memset(head_buf, 0, sizeof(head_buf));
hdr.type = htonl(UNIFIED2_IDS_EVENT_IPV6_TYPE);
hdr.length = htonl(sizeof(AlertIPv6Unified2));
memset(aun->data, 0, aun->datalen);
memcpy(head_buf, &hdr,sizeof(Unified2AlertFileHeader));
hdr->type = htonl(UNIFIED2_IDS_EVENT_IPV6_TYPE);
hdr->length = htonl(sizeof(AlertIPv6Unified2));
/* fill the phdr structure with the data of the packet */
phdr.sensor_id = 0;
phdr.event_id = 0;
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);
phdr.dst_ip = *(struct in6_addr*)GET_IPV6_DST_ADDR(p);
phdr.protocol = p->proto;
phdr->sensor_id = 0;
phdr->event_id = htonl(SC_ATOMIC_ADD(unified2_event_id, 1));
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);
phdr->dst_ip = *(struct in6_addr*)GET_IPV6_DST_ADDR(p);
phdr->protocol = p->proto;
if(p->action & ACTION_DROP)
phdr.packet_action = UNIFIED2_BLOCKED_FLAG;
phdr->packet_action = UNIFIED2_BLOCKED_FLAG;
else
phdr.packet_action = 0;
phdr->packet_action = 0;
switch(phdr.protocol) {
switch(phdr->protocol) {
case IPPROTO_ICMPV6:
if(p->icmpv6h) {
phdr.sp = htons(p->icmpv6h->type);
phdr.dp = htons(p->icmpv6h->code);
phdr->sp = htons(p->icmpv6h->type);
phdr->dp = htons(p->icmpv6h->code);
} else {
phdr.sp = 0;
phdr.dp = 0;
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);
phdr->sp = htons(p->icmpv4h->type);
phdr->dp = htons(p->icmpv4h->code);
} else {
phdr.sp = 0;
phdr.dp = 0;
phdr->sp = 0;
phdr->dp = 0;
}
break;
case IPPROTO_UDP:
case IPPROTO_TCP:
case IPPROTO_SCTP:
phdr.sp = htons(p->sp);
phdr.dp = htons(p->dp);
phdr->sp = htons(p->sp);
phdr->dp = htons(p->dp);
break;
default:
phdr.sp = 0;
phdr.dp = 0;
phdr->sp = 0;
phdr->dp = 0;
break;
}
@ -598,16 +799,13 @@ int Unified2IPv6TypeAlert (ThreadVars *t, Packet *p, void *data, PacketQueue *pq
}
/* fill the header structure with the data of the alert */
phdr.generator_id = htonl(pa->s->gid);
phdr.signature_id = htonl(pa->s->id);
phdr.signature_revision = htonl(pa->s->rev);
phdr.classification_id = htonl(pa->s->class);
phdr.priority_id = htonl(pa->s->prio);
memcpy(head_buf + sizeof(Unified2AlertFileHeader),&phdr,sizeof(AlertIPv6Unified2));
phdr->generator_id = htonl(pa->s->gid);
phdr->signature_id = htonl(pa->s->id);
phdr->signature_revision = htonl(pa->s->rev);
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 +(sizeof(hdr) + sizeof(phdr))) > aun->file_ctx->size_limit) {
if (Unified2AlertRotateFile(t,aun) < 0) {
SCMutexUnlock(&aun->file_ctx->fp_mutex);
@ -616,20 +814,16 @@ int Unified2IPv6TypeAlert (ThreadVars *t, Packet *p, void *data, PacketQueue *pq
}
}
ret = fwrite(head_buf,len, 1, aun->file_ctx->fp);
ret = Unified2PacketTypeAlert(aun, p, pa->alert_msg, phdr->event_id);
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;
aun->file_ctx->alerts++;
Unified2PacketTypeAlert(aun, p, pa->alert_msg);
aun->length = 0;
aun->offset = 0;
SCMutexUnlock(&aun->file_ctx->fp_mutex);
}
@ -651,62 +845,66 @@ int Unified2IPv6TypeAlert (ThreadVars *t, Packet *p, void *data, PacketQueue *pq
int Unified2IPv4TypeAlert (ThreadVars *tv, Packet *p, void *data, PacketQueue *pq)
{
Unified2AlertThread *aun = (Unified2AlertThread *)data;
AlertIPv4Unified2 phdr;
Unified2AlertFileHeader hdr;
Unified2AlertFileHeader *hdr = (Unified2AlertFileHeader *)aun->data;
AlertIPv4Unified2 *phdr = (AlertIPv4Unified2 *)(hdr + 1);
PacketAlert *pa;
int ret, len;
char head_buf[sizeof(Unified2AlertFileHeader) + sizeof(AlertIPv4Unified2)];
int offset, length;
int ret;
if (p->alerts.cnt == 0)
return 0;
len = (sizeof(Unified2AlertFileHeader) + sizeof(AlertIPv4Unified2));
memset(&hdr, 0, sizeof(Unified2AlertFileHeader));
memset(&phdr, 0, sizeof(AlertIPv4Unified2));
memset(head_buf, 0, sizeof(head_buf));
length = (sizeof(Unified2AlertFileHeader) + sizeof(AlertIPv4Unified2));
offset = length;
hdr.type = htonl(UNIFIED2_IDS_EVENT_TYPE);
hdr.length = htonl(sizeof(AlertIPv4Unified2));
memset(aun->data, 0, aun->datalen);
memcpy(head_buf,&hdr,sizeof(Unified2AlertFileHeader));
hdr->type = htonl(UNIFIED2_IDS_EVENT_TYPE);
hdr->length = htonl(sizeof(AlertIPv4Unified2));
/* fill the hdr structure with the packet data */
phdr.sensor_id = 0;
phdr.event_id = 0;
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);
phdr->sensor_id = 0;
phdr->event_id = htonl(SC_ATOMIC_ADD(unified2_event_id, 1));
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;
phdr->packet_action = UNIFIED2_BLOCKED_FLAG;
else
phdr.packet_action = 0;
phdr->packet_action = 0;
switch(phdr.protocol) {
/* TODO inverse order if needed, this should be done on a
* alert basis */
switch(phdr->protocol) {
case IPPROTO_ICMP:
if(p->icmpv4h) {
phdr.sp = htons(p->icmpv4h->type);
phdr.dp = htons(p->icmpv4h->code);
phdr->sp = htons(p->icmpv4h->type);
phdr->dp = htons(p->icmpv4h->code);
}
break;
case IPPROTO_UDP:
case IPPROTO_TCP:
case IPPROTO_SCTP:
phdr.sp = htons(p->sp);
phdr.dp = htons(p->dp);
phdr->sp = htons(p->sp);
phdr->dp = htons(p->dp);
break;
default:
phdr.sp = 0;
phdr.dp = 0;
phdr->sp = 0;
phdr->dp = 0;
break;
}
uint16_t i = 0;
for (; i < p->alerts.cnt + 1; i++) {
/* reset length and offset */
aun->offset = offset;
aun->length = length;
memset(aun->data + aun->offset, 0, aun->datalen - aun->offset);
if (i < p->alerts.cnt)
pa = &p->alerts.alerts[i];
else
@ -720,41 +918,33 @@ int Unified2IPv4TypeAlert (ThreadVars *tv, Packet *p, void *data, PacketQueue *p
}
/* fill the hdr structure with the alert data */
phdr.generator_id = htonl(pa->s->gid);
phdr.signature_id = htonl(pa->s->id);
phdr.signature_revision = htonl(pa->s->rev);
phdr.classification_id = htonl(pa->s->class);
phdr.priority_id = htonl(pa->s->prio);
memcpy(head_buf + sizeof(Unified2AlertFileHeader),&phdr,sizeof(AlertIPv4Unified2));
phdr->generator_id = htonl(pa->s->gid);
phdr->signature_id = htonl(pa->s->id);
phdr->signature_revision = htonl(pa->s->rev);
phdr->classification_id = htonl(pa->s->class);
phdr->priority_id = htonl(pa->s->prio);
/* 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 ((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(head_buf,len, 1, aun->file_ctx->fp);
/* Write the alert (it doesn't lock inside, since we
* already locked here for rotation check)
*/
ret = Unified2PacketTypeAlert(aun, p, pa->alert_msg, phdr->event_id);
if (ret != 1) {
SCLogError(SC_ERR_FWRITE, "Error: fwrite failed: %s", strerror(errno));
SCLogError(SC_ERR_FWRITE, "Error: PacketTypeAlert writing failed");
SCMutexUnlock(&aun->file_ctx->fp_mutex);
aun->file_ctx->alerts += i;
return -1;
}
fflush(aun->file_ctx->fp);
aun->file_ctx->size_current += len;
/* Write the alert (it doesn't lock inside, since we
* already locked here for rotation check)
*/
Unified2PacketTypeAlert(aun, p, pa->alert_msg);
SCMutexUnlock(&aun->file_ctx->fp_mutex);
}
aun->file_ctx->alerts += p->alerts.cnt;
@ -896,6 +1086,8 @@ OutputCtx *Unified2AlertInitCtx(ConfNode *conf)
SCLogInfo("Unified2-alert initialized: filename %s, limit %"PRIu64" MB",
filename, limit);
SC_ATOMIC_INIT(unified2_event_id);
return output_ctx;
error:

Loading…
Cancel
Save