mirror of
https://github.com/genodelabs/genode.git
synced 2025-03-11 06:54:18 +00:00
net: use generic internet checksum
This reduces the redundant implementations of checksum calculation to one generic implementation, makes the checksum interface conform over all protocols, and brings performance optimizations. For instance, the checksum is now calculated directly in big endian which saves us most of the previously done byte-re-ordering. Issue #2775
This commit is contained in:
parent
836df90f6b
commit
6b55790e73
@ -57,7 +57,9 @@ class Net::Icmp_packet
|
||||
ECHO_REPLY = 0,
|
||||
};
|
||||
|
||||
Genode::uint16_t calc_checksum(Genode::size_t data_sz) const;
|
||||
void update_checksum(Genode::size_t data_sz);
|
||||
|
||||
bool checksum_error(Genode::size_t data_sz) const;
|
||||
|
||||
|
||||
/***************
|
||||
|
35
repos/os/include/net/internet_checksum.h
Normal file
35
repos/os/include/net/internet_checksum.h
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* \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.
|
||||
*/
|
||||
|
||||
#ifndef _NET__INTERNET_CHECKSUM_H_
|
||||
#define _NET__INTERNET_CHECKSUM_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <net/ipv4.h>
|
||||
#include <base/stdint.h>
|
||||
|
||||
namespace Net {
|
||||
|
||||
Genode::uint16_t internet_checksum(Genode::uint16_t const *addr,
|
||||
Genode::size_t size,
|
||||
Genode::addr_t init_sum = 0);
|
||||
|
||||
Genode::uint16_t internet_checksum_pseudo_ip(Genode::uint16_t const *addr,
|
||||
Genode::size_t size,
|
||||
Genode::uint16_t size_be,
|
||||
Ipv4_packet::Protocol ip_prot,
|
||||
Ipv4_address &ip_src,
|
||||
Ipv4_address &ip_dst);
|
||||
}
|
||||
|
||||
#endif /* _NET__INTERNET_CHECKSUM_H_ */
|
@ -90,7 +90,9 @@ class Net::Ipv4_packet
|
||||
|
||||
static Ipv4_address ip_from_string(const char *ip);
|
||||
|
||||
static Genode::uint16_t calculate_checksum(Ipv4_packet const &packet);
|
||||
void update_checksum();
|
||||
|
||||
bool checksum_error() const;
|
||||
|
||||
private:
|
||||
|
||||
|
@ -70,6 +70,11 @@ class Net::Tcp_packet
|
||||
|
||||
public:
|
||||
|
||||
void update_checksum(Ipv4_address ip_src,
|
||||
Ipv4_address ip_dst,
|
||||
size_t tcp_size);
|
||||
|
||||
|
||||
/***************
|
||||
** Accessors **
|
||||
***************/
|
||||
@ -97,53 +102,6 @@ class Net::Tcp_packet
|
||||
void dst_port(Port p) { _dst_port = host_to_big_endian(p.value); }
|
||||
|
||||
|
||||
/**
|
||||
* TCP checksum is calculated over the tcp datagram + an IPv4
|
||||
* pseudo header.
|
||||
*
|
||||
* IPv4 pseudo header:
|
||||
*
|
||||
* --------------------------------------------------------------
|
||||
* | src-ipaddr | dst-ipaddr | zero-field | prot.-id | tcp-length |
|
||||
* | 4 bytes | 4 bytes | 1 byte | 1 byte | 2 bytes |
|
||||
* --------------------------------------------------------------
|
||||
*/
|
||||
void update_checksum(Ipv4_address ip_src,
|
||||
Ipv4_address ip_dst,
|
||||
size_t tcp_size)
|
||||
{
|
||||
/* have to reset the checksum field for calculation */
|
||||
_checksum = 0;
|
||||
|
||||
/* sum up pseudo header */
|
||||
uint32_t sum = 0;
|
||||
for (size_t i = 0; i < Ipv4_packet::ADDR_LEN; i += sizeof(uint16_t)) {
|
||||
uint16_t s = ip_src.addr[i] << 8 | ip_src.addr[i + 1];
|
||||
uint16_t d = ip_dst.addr[i] << 8 | ip_dst.addr[i + 1];
|
||||
sum += s + d;
|
||||
}
|
||||
uint8_t prot[] = { 0, (uint8_t)Ipv4_packet::Protocol::TCP };
|
||||
sum += host_to_big_endian(*(uint16_t *)&prot) + tcp_size;
|
||||
|
||||
/* sum up TCP packet itself */
|
||||
size_t max = (tcp_size & 1) ? (tcp_size - 1) : tcp_size;
|
||||
uint16_t * tcp = (uint16_t *)this;
|
||||
for (size_t i = 0; i < max; i = i + sizeof(*tcp)) {
|
||||
sum += host_to_big_endian(*tcp++); }
|
||||
|
||||
/* if TCP size is odd, append a zero byte */
|
||||
if (tcp_size & 1) {
|
||||
uint8_t last[] = { *((uint8_t *)this + (tcp_size - 1)), 0 };
|
||||
sum += host_to_big_endian(*(uint16_t *)&last);
|
||||
}
|
||||
/* keep the last 16 bits of the 32 bit sum and add the carries */
|
||||
while (sum >> 16) { sum = (sum & 0xffff) + (sum >> 16); }
|
||||
|
||||
/* one's complement of sum */
|
||||
_checksum = host_to_big_endian((uint16_t)~sum);
|
||||
}
|
||||
|
||||
|
||||
/*********
|
||||
** log **
|
||||
*********/
|
||||
|
@ -76,6 +76,9 @@ class Net::Udp_packet
|
||||
return *Genode::construct_at<T>(_data);
|
||||
}
|
||||
|
||||
void update_checksum(Ipv4_address ip_src,
|
||||
Ipv4_address ip_dst);
|
||||
|
||||
|
||||
/***************
|
||||
** Accessors **
|
||||
@ -91,66 +94,6 @@ class Net::Udp_packet
|
||||
void dst_port(Port p) { _dst_port = host_to_big_endian(p.value); }
|
||||
|
||||
|
||||
/***************************
|
||||
** Convenience functions **
|
||||
***************************/
|
||||
|
||||
/**
|
||||
* UDP checksum is calculated over the udp datagram + an IPv4
|
||||
* pseudo header.
|
||||
*
|
||||
* IPv4 pseudo header:
|
||||
*
|
||||
* --------------------------------------------------------------
|
||||
* | src-ipaddr | dst-ipaddr | zero-field | prot.-id | udp-length |
|
||||
* | 4 bytes | 4 bytes | 1 byte | 1 byte | 2 bytes |
|
||||
* --------------------------------------------------------------
|
||||
*/
|
||||
void update_checksum(Ipv4_address src,
|
||||
Ipv4_address dst)
|
||||
{
|
||||
/* have to reset the checksum field for calculation */
|
||||
_checksum = 0;
|
||||
|
||||
/*
|
||||
* sum up pseudo header
|
||||
*/
|
||||
Genode::uint32_t sum = 0;
|
||||
for (unsigned i = 0; i < Ipv4_packet::ADDR_LEN; i=i+2) {
|
||||
Genode::uint16_t s = src.addr[i] << 8 | src.addr[i + 1];
|
||||
Genode::uint16_t d = dst.addr[i] << 8 | dst.addr[i + 1];
|
||||
sum += s + d;
|
||||
}
|
||||
Genode::uint8_t prot[] = { 0, (Genode::uint8_t)Ipv4_packet::Protocol::UDP };
|
||||
sum += host_to_big_endian(*(Genode::uint16_t*)&prot) + length();
|
||||
|
||||
/*
|
||||
* sum up udp packet itself
|
||||
*/
|
||||
unsigned max = (length() & 1) ? (length() - 1) : length();
|
||||
Genode::uint16_t *udp = (Genode::uint16_t*) this;
|
||||
for (unsigned i = 0; i < max; i=i+2)
|
||||
sum += host_to_big_endian(*udp++);
|
||||
|
||||
/* if udp length is odd, append a zero byte */
|
||||
if (length() & 1) {
|
||||
Genode::uint8_t last[] =
|
||||
{ *((Genode::uint8_t*)this + (length()-1)), 0 };
|
||||
sum += host_to_big_endian(*(Genode::uint16_t*)&last);
|
||||
}
|
||||
|
||||
/*
|
||||
* keep only the last 16 bits of the 32 bit calculated sum
|
||||
* and add the carries
|
||||
*/
|
||||
while (sum >> 16)
|
||||
sum = (sum & 0xffff) + (sum >> 16);
|
||||
|
||||
/* one's complement of sum */
|
||||
_checksum = host_to_big_endian((Genode::uint16_t) ~sum);
|
||||
}
|
||||
|
||||
|
||||
/*********
|
||||
** log **
|
||||
*********/
|
||||
|
@ -1,4 +1,4 @@
|
||||
SRC_CC += ethernet.cc ipv4.cc dhcp.cc arp.cc udp.cc tcp.cc mac_address.cc
|
||||
SRC_CC += icmp.cc
|
||||
SRC_CC += icmp.cc internet_checksum.cc
|
||||
|
||||
vpath %.cc $(REP_DIR)/src/lib/net
|
||||
|
@ -209,7 +209,7 @@ void Main::_handle_ip(Ethernet_frame ð,
|
||||
return;
|
||||
}
|
||||
/* drop packet if IP checksum is invalid */
|
||||
if (Ipv4_packet::calculate_checksum(ip) != ip.checksum()) {
|
||||
if (ip.checksum_error()) {
|
||||
if (_verbose) {
|
||||
log("bad IP checksum"); }
|
||||
return;
|
||||
@ -293,7 +293,7 @@ void Main::_handle_icmp_dst_unreachbl(Ipv4_packet &ip,
|
||||
{
|
||||
/* drop packet if embedded IP checksum is invalid */
|
||||
Ipv4_packet &embed_ip = icmp.data<Ipv4_packet>(icmp_data_sz);
|
||||
if (Ipv4_packet::calculate_checksum(embed_ip) != embed_ip.checksum()) {
|
||||
if (embed_ip.checksum_error()) {
|
||||
if (_verbose) {
|
||||
log("bad IP checksum in payload of ICMP error"); }
|
||||
return;
|
||||
@ -330,7 +330,7 @@ void Main::_handle_icmp(Ipv4_packet &ip,
|
||||
size_t const icmp_sz = ip_size - sizeof(Ipv4_packet);
|
||||
Icmp_packet &icmp = ip.data<Icmp_packet>(icmp_sz);
|
||||
size_t const icmp_data_sz = icmp_sz - sizeof(Icmp_packet);
|
||||
if (icmp.calc_checksum(icmp_data_sz) != icmp.checksum()) {
|
||||
if (icmp.checksum_error(icmp_data_sz)) {
|
||||
if (_verbose) {
|
||||
log("bad ICMP checksum"); }
|
||||
return;
|
||||
@ -509,9 +509,9 @@ void Main::_send_ping(Duration)
|
||||
chr = chr < 'z' ? chr + 1 : 'a';
|
||||
}
|
||||
/* fill in header values that require the packet to be complete */
|
||||
icmp.checksum(icmp.calc_checksum(_icmp_data_sz));
|
||||
icmp.update_checksum(_icmp_data_sz);
|
||||
ip.total_length(size.curr() - ip_off);
|
||||
ip.checksum(Ipv4_packet::calculate_checksum(ip));
|
||||
ip.update_checksum();
|
||||
});
|
||||
_send_time = _timer.curr_time().trunc_to_plain_us();
|
||||
}
|
||||
|
@ -12,6 +12,7 @@
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <net/internet_checksum.h>
|
||||
#include <net/icmp.h>
|
||||
#include <base/output.h>
|
||||
|
||||
@ -26,29 +27,14 @@ void Net::Icmp_packet::print(Output &output) const
|
||||
}
|
||||
|
||||
|
||||
uint16_t Icmp_packet::calc_checksum(size_t data_sz) const
|
||||
void Icmp_packet::update_checksum(size_t data_sz)
|
||||
{
|
||||
/* do not sum-up checksum itself */
|
||||
register long sum = _type + _code;
|
||||
addr_t addr = (addr_t)&_rest_of_header_u32;
|
||||
size_t count = sizeof(Icmp_packet) + data_sz - sizeof(_type) -
|
||||
sizeof(_code) - sizeof(_checksum);
|
||||
|
||||
/* sum-up rest of header and data */
|
||||
while (count > 1) {
|
||||
sum += *(uint16_t *)addr;
|
||||
addr += sizeof(uint16_t);
|
||||
count -= sizeof(uint16_t);
|
||||
}
|
||||
/* add left-over byte, if any */
|
||||
if (count) {
|
||||
sum += *(uint8_t *)addr;
|
||||
}
|
||||
/* fold 32-bit sum to 16 bits */
|
||||
while (sum >> 16) {
|
||||
sum = (sum & 0xffff) + (sum >> 16);
|
||||
}
|
||||
/* write to header */
|
||||
uint16_t sum16 = ~sum;
|
||||
return host_to_big_endian(sum16);
|
||||
_checksum = 0;
|
||||
_checksum = internet_checksum((uint16_t *)this, sizeof(Icmp_packet) + data_sz);
|
||||
}
|
||||
|
||||
|
||||
bool Icmp_packet::checksum_error(size_t data_sz) const
|
||||
{
|
||||
return internet_checksum((uint16_t *)this, sizeof(Icmp_packet) + data_sz);
|
||||
}
|
||||
|
64
repos/os/src/lib/net/internet_checksum.cc
Normal file
64
repos/os/src/lib/net/internet_checksum.cc
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* \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);
|
||||
}
|
@ -11,9 +11,10 @@
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/token.h>
|
||||
#include <util/string.h>
|
||||
|
||||
#include <net/internet_checksum.h>
|
||||
#include <net/udp.h>
|
||||
#include <net/tcp.h>
|
||||
#include <net/icmp.h>
|
||||
@ -133,17 +134,15 @@ Ipv4_address Ipv4_packet::ip_from_string(const char *ip)
|
||||
return ip_addr;
|
||||
}
|
||||
|
||||
Genode::uint16_t Ipv4_packet::calculate_checksum(Ipv4_packet const &packet)
|
||||
|
||||
void Ipv4_packet::update_checksum()
|
||||
{
|
||||
Genode::uint16_t const *data = (Genode::uint16_t *)&packet;
|
||||
Genode::uint32_t const sum = host_to_big_endian(data[0])
|
||||
+ host_to_big_endian(data[1])
|
||||
+ host_to_big_endian(data[2])
|
||||
+ host_to_big_endian(data[3])
|
||||
+ host_to_big_endian(data[4])
|
||||
+ host_to_big_endian(data[6])
|
||||
+ host_to_big_endian(data[7])
|
||||
+ host_to_big_endian(data[8])
|
||||
+ host_to_big_endian(data[9]);
|
||||
return ~((0xFFFF & sum) + (sum >> 16));
|
||||
_checksum = 0;
|
||||
_checksum = internet_checksum((uint16_t *)this, sizeof(Ipv4_packet));
|
||||
}
|
||||
|
||||
|
||||
bool Ipv4_packet::checksum_error() const
|
||||
{
|
||||
return internet_checksum((uint16_t *)this, sizeof(Ipv4_packet));
|
||||
}
|
||||
|
@ -12,9 +12,13 @@
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <net/internet_checksum.h>
|
||||
#include <net/tcp.h>
|
||||
#include <base/output.h>
|
||||
|
||||
using namespace Net;
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
void Net::Tcp_packet::print(Genode::Output &output) const
|
||||
{
|
||||
@ -32,3 +36,14 @@ void Net::Tcp_packet::print(Genode::Output &output) const
|
||||
if (ns()) { Genode::print(output, "n"); }
|
||||
Genode::print(output, "' ");
|
||||
}
|
||||
|
||||
|
||||
void Net::Tcp_packet::update_checksum(Ipv4_address ip_src,
|
||||
Ipv4_address ip_dst,
|
||||
size_t tcp_size)
|
||||
{
|
||||
_checksum = 0;
|
||||
_checksum = internet_checksum_pseudo_ip((uint16_t*)this, tcp_size,
|
||||
host_to_big_endian((uint16_t)tcp_size),
|
||||
Ipv4_packet::Protocol::TCP, ip_src, ip_dst);
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
/*
|
||||
* \brief User datagram protocol.
|
||||
* \author Stefan Kalkowski
|
||||
* \author Martin Stein
|
||||
* \date 2010-08-19
|
||||
*/
|
||||
|
||||
@ -11,11 +12,15 @@
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
/* Genode */
|
||||
/* Genode includes */
|
||||
#include <net/internet_checksum.h>
|
||||
#include <net/udp.h>
|
||||
#include <net/dhcp.h>
|
||||
#include <base/output.h>
|
||||
|
||||
using namespace Net;
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
void Net::Udp_packet::print(Genode::Output &output) const
|
||||
{
|
||||
@ -25,3 +30,12 @@ void Net::Udp_packet::print(Genode::Output &output) const
|
||||
Genode::print(output, *reinterpret_cast<Dhcp_packet const *>(_data));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Net::Udp_packet::update_checksum(Ipv4_address ip_src,
|
||||
Ipv4_address ip_dst)
|
||||
{
|
||||
_checksum = 0;
|
||||
_checksum = internet_checksum_pseudo_ip((uint16_t*)this, length(), _length,
|
||||
Ipv4_packet::Protocol::UDP, ip_src, ip_dst);
|
||||
}
|
||||
|
@ -267,6 +267,6 @@ void Dhcp_client::_send(Message_type msg_type,
|
||||
udp.length(size.curr() - udp_off);
|
||||
udp.update_checksum(ip.src(), ip.dst());
|
||||
ip.total_length(size.curr() - ip_off);
|
||||
ip.checksum(Ipv4_packet::calculate_checksum(ip));
|
||||
ip.update_checksum();
|
||||
});
|
||||
}
|
||||
|
@ -113,8 +113,8 @@ static void _update_checksum(L3_protocol const prot,
|
||||
case L3_protocol::ICMP:
|
||||
{
|
||||
Icmp_packet &icmp = *(Icmp_packet *)prot_base;
|
||||
icmp.checksum(icmp.calc_checksum(ip_size - sizeof(Ipv4_packet) -
|
||||
sizeof(Icmp_packet)));
|
||||
icmp.update_checksum(ip_size - sizeof(Ipv4_packet) -
|
||||
sizeof(Icmp_packet));
|
||||
return;
|
||||
}
|
||||
default: throw Interface::Bad_transport_protocol(); }
|
||||
@ -208,7 +208,7 @@ void Interface::_pass_ip(Ethernet_frame ð,
|
||||
size_t const eth_size,
|
||||
Ipv4_packet &ip)
|
||||
{
|
||||
ip.checksum(Ipv4_packet::calculate_checksum(ip));
|
||||
ip.update_checksum();
|
||||
send(eth, eth_size);
|
||||
}
|
||||
|
||||
@ -516,7 +516,7 @@ void Interface::_send_dhcp_reply(Dhcp_server const &dhcp_srv,
|
||||
udp.length(size.curr() - udp_off);
|
||||
udp.update_checksum(ip.src(), ip.dst());
|
||||
ip.total_length(size.curr() - ip_off);
|
||||
ip.checksum(Ipv4_packet::calculate_checksum(ip));
|
||||
ip.update_checksum();
|
||||
});
|
||||
}
|
||||
|
||||
@ -733,9 +733,9 @@ void Interface::_send_icmp_dst_unreachable(Ipv4_address_prefix const &local_intf
|
||||
Genode::memcpy(&icmp.data<char>(~0), &req_ip, icmp_data_size);
|
||||
|
||||
/* fill in header values that require the packet to be complete */
|
||||
icmp.checksum(icmp.calc_checksum(icmp_data_size));
|
||||
icmp.update_checksum(icmp_data_size);
|
||||
ip.total_length(size.curr() - ip_off);
|
||||
ip.checksum(Ipv4_packet::calculate_checksum(ip));
|
||||
ip.update_checksum();
|
||||
});
|
||||
}
|
||||
|
||||
@ -808,7 +808,7 @@ void Interface::_handle_icmp_error(Ethernet_frame ð,
|
||||
/* drop packet if embedded IP checksum invalid */
|
||||
size_t const embed_ip_sz = icmp_sz - sizeof(Icmp_packet);
|
||||
Ipv4_packet &embed_ip = icmp.data<Ipv4_packet>(embed_ip_sz);
|
||||
if (Ipv4_packet::calculate_checksum(embed_ip) != embed_ip.checksum()) {
|
||||
if (embed_ip.checksum_error()) {
|
||||
throw Drop_packet_inform("bad checksum in IP packet embedded in ICMP error");
|
||||
}
|
||||
/* get link identity of the embeddeded transport packet */
|
||||
@ -843,9 +843,9 @@ void Interface::_handle_icmp_error(Ethernet_frame ð,
|
||||
_dst_port(embed_prot, embed_prot_base, remote_side.dst_port());
|
||||
|
||||
/* update checksum of both IP headers and the ICMP header */
|
||||
embed_ip.checksum(Ipv4_packet::calculate_checksum(embed_ip));
|
||||
icmp.checksum(icmp.calc_checksum(icmp_sz - sizeof(Icmp_packet)));
|
||||
ip.checksum(Ipv4_packet::calculate_checksum(ip));
|
||||
embed_ip.update_checksum();
|
||||
icmp.update_checksum(icmp_sz - sizeof(Icmp_packet));
|
||||
ip.update_checksum();
|
||||
|
||||
/* send adapted packet to all interfaces of remote domain */
|
||||
remote_domain.interfaces().for_each([&] (Interface &interface) {
|
||||
@ -874,7 +874,7 @@ void Interface::_handle_icmp(Ethernet_frame ð,
|
||||
size_t const icmp_sz = ip.total_length() - sizeof(Ipv4_packet);
|
||||
Icmp_packet &icmp = ip.data<Icmp_packet>(icmp_sz);
|
||||
size_t const icmp_data_sz = icmp_sz - sizeof(Icmp_packet);
|
||||
if (icmp.calc_checksum(icmp_data_sz) != icmp.checksum()) {
|
||||
if (icmp.checksum_error(icmp_data_sz)) {
|
||||
throw Drop_packet_inform("bad ICMP checksum");
|
||||
}
|
||||
/* select ICMP message type */
|
||||
|
Loading…
x
Reference in New Issue
Block a user