isc_result_t dst_key_fromdns(dns_name_t *name, dns_rdataclass_t rdclass, isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp) { isc_uint8_t alg, proto; isc_uint32_t flags, extflags; dst_key_t *key = NULL; dns_keytag_t id, rid; isc_region_t r; isc_result_t result; REQUIRE(dst_initialized); isc_buffer_remainingregion(source, &r); if (isc_buffer_remaininglength(source) < 4) return (DST_R_INVALIDPUBLICKEY); flags = isc_buffer_getuint16(source); proto = isc_buffer_getuint8(source); alg = isc_buffer_getuint8(source); id = dst_region_computeid(&r, alg); rid = dst_region_computerid(&r, alg); if (flags & DNS_KEYFLAG_EXTENDED) { if (isc_buffer_remaininglength(source) < 2) return (DST_R_INVALIDPUBLICKEY); extflags = isc_buffer_getuint16(source); flags |= (extflags << 16); } result = frombuffer(name, alg, flags, proto, rdclass, source, mctx, &key); if (result != ISC_R_SUCCESS) return (result); key->key_id = id; key->key_rid = rid; *keyp = key; return (ISC_R_SUCCESS); }
void dns_ncache_current(dns_rdataset_t *ncacherdataset, dns_name_t *found, dns_rdataset_t *rdataset) { dns_rdata_t rdata = DNS_RDATA_INIT; dns_trust_t trust; isc_region_t remaining, sigregion; isc_buffer_t source; dns_name_t tname; dns_rdatatype_t type; unsigned int count; dns_rdata_rrsig_t rrsig; unsigned char *raw; REQUIRE(ncacherdataset != NULL); REQUIRE(ncacherdataset->type == 0); REQUIRE((ncacherdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0); REQUIRE(found != NULL); REQUIRE(!dns_rdataset_isassociated(rdataset)); dns_rdataset_current(ncacherdataset, &rdata); isc_buffer_init(&source, rdata.data, rdata.length); isc_buffer_add(&source, rdata.length); dns_name_init(&tname, NULL); isc_buffer_remainingregion(&source, &remaining); dns_name_fromregion(found, &remaining); INSIST(remaining.length >= found->length); isc_buffer_forward(&source, found->length); remaining.length -= found->length; INSIST(remaining.length >= 5); type = isc_buffer_getuint16(&source); trust = isc_buffer_getuint8(&source); INSIST(trust <= dns_trust_ultimate); isc_buffer_remainingregion(&source, &remaining); rdataset->methods = &rdataset_methods; rdataset->rdclass = ncacherdataset->rdclass; rdataset->type = type; if (type == dns_rdatatype_rrsig) { /* * Extract covers from RRSIG. */ raw = remaining.base; count = raw[0] * 256 + raw[1]; INSIST(count > 0); raw += 2; sigregion.length = raw[0] * 256 + raw[1]; raw += 2; sigregion.base = raw; dns_rdata_reset(&rdata); dns_rdata_fromregion(&rdata, rdataset->rdclass, rdataset->type, &sigregion); (void)dns_rdata_tostruct(&rdata, &rrsig, NULL); rdataset->covers = rrsig.covered; } else rdataset->covers = 0; rdataset->ttl = ncacherdataset->ttl; rdataset->trust = trust; rdataset->private1 = NULL; rdataset->private2 = NULL; rdataset->private3 = remaining.base; /* * Reset iterator state. */ rdataset->privateuint4 = 0; rdataset->private5 = NULL; rdataset->private6 = NULL; }
isc_result_t dns_ncache_getsigrdataset(dns_rdataset_t *ncacherdataset, dns_name_t *name, dns_rdatatype_t covers, dns_rdataset_t *rdataset) { dns_name_t tname; dns_rdata_rrsig_t rrsig; dns_rdata_t rdata = DNS_RDATA_INIT; dns_rdataset_t clone; dns_rdatatype_t type; dns_trust_t trust = dns_trust_none; isc_buffer_t source; isc_region_t remaining, sigregion; isc_result_t result; unsigned char *raw; unsigned int count; REQUIRE(ncacherdataset != NULL); REQUIRE(ncacherdataset->type == 0); REQUIRE((ncacherdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0); REQUIRE(name != NULL); REQUIRE(!dns_rdataset_isassociated(rdataset)); dns_rdataset_init(&clone); dns_rdataset_clone(ncacherdataset, &clone); result = dns_rdataset_first(&clone); while (result == ISC_R_SUCCESS) { dns_rdataset_current(&clone, &rdata); isc_buffer_init(&source, rdata.data, rdata.length); isc_buffer_add(&source, rdata.length); dns_name_init(&tname, NULL); isc_buffer_remainingregion(&source, &remaining); dns_name_fromregion(&tname, &remaining); INSIST(remaining.length >= tname.length); isc_buffer_forward(&source, tname.length); isc_region_consume(&remaining, tname.length); INSIST(remaining.length >= 2); type = isc_buffer_getuint16(&source); isc_region_consume(&remaining, 2); if (type != dns_rdatatype_rrsig || !dns_name_equal(&tname, name)) { result = dns_rdataset_next(&clone); dns_rdata_reset(&rdata); continue; } INSIST(remaining.length >= 1); trust = isc_buffer_getuint8(&source); INSIST(trust <= dns_trust_ultimate); isc_region_consume(&remaining, 1); raw = remaining.base; count = raw[0] * 256 + raw[1]; INSIST(count > 0); raw += 2; sigregion.length = raw[0] * 256 + raw[1]; raw += 2; sigregion.base = raw; dns_rdata_reset(&rdata); dns_rdata_fromregion(&rdata, rdataset->rdclass, dns_rdatatype_rrsig, &sigregion); (void)dns_rdata_tostruct(&rdata, &rrsig, NULL); if (rrsig.covered == covers) { isc_buffer_remainingregion(&source, &remaining); break; } result = dns_rdataset_next(&clone); dns_rdata_reset(&rdata); } dns_rdataset_disassociate(&clone); if (result == ISC_R_NOMORE) return (ISC_R_NOTFOUND); if (result != ISC_R_SUCCESS) return (result); INSIST(remaining.length != 0); rdataset->methods = &rdataset_methods; rdataset->rdclass = ncacherdataset->rdclass; rdataset->type = dns_rdatatype_rrsig; rdataset->covers = covers; rdataset->ttl = ncacherdataset->ttl; rdataset->trust = trust; rdataset->private1 = NULL; rdataset->private2 = NULL; rdataset->private3 = remaining.base; /* * Reset iterator state. */ rdataset->privateuint4 = 0; rdataset->private5 = NULL; rdataset->private6 = NULL; return (ISC_R_SUCCESS); }
isc_result_t dns_ncache_getrdataset(dns_rdataset_t *ncacherdataset, dns_name_t *name, dns_rdatatype_t type, dns_rdataset_t *rdataset) { isc_result_t result; dns_rdata_t rdata = DNS_RDATA_INIT; isc_region_t remaining; isc_buffer_t source; dns_name_t tname; dns_rdatatype_t ttype; dns_trust_t trust = dns_trust_none; dns_rdataset_t clone; REQUIRE(ncacherdataset != NULL); REQUIRE(ncacherdataset->type == 0); REQUIRE((ncacherdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0); REQUIRE(name != NULL); REQUIRE(!dns_rdataset_isassociated(rdataset)); REQUIRE(type != dns_rdatatype_rrsig); dns_rdataset_init(&clone); dns_rdataset_clone(ncacherdataset, &clone); result = dns_rdataset_first(&clone); while (result == ISC_R_SUCCESS) { dns_rdataset_current(&clone, &rdata); isc_buffer_init(&source, rdata.data, rdata.length); isc_buffer_add(&source, rdata.length); dns_name_init(&tname, NULL); isc_buffer_remainingregion(&source, &remaining); dns_name_fromregion(&tname, &remaining); INSIST(remaining.length >= tname.length); isc_buffer_forward(&source, tname.length); remaining.length -= tname.length; INSIST(remaining.length >= 3); ttype = isc_buffer_getuint16(&source); if (ttype == type && dns_name_equal(&tname, name)) { trust = isc_buffer_getuint8(&source); INSIST(trust <= dns_trust_ultimate); isc_buffer_remainingregion(&source, &remaining); break; } result = dns_rdataset_next(&clone); dns_rdata_reset(&rdata); } dns_rdataset_disassociate(&clone); if (result == ISC_R_NOMORE) return (ISC_R_NOTFOUND); if (result != ISC_R_SUCCESS) return (result); INSIST(remaining.length != 0); rdataset->methods = &rdataset_methods; rdataset->rdclass = ncacherdataset->rdclass; rdataset->type = type; rdataset->covers = 0; rdataset->ttl = ncacherdataset->ttl; rdataset->trust = trust; rdataset->private1 = NULL; rdataset->private2 = NULL; rdataset->private3 = remaining.base; /* * Reset iterator state. */ rdataset->privateuint4 = 0; rdataset->private5 = NULL; rdataset->private6 = NULL; return (ISC_R_SUCCESS); }
isc_result_t dns_ncache_towire(dns_rdataset_t *rdataset, dns_compress_t *cctx, isc_buffer_t *target, unsigned int options, unsigned int *countp) { dns_rdata_t rdata = DNS_RDATA_INIT; isc_result_t result; isc_region_t remaining, tavailable; isc_buffer_t source, savedbuffer, rdlen; dns_name_t name; dns_rdatatype_t type; unsigned int i, rcount, count; /* * Convert the negative caching rdataset 'rdataset' to wire format, * compressing names as specified in 'cctx', and storing the result in * 'target'. */ REQUIRE(rdataset != NULL); REQUIRE(rdataset->type == 0); REQUIRE((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0); savedbuffer = *target; count = 0; result = dns_rdataset_first(rdataset); while (result == ISC_R_SUCCESS) { dns_rdataset_current(rdataset, &rdata); isc_buffer_init(&source, rdata.data, rdata.length); isc_buffer_add(&source, rdata.length); dns_name_init(&name, NULL); isc_buffer_remainingregion(&source, &remaining); dns_name_fromregion(&name, &remaining); INSIST(remaining.length >= name.length); isc_buffer_forward(&source, name.length); remaining.length -= name.length; INSIST(remaining.length >= 5); type = isc_buffer_getuint16(&source); isc_buffer_forward(&source, 1); rcount = isc_buffer_getuint16(&source); for (i = 0; i < rcount; i++) { /* * Get the length of this rdata and set up an * rdata structure for it. */ isc_buffer_remainingregion(&source, &remaining); INSIST(remaining.length >= 2); dns_rdata_reset(&rdata); rdata.length = isc_buffer_getuint16(&source); isc_buffer_remainingregion(&source, &remaining); rdata.data = remaining.base; rdata.type = type; rdata.rdclass = rdataset->rdclass; INSIST(remaining.length >= rdata.length); isc_buffer_forward(&source, rdata.length); if ((options & DNS_NCACHETOWIRE_OMITDNSSEC) != 0 && dns_rdatatype_isdnssec(type)) continue; /* * Write the name. */ dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14); result = dns_name_towire(&name, cctx, target); if (result != ISC_R_SUCCESS) goto rollback; /* * See if we have space for type, class, ttl, and * rdata length. Write the type, class, and ttl. */ isc_buffer_availableregion(target, &tavailable); if (tavailable.length < 10) { result = ISC_R_NOSPACE; goto rollback; } isc_buffer_putuint16(target, type); isc_buffer_putuint16(target, rdataset->rdclass); isc_buffer_putuint32(target, rdataset->ttl); /* * Save space for rdata length. */ rdlen = *target; isc_buffer_add(target, 2); /* * Write the rdata. */ result = dns_rdata_towire(&rdata, cctx, target); if (result != ISC_R_SUCCESS) goto rollback; /* * Set the rdata length field to the compressed * length. */ INSIST((target->used >= rdlen.used + 2) && (target->used - rdlen.used - 2 < 65536)); isc_buffer_putuint16(&rdlen, (isc_uint16_t)(target->used - rdlen.used - 2)); count++; } INSIST(isc_buffer_remaininglength(&source) == 0); result = dns_rdataset_next(rdataset); dns_rdata_reset(&rdata); } if (result != ISC_R_NOMORE) goto rollback; *countp = count; return (ISC_R_SUCCESS); rollback: INSIST(savedbuffer.used < 65536); dns_compress_rollback(cctx, (isc_uint16_t)savedbuffer.used); *countp = 0; *target = savedbuffer; return (result); }
isc_result_t dns_ncache_getrdataset(dns_rdataset_t *ncacherdataset, dns_name_t *name, dns_rdatatype_t type, dns_rdataset_t *rdataset) { isc_result_t result; dns_rdata_t rdata = DNS_RDATA_INIT; isc_region_t remaining; isc_buffer_t source; dns_name_t tname; dns_rdatatype_t ttype; unsigned int i, rcount; isc_uint16_t length; REQUIRE(ncacherdataset != NULL); REQUIRE(ncacherdataset->type == 0); REQUIRE(name != NULL); REQUIRE(!dns_rdataset_isassociated(rdataset)); REQUIRE(type != dns_rdatatype_rrsig); result = dns_rdataset_first(ncacherdataset); if (result != ISC_R_SUCCESS) return (result); dns_rdataset_current(ncacherdataset, &rdata); INSIST(dns_rdataset_next(ncacherdataset) == ISC_R_NOMORE); isc_buffer_init(&source, rdata.data, rdata.length); isc_buffer_add(&source, rdata.length); do { dns_name_init(&tname, NULL); isc_buffer_remainingregion(&source, &remaining); dns_name_fromregion(&tname, &remaining); INSIST(remaining.length >= tname.length); isc_buffer_forward(&source, tname.length); remaining.length -= tname.length; INSIST(remaining.length >= 4); ttype = isc_buffer_getuint16(&source); if (ttype == type && dns_name_equal(&tname, name)) { isc_buffer_remainingregion(&source, &remaining); break; } rcount = isc_buffer_getuint16(&source); for (i = 0; i < rcount; i++) { isc_buffer_remainingregion(&source, &remaining); INSIST(remaining.length >= 2); length = isc_buffer_getuint16(&source); isc_buffer_remainingregion(&source, &remaining); INSIST(remaining.length >= length); isc_buffer_forward(&source, length); } isc_buffer_remainingregion(&source, &remaining); } while (remaining.length > 0); if (remaining.length == 0) return (ISC_R_NOTFOUND); rdataset->methods = &rdataset_methods; rdataset->rdclass = ncacherdataset->rdclass; rdataset->type = type; rdataset->covers = 0; rdataset->ttl = ncacherdataset->ttl; rdataset->trust = ncacherdataset->trust; rdataset->private1 = NULL; rdataset->private2 = NULL; rdataset->private3 = remaining.base; /* * Reset iterator state. */ rdataset->privateuint4 = 0; rdataset->private5 = NULL; return (ISC_R_SUCCESS); }