mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-24 15:56:41 +00:00
nic_router: fix lifetime of DHCP clients
Let the DHCP client be a constructible member of Interface that is constructed only as long as the interface is attached to a domain with a dynamic IP config. This prevents DHCP client timeouts from a period with dynamic IP config to trigger after a reconfiguration to a static IP config. Furthermore, handle DHCP-reply packets at an interface only when the DHCP client its constructed. Otherwise drop such packets. Ref #3681
This commit is contained in:
parent
6d48b5484d
commit
0a468a07a7
@ -224,6 +224,7 @@ class Net::Domain : public Domain_base,
|
||||
Domain_link_stats &icmp_stats() { return _icmp_stats; }
|
||||
Domain_object_stats &arp_stats() { return _arp_stats; }
|
||||
Domain_object_stats &dhcp_stats() { return _dhcp_stats; }
|
||||
bool ip_config_dynamic() const { return _ip_config_dynamic; };
|
||||
};
|
||||
|
||||
#endif /* _DOMAIN_H_ */
|
||||
|
@ -343,9 +343,15 @@ void Interface::_detach_from_domain_raw()
|
||||
void Interface::attach_to_domain()
|
||||
{
|
||||
try {
|
||||
_attach_to_domain_raw(_config().domains().find_by_name(
|
||||
_policy.determine_domain_name()));
|
||||
Domain &domain =
|
||||
_config().domains().find_by_name(_policy.determine_domain_name());
|
||||
|
||||
_attach_to_domain_raw(domain);
|
||||
|
||||
/* construct DHCP client if the new domain needs it */
|
||||
if (domain.ip_config_dynamic()) {
|
||||
_dhcp_client.construct(_alloc, _timer, *this);
|
||||
}
|
||||
attach_to_domain_finish();
|
||||
}
|
||||
catch (Domain_tree::No_match) { }
|
||||
@ -361,7 +367,7 @@ void Interface::attach_to_domain_finish()
|
||||
Domain &domain = _domain();
|
||||
Ipv4_config const &ip_config = domain.ip_config();
|
||||
if (!ip_config.valid) {
|
||||
_dhcp_client.discover();
|
||||
_dhcp_client->discover();
|
||||
return;
|
||||
}
|
||||
attach_to_ip_config(domain, ip_config);
|
||||
@ -1101,7 +1107,10 @@ void Interface::_handle_ip(Ethernet_frame ð,
|
||||
}
|
||||
catch (Pointer<Dhcp_server>::Invalid) { }
|
||||
} else {
|
||||
_dhcp_client.handle_ip(eth, size_guard);
|
||||
if (!_dhcp_client.constructed()) {
|
||||
throw Drop_packet("DHCP client not active");
|
||||
}
|
||||
_dhcp_client->handle_ip(eth, size_guard);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1466,7 +1475,12 @@ void Interface::_handle_eth(Ethernet_frame ð,
|
||||
} else {
|
||||
|
||||
switch (eth.type()) {
|
||||
case Ethernet_frame::Type::IPV4: _dhcp_client.handle_ip(eth, size_guard); break;
|
||||
case Ethernet_frame::Type::IPV4:
|
||||
if (!_dhcp_client.constructed()) {
|
||||
throw Drop_packet("DHCP client not active");
|
||||
}
|
||||
_dhcp_client->handle_ip(eth, size_guard);
|
||||
break;
|
||||
default: throw Bad_network_protocol(); }
|
||||
}
|
||||
}
|
||||
@ -1912,18 +1926,41 @@ void Interface::handle_config_2()
|
||||
{
|
||||
Domain_name const &new_domain_name = _policy.determine_domain_name();
|
||||
try {
|
||||
/* if the domains differ, detach completely from the domain */
|
||||
Domain &old_domain = domain();
|
||||
try {
|
||||
Domain &new_domain = _config().domains().find_by_name(new_domain_name);
|
||||
|
||||
/* if the domains differ, detach completely from the domain */
|
||||
if (old_domain.name() != new_domain_name) {
|
||||
|
||||
_detach_from_domain();
|
||||
_attach_to_domain_raw(new_domain);
|
||||
|
||||
/* destruct and construct DHCP client if required */
|
||||
if (old_domain.ip_config_dynamic()) {
|
||||
_dhcp_client.destruct();
|
||||
}
|
||||
if (new_domain.ip_config_dynamic()) {
|
||||
_dhcp_client.construct(_alloc, _timer, *this);
|
||||
}
|
||||
return;
|
||||
}
|
||||
/* move to new domain object without considering any state objects */
|
||||
_detach_from_domain_raw();
|
||||
_attach_to_domain_raw(new_domain);
|
||||
|
||||
/* destruct or construct DHCP client if IP-config type changes */
|
||||
if (old_domain.ip_config_dynamic() &&
|
||||
!new_domain.ip_config_dynamic())
|
||||
{
|
||||
_dhcp_client.destruct();
|
||||
}
|
||||
if (!old_domain.ip_config_dynamic() &&
|
||||
new_domain.ip_config_dynamic())
|
||||
{
|
||||
_dhcp_client.construct(_alloc, _timer, *this);
|
||||
}
|
||||
|
||||
/* remember that the interface stays attached to the same domain */
|
||||
_update_domain.construct(old_domain, new_domain);
|
||||
return;
|
||||
@ -1932,11 +1969,25 @@ void Interface::handle_config_2()
|
||||
|
||||
/* the interface no longer has a domain */
|
||||
_detach_from_domain();
|
||||
|
||||
/* destruct DHCP client if it was constructed */
|
||||
if (old_domain.ip_config_dynamic()) {
|
||||
_dhcp_client.destruct();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Pointer<Domain>::Invalid) {
|
||||
|
||||
/* the interface had no domain but now it may get one */
|
||||
try { _attach_to_domain_raw(_config().domains().find_by_name(new_domain_name)); }
|
||||
try {
|
||||
Domain &new_domain = _config().domains().find_by_name(new_domain_name);
|
||||
_attach_to_domain_raw(new_domain);
|
||||
|
||||
/* construct DHCP client if the new domain needs it */
|
||||
if (new_domain.ip_config_dynamic()) {
|
||||
_dhcp_client.construct(_alloc, _timer, *this);
|
||||
}
|
||||
}
|
||||
catch (Domain_tree::No_match) { }
|
||||
}
|
||||
}
|
||||
|
@ -151,7 +151,7 @@ class Net::Interface : private Interface_list::Element
|
||||
Link_list _dissolved_icmp_links { };
|
||||
Dhcp_allocation_tree _dhcp_allocations { };
|
||||
Dhcp_allocation_list _released_dhcp_allocations { };
|
||||
Dhcp_client _dhcp_client { _alloc, _timer, *this };
|
||||
Genode::Constructible<Dhcp_client> _dhcp_client { };
|
||||
Interface_list &_interfaces;
|
||||
Genode::Constructible<Update_domain> _update_domain { };
|
||||
Interface_link_stats _udp_stats { };
|
||||
|
Loading…
Reference in New Issue
Block a user