mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-10 21:01:49 +00:00
net: consider tail of Ethernet frame
The Ethernet payload may be followed by padding of variable length and the FCS (Frame Check Sequence). Thus, we should consider the value "Ethernet-frame size minus Ethernet-header size" to be only the maximum size of the encapsulated IP packet. But until now, we considered it to be also the actual size of the encapsulated IP packet. This commit fixes the problem for all affected components of the Genode base-repository. Fixes #2775
This commit is contained in:
parent
841d583678
commit
11a297b557
@ -151,6 +151,8 @@ class Net::Ipv4_packet
|
||||
return *Genode::construct_at<T>(_data);
|
||||
}
|
||||
|
||||
Genode::size_t size(Genode::size_t max_size) const;
|
||||
|
||||
|
||||
/***************
|
||||
** Accessors **
|
||||
|
@ -199,8 +199,9 @@ void Main::_handle_ip(Ethernet_frame ð,
|
||||
size_t const eth_size)
|
||||
{
|
||||
/* drop packet if IP does not target us */
|
||||
size_t const ip_size = eth_size - sizeof(Ethernet_frame);
|
||||
Ipv4_packet &ip = eth.data<Ipv4_packet>(ip_size);
|
||||
size_t const ip_max_size = eth_size - sizeof(Ethernet_frame);
|
||||
Ipv4_packet &ip = eth.data<Ipv4_packet>(ip_max_size);
|
||||
size_t const ip_size = ip.size(ip_max_size);
|
||||
if (ip.dst() != _src_ip &&
|
||||
ip.dst() != Ipv4_packet::broadcast())
|
||||
{
|
||||
|
@ -146,3 +146,10 @@ bool Ipv4_packet::checksum_error() const
|
||||
{
|
||||
return internet_checksum((uint16_t *)this, sizeof(Ipv4_packet));
|
||||
}
|
||||
|
||||
|
||||
size_t Ipv4_packet::size(size_t max_size) const
|
||||
{
|
||||
size_t const stated_size = total_length();
|
||||
return stated_size < max_size ? stated_size : max_size;
|
||||
}
|
||||
|
@ -19,6 +19,8 @@
|
||||
#include <component.h>
|
||||
|
||||
using namespace Net;
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
bool Session_component::handle_arp(Ethernet_frame *eth, Genode::size_t size)
|
||||
{
|
||||
@ -50,17 +52,19 @@ bool Session_component::handle_arp(Ethernet_frame *eth, Genode::size_t size)
|
||||
|
||||
bool Session_component::handle_ip(Ethernet_frame *eth, Genode::size_t size)
|
||||
{
|
||||
Ipv4_packet &ip = eth->data<Ipv4_packet>(size - sizeof(Ethernet_frame));
|
||||
size_t const ip_max_size = size - sizeof(Ethernet_frame);
|
||||
Ipv4_packet &ip = eth->data<Ipv4_packet>(ip_max_size);
|
||||
size_t const ip_size = ip.size(ip_max_size);
|
||||
if (ip.protocol() == Ipv4_packet::Protocol::UDP) {
|
||||
|
||||
if (ip.protocol() == Ipv4_packet::Protocol::UDP)
|
||||
{
|
||||
Udp_packet &udp = ip.data<Udp_packet>(size - sizeof(Ethernet_frame)
|
||||
- sizeof(Ipv4_packet));
|
||||
size_t const udp_size = ip_size - sizeof(Ipv4_packet);
|
||||
Udp_packet &udp = ip.data<Udp_packet>(udp_size);
|
||||
if (Dhcp_packet::is_dhcp(&udp)) {
|
||||
Dhcp_packet &dhcp = udp.data<Dhcp_packet>(size - sizeof(Ethernet_frame)
|
||||
- sizeof(Ipv4_packet)
|
||||
- sizeof(Udp_packet));
|
||||
|
||||
size_t const dhcp_size = udp_size - sizeof(Udp_packet);
|
||||
Dhcp_packet &dhcp = udp.data<Dhcp_packet>(dhcp_size);
|
||||
if (dhcp.op() == Dhcp_packet::REQUEST) {
|
||||
|
||||
dhcp.broadcast(true);
|
||||
udp.update_checksum(ip.src(), ip.dst());
|
||||
}
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <component.h>
|
||||
|
||||
using namespace Net;
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
bool Net::Nic::handle_arp(Ethernet_frame *eth, Genode::size_t size) {
|
||||
@ -65,19 +66,21 @@ bool Net::Nic::handle_arp(Ethernet_frame *eth, Genode::size_t size) {
|
||||
|
||||
|
||||
bool Net::Nic::handle_ip(Ethernet_frame *eth, Genode::size_t size) {
|
||||
Ipv4_packet &ip = eth->data<Ipv4_packet>(size - sizeof(Ethernet_frame));
|
||||
|
||||
size_t const ip_max_size = size - sizeof(Ethernet_frame);
|
||||
Ipv4_packet &ip = eth->data<Ipv4_packet>(ip_max_size);
|
||||
size_t const ip_size = ip.size(ip_max_size);
|
||||
|
||||
/* is it an UDP packet ? */
|
||||
if (ip.protocol() == Ipv4_packet::Protocol::UDP)
|
||||
{
|
||||
Udp_packet &udp = ip.data<Udp_packet>(size - sizeof(Ethernet_frame)
|
||||
- sizeof(Ipv4_packet));
|
||||
size_t const udp_size = ip_size - sizeof(Ipv4_packet);
|
||||
Udp_packet &udp = ip.data<Udp_packet>(udp_size);
|
||||
|
||||
/* is it a DHCP packet ? */
|
||||
if (Dhcp_packet::is_dhcp(&udp)) {
|
||||
Dhcp_packet &dhcp = udp.data<Dhcp_packet>(size - sizeof(Ethernet_frame)
|
||||
- sizeof(Ipv4_packet)
|
||||
- sizeof(Udp_packet));
|
||||
size_t const dhcp_size = udp_size - sizeof(Udp_packet);
|
||||
Dhcp_packet &dhcp = udp.data<Dhcp_packet>(dhcp_size);
|
||||
|
||||
/* check for DHCP ACKs containing new client ips */
|
||||
if (dhcp.op() == Dhcp_packet::REPLY) {
|
||||
|
@ -119,20 +119,21 @@ void Dhcp_client::handle_ip(Ethernet_frame ð, size_t eth_size)
|
||||
{
|
||||
throw Drop_packet_inform("DHCP client expects Ethernet targeting the router");
|
||||
}
|
||||
Ipv4_packet &ip = eth.data<Ipv4_packet>(eth_size - sizeof(Ethernet_frame));
|
||||
size_t const ip_max_size = eth_size - sizeof(Ethernet_frame);
|
||||
Ipv4_packet &ip = eth.data<Ipv4_packet>(ip_max_size);
|
||||
size_t const ip_size = ip.size(ip_max_size);
|
||||
|
||||
if (ip.protocol() != Ipv4_packet::Protocol::UDP) {
|
||||
throw Drop_packet_inform("DHCP client expects UDP packet");
|
||||
}
|
||||
Udp_packet &udp = ip.data<Udp_packet>(eth_size - sizeof(Ethernet_frame)
|
||||
- sizeof(Ipv4_packet));
|
||||
size_t const udp_size = ip_size - sizeof(Ipv4_packet);
|
||||
Udp_packet &udp = ip.data<Udp_packet>(udp_size);
|
||||
|
||||
if (!Dhcp_packet::is_dhcp(&udp)) {
|
||||
throw Drop_packet_inform("DHCP client expects DHCP packet");
|
||||
}
|
||||
Dhcp_packet &dhcp = udp.data<Dhcp_packet>(eth_size - sizeof(Ethernet_frame)
|
||||
- sizeof(Ipv4_packet)
|
||||
- sizeof(Udp_packet));
|
||||
size_t const dhcp_size = udp_size - sizeof(Udp_packet);
|
||||
Dhcp_packet &dhcp = udp.data<Dhcp_packet>(dhcp_size);
|
||||
|
||||
if (dhcp.op() != Dhcp_packet::REPLY) {
|
||||
throw Drop_packet_inform("DHCP client expects DHCP reply");
|
||||
|
@ -892,7 +892,9 @@ void Interface::_handle_ip(Ethernet_frame ð,
|
||||
Domain &local_domain)
|
||||
{
|
||||
/* read packet information */
|
||||
Ipv4_packet &ip = eth.data<Ipv4_packet>(eth_size - sizeof(Ethernet_frame));
|
||||
size_t const ip_max_size = eth_size - sizeof(Ethernet_frame);
|
||||
Ipv4_packet &ip = eth.data<Ipv4_packet>(ip_max_size);
|
||||
size_t const ip_size = ip.size(ip_max_size);
|
||||
Ipv4_address_prefix const &local_intf = local_domain.ip_config().interface;
|
||||
|
||||
/* try handling subnet-local IP packets */
|
||||
@ -910,18 +912,18 @@ void Interface::_handle_ip(Ethernet_frame ð,
|
||||
/* try to route via transport layer rules */
|
||||
try {
|
||||
L3_protocol const prot = ip.protocol();
|
||||
size_t const prot_size = ip.total_length() - ip.header_length() * 4;
|
||||
size_t const prot_size = ip_size - sizeof(Ipv4_packet);
|
||||
void *const prot_base = _prot_base(prot, prot_size, ip);
|
||||
|
||||
/* try handling DHCP requests before trying any routing */
|
||||
if (prot == L3_protocol::UDP) {
|
||||
Udp_packet &udp = ip.data<Udp_packet>(eth_size - sizeof(Ipv4_packet));
|
||||
Udp_packet &udp = ip.data<Udp_packet>(prot_size);
|
||||
|
||||
if (Dhcp_packet::is_dhcp(&udp)) {
|
||||
|
||||
/* get DHCP packet */
|
||||
Dhcp_packet &dhcp = udp.data<Dhcp_packet>(eth_size - sizeof(Ipv4_packet)
|
||||
- sizeof(Udp_packet));
|
||||
size_t const dhcp_size = prot_size - sizeof(Udp_packet);
|
||||
Dhcp_packet &dhcp = udp.data<Dhcp_packet>(dhcp_size);
|
||||
|
||||
if (dhcp.op() == Dhcp_packet::REQUEST) {
|
||||
try {
|
||||
|
Loading…
x
Reference in New Issue
Block a user