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
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,
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);
#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;
}
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(!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;
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;
}
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;
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;