static isc_result_t 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, unsigned int nest_level, dns_acl_t **target) { isc_result_t result; const cfg_obj_t *cacl = NULL; dns_acl_t *dacl; dns_acl_t loop; const char *aclname = cfg_obj_asstring(nameobj); /* Look for an already-converted version. */ for (dacl = ISC_LIST_HEAD(ctx->named_acl_cache); dacl != NULL; dacl = ISC_LIST_NEXT(dacl, nextincache)) { if (strcasecmp(aclname, dacl->name) == 0) { if (ISC_MAGIC_VALID(dacl, LOOP_MAGIC)) { cfg_obj_log(nameobj, lctx, ISC_LOG_ERROR, "acl loop detected: %s", aclname); return (ISC_R_FAILURE); } dns_acl_attach(dacl, target); return (ISC_R_SUCCESS); } } /* Not yet converted. Convert now. */ result = get_acl_def(cctx, aclname, &cacl); if (result != ISC_R_SUCCESS) { cfg_obj_log(nameobj, lctx, ISC_LOG_WARNING, "undefined ACL '%s'", aclname); return (result); } /* * Add a loop detection element. */ memset(&loop, 0, sizeof(loop)); ISC_LINK_INIT(&loop, nextincache); DE_CONST(aclname, loop.name); 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); ISC_LIST_UNLINK(ctx->named_acl_cache, &loop, nextincache); loop.magic = 0; loop.name = NULL; if (result != ISC_R_SUCCESS) return (result); dacl->name = isc_mem_strdup(dacl->mctx, aclname); if (dacl->name == NULL) return (ISC_R_NOMEMORY); ISC_LIST_APPEND(ctx->named_acl_cache, dacl, nextincache); dns_acl_attach(dacl, target); return (ISC_R_SUCCESS); }
/* * 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, isc_boolean_t *has_negative) { const cfg_listelt_t *elt; const cfg_obj_t *cacl = NULL; isc_result_t result; int n = 0; if (has_negative != NULL) *has_negative = ISC_FALSE; 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 (has_negative != NULL) *has_negative = ISC_TRUE; } if (cfg_obj_istype(ce, &cfg_type_keyref)) { n++; } else if (cfg_obj_islist(ce)) { isc_boolean_t negative; n += count_acl_elements(ce, cctx, &negative); if (negative) n++; } else if (cfg_obj_isstring(ce)) { const char *name = cfg_obj_asstring(ce); if (strcasecmp(name, "localhost") == 0 || #ifdef SUPPORT_GEOIP strncasecmp(name, "country_", 8) == 0 || #endif 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, NULL) + 1; } } } return n; }