/** * \brief Recalculate the csum for a modified packet * * \param p packet to inspect */ void StreamTcpInlineRecalcCsum(Packet *p) { if (!(p->flags & PKT_STREAM_MODIFIED)) { SCReturn; } if (!(PKT_IS_TCP(p))) { SCReturn; } if (PKT_IS_IPV4(p)) { /* TCP */ p->tcph->th_sum = 0; p->tcph->th_sum = TCPCalculateChecksum((uint16_t *)&(p->ip4h->ip_src), (uint16_t *)p->tcph, (p->payload_len + p->tcpvars.hlen)); /* IPV4 */ p->ip4h->ip_csum = 0; p->ip4h->ip_csum = IPV4CalculateChecksum((uint16_t *)p->ip4h, IPV4_GET_RAW_HLEN(p->ip4h)); } else if (PKT_IS_IPV6(p)) { /* just TCP for IPV6 */ p->tcph->th_sum = 0; p->tcph->th_sum = TCPV6CalculateChecksum((uint16_t *)&(p->ip6h->ip6_src), (uint16_t *)p->tcph, (p->payload_len + p->tcpvars.hlen)); } SCReturn; }
static int TCPV6CalculateInvalidChecksumtest04(void) { uint16_t csum = 0; static uint8_t raw_ipv6[] = { 0x00, 0x60, 0x97, 0x07, 0x69, 0xea, 0x00, 0x00, 0x86, 0x05, 0x80, 0xda, 0x86, 0xdd, 0x60, 0x00, 0x00, 0x00, 0x00, 0x20, 0x06, 0x40, 0x3f, 0xfe, 0x05, 0x07, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x86, 0xff, 0xfe, 0x05, 0x80, 0xda, 0x3f, 0xfe, 0x05, 0x01, 0x04, 0x10, 0x00, 0x00, 0x02, 0xc0, 0xdf, 0xff, 0xfe, 0x47, 0x03, 0x3e, 0x03, 0xfe, 0x00, 0x16, 0xd6, 0x76, 0xf5, 0x2d, 0x0c, 0x7a, 0x08, 0x77, 0x80, 0x10, 0x21, 0x5c, 0xc2, 0xf1, 0x00, 0x00, 0x01, 0x01, 0x08, 0x0a, 0x00, 0x08, 0xca, 0x5a, 0x00, 0x01, 0x69, 0x28}; csum = *( ((uint16_t *)(raw_ipv6 + 70))); return (csum != TCPV6CalculateChecksum((uint16_t *)(raw_ipv6 + 14 + 8), (uint16_t *)(raw_ipv6 + 54), 32)); }
/** * \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; 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; int datalink = p->datalink; memset(hdr, 0, sizeof(Unified2AlertFileHeader)); memset(phdr, 0, sizeof(Unified2Packet)); hdr->type = htonl(UNIFIED2_PACKET_TYPE); aun->hdr = hdr; phdr->sensor_id = htonl(sensor_id); 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); 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 { goto error; } /* 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); goto error; } memcpy(aun->data + aun->offset, buf, buflen); aun->offset += buflen; /* rebuild checksum */ if (PKT_IS_IPV6(p)) { FakeIPv6Hdr *fakehdr = (FakeIPv6Hdr *)aun->iphdr; fakehdr->tcph.th_sum = TCPV6CalculateChecksum(fakehdr->ip6h.s_ip6_addrs, (uint16_t *)&fakehdr->tcph, buflen + sizeof(TCPHdr)); } else { FakeIPv4Hdr *fakehdr = (FakeIPv4Hdr *)aun->iphdr; fakehdr->tcph.th_sum = TCPCalculateChecksum(fakehdr->ip4h.s_ip_addrs, (uint16_t *)&fakehdr->tcph, buflen + sizeof(TCPHdr)); fakehdr->ip4h.ip_csum = IPV4CalculateChecksum((uint16_t *)&fakehdr->ip4h, IPV4_GET_RAW_HLEN(&fakehdr->ip4h)); } /* write out */ ret = Unified2Write(aun); if (ret != 1) { goto error; } return 1; error: aun->length = 0; aun->offset = 0; return -1; }