]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
1675. [bug] named would sometimes add extra NSEC records to
authorMark Andrews <marka@isc.org>
Tue, 29 Jun 2004 00:51:50 +0000 (00:51 +0000)
committerMark Andrews <marka@isc.org>
Tue, 29 Jun 2004 00:51:50 +0000 (00:51 +0000)
                        the authority section.

CHANGES
bin/named/query.c

diff --git a/CHANGES b/CHANGES
index f4aca61209ceb780e9f3a54acc361dd8c26b352a..e8e60c528ddbd44d1dcc6a49c6812f633aea1a90 100644 (file)
--- 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.
 
index 556c294646da07bf9a3d588d334966064b83d1c6..a1ed7c2004848e3e549719eefce7b36e3aff425f 100644 (file)
@@ -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 <config.h>
 
@@ -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);