]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
1234. [bug] 'rrset-order' and 'sortlist' should be additive
authorMark Andrews <marka@isc.org>
Thu, 7 Mar 2002 13:46:41 +0000 (13:46 +0000)
committerMark Andrews <marka@isc.org>
Thu, 7 Mar 2002 13:46:41 +0000 (13:46 +0000)
                        not exclusive.

1223.   [func]          'rrset-order' partially works 'cyclic' and 'random'
                        are supported.

CHANGES
bin/named/config.c
bin/named/include/named/config.h
bin/named/query.c
bin/named/server.c
lib/dns/include/dns/view.h
lib/dns/order.c
lib/dns/rdataset.c
lib/dns/view.c

diff --git a/CHANGES b/CHANGES
index 33294d8b368ac56df79672173f9906eefb0004ae..c8ef33fed329cc2155989a1860714eaeead160fc 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,9 @@
+1234.  [bug]           'rrset-order' and 'sortlist' should be additive
+                       not exclusive.
+
+1223.  [func]          'rrset-order' partially works 'cyclic' and 'random'
+                       are supported.
+
 1222.  [bug]           Specifying 'port *' did not always result in a system
                        selected (non-reserved) port being used. [RT #2537]
 
index 557244b2dc0a6a2c48e4e851908fc3f9335dfda3..08367cfd7c6fdcb36685ea08f1705ead9655de90 100644 (file)
@@ -15,7 +15,7 @@
  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: config.c,v 1.28 2002/03/06 23:52:38 marka Exp $ */
+/* $Id: config.c,v 1.29 2002/03/07 13:46:35 marka Exp $ */
 
 #include <config.h>
 
@@ -35,6 +35,7 @@
 #include <dns/fixedname.h>
 #include <dns/name.h>
 #include <dns/rdataclass.h>
+#include <dns/rdatatype.h>
 #include <dns/tsig.h>
 #include <dns/zone.h>
 
@@ -218,6 +219,27 @@ ns_config_getclass(cfg_obj_t *classobj, dns_rdataclass_t defclass,
        return (result);
 }
 
+isc_result_t
+ns_config_gettype(cfg_obj_t *typeobj, dns_rdatatype_t deftype,
+                  dns_rdatatype_t *typep) {
+       char *str;
+       isc_textregion_t r;
+       isc_result_t result;
+
+       if (!cfg_obj_isstring(typeobj)) {
+               *typep = deftype;
+               return (ISC_R_SUCCESS);
+       }
+       str = cfg_obj_asstring(typeobj);
+       r.base = str;
+       r.length = strlen(str);
+       result = dns_rdatatype_fromtext(typep, &r);
+       if (result != ISC_R_SUCCESS)
+               cfg_obj_log(typeobj, ns_g_lctx, ISC_LOG_ERROR,
+                           "unknown type '%s'", str);
+       return (result);
+}
+
 dns_zonetype_t
 ns_config_getzonetype(cfg_obj_t *zonetypeobj) {
        dns_zonetype_t ztype = dns_zone_none;
index e92aef51aca21fb59e09c7b6626ecbf0316878b8..9b767e3bad0041da08d8deba3069d122e86b0058 100644 (file)
@@ -15,7 +15,7 @@
  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: config.h,v 1.4 2001/08/09 17:21:06 gson Exp $ */
+/* $Id: config.h,v 1.5 2002/03/07 13:46:41 marka Exp $ */
 
 #ifndef NAMED_CONFIG_H
 #define NAMED_CONFIG_H 1
@@ -38,6 +38,10 @@ isc_result_t
 ns_config_getclass(cfg_obj_t *classobj, dns_rdataclass_t defclass,
                   dns_rdataclass_t *classp);
 
+isc_result_t
+ns_config_gettype(cfg_obj_t *typeobj, dns_rdatatype_t deftype,
+                 dns_rdatatype_t *typep);
+
 dns_zonetype_t
 ns_config_getzonetype(cfg_obj_t *zonetypeobj);
 
index 8d63a6e64b3e269feee0bcf908b080501e1d58d9..8d9a50aba5dd2b1500913639ab77314472e911c6 100644 (file)
@@ -15,7 +15,7 @@
  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: query.c,v 1.217 2002/02/20 03:33:18 marka Exp $ */
+/* $Id: query.c,v 1.218 2002/03/07 13:46:38 marka Exp $ */
 
 #include <config.h>
 
@@ -29,6 +29,7 @@
 #include <dns/db.h>
 #include <dns/events.h>
 #include <dns/message.h>
+#include <dns/order.h>
 #include <dns/rdata.h>
 #include <dns/rdataclass.h>
 #include <dns/rdatalist.h>
@@ -1536,6 +1537,10 @@ query_addrdataset(ns_client_t *client, dns_name_t *fname,
 
        ISC_LIST_APPEND(fname->list, rdataset, link);
 
+       if (client->view->order != NULL)
+               rdataset->attributes |= dns_order_find(client->view->order,
+                                                      fname, rdataset->type,
+                                                      rdataset->rdclass);
        if (NOADDITIONAL(client))
                return;
 
index 9a6cd1cf901eba4f329231a47c34ea5f1d85c1df..5dd913affda78aa6662c4caf355582944b3a4fd3 100644 (file)
@@ -15,7 +15,7 @@
  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: server.c,v 1.371 2002/02/20 03:33:21 marka Exp $ */
+/* $Id: server.c,v 1.372 2002/03/07 13:46:40 marka Exp $ */
 
 #include <config.h>
 
 #include <dns/journal.h>
 #include <dns/keytable.h>
 #include <dns/master.h>
+#include <dns/order.h>
 #include <dns/peer.h>
 #include <dns/rdataclass.h>
+#include <dns/rdataset.h>
 #include <dns/rdatastruct.h>
 #include <dns/resolver.h>
 #include <dns/rootns.h>
@@ -404,6 +406,56 @@ get_view_querysource_dispatch(cfg_obj_t **maps,
        return (ISC_R_SUCCESS);
 }
 
+static isc_result_t
+configure_order(dns_order_t *order, cfg_obj_t *ent) {
+       dns_rdataclass_t rdclass;
+       dns_rdatatype_t rdtype;
+       cfg_obj_t *obj;
+       dns_fixedname_t fixed;
+       unsigned int mode = 0;
+       const char *str;
+       isc_buffer_t b;
+       isc_result_t result;
+
+       result = ns_config_getclass(cfg_tuple_get(ent, "class"),
+                                   dns_rdataclass_any, &rdclass);
+       if (result != ISC_R_SUCCESS)
+               return (result);
+
+       result = ns_config_gettype(cfg_tuple_get(ent, "type"),
+                                  dns_rdatatype_any, &rdtype);
+       if (result != ISC_R_SUCCESS)
+               return (result);
+
+       obj = cfg_tuple_get(ent, "name");
+       if (cfg_obj_isstring(obj)) 
+               str = cfg_obj_asstring(obj);
+       else
+               str = "*";
+       isc_buffer_init(&b, str, strlen(str));
+       isc_buffer_add(&b, strlen(str));
+       dns_fixedname_init(&fixed);
+       result = dns_name_fromtext(dns_fixedname_name(&fixed), &b,
+                                 dns_rootname, ISC_FALSE, NULL);
+       if (result != ISC_R_SUCCESS)
+               return (result);
+
+       obj = cfg_tuple_get(ent, "ordering");
+       INSIST(cfg_obj_isstring(obj));
+       str = cfg_obj_asstring(obj);
+       if (!strcasecmp(str, "fixed"))
+               mode = DNS_RDATASETATTR_FIXEDORDER;
+       else if (!strcasecmp(str, "random"))
+               mode = DNS_RDATASETATTR_RANDOMIZE;
+       else if (!strcasecmp(str, "cyclic"))
+               mode = 0;
+       else
+               INSIST(0);
+
+       return (dns_order_add(order, dns_fixedname_name(&fixed),
+                             rdtype, rdclass, mode));
+}
+
 static isc_result_t
 configure_peer(cfg_obj_t *cpeer, isc_mem_t *mctx, dns_peer_t **peerp) {
        isc_sockaddr_t *sa;
@@ -510,6 +562,7 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
        isc_boolean_t reused_cache = ISC_FALSE;
        int i;
        char *str;
+       dns_order_t *order = NULL;
 
        REQUIRE(DNS_VIEW_VALID(view));
 
@@ -741,6 +794,28 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
                view->peers = newpeers; /* Transfer ownership. */
        }
 
+       /*
+        *      Configure the views rrset-order.
+        */
+       {
+               cfg_obj_t *rrsetorder = NULL;
+               cfg_listelt_t *element;
+
+               (void)ns_config_get(maps, "rrset-order", &rrsetorder);
+               CHECK(dns_order_create(mctx, &order));
+               for (element = cfg_list_first(rrsetorder);
+                    element != NULL;
+                    element = cfg_list_next(element))
+               {
+                       cfg_obj_t *ent = cfg_listelt_value(element);
+
+                       CHECK(configure_order(order, ent));
+               }
+               if (view->order != NULL)
+                       dns_order_detach(&view->order);
+               dns_order_attach(order, &view->order);
+               dns_order_detach(&order);
+       }
        /*
         * Copy the aclenv object.
         */
@@ -863,6 +938,8 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
        result = ISC_R_SUCCESS;
 
  cleanup:
+       if (order != NULL)
+               dns_order_detach(&order);
        if (cmctx != NULL)
                isc_mem_detach(&cmctx);
 
index 20f7e9164ff94d370ce5bd7df409177f0075308f..9b92440d119401fa74b62a9337b92a00b60eb971 100644 (file)
@@ -15,7 +15,7 @@
  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: view.h,v 1.76 2001/11/27 04:06:15 marka Exp $ */
+/* $Id: view.h,v 1.77 2002/03/07 13:46:34 marka Exp $ */
 
 #ifndef DNS_VIEW_H
 #define DNS_VIEW_H 1
@@ -100,6 +100,7 @@ struct dns_view {
        dns_tsig_keyring_t *            statickeys;
        dns_tsig_keyring_t *            dynamickeys;
        dns_peerlist_t *                peers;
+       dns_order_t *                   order;
        dns_fwdtable_t *                fwdtable;
        isc_boolean_t                   recursion;
        isc_boolean_t                   auth_nxdomain;
index 536f17e4b5fb064feb54f18aec1e0e01609e3f55..0c719fe43b6eb167146c08ff291a76f6145e3bb6 100644 (file)
@@ -15,7 +15,7 @@
  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: order.c,v 1.2 2002/03/07 07:48:46 bwelling Exp $ */
+/* $Id: order.c,v 1.3 2002/03/07 13:46:30 marka Exp $ */
 
 #include <isc/magic.h>
 #include <isc/mem.h>
@@ -63,6 +63,7 @@ dns_order_create(isc_mem_t *mctx, dns_order_t **orderp) {
        order->mctx = NULL;
        isc_mem_attach(mctx, &order->mctx);
        order->magic = DNS_ORDER_MAGIC;
+       *orderp = order;
        return (ISC_R_SUCCESS);
 }
 
index 7766cf8466a1fa6cd4c000f8796554a8aa89b4a2..81b30ec349b3f802bb890fdf3171d2fe318e29d7 100644 (file)
@@ -15,7 +15,7 @@
  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: rdataset.c,v 1.61 2002/02/20 03:34:18 marka Exp $ */
+/* $Id: rdataset.c,v 1.62 2002/03/07 13:46:31 marka Exp $ */
 
 #include <config.h>
 
@@ -256,6 +256,7 @@ dns_rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
 
 #define MAX_SHUFFLE    32
 #define WANT_FIXED(r)  (((r)->attributes & DNS_RDATASETATTR_FIXEDORDER) != 0)
+#define WANT_RANDOM(r) (((r)->attributes & DNS_RDATASETATTR_RANDOMIZE) != 0)
 
 struct towire_sort {
        int key;
@@ -279,7 +280,7 @@ towiresorted(dns_rdataset_t *rdataset, dns_name_t *owner_name,
        dns_rdata_t rdata = DNS_RDATA_INIT;
        isc_region_t r;
        isc_result_t result;
-       unsigned int i, count, added;
+       unsigned int i, count, added, choice;
        isc_buffer_t savedbuffer, rdlen, rrbuffer;
        unsigned int headlen;
        isc_boolean_t question = ISC_FALSE;
@@ -330,7 +331,7 @@ towiresorted(dns_rdataset_t *rdataset, dns_name_t *owner_name,
         */
        if (!question &&
            count > 1 &&
-           !WANT_FIXED(rdataset) &&
+           (!WANT_FIXED(rdataset) || order != NULL) &&
            count <= MAX_SHUFFLE &&
            rdataset->type != dns_rdatatype_sig)
        {
@@ -349,33 +350,61 @@ towiresorted(dns_rdataset_t *rdataset, dns_name_t *owner_name,
                if (result != ISC_R_NOMORE)
                        return (result);
                INSIST(i == count);
+
                /*
                 * Now we shuffle.
                 */
-               if (order != NULL) {
+               if (WANT_FIXED(rdataset)) {
                        /*
-                        * Sorted order.
+                        * 'Fixed' order.
                         */
+                       INSIST(order != NULL);
                        for (i = 0; i < count; i++) {
                                sorted[i].key = (*order)(&shuffled[i],
                                                         order_arg);
                                sorted[i].rdata = &shuffled[i];
                        }
-                       qsort(sorted, count, sizeof(sorted[0]),
-                             towire_compare);
+               } else if (WANT_RANDOM(rdataset)) {
+                       /*
+                        * 'Random' order.
+                        */
+                       for (i = 0; i < count; i++) {
+                               dns_rdata_t rdata;
+                               choice = i + (((u_int)rand()>>3) % (count - i));
+                               rdata = shuffled[i];
+                               shuffled[i] = shuffled[choice];
+                               shuffled[choice] = rdata;
+                               if (order != NULL)
+                                       sorted[i].key = (*order)(&shuffled[i],
+                                                                order_arg);
+                               else
+                                       sorted[i].key = 0; /* Unused */
+                               sorted[i].rdata = &shuffled[i];
+                       }
                } else {
                        /*
                         * "Cyclic" order.
                         */
                        unsigned int j = (((unsigned int)rand()) >> 3) % count;
                        for (i = 0; i < count; i++) {
-                               sorted[j].key = 0; /* Unused */
+                               if (order != NULL)
+                                       sorted[i].key = (*order)(&shuffled[i],
+                                                                order_arg);
+                               else
+                                       sorted[j].key = 0; /* Unused */
                                sorted[j].rdata = &shuffled[i];
                                j++;
                                if (j == count)
                                        j = 0; /* Wrap around. */
                        }
                }
+
+               /*
+                * Sorted order.
+                */
+               if (order != NULL)
+                       qsort(sorted, count, sizeof(sorted[0]),
+                             towire_compare);
        }
 
        savedbuffer = *target;
index 81e795a975560c56d7955e0a9182501317593a64..7545b26bc7e6a69c8b063d4644989d85dae6cb63 100644 (file)
@@ -15,7 +15,7 @@
  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: view.c,v 1.109 2001/11/30 01:59:23 gson Exp $ */
+/* $Id: view.c,v 1.110 2002/03/07 13:46:33 marka Exp $ */
 
 #include <config.h>
 
@@ -32,6 +32,7 @@
 #include <dns/keytable.h>
 #include <dns/master.h>
 #include <dns/masterdump.h>
+#include <dns/order.h>
 #include <dns/peer.h>
 #include <dns/rdataset.h>
 #include <dns/request.h>
@@ -139,6 +140,7 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
        if (result != ISC_R_SUCCESS)
                goto cleanup_fwdtable;
        view->peers = NULL;
+       view->order = NULL;
 
        /*
         * Initialize configuration data with default values.
@@ -159,10 +161,14 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
        view->maxncachettl = 3 * 3600;
        view->dstport = 53;
 
-       result = dns_peerlist_new(view->mctx, &view->peers);
+       result = dns_order_create(view->mctx, &view->order);
        if (result != ISC_R_SUCCESS)
                goto cleanup_dynkeys;
 
+       result = dns_peerlist_new(view->mctx, &view->peers);
+       if (result != ISC_R_SUCCESS)
+               goto cleanup_order;
+
        result = dns_aclenv_init(view->mctx, &view->aclenv);
        if (result != ISC_R_SUCCESS)
                goto cleanup_peerlist;
@@ -186,6 +192,9 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
  cleanup_peerlist:
        dns_peerlist_detach(&view->peers);
 
+ cleanup_order:
+       dns_order_detach(&view->order);
+
  cleanup_dynkeys:
        dns_tsigkeyring_destroy(&view->dynamickeys);
 
@@ -222,6 +231,8 @@ destroy(dns_view_t *view) {
        REQUIRE(ADBSHUTDOWN(view));
        REQUIRE(REQSHUTDOWN(view));
 
+       if (view->order != NULL)
+               dns_order_detach(&view->order);
        if (view->peers != NULL)
                dns_peerlist_detach(&view->peers);
        if (view->dynamickeys != NULL)