summaryrefslogtreecommitdiff
path: root/sys/src/libndb
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2020-07-17 16:53:20 +0200
committercinap_lenrek <cinap_lenrek@felloff.net>2020-07-17 16:53:20 +0200
commit9ea93a5fd347a04ed409c46410cd5ead033c0695 (patch)
tree27fe1e5882b1b2b60fa7218036c4ead724a32d7e /sys/src/libndb
parent407cf4ac6e59556b65d29b3c0de6ada6fdcc3cc7 (diff)
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.
Diffstat (limited to 'sys/src/libndb')
-rw-r--r--sys/src/libndb/ndbipinfo.c18
1 files changed, 13 insertions, 5 deletions
diff --git a/sys/src/libndb/ndbipinfo.c b/sys/src/libndb/ndbipinfo.c
index 5ee706e55..71092d4bc 100644
--- a/sys/src/libndb/ndbipinfo.c
+++ b/sys/src/libndb/ndbipinfo.c
@@ -114,17 +114,18 @@ prefixlen(uchar *ip)
}
/*
- * 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,14 +134,21 @@ subnet(Ndb *db, uchar *net, Ndbtuple *f, int prefix)
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;
}