From 97e7e2184b16ed2c0cfb08041ee5e0257c11523d Mon Sep 17 00:00:00 2001 From: iczero Date: Thu, 16 Sep 2021 02:08:37 -0400 Subject: [PATCH] Fix bug where less specific subnet may be selected --- src/subnet.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/subnet.c b/src/subnet.c index e6984564e..b5c3b5fb6 100644 --- a/src/subnet.c +++ b/src/subnet.c @@ -265,12 +265,18 @@ subnet_t *lookup_subnet_ipv4(const ipv4_t *address) { // Search all subnets for a matching one int last_rtt = INT_MAX; // current smallest rtt seen + int last_prefix_length = -1; // most specific prefix length seen for splay_each(subnet_t, p, &subnet_tree) { if(!p || p->type != SUBNET_IPV4) { continue; } + // we are on a route less specific than the one we found, break + if(p->net.ipv4.prefixlength < last_prefix_length) { + break; + } + if(!maskcmp(address, &p->net.ipv4.address, p->net.ipv4.prefixlength)) { if(!p->owner) { // this is a broadcast subnet @@ -292,10 +298,11 @@ subnet_t *lookup_subnet_ipv4(const ipv4_t *address) { if(rtt < last_rtt) { r = p; last_rtt = rtt; + last_prefix_length = p->net.ipv4.prefixlength; } } } else if(r) { - // no more matching subnets + // no more matching subnets with equal or greater specificity break; } } @@ -321,12 +328,18 @@ subnet_t *lookup_subnet_ipv6(const ipv6_t *address) { // Search all subnets for a matching one int last_rtt = INT_MAX; // current smallest rtt seen + int last_prefix_length = -1; // most specific prefix length seen for splay_each(subnet_t, p, &subnet_tree) { if(!p || p->type != SUBNET_IPV6) { continue; } + // we are on a route less specific than the one we found, break + if(p->net.ipv6.prefixlength < last_prefix_length) { + break; + } + if(!maskcmp(address, &p->net.ipv6.address, p->net.ipv6.prefixlength)) { if(!p->owner) { // this is a broadcast subnet @@ -348,10 +361,11 @@ subnet_t *lookup_subnet_ipv6(const ipv6_t *address) { if(rtt < last_rtt) { r = p; last_rtt = rtt; + last_prefix_length = p->net.ipv6.prefixlength; } } } else if(r) { - // no more matching subnets + // no more matching subnets with equal or greater specificity break; } }