net: check packet data size in accessor

Instead of having a method validate_size in each packet class, check
sizes in the data accessor of the surrounding packet class. This packet
accessor is the one that casts the data pointer to the desired data type
so it is sensible that it also checks whether the desired type would
exceed the available RAM before doing the cast. This also fits nicely
the fact that for the top-level packet-class of a packet, the size must
not be checked (which was previously done).

Issue #465
This commit is contained in:
Martin Stein 2018-01-08 14:11:29 +01:00 committed by Christian Helmuth
parent 89a9e88a7e
commit f4a2d932e3
17 changed files with 116 additions and 168 deletions

View File

@ -145,18 +145,6 @@ class Net::Arp_packet
}; };
/**
* Exception used to indicate protocol violation.
*/
class No_arp_packet : Genode::Exception {};
static void validate_size(Genode::size_t size) {
/* arp packet needs to fit in */
if (size < sizeof(Arp_packet))
throw No_arp_packet();
}
/*************** /***************
** Accessors ** ** Accessors **
***************/ ***************/

View File

@ -64,10 +64,6 @@ namespace Net { class Dhcp_packet; }
*/ */
class Net::Dhcp_packet class Net::Dhcp_packet
{ {
public:
struct No_dhcp_packet : Genode::Exception { };
private: private:
Genode::uint8_t _op; Genode::uint8_t _op;
@ -104,13 +100,6 @@ class Net::Dhcp_packet
BOOTPC = 68 BOOTPC = 68
}; };
static void validate_size(Genode::size_t size) {
/* dhcp packet needs to fit in */
if (size < sizeof(Dhcp_packet))
throw No_dhcp_packet();
}
void default_magic_cookie() { void default_magic_cookie() {
_magic_cookie = host_to_big_endian(0x63825363); _magic_cookie = host_to_big_endian(0x63825363);
} }

View File

@ -61,8 +61,6 @@ class Net::Ethernet_frame
public: public:
class No_ethernet_frame : Genode::Exception {};
enum { MIN_SIZE = 64 }; enum { MIN_SIZE = 64 };
/** /**
@ -73,11 +71,22 @@ class Net::Ethernet_frame
ARP = 0x0806, ARP = 0x0806,
}; };
static void validate_size(Genode::size_t size) struct Bad_data_type : Genode::Exception { };
template <typename T> T const *data(Genode::size_t data_size) const
{ {
/* at least, frame header needs to fit in */ if (data_size < sizeof(T)) {
if (size < sizeof(Ethernet_frame)) throw Bad_data_type();
throw No_ethernet_frame(); }
return (T const *)(_data);
}
template <typename T> T *data(Genode::size_t data_size)
{
if (data_size < sizeof(T)) {
throw Bad_data_type();
}
return (T *)(_data);
} }
@ -88,8 +97,6 @@ class Net::Ethernet_frame
Mac_address dst() const { return Mac_address((void *)_dst); } Mac_address dst() const { return Mac_address((void *)_dst); }
Mac_address src() const { return Mac_address((void *)_src); } Mac_address src() const { return Mac_address((void *)_src); }
Type type() const { return (Type)host_to_big_endian(_type); } Type type() const { return (Type)host_to_big_endian(_type); }
template <typename T> T const *data() const { return (T const *)(_data); }
template <typename T> T *data() { return (T *)(_data); }
void dst(Mac_address v) { v.copy(&_dst); } void dst(Mac_address v) { v.copy(&_dst); }
void src(Mac_address v) { v.copy(&_src); } void src(Mac_address v) { v.copy(&_src); }

View File

@ -148,16 +148,22 @@ class Net::Ipv4_packet
MORE_FRAGMENTS = 0x4 MORE_FRAGMENTS = 0x4
}; };
struct Bad_data_type : Genode::Exception { };
/** template <typename T> T const *data(Genode::size_t data_size) const
* Exception used to indicate protocol violation. {
*/ if (data_size < sizeof(T)) {
class No_ip_packet : Genode::Exception {}; throw Bad_data_type();
}
return (T const *)(_data);
}
static void validate_size(Genode::size_t size) { template <typename T> T *data(Genode::size_t data_size)
/* ip header needs to fit in */ {
if (size < sizeof(Ipv4_packet)) if (data_size < sizeof(T)) {
throw No_ip_packet(); throw Bad_data_type();
}
return (T *)(_data);
} }
@ -178,8 +184,6 @@ class Net::Ipv4_packet
Genode::uint16_t checksum() const { return host_to_big_endian(_checksum); } Genode::uint16_t checksum() const { return host_to_big_endian(_checksum); }
Ipv4_address src() const { return Ipv4_address((void *)&_src); } Ipv4_address src() const { return Ipv4_address((void *)&_src); }
Ipv4_address dst() const { return Ipv4_address((void *)&_dst); } Ipv4_address dst() const { return Ipv4_address((void *)&_dst); }
template <typename T> T const * data() const { return (T const *)(_data); }
template <typename T> T * data() { return (T *)(_data); }
void header_length(Genode::size_t v) { _header_length = v; } void header_length(Genode::size_t v) { _header_length = v; }
void version(Genode::uint8_t v) { _version = v; } void version(Genode::uint8_t v) { _version = v; }

View File

@ -70,12 +70,6 @@ class Net::Tcp_packet
public: public:
class No_tcp_packet : Exception {};
static void validate_size(Genode::size_t size) {
if (size < sizeof(Tcp_packet)) { throw No_tcp_packet(); } }
/*************** /***************
** Accessors ** ** Accessors **
***************/ ***************/

View File

@ -51,15 +51,22 @@ class Net::Udp_packet
public: public:
/** struct Bad_data_type : Genode::Exception { };
* Exception used to indicate protocol violation.
*/
class No_udp_packet : Genode::Exception {};
static void validate_size(Genode::size_t size) { template <typename T> T const *data(Genode::size_t data_size) const
/* Udp header needs to fit in */ {
if (size < sizeof(Udp_packet)) if (data_size < sizeof(T)) {
throw No_udp_packet(); throw Bad_data_type();
}
return (T const *)(_data);
}
template <typename T> T *data(Genode::size_t data_size)
{
if (data_size < sizeof(T)) {
throw Bad_data_type();
}
return (T *)(_data);
} }
@ -71,8 +78,6 @@ class Net::Udp_packet
Port dst_port() const { return Port(host_to_big_endian(_dst_port)); } Port dst_port() const { return Port(host_to_big_endian(_dst_port)); }
Genode::uint16_t length() const { return host_to_big_endian(_length); } Genode::uint16_t length() const { return host_to_big_endian(_length); }
Genode::uint16_t checksum() const { return host_to_big_endian(_checksum); } Genode::uint16_t checksum() const { return host_to_big_endian(_checksum); }
template <typename T> T const * data() const { return (T const *)(_data); }
template <typename T> T * data() { return (T *)(_data); }
void length(Genode::uint16_t v) { _length = host_to_big_endian(v); } void length(Genode::uint16_t v) { _length = host_to_big_endian(v); }
void src_port(Port p) { _src_port = host_to_big_endian(p.value); } void src_port(Port p) { _src_port = host_to_big_endian(p.value); }

View File

@ -25,12 +25,10 @@ void Net::Ethernet_frame::print(Genode::Output &output) const
Genode::print(output, "\033[32mETH\033[0m ", src(), " > ", dst(), " "); Genode::print(output, "\033[32mETH\033[0m ", src(), " > ", dst(), " ");
switch (type()) { switch (type()) {
case Ethernet_frame::Type::ARP: case Ethernet_frame::Type::ARP:
Genode::print(output, Genode::print(output, *reinterpret_cast<Arp_packet const *>(_data));
*reinterpret_cast<Arp_packet const *>(data<void>()));
break; break;
case Ethernet_frame::Type::IPV4: case Ethernet_frame::Type::IPV4:
Genode::print(output, Genode::print(output, *reinterpret_cast<Ipv4_packet const *>(_data));
*reinterpret_cast<Ipv4_packet const *>(data<void>()));
break; break;
default: ; } default: ; }
} }

View File

@ -27,12 +27,10 @@ void Net::Ipv4_packet::print(Genode::Output &output) const
Genode::print(output, "\033[32mIPV4\033[0m ", src(), " > ", dst(), " "); Genode::print(output, "\033[32mIPV4\033[0m ", src(), " > ", dst(), " ");
switch (protocol()) { switch (protocol()) {
case Protocol::TCP: case Protocol::TCP:
Genode::print(output, Genode::print(output, *reinterpret_cast<Tcp_packet const *>(_data));
*reinterpret_cast<Tcp_packet const *>(data<void>()));
break; break;
case Protocol::UDP: case Protocol::UDP:
Genode::print(output, Genode::print(output, *reinterpret_cast<Udp_packet const *>(_data));
*reinterpret_cast<Udp_packet const *>(data<void>()));
break; break;
default: ; } default: ; }
} }

View File

@ -22,7 +22,6 @@ void Net::Udp_packet::print(Genode::Output &output) const
Genode::print(output, "\033[32mUDP\033[0m ", src_port(), Genode::print(output, "\033[32mUDP\033[0m ", src_port(),
" > ", dst_port(), " "); " > ", dst_port(), " ");
if (Dhcp_packet::is_dhcp(this)) { if (Dhcp_packet::is_dhcp(this)) {
Genode::print(output, Genode::print(output, *reinterpret_cast<Dhcp_packet const *>(_data));
*reinterpret_cast<Dhcp_packet const *>(data<void>()));
} }
} }

View File

@ -22,8 +22,7 @@ using namespace Net;
bool Session_component::handle_arp(Ethernet_frame *eth, Genode::size_t size) bool Session_component::handle_arp(Ethernet_frame *eth, Genode::size_t size)
{ {
Arp_packet *arp = eth->data<Arp_packet>(); Arp_packet *arp = eth->data<Arp_packet>(size - sizeof(Ethernet_frame));
Arp_packet::validate_size(size - sizeof(Ethernet_frame));
if (arp->ethernet_ipv4() && if (arp->ethernet_ipv4() &&
arp->opcode() == Arp_packet::REQUEST) { arp->opcode() == Arp_packet::REQUEST) {
@ -51,17 +50,14 @@ bool Session_component::handle_arp(Ethernet_frame *eth, Genode::size_t size)
bool Session_component::handle_ip(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>(); Ipv4_packet *ip = eth->data<Ipv4_packet>(size - sizeof(Ethernet_frame));
Ipv4_packet::validate_size(size - sizeof(Ethernet_frame));
if (ip->protocol() == Ipv4_packet::Protocol::UDP) if (ip->protocol() == Ipv4_packet::Protocol::UDP)
{ {
Udp_packet *udp = ip->data<Udp_packet>(); Udp_packet *udp = ip->data<Udp_packet>(size - sizeof(Ethernet_frame)
Udp_packet::validate_size(size - sizeof(Ethernet_frame)
- sizeof(Ipv4_packet)); - sizeof(Ipv4_packet));
if (Dhcp_packet::is_dhcp(udp)) { if (Dhcp_packet::is_dhcp(udp)) {
Dhcp_packet *dhcp = udp->data<Dhcp_packet>(); Dhcp_packet *dhcp = udp->data<Dhcp_packet>(size - sizeof(Ethernet_frame)
Dhcp_packet::validate_size(size - sizeof(Ethernet_frame)
- sizeof(Ipv4_packet) - sizeof(Ipv4_packet)
- sizeof(Udp_packet)); - sizeof(Udp_packet));
if (dhcp->op() == Dhcp_packet::REQUEST) { if (dhcp->op() == Dhcp_packet::REQUEST) {

View File

@ -24,8 +24,7 @@ using namespace Net;
bool Net::Nic::handle_arp(Ethernet_frame *eth, Genode::size_t size) { bool Net::Nic::handle_arp(Ethernet_frame *eth, Genode::size_t size) {
Arp_packet *arp = eth->data<Arp_packet>(); Arp_packet *arp = eth->data<Arp_packet>(size - sizeof(Ethernet_frame));
Arp_packet::validate_size(size - sizeof(Ethernet_frame));
/* ignore broken packets */ /* ignore broken packets */
if (!arp->ethernet_ipv4()) if (!arp->ethernet_ipv4())
@ -66,20 +65,17 @@ bool Net::Nic::handle_arp(Ethernet_frame *eth, Genode::size_t size) {
bool Net::Nic::handle_ip(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>(); Ipv4_packet *ip = eth->data<Ipv4_packet>(size - sizeof(Ethernet_frame));
Ipv4_packet::validate_size(size - sizeof(Ethernet_frame));
/* is it an UDP packet ? */ /* is it an UDP packet ? */
if (ip->protocol() == Ipv4_packet::Protocol::UDP) if (ip->protocol() == Ipv4_packet::Protocol::UDP)
{ {
Udp_packet *udp = ip->data<Udp_packet>(); Udp_packet *udp = ip->data<Udp_packet>(size - sizeof(Ethernet_frame)
Udp_packet::validate_size(size - sizeof(Ethernet_frame)
- sizeof(Ipv4_packet)); - sizeof(Ipv4_packet));
/* is it a DHCP packet ? */ /* is it a DHCP packet ? */
if (Dhcp_packet::is_dhcp(udp)) { if (Dhcp_packet::is_dhcp(udp)) {
Dhcp_packet *dhcp = udp->data<Dhcp_packet>(); Dhcp_packet *dhcp = udp->data<Dhcp_packet>(size - sizeof(Ethernet_frame)
Dhcp_packet::validate_size(size - sizeof(Ethernet_frame)
- sizeof(Ipv4_packet) - sizeof(Ipv4_packet)
- sizeof(Udp_packet)); - sizeof(Udp_packet));

View File

@ -80,7 +80,6 @@ void Packet_handler::handle_ethernet(void* src, Genode::size_t size)
try { try {
/* parse ethernet frame header */ /* parse ethernet frame header */
Ethernet_frame *eth = reinterpret_cast<Ethernet_frame *>(src); Ethernet_frame *eth = reinterpret_cast<Ethernet_frame *>(src);
Ethernet_frame::validate_size(size);
switch (eth->type()) { switch (eth->type()) {
case Ethernet_frame::Type::ARP: case Ethernet_frame::Type::ARP:
if (!handle_arp(eth, size)) return; if (!handle_arp(eth, size)) return;
@ -94,15 +93,11 @@ void Packet_handler::handle_ethernet(void* src, Genode::size_t size)
broadcast_to_clients(eth, size); broadcast_to_clients(eth, size);
finalize_packet(eth, size); finalize_packet(eth, size);
} catch(Arp_packet::No_arp_packet) { } catch(Ethernet_frame::Bad_data_type) {
Genode::warning("Invalid ARP packet!"); Genode::warning("Invalid Ethernet frame!");
} catch(Ethernet_frame::No_ethernet_frame) { } catch(Ipv4_packet::Bad_data_type) {
Genode::warning("Invalid ethernet frame");
} catch(Dhcp_packet::No_dhcp_packet) {
Genode::warning("Invalid IPv4 packet!"); Genode::warning("Invalid IPv4 packet!");
} catch(Ipv4_packet::No_ip_packet) { } catch(Udp_packet::Bad_data_type) {
Genode::warning("Invalid IPv4 packet!");
} catch(Udp_packet::No_udp_packet) {
Genode::warning("Invalid UDP packet!"); Genode::warning("Invalid UDP packet!");
} }
} }

View File

@ -28,7 +28,6 @@ void Net::Interface::_handle_eth(void *const eth_base,
{ {
try { try {
Ethernet_frame &eth = *reinterpret_cast<Ethernet_frame *>(eth_base); Ethernet_frame &eth = *reinterpret_cast<Ethernet_frame *>(eth_base);
Ethernet_frame::validate_size(eth_size);
Interface &remote = _remote.deref(); Interface &remote = _remote.deref();
Packet_log_config log_cfg; Packet_log_config log_cfg;
@ -47,9 +46,6 @@ void Net::Interface::_handle_eth(void *const eth_base,
} }
remote._send(eth, eth_size); remote._send(eth, eth_size);
} }
catch (Ethernet_frame::No_ethernet_frame) {
error("invalid ethernet frame"); }
catch (Pointer<Interface>::Invalid) { catch (Pointer<Interface>::Invalid) {
error("no remote interface set"); } error("no remote interface set"); }
} }

View File

@ -157,12 +157,12 @@ void Packet_log<Ethernet_frame>::print(Output &output) const
switch (_pkt.type()) { switch (_pkt.type()) {
case Ethernet_frame::Type::ARP: case Ethernet_frame::Type::ARP:
print(output, " ", packet_log(*_pkt.data<Arp_packet const>(), _cfg)); print(output, " ", packet_log(*_pkt.data<Arp_packet const>(~0UL), _cfg));
break; break;
case Ethernet_frame::Type::IPV4: case Ethernet_frame::Type::IPV4:
print(output, " ", packet_log(*_pkt.data<Ipv4_packet const>(), _cfg)); print(output, " ", packet_log(*_pkt.data<Ipv4_packet const>(~0UL), _cfg));
break; break;
default: ; default: ;
@ -212,12 +212,12 @@ void Packet_log<Ipv4_packet>::print(Output &output) const
switch (_pkt.protocol()) { switch (_pkt.protocol()) {
case Ipv4_packet::Protocol::TCP: case Ipv4_packet::Protocol::TCP:
print(output, " ", packet_log(*_pkt.data<Tcp_packet const>(), _cfg)); print(output, " ", packet_log(*_pkt.data<Tcp_packet const>(~0UL), _cfg));
break; break;
case Ipv4_packet::Protocol::UDP: case Ipv4_packet::Protocol::UDP:
print(output, " ", packet_log(*_pkt.data<Udp_packet const>(), _cfg)); print(output, " ", packet_log(*_pkt.data<Udp_packet const>(~0UL), _cfg));
break; break;
default: ; } default: ; }
@ -292,6 +292,6 @@ void Packet_log<Udp_packet>::print(Output &output) const
} }
/* print encapsulated packet */ /* print encapsulated packet */
if (Dhcp_packet::is_dhcp(&_pkt)) { if (Dhcp_packet::is_dhcp(&_pkt)) {
print(output, " ", packet_log(*_pkt.data<Dhcp_packet const>(), _cfg)); print(output, " ", packet_log(*_pkt.data<Dhcp_packet const>(~0UL), _cfg));
} }
} }

View File

@ -93,21 +93,18 @@ void Dhcp_client::handle_ip(Ethernet_frame &eth, size_t eth_size)
{ {
throw Drop_packet_inform("DHCP client expects Ethernet targeting the router"); throw Drop_packet_inform("DHCP client expects Ethernet targeting the router");
} }
Ipv4_packet &ip = *eth.data<Ipv4_packet>(); Ipv4_packet &ip = *eth.data<Ipv4_packet>(eth_size - sizeof(Ethernet_frame));
Ipv4_packet::validate_size(eth_size - sizeof(Ethernet_frame));
if (ip.protocol() != Ipv4_packet::Protocol::UDP) { if (ip.protocol() != Ipv4_packet::Protocol::UDP) {
throw Drop_packet_inform("DHCP client expects UDP packet"); throw Drop_packet_inform("DHCP client expects UDP packet");
} }
Udp_packet &udp = *ip.data<Udp_packet>(); Udp_packet &udp = *ip.data<Udp_packet>(eth_size - sizeof(Ethernet_frame)
Udp_packet::validate_size(eth_size - sizeof(Ethernet_frame)
- sizeof(Ipv4_packet)); - sizeof(Ipv4_packet));
if (!Dhcp_packet::is_dhcp(&udp)) { if (!Dhcp_packet::is_dhcp(&udp)) {
throw Drop_packet_inform("DHCP client expects DHCP packet"); throw Drop_packet_inform("DHCP client expects DHCP packet");
} }
Dhcp_packet &dhcp = *udp.data<Dhcp_packet>(); Dhcp_packet &dhcp = *udp.data<Dhcp_packet>(eth_size - sizeof(Ethernet_frame)
Dhcp_packet::validate_size(eth_size - sizeof(Ethernet_frame)
- sizeof(Ipv4_packet) - sizeof(Ipv4_packet)
- sizeof(Udp_packet)); - sizeof(Udp_packet));
@ -187,8 +184,8 @@ void Dhcp_client::_send(Message_type msg_type,
/* create IP header of the request */ /* create IP header of the request */
enum { IPV4_TIME_TO_LIVE = 64 }; enum { IPV4_TIME_TO_LIVE = 64 };
size_t const ip_off = size.curr(); size_t const ip_off = size.curr();
Ipv4_packet &ip = *eth.data<Ipv4_packet>(size.left());
size.add(sizeof(Ipv4_packet)); size.add(sizeof(Ipv4_packet));
Ipv4_packet &ip = *eth.data<Ipv4_packet>();
ip.header_length(sizeof(Ipv4_packet) / 4); ip.header_length(sizeof(Ipv4_packet) / 4);
ip.version(4); ip.version(4);
ip.diff_service(0); ip.diff_service(0);
@ -202,15 +199,15 @@ void Dhcp_client::_send(Message_type msg_type,
/* create UDP header of the request */ /* create UDP header of the request */
size_t const udp_off = size.curr(); size_t const udp_off = size.curr();
Udp_packet &udp = *ip.data<Udp_packet>(size.left());
size.add(sizeof(Udp_packet)); size.add(sizeof(Udp_packet));
Udp_packet &udp = *ip.data<Udp_packet>();
udp.src_port(Port(Dhcp_packet::BOOTPC)); udp.src_port(Port(Dhcp_packet::BOOTPC));
udp.dst_port(Port(Dhcp_packet::BOOTPS)); udp.dst_port(Port(Dhcp_packet::BOOTPS));
/* create mandatory DHCP fields of the request */ /* create mandatory DHCP fields of the request */
size_t const dhcp_off = size.curr(); size_t const dhcp_off = size.curr();
Dhcp_packet &dhcp = *udp.data<Dhcp_packet>(size.left());
size.add(sizeof(Dhcp_packet)); size.add(sizeof(Dhcp_packet));
Dhcp_packet &dhcp = *udp.data<Dhcp_packet>();
dhcp.op(Dhcp_packet::REQUEST); dhcp.op(Dhcp_packet::REQUEST);
dhcp.htype(Dhcp_packet::Htype::ETH); dhcp.htype(Dhcp_packet::Htype::ETH);
dhcp.hlen(sizeof(Mac_address)); dhcp.hlen(sizeof(Mac_address));

View File

@ -143,12 +143,8 @@ static void *_prot_base(L3_protocol const prot,
Ipv4_packet &ip) Ipv4_packet &ip)
{ {
switch (prot) { switch (prot) {
case L3_protocol::TCP: case L3_protocol::TCP: return ip.data<Tcp_packet>(prot_size);
Tcp_packet::validate_size(prot_size); case L3_protocol::UDP: return ip.data<Udp_packet>(prot_size);
return ip.data<Tcp_packet>();
case L3_protocol::UDP:
Udp_packet::validate_size(prot_size);
return ip.data<Udp_packet>();
default: throw Interface::Bad_transport_protocol(); } default: throw Interface::Bad_transport_protocol(); }
} }
@ -315,8 +311,8 @@ void Interface::_send_dhcp_reply(Dhcp_server const &dhcp_srv,
/* create IP header of the reply */ /* create IP header of the reply */
enum { IPV4_TIME_TO_LIVE = 64 }; enum { IPV4_TIME_TO_LIVE = 64 };
size_t const ip_off = size.curr(); size_t const ip_off = size.curr();
Ipv4_packet &ip = *eth.data<Ipv4_packet>(size.left());
size.add(sizeof(Ipv4_packet)); size.add(sizeof(Ipv4_packet));
Ipv4_packet &ip = *eth.data<Ipv4_packet>();
ip.header_length(sizeof(Ipv4_packet) / 4); ip.header_length(sizeof(Ipv4_packet) / 4);
ip.version(4); ip.version(4);
ip.diff_service(0); ip.diff_service(0);
@ -330,14 +326,14 @@ void Interface::_send_dhcp_reply(Dhcp_server const &dhcp_srv,
/* create UDP header of the reply */ /* create UDP header of the reply */
size_t const udp_off = size.curr(); size_t const udp_off = size.curr();
Udp_packet &udp = *ip.data<Udp_packet>(size.left());
size.add(sizeof(Udp_packet)); size.add(sizeof(Udp_packet));
Udp_packet &udp = *ip.data<Udp_packet>();
udp.src_port(Port(Dhcp_packet::BOOTPS)); udp.src_port(Port(Dhcp_packet::BOOTPS));
udp.dst_port(Port(Dhcp_packet::BOOTPC)); udp.dst_port(Port(Dhcp_packet::BOOTPC));
/* create mandatory DHCP fields of the reply */ /* create mandatory DHCP fields of the reply */
Dhcp_packet &dhcp = *udp.data<Dhcp_packet>(size.left());
size.add(sizeof(Dhcp_packet)); size.add(sizeof(Dhcp_packet));
Dhcp_packet &dhcp = *udp.data<Dhcp_packet>();
dhcp.op(Dhcp_packet::REPLY); dhcp.op(Dhcp_packet::REPLY);
dhcp.htype(Dhcp_packet::Htype::ETH); dhcp.htype(Dhcp_packet::Htype::ETH);
dhcp.hlen(sizeof(Mac_address)); dhcp.hlen(sizeof(Mac_address));
@ -538,8 +534,7 @@ void Interface::_handle_ip(Ethernet_frame &eth,
Packet_descriptor const &pkt) Packet_descriptor const &pkt)
{ {
/* read packet information */ /* read packet information */
Ipv4_packet &ip = *eth.data<Ipv4_packet>(); Ipv4_packet &ip = *eth.data<Ipv4_packet>(eth_size - sizeof(Ethernet_frame));
Ipv4_packet::validate_size(eth_size - sizeof(Ethernet_frame));
/* try handling subnet-local IP packets */ /* try handling subnet-local IP packets */
if (_ip_config().interface.prefix_matches(ip.dst()) && if (_ip_config().interface.prefix_matches(ip.dst()) &&
@ -561,16 +556,12 @@ void Interface::_handle_ip(Ethernet_frame &eth,
/* try handling DHCP requests before trying any routing */ /* try handling DHCP requests before trying any routing */
if (prot == L3_protocol::UDP) { if (prot == L3_protocol::UDP) {
Udp_packet &udp = *ip.data<Udp_packet>(); Udp_packet &udp = *ip.data<Udp_packet>(eth_size - sizeof(Ipv4_packet));
Udp_packet::validate_size(eth_size - sizeof(Ethernet_frame)
- sizeof(Ipv4_packet));
if (Dhcp_packet::is_dhcp(&udp)) { if (Dhcp_packet::is_dhcp(&udp)) {
/* get DHCP packet */ /* get DHCP packet */
Dhcp_packet &dhcp = *udp.data<Dhcp_packet>(); Dhcp_packet &dhcp = *udp.data<Dhcp_packet>(eth_size - sizeof(Ipv4_packet)
Dhcp_packet::validate_size(eth_size - sizeof(Ethernet_frame)
- sizeof(Ipv4_packet)
- sizeof(Udp_packet)); - sizeof(Udp_packet));
if (dhcp.op() == Dhcp_packet::REQUEST) { if (dhcp.op() == Dhcp_packet::REQUEST) {
@ -696,7 +687,7 @@ void Interface::_broadcast_arp_request(Ipv4_address const &ip)
eth.type(Ethernet_frame::Type::ARP); eth.type(Ethernet_frame::Type::ARP);
/* write ARP header */ /* write ARP header */
Arp_packet &arp = *eth.data<Arp_packet>(); Arp_packet &arp = *eth.data<Arp_packet>(PKT_SIZE - sizeof(Ethernet_frame));
arp.hardware_address_type(Arp_packet::ETHERNET); arp.hardware_address_type(Arp_packet::ETHERNET);
arp.protocol_address_type(Arp_packet::IPV4); arp.protocol_address_type(Arp_packet::IPV4);
arp.hardware_address_size(sizeof(Mac_address)); arp.hardware_address_size(sizeof(Mac_address));
@ -817,9 +808,7 @@ void Interface::_handle_arp_request(Ethernet_frame &eth,
void Interface::_handle_arp(Ethernet_frame &eth, size_t const eth_size) void Interface::_handle_arp(Ethernet_frame &eth, size_t const eth_size)
{ {
/* ignore ARP regarding protocols other than IPv4 via ethernet */ /* ignore ARP regarding protocols other than IPv4 via ethernet */
size_t const arp_size = eth_size - sizeof(Ethernet_frame); Arp_packet &arp = *eth.data<Arp_packet>(eth_size - sizeof(Ethernet_frame));
Arp_packet &arp = *eth.data<Arp_packet>();
Arp_packet::validate_size(arp_size);
if (!arp.ethernet_ipv4()) { if (!arp.ethernet_ipv4()) {
error("ARP for unknown protocol"); } error("ARP for unknown protocol"); }
@ -890,7 +879,6 @@ void Interface::_handle_eth(void *const eth_base,
/* inspect and handle ethernet frame */ /* inspect and handle ethernet frame */
try { try {
Ethernet_frame *const eth = reinterpret_cast<Ethernet_frame *>(eth_base); Ethernet_frame *const eth = reinterpret_cast<Ethernet_frame *>(eth_base);
Ethernet_frame::validate_size(eth_size);
if (_config().verbose()) { if (_config().verbose()) {
log("(router <- ", _domain, ") ", *eth); } log("(router <- ", _domain, ") ", *eth); }
@ -908,12 +896,9 @@ void Interface::_handle_eth(void *const eth_base,
default: throw Bad_network_protocol(); } default: throw Bad_network_protocol(); }
} }
} }
catch (Ethernet_frame::No_ethernet_frame) { warning("malformed Ethernet frame"); } catch (Ethernet_frame::Bad_data_type) { warning("malformed Ethernet frame"); }
catch (Ipv4_packet::No_ip_packet) { warning("malformed IPv4 packet" ); } catch (Ipv4_packet::Bad_data_type) { warning("malformed IPv4 packet" ); }
catch (Tcp_packet::No_tcp_packet) { warning("malformed TCP packet" ); } catch (Udp_packet::Bad_data_type) { warning("malformed UDP packet" ); }
catch (Udp_packet::No_udp_packet) { warning("malformed UDP packet" ); }
catch (Dhcp_packet::No_dhcp_packet) { warning("malformed DHCP packet" ); }
catch (Arp_packet::No_arp_packet) { warning("malformed ARP packet" ); }
catch (Bad_network_protocol) { catch (Bad_network_protocol) {
if (_config().verbose()) { if (_config().verbose()) {

View File

@ -40,6 +40,7 @@ class Genode::Size_guard_tpl
} }
size_t curr() const { return _curr; } size_t curr() const { return _curr; }
size_t left() const { return MAX - _curr; }
}; };
#endif /* _SIZE_GUARD_H_ */ #endif /* _SIZE_GUARD_H_ */