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
*/
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);
/**
* 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.
+ */
int chunk_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
const void *const *args)
{
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.
*
* Arguments are: