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%<tincd interface>
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.
This commit is contained in:
thorkill 2015-07-09 22:19:26 +02:00
parent 49cc329cf9
commit f93352b095

View file

@ -541,11 +541,15 @@ static void route_ipv6(node_t *source, vpn_packet_t *packet) {
} }
subnet_t *subnet; subnet_t *subnet;
subnet_t *subnet_src;
node_t *via; node_t *via;
ipv6_t dest; ipv6_t dest;
ipv6_t src;
memcpy(&dest, &DATA(packet)[38], sizeof dest); memcpy(&dest, &DATA(packet)[38], sizeof dest);
memcpy(&src, &DATA(packet)[22], sizeof src);
subnet = lookup_subnet_ipv6(&dest); subnet = lookup_subnet_ipv6(&dest);
subnet_src = lookup_subnet_ipv6(&src);
if(!subnet) { 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", 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) { 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); broadcast_packet(source, packet);
return; return;
} }