From 66856831faec9d8202e2b58042b6be63e0421622 Mon Sep 17 00:00:00 2001 From: Victor Julien Date: Wed, 30 May 2012 15:27:16 +0200 Subject: [PATCH] unified2: big rewrite to clean up code that deals with tcp segment logging. --- src/alert-unified2-alert.c | 255 +++++++++++++++++++++---------------- 1 file changed, 143 insertions(+), 112 deletions(-) diff --git a/src/alert-unified2-alert.c b/src/alert-unified2-alert.c index edcb59e9f4..40008b0fbb 100644 --- a/src/alert-unified2-alert.c +++ b/src/alert-unified2-alert.c @@ -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; -- 2.47.2