checksum calculation functions for icmpv6, udp over ipv6 and tcp over ipv6

remotes/origin/master-1.0.x
Anoop Saldanha 15 years ago committed by Victor Julien
parent 1f782bb912
commit 401a0313d4

@ -3,6 +3,78 @@
#include "eidps-common.h"
#include "decode.h"
#include "decode-icmpv6.h"
#include "util-unittest.h"
/**
* \brief Calculates the checksum for the ICMPV6 packet
*
* \param shdr Pointer to source address field from the IPV6 packet. Used as a
* part of the psuedoheader for computing the checksum
* \param pkt Pointer to the start of the ICMPV6 packet
* \param tlen Total length of the ICMPV6 packet(header + payload)
*
* \retval csum Checksum for the ICMPV6 packet
*/
static inline uint16_t ICMPV6CalculateChecksum(uint16_t *shdr, uint16_t *pkt,
uint16_t tlen)
{
uint16_t pad = 0;
uint32_t csum = shdr[0];
csum += shdr[1] + shdr[2] + shdr[3] + shdr[4] + shdr[5] + shdr[6] +
shdr[7] + shdr[8] + shdr[9] + shdr[10] + shdr[11] + shdr[12] +
shdr[13] + shdr[14] + shdr[15] + htons(58 + tlen);
csum += pkt[0];
tlen -= 4;
pkt += 2;
while (tlen >= 64) {
csum += pkt[0] + pkt[1] + pkt[2] + pkt[3] + pkt[4] + pkt[5] + pkt[6] +
pkt[7] + pkt[8] + pkt[9] + pkt[10] + pkt[11] + pkt[12] + pkt[13] +
pkt[14] + pkt[15] + pkt[16] + pkt[17] + pkt[18] + pkt[19] +
pkt[20] + pkt[21] + pkt[22] + pkt[23] + pkt[24] + pkt[25] +
pkt[26] + pkt[27] + pkt[28] + pkt[29] + pkt[30] + pkt[31];
tlen -= 64;
pkt += 32;
}
while (tlen >= 32) {
csum += pkt[0] + pkt[1] + pkt[2] + pkt[3] + pkt[4] + pkt[5] + pkt[6] +
pkt[7] + pkt[8] + pkt[9] + pkt[10] + pkt[11] + pkt[12] + pkt[13] +
pkt[14] + pkt[15];
tlen -= 32;
pkt += 16;
}
while(tlen >= 8) {
csum += pkt[0] + pkt[1] + pkt[2] + pkt[3];
tlen -= 8;
pkt += 4;
}
while(tlen >= 4) {
csum += pkt[0] + pkt[1];
tlen -= 4;
pkt += 2;
}
while (tlen > 1) {
csum += pkt[0];
tlen -= 2;
pkt += 1;
}
if (tlen == 1) {
*(uint8_t *)(&pad) = (*(uint8_t *)pkt);
csum += pad;
}
csum = (csum >> 16) + (csum & 0x0000FFFF);
return (uint16_t) ~csum;
}
void DecodeICMPV6(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t len, PacketQueue *pq)
{
@ -23,3 +95,68 @@ void DecodeICMPV6(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt
return;
}
static int ICMPV6CalculateValidChecksumtest01(void) {
uint16_t csum = 0;
uint8_t raw_ipv6[] = {
0x00, 0x00, 0x86, 0x05, 0x80, 0xda, 0x00, 0x60,
0x97, 0x07, 0x69, 0xea, 0x86, 0xdd, 0x60, 0x00,
0x00, 0x00, 0x00, 0x44, 0x3a, 0x40, 0x3f, 0xfe,
0x05, 0x07, 0x00, 0x00, 0x00, 0x01, 0x02, 0x60,
0x97, 0xff, 0xfe, 0x07, 0x69, 0xea, 0x3f, 0xfe,
0x05, 0x07, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00,
0x86, 0xff, 0xfe, 0x05, 0x80, 0xda, 0x03, 0x00,
0xf7, 0x52, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00,
0x00, 0x00, 0x00, 0x14, 0x11, 0x01, 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, 0xa0, 0x75,
0x82, 0x9b, 0x00, 0x14, 0x82, 0x8b, 0x01, 0x01,
0x00, 0x00, 0xf9, 0xc8, 0xe7, 0x36, 0xf5, 0xed,
0x08, 0x00};
csum = *( ((uint16_t *)(raw_ipv6 + 56)));
return (csum == ICMPV6CalculateChecksum((uint16_t *)(raw_ipv6 + 14 + 8),
(uint16_t *)(raw_ipv6 + 54), 68));
}
static int ICMPV6CalculateInvalidChecksumtest02(void) {
uint16_t csum = 0;
uint8_t raw_ipv6[] = {
0x00, 0x00, 0x86, 0x05, 0x80, 0xda, 0x00, 0x60,
0x97, 0x07, 0x69, 0xea, 0x86, 0xdd, 0x60, 0x00,
0x00, 0x00, 0x00, 0x44, 0x3a, 0x40, 0x3f, 0xfe,
0x05, 0x07, 0x00, 0x00, 0x00, 0x01, 0x02, 0x60,
0x97, 0xff, 0xfe, 0x07, 0x69, 0xea, 0x3f, 0xfe,
0x05, 0x07, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00,
0x86, 0xff, 0xfe, 0x05, 0x80, 0xda, 0x03, 0x00,
0xf7, 0x52, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00,
0x00, 0x00, 0x00, 0x14, 0x11, 0x01, 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, 0xa0, 0x75,
0x82, 0x9b, 0x00, 0x14, 0x82, 0x8b, 0x01, 0x01,
0x00, 0x00, 0xf9, 0xc8, 0xe7, 0x36, 0xf5, 0xed,
0x08, 0x01};
csum = *( ((uint16_t *)(raw_ipv6 + 56)));
return (csum == ICMPV6CalculateChecksum((uint16_t *)(raw_ipv6 + 14 + 8),
(uint16_t *)(raw_ipv6 + 54), 68));
}
/**
* \brief Registers ICMPV6 unit tests
* \todo More ICMPv6 tests
*/
void DecodeICMPV6RegisterTests(void)
{
UtRegisterTest("ICMPV6CalculateValidChecksumtest01",
ICMPV6CalculateValidChecksumtest01, 1);
UtRegisterTest("ICMPV6CalculateInValidChecksumtest02",
ICMPV6CalculateInvalidChecksumtest02, 0);
}

@ -73,5 +73,7 @@ typedef struct ICMPV6Hdr_
/* XXX incomplete */
} ICMPV6Hdr;
void DecodeICMPV6RegisterTests(void);
#endif /* __DECODE_ICMPV6_H__ */

@ -68,6 +68,68 @@ static inline uint16_t TCPCalculateChecksum(uint16_t *shdr, uint16_t *pkt,
return (uint16_t) ~csum;
}
/**
* \brief Calculates the checksum for the TCP packet
*
* \param shdr Pointer to source address field from the IPV6 packet. Used as a
* part of the psuedoheader for computing the checksum
* \param pkt Pointer to the start of the TCP packet
* \param tlen Total length of the TCP packet(header + payload)
*
* \retval csum Checksum for the TCP packet
*/
static inline uint16_t TCPV6CalculateChecksum(uint16_t *shdr, uint16_t *pkt,
uint16_t tlen)
{
uint16_t pad = 0;
uint32_t csum = shdr[0];
csum += shdr[1] + shdr[2] + shdr[3] + shdr[4] + shdr[5] + shdr[6] +
shdr[7] + shdr[8] + shdr[9] + shdr[10] + shdr[11] + shdr[12] +
shdr[13] + shdr[14] + shdr[15] + htons(6 + tlen);
csum += pkt[0] + pkt[1] + pkt[2] + pkt[3] + pkt[4] + pkt[5] + pkt[6] +
pkt[7] + pkt[9];
tlen -= 20;
pkt += 10;
while (tlen >= 32) {
csum += pkt[0] + pkt[1] + pkt[2] + pkt[3] + pkt[4] + pkt[5] + pkt[6] +
pkt[7] + pkt[8] + pkt[9] + pkt[10] + pkt[11] + pkt[12] + pkt[13] +
pkt[14] + pkt[15];
tlen -= 32;
pkt += 16;
}
while(tlen >= 8) {
csum += pkt[0] + pkt[1] + pkt[2] + pkt[3];
tlen -= 8;
pkt += 4;
}
while(tlen >= 4) {
csum += pkt[0] + pkt[1];
tlen -= 4;
pkt += 2;
}
while (tlen > 1) {
csum += pkt[0];
pkt += 1;
tlen -= 2;
}
if (tlen == 1) {
*(uint8_t *)(&pad) = (*(uint8_t *)pkt);
csum += pad;
}
csum = (csum >> 16) + (csum & 0x0000FFFF);
return (uint16_t) ~csum;
}
static int DecodeTCPOptions(ThreadVars *tv, Packet *p, uint8_t *pkt, uint16_t len)
{
uint16_t plen = len;
@ -259,10 +321,61 @@ static int TCPCalculateInvalidChecksumtest02(void)
(uint16_t *)raw_tcp, sizeof(raw_tcp)));
}
static int TCPV6CalculateValidChecksumtest03(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, 0x27};
csum = *( ((uint16_t *)(raw_ipv6 + 70)));
return (csum == TCPV6CalculateChecksum((uint16_t *)(raw_ipv6 + 14 + 8),
(uint16_t *)(raw_ipv6 + 54), 32));
}
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));
}
void DecodeTCPRegisterTests(void)
{
UtRegisterTest("TCPCalculateValidChecksumtest01",
TCPCalculateValidChecksumtest01, 1);
UtRegisterTest("TCPCalculateInvalidChecksumtest02",
TCPCalculateInvalidChecksumtest02, 0);
UtRegisterTest("TCPV6CalculateValidChecksumtest03",
TCPV6CalculateValidChecksumtest03, 1);
UtRegisterTest("TCPV6CalculateInvalidChecksumtest04",
TCPV6CalculateInvalidChecksumtest04, 0);
}

@ -67,6 +67,67 @@ static inline uint16_t UDPV4CalculateChecksum(uint16_t *shdr, uint16_t *pkt,
return (uint16_t) ~csum;
}
/**
* \brief Calculates the checksum for the UDP packet
*
* \param shdr Pointer to source address field from the IPV6 packet. Used as a
* part of the psuedoheader for computing the checksum
* \param pkt Pointer to the start of the UDP packet
* \param tlen Total length of the UDP packet(header + payload)
*
* \retval csum Checksum for the UDP packet
*/
static inline uint16_t UDPV6CalculateChecksum(uint16_t *shdr, uint16_t *pkt,
uint16_t tlen)
{
uint16_t pad = 0;
uint32_t csum = shdr[0];
csum += shdr[1] + shdr[2] + shdr[3] + shdr[4] + shdr[5] + shdr[6] +
shdr[7] + shdr[8] + shdr[9] + shdr[10] + shdr[11] + shdr[12] +
shdr[13] + shdr[14] + shdr[15] + htons(17 + tlen);
csum += pkt[0] + pkt[1] + pkt[2];
tlen -= 8;
pkt += 4;
while (tlen >= 32) {
csum += pkt[0] + pkt[1] + pkt[2] + pkt[3] + pkt[4] + pkt[5] + pkt[6] +
pkt[7] + pkt[8] + pkt[9] + pkt[10] + pkt[11] + pkt[12] + pkt[13] +
pkt[14] + pkt[15];
tlen -= 32;
pkt += 16;
}
while(tlen >= 8) {
csum += pkt[0] + pkt[1] + pkt[2] + pkt[3];
tlen -= 8;
pkt += 4;
}
while(tlen >= 4) {
csum += pkt[0] + pkt[1];
tlen -= 4;
pkt += 2;
}
while (tlen > 1) {
csum += pkt[0];
pkt += 1;
tlen -= 2;
}
if (tlen == 1) {
*(uint8_t *)(&pad) = (*(uint8_t *)pkt);
csum += pad;
}
csum = (csum >> 16) + (csum & 0x0000FFFF);
return (uint16_t) ~csum;
}
static int DecodeUDPPacket(ThreadVars *t, Packet *p, uint8_t *pkt, uint16_t len)
{
if (len < UDP_HEADER_LEN) {
@ -171,10 +232,58 @@ static int UDPV4CalculateInvalidChecksumtest02(void)
sizeof(raw_udp)));
}
static int UDPV6CalculateValidChecksumtest03(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, 0x14, 0x11, 0x02, 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, 0xa0, 0x75,
0x82, 0xa0, 0x00, 0x14, 0x1a, 0xc3, 0x06, 0x02,
0x00, 0x00, 0xf9, 0xc8, 0xe7, 0x36, 0x57, 0xb0,
0x09, 0x00};
csum = *( ((uint16_t *)(raw_ipv6 + 60)));
return (csum == UDPV6CalculateChecksum((uint16_t *)(raw_ipv6 + 14 + 8),
(uint16_t *)(raw_ipv6 + 54), 20));
}
static int UDPV6CalculateInvalidChecksumtest04(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, 0x14, 0x11, 0x02, 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, 0xa0, 0x75,
0x82, 0xa0, 0x00, 0x14, 0x1a, 0xc3, 0x06, 0x02,
0x00, 0x00, 0xf9, 0xc8, 0xe7, 0x36, 0x57, 0xb0,
0x09, 0x01};
csum = *( ((uint16_t *)(raw_ipv6 + 60)));
return (csum == UDPV6CalculateChecksum((uint16_t *)(raw_ipv6 + 14 + 8),
(uint16_t *)(raw_ipv6 + 54), 20));
}
void DecodeUDPV4RegisterTests(void)
{
UtRegisterTest("UDPV4CalculateValidChecksumtest01",
UDPV4CalculateValidChecksumtest01, 1);
UtRegisterTest("UDPV4CalculateInvalidChecksumtest02",
UDPV4CalculateInvalidChecksumtest02, 0);
UtRegisterTest("UDPV6CalculateValidChecksumtest03",
UDPV6CalculateValidChecksumtest03, 1);
UtRegisterTest("UDPV6CalculateInvalidChecksumtest04",
UDPV6CalculateInvalidChecksumtest04, 0);
}

@ -973,6 +973,7 @@ int main(int argc, char **argv)
TLSParserRegisterTests();
DecodePPPOERegisterTests();
DecodeICMPV4RegisterTests();
DecodeICMPV6RegisterTests();
DecodeIPV4RegisterTests();
DecodeTCPRegisterTests();
DecodeUDPV4RegisterTests();

Loading…
Cancel
Save