]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
1443. [func] Masters lists can now be specified and referenced
authorMark Andrews <marka@isc.org>
Wed, 26 Feb 2003 06:04:03 +0000 (06:04 +0000)
committerMark Andrews <marka@isc.org>
Wed, 26 Feb 2003 06:04:03 +0000 (06:04 +0000)
                        in zone masters clauses and other masters lists.
developer: marka
reviewer: explorer

CHANGES
bin/named/config.c
doc/arm/Bv9ARM-book.xml
lib/bind9/check.c
lib/isccfg/namedconf.c

diff --git a/CHANGES b/CHANGES
index d6c092e0972f21faec8db6fbb0da4ea56e413816..22d805621e968d6522c5ac94215581db3130292b 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,6 @@
+1443.  [func]          Masters lists can now be specified and referenced
+                       in zone masters clauses and other masters lists.
+
 1442.  [func]          New fuctions for manipulating port lists:
                        dns_portlist_create(), dns_portlist_add(),
                        dns_portlist_remove(), dns_portlist_match(),
index 02610d403fa3a5fa6b1be1fd7a1632df4f2be11b..eda73be31a4a990c1c7ce79a938b95edf04f81bc 100644 (file)
@@ -15,7 +15,7 @@
  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: config.c,v 1.38 2003/02/26 02:03:57 marka Exp $ */
+/* $Id: config.c,v 1.39 2003/02/26 06:04:02 marka Exp $ */
 
 #include <config.h>
 
@@ -333,12 +333,40 @@ ns_config_putiplist(isc_mem_t *mctx, isc_sockaddr_t **addrsp,
        *addrsp = NULL;
 }
 
+static isc_result_t
+get_masters_def(cfg_obj_t *cctx, char *name, cfg_obj_t **ret) {
+       isc_result_t result;
+       cfg_obj_t *masters = NULL;
+       cfg_listelt_t *elt;
+
+       result = cfg_map_get(cctx, "masters", &masters);
+       if (result != ISC_R_SUCCESS)
+               return (result);
+       for (elt = cfg_list_first(masters);
+            elt != NULL;
+            elt = cfg_list_next(elt)) {
+               cfg_obj_t *list;
+               const char *listname;
+
+               list = cfg_listelt_value(elt);
+               listname = cfg_obj_asstring(cfg_tuple_get(list, "name"));
+
+               if (strcasecmp(listname, name) == 0) {
+                       *ret = list;
+                       return (ISC_R_SUCCESS);
+               }
+       }
+       return (ISC_R_NOTFOUND);
+}
+
 isc_result_t
 ns_config_getipandkeylist(cfg_obj_t *config, cfg_obj_t *list, isc_mem_t *mctx,
                          isc_sockaddr_t **addrsp, dns_name_t ***keysp,
                          isc_uint32_t *countp)
 {
-       isc_uint32_t count, i = 0;
+       isc_uint32_t addrcount = 0, keycount = 0, i = 0;
+       isc_uint32_t listcount = 0, l = 0, j;
+       isc_uint32_t stackcount = 0, pushed = 0;
        isc_result_t result;
        cfg_listelt_t *element;
        cfg_obj_t *addrlist;
@@ -347,12 +375,18 @@ ns_config_getipandkeylist(cfg_obj_t *config, cfg_obj_t *list, isc_mem_t *mctx,
        dns_fixedname_t fname;
        isc_sockaddr_t *addrs = NULL;
        dns_name_t **keys = NULL;
+       char **lists = NULL;
+       struct {
+               cfg_listelt_t *element;
+               in_port_t port;
+       } *stack = NULL;
 
-       INSIST(addrsp != NULL && *addrsp == NULL);
+       REQUIRE(addrsp != NULL && *addrsp == NULL);
+       REQUIRE(keysp != NULL && *keysp == NULL);
+       REQUIRE(countp != NULL);
 
+ newlist:
        addrlist = cfg_tuple_get(list, "addresses");
-       count = ns_config_listcount(addrlist);
-
        portobj = cfg_tuple_get(list, "port");
        if (cfg_obj_isuint32(portobj)) {
                isc_uint32_t val = cfg_obj_asuint32(portobj);
@@ -370,35 +404,126 @@ ns_config_getipandkeylist(cfg_obj_t *config, cfg_obj_t *list, isc_mem_t *mctx,
 
        result = ISC_R_NOMEMORY;
 
-       addrs = isc_mem_get(mctx, count * sizeof(isc_sockaddr_t));
-       if (addrs == NULL)
-               goto cleanup;
-
-       keys = isc_mem_get(mctx, count * sizeof(dns_name_t *));
-       if (keys == NULL)
-               goto cleanup;
-
-       for (element = cfg_list_first(addrlist);
+       element = cfg_list_first(addrlist);
+ resume:
+       for ( ;
             element != NULL;
-            element = cfg_list_next(element), i++)
+            element = cfg_list_next(element))
        {
                cfg_obj_t *addr;
                cfg_obj_t *key;
                char *keystr;
                isc_buffer_t b;
 
-               INSIST(i < count);
-
-               addr = cfg_tuple_get(cfg_listelt_value(element), "sockaddr");
+               addr = cfg_tuple_get(cfg_listelt_value(element),
+                                    "masterselement");
                key = cfg_tuple_get(cfg_listelt_value(element), "key");
 
+               if (!cfg_obj_issockaddr(addr)) {
+                       char *listname = cfg_obj_asstring(addr);
+                       isc_result_t tresult;
+
+                       /* Grow lists? */
+                       if (listcount == l) {
+                               void * new;
+                               isc_uint32_t newlen = listcount + 16;
+                               size_t newsize, oldsize;
+
+                               newsize = newlen * sizeof(*lists);
+                               oldsize = listcount * sizeof(*lists);
+                               new = isc_mem_get(mctx, newsize);
+                               if (new == NULL)
+                                       goto cleanup;
+                               if (listcount != 0) {
+                                       memcpy(new, lists, oldsize);
+                                       isc_mem_put(mctx, lists, oldsize);
+                               }
+                               lists = new;
+                               listcount = newlen;
+                       }
+                       /* Seen? */
+                       for (j = 0; j < l; j++)
+                               if (strcasecmp(lists[j], listname) == 0)
+                                       break;
+                       if (j < l)
+                               continue;
+                       tresult = get_masters_def(config, listname, &list);
+                       if (tresult == ISC_R_NOTFOUND) {
+                               cfg_obj_log(addr, ns_g_lctx, ISC_LOG_ERROR,
+                                    "masters \"%s\" not found", listname);
+
+                               result = tresult;
+                               goto cleanup;
+                       }
+                       if (tresult != ISC_R_SUCCESS)
+                               goto cleanup;
+                       lists[l++] = listname;
+                       /* Grow stack? */
+                       if (stackcount == pushed) {
+                               void * new;
+                               isc_uint32_t newlen = stackcount + 16;
+                               size_t newsize, oldsize;
+
+                               newsize = newlen * sizeof(*stack);
+                               oldsize = stackcount * sizeof(*stack);
+                               new = isc_mem_get(mctx, newsize);
+                               if (new == NULL)
+                                       goto cleanup;
+                               if (stackcount != 0) {
+                                       memcpy(new, stack, oldsize);
+                                       isc_mem_put(mctx, stack, oldsize);
+                               }
+                               stack = new;
+                               stackcount = newlen;
+                       }
+                       /*
+                        * We want to resume processing this list on the
+                        * next element.
+                        */
+                       stack[pushed].element = cfg_list_next(element);
+                       stack[pushed].port = port;
+                       pushed++;
+                       goto newlist;
+               }
+
+               if (i == addrcount) {
+                       void * new;
+                       isc_uint32_t newlen = addrcount + 16;
+                       size_t newsize, oldsize;
+
+                       newsize = newlen * sizeof(isc_sockaddr_t);
+                       oldsize = addrcount * sizeof(isc_sockaddr_t);
+                       new = isc_mem_get(mctx, newsize);
+                       if (new == NULL)
+                               goto cleanup;
+                       if (addrcount != 0) {
+                               memcpy(new, addrs, oldsize);
+                               isc_mem_put(mctx, addrs, oldsize);
+                       }
+                       addrs = new;
+                       addrcount = newlen;
+
+                       newsize = newlen * sizeof(dns_name_t *);
+                       oldsize = keycount * sizeof(dns_name_t *);
+                       new = isc_mem_get(mctx, newsize);
+                       if (new == NULL)
+                               goto cleanup;
+                       if (keycount != 0) {
+                               memcpy(new, keys, newsize);
+                               isc_mem_put(mctx, keys, newsize);
+                       }
+                       keys = new;
+                       keycount = newlen;
+               }
+
                addrs[i] = *cfg_obj_assockaddr(addr);
                if (isc_sockaddr_getport(&addrs[i]) == 0)
                        isc_sockaddr_setport(&addrs[i], port);
-
                keys[i] = NULL;
-               if (!cfg_obj_isstring(key))
+               if (!cfg_obj_isstring(key)) {
+                       i++;
                        continue;
+               }
                keys[i] = isc_mem_get(mctx, sizeof(dns_name_t));
                if (keys[i] == NULL)
                        goto cleanup;
@@ -416,20 +541,62 @@ ns_config_getipandkeylist(cfg_obj_t *config, cfg_obj_t *list, isc_mem_t *mctx,
                                      keys[i]);
                if (result != ISC_R_SUCCESS)
                        goto cleanup;
+               i++;
+       }
+       if (pushed != 0) {
+               pushed--;
+               element = stack[pushed].element;
+               port = stack[pushed].port;
+               goto resume;
+       }
+       if (i < addrcount) {
+               void * new;
+               size_t newsize, oldsize;
+
+               newsize = i * sizeof(isc_sockaddr_t);
+               oldsize = addrcount * sizeof(isc_sockaddr_t);
+               if (i != 0) {
+                       new = isc_mem_get(mctx, newsize);
+                       if (new == NULL)
+                               goto cleanup;
+                       memcpy(new, addrs, newsize);
+                       isc_mem_put(mctx, addrs, oldsize);
+               } else
+                       new = NULL;
+               addrs = new;
+               addrcount = i;
+
+               newsize = i * sizeof(dns_name_t *);
+               oldsize = keycount * sizeof(dns_name_t *);
+               if (i != 0) {
+                       new = isc_mem_get(mctx, newsize);
+                       if (new == NULL)
+                               goto cleanup;
+                       memcpy(new, keys,  newsize);
+                       isc_mem_put(mctx, keys, oldsize);
+               } else
+                       new = NULL;
+               keys = new;
+               keycount = i;
        }
-       INSIST(i == count);
+
+       if (lists != NULL)
+               isc_mem_put(mctx, lists, listcount * sizeof(*lists));
+       if (stack != NULL)
+               isc_mem_put(mctx, stack, stackcount * sizeof(*stack));
+       
+       INSIST(keycount == addrcount);
 
        *addrsp = addrs;
        *keysp = keys;
-       *countp = count;
+       *countp = addrcount;
 
        return (ISC_R_SUCCESS);
 
  cleanup:
        if (addrs != NULL)
-               isc_mem_put(mctx, addrs, count * sizeof(isc_sockaddr_t));
+               isc_mem_put(mctx, addrs, addrcount * sizeof(isc_sockaddr_t));
        if (keys != NULL) {
-               unsigned int j;
                for (j = 0; j <= i; j++) {
                        if (keys[j] == NULL)
                                continue;
@@ -437,8 +604,12 @@ ns_config_getipandkeylist(cfg_obj_t *config, cfg_obj_t *list, isc_mem_t *mctx,
                                dns_name_free(keys[j], mctx);
                        isc_mem_put(mctx, keys[j], sizeof(dns_name_t));
                }
-               isc_mem_put(mctx, keys, count * sizeof(dns_name_t *));
+               isc_mem_put(mctx, keys, keycount * sizeof(dns_name_t *));
        }
+       if (lists != NULL)
+               isc_mem_put(mctx, lists, listcount * sizeof(*lists));
+       if (stack != NULL)
+               isc_mem_put(mctx, stack, stackcount * sizeof(*stack));
        return (result);
 }
 
index c520e1032f12ddf7248168b11602b023a0474303..8004433455b625178687b0cd09c9fde158b26b35 100644 (file)
@@ -2,7 +2,7 @@
 <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.0//EN"
                "http://www.oasis-open.org/docbook/xml/4.0/docbookx.dtd">
 
-<!-- File: $Id: Bv9ARM-book.xml,v 1.216 2003/02/26 05:05:14 marka Exp $ -->
+<!-- File: $Id: Bv9ARM-book.xml,v 1.217 2003/02/26 06:04:03 marka Exp $ -->
 
 <book>
 <title>BIND 9 Administrator Reference Manual</title>
@@ -2021,6 +2021,11 @@ authentication and authorization using TSIG.</para></entry>
             <entry colname = "1"><para><command>logging</command></para></entry>
             <entry colname = "2"><para>specifies what the server logs, and where
 the log messages are sent.</para></entry>
+          </row>
+          <row rowsep = "0">
+            <entry colname = "1"><para><command>masters</command></para></entry>
+            <entry colname = "2"><para>defines a named masters list for
+inclusion in stub and slave zone masters clauses.</para></entry>
           </row>
           <row rowsep = "0">
             <entry colname = "1"><para><command>options</command></para></entry>
@@ -2681,6 +2686,17 @@ which are appended to relative names in queries.</para>
 number of dots in a relative domain name that should result in an
 exact match lookup before search path elements are appended.</para>
 </sect2>
+<sect2>
+      <title><command>masters</command> Statement Grammar</title>
+<programlisting>
+<command>masters</command> <replaceable>name</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> { ( <replaceable>masters_list</replaceable> | <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> <optional>key <replaceable>key</replaceable></optional> ) ; <optional>...</optional> } ; 
+</programlisting>
+</sect2>
+<sect2>
+      <title><command>masters</command> Statement Definition and Usage </title>
+<para><command>masters</command> lists allow for a common set of masters
+to be easily used by multiple stub and slave zones.
+</sect2>
 <sect2>
 <title><command>options</command> Statement Grammar</title>
 
@@ -4407,7 +4423,7 @@ Statement Grammar</title>
     <optional> ixfr-base <replaceable>string</replaceable> ; </optional>
     <optional> ixfr-tmp-file <replaceable>string</replaceable> ; </optional>
     <optional> maintain-ixfr-base <replaceable>yes_or_no</replaceable> ; </optional>
-    <optional> masters <optional>port <replaceable>ip_port</replaceable></optional> { <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> <optional>key <replaceable>key</replaceable></optional>; <optional>...</optional> } ; </optional>
+    <optional> masters <optional>port <replaceable>ip_port</replaceable></optional> { ( <replaceable>masters_list</replaceable> | <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> <optional>key <replaceable>key</replaceable></optional> ) ; <optional>...</optional> } ; </optional>
     <optional> max-ixfr-log-size <replaceable>number</replaceable> ; </optional>
     <optional> max-transfer-idle-in <replaceable>number</replaceable> ; </optional>
     <optional> max-transfer-idle-out <replaceable>number</replaceable> ; </optional>
@@ -4451,6 +4467,7 @@ it.</para></entry>
 <entry colname = "2"><para>A slave zone is a replica of a master
 zone. The <command>masters</command> list specifies one or more IP addresses
 of master servers that the slave contacts to update its copy of the zone.
+Masters list elements can also be names of other masters lists.
 By default, transfers are made from port 53 on the servers; this can
 be changed for all servers by specifying a port number before the
 list of IP addresses, or on a per-server basis after the IP address.
index ee1310749904809bb6dbfac0df02810516280670..074c230c8f024ea3e85147ac6808e5a2e78ac4d6 100644 (file)
@@ -15,7 +15,7 @@
  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: check.c,v 1.34 2003/01/16 03:59:24 marka Exp $ */
+/* $Id: check.c,v 1.35 2003/02/26 06:04:03 marka Exp $ */
 
 #include <config.h>
 
@@ -282,6 +282,126 @@ check_options(cfg_obj_t *options, isc_log_t *logctx) {
        return (result);
 }
 
+static isc_result_t
+get_masters_def(cfg_obj_t *cctx, char *name, cfg_obj_t **ret) {
+       isc_result_t result;
+       cfg_obj_t *masters = NULL;
+       cfg_listelt_t *elt;
+
+       result = cfg_map_get(cctx, "masters", &masters);
+       if (result != ISC_R_SUCCESS)
+               return (result);
+       for (elt = cfg_list_first(masters);
+            elt != NULL;
+            elt = cfg_list_next(elt)) {
+               cfg_obj_t *list;
+               const char *listname;
+
+               list = cfg_listelt_value(elt);
+               listname = cfg_obj_asstring(cfg_tuple_get(list, "name"));
+
+               if (strcasecmp(listname, name) == 0) {
+                       *ret = list;
+                       return (ISC_R_SUCCESS);
+               }
+       }
+       return (ISC_R_NOTFOUND);
+}
+
+static isc_result_t
+validate_masters(cfg_obj_t *obj, cfg_obj_t *config, isc_uint32_t *countp,
+                isc_log_t *logctx, isc_mem_t *mctx)
+{
+       isc_result_t result = ISC_R_SUCCESS;
+       isc_result_t tresult;
+       isc_uint32_t count = 0;
+       isc_symtab_t *symtab = NULL;
+       isc_symvalue_t symvalue;
+       cfg_listelt_t *element;
+       cfg_listelt_t **stack = NULL;
+       isc_uint32_t stackcount = 0, pushed = 0;
+       cfg_obj_t *list;
+
+       REQUIRE(countp != NULL);
+       result = isc_symtab_create(mctx, 100, NULL, NULL, ISC_FALSE, &symtab);
+       if (result != ISC_R_SUCCESS)
+               return (result);
+
+ newlist:
+       list = cfg_tuple_get(obj, "addresses");
+       element = cfg_list_first(list);
+ resume:       
+       for ( ;
+            element != NULL;
+            element = cfg_list_next(element))
+       {
+               char *listname;
+               cfg_obj_t *addr;
+               cfg_obj_t *key;
+
+               addr = cfg_tuple_get(cfg_listelt_value(element),
+                                    "masterselement");
+               key = cfg_tuple_get(cfg_listelt_value(element), "key");
+
+               if (cfg_obj_issockaddr(addr)) {
+                       count++;
+                       continue;
+               }
+               if (!cfg_obj_isvoid(key)) {
+                       cfg_obj_log(key, logctx, ISC_LOG_ERROR,
+                                   "unexpected token '%s'",
+                                   cfg_obj_asstring(key));
+                       if (result == ISC_R_SUCCESS)
+                               result = ISC_R_FAILURE;
+               }
+               listname = cfg_obj_asstring(addr);
+               symvalue.as_pointer = addr;
+               tresult = isc_symtab_define(symtab, listname, 1, symvalue,
+                                           isc_symexists_reject);
+               if (tresult == ISC_R_EXISTS)
+                       continue;
+               tresult = get_masters_def(config, listname, &obj);
+               if (tresult != ISC_R_SUCCESS) {
+                       if (result == ISC_R_SUCCESS)
+                               result = tresult;
+                       cfg_obj_log(addr, logctx, ISC_LOG_ERROR,
+                                   "unable to find masters list '%s'",
+                                   listname);
+                       continue;
+               }
+               /* Grow stack? */
+               if (stackcount == pushed) {
+                       void * new;
+                       isc_uint32_t newlen = stackcount + 16;
+                       size_t newsize, oldsize;
+
+                       newsize = newlen * sizeof(*stack);
+                       oldsize = stackcount * sizeof(*stack);
+                       new = isc_mem_get(mctx, newsize);
+                       if (new == NULL)
+                               goto cleanup;
+                       if (stackcount != 0) {
+                               memcpy(new, stack, oldsize);
+                               isc_mem_put(mctx, stack, oldsize);
+                       }
+                       stack = new;
+                       stackcount = newlen;
+               }
+               stack[pushed++] = cfg_list_next(element);
+               goto newlist;
+       }
+       if (pushed != 0) {
+               element = stack[--pushed];
+               goto resume;
+       }
+ cleanup:
+       if (stack != NULL)
+               isc_mem_put(mctx, stack, stackcount * sizeof(*stack));
+       isc_symtab_destroy(&symtab);
+       *countp = count;
+       return (result);
+}
+
 #define MASTERZONE     1
 #define SLAVEZONE      2
 #define STUBZONE       4
@@ -294,7 +414,7 @@ typedef struct {
 } optionstable;
 
 static isc_result_t
-check_zoneconf(cfg_obj_t *zconfig, isc_symtab_t *symtab,
+check_zoneconf(cfg_obj_t *zconfig, cfg_obj_t *config, isc_symtab_t *symtab,
               dns_rdataclass_t defclass, isc_log_t *logctx, isc_mem_t *mctx)
 {
        const char *zname;
@@ -302,7 +422,6 @@ check_zoneconf(cfg_obj_t *zconfig, isc_symtab_t *symtab,
        unsigned int ztype;
        cfg_obj_t *zoptions;
        cfg_obj_t *obj = NULL;
-       cfg_obj_t *addrlist = NULL;
        isc_symvalue_t symvalue;
        isc_result_t result = ISC_R_SUCCESS;
        isc_result_t tresult;
@@ -486,8 +605,12 @@ check_zoneconf(cfg_obj_t *zconfig, isc_symtab_t *symtab,
                                    zname);
                        result = ISC_R_FAILURE;
                } else {
-                       addrlist = cfg_tuple_get(obj, "addresses");
-                       if (cfg_list_first(addrlist) == NULL) {
+                       isc_uint32_t count;
+                       tresult = validate_masters(obj, config, &count,
+                                                  logctx, mctx);
+                       if (tresult != ISC_R_SUCCESS && result == ISC_R_SUCCESS)
+                               result = tresult;
+                       if (tresult == ISC_R_SUCCESS && count == 0) {
                                cfg_obj_log(zoptions, logctx, ISC_LOG_ERROR,
                                            "zone '%s': empty 'masters' entry",
                                            zname);
@@ -706,7 +829,8 @@ check_viewconf(cfg_obj_t *config, cfg_obj_t *vconfig, dns_rdataclass_t vclass,
                isc_result_t tresult;
                cfg_obj_t *zone = cfg_listelt_value(element);
 
-               tresult = check_zoneconf(zone, symtab, vclass, logctx, mctx);
+               tresult = check_zoneconf(zone, config, symtab, vclass,
+                                        logctx, mctx);
                if (tresult != ISC_R_SUCCESS)
                        result = ISC_R_FAILURE;
        }
@@ -938,5 +1062,43 @@ bind9_check_namedconf(cfg_obj_t *config, isc_log_t *logctx, isc_mem_t *mctx) {
                }
        }
 
+        tresult = cfg_map_get(config, "kal", &acls);
+        if (tresult == ISC_R_SUCCESS) {
+               cfg_listelt_t *elt;
+               cfg_listelt_t *elt2;
+               const char *aclname;
+
+               for (elt = cfg_list_first(acls);
+                    elt != NULL;
+                    elt = cfg_list_next(elt)) {
+                       cfg_obj_t *acl = cfg_listelt_value(elt);
+
+                       aclname = cfg_obj_asstring(cfg_tuple_get(acl, "name"));
+
+                       for (elt2 = cfg_list_next(elt);
+                            elt2 != NULL;
+                            elt2 = cfg_list_next(elt2)) {
+                               cfg_obj_t *acl2 = cfg_listelt_value(elt2);
+                               const char *name;
+                               name = cfg_obj_asstring(cfg_tuple_get(acl2,
+                                                                     "name"));
+                               if (strcasecmp(aclname, name) == 0) {
+                                       const char *file = cfg_obj_file(acl);
+                                       unsigned int line = cfg_obj_line(acl);
+
+                                       if (file == NULL)
+                                               file = "<unknown file>";
+
+                                       cfg_obj_log(acl2, logctx, ISC_LOG_ERROR,
+                                                   "attempt to redefine "
+                                                   "kal '%s' previous "
+                                                   "definition: %s:%u",
+                                                    name, file, line);
+                                       result = ISC_R_FAILURE;
+                               }
+                       }
+               }
+       }
+
        return (result);
 }
index e224aa4aec295582baa1222d22f6a636b787a8bf..f1ac5ebecc96f089d813051d950ec754530e8c0e 100644 (file)
@@ -15,7 +15,7 @@
  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: namedconf.c,v 1.17 2003/02/26 05:05:16 marka Exp $ */
+/* $Id: namedconf.c,v 1.18 2003/02/26 06:04:03 marka Exp $ */
 
 #include <config.h>
 
@@ -69,8 +69,7 @@ doc_optional_keyvalue(cfg_printer_t *pctx, const cfg_type_t *type);
 static cfg_type_t cfg_type_acl;
 static cfg_type_t cfg_type_addrmatchelt;
 static cfg_type_t cfg_type_bracketed_aml;
-static cfg_type_t cfg_type_bracketed_namesockaddrlist;
-static cfg_type_t cfg_type_bracketed_sockaddrkeylist;
+static cfg_type_t cfg_type_bracketed_namesockaddrkeylist;
 static cfg_type_t cfg_type_bracketed_sockaddrlist;
 static cfg_type_t cfg_type_controls;
 static cfg_type_t cfg_type_controls_sockaddr;
@@ -81,8 +80,8 @@ static cfg_type_t cfg_type_logfile;
 static cfg_type_t cfg_type_logging;
 static cfg_type_t cfg_type_logseverity;
 static cfg_type_t cfg_type_lwres;
+static cfg_type_t cfg_type_masterselement;
 static cfg_type_t cfg_type_nameportiplist;
-static cfg_type_t cfg_type_namesockaddr;
 static cfg_type_t cfg_type_negated;
 static cfg_type_t cfg_type_notifytype;
 static cfg_type_t cfg_type_optional_class;
@@ -140,38 +139,48 @@ static cfg_tuplefielddef_t acl_fields[] = {
 static cfg_type_t cfg_type_acl = {
        "acl", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple, acl_fields };
 
+/* masters */
+static cfg_tuplefielddef_t masters_fields[] = {
+       { "name", &cfg_type_astring, 0 },
+       { "port", &cfg_type_optional_port, 0 },
+       { "addresses", &cfg_type_bracketed_namesockaddrkeylist, 0 },
+       { NULL, NULL, 0 }
+};
+
+static cfg_type_t cfg_type_masters = {
+       "masters", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple, masters_fields };
 
 /*
  * "sockaddrkeylist", a list of socket addresses with optional keys
  * and an optional default port, as used in the masters option.
  * E.g.,
- *   "port 1234 { 10.0.0.1 key foo; 1::2 port 69; }"
+ *   "port 1234 { mymasters; 10.0.0.1 key foo; 1::2 port 69; }"
  */
 
-static cfg_tuplefielddef_t sockaddrkey_fields[] = {
-       { "sockaddr", &cfg_type_sockaddr, 0 },
+static cfg_tuplefielddef_t namesockaddrkey_fields[] = {
+       { "masterselement", &cfg_type_masterselement, 0 },
        { "key", &cfg_type_optional_keyref, 0 },
        { NULL, NULL, 0 },
 };
 
-static cfg_type_t cfg_type_sockaddrkey = {
-       "sockaddrkey", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple,
-       sockaddrkey_fields
+static cfg_type_t cfg_type_namesockaddrkey = {
+       "namesockaddrkey", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple,
+       namesockaddrkey_fields
 };
 
-static cfg_type_t cfg_type_bracketed_sockaddrkeylist = {
-       "bracketed_sockaddrkeylist", cfg_parse_bracketed_list,
-       cfg_print_bracketed_list, cfg_doc_bracketed_list, &cfg_rep_list, &cfg_type_sockaddrkey
+static cfg_type_t cfg_type_bracketed_namesockaddrkeylist = {
+       "bracketed_namesockaddrkeylist", cfg_parse_bracketed_list,
+       cfg_print_bracketed_list, cfg_doc_bracketed_list, &cfg_rep_list, &cfg_type_namesockaddrkey
 };
 
-static cfg_tuplefielddef_t sockaddrkeylist_fields[] = {
+static cfg_tuplefielddef_t namesockaddrkeylist_fields[] = {
        { "port", &cfg_type_optional_port, 0 },
-       { "addresses", &cfg_type_bracketed_sockaddrkeylist, 0 },
+       { "addresses", &cfg_type_bracketed_namesockaddrkeylist, 0 },
        { NULL, NULL, 0 }
 };
-static cfg_type_t cfg_type_sockaddrkeylist = {
+static cfg_type_t cfg_type_namesockaddrkeylist = {
        "sockaddrkeylist", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple,
-       sockaddrkeylist_fields
+       namesockaddrkeylist_fields
 };
 
 /*
@@ -526,6 +535,7 @@ namedconf_clauses[] = {
        { "options", &cfg_type_options, 0 },
        { "controls", &cfg_type_controls, CFG_CLAUSEFLAG_MULTI },
        { "acl", &cfg_type_acl, CFG_CLAUSEFLAG_MULTI },
+       { "masters", &cfg_type_masters, CFG_CLAUSEFLAG_MULTI },
        { "logging", &cfg_type_logging, 0 },
        { "view", &cfg_type_view, CFG_CLAUSEFLAG_MULTI },
        { "lwres", &cfg_type_lwres, CFG_CLAUSEFLAG_MULTI },
@@ -702,7 +712,7 @@ zone_only_clauses[] = {
        { "file", &cfg_type_qstring, 0 },
        { "ixfr-base", &cfg_type_qstring, CFG_CLAUSEFLAG_OBSOLETE },
        { "ixfr-tmp-file", &cfg_type_qstring, CFG_CLAUSEFLAG_OBSOLETE },
-       { "masters", &cfg_type_sockaddrkeylist, 0 },
+       { "masters", &cfg_type_namesockaddrkeylist, 0 },
        { "pubkey", &cfg_type_pubkey,
          CFG_CLAUSEFLAG_MULTI | CFG_CLAUSEFLAG_OBSOLETE },
        { "update-policy", &cfg_type_updatepolicy, 0 },
@@ -1676,7 +1686,7 @@ static cfg_type_t cfg_type_nameport = {
 };
 
 static void
-doc_namesockaddr(cfg_printer_t *pctx, const cfg_type_t *type) {
+doc_sockaddrnameport(cfg_printer_t *pctx, const cfg_type_t *type) {
        UNUSED(type);
        cfg_print_chars(pctx, "( ", 2);
        cfg_print_cstr(pctx, "<quoted_string>");
@@ -1694,7 +1704,8 @@ doc_namesockaddr(cfg_printer_t *pctx, const cfg_type_t *type) {
 }
 
 static isc_result_t
-parse_namesockaddr(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret)
+parse_sockaddrnameport(cfg_parser_t *pctx, const cfg_type_t *type,
+                      cfg_obj_t **ret)
 {
         isc_result_t result;
        cfg_obj_t *obj = NULL;
@@ -1719,7 +1730,7 @@ parse_namesockaddr(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret)
                }
        } else {
                cfg_parser_error(pctx, CFG_LOG_NEAR,
-                            "expected IP match list element");
+                            "expected IP address or hostname");
                return (ISC_R_UNEXPECTEDTOKEN);
        }
  cleanup:
@@ -1727,25 +1738,25 @@ parse_namesockaddr(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret)
        return (result);
 }
 
-static cfg_type_t cfg_type_namesockaddr = {
-       "namesockaddr_element", parse_namesockaddr, NULL, doc_namesockaddr,
-       NULL, NULL
+static cfg_type_t cfg_type_sockaddrnameport = {
+       "sockaddrnameport_element", parse_sockaddrnameport, NULL,
+        doc_sockaddrnameport, NULL, NULL
 };
 
-static cfg_type_t cfg_type_bracketed_namesockaddrlist = {
-       "bracketed_namesockaddrlist", cfg_parse_bracketed_list,
+static cfg_type_t cfg_type_bracketed_sockaddrnameportlist = {
+       "bracketed_sockaddrnameportlist", cfg_parse_bracketed_list,
        cfg_print_bracketed_list, cfg_doc_bracketed_list,
-       &cfg_rep_list, &cfg_type_namesockaddr
+       &cfg_rep_list, &cfg_type_sockaddrnameport
 };
 
 /*
- * A list of socket addresses or named with an optional default port,
+ * A list of socket addresses or name with an optional default port,
  * as used in the dual-stack-servers option.  E.g.,
  * "port 1234 { dual-stack-servers.net; 10.0.0.1; 1::2 port 69; }"
  */
 static cfg_tuplefielddef_t nameportiplist_fields[] = {
        { "port", &cfg_type_optional_port, 0 },
-       { "addresses", &cfg_type_bracketed_namesockaddrlist, 0 },
+       { "addresses", &cfg_type_bracketed_sockaddrnameportlist, 0 },
        { NULL, NULL, 0 }
 };
 
@@ -1753,3 +1764,53 @@ static cfg_type_t cfg_type_nameportiplist = {
        "nameportiplist", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
        &cfg_rep_tuple, nameportiplist_fields
 };
+
+/*
+ * masters element.
+ */
+
+static void
+doc_masterselement(cfg_printer_t *pctx, const cfg_type_t *type) {
+       UNUSED(type);
+       cfg_print_chars(pctx, "( ", 2);
+       cfg_print_cstr(pctx, "<masters>");
+       cfg_print_chars(pctx, " | ", 3);
+       cfg_print_cstr(pctx, "<ipv4_address>");
+       cfg_print_chars(pctx, " ", 1);
+       cfg_print_cstr(pctx, "[port <integer>]");
+       cfg_print_chars(pctx, " | ", 3);
+       cfg_print_cstr(pctx, "<ipv6_address>");
+       cfg_print_chars(pctx, " ", 1);
+       cfg_print_cstr(pctx, "[port <integer>]");
+       cfg_print_chars(pctx, " )", 2);
+}
+
+static isc_result_t
+parse_masterselement(cfg_parser_t *pctx, const cfg_type_t *type,
+                    cfg_obj_t **ret)
+{
+        isc_result_t result;
+       cfg_obj_t *obj = NULL;
+       UNUSED(type);
+
+       CHECK(cfg_peektoken(pctx, CFG_LEXOPT_QSTRING));
+       if (pctx->token.type == isc_tokentype_string ||
+           pctx->token.type == isc_tokentype_qstring) {
+               if (cfg_lookingat_netaddr(pctx, CFG_ADDR_V4OK | CFG_ADDR_V6OK))
+                       CHECK(cfg_parse_sockaddr(pctx, &cfg_type_sockaddr, ret));
+               else
+                       CHECK(cfg_parse_astring(pctx, &cfg_type_astring, ret));
+       } else {
+               cfg_parser_error(pctx, CFG_LOG_NEAR,
+                            "expected IP address or masters name");
+               return (ISC_R_UNEXPECTEDTOKEN);
+       }
+ cleanup:
+       CLEANUP_OBJ(obj);       
+       return (result);
+}
+
+static cfg_type_t cfg_type_masterselement = {
+       "masters_element", parse_masterselement, NULL,
+        doc_masterselement, NULL, NULL
+};