65 lines
1.9 KiB
C++
65 lines
1.9 KiB
C++
/*
|
|
* \brief Computing the Internet Checksum (conforms to RFC 1071)
|
|
* \author Martin Stein
|
|
* \date 2018-03-23
|
|
*/
|
|
|
|
/*
|
|
* Copyright (C) 2018 Genode Labs GmbH
|
|
*
|
|
* This file is part of the Genode OS framework, which is distributed
|
|
* under the terms of the GNU Affero General Public License version 3.
|
|
*/
|
|
|
|
/* Genode includes */
|
|
#include <net/internet_checksum.h>
|
|
|
|
using namespace Net;
|
|
using namespace Genode;
|
|
|
|
|
|
uint16_t Net::internet_checksum(uint16_t const *addr,
|
|
size_t size,
|
|
addr_t init_sum)
|
|
{
|
|
/* add up bytes in pairs */
|
|
addr_t sum = init_sum;
|
|
for (; size > 1; size -= 2)
|
|
sum += *addr++;
|
|
|
|
/* add left-over byte, if any */
|
|
if (size > 0)
|
|
sum += *(uint8_t *)addr;
|
|
|
|
/* fold sum to 16-bit value */
|
|
while (addr_t const sum_rsh = sum >> 16)
|
|
sum = (sum & 0xffff) + sum_rsh;
|
|
|
|
/* return one's complement */
|
|
return ~sum;
|
|
}
|
|
|
|
|
|
uint16_t Net::internet_checksum_pseudo_ip(uint16_t const *ip_data,
|
|
size_t ip_data_sz,
|
|
uint16_t ip_data_sz_be,
|
|
Ipv4_packet::Protocol ip_prot,
|
|
Ipv4_address &ip_src,
|
|
Ipv4_address &ip_dst)
|
|
{
|
|
/*
|
|
* Add up pseudo IP header:
|
|
*
|
|
* --------------------------------------------------------------
|
|
* | src-ipaddr | dst-ipaddr | zero-field | prot.-id | data size |
|
|
* | 4 bytes | 4 bytes | 1 byte | 1 byte | 2 bytes |
|
|
* --------------------------------------------------------------
|
|
*/
|
|
addr_t sum = host_to_big_endian((uint16_t)ip_prot) + ip_data_sz_be;
|
|
for (size_t i = 0; i < Ipv4_packet::ADDR_LEN; i += 2)
|
|
sum += *(uint16_t*)&ip_src.addr[i] + *(uint16_t*)&ip_dst.addr[i];
|
|
|
|
/* add up IP data bytes */
|
|
return internet_checksum(ip_data, ip_data_sz, sum);
|
|
}
|