mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-21 18:06:50 +00:00
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:
parent
d2adce7ba6
commit
7b3343c2dc
@ -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" />
|
||||
|
@ -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)),
|
||||
|
@ -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; }
|
||||
|
@ -136,6 +136,7 @@ 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::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);
|
||||
@ -243,10 +245,16 @@ void Domain::init(Domain_tree &domains)
|
||||
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)); }
|
||||
|
@ -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; }
|
||||
};
|
||||
|
||||
|
||||
|
@ -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(); }
|
||||
}
|
||||
|
||||
@ -113,6 +125,7 @@ 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::ICMP: return Port((*(Icmp_packet *)prot_base).query_id());
|
||||
default: throw Interface::Bad_transport_protocol(); }
|
||||
}
|
||||
|
||||
@ -124,6 +137,7 @@ static void _dst_port(L3_protocol const prot,
|
||||
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::ICMP: (*(Icmp_packet *)prot_base).query_id(port.value); return;
|
||||
default: throw Interface::Bad_transport_protocol(); }
|
||||
}
|
||||
|
||||
@ -133,6 +147,7 @@ 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::ICMP: return Port((*(Icmp_packet *)prot_base).query_id());
|
||||
default: throw Interface::Bad_transport_protocol(); }
|
||||
}
|
||||
|
||||
@ -144,6 +159,7 @@ static void _src_port(L3_protocol const prot,
|
||||
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::ICMP: ((Icmp_packet *)prot_base)->query_id(port.value); return;
|
||||
default: throw Interface::Bad_transport_protocol(); }
|
||||
}
|
||||
|
||||
@ -155,6 +171,7 @@ static void *_prot_base(L3_protocol const prot,
|
||||
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::ICMP: return ip.data<Icmp_packet>(prot_size);
|
||||
default: throw Interface::Bad_transport_protocol(); }
|
||||
}
|
||||
|
||||
@ -169,6 +186,7 @@ void Interface::_destroy_link(Link &link)
|
||||
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::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 ð,
|
||||
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);
|
||||
}
|
||||
|
||||
@ -297,6 +315,7 @@ void Interface::detach_from_ip_config()
|
||||
/* destroy links */
|
||||
_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(); }
|
||||
}
|
||||
|
||||
@ -359,6 +382,7 @@ 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::ICMP: return _icmp_links;
|
||||
default: throw Bad_transport_protocol(); }
|
||||
}
|
||||
|
||||
@ -368,6 +392,7 @@ 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::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 ð,
|
||||
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 ð,
|
||||
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 ð,
|
||||
Genode::size_t const eth_size,
|
||||
Packet_descriptor const &pkt,
|
||||
@ -782,6 +888,11 @@ void Interface::_handle_ip(Ethernet_frame ð,
|
||||
}
|
||||
}
|
||||
}
|
||||
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,6 +1197,7 @@ 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<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);
|
||||
@ -1375,6 +1487,7 @@ void Interface::handle_config(Configuration &config)
|
||||
try {
|
||||
/* destroy state objects that are not needed anymore */
|
||||
Domain &old_domain = domain();
|
||||
_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);
|
||||
@ -1402,6 +1515,7 @@ void Interface::handle_config(Configuration &config)
|
||||
/* update state objects */
|
||||
_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);
|
||||
}
|
||||
|
@ -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 ð,
|
||||
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 ð,
|
||||
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 ð,
|
||||
Ipv4_address const &dst_ip,
|
||||
Packet_descriptor const &pkt,
|
||||
|
@ -19,15 +19,18 @@
|
||||
#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::icmp_name() { return _icmp_name; }
|
||||
|
||||
|
||||
Cstring const &Net::l3_protocol_name(L3_protocol protocol)
|
||||
@ -35,5 +38,6 @@ 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::ICMP: return icmp_name();
|
||||
default: throw Interface::Bad_transport_protocol(); }
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -176,6 +176,7 @@ void Link::handle_config(Domain &cln_domain,
|
||||
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::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())
|
||||
{ }
|
||||
|
@ -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_ */
|
||||
|
@ -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))
|
||||
_udp_port_alloc (udp_port_alloc, node.attribute_value("udp-ports", 0UL)),
|
||||
_icmp_port_alloc(icmp_port_alloc, node.attribute_value("icmp-ids", 0UL))
|
||||
{ }
|
||||
|
||||
|
||||
@ -71,7 +73,8 @@ void Nat_rule::print(Output &output) const
|
||||
{
|
||||
Genode::print(output, "domain ", _domain,
|
||||
" tcp-ports ", _tcp_port_alloc.max(),
|
||||
" udp-ports ", _udp_port_alloc.max());
|
||||
" udp-ports ", _udp_port_alloc.max(),
|
||||
" icmp-ports ", _icmp_port_alloc.max());
|
||||
}
|
||||
|
||||
|
||||
@ -80,5 +83,6 @@ 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::ICMP: return _icmp_port_alloc;
|
||||
default: throw Interface::Bad_transport_protocol(); }
|
||||
}
|
||||
|
@ -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);
|
||||
@ -72,6 +74,7 @@ class Net::Nat_rule : public Leaf_rule,
|
||||
|
||||
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; }
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user