* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: sortlist.c,v 1.16 2007/09/12 01:09:07 each Exp $ */
+/* $Id: sortlist.c,v 1.17 2007/09/14 01:46:05 marka Exp $ */
/*! \file */
if (e->type == dns_aclelementtype_nestedacl) {
dns_acl_t *inner = e->nestedacl;
- if (inner->length < 1 || inner->length > 2)
+ if (inner->length == 0)
+ try_elt = e;
+ else if (inner->length > 2)
goto dont_sort;
- if (inner->elements[0].negative)
+ else if (inner->elements[0].negative)
goto dont_sort;
- try_elt = &inner->elements[0];
- if (inner->length == 2)
- order_elt = &inner->elements[1];
+ else {
+ try_elt = &inner->elements[0];
+ if (inner->length == 2)
+ order_elt = &inner->elements[1];
+ }
} else {
/*
* BIND 8 allows bare elements at the top level
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
-# $Id: tests.sh,v 1.8 2007/06/19 23:47:05 tbox Exp $
+# $Id: tests.sh,v 1.9 2007/09/14 01:46:05 marka Exp $
SYSTEMTESTTOP=..
. $SYSTEMTESTTOP/conf.sh
diff test1.dig test1.good || status=1
echo "I:test 1-element sortlist statement and undocumented BIND 8 features"
-for n in 2 3 4 5
-do
cat <<EOF >test2.good
b.example. 300 IN A 10.53.0.$n
EOF
- $DIG +tcp +noadd +nosea +nostat +noquest +noauth +nocomm +nocmd \
- b.example. \
- @10.53.0.1 -b 10.53.0.$n -p 5300 | sed 1q >test2.dig
- diff test2.dig test2.good || status=1
-done
+
+$DIG +tcp +noadd +nosea +nostat +noquest +noauth +nocomm +nocmd \
+ b.example. @10.53.0.1 -b 10.53.0.2 -p 5300 | sed 1q | \
+ egrep '10.53.0.(2|3)$' > test2.out &&
+$DIG +tcp +noadd +nosea +nostat +noquest +noauth +nocomm +nocmd \
+ b.example. @10.53.0.1 -b 10.53.0.3 -p 5300 | sed 1q | \
+ egrep '10.53.0.(2|3)$' >> test2.out &&
+$DIG +tcp +noadd +nosea +nostat +noquest +noauth +nocomm +nocmd \
+ b.example. @10.53.0.1 -b 10.53.0.4 -p 5300 | sed 1q | \
+ egrep '10.53.0.4$' >> test2.out &&
+$DIG +tcp +noadd +nosea +nostat +noquest +noauth +nocomm +nocmd \
+ b.example. @10.53.0.1 -b 10.53.0.5 -p 5300 | sed 1q | \
+ egrep '10.53.0.5$' >> test2.out || status=1
echo "I:exit status: $status"
exit $status
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: acl.c,v 1.33 2007/09/12 01:09:08 each Exp $ */
+/* $Id: acl.c,v 1.34 2007/09/14 01:46:05 marka Exp $ */
/*! \file */
isc_result_t
dns_acl_merge(dns_acl_t *dest, dns_acl_t *source, isc_boolean_t pos)
{
+ isc_result_t result;
unsigned int newalloc, nelem, i;
int max_node = 0, nodes;
* node_count value is set correctly afterward.
*/
nodes = max_node + dest->node_count;
- dns_iptable_merge(dest->iptable, source->iptable, pos);
+ result = dns_iptable_merge(dest->iptable, source->iptable, pos);
+ if (result != ISC_R_SUCCESS)
+ return (result);
if (nodes > dest->node_count)
dest->node_count = nodes;
dns_aclelement_t *de = &dacl->elements[i];
if (de->type == dns_aclelementtype_keyname) {
dns_name_free(&de->keyname, dacl->mctx);
+ } else if (de->type == dns_aclelementtype_nestedacl) {
+ dns_acl_detach(&de->nestedacl);
}
}
if (dacl->elements != NULL)
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: iptable.h,v 1.3 2007/09/12 23:46:47 tbox Exp $ */
+/* $Id: iptable.h,v 1.4 2007/09/14 01:46:05 marka Exp $ */
#ifndef DNS_IPTABLE_H
#define DNS_IPTABLE_H 1
* Add an IP prefix to an existing IP table
*/
-void
+isc_result_t
dns_iptable_merge(dns_iptable_t *tab, dns_iptable_t *source, isc_boolean_t pos);
/*
* Merge one IP table into another one.
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: iptable.c,v 1.3 2007/09/12 23:46:47 tbox Exp $ */
+/* $Id: iptable.c,v 1.4 2007/09/14 01:46:05 marka Exp $ */
#include <isc/mem.h>
#include <isc/radix.h>
INSIST(DNS_IPTABLE_VALID(tab));
INSIST(tab->radix);
-
NETADDR_TO_PREFIX_T(addr, pfx, bitlen);
result = isc_radix_insert(tab->radix, &node, NULL, &pfx);
/*
* Merge one IP table into another one.
*/
-void
+isc_result_t
dns_iptable_merge(dns_iptable_t *tab, dns_iptable_t *source, isc_boolean_t pos)
{
+ isc_result_t result;
isc_radix_node_t *node, *new_node;
int max_node = 0;
RADIX_WALK (source->radix->head, node) {
- isc_radix_insert (tab->radix, &new_node, node, NULL);
+ result = isc_radix_insert (tab->radix, &new_node, node, NULL);
+
+ if (result != ISC_R_SUCCESS)
+ return(result);
/*
* If we're negating a nested ACL, then we should
* becoming a positive match in the parent, which
* could be a security risk. To prevent this, we
* just leave the negative nodes negative.
- * (XXX: does this still need to be documented?)
*/
if (!pos &&
node->data &&
} RADIX_WALK_END;
tab->radix->num_added_node += max_node;
+ return (ISC_R_SUCCESS);
}
void
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: radix.c,v 1.3 2007/09/12 23:46:47 tbox Exp $ */
+/* $Id: radix.c,v 1.4 2007/09/14 01:46:05 marka Exp $ */
/*
* This source was adapted from MRT's RCS Ids:
{
isc_prefix_t *prefix;
+ REQUIRE(target != NULL);
+
if (family != AF_INET6 && family != AF_INET)
return (ISC_R_NOTIMPLEMENTED);
static void
_deref_prefix(isc_mem_t *mctx, isc_prefix_t *prefix) {
- size_t size;
int refs;
if (prefix == NULL)
if (refs <= 0) {
isc_refcount_destroy(&prefix->refcount);
-
- if (prefix->family == AF_INET6)
- size = sizeof(isc_prefix_t);
- else
- size = sizeof(isc_prefix_t);
-
- isc_mem_put(mctx, prefix, size);
+ isc_mem_put(mctx, prefix, sizeof(isc_prefix_t));
}
}
static isc_result_t
_ref_prefix(isc_mem_t *mctx, isc_prefix_t **target, isc_prefix_t *prefix) {
-
- INSIST((prefix->family == AF_INET && prefix->bitlen <= 32) ||
- (prefix->family == AF_INET6 && prefix->bitlen <= 128));
-
- if (prefix != NULL) {
- if (isc_refcount_current(&prefix->refcount) == 0) {
- /* Make a copy in case of a static prefix. */
- return (_new_prefix(mctx, target, prefix->family,
- &prefix->add, prefix->bitlen));
- }
-
- isc_refcount_increment(&prefix->refcount, NULL);
+ INSIST(prefix != NULL);
+ INSIST((prefix->family == AF_INET && prefix->bitlen <= 32) ||
+ (prefix->family == AF_INET6 && prefix->bitlen <= 128));
+ REQUIRE(target != NULL);
+
+ /* If this prefix is a static allocation, copy it into new memory */
+ if (isc_refcount_current(&prefix->refcount) == 0) {
+ isc_result_t ret;
+ ret = _new_prefix(mctx, target, prefix->family,
+ &prefix->add, prefix->bitlen);
+ if (ret == ISC_R_SUCCESS)
+ isc_refcount_destroy(&prefix->refcount);
+ return ret;
}
+ isc_refcount_increment(&prefix->refcount, NULL);
+
*target = prefix;
return (ISC_R_SUCCESS);
}
isc_radix_create(isc_mem_t *mctx, isc_radix_tree_t **target, int maxbits) {
isc_radix_tree_t *radix;
+ REQUIRE(target != NULL);
+
radix = isc_mem_get(mctx, sizeof(isc_radix_tree_t));
if (radix == NULL)
return (ISC_R_NOMEMORY);
radix->num_added_node = 0;
RUNTIME_CHECK(maxbits <= RADIX_MAXBITS); /* XXX */
radix->magic = RADIX_TREE_MAGIC;
-
*target = radix;
return (ISC_R_SUCCESS);
}
void
isc_destroy_radix(isc_radix_tree_t *radix, void_fn_t func)
{
+ REQUIRE(radix != NULL);
_clear_radix(radix, func);
isc_mem_put(radix->mctx, radix, sizeof(*radix));
}
if (_comp_with_mask(isc_prefix_tochar(node->prefix),
isc_prefix_tochar(prefix),
node->prefix->bitlen)) {
- if ((*target == NULL) ||
- (*target)->node_num > node->node_num)
- *target = node;
+ if ((*target == NULL) ||
+ (*target)->node_num > node->node_num)
+ *target = node;
}
}
REQUIRE(prefix || (source && source->prefix));
RUNTIME_CHECK(prefix->bitlen <= radix->maxbits);
- if (!prefix && source && source->prefix)
- prefix = source->prefix;
+ if (!prefix && source && source->prefix)
+ prefix = source->prefix;
if (radix->head == NULL) {
node = isc_mem_get(radix->mctx, sizeof(isc_radix_node_t));
new_node->l = new_node->r = NULL;
radix->num_active_node++;
- if (source) {
- /*
- * If source is non-NULL, then we're merging in a node
- * from an existing radix tree. Node_num values have to
- * remain consistent; they can't just be added in whatever
- * order came from walking the tree. So we don't increment
- * num_added_node here; instead, we add it to the node-num
- * values for each node from the nested tree, and then when
- * the whole tree is done, the calling function will bump
- * num_added_node by the highest value of node_num in the
- * tree.
- */
- new_node->node_num = radix->num_added_node + source->node_num;
- new_node->data = source->data;
- } else {
- new_node->node_num = ++radix->num_added_node;
- new_node->data = NULL;
- }
+ if (source) {
+ /*
+ * If source is non-NULL, then we're merging in a node
+ * from an existing radix tree. Node_num values have to
+ * remain consistent; they can't just be added in whatever
+ * order came from walking the tree. So we don't increment
+ * num_added_node here; instead, we add it to the node-num
+ * values for each node from the nested tree, and then when
+ * the whole tree is done, the calling function will bump
+ * num_added_node by the highest value of node_num in the
+ * tree.
+ */
+ new_node->node_num = radix->num_added_node + source->node_num;
+ new_node->data = source->data;
+ } else {
+ new_node->node_num = ++radix->num_added_node;
+ new_node->data = NULL;
+ }
if (node->bit == differ_bit) {
INSIST(glue == NULL);
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: aclconf.c,v 1.10 2007/09/12 01:09:08 each Exp $ */
+/* $Id: aclconf.c,v 1.11 2007/09/14 01:46:05 marka Exp $ */
#include <config.h>
void
cfg_aclconfctx_destroy(cfg_aclconfctx_t *ctx) {
- dns_acl_t *dacl, *next;
+ dns_acl_t *dacl, *next;
for (dacl = ISC_LIST_HEAD(ctx->named_acl_cache);
dacl != NULL;
convert_named_acl(const cfg_obj_t *nameobj, const cfg_obj_t *cctx,
isc_log_t *lctx, cfg_aclconfctx_t *ctx,
isc_mem_t *mctx, int nest_level,
- dns_acl_t **target)
+ dns_acl_t **target)
{
isc_result_t result;
const cfg_obj_t *cacl = NULL;
loop.magic = LOOP_MAGIC;
ISC_LIST_APPEND(ctx->named_acl_cache, &loop, nextincache);
result = cfg_acl_fromconfig(cacl, cctx, lctx, ctx, mctx,
- nest_level, &dacl);
+ nest_level, &dacl);
ISC_LIST_UNLINK(ctx->named_acl_cache, &loop, nextincache);
loop.magic = 0;
loop.name = NULL;
isc_result_t
cfg_acl_fromconfig(const cfg_obj_t *caml,
const cfg_obj_t *cctx,
- isc_log_t *lctx,
+ isc_log_t *lctx,
cfg_aclconfctx_t *ctx,
isc_mem_t *mctx,
- int nest_level,
+ int nest_level,
dns_acl_t **target)
{
isc_result_t result;
dns_acl_t *dacl = NULL, *inneracl = NULL;
dns_aclelement_t *de;
const cfg_listelt_t *elt;
- dns_iptable_t *iptab;
+ dns_iptable_t *iptab;
REQUIRE(target != NULL);
- REQUIRE(*target == NULL || ISC_MAGIC_VALID(target, DNS_ACL_MAGIC));
+ REQUIRE(*target == NULL || DNS_ACL_VALID(*target));
- if (*target != NULL) {
- /*
- * If target already points to an ACL, then we're being
- * called recursively to configure a nested ACL. The
- * nested ACL's contents should just be absorbed into its
- * parent ACL.
- */
- dacl = *target;
- } 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).
- */
- unsigned int element_count = 0;
- for (elt = cfg_list_first(caml);
- elt != NULL;
- elt = cfg_list_next(elt)) {
- const cfg_obj_t *ce = cfg_listelt_value(elt);
- if (cfg_obj_istuple(ce))
- ce = cfg_tuple_get(ce, "value");
- if (cfg_obj_isnetprefix(ce))
- element_count++;
- }
- result = dns_acl_create(mctx, element_count, &dacl);
- if (result != ISC_R_SUCCESS)
- return (result);
- }
+ if (*target != NULL) {
+ /*
+ * If target already points to an ACL, then we're being
+ * called recursively to configure a nested ACL. The
+ * nested ACL's contents should just be absorbed into its
+ * parent ACL.
+ */
+ dacl = *target;
+ } 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).
+ */
+ result = dns_acl_create(mctx, cfg_list_length(caml), &dacl);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
de = dacl->elements;
for (elt = cfg_list_first(caml);
} else
neg = ISC_FALSE;
- /*
- * If nest_level is nonzero, then every element is
- * to be stored as a separate, nested ACL rather than
- * merged into the main iptable.
- */
- iptab = dacl->iptable;
- if (nest_level) {
- result = dns_acl_create(mctx, 0, &de->nestedacl);
- if (result != ISC_R_SUCCESS)
- goto cleanup;
- iptab = de->nestedacl->iptable;
- }
+ /*
+ * If nest_level is nonzero, then every element is
+ * to be stored as a separate, nested ACL rather than
+ * merged into the main iptable.
+ */
+ iptab = dacl->iptable;
+ if (nest_level > 0) {
+ result = dns_acl_create(mctx, cfg_list_length(ce),
+ &de->nestedacl);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ iptab = de->nestedacl->iptable;
+ }
if (cfg_obj_isnetprefix(ce)) {
/* Network prefix */
- isc_netaddr_t addr;
- unsigned int bitlen;
+ isc_netaddr_t addr;
+ unsigned int bitlen;
- cfg_obj_asnetprefix(ce, &addr, &bitlen);
- result = dns_iptable_addprefix(iptab, &addr, bitlen,
- ISC_TF(!neg));
+ cfg_obj_asnetprefix(ce, &addr, &bitlen);
+ result = dns_iptable_addprefix(iptab, &addr, bitlen,
+ ISC_TF(!neg));
if (result != ISC_R_SUCCESS)
goto cleanup;
- continue;
+
+ if (nest_level > 0) {
+ /* This prefix is going into a nested acl */
+ de->type = dns_aclelementtype_nestedacl;
+ de->negative = neg;
+ } else
+ continue;
} else if (cfg_obj_islist(ce)) {
- /*
- * If we're nesting ACLs, put the nested
- * ACL onto the elements list; otherwise
- * merge it into *this* ACL.
- */
- if (nest_level == 0) {
- result = cfg_acl_fromconfig(ce,
- cctx, lctx, ctx, mctx, 0,
- &dacl);
- } else {
+ /*
+ * If we're nesting ACLs, put the nested
+ * ACL onto the elements list; otherwise
+ * merge it into *this* ACL.
+ */
+ if (nest_level == 0) {
+ result = cfg_acl_fromconfig(ce,
+ cctx, lctx, ctx, mctx, 0,
+ &dacl);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ continue;
+ } else {
de->type = dns_aclelementtype_nestedacl;
- de->negative = neg;
- result = cfg_acl_fromconfig(ce,
- cctx, lctx, ctx, mctx,
- nest_level - 1,
- &de->nestedacl);
- }
+ de->negative = neg;
+ result = cfg_acl_fromconfig(ce,
+ cctx, lctx, ctx, mctx,
+ nest_level - 1,
+ &de->nestedacl);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ /* Fall through */
+ }
+ } else if (cfg_obj_istype(ce, &cfg_type_keyref)) {
+ /* Key name */
+ de->type = dns_aclelementtype_keyname;
+ de->negative = neg;
+ dns_name_init(&de->keyname, NULL);
+ result = convert_keyname(ce, lctx, mctx,
+ &de->keyname);
if (result != ISC_R_SUCCESS)
- goto cleanup;
- continue;
+ goto cleanup;
} else if (cfg_obj_isstring(ce)) {
/* ACL name */
const char *name = cfg_obj_asstring(ce);
- if (strcasecmp(name, "any") == 0) {
- /* iptable entry with zero bit length */
- dns_iptable_addprefix(iptab, NULL, 0,
- ISC_TRUE);
- continue;
+ if (strcasecmp(name, "any") == 0) {
+ /* iptable entry with zero bit length */
+ dns_iptable_addprefix(iptab, NULL, 0,
+ ISC_TRUE);
+ continue;
} else if (strcasecmp(name, "none") == 0) {
- /* negated "any" */
- dns_iptable_addprefix(iptab, NULL, 0,
- ISC_FALSE);
- continue;
+ /* negated "any" */
+ dns_iptable_addprefix(iptab, NULL, 0,
+ ISC_FALSE);
+ continue;
} else if (strcasecmp(name, "localhost") == 0) {
de->type = dns_aclelementtype_localhost;
- de->negative = neg;
+ de->negative = neg;
} else if (strcasecmp(name, "localnets") == 0) {
de->type = dns_aclelementtype_localnets;
- de->negative = neg;
+ de->negative = neg;
} else {
result = get_acl_def(cctx, name, NULL);
if (result == ISC_R_SUCCESS) {
/* found it in acl definitions */
- inneracl = NULL;
+ inneracl = NULL;
result = convert_named_acl(ce, cctx,
lctx, ctx, mctx,
- nest_level
- ? (nest_level - 1)
- : 0,
- &inneracl);
+ (nest_level > 0)
+ ? (nest_level - 1)
+ : 0,
+ &inneracl);
}
if (result != ISC_R_SUCCESS)
goto cleanup;
- if (nest_level) {
- de->type = dns_aclelementtype_nestedacl,
- de->negative = neg;
- de->nestedacl = inneracl;
- } else {
- dns_acl_merge(dacl, inneracl,
- ISC_TF(!neg));
- dns_acl_detach(&inneracl);
- }
- continue;
+ if (nest_level) {
+ de->type = dns_aclelementtype_nestedacl,
+ de->negative = neg;
+ de->nestedacl = inneracl;
+ } else {
+ dns_acl_merge(dacl, inneracl,
+ ISC_TF(!neg));
+ dns_acl_detach(&inneracl);
+ }
+ continue;
}
- } else if (cfg_obj_istype(ce, &cfg_type_keyref)) {
- /* Key name */
- de->type = dns_aclelementtype_keyname;
- de->negative = neg;
- dns_name_init(&de->keyname, NULL);
- result = convert_keyname(ce, lctx, mctx,
- &de->keyname);
- if (result != ISC_R_SUCCESS)
- goto cleanup;
} else {
cfg_obj_log(ce, lctx, ISC_LOG_WARNING,
"address match list contains "
goto cleanup;
}
- /*
- * XXX each: This should only be reached for localhost,
- * localnets and keyname elements -- probably should
- * be refactored for clearer flow
- */
- if (nest_level && de->type != dns_aclelementtype_nestedacl)
- dns_acl_detach(&de->nestedacl);
+ /*
+ * This should only be reached for localhost, localnets
+ * and keyname elements, and nested ACLs if nest_level is
+ * nonzero (i.e., in sortlists).
+ */
+ if (nest_level > 0 && de->type != dns_aclelementtype_nestedacl)
+ dns_acl_detach(&de->nestedacl);
+
+ dacl->node_count++;
+ de->node_num = dacl->node_count;
- de->node_num = dacl->node_count++;
de++;
dacl->length++;
+ INSIST(dacl->length <= dacl->alloc);
}
*target = dacl;
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: cfg.h,v 1.42 2007/06/19 23:47:22 tbox Exp $ */
+/* $Id: cfg.h,v 1.43 2007/09/14 01:46:06 marka Exp $ */
#ifndef ISCCFG_CFG_H
#define ISCCFG_CFG_H 1
* or NULL if there are no more elements.
*/
+unsigned int
+cfg_list_length(const cfg_obj_t *obj);
+/*%<
+ * Returns the length of a list of configure objects. If obj is
+ * not a list, returns 0.
+ */
+
const cfg_obj_t *
cfg_listelt_value(const cfg_listelt_t *elt);
/*%<
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: parser.c,v 1.125 2007/06/19 23:47:22 tbox Exp $ */
+/* $Id: parser.c,v 1.126 2007/09/14 01:46:05 marka Exp $ */
/*! \file */
return (ISC_LIST_NEXT(elt, link));
}
+/*
+ * Return the length of a list object. If obj is NULL or is not
+ * a list, return 0.
+ */
+unsigned int
+cfg_list_length(const cfg_obj_t *obj) {
+ const cfg_listelt_t *elt;
+ unsigned int count = 0;
+
+ if (obj == NULL || ! cfg_obj_islist(obj))
+ return (0U);
+ for (elt = cfg_list_first(obj);
+ elt != NULL;
+ elt = cfg_list_next(elt)) {
+ count++;
+ }
+ return (count);
+}
+
const cfg_obj_t *
cfg_listelt_value(const cfg_listelt_t *elt) {
REQUIRE(elt != NULL);