/* vim: set expandtab ts=4 sw=4: */
/*
* You may redistribute this program and/or modify it under the terms of
* the GNU General Public License as published by the Free Software Foundation,
* either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#include "util/Checksum.h"
#include "util/Bits.h"
#include "util/Endian.h"
#include "util/Hex.h"
#include "util/Assert.h"
#include
#include
static void checksumAlgorithmTestCase(const char* hex, uint16_t expectedSum)
{
Assert_true(strlen(hex) < 512);
uint8_t packetBuff[256];
uint8_t* packet = packetBuff + ((uintptr_t)packetBuff % 2);
Assert_true(Hex_decode(packet, 256, hex, strlen(hex)) == (int)(strlen(hex) / 2));
uint16_t calcatedSum = Checksum_engine_be(packet, strlen(hex) / 2);
uint16_t expected_be = Endian_hostToBigEndian16(expectedSum);
if (calcatedSum != expected_be) {
printf("%2x != %2x\n", calcatedSum, expected_be);
Assert_true(calcatedSum == expected_be);
}
}
static void checksumAlgorithmTest()
{
checksumAlgorithmTestCase("00", 0xffff);
checksumAlgorithmTestCase("0001", 0xfffe);
checksumAlgorithmTestCase("000102", 0xfdfe);
checksumAlgorithmTestCase("00010203", 0xfdfb);
checksumAlgorithmTestCase("ff", 0xff);
checksumAlgorithmTestCase("fffe", 0x1);
checksumAlgorithmTestCase("fffefd", 0x300);
checksumAlgorithmTestCase("fffefdfc", 0x204);
checksumAlgorithmTestCase("45000054ccf3000040010000c0a80001c0a8000b", 0x2c59);
checksumAlgorithmTestCase("45000034fa4d400040064b8d0a4206015cde87c8", 0x0000);
checksumAlgorithmTestCase("45000034fa4d4000400600000a4206015cde87c8", 0x4b8d);
}
#define UDP_PACKET_HEX /* vvvv --- IPv4 header checksum */\
"4500""0033""7a95""4000""4011""f877""c0a8""0102""0402""0201" \
/* UDP checksum -- vvvv */\
"9e05""0035""001f""c7dd" \
/* content */\
"221a""0100""0001""0000""0000""0000""0564""6562""6f38""0000""1c00""01"
static const uint8_t* udpPacketHex = (uint8_t*) UDP_PACKET_HEX;
#define UDP_PACKET_SIZE ((sizeof(UDP_PACKET_HEX)-1)/2)
static void checksumUDPTest()
{
uint8_t packetBuff[UDP_PACKET_SIZE + 1];
uint8_t* packet = packetBuff + ((uintptr_t)packetBuff % 2);
Hex_decode(packet, UDP_PACKET_SIZE, udpPacketHex, UDP_PACKET_SIZE * 2);
//operating on the ip checksum which is easy to compute.
uint16_t checksum;
Bits_memcpy(&checksum, &packet[8], 2);
packet[8] = 0;
packet[9] = 0;
uint16_t calcatedSum = Checksum_engine_be(packet, 20);
//printf("%2x == %2x", checksum, calcatedSum);
Assert_true(checksum == calcatedSum);
}
#define UDP6_PACKET_HEX \
/* Packet type --- vv */ \
"6000""0000""0019""1140" \
/* Source addr. */ \
"fce5""de17""cbde""c87b""5289""0556""8b83""c9c8" \
/* Dest addr. */ \
"fc00""0000""0000""0000""0000""0000""0000""0001" \
/* UDP checksum -- vvvv */ \
"b4a9""0035""0019""4972" \
/* Content */ \
"e4e4""0100""0001""0000""0000""0000""0000""0200" \
"01"
static const uint8_t* udp6PacketHex = (uint8_t*) UDP6_PACKET_HEX;
#define UDP6_PACKET_SIZE ((sizeof(UDP6_PACKET_HEX)-1)/2)
static void udp6ChecksumTest()
{
uint8_t packet[UDP6_PACKET_SIZE + 3];
Hex_decode(packet, UDP6_PACKET_SIZE, udp6PacketHex, UDP6_PACKET_SIZE * 2);
// add some evil at the end to check for buffer overrun
packet[UDP6_PACKET_SIZE] = 0x00;
packet[UDP6_PACKET_SIZE + 1] = 0x00;
packet[UDP6_PACKET_SIZE + 2] = 0x00;
uint16_t udp6Checksum;
Bits_memcpy(&udp6Checksum, &packet[46], 2);
packet[46] = 0;
packet[47] = 0;
uint16_t calcatedSum = Checksum_udpIp6_be(&packet[8], &packet[40], 25);
printf("%2x == %2x", udp6Checksum, calcatedSum);
Assert_true(udp6Checksum == calcatedSum);
}
#define PING6_PACKET_HEX \
/* Packet type --- vv */ \
"6000""0000""0040""3a40" \
/* Source Addr. */\
"fce5""de17""cbde""c87b""5289""0556""8b83""c9c8" \
/* Dest Addr. */\
"fc00""0000""0000""0000""0000""0000""0000""0001" \
/* vvvv -- ICMP6 Checksum */\
"8000""1d00" \
/* Content */\
"792e""0020""11d3""a04f""0000""0000""57bb""0800" \
"0000""0000""1011""1213""1415""1617""1819""1a1b" \
"1c1d""1e1f""2021""2223""2425""2627""2829""2a2b" \
"2c2d""2e2f""3031""3233""3435""3637"
static const uint8_t* ping6PacketHex = (uint8_t*) PING6_PACKET_HEX;
#define PING6_PACKET_SIZE ((sizeof(PING6_PACKET_HEX)-1)/2)
static void icmp6ChecksumTest()
{
uint8_t packet[PING6_PACKET_SIZE];
Hex_decode(packet, PING6_PACKET_SIZE, ping6PacketHex, PING6_PACKET_SIZE * 2);
uint16_t checksum;
Bits_memcpy(&checksum, &packet[42], 2);
packet[42] = 0;
packet[43] = 0;
uint16_t calcatedSum = Checksum_icmp6_be(&packet[8], &packet[40], 64);
//printf("%2x == %2x", checksum, calcatedSum);
Assert_true(checksum == calcatedSum);
}
int main()
{
checksumAlgorithmTest();
checksumUDPTest();
udp6ChecksumTest();
icmp6ChecksumTest();
return 0;
}