mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-22 10:21:04 +00:00
nic_router: better warnings on bad DHCP requests
Be more descriptive about why the NIC router thinks that a DHCP request sent to him is bad. Issue #2534
This commit is contained in:
parent
b32f2d126a
commit
70c5c31ec9
@ -67,7 +67,6 @@ class Net::Dhcp_packet
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
struct No_dhcp_packet : Genode::Exception { };
|
struct No_dhcp_packet : Genode::Exception { };
|
||||||
struct Option_not_found : Genode::Exception { };
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@ -178,6 +177,12 @@ class Net::Dhcp_packet
|
|||||||
|
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct Option_not_found : Genode::Exception
|
||||||
|
{
|
||||||
|
Option::Code const code;
|
||||||
|
|
||||||
|
Option_not_found(Option::Code code) : code(code) { }
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DHCP option that contains a payload of type T
|
* DHCP option that contains a payload of type T
|
||||||
@ -373,7 +378,7 @@ class Net::Dhcp_packet
|
|||||||
if (opt.code() == Option::Code::INVALID ||
|
if (opt.code() == Option::Code::INVALID ||
|
||||||
opt.code() == Option::Code::END)
|
opt.code() == Option::Code::END)
|
||||||
{
|
{
|
||||||
throw Option_not_found();
|
throw Option_not_found(T::CODE);
|
||||||
}
|
}
|
||||||
if (opt.code() == T::CODE) {
|
if (opt.code() == T::CODE) {
|
||||||
return *reinterpret_cast<T *>(ptr);
|
return *reinterpret_cast<T *>(ptr);
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
using namespace Genode;
|
using namespace Genode;
|
||||||
using namespace Net;
|
using namespace Net;
|
||||||
using Message_type = Dhcp_packet::Message_type;
|
using Message_type = Dhcp_packet::Message_type;
|
||||||
using Packet_ignored = Interface::Packet_ignored;
|
using Drop_packet_inform = Interface::Drop_packet_inform;
|
||||||
|
|
||||||
|
|
||||||
Configuration &Dhcp_client::_config() { return _domain().config(); };
|
Configuration &Dhcp_client::_config() { return _domain().config(); };
|
||||||
@ -91,32 +91,32 @@ void Dhcp_client::handle_ip(Ethernet_frame ð, size_t eth_size)
|
|||||||
if (eth.dst() != _interface.router_mac() &&
|
if (eth.dst() != _interface.router_mac() &&
|
||||||
eth.dst() != Mac_address(0xff))
|
eth.dst() != Mac_address(0xff))
|
||||||
{
|
{
|
||||||
throw Packet_ignored("DHCP client expects Ethernet targeting the router");
|
throw Drop_packet_inform("DHCP client expects Ethernet targeting the router");
|
||||||
}
|
}
|
||||||
Ipv4_packet &ip = *new (eth.data<void>())
|
Ipv4_packet &ip = *new (eth.data<void>())
|
||||||
Ipv4_packet(eth_size - sizeof(Ethernet_frame));
|
Ipv4_packet(eth_size - sizeof(Ethernet_frame));
|
||||||
|
|
||||||
if (ip.protocol() != Ipv4_packet::Protocol::UDP) {
|
if (ip.protocol() != Ipv4_packet::Protocol::UDP) {
|
||||||
throw Packet_ignored("DHCP client expects UDP packet");
|
throw Drop_packet_inform("DHCP client expects UDP packet");
|
||||||
}
|
}
|
||||||
Udp_packet &udp = *new (ip.data<void>())
|
Udp_packet &udp = *new (ip.data<void>())
|
||||||
Udp_packet(eth_size - sizeof(Ipv4_packet));
|
Udp_packet(eth_size - sizeof(Ipv4_packet));
|
||||||
|
|
||||||
if (!Dhcp_packet::is_dhcp(&udp)) {
|
if (!Dhcp_packet::is_dhcp(&udp)) {
|
||||||
throw Packet_ignored("DHCP client expects DHCP packet");
|
throw Drop_packet_inform("DHCP client expects DHCP packet");
|
||||||
}
|
}
|
||||||
Dhcp_packet &dhcp = *new (udp.data<void>())
|
Dhcp_packet &dhcp = *new (udp.data<void>())
|
||||||
Dhcp_packet(eth_size - sizeof(Ipv4_packet) - sizeof(Udp_packet));
|
Dhcp_packet(eth_size - sizeof(Ipv4_packet) - sizeof(Udp_packet));
|
||||||
|
|
||||||
if (dhcp.op() != Dhcp_packet::REPLY) {
|
if (dhcp.op() != Dhcp_packet::REPLY) {
|
||||||
throw Packet_ignored("DHCP client expects DHCP reply");
|
throw Drop_packet_inform("DHCP client expects DHCP reply");
|
||||||
}
|
}
|
||||||
if (dhcp.client_mac() != _interface.router_mac()) {
|
if (dhcp.client_mac() != _interface.router_mac()) {
|
||||||
throw Packet_ignored("DHCP client expects DHCP targeting the router");
|
throw Drop_packet_inform("DHCP client expects DHCP targeting the router");
|
||||||
}
|
}
|
||||||
try { _handle_dhcp_reply(dhcp); }
|
try { _handle_dhcp_reply(dhcp); }
|
||||||
catch (Dhcp_packet::Option_not_found) {
|
catch (Dhcp_packet::Option_not_found) {
|
||||||
throw Packet_ignored("DHCP client misses DHCP option");
|
throw Drop_packet_inform("DHCP client misses DHCP option");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,7 +130,7 @@ void Dhcp_client::_handle_dhcp_reply(Dhcp_packet &dhcp)
|
|||||||
case State::SELECT:
|
case State::SELECT:
|
||||||
|
|
||||||
if (msg_type != Message_type::OFFER) {
|
if (msg_type != Message_type::OFFER) {
|
||||||
throw Packet_ignored("DHCP client expects an offer");
|
throw Drop_packet_inform("DHCP client expects an offer");
|
||||||
}
|
}
|
||||||
_set_state(State::REQUEST, _config().dhcp_request_timeout());
|
_set_state(State::REQUEST, _config().dhcp_request_timeout());
|
||||||
_send(Message_type::REQUEST, dhcp.yiaddr(),
|
_send(Message_type::REQUEST, dhcp.yiaddr(),
|
||||||
@ -140,7 +140,7 @@ void Dhcp_client::_handle_dhcp_reply(Dhcp_packet &dhcp)
|
|||||||
case State::REQUEST:
|
case State::REQUEST:
|
||||||
|
|
||||||
if (msg_type != Message_type::ACK) {
|
if (msg_type != Message_type::ACK) {
|
||||||
throw Packet_ignored("DHCP client expects an acknowledgement");
|
throw Drop_packet_inform("DHCP client expects an acknowledgement");
|
||||||
}
|
}
|
||||||
_lease_time_sec = dhcp.option<Dhcp_packet::Ip_lease_time>().value();
|
_lease_time_sec = dhcp.option<Dhcp_packet::Ip_lease_time>().value();
|
||||||
_set_state(State::BOUND, _rerequest_timeout(1));
|
_set_state(State::BOUND, _rerequest_timeout(1));
|
||||||
@ -153,13 +153,13 @@ void Dhcp_client::_handle_dhcp_reply(Dhcp_packet &dhcp)
|
|||||||
case State::REBIND:
|
case State::REBIND:
|
||||||
|
|
||||||
if (msg_type != Message_type::ACK) {
|
if (msg_type != Message_type::ACK) {
|
||||||
throw Packet_ignored("DHCP client expects an acknowledgement");
|
throw Drop_packet_inform("DHCP client expects an acknowledgement");
|
||||||
}
|
}
|
||||||
_set_state(State::BOUND, _rerequest_timeout(1));
|
_set_state(State::BOUND, _rerequest_timeout(1));
|
||||||
_lease_time_sec = dhcp.option<Dhcp_packet::Ip_lease_time>().value();
|
_lease_time_sec = dhcp.option<Dhcp_packet::Ip_lease_time>().value();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: throw Packet_ignored("DHCP client doesn't expect a packet");
|
default: throw Drop_packet_inform("DHCP client doesn't expect a packet");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -273,7 +273,7 @@ void Interface::_adapt_eth(Ethernet_frame ð,
|
|||||||
Interface &interface)
|
Interface &interface)
|
||||||
{
|
{
|
||||||
if (!interface.domain().ip_config().valid) {
|
if (!interface.domain().ip_config().valid) {
|
||||||
throw Packet_ignored("target domain has yet no IP config");
|
throw Drop_packet_inform("target domain has yet no IP config");
|
||||||
}
|
}
|
||||||
Ipv4_address const &hop_ip = interface._domain.next_hop(ip);
|
Ipv4_address const &hop_ip = interface._domain.next_hop(ip);
|
||||||
try { eth.dst(interface._arp_cache.find_by_ip(hop_ip).mac()); }
|
try { eth.dst(interface._arp_cache.find_by_ip(hop_ip).mac()); }
|
||||||
@ -430,7 +430,7 @@ void Interface::_handle_dhcp_request(Ethernet_frame ð,
|
|||||||
case Dhcp_packet::Message_type::DISCOVER:
|
case Dhcp_packet::Message_type::DISCOVER:
|
||||||
|
|
||||||
if (allocation.bound()) {
|
if (allocation.bound()) {
|
||||||
throw Bad_dhcp_request();
|
throw Drop_packet_warn("DHCP DISCOVER from client expected to be in DHCP BOUND state");
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
allocation.lifetime(_config().dhcp_offer_timeout());
|
allocation.lifetime(_config().dhcp_offer_timeout());
|
||||||
@ -490,10 +490,10 @@ void Interface::_handle_dhcp_request(Ethernet_frame ð,
|
|||||||
_destroy_dhcp_allocation(allocation);
|
_destroy_dhcp_allocation(allocation);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case Dhcp_packet::Message_type::NAK:
|
case Dhcp_packet::Message_type::NAK: throw Drop_packet_warn("DHCP NAK from client");
|
||||||
case Dhcp_packet::Message_type::OFFER:
|
case Dhcp_packet::Message_type::OFFER: throw Drop_packet_warn("DHCP OFFER from client");
|
||||||
case Dhcp_packet::Message_type::ACK:
|
case Dhcp_packet::Message_type::ACK: throw Drop_packet_warn("DHCP ACK from client");
|
||||||
default: throw Bad_dhcp_request();
|
default: throw Drop_packet_warn("DHCP request with broken message type");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Dhcp_allocation_tree::No_match) {
|
catch (Dhcp_allocation_tree::No_match) {
|
||||||
@ -517,18 +517,20 @@ void Interface::_handle_dhcp_request(Ethernet_frame ð,
|
|||||||
dhcp.xid());
|
dhcp.xid());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case Dhcp_packet::Message_type::REQUEST:
|
case Dhcp_packet::Message_type::REQUEST: throw Drop_packet_warn("DHCP REQUEST from client without offered/acked IP");
|
||||||
case Dhcp_packet::Message_type::DECLINE:
|
case Dhcp_packet::Message_type::DECLINE: throw Drop_packet_warn("DHCP DECLINE from client without offered/acked IP");
|
||||||
case Dhcp_packet::Message_type::RELEASE:
|
case Dhcp_packet::Message_type::RELEASE: throw Drop_packet_warn("DHCP RELEASE from client without offered/acked IP");
|
||||||
case Dhcp_packet::Message_type::NAK:
|
case Dhcp_packet::Message_type::NAK: throw Drop_packet_warn("DHCP NAK from client");
|
||||||
case Dhcp_packet::Message_type::OFFER:
|
case Dhcp_packet::Message_type::OFFER: throw Drop_packet_warn("DHCP OFFER from client");
|
||||||
case Dhcp_packet::Message_type::ACK:
|
case Dhcp_packet::Message_type::ACK: throw Drop_packet_warn("DHCP ACK from client");
|
||||||
default: throw Bad_dhcp_request();
|
default: throw Drop_packet_warn("DHCP request with broken message type");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Dhcp_packet::Option_not_found) {
|
catch (Dhcp_packet::Option_not_found exception) {
|
||||||
throw Bad_dhcp_request();
|
|
||||||
|
throw Drop_packet_warn("DHCP request misses required option ",
|
||||||
|
(unsigned long)exception.code);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -844,11 +846,14 @@ void Interface::_handle_eth(void *const eth_base,
|
|||||||
log("unknown network layer protocol");
|
log("unknown network layer protocol");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Packet_ignored exception) {
|
catch (Drop_packet_inform exception) {
|
||||||
if (_config().verbose()) {
|
if (_config().verbose()) {
|
||||||
log("Packet ignored: ", exception.reason);
|
log("(", _domain, ") Drop packet: ", exception.msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (Drop_packet_warn exception) {
|
||||||
|
warning("(", _domain, ") Drop packet: ", exception.msg);
|
||||||
|
}
|
||||||
catch (Ipv4_packet::No_ip_packet) {
|
catch (Ipv4_packet::No_ip_packet) {
|
||||||
error("invalid IP packet"); }
|
error("invalid IP packet"); }
|
||||||
|
|
||||||
@ -861,9 +866,6 @@ void Interface::_handle_eth(void *const eth_base,
|
|||||||
catch (Pointer<Interface>::Invalid) {
|
catch (Pointer<Interface>::Invalid) {
|
||||||
error("no interface connected to domain"); }
|
error("no interface connected to domain"); }
|
||||||
|
|
||||||
catch (Bad_dhcp_request) {
|
|
||||||
error("bad DHCP request"); }
|
|
||||||
|
|
||||||
catch (Alloc_dhcp_msg_buffer_failed) {
|
catch (Alloc_dhcp_msg_buffer_failed) {
|
||||||
error("failed to allocate buffer for DHCP reply"); }
|
error("failed to allocate buffer for DHCP reply"); }
|
||||||
|
|
||||||
|
@ -180,15 +180,23 @@ class Net::Interface
|
|||||||
struct Bad_transport_protocol : Genode::Exception { };
|
struct Bad_transport_protocol : Genode::Exception { };
|
||||||
struct Bad_network_protocol : Genode::Exception { };
|
struct Bad_network_protocol : Genode::Exception { };
|
||||||
struct Packet_postponed : Genode::Exception { };
|
struct Packet_postponed : Genode::Exception { };
|
||||||
struct Bad_dhcp_request : Genode::Exception { };
|
|
||||||
struct Alloc_dhcp_msg_buffer_failed : Genode::Exception { };
|
struct Alloc_dhcp_msg_buffer_failed : Genode::Exception { };
|
||||||
struct Dhcp_msg_buffer_too_small : Genode::Exception { };
|
struct Dhcp_msg_buffer_too_small : Genode::Exception { };
|
||||||
|
|
||||||
struct Packet_ignored : Genode::Exception
|
struct Drop_packet_inform : Genode::Exception
|
||||||
{
|
{
|
||||||
char const *reason;
|
Genode::String<128> msg;
|
||||||
|
|
||||||
Packet_ignored(char const *reason) : reason(reason) { }
|
template <typename... ARGS>
|
||||||
|
Drop_packet_inform(ARGS... args) : msg({args...}) { }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Drop_packet_warn : Genode::Exception
|
||||||
|
{
|
||||||
|
Genode::String<128> msg;
|
||||||
|
|
||||||
|
template <typename... ARGS>
|
||||||
|
Drop_packet_warn(ARGS... args) : msg({args...}) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
Interface(Genode::Entrypoint &ep,
|
Interface(Genode::Entrypoint &ep,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user