config.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2004-2015  Internet Systems Consortium, Inc. ("ISC")
00003  * Copyright (C) 2001-2003  Internet Software Consortium.
00004  *
00005  * Permission to use, copy, modify, and/or distribute this software for any
00006  * purpose with or without fee is hereby granted, provided that the above
00007  * copyright notice and this permission notice appear in all copies.
00008  *
00009  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
00010  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00011  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
00012  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00013  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00014  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00015  * PERFORMANCE OF THIS SOFTWARE.
00016  */
00017 
00018 /*! \file */
00019 
00020 #include <config.h>
00021 
00022 #include <stdlib.h>
00023 
00024 #include <isc/buffer.h>
00025 #include <isc/log.h>
00026 #include <isc/mem.h>
00027 #include <isc/parseint.h>
00028 #include <isc/region.h>
00029 #include <isc/result.h>
00030 #include <isc/sockaddr.h>
00031 #include <isc/string.h>
00032 #include <isc/util.h>
00033 
00034 #include <isccfg/namedconf.h>
00035 
00036 #include <dns/fixedname.h>
00037 #include <dns/name.h>
00038 #include <dns/rdataclass.h>
00039 #include <dns/rdatatype.h>
00040 #include <dns/tsig.h>
00041 #include <dns/zone.h>
00042 
00043 #include <dst/dst.h>
00044 
00045 #include <named/config.h>
00046 #include <named/globals.h>
00047 
00048 #include <bind.keys.h>
00049 
00050 /*% default configuration */
00051 static char defaultconf[] = "\
00052 options {\n\
00053         automatic-interface-scan yes;\n\
00054         bindkeys-file \"" NS_SYSCONFDIR "/bind.keys\";\n\
00055 #       blackhole {none;};\n"
00056 #ifndef WIN32
00057 "       coresize default;\n\
00058         datasize default;\n\
00059         files unlimited;\n\
00060         stacksize default;\n"
00061 #endif
00062 "#      session-keyfile \"" NS_LOCALSTATEDIR "/run/named/session.key\";\n\
00063         session-keyname local-ddns;\n\
00064         session-keyalg hmac-sha256;\n\
00065         deallocate-on-exit true;\n\
00066 #       directory <none>\n\
00067         dump-file \"named_dump.db\";\n\
00068         fake-iquery no;\n\
00069         has-old-clients false;\n\
00070         heartbeat-interval 60;\n\
00071         host-statistics no;\n\
00072         interface-interval 60;\n\
00073 #       keep-response-order {none;};\n\
00074         listen-on {any;};\n\
00075         listen-on-v6 {any;};\n\
00076         match-mapped-addresses no;\n\
00077         max-rsa-exponent-size 0; /* no limit */\n\
00078         memstatistics-file \"named.memstats\";\n\
00079         multiple-cnames no;\n\
00080 #       named-xfer <obsolete>;\n\
00081         nta-lifetime 3600;\n\
00082         nta-recheck 300;\n\
00083         notify-rate 20;\n\
00084 #       pid-file \"" NS_LOCALSTATEDIR "/run/named/named.pid\"; /* or /lwresd.pid */\n\
00085 #       lock-file \"" NS_LOCALSTATEDIR "/run/named/named.lock\";\n\
00086         port 53;\n\
00087         prefetch 2 9;\n\
00088         recursing-file \"named.recursing\";\n\
00089         secroots-file \"named.secroots\";\n\
00090 "
00091 #ifdef PATH_RANDOMDEV
00092 "\
00093         random-device \"" PATH_RANDOMDEV "\";\n\
00094 "
00095 #endif
00096 "\
00097         recursive-clients 1000;\n\
00098         resolver-query-timeout 10;\n\
00099         rrset-order { order random; };\n\
00100         serial-queries 20;\n\
00101         serial-query-rate 20;\n\
00102         server-id none;\n\
00103         startup-notify-rate 20;\n\
00104         statistics-file \"named.stats\";\n\
00105         statistics-interval 60;\n\
00106         tcp-clients 150;\n\
00107         tcp-listen-queue 10;\n\
00108 #       tkey-dhkey <none>\n\
00109 #       tkey-gssapi-credential <none>\n\
00110 #       tkey-domain <none>\n\
00111         transfers-per-ns 2;\n\
00112         transfers-in 10;\n\
00113         transfers-out 10;\n\
00114         treat-cr-as-space true;\n\
00115         use-id-pool true;\n\
00116         use-ixfr true;\n\
00117         edns-udp-size 4096;\n\
00118         max-udp-size 4096;\n\
00119 "
00120 #ifdef ISC_PLATFORM_USESIT
00121 "\
00122         nosit-udp-size 4096;\n\
00123         request-sit true;\n\
00124 "
00125 #endif
00126 "\
00127         request-nsid false;\n\
00128         reserved-sockets 512;\n\
00129 \n\
00130         /* DLV */\n\
00131         dnssec-lookaside . trust-anchor dlv.isc.org;\n\
00132 \n\
00133         /* view */\n\
00134         allow-notify {none;};\n\
00135         allow-update-forwarding {none;};\n\
00136         allow-query-cache { localnets; localhost; };\n\
00137         allow-query-cache-on { any; };\n\
00138         allow-recursion { localnets; localhost; };\n\
00139         allow-recursion-on { any; };\n\
00140 #       allow-v6-synthesis <obsolete>;\n\
00141 #       sortlist <none>\n\
00142 #       topology <none>\n\
00143         auth-nxdomain false;\n\
00144         minimal-responses false;\n\
00145         recursion true;\n\
00146         provide-ixfr true;\n\
00147         request-ixfr true;\n\
00148         request-expire true;\n\
00149         fetch-glue no;\n\
00150         rfc2308-type1 no;\n\
00151         additional-from-auth true;\n\
00152         additional-from-cache true;\n\
00153         query-source address *;\n\
00154         query-source-v6 address *;\n\
00155         notify-source *;\n\
00156         notify-source-v6 *;\n\
00157         cleaning-interval 0;  /* now meaningless */\n\
00158         min-roots 2;\n\
00159         lame-ttl 600;\n\
00160         servfail-ttl 10;\n\
00161         max-ncache-ttl 10800; /* 3 hours */\n\
00162         max-cache-ttl 604800; /* 1 week */\n\
00163         transfer-format many-answers;\n\
00164         max-cache-size 0;\n\
00165         check-names master fail;\n\
00166         check-names slave warn;\n\
00167         check-names response ignore;\n\
00168         check-dup-records warn;\n\
00169         check-mx warn;\n\
00170         check-spf warn;\n\
00171         acache-enable no;\n\
00172         acache-cleaning-interval 60;\n\
00173         max-acache-size 16M;\n\
00174         dnssec-enable yes;\n\
00175         dnssec-validation yes; \n\
00176         dnssec-accept-expired no;\n\
00177         clients-per-query 10;\n\
00178         max-clients-per-query 100;\n\
00179         max-recursion-depth 7;\n\
00180         max-recursion-queries 75;\n\
00181         zero-no-soa-ttl-cache no;\n\
00182         nsec3-test-zone no;\n\
00183         allow-new-zones no;\n\
00184 "
00185 #ifdef HAVE_GEOIP
00186 "\
00187         geoip-use-ecs yes;\n\
00188 "
00189 #endif
00190 #ifdef ALLOW_FILTER_AAAA
00191 "       filter-aaaa-on-v4 no;\n\
00192         filter-aaaa-on-v6 no;\n\
00193         filter-aaaa { any; };\n\
00194 "
00195 #endif
00196 
00197 "       /* zone */\n\
00198         allow-query {any;};\n\
00199         allow-query-on {any;};\n\
00200         allow-transfer {any;};\n\
00201         notify yes;\n\
00202 #       also-notify <none>\n\
00203         notify-delay 5;\n\
00204         notify-to-soa no;\n\
00205         dialup no;\n\
00206 #       forward <none>\n\
00207 #       forwarders <none>\n\
00208         maintain-ixfr-base no;\n\
00209 #       max-ixfr-log-size <obsolete>\n\
00210         transfer-source *;\n\
00211         transfer-source-v6 *;\n\
00212         alt-transfer-source *;\n\
00213         alt-transfer-source-v6 *;\n\
00214         max-transfer-time-in 120;\n\
00215         max-transfer-time-out 120;\n\
00216         max-transfer-idle-in 60;\n\
00217         max-transfer-idle-out 60;\n\
00218         max-retry-time 1209600; /* 2 weeks */\n\
00219         min-retry-time 500;\n\
00220         max-refresh-time 2419200; /* 4 weeks */\n\
00221         min-refresh-time 300;\n\
00222         multi-master no;\n\
00223         dnssec-secure-to-insecure no;\n\
00224         sig-validity-interval 30; /* days */\n\
00225         sig-signing-nodes 100;\n\
00226         sig-signing-signatures 10;\n\
00227         sig-signing-type 65534;\n\
00228         inline-signing no;\n\
00229         zone-statistics terse;\n\
00230         max-journal-size unlimited;\n\
00231         ixfr-from-differences false;\n\
00232         check-wildcard yes;\n\
00233         check-sibling yes;\n\
00234         check-integrity yes;\n\
00235         check-mx-cname warn;\n\
00236         check-srv-cname warn;\n\
00237         zero-no-soa-ttl yes;\n\
00238         update-check-ksk yes;\n\
00239         serial-update-method increment;\n\
00240         dnssec-update-mode maintain;\n\
00241         dnssec-dnskey-kskonly no;\n\
00242         dnssec-loadkeys-interval 60;\n\
00243         try-tcp-refresh yes; /* BIND 8 compat */\n\
00244 };\n\
00245 "
00246 
00247 "#\n\
00248 #  Zones in the \"_bind\" view are NOT counted in the count of zones.\n\
00249 #\n\
00250 view \"_bind\" chaos {\n\
00251         recursion no;\n\
00252         notify no;\n\
00253         allow-new-zones no;\n\
00254 \n\
00255         # Prevent use of this zone in DNS amplified reflection DoS attacks\n\
00256         rate-limit {\n\
00257                 responses-per-second 3;\n\
00258                 slip 0;\n\
00259                 min-table-size 10;\n\
00260         };\n\
00261 \n\
00262         zone \"version.bind\" chaos {\n\
00263                 type master;\n\
00264                 database \"_builtin version\";\n\
00265         };\n\
00266 \n\
00267         zone \"hostname.bind\" chaos {\n\
00268                 type master;\n\
00269                 database \"_builtin hostname\";\n\
00270         };\n\
00271 \n\
00272         zone \"authors.bind\" chaos {\n\
00273                 type master;\n\
00274                 database \"_builtin authors\";\n\
00275         };\n\
00276 \n\
00277         zone \"id.server\" chaos {\n\
00278                 type master;\n\
00279                 database \"_builtin id\";\n\
00280         };\n\
00281 };\n\
00282 "
00283 "#\n\
00284 #  Default trusted key(s) for builtin DLV support\n\
00285 #  (used if \"dnssec-lookaside auto;\" is set and\n\
00286 #  sysconfdir/bind.keys doesn't exist).\n\
00287 #\n\
00288 # BEGIN MANAGED KEYS\n"
00289 
00290 /* Imported from bind.keys.h: */
00291 MANAGED_KEYS
00292 
00293 "# END MANAGED KEYS\n\
00294 ";
00295 
00296 isc_result_t
00297 ns_config_parsedefaults(cfg_parser_t *parser, cfg_obj_t **conf) {
00298         isc_buffer_t b;
00299 
00300         isc_buffer_init(&b, defaultconf, sizeof(defaultconf) - 1);
00301         isc_buffer_add(&b, sizeof(defaultconf) - 1);
00302         return (cfg_parse_buffer(parser, &b, &cfg_type_namedconf, conf));
00303 }
00304 
00305 isc_result_t
00306 ns_config_get(cfg_obj_t const * const *maps, const char *name,
00307               const cfg_obj_t **obj)
00308 {
00309         int i;
00310 
00311         for (i = 0;; i++) {
00312                 if (maps[i] == NULL)
00313                         return (ISC_R_NOTFOUND);
00314                 if (cfg_map_get(maps[i], name, obj) == ISC_R_SUCCESS)
00315                         return (ISC_R_SUCCESS);
00316         }
00317 }
00318 
00319 isc_result_t
00320 ns_checknames_get(const cfg_obj_t **maps, const char *which,
00321                   const cfg_obj_t **obj)
00322 {
00323         const cfg_listelt_t *element;
00324         const cfg_obj_t *checknames;
00325         const cfg_obj_t *type;
00326         const cfg_obj_t *value;
00327         int i;
00328 
00329         for (i = 0;; i++) {
00330                 if (maps[i] == NULL)
00331                         return (ISC_R_NOTFOUND);
00332                 checknames = NULL;
00333                 if (cfg_map_get(maps[i], "check-names",
00334                                 &checknames) == ISC_R_SUCCESS) {
00335                         /*
00336                          * Zone map entry is not a list.
00337                          */
00338                         if (checknames != NULL && !cfg_obj_islist(checknames)) {
00339                                 *obj = checknames;
00340                                 return (ISC_R_SUCCESS);
00341                         }
00342                         for (element = cfg_list_first(checknames);
00343                              element != NULL;
00344                              element = cfg_list_next(element)) {
00345                                 value = cfg_listelt_value(element);
00346                                 type = cfg_tuple_get(value, "type");
00347                                 if (strcasecmp(cfg_obj_asstring(type),
00348                                                which) == 0) {
00349                                         *obj = cfg_tuple_get(value, "mode");
00350                                         return (ISC_R_SUCCESS);
00351                                 }
00352                         }
00353 
00354                 }
00355         }
00356 }
00357 
00358 int
00359 ns_config_listcount(const cfg_obj_t *list) {
00360         const cfg_listelt_t *e;
00361         int i = 0;
00362 
00363         for (e = cfg_list_first(list); e != NULL; e = cfg_list_next(e))
00364                 i++;
00365 
00366         return (i);
00367 }
00368 
00369 isc_result_t
00370 ns_config_getclass(const cfg_obj_t *classobj, dns_rdataclass_t defclass,
00371                    dns_rdataclass_t *classp) {
00372         isc_textregion_t r;
00373         isc_result_t result;
00374 
00375         if (!cfg_obj_isstring(classobj)) {
00376                 *classp = defclass;
00377                 return (ISC_R_SUCCESS);
00378         }
00379         DE_CONST(cfg_obj_asstring(classobj), r.base);
00380         r.length = strlen(r.base);
00381         result = dns_rdataclass_fromtext(classp, &r);
00382         if (result != ISC_R_SUCCESS)
00383                 cfg_obj_log(classobj, ns_g_lctx, ISC_LOG_ERROR,
00384                             "unknown class '%s'", r.base);
00385         return (result);
00386 }
00387 
00388 isc_result_t
00389 ns_config_gettype(const cfg_obj_t *typeobj, dns_rdatatype_t deftype,
00390                    dns_rdatatype_t *typep) {
00391         isc_textregion_t r;
00392         isc_result_t result;
00393 
00394         if (!cfg_obj_isstring(typeobj)) {
00395                 *typep = deftype;
00396                 return (ISC_R_SUCCESS);
00397         }
00398         DE_CONST(cfg_obj_asstring(typeobj), r.base);
00399         r.length = strlen(r.base);
00400         result = dns_rdatatype_fromtext(typep, &r);
00401         if (result != ISC_R_SUCCESS)
00402                 cfg_obj_log(typeobj, ns_g_lctx, ISC_LOG_ERROR,
00403                             "unknown type '%s'", r.base);
00404         return (result);
00405 }
00406 
00407 dns_zonetype_t
00408 ns_config_getzonetype(const cfg_obj_t *zonetypeobj) {
00409         dns_zonetype_t ztype = dns_zone_none;
00410         const char *str;
00411 
00412         str = cfg_obj_asstring(zonetypeobj);
00413         if (strcasecmp(str, "master") == 0)
00414                 ztype = dns_zone_master;
00415         else if (strcasecmp(str, "slave") == 0)
00416                 ztype = dns_zone_slave;
00417         else if (strcasecmp(str, "stub") == 0)
00418                 ztype = dns_zone_stub;
00419         else if (strcasecmp(str, "static-stub") == 0)
00420                 ztype = dns_zone_staticstub;
00421         else if (strcasecmp(str, "redirect") == 0)
00422                 ztype = dns_zone_redirect;
00423         else
00424                 INSIST(0);
00425         return (ztype);
00426 }
00427 
00428 isc_result_t
00429 ns_config_getiplist(const cfg_obj_t *config, const cfg_obj_t *list,
00430                     in_port_t defport, isc_mem_t *mctx,
00431                     isc_sockaddr_t **addrsp, isc_dscp_t **dscpsp,
00432                     isc_uint32_t *countp)
00433 {
00434         int count, i = 0;
00435         const cfg_obj_t *addrlist;
00436         const cfg_obj_t *portobj, *dscpobj;
00437         const cfg_listelt_t *element;
00438         isc_sockaddr_t *addrs;
00439         in_port_t port;
00440         isc_dscp_t dscp = -1, *dscps = NULL;
00441         isc_result_t result;
00442 
00443         INSIST(addrsp != NULL && *addrsp == NULL);
00444         INSIST(dscpsp == NULL || *dscpsp == NULL);
00445         INSIST(countp != NULL);
00446 
00447         addrlist = cfg_tuple_get(list, "addresses");
00448         count = ns_config_listcount(addrlist);
00449 
00450         portobj = cfg_tuple_get(list, "port");
00451         if (cfg_obj_isuint32(portobj)) {
00452                 isc_uint32_t val = cfg_obj_asuint32(portobj);
00453                 if (val > ISC_UINT16_MAX) {
00454                         cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR,
00455                                     "port '%u' out of range", val);
00456                         return (ISC_R_RANGE);
00457                 }
00458                 port = (in_port_t) val;
00459         } else if (defport != 0)
00460                 port = defport;
00461         else {
00462                 result = ns_config_getport(config, &port);
00463                 if (result != ISC_R_SUCCESS)
00464                         return (result);
00465         }
00466 
00467         if (dscpsp != NULL) {
00468                 dscpobj = cfg_tuple_get(list, "dscp");
00469                 if (dscpobj != NULL && cfg_obj_isuint32(dscpobj)) {
00470                         if (cfg_obj_asuint32(dscpobj) > 63) {
00471                                 cfg_obj_log(dscpobj, ns_g_lctx, ISC_LOG_ERROR,
00472                                             "dscp value '%u' is out of range",
00473                                             cfg_obj_asuint32(dscpobj));
00474                                 return (ISC_R_RANGE);
00475                         }
00476                         dscp = (isc_dscp_t)cfg_obj_asuint32(dscpobj);
00477                 }
00478 
00479                 dscps = isc_mem_get(mctx, count * sizeof(isc_dscp_t));
00480                 if (dscps == NULL)
00481                         return (ISC_R_NOMEMORY);
00482         }
00483 
00484         addrs = isc_mem_get(mctx, count * sizeof(isc_sockaddr_t));
00485         if (addrs == NULL) {
00486                 if (dscps != NULL)
00487                         isc_mem_put(mctx, dscps, count * sizeof(isc_dscp_t));
00488                 return (ISC_R_NOMEMORY);
00489         }
00490 
00491         for (element = cfg_list_first(addrlist);
00492              element != NULL;
00493              element = cfg_list_next(element), i++)
00494         {
00495                 const cfg_obj_t *addr;
00496                 INSIST(i < count);
00497                 addr = cfg_listelt_value(element);
00498                 addrs[i] = *cfg_obj_assockaddr(addr);
00499                 if (dscpsp != NULL) {
00500                         isc_dscp_t innerdscp;
00501                         innerdscp = cfg_obj_getdscp(addr);
00502                         if (innerdscp == -1)
00503                                 innerdscp = dscp;
00504                         dscps[i] = innerdscp;
00505                 }
00506                 if (isc_sockaddr_getport(&addrs[i]) == 0)
00507                         isc_sockaddr_setport(&addrs[i], port);
00508         }
00509         INSIST(i == count);
00510 
00511         *addrsp = addrs;
00512         *countp = count;
00513 
00514         if (dscpsp != NULL)
00515                 *dscpsp = dscps;
00516 
00517         return (ISC_R_SUCCESS);
00518 }
00519 
00520 void
00521 ns_config_putiplist(isc_mem_t *mctx, isc_sockaddr_t **addrsp,
00522                     isc_dscp_t **dscpsp, isc_uint32_t count)
00523 {
00524         INSIST(addrsp != NULL && *addrsp != NULL);
00525         INSIST(dscpsp == NULL || *dscpsp != NULL);
00526 
00527         isc_mem_put(mctx, *addrsp, count * sizeof(isc_sockaddr_t));
00528         *addrsp = NULL;
00529 
00530         if (dscpsp != NULL) {
00531                 isc_mem_put(mctx, *dscpsp, count * sizeof(isc_dscp_t));
00532                 *dscpsp = NULL;
00533         }
00534 }
00535 
00536 static isc_result_t
00537 get_masters_def(const cfg_obj_t *cctx, const char *name,
00538                 const cfg_obj_t **ret)
00539 {
00540         isc_result_t result;
00541         const cfg_obj_t *masters = NULL;
00542         const cfg_listelt_t *elt;
00543 
00544         result = cfg_map_get(cctx, "masters", &masters);
00545         if (result != ISC_R_SUCCESS)
00546                 return (result);
00547         for (elt = cfg_list_first(masters);
00548              elt != NULL;
00549              elt = cfg_list_next(elt)) {
00550                 const cfg_obj_t *list;
00551                 const char *listname;
00552 
00553                 list = cfg_listelt_value(elt);
00554                 listname = cfg_obj_asstring(cfg_tuple_get(list, "name"));
00555 
00556                 if (strcasecmp(listname, name) == 0) {
00557                         *ret = list;
00558                         return (ISC_R_SUCCESS);
00559                 }
00560         }
00561         return (ISC_R_NOTFOUND);
00562 }
00563 
00564 isc_result_t
00565 ns_config_getipandkeylist(const cfg_obj_t *config, const cfg_obj_t *list,
00566                           isc_mem_t *mctx, isc_sockaddr_t **addrsp,
00567                           isc_dscp_t **dscpsp, dns_name_t ***keysp,
00568                           isc_uint32_t *countp)
00569 {
00570         isc_uint32_t addrcount = 0, dscpcount = 0, keycount = 0, i = 0;
00571         isc_uint32_t listcount = 0, l = 0, j;
00572         isc_uint32_t stackcount = 0, pushed = 0;
00573         isc_result_t result;
00574         const cfg_listelt_t *element;
00575         const cfg_obj_t *addrlist;
00576         const cfg_obj_t *portobj;
00577         const cfg_obj_t *dscpobj;
00578         in_port_t port;
00579         isc_dscp_t dscp;
00580         dns_fixedname_t fname;
00581         isc_sockaddr_t *addrs = NULL;
00582         isc_dscp_t *dscps = NULL;
00583         dns_name_t **keys = NULL;
00584         struct { const char *name; } *lists = NULL;
00585         struct {
00586                 const cfg_listelt_t *element;
00587                 in_port_t port;
00588                 isc_dscp_t dscp;
00589         } *stack = NULL;
00590 
00591         REQUIRE(addrsp != NULL && *addrsp == NULL);
00592         REQUIRE(dscpsp != NULL && *dscpsp == NULL);
00593         REQUIRE(keysp != NULL && *keysp == NULL);
00594         REQUIRE(countp != NULL);
00595 
00596         /*
00597          * Get system defaults.
00598          */
00599         result = ns_config_getport(config, &port);
00600         if (result != ISC_R_SUCCESS)
00601                 goto cleanup;
00602 
00603         result = ns_config_getdscp(config, &dscp);
00604         if (result != ISC_R_SUCCESS)
00605                 goto cleanup;
00606 
00607  newlist:
00608         addrlist = cfg_tuple_get(list, "addresses");
00609         portobj = cfg_tuple_get(list, "port");
00610         dscpobj = cfg_tuple_get(list, "dscp");
00611 
00612         if (cfg_obj_isuint32(portobj)) {
00613                 isc_uint32_t val = cfg_obj_asuint32(portobj);
00614                 if (val > ISC_UINT16_MAX) {
00615                         cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR,
00616                                     "port '%u' out of range", val);
00617                         result = ISC_R_RANGE;
00618                         goto cleanup;
00619                 }
00620                 port = (in_port_t) val;
00621         }
00622 
00623         if (dscpobj != NULL && cfg_obj_isuint32(dscpobj)) {
00624                 if (cfg_obj_asuint32(dscpobj) > 63) {
00625                         cfg_obj_log(dscpobj, ns_g_lctx, ISC_LOG_ERROR,
00626                                     "dscp value '%u' is out of range",
00627                                     cfg_obj_asuint32(dscpobj));
00628                         result = ISC_R_RANGE;
00629                         goto cleanup;
00630                 }
00631                 dscp = (isc_dscp_t)cfg_obj_asuint32(dscpobj);
00632         }
00633 
00634         result = ISC_R_NOMEMORY;
00635 
00636         element = cfg_list_first(addrlist);
00637  resume:
00638         for ( ;
00639              element != NULL;
00640              element = cfg_list_next(element))
00641         {
00642                 const cfg_obj_t *addr;
00643                 const cfg_obj_t *key;
00644                 const char *keystr;
00645                 isc_buffer_t b;
00646 
00647                 addr = cfg_tuple_get(cfg_listelt_value(element),
00648                                      "masterselement");
00649                 key = cfg_tuple_get(cfg_listelt_value(element), "key");
00650 
00651                 if (!cfg_obj_issockaddr(addr)) {
00652                         const char *listname = cfg_obj_asstring(addr);
00653                         isc_result_t tresult;
00654 
00655                         /* Grow lists? */
00656                         if (listcount == l) {
00657                                 void * new;
00658                                 isc_uint32_t newlen = listcount + 16;
00659                                 size_t newsize, oldsize;
00660 
00661                                 newsize = newlen * sizeof(*lists);
00662                                 oldsize = listcount * sizeof(*lists);
00663                                 new = isc_mem_get(mctx, newsize);
00664                                 if (new == NULL)
00665                                         goto cleanup;
00666                                 if (listcount != 0) {
00667                                         memmove(new, lists, oldsize);
00668                                         isc_mem_put(mctx, lists, oldsize);
00669                                 }
00670                                 lists = new;
00671                                 listcount = newlen;
00672                         }
00673                         /* Seen? */
00674                         for (j = 0; j < l; j++)
00675                                 if (strcasecmp(lists[j].name, listname) == 0)
00676                                         break;
00677                         if (j < l)
00678                                 continue;
00679                         tresult = get_masters_def(config, listname, &list);
00680                         if (tresult == ISC_R_NOTFOUND) {
00681                                 cfg_obj_log(addr, ns_g_lctx, ISC_LOG_ERROR,
00682                                     "masters \"%s\" not found", listname);
00683 
00684                                 result = tresult;
00685                                 goto cleanup;
00686                         }
00687                         if (tresult != ISC_R_SUCCESS)
00688                                 goto cleanup;
00689                         lists[l++].name = listname;
00690                         /* Grow stack? */
00691                         if (stackcount == pushed) {
00692                                 void * new;
00693                                 isc_uint32_t newlen = stackcount + 16;
00694                                 size_t newsize, oldsize;
00695 
00696                                 newsize = newlen * sizeof(*stack);
00697                                 oldsize = stackcount * sizeof(*stack);
00698                                 new = isc_mem_get(mctx, newsize);
00699                                 if (new == NULL)
00700                                         goto cleanup;
00701                                 if (stackcount != 0) {
00702                                         memmove(new, stack, oldsize);
00703                                         isc_mem_put(mctx, stack, oldsize);
00704                                 }
00705                                 stack = new;
00706                                 stackcount = newlen;
00707                         }
00708                         /*
00709                          * We want to resume processing this list on the
00710                          * next element.
00711                          */
00712                         stack[pushed].element = cfg_list_next(element);
00713                         stack[pushed].port = port;
00714                         stack[pushed].dscp = dscp;
00715                         pushed++;
00716                         goto newlist;
00717                 }
00718 
00719                 if (i == addrcount) {
00720                         void * new;
00721                         isc_uint32_t newlen = addrcount + 16;
00722                         size_t newsize, oldsize;
00723 
00724                         newsize = newlen * sizeof(isc_sockaddr_t);
00725                         oldsize = addrcount * sizeof(isc_sockaddr_t);
00726                         new = isc_mem_get(mctx, newsize);
00727                         if (new == NULL)
00728                                 goto cleanup;
00729                         if (addrcount != 0) {
00730                                 memmove(new, addrs, oldsize);
00731                                 isc_mem_put(mctx, addrs, oldsize);
00732                         }
00733                         addrs = new;
00734                         addrcount = newlen;
00735 
00736                         newsize = newlen * sizeof(isc_dscp_t);
00737                         oldsize = dscpcount * sizeof(isc_dscp_t);
00738                         new = isc_mem_get(mctx, newsize);
00739                         if (new == NULL)
00740                                 goto cleanup;
00741                         if (dscpcount != 0) {
00742                                 memmove(new, dscps, oldsize);
00743                                 isc_mem_put(mctx, dscps, oldsize);
00744                         }
00745                         dscps = new;
00746                         dscpcount = newlen;
00747 
00748                         newsize = newlen * sizeof(dns_name_t *);
00749                         oldsize = keycount * sizeof(dns_name_t *);
00750                         new = isc_mem_get(mctx, newsize);
00751                         if (new == NULL)
00752                                 goto cleanup;
00753                         if (keycount != 0) {
00754                                 memmove(new, keys, oldsize);
00755                                 isc_mem_put(mctx, keys, oldsize);
00756                         }
00757                         keys = new;
00758                         keycount = newlen;
00759                 }
00760 
00761                 addrs[i] = *cfg_obj_assockaddr(addr);
00762                 if (isc_sockaddr_getport(&addrs[i]) == 0)
00763                         isc_sockaddr_setport(&addrs[i], port);
00764                 dscps[i] = cfg_obj_getdscp(addr);
00765                 if (dscps[i] == -1)
00766                         dscps[i] = dscp;
00767                 keys[i] = NULL;
00768                 i++;    /* Increment here so that cleanup on error works. */
00769                 if (!cfg_obj_isstring(key))
00770                         continue;
00771                 keys[i - 1] = isc_mem_get(mctx, sizeof(dns_name_t));
00772                 if (keys[i - 1] == NULL)
00773                         goto cleanup;
00774                 dns_name_init(keys[i - 1], NULL);
00775 
00776                 keystr = cfg_obj_asstring(key);
00777                 isc_buffer_constinit(&b, keystr, strlen(keystr));
00778                 isc_buffer_add(&b, strlen(keystr));
00779                 dns_fixedname_init(&fname);
00780                 result = dns_name_fromtext(dns_fixedname_name(&fname), &b,
00781                                            dns_rootname, 0, NULL);
00782                 if (result != ISC_R_SUCCESS)
00783                         goto cleanup;
00784                 result = dns_name_dup(dns_fixedname_name(&fname), mctx,
00785                                       keys[i - 1]);
00786                 if (result != ISC_R_SUCCESS)
00787                         goto cleanup;
00788         }
00789         if (pushed != 0) {
00790                 pushed--;
00791                 element = stack[pushed].element;
00792                 port = stack[pushed].port;
00793                 dscp = stack[pushed].dscp;
00794                 goto resume;
00795         }
00796         if (i < addrcount) {
00797                 void * new;
00798                 size_t newsize, oldsize;
00799 
00800                 newsize = i * sizeof(isc_sockaddr_t);
00801                 oldsize = addrcount * sizeof(isc_sockaddr_t);
00802                 if (i != 0) {
00803                         new = isc_mem_get(mctx, newsize);
00804                         if (new == NULL)
00805                                 goto cleanup;
00806                         memmove(new, addrs, newsize);
00807                 } else
00808                         new = NULL;
00809                 isc_mem_put(mctx, addrs, oldsize);
00810                 addrs = new;
00811                 addrcount = i;
00812 
00813                 newsize = i * sizeof(isc_dscp_t);
00814                 oldsize = dscpcount * sizeof(isc_dscp_t);
00815                 if (i != 0) {
00816                         new = isc_mem_get(mctx, newsize);
00817                         if (new == NULL)
00818                                 goto cleanup;
00819                         memmove(new, dscps, newsize);
00820                 } else
00821                         new = NULL;
00822                 isc_mem_put(mctx, dscps, oldsize);
00823                 dscps = new;
00824                 dscpcount = i;
00825 
00826                 newsize = i * sizeof(dns_name_t *);
00827                 oldsize = keycount * sizeof(dns_name_t *);
00828                 if (i != 0) {
00829                         new = isc_mem_get(mctx, newsize);
00830                         if (new == NULL)
00831                                 goto cleanup;
00832                         memmove(new, keys,  newsize);
00833                 } else
00834                         new = NULL;
00835                 isc_mem_put(mctx, keys, oldsize);
00836                 keys = new;
00837                 keycount = i;
00838         }
00839 
00840         if (lists != NULL)
00841                 isc_mem_put(mctx, lists, listcount * sizeof(*lists));
00842         if (stack != NULL)
00843                 isc_mem_put(mctx, stack, stackcount * sizeof(*stack));
00844 
00845         INSIST(keycount == addrcount);
00846 
00847         *addrsp = addrs;
00848         *dscpsp = dscps;
00849         *keysp = keys;
00850         *countp = addrcount;
00851 
00852         return (ISC_R_SUCCESS);
00853 
00854  cleanup:
00855         if (addrs != NULL)
00856                 isc_mem_put(mctx, addrs, addrcount * sizeof(isc_sockaddr_t));
00857         if (dscps != NULL)
00858                 isc_mem_put(mctx, dscps, dscpcount * sizeof(isc_dscp_t));
00859         if (keys != NULL) {
00860                 for (j = 0; j < i; j++) {
00861                         if (keys[j] == NULL)
00862                                 continue;
00863                         if (dns_name_dynamic(keys[j]))
00864                                 dns_name_free(keys[j], mctx);
00865                         isc_mem_put(mctx, keys[j], sizeof(dns_name_t));
00866                 }
00867                 isc_mem_put(mctx, keys, keycount * sizeof(dns_name_t *));
00868         }
00869         if (lists != NULL)
00870                 isc_mem_put(mctx, lists, listcount * sizeof(*lists));
00871         if (stack != NULL)
00872                 isc_mem_put(mctx, stack, stackcount * sizeof(*stack));
00873         return (result);
00874 }
00875 
00876 void
00877 ns_config_putipandkeylist(isc_mem_t *mctx, isc_sockaddr_t **addrsp,
00878                           isc_dscp_t **dscpsp, dns_name_t ***keysp,
00879                           isc_uint32_t count)
00880 {
00881         unsigned int i;
00882         dns_name_t **keys;
00883 
00884         REQUIRE(addrsp != NULL && *addrsp != NULL);
00885         REQUIRE(dscpsp == NULL || *dscpsp != NULL);
00886         REQUIRE(keysp != NULL && *keysp != NULL);
00887 
00888         keys = *keysp;
00889 
00890         isc_mem_put(mctx, *addrsp, count * sizeof(isc_sockaddr_t));
00891         if (dscpsp != NULL)
00892                 isc_mem_put(mctx, *dscpsp, count * sizeof(isc_dscp_t));
00893         for (i = 0; i < count; i++) {
00894                 if (keys[i] == NULL)
00895                         continue;
00896                 if (dns_name_dynamic(keys[i]))
00897                         dns_name_free(keys[i], mctx);
00898                 isc_mem_put(mctx, keys[i], sizeof(dns_name_t));
00899         }
00900         isc_mem_put(mctx, *keysp, count * sizeof(dns_name_t *));
00901         *addrsp = NULL;
00902         if (dscpsp != NULL)
00903                 *dscpsp = NULL;
00904         *keysp = NULL;
00905 }
00906 
00907 isc_result_t
00908 ns_config_getport(const cfg_obj_t *config, in_port_t *portp) {
00909         const cfg_obj_t *maps[3];
00910         const cfg_obj_t *options = NULL;
00911         const cfg_obj_t *portobj = NULL;
00912         isc_result_t result;
00913         int i;
00914 
00915         (void)cfg_map_get(config, "options", &options);
00916         i = 0;
00917         if (options != NULL)
00918                 maps[i++] = options;
00919         maps[i++] = ns_g_defaults;
00920         maps[i] = NULL;
00921 
00922         result = ns_config_get(maps, "port", &portobj);
00923         INSIST(result == ISC_R_SUCCESS);
00924         if (cfg_obj_asuint32(portobj) >= ISC_UINT16_MAX) {
00925                 cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR,
00926                             "port '%u' out of range",
00927                             cfg_obj_asuint32(portobj));
00928                 return (ISC_R_RANGE);
00929         }
00930         *portp = (in_port_t)cfg_obj_asuint32(portobj);
00931         return (ISC_R_SUCCESS);
00932 }
00933 
00934 isc_result_t
00935 ns_config_getdscp(const cfg_obj_t *config, isc_dscp_t *dscpp) {
00936         const cfg_obj_t *options = NULL;
00937         const cfg_obj_t *dscpobj = NULL;
00938         isc_result_t result;
00939 
00940         (void)cfg_map_get(config, "options", &options);
00941         if (options == NULL)
00942                 return (ISC_R_SUCCESS);
00943 
00944         result = cfg_map_get(options, "dscp", &dscpobj);
00945         if (result != ISC_R_SUCCESS || dscpobj == NULL) {
00946                 *dscpp = -1;
00947                 return (ISC_R_SUCCESS);
00948         }
00949         if (cfg_obj_asuint32(dscpobj) >= 64) {
00950                 cfg_obj_log(dscpobj, ns_g_lctx, ISC_LOG_ERROR,
00951                             "dscp '%u' out of range",
00952                             cfg_obj_asuint32(dscpobj));
00953                 return (ISC_R_RANGE);
00954         }
00955         *dscpp = (isc_dscp_t)cfg_obj_asuint32(dscpobj);
00956         return (ISC_R_SUCCESS);
00957 }
00958 
00959 struct keyalgorithms {
00960         const char *str;
00961         enum { hmacnone, hmacmd5, hmacsha1, hmacsha224,
00962                hmacsha256, hmacsha384, hmacsha512 } hmac;
00963         unsigned int type;
00964         isc_uint16_t size;
00965 } algorithms[] = {
00966         { "hmac-md5", hmacmd5, DST_ALG_HMACMD5, 128 },
00967         { "hmac-md5.sig-alg.reg.int", hmacmd5, DST_ALG_HMACMD5, 0 },
00968         { "hmac-md5.sig-alg.reg.int.", hmacmd5, DST_ALG_HMACMD5, 0 },
00969         { "hmac-sha1", hmacsha1, DST_ALG_HMACSHA1, 160 },
00970         { "hmac-sha224", hmacsha224, DST_ALG_HMACSHA224, 224 },
00971         { "hmac-sha256", hmacsha256, DST_ALG_HMACSHA256, 256 },
00972         { "hmac-sha384", hmacsha384, DST_ALG_HMACSHA384, 384 },
00973         { "hmac-sha512", hmacsha512, DST_ALG_HMACSHA512, 512 },
00974         {  NULL, hmacnone, DST_ALG_UNKNOWN, 0 }
00975 };
00976 
00977 isc_result_t
00978 ns_config_getkeyalgorithm(const char *str, dns_name_t **name,
00979                           isc_uint16_t *digestbits)
00980 {
00981         return (ns_config_getkeyalgorithm2(str, name, NULL, digestbits));
00982 }
00983 
00984 isc_result_t
00985 ns_config_getkeyalgorithm2(const char *str, dns_name_t **name,
00986                            unsigned int *typep, isc_uint16_t *digestbits)
00987 {
00988         int i;
00989         size_t len = 0;
00990         isc_uint16_t bits;
00991         isc_result_t result;
00992 
00993         for (i = 0; algorithms[i].str != NULL; i++) {
00994                 len = strlen(algorithms[i].str);
00995                 if (strncasecmp(algorithms[i].str, str, len) == 0 &&
00996                     (str[len] == '\0' ||
00997                      (algorithms[i].size != 0 && str[len] == '-')))
00998                         break;
00999         }
01000         if (algorithms[i].str == NULL)
01001                 return (ISC_R_NOTFOUND);
01002         if (str[len] == '-') {
01003                 result = isc_parse_uint16(&bits, str + len + 1, 10);
01004                 if (result != ISC_R_SUCCESS)
01005                         return (result);
01006                 if (bits > algorithms[i].size)
01007                         return (ISC_R_RANGE);
01008         } else if (algorithms[i].size == 0)
01009                 bits = 128;
01010         else
01011                 bits = algorithms[i].size;
01012 
01013         if (name != NULL) {
01014                 switch (algorithms[i].hmac) {
01015                 case hmacmd5: *name = dns_tsig_hmacmd5_name; break;
01016                 case hmacsha1: *name = dns_tsig_hmacsha1_name; break;
01017                 case hmacsha224: *name = dns_tsig_hmacsha224_name; break;
01018                 case hmacsha256: *name = dns_tsig_hmacsha256_name; break;
01019                 case hmacsha384: *name = dns_tsig_hmacsha384_name; break;
01020                 case hmacsha512: *name = dns_tsig_hmacsha512_name; break;
01021                 default:
01022                         INSIST(0);
01023                 }
01024         }
01025         if (typep != NULL)
01026                 *typep = algorithms[i].type;
01027         if (digestbits != NULL)
01028                 *digestbits = bits;
01029         return (ISC_R_SUCCESS);
01030 }

Generated on Tue Apr 28 17:40:54 2015 by Doxygen 1.5.4 for BIND9 Internals 9.11.0pre-alpha