From 98a8234e0ad1053cab59213814012e25d50587eb Mon Sep 17 00:00:00 2001 From: Anoop Saldanha Date: Thu, 5 Apr 2012 20:45:38 +0530 Subject: [PATCH] csum function fixes. Improves alert accuracy. FPs on invalid-csums decoder rules fixed --- src/decode-icmpv4.h | 1 + src/decode-icmpv6.h | 1 + src/decode-ipv4.h | 23 ++++++++++++----------- src/decode-tcp.h | 2 +- src/decode-udp.h | 16 +++++++++++++--- src/detect-csum.c | 2 +- 6 files changed, 29 insertions(+), 16 deletions(-) diff --git a/src/decode-icmpv4.h b/src/decode-icmpv4.h index ead983ec6b..547bb06745 100644 --- a/src/decode-icmpv4.h +++ b/src/decode-icmpv4.h @@ -339,6 +339,7 @@ static inline uint16_t ICMPV4CalculateChecksum(uint16_t *pkt, uint16_t tlen) } csum = (csum >> 16) + (csum & 0x0000FFFF); + csum += (csum >> 16); return (uint16_t) ~csum; } diff --git a/src/decode-icmpv6.h b/src/decode-icmpv6.h index da5ee25a81..b0c47a8338 100644 --- a/src/decode-icmpv6.h +++ b/src/decode-icmpv6.h @@ -247,6 +247,7 @@ static inline uint16_t ICMPV6CalculateChecksum(uint16_t *shdr, uint16_t *pkt, } csum = (csum >> 16) + (csum & 0x0000FFFF); + csum += (csum >> 16); return (uint16_t) ~csum; } diff --git a/src/decode-ipv4.h b/src/decode-ipv4.h index 82a122e122..1764a69d6b 100644 --- a/src/decode-ipv4.h +++ b/src/decode-ipv4.h @@ -212,39 +212,40 @@ static inline uint16_t IPV4CalculateChecksum(uint16_t *pkt, uint16_t hlen) if (hlen == 0) { ; - } - if (hlen == 4) + } else if (hlen == 4) { csum += pkt[0] + pkt[1]; - else if (hlen == 8) + } else if (hlen == 8) { csum += pkt[0] + pkt[1] + pkt[2] + pkt[3]; - else if (hlen == 12) + } else if (hlen == 12) { csum += pkt[0] + pkt[1] + pkt[2] + pkt[3] + pkt[4] + pkt[5]; - else if (hlen == 16) + } else if (hlen == 16) { csum += pkt[0] + pkt[1] + pkt[2] + pkt[3] + pkt[4] + pkt[5] + pkt[6] + pkt[7]; - else if (hlen == 20) + } else if (hlen == 20) { csum += pkt[0] + pkt[1] + pkt[2] + pkt[3] + pkt[4] + pkt[5] + pkt[6] + pkt[7] + pkt[8] + pkt[9]; - else if (hlen == 24) + } else if (hlen == 24) { 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]; - else if (hlen == 28) + } else if (hlen == 28) { 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]; - else if (hlen == 32) + } else if (hlen == 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]; - if (hlen == 36) + } else if (hlen == 36) { 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]; - if (hlen == 40) + } else if (hlen == 40) { 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]; + } csum = (csum >> 16) + (csum & 0x0000FFFF); + csum += (csum >> 16); return (uint16_t) ~csum; } diff --git a/src/decode-tcp.h b/src/decode-tcp.h index 9e29ebd2e7..e9ab99ea68 100644 --- a/src/decode-tcp.h +++ b/src/decode-tcp.h @@ -182,7 +182,7 @@ static inline uint16_t TCPV6CalculateChecksum(uint16_t *, uint16_t *, uint16_t); * \retval csum Checksum for the TCP packet */ static inline uint16_t TCPCalculateChecksum(uint16_t *shdr, uint16_t *pkt, - uint16_t tlen) + uint16_t tlen) { uint16_t pad = 0; uint32_t csum = shdr[0]; diff --git a/src/decode-udp.h b/src/decode-udp.h index c8332810e9..4f24892d60 100644 --- a/src/decode-udp.h +++ b/src/decode-udp.h @@ -72,7 +72,7 @@ static inline uint16_t UDPV6CalculateChecksum(uint16_t *, uint16_t *, uint16_t); * \retval csum Checksum for the UDP packet */ static inline uint16_t UDPV4CalculateChecksum(uint16_t *shdr, uint16_t *pkt, - uint16_t tlen) + uint16_t tlen) { uint16_t pad = 0; uint32_t csum = shdr[0]; @@ -118,7 +118,11 @@ static inline uint16_t UDPV4CalculateChecksum(uint16_t *shdr, uint16_t *pkt, csum = (csum >> 16) + (csum & 0x0000FFFF); csum += (csum >> 16); - return (uint16_t)~csum; + uint16_t csum_u16 = (uint16_t)~csum; + if (csum_u16 == 0) + return 0xFFFF; + else + return csum_u16; } /** @@ -132,7 +136,7 @@ static inline uint16_t UDPV4CalculateChecksum(uint16_t *shdr, uint16_t *pkt, * \retval csum Checksum for the UDP packet */ static inline uint16_t UDPV6CalculateChecksum(uint16_t *shdr, uint16_t *pkt, - uint16_t tlen) + uint16_t tlen) { uint16_t pad = 0; uint32_t csum = shdr[0]; @@ -180,6 +184,12 @@ static inline uint16_t UDPV6CalculateChecksum(uint16_t *shdr, uint16_t *pkt, csum = (csum >> 16) + (csum & 0x0000FFFF); csum += (csum >> 16); + uint16_t csum_u16 = (uint16_t)~csum; + if (csum_u16 == 0) + return 0xFFFF; + else + return csum_u16; + return (uint16_t)~csum; } diff --git a/src/detect-csum.c b/src/detect-csum.c index a0d0db8b14..418f87c67d 100644 --- a/src/detect-csum.c +++ b/src/detect-csum.c @@ -239,7 +239,7 @@ int DetectIPV4CsumMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx, if (p->ip4vars.comp_csum == -1) p->ip4vars.comp_csum = IPV4CalculateChecksum((uint16_t *)p->ip4h, - IPV4_GET_RAW_HLEN(p->ip4h)); + IPV4_GET_HLEN(p)); if (p->ip4vars.comp_csum == p->ip4h->ip_csum && cd->valid == 1) return 1;