1 /* $NetBSD: aclconf.c,v 1.8 2014/12/10 04:38:02 christos Exp $ */
4 * Copyright (C) 2004-2014 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 1999-2002 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
25 #include <isc/string.h> /* Required for HP/UX (and others?) */
28 #include <isccfg/namedconf.h>
29 #include <isccfg/aclconf.h>
32 #include <dns/iptable.h>
33 #include <dns/fixedname.h>
39 #endif /* HAVE_GEOIP */
41 #define LOOP_MAGIC ISC_MAGIC('L','O','O','P')
44 cfg_aclconfctx_create(isc_mem_t
*mctx
, cfg_aclconfctx_t
**ret
) {
46 cfg_aclconfctx_t
*actx
;
48 REQUIRE(mctx
!= NULL
);
49 REQUIRE(ret
!= NULL
&& *ret
== NULL
);
51 actx
= isc_mem_get(mctx
, sizeof(*actx
));
53 return (ISC_R_NOMEMORY
);
55 result
= isc_refcount_init(&actx
->references
, 1);
56 if (result
!= ISC_R_SUCCESS
)
60 isc_mem_attach(mctx
, &actx
->mctx
);
61 ISC_LIST_INIT(actx
->named_acl_cache
);
68 return (ISC_R_SUCCESS
);
71 isc_mem_put(mctx
, actx
, sizeof(*actx
));
76 cfg_aclconfctx_attach(cfg_aclconfctx_t
*src
, cfg_aclconfctx_t
**dest
) {
78 REQUIRE(dest
!= NULL
&& *dest
== NULL
);
80 isc_refcount_increment(&src
->references
, NULL
);
85 cfg_aclconfctx_detach(cfg_aclconfctx_t
**actxp
) {
86 cfg_aclconfctx_t
*actx
;
87 dns_acl_t
*dacl
, *next
;
90 REQUIRE(actxp
!= NULL
&& *actxp
!= NULL
);
94 isc_refcount_decrement(&actx
->references
, &refs
);
96 for (dacl
= ISC_LIST_HEAD(actx
->named_acl_cache
);
100 next
= ISC_LIST_NEXT(dacl
, nextincache
);
101 ISC_LIST_UNLINK(actx
->named_acl_cache
, dacl
,
103 dns_acl_detach(&dacl
);
105 isc_mem_putanddetach(&actx
->mctx
, actx
, sizeof(*actx
));
112 * Find the definition of the named acl whose name is "name".
115 get_acl_def(const cfg_obj_t
*cctx
, const char *name
, const cfg_obj_t
**ret
) {
117 const cfg_obj_t
*acls
= NULL
;
118 const cfg_listelt_t
*elt
;
120 result
= cfg_map_get(cctx
, "acl", &acls
);
121 if (result
!= ISC_R_SUCCESS
)
123 for (elt
= cfg_list_first(acls
);
125 elt
= cfg_list_next(elt
)) {
126 const cfg_obj_t
*acl
= cfg_listelt_value(elt
);
127 const char *aclname
= cfg_obj_asstring(cfg_tuple_get(acl
, "name"));
128 if (strcasecmp(aclname
, name
) == 0) {
130 *ret
= cfg_tuple_get(acl
, "value");
132 return (ISC_R_SUCCESS
);
135 return (ISC_R_NOTFOUND
);
139 convert_named_acl(const cfg_obj_t
*nameobj
, const cfg_obj_t
*cctx
,
140 isc_log_t
*lctx
, cfg_aclconfctx_t
*ctx
,
141 isc_mem_t
*mctx
, unsigned int nest_level
,
145 const cfg_obj_t
*cacl
= NULL
;
148 const char *aclname
= cfg_obj_asstring(nameobj
);
150 /* Look for an already-converted version. */
151 for (dacl
= ISC_LIST_HEAD(ctx
->named_acl_cache
);
153 dacl
= ISC_LIST_NEXT(dacl
, nextincache
))
155 if (strcasecmp(aclname
, dacl
->name
) == 0) {
156 if (ISC_MAGIC_VALID(dacl
, LOOP_MAGIC
)) {
157 cfg_obj_log(nameobj
, lctx
, ISC_LOG_ERROR
,
158 "acl loop detected: %s", aclname
);
159 return (ISC_R_FAILURE
);
161 dns_acl_attach(dacl
, target
);
162 return (ISC_R_SUCCESS
);
165 /* Not yet converted. Convert now. */
166 result
= get_acl_def(cctx
, aclname
, &cacl
);
167 if (result
!= ISC_R_SUCCESS
) {
168 cfg_obj_log(nameobj
, lctx
, ISC_LOG_WARNING
,
169 "undefined ACL '%s'", aclname
);
173 * Add a loop detection element.
175 memset(&loop
, 0, sizeof(loop
));
176 ISC_LINK_INIT(&loop
, nextincache
);
177 DE_CONST(aclname
, loop
.name
);
178 loop
.magic
= LOOP_MAGIC
;
179 ISC_LIST_APPEND(ctx
->named_acl_cache
, &loop
, nextincache
);
180 result
= cfg_acl_fromconfig(cacl
, cctx
, lctx
, ctx
, mctx
,
182 ISC_LIST_UNLINK(ctx
->named_acl_cache
, &loop
, nextincache
);
185 if (result
!= ISC_R_SUCCESS
)
187 dacl
->name
= isc_mem_strdup(dacl
->mctx
, aclname
);
188 if (dacl
->name
== NULL
)
189 return (ISC_R_NOMEMORY
);
190 ISC_LIST_APPEND(ctx
->named_acl_cache
, dacl
, nextincache
);
191 dns_acl_attach(dacl
, target
);
192 return (ISC_R_SUCCESS
);
196 convert_keyname(const cfg_obj_t
*keyobj
, isc_log_t
*lctx
, isc_mem_t
*mctx
,
201 dns_fixedname_t fixname
;
203 const char *txtname
= cfg_obj_asstring(keyobj
);
205 keylen
= strlen(txtname
);
206 isc_buffer_constinit(&buf
, txtname
, keylen
);
207 isc_buffer_add(&buf
, keylen
);
208 dns_fixedname_init(&fixname
);
209 result
= dns_name_fromtext(dns_fixedname_name(&fixname
), &buf
,
210 dns_rootname
, 0, NULL
);
211 if (result
!= ISC_R_SUCCESS
) {
212 cfg_obj_log(keyobj
, lctx
, ISC_LOG_WARNING
,
213 "key name '%s' is not a valid domain name",
217 return (dns_name_dup(dns_fixedname_name(&fixname
), mctx
, dnsname
));
221 * Recursively pre-parse an ACL definition to find the total number
222 * of non-IP-prefix elements (localhost, localnets, key) in all nested
223 * ACLs, so that the parent will have enough space allocated for the
224 * elements table after all the nested ACLs have been merged in to the
228 count_acl_elements(const cfg_obj_t
*caml
, const cfg_obj_t
*cctx
,
229 isc_log_t
*lctx
, cfg_aclconfctx_t
*ctx
, isc_mem_t
*mctx
,
230 isc_uint32_t
*count
, isc_boolean_t
*has_negative
)
232 const cfg_listelt_t
*elt
;
236 REQUIRE(count
!= NULL
);
238 if (has_negative
!= NULL
)
239 *has_negative
= ISC_FALSE
;
241 for (elt
= cfg_list_first(caml
);
243 elt
= cfg_list_next(elt
)) {
244 const cfg_obj_t
*ce
= cfg_listelt_value(elt
);
246 /* might be a negated element, in which case get the value. */
247 if (cfg_obj_istuple(ce
)) {
248 const cfg_obj_t
*negated
=
249 cfg_tuple_get(ce
, "negated");
250 if (! cfg_obj_isvoid(negated
)) {
252 if (has_negative
!= NULL
)
253 *has_negative
= ISC_TRUE
;
257 if (cfg_obj_istype(ce
, &cfg_type_keyref
)) {
259 } else if (cfg_obj_islist(ce
)) {
260 isc_boolean_t negative
;
262 result
= count_acl_elements(ce
, cctx
, lctx
, ctx
, mctx
,
264 if (result
!= ISC_R_SUCCESS
)
270 } else if (cfg_obj_istuple(ce
) &&
271 cfg_obj_isvoid(cfg_tuple_get(ce
, "negated")))
274 #endif /* HAVE_GEOIP */
275 } else if (cfg_obj_isstring(ce
)) {
276 const char *name
= cfg_obj_asstring(ce
);
277 if (strcasecmp(name
, "localhost") == 0 ||
278 strcasecmp(name
, "localnets") == 0) {
280 } else if (strcasecmp(name
, "any") != 0 &&
281 strcasecmp(name
, "none") != 0) {
282 dns_acl_t
*inneracl
= NULL
;
284 * Convert any named acls we reference now if
285 * they have not already been converted.
287 result
= convert_named_acl(ce
, cctx
, lctx
, ctx
,
289 if (result
== ISC_R_SUCCESS
) {
290 if (inneracl
->has_negatives
)
293 n
+= inneracl
->length
;
294 dns_acl_detach(&inneracl
);
302 return (ISC_R_SUCCESS
);
306 static dns_geoip_subtype_t
307 get_subtype(const cfg_obj_t
*obj
, isc_log_t
*lctx
,
308 dns_geoip_subtype_t subtype
, const char *dbname
)
314 case dns_geoip_countrycode
:
315 if (strcasecmp(dbname
, "city") == 0)
316 return (dns_geoip_city_countrycode
);
317 else if (strcasecmp(dbname
, "region") == 0)
318 return (dns_geoip_region_countrycode
);
319 else if (strcasecmp(dbname
, "country") == 0)
320 return (dns_geoip_country_code
);
321 cfg_obj_log(obj
, lctx
, ISC_LOG_ERROR
,
322 "invalid GeoIP DB specified for "
323 "country search: ignored");
325 case dns_geoip_countrycode3
:
326 if (strcasecmp(dbname
, "city") == 0)
327 return (dns_geoip_city_countrycode3
);
328 else if (strcasecmp(dbname
, "country") == 0)
329 return (dns_geoip_country_code3
);
330 cfg_obj_log(obj
, lctx
, ISC_LOG_ERROR
,
331 "invalid GeoIP DB specified for "
332 "country search: ignored");
334 case dns_geoip_countryname
:
335 if (strcasecmp(dbname
, "city") == 0)
336 return (dns_geoip_city_countryname
);
337 else if (strcasecmp(dbname
, "country") == 0)
338 return (dns_geoip_country_name
);
339 cfg_obj_log(obj
, lctx
, ISC_LOG_ERROR
,
340 "invalid GeoIP DB specified for "
341 "country search: ignored");
343 case dns_geoip_region
:
344 if (strcasecmp(dbname
, "city") == 0)
345 return (dns_geoip_city_region
);
346 else if (strcasecmp(dbname
, "region") == 0)
347 return (dns_geoip_region_code
);
348 cfg_obj_log(obj
, lctx
, ISC_LOG_ERROR
,
349 "invalid GeoIP DB specified for "
350 "region search: ignored");
352 case dns_geoip_regionname
:
353 if (strcasecmp(dbname
, "city") == 0)
354 return (dns_geoip_city_region
);
355 else if (strcasecmp(dbname
, "region") == 0)
356 return (dns_geoip_region_name
);
357 cfg_obj_log(obj
, lctx
, ISC_LOG_ERROR
,
358 "invalid GeoIP DB specified for "
359 "region search: ignored");
363 * Log a warning if the wrong database was specified
364 * on an unambiguous query
366 case dns_geoip_city_name
:
367 case dns_geoip_city_postalcode
:
368 case dns_geoip_city_metrocode
:
369 case dns_geoip_city_areacode
:
370 case dns_geoip_city_continentcode
:
371 case dns_geoip_city_timezonecode
:
372 if (strcasecmp(dbname
, "city") != 0)
373 cfg_obj_log(obj
, lctx
, ISC_LOG_WARNING
,
374 "invalid GeoIP DB specified for "
375 "a 'city'-only search type: ignoring");
377 case dns_geoip_isp_name
:
378 if (strcasecmp(dbname
, "isp") != 0)
379 cfg_obj_log(obj
, lctx
, ISC_LOG_WARNING
,
380 "invalid GeoIP DB specified for "
381 "an 'isp' search: ignoring");
383 case dns_geoip_org_name
:
384 if (strcasecmp(dbname
, "org") != 0)
385 cfg_obj_log(obj
, lctx
, ISC_LOG_WARNING
,
386 "invalid GeoIP DB specified for "
387 "an 'org' search: ignoring");
389 case dns_geoip_as_asnum
:
390 if (strcasecmp(dbname
, "asnum") != 0)
391 cfg_obj_log(obj
, lctx
, ISC_LOG_WARNING
,
392 "invalid GeoIP DB specified for "
393 "an 'asnum' search: ignoring");
395 case dns_geoip_domain_name
:
396 if (strcasecmp(dbname
, "domain") != 0)
397 cfg_obj_log(obj
, lctx
, ISC_LOG_WARNING
,
398 "invalid GeoIP DB specified for "
399 "a 'domain' search: ignoring");
401 case dns_geoip_netspeed_id
:
402 if (strcasecmp(dbname
, "netspeed") != 0)
403 cfg_obj_log(obj
, lctx
, ISC_LOG_WARNING
,
404 "invalid GeoIP DB specified for "
405 "a 'netspeed' search: ignoring");
413 geoip_can_answer(dns_aclelement_t
*elt
, cfg_aclconfctx_t
*ctx
) {
414 if (ctx
->geoip
== NULL
)
417 switch (elt
->geoip_elem
.subtype
) {
418 case dns_geoip_countrycode
:
419 case dns_geoip_countrycode3
:
420 case dns_geoip_countryname
:
421 if (ctx
->geoip
->city_v4
!= NULL
||
422 ctx
->geoip
->city_v6
!= NULL
||
423 ctx
->geoip
->country_v4
!= NULL
||
424 ctx
->geoip
->country_v6
!= NULL
||
425 ctx
->geoip
->region
!= NULL
)
427 case dns_geoip_region
:
428 case dns_geoip_regionname
:
429 if (ctx
->geoip
->city_v4
!= NULL
||
430 ctx
->geoip
->city_v6
!= NULL
||
431 ctx
->geoip
->region
!= NULL
)
433 case dns_geoip_country_code
:
434 case dns_geoip_country_code3
:
435 case dns_geoip_country_name
:
436 if (ctx
->geoip
->country_v4
!= NULL
||
437 ctx
->geoip
->country_v6
!= NULL
)
439 case dns_geoip_region_countrycode
:
440 case dns_geoip_region_code
:
441 case dns_geoip_region_name
:
442 if (ctx
->geoip
->region
!= NULL
)
444 case dns_geoip_city_countrycode
:
445 case dns_geoip_city_countrycode3
:
446 case dns_geoip_city_countryname
:
447 case dns_geoip_city_region
:
448 case dns_geoip_city_regionname
:
449 case dns_geoip_city_name
:
450 case dns_geoip_city_postalcode
:
451 case dns_geoip_city_metrocode
:
452 case dns_geoip_city_areacode
:
453 case dns_geoip_city_continentcode
:
454 case dns_geoip_city_timezonecode
:
455 if (ctx
->geoip
->city_v4
!= NULL
||
456 ctx
->geoip
->city_v6
!= NULL
)
458 case dns_geoip_isp_name
:
459 if (ctx
->geoip
->isp
!= NULL
)
461 case dns_geoip_org_name
:
462 if (ctx
->geoip
->org
!= NULL
)
464 case dns_geoip_as_asnum
:
465 if (ctx
->geoip
->as
!= NULL
)
467 case dns_geoip_domain_name
:
468 if (ctx
->geoip
->domain
!= NULL
)
470 case dns_geoip_netspeed_id
:
471 if (ctx
->geoip
->netspeed
!= NULL
)
479 parse_geoip_element(const cfg_obj_t
*obj
, isc_log_t
*lctx
,
480 cfg_aclconfctx_t
*ctx
, dns_aclelement_t
*dep
)
483 const char *dbname
= NULL
;
484 const char *stype
, *search
;
485 dns_geoip_subtype_t subtype
;
489 REQUIRE(dep
!= NULL
);
493 ge
= cfg_tuple_get(obj
, "db");
494 if (!cfg_obj_isvoid(ge
))
495 dbname
= cfg_obj_asstring(ge
);
497 stype
= cfg_obj_asstring(cfg_tuple_get(obj
, "subtype"));
498 search
= cfg_obj_asstring(cfg_tuple_get(obj
, "search"));
499 len
= strlen(search
);
502 cfg_obj_log(obj
, lctx
, ISC_LOG_ERROR
,
503 "zero-length geoip search field");
504 return (ISC_R_FAILURE
);
507 if (strcasecmp(stype
, "country") == 0 && len
== 2) {
508 /* Two-letter country code */
509 subtype
= dns_geoip_countrycode
;
510 strlcpy(de
.geoip_elem
.as_string
, search
,
511 sizeof(de
.geoip_elem
.as_string
));
512 } else if (strcasecmp(stype
, "country") == 0 && len
== 3) {
513 /* Three-letter country code */
514 subtype
= dns_geoip_countrycode3
;
515 strlcpy(de
.geoip_elem
.as_string
, search
,
516 sizeof(de
.geoip_elem
.as_string
));
517 } else if (strcasecmp(stype
, "country") == 0) {
519 subtype
= dns_geoip_countryname
;
520 strlcpy(de
.geoip_elem
.as_string
, search
,
521 sizeof(de
.geoip_elem
.as_string
));
522 } else if (strcasecmp(stype
, "region") == 0 && len
== 2) {
523 /* Two-letter region code */
524 subtype
= dns_geoip_region
;
525 strlcpy(de
.geoip_elem
.as_string
, search
,
526 sizeof(de
.geoip_elem
.as_string
));
527 } else if (strcasecmp(stype
, "region") == 0) {
529 subtype
= dns_geoip_regionname
;
530 strlcpy(de
.geoip_elem
.as_string
, search
,
531 sizeof(de
.geoip_elem
.as_string
));
532 } else if (strcasecmp(stype
, "city") == 0) {
534 subtype
= dns_geoip_city_name
;
535 strlcpy(de
.geoip_elem
.as_string
, search
,
536 sizeof(de
.geoip_elem
.as_string
));
537 } else if (strcasecmp(stype
, "postal") == 0 && len
< 7) {
538 subtype
= dns_geoip_city_postalcode
;
539 strlcpy(de
.geoip_elem
.as_string
, search
,
540 sizeof(de
.geoip_elem
.as_string
));
541 } else if (strcasecmp(stype
, "postal") == 0) {
542 cfg_obj_log(obj
, lctx
, ISC_LOG_ERROR
,
543 "geoiop postal code (%s) too long", search
);
544 return (ISC_R_FAILURE
);
545 } else if (strcasecmp(stype
, "metro") == 0) {
546 subtype
= dns_geoip_city_metrocode
;
547 de
.geoip_elem
.as_int
= atoi(search
);
548 } else if (strcasecmp(stype
, "area") == 0) {
549 subtype
= dns_geoip_city_areacode
;
550 de
.geoip_elem
.as_int
= atoi(search
);
551 } else if (strcasecmp(stype
, "tz") == 0) {
552 subtype
= dns_geoip_city_timezonecode
;
553 strlcpy(de
.geoip_elem
.as_string
, search
,
554 sizeof(de
.geoip_elem
.as_string
));
555 } else if (strcasecmp(stype
, "continent") == 0 && len
== 2) {
556 /* Two-letter continent code */
557 subtype
= dns_geoip_city_continentcode
;
558 strlcpy(de
.geoip_elem
.as_string
, search
,
559 sizeof(de
.geoip_elem
.as_string
));
560 } else if (strcasecmp(stype
, "continent") == 0) {
561 cfg_obj_log(obj
, lctx
, ISC_LOG_ERROR
,
562 "geoiop continent code (%s) too long", search
);
563 return (ISC_R_FAILURE
);
564 } else if (strcasecmp(stype
, "isp") == 0) {
565 subtype
= dns_geoip_isp_name
;
566 strlcpy(de
.geoip_elem
.as_string
, search
,
567 sizeof(de
.geoip_elem
.as_string
));
568 } else if (strcasecmp(stype
, "asnum") == 0) {
569 subtype
= dns_geoip_as_asnum
;
570 strlcpy(de
.geoip_elem
.as_string
, search
,
571 sizeof(de
.geoip_elem
.as_string
));
572 } else if (strcasecmp(stype
, "org") == 0) {
573 subtype
= dns_geoip_org_name
;
574 strlcpy(de
.geoip_elem
.as_string
, search
,
575 sizeof(de
.geoip_elem
.as_string
));
576 } else if (strcasecmp(stype
, "domain") == 0) {
577 subtype
= dns_geoip_domain_name
;
578 strlcpy(de
.geoip_elem
.as_string
, search
,
579 sizeof(de
.geoip_elem
.as_string
));
580 } else if (strcasecmp(stype
, "netspeed") == 0) {
581 subtype
= dns_geoip_netspeed_id
;
582 de
.geoip_elem
.as_int
= atoi(search
);
586 de
.geoip_elem
.subtype
= get_subtype(obj
, lctx
, subtype
, dbname
);
588 if (! geoip_can_answer(&de
, ctx
)) {
589 cfg_obj_log(obj
, lctx
, ISC_LOG_ERROR
,
590 "no GeoIP database installed which can answer "
591 "queries of type '%s'", stype
);
592 return (ISC_R_FAILURE
);
597 return (ISC_R_SUCCESS
);
602 cfg_acl_fromconfig(const cfg_obj_t
*caml
, const cfg_obj_t
*cctx
,
603 isc_log_t
*lctx
, cfg_aclconfctx_t
*ctx
,
604 isc_mem_t
*mctx
, unsigned int nest_level
,
607 return (cfg_acl_fromconfig2(caml
, cctx
, lctx
, ctx
, mctx
,
608 nest_level
, 0, target
));
612 cfg_acl_fromconfig2(const cfg_obj_t
*caml
, const cfg_obj_t
*cctx
,
613 isc_log_t
*lctx
, cfg_aclconfctx_t
*ctx
,
614 isc_mem_t
*mctx
, unsigned int nest_level
,
615 isc_uint16_t family
, dns_acl_t
**target
)
618 dns_acl_t
*dacl
= NULL
, *inneracl
= NULL
;
619 dns_aclelement_t
*de
;
620 const cfg_listelt_t
*elt
;
621 dns_iptable_t
*iptab
;
622 int new_nest_level
= 0;
625 new_nest_level
= nest_level
- 1;
627 REQUIRE(target
!= NULL
);
628 REQUIRE(*target
== NULL
|| DNS_ACL_VALID(*target
));
630 if (*target
!= NULL
) {
632 * If target already points to an ACL, then we're being
633 * called recursively to configure a nested ACL. The
634 * nested ACL's contents should just be absorbed into its
637 dns_acl_attach(*target
, &dacl
);
638 dns_acl_detach(target
);
641 * Need to allocate a new ACL structure. Count the items
642 * in the ACL definition that will require space in the
643 * elements table. (Note that if nest_level is nonzero,
644 * *everything* goes in the elements table.)
648 if (nest_level
== 0) {
649 result
= count_acl_elements(caml
, cctx
, lctx
, ctx
,
651 if (result
!= ISC_R_SUCCESS
)
654 nelem
= cfg_list_length(caml
, ISC_FALSE
);
656 result
= dns_acl_create(mctx
, nelem
, &dacl
);
657 if (result
!= ISC_R_SUCCESS
)
662 for (elt
= cfg_list_first(caml
);
664 elt
= cfg_list_next(elt
)) {
665 const cfg_obj_t
*ce
= cfg_listelt_value(elt
);
666 isc_boolean_t neg
= ISC_FALSE
;
668 INSIST(dacl
->length
<= dacl
->alloc
);
670 if (cfg_obj_istuple(ce
)) {
671 /* Might be a negated element */
672 const cfg_obj_t
*negated
=
673 cfg_tuple_get(ce
, "negated");
674 if (! cfg_obj_isvoid(negated
)) {
676 dacl
->has_negatives
= ISC_TRUE
;
682 * If nest_level is nonzero, then every element is
683 * to be stored as a separate, nested ACL rather than
684 * merged into the main iptable.
686 iptab
= dacl
->iptable
;
688 if (nest_level
!= 0) {
689 result
= dns_acl_create(mctx
,
690 cfg_list_length(ce
, ISC_FALSE
),
692 if (result
!= ISC_R_SUCCESS
)
694 iptab
= de
->nestedacl
->iptable
;
697 if (cfg_obj_isnetprefix(ce
)) {
702 cfg_obj_asnetprefix(ce
, &addr
, &bitlen
);
703 if (family
!= 0 && family
!= addr
.family
) {
704 char buf
[ISC_NETADDR_FORMATSIZE
+ 1];
705 isc_netaddr_format(&addr
, buf
, sizeof(buf
));
706 cfg_obj_log(ce
, lctx
, ISC_LOG_WARNING
,
707 "'%s': incorrect address family; "
710 dns_acl_detach(&de
->nestedacl
);
715 * If nesting ACLs (nest_level != 0), we negate
716 * the nestedacl element, not the iptable entry.
718 result
= dns_iptable_addprefix(iptab
, &addr
, bitlen
,
719 ISC_TF(nest_level
!= 0 || !neg
));
720 if (result
!= ISC_R_SUCCESS
)
723 if (nest_level
> 0) {
724 INSIST(dacl
->length
< dacl
->alloc
);
725 de
->type
= dns_aclelementtype_nestedacl
;
729 } else if (cfg_obj_islist(ce
)) {
731 * If we're nesting ACLs, put the nested
732 * ACL onto the elements list; otherwise
733 * merge it into *this* ACL. We nest ACLs
734 * in two cases: 1) sortlist, 2) if the
735 * nested ACL contains negated members.
737 if (inneracl
!= NULL
)
738 dns_acl_detach(&inneracl
);
739 result
= cfg_acl_fromconfig(ce
, cctx
, lctx
,
740 ctx
, mctx
, new_nest_level
,
742 if (result
!= ISC_R_SUCCESS
)
745 if (nest_level
> 0 || inneracl
->has_negatives
) {
746 INSIST(dacl
->length
< dacl
->alloc
);
747 de
->type
= dns_aclelementtype_nestedacl
;
749 if (de
->nestedacl
!= NULL
)
750 dns_acl_detach(&de
->nestedacl
);
751 dns_acl_attach(inneracl
,
753 dns_acl_detach(&inneracl
);
756 INSIST(dacl
->length
+ inneracl
->length
758 dns_acl_merge(dacl
, inneracl
,
760 de
+= inneracl
->length
; /* elements added */
761 dns_acl_detach(&inneracl
);
762 INSIST(dacl
->length
<= dacl
->alloc
);
765 } else if (cfg_obj_istype(ce
, &cfg_type_keyref
)) {
767 INSIST(dacl
->length
< dacl
->alloc
);
768 de
->type
= dns_aclelementtype_keyname
;
770 dns_name_init(&de
->keyname
, NULL
);
771 result
= convert_keyname(ce
, lctx
, mctx
,
773 if (result
!= ISC_R_SUCCESS
)
776 } else if (cfg_obj_istuple(ce
) &&
777 cfg_obj_isvoid(cfg_tuple_get(ce
, "negated")))
779 INSIST(dacl
->length
< dacl
->alloc
);
780 result
= parse_geoip_element(ce
, lctx
, ctx
, de
);
781 if (result
!= ISC_R_SUCCESS
)
783 de
->type
= dns_aclelementtype_geoip
;
785 #endif /* HAVE_GEOIP */
786 } else if (cfg_obj_isstring(ce
)) {
788 const char *name
= cfg_obj_asstring(ce
);
789 if (strcasecmp(name
, "any") == 0) {
790 /* Iptable entry with zero bit length. */
791 result
= dns_iptable_addprefix(iptab
, NULL
, 0,
792 ISC_TF(nest_level
!= 0 || !neg
));
793 if (result
!= ISC_R_SUCCESS
)
796 if (nest_level
!= 0) {
797 INSIST(dacl
->length
< dacl
->alloc
);
798 de
->type
= dns_aclelementtype_nestedacl
;
802 } else if (strcasecmp(name
, "none") == 0) {
805 * We don't unconditional set
806 * dacl->has_negatives and
807 * de->negative to true so we can handle
810 result
= dns_iptable_addprefix(iptab
, NULL
, 0,
811 ISC_TF(nest_level
!= 0 || neg
));
812 if (result
!= ISC_R_SUCCESS
)
816 dacl
->has_negatives
= !neg
;
818 if (nest_level
!= 0) {
819 INSIST(dacl
->length
< dacl
->alloc
);
820 de
->type
= dns_aclelementtype_nestedacl
;
824 } else if (strcasecmp(name
, "localhost") == 0) {
825 INSIST(dacl
->length
< dacl
->alloc
);
826 de
->type
= dns_aclelementtype_localhost
;
828 } else if (strcasecmp(name
, "localnets") == 0) {
829 INSIST(dacl
->length
< dacl
->alloc
);
830 de
->type
= dns_aclelementtype_localnets
;
833 if (inneracl
!= NULL
)
834 dns_acl_detach(&inneracl
);
836 * This call should just find the cached
839 result
= convert_named_acl(ce
, cctx
, lctx
, ctx
,
840 mctx
, new_nest_level
,
842 if (result
!= ISC_R_SUCCESS
)
848 cfg_obj_log(ce
, lctx
, ISC_LOG_WARNING
,
849 "address match list contains "
850 "unsupported element type");
851 result
= ISC_R_FAILURE
;
856 * This should only be reached for localhost, localnets
857 * and keyname elements, and nested ACLs if nest_level is
858 * nonzero (i.e., in sortlists).
860 if (de
->nestedacl
!= NULL
&&
861 de
->type
!= dns_aclelementtype_nestedacl
)
862 dns_acl_detach(&de
->nestedacl
);
865 de
->node_num
= dacl
->node_count
;
869 INSIST(dacl
->length
<= dacl
->alloc
);
872 dns_acl_attach(dacl
, target
);
873 result
= ISC_R_SUCCESS
;
876 if (inneracl
!= NULL
)
877 dns_acl_detach(&inneracl
);
878 dns_acl_detach(&dacl
);