xref: /minix3/external/bsd/bind/dist/lib/isccfg/aclconf.c (revision 00b67f09dd46474d133c95011a48590a8e8f94c7)
1*00b67f09SDavid van Moolenbroek /*	$NetBSD: aclconf.c,v 1.8 2014/12/10 04:38:02 christos Exp $	*/
2*00b67f09SDavid van Moolenbroek 
3*00b67f09SDavid van Moolenbroek /*
4*00b67f09SDavid van Moolenbroek  * Copyright (C) 2004-2014  Internet Systems Consortium, Inc. ("ISC")
5*00b67f09SDavid van Moolenbroek  * Copyright (C) 1999-2002  Internet Software Consortium.
6*00b67f09SDavid van Moolenbroek  *
7*00b67f09SDavid van Moolenbroek  * Permission to use, copy, modify, and/or distribute this software for any
8*00b67f09SDavid van Moolenbroek  * purpose with or without fee is hereby granted, provided that the above
9*00b67f09SDavid van Moolenbroek  * copyright notice and this permission notice appear in all copies.
10*00b67f09SDavid van Moolenbroek  *
11*00b67f09SDavid van Moolenbroek  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12*00b67f09SDavid van Moolenbroek  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13*00b67f09SDavid van Moolenbroek  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14*00b67f09SDavid van Moolenbroek  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15*00b67f09SDavid van Moolenbroek  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16*00b67f09SDavid van Moolenbroek  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17*00b67f09SDavid van Moolenbroek  * PERFORMANCE OF THIS SOFTWARE.
18*00b67f09SDavid van Moolenbroek  */
19*00b67f09SDavid van Moolenbroek 
20*00b67f09SDavid van Moolenbroek /* Id */
21*00b67f09SDavid van Moolenbroek 
22*00b67f09SDavid van Moolenbroek #include <config.h>
23*00b67f09SDavid van Moolenbroek 
24*00b67f09SDavid van Moolenbroek #include <isc/mem.h>
25*00b67f09SDavid van Moolenbroek #include <isc/string.h>		/* Required for HP/UX (and others?) */
26*00b67f09SDavid van Moolenbroek #include <isc/util.h>
27*00b67f09SDavid van Moolenbroek 
28*00b67f09SDavid van Moolenbroek #include <isccfg/namedconf.h>
29*00b67f09SDavid van Moolenbroek #include <isccfg/aclconf.h>
30*00b67f09SDavid van Moolenbroek 
31*00b67f09SDavid van Moolenbroek #include <dns/acl.h>
32*00b67f09SDavid van Moolenbroek #include <dns/iptable.h>
33*00b67f09SDavid van Moolenbroek #include <dns/fixedname.h>
34*00b67f09SDavid van Moolenbroek #include <dns/log.h>
35*00b67f09SDavid van Moolenbroek 
36*00b67f09SDavid van Moolenbroek #ifdef HAVE_GEOIP
37*00b67f09SDavid van Moolenbroek #include <stdlib.h>
38*00b67f09SDavid van Moolenbroek #include <math.h>
39*00b67f09SDavid van Moolenbroek #endif /* HAVE_GEOIP */
40*00b67f09SDavid van Moolenbroek 
41*00b67f09SDavid van Moolenbroek #define LOOP_MAGIC ISC_MAGIC('L','O','O','P')
42*00b67f09SDavid van Moolenbroek 
43*00b67f09SDavid van Moolenbroek isc_result_t
cfg_aclconfctx_create(isc_mem_t * mctx,cfg_aclconfctx_t ** ret)44*00b67f09SDavid van Moolenbroek cfg_aclconfctx_create(isc_mem_t *mctx, cfg_aclconfctx_t **ret) {
45*00b67f09SDavid van Moolenbroek 	isc_result_t result;
46*00b67f09SDavid van Moolenbroek 	cfg_aclconfctx_t *actx;
47*00b67f09SDavid van Moolenbroek 
48*00b67f09SDavid van Moolenbroek 	REQUIRE(mctx != NULL);
49*00b67f09SDavid van Moolenbroek 	REQUIRE(ret != NULL && *ret == NULL);
50*00b67f09SDavid van Moolenbroek 
51*00b67f09SDavid van Moolenbroek 	actx = isc_mem_get(mctx, sizeof(*actx));
52*00b67f09SDavid van Moolenbroek 	if (actx == NULL)
53*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOMEMORY);
54*00b67f09SDavid van Moolenbroek 
55*00b67f09SDavid van Moolenbroek 	result = isc_refcount_init(&actx->references, 1);
56*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
57*00b67f09SDavid van Moolenbroek 		goto cleanup;
58*00b67f09SDavid van Moolenbroek 
59*00b67f09SDavid van Moolenbroek 	actx->mctx = NULL;
60*00b67f09SDavid van Moolenbroek 	isc_mem_attach(mctx, &actx->mctx);
61*00b67f09SDavid van Moolenbroek 	ISC_LIST_INIT(actx->named_acl_cache);
62*00b67f09SDavid van Moolenbroek 
63*00b67f09SDavid van Moolenbroek #ifdef HAVE_GEOIP
64*00b67f09SDavid van Moolenbroek 	actx->geoip = NULL;
65*00b67f09SDavid van Moolenbroek #endif
66*00b67f09SDavid van Moolenbroek 
67*00b67f09SDavid van Moolenbroek 	*ret = actx;
68*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
69*00b67f09SDavid van Moolenbroek 
70*00b67f09SDavid van Moolenbroek  cleanup:
71*00b67f09SDavid van Moolenbroek 	isc_mem_put(mctx, actx, sizeof(*actx));
72*00b67f09SDavid van Moolenbroek 	return (result);
73*00b67f09SDavid van Moolenbroek }
74*00b67f09SDavid van Moolenbroek 
75*00b67f09SDavid van Moolenbroek void
cfg_aclconfctx_attach(cfg_aclconfctx_t * src,cfg_aclconfctx_t ** dest)76*00b67f09SDavid van Moolenbroek cfg_aclconfctx_attach(cfg_aclconfctx_t *src, cfg_aclconfctx_t **dest) {
77*00b67f09SDavid van Moolenbroek 	REQUIRE(src != NULL);
78*00b67f09SDavid van Moolenbroek 	REQUIRE(dest != NULL && *dest == NULL);
79*00b67f09SDavid van Moolenbroek 
80*00b67f09SDavid van Moolenbroek 	isc_refcount_increment(&src->references, NULL);
81*00b67f09SDavid van Moolenbroek 	*dest = src;
82*00b67f09SDavid van Moolenbroek }
83*00b67f09SDavid van Moolenbroek 
84*00b67f09SDavid van Moolenbroek void
cfg_aclconfctx_detach(cfg_aclconfctx_t ** actxp)85*00b67f09SDavid van Moolenbroek cfg_aclconfctx_detach(cfg_aclconfctx_t **actxp) {
86*00b67f09SDavid van Moolenbroek 	cfg_aclconfctx_t *actx;
87*00b67f09SDavid van Moolenbroek 	dns_acl_t *dacl, *next;
88*00b67f09SDavid van Moolenbroek 	unsigned int refs;
89*00b67f09SDavid van Moolenbroek 
90*00b67f09SDavid van Moolenbroek 	REQUIRE(actxp != NULL && *actxp != NULL);
91*00b67f09SDavid van Moolenbroek 
92*00b67f09SDavid van Moolenbroek 	actx = *actxp;
93*00b67f09SDavid van Moolenbroek 
94*00b67f09SDavid van Moolenbroek 	isc_refcount_decrement(&actx->references, &refs);
95*00b67f09SDavid van Moolenbroek 	if (refs == 0) {
96*00b67f09SDavid van Moolenbroek 		for (dacl = ISC_LIST_HEAD(actx->named_acl_cache);
97*00b67f09SDavid van Moolenbroek 		     dacl != NULL;
98*00b67f09SDavid van Moolenbroek 		     dacl = next)
99*00b67f09SDavid van Moolenbroek 		{
100*00b67f09SDavid van Moolenbroek 			next = ISC_LIST_NEXT(dacl, nextincache);
101*00b67f09SDavid van Moolenbroek 			ISC_LIST_UNLINK(actx->named_acl_cache, dacl,
102*00b67f09SDavid van Moolenbroek 					nextincache);
103*00b67f09SDavid van Moolenbroek 			dns_acl_detach(&dacl);
104*00b67f09SDavid van Moolenbroek 		}
105*00b67f09SDavid van Moolenbroek 		isc_mem_putanddetach(&actx->mctx, actx, sizeof(*actx));
106*00b67f09SDavid van Moolenbroek 	}
107*00b67f09SDavid van Moolenbroek 
108*00b67f09SDavid van Moolenbroek 	*actxp = NULL;
109*00b67f09SDavid van Moolenbroek }
110*00b67f09SDavid van Moolenbroek 
111*00b67f09SDavid van Moolenbroek /*
112*00b67f09SDavid van Moolenbroek  * Find the definition of the named acl whose name is "name".
113*00b67f09SDavid van Moolenbroek  */
114*00b67f09SDavid van Moolenbroek static isc_result_t
get_acl_def(const cfg_obj_t * cctx,const char * name,const cfg_obj_t ** ret)115*00b67f09SDavid van Moolenbroek get_acl_def(const cfg_obj_t *cctx, const char *name, const cfg_obj_t **ret) {
116*00b67f09SDavid van Moolenbroek 	isc_result_t result;
117*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *acls = NULL;
118*00b67f09SDavid van Moolenbroek 	const cfg_listelt_t *elt;
119*00b67f09SDavid van Moolenbroek 
120*00b67f09SDavid van Moolenbroek 	result = cfg_map_get(cctx, "acl", &acls);
121*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
122*00b67f09SDavid van Moolenbroek 		return (result);
123*00b67f09SDavid van Moolenbroek 	for (elt = cfg_list_first(acls);
124*00b67f09SDavid van Moolenbroek 	     elt != NULL;
125*00b67f09SDavid van Moolenbroek 	     elt = cfg_list_next(elt)) {
126*00b67f09SDavid van Moolenbroek 		const cfg_obj_t *acl = cfg_listelt_value(elt);
127*00b67f09SDavid van Moolenbroek 		const char *aclname = cfg_obj_asstring(cfg_tuple_get(acl, "name"));
128*00b67f09SDavid van Moolenbroek 		if (strcasecmp(aclname, name) == 0) {
129*00b67f09SDavid van Moolenbroek 			if (ret != NULL) {
130*00b67f09SDavid van Moolenbroek 				*ret = cfg_tuple_get(acl, "value");
131*00b67f09SDavid van Moolenbroek 			}
132*00b67f09SDavid van Moolenbroek 			return (ISC_R_SUCCESS);
133*00b67f09SDavid van Moolenbroek 		}
134*00b67f09SDavid van Moolenbroek 	}
135*00b67f09SDavid van Moolenbroek 	return (ISC_R_NOTFOUND);
136*00b67f09SDavid van Moolenbroek }
137*00b67f09SDavid van Moolenbroek 
138*00b67f09SDavid van Moolenbroek 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)139*00b67f09SDavid van Moolenbroek convert_named_acl(const cfg_obj_t *nameobj, const cfg_obj_t *cctx,
140*00b67f09SDavid van Moolenbroek 		  isc_log_t *lctx, cfg_aclconfctx_t *ctx,
141*00b67f09SDavid van Moolenbroek 		  isc_mem_t *mctx, unsigned int nest_level,
142*00b67f09SDavid van Moolenbroek 		  dns_acl_t **target)
143*00b67f09SDavid van Moolenbroek {
144*00b67f09SDavid van Moolenbroek 	isc_result_t result;
145*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *cacl = NULL;
146*00b67f09SDavid van Moolenbroek 	dns_acl_t *dacl;
147*00b67f09SDavid van Moolenbroek 	dns_acl_t loop;
148*00b67f09SDavid van Moolenbroek 	const char *aclname = cfg_obj_asstring(nameobj);
149*00b67f09SDavid van Moolenbroek 
150*00b67f09SDavid van Moolenbroek 	/* Look for an already-converted version. */
151*00b67f09SDavid van Moolenbroek 	for (dacl = ISC_LIST_HEAD(ctx->named_acl_cache);
152*00b67f09SDavid van Moolenbroek 	     dacl != NULL;
153*00b67f09SDavid van Moolenbroek 	     dacl = ISC_LIST_NEXT(dacl, nextincache))
154*00b67f09SDavid van Moolenbroek 	{
155*00b67f09SDavid van Moolenbroek 		if (strcasecmp(aclname, dacl->name) == 0) {
156*00b67f09SDavid van Moolenbroek 			if (ISC_MAGIC_VALID(dacl, LOOP_MAGIC)) {
157*00b67f09SDavid van Moolenbroek 				cfg_obj_log(nameobj, lctx, ISC_LOG_ERROR,
158*00b67f09SDavid van Moolenbroek 					    "acl loop detected: %s", aclname);
159*00b67f09SDavid van Moolenbroek 				return (ISC_R_FAILURE);
160*00b67f09SDavid van Moolenbroek 			}
161*00b67f09SDavid van Moolenbroek 			dns_acl_attach(dacl, target);
162*00b67f09SDavid van Moolenbroek 			return (ISC_R_SUCCESS);
163*00b67f09SDavid van Moolenbroek 		}
164*00b67f09SDavid van Moolenbroek 	}
165*00b67f09SDavid van Moolenbroek 	/* Not yet converted.  Convert now. */
166*00b67f09SDavid van Moolenbroek 	result = get_acl_def(cctx, aclname, &cacl);
167*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
168*00b67f09SDavid van Moolenbroek 		cfg_obj_log(nameobj, lctx, ISC_LOG_WARNING,
169*00b67f09SDavid van Moolenbroek 			    "undefined ACL '%s'", aclname);
170*00b67f09SDavid van Moolenbroek 		return (result);
171*00b67f09SDavid van Moolenbroek 	}
172*00b67f09SDavid van Moolenbroek 	/*
173*00b67f09SDavid van Moolenbroek 	 * Add a loop detection element.
174*00b67f09SDavid van Moolenbroek 	 */
175*00b67f09SDavid van Moolenbroek 	memset(&loop, 0, sizeof(loop));
176*00b67f09SDavid van Moolenbroek 	ISC_LINK_INIT(&loop, nextincache);
177*00b67f09SDavid van Moolenbroek 	DE_CONST(aclname, loop.name);
178*00b67f09SDavid van Moolenbroek 	loop.magic = LOOP_MAGIC;
179*00b67f09SDavid van Moolenbroek 	ISC_LIST_APPEND(ctx->named_acl_cache, &loop, nextincache);
180*00b67f09SDavid van Moolenbroek 	result = cfg_acl_fromconfig(cacl, cctx, lctx, ctx, mctx,
181*00b67f09SDavid van Moolenbroek 				    nest_level, &dacl);
182*00b67f09SDavid van Moolenbroek 	ISC_LIST_UNLINK(ctx->named_acl_cache, &loop, nextincache);
183*00b67f09SDavid van Moolenbroek 	loop.magic = 0;
184*00b67f09SDavid van Moolenbroek 	loop.name = NULL;
185*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
186*00b67f09SDavid van Moolenbroek 		return (result);
187*00b67f09SDavid van Moolenbroek 	dacl->name = isc_mem_strdup(dacl->mctx, aclname);
188*00b67f09SDavid van Moolenbroek 	if (dacl->name == NULL)
189*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOMEMORY);
190*00b67f09SDavid van Moolenbroek 	ISC_LIST_APPEND(ctx->named_acl_cache, dacl, nextincache);
191*00b67f09SDavid van Moolenbroek 	dns_acl_attach(dacl, target);
192*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
193*00b67f09SDavid van Moolenbroek }
194*00b67f09SDavid van Moolenbroek 
195*00b67f09SDavid van Moolenbroek static isc_result_t
convert_keyname(const cfg_obj_t * keyobj,isc_log_t * lctx,isc_mem_t * mctx,dns_name_t * dnsname)196*00b67f09SDavid van Moolenbroek convert_keyname(const cfg_obj_t *keyobj, isc_log_t *lctx, isc_mem_t *mctx,
197*00b67f09SDavid van Moolenbroek 		dns_name_t *dnsname)
198*00b67f09SDavid van Moolenbroek {
199*00b67f09SDavid van Moolenbroek 	isc_result_t result;
200*00b67f09SDavid van Moolenbroek 	isc_buffer_t buf;
201*00b67f09SDavid van Moolenbroek 	dns_fixedname_t fixname;
202*00b67f09SDavid van Moolenbroek 	unsigned int keylen;
203*00b67f09SDavid van Moolenbroek 	const char *txtname = cfg_obj_asstring(keyobj);
204*00b67f09SDavid van Moolenbroek 
205*00b67f09SDavid van Moolenbroek 	keylen = strlen(txtname);
206*00b67f09SDavid van Moolenbroek 	isc_buffer_constinit(&buf, txtname, keylen);
207*00b67f09SDavid van Moolenbroek 	isc_buffer_add(&buf, keylen);
208*00b67f09SDavid van Moolenbroek 	dns_fixedname_init(&fixname);
209*00b67f09SDavid van Moolenbroek 	result = dns_name_fromtext(dns_fixedname_name(&fixname), &buf,
210*00b67f09SDavid van Moolenbroek 				   dns_rootname, 0, NULL);
211*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
212*00b67f09SDavid van Moolenbroek 		cfg_obj_log(keyobj, lctx, ISC_LOG_WARNING,
213*00b67f09SDavid van Moolenbroek 			    "key name '%s' is not a valid domain name",
214*00b67f09SDavid van Moolenbroek 			    txtname);
215*00b67f09SDavid van Moolenbroek 		return (result);
216*00b67f09SDavid van Moolenbroek 	}
217*00b67f09SDavid van Moolenbroek 	return (dns_name_dup(dns_fixedname_name(&fixname), mctx, dnsname));
218*00b67f09SDavid van Moolenbroek }
219*00b67f09SDavid van Moolenbroek 
220*00b67f09SDavid van Moolenbroek /*
221*00b67f09SDavid van Moolenbroek  * Recursively pre-parse an ACL definition to find the total number
222*00b67f09SDavid van Moolenbroek  * of non-IP-prefix elements (localhost, localnets, key) in all nested
223*00b67f09SDavid van Moolenbroek  * ACLs, so that the parent will have enough space allocated for the
224*00b67f09SDavid van Moolenbroek  * elements table after all the nested ACLs have been merged in to the
225*00b67f09SDavid van Moolenbroek  * parent.
226*00b67f09SDavid van Moolenbroek  */
227*00b67f09SDavid van Moolenbroek static isc_result_t
count_acl_elements(const cfg_obj_t * caml,const cfg_obj_t * cctx,isc_log_t * lctx,cfg_aclconfctx_t * ctx,isc_mem_t * mctx,isc_uint32_t * count,isc_boolean_t * has_negative)228*00b67f09SDavid van Moolenbroek count_acl_elements(const cfg_obj_t *caml, const cfg_obj_t *cctx,
229*00b67f09SDavid van Moolenbroek 		   isc_log_t *lctx, cfg_aclconfctx_t *ctx, isc_mem_t *mctx,
230*00b67f09SDavid van Moolenbroek 		   isc_uint32_t *count, isc_boolean_t *has_negative)
231*00b67f09SDavid van Moolenbroek {
232*00b67f09SDavid van Moolenbroek 	const cfg_listelt_t *elt;
233*00b67f09SDavid van Moolenbroek 	isc_result_t result;
234*00b67f09SDavid van Moolenbroek 	isc_uint32_t n = 0;
235*00b67f09SDavid van Moolenbroek 
236*00b67f09SDavid van Moolenbroek 	REQUIRE(count != NULL);
237*00b67f09SDavid van Moolenbroek 
238*00b67f09SDavid van Moolenbroek 	if (has_negative != NULL)
239*00b67f09SDavid van Moolenbroek 		*has_negative = ISC_FALSE;
240*00b67f09SDavid van Moolenbroek 
241*00b67f09SDavid van Moolenbroek 	for (elt = cfg_list_first(caml);
242*00b67f09SDavid van Moolenbroek 	     elt != NULL;
243*00b67f09SDavid van Moolenbroek 	     elt = cfg_list_next(elt)) {
244*00b67f09SDavid van Moolenbroek 		const cfg_obj_t *ce = cfg_listelt_value(elt);
245*00b67f09SDavid van Moolenbroek 
246*00b67f09SDavid van Moolenbroek 		/* might be a negated element, in which case get the value. */
247*00b67f09SDavid van Moolenbroek 		if (cfg_obj_istuple(ce)) {
248*00b67f09SDavid van Moolenbroek 			const cfg_obj_t *negated =
249*00b67f09SDavid van Moolenbroek 				cfg_tuple_get(ce, "negated");
250*00b67f09SDavid van Moolenbroek 			if (! cfg_obj_isvoid(negated)) {
251*00b67f09SDavid van Moolenbroek 				ce = negated;
252*00b67f09SDavid van Moolenbroek 				if (has_negative != NULL)
253*00b67f09SDavid van Moolenbroek 					*has_negative = ISC_TRUE;
254*00b67f09SDavid van Moolenbroek 			}
255*00b67f09SDavid van Moolenbroek 		}
256*00b67f09SDavid van Moolenbroek 
257*00b67f09SDavid van Moolenbroek 		if (cfg_obj_istype(ce, &cfg_type_keyref)) {
258*00b67f09SDavid van Moolenbroek 			n++;
259*00b67f09SDavid van Moolenbroek 		} else if (cfg_obj_islist(ce)) {
260*00b67f09SDavid van Moolenbroek 			isc_boolean_t negative;
261*00b67f09SDavid van Moolenbroek 			isc_uint32_t sub;
262*00b67f09SDavid van Moolenbroek 			result = count_acl_elements(ce, cctx, lctx, ctx, mctx,
263*00b67f09SDavid van Moolenbroek 						    &sub, &negative);
264*00b67f09SDavid van Moolenbroek 			if (result != ISC_R_SUCCESS)
265*00b67f09SDavid van Moolenbroek 				return (result);
266*00b67f09SDavid van Moolenbroek 			n += sub;
267*00b67f09SDavid van Moolenbroek 			if (negative)
268*00b67f09SDavid van Moolenbroek 				n++;
269*00b67f09SDavid van Moolenbroek #ifdef HAVE_GEOIP
270*00b67f09SDavid van Moolenbroek 		} else if (cfg_obj_istuple(ce) &&
271*00b67f09SDavid van Moolenbroek 			   cfg_obj_isvoid(cfg_tuple_get(ce, "negated")))
272*00b67f09SDavid van Moolenbroek 		{
273*00b67f09SDavid van Moolenbroek 			n++;
274*00b67f09SDavid van Moolenbroek #endif /* HAVE_GEOIP */
275*00b67f09SDavid van Moolenbroek 		} else if (cfg_obj_isstring(ce)) {
276*00b67f09SDavid van Moolenbroek 			const char *name = cfg_obj_asstring(ce);
277*00b67f09SDavid van Moolenbroek 			if (strcasecmp(name, "localhost") == 0 ||
278*00b67f09SDavid van Moolenbroek 			    strcasecmp(name, "localnets") == 0) {
279*00b67f09SDavid van Moolenbroek 				n++;
280*00b67f09SDavid van Moolenbroek 			} else if (strcasecmp(name, "any") != 0 &&
281*00b67f09SDavid van Moolenbroek 				   strcasecmp(name, "none") != 0) {
282*00b67f09SDavid van Moolenbroek 				dns_acl_t *inneracl = NULL;
283*00b67f09SDavid van Moolenbroek 				/*
284*00b67f09SDavid van Moolenbroek 				 * Convert any named acls we reference now if
285*00b67f09SDavid van Moolenbroek 				 * they have not already been converted.
286*00b67f09SDavid van Moolenbroek 				 */
287*00b67f09SDavid van Moolenbroek 				result = convert_named_acl(ce, cctx, lctx, ctx,
288*00b67f09SDavid van Moolenbroek 							   mctx, 0, &inneracl);
289*00b67f09SDavid van Moolenbroek 				if (result == ISC_R_SUCCESS) {
290*00b67f09SDavid van Moolenbroek 					if (inneracl->has_negatives)
291*00b67f09SDavid van Moolenbroek 						n++;
292*00b67f09SDavid van Moolenbroek 					else
293*00b67f09SDavid van Moolenbroek 						n += inneracl->length;
294*00b67f09SDavid van Moolenbroek 					dns_acl_detach(&inneracl);
295*00b67f09SDavid van Moolenbroek 				} else
296*00b67f09SDavid van Moolenbroek 					return (result);
297*00b67f09SDavid van Moolenbroek 			}
298*00b67f09SDavid van Moolenbroek 		}
299*00b67f09SDavid van Moolenbroek 	}
300*00b67f09SDavid van Moolenbroek 
301*00b67f09SDavid van Moolenbroek 	*count = n;
302*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
303*00b67f09SDavid van Moolenbroek }
304*00b67f09SDavid van Moolenbroek 
305*00b67f09SDavid van Moolenbroek #ifdef HAVE_GEOIP
306*00b67f09SDavid van Moolenbroek static dns_geoip_subtype_t
get_subtype(const cfg_obj_t * obj,isc_log_t * lctx,dns_geoip_subtype_t subtype,const char * dbname)307*00b67f09SDavid van Moolenbroek get_subtype(const cfg_obj_t *obj, isc_log_t *lctx,
308*00b67f09SDavid van Moolenbroek 	    dns_geoip_subtype_t subtype, const char *dbname)
309*00b67f09SDavid van Moolenbroek {
310*00b67f09SDavid van Moolenbroek 	if (dbname == NULL)
311*00b67f09SDavid van Moolenbroek 		return (subtype);
312*00b67f09SDavid van Moolenbroek 
313*00b67f09SDavid van Moolenbroek 	switch (subtype) {
314*00b67f09SDavid van Moolenbroek 	case dns_geoip_countrycode:
315*00b67f09SDavid van Moolenbroek 		if (strcasecmp(dbname, "city") == 0)
316*00b67f09SDavid van Moolenbroek 			return (dns_geoip_city_countrycode);
317*00b67f09SDavid van Moolenbroek 		else if (strcasecmp(dbname, "region") == 0)
318*00b67f09SDavid van Moolenbroek 			return (dns_geoip_region_countrycode);
319*00b67f09SDavid van Moolenbroek 		else if (strcasecmp(dbname, "country") == 0)
320*00b67f09SDavid van Moolenbroek 			return (dns_geoip_country_code);
321*00b67f09SDavid van Moolenbroek 		cfg_obj_log(obj, lctx, ISC_LOG_ERROR,
322*00b67f09SDavid van Moolenbroek 			    "invalid GeoIP DB specified for "
323*00b67f09SDavid van Moolenbroek 			    "country search: ignored");
324*00b67f09SDavid van Moolenbroek 		return (subtype);
325*00b67f09SDavid van Moolenbroek 	case dns_geoip_countrycode3:
326*00b67f09SDavid van Moolenbroek 		if (strcasecmp(dbname, "city") == 0)
327*00b67f09SDavid van Moolenbroek 			return (dns_geoip_city_countrycode3);
328*00b67f09SDavid van Moolenbroek 		else if (strcasecmp(dbname, "country") == 0)
329*00b67f09SDavid van Moolenbroek 			return (dns_geoip_country_code3);
330*00b67f09SDavid van Moolenbroek 		cfg_obj_log(obj, lctx, ISC_LOG_ERROR,
331*00b67f09SDavid van Moolenbroek 			    "invalid GeoIP DB specified for "
332*00b67f09SDavid van Moolenbroek 			    "country search: ignored");
333*00b67f09SDavid van Moolenbroek 		return (subtype);
334*00b67f09SDavid van Moolenbroek 	case dns_geoip_countryname:
335*00b67f09SDavid van Moolenbroek 		if (strcasecmp(dbname, "city") == 0)
336*00b67f09SDavid van Moolenbroek 			return (dns_geoip_city_countryname);
337*00b67f09SDavid van Moolenbroek 		else if (strcasecmp(dbname, "country") == 0)
338*00b67f09SDavid van Moolenbroek 			return (dns_geoip_country_name);
339*00b67f09SDavid van Moolenbroek 		cfg_obj_log(obj, lctx, ISC_LOG_ERROR,
340*00b67f09SDavid van Moolenbroek 			    "invalid GeoIP DB specified for "
341*00b67f09SDavid van Moolenbroek 			    "country search: ignored");
342*00b67f09SDavid van Moolenbroek 		return (subtype);
343*00b67f09SDavid van Moolenbroek 	case dns_geoip_region:
344*00b67f09SDavid van Moolenbroek 		if (strcasecmp(dbname, "city") == 0)
345*00b67f09SDavid van Moolenbroek 			return (dns_geoip_city_region);
346*00b67f09SDavid van Moolenbroek 		else if (strcasecmp(dbname, "region") == 0)
347*00b67f09SDavid van Moolenbroek 			return (dns_geoip_region_code);
348*00b67f09SDavid van Moolenbroek 		cfg_obj_log(obj, lctx, ISC_LOG_ERROR,
349*00b67f09SDavid van Moolenbroek 			    "invalid GeoIP DB specified for "
350*00b67f09SDavid van Moolenbroek 			    "region search: ignored");
351*00b67f09SDavid van Moolenbroek 		return (subtype);
352*00b67f09SDavid van Moolenbroek 	case dns_geoip_regionname:
353*00b67f09SDavid van Moolenbroek 		if (strcasecmp(dbname, "city") == 0)
354*00b67f09SDavid van Moolenbroek 			return (dns_geoip_city_region);
355*00b67f09SDavid van Moolenbroek 		else if (strcasecmp(dbname, "region") == 0)
356*00b67f09SDavid van Moolenbroek 			return (dns_geoip_region_name);
357*00b67f09SDavid van Moolenbroek 		cfg_obj_log(obj, lctx, ISC_LOG_ERROR,
358*00b67f09SDavid van Moolenbroek 			    "invalid GeoIP DB specified for "
359*00b67f09SDavid van Moolenbroek 			    "region search: ignored");
360*00b67f09SDavid van Moolenbroek 		return (subtype);
361*00b67f09SDavid van Moolenbroek 
362*00b67f09SDavid van Moolenbroek 	/*
363*00b67f09SDavid van Moolenbroek 	 * Log a warning if the wrong database was specified
364*00b67f09SDavid van Moolenbroek 	 * on an unambiguous query
365*00b67f09SDavid van Moolenbroek 	 */
366*00b67f09SDavid van Moolenbroek 	case dns_geoip_city_name:
367*00b67f09SDavid van Moolenbroek 	case dns_geoip_city_postalcode:
368*00b67f09SDavid van Moolenbroek 	case dns_geoip_city_metrocode:
369*00b67f09SDavid van Moolenbroek 	case dns_geoip_city_areacode:
370*00b67f09SDavid van Moolenbroek 	case dns_geoip_city_continentcode:
371*00b67f09SDavid van Moolenbroek 	case dns_geoip_city_timezonecode:
372*00b67f09SDavid van Moolenbroek 		if (strcasecmp(dbname, "city") != 0)
373*00b67f09SDavid van Moolenbroek 			cfg_obj_log(obj, lctx, ISC_LOG_WARNING,
374*00b67f09SDavid van Moolenbroek 				    "invalid GeoIP DB specified for "
375*00b67f09SDavid van Moolenbroek 				    "a 'city'-only search type: ignoring");
376*00b67f09SDavid van Moolenbroek 		return (subtype);
377*00b67f09SDavid van Moolenbroek 	case dns_geoip_isp_name:
378*00b67f09SDavid van Moolenbroek 		if (strcasecmp(dbname, "isp") != 0)
379*00b67f09SDavid van Moolenbroek 			cfg_obj_log(obj, lctx, ISC_LOG_WARNING,
380*00b67f09SDavid van Moolenbroek 				    "invalid GeoIP DB specified for "
381*00b67f09SDavid van Moolenbroek 				    "an 'isp' search: ignoring");
382*00b67f09SDavid van Moolenbroek 		return (subtype);
383*00b67f09SDavid van Moolenbroek 	case dns_geoip_org_name:
384*00b67f09SDavid van Moolenbroek 		if (strcasecmp(dbname, "org") != 0)
385*00b67f09SDavid van Moolenbroek 			cfg_obj_log(obj, lctx, ISC_LOG_WARNING,
386*00b67f09SDavid van Moolenbroek 				    "invalid GeoIP DB specified for "
387*00b67f09SDavid van Moolenbroek 				    "an 'org' search: ignoring");
388*00b67f09SDavid van Moolenbroek 		return (subtype);
389*00b67f09SDavid van Moolenbroek 	case dns_geoip_as_asnum:
390*00b67f09SDavid van Moolenbroek 		if (strcasecmp(dbname, "asnum") != 0)
391*00b67f09SDavid van Moolenbroek 			cfg_obj_log(obj, lctx, ISC_LOG_WARNING,
392*00b67f09SDavid van Moolenbroek 				    "invalid GeoIP DB specified for "
393*00b67f09SDavid van Moolenbroek 				    "an 'asnum' search: ignoring");
394*00b67f09SDavid van Moolenbroek 		return (subtype);
395*00b67f09SDavid van Moolenbroek 	case dns_geoip_domain_name:
396*00b67f09SDavid van Moolenbroek 		if (strcasecmp(dbname, "domain") != 0)
397*00b67f09SDavid van Moolenbroek 			cfg_obj_log(obj, lctx, ISC_LOG_WARNING,
398*00b67f09SDavid van Moolenbroek 				    "invalid GeoIP DB specified for "
399*00b67f09SDavid van Moolenbroek 				    "a 'domain' search: ignoring");
400*00b67f09SDavid van Moolenbroek 		return (subtype);
401*00b67f09SDavid van Moolenbroek 	case dns_geoip_netspeed_id:
402*00b67f09SDavid van Moolenbroek 		if (strcasecmp(dbname, "netspeed") != 0)
403*00b67f09SDavid van Moolenbroek 			cfg_obj_log(obj, lctx, ISC_LOG_WARNING,
404*00b67f09SDavid van Moolenbroek 				    "invalid GeoIP DB specified for "
405*00b67f09SDavid van Moolenbroek 				    "a 'netspeed' search: ignoring");
406*00b67f09SDavid van Moolenbroek 		return (subtype);
407*00b67f09SDavid van Moolenbroek 	default:
408*00b67f09SDavid van Moolenbroek 		INSIST(0);
409*00b67f09SDavid van Moolenbroek 	}
410*00b67f09SDavid van Moolenbroek }
411*00b67f09SDavid van Moolenbroek 
412*00b67f09SDavid van Moolenbroek static isc_boolean_t
geoip_can_answer(dns_aclelement_t * elt,cfg_aclconfctx_t * ctx)413*00b67f09SDavid van Moolenbroek geoip_can_answer(dns_aclelement_t *elt, cfg_aclconfctx_t *ctx) {
414*00b67f09SDavid van Moolenbroek 	if (ctx->geoip == NULL)
415*00b67f09SDavid van Moolenbroek 		return (ISC_TRUE);
416*00b67f09SDavid van Moolenbroek 
417*00b67f09SDavid van Moolenbroek 	switch (elt->geoip_elem.subtype) {
418*00b67f09SDavid van Moolenbroek 	case dns_geoip_countrycode:
419*00b67f09SDavid van Moolenbroek 	case dns_geoip_countrycode3:
420*00b67f09SDavid van Moolenbroek 	case dns_geoip_countryname:
421*00b67f09SDavid van Moolenbroek 		if (ctx->geoip->city_v4 != NULL ||
422*00b67f09SDavid van Moolenbroek 		    ctx->geoip->city_v6 != NULL ||
423*00b67f09SDavid van Moolenbroek 		    ctx->geoip->country_v4 != NULL ||
424*00b67f09SDavid van Moolenbroek 		    ctx->geoip->country_v6 != NULL ||
425*00b67f09SDavid van Moolenbroek 		    ctx->geoip->region != NULL)
426*00b67f09SDavid van Moolenbroek 			return (ISC_TRUE);
427*00b67f09SDavid van Moolenbroek 	case dns_geoip_region:
428*00b67f09SDavid van Moolenbroek 	case dns_geoip_regionname:
429*00b67f09SDavid van Moolenbroek 		if (ctx->geoip->city_v4 != NULL ||
430*00b67f09SDavid van Moolenbroek 		    ctx->geoip->city_v6 != NULL ||
431*00b67f09SDavid van Moolenbroek 		    ctx->geoip->region != NULL)
432*00b67f09SDavid van Moolenbroek 			return (ISC_TRUE);
433*00b67f09SDavid van Moolenbroek 	case dns_geoip_country_code:
434*00b67f09SDavid van Moolenbroek 	case dns_geoip_country_code3:
435*00b67f09SDavid van Moolenbroek 	case dns_geoip_country_name:
436*00b67f09SDavid van Moolenbroek 		if (ctx->geoip->country_v4 != NULL ||
437*00b67f09SDavid van Moolenbroek 		    ctx->geoip->country_v6 != NULL)
438*00b67f09SDavid van Moolenbroek 			return (ISC_TRUE);
439*00b67f09SDavid van Moolenbroek 	case dns_geoip_region_countrycode:
440*00b67f09SDavid van Moolenbroek 	case dns_geoip_region_code:
441*00b67f09SDavid van Moolenbroek 	case dns_geoip_region_name:
442*00b67f09SDavid van Moolenbroek 		if (ctx->geoip->region != NULL)
443*00b67f09SDavid van Moolenbroek 			return (ISC_TRUE);
444*00b67f09SDavid van Moolenbroek 	case dns_geoip_city_countrycode:
445*00b67f09SDavid van Moolenbroek 	case dns_geoip_city_countrycode3:
446*00b67f09SDavid van Moolenbroek 	case dns_geoip_city_countryname:
447*00b67f09SDavid van Moolenbroek 	case dns_geoip_city_region:
448*00b67f09SDavid van Moolenbroek 	case dns_geoip_city_regionname:
449*00b67f09SDavid van Moolenbroek 	case dns_geoip_city_name:
450*00b67f09SDavid van Moolenbroek 	case dns_geoip_city_postalcode:
451*00b67f09SDavid van Moolenbroek 	case dns_geoip_city_metrocode:
452*00b67f09SDavid van Moolenbroek 	case dns_geoip_city_areacode:
453*00b67f09SDavid van Moolenbroek 	case dns_geoip_city_continentcode:
454*00b67f09SDavid van Moolenbroek 	case dns_geoip_city_timezonecode:
455*00b67f09SDavid van Moolenbroek 		if (ctx->geoip->city_v4 != NULL ||
456*00b67f09SDavid van Moolenbroek 		    ctx->geoip->city_v6 != NULL)
457*00b67f09SDavid van Moolenbroek 			return (ISC_TRUE);
458*00b67f09SDavid van Moolenbroek 	case dns_geoip_isp_name:
459*00b67f09SDavid van Moolenbroek 		if (ctx->geoip->isp != NULL)
460*00b67f09SDavid van Moolenbroek 			return (ISC_TRUE);
461*00b67f09SDavid van Moolenbroek 	case dns_geoip_org_name:
462*00b67f09SDavid van Moolenbroek 		if (ctx->geoip->org != NULL)
463*00b67f09SDavid van Moolenbroek 			return (ISC_TRUE);
464*00b67f09SDavid van Moolenbroek 	case dns_geoip_as_asnum:
465*00b67f09SDavid van Moolenbroek 		if (ctx->geoip->as != NULL)
466*00b67f09SDavid van Moolenbroek 			return (ISC_TRUE);
467*00b67f09SDavid van Moolenbroek 	case dns_geoip_domain_name:
468*00b67f09SDavid van Moolenbroek 		if (ctx->geoip->domain != NULL)
469*00b67f09SDavid van Moolenbroek 			return (ISC_TRUE);
470*00b67f09SDavid van Moolenbroek 	case dns_geoip_netspeed_id:
471*00b67f09SDavid van Moolenbroek 		if (ctx->geoip->netspeed != NULL)
472*00b67f09SDavid van Moolenbroek 			return (ISC_TRUE);
473*00b67f09SDavid van Moolenbroek 	}
474*00b67f09SDavid van Moolenbroek 
475*00b67f09SDavid van Moolenbroek 	return (ISC_FALSE);
476*00b67f09SDavid van Moolenbroek }
477*00b67f09SDavid van Moolenbroek 
478*00b67f09SDavid van Moolenbroek static isc_result_t
parse_geoip_element(const cfg_obj_t * obj,isc_log_t * lctx,cfg_aclconfctx_t * ctx,dns_aclelement_t * dep)479*00b67f09SDavid van Moolenbroek parse_geoip_element(const cfg_obj_t *obj, isc_log_t *lctx,
480*00b67f09SDavid van Moolenbroek 		    cfg_aclconfctx_t *ctx, dns_aclelement_t *dep)
481*00b67f09SDavid van Moolenbroek {
482*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *ge;
483*00b67f09SDavid van Moolenbroek 	const char *dbname = NULL;
484*00b67f09SDavid van Moolenbroek 	const char *stype, *search;
485*00b67f09SDavid van Moolenbroek 	dns_geoip_subtype_t subtype;
486*00b67f09SDavid van Moolenbroek 	dns_aclelement_t de;
487*00b67f09SDavid van Moolenbroek 	size_t len;
488*00b67f09SDavid van Moolenbroek 
489*00b67f09SDavid van Moolenbroek 	REQUIRE(dep != NULL);
490*00b67f09SDavid van Moolenbroek 
491*00b67f09SDavid van Moolenbroek 	de = *dep;
492*00b67f09SDavid van Moolenbroek 
493*00b67f09SDavid van Moolenbroek 	ge = cfg_tuple_get(obj, "db");
494*00b67f09SDavid van Moolenbroek 	if (!cfg_obj_isvoid(ge))
495*00b67f09SDavid van Moolenbroek 		dbname = cfg_obj_asstring(ge);
496*00b67f09SDavid van Moolenbroek 
497*00b67f09SDavid van Moolenbroek 	stype = cfg_obj_asstring(cfg_tuple_get(obj, "subtype"));
498*00b67f09SDavid van Moolenbroek 	search = cfg_obj_asstring(cfg_tuple_get(obj, "search"));
499*00b67f09SDavid van Moolenbroek 	len = strlen(search);
500*00b67f09SDavid van Moolenbroek 
501*00b67f09SDavid van Moolenbroek 	if (len == 0) {
502*00b67f09SDavid van Moolenbroek 		cfg_obj_log(obj, lctx, ISC_LOG_ERROR,
503*00b67f09SDavid van Moolenbroek 			    "zero-length geoip search field");
504*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
505*00b67f09SDavid van Moolenbroek 	}
506*00b67f09SDavid van Moolenbroek 
507*00b67f09SDavid van Moolenbroek 	if (strcasecmp(stype, "country") == 0 && len == 2) {
508*00b67f09SDavid van Moolenbroek 		/* Two-letter country code */
509*00b67f09SDavid van Moolenbroek 		subtype = dns_geoip_countrycode;
510*00b67f09SDavid van Moolenbroek 		strlcpy(de.geoip_elem.as_string, search,
511*00b67f09SDavid van Moolenbroek 			sizeof(de.geoip_elem.as_string));
512*00b67f09SDavid van Moolenbroek 	} else if (strcasecmp(stype, "country") == 0 && len == 3) {
513*00b67f09SDavid van Moolenbroek 		/* Three-letter country code */
514*00b67f09SDavid van Moolenbroek 		subtype = dns_geoip_countrycode3;
515*00b67f09SDavid van Moolenbroek 		strlcpy(de.geoip_elem.as_string, search,
516*00b67f09SDavid van Moolenbroek 			sizeof(de.geoip_elem.as_string));
517*00b67f09SDavid van Moolenbroek 	} else if (strcasecmp(stype, "country") == 0) {
518*00b67f09SDavid van Moolenbroek 		/* Country name */
519*00b67f09SDavid van Moolenbroek 		subtype = dns_geoip_countryname;
520*00b67f09SDavid van Moolenbroek 		strlcpy(de.geoip_elem.as_string, search,
521*00b67f09SDavid van Moolenbroek 			sizeof(de.geoip_elem.as_string));
522*00b67f09SDavid van Moolenbroek 	} else if (strcasecmp(stype, "region") == 0 && len == 2) {
523*00b67f09SDavid van Moolenbroek 		/* Two-letter region code */
524*00b67f09SDavid van Moolenbroek 		subtype = dns_geoip_region;
525*00b67f09SDavid van Moolenbroek 		strlcpy(de.geoip_elem.as_string, search,
526*00b67f09SDavid van Moolenbroek 			sizeof(de.geoip_elem.as_string));
527*00b67f09SDavid van Moolenbroek 	} else if (strcasecmp(stype, "region") == 0) {
528*00b67f09SDavid van Moolenbroek 		/* Region name */
529*00b67f09SDavid van Moolenbroek 		subtype = dns_geoip_regionname;
530*00b67f09SDavid van Moolenbroek 		strlcpy(de.geoip_elem.as_string, search,
531*00b67f09SDavid van Moolenbroek 			sizeof(de.geoip_elem.as_string));
532*00b67f09SDavid van Moolenbroek 	} else if (strcasecmp(stype, "city") == 0) {
533*00b67f09SDavid van Moolenbroek 		/* City name */
534*00b67f09SDavid van Moolenbroek 		subtype = dns_geoip_city_name;
535*00b67f09SDavid van Moolenbroek 		strlcpy(de.geoip_elem.as_string, search,
536*00b67f09SDavid van Moolenbroek 			sizeof(de.geoip_elem.as_string));
537*00b67f09SDavid van Moolenbroek 	} else if (strcasecmp(stype, "postal") == 0 && len < 7) {
538*00b67f09SDavid van Moolenbroek 		subtype = dns_geoip_city_postalcode;
539*00b67f09SDavid van Moolenbroek 		strlcpy(de.geoip_elem.as_string, search,
540*00b67f09SDavid van Moolenbroek 			sizeof(de.geoip_elem.as_string));
541*00b67f09SDavid van Moolenbroek 	} else if (strcasecmp(stype, "postal") == 0) {
542*00b67f09SDavid van Moolenbroek 		cfg_obj_log(obj, lctx, ISC_LOG_ERROR,
543*00b67f09SDavid van Moolenbroek 			    "geoiop postal code (%s) too long", search);
544*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
545*00b67f09SDavid van Moolenbroek 	} else if (strcasecmp(stype, "metro") == 0) {
546*00b67f09SDavid van Moolenbroek 		subtype = dns_geoip_city_metrocode;
547*00b67f09SDavid van Moolenbroek 		de.geoip_elem.as_int = atoi(search);
548*00b67f09SDavid van Moolenbroek 	} else if (strcasecmp(stype, "area") == 0) {
549*00b67f09SDavid van Moolenbroek 		subtype = dns_geoip_city_areacode;
550*00b67f09SDavid van Moolenbroek 		de.geoip_elem.as_int = atoi(search);
551*00b67f09SDavid van Moolenbroek 	} else if (strcasecmp(stype, "tz") == 0) {
552*00b67f09SDavid van Moolenbroek 		subtype = dns_geoip_city_timezonecode;
553*00b67f09SDavid van Moolenbroek 		strlcpy(de.geoip_elem.as_string, search,
554*00b67f09SDavid van Moolenbroek 			sizeof(de.geoip_elem.as_string));
555*00b67f09SDavid van Moolenbroek 	} else if (strcasecmp(stype, "continent") == 0 && len == 2) {
556*00b67f09SDavid van Moolenbroek 		/* Two-letter continent code */
557*00b67f09SDavid van Moolenbroek 		subtype = dns_geoip_city_continentcode;
558*00b67f09SDavid van Moolenbroek 		strlcpy(de.geoip_elem.as_string, search,
559*00b67f09SDavid van Moolenbroek 			sizeof(de.geoip_elem.as_string));
560*00b67f09SDavid van Moolenbroek 	} else if (strcasecmp(stype, "continent") == 0) {
561*00b67f09SDavid van Moolenbroek 		cfg_obj_log(obj, lctx, ISC_LOG_ERROR,
562*00b67f09SDavid van Moolenbroek 			    "geoiop continent code (%s) too long", search);
563*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
564*00b67f09SDavid van Moolenbroek 	} else if (strcasecmp(stype, "isp") == 0) {
565*00b67f09SDavid van Moolenbroek 		subtype = dns_geoip_isp_name;
566*00b67f09SDavid van Moolenbroek 		strlcpy(de.geoip_elem.as_string, search,
567*00b67f09SDavid van Moolenbroek 			sizeof(de.geoip_elem.as_string));
568*00b67f09SDavid van Moolenbroek 	} else if (strcasecmp(stype, "asnum") == 0) {
569*00b67f09SDavid van Moolenbroek 		subtype = dns_geoip_as_asnum;
570*00b67f09SDavid van Moolenbroek 		strlcpy(de.geoip_elem.as_string, search,
571*00b67f09SDavid van Moolenbroek 			sizeof(de.geoip_elem.as_string));
572*00b67f09SDavid van Moolenbroek 	} else if (strcasecmp(stype, "org") == 0) {
573*00b67f09SDavid van Moolenbroek 		subtype = dns_geoip_org_name;
574*00b67f09SDavid van Moolenbroek 		strlcpy(de.geoip_elem.as_string, search,
575*00b67f09SDavid van Moolenbroek 			sizeof(de.geoip_elem.as_string));
576*00b67f09SDavid van Moolenbroek 	} else if (strcasecmp(stype, "domain") == 0) {
577*00b67f09SDavid van Moolenbroek 		subtype = dns_geoip_domain_name;
578*00b67f09SDavid van Moolenbroek 		strlcpy(de.geoip_elem.as_string, search,
579*00b67f09SDavid van Moolenbroek 			sizeof(de.geoip_elem.as_string));
580*00b67f09SDavid van Moolenbroek 	} else if (strcasecmp(stype, "netspeed") == 0) {
581*00b67f09SDavid van Moolenbroek 		subtype = dns_geoip_netspeed_id;
582*00b67f09SDavid van Moolenbroek 		de.geoip_elem.as_int = atoi(search);
583*00b67f09SDavid van Moolenbroek 	} else
584*00b67f09SDavid van Moolenbroek 		INSIST(0);
585*00b67f09SDavid van Moolenbroek 
586*00b67f09SDavid van Moolenbroek 	de.geoip_elem.subtype = get_subtype(obj, lctx, subtype, dbname);
587*00b67f09SDavid van Moolenbroek 
588*00b67f09SDavid van Moolenbroek 	if (! geoip_can_answer(&de, ctx)) {
589*00b67f09SDavid van Moolenbroek 		cfg_obj_log(obj, lctx, ISC_LOG_ERROR,
590*00b67f09SDavid van Moolenbroek 			    "no GeoIP database installed which can answer "
591*00b67f09SDavid van Moolenbroek 			    "queries of type '%s'", stype);
592*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
593*00b67f09SDavid van Moolenbroek 	}
594*00b67f09SDavid van Moolenbroek 
595*00b67f09SDavid van Moolenbroek 	*dep = de;
596*00b67f09SDavid van Moolenbroek 
597*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
598*00b67f09SDavid van Moolenbroek }
599*00b67f09SDavid van Moolenbroek #endif
600*00b67f09SDavid van Moolenbroek 
601*00b67f09SDavid van Moolenbroek isc_result_t
cfg_acl_fromconfig(const cfg_obj_t * caml,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)602*00b67f09SDavid van Moolenbroek cfg_acl_fromconfig(const cfg_obj_t *caml, const cfg_obj_t *cctx,
603*00b67f09SDavid van Moolenbroek 		   isc_log_t *lctx, cfg_aclconfctx_t *ctx,
604*00b67f09SDavid van Moolenbroek 		   isc_mem_t *mctx, unsigned int nest_level,
605*00b67f09SDavid van Moolenbroek 		   dns_acl_t **target)
606*00b67f09SDavid van Moolenbroek {
607*00b67f09SDavid van Moolenbroek 	return (cfg_acl_fromconfig2(caml, cctx, lctx, ctx, mctx,
608*00b67f09SDavid van Moolenbroek 				    nest_level, 0, target));
609*00b67f09SDavid van Moolenbroek }
610*00b67f09SDavid van Moolenbroek 
611*00b67f09SDavid van Moolenbroek isc_result_t
cfg_acl_fromconfig2(const cfg_obj_t * caml,const cfg_obj_t * cctx,isc_log_t * lctx,cfg_aclconfctx_t * ctx,isc_mem_t * mctx,unsigned int nest_level,isc_uint16_t family,dns_acl_t ** target)612*00b67f09SDavid van Moolenbroek cfg_acl_fromconfig2(const cfg_obj_t *caml, const cfg_obj_t *cctx,
613*00b67f09SDavid van Moolenbroek 		   isc_log_t *lctx, cfg_aclconfctx_t *ctx,
614*00b67f09SDavid van Moolenbroek 		   isc_mem_t *mctx, unsigned int nest_level,
615*00b67f09SDavid van Moolenbroek 		   isc_uint16_t family, dns_acl_t **target)
616*00b67f09SDavid van Moolenbroek {
617*00b67f09SDavid van Moolenbroek 	isc_result_t result;
618*00b67f09SDavid van Moolenbroek 	dns_acl_t *dacl = NULL, *inneracl = NULL;
619*00b67f09SDavid van Moolenbroek 	dns_aclelement_t *de;
620*00b67f09SDavid van Moolenbroek 	const cfg_listelt_t *elt;
621*00b67f09SDavid van Moolenbroek 	dns_iptable_t *iptab;
622*00b67f09SDavid van Moolenbroek 	int new_nest_level = 0;
623*00b67f09SDavid van Moolenbroek 
624*00b67f09SDavid van Moolenbroek 	if (nest_level != 0)
625*00b67f09SDavid van Moolenbroek 		new_nest_level = nest_level - 1;
626*00b67f09SDavid van Moolenbroek 
627*00b67f09SDavid van Moolenbroek 	REQUIRE(target != NULL);
628*00b67f09SDavid van Moolenbroek 	REQUIRE(*target == NULL || DNS_ACL_VALID(*target));
629*00b67f09SDavid van Moolenbroek 
630*00b67f09SDavid van Moolenbroek 	if (*target != NULL) {
631*00b67f09SDavid van Moolenbroek 		/*
632*00b67f09SDavid van Moolenbroek 		 * If target already points to an ACL, then we're being
633*00b67f09SDavid van Moolenbroek 		 * called recursively to configure a nested ACL.  The
634*00b67f09SDavid van Moolenbroek 		 * nested ACL's contents should just be absorbed into its
635*00b67f09SDavid van Moolenbroek 		 * parent ACL.
636*00b67f09SDavid van Moolenbroek 		 */
637*00b67f09SDavid van Moolenbroek 		dns_acl_attach(*target, &dacl);
638*00b67f09SDavid van Moolenbroek 		dns_acl_detach(target);
639*00b67f09SDavid van Moolenbroek 	} else {
640*00b67f09SDavid van Moolenbroek 		/*
641*00b67f09SDavid van Moolenbroek 		 * Need to allocate a new ACL structure.  Count the items
642*00b67f09SDavid van Moolenbroek 		 * in the ACL definition that will require space in the
643*00b67f09SDavid van Moolenbroek 		 * elements table.  (Note that if nest_level is nonzero,
644*00b67f09SDavid van Moolenbroek 		 * *everything* goes in the elements table.)
645*00b67f09SDavid van Moolenbroek 		 */
646*00b67f09SDavid van Moolenbroek 		isc_uint32_t nelem;
647*00b67f09SDavid van Moolenbroek 
648*00b67f09SDavid van Moolenbroek 		if (nest_level == 0) {
649*00b67f09SDavid van Moolenbroek 			result = count_acl_elements(caml, cctx, lctx, ctx,
650*00b67f09SDavid van Moolenbroek 						    mctx, &nelem, NULL);
651*00b67f09SDavid van Moolenbroek 			if (result != ISC_R_SUCCESS)
652*00b67f09SDavid van Moolenbroek 				return (result);
653*00b67f09SDavid van Moolenbroek 		} else
654*00b67f09SDavid van Moolenbroek 			nelem = cfg_list_length(caml, ISC_FALSE);
655*00b67f09SDavid van Moolenbroek 
656*00b67f09SDavid van Moolenbroek 		result = dns_acl_create(mctx, nelem, &dacl);
657*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS)
658*00b67f09SDavid van Moolenbroek 			return (result);
659*00b67f09SDavid van Moolenbroek 	}
660*00b67f09SDavid van Moolenbroek 
661*00b67f09SDavid van Moolenbroek 	de = dacl->elements;
662*00b67f09SDavid van Moolenbroek 	for (elt = cfg_list_first(caml);
663*00b67f09SDavid van Moolenbroek 	     elt != NULL;
664*00b67f09SDavid van Moolenbroek 	     elt = cfg_list_next(elt)) {
665*00b67f09SDavid van Moolenbroek 		const cfg_obj_t *ce = cfg_listelt_value(elt);
666*00b67f09SDavid van Moolenbroek 		isc_boolean_t neg = ISC_FALSE;
667*00b67f09SDavid van Moolenbroek 
668*00b67f09SDavid van Moolenbroek 		INSIST(dacl->length <= dacl->alloc);
669*00b67f09SDavid van Moolenbroek 
670*00b67f09SDavid van Moolenbroek 		if (cfg_obj_istuple(ce)) {
671*00b67f09SDavid van Moolenbroek 			/* Might be a negated element */
672*00b67f09SDavid van Moolenbroek 			const cfg_obj_t *negated =
673*00b67f09SDavid van Moolenbroek 				cfg_tuple_get(ce, "negated");
674*00b67f09SDavid van Moolenbroek 			if (! cfg_obj_isvoid(negated)) {
675*00b67f09SDavid van Moolenbroek 				neg = ISC_TRUE;
676*00b67f09SDavid van Moolenbroek 				dacl->has_negatives = ISC_TRUE;
677*00b67f09SDavid van Moolenbroek 				ce = negated;
678*00b67f09SDavid van Moolenbroek 			}
679*00b67f09SDavid van Moolenbroek 		}
680*00b67f09SDavid van Moolenbroek 
681*00b67f09SDavid van Moolenbroek 		/*
682*00b67f09SDavid van Moolenbroek 		 * If nest_level is nonzero, then every element is
683*00b67f09SDavid van Moolenbroek 		 * to be stored as a separate, nested ACL rather than
684*00b67f09SDavid van Moolenbroek 		 * merged into the main iptable.
685*00b67f09SDavid van Moolenbroek 		 */
686*00b67f09SDavid van Moolenbroek 		iptab = dacl->iptable;
687*00b67f09SDavid van Moolenbroek 
688*00b67f09SDavid van Moolenbroek 		if (nest_level != 0) {
689*00b67f09SDavid van Moolenbroek 			result = dns_acl_create(mctx,
690*00b67f09SDavid van Moolenbroek 						cfg_list_length(ce, ISC_FALSE),
691*00b67f09SDavid van Moolenbroek 						&de->nestedacl);
692*00b67f09SDavid van Moolenbroek 			if (result != ISC_R_SUCCESS)
693*00b67f09SDavid van Moolenbroek 				goto cleanup;
694*00b67f09SDavid van Moolenbroek 			iptab = de->nestedacl->iptable;
695*00b67f09SDavid van Moolenbroek 		}
696*00b67f09SDavid van Moolenbroek 
697*00b67f09SDavid van Moolenbroek 		if (cfg_obj_isnetprefix(ce)) {
698*00b67f09SDavid van Moolenbroek 			/* Network prefix */
699*00b67f09SDavid van Moolenbroek 			isc_netaddr_t	addr;
700*00b67f09SDavid van Moolenbroek 			unsigned int	bitlen;
701*00b67f09SDavid van Moolenbroek 
702*00b67f09SDavid van Moolenbroek 			cfg_obj_asnetprefix(ce, &addr, &bitlen);
703*00b67f09SDavid van Moolenbroek 			if (family != 0 && family != addr.family) {
704*00b67f09SDavid van Moolenbroek 				char buf[ISC_NETADDR_FORMATSIZE + 1];
705*00b67f09SDavid van Moolenbroek 				isc_netaddr_format(&addr, buf, sizeof(buf));
706*00b67f09SDavid van Moolenbroek 				cfg_obj_log(ce, lctx, ISC_LOG_WARNING,
707*00b67f09SDavid van Moolenbroek 					    "'%s': incorrect address family; "
708*00b67f09SDavid van Moolenbroek 					    "ignoring", buf);
709*00b67f09SDavid van Moolenbroek 				if (nest_level != 0)
710*00b67f09SDavid van Moolenbroek 					dns_acl_detach(&de->nestedacl);
711*00b67f09SDavid van Moolenbroek 				continue;
712*00b67f09SDavid van Moolenbroek 			}
713*00b67f09SDavid van Moolenbroek 
714*00b67f09SDavid van Moolenbroek 			/*
715*00b67f09SDavid van Moolenbroek 			 * If nesting ACLs (nest_level != 0), we negate
716*00b67f09SDavid van Moolenbroek 			 * the nestedacl element, not the iptable entry.
717*00b67f09SDavid van Moolenbroek 			 */
718*00b67f09SDavid van Moolenbroek 			result = dns_iptable_addprefix(iptab, &addr, bitlen,
719*00b67f09SDavid van Moolenbroek 					      ISC_TF(nest_level != 0 || !neg));
720*00b67f09SDavid van Moolenbroek 			if (result != ISC_R_SUCCESS)
721*00b67f09SDavid van Moolenbroek 				goto cleanup;
722*00b67f09SDavid van Moolenbroek 
723*00b67f09SDavid van Moolenbroek 			if (nest_level > 0) {
724*00b67f09SDavid van Moolenbroek 				INSIST(dacl->length < dacl->alloc);
725*00b67f09SDavid van Moolenbroek 				de->type = dns_aclelementtype_nestedacl;
726*00b67f09SDavid van Moolenbroek 				de->negative = neg;
727*00b67f09SDavid van Moolenbroek 			} else
728*00b67f09SDavid van Moolenbroek 				continue;
729*00b67f09SDavid van Moolenbroek 		} else if (cfg_obj_islist(ce)) {
730*00b67f09SDavid van Moolenbroek 			/*
731*00b67f09SDavid van Moolenbroek 			 * If we're nesting ACLs, put the nested
732*00b67f09SDavid van Moolenbroek 			 * ACL onto the elements list; otherwise
733*00b67f09SDavid van Moolenbroek 			 * merge it into *this* ACL.  We nest ACLs
734*00b67f09SDavid van Moolenbroek 			 * in two cases: 1) sortlist, 2) if the
735*00b67f09SDavid van Moolenbroek 			 * nested ACL contains negated members.
736*00b67f09SDavid van Moolenbroek 			 */
737*00b67f09SDavid van Moolenbroek 			if (inneracl != NULL)
738*00b67f09SDavid van Moolenbroek 				dns_acl_detach(&inneracl);
739*00b67f09SDavid van Moolenbroek 			result = cfg_acl_fromconfig(ce, cctx, lctx,
740*00b67f09SDavid van Moolenbroek 						    ctx, mctx, new_nest_level,
741*00b67f09SDavid van Moolenbroek 						    &inneracl);
742*00b67f09SDavid van Moolenbroek 			if (result != ISC_R_SUCCESS)
743*00b67f09SDavid van Moolenbroek 				goto cleanup;
744*00b67f09SDavid van Moolenbroek nested_acl:
745*00b67f09SDavid van Moolenbroek 			if (nest_level > 0 || inneracl->has_negatives) {
746*00b67f09SDavid van Moolenbroek 				INSIST(dacl->length < dacl->alloc);
747*00b67f09SDavid van Moolenbroek 				de->type = dns_aclelementtype_nestedacl;
748*00b67f09SDavid van Moolenbroek 				de->negative = neg;
749*00b67f09SDavid van Moolenbroek 				if (de->nestedacl != NULL)
750*00b67f09SDavid van Moolenbroek 					dns_acl_detach(&de->nestedacl);
751*00b67f09SDavid van Moolenbroek 				dns_acl_attach(inneracl,
752*00b67f09SDavid van Moolenbroek 					       &de->nestedacl);
753*00b67f09SDavid van Moolenbroek 				dns_acl_detach(&inneracl);
754*00b67f09SDavid van Moolenbroek 				/* Fall through. */
755*00b67f09SDavid van Moolenbroek 			} else {
756*00b67f09SDavid van Moolenbroek 				INSIST(dacl->length + inneracl->length
757*00b67f09SDavid van Moolenbroek 				       <= dacl->alloc);
758*00b67f09SDavid van Moolenbroek 				dns_acl_merge(dacl, inneracl,
759*00b67f09SDavid van Moolenbroek 					      ISC_TF(!neg));
760*00b67f09SDavid van Moolenbroek 				de += inneracl->length;  /* elements added */
761*00b67f09SDavid van Moolenbroek 				dns_acl_detach(&inneracl);
762*00b67f09SDavid van Moolenbroek 				INSIST(dacl->length <= dacl->alloc);
763*00b67f09SDavid van Moolenbroek 				continue;
764*00b67f09SDavid van Moolenbroek 			}
765*00b67f09SDavid van Moolenbroek 		} else if (cfg_obj_istype(ce, &cfg_type_keyref)) {
766*00b67f09SDavid van Moolenbroek 			/* Key name. */
767*00b67f09SDavid van Moolenbroek 			INSIST(dacl->length < dacl->alloc);
768*00b67f09SDavid van Moolenbroek 			de->type = dns_aclelementtype_keyname;
769*00b67f09SDavid van Moolenbroek 			de->negative = neg;
770*00b67f09SDavid van Moolenbroek 			dns_name_init(&de->keyname, NULL);
771*00b67f09SDavid van Moolenbroek 			result = convert_keyname(ce, lctx, mctx,
772*00b67f09SDavid van Moolenbroek 						 &de->keyname);
773*00b67f09SDavid van Moolenbroek 			if (result != ISC_R_SUCCESS)
774*00b67f09SDavid van Moolenbroek 				goto cleanup;
775*00b67f09SDavid van Moolenbroek #ifdef HAVE_GEOIP
776*00b67f09SDavid van Moolenbroek 		} else if (cfg_obj_istuple(ce) &&
777*00b67f09SDavid van Moolenbroek 			   cfg_obj_isvoid(cfg_tuple_get(ce, "negated")))
778*00b67f09SDavid van Moolenbroek 		{
779*00b67f09SDavid van Moolenbroek 			INSIST(dacl->length < dacl->alloc);
780*00b67f09SDavid van Moolenbroek 			result = parse_geoip_element(ce, lctx, ctx, de);
781*00b67f09SDavid van Moolenbroek 			if (result != ISC_R_SUCCESS)
782*00b67f09SDavid van Moolenbroek 				goto cleanup;
783*00b67f09SDavid van Moolenbroek 			de->type = dns_aclelementtype_geoip;
784*00b67f09SDavid van Moolenbroek 			de->negative = neg;
785*00b67f09SDavid van Moolenbroek #endif /* HAVE_GEOIP */
786*00b67f09SDavid van Moolenbroek 		} else if (cfg_obj_isstring(ce)) {
787*00b67f09SDavid van Moolenbroek 			/* ACL name. */
788*00b67f09SDavid van Moolenbroek 			const char *name = cfg_obj_asstring(ce);
789*00b67f09SDavid van Moolenbroek 			if (strcasecmp(name, "any") == 0) {
790*00b67f09SDavid van Moolenbroek 				/* Iptable entry with zero bit length. */
791*00b67f09SDavid van Moolenbroek 				result = dns_iptable_addprefix(iptab, NULL, 0,
792*00b67f09SDavid van Moolenbroek 					      ISC_TF(nest_level != 0 || !neg));
793*00b67f09SDavid van Moolenbroek 				if (result != ISC_R_SUCCESS)
794*00b67f09SDavid van Moolenbroek 					goto cleanup;
795*00b67f09SDavid van Moolenbroek 
796*00b67f09SDavid van Moolenbroek 				if (nest_level != 0) {
797*00b67f09SDavid van Moolenbroek 					INSIST(dacl->length < dacl->alloc);
798*00b67f09SDavid van Moolenbroek 					de->type = dns_aclelementtype_nestedacl;
799*00b67f09SDavid van Moolenbroek 					de->negative = neg;
800*00b67f09SDavid van Moolenbroek 				} else
801*00b67f09SDavid van Moolenbroek 					continue;
802*00b67f09SDavid van Moolenbroek 			} else if (strcasecmp(name, "none") == 0) {
803*00b67f09SDavid van Moolenbroek 				/* none == !any */
804*00b67f09SDavid van Moolenbroek 				/*
805*00b67f09SDavid van Moolenbroek 				 * We don't unconditional set
806*00b67f09SDavid van Moolenbroek 				 * dacl->has_negatives and
807*00b67f09SDavid van Moolenbroek 				 * de->negative to true so we can handle
808*00b67f09SDavid van Moolenbroek 				 * "!none;".
809*00b67f09SDavid van Moolenbroek 				 */
810*00b67f09SDavid van Moolenbroek 				result = dns_iptable_addprefix(iptab, NULL, 0,
811*00b67f09SDavid van Moolenbroek 					      ISC_TF(nest_level != 0 || neg));
812*00b67f09SDavid van Moolenbroek 				if (result != ISC_R_SUCCESS)
813*00b67f09SDavid van Moolenbroek 					goto cleanup;
814*00b67f09SDavid van Moolenbroek 
815*00b67f09SDavid van Moolenbroek 				if (!neg)
816*00b67f09SDavid van Moolenbroek 					dacl->has_negatives = !neg;
817*00b67f09SDavid van Moolenbroek 
818*00b67f09SDavid van Moolenbroek 				if (nest_level != 0) {
819*00b67f09SDavid van Moolenbroek 					INSIST(dacl->length < dacl->alloc);
820*00b67f09SDavid van Moolenbroek 					de->type = dns_aclelementtype_nestedacl;
821*00b67f09SDavid van Moolenbroek 					de->negative = !neg;
822*00b67f09SDavid van Moolenbroek 				} else
823*00b67f09SDavid van Moolenbroek 					continue;
824*00b67f09SDavid van Moolenbroek 			} else if (strcasecmp(name, "localhost") == 0) {
825*00b67f09SDavid van Moolenbroek 				INSIST(dacl->length < dacl->alloc);
826*00b67f09SDavid van Moolenbroek 				de->type = dns_aclelementtype_localhost;
827*00b67f09SDavid van Moolenbroek 				de->negative = neg;
828*00b67f09SDavid van Moolenbroek 			} else if (strcasecmp(name, "localnets") == 0) {
829*00b67f09SDavid van Moolenbroek 				INSIST(dacl->length < dacl->alloc);
830*00b67f09SDavid van Moolenbroek 				de->type = dns_aclelementtype_localnets;
831*00b67f09SDavid van Moolenbroek 				de->negative = neg;
832*00b67f09SDavid van Moolenbroek 			} else {
833*00b67f09SDavid van Moolenbroek 				if (inneracl != NULL)
834*00b67f09SDavid van Moolenbroek 					dns_acl_detach(&inneracl);
835*00b67f09SDavid van Moolenbroek 				/*
836*00b67f09SDavid van Moolenbroek 				 * This call should just find the cached
837*00b67f09SDavid van Moolenbroek 				 * of the named acl.
838*00b67f09SDavid van Moolenbroek 				 */
839*00b67f09SDavid van Moolenbroek 				result = convert_named_acl(ce, cctx, lctx, ctx,
840*00b67f09SDavid van Moolenbroek 							   mctx, new_nest_level,
841*00b67f09SDavid van Moolenbroek 							   &inneracl);
842*00b67f09SDavid van Moolenbroek 				if (result != ISC_R_SUCCESS)
843*00b67f09SDavid van Moolenbroek 					goto cleanup;
844*00b67f09SDavid van Moolenbroek 
845*00b67f09SDavid van Moolenbroek 				goto nested_acl;
846*00b67f09SDavid van Moolenbroek 			}
847*00b67f09SDavid van Moolenbroek 		} else {
848*00b67f09SDavid van Moolenbroek 			cfg_obj_log(ce, lctx, ISC_LOG_WARNING,
849*00b67f09SDavid van Moolenbroek 				    "address match list contains "
850*00b67f09SDavid van Moolenbroek 				    "unsupported element type");
851*00b67f09SDavid van Moolenbroek 			result = ISC_R_FAILURE;
852*00b67f09SDavid van Moolenbroek 			goto cleanup;
853*00b67f09SDavid van Moolenbroek 		}
854*00b67f09SDavid van Moolenbroek 
855*00b67f09SDavid van Moolenbroek 		/*
856*00b67f09SDavid van Moolenbroek 		 * This should only be reached for localhost, localnets
857*00b67f09SDavid van Moolenbroek 		 * and keyname elements, and nested ACLs if nest_level is
858*00b67f09SDavid van Moolenbroek 		 * nonzero (i.e., in sortlists).
859*00b67f09SDavid van Moolenbroek 		 */
860*00b67f09SDavid van Moolenbroek 		if (de->nestedacl != NULL &&
861*00b67f09SDavid van Moolenbroek 		    de->type != dns_aclelementtype_nestedacl)
862*00b67f09SDavid van Moolenbroek 			dns_acl_detach(&de->nestedacl);
863*00b67f09SDavid van Moolenbroek 
864*00b67f09SDavid van Moolenbroek 		dacl->node_count++;
865*00b67f09SDavid van Moolenbroek 		de->node_num = dacl->node_count;
866*00b67f09SDavid van Moolenbroek 
867*00b67f09SDavid van Moolenbroek 		dacl->length++;
868*00b67f09SDavid van Moolenbroek 		de++;
869*00b67f09SDavid van Moolenbroek 		INSIST(dacl->length <= dacl->alloc);
870*00b67f09SDavid van Moolenbroek 	}
871*00b67f09SDavid van Moolenbroek 
872*00b67f09SDavid van Moolenbroek 	dns_acl_attach(dacl, target);
873*00b67f09SDavid van Moolenbroek 	result = ISC_R_SUCCESS;
874*00b67f09SDavid van Moolenbroek 
875*00b67f09SDavid van Moolenbroek  cleanup:
876*00b67f09SDavid van Moolenbroek 	if (inneracl != NULL)
877*00b67f09SDavid van Moolenbroek 		dns_acl_detach(&inneracl);
878*00b67f09SDavid van Moolenbroek 	dns_acl_detach(&dacl);
879*00b67f09SDavid van Moolenbroek 	return (result);
880*00b67f09SDavid van Moolenbroek }
881