shithub: riscv

Download patch

ref: ac4e21f52d8458732b6e18d6ca481ab880c6c9be
parent: 93b475981e7326f53dee0369476344f8552f4e7b
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sat Aug 8 14:37:10 EDT 2020

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.

--- a/sys/src/cmd/ndb/dblookup.c
+++ b/sys/src/cmd/ndb/dblookup.c
@@ -238,6 +238,10 @@
 		attr = "srv";
 		f = srvrr;
 		break;
+	case Ttxt:
+		attr = "txt";
+		f = txtrr;
+		break;
 	case Tmx:
 		attr = "mx";
 		f = mxrr;
@@ -366,6 +370,8 @@
 		}
 	ndbfree(t);
 
+	unique(list);
+
 //	dnslog("dblookup1(%s) -> %#p", name, list);
 	return list;
 }
@@ -575,7 +581,7 @@
 doaxfr(Ndb *db, char *name)
 {
 	USED(db, name);
-	return 0;
+	return nil;
 }
 
 /*
--- a/sys/src/cmd/ndb/dn.c
+++ b/sys/src/cmd/ndb/dn.c
@@ -245,8 +245,11 @@
 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 @@
 				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 @@
 }
 
 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