ref: 332f07d78e1a575af02fffab762fdd9429b5ffd2
parent: cceea047704c5333d2674108f9ec9100c50530bf
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Fri Jul 17 12:53:20 EDT 2020
libndb: order subnets by prefix length for ndbipinfo() lookups to reproduce: ipnet=foo0 ip=192.168.0.0 ipmask=/16 ipnet=foo1 ip=192.168.0.0 ipmask=/24 ip=192.168.0.1 sys=foo2 % ndb/ipquery sys foo2 ipnet ipmask ipnet=foo0 ipmask=/16 we would expect to get ipnet=foo1 here as it is more specific subnet. the solution is to order the subnets by prefix length in subnet() before calling filter(), so that we process the longest prefixes first.
--- a/sys/src/libndb/ndbipinfo.c
+++ b/sys/src/libndb/ndbipinfo.c
@@ -114,17 +114,18 @@
}
/*
- * look through a containing subset
+ * look through containing subsets
*/
static Ndbtuple*
subnet(Ndb *db, uchar *net, Ndbtuple *f, int prefix)
{Ndbs s;
+ int nprefix;
char netstr[64];
uchar mask[IPaddrlen];
- Ndbtuple *t, *nt, *xt;
+ Ndbtuple *at[128+1], *nt, *xt, *t;
- t = nil;
+ memset(at, 0, sizeof(at));
snprint(netstr, sizeof(netstr), "%I", net);
nt = ndbsearch(db, &s, "ip", netstr);
while(nt != nil){@@ -133,13 +134,20 @@
xt = ndbfindattr(nt, nt, "ipmask");
if(xt == nil || parseipmask(mask, xt->val, isv4(net)) == -1)
ipmove(mask, defmask(net));
- if(prefixlen(mask) <= prefix){- t = ndbconcatenate(t, filter(db, nt, f));
+ nprefix = prefixlen(mask);
+ if(nprefix <= prefix && at[nprefix] == nil){+ /* remember containing subnet, order by prefix length */
+ at[nprefix] = nt;
nt = nil;
}
}
ndbfree(nt);
nt = ndbsnext(&s, "ip", netstr);
+ }
+ /* filter subnets, longest prefix first */
+ for(t = nil; prefix >= 0; prefix--){+ if(at[prefix] != nil)
+ t = ndbconcatenate(t, filter(db, at[prefix], f));
}
ndbsetmalloctag(t, getcallerpc(&db));
return t;
--
⑨