mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-18 02:40:08 +00:00
nic_router: propagate dns domain name via dhcp
With this commit, the NIC router DHCP client reads out the first DNS domain name (DHCP option 15) if any from a DHCP reply that generates an IPv4 config for a domain and stores the name together with the IPv4 config for that domain. DNS domain names are reported via the new report tag '<dns-domain>' if the 'config' attribute in the config tag '<report>' is set. Furthermore, the NIC router DHCP server becomes able to obtain a DNS domain name from another domain that has a DHCP client dynamically (given the config attribute 'dns_config_from' is set and no static DNS config is given) or statically from its configuration (new config tag '<dns-domain>') and propagate this name with DHCP replies (DHCP option 15). The 'nic_router_dhcp_*' tests are adapted to test the new feautures. The commit also gets rid of some mirrored files in 'test/nic_router_dhcp/manager'. Fixes #4246
This commit is contained in:
parent
fa64aae7f8
commit
812fdec27c
@ -127,6 +127,7 @@ class Net::Dhcp_packet
|
||||
SUBNET_MASK = 1,
|
||||
ROUTER = 3,
|
||||
DNS_SERVER = 6,
|
||||
DOMAIN_NAME = 15,
|
||||
BROADCAST_ADDR = 28,
|
||||
REQ_IP_ADDR = 50,
|
||||
IP_LEASE_TIME = 51,
|
||||
@ -227,6 +228,28 @@ class Net::Dhcp_packet
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Domain name option
|
||||
*/
|
||||
class Domain_name : public Option
|
||||
{
|
||||
private:
|
||||
|
||||
char _name[0];
|
||||
|
||||
public:
|
||||
|
||||
static constexpr Code CODE = Code::DOMAIN_NAME;
|
||||
|
||||
Domain_name (Genode::size_t len) : Option(CODE, len) { }
|
||||
|
||||
template <typename FUNC>
|
||||
void with_string(FUNC && func) const
|
||||
{
|
||||
func(_name, Option::len());
|
||||
}
|
||||
};
|
||||
|
||||
enum class Message_type : Genode::uint8_t {
|
||||
DISCOVER = 1,
|
||||
OFFER = 2,
|
||||
@ -442,6 +465,16 @@ class Net::Dhcp_packet
|
||||
|
||||
_base += header_size + data.size();
|
||||
}
|
||||
|
||||
void append_domain_name(char const *data_src,
|
||||
Genode::size_t data_size)
|
||||
{
|
||||
Genode::size_t const header_size { sizeof(Domain_name) };
|
||||
_size_guard.consume_head(header_size + data_size);
|
||||
Genode::memcpy((char *)(_base + header_size), data_src, data_size);
|
||||
Genode::construct_at<Domain_name>((void *)_base, data_size);
|
||||
_base += header_size + data_size;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
@ -63,6 +63,7 @@ append config {
|
||||
<dns-server ip="1.2.3.4"/>
|
||||
<dns-server ip="2.3.4.5"/>
|
||||
<dns-server ip="3.4.5.6"/>
|
||||
<dns-domain name="genode.org"/>
|
||||
|
||||
</dhcp-server>
|
||||
|
||||
@ -96,7 +97,7 @@ append config {
|
||||
<sleep milliseconds="2000"/>
|
||||
<inline>
|
||||
|
||||
<config>
|
||||
<config verbose="yes">
|
||||
|
||||
<policy label="nic_router_2 -> " domain="downlink"/>
|
||||
|
||||
@ -106,6 +107,7 @@ append config {
|
||||
ip_last="10.2.4.2">
|
||||
|
||||
<dns-server ip="6.7.8.9"/>
|
||||
<dns-domain name="this_is_a_way_to_long_dns_domain_name_that_should_be_rejected_by_the_router_and_cause_the_corresponding_dhcp_option_to_disappear_but_you_never_know_and_so_we_better_test_it"/>
|
||||
|
||||
</dhcp-server>
|
||||
|
||||
@ -126,6 +128,8 @@ append config {
|
||||
<dhcp-server ip_first="10.2.4.200"
|
||||
ip_last="10.2.4.200">
|
||||
|
||||
<dns-domain name="genodians.org"/>
|
||||
|
||||
</dhcp-server>
|
||||
|
||||
</domain>
|
||||
@ -145,6 +149,8 @@ append config {
|
||||
<dhcp-server ip_first="10.2.3.2"
|
||||
ip_last="10.2.3.2">
|
||||
|
||||
<dns-domain name="genodians.org"/>
|
||||
|
||||
</dhcp-server>
|
||||
|
||||
</domain>
|
||||
@ -281,6 +287,7 @@ append done_string ".* Router: 10.0.3.1.*\n"
|
||||
append done_string ".* DNS server #1: 1.2.3.4.*\n"
|
||||
append done_string ".* DNS server #2: 2.3.4.5.*\n"
|
||||
append done_string ".* DNS server #3: 3.4.5.6.*\n"
|
||||
append done_string ".* DNS domain name: genode.org.*\n"
|
||||
append done_string ".*DHCP request completed:.*\n"
|
||||
append done_string ".* IP lease time: 3600 seconds.*\n"
|
||||
append done_string ".* Interface: 10.0.3.2/24.*\n"
|
||||
@ -296,10 +303,12 @@ append done_string ".*DHCP request completed:.*\n"
|
||||
append done_string ".* IP lease time: 3600 seconds.*\n"
|
||||
append done_string ".* Interface: 10.0.3.2/24.*\n"
|
||||
append done_string ".* Router: 10.0.3.1.*\n"
|
||||
append done_string ".* DNS domain name: genodians.org.*\n"
|
||||
append done_string ".*DHCP request completed:.*\n"
|
||||
append done_string ".* IP lease time: 3600 seconds.*\n"
|
||||
append done_string ".* Interface: 10.0.3.2/24.*\n"
|
||||
append done_string ".* Router: 10.0.3.1.*\n"
|
||||
append done_string ".* DNS domain name: genodians.org.*\n"
|
||||
append done_string ".*DHCP request completed:.*\n"
|
||||
append done_string ".* IP lease time: 3600 seconds.*\n"
|
||||
append done_string ".* Interface: 10.0.3.2/24.*\n"
|
||||
@ -307,5 +316,6 @@ append done_string ".* Router: 10.0.3.1.*\n"
|
||||
append done_string ".* DNS server #1: 1.2.3.4.*\n"
|
||||
append done_string ".* DNS server #2: 2.3.4.5.*\n"
|
||||
append done_string ".* DNS server #3: 3.4.5.6.*\n"
|
||||
append done_string ".* DNS domain name: genode.org.*\n"
|
||||
|
||||
run_genode_until $done_string 30
|
||||
|
@ -441,6 +441,7 @@ this:
|
||||
! ip_last="10.0.1.100"
|
||||
! ip_lease_time_sec="3600">
|
||||
!
|
||||
! <dns-domain name="genodians.org" />
|
||||
! <dns-server ip="8.8.8.8" />
|
||||
! <dns-server ip="1.1.1.1" />
|
||||
! ...
|
||||
@ -468,6 +469,10 @@ 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 given by this attribute.
|
||||
|
||||
The <dns-domain> sub-tag from the first example statically provides a DNS
|
||||
domain name that shall be propagated by the DHCP server through a DHCP option
|
||||
15 entry to its clients.
|
||||
|
||||
The <dns-server> sub-tags from the first example statically provide a list of
|
||||
DNS server addresses that shall be propagated by the DHCP server through a DHCP
|
||||
option 6 entry to its clients. These addresses might be of any IP subnet. The
|
||||
@ -475,14 +480,15 @@ addresses in the DHCP option 6 entry in the DHCP replies will have the same
|
||||
order as the <dns-server> tags in the configuration.
|
||||
|
||||
The 'dns_config_from' attribute from the second example takes effect only when
|
||||
the <dhcp-server> tag does not contain any <dns-server> sub-tags. The attribute
|
||||
states the domain from whose IP config to take the list of propagated DNS
|
||||
server addresses. Note that the order of DNS server adresses is not altered
|
||||
thereby. This is useful in scenarios where these addresses must be obtained
|
||||
dynamically through the DHCP client of another domain. An implication of the
|
||||
'dns_config_from' attribute is that the link state of all interfaces at the
|
||||
domain with the DHCP server becomes bound to the validity of the IP config of
|
||||
the domain that is stated in the attribute.
|
||||
the <dhcp-server> tag does not contain any <dns-domain> or <dns-server>
|
||||
sub-tags. The attribute states the domain from whose IP config to take the DNS
|
||||
domain name and the list of DNS server addresses that shall be propagated. Note
|
||||
that the order of DNS server adresses is not altered thereby. This is useful in
|
||||
scenarios where these addresses must be obtained dynamically through the DHCP
|
||||
client of another domain. An implication of the 'dns_config_from' attribute is
|
||||
that the link state of all interfaces at the domain with the DHCP server
|
||||
becomes bound to the validity of the IP config of the domain that is stated in
|
||||
the attribute.
|
||||
|
||||
The lifetime of an IP address assignment that was yet only offered to the
|
||||
client can be configured for all domains in the <config> tag of the router:
|
||||
@ -548,6 +554,7 @@ A complete state report of the NIC router is structured the following way
|
||||
! <domain name="domain_1" rx_bytes="17597" tx_bytes="7788"
|
||||
! ipv4="100.200.0.10/24" gw="100.200.0.1">
|
||||
!
|
||||
! <dns-domain name="genodians.org"/>
|
||||
! <dns ip="100.200.0.8"/>
|
||||
! <dns ip="1.1.1.1"/>
|
||||
! <dns ip="8.8.8.8"/>
|
||||
@ -687,14 +694,15 @@ simply the 'limit' value minus the 'used' value.
|
||||
'config'
|
||||
|
||||
A boolean value that controls whether the attributes 'ipv4' and 'gw' of the
|
||||
<domain> tag and the subtag <dns> in the <domain> tag are generated. The
|
||||
attribute 'ipv4' contains the current IPv4 address of the router in this domain
|
||||
suffixed by the length of the subnet prefix in bits. The 'gw' attribute
|
||||
contains the IPv4 address of the gateway in this domain. Each <dns> subtag of a
|
||||
<domain> tag shows the IPv4 address of a DNS server known to this domain. The
|
||||
<dns> subtags have the same order that the addresses had in the DHCP option 6
|
||||
entry of the DHCP reply that the router received and that led to the current
|
||||
IPv4 configuration of the domain.
|
||||
<domain> tag and the subtags <dns> and <dns-domain> in the <domain> tag are
|
||||
generated. The attribute 'ipv4' contains the current IPv4 address of the router
|
||||
in this domain suffixed by the length of the subnet prefix in bits. The 'gw'
|
||||
attribute contains the IPv4 address of the gateway in this domain. Each <dns>
|
||||
subtag of a <domain> tag shows the IPv4 address of a DNS server known to this
|
||||
domain. The <dns> subtags have the same order that the addresses had in the
|
||||
DHCP option 6 entry of the DHCP reply that the router received and that led to
|
||||
the current IPv4 configuration of the domain. The <dns-domain> subtag of the
|
||||
<domain> tag states the DNS domain name of this domain if any.
|
||||
|
||||
'config_triggers'
|
||||
|
||||
|
@ -12,6 +12,12 @@
|
||||
</xs:restriction>
|
||||
</xs:simpleType><!-- Domain_name -->
|
||||
|
||||
<xs:simpleType name="Dns_domain_name">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:minLength value="1"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType><!-- Dns_domain_name -->
|
||||
|
||||
<xs:simpleType name="Icmp_type_3_code_attribute">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="no" />
|
||||
@ -140,6 +146,12 @@
|
||||
</xs:complexType>
|
||||
</xs:element><!-- dns-server -->
|
||||
|
||||
<xs:element name="dns-domain">
|
||||
<xs:complexType>
|
||||
<xs:attribute name="name" type="Dns_domain_name" />
|
||||
</xs:complexType>
|
||||
</xs:element><!-- dns-domain -->
|
||||
|
||||
</xs:choice>
|
||||
<xs:attribute name="ip_first" type="Ipv4_address" />
|
||||
<xs:attribute name="ip_last" type="Ipv4_address" />
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <interface.h>
|
||||
#include <domain.h>
|
||||
#include <configuration.h>
|
||||
#include <xml_node.h>
|
||||
|
||||
using namespace Net;
|
||||
using namespace Genode;
|
||||
@ -42,6 +43,18 @@ Dhcp_server_base::Dhcp_server_base(Xml_node const &node,
|
||||
_invalid(domain, "invalid DNS server entry");
|
||||
}
|
||||
});
|
||||
node.with_sub_node("dns-domain", [&] (Xml_node const &sub_node) {
|
||||
xml_node_with_attribute(sub_node, "name", [&] (Xml_attribute const &attr) {
|
||||
_dns_domain_name.set_to(attr);
|
||||
|
||||
if (domain.config().verbose() &&
|
||||
!_dns_domain_name.valid()) {
|
||||
|
||||
log("[", domain, "] rejecting oversized DNS "
|
||||
"domain name from DHCP server configuration");
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -108,6 +121,9 @@ void Dhcp_server::print(Output &output) const
|
||||
_dns_servers.for_each([&] (Dns_server const &dns_server) {
|
||||
Genode::print(output, "DNS server ", dns_server.ip(), ", ");
|
||||
});
|
||||
_dns_domain_name.with_string([&] (Dns_domain_name::String const &str) {
|
||||
Genode::print(output, "DNS domain name ", str, ", ");
|
||||
});
|
||||
try { Genode::print(output, "DNS config from ", _dns_config_from(), ", "); }
|
||||
catch (Pointer<Domain>::Invalid) { }
|
||||
|
||||
@ -118,9 +134,11 @@ void Dhcp_server::print(Output &output) const
|
||||
}
|
||||
|
||||
|
||||
bool Dhcp_server::dns_servers_equal_to_those_of(Dhcp_server const &dhcp_server) const
|
||||
bool Dhcp_server::config_equal_to_that_of(Dhcp_server const &other) const
|
||||
{
|
||||
return _dns_servers.equal_to(dhcp_server._dns_servers);
|
||||
return _ip_lease_time.value == other._ip_lease_time.value &&
|
||||
_dns_servers.equal_to(other._dns_servers) &&
|
||||
_dns_domain_name.equal_to(other._dns_domain_name);
|
||||
}
|
||||
|
||||
|
||||
@ -177,7 +195,9 @@ void Dhcp_server::free_ip(Domain const &domain,
|
||||
Pointer<Domain> Dhcp_server::_init_dns_config_from(Genode::Xml_node const node,
|
||||
Domain_tree &domains)
|
||||
{
|
||||
if (!_dns_servers.empty()) {
|
||||
if (!_dns_servers.empty() ||
|
||||
_dns_domain_name.valid()) {
|
||||
|
||||
return Pointer<Domain>();
|
||||
}
|
||||
Domain_name dns_config_from =
|
||||
|
@ -18,7 +18,7 @@
|
||||
#include <bit_allocator_dynamic.h>
|
||||
#include <list.h>
|
||||
#include <pointer.h>
|
||||
#include <dns_server.h>
|
||||
#include <dns.h>
|
||||
#include <ipv4_config.h>
|
||||
|
||||
/* Genode includes */
|
||||
@ -47,8 +47,9 @@ class Net::Dhcp_server_base
|
||||
{
|
||||
protected:
|
||||
|
||||
Genode::Allocator &_alloc;
|
||||
Net::List<Dns_server> _dns_servers { };
|
||||
Genode::Allocator &_alloc;
|
||||
Dns_server_list _dns_servers { };
|
||||
Dns_domain_name _dns_domain_name { _alloc };
|
||||
|
||||
void _invalid(Domain const &domain,
|
||||
char const *reason);
|
||||
@ -123,8 +124,15 @@ class Net::Dhcp_server : private Genode::Noncopyable,
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
dns_servers_equal_to_those_of(Dhcp_server const &dhcp_server) const;
|
||||
Dns_domain_name const &dns_domain_name() const
|
||||
{
|
||||
if (_dns_config_from.valid()) {
|
||||
return _resolve_dns_config_from().dns_domain_name();
|
||||
}
|
||||
return _dns_domain_name;
|
||||
}
|
||||
|
||||
bool config_equal_to_that_of(Dhcp_server const &dhcp_server) const;
|
||||
|
||||
|
||||
/*********
|
||||
|
128
repos/os/src/server/nic_router/dns.cc
Normal file
128
repos/os/src/server/nic_router/dns.cc
Normal file
@ -0,0 +1,128 @@
|
||||
/*
|
||||
* \brief Utilities for handling DNS configurations
|
||||
* \author Martin Stein
|
||||
* \date 2020-11-17
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2020 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
/* local includes */
|
||||
#include <dns.h>
|
||||
#include <domain.h>
|
||||
#include <configuration.h>
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/xml_node.h>
|
||||
|
||||
using namespace Net;
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
/****************
|
||||
** Dns_server **
|
||||
****************/
|
||||
|
||||
Dns_server::Dns_server(Ipv4_address const &ip)
|
||||
:
|
||||
_ip { ip }
|
||||
{
|
||||
if (!_ip.valid()) {
|
||||
throw Invalid { };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Dns_server::equal_to(Dns_server const &server) const
|
||||
{
|
||||
return _ip == server._ip;
|
||||
}
|
||||
|
||||
|
||||
/*********************
|
||||
** Dns_domain_name **
|
||||
*********************/
|
||||
|
||||
void Dns_domain_name::set_to(Dns_domain_name const &name)
|
||||
{
|
||||
if (name.valid()) {
|
||||
name.with_string([&] (String const &string) {
|
||||
if (_string.valid()) {
|
||||
_string() = string;
|
||||
} else {
|
||||
_string = *new (_alloc) String { string };
|
||||
}
|
||||
});
|
||||
} else {
|
||||
set_invalid();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Dns_domain_name::set_to(Xml_attribute const &name_attr)
|
||||
{
|
||||
name_attr.with_raw_value([&] (char const *base, size_t size) {
|
||||
if (size < STRING_CAPACITY) {
|
||||
if (_string.valid()) {
|
||||
_string() = Cstring { base, size };
|
||||
} else {
|
||||
_string = *new (_alloc) String { Cstring { base, size } };
|
||||
}
|
||||
} else {
|
||||
set_invalid();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
void Dns_domain_name::set_to(Dhcp_packet::Domain_name const &name_option)
|
||||
{
|
||||
name_option.with_string([&] (char const *base, size_t size) {
|
||||
if (size < STRING_CAPACITY) {
|
||||
if (_string.valid()) {
|
||||
_string() = Cstring { base, size };
|
||||
} else {
|
||||
_string = *new (_alloc) String { Cstring { base, size } };
|
||||
}
|
||||
} else {
|
||||
set_invalid();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
void Dns_domain_name::set_invalid()
|
||||
{
|
||||
if (_string.valid()) {
|
||||
_alloc.free(&_string(), sizeof(String));
|
||||
_string = { };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Dns_domain_name::equal_to(Dns_domain_name const &other) const
|
||||
{
|
||||
if (_string.valid()) {
|
||||
if (other._string.valid()) {
|
||||
return _string() == other._string();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return !other._string.valid();
|
||||
}
|
||||
|
||||
|
||||
Dns_domain_name::Dns_domain_name(Genode::Allocator &alloc)
|
||||
:
|
||||
_alloc { alloc }
|
||||
{ }
|
||||
|
||||
|
||||
Dns_domain_name::~Dns_domain_name()
|
||||
{
|
||||
set_invalid();
|
||||
}
|
104
repos/os/src/server/nic_router/dns.h
Normal file
104
repos/os/src/server/nic_router/dns.h
Normal file
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* \brief Utilities for handling DNS configurations
|
||||
* \author Martin Stein
|
||||
* \date 2020-11-17
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2020 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
#ifndef _DNS_H_
|
||||
#define _DNS_H_
|
||||
|
||||
/* local includes */
|
||||
#include <list.h>
|
||||
#include <pointer.h>
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/reconstructible.h>
|
||||
#include <net/ipv4.h>
|
||||
#include <net/dhcp.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
class Xml_attribute;
|
||||
}
|
||||
|
||||
namespace Net {
|
||||
|
||||
class Dns_server;
|
||||
class Dns_domain_name;
|
||||
|
||||
using Dns_server_list = Net::List<Dns_server>;
|
||||
}
|
||||
|
||||
class Net::Dns_server : private Genode::Noncopyable,
|
||||
public Net::List<Dns_server>::Element
|
||||
{
|
||||
private:
|
||||
|
||||
Net::Ipv4_address const _ip;
|
||||
|
||||
public:
|
||||
|
||||
struct Invalid : Genode::Exception { };
|
||||
|
||||
Dns_server(Net::Ipv4_address const &ip);
|
||||
|
||||
bool equal_to(Dns_server const &server) const;
|
||||
|
||||
|
||||
/***************
|
||||
** Accessors **
|
||||
***************/
|
||||
|
||||
Net::Ipv4_address const &ip() const { return _ip; }
|
||||
};
|
||||
|
||||
class Net::Dns_domain_name : private Genode::Noncopyable
|
||||
{
|
||||
private:
|
||||
|
||||
enum { STRING_CAPACITY = 160 };
|
||||
|
||||
public:
|
||||
|
||||
using String = Genode::String<STRING_CAPACITY>;
|
||||
|
||||
private:
|
||||
|
||||
Genode::Allocator &_alloc;
|
||||
Pointer<String> _string { };
|
||||
|
||||
public:
|
||||
|
||||
Dns_domain_name(Genode::Allocator &alloc);
|
||||
|
||||
~Dns_domain_name();
|
||||
|
||||
void set_to(Dns_domain_name const &name);
|
||||
|
||||
void set_to(Genode::Xml_attribute const &name_attr);
|
||||
|
||||
void set_to(Dhcp_packet::Domain_name const &name_option);
|
||||
|
||||
void set_invalid();
|
||||
|
||||
bool valid() const { return _string.valid(); }
|
||||
|
||||
template <typename FUNC>
|
||||
void with_string(FUNC && func) const
|
||||
{
|
||||
if (_string.valid()) {
|
||||
func(_string());
|
||||
}
|
||||
}
|
||||
|
||||
bool equal_to(Dns_domain_name const &other) const;
|
||||
};
|
||||
|
||||
#endif /* _DNS_H_ */
|
@ -1,34 +0,0 @@
|
||||
/*
|
||||
* \brief DNS server entry of a DHCP server or IPv4 config
|
||||
* \author Martin Stein
|
||||
* \date 2020-11-17
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2020 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
/* local includes */
|
||||
#include <dns_server.h>
|
||||
|
||||
using namespace Net;
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
Net::Dns_server::Dns_server(Ipv4_address const &ip)
|
||||
:
|
||||
_ip { ip }
|
||||
{
|
||||
if (!_ip.valid()) {
|
||||
throw Invalid { };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Net::Dns_server::equal_to(Dns_server const &server) const
|
||||
{
|
||||
return _ip == server._ip;
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
/*
|
||||
* \brief DNS server entry of a DHCP server or IPv4 config
|
||||
* \author Martin Stein
|
||||
* \date 2020-11-17
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2020 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
#ifndef _DNS_SERVER_H_
|
||||
#define _DNS_SERVER_H_
|
||||
|
||||
/* local includes */
|
||||
#include <list.h>
|
||||
|
||||
/* Genode includes */
|
||||
#include <net/ipv4.h>
|
||||
|
||||
namespace Net { class Dns_server; }
|
||||
|
||||
class Net::Dns_server : private Genode::Noncopyable,
|
||||
public Net::List<Dns_server>::Element
|
||||
{
|
||||
private:
|
||||
|
||||
Net::Ipv4_address const _ip;
|
||||
|
||||
public:
|
||||
|
||||
struct Invalid : Genode::Exception { };
|
||||
|
||||
Dns_server(Net::Ipv4_address const &ip);
|
||||
|
||||
bool equal_to(Dns_server const &server) const;
|
||||
|
||||
|
||||
/***************
|
||||
** Accessors **
|
||||
***************/
|
||||
|
||||
Net::Ipv4_address const &ip() const { return _ip; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif /* _DHCP_SERVER_H_ */
|
@ -113,7 +113,7 @@ void Domain::discard_ip_config()
|
||||
void Domain::ip_config_from_dhcp_ack(Dhcp_packet &dhcp_ack)
|
||||
{
|
||||
_reconstruct_ip_config([&] (Reconstructible<Ipv4_config> &ip_config) {
|
||||
ip_config.construct(dhcp_ack, _alloc); });
|
||||
ip_config.construct(dhcp_ack, _alloc, *this); });
|
||||
}
|
||||
|
||||
|
||||
@ -397,6 +397,13 @@ void Domain::report(Xml_generator &xml)
|
||||
xml.attribute("ip", String<16>(dns_server.ip()));
|
||||
});
|
||||
});
|
||||
ip_config().dns_domain_name().with_string(
|
||||
[&] (Dns_domain_name::String const &str)
|
||||
{
|
||||
xml.node("dns-domain", [&] () {
|
||||
xml.attribute("name", str);
|
||||
});
|
||||
});
|
||||
empty = false;
|
||||
}
|
||||
if (_config.report().stats()) {
|
||||
|
@ -678,6 +678,11 @@ void Interface::_send_dhcp_reply(Dhcp_server const &dhcp_srv,
|
||||
data.append_address(addr);
|
||||
});
|
||||
});
|
||||
dhcp_srv.dns_domain_name().with_string(
|
||||
[&] (Dns_domain_name::String const &str)
|
||||
{
|
||||
dhcp_opts.append_domain_name(str.string(), str.length());
|
||||
});
|
||||
dhcp_opts.append_option<Dhcp_packet::Broadcast_addr>(local_intf.broadcast_address());
|
||||
dhcp_opts.append_option<Dhcp_packet::Options_end>();
|
||||
|
||||
@ -1908,12 +1913,7 @@ void Interface::_update_dhcp_allocations(Domain &old_domain,
|
||||
try {
|
||||
Dhcp_server &old_dhcp_srv = old_domain.dhcp_server();
|
||||
Dhcp_server &new_dhcp_srv = new_domain.dhcp_server();
|
||||
if (!old_dhcp_srv.dns_servers_equal_to_those_of(new_dhcp_srv)) {
|
||||
throw Pointer<Dhcp_server>::Invalid();
|
||||
}
|
||||
if (old_dhcp_srv.ip_lease_time().value !=
|
||||
new_dhcp_srv.ip_lease_time().value)
|
||||
{
|
||||
if (!old_dhcp_srv.config_equal_to_that_of(new_dhcp_srv)) {
|
||||
throw Pointer<Dhcp_server>::Invalid();
|
||||
}
|
||||
_dhcp_allocations.for_each([&] (Dhcp_allocation &allocation) {
|
||||
|
@ -16,6 +16,8 @@
|
||||
|
||||
/* local includes */
|
||||
#include <ipv4_config.h>
|
||||
#include <domain.h>
|
||||
#include <configuration.h>
|
||||
|
||||
using namespace Genode;
|
||||
using namespace Net;
|
||||
@ -45,22 +47,23 @@ Ipv4_config::Ipv4_config(Ipv4_config const &ip_config,
|
||||
_interface { ip_config._interface },
|
||||
_gateway { ip_config._gateway }
|
||||
{
|
||||
ip_config._dns_servers.for_each([&] (Dns_server const &dns_server) {
|
||||
ip_config.for_each_dns_server([&] (Dns_server const &dns_server) {
|
||||
_dns_servers.insert_as_tail(
|
||||
*new (alloc) Dns_server(dns_server.ip()));
|
||||
});
|
||||
_dns_domain_name.set_to(ip_config.dns_domain_name());
|
||||
}
|
||||
|
||||
|
||||
Ipv4_config::Ipv4_config(Dhcp_packet &dhcp_ack,
|
||||
Allocator &alloc)
|
||||
Ipv4_config::Ipv4_config(Dhcp_packet &dhcp_ack,
|
||||
Allocator &alloc,
|
||||
Domain const &domain)
|
||||
:
|
||||
_alloc { alloc },
|
||||
_interface { dhcp_ack.yiaddr(),
|
||||
dhcp_ipv4_option<Dhcp_packet::Subnet_mask>(dhcp_ack) },
|
||||
_gateway { dhcp_ipv4_option<Dhcp_packet::Router_ipv4>(dhcp_ack) }
|
||||
{
|
||||
|
||||
try {
|
||||
Dhcp_packet::Dns_server const &dns_server {
|
||||
dhcp_ack.option<Dhcp_packet::Dns_server>() };
|
||||
@ -70,6 +73,17 @@ Ipv4_config::Ipv4_config(Dhcp_packet &dhcp_ack,
|
||||
});
|
||||
}
|
||||
catch (Dhcp_packet::Option_not_found) { }
|
||||
try {
|
||||
_dns_domain_name.set_to(dhcp_ack.option<Dhcp_packet::Domain_name>());
|
||||
|
||||
if (domain.config().verbose() &&
|
||||
!_dns_domain_name.valid()) {
|
||||
|
||||
log("[", domain, "] rejecting oversized DNS "
|
||||
"domain name from DHCP reply");
|
||||
}
|
||||
}
|
||||
catch (Dhcp_packet::Option_not_found) { }
|
||||
}
|
||||
|
||||
|
||||
|
@ -17,12 +17,16 @@
|
||||
/* local includes */
|
||||
#include <ipv4_address_prefix.h>
|
||||
#include <dhcp.h>
|
||||
#include <dns_server.h>
|
||||
#include <dns.h>
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/xml_node.h>
|
||||
|
||||
namespace Net { class Ipv4_config; }
|
||||
namespace Net {
|
||||
|
||||
class Domain;
|
||||
class Ipv4_config;
|
||||
}
|
||||
|
||||
class Net::Ipv4_config
|
||||
{
|
||||
@ -36,7 +40,8 @@ class Net::Ipv4_config
|
||||
bool const _point_to_point { _gateway_valid &&
|
||||
_interface_valid &&
|
||||
_interface.prefix == 32 };
|
||||
Net::List<Dns_server> _dns_servers { };
|
||||
Dns_server_list _dns_servers { };
|
||||
Dns_domain_name _dns_domain_name { _alloc };
|
||||
bool const _valid { _point_to_point ||
|
||||
(_interface_valid &&
|
||||
(!_gateway_valid ||
|
||||
@ -45,7 +50,8 @@ class Net::Ipv4_config
|
||||
public:
|
||||
|
||||
Ipv4_config(Net::Dhcp_packet &dhcp_ack,
|
||||
Genode::Allocator &alloc);
|
||||
Genode::Allocator &alloc,
|
||||
Domain const &domain);
|
||||
|
||||
Ipv4_config(Genode::Xml_node const &domain_node,
|
||||
Genode::Allocator &alloc);
|
||||
@ -59,16 +65,17 @@ class Net::Ipv4_config
|
||||
|
||||
bool operator != (Ipv4_config const &other) const
|
||||
{
|
||||
return _interface != other._interface ||
|
||||
_gateway != other._gateway ||
|
||||
!_dns_servers.equal_to(other._dns_servers);
|
||||
return _interface != other._interface ||
|
||||
_gateway != other._gateway ||
|
||||
!_dns_servers.equal_to(other._dns_servers) ||
|
||||
!_dns_domain_name.equal_to(other._dns_domain_name);
|
||||
}
|
||||
|
||||
template <typename FUNC>
|
||||
void for_each_dns_server(FUNC && functor) const
|
||||
void for_each_dns_server(FUNC && func) const
|
||||
{
|
||||
_dns_servers.for_each([&] (Dns_server const &dns_server) {
|
||||
functor(dns_server);
|
||||
func(dns_server);
|
||||
});
|
||||
}
|
||||
|
||||
@ -84,10 +91,11 @@ class Net::Ipv4_config
|
||||
** Accessors **
|
||||
***************/
|
||||
|
||||
bool valid() const { return _valid; }
|
||||
Ipv4_address_prefix const &interface() const { return _interface; }
|
||||
Ipv4_address const &gateway() const { return _gateway; }
|
||||
bool gateway_valid() const { return _gateway_valid; }
|
||||
bool valid() const { return _valid; }
|
||||
Ipv4_address_prefix const &interface() const { return _interface; }
|
||||
Ipv4_address const &gateway() const { return _gateway; }
|
||||
bool gateway_valid() const { return _gateway_valid; }
|
||||
Dns_domain_name const &dns_domain_name() const { return _dns_domain_name; }
|
||||
};
|
||||
|
||||
#endif /* _IPV4_CONFIG_H_ */
|
||||
|
@ -73,6 +73,8 @@ class Net::Const_pointer
|
||||
|
||||
return *_obj;
|
||||
}
|
||||
|
||||
bool valid() const { return _obj != nullptr; }
|
||||
};
|
||||
|
||||
#endif /* _POINTER_H_ */
|
||||
|
@ -22,7 +22,7 @@ SRC_CC += \
|
||||
link.cc \
|
||||
transport_rule.cc \
|
||||
permit_rule.cc \
|
||||
dns_server.cc \
|
||||
dns.cc \
|
||||
dhcp_client.cc \
|
||||
dhcp_server.cc \
|
||||
report.cc \
|
||||
@ -30,7 +30,6 @@ SRC_CC += \
|
||||
uplink_session_root.cc \
|
||||
communication_buffer.cc \
|
||||
|
||||
|
||||
INC_DIR += $(PRG_DIR)
|
||||
|
||||
CONFIG_XSD = config.xsd
|
||||
|
@ -24,6 +24,16 @@ namespace Genode {
|
||||
Microseconds read_sec_attr(Xml_node const node,
|
||||
char const *name,
|
||||
uint64_t const default_sec);
|
||||
|
||||
template <typename FUNC>
|
||||
void xml_node_with_attribute(Xml_node const node,
|
||||
char const *name,
|
||||
FUNC && func)
|
||||
{
|
||||
if (node.has_attribute(name)) {
|
||||
func(node.attribute(name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* _XML_NODE_H_ */
|
||||
|
@ -185,6 +185,15 @@ void Dhcp_client::_handle_dhcp_reply(Dhcp_packet &dhcp)
|
||||
});
|
||||
}
|
||||
catch (Dhcp_packet::Option_not_found) { }
|
||||
try {
|
||||
Dhcp_packet::Domain_name const &domain_name {
|
||||
dhcp.option<Dhcp_packet::Domain_name>() };
|
||||
|
||||
domain_name.with_string([&] (char const *base, size_t size) {
|
||||
log(" DNS domain name: ", Cstring { base, size });
|
||||
});
|
||||
}
|
||||
catch (Dhcp_packet::Option_not_found) { }
|
||||
|
||||
Ipv4_config ip_config(
|
||||
Ipv4_address_prefix(
|
||||
|
@ -1,34 +0,0 @@
|
||||
/*
|
||||
* \brief DNS server entry of a DHCP server or IPv4 config
|
||||
* \author Martin Stein
|
||||
* \date 2020-11-17
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2020 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
/* local includes */
|
||||
#include <dns_server.h>
|
||||
|
||||
using namespace Net;
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
Local::Dns_server::Dns_server(Ipv4_address const &ip)
|
||||
:
|
||||
_ip { ip }
|
||||
{
|
||||
if (!_ip.valid()) {
|
||||
throw Invalid { };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Local::Dns_server::equal_to(Dns_server const &server) const
|
||||
{
|
||||
return _ip == server._ip;
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
/*
|
||||
* \brief DNS server entry of a DHCP server or IPv4 config
|
||||
* \author Martin Stein
|
||||
* \date 2020-11-17
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2020 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
#ifndef _DNS_SERVER_H_
|
||||
#define _DNS_SERVER_H_
|
||||
|
||||
/* local includes */
|
||||
#include <list.h>
|
||||
|
||||
/* Genode includes */
|
||||
#include <net/ipv4.h>
|
||||
|
||||
namespace Local { class Dns_server; }
|
||||
|
||||
class Local::Dns_server : private Genode::Noncopyable,
|
||||
public Local::List<Dns_server>::Element
|
||||
{
|
||||
private:
|
||||
|
||||
Net::Ipv4_address const _ip;
|
||||
|
||||
public:
|
||||
|
||||
struct Invalid : Genode::Exception { };
|
||||
|
||||
Dns_server(Net::Ipv4_address const &ip);
|
||||
|
||||
bool equal_to(Dns_server const &server) const;
|
||||
|
||||
|
||||
/***************
|
||||
** Accessors **
|
||||
***************/
|
||||
|
||||
Net::Ipv4_address const &ip() const { return _ip; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif /* _DHCP_SERVER_H_ */
|
@ -1,102 +0,0 @@
|
||||
/*
|
||||
* \brief Genode list with additional functions needed by NIC router
|
||||
* \author Martin Stein
|
||||
* \date 2016-08-19
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016-2017 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
#ifndef _LIST_H_
|
||||
#define _LIST_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/list.h>
|
||||
#include <base/allocator.h>
|
||||
|
||||
namespace Local { template <typename> class List; }
|
||||
|
||||
|
||||
template <typename LT>
|
||||
struct Local::List : Genode::List<LT>
|
||||
{
|
||||
using Base = Genode::List<LT>;
|
||||
|
||||
template <typename FUNC>
|
||||
void for_each(FUNC && functor)
|
||||
{
|
||||
for (LT *elem = Base::first(); elem; )
|
||||
{
|
||||
LT *const next = elem->Base::Element::next();
|
||||
functor(*elem);
|
||||
elem = next;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename FUNC>
|
||||
void for_each(FUNC && functor) const
|
||||
{
|
||||
for (LT const *elem = Base::first(); elem; )
|
||||
{
|
||||
LT const *const next = elem->Base::Element::next();
|
||||
functor(*elem);
|
||||
elem = next;
|
||||
}
|
||||
}
|
||||
|
||||
void destroy_each(Genode::Deallocator &dealloc)
|
||||
{
|
||||
while (LT *elem = Base::first()) {
|
||||
Base::remove(elem);
|
||||
destroy(dealloc, elem);
|
||||
}
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return Base::first() == nullptr;
|
||||
}
|
||||
|
||||
void insert_as_tail(LT const &le)
|
||||
{
|
||||
LT *elem { Base::first() };
|
||||
if (elem) {
|
||||
while (elem->Base::Element::next()) {
|
||||
elem = elem->Base::Element::next();
|
||||
}
|
||||
}
|
||||
Base::insert(&le, elem);
|
||||
}
|
||||
|
||||
bool equal_to(List<LT> const &list) const
|
||||
{
|
||||
LT const *curr_elem_1 { Base::first() };
|
||||
LT const *curr_elem_2 { list.Base::first() };
|
||||
while (true) {
|
||||
|
||||
if (curr_elem_1 == nullptr) {
|
||||
return curr_elem_2 == nullptr;
|
||||
}
|
||||
if (curr_elem_2 == nullptr) {
|
||||
return false;
|
||||
}
|
||||
LT const *const next_elem_1 {
|
||||
curr_elem_1->List<LT>::Element::next() };
|
||||
|
||||
LT const *const next_elem_2 {
|
||||
curr_elem_2->List<LT>::Element::next() };
|
||||
|
||||
if (!curr_elem_1->equal_to(*curr_elem_2)) {
|
||||
return false;
|
||||
}
|
||||
curr_elem_1 = next_elem_1;
|
||||
curr_elem_2 = next_elem_2;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _LIST_H_ */
|
@ -20,7 +20,10 @@
|
||||
|
||||
/* local includes */
|
||||
#include <ipv4_address_prefix.h>
|
||||
#include <dns_server.h>
|
||||
|
||||
/* NIC router includes */
|
||||
#include <dns.h>
|
||||
#include <xml_node.h>
|
||||
|
||||
using namespace Net;
|
||||
using namespace Genode;
|
||||
@ -39,7 +42,8 @@ class Local::Main
|
||||
Signal_handler<Main> _router_state_handler { _env.ep(), *this, &Main::_handle_router_state };
|
||||
Expanding_reporter _router_config_reporter { _env, "config", "router_config" };
|
||||
bool _router_config_outdated { true };
|
||||
Local::List<Dns_server> _dns_servers { };
|
||||
Dns_server_list _dns_servers { };
|
||||
Dns_domain_name _dns_domain_name { _heap };
|
||||
|
||||
void _handle_router_state();
|
||||
|
||||
@ -99,7 +103,7 @@ void Local::Main::_handle_router_state()
|
||||
* Read out all DNS servers from the new uplink state
|
||||
* and memorize them in a function-local list.
|
||||
*/
|
||||
Local::List<Dns_server> dns_servers { };
|
||||
Dns_server_list dns_servers { };
|
||||
domain_node.for_each_sub_node(
|
||||
"dns",
|
||||
[&] (Xml_node const &dns_node)
|
||||
@ -110,8 +114,8 @@ void Local::Main::_handle_router_state()
|
||||
});
|
||||
|
||||
/*
|
||||
* If the new list of DNS servers differs our member list,
|
||||
* update the member list, and remember to write out a new router
|
||||
* If the new list of DNS servers differs from the stored list,
|
||||
* update the stored list, and remember to write out a new router
|
||||
* configuration.
|
||||
*/
|
||||
if (!_dns_servers.equal_to(dns_servers)) {
|
||||
@ -124,6 +128,19 @@ void Local::Main::_handle_router_state()
|
||||
_router_config_outdated = true;
|
||||
}
|
||||
dns_servers.destroy_each(_heap);
|
||||
|
||||
/* read out new DNS domain name */
|
||||
Dns_domain_name dns_domain_name { _heap };
|
||||
domain_node.with_sub_node("dns-domain", [&] (Xml_node const &sub_node) {
|
||||
xml_node_with_attribute(sub_node, "name", [&] (Xml_attribute const &attr) {
|
||||
dns_domain_name.set_to(attr);
|
||||
});
|
||||
});
|
||||
/* update stored DNS domain name if necessary */
|
||||
if (!_dns_domain_name.equal_to(dns_domain_name)) {
|
||||
_dns_domain_name.set_to(dns_domain_name);
|
||||
_router_config_outdated = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -164,6 +181,13 @@ void Local::Main::_handle_router_state()
|
||||
xml.attribute("ip", String<16>(dns_server.ip()));
|
||||
});
|
||||
});
|
||||
_dns_domain_name.with_string(
|
||||
[&] (Dns_domain_name::String const &str)
|
||||
{
|
||||
xml.node("dns-domain", [&] () {
|
||||
xml.attribute("name", str);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -2,6 +2,9 @@ TARGET = test-nic_router_dhcp-manager
|
||||
|
||||
LIBS += base
|
||||
|
||||
SRC_CC += main.cc ipv4_address_prefix.cc dns_server.cc
|
||||
SRC_CC += main.cc ipv4_address_prefix.cc dns.cc xml_node.cc
|
||||
|
||||
INC_DIR += $(PRG_DIR)
|
||||
INC_DIR += $(PRG_DIR) $(REP_DIR)/src/server/nic_router
|
||||
|
||||
vpath dns.cc $(REP_DIR)/src/server/nic_router
|
||||
vpath xml_node.cc $(REP_DIR)/src/server/nic_router
|
||||
|
Loading…
Reference in New Issue
Block a user