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:
Martin Stein 2017-12-05 14:43:02 +01:00 committed by Christian Helmuth
parent b32f2d126a
commit 70c5c31ec9
4 changed files with 53 additions and 38 deletions

View File

@ -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);

View File

@ -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 &eth, 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");
} }
} }

View File

@ -273,7 +273,7 @@ void Interface::_adapt_eth(Ethernet_frame &eth,
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 &eth,
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 &eth,
_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 &eth,
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"); }

View File

@ -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,