Add the Forwarding option.
authorGuus Sliepen <guus@tinc-vpn.org>
Tue, 2 Mar 2010 21:34:26 +0000 (22:34 +0100)
committerGuus Sliepen <guus@tinc-vpn.org>
Tue, 2 Mar 2010 21:34:26 +0000 (22:34 +0100)
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
doc/tinc.texi
src/net_setup.c
src/route.c
src/route.h

index 6f8db9c008f09ce14bf85169138f0bd4cd7d6f34..797ca5225f44549f7c63dfb1df03e64702c389cc 100644 (file)
@@ -199,6 +199,26 @@ Tinc will expect packets read from the virtual network device
 to start with an Ethernet header.
 .El
 
 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
 .It Va GraphDumpFile Li = Ar filename Bq experimental
 If this option is present,
 .Nm tinc
index 5d0bf31fb42939e2b99f44965046f065d88cc8eb..091b5e7a0e50f3692722b6f92f39b5d9c32e6e05 100644 (file)
@@ -818,6 +818,26 @@ Tinc will expect packets read from the virtual network device
 to start with an Ethernet header.
 @end table
 
 to start with an Ethernet header.
 @end table
 
+@cindex Forwarding
+@item Forwarding = <off|internal|kernel> (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,
 @cindex GraphDumpFile
 @item GraphDumpFile = <@var{filename}> [experimental]
 If this option is present,
index cb606caad46897e9cb73def798b178e82d5372af..6e51b2e243107114577aa320473e17912eaf0085 100644 (file)
@@ -355,8 +355,21 @@ bool setup_myself(void) {
                        return false;
                }
                free(mode);
                        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);
 
        choice = true;
        get_config_bool(lookup_config(myself->connection->config_tree, "PMTUDiscovery"), &choice);
index 6c381ccf852b13159f105a733570159426654573..1f91db9729588d128848cbc2951118555c8ad6c5 100644 (file)
@@ -33,6 +33,7 @@
 #include "utils.h"
 
 rmode_t routing_mode = RMODE_ROUTER;
 #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;
 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)
        }
 
        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];
 
        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)
        }
 
        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;
        
 
        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;
        }
 
                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;
        // 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) {
 }
 
 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;
 
        if(!checklength(source, packet, ether_size))
                return;
 
index 1fcc6be7ca3941bb7af77beae59bfb696aaeb453..aa25dcf52eb96b5ff94b643afc0b4966b087bc6a 100644 (file)
@@ -30,7 +30,14 @@ typedef enum rmode_t {
        RMODE_ROUTER,
 } 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 rmode_t routing_mode;
+extern fmode_t forwarding_mode;
 extern bool overwrite_mac;
 extern bool priorityinheritance;
 extern int macexpire;
 extern bool overwrite_mac;
 extern bool priorityinheritance;
 extern int macexpire;