diff --git a/CHANGES b/CHANGES index f4aca61209..e8e60c528d 100644 --- a/CHANGES +++ b/CHANGES @@ -10,8 +10,9 @@ 1676. [placeholder] rt10864 -1675. [placeholder] rt10847 - +1675. [bug] named would sometimes add extra NSEC records to + the authority section. + 1674. [port] linux: increase buffer size used to scan /proc/net/if_inet6. diff --git a/bin/named/query.c b/bin/named/query.c index 556c294646..a1ed7c2004 100644 --- a/bin/named/query.c +++ b/bin/named/query.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: query.c,v 1.259 2004/05/14 00:10:52 marka Exp $ */ +/* $Id: query.c,v 1.260 2004/06/29 00:51:50 marka Exp $ */ #include @@ -1839,13 +1839,15 @@ query_addwildcardproof(ns_client_t *client, dns_db_t *db, isc_buffer_t *dbuf, b; dns_name_t *fname; dns_rdataset_t *rdataset, *sigrdataset; - dns_fixedname_t tfixed; - dns_name_t *tname; + dns_fixedname_t wfixed; + dns_name_t *wname; dns_dbnode_t *node; - unsigned int options; - unsigned int olabels, nlabels, i; - isc_boolean_t done; + unsigned int options, order; + unsigned int olabels, nlabels; isc_result_t result; + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdata_nsec_t nsec; + isc_boolean_t have_wname; CTRACE("query_addwildcardproof"); fname = NULL; @@ -1853,87 +1855,107 @@ query_addwildcardproof(ns_client_t *client, dns_db_t *db, sigrdataset = NULL; node = NULL; + /* + * Get the NOQNAME proof then if !ispositve + * get the NOWILDCARD proof. + * + * DNS_DBFIND_NOWILD finds the NSEC records that covers the + * name ignoring any wildcard. From the owner and next names + * of this record you can compute which wildcard (if it exists) + * will match by finding the longest common suffix of the + * owner name and next names with the qname and prefixing that + * with the wildcard label. + * + * e.g. + * Given: + * example SOA + * example NSEC b.example + * b.example A + * b.example NSEC a.d.example + * a.d.example A + * a.d.example NSEC g.f.example + * g.f.example A + * g.f.example NSEC z.i.example + * z.i.example A + * z.i.example NSEC example + * + * QNAME: + * a.example -> example NSEC b.example + * owner common example + * next common example + * wild *.example + * d.b.example -> b.example NSEC a.d.example + * owner common b.example + * next common example + * wild *.b.example + * a.f.example -> a.d.example NSEC g.f.example + * owner common example + * next common f.example + * wild *.f.example + * j.example -> z.i.example NSEC example + * owner common example + * next common example + * wild *.f.example + */ options = client->query.dboptions | DNS_DBFIND_NOWILD; + dns_fixedname_init(&wfixed); + wname = dns_fixedname_name(&wfixed); + again: + have_wname = ISC_FALSE; + /* + * We'll need some resources... + */ + dbuf = query_getnamebuf(client); + if (dbuf == NULL) + goto cleanup; + fname = query_newname(client, dbuf, &b); + rdataset = query_newrdataset(client); + sigrdataset = query_newrdataset(client); + if (fname == NULL || rdataset == NULL || sigrdataset == NULL) + goto cleanup; - if (ispositive) { - /* - * We'll need some resources... - */ - dbuf = query_getnamebuf(client); - if (dbuf == NULL) - goto cleanup; - fname = query_newname(client, dbuf, &b); - rdataset = query_newrdataset(client); - sigrdataset = query_newrdataset(client); - if (fname == NULL || rdataset == NULL || sigrdataset == NULL) - goto cleanup; - - result = dns_db_find(db, name, NULL, - dns_rdatatype_nsec, options, 0, &node, - fname, rdataset, sigrdataset); - if (node != NULL) - dns_db_detachnode(db, &node); - if (result == DNS_R_NXDOMAIN) - query_addrrset(client, &fname, &rdataset, &sigrdataset, - dbuf, DNS_SECTION_AUTHORITY); - if (rdataset != NULL) - query_putrdataset(client, &rdataset); - if (sigrdataset != NULL) - query_putrdataset(client, &sigrdataset); - if (fname != NULL) - query_releasename(client, &fname); - } - - olabels = dns_name_countlabels(dns_db_origin(db)); - nlabels = dns_name_countlabels(name); - done = ISC_FALSE; - - for (i = nlabels - 1; i >= olabels && !done; i--) { - /* - * We'll need some resources... - */ - dbuf = query_getnamebuf(client); - if (dbuf == NULL) - goto cleanup; - fname = query_newname(client, dbuf, &b); - rdataset = query_newrdataset(client); - sigrdataset = query_newrdataset(client); - if (fname == NULL || rdataset == NULL || sigrdataset == NULL) - goto cleanup; - - dns_fixedname_init(&tfixed); - tname = dns_fixedname_name(&tfixed); - dns_name_split(name, i, NULL, tname); - result = dns_name_concatenate(dns_wildcardname, tname, tname, - NULL); - if (result != ISC_R_SUCCESS) - continue; - - result = dns_db_find(db, tname, NULL, dns_rdatatype_nsec, - client->query.dboptions, 0, &node, - fname, rdataset, sigrdataset); - if (node != NULL) - dns_db_detachnode(db, &node); - /* - * If this returns success, we've found the wildcard for a - * successful answer, so we're done. - */ - if (result == ISC_R_SUCCESS && ispositive) - break; - if (result == DNS_R_NXDOMAIN || result == DNS_R_EMPTYNAME) { - if (!ispositive && - dns_name_issubdomain(name, fname)) - done = ISC_TRUE; - query_addrrset(client, &fname, &rdataset, &sigrdataset, - dbuf, DNS_SECTION_AUTHORITY); + result = dns_db_find(db, name, NULL, dns_rdatatype_nsec, options, + 0, &node, fname, rdataset, sigrdataset); + if (node != NULL) + dns_db_detachnode(db, &node); + if (result == DNS_R_NXDOMAIN) { + if (!ispositive) + result = dns_rdataset_first(rdataset); + if (result == ISC_R_SUCCESS) { + dns_rdataset_current(rdataset, &rdata); + result = dns_rdata_tostruct(&rdata, &nsec, NULL); } - if (rdataset != NULL) - query_putrdataset(client, &rdataset); - if (sigrdataset != NULL) - query_putrdataset(client, &sigrdataset); - if (fname != NULL) - query_releasename(client, &fname); + if (result == ISC_R_SUCCESS) { + (void)dns_name_fullcompare(name, fname, &order, + &olabels); + (void)dns_name_fullcompare(name, &nsec.next, &order, + &nlabels); + if (olabels > nlabels) + dns_name_split(name, olabels, NULL, wname); + else + dns_name_split(name, nlabels, NULL, wname); + result = dns_name_concatenate(dns_wildcardname, + wname, wname, NULL); + if (result == ISC_R_SUCCESS) + have_wname = ISC_TRUE; + dns_rdata_freestruct(&nsec); + } + query_addrrset(client, &fname, &rdataset, &sigrdataset, + dbuf, DNS_SECTION_AUTHORITY); } + if (rdataset != NULL) + query_putrdataset(client, &rdataset); + if (sigrdataset != NULL) + query_putrdataset(client, &sigrdataset); + if (fname != NULL) + query_releasename(client, &fname); + if (have_wname) { + ispositive = ISC_TRUE; /* prevent loop */ + if (!dns_name_equal(name, wname)) { + name = wname; + goto again; + } + } cleanup: if (rdataset != NULL) query_putrdataset(client, &rdataset);