nic_router: DHCP server considers dns_server_from

The dns_server_from attribute of the dhcp-server tag has effect only if
the dns_server attribute of the same tag 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.

Issue #2730
This commit is contained in:
Martin Stein 2018-03-22 22:53:32 +01:00 committed by Christian Helmuth
parent fec53690d7
commit 4bee38ea62
6 changed files with 88 additions and 17 deletions

View File

@ -292,18 +292,26 @@ this:
<dhcp-server ip_first="10.0.1.80"
ip_last="10.0.1.100"
ip_lease_time_sec="3600"
dns_server="10.0.0.2"/>
dns_server="10.0.0.2"
dns_server_from="uplink" />
...
</domain>
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 <config> 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 <config> tag of the router:
! <config dhcp_offer_timeout_sec="6">

View File

@ -131,6 +131,7 @@
<xs:attribute name="ip_last" type="Ipv4_address" />
<xs:attribute name="ip_lease_time_sec" type="Seconds" />
<xs:attribute name="dns_server" type="Ipv4_address" />
<xs:attribute name="dns_server_from" type="Domain_name" />
</xs:complexType>
</xs:element><!-- dhcp-server -->

View File

@ -14,6 +14,7 @@
/* local includes */
#include <dhcp_server.h>
#include <interface.h>
#include <domain.h>
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<Domain>::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<Domain> Dhcp_server::_init_dns_server_from(Genode::Xml_node const node,
Domain_tree &domains)
{
if (_dns_server.valid()) {
return Pointer<Domain>();
}
Domain_name dns_server_from =
node.attribute_value("dns_server_from", Domain_name());
if (dns_server_from == Domain_name()) {
return Pointer<Domain>();
}
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<Domain>::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<Domain>::Invalid) { }
return true;
}
/*********************
** Dhcp_allocation **
*********************/

View File

@ -18,6 +18,7 @@
#include <ipv4_address_prefix.h>
#include <bit_allocator_dynamic.h>
#include <list.h>
#include <pointer.h>
/* Genode includes */
#include <net/mac_address.h>
@ -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<Domain> 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<Domain> _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; }
};

View File

@ -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<Dhcp_server>::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()); }

View File

@ -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; }