summaryrefslogtreecommitdiff
path: root/sys/src/cmd/ndb
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2020-08-08 18:37:10 +0200
committercinap_lenrek <cinap_lenrek@felloff.net>2020-08-08 18:37:10 +0200
commitac4e21f52d8458732b6e18d6ca481ab880c6c9be (patch)
treed026fbd29aaf0ed5925d78fedb4eb7d451dbce19 /sys/src/cmd/ndb
parent93b475981e7326f53dee0369476344f8552f4e7b (diff)
ndb/dns: allow multiple txt, nullrr, cert, key and sig records (thanks kvik)
The de-duplication of txt, nullrr, cert, key and sig records reduced all records to a single one. Also, dblookup1() missed the txt record case and did not return a unique list of rr's. Now we consider these records unique if their value is different. The new txtequiv() function does that for TXT records, which is a bit tricky as it needs to take different segmentation into account.
Diffstat (limited to 'sys/src/cmd/ndb')
-rw-r--r--sys/src/cmd/ndb/dblookup.c8
-rw-r--r--sys/src/cmd/ndb/dn.c78
2 files changed, 78 insertions, 8 deletions
diff --git a/sys/src/cmd/ndb/dblookup.c b/sys/src/cmd/ndb/dblookup.c
index 1c8e5a86d..e6a31f2bc 100644
--- a/sys/src/cmd/ndb/dblookup.c
+++ b/sys/src/cmd/ndb/dblookup.c
@@ -238,6 +238,10 @@ dblookup1(char *name, int type, int auth, int ttl)
attr = "srv";
f = srvrr;
break;
+ case Ttxt:
+ attr = "txt";
+ f = txtrr;
+ break;
case Tmx:
attr = "mx";
f = mxrr;
@@ -366,6 +370,8 @@ dblookup1(char *name, int type, int auth, int ttl)
}
ndbfree(t);
+ unique(list);
+
// dnslog("dblookup1(%s) -> %#p", name, list);
return list;
}
@@ -575,7 +581,7 @@ static RR*
doaxfr(Ndb *db, char *name)
{
USED(db, name);
- return 0;
+ return nil;
}
/*
diff --git a/sys/src/cmd/ndb/dn.c b/sys/src/cmd/ndb/dn.c
index f565a38fe..71768e7e3 100644
--- a/sys/src/cmd/ndb/dn.c
+++ b/sys/src/cmd/ndb/dn.c
@@ -245,8 +245,11 @@ ipalookup(uchar *ip, int class, int enter)
static int
rrsame(RR *rr1, RR *rr2)
{
- return rr1 == rr2 || rr2 && rrequiv(rr1, rr2) &&
- rr1->db == rr2->db && rr1->auth == rr2->auth;
+ return rr1 == rr2 ||
+ rr1 != nil && rr2 != nil &&
+ rr1->db == rr2->db &&
+ rr1->auth == rr2->auth &&
+ rrequiv(rr1, rr2);
}
static int
@@ -798,7 +801,7 @@ rrattach1(RR *new, int auth)
continue;
}
/* all things equal, pick the newer one */
- else if(rp->arg0 == new->arg0 && rp->arg1 == new->arg1){
+ else if(rrequiv(rp, new)){
/* old drives out new */
if((long)(rp->expire - new->expire) > 0) {
rrfree(new);
@@ -1524,12 +1527,73 @@ slave(Request *req)
}
static int
+blockequiv(Block *a, Block *b)
+{
+ return a->dlen == b->dlen &&
+ memcmp(a->data, b->data, a->dlen) == 0;
+}
+
+static int
+keyequiv(Key *a, Key *b)
+{
+ return a->flags == b->flags &&
+ a->proto == b->proto &&
+ a->alg == b->alg &&
+ blockequiv(a, b);
+}
+
+static int
+certequiv(Cert *a, Cert *b)
+{
+ return a->type == a->type &&
+ a->tag == a->tag &&
+ a->alg == a->alg &&
+ blockequiv(a, b);
+}
+
+static int
+txtequiv(Txt *a, Txt *b)
+{
+ char *ap, *ae, *bp, *be;
+ int n;
+
+ for(ap = ae = bp = be = nil;;ap += n, bp += n){
+ while(a != nil && (ap == nil || (ap == ae && (a = a->next) != nil)))
+ ap = a->p, ae = ap + strlen(ap);
+ while(b != nil && (bp == nil || (bp == be && (b = b->next) != nil)))
+ bp = b->p, be = bp + strlen(bp);
+ if(a == b || a == nil || b == nil)
+ break;
+ n = ae - ap;
+ if(be - bp < n)
+ n = be - bp;
+ if(memcmp(ap, bp, n) != 0)
+ return 0;
+ }
+ return a == b;
+}
+
+static int
rrequiv(RR *r1, RR *r2)
{
- return r1->owner == r2->owner
- && r1->type == r2->type
- && r1->arg0 == r2->arg0
- && r1->arg1 == r2->arg1;
+ if(r1->owner != r2->owner
+ || r1->type != r2->type
+ || r1->arg0 != r2->arg0
+ || r1->arg1 != r2->arg1)
+ return 0;
+ switch(r1->type){
+ case Tkey:
+ return keyequiv(r1->key, r2->key);
+ case Tcert:
+ return certequiv(r1->cert, r2->cert);
+ case Tsig:
+ return r1->sig->signer == r2->sig->signer && certequiv(r1->sig, r2->sig);
+ case Tnull:
+ return blockequiv(r1->null, r2->null);
+ case Ttxt:
+ return txtequiv(r1->txt, r2->txt);
+ }
+ return 1;
}
void