* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: aclconf.c,v 1.21 2008/09/01 05:36:00 marka Exp $ */
+/* $Id: aclconf.c,v 1.22 2008/10/24 02:28:55 each Exp $ */
#include <config.h>
return (dns_name_dup(dns_fixedname_name(&fixname), mctx, dnsname));
}
+/*
+ * Recursively pre-parse an ACL definition to find the total number
+ * of non-IP-prefix elements (localhost, localnets, key) in all nested
+ * ACLs, so that the parent will have enough space allocated for the
+ * elements table after all the nested ACLs have been merged in to the
+ * parent.
+ */
+static int
+count_acl_elements(const cfg_obj_t *caml, const cfg_obj_t *cctx)
+{
+ const cfg_listelt_t *elt;
+ const cfg_obj_t *cacl = NULL;
+ isc_result_t result;
+ int n = 0;
+
+ for (elt = cfg_list_first(caml);
+ elt != NULL;
+ elt = cfg_list_next(elt)) {
+ const cfg_obj_t *ce = cfg_listelt_value(elt);
+
+ /* negated element; just get the value. */
+ if (cfg_obj_istuple(ce))
+ ce = cfg_tuple_get(ce, "value");
+
+ if (cfg_obj_istype(ce, &cfg_type_keyref)) {
+ n++;
+ } else if (cfg_obj_islist(ce)) {
+ n += count_acl_elements(ce, cctx);
+ } else if (cfg_obj_isstring(ce)) {
+ const char *name = cfg_obj_asstring(ce);
+ if (strcasecmp(name, "localhost") == 0 ||
+ strcasecmp(name, "localnets") == 0) {
+ n++;
+ } else if (strcasecmp(name, "any") != 0 &&
+ strcasecmp(name, "none") != 0) {
+ result = get_acl_def(cctx, name, &cacl);
+ if (result == ISC_R_SUCCESS)
+ n += count_acl_elements(cacl, cctx) + 1;
+ }
+ }
+ }
+
+ return n;
+}
+
isc_result_t
cfg_acl_fromconfig(const cfg_obj_t *caml,
const cfg_obj_t *cctx,
} else {
/*
* Need to allocate a new ACL structure. Count the items
- * in the ACL definition and allocate space for that many
- * elements (even though some or all of them may end up in
- * the iptable instead of the element array).
+ * in the ACL definition that will require space in the
+ * elemnts table. (Note that if nest_level is nonzero,
+ * *everything* goes in the elements table.)
*/
- isc_boolean_t recurse = ISC_TF(nest_level == 0);
- result = dns_acl_create(mctx,
- cfg_list_length(caml, recurse),
- &dacl);
+ int nelem;
+
+ if (nest_level == 0)
+ nelem = count_acl_elements(caml, cctx);
+ else
+ nelem = cfg_list_length(caml, ISC_FALSE);
+
+ result = dns_acl_create(mctx, nelem, &dacl);
if (result != ISC_R_SUCCESS)
return (result);
}
de = dacl->elements;
for (elt = cfg_list_first(caml);
elt != NULL;
- elt = cfg_list_next(elt))
- {
+ elt = cfg_list_next(elt)) {
const cfg_obj_t *ce = cfg_listelt_value(elt);
isc_boolean_t neg;