diff --git a/repos/os/include/net/ipv4.h b/repos/os/include/net/ipv4.h index 0bfbccfb03..dc61a79645 100644 --- a/repos/os/include/net/ipv4.h +++ b/repos/os/include/net/ipv4.h @@ -151,6 +151,8 @@ class Net::Ipv4_packet return *Genode::construct_at(_data); } + Genode::size_t size(Genode::size_t max_size) const; + /*************** ** Accessors ** diff --git a/repos/os/src/app/ping/main.cc b/repos/os/src/app/ping/main.cc index e06a50c354..5b6194364a 100644 --- a/repos/os/src/app/ping/main.cc +++ b/repos/os/src/app/ping/main.cc @@ -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(ip_size); + size_t const ip_max_size = eth_size - sizeof(Ethernet_frame); + Ipv4_packet &ip = eth.data(ip_max_size); + size_t const ip_size = ip.size(ip_max_size); if (ip.dst() != _src_ip && ip.dst() != Ipv4_packet::broadcast()) { diff --git a/repos/os/src/lib/net/ipv4.cc b/repos/os/src/lib/net/ipv4.cc index 9d0fc432bd..34615641a9 100644 --- a/repos/os/src/lib/net/ipv4.cc +++ b/repos/os/src/lib/net/ipv4.cc @@ -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; +} diff --git a/repos/os/src/server/nic_bridge/component.cc b/repos/os/src/server/nic_bridge/component.cc index f637d030f4..e3df0be11f 100644 --- a/repos/os/src/server/nic_bridge/component.cc +++ b/repos/os/src/server/nic_bridge/component.cc @@ -19,6 +19,8 @@ #include 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(size - sizeof(Ethernet_frame)); + size_t const ip_max_size = size - sizeof(Ethernet_frame); + Ipv4_packet &ip = eth->data(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(size - sizeof(Ethernet_frame) - - sizeof(Ipv4_packet)); + size_t const udp_size = ip_size - sizeof(Ipv4_packet); + Udp_packet &udp = ip.data(udp_size); if (Dhcp_packet::is_dhcp(&udp)) { - Dhcp_packet &dhcp = udp.data(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_size); if (dhcp.op() == Dhcp_packet::REQUEST) { + dhcp.broadcast(true); udp.update_checksum(ip.src(), ip.dst()); } diff --git a/repos/os/src/server/nic_bridge/nic.cc b/repos/os/src/server/nic_bridge/nic.cc index d5e8528a3c..c5e5a1762e 100644 --- a/repos/os/src/server/nic_bridge/nic.cc +++ b/repos/os/src/server/nic_bridge/nic.cc @@ -21,6 +21,7 @@ #include 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(size - sizeof(Ethernet_frame)); + + size_t const ip_max_size = size - sizeof(Ethernet_frame); + Ipv4_packet &ip = eth->data(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(size - sizeof(Ethernet_frame) - - sizeof(Ipv4_packet)); + size_t const udp_size = ip_size - sizeof(Ipv4_packet); + Udp_packet &udp = ip.data(udp_size); /* is it a DHCP packet ? */ if (Dhcp_packet::is_dhcp(&udp)) { - Dhcp_packet &dhcp = udp.data(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_size); /* check for DHCP ACKs containing new client ips */ if (dhcp.op() == Dhcp_packet::REPLY) { diff --git a/repos/os/src/server/nic_router/dhcp_client.cc b/repos/os/src/server/nic_router/dhcp_client.cc index 4926ad0d83..6ddf3a6fa6 100644 --- a/repos/os/src/server/nic_router/dhcp_client.cc +++ b/repos/os/src/server/nic_router/dhcp_client.cc @@ -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(eth_size - sizeof(Ethernet_frame)); + size_t const ip_max_size = eth_size - sizeof(Ethernet_frame); + Ipv4_packet &ip = eth.data(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(eth_size - sizeof(Ethernet_frame) - - sizeof(Ipv4_packet)); + size_t const udp_size = ip_size - sizeof(Ipv4_packet); + Udp_packet &udp = ip.data(udp_size); if (!Dhcp_packet::is_dhcp(&udp)) { throw Drop_packet_inform("DHCP client expects DHCP packet"); } - Dhcp_packet &dhcp = udp.data(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_size); if (dhcp.op() != Dhcp_packet::REPLY) { throw Drop_packet_inform("DHCP client expects DHCP reply"); diff --git a/repos/os/src/server/nic_router/interface.cc b/repos/os/src/server/nic_router/interface.cc index b4ad0d848c..a65be0c75a 100644 --- a/repos/os/src/server/nic_router/interface.cc +++ b/repos/os/src/server/nic_router/interface.cc @@ -892,7 +892,9 @@ void Interface::_handle_ip(Ethernet_frame ð, Domain &local_domain) { /* read packet information */ - Ipv4_packet &ip = eth.data(eth_size - sizeof(Ethernet_frame)); + size_t const ip_max_size = eth_size - sizeof(Ethernet_frame); + Ipv4_packet &ip = eth.data(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(eth_size - sizeof(Ipv4_packet)); + Udp_packet &udp = ip.data(prot_size); if (Dhcp_packet::is_dhcp(&udp)) { /* get DHCP packet */ - Dhcp_packet &dhcp = udp.data(eth_size - sizeof(Ipv4_packet) - - sizeof(Udp_packet)); + size_t const dhcp_size = prot_size - sizeof(Udp_packet); + Dhcp_packet &dhcp = udp.data(dhcp_size); if (dhcp.op() == Dhcp_packet::REQUEST) { try {