mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-14 17:00:09 +00:00
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:
parent
642254134e
commit
6b4b662357
@ -147,14 +147,22 @@ static void *_prot_base(uint8_t const prot,
|
|||||||
** Interface **
|
** Interface **
|
||||||
***************/
|
***************/
|
||||||
|
|
||||||
void Interface::_pass_ip(Ethernet_frame ð,
|
void Interface::_pass_prot(Ethernet_frame ð,
|
||||||
size_t const eth_size,
|
size_t const eth_size,
|
||||||
Ipv4_packet &ip,
|
Ipv4_packet &ip,
|
||||||
uint8_t const prot,
|
uint8_t const prot,
|
||||||
void *const prot_base,
|
void *const prot_base,
|
||||||
size_t const prot_size)
|
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());
|
||||||
|
_pass_ip(eth, eth_size, ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Interface::_pass_ip(Ethernet_frame ð,
|
||||||
|
size_t const eth_size,
|
||||||
|
Ipv4_packet &ip)
|
||||||
|
{
|
||||||
ip.checksum(Ipv4_packet::calculate_checksum(ip));
|
ip.checksum(Ipv4_packet::calculate_checksum(ip));
|
||||||
_send(eth, eth_size);
|
_send(eth, eth_size);
|
||||||
}
|
}
|
||||||
@ -288,7 +296,7 @@ void Interface::_nat_link_and_pass(Ethernet_frame ð,
|
|||||||
Link_side_id const remote = { ip.dst(), _dst_port(prot, prot_base),
|
Link_side_id const remote = { ip.dst(), _dst_port(prot, prot_base),
|
||||||
ip.src(), _src_port(prot, prot_base) };
|
ip.src(), _src_port(prot, prot_base) };
|
||||||
_new_link(prot, local, remote_port_alloc, interface, remote);
|
_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,84 +311,88 @@ void Interface::_handle_ip(Ethernet_frame ð,
|
|||||||
Ipv4_packet &ip = *new (eth.data<void>())
|
Ipv4_packet &ip = *new (eth.data<void>())
|
||||||
Ipv4_packet(eth_size - sizeof(Ethernet_frame));
|
Ipv4_packet(eth_size - sizeof(Ethernet_frame));
|
||||||
|
|
||||||
uint8_t const prot = ip.protocol();
|
/* try to route via transport layer rules */
|
||||||
size_t const prot_size = ip.total_length() - ip.header_length() * 4;
|
|
||||||
void *const prot_base = _prot_base(prot, prot_size, ip);
|
|
||||||
Link_side_id const local = { ip.src(), _src_port(prot, prot_base),
|
|
||||||
ip.dst(), _dst_port(prot, prot_base) };
|
|
||||||
|
|
||||||
/* try to route via existing UDP/TCP links */
|
|
||||||
try {
|
try {
|
||||||
Link_side const &local_side = _links(prot).find_by_id(local);
|
uint8_t const prot = ip.protocol();
|
||||||
Link &link = local_side.link();
|
size_t const prot_size = ip.total_length() - ip.header_length() * 4;
|
||||||
bool const client = local_side.is_client();
|
void *const prot_base = _prot_base(prot, prot_size, ip);
|
||||||
Link_side &remote_side = client ? link.server() : link.client();
|
Link_side_id const local = { ip.src(), _src_port(prot, prot_base),
|
||||||
Interface &interface = remote_side.interface();
|
ip.dst(), _dst_port(prot, prot_base) };
|
||||||
if(_config().verbose()) {
|
|
||||||
log("Using ", protocol_name(prot), " link: ", link); }
|
|
||||||
|
|
||||||
_adapt_eth(eth, eth_size, remote_side.src_ip(), pkt, interface);
|
/* try to route via existing UDP/TCP links */
|
||||||
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());
|
|
||||||
|
|
||||||
interface._pass_ip(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 forward rules */
|
|
||||||
if (local.dst_ip == _router_ip()) {
|
|
||||||
try {
|
try {
|
||||||
Forward_rule const &rule =
|
Link_side const &local_side = _links(prot).find_by_id(local);
|
||||||
_forward_rules(prot).find_by_port(local.dst_port);
|
Link &link = local_side.link();
|
||||||
|
bool const client = local_side.is_client();
|
||||||
Interface &interface = rule.domain().interface().deref();
|
Link_side &remote_side = client ? link.server() : link.client();
|
||||||
|
Interface &interface = remote_side.interface();
|
||||||
if(_config().verbose()) {
|
if(_config().verbose()) {
|
||||||
log("Using forward rule: ", protocol_name(prot), " ", rule); }
|
log("Using ", protocol_name(prot), " link: ", link); }
|
||||||
|
|
||||||
_adapt_eth(eth, eth_size, rule.to(), pkt, interface);
|
_adapt_eth(eth, eth_size, remote_side.src_ip(), pkt, interface);
|
||||||
ip.dst(rule.to());
|
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());
|
||||||
|
|
||||||
|
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 forward rules */
|
||||||
|
if (local.dst_ip == _router_ip()) {
|
||||||
|
try {
|
||||||
|
Forward_rule const &rule =
|
||||||
|
_forward_rules(prot).find_by_port(local.dst_port);
|
||||||
|
|
||||||
|
Interface &interface = rule.domain().interface().deref();
|
||||||
|
if(_config().verbose()) {
|
||||||
|
log("Using forward rule: ", protocol_name(prot), " ", rule); }
|
||||||
|
|
||||||
|
_adapt_eth(eth, eth_size, rule.to(), pkt, interface);
|
||||||
|
ip.dst(rule.to());
|
||||||
|
_nat_link_and_pass(eth, eth_size, ip, prot, prot_base, prot_size,
|
||||||
|
local, interface);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
catch (Forward_rule_tree::No_match) { }
|
||||||
|
}
|
||||||
|
/* try to route via transport and permit rules */
|
||||||
|
try {
|
||||||
|
Transport_rule const &transport_rule =
|
||||||
|
_transport_rules(prot).longest_prefix_match(local.dst_ip);
|
||||||
|
|
||||||
|
Permit_rule const &permit_rule =
|
||||||
|
transport_rule.permit_rule(local.dst_port);
|
||||||
|
|
||||||
|
Interface &interface = permit_rule.domain().interface().deref();
|
||||||
|
if(_config().verbose()) {
|
||||||
|
log("Using ", protocol_name(prot), " rule: ", transport_rule,
|
||||||
|
" ", permit_rule); }
|
||||||
|
|
||||||
|
_adapt_eth(eth, eth_size, local.dst_ip, pkt, interface);
|
||||||
_nat_link_and_pass(eth, eth_size, ip, prot, prot_base, prot_size,
|
_nat_link_and_pass(eth, eth_size, ip, prot, prot_base, prot_size,
|
||||||
local, interface);
|
local, interface);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
catch (Forward_rule_tree::No_match) { }
|
catch (Transport_rule_list::No_match) { }
|
||||||
|
catch (Permit_single_rule_tree::No_match) { }
|
||||||
}
|
}
|
||||||
/* try to route via transport and permit rules */
|
catch (Interface::Bad_transport_protocol) { }
|
||||||
try {
|
|
||||||
Transport_rule const &transport_rule =
|
|
||||||
_transport_rules(prot).longest_prefix_match(local.dst_ip);
|
|
||||||
|
|
||||||
Permit_rule const &permit_rule =
|
|
||||||
transport_rule.permit_rule(local.dst_port);
|
|
||||||
|
|
||||||
Interface &interface = permit_rule.domain().interface().deref();
|
|
||||||
if(_config().verbose()) {
|
|
||||||
log("Using ", protocol_name(prot), " rule: ", transport_rule,
|
|
||||||
" ", permit_rule); }
|
|
||||||
|
|
||||||
_adapt_eth(eth, eth_size, local.dst_ip, pkt, interface);
|
|
||||||
_nat_link_and_pass(eth, eth_size, ip, prot, prot_base, prot_size,
|
|
||||||
local, interface);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
catch (Transport_rule_list::No_match) { }
|
|
||||||
catch (Permit_single_rule_tree::No_match) { }
|
|
||||||
|
|
||||||
/* try to route via IP rules */
|
/* try to route via IP rules */
|
||||||
try {
|
try {
|
||||||
Ip_rule const &rule =
|
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();
|
Interface &interface = rule.domain().interface().deref();
|
||||||
if(_config().verbose()) {
|
if(_config().verbose()) {
|
||||||
log("Using IP rule: ", rule); }
|
log("Using IP rule: ", rule); }
|
||||||
|
|
||||||
_adapt_eth(eth, eth_size, local.dst_ip, pkt, interface);
|
_adapt_eth(eth, eth_size, ip.dst(), pkt, interface);
|
||||||
interface._pass_ip(eth, eth_size, ip, prot, prot_base, prot_size);
|
interface._pass_ip(eth, eth_size, ip);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
catch (Ip_rule_list::No_match) { }
|
catch (Ip_rule_list::No_match) { }
|
||||||
@ -531,9 +543,6 @@ void Interface::_handle_eth(void *const eth_base,
|
|||||||
catch (Ethernet_frame::No_ethernet_frame) {
|
catch (Ethernet_frame::No_ethernet_frame) {
|
||||||
error("invalid ethernet frame"); }
|
error("invalid ethernet frame"); }
|
||||||
|
|
||||||
catch (Interface::Bad_transport_protocol) {
|
|
||||||
error("unknown transport layer protocol"); }
|
|
||||||
|
|
||||||
catch (Interface::Bad_network_protocol) {
|
catch (Interface::Bad_network_protocol) {
|
||||||
error("unknown network layer protocol"); }
|
error("unknown network layer protocol"); }
|
||||||
|
|
||||||
|
@ -104,12 +104,16 @@ class Net::Interface
|
|||||||
|
|
||||||
void _send(Ethernet_frame ð, Genode::size_t const eth_size);
|
void _send(Ethernet_frame ð, Genode::size_t const eth_size);
|
||||||
|
|
||||||
void _pass_ip(Ethernet_frame ð,
|
void _pass_prot(Ethernet_frame ð,
|
||||||
Genode::size_t const eth_size,
|
Genode::size_t const eth_size,
|
||||||
Ipv4_packet &ip,
|
Ipv4_packet &ip,
|
||||||
Genode::uint8_t const prot,
|
Genode::uint8_t const prot,
|
||||||
void *const prot_base,
|
void *const prot_base,
|
||||||
Genode::size_t const prot_size);
|
Genode::size_t const prot_size);
|
||||||
|
|
||||||
|
void _pass_ip(Ethernet_frame ð,
|
||||||
|
Genode::size_t const eth_size,
|
||||||
|
Ipv4_packet &ip);
|
||||||
|
|
||||||
void _continue_handle_eth(Packet_descriptor const &pkt);
|
void _continue_handle_eth(Packet_descriptor const &pkt);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user