2016-09-12 12:55:12 +02:00
|
|
|
/*
|
|
|
|
* \brief Reflects an effective domain configuration node
|
|
|
|
* \author Martin Stein
|
|
|
|
* \date 2016-08-19
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2017-02-20 13:23:52 +01:00
|
|
|
* Copyright (C) 2016-2017 Genode Labs GmbH
|
2016-09-12 12:55:12 +02:00
|
|
|
*
|
|
|
|
* This file is part of the Genode OS framework, which is distributed
|
2017-02-20 13:23:52 +01:00
|
|
|
* under the terms of the GNU Affero General Public License version 3.
|
2016-09-12 12:55:12 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
/* local includes */
|
|
|
|
#include <configuration.h>
|
2017-09-14 15:10:32 +02:00
|
|
|
#include <l3_protocol.h>
|
2016-09-12 12:55:12 +02:00
|
|
|
|
|
|
|
/* Genode includes */
|
|
|
|
#include <util/xml_node.h>
|
|
|
|
#include <base/allocator.h>
|
|
|
|
#include <base/log.h>
|
|
|
|
|
|
|
|
using namespace Net;
|
|
|
|
using namespace Genode;
|
|
|
|
|
|
|
|
|
|
|
|
/***********************
|
|
|
|
** Domain_avl_member **
|
|
|
|
***********************/
|
|
|
|
|
|
|
|
Domain_avl_member::Domain_avl_member(Domain_name const &name,
|
|
|
|
Domain &domain)
|
|
|
|
:
|
|
|
|
Avl_string_base(name.string()), _domain(domain)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
|
|
|
|
/*****************
|
|
|
|
** Domain_base **
|
|
|
|
*****************/
|
|
|
|
|
2016-12-06 14:39:17 +01:00
|
|
|
Domain_base::Domain_base(Xml_node const node)
|
2016-12-22 01:02:50 +01:00
|
|
|
: _name(node.attribute_value("name", Domain_name())) { }
|
2016-09-12 12:55:12 +02:00
|
|
|
|
|
|
|
|
|
|
|
/************
|
|
|
|
** Domain **
|
|
|
|
************/
|
|
|
|
|
nic_router: DHCP client functionality
If the attribute 'interface' is not set in a 'domain' tag, the router tries to
dynamically receive and maintain an IP configuration for that domain by using
DHCP in the client role at all interfaces that connect to the domain. In the
DHCP discover phase, the router simply chooses the first DHCP offer that
arrives. So, no comparison of different DHCP offers is done. In the DHCP
request phase, the server is expected to provide an IP address, a gateway, a
subnet mask, and an IP lease time to the router. If anything substantial goes
wrong during a DHCP exchange, the router discards the outcome of the exchange
and goes back to the DHCP discover phase. At any time where there is no valid
IP configuration present at a domain, the domain does only act as DHCP client
and all other router functionality is disabled for the domain. A domain cannot
act as DHCP client and DHCP server at once. So, a 'domain' tag must either
have an 'interface' attribute or must not contain a 'dhcp-server' tag.
Ref #2534
2017-10-16 11:31:43 +02:00
|
|
|
void Domain::ip_config(Ipv4_address ip,
|
|
|
|
Ipv4_address subnet_mask,
|
|
|
|
Ipv4_address gateway)
|
|
|
|
{
|
|
|
|
_ip_config.construct(Ipv4_address_prefix(ip, subnet_mask), gateway);
|
|
|
|
_ip_config_changed();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Domain::discard_ip_config()
|
|
|
|
{
|
|
|
|
_ip_config.construct();
|
|
|
|
_ip_config_changed();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-09-12 12:55:12 +02:00
|
|
|
void Domain::_read_forward_rules(Cstring const &protocol,
|
|
|
|
Domain_tree &domains,
|
2016-12-06 14:39:17 +01:00
|
|
|
Xml_node const node,
|
2016-09-12 12:55:12 +02:00
|
|
|
char const *type,
|
|
|
|
Forward_rule_tree &rules)
|
|
|
|
{
|
2016-12-06 14:39:17 +01:00
|
|
|
node.for_each_sub_node(type, [&] (Xml_node const node) {
|
2016-09-12 12:55:12 +02:00
|
|
|
try {
|
|
|
|
Forward_rule &rule = *new (_alloc) Forward_rule(domains, node);
|
|
|
|
rules.insert(&rule);
|
|
|
|
if (_config.verbose()) {
|
|
|
|
log(" Forward rule: ", protocol, " ", rule); }
|
|
|
|
}
|
|
|
|
catch (Rule::Invalid) { warning("invalid forward rule"); }
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Domain::_read_transport_rules(Cstring const &protocol,
|
|
|
|
Domain_tree &domains,
|
2016-12-06 14:39:17 +01:00
|
|
|
Xml_node const node,
|
2016-09-12 12:55:12 +02:00
|
|
|
char const *type,
|
|
|
|
Transport_rule_list &rules)
|
|
|
|
{
|
2016-12-06 14:39:17 +01:00
|
|
|
node.for_each_sub_node(type, [&] (Xml_node const node) {
|
2016-09-12 12:55:12 +02:00
|
|
|
try {
|
|
|
|
rules.insert(*new (_alloc) Transport_rule(domains, node, _alloc,
|
|
|
|
protocol, _config));
|
|
|
|
}
|
|
|
|
catch (Rule::Invalid) { warning("invalid transport rule"); }
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Domain::print(Output &output) const
|
|
|
|
{
|
2017-09-25 16:54:11 +02:00
|
|
|
Genode::print(output, _name);
|
2016-09-12 12:55:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-12-06 14:39:17 +01:00
|
|
|
Domain::Domain(Configuration &config, Xml_node const node, Allocator &alloc)
|
2016-09-12 12:55:12 +02:00
|
|
|
:
|
|
|
|
Domain_base(node), _avl_member(_name, *this), _config(config),
|
|
|
|
_node(node), _alloc(alloc),
|
2017-10-13 16:22:05 +02:00
|
|
|
_ip_config(_node.attribute_value("interface", Ipv4_address_prefix()),
|
|
|
|
_node.attribute_value("gateway", Ipv4_address()))
|
2016-09-12 12:55:12 +02:00
|
|
|
{
|
nic_router: DHCP client functionality
If the attribute 'interface' is not set in a 'domain' tag, the router tries to
dynamically receive and maintain an IP configuration for that domain by using
DHCP in the client role at all interfaces that connect to the domain. In the
DHCP discover phase, the router simply chooses the first DHCP offer that
arrives. So, no comparison of different DHCP offers is done. In the DHCP
request phase, the server is expected to provide an IP address, a gateway, a
subnet mask, and an IP lease time to the router. If anything substantial goes
wrong during a DHCP exchange, the router discards the outcome of the exchange
and goes back to the DHCP discover phase. At any time where there is no valid
IP configuration present at a domain, the domain does only act as DHCP client
and all other router functionality is disabled for the domain. A domain cannot
act as DHCP client and DHCP server at once. So, a 'domain' tag must either
have an 'interface' attribute or must not contain a 'dhcp-server' tag.
Ref #2534
2017-10-16 11:31:43 +02:00
|
|
|
if (_name == Domain_name()) {
|
|
|
|
error("Missing name attribute in domain node");
|
2016-09-12 12:55:12 +02:00
|
|
|
throw Invalid();
|
|
|
|
}
|
nic_router: DHCP client functionality
If the attribute 'interface' is not set in a 'domain' tag, the router tries to
dynamically receive and maintain an IP configuration for that domain by using
DHCP in the client role at all interfaces that connect to the domain. In the
DHCP discover phase, the router simply chooses the first DHCP offer that
arrives. So, no comparison of different DHCP offers is done. In the DHCP
request phase, the server is expected to provide an IP address, a gateway, a
subnet mask, and an IP lease time to the router. If anything substantial goes
wrong during a DHCP exchange, the router discards the outcome of the exchange
and goes back to the DHCP discover phase. At any time where there is no valid
IP configuration present at a domain, the domain does only act as DHCP client
and all other router functionality is disabled for the domain. A domain cannot
act as DHCP client and DHCP server at once. So, a 'domain' tag must either
have an 'interface' attribute or must not contain a 'dhcp-server' tag.
Ref #2534
2017-10-16 11:31:43 +02:00
|
|
|
if (!ip_config().valid && _node.has_sub_node("dhcp-server")) {
|
|
|
|
error("Domain cannot act as DHCP client and server at once");
|
|
|
|
throw Invalid();
|
|
|
|
}
|
2017-12-04 19:38:39 +01:00
|
|
|
if (_config.verbose_domain_state()) {
|
|
|
|
log("\033[32m(", *this, ")\033[0m NIC sessions: 0");
|
|
|
|
}
|
nic_router: DHCP client functionality
If the attribute 'interface' is not set in a 'domain' tag, the router tries to
dynamically receive and maintain an IP configuration for that domain by using
DHCP in the client role at all interfaces that connect to the domain. In the
DHCP discover phase, the router simply chooses the first DHCP offer that
arrives. So, no comparison of different DHCP offers is done. In the DHCP
request phase, the server is expected to provide an IP address, a gateway, a
subnet mask, and an IP lease time to the router. If anything substantial goes
wrong during a DHCP exchange, the router discards the outcome of the exchange
and goes back to the DHCP discover phase. At any time where there is no valid
IP configuration present at a domain, the domain does only act as DHCP client
and all other router functionality is disabled for the domain. A domain cannot
act as DHCP client and DHCP server at once. So, a 'domain' tag must either
have an 'interface' attribute or must not contain a 'dhcp-server' tag.
Ref #2534
2017-10-16 11:31:43 +02:00
|
|
|
_ip_config_changed();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Domain::_ip_config_changed()
|
|
|
|
{
|
|
|
|
if (!ip_config().valid) {
|
2017-12-04 19:38:39 +01:00
|
|
|
|
|
|
|
if (_config.verbose_domain_state()) {
|
|
|
|
log("\033[32m(", *this, ")\033[0m IP config: none");
|
|
|
|
}
|
nic_router: DHCP client functionality
If the attribute 'interface' is not set in a 'domain' tag, the router tries to
dynamically receive and maintain an IP configuration for that domain by using
DHCP in the client role at all interfaces that connect to the domain. In the
DHCP discover phase, the router simply chooses the first DHCP offer that
arrives. So, no comparison of different DHCP offers is done. In the DHCP
request phase, the server is expected to provide an IP address, a gateway, a
subnet mask, and an IP lease time to the router. If anything substantial goes
wrong during a DHCP exchange, the router discards the outcome of the exchange
and goes back to the DHCP discover phase. At any time where there is no valid
IP configuration present at a domain, the domain does only act as DHCP client
and all other router functionality is disabled for the domain. A domain cannot
act as DHCP client and DHCP server at once. So, a 'domain' tag must either
have an 'interface' attribute or must not contain a 'dhcp-server' tag.
Ref #2534
2017-10-16 11:31:43 +02:00
|
|
|
return;
|
|
|
|
}
|
2017-12-04 19:38:39 +01:00
|
|
|
if (_config.verbose_domain_state()) {
|
|
|
|
log("\033[32m(", *this, ")\033[0m IP config:"
|
nic_router: DHCP client functionality
If the attribute 'interface' is not set in a 'domain' tag, the router tries to
dynamically receive and maintain an IP configuration for that domain by using
DHCP in the client role at all interfaces that connect to the domain. In the
DHCP discover phase, the router simply chooses the first DHCP offer that
arrives. So, no comparison of different DHCP offers is done. In the DHCP
request phase, the server is expected to provide an IP address, a gateway, a
subnet mask, and an IP lease time to the router. If anything substantial goes
wrong during a DHCP exchange, the router discards the outcome of the exchange
and goes back to the DHCP discover phase. At any time where there is no valid
IP configuration present at a domain, the domain does only act as DHCP client
and all other router functionality is disabled for the domain. A domain cannot
act as DHCP client and DHCP server at once. So, a 'domain' tag must either
have an 'interface' attribute or must not contain a 'dhcp-server' tag.
Ref #2534
2017-10-16 11:31:43 +02:00
|
|
|
" interface ", ip_config().interface,
|
2017-12-04 19:38:39 +01:00
|
|
|
", gateway ", ip_config().gateway);
|
nic_router: DHCP client functionality
If the attribute 'interface' is not set in a 'domain' tag, the router tries to
dynamically receive and maintain an IP configuration for that domain by using
DHCP in the client role at all interfaces that connect to the domain. In the
DHCP discover phase, the router simply chooses the first DHCP offer that
arrives. So, no comparison of different DHCP offers is done. In the DHCP
request phase, the server is expected to provide an IP address, a gateway, a
subnet mask, and an IP lease time to the router. If anything substantial goes
wrong during a DHCP exchange, the router discards the outcome of the exchange
and goes back to the DHCP discover phase. At any time where there is no valid
IP configuration present at a domain, the domain does only act as DHCP client
and all other router functionality is disabled for the domain. A domain cannot
act as DHCP client and DHCP server at once. So, a 'domain' tag must either
have an 'interface' attribute or must not contain a 'dhcp-server' tag.
Ref #2534
2017-10-16 11:31:43 +02:00
|
|
|
}
|
2017-10-06 13:00:05 +02:00
|
|
|
/* try to find configuration for DHCP server role */
|
|
|
|
try {
|
nic_router: DHCP client functionality
If the attribute 'interface' is not set in a 'domain' tag, the router tries to
dynamically receive and maintain an IP configuration for that domain by using
DHCP in the client role at all interfaces that connect to the domain. In the
DHCP discover phase, the router simply chooses the first DHCP offer that
arrives. So, no comparison of different DHCP offers is done. In the DHCP
request phase, the server is expected to provide an IP address, a gateway, a
subnet mask, and an IP lease time to the router. If anything substantial goes
wrong during a DHCP exchange, the router discards the outcome of the exchange
and goes back to the DHCP discover phase. At any time where there is no valid
IP configuration present at a domain, the domain does only act as DHCP client
and all other router functionality is disabled for the domain. A domain cannot
act as DHCP client and DHCP server at once. So, a 'domain' tag must either
have an 'interface' attribute or must not contain a 'dhcp-server' tag.
Ref #2534
2017-10-16 11:31:43 +02:00
|
|
|
_dhcp_server.set(*new (_alloc)
|
|
|
|
Dhcp_server(_node.sub_node("dhcp-server"), _alloc,
|
|
|
|
ip_config().interface));
|
2017-10-06 13:00:05 +02:00
|
|
|
|
|
|
|
if (_config.verbose()) {
|
nic_router: DHCP client functionality
If the attribute 'interface' is not set in a 'domain' tag, the router tries to
dynamically receive and maintain an IP configuration for that domain by using
DHCP in the client role at all interfaces that connect to the domain. In the
DHCP discover phase, the router simply chooses the first DHCP offer that
arrives. So, no comparison of different DHCP offers is done. In the DHCP
request phase, the server is expected to provide an IP address, a gateway, a
subnet mask, and an IP lease time to the router. If anything substantial goes
wrong during a DHCP exchange, the router discards the outcome of the exchange
and goes back to the DHCP discover phase. At any time where there is no valid
IP configuration present at a domain, the domain does only act as DHCP client
and all other router functionality is disabled for the domain. A domain cannot
act as DHCP client and DHCP server at once. So, a 'domain' tag must either
have an 'interface' attribute or must not contain a 'dhcp-server' tag.
Ref #2534
2017-10-16 11:31:43 +02:00
|
|
|
log("DHCP server at domain \"", *this, "\": ", _dhcp_server.deref()); }
|
2017-10-06 13:00:05 +02:00
|
|
|
}
|
|
|
|
catch (Xml_node::Nonexistent_sub_node) { }
|
|
|
|
catch (Dhcp_server::Invalid) {
|
2017-10-16 12:42:06 +02:00
|
|
|
error("Invalid DHCP server configuration at domain \"", *this, "\""); }
|
2017-10-06 13:00:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Domain::~Domain()
|
|
|
|
{
|
|
|
|
try { destroy(_alloc, &_dhcp_server.deref()); }
|
|
|
|
catch (Pointer<Dhcp_server>::Invalid) { }
|
2016-09-12 12:55:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Domain::create_rules(Domain_tree &domains)
|
|
|
|
{
|
|
|
|
/* read forward rules */
|
|
|
|
_read_forward_rules(tcp_name(), domains, _node, "tcp-forward",
|
|
|
|
_tcp_forward_rules);
|
|
|
|
_read_forward_rules(udp_name(), domains, _node, "udp-forward",
|
|
|
|
_udp_forward_rules);
|
|
|
|
|
|
|
|
/* read UDP and TCP rules */
|
|
|
|
_read_transport_rules(tcp_name(), domains, _node, "tcp", _tcp_rules);
|
|
|
|
_read_transport_rules(udp_name(), domains, _node, "udp", _udp_rules);
|
|
|
|
|
|
|
|
/* read NAT rules */
|
2016-12-06 14:39:17 +01:00
|
|
|
_node.for_each_sub_node("nat", [&] (Xml_node const node) {
|
2016-09-12 12:55:12 +02:00
|
|
|
try {
|
|
|
|
_nat_rules.insert(
|
|
|
|
new (_alloc) Nat_rule(domains, _tcp_port_alloc,
|
|
|
|
_udp_port_alloc, node));
|
|
|
|
}
|
|
|
|
catch (Rule::Invalid) { warning("invalid NAT rule"); }
|
|
|
|
});
|
|
|
|
/* read IP rules */
|
2016-12-06 14:39:17 +01:00
|
|
|
_node.for_each_sub_node("ip", [&] (Xml_node const node) {
|
2016-09-12 12:55:12 +02:00
|
|
|
try { _ip_rules.insert(*new (_alloc) Ip_rule(domains, node)); }
|
|
|
|
catch (Rule::Invalid) { warning("invalid IP rule"); }
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Ipv4_address const &Domain::next_hop(Ipv4_address const &ip) const
|
|
|
|
{
|
nic_router: DHCP client functionality
If the attribute 'interface' is not set in a 'domain' tag, the router tries to
dynamically receive and maintain an IP configuration for that domain by using
DHCP in the client role at all interfaces that connect to the domain. In the
DHCP discover phase, the router simply chooses the first DHCP offer that
arrives. So, no comparison of different DHCP offers is done. In the DHCP
request phase, the server is expected to provide an IP address, a gateway, a
subnet mask, and an IP lease time to the router. If anything substantial goes
wrong during a DHCP exchange, the router discards the outcome of the exchange
and goes back to the DHCP discover phase. At any time where there is no valid
IP configuration present at a domain, the domain does only act as DHCP client
and all other router functionality is disabled for the domain. A domain cannot
act as DHCP client and DHCP server at once. So, a 'domain' tag must either
have an 'interface' attribute or must not contain a 'dhcp-server' tag.
Ref #2534
2017-10-16 11:31:43 +02:00
|
|
|
if (ip_config().interface.prefix_matches(ip)) { return ip; }
|
|
|
|
if (ip_config().gateway_valid) { return ip_config().gateway; }
|
2016-09-12 12:55:12 +02:00
|
|
|
throw No_next_hop();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*****************
|
|
|
|
** Domain_tree **
|
|
|
|
*****************/
|
|
|
|
|
|
|
|
Domain &Domain_tree::domain(Avl_string_base const &node)
|
|
|
|
{
|
|
|
|
return static_cast<Domain_avl_member const *>(&node)->domain();
|
|
|
|
}
|
|
|
|
|
|
|
|
Domain &Domain_tree::find_by_name(Domain_name name)
|
|
|
|
{
|
|
|
|
if (name == Domain_name() || !first()) {
|
|
|
|
throw No_match(); }
|
|
|
|
|
|
|
|
Avl_string_base *node = first()->find_by_name(name.string());
|
|
|
|
if (!node) {
|
|
|
|
throw No_match(); }
|
|
|
|
|
|
|
|
return domain(*node);
|
|
|
|
}
|