diff --git a/repos/libports/run/nic_router.run b/repos/libports/run/nic_router.run index 9a0f390b08..3c1607b884 100644 --- a/repos/libports/run/nic_router.run +++ b/repos/libports/run/nic_router.run @@ -34,8 +34,8 @@ create_boot_directory proc test_1_config { } { if {[enable_test_1]} { return " [client_config t1_d1_c1_udp udp 10.0.98.55 10.0.98.33 255.255.255.0 nic_router 1337 10.0.98.33] - [client_config t1_d2_c1_udp udp 10.0.99.56 10.0.99.33 255.255.255.0 nic_router 1337 10.0.99.55] - [server_config t1_d2_s1_udp udp 10.0.99.55 10.0.99.33 255.255.255.0 nic_router 1337 ]" } + [client_config t1_d2_c1_udp udp 10.0.99.56 10.0.99.33 255.255.255.0 nic_router 999 10.0.99.55] + [server_config t1_d2_s1_udp udp 10.0.99.55 10.0.99.33 255.255.255.0 nic_router 999 ]" } } proc test_1_router_config { } { @@ -44,7 +44,7 @@ proc test_1_router_config { } { - + } } @@ -106,8 +106,8 @@ proc test_3_router_uplink_config { } { proc test_4_config { } { if {[enable_test_4]} { return " - [client_config t4_d0_c1_tcp http 10.0.2.201 10.0.2.1 255.255.255.0 nic_bridge 80 10.0.2.55] - [server_config t4_d1_s1_tcp http 192.168.1.18 192.168.1.1 255.255.255.0 nic_router 80 ]" } + [client_config t4_d0_c1_tcp http 10.0.2.201 10.0.2.1 255.255.255.0 nic_bridge 80 10.0.2.55] + [server_config t4_d1_s1_tcp http 192.168.1.18 192.168.1.1 255.255.255.0 nic_router 2048 ]" } } proc test_4_router_config { } { @@ -118,7 +118,7 @@ proc test_4_router_config { } { proc test_4_router_uplink_config { } { if {[enable_test_4]} { return { - } } + } } } # diff --git a/repos/os/src/server/nic_router/README b/repos/os/src/server/nic_router/README index 044bb8d9f0..f3b5f0f976 100644 --- a/repos/os/src/server/nic_router/README +++ b/repos/os/src/server/nic_router/README @@ -239,18 +239,19 @@ Port-forwarding rules These are examples for port-forwarding rules: -! +! ! Port-forwarding rules only apply to packets that come from the session of the -surrounding domain and are addressed to the router's IP identity at this -domain (Section [Basics]). Amongst those, 'tcp-forward' rules only apply to -the TCP packets and 'udp-forward' rules only to the UDP packets. The 'port' -attribute is compared with the packet's destination port. If a matching rule -is found, the IP destination of the packet is changed to the value of the 'to' -attribute. Then, the packet is routed to the domain given in the rule. Note -that the router accepts only system and registered ports (0 to 49151) for port -forwarding. +surrounding domain and are addressed to the router's IP identity at this domain +(Section [Basics]). Amongst those, 'tcp-forward' rules only apply to the TCP +packets and 'udp-forward' rules only to the UDP packets. The 'port' attribute +is compared with the packet's destination port. If a matching rule is found, +the IP destination of the packet is changed to the value of the 'to' attribute. +If the 'to_port' attribute is set and not zero, the packet's destination port +is changed to the attribute value. Then, the packet is routed to the domain +given in the rule. Note that the router accepts only system and registered +ports other than zero (1 to 49151) for port forwarding. For bidirectional traffic, you'll need only one port-forwarding rule describing the client-to-server direction. The server-sided domain doesn't @@ -628,7 +629,7 @@ following configuration: ! ! ! -! +! ! ! ! @@ -638,7 +639,8 @@ Amongst the packets that come from the uplink, only those that are addressed to 10.0.2.55 and TCP port 80, TCP port 70, or UDP port 69 are forwarded. All these packets are forwarded to Virtnet A. But beforehand, their IP destination is adapted. TCP-port-80 packets are redirected to 192.168.1.2, -TCP-port-70 packets to 192.168.1.3, and UDP-port-69 packets to 192.168.1.4. +TCP-port-70 packets to 192.168.1.3, and UDP-port-69 packets to +192.168.1.4:2048. Amongst the packets that come from Virtnet A, only those that match a link state at the uplink are forwarded, because the Virtnet-A domain contains no diff --git a/repos/os/src/server/nic_router/config.xsd b/repos/os/src/server/nic_router/config.xsd index 8c64b50be0..3cd521ef84 100644 --- a/repos/os/src/server/nic_router/config.xsd +++ b/repos/os/src/server/nic_router/config.xsd @@ -45,9 +45,10 @@ - - - + + + + diff --git a/repos/os/src/server/nic_router/forward_rule.cc b/repos/os/src/server/nic_router/forward_rule.cc index b26a5fd43a..30d8c6592e 100644 --- a/repos/os/src/server/nic_router/forward_rule.cc +++ b/repos/os/src/server/nic_router/forward_rule.cc @@ -40,17 +40,19 @@ Domain &Forward_rule::_find_domain(Domain_tree &domains, void Forward_rule::print(Output &output) const { - Genode::print(output, "port ", _port, " domain ", _domain, " to ", _to); + Genode::print(output, "port ", _port, " domain ", _domain, " to ip ", + _to_ip, " to port ", _to_port); } Forward_rule::Forward_rule(Domain_tree &domains, Xml_node const node) : - _port(node.attribute_value("port", Port(0))), - _to(node.attribute_value("to", Ipv4_address())), - _domain(_find_domain(domains, node)) + _port { node.attribute_value("port", Port(0)) }, + _to_ip { node.attribute_value("to", Ipv4_address()) }, + _to_port { node.attribute_value("to_port", Port(0)) }, + _domain { _find_domain(domains, node) } { - if (_port == Port(0) || !_to.valid() || dynamic_port(_port)) { + if (_port == Port(0) || !_to_ip.valid() || dynamic_port(_port)) { throw Invalid(); } } diff --git a/repos/os/src/server/nic_router/forward_rule.h b/repos/os/src/server/nic_router/forward_rule.h index ae33766d8c..c9b1a6477b 100644 --- a/repos/os/src/server/nic_router/forward_rule.h +++ b/repos/os/src/server/nic_router/forward_rule.h @@ -41,7 +41,8 @@ class Net::Forward_rule : public Genode::Avl_node private: Port const _port; - Ipv4_address const _to; + Ipv4_address const _to_ip; + Port const _to_port; Domain &_domain; static Domain &_find_domain(Domain_tree &domains, @@ -75,8 +76,9 @@ class Net::Forward_rule : public Genode::Avl_node ** Accessors ** ***************/ - Ipv4_address const &to() const { return _to; } - Domain &domain() const { return _domain; } + Ipv4_address const &to_ip() const { return _to_ip; } + Port const &to_port() const { return _to_port; } + Domain &domain() const { return _domain; } }; diff --git a/repos/os/src/server/nic_router/interface.cc b/repos/os/src/server/nic_router/interface.cc index 48237490ef..3a5f695ea7 100644 --- a/repos/os/src/server/nic_router/interface.cc +++ b/repos/os/src/server/nic_router/interface.cc @@ -1148,8 +1148,11 @@ void Interface::_handle_ip(Ethernet_frame ð, l3_protocol_name(prot), " ", rule); } Domain &remote_domain = rule.domain(); - _adapt_eth(eth, rule.to(), pkt, remote_domain); - ip.dst(rule.to()); + _adapt_eth(eth, rule.to_ip(), pkt, remote_domain); + ip.dst(rule.to_ip()); + if (!(rule.to_port() == Port(0))) { + _dst_port(prot, prot_base, rule.to_port()); + } _nat_link_and_pass(eth, size_guard, ip, prot, prot_base, prot_size, local_id, local_domain, remote_domain); return; @@ -1704,10 +1707,32 @@ void Interface::_update_udp_tcp_links(L3_protocol prot, find_by_port(link.client().dst_port()); /* if destination IP of forwarding changed, dismiss link */ - if (rule.to() != link.server().src_ip()) { + if (rule.to_ip() != link.server().src_ip()) { _dismiss_link_log(link, "other forward-rule to"); throw Dismiss_link(); } + /* + * If destination port of forwarding was set and then was + * modified or unset, dismiss link + */ + if (!(link.server().src_port() == link.client().dst_port())) { + if (!(rule.to_port() == link.server().src_port())) { + _dismiss_link_log(link, "other forward-rule to_port"); + throw Dismiss_link(); + } + } + /* + * If destination port of forwarding was not set and then was + * set, dismiss link + */ + else { + if (!(rule.to_port() == link.server().src_port()) && + !(rule.to_port() == Port(0))) + { + _dismiss_link_log(link, "new forward-rule to_port"); + throw Dismiss_link(); + } + } _update_link_check_nat(link, rule.domain(), prot, cln_dom); return; }