mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-19 13:47:56 +00:00
nic_router: act as ICMP Echo server
The ICMP-Echo-server functionality of the router has the following configuration attributes (default values shown): ! <config icmp_echo_server="yes"> ! <domain icmp_echo_server="yes" ... /> ! </config> The icmp_echo_server attribute configures whether the router answers ICMP Echo requests that address the router. The <config> value affects all domains without a <domain> local value. Issue #2874
This commit is contained in:
parent
a9183da87b
commit
0b8520a208
@ -10,6 +10,7 @@ these domains. This is a brief overview of the features thereby provided:
|
||||
* NAPT for UDP, TCP and ICMP "Echo",
|
||||
* forwarding of ICMP "Destination Unreachable" according to the UDP, TCP or
|
||||
ICMP "Echo" connection it refers to,
|
||||
* acting as ICMP echo server per domain
|
||||
* acting as DHCP server or client per domain,
|
||||
* provide per-domain network statistics via a report session,
|
||||
* print out header information for each packet received or sent,
|
||||
@ -361,6 +362,21 @@ Denial-of-Service attacks against the destination domain by occupying all of
|
||||
its ports or IDs.
|
||||
|
||||
|
||||
Configuring ICMP-Echo-server functionality
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The ICMP-Echo-server functionality of the router has the following
|
||||
configuration attributes (default values shown):
|
||||
|
||||
! <config icmp_echo_server="yes">
|
||||
! <domain icmp_echo_server="yes" ... />
|
||||
! </config>
|
||||
|
||||
The icmp_echo_server attribute configures whether the router answers ICMP Echo
|
||||
requests that address the router. The <config> value affects all domains
|
||||
without a <domain> local value.
|
||||
|
||||
|
||||
Configuring DHCP server functionality
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -151,11 +151,12 @@
|
||||
<xs:element name="udp-forward" type="L3_forward_rule" />
|
||||
|
||||
</xs:choice>
|
||||
<xs:attribute name="name" type="Domain_name" />
|
||||
<xs:attribute name="interface" type="Ipv4_address_prefix" />
|
||||
<xs:attribute name="gateway" type="Ipv4_address" />
|
||||
<xs:attribute name="verbose_packets" type="Boolean" />
|
||||
<xs:attribute name="label" type="Session_label" />
|
||||
<xs:attribute name="name" type="Domain_name" />
|
||||
<xs:attribute name="interface" type="Ipv4_address_prefix" />
|
||||
<xs:attribute name="gateway" type="Ipv4_address" />
|
||||
<xs:attribute name="verbose_packets" type="Boolean" />
|
||||
<xs:attribute name="label" type="Session_label" />
|
||||
<xs:attribute name="icmp_echo_server" type="Boolean" />
|
||||
</xs:complexType>
|
||||
</xs:element><!-- domain -->
|
||||
|
||||
@ -170,6 +171,7 @@
|
||||
<xs:attribute name="tcp_idle_timeout_sec" type="Seconds" />
|
||||
<xs:attribute name="icmp_idle_timeout_sec" type="Seconds" />
|
||||
<xs:attribute name="tcp_max_segm_lifetime_sec" type="Seconds" />
|
||||
<xs:attribute name="icmp_echo_server" type="Boolean" />
|
||||
</xs:complexType>
|
||||
</xs:element><!-- config -->
|
||||
|
||||
|
@ -68,6 +68,7 @@ Configuration::Configuration(Env &env,
|
||||
_verbose (node.attribute_value("verbose", false)),
|
||||
_verbose_packets (node.attribute_value("verbose_packets", false)),
|
||||
_verbose_domain_state (node.attribute_value("verbose_domain_state", false)),
|
||||
_icmp_echo_server (node.attribute_value("icmp_echo_server", true)),
|
||||
_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 )),
|
||||
|
@ -37,6 +37,7 @@ class Net::Configuration
|
||||
bool const _verbose { false };
|
||||
bool const _verbose_packets { false };
|
||||
bool const _verbose_domain_state { false };
|
||||
bool const _icmp_echo_server { true };
|
||||
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 };
|
||||
@ -87,6 +88,7 @@ class Net::Configuration
|
||||
bool verbose() const { return _verbose; }
|
||||
bool verbose_packets() const { return _verbose_packets; }
|
||||
bool verbose_domain_state() const { return _verbose_domain_state; }
|
||||
bool icmp_echo_server() const { return _icmp_echo_server; }
|
||||
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; }
|
||||
|
@ -205,6 +205,8 @@ Domain::Domain(Configuration &config, Xml_node const node, Allocator &alloc)
|
||||
Ipv4_address()),
|
||||
_verbose_packets(_node.attribute_value("verbose_packets", false) ||
|
||||
_config.verbose_packets()),
|
||||
_icmp_echo_server(_node.attribute_value("icmp_echo_server",
|
||||
_config.icmp_echo_server())),
|
||||
_label(_node.attribute_value("label", String<160>()).string())
|
||||
{
|
||||
_log_ip_config();
|
||||
|
@ -93,6 +93,7 @@ class Net::Domain : public Domain_base,
|
||||
Genode::size_t _tx_bytes { 0 };
|
||||
Genode::size_t _rx_bytes { 0 };
|
||||
bool const _verbose_packets { false };
|
||||
bool const _icmp_echo_server;
|
||||
Genode::Session_label const _label;
|
||||
|
||||
void _read_forward_rules(Genode::Cstring const &protocol,
|
||||
@ -166,26 +167,27 @@ class Net::Domain : public Domain_base,
|
||||
** Accessors **
|
||||
***************/
|
||||
|
||||
bool verbose_packets() const { return _verbose_packets; }
|
||||
Genode::Session_label const &label() const { return _label; }
|
||||
Ipv4_config const &ip_config() const { return *_ip_config; }
|
||||
List<Domain> &ip_config_dependents() { return _ip_config_dependents; }
|
||||
Domain_name const &name() const { return _name; }
|
||||
Ip_rule_list &ip_rules() { return _ip_rules; }
|
||||
Forward_rule_tree &tcp_forward_rules() { return _tcp_forward_rules; }
|
||||
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; }
|
||||
bool verbose_packets() const { return _verbose_packets; }
|
||||
bool icmp_echo_server() const { return _icmp_echo_server; }
|
||||
Genode::Session_label const &label() const { return _label; }
|
||||
Ipv4_config const &ip_config() const { return *_ip_config; }
|
||||
List<Domain> &ip_config_dependents() { return _ip_config_dependents; }
|
||||
Domain_name const &name() const { return _name; }
|
||||
Ip_rule_list &ip_rules() { return _ip_rules; }
|
||||
Forward_rule_tree &tcp_forward_rules() { return _tcp_forward_rules; }
|
||||
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; }
|
||||
Dhcp_server &dhcp_server();
|
||||
Arp_cache &arp_cache() { return _arp_cache; }
|
||||
Arp_waiter_list &foreign_arp_waiters() { return _foreign_arp_waiters; }
|
||||
Link_side_tree &tcp_links() { return _tcp_links; }
|
||||
Link_side_tree &udp_links() { return _udp_links; }
|
||||
Link_side_tree &icmp_links() { return _icmp_links; }
|
||||
Arp_cache &arp_cache() { return _arp_cache; }
|
||||
Arp_waiter_list &foreign_arp_waiters() { return _foreign_arp_waiters; }
|
||||
Link_side_tree &tcp_links() { return _tcp_links; }
|
||||
Link_side_tree &udp_links() { return _udp_links; }
|
||||
Link_side_tree &icmp_links() { return _icmp_links; }
|
||||
};
|
||||
|
||||
#endif /* _DOMAIN_H_ */
|
||||
|
@ -787,6 +787,33 @@ void Interface::handle_link_state()
|
||||
}
|
||||
|
||||
|
||||
void Interface::_send_icmp_echo_reply(Ethernet_frame ð,
|
||||
Ipv4_packet &ip,
|
||||
Icmp_packet &icmp,
|
||||
size_t icmp_sz,
|
||||
Size_guard &size_guard)
|
||||
{
|
||||
/* adapt Ethernet header */
|
||||
Mac_address const eth_src = eth.src();
|
||||
eth.src(eth.dst());
|
||||
eth.dst(eth_src);
|
||||
|
||||
/* adapt IPv4 header */
|
||||
Ipv4_address const ip_src = ip.src();
|
||||
ip.src(ip.dst());
|
||||
ip.dst(ip_src);
|
||||
|
||||
/* adapt ICMP header */
|
||||
icmp.type(Icmp_packet::Type::ECHO_REPLY);
|
||||
icmp.code(Icmp_packet::Code::ECHO_REPLY);
|
||||
|
||||
/* update checksums and send */
|
||||
icmp.update_checksum(icmp_sz - sizeof(Icmp_packet));
|
||||
ip.update_checksum();
|
||||
send(eth, size_guard);
|
||||
}
|
||||
|
||||
|
||||
void Interface::_handle_icmp_query(Ethernet_frame ð,
|
||||
Size_guard &size_guard,
|
||||
Ipv4_packet &ip,
|
||||
@ -908,26 +935,38 @@ void Interface::_handle_icmp_error(Ethernet_frame ð,
|
||||
}
|
||||
|
||||
|
||||
void Interface::_handle_icmp(Ethernet_frame ð,
|
||||
Size_guard &size_guard,
|
||||
Ipv4_packet &ip,
|
||||
Packet_descriptor const &pkt,
|
||||
L3_protocol prot,
|
||||
void *prot_base,
|
||||
size_t prot_size,
|
||||
Domain &local_domain)
|
||||
void Interface::_handle_icmp(Ethernet_frame ð,
|
||||
Size_guard &size_guard,
|
||||
Ipv4_packet &ip,
|
||||
Packet_descriptor const &pkt,
|
||||
L3_protocol prot,
|
||||
void *prot_base,
|
||||
size_t prot_size,
|
||||
Domain &local_domain,
|
||||
Ipv4_address_prefix const &local_intf)
|
||||
{
|
||||
/* drop packet if ICMP checksum is invalid */
|
||||
Icmp_packet &icmp = *reinterpret_cast<Icmp_packet *>(prot_base);
|
||||
if (icmp.checksum_error(size_guard.unconsumed())) {
|
||||
throw Drop_packet("bad ICMP checksum");
|
||||
throw Drop_packet("bad ICMP checksum"); }
|
||||
|
||||
/* try to act as ICMP Echo server */
|
||||
if (icmp.type() == Icmp_packet::Type::ECHO_REQUEST &&
|
||||
ip.dst() == local_intf.address &&
|
||||
local_domain.icmp_echo_server())
|
||||
{
|
||||
if(_config().verbose()) {
|
||||
log("[", local_domain, "] act as ICMP Echo server"); }
|
||||
|
||||
_send_icmp_echo_reply(eth, ip, icmp, prot_size, size_guard);
|
||||
return;
|
||||
}
|
||||
/* select ICMP message type */
|
||||
/* try to act as ICMP router */
|
||||
switch (icmp.type()) {
|
||||
case Icmp_packet::Type::ECHO_REPLY:
|
||||
case Icmp_packet::Type::ECHO_REQUEST: _handle_icmp_query(eth, size_guard, ip, pkt, prot, prot_base, prot_size, local_domain); break;
|
||||
case Icmp_packet::Type::DST_UNREACHABLE: _handle_icmp_error(eth, size_guard, ip, pkt, local_domain, icmp, prot_size); break;
|
||||
default: Drop_packet("unknown ICMP message type"); }
|
||||
default: Drop_packet("unhandled type in ICMP"); }
|
||||
}
|
||||
|
||||
|
||||
@ -979,7 +1018,8 @@ void Interface::_handle_ip(Ethernet_frame ð,
|
||||
}
|
||||
}
|
||||
else if (prot == L3_protocol::ICMP) {
|
||||
_handle_icmp(eth, size_guard, ip, pkt, prot, prot_base, prot_size, local_domain);
|
||||
_handle_icmp(eth, size_guard, ip, pkt, prot, prot_base, prot_size,
|
||||
local_domain, local_intf);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -140,6 +140,12 @@ class Net::Interface : private Interface_list::Element
|
||||
Genode::uint32_t xid,
|
||||
Ipv4_address_prefix const &local_intf);
|
||||
|
||||
void _send_icmp_echo_reply(Ethernet_frame ð,
|
||||
Ipv4_packet &ip,
|
||||
Icmp_packet &icmp,
|
||||
Genode::size_t icmp_sz,
|
||||
Size_guard &size_guard);
|
||||
|
||||
Forward_rule_tree &_forward_rules(Domain &local_domain,
|
||||
L3_protocol const prot) const;
|
||||
|
||||
@ -190,14 +196,15 @@ class Net::Interface : private Interface_list::Element
|
||||
Icmp_packet &icmp,
|
||||
Genode::size_t icmp_sz);
|
||||
|
||||
void _handle_icmp(Ethernet_frame ð,
|
||||
Size_guard &size_guard,
|
||||
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 ð,
|
||||
Size_guard &size_guard,
|
||||
Ipv4_packet &ip,
|
||||
Packet_descriptor const &pkt,
|
||||
L3_protocol prot,
|
||||
void *prot_base,
|
||||
Genode::size_t prot_size,
|
||||
Domain &local_domain,
|
||||
Ipv4_address_prefix const &local_intf);
|
||||
|
||||
void _adapt_eth(Ethernet_frame ð,
|
||||
Ipv4_address const &dst_ip,
|
||||
|
Loading…
Reference in New Issue
Block a user