isc_boolean_t dns_nsec_typepresent(dns_rdata_t *nsec, dns_rdatatype_t type) { dns_rdata_nsec_t nsecstruct; isc_result_t result; isc_boolean_t present; unsigned int i, len, window; REQUIRE(nsec != NULL); REQUIRE(nsec->type == dns_rdatatype_nsec); /* This should never fail */ result = dns_rdata_tostruct(nsec, &nsecstruct, NULL); INSIST(result == ISC_R_SUCCESS); present = ISC_FALSE; for (i = 0; i < nsecstruct.len; i += len) { INSIST(i + 2 <= nsecstruct.len); window = nsecstruct.typebits[i]; len = nsecstruct.typebits[i + 1]; INSIST(len > 0 && len <= 32); i += 2; INSIST(i + len <= nsecstruct.len); if (window * 256 > type) break; if ((window + 1) * 256 <= type) continue; if (type < (window * 256) + len * 8) present = ISC_TF(bit_isset(&nsecstruct.typebits[i], type % 256)); break; } dns_rdata_freestruct(&nsec); return (present); }
static void printsoa(dns_rdata_t *rdata) { dns_rdata_soa_t soa; isc_result_t result; char namebuf[DNS_NAME_FORMATSIZE]; result = dns_rdata_tostruct(rdata, &soa, NULL); check_result(result, "dns_rdata_tostruct"); dns_name_format(&soa.origin, namebuf, sizeof(namebuf)); printf("\torigin = %s\n", namebuf); dns_name_format(&soa.contact, namebuf, sizeof(namebuf)); printf("\tmail addr = %s\n", namebuf); printf("\tserial = %u\n", soa.serial); printf("\trefresh = %u\n", soa.refresh); printf("\tretry = %u\n", soa.retry); printf("\texpire = %u\n", soa.expire); printf("\tminimum = %u\n", soa.minimum); dns_rdata_freestruct(&soa); }
static isc_result_t add_mac(dst_context_t *tsigctx, isc_buffer_t *buf) { dns_rdata_any_tsig_t tsig; dns_rdata_t rdata = DNS_RDATA_INIT; isc_buffer_t databuf; isc_region_t r; isc_result_t result; unsigned char tsigbuf[1024]; isc_buffer_usedregion(buf, &r); dns_rdata_fromregion(&rdata, dns_rdataclass_any, dns_rdatatype_tsig, &r); isc_buffer_init(&databuf, tsigbuf, sizeof(tsigbuf)); CHECK(dns_rdata_tostruct(&rdata, &tsig, NULL)); isc_buffer_putuint16(&databuf, tsig.siglen); isc_buffer_putmem(&databuf, tsig.signature, tsig.siglen); isc_buffer_usedregion(&databuf, &r); result = dst_context_adddata(tsigctx, &r); dns_rdata_freestruct(&tsig); cleanup: return (result); }
static void chase_cnamechain(dns_message_t *msg, dns_name_t *qname) { isc_result_t result; dns_rdataset_t *rdataset; dns_rdata_cname_t cname; dns_rdata_t rdata = DNS_RDATA_INIT; unsigned int i = msg->counts[DNS_SECTION_ANSWER]; while (i-- > 0) { rdataset = NULL; result = dns_message_findname(msg, DNS_SECTION_ANSWER, qname, dns_rdatatype_cname, 0, NULL, &rdataset); if (result != ISC_R_SUCCESS) return; result = dns_rdataset_first(rdataset); check_result(result, "dns_rdataset_first"); dns_rdata_reset(&rdata); dns_rdataset_current(rdataset, &rdata); result = dns_rdata_tostruct(&rdata, &cname, NULL); check_result(result, "dns_rdata_tostruct"); dns_name_copy(&cname.cname, qname, NULL); dns_rdata_freestruct(&cname); } }
static void resolve_ns(isc_task_t *task, isc_event_t *event) { struct probe_trans *trans = event->ev_arg; dns_clientresevent_t *rev = (dns_clientresevent_t *)event; dns_name_t *name; dns_rdataset_t *rdataset; isc_result_t result = ISC_R_SUCCESS; dns_rdata_t rdata = DNS_RDATA_INIT; struct probe_ns *pns; REQUIRE(task == probe_task); REQUIRE(trans->inuse == ISC_TRUE); INSIST(outstanding_probes > 0); for (name = ISC_LIST_HEAD(rev->answerlist); name != NULL; name = ISC_LIST_NEXT(name, link)) { for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL; rdataset = ISC_LIST_NEXT(rdataset, link)) { (void)print_rdataset(rdataset, name); if (rdataset->type != dns_rdatatype_ns) continue; for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS; result = dns_rdataset_next(rdataset)) { dns_rdata_ns_t ns; dns_rdataset_current(rdataset, &rdata); /* * Extract the name from the NS record. */ result = dns_rdata_tostruct(&rdata, &ns, NULL); if (result != ISC_R_SUCCESS) continue; pns = isc_mem_get(mctx, sizeof(*pns)); if (pns == NULL) { fprintf(stderr, "resolve_ns: mem_get failed"); result = ISC_R_NOMEMORY; POST(result); /* * XXX: should we continue with the * available servers anyway? */ goto cleanup; } dns_fixedname_init(&pns->fixedname); pns->name = dns_fixedname_name(&pns->fixedname); ISC_LINK_INIT(pns, link); ISC_LIST_APPEND(trans->nslist, pns, link); ISC_LIST_INIT(pns->servers); dns_name_copy(&ns.name, pns->name, NULL); dns_rdata_reset(&rdata); dns_rdata_freestruct(&ns); } } } cleanup: dns_client_freeresanswer(client, &rev->answerlist); dns_client_destroyrestrans(&trans->resid); isc_event_free(&event); if (!ISC_LIST_EMPTY(trans->nslist)) { /* Go get addresses of NSes */ trans->current_ns = ISC_LIST_HEAD(trans->nslist); result = fetch_nsaddress(trans); } else result = ISC_R_FAILURE; if (result == ISC_R_SUCCESS) return; reset_probe(trans); }
static void viastruct(dns_rdata_t *rdata, isc_mem_t *mctx, dns_rdata_t *rdata2, isc_buffer_t *b) { isc_result_t result; void *sp = NULL; isc_boolean_t need_free = ISC_FALSE; dns_rdatatype_t rdt; dns_rdataclass_t rdc; UNUSED(rdata2); /* XXXMPA remove when fromstruct is ready. */ UNUSED(b); switch (rdata->type) { case dns_rdatatype_a6: { static dns_rdata_in_a6_t in_a6; result = dns_rdata_tostruct(rdata, sp = &in_a6, NULL); break; } case dns_rdatatype_a: { switch (rdata->rdclass) { case dns_rdataclass_hs: { static dns_rdata_hs_a_t hs_a; result = dns_rdata_tostruct(rdata, sp = &hs_a, NULL); break; } case dns_rdataclass_in: { static dns_rdata_in_a_t in_a; result = dns_rdata_tostruct(rdata, sp = &in_a, NULL); break; } default: result = ISC_R_NOTIMPLEMENTED; break; } break; } case dns_rdatatype_aaaa: { static dns_rdata_in_aaaa_t in_aaaa; result = dns_rdata_tostruct(rdata, sp = &in_aaaa, NULL); break; } case dns_rdatatype_afsdb: { static dns_rdata_afsdb_t afsdb; result = dns_rdata_tostruct(rdata, sp = &afsdb, NULL); break; } case dns_rdatatype_any: { result = ISC_R_NOTIMPLEMENTED; break; } case dns_rdatatype_apl: { switch (rdata->rdclass) { case dns_rdataclass_in: { static dns_rdata_in_apl_t in_apl; result = dns_rdata_tostruct(rdata, sp = &in_apl, NULL); break; } default: result = ISC_R_NOTIMPLEMENTED; break; } break; } case dns_rdatatype_cert: { static dns_rdata_cert_t cert; result = dns_rdata_tostruct(rdata, sp = &cert, NULL); break; } case dns_rdatatype_cname: { static dns_rdata_cname_t cname; result = dns_rdata_tostruct(rdata, sp = &cname, NULL); break; } case dns_rdatatype_dname: { static dns_rdata_dname_t dname; result = dns_rdata_tostruct(rdata, sp = &dname, NULL); break; } case dns_rdatatype_gpos: { static dns_rdata_gpos_t gpos; result = dns_rdata_tostruct(rdata, sp = &gpos, NULL); break; } case dns_rdatatype_hinfo: { static dns_rdata_hinfo_t hinfo; result = dns_rdata_tostruct(rdata, sp = &hinfo, NULL); break; } case dns_rdatatype_isdn: { static dns_rdata_isdn_t isdn; result = dns_rdata_tostruct(rdata, sp = &isdn, NULL); break; } case dns_rdatatype_key: { static dns_rdata_key_t key; result = dns_rdata_tostruct(rdata, sp = &key, NULL); break; } case dns_rdatatype_kx: { static dns_rdata_in_kx_t in_kx; result = dns_rdata_tostruct(rdata, sp = &in_kx, NULL); break; } case dns_rdatatype_loc: { static dns_rdata_loc_t loc; result = dns_rdata_tostruct(rdata, sp = &loc, NULL); break; } case dns_rdatatype_mb: { static dns_rdata_mb_t mb; result = dns_rdata_tostruct(rdata, sp = &mb, NULL); break; } case dns_rdatatype_md: { static dns_rdata_md_t md; result = dns_rdata_tostruct(rdata, sp = &md, NULL); break; } case dns_rdatatype_mf: { static dns_rdata_mf_t mf; result = dns_rdata_tostruct(rdata, sp = &mf, NULL); break; } case dns_rdatatype_mg: { static dns_rdata_mg_t mg; result = dns_rdata_tostruct(rdata, sp = &mg, NULL); break; } case dns_rdatatype_minfo: { static dns_rdata_minfo_t minfo; result = dns_rdata_tostruct(rdata, sp = &minfo, NULL); break; } case dns_rdatatype_mr: { static dns_rdata_mr_t mr; result = dns_rdata_tostruct(rdata, sp = &mr, NULL); break; } case dns_rdatatype_mx: { static dns_rdata_mx_t mx; result = dns_rdata_tostruct(rdata, sp = &mx, NULL); break; } case dns_rdatatype_naptr: { static dns_rdata_naptr_t naptr; result = dns_rdata_tostruct(rdata, sp = &naptr, NULL); break; } case dns_rdatatype_ns: { static dns_rdata_ns_t ns; result = dns_rdata_tostruct(rdata, sp = &ns, NULL); break; } case dns_rdatatype_nsap: { static dns_rdata_in_nsap_t in_nsap; result = dns_rdata_tostruct(rdata, sp = &in_nsap, NULL); break; } case dns_rdatatype_nsap_ptr: { static dns_rdata_in_nsap_ptr_t in_nsap_ptr; result = dns_rdata_tostruct(rdata, sp = &in_nsap_ptr, NULL); break; } case dns_rdatatype_null: { static dns_rdata_null_t null; result = dns_rdata_tostruct(rdata, sp = &null, NULL); break; } case dns_rdatatype_nxt: { static dns_rdata_nxt_t nxt; result = dns_rdata_tostruct(rdata, sp = &nxt, NULL); break; } case dns_rdatatype_opt: { static dns_rdata_opt_t opt; result = dns_rdata_tostruct(rdata, sp = &opt, NULL); break; } case dns_rdatatype_ptr: { static dns_rdata_ptr_t ptr; result = dns_rdata_tostruct(rdata, sp = &ptr, NULL); break; } case dns_rdatatype_px: { static dns_rdata_in_px_t in_px; result = dns_rdata_tostruct(rdata, sp = &in_px, NULL); break; } case dns_rdatatype_rp: { static dns_rdata_rp_t rp; result = dns_rdata_tostruct(rdata, sp = &rp, NULL); break; } case dns_rdatatype_rt: { static dns_rdata_rt_t rt; result = dns_rdata_tostruct(rdata, sp = &rt, NULL); break; } case dns_rdatatype_sig: { static dns_rdata_sig_t sig; result = dns_rdata_tostruct(rdata, sp = &sig, NULL); break; } case dns_rdatatype_soa: { static dns_rdata_soa_t soa; result = dns_rdata_tostruct(rdata, sp = &soa, NULL); break; } case dns_rdatatype_srv: { static dns_rdata_in_srv_t in_srv; result = dns_rdata_tostruct(rdata, sp = &in_srv, NULL); break; } case dns_rdatatype_tkey: { static dns_rdata_tkey_t tkey; result = dns_rdata_tostruct(rdata, sp = &tkey, NULL); break; } case dns_rdatatype_tsig: { static dns_rdata_any_tsig_t tsig; result = dns_rdata_tostruct(rdata, sp = &tsig, NULL); break; } case dns_rdatatype_txt: { static dns_rdata_txt_t txt; result = dns_rdata_tostruct(rdata, sp = &txt, NULL); break; } case dns_rdatatype_spf: { static dns_rdata_spf_t spf; result = dns_rdata_tostruct(rdata, sp = &spf, NULL); break; } case dns_rdatatype_unspec: { static dns_rdata_unspec_t unspec; result = dns_rdata_tostruct(rdata, sp = &unspec, NULL); break; } case dns_rdatatype_uri: { static dns_rdata_uri_t uri; result = dns_rdata_tostruct(rdata, sp = &uri, NULL); break; } case dns_rdatatype_wks: { static dns_rdata_in_wks_t in_wks; result = dns_rdata_tostruct(rdata, sp = &in_wks, NULL); break; } case dns_rdatatype_x25: { static dns_rdata_x25_t x25; result = dns_rdata_tostruct(rdata, sp = &x25, NULL); break; } case dns_rdatatype_nsec: { static dns_rdata_nsec_t nsec; result = dns_rdata_tostruct(rdata, sp = &nsec, NULL); break; } case dns_rdatatype_rrsig: { static dns_rdata_rrsig_t rrsig; result = dns_rdata_tostruct(rdata, sp = &rrsig, NULL); break; } case dns_rdatatype_dnskey: { static dns_rdata_dnskey_t dnskey; result = dns_rdata_tostruct(rdata, sp = &dnskey, NULL); break; } default: result = ISC_R_NOTIMPLEMENTED; break; } if (result != ISC_R_SUCCESS) fprintf(stdout, "viastruct: tostruct %d %d return %s\n", rdata->type, rdata->rdclass, dns_result_totext(result)); else dns_rdata_freestruct(sp); switch (rdata->type) { case dns_rdatatype_a6: { static dns_rdata_in_a6_t in_a6; result = dns_rdata_tostruct(rdata, sp = &in_a6, mctx); break; } case dns_rdatatype_a: { switch (rdata->rdclass) { case dns_rdataclass_hs: { static dns_rdata_hs_a_t hs_a; result = dns_rdata_tostruct(rdata, sp = &hs_a, mctx); break; } case dns_rdataclass_in: { static dns_rdata_in_a_t in_a; result = dns_rdata_tostruct(rdata, sp = &in_a, mctx); break; } default: result = ISC_R_NOTIMPLEMENTED; break; } break; } case dns_rdatatype_aaaa: { static dns_rdata_in_aaaa_t in_aaaa; result = dns_rdata_tostruct(rdata, sp = &in_aaaa, mctx); break; } case dns_rdatatype_afsdb: { static dns_rdata_afsdb_t afsdb; result = dns_rdata_tostruct(rdata, sp = &afsdb, mctx); break; } case dns_rdatatype_any: { result = ISC_R_NOTIMPLEMENTED; break; } case dns_rdatatype_apl: { switch (rdata->rdclass) { case dns_rdataclass_in: { static dns_rdata_in_apl_t in_apl; result = dns_rdata_tostruct(rdata, sp = &in_apl, mctx); break; } default: result = ISC_R_NOTIMPLEMENTED; break; } break; } case dns_rdatatype_cert: { static dns_rdata_cert_t cert; result = dns_rdata_tostruct(rdata, sp = &cert, mctx); break; } case dns_rdatatype_cname: { static dns_rdata_cname_t cname; result = dns_rdata_tostruct(rdata, sp = &cname, mctx); break; } case dns_rdatatype_dname: { static dns_rdata_dname_t dname; result = dns_rdata_tostruct(rdata, sp = &dname, mctx); break; } case dns_rdatatype_gpos: { static dns_rdata_gpos_t gpos; result = dns_rdata_tostruct(rdata, sp = &gpos, mctx); break; } case dns_rdatatype_hinfo: { static dns_rdata_hinfo_t hinfo; result = dns_rdata_tostruct(rdata, sp = &hinfo, mctx); break; } case dns_rdatatype_isdn: { static dns_rdata_isdn_t isdn; result = dns_rdata_tostruct(rdata, sp = &isdn, mctx); break; } case dns_rdatatype_key: { static dns_rdata_key_t key; result = dns_rdata_tostruct(rdata, sp = &key, mctx); break; } case dns_rdatatype_kx: { static dns_rdata_in_kx_t in_kx; result = dns_rdata_tostruct(rdata, sp = &in_kx, mctx); break; } case dns_rdatatype_loc: { static dns_rdata_loc_t loc; result = dns_rdata_tostruct(rdata, sp = &loc, mctx); break; } case dns_rdatatype_mb: { static dns_rdata_mb_t mb; result = dns_rdata_tostruct(rdata, sp = &mb, mctx); break; } case dns_rdatatype_md: { static dns_rdata_md_t md; result = dns_rdata_tostruct(rdata, sp = &md, mctx); break; } case dns_rdatatype_mf: { static dns_rdata_mf_t mf; result = dns_rdata_tostruct(rdata, sp = &mf, mctx); break; } case dns_rdatatype_mg: { static dns_rdata_mg_t mg; result = dns_rdata_tostruct(rdata, sp = &mg, mctx); break; } case dns_rdatatype_minfo: { static dns_rdata_minfo_t minfo; result = dns_rdata_tostruct(rdata, sp = &minfo, mctx); break; } case dns_rdatatype_mr: { static dns_rdata_mr_t mr; result = dns_rdata_tostruct(rdata, sp = &mr, mctx); break; } case dns_rdatatype_mx: { static dns_rdata_mx_t mx; result = dns_rdata_tostruct(rdata, sp = &mx, mctx); break; } case dns_rdatatype_naptr: { static dns_rdata_naptr_t naptr; result = dns_rdata_tostruct(rdata, sp = &naptr, mctx); break; } case dns_rdatatype_ns: { static dns_rdata_ns_t ns; result = dns_rdata_tostruct(rdata, sp = &ns, mctx); break; } case dns_rdatatype_nsap: { static dns_rdata_in_nsap_t in_nsap; result = dns_rdata_tostruct(rdata, sp = &in_nsap, mctx); break; } case dns_rdatatype_nsap_ptr: { static dns_rdata_in_nsap_ptr_t in_nsap_ptr; result = dns_rdata_tostruct(rdata, sp = &in_nsap_ptr, mctx); break; } case dns_rdatatype_null: { static dns_rdata_null_t null; result = dns_rdata_tostruct(rdata, sp = &null, mctx); break; } case dns_rdatatype_nxt: { static dns_rdata_nxt_t nxt; result = dns_rdata_tostruct(rdata, sp = &nxt, mctx); break; } case dns_rdatatype_opt: { static dns_rdata_opt_t opt; result = dns_rdata_tostruct(rdata, sp = &opt, mctx); break; } case dns_rdatatype_ptr: { static dns_rdata_ptr_t ptr; result = dns_rdata_tostruct(rdata, sp = &ptr, mctx); break; } case dns_rdatatype_px: { static dns_rdata_in_px_t in_px; result = dns_rdata_tostruct(rdata, sp = &in_px, mctx); break; } case dns_rdatatype_rp: { static dns_rdata_rp_t rp; result = dns_rdata_tostruct(rdata, sp = &rp, mctx); break; } case dns_rdatatype_rt: { static dns_rdata_rt_t rt; result = dns_rdata_tostruct(rdata, sp = &rt, mctx); break; } case dns_rdatatype_sig: { static dns_rdata_sig_t sig; result = dns_rdata_tostruct(rdata, sp = &sig, mctx); break; } case dns_rdatatype_soa: { static dns_rdata_soa_t soa; result = dns_rdata_tostruct(rdata, sp = &soa, mctx); break; } case dns_rdatatype_srv: { static dns_rdata_in_srv_t in_srv; result = dns_rdata_tostruct(rdata, sp = &in_srv, mctx); break; } case dns_rdatatype_tkey: { static dns_rdata_tkey_t tkey; result = dns_rdata_tostruct(rdata, sp = &tkey, mctx); break; } case dns_rdatatype_tsig: { static dns_rdata_any_tsig_t tsig; result = dns_rdata_tostruct(rdata, sp = &tsig, mctx); break; } case dns_rdatatype_txt: { static dns_rdata_txt_t txt; result = dns_rdata_tostruct(rdata, sp = &txt, mctx); break; } case dns_rdatatype_spf: { static dns_rdata_spf_t spf; result = dns_rdata_tostruct(rdata, sp = &spf, mctx); break; } case dns_rdatatype_unspec: { static dns_rdata_unspec_t unspec; result = dns_rdata_tostruct(rdata, sp = &unspec, mctx); break; } case dns_rdatatype_uri: { static dns_rdata_uri_t uri; result = dns_rdata_tostruct(rdata, sp = &uri, mctx); break; } case dns_rdatatype_wks: { static dns_rdata_in_wks_t in_wks; result = dns_rdata_tostruct(rdata, sp = &in_wks, mctx); break; } case dns_rdatatype_x25: { static dns_rdata_x25_t x25; result = dns_rdata_tostruct(rdata, sp = &x25, mctx); break; } case dns_rdatatype_nsec: { static dns_rdata_nsec_t nsec; result = dns_rdata_tostruct(rdata, sp = &nsec, mctx); break; } case dns_rdatatype_rrsig: { static dns_rdata_rrsig_t rrsig; result = dns_rdata_tostruct(rdata, sp = &rrsig, mctx); break; } case dns_rdatatype_dnskey: { static dns_rdata_dnskey_t dnskey; result = dns_rdata_tostruct(rdata, sp = &dnskey, mctx); break; } default: result = ISC_R_NOTIMPLEMENTED; break; } if (result != ISC_R_SUCCESS) fprintf(stdout, "viastruct: tostruct %d %d return %s\n", rdata->type, rdata->rdclass, dns_result_totext(result)); else { need_free = ISC_TRUE; rdc = rdata->rdclass; rdt = rdata->type; result = dns_rdata_fromstruct(rdata2, rdc, rdt, sp, b); if (result != ISC_R_SUCCESS) fprintf(stdout, "viastruct: fromstruct %d %d return %s\n", rdata->type, rdata->rdclass, dns_result_totext(result)); else if (rdata->length != rdata2->length || memcmp(rdata->data, rdata2->data, rdata->length) != 0) { isc_uint32_t i; isc_uint32_t l; fprintf(stdout, "viastruct: memcmp failed\n"); fprintf(stdout, "%d %d\n", rdata->length, rdata2->length); l = rdata->length; if (rdata2->length < l) l = rdata2->length; for (i = 0; i < l; i++) fprintf(stdout, "%02x %02x\n", rdata->data[i], rdata2->data[i]); } } #if 0 switch (rdata->type) { case dns_rdatatype_a6: { dns_rdata_in_a6_t in_a6; result = dns_rdata_fromstruct(rdata2, rdc, rdt, &in_a6, b); break; } case dns_rdatatype_a: { switch (rdata->rdclass) { case dns_rdataclass_hs: { dns_rdata_hs_a_t hs_a; result = dns_rdata_fromstruct(rdata2, rdc, rdt, &hs_a, b); break; } case dns_rdataclass_in: { dns_rdata_in_a_t in_a; result = dns_rdata_fromstruct(rdata2, rdc, rdt, &in_a, b); break; } default: result = ISC_R_NOTIMPLEMENTED; break; } break; } case dns_rdatatype_aaaa: { dns_rdata_in_aaaa_t in_aaaa; result = dns_rdata_fromstruct(rdata2, rdc, rdt, &in_aaaa, b); break; } case dns_rdatatype_afsdb: { dns_rdata_afsdb_t afsdb; result = dns_rdata_fromstruct(rdata2, rdc, rdt, &afsdb, b); break; } case dns_rdatatype_any: { result = ISC_R_NOTIMPLEMENTED; break; } case dns_rdatatype_apl: { switch (rdata->rdclass) { case dns_rdataclass_in: { dns_rdata_in_apl_t in_apl; result = dns_rdata_fromstruct(rdata, rdc, rdt, &in_apl, b); break; } default: result = ISC_R_NOTIMPLEMENTED; break; } break; } case dns_rdatatype_cert: { dns_rdata_cert_t cert; result = dns_rdata_fromstruct(rdata2, rdc, rdt, &cert, b); break; } case dns_rdatatype_cname: { dns_rdata_cname_t cname; result = dns_rdata_fromstruct(rdata2, rdc, rdt, &cname, b); break; } case dns_rdatatype_dname: { dns_rdata_dname_t dname; result = dns_rdata_fromstruct(rdata2, rdc, rdt, &dname, b); break; } case dns_rdatatype_gpos: { dns_rdata_gpos_t gpos; result = dns_rdata_fromstruct(rdata2, rdc, rdt, &gpos, b); break; } case dns_rdatatype_hinfo: { dns_rdata_hinfo_t hinfo; result = dns_rdata_fromstruct(rdata2, rdc, rdt, &hinfo, b); break; } case dns_rdatatype_isdn: { dns_rdata_isdn_t isdn; result = dns_rdata_fromstruct(rdata2, rdc, rdt, &isdn, b); break; } case dns_rdatatype_key: { dns_rdata_key_t key; result = dns_rdata_fromstruct(rdata2, rdc, rdt, &key, b); break; } case dns_rdatatype_kx: { dns_rdata_in_kx_t in_kx; result = dns_rdata_fromstruct(rdata2, rdc, rdt, &in_kx, b); break; } case dns_rdatatype_loc: { dns_rdata_loc_t loc; result = dns_rdata_fromstruct(rdata2, rdc, rdt, &loc, b); break; } case dns_rdatatype_mb: { dns_rdata_mb_t mb; result = dns_rdata_fromstruct(rdata2, rdc, rdt, &mb, b); break; } case dns_rdatatype_md: { dns_rdata_md_t md; result = dns_rdata_fromstruct(rdata2, rdc, rdt, &md, b); break; } case dns_rdatatype_mf: { dns_rdata_mf_t mf; result = dns_rdata_fromstruct(rdata2, rdc, rdt, &mf, b); break; } case dns_rdatatype_mg: { dns_rdata_mg_t mg; result = dns_rdata_fromstruct(rdata2, rdc, rdt, &mg, b); break; } case dns_rdatatype_minfo: { dns_rdata_minfo_t minfo; result = dns_rdata_fromstruct(rdata2, rdc, rdt, &minfo, b); break; } case dns_rdatatype_mr: { dns_rdata_mr_t mr; result = dns_rdata_fromstruct(rdata2, rdc, rdt, &mr, b); break; } case dns_rdatatype_mx: { dns_rdata_mx_t mx; result = dns_rdata_fromstruct(rdata2, rdc, rdt, &mx, b); break; } case dns_rdatatype_naptr: { dns_rdata_naptr_t naptr; result = dns_rdata_fromstruct(rdata2, rdc, rdt, &naptr, b); break; } case dns_rdatatype_ns: { dns_rdata_ns_t ns; result = dns_rdata_fromstruct(rdata2, rdc, rdt, &ns, b); break; } case dns_rdatatype_nsap: { dns_rdata_in_nsap_t in_nsap; result = dns_rdata_fromstruct(rdata2, rdc, rdt, &in_nsap, b); break; } case dns_rdatatype_nsap_ptr: { dns_rdata_in_nsap_ptr_t in_nsap_ptr; result = dns_rdata_fromstruct(rdata2, rdc, rdt, &in_nsap_ptr, b); break; } case dns_rdatatype_null: { dns_rdata_null_t null; result = dns_rdata_fromstruct(rdata2, rdc, rdt, &null, b); break; } case dns_rdatatype_nxt: { dns_rdata_nxt_t nxt; result = dns_rdata_fromstruct(rdata2, rdc, rdt, &nxt, b); break; } case dns_rdatatype_opt: { dns_rdata_opt_t opt; result = dns_rdata_fromstruct(rdata2, rdc, rdt, &opt, b); break; } case dns_rdatatype_ptr: { dns_rdata_ptr_t ptr; result = dns_rdata_fromstruct(rdata2, rdc, rdt, &ptr, b); break; } case dns_rdatatype_px: { dns_rdata_in_px_t in_px; result = dns_rdata_fromstruct(rdata2, rdc, rdt, &in_px, b); break; } case dns_rdatatype_rp: { dns_rdata_rp_t rp; result = dns_rdata_fromstruct(rdata2, rdc, rdt, &rp, b); break; } case dns_rdatatype_rt: { dns_rdata_rt_t rt; result = dns_rdata_fromstruct(rdata2, rdc, rdt, &rt, b); break; } case dns_rdatatype_sig: { dns_rdata_sig_t sig; result = dns_rdata_fromstruct(rdata2, rdc, rdt, &sig, b); break; } case dns_rdatatype_soa: { dns_rdata_soa_t soa; result = dns_rdata_fromstruct(rdata2, rdc, rdt, &soa, b); break; } case dns_rdatatype_srv: { dns_rdata_in_srv_t in_srv; result = dns_rdata_fromstruct(rdata2, rdc, rdt, &in_srv, b); break; } case dns_rdatatype_tkey: { dns_rdata_tkey_t tkey; result = dns_rdata_fromstruct(rdata2, rdc, rdt, &tkey, b); break; } case dns_rdatatype_tsig: { dns_rdata_any_tsig_t tsig; result = dns_rdata_fromstruct(rdata2, rdc, rdt, &tsig, b); break; } case dns_rdatatype_txt: { dns_rdata_txt_t txt; result = dns_rdata_fromstruct(rdata2, rdc, rdt, &txt, b); break; } case dns_rdatatype_spf: { dns_rdata_spf_t spf; result = dns_rdata_fromstruct(rdata2, rdc, rdt, &spf, b); break; } case dns_rdatatype_unspec: { dns_rdata_unspec_t unspec; result = dns_rdata_fromstruct(rdata2, rdc, rdt, &unspec, b); break; } case dns_rdatatype_uri: { dns_rdata_uri_t uri; result = dns_rdata_fromstruct(rdata2, rdc, rdt, &uri, b); break; } case dns_rdatatype_wks: { dns_rdata_in_wks_t in_wks; result = dns_rdata_fromstruct(rdata2, rdc, rdt, &in_wks, b); break; } case dns_rdatatype_x25: { dns_rdata_x25_t x25; result = dns_rdata_fromstruct(rdata2, rdc, rdt, &x25, b); break; } case dns_rdatatype_nsec: { dns_rdata_nsec_t nsec; result = dns_rdata_fromstruct(rdata2, rdc, rdt, &nsec, b); break; } case dns_rdatatype_rrsig: { dns_rdata_rrsig_t rrsig; result = dns_rdata_fromstruct(rdata2, rdc, rdt, &rrsig, b); break; } case dns_rdatatype_dnskey: { dns_rdata_dnskey_t dnskey; result = dns_rdata_fromstruct(rdata2, rdc, rdt, &dnskey, b); break; } default: result = ISC_R_NOTIMPLEMENTED; break; } #endif if (need_free) dns_rdata_freestruct(sp); }
static isc_result_t tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) { dns_rdata_any_tsig_t tsig, querytsig; isc_region_t r, source_r, header_r, sig_r; isc_buffer_t databuf; unsigned char data[32]; dns_name_t *keyname; dns_rdata_t rdata = DNS_RDATA_INIT; isc_stdtime_t now; isc_result_t ret; dns_tsigkey_t *tsigkey; dst_key_t *key = NULL; unsigned char header[DNS_MESSAGE_HEADERLEN]; isc_uint16_t addcount, id; isc_boolean_t has_tsig = ISC_FALSE; isc_mem_t *mctx; REQUIRE(source != NULL); REQUIRE(msg != NULL); REQUIRE(dns_message_gettsigkey(msg) != NULL); REQUIRE(msg->tcp_continuation == 1); REQUIRE(msg->querytsig != NULL); if (!is_response(msg)) return (DNS_R_EXPECTEDRESPONSE); mctx = msg->mctx; tsigkey = dns_message_gettsigkey(msg); /* * Extract and parse the previous TSIG */ ret = dns_rdataset_first(msg->querytsig); if (ret != ISC_R_SUCCESS) return (ret); dns_rdataset_current(msg->querytsig, &rdata); ret = dns_rdata_tostruct(&rdata, &querytsig, NULL); if (ret != ISC_R_SUCCESS) return (ret); dns_rdata_reset(&rdata); /* * If there is a TSIG in this message, do some checks. */ if (msg->tsig != NULL) { has_tsig = ISC_TRUE; keyname = msg->tsigname; ret = dns_rdataset_first(msg->tsig); if (ret != ISC_R_SUCCESS) goto cleanup_querystruct; dns_rdataset_current(msg->tsig, &rdata); ret = dns_rdata_tostruct(&rdata, &tsig, NULL); if (ret != ISC_R_SUCCESS) goto cleanup_querystruct; /* * Do the key name and algorithm match that of the query? */ if (!dns_name_equal(keyname, &tsigkey->name) || !dns_name_equal(&tsig.algorithm, &querytsig.algorithm)) { msg->tsigstatus = dns_tsigerror_badkey; ret = DNS_R_TSIGVERIFYFAILURE; tsig_log(msg->tsigkey, 2, "key name and algorithm do not match"); goto cleanup_querystruct; } /* * Is the time ok? */ isc_stdtime_get(&now); if (now + msg->timeadjust > tsig.timesigned + tsig.fudge) { msg->tsigstatus = dns_tsigerror_badtime; tsig_log(msg->tsigkey, 2, "signature has expired"); ret = DNS_R_CLOCKSKEW; goto cleanup_querystruct; } else if (now + msg->timeadjust < tsig.timesigned - tsig.fudge) { msg->tsigstatus = dns_tsigerror_badtime; tsig_log(msg->tsigkey, 2, "signature is in the future"); ret = DNS_R_CLOCKSKEW; goto cleanup_querystruct; } } key = tsigkey->key; if (msg->tsigctx == NULL) { ret = dst_context_create3(key, mctx, DNS_LOGCATEGORY_DNSSEC, ISC_FALSE, &msg->tsigctx); if (ret != ISC_R_SUCCESS) goto cleanup_querystruct; /* * Digest the length of the query signature */ isc_buffer_init(&databuf, data, sizeof(data)); isc_buffer_putuint16(&databuf, querytsig.siglen); isc_buffer_usedregion(&databuf, &r); ret = dst_context_adddata(msg->tsigctx, &r); if (ret != ISC_R_SUCCESS) goto cleanup_context; /* * Digest the data of the query signature */ if (querytsig.siglen > 0) { r.length = querytsig.siglen; r.base = querytsig.signature; ret = dst_context_adddata(msg->tsigctx, &r); if (ret != ISC_R_SUCCESS) goto cleanup_context; } } /* * Extract the header. */ isc_buffer_usedregion(source, &r); memmove(header, r.base, DNS_MESSAGE_HEADERLEN); isc_region_consume(&r, DNS_MESSAGE_HEADERLEN); /* * Decrement the additional field counter if necessary. */ if (has_tsig) { memmove(&addcount, &header[DNS_MESSAGE_HEADERLEN - 2], 2); addcount = htons((isc_uint16_t)(ntohs(addcount) - 1)); memmove(&header[DNS_MESSAGE_HEADERLEN - 2], &addcount, 2); } /* * Put in the original id. */ /* XXX Can TCP transfers be forwarded? How would that work? */ if (has_tsig) { id = htons(tsig.originalid); memmove(&header[0], &id, 2); } /* * Digest the modified header. */ header_r.base = (unsigned char *) header; header_r.length = DNS_MESSAGE_HEADERLEN; ret = dst_context_adddata(msg->tsigctx, &header_r); if (ret != ISC_R_SUCCESS) goto cleanup_context; /* * Digest all non-TSIG records. */ isc_buffer_usedregion(source, &source_r); r.base = source_r.base + DNS_MESSAGE_HEADERLEN; if (has_tsig) r.length = msg->sigstart - DNS_MESSAGE_HEADERLEN; else r.length = source_r.length - DNS_MESSAGE_HEADERLEN; ret = dst_context_adddata(msg->tsigctx, &r); if (ret != ISC_R_SUCCESS) goto cleanup_context; /* * Digest the time signed and fudge. */ if (has_tsig) { isc_buffer_init(&databuf, data, sizeof(data)); isc_buffer_putuint48(&databuf, tsig.timesigned); isc_buffer_putuint16(&databuf, tsig.fudge); isc_buffer_usedregion(&databuf, &r); ret = dst_context_adddata(msg->tsigctx, &r); if (ret != ISC_R_SUCCESS) goto cleanup_context; sig_r.base = tsig.signature; sig_r.length = tsig.siglen; if (tsig.siglen == 0) { if (tsig.error != dns_rcode_noerror) { if (tsig.error == dns_tsigerror_badtime) ret = DNS_R_CLOCKSKEW; else ret = DNS_R_TSIGERRORSET; } else { tsig_log(msg->tsigkey, 2, "signature is empty"); ret = DNS_R_TSIGVERIFYFAILURE; } goto cleanup_context; } ret = dst_context_verify(msg->tsigctx, &sig_r); if (ret == DST_R_VERIFYFAILURE) { msg->tsigstatus = dns_tsigerror_badsig; tsig_log(msg->tsigkey, 2, "signature failed to verify(2)"); ret = DNS_R_TSIGVERIFYFAILURE; goto cleanup_context; } else if (ret != ISC_R_SUCCESS) goto cleanup_context; dst_context_destroy(&msg->tsigctx); } msg->tsigstatus = dns_rcode_noerror; return (ISC_R_SUCCESS); cleanup_context: dst_context_destroy(&msg->tsigctx); cleanup_querystruct: dns_rdata_freestruct(&querytsig); return (ret); }
isc_result_t dns_dnssec_verifymessage(isc_buffer_t *source, dns_message_t *msg, dst_key_t *key) { dns_rdata_sig_t sig; /* SIG(0) */ unsigned char header[DNS_MESSAGE_HEADERLEN]; dns_rdata_t rdata = DNS_RDATA_INIT; isc_region_t r, source_r, sig_r, header_r; isc_stdtime_t now; dst_context_t *ctx = NULL; isc_mem_t *mctx; isc_result_t result; isc_uint16_t addcount; isc_boolean_t signeedsfree = ISC_FALSE; REQUIRE(source != NULL); REQUIRE(msg != NULL); REQUIRE(key != NULL); mctx = msg->mctx; msg->verify_attempted = 1; if (is_response(msg)) { if (msg->query.base == NULL) return (DNS_R_UNEXPECTEDTSIG); } isc_buffer_usedregion(source, &source_r); RETERR(dns_rdataset_first(msg->sig0)); dns_rdataset_current(msg->sig0, &rdata); RETERR(dns_rdata_tostruct(&rdata, &sig, NULL)); signeedsfree = ISC_TRUE; if (sig.labels != 0) { result = DNS_R_SIGINVALID; goto failure; } if (isc_serial_lt(sig.timeexpire, sig.timesigned)) { result = DNS_R_SIGINVALID; msg->sig0status = dns_tsigerror_badtime; goto failure; } isc_stdtime_get(&now); if (isc_serial_lt((isc_uint32_t)now, sig.timesigned)) { result = DNS_R_SIGFUTURE; msg->sig0status = dns_tsigerror_badtime; goto failure; } else if (isc_serial_lt(sig.timeexpire, (isc_uint32_t)now)) { result = DNS_R_SIGEXPIRED; msg->sig0status = dns_tsigerror_badtime; goto failure; } if (!dns_name_equal(dst_key_name(key), &sig.signer)) { result = DNS_R_SIGINVALID; msg->sig0status = dns_tsigerror_badkey; goto failure; } RETERR(dst_context_create(key, mctx, &ctx)); /* * Digest the SIG(0) record, except for the signature. */ dns_rdata_toregion(&rdata, &r); r.length -= sig.siglen; RETERR(dst_context_adddata(ctx, &r)); /* * If this is a response, digest the query. */ if (is_response(msg)) RETERR(dst_context_adddata(ctx, &msg->query)); /* * Extract the header. */ memcpy(header, source_r.base, DNS_MESSAGE_HEADERLEN); /* * Decrement the additional field counter. */ memcpy(&addcount, &header[DNS_MESSAGE_HEADERLEN - 2], 2); addcount = htons((isc_uint16_t)(ntohs(addcount) - 1)); memcpy(&header[DNS_MESSAGE_HEADERLEN - 2], &addcount, 2); /* * Digest the modified header. */ header_r.base = (unsigned char *) header; header_r.length = DNS_MESSAGE_HEADERLEN; RETERR(dst_context_adddata(ctx, &header_r)); /* * Digest all non-SIG(0) records. */ r.base = source_r.base + DNS_MESSAGE_HEADERLEN; r.length = msg->sigstart - DNS_MESSAGE_HEADERLEN; RETERR(dst_context_adddata(ctx, &r)); sig_r.base = sig.signature; sig_r.length = sig.siglen; result = dst_context_verify(ctx, &sig_r); if (result != ISC_R_SUCCESS) { msg->sig0status = dns_tsigerror_badsig; goto failure; } msg->verified_sig = 1; dst_context_destroy(&ctx); dns_rdata_freestruct(&sig); return (ISC_R_SUCCESS); failure: if (signeedsfree) dns_rdata_freestruct(&sig); if (ctx != NULL) dst_context_destroy(&ctx); return (result); }
isc_result_t dns_dnssec_verify2(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key, isc_boolean_t ignoretime, isc_mem_t *mctx, dns_rdata_t *sigrdata, dns_name_t *wild) { dns_rdata_rrsig_t sig; dns_fixedname_t fnewname; isc_region_t r; isc_buffer_t envbuf; dns_rdata_t *rdatas; int nrdatas, i; isc_stdtime_t now; isc_result_t ret; unsigned char data[300]; dst_context_t *ctx = NULL; int labels = 0; isc_uint32_t flags; REQUIRE(name != NULL); REQUIRE(set != NULL); REQUIRE(key != NULL); REQUIRE(mctx != NULL); REQUIRE(sigrdata != NULL && sigrdata->type == dns_rdatatype_rrsig); ret = dns_rdata_tostruct(sigrdata, &sig, NULL); if (ret != ISC_R_SUCCESS) return (ret); if (isc_serial_lt(sig.timeexpire, sig.timesigned)) return (DNS_R_SIGINVALID); if (!ignoretime) { isc_stdtime_get(&now); /* * Is SIG temporally valid? */ if (isc_serial_lt((isc_uint32_t)now, sig.timesigned)) return (DNS_R_SIGFUTURE); else if (isc_serial_lt(sig.timeexpire, (isc_uint32_t)now)) return (DNS_R_SIGEXPIRED); } /* * Is the key allowed to sign data? */ flags = dst_key_flags(key); if (flags & DNS_KEYTYPE_NOAUTH) return (DNS_R_KEYUNAUTHORIZED); if ((flags & DNS_KEYFLAG_OWNERMASK) != DNS_KEYOWNER_ZONE) return (DNS_R_KEYUNAUTHORIZED); ret = dst_context_create(key, mctx, &ctx); if (ret != ISC_R_SUCCESS) goto cleanup_struct; /* * Digest the SIG rdata (not including the signature). */ ret = digest_sig(ctx, sigrdata, &sig); if (ret != ISC_R_SUCCESS) goto cleanup_context; /* * If the name is an expanded wildcard, use the wildcard name. */ dns_fixedname_init(&fnewname); labels = dns_name_countlabels(name) - 1; RUNTIME_CHECK(dns_name_downcase(name, dns_fixedname_name(&fnewname), NULL) == ISC_R_SUCCESS); if (labels - sig.labels > 0) dns_name_split(dns_fixedname_name(&fnewname), sig.labels + 1, NULL, dns_fixedname_name(&fnewname)); dns_name_toregion(dns_fixedname_name(&fnewname), &r); /* * Create an envelope for each rdata: <name|type|class|ttl>. */ isc_buffer_init(&envbuf, data, sizeof(data)); if (labels - sig.labels > 0) { isc_buffer_putuint8(&envbuf, 1); isc_buffer_putuint8(&envbuf, '*'); memcpy(data + 2, r.base, r.length); } else memcpy(data, r.base, r.length); isc_buffer_add(&envbuf, r.length); isc_buffer_putuint16(&envbuf, set->type); isc_buffer_putuint16(&envbuf, set->rdclass); isc_buffer_putuint32(&envbuf, sig.originalttl); ret = rdataset_to_sortedarray(set, mctx, &rdatas, &nrdatas); if (ret != ISC_R_SUCCESS) goto cleanup_context; isc_buffer_usedregion(&envbuf, &r); for (i = 0; i < nrdatas; i++) { isc_uint16_t len; isc_buffer_t lenbuf; isc_region_t lenr; /* * Skip duplicates. */ if (i > 0 && dns_rdata_compare(&rdatas[i], &rdatas[i-1]) == 0) continue; /* * Digest the envelope. */ ret = dst_context_adddata(ctx, &r); if (ret != ISC_R_SUCCESS) goto cleanup_array; /* * Digest the rdata length. */ isc_buffer_init(&lenbuf, &len, sizeof(len)); INSIST(rdatas[i].length < 65536); isc_buffer_putuint16(&lenbuf, (isc_uint16_t)rdatas[i].length); isc_buffer_usedregion(&lenbuf, &lenr); /* * Digest the rdata. */ ret = dst_context_adddata(ctx, &lenr); if (ret != ISC_R_SUCCESS) goto cleanup_array; ret = dns_rdata_digest(&rdatas[i], digest_callback, ctx); if (ret != ISC_R_SUCCESS) goto cleanup_array; } r.base = sig.signature; r.length = sig.siglen; ret = dst_context_verify(ctx, &r); if (ret == DST_R_VERIFYFAILURE) ret = DNS_R_SIGINVALID; cleanup_array: isc_mem_put(mctx, rdatas, nrdatas * sizeof(dns_rdata_t)); cleanup_context: dst_context_destroy(&ctx); cleanup_struct: dns_rdata_freestruct(&sig); if (ret == ISC_R_SUCCESS && labels - sig.labels > 0) { if (wild != NULL) RUNTIME_CHECK(dns_name_concatenate(dns_wildcardname, dns_fixedname_name(&fnewname), wild, NULL) == ISC_R_SUCCESS); ret = DNS_R_FROMWILDCARD; } return (ret); }
static void lookup_find(dns_lookup_t *lookup, dns_fetchevent_t *event) { isc_result_t result; isc_boolean_t want_restart; isc_boolean_t send_event; dns_name_t *name, *fname, *prefix; dns_fixedname_t foundname, fixed; dns_rdata_t rdata = DNS_RDATA_INIT; unsigned int nlabels; int order; dns_namereln_t namereln; dns_rdata_cname_t cname; dns_rdata_dname_t dname; REQUIRE(VALID_LOOKUP(lookup)); LOCK(&lookup->lock); result = ISC_R_SUCCESS; name = dns_fixedname_name(&lookup->name); do { lookup->restarts++; want_restart = ISC_FALSE; send_event = ISC_TRUE; if (event == NULL && !lookup->canceled) { dns_fixedname_init(&foundname); fname = dns_fixedname_name(&foundname); INSIST(!dns_rdataset_isassociated(&lookup->rdataset)); INSIST(!dns_rdataset_isassociated (&lookup->sigrdataset)); /* * If we have restarted then clear the old node. */ if (lookup->event->node != NULL) { INSIST(lookup->event->db != NULL); dns_db_detachnode(lookup->event->db, &lookup->event->node); } if (lookup->event->db != NULL) dns_db_detach(&lookup->event->db); result = view_find(lookup, fname); if (result == ISC_R_NOTFOUND) { /* * We don't know anything about the name. * Launch a fetch. */ if (lookup->event->node != NULL) { INSIST(lookup->event->db != NULL); dns_db_detachnode(lookup->event->db, &lookup->event->node); } if (lookup->event->db != NULL) dns_db_detach(&lookup->event->db); result = start_fetch(lookup); if (result == ISC_R_SUCCESS) send_event = ISC_FALSE; goto done; } } else if (event != NULL) { result = event->result; fname = dns_fixedname_name(&event->foundname); dns_resolver_destroyfetch(&lookup->fetch); INSIST(event->rdataset == &lookup->rdataset); INSIST(event->sigrdataset == &lookup->sigrdataset); } else fname = NULL; /* Silence compiler warning. */ /* * If we've been canceled, forget about the result. */ if (lookup->canceled) result = ISC_R_CANCELED; switch (result) { case ISC_R_SUCCESS: result = build_event(lookup); if (event == NULL) break; if (event->db != NULL) dns_db_attach(event->db, &lookup->event->db); if (event->node != NULL) dns_db_attachnode(lookup->event->db, event->node, &lookup->event->node); break; case DNS_R_CNAME: /* * Copy the CNAME's target into the lookup's * query name and start over. */ result = dns_rdataset_first(&lookup->rdataset); if (result != ISC_R_SUCCESS) break; dns_rdataset_current(&lookup->rdataset, &rdata); result = dns_rdata_tostruct(&rdata, &cname, NULL); dns_rdata_reset(&rdata); if (result != ISC_R_SUCCESS) break; result = dns_name_copy(&cname.cname, name, NULL); dns_rdata_freestruct(&cname); if (result == ISC_R_SUCCESS) { want_restart = ISC_TRUE; send_event = ISC_FALSE; } break; case DNS_R_DNAME: namereln = dns_name_fullcompare(name, fname, &order, &nlabels); INSIST(namereln == dns_namereln_subdomain); /* * Get the target name of the DNAME. */ result = dns_rdataset_first(&lookup->rdataset); if (result != ISC_R_SUCCESS) break; dns_rdataset_current(&lookup->rdataset, &rdata); result = dns_rdata_tostruct(&rdata, &dname, NULL); dns_rdata_reset(&rdata); if (result != ISC_R_SUCCESS) break; /* * Construct the new query name and start over. */ dns_fixedname_init(&fixed); prefix = dns_fixedname_name(&fixed); dns_name_split(name, nlabels, prefix, NULL); result = dns_name_concatenate(prefix, &dname.dname, name, NULL); dns_rdata_freestruct(&dname); if (result == ISC_R_SUCCESS) { want_restart = ISC_TRUE; send_event = ISC_FALSE; } break; default: send_event = ISC_TRUE; } if (dns_rdataset_isassociated(&lookup->rdataset)) dns_rdataset_disassociate(&lookup->rdataset); if (dns_rdataset_isassociated(&lookup->sigrdataset)) dns_rdataset_disassociate(&lookup->sigrdataset); done: if (event != NULL) { if (event->node != NULL) dns_db_detachnode(event->db, &event->node); if (event->db != NULL) dns_db_detach(&event->db); isc_event_free(ISC_EVENT_PTR(&event)); } /* * Limit the number of restarts. */ if (want_restart && lookup->restarts == MAX_RESTARTS) { want_restart = ISC_FALSE; result = ISC_R_QUOTA; send_event = ISC_TRUE; } } while (want_restart); if (send_event) { lookup->event->result = result; lookup->event->ev_sender = lookup; isc_task_sendanddetach(&lookup->task, (isc_event_t **)(void *)&lookup->event); dns_view_detach(&lookup->view); } UNLOCK(&lookup->lock); }
/*% * Return ISC_R_SUCCESS if we can determine that the name doesn't exist * or we can determine whether there is data or not at the name. * If the name does not exist return the wildcard name. * * Return ISC_R_IGNORE when the NSEC is not the appropriate one. */ isc_result_t dns_nsec_noexistnodata(dns_rdatatype_t type, dns_name_t *name, dns_name_t *nsecname, dns_rdataset_t *nsecset, isc_boolean_t *exists, isc_boolean_t *data, dns_name_t *wild, dns_nseclog_t logit, void *arg) { int order; dns_rdata_t rdata = DNS_RDATA_INIT; isc_result_t result; dns_namereln_t relation; unsigned int olabels, nlabels, labels; dns_rdata_nsec_t nsec; isc_boolean_t atparent; isc_boolean_t ns; isc_boolean_t soa; REQUIRE(exists != NULL); REQUIRE(data != NULL); REQUIRE(nsecset != NULL && nsecset->type == dns_rdatatype_nsec); result = dns_rdataset_first(nsecset); if (result != ISC_R_SUCCESS) { (*logit)(arg, ISC_LOG_DEBUG(3), "failure processing NSEC set"); return (result); } dns_rdataset_current(nsecset, &rdata); (*logit)(arg, ISC_LOG_DEBUG(3), "looking for relevant NSEC"); relation = dns_name_fullcompare(name, nsecname, &order, &olabels); if (order < 0) { /* * The name is not within the NSEC range. */ (*logit)(arg, ISC_LOG_DEBUG(3), "NSEC does not cover name, before NSEC"); return (ISC_R_IGNORE); } if (order == 0) { /* * The names are the same. If we are validating "." * then atparent should not be set as there is no parent. */ atparent = (olabels != 1) && dns_rdatatype_atparent(type); ns = dns_nsec_typepresent(&rdata, dns_rdatatype_ns); soa = dns_nsec_typepresent(&rdata, dns_rdatatype_soa); if (ns && !soa) { if (!atparent) { /* * This NSEC record is from somewhere higher in * the DNS, and at the parent of a delegation. * It can not be legitimately used here. */ (*logit)(arg, ISC_LOG_DEBUG(3), "ignoring parent nsec"); return (ISC_R_IGNORE); } } else if (atparent && ns && soa) { /* * This NSEC record is from the child. * It can not be legitimately used here. */ (*logit)(arg, ISC_LOG_DEBUG(3), "ignoring child nsec"); return (ISC_R_IGNORE); } if (type == dns_rdatatype_cname || type == dns_rdatatype_nxt || type == dns_rdatatype_nsec || type == dns_rdatatype_key || !dns_nsec_typepresent(&rdata, dns_rdatatype_cname)) { *exists = ISC_TRUE; *data = dns_nsec_typepresent(&rdata, type); (*logit)(arg, ISC_LOG_DEBUG(3), "nsec proves name exists (owner) data=%d", *data); return (ISC_R_SUCCESS); } (*logit)(arg, ISC_LOG_DEBUG(3), "NSEC proves CNAME exists"); return (ISC_R_IGNORE); } if (relation == dns_namereln_subdomain && dns_nsec_typepresent(&rdata, dns_rdatatype_ns) && !dns_nsec_typepresent(&rdata, dns_rdatatype_soa)) { /* * This NSEC record is from somewhere higher in * the DNS, and at the parent of a delegation. * It can not be legitimately used here. */ (*logit)(arg, ISC_LOG_DEBUG(3), "ignoring parent nsec"); return (ISC_R_IGNORE); } result = dns_rdata_tostruct(&rdata, &nsec, NULL); if (result != ISC_R_SUCCESS) return (result); relation = dns_name_fullcompare(&nsec.next, name, &order, &nlabels); if (order == 0) { dns_rdata_freestruct(&nsec); (*logit)(arg, ISC_LOG_DEBUG(3), "ignoring nsec matches next name"); return (ISC_R_IGNORE); } if (order < 0 && !dns_name_issubdomain(nsecname, &nsec.next)) { /* * The name is not within the NSEC range. */ dns_rdata_freestruct(&nsec); (*logit)(arg, ISC_LOG_DEBUG(3), "ignoring nsec because name is past end of range"); return (ISC_R_IGNORE); } if (order > 0 && relation == dns_namereln_subdomain) { (*logit)(arg, ISC_LOG_DEBUG(3), "nsec proves name exist (empty)"); dns_rdata_freestruct(&nsec); *exists = ISC_TRUE; *data = ISC_FALSE; return (ISC_R_SUCCESS); } if (wild != NULL) { dns_name_t common; dns_name_init(&common, NULL); if (olabels > nlabels) { labels = dns_name_countlabels(nsecname); dns_name_getlabelsequence(nsecname, labels - olabels, olabels, &common); } else { labels = dns_name_countlabels(&nsec.next); dns_name_getlabelsequence(&nsec.next, labels - nlabels, nlabels, &common); } result = dns_name_concatenate(dns_wildcardname, &common, wild, NULL); if (result != ISC_R_SUCCESS) { dns_rdata_freestruct(&nsec); (*logit)(arg, ISC_LOG_DEBUG(3), "failure generating wildcard name"); return (result); } } dns_rdata_freestruct(&nsec); (*logit)(arg, ISC_LOG_DEBUG(3), "nsec range ok"); *exists = ISC_FALSE; return (ISC_R_SUCCESS); }