diff --git a/repos/os/src/server/nic_router/interface.cc b/repos/os/src/server/nic_router/interface.cc index 781bbe239d..4e989fc922 100644 --- a/repos/os/src/server/nic_router/interface.cc +++ b/repos/os/src/server/nic_router/interface.cc @@ -589,16 +589,19 @@ void Interface::_nat_link_and_pass(Ethernet_frame ð, { try { Pointer remote_port_alloc; - try { - Nat_rule &nat = remote_domain.nat_rules().find_by_domain(local_domain); - if(_config().verbose()) { - log("[", local_domain, "] using NAT rule: ", nat); } + remote_domain.nat_rules().find_by_domain( + local_domain, + [&] /* handle_match */ (Nat_rule &nat) + { + if(_config().verbose()) { + log("[", local_domain, "] using NAT rule: ", nat); } - _src_port(prot, prot_base, nat.port_alloc(prot).alloc()); - ip.src(remote_domain.ip_config().interface().address); - remote_port_alloc = nat.port_alloc(prot); - } - catch (Nat_rule_tree::No_match) { } + _src_port(prot, prot_base, nat.port_alloc(prot).alloc()); + ip.src(remote_domain.ip_config().interface().address); + remote_port_alloc = nat.port_alloc(prot); + }, + [&] /* no_match */ () { } + ); Link_side_id const remote_id = { ip.dst(), _dst_port(prot, prot_base), ip.src(), _src_port(prot, prot_base) }; _new_link(prot, local_id, remote_port_alloc, remote_domain, remote_id); @@ -1869,14 +1872,28 @@ void Interface::_update_link_check_nat(Link &link, _dismiss_link_log(link, "NAT IP"); throw Dismiss_link(); } - Nat_rule &nat = new_srv_dom.nat_rules().find_by_domain(cln_dom); - Port_allocator_guard &remote_port_alloc = nat.port_alloc(prot); - remote_port_alloc.alloc(link.server().dst_port()); - remote_port_alloc_ptr = remote_port_alloc; - link.handle_config(cln_dom, new_srv_dom, remote_port_alloc_ptr, _config()); - return; + bool done { false }; + new_srv_dom.nat_rules().find_by_domain( + cln_dom, + [&] /* handle_match */ (Nat_rule &nat) + { + Port_allocator_guard &remote_port_alloc = nat.port_alloc(prot); + remote_port_alloc.alloc(link.server().dst_port()); + remote_port_alloc_ptr = remote_port_alloc; + link.handle_config( + cln_dom, new_srv_dom, remote_port_alloc_ptr, _config()); + + done = true; + }, + [&] /* handle_no_match */ () + { + _dismiss_link_log(link, "no NAT rule"); + } + ); + if (done) { + return; + } } - catch (Nat_rule_tree::No_match) { _dismiss_link_log(link, "no NAT rule"); } catch (Port_allocator::Allocation_conflict) { _dismiss_link_log(link, "no NAT-port"); } catch (Port_allocator_guard::Out_of_indices) { _dismiss_link_log(link, "no NAT-port quota"); } throw Dismiss_link(); diff --git a/repos/os/src/server/nic_router/nat_rule.cc b/repos/os/src/server/nic_router/nat_rule.cc index 1839b8ce22..3395f60196 100644 --- a/repos/os/src/server/nic_router/nat_rule.cc +++ b/repos/os/src/server/nic_router/nat_rule.cc @@ -57,30 +57,6 @@ Nat_rule::Nat_rule(Domain_tree &domains, { } -Nat_rule &Nat_rule::find_by_domain(Domain &domain) -{ - if (&domain == &_domain) { - return *this; } - - bool const side = (addr_t)&domain > (addr_t)&_domain; - Nat_rule *const rule = Avl_node::child(side); - if (!rule) { - throw Nat_rule_tree::No_match(); } - - return rule->find_by_domain(domain); -} - - -Nat_rule &Nat_rule_tree::find_by_domain(Domain &domain) -{ - Nat_rule *const rule = first(); - if (!rule) { - throw No_match(); } - - return rule->find_by_domain(domain); -} - - void Nat_rule::print(Output &output) const { Genode::print(output, "domain ", _domain, diff --git a/repos/os/src/server/nic_router/nat_rule.h b/repos/os/src/server/nic_router/nat_rule.h index 500d444106..4f6853ce3a 100644 --- a/repos/os/src/server/nic_router/nat_rule.h +++ b/repos/os/src/server/nic_router/nat_rule.h @@ -59,6 +59,35 @@ class Net::Nat_rule : public Genode::Avl_node Nat_rule &find_by_domain(Domain &domain); + template + + void find_by_domain(Domain &domain, + HANDLE_MATCH_FN && handle_match, + HANDLE_NO_MATCH_FN && handle_no_match) + { + if (&domain != &_domain) { + + Nat_rule *const rule_ptr { + Avl_node::child( + (Genode::addr_t)&domain > (Genode::addr_t)&_domain) }; + + if (rule_ptr != nullptr) { + + rule_ptr->find_by_domain( + domain, handle_match, handle_no_match); + + } else { + + handle_no_match(); + } + + } else { + + handle_match(*this); + } + } + Port_allocator_guard &port_alloc(L3_protocol const prot); @@ -89,9 +118,22 @@ class Net::Nat_rule : public Genode::Avl_node struct Net::Nat_rule_tree : Avl_tree { - struct No_match : Genode::Exception { }; + template - Nat_rule &find_by_domain(Domain &domain); + void find_by_domain(Domain &domain, + HANDLE_MATCH_FN && handle_match, + HANDLE_NO_MATCH_FN && handle_no_match) + { + if (first() != nullptr) { + + first()->find_by_domain(domain, handle_match, handle_no_match); + + } else { + + handle_no_match(); + } + } }; #endif /* _NAT_RULE_H_ */