diff --git a/repos/os/src/server/nic_router/README b/repos/os/src/server/nic_router/README index 1f317f77d8..4f937fc42e 100644 --- a/repos/os/src/server/nic_router/README +++ b/repos/os/src/server/nic_router/README @@ -292,18 +292,26 @@ this: + dns_server="10.0.0.2" + dns_server_from="uplink" /> ... -The attributes ip_first and ip_last define the available IPv4 address -range while ip_lease_time_sec defines the lifetime of an IPv4 address -assignment in seconds. The IPv4 address range must be in the subnet -defined by the interface attribute of the domain tag and must not cover -the IPv4 address in this attribute. The dns_server attribute gives the -IPv4 address of the DNS server that might also be in another subnet. -The lifetime of an assignment that was yet only offered to the client -can be configured for all domains in the tag of the router: +The attributes ip_first and ip_last define the available IPv4 address range +while ip_lease_time_sec defines the lifetime of an IPv4 address assignment in +seconds. The IPv4 address range must be in the subnet defined by the interface +attribute of the domain tag and must not cover the IPv4 address in this +attribute. The dns_server attribute gives the IPv4 address of the DNS server +that might also be in another subnet. The dns_server_from attribute has effect +only if the dns_server attribute is not set. If this is the case, the +dns_server_from attribute states the domain from whose IP config to take the +DNS server address. This is useful, for instance, if the stated domain +receives the address of a local DNS server via DHCP. Whenever the IP config +of the stated domain becomes invalid, the DHCP server switches to a mode where +it drops all requests unanswered until the IP config becomes valid again. + +The lifetime of an assignment that was yet only offered to the client can be +configured for all domains in the tag of the router: ! diff --git a/repos/os/src/server/nic_router/config.xsd b/repos/os/src/server/nic_router/config.xsd index 3f731025a7..caef35ac67 100644 --- a/repos/os/src/server/nic_router/config.xsd +++ b/repos/os/src/server/nic_router/config.xsd @@ -131,6 +131,7 @@ + diff --git a/repos/os/src/server/nic_router/dhcp_server.cc b/repos/os/src/server/nic_router/dhcp_server.cc index ed1bc1a169..25787a42b2 100644 --- a/repos/os/src/server/nic_router/dhcp_server.cc +++ b/repos/os/src/server/nic_router/dhcp_server.cc @@ -14,6 +14,7 @@ /* local includes */ #include #include +#include using namespace Net; using namespace Genode; @@ -25,10 +26,12 @@ using namespace Genode; Dhcp_server::Dhcp_server(Xml_node const node, Allocator &alloc, - Ipv4_address_prefix const &interface) + Ipv4_address_prefix const &interface, + Domain_tree &domains) : _dns_server(node.attribute_value("dns_server", Ipv4_address())), - _ip_lease_time(_init_ip_lease_time(node)), + _dns_server_from(_init_dns_server_from(node, domains)), + _ip_lease_time (_init_ip_lease_time(node)), _ip_first(node.attribute_value("ip_first", Ipv4_address())), _ip_last(node.attribute_value("ip_last", Ipv4_address())), _ip_first_raw(_ip_first.to_uint32_little_endian()), @@ -59,8 +62,11 @@ Microseconds Dhcp_server::_init_ip_lease_time(Xml_node const node) void Dhcp_server::print(Output &output) const { if (_dns_server.valid()) { - Genode::print(output, "DNS server ", _dns_server, " "); + Genode::print(output, "DNS server ", _dns_server, ", "); } + try { Genode::print(output, "DNS server from ", _dns_server_from(), ", "); } + catch (Pointer::Invalid) { } + Genode::print(output, "IP first ", _ip_first, ", last ", _ip_last, ", count ", _ip_count, @@ -94,6 +100,42 @@ void Dhcp_server::free_ip(Ipv4_address const &ip) } +Pointer Dhcp_server::_init_dns_server_from(Genode::Xml_node const node, + Domain_tree &domains) +{ + if (_dns_server.valid()) { + return Pointer(); + } + Domain_name dns_server_from = + node.attribute_value("dns_server_from", Domain_name()); + + if (dns_server_from == Domain_name()) { + return Pointer(); + } + try { return domains.find_by_name(dns_server_from); } + catch (Domain_tree::No_match) { throw Invalid(); } +} + + +Ipv4_address const &Dhcp_server::dns_server() const +{ + try { return _dns_server_from().ip_config().dns_server; } + catch (Pointer::Invalid) { } + return _dns_server; +} + + +bool Dhcp_server::ready() const +{ + if (_dns_server.valid()) { + return true; + } + try { return _dns_server_from().ip_config().valid; } + catch (Pointer::Invalid) { } + return true; +} + + /********************* ** Dhcp_allocation ** *********************/ diff --git a/repos/os/src/server/nic_router/dhcp_server.h b/repos/os/src/server/nic_router/dhcp_server.h index 08835da314..6da911cfed 100644 --- a/repos/os/src/server/nic_router/dhcp_server.h +++ b/repos/os/src/server/nic_router/dhcp_server.h @@ -18,6 +18,7 @@ #include #include #include +#include /* Genode includes */ #include @@ -35,6 +36,8 @@ namespace Net { /* forward declarations */ class Interface; + class Domain; + class Domain_tree; } @@ -43,6 +46,7 @@ class Net::Dhcp_server : private Genode::Noncopyable private: Ipv4_address const _dns_server; + Pointer const _dns_server_from; Genode::Microseconds const _ip_lease_time; Ipv4_address const _ip_first; Ipv4_address const _ip_last; @@ -52,6 +56,9 @@ class Net::Dhcp_server : private Genode::Noncopyable Genode::Microseconds _init_ip_lease_time(Genode::Xml_node const node); + Pointer _init_dns_server_from(Genode::Xml_node const node, + Domain_tree &domains); + public: enum { DEFAULT_IP_LEASE_TIME_SEC = 3600 }; @@ -61,7 +68,8 @@ class Net::Dhcp_server : private Genode::Noncopyable Dhcp_server(Genode::Xml_node const node, Genode::Allocator &alloc, - Ipv4_address_prefix const &interface); + Ipv4_address_prefix const &interface, + Domain_tree &domains); Ipv4_address alloc_ip(); @@ -69,6 +77,8 @@ class Net::Dhcp_server : private Genode::Noncopyable void free_ip(Ipv4_address const &ip); + bool ready() const; + /********* ** log ** @@ -81,7 +91,7 @@ class Net::Dhcp_server : private Genode::Noncopyable ** Accessors ** ***************/ - Ipv4_address const &dns_server() const { return _dns_server; } + Ipv4_address const &dns_server() const; Genode::Microseconds ip_lease_time() const { return _ip_lease_time; } }; diff --git a/repos/os/src/server/nic_router/domain.cc b/repos/os/src/server/nic_router/domain.cc index c0c0fc40d0..95c2f2a79c 100644 --- a/repos/os/src/server/nic_router/domain.cc +++ b/repos/os/src/server/nic_router/domain.cc @@ -128,7 +128,6 @@ Domain::Domain(Configuration &config, Xml_node const node, Allocator &alloc) if (_config.verbose_domain_state()) { log("[", *this, "] NIC sessions: ", _interface_cnt); } - _ip_config_changed(); } @@ -188,6 +187,16 @@ void Domain::__FIXME__dissolve_foreign_arp_waiters() } +Dhcp_server &Domain::dhcp_server() +{ + Dhcp_server &dhcp_server = _dhcp_server(); + if (!dhcp_server.ready()) { + throw Pointer::Invalid(); + } + return dhcp_server; +} + + void Domain::init(Domain_tree &domains) { /* read DHCP server configuration */ @@ -198,7 +207,8 @@ void Domain::init(Domain_tree &domains) throw Invalid(); } _dhcp_server = *new (_alloc) - Dhcp_server(dhcp_server_node, _alloc, ip_config().interface); + Dhcp_server(dhcp_server_node, _alloc, ip_config().interface, + domains); if (_config.verbose()) { log("[", *this, "] DHCP server: ", _dhcp_server()); } diff --git a/repos/os/src/server/nic_router/domain.h b/repos/os/src/server/nic_router/domain.h index 47d4129e9b..29f063ba8f 100644 --- a/repos/os/src/server/nic_router/domain.h +++ b/repos/os/src/server/nic_router/domain.h @@ -180,7 +180,7 @@ class Net::Domain : public Domain_base Interface_list &interfaces() { return _interfaces; } Configuration &config() const { return _config; } Domain_avl_member &avl_member() { return _avl_member; } - Dhcp_server &dhcp_server() { return _dhcp_server(); } + Dhcp_server &dhcp_server(); Arp_cache &arp_cache() { return _arp_cache; } Arp_waiter_list &foreign_arp_waiters() { return _foreign_arp_waiters; } Link_side_tree &tcp_links() { return _tcp_links; }