chunk: Add function to calculate Internet Checksums according to RFC 1071

This commit is contained in:
Tobias Brunner
2014-07-22 11:10:35 +02:00
parent a10eb93566
commit b557f4a7cd
3 changed files with 105 additions and 0 deletions
@@ -783,6 +783,51 @@ START_TEST(test_chunk_hash_static)
}
END_TEST
/*******************************************************************************
* test for chunk_internet_checksum[_inc]()
*/
START_TEST(test_chunk_internet_checksum)
{
chunk_t chunk;
u_int16_t sum;
chunk = chunk_from_chars(0x45,0x00,0x00,0x30,0x44,0x22,0x40,0x00,0x80,0x06,
0x00,0x00,0x8c,0x7c,0x19,0xac,0xae,0x24,0x1e,0x2b);
sum = chunk_internet_checksum(chunk);
ck_assert_int_eq(0x442e, ntohs(sum));
sum = chunk_internet_checksum(chunk_create(chunk.ptr, 10));
sum = chunk_internet_checksum_inc(chunk_create(chunk.ptr+10, 10), sum);
ck_assert_int_eq(0x442e, ntohs(sum));
/* need to compensate for even/odd alignment */
sum = chunk_internet_checksum(chunk_create(chunk.ptr, 9));
sum = ntohs(sum);
sum = chunk_internet_checksum_inc(chunk_create(chunk.ptr+9, 11), sum);
sum = ntohs(sum);
ck_assert_int_eq(0x442e, ntohs(sum));
chunk = chunk_from_chars(0x45,0x00,0x00,0x30,0x44,0x22,0x40,0x00,0x80,0x06,
0x00,0x00,0x8c,0x7c,0x19,0xac,0xae,0x24,0x1e);
sum = chunk_internet_checksum(chunk);
ck_assert_int_eq(0x4459, ntohs(sum));
sum = chunk_internet_checksum(chunk_create(chunk.ptr, 10));
sum = chunk_internet_checksum_inc(chunk_create(chunk.ptr+10, 9), sum);
ck_assert_int_eq(0x4459, ntohs(sum));
/* need to compensate for even/odd alignment */
sum = chunk_internet_checksum(chunk_create(chunk.ptr, 9));
sum = ntohs(sum);
sum = chunk_internet_checksum_inc(chunk_create(chunk.ptr+9, 10), sum);
sum = ntohs(sum);
ck_assert_int_eq(0x4459, ntohs(sum));
}
END_TEST
/*******************************************************************************
* test for chunk_map and friends
*/
@@ -1018,6 +1063,10 @@ Suite *chunk_suite_create()
tcase_add_test(tc, test_chunk_hash_static);
suite_add_tcase(s, tc);
tc = tcase_create("chunk_internet_checksum");
tcase_add_test(tc, test_chunk_internet_checksum);
suite_add_tcase(s, tc);
tc = tcase_create("chunk_map");
tcase_add_test(tc, test_chunk_map);
suite_add_tcase(s, tc);
+31
View File
@@ -987,6 +987,37 @@ u_int32_t chunk_hash_static(chunk_t chunk)
return chunk_mac(chunk, static_key);
}
/**
* Described in header.
*/
u_int16_t chunk_internet_checksum_inc(chunk_t data, u_int16_t checksum)
{
u_int32_t sum = ntohs(~checksum);
while (data.len > 1)
{
sum += untoh16(data.ptr);
data = chunk_skip(data, 2);
}
if (data.len)
{
sum += (u_int16_t)*data.ptr << 8;
}
while (sum >> 16)
{
sum = (sum & 0xffff) + (sum >> 16);
}
return htons(~sum);
}
/**
* Described in header.
*/
u_int16_t chunk_internet_checksum(chunk_t data)
{
return chunk_internet_checksum_inc(data, 0xffff);
}
/**
* Described in header.
*/
+25
View File
@@ -411,6 +411,31 @@ u_int32_t chunk_hash_static_inc(chunk_t chunk, u_int32_t hash);
*/
u_int64_t chunk_mac(chunk_t chunk, u_char *key);
/**
* Calculate the Internet Checksum according to RFC 1071 for the given chunk.
*
* If the result is used with chunk_internet_checksum_inc() and the data length
* is not a multiple of 16 bit the checksum bytes have to be swapped to
* compensate the even/odd alignment.
*
* @param chunk data to process
* @return checksum (one's complement, network order)
*/
u_int16_t chunk_internet_checksum(chunk_t data);
/**
* Extend the given Internet Checksum (one's complement, in network byte order)
* with the given data.
*
* If data is not a multiple of 16 bits the checksum may have to be swapped to
* compensate even/odd alignment (see chunk_internet_checksum()).
*
* @param chunk data to process
* @param checksum previous checksum (one's complement, network order)
* @return checksum (one's complement, network order)
*/
u_int16_t chunk_internet_checksum_inc(chunk_t data, u_int16_t checksum);
/**
* printf hook function for chunk_t.
*