00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <config.h>
00021
00022 #include <isc/mem.h>
00023 #include <isc/string.h>
00024 #include <isc/util.h>
00025
00026 #include <isccfg/namedconf.h>
00027 #include <isccfg/aclconf.h>
00028
00029 #include <dns/acl.h>
00030 #include <dns/iptable.h>
00031 #include <dns/fixedname.h>
00032 #include <dns/log.h>
00033
00034 #ifdef HAVE_GEOIP
00035 #include <stdlib.h>
00036 #include <math.h>
00037 #endif
00038
00039 #define LOOP_MAGIC ISC_MAGIC('L','O','O','P')
00040
00041 isc_result_t
00042 cfg_aclconfctx_create(isc_mem_t *mctx, cfg_aclconfctx_t **ret) {
00043 isc_result_t result;
00044 cfg_aclconfctx_t *actx;
00045
00046 REQUIRE(mctx != NULL);
00047 REQUIRE(ret != NULL && *ret == NULL);
00048
00049 actx = isc_mem_get(mctx, sizeof(*actx));
00050 if (actx == NULL)
00051 return (ISC_R_NOMEMORY);
00052
00053 result = isc_refcount_init(&actx->references, 1);
00054 if (result != ISC_R_SUCCESS)
00055 goto cleanup;
00056
00057 actx->mctx = NULL;
00058 isc_mem_attach(mctx, &actx->mctx);
00059 ISC_LIST_INIT(actx->named_acl_cache);
00060
00061 #ifdef HAVE_GEOIP
00062 actx->geoip = NULL;
00063 #endif
00064
00065 *ret = actx;
00066 return (ISC_R_SUCCESS);
00067
00068 cleanup:
00069 isc_mem_put(mctx, actx, sizeof(*actx));
00070 return (result);
00071 }
00072
00073 void
00074 cfg_aclconfctx_attach(cfg_aclconfctx_t *src, cfg_aclconfctx_t **dest) {
00075 REQUIRE(src != NULL);
00076 REQUIRE(dest != NULL && *dest == NULL);
00077
00078 isc_refcount_increment(&src->references, NULL);
00079 *dest = src;
00080 }
00081
00082 void
00083 cfg_aclconfctx_detach(cfg_aclconfctx_t **actxp) {
00084 cfg_aclconfctx_t *actx;
00085 dns_acl_t *dacl, *next;
00086 unsigned int refs;
00087
00088 REQUIRE(actxp != NULL && *actxp != NULL);
00089
00090 actx = *actxp;
00091
00092 isc_refcount_decrement(&actx->references, &refs);
00093 if (refs == 0) {
00094 for (dacl = ISC_LIST_HEAD(actx->named_acl_cache);
00095 dacl != NULL;
00096 dacl = next)
00097 {
00098 next = ISC_LIST_NEXT(dacl, nextincache);
00099 ISC_LIST_UNLINK(actx->named_acl_cache, dacl,
00100 nextincache);
00101 dns_acl_detach(&dacl);
00102 }
00103 isc_mem_putanddetach(&actx->mctx, actx, sizeof(*actx));
00104 }
00105
00106 *actxp = NULL;
00107 }
00108
00109
00110
00111
00112 static isc_result_t
00113 get_acl_def(const cfg_obj_t *cctx, const char *name, const cfg_obj_t **ret) {
00114 isc_result_t result;
00115 const cfg_obj_t *acls = NULL;
00116 const cfg_listelt_t *elt;
00117
00118 result = cfg_map_get(cctx, "acl", &acls);
00119 if (result != ISC_R_SUCCESS)
00120 return (result);
00121 for (elt = cfg_list_first(acls);
00122 elt != NULL;
00123 elt = cfg_list_next(elt)) {
00124 const cfg_obj_t *acl = cfg_listelt_value(elt);
00125 const char *aclname = cfg_obj_asstring(cfg_tuple_get(acl, "name"));
00126 if (strcasecmp(aclname, name) == 0) {
00127 if (ret != NULL) {
00128 *ret = cfg_tuple_get(acl, "value");
00129 }
00130 return (ISC_R_SUCCESS);
00131 }
00132 }
00133 return (ISC_R_NOTFOUND);
00134 }
00135
00136 static isc_result_t
00137 convert_named_acl(const cfg_obj_t *nameobj, const cfg_obj_t *cctx,
00138 isc_log_t *lctx, cfg_aclconfctx_t *ctx,
00139 isc_mem_t *mctx, unsigned int nest_level,
00140 dns_acl_t **target)
00141 {
00142 isc_result_t result;
00143 const cfg_obj_t *cacl = NULL;
00144 dns_acl_t *dacl;
00145 dns_acl_t loop;
00146 const char *aclname = cfg_obj_asstring(nameobj);
00147
00148
00149 for (dacl = ISC_LIST_HEAD(ctx->named_acl_cache);
00150 dacl != NULL;
00151 dacl = ISC_LIST_NEXT(dacl, nextincache))
00152 {
00153 if (strcasecmp(aclname, dacl->name) == 0) {
00154 if (ISC_MAGIC_VALID(dacl, LOOP_MAGIC)) {
00155 cfg_obj_log(nameobj, lctx, ISC_LOG_ERROR,
00156 "acl loop detected: %s", aclname);
00157 return (ISC_R_FAILURE);
00158 }
00159 dns_acl_attach(dacl, target);
00160 return (ISC_R_SUCCESS);
00161 }
00162 }
00163
00164 result = get_acl_def(cctx, aclname, &cacl);
00165 if (result != ISC_R_SUCCESS) {
00166 cfg_obj_log(nameobj, lctx, ISC_LOG_WARNING,
00167 "undefined ACL '%s'", aclname);
00168 return (result);
00169 }
00170
00171
00172
00173 memset(&loop, 0, sizeof(loop));
00174 ISC_LINK_INIT(&loop, nextincache);
00175 DE_CONST(aclname, loop.name);
00176 loop.magic = LOOP_MAGIC;
00177 ISC_LIST_APPEND(ctx->named_acl_cache, &loop, nextincache);
00178 result = cfg_acl_fromconfig(cacl, cctx, lctx, ctx, mctx,
00179 nest_level, &dacl);
00180 ISC_LIST_UNLINK(ctx->named_acl_cache, &loop, nextincache);
00181 loop.magic = 0;
00182 loop.name = NULL;
00183 if (result != ISC_R_SUCCESS)
00184 return (result);
00185 dacl->name = isc_mem_strdup(dacl->mctx, aclname);
00186 if (dacl->name == NULL)
00187 return (ISC_R_NOMEMORY);
00188 ISC_LIST_APPEND(ctx->named_acl_cache, dacl, nextincache);
00189 dns_acl_attach(dacl, target);
00190 return (ISC_R_SUCCESS);
00191 }
00192
00193 static isc_result_t
00194 convert_keyname(const cfg_obj_t *keyobj, isc_log_t *lctx, isc_mem_t *mctx,
00195 dns_name_t *dnsname)
00196 {
00197 isc_result_t result;
00198 isc_buffer_t buf;
00199 dns_fixedname_t fixname;
00200 unsigned int keylen;
00201 const char *txtname = cfg_obj_asstring(keyobj);
00202
00203 keylen = strlen(txtname);
00204 isc_buffer_constinit(&buf, txtname, keylen);
00205 isc_buffer_add(&buf, keylen);
00206 dns_fixedname_init(&fixname);
00207 result = dns_name_fromtext(dns_fixedname_name(&fixname), &buf,
00208 dns_rootname, 0, NULL);
00209 if (result != ISC_R_SUCCESS) {
00210 cfg_obj_log(keyobj, lctx, ISC_LOG_WARNING,
00211 "key name '%s' is not a valid domain name",
00212 txtname);
00213 return (result);
00214 }
00215 return (dns_name_dup(dns_fixedname_name(&fixname), mctx, dnsname));
00216 }
00217
00218
00219
00220
00221
00222
00223
00224
00225 static isc_result_t
00226 count_acl_elements(const cfg_obj_t *caml, const cfg_obj_t *cctx,
00227 isc_log_t *lctx, cfg_aclconfctx_t *ctx, isc_mem_t *mctx,
00228 isc_uint32_t *count, isc_boolean_t *has_negative)
00229 {
00230 const cfg_listelt_t *elt;
00231 isc_result_t result;
00232 isc_uint32_t n = 0;
00233
00234 REQUIRE(count != NULL);
00235
00236 if (has_negative != NULL)
00237 *has_negative = ISC_FALSE;
00238
00239 for (elt = cfg_list_first(caml);
00240 elt != NULL;
00241 elt = cfg_list_next(elt)) {
00242 const cfg_obj_t *ce = cfg_listelt_value(elt);
00243
00244
00245 if (cfg_obj_istuple(ce)) {
00246 const cfg_obj_t *negated =
00247 cfg_tuple_get(ce, "negated");
00248 if (! cfg_obj_isvoid(negated)) {
00249 ce = negated;
00250 if (has_negative != NULL)
00251 *has_negative = ISC_TRUE;
00252 }
00253 }
00254
00255 if (cfg_obj_istype(ce, &cfg_type_keyref)) {
00256 n++;
00257 } else if (cfg_obj_islist(ce)) {
00258 isc_boolean_t negative;
00259 isc_uint32_t sub;
00260 result = count_acl_elements(ce, cctx, lctx, ctx, mctx,
00261 &sub, &negative);
00262 if (result != ISC_R_SUCCESS)
00263 return (result);
00264 n += sub;
00265 if (negative)
00266 n++;
00267 #ifdef HAVE_GEOIP
00268 } else if (cfg_obj_istuple(ce) &&
00269 cfg_obj_isvoid(cfg_tuple_get(ce, "negated")))
00270 {
00271 n++;
00272 #endif
00273 } else if (cfg_obj_isstring(ce)) {
00274 const char *name = cfg_obj_asstring(ce);
00275 if (strcasecmp(name, "localhost") == 0 ||
00276 strcasecmp(name, "localnets") == 0) {
00277 n++;
00278 } else if (strcasecmp(name, "any") != 0 &&
00279 strcasecmp(name, "none") != 0) {
00280 dns_acl_t *inneracl = NULL;
00281
00282
00283
00284
00285 result = convert_named_acl(ce, cctx, lctx, ctx,
00286 mctx, 0, &inneracl);
00287 if (result == ISC_R_SUCCESS) {
00288 if (inneracl->has_negatives)
00289 n++;
00290 else
00291 n += inneracl->length;
00292 dns_acl_detach(&inneracl);
00293 } else
00294 return (result);
00295 }
00296 }
00297 }
00298
00299 *count = n;
00300 return (ISC_R_SUCCESS);
00301 }
00302
00303 #ifdef HAVE_GEOIP
00304 static dns_geoip_subtype_t
00305 get_subtype(const cfg_obj_t *obj, isc_log_t *lctx,
00306 dns_geoip_subtype_t subtype, const char *dbname)
00307 {
00308 if (dbname == NULL)
00309 return (subtype);
00310
00311 switch (subtype) {
00312 case dns_geoip_countrycode:
00313 if (strcasecmp(dbname, "city") == 0)
00314 return (dns_geoip_city_countrycode);
00315 else if (strcasecmp(dbname, "region") == 0)
00316 return (dns_geoip_region_countrycode);
00317 else if (strcasecmp(dbname, "country") == 0)
00318 return (dns_geoip_country_code);
00319 cfg_obj_log(obj, lctx, ISC_LOG_ERROR,
00320 "invalid GeoIP DB specified for "
00321 "country search: ignored");
00322 return (subtype);
00323 case dns_geoip_countrycode3:
00324 if (strcasecmp(dbname, "city") == 0)
00325 return (dns_geoip_city_countrycode3);
00326 else if (strcasecmp(dbname, "country") == 0)
00327 return (dns_geoip_country_code3);
00328 cfg_obj_log(obj, lctx, ISC_LOG_ERROR,
00329 "invalid GeoIP DB specified for "
00330 "country search: ignored");
00331 return (subtype);
00332 case dns_geoip_countryname:
00333 if (strcasecmp(dbname, "city") == 0)
00334 return (dns_geoip_city_countryname);
00335 else if (strcasecmp(dbname, "country") == 0)
00336 return (dns_geoip_country_name);
00337 cfg_obj_log(obj, lctx, ISC_LOG_ERROR,
00338 "invalid GeoIP DB specified for "
00339 "country search: ignored");
00340 return (subtype);
00341 case dns_geoip_region:
00342 if (strcasecmp(dbname, "city") == 0)
00343 return (dns_geoip_city_region);
00344 else if (strcasecmp(dbname, "region") == 0)
00345 return (dns_geoip_region_code);
00346 cfg_obj_log(obj, lctx, ISC_LOG_ERROR,
00347 "invalid GeoIP DB specified for "
00348 "region search: ignored");
00349 return (subtype);
00350 case dns_geoip_regionname:
00351 if (strcasecmp(dbname, "city") == 0)
00352 return (dns_geoip_city_region);
00353 else if (strcasecmp(dbname, "region") == 0)
00354 return (dns_geoip_region_name);
00355 cfg_obj_log(obj, lctx, ISC_LOG_ERROR,
00356 "invalid GeoIP DB specified for "
00357 "region search: ignored");
00358 return (subtype);
00359
00360
00361
00362
00363
00364 case dns_geoip_city_name:
00365 case dns_geoip_city_postalcode:
00366 case dns_geoip_city_metrocode:
00367 case dns_geoip_city_areacode:
00368 case dns_geoip_city_continentcode:
00369 case dns_geoip_city_timezonecode:
00370 if (strcasecmp(dbname, "city") != 0)
00371 cfg_obj_log(obj, lctx, ISC_LOG_WARNING,
00372 "invalid GeoIP DB specified for "
00373 "a 'city'-only search type: ignoring");
00374 return (subtype);
00375 case dns_geoip_isp_name:
00376 if (strcasecmp(dbname, "isp") != 0)
00377 cfg_obj_log(obj, lctx, ISC_LOG_WARNING,
00378 "invalid GeoIP DB specified for "
00379 "an 'isp' search: ignoring");
00380 return (subtype);
00381 case dns_geoip_org_name:
00382 if (strcasecmp(dbname, "org") != 0)
00383 cfg_obj_log(obj, lctx, ISC_LOG_WARNING,
00384 "invalid GeoIP DB specified for "
00385 "an 'org' search: ignoring");
00386 return (subtype);
00387 case dns_geoip_as_asnum:
00388 if (strcasecmp(dbname, "asnum") != 0)
00389 cfg_obj_log(obj, lctx, ISC_LOG_WARNING,
00390 "invalid GeoIP DB specified for "
00391 "an 'asnum' search: ignoring");
00392 return (subtype);
00393 case dns_geoip_domain_name:
00394 if (strcasecmp(dbname, "domain") != 0)
00395 cfg_obj_log(obj, lctx, ISC_LOG_WARNING,
00396 "invalid GeoIP DB specified for "
00397 "a 'domain' search: ignoring");
00398 return (subtype);
00399 case dns_geoip_netspeed_id:
00400 if (strcasecmp(dbname, "netspeed") != 0)
00401 cfg_obj_log(obj, lctx, ISC_LOG_WARNING,
00402 "invalid GeoIP DB specified for "
00403 "a 'netspeed' search: ignoring");
00404 return (subtype);
00405 default:
00406 INSIST(0);
00407 }
00408 }
00409
00410 static isc_boolean_t
00411 geoip_can_answer(dns_aclelement_t *elt, cfg_aclconfctx_t *ctx) {
00412 if (ctx->geoip == NULL)
00413 return (ISC_TRUE);
00414
00415 switch (elt->geoip_elem.subtype) {
00416 case dns_geoip_countrycode:
00417 case dns_geoip_countrycode3:
00418 case dns_geoip_countryname:
00419 if (ctx->geoip->city_v4 != NULL ||
00420 ctx->geoip->city_v6 != NULL ||
00421 ctx->geoip->country_v4 != NULL ||
00422 ctx->geoip->country_v6 != NULL ||
00423 ctx->geoip->region != NULL)
00424 return (ISC_TRUE);
00425 case dns_geoip_region:
00426 case dns_geoip_regionname:
00427 if (ctx->geoip->city_v4 != NULL ||
00428 ctx->geoip->city_v6 != NULL ||
00429 ctx->geoip->region != NULL)
00430 return (ISC_TRUE);
00431 case dns_geoip_country_code:
00432 case dns_geoip_country_code3:
00433 case dns_geoip_country_name:
00434 if (ctx->geoip->country_v4 != NULL ||
00435 ctx->geoip->country_v6 != NULL)
00436 return (ISC_TRUE);
00437 case dns_geoip_region_countrycode:
00438 case dns_geoip_region_code:
00439 case dns_geoip_region_name:
00440 if (ctx->geoip->region != NULL)
00441 return (ISC_TRUE);
00442 case dns_geoip_city_countrycode:
00443 case dns_geoip_city_countrycode3:
00444 case dns_geoip_city_countryname:
00445 case dns_geoip_city_region:
00446 case dns_geoip_city_regionname:
00447 case dns_geoip_city_name:
00448 case dns_geoip_city_postalcode:
00449 case dns_geoip_city_metrocode:
00450 case dns_geoip_city_areacode:
00451 case dns_geoip_city_continentcode:
00452 case dns_geoip_city_timezonecode:
00453 if (ctx->geoip->city_v4 != NULL ||
00454 ctx->geoip->city_v6 != NULL)
00455 return (ISC_TRUE);
00456 case dns_geoip_isp_name:
00457 if (ctx->geoip->isp != NULL)
00458 return (ISC_TRUE);
00459 case dns_geoip_org_name:
00460 if (ctx->geoip->org != NULL)
00461 return (ISC_TRUE);
00462 case dns_geoip_as_asnum:
00463 if (ctx->geoip->as != NULL)
00464 return (ISC_TRUE);
00465 case dns_geoip_domain_name:
00466 if (ctx->geoip->domain != NULL)
00467 return (ISC_TRUE);
00468 case dns_geoip_netspeed_id:
00469 if (ctx->geoip->netspeed != NULL)
00470 return (ISC_TRUE);
00471 }
00472
00473 return (ISC_FALSE);
00474 }
00475
00476 static isc_result_t
00477 parse_geoip_element(const cfg_obj_t *obj, isc_log_t *lctx,
00478 cfg_aclconfctx_t *ctx, dns_aclelement_t *dep)
00479 {
00480 const cfg_obj_t *ge;
00481 const char *dbname = NULL;
00482 const char *stype, *search;
00483 dns_geoip_subtype_t subtype;
00484 dns_aclelement_t de;
00485 size_t len;
00486
00487 REQUIRE(dep != NULL);
00488
00489 de = *dep;
00490
00491 ge = cfg_tuple_get(obj, "db");
00492 if (!cfg_obj_isvoid(ge))
00493 dbname = cfg_obj_asstring(ge);
00494
00495 stype = cfg_obj_asstring(cfg_tuple_get(obj, "subtype"));
00496 search = cfg_obj_asstring(cfg_tuple_get(obj, "search"));
00497 len = strlen(search);
00498
00499 if (len == 0) {
00500 cfg_obj_log(obj, lctx, ISC_LOG_ERROR,
00501 "zero-length geoip search field");
00502 return (ISC_R_FAILURE);
00503 }
00504
00505 if (strcasecmp(stype, "country") == 0 && len == 2) {
00506
00507 subtype = dns_geoip_countrycode;
00508 strlcpy(de.geoip_elem.as_string, search,
00509 sizeof(de.geoip_elem.as_string));
00510 } else if (strcasecmp(stype, "country") == 0 && len == 3) {
00511
00512 subtype = dns_geoip_countrycode3;
00513 strlcpy(de.geoip_elem.as_string, search,
00514 sizeof(de.geoip_elem.as_string));
00515 } else if (strcasecmp(stype, "country") == 0) {
00516
00517 subtype = dns_geoip_countryname;
00518 strlcpy(de.geoip_elem.as_string, search,
00519 sizeof(de.geoip_elem.as_string));
00520 } else if (strcasecmp(stype, "region") == 0 && len == 2) {
00521
00522 subtype = dns_geoip_region;
00523 strlcpy(de.geoip_elem.as_string, search,
00524 sizeof(de.geoip_elem.as_string));
00525 } else if (strcasecmp(stype, "region") == 0) {
00526
00527 subtype = dns_geoip_regionname;
00528 strlcpy(de.geoip_elem.as_string, search,
00529 sizeof(de.geoip_elem.as_string));
00530 } else if (strcasecmp(stype, "city") == 0) {
00531
00532 subtype = dns_geoip_city_name;
00533 strlcpy(de.geoip_elem.as_string, search,
00534 sizeof(de.geoip_elem.as_string));
00535 } else if (strcasecmp(stype, "postal") == 0 && len < 7) {
00536 subtype = dns_geoip_city_postalcode;
00537 strlcpy(de.geoip_elem.as_string, search,
00538 sizeof(de.geoip_elem.as_string));
00539 } else if (strcasecmp(stype, "postal") == 0) {
00540 cfg_obj_log(obj, lctx, ISC_LOG_ERROR,
00541 "geoiop postal code (%s) too long", search);
00542 return (ISC_R_FAILURE);
00543 } else if (strcasecmp(stype, "metro") == 0) {
00544 subtype = dns_geoip_city_metrocode;
00545 de.geoip_elem.as_int = atoi(search);
00546 } else if (strcasecmp(stype, "area") == 0) {
00547 subtype = dns_geoip_city_areacode;
00548 de.geoip_elem.as_int = atoi(search);
00549 } else if (strcasecmp(stype, "tz") == 0) {
00550 subtype = dns_geoip_city_timezonecode;
00551 strlcpy(de.geoip_elem.as_string, search,
00552 sizeof(de.geoip_elem.as_string));
00553 } else if (strcasecmp(stype, "continent") == 0 && len == 2) {
00554
00555 subtype = dns_geoip_city_continentcode;
00556 strlcpy(de.geoip_elem.as_string, search,
00557 sizeof(de.geoip_elem.as_string));
00558 } else if (strcasecmp(stype, "continent") == 0) {
00559 cfg_obj_log(obj, lctx, ISC_LOG_ERROR,
00560 "geoiop continent code (%s) too long", search);
00561 return (ISC_R_FAILURE);
00562 } else if (strcasecmp(stype, "isp") == 0) {
00563 subtype = dns_geoip_isp_name;
00564 strlcpy(de.geoip_elem.as_string, search,
00565 sizeof(de.geoip_elem.as_string));
00566 } else if (strcasecmp(stype, "asnum") == 0) {
00567 subtype = dns_geoip_as_asnum;
00568 strlcpy(de.geoip_elem.as_string, search,
00569 sizeof(de.geoip_elem.as_string));
00570 } else if (strcasecmp(stype, "org") == 0) {
00571 subtype = dns_geoip_org_name;
00572 strlcpy(de.geoip_elem.as_string, search,
00573 sizeof(de.geoip_elem.as_string));
00574 } else if (strcasecmp(stype, "domain") == 0) {
00575 subtype = dns_geoip_domain_name;
00576 strlcpy(de.geoip_elem.as_string, search,
00577 sizeof(de.geoip_elem.as_string));
00578 } else if (strcasecmp(stype, "netspeed") == 0) {
00579 subtype = dns_geoip_netspeed_id;
00580 de.geoip_elem.as_int = atoi(search);
00581 } else
00582 INSIST(0);
00583
00584 de.geoip_elem.subtype = get_subtype(obj, lctx, subtype, dbname);
00585
00586 if (! geoip_can_answer(&de, ctx)) {
00587 cfg_obj_log(obj, lctx, ISC_LOG_ERROR,
00588 "no GeoIP database installed which can answer "
00589 "queries of type '%s'", stype);
00590 return (ISC_R_FAILURE);
00591 }
00592
00593 *dep = de;
00594
00595 return (ISC_R_SUCCESS);
00596 }
00597 #endif
00598
00599 isc_result_t
00600 cfg_acl_fromconfig(const cfg_obj_t *caml, const cfg_obj_t *cctx,
00601 isc_log_t *lctx, cfg_aclconfctx_t *ctx,
00602 isc_mem_t *mctx, unsigned int nest_level,
00603 dns_acl_t **target)
00604 {
00605 return (cfg_acl_fromconfig2(caml, cctx, lctx, ctx, mctx,
00606 nest_level, 0, target));
00607 }
00608
00609 isc_result_t
00610 cfg_acl_fromconfig2(const cfg_obj_t *caml, const cfg_obj_t *cctx,
00611 isc_log_t *lctx, cfg_aclconfctx_t *ctx,
00612 isc_mem_t *mctx, unsigned int nest_level,
00613 isc_uint16_t family, dns_acl_t **target)
00614 {
00615 isc_result_t result;
00616 dns_acl_t *dacl = NULL, *inneracl = NULL;
00617 dns_aclelement_t *de;
00618 const cfg_listelt_t *elt;
00619 dns_iptable_t *iptab;
00620 int new_nest_level = 0;
00621
00622 if (nest_level != 0)
00623 new_nest_level = nest_level - 1;
00624
00625 REQUIRE(target != NULL);
00626 REQUIRE(*target == NULL || DNS_ACL_VALID(*target));
00627
00628 if (*target != NULL) {
00629
00630
00631
00632
00633
00634
00635 dns_acl_attach(*target, &dacl);
00636 dns_acl_detach(target);
00637 } else {
00638
00639
00640
00641
00642
00643
00644 isc_uint32_t nelem;
00645
00646 if (nest_level == 0) {
00647 result = count_acl_elements(caml, cctx, lctx, ctx,
00648 mctx, &nelem, NULL);
00649 if (result != ISC_R_SUCCESS)
00650 return (result);
00651 } else
00652 nelem = cfg_list_length(caml, ISC_FALSE);
00653
00654 result = dns_acl_create(mctx, nelem, &dacl);
00655 if (result != ISC_R_SUCCESS)
00656 return (result);
00657 }
00658
00659 de = dacl->elements;
00660 for (elt = cfg_list_first(caml);
00661 elt != NULL;
00662 elt = cfg_list_next(elt)) {
00663 const cfg_obj_t *ce = cfg_listelt_value(elt);
00664 isc_boolean_t neg = ISC_FALSE;
00665
00666 INSIST(dacl->length <= dacl->alloc);
00667
00668 if (cfg_obj_istuple(ce)) {
00669
00670 const cfg_obj_t *negated =
00671 cfg_tuple_get(ce, "negated");
00672 if (! cfg_obj_isvoid(negated)) {
00673 neg = ISC_TRUE;
00674 dacl->has_negatives = ISC_TRUE;
00675 ce = negated;
00676 }
00677 }
00678
00679
00680
00681
00682
00683
00684 iptab = dacl->iptable;
00685
00686 if (nest_level != 0) {
00687 result = dns_acl_create(mctx,
00688 cfg_list_length(ce, ISC_FALSE),
00689 &de->nestedacl);
00690 if (result != ISC_R_SUCCESS)
00691 goto cleanup;
00692 iptab = de->nestedacl->iptable;
00693 }
00694
00695 if (cfg_obj_isnetprefix(ce)) {
00696
00697 isc_netaddr_t addr;
00698 unsigned int bitlen;
00699 isc_boolean_t setpos, setecs;
00700
00701 cfg_obj_asnetprefix(ce, &addr, &bitlen);
00702 if (family != 0 && family != addr.family) {
00703 char buf[ISC_NETADDR_FORMATSIZE + 1];
00704 isc_netaddr_format(&addr, buf, sizeof(buf));
00705 cfg_obj_log(ce, lctx, ISC_LOG_WARNING,
00706 "'%s': incorrect address family; "
00707 "ignoring", buf);
00708 if (nest_level != 0)
00709 dns_acl_detach(&de->nestedacl);
00710 continue;
00711 }
00712
00713
00714
00715
00716
00717 setpos = ISC_TF(nest_level != 0 || !neg);
00718 setecs = cfg_obj_istype(ce, &cfg_type_ecsprefix);
00719 result = dns_iptable_addprefix2(iptab, &addr, bitlen,
00720 setpos, setecs);
00721 if (result != ISC_R_SUCCESS)
00722 goto cleanup;
00723
00724 if (nest_level > 0) {
00725 INSIST(dacl->length < dacl->alloc);
00726 de->type = dns_aclelementtype_nestedacl;
00727 de->negative = neg;
00728 } else
00729 continue;
00730 } else if (cfg_obj_islist(ce)) {
00731
00732
00733
00734
00735
00736
00737
00738 if (inneracl != NULL)
00739 dns_acl_detach(&inneracl);
00740 result = cfg_acl_fromconfig(ce, cctx, lctx,
00741 ctx, mctx, new_nest_level,
00742 &inneracl);
00743 if (result != ISC_R_SUCCESS)
00744 goto cleanup;
00745 nested_acl:
00746 if (nest_level > 0 || inneracl->has_negatives) {
00747 INSIST(dacl->length < dacl->alloc);
00748 de->type = dns_aclelementtype_nestedacl;
00749 de->negative = neg;
00750 if (de->nestedacl != NULL)
00751 dns_acl_detach(&de->nestedacl);
00752 dns_acl_attach(inneracl,
00753 &de->nestedacl);
00754 dns_acl_detach(&inneracl);
00755
00756 } else {
00757 INSIST(dacl->length + inneracl->length
00758 <= dacl->alloc);
00759 dns_acl_merge(dacl, inneracl,
00760 ISC_TF(!neg));
00761 de += inneracl->length;
00762 dns_acl_detach(&inneracl);
00763 INSIST(dacl->length <= dacl->alloc);
00764 continue;
00765 }
00766 } else if (cfg_obj_istype(ce, &cfg_type_keyref)) {
00767
00768 INSIST(dacl->length < dacl->alloc);
00769 de->type = dns_aclelementtype_keyname;
00770 de->negative = neg;
00771 dns_name_init(&de->keyname, NULL);
00772 result = convert_keyname(ce, lctx, mctx,
00773 &de->keyname);
00774 if (result != ISC_R_SUCCESS)
00775 goto cleanup;
00776 #ifdef HAVE_GEOIP
00777 } else if (cfg_obj_istuple(ce) &&
00778 cfg_obj_isvoid(cfg_tuple_get(ce, "negated")))
00779 {
00780 INSIST(dacl->length < dacl->alloc);
00781 result = parse_geoip_element(ce, lctx, ctx, de);
00782 if (result != ISC_R_SUCCESS)
00783 goto cleanup;
00784 de->type = dns_aclelementtype_geoip;
00785 de->negative = neg;
00786 #endif
00787 } else if (cfg_obj_isstring(ce)) {
00788
00789 const char *name = cfg_obj_asstring(ce);
00790 if (strcasecmp(name, "any") == 0) {
00791
00792 result = dns_iptable_addprefix(iptab, NULL, 0,
00793 ISC_TF(nest_level != 0 || !neg));
00794 if (result != ISC_R_SUCCESS)
00795 goto cleanup;
00796
00797 if (nest_level != 0) {
00798 INSIST(dacl->length < dacl->alloc);
00799 de->type = dns_aclelementtype_nestedacl;
00800 de->negative = neg;
00801 } else
00802 continue;
00803 } else if (strcasecmp(name, "none") == 0) {
00804
00805
00806
00807
00808
00809
00810
00811 result = dns_iptable_addprefix(iptab, NULL, 0,
00812 ISC_TF(nest_level != 0 || neg));
00813 if (result != ISC_R_SUCCESS)
00814 goto cleanup;
00815
00816 if (!neg)
00817 dacl->has_negatives = !neg;
00818
00819 if (nest_level != 0) {
00820 INSIST(dacl->length < dacl->alloc);
00821 de->type = dns_aclelementtype_nestedacl;
00822 de->negative = !neg;
00823 } else
00824 continue;
00825 } else if (strcasecmp(name, "localhost") == 0) {
00826 INSIST(dacl->length < dacl->alloc);
00827 de->type = dns_aclelementtype_localhost;
00828 de->negative = neg;
00829 } else if (strcasecmp(name, "localnets") == 0) {
00830 INSIST(dacl->length < dacl->alloc);
00831 de->type = dns_aclelementtype_localnets;
00832 de->negative = neg;
00833 } else {
00834 if (inneracl != NULL)
00835 dns_acl_detach(&inneracl);
00836
00837
00838
00839
00840 result = convert_named_acl(ce, cctx, lctx, ctx,
00841 mctx, new_nest_level,
00842 &inneracl);
00843 if (result != ISC_R_SUCCESS)
00844 goto cleanup;
00845
00846 goto nested_acl;
00847 }
00848 } else {
00849 cfg_obj_log(ce, lctx, ISC_LOG_WARNING,
00850 "address match list contains "
00851 "unsupported element type");
00852 result = ISC_R_FAILURE;
00853 goto cleanup;
00854 }
00855
00856
00857
00858
00859
00860
00861 if (de->nestedacl != NULL &&
00862 de->type != dns_aclelementtype_nestedacl)
00863 dns_acl_detach(&de->nestedacl);
00864
00865 dacl->node_count++;
00866 de->node_num = dacl->node_count;
00867
00868 dacl->length++;
00869 de++;
00870 INSIST(dacl->length <= dacl->alloc);
00871 }
00872
00873 dns_acl_attach(dacl, target);
00874 result = ISC_R_SUCCESS;
00875
00876 cleanup:
00877 if (inneracl != NULL)
00878 dns_acl_detach(&inneracl);
00879 dns_acl_detach(&dacl);
00880 return (result);
00881 }