|
|
|
|
@ -159,6 +159,7 @@ typedef struct Unified2AlertThread_ {
|
|
|
|
|
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 */
|
|
|
|
|
uint32_t event_id;
|
|
|
|
|
} Unified2AlertThread;
|
|
|
|
|
|
|
|
|
|
#define UNIFIED2_PACKET_SIZE (sizeof(Unified2Packet) - 4)
|
|
|
|
|
@ -311,11 +312,14 @@ typedef struct _FakeIPv6Hdr {
|
|
|
|
|
TCPHdr tcph;
|
|
|
|
|
} FakeIPv6Hdr;
|
|
|
|
|
|
|
|
|
|
static int Unified2ForgeFakeIPv6Header(FakeIPv6Hdr *fakehdr, Packet *p, int pkt_len, char invert)
|
|
|
|
|
/**
|
|
|
|
|
* \param payload_len length of the payload
|
|
|
|
|
*/
|
|
|
|
|
static int Unified2ForgeFakeIPv6Header(FakeIPv6Hdr *fakehdr, Packet *p, int payload_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));
|
|
|
|
|
fakehdr->ip6h.s_ip6_plen = htons(sizeof(TCPHdr) + payload_len);
|
|
|
|
|
if (!invert) {
|
|
|
|
|
memcpy(fakehdr->ip6h.s_ip6_addrs, p->ip6h->s_ip6_addrs, 32);
|
|
|
|
|
} else {
|
|
|
|
|
@ -341,33 +345,119 @@ static int Unified2PrintStreamSegmentCallback(Packet *p, void *data, uint8_t *bu
|
|
|
|
|
{
|
|
|
|
|
int ret = 1;
|
|
|
|
|
Unified2AlertThread *aun = (Unified2AlertThread *)data;
|
|
|
|
|
Unified2AlertFileHeader *hdr = (Unified2AlertFileHeader*)(aun->data);
|
|
|
|
|
Unified2Packet *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;
|
|
|
|
|
uint32_t orig_length = aun->length;
|
|
|
|
|
int datalink = p->datalink;
|
|
|
|
|
|
|
|
|
|
if (PKT_IS_IPV6(p)) {
|
|
|
|
|
FakeIPv6Hdr *fakehdr = (FakeIPv6Hdr *)aun->iphdr;
|
|
|
|
|
memset(hdr, 0, sizeof(Unified2AlertFileHeader));
|
|
|
|
|
memset(phdr, 0, sizeof(Unified2Packet));
|
|
|
|
|
|
|
|
|
|
hdr->type = htonl(UNIFIED2_PACKET_TYPE);
|
|
|
|
|
aun->hdr = hdr;
|
|
|
|
|
|
|
|
|
|
phdr->sensor_id = 0;
|
|
|
|
|
phdr->linktype = htonl(datalink);
|
|
|
|
|
phdr->event_id = aun->event_id;
|
|
|
|
|
phdr->event_second = phdr->packet_second = htonl(p->ts.tv_sec);
|
|
|
|
|
phdr->packet_microsecond = htonl(p->ts.tv_usec);
|
|
|
|
|
aun->phdr = phdr;
|
|
|
|
|
|
|
|
|
|
if (p->datalink != DLT_EN10MB) {
|
|
|
|
|
/* We have raw data here */
|
|
|
|
|
phdr->linktype = htonl(DLT_RAW);
|
|
|
|
|
datalink = DLT_RAW;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
aun->length = sizeof(Unified2AlertFileHeader) + UNIFIED2_PACKET_SIZE;
|
|
|
|
|
aun->offset = sizeof(Unified2AlertFileHeader) + UNIFIED2_PACKET_SIZE;
|
|
|
|
|
|
|
|
|
|
/* Include Packet header */
|
|
|
|
|
if (PKT_IS_IPV4(p)) {
|
|
|
|
|
FakeIPv4Hdr fakehdr;
|
|
|
|
|
hdr_length = sizeof(FakeIPv4Hdr);
|
|
|
|
|
|
|
|
|
|
if (p->datalink == DLT_EN10MB) {
|
|
|
|
|
/* Fake this */
|
|
|
|
|
ethh_offset = 14;
|
|
|
|
|
datalink = DLT_EN10MB;
|
|
|
|
|
phdr->linktype = htonl(datalink);
|
|
|
|
|
aun->length += ethh_offset;
|
|
|
|
|
|
|
|
|
|
if (aun->length > aun->datalen) {
|
|
|
|
|
SCLogError(SC_ERR_INVALID_VALUE, "len is too big for thread data");
|
|
|
|
|
goto error;
|
|
|
|
|
}
|
|
|
|
|
ethhdr.eth_type = htons(ETHERNET_TYPE_IP);
|
|
|
|
|
|
|
|
|
|
memcpy(aun->data + aun->offset, ðhdr, 14);
|
|
|
|
|
aun->offset += ethh_offset;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
memset(&fakehdr, 0, hdr_length);
|
|
|
|
|
aun->length += hdr_length;
|
|
|
|
|
Unified2ForgeFakeIPv4Header(&fakehdr, p, hdr_length + buflen, 0);
|
|
|
|
|
if (aun->length > aun->datalen) {
|
|
|
|
|
SCLogError(SC_ERR_INVALID_VALUE, "len is too big for thread data");
|
|
|
|
|
goto error;
|
|
|
|
|
}
|
|
|
|
|
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)) {
|
|
|
|
|
FakeIPv6Hdr fakehdr;
|
|
|
|
|
hdr_length = sizeof(FakeIPv6Hdr);
|
|
|
|
|
fakehdr->ip6h.s_ip6_plen = htons((uint16_t) (hdr_length + buflen));
|
|
|
|
|
|
|
|
|
|
if (p->datalink == DLT_EN10MB) {
|
|
|
|
|
/* Fake this */
|
|
|
|
|
ethh_offset = 14;
|
|
|
|
|
datalink = DLT_EN10MB;
|
|
|
|
|
phdr->linktype = htonl(datalink);
|
|
|
|
|
aun->length += ethh_offset;
|
|
|
|
|
if (aun->length > aun->datalen) {
|
|
|
|
|
SCLogError(SC_ERR_INVALID_VALUE, "len is too big for thread data");
|
|
|
|
|
goto error;
|
|
|
|
|
}
|
|
|
|
|
ethhdr.eth_type = htons(ETHERNET_TYPE_IPV6);
|
|
|
|
|
|
|
|
|
|
memcpy(aun->data + aun->offset, ðhdr, 14);
|
|
|
|
|
aun->offset += ethh_offset;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
memset(&fakehdr, 0, hdr_length);
|
|
|
|
|
Unified2ForgeFakeIPv6Header(&fakehdr, p, buflen, 1);
|
|
|
|
|
|
|
|
|
|
aun->length += hdr_length;
|
|
|
|
|
if (aun->length > aun->datalen) {
|
|
|
|
|
SCLogError(SC_ERR_INVALID_VALUE, "len is too big for thread data");
|
|
|
|
|
goto error;
|
|
|
|
|
}
|
|
|
|
|
memcpy(aun->data + aun->offset, &fakehdr, hdr_length);
|
|
|
|
|
aun->iphdr = (void *)(aun->data + aun->offset);
|
|
|
|
|
aun->offset += hdr_length;
|
|
|
|
|
} else {
|
|
|
|
|
FakeIPv4Hdr *fakehdr = (FakeIPv4Hdr *)aun->iphdr;
|
|
|
|
|
hdr_length = sizeof(FakeIPv4Hdr);
|
|
|
|
|
fakehdr->ip4h.ip_len = htons((uint16_t) (hdr_length + buflen));
|
|
|
|
|
goto error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
aun->hdr->length = htonl(UNIFIED2_PACKET_SIZE +
|
|
|
|
|
((p->datalink == DLT_EN10MB) ? 14 : 0) +
|
|
|
|
|
buflen + hdr_length);
|
|
|
|
|
aun->phdr->packet_length = htonl(buflen + hdr_length +
|
|
|
|
|
((p->datalink == DLT_EN10MB) ? 14 : 0));
|
|
|
|
|
/* update unified2 headers for length */
|
|
|
|
|
aun->hdr->length = htonl(UNIFIED2_PACKET_SIZE + ethh_offset +
|
|
|
|
|
hdr_length + buflen);
|
|
|
|
|
aun->phdr->packet_length = htonl(ethh_offset + hdr_length + buflen);
|
|
|
|
|
|
|
|
|
|
/* copy stream segment payload in */
|
|
|
|
|
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;
|
|
|
|
|
goto error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
memcpy(aun->data + aun->offset, buf, buflen);
|
|
|
|
|
aun->offset += buflen;
|
|
|
|
|
|
|
|
|
|
/* rebuild checksum */
|
|
|
|
|
if (PKT_IS_IPV6(p)) {
|
|
|
|
|
@ -384,12 +474,17 @@ static int Unified2PrintStreamSegmentCallback(Packet *p, void *data, uint8_t *bu
|
|
|
|
|
IPV4_GET_RAW_HLEN(&fakehdr->ip4h));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* write out */
|
|
|
|
|
ret = Unified2Write(aun);
|
|
|
|
|
if (ret != 1) {
|
|
|
|
|
aun->length = orig_length;
|
|
|
|
|
return ret;
|
|
|
|
|
goto error;
|
|
|
|
|
}
|
|
|
|
|
return ret;
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
|
|
error:
|
|
|
|
|
aun->length = 0;
|
|
|
|
|
aun->offset = 0;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -406,43 +501,21 @@ static int Unified2PrintStreamSegmentCallback(Packet *p, void *data, uint8_t *bu
|
|
|
|
|
* \param aun thread local data
|
|
|
|
|
* \param p Packet
|
|
|
|
|
* \param stream pointer to stream chunk
|
|
|
|
|
* \param event_id unique event id
|
|
|
|
|
* \param stream state/stream match, try logging stream segments
|
|
|
|
|
*
|
|
|
|
|
* \retval 0 on succces
|
|
|
|
|
* \retval -1 on failure
|
|
|
|
|
*/
|
|
|
|
|
int Unified2PacketTypeAlert (Unified2AlertThread *aun, Packet *p, uint32_t event_id, int state)
|
|
|
|
|
int Unified2PacketTypeAlert (Unified2AlertThread *aun, Packet *p, uint32_t event_id, int stream)
|
|
|
|
|
{
|
|
|
|
|
Unified2AlertFileHeader *hdr = (Unified2AlertFileHeader*)(aun->data + aun->offset);
|
|
|
|
|
Unified2Packet *phdr = (Unified2Packet *)(hdr + 1);
|
|
|
|
|
int ret = 0;
|
|
|
|
|
int len = aun->offset + (sizeof(Unified2AlertFileHeader) + UNIFIED2_PACKET_SIZE);
|
|
|
|
|
int datalink = p->datalink;
|
|
|
|
|
int ethh_offset = 0;
|
|
|
|
|
EthernetHdr ethhdr = { {0,0,0,0,0,0}, {0,0,0,0,0,0}, htons(ETHERNET_TYPE_IPV6) };
|
|
|
|
|
|
|
|
|
|
memset(hdr, 0, sizeof(Unified2AlertFileHeader));
|
|
|
|
|
memset(phdr, 0, sizeof(Unified2Packet));
|
|
|
|
|
|
|
|
|
|
hdr->type = htonl(UNIFIED2_PACKET_TYPE);
|
|
|
|
|
aun->hdr = hdr;
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
if (state) {
|
|
|
|
|
/* try stream logging first */
|
|
|
|
|
if (stream) {
|
|
|
|
|
SCLogDebug("logging the state");
|
|
|
|
|
uint8_t flag;
|
|
|
|
|
|
|
|
|
|
if (p->datalink != DLT_EN10MB) {
|
|
|
|
|
/* We have raw data here */
|
|
|
|
|
phdr->linktype = htonl(DLT_RAW);
|
|
|
|
|
}
|
|
|
|
|
aun->length = len;
|
|
|
|
|
|
|
|
|
|
/* IDS mode reverse the data */
|
|
|
|
|
/** \todo improve the order selection policy */
|
|
|
|
|
if (!StreamTcpInlineMode()) {
|
|
|
|
|
@ -458,74 +531,11 @@ int Unified2PacketTypeAlert (Unified2AlertThread *aun, Packet *p, uint32_t event
|
|
|
|
|
flag = FLOW_PKT_TOCLIENT;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
/* Include Packet header */
|
|
|
|
|
if (PKT_IS_IPV4(p)) {
|
|
|
|
|
FakeIPv4Hdr fakehdr;
|
|
|
|
|
uint32_t hdr_length = sizeof(FakeIPv4Hdr);
|
|
|
|
|
|
|
|
|
|
if (p->datalink == DLT_EN10MB) {
|
|
|
|
|
/* Fake this */
|
|
|
|
|
ethh_offset = 14;
|
|
|
|
|
datalink = DLT_EN10MB;
|
|
|
|
|
phdr->linktype = htonl(datalink);
|
|
|
|
|
aun->length += ethh_offset;
|
|
|
|
|
if (aun->length > aun->datalen) {
|
|
|
|
|
SCLogError(SC_ERR_INVALID_VALUE, "len is too big for thread data: %d vs %d",
|
|
|
|
|
len, aun->datalen - aun->offset);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
ethhdr.eth_type = htons(ETHERNET_TYPE_IP);
|
|
|
|
|
|
|
|
|
|
memcpy(aun->data + aun->offset, ðhdr, 14);
|
|
|
|
|
aun->offset += ethh_offset;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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 { /* Implied IPv6 */
|
|
|
|
|
FakeIPv6Hdr fakehdr;
|
|
|
|
|
uint32_t hdr_length = sizeof(FakeIPv6Hdr);
|
|
|
|
|
|
|
|
|
|
if (p->datalink == DLT_EN10MB) {
|
|
|
|
|
/* Fake this */
|
|
|
|
|
ethh_offset = 14;
|
|
|
|
|
datalink = DLT_EN10MB;
|
|
|
|
|
phdr->linktype = htonl(datalink);
|
|
|
|
|
aun->length += ethh_offset;
|
|
|
|
|
if (aun->length > aun->datalen) {
|
|
|
|
|
SCLogError(SC_ERR_INVALID_VALUE, "len is too big for thread data: %d vs %d",
|
|
|
|
|
len, aun->datalen - aun->offset);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
ethhdr.eth_type = htons(ETHERNET_TYPE_IPV6);
|
|
|
|
|
|
|
|
|
|
memcpy(aun->data + aun->offset, ðhdr, 14);
|
|
|
|
|
aun->offset += ethh_offset;
|
|
|
|
|
}
|
|
|
|
|
/* make event id available to callback */
|
|
|
|
|
aun->event_id = event_id;
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
/* run callback for all segments in the stream */
|
|
|
|
|
ret = StreamSegmentForEach(p, flag, Unified2PrintStreamSegmentCallback, (void *)aun);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -533,6 +543,27 @@ int Unified2PacketTypeAlert (Unified2AlertThread *aun, Packet *p, uint32_t event
|
|
|
|
|
if (ret == 0) {
|
|
|
|
|
SCLogDebug("no stream, no state: falling back to payload logging");
|
|
|
|
|
|
|
|
|
|
Unified2AlertFileHeader *hdr = (Unified2AlertFileHeader*)(aun->data);
|
|
|
|
|
Unified2Packet *phdr = (Unified2Packet *)(hdr + 1);
|
|
|
|
|
int len = (sizeof(Unified2AlertFileHeader) + UNIFIED2_PACKET_SIZE);
|
|
|
|
|
int datalink = p->datalink;
|
|
|
|
|
#ifdef HAVE_OLD_BARNYARD2
|
|
|
|
|
int ethh_offset = 0;
|
|
|
|
|
EthernetHdr ethhdr = { {0,0,0,0,0,0}, {0,0,0,0,0,0}, htons(ETHERNET_TYPE_IPV6) };
|
|
|
|
|
#endif
|
|
|
|
|
memset(hdr, 0, sizeof(Unified2AlertFileHeader));
|
|
|
|
|
memset(phdr, 0, sizeof(Unified2Packet));
|
|
|
|
|
|
|
|
|
|
hdr->type = htonl(UNIFIED2_PACKET_TYPE);
|
|
|
|
|
aun->hdr = hdr;
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
/* we need to reset offset and length which could
|
|
|
|
|
* have been modified by the segment logging */
|
|
|
|
|
aun->offset = len;
|
|
|
|
|
|