nic_router: inform clients on DNS server change

If the remote DNS server address value of a DHCP server changes, the affected
interfaces do a link down/up to inform all DHCP clients that they should
re-request their DHCP info.

Issue #2730
This commit is contained in:
Martin Stein 2018-03-23 02:43:00 +01:00 committed by Christian Helmuth
parent 4bee38ea62
commit e213b9046d
5 changed files with 42 additions and 20 deletions

View File

@ -92,6 +92,7 @@ class Net::Dhcp_server : private Genode::Noncopyable
***************/
Ipv4_address const &dns_server() const;
Domain &dns_server_from() { return _dns_server_from(); }
Genode::Microseconds ip_lease_time() const { return _ip_lease_time; }
};

View File

@ -146,6 +146,11 @@ void Domain::_ip_config_changed()
_interfaces.for_each([&] (Interface &interface) {
interface.detach_from_ip_config();
});
_ip_config_dependents.for_each([&] (Domain &domain) {
domain._interfaces.for_each([&] (Interface &interface) {
interface.detach_from_remote_ip_config();
});
});
/* log the change */
if (_config.verbose_domain_state()) {
if (!ip_config().valid) {
@ -206,10 +211,14 @@ void Domain::init(Domain_tree &domains)
log("[", *this, "] cannot be DHCP server and client at the same time");
throw Invalid();
}
_dhcp_server = *new (_alloc)
Dhcp_server &dhcp_server = *new (_alloc)
Dhcp_server(dhcp_server_node, _alloc, ip_config().interface,
domains);
try { dhcp_server.dns_server_from().ip_config_dependents().insert(this); }
catch (Pointer<Domain>::Invalid) { }
_dhcp_server = dhcp_server;
if (_config.verbose()) {
log("[", *this, "] DHCP server: ", _dhcp_server()); }
}

View File

@ -78,7 +78,8 @@ class Net::Domain_base
};
class Net::Domain : public Domain_base
class Net::Domain : public Domain_base,
public List<Domain>::Element
{
private:
@ -86,25 +87,26 @@ class Net::Domain : public Domain_base
Configuration &_config;
Genode::Xml_node _node;
Genode::Allocator &_alloc;
Ip_rule_list _ip_rules { };
Forward_rule_tree _tcp_forward_rules { };
Forward_rule_tree _udp_forward_rules { };
Transport_rule_list _tcp_rules { };
Transport_rule_list _udp_rules { };
Port_allocator _tcp_port_alloc { };
Port_allocator _udp_port_alloc { };
Nat_rule_tree _nat_rules { };
Interface_list _interfaces { };
unsigned long _interface_cnt { 0 };
Pointer<Dhcp_server> _dhcp_server { };
Ip_rule_list _ip_rules { };
Forward_rule_tree _tcp_forward_rules { };
Forward_rule_tree _udp_forward_rules { };
Transport_rule_list _tcp_rules { };
Transport_rule_list _udp_rules { };
Port_allocator _tcp_port_alloc { };
Port_allocator _udp_port_alloc { };
Nat_rule_tree _nat_rules { };
Interface_list _interfaces { };
unsigned long _interface_cnt { 0 };
Pointer<Dhcp_server> _dhcp_server { };
Genode::Reconstructible<Ipv4_config> _ip_config;
Arp_cache _arp_cache { *this };
Arp_waiter_list _foreign_arp_waiters { };
Link_side_tree _tcp_links { };
Link_side_tree _udp_links { };
Genode::size_t _tx_bytes { 0 };
Genode::size_t _rx_bytes { 0 };
bool const _verbose_packets { false };
List<Domain> _ip_config_dependents { };
Arp_cache _arp_cache { *this };
Arp_waiter_list _foreign_arp_waiters { };
Link_side_tree _tcp_links { };
Link_side_tree _udp_links { };
Genode::size_t _tx_bytes { 0 };
Genode::size_t _rx_bytes { 0 };
bool const _verbose_packets { false };
void _read_forward_rules(Genode::Cstring const &protocol,
Domain_tree &domains,
@ -170,6 +172,7 @@ class Net::Domain : public Domain_base
bool verbose_packets() const { return _verbose_packets; }
Ipv4_config const &ip_config() const { return *_ip_config; }
List<Domain> &ip_config_dependents() { return _ip_config_dependents; }
Domain_name const &name() const { return _name; }
Ip_rule_list &ip_rules() { return _ip_rules; }
Forward_rule_tree &tcp_forward_rules() { return _tcp_forward_rules; }

View File

@ -309,6 +309,13 @@ void Interface::detach_from_ip_config()
}
void Interface::detach_from_remote_ip_config()
{
/* only the DNS server address of the local DHCP server can be remote */
Signal_transmitter(_link_state_sigh).submit();
}
void Interface::_detach_from_domain()
{
try {

View File

@ -318,6 +318,8 @@ class Net::Interface : private Interface_list::Element
void detach_from_ip_config();
void detach_from_remote_ip_config();
bool link_state();
void link_state_sigh(Genode::Signal_context_capability sigh);