mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-21 03:55:04 +00:00
parent
f90964fdcc
commit
89085096d2
@ -2,6 +2,9 @@
|
||||
# Build
|
||||
#
|
||||
|
||||
# the lwip/http_clnt requires FOC
|
||||
assert_spec foc
|
||||
|
||||
set tcp_up_to_down_1 1
|
||||
set tcp_up_to_down_2 1
|
||||
set tcp_down_to_up_1 1
|
||||
@ -63,67 +66,40 @@ append config {
|
||||
<provides><service name="Nic"/></provides>
|
||||
<config rtt_sec="3" verbose="no">
|
||||
|
||||
<policy label="uplink" src="10.0.2.55">
|
||||
<ip dst="192.168.1.18/32" label="http_srv_1" />
|
||||
<ip dst="10.0.2.0/24">
|
||||
<tcp dst="29" label="commander"/>
|
||||
<tcp dst="80" label="keen" via="192.168.1.18" />
|
||||
<tcp dst="8080" via="192.168.1.72" />
|
||||
<tcp dst="10" label="earthworm"/>
|
||||
<tcp dst="2345" label="jim"/>
|
||||
</ip>
|
||||
<ip dst="10.0.0.0/16" label="link" />
|
||||
<ip dst="192.168.1.72/31" label="http_srv_2" />
|
||||
<ip dst="10.0.2.55/32">
|
||||
<tcp dst="132" label="samus" to="192.168.1.72"
|
||||
via="192.168.1.14" />
|
||||
<policy label_prefix="udp_client_1" domain="udp_client_1" />
|
||||
<policy label_prefix="http_client_3" domain="http_client_3" />
|
||||
<policy label_prefix="udp_client_3" domain="udp_client_3" />
|
||||
<policy label_prefix="http_server_1" domain="http_server_1" />
|
||||
<policy label_prefix="http_server_2" domain="http_server_2" />
|
||||
<policy label_prefix="udp_server_1" domain="udp_server_1" />
|
||||
<policy label_prefix="udp_server_2" domain="udp_server_2" />
|
||||
|
||||
<tcp dst="80" label="pacman" />
|
||||
<tcp dst="80" label="http_srv_1" to="192.168.1.18" />
|
||||
<tcp dst="8080" />
|
||||
<udp dst="1337" label="udp_srv_1" to="10.0.99.55"
|
||||
via="10.0.99.55" />
|
||||
<domain name="uplink" interface="10.0.2.55/24" gateway="10.0.2.1">
|
||||
<tcp-forward port="80" domain="http_server_1" to="192.168.1.18" />
|
||||
<tcp-forward port="8080" domain="http_server_2" to="192.168.2.72" />
|
||||
<udp-forward port="1" domain="udp_server_2" to="18.17.16.15" />
|
||||
<nat domain="http_client_3" tcp-ports="6" />
|
||||
<ip dst="217.13.192.0/24" domain="udp_client_3" />
|
||||
</domain>
|
||||
|
||||
<udp dst="1" label="udp_srv_2" to="18.17.16.15" />
|
||||
<tcp dst="8080" label="http_srv_2" to="192.168.1.72" />
|
||||
</ip>
|
||||
</policy>
|
||||
<domain name="udp_client_1" interface="10.0.98.33/24">
|
||||
<udp-forward port="1337" domain="udp_server_1" to="10.0.99.55" />
|
||||
</domain>
|
||||
|
||||
<policy label_prefix="http_srv_1" src="192.168.1.1" nat="yes" nat-tcp-ports="4">
|
||||
<ip dst="10.0.0.0/19" label="uplink" via="10.0.6.1" />
|
||||
<ip dst="10.0.2.128/25" label="uplink" via="10.0.3.1" />
|
||||
<ip dst="10.0.2.0/24" label="uplink" />
|
||||
</policy>
|
||||
<domain name="http_client_3" interface="100.200.0.1/24">
|
||||
<tcp dst="10.0.0.0/16">
|
||||
<permit port="2345" domain="uplink" />
|
||||
</tcp>
|
||||
</domain>
|
||||
|
||||
<policy label_prefix="http_srv_2" src="192.168.1.1" nat="yes" nat-tcp-ports="2">
|
||||
<ip dst="10.0.2.0/24" label="uplink" />
|
||||
</policy>
|
||||
<domain name="udp_client_3" interface="217.13.192.1/24">
|
||||
<ip dst="10.0.2.0/24" domain="uplink" />
|
||||
</domain>
|
||||
|
||||
<policy label_prefix="http_clnt_3" src="100.200.0.1" nat="yes" nat-tcp-ports="4">
|
||||
<ip dst="10.0.6.0/23" label="uplink" via="10.0.4.1" />
|
||||
<ip dst="10.0.0.0/16" />
|
||||
<ip dst="10.0.2.0/24" label="uplink" />
|
||||
</policy>
|
||||
|
||||
<policy label_prefix="udp_srv_1" src="10.0.99.33" nat="yes" nat-udp-ports="1">
|
||||
<ip dst="10.0.2.0/24" label="uplink" />
|
||||
<ip dst="10.0.98.0/24" label="udp_clnt_1" />
|
||||
</policy>
|
||||
|
||||
<policy label_prefix="udp_srv_2" src="18.17.15.14">
|
||||
<ip dst="10.0.2.0/24" label="uplink" />
|
||||
</policy>
|
||||
|
||||
<policy label_prefix="udp_clnt_1" src="10.0.98.33">
|
||||
<ip dst="10.0.98.33/32">
|
||||
<udp dst="1337" label="udp_srv_1" to="10.0.99.55"
|
||||
via="10.0.99.55"/>
|
||||
</ip>
|
||||
</policy>
|
||||
|
||||
<policy label_prefix="udp_clnt_3" src="217.13.192.1" nat="yes" nat-udp-ports="2">
|
||||
<ip dst="10.0.0.0/18" label="uplink" />
|
||||
</policy>
|
||||
<domain name="http_server_1" interface="192.168.1.1/24" />
|
||||
<domain name="http_server_2" interface="192.168.2.1/24" />
|
||||
<domain name="udp_server_1" interface="10.0.99.33/24" />
|
||||
<domain name="udp_server_2" interface="18.17.16.14/24" />
|
||||
|
||||
</config>
|
||||
<route>
|
||||
@ -136,10 +112,10 @@ append config {
|
||||
<resource name="RAM" quantum="10M"/>
|
||||
<provides><service name="Nic"/></provides>
|
||||
<config>
|
||||
<policy label_prefix="nic_router" ip_addr="10.0.2.55"/>
|
||||
<policy label_prefix="http_srv_3" ip_addr="10.0.2.11"/>
|
||||
<policy label_prefix="udp_clnt_2" ip_addr="10.0.2.123"/>
|
||||
<policy label_prefix="udp_srv_3" ip_addr="10.0.2.70"/>
|
||||
<policy label_prefix="nic_router" ip_addr="10.0.2.55" />
|
||||
<policy label_prefix="http_server_3" ip_addr="10.0.2.11" />
|
||||
<policy label_prefix="udp_client_2" ip_addr="10.0.2.123" />
|
||||
<policy label_prefix="udp_server_3" ip_addr="10.0.2.70" />
|
||||
</config>
|
||||
<route>
|
||||
<service name="Nic"> <child name="nic_drv"/> </service>
|
||||
@ -149,7 +125,7 @@ append config {
|
||||
|
||||
append_if $udp_down_to_down_1 config {
|
||||
|
||||
<start name="udp_clnt_1">
|
||||
<start name="udp_client_1">
|
||||
<binary name="test-lxip_udp_client" />
|
||||
<resource name="RAM" quantum="2M"/>
|
||||
<route>
|
||||
@ -166,7 +142,7 @@ append_if $udp_down_to_down_1 config {
|
||||
</config>
|
||||
</start>
|
||||
|
||||
<start name="udp_srv_1">
|
||||
<start name="udp_server_1">
|
||||
<binary name="test-lxip_udp_echo" />
|
||||
<resource name="RAM" quantum="2M"/>
|
||||
<route>
|
||||
@ -184,7 +160,7 @@ append_if $udp_down_to_down_1 config {
|
||||
|
||||
append_if $udp_up_to_down_1 config {
|
||||
|
||||
<start name="udp_clnt_2">
|
||||
<start name="udp_client_2">
|
||||
<binary name="test-lxip_udp_client" />
|
||||
<resource name="RAM" quantum="2M"/>
|
||||
<route>
|
||||
@ -201,7 +177,7 @@ append_if $udp_up_to_down_1 config {
|
||||
</config>
|
||||
</start>
|
||||
|
||||
<start name="udp_srv_2">
|
||||
<start name="udp_server_2">
|
||||
<binary name="test-lxip_udp_echo" />
|
||||
<resource name="RAM" quantum="2M"/>
|
||||
<route>
|
||||
@ -210,7 +186,7 @@ append_if $udp_up_to_down_1 config {
|
||||
</route>
|
||||
<config ld_verbose="yes">
|
||||
<libc stdout="/dev/log" stderr="/dev/log" ip_addr="18.17.16.15"
|
||||
gateway="18.17.15.14" netmask="255.255.0.0" port="1">
|
||||
gateway="18.17.16.14" netmask="255.255.0.0" port="1">
|
||||
|
||||
<vfs> <dir name="dev"> <log/> </dir> </vfs>
|
||||
</libc>
|
||||
@ -219,7 +195,7 @@ append_if $udp_up_to_down_1 config {
|
||||
|
||||
append_if $udp_down_to_up_1 config {
|
||||
|
||||
<start name="udp_clnt_3">
|
||||
<start name="udp_client_3">
|
||||
<binary name="test-lxip_udp_client" />
|
||||
<resource name="RAM" quantum="2M"/>
|
||||
<route>
|
||||
@ -236,7 +212,7 @@ append_if $udp_down_to_up_1 config {
|
||||
</config>
|
||||
</start>
|
||||
|
||||
<start name="udp_srv_3">
|
||||
<start name="udp_server_3">
|
||||
<binary name="test-lxip_udp_echo" />
|
||||
<resource name="RAM" quantum="2M"/>
|
||||
<route>
|
||||
@ -245,7 +221,7 @@ append_if $udp_down_to_up_1 config {
|
||||
</route>
|
||||
<config ld_verbose="yes">
|
||||
<libc stdout="/dev/log" stderr="/dev/log" ip_addr="10.0.2.70"
|
||||
netmask="255.255.255.0" gateway="10.0.2.1" port="65535">
|
||||
netmask="255.255.255.0" gateway="10.0.2.55" port="65535">
|
||||
|
||||
<vfs> <dir name="dev"> <log/> </dir> </vfs>
|
||||
</libc>
|
||||
@ -254,7 +230,7 @@ append_if $udp_down_to_up_1 config {
|
||||
|
||||
append_if $tcp_up_to_down_1 config {
|
||||
|
||||
<start name="http_srv_1">
|
||||
<start name="http_server_1">
|
||||
<binary name="test-lwip_httpsrv_static"/>
|
||||
<resource name="RAM" quantum="2M"/>
|
||||
<route>
|
||||
@ -269,7 +245,7 @@ append_if $tcp_up_to_down_1 config {
|
||||
</libc>
|
||||
</config>
|
||||
</start>
|
||||
<start name="http_clnt_1">
|
||||
<start name="http_client_1">
|
||||
<binary name="test-http_clnt"/>
|
||||
<resource name="RAM" quantum="2M"/>
|
||||
<route>
|
||||
@ -287,7 +263,7 @@ append_if $tcp_up_to_down_1 config {
|
||||
|
||||
append_if $tcp_up_to_down_2 config {
|
||||
|
||||
<start name="http_srv_2">
|
||||
<start name="http_server_2">
|
||||
<binary name="test-lwip_httpsrv_static"/>
|
||||
<resource name="RAM" quantum="2M"/>
|
||||
<route>
|
||||
@ -295,15 +271,15 @@ append_if $tcp_up_to_down_2 config {
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</route>
|
||||
<config>
|
||||
<libc stdout="/dev/log" stderr="/dev/log" ip_addr="192.168.1.72"
|
||||
netmask="255.255.255.0" gateway="192.168.1.1"
|
||||
<libc stdout="/dev/log" stderr="/dev/log" ip_addr="192.168.2.72"
|
||||
netmask="255.255.255.0" gateway="192.168.2.1"
|
||||
http_port="8080">
|
||||
|
||||
<vfs> <dir name="dev"> <log/> </dir> </vfs>
|
||||
</libc>
|
||||
</config>
|
||||
</start>
|
||||
<start name="http_clnt_2">
|
||||
<start name="http_client_2">
|
||||
<binary name="test-http_clnt"/>
|
||||
<resource name="RAM" quantum="2M"/>
|
||||
<route>
|
||||
@ -321,7 +297,7 @@ append_if $tcp_up_to_down_2 config {
|
||||
|
||||
append_if $tcp_down_to_up_1 config {
|
||||
|
||||
<start name="http_srv_3">
|
||||
<start name="http_server_3">
|
||||
<binary name="test-lwip_httpsrv_static"/>
|
||||
<resource name="RAM" quantum="2M"/>
|
||||
<route>
|
||||
@ -336,7 +312,7 @@ append_if $tcp_down_to_up_1 config {
|
||||
</libc>
|
||||
</config>
|
||||
</start>
|
||||
<start name="http_clnt_3">
|
||||
<start name="http_client_3">
|
||||
<binary name="test-http_clnt"/>
|
||||
<resource name="RAM" quantum="2M"/>
|
||||
<route>
|
||||
@ -378,17 +354,11 @@ append_platform_drv_boot_modules
|
||||
build_boot_image $boot_modules
|
||||
|
||||
# qemu config
|
||||
append qemu_args " -m 128 -nographic "
|
||||
append qemu_args " -m 256 -nographic "
|
||||
|
||||
append_if [have_spec x86] qemu_args " -net nic,model=e1000 "
|
||||
append_if [have_spec lan9118] qemu_args " -net nic,model=lan9118 "
|
||||
|
||||
append qemu_args " -net user -redir udp:5555::1337 "
|
||||
|
||||
#
|
||||
# FIXME: For unknown reasons, there seems to be a problem in the NIC router
|
||||
# with the destruction of NIC sessions that had TCP connections running.
|
||||
# This is why sometimes not all HTTP clients exit properly. Thus, look
|
||||
# merely for 4 client exits (at least 3xUDP 1xTCP) by now.
|
||||
#
|
||||
run_genode_until ".*child \".*_clnt_.\" exited with exit value 0.*\n.*child \".*_clnt_.\" exited with exit value 0.*\n.*child \".*_clnt_.\" exited with exit value 0.*\n.*child \".*_clnt_.\" exited with exit value 0.*\n" 100
|
||||
run_genode_until ".*Test done.*\n.*Test done.*\n.*Test done.*\n.*Test done.*\n.*Test done.*\n.*Test done.*\n" 60
|
||||
|
@ -11,10 +11,10 @@
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _MAC_H_
|
||||
#define _MAC_H_
|
||||
#ifndef _MAC_ALLOCATOR_H_
|
||||
#define _MAC_ALLOCATOR_H_
|
||||
|
||||
/* Genode */
|
||||
/* Genode includes */
|
||||
#include <base/exception.h>
|
||||
#include <net/ethernet.h>
|
||||
|
||||
@ -22,7 +22,7 @@ namespace Net {
|
||||
|
||||
/**
|
||||
* The MAC allocator is used to administer MAC addresses for
|
||||
* the proxy-ARP's client's.
|
||||
* NIC session clients.
|
||||
*/
|
||||
class Mac_allocator
|
||||
{
|
||||
@ -41,7 +41,7 @@ namespace Net {
|
||||
|
||||
public:
|
||||
|
||||
struct Alloc_failed : Genode::Exception {};
|
||||
class Alloc_failed : Genode::Exception {};
|
||||
|
||||
|
||||
/* reference MAC address */
|
||||
@ -77,4 +77,4 @@ namespace Net {
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _MAC_H_ */
|
||||
#endif /* _MAC_ALLOCATOR_H_ */
|
@ -20,13 +20,13 @@
|
||||
#include <nic/packet_allocator.h>
|
||||
#include <nic_session/rpc_object.h>
|
||||
#include <nic_session/connection.h>
|
||||
#include <nic_bridge/mac_allocator.h>
|
||||
#include <os/ram_session_guard.h>
|
||||
#include <os/session_policy.h>
|
||||
#include <root/component.h>
|
||||
#include <util/arg_string.h>
|
||||
|
||||
#include <address_node.h>
|
||||
#include <mac.h>
|
||||
#include <nic.h>
|
||||
#include <packet_handler.h>
|
||||
|
||||
|
@ -1,80 +0,0 @@
|
||||
/*
|
||||
* \brief MAC-address allocator
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2010-08-25
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _MAC_H_
|
||||
#define _MAC_H_
|
||||
|
||||
/* Genode */
|
||||
#include <base/exception.h>
|
||||
#include <net/ethernet.h>
|
||||
|
||||
namespace Net {
|
||||
|
||||
/**
|
||||
* The MAC allocator is used to administer MAC addresses for
|
||||
* the proxy-ARP's client's.
|
||||
*/
|
||||
class Mac_allocator
|
||||
{
|
||||
private:
|
||||
|
||||
/* limit available MAC addresses to one byte range */
|
||||
enum { MSB_MAX = 0xFF };
|
||||
|
||||
/* signals, whether most significant byte is in use */
|
||||
typedef struct
|
||||
{
|
||||
unsigned used : 1;
|
||||
} Msb;
|
||||
|
||||
Msb _msbs[MSB_MAX]; /* bitfield of MSBs */
|
||||
|
||||
public:
|
||||
|
||||
class Alloc_failed : Genode::Exception {};
|
||||
|
||||
|
||||
/* reference MAC address */
|
||||
static Mac_address mac_addr_base;
|
||||
|
||||
Mac_allocator() { Genode::memset(&_msbs, 0, sizeof(_msbs)); }
|
||||
|
||||
|
||||
/**
|
||||
* Allocates a new MAC address.
|
||||
*
|
||||
* \throws Alloc_failed if no more MAC addresses are available.
|
||||
* \return MAC address
|
||||
*/
|
||||
Mac_address alloc()
|
||||
{
|
||||
for (int i=0; i < MSB_MAX; i++) {
|
||||
if (!_msbs[i].used) {
|
||||
_msbs[i].used = 1;
|
||||
Mac_address mac = mac_addr_base;
|
||||
mac.addr[5] = i;
|
||||
return mac;
|
||||
}
|
||||
}
|
||||
throw Alloc_failed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees a formerly allocated MAC address.
|
||||
*/
|
||||
void free(Mac_address mac) {
|
||||
_msbs[(unsigned)mac.addr[5]].used = 0; }
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _MAC_H_ */
|
@ -11,7 +11,8 @@
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#include <mac.h>
|
||||
/* Genode includes */
|
||||
#include <nic_bridge/mac_allocator.h>
|
||||
|
||||
/**
|
||||
* We take the range 02:02:02:02:02:XX for our MAC address allocator,
|
@ -1,4 +1,4 @@
|
||||
TARGET = nic_bridge
|
||||
LIBS = base net
|
||||
SRC_CC = component.cc mac.cc main.cc nic.cc packet_handler.cc
|
||||
SRC_CC = component.cc mac_allocator.cc main.cc nic.cc packet_handler.cc
|
||||
INC_DIR += $(PRG_DIR)
|
||||
|
@ -7,202 +7,390 @@
|
||||
Brief
|
||||
#####
|
||||
|
||||
The nic_router component can be used to individually route IPv4 packets between
|
||||
multiple NIC sessions. Thereby, it can translate between different IP subnets.
|
||||
The component supports port forwarding, as well as the partitioning of the TCP
|
||||
and UDP port spaces.
|
||||
The 'nic_router' component can be used to individually route IPv4 packets
|
||||
between multiple NIC sessions. Thereby, it can translate between different
|
||||
subnets. The component supports IP routing, TCP and UDP routing, the
|
||||
partitioning of the TCP and UDP port spaces, port forwarding, and NAT.
|
||||
|
||||
|
||||
Basic routing
|
||||
#############
|
||||
Basics
|
||||
######
|
||||
|
||||
The nic_router component provides multiple sessions of the 'NIC' service
|
||||
The 'nic_router' component provides multiple sessions of the 'NIC' service
|
||||
(downlinks) while requesting one 'NIC' session (the uplink) itself. Through
|
||||
common Genode session routing, the uplink can be connected to any other NIC
|
||||
server. Inside the component, uplink and downlinks are treated the same. Its
|
||||
routing algorithm is ultimately controlled through the configuration. For each
|
||||
NIC session there must be a policy:
|
||||
routing algorithm is ultimately controlled through the configuration. NIC
|
||||
sessions are assigned to domains. Each domain represents one subnet and a
|
||||
corresponding routing configuration. Currently, each domain can contain
|
||||
only one NIC session at a time. The assigment of sessions to domains is
|
||||
controlled through the the common Genode session-policy tag:
|
||||
|
||||
! <policy label="uplink" src="192.168.1.3" />
|
||||
! <policy label="http_servers" src="10.0.2.1" />
|
||||
! <policy label_prefix="http_server" domain="http_servers" />
|
||||
! <policy label_prefix="imap_server" domain="imap_servers" />
|
||||
|
||||
The 'label' attribute must match the session label respectively 'uplink' for the
|
||||
uplink session. The 'src' attribute contains a static IPv4 identity that
|
||||
represents the nic_router with respect to that session. This identity is used
|
||||
when doing Network-Address-Translation to the session. Moreover, a policy tag
|
||||
may contain multiple 'ip' sub-tags:
|
||||
The domain name can be freely choosen but must be unique. There is no need
|
||||
to have a policy for the uplink. It is automatically assigned to the domain
|
||||
named "uplink". For each domain there must be a domain tag:
|
||||
|
||||
! <ip dst="192.168.1.0/24" label="uplink" />
|
||||
! <ip dst="10.0.0.0/16" label="http_servers" />
|
||||
! <domain name="uplink" interface="10.0.2.55/24" />
|
||||
! <domain name="http_servers" interface="192.168.1.18/24" />
|
||||
! <domain name="imap_servers" interface="192.168.2.17/24" />
|
||||
|
||||
Each 'ip' tag defines a routing rule for IPv4 packets that are sent by the
|
||||
session of the surrounding policy. Such a rule needs at least a 'dst' attribute
|
||||
that contains an IPv4 address prefix. When the nic_router receives an IPv4
|
||||
packet, it goes top-down through all the rules of the session, checking whether
|
||||
the packet destination matches the 'dst' attribute. The first rule that matches
|
||||
is inspected deeper. The next thing to be read is the 'label' attribute that
|
||||
names the target session of the rule. If the label points to a valid session,
|
||||
the packet could now be routed via this rule. But the IP rule is only remembered
|
||||
as fallback yet because it may contain sub-tags for preferred UDP and TCP
|
||||
routing:
|
||||
The 'interface' attribute defines two things at once. First, it tells the
|
||||
router which subnet can be found behind this domain, and second, which IP
|
||||
identity the router shall use in case it has to communicate as itself with
|
||||
the subnet.
|
||||
|
||||
! <udp dst="443" label="udp_servers" />
|
||||
! <tcp dst="80" label="http_servers" />
|
||||
Additionaly, the optional 'gateway' attribute can be set for a domain:
|
||||
|
||||
Those tags work pretty similar to the IP rules. The 'dst' attribute defines
|
||||
the port that a packet must be addressed to for a match. The 'label' attribute
|
||||
again points to the target session. If no matching UDP or TCP rule with a
|
||||
valid target session is found inside the matching IP rule, the nic_router
|
||||
falls back to the IP rule. If the target session of the matching IP rule isn't
|
||||
valid, it continues with the next matching IP rule, and so on.
|
||||
! <domain name="uplink" interface="10.0.2.55/24" gateway="10.0.2.1" />
|
||||
|
||||
It defines the standard gateway of the subnet behind this domain. If a packet
|
||||
shall be routed to this domain and its final IP destination does not match
|
||||
the subnet, its Ethernet destination is set to the MAC address of the gateway.
|
||||
If a gateway isn't given for a domain, such packets get dropped.
|
||||
|
||||
For each domain, the routing of packets from this domain can be configured
|
||||
individually by adding subtags to the corresponding domain tag. There are
|
||||
multiple types of subtags expressing different types of routing rules. The
|
||||
following table gives a brief overview over the different subtags and their
|
||||
meaning:
|
||||
|
||||
Subtag | Description
|
||||
---------------------------------------------------------------
|
||||
<tcp-forward port="X" /> | Port forwarding for TCP port X *
|
||||
---------------------------------------------------------------
|
||||
<udp-forward port="X" /> | Port forwarding for UDP port X *
|
||||
---------------------------------------------------------------
|
||||
<tcp dst="X"> | Routing TCP packets that target
|
||||
<permit-any /> | IP range X *
|
||||
</tcp> |
|
||||
---------------------------------------------------------------
|
||||
<udp dst="X"> | Routing UDP packets that target
|
||||
<permit-any /> | IP range X *
|
||||
</udp> |
|
||||
---------------------------------------------------------------
|
||||
<tcp dst="X"> | Routing TCP packets that target
|
||||
<permit port="Y" /> | IP range X and port Y or Z *
|
||||
<permit port="Z" /> |
|
||||
</tcp> |
|
||||
---------------------------------------------------------------
|
||||
<udp dst="X"> | Routing UDP packets that target
|
||||
<permit port="Y" /> | IP range X and port Y or Z *
|
||||
<permit port="Z" /> |
|
||||
</udp> |
|
||||
---------------------------------------------------------------
|
||||
<ip dst="X" /> | Routing IP packets that target
|
||||
| IP range X
|
||||
|
||||
A detailed explanation of the different routing rules is given in the
|
||||
following sections of this document. For all rules marked with a star, the
|
||||
router also keeps track of corresponding TCP connections and UDP
|
||||
pseudo-connections. With these so-called link states, corresponding reply
|
||||
packets are automatically routed back. The user doesn't have to add an
|
||||
additional back-routing rule for that.
|
||||
|
||||
Now having this variety of ways of routing a packet, it is absolutely legal
|
||||
that for one packet the domain may contain multiple rules that are applicable.
|
||||
And additionally, there may even be a link state that fits. The router's
|
||||
choice, however, is always deterministic. It follows a simple priority scheme:
|
||||
|
||||
1) Link states
|
||||
2) Port forwarding rules
|
||||
3) Longest prefix match amongst TCP respectively UDP rules
|
||||
3.1) Subrule that permits any port
|
||||
3.2) Subrules that permit specific ports
|
||||
4) Longest prefix match amongst IP rules
|
||||
|
||||
|
||||
Modify destination and gateway
|
||||
##############################
|
||||
IP rules
|
||||
########
|
||||
|
||||
All three, the 'ip', 'udp', and 'tcp' tag may have further attributes 'to'
|
||||
and/or 'via'. Both attributes define an IPv4 address. The address in the 'to'
|
||||
attribute replaces the IPv4 destination of an affected packet. The address in
|
||||
the 'via' attribute is the gateway for that rule. This means, when searching
|
||||
for the next Ethernet destination of an affected packet, the nic_router uses the
|
||||
'via' address as criterion. If not set, the 'via' address is always the IPv4
|
||||
destination of the packet. Hence, if only the 'to' attribute is set for a
|
||||
rule, the value is also used as 'via' address.
|
||||
These are examples for IP rules:
|
||||
|
||||
! <udp ... via="192.168.2.1" />
|
||||
! <ip ... to="10.0.2.234" via="192.168.2.1" />
|
||||
! <tcp ... to="10.0.2.234" />
|
||||
! <ip dst="10.0.2.0/24" domain="intranet" />
|
||||
! <ip dst="192.168.1.18/32" domain="my_server" />
|
||||
! <ip dst="0.0.0.0/0" domain="uplink" />
|
||||
|
||||
IP rules only apply to IPv4 packets from the session of the surrounding
|
||||
domain. The 'dst' attribute is compared with the IP destination of the packet.
|
||||
The rule with the longest prefix match is taken. The packet is then routed to
|
||||
the domain given in the rule.
|
||||
|
||||
IP rules work pretty simple. They merely affect the Ethernet header of a
|
||||
packet and they don't imply link-state tracking. This has consequences. First,
|
||||
IP rules do not automatically route back reply packets from the remote side.
|
||||
If you like to enable bidirectional communication via IP rules, both domains
|
||||
must have an appropriate rule in their domain tag. And second, IP rules do not
|
||||
consider a NAT configuration (Section [Configuring NAT]). As this could lead
|
||||
to unexpected leakage of local IP addresses and ports, you should use the
|
||||
combination of IP rules and NAT only with great care.
|
||||
|
||||
|
||||
Network address translation
|
||||
###########################
|
||||
TCP and UDP rules
|
||||
#################
|
||||
|
||||
The nic_router component can translate between different IPv4 subnets of clients,
|
||||
and "uplink". When enabled within the policy of a client:
|
||||
TCP and UDP rules must always be accompanied by one or more port permission
|
||||
rules to get effective:
|
||||
|
||||
! <policy ... nat="yes" />
|
||||
! <tcp dst="192.168.1.18/32">
|
||||
! <permit port="70" domain="gopher_servers" />
|
||||
! <permit port="80" domain="http_servers" />
|
||||
! </tcp>
|
||||
! <udp dst="10.0.2.0/24">
|
||||
! <permit-any domain="uplink" />
|
||||
! </udp>
|
||||
|
||||
the source address of all IPv4 packets of that client is replaced by the 'src'
|
||||
value of the applied target session. And the TCP/UDP source port is replaced
|
||||
by a dynamically allocated source port of the applied target session. There is
|
||||
an exception from the latter. If the source port of the packet matches a
|
||||
TCP/UDP rule of the applied target session, the packet is assumed to be a
|
||||
reply to a port-forwarded request from the counterside. In this case, the
|
||||
source port remains unchanged to enable the receiver to correlate the packet
|
||||
correctly.
|
||||
TCP rules only apply to TCP packets and UDP rules only to UDP packets from the
|
||||
session of the surrounding domain. The 'dst' attribute is compared with the IP
|
||||
destination of the packet. The rule with the longest prefix match is taken.
|
||||
If the rule contains a 'permit-any' subrule or a 'permit' subrule whose 'port'
|
||||
attribute matches the destination port of the packet, the packet is routed to
|
||||
the domain given in the subrule.
|
||||
|
||||
For partitioning the TCP/UDP port space, e.g., the source ports regarding the
|
||||
'uplink' session between different client sessions, one can configure how many
|
||||
ports may be used concurrently per client session:
|
||||
For bidirectional traffic, you'll need only one TCP or UDP rule describing the
|
||||
client-to-server direction. The server-sided domain doesn't need a rule as the
|
||||
router correlates replies to the client-sided rule (and only those) via a link
|
||||
state (Section [Link states]) that was created at the clients initial request.
|
||||
|
||||
! <policy ... nat="yes" nat-udp-ports="1001" />
|
||||
! <policy ... nat="yes" nat-tcp-ports="43" nat-udp-ports="21" />
|
||||
! <policy ... nat="yes" nat-tcp-ports="3" />
|
||||
TCP and UDP rules consider whether the router shall apply NAT
|
||||
(Section [Configuring NAT]) for the client side. If this is the case, source
|
||||
IP and port are replaced by the router's IP identity and a free port at the
|
||||
server-sided domain. Also the corresponding link state takes this in account
|
||||
to change back the destination of the replies.
|
||||
|
||||
The ports attribute contains the maximum number of ports that the nic_router
|
||||
assigns to the given session. This is necessary to avoid that a NIC session
|
||||
can run Denial-of-Service attacks against the nic_router by occupying all of
|
||||
its ports.
|
||||
|
||||
For both, UDP and TCP activities, the nic_router holds link states. The link
|
||||
states enable the nic_router to re-direct related packets from the counterside
|
||||
correctly without the need for additional routing rules. Such link state rules
|
||||
are the most preferred way of routing. Before the nic_router starts looking
|
||||
for IP, UDP, or TCP rules for a packet, it tries to find a matching rule
|
||||
amongst the link states.
|
||||
Port-forwarding rules
|
||||
#####################
|
||||
|
||||
As link state rules are created on demand and are bound to an active
|
||||
connection between two peers, it is desirable to clear them away as soon as
|
||||
they are not needed anymore. A precise algorithm for that enables the NIC
|
||||
sessions to get the maximum out of their resources (ports, RAM). A TCP state
|
||||
rule corresponding is held until the nic_router observes the four-way
|
||||
termination handshake of TCP and two times the estimated round-trip time has
|
||||
passed. The nic_router currently doesn't estimate any round-trip times by
|
||||
itself. Instead it expects an attribute 'rtt_sec' in its 'config' tag:
|
||||
These are examples for port-forwarding rules:
|
||||
|
||||
! <tcp-forward port="80" domain="http_servers" to="192.168.1.18" />
|
||||
! <udp-forward port="69" domain="tftp_servers" to="192.168.2.23" />
|
||||
|
||||
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.
|
||||
|
||||
For bidirectional traffic, you'll need only one port-forwarding rule
|
||||
describing the client-to-server direction. The server-sided domain doesn't
|
||||
need a rule as the router correlates replies to the client-sided rule (and
|
||||
only those) via a link state (Section [Link states]) that was created at the
|
||||
clients initial request.
|
||||
|
||||
It's in the nature of port forwarding that it comes along with NAT for the
|
||||
server side. However, the router only translates the server IP. The port
|
||||
remains unchanged. For the client side, port-forwarding rules apply NAT only
|
||||
when configured (Section [Configuring NAT]). If this is the case, client IP
|
||||
and port are translated.
|
||||
|
||||
|
||||
Link states
|
||||
###########
|
||||
|
||||
Each time a packet gets routed by using a TCP, UDP, or port-forwarding rule,
|
||||
the router creates a link state. From then on, all packets that belong
|
||||
to the exchange this first packet initiated and come from one of the two
|
||||
involved domains are routed by the link state and not by a rule. The costs
|
||||
for the link state are paid by the session that sent the first packet.
|
||||
|
||||
If a link state exists for a packet, it is unambiguously correlated through
|
||||
the source IP and port as well as the destination IP and port. This is also
|
||||
the case if the transfer includes NAT no matter of what kind or for which
|
||||
side.
|
||||
|
||||
It is desirable to discard a link state as soon as it is not needed anymore.
|
||||
The more precise the algorithm for that, the more efficient can NIC sessions
|
||||
use their resources (ports, RAM), and the less is the risk for DoS attacks.
|
||||
In order to meet this requirement, the router needs to know the round-trip
|
||||
time of the exchange behind a link state. This value is given through the
|
||||
attribute 'rtt_sec' in the router's configuration:
|
||||
|
||||
! <config rtt_sec="3"> ... </config>
|
||||
|
||||
This would set the round-trip time to three seconds which means that link
|
||||
state rules wait six seconds after a termination handshake before they close
|
||||
themselves. As UDP has no notion of connections, UDP state rules are simply
|
||||
held for a duration of two times the round-trip time after the last packet.
|
||||
This way, the peers can keep alive a UDP pseudo-connection by frequently
|
||||
sending empty packets.
|
||||
This would set the round-trip time to three seconds. The value is used for all
|
||||
link states so you should choose it with care. If it is too low, replies that
|
||||
normally need no routing rule may get lost. If it is too high, link states are
|
||||
held longer than necessary.
|
||||
|
||||
In general, each link state is discarded after a duration of two times the
|
||||
round-trip time without a matching packet. For UDP link states, this is the
|
||||
only rule and better known as hole punching. It allows peers to keep alive a
|
||||
UDP pseudo-connection through the router by frequently sending empty packets.
|
||||
The need for such a pseudo-connection arises from the router's demand to
|
||||
support NAT for UDP transfers and the consequence of keeping the corresponding
|
||||
mapping information.
|
||||
|
||||
The lifetime management of TCP link states, in contrast, is more complex. In
|
||||
addition to the common timeout, they may be discarded even if they still
|
||||
receive packets. This is the case when the router observed the four-way
|
||||
termination handshake of TCP and two times the round-trip time has passed.
|
||||
|
||||
|
||||
Configuring NAT
|
||||
###############
|
||||
|
||||
In contrast to routing rules that affect packets coming from their domain,
|
||||
NAT rules affect packets that go to their domain:
|
||||
|
||||
! <domain name="uplink" interface="10.0.2.55/24">
|
||||
! <nat domain="http_client" tcp-ports="6" />
|
||||
! </domain>
|
||||
|
||||
This would tell the router to apply NAT for the HTTP client when it speaks to
|
||||
the uplink. This means, it affects all packets from the HTTP client that get
|
||||
routed to the uplink by using a UDP, TCP, or port-forwarding rule respectively
|
||||
a corresponding link state. If this is the case, the packet's source IP
|
||||
address is changed to "10.0.2.55" and the source port is replaced by a free
|
||||
source port of the router. When saying "free source port" this actually means
|
||||
a port that the router currently doesn't use at the destination domain. So,
|
||||
at each domain, the router has two complete port spaces for source NAT
|
||||
available. One for UDP and one for TCP. Each port space contains the IANA
|
||||
dynamic port range 49152 to 65535.
|
||||
|
||||
As you can see, the NAT rule also has a 'tcp-ports' attribute. It restricts
|
||||
how many TCP source ports of the uplink the HTTP client may use at a time. The
|
||||
same goes also for UDP:
|
||||
|
||||
! <nat domain="tftp_client" udp-ports="13" />
|
||||
|
||||
And even combined:
|
||||
|
||||
! <nat domain="intranet" tcp-ports="43" udp-ports="21" />
|
||||
|
||||
If one of the two attributes is not set, this means that no port shall be used
|
||||
for this protocol which effectively disables it. Thus, at least one of the two
|
||||
attributes must be set for the NAT rule to be sensible. Restricting the port
|
||||
usage is necessary to avoid that a client can run Denial-of-Service attacks
|
||||
against the destination domain by occupying all of its ports.
|
||||
|
||||
|
||||
Examples
|
||||
########
|
||||
|
||||
This paragraph will list and explain some interesting configuration snippets.
|
||||
A comprehensive example of how to use the nic_router can be found in the test
|
||||
script 'libports/run/nic_router.run' .
|
||||
This section will list and explain some interesting configuration snippets. A
|
||||
comprehensive example of how to use the router can be found in the test script
|
||||
'libports/run/nic_router.run'. The environment for the examples shall be as
|
||||
follows. There are two virtual subnets 192.168.1.0/24 and 192.168.2.0/24 that
|
||||
connect as Virtnet A and B to the router. The standard gateway of the virtual
|
||||
networks is the NIC router with IP 192.168.*.1 . The router's uplink leads to
|
||||
the NIC driver that connects the machine with your home network 10.0.2.0/24.
|
||||
Your home network is connected to the internet through its standard gateway
|
||||
10.0.2.1 .
|
||||
|
||||
|
||||
Accessing a private server network
|
||||
==================================
|
||||
Connecting local networks
|
||||
=========================
|
||||
|
||||
In this example, we assume that there is a HTTP server "behind" the nic_router
|
||||
(downlink) listening at port 80. Through the uplink session, several clients
|
||||
may ask the nic_router for HTTP. The nic_router has the following
|
||||
configuration:
|
||||
Let's assume we simply want the virtual networks and the home network to be
|
||||
able to talk to each other. Furthermore, the virtual networks shall be able to
|
||||
use the internet connection of your home network. The router would have the
|
||||
following configuration:
|
||||
|
||||
! <policy label="uplink" src="10.0.2.55">
|
||||
! <ip dst="10.0.2.55/32">
|
||||
! <tcp dst="80" label="http_servers" to="192.168.1.2" />
|
||||
! </ip>
|
||||
! </policy>
|
||||
! <policy label_prefix="virtnet_a" domain="virtnet_a" />
|
||||
! <policy label_prefix="virtnet_b" domain="virtnet_b" />
|
||||
!
|
||||
! <policy label="http_servers" src="192.168.1.1" nat="yes" nat-tcp-ports="30">
|
||||
! <ip dst="10.0.2.0/24" label="uplink" />
|
||||
! </policy>
|
||||
|
||||
The uplink IP rule matches only packets that directly address the nic_router's
|
||||
uplink identity. Amongst those packets, the ones to TCP port 80 also match the
|
||||
TCP sub-rule. The TCP sub-rule is rated higher than the surrounding IP rule
|
||||
and thus gets applied. Consequently, the nic_router replaces the IPv4
|
||||
destination of the packets with the 'to' value (which is the local server
|
||||
address), then looks up and installs the next Ethernet destination for the
|
||||
given server address, and finally sends the packet on the servers NIC session.
|
||||
All other packets from the uplink are dropped. Even those that address the
|
||||
nic_router directly but with another port. This is because, although the IP
|
||||
rule still matches, it specifies no target session.
|
||||
|
||||
If the server sends back reply packets to the client, they address the clients
|
||||
public IP because the IPv4 source of the previous request wasn't modified.
|
||||
Thus, these packets match the IP rule in the server policy and get forwarded
|
||||
to the uplink. But furthermore, the nic_router is configured do NAT for the
|
||||
server (with 30 simultaneous TCP connections allowed). Hence, the nic_router
|
||||
replaces the IPv4 source in the server replies by its uplink identity
|
||||
'10.0.2.55'. The source port, at the other hand, is not replaced because it
|
||||
matches a TCP rule in the uplink policy. This way, the client is able to
|
||||
associate the replies to its TCP connection with the server.
|
||||
|
||||
|
||||
Using public servers from a private network
|
||||
===========================================
|
||||
|
||||
Let's assume we have a UDP client "behind" the nic_router and like to talk to an
|
||||
"outside" server. An example configuration for that would be:
|
||||
|
||||
! <policy label="uplink" src="10.0.2.55" />
|
||||
! <domain name="uplink" interface="10.0.2.55/24" gateway="10.0.2.1/24">
|
||||
! <ip dst="192.168.1.0/24" domain="virtnet_a"/>
|
||||
! <ip dst="192.168.2.0/24" domain="virtnet_b"/>
|
||||
! </domain>
|
||||
!
|
||||
! <policy label="udp_clients" src="100.200.0.1" nat="yes" nat-udp-ports="2">
|
||||
! <ip dst="10.0.2.0/24" label="uplink" />
|
||||
! </policy>
|
||||
! <domain name="virtnet_a" interface="192.168.1.1/24">
|
||||
! <ip dst="192.168.2.0/24" domain="virtnet_b"/>
|
||||
! <ip dst="0.0.0.0/0" domain="uplink"/>
|
||||
! </domain>
|
||||
!
|
||||
! <domain name="virtnet_b" interface="192.168.2.1/24">
|
||||
! <ip dst="192.168.1.0/24" domain="virtnet_a"/>
|
||||
! <ip dst="0.0.0.0/0" domain="uplink"/>
|
||||
! </domain>
|
||||
|
||||
UDP packets from the client to the public network match the clients IP rule
|
||||
and therefore are forwarded to the uplink. Because of the NAT attributes, the
|
||||
packets are modified to have '10.0.2.55' as IPv4 source and a free UDP port of
|
||||
the uplink session as source port. The client is allowed to open a maximum of
|
||||
two such connections at a time. The uplink doesn't need any rules to forward
|
||||
the replies for the UDP client correctly as long as the server replies in
|
||||
time. This is because the nic_router still holds the link state of the initial
|
||||
UDP packet from the client and can use it to map back IP address and port.
|
||||
IP packets from Virtnet A and uplink that target an IP address 192.168.2.* are
|
||||
routed to Virtnet B. IP packets from Virtnet B and uplink that target an IP
|
||||
address 192.168.1.* are routed to Virtnet A. Packets that are addressed to
|
||||
hosts in the same local network should never reach the router as they can be
|
||||
transmitted directly. If there's a packet from one of the virtual networks
|
||||
that doesn't target 192.168.1.* or 192.168.2.*, the IP 0.0.0.0/0 rules route
|
||||
them to the uplink. If these packets target an IP 10.0.2.*, the router sends
|
||||
them directly to the host in your home network. Otherwise, the router sends
|
||||
them to your gateway 10.0.2.1 . Note that none of the packets is modified on
|
||||
layer 2 or higher, so, no NAT is done by the router to hide the virtual
|
||||
networks.
|
||||
|
||||
|
||||
Limitations
|
||||
###########
|
||||
Clients in a private network
|
||||
============================
|
||||
|
||||
Currently, different client sessions should not share the same subnet to be able
|
||||
to communicate with each other, because forwarding broadcast packets (e.g., ARP
|
||||
packets) between different clients of the same subnet is not supported yet.
|
||||
Now we have some clients in Virtnet A that like to talk to the internet as
|
||||
well as to the home network. We want them to be hidden via NAT when they do so
|
||||
and to be limited to HTTP+TLS/SSL and IMAP+TLS/SSL when talking to the
|
||||
internet. The router would have the following configuration:
|
||||
|
||||
! <policy label_prefix="virtnet_a" domain="virtnet_a" />
|
||||
! <policy label_prefix="virtnet_b" domain="virtnet_b" />
|
||||
!
|
||||
! <domain name="uplink" interface="10.0.2.55/24" gateway="10.0.2.1/24">
|
||||
! <nat domain="virtnet_a" tcp_ports="1000" udp_ports="1000">
|
||||
! </domain>
|
||||
!
|
||||
! <domain name="virtnet_a" interface="192.168.1.1/24">
|
||||
! <tcp dst="10.0.2.0/24"><permit-any domain="uplink" /></tcp>
|
||||
! <udp dst="10.0.2.0/24"><permit-any domain="uplink" /></udp>
|
||||
! <tcp dst="0.0.0.0/0">
|
||||
! <permit port="443" domain="uplink" />
|
||||
! <permit port="993" domain="uplink" />
|
||||
! </tcp>
|
||||
! </domain>
|
||||
|
||||
From the packets that come from Virtnet A, those that target an IP 10.0.2.*
|
||||
are routed to the uplink without inspecting the port. At the uplink, the
|
||||
router notices that it shall apply NAT for Virtnet A. It replaces the source
|
||||
IP with 10.0.2.55 and allocates one of its uplink source ports for the
|
||||
exchange. On replies to Virtnet-A packets from the home network, the router
|
||||
translates IP and port back using the corresponding link state. For packets
|
||||
from Virtnet A that target other IPs, only the 0.0.0.0/0 rule applies and only
|
||||
if the packet targets TCP port 443 or 993. Both ports route the packet to the
|
||||
uplink where, again, NAT is applied and the packets are sent to the gateway
|
||||
10.0.2.1 .
|
||||
|
||||
|
||||
Servers in a private network
|
||||
============================
|
||||
|
||||
In this example, we assume that there are three servers in Virtnet A. An HTTP
|
||||
server at port 80 with IP 192.168.1.2, a GOPHER server at port 70 with IP
|
||||
192.168.1.3, and a TFTP server at port 69 with IP 192.168.1.4 . Now you want
|
||||
the servers (and only them) to be reachable to the home network via the
|
||||
router's IP and to the internet via your gateway. The router would have the
|
||||
following configuration:
|
||||
|
||||
! <policy label_prefix="virtnet_a" domain="virtnet_a" />
|
||||
! <policy label_prefix="virtnet_b" domain="virtnet_b" />
|
||||
!
|
||||
! <domain name="uplink" interface="10.0.2.55/24" gateway="10.0.2.1">
|
||||
! <tcp-forward port="80" domain="virtnet_a" to="192.168.1.2" />
|
||||
! <tcp-forward port="70" domain="virtnet_a" to="192.168.1.3" />
|
||||
! <udp-forward port="69" domain="virtnet_a" to="192.168.1.4" />
|
||||
! </domain>
|
||||
!
|
||||
! <domain name="virtnet_a" interface="192.168.1.1/24" />
|
||||
! <domain name="virtnet_b" interface="192.168.1.1/24" />
|
||||
|
||||
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.
|
||||
|
||||
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
|
||||
rules. Thus, Virtnet A can only talk to the uplink in the context of
|
||||
TCP-connections or UDP pseudo-connections that were opened by clients behind
|
||||
the uplink. The servers IP addresses never leave Virtnet A.
|
||||
|
@ -18,40 +18,58 @@ using namespace Net;
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
Arp_cache_entry::Arp_cache_entry(Ipv4_address ip_addr, Mac_address mac_addr)
|
||||
/*********************
|
||||
** Arp_cache_entry **
|
||||
*********************/
|
||||
|
||||
Arp_cache_entry::Arp_cache_entry(Ipv4_address const &ip,
|
||||
Mac_address const &mac)
|
||||
:
|
||||
_ip_addr(ip_addr), _mac_addr(mac_addr)
|
||||
_ip(ip), _mac(mac)
|
||||
{ }
|
||||
|
||||
|
||||
bool Arp_cache_entry::higher(Arp_cache_entry *entry)
|
||||
bool Arp_cache_entry::_higher(Ipv4_address const &ip) const
|
||||
{
|
||||
return (memcmp(&entry->_ip_addr.addr, &_ip_addr.addr,
|
||||
sizeof(_ip_addr.addr)) > 0);
|
||||
return memcmp(ip.addr, _ip.addr, sizeof(_ip.addr)) > 0;
|
||||
}
|
||||
|
||||
|
||||
Arp_cache_entry &Arp_cache_entry::find_by_ip_addr(Ipv4_address ip_addr)
|
||||
Arp_cache_entry const &
|
||||
Arp_cache_entry::find_by_ip(Ipv4_address const &ip) const
|
||||
{
|
||||
if (ip_addr == _ip_addr) {
|
||||
if (ip == _ip) {
|
||||
return *this; }
|
||||
|
||||
bool const side =
|
||||
memcmp(&ip_addr.addr, _ip_addr.addr, sizeof(_ip_addr.addr)) > 0;
|
||||
|
||||
Arp_cache_entry * entry = Avl_node<Arp_cache_entry>::child(side);
|
||||
Arp_cache_entry const *const entry = child(_higher(ip));
|
||||
if (!entry) {
|
||||
throw Arp_cache::No_matching_entry(); }
|
||||
throw Arp_cache::No_match(); }
|
||||
|
||||
return entry->find_by_ip_addr(ip_addr);
|
||||
return entry->find_by_ip(ip);
|
||||
}
|
||||
|
||||
|
||||
Arp_cache_entry &Arp_cache::find_by_ip_addr(Ipv4_address ip_addr)
|
||||
/***************
|
||||
** Arp_cache **
|
||||
***************/
|
||||
|
||||
void Arp_cache::new_entry(Ipv4_address const &ip, Mac_address const &mac)
|
||||
{
|
||||
Arp_cache_entry * const entry = first();
|
||||
if (!entry) {
|
||||
throw No_matching_entry(); }
|
||||
|
||||
return entry->find_by_ip_addr(ip_addr);
|
||||
if (_entries[_curr].constructed()) { remove(&(*_entries[_curr])); }
|
||||
_entries[_curr].construct(ip, mac);
|
||||
insert(&(*_entries[_curr]));
|
||||
if (_curr < NR_OF_ENTRIES - 1) {
|
||||
_curr++;
|
||||
} else {
|
||||
_curr = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Arp_cache_entry const &Arp_cache::find_by_ip(Ipv4_address const &ip) const
|
||||
{
|
||||
if (!first()) {
|
||||
throw No_match(); }
|
||||
|
||||
return first()->find_by_ip(ip);
|
||||
}
|
||||
|
@ -11,54 +11,74 @@
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _ARP_CACHE_H_
|
||||
#define _ARP_CACHE_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <net/ipv4.h>
|
||||
#include <net/ethernet.h>
|
||||
#include <util/avl_tree.h>
|
||||
|
||||
#ifndef _ARP_CACHE_H_
|
||||
#define _ARP_CACHE_H_
|
||||
#include <util/volatile_object.h>
|
||||
|
||||
namespace Net {
|
||||
|
||||
class Arp_cache;
|
||||
class Arp_cache_entry;
|
||||
using Arp_cache_entry_slot = Genode::Lazy_volatile_object<Arp_cache_entry>;
|
||||
}
|
||||
|
||||
|
||||
class Net::Arp_cache_entry : public Genode::Avl_node<Arp_cache_entry>
|
||||
{
|
||||
private:
|
||||
|
||||
Ipv4_address const _ip_addr;
|
||||
Mac_address const _mac_addr;
|
||||
Ipv4_address const _ip;
|
||||
Mac_address const _mac;
|
||||
|
||||
bool _higher(Ipv4_address const &ip) const;
|
||||
|
||||
public:
|
||||
|
||||
Arp_cache_entry(Ipv4_address ip_addr, Mac_address mac_addr);
|
||||
Arp_cache_entry(Ipv4_address const &ip, Mac_address const &mac);
|
||||
|
||||
Arp_cache_entry &find_by_ip_addr(Ipv4_address ip_addr);
|
||||
Arp_cache_entry const &find_by_ip(Ipv4_address const &ip) const;
|
||||
|
||||
|
||||
/**************
|
||||
** Avl_node **
|
||||
**************/
|
||||
|
||||
bool higher(Arp_cache_entry *entry);
|
||||
bool higher(Arp_cache_entry *entry) { return _higher(entry->_ip); }
|
||||
|
||||
|
||||
/***************
|
||||
** Accessors **
|
||||
***************/
|
||||
|
||||
Ipv4_address ip_addr() const { return _ip_addr; }
|
||||
Mac_address mac_addr() const { return _mac_addr; }
|
||||
Mac_address const &mac() const { return _mac; }
|
||||
};
|
||||
|
||||
struct Net::Arp_cache : Genode::Avl_tree<Arp_cache_entry>
|
||||
{
|
||||
struct No_matching_entry : Genode::Exception { };
|
||||
|
||||
Arp_cache_entry &find_by_ip_addr(Ipv4_address ip_addr);
|
||||
class Net::Arp_cache : public Genode::Avl_tree<Arp_cache_entry>
|
||||
{
|
||||
private:
|
||||
|
||||
enum {
|
||||
ENTRIES_SIZE = 1024 * sizeof(Genode::addr_t),
|
||||
NR_OF_ENTRIES = ENTRIES_SIZE / sizeof(Arp_cache_entry),
|
||||
};
|
||||
|
||||
Arp_cache_entry_slot _entries[NR_OF_ENTRIES];
|
||||
bool _init = true;
|
||||
unsigned _curr = 0;
|
||||
|
||||
public:
|
||||
|
||||
struct No_match : Genode::Exception { };
|
||||
|
||||
void new_entry(Ipv4_address const &ip, Mac_address const &mac);
|
||||
|
||||
Arp_cache_entry const &find_by_ip(Ipv4_address const &ip) const;
|
||||
};
|
||||
|
||||
#endif /* _ARP_CACHE_H_ */
|
||||
|
@ -13,25 +13,27 @@
|
||||
|
||||
/* local includes */
|
||||
#include <arp_waiter.h>
|
||||
#include <arp_cache.h>
|
||||
#include <interface.h>
|
||||
|
||||
using namespace Net;
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
Arp_waiter::Arp_waiter(Interface &interface, Ipv4_address ip_addr,
|
||||
Ethernet_frame ð, size_t const eth_size,
|
||||
Packet_descriptor &packet)
|
||||
Arp_waiter::Arp_waiter(Interface &src,
|
||||
Interface &dst,
|
||||
Ipv4_address const &ip,
|
||||
Packet_descriptor const &packet)
|
||||
:
|
||||
_interface(interface), _ip_addr(ip_addr), _eth(eth), _eth_size(eth_size),
|
||||
_src_le(this), _src(src), _dst_le(this), _dst(dst), _ip(ip),
|
||||
_packet(packet)
|
||||
{ }
|
||||
|
||||
|
||||
bool Arp_waiter::new_arp_cache_entry(Arp_cache_entry &entry)
|
||||
{
|
||||
if (!(entry.ip_addr() == _ip_addr)) { return false; }
|
||||
_interface.continue_handle_ethernet(&_eth, _eth_size, &_packet);
|
||||
return true;
|
||||
_src.own_arp_waiters().insert(&_src_le);
|
||||
_dst.foreign_arp_waiters().insert(&_dst_le);
|
||||
}
|
||||
|
||||
|
||||
Arp_waiter::~Arp_waiter()
|
||||
{
|
||||
_src.own_arp_waiters().remove(&_src_le);
|
||||
_dst.foreign_arp_waiters().remove(&_dst_le);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* \brief Aspect of waiting for an ARP reply
|
||||
* \brief Remember packets that wait for ARP replies at different interfaces
|
||||
* \author Martin Stein
|
||||
* \date 2016-08-19
|
||||
*/
|
||||
@ -11,50 +11,52 @@
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <net/ipv4.h>
|
||||
#include <nic_session/nic_session.h>
|
||||
#include <util/list.h>
|
||||
|
||||
#ifndef _ARP_WAITER_H_
|
||||
#define _ARP_WAITER_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <net/ipv4.h>
|
||||
#include <util/list.h>
|
||||
#include <nic_session/nic_session.h>
|
||||
|
||||
namespace Net {
|
||||
|
||||
using ::Nic::Packet_descriptor;
|
||||
using Packet_descriptor = ::Nic::Packet_descriptor;
|
||||
class Interface;
|
||||
class Ethernet_frame;
|
||||
class Arp_waiter;
|
||||
class Arp_cache_entry;
|
||||
using Arp_waiter_list = Genode::List<Arp_waiter>;
|
||||
using Arp_waiter_list_element = Genode::List_element<Arp_waiter>;
|
||||
using Arp_waiter_list = Genode::List<Arp_waiter_list_element >;
|
||||
}
|
||||
|
||||
class Net::Arp_waiter : public Genode::List<Arp_waiter>::Element
|
||||
|
||||
class Net::Arp_waiter
|
||||
{
|
||||
private:
|
||||
|
||||
Interface &_interface;
|
||||
Ipv4_address _ip_addr;
|
||||
Ethernet_frame &_eth;
|
||||
Genode::size_t const _eth_size;
|
||||
Packet_descriptor &_packet;
|
||||
Arp_waiter_list_element _src_le;
|
||||
Interface &_src;
|
||||
Arp_waiter_list_element _dst_le;
|
||||
Interface &_dst;
|
||||
Ipv4_address const _ip;
|
||||
Packet_descriptor const _packet;
|
||||
|
||||
public:
|
||||
|
||||
Arp_waiter(Interface &interface, Ipv4_address ip_addr,
|
||||
Ethernet_frame ð, Genode::size_t const eth_size,
|
||||
Packet_descriptor &packet);
|
||||
Arp_waiter(Interface &src,
|
||||
Interface &dst,
|
||||
Ipv4_address const &ip,
|
||||
Packet_descriptor const &packet);
|
||||
|
||||
bool new_arp_cache_entry(Arp_cache_entry &entry);
|
||||
~Arp_waiter();
|
||||
|
||||
|
||||
/***************
|
||||
** Accessors **
|
||||
***************/
|
||||
|
||||
Interface &interface() const { return _interface; }
|
||||
Ethernet_frame ð() const { return _eth; }
|
||||
Genode::size_t eth_size() const { return _eth_size; }
|
||||
Interface &src() const { return _src; }
|
||||
Ipv4_address const &ip() const { return _ip; }
|
||||
Packet_descriptor const &packet() const { return _packet; }
|
||||
};
|
||||
|
||||
#endif /* _ARP_WAITER_H_ */
|
||||
|
@ -11,59 +11,63 @@
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <os/session_policy.h>
|
||||
|
||||
/* local includes */
|
||||
#include <component.h>
|
||||
#include <arp_cache.h>
|
||||
#include <port_allocator.h>
|
||||
#include <configuration.h>
|
||||
|
||||
using namespace Net;
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
bool Session_component::link_state()
|
||||
{
|
||||
warning(__func__, " not implemented");
|
||||
return false;
|
||||
}
|
||||
/**************************
|
||||
** Communication_buffer **
|
||||
**************************/
|
||||
|
||||
|
||||
void Session_component::link_state_sigh(Signal_context_capability sigh)
|
||||
{
|
||||
warning(__func__, " not implemented");
|
||||
}
|
||||
|
||||
|
||||
Net::Session_component::Session_component(Allocator &allocator,
|
||||
size_t const amount,
|
||||
size_t const tx_buf_size,
|
||||
size_t const rx_buf_size,
|
||||
Mac_address mac,
|
||||
Server::Entrypoint &ep,
|
||||
Mac_address router_mac,
|
||||
Ipv4_address router_ip,
|
||||
char const *args,
|
||||
Port_allocator &tcp_port_alloc,
|
||||
Port_allocator &udp_port_alloc,
|
||||
Tcp_proxy_list &tcp_proxys,
|
||||
Udp_proxy_list &udp_proxys,
|
||||
unsigned const rtt_sec,
|
||||
Interface_tree &interface_tree,
|
||||
Arp_cache &arp_cache,
|
||||
Arp_waiter_list &arp_waiters,
|
||||
bool verbose)
|
||||
Communication_buffer::Communication_buffer(Ram_session &ram,
|
||||
Genode::size_t const size)
|
||||
:
|
||||
Guarded_range_allocator(allocator, amount),
|
||||
Tx_rx_communication_buffers(tx_buf_size, rx_buf_size),
|
||||
Ram_dataspace_capability(ram.alloc(size)), _ram(ram)
|
||||
{ }
|
||||
|
||||
Session_rpc_object(
|
||||
Tx_rx_communication_buffers::tx_ds(),
|
||||
Tx_rx_communication_buffers::rx_ds(),
|
||||
&range_allocator(), ep.rpc_ep()),
|
||||
|
||||
Interface(
|
||||
ep, router_mac, router_ip, guarded_allocator(), args, tcp_port_alloc,
|
||||
udp_port_alloc, mac, tcp_proxys, udp_proxys, rtt_sec, interface_tree,
|
||||
arp_cache, arp_waiters, verbose)
|
||||
/****************************
|
||||
** Session_component_base **
|
||||
****************************/
|
||||
|
||||
Session_component_base::
|
||||
Session_component_base(Allocator &guarded_alloc_backing,
|
||||
size_t const guarded_alloc_amount,
|
||||
Ram_session &buf_ram,
|
||||
size_t const tx_buf_size,
|
||||
size_t const rx_buf_size)
|
||||
:
|
||||
_guarded_alloc(&guarded_alloc_backing, guarded_alloc_amount),
|
||||
_range_alloc(&_guarded_alloc), _tx_buf(buf_ram, tx_buf_size),
|
||||
_rx_buf(buf_ram, rx_buf_size)
|
||||
{ }
|
||||
|
||||
|
||||
/***********************
|
||||
** Session_component **
|
||||
***********************/
|
||||
|
||||
Net::Session_component::Session_component(Allocator &alloc,
|
||||
Genode::Timer &timer,
|
||||
size_t const amount,
|
||||
Ram_session &buf_ram,
|
||||
size_t const tx_buf_size,
|
||||
size_t const rx_buf_size,
|
||||
Mac_address const mac,
|
||||
Entrypoint &ep,
|
||||
Mac_address const &router_mac,
|
||||
Domain &domain)
|
||||
:
|
||||
Session_component_base(alloc, amount, buf_ram, tx_buf_size, rx_buf_size),
|
||||
Session_rpc_object(_tx_buf, _rx_buf, &_range_alloc, ep.rpc_ep()),
|
||||
Interface(ep, timer, router_mac, _guarded_alloc, mac, domain)
|
||||
{
|
||||
_tx.sigh_ready_to_ack(_sink_ack);
|
||||
_tx.sigh_packet_avail(_sink_submit);
|
||||
@ -72,106 +76,87 @@ Net::Session_component::Session_component(Allocator &allocator,
|
||||
}
|
||||
|
||||
|
||||
Session_component::~Session_component() { }
|
||||
bool Session_component::link_state()
|
||||
{
|
||||
warning("Session_component::link_state not implemented");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Net::Root::Root(Server::Entrypoint &ep,
|
||||
Allocator &md_alloc,
|
||||
Mac_address router_mac,
|
||||
Port_allocator &tcp_port_alloc,
|
||||
Port_allocator &udp_port_alloc,
|
||||
Tcp_proxy_list &tcp_proxys,
|
||||
Udp_proxy_list &udp_proxys,
|
||||
unsigned rtt_sec,
|
||||
Interface_tree &interface_tree,
|
||||
Arp_cache &arp_cache,
|
||||
Arp_waiter_list &arp_waiters,
|
||||
bool verbose)
|
||||
void Session_component::link_state_sigh(Signal_context_capability sigh)
|
||||
{
|
||||
warning("Session_component::link_state_sigh not implemented");
|
||||
}
|
||||
|
||||
|
||||
/**********
|
||||
** Root **
|
||||
**********/
|
||||
|
||||
Net::Root::Root(Entrypoint &ep,
|
||||
Genode::Timer &timer,
|
||||
Allocator &alloc,
|
||||
Mac_address const &router_mac,
|
||||
Configuration &config,
|
||||
Ram_session &buf_ram)
|
||||
:
|
||||
Root_component<Session_component>(&ep.rpc_ep(), &md_alloc),
|
||||
_ep(ep), _router_mac(router_mac), _tcp_port_alloc(tcp_port_alloc),
|
||||
_udp_port_alloc(udp_port_alloc), _tcp_proxys(tcp_proxys),
|
||||
_udp_proxys(udp_proxys), _rtt_sec(rtt_sec),
|
||||
_interface_tree(interface_tree), _arp_cache(arp_cache),
|
||||
_arp_waiters(arp_waiters), _verbose(verbose)
|
||||
Root_component<Session_component>(&ep.rpc_ep(), &alloc), _timer(timer),
|
||||
_ep(ep), _router_mac(router_mac), _config(config), _buf_ram(buf_ram)
|
||||
{ }
|
||||
|
||||
|
||||
Session_component *Net::Root::_create_session(char const *args)
|
||||
{
|
||||
Ipv4_address src;
|
||||
try {
|
||||
Session_policy policy(label_from_args(args));
|
||||
src = policy.attribute_value("src", Ipv4_address());
|
||||
Session_label const label = label_from_args(args);
|
||||
Session_policy policy(label, _config.node());
|
||||
Domain_name domain_name(Cstring(policy.attribute("domain").value_base(),
|
||||
policy.attribute("domain").value_size()));
|
||||
|
||||
} catch (Session_policy::No_policy_defined) {
|
||||
Domain &domain = _config.domains().find_by_name(domain_name);
|
||||
|
||||
error("No matching policy");
|
||||
throw Root::Unavailable();
|
||||
size_t const ram_quota =
|
||||
Arg_string::find_arg(args, "ram_quota").ulong_value(0);
|
||||
|
||||
size_t const tx_buf_size =
|
||||
Arg_string::find_arg(args, "tx_buf_size").ulong_value(0);
|
||||
|
||||
size_t const rx_buf_size =
|
||||
Arg_string::find_arg(args, "rx_buf_size").ulong_value(0);
|
||||
|
||||
size_t const session_size =
|
||||
max((size_t)4096, sizeof(Session_component));
|
||||
|
||||
if (ram_quota < session_size) {
|
||||
throw Root::Quota_exceeded(); }
|
||||
|
||||
if (tx_buf_size > ram_quota - session_size ||
|
||||
rx_buf_size > ram_quota - session_size ||
|
||||
tx_buf_size + rx_buf_size > ram_quota - session_size)
|
||||
{
|
||||
error("insufficient 'ram_quota' for session creation");
|
||||
throw Root::Quota_exceeded();
|
||||
}
|
||||
return new (md_alloc())
|
||||
Session_component(*md_alloc(), _timer, ram_quota - session_size,
|
||||
_buf_ram, tx_buf_size, rx_buf_size,
|
||||
_mac_alloc.alloc(), _ep, _router_mac,
|
||||
domain);
|
||||
}
|
||||
if (src == Ipv4_address()) {
|
||||
|
||||
error("Missing 'src' attribute in policy");
|
||||
throw Root::Unavailable();
|
||||
catch (Session_policy::No_policy_defined) {
|
||||
error("no matching policy");
|
||||
}
|
||||
size_t const ram_quota =
|
||||
Arg_string::find_arg(args, "ram_quota" ).ulong_value(0);
|
||||
|
||||
size_t const tx_buf_size =
|
||||
Arg_string::find_arg(args, "tx_buf_size").ulong_value(0);
|
||||
|
||||
size_t const rx_buf_size =
|
||||
Arg_string::find_arg(args, "rx_buf_size").ulong_value(0);
|
||||
|
||||
size_t const session_size = max((size_t)4096, sizeof(Session_component));
|
||||
if (ram_quota < session_size) {
|
||||
throw Root::Quota_exceeded(); }
|
||||
|
||||
if (tx_buf_size > ram_quota - session_size ||
|
||||
rx_buf_size > ram_quota - session_size ||
|
||||
tx_buf_size + rx_buf_size > ram_quota - session_size)
|
||||
{
|
||||
error("insufficient 'ram_quota' for session creation");
|
||||
throw Root::Quota_exceeded();
|
||||
catch (Domain_tree::No_match) {
|
||||
error("no matching domain");
|
||||
}
|
||||
Mac_address mac;
|
||||
try { mac = _mac_alloc.alloc(); }
|
||||
catch (Mac_allocator::Alloc_failed) {
|
||||
|
||||
error("failed to allocate MAC address");
|
||||
throw Root::Unavailable();
|
||||
}
|
||||
return new (md_alloc())
|
||||
Session_component(*env()->heap(), ram_quota - session_size,
|
||||
tx_buf_size, rx_buf_size, mac, _ep, _router_mac,
|
||||
src, args, _tcp_port_alloc, _udp_port_alloc,
|
||||
_tcp_proxys, _udp_proxys, _rtt_sec, _interface_tree,
|
||||
_arp_cache, _arp_waiters, _verbose);
|
||||
catch (Xml_node::Nonexistent_attribute) {
|
||||
error("missing domain attribute in policy");
|
||||
}
|
||||
catch (Pointer<Interface>::Valid) {
|
||||
error("one session per domain only");
|
||||
}
|
||||
throw Root::Unavailable();
|
||||
}
|
||||
|
||||
|
||||
Tx_rx_communication_buffers::
|
||||
Tx_rx_communication_buffers(Genode::size_t const tx_size,
|
||||
Genode::size_t const rx_size)
|
||||
:
|
||||
_tx_buf(tx_size), _rx_buf(rx_size)
|
||||
{ }
|
||||
|
||||
|
||||
Communication_buffer::Communication_buffer(Genode::size_t size)
|
||||
:
|
||||
Ram_dataspace_capability(Genode::env()->ram_session()->alloc(size))
|
||||
{ }
|
||||
|
||||
|
||||
Range_allocator &Guarded_range_allocator::range_allocator()
|
||||
{
|
||||
return *static_cast<Range_allocator *>(&_range_alloc);
|
||||
}
|
||||
|
||||
|
||||
Guarded_range_allocator::
|
||||
Guarded_range_allocator(Allocator &backing_store, size_t const amount)
|
||||
:
|
||||
_guarded_alloc(&backing_store, amount), _range_alloc(&_guarded_alloc)
|
||||
{ }
|
||||
|
@ -15,123 +15,93 @@
|
||||
#define _COMPONENT_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/allocator_guard.h>
|
||||
#include <root/component.h>
|
||||
#include <nic/packet_allocator.h>
|
||||
#include <nic_session/rpc_object.h>
|
||||
#include <net/ipv4.h>
|
||||
#include <base/allocator_guard.h>
|
||||
#include <nic_bridge/mac_allocator.h>
|
||||
|
||||
/* local includes */
|
||||
#include <mac_allocator.h>
|
||||
#include <interface.h>
|
||||
|
||||
namespace Net {
|
||||
|
||||
class Port_allocator;
|
||||
class Guarded_range_allocator;
|
||||
class Domain;
|
||||
class Communication_buffer;
|
||||
class Tx_rx_communication_buffers;
|
||||
class Session_component_base;
|
||||
class Session_component;
|
||||
class Root;
|
||||
}
|
||||
|
||||
|
||||
class Net::Guarded_range_allocator
|
||||
class Net::Communication_buffer : public Genode::Ram_dataspace_capability
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::Ram_session &_ram;
|
||||
|
||||
public:
|
||||
|
||||
Communication_buffer(Genode::Ram_session &ram,
|
||||
Genode::size_t const size);
|
||||
|
||||
~Communication_buffer() { _ram.free(*this); }
|
||||
};
|
||||
|
||||
|
||||
class Net::Session_component_base
|
||||
{
|
||||
protected:
|
||||
|
||||
Genode::Allocator_guard _guarded_alloc;
|
||||
Nic::Packet_allocator _range_alloc;
|
||||
Communication_buffer _tx_buf;
|
||||
Communication_buffer _rx_buf;
|
||||
|
||||
public:
|
||||
|
||||
Guarded_range_allocator(Genode::Allocator &backing_store,
|
||||
Genode::size_t const amount);
|
||||
|
||||
|
||||
/***************
|
||||
** Accessors **
|
||||
***************/
|
||||
|
||||
Genode::Allocator_guard &guarded_allocator() { return _guarded_alloc; }
|
||||
Genode::Range_allocator &range_allocator();
|
||||
Session_component_base(Genode::Allocator &guarded_alloc_backing,
|
||||
Genode::size_t const guarded_alloc_amount,
|
||||
Genode::Ram_session &buf_ram,
|
||||
Genode::size_t const tx_buf_size,
|
||||
Genode::size_t const rx_buf_size);
|
||||
};
|
||||
|
||||
|
||||
struct Net::Communication_buffer : Genode::Ram_dataspace_capability
|
||||
{
|
||||
Communication_buffer(Genode::size_t const size);
|
||||
|
||||
~Communication_buffer() { Genode::env()->ram_session()->free(*this); }
|
||||
|
||||
Genode::Dataspace_capability dataspace() { return *this; }
|
||||
};
|
||||
|
||||
|
||||
class Net::Tx_rx_communication_buffers
|
||||
class Net::Session_component : public Session_component_base,
|
||||
public ::Nic::Session_rpc_object,
|
||||
public Interface
|
||||
{
|
||||
private:
|
||||
|
||||
Communication_buffer _tx_buf, _rx_buf;
|
||||
/********************
|
||||
** Net::Interface **
|
||||
********************/
|
||||
|
||||
Packet_stream_sink &_sink() { return *_tx.sink(); }
|
||||
Packet_stream_source &_source() { return *_rx.source(); }
|
||||
|
||||
public:
|
||||
|
||||
Tx_rx_communication_buffers(Genode::size_t const tx_size,
|
||||
Genode::size_t const rx_size);
|
||||
|
||||
Genode::Dataspace_capability tx_ds() { return _tx_buf.dataspace(); }
|
||||
Genode::Dataspace_capability rx_ds() { return _rx_buf.dataspace(); }
|
||||
};
|
||||
|
||||
|
||||
class Net::Session_component : public Guarded_range_allocator,
|
||||
private Tx_rx_communication_buffers,
|
||||
public ::Nic::Session_rpc_object,
|
||||
public Interface
|
||||
{
|
||||
private:
|
||||
|
||||
void _arp_broadcast(Interface &interface, Ipv4_address ip_addr);
|
||||
|
||||
public:
|
||||
|
||||
Session_component(Genode::Allocator &allocator,
|
||||
Genode::size_t amount,
|
||||
Genode::size_t tx_buf_size,
|
||||
Genode::size_t rx_buf_size,
|
||||
Mac_address vmac,
|
||||
Server::Entrypoint &ep,
|
||||
Mac_address router_mac,
|
||||
Ipv4_address router_ip,
|
||||
char const *args,
|
||||
Port_allocator &tcp_port_alloc,
|
||||
Port_allocator &udp_port_alloc,
|
||||
Tcp_proxy_list &tcp_proxys,
|
||||
Udp_proxy_list &udp_proxys,
|
||||
unsigned rtt_sec,
|
||||
Interface_tree &interface_tree,
|
||||
Arp_cache &arp_cache,
|
||||
Arp_waiter_list &arp_waiters,
|
||||
bool verbose);
|
||||
|
||||
~Session_component();
|
||||
Session_component(Genode::Allocator &alloc,
|
||||
Genode::Timer &timer,
|
||||
Genode::size_t const amount,
|
||||
Genode::Ram_session &buf_ram,
|
||||
Genode::size_t const tx_buf_size,
|
||||
Genode::size_t const rx_buf_size,
|
||||
Mac_address const mac,
|
||||
Genode::Entrypoint &ep,
|
||||
Mac_address const &router_mac,
|
||||
Domain &domain);
|
||||
|
||||
|
||||
/******************
|
||||
** Nic::Session **
|
||||
******************/
|
||||
|
||||
Mac_address mac_address() { return Interface::mac(); }
|
||||
Mac_address mac_address() { return _mac; }
|
||||
bool link_state();
|
||||
void link_state_sigh(Genode::Signal_context_capability sigh);
|
||||
|
||||
|
||||
/********************
|
||||
** Net::Interface **
|
||||
********************/
|
||||
|
||||
Packet_stream_sink<Nic::Session::Policy> *sink() { return _tx.sink(); }
|
||||
Packet_stream_source<Nic::Session::Policy> *source() { return _rx.source(); }
|
||||
};
|
||||
|
||||
|
||||
@ -139,40 +109,28 @@ class Net::Root : public Genode::Root_component<Session_component>
|
||||
{
|
||||
private:
|
||||
|
||||
Mac_allocator _mac_alloc;
|
||||
Server::Entrypoint &_ep;
|
||||
Mac_address _router_mac;
|
||||
Port_allocator &_tcp_port_alloc;
|
||||
Port_allocator &_udp_port_alloc;
|
||||
Tcp_proxy_list &_tcp_proxys;
|
||||
Udp_proxy_list &_udp_proxys;
|
||||
unsigned _rtt_sec;
|
||||
Interface_tree &_interface_tree;
|
||||
Arp_cache &_arp_cache;
|
||||
Arp_waiter_list &_arp_waiters;
|
||||
bool _verbose;
|
||||
Genode::Timer &_timer;
|
||||
Mac_allocator _mac_alloc;
|
||||
Genode::Entrypoint &_ep;
|
||||
Mac_address const _router_mac;
|
||||
Configuration &_config;
|
||||
Genode::Ram_session &_buf_ram;
|
||||
|
||||
|
||||
/********************
|
||||
** Root_component **
|
||||
********************/
|
||||
|
||||
Session_component *_create_session(const char *args);
|
||||
Session_component *_create_session(char const *args);
|
||||
|
||||
public:
|
||||
|
||||
Root(Server::Entrypoint &ep,
|
||||
Genode::Allocator &md_alloc,
|
||||
Mac_address router_mac,
|
||||
Port_allocator &tcp_port_alloc,
|
||||
Port_allocator &udp_port_alloc,
|
||||
Tcp_proxy_list &tcp_proxys,
|
||||
Udp_proxy_list &udp_proxys,
|
||||
unsigned rtt_sec,
|
||||
Interface_tree &interface_tree,
|
||||
Arp_cache &arp_cache,
|
||||
Arp_waiter_list &arp_waiters,
|
||||
bool verbose);
|
||||
Root(Genode::Entrypoint &ep,
|
||||
Genode::Timer &timer,
|
||||
Genode::Allocator &alloc,
|
||||
Mac_address const &router_mac,
|
||||
Configuration &config,
|
||||
Genode::Ram_session &buf_ram);
|
||||
};
|
||||
|
||||
#endif /* _COMPONENT_H_ */
|
||||
|
62
repos/os/src/server/nic_router/configuration.cc
Normal file
62
repos/os/src/server/nic_router/configuration.cc
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* \brief Reflects the current router configuration through objects
|
||||
* \author Martin Stein
|
||||
* \date 2016-08-19
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* local includes */
|
||||
#include <configuration.h>
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/xml_node.h>
|
||||
#include <base/allocator.h>
|
||||
#include <base/log.h>
|
||||
|
||||
using namespace Net;
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
/***************
|
||||
** Utilities **
|
||||
***************/
|
||||
|
||||
static unsigned read_rtt_sec(Xml_node const &node)
|
||||
{
|
||||
unsigned const rtt_sec = node.attribute_value("rtt_sec", 0UL);
|
||||
if (!rtt_sec) {
|
||||
warning("fall back to default rtt_sec=\"3\"");
|
||||
return 3;
|
||||
}
|
||||
return rtt_sec;
|
||||
}
|
||||
|
||||
|
||||
/*******************
|
||||
** Configuration **
|
||||
*******************/
|
||||
|
||||
Configuration::Configuration(Xml_node const node, Allocator &alloc)
|
||||
:
|
||||
_alloc(alloc), _verbose(node.attribute_value("verbose", false)),
|
||||
_rtt_sec(read_rtt_sec(node)), _node(node)
|
||||
{
|
||||
/* read domains */
|
||||
node.for_each_sub_node("domain", [&] (Xml_node const &node) {
|
||||
try { _domains.insert(*new (_alloc) Domain(*this, node, _alloc)); }
|
||||
catch (Domain::Invalid) { warning("invalid domain"); }
|
||||
});
|
||||
/* as they must resolve domain names, create rules after domains */
|
||||
_domains.for_each([&] (Domain &domain) {
|
||||
if (_verbose) {
|
||||
log("Domain: ", domain); }
|
||||
|
||||
domain.create_rules(_domains);
|
||||
});
|
||||
}
|
50
repos/os/src/server/nic_router/configuration.h
Normal file
50
repos/os/src/server/nic_router/configuration.h
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* \brief Reflects the current router configuration through objects
|
||||
* \author Martin Stein
|
||||
* \date 2016-08-19
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _CONFIGURATION_H_
|
||||
#define _CONFIGURATION_H_
|
||||
|
||||
/* local includes */
|
||||
#include <domain.h>
|
||||
|
||||
namespace Genode { class Allocator; }
|
||||
|
||||
namespace Net { class Configuration; }
|
||||
|
||||
|
||||
class Net::Configuration
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::Allocator &_alloc;
|
||||
bool const _verbose;
|
||||
unsigned const _rtt_sec;
|
||||
Domain_tree _domains;
|
||||
Genode::Xml_node const _node;
|
||||
|
||||
public:
|
||||
|
||||
Configuration(Genode::Xml_node const node, Genode::Allocator &alloc);
|
||||
|
||||
|
||||
/***************
|
||||
** Accessors **
|
||||
***************/
|
||||
|
||||
bool verbose() const { return _verbose; }
|
||||
unsigned rtt_sec() const { return _rtt_sec; }
|
||||
Domain_tree &domains() { return _domains; }
|
||||
Genode::Xml_node node() const { return _node; }
|
||||
};
|
||||
|
||||
#endif /* _CONFIGURATION_H_ */
|
36
repos/os/src/server/nic_router/direct_rule.cc
Normal file
36
repos/os/src/server/nic_router/direct_rule.cc
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* \brief Routing rule for direct traffic between two interfaces
|
||||
* \author Martin Stein
|
||||
* \date 2016-08-19
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* local includes */
|
||||
#include <direct_rule.h>
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/xml_node.h>
|
||||
|
||||
using namespace Net;
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
Direct_rule_base::Direct_rule_base(Xml_node const &node)
|
||||
:
|
||||
_dst(node.attribute_value("dst", Ipv4_address_prefix()))
|
||||
{
|
||||
if (!_dst.valid()) {
|
||||
throw Invalid(); }
|
||||
}
|
||||
|
||||
|
||||
void Direct_rule_base::print(Output &output) const
|
||||
{
|
||||
Genode::print(output, _dst);
|
||||
}
|
99
repos/os/src/server/nic_router/direct_rule.h
Normal file
99
repos/os/src/server/nic_router/direct_rule.h
Normal file
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* \brief Routing rule for direct traffic between two interfaces
|
||||
* \author Martin Stein
|
||||
* \date 2016-08-19
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _DIRECT_RULE_H_
|
||||
#define _DIRECT_RULE_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <net/ipv4.h>
|
||||
#include <util/list.h>
|
||||
|
||||
/* local includes */
|
||||
#include <rule.h>
|
||||
|
||||
namespace Genode { class Xml_node; }
|
||||
|
||||
namespace Net {
|
||||
|
||||
class Direct_rule_base;
|
||||
template <typename> class Direct_rule;
|
||||
template <typename> class Direct_rule_list;
|
||||
}
|
||||
|
||||
|
||||
class Net::Direct_rule_base : public Rule
|
||||
{
|
||||
protected:
|
||||
|
||||
Ipv4_address_prefix const _dst;
|
||||
|
||||
public:
|
||||
|
||||
Direct_rule_base(Genode::Xml_node const &node);
|
||||
|
||||
|
||||
/*********
|
||||
** log **
|
||||
*********/
|
||||
|
||||
void print(Genode::Output &output) const;
|
||||
|
||||
|
||||
/***************
|
||||
** Accessors **
|
||||
***************/
|
||||
|
||||
Ipv4_address_prefix const &dst() const { return _dst; }
|
||||
};
|
||||
|
||||
|
||||
template <typename T>
|
||||
struct Net::Direct_rule : Direct_rule_base,
|
||||
Direct_rule_list<T>::Element
|
||||
{
|
||||
Direct_rule(Genode::Xml_node const &node) : Direct_rule_base(node) { }
|
||||
};
|
||||
|
||||
|
||||
template <typename T>
|
||||
struct Net::Direct_rule_list : Genode::List<T>
|
||||
{
|
||||
using List = Genode::List<T>;
|
||||
|
||||
struct No_match : Genode::Exception { };
|
||||
|
||||
T const &longest_prefix_match(Ipv4_address const &ip) const
|
||||
{
|
||||
/* first match is sufficient as the list is prefix-size-sorted */
|
||||
for (T const *curr = List::first(); curr; curr = curr->next()) {
|
||||
if (curr->dst().prefix_matches(ip)) {
|
||||
return *curr; }
|
||||
}
|
||||
throw No_match();
|
||||
}
|
||||
|
||||
void insert(T &rule)
|
||||
{
|
||||
/* ensure that the list stays prefix-size-sorted (descending) */
|
||||
T *behind = nullptr;
|
||||
for (T *curr = List::first(); curr; curr = curr->next()) {
|
||||
if (rule.dst().prefix >= curr->dst().prefix) {
|
||||
break; }
|
||||
|
||||
behind = curr;
|
||||
}
|
||||
List::insert(&rule, behind);
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _RULE_H_ */
|
165
repos/os/src/server/nic_router/domain.cc
Normal file
165
repos/os/src/server/nic_router/domain.cc
Normal file
@ -0,0 +1,165 @@
|
||||
/*
|
||||
* \brief Reflects an effective domain configuration node
|
||||
* \author Martin Stein
|
||||
* \date 2016-08-19
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* local includes */
|
||||
#include <configuration.h>
|
||||
#include <protocol_name.h>
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/xml_node.h>
|
||||
#include <base/allocator.h>
|
||||
#include <base/log.h>
|
||||
|
||||
using namespace Net;
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
/***********************
|
||||
** Domain_avl_member **
|
||||
***********************/
|
||||
|
||||
Domain_avl_member::Domain_avl_member(Domain_name const &name,
|
||||
Domain &domain)
|
||||
:
|
||||
Avl_string_base(name.string()), _domain(domain)
|
||||
{ }
|
||||
|
||||
|
||||
/*****************
|
||||
** Domain_base **
|
||||
*****************/
|
||||
|
||||
Domain_base::Domain_base(Xml_node const &node)
|
||||
:
|
||||
_name(Cstring(node.attribute("name").value_base(),
|
||||
node.attribute("name").value_size()))
|
||||
{ }
|
||||
|
||||
|
||||
/************
|
||||
** Domain **
|
||||
************/
|
||||
|
||||
void Domain::_read_forward_rules(Cstring const &protocol,
|
||||
Domain_tree &domains,
|
||||
Xml_node const &node,
|
||||
char const *type,
|
||||
Forward_rule_tree &rules)
|
||||
{
|
||||
node.for_each_sub_node(type, [&] (Xml_node const &node) {
|
||||
try {
|
||||
Forward_rule &rule = *new (_alloc) Forward_rule(domains, node);
|
||||
rules.insert(&rule);
|
||||
if (_config.verbose()) {
|
||||
log(" Forward rule: ", protocol, " ", rule); }
|
||||
}
|
||||
catch (Rule::Invalid) { warning("invalid forward rule"); }
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
void Domain::_read_transport_rules(Cstring const &protocol,
|
||||
Domain_tree &domains,
|
||||
Xml_node const &node,
|
||||
char const *type,
|
||||
Transport_rule_list &rules)
|
||||
{
|
||||
node.for_each_sub_node(type, [&] (Xml_node const &node) {
|
||||
try {
|
||||
rules.insert(*new (_alloc) Transport_rule(domains, node, _alloc,
|
||||
protocol, _config));
|
||||
}
|
||||
catch (Rule::Invalid) { warning("invalid transport rule"); }
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
void Domain::print(Output &output) const
|
||||
{
|
||||
Genode::print(output, "\"", _name, "\"");
|
||||
}
|
||||
|
||||
|
||||
Domain::Domain(Configuration &config, Xml_node const &node, Allocator &alloc)
|
||||
:
|
||||
Domain_base(node), _avl_member(_name, *this), _config(config),
|
||||
_node(node), _alloc(alloc),
|
||||
_interface_attr(node.attribute_value("interface", Ipv4_address_prefix())),
|
||||
_gateway(node.attribute_value("gateway", Ipv4_address())),
|
||||
_gateway_valid(_gateway.valid())
|
||||
{
|
||||
if (_name == Domain_name() || !_interface_attr.valid() ||
|
||||
(_gateway_valid && !_interface_attr.prefix_matches(_gateway)))
|
||||
{
|
||||
throw Invalid();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Domain::create_rules(Domain_tree &domains)
|
||||
{
|
||||
/* read forward rules */
|
||||
_read_forward_rules(tcp_name(), domains, _node, "tcp-forward",
|
||||
_tcp_forward_rules);
|
||||
_read_forward_rules(udp_name(), domains, _node, "udp-forward",
|
||||
_udp_forward_rules);
|
||||
|
||||
/* read UDP and TCP rules */
|
||||
_read_transport_rules(tcp_name(), domains, _node, "tcp", _tcp_rules);
|
||||
_read_transport_rules(udp_name(), domains, _node, "udp", _udp_rules);
|
||||
|
||||
/* read NAT rules */
|
||||
_node.for_each_sub_node("nat", [&] (Xml_node const &node) {
|
||||
try {
|
||||
_nat_rules.insert(
|
||||
new (_alloc) Nat_rule(domains, _tcp_port_alloc,
|
||||
_udp_port_alloc, node));
|
||||
}
|
||||
catch (Rule::Invalid) { warning("invalid NAT rule"); }
|
||||
});
|
||||
/* read IP rules */
|
||||
_node.for_each_sub_node("ip", [&] (Xml_node const &node) {
|
||||
try { _ip_rules.insert(*new (_alloc) Ip_rule(domains, node)); }
|
||||
catch (Rule::Invalid) { warning("invalid IP rule"); }
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Ipv4_address const &Domain::next_hop(Ipv4_address const &ip) const
|
||||
{
|
||||
if (_interface_attr.prefix_matches(ip)) { return ip; }
|
||||
if (_gateway_valid) { return _gateway; }
|
||||
throw No_next_hop();
|
||||
}
|
||||
|
||||
|
||||
/*****************
|
||||
** Domain_tree **
|
||||
*****************/
|
||||
|
||||
Domain &Domain_tree::domain(Avl_string_base const &node)
|
||||
{
|
||||
return static_cast<Domain_avl_member const *>(&node)->domain();
|
||||
}
|
||||
|
||||
Domain &Domain_tree::find_by_name(Domain_name name)
|
||||
{
|
||||
if (name == Domain_name() || !first()) {
|
||||
throw No_match(); }
|
||||
|
||||
Avl_string_base *node = first()->find_by_name(name.string());
|
||||
if (!node) {
|
||||
throw No_match(); }
|
||||
|
||||
return domain(*node);
|
||||
}
|
165
repos/os/src/server/nic_router/domain.h
Normal file
165
repos/os/src/server/nic_router/domain.h
Normal file
@ -0,0 +1,165 @@
|
||||
/*
|
||||
* \brief Reflects an effective domain configuration node
|
||||
* \author Martin Stein
|
||||
* \date 2016-08-19
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _DOMAIN_H_
|
||||
#define _DOMAIN_H_
|
||||
|
||||
/* local includes */
|
||||
#include <forward_rule.h>
|
||||
#include <transport_rule.h>
|
||||
#include <nat_rule.h>
|
||||
#include <ip_rule.h>
|
||||
#include <port_allocator.h>
|
||||
#include <pointer.h>
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/avl_string.h>
|
||||
#include <util/xml_node.h>
|
||||
|
||||
namespace Genode { class Allocator; }
|
||||
|
||||
namespace Net {
|
||||
|
||||
class Interface;
|
||||
class Configuration;
|
||||
class Domain_avl_member;
|
||||
class Domain_base;
|
||||
class Domain;
|
||||
class Domain_tree;
|
||||
using Domain_name = Genode::String<160>;
|
||||
}
|
||||
|
||||
|
||||
class Net::Domain_avl_member : public Genode::Avl_string_base
|
||||
{
|
||||
private:
|
||||
|
||||
Domain &_domain;
|
||||
|
||||
public:
|
||||
|
||||
Domain_avl_member(Domain_name const &name,
|
||||
Domain &domain);
|
||||
|
||||
|
||||
/***************
|
||||
** Accessors **
|
||||
***************/
|
||||
|
||||
Domain &domain() const { return _domain; }
|
||||
};
|
||||
|
||||
|
||||
class Net::Domain_base
|
||||
{
|
||||
protected:
|
||||
|
||||
Domain_name const _name;
|
||||
|
||||
Domain_base(Genode::Xml_node const &node);
|
||||
};
|
||||
|
||||
|
||||
class Net::Domain : public Domain_base
|
||||
{
|
||||
private:
|
||||
|
||||
Domain_avl_member _avl_member;
|
||||
Configuration &_config;
|
||||
Genode::Xml_node _node;
|
||||
Genode::Allocator &_alloc;
|
||||
Ipv4_address_prefix _interface_attr;
|
||||
Ipv4_address const _gateway;
|
||||
bool const _gateway_valid;
|
||||
Ip_rule_list _ip_rules;
|
||||
Forward_rule_tree _tcp_forward_rules;
|
||||
Forward_rule_tree _udp_forward_rules;
|
||||
Transport_rule_list _tcp_rules;
|
||||
Transport_rule_list _udp_rules;
|
||||
Port_allocator _tcp_port_alloc;
|
||||
Port_allocator _udp_port_alloc;
|
||||
Nat_rule_tree _nat_rules;
|
||||
Pointer<Interface> _interface;
|
||||
|
||||
void _read_forward_rules(Genode::Cstring const &protocol,
|
||||
Domain_tree &domains,
|
||||
Genode::Xml_node const &node,
|
||||
char const *type,
|
||||
Forward_rule_tree &rules);
|
||||
|
||||
void _read_transport_rules(Genode::Cstring const &protocol,
|
||||
Domain_tree &domains,
|
||||
Genode::Xml_node const &node,
|
||||
char const *type,
|
||||
Transport_rule_list &rules);
|
||||
|
||||
public:
|
||||
|
||||
struct Invalid : Genode::Exception { };
|
||||
struct No_next_hop : Genode::Exception { };
|
||||
|
||||
Domain(Configuration &config,
|
||||
Genode::Xml_node const &node,
|
||||
Genode::Allocator &alloc);
|
||||
|
||||
void create_rules(Domain_tree &domains);
|
||||
|
||||
Ipv4_address const &next_hop(Ipv4_address const &ip) const;
|
||||
|
||||
|
||||
/*********
|
||||
** log **
|
||||
*********/
|
||||
|
||||
void print(Genode::Output &output) const;
|
||||
|
||||
|
||||
/***************
|
||||
** Accessors **
|
||||
***************/
|
||||
|
||||
Domain_name const &name() { 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; }
|
||||
Nat_rule_tree &nat_rules() { return _nat_rules; }
|
||||
Ipv4_address_prefix &interface_attr() { return _interface_attr; }
|
||||
Pointer<Interface> &interface() { return _interface; }
|
||||
Configuration &config() const { return _config; }
|
||||
Domain_avl_member &avl_member() { return _avl_member; }
|
||||
};
|
||||
|
||||
|
||||
struct Net::Domain_tree : Genode::Avl_tree<Genode::Avl_string_base>
|
||||
{
|
||||
using Avl_tree = Genode::Avl_tree<Genode::Avl_string_base>;
|
||||
|
||||
struct No_match : Genode::Exception { };
|
||||
|
||||
static Domain &domain(Genode::Avl_string_base const &node);
|
||||
|
||||
Domain &find_by_name(Domain_name name);
|
||||
|
||||
template <typename FUNC>
|
||||
void for_each(FUNC && functor) const {
|
||||
Avl_tree::for_each([&] (Genode::Avl_string_base const &node) {
|
||||
functor(domain(node));
|
||||
});
|
||||
}
|
||||
|
||||
void insert(Domain &domain) { Avl_tree::insert(&domain.avl_member()); }
|
||||
};
|
||||
|
||||
#endif /* _DOMAIN_H_ */
|
70
repos/os/src/server/nic_router/forward_rule.cc
Normal file
70
repos/os/src/server/nic_router/forward_rule.cc
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* \brief Rule for forwarding a TCP/UDP port of the router to an interface
|
||||
* \author Martin Stein
|
||||
* \date 2016-08-19
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* local includes */
|
||||
#include <forward_rule.h>
|
||||
#include <domain.h>
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/xml_node.h>
|
||||
|
||||
using namespace Net;
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
/******************
|
||||
** Forward_rule **
|
||||
******************/
|
||||
|
||||
void Forward_rule::print(Output &output) const
|
||||
{
|
||||
Genode::print(output, "port ", _port, " requests to ", _to,
|
||||
" at ", _domain);
|
||||
}
|
||||
|
||||
|
||||
Forward_rule::Forward_rule(Domain_tree &domains, Xml_node const &node)
|
||||
:
|
||||
Leaf_rule(domains, node),
|
||||
_port(node.attribute_value("port", 0UL)),
|
||||
_to(node.attribute_value("to", Ipv4_address()))
|
||||
{
|
||||
if (!_port || !_to.valid() || dynamic_port(_port)) {
|
||||
throw Invalid(); }
|
||||
}
|
||||
|
||||
|
||||
Forward_rule const &Forward_rule::find_by_port(uint8_t const port) const
|
||||
{
|
||||
if (port == _port) {
|
||||
return *this; }
|
||||
|
||||
Forward_rule *const rule = Avl_node<Forward_rule>::child(port > _port);
|
||||
if (!rule) {
|
||||
throw Forward_rule_tree::No_match(); }
|
||||
|
||||
return rule->find_by_port(port);
|
||||
}
|
||||
|
||||
|
||||
/***********************
|
||||
** Forward_rule_tree **
|
||||
***********************/
|
||||
|
||||
Forward_rule const &Forward_rule_tree::find_by_port(uint8_t const port) const
|
||||
{
|
||||
if (!first()) {
|
||||
throw No_match(); }
|
||||
|
||||
return first()->find_by_port(port);
|
||||
}
|
77
repos/os/src/server/nic_router/forward_rule.h
Normal file
77
repos/os/src/server/nic_router/forward_rule.h
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* \brief Rule for forwarding a TCP/UDP port of the router to an interface
|
||||
* \author Martin Stein
|
||||
* \date 2016-08-19
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _FORWARD_RULE_H_
|
||||
#define _FORWARD_RULE_H_
|
||||
|
||||
/* local includes */
|
||||
#include <leaf_rule.h>
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/avl_tree.h>
|
||||
#include <net/ipv4.h>
|
||||
|
||||
namespace Net {
|
||||
|
||||
class Forward_rule;
|
||||
class Forward_rule_tree;
|
||||
class Forward_link;
|
||||
class Forward_link_tree;
|
||||
}
|
||||
|
||||
|
||||
class Net::Forward_rule : public Leaf_rule,
|
||||
public Genode::Avl_node<Forward_rule>
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::uint8_t const _port;
|
||||
Ipv4_address const _to;
|
||||
|
||||
public:
|
||||
|
||||
Forward_rule(Domain_tree &domains, Genode::Xml_node const &node);
|
||||
|
||||
Forward_rule const &find_by_port(Genode::uint8_t const port) const;
|
||||
|
||||
|
||||
/*********
|
||||
** log **
|
||||
*********/
|
||||
|
||||
void print(Genode::Output &output) const;
|
||||
|
||||
|
||||
/**************
|
||||
** Avl_node **
|
||||
**************/
|
||||
|
||||
bool higher(Forward_rule *rule) { return rule->_port > _port; }
|
||||
|
||||
|
||||
/***************
|
||||
** Accessors **
|
||||
***************/
|
||||
|
||||
Ipv4_address const &to() const { return _to; }
|
||||
};
|
||||
|
||||
|
||||
struct Net::Forward_rule_tree : Genode::Avl_tree<Forward_rule>
|
||||
{
|
||||
struct No_match : Genode::Exception { };
|
||||
|
||||
Forward_rule const &find_by_port(Genode::uint8_t const port) const;
|
||||
};
|
||||
|
||||
#endif /* _FORWARD_RULE_H_ */
|
File diff suppressed because it is too large
Load Diff
@ -14,192 +14,168 @@
|
||||
#ifndef _INTERFACE_H_
|
||||
#define _INTERFACE_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <os/server.h>
|
||||
#include <os/session_policy.h>
|
||||
#include <util/avl_string.h>
|
||||
#include <nic_session/nic_session.h>
|
||||
|
||||
/* local includes */
|
||||
#include <ip_route.h>
|
||||
#include <link.h>
|
||||
#include <arp_cache.h>
|
||||
#include <arp_waiter.h>
|
||||
|
||||
/* Genode includes */
|
||||
#include <nic_session/nic_session.h>
|
||||
|
||||
namespace Net {
|
||||
|
||||
using ::Nic::Packet_stream_sink;
|
||||
using ::Nic::Packet_stream_source;
|
||||
using ::Nic::Packet_descriptor;
|
||||
|
||||
using Packet_descriptor = ::Nic::Packet_descriptor;
|
||||
using Packet_stream_sink = ::Nic::Packet_stream_sink< ::Nic::Session::Policy>;
|
||||
using Packet_stream_source = ::Nic::Packet_stream_source< ::Nic::Session::Policy>;
|
||||
class Forward_rule_tree;
|
||||
class Transport_rule_list;
|
||||
class Ethernet_frame;
|
||||
class Arp_packet;
|
||||
class Arp_waiter;
|
||||
class Arp_cache;
|
||||
class Arp_cache_entry;
|
||||
class Port_allocator;
|
||||
class Tcp_proxy;
|
||||
class Udp_proxy;
|
||||
class Interface;
|
||||
class Interface_tree;
|
||||
|
||||
using Interface_list = Genode::List<Interface>;
|
||||
using Arp_waiter_list = Genode::List<Arp_waiter>;
|
||||
using Tcp_proxy_list = Genode::List<Tcp_proxy>;
|
||||
using Udp_proxy_list = Genode::List<Udp_proxy>;
|
||||
using Signal_rpc_member = Genode::Signal_rpc_member<Interface>;
|
||||
class Configuration;
|
||||
class Domain;
|
||||
}
|
||||
|
||||
|
||||
class Net::Interface : public Genode::Session_label, public Genode::Avl_string_base
|
||||
class Net::Interface
|
||||
{
|
||||
protected:
|
||||
|
||||
Signal_rpc_member _sink_ack;
|
||||
Signal_rpc_member _sink_submit;
|
||||
Signal_rpc_member _source_ack;
|
||||
Signal_rpc_member _source_submit;
|
||||
using Signal_handler = Genode::Signal_handler<Interface>;
|
||||
|
||||
Signal_handler _sink_ack;
|
||||
Signal_handler _sink_submit;
|
||||
Signal_handler _source_ack;
|
||||
Signal_handler _source_submit;
|
||||
Mac_address const _router_mac;
|
||||
Mac_address const _mac;
|
||||
|
||||
private:
|
||||
|
||||
Packet_descriptor _packet;
|
||||
Genode::Entrypoint &_ep;
|
||||
Ip_route_list _ip_routes;
|
||||
Mac_address const _router_mac;
|
||||
Ipv4_address const _router_ip;
|
||||
Mac_address const _mac;
|
||||
Genode::Allocator &_allocator;
|
||||
Genode::Session_policy _policy;
|
||||
bool const _proxy;
|
||||
unsigned _tcp_proxy;
|
||||
unsigned _tcp_proxy_used;
|
||||
Tcp_proxy_list &_tcp_proxies;
|
||||
Port_allocator &_tcp_port_alloc;
|
||||
unsigned _udp_proxy;
|
||||
unsigned _udp_proxy_used;
|
||||
Udp_proxy_list &_udp_proxies;
|
||||
Port_allocator &_udp_port_alloc;
|
||||
unsigned const _rtt_sec;
|
||||
Interface_tree &_interface_tree;
|
||||
Arp_cache &_arp_cache;
|
||||
Arp_waiter_list &_arp_waiters;
|
||||
bool _verbose;
|
||||
Genode::Timer &_timer;
|
||||
Genode::Allocator &_alloc;
|
||||
Domain &_domain;
|
||||
Arp_cache _arp_cache;
|
||||
Arp_waiter_list _own_arp_waiters;
|
||||
Arp_waiter_list _foreign_arp_waiters;
|
||||
Link_side_tree _tcp_links;
|
||||
Link_side_tree _udp_links;
|
||||
Link_list _closed_tcp_links;
|
||||
Link_list _closed_udp_links;
|
||||
|
||||
void _read_route(Genode::Xml_node &route_xn);
|
||||
void _new_link(Genode::uint8_t const protocol,
|
||||
Link_side_id const &local_id,
|
||||
Pointer<Port_allocator_guard> const remote_port_alloc,
|
||||
Interface &remote_interface,
|
||||
Link_side_id const &remote_id);
|
||||
|
||||
Tcp_proxy *_find_tcp_proxy_by_client(Ipv4_address ip,
|
||||
Genode::uint16_t port);
|
||||
Forward_rule_tree &_forward_rules(Genode::uint8_t const prot) const;
|
||||
|
||||
Udp_proxy *_find_udp_proxy_by_client(Ipv4_address ip,
|
||||
Genode::uint16_t port);
|
||||
Transport_rule_list &_transport_rules(Genode::uint8_t const prot) const;
|
||||
|
||||
Interface *_tlp_proxy_route(Genode::uint8_t tlp, void *ptr,
|
||||
Genode::uint16_t &dst_port,
|
||||
Ipv4_packet *ip, Ipv4_address &to,
|
||||
Ipv4_address &via);
|
||||
void _handle_arp(Ethernet_frame ð, Genode::size_t const eth_size);
|
||||
|
||||
void _tlp_apply_port_proxy(Genode::uint8_t tlp, void *tlp_ptr,
|
||||
Ipv4_packet *ip, Ipv4_address client_ip,
|
||||
Genode::uint16_t src_port);
|
||||
void _handle_arp_reply(Arp_packet &arp);
|
||||
|
||||
Tcp_proxy *_find_tcp_proxy_by_proxy(Ipv4_address ip,
|
||||
Genode::uint16_t port);
|
||||
void _handle_arp_request(Ethernet_frame ð,
|
||||
Genode::size_t const eth_size,
|
||||
Arp_packet &arp);
|
||||
|
||||
Udp_proxy *_find_udp_proxy_by_proxy(Ipv4_address ip,
|
||||
Genode::uint16_t port);
|
||||
void _handle_ip(Ethernet_frame ð,
|
||||
Genode::size_t const eth_size,
|
||||
Packet_descriptor const &pkt);
|
||||
|
||||
void _handle_arp_reply(Arp_packet * const arp);
|
||||
void _adapt_eth(Ethernet_frame ð,
|
||||
Genode::size_t const eth_size,
|
||||
Ipv4_address const &ip,
|
||||
Packet_descriptor const &pkt,
|
||||
Interface &interface);
|
||||
|
||||
void _handle_arp_request(Ethernet_frame * const eth,
|
||||
Genode::size_t const eth_size,
|
||||
Arp_packet * const arp);
|
||||
void _nat_link_and_pass(Ethernet_frame ð,
|
||||
Genode::size_t const eth_size,
|
||||
Ipv4_packet &ip,
|
||||
Genode::uint8_t const prot,
|
||||
void *const prot_base,
|
||||
Genode::size_t const prot_size,
|
||||
Link_side_id const &local_id,
|
||||
Interface &interface);
|
||||
|
||||
Arp_waiter *_new_arp_entry(Arp_waiter *arp_waiter,
|
||||
Arp_cache_entry *entry);
|
||||
void _broadcast_arp_request(Ipv4_address const &ip);
|
||||
|
||||
void _remove_arp_waiter(Arp_waiter *arp_waiter);
|
||||
void _send(Ethernet_frame ð, Genode::size_t const eth_size);
|
||||
|
||||
void _handle_arp(Ethernet_frame *eth, Genode::size_t size);
|
||||
void _pass_ip(Ethernet_frame ð,
|
||||
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 _handle_ip(Ethernet_frame *eth, Genode::size_t eth_size,
|
||||
bool &ack_packet, Packet_descriptor *packet);
|
||||
void _continue_handle_eth(Packet_descriptor const &pkt);
|
||||
|
||||
Tcp_proxy *_new_tcp_proxy(unsigned const client_port,
|
||||
Ipv4_address client_ip,
|
||||
Ipv4_address proxy_ip);
|
||||
Link_list &_closed_links(Genode::uint8_t const protocol);
|
||||
|
||||
Udp_proxy *_new_udp_proxy(unsigned const client_port,
|
||||
Ipv4_address client_ip,
|
||||
Ipv4_address proxy_ip);
|
||||
Link_side_tree &_links(Genode::uint8_t const protocol);
|
||||
|
||||
void _delete_tcp_proxy(Tcp_proxy * const proxy);
|
||||
Configuration &_config() const;
|
||||
|
||||
bool _chk_delete_tcp_proxy(Tcp_proxy * &proxy);
|
||||
Ipv4_address const &_router_ip() const;
|
||||
|
||||
void _delete_udp_proxy(Udp_proxy * const proxy);
|
||||
void _handle_eth(void *const eth_base,
|
||||
Genode::size_t const eth_size,
|
||||
Packet_descriptor const &pkt);
|
||||
|
||||
bool _chk_delete_udp_proxy(Udp_proxy * &proxy);
|
||||
void _ack_packet(Packet_descriptor const &pkt);
|
||||
|
||||
void _cancel_arp_waiting(Arp_waiter &waiter);
|
||||
|
||||
virtual Packet_stream_sink &_sink() = 0;
|
||||
|
||||
virtual Packet_stream_source &_source() = 0;
|
||||
|
||||
|
||||
/***********************************
|
||||
** Packet-stream signal handlers **
|
||||
***********************************/
|
||||
|
||||
void _ready_to_submit(unsigned);
|
||||
void _ack_avail(unsigned) { }
|
||||
void _ready_to_ack(unsigned);
|
||||
void _packet_avail(unsigned) { }
|
||||
void _ready_to_submit();
|
||||
void _ack_avail() { }
|
||||
void _ready_to_ack();
|
||||
void _packet_avail() { }
|
||||
|
||||
public:
|
||||
|
||||
struct Too_many_tcp_proxies : Genode::Exception { };
|
||||
struct Too_many_udp_proxies : Genode::Exception { };
|
||||
struct Bad_transport_protocol : Genode::Exception { };
|
||||
struct Bad_network_protocol : Genode::Exception { };
|
||||
struct Packet_postponed : Genode::Exception { };
|
||||
|
||||
Interface(Server::Entrypoint &ep,
|
||||
Mac_address const router_mac,
|
||||
Ipv4_address const router_ip,
|
||||
Genode::Allocator &allocator,
|
||||
char const *args,
|
||||
Port_allocator &tcp_port_alloc,
|
||||
Port_allocator &udp_port_alloc,
|
||||
Mac_address const mac,
|
||||
Tcp_proxy_list &tcp_proxies,
|
||||
Udp_proxy_list &udp_proxies,
|
||||
unsigned const rtt_sec,
|
||||
Interface_tree &interface_tree,
|
||||
Arp_cache &arp_cache,
|
||||
Arp_waiter_list &arp_waiters,
|
||||
bool verbose);
|
||||
Interface(Genode::Entrypoint &ep,
|
||||
Genode::Timer &timer,
|
||||
Mac_address const router_mac,
|
||||
Genode::Allocator &alloc,
|
||||
Mac_address const mac,
|
||||
Domain &domain);
|
||||
|
||||
~Interface();
|
||||
|
||||
void arp_broadcast(Ipv4_address ip_addr);
|
||||
void link_closed(Link &link, Genode::uint8_t const prot);
|
||||
|
||||
void send(Ethernet_frame *eth, Genode::size_t eth_size);
|
||||
void dissolve_link(Link_side &link_side, Genode::uint8_t const prot);
|
||||
|
||||
void handle_ethernet(void *src, Genode::size_t size, bool &ack,
|
||||
Packet_descriptor *packet);
|
||||
|
||||
void continue_handle_ethernet(void *src, Genode::size_t size,
|
||||
Packet_descriptor *packet);
|
||||
/*********
|
||||
** log **
|
||||
*********/
|
||||
|
||||
void print(Genode::Output &output) const;
|
||||
|
||||
|
||||
/***************
|
||||
** Accessors **
|
||||
***************/
|
||||
|
||||
Mac_address router_mac() const { return _router_mac; }
|
||||
Mac_address mac() const { return _mac; }
|
||||
Ipv4_address router_ip() const { return _router_ip; }
|
||||
Ip_route_list &ip_routes() { return _ip_routes; }
|
||||
Genode::Allocator &allocator() const { return _allocator; }
|
||||
Session_label &label() { return *this; }
|
||||
|
||||
virtual Packet_stream_sink< ::Nic::Session::Policy> *sink() = 0;
|
||||
virtual Packet_stream_source< ::Nic::Session::Policy> *source() = 0;
|
||||
};
|
||||
|
||||
|
||||
struct Net::Interface_tree : Genode::Avl_tree<Genode::Avl_string_base>
|
||||
{
|
||||
Interface *find_by_label(char const *label);
|
||||
Arp_waiter_list &own_arp_waiters() { return _own_arp_waiters; }
|
||||
Arp_waiter_list &foreign_arp_waiters() { return _foreign_arp_waiters; }
|
||||
};
|
||||
|
||||
#endif /* _INTERFACE_H_ */
|
||||
|
@ -1,141 +0,0 @@
|
||||
/*
|
||||
* \brief IP routing entry
|
||||
* \author Martin Stein
|
||||
* \date 2016-08-19
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <net/ipv4.h>
|
||||
#include <util/xml_node.h>
|
||||
#include <base/allocator.h>
|
||||
#include <base/log.h>
|
||||
|
||||
/* local includes */
|
||||
#include <ip_route.h>
|
||||
|
||||
using namespace Net;
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
bool Ip_route::matches(Ipv4_address ip_addr)
|
||||
{
|
||||
if (memcmp(&ip_addr.addr, _ip_addr.addr, _prefix_bytes)) {
|
||||
return false; }
|
||||
|
||||
if (!_prefix_tail) {
|
||||
return true; }
|
||||
|
||||
uint8_t ip_tail = ip_addr.addr[_prefix_bytes] & _prefix_tail;
|
||||
if (ip_tail != _ip_addr.addr[_prefix_bytes]) {
|
||||
return false; }
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void Ip_route::print(Output &output) const
|
||||
{
|
||||
Genode::print(output, _ip_addr, "/", _prefix, " -> \"",
|
||||
_label, "\" to ", _to, " via ", _via);
|
||||
}
|
||||
|
||||
|
||||
void Ip_route::_read_tcp_port(Xml_node &port, Allocator &alloc)
|
||||
{
|
||||
uint16_t const dst = port.attribute_value("dst", 0UL);
|
||||
if (!dst) {
|
||||
return; }
|
||||
|
||||
Port_route *port_route;
|
||||
try {
|
||||
char const *label = port.attribute("label").value_base();
|
||||
size_t label_size = port.attribute("label").value_size();
|
||||
Ipv4_address const via = port.attribute_value("via", Ipv4_address());
|
||||
Ipv4_address const to = port.attribute_value("to", Ipv4_address());
|
||||
port_route = new (&alloc) Port_route(dst, label, label_size, via, to);
|
||||
|
||||
} catch (Xml_attribute::Nonexistent_attribute) {
|
||||
|
||||
Ipv4_address const via = port.attribute_value("via", Ipv4_address());
|
||||
Ipv4_address const to = port.attribute_value("to", Ipv4_address());
|
||||
port_route = new (alloc) Port_route(dst, "", 0, via, to);
|
||||
}
|
||||
_tcp_port_tree.insert(port_route);
|
||||
_tcp_port_list.insert(port_route);
|
||||
if (_verbose) { log(" TCP port route: ", *port_route); }
|
||||
}
|
||||
|
||||
void Ip_route::_read_udp_port(Xml_node &port, Allocator &alloc)
|
||||
{
|
||||
uint16_t const dst = port.attribute_value("dst", 0UL);
|
||||
if (!dst) {
|
||||
warning("missing 'dst' attribute in port route");
|
||||
return;
|
||||
}
|
||||
char const *label = port.attribute("label").value_base();
|
||||
size_t label_size = port.attribute("label").value_size();
|
||||
Ipv4_address const via = port.attribute_value("via", Ipv4_address());
|
||||
Ipv4_address const to = port.attribute_value("to", Ipv4_address());
|
||||
Port_route *port_route = new (alloc)
|
||||
Port_route(dst, label, label_size, via, to);
|
||||
|
||||
_udp_port_tree.insert(port_route);
|
||||
_udp_port_list.insert(port_route);
|
||||
if (_verbose) {
|
||||
log(" UDP port route: ", *port_route); }
|
||||
}
|
||||
|
||||
|
||||
|
||||
Ip_route::Ip_route(Ipv4_address ip_addr, uint8_t prefix, Ipv4_address via,
|
||||
Ipv4_address to, char const *label, size_t label_size,
|
||||
Allocator &alloc, Xml_node &route, bool verbose)
|
||||
:
|
||||
_ip_addr(ip_addr), _prefix(prefix), _prefix_bytes(_prefix / 8),
|
||||
_prefix_tail(~(((uint8_t)~0) >> (_prefix - (_prefix_bytes * 8)))),
|
||||
_via(via), _to(to), _label(Genode::Cstring(label, label_size)),
|
||||
_verbose(verbose)
|
||||
{
|
||||
if (_prefix_bytes < sizeof(ip_addr.addr)) {
|
||||
_ip_addr.addr[_prefix_bytes] &= _prefix_tail; }
|
||||
try {
|
||||
Xml_node port = route.sub_node("tcp");
|
||||
for (; ; port = port.next("tcp")) { _read_tcp_port(port, alloc); }
|
||||
|
||||
} catch (Xml_node::Nonexistent_sub_node) { }
|
||||
try {
|
||||
Xml_node port = route.sub_node("udp");
|
||||
for (; ; port = port.next("udp")) { _read_udp_port(port, alloc); }
|
||||
|
||||
} catch (Xml_node::Nonexistent_sub_node) { }
|
||||
}
|
||||
|
||||
|
||||
Ip_route *Ip_route_list::longest_prefix_match(Ipv4_address ip_addr)
|
||||
{
|
||||
for (Ip_route *curr = first(); curr; curr = curr->next()) {
|
||||
if (curr->matches(ip_addr)) {
|
||||
return curr; }
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
void Ip_route_list::insert(Ip_route *route)
|
||||
{
|
||||
Ip_route *behind = nullptr;
|
||||
for (Ip_route *curr = first(); curr; curr = curr->next()) {
|
||||
if (route->prefix() >= curr->prefix()) {
|
||||
break; }
|
||||
|
||||
behind = curr;
|
||||
}
|
||||
Genode::List<Ip_route>::insert(route, behind);
|
||||
}
|
@ -1,89 +0,0 @@
|
||||
/*
|
||||
* \brief IP routing entry
|
||||
* \author Martin Stein
|
||||
* \date 2016-08-19
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* local includes */
|
||||
#include <port_route.h>
|
||||
|
||||
#ifndef _IP_ROUTE_H_
|
||||
#define _IP_ROUTE_H_
|
||||
|
||||
namespace Genode {
|
||||
|
||||
class Xml_node;
|
||||
class Allocator;
|
||||
}
|
||||
|
||||
namespace Net {
|
||||
|
||||
class Ip_route;
|
||||
class Ip_route_list;
|
||||
}
|
||||
|
||||
class Net::Ip_route : public Genode::List<Ip_route>::Element
|
||||
{
|
||||
private:
|
||||
|
||||
Ipv4_address _ip_addr;
|
||||
Genode::uint8_t _prefix;
|
||||
Genode::uint8_t _prefix_bytes;
|
||||
Genode::uint8_t _prefix_tail;
|
||||
Ipv4_address _via;
|
||||
Ipv4_address _to;
|
||||
Genode::Session_label _label;
|
||||
Port_route_tree _udp_port_tree;
|
||||
Port_route_tree _tcp_port_tree;
|
||||
Port_route_list _udp_port_list;
|
||||
Port_route_list _tcp_port_list;
|
||||
bool _verbose;
|
||||
|
||||
void _read_tcp_port(Genode::Xml_node &port, Genode::Allocator &alloc);
|
||||
|
||||
void _read_udp_port(Genode::Xml_node &port, Genode::Allocator &alloc);
|
||||
|
||||
public:
|
||||
|
||||
Ip_route(Ipv4_address ip_addr, Genode::uint8_t prefix,
|
||||
Ipv4_address via, Ipv4_address to, char const *label,
|
||||
Genode::size_t label_size, Genode::Allocator &alloc,
|
||||
Genode::Xml_node &route, bool verbose);
|
||||
|
||||
void print(Genode::Output &output) const;
|
||||
|
||||
bool matches(Ipv4_address ip_addr);
|
||||
|
||||
|
||||
/***************
|
||||
** Accessors **
|
||||
***************/
|
||||
|
||||
Ipv4_address ip_addr() const { return _ip_addr; }
|
||||
Ipv4_address via() const { return _via; }
|
||||
Ipv4_address to() const { return _to; }
|
||||
Genode::uint8_t prefix() const { return _prefix; }
|
||||
Genode::Session_label &label() { return _label; }
|
||||
Port_route_tree *tcp_port_tree() { return &_tcp_port_tree; }
|
||||
Port_route_tree *udp_port_tree() { return &_udp_port_tree; }
|
||||
Port_route_list *tcp_port_list() { return &_tcp_port_list; }
|
||||
Port_route_list *udp_port_list() { return &_udp_port_list; }
|
||||
};
|
||||
|
||||
class Net::Ip_route_list : public Genode::List<Ip_route>
|
||||
{
|
||||
public:
|
||||
|
||||
Ip_route *longest_prefix_match(Ipv4_address ip_addr);
|
||||
|
||||
void insert(Ip_route *route);
|
||||
};
|
||||
|
||||
#endif /* _IP_ROUTE_H_ */
|
25
repos/os/src/server/nic_router/ip_rule.cc
Normal file
25
repos/os/src/server/nic_router/ip_rule.cc
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* \brief IP routing entry
|
||||
* \author Martin Stein
|
||||
* \date 2016-08-19
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* local includes */
|
||||
#include <ip_rule.h>
|
||||
|
||||
using namespace Net;
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
Ip_rule::Ip_rule(Domain_tree &domains, Xml_node const &node)
|
||||
:
|
||||
Leaf_rule(domains, node),
|
||||
Direct_rule(node)
|
||||
{ }
|
35
repos/os/src/server/nic_router/ip_rule.h
Normal file
35
repos/os/src/server/nic_router/ip_rule.h
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* \brief IP routing entry
|
||||
* \author Martin Stein
|
||||
* \date 2016-08-19
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _IP_RULE_H_
|
||||
#define _IP_RULE_H_
|
||||
|
||||
/* local includes */
|
||||
#include <leaf_rule.h>
|
||||
#include <direct_rule.h>
|
||||
|
||||
namespace Net {
|
||||
|
||||
class Ip_rule;
|
||||
struct Ip_rule_list : Direct_rule_list<Ip_rule> { };
|
||||
}
|
||||
|
||||
|
||||
struct Net::Ip_rule : Leaf_rule, Direct_rule<Ip_rule>
|
||||
{
|
||||
public:
|
||||
|
||||
Ip_rule(Domain_tree &domains, Genode::Xml_node const &node);
|
||||
};
|
||||
|
||||
#endif /* _IP_RULE_H_ */
|
37
repos/os/src/server/nic_router/leaf_rule.cc
Normal file
37
repos/os/src/server/nic_router/leaf_rule.cc
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* \brief Routing rule that defines a target interface
|
||||
* \author Martin Stein
|
||||
* \date 2016-08-19
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* local includes */
|
||||
#include <leaf_rule.h>
|
||||
#include <domain.h>
|
||||
|
||||
using namespace Net;
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
Domain &Leaf_rule::_find_domain(Domain_tree &domains,
|
||||
Xml_node const &node)
|
||||
{
|
||||
try {
|
||||
return domains.find_by_name(
|
||||
Cstring(node.attribute("domain").value_base(),
|
||||
node.attribute("domain").value_size()));
|
||||
}
|
||||
catch (Domain_tree::No_match) { throw Invalid(); }
|
||||
}
|
||||
|
||||
|
||||
Leaf_rule::Leaf_rule(Domain_tree &domains, Xml_node const &node)
|
||||
:
|
||||
_domain(_find_domain(domains, node))
|
||||
{ }
|
50
repos/os/src/server/nic_router/leaf_rule.h
Normal file
50
repos/os/src/server/nic_router/leaf_rule.h
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* \brief Routing rule that defines a target interface
|
||||
* \author Martin Stein
|
||||
* \date 2016-08-19
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _LEAF_RULE_H_
|
||||
#define _LEAF_RULE_H_
|
||||
|
||||
/* local includes */
|
||||
#include <rule.h>
|
||||
|
||||
namespace Genode { class Xml_node; }
|
||||
|
||||
namespace Net {
|
||||
|
||||
class Domain;
|
||||
class Domain_tree;
|
||||
class Leaf_rule;
|
||||
}
|
||||
|
||||
class Net::Leaf_rule : public Rule
|
||||
{
|
||||
protected:
|
||||
|
||||
Domain &_domain;
|
||||
|
||||
static Domain &_find_domain(Domain_tree &domains,
|
||||
Genode::Xml_node const &node);
|
||||
|
||||
public:
|
||||
|
||||
Leaf_rule(Domain_tree &domains, Genode::Xml_node const &node);
|
||||
|
||||
|
||||
/***************
|
||||
** Accessors **
|
||||
***************/
|
||||
|
||||
Domain &domain() const { return _domain; }
|
||||
};
|
||||
|
||||
#endif /* _LEAF_RULE_H_ */
|
237
repos/os/src/server/nic_router/link.cc
Normal file
237
repos/os/src/server/nic_router/link.cc
Normal file
@ -0,0 +1,237 @@
|
||||
/*
|
||||
* \brief State tracking for UDP/TCP connections
|
||||
* \author Martin Stein
|
||||
* \date 2016-08-19
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <net/tcp.h>
|
||||
|
||||
/* local includes */
|
||||
#include <link.h>
|
||||
#include <interface.h>
|
||||
#include <configuration.h>
|
||||
#include <protocol_name.h>
|
||||
|
||||
using namespace Net;
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
/******************
|
||||
** Link_side_id **
|
||||
******************/
|
||||
|
||||
constexpr size_t Link_side_id::data_size()
|
||||
{
|
||||
return sizeof(src_ip) + sizeof(src_port) +
|
||||
sizeof(dst_ip) + sizeof(dst_port);
|
||||
}
|
||||
|
||||
|
||||
bool Link_side_id::operator == (Link_side_id const &id) const
|
||||
{
|
||||
return memcmp(id.data, data, data_size()) == 0;
|
||||
}
|
||||
|
||||
|
||||
bool Link_side_id::operator > (Link_side_id const &id) const
|
||||
{
|
||||
return memcmp(id.data, data, data_size()) > 0;
|
||||
}
|
||||
|
||||
|
||||
/***************
|
||||
** Link_side **
|
||||
***************/
|
||||
|
||||
Link_side::Link_side(Interface &interface,
|
||||
Link_side_id const &id,
|
||||
Link &link)
|
||||
:
|
||||
_interface(interface), _id(id), _link(link)
|
||||
{ }
|
||||
|
||||
|
||||
Link_side const &Link_side::find_by_id(Link_side_id const &id) const
|
||||
{
|
||||
if (id == _id) {
|
||||
return *this; }
|
||||
|
||||
bool const side = id > _id;
|
||||
Link_side *const link_side = Avl_node<Link_side>::child(side);
|
||||
if (!link_side) {
|
||||
throw Link_side_tree::No_match(); }
|
||||
|
||||
return link_side->find_by_id(id);
|
||||
}
|
||||
|
||||
|
||||
void Link_side::print(Output &output) const
|
||||
{
|
||||
Genode::print(output, "src ", src_ip(), ":", src_port(),
|
||||
" dst ", dst_ip(), ":", dst_port());
|
||||
}
|
||||
|
||||
|
||||
bool Link_side::is_client() const
|
||||
{
|
||||
return this == &_link.client();
|
||||
}
|
||||
|
||||
|
||||
/********************
|
||||
** Link_side_tree **
|
||||
********************/
|
||||
|
||||
Link_side const &Link_side_tree::find_by_id(Link_side_id const &id) const
|
||||
{
|
||||
Link_side *const link_side = first();
|
||||
if (!link_side) {
|
||||
throw No_match(); }
|
||||
|
||||
return link_side->find_by_id(id);
|
||||
}
|
||||
|
||||
|
||||
/**********
|
||||
** Link **
|
||||
**********/
|
||||
|
||||
void Link::print(Output &output) const
|
||||
{
|
||||
Genode::print(output, "CLN ", _client, " SRV ", _server);
|
||||
}
|
||||
|
||||
|
||||
Link::Link(Interface &cln_interface,
|
||||
Link_side_id const &cln_id,
|
||||
Pointer<Port_allocator_guard> const srv_port_alloc,
|
||||
Interface &srv_interface,
|
||||
Link_side_id const &srv_id,
|
||||
Genode::Timer &timer,
|
||||
Configuration &config,
|
||||
uint8_t const protocol)
|
||||
:
|
||||
_config(config),
|
||||
_client(cln_interface, cln_id, *this),
|
||||
_server_port_alloc(srv_port_alloc),
|
||||
_server(srv_interface, srv_id, *this),
|
||||
_close_timeout(timer, *this, &Link::_handle_close_timeout),
|
||||
_close_timeout_us(_config.rtt_sec() * 2 * 1000 * 1000),
|
||||
_protocol(protocol)
|
||||
{
|
||||
_close_timeout.start(_close_timeout_us);
|
||||
}
|
||||
|
||||
|
||||
void Link::_handle_close_timeout(Genode::Timer::Microseconds)
|
||||
{
|
||||
dissolve();
|
||||
_client._interface.link_closed(*this, _protocol);
|
||||
}
|
||||
|
||||
|
||||
void Link::dissolve()
|
||||
{
|
||||
_client._interface.dissolve_link(_client, _protocol);
|
||||
_server._interface.dissolve_link(_server, _protocol);
|
||||
if (_config.verbose()) {
|
||||
log("Dissolve ", protocol_name(_protocol), " link: ", *this); }
|
||||
|
||||
try {
|
||||
_server_port_alloc.deref().free(_server.dst_port());
|
||||
if (_config.verbose()) {
|
||||
log("Free ", protocol_name(_protocol),
|
||||
" port ", _server.dst_port(),
|
||||
" at ", _server.interface(),
|
||||
" that was used by ", _client.interface());
|
||||
}
|
||||
}
|
||||
catch (Pointer<Port_allocator_guard>::Invalid) { }
|
||||
}
|
||||
|
||||
|
||||
/**************
|
||||
** Tcp_link **
|
||||
**************/
|
||||
|
||||
Tcp_link::Tcp_link(Interface &cln_interface,
|
||||
Link_side_id const &cln_id,
|
||||
Pointer<Port_allocator_guard> const srv_port_alloc,
|
||||
Interface &srv_interface,
|
||||
Link_side_id const &srv_id,
|
||||
Genode::Timer &timer,
|
||||
Configuration &config,
|
||||
uint8_t const protocol)
|
||||
:
|
||||
Link(cln_interface, cln_id, srv_port_alloc, srv_interface, srv_id, timer,
|
||||
config, protocol)
|
||||
{ }
|
||||
|
||||
|
||||
void Tcp_link::_fin_acked()
|
||||
{
|
||||
if (_server_fin_acked && _client_fin_acked) {
|
||||
_close_timeout.start(_close_timeout_us);
|
||||
_closed = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Tcp_link::server_packet(Tcp_packet &tcp)
|
||||
{
|
||||
if (_closed) {
|
||||
return; }
|
||||
|
||||
if (tcp.fin()) {
|
||||
_server_fin = true; }
|
||||
|
||||
if (tcp.ack() && _client_fin) {
|
||||
_client_fin_acked = true;
|
||||
_fin_acked();
|
||||
}
|
||||
if (!_closed) {
|
||||
_packet(); }
|
||||
}
|
||||
|
||||
|
||||
void Tcp_link::client_packet(Tcp_packet &tcp)
|
||||
{
|
||||
if (_closed) {
|
||||
return; }
|
||||
|
||||
if (tcp.fin()) {
|
||||
_client_fin = true; }
|
||||
|
||||
if (tcp.ack() && _server_fin) {
|
||||
_server_fin_acked = true;
|
||||
_fin_acked();
|
||||
}
|
||||
if (!_closed) {
|
||||
_packet(); }
|
||||
}
|
||||
|
||||
|
||||
/**************
|
||||
** Udp_link **
|
||||
**************/
|
||||
|
||||
Udp_link::Udp_link(Interface &cln_interface,
|
||||
Link_side_id const &cln_id,
|
||||
Pointer<Port_allocator_guard> const srv_port_alloc,
|
||||
Interface &srv_interface,
|
||||
Link_side_id const &srv_id,
|
||||
Genode::Timer &timer,
|
||||
Configuration &config,
|
||||
uint8_t const protocol)
|
||||
:
|
||||
Link(cln_interface, cln_id, srv_port_alloc, srv_interface, srv_id, timer,
|
||||
config, protocol)
|
||||
{ }
|
213
repos/os/src/server/nic_router/link.h
Normal file
213
repos/os/src/server/nic_router/link.h
Normal file
@ -0,0 +1,213 @@
|
||||
/*
|
||||
* \brief State tracking for UDP/TCP connections
|
||||
* \author Martin Stein
|
||||
* \date 2016-08-19
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _LINK_H_
|
||||
#define _LINK_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <os/timer.h>
|
||||
#include <util/avl_tree.h>
|
||||
#include <util/list.h>
|
||||
#include <net/ipv4.h>
|
||||
|
||||
/* local includes */
|
||||
#include <pointer.h>
|
||||
|
||||
namespace Net {
|
||||
|
||||
class Configuration;
|
||||
class Port_allocator_guard;
|
||||
class Tcp_packet;
|
||||
class Interface;
|
||||
class Link_side_id;
|
||||
class Link_side;
|
||||
class Link_side_tree;
|
||||
class Link;
|
||||
struct Link_list : Genode::List<Link> { };
|
||||
class Tcp_link;
|
||||
class Udp_link;
|
||||
}
|
||||
|
||||
|
||||
struct Net::Link_side_id
|
||||
{
|
||||
int const data[];
|
||||
Ipv4_address const src_ip;
|
||||
Genode::uint16_t const src_port;
|
||||
Ipv4_address const dst_ip;
|
||||
Genode::uint16_t const dst_port;
|
||||
|
||||
static constexpr Genode::size_t data_size();
|
||||
|
||||
|
||||
/************************
|
||||
** Standard operators **
|
||||
************************/
|
||||
|
||||
bool operator == (Link_side_id const &id) const;
|
||||
|
||||
bool operator > (Link_side_id const &id) const;
|
||||
}
|
||||
__attribute__((__packed__));
|
||||
|
||||
|
||||
class Net::Link_side : public Genode::Avl_node<Link_side>
|
||||
{
|
||||
friend class Link;
|
||||
|
||||
private:
|
||||
|
||||
Interface &_interface;
|
||||
Link_side_id const _id;
|
||||
Link &_link;
|
||||
|
||||
public:
|
||||
|
||||
Link_side(Interface &interface,
|
||||
Link_side_id const &id,
|
||||
Link &link);
|
||||
|
||||
Link_side const &find_by_id(Link_side_id const &id) const;
|
||||
|
||||
bool is_client() const;
|
||||
|
||||
|
||||
/**************
|
||||
** Avl_node **
|
||||
**************/
|
||||
|
||||
bool higher(Link_side *side) { return side->_id > _id; }
|
||||
|
||||
|
||||
/*********
|
||||
** Log **
|
||||
*********/
|
||||
|
||||
void print(Genode::Output &output) const;
|
||||
|
||||
|
||||
/***************
|
||||
** Accessors **
|
||||
***************/
|
||||
|
||||
Interface &interface() const { return _interface; }
|
||||
Link &link() const { return _link; }
|
||||
Ipv4_address const &src_ip() const { return _id.src_ip; }
|
||||
Ipv4_address const &dst_ip() const { return _id.dst_ip; }
|
||||
Genode::uint16_t src_port() const { return _id.src_port; }
|
||||
Genode::uint16_t dst_port() const { return _id.dst_port; }
|
||||
};
|
||||
|
||||
|
||||
struct Net::Link_side_tree : Genode::Avl_tree<Link_side>
|
||||
{
|
||||
struct No_match : Genode::Exception { };
|
||||
|
||||
Link_side const &find_by_id(Link_side_id const &id) const;
|
||||
};
|
||||
|
||||
|
||||
class Net::Link : public Link_list::Element
|
||||
{
|
||||
protected:
|
||||
|
||||
using Signal_handler = Genode::Signal_handler<Link>;
|
||||
|
||||
Configuration &_config;
|
||||
Link_side _client;
|
||||
Pointer<Port_allocator_guard> const _server_port_alloc;
|
||||
Link_side _server;
|
||||
Genode::One_shot_timeout<Link> _close_timeout;
|
||||
Genode::Timer::Microseconds const _close_timeout_us;
|
||||
Genode::uint8_t const _protocol;
|
||||
|
||||
void _handle_close_timeout(Genode::Timer::Microseconds);
|
||||
|
||||
void _packet() { _close_timeout.start(_close_timeout_us); }
|
||||
|
||||
public:
|
||||
|
||||
struct No_port_allocator : Genode::Exception { };
|
||||
|
||||
Link(Interface &cln_interface,
|
||||
Link_side_id const &cln_id,
|
||||
Pointer<Port_allocator_guard> const srv_port_alloc,
|
||||
Interface &srv_interface,
|
||||
Link_side_id const &srv_id,
|
||||
Genode::Timer &timer,
|
||||
Configuration &config,
|
||||
Genode::uint8_t const protocol);
|
||||
|
||||
void dissolve();
|
||||
|
||||
|
||||
/*********
|
||||
** Log **
|
||||
*********/
|
||||
|
||||
void print(Genode::Output &output) const;
|
||||
|
||||
|
||||
/***************
|
||||
** Accessors **
|
||||
***************/
|
||||
|
||||
Link_side &client() { return _client; }
|
||||
Link_side &server() { return _server; }
|
||||
};
|
||||
|
||||
|
||||
class Net::Tcp_link : public Link
|
||||
{
|
||||
private:
|
||||
|
||||
bool _client_fin = false;
|
||||
bool _server_fin = false;
|
||||
bool _client_fin_acked = false;
|
||||
bool _server_fin_acked = false;
|
||||
bool _closed = false;
|
||||
|
||||
void _fin_acked();
|
||||
|
||||
public:
|
||||
|
||||
Tcp_link(Interface &cln_interface,
|
||||
Link_side_id const &cln_id,
|
||||
Pointer<Port_allocator_guard> const srv_port_alloc,
|
||||
Interface &srv_interface,
|
||||
Link_side_id const &srv_id,
|
||||
Genode::Timer &timer,
|
||||
Configuration &config,
|
||||
Genode::uint8_t const protocol);
|
||||
|
||||
void client_packet(Tcp_packet &tcp);
|
||||
|
||||
void server_packet(Tcp_packet &tcp);
|
||||
};
|
||||
|
||||
|
||||
struct Net::Udp_link : Link
|
||||
{
|
||||
Udp_link(Interface &cln_interface,
|
||||
Link_side_id const &cln_id,
|
||||
Pointer<Port_allocator_guard> const srv_port_alloc,
|
||||
Interface &srv_interface,
|
||||
Link_side_id const &srv_id,
|
||||
Genode::Timer &timer,
|
||||
Configuration &config,
|
||||
Genode::uint8_t const protocol);
|
||||
|
||||
void packet() { _packet(); }
|
||||
};
|
||||
|
||||
#endif /* _LINK_H_ */
|
@ -1,21 +1,17 @@
|
||||
/*
|
||||
* \brief MAC-address allocator
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2010-08-25
|
||||
* \author Martin Stein
|
||||
* \date 2016-10-24
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010-2013 Genode Labs GmbH
|
||||
* Copyright (C) 2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#include <mac_allocator.h>
|
||||
/* Genode includes */
|
||||
#include <nic_bridge/mac_allocator.h>
|
||||
|
||||
/**
|
||||
* We take the range 02:02:02:02:02:XX for our MAC address allocator,
|
||||
* it's likely, that we will have no clashes here.
|
||||
* (e.g. Linux uses 02:00... for its tap-devices.)
|
||||
*/
|
||||
Net::Mac_address Net::Mac_allocator::mac_addr_base(0x03);
|
||||
|
@ -12,118 +12,53 @@
|
||||
*/
|
||||
|
||||
/* Genode */
|
||||
#include <base/component.h>
|
||||
#include <base/heap.h>
|
||||
#include <os/config.h>
|
||||
#include <os/timer.h>
|
||||
#include <nic/xml_node.h>
|
||||
#include <os/server.h>
|
||||
#include <timer_session/connection.h>
|
||||
|
||||
/* local includes */
|
||||
#include <component.h>
|
||||
#include <arp_cache.h>
|
||||
#include <uplink.h>
|
||||
#include <port_allocator.h>
|
||||
#include <configuration.h>
|
||||
|
||||
using namespace Net;
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
unsigned read_rtt_sec()
|
||||
{
|
||||
unsigned rtt_sec = config()->xml_node().attribute_value("rtt_sec", 0UL);
|
||||
if (!rtt_sec) {
|
||||
rtt_sec = 3;
|
||||
warning("missing 'rtt_sec' attribute in config tag,",
|
||||
"using default value \"3\"");
|
||||
}
|
||||
return rtt_sec;
|
||||
}
|
||||
|
||||
|
||||
class Main
|
||||
{
|
||||
private:
|
||||
|
||||
bool const _verbose;
|
||||
Port_allocator _tcp_port_alloc;
|
||||
Port_allocator _udp_port_alloc;
|
||||
Server::Entrypoint &_ep;
|
||||
Interface_tree _interface_tree;
|
||||
Arp_cache _arp_cache;
|
||||
Arp_waiter_list _arp_waiters;
|
||||
Tcp_proxy_list _tcp_proxys;
|
||||
Udp_proxy_list _udp_proxys;
|
||||
unsigned _rtt_sec;
|
||||
Uplink _uplink;
|
||||
Net::Root _root;
|
||||
|
||||
void _read_ports(Genode::Xml_node &route, char const *name,
|
||||
Port_allocator &_port_alloc);
|
||||
|
||||
Timer::Connection _timer_connection;
|
||||
Genode::Timer _timer;
|
||||
Genode::Heap _heap;
|
||||
Configuration _config;
|
||||
Uplink _uplink;
|
||||
Net::Root _root;
|
||||
|
||||
public:
|
||||
|
||||
Main(Server::Entrypoint &ep);
|
||||
Main(Env &env);
|
||||
};
|
||||
|
||||
|
||||
void Main::_read_ports(Xml_node &route, char const *name,
|
||||
Port_allocator &port_alloc)
|
||||
{
|
||||
try {
|
||||
for (Xml_node port = route.sub_node(name); ; port = port.next(name)) {
|
||||
uint32_t const dst = port.attribute_value("dst", 0UL);
|
||||
if (!dst) {
|
||||
warning("missing 'dst' attribute in port route");
|
||||
continue;
|
||||
}
|
||||
if (dst >= Port_allocator::FIRST &&
|
||||
dst < Port_allocator::FIRST + Port_allocator::COUNT)
|
||||
{
|
||||
error("port forwarding clashes with dynamic port range"); }
|
||||
}
|
||||
} catch (Xml_node::Nonexistent_sub_node) { }
|
||||
}
|
||||
|
||||
|
||||
Main::Main(Server::Entrypoint &ep)
|
||||
Main::Main(Env &env)
|
||||
:
|
||||
_verbose(config()->xml_node().attribute_value("verbose", false)),
|
||||
_ep(ep), _rtt_sec(read_rtt_sec()),
|
||||
|
||||
_uplink(_ep, _tcp_port_alloc, _udp_port_alloc, _tcp_proxys,
|
||||
_udp_proxys, _rtt_sec, _interface_tree, _arp_cache,
|
||||
_arp_waiters, _verbose),
|
||||
|
||||
_root(_ep, *env()->heap(), _uplink.router_mac(), _tcp_port_alloc,
|
||||
_udp_port_alloc, _tcp_proxys, _udp_proxys,
|
||||
_rtt_sec, _interface_tree, _arp_cache, _arp_waiters, _verbose)
|
||||
_timer_connection(env), _timer(_timer_connection, env.ep()),
|
||||
_heap(&env.ram(), &env.rm()), _config(config()->xml_node(), _heap),
|
||||
_uplink(env.ep(), _timer, _heap, _config),
|
||||
_root(env.ep(), _timer, _heap, _uplink.router_mac(), _config, env.ram())
|
||||
{
|
||||
/* reserve all ports that are used in port routes */
|
||||
try {
|
||||
Xml_node policy = config()->xml_node().sub_node("policy");
|
||||
for (; ; policy = policy.next("policy")) {
|
||||
try {
|
||||
Xml_node route = policy.sub_node("ip");
|
||||
for (; ; route = route.next("ip")) {
|
||||
_read_ports(route, "tcp", _tcp_port_alloc);
|
||||
_read_ports(route, "udp", _udp_port_alloc);
|
||||
}
|
||||
} catch (Xml_node::Nonexistent_sub_node) { }
|
||||
}
|
||||
} catch (Xml_node::Nonexistent_sub_node) { }
|
||||
|
||||
/* announce service */
|
||||
env()->parent()->announce(ep.manage(_root));
|
||||
env.parent().announce(env.ep().manage(_root));
|
||||
}
|
||||
|
||||
|
||||
/************
|
||||
** Server **
|
||||
************/
|
||||
/***************
|
||||
** Component **
|
||||
***************/
|
||||
|
||||
namespace Server {
|
||||
|
||||
char const *name() { return "nic_router_ep"; }
|
||||
|
||||
size_t stack_size() { return 4096 *sizeof(addr_t); }
|
||||
|
||||
void construct(Entrypoint &ep) { static Main router(ep); }
|
||||
}
|
||||
size_t Component::stack_size() { return 4 * 1024 * sizeof(addr_t); }
|
||||
void Component::construct(Env &env) { static Main main(env); }
|
||||
|
84
repos/os/src/server/nic_router/nat_rule.cc
Normal file
84
repos/os/src/server/nic_router/nat_rule.cc
Normal file
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* \brief Rule for doing NAT from one given interface to another
|
||||
* \author Martin Stein
|
||||
* \date 2016-09-13
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/xml_node.h>
|
||||
#include <base/log.h>
|
||||
#include <net/tcp.h>
|
||||
#include <net/udp.h>
|
||||
|
||||
/* local includes */
|
||||
#include <nat_rule.h>
|
||||
#include <domain.h>
|
||||
#include <interface.h>
|
||||
|
||||
using namespace Net;
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
bool Nat_rule::higher(Nat_rule *rule)
|
||||
{
|
||||
return (addr_t)&rule->domain() > (addr_t)&_domain;
|
||||
}
|
||||
|
||||
|
||||
Nat_rule::Nat_rule(Domain_tree &domains,
|
||||
Port_allocator &tcp_port_alloc,
|
||||
Port_allocator &udp_port_alloc,
|
||||
Xml_node const &node)
|
||||
:
|
||||
Leaf_rule(domains, node),
|
||||
_tcp_port_alloc(tcp_port_alloc, node.attribute_value("tcp-ports", 0UL)),
|
||||
_udp_port_alloc(udp_port_alloc, node.attribute_value("udp-ports", 0UL))
|
||||
{ }
|
||||
|
||||
|
||||
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<Nat_rule>::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,
|
||||
" tcp-ports ", _tcp_port_alloc.max(),
|
||||
" udp-ports ", _udp_port_alloc.max());
|
||||
}
|
||||
|
||||
|
||||
Port_allocator_guard &Nat_rule::port_alloc(uint8_t const prot)
|
||||
{
|
||||
switch (prot) {
|
||||
case Tcp_packet::IP_ID: return _tcp_port_alloc;
|
||||
case Udp_packet::IP_ID: return _udp_port_alloc;
|
||||
default: throw Interface::Bad_transport_protocol(); }
|
||||
}
|
83
repos/os/src/server/nic_router/nat_rule.h
Normal file
83
repos/os/src/server/nic_router/nat_rule.h
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* \brief Rule for doing NAT from one given interface to another
|
||||
* \author Martin Stein
|
||||
* \date 2016-09-13
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _NAT_RULE_H_
|
||||
#define _NAT_RULE_H_
|
||||
|
||||
/* local includes */
|
||||
#include <port_allocator.h>
|
||||
#include <leaf_rule.h>
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/avl_string.h>
|
||||
|
||||
namespace Net {
|
||||
|
||||
class Port_allocator;
|
||||
class Nat_rule_base;
|
||||
class Nat_rule;
|
||||
class Nat_rule_tree;
|
||||
}
|
||||
|
||||
|
||||
class Net::Nat_rule : public Leaf_rule,
|
||||
public Genode::Avl_node<Nat_rule>
|
||||
{
|
||||
private:
|
||||
|
||||
Port_allocator_guard _tcp_port_alloc;
|
||||
Port_allocator_guard _udp_port_alloc;
|
||||
|
||||
public:
|
||||
|
||||
Nat_rule(Domain_tree &domains,
|
||||
Port_allocator &tcp_port_alloc,
|
||||
Port_allocator &udp_port_alloc,
|
||||
Genode::Xml_node const &node);
|
||||
|
||||
Nat_rule &find_by_domain(Domain &domain);
|
||||
|
||||
Port_allocator_guard &port_alloc(Genode::uint8_t const prot);
|
||||
|
||||
|
||||
/*********
|
||||
** log **
|
||||
*********/
|
||||
|
||||
void print(Genode::Output &output) const;
|
||||
|
||||
|
||||
/**************
|
||||
** Avl_node **
|
||||
**************/
|
||||
|
||||
bool higher(Nat_rule *rule);
|
||||
|
||||
|
||||
/***************
|
||||
** Accessors **
|
||||
***************/
|
||||
|
||||
Port_allocator_guard &tcp_port_alloc() { return _tcp_port_alloc; }
|
||||
Port_allocator_guard &udp_port_alloc() { return _udp_port_alloc; }
|
||||
};
|
||||
|
||||
|
||||
struct Net::Nat_rule_tree : Genode::Avl_tree<Nat_rule>
|
||||
{
|
||||
struct No_match : Genode::Exception { };
|
||||
|
||||
Nat_rule &find_by_domain(Domain &domain);
|
||||
};
|
||||
|
||||
#endif /* _NAT_RULE_H_ */
|
106
repos/os/src/server/nic_router/permit_rule.cc
Normal file
106
repos/os/src/server/nic_router/permit_rule.cc
Normal file
@ -0,0 +1,106 @@
|
||||
/*
|
||||
* \brief Rule for permitting ports in the context of a transport rule
|
||||
* \author Martin Stein
|
||||
* \date 2016-08-19
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/log.h>
|
||||
|
||||
/* local includes */
|
||||
#include <permit_rule.h>
|
||||
#include <domain.h>
|
||||
|
||||
using namespace Net;
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
/*****************
|
||||
** Permit_rule **
|
||||
*****************/
|
||||
|
||||
Permit_rule::Permit_rule(Domain_tree &domains, Xml_node const &node)
|
||||
:
|
||||
Leaf_rule(domains, node)
|
||||
{ }
|
||||
|
||||
|
||||
/*********************
|
||||
** Permit_any_rule **
|
||||
*********************/
|
||||
|
||||
void Permit_any_rule::print(Output &output) const
|
||||
{
|
||||
Genode::print(output, "requests to ", _domain);
|
||||
}
|
||||
|
||||
|
||||
Permit_any_rule::Permit_any_rule(Domain_tree &domains, Xml_node const &node)
|
||||
:
|
||||
Permit_rule(domains, node)
|
||||
{ }
|
||||
|
||||
|
||||
/************************
|
||||
** Permit_single_rule **
|
||||
************************/
|
||||
|
||||
bool Permit_single_rule::higher(Permit_single_rule *rule)
|
||||
{
|
||||
return rule->_port > _port;
|
||||
}
|
||||
|
||||
|
||||
void Permit_single_rule::print(Output &output) const
|
||||
{
|
||||
Genode::print(output, "port ", _port, " requests to ", _domain);
|
||||
}
|
||||
|
||||
|
||||
Permit_single_rule::Permit_single_rule(Domain_tree &domains,
|
||||
Xml_node const &node)
|
||||
:
|
||||
Permit_rule(domains, node),
|
||||
_port(node.attribute_value("port", 0UL))
|
||||
{
|
||||
if (!_port || dynamic_port(_port)) {
|
||||
throw Invalid(); }
|
||||
}
|
||||
|
||||
|
||||
Permit_single_rule const &
|
||||
Permit_single_rule::find_by_port(uint16_t const port) const
|
||||
{
|
||||
if (port == _port) {
|
||||
return *this; }
|
||||
|
||||
bool const side = port > _port;
|
||||
Permit_single_rule *const rule = Avl_node<Permit_single_rule>::child(side);
|
||||
if (!rule) {
|
||||
throw Permit_single_rule_tree::No_match(); }
|
||||
|
||||
return rule->find_by_port(port);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*****************************
|
||||
** Permit_single_rule_tree **
|
||||
*****************************/
|
||||
|
||||
Permit_single_rule const &
|
||||
Permit_single_rule_tree::find_by_port(uint16_t const port) const
|
||||
{
|
||||
Permit_single_rule *const rule = first();
|
||||
if (!rule) {
|
||||
throw No_match(); }
|
||||
|
||||
return rule->find_by_port(port);
|
||||
}
|
105
repos/os/src/server/nic_router/permit_rule.h
Normal file
105
repos/os/src/server/nic_router/permit_rule.h
Normal file
@ -0,0 +1,105 @@
|
||||
/*
|
||||
* \brief Rules for permitting ports in the context of a transport rule
|
||||
* \author Martin Stein
|
||||
* \date 2016-08-19
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _PERMIT_RULE_H_
|
||||
#define _PERMIT_RULE_H_
|
||||
|
||||
/* local includes */
|
||||
#include <leaf_rule.h>
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/avl_tree.h>
|
||||
|
||||
namespace Genode { class Output; }
|
||||
|
||||
namespace Net {
|
||||
|
||||
class Permit_rule;
|
||||
class Permit_any_rule;
|
||||
class Permit_single_rule;
|
||||
class Permit_single_rule_tree;
|
||||
}
|
||||
|
||||
|
||||
struct Net::Permit_rule : Leaf_rule
|
||||
{
|
||||
Permit_rule(Domain_tree &domains, Genode::Xml_node const &node);
|
||||
|
||||
|
||||
/*********
|
||||
** log **
|
||||
*********/
|
||||
|
||||
virtual void print(Genode::Output &output) const = 0;
|
||||
};
|
||||
|
||||
|
||||
struct Net::Permit_any_rule : Permit_rule
|
||||
{
|
||||
Permit_any_rule(Domain_tree &domains, Genode::Xml_node const &node);
|
||||
|
||||
|
||||
/*********
|
||||
** log **
|
||||
*********/
|
||||
|
||||
void print(Genode::Output &output) const;
|
||||
};
|
||||
|
||||
|
||||
class Net::Permit_single_rule : public Permit_rule,
|
||||
public Genode::Avl_node<Permit_single_rule>
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::uint16_t const _port;
|
||||
|
||||
public:
|
||||
|
||||
Permit_single_rule(Domain_tree &domains,
|
||||
Genode::Xml_node const &node);
|
||||
|
||||
Permit_single_rule const &
|
||||
find_by_port(Genode::uint16_t const port) const;
|
||||
|
||||
|
||||
/*********
|
||||
** log **
|
||||
*********/
|
||||
|
||||
void print(Genode::Output &output) const;
|
||||
|
||||
|
||||
/**************
|
||||
** Avl_node **
|
||||
**************/
|
||||
|
||||
bool higher(Permit_single_rule *rule);
|
||||
|
||||
|
||||
/***************
|
||||
** Accessors **
|
||||
***************/
|
||||
|
||||
Genode::uint16_t port() const { return _port; }
|
||||
};
|
||||
|
||||
|
||||
struct Net::Permit_single_rule_tree : Genode::Avl_tree<Permit_single_rule>
|
||||
{
|
||||
struct No_match : Genode::Exception { };
|
||||
|
||||
Permit_single_rule const &find_by_port(Genode::uint16_t const port) const;
|
||||
};
|
||||
|
||||
#endif /* _PERMIT_RULE_H_ */
|
55
repos/os/src/server/nic_router/pointer.h
Normal file
55
repos/os/src/server/nic_router/pointer.h
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* \brief Pointer that can be dereferenced only when valid
|
||||
* \author Martin Stein
|
||||
* \date 2016-08-24
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _POINTER_H_
|
||||
#define _POINTER_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/exception.h>
|
||||
|
||||
namespace Net { template <typename> class Pointer; }
|
||||
|
||||
template <typename T>
|
||||
class Net::Pointer
|
||||
{
|
||||
private:
|
||||
|
||||
T *_ptr;
|
||||
|
||||
public:
|
||||
|
||||
struct Valid : Genode::Exception { };
|
||||
struct Invalid : Genode::Exception { };
|
||||
|
||||
Pointer() : _ptr(nullptr) { }
|
||||
|
||||
T &deref() const
|
||||
{
|
||||
if (_ptr == nullptr) {
|
||||
throw Invalid(); }
|
||||
|
||||
return *_ptr;
|
||||
}
|
||||
|
||||
void set(T &ptr)
|
||||
{
|
||||
if (_ptr != nullptr) {
|
||||
throw Valid(); }
|
||||
|
||||
_ptr = &ptr;
|
||||
}
|
||||
|
||||
void unset() { _ptr = nullptr; }
|
||||
};
|
||||
|
||||
#endif /* _POINTER_H_ */
|
@ -18,8 +18,33 @@ using namespace Net;
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
Port_allocator::Port_allocator()
|
||||
Genode::uint16_t Port_allocator_guard::alloc()
|
||||
{
|
||||
try { alloc_index(0); }
|
||||
catch (Already_allocated) { throw Failed_to_reserve_port_0(); }
|
||||
if (_used == _max) {
|
||||
throw Out_of_indices(); }
|
||||
|
||||
uint16_t const port = _port_alloc.alloc();
|
||||
_used++;
|
||||
return port;
|
||||
}
|
||||
|
||||
|
||||
void Port_allocator_guard::free(Genode::uint16_t port)
|
||||
{
|
||||
_port_alloc.free(port);
|
||||
_used = _used ? _used - 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
Port_allocator_guard::Port_allocator_guard(Port_allocator & port_alloc,
|
||||
unsigned const max)
|
||||
:
|
||||
_port_alloc(port_alloc), _max(max)
|
||||
{ }
|
||||
|
||||
|
||||
bool Net::dynamic_port(uint16_t const port)
|
||||
{
|
||||
return port >= Port_allocator::FIRST &&
|
||||
port < (uint32_t)Port_allocator::FIRST + Port_allocator::COUNT;
|
||||
}
|
||||
|
@ -18,7 +18,14 @@
|
||||
/* Genode includes */
|
||||
#include <util/bit_allocator.h>
|
||||
|
||||
namespace Net { class Port_allocator; }
|
||||
namespace Net {
|
||||
|
||||
class Port_allocator;
|
||||
class Port_allocator_guard;
|
||||
|
||||
bool dynamic_port(Genode::uint16_t const port);
|
||||
}
|
||||
|
||||
|
||||
class Net::Port_allocator
|
||||
{
|
||||
@ -37,4 +44,26 @@ class Net::Port_allocator
|
||||
void free(Genode::uint16_t port) { _alloc.free(port - FIRST); }
|
||||
};
|
||||
|
||||
|
||||
class Net::Port_allocator_guard
|
||||
{
|
||||
private:
|
||||
|
||||
Port_allocator &_port_alloc;
|
||||
unsigned const _max;
|
||||
unsigned _used = 0;
|
||||
|
||||
public:
|
||||
|
||||
class Out_of_indices : Genode::Exception {};
|
||||
|
||||
Genode::uint16_t alloc();
|
||||
|
||||
void free(Genode::uint16_t port);
|
||||
|
||||
Port_allocator_guard(Port_allocator & port_alloc, unsigned const max);
|
||||
|
||||
unsigned max() const { return _max; }
|
||||
};
|
||||
|
||||
#endif /* _PORT_ALLOCATOR_H_ */
|
||||
|
@ -1,54 +0,0 @@
|
||||
/*
|
||||
* \brief Port routing entry
|
||||
* \author Martin Stein
|
||||
* \date 2016-08-19
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* local includes */
|
||||
#include <port_route.h>
|
||||
|
||||
using namespace Net;
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
Port_route::Port_route(uint16_t dst, char const *label, size_t label_size,
|
||||
Ipv4_address via, Ipv4_address to)
|
||||
:
|
||||
_dst(dst), _label(Genode::Cstring(label, label_size)), _via(via), _to(to)
|
||||
{ }
|
||||
|
||||
|
||||
void Port_route::print(Output &output) const
|
||||
{
|
||||
Genode::print(output, "", _dst, " -> \"", _label, "\" to ", _to,
|
||||
" via ", _via);
|
||||
}
|
||||
|
||||
|
||||
Port_route *Port_route::find_by_dst(uint16_t dst)
|
||||
{
|
||||
if (dst == _dst) {
|
||||
return this; }
|
||||
|
||||
bool const side = dst > _dst;
|
||||
Port_route *c = Avl_node<Port_route>::child(side);
|
||||
return c ? c->find_by_dst(dst) : 0;
|
||||
}
|
||||
|
||||
|
||||
Port_route *Port_route_tree::find_by_dst(uint16_t dst)
|
||||
{
|
||||
Port_route *port = first();
|
||||
if (!port) {
|
||||
return port; }
|
||||
|
||||
port = port->find_by_dst(dst);
|
||||
return port;
|
||||
}
|
@ -1,75 +0,0 @@
|
||||
/*
|
||||
* \brief Port routing entry
|
||||
* \author Martin Stein
|
||||
* \date 2016-08-19
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/session_label.h>
|
||||
#include <util/avl_tree.h>
|
||||
#include <util/list.h>
|
||||
#include <net/ipv4.h>
|
||||
|
||||
#ifndef _PORT_ROUTE_H_
|
||||
#define _PORT_ROUTE_H_
|
||||
|
||||
namespace Net {
|
||||
|
||||
class Port_route;
|
||||
class Port_route_tree;
|
||||
using Port_route_list = Genode::List<Port_route>;
|
||||
}
|
||||
|
||||
|
||||
class Net::Port_route : public Genode::Avl_node<Port_route>,
|
||||
public Port_route_list::Element
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::uint16_t _dst;
|
||||
Genode::Session_label _label;
|
||||
Ipv4_address _via;
|
||||
Ipv4_address _to;
|
||||
|
||||
public:
|
||||
|
||||
Port_route(Genode::uint16_t dst, char const *label,
|
||||
Genode::size_t label_size, Ipv4_address via,
|
||||
Ipv4_address to);
|
||||
|
||||
void print(Genode::Output &output) const;
|
||||
|
||||
Port_route *find_by_dst(Genode::uint16_t dst);
|
||||
|
||||
|
||||
/**************
|
||||
** Avl_node **
|
||||
**************/
|
||||
|
||||
bool higher(Port_route *route) { return route->_dst > _dst; }
|
||||
|
||||
|
||||
/***************
|
||||
** Accessors **
|
||||
***************/
|
||||
|
||||
Genode::Session_label &label() { return _label; }
|
||||
Ipv4_address via() { return _via; }
|
||||
Ipv4_address to() { return _to; }
|
||||
Genode::uint16_t dst() { return _dst; }
|
||||
};
|
||||
|
||||
|
||||
struct Net::Port_route_tree : Genode::Avl_tree<Port_route>
|
||||
{
|
||||
Port_route *find_by_dst(Genode::uint16_t dst);
|
||||
};
|
||||
|
||||
#endif /* _PORT_ROUTE_H_ */
|
39
repos/os/src/server/nic_router/protocol_name.cc
Normal file
39
repos/os/src/server/nic_router/protocol_name.cc
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* \brief Provide protocol names as Genode Cstring objects
|
||||
* \author Martin Stein
|
||||
* \date 2016-08-19
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* local includes */
|
||||
#include <protocol_name.h>
|
||||
#include <interface.h>
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/string.h>
|
||||
#include <net/tcp.h>
|
||||
#include <net/udp.h>
|
||||
|
||||
using namespace Net;
|
||||
using namespace Genode;
|
||||
|
||||
static Cstring const _udp_name("UDP");
|
||||
static Cstring const _tcp_name("TCP");
|
||||
|
||||
Cstring const &Net::udp_name() { return _udp_name; }
|
||||
Cstring const &Net::tcp_name() { return _tcp_name; }
|
||||
|
||||
|
||||
Cstring const &Net::protocol_name(uint8_t protocol)
|
||||
{
|
||||
switch (protocol) {
|
||||
case Tcp_packet::IP_ID: return tcp_name();
|
||||
case Udp_packet::IP_ID: return udp_name();
|
||||
default: throw Interface::Bad_transport_protocol(); }
|
||||
}
|
29
repos/os/src/server/nic_router/protocol_name.h
Normal file
29
repos/os/src/server/nic_router/protocol_name.h
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* \brief Provide protocol names as Genode Cstring objects
|
||||
* \author Martin Stein
|
||||
* \date 2016-08-19
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _PROTOCOL_NAME_H_
|
||||
#define _PROTOCOL_NAME_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/stdint.h>
|
||||
|
||||
namespace Genode { class Cstring; }
|
||||
|
||||
namespace Net {
|
||||
|
||||
Genode::Cstring const &tcp_name();
|
||||
Genode::Cstring const &udp_name();
|
||||
Genode::Cstring const &protocol_name(Genode::uint8_t protocol);
|
||||
}
|
||||
|
||||
#endif /* _PROTOCOL_NAME_H_ */
|
@ -1,120 +0,0 @@
|
||||
/*
|
||||
* \brief UDP/TCP proxy session
|
||||
* \author Martin Stein
|
||||
* \date 2016-08-19
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <net/tcp.h>
|
||||
#include <net/udp.h>
|
||||
#include <base/log.h>
|
||||
|
||||
/* local includes */
|
||||
#include <proxy.h>
|
||||
|
||||
using namespace Net;
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
Tcp_proxy::Tcp_proxy(uint16_t client_port, uint16_t proxy_port,
|
||||
Ipv4_address client_ip, Ipv4_address proxy_ip,
|
||||
Interface &client, Genode::Entrypoint &ep,
|
||||
unsigned const rtt_sec)
|
||||
:
|
||||
_client_port(client_port), _proxy_port(proxy_port), _client_ip(client_ip),
|
||||
_proxy_ip(proxy_ip), _client(client),
|
||||
_del_timeout(ep, *this, &Tcp_proxy::_del_timeout_handle),
|
||||
_del_timeout_us(rtt_sec * 2 * 1000 * 1000)
|
||||
{ }
|
||||
|
||||
|
||||
bool Tcp_proxy::matches_client(Ipv4_address client_ip, uint16_t client_port)
|
||||
{
|
||||
return client_ip == _client_ip && client_port == _client_port;
|
||||
}
|
||||
|
||||
|
||||
bool Tcp_proxy::matches_proxy(Ipv4_address proxy_ip, uint16_t proxy_port)
|
||||
{
|
||||
return proxy_ip == _proxy_ip && proxy_port == _proxy_port;
|
||||
}
|
||||
|
||||
|
||||
void Tcp_proxy::tcp_packet(Ipv4_packet * const ip, Tcp_packet * const tcp)
|
||||
{
|
||||
/* find out which side sent the packet */
|
||||
bool from_client;
|
||||
if (tcp->src_port() == _client_port) { from_client = true; }
|
||||
else { from_client = false; }
|
||||
|
||||
/* Remember FIN packets and which side sent them */
|
||||
if (tcp->fin()) {
|
||||
if (from_client) { _client_fin = true; }
|
||||
else { _other_fin = true; }
|
||||
}
|
||||
/* look for packets that ACK a previous FIN and remember those ACKs */
|
||||
if (tcp->ack()) {
|
||||
if (from_client && _other_fin) { _other_fin_acked = true; }
|
||||
if (!from_client && _client_fin) { _client_fin_acked = true; }
|
||||
|
||||
/* if both sides sent a FIN and got ACKed, init delayed destruction */
|
||||
if (_other_fin_acked && _client_fin_acked) {
|
||||
_timer.sigh(_del_timeout);
|
||||
_timer.trigger_once(_del_timeout_us);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Udp_proxy::print(Output &out) const
|
||||
{
|
||||
Genode::print(out, _client_ip, ":", _client_port, " -> ",
|
||||
_proxy_ip, ":", _proxy_port);
|
||||
}
|
||||
|
||||
|
||||
void Tcp_proxy::print(Output &out) const
|
||||
{
|
||||
Genode::print(out, _client_ip, ":", _client_port, " -> ",
|
||||
_proxy_ip, ":", _proxy_port);
|
||||
}
|
||||
|
||||
|
||||
Udp_proxy::Udp_proxy(uint16_t client_port, uint16_t proxy_port,
|
||||
Ipv4_address client_ip, Ipv4_address proxy_ip,
|
||||
Interface &client, Genode::Entrypoint &ep,
|
||||
unsigned const rtt_sec)
|
||||
:
|
||||
_client_port(client_port), _proxy_port(proxy_port), _client_ip(client_ip),
|
||||
_proxy_ip(proxy_ip), _client(client),
|
||||
_del_timeout(ep, *this, &Udp_proxy::_del_timeout_handle),
|
||||
_del_timeout_us(rtt_sec * 2 * 1000 * 1000)
|
||||
{
|
||||
_timer.sigh(_del_timeout);
|
||||
_timer.trigger_once(_del_timeout_us);
|
||||
}
|
||||
|
||||
|
||||
bool Udp_proxy::matches_client(Ipv4_address client_ip, uint16_t client_port)
|
||||
{
|
||||
return client_ip == _client_ip && client_port == _client_port;
|
||||
}
|
||||
|
||||
|
||||
bool Udp_proxy::matches_proxy(Ipv4_address proxy_ip, uint16_t proxy_port)
|
||||
{
|
||||
return proxy_ip == _proxy_ip && proxy_port == _proxy_port;
|
||||
}
|
||||
|
||||
|
||||
void Udp_proxy::udp_packet(Ipv4_packet * const ip, Udp_packet * const udp)
|
||||
{
|
||||
_timer.trigger_once(_del_timeout_us);
|
||||
}
|
@ -1,134 +0,0 @@
|
||||
/*
|
||||
* \brief UDP/TCP proxy session
|
||||
* \author Martin Stein
|
||||
* \date 2016-08-19
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _PROXY_H_
|
||||
#define _PROXY_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <timer_session/connection.h>
|
||||
#include <net/ipv4.h>
|
||||
#include <util/list.h>
|
||||
|
||||
namespace Net {
|
||||
|
||||
class Tcp_packet;
|
||||
class Udp_packet;
|
||||
class Interface;
|
||||
class Tcp_proxy;
|
||||
class Udp_proxy;
|
||||
|
||||
using Tcp_proxy_list = Genode::List<Tcp_proxy>;
|
||||
using Udp_proxy_list = Genode::List<Udp_proxy>;
|
||||
}
|
||||
|
||||
class Net::Tcp_proxy : public Genode::List<Tcp_proxy>::Element
|
||||
{
|
||||
private:
|
||||
|
||||
using Signal_handler = Genode::Signal_handler<Tcp_proxy>;
|
||||
|
||||
Genode::uint16_t const _client_port;
|
||||
Genode::uint16_t const _proxy_port;
|
||||
Ipv4_address const _client_ip;
|
||||
Ipv4_address const _proxy_ip;
|
||||
Interface &_client;
|
||||
Timer::Connection _timer;
|
||||
bool _client_fin = false;
|
||||
bool _other_fin = false;
|
||||
bool _client_fin_acked = false;
|
||||
bool _other_fin_acked = false;
|
||||
bool _del = false;
|
||||
Signal_handler _del_timeout;
|
||||
unsigned const _del_timeout_us;
|
||||
|
||||
void _del_timeout_handle() { _del = true; }
|
||||
|
||||
public:
|
||||
|
||||
Tcp_proxy(Genode::uint16_t client_port, Genode::uint16_t proxy_port,
|
||||
Ipv4_address client_ip, Ipv4_address proxy_ip,
|
||||
Interface &client, Genode::Entrypoint &ep,
|
||||
unsigned const rtt_sec);
|
||||
|
||||
void print(Genode::Output &out) const;
|
||||
|
||||
bool matches_client(Ipv4_address client_ip,
|
||||
Genode::uint16_t client_port);
|
||||
|
||||
bool matches_proxy(Ipv4_address proxy_ip,
|
||||
Genode::uint16_t proxy_port);
|
||||
|
||||
void tcp_packet(Ipv4_packet *const ip, Tcp_packet *const tcp);
|
||||
|
||||
|
||||
/***************
|
||||
** Accessors **
|
||||
***************/
|
||||
|
||||
Genode::uint16_t client_port() const { return _client_port; }
|
||||
Genode::uint16_t proxy_port() const { return _proxy_port; }
|
||||
Ipv4_address client_ip() const { return _client_ip; }
|
||||
Ipv4_address proxy_ip() const { return _proxy_ip; }
|
||||
Interface &client() const { return _client; }
|
||||
bool del() const { return _del; }
|
||||
};
|
||||
|
||||
class Net::Udp_proxy : public Genode::List<Udp_proxy>::Element
|
||||
{
|
||||
private:
|
||||
|
||||
using Signal_handler = Genode::Signal_handler<Udp_proxy>;
|
||||
|
||||
Genode::uint16_t const _client_port;
|
||||
Genode::uint16_t const _proxy_port;
|
||||
Ipv4_address const _client_ip;
|
||||
Ipv4_address const _proxy_ip;
|
||||
Interface &_client;
|
||||
Timer::Connection _timer;
|
||||
bool _del = false;
|
||||
Signal_handler _del_timeout;
|
||||
unsigned const _del_timeout_us;
|
||||
|
||||
void _del_timeout_handle() { _del = true; }
|
||||
|
||||
public:
|
||||
|
||||
Udp_proxy(Genode::uint16_t client_port, Genode::uint16_t proxy_port,
|
||||
Ipv4_address client_ip, Ipv4_address proxy_ip,
|
||||
Interface &client, Genode::Entrypoint &ep,
|
||||
unsigned const rtt_sec);
|
||||
|
||||
void print(Genode::Output &out) const;
|
||||
|
||||
bool matches_client(Ipv4_address client_ip,
|
||||
Genode::uint16_t client_port);
|
||||
|
||||
bool matches_proxy(Ipv4_address proxy_ip,
|
||||
Genode::uint16_t proxy_port);
|
||||
|
||||
void udp_packet(Ipv4_packet *const ip, Udp_packet *const udp);
|
||||
|
||||
|
||||
/***************
|
||||
** Accessors **
|
||||
***************/
|
||||
|
||||
Genode::uint16_t client_port() const { return _client_port; }
|
||||
Genode::uint16_t proxy_port() const { return _proxy_port; }
|
||||
Ipv4_address client_ip() const { return _client_ip; }
|
||||
Ipv4_address proxy_ip() const { return _proxy_ip; }
|
||||
Interface &client() const { return _client; }
|
||||
bool del() const { return _del; }
|
||||
};
|
||||
|
||||
#endif /* _PROXY_H_ */
|
22
repos/os/src/server/nic_router/rule.h
Normal file
22
repos/os/src/server/nic_router/rule.h
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* \brief Base of each routing rule
|
||||
* \author Martin Stein
|
||||
* \date 2016-08-19
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _RULE_H_
|
||||
#define _RULE_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/exception.h>
|
||||
|
||||
namespace Net { struct Rule { struct Invalid : Genode::Exception { }; }; }
|
||||
|
||||
#endif /* _RULE_H_ */
|
@ -1,11 +1,12 @@
|
||||
TARGET = nic_router
|
||||
|
||||
LIBS += base net config server
|
||||
LIBS += base net config timeout
|
||||
|
||||
SRC_CC += arp_waiter.cc ip_route.cc proxy.cc
|
||||
SRC_CC += port_route.cc component.cc
|
||||
SRC_CC += mac_allocator.cc main.cc uplink.cc interface.cc arp_cache.cc
|
||||
SRC_CC += arp_waiter.cc ip_rule.cc
|
||||
SRC_CC += component.cc port_allocator.cc forward_rule.cc
|
||||
SRC_CC += nat_rule.cc mac_allocator.cc main.cc
|
||||
SRC_CC += uplink.cc interface.cc arp_cache.cc configuration.cc
|
||||
SRC_CC += domain.cc protocol_name.cc direct_rule.cc link.cc
|
||||
SRC_CC += transport_rule.cc leaf_rule.cc permit_rule.cc
|
||||
|
||||
INC_DIR += $(PRG_DIR)
|
||||
|
||||
vpath *.cc $(REP_DIR)/src/server/proxy_arp
|
||||
|
79
repos/os/src/server/nic_router/transport_rule.cc
Normal file
79
repos/os/src/server/nic_router/transport_rule.cc
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* \brief Rule for allowing direct TCP/UDP traffic between two interfaces
|
||||
* \author Martin Stein
|
||||
* \date 2016-08-19
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/xml_node.h>
|
||||
#include <base/allocator.h>
|
||||
#include <base/log.h>
|
||||
|
||||
/* local includes */
|
||||
#include <transport_rule.h>
|
||||
#include <configuration.h>
|
||||
|
||||
using namespace Net;
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
Permit_any_rule *Transport_rule::_read_permit_any(Domain_tree &domains,
|
||||
Xml_node const &node,
|
||||
Allocator &alloc)
|
||||
{
|
||||
try {
|
||||
Xml_node sub_node = node.sub_node("permit-any");
|
||||
return new (alloc) Permit_any_rule(domains, sub_node);
|
||||
}
|
||||
catch (Xml_node::Nonexistent_sub_node) { }
|
||||
catch (Rule::Invalid) { warning("invalid permit-any rule"); }
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
Transport_rule::Transport_rule(Domain_tree &domains,
|
||||
Xml_node const &node,
|
||||
Allocator &alloc,
|
||||
Cstring const &protocol,
|
||||
Configuration &config)
|
||||
:
|
||||
Direct_rule(node), _permit_any(_read_permit_any(domains, node, alloc))
|
||||
{
|
||||
/* skip specific permit rules if all ports are permitted anyway */
|
||||
if (_permit_any) {
|
||||
if (config.verbose()) {
|
||||
log(" ", protocol, " rule: ", _dst, " ", *_permit_any); }
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* read specific permit rules */
|
||||
node.for_each_sub_node("permit", [&] (Xml_node const &node) {
|
||||
try {
|
||||
Permit_single_rule &rule = *new (alloc)
|
||||
Permit_single_rule(domains, node);
|
||||
|
||||
_permit_single_rules.insert(&rule);
|
||||
if (config.verbose()) {
|
||||
log(protocol, " rule: ", _dst, " ", rule); }
|
||||
}
|
||||
catch (Rule::Invalid) { warning("invalid permit rule"); }
|
||||
});
|
||||
/* drop the transport rule if it has no permitted ports */
|
||||
if (!_permit_single_rules.first()) {
|
||||
throw Invalid(); }
|
||||
}
|
||||
|
||||
|
||||
Permit_rule const &Transport_rule::permit_rule(uint16_t const port) const
|
||||
{
|
||||
if (_permit_any) { return *_permit_any; }
|
||||
return _permit_single_rules.find_by_port(port);
|
||||
}
|
54
repos/os/src/server/nic_router/transport_rule.h
Normal file
54
repos/os/src/server/nic_router/transport_rule.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* \brief Rule for allowing direct TCP/UDP traffic between two interfaces
|
||||
* \author Martin Stein
|
||||
* \date 2016-08-19
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _TRANSPORT_RULE_H_
|
||||
#define _TRANSPORT_RULE_H_
|
||||
|
||||
/* local includes */
|
||||
#include <direct_rule.h>
|
||||
#include <permit_rule.h>
|
||||
|
||||
namespace Genode { class Allocator; }
|
||||
|
||||
namespace Net {
|
||||
|
||||
class Configuration;
|
||||
class Transport_rule;
|
||||
struct Transport_rule_list : Direct_rule_list<Transport_rule> { };
|
||||
}
|
||||
|
||||
|
||||
class Net::Transport_rule : public Direct_rule<Transport_rule>
|
||||
{
|
||||
private:
|
||||
|
||||
Permit_any_rule *const _permit_any;
|
||||
Permit_single_rule_tree _permit_single_rules;
|
||||
|
||||
static Permit_any_rule *
|
||||
_read_permit_any(Domain_tree &domains,
|
||||
Genode::Xml_node const &node,
|
||||
Genode::Allocator &alloc);
|
||||
|
||||
public:
|
||||
|
||||
Transport_rule(Domain_tree &domains,
|
||||
Genode::Xml_node const &node,
|
||||
Genode::Allocator &alloc,
|
||||
Genode::Cstring const &protocol,
|
||||
Configuration &config);
|
||||
|
||||
Permit_rule const &permit_rule(Genode::uint16_t const port) const;
|
||||
};
|
||||
|
||||
#endif /* _TRANSPORT_RULE_H_ */
|
@ -1,11 +1,11 @@
|
||||
/*
|
||||
* \brief NIC handler
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2013-05-24
|
||||
* \brief Uplink interface in form of a NIC session component
|
||||
* \author Martin Stein
|
||||
* \date 2016-08-23
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013 Genode Labs GmbH
|
||||
* Copyright (C) 2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
@ -14,48 +14,24 @@
|
||||
/* Genode includes */
|
||||
#include <base/env.h>
|
||||
#include <net/ethernet.h>
|
||||
#include <net/ipv4.h>
|
||||
#include <net/udp.h>
|
||||
#include <net/tcp.h>
|
||||
#include <net/dhcp.h>
|
||||
#include <os/config.h>
|
||||
|
||||
/* local includes */
|
||||
#include <component.h>
|
||||
#include <uplink.h>
|
||||
#include <configuration.h>
|
||||
|
||||
using namespace Net;
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
Ipv4_address Net::Uplink::_read_src() {
|
||||
|
||||
Session_policy policy(label_from_args("label=\"uplink\""));
|
||||
Ipv4_address const src = policy.attribute_value("src", Ipv4_address());
|
||||
if (src == Ipv4_address()) {
|
||||
warning("missing 'src' attribute in policy"); }
|
||||
return src;
|
||||
}
|
||||
|
||||
|
||||
Net::Uplink::Uplink(Server::Entrypoint &ep,
|
||||
Port_allocator &tcp_port_alloc,
|
||||
Port_allocator &udp_port_alloc,
|
||||
Tcp_proxy_list &tcp_proxys,
|
||||
Udp_proxy_list &udp_proxys,
|
||||
unsigned rtt_sec,
|
||||
Interface_tree &interface_tree,
|
||||
Arp_cache &arp_cache,
|
||||
Arp_waiter_list &arp_waiters,
|
||||
bool verbose)
|
||||
Net::Uplink::Uplink(Entrypoint &ep,
|
||||
Genode::Timer &timer,
|
||||
Genode::Allocator &alloc,
|
||||
Configuration &config)
|
||||
:
|
||||
Nic::Packet_allocator(env()->heap()),
|
||||
Nic::Packet_allocator(&alloc),
|
||||
Nic::Connection(this, BUF_SIZE, BUF_SIZE),
|
||||
|
||||
Interface(ep, mac_address(), _read_src(), *env()->heap(),
|
||||
"label=\"uplink\"", tcp_port_alloc, udp_port_alloc,
|
||||
Mac_address(), tcp_proxys, udp_proxys,
|
||||
rtt_sec, interface_tree, arp_cache, arp_waiters, verbose)
|
||||
Interface(ep, timer, mac_address(), alloc, Mac_address(),
|
||||
config.domains().find_by_name(Cstring("uplink")))
|
||||
{
|
||||
rx_channel()->sigh_ready_to_ack(_sink_ack);
|
||||
rx_channel()->sigh_packet_avail(_sink_submit);
|
||||
|
@ -16,18 +16,16 @@
|
||||
|
||||
/* Genode includes */
|
||||
#include <nic_session/connection.h>
|
||||
#include <nic/packet_allocator.h>
|
||||
|
||||
/* local includes */
|
||||
#include <interface.h>
|
||||
|
||||
namespace Net {
|
||||
|
||||
class Port_allocator;
|
||||
class Uplink;
|
||||
}
|
||||
namespace Net { class Uplink; }
|
||||
|
||||
class Net::Uplink : public Nic::Packet_allocator,
|
||||
public Nic::Connection, public Net::Interface
|
||||
public Nic::Connection,
|
||||
public Interface
|
||||
{
|
||||
private:
|
||||
|
||||
@ -36,28 +34,29 @@ class Net::Uplink : public Nic::Packet_allocator,
|
||||
BUF_SIZE = Nic::Session::QUEUE_SIZE * PKT_SIZE,
|
||||
};
|
||||
|
||||
Ipv4_address _read_src();
|
||||
|
||||
public:
|
||||
|
||||
Uplink(Server::Entrypoint &ep,
|
||||
Port_allocator &tcp_port_alloc,
|
||||
Port_allocator &udp_port_alloc,
|
||||
Tcp_proxy_list &tcp_proxys,
|
||||
Udp_proxy_list &udp_proxys,
|
||||
unsigned rtt_sec,
|
||||
Interface_tree &interface_tree,
|
||||
Arp_cache &arp_cache,
|
||||
Arp_waiter_list &arp_waiters,
|
||||
bool verbose);
|
||||
Ipv4_address_prefix _read_interface();
|
||||
|
||||
|
||||
/********************
|
||||
** Net::Interface **
|
||||
********************/
|
||||
|
||||
Packet_stream_sink<Nic::Session::Policy> *sink() { return rx(); }
|
||||
Packet_stream_source<Nic::Session::Policy> *source() { return tx(); }
|
||||
Packet_stream_sink &_sink() { return *rx(); }
|
||||
Packet_stream_source &_source() { return *tx(); }
|
||||
|
||||
public:
|
||||
|
||||
Uplink(Genode::Entrypoint &ep,
|
||||
Genode::Timer &timer,
|
||||
Genode::Allocator &alloc,
|
||||
Configuration &config);
|
||||
|
||||
|
||||
/***************
|
||||
** Accessors **
|
||||
***************/
|
||||
|
||||
Mac_address const &router_mac() const { return _router_mac; }
|
||||
};
|
||||
|
||||
#endif /* _UPLINK_H_ */
|
||||
|
@ -76,3 +76,4 @@ usb_hid
|
||||
smartcard
|
||||
new_delete
|
||||
timeout
|
||||
nic_router
|
||||
|
Loading…
Reference in New Issue
Block a user