nic_router: fix for unknown transport protocols

Do not stop routing if the transport layer protocol is unknown but
continue with trying IP routing instead. The latter was already
done when no transport routing could be applied but for unknown transport
protocols we caught the exception at the wrong place.

Ref #2490
This commit is contained in:
Martin Stein 2017-09-21 20:00:37 +02:00 committed by Christian Helmuth
parent 642254134e
commit 6b4b662357
2 changed files with 88 additions and 75 deletions

View File

@ -147,7 +147,7 @@ static void *_prot_base(uint8_t const prot,
** Interface **
***************/
void Interface::_pass_ip(Ethernet_frame &eth,
void Interface::_pass_prot(Ethernet_frame &eth,
size_t const eth_size,
Ipv4_packet &ip,
uint8_t const prot,
@ -155,6 +155,14 @@ void Interface::_pass_ip(Ethernet_frame &eth,
size_t const prot_size)
{
_update_checksum(prot, prot_base, prot_size, ip.src(), ip.dst());
_pass_ip(eth, eth_size, ip);
}
void Interface::_pass_ip(Ethernet_frame &eth,
size_t const eth_size,
Ipv4_packet &ip)
{
ip.checksum(Ipv4_packet::calculate_checksum(ip));
_send(eth, eth_size);
}
@ -288,7 +296,7 @@ void Interface::_nat_link_and_pass(Ethernet_frame &eth,
Link_side_id const remote = { ip.dst(), _dst_port(prot, prot_base),
ip.src(), _src_port(prot, prot_base) };
_new_link(prot, local, remote_port_alloc, interface, remote);
interface._pass_ip(eth, eth_size, ip, prot, prot_base, prot_size);
interface._pass_prot(eth, eth_size, ip, prot, prot_base, prot_size);
}
@ -303,6 +311,8 @@ void Interface::_handle_ip(Ethernet_frame &eth,
Ipv4_packet &ip = *new (eth.data<void>())
Ipv4_packet(eth_size - sizeof(Ethernet_frame));
/* try to route via transport layer rules */
try {
uint8_t const prot = ip.protocol();
size_t const prot_size = ip.total_length() - ip.header_length() * 4;
void *const prot_base = _prot_base(prot, prot_size, ip);
@ -325,7 +335,7 @@ void Interface::_handle_ip(Ethernet_frame &eth,
_src_port(prot, prot_base, remote_side.dst_port());
_dst_port(prot, prot_base, remote_side.src_port());
interface._pass_ip(eth, eth_size, ip, prot, prot_base, prot_size);
interface._pass_prot(eth, eth_size, ip, prot, prot_base, prot_size);
_link_packet(prot, prot_base, link, client);
return;
}
@ -369,18 +379,20 @@ void Interface::_handle_ip(Ethernet_frame &eth,
}
catch (Transport_rule_list::No_match) { }
catch (Permit_single_rule_tree::No_match) { }
}
catch (Interface::Bad_transport_protocol) { }
/* try to route via IP rules */
try {
Ip_rule const &rule =
_domain.ip_rules().longest_prefix_match(local.dst_ip);
_domain.ip_rules().longest_prefix_match(ip.dst());
Interface &interface = rule.domain().interface().deref();
if(_config().verbose()) {
log("Using IP rule: ", rule); }
_adapt_eth(eth, eth_size, local.dst_ip, pkt, interface);
interface._pass_ip(eth, eth_size, ip, prot, prot_base, prot_size);
_adapt_eth(eth, eth_size, ip.dst(), pkt, interface);
interface._pass_ip(eth, eth_size, ip);
return;
}
catch (Ip_rule_list::No_match) { }
@ -531,9 +543,6 @@ void Interface::_handle_eth(void *const eth_base,
catch (Ethernet_frame::No_ethernet_frame) {
error("invalid ethernet frame"); }
catch (Interface::Bad_transport_protocol) {
error("unknown transport layer protocol"); }
catch (Interface::Bad_network_protocol) {
error("unknown network layer protocol"); }

View File

@ -104,13 +104,17 @@ class Net::Interface
void _send(Ethernet_frame &eth, Genode::size_t const eth_size);
void _pass_ip(Ethernet_frame &eth,
void _pass_prot(Ethernet_frame &eth,
Genode::size_t const eth_size,
Ipv4_packet &ip,
Genode::uint8_t const prot,
void *const prot_base,
Genode::size_t const prot_size);
void _pass_ip(Ethernet_frame &eth,
Genode::size_t const eth_size,
Ipv4_packet &ip);
void _continue_handle_eth(Packet_descriptor const &pkt);
Link_list &_closed_links(Genode::uint8_t const protocol);