From 95a6974de173e0cb78611c6704ed09631d510dae Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Tue, 2 Mar 2010 22:34:26 +0100 Subject: [PATCH] Add the Forwarding option. This determines if and how incoming packets that are not meant for the local node are forwarded. It can either be off, internal (tinc forwards them itself, as in previous versions), or kernel (packets are always sent to the TUN/TAP device, letting the kernel sort them out). --- doc/tinc.conf.5.in | 20 ++++++++++++++++++++ doc/tinc.texi | 20 ++++++++++++++++++++ src/net_setup.c | 17 +++++++++++++++-- src/route.c | 19 +++++++++++++++++-- src/route.h | 7 +++++++ 5 files changed, 79 insertions(+), 4 deletions(-) diff --git a/doc/tinc.conf.5.in b/doc/tinc.conf.5.in index 6f8db9c0..797ca522 100644 --- a/doc/tinc.conf.5.in +++ b/doc/tinc.conf.5.in @@ -199,6 +199,26 @@ Tinc will expect packets read from the virtual network device to start with an Ethernet header. .El +.It Va Forwarding Li = off | internal | kernel Pq internal +This option selects the way indirect packets are forwarded. +.Bl -tag -width indent + +.It off +Incoming packets that are not meant for the local node, +but which should be forwarded to another node, are dropped. + +.It internal +Incoming packets that are meant for another node are forwarded by tinc internally. + +.Pp +This is the default mode, and unless you really know you need another forwarding mode, don't change it. + +.It kernel +Incoming packets are always sent to the TUN/TAP device, even if the packets are not for the local node. +This is less efficient, but allows the kernel to apply its routing and firewall rules on them, +and can also help debugging. +.El + .It Va GraphDumpFile Li = Ar filename Bq experimental If this option is present, .Nm tinc diff --git a/doc/tinc.texi b/doc/tinc.texi index 5d0bf31f..091b5e7a 100644 --- a/doc/tinc.texi +++ b/doc/tinc.texi @@ -818,6 +818,26 @@ Tinc will expect packets read from the virtual network device to start with an Ethernet header. @end table +@cindex Forwarding +@item Forwarding = (internal) +This option selects the way indirect packets are forwarded. + +@table @asis +@item off +Incoming packets that are not meant for the local node, +but which should be forwarded to another node, are dropped. + +@item internal +Incoming packets that are meant for another node are forwarded by tinc internally. + +This is the default mode, and unless you really know you need another forwarding mode, don't change it. + +@item kernel +Incoming packets are always sent to the TUN/TAP device, even if the packets are not for the local node. +This is less efficient, but allows the kernel to apply its routing and firewall rules on them, +and can also help debugging. +@end table + @cindex GraphDumpFile @item GraphDumpFile = <@var{filename}> [experimental] If this option is present, diff --git a/src/net_setup.c b/src/net_setup.c index cb606caa..6e51b2e2 100644 --- a/src/net_setup.c +++ b/src/net_setup.c @@ -355,8 +355,21 @@ bool setup_myself(void) { return false; } free(mode); - } else - routing_mode = RMODE_ROUTER; + } + + if(get_config_string(lookup_config(config_tree, "Forwarding"), &mode)) { + if(!strcasecmp(mode, "off")) + routing_mode = FMODE_OFF; + else if(!strcasecmp(mode, "internal")) + routing_mode = FMODE_INTERNAL; + else if(!strcasecmp(mode, "kernel")) + routing_mode = FMODE_KERNEL; + else { + logger(LOG_ERR, "Invalid forwarding mode!"); + return false; + } + free(mode); + } choice = true; get_config_bool(lookup_config(myself->connection->config_tree, "PMTUDiscovery"), &choice); diff --git a/src/route.c b/src/route.c index 6c381ccf..1f91db97 100644 --- a/src/route.c +++ b/src/route.c @@ -33,6 +33,7 @@ #include "utils.h" rmode_t routing_mode = RMODE_ROUTER; +fmode_t forwarding_mode = FMODE_INTERNAL; bool priorityinheritance = false; int macexpire = 600; bool overwrite_mac = false; @@ -383,7 +384,10 @@ static void route_ipv4_unicast(node_t *source, vpn_packet_t *packet) { } if(!subnet->owner->status.reachable) - route_ipv4_unreachable(source, packet, ICMP_DEST_UNREACH, ICMP_NET_UNREACH); + return route_ipv4_unreachable(source, packet, ICMP_DEST_UNREACH, ICMP_NET_UNREACH); + + if(forwarding_mode == FMODE_OFF && source != myself && subnet->owner != myself) + return route_ipv4_unreachable(source, packet, ICMP_DEST_UNREACH, ICMP_NET_ANO); if(priorityinheritance) packet->priority = packet->data[15]; @@ -531,7 +535,10 @@ static void route_ipv6_unicast(node_t *source, vpn_packet_t *packet) { } if(!subnet->owner->status.reachable) - route_ipv6_unreachable(source, packet, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOROUTE); + return route_ipv6_unreachable(source, packet, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOROUTE); + + if(forwarding_mode == FMODE_OFF && source != myself && subnet->owner != myself) + return route_ipv6_unreachable(source, packet, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADMIN); via = (subnet->owner->via == myself) ? subnet->owner->nexthop : subnet->owner->via; @@ -796,6 +803,9 @@ static void route_mac(node_t *source, vpn_packet_t *packet) { return; } + if(forwarding_mode == FMODE_OFF && source != myself && subnet->owner != myself) + return; + // Handle packets larger than PMTU node_t *via = (subnet->owner->via == myself) ? subnet->owner->nexthop : subnet->owner->via; @@ -824,6 +834,11 @@ static void route_mac(node_t *source, vpn_packet_t *packet) { } void route(node_t *source, vpn_packet_t *packet) { + if(forwarding_mode == FMODE_KERNEL) { + send_packet(myself, packet); + return; + } + if(!checklength(source, packet, ether_size)) return; diff --git a/src/route.h b/src/route.h index 1fcc6be7..aa25dcf5 100644 --- a/src/route.h +++ b/src/route.h @@ -30,7 +30,14 @@ typedef enum rmode_t { RMODE_ROUTER, } rmode_t; +typedef enum fmode_t { + FMODE_OFF = 0, + FMODE_INTERNAL, + FMODE_KERNEL, +} fmode_t; + extern rmode_t routing_mode; +extern fmode_t forwarding_mode; extern bool overwrite_mac; extern bool priorityinheritance; extern int macexpire; -- 2.20.1