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)
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 {
{
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)) {
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;
}
* \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()) {
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);
}
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;