mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-12 07:52:44 +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_link_stats &icmp_stats() { return _icmp_stats; }
|
||||||
Domain_object_stats &arp_stats() { return _arp_stats; }
|
Domain_object_stats &arp_stats() { return _arp_stats; }
|
||||||
Domain_object_stats &dhcp_stats() { return _dhcp_stats; }
|
Domain_object_stats &dhcp_stats() { return _dhcp_stats; }
|
||||||
|
bool ip_config_dynamic() const { return _ip_config_dynamic; };
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* _DOMAIN_H_ */
|
#endif /* _DOMAIN_H_ */
|
||||||
|
@ -343,9 +343,15 @@ void Interface::_detach_from_domain_raw()
|
|||||||
void Interface::attach_to_domain()
|
void Interface::attach_to_domain()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
_attach_to_domain_raw(_config().domains().find_by_name(
|
Domain &domain =
|
||||||
_policy.determine_domain_name()));
|
_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();
|
attach_to_domain_finish();
|
||||||
}
|
}
|
||||||
catch (Domain_tree::No_match) { }
|
catch (Domain_tree::No_match) { }
|
||||||
@ -361,7 +367,7 @@ void Interface::attach_to_domain_finish()
|
|||||||
Domain &domain = _domain();
|
Domain &domain = _domain();
|
||||||
Ipv4_config const &ip_config = domain.ip_config();
|
Ipv4_config const &ip_config = domain.ip_config();
|
||||||
if (!ip_config.valid) {
|
if (!ip_config.valid) {
|
||||||
_dhcp_client.discover();
|
_dhcp_client->discover();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
attach_to_ip_config(domain, ip_config);
|
attach_to_ip_config(domain, ip_config);
|
||||||
@ -1101,7 +1107,10 @@ void Interface::_handle_ip(Ethernet_frame ð,
|
|||||||
}
|
}
|
||||||
catch (Pointer<Dhcp_server>::Invalid) { }
|
catch (Pointer<Dhcp_server>::Invalid) { }
|
||||||
} else {
|
} 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;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1466,7 +1475,12 @@ void Interface::_handle_eth(Ethernet_frame ð,
|
|||||||
} else {
|
} else {
|
||||||
|
|
||||||
switch (eth.type()) {
|
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(); }
|
default: throw Bad_network_protocol(); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1912,31 +1926,68 @@ void Interface::handle_config_2()
|
|||||||
{
|
{
|
||||||
Domain_name const &new_domain_name = _policy.determine_domain_name();
|
Domain_name const &new_domain_name = _policy.determine_domain_name();
|
||||||
try {
|
try {
|
||||||
/* if the domains differ, detach completely from the domain */
|
|
||||||
Domain &old_domain = domain();
|
Domain &old_domain = domain();
|
||||||
Domain &new_domain = _config().domains().find_by_name(new_domain_name);
|
try {
|
||||||
if (old_domain.name() != new_domain_name) {
|
Domain &new_domain = _config().domains().find_by_name(new_domain_name);
|
||||||
_detach_from_domain();
|
|
||||||
|
/* 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);
|
_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;
|
return;
|
||||||
}
|
}
|
||||||
/* move to new domain object without considering any state objects */
|
catch (Domain_tree::No_match) {
|
||||||
_detach_from_domain_raw();
|
|
||||||
_attach_to_domain_raw(new_domain);
|
|
||||||
|
|
||||||
/* remember that the interface stays attached to the same domain */
|
/* the interface no longer has a domain */
|
||||||
_update_domain.construct(old_domain, new_domain);
|
_detach_from_domain();
|
||||||
return;
|
|
||||||
}
|
|
||||||
catch (Domain_tree::No_match) {
|
|
||||||
|
|
||||||
/* the interface no longer has a domain */
|
/* destruct DHCP client if it was constructed */
|
||||||
_detach_from_domain();
|
if (old_domain.ip_config_dynamic()) {
|
||||||
|
_dhcp_client.destruct();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Pointer<Domain>::Invalid) {
|
catch (Pointer<Domain>::Invalid) {
|
||||||
|
|
||||||
/* the interface had no domain but now it may get one */
|
/* 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) { }
|
catch (Domain_tree::No_match) { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -151,7 +151,7 @@ class Net::Interface : private Interface_list::Element
|
|||||||
Link_list _dissolved_icmp_links { };
|
Link_list _dissolved_icmp_links { };
|
||||||
Dhcp_allocation_tree _dhcp_allocations { };
|
Dhcp_allocation_tree _dhcp_allocations { };
|
||||||
Dhcp_allocation_list _released_dhcp_allocations { };
|
Dhcp_allocation_list _released_dhcp_allocations { };
|
||||||
Dhcp_client _dhcp_client { _alloc, _timer, *this };
|
Genode::Constructible<Dhcp_client> _dhcp_client { };
|
||||||
Interface_list &_interfaces;
|
Interface_list &_interfaces;
|
||||||
Genode::Constructible<Update_domain> _update_domain { };
|
Genode::Constructible<Update_domain> _update_domain { };
|
||||||
Interface_link_stats _udp_stats { };
|
Interface_link_stats _udp_stats { };
|
||||||
|
Loading…
Reference in New Issue
Block a user