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:
struct No_dhcp_packet : Genode::Exception { };
struct Option_not_found : Genode::Exception { };
private:
@ -178,6 +177,12 @@ class Net::Dhcp_packet
} __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
@ -373,7 +378,7 @@ class Net::Dhcp_packet
if (opt.code() == Option::Code::INVALID ||
opt.code() == Option::Code::END)
{
throw Option_not_found();
throw Option_not_found(T::CODE);
}
if (opt.code() == T::CODE) {
return *reinterpret_cast<T *>(ptr);

View File

@ -20,8 +20,8 @@
using namespace Genode;
using namespace Net;
using Message_type = Dhcp_packet::Message_type;
using Packet_ignored = Interface::Packet_ignored;
using Message_type = Dhcp_packet::Message_type;
using Drop_packet_inform = Interface::Drop_packet_inform;
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() &&
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(eth_size - sizeof(Ethernet_frame));
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(eth_size - sizeof(Ipv4_packet));
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(eth_size - sizeof(Ipv4_packet) - sizeof(Udp_packet));
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()) {
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); }
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:
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());
_send(Message_type::REQUEST, dhcp.yiaddr(),
@ -140,7 +140,7 @@ void Dhcp_client::_handle_dhcp_reply(Dhcp_packet &dhcp)
case State::REQUEST:
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();
_set_state(State::BOUND, _rerequest_timeout(1));
@ -153,13 +153,13 @@ void Dhcp_client::_handle_dhcp_reply(Dhcp_packet &dhcp)
case State::REBIND:
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));
_lease_time_sec = dhcp.option<Dhcp_packet::Ip_lease_time>().value();
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)
{
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);
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:
if (allocation.bound()) {
throw Bad_dhcp_request();
throw Drop_packet_warn("DHCP DISCOVER from client expected to be in DHCP BOUND state");
} else {
allocation.lifetime(_config().dhcp_offer_timeout());
@ -490,10 +490,10 @@ void Interface::_handle_dhcp_request(Ethernet_frame &eth,
_destroy_dhcp_allocation(allocation);
return;
case Dhcp_packet::Message_type::NAK:
case Dhcp_packet::Message_type::OFFER:
case Dhcp_packet::Message_type::ACK:
default: throw Bad_dhcp_request();
case Dhcp_packet::Message_type::NAK: throw Drop_packet_warn("DHCP NAK from client");
case Dhcp_packet::Message_type::OFFER: throw Drop_packet_warn("DHCP OFFER from client");
case Dhcp_packet::Message_type::ACK: throw Drop_packet_warn("DHCP ACK from client");
default: throw Drop_packet_warn("DHCP request with broken message type");
}
}
catch (Dhcp_allocation_tree::No_match) {
@ -517,18 +517,20 @@ void Interface::_handle_dhcp_request(Ethernet_frame &eth,
dhcp.xid());
return;
}
case Dhcp_packet::Message_type::REQUEST:
case Dhcp_packet::Message_type::DECLINE:
case Dhcp_packet::Message_type::RELEASE:
case Dhcp_packet::Message_type::NAK:
case Dhcp_packet::Message_type::OFFER:
case Dhcp_packet::Message_type::ACK:
default: throw Bad_dhcp_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: throw Drop_packet_warn("DHCP DECLINE from client without offered/acked IP");
case Dhcp_packet::Message_type::RELEASE: throw Drop_packet_warn("DHCP RELEASE from client without offered/acked IP");
case Dhcp_packet::Message_type::NAK: throw Drop_packet_warn("DHCP NAK from client");
case Dhcp_packet::Message_type::OFFER: throw Drop_packet_warn("DHCP OFFER from client");
case Dhcp_packet::Message_type::ACK: throw Drop_packet_warn("DHCP ACK from client");
default: throw Drop_packet_warn("DHCP request with broken message type");
}
}
}
catch (Dhcp_packet::Option_not_found) {
throw Bad_dhcp_request();
catch (Dhcp_packet::Option_not_found exception) {
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");
}
}
catch (Packet_ignored exception) {
catch (Drop_packet_inform exception) {
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) {
error("invalid IP packet"); }
@ -861,9 +866,6 @@ void Interface::_handle_eth(void *const eth_base,
catch (Pointer<Interface>::Invalid) {
error("no interface connected to domain"); }
catch (Bad_dhcp_request) {
error("bad DHCP request"); }
catch (Alloc_dhcp_msg_buffer_failed) {
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_network_protocol : Genode::Exception { };
struct Packet_postponed : Genode::Exception { };
struct Bad_dhcp_request : Genode::Exception { };
struct Alloc_dhcp_msg_buffer_failed : 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,