diff options
Diffstat (limited to 'lib/dns/nsec.c')
-rw-r--r-- | lib/dns/nsec.c | 97 |
1 files changed, 56 insertions, 41 deletions
diff --git a/lib/dns/nsec.c b/lib/dns/nsec.c index 41b5dc3..e446806b 100644 --- a/lib/dns/nsec.c +++ b/lib/dns/nsec.c @@ -42,28 +42,61 @@ goto failure; \ } while (0) -static void -set_bit(unsigned char *array, unsigned int index, unsigned int bit) { +void +dns_nsec_setbit(unsigned char *array, unsigned int type, unsigned int bit) { unsigned int shift, mask; - shift = 7 - (index % 8); + shift = 7 - (type % 8); mask = 1 << shift; if (bit != 0) - array[index / 8] |= mask; + array[type / 8] |= mask; else - array[index / 8] &= (~mask & 0xFF); + array[type / 8] &= (~mask & 0xFF); } -static unsigned int -bit_isset(unsigned char *array, unsigned int index) { +isc_boolean_t +dns_nsec_isset(const unsigned char *array, unsigned int type) { unsigned int byte, shift, mask; - byte = array[index / 8]; - shift = 7 - (index % 8); + byte = array[type / 8]; + shift = 7 - (type % 8); mask = 1 << shift; - return ((byte & mask) != 0); + return (ISC_TF(byte & mask)); +} + +unsigned int +dns_nsec_compressbitmap(unsigned char *map, const unsigned char *raw, + unsigned int max_type) +{ + unsigned char *start = map; + unsigned int window; + int octet; + + if (raw == NULL) + return (0); + + for (window = 0; window < 256; window++) { + if (window * 256 > max_type) + break; + for (octet = 31; octet >= 0; octet--) + if (*(raw + octet) != 0) + break; + if (octet < 0) { + raw += 32; + continue; + } + *map++ = window; + *map++ = octet + 1; + /* + * Note: potential overlapping move. + */ + memmove(map, raw, octet + 1); + map += octet + 1; + raw += 32; + } + return (map - start); } isc_result_t @@ -74,8 +107,7 @@ dns_nsec_buildrdata(dns_db_t *db, dns_dbversion_t *version, isc_result_t result; dns_rdataset_t rdataset; isc_region_t r; - unsigned int i, window; - int octet; + unsigned int i; unsigned char *nsec_bits, *bm; unsigned int max_type; @@ -91,8 +123,8 @@ dns_nsec_buildrdata(dns_db_t *db, dns_dbversion_t *version, */ bm = r.base + r.length + 512; nsec_bits = r.base + r.length; - set_bit(bm, dns_rdatatype_rrsig, 1); - set_bit(bm, dns_rdatatype_nsec, 1); + dns_nsec_setbit(bm, dns_rdatatype_rrsig, 1); + dns_nsec_setbit(bm, dns_rdatatype_nsec, 1); max_type = dns_rdatatype_nsec; dns_rdataset_init(&rdataset); rdsiter = NULL; @@ -109,7 +141,7 @@ dns_nsec_buildrdata(dns_db_t *db, dns_dbversion_t *version, rdataset.type != dns_rdatatype_rrsig) { if (rdataset.type > max_type) max_type = rdataset.type; - set_bit(bm, rdataset.type, 1); + dns_nsec_setbit(bm, rdataset.type, 1); } dns_rdataset_disassociate(&rdataset); } @@ -117,12 +149,12 @@ dns_nsec_buildrdata(dns_db_t *db, dns_dbversion_t *version, /* * At zone cuts, deny the existence of glue in the parent zone. */ - if (bit_isset(bm, dns_rdatatype_ns) && - ! bit_isset(bm, dns_rdatatype_soa)) { + if (dns_nsec_isset(bm, dns_rdatatype_ns) && + ! dns_nsec_isset(bm, dns_rdatatype_soa)) { for (i = 0; i <= max_type; i++) { - if (bit_isset(bm, i) && + if (dns_nsec_isset(bm, i) && ! dns_rdatatype_iszonecutauth((dns_rdatatype_t)i)) - set_bit(bm, i, 0); + dns_nsec_setbit(bm, i, 0); } } @@ -130,22 +162,8 @@ dns_nsec_buildrdata(dns_db_t *db, dns_dbversion_t *version, if (result != ISC_R_NOMORE) return (result); - for (window = 0; window < 256; window++) { - if (window * 256 > max_type) - break; - for (octet = 31; octet >= 0; octet--) - if (bm[window * 32 + octet] != 0) - break; - if (octet < 0) - continue; - nsec_bits[0] = window; - nsec_bits[1] = octet + 1; - /* - * Note: potential overlapping move. - */ - memmove(&nsec_bits[2], &bm[window * 32], octet + 1); - nsec_bits += 3 + octet; - } + nsec_bits += dns_nsec_compressbitmap(nsec_bits, bm, max_type); + r.length = nsec_bits - r.base; INSIST(r.length <= DNS_NSEC_BUFFERSIZE); dns_rdata_fromregion(rdata, @@ -156,7 +174,6 @@ dns_nsec_buildrdata(dns_db_t *db, dns_dbversion_t *version, return (ISC_R_SUCCESS); } - isc_result_t dns_nsec_build(dns_db_t *db, dns_dbversion_t *version, dns_dbnode_t *node, dns_name_t *target, dns_ttl_t ttl) @@ -217,8 +234,8 @@ dns_nsec_typepresent(dns_rdata_t *nsec, dns_rdatatype_t type) { if ((window + 1) * 256 <= type) continue; if (type < (window * 256) + len * 8) - present = ISC_TF(bit_isset(&nsecstruct.typebits[i], - type % 256)); + present = ISC_TF(dns_nsec_isset(&nsecstruct.typebits[i], + type % 256)); break; } dns_rdata_freestruct(&nsecstruct); @@ -246,10 +263,8 @@ dns_nsec_nseconly(dns_db_t *db, dns_dbversion_t *version, 0, 0, &rdataset, NULL); dns_db_detachnode(db, &node); - if (result == ISC_R_NOTFOUND) { + if (result == ISC_R_NOTFOUND) *answer = ISC_FALSE; - return (ISC_R_SUCCESS); - } if (result != ISC_R_SUCCESS) return (result); for (result = dns_rdataset_first(&rdataset); |