From f93352b0954be3c6a25b277bd6b19ad6edcbf4d7 Mon Sep 17 00:00:00 2001 From: thorkill Date: Thu, 9 Jul 2015 22:19:26 +0200 Subject: [PATCH] Prevent packet loops when ICMP6 router solicitation packets are sent to tinc device When tincd setups it's network device some operating systems send router solicitation packets from local scope ip addresses. tincd forwards it then to his neighbors then those nodes follow the same routine fowarding it to the next hops. I may happen that an loop will occur consuming large amount of bandwith. Constrains: Mode = Router, Broadcast = mst. Reproduction: ping6 -c 1 ff02::2% Sending one packet will, depending on your setup, generate about 3k packets. Proposed solution in this commit: enable StrictSubnets, tincd will reject such packets due to unknown subnet. Future work: check scope of the ip address and make decisions about forwarding based on Mode tincd is configured to work. --- src/route.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/route.c b/src/route.c index 4ac14224..2b78a57a 100644 --- a/src/route.c +++ b/src/route.c @@ -541,11 +541,15 @@ static void route_ipv6(node_t *source, vpn_packet_t *packet) { } subnet_t *subnet; + subnet_t *subnet_src; node_t *via; ipv6_t dest; + ipv6_t src; memcpy(&dest, &DATA(packet)[38], sizeof dest); + memcpy(&src, &DATA(packet)[22], sizeof src); subnet = lookup_subnet_ipv6(&dest); + subnet_src = lookup_subnet_ipv6(&src); if(!subnet) { logger(DEBUG_TRAFFIC, LOG_WARNING, "Cannot route packet from %s (%s): unknown IPv6 destination address %hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx", @@ -564,6 +568,22 @@ static void route_ipv6(node_t *source, vpn_packet_t *packet) { } if (!subnet->owner) { + // Prevent loops + if (strictsubnets && !subnet_src) { + logger(DEBUG_ALWAYS, LOG_WARNING, "Ignore broadcast packet from %s (%s): unknown IPv6 source address %hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx", + source->name, source->hostname, + ntohs(src.x[0]), + ntohs(src.x[1]), + ntohs(src.x[2]), + ntohs(src.x[3]), + ntohs(src.x[4]), + ntohs(src.x[5]), + ntohs(src.x[6]), + ntohs(src.x[7])); + route_ipv6_unreachable(source, packet, ether_size, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADDR); + return; + } + broadcast_packet(source, packet); return; }