nic_router: NAPT for ICMP echo messages

This follows the guidelines in RFC 5508 to enable ICMP echo through a NAPT
channel of the NIC router. It serves also as blueprint for ICMP queries in
general (they are merely not enabled because we don't test them by now).

Issue #2732
This commit is contained in:
Martin Stein 2018-03-28 02:49:44 +02:00 committed by Christian Helmuth
parent d2adce7ba6
commit 7b3343c2dc
13 changed files with 258 additions and 58 deletions

View File

@ -59,6 +59,11 @@
</xs:restriction>
</xs:simpleType><!-- Ipv4_address_prefix -->
<xs:complexType name="L2_rule">
<xs:attribute name="dst" type="Ipv4_address_prefix" />
<xs:attribute name="domain" type="Domain_name" />
</xs:complexType><!-- L2_rule -->
<xs:complexType name="L3_rule">
<xs:choice minOccurs="0" maxOccurs="unbounded">
@ -110,15 +115,12 @@
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="ip">
<xs:complexType>
<xs:attribute name="dst" type="Ipv4_address_prefix" />
<xs:attribute name="domain" type="Domain_name" />
</xs:complexType>
</xs:element><!-- ip -->
<xs:element name="ip" type="L2_rule" />
<xs:element name="icmp" type="L2_rule" />
<xs:element name="nat">
<xs:complexType>
<xs:attribute name="icmp-ids" type="Nr_of_ports" />
<xs:attribute name="tcp-ports" type="Nr_of_ports" />
<xs:attribute name="udp-ports" type="Nr_of_ports" />
<xs:attribute name="domain" type="Domain_name" />

View File

@ -48,6 +48,7 @@ Configuration::Configuration(Env &env,
_dhcp_discover_timeout(read_sec_attr(node, "dhcp_discover_timeout_sec", DEFAULT_DHCP_DISCOVER_TIMEOUT_SEC)),
_dhcp_request_timeout (read_sec_attr(node, "dhcp_request_timeout_sec", DEFAULT_DHCP_REQUEST_TIMEOUT_SEC )),
_dhcp_offer_timeout (read_sec_attr(node, "dhcp_offer_timeout_sec", DEFAULT_DHCP_OFFER_TIMEOUT_SEC )),
_icmp_idle_timeout (read_sec_attr(node, "icmp_idle_timeout_sec", DEFAULT_ICMP_IDLE_TIMEOUT_SEC )),
_udp_idle_timeout (read_sec_attr(node, "udp_idle_timeout_sec", DEFAULT_UDP_IDLE_TIMEOUT_SEC )),
_tcp_idle_timeout (read_sec_attr(node, "tcp_idle_timeout_sec", DEFAULT_TCP_IDLE_TIMEOUT_SEC )),
_tcp_max_segm_lifetime(read_sec_attr(node, "tcp_max_segm_lifetime_sec", DEFAULT_TCP_MAX_SEGM_LIFETIME_SEC)),

View File

@ -37,6 +37,7 @@ class Net::Configuration
Genode::Microseconds const _dhcp_discover_timeout { DEFAULT_DHCP_DISCOVER_TIMEOUT_SEC };
Genode::Microseconds const _dhcp_request_timeout { DEFAULT_DHCP_REQUEST_TIMEOUT_SEC };
Genode::Microseconds const _dhcp_offer_timeout { DEFAULT_DHCP_OFFER_TIMEOUT_SEC };
Genode::Microseconds const _icmp_idle_timeout { DEFAULT_ICMP_IDLE_TIMEOUT_SEC };
Genode::Microseconds const _udp_idle_timeout { DEFAULT_UDP_IDLE_TIMEOUT_SEC };
Genode::Microseconds const _tcp_idle_timeout { DEFAULT_TCP_IDLE_TIMEOUT_SEC };
Genode::Microseconds const _tcp_max_segm_lifetime { DEFAULT_TCP_MAX_SEGM_LIFETIME_SEC };
@ -51,6 +52,7 @@ class Net::Configuration
enum { DEFAULT_DHCP_DISCOVER_TIMEOUT_SEC = 10 };
enum { DEFAULT_DHCP_REQUEST_TIMEOUT_SEC = 10 };
enum { DEFAULT_DHCP_OFFER_TIMEOUT_SEC = 10 };
enum { DEFAULT_ICMP_IDLE_TIMEOUT_SEC = 10 };
enum { DEFAULT_UDP_IDLE_TIMEOUT_SEC = 30 };
enum { DEFAULT_TCP_IDLE_TIMEOUT_SEC = 600 };
enum { DEFAULT_TCP_MAX_SEGM_LIFETIME_SEC = 30 };
@ -77,6 +79,7 @@ class Net::Configuration
Genode::Microseconds dhcp_discover_timeout() const { return _dhcp_discover_timeout; }
Genode::Microseconds dhcp_request_timeout() const { return _dhcp_request_timeout; }
Genode::Microseconds dhcp_offer_timeout() const { return _dhcp_offer_timeout; }
Genode::Microseconds icmp_idle_timeout() const { return _icmp_idle_timeout; }
Genode::Microseconds udp_idle_timeout() const { return _udp_idle_timeout; }
Genode::Microseconds tcp_idle_timeout() const { return _tcp_idle_timeout; }
Genode::Microseconds tcp_max_segm_lifetime() const { return _tcp_max_segm_lifetime; }

View File

@ -134,8 +134,9 @@ Domain::Domain(Configuration &config, Xml_node const node, Allocator &alloc)
Link_side_tree &Domain::links(L3_protocol const protocol)
{
switch (protocol) {
case L3_protocol::TCP: return _tcp_links;
case L3_protocol::UDP: return _udp_links;
case L3_protocol::TCP: return _tcp_links;
case L3_protocol::UDP: return _udp_links;
case L3_protocol::ICMP: return _icmp_links;
default: throw Interface::Bad_transport_protocol(); }
}
@ -170,6 +171,7 @@ Domain::~Domain()
/* destroy rules */
_ip_rules.destroy_each(_alloc);
_nat_rules.destroy_each(_alloc);
_icmp_rules.destroy_each(_alloc);
_udp_rules.destroy_each(_alloc);
_tcp_rules.destroy_each(_alloc);
_udp_forward_rules.destroy_each(_alloc);
@ -235,18 +237,24 @@ void Domain::init(Domain_tree &domains)
_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_transport_rules(tcp_name(), domains, _node, "tcp", _tcp_rules);
_read_transport_rules(udp_name(), domains, _node, "udp", _udp_rules);
/* read NAT rules */
_node.for_each_sub_node("nat", [&] (Xml_node const node) {
try {
_nat_rules.insert(
new (_alloc) Nat_rule(domains, _tcp_port_alloc,
_udp_port_alloc, node));
_udp_port_alloc, _icmp_port_alloc,
node));
}
catch (Rule::Invalid) { warning("invalid NAT rule"); }
});
/* read ICMP rules */
_node.for_each_sub_node("icmp", [&] (Xml_node const node) {
try { _icmp_rules.insert(*new (_alloc) Ip_rule(domains, node)); }
catch (Rule::Invalid) { warning("invalid ICMP rule"); }
});
/* read IP rules */
_node.for_each_sub_node("ip", [&] (Xml_node const node) {
try { _ip_rules.insert(*new (_alloc) Ip_rule(domains, node)); }

View File

@ -92,8 +92,10 @@ class Net::Domain : public Domain_base,
Forward_rule_tree _udp_forward_rules { };
Transport_rule_list _tcp_rules { };
Transport_rule_list _udp_rules { };
Ip_rule_list _icmp_rules { };
Port_allocator _tcp_port_alloc { };
Port_allocator _udp_port_alloc { };
Port_allocator _icmp_port_alloc { };
Nat_rule_tree _nat_rules { };
Interface_list _interfaces { };
unsigned long _interface_cnt { 0 };
@ -104,6 +106,7 @@ class Net::Domain : public Domain_base,
Arp_waiter_list _foreign_arp_waiters { };
Link_side_tree _tcp_links { };
Link_side_tree _udp_links { };
Link_side_tree _icmp_links { };
Genode::size_t _tx_bytes { 0 };
Genode::size_t _rx_bytes { 0 };
bool const _verbose_packets { false };
@ -179,6 +182,7 @@ class Net::Domain : public Domain_base,
Forward_rule_tree &udp_forward_rules() { return _udp_forward_rules; }
Transport_rule_list &tcp_rules() { return _tcp_rules; }
Transport_rule_list &udp_rules() { return _udp_rules; }
Ip_rule_list &icmp_rules() { return _icmp_rules; }
Nat_rule_tree &nat_rules() { return _nat_rules; }
Interface_list &interfaces() { return _interfaces; }
Configuration &config() const { return _config; }
@ -188,6 +192,7 @@ class Net::Domain : public Domain_base,
Arp_waiter_list &foreign_arp_waiters() { return _foreign_arp_waiters; }
Link_side_tree &tcp_links() { return _tcp_links; }
Link_side_tree &udp_links() { return _udp_links; }
Link_side_tree &icmp_links() { return _icmp_links; }
};

View File

@ -14,6 +14,7 @@
/* Genode includes */
#include <net/tcp.h>
#include <net/udp.h>
#include <net/icmp.h>
#include <net/arp.h>
/* local includes */
@ -87,6 +88,9 @@ static void _link_packet(L3_protocol const prot,
case L3_protocol::UDP:
static_cast<Udp_link *>(&link)->packet();
return;
case L3_protocol::ICMP:
static_cast<Icmp_link *>(&link)->packet();
return;
default: throw Interface::Bad_transport_protocol(); }
}
@ -95,7 +99,8 @@ static void _update_checksum(L3_protocol const prot,
void *const prot_base,
size_t const prot_size,
Ipv4_address const src,
Ipv4_address const dst)
Ipv4_address const dst,
size_t const ip_size)
{
switch (prot) {
case L3_protocol::TCP:
@ -104,6 +109,13 @@ static void _update_checksum(L3_protocol const prot,
case L3_protocol::UDP:
((Udp_packet *)prot_base)->update_checksum(src, dst);
return;
case L3_protocol::ICMP:
{
Icmp_packet &icmp = *(Icmp_packet *)prot_base;
icmp.checksum(icmp.calc_checksum(ip_size - sizeof(Ipv4_packet) -
sizeof(Icmp_packet)));
return;
}
default: throw Interface::Bad_transport_protocol(); }
}
@ -111,8 +123,9 @@ static void _update_checksum(L3_protocol const prot,
static Port _dst_port(L3_protocol const prot, void *const prot_base)
{
switch (prot) {
case L3_protocol::TCP: return (*(Tcp_packet *)prot_base).dst_port();
case L3_protocol::UDP: return (*(Udp_packet *)prot_base).dst_port();
case L3_protocol::TCP: return (*(Tcp_packet *)prot_base).dst_port();
case L3_protocol::UDP: return (*(Udp_packet *)prot_base).dst_port();
case L3_protocol::ICMP: return Port((*(Icmp_packet *)prot_base).query_id());
default: throw Interface::Bad_transport_protocol(); }
}
@ -122,8 +135,9 @@ static void _dst_port(L3_protocol const prot,
Port const port)
{
switch (prot) {
case L3_protocol::TCP: (*(Tcp_packet *)prot_base).dst_port(port); return;
case L3_protocol::UDP: (*(Udp_packet *)prot_base).dst_port(port); return;
case L3_protocol::TCP: (*(Tcp_packet *)prot_base).dst_port(port); return;
case L3_protocol::UDP: (*(Udp_packet *)prot_base).dst_port(port); return;
case L3_protocol::ICMP: (*(Icmp_packet *)prot_base).query_id(port.value); return;
default: throw Interface::Bad_transport_protocol(); }
}
@ -131,8 +145,9 @@ static void _dst_port(L3_protocol const prot,
static Port _src_port(L3_protocol const prot, void *const prot_base)
{
switch (prot) {
case L3_protocol::TCP: return (*(Tcp_packet *)prot_base).src_port();
case L3_protocol::UDP: return (*(Udp_packet *)prot_base).src_port();
case L3_protocol::TCP: return (*(Tcp_packet *)prot_base).src_port();
case L3_protocol::UDP: return (*(Udp_packet *)prot_base).src_port();
case L3_protocol::ICMP: return Port((*(Icmp_packet *)prot_base).query_id());
default: throw Interface::Bad_transport_protocol(); }
}
@ -142,8 +157,9 @@ static void _src_port(L3_protocol const prot,
Port const port)
{
switch (prot) {
case L3_protocol::TCP: ((Tcp_packet *)prot_base)->src_port(port); return;
case L3_protocol::UDP: ((Udp_packet *)prot_base)->src_port(port); return;
case L3_protocol::TCP: ((Tcp_packet *)prot_base)->src_port(port); return;
case L3_protocol::UDP: ((Udp_packet *)prot_base)->src_port(port); return;
case L3_protocol::ICMP: ((Icmp_packet *)prot_base)->query_id(port.value); return;
default: throw Interface::Bad_transport_protocol(); }
}
@ -153,8 +169,9 @@ static void *_prot_base(L3_protocol const prot,
Ipv4_packet &ip)
{
switch (prot) {
case L3_protocol::TCP: return ip.data<Tcp_packet>(prot_size);
case L3_protocol::UDP: return ip.data<Udp_packet>(prot_size);
case L3_protocol::TCP: return ip.data<Tcp_packet>(prot_size);
case L3_protocol::UDP: return ip.data<Udp_packet>(prot_size);
case L3_protocol::ICMP: return ip.data<Icmp_packet>(prot_size);
default: throw Interface::Bad_transport_protocol(); }
}
@ -167,8 +184,9 @@ void Interface::_destroy_link(Link &link)
{
L3_protocol const prot = link.protocol();
switch (prot) {
case L3_protocol::TCP: ::_destroy_link<Tcp_link>(link, links(prot), _alloc); break;
case L3_protocol::UDP: ::_destroy_link<Udp_link>(link, links(prot), _alloc); break;
case L3_protocol::TCP: ::_destroy_link<Tcp_link>(link, links(prot), _alloc); break;
case L3_protocol::UDP: ::_destroy_link<Udp_link>(link, links(prot), _alloc); break;
case L3_protocol::ICMP: ::_destroy_link<Icmp_link>(link, links(prot), _alloc); break;
default: throw Bad_transport_protocol(); }
}
@ -180,7 +198,7 @@ void Interface::_pass_prot(Ethernet_frame &eth,
void *const prot_base,
size_t const prot_size)
{
_update_checksum(prot, prot_base, prot_size, ip.src(), ip.dst());
_update_checksum(prot, prot_base, prot_size, ip.src(), ip.dst(), ip.total_length());
_pass_ip(eth, eth_size, ip);
}
@ -295,8 +313,9 @@ void Interface::detach_from_ip_config()
cancel_arp_waiting(*_own_arp_waiters.first()->object());
}
/* destroy links */
_destroy_links<Tcp_link>(_tcp_links, _dissolved_tcp_links, _alloc);
_destroy_links<Udp_link>(_udp_links, _dissolved_udp_links, _alloc);
_destroy_links<Tcp_link> (_tcp_links, _dissolved_tcp_links, _alloc);
_destroy_links<Udp_link> (_udp_links, _dissolved_udp_links, _alloc);
_destroy_links<Icmp_link>(_icmp_links, _dissolved_icmp_links, _alloc);
/* destroy DHCP allocations */
_destroy_released_dhcp_allocations(domain);
@ -343,6 +362,10 @@ Interface::_new_link(L3_protocol const protocol,
new (_alloc) Udp_link(*this, local, remote_port_alloc, remote_domain,
remote, _timer, _config(), protocol);
break;
case L3_protocol::ICMP:
new (_alloc) Icmp_link(*this, local, remote_port_alloc, remote_domain,
remote, _timer, _config(), protocol);
break;
default: throw Bad_transport_protocol(); }
}
@ -357,8 +380,9 @@ void Interface::dhcp_allocation_expired(Dhcp_allocation &allocation)
Link_list &Interface::links(L3_protocol const protocol)
{
switch (protocol) {
case L3_protocol::TCP: return _tcp_links;
case L3_protocol::UDP: return _udp_links;
case L3_protocol::TCP: return _tcp_links;
case L3_protocol::UDP: return _udp_links;
case L3_protocol::ICMP: return _icmp_links;
default: throw Bad_transport_protocol(); }
}
@ -366,8 +390,9 @@ Link_list &Interface::links(L3_protocol const protocol)
Link_list &Interface::dissolved_links(L3_protocol const protocol)
{
switch (protocol) {
case L3_protocol::TCP: return _dissolved_tcp_links;
case L3_protocol::UDP: return _dissolved_udp_links;
case L3_protocol::TCP: return _dissolved_tcp_links;
case L3_protocol::UDP: return _dissolved_udp_links;
case L3_protocol::ICMP: return _dissolved_icmp_links;
default: throw Bad_transport_protocol(); }
}
@ -726,13 +751,94 @@ void Interface::_send_icmp_dst_unreachable(Ipv4_address_prefix const &local_intf
Genode::memcpy(&icmp.data<char>(~0), &req_ip, icmp_data_size);
/* fill in header values that require the packet to be complete */
icmp.update_checksum(icmp_data_size);
icmp.checksum(icmp.calc_checksum(icmp_data_size));
ip.total_length(size.curr() - ip_off);
ip.checksum(Ipv4_packet::calculate_checksum(ip));
});
}
void Interface::_handle_icmp_query(Ethernet_frame &eth,
size_t eth_size,
Ipv4_packet &ip,
Packet_descriptor const &pkt,
L3_protocol prot,
void *prot_base,
size_t prot_size,
Domain &local_domain)
{
Link_side_id const local_id = { ip.src(), _src_port(prot, prot_base),
ip.dst(), _dst_port(prot, prot_base) };
/* try to route via existing ICMP links */
try {
Link_side const &local_side = local_domain.links(prot).find_by_id(local_id);
Link &link = local_side.link();
bool const client = local_side.is_client();
Link_side &remote_side = client ? link.server() : link.client();
Domain &remote_domain = remote_side.domain();
if (_config().verbose()) {
log("Using ", l3_protocol_name(prot), " link: ", link); }
_adapt_eth(eth, remote_side.src_ip(), pkt, remote_domain);
ip.src(remote_side.dst_ip());
ip.dst(remote_side.src_ip());
_src_port(prot, prot_base, remote_side.dst_port());
_dst_port(prot, prot_base, remote_side.src_port());
remote_domain.interfaces().for_each([&] (Interface &interface) {
interface._pass_prot(eth, eth_size, ip, prot, prot_base, prot_size);
});
_link_packet(prot, prot_base, link, client);
return;
}
catch (Link_side_tree::No_match) { }
/* try to route via ICMP rules */
try {
Ip_rule const &rule =
local_domain.icmp_rules().longest_prefix_match(ip.dst());
if(_config().verbose()) {
log("Using ICMP rule: ", rule); }
Domain &remote_domain = rule.domain();
_adapt_eth(eth, local_id.dst_ip, pkt, remote_domain);
_nat_link_and_pass(eth, eth_size, ip, prot, prot_base, prot_size,
local_id, local_domain, remote_domain);
return;
}
catch (Ip_rule_list::No_match) { }
throw Bad_transport_protocol();
}
void Interface::_handle_icmp(Ethernet_frame &eth,
size_t eth_size,
Ipv4_packet &ip,
Packet_descriptor const &pkt,
L3_protocol prot,
void *prot_base,
size_t prot_size,
Domain &local_domain)
{
/* drop packet if ICMP checksum is invalid */
size_t const icmp_sz = ip.total_length() - sizeof(Ipv4_packet);
Icmp_packet &icmp = *ip.data<Icmp_packet>(icmp_sz);
size_t const icmp_data_sz = icmp_sz - sizeof(Icmp_packet);
if (icmp.calc_checksum(icmp_data_sz) != icmp.checksum()) {
throw Drop_packet_inform("bad ICMP checksum");
}
/* select ICMP message type */
switch (icmp.type()) {
case Icmp_packet::Type::ECHO_REPLY:
case Icmp_packet::Type::ECHO_REQUEST: _handle_icmp_query(eth, eth_size, ip, pkt, prot, prot_base, prot_size, local_domain); break;
default: Drop_packet_inform("unknown ICMP message type"); }
}
void Interface::_handle_ip(Ethernet_frame &eth,
Genode::size_t const eth_size,
Packet_descriptor const &pkt,
@ -782,6 +888,11 @@ void Interface::_handle_ip(Ethernet_frame &eth,
}
}
}
else if (prot == L3_protocol::ICMP) {
_handle_icmp(eth, eth_size, ip, pkt, prot, prot_base, prot_size, local_domain);
return;
}
Link_side_id const local_id = { ip.src(), _src_port(prot, prot_base),
ip.dst(), _dst_port(prot, prot_base) };
@ -1086,8 +1197,9 @@ void Interface::_handle_eth(void *const eth_base,
local_domain.raise_rx_bytes(eth_size);
/* do garbage collection over transport-layer links and DHCP allocations */
_destroy_dissolved_links<Udp_link>(_dissolved_udp_links, _alloc);
_destroy_dissolved_links<Tcp_link>(_dissolved_tcp_links, _alloc);
_destroy_dissolved_links<Icmp_link>(_dissolved_icmp_links, _alloc);
_destroy_dissolved_links<Udp_link>(_dissolved_udp_links, _alloc);
_destroy_dissolved_links<Tcp_link>(_dissolved_tcp_links, _alloc);
_destroy_released_dhcp_allocations(local_domain);
/* inspect and handle ethernet frame */
@ -1375,8 +1487,9 @@ void Interface::handle_config(Configuration &config)
try {
/* destroy state objects that are not needed anymore */
Domain &old_domain = domain();
_destroy_dissolved_links<Udp_link>(_dissolved_udp_links, _alloc);
_destroy_dissolved_links<Tcp_link>(_dissolved_tcp_links, _alloc);
_destroy_dissolved_links<Icmp_link>(_dissolved_icmp_links, _alloc);
_destroy_dissolved_links<Udp_link> (_dissolved_udp_links, _alloc);
_destroy_dissolved_links<Tcp_link> (_dissolved_tcp_links, _alloc);
_destroy_released_dhcp_allocations(old_domain);
/* if the domains differ, detach completely from the domain */
@ -1400,8 +1513,9 @@ void Interface::handle_config(Configuration &config)
return;
}
/* update state objects */
_update_links(L3_protocol::TCP, new_domain);
_update_links(L3_protocol::UDP, new_domain);
_update_links(L3_protocol::TCP, new_domain);
_update_links(L3_protocol::UDP, new_domain);
_update_links(L3_protocol::ICMP, new_domain);
_update_dhcp_allocations(old_domain, new_domain);
_update_own_arp_waiters(new_domain);
}

View File

@ -89,8 +89,10 @@ class Net::Interface : private Interface_list::Element
Arp_waiter_list _own_arp_waiters { };
Link_list _tcp_links { };
Link_list _udp_links { };
Link_list _icmp_links { };
Link_list _dissolved_tcp_links { };
Link_list _dissolved_udp_links { };
Link_list _dissolved_icmp_links { };
Dhcp_allocation_tree _dhcp_allocations { };
Dhcp_allocation_list _released_dhcp_allocations { };
Dhcp_client _dhcp_client { _alloc, _timer, *this };
@ -158,6 +160,24 @@ class Net::Interface : private Interface_list::Element
Packet_descriptor const &pkt,
Domain &local_domain);
void _handle_icmp_query(Ethernet_frame &eth,
Genode::size_t eth_size,
Ipv4_packet &ip,
Packet_descriptor const &pkt,
L3_protocol prot,
void *prot_base,
Genode::size_t prot_size,
Domain &local_domain);
void _handle_icmp(Ethernet_frame &eth,
Genode::size_t eth_size,
Ipv4_packet &ip,
Packet_descriptor const &pkt,
L3_protocol prot,
void *prot_base,
Genode::size_t prot_size,
Domain &local_domain);
void _adapt_eth(Ethernet_frame &eth,
Ipv4_address const &dst_ip,
Packet_descriptor const &pkt,

View File

@ -19,21 +19,25 @@
#include <util/string.h>
#include <net/tcp.h>
#include <net/udp.h>
#include <net/icmp.h>
using namespace Net;
using namespace Genode;
static Cstring const _udp_name("UDP");
static Cstring const _tcp_name("TCP");
static Cstring const _icmp_name("ICMP");
Cstring const &Net::udp_name() { return _udp_name; }
Cstring const &Net::tcp_name() { return _tcp_name; }
Cstring const &Net::udp_name() { return _udp_name; }
Cstring const &Net::tcp_name() { return _tcp_name; }
Cstring const &Net::icmp_name() { return _icmp_name; }
Cstring const &Net::l3_protocol_name(L3_protocol protocol)
{
switch (protocol) {
case L3_protocol::TCP: return tcp_name();
case L3_protocol::UDP: return udp_name();
case L3_protocol::TCP: return tcp_name();
case L3_protocol::UDP: return udp_name();
case L3_protocol::ICMP: return icmp_name();
default: throw Interface::Bad_transport_protocol(); }
}

View File

@ -26,6 +26,7 @@ namespace Net {
Genode::Cstring const &tcp_name();
Genode::Cstring const &udp_name();
Genode::Cstring const &icmp_name();
Genode::Cstring const &l3_protocol_name(L3_protocol protocol);
}

View File

@ -174,8 +174,9 @@ void Link::handle_config(Domain &cln_domain,
{
Microseconds dissolve_timeout_us(0);
switch (_protocol) {
case L3_protocol::TCP: dissolve_timeout_us = config.tcp_idle_timeout(); break;
case L3_protocol::UDP: dissolve_timeout_us = config.udp_idle_timeout(); break;
case L3_protocol::TCP: dissolve_timeout_us = config.tcp_idle_timeout(); break;
case L3_protocol::UDP: dissolve_timeout_us = config.udp_idle_timeout(); break;
case L3_protocol::ICMP: dissolve_timeout_us = config.icmp_idle_timeout(); break;
default: throw Interface::Bad_transport_protocol();
}
_dissolve_timeout_us = dissolve_timeout_us;
@ -276,3 +277,21 @@ Udp_link::Udp_link(Interface &cln_interface,
Link(cln_interface, cln_id, srv_port_alloc, srv_domain, srv_id, timer,
config, protocol, config.udp_idle_timeout())
{ }
/***************
** Icmp_link **
***************/
Icmp_link::Icmp_link(Interface &cln_interface,
Link_side_id const &cln_id,
Pointer<Port_allocator_guard> srv_port_alloc,
Domain &srv_domain,
Link_side_id const &srv_id,
Timer::Connection &timer,
Configuration &config,
L3_protocol const protocol)
:
Link(cln_interface, cln_id, srv_port_alloc, srv_domain, srv_id, timer,
config, protocol, config.icmp_idle_timeout())
{ }

View File

@ -1,13 +1,13 @@
/*
* \brief State tracking for UDP/TCP connections
* \brief State tracking for ICMP/UDP//TCP connections
* \author Martin Stein
* \date 2016-08-19
*
* A link is in the UDP case the state tracking of a pseudo UDP connection
* (UDP hole punching) and in the TCP case the state tracking of a TCP
* connection. Beside the layer-3 connection state, a link also contains
* information about the routing and the NAT translation that correspond to
* the connection. Link objects have three different functions:
* A link is in the UDP/ICMP case the state tracking of a pseudo UDP/ICMP
* connection (UDP/ICMP hole punching) and in the TCP case the state tracking
* of a TCP connection. Beside the layer-3 connection state, a link also
* contains information about the routing and the NAT translation that
* correspond to the connection. Link objects have three different functions:
*
* 1) Link objects allow the router to manage the lifetime of resources
* related to a layer-3 connection.
@ -57,6 +57,7 @@ namespace Net {
struct Link_list : List<Link> { };
class Tcp_link;
class Udp_link;
class Icmp_link;
}
@ -238,4 +239,19 @@ struct Net::Udp_link : Link
void packet() { _packet(); }
};
struct Net::Icmp_link : Link
{
Icmp_link(Interface &cln_interface,
Link_side_id const &cln_id,
Pointer<Port_allocator_guard> srv_port_alloc,
Domain &srv_domain,
Link_side_id const &srv_id,
Timer::Connection &timer,
Configuration &config,
L3_protocol const protocol);
void packet() { _packet(); }
};
#endif /* _LINK_H_ */

View File

@ -35,11 +35,13 @@ bool Nat_rule::higher(Nat_rule *rule)
Nat_rule::Nat_rule(Domain_tree &domains,
Port_allocator &tcp_port_alloc,
Port_allocator &udp_port_alloc,
Port_allocator &icmp_port_alloc,
Xml_node const node)
:
Leaf_rule(domains, node),
_tcp_port_alloc(tcp_port_alloc, node.attribute_value("tcp-ports", 0UL)),
_udp_port_alloc(udp_port_alloc, node.attribute_value("udp-ports", 0UL))
_tcp_port_alloc (tcp_port_alloc, node.attribute_value("tcp-ports", 0UL)),
_udp_port_alloc (udp_port_alloc, node.attribute_value("udp-ports", 0UL)),
_icmp_port_alloc(icmp_port_alloc, node.attribute_value("icmp-ids", 0UL))
{ }
@ -70,15 +72,17 @@ Nat_rule &Nat_rule_tree::find_by_domain(Domain &domain)
void Nat_rule::print(Output &output) const
{
Genode::print(output, "domain ", _domain,
" tcp-ports ", _tcp_port_alloc.max(),
" udp-ports ", _udp_port_alloc.max());
" tcp-ports ", _tcp_port_alloc.max(),
" udp-ports ", _udp_port_alloc.max(),
" icmp-ports ", _icmp_port_alloc.max());
}
Port_allocator_guard &Nat_rule::port_alloc(L3_protocol const prot)
{
switch (prot) {
case L3_protocol::TCP: return _tcp_port_alloc;
case L3_protocol::UDP: return _udp_port_alloc;
case L3_protocol::TCP: return _tcp_port_alloc;
case L3_protocol::UDP: return _udp_port_alloc;
case L3_protocol::ICMP: return _icmp_port_alloc;
default: throw Interface::Bad_transport_protocol(); }
}

View File

@ -39,12 +39,14 @@ class Net::Nat_rule : public Leaf_rule,
Port_allocator_guard _tcp_port_alloc;
Port_allocator_guard _udp_port_alloc;
Port_allocator_guard _icmp_port_alloc;
public:
Nat_rule(Domain_tree &domains,
Port_allocator &tcp_port_alloc,
Port_allocator &udp_port_alloc,
Port_allocator &icmp_port_alloc,
Genode::Xml_node const node);
Nat_rule &find_by_domain(Domain &domain);
@ -70,8 +72,9 @@ class Net::Nat_rule : public Leaf_rule,
** Accessors **
***************/
Port_allocator_guard &tcp_port_alloc() { return _tcp_port_alloc; }
Port_allocator_guard &udp_port_alloc() { return _udp_port_alloc; }
Port_allocator_guard &tcp_port_alloc() { return _tcp_port_alloc; }
Port_allocator_guard &udp_port_alloc() { return _udp_port_alloc; }
Port_allocator_guard &icmp_port_alloc() { return _icmp_port_alloc; }
};