query.c
来自「非常好的dns解析软件」· C语言 代码 · 共 2,425 行 · 第 1/5 页
C
2,425 行
if (sigrdatasetp != NULL) sigrdataset = *sigrdatasetp; else sigrdataset = NULL; mname = NULL; mrdataset = NULL; result = dns_message_findname(client->message, section, name, rdataset->type, rdataset->covers, &mname, &mrdataset); if (result == ISC_R_SUCCESS) { /* * We've already got an RRset of the given name and type. * There's nothing else to do; */ CTRACE("query_addrrset: dns_message_findname succeeded: done"); if (dbuf != NULL) query_releasename(client, namep); return; } else if (result == DNS_R_NXDOMAIN) { /* * The name doesn't exist. */ if (dbuf != NULL) query_keepname(client, name, dbuf); dns_message_addname(client->message, name, section); *namep = NULL; mname = name; } else { RUNTIME_CHECK(result == DNS_R_NXRRSET); if (dbuf != NULL) query_releasename(client, namep); } if (rdataset->trust != dns_trust_secure && (section == DNS_SECTION_ANSWER || section == DNS_SECTION_AUTHORITY)) client->query.attributes &= ~NS_QUERYATTR_SECURE; /* * Note: we only add SIGs if we've added the type they cover, so * we do not need to check if the SIG rdataset is already in the * response. */ query_addrdataset(client, mname, rdataset); *rdatasetp = NULL; if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) { /* * We have a signature. Add it to the response. */ ISC_LIST_APPEND(mname->list, sigrdataset, link); *sigrdatasetp = NULL; } CTRACE("query_addrrset: done");}static inline isc_result_tquery_addsoa(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version, isc_boolean_t zero_ttl){ dns_name_t *name; dns_dbnode_t *node; isc_result_t result, eresult; dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL; dns_rdataset_t **sigrdatasetp = NULL; CTRACE("query_addsoa"); /* * Initialization. */ eresult = ISC_R_SUCCESS; name = NULL; rdataset = NULL; node = NULL; /* * Get resources and make 'name' be the database origin. */ result = dns_message_gettempname(client->message, &name); if (result != ISC_R_SUCCESS) return (result); dns_name_init(name, NULL); dns_name_clone(dns_db_origin(db), name); rdataset = query_newrdataset(client); if (rdataset == NULL) { eresult = DNS_R_SERVFAIL; goto cleanup; } if (WANTDNSSEC(client)) { sigrdataset = query_newrdataset(client); if (sigrdataset == NULL) { eresult = DNS_R_SERVFAIL; goto cleanup; } } /* * Find the SOA. */ result = dns_db_getoriginnode(db, &node); if (result == ISC_R_SUCCESS) { result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa, 0, client->now, rdataset, sigrdataset); } else { dns_fixedname_t foundname; dns_name_t *fname; dns_fixedname_init(&foundname); fname = dns_fixedname_name(&foundname); result = dns_db_find(db, name, version, dns_rdatatype_soa, client->query.dboptions, 0, &node, fname, rdataset, sigrdataset); } if (result != ISC_R_SUCCESS) { /* * This is bad. We tried to get the SOA RR at the zone top * and it didn't work! */ eresult = DNS_R_SERVFAIL; } else { /* * Extract the SOA MINIMUM. */ dns_rdata_soa_t soa; dns_rdata_t rdata = DNS_RDATA_INIT; result = dns_rdataset_first(rdataset); RUNTIME_CHECK(result == ISC_R_SUCCESS); dns_rdataset_current(rdataset, &rdata); result = dns_rdata_tostruct(&rdata, &soa, NULL); if (result != ISC_R_SUCCESS) goto cleanup; if (zero_ttl) { rdataset->ttl = 0; if (sigrdataset != NULL) sigrdataset->ttl = 0; } /* * Add the SOA and its SIG to the response, with the * TTLs adjusted per RFC2308 section 3. */ if (rdataset->ttl > soa.minimum) rdataset->ttl = soa.minimum; if (sigrdataset != NULL && sigrdataset->ttl > soa.minimum) sigrdataset->ttl = soa.minimum; if (sigrdataset != NULL) sigrdatasetp = &sigrdataset; else sigrdatasetp = NULL; query_addrrset(client, &name, &rdataset, sigrdatasetp, NULL, DNS_SECTION_AUTHORITY); } cleanup: query_putrdataset(client, &rdataset); if (sigrdataset != NULL) query_putrdataset(client, &sigrdataset); if (name != NULL) query_releasename(client, &name); if (node != NULL) dns_db_detachnode(db, &node); return (eresult);}static inline isc_result_tquery_addns(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version) { dns_name_t *name, *fname; dns_dbnode_t *node; isc_result_t result, eresult; dns_fixedname_t foundname; dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL; dns_rdataset_t **sigrdatasetp = NULL; CTRACE("query_addns"); /* * Initialization. */ eresult = ISC_R_SUCCESS; name = NULL; rdataset = NULL; node = NULL; dns_fixedname_init(&foundname); fname = dns_fixedname_name(&foundname); /* * Get resources and make 'name' be the database origin. */ result = dns_message_gettempname(client->message, &name); if (result != ISC_R_SUCCESS) { CTRACE("query_addns: dns_message_gettempname failed: done"); return (result); } dns_name_init(name, NULL); dns_name_clone(dns_db_origin(db), name); rdataset = query_newrdataset(client); if (rdataset == NULL) { CTRACE("query_addns: query_newrdataset failed"); eresult = DNS_R_SERVFAIL; goto cleanup; } if (WANTDNSSEC(client)) { sigrdataset = query_newrdataset(client); if (sigrdataset == NULL) { CTRACE("query_addns: query_newrdataset failed"); eresult = DNS_R_SERVFAIL; goto cleanup; } } /* * Find the NS rdataset. */ result = dns_db_getoriginnode(db, &node); if (result == ISC_R_SUCCESS) { result = dns_db_findrdataset(db, node, version, dns_rdatatype_ns, 0, client->now, rdataset, sigrdataset); } else { CTRACE("query_addns: calling dns_db_find"); result = dns_db_find(db, name, NULL, dns_rdatatype_ns, client->query.dboptions, 0, &node, fname, rdataset, sigrdataset); CTRACE("query_addns: dns_db_find complete"); } if (result != ISC_R_SUCCESS) { CTRACE("query_addns: " "dns_db_findrdataset or dns_db_find failed"); /* * This is bad. We tried to get the NS rdataset at the zone * top and it didn't work! */ eresult = DNS_R_SERVFAIL; } else { if (sigrdataset != NULL) sigrdatasetp = &sigrdataset; else sigrdatasetp = NULL; query_addrrset(client, &name, &rdataset, sigrdatasetp, NULL, DNS_SECTION_AUTHORITY); } cleanup: CTRACE("query_addns: cleanup"); query_putrdataset(client, &rdataset); if (sigrdataset != NULL) query_putrdataset(client, &sigrdataset); if (name != NULL) query_releasename(client, &name); if (node != NULL) dns_db_detachnode(db, &node); CTRACE("query_addns: done"); return (eresult);}static inline isc_result_tquery_addcnamelike(ns_client_t *client, dns_name_t *qname, dns_name_t *tname, dns_trust_t trust, dns_name_t **anamep, dns_rdatatype_t type){ dns_rdataset_t *rdataset; dns_rdatalist_t *rdatalist; dns_rdata_t *rdata; isc_result_t result; isc_region_t r; /* * We assume the name data referred to by tname won't go away. */ REQUIRE(anamep != NULL); rdatalist = NULL; result = dns_message_gettemprdatalist(client->message, &rdatalist); if (result != ISC_R_SUCCESS) return (result); rdata = NULL; result = dns_message_gettemprdata(client->message, &rdata); if (result != ISC_R_SUCCESS) return (result); rdataset = NULL; result = dns_message_gettemprdataset(client->message, &rdataset); if (result != ISC_R_SUCCESS) return (result); dns_rdataset_init(rdataset); result = dns_name_dup(qname, client->mctx, *anamep); if (result != ISC_R_SUCCESS) { dns_message_puttemprdataset(client->message, &rdataset); return (result); } rdatalist->type = type; rdatalist->covers = 0; rdatalist->rdclass = client->message->rdclass; rdatalist->ttl = 0; dns_name_toregion(tname, &r); rdata->data = r.base; rdata->length = r.length; rdata->rdclass = client->message->rdclass; rdata->type = type; ISC_LIST_INIT(rdatalist->rdata); ISC_LIST_APPEND(rdatalist->rdata, rdata, link); RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) == ISC_R_SUCCESS); rdataset->trust = trust; query_addrrset(client, anamep, &rdataset, NULL, NULL, DNS_SECTION_ANSWER); if (rdataset != NULL) { if (dns_rdataset_isassociated(rdataset)) dns_rdataset_disassociate(rdataset); dns_message_puttemprdataset(client->message, &rdataset); } return (ISC_R_SUCCESS);}/* * Mark the RRsets as secure. Update the cache (db) to reflect the * change in trust level. */static voidmark_secure(ns_client_t *client, dns_db_t *db, dns_name_t *name, dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset){ isc_result_t result; dns_dbnode_t *node = NULL; rdataset->trust = dns_trust_secure; sigrdataset->trust = dns_trust_secure; /* * Save the updated secure state. Ignore failures. */ result = dns_db_findnode(db, name, ISC_TRUE, &node); if (result != ISC_R_SUCCESS) return; (void)dns_db_addrdataset(db, node, NULL, client->now, rdataset, 0, NULL); (void)dns_db_addrdataset(db, node, NULL, client->now, sigrdataset, 0, NULL); dns_db_detachnode(db, &node);}/* * Find the secure key that corresponds to rrsig. * Note: 'keyrdataset' maintains state between sucessive calls, * there may be multiple keys with the same keyid. * Return ISC_FALSE if we have exhausted all the possible keys. */static isc_boolean_tget_key(ns_client_t *client, dns_db_t *db, dns_rdata_rrsig_t *rrsig, dns_rdataset_t *keyrdataset, dst_key_t **keyp){ isc_result_t result; dns_dbnode_t *node = NULL; isc_boolean_t secure = ISC_FALSE; if (!dns_rdataset_isassociated(keyrdataset)) { result = dns_db_findnode(db, &rrsig->signer, ISC_FALSE, &node); if (result != ISC_R_SUCCESS) return (ISC_FALSE); result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_dnskey, 0, client->now, keyrdataset, NULL); dns_db_detachnode(db, &node); if (result != ISC_R_SUCCESS) return (ISC_FALSE); if (keyrdataset->trust != dns_trust_secure) return (ISC_FALSE); result = dns_rdataset_first(keyrdataset); } else result = dns_rdataset_next(keyrdataset); for ( ; result == ISC_R_SUCCESS; result = dns_rdataset_next(keyrdataset)) { dns_rdata_t rdata = DNS_RDATA_INIT; isc_buffer_t b; dns_rdataset_current(keyrdataset, &rdata); isc_buffer_init(&b, rdata.data, rdata.length); isc_buffer_add(&b, rdata.length); result = dst_key_fromdns(&rrsig->signer, rdata.rdclass, &b, client->mctx, keyp); if (result != ISC_R_SUCCESS) continue; if (rrsig->algorithm == (dns_secalg_t)dst_key_alg(*keyp) && rrsig->keyid == (dns_keytag_t)dst_key_id(*keyp) && dst_key_iszonekey(*keyp)) { secure = ISC_TRUE; break; } dst_key_free(keyp); } return (secure);}static isc_boolean_tverify(dst_key_t *key, dns_name_t *name, dns_rdataset_t *rdataset, dns_rdata_t *rdata, isc_mem_t *mctx, isc_boolean_t acceptexpired){ isc_result_t result; dns_fixedname_t fixed; isc_boolean_t ignore = ISC_FALSE; dns_fixedname_init(&fixed); again: result = dns_dnssec_verify2(name, rdataset, key, ignore, mctx, rdata, NULL); if (result == DNS_R_SIGEXPIRED && acceptexpired) { ignore = ISC_TRUE; goto again; } if (result == ISC_R_SUCCESS || result == DNS_R_FROMWILDCARD) return (ISC_TRUE); return (ISC_FALSE);}/* * Validate the rdataset if possible with available records. */static isc_boolean_tvalidate(ns_client_t *client, dns_db_t *db, dns_name_t *name, dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset){ isc_result_t result; dns_rdata_t rdata = DNS_RDATA_INIT; dns_rdata_rrsig_t rrsig; dst_key_t *key = NULL; dns_rdataset_t keyrdataset; if (sigrdataset == NULL || !dns_rdataset_isassociated(sigrdataset)) return (ISC_FALSE); for (result = dns_rdataset_first(sigrdataset); result == ISC_R_SUCCESS; result = dns_rdataset_next(sigrdataset)) { dns_rdata_reset(&rdata); dns_rdataset_current(sigrdataset, &rdata); result = dns_rdata_tostruct(&rdata, &rrsig, NULL); if (result != ISC_R_SUCCESS) return (ISC_FALSE); if (!dns_resolver_algorithm_supported(client->view->resolver, name, rrsig.algorithm)) continue; if (!dns_name_issubdomain(name, &rrsig.signer)) continue; dns_rdataset_init(&keyrdataset); do { if (!get_key(client, db, &rrsig, &keyrdataset, &key)) break; if (verify(key, name, rdataset, &rdata, client->mctx, client->view->acceptexpired)) { dst_key_free(&key); dns_rdataset_disassociate(&keyrdataset); mark_secure(client, db, name, rdataset, sigrdataset); return (ISC_TRUE); } dst_key_free(&key); } while (1); if (dns_rdataset_isassociated(&keyrdataset)) dns_rdataset_disassociate(&keyrdataset); } return (ISC_FALSE);}static voidquery_addbestns(ns_client_t *client) { dns_db_t *db, *zdb; dns_dbnode_t *node; dns_name_t *fname, *zfname; dns_rdataset_t *rdataset, *sigrdataset, *zrdataset, *zsigrdataset
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?