1 1.19 christos /* $NetBSD: config.c,v 1.20 2026/01/29 18:36:27 christos Exp $ */ 2 1.1 christos 3 1.1 christos /* 4 1.1 christos * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 1.1 christos * 6 1.13 christos * SPDX-License-Identifier: MPL-2.0 7 1.13 christos * 8 1.1 christos * This Source Code Form is subject to the terms of the Mozilla Public 9 1.1 christos * License, v. 2.0. If a copy of the MPL was not distributed with this 10 1.10 christos * file, you can obtain one at https://mozilla.org/MPL/2.0/. 11 1.1 christos * 12 1.1 christos * See the COPYRIGHT file distributed with this work for additional 13 1.1 christos * information regarding copyright ownership. 14 1.1 christos */ 15 1.1 christos 16 1.1 christos /*! \file */ 17 1.1 christos 18 1.8 christos #include <bind.keys.h> 19 1.3 christos #include <inttypes.h> 20 1.1 christos #include <stdlib.h> 21 1.1 christos 22 1.1 christos #include <isc/buffer.h> 23 1.1 christos #include <isc/log.h> 24 1.1 christos #include <isc/mem.h> 25 1.13 christos #include <isc/netmgr.h> 26 1.1 christos #include <isc/parseint.h> 27 1.1 christos #include <isc/region.h> 28 1.1 christos #include <isc/result.h> 29 1.1 christos #include <isc/sockaddr.h> 30 1.1 christos #include <isc/string.h> 31 1.1 christos #include <isc/util.h> 32 1.1 christos 33 1.1 christos #include <dns/fixedname.h> 34 1.15 christos #include <dns/kasp.h> 35 1.1 christos #include <dns/name.h> 36 1.1 christos #include <dns/rdataclass.h> 37 1.1 christos #include <dns/rdatatype.h> 38 1.1 christos #include <dns/tsig.h> 39 1.1 christos #include <dns/zone.h> 40 1.1 christos 41 1.1 christos #include <dst/dst.h> 42 1.1 christos 43 1.8 christos #include <isccfg/grammar.h> 44 1.8 christos #include <isccfg/namedconf.h> 45 1.8 christos 46 1.1 christos #include <named/config.h> 47 1.1 christos #include <named/globals.h> 48 1.1 christos 49 1.1 christos /*% default configuration */ 50 1.1 christos static char defaultconf[] = "\ 51 1.1 christos options {\n\ 52 1.1 christos answer-cookie true;\n\ 53 1.1 christos automatic-interface-scan yes;\n\ 54 1.17 christos # blackhole {none;};\n\ 55 1.17 christos cookie-algorithm siphash24;\n\ 56 1.1 christos # directory <none>\n\ 57 1.8 christos dnssec-policy \"none\";\n\ 58 1.1 christos dump-file \"named_dump.db\";\n\ 59 1.17 christos edns-udp-size 1232;\n" 60 1.15 christos #if defined(HAVE_GEOIP2) 61 1.15 christos "\ 62 1.15 christos geoip-directory \"" MAXMINDDB_PREFIX "/share/GeoIP\";\n" 63 1.5 christos #elif defined(HAVE_GEOIP2) 64 1.15 christos "\ 65 1.15 christos geoip-directory \".\";\n" 66 1.15 christos #endif /* if defined(HAVE_GEOIP2) */ 67 1.8 christos "\ 68 1.1 christos heartbeat-interval 60;\n\ 69 1.19 christos interface-interval 60m;\n \ 70 1.1 christos listen-on {any;};\n\ 71 1.1 christos listen-on-v6 {any;};\n\ 72 1.1 christos match-mapped-addresses no;\n\ 73 1.15 christos max-ixfr-ratio 100%;\n\ 74 1.1 christos max-rsa-exponent-size 0; /* no limit */\n\ 75 1.10 christos max-udp-size 1232;\n\ 76 1.1 christos memstatistics-file \"named.memstats\";\n\ 77 1.1 christos nocookie-udp-size 4096;\n\ 78 1.1 christos notify-rate 20;\n\ 79 1.1 christos nta-lifetime 3600;\n\ 80 1.1 christos nta-recheck 300;\n\ 81 1.1 christos # pid-file \"" NAMED_LOCALSTATEDIR "/run/named/named.pid\"; \n\ 82 1.13 christos port 53;\n" 83 1.13 christos #if HAVE_SO_REUSEPORT_LB 84 1.13 christos "\ 85 1.13 christos reuseport yes;\n" 86 1.13 christos #else 87 1.13 christos "\ 88 1.13 christos reuseport no;\n" 89 1.13 christos #endif 90 1.13 christos "\ 91 1.15 christos tls-port 853;\n" 92 1.15 christos #if HAVE_LIBNGHTTP2 93 1.15 christos "\ 94 1.15 christos http-port 80;\n\ 95 1.15 christos https-port 443;\n\ 96 1.15 christos http-listener-clients 300;\n\ 97 1.15 christos http-streams-per-connection 100;\n" 98 1.15 christos #endif 99 1.15 christos "\ 100 1.3 christos prefetch 2 9;\n\ 101 1.17 christos # querylog <boolean>;\n\ 102 1.3 christos recursing-file \"named.recursing\";\n\ 103 1.1 christos recursive-clients 1000;\n\ 104 1.1 christos request-nsid false;\n\ 105 1.1 christos resolver-query-timeout 10;\n\ 106 1.17 christos # responselog <boolean>;\n\ 107 1.1 christos rrset-order { order random; };\n\ 108 1.1 christos secroots-file \"named.secroots\";\n\ 109 1.1 christos send-cookie true;\n\ 110 1.1 christos serial-query-rate 20;\n\ 111 1.1 christos server-id none;\n\ 112 1.1 christos session-keyalg hmac-sha256;\n\ 113 1.1 christos # session-keyfile \"" NAMED_LOCALSTATEDIR "/run/named/session.key\";\n\ 114 1.15 christos session-keyname local-ddns;\n\ 115 1.15 christos startup-notify-rate 20;\n\ 116 1.17 christos sig0checks-quota 1;\n\ 117 1.18 christos sig0key-checks-limit 16;\n\ 118 1.18 christos sig0message-checks-limit 2;\n\ 119 1.1 christos statistics-file \"named.stats\";\n\ 120 1.1 christos tcp-advertised-timeout 300;\n\ 121 1.1 christos tcp-clients 150;\n\ 122 1.1 christos tcp-idle-timeout 300;\n\ 123 1.1 christos tcp-initial-timeout 300;\n\ 124 1.1 christos tcp-keepalive-timeout 300;\n\ 125 1.1 christos tcp-listen-queue 10;\n\ 126 1.15 christos tcp-receive-buffer 0;\n\ 127 1.15 christos tcp-send-buffer 0;\n\ 128 1.1 christos # tkey-gssapi-credential <none>\n\ 129 1.1 christos transfer-message-size 20480;\n\ 130 1.1 christos transfers-in 10;\n\ 131 1.1 christos transfers-out 10;\n\ 132 1.1 christos transfers-per-ns 2;\n\ 133 1.1 christos trust-anchor-telemetry yes;\n\ 134 1.15 christos udp-receive-buffer 0;\n\ 135 1.15 christos udp-send-buffer 0;\n\ 136 1.14 christos update-quota 100;\n\ 137 1.1 christos \n\ 138 1.1 christos /* view */\n\ 139 1.1 christos allow-new-zones no;\n\ 140 1.1 christos allow-notify {none;};\n\ 141 1.17 christos allow-proxy {none;};\n\ 142 1.17 christos allow-proxy-on {any;};\n\ 143 1.1 christos allow-query-cache { localnets; localhost; };\n\ 144 1.1 christos allow-query-cache-on { any; };\n\ 145 1.1 christos allow-recursion { localnets; localhost; };\n\ 146 1.1 christos allow-recursion-on { any; };\n\ 147 1.1 christos allow-update-forwarding {none;};\n\ 148 1.1 christos auth-nxdomain false;\n\ 149 1.1 christos check-dup-records warn;\n\ 150 1.1 christos check-mx warn;\n\ 151 1.13 christos check-names primary fail;\n\ 152 1.1 christos check-names response ignore;\n\ 153 1.13 christos check-names secondary warn;\n\ 154 1.1 christos check-spf warn;\n\ 155 1.17 christos check-svcb yes;\n\ 156 1.1 christos clients-per-query 10;\n\ 157 1.1 christos dnssec-accept-expired no;\n\ 158 1.3 christos dnssec-validation " VALIDATION_DEFAULT "; \n" 159 1.17 christos #ifdef USE_DNSRPS 160 1.17 christos " dnsrps-library \"" DNSRPS_LIBRPZ_PATH "\";\n" 161 1.17 christos #endif /* ifdef USE_DNSRPS */ 162 1.1 christos #ifdef HAVE_DNSTAP 163 1.8 christos " dnstap-identity hostname;\n" 164 1.8 christos #endif /* ifdef HAVE_DNSTAP */ 165 1.8 christos "\ 166 1.1 christos fetch-quota-params 100 0.1 0.3 0.7;\n\ 167 1.1 christos fetches-per-server 0;\n\ 168 1.5 christos fetches-per-zone 0;\n\ 169 1.13 christos lame-ttl 0;\n" 170 1.1 christos #ifdef HAVE_LMDB 171 1.8 christos " lmdb-mapsize 32M;\n" 172 1.8 christos #endif /* ifdef HAVE_LMDB */ 173 1.20 christos " max-cache-size default;\n\ 174 1.1 christos max-cache-ttl 604800; /* 1 week */\n\ 175 1.1 christos max-clients-per-query 100;\n\ 176 1.1 christos max-ncache-ttl 10800; /* 3 hours */\n\ 177 1.1 christos max-recursion-depth 7;\n\ 178 1.18 christos max-recursion-queries 50;\n\ 179 1.18 christos max-query-count 200;\n\ 180 1.16 christos max-query-restarts 11;\n\ 181 1.10 christos max-stale-ttl 86400; /* 1 day */\n\ 182 1.1 christos message-compression yes;\n\ 183 1.3 christos min-ncache-ttl 0; /* 0 hours */\n\ 184 1.3 christos min-cache-ttl 0; /* 0 seconds */\n\ 185 1.1 christos minimal-any false;\n\ 186 1.1 christos minimal-responses no-auth-recursive;\n\ 187 1.1 christos notify-source *;\n\ 188 1.1 christos notify-source-v6 *;\n\ 189 1.1 christos nsec3-test-zone no;\n\ 190 1.12 christos parental-source *;\n\ 191 1.12 christos parental-source-v6 *;\n\ 192 1.1 christos provide-ixfr true;\n\ 193 1.20 christos response-padding { none; } block-size 0;\n\ 194 1.3 christos qname-minimization relaxed;\n\ 195 1.1 christos query-source address *;\n\ 196 1.1 christos query-source-v6 address *;\n\ 197 1.1 christos recursion true;\n\ 198 1.1 christos request-expire true;\n\ 199 1.1 christos request-ixfr true;\n\ 200 1.1 christos require-server-cookie no;\n\ 201 1.1 christos root-key-sentinel yes;\n\ 202 1.1 christos servfail-ttl 1;\n\ 203 1.1 christos # sortlist <none>\n\ 204 1.12 christos stale-answer-client-timeout off;\n\ 205 1.1 christos stale-answer-enable false;\n\ 206 1.10 christos stale-answer-ttl 30; /* 30 seconds */\n\ 207 1.15 christos stale-cache-enable false;\n\ 208 1.10 christos stale-refresh-time 30; /* 30 seconds */\n\ 209 1.15 christos synth-from-dnssec yes;\n\ 210 1.1 christos # topology <none>\n\ 211 1.1 christos transfer-format many-answers;\n\ 212 1.17 christos resolver-use-dns64 false;\n\ 213 1.1 christos v6-bias 50;\n\ 214 1.1 christos zero-no-soa-ttl-cache no;\n\ 215 1.1 christos \n\ 216 1.1 christos /* zone */\n\ 217 1.1 christos allow-query {any;};\n\ 218 1.1 christos allow-query-on {any;};\n\ 219 1.17 christos allow-transfer {none;};\n\ 220 1.1 christos # also-notify <none>\n\ 221 1.1 christos check-integrity yes;\n\ 222 1.1 christos check-mx-cname warn;\n\ 223 1.1 christos check-sibling yes;\n\ 224 1.1 christos check-srv-cname warn;\n\ 225 1.1 christos check-wildcard yes;\n\ 226 1.1 christos dialup no;\n\ 227 1.1 christos dnssec-loadkeys-interval 60;\n\ 228 1.1 christos # forward <none>\n\ 229 1.1 christos # forwarders <none>\n\ 230 1.12 christos # inline-signing no;\n\ 231 1.1 christos ixfr-from-differences false;\n\ 232 1.1 christos max-journal-size default;\n\ 233 1.1 christos max-records 0;\n\ 234 1.16 christos max-records-per-type 100;\n\ 235 1.1 christos max-refresh-time 2419200; /* 4 weeks */\n\ 236 1.1 christos max-retry-time 1209600; /* 2 weeks */\n\ 237 1.16 christos max-types-per-name 100;\n\ 238 1.1 christos max-transfer-idle-in 60;\n\ 239 1.1 christos max-transfer-idle-out 60;\n\ 240 1.1 christos max-transfer-time-in 120;\n\ 241 1.1 christos max-transfer-time-out 120;\n\ 242 1.1 christos min-refresh-time 300;\n\ 243 1.1 christos min-retry-time 500;\n\ 244 1.18 christos min-transfer-rate-in 10240 5;\n\ 245 1.1 christos multi-master no;\n\ 246 1.1 christos notify yes;\n\ 247 1.19 christos notify-defer 0;\n\ 248 1.1 christos notify-delay 5;\n\ 249 1.1 christos notify-to-soa no;\n\ 250 1.1 christos serial-update-method increment;\n\ 251 1.1 christos sig-signing-nodes 100;\n\ 252 1.1 christos sig-signing-signatures 10;\n\ 253 1.1 christos sig-signing-type 65534;\n\ 254 1.1 christos transfer-source *;\n\ 255 1.1 christos transfer-source-v6 *;\n\ 256 1.1 christos try-tcp-refresh yes; /* BIND 8 compat */\n\ 257 1.1 christos zero-no-soa-ttl yes;\n\ 258 1.1 christos zone-statistics terse;\n\ 259 1.1 christos };\n\ 260 1.1 christos " 261 1.1 christos 262 1.8 christos "#\n\ 263 1.1 christos # Zones in the \"_bind\" view are NOT counted in the count of zones.\n\ 264 1.1 christos #\n\ 265 1.1 christos view \"_bind\" chaos {\n\ 266 1.1 christos recursion no;\n\ 267 1.1 christos notify no;\n\ 268 1.1 christos allow-new-zones no;\n\ 269 1.12 christos max-cache-size 2M;\n\ 270 1.1 christos \n\ 271 1.1 christos # Prevent use of this zone in DNS amplified reflection DoS attacks\n\ 272 1.1 christos rate-limit {\n\ 273 1.1 christos responses-per-second 3;\n\ 274 1.1 christos slip 0;\n\ 275 1.1 christos min-table-size 10;\n\ 276 1.1 christos };\n\ 277 1.1 christos \n\ 278 1.1 christos zone \"version.bind\" chaos {\n\ 279 1.13 christos type primary;\n\ 280 1.1 christos database \"_builtin version\";\n\ 281 1.1 christos };\n\ 282 1.1 christos \n\ 283 1.1 christos zone \"hostname.bind\" chaos {\n\ 284 1.13 christos type primary;\n\ 285 1.1 christos database \"_builtin hostname\";\n\ 286 1.1 christos };\n\ 287 1.1 christos \n\ 288 1.1 christos zone \"authors.bind\" chaos {\n\ 289 1.13 christos type primary;\n\ 290 1.1 christos database \"_builtin authors\";\n\ 291 1.1 christos };\n\ 292 1.1 christos \n\ 293 1.1 christos zone \"id.server\" chaos {\n\ 294 1.13 christos type primary;\n\ 295 1.1 christos database \"_builtin id\";\n\ 296 1.1 christos };\n\ 297 1.1 christos };\n\ 298 1.1 christos " 299 1.8 christos "#\n\ 300 1.15 christos # Built-in DNSSEC key and signing policies.\n\ 301 1.15 christos #\n\ 302 1.15 christos dnssec-policy \"default\" {\n\ 303 1.15 christos keys {\n\ 304 1.15 christos csk key-directory lifetime unlimited algorithm 13;\n\ 305 1.15 christos };\n\ 306 1.15 christos \n\ 307 1.17 christos cdnskey yes;\n\ 308 1.17 christos cds-digest-types { 2; };\n\ 309 1.15 christos dnskey-ttl " DNS_KASP_KEY_TTL ";\n\ 310 1.17 christos inline-signing yes;\n\ 311 1.20 christos manual-mode no;\n\ 312 1.17 christos offline-ksk no;\n\ 313 1.15 christos publish-safety " DNS_KASP_PUBLISH_SAFETY "; \n\ 314 1.15 christos retire-safety " DNS_KASP_RETIRE_SAFETY "; \n\ 315 1.15 christos purge-keys " DNS_KASP_PURGE_KEYS "; \n\ 316 1.16 christos signatures-jitter " DNS_KASP_SIG_JITTER "; \n\ 317 1.15 christos signatures-refresh " DNS_KASP_SIG_REFRESH "; \n\ 318 1.15 christos signatures-validity " DNS_KASP_SIG_VALIDITY "; \n\ 319 1.15 christos signatures-validity-dnskey " DNS_KASP_SIG_VALIDITY_DNSKEY "; \n\ 320 1.15 christos max-zone-ttl " DNS_KASP_ZONE_MAXTTL "; \n\ 321 1.15 christos zone-propagation-delay " DNS_KASP_ZONE_PROPDELAY "; \n\ 322 1.15 christos parent-ds-ttl " DNS_KASP_DS_TTL "; \n\ 323 1.15 christos parent-propagation-delay " DNS_KASP_PARENT_PROPDELAY "; \n\ 324 1.15 christos };\n\ 325 1.15 christos \n\ 326 1.15 christos dnssec-policy \"insecure\" {\n\ 327 1.15 christos max-zone-ttl 0; \n\ 328 1.15 christos keys { };\n\ 329 1.17 christos inline-signing yes;\n\ 330 1.20 christos manual-mode no;\n\ 331 1.15 christos };\n\ 332 1.15 christos \n\ 333 1.15 christos " 334 1.15 christos "#\n\ 335 1.1 christos # Default trusted key(s), used if \n\ 336 1.1 christos # \"dnssec-validation auto;\" is set and\n\ 337 1.13 christos # " NAMED_SYSCONFDIR "/bind.keys doesn't exist).\n\ 338 1.1 christos #\n\ 339 1.13 christos # BEGIN TRUST ANCHORS\n" 340 1.1 christos 341 1.8 christos /* Imported from bind.keys.h: */ 342 1.8 christos TRUST_ANCHORS 343 1.1 christos 344 1.13 christos "# END TRUST ANCHORS\n\ 345 1.3 christos \n\ 346 1.18 christos remote-servers " DEFAULT_IANA_ROOT_ZONE_PRIMARIES " {\n\ 347 1.15 christos 2801:1b8:10::b; # b.root-servers.net\n\ 348 1.13 christos 2001:500:2::c; # c.root-servers.net\n\ 349 1.3 christos 2001:500:2f::f; # f.root-servers.net\n\ 350 1.13 christos 2001:500:12::d0d; # g.root-servers.net\n\ 351 1.3 christos 2001:7fd::1; # k.root-servers.net\n\ 352 1.3 christos 2620:0:2830:202::132; # xfr.cjr.dns.icann.org\n\ 353 1.3 christos 2620:0:2d0:202::132; # xfr.lax.dns.icann.org\n\ 354 1.15 christos 170.247.170.2; # b.root-servers.net\n\ 355 1.3 christos 192.33.4.12; # c.root-servers.net\n\ 356 1.3 christos 192.5.5.241; # f.root-servers.net\n\ 357 1.3 christos 192.112.36.4; # g.root-servers.net\n\ 358 1.3 christos 193.0.14.129; # k.root-servers.net\n\ 359 1.3 christos 192.0.47.132; # xfr.cjr.dns.icann.org\n\ 360 1.3 christos 192.0.32.132; # xfr.lax.dns.icann.org\n\ 361 1.3 christos };\n\ 362 1.1 christos "; 363 1.1 christos 364 1.1 christos isc_result_t 365 1.1 christos named_config_parsedefaults(cfg_parser_t *parser, cfg_obj_t **conf) { 366 1.1 christos isc_buffer_t b; 367 1.1 christos 368 1.1 christos isc_buffer_init(&b, defaultconf, sizeof(defaultconf) - 1); 369 1.1 christos isc_buffer_add(&b, sizeof(defaultconf) - 1); 370 1.17 christos return cfg_parse_buffer(parser, &b, __FILE__, 0, &cfg_type_namedconf, 371 1.17 christos CFG_PCTX_NODEPRECATED | CFG_PCTX_NOOBSOLETE | 372 1.17 christos CFG_PCTX_NOEXPERIMENTAL, 373 1.17 christos conf); 374 1.1 christos } 375 1.1 christos 376 1.13 christos const char * 377 1.13 christos named_config_getdefault(void) { 378 1.17 christos return defaultconf; 379 1.13 christos } 380 1.13 christos 381 1.1 christos isc_result_t 382 1.8 christos named_config_get(cfg_obj_t const *const *maps, const char *name, 383 1.8 christos const cfg_obj_t **obj) { 384 1.1 christos int i; 385 1.1 christos 386 1.13 christos for (i = 0; maps[i] != NULL; i++) { 387 1.8 christos if (cfg_map_get(maps[i], name, obj) == ISC_R_SUCCESS) { 388 1.17 christos return ISC_R_SUCCESS; 389 1.8 christos } 390 1.1 christos } 391 1.17 christos return ISC_R_NOTFOUND; 392 1.1 christos } 393 1.1 christos 394 1.1 christos isc_result_t 395 1.13 christos named_checknames_get(const cfg_obj_t **maps, const char *const names[], 396 1.8 christos const cfg_obj_t **obj) { 397 1.1 christos const cfg_listelt_t *element; 398 1.1 christos const cfg_obj_t *checknames; 399 1.1 christos const cfg_obj_t *type; 400 1.1 christos const cfg_obj_t *value; 401 1.1 christos int i; 402 1.1 christos 403 1.9 christos REQUIRE(maps != NULL); 404 1.13 christos REQUIRE(names != NULL); 405 1.9 christos REQUIRE(obj != NULL && *obj == NULL); 406 1.9 christos 407 1.13 christos for (i = 0; maps[i] != NULL; i++) { 408 1.1 christos checknames = NULL; 409 1.8 christos if (cfg_map_get(maps[i], "check-names", &checknames) == 410 1.14 christos ISC_R_SUCCESS) 411 1.14 christos { 412 1.1 christos /* 413 1.1 christos * Zone map entry is not a list. 414 1.1 christos */ 415 1.1 christos if (checknames != NULL && !cfg_obj_islist(checknames)) { 416 1.1 christos *obj = checknames; 417 1.17 christos return ISC_R_SUCCESS; 418 1.1 christos } 419 1.1 christos for (element = cfg_list_first(checknames); 420 1.8 christos element != NULL; element = cfg_list_next(element)) 421 1.8 christos { 422 1.1 christos value = cfg_listelt_value(element); 423 1.1 christos type = cfg_tuple_get(value, "type"); 424 1.13 christos 425 1.13 christos for (size_t j = 0; names[j] != NULL; j++) { 426 1.13 christos if (strcasecmp(cfg_obj_asstring(type), 427 1.14 christos names[j]) == 0) 428 1.14 christos { 429 1.13 christos *obj = cfg_tuple_get(value, 430 1.13 christos "mode"); 431 1.17 christos return ISC_R_SUCCESS; 432 1.13 christos } 433 1.1 christos } 434 1.1 christos } 435 1.1 christos } 436 1.1 christos } 437 1.17 christos return ISC_R_NOTFOUND; 438 1.1 christos } 439 1.1 christos 440 1.1 christos int 441 1.1 christos named_config_listcount(const cfg_obj_t *list) { 442 1.1 christos const cfg_listelt_t *e; 443 1.1 christos int i = 0; 444 1.1 christos 445 1.8 christos for (e = cfg_list_first(list); e != NULL; e = cfg_list_next(e)) { 446 1.1 christos i++; 447 1.8 christos } 448 1.1 christos 449 1.17 christos return i; 450 1.1 christos } 451 1.1 christos 452 1.1 christos isc_result_t 453 1.1 christos named_config_getclass(const cfg_obj_t *classobj, dns_rdataclass_t defclass, 454 1.8 christos dns_rdataclass_t *classp) { 455 1.1 christos isc_textregion_t r; 456 1.1 christos isc_result_t result; 457 1.1 christos 458 1.1 christos if (!cfg_obj_isstring(classobj)) { 459 1.1 christos *classp = defclass; 460 1.17 christos return ISC_R_SUCCESS; 461 1.1 christos } 462 1.17 christos r.base = UNCONST(cfg_obj_asstring(classobj)); 463 1.1 christos r.length = strlen(r.base); 464 1.1 christos result = dns_rdataclass_fromtext(classp, &r); 465 1.8 christos if (result != ISC_R_SUCCESS) { 466 1.1 christos cfg_obj_log(classobj, named_g_lctx, ISC_LOG_ERROR, 467 1.1 christos "unknown class '%s'", r.base); 468 1.8 christos } 469 1.17 christos return result; 470 1.1 christos } 471 1.1 christos 472 1.1 christos isc_result_t 473 1.1 christos named_config_gettype(const cfg_obj_t *typeobj, dns_rdatatype_t deftype, 474 1.8 christos dns_rdatatype_t *typep) { 475 1.1 christos isc_textregion_t r; 476 1.1 christos isc_result_t result; 477 1.1 christos 478 1.1 christos if (!cfg_obj_isstring(typeobj)) { 479 1.1 christos *typep = deftype; 480 1.17 christos return ISC_R_SUCCESS; 481 1.1 christos } 482 1.17 christos r.base = UNCONST(cfg_obj_asstring(typeobj)); 483 1.1 christos r.length = strlen(r.base); 484 1.1 christos result = dns_rdatatype_fromtext(typep, &r); 485 1.8 christos if (result != ISC_R_SUCCESS) { 486 1.1 christos cfg_obj_log(typeobj, named_g_lctx, ISC_LOG_ERROR, 487 1.1 christos "unknown type '%s'", r.base); 488 1.8 christos } 489 1.17 christos return result; 490 1.1 christos } 491 1.1 christos 492 1.1 christos dns_zonetype_t 493 1.1 christos named_config_getzonetype(const cfg_obj_t *zonetypeobj) { 494 1.1 christos dns_zonetype_t ztype = dns_zone_none; 495 1.1 christos const char *str; 496 1.1 christos 497 1.1 christos str = cfg_obj_asstring(zonetypeobj); 498 1.8 christos if (strcasecmp(str, "primary") == 0 || strcasecmp(str, "master") == 0) { 499 1.13 christos ztype = dns_zone_primary; 500 1.3 christos } else if (strcasecmp(str, "secondary") == 0 || 501 1.14 christos strcasecmp(str, "slave") == 0) 502 1.14 christos { 503 1.13 christos ztype = dns_zone_secondary; 504 1.3 christos } else if (strcasecmp(str, "mirror") == 0) { 505 1.3 christos ztype = dns_zone_mirror; 506 1.3 christos } else if (strcasecmp(str, "stub") == 0) { 507 1.1 christos ztype = dns_zone_stub; 508 1.3 christos } else if (strcasecmp(str, "static-stub") == 0) { 509 1.1 christos ztype = dns_zone_staticstub; 510 1.3 christos } else if (strcasecmp(str, "redirect") == 0) { 511 1.1 christos ztype = dns_zone_redirect; 512 1.3 christos } else { 513 1.13 christos UNREACHABLE(); 514 1.3 christos } 515 1.17 christos return ztype; 516 1.1 christos } 517 1.1 christos 518 1.18 christos isc_result_t 519 1.18 christos named_config_getremotesdef(const cfg_obj_t *cctx, const char *list, 520 1.18 christos const char *name, const cfg_obj_t **ret) { 521 1.1 christos isc_result_t result; 522 1.10 christos const cfg_obj_t *obj = NULL; 523 1.1 christos const cfg_listelt_t *elt; 524 1.1 christos 525 1.10 christos REQUIRE(cctx != NULL); 526 1.10 christos REQUIRE(name != NULL); 527 1.10 christos REQUIRE(ret != NULL && *ret == NULL); 528 1.10 christos 529 1.10 christos result = cfg_map_get(cctx, list, &obj); 530 1.8 christos if (result != ISC_R_SUCCESS) { 531 1.17 christos return result; 532 1.8 christos } 533 1.10 christos elt = cfg_list_first(obj); 534 1.10 christos while (elt != NULL) { 535 1.10 christos obj = cfg_listelt_value(elt); 536 1.10 christos if (strcasecmp(cfg_obj_asstring(cfg_tuple_get(obj, "name")), 537 1.14 christos name) == 0) 538 1.14 christos { 539 1.10 christos *ret = obj; 540 1.17 christos return ISC_R_SUCCESS; 541 1.1 christos } 542 1.10 christos elt = cfg_list_next(elt); 543 1.1 christos } 544 1.17 christos return ISC_R_NOTFOUND; 545 1.1 christos } 546 1.1 christos 547 1.15 christos static isc_result_t 548 1.15 christos named_config_getname(isc_mem_t *mctx, const cfg_obj_t *obj, 549 1.15 christos dns_name_t **namep) { 550 1.15 christos REQUIRE(namep != NULL && *namep == NULL); 551 1.15 christos 552 1.15 christos const char *objstr; 553 1.15 christos isc_result_t result; 554 1.15 christos isc_buffer_t b; 555 1.15 christos dns_fixedname_t fname; 556 1.15 christos 557 1.15 christos if (!cfg_obj_isstring(obj)) { 558 1.15 christos *namep = NULL; 559 1.17 christos return ISC_R_SUCCESS; 560 1.15 christos } 561 1.15 christos 562 1.15 christos *namep = isc_mem_get(mctx, sizeof(**namep)); 563 1.15 christos dns_name_init(*namep, NULL); 564 1.15 christos 565 1.15 christos objstr = cfg_obj_asstring(obj); 566 1.15 christos isc_buffer_constinit(&b, objstr, strlen(objstr)); 567 1.15 christos isc_buffer_add(&b, strlen(objstr)); 568 1.15 christos dns_fixedname_init(&fname); 569 1.15 christos result = dns_name_fromtext(dns_fixedname_name(&fname), &b, dns_rootname, 570 1.15 christos 0, NULL); 571 1.15 christos if (result != ISC_R_SUCCESS) { 572 1.15 christos isc_mem_put(mctx, *namep, sizeof(**namep)); 573 1.15 christos *namep = NULL; 574 1.17 christos return result; 575 1.15 christos } 576 1.15 christos dns_name_dup(dns_fixedname_name(&fname), mctx, *namep); 577 1.15 christos 578 1.17 christos return ISC_R_SUCCESS; 579 1.15 christos } 580 1.15 christos 581 1.17 christos #define grow_array(mctx, array, newlen, oldlen) \ 582 1.17 christos if (newlen >= oldlen) { \ 583 1.17 christos array = isc_mem_creget(mctx, array, oldlen, newlen + 16, \ 584 1.17 christos sizeof(array[0])); \ 585 1.17 christos oldlen = newlen + 16; \ 586 1.17 christos } 587 1.17 christos 588 1.17 christos #define shrink_array(mctx, array, newlen, oldlen) \ 589 1.17 christos if (newlen < oldlen) { \ 590 1.17 christos array = isc_mem_creget(mctx, array, oldlen, newlen, \ 591 1.17 christos sizeof(array[0])); \ 592 1.17 christos oldlen = newlen; \ 593 1.15 christos } 594 1.15 christos 595 1.18 christos static const char *remotesnames[4] = { "remote-servers", "parental-agents", 596 1.18 christos "primaries", "masters" }; 597 1.18 christos 598 1.20 christos typedef struct { 599 1.20 christos isc_sockaddr_t *addrs; 600 1.20 christos size_t addrsallocated; 601 1.20 christos 602 1.20 christos isc_sockaddr_t *sources; 603 1.20 christos size_t sourcesallocated; 604 1.20 christos 605 1.20 christos dns_name_t **keys; 606 1.20 christos size_t keysallocated; 607 1.1 christos 608 1.20 christos dns_name_t **tlss; 609 1.20 christos size_t tlssallocated; 610 1.1 christos 611 1.20 christos size_t count; /* common to addrs, sources, keys and tlss */ 612 1.1 christos 613 1.20 christos const char **seen; 614 1.20 christos size_t seencount; 615 1.20 christos size_t seenallocated; 616 1.20 christos } getipandkeylist_state_t; 617 1.1 christos 618 1.20 christos static isc_result_t 619 1.20 christos getipandkeylist(in_port_t defport, in_port_t deftlsport, 620 1.20 christos const cfg_obj_t *config, const cfg_obj_t *list, 621 1.20 christos in_port_t listport, const cfg_obj_t *listkey, 622 1.20 christos const cfg_obj_t *listtls, isc_mem_t *mctx, 623 1.20 christos getipandkeylist_state_t *s) { 624 1.20 christos const cfg_obj_t *addrlist = cfg_tuple_get(list, "addresses"); 625 1.20 christos const cfg_obj_t *portobj = cfg_tuple_get(list, "port"); 626 1.20 christos const cfg_obj_t *src4obj = cfg_tuple_get(list, "source"); 627 1.20 christos const cfg_obj_t *src6obj = cfg_tuple_get(list, "source-v6"); 628 1.20 christos in_port_t port = (in_port_t)0; 629 1.20 christos isc_sockaddr_t src4; 630 1.20 christos isc_sockaddr_t src6; 631 1.20 christos isc_result_t result = ISC_R_SUCCESS; 632 1.1 christos 633 1.1 christos if (cfg_obj_isuint32(portobj)) { 634 1.3 christos uint32_t val = cfg_obj_asuint32(portobj); 635 1.3 christos if (val > UINT16_MAX) { 636 1.1 christos cfg_obj_log(portobj, named_g_lctx, ISC_LOG_ERROR, 637 1.1 christos "port '%u' out of range", val); 638 1.20 christos return ISC_R_RANGE; 639 1.1 christos } 640 1.8 christos port = (in_port_t)val; 641 1.20 christos } else if (listport > 0) { 642 1.20 christos /* 643 1.20 christos * No port in the current list, but it is a list named elsewhere 644 1.20 christos * where the port is defined, i.e: 645 1.20 christos * 646 1.20 christos * remote-servers bar { 10.53.0.4; }; 647 1.20 christos * remote-servers foo port 5555 { bar; 10.54.0.3; }; 648 1.20 christos * ^^^ 649 1.20 christos * 650 1.20 christos * The current list is the list `bar`, and the server 651 1.20 christos * `10.53.0.4` has the port `5555` defined. 652 1.20 christos */ 653 1.20 christos port = listport; 654 1.1 christos } 655 1.1 christos 656 1.17 christos if (src4obj != NULL && cfg_obj_issockaddr(src4obj)) { 657 1.17 christos src4 = *cfg_obj_assockaddr(src4obj); 658 1.17 christos } else { 659 1.17 christos isc_sockaddr_any(&src4); 660 1.17 christos } 661 1.17 christos 662 1.17 christos if (src6obj != NULL && cfg_obj_issockaddr(src6obj)) { 663 1.17 christos src6 = *cfg_obj_assockaddr(src6obj); 664 1.17 christos } else { 665 1.17 christos isc_sockaddr_any6(&src6); 666 1.17 christos } 667 1.17 christos 668 1.20 christos for (const cfg_listelt_t *element = cfg_list_first(addrlist); 669 1.20 christos element != NULL; element = cfg_list_next(element)) 670 1.20 christos { 671 1.1 christos const cfg_obj_t *addr; 672 1.1 christos const cfg_obj_t *key; 673 1.15 christos const cfg_obj_t *tls; 674 1.1 christos 675 1.20 christos skiplist: 676 1.1 christos addr = cfg_tuple_get(cfg_listelt_value(element), 677 1.12 christos "remoteselement"); 678 1.1 christos key = cfg_tuple_get(cfg_listelt_value(element), "key"); 679 1.15 christos tls = cfg_tuple_get(cfg_listelt_value(element), "tls"); 680 1.1 christos 681 1.20 christos /* 682 1.20 christos * If this is not an address, this is the name of a nested list, 683 1.20 christos * i.e. 684 1.20 christos * 685 1.20 christos * remote-servers nestedlist { 10.53.0.4; }; 686 1.20 christos * remote-servers list { nestedlist key foo; 10.54.0.6; }; 687 1.20 christos * ^^^^^^^^^^^^^^^^^^ 688 1.20 christos * 689 1.20 christos * We are currently in the list `list`, and `addr` is the name 690 1.20 christos * `nestedlist`, so we'll immediately recurse to process 691 1.20 christos * `nestedlist` before processing the next element of `list`. 692 1.20 christos */ 693 1.1 christos if (!cfg_obj_issockaddr(addr)) { 694 1.1 christos const char *listname = cfg_obj_asstring(addr); 695 1.20 christos const cfg_obj_t *nestedlist = NULL; 696 1.1 christos isc_result_t tresult; 697 1.1 christos 698 1.20 christos for (size_t i = 0; i < s->seencount; i++) { 699 1.20 christos if (strcasecmp(s->seen[i], listname) == 0) { 700 1.20 christos element = cfg_list_next(element); 701 1.20 christos goto skiplist; 702 1.8 christos } 703 1.8 christos } 704 1.20 christos 705 1.20 christos grow_array(mctx, s->seen, s->seencount, 706 1.20 christos s->seenallocated); 707 1.20 christos s->seen[s->seencount] = listname; 708 1.20 christos 709 1.20 christos for (size_t i = 0; i < ARRAY_SIZE(remotesnames); i++) { 710 1.18 christos tresult = named_config_getremotesdef( 711 1.20 christos config, remotesnames[i], listname, 712 1.20 christos &nestedlist); 713 1.18 christos if (tresult == ISC_R_SUCCESS) { 714 1.18 christos break; 715 1.18 christos } 716 1.18 christos } 717 1.20 christos 718 1.20 christos if (tresult != ISC_R_SUCCESS) { 719 1.1 christos cfg_obj_log(addr, named_g_lctx, ISC_LOG_ERROR, 720 1.18 christos "remote-servers \"%s\" not found", 721 1.8 christos listname); 722 1.20 christos return tresult; 723 1.1 christos } 724 1.20 christos 725 1.20 christos result = getipandkeylist(defport, deftlsport, config, 726 1.20 christos nestedlist, port, key, tls, 727 1.20 christos mctx, s); 728 1.20 christos if (result != ISC_R_SUCCESS) { 729 1.20 christos goto out; 730 1.8 christos } 731 1.20 christos continue; 732 1.20 christos } 733 1.20 christos 734 1.20 christos grow_array(mctx, s->addrs, s->count, s->addrsallocated); 735 1.20 christos grow_array(mctx, s->keys, s->count, s->keysallocated); 736 1.20 christos grow_array(mctx, s->tlss, s->count, s->tlssallocated); 737 1.20 christos grow_array(mctx, s->sources, s->count, s->sourcesallocated); 738 1.15 christos 739 1.20 christos s->addrs[s->count] = *cfg_obj_assockaddr(addr); 740 1.1 christos 741 1.20 christos result = named_config_getname(mctx, key, &s->keys[s->count]); 742 1.15 christos if (result != ISC_R_SUCCESS) { 743 1.20 christos goto out; 744 1.15 christos } 745 1.1 christos 746 1.20 christos /* 747 1.20 christos * The `key` is not provided for this address, so, if we're 748 1.20 christos * inside a named list, get the `key` provided at the point the 749 1.20 christos * list is used. 750 1.20 christos */ 751 1.20 christos if (s->keys[s->count] == NULL && listkey != NULL) { 752 1.20 christos result = named_config_getname(mctx, listkey, 753 1.20 christos &s->keys[s->count]); 754 1.20 christos if (result != ISC_R_SUCCESS) { 755 1.20 christos goto out; 756 1.20 christos } 757 1.20 christos } 758 1.20 christos 759 1.20 christos result = named_config_getname(mctx, tls, &s->tlss[s->count]); 760 1.15 christos if (result != ISC_R_SUCCESS) { 761 1.20 christos goto out; 762 1.20 christos } 763 1.20 christos 764 1.20 christos /* 765 1.20 christos * The `tls` is not provided for this address, so, if we're 766 1.20 christos * inside a named list, get the `tls` provided at the point the 767 1.20 christos * named list is used. 768 1.20 christos */ 769 1.20 christos if (s->tlss[s->count] == NULL && listtls != NULL) { 770 1.20 christos result = named_config_getname(mctx, listtls, 771 1.20 christos &s->tlss[s->count]); 772 1.1 christos } 773 1.1 christos 774 1.15 christos /* If the port is unset, take it from one of the upper levels */ 775 1.20 christos if (isc_sockaddr_getport(&s->addrs[s->count]) == 0) { 776 1.15 christos in_port_t addr_port = port; 777 1.15 christos 778 1.15 christos /* If unset, use the default port or tls-port */ 779 1.15 christos if (addr_port == 0) { 780 1.20 christos if (s->tlss[s->count] != NULL) { 781 1.20 christos addr_port = deftlsport; 782 1.15 christos } else { 783 1.20 christos addr_port = defport; 784 1.15 christos } 785 1.15 christos } 786 1.15 christos 787 1.20 christos isc_sockaddr_setport(&s->addrs[s->count], addr_port); 788 1.8 christos } 789 1.1 christos 790 1.20 christos switch (isc_sockaddr_pf(&s->addrs[s->count])) { 791 1.17 christos case PF_INET: 792 1.20 christos s->sources[s->count] = src4; 793 1.17 christos break; 794 1.17 christos case PF_INET6: 795 1.20 christos s->sources[s->count] = src6; 796 1.17 christos break; 797 1.17 christos default: 798 1.17 christos result = ISC_R_NOTIMPLEMENTED; 799 1.20 christos goto out; 800 1.17 christos } 801 1.17 christos 802 1.20 christos s->count++; 803 1.20 christos } 804 1.20 christos 805 1.20 christos out: 806 1.20 christos if (result != ISC_R_SUCCESS) { 807 1.20 christos /* 808 1.20 christos * Reaching this point without success means we were in the 809 1.20 christos * middle of adding a new entry, so it needs to be counted for 810 1.20 christos * correctly free `s.keys` and `s.tlss` (as they potentially 811 1.20 christos * added a new element right before something fails) 812 1.20 christos */ 813 1.20 christos s->count++; 814 1.20 christos } 815 1.20 christos return result; 816 1.20 christos } 817 1.20 christos 818 1.20 christos isc_result_t 819 1.20 christos named_config_getipandkeylist(const cfg_obj_t *config, const cfg_obj_t *list, 820 1.20 christos isc_mem_t *mctx, dns_ipkeylist_t *ipkl) { 821 1.20 christos isc_result_t result; 822 1.20 christos in_port_t def_port; 823 1.20 christos in_port_t def_tlsport; 824 1.20 christos getipandkeylist_state_t s = {}; 825 1.20 christos 826 1.20 christos REQUIRE(ipkl != NULL); 827 1.20 christos REQUIRE(ipkl->count == 0); 828 1.20 christos REQUIRE(ipkl->addrs == NULL); 829 1.20 christos REQUIRE(ipkl->keys == NULL); 830 1.20 christos REQUIRE(ipkl->tlss == NULL); 831 1.20 christos REQUIRE(ipkl->labels == NULL); 832 1.20 christos REQUIRE(ipkl->allocated == 0); 833 1.20 christos 834 1.20 christos /* 835 1.20 christos * Get system defaults. 836 1.20 christos */ 837 1.20 christos result = named_config_getport(config, "port", &def_port); 838 1.20 christos if (result != ISC_R_SUCCESS) { 839 1.20 christos goto cleanup; 840 1.20 christos } 841 1.20 christos 842 1.20 christos result = named_config_getport(config, "tls-port", &def_tlsport); 843 1.20 christos if (result != ISC_R_SUCCESS) { 844 1.20 christos goto cleanup; 845 1.20 christos } 846 1.20 christos 847 1.20 christos /* 848 1.20 christos * Process the (nested) list(s). 849 1.20 christos */ 850 1.20 christos result = getipandkeylist(def_port, def_tlsport, config, list, 851 1.20 christos (in_port_t)0, NULL, NULL, mctx, &s); 852 1.20 christos if (result != ISC_R_SUCCESS) { 853 1.20 christos goto cleanup; 854 1.20 christos } 855 1.20 christos 856 1.20 christos shrink_array(mctx, s.addrs, s.count, s.addrsallocated); 857 1.20 christos shrink_array(mctx, s.keys, s.count, s.keysallocated); 858 1.20 christos shrink_array(mctx, s.tlss, s.count, s.tlssallocated); 859 1.20 christos shrink_array(mctx, s.sources, s.count, s.sourcesallocated); 860 1.20 christos 861 1.20 christos ipkl->addrs = s.addrs; 862 1.20 christos ipkl->keys = s.keys; 863 1.20 christos ipkl->tlss = s.tlss; 864 1.20 christos ipkl->sources = s.sources; 865 1.20 christos ipkl->count = s.count; 866 1.20 christos 867 1.20 christos INSIST(s.addrsallocated == s.keysallocated); 868 1.20 christos INSIST(s.addrsallocated == s.tlssallocated); 869 1.20 christos INSIST(s.addrsallocated == s.sourcesallocated); 870 1.20 christos ipkl->allocated = s.addrsallocated; 871 1.20 christos 872 1.20 christos if (s.seen != NULL) { 873 1.20 christos /* 874 1.20 christos * `s.seen` is not shrinked (no point, as it's deleted right 875 1.20 christos * away anyway), so we need to use `s.seenallocated` to 876 1.20 christos * correctly free the array. 877 1.20 christos */ 878 1.20 christos isc_mem_cput(mctx, s.seen, s.seenallocated, sizeof(s.seen[0])); 879 1.1 christos } 880 1.1 christos 881 1.17 christos return ISC_R_SUCCESS; 882 1.1 christos 883 1.8 christos cleanup: 884 1.20 christos /* 885 1.20 christos * Because we didn't shrinked the array back in this path, we need to 886 1.20 christos * use `s.*allocated` to correctly free the allocated arrays. 887 1.20 christos */ 888 1.20 christos if (s.addrs != NULL) { 889 1.20 christos isc_mem_cput(mctx, s.addrs, s.count, sizeof(s.addrs[0])); 890 1.8 christos } 891 1.20 christos if (s.keys != NULL) { 892 1.20 christos for (size_t i = 0; i < s.count; i++) { 893 1.20 christos if (s.keys[i] == NULL) { 894 1.1 christos continue; 895 1.8 christos } 896 1.20 christos if (dns_name_dynamic(s.keys[i])) { 897 1.20 christos dns_name_free(s.keys[i], mctx); 898 1.8 christos } 899 1.20 christos isc_mem_put(mctx, s.keys[i], sizeof(*s.keys[i])); 900 1.15 christos } 901 1.20 christos isc_mem_cput(mctx, s.keys, s.keysallocated, sizeof(s.keys[0])); 902 1.15 christos } 903 1.20 christos if (s.tlss != NULL) { 904 1.20 christos for (size_t i = 0; i < s.count; i++) { 905 1.20 christos if (s.tlss[i] == NULL) { 906 1.15 christos continue; 907 1.15 christos } 908 1.20 christos if (dns_name_dynamic(s.tlss[i])) { 909 1.20 christos dns_name_free(s.tlss[i], mctx); 910 1.15 christos } 911 1.20 christos isc_mem_put(mctx, s.tlss[i], sizeof(*s.tlss[i])); 912 1.1 christos } 913 1.20 christos isc_mem_cput(mctx, s.tlss, s.tlssallocated, sizeof(s.tlss[0])); 914 1.17 christos } 915 1.20 christos if (s.sources != NULL) { 916 1.20 christos isc_mem_cput(mctx, s.sources, s.sourcesallocated, 917 1.20 christos sizeof(s.sources[0])); 918 1.1 christos } 919 1.20 christos if (s.seen != NULL) { 920 1.20 christos isc_mem_cput(mctx, s.seen, s.seenallocated, sizeof(s.seen[0])); 921 1.8 christos } 922 1.20 christos 923 1.17 christos return result; 924 1.1 christos } 925 1.1 christos 926 1.1 christos isc_result_t 927 1.15 christos named_config_getport(const cfg_obj_t *config, const char *type, 928 1.15 christos in_port_t *portp) { 929 1.1 christos const cfg_obj_t *maps[3]; 930 1.1 christos const cfg_obj_t *options = NULL; 931 1.1 christos const cfg_obj_t *portobj = NULL; 932 1.1 christos isc_result_t result; 933 1.1 christos int i; 934 1.1 christos 935 1.1 christos (void)cfg_map_get(config, "options", &options); 936 1.1 christos i = 0; 937 1.8 christos if (options != NULL) { 938 1.1 christos maps[i++] = options; 939 1.8 christos } 940 1.1 christos maps[i++] = named_g_defaults; 941 1.1 christos maps[i] = NULL; 942 1.1 christos 943 1.15 christos result = named_config_get(maps, type, &portobj); 944 1.1 christos INSIST(result == ISC_R_SUCCESS); 945 1.3 christos if (cfg_obj_asuint32(portobj) >= UINT16_MAX) { 946 1.1 christos cfg_obj_log(portobj, named_g_lctx, ISC_LOG_ERROR, 947 1.1 christos "port '%u' out of range", 948 1.1 christos cfg_obj_asuint32(portobj)); 949 1.17 christos return ISC_R_RANGE; 950 1.1 christos } 951 1.1 christos *portp = (in_port_t)cfg_obj_asuint32(portobj); 952 1.17 christos return ISC_R_SUCCESS; 953 1.1 christos } 954 1.1 christos 955 1.1 christos struct keyalgorithms { 956 1.1 christos const char *str; 957 1.10 christos enum { 958 1.10 christos hmacnone, 959 1.10 christos hmacmd5, 960 1.10 christos hmacsha1, 961 1.10 christos hmacsha224, 962 1.10 christos hmacsha256, 963 1.10 christos hmacsha384, 964 1.10 christos hmacsha512 965 1.10 christos } hmac; 966 1.1 christos unsigned int type; 967 1.3 christos uint16_t size; 968 1.8 christos } algorithms[] = { { "hmac-md5", hmacmd5, DST_ALG_HMACMD5, 128 }, 969 1.8 christos { "hmac-md5.sig-alg.reg.int", hmacmd5, DST_ALG_HMACMD5, 0 }, 970 1.8 christos { "hmac-md5.sig-alg.reg.int.", hmacmd5, DST_ALG_HMACMD5, 0 }, 971 1.8 christos { "hmac-sha1", hmacsha1, DST_ALG_HMACSHA1, 160 }, 972 1.8 christos { "hmac-sha224", hmacsha224, DST_ALG_HMACSHA224, 224 }, 973 1.8 christos { "hmac-sha256", hmacsha256, DST_ALG_HMACSHA256, 256 }, 974 1.8 christos { "hmac-sha384", hmacsha384, DST_ALG_HMACSHA384, 384 }, 975 1.8 christos { "hmac-sha512", hmacsha512, DST_ALG_HMACSHA512, 512 }, 976 1.8 christos { NULL, hmacnone, DST_ALG_UNKNOWN, 0 } }; 977 1.1 christos 978 1.1 christos isc_result_t 979 1.17 christos named_config_getkeyalgorithm(const char *str, unsigned int *typep, 980 1.8 christos uint16_t *digestbits) { 981 1.1 christos int i; 982 1.1 christos size_t len = 0; 983 1.3 christos uint16_t bits; 984 1.1 christos isc_result_t result; 985 1.1 christos 986 1.1 christos for (i = 0; algorithms[i].str != NULL; i++) { 987 1.1 christos len = strlen(algorithms[i].str); 988 1.1 christos if (strncasecmp(algorithms[i].str, str, len) == 0 && 989 1.1 christos (str[len] == '\0' || 990 1.1 christos (algorithms[i].size != 0 && str[len] == '-'))) 991 1.8 christos { 992 1.1 christos break; 993 1.8 christos } 994 1.1 christos } 995 1.8 christos if (algorithms[i].str == NULL) { 996 1.17 christos return ISC_R_NOTFOUND; 997 1.8 christos } 998 1.1 christos if (str[len] == '-') { 999 1.1 christos result = isc_parse_uint16(&bits, str + len + 1, 10); 1000 1.8 christos if (result != ISC_R_SUCCESS) { 1001 1.17 christos return result; 1002 1.8 christos } 1003 1.8 christos if (bits > algorithms[i].size) { 1004 1.17 christos return ISC_R_RANGE; 1005 1.8 christos } 1006 1.8 christos } else if (algorithms[i].size == 0) { 1007 1.1 christos bits = 128; 1008 1.8 christos } else { 1009 1.1 christos bits = algorithms[i].size; 1010 1.8 christos } 1011 1.17 christos SET_IF_NOT_NULL(typep, algorithms[i].type); 1012 1.17 christos SET_IF_NOT_NULL(digestbits, bits); 1013 1.17 christos return ISC_R_SUCCESS; 1014 1.1 christos } 1015