unified2: big rewrite to clean up code that deals with tcp segment logging.

remotes/origin/HEAD
Victor Julien 14 years ago
parent a0e57f58e5
commit 66856831fa

@ -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, &ethhdr, 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, &ethhdr, 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, &ethhdr, 14);
aun->offset += ethh_offset;
}
/* make event id available to callback */
aun->event_id = event_id;
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, &ethhdr, 14);
aun->offset += ethh_offset;
}
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;

Loading…
Cancel
Save